mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-05 13:30:02 -05:00
spatializer: move to sofa_plugin
This commit is contained in:
parent
8677cb2fdf
commit
9399fc318e
5 changed files with 315 additions and 282 deletions
|
|
@ -108,6 +108,7 @@ filter_chain_sources = [
|
|||
'module-filter-chain/biquad.c',
|
||||
'module-filter-chain/ladspa_plugin.c',
|
||||
'module-filter-chain/builtin_plugin.c',
|
||||
'module-filter-chain/sofa_plugin.c',
|
||||
'module-filter-chain/convolver.c'
|
||||
]
|
||||
filter_chain_dependencies = [
|
||||
|
|
|
|||
|
|
@ -1205,6 +1205,9 @@ static struct plugin *plugin_load(struct impl *impl, const char *type, const cha
|
|||
if (spa_streq(type, "builtin")) {
|
||||
pl = load_builtin_plugin(support, n_support, &impl->dsp, path, NULL);
|
||||
}
|
||||
else if (spa_streq(type, "sofa")) {
|
||||
pl = load_sofa_plugin(support, n_support, &impl->dsp, path, NULL);
|
||||
}
|
||||
else if (spa_streq(type, "ladspa")) {
|
||||
pl = load_ladspa_plugin(support, n_support, &impl->dsp, path, NULL);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,16 +26,10 @@
|
|||
|
||||
#include <float.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifdef HAVE_SNDFILE
|
||||
#include <sndfile.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBMYSOFA
|
||||
#include <mysofa.h>
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#include <spa/utils/json.h>
|
||||
#include <spa/utils/result.h>
|
||||
#include <spa/support/cpu.h>
|
||||
|
|
@ -52,14 +46,6 @@
|
|||
|
||||
#define MAX_RATES 32u
|
||||
|
||||
#ifdef HAVE_LIBMYSOFA
|
||||
// > If your program is using several threads, you must use
|
||||
// > appropriate synchronisation mechanisms so only
|
||||
// > a single thread can access the mysofa_open_cached
|
||||
// > and mysofa_close_cached functions at a given time.
|
||||
static pthread_mutex_t libmysofa_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
#endif
|
||||
|
||||
static struct dsp_ops *dsp_ops;
|
||||
|
||||
struct builtin {
|
||||
|
|
@ -861,272 +847,6 @@ static const struct fc_descriptor convolve_desc = {
|
|||
.cleanup = convolver_cleanup,
|
||||
};
|
||||
|
||||
struct spatializer_impl {
|
||||
unsigned long rate;
|
||||
float *port[64];
|
||||
float old_coords[3];
|
||||
float coords[3];
|
||||
int n_samples, blocksize, tailsize;
|
||||
|
||||
#ifdef HAVE_LIBMYSOFA
|
||||
struct MYSOFA_EASY *sofa;
|
||||
#endif
|
||||
|
||||
struct convolver *l_conv;
|
||||
struct convolver *r_conv;
|
||||
};
|
||||
|
||||
static void * spatializer_instantiate(const struct fc_descriptor * Descriptor,
|
||||
unsigned long SampleRate, int index, const char *config)
|
||||
{
|
||||
#ifdef HAVE_LIBMYSOFA
|
||||
struct spatializer_impl *impl;
|
||||
struct spa_json it[2];
|
||||
const char *val;
|
||||
char key[256];
|
||||
char filename[PATH_MAX] = "";
|
||||
|
||||
errno = EINVAL;
|
||||
if (config == NULL)
|
||||
return NULL;
|
||||
|
||||
spa_json_init(&it[0], config, strlen(config));
|
||||
if (spa_json_enter_object(&it[0], &it[1]) <= 0)
|
||||
return NULL;
|
||||
|
||||
impl = calloc(1, sizeof(*impl));
|
||||
if (impl == NULL)
|
||||
goto error;
|
||||
|
||||
while (spa_json_get_string(&it[1], key, sizeof(key)) > 0) {
|
||||
if (spa_streq(key, "blocksize")) {
|
||||
if (spa_json_get_int(&it[1], &impl->blocksize) <= 0) {
|
||||
pw_log_error("spatializer:blocksize requires a number");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else if (spa_streq(key, "tailsize")) {
|
||||
if (spa_json_get_int(&it[1], &impl->tailsize) <= 0) {
|
||||
pw_log_error("spatializer:tailsize requires a number");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else if (spa_streq(key, "filename")) {
|
||||
if (spa_json_get_string(&it[1], filename, sizeof(filename)) <= 0) {
|
||||
pw_log_error("spatializer:filename requires a string");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else if (spa_json_next(&it[1], &val) < 0)
|
||||
break;
|
||||
}
|
||||
if (!filename[0]) {
|
||||
pw_log_error("spatializer:filename was not given");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int ret = MYSOFA_OK;
|
||||
|
||||
pthread_mutex_lock(&libmysofa_mutex);
|
||||
impl->sofa = mysofa_open_cached(filename, SampleRate, &impl->n_samples, &ret);
|
||||
pthread_mutex_unlock(&libmysofa_mutex);
|
||||
|
||||
if (ret != MYSOFA_OK) {
|
||||
pw_log_error("Unable to load HRTF from %s: %d %m", filename, ret);
|
||||
errno = ENOENT;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < 3; i++) {
|
||||
impl->old_coords[i] = impl->coords[i] =
|
||||
impl->port[3 + i] ? impl->port[3 + i][0] : 0.0f;
|
||||
impl->old_coords[i] = impl->coords[i] = NAN;
|
||||
}
|
||||
|
||||
mysofa_s2c(impl->coords);
|
||||
|
||||
mysofa_getfilter_float(
|
||||
impl->sofa,
|
||||
impl->coords[0],
|
||||
impl->coords[1],
|
||||
impl->coords[2],
|
||||
left_ir,
|
||||
right_ir,
|
||||
&left_delay,
|
||||
&right_delay
|
||||
);
|
||||
|
||||
// TODO: make use of delay
|
||||
if ((left_delay || right_delay) && (!isnan(left_delay) || !isnan(right_delay))) {
|
||||
pw_log_warn("delay dropped l: %f, r: %f", left_delay, right_delay);
|
||||
}
|
||||
|
||||
if (impl->blocksize <= 0)
|
||||
impl->blocksize = SPA_CLAMP(impl->n_samples, 64, 256);
|
||||
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,
|
||||
impl->blocksize, impl->tailsize, filename);
|
||||
|
||||
impl->rate = SampleRate;
|
||||
return impl;
|
||||
error:
|
||||
if (impl->sofa) {
|
||||
pthread_mutex_lock(&libmysofa_mutex);
|
||||
mysofa_close_cached(impl->sofa);
|
||||
pthread_mutex_unlock(&libmysofa_mutex);
|
||||
}
|
||||
|
||||
free(impl);
|
||||
return NULL;
|
||||
#else
|
||||
pw_log_error("libmysofa is required for spatializer, but disabled at compile time");
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void spatializer_run(void * Instance, unsigned long SampleCount)
|
||||
{
|
||||
#ifdef HAVE_LIBMYSOFA
|
||||
struct spatializer_impl *impl = Instance;
|
||||
|
||||
bool reload = false;
|
||||
for (uint8_t i = 0; i < 3; i++) {
|
||||
if ((impl->port[3 + i] && impl->old_coords[i] != impl->port[3 + i][0])
|
||||
|| isnan(impl->old_coords[i])) {
|
||||
reload = true;
|
||||
}
|
||||
impl->old_coords[i] = impl->coords[i] =
|
||||
impl->port[3 + i][0];
|
||||
}
|
||||
|
||||
if (reload) {
|
||||
float *left_ir = calloc(impl->n_samples, sizeof(float));
|
||||
float *right_ir = calloc(impl->n_samples, sizeof(float));
|
||||
float left_delay;
|
||||
float right_delay;
|
||||
|
||||
mysofa_s2c(impl->coords);
|
||||
|
||||
mysofa_getfilter_float(
|
||||
impl->sofa,
|
||||
impl->coords[0],
|
||||
impl->coords[1],
|
||||
impl->coords[2],
|
||||
left_ir,
|
||||
right_ir,
|
||||
&left_delay,
|
||||
&right_delay
|
||||
);
|
||||
|
||||
// TODO: make use of delay
|
||||
if ((left_delay || right_delay) && (!isnan(left_delay) || !isnan(right_delay))) {
|
||||
pw_log_warn("delay dropped l: %f, r: %f", left_delay, right_delay);
|
||||
}
|
||||
|
||||
if (impl->l_conv)
|
||||
convolver_free(impl->l_conv);
|
||||
impl->l_conv = convolver_new(dsp_ops, impl->blocksize, impl->tailsize, left_ir, impl->n_samples);
|
||||
free(left_ir);
|
||||
if (impl->l_conv == NULL) {
|
||||
pw_log_error("reloading left convolver failed");
|
||||
return;
|
||||
}
|
||||
|
||||
if (impl->r_conv)
|
||||
convolver_free(impl->r_conv);
|
||||
impl->r_conv = convolver_new(dsp_ops, impl->blocksize, impl->tailsize, right_ir, impl->n_samples);
|
||||
free(right_ir);
|
||||
if (impl->r_conv == NULL) {
|
||||
pw_log_error("reloading right convolver failed");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
convolver_run(impl->l_conv, impl->port[2], impl->port[0], SampleCount);
|
||||
convolver_run(impl->r_conv, impl->port[2], impl->port[1], SampleCount);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void spatializer_connect_port(void * Instance, unsigned long Port,
|
||||
float * DataLocation)
|
||||
{
|
||||
struct spatializer_impl *impl = Instance;
|
||||
impl->port[Port] = DataLocation;
|
||||
}
|
||||
|
||||
static void spatializer_cleanup(void * Instance)
|
||||
{
|
||||
struct spatializer_impl *impl = Instance;
|
||||
if (impl->l_conv)
|
||||
convolver_free(impl->l_conv);
|
||||
if (impl->r_conv)
|
||||
convolver_free(impl->r_conv);
|
||||
#ifdef HAVE_LIBMYSOFA
|
||||
if (impl->sofa) {
|
||||
pthread_mutex_lock(&libmysofa_mutex);
|
||||
mysofa_close_cached(impl->sofa);
|
||||
pthread_mutex_unlock(&libmysofa_mutex);
|
||||
}
|
||||
#endif
|
||||
free(impl);
|
||||
}
|
||||
|
||||
static struct fc_port spatializer_ports[] = {
|
||||
{ .index = 0,
|
||||
.name = "Out L",
|
||||
.flags = FC_PORT_OUTPUT | FC_PORT_AUDIO,
|
||||
},
|
||||
{ .index = 1,
|
||||
.name = "Out R",
|
||||
.flags = FC_PORT_OUTPUT | FC_PORT_AUDIO,
|
||||
},
|
||||
{ .index = 2,
|
||||
.name = "In",
|
||||
.flags = FC_PORT_INPUT | FC_PORT_AUDIO,
|
||||
},
|
||||
|
||||
{ .index = 3,
|
||||
.name = "Azimuth",
|
||||
.flags = FC_PORT_INPUT | FC_PORT_CONTROL,
|
||||
.def = 0.0f, .min = 0.0f, .max = 360.0f
|
||||
},
|
||||
{ .index = 4,
|
||||
.name = "Elevation",
|
||||
.flags = FC_PORT_INPUT | FC_PORT_CONTROL,
|
||||
.def = 0.0f, .min = -90.0f, .max = 90.0f
|
||||
},
|
||||
{ .index = 5,
|
||||
.name = "Radius",
|
||||
.flags = FC_PORT_INPUT | FC_PORT_CONTROL,
|
||||
.def = 1.0f, .min = 0.0f, .max = 100.0f
|
||||
},
|
||||
};
|
||||
|
||||
static void spatializer_deactivate(void * Instance)
|
||||
{
|
||||
struct spatializer_impl *impl = Instance;
|
||||
if (impl->l_conv)
|
||||
convolver_reset(impl->l_conv);
|
||||
if (impl->r_conv)
|
||||
convolver_reset(impl->r_conv);
|
||||
}
|
||||
|
||||
static const struct fc_descriptor spatializer_desc = {
|
||||
.name = "spatializer",
|
||||
|
||||
.n_ports = 6,
|
||||
.ports = spatializer_ports,
|
||||
|
||||
.instantiate = spatializer_instantiate,
|
||||
.connect_port = spatializer_connect_port,
|
||||
.deactivate = spatializer_deactivate,
|
||||
.run = spatializer_run,
|
||||
.cleanup = spatializer_cleanup,
|
||||
};
|
||||
|
||||
/** delay */
|
||||
struct delay_impl {
|
||||
unsigned long rate;
|
||||
|
|
@ -1285,8 +1005,6 @@ static const struct fc_descriptor * builtin_descriptor(unsigned long Index)
|
|||
return &convolve_desc;
|
||||
case 11:
|
||||
return &delay_desc;
|
||||
case 12:
|
||||
return &spatializer_desc;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -108,5 +108,7 @@ struct fc_plugin *load_lv2_plugin(const struct spa_support *support, uint32_t n_
|
|||
struct dsp_ops *dsp, const char *path, const char *config);
|
||||
struct fc_plugin *load_builtin_plugin(const struct spa_support *support, uint32_t n_support,
|
||||
struct dsp_ops *dsp, const char *path, const char *config);
|
||||
struct fc_plugin *load_sofa_plugin(const struct spa_support *support, uint32_t n_support,
|
||||
struct dsp_ops *dsp, const char *path, const char *config);
|
||||
|
||||
#endif /* PLUGIN_H */
|
||||
|
|
|
|||
309
src/modules/module-filter-chain/sofa_plugin.c
Normal file
309
src/modules/module-filter-chain/sofa_plugin.c
Normal file
|
|
@ -0,0 +1,309 @@
|
|||
#include "config.h"
|
||||
|
||||
#include <spa/utils/json.h>
|
||||
#include <pipewire/log.h>
|
||||
#include "plugin.h"
|
||||
#include "convolver.h"
|
||||
#include "dsp-ops.h"
|
||||
#include "pffft.h"
|
||||
|
||||
#ifdef HAVE_LIBMYSOFA
|
||||
#include <mysofa.h>
|
||||
#include <pthread.h>
|
||||
|
||||
// > If your program is using several threads, you must use
|
||||
// > appropriate synchronisation mechanisms so only
|
||||
// > a single thread can access the mysofa_open_cached
|
||||
// > and mysofa_close_cached functions at a given time.
|
||||
static pthread_mutex_t libmysofa_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
#endif
|
||||
|
||||
static struct dsp_ops *dsp_ops;
|
||||
|
||||
struct spatializer_impl {
|
||||
unsigned long rate;
|
||||
float *port[64];
|
||||
float old_coords[3];
|
||||
float coords[3];
|
||||
int n_samples, blocksize, tailsize;
|
||||
|
||||
#ifdef HAVE_LIBMYSOFA
|
||||
struct MYSOFA_EASY *sofa;
|
||||
#endif
|
||||
|
||||
struct convolver *l_conv;
|
||||
struct convolver *r_conv;
|
||||
};
|
||||
|
||||
static void * spatializer_instantiate(const struct fc_descriptor * Descriptor,
|
||||
unsigned long SampleRate, int index, const char *config)
|
||||
{
|
||||
#ifdef HAVE_LIBMYSOFA
|
||||
struct spatializer_impl *impl;
|
||||
struct spa_json it[2];
|
||||
const char *val;
|
||||
char key[256];
|
||||
char filename[PATH_MAX] = "";
|
||||
|
||||
errno = EINVAL;
|
||||
if (config == NULL)
|
||||
return NULL;
|
||||
|
||||
spa_json_init(&it[0], config, strlen(config));
|
||||
if (spa_json_enter_object(&it[0], &it[1]) <= 0)
|
||||
return NULL;
|
||||
|
||||
impl = calloc(1, sizeof(*impl));
|
||||
if (impl == NULL) {
|
||||
errno = ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
|
||||
while (spa_json_get_string(&it[1], key, sizeof(key)) > 0) {
|
||||
if (spa_streq(key, "blocksize")) {
|
||||
if (spa_json_get_int(&it[1], &impl->blocksize) <= 0) {
|
||||
pw_log_error("spatializer:blocksize requires a number");
|
||||
errno = EINVAL;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
else if (spa_streq(key, "tailsize")) {
|
||||
if (spa_json_get_int(&it[1], &impl->tailsize) <= 0) {
|
||||
pw_log_error("spatializer:tailsize requires a number");
|
||||
errno = EINVAL;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
else if (spa_streq(key, "filename")) {
|
||||
if (spa_json_get_string(&it[1], filename, sizeof(filename)) <= 0) {
|
||||
pw_log_error("spatializer:filename requires a string");
|
||||
errno = EINVAL;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
else if (spa_json_next(&it[1], &val) < 0)
|
||||
break;
|
||||
}
|
||||
if (!filename[0]) {
|
||||
pw_log_error("spatializer:filename was not given");
|
||||
errno = EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
int ret = MYSOFA_OK;
|
||||
|
||||
pthread_mutex_lock(&libmysofa_mutex);
|
||||
impl->sofa = mysofa_open_cached(filename, SampleRate, &impl->n_samples, &ret);
|
||||
pthread_mutex_unlock(&libmysofa_mutex);
|
||||
|
||||
if (ret != MYSOFA_OK) {
|
||||
pw_log_error("Unable to load HRTF from %s: %d %m", filename, ret);
|
||||
errno = ENOENT;
|
||||
goto error;
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < 3; i++) {
|
||||
impl->old_coords[i] = impl->coords[i] = NAN;
|
||||
}
|
||||
|
||||
if (impl->blocksize <= 0)
|
||||
impl->blocksize = SPA_CLAMP(impl->n_samples, 64, 256);
|
||||
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,
|
||||
impl->blocksize, impl->tailsize, filename);
|
||||
|
||||
impl->rate = SampleRate;
|
||||
return impl;
|
||||
error:
|
||||
if (impl->sofa) {
|
||||
pthread_mutex_lock(&libmysofa_mutex);
|
||||
mysofa_close_cached(impl->sofa);
|
||||
pthread_mutex_unlock(&libmysofa_mutex);
|
||||
}
|
||||
free(impl);
|
||||
return NULL;
|
||||
#else
|
||||
pw_log_error("libmysofa is required for spatializer, but disabled at compile time");
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void spatializer_run(void * Instance, unsigned long SampleCount)
|
||||
{
|
||||
#ifdef HAVE_LIBMYSOFA
|
||||
struct spatializer_impl *impl = Instance;
|
||||
|
||||
bool reload = false;
|
||||
for (uint8_t i = 0; i < 3; i++) {
|
||||
if ((impl->port[3 + i] && impl->old_coords[i] != impl->port[3 + i][0])
|
||||
|| isnan(impl->old_coords[i])) {
|
||||
reload = true;
|
||||
}
|
||||
impl->old_coords[i] = impl->coords[i] =
|
||||
impl->port[3 + i][0];
|
||||
}
|
||||
|
||||
if (reload) {
|
||||
float *left_ir = calloc(impl->n_samples, sizeof(float));
|
||||
float *right_ir = calloc(impl->n_samples, sizeof(float));
|
||||
float left_delay;
|
||||
float right_delay;
|
||||
|
||||
mysofa_s2c(impl->coords);
|
||||
mysofa_getfilter_float(
|
||||
impl->sofa,
|
||||
impl->coords[0],
|
||||
impl->coords[1],
|
||||
impl->coords[2],
|
||||
left_ir,
|
||||
right_ir,
|
||||
&left_delay,
|
||||
&right_delay
|
||||
);
|
||||
|
||||
// TODO: make use of delay
|
||||
if ((left_delay || right_delay) && (!isnan(left_delay) || !isnan(right_delay))) {
|
||||
pw_log_warn("delay dropped l: %f, r: %f", left_delay, right_delay);
|
||||
}
|
||||
|
||||
if (impl->l_conv)
|
||||
convolver_free(impl->l_conv);
|
||||
impl->l_conv = convolver_new(dsp_ops, impl->blocksize, impl->tailsize, left_ir, impl->n_samples);
|
||||
free(left_ir);
|
||||
if (impl->l_conv == NULL) {
|
||||
pw_log_error("reloading left convolver failed");
|
||||
return;
|
||||
}
|
||||
|
||||
if (impl->r_conv)
|
||||
convolver_free(impl->r_conv);
|
||||
impl->r_conv = convolver_new(dsp_ops, impl->blocksize, impl->tailsize, right_ir, impl->n_samples);
|
||||
free(right_ir);
|
||||
if (impl->r_conv == NULL) {
|
||||
pw_log_error("reloading right convolver failed");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
convolver_run(impl->l_conv, impl->port[2], impl->port[0], SampleCount);
|
||||
convolver_run(impl->r_conv, impl->port[2], impl->port[1], SampleCount);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void spatializer_connect_port(void * Instance, unsigned long Port,
|
||||
float * DataLocation)
|
||||
{
|
||||
struct spatializer_impl *impl = Instance;
|
||||
impl->port[Port] = DataLocation;
|
||||
}
|
||||
|
||||
static void spatializer_cleanup(void * Instance)
|
||||
{
|
||||
struct spatializer_impl *impl = Instance;
|
||||
if (impl->l_conv)
|
||||
convolver_free(impl->l_conv);
|
||||
if (impl->r_conv)
|
||||
convolver_free(impl->r_conv);
|
||||
|
||||
#ifdef HAVE_LIBMYSOFA
|
||||
if (impl->sofa) {
|
||||
pthread_mutex_lock(&libmysofa_mutex);
|
||||
mysofa_close_cached(impl->sofa);
|
||||
pthread_mutex_unlock(&libmysofa_mutex);
|
||||
}
|
||||
#endif
|
||||
|
||||
free(impl);
|
||||
}
|
||||
|
||||
static void spatializer_deactivate(void * Instance)
|
||||
{
|
||||
struct spatializer_impl *impl = Instance;
|
||||
if (impl->l_conv)
|
||||
convolver_reset(impl->l_conv);
|
||||
if (impl->r_conv)
|
||||
convolver_reset(impl->r_conv);
|
||||
}
|
||||
|
||||
static struct fc_port spatializer_ports[] = {
|
||||
{ .index = 0,
|
||||
.name = "Out L",
|
||||
.flags = FC_PORT_OUTPUT | FC_PORT_AUDIO,
|
||||
},
|
||||
{ .index = 1,
|
||||
.name = "Out R",
|
||||
.flags = FC_PORT_OUTPUT | FC_PORT_AUDIO,
|
||||
},
|
||||
{ .index = 2,
|
||||
.name = "In",
|
||||
.flags = FC_PORT_INPUT | FC_PORT_AUDIO,
|
||||
},
|
||||
|
||||
{ .index = 3,
|
||||
.name = "Azimuth",
|
||||
.flags = FC_PORT_INPUT | FC_PORT_CONTROL,
|
||||
.def = 0.0f, .min = 0.0f, .max = 360.0f
|
||||
},
|
||||
{ .index = 4,
|
||||
.name = "Elevation",
|
||||
.flags = FC_PORT_INPUT | FC_PORT_CONTROL,
|
||||
.def = 0.0f, .min = -90.0f, .max = 90.0f
|
||||
},
|
||||
{ .index = 5,
|
||||
.name = "Radius",
|
||||
.flags = FC_PORT_INPUT | FC_PORT_CONTROL,
|
||||
.def = 1.0f, .min = 0.0f, .max = 100.0f
|
||||
},
|
||||
};
|
||||
|
||||
static const struct fc_descriptor spatializer_desc = {
|
||||
.name = "spatializer",
|
||||
|
||||
.n_ports = 6,
|
||||
.ports = spatializer_ports,
|
||||
|
||||
.instantiate = spatializer_instantiate,
|
||||
.connect_port = spatializer_connect_port,
|
||||
.deactivate = spatializer_deactivate,
|
||||
.run = spatializer_run,
|
||||
.cleanup = spatializer_cleanup,
|
||||
};
|
||||
|
||||
static const struct fc_descriptor * sofa_descriptor(unsigned long Index)
|
||||
{
|
||||
switch(Index) {
|
||||
case 0:
|
||||
return &spatializer_desc;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static const struct fc_descriptor *sofa_make_desc(struct fc_plugin *plugin, const char *name)
|
||||
{
|
||||
unsigned long i;
|
||||
for (i = 0; ;i++) {
|
||||
const struct fc_descriptor *d = sofa_descriptor(i);
|
||||
if (d == NULL)
|
||||
break;
|
||||
if (spa_streq(d->name, name))
|
||||
return d;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct fc_plugin builtin_plugin = {
|
||||
.make_desc = sofa_make_desc
|
||||
};
|
||||
|
||||
struct fc_plugin *load_sofa_plugin(const struct spa_support *support, uint32_t n_support,
|
||||
struct dsp_ops *dsp, const char *plugin, const char *config)
|
||||
{
|
||||
dsp_ops = dsp;
|
||||
pffft_select_cpu(dsp->cpu_flags);
|
||||
return &builtin_plugin;
|
||||
}
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue