From c32935000840dbd8216bfa8e3564432d4c66d4bd Mon Sep 17 00:00:00 2001 From: Danil Chapovalov Date: Fri, 20 Dec 2024 13:53:27 +0100 Subject: [PATCH] Propagate field trials into EchoCanceller3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bug: webrtc:369904700 Change-Id: I698dd126f1627f84abe2633bde215c06aeef6299 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/372400 Commit-Queue: Danil Chapovalov Reviewed-by: Per Ã…hgren Cr-Commit-Position: refs/heads/main@{#43733} --- api/audio/BUILD.gn | 2 + api/audio/echo_canceller3_factory.cc | 7 +- api/audio/echo_canceller3_factory.h | 10 +- api/audio/echo_control.h | 15 +- modules/audio_processing/aec3/BUILD.gn | 5 + .../audio_processing/aec3/echo_canceller3.cc | 177 ++++++++++-------- .../audio_processing/aec3/echo_canceller3.h | 8 +- .../aec3/echo_canceller3_unittest.cc | 73 +++++--- .../audio_processing/audio_processing_impl.cc | 2 +- test/fuzzers/BUILD.gn | 1 + test/fuzzers/aec3_fuzzer.cc | 3 +- 11 files changed, 167 insertions(+), 136 deletions(-) diff --git a/api/audio/BUILD.gn b/api/audio/BUILD.gn index 60cc9c6ef7..1199ad8cf5 100644 --- a/api/audio/BUILD.gn +++ b/api/audio/BUILD.gn @@ -140,6 +140,8 @@ rtc_library("aec3_factory") { ":echo_control", "../../modules/audio_processing/aec3", "../../rtc_base/system:rtc_export", + "../environment", + "//third_party/abseil-cpp/absl/base:nullability", ] } diff --git a/api/audio/echo_canceller3_factory.cc b/api/audio/echo_canceller3_factory.cc index 9b1273d8be..ca463c07bc 100644 --- a/api/audio/echo_canceller3_factory.cc +++ b/api/audio/echo_canceller3_factory.cc @@ -12,8 +12,10 @@ #include #include +#include "absl/base/nullability.h" #include "api/audio/echo_canceller3_config.h" #include "api/audio/echo_control.h" +#include "api/environment/environment.h" #include "modules/audio_processing/aec3/echo_canceller3.h" namespace webrtc { @@ -23,12 +25,13 @@ EchoCanceller3Factory::EchoCanceller3Factory() {} EchoCanceller3Factory::EchoCanceller3Factory(const EchoCanceller3Config& config) : config_(config) {} -std::unique_ptr EchoCanceller3Factory::Create( +absl::Nonnull> EchoCanceller3Factory::Create( + const Environment& env, int sample_rate_hz, int num_render_channels, int num_capture_channels) { return std::make_unique( - config_, /*multichannel_config=*/std::nullopt, sample_rate_hz, + env, config_, /*multichannel_config=*/std::nullopt, sample_rate_hz, num_render_channels, num_capture_channels); } diff --git a/api/audio/echo_canceller3_factory.h b/api/audio/echo_canceller3_factory.h index 8b5380057b..1c27d40e01 100644 --- a/api/audio/echo_canceller3_factory.h +++ b/api/audio/echo_canceller3_factory.h @@ -13,8 +13,10 @@ #include +#include "absl/base/nullability.h" #include "api/audio/echo_canceller3_config.h" #include "api/audio/echo_control.h" +#include "api/environment/environment.h" #include "rtc_base/system/rtc_export.h" namespace webrtc { @@ -29,9 +31,11 @@ class RTC_EXPORT EchoCanceller3Factory : public EchoControlFactory { explicit EchoCanceller3Factory(const EchoCanceller3Config& config); // Creates an EchoCanceller3 with a specified channel count and sampling rate. - std::unique_ptr Create(int sample_rate_hz, - int num_render_channels, - int num_capture_channels) override; + absl::Nonnull> Create( + const Environment& env, + int sample_rate_hz, + int num_render_channels, + int num_capture_channels) override; private: const EchoCanceller3Config config_; diff --git a/api/audio/echo_control.h b/api/audio/echo_control.h index ddd5e902ac..3874d2b354 100644 --- a/api/audio/echo_control.h +++ b/api/audio/echo_control.h @@ -15,7 +15,6 @@ #include "absl/base/nullability.h" #include "api/environment/environment.h" -#include "rtc_base/checks.h" namespace webrtc { @@ -68,23 +67,11 @@ class EchoControlFactory { public: virtual ~EchoControlFactory() = default; - // TODO: bugs.webrtc.org/369904700 - Make pure virtual when implemented by - // all derived classes. virtual absl::Nonnull> Create( const Environment& env, int sample_rate_hz, int num_render_channels, - int num_capture_channels) { - 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 Create(int sample_rate_hz, - int num_render_channels, - int num_capture_channels) { - RTC_CHECK_NOTREACHED(); - } + int num_capture_channels) = 0; }; } // namespace webrtc diff --git a/modules/audio_processing/aec3/BUILD.gn b/modules/audio_processing/aec3/BUILD.gn index 12a32b8929..98f01b930a 100644 --- a/modules/audio_processing/aec3/BUILD.gn +++ b/modules/audio_processing/aec3/BUILD.gn @@ -141,8 +141,10 @@ rtc_library("aec3") { "..:audio_buffer", "..:high_pass_filter", "../../../api:array_view", + "../../../api:field_trials_view", "../../../api/audio:aec3_config", "../../../api/audio:echo_control", + "../../../api/environment", "../../../common_audio:common_audio_c", "../../../rtc_base:checks", "../../../rtc_base:logging", @@ -313,6 +315,8 @@ if (rtc_include_tests) { "..:high_pass_filter", "../../../api:array_view", "../../../api/audio:aec3_config", + "../../../api/environment", + "../../../api/environment:environment_factory", "../../../rtc_base:checks", "../../../rtc_base:macromagic", "../../../rtc_base:random", @@ -321,6 +325,7 @@ if (rtc_include_tests) { "../../../rtc_base/system:arch", "../../../system_wrappers", "../../../system_wrappers:metrics", + "../../../test:explicit_key_value_config", "../../../test:field_trial", "../../../test:test_support", "../utility:cascaded_biquad_filter", diff --git a/modules/audio_processing/aec3/echo_canceller3.cc b/modules/audio_processing/aec3/echo_canceller3.cc index 00010ceaea..55a4db79a3 100644 --- a/modules/audio_processing/aec3/echo_canceller3.cc +++ b/modules/audio_processing/aec3/echo_canceller3.cc @@ -13,12 +13,13 @@ #include #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/high_pass_filter.h" #include "modules/audio_processing/logging/apm_data_dumper.h" #include "rtc_base/experiments/field_trial_parser.h" #include "rtc_base/logging.h" -#include "system_wrappers/include/field_trial.h" namespace webrtc { @@ -38,11 +39,12 @@ bool DetectSaturation(rtc::ArrayView y) { // 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 // 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 max, 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 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 max, 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 field_trial_param(/*key=*/"", *value_to_update); @@ -256,61 +259,62 @@ void CopyBufferIntoFrame(const AudioBuffer& buffer, } // namespace // 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; - if (field_trial::IsEnabled("WebRTC-Aec3StereoContentDetectionKillSwitch")) { + if (field_trials.IsEnabled("WebRTC-Aec3StereoContentDetectionKillSwitch")) { 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 .anti_howling_activation_threshold = 25.f; 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; } - if (field_trial::IsEnabled("WebRTC-Aec3UseZeroInitialStateDuration")) { + if (field_trials.IsEnabled("WebRTC-Aec3UseZeroInitialStateDuration")) { adjusted_cfg.filter.initial_state_seconds = 0.f; - } else if (field_trial::IsEnabled( + } else if (field_trials.IsEnabled( "WebRTC-Aec3UseDot1SecondsInitialStateDuration")) { adjusted_cfg.filter.initial_state_seconds = .1f; - } else if (field_trial::IsEnabled( + } else if (field_trials.IsEnabled( "WebRTC-Aec3UseDot2SecondsInitialStateDuration")) { adjusted_cfg.filter.initial_state_seconds = .2f; - } else if (field_trial::IsEnabled( + } else if (field_trials.IsEnabled( "WebRTC-Aec3UseDot3SecondsInitialStateDuration")) { adjusted_cfg.filter.initial_state_seconds = .3f; - } else if (field_trial::IsEnabled( + } else if (field_trials.IsEnabled( "WebRTC-Aec3UseDot6SecondsInitialStateDuration")) { adjusted_cfg.filter.initial_state_seconds = .6f; - } else if (field_trial::IsEnabled( + } else if (field_trials.IsEnabled( "WebRTC-Aec3UseDot9SecondsInitialStateDuration")) { adjusted_cfg.filter.initial_state_seconds = .9f; - } else if (field_trial::IsEnabled( + } else if (field_trials.IsEnabled( "WebRTC-Aec3Use1Dot2SecondsInitialStateDuration")) { adjusted_cfg.filter.initial_state_seconds = 1.2f; - } else if (field_trial::IsEnabled( + } else if (field_trials.IsEnabled( "WebRTC-Aec3Use1Dot6SecondsInitialStateDuration")) { adjusted_cfg.filter.initial_state_seconds = 1.6f; - } else if (field_trial::IsEnabled( + } else if (field_trials.IsEnabled( "WebRTC-Aec3Use2Dot0SecondsInitialStateDuration")) { 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; } - if (field_trial::IsEnabled("WebRTC-Aec3EchoSaturationDetectionKillSwitch")) { + if (field_trials.IsEnabled("WebRTC-Aec3EchoSaturationDetectionKillSwitch")) { adjusted_cfg.ep_strength.echo_can_saturate = false; } const std::string use_nearend_reverb_len_tunings = - field_trial::FindFullName("WebRTC-Aec3UseNearendReverbLen"); + field_trials.Lookup("WebRTC-Aec3UseNearendReverbLen"); FieldTrialParameter nearend_reverb_default_len( "default_len", adjusted_cfg.ep_strength.default_len); FieldTrialParameter nearend_reverb_nearend_len( @@ -328,138 +332,138 @@ EchoCanceller3Config AdjustConfig(const EchoCanceller3Config& config) { static_cast(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; } - if (field_trial::IsDisabled("WebRTC-Aec3ConservativeTailFreqResponse")) { + if (field_trials.IsDisabled("WebRTC-Aec3ConservativeTailFreqResponse")) { 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. 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; } - if (field_trial::IsEnabled("WebRTC-Aec3ClampInstQualityToOneKillSwitch")) { + if (field_trials.IsEnabled("WebRTC-Aec3ClampInstQualityToOneKillSwitch")) { 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; } - if (field_trial::IsEnabled( + if (field_trials.IsEnabled( "WebRTC-Aec3EnforceRenderDelayEstimationDownmixing")) { adjusted_cfg.delay.render_alignment_mixing.downmix = true; adjusted_cfg.delay.render_alignment_mixing.adaptive_selection = false; } - if (field_trial::IsEnabled( + if (field_trials.IsEnabled( "WebRTC-Aec3EnforceCaptureDelayEstimationDownmixing")) { adjusted_cfg.delay.capture_alignment_mixing.downmix = true; adjusted_cfg.delay.capture_alignment_mixing.adaptive_selection = false; } - if (field_trial::IsEnabled( + if (field_trials.IsEnabled( "WebRTC-Aec3EnforceCaptureDelayEstimationLeftRightPrioritization")) { adjusted_cfg.delay.capture_alignment_mixing.prefer_first_two_channels = true; } - if (field_trial::IsEnabled( + if (field_trials.IsEnabled( "WebRTC-" "Aec3RenderDelayEstimationLeftRightPrioritizationKillSwitch")) { adjusted_cfg.delay.capture_alignment_mixing.prefer_first_two_channels = false; } - if (field_trial::IsEnabled("WebRTC-Aec3SensitiveDominantNearendActivation")) { + if (field_trials.IsEnabled("WebRTC-Aec3SensitiveDominantNearendActivation")) { adjusted_cfg.suppressor.dominant_nearend_detection.enr_threshold = 0.5f; - } else if (field_trial::IsEnabled( + } else if (field_trials.IsEnabled( "WebRTC-Aec3VerySensitiveDominantNearendActivation")) { 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; } - if (field_trial::IsEnabled( + if (field_trials.IsEnabled( "WebRTC-Aec3EnforceMoreTransparentNormalSuppressorTuning")) { adjusted_cfg.suppressor.normal_tuning.mask_lf.enr_transparent = 0.4f; adjusted_cfg.suppressor.normal_tuning.mask_lf.enr_suppress = 0.5f; } - if (field_trial::IsEnabled( + if (field_trials.IsEnabled( "WebRTC-Aec3EnforceMoreTransparentNearendSuppressorTuning")) { adjusted_cfg.suppressor.nearend_tuning.mask_lf.enr_transparent = 1.29f; adjusted_cfg.suppressor.nearend_tuning.mask_lf.enr_suppress = 1.3f; } - if (field_trial::IsEnabled( + if (field_trials.IsEnabled( "WebRTC-Aec3EnforceMoreTransparentNormalSuppressorHfTuning")) { adjusted_cfg.suppressor.normal_tuning.mask_hf.enr_transparent = 0.3f; adjusted_cfg.suppressor.normal_tuning.mask_hf.enr_suppress = 0.4f; } - if (field_trial::IsEnabled( + if (field_trials.IsEnabled( "WebRTC-Aec3EnforceMoreTransparentNearendSuppressorHfTuning")) { adjusted_cfg.suppressor.nearend_tuning.mask_hf.enr_transparent = 1.09f; adjusted_cfg.suppressor.nearend_tuning.mask_hf.enr_suppress = 1.1f; } - if (field_trial::IsEnabled( + if (field_trials.IsEnabled( "WebRTC-Aec3EnforceRapidlyAdjustingNormalSuppressorTunings")) { adjusted_cfg.suppressor.normal_tuning.max_inc_factor = 2.5f; } - if (field_trial::IsEnabled( + if (field_trials.IsEnabled( "WebRTC-Aec3EnforceRapidlyAdjustingNearendSuppressorTunings")) { adjusted_cfg.suppressor.nearend_tuning.max_inc_factor = 2.5f; } - if (field_trial::IsEnabled( + if (field_trials.IsEnabled( "WebRTC-Aec3EnforceSlowlyAdjustingNormalSuppressorTunings")) { adjusted_cfg.suppressor.normal_tuning.max_dec_factor_lf = .2f; } - if (field_trial::IsEnabled( + if (field_trials.IsEnabled( "WebRTC-Aec3EnforceSlowlyAdjustingNearendSuppressorTunings")) { 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; } - if (field_trial::IsEnabled("WebRTC-Aec3EnforceStationarityProperties")) { + if (field_trials.IsEnabled("WebRTC-Aec3EnforceStationarityProperties")) { adjusted_cfg.echo_audibility.use_stationarity_properties = true; } - if (field_trial::IsEnabled( + if (field_trials.IsEnabled( "WebRTC-Aec3EnforceStationarityPropertiesAtInit")) { 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; - } else if (field_trial::IsEnabled( + } else if (field_trials.IsEnabled( "WebRTC-Aec3EnforceVeryLowActiveRenderLimit")) { 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; } // Field-trial based override for the whole suppressor tuning. const std::string suppressor_tuning_override_trial_name = - field_trial::FindFullName("WebRTC-Aec3SuppressorTuningOverride"); + field_trials.Lookup("WebRTC-Aec3SuppressorTuningOverride"); FieldTrialParameter 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. RetrieveFieldTrialValue( - "WebRTC-Aec3SuppressorNearendLfMaskTransparentOverride", 0.f, 10.f, + field_trials, "WebRTC-Aec3SuppressorNearendLfMaskTransparentOverride", + 0.f, 10.f, &adjusted_cfg.suppressor.nearend_tuning.mask_lf.enr_transparent); RetrieveFieldTrialValue( - "WebRTC-Aec3SuppressorNearendLfMaskSuppressOverride", 0.f, 10.f, - &adjusted_cfg.suppressor.nearend_tuning.mask_lf.enr_suppress); + field_trials, "WebRTC-Aec3SuppressorNearendLfMaskSuppressOverride", 0.f, + 10.f, &adjusted_cfg.suppressor.nearend_tuning.mask_lf.enr_suppress); RetrieveFieldTrialValue( - "WebRTC-Aec3SuppressorNearendHfMaskTransparentOverride", 0.f, 10.f, + field_trials, "WebRTC-Aec3SuppressorNearendHfMaskTransparentOverride", + 0.f, 10.f, &adjusted_cfg.suppressor.nearend_tuning.mask_hf.enr_transparent); RetrieveFieldTrialValue( - "WebRTC-Aec3SuppressorNearendHfMaskSuppressOverride", 0.f, 10.f, - &adjusted_cfg.suppressor.nearend_tuning.mask_hf.enr_suppress); + field_trials, "WebRTC-Aec3SuppressorNearendHfMaskSuppressOverride", 0.f, + 10.f, &adjusted_cfg.suppressor.nearend_tuning.mask_hf.enr_suppress); RetrieveFieldTrialValue( - "WebRTC-Aec3SuppressorNearendMaxIncFactorOverride", 0.f, 10.f, - &adjusted_cfg.suppressor.nearend_tuning.max_inc_factor); + field_trials, "WebRTC-Aec3SuppressorNearendMaxIncFactorOverride", 0.f, + 10.f, &adjusted_cfg.suppressor.nearend_tuning.max_inc_factor); RetrieveFieldTrialValue( - "WebRTC-Aec3SuppressorNearendMaxDecFactorLfOverride", 0.f, 10.f, - &adjusted_cfg.suppressor.nearend_tuning.max_dec_factor_lf); + field_trials, "WebRTC-Aec3SuppressorNearendMaxDecFactorLfOverride", 0.f, + 10.f, &adjusted_cfg.suppressor.nearend_tuning.max_dec_factor_lf); RetrieveFieldTrialValue( - "WebRTC-Aec3SuppressorNormalLfMaskTransparentOverride", 0.f, 10.f, - &adjusted_cfg.suppressor.normal_tuning.mask_lf.enr_transparent); + field_trials, "WebRTC-Aec3SuppressorNormalLfMaskTransparentOverride", 0.f, + 10.f, &adjusted_cfg.suppressor.normal_tuning.mask_lf.enr_transparent); RetrieveFieldTrialValue( - "WebRTC-Aec3SuppressorNormalLfMaskSuppressOverride", 0.f, 10.f, - &adjusted_cfg.suppressor.normal_tuning.mask_lf.enr_suppress); + field_trials, "WebRTC-Aec3SuppressorNormalLfMaskSuppressOverride", 0.f, + 10.f, &adjusted_cfg.suppressor.normal_tuning.mask_lf.enr_suppress); RetrieveFieldTrialValue( - "WebRTC-Aec3SuppressorNormalHfMaskTransparentOverride", 0.f, 10.f, - &adjusted_cfg.suppressor.normal_tuning.mask_hf.enr_transparent); + field_trials, "WebRTC-Aec3SuppressorNormalHfMaskTransparentOverride", 0.f, + 10.f, &adjusted_cfg.suppressor.normal_tuning.mask_hf.enr_transparent); RetrieveFieldTrialValue( - "WebRTC-Aec3SuppressorNormalHfMaskSuppressOverride", 0.f, 10.f, - &adjusted_cfg.suppressor.normal_tuning.mask_hf.enr_suppress); + field_trials, "WebRTC-Aec3SuppressorNormalHfMaskSuppressOverride", 0.f, + 10.f, &adjusted_cfg.suppressor.normal_tuning.mask_hf.enr_suppress); RetrieveFieldTrialValue( - "WebRTC-Aec3SuppressorNormalMaxIncFactorOverride", 0.f, 10.f, - &adjusted_cfg.suppressor.normal_tuning.max_inc_factor); + field_trials, "WebRTC-Aec3SuppressorNormalMaxIncFactorOverride", 0.f, + 10.f, &adjusted_cfg.suppressor.normal_tuning.max_inc_factor); RetrieveFieldTrialValue( - "WebRTC-Aec3SuppressorNormalMaxDecFactorLfOverride", 0.f, 10.f, - &adjusted_cfg.suppressor.normal_tuning.max_dec_factor_lf); + field_trials, "WebRTC-Aec3SuppressorNormalMaxDecFactorLfOverride", 0.f, + 10.f, &adjusted_cfg.suppressor.normal_tuning.max_dec_factor_lf); RetrieveFieldTrialValue( - "WebRTC-Aec3SuppressorDominantNearendEnrThresholdOverride", 0.f, 100.f, + field_trials, "WebRTC-Aec3SuppressorDominantNearendEnrThresholdOverride", + 0.f, 100.f, &adjusted_cfg.suppressor.dominant_nearend_detection.enr_threshold); RetrieveFieldTrialValue( + field_trials, "WebRTC-Aec3SuppressorDominantNearendEnrExitThresholdOverride", 0.f, 100.f, &adjusted_cfg.suppressor.dominant_nearend_detection.enr_exit_threshold); RetrieveFieldTrialValue( - "WebRTC-Aec3SuppressorDominantNearendSnrThresholdOverride", 0.f, 100.f, + field_trials, "WebRTC-Aec3SuppressorDominantNearendSnrThresholdOverride", + 0.f, 100.f, &adjusted_cfg.suppressor.dominant_nearend_detection.snr_threshold); RetrieveFieldTrialValue( - "WebRTC-Aec3SuppressorDominantNearendHoldDurationOverride", 0, 1000, + field_trials, "WebRTC-Aec3SuppressorDominantNearendHoldDurationOverride", + 0, 1000, &adjusted_cfg.suppressor.dominant_nearend_detection.hold_duration); RetrieveFieldTrialValue( + field_trials, "WebRTC-Aec3SuppressorDominantNearendTriggerThresholdOverride", 0, 1000, &adjusted_cfg.suppressor.dominant_nearend_detection.trigger_threshold); RetrieveFieldTrialValue( - "WebRTC-Aec3SuppressorAntiHowlingGainOverride", 0.f, 10.f, + field_trials, "WebRTC-Aec3SuppressorAntiHowlingGainOverride", 0.f, 10.f, &adjusted_cfg.suppressor.high_bands_suppression.anti_howling_gain); // 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); RetrieveFieldTrialValue( - "WebRTC-Aec3DelayEstimateSmoothingDelayFoundOverride", 0.f, 1.f, - &adjusted_cfg.delay.delay_estimate_smoothing_delay_found); + field_trials, "WebRTC-Aec3DelayEstimateSmoothingDelayFoundOverride", 0.f, + 1.f, &adjusted_cfg.delay.delay_estimate_smoothing_delay_found); int max_allowed_excess_render_blocks_override = adjusted_cfg.buffering.max_allowed_excess_render_blocks; RetrieveFieldTrialValue( - "WebRTC-Aec3BufferingMaxAllowedExcessRenderBlocksOverride", 0, 20, - &max_allowed_excess_render_blocks_override); + field_trials, "WebRTC-Aec3BufferingMaxAllowedExcessRenderBlocksOverride", + 0, 20, &max_allowed_excess_render_blocks_override); adjusted_cfg.buffering.max_allowed_excess_render_blocks = max_allowed_excess_render_blocks_override; return adjusted_cfg; @@ -717,18 +729,19 @@ void EchoCanceller3::RenderWriter::Insert(const AudioBuffer& input) { std::atomic EchoCanceller3::instance_count_(0); EchoCanceller3::EchoCanceller3( + const Environment& env, const EchoCanceller3Config& config, const std::optional& multichannel_config, int sample_rate_hz, size_t num_render_channels, size_t num_capture_channels) : 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), num_bands_(NumBandsForRate(sample_rate_hz_)), num_render_input_channels_(num_render_channels), num_capture_channels_(num_capture_channels), - config_selector_(AdjustConfig(config), + config_selector_(config_, multichannel_config, num_render_input_channels_), multichannel_content_detector_( diff --git a/modules/audio_processing/aec3/echo_canceller3.h b/modules/audio_processing/aec3/echo_canceller3.h index b05b3d96a0..8831d71499 100644 --- a/modules/audio_processing/aec3/echo_canceller3.h +++ b/modules/audio_processing/aec3/echo_canceller3.h @@ -21,6 +21,8 @@ #include "api/array_view.h" #include "api/audio/echo_canceller3_config.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/block_delay_buffer.h" #include "modules/audio_processing/aec3/block_framer.h" @@ -40,7 +42,8 @@ namespace webrtc { // Method for adjusting config parameter dependencies. // Only to be used externally to AEC3 for testing purposes. // 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 // queue. @@ -88,7 +91,8 @@ class Aec3RenderQueueItemVerifier { // AnalyzeRender call which can be called concurrently with the other methods. class EchoCanceller3 : public EchoControl { public: - EchoCanceller3(const EchoCanceller3Config& config, + EchoCanceller3(const Environment& env, + const EchoCanceller3Config& config, const std::optional& multichannel_config, int sample_rate_hz, size_t num_render_channels, diff --git a/modules/audio_processing/aec3/echo_canceller3_unittest.cc b/modules/audio_processing/aec3/echo_canceller3_unittest.cc index 2da0f62592..29a2962604 100644 --- a/modules/audio_processing/aec3/echo_canceller3_unittest.cc +++ b/modules/audio_processing/aec3/echo_canceller3_unittest.cc @@ -16,6 +16,8 @@ #include #include +#include "api/environment/environment.h" +#include "api/environment/environment_factory.h" #include "modules/audio_processing/aec3/aec3_common.h" #include "modules/audio_processing/aec3/block_processor.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/utility/cascaded_biquad_filter.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/gtest.h" namespace webrtc { namespace { +using test::ExplicitKeyValueConfig; using ::testing::_; using ::testing::StrictMock; @@ -240,7 +243,7 @@ class EchoCanceller3Tester { // and that the processor data is properly passed to the EchoCanceller3 // output. void RunCaptureTransportVerificationTest() { - EchoCanceller3 aec3(EchoCanceller3Config(), + EchoCanceller3 aec3(CreateEnvironment(), EchoCanceller3Config(), /*multichannel_config=*/std::nullopt, sample_rate_hz_, 1, 1); aec3.SetBlockProcessorForTesting( @@ -266,7 +269,7 @@ class EchoCanceller3Tester { // Test method for testing that the render data is properly received by the // block processor. void RunRenderTransportVerificationTest() { - EchoCanceller3 aec3(EchoCanceller3Config(), + EchoCanceller3 aec3(CreateEnvironment(), EchoCanceller3Config(), /*multichannel_config=*/std::nullopt, sample_rate_hz_, 1, 1); aec3.SetBlockProcessorForTesting( @@ -337,7 +340,7 @@ class EchoCanceller3Tester { break; } - EchoCanceller3 aec3(EchoCanceller3Config(), + EchoCanceller3 aec3(CreateEnvironment(), EchoCanceller3Config(), /*multichannel_config=*/std::nullopt, sample_rate_hz_, 1, 1); aec3.SetBlockProcessorForTesting(std::move(block_processor_mock)); @@ -419,7 +422,7 @@ class EchoCanceller3Tester { } break; } - EchoCanceller3 aec3(EchoCanceller3Config(), + EchoCanceller3 aec3(CreateEnvironment(), EchoCanceller3Config(), /*multichannel_config=*/std::nullopt, sample_rate_hz_, 1, 1); aec3.SetBlockProcessorForTesting(std::move(block_processor_mock)); @@ -507,7 +510,7 @@ class EchoCanceller3Tester { } break; } - EchoCanceller3 aec3(EchoCanceller3Config(), + EchoCanceller3 aec3(CreateEnvironment(), EchoCanceller3Config(), /*multichannel_config=*/std::nullopt, sample_rate_hz_, 1, 1); aec3.SetBlockProcessorForTesting(std::move(block_processor_mock)); @@ -548,8 +551,9 @@ class EchoCanceller3Tester { // capture and render API calls. void RunRenderSwapQueueVerificationTest() { const EchoCanceller3Config config; - EchoCanceller3 aec3(config, /*multichannel_config=*/std::nullopt, - sample_rate_hz_, 1, 1); + EchoCanceller3 aec3(CreateEnvironment(), config, + /*multichannel_config=*/std::nullopt, sample_rate_hz_, + 1, 1); aec3.SetBlockProcessorForTesting( std::make_unique(num_bands_)); @@ -597,7 +601,7 @@ class EchoCanceller3Tester { // This test verifies that a buffer overrun in the render swapqueue is // properly reported. void RunRenderPipelineSwapQueueOverrunReturnValueTest() { - EchoCanceller3 aec3(EchoCanceller3Config(), + EchoCanceller3 aec3(CreateEnvironment(), EchoCanceller3Config(), /*multichannel_config=*/std::nullopt, sample_rate_hz_, 1, 1); @@ -624,7 +628,7 @@ class EchoCanceller3Tester { // 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. const int aec3_sample_rate_hz = sample_rate_hz_ == 48000 ? 32000 : 48000; - EchoCanceller3 aec3(EchoCanceller3Config(), + EchoCanceller3 aec3(CreateEnvironment(), EchoCanceller3Config(), /*multichannel_config=*/std::nullopt, aec3_sample_rate_hz, 1, 1); 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 // way that the number of bands for the rates are different. const int aec3_sample_rate_hz = sample_rate_hz_ == 48000 ? 32000 : 48000; - EchoCanceller3 aec3(EchoCanceller3Config(), + EchoCanceller3 aec3(CreateEnvironment(), EchoCanceller3Config(), /*multichannel_config=*/std::nullopt, aec3_sample_rate_hz, 1, 1); PopulateInputFrame(frame_length_, num_bands_, 0, @@ -735,14 +739,15 @@ TEST(EchoCanceller3Messaging, EchoLeakage) { // anti-howling gain. TEST(EchoCanceller3FieldTrials, Aec3SuppressorAntiHowlingGainOverride) { EchoCanceller3Config default_config; - EchoCanceller3Config adjusted_config = AdjustConfig(default_config); + EchoCanceller3Config adjusted_config = + AdjustConfig(default_config, ExplicitKeyValueConfig("")); ASSERT_EQ( default_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/"); - adjusted_config = AdjustConfig(default_config); + adjusted_config = AdjustConfig(default_config, field_trials); ASSERT_NE( default_config.suppressor.high_bands_suppression.anti_howling_gain, @@ -756,13 +761,14 @@ TEST(EchoCanceller3FieldTrials, Aec3SuppressorAntiHowlingGainOverride) { // limit. TEST(EchoCanceller3FieldTrials, Aec3EnforceLowActiveRenderLimit) { 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, adjusted_config.render_levels.active_render_limit); - webrtc::test::ScopedFieldTrials field_trials( + ExplicitKeyValueConfig field_trials( "WebRTC-Aec3EnforceLowActiveRenderLimit/Enabled/"); - adjusted_config = AdjustConfig(default_config); + adjusted_config = AdjustConfig(default_config, field_trials); ASSERT_NE(default_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 // joint passing of all parameters. TEST(EchoCanceller3FieldTrials, Aec3SuppressorTuningOverrideAllParams) { - webrtc::test::ScopedFieldTrials field_trials( + ExplicitKeyValueConfig field_trials( "WebRTC-Aec3SuppressorTuningOverride/" "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_" @@ -787,7 +793,8 @@ TEST(EchoCanceller3FieldTrials, Aec3SuppressorTuningOverrideAllParams) { "threshold:11/"); 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, 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 // passing one parameter. TEST(EchoCanceller3FieldTrials, Aec3SuppressorTuningOverrideOneParam) { - webrtc::test::ScopedFieldTrials field_trials( + ExplicitKeyValueConfig field_trials( "WebRTC-Aec3SuppressorTuningOverride/nearend_tuning_max_inc_factor:0.5/"); 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, 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. TEST(EchoCanceller3FieldTrials, Aec3UseNearendReverb) { - webrtc::test::ScopedFieldTrials field_trials( + ExplicitKeyValueConfig field_trials( "WebRTC-Aec3UseNearendReverbLen/default_len:0.9,nearend_len:0.8/"); 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.nearend_len, 0.8); } @@ -927,10 +936,11 @@ TEST(EchoCanceller3FieldTrials, Aec3UseNearendReverb) { // Testing the field trial-based that overrides the maximum allowed ecess render // blocks in the render buffering. TEST(EchoCanceller3FieldTrials, Aec3BufferingMaxAllowedExcessRenderBlocks) { - webrtc::test::ScopedFieldTrials field_trials( + ExplicitKeyValueConfig field_trials( "WebRTC-Aec3BufferingMaxAllowedExcessRenderBlocksOverride/2/"); 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); } @@ -957,7 +967,7 @@ TEST(EchoCanceller3, DetectionOfProperStereo) { multichannel_config->filter.coarse_initial.length_blocks = kNumBlocksForSurroundConfig; - EchoCanceller3 aec3(mono_config, multichannel_config, + EchoCanceller3 aec3(CreateEnvironment(), mono_config, multichannel_config, /*sample_rate_hz=*/kSampleRateHz, /*num_render_channels=*/kNumChannels, /*num_capture_input_channels=*/kNumChannels); @@ -1005,7 +1015,7 @@ TEST(EchoCanceller3, DetectionOfProperStereoUsingThreshold) { multichannel_config->filter.coarse_initial.length_blocks = kNumBlocksForSurroundConfig; - EchoCanceller3 aec3(mono_config, multichannel_config, + EchoCanceller3 aec3(CreateEnvironment(), mono_config, multichannel_config, /*sample_rate_hz=*/kSampleRateHz, /*num_render_channels=*/kNumChannels, /*num_capture_input_channels=*/kNumChannels); @@ -1052,7 +1062,7 @@ TEST(EchoCanceller3, DetectionOfProperStereoUsingHysteresis) { surround_config->filter.coarse_initial.length_blocks = kNumBlocksForSurroundConfig; - EchoCanceller3 aec3(mono_config, surround_config, + EchoCanceller3 aec3(CreateEnvironment(), mono_config, surround_config, /*sample_rate_hz=*/kSampleRateHz, /*num_render_channels=*/kNumChannels, /*num_capture_input_channels=*/kNumChannels); @@ -1100,6 +1110,7 @@ TEST(EchoCanceller3, StereoContentDetectionForMonoSignals) { constexpr size_t kNumBlocksForMonoConfig = 1; constexpr size_t kNumBlocksForSurroundConfig = 2; + const Environment env = CreateEnvironment(); EchoCanceller3Config mono_config; std::optional multichannel_config; @@ -1117,7 +1128,7 @@ TEST(EchoCanceller3, StereoContentDetectionForMonoSignals) { /*output_rate=*/kSampleRateHz, /*output_num_channels=*/1); - EchoCanceller3 aec3(mono_config, multichannel_config, + EchoCanceller3 aec3(env, mono_config, multichannel_config, /*sample_rate_hz=*/kSampleRateHz, /*num_render_channels=*/1, /*num_capture_input_channels=*/1); @@ -1148,7 +1159,7 @@ TEST(EchoCanceller3InputCheckDeathTest, WrongCaptureNumBandsCheckVerification) { // call works. TEST(EchoCanceller3InputCheckDeathTest, NullCaptureProcessingParameter) { EXPECT_DEATH( - EchoCanceller3(EchoCanceller3Config(), + EchoCanceller3(CreateEnvironment(), EchoCanceller3Config(), /*multichannel_config_=*/std::nullopt, 16000, 1, 1) .ProcessCapture(nullptr, false), ""); @@ -1160,7 +1171,7 @@ TEST(EchoCanceller3InputCheckDeathTest, NullCaptureProcessingParameter) { TEST(EchoCanceller3InputCheckDeathTest, DISABLED_WrongSampleRate) { ApmDataDumper data_dumper(0); EXPECT_DEATH( - EchoCanceller3(EchoCanceller3Config(), + EchoCanceller3(CreateEnvironment(), EchoCanceller3Config(), /*multichannel_config_=*/std::nullopt, 8001, 1, 1), ""); } diff --git a/modules/audio_processing/audio_processing_impl.cc b/modules/audio_processing/audio_processing_impl.cc index 45b1c8299c..db2a60ab96 100644 --- a/modules/audio_processing/audio_processing_impl.cc +++ b/modules/audio_processing/audio_processing_impl.cc @@ -1898,7 +1898,7 @@ void AudioProcessingImpl::InitializeEchoController() { multichannel_config = EchoCanceller3::CreateDefaultMultichannelConfig(); } submodules_.echo_controller = std::make_unique( - config, multichannel_config, proc_sample_rate_hz(), + env_, config, multichannel_config, proc_sample_rate_hz(), num_reverse_channels(), num_proc_channels()); } diff --git a/test/fuzzers/BUILD.gn b/test/fuzzers/BUILD.gn index c1f6792ed4..b7c7fc621d 100644 --- a/test/fuzzers/BUILD.gn +++ b/test/fuzzers/BUILD.gn @@ -590,6 +590,7 @@ webrtc_fuzzer_test("aec3_fuzzer") { deps = [ ":fuzz_data_helper", "../../api/audio:audio_processing", + "../../api/environment:environment_factory", "../../modules/audio_processing:audio_buffer", "../../modules/audio_processing/aec3", ] diff --git a/test/fuzzers/aec3_fuzzer.cc b/test/fuzzers/aec3_fuzzer.cc index 71a316db31..dc9e171965 100644 --- a/test/fuzzers/aec3_fuzzer.cc +++ b/test/fuzzers/aec3_fuzzer.cc @@ -11,6 +11,7 @@ #include #include "api/audio/audio_processing.h" +#include "api/environment/environment_factory.h" #include "modules/audio_processing/aec3/echo_canceller3.h" #include "modules/audio_processing/audio_buffer.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 = 1 + fuzz_data.ReadOrDefaultValue(0) % (kMaxNumChannels - 1); - EchoCanceller3 aec3(EchoCanceller3Config(), + EchoCanceller3 aec3(CreateEnvironment(), EchoCanceller3Config(), /*multichannel_config=*/std::nullopt, sample_rate_hz, num_render_channels, num_capture_channels);