resample: limit the amount of phases

If we have in and out rates with a very small GCD, we might end up with
a lot of phases. Limit the number of phases to 1024 and switch to
interpolating mode. 1024 phases is enough to accurately interpolate
from.

Together with the MAX_TAPS limit we will never create a filter
size that overflows 32 bits.

Fixes #5073
This commit is contained in:
Wim Taymans 2026-01-15 12:05:07 +01:00
parent 8eb60b132c
commit 429505e91c
2 changed files with 9 additions and 3 deletions

View file

@ -47,6 +47,7 @@ struct native_data {
float *filter;
float *hist_mem;
const struct resample_info *info;
bool force_inter;
};
#define DEFINE_RESAMPLER(type,arch) \

View file

@ -13,6 +13,9 @@
SPA_LOG_TOPIC_DEFINE(resample_log_topic, "spa.resample");
#define MAX_TAPS (1u<<18)
#define MAX_PHASES 1024u
struct quality {
uint32_t n_taps;
double cutoff;
@ -148,7 +151,7 @@ static void impl_native_update_rate(struct resample *r, double rate)
in_rate = r->i_rate;
out_rate = r->o_rate;
if (rate != 1.0) {
if (rate != 1.0 || data->force_inter) {
in_rate = (uint32_t)(in_rate / rate);
data->func = data->info->process_inter;
}
@ -362,16 +365,17 @@ int resample_native_init(struct resample *r)
/* multiple of 8 taps to ease simd optimizations */
n_taps = SPA_ROUND_UP_N((uint32_t)ceil(q->n_taps / scale), 8);
n_taps = SPA_MIN(n_taps, 1u << 18);
n_taps = SPA_MIN(n_taps, MAX_TAPS);
/* try to get at least 256 phases so that interpolation is
* accurate enough when activated */
n_phases = out_rate;
n_phases = SPA_MIN(MAX_PHASES, out_rate);
oversample = (255 + n_phases) / n_phases;
n_phases *= oversample;
filter_stride = SPA_ROUND_UP_N(n_taps * sizeof(float), 64);
filter_size = filter_stride * (n_phases + 1);
history_stride = SPA_ROUND_UP_N(2 * n_taps * sizeof(float), 64);
history_size = r->channels * history_stride;
@ -389,6 +393,7 @@ int resample_native_init(struct resample *r)
d->n_phases = n_phases;
d->in_rate = in_rate;
d->out_rate = out_rate;
d->force_inter = out_rate > n_phases;
d->gcd = gcd;
d->pm = (float)n_phases / r->o_rate;
d->filter = SPA_PTROFF_ALIGN(d, sizeof(struct native_data), 64, float);