mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-05 13:30:02 -05:00
filter-chain: don't let plugins depend on pipewire, just spa
This commit is contained in:
parent
44340fde05
commit
02edfba21a
4 changed files with 221 additions and 158 deletions
|
|
@ -15,10 +15,9 @@
|
|||
#include <spa/utils/json.h>
|
||||
#include <spa/utils/result.h>
|
||||
#include <spa/support/cpu.h>
|
||||
#include <spa/support/log.h>
|
||||
#include <spa/plugins/audioconvert/resample.h>
|
||||
|
||||
#include <pipewire/log.h>
|
||||
|
||||
#include "plugin.h"
|
||||
|
||||
#include "biquad.h"
|
||||
|
|
@ -30,11 +29,16 @@
|
|||
|
||||
struct plugin {
|
||||
struct fc_plugin plugin;
|
||||
struct dsp_ops *dsp_ops;
|
||||
struct dsp_ops *dsp;
|
||||
struct spa_log *log;
|
||||
};
|
||||
|
||||
struct builtin {
|
||||
struct plugin *plugin;
|
||||
|
||||
struct dsp_ops *dsp;
|
||||
struct spa_log *log;
|
||||
|
||||
unsigned long rate;
|
||||
float *port[64];
|
||||
|
||||
|
|
@ -80,7 +84,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(impl->plugin->dsp_ops, out, in, SampleCount);
|
||||
dsp_ops_copy(impl->dsp, out, in, SampleCount);
|
||||
}
|
||||
|
||||
static struct fc_port copy_ports[] = {
|
||||
|
|
@ -129,7 +133,7 @@ static void mixer_run(void * Instance, unsigned long SampleCount)
|
|||
src[n_src] = in;
|
||||
gains[n_src++] = gain;
|
||||
}
|
||||
dsp_ops_mix_gain(impl->plugin->dsp_ops, out, src, gains, n_src, SampleCount);
|
||||
dsp_ops_mix_gain(impl->dsp, out, src, gains, n_src, SampleCount);
|
||||
}
|
||||
|
||||
static struct fc_port mixer_ports[] = {
|
||||
|
|
@ -320,6 +324,8 @@ static void *bq_instantiate(const struct fc_plugin *plugin, const struct fc_desc
|
|||
return NULL;
|
||||
|
||||
impl->plugin = (struct plugin *) plugin;
|
||||
impl->log = impl->plugin->log;
|
||||
impl->dsp = impl->plugin->dsp;
|
||||
impl->rate = SampleRate;
|
||||
impl->b0 = impl->a0 = 1.0f;
|
||||
impl->type = bq_type_from_name(Descriptor->name);
|
||||
|
|
@ -327,19 +333,19 @@ static void *bq_instantiate(const struct fc_plugin *plugin, const struct fc_desc
|
|||
return impl;
|
||||
|
||||
if (config == NULL) {
|
||||
pw_log_error("biquads:bq_raw requires a config section");
|
||||
spa_log_error(impl->log, "biquads:bq_raw requires a config section");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (spa_json_begin_object(&it[0], config, strlen(config)) <= 0) {
|
||||
pw_log_error("biquads:config section must be an object");
|
||||
spa_log_error(impl->log, "biquads:config section must be an object");
|
||||
goto error;
|
||||
}
|
||||
|
||||
while ((len = spa_json_object_next(&it[0], key, sizeof(key), &val)) > 0) {
|
||||
if (spa_streq(key, "coefficients")) {
|
||||
if (!spa_json_is_array(val, len)) {
|
||||
pw_log_error("biquads:coefficients require an array");
|
||||
spa_log_error(impl->log, "biquads:coefficients require an array");
|
||||
goto error;
|
||||
}
|
||||
spa_json_enter(&it[0], &it[1]);
|
||||
|
|
@ -351,48 +357,48 @@ static void *bq_instantiate(const struct fc_plugin *plugin, const struct fc_desc
|
|||
while ((len = spa_json_object_next(&it[2], key, sizeof(key), &val)) > 0) {
|
||||
if (spa_streq(key, "rate")) {
|
||||
if (spa_json_parse_int(val, len, &rate) <= 0) {
|
||||
pw_log_error("biquads:rate requires a number");
|
||||
spa_log_error(impl->log, "biquads:rate requires a number");
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
else if (spa_streq(key, "b0")) {
|
||||
if (spa_json_parse_float(val, len, &b0) <= 0) {
|
||||
pw_log_error("biquads:b0 requires a float");
|
||||
spa_log_error(impl->log, "biquads:b0 requires a float");
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
else if (spa_streq(key, "b1")) {
|
||||
if (spa_json_parse_float(val, len, &b1) <= 0) {
|
||||
pw_log_error("biquads:b1 requires a float");
|
||||
spa_log_error(impl->log, "biquads:b1 requires a float");
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
else if (spa_streq(key, "b2")) {
|
||||
if (spa_json_parse_float(val, len, &b2) <= 0) {
|
||||
pw_log_error("biquads:b2 requires a float");
|
||||
spa_log_error(impl->log, "biquads:b2 requires a float");
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
else if (spa_streq(key, "a0")) {
|
||||
if (spa_json_parse_float(val, len, &a0) <= 0) {
|
||||
pw_log_error("biquads:a0 requires a float");
|
||||
spa_log_error(impl->log, "biquads:a0 requires a float");
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
else if (spa_streq(key, "a1")) {
|
||||
if (spa_json_parse_float(val, len, &a1) <= 0) {
|
||||
pw_log_error("biquads:a1 requires a float");
|
||||
spa_log_error(impl->log, "biquads:a1 requires a float");
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
else if (spa_streq(key, "a2")) {
|
||||
if (spa_json_parse_float(val, len, &a2) <= 0) {
|
||||
pw_log_error("biquads:a0 requires a float");
|
||||
spa_log_error(impl->log, "biquads:a0 requires a float");
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
else {
|
||||
pw_log_warn("biquads: ignoring coefficients key: '%s'", key);
|
||||
spa_log_warn(impl->log, "biquads: ignoring coefficients key: '%s'", key);
|
||||
}
|
||||
}
|
||||
if (labs((long)rate - (long)SampleRate) <
|
||||
|
|
@ -403,7 +409,7 @@ static void *bq_instantiate(const struct fc_plugin *plugin, const struct fc_desc
|
|||
}
|
||||
}
|
||||
else {
|
||||
pw_log_warn("biquads: ignoring config key: '%s'", key);
|
||||
spa_log_warn(impl->log, "biquads: ignoring config key: '%s'", key);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -532,7 +538,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(impl->plugin->dsp_ops, bq, out, in, samples);
|
||||
dsp_ops_biquad_run(impl->dsp, bq, out, in, samples);
|
||||
}
|
||||
|
||||
/** bq_lowpass */
|
||||
|
|
@ -665,6 +671,9 @@ static const struct fc_descriptor bq_raw_desc = {
|
|||
/** convolve */
|
||||
struct convolver_impl {
|
||||
struct plugin *plugin;
|
||||
|
||||
struct spa_log *log;
|
||||
struct dsp_ops *dsp;
|
||||
unsigned long rate;
|
||||
float *port[2];
|
||||
|
||||
|
|
@ -707,7 +716,7 @@ static float *read_samples_from_sf(SNDFILE *f, SF_INFO info, float gain, int del
|
|||
}
|
||||
#endif
|
||||
|
||||
static float *read_closest(char **filenames, float gain, float delay_sec, int offset,
|
||||
static float *read_closest(struct plugin *pl, char **filenames, float gain, float delay_sec, int offset,
|
||||
int length, int channel, long unsigned *rate, int *n_samples)
|
||||
{
|
||||
#ifdef HAVE_SNDFILE
|
||||
|
|
@ -729,24 +738,24 @@ static float *read_closest(char **filenames, float gain, float delay_sec, int of
|
|||
if (labs((long)infos[i].samplerate - (long)*rate) < diff) {
|
||||
best = i;
|
||||
diff = labs((long)infos[i].samplerate - (long)*rate);
|
||||
pw_log_debug("new closest match: %d", infos[i].samplerate);
|
||||
spa_log_debug(pl->log, "new closest match: %d", infos[i].samplerate);
|
||||
}
|
||||
}
|
||||
if (fs[best] != NULL) {
|
||||
pw_log_info("loading best rate:%u %s", infos[best].samplerate, filenames[best]);
|
||||
spa_log_info(pl->log, "loading best rate:%u %s", infos[best].samplerate, filenames[best]);
|
||||
samples = read_samples_from_sf(fs[best], infos[best], gain,
|
||||
(int) (delay_sec * infos[best].samplerate), offset, length,
|
||||
channel, rate, n_samples);
|
||||
} else {
|
||||
char buf[PATH_MAX];
|
||||
pw_log_error("Can't open any sample file (CWD %s):",
|
||||
spa_log_error(pl->log, "Can't open any sample file (CWD %s):",
|
||||
getcwd(buf, sizeof(buf)));
|
||||
for (i = 0; i < MAX_RATES && filenames[i] && filenames[i][0]; i++) {
|
||||
fs[i] = sf_open(filenames[i], SFM_READ, &infos[i]);
|
||||
if (fs[i] == NULL)
|
||||
pw_log_error(" failed file %s: %s", filenames[i], sf_strerror(fs[i]));
|
||||
spa_log_error(pl->log, " failed file %s: %s", filenames[i], sf_strerror(fs[i]));
|
||||
else
|
||||
pw_log_warn(" unexpectedly opened file %s", filenames[i]);
|
||||
spa_log_warn(pl->log, " unexpectedly opened file %s", filenames[i]);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < MAX_RATES; i++)
|
||||
|
|
@ -755,7 +764,7 @@ static float *read_closest(char **filenames, float gain, float delay_sec, int of
|
|||
|
||||
return samples;
|
||||
#else
|
||||
pw_log_error("compiled without sndfile support, can't load samples: "
|
||||
spa_log_error(pl->log, "compiled without sndfile support, can't load samples: "
|
||||
"using dirac impulse");
|
||||
float *samples = calloc(1, sizeof(float));
|
||||
samples[0] = gain;
|
||||
|
|
@ -764,7 +773,7 @@ static float *read_closest(char **filenames, float gain, float delay_sec, int of
|
|||
#endif
|
||||
}
|
||||
|
||||
static float *create_hilbert(const char *filename, float gain, int rate, float delay_sec, int offset,
|
||||
static float *create_hilbert(struct plugin *pl, const char *filename, float gain, int rate, float delay_sec, int offset,
|
||||
int length, int *n_samples)
|
||||
{
|
||||
float *samples, v;
|
||||
|
|
@ -795,7 +804,7 @@ static float *create_hilbert(const char *filename, float gain, int rate, float d
|
|||
return samples;
|
||||
}
|
||||
|
||||
static float *create_dirac(const char *filename, float gain, int rate, float delay_sec, int offset,
|
||||
static float *create_dirac(struct plugin *pl, const char *filename, float gain, int rate, float delay_sec, int offset,
|
||||
int length, int *n_samples)
|
||||
{
|
||||
float *samples;
|
||||
|
|
@ -814,7 +823,7 @@ static float *create_dirac(const char *filename, float gain, int rate, float del
|
|||
return samples;
|
||||
}
|
||||
|
||||
static float *resample_buffer(struct dsp_ops *dsp_ops, float *samples, int *n_samples,
|
||||
static float *resample_buffer(struct plugin *pl, float *samples, int *n_samples,
|
||||
unsigned long in_rate, unsigned long out_rate, uint32_t quality)
|
||||
{
|
||||
#ifdef HAVE_SPA_PLUGINS
|
||||
|
|
@ -828,10 +837,10 @@ static float *resample_buffer(struct dsp_ops *dsp_ops, float *samples, int *n_sa
|
|||
r.channels = 1;
|
||||
r.i_rate = in_rate;
|
||||
r.o_rate = out_rate;
|
||||
r.cpu_flags = dsp_ops->cpu_flags;
|
||||
r.cpu_flags = pl->dsp->cpu_flags;
|
||||
r.quality = quality;
|
||||
if ((res = resample_native_init(&r)) < 0) {
|
||||
pw_log_error("resampling failed: %s", spa_strerror(res));
|
||||
spa_log_error(pl->log, "resampling failed: %s", spa_strerror(res));
|
||||
errno = -res;
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -846,11 +855,11 @@ static float *resample_buffer(struct dsp_ops *dsp_ops, float *samples, int *n_sa
|
|||
out_len = out_n_samples;
|
||||
out_buf = out_samples;
|
||||
|
||||
pw_log_info("Resampling filter: rate: %lu => %lu, n_samples: %u => %u, q:%u",
|
||||
spa_log_info(pl->log, "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);
|
||||
spa_log_debug(pl->log, "resampled: %u -> %u samples", in_len, out_len);
|
||||
total_out += out_len;
|
||||
|
||||
in_len = resample_delay(&r);
|
||||
|
|
@ -861,9 +870,9 @@ static float *resample_buffer(struct dsp_ops *dsp_ops, float *samples, int *n_sa
|
|||
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);
|
||||
spa_log_debug(pl->log, "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);
|
||||
spa_log_debug(pl->log, "flushed: %u -> %u samples", in_len, out_len);
|
||||
total_out += out_len;
|
||||
|
||||
free(in_buf);
|
||||
|
|
@ -884,7 +893,7 @@ error:
|
|||
free(out_samples);
|
||||
return NULL;
|
||||
#else
|
||||
pw_log_error("compiled without spa-plugins support, can't resample");
|
||||
spa_log_error(impl->log, "compiled without spa-plugins support, can't resample");
|
||||
float *out_samples = calloc(*n_samples, sizeof(float));
|
||||
memcpy(out_samples, samples, *n_samples * sizeof(float));
|
||||
return out_samples;
|
||||
|
|
@ -895,6 +904,7 @@ static void * convolver_instantiate(const struct fc_plugin *plugin, const struct
|
|||
unsigned long SampleRate, int index, const char *config)
|
||||
{
|
||||
struct convolver_impl *impl;
|
||||
struct plugin *pl = (struct plugin*)plugin;
|
||||
float *samples;
|
||||
int offset = 0, length = 0, channel = index, n_samples = 0, len;
|
||||
uint32_t i = 0;
|
||||
|
|
@ -909,31 +919,31 @@ static void * convolver_instantiate(const struct fc_plugin *plugin, const struct
|
|||
|
||||
errno = EINVAL;
|
||||
if (config == NULL) {
|
||||
pw_log_error("convolver: requires a config section");
|
||||
spa_log_error(pl->log, "convolver: requires a config section");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (spa_json_begin_object(&it[0], config, strlen(config)) <= 0) {
|
||||
pw_log_error("convolver:config must be an object");
|
||||
spa_log_error(pl->log, "convolver:config must be an object");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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, &blocksize) <= 0) {
|
||||
pw_log_error("convolver:blocksize requires a number");
|
||||
spa_log_error(pl->log, "convolver:blocksize requires a number");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else if (spa_streq(key, "tailsize")) {
|
||||
if (spa_json_parse_int(val, len, &tailsize) <= 0) {
|
||||
pw_log_error("convolver:tailsize requires a number");
|
||||
spa_log_error(pl->log, "convolver:tailsize requires a number");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else if (spa_streq(key, "gain")) {
|
||||
if (spa_json_parse_float(val, len, &gain) <= 0) {
|
||||
pw_log_error("convolver:gain requires a number");
|
||||
spa_log_error(pl->log, "convolver:gain requires a number");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
|
@ -942,7 +952,7 @@ static void * convolver_instantiate(const struct fc_plugin *plugin, const struct
|
|||
if (spa_json_parse_int(val, len, &delay_i) > 0) {
|
||||
delay = delay_i / (float)SampleRate;
|
||||
} else if (spa_json_parse_float(val, len, &delay) <= 0) {
|
||||
pw_log_error("convolver:delay requires a number");
|
||||
spa_log_error(pl->log, "convolver:delay requires a number");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
|
@ -956,7 +966,7 @@ static void * convolver_instantiate(const struct fc_plugin *plugin, const struct
|
|||
}
|
||||
}
|
||||
else if (spa_json_parse_stringn(val, len, v, sizeof(v)) <= 0) {
|
||||
pw_log_error("convolver:filename requires a string or an array");
|
||||
spa_log_error(pl->log, "convolver:filename requires a string or an array");
|
||||
return NULL;
|
||||
} else {
|
||||
filenames[0] = strdup(v);
|
||||
|
|
@ -964,34 +974,34 @@ static void * convolver_instantiate(const struct fc_plugin *plugin, const struct
|
|||
}
|
||||
else if (spa_streq(key, "offset")) {
|
||||
if (spa_json_parse_int(val, len, &offset) <= 0) {
|
||||
pw_log_error("convolver:offset requires a number");
|
||||
spa_log_error(pl->log, "convolver:offset requires a number");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else if (spa_streq(key, "length")) {
|
||||
if (spa_json_parse_int(val, len, &length) <= 0) {
|
||||
pw_log_error("convolver:length requires a number");
|
||||
spa_log_error(pl->log, "convolver:length requires a number");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else if (spa_streq(key, "channel")) {
|
||||
if (spa_json_parse_int(val, len, &channel) <= 0) {
|
||||
pw_log_error("convolver:channel requires a number");
|
||||
spa_log_error(pl->log, "convolver:channel requires a number");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else if (spa_streq(key, "resample_quality")) {
|
||||
if (spa_json_parse_int(val, len, &resample_quality) <= 0) {
|
||||
pw_log_error("convolver:resample_quality requires a number");
|
||||
spa_log_error(pl->log, "convolver:resample_quality requires a number");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
pw_log_warn("convolver: ignoring config key: '%s'", key);
|
||||
spa_log_warn(pl->log, "convolver: ignoring config key: '%s'", key);
|
||||
}
|
||||
}
|
||||
if (filenames[0] == NULL) {
|
||||
pw_log_error("convolver:filename was not given");
|
||||
spa_log_error(pl->log, "convolver:filename was not given");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -1001,18 +1011,17 @@ static void * convolver_instantiate(const struct fc_plugin *plugin, const struct
|
|||
offset = 0;
|
||||
|
||||
if (spa_streq(filenames[0], "/hilbert")) {
|
||||
samples = create_hilbert(filenames[0], gain, SampleRate, delay, offset,
|
||||
samples = create_hilbert(pl, filenames[0], gain, SampleRate, delay, offset,
|
||||
length, &n_samples);
|
||||
} else if (spa_streq(filenames[0], "/dirac")) {
|
||||
samples = create_dirac(filenames[0], gain, SampleRate, delay, offset,
|
||||
samples = create_dirac(pl, filenames[0], gain, SampleRate, delay, offset,
|
||||
length, &n_samples);
|
||||
} else {
|
||||
rate = SampleRate;
|
||||
samples = read_closest(filenames, gain, delay, offset,
|
||||
samples = read_closest(pl, filenames, gain, delay, offset,
|
||||
length, channel, &rate, &n_samples);
|
||||
if (samples != NULL && rate != SampleRate) {
|
||||
struct plugin *p = (struct plugin *) plugin;
|
||||
samples = resample_buffer(p->dsp_ops, samples, &n_samples,
|
||||
samples = resample_buffer(pl, samples, &n_samples,
|
||||
rate, SampleRate, resample_quality);
|
||||
}
|
||||
}
|
||||
|
|
@ -1031,17 +1040,19 @@ static void * convolver_instantiate(const struct fc_plugin *plugin, const struct
|
|||
if (tailsize <= 0)
|
||||
tailsize = SPA_CLAMP(4096, blocksize, 32768);
|
||||
|
||||
pw_log_info("using n_samples:%u %d:%d blocksize delay:%f", n_samples,
|
||||
spa_log_info(pl->log, "using n_samples:%u %d:%d blocksize delay:%f", n_samples,
|
||||
blocksize, tailsize, delay);
|
||||
|
||||
impl = calloc(1, sizeof(*impl));
|
||||
if (impl == NULL)
|
||||
goto error;
|
||||
|
||||
impl->plugin = (struct plugin *) plugin;
|
||||
impl->plugin = pl;
|
||||
impl->log = pl->log;
|
||||
impl->dsp = pl->dsp;
|
||||
impl->rate = SampleRate;
|
||||
|
||||
impl->conv = convolver_new(impl->plugin->dsp_ops, blocksize, tailsize, samples, n_samples);
|
||||
impl->conv = convolver_new(impl->dsp, blocksize, tailsize, samples, n_samples);
|
||||
if (impl->conv == NULL)
|
||||
goto error;
|
||||
|
||||
|
|
@ -1110,6 +1121,10 @@ static const struct fc_descriptor convolve_desc = {
|
|||
/** delay */
|
||||
struct delay_impl {
|
||||
struct plugin *plugin;
|
||||
|
||||
struct dsp_ops *dsp;
|
||||
struct spa_log *log;
|
||||
|
||||
unsigned long rate;
|
||||
float *port[4];
|
||||
|
||||
|
|
@ -1130,6 +1145,7 @@ static void delay_cleanup(void * Instance)
|
|||
static void *delay_instantiate(const struct fc_plugin *plugin, const struct fc_descriptor * Descriptor,
|
||||
unsigned long SampleRate, int index, const char *config)
|
||||
{
|
||||
struct plugin *pl = (struct plugin*) plugin;
|
||||
struct delay_impl *impl;
|
||||
struct spa_json it[1];
|
||||
const char *val;
|
||||
|
|
@ -1138,24 +1154,24 @@ static void *delay_instantiate(const struct fc_plugin *plugin, const struct fc_d
|
|||
int len;
|
||||
|
||||
if (config == NULL) {
|
||||
pw_log_error("delay: requires a config section");
|
||||
spa_log_error(pl->log, "delay: requires a config section");
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (spa_json_begin_object(&it[0], config, strlen(config)) <= 0) {
|
||||
pw_log_error("delay:config must be an object");
|
||||
spa_log_error(pl->log, "delay:config must be an object");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while ((len = spa_json_object_next(&it[0], key, sizeof(key), &val)) > 0) {
|
||||
if (spa_streq(key, "max-delay")) {
|
||||
if (spa_json_parse_float(val, len, &max_delay) <= 0) {
|
||||
pw_log_error("delay:max-delay requires a number");
|
||||
spa_log_error(pl->log, "delay:max-delay requires a number");
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
pw_log_warn("delay: ignoring config key: '%s'", key);
|
||||
spa_log_warn(pl->log, "delay: ignoring config key: '%s'", key);
|
||||
}
|
||||
}
|
||||
if (max_delay <= 0.0f)
|
||||
|
|
@ -1165,10 +1181,12 @@ static void *delay_instantiate(const struct fc_plugin *plugin, const struct fc_d
|
|||
if (impl == NULL)
|
||||
return NULL;
|
||||
|
||||
impl->plugin = (struct plugin *) plugin;
|
||||
impl->plugin = pl;
|
||||
impl->dsp = pl->dsp;
|
||||
impl->log = pl->log;
|
||||
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);
|
||||
spa_log_info(impl->log, "max-delay:%f seconds rate:%lu samples:%d", max_delay, impl->rate, impl->buffer_samples);
|
||||
|
||||
impl->buffer = calloc(impl->buffer_samples * 2 + 64, sizeof(float));
|
||||
if (impl->buffer == NULL) {
|
||||
|
|
@ -1200,7 +1218,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(impl->plugin->dsp_ops, impl->buffer, &impl->ptr, impl->buffer_samples,
|
||||
dsp_ops_delay(impl->dsp, impl->buffer, &impl->ptr, impl->buffer_samples,
|
||||
impl->delay_samples, out, in, SampleCount);
|
||||
}
|
||||
|
||||
|
|
@ -1334,7 +1352,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(impl->plugin->dsp_ops, out, in, mult, add, SampleCount);
|
||||
dsp_ops_linear(impl->dsp, out, in, mult, add, SampleCount);
|
||||
|
||||
if (ctrl != NULL && notify != NULL)
|
||||
notify[0] = ctrl[0] * mult + add;
|
||||
|
|
@ -1579,7 +1597,7 @@ static void mult_run(void * Instance, unsigned long SampleCount)
|
|||
|
||||
src[n_src++] = in;
|
||||
}
|
||||
dsp_ops_mult(impl->plugin->dsp_ops, out, src, n_src, SampleCount);
|
||||
dsp_ops_mult(impl->dsp, out, src, n_src, SampleCount);
|
||||
}
|
||||
|
||||
static struct fc_port mult_ports[] = {
|
||||
|
|
@ -1706,6 +1724,10 @@ static const struct fc_descriptor sine_desc = {
|
|||
#define PARAM_EQ_MAX 64
|
||||
struct param_eq_impl {
|
||||
struct plugin *plugin;
|
||||
|
||||
struct dsp_ops *dsp;
|
||||
struct spa_log *log;
|
||||
|
||||
unsigned long rate;
|
||||
float *port[8*2];
|
||||
|
||||
|
|
@ -1713,7 +1735,8 @@ struct param_eq_impl {
|
|||
struct biquad bq[PARAM_EQ_MAX * 8];
|
||||
};
|
||||
|
||||
static int load_eq_bands(const char *filename, int rate, struct biquad *bq, uint32_t max_bq, uint32_t *n_bq)
|
||||
static int load_eq_bands(struct plugin *pl, const char *filename, int rate,
|
||||
struct biquad *bq, uint32_t max_bq, uint32_t *n_bq)
|
||||
{
|
||||
FILE *f = NULL;
|
||||
char *line = NULL;
|
||||
|
|
@ -1728,7 +1751,7 @@ static int load_eq_bands(const char *filename, int rate, struct biquad *bq, uint
|
|||
|
||||
if ((f = fopen(filename, "r")) == NULL) {
|
||||
res = -errno;
|
||||
pw_log_error("failed to open param_eq file '%s': %m", filename);
|
||||
spa_log_error(pl->log, "failed to open param_eq file '%s': %m", filename);
|
||||
goto exit;
|
||||
}
|
||||
/*
|
||||
|
|
@ -1746,7 +1769,7 @@ static int load_eq_bands(const char *filename, int rate, struct biquad *bq, uint
|
|||
nread = getline(&line, &linelen, f);
|
||||
if (nread != -1 && sscanf(line, "%*s %6s %*s", gain) == 1) {
|
||||
if (spa_json_parse_float(gain, strlen(gain), &vg)) {
|
||||
pw_log_info("%d %s freq:0 q:1.0 gain:%f", n,
|
||||
spa_log_info(pl->log, "%d %s freq:0 q:1.0 gain:%f", n,
|
||||
bq_name_from_type(BQ_HIGHSHELF), vg);
|
||||
biquad_set(&bq[n++], BQ_HIGHSHELF, 0.0f, 1.0f, vg);
|
||||
}
|
||||
|
|
@ -1784,7 +1807,7 @@ static int load_eq_bands(const char *filename, int rate, struct biquad *bq, uint
|
|||
|
||||
if (spa_json_parse_float(gain, strlen(gain), &vg) &&
|
||||
spa_json_parse_float(q, strlen(q), &vq)) {
|
||||
pw_log_info("%d %s freq:%d q:%f gain:%f", n,
|
||||
spa_log_info(pl->log, "%d %s freq:%d q:%f gain:%f", n,
|
||||
bq_name_from_type(type), freq, vq, vg);
|
||||
biquad_set(&bq[n++], type, freq * 2.0f / rate, vq, vg);
|
||||
}
|
||||
|
|
@ -1810,7 +1833,8 @@ exit:
|
|||
* { type=bq_peaking freq=1600 gain=2.3 q=2.700 }
|
||||
* ]
|
||||
*/
|
||||
static int parse_filters(struct spa_json *iter, int rate, struct biquad *bq, uint32_t max_bq, uint32_t *n_bq)
|
||||
static int parse_filters(struct plugin *pl, struct spa_json *iter, int rate,
|
||||
struct biquad *bq, uint32_t max_bq, uint32_t *n_bq)
|
||||
{
|
||||
struct spa_json it[1];
|
||||
const char *val;
|
||||
|
|
@ -1826,37 +1850,37 @@ static int parse_filters(struct spa_json *iter, int rate, struct biquad *bq, uin
|
|||
while ((len = spa_json_object_next(&it[0], key, sizeof(key), &val)) > 0) {
|
||||
if (spa_streq(key, "type")) {
|
||||
if (spa_json_parse_stringn(val, len, type_str, sizeof(type_str)) <= 0) {
|
||||
pw_log_error("param_eq:type requires a string");
|
||||
spa_log_error(pl->log, "param_eq:type requires a string");
|
||||
return -EINVAL;
|
||||
}
|
||||
type = bq_type_from_name(type_str);
|
||||
}
|
||||
else if (spa_streq(key, "freq")) {
|
||||
if (spa_json_parse_float(val, len, &freq) <= 0) {
|
||||
pw_log_error("param_eq:rate requires a number");
|
||||
spa_log_error(pl->log, "param_eq:rate requires a number");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
else if (spa_streq(key, "q")) {
|
||||
if (spa_json_parse_float(val, len, &q) <= 0) {
|
||||
pw_log_error("param_eq:q requires a float");
|
||||
spa_log_error(pl->log, "param_eq:q requires a float");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
else if (spa_streq(key, "gain")) {
|
||||
if (spa_json_parse_float(val, len, &gain) <= 0) {
|
||||
pw_log_error("param_eq:gain requires a float");
|
||||
spa_log_error(pl->log, "param_eq:gain requires a float");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
pw_log_warn("param_eq: ignoring filter key: '%s'", key);
|
||||
spa_log_warn(pl->log, "param_eq: ignoring filter key: '%s'", key);
|
||||
}
|
||||
}
|
||||
if (n == max_bq)
|
||||
return -ENOSPC;
|
||||
|
||||
pw_log_info("%d %s freq:%f q:%f gain:%f", n,
|
||||
spa_log_info(pl->log, "%d %s freq:%f q:%f gain:%f", n,
|
||||
bq_name_from_type(type), freq, q, gain);
|
||||
biquad_set(&bq[n++], type, freq * 2 / rate, q, gain);
|
||||
}
|
||||
|
|
@ -1875,6 +1899,7 @@ static int parse_filters(struct spa_json *iter, int rate, struct biquad *bq, uin
|
|||
static void *param_eq_instantiate(const struct fc_plugin *plugin, const struct fc_descriptor * Descriptor,
|
||||
unsigned long SampleRate, int index, const char *config)
|
||||
{
|
||||
struct plugin *pl = (struct plugin *) plugin;
|
||||
struct spa_json it[3];
|
||||
const char *val;
|
||||
char key[256], filename[PATH_MAX];
|
||||
|
|
@ -1883,13 +1908,13 @@ static void *param_eq_instantiate(const struct fc_plugin *plugin, const struct f
|
|||
uint32_t i, n_bq = 0;
|
||||
|
||||
if (config == NULL) {
|
||||
pw_log_error("param_eq: requires a config section");
|
||||
spa_log_error(pl->log, "param_eq: requires a config section");
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (spa_json_begin_object(&it[0], config, strlen(config)) <= 0) {
|
||||
pw_log_error("param_eq: config must be an object");
|
||||
spa_log_error(pl->log, "param_eq: config must be an object");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -1897,7 +1922,9 @@ static void *param_eq_instantiate(const struct fc_plugin *plugin, const struct f
|
|||
if (impl == NULL)
|
||||
return NULL;
|
||||
|
||||
impl->plugin = (struct plugin *) plugin;
|
||||
impl->plugin = pl;
|
||||
impl->dsp = pl->dsp;
|
||||
impl->log = pl->log;
|
||||
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);
|
||||
|
|
@ -1908,23 +1935,23 @@ static void *param_eq_instantiate(const struct fc_plugin *plugin, const struct f
|
|||
|
||||
if (spa_strstartswith(key, "filename")) {
|
||||
if (spa_json_parse_stringn(val, len, filename, sizeof(filename)) <= 0) {
|
||||
pw_log_error("param_eq: filename requires a string");
|
||||
spa_log_error(impl->log, "param_eq: filename requires a string");
|
||||
goto error;
|
||||
}
|
||||
if (spa_atoi32(key+8, &idx, 0))
|
||||
bq = &impl->bq[(SPA_CLAMP(idx, 1, 8) - 1) * PARAM_EQ_MAX];
|
||||
|
||||
res = load_eq_bands(filename, impl->rate, bq, PARAM_EQ_MAX, &n_bq);
|
||||
res = load_eq_bands(pl, filename, impl->rate, bq, PARAM_EQ_MAX, &n_bq);
|
||||
if (res < 0) {
|
||||
pw_log_error("param_eq: failed to parse configuration from '%s'", filename);
|
||||
spa_log_error(impl->log, "param_eq: failed to parse configuration from '%s'", filename);
|
||||
goto error;
|
||||
}
|
||||
pw_log_info("loaded %d biquads for channel %d", n_bq, idx);
|
||||
spa_log_info(impl->log, "loaded %d biquads for channel %d", n_bq, idx);
|
||||
impl->n_bq = SPA_MAX(impl->n_bq, n_bq);
|
||||
}
|
||||
else if (spa_strstartswith(key, "filters")) {
|
||||
if (!spa_json_is_array(val, len)) {
|
||||
pw_log_error("param_eq:filters require an array");
|
||||
spa_log_error(impl->log, "param_eq:filters require an array");
|
||||
goto error;
|
||||
}
|
||||
spa_json_enter(&it[0], &it[1]);
|
||||
|
|
@ -1932,15 +1959,15 @@ static void *param_eq_instantiate(const struct fc_plugin *plugin, const struct f
|
|||
if (spa_atoi32(key+7, &idx, 0))
|
||||
bq = &impl->bq[(SPA_CLAMP(idx, 1, 8) - 1) * PARAM_EQ_MAX];
|
||||
|
||||
res = parse_filters(&it[1], impl->rate, bq, PARAM_EQ_MAX, &n_bq);
|
||||
res = parse_filters(pl, &it[1], impl->rate, bq, PARAM_EQ_MAX, &n_bq);
|
||||
if (res < 0) {
|
||||
pw_log_error("param_eq: failed to parse configuration");
|
||||
spa_log_error(impl->log, "param_eq: failed to parse configuration");
|
||||
goto error;
|
||||
}
|
||||
pw_log_info("parsed %d biquads for channel %d", n_bq, idx);
|
||||
spa_log_info(impl->log, "parsed %d biquads for channel %d", n_bq, idx);
|
||||
impl->n_bq = SPA_MAX(impl->n_bq, n_bq);
|
||||
} else {
|
||||
pw_log_warn("param_eq: ignoring config key: '%s'", key);
|
||||
spa_log_warn(impl->log, "param_eq: ignoring config key: '%s'", key);
|
||||
}
|
||||
if (idx == 0) {
|
||||
for (i = 1; i < 8; i++)
|
||||
|
|
@ -1964,7 +1991,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(impl->plugin->dsp_ops, impl->bq, impl->n_bq, PARAM_EQ_MAX,
|
||||
dsp_ops_biquadn_run(impl->dsp, impl->bq, impl->n_bq, PARAM_EQ_MAX,
|
||||
&impl->port[8], (const float**)impl->port, 8, SampleCount);
|
||||
}
|
||||
|
||||
|
|
@ -2124,7 +2151,8 @@ struct fc_plugin *load_builtin_plugin(const struct spa_support *support, uint32_
|
|||
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;
|
||||
impl->dsp = dsp;
|
||||
pffft_select_cpu(dsp->cpu_flags);
|
||||
impl->log = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_Log);
|
||||
return (struct fc_plugin *) impl;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,15 +11,16 @@
|
|||
#include <spa/utils/defs.h>
|
||||
#include <spa/utils/list.h>
|
||||
#include <spa/utils/string.h>
|
||||
|
||||
#include <pipewire/log.h>
|
||||
#include <pipewire/utils.h>
|
||||
#include <spa/support/log.h>
|
||||
|
||||
#include "plugin.h"
|
||||
#include "ladspa.h"
|
||||
|
||||
struct plugin {
|
||||
struct fc_plugin plugin;
|
||||
|
||||
struct spa_log *log;
|
||||
|
||||
void *handle;
|
||||
LADSPA_Descriptor_Function desc_func;
|
||||
};
|
||||
|
|
@ -172,47 +173,70 @@ static void ladspa_unload(struct fc_plugin *plugin)
|
|||
free(p);
|
||||
}
|
||||
|
||||
static struct fc_plugin *ladspa_handle_load_by_path(const char *path)
|
||||
static struct fc_plugin *ladspa_handle_load_by_path(struct spa_log *log, const char *path)
|
||||
{
|
||||
struct plugin *p;
|
||||
int res;
|
||||
void *handle = NULL;
|
||||
LADSPA_Descriptor_Function desc_func;
|
||||
|
||||
p = calloc(1, sizeof(*p));
|
||||
if (!p)
|
||||
return NULL;
|
||||
|
||||
p->handle = dlopen(path, RTLD_NOW);
|
||||
if (!p->handle) {
|
||||
pw_log_debug("failed to open '%s': %s", path, dlerror());
|
||||
handle = dlopen(path, RTLD_NOW);
|
||||
if (handle == NULL) {
|
||||
spa_log_debug(log, "failed to open '%s': %s", path, dlerror());
|
||||
res = -ENOENT;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
pw_log_info("successfully opened '%s'", path);
|
||||
spa_log_info(log, "successfully opened '%s'", path);
|
||||
|
||||
p->desc_func = (LADSPA_Descriptor_Function) dlsym(p->handle, "ladspa_descriptor");
|
||||
if (!p->desc_func) {
|
||||
pw_log_warn("cannot find descriptor function in '%s': %s", path, dlerror());
|
||||
desc_func = (LADSPA_Descriptor_Function) dlsym(handle, "ladspa_descriptor");
|
||||
if (desc_func == NULL) {
|
||||
spa_log_warn(log, "cannot find descriptor function in '%s': %s", path, dlerror());
|
||||
res = -ENOSYS;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
p = calloc(1, sizeof(*p));
|
||||
if (!p) {
|
||||
res = -errno;
|
||||
goto exit;
|
||||
}
|
||||
p->log = log;
|
||||
p->handle = handle;
|
||||
p->desc_func = desc_func;
|
||||
p->plugin.make_desc = ladspa_make_desc;
|
||||
p->plugin.unload = ladspa_unload;
|
||||
|
||||
return &p->plugin;
|
||||
|
||||
exit:
|
||||
if (p->handle)
|
||||
dlclose(p->handle);
|
||||
free(p);
|
||||
if (handle)
|
||||
dlclose(handle);
|
||||
errno = -res;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline const char *split_walk(const char *str, const char *delimiter, size_t * len, const char **state)
|
||||
{
|
||||
const char *s = *state ? *state : str;
|
||||
|
||||
s += strspn(s, delimiter);
|
||||
if (*s == '\0')
|
||||
return NULL;
|
||||
|
||||
*len = strcspn(s, delimiter);
|
||||
*state = s + *len;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
struct fc_plugin *load_ladspa_plugin(const struct spa_support *support, uint32_t n_support,
|
||||
struct dsp_ops *dsp, const char *plugin, const struct spa_dict *info)
|
||||
{
|
||||
struct fc_plugin *pl = NULL;
|
||||
struct spa_log *log;
|
||||
|
||||
log = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_Log);
|
||||
|
||||
if (plugin[0] != '/') {
|
||||
const char *search_dirs, *p, *state = NULL;
|
||||
|
|
@ -230,7 +254,7 @@ struct fc_plugin *load_ladspa_plugin(const struct spa_support *support, uint32_t
|
|||
*/
|
||||
errno = ENAMETOOLONG;
|
||||
|
||||
while ((p = pw_split_walk(search_dirs, ":", &len, &state))) {
|
||||
while ((p = split_walk(search_dirs, ":", &len, &state))) {
|
||||
int pathlen;
|
||||
|
||||
if (len >= sizeof(path))
|
||||
|
|
@ -240,17 +264,17 @@ struct fc_plugin *load_ladspa_plugin(const struct spa_support *support, uint32_t
|
|||
if (pathlen < 0 || (size_t) pathlen >= sizeof(path))
|
||||
continue;
|
||||
|
||||
pl = ladspa_handle_load_by_path(path);
|
||||
pl = ladspa_handle_load_by_path(log, path);
|
||||
if (pl != NULL)
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
pl = ladspa_handle_load_by_path(plugin);
|
||||
pl = ladspa_handle_load_by_path(log, plugin);
|
||||
}
|
||||
|
||||
if (pl == NULL)
|
||||
pw_log_error("failed to load plugin '%s': %s", plugin, strerror(errno));
|
||||
spa_log_error(log, "failed to load plugin '%s': %s", plugin, strerror(errno));
|
||||
|
||||
return pl;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,16 +5,13 @@
|
|||
#include <dlfcn.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <lilv/lilv.h>
|
||||
|
||||
#include <spa/utils/defs.h>
|
||||
#include <spa/utils/list.h>
|
||||
#include <spa/utils/string.h>
|
||||
#include <spa/support/loop.h>
|
||||
|
||||
#include <pipewire/log.h>
|
||||
#include <pipewire/utils.h>
|
||||
#include <pipewire/array.h>
|
||||
|
||||
#include <lilv/lilv.h>
|
||||
#include <spa/support/log.h>
|
||||
|
||||
#if defined __has_include
|
||||
# if __has_include (<lv2/atom/atom.h>)
|
||||
|
|
@ -42,45 +39,48 @@
|
|||
static struct context *_context;
|
||||
|
||||
typedef struct URITable {
|
||||
struct pw_array array;
|
||||
char **data;
|
||||
size_t alloc;
|
||||
size_t len;
|
||||
} URITable;
|
||||
|
||||
static void uri_table_init(URITable *table)
|
||||
{
|
||||
pw_array_init(&table->array, 1024);
|
||||
table->data = NULL;
|
||||
table->len = table->alloc = 0;
|
||||
}
|
||||
|
||||
static void uri_table_destroy(URITable *table)
|
||||
{
|
||||
char **p;
|
||||
pw_array_for_each(p, &table->array)
|
||||
free(*p);
|
||||
pw_array_clear(&table->array);
|
||||
size_t i;
|
||||
for (i = 0; i < table->len; i++)
|
||||
free(table->data[i]);
|
||||
free(table->data);
|
||||
uri_table_init(table);
|
||||
}
|
||||
|
||||
static LV2_URID uri_table_map(LV2_URID_Map_Handle handle, const char *uri)
|
||||
{
|
||||
URITable *table = (URITable*)handle;
|
||||
char **p;
|
||||
size_t i = 0;
|
||||
size_t i;
|
||||
|
||||
pw_array_for_each(p, &table->array) {
|
||||
i++;
|
||||
if (spa_streq(*p, uri))
|
||||
goto done;
|
||||
for (i = 0; i < table->len; i++)
|
||||
if (spa_streq(table->data[i], uri))
|
||||
return i+1;
|
||||
|
||||
if (table->len == table->alloc) {
|
||||
table->alloc += 64;
|
||||
table->data = realloc(table->data, table->alloc * sizeof(char *));
|
||||
}
|
||||
pw_array_add_ptr(&table->array, strdup(uri));
|
||||
i = pw_array_get_len(&table->array, char*);
|
||||
done:
|
||||
return i;
|
||||
table->data[table->len++] = strdup(uri);
|
||||
return table->len;
|
||||
}
|
||||
|
||||
static const char *uri_table_unmap(LV2_URID_Map_Handle handle, LV2_URID urid)
|
||||
{
|
||||
URITable *table = (URITable*)handle;
|
||||
|
||||
if (urid > 0 && urid <= pw_array_get_len(&table->array, char*))
|
||||
return *pw_array_get_unchecked(&table->array, urid - 1, char*);
|
||||
if (urid > 0 && urid <= table->len)
|
||||
return table->data[urid-1];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -88,6 +88,7 @@ struct context {
|
|||
int ref;
|
||||
LilvWorld *world;
|
||||
|
||||
struct spa_log *log;
|
||||
struct spa_loop *data_loop;
|
||||
struct spa_loop *main_loop;
|
||||
|
||||
|
|
@ -185,6 +186,7 @@ static struct context *context_new(const struct spa_support *support, uint32_t n
|
|||
c->atom_Int = context_map(c, LV2_ATOM__Int);
|
||||
c->atom_Float = context_map(c, LV2_ATOM__Float);
|
||||
|
||||
c->log = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_Log);
|
||||
c->data_loop = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_DataLoop);
|
||||
c->main_loop = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_Loop);
|
||||
|
||||
|
|
@ -475,7 +477,7 @@ struct fc_plugin *pipewire__filter_chain_plugin_load(const struct spa_support *s
|
|||
|
||||
uri = lilv_new_uri(c->world, plugin_uri);
|
||||
if (uri == NULL) {
|
||||
pw_log_warn("invalid URI %s", plugin_uri);
|
||||
spa_log_warn(c->log, "invalid URI %s", plugin_uri);
|
||||
res = -EINVAL;
|
||||
goto error_unref;
|
||||
}
|
||||
|
|
@ -485,7 +487,7 @@ struct fc_plugin *pipewire__filter_chain_plugin_load(const struct spa_support *s
|
|||
lilv_node_free(uri);
|
||||
|
||||
if (plugin == NULL) {
|
||||
pw_log_warn("can't load plugin %s", plugin_uri);
|
||||
spa_log_warn(c->log, "can't load plugin %s", plugin_uri);
|
||||
res = -EINVAL;
|
||||
goto error_unref;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,8 +4,7 @@
|
|||
|
||||
#include <spa/utils/json.h>
|
||||
#include <spa/support/loop.h>
|
||||
|
||||
#include <pipewire/log.h>
|
||||
#include <spa/support/log.h>
|
||||
|
||||
#include "plugin.h"
|
||||
#include "convolver.h"
|
||||
|
|
@ -16,7 +15,9 @@
|
|||
|
||||
struct plugin {
|
||||
struct fc_plugin plugin;
|
||||
struct dsp_ops *dsp_ops;
|
||||
|
||||
struct dsp_ops *dsp;
|
||||
struct spa_log *log;
|
||||
struct spa_loop *data_loop;
|
||||
struct spa_loop *main_loop;
|
||||
uint32_t quantum_limit;
|
||||
|
|
@ -24,6 +25,10 @@ struct plugin {
|
|||
|
||||
struct spatializer_impl {
|
||||
struct plugin *plugin;
|
||||
|
||||
struct dsp_ops *dsp;
|
||||
struct spa_log *log;
|
||||
|
||||
unsigned long rate;
|
||||
float *port[6];
|
||||
int n_samples, blocksize, tailsize;
|
||||
|
|
@ -39,6 +44,7 @@ static void * spatializer_instantiate(const struct fc_plugin *plugin, const stru
|
|||
unsigned long SampleRate, int index, const char *config)
|
||||
{
|
||||
struct spatializer_impl *impl;
|
||||
struct plugin *pl = (struct plugin*) plugin;
|
||||
struct spa_json it[1];
|
||||
const char *val;
|
||||
char key[256];
|
||||
|
|
@ -47,12 +53,12 @@ static void * spatializer_instantiate(const struct fc_plugin *plugin, const stru
|
|||
|
||||
errno = EINVAL;
|
||||
if (config == NULL) {
|
||||
pw_log_error("spatializer: no config was given");
|
||||
spa_log_error(pl->log, "spatializer: no config was given");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (spa_json_begin_object(&it[0], config, strlen(config)) <= 0) {
|
||||
pw_log_error("spatializer: expected object in config");
|
||||
spa_log_error(pl->log, "spatializer: expected object in config");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -62,33 +68,35 @@ static void * spatializer_instantiate(const struct fc_plugin *plugin, const stru
|
|||
return NULL;
|
||||
}
|
||||
|
||||
impl->plugin = (struct plugin *) plugin;
|
||||
impl->plugin = pl;
|
||||
impl->dsp = pl->dsp;
|
||||
impl->log = pl->log;
|
||||
|
||||
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) {
|
||||
pw_log_error("spatializer:blocksize requires a number");
|
||||
spa_log_error(impl->log, "spatializer:blocksize requires a number");
|
||||
errno = EINVAL;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
else if (spa_streq(key, "tailsize")) {
|
||||
if (spa_json_parse_int(val, len, &impl->tailsize) <= 0) {
|
||||
pw_log_error("spatializer:tailsize requires a number");
|
||||
spa_log_error(impl->log, "spatializer:tailsize requires a number");
|
||||
errno = EINVAL;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
else if (spa_streq(key, "filename")) {
|
||||
if (spa_json_parse_stringn(val, len, filename, sizeof(filename)) <= 0) {
|
||||
pw_log_error("spatializer:filename requires a string");
|
||||
spa_log_error(impl->log, "spatializer:filename requires a string");
|
||||
errno = EINVAL;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!filename[0]) {
|
||||
pw_log_error("spatializer:filename was not given");
|
||||
spa_log_error(impl->log, "spatializer:filename was not given");
|
||||
errno = EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
|
@ -166,7 +174,7 @@ static void * spatializer_instantiate(const struct fc_plugin *plugin, const stru
|
|||
reason = "Internal error";
|
||||
break;
|
||||
}
|
||||
pw_log_error("Unable to load HRTF from %s: %s (%d)", filename, reason, ret);
|
||||
spa_log_error(impl->log, "Unable to load HRTF from %s: %s (%d)", filename, reason, ret);
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
|
@ -175,7 +183,7 @@ static void * spatializer_instantiate(const struct fc_plugin *plugin, const stru
|
|||
if (impl->tailsize <= 0)
|
||||
impl->tailsize = SPA_CLAMP(4096, impl->blocksize, 32768);
|
||||
|
||||
pw_log_info("using n_samples:%u %d:%d blocksize sofa:%s", impl->n_samples,
|
||||
spa_log_info(impl->log, "using n_samples:%u %d:%d blocksize sofa:%s", impl->n_samples,
|
||||
impl->blocksize, impl->tailsize, filename);
|
||||
|
||||
impl->tmp[0] = calloc(impl->plugin->quantum_limit, sizeof(float));
|
||||
|
|
@ -219,7 +227,7 @@ static void spatializer_reload(void * Instance)
|
|||
for (uint8_t i = 0; i < 3; i++)
|
||||
coords[i] = impl->port[3 + i][0];
|
||||
|
||||
pw_log_info("making spatializer with %f %f %f", coords[0], coords[1], coords[2]);
|
||||
spa_log_info(impl->log, "making spatializer with %f %f %f", coords[0], coords[1], coords[2]);
|
||||
|
||||
mysofa_s2c(coords);
|
||||
mysofa_getfilter_float(
|
||||
|
|
@ -235,23 +243,23 @@ static void spatializer_reload(void * Instance)
|
|||
|
||||
// TODO: make use of delay
|
||||
if ((left_delay != 0.0f || right_delay != 0.0f) && (!isnan(left_delay) || !isnan(right_delay)))
|
||||
pw_log_warn("delay dropped l: %f, r: %f", left_delay, right_delay);
|
||||
spa_log_warn(impl->log, "delay dropped l: %f, r: %f", left_delay, right_delay);
|
||||
|
||||
if (impl->l_conv[2])
|
||||
convolver_free(impl->l_conv[2]);
|
||||
if (impl->r_conv[2])
|
||||
convolver_free(impl->r_conv[2]);
|
||||
|
||||
impl->l_conv[2] = convolver_new(impl->plugin->dsp_ops, impl->blocksize, impl->tailsize,
|
||||
impl->l_conv[2] = convolver_new(impl->dsp, impl->blocksize, impl->tailsize,
|
||||
left_ir, impl->n_samples);
|
||||
impl->r_conv[2] = convolver_new(impl->plugin->dsp_ops, impl->blocksize, impl->tailsize,
|
||||
impl->r_conv[2] = convolver_new(impl->dsp, impl->blocksize, impl->tailsize,
|
||||
right_ir, impl->n_samples);
|
||||
|
||||
free(left_ir);
|
||||
free(right_ir);
|
||||
|
||||
if (impl->l_conv[2] == NULL || impl->r_conv[2] == NULL) {
|
||||
pw_log_error("reloading left or right convolver failed");
|
||||
spa_log_error(impl->log, "reloading left or right convolver failed");
|
||||
return;
|
||||
}
|
||||
spa_loop_invoke(impl->plugin->data_loop, do_switch, 1, NULL, 0, true, impl);
|
||||
|
|
@ -438,11 +446,12 @@ struct fc_plugin *pipewire__filter_chain_plugin_load(const struct spa_support *s
|
|||
if (spa_streq(k, "clock.quantum-limit"))
|
||||
spa_atou32(s, &impl->quantum_limit, 0);
|
||||
}
|
||||
impl->dsp_ops = dsp;
|
||||
impl->dsp = dsp;
|
||||
pffft_select_cpu(dsp->cpu_flags);
|
||||
|
||||
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);
|
||||
impl->log = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_Log);
|
||||
|
||||
return (struct fc_plugin *) impl;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue