audio: split sample conversion and volume mixing
authorMichael Walle <michael@walle.cc>
Wed, 5 Jan 2011 00:05:47 +0000 (01:05 +0100)
committermalc <av1474@comtv.ru>
Wed, 12 Jan 2011 15:36:22 +0000 (18:36 +0300)
Refactor the volume mixing, so it can be reused for capturing devices.
Additionally, it removes superfluous multiplications with the nominal
volume within the hardware voice code path.

Signed-off-by: Michael Walle <michael@walle.cc>
Signed-off-by: malc <av1474@comtv.ru>
13 files changed:
audio/alsaaudio.c
audio/audio.c
audio/audio_int.h
audio/dsoundaudio.c
audio/esdaudio.c
audio/fmodaudio.c
audio/mixeng.c
audio/mixeng.h
audio/mixeng_template.h
audio/ossaudio.c
audio/paaudio.c
audio/spiceaudio.c
audio/winwaveaudio.c

index 727b9f84c3e9c23316e02d7d7dbdfb2fcdc9269a..4d720146df02ad22700b53e4bd04e5436566edaf 100644 (file)
@@ -1097,7 +1097,7 @@ static int alsa_run_in (HWVoiceIn *hw)
                 }
             }
 
-            hw->conv (dst, src, nread, &nominal_volume);
+            hw->conv (dst, src, nread);
 
             src = advance (src, nread << hwshift);
             dst += nread;
index 17074469b2502563260edeb0da1d4d93a1040cd8..1729c0be2c989f43c9d40cdcd7d04150b47a13cf 100644 (file)
@@ -104,7 +104,7 @@ static struct {
 
 static AudioState glob_audio_state;
 
-struct mixeng_volume nominal_volume = {
+const struct mixeng_volume nominal_volume = {
     .mute = 0,
 #ifdef FLOAT_MIXENG
     .r = 1.0,
@@ -702,13 +702,11 @@ void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len)
 /*
  * Capture
  */
-static void noop_conv (struct st_sample *dst, const void *src,
-                       int samples, struct mixeng_volume *vol)
+static void noop_conv (struct st_sample *dst, const void *src, int samples)
 {
     (void) src;
     (void) dst;
     (void) samples;
-    (void) vol;
 }
 
 static CaptureVoiceOut *audio_pcm_capture_find_specific (
@@ -956,6 +954,8 @@ int audio_pcm_sw_read (SWVoiceIn *sw, void *buf, int size)
         total += isamp;
     }
 
+    mixeng_volume (sw->buf, ret, &sw->vol);
+
     sw->clip (buf, sw->buf, ret);
     sw->total_hw_samples_acquired += total;
     return ret << sw->info.shift;
@@ -1037,7 +1037,8 @@ int audio_pcm_sw_write (SWVoiceOut *sw, void *buf, int size)
     swlim = ((int64_t) dead << 32) / sw->ratio;
     swlim = audio_MIN (swlim, samples);
     if (swlim) {
-        sw->conv (sw->buf, buf, swlim, &sw->vol);
+        sw->conv (sw->buf, buf, swlim);
+        mixeng_volume (sw->buf, swlim, &sw->vol);
     }
 
     while (swlim) {
index d66f2c3bf6fea2d7d7aa6bfba95f68887ac13502..2003f8bf20a56fb29c5518b39b690a87751f9552 100644 (file)
@@ -211,7 +211,7 @@ extern struct audio_driver esd_audio_driver;
 extern struct audio_driver pa_audio_driver;
 extern struct audio_driver spice_audio_driver;
 extern struct audio_driver winwave_audio_driver;
-extern struct mixeng_volume nominal_volume;
+extern const struct mixeng_volume nominal_volume;
 
 void audio_pcm_init_info (struct audio_pcm_info *info, struct audsettings *as);
 void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len);
index e5479555fa020dc7e0c61c6fc2bf5a0e5d434830..e2d89fd5d59d13c56cb14d71a99c815896493935 100644 (file)
@@ -831,11 +831,11 @@ static int dsound_run_in (HWVoiceIn *hw)
     decr = len1 + len2;
 
     if (p1 && len1) {
-        hw->conv (hw->conv_buf + hw->wpos, p1, len1, &nominal_volume);
+        hw->conv (hw->conv_buf + hw->wpos, p1, len1);
     }
 
     if (p2 && len2) {
-        hw->conv (hw->conv_buf, p2, len2, &nominal_volume);
+        hw->conv (hw->conv_buf, p2, len2);
     }
 
     dsound_unlock_in (dscb, p1, p2, blen1, blen2);
index 9a1f2f861781dbc356cb6ff95015693774c37085..ff97b397d20038a5e41fca5ff6fa4b584a665026 100644 (file)
@@ -346,8 +346,7 @@ static void *qesd_thread_in (void *arg)
                 break;
             }
 
-            hw->conv (hw->conv_buf + wpos, buf, nread >> hw->info.shift,
-                      &nominal_volume);
+            hw->conv (hw->conv_buf + wpos, buf, nread >> hw->info.shift);
             wpos = (wpos + chunk) % hw->samples;
             to_grab -= chunk;
         }
