From 63e283f377edafe4df2557198bcb38b058b8fea1 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Mon, 15 Jan 2024 15:03:54 +0100 Subject: [PATCH] audioconvert: update initial resampler rate match When starting the converter, calculate the initial size needed by the resampler to fill one quantum. This makes it possible to get the requested amount of samples before the first process call is made. --- spa/plugins/audioconvert/audioconvert.c | 98 +++++++++++++------------ 1 file changed, 53 insertions(+), 45 deletions(-) diff --git a/spa/plugins/audioconvert/audioconvert.c b/spa/plugins/audioconvert/audioconvert.c index 5d7ff1f2b..789af5af4 100644 --- a/spa/plugins/audioconvert/audioconvert.c +++ b/spa/plugins/audioconvert/audioconvert.c @@ -1813,10 +1813,53 @@ static int ensure_tmp(struct impl *this, uint32_t maxsize, uint32_t maxports) return 0; } +static uint32_t resample_update_rate_match(struct impl *this, bool passthrough, uint32_t out_size, uint32_t in_queued) +{ + uint32_t delay, match_size; + + if (passthrough) { + delay = 0; + match_size = out_size; + } else { + double rate = this->rate_scale / this->props.rate; + if (this->io_rate_match && + SPA_FLAG_IS_SET(this->io_rate_match->flags, SPA_IO_RATE_MATCH_FLAG_ACTIVE)) + rate *= this->io_rate_match->rate; + resample_update_rate(&this->resample, rate); + delay = resample_delay(&this->resample); + match_size = resample_in_len(&this->resample, out_size); + } + match_size -= SPA_MIN(match_size, in_queued); + + spa_log_trace_fp(this->log, "%p: next match %u", this, match_size); + + if (this->io_rate_match) { + this->io_rate_match->delay = delay + in_queued; + this->io_rate_match->size = match_size; + } + return match_size; +} + +static inline bool resample_is_passthrough(struct impl *this) +{ + if (this->props.resample_disabled) + return true; + if (this->resample.i_rate != this->resample.o_rate) + return false; + if (this->rate_scale != 1.0) + return false; + if (this->rate_adjust) + return false; + if (this->io_rate_match != NULL && + SPA_FLAG_IS_SET(this->io_rate_match->flags, SPA_IO_RATE_MATCH_FLAG_ACTIVE)) + return false; + return true; +} + static int setup_convert(struct impl *this) { struct dir *in, *out; - uint32_t i, rate, maxsize, maxports; + uint32_t i, rate, maxsize, maxports, duration; struct port *p; int res; @@ -1832,7 +1875,13 @@ static int setup_convert(struct impl *this) if (!in->have_format || !out->have_format) return -EINVAL; - rate = this->io_position ? this->io_position->clock.target_rate.denom : DEFAULT_RATE; + if (this->io_position != NULL) { + rate = this->io_position->clock.target_rate.denom; + duration = this->io_position->clock.target_duration; + } else { + rate = DEFAULT_RATE; + duration = this->quantum_limit; + } /* in DSP mode we always convert to the DSP rate */ if (in->mode == SPA_PARAM_PORT_CONFIG_MODE_dsp) @@ -1879,6 +1928,8 @@ static int setup_convert(struct impl *this) if ((res = ensure_tmp(this, maxsize, maxports)) < 0) return res; + resample_update_rate_match(this, resample_is_passthrough(this), duration, 0); + this->setup = true; emit_node_info(this, false); @@ -2736,49 +2787,6 @@ static inline uint32_t resample_get_in_size(struct impl *this, bool passthrough, return match_size; } -static uint32_t resample_update_rate_match(struct impl *this, bool passthrough, uint32_t out_size, uint32_t in_queued) -{ - uint32_t delay, match_size; - - if (passthrough) { - delay = 0; - match_size = out_size; - } else { - double rate = this->rate_scale / this->props.rate; - if (this->io_rate_match && - SPA_FLAG_IS_SET(this->io_rate_match->flags, SPA_IO_RATE_MATCH_FLAG_ACTIVE)) - rate *= this->io_rate_match->rate; - resample_update_rate(&this->resample, rate); - delay = resample_delay(&this->resample); - match_size = resample_in_len(&this->resample, out_size); - } - match_size -= SPA_MIN(match_size, in_queued); - - spa_log_trace_fp(this->log, "%p: next match %u", this, match_size); - - if (this->io_rate_match) { - this->io_rate_match->delay = delay + in_queued; - this->io_rate_match->size = match_size; - } - return match_size; -} - -static inline bool resample_is_passthrough(struct impl *this) -{ - if (this->props.resample_disabled) - return true; - if (this->resample.i_rate != this->resample.o_rate) - return false; - if (this->rate_scale != 1.0) - return false; - if (this->rate_adjust) - return false; - if (this->io_rate_match != NULL && - SPA_FLAG_IS_SET(this->io_rate_match->flags, SPA_IO_RATE_MATCH_FLAG_ACTIVE)) - return false; - return true; -} - static uint64_t get_time_ns(struct impl *impl) { struct timespec now;