changeset 134:1ba202b448e0

Implement volume and panning ramps (interpolation between callbacks aka "frames") in the mixer.
author Matti Hamalainen <ccr@tnsp.org>
date Fri, 05 Oct 2012 02:47:36 +0300
parents 92cc5e1fa180
children ff0fe1d1ab3d
files jmix_c_in.c jmixtmpl_c.h jssmix.c jssmix.h
diffstat 4 files changed, 60 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/jmix_c_in.c	Fri Oct 05 00:36:40 2012 +0300
+++ b/jmix_c_in.c	Fri Oct 05 02:47:36 2012 +0300
@@ -12,8 +12,9 @@
 /* Mono / Linear Interpolation
  */
 #define JMIXER_SAMPLE_TYPE Sint16
-#define JMIXER_INIT        const Sint32 vol = (chn->chVolume * mixer->globalVol) / 256;
+#define JMIXER_INIT        
 #define JMIXER_FUNC \
+    const Sint32 vol = (FP_GETH(tmpVolume) * mixer->globalVol) / 256; \
     memmove(&tl[0], &tl[1], 4 * sizeof(tl[0])); \
     tl[4] = (((Sint32) sp[FP_GETH(tmpPos)]) * vol * 3 + tl[3] * 2 + tl[2] + tl[1] + tl[0]) / (256 * 8); *(ap++) += tl[4]; \
 
@@ -36,10 +37,11 @@
 /* Stereo / Linear Interpolation
  */
 #define JMIXER_SAMPLE_TYPE Sint16
-#define JMIXER_INIT        const Sint32 vol_l = (chn->chVolume * mixer->globalVol) / 256, \
-                                        vol_r = (chn->chVolume * mixer->globalVol) / 256;
+#define JMIXER_INIT
 
 #define JMIXER_FUNC \
+    const Sint32 vol_l = (FP_GETH(tmpVolume) * mixer->globalVol) / 256, \
+                 vol_r = (FP_GETH(tmpVolume) * mixer->globalVol) / 256; \
     memmove(&tl[0], &tl[1], 4 * sizeof(tl[0])); \
     memmove(&tr[0], &tr[1], 4 * sizeof(tr[0])); \
     tl[4] = (((Sint32) sp[FP_GETH(tmpPos)]) * vol_l * 3 + tl[3] * 2 + tl[2] + tl[1] + tl[0]) / (256 * 8); *(ap++) += tl[4]; \
--- a/jmixtmpl_c.h	Fri Oct 05 00:36:40 2012 +0300
+++ b/jmixtmpl_c.h	Fri Oct 05 02:47:36 2012 +0300
@@ -9,8 +9,8 @@
 #else
 int JMIXER_NAME (JSSMixer *mixer, JSSChannel *chn, JMIXER_ADDBUF_TYPE *addBuffer, const int mixLength, const Sint32 endPos)
 {
-    const DMFixedPoint tmpDelta = chn->chDeltaO;
-    DMFixedPoint tmpPos = chn->chPos;
+    const DMFixedPoint tmpDelta = chn->chDeltaO, tmpDeltaV = chn->chDeltaV;
+    DMFixedPoint tmpPos = chn->chPos, tmpVolume = chn->chVolume;
     JMIXER_ADDBUF_TYPE
         *ap = addBuffer,
         *tr = chn->chPrevR,
@@ -26,10 +26,12 @@
         JMIXER_FUNC
         JMIXER_DEBUG
         JMIXER_NEXT
+        FP_ADD(tmpVolume, tmpDeltaV);
         strideLength++;
     }
 
-    chn->chPos.dw = tmpPos.dw;
+    chn->chPos = tmpPos;
+    chn->chVolume = tmpVolume;
     return strideLength;
 }
 #endif
