mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-01 22:58:50 -04:00
audiomixer: add support for more formats in the mix table
The S8, S16, S24 and S32 formats are now supported. The mixing process also takes into account the number of channels.
This commit is contained in:
parent
28cf342bb8
commit
dddbe289fb
3 changed files with 156 additions and 12 deletions
|
|
@ -30,6 +30,85 @@
|
|||
|
||||
#include "mix-ops.h"
|
||||
|
||||
void
|
||||
mix_s8_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;
|
||||
int8_t *d = dst;
|
||||
|
||||
if (n_src == 0)
|
||||
memset(dst, 0, n_samples * ops->n_channels * sizeof(int8_t));
|
||||
else if (dst != src[0])
|
||||
memcpy(dst, src[0], n_samples * ops->n_channels * sizeof(int8_t));
|
||||
|
||||
for (i = 1; i < n_src; i++) {
|
||||
const int8_t *s = src[i];
|
||||
for (n = 0; n < n_samples * ops->n_channels; n++)
|
||||
d[n] = S8_MIX(d[n], s[n]);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
mix_s16_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;
|
||||
int16_t *d = dst;
|
||||
|
||||
if (n_src == 0)
|
||||
memset(dst, 0, n_samples * ops->n_channels * sizeof(int16_t));
|
||||
else if (dst != src[0])
|
||||
memcpy(dst, src[0], n_samples * ops->n_channels * sizeof(int16_t));
|
||||
|
||||
for (i = 1; i < n_src; i++) {
|
||||
const int16_t *s = src[i];
|
||||
for (n = 0; n < n_samples * ops->n_channels; n++)
|
||||
d[n] = S16_MIX(d[n], s[n]);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
mix_s24_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;
|
||||
uint8_t *d = dst;
|
||||
|
||||
if (n_src == 0)
|
||||
memset(dst, 0, n_samples * ops->n_channels * sizeof(uint8_t) * 3);
|
||||
else if (dst != src[0])
|
||||
memcpy(dst, src[0], n_samples * ops->n_channels * sizeof(uint8_t) * 3);
|
||||
|
||||
for (i = 1; i < n_src; i++) {
|
||||
const uint8_t *s = src[i];
|
||||
for (n = 0; n < n_samples * ops->n_channels; n++) {
|
||||
write_s24(d, S24_MIX(read_s24(d), read_s24(s)));
|
||||
d += 3;
|
||||
s += 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
mix_s32_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;
|
||||
int32_t *d = dst;
|
||||
|
||||
if (n_src == 0)
|
||||
memset(dst, 0, n_samples * ops->n_channels * sizeof(int32_t));
|
||||
else if (dst != src[0])
|
||||
memcpy(dst, src[0], n_samples * ops->n_channels * sizeof(int32_t));
|
||||
|
||||
for (i = 1; i < n_src; i++) {
|
||||
const int32_t *s = src[i];
|
||||
for (n = 0; n < n_samples * ops->n_channels; n++)
|
||||
d[n] = S32_MIX(d[n], s[n]);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
mix_f32_c(struct mix_ops *ops, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src[],
|
||||
uint32_t n_src, uint32_t n_samples)
|
||||
|
|
@ -38,14 +117,14 @@ mix_f32_c(struct mix_ops *ops, void * SPA_RESTRICT dst, const void * SPA_RESTRIC
|
|||
float *d = dst;
|
||||
|
||||
if (n_src == 0)
|
||||
memset(dst, 0, n_samples * sizeof(float));
|
||||
memset(dst, 0, n_samples * ops->n_channels * sizeof(float));
|
||||
else if (dst != src[0])
|
||||
memcpy(dst, src[0], n_samples * sizeof(float));
|
||||
memcpy(dst, src[0], n_samples * ops->n_channels * sizeof(float));
|
||||
|
||||
for (i = 1; i < n_src; i++) {
|
||||
const float *s = src[i];
|
||||
for (n = 0; n < n_samples; n++)
|
||||
d[n] += s[n];
|
||||
for (n = 0; n < n_samples * ops->n_channels; n++)
|
||||
d[n] = F32_MIX(d[n], s[n]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -57,13 +136,13 @@ mix_f64_c(struct mix_ops *ops, void * SPA_RESTRICT dst, const void * SPA_RESTRIC
|
|||
double *d = dst;
|
||||
|
||||
if (n_src == 0)
|
||||
memset(dst, 0, n_samples * sizeof(double));
|
||||
memset(dst, 0, n_samples * ops->n_channels * sizeof(double));
|
||||
else if (dst != src[0])
|
||||
memcpy(dst, src[0], n_samples * sizeof(double));
|
||||
memcpy(dst, src[0], n_samples * ops->n_channels * sizeof(double));
|
||||
|
||||
for (i = 1; i < n_src; i++) {
|
||||
const double *s = src[i];
|
||||
for (n = 0; n < n_samples; n++)
|
||||
d[n] += s[n];
|
||||
for (n = 0; n < n_samples * ops->n_channels; n++)
|
||||
d[n] = F64_MIX(d[n], s[n]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,15 +54,32 @@ static struct mix_info mix_table[] =
|
|||
{ SPA_AUDIO_FORMAT_F32, 1, SPA_CPU_FLAG_SSE, 4, mix_f32_sse },
|
||||
{ SPA_AUDIO_FORMAT_F32P, 1, SPA_CPU_FLAG_SSE, 4, mix_f32_sse },
|
||||
#endif
|
||||
{ SPA_AUDIO_FORMAT_F32, 1, 0, 4, mix_f32_c },
|
||||
{ SPA_AUDIO_FORMAT_F32P, 1, 0, 4, mix_f32_c },
|
||||
{ SPA_AUDIO_FORMAT_F32, 0, 0, 4, mix_f32_c },
|
||||
{ SPA_AUDIO_FORMAT_F32P, 0, 0, 4, mix_f32_c },
|
||||
|
||||
/* f64 */
|
||||
#if defined (HAVE_SSE2)
|
||||
{ SPA_AUDIO_FORMAT_F64, 1, SPA_CPU_FLAG_SSE2, 8, mix_f64_sse2 },
|
||||
{ SPA_AUDIO_FORMAT_F64P, 1, SPA_CPU_FLAG_SSE2, 8, mix_f64_sse2 },
|
||||
#endif
|
||||
{ SPA_AUDIO_FORMAT_F64, 1, 0, 8, mix_f64_c },
|
||||
{ SPA_AUDIO_FORMAT_F64P, 1, 0, 8, mix_f64_c },
|
||||
{ SPA_AUDIO_FORMAT_F64, 0, 0, 8, mix_f64_c },
|
||||
{ SPA_AUDIO_FORMAT_F64P, 0, 0, 8, mix_f64_c },
|
||||
|
||||
/* s8 */
|
||||
{ SPA_AUDIO_FORMAT_S8, 0, 0, 1, mix_s8_c },
|
||||
{ SPA_AUDIO_FORMAT_S8P, 0, 0, 1, mix_s8_c },
|
||||
|
||||
/* s16 */
|
||||
{ SPA_AUDIO_FORMAT_S16, 0, 0, 2, mix_s16_c },
|
||||
{ SPA_AUDIO_FORMAT_S16P, 0, 0, 2, mix_s16_c },
|
||||
|
||||
/* s24 */
|
||||
{ SPA_AUDIO_FORMAT_S24, 0, 0, 3, mix_s24_c },
|
||||
{ SPA_AUDIO_FORMAT_S24P, 0, 0, 3, mix_s24_c },
|
||||
|
||||
/* s32 */
|
||||
{ SPA_AUDIO_FORMAT_S32, 0, 0, 4, mix_s32_c },
|
||||
{ SPA_AUDIO_FORMAT_S32P, 0, 0, 4, mix_s32_c },
|
||||
};
|
||||
|
||||
#define MATCH_CHAN(a,b) ((a) == 0 || (a) == (b))
|
||||
|
|
|
|||
|
|
@ -24,6 +24,50 @@
|
|||
|
||||
#include <spa/utils/defs.h>
|
||||
|
||||
static inline int32_t read_s24(const void *src)
|
||||
{
|
||||
const int8_t *s = src;
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
return (((int32_t)s[2] << 16) | ((uint32_t)(uint8_t)s[1] << 8) | (uint32_t)(uint8_t)s[0]);
|
||||
#else
|
||||
return (((int32_t)s[0] << 16) | ((uint32_t)(uint8_t)s[1] << 8) | (uint32_t)(uint8_t)s[2]);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void write_s24(void *dst, int32_t val)
|
||||
{
|
||||
uint8_t *d = dst;
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
d[0] = (uint8_t) (val);
|
||||
d[1] = (uint8_t) (val >> 8);
|
||||
d[2] = (uint8_t) (val >> 16);
|
||||
#else
|
||||
d[0] = (uint8_t) (val >> 16);
|
||||
d[1] = (uint8_t) (val >> 8);
|
||||
d[2] = (uint8_t) (val);
|
||||
#endif
|
||||
}
|
||||
|
||||
#define S8_MIN -127
|
||||
#define S8_MAX 127
|
||||
#define S8_MIX(a, b) (int8_t)(SPA_CLAMP((int16_t)(a) + (int16_t)(b), S8_MIN, S8_MAX))
|
||||
|
||||
#define S16_MIN -32767
|
||||
#define S16_MAX 32767
|
||||
#define S16_MIX(a, b) (int16_t)(SPA_CLAMP((int32_t)(a) + (int32_t)(b), S16_MIN, S16_MAX))
|
||||
|
||||
#define S24_MIN -8388607
|
||||
#define S24_MAX 8388607
|
||||
#define S24_MIX(a, b) (int32_t)(SPA_CLAMP((int32_t)(a) + (int32_t)(b), S24_MIN, S24_MAX))
|
||||
|
||||
#define S32_MIN -2147483647
|
||||
#define S32_MAX 2147483647
|
||||
#define S32_MIX(a, b) (int32_t)(SPA_CLAMP((int64_t)(a) + (int64_t)(b), S32_MIN, S32_MAX))
|
||||
|
||||
#define F32_MIX(a, b) (float)((float)(a) + (float)(b))
|
||||
|
||||
#define F64_MIX(a, b) (double)((double)(a) + (double)(b))
|
||||
|
||||
struct mix_ops {
|
||||
uint32_t fmt;
|
||||
uint32_t n_channels;
|
||||
|
|
@ -50,6 +94,10 @@ void mix_##name##_##arch(struct mix_ops *ops, void * SPA_RESTRICT dst, \
|
|||
const void * SPA_RESTRICT src[], uint32_t n_src, \
|
||||
uint32_t n_samples) \
|
||||
|
||||
DEFINE_FUNCTION(s8, c);
|
||||
DEFINE_FUNCTION(s16, c);
|
||||
DEFINE_FUNCTION(s24, c);
|
||||
DEFINE_FUNCTION(s32, c);
|
||||
DEFINE_FUNCTION(f32, c);
|
||||
DEFINE_FUNCTION(f64, c);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue