mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-02 09:01:50 -05:00
audiomixer: rewrite the mixer functions
Let the mixer functions accumulate the intermediate results into a larger size variable and then clamp to the final precission. This avoids distortions because of intermediate clamping. Although the access pattern of the reads are no longer sequential, the writes are sequential and we don't need to read intermediate values. Together with the avoided clamping this is probably faster overall. Add a unit test for the various cases.
This commit is contained in:
parent
3ffb9f4b26
commit
371b5a1836
4 changed files with 376 additions and 48 deletions
|
|
@ -30,34 +30,39 @@
|
|||
|
||||
#include "mix-ops.h"
|
||||
|
||||
#define MAKE_FUNC(name,type,func) \
|
||||
#define MAKE_FUNC(name,type,atype,accum,clamp,zero) \
|
||||
void mix_ ##name## _c(struct mix_ops *ops, \
|
||||
void * SPA_RESTRICT dst, const void * SPA_RESTRICT src[], \
|
||||
uint32_t n_src, uint32_t n_samples) \
|
||||
{ \
|
||||
uint32_t i, n; \
|
||||
type *d = dst; \
|
||||
const type **s = (const type **)src; \
|
||||
n_samples *= ops->n_channels; \
|
||||
if (n_src == 0) \
|
||||
if (n_src == 0 && zero) \
|
||||
memset(dst, 0, n_samples * sizeof(type)); \
|
||||
else if (dst != src[0]) \
|
||||
spa_memcpy(dst, src[0], n_samples * sizeof(type)); \
|
||||
for (i = 1; i < n_src; i++) { \
|
||||
const type *s = src[i]; \
|
||||
for (n = 0; n < n_samples; n++) \
|
||||
d[n] = func (d[n], s[n]); \
|
||||
else if (n_src == 1) { \
|
||||
if (dst != src[0]) \
|
||||
spa_memcpy(dst, src[0], n_samples * sizeof(type)); \
|
||||
} else { \
|
||||
for (n = 0; n < n_samples; n++) { \
|
||||
atype ac = 0; \
|
||||
for (i = 0; i < n_src; i++) \
|
||||
ac = accum (ac, s[i][n]); \
|
||||
d[n] = clamp (ac); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
MAKE_FUNC(s8, int8_t, S8_MIX);
|
||||
MAKE_FUNC(u8, uint8_t, U8_MIX);
|
||||
MAKE_FUNC(s16, int16_t, S16_MIX);
|
||||
MAKE_FUNC(u16, uint16_t, U16_MIX);
|
||||
MAKE_FUNC(s24, int24_t, S24_MIX);
|
||||
MAKE_FUNC(u24, uint24_t, U24_MIX);
|
||||
MAKE_FUNC(s32, int32_t, S32_MIX);
|
||||
MAKE_FUNC(u32, uint32_t, U32_MIX);
|
||||
MAKE_FUNC(s24_32, int32_t, S24_32_MIX);
|
||||
MAKE_FUNC(u24_32, uint32_t, U24_32_MIX);
|
||||
MAKE_FUNC(f32, float, F32_MIX);
|
||||
MAKE_FUNC(f64, double, F64_MIX);
|
||||
MAKE_FUNC(s8, int8_t, int16_t, S8_ACCUM, S8_CLAMP, true);
|
||||
MAKE_FUNC(u8, uint8_t, int16_t, U8_ACCUM, U8_CLAMP, false);
|
||||
MAKE_FUNC(s16, int16_t, int32_t, S16_ACCUM, S16_CLAMP, true);
|
||||
MAKE_FUNC(u16, uint16_t, int16_t, U16_ACCUM, U16_CLAMP, false);
|
||||
MAKE_FUNC(s24, int24_t, int32_t, S24_ACCUM, S24_CLAMP, false);
|
||||
MAKE_FUNC(u24, uint24_t, int32_t, U24_ACCUM, U24_CLAMP, false);
|
||||
MAKE_FUNC(s32, int32_t, int64_t, S32_ACCUM, S32_CLAMP, true);
|
||||
MAKE_FUNC(u32, uint32_t, int64_t, U32_ACCUM, U32_CLAMP, false);
|
||||
MAKE_FUNC(s24_32, int32_t, int32_t, S24_32_ACCUM, S24_32_CLAMP, true);
|
||||
MAKE_FUNC(u24_32, uint32_t, int32_t, U24_32_ACCUM, U24_32_CLAMP, false);
|
||||
MAKE_FUNC(f32, float, float, F32_ACCUM, F32_CLAMP, true);
|
||||
MAKE_FUNC(f64, double, double, F64_ACCUM, F64_CLAMP, true);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue