Allow setting the AGC2 fixed gain during runtime

This CL extends the supported runtime settings in
APM to also comprise the AGC2 fixed gain.
The CL was originally created by Adam Whiteside.

Bug: webrtc:10574
Change-Id: I79b3d6501f1e202b66a9b6018f8a493a56b01f62
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/134101
Commit-Queue: Per Åhgren <peah@webrtc.org>
Reviewed-by: Sam Zackrisson <saza@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#27782}
diff --git a/modules/audio_processing/aec_dump/aec_dump_impl.cc b/modules/audio_processing/aec_dump/aec_dump_impl.cc
index a915222..e4ee872 100644
--- a/modules/audio_processing/aec_dump/aec_dump_impl.cc
+++ b/modules/audio_processing/aec_dump/aec_dump_impl.cc
@@ -192,6 +192,11 @@
       // Runtime AGC1 compression gain is ignored.
       // TODO(http://bugs.webrtc.org/10432): Store compression gain in aecdumps.
       break;
+    case AudioProcessing::RuntimeSetting::Type::kCaptureFixedPostGain:
+      float x;
+      runtime_setting.GetFloat(&x);
+      setting->set_capture_fixed_post_gain(x);
+      break;
     case AudioProcessing::RuntimeSetting::Type::kNotSpecified:
       RTC_NOTREACHED();
       break;
diff --git a/modules/audio_processing/audio_processing_impl.cc b/modules/audio_processing/audio_processing_impl.cc
index 6950623..a796ed6 100644
--- a/modules/audio_processing/audio_processing_impl.cc
+++ b/modules/audio_processing/audio_processing_impl.cc
@@ -187,8 +187,7 @@
   changed |= (noise_suppressor_enabled != noise_suppressor_enabled_);
   changed |=
       (adaptive_gain_controller_enabled != adaptive_gain_controller_enabled_);
-  changed |=
-      (gain_controller2_enabled != gain_controller2_enabled_);
+  changed |= (gain_controller2_enabled != gain_controller2_enabled_);
   changed |= (pre_amplifier_enabled_ != pre_amplifier_enabled);
   changed |= (echo_controller_enabled != echo_controller_enabled_);
   changed |= (level_estimator_enabled != level_estimator_enabled_);
@@ -858,6 +857,7 @@
       return;
     case RuntimeSetting::Type::kCapturePreGain:
     case RuntimeSetting::Type::kCaptureCompressionGain:
+    case RuntimeSetting::Type::kCaptureFixedPostGain:
       capture_runtime_settings_enqueuer_.Enqueue(setting);
       return;
   }
@@ -993,6 +993,16 @@
         RTC_DCHECK_EQ(kNoError, error);
         break;
       }
+      case RuntimeSetting::Type::kCaptureFixedPostGain: {
+        if (config_.gain_controller2.enabled) {
+          float value;
+          setting.GetFloat(&value);
+          config_.gain_controller2.fixed_digital.gain_db = value;
+          private_submodules_->gain_controller2->ApplyConfig(
+              config_.gain_controller2);
+        }
+        break;
+      }
       case RuntimeSetting::Type::kCustomRenderProcessingRuntimeSetting:
         RTC_NOTREACHED();
         break;
@@ -1017,6 +1027,7 @@
         break;
       case RuntimeSetting::Type::kCapturePreGain:          // fall-through
       case RuntimeSetting::Type::kCaptureCompressionGain:  // fall-through
+      case RuntimeSetting::Type::kCaptureFixedPostGain:    // fall-through
       case RuntimeSetting::Type::kNotSpecified:
         RTC_NOTREACHED();
         break;
diff --git a/modules/audio_processing/audio_processing_unittest.cc b/modules/audio_processing/audio_processing_unittest.cc
index ec2c58b..7015042 100644
--- a/modules/audio_processing/audio_processing_unittest.cc
+++ b/modules/audio_processing/audio_processing_unittest.cc
@@ -2349,6 +2349,21 @@
 #endif
 }
 
