Propagate field trials into EchoCanceller3

Bug: webrtc:369904700
Change-Id: I698dd126f1627f84abe2633bde215c06aeef6299
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/372400
Commit-Queue: Danil Chapovalov <danilchap@webrtc.org>
Reviewed-by: Per Åhgren <peah@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#43733}
This commit is contained in:
Danil Chapovalov 2024-12-20 13:53:27 +01:00 committed by WebRTC LUCI CQ
parent 63b914d178
commit c329350008
11 changed files with 167 additions and 136 deletions

View File

@ -140,6 +140,8 @@ rtc_library("aec3_factory") {
":echo_control", ":echo_control",
"../../modules/audio_processing/aec3", "../../modules/audio_processing/aec3",
"../../rtc_base/system:rtc_export", "../../rtc_base/system:rtc_export",
"../environment",
"//third_party/abseil-cpp/absl/base:nullability",
] ]
} }

View File

@ -12,8 +12,10 @@
#include <memory> #include <memory>
#include <optional> #include <optional>
#include "absl/base/nullability.h"
#include "api/audio/echo_canceller3_config.h" #include "api/audio/echo_canceller3_config.h"
#include "api/audio/echo_control.h" #include "api/audio/echo_control.h"
#include "api/environment/environment.h"
#include "modules/audio_processing/aec3/echo_canceller3.h" #include "modules/audio_processing/aec3/echo_canceller3.h"
namespace webrtc { namespace webrtc {
@ -23,12 +25,13 @@ EchoCanceller3Factory::EchoCanceller3Factory() {}
EchoCanceller3Factory::EchoCanceller3Factory(const EchoCanceller3Config& config) EchoCanceller3Factory::EchoCanceller3Factory(const EchoCanceller3Config& config)
: config_(config) {} : config_(config) {}
std::unique_ptr<EchoControl> EchoCanceller3Factory::Create( absl::Nonnull<std::unique_ptr<EchoControl>> EchoCanceller3Factory::Create(
const Environment& env,
int sample_rate_hz, int sample_rate_hz,
int num_render_channels, int num_render_channels,
int num_capture_channels) { int num_capture_channels) {
return std::make_unique<EchoCanceller3>( return std::make_unique<EchoCanceller3>(
config_, /*multichannel_config=*/std::nullopt, sample_rate_hz, env, config_, /*multichannel_config=*/std::nullopt, sample_rate_hz,
num_render_channels, num_capture_channels); num_render_channels, num_capture_channels);
} }

View File

@ -13,8 +13,10 @@
#include <memory> #include <memory>
#include "absl/base/nullability.h"
#include "api/audio/echo_canceller3_config.h" #include "api/audio/echo_canceller3_config.h"
#include "api/audio/echo_control.h" #include "api/audio/echo_control.h"
#include "api/environment/environment.h"
#include "rtc_base/system/rtc_export.h" #include "rtc_base/system/rtc_export.h"
namespace webrtc { namespace webrtc {
@ -29,9 +31,11 @@ class RTC_EXPORT EchoCanceller3Factory : public EchoControlFactory {
explicit EchoCanceller3Factory(const EchoCanceller3Config& config); explicit EchoCanceller3Factory(const EchoCanceller3Config& config);
// Creates an EchoCanceller3 with a specified channel count and sampling rate. // Creates an EchoCanceller3 with a specified channel count and sampling rate.
std::unique_ptr<EchoControl> Create(int sample_rate_hz, absl::Nonnull<std::unique_ptr<EchoControl>> Create(
int num_render_channels, const Environment& env,
int num_capture_channels) override; int sample_rate_hz,
int num_render_channels,
int num_capture_channels) override;
private: private:
const EchoCanceller3Config config_; const EchoCanceller3Config config_;

View File

@ -15,7 +15,6 @@
#include "absl/base/nullability.h" #include "absl/base/nullability.h"
#include "api/environment/environment.h" #include "api/environment/environment.h"
#include "rtc_base/checks.h"
namespace webrtc { namespace webrtc {
@ -68,23 +67,11 @@ class EchoControlFactory {
public: public:
virtual ~EchoControlFactory() = default; virtual ~EchoControlFactory() = default;
// TODO: bugs.webrtc.org/369904700 - Make pure virtual when implemented by
// all derived classes.
virtual absl::Nonnull<std::unique_ptr<EchoControl>> Create( virtual absl::Nonnull<std::unique_ptr<EchoControl>> Create(
const Environment& env, const Environment& env,
int sample_rate_hz, int sample_rate_hz,
int num_render_channels, int num_render_channels,
int num_capture_channels) { int num_capture_channels) = 0;
return Create(sample_rate_hz, num_render_channels, num_capture_channels);
}
// TODO: bugs.webrtc.org/369904700 - Delete when implementations are removed
// from the derived classes.
virtual std::unique_ptr<EchoControl> Create(int sample_rate_hz,
int num_render_channels,
int num_capture_channels) {
RTC_CHECK_NOTREACHED();
}
}; };
} // namespace webrtc } // namespace webrtc

View File

@ -141,8 +141,10 @@ rtc_library("aec3") {
"..:audio_buffer", "..:audio_buffer",
"..:high_pass_filter", "..:high_pass_filter",
"../../../api:array_view", "../../../api:array_view",
"../../../api:field_trials_view",
"../../../api/audio:aec3_config", "../../../api/audio:aec3_config",
"../../../api/audio:echo_control", "../../../api/audio:echo_control",
"../../../api/environment",
"../../../common_audio:common_audio_c", "../../../common_audio:common_audio_c",
"../../../rtc_base:checks", "../../../rtc_base:checks",
"../../../rtc_base:logging", "../../../rtc_base:logging",
@ -313,6 +315,8 @@ if (rtc_include_tests) {
"..:high_pass_filter", "..:high_pass_filter",
"../../../api:array_view", "../../../api:array_view",
"../../../api/audio:aec3_config", "../../../api/audio:aec3_config",
"../../../api/environment",
"../../../api/environment:environment_factory",
"../../../rtc_base:checks", "../../../rtc_base:checks",
"../../../rtc_base:macromagic", "../../../rtc_base:macromagic",
"../../../rtc_base:random", "../../../rtc_base:random",
@ -321,6 +325,7 @@ if (rtc_include_tests) {
"../../../rtc_base/system:arch", "../../../rtc_base/system:arch",
"../../../system_wrappers", "../../../system_wrappers",
"../../../system_wrappers:metrics", "../../../system_wrappers:metrics",
"../../../test:explicit_key_value_config",
"../../../test:field_trial", "../../../test:field_trial",
"../../../test:test_support", "../../../test:test_support",
"../utility:cascaded_biquad_filter", "../utility:cascaded_biquad_filter",

View File

@ -13,12 +13,13 @@
#include <utility> #include <utility>
#include "absl/strings/string_view.h" #include "absl/strings/string_view.h"
#include "api/environment/environment.h"
#include "api/field_trials_view.h"
#include "modules/audio_processing/aec3/aec3_common.h" #include "modules/audio_processing/aec3/aec3_common.h"
#include "modules/audio_processing/high_pass_filter.h" #include "modules/audio_processing/high_pass_filter.h"
#include "modules/audio_processing/logging/apm_data_dumper.h" #include "modules/audio_processing/logging/apm_data_dumper.h"
#include "rtc_base/experiments/field_trial_parser.h" #include "rtc_base/experiments/field_trial_parser.h"
#include "rtc_base/logging.h" #include "rtc_base/logging.h"
#include "system_wrappers/include/field_trial.h"
namespace webrtc { namespace webrtc {
@ -38,11 +39,12 @@ bool DetectSaturation(rtc::ArrayView<const float> y) {
// Retrieves a value from a field trial if it is available. If no value is // Retrieves a value from a field trial if it is available. If no value is
// present, the default value is returned. If the retrieved value is beyond the // present, the default value is returned. If the retrieved value is beyond the
// specified limits, the default value is returned instead. // specified limits, the default value is returned instead.
void RetrieveFieldTrialValue(absl::string_view trial_name, void RetrieveFieldTrialValue(const FieldTrialsView& field_trials,
absl::string_view trial_name,
float min, float min,
float max, float max,
float* value_to_update) { float* value_to_update) {
const std::string field_trial_str = field_trial::FindFullName(trial_name); const std::string field_trial_str = field_trials.Lookup(trial_name);
FieldTrialParameter<double> field_trial_param(/*key=*/"", *value_to_update); FieldTrialParameter<double> field_trial_param(/*key=*/"", *value_to_update);
@ -58,11 +60,12 @@ void RetrieveFieldTrialValue(absl::string_view trial_name,
} }
} }
void RetrieveFieldTrialValue(absl::string_view trial_name, void RetrieveFieldTrialValue(const FieldTrialsView& field_trials,
absl::string_view trial_name,
int min, int min,
int max, int max,
int* value_to_update) { int* value_to_update) {
const std::string field_trial_str = field_trial::FindFullName(trial_name); const std::string field_trial_str = field_trials.Lookup(trial_name);
FieldTrialParameter<int> field_trial_param(/*key=*/"", *value_to_update); FieldTrialParameter<int> field_trial_param(/*key=*/"", *value_to_update);
@ -256,61 +259,62 @@ void CopyBufferIntoFrame(const AudioBuffer& buffer,
} // namespace } // namespace
// TODO(webrtc:5298): Move this to a separate file. // TODO(webrtc:5298): Move this to a separate file.
EchoCanceller3Config AdjustConfig(const EchoCanceller3Config& config) { EchoCanceller3Config AdjustConfig(const EchoCanceller3Config& config,
const FieldTrialsView& field_trials) {
EchoCanceller3Config adjusted_cfg = config; EchoCanceller3Config adjusted_cfg = config;
if (field_trial::IsEnabled("WebRTC-Aec3StereoContentDetectionKillSwitch")) { if (field_trials.IsEnabled("WebRTC-Aec3StereoContentDetectionKillSwitch")) {
adjusted_cfg.multi_channel.detect_stereo_content = false; adjusted_cfg.multi_channel.detect_stereo_content = false;
} }
if (field_trial::IsEnabled("WebRTC-Aec3AntiHowlingMinimizationKillSwitch")) { if (field_trials.IsEnabled("WebRTC-Aec3AntiHowlingMinimizationKillSwitch")) {
adjusted_cfg.suppressor.high_bands_suppression adjusted_cfg.suppressor.high_bands_suppression
.anti_howling_activation_threshold = 25.f; .anti_howling_activation_threshold = 25.f;
adjusted_cfg.suppressor.high_bands_suppression.anti_howling_gain = 0.01f; adjusted_cfg.suppressor.high_bands_suppression.anti_howling_gain = 0.01f;
} }
if (field_trial::IsEnabled("WebRTC-Aec3UseShortConfigChangeDuration")) { if (field_trials.IsEnabled("WebRTC-Aec3UseShortConfigChangeDuration")) {
adjusted_cfg.filter.config_change_duration_blocks = 10; adjusted_cfg.filter.config_change_duration_blocks = 10;
} }
if (field_trial::IsEnabled("WebRTC-Aec3UseZeroInitialStateDuration")) { if (field_trials.IsEnabled("WebRTC-Aec3UseZeroInitialStateDuration")) {
adjusted_cfg.filter.initial_state_seconds = 0.f; adjusted_cfg.filter.initial_state_seconds = 0.f;
} else if (field_trial::IsEnabled( } else if (field_trials.IsEnabled(
"WebRTC-Aec3UseDot1SecondsInitialStateDuration")) { "WebRTC-Aec3UseDot1SecondsInitialStateDuration")) {
adjusted_cfg.filter.initial_state_seconds = .1f; adjusted_cfg.filter.initial_state_seconds = .1f;
} else if (field_trial::IsEnabled( } else if (field_trials.IsEnabled(
"WebRTC-Aec3UseDot2SecondsInitialStateDuration")) { "WebRTC-Aec3UseDot2SecondsInitialStateDuration")) {
adjusted_cfg.filter.initial_state_seconds = .2f; adjusted_cfg.filter.initial_state_seconds = .2f;
} else if (field_trial::IsEnabled( } else if (field_trials.IsEnabled(
"WebRTC-Aec3UseDot3SecondsInitialStateDuration")) { "WebRTC-Aec3UseDot3SecondsInitialStateDuration")) {
adjusted_cfg.filter.initial_state_seconds = .3f; adjusted_cfg.filter.initial_state_seconds = .3f;
} else if (field_trial::IsEnabled( } else if (field_trials.IsEnabled(
"WebRTC-Aec3UseDot6SecondsInitialStateDuration")) { "WebRTC-Aec3UseDot6SecondsInitialStateDuration")) {
adjusted_cfg.filter.initial_state_seconds = .6f; adjusted_cfg.filter.initial_state_seconds = .6f;
} else if (field_trial::IsEnabled( } else if (field_trials.IsEnabled(
"WebRTC-Aec3UseDot9SecondsInitialStateDuration")) { "WebRTC-Aec3UseDot9SecondsInitialStateDuration")) {
adjusted_cfg.filter.initial_state_seconds = .9f; adjusted_cfg.filter.initial_state_seconds = .9f;
} else if (field_trial::IsEnabled( } else if (field_trials.IsEnabled(
"WebRTC-Aec3Use1Dot2SecondsInitialStateDuration")) { "WebRTC-Aec3Use1Dot2SecondsInitialStateDuration")) {
adjusted_cfg.filter.initial_state_seconds = 1.2f; adjusted_cfg.filter.initial_state_seconds = 1.2f;
} else if (field_trial::IsEnabled( } else if (field_trials.IsEnabled(
"WebRTC-Aec3Use1Dot6SecondsInitialStateDuration")) { "WebRTC-Aec3Use1Dot6SecondsInitialStateDuration")) {
adjusted_cfg.filter.initial_state_seconds = 1.6f; adjusted_cfg.filter.initial_state_seconds = 1.6f;
} else if (field_trial::IsEnabled( } else if (field_trials.IsEnabled(
"WebRTC-Aec3Use2Dot0SecondsInitialStateDuration")) { "WebRTC-Aec3Use2Dot0SecondsInitialStateDuration")) {
adjusted_cfg.filter.initial_state_seconds = 2.0f; adjusted_cfg.filter.initial_state_seconds = 2.0f;
} }
if (field_trial::IsEnabled("WebRTC-Aec3HighPassFilterEchoReference")) { if (field_trials.IsEnabled("WebRTC-Aec3HighPassFilterEchoReference")) {
adjusted_cfg.filter.high_pass_filter_echo_reference = true; adjusted_cfg.filter.high_pass_filter_echo_reference = true;
} }
if (field_trial::IsEnabled("WebRTC-Aec3EchoSaturationDetectionKillSwitch")) { if (field_trials.IsEnabled("WebRTC-Aec3EchoSaturationDetectionKillSwitch")) {
adjusted_cfg.ep_strength.echo_can_saturate = false; adjusted_cfg.ep_strength.echo_can_saturate = false;
} }
const std::string use_nearend_reverb_len_tunings = const std::string use_nearend_reverb_len_tunings =
field_trial::FindFullName("WebRTC-Aec3UseNearendReverbLen"); field_trials.Lookup("WebRTC-Aec3UseNearendReverbLen");
FieldTrialParameter<double> nearend_reverb_default_len( FieldTrialParameter<double> nearend_reverb_default_len(
"default_len", adjusted_cfg.ep_strength.default_len); "default_len", adjusted_cfg.ep_strength.default_len);
FieldTrialParameter<double> nearend_reverb_nearend_len( FieldTrialParameter<double> nearend_reverb_nearend_len(
@ -328,138 +332,138 @@ EchoCanceller3Config AdjustConfig(const EchoCanceller3Config& config) {
static_cast<float>(nearend_reverb_nearend_len.Get()); static_cast<float>(nearend_reverb_nearend_len.Get());
} }
if (field_trial::IsEnabled("WebRTC-Aec3ConservativeTailFreqResponse")) { if (field_trials.IsEnabled("WebRTC-Aec3ConservativeTailFreqResponse")) {
adjusted_cfg.ep_strength.use_conservative_tail_frequency_response = true; adjusted_cfg.ep_strength.use_conservative_tail_frequency_response = true;
} }
if (field_trial::IsDisabled("WebRTC-Aec3ConservativeTailFreqResponse")) { if (field_trials.IsDisabled("WebRTC-Aec3ConservativeTailFreqResponse")) {
adjusted_cfg.ep_strength.use_conservative_tail_frequency_response = false; adjusted_cfg.ep_strength.use_conservative_tail_frequency_response = false;
} }
if (field_trial::IsEnabled("WebRTC-Aec3ShortHeadroomKillSwitch")) { if (field_trials.IsEnabled("WebRTC-Aec3ShortHeadroomKillSwitch")) {
// Two blocks headroom. // Two blocks headroom.
adjusted_cfg.delay.delay_headroom_samples = kBlockSize * 2; adjusted_cfg.delay.delay_headroom_samples = kBlockSize * 2;
} }
if (field_trial::IsEnabled("WebRTC-Aec3ClampInstQualityToZeroKillSwitch")) { if (field_trials.IsEnabled("WebRTC-Aec3ClampInstQualityToZeroKillSwitch")) {
adjusted_cfg.erle.clamp_quality_estimate_to_zero = false; adjusted_cfg.erle.clamp_quality_estimate_to_zero = false;
} }
if (field_trial::IsEnabled("WebRTC-Aec3ClampInstQualityToOneKillSwitch")) { if (field_trials.IsEnabled("WebRTC-Aec3ClampInstQualityToOneKillSwitch")) {
adjusted_cfg.erle.clamp_quality_estimate_to_one = false; adjusted_cfg.erle.clamp_quality_estimate_to_one = false;
} }
if (field_trial::IsEnabled("WebRTC-Aec3OnsetDetectionKillSwitch")) { if (field_trials.IsEnabled("WebRTC-Aec3OnsetDetectionKillSwitch")) {
adjusted_cfg.erle.onset_detection = false; adjusted_cfg.erle.onset_detection = false;
} }
if (field_trial::IsEnabled( if (field_trials.IsEnabled(
"WebRTC-Aec3EnforceRenderDelayEstimationDownmixing")) { "WebRTC-Aec3EnforceRenderDelayEstimationDownmixing")) {
adjusted_cfg.delay.render_alignment_mixing.downmix = true; adjusted_cfg.delay.render_alignment_mixing.downmix = true;
adjusted_cfg.delay.render_alignment_mixing.adaptive_selection = false; adjusted_cfg.delay.render_alignment_mixing.adaptive_selection = false;
} }
if (field_trial::IsEnabled( if (field_trials.IsEnabled(
"WebRTC-Aec3EnforceCaptureDelayEstimationDownmixing")) { "WebRTC-Aec3EnforceCaptureDelayEstimationDownmixing")) {
adjusted_cfg.delay.capture_alignment_mixing.downmix = true; adjusted_cfg.delay.capture_alignment_mixing.downmix = true;
adjusted_cfg.delay.capture_alignment_mixing.adaptive_selection = false; adjusted_cfg.delay.capture_alignment_mixing.adaptive_selection = false;
} }
if (field_trial::IsEnabled( if (field_trials.IsEnabled(
"WebRTC-Aec3EnforceCaptureDelayEstimationLeftRightPrioritization")) { "WebRTC-Aec3EnforceCaptureDelayEstimationLeftRightPrioritization")) {
adjusted_cfg.delay.capture_alignment_mixing.prefer_first_two_channels = adjusted_cfg.delay.capture_alignment_mixing.prefer_first_two_channels =
true; true;
} }
if (field_trial::IsEnabled( if (field_trials.IsEnabled(
"WebRTC-" "WebRTC-"
"Aec3RenderDelayEstimationLeftRightPrioritizationKillSwitch")) { "Aec3RenderDelayEstimationLeftRightPrioritizationKillSwitch")) {
adjusted_cfg.delay.capture_alignment_mixing.prefer_first_two_channels = adjusted_cfg.delay.capture_alignment_mixing.prefer_first_two_channels =
false; false;
} }
if (field_trial::IsEnabled("WebRTC-Aec3SensitiveDominantNearendActivation")) { if (field_trials.IsEnabled("WebRTC-Aec3SensitiveDominantNearendActivation")) {
adjusted_cfg.suppressor.dominant_nearend_detection.enr_threshold = 0.5f; adjusted_cfg.suppressor.dominant_nearend_detection.enr_threshold = 0.5f;
} else if (field_trial::IsEnabled( } else if (field_trials.IsEnabled(
"WebRTC-Aec3VerySensitiveDominantNearendActivation")) { "WebRTC-Aec3VerySensitiveDominantNearendActivation")) {
adjusted_cfg.suppressor.dominant_nearend_detection.enr_threshold = 0.75f; adjusted_cfg.suppressor.dominant_nearend_detection.enr_threshold = 0.75f;
} }
if (field_trial::IsEnabled("WebRTC-Aec3TransparentAntiHowlingGain")) { if (field_trials.IsEnabled("WebRTC-Aec3TransparentAntiHowlingGain")) {
adjusted_cfg.suppressor.high_bands_suppression.anti_howling_gain = 1.f; adjusted_cfg.suppressor.high_bands_suppression.anti_howling_gain = 1.f;
} }
if (field_trial::IsEnabled( if (field_trials.IsEnabled(
"WebRTC-Aec3EnforceMoreTransparentNormalSuppressorTuning")) { "WebRTC-Aec3EnforceMoreTransparentNormalSuppressorTuning")) {
adjusted_cfg.suppressor.normal_tuning.mask_lf.enr_transparent = 0.4f; adjusted_cfg.suppressor.normal_tuning.mask_lf.enr_transparent = 0.4f;
adjusted_cfg.suppressor.normal_tuning.mask_lf.enr_suppress = 0.5f; adjusted_cfg.suppressor.normal_tuning.mask_lf.enr_suppress = 0.5f;
} }
if (field_trial::IsEnabled( if (field_trials.IsEnabled(
"WebRTC-Aec3EnforceMoreTransparentNearendSuppressorTuning")) { "WebRTC-Aec3EnforceMoreTransparentNearendSuppressorTuning")) {
adjusted_cfg.suppressor.nearend_tuning.mask_lf.enr_transparent = 1.29f; adjusted_cfg.suppressor.nearend_tuning.mask_lf.enr_transparent = 1.29f;
adjusted_cfg.suppressor.nearend_tuning.mask_lf.enr_suppress = 1.3f; adjusted_cfg.suppressor.nearend_tuning.mask_lf.enr_suppress = 1.3f;
} }
if (field_trial::IsEnabled( if (field_trials.IsEnabled(
"WebRTC-Aec3EnforceMoreTransparentNormalSuppressorHfTuning")) { "WebRTC-Aec3EnforceMoreTransparentNormalSuppressorHfTuning")) {
adjusted_cfg.suppressor.normal_tuning.mask_hf.enr_transparent = 0.3f; adjusted_cfg.suppressor.normal_tuning.mask_hf.enr_transparent = 0.3f;
adjusted_cfg.suppressor.normal_tuning.mask_hf.enr_suppress = 0.4f; adjusted_cfg.suppressor.normal_tuning.mask_hf.enr_suppress = 0.4f;
} }
if (field_trial::IsEnabled( if (field_trials.IsEnabled(
"WebRTC-Aec3EnforceMoreTransparentNearendSuppressorHfTuning")) { "WebRTC-Aec3EnforceMoreTransparentNearendSuppressorHfTuning")) {
adjusted_cfg.suppressor.nearend_tuning.mask_hf.enr_transparent = 1.09f; adjusted_cfg.suppressor.nearend_tuning.mask_hf.enr_transparent = 1.09f;
adjusted_cfg.suppressor.nearend_tuning.mask_hf.enr_suppress = 1.1f; adjusted_cfg.suppressor.nearend_tuning.mask_hf.enr_suppress = 1.1f;
} }
if (field_trial::IsEnabled( if (field_trials.IsEnabled(
"WebRTC-Aec3EnforceRapidlyAdjustingNormalSuppressorTunings")) { "WebRTC-Aec3EnforceRapidlyAdjustingNormalSuppressorTunings")) {
adjusted_cfg.suppressor.normal_tuning.max_inc_factor = 2.5f; adjusted_cfg.suppressor.normal_tuning.max_inc_factor = 2.5f;
} }
if (field_trial::IsEnabled( if (field_trials.IsEnabled(
"WebRTC-Aec3EnforceRapidlyAdjustingNearendSuppressorTunings")) { "WebRTC-Aec3EnforceRapidlyAdjustingNearendSuppressorTunings")) {
adjusted_cfg.suppressor.nearend_tuning.max_inc_factor = 2.5f; adjusted_cfg.suppressor.nearend_tuning.max_inc_factor = 2.5f;
} }
if (field_trial::IsEnabled( if (field_trials.IsEnabled(
"WebRTC-Aec3EnforceSlowlyAdjustingNormalSuppressorTunings")) { "WebRTC-Aec3EnforceSlowlyAdjustingNormalSuppressorTunings")) {
adjusted_cfg.suppressor.normal_tuning.max_dec_factor_lf = .2f; adjusted_cfg.suppressor.normal_tuning.max_dec_factor_lf = .2f;
} }
if (field_trial::IsEnabled( if (field_trials.IsEnabled(
"WebRTC-Aec3EnforceSlowlyAdjustingNearendSuppressorTunings")) { "WebRTC-Aec3EnforceSlowlyAdjustingNearendSuppressorTunings")) {
adjusted_cfg.suppressor.nearend_tuning.max_dec_factor_lf = .2f; adjusted_cfg.suppressor.nearend_tuning.max_dec_factor_lf = .2f;
} }
if (field_trial::IsEnabled("WebRTC-Aec3EnforceConservativeHfSuppression")) { if (field_trials.IsEnabled("WebRTC-Aec3EnforceConservativeHfSuppression")) {
adjusted_cfg.suppressor.conservative_hf_suppression = true; adjusted_cfg.suppressor.conservative_hf_suppression = true;
} }
if (field_trial::IsEnabled("WebRTC-Aec3EnforceStationarityProperties")) { if (field_trials.IsEnabled("WebRTC-Aec3EnforceStationarityProperties")) {
adjusted_cfg.echo_audibility.use_stationarity_properties = true; adjusted_cfg.echo_audibility.use_stationarity_properties = true;
} }
if (field_trial::IsEnabled( if (field_trials.IsEnabled(
"WebRTC-Aec3EnforceStationarityPropertiesAtInit")) { "WebRTC-Aec3EnforceStationarityPropertiesAtInit")) {
adjusted_cfg.echo_audibility.use_stationarity_properties_at_init = true; adjusted_cfg.echo_audibility.use_stationarity_properties_at_init = true;
} }
if (field_trial::IsEnabled("WebRTC-Aec3EnforceLowActiveRenderLimit")) { if (field_trials.IsEnabled("WebRTC-Aec3EnforceLowActiveRenderLimit")) {
adjusted_cfg.render_levels.active_render_limit = 50.f; adjusted_cfg.render_levels.active_render_limit = 50.f;
} else if (field_trial::IsEnabled( } else if (field_trials.IsEnabled(
"WebRTC-Aec3EnforceVeryLowActiveRenderLimit")) { "WebRTC-Aec3EnforceVeryLowActiveRenderLimit")) {
adjusted_cfg.render_levels.active_render_limit = 30.f; adjusted_cfg.render_levels.active_render_limit = 30.f;
} }
if (field_trial::IsEnabled("WebRTC-Aec3NonlinearModeReverbKillSwitch")) { if (field_trials.IsEnabled("WebRTC-Aec3NonlinearModeReverbKillSwitch")) {
adjusted_cfg.echo_model.model_reverb_in_nonlinear_mode = false; adjusted_cfg.echo_model.model_reverb_in_nonlinear_mode = false;
} }
// Field-trial based override for the whole suppressor tuning. // Field-trial based override for the whole suppressor tuning.
const std::string suppressor_tuning_override_trial_name = const std::string suppressor_tuning_override_trial_name =
field_trial::FindFullName("WebRTC-Aec3SuppressorTuningOverride"); field_trials.Lookup("WebRTC-Aec3SuppressorTuningOverride");
FieldTrialParameter<double> nearend_tuning_mask_lf_enr_transparent( FieldTrialParameter<double> nearend_tuning_mask_lf_enr_transparent(
"nearend_tuning_mask_lf_enr_transparent", "nearend_tuning_mask_lf_enr_transparent",
@ -568,76 +572,84 @@ EchoCanceller3Config AdjustConfig(const EchoCanceller3Config& config) {
// Field trial-based overrides of individual suppressor parameters. // Field trial-based overrides of individual suppressor parameters.
RetrieveFieldTrialValue( RetrieveFieldTrialValue(
"WebRTC-Aec3SuppressorNearendLfMaskTransparentOverride", 0.f, 10.f, field_trials, "WebRTC-Aec3SuppressorNearendLfMaskTransparentOverride",
0.f, 10.f,
&adjusted_cfg.suppressor.nearend_tuning.mask_lf.enr_transparent); &adjusted_cfg.suppressor.nearend_tuning.mask_lf.enr_transparent);
RetrieveFieldTrialValue( RetrieveFieldTrialValue(
"WebRTC-Aec3SuppressorNearendLfMaskSuppressOverride", 0.f, 10.f, field_trials, "WebRTC-Aec3SuppressorNearendLfMaskSuppressOverride", 0.f,
&adjusted_cfg.suppressor.nearend_tuning.mask_lf.enr_suppress); 10.f, &adjusted_cfg.suppressor.nearend_tuning.mask_lf.enr_suppress);
RetrieveFieldTrialValue( RetrieveFieldTrialValue(
"WebRTC-Aec3SuppressorNearendHfMaskTransparentOverride", 0.f, 10.f, field_trials, "WebRTC-Aec3SuppressorNearendHfMaskTransparentOverride",
0.f, 10.f,
&adjusted_cfg.suppressor.nearend_tuning.mask_hf.enr_transparent); &adjusted_cfg.suppressor.nearend_tuning.mask_hf.enr_transparent);
RetrieveFieldTrialValue( RetrieveFieldTrialValue(
"WebRTC-Aec3SuppressorNearendHfMaskSuppressOverride", 0.f, 10.f, field_trials, "WebRTC-Aec3SuppressorNearendHfMaskSuppressOverride", 0.f,
&adjusted_cfg.suppressor.nearend_tuning.mask_hf.enr_suppress); 10.f, &adjusted_cfg.suppressor.nearend_tuning.mask_hf.enr_suppress);
RetrieveFieldTrialValue( RetrieveFieldTrialValue(
"WebRTC-Aec3SuppressorNearendMaxIncFactorOverride", 0.f, 10.f, field_trials, "WebRTC-Aec3SuppressorNearendMaxIncFactorOverride", 0.f,
&adjusted_cfg.suppressor.nearend_tuning.max_inc_factor); 10.f, &adjusted_cfg.suppressor.nearend_tuning.max_inc_factor);
RetrieveFieldTrialValue( RetrieveFieldTrialValue(
"WebRTC-Aec3SuppressorNearendMaxDecFactorLfOverride", 0.f, 10.f, field_trials, "WebRTC-Aec3SuppressorNearendMaxDecFactorLfOverride", 0.f,
&adjusted_cfg.suppressor.nearend_tuning.max_dec_factor_lf); 10.f, &adjusted_cfg.suppressor.nearend_tuning.max_dec_factor_lf);
RetrieveFieldTrialValue( RetrieveFieldTrialValue(
"WebRTC-Aec3SuppressorNormalLfMaskTransparentOverride", 0.f, 10.f, field_trials, "WebRTC-Aec3SuppressorNormalLfMaskTransparentOverride", 0.f,
&adjusted_cfg.suppressor.normal_tuning.mask_lf.enr_transparent); 10.f, &adjusted_cfg.suppressor.normal_tuning.mask_lf.enr_transparent);
RetrieveFieldTrialValue( RetrieveFieldTrialValue(
"WebRTC-Aec3SuppressorNormalLfMaskSuppressOverride", 0.f, 10.f, field_trials, "WebRTC-Aec3SuppressorNormalLfMaskSuppressOverride", 0.f,
&adjusted_cfg.suppressor.normal_tuning.mask_lf.enr_suppress); 10.f, &adjusted_cfg.suppressor.normal_tuning.mask_lf.enr_suppress);
RetrieveFieldTrialValue( RetrieveFieldTrialValue(
"WebRTC-Aec3SuppressorNormalHfMaskTransparentOverride", 0.f, 10.f, field_trials, "WebRTC-Aec3SuppressorNormalHfMaskTransparentOverride", 0.f,
&adjusted_cfg.suppressor.normal_tuning.mask_hf.enr_transparent); 10.f, &adjusted_cfg.suppressor.normal_tuning.mask_hf.enr_transparent);
RetrieveFieldTrialValue( RetrieveFieldTrialValue(
"WebRTC-Aec3SuppressorNormalHfMaskSuppressOverride", 0.f, 10.f, field_trials, "WebRTC-Aec3SuppressorNormalHfMaskSuppressOverride", 0.f,
&adjusted_cfg.suppressor.normal_tuning.mask_hf.enr_suppress); 10.f, &adjusted_cfg.suppressor.normal_tuning.mask_hf.enr_suppress);
RetrieveFieldTrialValue( RetrieveFieldTrialValue(
"WebRTC-Aec3SuppressorNormalMaxIncFactorOverride", 0.f, 10.f, field_trials, "WebRTC-Aec3SuppressorNormalMaxIncFactorOverride", 0.f,
&adjusted_cfg.suppressor.normal_tuning.max_inc_factor); 10.f, &adjusted_cfg.suppressor.normal_tuning.max_inc_factor);
RetrieveFieldTrialValue( RetrieveFieldTrialValue(
"WebRTC-Aec3SuppressorNormalMaxDecFactorLfOverride", 0.f, 10.f, field_trials, "WebRTC-Aec3SuppressorNormalMaxDecFactorLfOverride", 0.f,
&adjusted_cfg.suppressor.normal_tuning.max_dec_factor_lf); 10.f, &adjusted_cfg.suppressor.normal_tuning.max_dec_factor_lf);
RetrieveFieldTrialValue( RetrieveFieldTrialValue(
"WebRTC-Aec3SuppressorDominantNearendEnrThresholdOverride", 0.f, 100.f, field_trials, "WebRTC-Aec3SuppressorDominantNearendEnrThresholdOverride",
0.f, 100.f,
&adjusted_cfg.suppressor.dominant_nearend_detection.enr_threshold); &adjusted_cfg.suppressor.dominant_nearend_detection.enr_threshold);
RetrieveFieldTrialValue( RetrieveFieldTrialValue(
field_trials,
"WebRTC-Aec3SuppressorDominantNearendEnrExitThresholdOverride", 0.f, "WebRTC-Aec3SuppressorDominantNearendEnrExitThresholdOverride", 0.f,
100.f, 100.f,
&adjusted_cfg.suppressor.dominant_nearend_detection.enr_exit_threshold); &adjusted_cfg.suppressor.dominant_nearend_detection.enr_exit_threshold);
RetrieveFieldTrialValue( RetrieveFieldTrialValue(
"WebRTC-Aec3SuppressorDominantNearendSnrThresholdOverride", 0.f, 100.f, field_trials, "WebRTC-Aec3SuppressorDominantNearendSnrThresholdOverride",
0.f, 100.f,
&adjusted_cfg.suppressor.dominant_nearend_detection.snr_threshold); &adjusted_cfg.suppressor.dominant_nearend_detection.snr_threshold);
RetrieveFieldTrialValue( RetrieveFieldTrialValue(
"WebRTC-Aec3SuppressorDominantNearendHoldDurationOverride", 0, 1000, field_trials, "WebRTC-Aec3SuppressorDominantNearendHoldDurationOverride",
0, 1000,
&adjusted_cfg.suppressor.dominant_nearend_detection.hold_duration); &adjusted_cfg.suppressor.dominant_nearend_detection.hold_duration);
RetrieveFieldTrialValue( RetrieveFieldTrialValue(
field_trials,
"WebRTC-Aec3SuppressorDominantNearendTriggerThresholdOverride", 0, 1000, "WebRTC-Aec3SuppressorDominantNearendTriggerThresholdOverride", 0, 1000,
&adjusted_cfg.suppressor.dominant_nearend_detection.trigger_threshold); &adjusted_cfg.suppressor.dominant_nearend_detection.trigger_threshold);
RetrieveFieldTrialValue( RetrieveFieldTrialValue(
"WebRTC-Aec3SuppressorAntiHowlingGainOverride", 0.f, 10.f, field_trials, "WebRTC-Aec3SuppressorAntiHowlingGainOverride", 0.f, 10.f,
&adjusted_cfg.suppressor.high_bands_suppression.anti_howling_gain); &adjusted_cfg.suppressor.high_bands_suppression.anti_howling_gain);
// Field trial-based overrides of individual delay estimator parameters. // Field trial-based overrides of individual delay estimator parameters.
RetrieveFieldTrialValue("WebRTC-Aec3DelayEstimateSmoothingOverride", 0.f, 1.f, RetrieveFieldTrialValue(field_trials,
"WebRTC-Aec3DelayEstimateSmoothingOverride", 0.f, 1.f,
&adjusted_cfg.delay.delay_estimate_smoothing); &adjusted_cfg.delay.delay_estimate_smoothing);
RetrieveFieldTrialValue( RetrieveFieldTrialValue(
"WebRTC-Aec3DelayEstimateSmoothingDelayFoundOverride", 0.f, 1.f, field_trials, "WebRTC-Aec3DelayEstimateSmoothingDelayFoundOverride", 0.f,
&adjusted_cfg.delay.delay_estimate_smoothing_delay_found); 1.f, &adjusted_cfg.delay.delay_estimate_smoothing_delay_found);
int max_allowed_excess_render_blocks_override = int max_allowed_excess_render_blocks_override =
adjusted_cfg.buffering.max_allowed_excess_render_blocks; adjusted_cfg.buffering.max_allowed_excess_render_blocks;
RetrieveFieldTrialValue( RetrieveFieldTrialValue(
"WebRTC-Aec3BufferingMaxAllowedExcessRenderBlocksOverride", 0, 20, field_trials, "WebRTC-Aec3BufferingMaxAllowedExcessRenderBlocksOverride",
&max_allowed_excess_render_blocks_override); 0, 20, &max_allowed_excess_render_blocks_override);
adjusted_cfg.buffering.max_allowed_excess_render_blocks = adjusted_cfg.buffering.max_allowed_excess_render_blocks =
max_allowed_excess_render_blocks_override; max_allowed_excess_render_blocks_override;
return adjusted_cfg; return adjusted_cfg;
@ -717,18 +729,19 @@ void EchoCanceller3::RenderWriter::Insert(const AudioBuffer& input) {
std::atomic<int> EchoCanceller3::instance_count_(0); std::atomic<int> EchoCanceller3::instance_count_(0);
EchoCanceller3::EchoCanceller3( EchoCanceller3::EchoCanceller3(
const Environment& env,
const EchoCanceller3Config& config, const EchoCanceller3Config& config,
const std::optional<EchoCanceller3Config>& multichannel_config, const std::optional<EchoCanceller3Config>& multichannel_config,
int sample_rate_hz, int sample_rate_hz,
size_t num_render_channels, size_t num_render_channels,
size_t num_capture_channels) size_t num_capture_channels)
: data_dumper_(new ApmDataDumper(instance_count_.fetch_add(1) + 1)), : data_dumper_(new ApmDataDumper(instance_count_.fetch_add(1) + 1)),
config_(AdjustConfig(config)), config_(AdjustConfig(config, env.field_trials())),
sample_rate_hz_(sample_rate_hz), sample_rate_hz_(sample_rate_hz),
num_bands_(NumBandsForRate(sample_rate_hz_)), num_bands_(NumBandsForRate(sample_rate_hz_)),
num_render_input_channels_(num_render_channels), num_render_input_channels_(num_render_channels),
num_capture_channels_(num_capture_channels), num_capture_channels_(num_capture_channels),
config_selector_(AdjustConfig(config), config_selector_(config_,
multichannel_config, multichannel_config,
num_render_input_channels_), num_render_input_channels_),
multichannel_content_detector_( multichannel_content_detector_(

View File

@ -21,6 +21,8 @@
#include "api/array_view.h" #include "api/array_view.h"
#include "api/audio/echo_canceller3_config.h" #include "api/audio/echo_canceller3_config.h"
#include "api/audio/echo_control.h" #include "api/audio/echo_control.h"
#include "api/environment/environment.h"
#include "api/field_trials_view.h"
#include "modules/audio_processing/aec3/api_call_jitter_metrics.h" #include "modules/audio_processing/aec3/api_call_jitter_metrics.h"
#include "modules/audio_processing/aec3/block_delay_buffer.h" #include "modules/audio_processing/aec3/block_delay_buffer.h"
#include "modules/audio_processing/aec3/block_framer.h" #include "modules/audio_processing/aec3/block_framer.h"
@ -40,7 +42,8 @@ namespace webrtc {
// Method for adjusting config parameter dependencies. // Method for adjusting config parameter dependencies.
// Only to be used externally to AEC3 for testing purposes. // Only to be used externally to AEC3 for testing purposes.
// TODO(webrtc:5298): Move this to a separate file. // TODO(webrtc:5298): Move this to a separate file.
EchoCanceller3Config AdjustConfig(const EchoCanceller3Config& config); EchoCanceller3Config AdjustConfig(const EchoCanceller3Config& config,
const FieldTrialsView& field_trials);
// Functor for verifying the invariance of the frames being put into the render // Functor for verifying the invariance of the frames being put into the render
// queue. // queue.
@ -88,7 +91,8 @@ class Aec3RenderQueueItemVerifier {
// AnalyzeRender call which can be called concurrently with the other methods. // AnalyzeRender call which can be called concurrently with the other methods.
class EchoCanceller3 : public EchoControl { class EchoCanceller3 : public EchoControl {
public: public:
EchoCanceller3(const EchoCanceller3Config& config, EchoCanceller3(const Environment& env,
const EchoCanceller3Config& config,
const std::optional<EchoCanceller3Config>& multichannel_config, const std::optional<EchoCanceller3Config>& multichannel_config,
int sample_rate_hz, int sample_rate_hz,
size_t num_render_channels, size_t num_render_channels,

View File

@ -16,6 +16,8 @@
#include <utility> #include <utility>
#include <vector> #include <vector>
#include "api/environment/environment.h"
#include "api/environment/environment_factory.h"
#include "modules/audio_processing/aec3/aec3_common.h" #include "modules/audio_processing/aec3/aec3_common.h"
#include "modules/audio_processing/aec3/block_processor.h" #include "modules/audio_processing/aec3/block_processor.h"
#include "modules/audio_processing/aec3/frame_blocker.h" #include "modules/audio_processing/aec3/frame_blocker.h"
@ -24,13 +26,14 @@
#include "modules/audio_processing/high_pass_filter.h" #include "modules/audio_processing/high_pass_filter.h"
#include "modules/audio_processing/utility/cascaded_biquad_filter.h" #include "modules/audio_processing/utility/cascaded_biquad_filter.h"
#include "rtc_base/strings/string_builder.h" #include "rtc_base/strings/string_builder.h"
#include "test/field_trial.h" #include "test/explicit_key_value_config.h"
#include "test/gmock.h" #include "test/gmock.h"
#include "test/gtest.h" #include "test/gtest.h"
namespace webrtc { namespace webrtc {
namespace { namespace {
using test::ExplicitKeyValueConfig;
using ::testing::_; using ::testing::_;
using ::testing::StrictMock; using ::testing::StrictMock;
@ -240,7 +243,7 @@ class EchoCanceller3Tester {
// and that the processor data is properly passed to the EchoCanceller3 // and that the processor data is properly passed to the EchoCanceller3
// output. // output.
void RunCaptureTransportVerificationTest() { void RunCaptureTransportVerificationTest() {
EchoCanceller3 aec3(EchoCanceller3Config(), EchoCanceller3 aec3(CreateEnvironment(), EchoCanceller3Config(),
/*multichannel_config=*/std::nullopt, sample_rate_hz_, /*multichannel_config=*/std::nullopt, sample_rate_hz_,
1, 1); 1, 1);
aec3.SetBlockProcessorForTesting( aec3.SetBlockProcessorForTesting(
@ -266,7 +269,7 @@ class EchoCanceller3Tester {
// Test method for testing that the render data is properly received by the // Test method for testing that the render data is properly received by the
// block processor. // block processor.
void RunRenderTransportVerificationTest() { void RunRenderTransportVerificationTest() {
EchoCanceller3 aec3(EchoCanceller3Config(), EchoCanceller3 aec3(CreateEnvironment(), EchoCanceller3Config(),
/*multichannel_config=*/std::nullopt, sample_rate_hz_, /*multichannel_config=*/std::nullopt, sample_rate_hz_,
1, 1); 1, 1);
aec3.SetBlockProcessorForTesting( aec3.SetBlockProcessorForTesting(
@ -337,7 +340,7 @@ class EchoCanceller3Tester {
break; break;
} }
EchoCanceller3 aec3(EchoCanceller3Config(), EchoCanceller3 aec3(CreateEnvironment(), EchoCanceller3Config(),
/*multichannel_config=*/std::nullopt, sample_rate_hz_, /*multichannel_config=*/std::nullopt, sample_rate_hz_,
1, 1); 1, 1);
aec3.SetBlockProcessorForTesting(std::move(block_processor_mock)); aec3.SetBlockProcessorForTesting(std::move(block_processor_mock));
@ -419,7 +422,7 @@ class EchoCanceller3Tester {
} break; } break;
} }
EchoCanceller3 aec3(EchoCanceller3Config(), EchoCanceller3 aec3(CreateEnvironment(), EchoCanceller3Config(),
/*multichannel_config=*/std::nullopt, sample_rate_hz_, /*multichannel_config=*/std::nullopt, sample_rate_hz_,
1, 1); 1, 1);
aec3.SetBlockProcessorForTesting(std::move(block_processor_mock)); aec3.SetBlockProcessorForTesting(std::move(block_processor_mock));
@ -507,7 +510,7 @@ class EchoCanceller3Tester {
} break; } break;
} }
EchoCanceller3 aec3(EchoCanceller3Config(), EchoCanceller3 aec3(CreateEnvironment(), EchoCanceller3Config(),
/*multichannel_config=*/std::nullopt, sample_rate_hz_, /*multichannel_config=*/std::nullopt, sample_rate_hz_,
1, 1); 1, 1);
aec3.SetBlockProcessorForTesting(std::move(block_processor_mock)); aec3.SetBlockProcessorForTesting(std::move(block_processor_mock));
@ -548,8 +551,9 @@ class EchoCanceller3Tester {
// capture and render API calls. // capture and render API calls.
void RunRenderSwapQueueVerificationTest() { void RunRenderSwapQueueVerificationTest() {
const EchoCanceller3Config config; const EchoCanceller3Config config;
EchoCanceller3 aec3(config, /*multichannel_config=*/std::nullopt, EchoCanceller3 aec3(CreateEnvironment(), config,
sample_rate_hz_, 1, 1); /*multichannel_config=*/std::nullopt, sample_rate_hz_,
1, 1);
aec3.SetBlockProcessorForTesting( aec3.SetBlockProcessorForTesting(
std::make_unique<RenderTransportVerificationProcessor>(num_bands_)); std::make_unique<RenderTransportVerificationProcessor>(num_bands_));
@ -597,7 +601,7 @@ class EchoCanceller3Tester {
// This test verifies that a buffer overrun in the render swapqueue is // This test verifies that a buffer overrun in the render swapqueue is
// properly reported. // properly reported.
void RunRenderPipelineSwapQueueOverrunReturnValueTest() { void RunRenderPipelineSwapQueueOverrunReturnValueTest() {
EchoCanceller3 aec3(EchoCanceller3Config(), EchoCanceller3 aec3(CreateEnvironment(), EchoCanceller3Config(),
/*multichannel_config=*/std::nullopt, sample_rate_hz_, /*multichannel_config=*/std::nullopt, sample_rate_hz_,
1, 1); 1, 1);
@ -624,7 +628,7 @@ class EchoCanceller3Tester {
// Set aec3_sample_rate_hz to be different from sample_rate_hz_ in such a // Set aec3_sample_rate_hz to be different from sample_rate_hz_ in such a
// way that the number of bands for the rates are different. // way that the number of bands for the rates are different.
const int aec3_sample_rate_hz = sample_rate_hz_ == 48000 ? 32000 : 48000; const int aec3_sample_rate_hz = sample_rate_hz_ == 48000 ? 32000 : 48000;
EchoCanceller3 aec3(EchoCanceller3Config(), EchoCanceller3 aec3(CreateEnvironment(), EchoCanceller3Config(),
/*multichannel_config=*/std::nullopt, /*multichannel_config=*/std::nullopt,
aec3_sample_rate_hz, 1, 1); aec3_sample_rate_hz, 1, 1);
PopulateInputFrame(frame_length_, 0, &render_buffer_.channels_f()[0][0], 0); PopulateInputFrame(frame_length_, 0, &render_buffer_.channels_f()[0][0], 0);
@ -639,7 +643,7 @@ class EchoCanceller3Tester {
// Set aec3_sample_rate_hz to be different from sample_rate_hz_ in such a // Set aec3_sample_rate_hz to be different from sample_rate_hz_ in such a
// way that the number of bands for the rates are different. // way that the number of bands for the rates are different.
const int aec3_sample_rate_hz = sample_rate_hz_ == 48000 ? 32000 : 48000; const int aec3_sample_rate_hz = sample_rate_hz_ == 48000 ? 32000 : 48000;
EchoCanceller3 aec3(EchoCanceller3Config(), EchoCanceller3 aec3(CreateEnvironment(), EchoCanceller3Config(),
/*multichannel_config=*/std::nullopt, /*multichannel_config=*/std::nullopt,
aec3_sample_rate_hz, 1, 1); aec3_sample_rate_hz, 1, 1);
PopulateInputFrame(frame_length_, num_bands_, 0, PopulateInputFrame(frame_length_, num_bands_, 0,
@ -735,14 +739,15 @@ TEST(EchoCanceller3Messaging, EchoLeakage) {
// anti-howling gain. // anti-howling gain.
TEST(EchoCanceller3FieldTrials, Aec3SuppressorAntiHowlingGainOverride) { TEST(EchoCanceller3FieldTrials, Aec3SuppressorAntiHowlingGainOverride) {
EchoCanceller3Config default_config; EchoCanceller3Config default_config;
EchoCanceller3Config adjusted_config = AdjustConfig(default_config); EchoCanceller3Config adjusted_config =
AdjustConfig(default_config, ExplicitKeyValueConfig(""));
ASSERT_EQ( ASSERT_EQ(
default_config.suppressor.high_bands_suppression.anti_howling_gain, default_config.suppressor.high_bands_suppression.anti_howling_gain,
adjusted_config.suppressor.high_bands_suppression.anti_howling_gain); adjusted_config.suppressor.high_bands_suppression.anti_howling_gain);
webrtc::test::ScopedFieldTrials field_trials( ExplicitKeyValueConfig field_trials(
"WebRTC-Aec3SuppressorAntiHowlingGainOverride/0.02/"); "WebRTC-Aec3SuppressorAntiHowlingGainOverride/0.02/");
adjusted_config = AdjustConfig(default_config); adjusted_config = AdjustConfig(default_config, field_trials);
ASSERT_NE( ASSERT_NE(
default_config.suppressor.high_bands_suppression.anti_howling_gain, default_config.suppressor.high_bands_suppression.anti_howling_gain,
@ -756,13 +761,14 @@ TEST(EchoCanceller3FieldTrials, Aec3SuppressorAntiHowlingGainOverride) {
// limit. // limit.
TEST(EchoCanceller3FieldTrials, Aec3EnforceLowActiveRenderLimit) { TEST(EchoCanceller3FieldTrials, Aec3EnforceLowActiveRenderLimit) {
EchoCanceller3Config default_config; EchoCanceller3Config default_config;
EchoCanceller3Config adjusted_config = AdjustConfig(default_config); EchoCanceller3Config adjusted_config =
AdjustConfig(default_config, ExplicitKeyValueConfig(""));
ASSERT_EQ(default_config.render_levels.active_render_limit, ASSERT_EQ(default_config.render_levels.active_render_limit,
adjusted_config.render_levels.active_render_limit); adjusted_config.render_levels.active_render_limit);
webrtc::test::ScopedFieldTrials field_trials( ExplicitKeyValueConfig field_trials(
"WebRTC-Aec3EnforceLowActiveRenderLimit/Enabled/"); "WebRTC-Aec3EnforceLowActiveRenderLimit/Enabled/");
adjusted_config = AdjustConfig(default_config); adjusted_config = AdjustConfig(default_config, field_trials);
ASSERT_NE(default_config.render_levels.active_render_limit, ASSERT_NE(default_config.render_levels.active_render_limit,
adjusted_config.render_levels.active_render_limit); adjusted_config.render_levels.active_render_limit);
@ -772,7 +778,7 @@ TEST(EchoCanceller3FieldTrials, Aec3EnforceLowActiveRenderLimit) {
// Testing the field trial-based override of the suppressor parameters for a // Testing the field trial-based override of the suppressor parameters for a
// joint passing of all parameters. // joint passing of all parameters.
TEST(EchoCanceller3FieldTrials, Aec3SuppressorTuningOverrideAllParams) { TEST(EchoCanceller3FieldTrials, Aec3SuppressorTuningOverrideAllParams) {
webrtc::test::ScopedFieldTrials field_trials( ExplicitKeyValueConfig field_trials(
"WebRTC-Aec3SuppressorTuningOverride/" "WebRTC-Aec3SuppressorTuningOverride/"
"nearend_tuning_mask_lf_enr_transparent:0.1,nearend_tuning_mask_lf_enr_" "nearend_tuning_mask_lf_enr_transparent:0.1,nearend_tuning_mask_lf_enr_"
"suppress:0.2,nearend_tuning_mask_hf_enr_transparent:0.3,nearend_tuning_" "suppress:0.2,nearend_tuning_mask_hf_enr_transparent:0.3,nearend_tuning_"
@ -787,7 +793,8 @@ TEST(EchoCanceller3FieldTrials, Aec3SuppressorTuningOverrideAllParams) {
"threshold:11/"); "threshold:11/");
EchoCanceller3Config default_config; EchoCanceller3Config default_config;
EchoCanceller3Config adjusted_config = AdjustConfig(default_config); EchoCanceller3Config adjusted_config =
AdjustConfig(default_config, field_trials);
ASSERT_NE(adjusted_config.suppressor.nearend_tuning.mask_lf.enr_transparent, ASSERT_NE(adjusted_config.suppressor.nearend_tuning.mask_lf.enr_transparent,
default_config.suppressor.nearend_tuning.mask_lf.enr_transparent); default_config.suppressor.nearend_tuning.mask_lf.enr_transparent);
@ -866,11 +873,12 @@ TEST(EchoCanceller3FieldTrials, Aec3SuppressorTuningOverrideAllParams) {
// Testing the field trial-based override of the suppressor parameters for // Testing the field trial-based override of the suppressor parameters for
// passing one parameter. // passing one parameter.
TEST(EchoCanceller3FieldTrials, Aec3SuppressorTuningOverrideOneParam) { TEST(EchoCanceller3FieldTrials, Aec3SuppressorTuningOverrideOneParam) {
webrtc::test::ScopedFieldTrials field_trials( ExplicitKeyValueConfig field_trials(
"WebRTC-Aec3SuppressorTuningOverride/nearend_tuning_max_inc_factor:0.5/"); "WebRTC-Aec3SuppressorTuningOverride/nearend_tuning_max_inc_factor:0.5/");
EchoCanceller3Config default_config; EchoCanceller3Config default_config;
EchoCanceller3Config adjusted_config = AdjustConfig(default_config); EchoCanceller3Config adjusted_config =
AdjustConfig(default_config, field_trials);
ASSERT_EQ(adjusted_config.suppressor.nearend_tuning.mask_lf.enr_transparent, ASSERT_EQ(adjusted_config.suppressor.nearend_tuning.mask_lf.enr_transparent,
default_config.suppressor.nearend_tuning.mask_lf.enr_transparent); default_config.suppressor.nearend_tuning.mask_lf.enr_transparent);
@ -916,10 +924,11 @@ TEST(EchoCanceller3FieldTrials, Aec3SuppressorTuningOverrideOneParam) {
// Testing the field trial-based that override the exponential decay parameters. // Testing the field trial-based that override the exponential decay parameters.
TEST(EchoCanceller3FieldTrials, Aec3UseNearendReverb) { TEST(EchoCanceller3FieldTrials, Aec3UseNearendReverb) {
webrtc::test::ScopedFieldTrials field_trials( ExplicitKeyValueConfig field_trials(
"WebRTC-Aec3UseNearendReverbLen/default_len:0.9,nearend_len:0.8/"); "WebRTC-Aec3UseNearendReverbLen/default_len:0.9,nearend_len:0.8/");
EchoCanceller3Config default_config; EchoCanceller3Config default_config;
EchoCanceller3Config adjusted_config = AdjustConfig(default_config); EchoCanceller3Config adjusted_config =
AdjustConfig(default_config, field_trials);
EXPECT_FLOAT_EQ(adjusted_config.ep_strength.default_len, 0.9); EXPECT_FLOAT_EQ(adjusted_config.ep_strength.default_len, 0.9);
EXPECT_FLOAT_EQ(adjusted_config.ep_strength.nearend_len, 0.8); EXPECT_FLOAT_EQ(adjusted_config.ep_strength.nearend_len, 0.8);
} }
@ -927,10 +936,11 @@ TEST(EchoCanceller3FieldTrials, Aec3UseNearendReverb) {
// Testing the field trial-based that overrides the maximum allowed ecess render // Testing the field trial-based that overrides the maximum allowed ecess render
// blocks in the render buffering. // blocks in the render buffering.
TEST(EchoCanceller3FieldTrials, Aec3BufferingMaxAllowedExcessRenderBlocks) { TEST(EchoCanceller3FieldTrials, Aec3BufferingMaxAllowedExcessRenderBlocks) {
webrtc::test::ScopedFieldTrials field_trials( ExplicitKeyValueConfig field_trials(
"WebRTC-Aec3BufferingMaxAllowedExcessRenderBlocksOverride/2/"); "WebRTC-Aec3BufferingMaxAllowedExcessRenderBlocksOverride/2/");
EchoCanceller3Config default_config; EchoCanceller3Config default_config;
EchoCanceller3Config adjusted_config = AdjustConfig(default_config); EchoCanceller3Config adjusted_config =
AdjustConfig(default_config, field_trials);
EXPECT_EQ(adjusted_config.buffering.max_allowed_excess_render_blocks, 2ul); EXPECT_EQ(adjusted_config.buffering.max_allowed_excess_render_blocks, 2ul);
} }
@ -957,7 +967,7 @@ TEST(EchoCanceller3, DetectionOfProperStereo) {
multichannel_config->filter.coarse_initial.length_blocks = multichannel_config->filter.coarse_initial.length_blocks =
kNumBlocksForSurroundConfig; kNumBlocksForSurroundConfig;
EchoCanceller3 aec3(mono_config, multichannel_config, EchoCanceller3 aec3(CreateEnvironment(), mono_config, multichannel_config,
/*sample_rate_hz=*/kSampleRateHz, /*sample_rate_hz=*/kSampleRateHz,
/*num_render_channels=*/kNumChannels, /*num_render_channels=*/kNumChannels,
/*num_capture_input_channels=*/kNumChannels); /*num_capture_input_channels=*/kNumChannels);
@ -1005,7 +1015,7 @@ TEST(EchoCanceller3, DetectionOfProperStereoUsingThreshold) {
multichannel_config->filter.coarse_initial.length_blocks = multichannel_config->filter.coarse_initial.length_blocks =
kNumBlocksForSurroundConfig; kNumBlocksForSurroundConfig;
EchoCanceller3 aec3(mono_config, multichannel_config, EchoCanceller3 aec3(CreateEnvironment(), mono_config, multichannel_config,
/*sample_rate_hz=*/kSampleRateHz, /*sample_rate_hz=*/kSampleRateHz,
/*num_render_channels=*/kNumChannels, /*num_render_channels=*/kNumChannels,
/*num_capture_input_channels=*/kNumChannels); /*num_capture_input_channels=*/kNumChannels);
@ -1052,7 +1062,7 @@ TEST(EchoCanceller3, DetectionOfProperStereoUsingHysteresis) {
surround_config->filter.coarse_initial.length_blocks = surround_config->filter.coarse_initial.length_blocks =
kNumBlocksForSurroundConfig; kNumBlocksForSurroundConfig;
EchoCanceller3 aec3(mono_config, surround_config, EchoCanceller3 aec3(CreateEnvironment(), mono_config, surround_config,
/*sample_rate_hz=*/kSampleRateHz, /*sample_rate_hz=*/kSampleRateHz,
/*num_render_channels=*/kNumChannels, /*num_render_channels=*/kNumChannels,
/*num_capture_input_channels=*/kNumChannels); /*num_capture_input_channels=*/kNumChannels);
@ -1100,6 +1110,7 @@ TEST(EchoCanceller3, StereoContentDetectionForMonoSignals) {
constexpr size_t kNumBlocksForMonoConfig = 1; constexpr size_t kNumBlocksForMonoConfig = 1;
constexpr size_t kNumBlocksForSurroundConfig = 2; constexpr size_t kNumBlocksForSurroundConfig = 2;
const Environment env = CreateEnvironment();
EchoCanceller3Config mono_config; EchoCanceller3Config mono_config;
std::optional<EchoCanceller3Config> multichannel_config; std::optional<EchoCanceller3Config> multichannel_config;
@ -1117,7 +1128,7 @@ TEST(EchoCanceller3, StereoContentDetectionForMonoSignals) {
/*output_rate=*/kSampleRateHz, /*output_rate=*/kSampleRateHz,
/*output_num_channels=*/1); /*output_num_channels=*/1);
EchoCanceller3 aec3(mono_config, multichannel_config, EchoCanceller3 aec3(env, mono_config, multichannel_config,
/*sample_rate_hz=*/kSampleRateHz, /*sample_rate_hz=*/kSampleRateHz,
/*num_render_channels=*/1, /*num_render_channels=*/1,
/*num_capture_input_channels=*/1); /*num_capture_input_channels=*/1);
@ -1148,7 +1159,7 @@ TEST(EchoCanceller3InputCheckDeathTest, WrongCaptureNumBandsCheckVerification) {
// call works. // call works.
TEST(EchoCanceller3InputCheckDeathTest, NullCaptureProcessingParameter) { TEST(EchoCanceller3InputCheckDeathTest, NullCaptureProcessingParameter) {
EXPECT_DEATH( EXPECT_DEATH(
EchoCanceller3(EchoCanceller3Config(), EchoCanceller3(CreateEnvironment(), EchoCanceller3Config(),
/*multichannel_config_=*/std::nullopt, 16000, 1, 1) /*multichannel_config_=*/std::nullopt, 16000, 1, 1)
.ProcessCapture(nullptr, false), .ProcessCapture(nullptr, false),
""); "");
@ -1160,7 +1171,7 @@ TEST(EchoCanceller3InputCheckDeathTest, NullCaptureProcessingParameter) {
TEST(EchoCanceller3InputCheckDeathTest, DISABLED_WrongSampleRate) { TEST(EchoCanceller3InputCheckDeathTest, DISABLED_WrongSampleRate) {
ApmDataDumper data_dumper(0); ApmDataDumper data_dumper(0);
EXPECT_DEATH( EXPECT_DEATH(
EchoCanceller3(EchoCanceller3Config(), EchoCanceller3(CreateEnvironment(), EchoCanceller3Config(),
/*multichannel_config_=*/std::nullopt, 8001, 1, 1), /*multichannel_config_=*/std::nullopt, 8001, 1, 1),
""); "");
} }

View File

@ -1898,7 +1898,7 @@ void AudioProcessingImpl::InitializeEchoController() {
multichannel_config = EchoCanceller3::CreateDefaultMultichannelConfig(); multichannel_config = EchoCanceller3::CreateDefaultMultichannelConfig();
} }
submodules_.echo_controller = std::make_unique<EchoCanceller3>( submodules_.echo_controller = std::make_unique<EchoCanceller3>(
config, multichannel_config, proc_sample_rate_hz(), env_, config, multichannel_config, proc_sample_rate_hz(),
num_reverse_channels(), num_proc_channels()); num_reverse_channels(), num_proc_channels());
} }

View File

@ -590,6 +590,7 @@ webrtc_fuzzer_test("aec3_fuzzer") {
deps = [ deps = [
":fuzz_data_helper", ":fuzz_data_helper",
"../../api/audio:audio_processing", "../../api/audio:audio_processing",
"../../api/environment:environment_factory",
"../../modules/audio_processing:audio_buffer", "../../modules/audio_processing:audio_buffer",
"../../modules/audio_processing/aec3", "../../modules/audio_processing/aec3",
] ]

View File

@ -11,6 +11,7 @@
#include <optional> #include <optional>
#include "api/audio/audio_processing.h" #include "api/audio/audio_processing.h"
#include "api/environment/environment_factory.h"
#include "modules/audio_processing/aec3/echo_canceller3.h" #include "modules/audio_processing/aec3/echo_canceller3.h"
#include "modules/audio_processing/audio_buffer.h" #include "modules/audio_processing/audio_buffer.h"
#include "test/fuzzers/fuzz_data_helper.h" #include "test/fuzzers/fuzz_data_helper.h"
@ -53,7 +54,7 @@ void FuzzOneInput(const uint8_t* data, size_t size) {
const size_t num_capture_channels = const size_t num_capture_channels =
1 + fuzz_data.ReadOrDefaultValue<uint8_t>(0) % (kMaxNumChannels - 1); 1 + fuzz_data.ReadOrDefaultValue<uint8_t>(0) % (kMaxNumChannels - 1);
EchoCanceller3 aec3(EchoCanceller3Config(), EchoCanceller3 aec3(CreateEnvironment(), EchoCanceller3Config(),
/*multichannel_config=*/std::nullopt, sample_rate_hz, /*multichannel_config=*/std::nullopt, sample_rate_hz,
num_render_channels, num_capture_channels); num_render_channels, num_capture_channels);