index 7f08e14718ec71b3689f237087d718df9ab1b9c3..c34cf535674abee262859bcf675b16ccfdebbb44 100644 (file)
@@ -488,10 +488,10 @@ static int fmod_run_in (HWVoiceIn *hw)
     decr = len1 + len2;
 
     if (p1 && blen1) {
-        hw->conv (hw->conv_buf + hw->wpos, p1, len1, &nominal_volume);
+        hw->conv (hw->conv_buf + hw->wpos, p1, len1);
     }
     if (p2 && len2) {
-        hw->conv (hw->conv_buf, p2, len2, &nominal_volume);
+        hw->conv (hw->conv_buf, p2, len2);
     }
 
     fmod_unlock_sample (fmd->fmod_sample, p1, p2, blen1, blen2);
index 9f1d93fcfc3d2ffcbfb18a321713ee9c9b80c638..4a9e8ebe2afe75cb941f9787975f26422563f12c 100644 (file)
@@ -333,3 +333,28 @@ void mixeng_clear (struct st_sample *buf, int len)
 {
     memset (buf, 0, len * sizeof (struct st_sample));
 }
+
+void mixeng_volume (struct st_sample *buf, int len, struct mixeng_volume *vol)
+{
+#ifdef CONFIG_MIXEMU
+    if (vol->mute) {
+        mixeng_clear (buf, len);
+        return;
+    }
+
+    while (len--) {
+#ifdef FLOAT_MIXENG
+        buf->l = buf->l * vol->l;
+        buf->r = buf->r * vol->r;
+#else
+        buf->l = (buf->l * vol->l) >> 32;
+        buf->r = (buf->r * vol->r) >> 32;
+#endif
+        buf += 1;
+    }
+#else
+    (void) buf;
+    (void) len;
+    (void) vol;
+#endif
+}
index 4af1dd989199eb6337de3d1f38433c5253711e40..9de443b01d5062dafadef3b54ae5d4513bb73e0d 100644 (file)
@@ -33,8 +33,7 @@ struct mixeng_volume { int mute; int64_t r; int64_t l; };
 struct st_sample { int64_t l; int64_t r; };
 #endif
 
-typedef void (t_sample) (struct st_sample *dst, const void *src,
-                         int samples, struct mixeng_volume *vol);
+typedef void (t_sample) (struct st_sample *dst, const void *src, int samples);
 typedef void (f_sample) (void *dst, const struct st_sample *src, int samples);
 
 extern t_sample *mixeng_conv[2][2][2][3];
@@ -47,5 +46,6 @@ void st_rate_flow_mix (void *opaque, struct st_sample *ibuf, struct st_sample *o
                        int *isamp, int *osamp);
 void st_rate_stop (void *opaque);
 void mixeng_clear (struct st_sample *buf, int len);
+void mixeng_volume (struct st_sample *buf, int len, struct mixeng_volume *vol);
 
 #endif  /* mixeng.h */
index 56177056ce1400087d6ec3a15e689f771e7e6141..a2d0ef84fd86d892d89b5338e822f7de36a2e0e2 100644 (file)
 #define HALF (IN_MAX >> 1)
 #endif
 
-#ifdef CONFIG_MIXEMU
-#ifdef FLOAT_MIXENG
-#define VOL(a, b) ((a) * (b))
-#else
-#define VOL(a, b) ((a) * (b)) >> 32
-#endif
-#else
-#define VOL(a, b) a
-#endif
-
 #define ET glue (ENDIAN_CONVERSION, glue (_, IN_T))
 
 #ifdef FLOAT_MIXENG
