audioconvert: add dither noise even on empty input

When we are asked to add noise bits, don't call the clear function.

Make the passthrough and clear-on-empty flags available with a new flag
field to make it more extensible.

Fixes #5260
This commit is contained in:
Wim Taymans 2026-05-14 11:19:02 +02:00
parent 4f975d0071
commit 61431dcbc0
3 changed files with 17 additions and 11 deletions

View file

@ -2176,8 +2176,8 @@ static int setup_in_convert(struct impl *this)
if ((res = convert_init(&in->conv)) < 0)
return res;
spa_log_debug(this->log, "%p: got converter features %08x:%08x passthrough:%d remap:%d %s", this,
this->cpu_flags, in->conv.func_cpu_flags, in->conv.is_passthrough,
spa_log_debug(this->log, "%p: got converter features %08x:%08x flags:%08x remap:%d %s", this,
this->cpu_flags, in->conv.func_cpu_flags, in->conv.flags,
remap, in->conv.func_name);
return 0;
@ -2478,9 +2478,9 @@ static int setup_out_convert(struct impl *this)
return res;
spa_log_debug(this->log, "%p: got converter features %08x:%08x quant:%d:%d"
" passthrough:%d remap:%d %s", this,
" flags:%08x remap:%d %s", this,
this->cpu_flags, out->conv.func_cpu_flags, out->conv.method,
out->conv.noise_bits, out->conv.is_passthrough, remap, out->conv.func_name);
out->conv.noise_bits, out->conv.flags, remap, out->conv.func_name);
return 0;
}
@ -3643,7 +3643,7 @@ static void run_src_convert_stage(struct stage *s, struct stage_context *c)
} else {
dst = c->datas[s->out_idx];
}
if (c->empty && dir->conv.clear)
if (c->empty && dir->conv.clear && convert_is_clear_on_empty(&dir->conv))
convert_clear(&dir->conv, dst, c->n_samples);
else
convert_process(&dir->conv, dst, (const void**)c->datas[s->in_idx], c->n_samples);
@ -3757,7 +3757,7 @@ static void run_dst_convert_stage(struct stage *s, struct stage_context *c)
struct dir *dir = &impl->dir[SPA_DIRECTION_OUTPUT];
void *remap_datas[MAX_PORTS], **src;
spa_log_trace_fp(impl->log, "%p: output convert %d", impl, c->n_samples);
spa_log_trace_fp(impl->log, "%p: output convert %d %d", impl, c->n_samples, c->empty);
if (dir->need_remap) {
uint32_t i;
for (i = 0; i < dir->conv.n_channels; i++) {
@ -3768,7 +3768,7 @@ static void run_dst_convert_stage(struct stage *s, struct stage_context *c)
} else {
src = c->datas[s->in_idx];
}
if (c->empty && dir->conv.clear)
if (c->empty && dir->conv.clear && convert_is_clear_on_empty(&dir->conv))
convert_clear(&dir->conv, c->datas[s->out_idx], c->n_samples);
else
convert_process(&dir->conv, c->datas[s->out_idx], (const void **)src, c->n_samples);
@ -3805,11 +3805,11 @@ static void recalc_stages(struct impl *this, struct stage_context *ctx)
/* set bits for things we need to do */
dir = &this->dir[SPA_DIRECTION_INPUT];
SPA_FLAG_UPDATE(ctx->bits, SRC_CONVERT_BIT, !dir->conv.is_passthrough);
SPA_FLAG_UPDATE(ctx->bits, SRC_CONVERT_BIT, !convert_is_passthrough(&dir->conv));
in_need_remap = dir->need_remap;
dir = &this->dir[SPA_DIRECTION_OUTPUT];
SPA_FLAG_UPDATE(ctx->bits, DST_CONVERT_BIT, !dir->conv.is_passthrough);
SPA_FLAG_UPDATE(ctx->bits, DST_CONVERT_BIT, !convert_is_passthrough(&dir->conv));
out_need_remap = dir->need_remap;
this->resample_passthrough = resample_is_passthrough(this);

View file

@ -640,7 +640,8 @@ int convert_init(struct convert *conv)
for (i = 0; i < RANDOM_SIZE; i++)
conv->random[i] = random();
conv->is_passthrough = conv->src_fmt == conv->dst_fmt;
SPA_FLAG_UPDATE(conv->flags, CONVERT_FLAG_CLEAR_ON_EMPTY, conv->noise_bits == 0);
SPA_FLAG_UPDATE(conv->flags, CONVERT_FLAG_PASSTHROUGH, conv->src_fmt == conv->dst_fmt);
conv->func_cpu_flags = info->cpu_flags;
conv->update_noise = ninfo->noise;
conv->process = info->process;

View file

@ -222,7 +222,9 @@ struct convert {
uint32_t func_cpu_flags;
const char *func_name;
unsigned int is_passthrough:1;
#define CONVERT_FLAG_PASSTHROUGH (1u<<0)
#define CONVERT_FLAG_CLEAR_ON_EMPTY (1u<<1)
uint32_t flags;
float scale;
uint32_t *random;
@ -283,6 +285,9 @@ static inline uint32_t dither_method_from_label(const char *label)
#define convert_clear(conv,...) (conv)->clear(conv, __VA_ARGS__)
#define convert_free(conv) (conv)->free(conv)
#define convert_is_passthrough(conv) SPA_FLAG_IS_SET((conv)->flags, CONVERT_FLAG_PASSTHROUGH)
#define convert_is_clear_on_empty(conv) SPA_FLAG_IS_SET((conv)->flags, CONVERT_FLAG_CLEAR_ON_EMPTY)
#define DEFINE_NOISE_FUNCTION(name,arch) \
void conv_noise_##name##_##arch(struct convert *conv, float *noise, \
uint32_t n_samples)