--- a/jssmix.c	Fri Oct 05 00:36:40 2012 +0300
+++ b/jssmix.c	Fri Oct 05 02:47:36 2012 +0300
@@ -385,6 +385,12 @@
         {
             if (mixer->cbCounter <= 0)
             {
+                for (i = 0; i < jsetNChannels; i++)
+                {
+                    JSSChannel *chn = &(mixer->channels[i]);
+                    if (chn->chPlaying && !chn->chMute)
+                        chn->chDeltaV.dw = chn->chDeltaP.dw = 0;
+                }
                 mixer->cbFunction(mixer, mixer->cbData);
                 mixer->cbCounter = mixer->cbFreq;
             }
@@ -459,13 +465,13 @@
 {
     assert(mixer);
 
-    if ((cbFreq < 1) || (cbFreq >= mixer->outFreq))
+    if (cbFreq < 1 || cbFreq >= mixer->outFreq)
         JSSERROR(DMERR_INVALID_ARGS, DMERR_INVALID_ARGS,
          "Invalid callback frequency given (%i / %i)\n", cbFreq, mixer->outFreq);
 
     JSS_LOCK(mixer);
     
-    mixer->cbFreq = (mixer->outFreq / cbFreq);
+    mixer->cbFreq = mixer->outFreq / cbFreq;
     mixer->cbCounter = 0;
 
 //fprintf(stderr, "set(outFreq = %d, cbFreq = %d) = %d\n", mixer->outFreq, cbFreq, mixer->cbFreq);
@@ -553,7 +559,22 @@
 void jvmSetVolume(JSSMixer * mixer, const int channel, const int volume)
 {
     JSS_LOCK(mixer);
-    mixer->channels[channel].chVolume = volume;
+    FP_SETHL(mixer->channels[channel].chVolume, volume, 0);
+    mixer->channels[channel].chDeltaV.dw = 0;
+    JSS_UNLOCK(mixer);
+}
+
+
+void jvmSetVolumeRamp(JSSMixer * mixer, const int channel, const int start, const int end)
+{
+    DMFixedPoint a, b;
+    JSS_LOCK(mixer);
+    FP_SETHL(mixer->channels[channel].chVolume, start, 0);
+
+    FP_SETHL(a, (end - start), 0);
+    FP_CONV(b, mixer->cbFreq);
+    FP_DIV_R(mixer->channels[channel].chDeltaV, a, b);
+
     JSS_UNLOCK(mixer);
 }
 
@@ -563,7 +584,7 @@
     int tmp;
 
     JSS_LOCK(mixer);
-    tmp = mixer->channels[channel].chVolume;
+    tmp = FP_GETH(mixer->channels[channel].chVolume);
     JSS_UNLOCK(mixer);
 
     return tmp;
@@ -573,8 +594,7 @@
 void jvmSetPos(JSSMixer * mixer, const int channel, const Sint32 pos)
 {
     JSS_LOCK(mixer);
-    FP_SETH(mixer->channels[channel].chPos, pos);
-    FP_SETL(mixer->channels[channel].chPos, 0);
+    FP_SETHL(mixer->channels[channel].chPos, pos, 0);
     JSS_UNLOCK(mixer);
 }
 
@@ -594,7 +614,20 @@
 void jvmSetPan(JSSMixer * mixer, const int channel, const int panning)
 {
     JSS_LOCK(mixer);
-    mixer->channels[channel].chPanning = panning;
+    FP_SETHL(mixer->channels[channel].chPanning, panning, 0);
+    mixer->channels[channel].chDeltaP.dw = 0;
+    JSS_UNLOCK(mixer);
+}
+
+
+void jvmSetPanRamp(JSSMixer * mixer, const int channel, const int start, const int end)
+{
+    DMFixedPoint a, b;
+    JSS_LOCK(mixer);
+    FP_SETHL(mixer->channels[channel].chPanning, start, 0);
+    FP_SETHL(a, (end - start), 0);
+    FP_CONV(b, mixer->cbFreq);
+    FP_DIV_R(mixer->channels[channel].chDeltaP, a, b);
     JSS_UNLOCK(mixer);
 }
 
@@ -604,7 +637,7 @@
     int tmp;
 
     JSS_LOCK(mixer);
-    tmp = mixer->channels[channel].chPanning;
+    tmp = FP_GETH(mixer->channels[channel].chPanning);
     JSS_UNLOCK(mixer);
 
     return tmp;
--- a/jssmix.h	Fri Oct 05 00:36:40 2012 +0300
+++ b/jssmix.h	Fri Oct 05 02:47:36 2012 +0300
@@ -25,7 +25,11 @@
 {
     DMFixedPoint
             chPos,          // Current position in sample, 32:32 fixpoint
-            chDeltaO;       // Delta in 32:32 UNSIGNED! (chDirection)
+            chDeltaO,       // Delta in 32:32 UNSIGNED! (chDirection)
+            chVolume,       // Volume
+            chDeltaV,
+            chPanning,      // Panning
+            chDeltaP;
 
     int     chFreq;         // Frequency of sampel in Hz
     Sint32
@@ -40,8 +44,6 @@
             chDirection;    // TRUE = playing forwards, FALSE = backwards
 
     int     chFlags;        // Flags
-    int     chVolume,       // Volume
-            chPanning;      // Panning
 
     JMIXER_ADDBUF_TYPE chPrevR[5], chPrevL[5];
 } JSSChannel;
@@ -131,12 +133,16 @@
 
 void        jvmSetFreq(JSSMixer *mixer, const int channel, const int freq);
 int         jvmGetFreq(JSSMixer *mixer, const int channel);
+
 void        jvmSetVolume(JSSMixer *mixer, const int channel, const int volume);
+void        jvmSetVolumeRamp(JSSMixer * mixer, const int channel, const int start, const int end);
 int         jvmGetVolume(JSSMixer *mixer, const int channel);
+
 void        jvmSetPos(JSSMixer *mixer, const int channel, const Sint32 pos);
 Sint32      jvmGetPos(JSSMixer *mixer, const int channel);
 
 void        jvmSetPan(JSSMixer *mixer, const int channel, const int panning);
+void        jvmSetPanRamp(JSSMixer * mixer, const int channel, const int start, const int end);
 int         jvmGetPan(JSSMixer *mixer, const int channel);
 
 void        jvmMute(JSSMixer *mixer, const int channel, const BOOL mute);