if all channels have same volume setting, use fast way to do volume change. this patch intended to work for two formats: s16ne/s16re. Signed-off-by: Wang Xingchao <xingchao.wang at intel.com> --- src/pulsecore/svolume_c.c | 70 +++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 70 insertions(+), 0 deletions(-) diff --git a/src/pulsecore/svolume_c.c b/src/pulsecore/svolume_c.c index 272e7a7..7919faa 100644 --- a/src/pulsecore/svolume_c.c +++ b/src/pulsecore/svolume_c.c @@ -90,9 +90,43 @@ static void pa_volume_ulaw_c(uint8_t *samples, int32_t *volumes, unsigned channe static void pa_volume_s16ne_c(int16_t *samples, int32_t *volumes, unsigned channels, unsigned length) { unsigned channel; + int32_t same_vol = volumes[0]; + unsigned fast_vol; length /= sizeof(int16_t); + for (channel = 0; channel < channels; channel++) { + if (volumes[channel] != same_vol) + break; + } + + fast_vol = channel < channels? 0 : 1; + + if (fast_vol) { + int32_t t, hi, lo; + int32_t ht, lt; + + hi = same_vol >> 16; + lo = same_vol & 0xffff; + while (length) { + t = *((int32_t *)samples); + ht = t >> 16; + lt = t & 0xffff; + + ht = ((ht * lo) >> 16) + (ht * hi); + ht = PA_CLAMP_UNLIKELY(ht, -0x8000, 0x7FFF); + + lt = ((lt * lo) >> 16) + (lt * hi); + lt = PA_CLAMP_UNLIKELY(lt, -0x8000, 0x7FFF); + + *((int32_t *)samples) = ht<<16|lt; + + samples += 2; + length -= 2; + } + + return; + } for (channel = 0; length; length--) { int32_t t, hi, lo; @@ -117,9 +151,45 @@ static void pa_volume_s16ne_c(int16_t *samples, int32_t *volumes, unsigned chann static void pa_volume_s16re_c(int16_t *samples, int32_t *volumes, unsigned channels, unsigned length) { unsigned channel; + int32_t same_vol = volumes[0]; + unsigned fast_vol; length /= sizeof(int16_t); + for (channel = 0; channel < channels; channel++) { + if (volumes[channel] != same_vol) + break; + } + + fast_vol = channel < channels? 0 : 1; + + if (fast_vol) { + int32_t t, hi, lo; + int32_t ht, lt; + + hi = same_vol >> 16; + lo = same_vol & 0xffff; + + while (length) { + t = *((int32_t *)samples); + ht = (int32_t)PA_INT16_SWAP((int16_t)(t >> 16)); + lt = (int32_t)PA_INT16_SWAP((int16_t)(t & 0xffff)); + + ht = ((ht * lo) >> 16) + (ht * hi); + ht = PA_CLAMP_UNLIKELY(ht, -0x8000, 0x7FFF); + + lt = ((lt * lo) >> 16) + (lt * hi); + lt = PA_CLAMP_UNLIKELY(lt, -0x8000, 0x7FFF); + + *((int32_t *)samples) = PA_INT16_SWAP((int16_t) ht<<16)|PA_INT16_SWAP((int16_t) lt); + + samples += 2; + length -= 2; + } + + return; + } + for (channel = 0; length; length--) { int32_t t, hi, lo; -- 1.7.1