APM: Add field trial parameters and rename

Add AGC2 digital adaptive config parameters in the field trial
"WebRTC-Audio-InputVolumeControllerExperiment". Rename it as
"WebRTC-Audio-GainController2" to reflect that the override now adjusts
the parameters for both input volume controller and adaptive digital
controller.

Bug: webrtc:7494
Change-Id: Ifbc1b8be76cf23b0b6b74b22b5167a45972cab38
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/286880
Reviewed-by: Alessio Bazzica <alessiob@webrtc.org>
Commit-Queue: Hanna Silen <silen@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#38855}
diff --git a/modules/audio_processing/audio_processing_impl.cc b/modules/audio_processing/audio_processing_impl.cc
index c1a2756..3200ea4 100644
--- a/modules/audio_processing/audio_processing_impl.cc
+++ b/modules/audio_processing/audio_processing_impl.cc
@@ -325,83 +325,124 @@
   return error_code;
 }
 
-const absl::optional<InputVolumeController::Config>
-GetInputVolumeControllerConfigOverride() {
-  constexpr char kInputVolumeControllerFieldTrial[] =
-      "WebRTC-Audio-InputVolumeControllerExperiment";
+const absl::optional<AudioProcessingImpl::GainController2ConfigOverride>
+GetGainController2ConfigOverride() {
+  constexpr char kFieldTrialName[] = "WebRTC-Audio-GainController2";
 
-  if (!field_trial::IsEnabled(kInputVolumeControllerFieldTrial)) {
+  if (!field_trial::IsEnabled(kFieldTrialName)) {
     return absl::nullopt;
   }
 
-  constexpr InputVolumeController::Config kDefaultConfig;
+  constexpr InputVolumeController::Config kDefaultInputVolumeControllerConfig;
 
   FieldTrialFlag enabled("Enabled", false);
   FieldTrialConstrained<int> clipped_level_min(
-      "clipped_level_min", kDefaultConfig.clipped_level_min, 0, 255);
+      "clipped_level_min",
+      kDefaultInputVolumeControllerConfig.clipped_level_min, 0, 255);
   FieldTrialConstrained<int> clipped_level_step(
-      "clipped_level_step", kDefaultConfig.clipped_level_step, 0, 255);
+      "clipped_level_step",
+      kDefaultInputVolumeControllerConfig.clipped_level_step, 0, 255);
   FieldTrialConstrained<double> clipped_ratio_threshold(
-      "clipped_ratio_threshold", kDefaultConfig.clipped_ratio_threshold, 0, 1);
+      "clipped_ratio_threshold",
+      kDefaultInputVolumeControllerConfig.clipped_ratio_threshold, 0, 1);
   FieldTrialConstrained<int> clipped_wait_frames(
-      "clipped_wait_frames", kDefaultConfig.clipped_wait_frames, 0,
+      "clipped_wait_frames",
+      kDefaultInputVolumeControllerConfig.clipped_wait_frames, 0,
       absl::nullopt);
   FieldTrialParameter<bool> enable_clipping_predictor(
-      "enable_clipping_predictor", kDefaultConfig.enable_clipping_predictor);
+      "enable_clipping_predictor",
+      kDefaultInputVolumeControllerConfig.enable_clipping_predictor);
   FieldTrialConstrained<int> target_range_max_dbfs(
-      "target_range_max_dbfs", kDefaultConfig.target_range_max_dbfs, -90, 30);
+      "target_range_max_dbfs",
+      kDefaultInputVolumeControllerConfig.target_range_max_dbfs, -90, 30);
   FieldTrialConstrained<int> target_range_min_dbfs(
-      "target_range_min_dbfs", kDefaultConfig.target_range_min_dbfs, -90, 30);
+      "target_range_min_dbfs",
+      kDefaultInputVolumeControllerConfig.target_range_min_dbfs, -90, 30);
   FieldTrialConstrained<int> update_input_volume_wait_frames(
       "update_input_volume_wait_frames",
-      kDefaultConfig.update_input_volume_wait_frames, 0, absl::nullopt);
+      kDefaultInputVolumeControllerConfig.update_input_volume_wait_frames, 0,
+      absl::nullopt);
   FieldTrialConstrained<double> speech_probability_threshold(
       "speech_probability_threshold",
-      kDefaultConfig.speech_probability_threshold, 0, 1);
+      kDefaultInputVolumeControllerConfig.speech_probability_threshold, 0, 1);
   FieldTrialConstrained<double> speech_ratio_threshold(
-      "speech_ratio_threshold", kDefaultConfig.speech_ratio_threshold, 0, 1);
+      "speech_ratio_threshold",
+      kDefaultInputVolumeControllerConfig.speech_ratio_threshold, 0, 1);
 
-  // Field-trial based override for the input volume controller config.
+  constexpr AudioProcessing::Config::GainController2::AdaptiveDigital
+      kDefaultAdaptiveDigitalConfig;
+
+  FieldTrialConstrained<double> headroom_db(
+      "headroom_db", kDefaultAdaptiveDigitalConfig.headroom_db, 0,
+      absl::nullopt);
+  FieldTrialConstrained<double> max_gain_db(
+      "max_gain_db", kDefaultAdaptiveDigitalConfig.max_gain_db, 0,
+      absl::nullopt);
+  FieldTrialConstrained<double> max_gain_change_db_per_second(
+      "max_gain_change_db_per_second",
+      kDefaultAdaptiveDigitalConfig.max_gain_change_db_per_second, 0,
+      absl::nullopt);
+  FieldTrialConstrained<double> max_output_noise_level_dbfs(
+      "max_output_noise_level_dbfs",
+      kDefaultAdaptiveDigitalConfig.max_output_noise_level_dbfs, absl::nullopt,
+      0);
+
+  // Field-trial based override for the input volume controller and adaptive
+  // digital configs.
   const std::string field_trial_name =
-      field_trial::FindFullName(kInputVolumeControllerFieldTrial);
+      field_trial::FindFullName(kFieldTrialName);
 
   ParseFieldTrial({&enabled, &clipped_level_min, &clipped_level_step,
                    &clipped_ratio_threshold, &clipped_wait_frames,
                    &enable_clipping_predictor, &target_range_max_dbfs,
                    &target_range_min_dbfs, &update_input_volume_wait_frames,
-                   &speech_probability_threshold, &speech_ratio_threshold},
+                   &speech_probability_threshold, &speech_ratio_threshold,
+                   &headroom_db, &max_gain_db, &max_gain_change_db_per_second,
+                   &max_output_noise_level_dbfs},
                   field_trial_name);
 
   // Checked already by `IsEnabled()` before parsing, therefore always true.
   RTC_DCHECK(enabled);
 
