Utilizing the AEC3 config struct for constants.

This CL replaces inline constants with config struct
constants.

BUG=webrtc:5298

Review-Url: https://codereview.webrtc.org/3003733002
Cr-Original-Commit-Position: refs/heads/master@{#19507}
Cr-Mirrored-From: https://chromium.googlesource.com/external/webrtc
Cr-Mirrored-Commit: 8cee56f2546c329d193d9478e29894cf9f6ad2ff
diff --git a/modules/audio_processing/aec3/adaptive_fir_filter_unittest.cc b/modules/audio_processing/aec3/adaptive_fir_filter_unittest.cc
index ddc7896..c861d46 100644
--- a/modules/audio_processing/aec3/adaptive_fir_filter_unittest.cc
+++ b/modules/audio_processing/aec3/adaptive_fir_filter_unittest.cc
@@ -305,7 +305,7 @@
   std::vector<std::vector<float>> x(3, std::vector<float>(kBlockSize, 0.f));
   std::vector<float> n(kBlockSize, 0.f);
   std::vector<float> y(kBlockSize, 0.f);
-  AecState aec_state(0.f);
+  AecState aec_state(AudioProcessing::Config::EchoCanceller3{});
   RenderSignalAnalyzer render_signal_analyzer;
   std::vector<float> e(kBlockSize, 0.f);
   std::array<float, kFftLength> s_scratch;
diff --git a/modules/audio_processing/aec3/aec_state.cc b/modules/audio_processing/aec3/aec_state.cc
index cc344ab..6908270 100644
--- a/modules/audio_processing/aec3/aec_state.cc
+++ b/modules/audio_processing/aec3/aec_state.cc
@@ -75,11 +75,15 @@
 
 int AecState::instance_count_ = 0;
 
-AecState::AecState(float reverb_decay)
+AecState::AecState(const AudioProcessing::Config::EchoCanceller3& config)
     : data_dumper_(
           new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))),
+      erle_estimator_(config.param.erle.min,
+                      config.param.erle.max_l,
+                      config.param.erle.max_h),
       echo_path_change_counter_(kEchoPathChangeCounterInitial),
-      reverb_decay_(reverb_decay) {}
+      config_(config),
+      reverb_decay_(config_.param.ep_strength.default_len) {}
 
 AecState::~AecState() = default;
 
@@ -252,7 +256,8 @@
 
       // Limit the estimated reverb_decay_ to the maximum one needed in practice
       // to minimize the impact of incorrect estimates.
-      reverb_decay_ = std::min(0.8f, reverb_decay_);
+      reverb_decay_ =
+          std::min(config_.param.ep_strength.default_len, reverb_decay_);
     }
     reverb_decay_to_test_ = 0.9f;
     reverb_decay_candidate_residual_ = -1.f;
@@ -260,7 +265,7 @@
 
   // For noisy impulse responses, assume a fixed tail length.
   if (tail_power > 0.0005f) {
-    reverb_decay_ = 0.7f;
+    reverb_decay_ = config_.param.ep_strength.default_len;
   }
   data_dumper_->DumpRaw("aec3_reverb_decay", reverb_decay_);
   data_dumper_->DumpRaw("aec3_tail_power", tail_power);
diff --git a/modules/audio_processing/aec3/aec_state.h b/modules/audio_processing/aec3/aec_state.h
index 5192a92..44a1767 100644
--- a/modules/audio_processing/aec3/aec_state.h
+++ b/modules/audio_processing/aec3/aec_state.h
@@ -20,6 +20,7 @@
 #include "webrtc/modules/audio_processing/aec3/erl_estimator.h"
 #include "webrtc/modules/audio_processing/aec3/erle_estimator.h"
 #include "webrtc/modules/audio_processing/aec3/render_buffer.h"
+#include "webrtc/modules/audio_processing/include/audio_processing.h"
 #include "webrtc/rtc_base/array_view.h"
 #include "webrtc/rtc_base/constructormagic.h"
 #include "webrtc/rtc_base/optional.h"
@@ -31,7 +32,7 @@
 // Handles the state and the conditions for the echo removal functionality.
 class AecState {
  public:
-  explicit AecState(float reverb_decay);
+  explicit AecState(const AudioProcessing::Config::EchoCanceller3& config);
   ~AecState();
 
   // Returns whether the linear filter estimate is usable.
@@ -140,13 +141,14 @@
   rtc::Optional<size_t> filter_delay_;
   rtc::Optional<size_t> external_delay_;
   size_t blocks_since_last_saturation_ = 1000;
-  float reverb_decay_;
   float reverb_decay_to_test_ = 0.9f;
   float reverb_decay_candidate_ = 0.f;
   float reverb_decay_candidate_residual_ = -1.f;
   EchoAudibility echo_audibility_;
+  const AudioProcessing::Config::EchoCanceller3 config_;
+  float reverb_decay_;
 
-  RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(AecState);
+  RTC_DISALLOW_COPY_AND_ASSIGN(AecState);
 };
 
 }  // namespace webrtc
