From 277addcca6f00874840c2db6e9f6278dc86486a6 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Mon, 11 Jul 2022 16:28:51 +0200 Subject: [PATCH] audioconvert: add triangular dither --- spa/plugins/audioconvert/fmt-ops-c.c | 9 +++++++-- spa/plugins/audioconvert/fmt-ops-sse2.c | 14 +++++++++++++- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/spa/plugins/audioconvert/fmt-ops-c.c b/spa/plugins/audioconvert/fmt-ops-c.c index 9d2d171b2..f37a41523 100644 --- a/spa/plugins/audioconvert/fmt-ops-c.c +++ b/spa/plugins/audioconvert/fmt-ops-c.c @@ -236,8 +236,13 @@ static inline void update_dither_c(struct convert *conv, uint32_t n_samples) float *dither = conv->dither, scale = conv->scale; uint32_t *state = &conv->random[0]; - for (n = 0; n < n_samples; n++) - dither[n] = lcnoise(state) * scale; + if (conv->method < DITHER_METHOD_TRIANGULAR) { + for (n = 0; n < n_samples; n++) + dither[n] = lcnoise(state) * scale; + } else { + for (n = 0; n < n_samples; n++) + dither[n] = (lcnoise(state) + lcnoise(state)) * scale; + } } #define MAKE_D_dither(dname,dtype,func) \ diff --git a/spa/plugins/audioconvert/fmt-ops-sse2.c b/spa/plugins/audioconvert/fmt-ops-sse2.c index 5b4f06324..d28f556d6 100644 --- a/spa/plugins/audioconvert/fmt-ops-sse2.c +++ b/spa/plugins/audioconvert/fmt-ops-sse2.c @@ -571,7 +571,7 @@ static inline void update_dither_sse2(struct convert *conv, uint32_t n_samples) const uint32_t *r = SPA_PTR_ALIGN(conv->random, 16, uint32_t); float *dither = SPA_PTR_ALIGN(conv->dither, 16, float); __m128 scale = _mm_set1_ps(conv->scale), out[1]; - __m128i in[1], t[1]; + __m128i in[2], t[1]; for (n = 0; n < n_samples; n += 4) { /* 32 bit xorshift PRNG, see https://en.wikipedia.org/wiki/Xorshift */ @@ -584,6 +584,18 @@ static inline void update_dither_sse2(struct convert *conv, uint32_t n_samples) in[0] = _mm_xor_si128(in[0], t[0]); _mm_store_si128((__m128i*)r, in[0]); + if (conv->method >= DITHER_METHOD_TRIANGULAR) { + in[1] = _mm_load_si128((__m128i*)r); + t[0] = _mm_slli_epi32(in[1], 13); + in[1] = _mm_xor_si128(in[1], t[0]); + t[0] = _mm_srli_epi32(in[1], 17); + in[1] = _mm_xor_si128(in[1], t[0]); + t[0] = _mm_slli_epi32(in[1], 5); + in[1] = _mm_xor_si128(in[1], t[0]); + _mm_store_si128((__m128i*)r, in[1]); + + in[0] = _mm_add_epi32(in[0], in[1]); + } out[0] = _mm_cvtepi32_ps(in[0]); out[0] = _mm_mul_ps(out[0], scale); _mm_store_ps(&dither[n], out[0]);