APM: Add a field trial for input volume controller

Add a field trial WebRTC-Audio-InputVolumeControllerExperiment and
a mechanism to adjust the config accordingly. Pass the additional
input volume controller config to GainController2.

Bug: webrtc:7494
Change-Id: I3dd624df1f4774cb533417747627995e1f60aa68
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/284101
Reviewed-by: Alessio Bazzica <alessiob@webrtc.org>
Reviewed-by: Per Ã…hgren <peah@webrtc.org>
Reviewed-by: Sam Zackrisson <saza@webrtc.org>
Commit-Queue: Hanna Silen <silen@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#38780}
diff --git a/modules/audio_processing/audio_processing_impl_unittest.cc b/modules/audio_processing/audio_processing_impl_unittest.cc
index fea7a8c..ea61dae 100644
--- a/modules/audio_processing/audio_processing_impl_unittest.cc
+++ b/modules/audio_processing/audio_processing_impl_unittest.cc
@@ -1188,4 +1188,282 @@
   EXPECT_EQ(ProcessInputVolume(*apm, kOneFrame, /*initial_volume=*/135), 135);
 }
 
+TEST(AudioProcessingImplInputVolumeControllerExperimentTest,
+     ConfigAdjustedWhenExperimentEnabledAndAgc1AnalogEnabled) {
+  webrtc::test::ScopedFieldTrials field_trials(
+      "WebRTC-Audio-InputVolumeControllerExperiment/"
+      "Enabled,"
+      "enable_clipping_predictor:true,"
+      "clipped_level_min:20,"
+      "clipped_level_step:30,"
+      "clipped_ratio_threshold:0.4,"
+      "clipped_wait_frames:50,"
+      "target_range_max_dbfs:-6,"
+      "target_range_min_dbfs:-70,"
+      "update_input_volume_wait_frames:80,"
+      "speech_probability_threshold:0.9,"
+      "speech_ratio_threshold:1.0/");
+
+  AudioProcessingBuilderForTesting apm_builder;
+
+  // Set a config with analog AGC1 enabled.
+  AudioProcessing::Config config;
+  config.gain_controller1.enabled = true;
+  config.gain_controller1.analog_gain_controller.enabled = true;
+  config.gain_controller1.analog_gain_controller.enable_digital_adaptive = true;
+  config.gain_controller2.enabled = false;
+  config.gain_controller1.mode =
+      AudioProcessing::Config::GainController1::kAdaptiveAnalog;
+
+  EXPECT_FALSE(config.gain_controller2.input_volume_controller.enabled);
+
+  apm_builder.SetConfig(config);
+
+  auto apm = apm_builder.Create();
+  auto adjusted_config = apm->GetConfig();
+
+  // Expect the config to be adjusted.
+  EXPECT_FALSE(adjusted_config.gain_controller1.enabled);
+  EXPECT_FALSE(adjusted_config.gain_controller1.analog_gain_controller.enabled);
+  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);
+
+  // Change config back and compare.
+  adjusted_config.gain_controller1.enabled = config.gain_controller1.enabled;
+  adjusted_config.gain_controller1.analog_gain_controller.enabled =
+      config.gain_controller1.analog_gain_controller.enabled;
+  adjusted_config.gain_controller2.enabled = config.gain_controller2.enabled;
+  adjusted_config.gain_controller2.adaptive_digital.enabled =
+      config.gain_controller2.adaptive_digital.enabled;
+  adjusted_config.gain_controller2.input_volume_controller.enabled =
+      config.gain_controller2.input_volume_controller.enabled;
+
+  EXPECT_THAT(adjusted_config.ToString(), ::testing::StrEq(config.ToString()));
+}
+
+TEST(AudioProcessingImplInputVolumeControllerExperimentTest,
+     ConfigAdjustedWhenExperimentEnabledAndHybridAgcEnabled) {
+  webrtc::test::ScopedFieldTrials field_trials(
+      "WebRTC-Audio-InputVolumeControllerExperiment/"
+      "Enabled,"
+      "enable_clipping_predictor:true,"
+      "clipped_level_min:20,"
+      "clipped_level_step:30,"
+      "clipped_ratio_threshold:0.4,"
+      "clipped_wait_frames:50,"
+      "target_range_max_dbfs:-6,"
+      "target_range_min_dbfs:-70,"
+      "update_input_volume_wait_frames:80,"
+      "speech_probability_threshold:0.9,"
+      "speech_ratio_threshold:1.0/");
+
+  AudioProcessingBuilderForTesting apm_builder;
+
+  // Set a config with hybrid AGC enabled.
+  AudioProcessing::Config config;
+  config.gain_controller1.enabled = true;
+  config.gain_controller1.analog_gain_controller.enabled = true;
+  config.gain_controller1.analog_gain_controller.enable_digital_adaptive =
+      false;
+  config.gain_controller2.enabled = true;
+  config.gain_controller2.adaptive_digital.enabled = true;
+  config.gain_controller1.mode =
+      AudioProcessing::Config::GainController1::kAdaptiveAnalog;
+
+  EXPECT_FALSE(config.gain_controller2.input_volume_controller.enabled);
+
+  apm_builder.SetConfig(config);
+
+  auto apm = apm_builder.Create();
+  auto adjusted_config = apm->GetConfig();
+
+  // Expect the config to be adjusted.
+  EXPECT_FALSE(adjusted_config.gain_controller1.enabled);
+  EXPECT_FALSE(adjusted_config.gain_controller1.analog_gain_controller.enabled);
+  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);
+
+  // Change config back and compare.
+  adjusted_config.gain_controller1.enabled = config.gain_controller1.enabled;
+  adjusted_config.gain_controller1.analog_gain_controller.enabled =
+      config.gain_controller1.analog_gain_controller.enabled;
+  adjusted_config.gain_controller2.enabled = config.gain_controller2.enabled;
+  adjusted_config.gain_controller2.adaptive_digital.enabled =
+      config.gain_controller2.adaptive_digital.enabled;
+  adjusted_config.gain_controller2.input_volume_controller.enabled =
+      config.gain_controller2.input_volume_controller.enabled;
+
+  EXPECT_THAT(adjusted_config.ToString(), ::testing::StrEq(config.ToString()));
+}
+
+TEST(AudioProcessingImplInputVolumeControllerExperimentTest,
+     ConfigNotAdjustedWhenExperimentEnabledAndAgc1AnalogNotEnabled) {
+  webrtc::test::ScopedFieldTrials field_trials(
+      "WebRTC-Audio-InputVolumeControllerExperiment/"
+      "Enabled,"
+      "enable_clipping_predictor:true,"
+      "clipped_level_min:20,"
+      "clipped_level_step:30,"
+      "clipped_ratio_threshold:0.4,"
+      "clipped_wait_frames:50,"
+      "target_range_max_dbfs:-6,"
+      "target_range_min_dbfs:-70,"
+      "update_input_volume_wait_frames:80,"
+      "speech_probability_threshold:0.9,"
+      "speech_ratio_threshold:1.0/");
+
+  AudioProcessingBuilderForTesting apm_builder;
+
+  // Set a config with analog AGC1 not enabled.
+  AudioProcessing::Config config;
+  config.gain_controller1.enabled = false;
+  config.gain_controller1.analog_gain_controller.enabled = true;
+  config.gain_controller1.analog_gain_controller.enable_digital_adaptive = true;
+  config.gain_controller2.enabled = false;
+  config.gain_controller1.mode =
+      AudioProcessing::Config::GainController1::kAdaptiveAnalog;
+
+  EXPECT_FALSE(config.gain_controller2.input_volume_controller.enabled);
+
+  apm_builder.SetConfig(config);
+
+  auto apm = apm_builder.Create();
+  auto adjusted_config = apm->GetConfig();
+
+  EXPECT_EQ(config.gain_controller1.enabled,
+            adjusted_config.gain_controller1.enabled);
+  EXPECT_EQ(config.gain_controller1.analog_gain_controller.enabled,
+            adjusted_config.gain_controller1.analog_gain_controller.enabled);
+  EXPECT_EQ(config.gain_controller2.enabled,
+            adjusted_config.gain_controller2.enabled);
+  EXPECT_EQ(config.gain_controller2.adaptive_digital.enabled,
+            adjusted_config.gain_controller2.adaptive_digital.enabled);
+  EXPECT_FALSE(
+      adjusted_config.gain_controller2.input_volume_controller.enabled);
+
+  EXPECT_THAT(adjusted_config.ToString(), ::testing::StrEq(config.ToString()));
+}
+
+TEST(AudioProcessingImplInputVolumeControllerExperimentTest,
+     ConfigNotAdjustedWhenExperimentEnabledAndHybridAgcNotEnabled) {
+  webrtc::test::ScopedFieldTrials field_trials(
+      "WebRTC-Audio-InputVolumeControllerExperiment/"
+      "Enabled,"
+      "enable_clipping_predictor:true,"
+      "clipped_level_min:20,"
+      "clipped_level_step:30,"
+      "clipped_ratio_threshold:0.4,"
+      "clipped_wait_frames:50,"
+      "target_range_max_dbfs:-6,"
+      "target_range_min_dbfs:-70,"
+      "update_input_volume_wait_frames:80,"
+      "speech_probability_threshold:0.9,"
+      "speech_ratio_threshold:1.0/");
+
+  AudioProcessingBuilderForTesting apm_builder;
+
+  // Set a config with hybrid AGC analog not enabled.
+  AudioProcessing::Config config;
+  config.gain_controller1.enabled = false;
+  config.gain_controller1.analog_gain_controller.enabled = true;
+  config.gain_controller1.analog_gain_controller.enable_digital_adaptive =
+      false;
+  config.gain_controller2.enabled = true;
+  config.gain_controller2.adaptive_digital.enabled = true;
+  config.gain_controller1.mode =
+      AudioProcessing::Config::GainController1::kAdaptiveAnalog;
+
+  EXPECT_FALSE(config.gain_controller2.input_volume_controller.enabled);
+
+  apm_builder.SetConfig(config);
+
+  auto apm = apm_builder.Create();
+  auto adjusted_config = apm->GetConfig();
+
+  EXPECT_EQ(config.gain_controller1.enabled,
+            adjusted_config.gain_controller1.enabled);
+  EXPECT_EQ(config.gain_controller1.analog_gain_controller.enabled,
+            adjusted_config.gain_controller1.analog_gain_controller.enabled);
+  EXPECT_EQ(config.gain_controller2.enabled,
+            adjusted_config.gain_controller2.enabled);
+  EXPECT_EQ(config.gain_controller2.adaptive_digital.enabled,
+            adjusted_config.gain_controller2.adaptive_digital.enabled);
+  EXPECT_FALSE(
+      adjusted_config.gain_controller2.input_volume_controller.enabled);
+
+  EXPECT_THAT(adjusted_config.ToString(), ::testing::StrEq(config.ToString()));
+}
+
+TEST(AudioProcessingImplInputVolumeControllerExperimentTest,
+     ConfigNotAdjustedWhenExperimentNotEnabledAndAgc1AnalogEnabled) {
+  AudioProcessingBuilderForTesting apm_builder;
+
+  // Set a config with analog AGC1 analog enabled.
+  AudioProcessing::Config config;
+  config.gain_controller1.enabled = true;
+  config.gain_controller1.analog_gain_controller.enabled = true;
+  config.gain_controller1.analog_gain_controller.enable_digital_adaptive = true;
+  config.gain_controller2.enabled = false;
+  config.gain_controller1.mode =
+      AudioProcessing::Config::GainController1::kAdaptiveAnalog;
+
+  EXPECT_FALSE(config.gain_controller2.input_volume_controller.enabled);
+
+  apm_builder.SetConfig(config);
+
+  auto apm = apm_builder.Create();
+  auto adjusted_config = apm->GetConfig();
+
+  EXPECT_EQ(config.gain_controller1.enabled,
+            adjusted_config.gain_controller1.enabled);
+  EXPECT_EQ(config.gain_controller1.analog_gain_controller.enabled,
+            adjusted_config.gain_controller1.analog_gain_controller.enabled);
+  EXPECT_EQ(config.gain_controller2.enabled,
+            adjusted_config.gain_controller2.enabled);
+  EXPECT_EQ(config.gain_controller2.adaptive_digital.enabled,
+            adjusted_config.gain_controller2.adaptive_digital.enabled);
+  EXPECT_FALSE(
+      adjusted_config.gain_controller2.input_volume_controller.enabled);
+
+  EXPECT_THAT(adjusted_config.ToString(), ::testing::StrEq(config.ToString()));
+}
+
+TEST(AudioProcessingImplInputVolumeControllerExperimentTest,
+     ConfigNotAdjustedWhenExperimentNotEnabledAndHybridAgcEnabled) {
+  AudioProcessingBuilderForTesting apm_builder;
+
+  // Set a config with hybrid AGC enabled.
+  AudioProcessing::Config config;
+  config.gain_controller1.enabled = true;
+  config.gain_controller1.analog_gain_controller.enabled = true;
+  config.gain_controller1.analog_gain_controller.enable_digital_adaptive =
+      false;
+  config.gain_controller2.enabled = true;
+  config.gain_controller2.adaptive_digital.enabled = true;
+  config.gain_controller1.mode =
+      AudioProcessing::Config::GainController1::kAdaptiveAnalog;
+
+  EXPECT_FALSE(config.gain_controller2.input_volume_controller.enabled);
+
+  apm_builder.SetConfig(config);
+
+  auto apm = apm_builder.Create();
+  auto adjusted_config = apm->GetConfig();
+
+  EXPECT_EQ(config.gain_controller1.enabled,
+            adjusted_config.gain_controller1.enabled);
+  EXPECT_EQ(config.gain_controller1.analog_gain_controller.enabled,
+            adjusted_config.gain_controller1.analog_gain_controller.enabled);
+  EXPECT_EQ(config.gain_controller2.enabled,
+            adjusted_config.gain_controller2.enabled);
+  EXPECT_EQ(config.gain_controller2.adaptive_digital.enabled,
+            adjusted_config.gain_controller2.adaptive_digital.enabled);
+  EXPECT_FALSE(
+      adjusted_config.gain_controller2.input_volume_controller.enabled);
+
+  EXPECT_THAT(adjusted_config.ToString(), ::testing::StrEq(config.ToString()));
+}
+
 }  // namespace webrtc