+TEST(RuntimeSettingTest, TestCaptureFixedPostGain) {
+  using Type = AudioProcessing::RuntimeSetting::Type;
+  {
+    auto s = AudioProcessing::RuntimeSetting::CreateCaptureFixedPostGain(1.25f);
+    EXPECT_EQ(Type::kCaptureFixedPostGain, s.type());
+    float v;
+    s.GetFloat(&v);
+    EXPECT_EQ(1.25f, v);
+  }
+
+#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
+  EXPECT_DEATH(AudioProcessing::RuntimeSetting::CreateCapturePreGain(0.1f), "");
+#endif
+}
+
 TEST(RuntimeSettingTest, TestUsageWithSwapQueue) {
   SwapQueue<AudioProcessing::RuntimeSetting> q(1);
   auto s = AudioProcessing::RuntimeSetting();
diff --git a/modules/audio_processing/debug.proto b/modules/audio_processing/debug.proto
index 40bd5d5..2af7c81 100644
--- a/modules/audio_processing/debug.proto
+++ b/modules/audio_processing/debug.proto
@@ -83,6 +83,7 @@
 message RuntimeSetting {
   optional float capture_pre_gain = 1;
   optional float custom_render_processing_setting = 2;
+  optional float capture_fixed_post_gain = 3;
 }
 
 message Event {
diff --git a/modules/audio_processing/include/audio_processing.h b/modules/audio_processing/include/audio_processing.h
index 1d421f5..4477e81 100644
--- a/modules/audio_processing/include/audio_processing.h
+++ b/modules/audio_processing/include/audio_processing.h
@@ -391,6 +391,7 @@
       kNotSpecified,
       kCapturePreGain,
       kCaptureCompressionGain,
+      kCaptureFixedPostGain,
       kCustomRenderProcessingRuntimeSetting
     };
 
@@ -410,6 +411,14 @@
       return {Type::kCaptureCompressionGain, static_cast<float>(gain_db)};
     }
 
+    // Corresponds to Config::GainController2::fixed_digital::gain_db, but for
+    // runtime configuration.
+    static RuntimeSetting CreateCaptureFixedPostGain(float gain_db) {
+      RTC_DCHECK_GE(gain_db, 0.f);
+      RTC_DCHECK_LE(gain_db, 90.f);
+      return {Type::kCaptureFixedPostGain, gain_db};
+    }
+
     static RuntimeSetting CreateCustomRenderSetting(float payload) {
       return {Type::kCustomRenderProcessingRuntimeSetting, payload};
     }
diff --git a/modules/audio_processing/test/aec_dump_based_simulator.cc b/modules/audio_processing/test/aec_dump_based_simulator.cc
index 0852fe0..e52dfcf 100644
--- a/modules/audio_processing/test/aec_dump_based_simulator.cc
+++ b/modules/audio_processing/test/aec_dump_based_simulator.cc
@@ -8,12 +8,13 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
+#include "modules/audio_processing/test/aec_dump_based_simulator.h"
+
 #include <iostream>
 
 #include "absl/memory/memory.h"
 #include "modules/audio_processing/echo_cancellation_impl.h"
 #include "modules/audio_processing/echo_control_mobile_impl.h"
-#include "modules/audio_processing/test/aec_dump_based_simulator.h"
 #include "modules/audio_processing/test/protobuf_utils.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/logging.h"
@@ -393,6 +394,19 @@
       }
     }
 