-  return InputVolumeController::Config{
-      .clipped_level_min = static_cast<int>(clipped_level_min.Get()),
-      .clipped_level_step = static_cast<int>(clipped_level_step.Get()),
-      .clipped_ratio_threshold =
-          static_cast<float>(clipped_ratio_threshold.Get()),
-      .clipped_wait_frames = static_cast<int>(clipped_wait_frames.Get()),
-      .enable_clipping_predictor =
-          static_cast<bool>(enable_clipping_predictor.Get()),
-      .target_range_max_dbfs = static_cast<int>(target_range_max_dbfs.Get()),
-      .target_range_min_dbfs = static_cast<int>(target_range_min_dbfs.Get()),
-      .update_input_volume_wait_frames =
-          static_cast<int>(update_input_volume_wait_frames.Get()),
-      .speech_probability_threshold =
-          static_cast<float>(speech_probability_threshold.Get()),
-      .speech_ratio_threshold =
-          static_cast<float>(speech_ratio_threshold.Get()),
+  return AudioProcessingImpl::GainController2ConfigOverride{
+      InputVolumeController::Config{
+          .clipped_level_min = static_cast<int>(clipped_level_min.Get()),
+          .clipped_level_step = static_cast<int>(clipped_level_step.Get()),
+          .clipped_ratio_threshold =
+              static_cast<float>(clipped_ratio_threshold.Get()),
+          .clipped_wait_frames = static_cast<int>(clipped_wait_frames.Get()),
+          .enable_clipping_predictor =
+              static_cast<bool>(enable_clipping_predictor.Get()),
+          .target_range_max_dbfs =
+              static_cast<int>(target_range_max_dbfs.Get()),
+          .target_range_min_dbfs =
+              static_cast<int>(target_range_min_dbfs.Get()),
+          .update_input_volume_wait_frames =
+              static_cast<int>(update_input_volume_wait_frames.Get()),
+          .speech_probability_threshold =
+              static_cast<float>(speech_probability_threshold.Get()),
+          .speech_ratio_threshold =
+              static_cast<float>(speech_ratio_threshold.Get()),
+      },
+      AudioProcessingImpl::GainController2ConfigOverride::AdaptiveDigitalConfig{
+          .headroom_db = static_cast<float>(headroom_db.Get()),
+          .max_gain_db = static_cast<float>(max_gain_db.Get()),
+          .max_gain_change_db_per_second =
+              static_cast<float>(max_gain_change_db_per_second.Get()),
+          .max_output_noise_level_dbfs =
+              static_cast<float>(max_output_noise_level_dbfs.Get()),
+      },
   };
 }
 
 // If `disallow_transient_supporessor_usage` is true, disables transient
-// suppression. When `input_volume_controller_config_override` is specified,
+// suppression. When `gain_controller2_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<InputVolumeController::Config>&
-        input_volume_controller_config_override) {
+    const absl::optional<AudioProcessingImpl::GainController2ConfigOverride>&
+        gain_controller2_config_override) {
   AudioProcessing::Config adjusted_config = config;
 
   // Override the transient suppressor configuration.
@@ -410,15 +451,14 @@
   }
 
   // Override the auto gain control configuration if the AGC1 analog gain
-  // controller is active and `input_volume_controller_config_override` is
+  // controller is active and `gain_controller2_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);
-  if (agc1_analog_enabled &&
-      input_volume_controller_config_override.has_value()) {
+  if (agc1_analog_enabled && gain_controller2_config_override.has_value()) {
     // Check that the unadjusted AGC config meets the preconditions.
     const bool hybrid_agc_config_detected =
         config.gain_controller1.enabled &&
@@ -447,9 +487,23 @@
     } 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;
+
+      auto& adjusted_adaptive_digital =  // Alias.
+          adjusted_config.gain_controller2.adaptive_digital;
+      const auto& adaptive_digital_override =  // Alias.
+          gain_controller2_config_override->adaptive_digital_config;
+      adjusted_adaptive_digital.headroom_db =
+          adaptive_digital_override.headroom_db;
+      adjusted_adaptive_digital.max_gain_db =
+          adaptive_digital_override.max_gain_db;
+      adjusted_adaptive_digital.max_gain_change_db_per_second =
+          adaptive_digital_override.max_gain_change_db_per_second;
+      adjusted_adaptive_digital.max_output_noise_level_dbfs =
+          adaptive_digital_override.max_output_noise_level_dbfs;
     }
   }
 
@@ -593,8 +647,7 @@
     : data_dumper_(new ApmDataDumper(instance_count_.fetch_add(1) + 1)),
       use_setup_specific_default_aec3_config_(
           UseSetupSpecificDefaultAec3Congfig()),
-      input_volume_controller_config_override_(
-          GetInputVolumeControllerConfigOverride()),
+      gain_controller2_config_override_(GetGainController2ConfigOverride()),
       use_denormal_disabler_(
           !field_trial::IsEnabled("WebRTC-ApmDenormalDisablerKillSwitch")),
       disallow_transient_supporessor_usage_(
@@ -607,7 +660,7 @@
       echo_control_factory_(std::move(echo_control_factory)),
       config_(AdjustConfig(config,
                            disallow_transient_supporessor_usage_,
-                           input_volume_controller_config_override_)),
+                           gain_controller2_config_override_)),
       submodule_states_(!!capture_post_processor,
                         !!render_pre_processor,
                         !!capture_analyzer),
@@ -844,7 +897,7 @@
 
   const auto adjusted_config =
       AdjustConfig(config, disallow_transient_supporessor_usage_,
-                   input_volume_controller_config_override_);
+                   gain_controller2_config_override_);
   RTC_LOG(LS_INFO) << "AudioProcessing::ApplyConfig: "
                    << adjusted_config.ToString();
 
@@ -2292,8 +2345,9 @@
         transient_suppressor_vad_mode_ != TransientSuppressor::VadMode::kRnnVad;
     submodules_.gain_controller2 = std::make_unique<GainController2>(
         config_.gain_controller2,
-        input_volume_controller_config_override_.value_or(
-            InputVolumeController::Config{}),
+        gain_controller2_config_override_.has_value()
+            ? gain_controller2_config_override_->input_volume_controller_config
+            : InputVolumeController::Config{},
         proc_fullband_sample_rate_hz(), num_input_channels(), use_internal_vad);
     submodules_.gain_controller2->SetCaptureOutputUsed(
         capture_.capture_output_used);
diff --git a/modules/audio_processing/audio_processing_impl.h b/modules/audio_processing/audio_processing_impl.h
index 66e98dc..189ed03 100644
--- a/modules/audio_processing/audio_processing_impl.h
+++ b/modules/audio_processing/audio_processing_impl.h
@@ -138,6 +138,18 @@
 
   AudioProcessing::Config GetConfig() const override;
 
+  // TODO(bugs.webrtc.org/7494): Remove when the related field trial is
+  // removed.
+  struct GainController2ConfigOverride {
+    InputVolumeController::Config input_volume_controller_config;
+    struct AdaptiveDigitalConfig {
+      float headroom_db;
+      float max_gain_db;
+      float max_gain_change_db_per_second;
+      float max_output_noise_level_dbfs;
+    } adaptive_digital_config;
+  };
+
  protected:
   // Overridden in a mock.
   virtual void InitializeLocked()
@@ -161,7 +173,7 @@
   FRIEND_TEST_ALL_PREFIXES(ApmWithSubmodulesExcludedTest,
                            BitexactWithDisabledModules);
   FRIEND_TEST_ALL_PREFIXES(
-      AudioProcessingImplInputVolumeControllerExperimentParametrizedTest,
+      AudioProcessingImplGainController2FieldTrialParametrizedTest,
       ConfigAdjustedWhenExperimentEnabled);
 
   void set_stream_analog_level_locked(int level)
@@ -192,10 +204,10 @@
   const bool use_setup_specific_default_aec3_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<InputVolumeController::Config>
-      input_volume_controller_config_override_;
+  // Override based on the "WebRTC-Audio-GainController2" field trial for the
+  // AGC2 input volume controller and adaptive digital controller configuration.
+  const absl::optional<GainController2ConfigOverride>
+      gain_controller2_config_override_;
 
   const bool use_denormal_disabler_;
 
diff --git a/modules/audio_processing/audio_processing_impl_unittest.cc b/modules/audio_processing/audio_processing_impl_unittest.cc
index 7a45c45..b394e93 100644
--- a/modules/audio_processing/audio_processing_impl_unittest.cc
+++ b/modules/audio_processing/audio_processing_impl_unittest.cc
@@ -1235,10 +1235,12 @@
   EXPECT_EQ(ProcessInputVolume(*apm, kOneFrame, /*initial_volume=*/135), 135);
 }
 
