From 1e4e83d305a7b0705415b64014bcaf5dbdae6c11 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Tue, 24 Aug 2021 16:23:47 +0200 Subject: [PATCH] filter-chain: add more mixer ports Add option to set NULL data as the port data so that plugins can skip processing. Add 8 mixer ports and skip NULL data. Move silence and discard samples to static area. Improve the virtual sink examples. use the correct mixing for the HRIR channels. --- src/daemon/filter-chain/sink-convolver.conf | 104 +++++++++++++----- src/modules/module-filter-chain.c | 15 ++- .../module-filter-chain/builtin_plugin.c | 104 +++++++++++++++--- .../module-filter-chain/ladspa_plugin.c | 1 - src/modules/module-filter-chain/plugin.h | 1 + 5 files changed, 177 insertions(+), 48 deletions(-) diff --git a/src/daemon/filter-chain/sink-convolver.conf b/src/daemon/filter-chain/sink-convolver.conf index c40358d6c..fdfd352ed 100644 --- a/src/daemon/filter-chain/sink-convolver.conf +++ b/src/daemon/filter-chain/sink-convolver.conf @@ -35,7 +35,7 @@ context.modules = [ { type = builtin label = convolver - name = convFL + name = convFL_L config = { filename = "hrir_kemar/hrir-kemar.wav" channel = 0 @@ -44,10 +44,28 @@ context.modules = [ { type = builtin label = convolver - name = convFR + name = convFL_R config = { filename = "hrir_kemar/hrir-kemar.wav" - channel = 4 + channel = 1 + } + } + { + type = builtin + label = convolver + name = convFR_L + config = { + filename = "hrir_kemar/hrir-kemar.wav" + channel = 1 + } + } + { + type = builtin + label = convolver + name = convFR_R + config = { + filename = "hrir_kemar/hrir-kemar.wav" + channel = 0 } } { @@ -71,16 +89,16 @@ context.modules = [ { type = builtin label = convolver - name = convSL + name = convSL_L config = { filename = "hrir_kemar/hrir-kemar.wav" - channel = 1 + channel = 4 } } { type = builtin label = convolver - name = convSR + name = convSL_R config = { filename = "hrir_kemar/hrir-kemar.wav" channel = 5 @@ -88,48 +106,80 @@ context.modules = [ } { type = builtin - label = mixer - name = mix1L + label = convolver + name = convSR_L + config = { + filename = "hrir_kemar/hrir-kemar.wav" + channel = 5 + } + } + { + type = builtin + label = convolver + name = convSR_R + config = { + filename = "hrir_kemar/hrir-kemar.wav" + channel = 4 + } } { type = builtin label = mixer - name = mix1R + name = mixL } { type = builtin label = mixer - name = mixC + name = mixR } { type = builtin - label = mixer - name = mix2L + label = copy + name = copyFL } { type = builtin - label = mixer - name = mix2R + label = copy + name = copyFR + } + { + type = builtin + label = copy + name = copySL + } + { + type = builtin + label = copy + name = copySR } ] links = [ - { output = "convFL:Out" input = "mix1L:In 1" } - { output = "convSL:Out" input = "mix1L:In 2" } + { output = "copyFL:Out" input = "convFL_L:In" } + { output = "copyFL:Out" input = "convFL_R:In" } + { output = "copyFR:Out" input = "convFR_R:In" } + { output = "copyFR:Out" input = "convFR_L:In" } - { output = "convFR:Out" input = "mix1R:In 1" } - { output = "convSR:Out" input = "mix1R:In 2" } + { output = "copySL:Out" input = "convSL_L:In" } + { output = "copySL:Out" input = "convSL_R:In" } + { output = "copySR:Out" input = "convSR_R:In" } + { output = "copySR:Out" input = "convSR_L:In" } - { output = "convFC:Out" input = "mixC:In 1" } - { output = "convLFE:Out" input = "mixC:In 2" } + { output = "convFL_L:Out" input = "mixL:In 1" } + { output = "convFR_L:Out" input = "mixL:In 2" } + { output = "convFC:Out" input = "mixL:In 3" } + { output = "convLFE:Out" input = "mixL:In 4" } + { output = "convSL_L:Out" input = "mixL:In 5" } + { output = "convSR_L:Out" input = "mixL:In 6" } - { output = "mixC:Out" input = "mix2L:In 1" } - { output = "mix1L:Out" input = "mix2L:In 2" } - - { output = "mixC:Out" input = "mix2R:In 1" } - { output = "mix1R:Out" input = "mix2R:In 2" } + { output = "convFL_R:Out" input = "mixR:In 1" } + { output = "convFR_R:Out" input = "mixR:In 2" } + { output = "convFC:Out" input = "mixR:In 3" } + { output = "convLFE:Out" input = "mixR:In 4" } + { output = "convSL_R:Out" input = "mixR:In 5" } + { output = "convSR_R:Out" input = "mixR:In 6" } ] - inputs = [ "convFL:In" "convFR:In" "convFC:In" "convLFE:In" "convSL:In" "convSR:In" ] - outputs = [ "mix2L:Out" "mix2R:Out" ] + inputs = [ "copyFL:In" "copyFR:In" "convFC:In" "convLFE:In" "copySL:In" "copySR:In" ] + outputs = [ "mixL:Out" "mixR:Out" ] } capture.props = { diff --git a/src/modules/module-filter-chain.c b/src/modules/module-filter-chain.c index 8633b002e..813af36d4 100644 --- a/src/modules/module-filter-chain.c +++ b/src/modules/module-filter-chain.c @@ -109,6 +109,9 @@ static const struct spa_dict_item module_props[] = { #define MAX_CONTROLS 256 #define MAX_SAMPLES 8192 +static float silence_data[MAX_SAMPLES]; +static float discard_data[MAX_SAMPLES]; + struct plugin { struct spa_list link; int ref; @@ -212,9 +215,6 @@ struct graph { uint32_t n_control; struct port *control_port[MAX_CONTROLS]; - - float silence_data[MAX_SAMPLES]; - float discard_data[MAX_SAMPLES]; }; struct impl { @@ -1265,8 +1265,13 @@ static int setup_graph(struct graph *graph, struct spa_json *inputs, struct spa_ * the control and notify ports already */ graph->n_control = 0; spa_list_for_each(node, &graph->node_list, link) { + float *sd = silence_data, *dd = discard_data; + desc = node->desc; d = desc->desc; + if (d->flags & FC_DESCRIPTOR_SUPPORTS_NULL_DATA) + sd = dd = NULL; + for (i = 0; i < n_hndl; i++) { if ((node->hndl[i] = d->instantiate(d, impl->rate, i, node->config)) == NULL) { pw_log_error("cannot create plugin instance"); @@ -1277,11 +1282,11 @@ static int setup_graph(struct graph *graph, struct spa_json *inputs, struct spa_ for (j = 0; j < desc->n_input; j++) { p = desc->input[j]; - d->connect_port(node->hndl[i], p, graph->silence_data); + d->connect_port(node->hndl[i], p, sd); } for (j = 0; j < desc->n_output; j++) { p = desc->output[j]; - d->connect_port(node->hndl[i], p, graph->discard_data); + d->connect_port(node->hndl[i], p, dd); } for (j = 0; j < desc->n_control; j++) { port = &node->control_port[j]; diff --git a/src/modules/module-filter-chain/builtin_plugin.c b/src/modules/module-filter-chain/builtin_plugin.c index d306cf05b..e285f7afa 100644 --- a/src/modules/module-filter-chain/builtin_plugin.c +++ b/src/modules/module-filter-chain/builtin_plugin.c @@ -61,8 +61,7 @@ static void *builtin_instantiate(const struct fc_descriptor * Descriptor, return impl; } -static void builtin_connect_port(void *Instance, unsigned long Port, - float * DataLocation) +static void builtin_connect_port(void *Instance, unsigned long Port, float * DataLocation) { struct builtin *impl = Instance; impl->port[Port] = DataLocation; @@ -110,19 +109,37 @@ static void mixer_run(void * Instance, unsigned long SampleCount) { struct builtin *impl = Instance; unsigned long i; - float gain1 = impl->port[3][0]; - float gain2 = impl->port[4][0]; - float *in1 = impl->port[1], *in2 = impl->port[2], *out = impl->port[0]; + float *out = impl->port[0]; + bool first = true; - if (gain1 == 0.0f && gain2 == 0.0f) { - memset(out, 0, SampleCount * sizeof(float)); - } else if (gain1 == 1.0f && gain2 == 1.0f) { - for (i = 0; i < SampleCount; i++) - out[i] = in1[i] + in2[i]; - } else { - for (i = 0; i < SampleCount; i++) - out[i] = in1[i] * gain1 + in2[i] * gain2; + if (out == NULL) + return; + + for (i = 0; i < 8; i++) { + float *in = impl->port[1+i]; + float gain = impl->port[9+i][0]; + + if (in == NULL || gain == 0.0f) + continue; + + if (first) { + if (gain == 1.0f) + memcpy(out, in, SampleCount * sizeof(float)); + else + for (i = 0; i < SampleCount; i++) + out[i] = in[i] * gain; + first = false; + } else { + if (gain == 1.0f) + for (i = 0; i < SampleCount; i++) + out[i] += in[i]; + else + for (i = 0; i < SampleCount; i++) + out[i] += in[i] * gain; + } } + if (first) + memset(out, 0, SampleCount * sizeof(float)); } static struct fc_port mixer_ports[] = { @@ -130,6 +147,7 @@ static struct fc_port mixer_ports[] = { .name = "Out", .flags = FC_PORT_OUTPUT | FC_PORT_AUDIO, }, + { .index = 1, .name = "In 1", .flags = FC_PORT_INPUT | FC_PORT_AUDIO, @@ -139,21 +157,77 @@ static struct fc_port mixer_ports[] = { .flags = FC_PORT_INPUT | FC_PORT_AUDIO, }, { .index = 3, + .name = "In 3", + .flags = FC_PORT_INPUT | FC_PORT_AUDIO, + }, + { .index = 4, + .name = "In 4", + .flags = FC_PORT_INPUT | FC_PORT_AUDIO, + }, + { .index = 5, + .name = "In 5", + .flags = FC_PORT_INPUT | FC_PORT_AUDIO, + }, + { .index = 6, + .name = "In 6", + .flags = FC_PORT_INPUT | FC_PORT_AUDIO, + }, + { .index = 7, + .name = "In 7", + .flags = FC_PORT_INPUT | FC_PORT_AUDIO, + }, + { .index = 8, + .name = "In 8", + .flags = FC_PORT_INPUT | FC_PORT_AUDIO, + }, + + { .index = 9, .name = "Gain 1", .flags = FC_PORT_INPUT | FC_PORT_CONTROL, .def = 1.0f, .min = 0.0f, .max = 10.0f }, - { .index = 4, + { .index = 10, .name = "Gain 2", .flags = FC_PORT_INPUT | FC_PORT_CONTROL, .def = 1.0f, .min = 0.0f, .max = 10.0f }, + { .index = 11, + .name = "Gain 3", + .flags = FC_PORT_INPUT | FC_PORT_CONTROL, + .def = 1.0f, .min = 0.0f, .max = 10.0f + }, + { .index = 12, + .name = "Gain 4", + .flags = FC_PORT_INPUT | FC_PORT_CONTROL, + .def = 1.0f, .min = 0.0f, .max = 10.0f + }, + { .index = 13, + .name = "Gain 5", + .flags = FC_PORT_INPUT | FC_PORT_CONTROL, + .def = 1.0f, .min = 0.0f, .max = 10.0f + }, + { .index = 14, + .name = "Gain 6", + .flags = FC_PORT_INPUT | FC_PORT_CONTROL, + .def = 1.0f, .min = 0.0f, .max = 10.0f + }, + { .index = 15, + .name = "Gain 7", + .flags = FC_PORT_INPUT | FC_PORT_CONTROL, + .def = 1.0f, .min = 0.0f, .max = 10.0f + }, + { .index = 16, + .name = "Gain 8", + .flags = FC_PORT_INPUT | FC_PORT_CONTROL, + .def = 1.0f, .min = 0.0f, .max = 10.0f + }, }; static const struct fc_descriptor mixer_desc = { .name = "mixer", + .flags = FC_DESCRIPTOR_SUPPORTS_NULL_DATA, - .n_ports = 5, + .n_ports = 17, .ports = mixer_ports, .instantiate = builtin_instantiate, diff --git a/src/modules/module-filter-chain/ladspa_plugin.c b/src/modules/module-filter-chain/ladspa_plugin.c index b515ef9ea..d34a9ace0 100644 --- a/src/modules/module-filter-chain/ladspa_plugin.c +++ b/src/modules/module-filter-chain/ladspa_plugin.c @@ -35,7 +35,6 @@ #include "plugin.h" #include "ladspa.h" - struct plugin { struct fc_plugin plugin; void *handle; diff --git a/src/modules/module-filter-chain/plugin.h b/src/modules/module-filter-chain/plugin.h index 801230884..442606a97 100644 --- a/src/modules/module-filter-chain/plugin.h +++ b/src/modules/module-filter-chain/plugin.h @@ -60,6 +60,7 @@ struct fc_port { struct fc_descriptor { const char *name; +#define FC_DESCRIPTOR_SUPPORTS_NULL_DATA (1ULL << 0) uint64_t flags; void (*free) (struct fc_descriptor *desc);