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/BUILD.gn b/modules/audio_processing/BUILD.gn
index 57b49b2..9e6ee75 100644
--- a/modules/audio_processing/BUILD.gn
+++ b/modules/audio_processing/BUILD.gn
@@ -124,8 +124,6 @@
     "echo_detector/moving_max.h",
     "echo_detector/normalized_covariance_estimator.cc",
     "echo_detector/normalized_covariance_estimator.h",
-    "gain_control_for_experimental_agc.cc",
-    "gain_control_for_experimental_agc.h",
     "gain_control_impl.cc",
     "gain_control_impl.h",
     "gain_controller2.cc",
diff --git a/modules/audio_processing/agc/BUILD.gn b/modules/audio_processing/agc/BUILD.gn
index 05eb42d..dc93ebe 100644
--- a/modules/audio_processing/agc/BUILD.gn
+++ b/modules/audio_processing/agc/BUILD.gn
@@ -36,6 +36,7 @@
     "../../../system_wrappers:metrics",
     "../agc2:level_estimation_agc",
     "../vad",
+    "//third_party/abseil-cpp/absl/types:optional",
   ]
 }
 
diff --git a/modules/audio_processing/agc/agc_manager_direct.cc b/modules/audio_processing/agc/agc_manager_direct.cc
index 13b902f..2f453f4 100644
--- a/modules/audio_processing/agc/agc_manager_direct.cc
+++ b/modules/audio_processing/agc/agc_manager_direct.cc
@@ -116,31 +116,6 @@
   return new_level;
 }
 
-int InitializeGainControl(GainControl* gain_control,
-                          bool disable_digital_adaptive) {
-  if (gain_control->set_mode(GainControl::kFixedDigital) != 0) {
-    RTC_LOG(LS_ERROR) << "set_mode(GainControl::kFixedDigital) failed.";
-    return -1;
-  }
-  const int target_level_dbfs = disable_digital_adaptive ? 0 : 2;
-  if (gain_control->set_target_level_dbfs(target_level_dbfs) != 0) {
-    RTC_LOG(LS_ERROR) << "set_target_level_dbfs() failed.";
-    return -1;
-  }
-  const int compression_gain_db =
-      disable_digital_adaptive ? 0 : kDefaultCompressionGain;
-  if (gain_control->set_compression_gain_db(compression_gain_db) != 0) {
-    RTC_LOG(LS_ERROR) << "set_compression_gain_db() failed.";
-    return -1;
-  }
-  const bool enable_limiter = !disable_digital_adaptive;
-  if (gain_control->enable_limiter(enable_limiter) != 0) {
-    RTC_LOG(LS_ERROR) << "enable_limiter() failed.";
-    return -1;
-  }
-  return 0;
-}
-
 // Returns the proportion of samples in the buffer which are at full-scale
 // (and presumably clipped).
 float ComputeClippedRatio(const float* const* audio,
@@ -164,29 +139,18 @@
 }  // namespace
 
 AgcManagerDirect::AgcManagerDirect(Agc* agc,
-                                   GainControl* gctrl,
-                                   VolumeCallbacks* volume_callbacks,
                                    int startup_min_level,
                                    int clipped_level_min)
