From 61750813ffc50305bae7f437d5f581b79376fd0c Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Tue, 13 Dec 2022 12:18:46 +0100 Subject: [PATCH] filter-chain: move buffer resample to separate function Fix the error paths. Rename some variables around to make things clearer. --- .../module-filter-chain/builtin_plugin.c | 110 +++++++++++------- 1 file changed, 69 insertions(+), 41 deletions(-) diff --git a/src/modules/module-filter-chain/builtin_plugin.c b/src/modules/module-filter-chain/builtin_plugin.c index b3f180c2a..49163686e 100644 --- a/src/modules/module-filter-chain/builtin_plugin.c +++ b/src/modules/module-filter-chain/builtin_plugin.c @@ -31,6 +31,7 @@ #endif #include +#include #include #include @@ -540,6 +541,71 @@ static float *create_dirac(const char *filename, float gain, int delay, int offs return samples; } +static float *resample_buffer(float *samples, int *n_samples, + unsigned long in_rate, unsigned long out_rate, uint32_t quality) +{ + uint32_t in_len, out_len, total_out = 0; + int out_n_samples; + float *out_samples, *out_buf, *in_buf; + struct resample r; + int res; + + spa_zero(r); + r.channels = 1; + r.i_rate = in_rate; + r.o_rate = out_rate; + r.cpu_flags = dsp_ops.cpu_flags; + r.quality = quality; + if ((res = resample_native_init(&r)) < 0) { + pw_log_error("resampling failed: %s", spa_strerror(res)); + errno = -res; + return NULL; + } + + out_n_samples = SPA_ROUND_UP(*n_samples * out_rate, in_rate) / in_rate; + out_samples = calloc(out_n_samples, sizeof(float)); + if (out_samples == NULL) + goto error; + + in_len = *n_samples; + in_buf = samples; + out_len = out_n_samples; + out_buf = out_samples; + + pw_log_info("Resampling filter: rate: %lu => %lu, n_samples: %u => %u, q:%u", + in_rate, out_rate, in_len, out_len, quality); + + resample_process(&r, (void*)&in_buf, &in_len, (void*)&out_buf, &out_len); + pw_log_debug("resampled: %u -> %u samples", in_len, out_len); + total_out += out_len; + + in_len = resample_delay(&r); + in_buf = calloc(in_len, sizeof(float)); + if (in_buf == NULL) + goto error; + + out_buf = out_samples + total_out; + out_len = out_n_samples - total_out; + + pw_log_debug("flushing resampler: %u in %u out", in_len, out_len); + resample_process(&r, (void*)&in_buf, &in_len, (void*)&out_buf, &out_len); + pw_log_debug("flushed: %u -> %u samples", in_len, out_len); + total_out += out_len; + + free(in_buf); + free(samples); + resample_free(&r); + + *n_samples = total_out; + return out_samples; + +error: + resample_free(&r); + free(samples); + free(out_samples); + return NULL; +} + static void * convolver_instantiate(const struct fc_descriptor * Descriptor, unsigned long SampleRate, int index, const char *config) { @@ -642,47 +708,9 @@ static void * convolver_instantiate(const struct fc_descriptor * Descriptor, rate = SampleRate; samples = read_samples(filename, gain, delay, offset, length, channel, &rate, &n_samples); - if (rate != SampleRate) { - float *in_buffer = samples; - uint32_t in_len = n_samples; - uint32_t out_len = SPA_ROUND_UP(in_len * SampleRate, rate) / rate; - samples = calloc(out_len, sizeof(float)); - - pw_log_info( - "Resampling filter: rate: %lu => %lu, n_samples: %d => %d, q: %d", - rate, SampleRate, n_samples, out_len, resample_quality - ); - - struct resample r; - spa_zero(r); - r.channels = 1; - r.i_rate = rate; - r.o_rate = SampleRate; - r.quality = resample_quality; - if (resample_native_init(&r) < 0) { - pw_log_error("resampling failed"); - return NULL; - } - - n_samples = out_len; - rate = SampleRate; - - resample_process(&r, (void *)&in_buffer, &in_len, (void *)&samples, &out_len); - pw_log_debug("resampled: %u samples out", out_len); - - free(in_buffer); - - in_len = resample_delay(&r); - in_buffer = calloc(in_len, sizeof(float)); - - void *out_padded = samples + out_len; - out_len = n_samples - out_len; // Available space in buffer - pw_log_debug("flushing resampler: %u in %u out", in_len, out_len); - resample_process(&r, (void *)&in_buffer, &in_len, &out_padded, &out_len); - - free(in_buffer); - r.free(&r); - } + if (rate != SampleRate) + samples = resample_buffer(samples, &n_samples, + rate, SampleRate, resample_quality); } if (samples == NULL) { errno = ENOENT;