resampler: Precompute some common filter coefficients

While this is quite fast on x86 (order of a few microseconds), the
computation can take a few milliseconds on ARM (measured at 1.9ms (32000
-> 48000) and 3.3ms (32000 -> 44100) on a Cortex A53).

Let's precompute some common rates so that we can avoid this overhead on
each stream (or any other audioconvert) instantiation. The approach
taken here is to write a little program to create the resampler
instance, and run that on the host at compile-time to generate some
common rate conversions.
This commit is contained in:
Arun Raghavan 2024-08-07 12:30:10 -04:00
parent 46f89d8009
commit 70a7bae5d7
5 changed files with 260 additions and 1 deletions

View file

@ -7,6 +7,9 @@
#include <spa/param/audio/format.h>
#include "resample-native-impl.h"
#ifndef RESAMPLE_DISABLE_PRECOMP
#include "resample-native-precomp.h"
#endif
struct quality {
uint32_t n_taps;
@ -375,7 +378,25 @@ int resample_native_init(struct resample *r)
for (c = 0; c < r->channels; c++)
d->history[c] = SPA_PTROFF(d->hist_mem, c * history_stride, float);
build_filter(d->filter, d->filter_stride, n_taps, n_phases, scale);
#ifndef RESAMPLE_DISABLE_PRECOMP
/* See if we have precomputed coefficients */
for (c = 0; precomp_coeffs[c].filter; c++) {
if (precomp_coeffs[c].in_rate == r->i_rate &&
precomp_coeffs[c].out_rate == r->o_rate &&
precomp_coeffs[c].quality == r->quality)
break;
}
if (precomp_coeffs[c].filter) {
spa_log_debug(r->log, "using precomputed filter for %u->%u(%u)",
r->i_rate, r->o_rate, r->quality);
spa_memcpy(d->filter, precomp_coeffs[c].filter, filter_size);
} else {
#endif
build_filter(d->filter, d->filter_stride, n_taps, n_phases, scale);
#ifndef RESAMPLE_DISABLE_PRECOMP
}
#endif
d->info = find_resample_info(SPA_AUDIO_FORMAT_F32, r->cpu_flags);
if (SPA_UNLIKELY(d->info == NULL)) {