audioconvert: add dither noise setting in dither struct

Move the noise setting in the dither struct so that it can be
handled separately.
Setup dither separately.
Set used cpu_flags in structures after setup.
This commit is contained in:
Wim Taymans 2022-06-28 10:52:31 +02:00
parent b7e26002be
commit b5e0151cc0
5 changed files with 33 additions and 20 deletions

View file

@ -93,7 +93,6 @@ struct props {
unsigned int resample_quality; unsigned int resample_quality;
unsigned int resample_disabled:1; unsigned int resample_disabled:1;
double rate; double rate;
uint32_t dither_noise;
}; };
static void props_reset(struct props *props) static void props_reset(struct props *props)
@ -110,7 +109,6 @@ static void props_reset(struct props *props)
props->rate = 1.0; props->rate = 1.0;
props->resample_quality = RESAMPLE_DEFAULT_QUALITY; props->resample_quality = RESAMPLE_DEFAULT_QUALITY;
props->resample_disabled = false; props->resample_disabled = false;
props->dither_noise = 0;
} }
struct buffer { struct buffer {
@ -614,7 +612,7 @@ static int impl_node_enum_params(void *object, int seq,
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 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)); SPA_PROP_INFO_params, SPA_POD_Bool(true));
break; break;
default: 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_string(&b, "resample.disable");
spa_pod_builder_bool(&b, p->resample_disabled); spa_pod_builder_bool(&b, p->resample_disabled);
spa_pod_builder_string(&b, "dither.noise"); 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]); spa_pod_builder_pop(&b, &f[1]);
param = spa_pod_builder_pop(&b, &f[0]); param = spa_pod_builder_pop(&b, &f[0]);
break; 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")) else if (spa_streq(k, "resample.disable"))
this->props.resample_disabled = spa_atob(s); this->props.resample_disabled = spa_atob(s);
else if (spa_streq(k, "dither.noise")) else if (spa_streq(k, "dither.noise"))
spa_atou32(s, &this->props.dither_noise, 0); spa_atou32(s, &this->dither.noise, 0);
else else
return 0; return 0;
return 1; 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); this->cpu_flags, out->conv.cpu_flags, out->conv.is_passthrough);
if (this->props.dither_noise > 0) { return 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;
if ((res = dither_init(&this->dither)) < 0) static int setup_dither(struct impl *this)
return res; {
struct dir *out = &this->dir[SPA_DIRECTION_OUTPUT];
int res;
spa_log_info(this->log, "%p: dither noise:%d quantize:%d", this, this->dither.quantize = calc_width(&out->format) * 8;
this->props.dither_noise, this->dither.quantize); 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; return 0;
} }
@ -1453,6 +1457,8 @@ static int setup_convert(struct impl *this)
return res; return res;
if ((res = setup_out_convert(this)) < 0) if ((res = setup_out_convert(this)) < 0)
return res; return res;
if ((res = setup_dither(this)) < 0)
return res;
for (i = 0; i < MAX_PORTS; i++) { for (i = 0; i < MAX_PORTS; i++) {
this->tmp_datas[0][i] = SPA_PTROFF(this->tmp, this->empty_size * i, void); this->tmp_datas[0][i] = SPA_PTROFF(this->tmp, this->empty_size * i, void);

View file

@ -45,7 +45,7 @@ static const struct dither_info {
} dither_table[] = } dither_table[] =
{ {
#if defined (HAVE_SSE2) #if defined (HAVE_SSE2)
{ dither_f32_sse2, 0 }, { dither_f32_sse2, SPA_CPU_FLAG_SSE, },
#endif #endif
{ dither_f32_c, 0 }, { dither_f32_c, 0 },
}; };
@ -74,12 +74,16 @@ int dither_init(struct dither *d)
{ {
const struct dither_info *info; const struct dither_info *info;
size_t i; size_t i;
uint32_t scale;
info = find_dither_info(d->cpu_flags); info = find_dither_info(d->cpu_flags);
if (info == NULL) if (info == NULL)
return -ENOTSUP; 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_size = DITHER_SIZE;
d->dither = calloc(d->dither_size + DITHER_OPS_MAX_OVERREAD + 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++) for (i = 0; i < SPA_N_ELEMENTS(d->random); i++)
d->random[i] = random(); d->random[i] = random();
d->cpu_flags = info->cpu_flags;
d->free = impl_dither_free; d->free = impl_dither_free;
d->process = info->process; d->process = info->process;
return 0; return 0;

View file

@ -34,6 +34,7 @@
struct dither { struct dither {
uint32_t quantize; uint32_t quantize;
uint32_t noise;
#define DITHER_METHOD_NONE 0 #define DITHER_METHOD_NONE 0
#define DITHER_METHOD_RECTANGULAR 2 #define DITHER_METHOD_RECTANGULAR 2
#define DITHER_METHOD_TRIANGULAR 3 #define DITHER_METHOD_TRIANGULAR 3

View file

@ -396,10 +396,9 @@ int resample_native_init(struct resample *r)
build_filter(d->filter, d->filter_stride, n_taps, n_phases, scale); build_filter(d->filter, d->filter_stride, n_taps, n_phases, scale);
d->info = find_resample_info(SPA_AUDIO_FORMAT_F32, r->cpu_flags); 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!"); 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", spa_log_debug(r->log, "native %p: q:%d in:%d out:%d n_taps:%d n_phases:%d features:%08x:%08x",

View file

@ -73,6 +73,7 @@ int volume_init(struct volume *vol)
if (info == NULL) if (info == NULL)
return -ENOTSUP; return -ENOTSUP;
vol->cpu_flags = info->cpu_flags;
vol->free = impl_volume_free; vol->free = impl_volume_free;
vol->process = info->process; vol->process = info->process;
return 0; return 0;