filter-chain: move dsp_ops pointers to dynamically allocated memory

Make a plugin structure that is dynamically allocated for each plugin
and pass it around to the descriptor instance structures, so that they
all have access to dsp_ops without sharing a static pointer.

The problem with the static pointer is that the dsp_ops structure is
actually allocated in module-filter-chain's instance structure,
so it always points to the instance of the last filter-chain that was
loaded in the process. When this is unloaded, the other filter-chains
crash.
This commit is contained in:
George Kiagiadakis 2024-11-06 20:11:40 +02:00 committed by Wim Taymans
parent b2dd733520
commit c7854e1da4
7 changed files with 135 additions and 103 deletions

View file

@ -2433,6 +2433,7 @@ static int graph_instantiate(struct graph *graph)
struct link *link;
struct descriptor *desc;
const struct fc_descriptor *d;
const struct fc_plugin *p;
uint32_t i, j, max_samples = impl->quantum_limit;
int res;
float *sd, *dd;
@ -2448,11 +2449,12 @@ static int graph_instantiate(struct graph *graph)
desc = node->desc;
d = desc->desc;
p = desc->plugin->plugin;
for (i = 0; i < node->n_hndl; i++) {
pw_log_info("instantiate %s %s[%d] rate:%lu", d->name, node->name, i, impl->rate);
errno = EINVAL;
if ((node->hndl[i] = d->instantiate(d, impl->rate, i, node->config)) == NULL) {
if ((node->hndl[i] = d->instantiate(p, d, impl->rate, i, node->config)) == NULL) {
pw_log_error("cannot create plugin instance %d rate:%lu: %m", i, impl->rate);
res = -errno;
goto error;

View file

@ -28,9 +28,13 @@
#define MAX_RATES 32u
static struct dsp_ops *dsp_ops;
struct plugin {
struct fc_plugin plugin;
struct dsp_ops *dsp_ops;
};
struct builtin {
struct plugin *plugin;
unsigned long rate;
float *port[64];
@ -44,7 +48,7 @@ struct builtin {
float accum;
};
static void *builtin_instantiate(const struct fc_descriptor * Descriptor,
static void *builtin_instantiate(const struct fc_plugin *plugin, const struct fc_descriptor * Descriptor,
unsigned long SampleRate, int index, const char *config)
{
struct builtin *impl;
@ -53,6 +57,7 @@ static void *builtin_instantiate(const struct fc_descriptor * Descriptor,
if (impl == NULL)
return NULL;
impl->plugin = (struct plugin *) plugin;
impl->rate = SampleRate;
return impl;
@ -75,7 +80,7 @@ static void copy_run(void * Instance, unsigned long SampleCount)
{
struct builtin *impl = Instance;
float *in = impl->port[1], *out = impl->port[0];
dsp_ops_copy(dsp_ops, out, in, SampleCount);
dsp_ops_copy(impl->plugin->dsp_ops, out, in, SampleCount);
}
static struct fc_port copy_ports[] = {
@ -124,7 +129,7 @@ static void mixer_run(void * Instance, unsigned long SampleCount)
src[n_src] = in;
gains[n_src++] = gain;
}
dsp_ops_mix_gain(dsp_ops, out, src, gains, n_src, SampleCount);
dsp_ops_mix_gain(impl->plugin->dsp_ops, out, src, gains, n_src, SampleCount);
}
static struct fc_port mixer_ports[] = {
@ -300,7 +305,7 @@ static void bq_raw_update(struct builtin *impl, float b0, float b1, float b2,
* ]
* }
*/
static void *bq_instantiate(const struct fc_descriptor * Descriptor,
static void *bq_instantiate(const struct fc_plugin *plugin, const struct fc_descriptor * Descriptor,
unsigned long SampleRate, int index, const char *config)
{
struct builtin *impl;
@ -314,6 +319,7 @@ static void *bq_instantiate(const struct fc_descriptor * Descriptor,
if (impl == NULL)
return NULL;
impl->plugin = (struct plugin *) plugin;
impl->rate = SampleRate;
impl->b0 = impl->a0 = 1.0f;
impl->type = bq_type_from_name(Descriptor->name);
@ -526,7 +532,7 @@ static void bq_run(void *Instance, unsigned long samples)
if (impl->freq != freq || impl->Q != Q || impl->gain != gain)
bq_freq_update(impl, impl->type, freq, Q, gain);
}
dsp_ops_biquad_run(dsp_ops, bq, out, in, samples);
dsp_ops_biquad_run(impl->plugin->dsp_ops, bq, out, in, samples);
}
/** bq_lowpass */
@ -658,6 +664,7 @@ static const struct fc_descriptor bq_raw_desc = {
/** convolve */
struct convolver_impl {
struct plugin *plugin;
unsigned long rate;
float *port[2];
@ -807,7 +814,7 @@ static float *create_dirac(const char *filename, float gain, int rate, float del
return samples;
}
static float *resample_buffer(float *samples, int *n_samples,
static float *resample_buffer(struct dsp_ops *dsp_ops, float *samples, int *n_samples,
unsigned long in_rate, unsigned long out_rate, uint32_t quality)
{
#ifdef HAVE_SPA_PLUGINS
@ -884,7 +891,7 @@ error:
#endif
}
static void * convolver_instantiate(const struct fc_descriptor * Descriptor,
static void * convolver_instantiate(const struct fc_plugin *plugin, const struct fc_descriptor * Descriptor,
unsigned long SampleRate, int index, const char *config)
{
struct convolver_impl *impl;
@ -1003,9 +1010,11 @@ static void * convolver_instantiate(const struct fc_descriptor * Descriptor,
rate = SampleRate;
samples = read_closest(filenames, gain, delay, offset,
length, channel, &rate, &n_samples);
if (samples != NULL && rate != SampleRate)
samples = resample_buffer(samples, &n_samples,
if (samples != NULL && rate != SampleRate) {
struct plugin *p = (struct plugin *) plugin;
samples = resample_buffer(p->dsp_ops, samples, &n_samples,
rate, SampleRate, resample_quality);
}
}
for (i = 0; i < MAX_RATES; i++)
@ -1029,9 +1038,10 @@ static void * convolver_instantiate(const struct fc_descriptor * Descriptor,
if (impl == NULL)
goto error;
impl->plugin = (struct plugin *) plugin;
impl->rate = SampleRate;
impl->conv = convolver_new(dsp_ops, blocksize, tailsize, samples, n_samples);
impl->conv = convolver_new(impl->plugin->dsp_ops, blocksize, tailsize, samples, n_samples);
if (impl->conv == NULL)
goto error;
@ -1099,6 +1109,7 @@ static const struct fc_descriptor convolve_desc = {
/** delay */
struct delay_impl {
struct plugin *plugin;
unsigned long rate;
float *port[4];
@ -1116,7 +1127,7 @@ static void delay_cleanup(void * Instance)
free(impl);
}
static void *delay_instantiate(const struct fc_descriptor * Descriptor,
static void *delay_instantiate(const struct fc_plugin *plugin, const struct fc_descriptor * Descriptor,
unsigned long SampleRate, int index, const char *config)
{
struct delay_impl *impl;
@ -1154,6 +1165,7 @@ static void *delay_instantiate(const struct fc_descriptor * Descriptor,
if (impl == NULL)
return NULL;
impl->plugin = (struct plugin *) plugin;
impl->rate = SampleRate;
impl->buffer_samples = SPA_ROUND_UP_N((uint32_t)(max_delay * impl->rate), 64);
pw_log_info("max-delay:%f seconds rate:%lu samples:%d", max_delay, impl->rate, impl->buffer_samples);
@ -1188,7 +1200,7 @@ static void delay_run(void * Instance, unsigned long SampleCount)
impl->delay_samples = SPA_CLAMP((uint32_t)(delay * impl->rate), 0u, impl->buffer_samples-1);
impl->delay = delay;
}
dsp_ops_delay(dsp_ops, impl->buffer, &impl->ptr, impl->buffer_samples,
dsp_ops_delay(impl->plugin->dsp_ops, impl->buffer, &impl->ptr, impl->buffer_samples,
impl->delay_samples, out, in, SampleCount);
}
@ -1322,7 +1334,7 @@ static void linear_run(void * Instance, unsigned long SampleCount)
float *ctrl = impl->port[3], *notify = impl->port[2];
if (in != NULL && out != NULL)
dsp_ops_linear(dsp_ops, out, in, mult, add, SampleCount);
dsp_ops_linear(impl->plugin->dsp_ops, out, in, mult, add, SampleCount);
if (ctrl != NULL && notify != NULL)
notify[0] = ctrl[0] * mult + add;
@ -1567,7 +1579,7 @@ static void mult_run(void * Instance, unsigned long SampleCount)
src[n_src++] = in;
}
dsp_ops_mult(dsp_ops, out, src, n_src, SampleCount);
dsp_ops_mult(impl->plugin->dsp_ops, out, src, n_src, SampleCount);
}
static struct fc_port mult_ports[] = {
@ -1693,6 +1705,7 @@ static const struct fc_descriptor sine_desc = {
#define PARAM_EQ_MAX 64
struct param_eq_impl {
struct plugin *plugin;
unsigned long rate;
float *port[8*2];
@ -1859,7 +1872,7 @@ static int parse_filters(struct spa_json *iter, int rate, struct biquad *bq, uin
* filtersX = [ ... ] # to load channel X
* }
*/
static void *param_eq_instantiate(const struct fc_descriptor * Descriptor,
static void *param_eq_instantiate(const struct fc_plugin *plugin, const struct fc_descriptor * Descriptor,
unsigned long SampleRate, int index, const char *config)
{
struct spa_json it[3];
@ -1884,6 +1897,7 @@ static void *param_eq_instantiate(const struct fc_descriptor * Descriptor,
if (impl == NULL)
return NULL;
impl->plugin = (struct plugin *) plugin;
impl->rate = SampleRate;
for (i = 0; i < SPA_N_ELEMENTS(impl->bq); i++)
biquad_set(&impl->bq[i], BQ_NONE, 0.0f, 0.0f, 0.0f);
@ -1950,7 +1964,7 @@ static void param_eq_connect_port(void * Instance, unsigned long Port,
static void param_eq_run(void * Instance, unsigned long SampleCount)
{
struct param_eq_impl *impl = Instance;
dsp_ops_biquadn_run(dsp_ops, impl->bq, impl->n_bq, PARAM_EQ_MAX,
dsp_ops_biquadn_run(impl->plugin->dsp_ops, impl->bq, impl->n_bq, PARAM_EQ_MAX,
&impl->port[8], (const float**)impl->port, 8, SampleCount);
}
@ -2099,14 +2113,18 @@ static const struct fc_descriptor *builtin_make_desc(struct fc_plugin *plugin, c
return NULL;
}
static struct fc_plugin builtin_plugin = {
.make_desc = builtin_make_desc
};
static void builtin_plugin_unload(struct fc_plugin *p)
{
free(p);
}
struct fc_plugin *load_builtin_plugin(const struct spa_support *support, uint32_t n_support,
struct dsp_ops *dsp, const char *plugin, const char *config)
{
dsp_ops = dsp;
struct plugin *impl = calloc (1, sizeof (struct plugin));
impl->plugin.make_desc = builtin_make_desc;
impl->plugin.unload = builtin_plugin_unload;
impl->dsp_ops = dsp;
pffft_select_cpu(dsp->cpu_flags);
return &builtin_plugin;
return (struct fc_plugin *) impl;
}

View file

@ -10,9 +10,9 @@
#include <math.h>
static struct dsp_ops *dsp;
struct convolver1 {
struct dsp_ops *dsp;
int blockSize;
int segSize;
int segCount;
@ -49,11 +49,11 @@ static void convolver1_reset(struct convolver1 *conv)
{
int i;
for (i = 0; i < conv->segCount; i++)
dsp_ops_fft_memclear(dsp, conv->segments[i], conv->fftComplexSize, false);
dsp_ops_fft_memclear(dsp, conv->overlap, conv->blockSize, true);
dsp_ops_fft_memclear(dsp, conv->inputBuffer, conv->segSize, true);
dsp_ops_fft_memclear(dsp, conv->pre_mult, conv->fftComplexSize, false);
dsp_ops_fft_memclear(dsp, conv->conv, conv->fftComplexSize, false);
dsp_ops_fft_memclear(conv->dsp, conv->segments[i], conv->fftComplexSize, false);
dsp_ops_fft_memclear(conv->dsp, conv->overlap, conv->blockSize, true);
dsp_ops_fft_memclear(conv->dsp, conv->inputBuffer, conv->segSize, true);
dsp_ops_fft_memclear(conv->dsp, conv->pre_mult, conv->fftComplexSize, false);
dsp_ops_fft_memclear(conv->dsp, conv->conv, conv->fftComplexSize, false);
conv->inputBufferFill = 0;
conv->current = 0;
}
@ -63,26 +63,26 @@ static void convolver1_free(struct convolver1 *conv)
int i;
for (i = 0; i < conv->segCount; i++) {
if (conv->segments)
dsp_ops_fft_memfree(dsp, conv->segments[i]);
dsp_ops_fft_memfree(conv->dsp, conv->segments[i]);
if (conv->segmentsIr)
dsp_ops_fft_memfree(dsp, conv->segmentsIr[i]);
dsp_ops_fft_memfree(conv->dsp, conv->segmentsIr[i]);
}
if (conv->fft)
dsp_ops_fft_free(dsp, conv->fft);
dsp_ops_fft_free(conv->dsp, conv->fft);
if (conv->ifft)
dsp_ops_fft_free(dsp, conv->ifft);
dsp_ops_fft_free(conv->dsp, conv->ifft);
if (conv->fft_buffer)
dsp_ops_fft_memfree(dsp, conv->fft_buffer);
dsp_ops_fft_memfree(conv->dsp, conv->fft_buffer);
free(conv->segments);
free(conv->segmentsIr);
dsp_ops_fft_memfree(dsp, conv->pre_mult);
dsp_ops_fft_memfree(dsp, conv->conv);
dsp_ops_fft_memfree(dsp, conv->overlap);
dsp_ops_fft_memfree(dsp, conv->inputBuffer);
dsp_ops_fft_memfree(conv->dsp, conv->pre_mult);
dsp_ops_fft_memfree(conv->dsp, conv->conv);
dsp_ops_fft_memfree(conv->dsp, conv->overlap);
dsp_ops_fft_memfree(conv->dsp, conv->inputBuffer);
free(conv);
}
static struct convolver1 *convolver1_new(int block, const float *ir, int irlen)
static struct convolver1 *convolver1_new(struct dsp_ops *dsp, int block, const float *ir, int irlen)
{
struct convolver1 *conv;
int i;
@ -100,19 +100,20 @@ static struct convolver1 *convolver1_new(int block, const float *ir, int irlen)
if (irlen == 0)
return conv;
conv->dsp = dsp;
conv->blockSize = next_power_of_two(block);
conv->segSize = 2 * conv->blockSize;
conv->segCount = (irlen + conv->blockSize-1) / conv->blockSize;
conv->fftComplexSize = (conv->segSize / 2) + 1;
conv->fft = dsp_ops_fft_new(dsp, conv->segSize, true);
conv->fft = dsp_ops_fft_new(conv->dsp, conv->segSize, true);
if (conv->fft == NULL)
goto error;
conv->ifft = dsp_ops_fft_new(dsp, conv->segSize, true);
conv->ifft = dsp_ops_fft_new(conv->dsp, conv->segSize, true);
if (conv->ifft == NULL)
goto error;
conv->fft_buffer = dsp_ops_fft_memalloc(dsp, conv->segSize, true);
conv->fft_buffer = dsp_ops_fft_memalloc(conv->dsp, conv->segSize, true);
if (conv->fft_buffer == NULL)
goto error;
@ -125,21 +126,21 @@ static struct convolver1 *convolver1_new(int block, const float *ir, int irlen)
int left = irlen - (i * conv->blockSize);
int copy = SPA_MIN(conv->blockSize, left);
conv->segments[i] = dsp_ops_fft_memalloc(dsp, conv->fftComplexSize, false);
conv->segmentsIr[i] = dsp_ops_fft_memalloc(dsp, conv->fftComplexSize, false);
conv->segments[i] = dsp_ops_fft_memalloc(conv->dsp, conv->fftComplexSize, false);
conv->segmentsIr[i] = dsp_ops_fft_memalloc(conv->dsp, conv->fftComplexSize, false);
if (conv->segments[i] == NULL || conv->segmentsIr[i] == NULL)
goto error;
dsp_ops_copy(dsp, conv->fft_buffer, &ir[i * conv->blockSize], copy);
dsp_ops_copy(conv->dsp, conv->fft_buffer, &ir[i * conv->blockSize], copy);
if (copy < conv->segSize)
dsp_ops_fft_memclear(dsp, conv->fft_buffer + copy, conv->segSize - copy, true);
dsp_ops_fft_memclear(conv->dsp, conv->fft_buffer + copy, conv->segSize - copy, true);
dsp_ops_fft_run(dsp, conv->fft, 1, conv->fft_buffer, conv->segmentsIr[i]);
dsp_ops_fft_run(conv->dsp, conv->fft, 1, conv->fft_buffer, conv->segmentsIr[i]);
}
conv->pre_mult = dsp_ops_fft_memalloc(dsp, conv->fftComplexSize, false);
conv->conv = dsp_ops_fft_memalloc(dsp, conv->fftComplexSize, false);
conv->overlap = dsp_ops_fft_memalloc(dsp, conv->blockSize, true);
conv->inputBuffer = dsp_ops_fft_memalloc(dsp, conv->segSize, true);
conv->pre_mult = dsp_ops_fft_memalloc(conv->dsp, conv->fftComplexSize, false);
conv->conv = dsp_ops_fft_memalloc(conv->dsp, conv->fftComplexSize, false);
conv->overlap = dsp_ops_fft_memalloc(conv->dsp, conv->blockSize, true);
conv->inputBuffer = dsp_ops_fft_memalloc(conv->dsp, conv->segSize, true);
if (conv->pre_mult == NULL || conv->conv == NULL || conv->overlap == NULL ||
conv->inputBuffer == NULL)
goto error;
@ -157,7 +158,7 @@ static int convolver1_run(struct convolver1 *conv, const float *input, float *ou
int i, processed = 0;
if (conv == NULL || conv->segCount == 0) {
dsp_ops_fft_memclear(dsp, output, len, true);
dsp_ops_fft_memclear(conv->dsp, output, len, true);
return len;
}
@ -165,17 +166,17 @@ static int convolver1_run(struct convolver1 *conv, const float *input, float *ou
const int processing = SPA_MIN(len - processed, conv->blockSize - conv->inputBufferFill);
const int inputBufferPos = conv->inputBufferFill;
dsp_ops_copy(dsp, conv->inputBuffer + inputBufferPos, input + processed, processing);
dsp_ops_copy(conv->dsp, conv->inputBuffer + inputBufferPos, input + processed, processing);
if (inputBufferPos == 0 && processing < conv->blockSize)
dsp_ops_fft_memclear(dsp, conv->inputBuffer + processing, conv->blockSize - processing, true);
dsp_ops_fft_memclear(conv->dsp, conv->inputBuffer + processing, conv->blockSize - processing, true);
dsp_ops_fft_run(dsp, conv->fft, 1, conv->inputBuffer, conv->segments[conv->current]);
dsp_ops_fft_run(conv->dsp, conv->fft, 1, conv->inputBuffer, conv->segments[conv->current]);
if (conv->segCount > 1) {
if (conv->inputBufferFill == 0) {
int indexAudio = (conv->current + 1) % conv->segCount;
dsp_ops_fft_cmul(dsp, conv->fft, conv->pre_mult,
dsp_ops_fft_cmul(conv->dsp, conv->fft, conv->pre_mult,
conv->segmentsIr[1],
conv->segments[indexAudio],
conv->fftComplexSize, conv->scale);
@ -183,7 +184,7 @@ static int convolver1_run(struct convolver1 *conv, const float *input, float *ou
for (i = 2; i < conv->segCount; i++) {
indexAudio = (conv->current + i) % conv->segCount;
dsp_ops_fft_cmuladd(dsp, conv->fft,
dsp_ops_fft_cmuladd(conv->dsp, conv->fft,
conv->pre_mult,
conv->pre_mult,
conv->segmentsIr[i],
@ -191,30 +192,30 @@ static int convolver1_run(struct convolver1 *conv, const float *input, float *ou
conv->fftComplexSize, conv->scale);
}
}
dsp_ops_fft_cmuladd(dsp, conv->fft,
dsp_ops_fft_cmuladd(conv->dsp, conv->fft,
conv->conv,
conv->pre_mult,
conv->segments[conv->current],
conv->segmentsIr[0],
conv->fftComplexSize, conv->scale);
} else {
dsp_ops_fft_cmul(dsp, conv->fft,
dsp_ops_fft_cmul(conv->dsp, conv->fft,
conv->conv,
conv->segments[conv->current],
conv->segmentsIr[0],
conv->fftComplexSize, conv->scale);
}
dsp_ops_fft_run(dsp, conv->ifft, -1, conv->conv, conv->fft_buffer);
dsp_ops_fft_run(conv->dsp, conv->ifft, -1, conv->conv, conv->fft_buffer);
dsp_ops_sum(dsp, output + processed, conv->fft_buffer + inputBufferPos,
dsp_ops_sum(conv->dsp, output + processed, conv->fft_buffer + inputBufferPos,
conv->overlap + inputBufferPos, processing);
conv->inputBufferFill += processing;
if (conv->inputBufferFill == conv->blockSize) {
conv->inputBufferFill = 0;
dsp_ops_copy(dsp, conv->overlap, conv->fft_buffer + conv->blockSize, conv->blockSize);
dsp_ops_copy(conv->dsp, conv->overlap, conv->fft_buffer + conv->blockSize, conv->blockSize);
conv->current = (conv->current > 0) ? (conv->current - 1) : (conv->segCount - 1);
}
@ -226,6 +227,7 @@ static int convolver1_run(struct convolver1 *conv, const float *input, float *ou
struct convolver
{
struct dsp_ops *dsp;
int headBlockSize;
int tailBlockSize;
struct convolver1 *headConvolver;
@ -246,13 +248,13 @@ void convolver_reset(struct convolver *conv)
convolver1_reset(conv->headConvolver);
if (conv->tailConvolver0) {
convolver1_reset(conv->tailConvolver0);
dsp_ops_fft_memclear(dsp, conv->tailOutput0, conv->tailBlockSize, true);
dsp_ops_fft_memclear(dsp, conv->tailPrecalculated0, conv->tailBlockSize, true);
dsp_ops_fft_memclear(conv->dsp, conv->tailOutput0, conv->tailBlockSize, true);
dsp_ops_fft_memclear(conv->dsp, conv->tailPrecalculated0, conv->tailBlockSize, true);
}
if (conv->tailConvolver) {
convolver1_reset(conv->tailConvolver);
dsp_ops_fft_memclear(dsp, conv->tailOutput, conv->tailBlockSize, true);
dsp_ops_fft_memclear(dsp, conv->tailPrecalculated, conv->tailBlockSize, true);
dsp_ops_fft_memclear(conv->dsp, conv->tailOutput, conv->tailBlockSize, true);
dsp_ops_fft_memclear(conv->dsp, conv->tailPrecalculated, conv->tailBlockSize, true);
}
conv->tailInputFill = 0;
conv->precalculatedPos = 0;
@ -263,8 +265,6 @@ struct convolver *convolver_new(struct dsp_ops *dsp_ops, int head_block, int tai
struct convolver *conv;
int head_ir_len;
dsp = dsp_ops;
if (head_block == 0 || tail_block == 0)
return NULL;
@ -282,19 +282,20 @@ struct convolver *convolver_new(struct dsp_ops *dsp_ops, int head_block, int tai
if (irlen == 0)
return conv;
conv->dsp = dsp_ops;
conv->headBlockSize = next_power_of_two(head_block);
conv->tailBlockSize = next_power_of_two(tail_block);
head_ir_len = SPA_MIN(irlen, conv->tailBlockSize);
conv->headConvolver = convolver1_new(conv->headBlockSize, ir, head_ir_len);
conv->headConvolver = convolver1_new(dsp_ops, conv->headBlockSize, ir, head_ir_len);
if (conv->headConvolver == NULL)
goto error;
if (irlen > conv->tailBlockSize) {
int conv1IrLen = SPA_MIN(irlen - conv->tailBlockSize, conv->tailBlockSize);
conv->tailConvolver0 = convolver1_new(conv->headBlockSize, ir + conv->tailBlockSize, conv1IrLen);
conv->tailOutput0 = dsp_ops_fft_memalloc(dsp, conv->tailBlockSize, true);
conv->tailPrecalculated0 = dsp_ops_fft_memalloc(dsp, conv->tailBlockSize, true);
conv->tailConvolver0 = convolver1_new(dsp_ops, conv->headBlockSize, ir + conv->tailBlockSize, conv1IrLen);
conv->tailOutput0 = dsp_ops_fft_memalloc(conv->dsp, conv->tailBlockSize, true);
conv->tailPrecalculated0 = dsp_ops_fft_memalloc(conv->dsp, conv->tailBlockSize, true);
if (conv->tailConvolver0 == NULL || conv->tailOutput0 == NULL ||
conv->tailPrecalculated0 == NULL)
goto error;
@ -302,16 +303,16 @@ struct convolver *convolver_new(struct dsp_ops *dsp_ops, int head_block, int tai
if (irlen > 2 * conv->tailBlockSize) {
int tailIrLen = irlen - (2 * conv->tailBlockSize);
conv->tailConvolver = convolver1_new(conv->tailBlockSize, ir + (2 * conv->tailBlockSize), tailIrLen);
conv->tailOutput = dsp_ops_fft_memalloc(dsp, conv->tailBlockSize, true);
conv->tailPrecalculated = dsp_ops_fft_memalloc(dsp, conv->tailBlockSize, true);
conv->tailConvolver = convolver1_new(dsp_ops, conv->tailBlockSize, ir + (2 * conv->tailBlockSize), tailIrLen);
conv->tailOutput = dsp_ops_fft_memalloc(conv->dsp, conv->tailBlockSize, true);
conv->tailPrecalculated = dsp_ops_fft_memalloc(conv->dsp, conv->tailBlockSize, true);
if (conv->tailConvolver == NULL || conv->tailOutput == NULL ||
conv->tailPrecalculated == NULL)
goto error;
}
if (conv->tailConvolver0 || conv->tailConvolver) {
conv->tailInput = dsp_ops_fft_memalloc(dsp, conv->tailBlockSize, true);
conv->tailInput = dsp_ops_fft_memalloc(conv->dsp, conv->tailBlockSize, true);
if (conv->tailInput == NULL)
goto error;
}
@ -332,11 +333,11 @@ void convolver_free(struct convolver *conv)
convolver1_free(conv->tailConvolver0);
if (conv->tailConvolver)
convolver1_free(conv->tailConvolver);
dsp_ops_fft_memfree(dsp, conv->tailOutput0);
dsp_ops_fft_memfree(dsp, conv->tailPrecalculated0);
dsp_ops_fft_memfree(dsp, conv->tailOutput);
dsp_ops_fft_memfree(dsp, conv->tailPrecalculated);
dsp_ops_fft_memfree(dsp, conv->tailInput);
dsp_ops_fft_memfree(conv->dsp, conv->tailOutput0);
dsp_ops_fft_memfree(conv->dsp, conv->tailPrecalculated0);
dsp_ops_fft_memfree(conv->dsp, conv->tailOutput);
dsp_ops_fft_memfree(conv->dsp, conv->tailPrecalculated);
dsp_ops_fft_memfree(conv->dsp, conv->tailInput);
free(conv);
}
@ -352,16 +353,16 @@ int convolver_run(struct convolver *conv, const float *input, float *output, int
int processing = SPA_MIN(remaining, conv->headBlockSize - (conv->tailInputFill % conv->headBlockSize));
if (conv->tailPrecalculated0)
dsp_ops_sum(dsp, &output[processed], &output[processed],
dsp_ops_sum(conv->dsp, &output[processed], &output[processed],
&conv->tailPrecalculated0[conv->precalculatedPos],
processing);
if (conv->tailPrecalculated)
dsp_ops_sum(dsp, &output[processed], &output[processed],
dsp_ops_sum(conv->dsp, &output[processed], &output[processed],
&conv->tailPrecalculated[conv->precalculatedPos],
processing);
conv->precalculatedPos += processing;
dsp_ops_copy(dsp, conv->tailInput + conv->tailInputFill, input + processed, processing);
dsp_ops_copy(conv->dsp, conv->tailInput + conv->tailInputFill, input + processed, processing);
conv->tailInputFill += processing;
if (conv->tailPrecalculated0 && (conv->tailInputFill % conv->headBlockSize == 0)) {

View file

@ -29,7 +29,7 @@ struct descriptor {
const LADSPA_Descriptor *d;
};
static void *ladspa_instantiate(const struct fc_descriptor *desc,
static void *ladspa_instantiate(const struct fc_plugin *plugin, const struct fc_descriptor *desc,
unsigned long SampleRate, int index, const char *config)
{
struct descriptor *d = (struct descriptor *)desc;

View file

@ -278,7 +278,7 @@ work_schedule(LV2_Worker_Schedule_Handle handle, uint32_t size, const void *data
return LV2_WORKER_SUCCESS;
}
static void *lv2_instantiate(const struct fc_descriptor *desc,
static void *lv2_instantiate(const struct fc_plugin *plugin, const struct fc_descriptor *desc,
unsigned long SampleRate, int index, const char *config)
{
struct descriptor *d = (struct descriptor*)desc;

View file

@ -51,7 +51,7 @@ struct fc_descriptor {
uint32_t n_ports;
struct fc_port *ports;
void *(*instantiate) (const struct fc_descriptor *desc,
void *(*instantiate) (const struct fc_plugin *plugin, const struct fc_descriptor *desc,
unsigned long SampleRate, int index, const char *config);
void (*cleanup) (void *instance);

View file

@ -16,11 +16,15 @@
#define MAX_SAMPLES 8192u
static struct dsp_ops *dsp_ops;
static struct spa_loop *data_loop;
static struct spa_loop *main_loop;
struct plugin {
struct fc_plugin plugin;
struct dsp_ops *dsp_ops;
struct spa_loop *data_loop;
struct spa_loop *main_loop;
};
struct spatializer_impl {
struct plugin *plugin;
unsigned long rate;
float *port[6];
int n_samples, blocksize, tailsize;
@ -32,7 +36,7 @@ struct spatializer_impl {
struct convolver *r_conv[3];
};
static void * spatializer_instantiate(const struct fc_descriptor * Descriptor,
static void * spatializer_instantiate(const struct fc_plugin *plugin, const struct fc_descriptor * Descriptor,
unsigned long SampleRate, int index, const char *config)
{
struct spatializer_impl *impl;
@ -59,6 +63,8 @@ static void * spatializer_instantiate(const struct fc_descriptor * Descriptor,
return NULL;
}
impl->plugin = (struct plugin *) plugin;
while ((len = spa_json_object_next(&it[0], key, sizeof(key), &val)) > 0) {
if (spa_streq(key, "blocksize")) {
if (spa_json_parse_int(val, len, &impl->blocksize) <= 0) {
@ -237,9 +243,9 @@ static void spatializer_reload(void * Instance)
if (impl->r_conv[2])
convolver_free(impl->r_conv[2]);
impl->l_conv[2] = convolver_new(dsp_ops, impl->blocksize, impl->tailsize,
impl->l_conv[2] = convolver_new(impl->plugin->dsp_ops, impl->blocksize, impl->tailsize,
left_ir, impl->n_samples);
impl->r_conv[2] = convolver_new(dsp_ops, impl->blocksize, impl->tailsize,
impl->r_conv[2] = convolver_new(impl->plugin->dsp_ops, impl->blocksize, impl->tailsize,
right_ir, impl->n_samples);
free(left_ir);
@ -249,7 +255,7 @@ static void spatializer_reload(void * Instance)
pw_log_error("reloading left or right convolver failed");
return;
}
spa_loop_invoke(data_loop, do_switch, 1, NULL, 0, true, impl);
spa_loop_invoke(impl->plugin->data_loop, do_switch, 1, NULL, 0, true, impl);
}
struct free_data {
@ -294,7 +300,7 @@ static void spatializer_run(void * Instance, unsigned long SampleCount)
impl->l_conv[1] = impl->r_conv[1] = NULL;
impl->interpolate = false;
spa_loop_invoke(main_loop, do_free, 1, &free_data, sizeof(free_data), false, impl);
spa_loop_invoke(impl->plugin->main_loop, do_free, 1, &free_data, sizeof(free_data), false, impl);
} else if (impl->l_conv[0] && impl->r_conv[0]) {
convolver_run(impl->l_conv[0], impl->port[2], impl->port[0], SampleCount);
convolver_run(impl->r_conv[0], impl->port[2], impl->port[1], SampleCount);
@ -411,19 +417,24 @@ static const struct fc_descriptor *sofa_make_desc(struct fc_plugin *plugin, cons
return NULL;
}
static struct fc_plugin builtin_plugin = {
.make_desc = sofa_make_desc
};
static void sofa_plugin_unload(struct fc_plugin *p)
{
free(p);
}
SPA_EXPORT
struct fc_plugin *pipewire__filter_chain_plugin_load(const struct spa_support *support, uint32_t n_support,
struct dsp_ops *dsp, const char *plugin, const char *config)
{
dsp_ops = dsp;
struct plugin *impl = calloc(1, sizeof (struct plugin));
impl->plugin.make_desc = sofa_make_desc;
impl->plugin.unload = sofa_plugin_unload;
impl->dsp_ops = dsp;
pffft_select_cpu(dsp->cpu_flags);
data_loop = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_DataLoop);
main_loop = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_Loop);
impl->data_loop = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_DataLoop);
impl->main_loop = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_Loop);
return &builtin_plugin;
return (struct fc_plugin *) impl;
}