Allow setting AEC3 config on the audio processing builder
Tested: Bitexact on a large set of aecdumps, except when aecdump settings are respected and AECM is used (then processing becomes more faithful to the stored aecdump settings). Also verified that --aec_settings still takes effect.
Bug: webrtc:442444736, b:428638881
Change-Id: If1a0671c8faf994ceeda5d9ec5d99218981c87d6
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/411800
Reviewed-by: Jesus de Vicente Pena <devicentepena@webrtc.org>
Reviewed-by: Per Ã…hgren <peah@webrtc.org>
Commit-Queue: Sam Zackrisson <saza@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#45748}
diff --git a/api/audio/BUILD.gn b/api/audio/BUILD.gn
index 5e24cc7..2537979 100644
--- a/api/audio/BUILD.gn
+++ b/api/audio/BUILD.gn
@@ -106,6 +106,7 @@
"builtin_audio_processing_builder.h",
]
deps = [
+ ":aec3_config",
":audio_processing",
":echo_control",
":neural_residual_echo_estimator_api",
diff --git a/api/audio/builtin_audio_processing_builder.cc b/api/audio/builtin_audio_processing_builder.cc
index afb2e1a..b93187d 100644
--- a/api/audio/builtin_audio_processing_builder.cc
+++ b/api/audio/builtin_audio_processing_builder.cc
@@ -23,10 +23,10 @@
absl_nullable scoped_refptr<AudioProcessing>
BuiltinAudioProcessingBuilder::Build(const Environment& env) {
return make_ref_counted<AudioProcessingImpl>(
- env, config_, std::move(capture_post_processing_),
- std::move(render_pre_processing_), std::move(echo_control_factory_),
- std::move(echo_detector_), std::move(capture_analyzer_),
- std::move(neural_residual_echo_estimator_));
+ env, config_, echo_canceller_config_, echo_canceller_multichannel_config_,
+ std::move(capture_post_processing_), std::move(render_pre_processing_),
+ std::move(echo_control_factory_), std::move(echo_detector_),
+ std::move(capture_analyzer_), std::move(neural_residual_echo_estimator_));
}
} // namespace webrtc
diff --git a/api/audio/builtin_audio_processing_builder.h b/api/audio/builtin_audio_processing_builder.h
index bd8f495..396bfca 100644
--- a/api/audio/builtin_audio_processing_builder.h
+++ b/api/audio/builtin_audio_processing_builder.h
@@ -12,10 +12,12 @@
#define API_AUDIO_BUILTIN_AUDIO_PROCESSING_BUILDER_H_
#include <memory>
+#include <optional>
#include <utility>
#include "absl/base/nullability.h"
#include "api/audio/audio_processing.h"
+#include "api/audio/echo_canceller3_config.h"
#include "api/audio/echo_control.h"
#include "api/audio/neural_residual_echo_estimator.h"
#include "api/environment/environment.h"
@@ -42,6 +44,18 @@
return *this;
}
+ // Sets an echo canceller config to inject when APM is created. If a custom
+ // EchoControlFactory is also specified, this config has no effect.
+ // `echo_canceller_multichannel_config` is an optional config that, if
+ // specified, is applied for non-mono content.
+ BuiltinAudioProcessingBuilder& SetEchoCancellerConfig(
+ const EchoCanceller3Config& echo_canceller_config,
+ std::optional<EchoCanceller3Config> echo_canceller_multichannel_config) {
+ echo_canceller_config_ = echo_canceller_config;
+ echo_canceller_multichannel_config_ = echo_canceller_multichannel_config;
+ return *this;
+ }
+
// Sets the echo controller factory to inject when APM is created.
BuiltinAudioProcessingBuilder& SetEchoControlFactory(
std::unique_ptr<EchoControlFactory> echo_control_factory) {
@@ -77,7 +91,7 @@
return *this;
}
- // The AudioProcessingBuilder takes ownership of the
+ // The BuiltinAudioProcessingBuilder takes ownership of the
// neural_residual_echo_estimator.
BuiltinAudioProcessingBuilder& SetNeuralResidualEchoEstimator(
std::unique_ptr<NeuralResidualEchoEstimator>
@@ -94,6 +108,8 @@
private:
AudioProcessing::Config config_;
+ std::optional<EchoCanceller3Config> echo_canceller_config_;
+ std::optional<EchoCanceller3Config> echo_canceller_multichannel_config_;
std::unique_ptr<EchoControlFactory> echo_control_factory_;
std::unique_ptr<CustomProcessing> capture_post_processing_;
std::unique_ptr<CustomProcessing> render_pre_processing_;
diff --git a/modules/audio_processing/audio_processing_impl.cc b/modules/audio_processing/audio_processing_impl.cc
index b4e822b..0256ba0 100644
--- a/modules/audio_processing/audio_processing_impl.cc
+++ b/modules/audio_processing/audio_processing_impl.cc
@@ -433,6 +433,8 @@
AudioProcessingImpl::AudioProcessingImpl(const Environment& env)
: AudioProcessingImpl(env,
/*config=*/{},
+ /*echo_canceller_config=*/std::nullopt,
+ /*echo_canceller_multichannel_config=*/std::nullopt,
/*capture_post_processor=*/nullptr,
/*render_pre_processor=*/nullptr,
/*echo_control_factory=*/nullptr,
@@ -445,6 +447,8 @@
AudioProcessingImpl::AudioProcessingImpl(
const Environment& env,
const AudioProcessing::Config& config,
+ std::optional<EchoCanceller3Config> echo_canceller_config,
+ std::optional<EchoCanceller3Config> echo_canceller_multichannel_config,
std::unique_ptr<CustomProcessing> capture_post_processor,
std::unique_ptr<CustomProcessing> render_pre_processor,
std::unique_ptr<EchoControlFactory> echo_control_factory,
@@ -459,6 +463,8 @@
render_runtime_settings_enqueuer_(&render_runtime_settings_),
echo_control_factory_(std::move(echo_control_factory)),
config_(config),
+ echo_canceller_config_(echo_canceller_config),
+ echo_canceller_multichannel_config_(echo_canceller_multichannel_config),
submodule_states_(!!capture_post_processor,
!!render_pre_processor,
!!capture_analyzer),
@@ -1916,11 +1922,20 @@
submodules_.neural_residual_echo_estimator.get());
RTC_DCHECK(submodules_.echo_controller);
} else {
- EchoCanceller3Config config;
- std::optional<EchoCanceller3Config> multichannel_config =
- EchoCanceller3Config::CreateDefaultMultichannelConfig();
+ EchoCanceller3Config config_to_use =
+ echo_canceller_config_.value_or(EchoCanceller3Config());
+ std::optional<EchoCanceller3Config> multichannel_config_to_use =
+ echo_canceller_multichannel_config_;
+ if (!echo_canceller_config_.has_value() &&
+ !multichannel_config_to_use.has_value()) {
+ // We create a default multichannel config only if the user has set no
+ // config: If the user only provides a non-multichannel config, that
+ // config is used for both mono and multichannel AEC.
+ multichannel_config_to_use =
+ EchoCanceller3Config::CreateDefaultMultichannelConfig();
+ }
submodules_.echo_controller = std::make_unique<EchoCanceller3>(
- env_, config, multichannel_config,
+ env_, config_to_use, multichannel_config_to_use,
submodules_.neural_residual_echo_estimator.get(),
proc_sample_rate_hz(), num_reverse_channels(), num_proc_channels());
}
diff --git a/modules/audio_processing/audio_processing_impl.h b/modules/audio_processing/audio_processing_impl.h
index 1dd958d..aab0005 100644
--- a/modules/audio_processing/audio_processing_impl.h
+++ b/modules/audio_processing/audio_processing_impl.h
@@ -25,6 +25,7 @@
#include "api/array_view.h"
#include "api/audio/audio_processing.h"
#include "api/audio/audio_processing_statistics.h"
+#include "api/audio/echo_canceller3_config.h"
#include "api/audio/echo_control.h"
#include "api/audio/neural_residual_echo_estimator.h"
#include "api/environment/environment.h"
@@ -63,15 +64,18 @@
// Methods forcing APM to run in a single-threaded manner.
// Acquires both the render and capture locks.
explicit AudioProcessingImpl(const Environment& env);
- AudioProcessingImpl(const Environment& env,
- const AudioProcessing::Config& config,
- std::unique_ptr<CustomProcessing> capture_post_processor,
- std::unique_ptr<CustomProcessing> render_pre_processor,
- std::unique_ptr<EchoControlFactory> echo_control_factory,
- scoped_refptr<EchoDetector> echo_detector,
- std::unique_ptr<CustomAudioAnalyzer> capture_analyzer,
- std::unique_ptr<NeuralResidualEchoEstimator>
- neural_residual_echo_estimator);
+ AudioProcessingImpl(
+ const Environment& env,
+ const AudioProcessing::Config& config,
+ std::optional<EchoCanceller3Config> echo_canceller_config,
+ std::optional<EchoCanceller3Config> echo_canceller_multichannel_config,
+ std::unique_ptr<CustomProcessing> capture_post_processor,
+ std::unique_ptr<CustomProcessing> render_pre_processor,
+ std::unique_ptr<EchoControlFactory> echo_control_factory,
+ scoped_refptr<EchoDetector> echo_detector,
+ std::unique_ptr<CustomAudioAnalyzer> capture_analyzer,
+ std::unique_ptr<NeuralResidualEchoEstimator>
+ neural_residual_echo_estimator);
~AudioProcessingImpl() override;
int Initialize() override;
int Initialize(const ProcessingConfig& processing_config) override;
@@ -361,6 +365,10 @@
// Struct containing the Config specifying the behavior of APM.
AudioProcessing::Config config_;
+ // AEC3 settings used when an EchoControlFactory is not present.
+ const std::optional<EchoCanceller3Config> echo_canceller_config_;
+ const std::optional<EchoCanceller3Config> echo_canceller_multichannel_config_;
+
// Class containing information about what submodules are active.
SubmoduleStates submodule_states_;
diff --git a/modules/audio_processing/test/audioproc_float_impl.cc b/modules/audio_processing/test/audioproc_float_impl.cc
index ddf0647..5606cd8 100644
--- a/modules/audio_processing/test/audioproc_float_impl.cc
+++ b/modules/audio_processing/test/audioproc_float_impl.cc
@@ -28,7 +28,6 @@
#include "api/audio/audio_processing.h"
#include "api/audio/builtin_audio_processing_builder.h"
#include "api/audio/echo_canceller3_config.h"
-#include "api/audio/echo_canceller3_factory.h"
#include "api/audio/echo_detector_creator.h"
#include "api/environment/environment.h"
#include "api/environment/environment_factory.h"
@@ -789,30 +788,27 @@
void SetDependencies(const SimulationSettings& settings,
BuiltinAudioProcessingBuilder& builder) {
- // Create and set an EchoCanceller3Factory if needed.
- if (settings.use_aec && *settings.use_aec) {
- EchoCanceller3Config cfg;
- if (settings.aec_settings_filename) {
- if (settings.use_verbose_logging) {
- std::cout << "Reading AEC Parameters from JSON input." << std::endl;
- }
- cfg = ReadAec3ConfigFromJsonFile(*settings.aec_settings_filename);
+ EchoCanceller3Config aec3_config;
+ if (settings.aec_settings_filename) {
+ if (settings.use_verbose_logging) {
+ std::cout << "Reading AEC Parameters from JSON input." << std::endl;
}
-
- if (settings.linear_aec_output_filename) {
- cfg.filter.export_linear_aec_output = true;
- }
-
- if (settings.print_aec_parameter_values) {
- if (!settings.use_quiet_output) {
- std::cout << "AEC settings:" << std::endl;
- }
- std::cout << Aec3ConfigToJsonString(cfg) << std::endl;
- }
-
- builder.SetEchoControlFactory(std::make_unique<EchoCanceller3Factory>(cfg));
+ aec3_config = ReadAec3ConfigFromJsonFile(*settings.aec_settings_filename);
}
+ if (settings.linear_aec_output_filename) {
+ aec3_config.filter.export_linear_aec_output = true;
+ }
+
+ if (settings.print_aec_parameter_values) {
+ if (!settings.use_quiet_output) {
+ std::cout << "AEC settings:" << std::endl;
+ }
+ std::cout << Aec3ConfigToJsonString(aec3_config) << std::endl;
+ }
+ builder.SetEchoCancellerConfig(
+ aec3_config, /*echo_canceller_multichannel_config=*/std::nullopt);
+
if (settings.neural_echo_residual_estimator_model) {
auto model_runner = NeuralResidualEchoEstimatorImpl::LoadTfLiteModel(
*settings.neural_echo_residual_estimator_model);