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:
parent
0f136d9e06
commit
00e076795f
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user