diff jssmix.c @ 287:1e89cd081956

Use fixed point everywhere in the mixing internals, to avoid going over sample boundaries.
author Matti Hamalainen <ccr@tnsp.org>
date Thu, 11 Oct 2012 11:09:26 +0300
parents b7e23d91a8c2
children 701c3d22e0f9
line wrap: on
line diff
--- a/jssmix.c	Thu Oct 11 10:24:00 2012 +0300
+++ b/jssmix.c	Thu Oct 11 11:09:26 2012 +0300
@@ -28,8 +28,8 @@
     int    outFormat;
     int    outChannels;
 
-    int    (*jvmMixChannel_FW)(JSSMixer *, JSSChannel *, JMIXER_ADDBUF_TYPE *, const int, const Sint32);
-    int    (*jvmMixChannel_BW)(JSSMixer *, JSSChannel *, JMIXER_ADDBUF_TYPE *, const int, const Sint32);
+    int    (*jvmMixChannel_FW)(JSSMixer *, JSSChannel *, JMIXER_ADDBUF_TYPE *, const int, const DMFixedPoint);
+    int    (*jvmMixChannel_BW)(JSSMixer *, JSSChannel *, JMIXER_ADDBUF_TYPE *, const int, const DMFixedPoint);
     void   (*jvmPostProcess)(JMIXER_ADDBUF_TYPE *, void *, const int);
 } JSSMixingRoutine;
 
@@ -250,10 +250,10 @@
                 if (chn->chFlags & jsfBiDi)
                 {
                     // Bi-directional loop
-                    if (FP_GETH(chn->chPos) >= chn->chLoopE)
+                    if (chn->chPos.dw >= chn->chLoopE.dw)
                     {
                         DMFixedPoint end;
-                        FP_SETHL(end, chn->chLoopE + chn->chLoopE, 0);
+                        FP_ADD_R(end, chn->chLoopE, chn->chLoopE);
                         FP_SUB_R(chn->chPos, end, chn->chPos);
                         chn->chDirection = FALSE;
                     }
@@ -261,20 +261,18 @@
                 else
                 {
                     // Normal forward loop
-                    if (FP_GETH(chn->chPos) >= chn->chLoopE)
+                    if (chn->chPos.dw >= chn->chLoopE.dw)
                     {
-                        DMFixedPoint diff, end;
-                        FP_SETHL(end, chn->chLoopE, 0);
-                        FP_SUB_R(diff, chn->chPos, end);
-                        FP_SETHL(chn->chPos, chn->chLoopS, 0);
-                        FP_ADD(chn->chPos, diff);
+                        DMFixedPoint diff;
+                        FP_SUB_R(diff, chn->chPos, chn->chLoopE);
+                        FP_ADD_R(chn->chPos, chn->chLoopS, diff);
                     }
                 }
             }
             else
             {
                 // Normal (non-looped) sample
-                if (FP_GETH(chn->chPos) >= chn->chSize)
+                if (chn->chPos.dw >= chn->chSize.dw)
                 {
                     chn->chPlaying = FALSE;
                     return;
@@ -290,10 +288,10 @@
                 if (chn->chFlags & jsfBiDi)
                 {
                     // Bi-directional loop
-                    if (FP_GETH(chn->chPos) <= chn->chLoopS)
+                    if (chn->chPos.dw <= chn->chLoopS.dw)
                     {
                         DMFixedPoint start;
-                        FP_SETHL(start, chn->chLoopS + chn->chLoopS, 0);
+                        FP_ADD_R(start, chn->chLoopS, chn->chLoopS);
                         FP_SUB_R(chn->chPos, start, chn->chPos);
                         chn->chDirection = TRUE;
                     }
@@ -301,10 +299,10 @@
                 else
                 {
                     // Normal forward loop
-                    if (FP_GETH(chn->chPos) <= chn->chLoopS)
+                    if (chn->chPos.dw <= chn->chLoopS.dw)
                     {
                         DMFixedPoint diff;
-                        FP_SETHL(diff, chn->chLoopE - chn->chLoopS, 0);
+                        FP_SUB_R(diff, chn->chLoopE, chn->chLoopS);
                         FP_ADD(chn->chPos, diff);
                     }
                 }
@@ -312,7 +310,7 @@
             else
             {
                 // Normal (non-looped) sample
-                if (FP_GETH(chn->chPos) <= 0)
+                if (chn->chPos.dw <= 0)
                 {
                     chn->chPlaying = FALSE;
                     return;
@@ -326,13 +324,13 @@
             DBG("MIX_FW[%p : %d : ", ab, mixDone);
             if (chn->chFlags & jsfLooped)
             {
-                DBG("%d (%x)] {loop}\n", chn->chLoopE, chn->chLoopE);
+                DBG("%d (%x)] {loop}\n", FP_GETH(chn->chLoopE), FP_GETH(chn->chLoopE));
                 mixResult = mixer->jvmMixChannel_FW((void *) mixer, chn,
                     ab, mixDone, chn->chLoopE);
             }
             else
             {
-                DBG("%d (%x)]\n", chn->chSize, chn->chSize);
+                DBG("%d (%x)]\n", FP_GETH(chn->chSize), FP_GETH(chn->chSize));
                 mixResult = mixer->jvmMixChannel_FW((void *) mixer, chn,
                     ab, mixDone, chn->chSize);
             }
@@ -348,9 +346,10 @@
             }
             else
             {
+                static const DMFixedPoint zero = { 0 };
                 DBG("%d (%x)]\n", 0, 0);
                 mixResult = mixer->jvmMixChannel_BW(mixer, chn,
-                    ab, mixDone, 0);
+                    ab, mixDone, zero);
             }
         }
         
@@ -518,10 +517,10 @@
     JSS_LOCK(mixer);
     c = &mixer->channels[channel];
     
+    FP_SETHL(c->chSize, size, 0);
+    FP_SETHL(c->chLoopS, loopS, 0);
+    FP_SETHL(c->chLoopE, loopE, 0);
     c->chData      = data;
-    c->chSize      = size;
-    c->chLoopS     = loopS;
-    c->chLoopE     = loopE;
     c->chFlags     = flags;
     c->chDirection = TRUE;
     c->chPos.dw    = c->chDeltaO.dw = 0;