diff --git a/modules/audio_processing/aec3/aec_state_unittest.cc b/modules/audio_processing/aec3/aec_state_unittest.cc
index 7062d24..05530ca 100644
--- a/modules/audio_processing/aec3/aec_state_unittest.cc
+++ b/modules/audio_processing/aec3/aec_state_unittest.cc
@@ -18,7 +18,7 @@
 // Verify the general functionality of AecState
 TEST(AecState, NormalUsage) {
   ApmDataDumper data_dumper(42);
-  AecState state(0.f);
+  AecState state(AudioProcessing::Config::EchoCanceller3{});
   RenderBuffer render_buffer(Aec3Optimization::kNone, 3, 30,
                              std::vector<size_t>(1, 30));
   std::array<float, kFftLengthBy2Plus1> E2_main = {};
@@ -163,7 +163,7 @@
 
 // Verifies the a non-significant delay is correctly identified.
 TEST(AecState, NonSignificantDelay) {
-  AecState state(0.f);
+  AecState state(AudioProcessing::Config::EchoCanceller3{});
   RenderBuffer render_buffer(Aec3Optimization::kNone, 3, 30,
                              std::vector<size_t>(1, 30));
   std::array<float, kFftLengthBy2Plus1> E2_main;
@@ -192,7 +192,7 @@
 // Verifies the delay for a converged filter is correctly identified.
 TEST(AecState, ConvergedFilterDelay) {
   constexpr int kFilterLength = 10;
-  AecState state(0.f);
+  AecState state(AudioProcessing::Config::EchoCanceller3{});
   RenderBuffer render_buffer(Aec3Optimization::kNone, 3, 30,
                              std::vector<size_t>(1, 30));
   std::array<float, kFftLengthBy2Plus1> E2_main;
@@ -228,7 +228,7 @@
 
 // Verify that the externally reported delay is properly reported and converted.
 TEST(AecState, ExternalDelay) {
-  AecState state(0.f);
+  AecState state(AudioProcessing::Config::EchoCanceller3{});
   std::array<float, kFftLengthBy2Plus1> E2_main;
   std::array<float, kFftLengthBy2Plus1> E2_shadow;
   std::array<float, kFftLengthBy2Plus1> Y2;
diff --git a/modules/audio_processing/aec3/comfort_noise_generator_unittest.cc b/modules/audio_processing/aec3/comfort_noise_generator_unittest.cc
index 9e10ee8..7cb0aa1 100644
--- a/modules/audio_processing/aec3/comfort_noise_generator_unittest.cc
+++ b/modules/audio_processing/aec3/comfort_noise_generator_unittest.cc
@@ -36,7 +36,8 @@
   std::array<float, kFftLengthBy2Plus1> N2;
   FftData noise;
   EXPECT_DEATH(ComfortNoiseGenerator(DetectOptimization())
-                   .Compute(AecState(0.f), N2, nullptr, &noise),
+                   .Compute(AecState(AudioProcessing::Config::EchoCanceller3{}),
+                            N2, nullptr, &noise),
                "");
 }
 
@@ -44,7 +45,8 @@
   std::array<float, kFftLengthBy2Plus1> N2;
   FftData noise;
   EXPECT_DEATH(ComfortNoiseGenerator(DetectOptimization())
-                   .Compute(AecState(0.f), N2, &noise, nullptr),
+                   .Compute(AecState(AudioProcessing::Config::EchoCanceller3{}),
+                            N2, &noise, nullptr),
                "");
 }
 
@@ -91,7 +93,7 @@
 
 TEST(ComfortNoiseGenerator, CorrectLevel) {
   ComfortNoiseGenerator cng(DetectOptimization());
-  AecState aec_state(0.f);
+  AecState aec_state(AudioProcessing::Config::EchoCanceller3{});
 
   std::array<float, kFftLengthBy2Plus1> N2;
   N2.fill(1000.f * 1000.f);
diff --git a/modules/audio_processing/aec3/echo_remover.cc b/modules/audio_processing/aec3/echo_remover.cc
index a67a04e..32ecc73 100644
--- a/modules/audio_processing/aec3/echo_remover.cc
+++ b/modules/audio_processing/aec3/echo_remover.cc
@@ -72,6 +72,7 @@
 
  private:
   static int instance_count_;
+  const AudioProcessing::Config::EchoCanceller3 config_;
   const Aec3Fft fft_;
   std::unique_ptr<ApmDataDumper> data_dumper_;
   const Aec3Optimization optimization_;
@@ -95,16 +96,18 @@
 EchoRemoverImpl::EchoRemoverImpl(
     const AudioProcessing::Config::EchoCanceller3& config,
     int sample_rate_hz)
-    : fft_(),
+    : config_(config),
+      fft_(),
       data_dumper_(
           new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))),
       optimization_(DetectOptimization()),
       sample_rate_hz_(sample_rate_hz),
       subtractor_(data_dumper_.get(), optimization_),
-      suppression_gain_(optimization_),
+      suppression_gain_(config_, optimization_),
       cng_(optimization_),
       suppression_filter_(sample_rate_hz_),
-      aec_state_(0.8f) {
+      residual_echo_estimator_(config_),
+      aec_state_(config_) {
   RTC_DCHECK(ValidFullBandRate(sample_rate_hz));
 }
 
diff --git a/modules/audio_processing/aec3/echo_remover_metrics_unittest.cc b/modules/audio_processing/aec3/echo_remover_metrics_unittest.cc
index 21a5af2..094508e 100644
--- a/modules/audio_processing/aec3/echo_remover_metrics_unittest.cc
+++ b/modules/audio_processing/aec3/echo_remover_metrics_unittest.cc
@@ -126,7 +126,7 @@
 // Verify the general functionality of EchoRemoverMetrics.
 TEST(EchoRemoverMetrics, NormalUsage) {
   EchoRemoverMetrics metrics;
-  AecState aec_state(0.f);
+  AecState aec_state(AudioProcessing::Config::EchoCanceller3{});
   std::array<float, kFftLengthBy2Plus1> comfort_noise_spectrum;
   std::array<float, kFftLengthBy2Plus1> suppressor_gain;
   comfort_noise_spectrum.fill(10.f);
diff --git a/modules/audio_processing/aec3/erle_estimator.cc b/modules/audio_processing/aec3/erle_estimator.cc
index 8cdaee5..da0e421 100644
--- a/modules/audio_processing/aec3/erle_estimator.cc
+++ b/modules/audio_processing/aec3/erle_estimator.cc
@@ -16,16 +16,13 @@
 
 namespace webrtc {
 
-namespace {
-
-constexpr float kMinErle = 1.f;
-constexpr float kMaxLfErle = 8.f;
-constexpr float kMaxHfErle = 1.5f;
-
-}  // namespace
-
-ErleEstimator::ErleEstimator() {
-  erle_.fill(kMinErle);
+ErleEstimator::ErleEstimator(float min_erle,
+                             float max_erle_lf,
+                             float max_erle_hf)
+    : min_erle_(min_erle),
+      max_erle_lf_(max_erle_lf),
+      max_erle_hf_(max_erle_hf) {
+  erle_.fill(min_erle_);
   hold_counters_.fill(0);
 }
 
@@ -50,19 +47,19 @@
         if (new_erle > erle_[k]) {
           hold_counters_[k - 1] = 100;
           erle_[k] += 0.1f * (new_erle - erle_[k]);
-          erle_[k] = rtc::SafeClamp(erle_[k], kMinErle, max_erle);
+          erle_[k] = rtc::SafeClamp(erle_[k], min_erle_, max_erle);
         }
       }
     }
   };
-  erle_update(1, kFftLengthBy2 / 2, kMaxLfErle);
-  erle_update(kFftLengthBy2 / 2, kFftLengthBy2, kMaxHfErle);
+  erle_update(1, kFftLengthBy2 / 2, max_erle_lf_);
+  erle_update(kFftLengthBy2 / 2, kFftLengthBy2, max_erle_hf_);
 
   std::for_each(hold_counters_.begin(), hold_counters_.end(),
                 [](int& a) { --a; });
   std::transform(hold_counters_.begin(), hold_counters_.end(),
-                 erle_.begin() + 1, erle_.begin() + 1, [](int a, float b) {
-                   return a > 0 ? b : std::max(kMinErle, 0.97f * b);
+                 erle_.begin() + 1, erle_.begin() + 1, [&](int a, float b) {
+                   return a > 0 ? b : std::max(min_erle_, 0.97f * b);
                  });
 
   erle_[0] = erle_[1];
diff --git a/modules/audio_processing/aec3/erle_estimator.h b/modules/audio_processing/aec3/erle_estimator.h
index 48bb75a..91a8c6c 100644
--- a/modules/audio_processing/aec3/erle_estimator.h
+++ b/modules/audio_processing/aec3/erle_estimator.h
@@ -21,7 +21,7 @@
 // Estimates the echo return loss enhancement based on the signal spectra.
 class ErleEstimator {
  public:
-  ErleEstimator();
+  ErleEstimator(float min_erle, float max_erle_lf, float max_erle_hf);
   ~ErleEstimator();
 
   // Updates the ERLE estimate.
@@ -35,6 +35,9 @@
  private:
   std::array<float, kFftLengthBy2Plus1> erle_;
   std::array<int, kFftLengthBy2Minus1> hold_counters_;
+  const float min_erle_;
+  const float max_erle_lf_;
+  const float max_erle_hf_;
 
   RTC_DISALLOW_COPY_AND_ASSIGN(ErleEstimator);
 };
diff --git a/modules/audio_processing/aec3/erle_estimator_unittest.cc b/modules/audio_processing/aec3/erle_estimator_unittest.cc
index dc95eee..be435c0 100644
--- a/modules/audio_processing/aec3/erle_estimator_unittest.cc
+++ b/modules/audio_processing/aec3/erle_estimator_unittest.cc
@@ -36,7 +36,7 @@
   std::array<float, kFftLengthBy2Plus1> E2;
   std::array<float, kFftLengthBy2Plus1> Y2;
 
-  ErleEstimator estimator;
+  ErleEstimator estimator(1.f, 8.f, 1.5f);
 
   // Verifies that the ERLE estimate is properley increased to higher values.
   X2.fill(500 * 1000.f * 1000.f);
diff --git a/modules/audio_processing/aec3/main_filter_update_gain_unittest.cc b/modules/audio_processing/aec3/main_filter_update_gain_unittest.cc
index 6e8a80b..cbd62b5 100644
--- a/modules/audio_processing/aec3/main_filter_update_gain_unittest.cc
+++ b/modules/audio_processing/aec3/main_filter_update_gain_unittest.cc
@@ -53,7 +53,7 @@
   Random random_generator(42U);
   std::vector<std::vector<float>> x(3, std::vector<float>(kBlockSize, 0.f));
   std::vector<float> y(kBlockSize, 0.f);
-  AecState aec_state(0.f);
+  AecState aec_state(AudioProcessing::Config::EchoCanceller3{});
   RenderSignalAnalyzer render_signal_analyzer;
   std::array<float, kFftLength> s_scratch;
   std::array<float, kBlockSize> s;
diff --git a/modules/audio_processing/aec3/residual_echo_estimator.cc b/modules/audio_processing/aec3/residual_echo_estimator.cc
index c708664..0dfec66 100644
--- a/modules/audio_processing/aec3/residual_echo_estimator.cc
+++ b/modules/audio_processing/aec3/residual_echo_estimator.cc
@@ -79,7 +79,9 @@
 
 }  // namespace
 
-ResidualEchoEstimator::ResidualEchoEstimator() {
+ResidualEchoEstimator::ResidualEchoEstimator(
+    const AudioProcessing::Config::EchoCanceller3& config)
+    : config_(config) {
   Reset();
 }
 
@@ -188,11 +190,12 @@
     const std::array<float, kFftLengthBy2Plus1>& Y2,
     std::array<float, kFftLengthBy2Plus1>* R2) {
   // Choose gains.
-  const float echo_path_gain_lf = headset_detected ? kHeadsetEchoPathGain : 100;
+  const float echo_path_gain_lf =
+      headset_detected ? kHeadsetEchoPathGain : config_.param.ep_strength.lf;
   const float echo_path_gain_mf =
-      headset_detected ? kHeadsetEchoPathGain : 1000;
+      headset_detected ? kHeadsetEchoPathGain : config_.param.ep_strength.mf;
   const float echo_path_gain_hf =
-      headset_detected ? kHeadsetEchoPathGain : 5000;
+      headset_detected ? kHeadsetEchoPathGain : config_.param.ep_strength.hf;
 
   // Compute preliminary residual echo.
   std::transform(
diff --git a/modules/audio_processing/aec3/residual_echo_estimator.h b/modules/audio_processing/aec3/residual_echo_estimator.h
index e9370ba..5d2835d 100644
--- a/modules/audio_processing/aec3/residual_echo_estimator.h
+++ b/modules/audio_processing/aec3/residual_echo_estimator.h
@@ -18,6 +18,7 @@
 #include "webrtc/modules/audio_processing/aec3/aec3_common.h"
 #include "webrtc/modules/audio_processing/aec3/aec_state.h"
 #include "webrtc/modules/audio_processing/aec3/render_buffer.h"
+#include "webrtc/modules/audio_processing/include/audio_processing.h"
 #include "webrtc/rtc_base/array_view.h"
 #include "webrtc/rtc_base/constructormagic.h"
 
@@ -25,7 +26,8 @@
 
 class ResidualEchoEstimator {
  public:
-  ResidualEchoEstimator();
+  explicit ResidualEchoEstimator(
+      const AudioProcessing::Config::EchoCanceller3& config);
   ~ResidualEchoEstimator();
 
   void Estimate(bool using_subtractor_output,
@@ -69,8 +71,9 @@
       S2_old_;
   std::array<float, kFftLengthBy2Plus1> X2_noise_floor_;
   std::array<int, kFftLengthBy2Plus1> X2_noise_floor_counter_;
+  const AudioProcessing::Config::EchoCanceller3 config_;
 
-  RTC_DISALLOW_COPY_AND_ASSIGN(ResidualEchoEstimator);
+  RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(ResidualEchoEstimator);
 };
 
 }  // namespace webrtc
diff --git a/modules/audio_processing/aec3/residual_echo_estimator_unittest.cc b/modules/audio_processing/aec3/residual_echo_estimator_unittest.cc
index b448c4d..6abb155 100644
--- a/modules/audio_processing/aec3/residual_echo_estimator_unittest.cc
+++ b/modules/audio_processing/aec3/residual_echo_estimator_unittest.cc
@@ -12,6 +12,7 @@
 
 #include "webrtc/modules/audio_processing/aec3/aec3_fft.h"
 #include "webrtc/modules/audio_processing/aec3/aec_state.h"
+#include "webrtc/modules/audio_processing/include/audio_processing.h"
 #include "webrtc/modules/audio_processing/test/echo_canceller_test_tools.h"
 #include "webrtc/rtc_base/random.h"
 #include "webrtc/test/gtest.h"
@@ -22,22 +23,25 @@
 
 // Verifies that the check for non-null output residual echo power works.
 TEST(ResidualEchoEstimator, NullResidualEchoPowerOutput) {
-  AecState aec_state(0.f);
+  AecState aec_state(AudioProcessing::Config::EchoCanceller3{});
   RenderBuffer render_buffer(Aec3Optimization::kNone, 3, 10,
                              std::vector<size_t>(1, 10));
   std::vector<std::array<float, kFftLengthBy2Plus1>> H2;
   std::array<float, kFftLengthBy2Plus1> S2_linear;
   std::array<float, kFftLengthBy2Plus1> Y2;
-  EXPECT_DEATH(ResidualEchoEstimator().Estimate(true, aec_state, render_buffer,
-                                                S2_linear, Y2, nullptr),
-               "");
+  EXPECT_DEATH(
+      ResidualEchoEstimator(AudioProcessing::Config::EchoCanceller3{})
+          .Estimate(true, aec_state, render_buffer, S2_linear, Y2, nullptr),
+      "");
 }
 
 #endif
 
 TEST(ResidualEchoEstimator, BasicTest) {
-  ResidualEchoEstimator estimator;
-  AecState aec_state(0.f);
+  ResidualEchoEstimator estimator(AudioProcessing::Config::EchoCanceller3{});
+  AudioProcessing::Config::EchoCanceller3 config;
+  config.param.ep_strength.default_len = 0.f;
+  AecState aec_state(config);
   RenderBuffer render_buffer(Aec3Optimization::kNone, 3, 10,
                              std::vector<size_t>(1, 10));
   std::array<float, kFftLengthBy2Plus1> E2_main;
diff --git a/modules/audio_processing/aec3/shadow_filter_update_gain_unittest.cc b/modules/audio_processing/aec3/shadow_filter_update_gain_unittest.cc
index 1ceb634..99e3f25 100644
--- a/modules/audio_processing/aec3/shadow_filter_update_gain_unittest.cc
+++ b/modules/audio_processing/aec3/shadow_filter_update_gain_unittest.cc
@@ -47,7 +47,7 @@
   Random random_generator(42U);
   std::vector<std::vector<float>> x(3, std::vector<float>(kBlockSize, 0.f));
   std::vector<float> y(kBlockSize, 0.f);
-  AecState aec_state(0.f);
+  AecState aec_state(AudioProcessing::Config::EchoCanceller3{});
   RenderSignalAnalyzer render_signal_analyzer;
   std::array<float, kFftLength> s;
   FftData S;
diff --git a/modules/audio_processing/aec3/subtractor_unittest.cc b/modules/audio_processing/aec3/subtractor_unittest.cc
index 32fc054..07b1213 100644
--- a/modules/audio_processing/aec3/subtractor_unittest.cc
+++ b/modules/audio_processing/aec3/subtractor_unittest.cc
@@ -40,7 +40,7 @@
   std::array<float, kFftLengthBy2Plus1> Y2;
   std::array<float, kFftLengthBy2Plus1> E2_main;
   std::array<float, kFftLengthBy2Plus1> E2_shadow;
-  AecState aec_state(0.f);
+  AecState aec_state(AudioProcessing::Config::EchoCanceller3{});
   x_old.fill(0.f);
   Y2.fill(0.f);
   E2_main.fill(0.f);
@@ -109,9 +109,11 @@
   RenderSignalAnalyzer render_signal_analyzer;
   std::vector<float> y(kBlockSize, 0.f);
 
-  EXPECT_DEATH(subtractor.Process(render_buffer, y, render_signal_analyzer,
-                                  AecState(0.f), nullptr),
-               "");
+  EXPECT_DEATH(
+      subtractor.Process(render_buffer, y, render_signal_analyzer,
+                         AecState(AudioProcessing::Config::EchoCanceller3{}),
+                         nullptr),
+      "");
 }
 
 // Verifies the check for the capture signal size.
@@ -124,9 +126,11 @@
   std::vector<float> y(kBlockSize - 1, 0.f);
   SubtractorOutput output;
 
-  EXPECT_DEATH(subtractor.Process(render_buffer, y, render_signal_analyzer,
-                                  AecState(0.f), &output),
-               "");
+  EXPECT_DEATH(
+      subtractor.Process(render_buffer, y, render_signal_analyzer,
+                         AecState(AudioProcessing::Config::EchoCanceller3{}),
+                         &output),
+      "");
 }
 
 #endif
diff --git a/modules/audio_processing/aec3/suppression_gain.cc b/modules/audio_processing/aec3/suppression_gain.cc
index a25f748..8e78967 100644
--- a/modules/audio_processing/aec3/suppression_gain.cc
+++ b/modules/audio_processing/aec3/suppression_gain.cc
@@ -109,6 +109,7 @@
 
 // Limits the gain increase.
 void UpdateMaxGainIncrease(
+    const AudioProcessing::Config::EchoCanceller3& config,
     size_t no_saturation_counter,
     bool low_noise_render,
     const std::array<float, kFftLengthBy2Plus1>& last_echo,
@@ -123,27 +124,28 @@
   float min_increasing;
   float min_decreasing;
 
+  auto& param = config.param.gain_updates;
   if (low_noise_render) {
-    max_increasing = 8.f;
-    max_decreasing = 8.f;
-    rate_increasing = 2.f;
-    rate_decreasing = 2.f;
-    min_increasing = 4.f;
-    min_decreasing = 4.f;
+    max_increasing = param.low_noise.max_inc;
+    max_decreasing = param.low_noise.max_dec;
+    rate_increasing = param.low_noise.rate_inc;
+    rate_decreasing = param.low_noise.rate_dec;
+    min_increasing = param.low_noise.min_inc;
+    min_decreasing = param.low_noise.min_dec;
   } else if (no_saturation_counter > 10) {
-    max_increasing = 4.f;
-    max_decreasing = 4.f;
-    rate_increasing = 2.f;
-    rate_decreasing = 2.f;
-    min_increasing = 1.2f;
-    min_decreasing = 2.f;
+    max_increasing = param.normal.max_inc;
+    max_decreasing = param.normal.max_dec;
+    rate_increasing = param.normal.rate_inc;
+    rate_decreasing = param.normal.rate_dec;
+    min_increasing = param.normal.min_inc;
+    min_decreasing = param.normal.min_dec;
   } else {
-    max_increasing = 1.2f;
-    max_decreasing = 1.2f;
-    rate_increasing = 1.5f;
-    rate_decreasing = 1.5f;
-    min_increasing = 1.f;
-    min_decreasing = 1.f;
+    max_increasing = param.saturation.max_inc;
+    max_decreasing = param.saturation.max_dec;
+    rate_increasing = param.saturation.rate_inc;
+    rate_decreasing = param.saturation.rate_dec;
+    min_increasing = param.saturation.min_inc;
+    min_decreasing = param.saturation.min_dec;
   }
 
   for (size_t k = 0; k < new_gain.size(); ++k) {
@@ -163,6 +165,7 @@
 
 // Computes the gain to reduce the echo to a non audible level.
 void GainToNoAudibleEcho(
+    const AudioProcessing::Config::EchoCanceller3& config,
     bool low_noise_render,
     bool saturated_echo,
     const std::array<float, kFftLengthBy2Plus1>& nearend,
@@ -172,16 +175,17 @@
     const std::array<float, kFftLengthBy2Plus1>& max_gain,
     const std::array<float, kFftLengthBy2Plus1>& one_by_echo,
     std::array<float, kFftLengthBy2Plus1>* gain) {
-  constexpr float kEchoMaskingMargin = 1.f / 100.f;
   const float nearend_masking_margin =
-      low_noise_render ? 0.1f : (saturated_echo ? 0.001f : 0.01f);
+      low_noise_render ? 0.1f
+                       : (saturated_echo ? config.param.gain_mask.m2
+                                         : config.param.gain_mask.m3);
 
   for (size_t k = 0; k < gain->size(); ++k) {
     RTC_DCHECK_LE(0.f, nearend_masking_margin * nearend[k]);
     if (echo[k] <= nearend_masking_margin * nearend[k]) {
       (*gain)[k] = 1.f;
     } else {
-      (*gain)[k] = kEchoMaskingMargin * masker[k] * one_by_echo[k];
+      (*gain)[k] = config.param.gain_mask.m1 * masker[k] * one_by_echo[k];
     }
 
     (*gain)[k] = std::min(std::max((*gain)[k], min_gain[k]), max_gain[k]);
@@ -189,7 +193,8 @@
 }
 
 // Computes the signal output power that masks the echo signal.
-void MaskingPower(const std::array<float, kFftLengthBy2Plus1>& nearend,
+void MaskingPower(const AudioProcessing::Config::EchoCanceller3& config,
+                  const std::array<float, kFftLengthBy2Plus1>& nearend,
                   const std::array<float, kFftLengthBy2Plus1>& comfort_noise,
                   const std::array<float, kFftLengthBy2Plus1>& last_masker,
                   const std::array<float, kFftLengthBy2Plus1>& gain,
@@ -197,7 +202,8 @@
   std::array<float, kFftLengthBy2Plus1> side_band_masker;
   for (size_t k = 0; k < gain.size(); ++k) {
     side_band_masker[k] = nearend[k] * gain[k] + comfort_noise[k];
-    (*masker)[k] = comfort_noise[k] + 0.1f * last_masker[k];
+    (*masker)[k] =
+        comfort_noise[k] + config.param.gain_mask.m4 * last_masker[k];
   }
   for (size_t k = 1; k < gain.size() - 1; ++k) {
     (*masker)[k] += 0.1f * (side_band_masker[k - 1] + side_band_masker[k + 1]);
@@ -227,7 +233,9 @@
   // Compute the minimum gain as the attenuating gain to put the signal just
   // above the zero sample values.
   std::array<float, kFftLengthBy2Plus1> min_gain;
-  const float min_echo_power = low_noise_render ? 192.f : 64.f;
+  const float min_echo_power =
+      low_noise_render ? config_.param.echo_audibility.low_render_limit
+                       : config_.param.echo_audibility.normal_render_limit;
   if (no_saturation_counter_ > 10) {
     for (size_t k = 0; k < nearend.size(); ++k) {
       const float denom = std::min(nearend[k], echo[k]);
@@ -243,7 +251,9 @@
   std::array<float, kFftLengthBy2Plus1> max_gain;
   for (size_t k = 0; k < gain->size(); ++k) {
     max_gain[k] =
-        std::min(std::max(last_gain_[k] * gain_increase_[k], 0.001f), 1.f);
+        std::min(std::max(last_gain_[k] * gain_increase_[k],
+                          config_.param.gain_updates.floor_first_increase),
+                 1.f);
   }
 
   // Iteratively compute the gain required to attenuate the echo to a non
@@ -251,9 +261,9 @@
   gain->fill(0.f);
   for (int k = 0; k < 2; ++k) {
     std::array<float, kFftLengthBy2Plus1> masker;
-    MaskingPower(nearend, comfort_noise, last_masker_, *gain, &masker);
-    GainToNoAudibleEcho(low_noise_render, saturated_echo, nearend, echo, masker,
-                        min_gain, max_gain, one_by_echo, gain);
+    MaskingPower(config_, nearend, comfort_noise, last_masker_, *gain, &masker);
+    GainToNoAudibleEcho(config_, low_noise_render, saturated_echo, nearend,
+                        echo, masker, min_gain, max_gain, one_by_echo, gain);
     AdjustForExternalFilters(gain);
     if (narrow_peak_band) {
       NarrowBandAttenuation(*narrow_peak_band, gain);
@@ -261,18 +271,21 @@
   }
 
   // Update the allowed maximum gain increase.
-  UpdateMaxGainIncrease(no_saturation_counter_, low_noise_render, last_echo_,
-                        echo, last_gain_, *gain, &gain_increase_);
+  UpdateMaxGainIncrease(config_, no_saturation_counter_, low_noise_render,
+                        last_echo_, echo, last_gain_, *gain, &gain_increase_);
 
   // Store data required for the gain computation of the next block.
   std::copy(echo.begin(), echo.end(), last_echo_.begin());
   std::copy(gain->begin(), gain->end(), last_gain_.begin());
-  MaskingPower(nearend, comfort_noise, last_masker_, *gain, &last_masker_);
+  MaskingPower(config_, nearend, comfort_noise, last_masker_, *gain,
+               &last_masker_);
   aec3::VectorMath(optimization_).Sqrt(*gain);
 }
 
-SuppressionGain::SuppressionGain(Aec3Optimization optimization)
-    : optimization_(optimization) {
+SuppressionGain::SuppressionGain(
+    const AudioProcessing::Config::EchoCanceller3& config,
+    Aec3Optimization optimization)
+    : optimization_(optimization), config_(config) {
   last_gain_.fill(1.f);
   last_masker_.fill(0.f);
   gain_increase_.fill(1.f);
diff --git a/modules/audio_processing/aec3/suppression_gain.h b/modules/audio_processing/aec3/suppression_gain.h
index d22eb8a..2d618c3 100644
--- a/modules/audio_processing/aec3/suppression_gain.h
+++ b/modules/audio_processing/aec3/suppression_gain.h
@@ -16,13 +16,15 @@
 
 #include "webrtc/modules/audio_processing/aec3/aec3_common.h"
 #include "webrtc/modules/audio_processing/aec3/render_signal_analyzer.h"
+#include "webrtc/modules/audio_processing/include/audio_processing.h"
 #include "webrtc/rtc_base/constructormagic.h"
 
 namespace webrtc {
 
 class SuppressionGain {
  public:
-  explicit SuppressionGain(Aec3Optimization optimization);
+  SuppressionGain(const AudioProcessing::Config::EchoCanceller3& config,
+                  Aec3Optimization optimization);
   void GetGain(const std::array<float, kFftLengthBy2Plus1>& nearend,
                const std::array<float, kFftLengthBy2Plus1>& echo,
                const std::array<float, kFftLengthBy2Plus1>& comfort_noise,
@@ -58,7 +60,8 @@
 
   LowNoiseRenderDetector low_render_detector_;
   size_t no_saturation_counter_ = 0;
-  RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(SuppressionGain);
+  const AudioProcessing::Config::EchoCanceller3 config_;
+  RTC_DISALLOW_COPY_AND_ASSIGN(SuppressionGain);
 };
 
 }  // namespace webrtc
diff --git a/modules/audio_processing/aec3/suppression_gain_unittest.cc b/modules/audio_processing/aec3/suppression_gain_unittest.cc
index 61238d9..cde3c94 100644
--- a/modules/audio_processing/aec3/suppression_gain_unittest.cc
+++ b/modules/audio_processing/aec3/suppression_gain_unittest.cc
@@ -29,7 +29,8 @@
   R2.fill(0.f);
   N2.fill(0.f);
   float high_bands_gain;
-  EXPECT_DEATH(SuppressionGain(DetectOptimization())
+  EXPECT_DEATH(SuppressionGain(AudioProcessing::Config::EchoCanceller3{},
+                               DetectOptimization())
                    .GetGain(E2, R2, N2, RenderSignalAnalyzer(), false,
                             std::vector<std::vector<float>>(
                                 3, std::vector<float>(kBlockSize, 0.f)),
@@ -41,7 +42,8 @@
 
 // Does a sanity check that the gains are correctly computed.
 TEST(SuppressionGain, BasicGainComputation) {
-  SuppressionGain suppression_gain(DetectOptimization());
+  SuppressionGain suppression_gain(AudioProcessing::Config::EchoCanceller3(),
+                                   DetectOptimization());
   RenderSignalAnalyzer analyzer;
   float high_bands_gain;
   std::array<float, kFftLengthBy2Plus1> E2;
diff --git a/modules/audio_processing/include/audio_processing.h b/modules/audio_processing/include/audio_processing.h
index 0a09517..de77bac 100644
--- a/modules/audio_processing/include/audio_processing.h
+++ b/modules/audio_processing/include/audio_processing.h
@@ -17,6 +17,7 @@
 #include <math.h>
 #include <stddef.h>  // size_t
 #include <stdio.h>  // FILE
+#include <string.h>
 #include <vector>
 
 #include "webrtc/modules/audio_processing/beamformer/array_util.h"
@@ -267,6 +268,49 @@
     // The functionality is not yet activated in the code and turning this on
     // does not yet have the desired behavior.
     struct EchoCanceller3 {
+      struct Param {
+        struct Erle {
+          float min = 1.f;
+          float max_l = 8.f;
+          float max_h = 1.5f;
+        } erle;
+
+        struct EpStrength {
+          float lf = 100.f;
+          float mf = 1000.f;
+          float hf = 5000.f;
+          float default_len = 0.7f;
+        } ep_strength;
+
+        struct Mask {
+          float m1 = 0.01f;
+          float m2 = 0.001f;
+          float m3 = 0.01f;
+          float m4 = 0.1f;
+        } gain_mask;
+
+        struct EchoAudibility {
+          float low_render_limit = 192.f;
+          float normal_render_limit = 64.f;
+        } echo_audibility;
+
+        struct GainUpdates {
+          struct GainChanges {
+            float max_inc;
+            float max_dec;
+            float rate_inc;
+            float rate_dec;
+            float min_inc;
+            float min_dec;
+          };
+
+          GainChanges low_noise = {8.f, 8.f, 2.f, 2.f, 4.f, 4.f};
+          GainChanges normal = {4.f, 4.f, 2.f, 2.f, 1.2f, 2.f};
+          GainChanges saturation = {1.2f, 1.2f, 1.5f, 1.5f, 1.f, 1.f};
+
+          float floor_first_increase = 0.001f;
+        } gain_updates;
+      } param;
       bool enabled = false;
     } echo_canceller3;
 
@@ -277,6 +321,17 @@
     struct GainController2 {
       bool enabled = false;
     } gain_controller2;
+
+    // Explicit copy assignment implementation to avoid issues with memory
+    // sanitizer complaints in case of self-assignment.
+    // TODO(peah): Add buildflag to ensure that this is only included for memory
+    // sanitizer builds.
+    Config& operator=(const Config& config) {
+      if (this != &config) {
+        memcpy(this, &config, sizeof(*this));
+      }
+      return *this;
+    }
   };
 
   // TODO(mgraczyk): Remove once all methods that use ChannelLayout are gone.