@@ -109,40 +99,26 @@ static inline IN_T glue (clip_, ET) (int64_t v)
 #endif
 
 static void glue (glue (conv_, ET), _to_stereo)
-    (struct st_sample *dst, const void *src, int samples, struct mixeng_volume *vol)
+    (struct st_sample *dst, const void *src, int samples)
 {
     struct st_sample *out = dst;
     IN_T *in = (IN_T *) src;
-#ifdef CONFIG_MIXEMU
-    if (vol->mute) {
-        mixeng_clear (dst, samples);
-        return;
-    }
-#else
-    (void) vol;
-#endif
+
     while (samples--) {
-        out->l = VOL (glue (conv_, ET) (*in++), vol->l);
-        out->r = VOL (glue (conv_, ET) (*in++), vol->r);
+        out->l = glue (conv_, ET) (*in++);
+        out->r = glue (conv_, ET) (*in++);
         out += 1;
     }
 }
 
 static void glue (glue (conv_, ET), _to_mono)
-    (struct st_sample *dst, const void *src, int samples, struct mixeng_volume *vol)
+    (struct st_sample *dst, const void *src, int samples)
 {
     struct st_sample *out = dst;
     IN_T *in = (IN_T *) src;
-#ifdef CONFIG_MIXEMU
-    if (vol->mute) {
-        mixeng_clear (dst, samples);
-        return;
-    }
-#else
-    (void) vol;
-#endif
+
     while (samples--) {
-        out->l = VOL (glue (conv_, ET) (in[0]), vol->l);
+        out->l = glue (conv_, ET) (in[0]);
         out->r = out->l;
         out += 1;
         in += 1;
@@ -174,4 +150,3 @@ static void glue (glue (clip_, ET), _from_mono)
 
 #undef ET
 #undef HALF
-#undef VOL
index d7a55e5441f6f92826161617ddfb5263581ee044..b49e102747737f05db7fca6347bf927df66fb28b 100644 (file)
@@ -788,8 +788,7 @@ static int oss_run_in (HWVoiceIn *hw)
                            hw->info.align + 1);
                 }
                 read_samples += nread >> hwshift;
-                hw->conv (hw->conv_buf + bufs[i].add, p, nread >> hwshift,
-                          &nominal_volume);
+                hw->conv (hw->conv_buf + bufs[i].add, p, nread >> hwshift);
             }
 
             if (bufs[i].len - nread) {
index ff71dac2a59a044cd4223f70421bfeedd3b16f48..9cf685d30fe6c28b9a609228cf60d0317faf7aad 100644 (file)
@@ -195,7 +195,7 @@ static void *qpa_thread_in (void *arg)
                 return NULL;
             }
 
-            hw->conv (hw->conv_buf + wpos, buf, chunk, &nominal_volume);
+            hw->conv (hw->conv_buf + wpos, buf, chunk);
             wpos = (wpos + chunk) % hw->samples;
             to_grab -= chunk;
         }
index 373e4c43ed9935903ea9af107e75da6bed26ac23..a5c0d6bc660b17289c73af3d47b1a4b3b9792ca5 100644 (file)
@@ -268,11 +268,10 @@ static int line_in_run (HWVoiceIn *hw)
         len[1] = 0;
     }
 
-    hw->conv (hw->conv_buf + hw->wpos, samples, len[0], &nominal_volume);
+    hw->conv (hw->conv_buf + hw->wpos, samples, len[0]);
 
     if (len[1]) {
-        hw->conv (hw->conv_buf, samples + len[0], len[1],
-                  &nominal_volume);
+        hw->conv (hw->conv_buf, samples + len[0], len[1]);
     }
 
     hw->wpos = (hw->wpos + num_samples) % hw->samples;
index cdf483b89ac432ab4c2dc639649414b84de00b33..e5ad3c66047005364ce889be6f82daf3a50eb0cf 100644 (file)
@@ -581,8 +581,7 @@ static int winwave_run_in (HWVoiceIn *hw)
         int conv = audio_MIN (left, decr);
         hw->conv (hw->conv_buf + hw->wpos,
                   advance (wave->pcm_buf, wave->rpos << hw->info.shift),
-                  conv,
-                  &nominal_volume);
+                  conv);
 
         wave->rpos = (wave->rpos + conv) % hw->samples;
         hw->wpos = (hw->wpos + conv) % hw->samples;