mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05: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