mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-02 09:01:50 -05:00
filter-graph: add latency support for the delay plugin
This commit is contained in:
parent
dbca286de8
commit
8ee51cd88f
2 changed files with 35 additions and 10 deletions
|
|
@ -1163,6 +1163,7 @@ struct delay_impl {
|
||||||
uint32_t buffer_samples;
|
uint32_t buffer_samples;
|
||||||
float *buffer;
|
float *buffer;
|
||||||
uint32_t ptr;
|
uint32_t ptr;
|
||||||
|
float latency;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void delay_cleanup(void * Instance)
|
static void delay_cleanup(void * Instance)
|
||||||
|
|
@ -1180,7 +1181,7 @@ static void *delay_instantiate(const struct spa_fga_plugin *plugin, const struct
|
||||||
struct spa_json it[1];
|
struct spa_json it[1];
|
||||||
const char *val;
|
const char *val;
|
||||||
char key[256];
|
char key[256];
|
||||||
float max_delay = 1.0f;
|
float max_delay = 1.0f, latency = 0.0f;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
if (config == NULL) {
|
if (config == NULL) {
|
||||||
|
|
@ -1200,12 +1201,19 @@ static void *delay_instantiate(const struct spa_fga_plugin *plugin, const struct
|
||||||
spa_log_error(pl->log, "delay:max-delay requires a number");
|
spa_log_error(pl->log, "delay:max-delay requires a number");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
} else if (spa_streq(key, "latency")) {
|
||||||
|
if (spa_json_parse_float(val, len, &latency) <= 0) {
|
||||||
|
spa_log_error(pl->log, "delay:latency requires a number");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
spa_log_warn(pl->log, "delay: ignoring config key: '%s'", key);
|
spa_log_warn(pl->log, "delay: ignoring config key: '%s'", key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (max_delay <= 0.0f)
|
if (max_delay <= 0.0f)
|
||||||
max_delay = 1.0f;
|
max_delay = 1.0f;
|
||||||
|
if (latency <= 0.0f)
|
||||||
|
latency = 0.0f;
|
||||||
|
|
||||||
impl = calloc(1, sizeof(*impl));
|
impl = calloc(1, sizeof(*impl));
|
||||||
if (impl == NULL)
|
if (impl == NULL)
|
||||||
|
|
@ -1216,7 +1224,9 @@ static void *delay_instantiate(const struct spa_fga_plugin *plugin, const struct
|
||||||
impl->log = pl->log;
|
impl->log = pl->log;
|
||||||
impl->rate = SampleRate;
|
impl->rate = SampleRate;
|
||||||
impl->buffer_samples = SPA_ROUND_UP_N((uint32_t)(max_delay * impl->rate), 64);
|
impl->buffer_samples = SPA_ROUND_UP_N((uint32_t)(max_delay * impl->rate), 64);
|
||||||
spa_log_info(impl->log, "max-delay:%f seconds rate:%lu samples:%d", max_delay, impl->rate, impl->buffer_samples);
|
impl->latency = latency * impl->rate;
|
||||||
|
spa_log_info(impl->log, "max-delay:%f seconds rate:%lu samples:%d latency:%f",
|
||||||
|
max_delay, impl->rate, impl->buffer_samples, impl->latency);
|
||||||
|
|
||||||
impl->buffer = calloc(impl->buffer_samples * 2 + 64, sizeof(float));
|
impl->buffer = calloc(impl->buffer_samples * 2 + 64, sizeof(float));
|
||||||
if (impl->buffer == NULL) {
|
if (impl->buffer == NULL) {
|
||||||
|
|
@ -1230,26 +1240,32 @@ static void delay_connect_port(void * Instance, unsigned long Port,
|
||||||
float * DataLocation)
|
float * DataLocation)
|
||||||
{
|
{
|
||||||
struct delay_impl *impl = Instance;
|
struct delay_impl *impl = Instance;
|
||||||
if (Port > 2)
|
|
||||||
return;
|
|
||||||
impl->port[Port] = DataLocation;
|
impl->port[Port] = DataLocation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void delay_activate(void * Instance)
|
||||||
|
{
|
||||||
|
struct delay_impl *impl = Instance;
|
||||||
|
if (impl->port[3] != NULL)
|
||||||
|
impl->port[3][0] = impl->latency;
|
||||||
|
}
|
||||||
|
|
||||||
static void delay_run(void * Instance, unsigned long SampleCount)
|
static void delay_run(void * Instance, unsigned long SampleCount)
|
||||||
{
|
{
|
||||||
struct delay_impl *impl = Instance;
|
struct delay_impl *impl = Instance;
|
||||||
float *in = impl->port[1], *out = impl->port[0];
|
float *in = impl->port[1], *out = impl->port[0];
|
||||||
float delay = impl->port[2][0];
|
float delay = impl->port[2][0];
|
||||||
|
|
||||||
if (in == NULL || out == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (delay != impl->delay) {
|
if (delay != impl->delay) {
|
||||||
impl->delay_samples = SPA_CLAMP((uint32_t)(delay * impl->rate), 0u, impl->buffer_samples-1);
|
impl->delay_samples = SPA_CLAMP((uint32_t)(delay * impl->rate), 0u, impl->buffer_samples-1);
|
||||||
impl->delay = delay;
|
impl->delay = delay;
|
||||||
}
|
}
|
||||||
spa_fga_dsp_delay(impl->dsp, impl->buffer, &impl->ptr, impl->buffer_samples,
|
if (in != NULL && out == NULL) {
|
||||||
impl->delay_samples, out, in, SampleCount);
|
spa_fga_dsp_delay(impl->dsp, impl->buffer, &impl->ptr, impl->buffer_samples,
|
||||||
|
impl->delay_samples, out, in, SampleCount);
|
||||||
|
}
|
||||||
|
if (impl->port[3] != NULL)
|
||||||
|
impl->port[3][0] = impl->latency;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct spa_fga_port delay_ports[] = {
|
static struct spa_fga_port delay_ports[] = {
|
||||||
|
|
@ -1266,17 +1282,23 @@ static struct spa_fga_port delay_ports[] = {
|
||||||
.flags = SPA_FGA_PORT_INPUT | SPA_FGA_PORT_CONTROL,
|
.flags = SPA_FGA_PORT_INPUT | SPA_FGA_PORT_CONTROL,
|
||||||
.def = 0.0f, .min = 0.0f, .max = 100.0f
|
.def = 0.0f, .min = 0.0f, .max = 100.0f
|
||||||
},
|
},
|
||||||
|
{ .index = 3,
|
||||||
|
.name = "latency",
|
||||||
|
.hint = SPA_FGA_HINT_LATENCY,
|
||||||
|
.flags = SPA_FGA_PORT_OUTPUT | SPA_FGA_PORT_CONTROL,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct spa_fga_descriptor delay_desc = {
|
static const struct spa_fga_descriptor delay_desc = {
|
||||||
.name = "delay",
|
.name = "delay",
|
||||||
.flags = SPA_FGA_DESCRIPTOR_SUPPORTS_NULL_DATA,
|
.flags = SPA_FGA_DESCRIPTOR_SUPPORTS_NULL_DATA,
|
||||||
|
|
||||||
.n_ports = 3,
|
.n_ports = SPA_N_ELEMENTS(delay_ports),
|
||||||
.ports = delay_ports,
|
.ports = delay_ports,
|
||||||
|
|
||||||
.instantiate = delay_instantiate,
|
.instantiate = delay_instantiate,
|
||||||
.connect_port = delay_connect_port,
|
.connect_port = delay_connect_port,
|
||||||
|
.activate = delay_activate,
|
||||||
.run = delay_run,
|
.run = delay_run,
|
||||||
.cleanup = delay_cleanup,
|
.cleanup = delay_cleanup,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -379,6 +379,7 @@ extern struct spa_handle_factory spa_filter_graph_factory;
|
||||||
* label = delay
|
* label = delay
|
||||||
* config = {
|
* config = {
|
||||||
* "max-delay" = ...
|
* "max-delay" = ...
|
||||||
|
* "latency" = ...
|
||||||
* }
|
* }
|
||||||
* control = {
|
* control = {
|
||||||
* "Delay (s)" = ...
|
* "Delay (s)" = ...
|
||||||
|
|
@ -392,6 +393,8 @@ extern struct spa_handle_factory spa_filter_graph_factory;
|
||||||
*
|
*
|
||||||
* - `max-delay` the maximum delay in seconds. The "Delay (s)" parameter will
|
* - `max-delay` the maximum delay in seconds. The "Delay (s)" parameter will
|
||||||
* be clamped to this value.
|
* be clamped to this value.
|
||||||
|
* - `latency` the latency in seconds. This is 0 by default but in some cases
|
||||||
|
* the delay can be used to introduce latency with this option.
|
||||||
*
|
*
|
||||||
* ### Invert
|
* ### Invert
|
||||||
*
|
*
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue