audio: split sample conversion and volume mixing

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>
This commit is contained in:
Michael Walle 2011-01-05 01:05:47 +01:00 committed by malc
parent 0f136d9e06
commit 00e076795f
13 changed files with 52 additions and 55 deletions

View 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;

View 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) {

View 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);

View 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);

View 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;
}

View 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);

View 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
}

View 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 */

View file

@ -31,16 +31,6 @@
#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

View 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) {

View 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;
}

View 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;

View 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;