From b7e26002be728ae5eeebffcb336a4d5f4db2a719 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Tue, 28 Jun 2022 10:11:46 +0200 Subject: [PATCH] audiocovert: improve dither setup The quantize is the amount of bits we want to keep from the original signal, subtract the amount of bits for noise. Clamp this to 0 (all noise). Calculate the scale factor better with powf() and avoid overflows. Fixes #2479 --- spa/plugins/audioconvert/audioconvert.c | 7 ++++--- spa/plugins/audioconvert/dither-ops.c | 5 +---- spa/plugins/audioconvert/dither-ops.h | 8 ++++---- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/spa/plugins/audioconvert/audioconvert.c b/spa/plugins/audioconvert/audioconvert.c index 6673a8b46..4fd17a071 100644 --- a/spa/plugins/audioconvert/audioconvert.c +++ b/spa/plugins/audioconvert/audioconvert.c @@ -1395,9 +1395,10 @@ static int setup_out_convert(struct impl *this) spa_log_debug(this->log, "%p: got converter features %08x:%08x passthrough:%d", this, this->cpu_flags, out->conv.cpu_flags, out->conv.is_passthrough); + if (this->props.dither_noise > 0) { - this->dither.quantize = 32 - (calc_width(&dst_info) * 8); - this->dither.quantize += this->props.dither_noise; + this->dither.quantize = calc_width(&dst_info) * 8; + this->dither.quantize -= SPA_MIN(this->dither.quantize, this->props.dither_noise); this->dither.n_channels = dst_info.info.raw.channels; this->dither.cpu_flags = this->cpu_flags; @@ -2478,7 +2479,7 @@ static int impl_node_process(void *object) } this->out_offset += n_samples; - if (this->props.dither_noise > 0) { + if (this->dither.process != NULL) { in_datas = (const void**)out_datas; if (out_passthrough) out_datas = dst_datas; diff --git a/spa/plugins/audioconvert/dither-ops.c b/spa/plugins/audioconvert/dither-ops.c index ffb79989c..ee9d039c9 100644 --- a/spa/plugins/audioconvert/dither-ops.c +++ b/spa/plugins/audioconvert/dither-ops.c @@ -79,10 +79,7 @@ int dither_init(struct dither *d) if (info == NULL) return -ENOTSUP; - if (d->quantize >= 32) - return -EINVAL; - - d->scale = 1.0f / (1ULL << (63 - d->quantize)); + d->scale = 1.0f / powf(2.0f, 31 + d->quantize); d->dither_size = DITHER_SIZE; d->dither = calloc(d->dither_size + DITHER_OPS_MAX_OVERREAD + diff --git a/spa/plugins/audioconvert/dither-ops.h b/spa/plugins/audioconvert/dither-ops.h index afa96db5f..7f0f9bc60 100644 --- a/spa/plugins/audioconvert/dither-ops.h +++ b/spa/plugins/audioconvert/dither-ops.h @@ -34,10 +34,10 @@ struct dither { uint32_t quantize; -#define DITHER_METHOD_NONE 0 -#define DITHER_METHOD_RECTANGULAR 2 -#define DITHER_METHOD_TRIANGULAR 3 -#define DITHER_METHOD_SHAPED_5 4 +#define DITHER_METHOD_NONE 0 +#define DITHER_METHOD_RECTANGULAR 2 +#define DITHER_METHOD_TRIANGULAR 3 +#define DITHER_METHOD_SHAPED_5 4 uint32_t method; uint32_t n_channels; uint32_t cpu_flags;