-TEST(AudioProcessingImplInputVolumeControllerExperimentTest,
+TEST(AudioProcessingImplGainController2FieldTrialTest,
      ConfigAdjustedWhenExperimentEnabledAndAgc1AnalogEnabled) {
+  constexpr AudioProcessing::Config::GainController2::AdaptiveDigital
+      kDefaultAdaptiveDigitalConfig;
   webrtc::test::ScopedFieldTrials field_trials(
-      "WebRTC-Audio-InputVolumeControllerExperiment/"
+      "WebRTC-Audio-GainController2/"
       "Enabled,"
       "enable_clipping_predictor:true,"
       "clipped_level_min:20,"
@@ -1249,7 +1251,11 @@
       "target_range_min_dbfs:-70,"
       "update_input_volume_wait_frames:80,"
       "speech_probability_threshold:0.9,"
-      "speech_ratio_threshold:1.0/");
+      "speech_ratio_threshold:1.0,"
+      "headroom_db:10,"
+      "max_gain_db:20,"
+      "max_gain_change_db_per_second:3,"
+      "max_output_noise_level_dbfs:-40/");
 
   AudioProcessingBuilderForTesting apm_builder;
 
@@ -1275,6 +1281,8 @@
   EXPECT_TRUE(adjusted_config.gain_controller2.enabled);
   EXPECT_TRUE(adjusted_config.gain_controller2.adaptive_digital.enabled);
   EXPECT_TRUE(adjusted_config.gain_controller2.input_volume_controller.enabled);
+  EXPECT_NE(adjusted_config.gain_controller2.adaptive_digital,
+            kDefaultAdaptiveDigitalConfig);
 
   // Change config back and compare.
   adjusted_config.gain_controller1.enabled = config.gain_controller1.enabled;
@@ -1285,14 +1293,18 @@
       config.gain_controller2.adaptive_digital.enabled;
   adjusted_config.gain_controller2.input_volume_controller.enabled =
       config.gain_controller2.input_volume_controller.enabled;
+  adjusted_config.gain_controller2.adaptive_digital =
+      config.gain_controller2.adaptive_digital;
 
   EXPECT_THAT(adjusted_config.ToString(), ::testing::StrEq(config.ToString()));
 }
 
-TEST(AudioProcessingImplInputVolumeControllerExperimentTest,
+TEST(AudioProcessingImplGainController2FieldTrialTest,
      ConfigAdjustedWhenExperimentEnabledAndHybridAgcEnabled) {
+  constexpr AudioProcessing::Config::GainController2::AdaptiveDigital
+      kDefaultAdaptiveDigitalConfig;
   webrtc::test::ScopedFieldTrials field_trials(
-      "WebRTC-Audio-InputVolumeControllerExperiment/"
+      "WebRTC-Audio-GainController2/"
       "Enabled,"
       "enable_clipping_predictor:true,"
       "clipped_level_min:20,"
@@ -1303,7 +1315,11 @@
       "target_range_min_dbfs:-70,"
       "update_input_volume_wait_frames:80,"
       "speech_probability_threshold:0.9,"
-      "speech_ratio_threshold:1.0/");
+      "speech_ratio_threshold:1.0,"
+      "headroom_db:10,"
+      "max_gain_db:20,"
+      "max_gain_change_db_per_second:3,"
+      "max_output_noise_level_dbfs:-40/");
 
   AudioProcessingBuilderForTesting apm_builder;
 
@@ -1331,6 +1347,8 @@
   EXPECT_TRUE(adjusted_config.gain_controller2.enabled);
   EXPECT_TRUE(adjusted_config.gain_controller2.adaptive_digital.enabled);
   EXPECT_TRUE(adjusted_config.gain_controller2.input_volume_controller.enabled);
+  EXPECT_NE(adjusted_config.gain_controller2.adaptive_digital,
+            kDefaultAdaptiveDigitalConfig);
 
   // Change config back and compare.
   adjusted_config.gain_controller1.enabled = config.gain_controller1.enabled;
@@ -1341,14 +1359,16 @@
       config.gain_controller2.adaptive_digital.enabled;
   adjusted_config.gain_controller2.input_volume_controller.enabled =
       config.gain_controller2.input_volume_controller.enabled;
+  adjusted_config.gain_controller2.adaptive_digital =
+      config.gain_controller2.adaptive_digital;
 
   EXPECT_THAT(adjusted_config.ToString(), ::testing::StrEq(config.ToString()));
 }
 
