mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-02 09:01:50 -05:00
spatializer: move coords to control ports
Allows for simple cases with moveable sources
This commit is contained in:
parent
3e0dc2678b
commit
7977755dd0
1 changed files with 109 additions and 70 deletions
|
|
@ -864,6 +864,13 @@ static const struct fc_descriptor convolve_desc = {
|
||||||
struct spatializer_impl {
|
struct spatializer_impl {
|
||||||
unsigned long rate;
|
unsigned long rate;
|
||||||
float *port[64];
|
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 *l_conv;
|
||||||
struct convolver *r_conv;
|
struct convolver *r_conv;
|
||||||
|
|
@ -874,15 +881,10 @@ static void * spatializer_instantiate(const struct fc_descriptor * Descriptor,
|
||||||
{
|
{
|
||||||
#ifdef HAVE_LIBMYSOFA
|
#ifdef HAVE_LIBMYSOFA
|
||||||
struct spatializer_impl *impl;
|
struct spatializer_impl *impl;
|
||||||
float *samples = NULL;
|
|
||||||
int offset = 0, length = 0, n_samples;
|
|
||||||
struct spa_json it[2];
|
struct spa_json it[2];
|
||||||
const char *val;
|
const char *val;
|
||||||
char key[256];
|
char key[256];
|
||||||
char filename[PATH_MAX] = "";
|
char filename[PATH_MAX] = "";
|
||||||
int blocksize = 0, tailsize = 0;
|
|
||||||
float coords[3] = { 0, 0, 1 };
|
|
||||||
struct MYSOFA_EASY *sofa;
|
|
||||||
|
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
if (config == NULL)
|
if (config == NULL)
|
||||||
|
|
@ -892,15 +894,19 @@ static void * spatializer_instantiate(const struct fc_descriptor * Descriptor,
|
||||||
if (spa_json_enter_object(&it[0], &it[1]) <= 0)
|
if (spa_json_enter_object(&it[0], &it[1]) <= 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
impl = calloc(1, sizeof(*impl));
|
||||||
|
if (impl == NULL)
|
||||||
|
goto error;
|
||||||
|
|
||||||
while (spa_json_get_string(&it[1], key, sizeof(key)) > 0) {
|
while (spa_json_get_string(&it[1], key, sizeof(key)) > 0) {
|
||||||
if (spa_streq(key, "blocksize")) {
|
if (spa_streq(key, "blocksize")) {
|
||||||
if (spa_json_get_int(&it[1], &blocksize) <= 0) {
|
if (spa_json_get_int(&it[1], &impl->blocksize) <= 0) {
|
||||||
pw_log_error("spatializer:blocksize requires a number");
|
pw_log_error("spatializer:blocksize requires a number");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (spa_streq(key, "tailsize")) {
|
else if (spa_streq(key, "tailsize")) {
|
||||||
if (spa_json_get_int(&it[1], &tailsize) <= 0) {
|
if (spa_json_get_int(&it[1], &impl->tailsize) <= 0) {
|
||||||
pw_log_error("spatializer:tailsize requires a number");
|
pw_log_error("spatializer:tailsize requires a number");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
@ -911,36 +917,6 @@ static void * spatializer_instantiate(const struct fc_descriptor * Descriptor,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (spa_streq(key, "offset")) {
|
|
||||||
if (spa_json_get_int(&it[1], &offset) <= 0) {
|
|
||||||
pw_log_error("spatializer:offset requires a number");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (spa_streq(key, "length")) {
|
|
||||||
if (spa_json_get_int(&it[1], &length) <= 0) {
|
|
||||||
pw_log_error("spatializer:length requires a number");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (spa_streq(key, "azimuth")) {
|
|
||||||
if (spa_json_get_float(&it[1], &coords[0]) <= 0) {
|
|
||||||
pw_log_error("spatializer:azimuth requires a float number");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (spa_streq(key, "elevation")) {
|
|
||||||
if (spa_json_get_float(&it[1], &coords[1]) <= 0) {
|
|
||||||
pw_log_error("spatializer:elevation requires a float number");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (spa_streq(key, "radius")) {
|
|
||||||
if (spa_json_get_float(&it[1], &coords[2]) <= 0) {
|
|
||||||
pw_log_error("spatializer:radius requires a float number");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (spa_json_next(&it[1], &val) < 0)
|
else if (spa_json_next(&it[1], &val) < 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -952,7 +928,7 @@ static void * spatializer_instantiate(const struct fc_descriptor * Descriptor,
|
||||||
int ret = MYSOFA_OK;
|
int ret = MYSOFA_OK;
|
||||||
|
|
||||||
pthread_mutex_lock(&libmysofa_mutex);
|
pthread_mutex_lock(&libmysofa_mutex);
|
||||||
sofa = mysofa_open_cached(filename, SampleRate, &n_samples, &ret);
|
impl->sofa = mysofa_open_cached(filename, SampleRate, &impl->n_samples, &ret);
|
||||||
pthread_mutex_unlock(&libmysofa_mutex);
|
pthread_mutex_unlock(&libmysofa_mutex);
|
||||||
|
|
||||||
if (ret != MYSOFA_OK) {
|
if (ret != MYSOFA_OK) {
|
||||||
|
|
@ -961,18 +937,23 @@ static void * spatializer_instantiate(const struct fc_descriptor * Descriptor,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
float *left_ir = calloc(n_samples, sizeof(float));
|
float *left_ir = calloc(impl->n_samples, sizeof(float));
|
||||||
float *right_ir = calloc(n_samples, sizeof(float));
|
float *right_ir = calloc(impl->n_samples, sizeof(float));
|
||||||
float left_delay;
|
float left_delay;
|
||||||
float right_delay;
|
float right_delay;
|
||||||
|
|
||||||
mysofa_s2c(coords);
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
mysofa_s2c(impl->coords);
|
||||||
|
|
||||||
mysofa_getfilter_float(
|
mysofa_getfilter_float(
|
||||||
sofa,
|
impl->sofa,
|
||||||
coords[0],
|
impl->coords[0],
|
||||||
coords[1],
|
impl->coords[1],
|
||||||
coords[2],
|
impl->coords[2],
|
||||||
left_ir,
|
left_ir,
|
||||||
right_ir,
|
right_ir,
|
||||||
&left_delay,
|
&left_delay,
|
||||||
|
|
@ -982,44 +963,35 @@ static void * spatializer_instantiate(const struct fc_descriptor * Descriptor,
|
||||||
// TODO: make use of delay
|
// TODO: make use of delay
|
||||||
pw_log_info("delay l: %f, r: %f", left_delay, right_delay);
|
pw_log_info("delay l: %f, r: %f", left_delay, right_delay);
|
||||||
|
|
||||||
if (blocksize <= 0)
|
if (impl->blocksize <= 0)
|
||||||
blocksize = SPA_CLAMP(n_samples, 64, 256);
|
impl->blocksize = SPA_CLAMP(impl->n_samples, 64, 256);
|
||||||
if (tailsize <= 0)
|
if (impl->tailsize <= 0)
|
||||||
tailsize = SPA_CLAMP(4096, blocksize, 32768);
|
impl->tailsize = SPA_CLAMP(4096, impl->blocksize, 32768);
|
||||||
|
|
||||||
pw_log_info("using n_samples:%u %d:%d blocksize sofa:%s", n_samples,
|
pw_log_info("using n_samples:%u %d:%d blocksize sofa:%s", impl->n_samples,
|
||||||
blocksize, tailsize, filename);
|
impl->blocksize, impl->tailsize, filename);
|
||||||
|
|
||||||
impl = calloc(1, sizeof(*impl));
|
|
||||||
if (impl == NULL)
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
impl->rate = SampleRate;
|
impl->rate = SampleRate;
|
||||||
|
|
||||||
impl->l_conv = convolver_new(dsp_ops, blocksize, tailsize, left_ir, n_samples);
|
impl->l_conv = convolver_new(dsp_ops, impl->blocksize, impl->tailsize, left_ir, impl->n_samples);
|
||||||
if (impl->l_conv == NULL)
|
if (impl->l_conv == NULL)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
impl->r_conv = convolver_new(dsp_ops, blocksize, tailsize, right_ir, n_samples);
|
free(left_ir);
|
||||||
|
|
||||||
|
impl->r_conv = convolver_new(dsp_ops, impl->blocksize, impl->tailsize, right_ir, impl->n_samples);
|
||||||
if (impl->r_conv == NULL)
|
if (impl->r_conv == NULL)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
free(samples);
|
free(right_ir);
|
||||||
if (sofa) {
|
return impl;
|
||||||
|
error:
|
||||||
|
if (impl->sofa) {
|
||||||
pthread_mutex_lock(&libmysofa_mutex);
|
pthread_mutex_lock(&libmysofa_mutex);
|
||||||
mysofa_close_cached(sofa);
|
mysofa_close_cached(impl->sofa);
|
||||||
pthread_mutex_unlock(&libmysofa_mutex);
|
pthread_mutex_unlock(&libmysofa_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
return impl;
|
|
||||||
error:
|
|
||||||
if (samples)
|
|
||||||
free(samples);
|
|
||||||
if (sofa) {
|
|
||||||
pthread_mutex_lock(&libmysofa_mutex);
|
|
||||||
mysofa_close_cached(sofa);
|
|
||||||
pthread_mutex_unlock(&libmysofa_mutex);
|
|
||||||
}
|
|
||||||
free(impl);
|
free(impl);
|
||||||
return NULL;
|
return NULL;
|
||||||
#else
|
#else
|
||||||
|
|
@ -1033,6 +1005,57 @@ static void spatializer_run(void * Instance, unsigned long SampleCount)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_LIBMYSOFA
|
#ifdef HAVE_LIBMYSOFA
|
||||||
struct spatializer_impl *impl = Instance;
|
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]) {
|
||||||
|
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
|
||||||
|
pw_log_info("delay 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->l_conv, impl->port[2], impl->port[0], SampleCount);
|
||||||
convolver_run(impl->r_conv, impl->port[2], impl->port[1], SampleCount);
|
convolver_run(impl->r_conv, impl->port[2], impl->port[1], SampleCount);
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -1075,6 +1098,22 @@ static struct fc_port spatializer_ports[] = {
|
||||||
.name = "In",
|
.name = "In",
|
||||||
.flags = FC_PORT_INPUT | FC_PORT_AUDIO,
|
.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)
|
static void spatializer_deactivate(void * Instance)
|
||||||
|
|
@ -1087,7 +1126,7 @@ static void spatializer_deactivate(void * Instance)
|
||||||
static const struct fc_descriptor spatializer_desc = {
|
static const struct fc_descriptor spatializer_desc = {
|
||||||
.name = "spatializer",
|
.name = "spatializer",
|
||||||
|
|
||||||
.n_ports = 3,
|
.n_ports = 6,
|
||||||
.ports = spatializer_ports,
|
.ports = spatializer_ports,
|
||||||
|
|
||||||
.instantiate = spatializer_instantiate,
|
.instantiate = spatializer_instantiate,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue