diff --git a/spa/plugins/audioconvert/audioconvert.c b/spa/plugins/audioconvert/audioconvert.c index 4fd17a071..a936f3a4a 100644 --- a/spa/plugins/audioconvert/audioconvert.c +++ b/spa/plugins/audioconvert/audioconvert.c @@ -93,7 +93,6 @@ struct props { unsigned int resample_quality; unsigned int resample_disabled:1; double rate; - uint32_t dither_noise; }; static void props_reset(struct props *props) @@ -110,7 +109,6 @@ static void props_reset(struct props *props) props->rate = 1.0; props->resample_quality = RESAMPLE_DEFAULT_QUALITY; props->resample_disabled = false; - props->dither_noise = 0; } struct buffer { @@ -614,7 +612,7 @@ static int impl_node_enum_params(void *object, int seq, SPA_TYPE_OBJECT_PropInfo, id, SPA_PROP_INFO_name, SPA_POD_String("dither.noise"), SPA_PROP_INFO_description, SPA_POD_String("Add dithering noise"), - SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Int(p->dither_noise, 0, 16), + SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Int(this->dither.noise, 0, 16), SPA_PROP_INFO_params, SPA_POD_Bool(true)); break; default: @@ -684,7 +682,7 @@ static int impl_node_enum_params(void *object, int seq, spa_pod_builder_string(&b, "resample.disable"); spa_pod_builder_bool(&b, p->resample_disabled); spa_pod_builder_string(&b, "dither.noise"); - spa_pod_builder_int(&b, p->dither_noise); + spa_pod_builder_int(&b, this->dither.noise); spa_pod_builder_pop(&b, &f[1]); param = spa_pod_builder_pop(&b, &f[0]); break; @@ -755,7 +753,7 @@ static int audioconvert_set_param(struct impl *this, const char *k, const char * else if (spa_streq(k, "resample.disable")) this->props.resample_disabled = spa_atob(s); else if (spa_streq(k, "dither.noise")) - spa_atou32(s, &this->props.dither_noise, 0); + spa_atou32(s, &this->dither.noise, 0); else return 0; return 1; @@ -1396,18 +1394,24 @@ static int setup_out_convert(struct impl *this) this->cpu_flags, out->conv.cpu_flags, out->conv.is_passthrough); - if (this->props.dither_noise > 0) { - 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; + return 0; +} - if ((res = dither_init(&this->dither)) < 0) - return res; +static int setup_dither(struct impl *this) +{ + struct dir *out = &this->dir[SPA_DIRECTION_OUTPUT]; + int res; - spa_log_info(this->log, "%p: dither noise:%d quantize:%d", this, - this->props.dither_noise, this->dither.quantize); - } + this->dither.quantize = calc_width(&out->format) * 8; + this->dither.n_channels = out->format.info.raw.channels; + this->dither.cpu_flags = this->cpu_flags; + + if ((res = dither_init(&this->dither)) < 0) + return res; + + spa_log_info(this->log, "%p:got dither %08x:%08x noise:%d quantize:%d", this, + this->cpu_flags, this->dither.cpu_flags, + this->dither.noise, this->dither.quantize); return 0; } @@ -1453,6 +1457,8 @@ static int setup_convert(struct impl *this) return res; if ((res = setup_out_convert(this)) < 0) return res; + if ((res = setup_dither(this)) < 0) + return res; for (i = 0; i < MAX_PORTS; i++) { this->tmp_datas[0][i] = SPA_PTROFF(this->tmp, this->empty_size * i, void); diff --git a/spa/plugins/audioconvert/dither-ops.c b/spa/plugins/audioconvert/dither-ops.c index ee9d039c9..70ea32e75 100644 --- a/spa/plugins/audioconvert/dither-ops.c +++ b/spa/plugins/audioconvert/dither-ops.c @@ -45,7 +45,7 @@ static const struct dither_info { } dither_table[] = { #if defined (HAVE_SSE2) - { dither_f32_sse2, 0 }, + { dither_f32_sse2, SPA_CPU_FLAG_SSE, }, #endif { dither_f32_c, 0 }, }; @@ -74,12 +74,16 @@ int dither_init(struct dither *d) { const struct dither_info *info; size_t i; + uint32_t scale; info = find_dither_info(d->cpu_flags); if (info == NULL) return -ENOTSUP; - d->scale = 1.0f / powf(2.0f, 31 + d->quantize); + scale = d->quantize; + scale -= SPA_MIN(scale, d->noise); + + d->scale = 1.0f / powf(2.0f, 31 + scale); d->dither_size = DITHER_SIZE; d->dither = calloc(d->dither_size + DITHER_OPS_MAX_OVERREAD + @@ -90,6 +94,8 @@ int dither_init(struct dither *d) for (i = 0; i < SPA_N_ELEMENTS(d->random); i++) d->random[i] = random(); + d->cpu_flags = info->cpu_flags; + d->free = impl_dither_free; d->process = info->process; return 0; diff --git a/spa/plugins/audioconvert/dither-ops.h b/spa/plugins/audioconvert/dither-ops.h index 7f0f9bc60..46feb4d69 100644 --- a/spa/plugins/audioconvert/dither-ops.h +++ b/spa/plugins/audioconvert/dither-ops.h @@ -34,6 +34,7 @@ struct dither { uint32_t quantize; + uint32_t noise; #define DITHER_METHOD_NONE 0 #define DITHER_METHOD_RECTANGULAR 2 #define DITHER_METHOD_TRIANGULAR 3 diff --git a/spa/plugins/audioconvert/resample-native.c b/spa/plugins/audioconvert/resample-native.c index f522d67e2..269f47195 100644 --- a/spa/plugins/audioconvert/resample-native.c +++ b/spa/plugins/audioconvert/resample-native.c @@ -396,10 +396,9 @@ int resample_native_init(struct resample *r) build_filter(d->filter, d->filter_stride, n_taps, n_phases, scale); d->info = find_resample_info(SPA_AUDIO_FORMAT_F32, r->cpu_flags); - if (SPA_UNLIKELY(!d->info)) - { + if (SPA_UNLIKELY(d->info == NULL)) { spa_log_error(r->log, "failed to find suitable resample format!"); - return -1; + return -ENOTSUP; } spa_log_debug(r->log, "native %p: q:%d in:%d out:%d n_taps:%d n_phases:%d features:%08x:%08x", diff --git a/spa/plugins/audioconvert/volume-ops.c b/spa/plugins/audioconvert/volume-ops.c index 32a0d22cb..42de61afe 100644 --- a/spa/plugins/audioconvert/volume-ops.c +++ b/spa/plugins/audioconvert/volume-ops.c @@ -73,6 +73,7 @@ int volume_init(struct volume *vol) if (info == NULL) return -ENOTSUP; + vol->cpu_flags = info->cpu_flags; vol->free = impl_volume_free; vol->process = info->process; return 0;