Refactoring of the analog AGC functionality to add multichannel support

This CL refactors the analog AGC functionality. In particular it:
-Breaks then tight dependency between the analog AGC and the digital
AGC implementation.
-Removes the complicated callback interface for reporting the analog
level and replaces it with an int.

Bug: webrtc:10859
Change-Id: I3572d60ab98edebbcffa25af64cc74c66f9868fc
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/159039
Reviewed-by: Sam Zackrisson <saza@webrtc.org>
Commit-Queue: Per Åhgren <peah@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#29838}
diff --git a/modules/audio_processing/audio_processing_impl.cc b/modules/audio_processing/audio_processing_impl.cc
index fad02a0..bfa2e0d 100644
--- a/modules/audio_processing/audio_processing_impl.cc
+++ b/modules/audio_processing/audio_processing_impl.cc
@@ -323,18 +323,20 @@
       submodules_(std::move(capture_post_processor),
                   std::move(render_pre_processor),
                   std::move(echo_detector),
-                  std::move(capture_analyzer)),
-      constants_(config.Get<ExperimentalAgc>().startup_min_volume,
-                 config.Get<ExperimentalAgc>().clipped_level_min,
+                  std::move(capture_analyzer),
+                  config.Get<ExperimentalAgc>().startup_min_volume,
+                  config.Get<ExperimentalAgc>().clipped_level_min,
 #if defined(WEBRTC_ANDROID) || defined(WEBRTC_IOS)
-                 /* enabled= */ false,
-                 /* enabled_agc2_level_estimator= */ false,
-                 /* digital_adaptive_disabled= */ false,
+                  /* enabled= */ false,
+                  /* enabled_agc2_level_estimator= */ false,
+                  /* digital_adaptive_disabled= */ false
 #else
-                 config.Get<ExperimentalAgc>().enabled,
-                 config.Get<ExperimentalAgc>().enabled_agc2_level_estimator,
-                 config.Get<ExperimentalAgc>().digital_adaptive_disabled,
+                  config.Get<ExperimentalAgc>().enabled,
+                  config.Get<ExperimentalAgc>().enabled_agc2_level_estimator,
+                  config.Get<ExperimentalAgc>().digital_adaptive_disabled
 #endif
+                  ),
+      constants_(config.Get<ExperimentalAgc>().clipped_level_min,
                  !field_trial::IsEnabled(
                      "WebRTC-ApmExperimentalMultiChannelRenderKillSwitch"),
                  !field_trial::IsEnabled(
@@ -359,8 +361,6 @@
       static_cast<bool>(echo_control_factory_);
 
   submodules_.gain_control.reset(new GainControlImpl());
-  submodules_.gain_control_for_experimental_agc.reset(
-      new GainControlForExperimentalAgc(submodules_.gain_control.get()));
 
   // If no echo detector is injected, use the ResidualEchoDetector.
   if (!submodules_.echo_detector) {
@@ -375,13 +375,7 @@
   SetExtraOptions(config);
 }
 
-AudioProcessingImpl::~AudioProcessingImpl() {
-  // Depends on gain_control_ and
-  // submodules_.gain_control_for_experimental_agc.
-  submodules_.agc_manager.reset();
-  // Depends on gain_control_.
-  submodules_.gain_control_for_experimental_agc.reset();
-}
+AudioProcessingImpl::~AudioProcessingImpl() = default;
 
 int AudioProcessingImpl::Initialize() {
   // Run in a single-threaded manner during initialization.
@@ -484,18 +478,11 @@
 
   submodules_.gain_control->Initialize(num_proc_channels(),
                                        proc_sample_rate_hz());
-  if (constants_.use_experimental_agc) {
-    if (!submodules_.agc_manager.get()) {
-      submodules_.agc_manager.reset(new AgcManagerDirect(
-          submodules_.gain_control.get(),
-          submodules_.gain_control_for_experimental_agc.get(),
-          constants_.agc_startup_min_volume, constants_.agc_clipped_level_min,
-          constants_.use_experimental_agc_agc2_level_estimation,
-          constants_.use_experimental_agc_agc2_digital_adaptive));
-    }
+  if (submodules_.agc_manager) {
     submodules_.agc_manager->Initialize();
+    submodules_.agc_manager->ConfigureGainControl(
+        submodules_.gain_control.get());
     submodules_.agc_manager->SetCaptureMuted(capture_.output_will_be_muted);
-    submodules_.gain_control_for_experimental_agc->Initialize();
   }
   InitializeTransient();
   InitializeHighPassFilter();
@@ -695,34 +682,25 @@
 
 void AudioProcessingImpl::ApplyAgc1Config(
     const Config::GainController1& config) {
-  GainControl* agc = agc1();
-  int error = agc->Enable(config.enabled);
+  int error = submodules_.gain_control->Enable(config.enabled);
   RTC_DCHECK_EQ(kNoError, error);
-  error = agc->set_mode(Agc1ConfigModeToInterfaceMode(config.mode));
-  RTC_DCHECK_EQ(kNoError, error);
-  error = agc->set_target_level_dbfs(config.target_level_dbfs);
-  RTC_DCHECK_EQ(kNoError, error);
-  error = agc->set_compression_gain_db(config.compression_gain_db);
-  RTC_DCHECK_EQ(kNoError, error);
-  error = agc->enable_limiter(config.enable_limiter);
-  RTC_DCHECK_EQ(kNoError, error);
-  error = agc->set_analog_level_limits(config.analog_level_minimum,
-                                       config.analog_level_maximum);
-  RTC_DCHECK_EQ(kNoError, error);
-}
 
-GainControl* AudioProcessingImpl::agc1() {
-  if (constants_.use_experimental_agc) {
-    return submodules_.gain_control_for_experimental_agc.get();
+  if (!submodules_.agc_manager) {
+    error = submodules_.gain_control->set_mode(
+        Agc1ConfigModeToInterfaceMode(config.mode));
+    RTC_DCHECK_EQ(kNoError, error);
+    error = submodules_.gain_control->set_target_level_dbfs(
+        config.target_level_dbfs);
+    RTC_DCHECK_EQ(kNoError, error);
+    error = submodules_.gain_control->set_compression_gain_db(
+        config.compression_gain_db);
+    RTC_DCHECK_EQ(kNoError, error);
+    error = submodules_.gain_control->enable_limiter(config.enable_limiter);
+    RTC_DCHECK_EQ(kNoError, error);
+    error = submodules_.gain_control->set_analog_level_limits(
+        config.analog_level_minimum, config.analog_level_maximum);
+    RTC_DCHECK_EQ(kNoError, error);
   }
-  return submodules_.gain_control.get();
-}
-
-const GainControl* AudioProcessingImpl::agc1() const {
-  if (constants_.use_experimental_agc) {
-    return submodules_.gain_control_for_experimental_agc.get();
-  }
-  return submodules_.gain_control.get();
 }
 
 void AudioProcessingImpl::SetExtraOptions(const webrtc::Config& config) {
@@ -926,12 +904,15 @@
         // TODO(bugs.chromium.org/9138): Log setting handling by Aec Dump.
         break;
       case RuntimeSetting::Type::kCaptureCompressionGain: {
-        float value;
-        setting.GetFloat(&value);
-        int int_value = static_cast<int>(value + .5f);
-        config_.gain_controller1.compression_gain_db = int_value;
-        int error = agc1()->set_compression_gain_db(int_value);
-        RTC_DCHECK_EQ(kNoError, error);
+        if (!submodules_.agc_manager) {
+          float value;
+          setting.GetFloat(&value);
+          int int_value = static_cast<int>(value + .5f);
+          config_.gain_controller1.compression_gain_db = int_value;
+          int error =
+              submodules_.gain_control->set_compression_gain_db(int_value);
+          RTC_DCHECK_EQ(kNoError, error);
+        }
         break;
       }
       case RuntimeSetting::Type::kCaptureFixedPostGain: {
@@ -1023,7 +1004,7 @@
     }
   }
 
-  if (!constants_.use_experimental_agc) {
+  if (!submodules_.agc_manager) {
     GainControlImpl::PackRenderAudioBuffer(audio, &agc_render_queue_buffer_);
     // Insert the samples into the queue.
     if (!agc_render_signal_queue_->Insert(&agc_render_queue_buffer_)) {
@@ -1255,7 +1236,7 @@
 
   if (submodules_.echo_controller) {
     // Detect and flag any change in the analog gain.
-    int analog_mic_level = agc1()->stream_analog_level();
+    int analog_mic_level = recommended_stream_analog_level();
     capture_.echo_path_gain_change =
         capture_.prev_analog_mic_level != analog_mic_level &&
         capture_.prev_analog_mic_level != -1;
@@ -1281,8 +1262,7 @@
     submodules_.echo_controller->AnalyzeCapture(capture_buffer);
   }
 
-  if (constants_.use_experimental_agc &&
-      submodules_.gain_control->is_enabled()) {
+  if (submodules_.agc_manager && submodules_.gain_control->is_enabled()) {
     submodules_.agc_manager->AnalyzePreProcess(
         capture_buffer->channels_const(), capture_buffer->num_channels(),
         capture_nonlocked_.capture_processing_format.num_frames());
@@ -1370,11 +1350,11 @@
     capture_.stats.voice_detected = absl::nullopt;
   }
 
-  if (constants_.use_experimental_agc &&
-      submodules_.gain_control->is_enabled()) {
+  if (submodules_.agc_manager && submodules_.gain_control->is_enabled()) {
     submodules_.agc_manager->Process(
         capture_buffer->split_bands_const_f(0)[kBand0To8kHz],
-        capture_buffer->num_frames_per_band(), capture_nonlocked_.split_rate);
+        capture_buffer->num_frames_per_band(), capture_nonlocked_.split_rate,
+        submodules_.gain_control.get());
   }
   // TODO(peah): Add reporting from AEC3 whether there is echo.
   RETURN_ON_ERR(submodules_.gain_control->ProcessCaptureAudio(
@@ -1428,7 +1408,7 @@
 
   if (config_.gain_controller2.enabled) {
     submodules_.gain_controller2->NotifyAnalogLevel(
-        agc1()->stream_analog_level());
+        recommended_stream_analog_level());
     submodules_.gain_controller2->Process(capture_buffer);
   }
 
@@ -1455,6 +1435,12 @@
                                 levels.peak, 1, RmsLevel::kMinLevelDb, 64);
   }
 
+  if (submodules_.agc_manager) {
+    int level = recommended_stream_analog_level();
+    data_dumper_->DumpRaw("experimental_gain_control_stream_analog_level", 1,
+                          &level);
+  }
+
   capture_.was_stream_delay_set = false;
   return kNoError;
 }
@@ -1678,13 +1664,23 @@
 
 void AudioProcessingImpl::set_stream_analog_level(int level) {
   rtc::CritScope cs_capture(&crit_capture_);
-  int error = agc1()->set_stream_analog_level(level);
-  RTC_DCHECK_EQ(kNoError, error);
+
+  if (submodules_.agc_manager) {
+    submodules_.agc_manager->set_stream_analog_level(level);
+    data_dumper_->DumpRaw("experimental_gain_control_set_stream_analog_level",
+                          1, &level);
+  } else {
+    int error = submodules_.gain_control->set_stream_analog_level(level);
+    RTC_DCHECK_EQ(kNoError, error);
+  }
 }
 
 int AudioProcessingImpl::recommended_stream_analog_level() const {
   rtc::CritScope cs_capture(&crit_capture_);
-  return agc1()->stream_analog_level();
+  if (submodules_.agc_manager) {
+    return submodules_.agc_manager->stream_analog_level();
+  }
+  return submodules_.gain_control->stream_analog_level();
 }
 
 void AudioProcessingImpl::AttachAecDump(std::unique_ptr<AecDump> aec_dump) {
@@ -2050,7 +2046,7 @@
   apm_config.agc_mode = static_cast<int>(submodules_.gain_control->mode());
   apm_config.agc_limiter_enabled =
       submodules_.gain_control->is_limiter_enabled();
-  apm_config.noise_robust_agc_enabled = constants_.use_experimental_agc;
+  apm_config.noise_robust_agc_enabled = !!submodules_.agc_manager;
 
   apm_config.hpf_enabled = config_.high_pass_filter.enabled;
 
@@ -2120,7 +2116,7 @@
       submodules_.echo_cancellation
           ? submodules_.echo_cancellation->stream_drift_samples()
           : 0;
-  audio_proc_state.level = agc1()->stream_analog_level();
+  audio_proc_state.level = recommended_stream_analog_level();
   audio_proc_state.keypress = capture_.key_pressed;
   aec_dump_->AddAudioProcessingState(audio_proc_state);
 }