mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	filter-chain: add Level control input port for noisegate
This makes it possible to use another volume measurement algorithm to drive the noise gate, such as a VAD algorithm.
This commit is contained in:
		
							parent
							
								
									4b37f3db3d
								
							
						
					
					
						commit
						b3dddfed6a
					
				
					 2 changed files with 32 additions and 17 deletions
				
			
		| 
						 | 
					@ -2892,26 +2892,31 @@ static struct spa_fga_port noisegate_ports[] = {
 | 
				
			||||||
	  .flags = SPA_FGA_PORT_OUTPUT | SPA_FGA_PORT_AUDIO,
 | 
						  .flags = SPA_FGA_PORT_OUTPUT | SPA_FGA_PORT_AUDIO,
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	{ .index = 2,
 | 
						{ .index = 2,
 | 
				
			||||||
	  .name = "Open Threshold",
 | 
						  .name = "Level",
 | 
				
			||||||
	  .flags = SPA_FGA_PORT_INPUT | SPA_FGA_PORT_CONTROL,
 | 
						  .flags = SPA_FGA_PORT_INPUT | SPA_FGA_PORT_CONTROL,
 | 
				
			||||||
	  .def = 0.004f, .min = 0.0f, .max = 1.0f
 | 
						  .def = NAN
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	{ .index = 3,
 | 
						{ .index = 3,
 | 
				
			||||||
	  .name = "Close Threshold",
 | 
						  .name = "Open Threshold",
 | 
				
			||||||
	  .flags = SPA_FGA_PORT_INPUT | SPA_FGA_PORT_CONTROL,
 | 
						  .flags = SPA_FGA_PORT_INPUT | SPA_FGA_PORT_CONTROL,
 | 
				
			||||||
	  .def = 0.003f, .min = 0.0f, .max = 1.0f
 | 
						  .def = 0.04f, .min = 0.0f, .max = 1.0f
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	{ .index = 4,
 | 
						{ .index = 4,
 | 
				
			||||||
 | 
						  .name = "Close Threshold",
 | 
				
			||||||
 | 
						  .flags = SPA_FGA_PORT_INPUT | SPA_FGA_PORT_CONTROL,
 | 
				
			||||||
 | 
						  .def = 0.03f, .min = 0.0f, .max = 1.0f
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						{ .index = 5,
 | 
				
			||||||
	  .name = "Attack (s)",
 | 
						  .name = "Attack (s)",
 | 
				
			||||||
	  .flags = SPA_FGA_PORT_INPUT | SPA_FGA_PORT_CONTROL,
 | 
						  .flags = SPA_FGA_PORT_INPUT | SPA_FGA_PORT_CONTROL,
 | 
				
			||||||
	  .def = 0.005f, .min = 0.0f, .max = 1.0f
 | 
						  .def = 0.005f, .min = 0.0f, .max = 1.0f
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	{ .index = 5,
 | 
						{ .index = 6,
 | 
				
			||||||
	  .name = "Hold (s)",
 | 
						  .name = "Hold (s)",
 | 
				
			||||||
	  .flags = SPA_FGA_PORT_INPUT | SPA_FGA_PORT_CONTROL,
 | 
						  .flags = SPA_FGA_PORT_INPUT | SPA_FGA_PORT_CONTROL,
 | 
				
			||||||
	  .def = 0.050f, .min = 0.0f, .max = 1.0f
 | 
						  .def = 0.050f, .min = 0.0f, .max = 1.0f
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	{ .index = 6,
 | 
						{ .index = 7,
 | 
				
			||||||
	  .name = "Release (s)",
 | 
						  .name = "Release (s)",
 | 
				
			||||||
	  .flags = SPA_FGA_PORT_INPUT | SPA_FGA_PORT_CONTROL,
 | 
						  .flags = SPA_FGA_PORT_INPUT | SPA_FGA_PORT_CONTROL,
 | 
				
			||||||
	  .def = 0.010f, .min = 0.0f, .max = 1.0f
 | 
						  .def = 0.010f, .min = 0.0f, .max = 1.0f
 | 
				
			||||||
| 
						 | 
					@ -2923,9 +2928,10 @@ static void noisegate_run(void * Instance, unsigned long SampleCount)
 | 
				
			||||||
	struct builtin *impl = Instance;
 | 
						struct builtin *impl = Instance;
 | 
				
			||||||
	float *in = impl->port[0];
 | 
						float *in = impl->port[0];
 | 
				
			||||||
	float *out = impl->port[1];
 | 
						float *out = impl->port[1];
 | 
				
			||||||
 | 
						float in_lev = impl->port[2][0];
 | 
				
			||||||
	unsigned long n;
 | 
						unsigned long n;
 | 
				
			||||||
	float o_thres = impl->port[2][0];
 | 
						float o_thres = impl->port[3][0];
 | 
				
			||||||
	float c_thres = impl->port[3][0];
 | 
						float c_thres = impl->port[4][0];
 | 
				
			||||||
	float gate, hold, o_rate, c_rate, level;
 | 
						float gate, hold, o_rate, c_rate, level;
 | 
				
			||||||
	int mode;
 | 
						int mode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2937,20 +2943,25 @@ static void noisegate_run(void * Instance, unsigned long SampleCount)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	o_rate = 1.0f / (impl->port[4][0] * impl->rate);
 | 
						o_rate = 1.0f / (impl->port[5][0] * impl->rate);
 | 
				
			||||||
	c_rate = 1.0f / (impl->port[6][0] * impl->rate);
 | 
						c_rate = 1.0f / (impl->port[7][0] * impl->rate);
 | 
				
			||||||
	gate = impl->gate;
 | 
						gate = impl->gate;
 | 
				
			||||||
	hold = impl->hold;
 | 
						hold = impl->hold;
 | 
				
			||||||
	mode = impl->mode;
 | 
						mode = impl->mode;
 | 
				
			||||||
	level = impl->last;
 | 
						level = impl->last;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (n = 0; n < SampleCount; n++) {
 | 
						spa_log_trace_fp(impl->log, "%f %d %f", level, mode, gate);
 | 
				
			||||||
		float lev = fabsf(in[n]);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (lev > level)
 | 
						for (n = 0; n < SampleCount; n++) {
 | 
				
			||||||
			level = lev;
 | 
							if (isnan(in_lev)) {
 | 
				
			||||||
		else
 | 
								float lev = fabsf(in[n]);
 | 
				
			||||||
			level = lev * 0.05f + level * 0.95f;
 | 
								if (lev > level)
 | 
				
			||||||
 | 
									level = lev;
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
									level = lev * 0.05f + level * 0.95f;
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								level = in_lev;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		switch (mode) {
 | 
							switch (mode) {
 | 
				
			||||||
		case 0:
 | 
							case 0:
 | 
				
			||||||
| 
						 | 
					@ -2964,7 +2975,7 @@ static void noisegate_run(void * Instance, unsigned long SampleCount)
 | 
				
			||||||
			if (gate >= 1.0f) {
 | 
								if (gate >= 1.0f) {
 | 
				
			||||||
				gate = 1.0f;
 | 
									gate = 1.0f;
 | 
				
			||||||
				mode = 2;
 | 
									mode = 2;
 | 
				
			||||||
				hold = impl->port[5][0] * impl->rate;
 | 
									hold = impl->port[6][0] * impl->rate;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		case 2:
 | 
							case 2:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -630,6 +630,10 @@ extern struct spa_handle_factory spa_filter_graph_factory;
 | 
				
			||||||
 * It has an "In" input port and an "Out" output data ports. Normally the input
 | 
					 * It has an "In" input port and an "Out" output data ports. Normally the input
 | 
				
			||||||
 * data is passed directly to the output.
 | 
					 * data is passed directly to the output.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 | 
					 * The "Level" control port can be used to control the measured volume of the "In"
 | 
				
			||||||
 | 
					 * port. When not connected, a simple volume algorithm on the "In" port will be
 | 
				
			||||||
 | 
					 * used.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 * If the volume drops below "Close threshold", the noisegate will ramp down the
 | 
					 * If the volume drops below "Close threshold", the noisegate will ramp down the
 | 
				
			||||||
 * volume to zero for a duration of "Release (s)" seconds. When the volume is above
 | 
					 * volume to zero for a duration of "Release (s)" seconds. When the volume is above
 | 
				
			||||||
 * "Open threshold", the noisegate will ramp up the volume to 1 for a duration
 | 
					 * "Open threshold", the noisegate will ramp up the volume to 1 for a duration
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue