DavidGriffith / gorilla-audio

Automatically exported from code.google.com/p/gorilla-audio
MIT License
0 stars 0 forks source link

Audio crackles when panning quickly #4

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
I implemented positional audio on top of gorilla, but get audio crackles when 
the pan of a handle changes. How do I mitigate that?

Original issue reported on code.google.com by zel...@gmail.com on 26 Sep 2014 at 5:16

GoogleCodeExporter commented 9 years ago
Fixed. problem was also with gain. Patch here:

diff --git a/deps/gorilla-audio/include/gorilla/ga_internal.h 
b/deps/gorilla-audio/include/gorilla/ga_internal.h
index 126bd9b..c072ce9 100644
--- a/deps/gorilla-audio/include/gorilla/ga_internal.h
+++ b/deps/gorilla-audio/include/gorilla/ga_internal.h
@@ -192,6 +192,8 @@ struct ga_Handle {
   gc_float32 gain;
   gc_float32 pitch;
   gc_float32 pan;
+  gc_float32 lastPan;
+  gc_float32 lastGain;
   gc_Link dispatchLink;
   gc_Link mixLink;
   gc_Mutex* handleMutex;
diff --git a/deps/gorilla-audio/src/ga.c b/deps/gorilla-audio/src/ga.c
index bc573ca..dd9ad90 100644
--- a/deps/gorilla-audio/src/ga.c
+++ b/deps/gorilla-audio/src/ga.c
@@ -534,6 +534,8 @@ void gaX_handle_init(ga_Handle* in_handle, ga_Mixer* 
in_mixer)
   h->gain = 1.0f;
   h->pitch = 1.0f;
   h->pan = 0.0f;
+  h->lastPan = 0;
+  h->lastGain = 1;
   h->handleMutex = gc_mutex_create();
 }

@@ -737,7 +739,7 @@ gc_int32 ga_mixer_numSamples(ga_Mixer* in_mixer)
 void gaX_mixer_mix_buffer(ga_Mixer* in_mixer,
                           void* in_srcBuffer, gc_int32 in_srcSamples, ga_Format* in_srcFmt,
                           gc_int32* in_dstBuffer, gc_int32 in_dstSamples, ga_Format* in_dstFmt,
-                          gc_float32 in_gain, gc_float32 in_pan, gc_float32 
in_pitch)
+                          gc_float32 in_gain, gc_float32 in_pan, gc_float32 
in_pitch, gc_float32 in_lastGain, gc_float32 in_lastPan)
 {
   ga_Format* mixFmt = in_dstFmt;
   gc_int32 mixerChannels = mixFmt->numChannels;
@@ -750,12 +752,25 @@ void gaX_mixer_mix_buffer(ga_Mixer* in_mixer,
   gc_int32 i = 0;
   gc_float32 pan = in_pan;
   gc_float32 gain = in_gain;
+  gc_float32 lastPan = in_lastPan;
+  gc_float32 lastGain = in_lastGain;
   gc_float32 srcSamplesRead = 0.0f;
   gc_int32 sampleSize = ga_format_sampleSize(in_srcFmt);
+
   pan = (pan + 1.0f) / 2.0f;
   pan = pan > 1.0f ? 1.0f : pan;
   pan = pan < 0.0f ? 0.0f : pan;

+  lastPan = (lastPan + 1.0f) / 2.0f;
+  lastPan = lastPan > 1.0f ? 1.0f : lastPan;
+  lastPan = lastPan < 0.0f ? 0.0f : lastPan;
+
+  gc_float32 curGain = lastGain;
+  gc_float32 curPan = lastPan;
+  gc_float32 incGain = (gain - curGain) / numToFill;
+  gc_float32 incPan = (pan - curPan) / numToFill;
+  //printf("curGain = %f | %f (%f .. %f)\n curPan = %f | %f (%f .. %f)\n", 
curGain, incGain, lastGain, gain, curPan, incPan, lastPan, pan);
+
   /* TODO: Support 8-bit/16-bit mono/stereo mixer format */
   switch(in_srcFmt->bitsPerSample)
   {
@@ -765,9 +780,13 @@ void gaX_mixer_mix_buffer(ga_Mixer* in_mixer,
       const gc_int16* src = (const gc_int16*)in_srcBuffer;
       while(i < numToFill * (gc_int32)mixerChannels && srcBytes >= 2 * srcChannels)
       {
+       gc_float32 lmul = curGain * (curPan < 0.5 ? 1 : (1 - curPan) * 2);
+       gc_float32 rmul = curGain * (curPan > 0.5 ? 1 : curPan * 2);
+       curGain += incGain;
+       curPan += incPan;
         gc_int32 newJ, deltaSrcBytes;
-        dst[i] += (gc_int32)((gc_int32)src[j] * gain * (1.0f - pan) * 2);
-        dst[i + 1] += (gc_int32)((gc_int32)src[j + ((srcChannels == 1) ? 0 : 
1)] * gain * pan * 2);
+        dst[i] += (gc_int32)((gc_int32)src[j] * lmul);
+        dst[i + 1] += (gc_int32)((gc_int32)src[j + ((srcChannels == 1) ? 0 : 
1)] * rmul);
         i += mixerChannels;
         fj += sampleScale * srcChannels;
         srcSamplesRead += sampleScale * srcChannels;
@@ -811,7 +830,7 @@ void gaX_mixer_mix_handle(ga_Mixer* in_mixer, ga_Handle* 
in_handle, gc_int32 in_
         requested = requested / dstToSrc < in_numSamples ? requested + 1 : requested;
         if(requested > 0 && ga_sample_source_ready(ss, requested))
         {
-          gc_float32 gain, pan, pitch;
+          gc_float32 gain, pan, pitch, lastPan, lastGain;
           gc_int32* dstBuffer;
           gc_int32 dstSamples;

@@ -819,6 +838,10 @@ void gaX_mixer_mix_handle(ga_Mixer* in_mixer, ga_Handle* 
in_handle, gc_int32 in_
           gain = h->gain;
           pan = h->pan;
           pitch = h->pitch;
+         lastPan = h->lastPan;
+         lastGain = h->lastGain;
+         h->lastPan = pan;
+         h->lastGain = gain;
           gc_mutex_unlock(h->handleMutex);

           /* We avoided a mutex lock by using pitch to check if buffer has enough dst samples */
@@ -844,7 +867,7 @@ void gaX_mixer_mix_handle(ga_Mixer* in_mixer, ga_Handle* 
in_handle, gc_int32 in_
             gaX_mixer_mix_buffer(in_mixer,
                                  src, numRead, &handleFormat,
                                  dstBuffer, dstSamples, &m->format,
-                                 gain, pan, pitch);
+                                 gain, pan, pitch, lastGain, lastPan);
             gcX_ops->freeFunc(src);
           }
         }

Original comment by zel...@gmail.com on 26 Sep 2014 at 7:28