mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-01 22:58:50 -04:00
filter-chain: add scale property to volume
Some controls will scale the volume so add a scale property to undo this scaling before setting the value. See #3434
This commit is contained in:
parent
bf9efb78ab
commit
f03317e86e
1 changed files with 39 additions and 9 deletions
|
|
@ -83,10 +83,10 @@ PW_LOG_TOPIC_STATIC(mod_topic, "mod." NAME);
|
||||||
* inputs = [ <portname> ... ]
|
* inputs = [ <portname> ... ]
|
||||||
* outputs = [ <portname> ... ]
|
* outputs = [ <portname> ... ]
|
||||||
* capture.volumes = [
|
* capture.volumes = [
|
||||||
* { control = <portname> min = <value> max = <value> } ...
|
* { control = <portname> min = <value> max = <value> scale = <scale> } ...
|
||||||
* ]
|
* ]
|
||||||
* playback.volumes = [
|
* playback.volumes = [
|
||||||
* { control = <portname> min = <value> max = <value> } ...
|
* { control = <portname> min = <value> max = <value> scale = <scale> } ...
|
||||||
* ]
|
* ]
|
||||||
* }
|
* }
|
||||||
*\endcode
|
*\endcode
|
||||||
|
|
@ -152,6 +152,11 @@ PW_LOG_TOPIC_STATIC(mod_topic, "mod." NAME);
|
||||||
* The min and max values (defaults 0.0 and 1.0) respectively can be used to scale
|
* The min and max values (defaults 0.0 and 1.0) respectively can be used to scale
|
||||||
* and translate the volume min and max values.
|
* and translate the volume min and max values.
|
||||||
*
|
*
|
||||||
|
* Normally the control values are linear and it is assumed that the plugin does not
|
||||||
|
* perform any scaling to the values. This can be changed with the scale property. By
|
||||||
|
* default this is linear but it can be set to cubic when the control applies a
|
||||||
|
* cubic transformation.
|
||||||
|
*
|
||||||
* ## Builtin filters
|
* ## Builtin filters
|
||||||
*
|
*
|
||||||
* There are some useful builtin filters available. You select them with the label
|
* There are some useful builtin filters available. You select them with the label
|
||||||
|
|
@ -644,11 +649,14 @@ struct volume {
|
||||||
bool mute;
|
bool mute;
|
||||||
uint32_t n_volumes;
|
uint32_t n_volumes;
|
||||||
float volumes[SPA_AUDIO_MAX_CHANNELS];
|
float volumes[SPA_AUDIO_MAX_CHANNELS];
|
||||||
float min[SPA_AUDIO_MAX_CHANNELS];
|
|
||||||
float max[SPA_AUDIO_MAX_CHANNELS];
|
|
||||||
|
|
||||||
uint32_t n_ports;
|
uint32_t n_ports;
|
||||||
struct port *ports[SPA_AUDIO_MAX_CHANNELS];
|
struct port *ports[SPA_AUDIO_MAX_CHANNELS];
|
||||||
|
float min[SPA_AUDIO_MAX_CHANNELS];
|
||||||
|
float max[SPA_AUDIO_MAX_CHANNELS];
|
||||||
|
#define SCALE_LINEAR 0
|
||||||
|
#define SCALE_CUBIC 1
|
||||||
|
int scale[SPA_AUDIO_MAX_CHANNELS];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct graph {
|
struct graph {
|
||||||
|
|
@ -1135,7 +1143,13 @@ static int sync_volume(struct graph *graph, struct volume *vol)
|
||||||
uint32_t n_port = i % vol->n_ports, n_hndl;
|
uint32_t n_port = i % vol->n_ports, n_hndl;
|
||||||
struct port *p = vol->ports[n_port];
|
struct port *p = vol->ports[n_port];
|
||||||
float v = vol->mute ? 0.0f : vol->volumes[i];
|
float v = vol->mute ? 0.0f : vol->volumes[i];
|
||||||
|
switch (vol->scale[n_port]) {
|
||||||
|
case SCALE_CUBIC:
|
||||||
|
v = cbrt(v);
|
||||||
|
break;
|
||||||
|
}
|
||||||
v = v * (vol->max[n_port] - vol->min[n_port]) + vol->min[n_port];
|
v = v * (vol->max[n_port] - vol->min[n_port]) + vol->min[n_port];
|
||||||
|
|
||||||
n_hndl = SPA_MAX(1u, p->node->n_hndl);
|
n_hndl = SPA_MAX(1u, p->node->n_hndl);
|
||||||
res += port_set_control_value(p, &v, i % n_hndl);
|
res += port_set_control_value(p, &v, i % n_hndl);
|
||||||
}
|
}
|
||||||
|
|
@ -1933,14 +1947,16 @@ static void link_free(struct link *link)
|
||||||
/**
|
/**
|
||||||
* {
|
* {
|
||||||
* control = [name:][portname]
|
* control = [name:][portname]
|
||||||
* min = ...
|
* min = <float, defaukt 0.0>
|
||||||
* max = ...
|
* max = <float, default 1.0>
|
||||||
|
* scale = <string, default "linear", options "linear","cubic">
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
static int parse_volume(struct graph *graph, struct spa_json *json, bool capture)
|
static int parse_volume(struct graph *graph, struct spa_json *json, bool capture)
|
||||||
{
|
{
|
||||||
char key[256];
|
char key[256];
|
||||||
char control[256] = "";
|
char control[256] = "";
|
||||||
|
char scale[64] = "linear";
|
||||||
float min = 0.0f, max = 1.0f;
|
float min = 0.0f, max = 1.0f;
|
||||||
const char *val;
|
const char *val;
|
||||||
struct node *def_control;
|
struct node *def_control;
|
||||||
|
|
@ -1971,6 +1987,12 @@ static int parse_volume(struct graph *graph, struct spa_json *json, bool capture
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (spa_streq(key, "scale")) {
|
||||||
|
if (spa_json_get_string(json, scale, sizeof(scale)) <= 0) {
|
||||||
|
pw_log_error("scale expects a string");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (spa_json_next(json, &val) < 0)
|
else if (spa_json_next(json, &val) < 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -1986,10 +2008,18 @@ static int parse_volume(struct graph *graph, struct spa_json *json, bool capture
|
||||||
}
|
}
|
||||||
if (vol->n_ports >= SPA_AUDIO_MAX_CHANNELS) {
|
if (vol->n_ports >= SPA_AUDIO_MAX_CHANNELS) {
|
||||||
pw_log_error("too many volume controls");
|
pw_log_error("too many volume controls");
|
||||||
return -ENOENT;
|
return -ENOSPC;
|
||||||
}
|
}
|
||||||
pw_log_info("volume %d: \"%s:%s\" min:%f max:%f", vol->n_ports, port->node->name,
|
if (spa_streq(scale, "linear")) {
|
||||||
port->node->desc->desc->ports[port->p].name, min, max);
|
vol->scale[vol->n_ports] = SCALE_LINEAR;
|
||||||
|
} else if (spa_streq(scale, "cubic")) {
|
||||||
|
vol->scale[vol->n_ports] = SCALE_CUBIC;
|
||||||
|
} else {
|
||||||
|
pw_log_error("Invalid scale value '%s', use one of linear or cubic", scale);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
pw_log_info("volume %d: \"%s:%s\" min:%f max:%f scale:%s", vol->n_ports, port->node->name,
|
||||||
|
port->node->desc->desc->ports[port->p].name, min, max, scale);
|
||||||
|
|
||||||
vol->ports[vol->n_ports] = port;
|
vol->ports[vol->n_ports] = port;
|
||||||
vol->min[vol->n_ports] = min;
|
vol->min[vol->n_ports] = min;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue