mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-03 09:01:54 -05:00
resample: keep fractional part of in_rate when interpolating
When interpolating with rate correction != 1.0, don't floor the resulting input rate to the nearest smallest integer. This allows rate corrections < 1/in_rate to have some effect, and reduces jumps in the response. One of the jumps is inconveniently between rate=1.0 and rate=1.0+eps and will cause rate corrections to oscillate if target rate varies close to 1.0.
This commit is contained in:
parent
244d5a1cc1
commit
847982eb0e
2 changed files with 11 additions and 10 deletions
|
|
@ -39,7 +39,7 @@ struct native_data {
|
||||||
double rate;
|
double rate;
|
||||||
uint32_t n_taps;
|
uint32_t n_taps;
|
||||||
uint32_t n_phases;
|
uint32_t n_phases;
|
||||||
uint32_t in_rate;
|
struct fixp in_rate;
|
||||||
uint32_t out_rate;
|
uint32_t out_rate;
|
||||||
struct fixp phase;
|
struct fixp phase;
|
||||||
float pm;
|
float pm;
|
||||||
|
|
|
||||||
|
|
@ -137,24 +137,25 @@ static inline uint32_t calc_gcd(uint32_t a, uint32_t b)
|
||||||
static void impl_native_update_rate(struct resample *r, double rate)
|
static void impl_native_update_rate(struct resample *r, double rate)
|
||||||
{
|
{
|
||||||
struct native_data *data = r->data;
|
struct native_data *data = r->data;
|
||||||
uint32_t in_rate, out_rate;
|
struct fixp in_rate;
|
||||||
|
uint32_t out_rate;
|
||||||
|
|
||||||
if (SPA_LIKELY(data->rate == rate))
|
if (SPA_LIKELY(data->rate == rate))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
data->rate = rate;
|
data->rate = rate;
|
||||||
in_rate = r->i_rate;
|
in_rate = UINT32_TO_FIXP(r->i_rate);
|
||||||
out_rate = r->o_rate;
|
out_rate = r->o_rate;
|
||||||
|
|
||||||
if (rate != 1.0) {
|
if (rate != 1.0) {
|
||||||
in_rate = (uint32_t)(in_rate / rate);
|
in_rate.value = (uint64_t)round(in_rate.value / rate);
|
||||||
data->func = data->info->process_inter;
|
data->func = data->info->process_inter;
|
||||||
}
|
}
|
||||||
else if (in_rate == out_rate) {
|
else if (in_rate.value == UINT32_TO_FIXP(out_rate).value) {
|
||||||
data->func = data->info->process_copy;
|
data->func = data->info->process_copy;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
in_rate /= data->gcd;
|
in_rate.value /= data->gcd;
|
||||||
out_rate /= data->gcd;
|
out_rate /= data->gcd;
|
||||||
data->func = data->info->process_full;
|
data->func = data->info->process_full;
|
||||||
}
|
}
|
||||||
|
|
@ -169,8 +170,8 @@ static void impl_native_update_rate(struct resample *r, double rate)
|
||||||
data->in_rate = in_rate;
|
data->in_rate = in_rate;
|
||||||
data->out_rate = out_rate;
|
data->out_rate = out_rate;
|
||||||
|
|
||||||
data->inc = in_rate / out_rate;
|
data->inc = in_rate.value / UINT32_TO_FIXP(out_rate).value;
|
||||||
data->frac = UINT32_TO_FIXP(in_rate % out_rate);
|
data->frac.value = in_rate.value % UINT32_TO_FIXP(out_rate).value;
|
||||||
|
|
||||||
spa_log_trace_fp(r->log, "native %p: rate:%f in:%d out:%d phase:%f inc:%d frac:%f", r,
|
spa_log_trace_fp(r->log, "native %p: rate:%f in:%d out:%d phase:%f inc:%d frac:%f", r,
|
||||||
rate, r->i_rate, r->o_rate, FIXP_TO_FLOAT(data->phase),
|
rate, r->i_rate, r->o_rate, FIXP_TO_FLOAT(data->phase),
|
||||||
|
|
@ -206,7 +207,7 @@ static uint32_t impl_native_out_len(struct resample *r, uint32_t in_len)
|
||||||
|
|
||||||
in_len = in_len - SPA_MIN(in_len, data->n_taps - data->hist);
|
in_len = in_len - SPA_MIN(in_len, data->n_taps - data->hist);
|
||||||
out_len = in_len * data->out_rate - FIXP_TO_UINT32(data->phase);
|
out_len = in_len * data->out_rate - FIXP_TO_UINT32(data->phase);
|
||||||
out_len = (out_len + data->in_rate - 1) / data->in_rate;
|
out_len = (UINT32_TO_FIXP(out_len).value + data->in_rate.value - 1) / data->in_rate.value;
|
||||||
|
|
||||||
spa_log_trace_fp(r->log, "native %p: hist:%d %d->%d", r, data->hist, in_len, out_len);
|
spa_log_trace_fp(r->log, "native %p: hist:%d %d->%d", r, data->hist, in_len, out_len);
|
||||||
|
|
||||||
|
|
@ -399,7 +400,7 @@ int resample_native_init(struct resample *r)
|
||||||
r->data = d;
|
r->data = d;
|
||||||
d->n_taps = n_taps;
|
d->n_taps = n_taps;
|
||||||
d->n_phases = n_phases;
|
d->n_phases = n_phases;
|
||||||
d->in_rate = in_rate;
|
d->in_rate = UINT32_TO_FIXP(in_rate);
|
||||||
d->out_rate = out_rate;
|
d->out_rate = out_rate;
|
||||||
d->gcd = gcd;
|
d->gcd = gcd;
|
||||||
d->pm = (float)n_phases / r->o_rate / FIXP_SCALE;
|
d->pm = (float)n_phases / r->o_rate / FIXP_SCALE;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue