]> git.mxchange.org Git - simgear.git/blobdiff - src/slSamplePlayer.cxx
Added point3d.hxx to replace cheezy fgPoint3d struct.
[simgear.git] / src / slSamplePlayer.cxx
index fa079f4b54fa2bd060595b19a19f764f3359cc7c..12eecaf6560479cd405184cc4d41ec80bae3c2d5 100644 (file)
@@ -68,83 +68,121 @@ void slSamplePlayer::skip ( int nframes )
 }
 
 
-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 ;
 }
 
+
+