implement repeating sound effects
[fishladder.git] / vg / vg_audio.h
index a21a5d5aa292df3faae590c7ea1d7976a887d1a2..457ac13d63ea8dbdb4ca276c26bba46a661591e6 100644 (file)
@@ -6,11 +6,12 @@
 #define STB_VORBIS_MAX_CHANNELS 2
 #include "stb/stb_vorbis.h"
 
-#define SFX_MAX_SYSTEMS 16
-#define SFX_FLAG_ONESHOT 0x1
-#define SFX_FLAG_STEREO         0x2
-#define FADEOUT_LENGTH 441
-#define FADEOUT_DIVISOR (1.f/(float)FADEOUT_LENGTH)
+#define SFX_MAX_SYSTEMS        16
+#define SFX_FLAG_ONESHOT       0x1
+#define SFX_FLAG_STEREO                0x2
+#define SFX_FLAG_REPEAT        0x4
+#define FADEOUT_LENGTH                 441
+#define FADEOUT_DIVISOR        (1.f/(float)FADEOUT_LENGTH)
 
 typedef struct sfx_vol_control sfx_vol_control;
 typedef struct sfx_system sfx_system;
@@ -31,7 +32,8 @@ struct sfx_system
        float   vol;
        
        // Info
-       int ch, end, cur, flags;
+       int ch, end, cur;
+       u32 flags;
        
        // Effects
        u32 fadeout, fadeout_length, fadeout_cursor;
@@ -448,42 +450,62 @@ void audio_mixer_callback( ma_device *pDevice, void *pOutBuf, const void *pInput
                if( sys->fadeout_cursor != sys->cur )
                        sys->fadeout = sys->fadeout_length;
                
-               while( cursor < vg_min( sys->cur + frameCount, sys->end ) )
+               u32 frames_write = frameCount;
+               
+               while( frames_write )
                {
-                       audio_mixer_getsamples( pcf, sys->source, cursor, sys->ch );
-                       
-                       avgvol += fabs( pcf[0] * sys->vol );
-                       avgvol += fabs( pcf[1] * sys->vol );
+                       u32 samples_this_run = vg_min( frames_write, sys->end - cursor );
+               
+                       for( u32 j = 0; j < samples_this_run; j ++ )
+                       {
+                               audio_mixer_getsamples( pcf, sys->source, cursor, sys->ch );
+                               
+                               avgvol += fabs( pcf[0] * sys->vol );
+                               avgvol += fabs( pcf[1] * sys->vol );
+                               
+                               pOut32F[ bpos*2+0 ] += pcf[0] * sys->vol;
+                               pOut32F[ bpos*2+1 ] += pcf[1] * sys->vol;
+                               
+                               // Blend the fadeout cursor in to prevent popping
+                               if( sys->fadeout )
+                               {
+                                       if( sys->fadeout_cursor < sys->end )
+                                       {
+                                               audio_mixer_getsamples( pcf, sys->source, sys->fadeout_cursor, sys->ch );
+                                               
+                                               float mul = (float)sys->fadeout * FADEOUT_DIVISOR;
+                                               
+                                               pOut32F[ bpos*2+0 ] += pcf[0] * sys->vol * mul;
+                                               pOut32F[ bpos*2+1 ] += pcf[1] * sys->vol * mul;
+                                               
+                                               sys->fadeout_cursor ++;
+                                               sys->fadeout --;
+                                       }
+                                       else
+                                               sys->fadeout = 0;
+                               }
+
+                               cursor ++;
+                               bpos ++;
+                       }
                        
-                       pOut32F[ bpos*2+0 ] += pcf[0] * sys->vol;
-                       pOut32F[ bpos*2+1 ] += pcf[1] * sys->vol;
+                       frames_write -= samples_this_run;
                        
-                       // Blend the fadeout cursor in to prevent popping
-                       if( sys->fadeout )
+                       if( sys->flags & SFX_FLAG_REPEAT)
                        {
-                               if( sys->fadeout_cursor < sys->end )
+                               if( frames_write )
                                {
-                                       audio_mixer_getsamples( pcf, sys->source, sys->fadeout_cursor, sys->ch );
-                                       
-                                       float mul = (float)sys->fadeout * FADEOUT_DIVISOR;
-                                       
-                                       pOut32F[ bpos*2+0 ] += pcf[0] * sys->vol * mul;
-                                       pOut32F[ bpos*2+1 ] += pcf[1] * sys->vol * mul;
-                                       
-                                       sys->fadeout_cursor ++;
-                                       sys->fadeout --;
+                                       cursor = 0;
+                                       continue;
                                }
-                               else
-                                       sys->fadeout = 0;
                        }
 
-                       cursor ++;
-                       bpos ++;
+                       sys->cur = cursor;
+                       sys->fadeout_cursor = cursor;
+                       sys->signal_average = avgvol / (float)(bpos*2);
+                       
+                       break;
                }
-               
-               sys->signal_average = avgvol / (float)(bpos*2);
-               sys->cur += frameCount;
-               sys->fadeout_cursor = sys->cur;
        }
 
        // Redistribute sound systems
@@ -494,8 +516,8 @@ void audio_mixer_callback( ma_device *pDevice, void *pOutBuf, const void *pInput
        {
                sfx_system *src = sfx_sys + idx;
        
-               // Keep only if cursor is before end
-               if( src->cur < src->end ) 
+               // Keep only if cursor is before end or repeating
+               if( src->cur < src->end || (src->flags & SFX_FLAG_REPEAT) 
                {
                        // Correct source pointer on persisitent originals since we shifted ID's
                        if( !(src->flags & SFX_FLAG_ONESHOT) )