-TEST(AudioProcessingImplInputVolumeControllerExperimentTest,
+TEST(AudioProcessingImplGainController2FieldTrialTest,
      ConfigNotAdjustedWhenExperimentEnabledAndAgc1AnalogNotEnabled) {
   webrtc::test::ScopedFieldTrials field_trials(
-      "WebRTC-Audio-InputVolumeControllerExperiment/"
+      "WebRTC-Audio-GainController2/"
       "Enabled,"
       "enable_clipping_predictor:true,"
       "clipped_level_min:20,"
@@ -1359,7 +1379,11 @@
       "target_range_min_dbfs:-70,"
       "update_input_volume_wait_frames:80,"
       "speech_probability_threshold:0.9,"
-      "speech_ratio_threshold:1.0/");
+      "speech_ratio_threshold:1.0,"
+      "headroom_db:10,"
+      "max_gain_db:20,"
+      "max_gain_change_db_per_second:3,"
+      "max_output_noise_level_dbfs:-40/");
 
   AudioProcessingBuilderForTesting apm_builder;
 
@@ -1393,10 +1417,10 @@
   EXPECT_THAT(adjusted_config.ToString(), ::testing::StrEq(config.ToString()));
 }
 
-TEST(AudioProcessingImplInputVolumeControllerExperimentTest,
+TEST(AudioProcessingImplGainController2FieldTrialTest,
      ConfigNotAdjustedWhenExperimentEnabledAndHybridAgcNotEnabled) {
   webrtc::test::ScopedFieldTrials field_trials(
-      "WebRTC-Audio-InputVolumeControllerExperiment/"
+      "WebRTC-Audio-GainController2/"
       "Enabled,"
       "enable_clipping_predictor:true,"
       "clipped_level_min:20,"
@@ -1407,7 +1431,11 @@
       "target_range_min_dbfs:-70,"
       "update_input_volume_wait_frames:80,"
       "speech_probability_threshold:0.9,"
-      "speech_ratio_threshold:1.0/");
+      "speech_ratio_threshold:1.0,"
+      "headroom_db:10,"
+      "max_gain_db:20,"
+      "max_gain_change_db_per_second:3,"
+      "max_output_noise_level_dbfs:-40/");
 
   AudioProcessingBuilderForTesting apm_builder;
 
@@ -1443,7 +1471,7 @@
   EXPECT_THAT(adjusted_config.ToString(), ::testing::StrEq(config.ToString()));
 }
 
-TEST(AudioProcessingImplInputVolumeControllerExperimentTest,
+TEST(AudioProcessingImplGainController2FieldTrialTest,
      ConfigNotAdjustedWhenExperimentNotEnabledAndAgc1AnalogEnabled) {
   AudioProcessingBuilderForTesting apm_builder;
 
@@ -1477,7 +1505,7 @@
   EXPECT_THAT(adjusted_config.ToString(), ::testing::StrEq(config.ToString()));
 }
 
-TEST(AudioProcessingImplInputVolumeControllerExperimentTest,
+TEST(AudioProcessingImplGainController2FieldTrialTest,
      ConfigNotAdjustedWhenExperimentNotEnabledAndHybridAgcEnabled) {
   AudioProcessingBuilderForTesting apm_builder;