From 352f38c7a8590e94115a90401b6538be04271e0c Mon Sep 17 00:00:00 2001 From: Alessio Bazzica Date: Wed, 7 Dec 2022 16:13:35 +0100 Subject: [PATCH] APM: add field trial to disable `TransientSuppressor` Regardless of the APM config, the transient suppressor (TS) submodule won't be created if the `WebRTC-ApmTransientSuppressorKillSwitch` field trial, disabled by default, is enabled. Bug: webrtc:13663 Change-Id: Ic1ef9aa57c728296d671d4ef253630c581a86610 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/286382 Reviewed-by: Hanna Silen Commit-Queue: Alessio Bazzica Cr-Commit-Position: refs/heads/main@{#38839} --- .../audio_processing/audio_processing_impl.cc | 98 +++++++++++-------- .../audio_processing/audio_processing_impl.h | 11 ++- .../audio_processing_impl_unittest.cc | 49 ++++++++++ 3 files changed, 114 insertions(+), 44 deletions(-) diff --git a/modules/audio_processing/audio_processing_impl.cc b/modules/audio_processing/audio_processing_impl.cc index 2cb48588d8..972466621a 100644 --- a/modules/audio_processing/audio_processing_impl.cc +++ b/modules/audio_processing/audio_processing_impl.cc @@ -394,51 +394,65 @@ GetInputVolumeControllerConfigOverride() { }; } -// Switches all gain control to AGC2 if experimenting with input volume -// controller. -const AudioProcessing::Config AdjustConfig( +// If `disallow_transient_supporessor_usage` is true, disables transient +// suppression. When `input_volume_controller_config_override` is specified, +// switches all gain control to AGC2. +AudioProcessing::Config AdjustConfig( const AudioProcessing::Config& config, + bool disallow_transient_supporessor_usage, const absl::optional& input_volume_controller_config_override) { - const bool analog_agc_enabled = + AudioProcessing::Config adjusted_config = config; + + // Override the transient suppressor configuration. + if (disallow_transient_supporessor_usage) { + adjusted_config.transient_suppression.enabled = false; + } + + // Override the auto gain control configuration if the AGC1 analog gain + // controller is active and `input_volume_controller_config_override` is + // specified. + const bool agc1_analog_enabled = config.gain_controller1.enabled && (config.gain_controller1.mode == AudioProcessing::Config::GainController1::kAdaptiveAnalog || config.gain_controller1.analog_gain_controller.enabled); - - // Do not update the config if none of the analog AGCs is active - // regardless of the input volume controller override. - if (!analog_agc_enabled || - !input_volume_controller_config_override.has_value()) { - return config; + if (agc1_analog_enabled && + input_volume_controller_config_override.has_value()) { + // Check that the unadjusted AGC config meets the preconditions. + const bool hybrid_agc_config_detected = + config.gain_controller1.enabled && + config.gain_controller1.analog_gain_controller.enabled && + !config.gain_controller1.analog_gain_controller + .enable_digital_adaptive && + config.gain_controller2.enabled && + config.gain_controller2.adaptive_digital.enabled; + const bool full_agc1_config_detected = + config.gain_controller1.enabled && + config.gain_controller1.analog_gain_controller.enabled && + config.gain_controller1.analog_gain_controller + .enable_digital_adaptive && + !config.gain_controller2.enabled; + const bool one_and_only_one_input_volume_controller = + hybrid_agc_config_detected != full_agc1_config_detected; + if (!one_and_only_one_input_volume_controller || + config.gain_controller2.input_volume_controller.enabled) { + RTC_LOG(LS_ERROR) << "Cannot adjust AGC config (precondition failed)"; + if (!one_and_only_one_input_volume_controller) + RTC_LOG(LS_ERROR) + << "One and only one input volume controller must be enabled."; + if (config.gain_controller2.input_volume_controller.enabled) + RTC_LOG(LS_ERROR) + << "The AGC2 input volume controller must be disabled."; + } else { + adjusted_config.gain_controller1.enabled = false; + adjusted_config.gain_controller1.analog_gain_controller.enabled = false; + adjusted_config.gain_controller2.enabled = true; + adjusted_config.gain_controller2.adaptive_digital.enabled = true; + adjusted_config.gain_controller2.input_volume_controller.enabled = true; + } } - const bool hybrid_agc_config_detected = - config.gain_controller1.enabled && - config.gain_controller1.analog_gain_controller.enabled && - !config.gain_controller1.analog_gain_controller.enable_digital_adaptive && - config.gain_controller2.enabled && - config.gain_controller2.adaptive_digital.enabled; - - const bool full_agc1_config_detected = - config.gain_controller1.enabled && - config.gain_controller1.analog_gain_controller.enabled && - config.gain_controller1.analog_gain_controller.enable_digital_adaptive && - !config.gain_controller2.enabled; - - if (hybrid_agc_config_detected == full_agc1_config_detected || - config.gain_controller2.input_volume_controller.enabled) { - RTC_LOG(LS_ERROR) << "Unexpected AGC config: Config not adjusted."; - return config; - } - - AudioProcessing::Config adjusted_config = config; - adjusted_config.gain_controller1.enabled = false; - adjusted_config.gain_controller1.analog_gain_controller.enabled = false; - adjusted_config.gain_controller2.enabled = true; - adjusted_config.gain_controller2.adaptive_digital.enabled = true; - adjusted_config.gain_controller2.input_volume_controller.enabled = true; - return adjusted_config; } @@ -583,13 +597,17 @@ AudioProcessingImpl::AudioProcessingImpl( GetInputVolumeControllerConfigOverride()), use_denormal_disabler_( !field_trial::IsEnabled("WebRTC-ApmDenormalDisablerKillSwitch")), + disallow_transient_supporessor_usage_( + field_trial::IsEnabled("WebRTC-ApmTransientSuppressorKillSwitch")), transient_suppressor_vad_mode_(GetTransientSuppressorVadMode()), capture_runtime_settings_(RuntimeSettingQueueSize()), render_runtime_settings_(RuntimeSettingQueueSize()), capture_runtime_settings_enqueuer_(&capture_runtime_settings_), render_runtime_settings_enqueuer_(&render_runtime_settings_), echo_control_factory_(std::move(echo_control_factory)), - config_(AdjustConfig(config, input_volume_controller_config_override_)), + config_(AdjustConfig(config, + disallow_transient_supporessor_usage_, + input_volume_controller_config_override_)), submodule_states_(!!capture_post_processor, !!render_pre_processor, !!capture_analyzer), @@ -824,11 +842,9 @@ void AudioProcessingImpl::ApplyConfig(const AudioProcessing::Config& config) { MutexLock lock_render(&mutex_render_); MutexLock lock_capture(&mutex_capture_); - // TODO(bugs.webrtc.org/7494): Replace `adjusted_config` with `config` after - // "WebRTC-Audio-InputVolumeControllerExperiment" field trial is removed. const auto adjusted_config = - AdjustConfig(config, input_volume_controller_config_override_); - + AdjustConfig(config, disallow_transient_supporessor_usage_, + input_volume_controller_config_override_); RTC_LOG(LS_INFO) << "AudioProcessing::ApplyConfig: " << adjusted_config.ToString(); diff --git a/modules/audio_processing/audio_processing_impl.h b/modules/audio_processing/audio_processing_impl.h index 9a30c8b9f6..66e98dc304 100644 --- a/modules/audio_processing/audio_processing_impl.h +++ b/modules/audio_processing/audio_processing_impl.h @@ -191,14 +191,19 @@ class AudioProcessingImpl : public AudioProcessing { static std::atomic instance_count_; const bool use_setup_specific_default_aec3_config_; - // TODO(bugs.webrtc.org/7494): Remove the the config when the field trial is - // removed. "WebRTC-Audio-InputVolumeControllerExperiment" field trial - // override for the input volume controller config. + // TODO(bugs.webrtc.org/7494): Remove when the linked field trial is removed. + // Override base on the "WebRTC-Audio-InputVolumeControllerExperiment" field + // trial for the AGC2 input volume controller configuration. const absl::optional input_volume_controller_config_override_; const bool use_denormal_disabler_; + // When true, the transient suppressor submodule is never created regardless + // of the APM configuration. + // TODO(bugs.webrtc.org/13663): Remove when the linked field trial is removed. + const bool disallow_transient_supporessor_usage_; + const TransientSuppressor::VadMode transient_suppressor_vad_mode_; SwapQueue capture_runtime_settings_; diff --git a/modules/audio_processing/audio_processing_impl_unittest.cc b/modules/audio_processing/audio_processing_impl_unittest.cc index ea61dae2d5..346b5f5e14 100644 --- a/modules/audio_processing/audio_processing_impl_unittest.cc +++ b/modules/audio_processing/audio_processing_impl_unittest.cc @@ -960,6 +960,55 @@ TEST(ApmWithSubmodulesExcludedTest, ToggleTransientSuppressor) { } } +TEST(AudioProcessingImplTest, CanDisableTransientSuppressor) { + // Do not explicitly disable "WebRTC-ApmTransientSuppressorKillSwitch" since + // to check that, by default, it is disabled. + auto apm = AudioProcessingBuilder() + .SetConfig({.transient_suppression = {.enabled = false}}) + .Create(); + EXPECT_FALSE(apm->GetConfig().transient_suppression.enabled); +} + +TEST(AudioProcessingImplTest, CanEnableTransientSuppressor) { + // Do not explicitly disable "WebRTC-ApmTransientSuppressorKillSwitch" since + // to check that, by default, it is disabled. + auto apm = AudioProcessingBuilder() + .SetConfig({.transient_suppression = {.enabled = true}}) + .Create(); + EXPECT_TRUE(apm->GetConfig().transient_suppression.enabled); +} + +TEST(AudioProcessingImplTest, CanDisableTransientSuppressorIfUsageAllowed) { + // Disable the field trial that disallows to enable transient suppression. + test::ScopedFieldTrials field_trials( + "WebRTC-ApmTransientSuppressorKillSwitch/Disabled/"); + auto apm = AudioProcessingBuilder() + .SetConfig({.transient_suppression = {.enabled = false}}) + .Create(); + EXPECT_FALSE(apm->GetConfig().transient_suppression.enabled); +} + +TEST(AudioProcessingImplTest, CanEnableTransientSuppressorIfUsageAllowed) { + // Disable the field trial that disallows to enable transient suppression. + test::ScopedFieldTrials field_trials( + "WebRTC-ApmTransientSuppressorKillSwitch/Disabled/"); + auto apm = AudioProcessingBuilder() + .SetConfig({.transient_suppression = {.enabled = true}}) + .Create(); + EXPECT_TRUE(apm->GetConfig().transient_suppression.enabled); +} + +TEST(AudioProcessingImplTest, + CannotEnableTransientSuppressorIfUsageDisallowed) { + // Enable the field trial that disallows to enable transient suppression. + test::ScopedFieldTrials field_trials( + "WebRTC-ApmTransientSuppressorKillSwitch/Enabled/"); + auto apm = AudioProcessingBuilder() + .SetConfig({.transient_suppression = {.enabled = true}}) + .Create(); + EXPECT_FALSE(apm->GetConfig().transient_suppression.enabled); +} + // Tests that the minimum startup volume is applied at the startup. TEST_P(InputVolumeStartupParameterizedTest, VerifyStartupMinVolumeAppliedAtStartup) {