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);
 | 
							pw_properties_set(props, PW_KEY_NODE_GROUP, str);
 | 
				
			||||||
	if ((str = pw_properties_get(impl->source_props, PW_KEY_NODE_LINK_GROUP)) != NULL)
 | 
						if ((str = pw_properties_get(impl->source_props, PW_KEY_NODE_LINK_GROUP)) != NULL)
 | 
				
			||||||
		pw_properties_set(props, PW_KEY_NODE_LINK_GROUP, str);
 | 
							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);
 | 
							pw_properties_set(props, PW_KEY_NODE_LATENCY, impl->aec_info->latency);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	impl->capture = pw_stream_new(impl->core,
 | 
						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);
 | 
							pw_properties_set(props, PW_KEY_NODE_GROUP, str);
 | 
				
			||||||
	if ((str = pw_properties_get(impl->sink_props, PW_KEY_NODE_LINK_GROUP)) != NULL)
 | 
						if ((str = pw_properties_get(impl->sink_props, PW_KEY_NODE_LINK_GROUP)) != NULL)
 | 
				
			||||||
		pw_properties_set(props, PW_KEY_NODE_LINK_GROUP, str);
 | 
							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);
 | 
							pw_properties_set(props, PW_KEY_NODE_LATENCY, impl->aec_info->latency);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	impl->playback = pw_stream_new(impl->core,
 | 
						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);
 | 
						pw_properties_free(aec_props);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (impl->aec_info->latency) {
 | 
						if (impl->aec_info->latency) {
 | 
				
			||||||
		unsigned int num, denom;
 | 
							unsigned int num, denom, req_num, req_denom;
 | 
				
			||||||
 | 
							unsigned int factor = 0;
 | 
				
			||||||
		pw_log_info("Setting node latency to %s", impl->aec_info->latency);
 | 
							unsigned int new_num = 0;
 | 
				
			||||||
		pw_properties_set(props, PW_KEY_NODE_LATENCY, impl->aec_info->latency);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		sscanf(impl->aec_info->latency, "%u/%u", &num, &denom);
 | 
							sscanf(impl->aec_info->latency, "%u/%u", &num, &denom);
 | 
				
			||||||
		impl->aec_blocksize = sizeof(float) * impl->info.rate * 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 {
 | 
						} else {
 | 
				
			||||||
		/* Implementation doesn't care about the block size */
 | 
							/* Implementation doesn't care about the block size */
 | 
				
			||||||
		impl->aec_blocksize = 0;
 | 
							impl->aec_blocksize = 0;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -34,6 +34,9 @@
 | 
				
			||||||
struct impl {
 | 
					struct impl {
 | 
				
			||||||
	webrtc::AudioProcessing *apm = NULL;
 | 
						webrtc::AudioProcessing *apm = NULL;
 | 
				
			||||||
	spa_audio_info_raw info;
 | 
						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)
 | 
					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 = (struct impl *)calloc(1, sizeof(struct impl));
 | 
				
			||||||
	impl->info = *info;
 | 
						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;
 | 
						impl->apm = apm;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return impl;
 | 
						return impl;
 | 
				
			||||||
| 
						 | 
					@ -88,6 +95,9 @@ static void webrtc_destroy(void *ec)
 | 
				
			||||||
	struct impl *impl = (struct impl*)ec;
 | 
						struct impl *impl = (struct impl*)ec;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	delete impl->apm;
 | 
						delete impl->apm;
 | 
				
			||||||
 | 
						free(impl->play_buffer);
 | 
				
			||||||
 | 
						free(impl->rec_buffer);
 | 
				
			||||||
 | 
						free(impl->out_buffer);
 | 
				
			||||||
	free(impl);
 | 
						free(impl);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -96,25 +106,33 @@ static int webrtc_run(void *ec, const float *rec[], const float *play[], float *
 | 
				
			||||||
	struct impl *impl = (struct impl*)ec;
 | 
						struct impl *impl = (struct impl*)ec;
 | 
				
			||||||
	webrtc::StreamConfig config =
 | 
						webrtc::StreamConfig config =
 | 
				
			||||||
		webrtc::StreamConfig(impl->info.rate, impl->info.channels, false);
 | 
							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) {
 | 
						if (n_samples * 1000 / impl->info.rate % 10 != 0) {
 | 
				
			||||||
		pw_log_error("Buffers must be 10ms in length (currently %u samples)", n_samples);
 | 
							pw_log_error("Buffers must be multiples of 10ms in length (currently %u samples)", n_samples);
 | 
				
			||||||
		return -1;
 | 
							return -1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* FIXME: ProcessReverseStream may change the playback buffer, in which
 | 
						for (size_t i = 0; i < num_blocks; i ++) {
 | 
				
			||||||
	 * case we should use that, if we ever expose the intelligibility
 | 
							for (size_t j = 0; j < impl->info.channels; j++) {
 | 
				
			||||||
	 * enhancer */
 | 
								impl->play_buffer[j] = (float*)play[j] + config.num_frames() * i;
 | 
				
			||||||
	if (impl->apm->ProcessReverseStream(play, config, config, (float**)play) !=
 | 
								impl->rec_buffer[j] = (float*)rec[j] + config.num_frames() * i;
 | 
				
			||||||
			webrtc::AudioProcessing::kNoError) {
 | 
								impl->out_buffer[j] = out[j] + config.num_frames() * i;
 | 
				
			||||||
		pw_log_error("Processing reverse stream failed");
 | 
							}
 | 
				
			||||||
	}
 | 
							/* 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(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);
 | 
							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) {
 | 
									webrtc::AudioProcessing::kNoError) {
 | 
				
			||||||
		pw_log_error("Processing stream failed");
 | 
								pw_log_error("Processing stream failed");
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue