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.
This commit is contained in:
Wim Taymans 2021-08-24 16:23:47 +02:00
parent 123fe3d1c5
commit 1e4e83d305
5 changed files with 177 additions and 48 deletions

View file

@ -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 = {

View file

@ -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];

View file

@ -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,

View file

@ -35,7 +35,6 @@
#include "plugin.h"
#include "ladspa.h"
struct plugin {
struct fc_plugin plugin;
void *handle;

View file

@ -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);