-    : AgcManagerDirect(gctrl,
-                       volume_callbacks,
-                       startup_min_level,
-                       clipped_level_min,
-                       false,
-                       false) {
+    : AgcManagerDirect(startup_min_level, clipped_level_min, false, false) {
   RTC_DCHECK(agc_);
   agc_.reset(agc);
 }
 
-AgcManagerDirect::AgcManagerDirect(GainControl* gctrl,
-                                   VolumeCallbacks* volume_callbacks,
-                                   int startup_min_level,
+AgcManagerDirect::AgcManagerDirect(int startup_min_level,
                                    int clipped_level_min,
                                    bool use_agc2_level_estimation,
                                    bool disable_digital_adaptive)
     : data_dumper_(new ApmDataDumper(instance_counter_)),
-      gctrl_(gctrl),
-      volume_callbacks_(volume_callbacks),
       frames_since_clipped_(kClippedWaitFrames),
       level_(0),
       max_level_(kMaxMicLevel),
@@ -211,7 +175,7 @@
 
 AgcManagerDirect::~AgcManagerDirect() {}
 
-int AgcManagerDirect::Initialize() {
+void AgcManagerDirect::Initialize() {
   RTC_DLOG(LS_INFO) << "AgcManagerDirect::Initialize";
   max_level_ = kMaxMicLevel;
   max_compression_gain_ = kMaxCompressionGain;
@@ -224,8 +188,25 @@
   // example, what happens when we change devices.
 
   data_dumper_->InitiateNewSetOfRecordings();
+}
 
-  return InitializeGainControl(gctrl_, disable_digital_adaptive_);
+void AgcManagerDirect::ConfigureGainControl(GainControl* gain_control) const {
+  if (gain_control->set_mode(GainControl::kFixedDigital) != 0) {
+    RTC_LOG(LS_ERROR) << "set_mode(GainControl::kFixedDigital) failed.";
+  }
+  const int target_level_dbfs = disable_digital_adaptive_ ? 0 : 2;
+  if (gain_control->set_target_level_dbfs(target_level_dbfs) != 0) {
+    RTC_LOG(LS_ERROR) << "set_target_level_dbfs() failed.";
+  }
+  const int compression_gain_db =
+      disable_digital_adaptive_ ? 0 : kDefaultCompressionGain;
+  if (gain_control->set_compression_gain_db(compression_gain_db) != 0) {
+    RTC_LOG(LS_ERROR) << "set_compression_gain_db() failed.";
+  }
+  const bool enable_limiter = !disable_digital_adaptive_;
+  if (gain_control->enable_limiter(enable_limiter) != 0) {
+    RTC_LOG(LS_ERROR) << "enable_limiter() failed.";
+  }
 }
 
 void AgcManagerDirect::AnalyzePreProcess(const float* const* audio,
@@ -274,7 +255,8 @@
 
 void AgcManagerDirect::Process(const float* audio,
                                size_t length,
-                               int sample_rate_hz) {
+                               int sample_rate_hz,
+                               GainControl* gain_control) {
   if (capture_muted_) {
     return;
   }
@@ -305,12 +287,19 @@
     UpdateCompressor();
   }
 
+  if (new_compression_to_set_) {
+    if (gain_control->set_compression_gain_db(*new_compression_to_set_) != 0) {
+      RTC_LOG(LS_ERROR) << "set_compression_gain_db(" << compression_
+                        << ") failed.";
+    }
+  }
+  new_compression_to_set_ = absl::nullopt;
   data_dumper_->DumpRaw("experimental_gain_control_compression_gain_db", 1,
                         &compression_);
 }
 
 void AgcManagerDirect::SetLevel(int new_level) {
-  int voe_level = volume_callbacks_->GetMicVolume();
+  int voe_level = stream_analog_level_;
   if (voe_level == 0) {
     RTC_DLOG(LS_INFO)
         << "[agc] VolumeCallbacks returned level=0, taking no action.";
@@ -344,7 +333,7 @@
     return;
   }
 
-  volume_callbacks_->SetMicVolume(new_level);
+  stream_analog_level_ = new_level;
   RTC_DLOG(LS_INFO) << "[agc] voe_level=" << voe_level << ", "
                     << "level_=" << level_ << ", "
                     << "new_level=" << new_level;
@@ -382,7 +371,7 @@
 }
 
 int AgcManagerDirect::CheckVolumeAndReset() {
-  int level = volume_callbacks_->GetMicVolume();
+  int level = stream_analog_level_;
   // Reasons for taking action at startup:
   // 1) A person starting a call is expected to be heard.
   // 2) Independent of interpretation of |level| == 0 we should raise it so the
@@ -403,7 +392,7 @@
   if (level < minLevel) {
     level = minLevel;
     RTC_DLOG(LS_INFO) << "[agc] Initial volume too low, raising to " << level;
-    volume_callbacks_->SetMicVolume(level);
+    stream_analog_level_ = level;
   }
   agc_->Reset();
   level_ = level;
@@ -508,10 +497,7 @@
                                 kMaxCompressionGain + 1);
     compression_ = new_compression;
     compression_accumulator_ = new_compression;
-    if (gctrl_->set_compression_gain_db(compression_) != 0) {
-      RTC_LOG(LS_ERROR) << "set_compression_gain_db(" << compression_
-                        << ") failed.";
-    }
+    new_compression_to_set_ = compression_;
   }
 }
 
diff --git a/modules/audio_processing/agc/agc_manager_direct.h b/modules/audio_processing/agc/agc_manager_direct.h
index 505ad15..05f72ea 100644
--- a/modules/audio_processing/agc/agc_manager_direct.h
+++ b/modules/audio_processing/agc/agc_manager_direct.h
@@ -13,6 +13,7 @@
 
 #include <memory>
 
+#include "absl/types/optional.h"
 #include "modules/audio_processing/agc/agc.h"
 #include "modules/audio_processing/logging/apm_data_dumper.h"
 #include "rtc_base/constructor_magic.h"
@@ -23,17 +24,6 @@
 class AudioFrame;
 class GainControl;
 
-// Callbacks that need to be injected into AgcManagerDirect to read and control
-// the volume values. This is done to remove the VoiceEngine dependency in
-// AgcManagerDirect.
-// TODO(aluebs): Remove VolumeCallbacks.
-class VolumeCallbacks {
- public:
-  virtual ~VolumeCallbacks() {}
-  virtual void SetMicVolume(int volume) = 0;
-  virtual int GetMicVolume() = 0;
-};
-
 // Direct interface to use AGC to set volume and compression values.
 // AudioProcessing uses this interface directly to integrate the callback-less
 // AGC.
@@ -45,20 +35,23 @@
   // responsible for processing the audio using it after the call to Process.
   // The operating range of startup_min_level is [12, 255] and any input value
   // outside that range will be clamped.
-  AgcManagerDirect(GainControl* gctrl,
-                   VolumeCallbacks* volume_callbacks,
-                   int startup_min_level,
+  AgcManagerDirect(int startup_min_level,
                    int clipped_level_min,
                    bool use_agc2_level_estimation,
                    bool disable_digital_adaptive);
 
   ~AgcManagerDirect();
 
-  int Initialize();
+  void Initialize();
+  void ConfigureGainControl(GainControl* gain_control) const;
+
   void AnalyzePreProcess(const float* const* audio,
                          int num_channels,
                          size_t samples_per_channel);
-  void Process(const float* audio, size_t length, int sample_rate_hz);
+  void Process(const float* audio,
+               size_t length,
+               int sample_rate_hz,
+               GainControl* gain_control);
 
   // Call when the capture stream has been muted/unmuted. This causes the
   // manager to disregard all incoming audio; chances are good it's background
@@ -68,6 +61,9 @@
 
   float voice_probability();
 
+  int stream_analog_level() const { return stream_analog_level_; }
+  void set_stream_analog_level(int level) { stream_analog_level_ = level; }
+
  private:
   friend class AgcManagerDirectTest;
 
@@ -79,8 +75,6 @@
   // Dependency injection for testing. Don't delete |agc| as the memory is owned
   // by the manager.
   AgcManagerDirect(Agc* agc,
-                   GainControl* gctrl,
-                   VolumeCallbacks* volume_callbacks,
                    int startup_min_level,
                    int clipped_level_min);
 
@@ -104,8 +98,6 @@
   static int instance_counter_;
 
   std::unique_ptr<Agc> agc_;
-  GainControl* gctrl_;
-  VolumeCallbacks* volume_callbacks_;
 
   int frames_since_clipped_;
   int level_;
@@ -122,6 +114,8 @@
   int startup_min_level_;
   const int clipped_level_min_;
   int calls_since_last_gain_log_ = 0;
+  int stream_analog_level_ = 0;
+  absl::optional<int> new_compression_to_set_;
 
   RTC_DISALLOW_COPY_AND_ASSIGN(AgcManagerDirect);
 };
diff --git a/modules/audio_processing/agc/agc_manager_direct_unittest.cc b/modules/audio_processing/agc/agc_manager_direct_unittest.cc
index bc8309e..43f5d2d 100644
--- a/modules/audio_processing/agc/agc_manager_direct_unittest.cc
+++ b/modules/audio_processing/agc/agc_manager_direct_unittest.cc
@@ -55,27 +55,18 @@
   MOCK_CONST_METHOD0(stream_is_saturated, bool());
 };
 
-class TestVolumeCallbacks : public VolumeCallbacks {
- public:
-  TestVolumeCallbacks() : volume_(0) {}
-  void SetMicVolume(int volume) override { volume_ = volume; }
-  int GetMicVolume() override { return volume_; }
-
- private:
-  int volume_;
-};
-
 }  // namespace
 
 class AgcManagerDirectTest : public ::testing::Test {
  protected:
   AgcManagerDirectTest()
       : agc_(new MockAgc),
-        manager_(agc_, &gctrl_, &volume_, kInitialVolume, kClippedMin),
+        manager_(agc_, kInitialVolume, kClippedMin),
         audio(kNumChannels),
         audio_data(kNumChannels * kSamplesPerChannel, 0.f) {
     ExpectInitialize();
     manager_.Initialize();
+    manager_.ConfigureGainControl(&gctrl_);
     for (size_t ch = 0; ch < kNumChannels; ++ch) {
       audio[ch] = &audio_data[ch * kSamplesPerChannel];
     }
@@ -88,12 +79,12 @@
   }
 
   void SetVolumeAndProcess(int volume) {
-    volume_.SetMicVolume(volume);
+    manager_.set_stream_analog_level(volume);
     FirstProcess();
   }
 
   void ExpectCheckVolumeAndReset(int volume) {
-    volume_.SetMicVolume(volume);
+    manager_.set_stream_analog_level(volume);
     EXPECT_CALL(*agc_, Reset());
   }
 
@@ -107,7 +98,7 @@
   void CallProcess(int num_calls) {
     for (int i = 0; i < num_calls; ++i) {
       EXPECT_CALL(*agc_, Process(_, _, _)).WillOnce(Return());
-      manager_.Process(nullptr, kSamplesPerChannel, kSampleRateHz);
+      manager_.Process(nullptr, kSamplesPerChannel, kSampleRateHz, &gctrl_);
     }
   }
 
@@ -129,7 +120,6 @@
 
   MockAgc* agc_;
   MockGainControl gctrl_;
-  TestVolumeCallbacks volume_;
   AgcManagerDirect manager_;
   std::vector<float*> audio;
   std::vector<float> audio_data;
@@ -137,7 +127,7 @@
 
 TEST_F(AgcManagerDirectTest, StartupMinVolumeConfigurationIsRespected) {
   FirstProcess();
-  EXPECT_EQ(kInitialVolume, volume_.GetMicVolume());
+  EXPECT_EQ(kInitialVolume, manager_.stream_analog_level());
 }
 
 TEST_F(AgcManagerDirectTest, MicVolumeResponseToRmsError) {
@@ -157,12 +147,12 @@
   EXPECT_CALL(*agc_, GetRmsErrorDb(_))
       .WillOnce(DoAll(SetArgPointee<0>(11), Return(true)));
   CallProcess(1);
-  EXPECT_EQ(130, volume_.GetMicVolume());
+  EXPECT_EQ(130, manager_.stream_analog_level());
 
   EXPECT_CALL(*agc_, GetRmsErrorDb(_))
       .WillOnce(DoAll(SetArgPointee<0>(20), Return(true)));
   CallProcess(1);
-  EXPECT_EQ(168, volume_.GetMicVolume());
+  EXPECT_EQ(168, manager_.stream_analog_level());
 
   // Inside the compressor's window; no change of volume.
   EXPECT_CALL(*agc_, GetRmsErrorDb(_))
@@ -176,17 +166,17 @@
   EXPECT_CALL(*agc_, GetRmsErrorDb(_))
       .WillOnce(DoAll(SetArgPointee<0>(-1), Return(true)));
   CallProcess(1);
-  EXPECT_EQ(167, volume_.GetMicVolume());
+  EXPECT_EQ(167, manager_.stream_analog_level());
 
   EXPECT_CALL(*agc_, GetRmsErrorDb(_))
       .WillOnce(DoAll(SetArgPointee<0>(-1), Return(true)));
   CallProcess(1);
-  EXPECT_EQ(163, volume_.GetMicVolume());
+  EXPECT_EQ(163, manager_.stream_analog_level());
 
   EXPECT_CALL(*agc_, GetRmsErrorDb(_))
       .WillOnce(DoAll(SetArgPointee<0>(-9), Return(true)));
   CallProcess(1);
-  EXPECT_EQ(129, volume_.GetMicVolume());
+  EXPECT_EQ(129, manager_.stream_analog_level());
 }
 
 TEST_F(AgcManagerDirectTest, MicVolumeIsLimited) {
@@ -196,60 +186,60 @@
   EXPECT_CALL(*agc_, GetRmsErrorDb(_))
       .WillOnce(DoAll(SetArgPointee<0>(30), Return(true)));
   CallProcess(1);
-  EXPECT_EQ(183, volume_.GetMicVolume());
+  EXPECT_EQ(183, manager_.stream_analog_level());
 
   EXPECT_CALL(*agc_, GetRmsErrorDb(_))
       .WillOnce(DoAll(SetArgPointee<0>(30), Return(true)));
   CallProcess(1);
-  EXPECT_EQ(243, volume_.GetMicVolume());
+  EXPECT_EQ(243, manager_.stream_analog_level());
 
   // Won't go higher than the maximum.
   EXPECT_CALL(*agc_, GetRmsErrorDb(_))
       .WillOnce(DoAll(SetArgPointee<0>(30), Return(true)));
   CallProcess(1);
-  EXPECT_EQ(255, volume_.GetMicVolume());
+  EXPECT_EQ(255, manager_.stream_analog_level());
 
   EXPECT_CALL(*agc_, GetRmsErrorDb(_))
       .WillOnce(DoAll(SetArgPointee<0>(-1), Return(true)));
   CallProcess(1);
-  EXPECT_EQ(254, volume_.GetMicVolume());
+  EXPECT_EQ(254, manager_.stream_analog_level());
 
   // Maximum downwards change is limited.
   EXPECT_CALL(*agc_, GetRmsErrorDb(_))
       .WillOnce(DoAll(SetArgPointee<0>(-40), Return(true)));
   CallProcess(1);
-  EXPECT_EQ(194, volume_.GetMicVolume());
+  EXPECT_EQ(194, manager_.stream_analog_level());
 
   EXPECT_CALL(*agc_, GetRmsErrorDb(_))
       .WillOnce(DoAll(SetArgPointee<0>(-40), Return(true)));
   CallProcess(1);
-  EXPECT_EQ(137, volume_.GetMicVolume());
+  EXPECT_EQ(137, manager_.stream_analog_level());
 
   EXPECT_CALL(*agc_, GetRmsErrorDb(_))
       .WillOnce(DoAll(SetArgPointee<0>(-40), Return(true)));
   CallProcess(1);
-  EXPECT_EQ(88, volume_.GetMicVolume());
+  EXPECT_EQ(88, manager_.stream_analog_level());
 
   EXPECT_CALL(*agc_, GetRmsErrorDb(_))
       .WillOnce(DoAll(SetArgPointee<0>(-40), Return(true)));
   CallProcess(1);
-  EXPECT_EQ(54, volume_.GetMicVolume());
+  EXPECT_EQ(54, manager_.stream_analog_level());
 
   EXPECT_CALL(*agc_, GetRmsErrorDb(_))
       .WillOnce(DoAll(SetArgPointee<0>(-40), Return(true)));
   CallProcess(1);
-  EXPECT_EQ(33, volume_.GetMicVolume());
+  EXPECT_EQ(33, manager_.stream_analog_level());
 
   EXPECT_CALL(*agc_, GetRmsErrorDb(_))
       .WillOnce(DoAll(SetArgPointee<0>(-40), Return(true)));
   CallProcess(1);
-  EXPECT_EQ(18, volume_.GetMicVolume());
+  EXPECT_EQ(18, manager_.stream_analog_level());
 
   // Won't go lower than the minimum.
   EXPECT_CALL(*agc_, GetRmsErrorDb(_))
       .WillOnce(DoAll(SetArgPointee<0>(-40), Return(true)));
   CallProcess(1);
-  EXPECT_EQ(12, volume_.GetMicVolume());
+  EXPECT_EQ(12, manager_.stream_analog_level());
 }
 
 TEST_F(AgcManagerDirectTest, CompressorStepsTowardsTarget) {
@@ -374,7 +364,7 @@
 
 TEST_F(AgcManagerDirectTest, NoActionWhileMuted) {
   manager_.SetCaptureMuted(true);
-  manager_.Process(nullptr, kSamplesPerChannel, kSampleRateHz);
+  manager_.Process(nullptr, kSamplesPerChannel, kSampleRateHz, &gctrl_);
 }
 
 TEST_F(AgcManagerDirectTest, UnmutingChecksVolumeWithoutRaising) {
@@ -386,7 +376,7 @@
   // SetMicVolume should not be called.
   EXPECT_CALL(*agc_, GetRmsErrorDb(_)).WillOnce(Return(false));
   CallProcess(1);
-  EXPECT_EQ(127, volume_.GetMicVolume());
+  EXPECT_EQ(127, manager_.stream_analog_level());
 }
 
 TEST_F(AgcManagerDirectTest, UnmutingRaisesTooLowVolume) {
@@ -397,7 +387,7 @@
   ExpectCheckVolumeAndReset(11);
   EXPECT_CALL(*agc_, GetRmsErrorDb(_)).WillOnce(Return(false));
   CallProcess(1);
-  EXPECT_EQ(12, volume_.GetMicVolume());
+  EXPECT_EQ(12, manager_.stream_analog_level());
 }
 
 TEST_F(AgcManagerDirectTest, ManualLevelChangeResultsInNoSetMicCall) {
@@ -413,24 +403,24 @@
 
   // GetMicVolume returns a value outside of the quantization slack, indicating
   // a manual volume change.
-  ASSERT_NE(volume_.GetMicVolume(), 154);
-  volume_.SetMicVolume(154);
+  ASSERT_NE(manager_.stream_analog_level(), 154);
+  manager_.set_stream_analog_level(154);
   CallProcess(1);
-  EXPECT_EQ(154, volume_.GetMicVolume());
+  EXPECT_EQ(154, manager_.stream_analog_level());
 
   // Do the same thing, except downwards now.
   EXPECT_CALL(*agc_, GetRmsErrorDb(_))
       .WillOnce(DoAll(SetArgPointee<0>(-1), Return(true)));
-  volume_.SetMicVolume(100);
+  manager_.set_stream_analog_level(100);
   EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
   CallProcess(1);
-  EXPECT_EQ(100, volume_.GetMicVolume());
+  EXPECT_EQ(100, manager_.stream_analog_level());
 
   // And finally verify the AGC continues working without a manual change.
   EXPECT_CALL(*agc_, GetRmsErrorDb(_))
       .WillOnce(DoAll(SetArgPointee<0>(-1), Return(true)));
   CallProcess(1);
-  EXPECT_EQ(99, volume_.GetMicVolume());
+  EXPECT_EQ(99, manager_.stream_analog_level());
 }
 
 TEST_F(AgcManagerDirectTest, RecoveryAfterManualLevelChangeFromMax) {
@@ -441,25 +431,25 @@
   EXPECT_CALL(*agc_, GetRmsErrorDb(_))
       .WillRepeatedly(DoAll(SetArgPointee<0>(30), Return(true)));
   CallProcess(1);
-  EXPECT_EQ(183, volume_.GetMicVolume());
+  EXPECT_EQ(183, manager_.stream_analog_level());
   CallProcess(1);
-  EXPECT_EQ(243, volume_.GetMicVolume());
+  EXPECT_EQ(243, manager_.stream_analog_level());
   CallProcess(1);
-  EXPECT_EQ(255, volume_.GetMicVolume());
+  EXPECT_EQ(255, manager_.stream_analog_level());
 
   // Manual change does not result in SetMicVolume call.
   EXPECT_CALL(*agc_, GetRmsErrorDb(_))
       .WillOnce(DoAll(SetArgPointee<0>(-1), Return(true)));
-  volume_.SetMicVolume(50);
+  manager_.set_stream_analog_level(50);
   EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
   CallProcess(1);
-  EXPECT_EQ(50, volume_.GetMicVolume());
+  EXPECT_EQ(50, manager_.stream_analog_level());
 
   // Continues working as usual afterwards.
   EXPECT_CALL(*agc_, GetRmsErrorDb(_))
       .WillOnce(DoAll(SetArgPointee<0>(20), Return(true)));
   CallProcess(1);
-  EXPECT_EQ(69, volume_.GetMicVolume());
+  EXPECT_EQ(69, manager_.stream_analog_level());
 }
 
 TEST_F(AgcManagerDirectTest, RecoveryAfterManualLevelChangeBelowMin) {
@@ -469,40 +459,40 @@
   EXPECT_CALL(*agc_, GetRmsErrorDb(_))
       .WillOnce(DoAll(SetArgPointee<0>(-1), Return(true)));
   // Don't set to zero, which will cause AGC to take no action.
-  volume_.SetMicVolume(1);
+  manager_.set_stream_analog_level(1);
   EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
   CallProcess(1);
-  EXPECT_EQ(1, volume_.GetMicVolume());
+  EXPECT_EQ(1, manager_.stream_analog_level());
 
   // Continues working as usual afterwards.
   EXPECT_CALL(*agc_, GetRmsErrorDb(_))
       .WillOnce(DoAll(SetArgPointee<0>(11), Return(true)));
   CallProcess(1);
-  EXPECT_EQ(2, volume_.GetMicVolume());
+  EXPECT_EQ(2, manager_.stream_analog_level());
 
   EXPECT_CALL(*agc_, GetRmsErrorDb(_))
       .WillOnce(DoAll(SetArgPointee<0>(30), Return(true)));
   CallProcess(1);
-  EXPECT_EQ(11, volume_.GetMicVolume());
+  EXPECT_EQ(11, manager_.stream_analog_level());
 
   EXPECT_CALL(*agc_, GetRmsErrorDb(_))
       .WillOnce(DoAll(SetArgPointee<0>(20), Return(true)));
   CallProcess(1);
-  EXPECT_EQ(18, volume_.GetMicVolume());
+  EXPECT_EQ(18, manager_.stream_analog_level());
 }
 
 TEST_F(AgcManagerDirectTest, NoClippingHasNoImpact) {
   FirstProcess();
 
   CallPreProc(100, 0);
-  EXPECT_EQ(128, volume_.GetMicVolume());
+  EXPECT_EQ(128, manager_.stream_analog_level());
 }
 
 TEST_F(AgcManagerDirectTest, ClippingUnderThresholdHasNoImpact) {
   FirstProcess();
 
   CallPreProc(1, 0.099);
-  EXPECT_EQ(128, volume_.GetMicVolume());
+  EXPECT_EQ(128, manager_.stream_analog_level());
 }
 
 TEST_F(AgcManagerDirectTest, ClippingLowersVolume) {
@@ -510,7 +500,7 @@
 
   EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
   CallPreProc(1, 0.2);
-  EXPECT_EQ(240, volume_.GetMicVolume());
+  EXPECT_EQ(240, manager_.stream_analog_level());
 }
 
 TEST_F(AgcManagerDirectTest, WaitingPeriodBetweenClippingChecks) {
@@ -518,15 +508,15 @@
 
   EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
   CallPreProc(1, kAboveClippedThreshold);
-  EXPECT_EQ(240, volume_.GetMicVolume());
+  EXPECT_EQ(240, manager_.stream_analog_level());
 
   EXPECT_CALL(*agc_, Reset()).Times(0);
   CallPreProc(300, kAboveClippedThreshold);
-  EXPECT_EQ(240, volume_.GetMicVolume());
+  EXPECT_EQ(240, manager_.stream_analog_level());
 
   EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
   CallPreProc(1, kAboveClippedThreshold);
-  EXPECT_EQ(225, volume_.GetMicVolume());
+  EXPECT_EQ(225, manager_.stream_analog_level());
 }
 
 TEST_F(AgcManagerDirectTest, ClippingLoweringIsLimited) {
@@ -534,11 +524,11 @@
 
   EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
   CallPreProc(1, kAboveClippedThreshold);
-  EXPECT_EQ(kClippedMin, volume_.GetMicVolume());
+  EXPECT_EQ(kClippedMin, manager_.stream_analog_level());
 
   EXPECT_CALL(*agc_, Reset()).Times(0);
   CallPreProc(1000, kAboveClippedThreshold);
-  EXPECT_EQ(kClippedMin, volume_.GetMicVolume());
+  EXPECT_EQ(kClippedMin, manager_.stream_analog_level());
 }
 
 TEST_F(AgcManagerDirectTest, ClippingMaxIsRespectedWhenEqualToLevel) {
@@ -546,12 +536,12 @@
 
   EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
   CallPreProc(1, kAboveClippedThreshold);
-  EXPECT_EQ(240, volume_.GetMicVolume());
+  EXPECT_EQ(240, manager_.stream_analog_level());
 
   EXPECT_CALL(*agc_, GetRmsErrorDb(_))
       .WillRepeatedly(DoAll(SetArgPointee<0>(30), Return(true)));
   CallProcess(10);
-  EXPECT_EQ(240, volume_.GetMicVolume());
+  EXPECT_EQ(240, manager_.stream_analog_level());
 }
 
 TEST_F(AgcManagerDirectTest, ClippingMaxIsRespectedWhenHigherThanLevel) {
@@ -559,14 +549,14 @@
 
   EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
   CallPreProc(1, kAboveClippedThreshold);
-  EXPECT_EQ(185, volume_.GetMicVolume());
+  EXPECT_EQ(185, manager_.stream_analog_level());
 
   EXPECT_CALL(*agc_, GetRmsErrorDb(_))
       .WillRepeatedly(DoAll(SetArgPointee<0>(40), Return(true)));
   CallProcess(1);
-  EXPECT_EQ(240, volume_.GetMicVolume());
+  EXPECT_EQ(240, manager_.stream_analog_level());
   CallProcess(10);
-  EXPECT_EQ(240, volume_.GetMicVolume());
+  EXPECT_EQ(240, manager_.stream_analog_level());
 }
 
 TEST_F(AgcManagerDirectTest, MaxCompressionIsIncreasedAfterClipping) {
@@ -574,7 +564,7 @@
 
   EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
   CallPreProc(1, kAboveClippedThreshold);
-  EXPECT_EQ(195, volume_.GetMicVolume());
+  EXPECT_EQ(195, manager_.stream_analog_level());
 
   EXPECT_CALL(*agc_, GetRmsErrorDb(_))
       .WillOnce(DoAll(SetArgPointee<0>(11), Return(true)))
@@ -601,12 +591,12 @@
   CallPreProc(300, kAboveClippedThreshold);
   EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
   CallPreProc(1, kAboveClippedThreshold);
-  EXPECT_EQ(180, volume_.GetMicVolume());
+  EXPECT_EQ(180, manager_.stream_analog_level());
 
   CallPreProc(300, kAboveClippedThreshold);
   EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
   CallPreProc(1, kAboveClippedThreshold);
-  EXPECT_EQ(kClippedMin, volume_.GetMicVolume());
+  EXPECT_EQ(kClippedMin, manager_.stream_analog_level());
 
   // Current level is now at the minimum, but the maximum allowed level still
   // has more to decrease.
@@ -643,41 +633,41 @@
 
   EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
   CallPreProc(1, kAboveClippedThreshold);
-  EXPECT_EQ(210, volume_.GetMicVolume());
+  EXPECT_EQ(210, manager_.stream_analog_level());
 
   // High enough error to trigger a volume check.
   EXPECT_CALL(*agc_, GetRmsErrorDb(_))
       .WillOnce(DoAll(SetArgPointee<0>(14), Return(true)));
   // User changed the volume.
-  volume_.SetMicVolume(250);
+  manager_.set_stream_analog_level(250);
   EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
   CallProcess(1);
-  EXPECT_EQ(250, volume_.GetMicVolume());
+  EXPECT_EQ(250, manager_.stream_analog_level());
 
   // Move down...
   EXPECT_CALL(*agc_, GetRmsErrorDb(_))
       .WillOnce(DoAll(SetArgPointee<0>(-10), Return(true)));
   CallProcess(1);
-  EXPECT_EQ(210, volume_.GetMicVolume());
+  EXPECT_EQ(210, manager_.stream_analog_level());
   // And back up to the new max established by the user.
   EXPECT_CALL(*agc_, GetRmsErrorDb(_))
       .WillOnce(DoAll(SetArgPointee<0>(40), Return(true)));
   CallProcess(1);
-  EXPECT_EQ(250, volume_.GetMicVolume());
+  EXPECT_EQ(250, manager_.stream_analog_level());
   // Will not move above new maximum.
   EXPECT_CALL(*agc_, GetRmsErrorDb(_))
       .WillOnce(DoAll(SetArgPointee<0>(30), Return(true)));
   CallProcess(1);
-  EXPECT_EQ(250, volume_.GetMicVolume());
+  EXPECT_EQ(250, manager_.stream_analog_level());
 }
 
 TEST_F(AgcManagerDirectTest, ClippingDoesNotPullLowVolumeBackUp) {
   SetVolumeAndProcess(80);
 
   EXPECT_CALL(*agc_, Reset()).Times(0);
-  int initial_volume = volume_.GetMicVolume();
+  int initial_volume = manager_.stream_analog_level();
   CallPreProc(1, kAboveClippedThreshold);
-  EXPECT_EQ(initial_volume, volume_.GetMicVolume());
+  EXPECT_EQ(initial_volume, manager_.stream_analog_level());
 }
 
 TEST_F(AgcManagerDirectTest, TakesNoActionOnZeroMicVolume) {
@@ -685,17 +675,15 @@
 
   EXPECT_CALL(*agc_, GetRmsErrorDb(_))
       .WillRepeatedly(DoAll(SetArgPointee<0>(30), Return(true)));
-  volume_.SetMicVolume(0);
+  manager_.set_stream_analog_level(0);
   CallProcess(10);
-  EXPECT_EQ(0, volume_.GetMicVolume());
+  EXPECT_EQ(0, manager_.stream_analog_level());
 }
 
 TEST(AgcManagerDirectStandaloneTest, DisableDigitalDisablesDigital) {
   auto agc = std::unique_ptr<Agc>(new ::testing::NiceMock<MockAgc>());
   MockGainControl gctrl;
-  TestVolumeCallbacks volume;
-
-  AgcManagerDirect manager(&gctrl, &volume, kInitialVolume, kClippedMin,
+  AgcManagerDirect manager(kInitialVolume, kClippedMin,
                            /* use agc2 level estimation */ false,
                            /* disable digital adaptive */ true);
 
@@ -705,18 +693,19 @@
   EXPECT_CALL(gctrl, enable_limiter(false));
 
   manager.Initialize();
+  manager.ConfigureGainControl(&gctrl);
 }
 
 TEST(AgcManagerDirectStandaloneTest, AgcMinMicLevelExperiment) {
-  auto agc_man = std::unique_ptr<AgcManagerDirect>(new AgcManagerDirect(
-      nullptr, nullptr, kInitialVolume, kClippedMin, true, true));
+  auto agc_man = std::unique_ptr<AgcManagerDirect>(
+      new AgcManagerDirect(kInitialVolume, kClippedMin, true, true));
   EXPECT_EQ(agc_man->min_mic_level(), kMinMicLevel);
   EXPECT_EQ(agc_man->startup_min_level(), kInitialVolume);
   {
     test::ScopedFieldTrials field_trial(
         "WebRTC-Audio-AgcMinMicLevelExperiment/Disabled/");
-    agc_man.reset(new AgcManagerDirect(nullptr, nullptr, kInitialVolume,
-                                       kClippedMin, true, true));
+    agc_man.reset(
+        new AgcManagerDirect(kInitialVolume, kClippedMin, true, true));
     EXPECT_EQ(agc_man->min_mic_level(), kMinMicLevel);
     EXPECT_EQ(agc_man->startup_min_level(), kInitialVolume);
   }
@@ -724,16 +713,16 @@
     // Valid range of field-trial parameter is [0,255].
     test::ScopedFieldTrials field_trial(
         "WebRTC-Audio-AgcMinMicLevelExperiment/Enabled-256/");
-    agc_man.reset(new AgcManagerDirect(nullptr, nullptr, kInitialVolume,
-                                       kClippedMin, true, true));
+    agc_man.reset(
+        new AgcManagerDirect(kInitialVolume, kClippedMin, true, true));
     EXPECT_EQ(agc_man->min_mic_level(), kMinMicLevel);
     EXPECT_EQ(agc_man->startup_min_level(), kInitialVolume);
   }
   {
     test::ScopedFieldTrials field_trial(
         "WebRTC-Audio-AgcMinMicLevelExperiment/Enabled--1/");
-    agc_man.reset(new AgcManagerDirect(nullptr, nullptr, kInitialVolume,
-                                       kClippedMin, true, true));
+    agc_man.reset(
+        new AgcManagerDirect(kInitialVolume, kClippedMin, true, true));
     EXPECT_EQ(agc_man->min_mic_level(), kMinMicLevel);
     EXPECT_EQ(agc_man->startup_min_level(), kInitialVolume);
   }
@@ -743,8 +732,8 @@
     // be changed.
     test::ScopedFieldTrials field_trial(
         "WebRTC-Audio-AgcMinMicLevelExperiment/Enabled-50/");
-    agc_man.reset(new AgcManagerDirect(nullptr, nullptr, kInitialVolume,
-                                       kClippedMin, true, true));
+    agc_man.reset(
+        new AgcManagerDirect(kInitialVolume, kClippedMin, true, true));
     EXPECT_EQ(agc_man->min_mic_level(), 50);
     EXPECT_EQ(agc_man->startup_min_level(), kInitialVolume);
   }
@@ -754,8 +743,7 @@
     // level set by the experiment.
     test::ScopedFieldTrials field_trial(
         "WebRTC-Audio-AgcMinMicLevelExperiment/Enabled-50/");
-    agc_man.reset(
-        new AgcManagerDirect(nullptr, nullptr, 30, kClippedMin, true, true));
+    agc_man.reset(new AgcManagerDirect(30, kClippedMin, true, true));
     EXPECT_EQ(agc_man->min_mic_level(), 50);
     EXPECT_EQ(agc_man->startup_min_level(), 50);
   }
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);
 }
diff --git a/modules/audio_processing/audio_processing_impl.h b/modules/audio_processing/audio_processing_impl.h
index f7320ac..a5717d3 100644
--- a/modules/audio_processing/audio_processing_impl.h
+++ b/modules/audio_processing/audio_processing_impl.h
@@ -22,7 +22,6 @@
 #include "modules/audio_processing/audio_buffer.h"
 #include "modules/audio_processing/echo_cancellation_impl.h"
 #include "modules/audio_processing/echo_control_mobile_impl.h"
-#include "modules/audio_processing/gain_control_for_experimental_agc.h"
 #include "modules/audio_processing/gain_control_impl.h"
 #include "modules/audio_processing/gain_controller2.h"
 #include "modules/audio_processing/high_pass_filter.h"
@@ -254,11 +253,6 @@
   void ApplyAgc1Config(const Config::GainController1& agc_config)
       RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_capture_);
 
-  // Returns a direct pointer to the AGC1 submodule: either a GainControlImpl
-  // or GainControlForExperimentalAgc instance.
-  GainControl* agc1();
-  const GainControl* agc1() const;
-
   void EmptyQueuedRenderAudio();
   void AllocateRenderQueue()
       RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_render_, crit_capture_);
@@ -331,16 +325,26 @@
     Submodules(std::unique_ptr<CustomProcessing> capture_post_processor,
                std::unique_ptr<CustomProcessing> render_pre_processor,
                rtc::scoped_refptr<EchoDetector> echo_detector,
-               std::unique_ptr<CustomAudioAnalyzer> capture_analyzer)
+               std::unique_ptr<CustomAudioAnalyzer> capture_analyzer,
+               int agc_startup_min_volume,
+               int agc_clipped_level_min,
+               bool use_experimental_agc,
+               bool use_experimental_agc_agc2_level_estimation,
+               bool use_experimental_agc_agc2_digital_adaptive)
         : echo_detector(std::move(echo_detector)),
           capture_post_processor(std::move(capture_post_processor)),
           render_pre_processor(std::move(render_pre_processor)),
-          capture_analyzer(std::move(capture_analyzer)) {}
+          capture_analyzer(std::move(capture_analyzer)) {
+      if (use_experimental_agc) {
+        agc_manager = std::make_unique<AgcManagerDirect>(
+            agc_startup_min_volume, agc_clipped_level_min,
+            use_experimental_agc_agc2_level_estimation,
+            use_experimental_agc_agc2_digital_adaptive);
+      }
+    }
     // Accessed internally from capture or during initialization.
     std::unique_ptr<AgcManagerDirect> agc_manager;
     std::unique_ptr<GainControlImpl> gain_control;
-    std::unique_ptr<GainControlForExperimentalAgc>
-        gain_control_for_experimental_agc;
     std::unique_ptr<GainController2> gain_controller2;
     std::unique_ptr<HighPassFilter> high_pass_filter;
     rtc::scoped_refptr<EchoDetector> echo_detector;
@@ -377,29 +381,15 @@
 
   // APM constants.
   const struct ApmConstants {
-    ApmConstants(int agc_startup_min_volume,
-                 int agc_clipped_level_min,
-                 bool use_experimental_agc,
-                 bool use_experimental_agc_agc2_level_estimation,
-                 bool use_experimental_agc_agc2_digital_adaptive,
+    ApmConstants(int agc_clipped_level_min,
                  bool experimental_multi_channel_render_support,
                  bool experimental_multi_channel_capture_support)
-        : agc_startup_min_volume(agc_startup_min_volume),
-          agc_clipped_level_min(agc_clipped_level_min),
-          use_experimental_agc(use_experimental_agc),
-          use_experimental_agc_agc2_level_estimation(
-              use_experimental_agc_agc2_level_estimation),
-          use_experimental_agc_agc2_digital_adaptive(
-              use_experimental_agc_agc2_digital_adaptive),
+        : agc_clipped_level_min(agc_clipped_level_min),
           experimental_multi_channel_render_support(
               experimental_multi_channel_render_support),
           experimental_multi_channel_capture_support(
               experimental_multi_channel_capture_support) {}
-    int agc_startup_min_volume;
     int agc_clipped_level_min;
-    bool use_experimental_agc;
-    bool use_experimental_agc_agc2_level_estimation;
-    bool use_experimental_agc_agc2_digital_adaptive;
     bool experimental_multi_channel_render_support;
     bool experimental_multi_channel_capture_support;
   } constants_;
diff --git a/modules/audio_processing/gain_control_for_experimental_agc.cc b/modules/audio_processing/gain_control_for_experimental_agc.cc
deleted file mode 100644
index 9e4d4f5..0000000
--- a/modules/audio_processing/gain_control_for_experimental_agc.cc
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
- *
- *  Use of this source code is governed by a BSD-style license
- *  that can be found in the LICENSE file in the root of the source
- *  tree. An additional intellectual property rights grant can be found
- *  in the file PATENTS.  All contributing project authors may
- *  be found in the AUTHORS file in the root of the source tree.
- */
-
-#include "modules/audio_processing/gain_control_for_experimental_agc.h"
-
-#include "modules/audio_processing/include/audio_processing.h"
-#include "modules/audio_processing/logging/apm_data_dumper.h"
-#include "rtc_base/atomic_ops.h"
-#include "rtc_base/critical_section.h"
-
-namespace webrtc {
-
-int GainControlForExperimentalAgc::instance_counter_ = 0;
-
-GainControlForExperimentalAgc::GainControlForExperimentalAgc(
-    GainControl* gain_control)
-    : data_dumper_(
-          new ApmDataDumper(rtc::AtomicOps::Increment(&instance_counter_))),
-      real_gain_control_(gain_control),
-      volume_(0) {}
-
-GainControlForExperimentalAgc::~GainControlForExperimentalAgc() = default;
-
-int GainControlForExperimentalAgc::Enable(bool enable) {
-  return real_gain_control_->Enable(enable);
-}
-
-bool GainControlForExperimentalAgc::is_enabled() const {
-  return real_gain_control_->is_enabled();
-}
-
-int GainControlForExperimentalAgc::set_stream_analog_level(int level) {
-  data_dumper_->DumpRaw("experimental_gain_control_set_stream_analog_level", 1,
-                        &level);
-  do_log_level_ = true;
-  volume_ = level;
-  return AudioProcessing::kNoError;
-}
-
-int GainControlForExperimentalAgc::stream_analog_level() const {
-  if (do_log_level_) {
-    data_dumper_->DumpRaw("experimental_gain_control_stream_analog_level", 1,
-                          &volume_);
-    do_log_level_ = false;
-  }
-  return volume_;
-}
-
-int GainControlForExperimentalAgc::set_mode(Mode mode) {
-  return AudioProcessing::kNoError;
-}
-
-GainControl::Mode GainControlForExperimentalAgc::mode() const {
-  return GainControl::kAdaptiveAnalog;
-}
-
-int GainControlForExperimentalAgc::set_target_level_dbfs(int level) {
-  return AudioProcessing::kNoError;
-}
-
-int GainControlForExperimentalAgc::target_level_dbfs() const {
-  return real_gain_control_->target_level_dbfs();
-}
-
-int GainControlForExperimentalAgc::set_compression_gain_db(int gain) {
-  return AudioProcessing::kNoError;
-}
-
-int GainControlForExperimentalAgc::compression_gain_db() const {
-  return real_gain_control_->compression_gain_db();
-}
-
-int GainControlForExperimentalAgc::enable_limiter(bool enable) {
-  return AudioProcessing::kNoError;
-}
-
-bool GainControlForExperimentalAgc::is_limiter_enabled() const {
-  return real_gain_control_->is_limiter_enabled();
-}
-
-int GainControlForExperimentalAgc::set_analog_level_limits(int minimum,
-                                                           int maximum) {
-  return AudioProcessing::kNoError;
-}
-
-int GainControlForExperimentalAgc::analog_level_minimum() const {
-  return real_gain_control_->analog_level_minimum();
-}
-
-int GainControlForExperimentalAgc::analog_level_maximum() const {
-  return real_gain_control_->analog_level_maximum();
-}
-
-bool GainControlForExperimentalAgc::stream_is_saturated() const {
-  return real_gain_control_->stream_is_saturated();
-}
-
-void GainControlForExperimentalAgc::SetMicVolume(int volume) {
-  volume_ = volume;
-}
-
-int GainControlForExperimentalAgc::GetMicVolume() {
-  return volume_;
-}
-
-void GainControlForExperimentalAgc::Initialize() {
-  data_dumper_->InitiateNewSetOfRecordings();
-}
-
-}  // namespace webrtc
diff --git a/modules/audio_processing/gain_control_for_experimental_agc.h b/modules/audio_processing/gain_control_for_experimental_agc.h
deleted file mode 100644
index a8bc808..0000000
--- a/modules/audio_processing/gain_control_for_experimental_agc.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
- *
- *  Use of this source code is governed by a BSD-style license
- *  that can be found in the LICENSE file in the root of the source
- *  tree. An additional intellectual property rights grant can be found
- *  in the file PATENTS.  All contributing project authors may
- *  be found in the AUTHORS file in the root of the source tree.
- */
-
-#ifndef MODULES_AUDIO_PROCESSING_GAIN_CONTROL_FOR_EXPERIMENTAL_AGC_H_
-#define MODULES_AUDIO_PROCESSING_GAIN_CONTROL_FOR_EXPERIMENTAL_AGC_H_
-
-#include "modules/audio_processing/agc/agc_manager_direct.h"
-#include "modules/audio_processing/agc/gain_control.h"
-#include "rtc_base/thread_checker.h"
-
-namespace webrtc {
-
-class ApmDataDumper;
-
-// This class has two main purposes:
-//
-// 1) It is returned instead of the real GainControl after the new AGC has been
-//    enabled in order to prevent an outside user from overriding compression
-//    settings. It doesn't do anything in its implementation, except for
-//    delegating the const methods and Enable calls to the real GainControl, so
-//    AGC can still be disabled.
-//
-// 2) It is injected into AgcManagerDirect and implements volume callbacks for
-//    getting and setting the volume level. It just caches this value to be used
-//    in VoiceEngine later.
-class GainControlForExperimentalAgc : public GainControl,
-                                      public VolumeCallbacks {
- public:
-  explicit GainControlForExperimentalAgc(GainControl* gain_control);
-  GainControlForExperimentalAgc(const GainControlForExperimentalAgc&) = delete;
-  GainControlForExperimentalAgc& operator=(
-      const GainControlForExperimentalAgc&) = delete;
-
-  ~GainControlForExperimentalAgc() override;
-
-  // GainControl implementation.
-  int Enable(bool enable) override;
-  bool is_enabled() const override;
-  int set_stream_analog_level(int level) override;
-  int stream_analog_level() const override;
-  int set_mode(Mode mode) override;
-  Mode mode() const override;
-  int set_target_level_dbfs(int level) override;
-  int target_level_dbfs() const override;
-  int set_compression_gain_db(int gain) override;
-  int compression_gain_db() const override;
-  int enable_limiter(bool enable) override;
-  bool is_limiter_enabled() const override;
-  int set_analog_level_limits(int minimum, int maximum) override;
-  int analog_level_minimum() const override;
-  int analog_level_maximum() const override;
-  bool stream_is_saturated() const override;
-
-  // VolumeCallbacks implementation.
-  void SetMicVolume(int volume) override;
-  int GetMicVolume() override;
-
-  void Initialize();
-
- private:
-  std::unique_ptr<ApmDataDumper> data_dumper_;
-  GainControl* real_gain_control_;
-  int volume_;
-  mutable bool do_log_level_ = true;
-  static int instance_counter_;
-};
-
-}  // namespace webrtc
-
-#endif  // MODULES_AUDIO_PROCESSING_GAIN_CONTROL_FOR_EXPERIMENTAL_AGC_H_
diff --git a/modules/audio_processing/gain_control_impl.h b/modules/audio_processing/gain_control_impl.h
index 4ec1941..7976613 100644
--- a/modules/audio_processing/gain_control_impl.h
+++ b/modules/audio_processing/gain_control_impl.h
@@ -49,21 +49,20 @@
   int stream_analog_level() const override;
   bool is_limiter_enabled() const override;
   Mode mode() const override;
-
+  int Enable(bool enable) override;
+  int set_mode(Mode mode) override;
   int compression_gain_db() const override;
+  int set_analog_level_limits(int minimum, int maximum) override;
+  int set_compression_gain_db(int gain) override;
+  int set_target_level_dbfs(int level) override;
+  int enable_limiter(bool enable) override;
+  int set_stream_analog_level(int level) override;
 
  private:
   class GainController;
 
   // GainControl implementation.
-  int Enable(bool enable) override;
-  int set_stream_analog_level(int level) override;
-  int set_mode(Mode mode) override;
-  int set_target_level_dbfs(int level) override;
   int target_level_dbfs() const override;
-  int set_compression_gain_db(int gain) override;
-  int enable_limiter(bool enable) override;
-  int set_analog_level_limits(int minimum, int maximum) override;
   int analog_level_minimum() const override;
   int analog_level_maximum() const override;
   bool stream_is_saturated() const override;