mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	Allow echo-cancel to select larger buffer sizes
This commit is contained in:
		
							parent
							
								
									002566ae83
								
							
						
					
					
						commit
						2bfc03f43c
					
				
					 2 changed files with 60 additions and 20 deletions
				
			
		| 
						 | 
				
			
			@ -614,7 +614,9 @@ static int setup_streams(struct impl *impl)
 | 
			
		|||
		pw_properties_set(props, PW_KEY_NODE_GROUP, str);
 | 
			
		||||
	if ((str = pw_properties_get(impl->source_props, PW_KEY_NODE_LINK_GROUP)) != NULL)
 | 
			
		||||
		pw_properties_set(props, PW_KEY_NODE_LINK_GROUP, str);
 | 
			
		||||
	if (impl->aec_info->latency)
 | 
			
		||||
	if ((str = pw_properties_get(impl->source_props, PW_KEY_NODE_LATENCY)) != NULL)
 | 
			
		||||
		pw_properties_set(props, PW_KEY_NODE_LATENCY, str);
 | 
			
		||||
	else if (impl->aec_info->latency)
 | 
			
		||||
		pw_properties_set(props, PW_KEY_NODE_LATENCY, impl->aec_info->latency);
 | 
			
		||||
 | 
			
		||||
	impl->capture = pw_stream_new(impl->core,
 | 
			
		||||
| 
						 | 
				
			
			@ -645,7 +647,9 @@ static int setup_streams(struct impl *impl)
 | 
			
		|||
		pw_properties_set(props, PW_KEY_NODE_GROUP, str);
 | 
			
		||||
	if ((str = pw_properties_get(impl->sink_props, PW_KEY_NODE_LINK_GROUP)) != NULL)
 | 
			
		||||
		pw_properties_set(props, PW_KEY_NODE_LINK_GROUP, str);
 | 
			
		||||
	if (impl->aec_info->latency)
 | 
			
		||||
	if ((str = pw_properties_get(impl->sink_props, PW_KEY_NODE_LATENCY)) != NULL)
 | 
			
		||||
		pw_properties_set(props, PW_KEY_NODE_LATENCY, str);
 | 
			
		||||
	else if (impl->aec_info->latency)
 | 
			
		||||
		pw_properties_set(props, PW_KEY_NODE_LATENCY, impl->aec_info->latency);
 | 
			
		||||
 | 
			
		||||
	impl->playback = pw_stream_new(impl->core,
 | 
			
		||||
| 
						 | 
				
			
			@ -946,13 +950,31 @@ int pipewire__module_init(struct pw_impl_module *module, const char *args)
 | 
			
		|||
	pw_properties_free(aec_props);
 | 
			
		||||
 | 
			
		||||
	if (impl->aec_info->latency) {
 | 
			
		||||
		unsigned int num, denom;
 | 
			
		||||
 | 
			
		||||
		pw_log_info("Setting node latency to %s", impl->aec_info->latency);
 | 
			
		||||
		pw_properties_set(props, PW_KEY_NODE_LATENCY, impl->aec_info->latency);
 | 
			
		||||
		unsigned int num, denom, req_num, req_denom;
 | 
			
		||||
		unsigned int factor = 0;
 | 
			
		||||
		unsigned int new_num = 0;
 | 
			
		||||
 | 
			
		||||
		sscanf(impl->aec_info->latency, "%u/%u", &num, &denom);
 | 
			
		||||
 | 
			
		||||
		if ((str = pw_properties_get(props, PW_KEY_NODE_LATENCY)) != NULL) {
 | 
			
		||||
			sscanf(str, "%u/%u", &req_num, &req_denom);
 | 
			
		||||
			factor = (req_num * denom) / (req_denom * num);
 | 
			
		||||
			new_num = req_num / factor * factor;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (factor == 0 || new_num == 0) {
 | 
			
		||||
			pw_log_info("Setting node latency to %s", impl->aec_info->latency);
 | 
			
		||||
			pw_properties_set(props, PW_KEY_NODE_LATENCY, impl->aec_info->latency);
 | 
			
		||||
			impl->aec_blocksize = sizeof(float) * impl->info.rate * num / denom;
 | 
			
		||||
		} else {
 | 
			
		||||
			char* new_latency_str = (char*)calloc(strlen(str), sizeof(char));
 | 
			
		||||
 | 
			
		||||
			sprintf(new_latency_str, "%u/%u", new_num, req_denom);
 | 
			
		||||
			pw_log_info("Setting node latency to %s", new_latency_str);
 | 
			
		||||
			pw_properties_set(props, PW_KEY_NODE_LATENCY, new_latency_str);
 | 
			
		||||
			impl->aec_blocksize = sizeof(float) * impl->info.rate * num / denom * factor;
 | 
			
		||||
			free(new_latency_str);
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		/* Implementation doesn't care about the block size */
 | 
			
		||||
		impl->aec_blocksize = 0;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -34,6 +34,9 @@
 | 
			
		|||
struct impl {
 | 
			
		||||
	webrtc::AudioProcessing *apm = NULL;
 | 
			
		||||
	spa_audio_info_raw info;
 | 
			
		||||
	float** play_buffer;
 | 
			
		||||
	float** rec_buffer;
 | 
			
		||||
	float** out_buffer;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void *webrtc_create(const struct pw_properties *args, const spa_audio_info_raw *info)
 | 
			
		||||
| 
						 | 
				
			
			@ -72,6 +75,10 @@ static void *webrtc_create(const struct pw_properties *args, const spa_audio_inf
 | 
			
		|||
	impl = (struct impl *)calloc(1, sizeof(struct impl));
 | 
			
		||||
	impl->info = *info;
 | 
			
		||||
 | 
			
		||||
	impl->play_buffer = (float **)calloc(info->channels, sizeof(float*));
 | 
			
		||||
	impl->rec_buffer = (float **)calloc(info->channels, sizeof(float*));
 | 
			
		||||
	impl->out_buffer = (float **)calloc(info->channels, sizeof(float*));
 | 
			
		||||
 | 
			
		||||
	impl->apm = apm;
 | 
			
		||||
 | 
			
		||||
	return impl;
 | 
			
		||||
| 
						 | 
				
			
			@ -88,6 +95,9 @@ static void webrtc_destroy(void *ec)
 | 
			
		|||
	struct impl *impl = (struct impl*)ec;
 | 
			
		||||
 | 
			
		||||
	delete impl->apm;
 | 
			
		||||
	free(impl->play_buffer);
 | 
			
		||||
	free(impl->rec_buffer);
 | 
			
		||||
	free(impl->out_buffer);
 | 
			
		||||
	free(impl);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -96,26 +106,34 @@ static int webrtc_run(void *ec, const float *rec[], const float *play[], float *
 | 
			
		|||
	struct impl *impl = (struct impl*)ec;
 | 
			
		||||
	webrtc::StreamConfig config =
 | 
			
		||||
		webrtc::StreamConfig(impl->info.rate, impl->info.channels, false);
 | 
			
		||||
	unsigned int num_blocks = n_samples * 1000 / impl->info.rate / 10;
 | 
			
		||||
 | 
			
		||||
	if (n_samples * 1000 / impl->info.rate != 10) {
 | 
			
		||||
		pw_log_error("Buffers must be 10ms in length (currently %u samples)", n_samples);
 | 
			
		||||
	if (n_samples * 1000 / impl->info.rate % 10 != 0) {
 | 
			
		||||
		pw_log_error("Buffers must be multiples of 10ms in length (currently %u samples)", n_samples);
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (size_t i = 0; i < num_blocks; i ++) {
 | 
			
		||||
		for (size_t j = 0; j < impl->info.channels; j++) {
 | 
			
		||||
			impl->play_buffer[j] = (float*)play[j] + config.num_frames() * i;
 | 
			
		||||
			impl->rec_buffer[j] = (float*)rec[j] + config.num_frames() * i;
 | 
			
		||||
			impl->out_buffer[j] = out[j] + config.num_frames() * i;
 | 
			
		||||
		}
 | 
			
		||||
		/* FIXME: ProcessReverseStream may change the playback buffer, in which
 | 
			
		||||
		* case we should use that, if we ever expose the intelligibility
 | 
			
		||||
		* enhancer */
 | 
			
		||||
	if (impl->apm->ProcessReverseStream(play, config, config, (float**)play) !=
 | 
			
		||||
		if (impl->apm->ProcessReverseStream(impl->play_buffer, config, config, impl->play_buffer) !=
 | 
			
		||||
				webrtc::AudioProcessing::kNoError) {
 | 
			
		||||
			pw_log_error("Processing reverse stream failed");
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		impl->apm->set_stream_delay_ms(0);
 | 
			
		||||
 | 
			
		||||
	if (impl->apm->ProcessStream(rec, config, config, out) !=
 | 
			
		||||
		if (impl->apm->ProcessStream(impl->rec_buffer, config, config, impl->out_buffer) !=
 | 
			
		||||
				webrtc::AudioProcessing::kNoError) {
 | 
			
		||||
			pw_log_error("Processing stream failed");
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue