}
-Uchar *slSamplePlayer::read ( int nframes, Uchar *spare1, Uchar *spare2 )
+void slSamplePlayer::read ( int nframes, Uchar *dst, int next_env )
{
- if ( isWaiting() ) start () ;
+ /*
+ WARNING:
+
+ CO-RECURSIVE!
+ */
+
+ /* Find the next envelope */
+
+ while ( next_env < SL_MAX_ENVELOPES && env [ next_env ] == NULL )
+ next_env++ ;
- if ( nframes > lengthRemaining ) /* This is an error */
+ /*
+ If there are no fancy envelopes to process then return
+ the raw data.
+ */
+
+ if ( next_env >= SL_MAX_ENVELOPES ) /* No fancy envelopes left */
{
- fprintf ( stderr, "slSamplePlayer: FATAL ERROR - Mixer Requested too much data.\n" ) ;
- abort () ;
+ low_read ( nframes, dst ) ;
+ return ;
}
- Uchar *src = bufferPos ;
- Uchar *dst = spare1 ;
+ /*
+ Envelope processing required...
+
+ Process the next envelope using data read recursively through
+ the remaining envelopes.
+ */
- for ( int i = 0 ; i < SL_MAX_ENVELOPES ; i++ )
+ switch ( env_type [ next_env ] )
{
- if ( env[i] )
- {
- switch ( env_type [ i ] )
- {
- case SL_INVERSE_PITCH_ENVELOPE :
- case SL_PITCH_ENVELOPE :
- memcpy ( dst, src, nframes ) /* Tricky! */ ;
- break ;
-
- case SL_INVERSE_VOLUME_ENVELOPE:
- env[i]->applyToInvVolume ( dst,src,nframes,env_start_time[i] ) ;
- break ;
-
- case SL_VOLUME_ENVELOPE :
- env[i]->applyToVolume ( dst,src,nframes,env_start_time[i] ) ;
- break ;
-
- case SL_INVERSE_FILTER_ENVELOPE:
- case SL_FILTER_ENVELOPE :
- memcpy ( dst, src, nframes ) /* Tricky! */ ;
- break ;
-
- case SL_INVERSE_PAN_ENVELOPE :
- case SL_PAN_ENVELOPE :
- memcpy ( dst, src, nframes ) /* Tricky! */ ;
- break ;
-
- case SL_INVERSE_ECHO_ENVELOPE :
- case SL_ECHO_ENVELOPE :
- memcpy ( dst, src, nframes ) /* Tricky! */ ;
- break ;
- }
-
- if ( dst == spare1 )
- {
- src = spare1 ;
- dst = spare2 ;
- }
- else
- {
- dst = spare1 ;
- src = spare2 ;
- }
- }
+ /* For Volume envelopes, SRC and DST can be the same buffer */
+
+ case SL_INVERSE_VOLUME_ENVELOPE:
+ read ( nframes, dst, next_env+1 ) ;
+ env[ next_env ]->applyToInvVolume ( dst,dst,nframes,env_start_time[ next_env ] ) ;
+ break ;
+
+ case SL_VOLUME_ENVELOPE :
+ read ( nframes, dst, next_env+1 ) ;
+ env[ next_env ]->applyToVolume ( dst,dst,nframes,env_start_time[ next_env ] ) ;
+ break ;
+
+ case SL_INVERSE_PITCH_ENVELOPE :
+ env[ next_env ]->applyToInvPitch ( dst,this,nframes,env_start_time[ next_env ], next_env+1 ) ;
+ break ;
+
+ case SL_PITCH_ENVELOPE :
+ env[ next_env ]->applyToPitch ( dst,this,nframes,env_start_time[ next_env ], next_env+1 ) ;
+ break ;
+
+ case SL_INVERSE_FILTER_ENVELOPE:
+ case SL_FILTER_ENVELOPE :
+ read ( nframes, dst, next_env+1 ) ;
+ break ;
+
+ case SL_INVERSE_PAN_ENVELOPE :
+ case SL_PAN_ENVELOPE :
+ read ( nframes, dst, next_env+1 ) ;
+ break ;
+
+ case SL_INVERSE_ECHO_ENVELOPE :
+ case SL_ECHO_ENVELOPE :
+ read ( nframes, dst, next_env+1 ) ;
+ break ;
}
-
- if ( nframes < lengthRemaining ) /* Less data than there is left... */
+}
+
+
+void slSamplePlayer::low_read ( int nframes, Uchar *dst )
+{
+ if ( isWaiting() ) start () ;
+
+ if ( bufferPos == NULL ) /* Run out of sample & no repeats */
{
- lengthRemaining -= nframes ;
- bufferPos += nframes ;
+ memset ( dst, 0x80, nframes ) ;
+ return ;
}
- else /* Read it all */
+
+ while ( SL_TRUE )
{
+ /*
+ If we can satisfy this request in one read (with data left in
+ the sample buffer ready for next time around) - then we are done...
+ */
+
+ if ( nframes < lengthRemaining )
+ {
+ memcpy ( dst, bufferPos, nframes ) ;
+ bufferPos += nframes ;
+ lengthRemaining -= nframes ;
+ return ;
+ }
+
+ memcpy ( dst, bufferPos, lengthRemaining ) ;
+ bufferPos += lengthRemaining ;
+ dst += lengthRemaining ;
+ nframes -= lengthRemaining ;
+ lengthRemaining = 0 ;
+
if ( replay_mode == SL_SAMPLE_ONE_SHOT )
+ {
stop () ;
+ memset ( dst, 0x80, nframes ) ;
+ return ;
+ }
else
{
slScheduler::getCurrent() -> addCallBack ( callback, sample, SL_EVENT_LOOPED, magic ) ;
start () ;
}
}
-
- return src ;
}
+
+