have individual function for mixing stream with different sample format instead of huge case block in pa_mix() shorter functions, prepare for optimized code path Signed-off-by: Peter Meerwald <pmeerw at pmeerw.net> --- src/pulsecore/mix.c | 674 +++++++++++++++++++++++++-------------------------- 1 file changed, 330 insertions(+), 344 deletions(-) diff --git a/src/pulsecore/mix.c b/src/pulsecore/mix.c index af854cc..2a132e1 100644 --- a/src/pulsecore/mix.c +++ b/src/pulsecore/mix.c @@ -122,490 +122,476 @@ static const pa_calc_stream_volumes_func_t calc_stream_volumes_table[] = { [PA_SAMPLE_S24_32BE] = (pa_calc_stream_volumes_func_t) calc_linear_integer_stream_volumes }; -size_t pa_mix( - pa_mix_info streams[], - unsigned nstreams, - void *data, - size_t length, - const pa_sample_spec *spec, - const pa_cvolume *volume, - pa_bool_t mute) { - - pa_cvolume full_volume; - unsigned k; - unsigned z; - void *end; - - pa_assert(streams); - pa_assert(data); - pa_assert(length); - pa_assert(spec); - - if (!volume) - volume = pa_cvolume_reset(&full_volume, spec->channels); +static void pa_mix_s16ne_c(pa_mix_info streams[], unsigned nstreams, unsigned channels, void *data, void *end) { + unsigned channel = 0; - if (mute || pa_cvolume_is_muted(volume) || nstreams <= 0) { - pa_silence_memory(data, length, spec); - return length; - } - - for (k = 0; k < nstreams; k++) - streams[k].ptr = pa_memblock_acquire_chunk(&streams[k].chunk); + while (data < end) { + int32_t sum = 0; + unsigned i; - for (z = 0; z < nstreams; z++) - if (length > streams[z].chunk.length) - length = streams[z].chunk.length; + for (i = 0; i < nstreams; i++) { + pa_mix_info *m = streams + i; + int32_t v, lo, hi, cv = m->linear[channel].i; - end = (uint8_t*) data + length; + if (PA_LIKELY(cv > 0)) { - calc_stream_volumes_table[spec->format](streams, nstreams, volume, spec); + /* Multiplying the 32bit volume factor with the + * 16bit sample might result in an 48bit value. We + * want to do without 64 bit integers and hence do + * the multiplication independently for the HI and + * LO part of the volume. */ - switch (spec->format) { + hi = cv >> 16; + lo = cv & 0xFFFF; - case PA_SAMPLE_S16NE:{ - unsigned channel = 0; + v = *((int16_t*) m->ptr); + v = ((v * lo) >> 16) + (v * hi); + sum += v; + } + m->ptr = (uint8_t*) m->ptr + sizeof(int16_t); + } - while (data < end) { - int32_t sum = 0; - unsigned i; + sum = PA_CLAMP_UNLIKELY(sum, -0x8000, 0x7FFF); + *((int16_t*) data) = (int16_t) sum; - for (i = 0; i < nstreams; i++) { - pa_mix_info *m = streams + i; - int32_t v, lo, hi, cv = m->linear[channel].i; + data = (uint8_t*) data + sizeof(int16_t); - if (PA_LIKELY(cv > 0)) { + if (PA_UNLIKELY(++channel >= channels)) + channel = 0; + } +} - /* Multiplying the 32bit volume factor with the - * 16bit sample might result in an 48bit value. We - * want to do without 64 bit integers and hence do - * the multiplication independently for the HI and - * LO part of the volume. */ +static void pa_mix_s16re_c(pa_mix_info streams[], unsigned nstreams, unsigned channels, void *data, void *end) { + unsigned channel = 0; - hi = cv >> 16; - lo = cv & 0xFFFF; + while (data < end) { + int32_t sum = 0; + unsigned i; - v = *((int16_t*) m->ptr); - v = ((v * lo) >> 16) + (v * hi); - sum += v; - } - m->ptr = (uint8_t*) m->ptr + sizeof(int16_t); - } + for (i = 0; i < nstreams; i++) { + pa_mix_info *m = streams + i; + int32_t v, lo, hi, cv = m->linear[channel].i; - sum = PA_CLAMP_UNLIKELY(sum, -0x8000, 0x7FFF); - *((int16_t*) data) = (int16_t) sum; + if (PA_LIKELY(cv > 0)) { - data = (uint8_t*) data + sizeof(int16_t); + hi = cv >> 16; + lo = cv & 0xFFFF; - if (PA_UNLIKELY(++channel >= spec->channels)) - channel = 0; + v = PA_INT16_SWAP(*((int16_t*) m->ptr)); + v = ((v * lo) >> 16) + (v * hi); + sum += v; } - - break; + m->ptr = (uint8_t*) m->ptr + sizeof(int16_t); } - case PA_SAMPLE_S16RE:{ - unsigned channel = 0; - - while (data < end) { - int32_t sum = 0; - unsigned i; + sum = PA_CLAMP_UNLIKELY(sum, -0x8000, 0x7FFF); + *((int16_t*) data) = PA_INT16_SWAP((int16_t) sum); - for (i = 0; i < nstreams; i++) { - pa_mix_info *m = streams + i; - int32_t v, lo, hi, cv = m->linear[channel].i; + data = (uint8_t*) data + sizeof(int16_t); - if (PA_LIKELY(cv > 0)) { + if (PA_UNLIKELY(++channel >= channels)) + channel = 0; + } +} - hi = cv >> 16; - lo = cv & 0xFFFF; +static void pa_mix_s32ne_c(pa_mix_info streams[], unsigned nstreams, unsigned channels, void *data, void *end) { + unsigned channel = 0; - v = PA_INT16_SWAP(*((int16_t*) m->ptr)); - v = ((v * lo) >> 16) + (v * hi); - sum += v; - } - m->ptr = (uint8_t*) m->ptr + sizeof(int16_t); - } + while (data < end) { + int64_t sum = 0; + unsigned i; - sum = PA_CLAMP_UNLIKELY(sum, -0x8000, 0x7FFF); - *((int16_t*) data) = PA_INT16_SWAP((int16_t) sum); + for (i = 0; i < nstreams; i++) { + pa_mix_info *m = streams + i; + int32_t cv = m->linear[channel].i; + int64_t v; - data = (uint8_t*) data + sizeof(int16_t); + if (PA_LIKELY(cv > 0)) { - if (PA_UNLIKELY(++channel >= spec->channels)) - channel = 0; + v = *((int32_t*) m->ptr); + v = (v * cv) >> 16; + sum += v; } - - break; + m->ptr = (uint8_t*) m->ptr + sizeof(int32_t); } - case PA_SAMPLE_S32NE:{ - unsigned channel = 0; + sum = PA_CLAMP_UNLIKELY(sum, -0x80000000LL, 0x7FFFFFFFLL); + *((int32_t*) data) = (int32_t) sum; - while (data < end) { - int64_t sum = 0; - unsigned i; + data = (uint8_t*) data + sizeof(int32_t); - for (i = 0; i < nstreams; i++) { - pa_mix_info *m = streams + i; - int32_t cv = m->linear[channel].i; - int64_t v; + if (PA_UNLIKELY(++channel >= channels)) + channel = 0; + } +} - if (PA_LIKELY(cv > 0)) { +static void pa_mix_s32re_c(pa_mix_info streams[], unsigned nstreams, unsigned channels, void *data, void *end) { + unsigned channel = 0; - v = *((int32_t*) m->ptr); - v = (v * cv) >> 16; - sum += v; - } - m->ptr = (uint8_t*) m->ptr + sizeof(int32_t); - } + while (data < end) { + int64_t sum = 0; + unsigned i; - sum = PA_CLAMP_UNLIKELY(sum, -0x80000000LL, 0x7FFFFFFFLL); - *((int32_t*) data) = (int32_t) sum; + for (i = 0; i < nstreams; i++) { + pa_mix_info *m = streams + i; + int32_t cv = m->linear[channel].i; + int64_t v; - data = (uint8_t*) data + sizeof(int32_t); + if (PA_LIKELY(cv > 0)) { - if (PA_UNLIKELY(++channel >= spec->channels)) - channel = 0; + v = PA_INT32_SWAP(*((int32_t*) m->ptr)); + v = (v * cv) >> 16; + sum += v; } - - break; + m->ptr = (uint8_t*) m->ptr + sizeof(int32_t); } - case PA_SAMPLE_S32RE:{ - unsigned channel = 0; + sum = PA_CLAMP_UNLIKELY(sum, -0x80000000LL, 0x7FFFFFFFLL); + *((int32_t*) data) = PA_INT32_SWAP((int32_t) sum); - while (data < end) { - int64_t sum = 0; - unsigned i; + data = (uint8_t*) data + sizeof(int32_t); - for (i = 0; i < nstreams; i++) { - pa_mix_info *m = streams + i; - int32_t cv = m->linear[channel].i; - int64_t v; + if (PA_UNLIKELY(++channel >= channels)) + channel = 0; + } +} - if (PA_LIKELY(cv > 0)) { +static void pa_mix_s24ne_c(pa_mix_info streams[], unsigned nstreams, unsigned channels, void *data, void *end) { + unsigned channel = 0; - v = PA_INT32_SWAP(*((int32_t*) m->ptr)); - v = (v * cv) >> 16; - sum += v; - } - m->ptr = (uint8_t*) m->ptr + sizeof(int32_t); - } + while (data < end) { + int64_t sum = 0; + unsigned i; - sum = PA_CLAMP_UNLIKELY(sum, -0x80000000LL, 0x7FFFFFFFLL); - *((int32_t*) data) = PA_INT32_SWAP((int32_t) sum); + for (i = 0; i < nstreams; i++) { + pa_mix_info *m = streams + i; + int32_t cv = m->linear[channel].i; + int64_t v; - data = (uint8_t*) data + sizeof(int32_t); + if (PA_LIKELY(cv > 0)) { - if (PA_UNLIKELY(++channel >= spec->channels)) - channel = 0; + v = (int32_t) (PA_READ24NE(m->ptr) << 8); + v = (v * cv) >> 16; + sum += v; } - - break; + m->ptr = (uint8_t*) m->ptr + 3; } - case PA_SAMPLE_S24NE: { - unsigned channel = 0; + sum = PA_CLAMP_UNLIKELY(sum, -0x80000000LL, 0x7FFFFFFFLL); + PA_WRITE24NE(data, ((uint32_t) sum) >> 8); - while (data < end) { - int64_t sum = 0; - unsigned i; + data = (uint8_t*) data + 3; - for (i = 0; i < nstreams; i++) { - pa_mix_info *m = streams + i; - int32_t cv = m->linear[channel].i; - int64_t v; + if (PA_UNLIKELY(++channel >= channels)) + channel = 0; + } +} - if (PA_LIKELY(cv > 0)) { +static void pa_mix_s24re_c(pa_mix_info streams[], unsigned nstreams, unsigned channels, void *data, void *end) { + unsigned channel = 0; - v = (int32_t) (PA_READ24NE(m->ptr) << 8); - v = (v * cv) >> 16; - sum += v; - } - m->ptr = (uint8_t*) m->ptr + 3; - } + while (data < end) { + int64_t sum = 0; + unsigned i; - sum = PA_CLAMP_UNLIKELY(sum, -0x80000000LL, 0x7FFFFFFFLL); - PA_WRITE24NE(data, ((uint32_t) sum) >> 8); + for (i = 0; i < nstreams; i++) { + pa_mix_info *m = streams + i; + int32_t cv = m->linear[channel].i; + int64_t v; - data = (uint8_t*) data + 3; + if (PA_LIKELY(cv > 0)) { - if (PA_UNLIKELY(++channel >= spec->channels)) - channel = 0; + v = (int32_t) (PA_READ24RE(m->ptr) << 8); + v = (v * cv) >> 16; + sum += v; } - - break; + m->ptr = (uint8_t*) m->ptr + 3; } - case PA_SAMPLE_S24RE: { - unsigned channel = 0; + sum = PA_CLAMP_UNLIKELY(sum, -0x80000000LL, 0x7FFFFFFFLL); + PA_WRITE24RE(data, ((uint32_t) sum) >> 8); - while (data < end) { - int64_t sum = 0; - unsigned i; + data = (uint8_t*) data + 3; - for (i = 0; i < nstreams; i++) { - pa_mix_info *m = streams + i; - int32_t cv = m->linear[channel].i; - int64_t v; + if (PA_UNLIKELY(++channel >= channels)) + channel = 0; + } +} - if (PA_LIKELY(cv > 0)) { +static void pa_mix_s24_32ne_c(pa_mix_info streams[], unsigned nstreams, unsigned channels, void *data, void *end) { + unsigned channel = 0; - v = (int32_t) (PA_READ24RE(m->ptr) << 8); - v = (v * cv) >> 16; - sum += v; - } - m->ptr = (uint8_t*) m->ptr + 3; - } + while (data < end) { + int64_t sum = 0; + unsigned i; - sum = PA_CLAMP_UNLIKELY(sum, -0x80000000LL, 0x7FFFFFFFLL); - PA_WRITE24RE(data, ((uint32_t) sum) >> 8); + for (i = 0; i < nstreams; i++) { + pa_mix_info *m = streams + i; + int32_t cv = m->linear[channel].i; + int64_t v; - data = (uint8_t*) data + 3; + if (PA_LIKELY(cv > 0)) { - if (PA_UNLIKELY(++channel >= spec->channels)) - channel = 0; + v = (int32_t) (*((uint32_t*)m->ptr) << 8); + v = (v * cv) >> 16; + sum += v; } - - break; + m->ptr = (uint8_t*) m->ptr + sizeof(int32_t); } - case PA_SAMPLE_S24_32NE: { - unsigned channel = 0; + sum = PA_CLAMP_UNLIKELY(sum, -0x80000000LL, 0x7FFFFFFFLL); + *((uint32_t*) data) = ((uint32_t) (int32_t) sum) >> 8; - while (data < end) { - int64_t sum = 0; - unsigned i; + data = (uint8_t*) data + sizeof(uint32_t); - for (i = 0; i < nstreams; i++) { - pa_mix_info *m = streams + i; - int32_t cv = m->linear[channel].i; - int64_t v; + if (PA_UNLIKELY(++channel >= channels)) + channel = 0; + } +} - if (PA_LIKELY(cv > 0)) { +static void pa_mix_s24_32re_c(pa_mix_info streams[], unsigned nstreams, unsigned channels, void *data, void *end) { + unsigned channel = 0; - v = (int32_t) (*((uint32_t*)m->ptr) << 8); - v = (v * cv) >> 16; - sum += v; - } - m->ptr = (uint8_t*) m->ptr + sizeof(int32_t); - } + while (data < end) { + int64_t sum = 0; + unsigned i; - sum = PA_CLAMP_UNLIKELY(sum, -0x80000000LL, 0x7FFFFFFFLL); - *((uint32_t*) data) = ((uint32_t) (int32_t) sum) >> 8; + for (i = 0; i < nstreams; i++) { + pa_mix_info *m = streams + i; + int32_t cv = m->linear[channel].i; + int64_t v; - data = (uint8_t*) data + sizeof(uint32_t); + if (PA_LIKELY(cv > 0)) { - if (PA_UNLIKELY(++channel >= spec->channels)) - channel = 0; + v = (int32_t) (PA_UINT32_SWAP(*((uint32_t*) m->ptr)) << 8); + v = (v * cv) >> 16; + sum += v; } - - break; + m->ptr = (uint8_t*) m->ptr + 3; } - case PA_SAMPLE_S24_32RE: { - unsigned channel = 0; + sum = PA_CLAMP_UNLIKELY(sum, -0x80000000LL, 0x7FFFFFFFLL); + *((uint32_t*) data) = PA_INT32_SWAP(((uint32_t) (int32_t) sum) >> 8); - while (data < end) { - int64_t sum = 0; - unsigned i; + data = (uint8_t*) data + sizeof(uint32_t); - for (i = 0; i < nstreams; i++) { - pa_mix_info *m = streams + i; - int32_t cv = m->linear[channel].i; - int64_t v; + if (PA_UNLIKELY(++channel >= channels)) + channel = 0; + } +} - if (PA_LIKELY(cv > 0)) { +static void pa_mix_u8_c(pa_mix_info streams[], unsigned nstreams, unsigned channels, void *data, void *end) { + unsigned channel = 0; - v = (int32_t) (PA_UINT32_SWAP(*((uint32_t*) m->ptr)) << 8); - v = (v * cv) >> 16; - sum += v; - } - m->ptr = (uint8_t*) m->ptr + 3; - } + while (data < end) { + int32_t sum = 0; + unsigned i; - sum = PA_CLAMP_UNLIKELY(sum, -0x80000000LL, 0x7FFFFFFFLL); - *((uint32_t*) data) = PA_INT32_SWAP(((uint32_t) (int32_t) sum) >> 8); + for (i = 0; i < nstreams; i++) { + pa_mix_info *m = streams + i; + int32_t v, cv = m->linear[channel].i; - data = (uint8_t*) data + sizeof(uint32_t); + if (PA_LIKELY(cv > 0)) { - if (PA_UNLIKELY(++channel >= spec->channels)) - channel = 0; + v = (int32_t) *((uint8_t*) m->ptr) - 0x80; + v = (v * cv) >> 16; + sum += v; } - - break; + m->ptr = (uint8_t*) m->ptr + 1; } - case PA_SAMPLE_U8: { - unsigned channel = 0; + sum = PA_CLAMP_UNLIKELY(sum, -0x80, 0x7F); + *((uint8_t*) data) = (uint8_t) (sum + 0x80); - while (data < end) { - int32_t sum = 0; - unsigned i; + data = (uint8_t*) data + 1; - for (i = 0; i < nstreams; i++) { - pa_mix_info *m = streams + i; - int32_t v, cv = m->linear[channel].i; + if (PA_UNLIKELY(++channel >= channels)) + channel = 0; + } +} - if (PA_LIKELY(cv > 0)) { +static void pa_mix_ulaw_c(pa_mix_info streams[], unsigned nstreams, unsigned channels, void *data, void *end) { + unsigned channel = 0; - v = (int32_t) *((uint8_t*) m->ptr) - 0x80; - v = (v * cv) >> 16; - sum += v; - } - m->ptr = (uint8_t*) m->ptr + 1; - } + while (data < end) { + int32_t sum = 0; + unsigned i; - sum = PA_CLAMP_UNLIKELY(sum, -0x80, 0x7F); - *((uint8_t*) data) = (uint8_t) (sum + 0x80); + for (i = 0; i < nstreams; i++) { + pa_mix_info *m = streams + i; + int32_t v, hi, lo, cv = m->linear[channel].i; - data = (uint8_t*) data + 1; + if (PA_LIKELY(cv > 0)) { - if (PA_UNLIKELY(++channel >= spec->channels)) - channel = 0; - } + hi = cv >> 16; + lo = cv & 0xFFFF; - break; + v = (int32_t) st_ulaw2linear16(*((uint8_t*) m->ptr)); + v = ((v * lo) >> 16) + (v * hi); + sum += v; + } + m->ptr = (uint8_t*) m->ptr + 1; } - case PA_SAMPLE_ULAW: { - unsigned channel = 0; + sum = PA_CLAMP_UNLIKELY(sum, -0x8000, 0x7FFF); + *((uint8_t*) data) = (uint8_t) st_14linear2ulaw((int16_t) sum >> 2); - while (data < end) { - int32_t sum = 0; - unsigned i; + data = (uint8_t*) data + 1; - for (i = 0; i < nstreams; i++) { - pa_mix_info *m = streams + i; - int32_t v, hi, lo, cv = m->linear[channel].i; + if (PA_UNLIKELY(++channel >= channels)) + channel = 0; + } +} - if (PA_LIKELY(cv > 0)) { +static void pa_mix_alaw_c(pa_mix_info streams[], unsigned nstreams, unsigned channels, void *data, void *end) { + unsigned channel = 0; - hi = cv >> 16; - lo = cv & 0xFFFF; + while (data < end) { + int32_t sum = 0; + unsigned i; - v = (int32_t) st_ulaw2linear16(*((uint8_t*) m->ptr)); - v = ((v * lo) >> 16) + (v * hi); - sum += v; - } - m->ptr = (uint8_t*) m->ptr + 1; - } + for (i = 0; i < nstreams; i++) { + pa_mix_info *m = streams + i; + int32_t v, hi, lo, cv = m->linear[channel].i; - sum = PA_CLAMP_UNLIKELY(sum, -0x8000, 0x7FFF); - *((uint8_t*) data) = (uint8_t) st_14linear2ulaw((int16_t) sum >> 2); + if (PA_LIKELY(cv > 0)) { - data = (uint8_t*) data + 1; + hi = cv >> 16; + lo = cv & 0xFFFF; - if (PA_UNLIKELY(++channel >= spec->channels)) - channel = 0; + v = (int32_t) st_alaw2linear16(*((uint8_t*) m->ptr)); + v = ((v * lo) >> 16) + (v * hi); + sum += v; } - - break; + m->ptr = (uint8_t*) m->ptr + 1; } - case PA_SAMPLE_ALAW: { - unsigned channel = 0; + sum = PA_CLAMP_UNLIKELY(sum, -0x8000, 0x7FFF); + *((uint8_t*) data) = (uint8_t) st_13linear2alaw((int16_t) sum >> 3); - while (data < end) { - int32_t sum = 0; - unsigned i; + data = (uint8_t*) data + 1; - for (i = 0; i < nstreams; i++) { - pa_mix_info *m = streams + i; - int32_t v, hi, lo, cv = m->linear[channel].i; - - if (PA_LIKELY(cv > 0)) { + if (PA_UNLIKELY(++channel >= channels)) + channel = 0; + } +} - hi = cv >> 16; - lo = cv & 0xFFFF; +static void pa_mix_float32ne_c(pa_mix_info streams[], unsigned nstreams, unsigned channels, void *data, void *end) { + unsigned channel = 0; - v = (int32_t) st_alaw2linear16(*((uint8_t*) m->ptr)); - v = ((v * lo) >> 16) + (v * hi); - sum += v; - } - m->ptr = (uint8_t*) m->ptr + 1; - } + while (data < end) { + float sum = 0; + unsigned i; - sum = PA_CLAMP_UNLIKELY(sum, -0x8000, 0x7FFF); - *((uint8_t*) data) = (uint8_t) st_13linear2alaw((int16_t) sum >> 3); + for (i = 0; i < nstreams; i++) { + pa_mix_info *m = streams + i; + float v, cv = m->linear[channel].f; - data = (uint8_t*) data + 1; + if (PA_LIKELY(cv > 0)) { - if (PA_UNLIKELY(++channel >= spec->channels)) - channel = 0; + v = *((float*) m->ptr); + v *= cv; + sum += v; } - - break; + m->ptr = (uint8_t*) m->ptr + sizeof(float); } - case PA_SAMPLE_FLOAT32NE: { - unsigned channel = 0; + *((float*) data) = sum; - while (data < end) { - float sum = 0; - unsigned i; + data = (uint8_t*) data + sizeof(float); - for (i = 0; i < nstreams; i++) { - pa_mix_info *m = streams + i; - float v, cv = m->linear[channel].f; + if (PA_UNLIKELY(++channel >= channels)) + channel = 0; + } +} - if (PA_LIKELY(cv > 0)) { +static void pa_mix_float32re_c(pa_mix_info streams[], unsigned nstreams, unsigned channels, void *data, void *end) { + unsigned channel = 0; - v = *((float*) m->ptr); - v *= cv; - sum += v; - } - m->ptr = (uint8_t*) m->ptr + sizeof(float); - } + while (data < end) { + float sum = 0; + unsigned i; - *((float*) data) = sum; + for (i = 0; i < nstreams; i++) { + pa_mix_info *m = streams + i; + float v, cv = m->linear[channel].f; - data = (uint8_t*) data + sizeof(float); + if (PA_LIKELY(cv > 0)) { - if (PA_UNLIKELY(++channel >= spec->channels)) - channel = 0; + v = PA_FLOAT32_SWAP(*(float*) m->ptr); + v *= cv; + sum += v; } - - break; + m->ptr = (uint8_t*) m->ptr + sizeof(float); } - case PA_SAMPLE_FLOAT32RE: { - unsigned channel = 0; + *((float*) data) = PA_FLOAT32_SWAP(sum); - while (data < end) { - float sum = 0; - unsigned i; + data = (uint8_t*) data + sizeof(float); - for (i = 0; i < nstreams; i++) { - pa_mix_info *m = streams + i; - float v, cv = m->linear[channel].f; - - if (PA_LIKELY(cv > 0)) { + if (PA_UNLIKELY(++channel >= channels)) + channel = 0; + } +} - v = PA_FLOAT32_SWAP(*(float*) m->ptr); - v *= cv; - sum += v; - } - m->ptr = (uint8_t*) m->ptr + sizeof(float); - } +typedef void (*pa_do_mix_func_t) (pa_mix_info streams[], unsigned nstreams, unsigned channels, void *data, void *end); + +static pa_do_mix_func_t do_mix_table[] = { + [PA_SAMPLE_U8] = (pa_do_mix_func_t) pa_mix_u8_c, + [PA_SAMPLE_ALAW] = (pa_do_mix_func_t) pa_mix_alaw_c, + [PA_SAMPLE_ULAW] = (pa_do_mix_func_t) pa_mix_ulaw_c, + [PA_SAMPLE_S16NE] = (pa_do_mix_func_t) pa_mix_s16ne_c, + [PA_SAMPLE_S16RE] = (pa_do_mix_func_t) pa_mix_s16re_c, + [PA_SAMPLE_FLOAT32NE] = (pa_do_mix_func_t) pa_mix_float32ne_c, + [PA_SAMPLE_FLOAT32RE] = (pa_do_mix_func_t) pa_mix_float32re_c, + [PA_SAMPLE_S32NE] = (pa_do_mix_func_t) pa_mix_s32ne_c, + [PA_SAMPLE_S32RE] = (pa_do_mix_func_t) pa_mix_s32re_c, + [PA_SAMPLE_S24NE] = (pa_do_mix_func_t) pa_mix_s24ne_c, + [PA_SAMPLE_S24RE] = (pa_do_mix_func_t) pa_mix_s24re_c, + [PA_SAMPLE_S24_32NE] = (pa_do_mix_func_t) pa_mix_s24_32ne_c, + [PA_SAMPLE_S24_32RE] = (pa_do_mix_func_t) pa_mix_s24_32re_c +}; - *((float*) data) = PA_FLOAT32_SWAP(sum); +size_t pa_mix( + pa_mix_info streams[], + unsigned nstreams, + void *data, + size_t length, + const pa_sample_spec *spec, + const pa_cvolume *volume, + pa_bool_t mute) { - data = (uint8_t*) data + sizeof(float); + pa_cvolume full_volume; + unsigned k; + unsigned z; + void *end; - if (PA_UNLIKELY(++channel >= spec->channels)) - channel = 0; - } + pa_assert(streams); + pa_assert(data); + pa_assert(length); + pa_assert(spec); - break; - } + if (!volume) + volume = pa_cvolume_reset(&full_volume, spec->channels); - default: - pa_log_error("Unable to mix audio data of format %s.", pa_sample_format_to_string(spec->format)); - pa_assert_not_reached(); + if (mute || pa_cvolume_is_muted(volume) || nstreams <= 0) { + pa_silence_memory(data, length, spec); + return length; } for (k = 0; k < nstreams; k++) + streams[k].ptr = pa_memblock_acquire_chunk(&streams[k].chunk); + + for (z = 0; z < nstreams; z++) + if (length > streams[z].chunk.length) + length = streams[z].chunk.length; + + end = (uint8_t*) data + length; + + calc_stream_volumes_table[spec->format](streams, nstreams, volume, spec); + do_mix_table[spec->format](streams, nstreams, spec->channels, data, end); + + for (k = 0; k < nstreams; k++) pa_memblock_release(streams[k].chunk.memblock); return length; -- 1.7.9.5