+    if (settings_.use_agc2) {
+      bool enable = *settings_.use_agc2;
+      apm_config.gain_controller2.enabled = enable;
+      if (settings_.agc2_fixed_gain_db) {
+        apm_config.gain_controller2.fixed_digital.gain_db =
+            *settings_.agc2_fixed_gain_db;
+      }
+      if (settings_.use_verbose_logging) {
+        std::cout << " agc2_enabled: " << (enable ? "true" : "false")
+                  << std::endl;
+      }
+    }
+
     // TODO(peah): Add support for controlling the Experimental AGC from the
     // command line.
     if (msg.has_noise_robust_agc_enabled()) {
@@ -447,10 +461,14 @@
                               ? *settings_.use_pre_amplifier
                               : msg.pre_amplifier_enabled();
       apm_config.pre_amplifier.enabled = enable;
-      if (settings_.pre_amplifier_gain_factor) {
-        apm_config.pre_amplifier.fixed_gain_factor =
-            *settings_.pre_amplifier_gain_factor;
-      }
+    }
+
+    if (msg.has_pre_amplifier_fixed_gain_factor() ||
+        settings_.pre_amplifier_gain_factor) {
+      const float gain = settings_.pre_amplifier_gain_factor
+                             ? *settings_.pre_amplifier_gain_factor
+                             : msg.pre_amplifier_fixed_gain_factor();
+      apm_config.pre_amplifier.fixed_gain_factor = gain;
     }
 
     if (settings_.use_verbose_logging && msg.has_experiments_description() &&
@@ -550,12 +568,22 @@
 void AecDumpBasedSimulator::HandleMessage(
     const webrtc::audioproc::RuntimeSetting& msg) {
   RTC_CHECK(ap_.get());
-  // Handle capture pre-gain runtime setting only if not overridden.
-  if ((!settings_.use_pre_amplifier || !(*settings_.use_pre_amplifier)) &&
-      !settings_.pre_amplifier_gain_factor) {
-    ap_->SetRuntimeSetting(
-        AudioProcessing::RuntimeSetting::CreateCapturePreGain(
-            msg.capture_pre_gain()));
+  if (msg.has_capture_pre_gain()) {
+    // Handle capture pre-gain runtime setting only if not overridden.
+    if ((!settings_.use_pre_amplifier || *settings_.use_pre_amplifier) &&
+        !settings_.pre_amplifier_gain_factor) {
+      ap_->SetRuntimeSetting(
+          AudioProcessing::RuntimeSetting::CreateCapturePreGain(
+              msg.capture_pre_gain()));
+    }
+  } else if (msg.has_capture_fixed_post_gain()) {
+    // Handle capture fixed-post-gain runtime setting only if not overridden.
+    if ((!settings_.use_agc2 || *settings_.use_agc2) &&
+        !settings_.agc2_fixed_gain_db) {
+      ap_->SetRuntimeSetting(
+          AudioProcessing::RuntimeSetting::CreateCaptureFixedPostGain(
+              msg.capture_fixed_post_gain()));
+    }
   }
 }
 
diff --git a/modules/audio_processing/test/audio_processing_simulator.cc b/modules/audio_processing/test/audio_processing_simulator.cc
index 277b1b3..a212125 100644
--- a/modules/audio_processing/test/audio_processing_simulator.cc
+++ b/modules/audio_processing/test/audio_processing_simulator.cc
@@ -373,8 +373,10 @@
   }
   if (settings_.use_agc2) {
     apm_config.gain_controller2.enabled = *settings_.use_agc2;
-    apm_config.gain_controller2.fixed_digital.gain_db =
-        settings_.agc2_fixed_gain_db;
+    if (settings_.agc2_fixed_gain_db) {
+      apm_config.gain_controller2.fixed_digital.gain_db =
+          *settings_.agc2_fixed_gain_db;
+    }
     if (settings_.agc2_use_adaptive_gain) {
       apm_config.gain_controller2.adaptive_digital.enabled =
           *settings_.agc2_use_adaptive_gain;
diff --git a/modules/audio_processing/test/audio_processing_simulator.h b/modules/audio_processing/test/audio_processing_simulator.h
index 60ee6ea..7800afa 100644
--- a/modules/audio_processing/test/audio_processing_simulator.h
+++ b/modules/audio_processing/test/audio_processing_simulator.h
@@ -75,7 +75,7 @@
   absl::optional<bool> use_agc_limiter;
   absl::optional<int> agc_compression_gain;
   absl::optional<bool> agc2_use_adaptive_gain;
-  float agc2_fixed_gain_db;
+  absl::optional<float> agc2_fixed_gain_db;
   AudioProcessing::Config::GainController2::LevelEstimator
       agc2_adaptive_level_estimator;
   absl::optional<float> pre_amplifier_gain_factor;
diff --git a/modules/audio_processing/test/audioproc_float_impl.cc b/modules/audio_processing/test/audioproc_float_impl.cc
index f9cefce..6b94a07 100644
--- a/modules/audio_processing/test/audioproc_float_impl.cc
+++ b/modules/audio_processing/test/audioproc_float_impl.cc
@@ -8,6 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
+#include "modules/audio_processing/test/audioproc_float_impl.h"
+
 #include <string.h>
 
 #include <iostream>
@@ -20,7 +22,6 @@
 #include "modules/audio_processing/include/audio_processing.h"
 #include "modules/audio_processing/test/aec_dump_based_simulator.h"
 #include "modules/audio_processing/test/audio_processing_simulator.h"
-#include "modules/audio_processing/test/audioproc_float_impl.h"
 #include "modules/audio_processing/test/wav_based_simulator.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/flags.h"
@@ -149,10 +150,12 @@
 WEBRTC_DEFINE_int(agc_compression_gain,
                   kParameterNotSpecifiedValue,
                   "Specify the AGC compression gain (0-90)");
-WEBRTC_DEFINE_float(agc2_enable_adaptive_gain,
+WEBRTC_DEFINE_int(agc2_enable_adaptive_gain,
+                  kParameterNotSpecifiedValue,
+                  "Activate (1) or deactivate(0) the AGC2 adaptive gain");
+WEBRTC_DEFINE_float(agc2_fixed_gain_db,
                     kParameterNotSpecifiedValue,
-                    "Activate (1) or deactivate(0) the AGC2 adaptive gain");
-WEBRTC_DEFINE_float(agc2_fixed_gain_db, 0.f, "AGC2 fixed gain (dB) to apply");
+                    "AGC2 fixed gain (dB) to apply");
 
 std::vector<std::string> GetAgc2AdaptiveLevelEstimatorNames() {
   return {"RMS", "peak"};
@@ -344,7 +347,7 @@
                         &settings.agc_compression_gain);
   SetSettingIfFlagSet(FLAG_agc2_enable_adaptive_gain,
                       &settings.agc2_use_adaptive_gain);
-  settings.agc2_fixed_gain_db = FLAG_agc2_fixed_gain_db;
+  SetSettingIfSpecified(FLAG_agc2_fixed_gain_db, &settings.agc2_fixed_gain_db);
   settings.agc2_adaptive_level_estimator =
       MapAgc2AdaptiveLevelEstimator(FLAG_agc2_adaptive_level_estimator);
   SetSettingIfSpecified(FLAG_pre_amplifier_gain_factor,
@@ -454,9 +457,8 @@
       "Error: --agc_compression_gain must be specified between 0 and 90.\n");
 
   ReportConditionalErrorAndExit(
-      settings.use_agc2 && *settings.use_agc2 &&
-          ((settings.agc2_fixed_gain_db) < 0 ||
-           (settings.agc2_fixed_gain_db) > 90),
+      settings.agc2_fixed_gain_db && ((*settings.agc2_fixed_gain_db) < 0 ||
+                                      (*settings.agc2_fixed_gain_db) > 90),
       "Error: --agc2_fixed_gain_db must be specified between 0 and 90.\n");
 
   ReportConditionalErrorAndExit(
diff --git a/modules/audio_processing/test/runtime_setting_util.cc b/modules/audio_processing/test/runtime_setting_util.cc
index 104b600..bc5f700 100644
--- a/modules/audio_processing/test/runtime_setting_util.cc
+++ b/modules/audio_processing/test/runtime_setting_util.cc
@@ -9,6 +9,7 @@
  */
 
 #include "modules/audio_processing/test/runtime_setting_util.h"
+
 #include "rtc_base/checks.h"
 
 namespace webrtc {
@@ -17,9 +18,19 @@
                           const webrtc::audioproc::RuntimeSetting& setting) {
   RTC_CHECK(apm);
   // TODO(bugs.webrtc.org/9138): Add ability to handle different types
-  // of settings. Currently only CapturePreGain is supported.
-  RTC_CHECK(setting.has_capture_pre_gain());
-  apm->SetRuntimeSetting(AudioProcessing::RuntimeSetting::CreateCapturePreGain(
-      setting.capture_pre_gain()));
+  // of settings. Currently only CapturePreGain and CaptureFixedPostGain are
+  // supported.
+  RTC_CHECK(setting.has_capture_pre_gain() ||
+            setting.has_capture_fixed_post_gain());
+
+  if (setting.has_capture_pre_gain()) {
+    apm->SetRuntimeSetting(
+        AudioProcessing::RuntimeSetting::CreateCapturePreGain(
+            setting.capture_pre_gain()));
+  } else if (setting.has_capture_fixed_post_gain()) {
+    apm->SetRuntimeSetting(
+        AudioProcessing::RuntimeSetting::CreateCaptureFixedPostGain(
+            setting.capture_fixed_post_gain()));
+  }
 }
 }  // namespace webrtc