mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-10-29 05:40:27 -04:00
audioconvert: improve noise shaping
Reorganize things a little so we can add more noise shapers. Add sloped triangular noise. Add wanamaker3 noise shaping.
This commit is contained in:
parent
7151150802
commit
a4db745a7e
6 changed files with 272 additions and 171 deletions
|
|
@ -628,8 +628,8 @@ static int impl_node_enum_params(void *object, int seq,
|
||||||
param = spa_pod_builder_add_object(&b,
|
param = spa_pod_builder_add_object(&b,
|
||||||
SPA_TYPE_OBJECT_PropInfo, id,
|
SPA_TYPE_OBJECT_PropInfo, id,
|
||||||
SPA_PROP_INFO_name, SPA_POD_String("dither.noise"),
|
SPA_PROP_INFO_name, SPA_POD_String("dither.noise"),
|
||||||
SPA_PROP_INFO_description, SPA_POD_String("Add dithering noise"),
|
SPA_PROP_INFO_description, SPA_POD_String("Add noise bits"),
|
||||||
SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Int(this->dir[1].conv.noise, 0, 16),
|
SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Int(this->dir[1].conv.noise_bits, 0, 16),
|
||||||
SPA_PROP_INFO_params, SPA_POD_Bool(true));
|
SPA_PROP_INFO_params, SPA_POD_Bool(true));
|
||||||
break;
|
break;
|
||||||
case 23:
|
case 23:
|
||||||
|
|
|
||||||
|
|
@ -230,95 +230,104 @@ lcnoise(uint32_t *state)
|
||||||
return (int32_t)(*state);
|
return (int32_t)(*state);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void update_dither_c(struct convert *conv, uint32_t n_samples)
|
static inline void update_noise_c(struct convert *conv, uint32_t n_samples)
|
||||||
{
|
{
|
||||||
uint32_t n;
|
uint32_t n;
|
||||||
float *dither = conv->dither, scale = conv->scale;
|
float *noise = conv->noise, scale = conv->scale;
|
||||||
uint32_t *state = &conv->random[0];
|
uint32_t *state = &conv->random[0];
|
||||||
|
int32_t *prev = &conv->prev[0], old, new;
|
||||||
|
|
||||||
if (conv->method < DITHER_METHOD_TRIANGULAR) {
|
switch (conv->noise_method) {
|
||||||
|
case NOISE_METHOD_RECTANGULAR:
|
||||||
for (n = 0; n < n_samples; n++)
|
for (n = 0; n < n_samples; n++)
|
||||||
dither[n] = lcnoise(state) * scale;
|
noise[n] = lcnoise(state) * scale;
|
||||||
} else {
|
break;
|
||||||
|
case NOISE_METHOD_TRIANGULAR:
|
||||||
for (n = 0; n < n_samples; n++)
|
for (n = 0; n < n_samples; n++)
|
||||||
dither[n] = (lcnoise(state) + lcnoise(state)) * scale;
|
noise[n] = (lcnoise(state) - lcnoise(state)) * scale;
|
||||||
|
break;
|
||||||
|
case NOISE_METHOD_TRIANGULAR_HF:
|
||||||
|
old = *prev;
|
||||||
|
for (n = 0; n < n_samples; n++) {
|
||||||
|
new = lcnoise(state);
|
||||||
|
noise[n] = (new - old) * scale;
|
||||||
|
old = new;
|
||||||
|
}
|
||||||
|
*prev = old;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MAKE_D_dither(dname,dtype,func) \
|
#define MAKE_D_noise(dname,dtype,func) \
|
||||||
void conv_f32d_to_ ##dname## d_dither_c(struct convert *conv, \
|
void conv_f32d_to_ ##dname## d_noise_c(struct convert *conv, \
|
||||||
void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], \
|
void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], \
|
||||||
uint32_t n_samples) \
|
uint32_t n_samples) \
|
||||||
{ \
|
{ \
|
||||||
uint32_t i, j, k, chunk, n_channels = conv->n_channels, dither_size = conv->dither_size; \
|
uint32_t i, j, k, chunk, n_channels = conv->n_channels, noise_size = conv->noise_size; \
|
||||||
float *dither = conv->dither; \
|
float *noise = conv->noise; \
|
||||||
update_dither_c(conv, SPA_MIN(n_samples, dither_size)); \
|
update_noise_c(conv, SPA_MIN(n_samples, noise_size)); \
|
||||||
for (i = 0; i < n_channels; i++) { \
|
for (i = 0; i < n_channels; i++) { \
|
||||||
const float *s = src[i]; \
|
const float *s = src[i]; \
|
||||||
dtype *d = dst[i]; \
|
dtype *d = dst[i]; \
|
||||||
for (j = 0; j < n_samples;) { \
|
for (j = 0; j < n_samples;) { \
|
||||||
chunk = SPA_MIN(n_samples - j, dither_size); \
|
chunk = SPA_MIN(n_samples - j, noise_size); \
|
||||||
for (k = 0; k < chunk; k++, j++) \
|
for (k = 0; k < chunk; k++, j++) \
|
||||||
d[j] = func (s[j], dither[k]); \
|
d[j] = func (s[j], noise[k]); \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MAKE_I_dither(dname,dtype,func) \
|
#define MAKE_I_noise(dname,dtype,func) \
|
||||||
void conv_f32d_to_ ##dname## _dither_c(struct convert *conv, \
|
void conv_f32d_to_ ##dname## _noise_c(struct convert *conv, \
|
||||||
void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], \
|
void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], \
|
||||||
uint32_t n_samples) \
|
uint32_t n_samples) \
|
||||||
{ \
|
{ \
|
||||||
const float **s = (const float **) src; \
|
const float **s = (const float **) src; \
|
||||||
dtype *d = dst[0]; \
|
dtype *d = dst[0]; \
|
||||||
uint32_t i, j, k, chunk, n_channels = conv->n_channels, dither_size = conv->dither_size; \
|
uint32_t i, j, k, chunk, n_channels = conv->n_channels, noise_size = conv->noise_size; \
|
||||||
float *dither = conv->dither; \
|
float *noise = conv->noise; \
|
||||||
update_dither_c(conv, SPA_MIN(n_samples, dither_size)); \
|
update_noise_c(conv, SPA_MIN(n_samples, noise_size)); \
|
||||||
for (j = 0; j < n_samples;) { \
|
for (j = 0; j < n_samples;) { \
|
||||||
chunk = SPA_MIN(n_samples - j, dither_size); \
|
chunk = SPA_MIN(n_samples - j, noise_size); \
|
||||||
for (k = 0; k < chunk; k++, j++) { \
|
for (k = 0; k < chunk; k++, j++) { \
|
||||||
for (i = 0; i < n_channels; i++) \
|
for (i = 0; i < n_channels; i++) \
|
||||||
*d++ = func (s[i][j], dither[k]); \
|
*d++ = func (s[i][j], noise[k]); \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
MAKE_D_dither(u8, uint8_t, F32_TO_U8_D);
|
MAKE_D_noise(u8, uint8_t, F32_TO_U8_D);
|
||||||
MAKE_I_dither(u8, uint8_t, F32_TO_U8_D);
|
MAKE_I_noise(u8, uint8_t, F32_TO_U8_D);
|
||||||
MAKE_D_dither(s8, int8_t, F32_TO_S8_D);
|
MAKE_D_noise(s8, int8_t, F32_TO_S8_D);
|
||||||
MAKE_I_dither(s8, int8_t, F32_TO_S8_D);
|
MAKE_I_noise(s8, int8_t, F32_TO_S8_D);
|
||||||
MAKE_D_dither(s16, int16_t, F32_TO_S16_D);
|
MAKE_D_noise(s16, int16_t, F32_TO_S16_D);
|
||||||
MAKE_I_dither(s16, int16_t, F32_TO_S16_D);
|
MAKE_I_noise(s16, int16_t, F32_TO_S16_D);
|
||||||
MAKE_I_dither(s16s, uint16_t, F32_TO_S16S_D);
|
MAKE_I_noise(s16s, uint16_t, F32_TO_S16S_D);
|
||||||
MAKE_D_dither(s32, int32_t, F32_TO_S32_D);
|
MAKE_D_noise(s32, int32_t, F32_TO_S32_D);
|
||||||
MAKE_I_dither(s32, int32_t, F32_TO_S32_D);
|
MAKE_I_noise(s32, int32_t, F32_TO_S32_D);
|
||||||
MAKE_I_dither(s32s, uint32_t, F32_TO_S32S_D);
|
MAKE_I_noise(s32s, uint32_t, F32_TO_S32S_D);
|
||||||
MAKE_D_dither(s24, int24_t, F32_TO_S24_D);
|
MAKE_D_noise(s24, int24_t, F32_TO_S24_D);
|
||||||
MAKE_I_dither(s24, int24_t, F32_TO_S24_D);
|
MAKE_I_noise(s24, int24_t, F32_TO_S24_D);
|
||||||
MAKE_I_dither(s24s, int24_t, F32_TO_S24_D);
|
MAKE_I_noise(s24s, int24_t, F32_TO_S24_D);
|
||||||
MAKE_D_dither(s24_32, int32_t, F32_TO_S24_32_D);
|
MAKE_D_noise(s24_32, int32_t, F32_TO_S24_32_D);
|
||||||
MAKE_I_dither(s24_32, int32_t, F32_TO_S24_32_D);
|
MAKE_I_noise(s24_32, int32_t, F32_TO_S24_32_D);
|
||||||
MAKE_I_dither(s24_32s, int32_t, F32_TO_S24_32S_D);
|
MAKE_I_noise(s24_32s, int32_t, F32_TO_S24_32S_D);
|
||||||
|
|
||||||
|
#define SHAPER(type,s,scale,offs,sh,min,max,d) \
|
||||||
#define SHAPER5(type,s,scale,offs,sh,min,max,d) \
|
|
||||||
({ \
|
({ \
|
||||||
type t; \
|
type t; \
|
||||||
float v = s * scale + offs + \
|
float v = s * scale + offs; \
|
||||||
- sh->e[idx] * 2.033f \
|
for (n = 0; n < n_ns; n++) \
|
||||||
+ sh->e[(idx - 1) & NS_MASK] * 2.165f \
|
v += sh->e[idx + n] * ns[n]; \
|
||||||
- sh->e[(idx - 2) & NS_MASK] * 1.959f \
|
t = FTOI(type, v, 1.0f, 0.0f, d, min, max); \
|
||||||
+ sh->e[(idx - 3) & NS_MASK] * 1.590f \
|
idx = (idx - 1) & NS_MASK; \
|
||||||
- sh->e[(idx - 4) & NS_MASK] * 0.6149f; \
|
sh->e[idx] = sh->e[idx + NS_MAX] = v - t; \
|
||||||
t = (type)SPA_CLAMP(v + d, min, max); \
|
|
||||||
idx = (idx + 1) & NS_MASK; \
|
|
||||||
sh->e[idx] = t - v; \
|
|
||||||
t; \
|
t; \
|
||||||
})
|
})
|
||||||
|
|
||||||
#define F32_TO_U8_SH(s,sh,d) SHAPER5(uint8_t, s, U8_SCALE, U8_OFFS, sh, U8_MIN, U8_MAX, d)
|
#define F32_TO_U8_SH(s,sh,d) SHAPER(uint8_t, s, U8_SCALE, U8_OFFS, sh, U8_MIN, U8_MAX, d)
|
||||||
#define F32_TO_S8_SH(s,sh,d) SHAPER5(int8_t, s, S8_SCALE, 0, sh, S8_MIN, S8_MAX, d)
|
#define F32_TO_S8_SH(s,sh,d) SHAPER(int8_t, s, S8_SCALE, 0, sh, S8_MIN, S8_MAX, d)
|
||||||
#define F32_TO_S16_SH(s,sh,d) SHAPER5(int16_t, s, S16_SCALE, 0, sh, S16_MIN, S16_MAX, d)
|
#define F32_TO_S16_SH(s,sh,d) SHAPER(int16_t, s, S16_SCALE, 0, sh, S16_MIN, S16_MAX, d)
|
||||||
#define F32_TO_S16S_SH(s,sh,d) bswap_16(F32_TO_S16_SH(s,sh,d))
|
#define F32_TO_S16S_SH(s,sh,d) bswap_16(F32_TO_S16_SH(s,sh,d))
|
||||||
|
|
||||||
#define MAKE_D_shaped(dname,dtype,func) \
|
#define MAKE_D_shaped(dname,dtype,func) \
|
||||||
|
|
@ -326,18 +335,19 @@ void conv_f32d_to_ ##dname## d_shaped_c(struct convert *conv, \
|
||||||
void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], \
|
void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], \
|
||||||
uint32_t n_samples) \
|
uint32_t n_samples) \
|
||||||
{ \
|
{ \
|
||||||
uint32_t i, j, k, chunk, n_channels = conv->n_channels, dither_size = conv->dither_size; \
|
uint32_t i, j, k, chunk, n_channels = conv->n_channels, noise_size = conv->noise_size; \
|
||||||
float *dither = conv->dither; \
|
const float *noise = conv->noise, *ns = conv->ns; \
|
||||||
update_dither_c(conv, SPA_MIN(n_samples, dither_size)); \
|
uint32_t n, n_ns = conv->n_ns; \
|
||||||
|
update_noise_c(conv, SPA_MIN(n_samples, noise_size)); \
|
||||||
for (i = 0; i < n_channels; i++) { \
|
for (i = 0; i < n_channels; i++) { \
|
||||||
const float *s = src[i]; \
|
const float *s = src[i]; \
|
||||||
dtype *d = dst[i]; \
|
dtype *d = dst[i]; \
|
||||||
struct shaper *sh = &conv->shaper[i]; \
|
struct shaper *sh = &conv->shaper[i]; \
|
||||||
uint32_t idx = sh->idx; \
|
uint32_t idx = sh->idx; \
|
||||||
for (j = 0; j < n_samples;) { \
|
for (j = 0; j < n_samples;) { \
|
||||||
chunk = SPA_MIN(n_samples - j, dither_size); \
|
chunk = SPA_MIN(n_samples - j, noise_size); \
|
||||||
for (k = 0; k < chunk; k++, j++) \
|
for (k = 0; k < chunk; k++, j++) \
|
||||||
d[j] = func (s[j], sh, dither[k]); \
|
d[j] = func (s[j], sh, noise[k]); \
|
||||||
} \
|
} \
|
||||||
sh->idx = idx; \
|
sh->idx = idx; \
|
||||||
} \
|
} \
|
||||||
|
|
@ -349,18 +359,19 @@ void conv_f32d_to_ ##dname## _shaped_c(struct convert *conv, \
|
||||||
uint32_t n_samples) \
|
uint32_t n_samples) \
|
||||||
{ \
|
{ \
|
||||||
dtype *d0 = dst[0]; \
|
dtype *d0 = dst[0]; \
|
||||||
uint32_t i, j, k, chunk, n_channels = conv->n_channels, dither_size = conv->dither_size; \
|
uint32_t i, j, k, chunk, n_channels = conv->n_channels, noise_size = conv->noise_size; \
|
||||||
float *dither = conv->dither; \
|
const float *noise = conv->noise, *ns = conv->ns; \
|
||||||
update_dither_c(conv, SPA_MIN(n_samples, dither_size)); \
|
uint32_t n, n_ns = conv->n_ns; \
|
||||||
|
update_noise_c(conv, SPA_MIN(n_samples, noise_size)); \
|
||||||
for (i = 0; i < n_channels; i++) { \
|
for (i = 0; i < n_channels; i++) { \
|
||||||
const float *s = src[i]; \
|
const float *s = src[i]; \
|
||||||
dtype *d = &d0[i]; \
|
dtype *d = &d0[i]; \
|
||||||
struct shaper *sh = &conv->shaper[i]; \
|
struct shaper *sh = &conv->shaper[i]; \
|
||||||
uint32_t idx = sh->idx; \
|
uint32_t idx = sh->idx; \
|
||||||
for (j = 0; j < n_samples;) { \
|
for (j = 0; j < n_samples;) { \
|
||||||
chunk = SPA_MIN(n_samples - j, dither_size); \
|
chunk = SPA_MIN(n_samples - j, noise_size); \
|
||||||
for (k = 0; k < chunk; k++, j++) \
|
for (k = 0; k < chunk; k++, j++) \
|
||||||
d[j*n_channels] = func (s[j], sh, dither[k]); \
|
d[j*n_channels] = func (s[j], sh, noise[k]); \
|
||||||
} \
|
} \
|
||||||
sh->idx = idx; \
|
sh->idx = idx; \
|
||||||
} \
|
} \
|
||||||
|
|
|
||||||
|
|
@ -577,38 +577,54 @@ conv_f32d_to_s32_sse2(struct convert *conv, void * SPA_RESTRICT dst[], const voi
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
static inline void update_dither_sse2(struct convert *conv, uint32_t n_samples)
|
static inline void update_noise_sse2(struct convert *conv, uint32_t n_samples)
|
||||||
{
|
{
|
||||||
uint32_t n;
|
uint32_t n;
|
||||||
const uint32_t *r = SPA_PTR_ALIGN(conv->random, 16, uint32_t);
|
const uint32_t *r = SPA_PTR_ALIGN(conv->random, 16, uint32_t);
|
||||||
|
const int32_t *p = SPA_PTR_ALIGN(conv->prev, 16, int32_t);
|
||||||
__m128 scale = _mm_set1_ps(conv->scale);
|
__m128 scale = _mm_set1_ps(conv->scale);
|
||||||
__m128 out[1];
|
__m128 out[1];
|
||||||
float *dither = SPA_PTR_ALIGN(conv->dither, 16, float);
|
float *noise = SPA_PTR_ALIGN(conv->noise, 16, float);
|
||||||
__m128i in[2];
|
__m128i in[1], old[1], new[1];
|
||||||
|
|
||||||
if (conv->method < DITHER_METHOD_TRIANGULAR) {
|
switch (conv->noise_method) {
|
||||||
|
case DITHER_METHOD_RECTANGULAR:
|
||||||
for (n = 0; n < n_samples; n += 4) {
|
for (n = 0; n < n_samples; n += 4) {
|
||||||
in[0] = _MM_XORSHIFT_EPI32(r);
|
in[0] = _MM_XORSHIFT_EPI32(r);
|
||||||
out[0] = _mm_cvtepi32_ps(_MM_XORSHIFT_EPI32(r));
|
out[0] = _mm_cvtepi32_ps(_MM_XORSHIFT_EPI32(r));
|
||||||
out[0] = _mm_mul_ps(out[0], scale);
|
out[0] = _mm_mul_ps(out[0], scale);
|
||||||
_mm_store_ps(&dither[n], out[0]);
|
_mm_store_ps(&noise[n], out[0]);
|
||||||
}
|
}
|
||||||
} else {
|
break;
|
||||||
|
case DITHER_METHOD_TRIANGULAR:
|
||||||
for (n = 0; n < n_samples; n += 4) {
|
for (n = 0; n < n_samples; n += 4) {
|
||||||
in[0] = _mm_add_epi32( _MM_XORSHIFT_EPI32(r), _MM_XORSHIFT_EPI32(r));
|
in[0] = _mm_sub_epi32( _MM_XORSHIFT_EPI32(r), _MM_XORSHIFT_EPI32(r));
|
||||||
out[0] = _mm_cvtepi32_ps(in[0]);
|
out[0] = _mm_cvtepi32_ps(in[0]);
|
||||||
out[0] = _mm_mul_ps(out[0], scale);
|
out[0] = _mm_mul_ps(out[0], scale);
|
||||||
_mm_store_ps(&dither[n], out[0]);
|
_mm_store_ps(&noise[n], out[0]);
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
case DITHER_METHOD_TRIANGULAR_HF:
|
||||||
|
old[0] = _mm_load_si128((__m128i*)p);
|
||||||
|
for (n = 0; n < n_samples; n += 4) {
|
||||||
|
new[0] = _MM_XORSHIFT_EPI32(r);
|
||||||
|
in[0] = _mm_sub_epi32(old[0], new[0]);
|
||||||
|
old[0] = new[0];
|
||||||
|
out[0] = _mm_cvtepi32_ps(in[0]);
|
||||||
|
out[0] = _mm_mul_ps(out[0], scale);
|
||||||
|
_mm_store_ps(&noise[n], out[0]);
|
||||||
|
}
|
||||||
|
_mm_store_si128((__m128i*)p, old[0]);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
conv_f32d_to_s32_1s_dither_sse2(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src,
|
conv_f32d_to_s32_1s_noise_sse2(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src,
|
||||||
uint32_t n_channels, uint32_t n_samples)
|
uint32_t n_channels, uint32_t n_samples)
|
||||||
{
|
{
|
||||||
const float *s = src;
|
const float *s = src;
|
||||||
float *dither = SPA_PTR_ALIGN(conv->dither, 16, float);
|
float *noise = SPA_PTR_ALIGN(conv->noise, 16, float);
|
||||||
int32_t *d = dst;
|
int32_t *d = dst;
|
||||||
uint32_t n, unrolled;
|
uint32_t n, unrolled;
|
||||||
__m128 in[1];
|
__m128 in[1];
|
||||||
|
|
@ -624,7 +640,7 @@ conv_f32d_to_s32_1s_dither_sse2(struct convert *conv, void * SPA_RESTRICT dst, c
|
||||||
|
|
||||||
for(n = 0; n < unrolled; n += 4) {
|
for(n = 0; n < unrolled; n += 4) {
|
||||||
in[0] = _mm_mul_ps(_mm_load_ps(&s[n]), scale);
|
in[0] = _mm_mul_ps(_mm_load_ps(&s[n]), scale);
|
||||||
in[0] = _mm_add_ps(in[0], _mm_load_ps(&dither[n]));
|
in[0] = _mm_add_ps(in[0], _mm_load_ps(&noise[n]));
|
||||||
in[0] = _MM_CLAMP_PS(in[0], int_min, int_max);
|
in[0] = _MM_CLAMP_PS(in[0], int_min, int_max);
|
||||||
out[0] = _mm_cvtps_epi32(in[0]);
|
out[0] = _mm_cvtps_epi32(in[0]);
|
||||||
out[0] = _mm_slli_epi32(out[0], 8);
|
out[0] = _mm_slli_epi32(out[0], 8);
|
||||||
|
|
@ -641,7 +657,7 @@ conv_f32d_to_s32_1s_dither_sse2(struct convert *conv, void * SPA_RESTRICT dst, c
|
||||||
for(; n < n_samples; n++) {
|
for(; n < n_samples; n++) {
|
||||||
in[0] = _mm_load_ss(&s[n]);
|
in[0] = _mm_load_ss(&s[n]);
|
||||||
in[0] = _mm_mul_ss(in[0], scale);
|
in[0] = _mm_mul_ss(in[0], scale);
|
||||||
in[0] = _mm_add_ss(in[0], _mm_load_ss(&dither[n]));
|
in[0] = _mm_add_ss(in[0], _mm_load_ss(&noise[n]));
|
||||||
in[0] = _MM_CLAMP_SS(in[0], int_min, int_max);
|
in[0] = _MM_CLAMP_SS(in[0], int_min, int_max);
|
||||||
*d = _mm_cvtss_si32(in[0]) << 8;
|
*d = _mm_cvtss_si32(in[0]) << 8;
|
||||||
d += n_channels;
|
d += n_channels;
|
||||||
|
|
@ -649,19 +665,19 @@ conv_f32d_to_s32_1s_dither_sse2(struct convert *conv, void * SPA_RESTRICT dst, c
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
conv_f32d_to_s32_dither_sse2(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[],
|
conv_f32d_to_s32_noise_sse2(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[],
|
||||||
uint32_t n_samples)
|
uint32_t n_samples)
|
||||||
{
|
{
|
||||||
int32_t *d = dst[0];
|
int32_t *d = dst[0];
|
||||||
uint32_t i, k, chunk, n_channels = conv->n_channels;
|
uint32_t i, k, chunk, n_channels = conv->n_channels;
|
||||||
|
|
||||||
update_dither_sse2(conv, SPA_MIN(n_samples, conv->dither_size));
|
update_noise_sse2(conv, SPA_MIN(n_samples, conv->noise_size));
|
||||||
|
|
||||||
for(i = 0; i < n_channels; i++) {
|
for(i = 0; i < n_channels; i++) {
|
||||||
const float *s = src[i];
|
const float *s = src[i];
|
||||||
for(k = 0; k < n_samples; k += chunk) {
|
for(k = 0; k < n_samples; k += chunk) {
|
||||||
chunk = SPA_MIN(n_samples - k, conv->dither_size);
|
chunk = SPA_MIN(n_samples - k, conv->noise_size);
|
||||||
conv_f32d_to_s32_1s_dither_sse2(conv, &d[i + k*n_channels], &s[k], n_channels, chunk);
|
conv_f32d_to_s32_1s_noise_sse2(conv, &d[i + k*n_channels], &s[k], n_channels, chunk);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1238,12 +1254,12 @@ conv_f32d_to_s16_sse2(struct convert *conv, void * SPA_RESTRICT dst[], const voi
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
conv_f32d_to_s16_1s_dither_sse2(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src,
|
conv_f32d_to_s16_1s_noise_sse2(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src,
|
||||||
uint32_t n_channels, uint32_t n_samples)
|
uint32_t n_channels, uint32_t n_samples)
|
||||||
{
|
{
|
||||||
const float *s0 = src;
|
const float *s0 = src;
|
||||||
int16_t *d = dst;
|
int16_t *d = dst;
|
||||||
float *dither = SPA_PTR_ALIGN(conv->dither, 16, float);
|
float *noise = SPA_PTR_ALIGN(conv->noise, 16, float);
|
||||||
uint32_t n, unrolled;
|
uint32_t n, unrolled;
|
||||||
__m128 in[2];
|
__m128 in[2];
|
||||||
__m128i out[2];
|
__m128i out[2];
|
||||||
|
|
@ -1259,8 +1275,8 @@ conv_f32d_to_s16_1s_dither_sse2(struct convert *conv, void * SPA_RESTRICT dst, c
|
||||||
for(n = 0; n < unrolled; n += 8) {
|
for(n = 0; n < unrolled; n += 8) {
|
||||||
in[0] = _mm_mul_ps(_mm_load_ps(&s0[n]), int_scale);
|
in[0] = _mm_mul_ps(_mm_load_ps(&s0[n]), int_scale);
|
||||||
in[1] = _mm_mul_ps(_mm_load_ps(&s0[n+4]), int_scale);
|
in[1] = _mm_mul_ps(_mm_load_ps(&s0[n+4]), int_scale);
|
||||||
in[0] = _mm_add_ps(in[0], _mm_load_ps(&dither[n]));
|
in[0] = _mm_add_ps(in[0], _mm_load_ps(&noise[n]));
|
||||||
in[1] = _mm_add_ps(in[1], _mm_load_ps(&dither[n+4]));
|
in[1] = _mm_add_ps(in[1], _mm_load_ps(&noise[n+4]));
|
||||||
out[0] = _mm_cvtps_epi32(in[0]);
|
out[0] = _mm_cvtps_epi32(in[0]);
|
||||||
out[1] = _mm_cvtps_epi32(in[1]);
|
out[1] = _mm_cvtps_epi32(in[1]);
|
||||||
out[0] = _mm_packs_epi32(out[0], out[1]);
|
out[0] = _mm_packs_epi32(out[0], out[1]);
|
||||||
|
|
@ -1277,7 +1293,7 @@ conv_f32d_to_s16_1s_dither_sse2(struct convert *conv, void * SPA_RESTRICT dst, c
|
||||||
}
|
}
|
||||||
for(; n < n_samples; n++) {
|
for(; n < n_samples; n++) {
|
||||||
in[0] = _mm_mul_ss(_mm_load_ss(&s0[n]), int_scale);
|
in[0] = _mm_mul_ss(_mm_load_ss(&s0[n]), int_scale);
|
||||||
in[0] = _mm_add_ss(in[0], _mm_load_ss(&dither[n]));
|
in[0] = _mm_add_ss(in[0], _mm_load_ss(&noise[n]));
|
||||||
in[0] = _MM_CLAMP_SS(in[0], int_min, int_max);
|
in[0] = _MM_CLAMP_SS(in[0], int_min, int_max);
|
||||||
*d = _mm_cvtss_si32(in[0]);
|
*d = _mm_cvtss_si32(in[0]);
|
||||||
d += n_channels;
|
d += n_channels;
|
||||||
|
|
@ -1285,30 +1301,30 @@ conv_f32d_to_s16_1s_dither_sse2(struct convert *conv, void * SPA_RESTRICT dst, c
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
conv_f32d_to_s16_dither_sse2(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[],
|
conv_f32d_to_s16_noise_sse2(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[],
|
||||||
uint32_t n_samples)
|
uint32_t n_samples)
|
||||||
{
|
{
|
||||||
int16_t *d = dst[0];
|
int16_t *d = dst[0];
|
||||||
uint32_t i, k, chunk, n_channels = conv->n_channels;
|
uint32_t i, k, chunk, n_channels = conv->n_channels;
|
||||||
|
|
||||||
update_dither_sse2(conv, SPA_MIN(n_samples, conv->dither_size));
|
update_noise_sse2(conv, SPA_MIN(n_samples, conv->noise_size));
|
||||||
|
|
||||||
for(i = 0; i < n_channels; i++) {
|
for(i = 0; i < n_channels; i++) {
|
||||||
const float *s = src[i];
|
const float *s = src[i];
|
||||||
for(k = 0; k < n_samples; k += chunk) {
|
for(k = 0; k < n_samples; k += chunk) {
|
||||||
chunk = SPA_MIN(n_samples - k, conv->dither_size);
|
chunk = SPA_MIN(n_samples - k, conv->noise_size);
|
||||||
conv_f32d_to_s16_1s_dither_sse2(conv, &d[i + k*n_channels], &s[k], n_channels, chunk);
|
conv_f32d_to_s16_1s_noise_sse2(conv, &d[i + k*n_channels], &s[k], n_channels, chunk);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
conv_f32_to_s16_1_dither_sse2(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src,
|
conv_f32_to_s16_1_noise_sse2(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src,
|
||||||
uint32_t n_samples)
|
uint32_t n_samples)
|
||||||
{
|
{
|
||||||
const float *s = src;
|
const float *s = src;
|
||||||
int16_t *d = dst;
|
int16_t *d = dst;
|
||||||
float *dither = SPA_PTR_ALIGN(conv->dither, 16, float);
|
float *noise = SPA_PTR_ALIGN(conv->noise, 16, float);
|
||||||
uint32_t n, unrolled;
|
uint32_t n, unrolled;
|
||||||
__m128 in[2];
|
__m128 in[2];
|
||||||
__m128i out[2];
|
__m128i out[2];
|
||||||
|
|
@ -1324,8 +1340,8 @@ conv_f32_to_s16_1_dither_sse2(struct convert *conv, void * SPA_RESTRICT dst, con
|
||||||
for(n = 0; n < unrolled; n += 8) {
|
for(n = 0; n < unrolled; n += 8) {
|
||||||
in[0] = _mm_mul_ps(_mm_load_ps(&s[n]), int_scale);
|
in[0] = _mm_mul_ps(_mm_load_ps(&s[n]), int_scale);
|
||||||
in[1] = _mm_mul_ps(_mm_load_ps(&s[n+4]), int_scale);
|
in[1] = _mm_mul_ps(_mm_load_ps(&s[n+4]), int_scale);
|
||||||
in[0] = _mm_add_ps(in[0], _mm_load_ps(&dither[n]));
|
in[0] = _mm_add_ps(in[0], _mm_load_ps(&noise[n]));
|
||||||
in[1] = _mm_add_ps(in[1], _mm_load_ps(&dither[n+4]));
|
in[1] = _mm_add_ps(in[1], _mm_load_ps(&noise[n+4]));
|
||||||
out[0] = _mm_cvtps_epi32(in[0]);
|
out[0] = _mm_cvtps_epi32(in[0]);
|
||||||
out[1] = _mm_cvtps_epi32(in[1]);
|
out[1] = _mm_cvtps_epi32(in[1]);
|
||||||
out[0] = _mm_packs_epi32(out[0], out[1]);
|
out[0] = _mm_packs_epi32(out[0], out[1]);
|
||||||
|
|
@ -1333,26 +1349,26 @@ conv_f32_to_s16_1_dither_sse2(struct convert *conv, void * SPA_RESTRICT dst, con
|
||||||
}
|
}
|
||||||
for(; n < n_samples; n++) {
|
for(; n < n_samples; n++) {
|
||||||
in[0] = _mm_mul_ss(_mm_load_ss(&s[n]), int_scale);
|
in[0] = _mm_mul_ss(_mm_load_ss(&s[n]), int_scale);
|
||||||
in[0] = _mm_add_ss(in[0], _mm_load_ss(&dither[n]));
|
in[0] = _mm_add_ss(in[0], _mm_load_ss(&noise[n]));
|
||||||
in[0] = _MM_CLAMP_SS(in[0], int_min, int_max);
|
in[0] = _MM_CLAMP_SS(in[0], int_min, int_max);
|
||||||
d[n] = _mm_cvtss_si32(in[0]);
|
d[n] = _mm_cvtss_si32(in[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
conv_f32d_to_s16d_dither_sse2(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[],
|
conv_f32d_to_s16d_noise_sse2(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[],
|
||||||
uint32_t n_samples)
|
uint32_t n_samples)
|
||||||
{
|
{
|
||||||
uint32_t i, k, chunk, n_channels = conv->n_channels;
|
uint32_t i, k, chunk, n_channels = conv->n_channels;
|
||||||
|
|
||||||
update_dither_sse2(conv, SPA_MIN(n_samples, conv->dither_size));
|
update_noise_sse2(conv, SPA_MIN(n_samples, conv->noise_size));
|
||||||
|
|
||||||
for(i = 0; i < n_channels; i++) {
|
for(i = 0; i < n_channels; i++) {
|
||||||
const float *s = src[i];
|
const float *s = src[i];
|
||||||
int16_t *d = dst[i];
|
int16_t *d = dst[i];
|
||||||
for(k = 0; k < n_samples; k += chunk) {
|
for(k = 0; k < n_samples; k += chunk) {
|
||||||
chunk = SPA_MIN(n_samples - k, conv->dither_size);
|
chunk = SPA_MIN(n_samples - k, conv->noise_size);
|
||||||
conv_f32_to_s16_1_dither_sse2(conv, &d[k], &s[k], chunk);
|
conv_f32_to_s16_1_noise_sse2(conv, &d[k], &s[k], chunk);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -46,9 +46,9 @@ struct conv_info {
|
||||||
const char *name;
|
const char *name;
|
||||||
|
|
||||||
uint32_t cpu_flags;
|
uint32_t cpu_flags;
|
||||||
#define CONV_DITHER (1<<0)
|
#define CONV_NOISE (1<<0)
|
||||||
#define CONV_SHAPE (1<<1)
|
#define CONV_SHAPE (1<<1)
|
||||||
uint32_t dither_flags;
|
uint32_t conv_flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MAKE(fmt1,fmt2,chan,func,...) \
|
#define MAKE(fmt1,fmt2,chan,func,...) \
|
||||||
|
|
@ -171,20 +171,20 @@ static struct conv_info conv_table[] =
|
||||||
/* from f32 */
|
/* from f32 */
|
||||||
MAKE(F32, U8, 0, conv_f32_to_u8_c),
|
MAKE(F32, U8, 0, conv_f32_to_u8_c),
|
||||||
MAKE(F32P, U8P, 0, conv_f32d_to_u8d_shaped_c, 0, CONV_SHAPE),
|
MAKE(F32P, U8P, 0, conv_f32d_to_u8d_shaped_c, 0, CONV_SHAPE),
|
||||||
MAKE(F32P, U8P, 0, conv_f32d_to_u8d_dither_c, 0, CONV_DITHER),
|
MAKE(F32P, U8P, 0, conv_f32d_to_u8d_noise_c, 0, CONV_NOISE),
|
||||||
MAKE(F32P, U8P, 0, conv_f32d_to_u8d_c),
|
MAKE(F32P, U8P, 0, conv_f32d_to_u8d_c),
|
||||||
MAKE(F32, U8P, 0, conv_f32_to_u8d_c),
|
MAKE(F32, U8P, 0, conv_f32_to_u8d_c),
|
||||||
MAKE(F32P, U8, 0, conv_f32d_to_u8_shaped_c, 0, CONV_SHAPE),
|
MAKE(F32P, U8, 0, conv_f32d_to_u8_shaped_c, 0, CONV_SHAPE),
|
||||||
MAKE(F32P, U8, 0, conv_f32d_to_u8_dither_c, 0, CONV_DITHER),
|
MAKE(F32P, U8, 0, conv_f32d_to_u8_noise_c, 0, CONV_NOISE),
|
||||||
MAKE(F32P, U8, 0, conv_f32d_to_u8_c),
|
MAKE(F32P, U8, 0, conv_f32d_to_u8_c),
|
||||||
|
|
||||||
MAKE(F32, S8, 0, conv_f32_to_s8_c),
|
MAKE(F32, S8, 0, conv_f32_to_s8_c),
|
||||||
MAKE(F32P, S8P, 0, conv_f32d_to_s8d_shaped_c, 0, CONV_SHAPE),
|
MAKE(F32P, S8P, 0, conv_f32d_to_s8d_shaped_c, 0, CONV_SHAPE),
|
||||||
MAKE(F32P, S8P, 0, conv_f32d_to_s8d_dither_c, 0, CONV_DITHER),
|
MAKE(F32P, S8P, 0, conv_f32d_to_s8d_noise_c, 0, CONV_NOISE),
|
||||||
MAKE(F32P, S8P, 0, conv_f32d_to_s8d_c),
|
MAKE(F32P, S8P, 0, conv_f32d_to_s8d_c),
|
||||||
MAKE(F32, S8P, 0, conv_f32_to_s8d_c),
|
MAKE(F32, S8P, 0, conv_f32_to_s8d_c),
|
||||||
MAKE(F32P, S8, 0, conv_f32d_to_s8_shaped_c, 0, CONV_SHAPE),
|
MAKE(F32P, S8, 0, conv_f32d_to_s8_shaped_c, 0, CONV_SHAPE),
|
||||||
MAKE(F32P, S8, 0, conv_f32d_to_s8_dither_c, 0, CONV_DITHER),
|
MAKE(F32P, S8, 0, conv_f32d_to_s8_noise_c, 0, CONV_NOISE),
|
||||||
MAKE(F32P, S8, 0, conv_f32d_to_s8_c),
|
MAKE(F32P, S8, 0, conv_f32d_to_s8_c),
|
||||||
|
|
||||||
MAKE(F32P, ALAW, 0, conv_f32d_to_alaw_c),
|
MAKE(F32P, ALAW, 0, conv_f32d_to_alaw_c),
|
||||||
|
|
@ -200,9 +200,9 @@ static struct conv_info conv_table[] =
|
||||||
|
|
||||||
MAKE(F32P, S16P, 0, conv_f32d_to_s16d_shaped_c, 0, CONV_SHAPE),
|
MAKE(F32P, S16P, 0, conv_f32d_to_s16d_shaped_c, 0, CONV_SHAPE),
|
||||||
#if defined (HAVE_SSE2)
|
#if defined (HAVE_SSE2)
|
||||||
MAKE(F32P, S16P, 0, conv_f32d_to_s16d_dither_sse2, SPA_CPU_FLAG_SSE2, CONV_DITHER),
|
MAKE(F32P, S16P, 0, conv_f32d_to_s16d_noise_sse2, SPA_CPU_FLAG_SSE2, CONV_NOISE),
|
||||||
#endif
|
#endif
|
||||||
MAKE(F32P, S16P, 0, conv_f32d_to_s16d_dither_c, 0, CONV_DITHER),
|
MAKE(F32P, S16P, 0, conv_f32d_to_s16d_noise_c, 0, CONV_NOISE),
|
||||||
#if defined (HAVE_SSE2)
|
#if defined (HAVE_SSE2)
|
||||||
MAKE(F32P, S16P, 0, conv_f32d_to_s16d_sse2, SPA_CPU_FLAG_SSE2),
|
MAKE(F32P, S16P, 0, conv_f32d_to_s16d_sse2, SPA_CPU_FLAG_SSE2),
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -212,9 +212,9 @@ static struct conv_info conv_table[] =
|
||||||
|
|
||||||
MAKE(F32P, S16, 0, conv_f32d_to_s16_shaped_c, 0, CONV_SHAPE),
|
MAKE(F32P, S16, 0, conv_f32d_to_s16_shaped_c, 0, CONV_SHAPE),
|
||||||
#if defined (HAVE_SSE2)
|
#if defined (HAVE_SSE2)
|
||||||
MAKE(F32P, S16, 0, conv_f32d_to_s16_dither_sse2, SPA_CPU_FLAG_SSE2, CONV_DITHER),
|
MAKE(F32P, S16, 0, conv_f32d_to_s16_noise_sse2, SPA_CPU_FLAG_SSE2, CONV_NOISE),
|
||||||
#endif
|
#endif
|
||||||
MAKE(F32P, S16, 0, conv_f32d_to_s16_dither_c, 0, CONV_DITHER),
|
MAKE(F32P, S16, 0, conv_f32d_to_s16_noise_c, 0, CONV_NOISE),
|
||||||
#if defined (HAVE_NEON)
|
#if defined (HAVE_NEON)
|
||||||
MAKE(F32P, S16, 0, conv_f32d_to_s16_neon, SPA_CPU_FLAG_NEON),
|
MAKE(F32P, S16, 0, conv_f32d_to_s16_neon, SPA_CPU_FLAG_NEON),
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -230,21 +230,21 @@ static struct conv_info conv_table[] =
|
||||||
MAKE(F32P, S16, 0, conv_f32d_to_s16_c),
|
MAKE(F32P, S16, 0, conv_f32d_to_s16_c),
|
||||||
|
|
||||||
MAKE(F32P, S16_OE, 0, conv_f32d_to_s16s_shaped_c, 0, CONV_SHAPE),
|
MAKE(F32P, S16_OE, 0, conv_f32d_to_s16s_shaped_c, 0, CONV_SHAPE),
|
||||||
MAKE(F32P, S16_OE, 0, conv_f32d_to_s16s_dither_c, 0, CONV_DITHER),
|
MAKE(F32P, S16_OE, 0, conv_f32d_to_s16s_noise_c, 0, CONV_NOISE),
|
||||||
MAKE(F32P, S16_OE, 0, conv_f32d_to_s16s_c),
|
MAKE(F32P, S16_OE, 0, conv_f32d_to_s16s_c),
|
||||||
|
|
||||||
MAKE(F32, U32, 0, conv_f32_to_u32_c),
|
MAKE(F32, U32, 0, conv_f32_to_u32_c),
|
||||||
MAKE(F32P, U32, 0, conv_f32d_to_u32_c),
|
MAKE(F32P, U32, 0, conv_f32d_to_u32_c),
|
||||||
|
|
||||||
MAKE(F32, S32, 0, conv_f32_to_s32_c),
|
MAKE(F32, S32, 0, conv_f32_to_s32_c),
|
||||||
MAKE(F32P, S32P, 0, conv_f32d_to_s32d_dither_c, 0, CONV_DITHER),
|
MAKE(F32P, S32P, 0, conv_f32d_to_s32d_noise_c, 0, CONV_NOISE),
|
||||||
MAKE(F32P, S32P, 0, conv_f32d_to_s32d_c),
|
MAKE(F32P, S32P, 0, conv_f32d_to_s32d_c),
|
||||||
MAKE(F32, S32P, 0, conv_f32_to_s32d_c),
|
MAKE(F32, S32P, 0, conv_f32_to_s32d_c),
|
||||||
|
|
||||||
#if defined (HAVE_SSE2)
|
#if defined (HAVE_SSE2)
|
||||||
MAKE(F32P, S32, 0, conv_f32d_to_s32_dither_sse2, SPA_CPU_FLAG_SSE2, CONV_DITHER),
|
MAKE(F32P, S32, 0, conv_f32d_to_s32_noise_sse2, SPA_CPU_FLAG_SSE2, CONV_NOISE),
|
||||||
#endif
|
#endif
|
||||||
MAKE(F32P, S32, 0, conv_f32d_to_s32_dither_c, 0, CONV_DITHER),
|
MAKE(F32P, S32, 0, conv_f32d_to_s32_noise_c, 0, CONV_NOISE),
|
||||||
|
|
||||||
#if defined (HAVE_AVX2)
|
#if defined (HAVE_AVX2)
|
||||||
MAKE(F32P, S32, 0, conv_f32d_to_s32_avx2, SPA_CPU_FLAG_AVX2),
|
MAKE(F32P, S32, 0, conv_f32d_to_s32_avx2, SPA_CPU_FLAG_AVX2),
|
||||||
|
|
@ -254,33 +254,33 @@ static struct conv_info conv_table[] =
|
||||||
#endif
|
#endif
|
||||||
MAKE(F32P, S32, 0, conv_f32d_to_s32_c),
|
MAKE(F32P, S32, 0, conv_f32d_to_s32_c),
|
||||||
|
|
||||||
MAKE(F32P, S32_OE, 0, conv_f32d_to_s32s_dither_c, 0, CONV_DITHER),
|
MAKE(F32P, S32_OE, 0, conv_f32d_to_s32s_noise_c, 0, CONV_NOISE),
|
||||||
MAKE(F32P, S32_OE, 0, conv_f32d_to_s32s_c),
|
MAKE(F32P, S32_OE, 0, conv_f32d_to_s32s_c),
|
||||||
|
|
||||||
MAKE(F32, U24, 0, conv_f32_to_u24_c),
|
MAKE(F32, U24, 0, conv_f32_to_u24_c),
|
||||||
MAKE(F32P, U24, 0, conv_f32d_to_u24_c),
|
MAKE(F32P, U24, 0, conv_f32d_to_u24_c),
|
||||||
|
|
||||||
MAKE(F32, S24, 0, conv_f32_to_s24_c),
|
MAKE(F32, S24, 0, conv_f32_to_s24_c),
|
||||||
MAKE(F32P, S24P, 0, conv_f32d_to_s24d_dither_c, 0, CONV_DITHER),
|
MAKE(F32P, S24P, 0, conv_f32d_to_s24d_noise_c, 0, CONV_NOISE),
|
||||||
MAKE(F32P, S24P, 0, conv_f32d_to_s24d_c),
|
MAKE(F32P, S24P, 0, conv_f32d_to_s24d_c),
|
||||||
MAKE(F32, S24P, 0, conv_f32_to_s24d_c),
|
MAKE(F32, S24P, 0, conv_f32_to_s24d_c),
|
||||||
MAKE(F32P, S24, 0, conv_f32d_to_s24_dither_c, 0, CONV_DITHER),
|
MAKE(F32P, S24, 0, conv_f32d_to_s24_noise_c, 0, CONV_NOISE),
|
||||||
MAKE(F32P, S24, 0, conv_f32d_to_s24_c),
|
MAKE(F32P, S24, 0, conv_f32d_to_s24_c),
|
||||||
|
|
||||||
MAKE(F32P, S24_OE, 0, conv_f32d_to_s24s_dither_c, 0, CONV_DITHER),
|
MAKE(F32P, S24_OE, 0, conv_f32d_to_s24s_noise_c, 0, CONV_NOISE),
|
||||||
MAKE(F32P, S24_OE, 0, conv_f32d_to_s24s_c),
|
MAKE(F32P, S24_OE, 0, conv_f32d_to_s24s_c),
|
||||||
|
|
||||||
MAKE(F32, U24_32, 0, conv_f32_to_u24_32_c),
|
MAKE(F32, U24_32, 0, conv_f32_to_u24_32_c),
|
||||||
MAKE(F32P, U24_32, 0, conv_f32d_to_u24_32_c),
|
MAKE(F32P, U24_32, 0, conv_f32d_to_u24_32_c),
|
||||||
|
|
||||||
MAKE(F32, S24_32, 0, conv_f32_to_s24_32_c),
|
MAKE(F32, S24_32, 0, conv_f32_to_s24_32_c),
|
||||||
MAKE(F32P, S24_32P, 0, conv_f32d_to_s24_32d_dither_c, 0, CONV_DITHER),
|
MAKE(F32P, S24_32P, 0, conv_f32d_to_s24_32d_noise_c, 0, CONV_NOISE),
|
||||||
MAKE(F32P, S24_32P, 0, conv_f32d_to_s24_32d_c),
|
MAKE(F32P, S24_32P, 0, conv_f32d_to_s24_32d_c),
|
||||||
MAKE(F32, S24_32P, 0, conv_f32_to_s24_32d_c),
|
MAKE(F32, S24_32P, 0, conv_f32_to_s24_32d_c),
|
||||||
MAKE(F32P, S24_32, 0, conv_f32d_to_s24_32_dither_c, 0, CONV_DITHER),
|
MAKE(F32P, S24_32, 0, conv_f32d_to_s24_32_noise_c, 0, CONV_NOISE),
|
||||||
MAKE(F32P, S24_32, 0, conv_f32d_to_s24_32_c),
|
MAKE(F32P, S24_32, 0, conv_f32d_to_s24_32_c),
|
||||||
|
|
||||||
MAKE(F32P, S24_32_OE, 0, conv_f32d_to_s24_32s_dither_c, 0, CONV_DITHER),
|
MAKE(F32P, S24_32_OE, 0, conv_f32d_to_s24_32s_noise_c, 0, CONV_NOISE),
|
||||||
MAKE(F32P, S24_32_OE, 0, conv_f32d_to_s24_32s_c),
|
MAKE(F32P, S24_32_OE, 0, conv_f32d_to_s24_32s_c),
|
||||||
|
|
||||||
MAKE(F32, F64, 0, conv_f32_to_f64_c),
|
MAKE(F32, F64, 0, conv_f32_to_f64_c),
|
||||||
|
|
@ -356,7 +356,7 @@ static struct conv_info conv_table[] =
|
||||||
#define MATCH_DITHER(a,b) ((a) == 0 || ((a) & (b)) == a)
|
#define MATCH_DITHER(a,b) ((a) == 0 || ((a) & (b)) == a)
|
||||||
|
|
||||||
static const struct conv_info *find_conv_info(uint32_t src_fmt, uint32_t dst_fmt,
|
static const struct conv_info *find_conv_info(uint32_t src_fmt, uint32_t dst_fmt,
|
||||||
uint32_t n_channels, uint32_t cpu_flags, uint32_t dither_flags)
|
uint32_t n_channels, uint32_t cpu_flags, uint32_t conv_flags)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
|
|
@ -365,7 +365,7 @@ static const struct conv_info *find_conv_info(uint32_t src_fmt, uint32_t dst_fmt
|
||||||
conv_table[i].dst_fmt == dst_fmt &&
|
conv_table[i].dst_fmt == dst_fmt &&
|
||||||
MATCH_CHAN(conv_table[i].n_channels, n_channels) &&
|
MATCH_CHAN(conv_table[i].n_channels, n_channels) &&
|
||||||
MATCH_CPU_FLAGS(conv_table[i].cpu_flags, cpu_flags) &&
|
MATCH_CPU_FLAGS(conv_table[i].cpu_flags, cpu_flags) &&
|
||||||
MATCH_DITHER(conv_table[i].dither_flags, dither_flags))
|
MATCH_DITHER(conv_table[i].conv_flags, conv_flags))
|
||||||
return &conv_table[i];
|
return &conv_table[i];
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
@ -374,8 +374,8 @@ static const struct conv_info *find_conv_info(uint32_t src_fmt, uint32_t dst_fmt
|
||||||
static void impl_convert_free(struct convert *conv)
|
static void impl_convert_free(struct convert *conv)
|
||||||
{
|
{
|
||||||
conv->process = NULL;
|
conv->process = NULL;
|
||||||
free(conv->dither);
|
free(conv->noise);
|
||||||
conv->dither = NULL;
|
conv->noise = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool need_dither(uint32_t format)
|
static bool need_dither(uint32_t format)
|
||||||
|
|
@ -395,43 +395,99 @@ static bool need_dither(uint32_t format)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* filters based on F-weighted curves
|
||||||
|
* from 'Psychoacoustically Optimal Noise Shaping' (**)
|
||||||
|
* this filter is the "F-Weighted" noise filter described by Wannamaker
|
||||||
|
* It is designed to produce minimum audibility: */
|
||||||
|
static const float wan3[] = { /* Table 3; 3 Coefficients */
|
||||||
|
1.623f, -0.982f, 0.109f
|
||||||
|
};
|
||||||
|
/* Noise shaping coefficients from[1], moves most power of the
|
||||||
|
* error noise into inaudible frequency ranges.
|
||||||
|
*
|
||||||
|
* [1]
|
||||||
|
* "Minimally Audible Noise Shaping", Stanley P. Lipshitz,
|
||||||
|
* John Vanderkooy, and Robert A. Wannamaker,
|
||||||
|
* J. Audio Eng. Soc., Vol. 39, No. 11, November 1991. */
|
||||||
|
static const float lips44[] = { /* improved E-weighted (appendix: 5) */
|
||||||
|
2.033f, -2.165f, 1.959f, -1.590f, 0.6149f
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct dither_info {
|
||||||
|
uint32_t method;
|
||||||
|
uint32_t noise_method;
|
||||||
|
uint32_t rate;
|
||||||
|
const float *ns;
|
||||||
|
uint32_t n_ns;
|
||||||
|
} dither_info[] = {
|
||||||
|
{ DITHER_METHOD_NONE, NOISE_METHOD_NONE, },
|
||||||
|
{ DITHER_METHOD_RECTANGULAR, NOISE_METHOD_RECTANGULAR, },
|
||||||
|
{ DITHER_METHOD_TRIANGULAR, NOISE_METHOD_TRIANGULAR, },
|
||||||
|
{ DITHER_METHOD_TRIANGULAR_HF, NOISE_METHOD_TRIANGULAR_HF, },
|
||||||
|
{ DITHER_METHOD_WANAMAKER_3, NOISE_METHOD_TRIANGULAR_HF, 44100, wan3, SPA_N_ELEMENTS(wan3) },
|
||||||
|
{ DITHER_METHOD_LIPSHITZ, NOISE_METHOD_TRIANGULAR, 44100, lips44, SPA_N_ELEMENTS(lips44) }
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct dither_info *find_dither_info(uint32_t method, uint32_t rate)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < SPA_N_ELEMENTS(dither_info); i++) {
|
||||||
|
const struct dither_info *di = &dither_info[i];
|
||||||
|
if (di->method != method)
|
||||||
|
continue;
|
||||||
|
/* don't use shaped for too low rates, it moves the noise to
|
||||||
|
* audible ranges */
|
||||||
|
if (di->ns != NULL && rate < di->rate * 3 / 4)
|
||||||
|
return find_dither_info(DITHER_METHOD_TRIANGULAR_HF, rate);
|
||||||
|
return &dither_info[i];
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
int convert_init(struct convert *conv)
|
int convert_init(struct convert *conv)
|
||||||
{
|
{
|
||||||
const struct conv_info *info;
|
const struct conv_info *info;
|
||||||
uint32_t i, dither_flags;
|
const struct dither_info *dinfo;
|
||||||
|
uint32_t i, conv_flags;
|
||||||
|
|
||||||
conv->scale = 1.0f / (float)(INT32_MAX);
|
conv->scale = 1.0f / (float)(INT32_MAX);
|
||||||
|
|
||||||
if (conv->noise > 0)
|
if (conv->noise_bits > 0)
|
||||||
conv->scale *= (1 << (conv->noise + 1));
|
conv->scale *= (1 << (conv->noise_bits + 1));
|
||||||
|
|
||||||
/* disable dither if not needed */
|
/* disable dither if not needed */
|
||||||
if (!need_dither(conv->dst_fmt))
|
if (!need_dither(conv->dst_fmt))
|
||||||
conv->method = DITHER_METHOD_NONE;
|
conv->method = DITHER_METHOD_NONE;
|
||||||
|
|
||||||
/* don't use shaped for too low rates, it moves the noise to
|
dinfo = find_dither_info(conv->method, conv->rate);
|
||||||
* audible ranges */
|
if (dinfo == NULL)
|
||||||
if (conv->method == DITHER_METHOD_SHAPED_5 && conv->rate < 32000)
|
return -EINVAL;
|
||||||
conv->method = DITHER_METHOD_TRIANGULAR;
|
|
||||||
|
|
||||||
if (conv->method < DITHER_METHOD_TRIANGULAR)
|
conv->noise_method = dinfo->noise_method;
|
||||||
|
if (conv->noise_bits && conv->noise_method == NOISE_METHOD_NONE)
|
||||||
|
conv->noise_method = NOISE_METHOD_RECTANGULAR;
|
||||||
|
if (conv->noise_method < NOISE_METHOD_TRIANGULAR)
|
||||||
conv->scale *= 0.5f;
|
conv->scale *= 0.5f;
|
||||||
|
|
||||||
dither_flags = 0;
|
conv_flags = 0;
|
||||||
if (conv->method != DITHER_METHOD_NONE || conv->noise)
|
if (conv->noise_method != NOISE_METHOD_NONE)
|
||||||
dither_flags |= CONV_DITHER;
|
conv_flags |= CONV_NOISE;
|
||||||
if (conv->method == DITHER_METHOD_SHAPED_5)
|
if (dinfo->n_ns > 0) {
|
||||||
dither_flags |= CONV_SHAPE;
|
conv_flags |= CONV_SHAPE;
|
||||||
|
conv->n_ns = dinfo->n_ns;
|
||||||
|
conv->ns = dinfo->ns;
|
||||||
|
}
|
||||||
|
|
||||||
info = find_conv_info(conv->src_fmt, conv->dst_fmt, conv->n_channels,
|
info = find_conv_info(conv->src_fmt, conv->dst_fmt, conv->n_channels,
|
||||||
conv->cpu_flags, dither_flags);
|
conv->cpu_flags, conv_flags);
|
||||||
if (info == NULL)
|
if (info == NULL)
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
|
|
||||||
conv->dither_size = DITHER_SIZE;
|
conv->noise_size = DITHER_SIZE;
|
||||||
conv->dither = calloc(conv->dither_size + 16 +
|
conv->noise = calloc(conv->noise_size + 16 +
|
||||||
FMT_OPS_MAX_ALIGN / sizeof(float), sizeof(float));
|
FMT_OPS_MAX_ALIGN / sizeof(float), sizeof(float));
|
||||||
if (conv->dither == NULL)
|
if (conv->noise == NULL)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
for (i = 0; i < SPA_N_ELEMENTS(conv->random); i++)
|
for (i = 0; i < SPA_N_ELEMENTS(conv->random); i++)
|
||||||
|
|
|
||||||
|
|
@ -39,8 +39,8 @@
|
||||||
|
|
||||||
#define ITOF(type,v,scale,offs) \
|
#define ITOF(type,v,scale,offs) \
|
||||||
(((type)(v)) * (1.0f / (scale)) - (offs))
|
(((type)(v)) * (1.0f / (scale)) - (offs))
|
||||||
#define FTOI(type,v,scale,offs,dither,min,max) \
|
#define FTOI(type,v,scale,offs,noise,min,max) \
|
||||||
(type)f32_round(SPA_CLAMP((v) * (scale) + (offs) + (dither), min, max))
|
(type)f32_round(SPA_CLAMP((v) * (scale) + (offs) + (noise), min, max))
|
||||||
|
|
||||||
#define FMT_OPS_MAX_ALIGN 32
|
#define FMT_OPS_MAX_ALIGN 32
|
||||||
|
|
||||||
|
|
@ -202,17 +202,19 @@ static inline int24_t bswap_s24(int24_t src)
|
||||||
#define NS_MASK (NS_MAX-1)
|
#define NS_MASK (NS_MAX-1)
|
||||||
|
|
||||||
struct shaper {
|
struct shaper {
|
||||||
float e[NS_MAX];
|
float e[NS_MAX * 2];
|
||||||
uint32_t idx;
|
uint32_t idx;
|
||||||
float r;
|
float r;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct convert {
|
struct convert {
|
||||||
uint32_t noise;
|
uint32_t noise_bits;
|
||||||
#define DITHER_METHOD_NONE 0
|
#define DITHER_METHOD_NONE 0
|
||||||
#define DITHER_METHOD_RECTANGULAR 1
|
#define DITHER_METHOD_RECTANGULAR 1
|
||||||
#define DITHER_METHOD_TRIANGULAR 2
|
#define DITHER_METHOD_TRIANGULAR 2
|
||||||
#define DITHER_METHOD_SHAPED_5 3
|
#define DITHER_METHOD_TRIANGULAR_HF 3
|
||||||
|
#define DITHER_METHOD_WANAMAKER_3 4
|
||||||
|
#define DITHER_METHOD_LIPSHITZ 5
|
||||||
uint32_t method;
|
uint32_t method;
|
||||||
|
|
||||||
uint32_t src_fmt;
|
uint32_t src_fmt;
|
||||||
|
|
@ -226,8 +228,16 @@ struct convert {
|
||||||
|
|
||||||
float scale;
|
float scale;
|
||||||
uint32_t random[16 + FMT_OPS_MAX_ALIGN/4];
|
uint32_t random[16 + FMT_OPS_MAX_ALIGN/4];
|
||||||
float *dither;
|
int32_t prev[16 + FMT_OPS_MAX_ALIGN/4];
|
||||||
uint32_t dither_size;
|
#define NOISE_METHOD_NONE 0
|
||||||
|
#define NOISE_METHOD_RECTANGULAR 1
|
||||||
|
#define NOISE_METHOD_TRIANGULAR 2
|
||||||
|
#define NOISE_METHOD_TRIANGULAR_HF 3
|
||||||
|
uint32_t noise_method;
|
||||||
|
float *noise;
|
||||||
|
uint32_t noise_size;
|
||||||
|
const float *ns;
|
||||||
|
uint32_t n_ns;
|
||||||
struct shaper shaper[64];
|
struct shaper shaper[64];
|
||||||
|
|
||||||
void (*process) (struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[],
|
void (*process) (struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[],
|
||||||
|
|
@ -238,14 +248,22 @@ struct convert {
|
||||||
int convert_init(struct convert *conv);
|
int convert_init(struct convert *conv);
|
||||||
|
|
||||||
static const struct dither_method_info {
|
static const struct dither_method_info {
|
||||||
|
uint32_t method;
|
||||||
const char *label;
|
const char *label;
|
||||||
const char *description;
|
const char *description;
|
||||||
uint32_t method;
|
|
||||||
} dither_method_info[] = {
|
} dither_method_info[] = {
|
||||||
[DITHER_METHOD_NONE] = { "none", "Disabled", DITHER_METHOD_NONE },
|
[DITHER_METHOD_NONE] = { DITHER_METHOD_NONE,
|
||||||
[DITHER_METHOD_RECTANGULAR] = { "rectangular", "Rectangular dithering", DITHER_METHOD_RECTANGULAR },
|
"none", "Disabled", },
|
||||||
[DITHER_METHOD_TRIANGULAR] = { "triangular", "Triangular dithering", DITHER_METHOD_TRIANGULAR },
|
[DITHER_METHOD_RECTANGULAR] = { DITHER_METHOD_RECTANGULAR,
|
||||||
[DITHER_METHOD_SHAPED_5] = { "shaped5", "Shaped 5 dithering", DITHER_METHOD_SHAPED_5 }
|
"rectangular", "Rectangular dithering", },
|
||||||
|
[DITHER_METHOD_TRIANGULAR] = { DITHER_METHOD_TRIANGULAR,
|
||||||
|
"triangular", "Triangular dithering", },
|
||||||
|
[DITHER_METHOD_TRIANGULAR_HF] = { DITHER_METHOD_TRIANGULAR_HF,
|
||||||
|
"triangular-hf", "Sloped Triangular dithering", },
|
||||||
|
[DITHER_METHOD_WANAMAKER_3] = { DITHER_METHOD_WANAMAKER_3,
|
||||||
|
"wanamaker3", "Wanamaker 3 dithering", },
|
||||||
|
[DITHER_METHOD_LIPSHITZ] = { DITHER_METHOD_LIPSHITZ,
|
||||||
|
"shaped5", "Lipshitz 5 dithering", },
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline uint32_t dither_method_from_label(const char *label)
|
static inline uint32_t dither_method_from_label(const char *label)
|
||||||
|
|
@ -319,66 +337,66 @@ DEFINE_FUNCTION(f64_to_f32d, c);
|
||||||
DEFINE_FUNCTION(f64s_to_f32d, c);
|
DEFINE_FUNCTION(f64s_to_f32d, c);
|
||||||
DEFINE_FUNCTION(f64d_to_f32, c);
|
DEFINE_FUNCTION(f64d_to_f32, c);
|
||||||
DEFINE_FUNCTION(f32d_to_u8d, c);
|
DEFINE_FUNCTION(f32d_to_u8d, c);
|
||||||
DEFINE_FUNCTION(f32d_to_u8d_dither, c);
|
DEFINE_FUNCTION(f32d_to_u8d_noise, c);
|
||||||
DEFINE_FUNCTION(f32d_to_u8d_shaped, c);
|
DEFINE_FUNCTION(f32d_to_u8d_shaped, c);
|
||||||
DEFINE_FUNCTION(f32_to_u8, c);
|
DEFINE_FUNCTION(f32_to_u8, c);
|
||||||
DEFINE_FUNCTION(f32_to_u8d, c);
|
DEFINE_FUNCTION(f32_to_u8d, c);
|
||||||
DEFINE_FUNCTION(f32d_to_u8, c);
|
DEFINE_FUNCTION(f32d_to_u8, c);
|
||||||
DEFINE_FUNCTION(f32d_to_u8_dither, c);
|
DEFINE_FUNCTION(f32d_to_u8_noise, c);
|
||||||
DEFINE_FUNCTION(f32d_to_u8_shaped, c);
|
DEFINE_FUNCTION(f32d_to_u8_shaped, c);
|
||||||
DEFINE_FUNCTION(f32d_to_s8d, c);
|
DEFINE_FUNCTION(f32d_to_s8d, c);
|
||||||
DEFINE_FUNCTION(f32d_to_s8d_dither, c);
|
DEFINE_FUNCTION(f32d_to_s8d_noise, c);
|
||||||
DEFINE_FUNCTION(f32d_to_s8d_shaped, c);
|
DEFINE_FUNCTION(f32d_to_s8d_shaped, c);
|
||||||
DEFINE_FUNCTION(f32_to_s8, c);
|
DEFINE_FUNCTION(f32_to_s8, c);
|
||||||
DEFINE_FUNCTION(f32_to_s8d, c);
|
DEFINE_FUNCTION(f32_to_s8d, c);
|
||||||
DEFINE_FUNCTION(f32d_to_s8, c);
|
DEFINE_FUNCTION(f32d_to_s8, c);
|
||||||
DEFINE_FUNCTION(f32d_to_s8_dither, c);
|
DEFINE_FUNCTION(f32d_to_s8_noise, c);
|
||||||
DEFINE_FUNCTION(f32d_to_s8_shaped, c);
|
DEFINE_FUNCTION(f32d_to_s8_shaped, c);
|
||||||
DEFINE_FUNCTION(f32d_to_alaw, c);
|
DEFINE_FUNCTION(f32d_to_alaw, c);
|
||||||
DEFINE_FUNCTION(f32d_to_ulaw, c);
|
DEFINE_FUNCTION(f32d_to_ulaw, c);
|
||||||
DEFINE_FUNCTION(f32_to_u16, c);
|
DEFINE_FUNCTION(f32_to_u16, c);
|
||||||
DEFINE_FUNCTION(f32d_to_u16, c);
|
DEFINE_FUNCTION(f32d_to_u16, c);
|
||||||
DEFINE_FUNCTION(f32d_to_s16d, c);
|
DEFINE_FUNCTION(f32d_to_s16d, c);
|
||||||
DEFINE_FUNCTION(f32d_to_s16d_dither, c);
|
DEFINE_FUNCTION(f32d_to_s16d_noise, c);
|
||||||
DEFINE_FUNCTION(f32d_to_s16d_shaped, c);
|
DEFINE_FUNCTION(f32d_to_s16d_shaped, c);
|
||||||
DEFINE_FUNCTION(f32_to_s16, c);
|
DEFINE_FUNCTION(f32_to_s16, c);
|
||||||
DEFINE_FUNCTION(f32_to_s16d, c);
|
DEFINE_FUNCTION(f32_to_s16d, c);
|
||||||
DEFINE_FUNCTION(f32d_to_s16, c);
|
DEFINE_FUNCTION(f32d_to_s16, c);
|
||||||
DEFINE_FUNCTION(f32d_to_s16_dither, c);
|
DEFINE_FUNCTION(f32d_to_s16_noise, c);
|
||||||
DEFINE_FUNCTION(f32d_to_s16_shaped, c);
|
DEFINE_FUNCTION(f32d_to_s16_shaped, c);
|
||||||
DEFINE_FUNCTION(f32d_to_s16s, c);
|
DEFINE_FUNCTION(f32d_to_s16s, c);
|
||||||
DEFINE_FUNCTION(f32d_to_s16s_dither, c);
|
DEFINE_FUNCTION(f32d_to_s16s_noise, c);
|
||||||
DEFINE_FUNCTION(f32d_to_s16s_shaped, c);
|
DEFINE_FUNCTION(f32d_to_s16s_shaped, c);
|
||||||
DEFINE_FUNCTION(f32_to_u32, c);
|
DEFINE_FUNCTION(f32_to_u32, c);
|
||||||
DEFINE_FUNCTION(f32d_to_u32, c);
|
DEFINE_FUNCTION(f32d_to_u32, c);
|
||||||
DEFINE_FUNCTION(f32d_to_s32d, c);
|
DEFINE_FUNCTION(f32d_to_s32d, c);
|
||||||
DEFINE_FUNCTION(f32d_to_s32d_dither, c);
|
DEFINE_FUNCTION(f32d_to_s32d_noise, c);
|
||||||
DEFINE_FUNCTION(f32_to_s32, c);
|
DEFINE_FUNCTION(f32_to_s32, c);
|
||||||
DEFINE_FUNCTION(f32_to_s32d, c);
|
DEFINE_FUNCTION(f32_to_s32d, c);
|
||||||
DEFINE_FUNCTION(f32d_to_s32, c);
|
DEFINE_FUNCTION(f32d_to_s32, c);
|
||||||
DEFINE_FUNCTION(f32d_to_s32_dither, c);
|
DEFINE_FUNCTION(f32d_to_s32_noise, c);
|
||||||
DEFINE_FUNCTION(f32d_to_s32s, c);
|
DEFINE_FUNCTION(f32d_to_s32s, c);
|
||||||
DEFINE_FUNCTION(f32d_to_s32s_dither, c);
|
DEFINE_FUNCTION(f32d_to_s32s_noise, c);
|
||||||
DEFINE_FUNCTION(f32_to_u24, c);
|
DEFINE_FUNCTION(f32_to_u24, c);
|
||||||
DEFINE_FUNCTION(f32d_to_u24, c);
|
DEFINE_FUNCTION(f32d_to_u24, c);
|
||||||
DEFINE_FUNCTION(f32d_to_s24d, c);
|
DEFINE_FUNCTION(f32d_to_s24d, c);
|
||||||
DEFINE_FUNCTION(f32d_to_s24d_dither, c);
|
DEFINE_FUNCTION(f32d_to_s24d_noise, c);
|
||||||
DEFINE_FUNCTION(f32_to_s24, c);
|
DEFINE_FUNCTION(f32_to_s24, c);
|
||||||
DEFINE_FUNCTION(f32_to_s24d, c);
|
DEFINE_FUNCTION(f32_to_s24d, c);
|
||||||
DEFINE_FUNCTION(f32d_to_s24, c);
|
DEFINE_FUNCTION(f32d_to_s24, c);
|
||||||
DEFINE_FUNCTION(f32d_to_s24_dither, c);
|
DEFINE_FUNCTION(f32d_to_s24_noise, c);
|
||||||
DEFINE_FUNCTION(f32d_to_s24s, c);
|
DEFINE_FUNCTION(f32d_to_s24s, c);
|
||||||
DEFINE_FUNCTION(f32d_to_s24s_dither, c);
|
DEFINE_FUNCTION(f32d_to_s24s_noise, c);
|
||||||
DEFINE_FUNCTION(f32_to_u24_32, c);
|
DEFINE_FUNCTION(f32_to_u24_32, c);
|
||||||
DEFINE_FUNCTION(f32d_to_u24_32, c);
|
DEFINE_FUNCTION(f32d_to_u24_32, c);
|
||||||
DEFINE_FUNCTION(f32d_to_s24_32d, c);
|
DEFINE_FUNCTION(f32d_to_s24_32d, c);
|
||||||
DEFINE_FUNCTION(f32d_to_s24_32d_dither, c);
|
DEFINE_FUNCTION(f32d_to_s24_32d_noise, c);
|
||||||
DEFINE_FUNCTION(f32_to_s24_32, c);
|
DEFINE_FUNCTION(f32_to_s24_32, c);
|
||||||
DEFINE_FUNCTION(f32_to_s24_32d, c);
|
DEFINE_FUNCTION(f32_to_s24_32d, c);
|
||||||
DEFINE_FUNCTION(f32d_to_s24_32, c);
|
DEFINE_FUNCTION(f32d_to_s24_32, c);
|
||||||
DEFINE_FUNCTION(f32d_to_s24_32_dither, c);
|
DEFINE_FUNCTION(f32d_to_s24_32_noise, c);
|
||||||
DEFINE_FUNCTION(f32d_to_s24_32s, c);
|
DEFINE_FUNCTION(f32d_to_s24_32s, c);
|
||||||
DEFINE_FUNCTION(f32d_to_s24_32s_dither, c);
|
DEFINE_FUNCTION(f32d_to_s24_32s_noise, c);
|
||||||
DEFINE_FUNCTION(f32d_to_f64d, c);
|
DEFINE_FUNCTION(f32d_to_f64d, c);
|
||||||
DEFINE_FUNCTION(f32_to_f64, c);
|
DEFINE_FUNCTION(f32_to_f64, c);
|
||||||
DEFINE_FUNCTION(f32_to_f64d, c);
|
DEFINE_FUNCTION(f32_to_f64d, c);
|
||||||
|
|
@ -410,13 +428,13 @@ DEFINE_FUNCTION(s16_to_f32d, sse2);
|
||||||
DEFINE_FUNCTION(s24_to_f32d, sse2);
|
DEFINE_FUNCTION(s24_to_f32d, sse2);
|
||||||
DEFINE_FUNCTION(s32_to_f32d, sse2);
|
DEFINE_FUNCTION(s32_to_f32d, sse2);
|
||||||
DEFINE_FUNCTION(f32d_to_s32, sse2);
|
DEFINE_FUNCTION(f32d_to_s32, sse2);
|
||||||
DEFINE_FUNCTION(f32d_to_s32_dither, sse2);
|
DEFINE_FUNCTION(f32d_to_s32_noise, sse2);
|
||||||
DEFINE_FUNCTION(f32_to_s16, sse2);
|
DEFINE_FUNCTION(f32_to_s16, sse2);
|
||||||
DEFINE_FUNCTION(f32d_to_s16_2, sse2);
|
DEFINE_FUNCTION(f32d_to_s16_2, sse2);
|
||||||
DEFINE_FUNCTION(f32d_to_s16, sse2);
|
DEFINE_FUNCTION(f32d_to_s16, sse2);
|
||||||
DEFINE_FUNCTION(f32d_to_s16_dither, sse2);
|
DEFINE_FUNCTION(f32d_to_s16_noise, sse2);
|
||||||
DEFINE_FUNCTION(f32d_to_s16d, sse2);
|
DEFINE_FUNCTION(f32d_to_s16d, sse2);
|
||||||
DEFINE_FUNCTION(f32d_to_s16d_dither, sse2);
|
DEFINE_FUNCTION(f32d_to_s16d_noise, sse2);
|
||||||
DEFINE_FUNCTION(32_to_32d, sse2);
|
DEFINE_FUNCTION(32_to_32d, sse2);
|
||||||
DEFINE_FUNCTION(32s_to_32d, sse2);
|
DEFINE_FUNCTION(32s_to_32d, sse2);
|
||||||
DEFINE_FUNCTION(32d_to_32, sse2);
|
DEFINE_FUNCTION(32d_to_32, sse2);
|
||||||
|
|
|
||||||
|
|
@ -656,7 +656,7 @@ static void run_test_noise(uint32_t fmt, uint32_t noise, uint32_t flags)
|
||||||
|
|
||||||
spa_zero(conv);
|
spa_zero(conv);
|
||||||
|
|
||||||
conv.noise = noise;
|
conv.noise_bits = noise;
|
||||||
conv.src_fmt = SPA_AUDIO_FORMAT_F32P;
|
conv.src_fmt = SPA_AUDIO_FORMAT_F32P;
|
||||||
conv.dst_fmt = fmt;
|
conv.dst_fmt = fmt;
|
||||||
conv.n_channels = 2;
|
conv.n_channels = 2;
|
||||||
|
|
@ -672,7 +672,7 @@ static void run_test_noise(uint32_t fmt, uint32_t noise, uint32_t flags)
|
||||||
}
|
}
|
||||||
convert_process(&conv, op, ip, N_SAMPLES);
|
convert_process(&conv, op, ip, N_SAMPLES);
|
||||||
|
|
||||||
range = 1 << conv.noise;
|
range = 1 << conv.noise_bits;
|
||||||
|
|
||||||
all_zero = true;
|
all_zero = true;
|
||||||
for (i = 0; i < conv.n_channels * N_SAMPLES; i++) {
|
for (i = 0; i < conv.n_channels * N_SAMPLES; i++) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue