mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-12-17 08:56:49 -05:00
audioconvert: fix dither scale
Rectangular dither should be [-0.5, 0.5] Triangular dither should be [-1.0, 1.0] Noise should add extra bits.
This commit is contained in:
parent
e313149f7f
commit
68f883ff77
4 changed files with 23 additions and 3 deletions
|
|
@ -237,6 +237,7 @@ static inline void update_dither_c(struct convert *conv, uint32_t n_samples)
|
||||||
uint32_t *state = &conv->random[0];
|
uint32_t *state = &conv->random[0];
|
||||||
|
|
||||||
if (conv->method < DITHER_METHOD_TRIANGULAR) {
|
if (conv->method < DITHER_METHOD_TRIANGULAR) {
|
||||||
|
scale *= 0.5f;
|
||||||
for (n = 0; n < n_samples; n++)
|
for (n = 0; n < n_samples; n++)
|
||||||
dither[n] = lcnoise(state) * scale;
|
dither[n] = lcnoise(state) * scale;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -585,11 +585,12 @@ static inline void update_dither_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);
|
||||||
|
__m128 out[1];
|
||||||
float *dither = SPA_PTR_ALIGN(conv->dither, 16, float);
|
float *dither = SPA_PTR_ALIGN(conv->dither, 16, float);
|
||||||
__m128 scale = _mm_set1_ps(conv->scale), out[1];
|
|
||||||
__m128i in[2];
|
__m128i in[2];
|
||||||
|
|
||||||
if (conv->method < DITHER_METHOD_TRIANGULAR) {
|
if (conv->method < DITHER_METHOD_TRIANGULAR) {
|
||||||
|
__m128 scale = _mm_set1_ps(conv->scale * 0.5f);
|
||||||
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));
|
||||||
|
|
@ -597,6 +598,7 @@ static inline void update_dither_sse2(struct convert *conv, uint32_t n_samples)
|
||||||
_mm_store_ps(&dither[n], out[0]);
|
_mm_store_ps(&dither[n], out[0]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
__m128 scale = _mm_set1_ps(conv->scale);
|
||||||
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_add_epi32( _MM_XORSHIFT_EPI32(r), _MM_XORSHIFT_EPI32(r));
|
||||||
out[0] = _mm_cvtepi32_ps(in[0]);
|
out[0] = _mm_cvtepi32_ps(in[0]);
|
||||||
|
|
|
||||||
|
|
@ -394,7 +394,10 @@ int convert_init(struct convert *conv)
|
||||||
const struct conv_info *info;
|
const struct conv_info *info;
|
||||||
uint32_t i, dither_flags;
|
uint32_t i, dither_flags;
|
||||||
|
|
||||||
conv->scale = 1.0f / (float)(INT32_MAX >> conv->noise);
|
conv->scale = 1.0f / (float)(INT32_MAX);
|
||||||
|
|
||||||
|
if (conv->noise > 0)
|
||||||
|
conv->scale *= (1 << (conv->noise + 1));
|
||||||
|
|
||||||
/* disable dither if not needed */
|
/* disable dither if not needed */
|
||||||
if (!need_dither(conv->dst_fmt))
|
if (!need_dither(conv->dst_fmt))
|
||||||
|
|
|
||||||
|
|
@ -632,6 +632,7 @@ static void run_test_noise(uint32_t fmt, uint32_t noise, uint32_t flags)
|
||||||
const void *ip[N_CHANNELS];
|
const void *ip[N_CHANNELS];
|
||||||
void *op[N_CHANNELS];
|
void *op[N_CHANNELS];
|
||||||
uint32_t i, range;
|
uint32_t i, range;
|
||||||
|
bool all_zero;
|
||||||
|
|
||||||
spa_zero(conv);
|
spa_zero(conv);
|
||||||
|
|
||||||
|
|
@ -653,35 +654,47 @@ static void run_test_noise(uint32_t fmt, uint32_t noise, uint32_t flags)
|
||||||
|
|
||||||
range = (1 << conv.noise) - 1;
|
range = (1 << conv.noise) - 1;
|
||||||
|
|
||||||
|
all_zero = true;
|
||||||
for (i = 0; i < conv.n_channels * N_SAMPLES; i++) {
|
for (i = 0; i < conv.n_channels * N_SAMPLES; i++) {
|
||||||
switch (fmt) {
|
switch (fmt) {
|
||||||
case SPA_AUDIO_FORMAT_S8:
|
case SPA_AUDIO_FORMAT_S8:
|
||||||
{
|
{
|
||||||
int8_t *d = (int8_t *)samp_out;
|
int8_t *d = (int8_t *)samp_out;
|
||||||
|
if (d[i] != 0)
|
||||||
|
all_zero = false;
|
||||||
spa_assert_se(SPA_ABS(d[i] - 0) <= (int8_t)range);
|
spa_assert_se(SPA_ABS(d[i] - 0) <= (int8_t)range);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SPA_AUDIO_FORMAT_U8:
|
case SPA_AUDIO_FORMAT_U8:
|
||||||
{
|
{
|
||||||
uint8_t *d = (uint8_t *)samp_out;
|
uint8_t *d = (uint8_t *)samp_out;
|
||||||
|
if (d[i] != 0x80)
|
||||||
|
all_zero = false;
|
||||||
spa_assert_se((int8_t)SPA_ABS(d[i] - 0x80) <= (int8_t)(range<<1));
|
spa_assert_se((int8_t)SPA_ABS(d[i] - 0x80) <= (int8_t)(range<<1));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SPA_AUDIO_FORMAT_S16:
|
case SPA_AUDIO_FORMAT_S16:
|
||||||
{
|
{
|
||||||
int16_t *d = (int16_t *)samp_out;
|
int16_t *d = (int16_t *)samp_out;
|
||||||
|
if (d[i] != 0)
|
||||||
|
all_zero = false;
|
||||||
spa_assert_se(SPA_ABS(d[i] - 0) <= (int16_t)range);
|
spa_assert_se(SPA_ABS(d[i] - 0) <= (int16_t)range);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SPA_AUDIO_FORMAT_S24:
|
case SPA_AUDIO_FORMAT_S24:
|
||||||
{
|
{
|
||||||
int24_t *d = (int24_t *)samp_out;
|
int24_t *d = (int24_t *)samp_out;
|
||||||
spa_assert_se(SPA_ABS(s24_to_s32(d[i]) - 0) <= (int32_t)range);
|
int32_t t = s24_to_s32(d[i]);
|
||||||
|
if (t != 0)
|
||||||
|
all_zero = false;
|
||||||
|
spa_assert_se(SPA_ABS(t - 0) <= (int32_t)range);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SPA_AUDIO_FORMAT_S32:
|
case SPA_AUDIO_FORMAT_S32:
|
||||||
{
|
{
|
||||||
int32_t *d = (int32_t *)samp_out;
|
int32_t *d = (int32_t *)samp_out;
|
||||||
|
if (d[i] != 0)
|
||||||
|
all_zero = false;
|
||||||
spa_assert_se(SPA_ABS(d[i] - 0) <= (int32_t)(range << 8));
|
spa_assert_se(SPA_ABS(d[i] - 0) <= (int32_t)(range << 8));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -690,6 +703,7 @@ static void run_test_noise(uint32_t fmt, uint32_t noise, uint32_t flags)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
spa_assert_se(all_zero == false);
|
||||||
convert_free(&conv);
|
convert_free(&conv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue