Integrate ClippingPredictor into AudioProcessingImpl and AgcManagerDirect

Integrate ClippingPredictor in AgcManagerDirect and
AudioProcessingImpl. Disable functionality by default.

Bug: webrtc:12774
Change-Id: Ic67a47f439c89b75066506fca8acaf636d8812f0
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/221100
Commit-Queue: Hanna Silen <silen@webrtc.org>
Reviewed-by: Minyue Li <minyue@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#34207}
diff --git a/modules/audio_processing/agc/BUILD.gn b/modules/audio_processing/agc/BUILD.gn
index f622a59..3b2b205 100644
--- a/modules/audio_processing/agc/BUILD.gn
+++ b/modules/audio_processing/agc/BUILD.gn
@@ -19,11 +19,13 @@
   ]
   configs += [ "..:apm_debug_dump" ]
   deps = [
+    ":clipping_predictor",
     ":gain_control_interface",
     ":gain_map",
     ":level_estimation",
     "..:apm_logging",
     "..:audio_buffer",
+    "..:audio_frame_view",
     "../../../common_audio",
     "../../../common_audio:common_audio_c",
     "../../../rtc_base:checks",
@@ -38,18 +40,6 @@
   absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
 }
 
-rtc_library("clipping_predictor_level_buffer") {
-  sources = [
-    "clipping_predictor_level_buffer.cc",
-    "clipping_predictor_level_buffer.h",
-  ]
-  deps = [
-    "../../../rtc_base:checks",
-    "../../../rtc_base:logging",
-  ]
-  absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
-}
-
 rtc_library("clipping_predictor") {
   sources = [
     "clipping_predictor.cc",
@@ -68,6 +58,18 @@
   absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
 }
 
+rtc_library("clipping_predictor_level_buffer") {
+  sources = [
+    "clipping_predictor_level_buffer.cc",
+    "clipping_predictor_level_buffer.h",
+  ]
+  deps = [
+    "../../../rtc_base:checks",
+    "../../../rtc_base:logging",
+  ]
+  absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
+}
+
 rtc_library("level_estimation") {
   sources = [
     "agc.cc",
diff --git a/modules/audio_processing/agc/agc_manager_direct.cc b/modules/audio_processing/agc/agc_manager_direct.cc
index ebd978b..46304d2 100644
--- a/modules/audio_processing/agc/agc_manager_direct.cc
+++ b/modules/audio_processing/agc/agc_manager_direct.cc
@@ -16,6 +16,7 @@
 #include "common_audio/include/audio_util.h"
 #include "modules/audio_processing/agc/gain_control.h"
 #include "modules/audio_processing/agc/gain_map_internal.h"
+#include "modules/audio_processing/include/audio_frame_view.h"
 #include "rtc_base/atomic_ops.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/logging.h"
@@ -48,6 +49,9 @@
 // restrictions from clipping events.
 constexpr int kSurplusCompressionGain = 6;
 
+using ClippingPredictorConfig = AudioProcessing::Config::GainController1::
+    AnalogGainController::ClippingPredictor;
+
 // Returns whether a fall-back solution to choose the maximum level should be
 // chosen.
 bool UseMaxAnalogChannelLevel() {
@@ -125,6 +129,26 @@
   return static_cast<float>(num_clipped) / (samples_per_channel);
 }
 
+std::unique_ptr<ClippingPredictor> CreateClippingPredictor(
+    int num_capture_channels,
+    const ClippingPredictorConfig& config) {
+  if (config.enabled) {
+    RTC_LOG(LS_INFO) << "[agc] Clipping prediction enabled.";
+    switch (config.mode) {
+      case ClippingPredictorConfig::kClippingEventPrediction:
+        return CreateClippingEventPredictor(num_capture_channels, config);
+      case ClippingPredictorConfig::kAdaptiveStepClippingPeakPrediction:
+        return CreateAdaptiveStepClippingPeakPredictor(num_capture_channels,
+                                                       config);
+      case ClippingPredictorConfig::kFixedStepClippingPeakPrediction:
+        return CreateFixedStepClippingPeakPredictor(num_capture_channels,
+                                                    config);
+    }
+  } else {
+    return nullptr;
+  }
+}
+
 }  // namespace
 
 MonoAgc::MonoAgc(ApmDataDumper* data_dumper,
@@ -400,7 +424,8 @@
                                    int sample_rate_hz,
                                    int clipped_level_step,
                                    float clipped_ratio_threshold,
-                                   int clipped_wait_frames)
+                                   int clipped_wait_frames,
+                                   const ClippingPredictorConfig& clipping_cfg)
     : AgcManagerDirect(/*num_capture_channels*/ 1,
                        startup_min_level,
                        clipped_level_min,
@@ -408,7 +433,8 @@
                        sample_rate_hz,
                        clipped_level_step,
                        clipped_ratio_threshold,
-                       clipped_wait_frames) {
+                       clipped_wait_frames,
+                       clipping_cfg) {
   RTC_DCHECK(channel_agcs_[0]);
   RTC_DCHECK(agc);
   channel_agcs_[0]->set_agc(agc);
@@ -421,7 +447,8 @@
                                    int sample_rate_hz,
                                    int clipped_level_step,
                                    float clipped_ratio_threshold,
-                                   int clipped_wait_frames)
+                                   int clipped_wait_frames,
+                                   const ClippingPredictorConfig& clipping_cfg)
     : data_dumper_(
           new ApmDataDumper(rtc::AtomicOps::Increment(&instance_counter_))),
       use_min_channel_level_(!UseMaxAnalogChannelLevel()),
@@ -434,7 +461,9 @@
       clipped_ratio_threshold_(clipped_ratio_threshold),
       clipped_wait_frames_(clipped_wait_frames),
       channel_agcs_(num_capture_channels),
-      new_compressions_to_set_(num_capture_channels) {
+      new_compressions_to_set_(num_capture_channels),
+      clipping_predictor_(
+          CreateClippingPredictor(num_capture_channels, clipping_cfg)) {
   const int min_mic_level = GetMinMicLevel();
   for (size_t ch = 0; ch < channel_agcs_.size(); ++ch) {
     ApmDataDumper* data_dumper_ch = ch == 0 ? data_dumper_.get() : nullptr;
@@ -449,7 +478,6 @@
   RTC_DCHECK_GT(clipped_ratio_threshold, 0.f);
   RTC_DCHECK_LT(clipped_ratio_threshold, 1.f);
   RTC_DCHECK_GT(clipped_wait_frames, 0);
-
   channel_agcs_[0]->ActivateLogging();
 }
 
@@ -500,6 +528,12 @@
     return;
   }
 
+  if (!!clipping_predictor_) {
+    AudioFrameView<const float> frame = AudioFrameView<const float>(
+        audio, num_capture_channels_, static_cast<int>(samples_per_channel));
+    clipping_predictor_->Process(frame);
+  }
+
   if (frames_since_clipped_ < clipped_wait_frames_) {
     ++frames_since_clipped_;
     return;
@@ -516,14 +550,37 @@
   // gain is increased, through SetMaxLevel().
   float clipped_ratio =
       ComputeClippedRatio(audio, num_capture_channels_, samples_per_channel);
-
-  if (clipped_ratio > clipped_ratio_threshold_) {
-    RTC_DLOG(LS_INFO) << "[agc] Clipping detected. clipped_ratio="
-                      << clipped_ratio;
+  const bool clipping_detected = clipped_ratio > clipped_ratio_threshold_;
+  bool clipping_predicted = false;
+  int predicted_step = 0;
+  if (!!clipping_predictor_) {
+    for (int channel = 0; channel < num_capture_channels_; ++channel) {
+      const auto step = clipping_predictor_->EstimateClippedLevelStep(
+          channel, stream_analog_level_, clipped_level_step_,
+          channel_agcs_[channel]->min_mic_level(), kMaxMicLevel);
+      if (step.has_value()) {
+        predicted_step = std::max(predicted_step, step.value());
+        clipping_predicted = true;
+      }
+    }
+  }
+  if (clipping_detected || clipping_predicted) {
+    int step = clipped_level_step_;
+    if (clipping_detected) {
+      RTC_DLOG(LS_INFO) << "[agc] Clipping detected. clipped_ratio="
+                        << clipped_ratio;
+    }
+    if (clipping_predicted) {
+      step = std::max(predicted_step, clipped_level_step_);
+      RTC_DLOG(LS_INFO) << "[agc] Clipping predicted. step=" << step;
+    }
     for (auto& state_ch : channel_agcs_) {
-      state_ch->HandleClipping(clipped_level_step_);
+      state_ch->HandleClipping(step);
     }
     frames_since_clipped_ = 0;
+    if (!!clipping_predictor_) {
+      clipping_predictor_->Reset();
+    }
   }
   AggregateChannelLevels();
 }
@@ -606,4 +663,8 @@
   }
 }
 
+bool AgcManagerDirect::clipping_predictor_enabled() const {
+  return !!clipping_predictor_;
+}
+
 }  // namespace webrtc
diff --git a/modules/audio_processing/agc/agc_manager_direct.h b/modules/audio_processing/agc/agc_manager_direct.h
index e0be1a0..55a7ffa 100644
--- a/modules/audio_processing/agc/agc_manager_direct.h
+++ b/modules/audio_processing/agc/agc_manager_direct.h
@@ -15,6 +15,7 @@
 
 #include "absl/types/optional.h"
 #include "modules/audio_processing/agc/agc.h"
+#include "modules/audio_processing/agc/clipping_predictor.h"
 #include "modules/audio_processing/audio_buffer.h"
 #include "modules/audio_processing/logging/apm_data_dumper.h"
 #include "rtc_base/gtest_prod_util.h"
@@ -47,7 +48,9 @@
                    int sample_rate_hz,
                    int clipped_level_step,
                    float clipped_ratio_threshold,
-                   int clipped_wait_frames);
+                   int clipped_wait_frames,
+                   const AudioProcessing::Config::GainController1::
+                       AnalogGainController::ClippingPredictor& clipping_cfg);
 
   ~AgcManagerDirect();
   AgcManagerDirect(const AgcManagerDirect&) = delete;
@@ -69,6 +72,9 @@
   int num_channels() const { return num_capture_channels_; }
   int sample_rate_hz() const { return sample_rate_hz_; }
 
+  // Returns true if clipping prediction was set to be used in ctor.
+  bool clipping_predictor_enabled() const;
+
   // If available, returns a new compression gain for the digital gain control.
   absl::optional<int> GetDigitalComressionGain();
 
@@ -91,6 +97,10 @@
                            AgcMinMicLevelExperimentEnabledAboveStartupLevel);
   FRIEND_TEST_ALL_PREFIXES(AgcManagerDirectStandaloneTest,
                            ClippingParametersVerified);
+  FRIEND_TEST_ALL_PREFIXES(AgcManagerDirectStandaloneTest,
+                           DisableClippingPredictorDoesNotLowerVolume);
+  FRIEND_TEST_ALL_PREFIXES(AgcManagerDirectStandaloneTest,
+                           EnableClippingPredictorLowersVolume);
 
   // Dependency injection for testing. Don't delete |agc| as the memory is owned
   // by the manager.
@@ -100,7 +110,9 @@
                    int sample_rate_hz,
                    int clipped_level_step,
                    float clipped_ratio_threshold,
-                   int clipped_wait_frames);
+                   int clipped_wait_frames,
+                   const AudioProcessing::Config::GainController1::
+                       AnalogGainController::ClippingPredictor& clipping_cfg);
 
   void AnalyzePreProcess(const float* const* audio, size_t samples_per_channel);
 
@@ -124,6 +136,8 @@
 
   std::vector<std::unique_ptr<MonoAgc>> channel_agcs_;
   std::vector<absl::optional<int>> new_compressions_to_set_;
+
+  const std::unique_ptr<ClippingPredictor> clipping_predictor_;
 };
 
 class MonoAgc {
diff --git a/modules/audio_processing/agc/agc_manager_direct_unittest.cc b/modules/audio_processing/agc/agc_manager_direct_unittest.cc
index 6fdfa6d..07bb040 100644
--- a/modules/audio_processing/agc/agc_manager_direct_unittest.cc
+++ b/modules/audio_processing/agc/agc_manager_direct_unittest.cc
@@ -37,6 +37,9 @@
 constexpr float kClippedRatioThreshold = 0.1f;
 constexpr int kClippedWaitFrames = 300;
 
+using ClippingPredictorConfig = AudioProcessing::Config::GainController1::
+    AnalogGainController::ClippingPredictor;
+
 class MockGainControl : public GainControl {
  public:
   virtual ~MockGainControl() {}
@@ -67,7 +70,46 @@
   return std::make_unique<AgcManagerDirect>(
       /*num_capture_channels=*/1, startup_min_level, kClippedMin,
       /*disable_digital_adaptive=*/true, kSampleRateHz, clipped_level_step,
-      clipped_ratio_threshold, clipped_wait_frames);
+      clipped_ratio_threshold, clipped_wait_frames, ClippingPredictorConfig());
+}
+
+std::unique_ptr<AgcManagerDirect> CreateAgcManagerDirect(
+    int startup_min_level,
+    int clipped_level_step,
+    float clipped_ratio_threshold,
+    int clipped_wait_frames,
+    const ClippingPredictorConfig& clipping_cfg) {
+  return std::make_unique<AgcManagerDirect>(
+      /*num_capture_channels=*/1, startup_min_level, kClippedMin,
+      /*disable_digital_adaptive=*/true, kSampleRateHz, clipped_level_step,
+      clipped_ratio_threshold, clipped_wait_frames, clipping_cfg);
+}
+
+void CallPreProcessAudioBuffer(int num_calls,
+                               float peak_ratio,
+                               AgcManagerDirect& manager) {
+  RTC_DCHECK_GE(1.f, peak_ratio);
+  AudioBuffer audio_buffer(kSampleRateHz, 1, kSampleRateHz, 1, kSampleRateHz,
+                           1);
+  const int num_channels = audio_buffer.num_channels();
+  const int num_frames = audio_buffer.num_frames();
+  for (int ch = 0; ch < num_channels; ++ch) {
+    for (int i = 0; i < num_frames; i += 2) {
+      audio_buffer.channels()[ch][i] = peak_ratio * 32767.f;
+      audio_buffer.channels()[ch][i + 1] = 0.0f;
+    }
+  }
+  for (int n = 0; n < num_calls / 2; ++n) {
+    manager.AnalyzePreProcess(&audio_buffer);
+  }
+  for (int ch = 0; ch < num_channels; ++ch) {
+    for (int i = 0; i < num_frames; ++i) {
+      audio_buffer.channels()[ch][i] = peak_ratio * 32767.f;
+    }
+  }
+  for (int n = 0; n < num_calls - num_calls / 2; ++n) {
+    manager.AnalyzePreProcess(&audio_buffer);
+  }
 }
 
 }  // namespace
@@ -82,7 +124,8 @@
                  kSampleRateHz,
                  kClippedLevelStep,
                  kClippedRatioThreshold,
-                 kClippedWaitFrames),
+                 kClippedWaitFrames,
+                 ClippingPredictorConfig()),
         audio(kNumChannels),
         audio_data(kNumChannels * kSamplesPerChannel, 0.f) {
     ExpectInitialize();
@@ -137,12 +180,32 @@
         audio[ch][k] = 32767.f;
       }
     }
-
     for (int i = 0; i < num_calls; ++i) {
       manager_.AnalyzePreProcess(audio.data(), kSamplesPerChannel);
     }
   }
 
+  void CallPreProcForChangingAudio(int num_calls, float peak_ratio) {
+    RTC_DCHECK_GE(1.f, peak_ratio);
+    std::fill(audio_data.begin(), audio_data.end(), 0.f);
+    for (size_t ch = 0; ch < kNumChannels; ++ch) {
+      for (size_t k = 0; k < kSamplesPerChannel; k += 2) {
+        audio[ch][k] = peak_ratio * 32767.f;
+      }
+    }
+    for (int i = 0; i < num_calls / 2; ++i) {
+      manager_.AnalyzePreProcess(audio.data(), kSamplesPerChannel);
+    }
+    for (size_t ch = 0; ch < kNumChannels; ++ch) {
+      for (size_t k = 0; k < kSamplesPerChannel; ++k) {
+        audio[ch][k] = peak_ratio * 32767.f;
+      }
+    }
+    for (int i = 0; i < num_calls - num_calls / 2; ++i) {
+      manager_.AnalyzePreProcess(audio.data(), kSamplesPerChannel);
+    }
+  }
+
   MockAgc* agc_;
   MockGainControl gctrl_;
   AgcManagerDirect manager_;
@@ -709,6 +772,25 @@
   EXPECT_EQ(0, manager_.stream_analog_level());
 }
 
+TEST_F(AgcManagerDirectTest, ClippingDetectionLowersVolume) {
+  SetVolumeAndProcess(255);
+  EXPECT_EQ(255, manager_.stream_analog_level());
+  CallPreProcForChangingAudio(/*num_calls=*/100, /*peak_ratio=*/0.99f);
+  EXPECT_EQ(255, manager_.stream_analog_level());
+  CallPreProcForChangingAudio(/*num_calls=*/100, /*peak_ratio=*/1.0f);
+  EXPECT_EQ(240, manager_.stream_analog_level());
+}
+
+TEST_F(AgcManagerDirectTest, DisabledClippingPredictorDoesNotLowerVolume) {
+  SetVolumeAndProcess(255);
+  EXPECT_FALSE(manager_.clipping_predictor_enabled());
+  EXPECT_EQ(255, manager_.stream_analog_level());
+  CallPreProcForChangingAudio(/*num_calls=*/100, /*peak_ratio=*/0.99f);
+  EXPECT_EQ(255, manager_.stream_analog_level());
+  CallPreProcForChangingAudio(/*num_calls=*/100, /*peak_ratio=*/0.99f);
+  EXPECT_EQ(255, manager_.stream_analog_level());
+}
+
 TEST(AgcManagerDirectStandaloneTest, DisableDigitalDisablesDigital) {
   auto agc = std::unique_ptr<Agc>(new ::testing::NiceMock<MockAgc>());
   MockGainControl gctrl;
@@ -807,13 +889,81 @@
   EXPECT_EQ(manager->clipped_wait_frames_, kClippedWaitFrames);
   std::unique_ptr<AgcManagerDirect> manager_custom =
       CreateAgcManagerDirect(kInitialVolume,
-                             /*clipped_level_step*/ 10,
-                             /*clipped_ratio_threshold*/ 0.2f,
-                             /*clipped_wait_frames*/ 50);
+                             /*clipped_level_step=*/10,
+                             /*clipped_ratio_threshold=*/0.2f,
+                             /*clipped_wait_frames=*/50);
   manager_custom->Initialize();
   EXPECT_EQ(manager_custom->clipped_level_step_, 10);
   EXPECT_EQ(manager_custom->clipped_ratio_threshold_, 0.2f);
   EXPECT_EQ(manager_custom->clipped_wait_frames_, 50);
 }
 
+TEST(AgcManagerDirectStandaloneTest,
+     DisableClippingPredictorDisablesClippingPredictor) {
+  ClippingPredictorConfig default_config;
+  EXPECT_FALSE(default_config.enabled);
+  std::unique_ptr<AgcManagerDirect> manager = CreateAgcManagerDirect(
+      kInitialVolume, kClippedLevelStep, kClippedRatioThreshold,
+      kClippedWaitFrames, default_config);
+  manager->Initialize();
+  EXPECT_FALSE(manager->clipping_predictor_enabled());
+}
+
+TEST(AgcManagerDirectStandaloneTest,
+     EnableClippingPredictorEnablesClippingPredictor) {
+  const ClippingPredictorConfig config(
+      {/*enabled=*/true, ClippingPredictorConfig::kClippingEventPrediction,
+       /*window_length=*/5, /*reference_window_length=*/5,
+       /*reference_window_delay=*/5, /*clipping_threshold=*/-1.0f,
+       /*crest_factor_margin=*/3.0f});
+  std::unique_ptr<AgcManagerDirect> manager = CreateAgcManagerDirect(
+      kInitialVolume, kClippedLevelStep, kClippedRatioThreshold,
+      kClippedWaitFrames, config);
+  manager->Initialize();
+  EXPECT_TRUE(manager->clipping_predictor_enabled());
+}
+
+TEST(AgcManagerDirectStandaloneTest,
+     DisableClippingPredictorDoesNotLowerVolume) {
+  const ClippingPredictorConfig default_config;
+  EXPECT_FALSE(default_config.enabled);
+  AgcManagerDirect manager(new ::testing::NiceMock<MockAgc>(), kInitialVolume,
+                           kClippedMin, kSampleRateHz, kClippedLevelStep,
+                           kClippedRatioThreshold, kClippedWaitFrames,
+                           default_config);
+  manager.Initialize();
+  manager.set_stream_analog_level(/*level=*/255);
+  EXPECT_FALSE(manager.clipping_predictor_enabled());
+  EXPECT_EQ(manager.stream_analog_level(), 255);
+  manager.Process(nullptr);
+  CallPreProcessAudioBuffer(/*num_calls=*/10, /*peak_ratio=*/0.99f, manager);
+  EXPECT_EQ(manager.stream_analog_level(), 255);
+  CallPreProcessAudioBuffer(/*num_calls=*/300, /*peak_ratio=*/0.99f, manager);
+  EXPECT_EQ(manager.stream_analog_level(), 255);
+  CallPreProcessAudioBuffer(/*num_calls=*/10, /*peak_ratio=*/0.99f, manager);
+  EXPECT_EQ(manager.stream_analog_level(), 255);
+}
+
+TEST(AgcManagerDirectStandaloneTest, EnableClippingPredictorLowersVolume) {
+  const ClippingPredictorConfig config(
+      {/*enabled=*/true, ClippingPredictorConfig::kClippingEventPrediction,
+       /*window_length=*/5, /*reference_window_length=*/5,
+       /*reference_window_delay=*/5, /*clipping_threshold=*/-1.0f,
+       /*crest_factor_margin=*/3.0f});
+  AgcManagerDirect manager(new ::testing::NiceMock<MockAgc>(), kInitialVolume,
+                           kClippedMin, kSampleRateHz, kClippedLevelStep,
+                           kClippedRatioThreshold, kClippedWaitFrames, config);
+  manager.Initialize();
+  manager.set_stream_analog_level(/*level=*/255);
+  EXPECT_TRUE(manager.clipping_predictor_enabled());
+  EXPECT_EQ(manager.stream_analog_level(), 255);
+  manager.Process(nullptr);
+  CallPreProcessAudioBuffer(/*num_calls=*/10, /*peak_ratio=*/0.99f, manager);
+  EXPECT_EQ(manager.stream_analog_level(), 240);
+  CallPreProcessAudioBuffer(/*num_calls=*/300, /*peak_ratio=*/0.99f, manager);
+  EXPECT_EQ(manager.stream_analog_level(), 240);
+  CallPreProcessAudioBuffer(/*num_calls=*/10, /*peak_ratio=*/0.99f, manager);
+  EXPECT_EQ(manager.stream_analog_level(), 225);
+}
+
 }  // namespace webrtc
diff --git a/modules/audio_processing/agc/clipping_predictor.h b/modules/audio_processing/agc/clipping_predictor.h
index 301e47e..0fe9827 100644
--- a/modules/audio_processing/agc/clipping_predictor.h
+++ b/modules/audio_processing/agc/clipping_predictor.h
@@ -48,21 +48,21 @@
 // prediction.
 std::unique_ptr<ClippingPredictor> CreateClippingEventPredictor(
     int num_channels,
-    const AudioProcessing::Config::GainController1 ::AnalogGainController::
+    const AudioProcessing::Config::GainController1::AnalogGainController::
         ClippingPredictor& config);
 
 // Creates a ClippingPredictor based on crest factor-based peak estimation and
 // fixed-step clipped level step estimation.
 std::unique_ptr<ClippingPredictor> CreateFixedStepClippingPeakPredictor(
     int num_channels,
-    const AudioProcessing::Config::GainController1 ::AnalogGainController::
+    const AudioProcessing::Config::GainController1::AnalogGainController::
         ClippingPredictor& config);
 
 // Creates a ClippingPredictor based on crest factor-based peak estimation and
 // adaptive-step clipped level step estimation.
 std::unique_ptr<ClippingPredictor> CreateAdaptiveStepClippingPeakPredictor(
     int num_channels,
-    const AudioProcessing::Config::GainController1 ::AnalogGainController::
+    const AudioProcessing::Config::GainController1::AnalogGainController::
         ClippingPredictor& config);
 
 }  // namespace webrtc
diff --git a/modules/audio_processing/agc/clipping_predictor_unittest.cc b/modules/audio_processing/agc/clipping_predictor_unittest.cc
index e27ae28..ab76aba 100644
--- a/modules/audio_processing/agc/clipping_predictor_unittest.cc
+++ b/modules/audio_processing/agc/clipping_predictor_unittest.cc
@@ -32,7 +32,7 @@
 constexpr int kMinMicLevel = 12;
 constexpr int kDefaultClippedLevelStep = 15;
 
-using ClippingPredictorConfig = AudioProcessing::Config::GainController1 ::
+using ClippingPredictorConfig = AudioProcessing::Config::GainController1::
     AnalogGainController::ClippingPredictor;
 
 void CallProcess(int num_calls,
diff --git a/modules/audio_processing/audio_processing_impl.cc b/modules/audio_processing/audio_processing_impl.cc
index 3c5d9fb..4a19855 100644
--- a/modules/audio_processing/audio_processing_impl.cc
+++ b/modules/audio_processing/audio_processing_impl.cc
@@ -1921,7 +1921,8 @@
         capture_nonlocked_.split_rate,
         config_.gain_controller1.analog_gain_controller.clipped_level_step,
         config_.gain_controller1.analog_gain_controller.clipped_ratio_threshold,
-        config_.gain_controller1.analog_gain_controller.clipped_wait_frames));
+        config_.gain_controller1.analog_gain_controller.clipped_wait_frames,
+        config_.gain_controller1.analog_gain_controller.clipping_predictor));
     if (re_creation) {
       submodules_.agc_manager->set_stream_analog_level(stream_analog_level);
     }