Added the ability to adjust the AEC3 performance for large rooms

This CL exposes the parameter for adjusting the AEC3 performance
for large rooms.

Bug: webrtc:7519
Review-Url: https://codereview.webrtc.org/2967603002
Cr-Commit-Position: refs/heads/master@{#18862}
diff --git a/webrtc/modules/audio_processing/aec3/adaptive_fir_filter_unittest.cc b/webrtc/modules/audio_processing/aec3/adaptive_fir_filter_unittest.cc
index 2402d91..83c3ac8 100644
--- a/webrtc/modules/audio_processing/aec3/adaptive_fir_filter_unittest.cc
+++ b/webrtc/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;
+  AecState aec_state(0.f);
   RenderSignalAnalyzer render_signal_analyzer;
   std::vector<float> e(kBlockSize, 0.f);
   std::array<float, kFftLength> s;
diff --git a/webrtc/modules/audio_processing/aec3/aec_state.cc b/webrtc/modules/audio_processing/aec3/aec_state.cc
index de4a0c1..316f888 100644
--- a/webrtc/modules/audio_processing/aec3/aec_state.cc
+++ b/webrtc/modules/audio_processing/aec3/aec_state.cc
@@ -78,10 +78,11 @@
 
 int AecState::instance_count_ = 0;
 
-AecState::AecState()
+AecState::AecState(float echo_decay)
     : data_dumper_(
           new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))),
-      echo_path_change_counter_(kEchoPathChangeCounterInitial) {}
+      echo_path_change_counter_(kEchoPathChangeCounterInitial),
+      echo_decay_factor_(echo_decay) {}
 
 AecState::~AecState() = default;
 
diff --git a/webrtc/modules/audio_processing/aec3/aec_state.h b/webrtc/modules/audio_processing/aec3/aec_state.h
index 519665f..8708936 100644
--- a/webrtc/modules/audio_processing/aec3/aec_state.h
+++ b/webrtc/modules/audio_processing/aec3/aec_state.h
@@ -31,7 +31,7 @@
 // Handles the state and the conditions for the echo removal functionality.
 class AecState {
  public:
-  AecState();
+  explicit AecState(float echo_decay);
   ~AecState();
 
   // Returns whether the linear filter estimate is usable.
@@ -79,7 +79,7 @@
 
   // Returns the decay factor for the echo reverberation.
   // TODO(peah): Make this adaptive.
-  float ReverbDecayFactor() const { return 0.f; }
+  float ReverbDecayFactor() const { return echo_decay_factor_; }
 
   // Returns whether the echo suppression gain should be forced to zero.
   bool ForcedZeroGain() const { return force_zero_gain_; }
@@ -113,8 +113,8 @@
   rtc::Optional<size_t> filter_delay_;
   rtc::Optional<size_t> external_delay_;
   size_t blocks_since_last_saturation_ = 1000;
-
-  RTC_DISALLOW_COPY_AND_ASSIGN(AecState);
+  const float echo_decay_factor_;
+  RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(AecState);
 };
 
 }  // namespace webrtc
diff --git a/webrtc/modules/audio_processing/aec3/aec_state_unittest.cc b/webrtc/modules/audio_processing/aec3/aec_state_unittest.cc
index 90b7cb9..682126e 100644
--- a/webrtc/modules/audio_processing/aec3/aec_state_unittest.cc
+++ b/webrtc/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;
+  AecState state(0.f);
   RenderBuffer render_buffer(Aec3Optimization::kNone, 3, 30,
                              std::vector<size_t>(1, 30));
   std::array<float, kFftLengthBy2Plus1> E2_main = {};
@@ -148,7 +148,7 @@
 
 // Verifies the a non-significant delay is correctly identified.
 TEST(AecState, NonSignificantDelay) {
-  AecState state;
+  AecState state(0.f);
   RenderBuffer render_buffer(Aec3Optimization::kNone, 3, 30,
                              std::vector<size_t>(1, 30));
   std::array<float, kFftLengthBy2Plus1> E2_main;
@@ -172,7 +172,7 @@
 // Verifies the delay for a converged filter is correctly identified.
 TEST(AecState, ConvergedFilterDelay) {
   constexpr int kFilterLength = 10;
-  AecState state;
+  AecState state(0.f);
   RenderBuffer render_buffer(Aec3Optimization::kNone, 3, 30,
                              std::vector<size_t>(1, 30));
   std::array<float, kFftLengthBy2Plus1> E2_main;
@@ -203,7 +203,7 @@
 
 // Verify that the externally reported delay is properly reported and converted.
 TEST(AecState, ExternalDelay) {
-  AecState state;
+  AecState state(0.f);
   std::array<float, kFftLengthBy2Plus1> E2_main;
   std::array<float, kFftLengthBy2Plus1> E2_shadow;
   std::array<float, kFftLengthBy2Plus1> Y2;
diff --git a/webrtc/modules/audio_processing/aec3/block_processor.cc b/webrtc/modules/audio_processing/aec3/block_processor.cc
index bb1286c..2cf5606 100644
--- a/webrtc/modules/audio_processing/aec3/block_processor.cc
+++ b/webrtc/modules/audio_processing/aec3/block_processor.cc
@@ -168,29 +168,33 @@
 
 }  // namespace
 
-BlockProcessor* BlockProcessor::Create(int sample_rate_hz) {
+BlockProcessor* BlockProcessor::Create(
+    const AudioProcessing::Config::EchoCanceller3& config,
+    int sample_rate_hz) {
   std::unique_ptr<RenderDelayBuffer> render_buffer(
       RenderDelayBuffer::Create(NumBandsForRate(sample_rate_hz)));
   std::unique_ptr<RenderDelayController> delay_controller(
       RenderDelayController::Create(sample_rate_hz));
   std::unique_ptr<EchoRemover> echo_remover(
-      EchoRemover::Create(sample_rate_hz));
-  return Create(sample_rate_hz, std::move(render_buffer),
+      EchoRemover::Create(config, sample_rate_hz));
+  return Create(config, sample_rate_hz, std::move(render_buffer),
                 std::move(delay_controller), std::move(echo_remover));
 }
 
 BlockProcessor* BlockProcessor::Create(
+    const AudioProcessing::Config::EchoCanceller3& config,
     int sample_rate_hz,
     std::unique_ptr<RenderDelayBuffer> render_buffer) {
   std::unique_ptr<RenderDelayController> delay_controller(
       RenderDelayController::Create(sample_rate_hz));
   std::unique_ptr<EchoRemover> echo_remover(
-      EchoRemover::Create(sample_rate_hz));
-  return Create(sample_rate_hz, std::move(render_buffer),
+      EchoRemover::Create(config, sample_rate_hz));
+  return Create(config, sample_rate_hz, std::move(render_buffer),
                 std::move(delay_controller), std::move(echo_remover));
 }
 
 BlockProcessor* BlockProcessor::Create(
+    const AudioProcessing::Config::EchoCanceller3& config,
     int sample_rate_hz,
     std::unique_ptr<RenderDelayBuffer> render_buffer,
     std::unique_ptr<RenderDelayController> delay_controller,
diff --git a/webrtc/modules/audio_processing/aec3/block_processor.h b/webrtc/modules/audio_processing/aec3/block_processor.h
index 830fec7..9235931 100644
--- a/webrtc/modules/audio_processing/aec3/block_processor.h
+++ b/webrtc/modules/audio_processing/aec3/block_processor.h
@@ -23,12 +23,16 @@
 // Class for performing echo cancellation on 64 sample blocks of audio data.
 class BlockProcessor {
  public:
-  static BlockProcessor* Create(int sample_rate_hz);
+  static BlockProcessor* Create(
+      const AudioProcessing::Config::EchoCanceller3& config,
+      int sample_rate_hz);
   // Only used for testing purposes.
   static BlockProcessor* Create(
+      const AudioProcessing::Config::EchoCanceller3& config,
       int sample_rate_hz,
       std::unique_ptr<RenderDelayBuffer> render_buffer);
   static BlockProcessor* Create(
+      const AudioProcessing::Config::EchoCanceller3& config,
       int sample_rate_hz,
       std::unique_ptr<RenderDelayBuffer> render_buffer,
       std::unique_ptr<RenderDelayController> delay_controller,
diff --git a/webrtc/modules/audio_processing/aec3/block_processor_unittest.cc b/webrtc/modules/audio_processing/aec3/block_processor_unittest.cc
index 01db982..1c04536 100644
--- a/webrtc/modules/audio_processing/aec3/block_processor_unittest.cc
+++ b/webrtc/modules/audio_processing/aec3/block_processor_unittest.cc
@@ -36,8 +36,8 @@
 // Verifies that the basic BlockProcessor functionality works and that the API
 // methods are callable.
 void RunBasicSetupAndApiCallTest(int sample_rate_hz) {
-  std::unique_ptr<BlockProcessor> block_processor(
-      BlockProcessor::Create(sample_rate_hz));
+  std::unique_ptr<BlockProcessor> block_processor(BlockProcessor::Create(
+      AudioProcessing::Config::EchoCanceller3(), sample_rate_hz));
   std::vector<std::vector<float>> block(NumBandsForRate(sample_rate_hz),
                                         std::vector<float>(kBlockSize, 0.f));
 
@@ -48,8 +48,8 @@
 
 #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
 void RunRenderBlockSizeVerificationTest(int sample_rate_hz) {
-  std::unique_ptr<BlockProcessor> block_processor(
-      BlockProcessor::Create(sample_rate_hz));
+  std::unique_ptr<BlockProcessor> block_processor(BlockProcessor::Create(
+      AudioProcessing::Config::EchoCanceller3(), sample_rate_hz));
   std::vector<std::vector<float>> block(
       NumBandsForRate(sample_rate_hz), std::vector<float>(kBlockSize - 1, 0.f));
 
@@ -57,8 +57,8 @@
 }
 
 void RunCaptureBlockSizeVerificationTest(int sample_rate_hz) {
-  std::unique_ptr<BlockProcessor> block_processor(
-      BlockProcessor::Create(sample_rate_hz));
+  std::unique_ptr<BlockProcessor> block_processor(BlockProcessor::Create(
+      AudioProcessing::Config::EchoCanceller3(), sample_rate_hz));
   std::vector<std::vector<float>> block(
       NumBandsForRate(sample_rate_hz), std::vector<float>(kBlockSize - 1, 0.f));
 
@@ -69,8 +69,8 @@
   const size_t wrong_num_bands = NumBandsForRate(sample_rate_hz) < 3
                                      ? NumBandsForRate(sample_rate_hz) + 1
                                      : 1;
-  std::unique_ptr<BlockProcessor> block_processor(
-      BlockProcessor::Create(sample_rate_hz));
+  std::unique_ptr<BlockProcessor> block_processor(BlockProcessor::Create(
+      AudioProcessing::Config::EchoCanceller3(), sample_rate_hz));
   std::vector<std::vector<float>> block(wrong_num_bands,
                                         std::vector<float>(kBlockSize, 0.f));
 
@@ -81,8 +81,8 @@
   const size_t wrong_num_bands = NumBandsForRate(sample_rate_hz) < 3
                                      ? NumBandsForRate(sample_rate_hz) + 1
                                      : 1;
-  std::unique_ptr<BlockProcessor> block_processor(
-      BlockProcessor::Create(sample_rate_hz));
+  std::unique_ptr<BlockProcessor> block_processor(BlockProcessor::Create(
+      AudioProcessing::Config::EchoCanceller3(), sample_rate_hz));
   std::vector<std::vector<float>> block(wrong_num_bands,
                                         std::vector<float>(kBlockSize, 0.f));
 
@@ -126,7 +126,8 @@
         .Times(kNumBlocks + 1)
         .WillRepeatedly(Return(0));
     std::unique_ptr<BlockProcessor> block_processor(
-        BlockProcessor::Create(rate, std::move(render_delay_buffer_mock)));
+        BlockProcessor::Create(AudioProcessing::Config::EchoCanceller3(), rate,
+                               std::move(render_delay_buffer_mock)));
 
     std::vector<std::vector<float>> render_block(
         NumBandsForRate(rate), std::vector<float>(kBlockSize, 0.f));
@@ -180,7 +181,8 @@
         .Times(kNumBlocks);
 
     std::unique_ptr<BlockProcessor> block_processor(BlockProcessor::Create(
-        rate, std::move(render_delay_buffer_mock),
+        AudioProcessing::Config::EchoCanceller3(), rate,
+        std::move(render_delay_buffer_mock),
         std::move(render_delay_controller_mock), std::move(echo_remover_mock)));
 
     std::vector<std::vector<float>> render_block(
@@ -238,7 +240,9 @@
 
 // Verifiers that the verification for null ProcessCapture input works.
 TEST(BlockProcessor, NullProcessCaptureParameter) {
-  EXPECT_DEATH(std::unique_ptr<BlockProcessor>(BlockProcessor::Create(8000))
+  EXPECT_DEATH(std::unique_ptr<BlockProcessor>(
+                   BlockProcessor::Create(
+                       AudioProcessing::Config::EchoCanceller3(), 8000))
                    ->ProcessCapture(false, false, nullptr),
                "");
 }
@@ -247,7 +251,8 @@
 // TODO(peah): Re-enable the test once the issue with memory leaks during DEATH
 // tests on test bots has been fixed.
 TEST(BlockProcessor, DISABLED_WrongSampleRate) {
-  EXPECT_DEATH(std::unique_ptr<BlockProcessor>(BlockProcessor::Create(8001)),
+  EXPECT_DEATH(std::unique_ptr<BlockProcessor>(BlockProcessor::Create(
+                   AudioProcessing::Config::EchoCanceller3(), 8001)),
                "");
 }
 
diff --git a/webrtc/modules/audio_processing/aec3/comfort_noise_generator_unittest.cc b/webrtc/modules/audio_processing/aec3/comfort_noise_generator_unittest.cc
index dcdbab3..ce86f2d 100644
--- a/webrtc/modules/audio_processing/aec3/comfort_noise_generator_unittest.cc
+++ b/webrtc/modules/audio_processing/aec3/comfort_noise_generator_unittest.cc
@@ -36,7 +36,7 @@
   std::array<float, kFftLengthBy2Plus1> N2;
   FftData noise;
   EXPECT_DEATH(ComfortNoiseGenerator(DetectOptimization())
-                   .Compute(AecState(), N2, nullptr, &noise),
+                   .Compute(AecState(0.f), N2, nullptr, &noise),
                "");
 }
 
@@ -44,7 +44,7 @@
   std::array<float, kFftLengthBy2Plus1> N2;
   FftData noise;
   EXPECT_DEATH(ComfortNoiseGenerator(DetectOptimization())
-                   .Compute(AecState(), N2, &noise, nullptr),
+                   .Compute(AecState(0.f), N2, &noise, nullptr),
                "");
 }
 
@@ -91,7 +91,7 @@
 
 TEST(ComfortNoiseGenerator, CorrectLevel) {
   ComfortNoiseGenerator cng(DetectOptimization());
-  AecState aec_state;
+  AecState aec_state(0.f);
 
   std::array<float, kFftLengthBy2Plus1> N2;
   N2.fill(1000.f * 1000.f);
diff --git a/webrtc/modules/audio_processing/aec3/echo_canceller3.cc b/webrtc/modules/audio_processing/aec3/echo_canceller3.cc
index 4cd9c39..3175c54 100644
--- a/webrtc/modules/audio_processing/aec3/echo_canceller3.cc
+++ b/webrtc/modules/audio_processing/aec3/echo_canceller3.cc
@@ -200,11 +200,14 @@
 
 int EchoCanceller3::instance_count_ = 0;
 
-EchoCanceller3::EchoCanceller3(int sample_rate_hz, bool use_highpass_filter)
+EchoCanceller3::EchoCanceller3(
+    const AudioProcessing::Config::EchoCanceller3& config,
+    int sample_rate_hz,
+    bool use_highpass_filter)
     : EchoCanceller3(sample_rate_hz,
                      use_highpass_filter,
                      std::unique_ptr<BlockProcessor>(
-                         BlockProcessor::Create(sample_rate_hz))) {}
+                         BlockProcessor::Create(config, sample_rate_hz))) {}
 EchoCanceller3::EchoCanceller3(int sample_rate_hz,
                                bool use_highpass_filter,
                                std::unique_ptr<BlockProcessor> block_processor)
@@ -331,7 +334,7 @@
 
 bool EchoCanceller3::Validate(
     const AudioProcessing::Config::EchoCanceller3& config) {
-  return true;
+  return (config.echo_decay >= 0.f && config.echo_decay < 1.f);
 }
 
 void EchoCanceller3::EmptyRenderQueue() {
diff --git a/webrtc/modules/audio_processing/aec3/echo_canceller3.h b/webrtc/modules/audio_processing/aec3/echo_canceller3.h
index aa19c05..6324cc6 100644
--- a/webrtc/modules/audio_processing/aec3/echo_canceller3.h
+++ b/webrtc/modules/audio_processing/aec3/echo_canceller3.h
@@ -63,7 +63,9 @@
 class EchoCanceller3 {
  public:
   // Normal c-tor to use.
-  EchoCanceller3(int sample_rate_hz, bool use_highpass_filter);
+  EchoCanceller3(const AudioProcessing::Config::EchoCanceller3& config,
+                 int sample_rate_hz,
+                 bool use_highpass_filter);
   // Testing c-tor that is used only for testing purposes.
   EchoCanceller3(int sample_rate_hz,
                  bool use_highpass_filter,
diff --git a/webrtc/modules/audio_processing/aec3/echo_canceller3_unittest.cc b/webrtc/modules/audio_processing/aec3/echo_canceller3_unittest.cc
index 78a10c0..376cf1e 100644
--- a/webrtc/modules/audio_processing/aec3/echo_canceller3_unittest.cc
+++ b/webrtc/modules/audio_processing/aec3/echo_canceller3_unittest.cc
@@ -495,7 +495,8 @@
   // This test verifies that a buffer overrun in the render swapqueue is
   // properly reported.
   void RunRenderPipelineSwapQueueOverrunReturnValueTest() {
-    EchoCanceller3 aec3(sample_rate_hz_, false);
+    EchoCanceller3 aec3(AudioProcessing::Config::EchoCanceller3(),
+                        sample_rate_hz_, false);
 
     constexpr size_t kRenderTransferQueueSize = 30;
     for (size_t k = 0; k < 2; ++k) {
@@ -524,7 +525,8 @@
     // Set aec3_sample_rate_hz to be different from sample_rate_hz_ in such a
     // way that the number of bands for the rates are different.
     const int aec3_sample_rate_hz = sample_rate_hz_ == 48000 ? 32000 : 48000;
-    EchoCanceller3 aec3(aec3_sample_rate_hz, false);
+    EchoCanceller3 aec3(AudioProcessing::Config::EchoCanceller3(),
+                        aec3_sample_rate_hz, false);
     PopulateInputFrame(frame_length_, 0, &render_buffer_.channels_f()[0][0], 0);
 
     EXPECT_DEATH(aec3.AnalyzeRender(&render_buffer_), "");
@@ -537,7 +539,8 @@
     // Set aec3_sample_rate_hz to be different from sample_rate_hz_ in such a
     // way that the number of bands for the rates are different.
     const int aec3_sample_rate_hz = sample_rate_hz_ == 48000 ? 32000 : 48000;
-    EchoCanceller3 aec3(aec3_sample_rate_hz, false);
+    EchoCanceller3 aec3(AudioProcessing::Config::EchoCanceller3(),
+                        aec3_sample_rate_hz, false);
     PopulateInputFrame(frame_length_, num_bands_, 0,
                        &capture_buffer_.split_bands_f(0)[0], 100);
     EXPECT_DEATH(aec3.ProcessCapture(&capture_buffer_, false), "");
@@ -550,7 +553,8 @@
     // Set aec3_sample_rate_hz to be different from sample_rate_hz_ in such a
     // way that the band frame lengths are different.
     const int aec3_sample_rate_hz = sample_rate_hz_ == 8000 ? 16000 : 8000;
-    EchoCanceller3 aec3(aec3_sample_rate_hz, false);
+    EchoCanceller3 aec3(AudioProcessing::Config::EchoCanceller3(),
+                        aec3_sample_rate_hz, false);
 
     OptionalBandSplit();
     PopulateInputFrame(frame_length_, 0, &render_buffer_.channels_f()[0][0], 0);
@@ -565,7 +569,8 @@
     // Set aec3_sample_rate_hz to be different from sample_rate_hz_ in such a
     // way that the band frame lengths are different.
     const int aec3_sample_rate_hz = sample_rate_hz_ == 8000 ? 16000 : 8000;
-    EchoCanceller3 aec3(aec3_sample_rate_hz, false);
+    EchoCanceller3 aec3(AudioProcessing::Config::EchoCanceller3(),
+                        aec3_sample_rate_hz, false);
 
     OptionalBandSplit();
     PopulateInputFrame(frame_length_, num_bands_, 0,
@@ -677,6 +682,21 @@
   }
 }
 
+TEST(EchoCanceller3, ConfigValidation) {
+  AudioProcessing::Config::EchoCanceller3 config;
+
+  config.echo_decay = 0.f;
+  EXPECT_TRUE(EchoCanceller3::Validate(config));
+  config.echo_decay = 0.9f;
+  EXPECT_TRUE(EchoCanceller3::Validate(config));
+  config.echo_decay = -0.1f;
+  EXPECT_FALSE(EchoCanceller3::Validate(config));
+  config.echo_decay = 1.0f;
+  EXPECT_FALSE(EchoCanceller3::Validate(config));
+  config.echo_decay = 1.1f;
+  EXPECT_FALSE(EchoCanceller3::Validate(config));
+}
+
 #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
 
 TEST(EchoCanceller3InputCheck, WrongCaptureNumBandsCheckVerification) {
@@ -706,19 +726,28 @@
 // Verifiers that the verification for null input to the render analysis api
 // call works.
 TEST(EchoCanceller3InputCheck, NullRenderAnalysisParameter) {
-  EXPECT_DEATH(EchoCanceller3(8000, false).AnalyzeRender(nullptr), "");
+  EXPECT_DEATH(
+      EchoCanceller3(AudioProcessing::Config::EchoCanceller3(), 8000, false)
+          .AnalyzeRender(nullptr),
+      "");
 }
 
 // Verifiers that the verification for null input to the capture analysis api
 // call works.
 TEST(EchoCanceller3InputCheck, NullCaptureAnalysisParameter) {
-  EXPECT_DEATH(EchoCanceller3(8000, false).AnalyzeCapture(nullptr), "");
+  EXPECT_DEATH(
+      EchoCanceller3(AudioProcessing::Config::EchoCanceller3(), 8000, false)
+          .AnalyzeCapture(nullptr),
+      "");
 }
 
 // Verifiers that the verification for null input to the capture processing api
 // call works.
 TEST(EchoCanceller3InputCheck, NullCaptureProcessingParameter) {
-  EXPECT_DEATH(EchoCanceller3(8000, false).ProcessCapture(nullptr, false), "");
+  EXPECT_DEATH(
+      EchoCanceller3(AudioProcessing::Config::EchoCanceller3(), 8000, false)
+          .ProcessCapture(nullptr, false),
+      "");
 }
 
 // Verifies the check for correct sample rate.
@@ -726,7 +755,9 @@
 // tests on test bots has been fixed.
 TEST(EchoCanceller3InputCheck, DISABLED_WrongSampleRate) {
   ApmDataDumper data_dumper(0);
-  EXPECT_DEATH(EchoCanceller3(8001, false), "");
+  EXPECT_DEATH(
+      EchoCanceller3(AudioProcessing::Config::EchoCanceller3(), 8001, false),
+      "");
 }
 
 #endif
diff --git a/webrtc/modules/audio_processing/aec3/echo_remover.cc b/webrtc/modules/audio_processing/aec3/echo_remover.cc
index 9737251..0c6184e 100644
--- a/webrtc/modules/audio_processing/aec3/echo_remover.cc
+++ b/webrtc/modules/audio_processing/aec3/echo_remover.cc
@@ -49,7 +49,9 @@
 // Class for removing the echo from the capture signal.
 class EchoRemoverImpl final : public EchoRemover {
  public:
-  explicit EchoRemoverImpl(int sample_rate_hz);
+  explicit EchoRemoverImpl(
+      const AudioProcessing::Config::EchoCanceller3& config,
+      int sample_rate_hz);
   ~EchoRemoverImpl() override;
 
   // Removes the echo from a block of samples from the capture signal. The
@@ -90,7 +92,9 @@
 
 int EchoRemoverImpl::instance_count_ = 0;
 
-EchoRemoverImpl::EchoRemoverImpl(int sample_rate_hz)
+EchoRemoverImpl::EchoRemoverImpl(
+    const AudioProcessing::Config::EchoCanceller3& config,
+    int sample_rate_hz)
     : fft_(),
       data_dumper_(
           new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))),
@@ -99,7 +103,8 @@
       subtractor_(data_dumper_.get(), optimization_),
       suppression_gain_(optimization_),
       cng_(optimization_),
-      suppression_filter_(sample_rate_hz_) {
+      suppression_filter_(sample_rate_hz_),
+      aec_state_(config.echo_decay) {
   RTC_DCHECK(ValidFullBandRate(sample_rate_hz));
 }
 
@@ -221,8 +226,10 @@
 
 }  // namespace
 
-EchoRemover* EchoRemover::Create(int sample_rate_hz) {
-  return new EchoRemoverImpl(sample_rate_hz);
+EchoRemover* EchoRemover::Create(
+    const AudioProcessing::Config::EchoCanceller3& config,
+    int sample_rate_hz) {
+  return new EchoRemoverImpl(config, sample_rate_hz);
 }
 
 }  // namespace webrtc
diff --git a/webrtc/modules/audio_processing/aec3/echo_remover.h b/webrtc/modules/audio_processing/aec3/echo_remover.h
index 4e25b25..4704f31 100644
--- a/webrtc/modules/audio_processing/aec3/echo_remover.h
+++ b/webrtc/modules/audio_processing/aec3/echo_remover.h
@@ -16,13 +16,16 @@
 #include "webrtc/base/optional.h"
 #include "webrtc/modules/audio_processing/aec3/echo_path_variability.h"
 #include "webrtc/modules/audio_processing/aec3/render_buffer.h"
+#include "webrtc/modules/audio_processing/include/audio_processing.h"
 
 namespace webrtc {
 
 // Class for removing the echo from the capture signal.
 class EchoRemover {
  public:
-  static EchoRemover* Create(int sample_rate_hz);
+  static EchoRemover* Create(
+      const AudioProcessing::Config::EchoCanceller3& config,
+      int sample_rate_hz);
   virtual ~EchoRemover() = default;
 
   // Removes the echo from a block of samples from the capture signal. The
diff --git a/webrtc/modules/audio_processing/aec3/echo_remover_metrics_unittest.cc b/webrtc/modules/audio_processing/aec3/echo_remover_metrics_unittest.cc
index 8030f81..21a5af2 100644
--- a/webrtc/modules/audio_processing/aec3/echo_remover_metrics_unittest.cc
+++ b/webrtc/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;
+  AecState aec_state(0.f);
   std::array<float, kFftLengthBy2Plus1> comfort_noise_spectrum;
   std::array<float, kFftLengthBy2Plus1> suppressor_gain;
   comfort_noise_spectrum.fill(10.f);
diff --git a/webrtc/modules/audio_processing/aec3/echo_remover_unittest.cc b/webrtc/modules/audio_processing/aec3/echo_remover_unittest.cc
index dd43b37..d5ffb66 100644
--- a/webrtc/modules/audio_processing/aec3/echo_remover_unittest.cc
+++ b/webrtc/modules/audio_processing/aec3/echo_remover_unittest.cc
@@ -45,7 +45,8 @@
 TEST(EchoRemover, BasicApiCalls) {
   for (auto rate : {8000, 16000, 32000, 48000}) {
     SCOPED_TRACE(ProduceDebugText(rate));
-    std::unique_ptr<EchoRemover> remover(EchoRemover::Create(rate));
+    std::unique_ptr<EchoRemover> remover(
+        EchoRemover::Create(AudioProcessing::Config::EchoCanceller3(), rate));
     std::unique_ptr<RenderDelayBuffer> render_buffer(
         RenderDelayBuffer::Create(NumBandsForRate(rate)));
 
@@ -74,14 +75,17 @@
 // TODO(peah): Re-enable the test once the issue with memory leaks during DEATH
 // tests on test bots has been fixed.
 TEST(EchoRemover, DISABLED_WrongSampleRate) {
-  EXPECT_DEATH(std::unique_ptr<EchoRemover>(EchoRemover::Create(8001)), "");
+  EXPECT_DEATH(std::unique_ptr<EchoRemover>(EchoRemover::Create(
+                   AudioProcessing::Config::EchoCanceller3(), 8001)),
+               "");
 }
 
 // Verifies the check for the capture block size.
 TEST(EchoRemover, WrongCaptureBlockSize) {
   for (auto rate : {8000, 16000, 32000, 48000}) {
     SCOPED_TRACE(ProduceDebugText(rate));
-    std::unique_ptr<EchoRemover> remover(EchoRemover::Create(rate));
+    std::unique_ptr<EchoRemover> remover(
+        EchoRemover::Create(AudioProcessing::Config::EchoCanceller3(), rate));
     std::unique_ptr<RenderDelayBuffer> render_buffer(
         RenderDelayBuffer::Create(NumBandsForRate(rate)));
     std::vector<std::vector<float>> capture(
@@ -101,7 +105,8 @@
 TEST(EchoRemover, DISABLED_WrongCaptureNumBands) {
   for (auto rate : {16000, 32000, 48000}) {
     SCOPED_TRACE(ProduceDebugText(rate));
-    std::unique_ptr<EchoRemover> remover(EchoRemover::Create(rate));
+    std::unique_ptr<EchoRemover> remover(
+        EchoRemover::Create(AudioProcessing::Config::EchoCanceller3(), rate));
     std::unique_ptr<RenderDelayBuffer> render_buffer(
         RenderDelayBuffer::Create(NumBandsForRate(rate)));
     std::vector<std::vector<float>> capture(
@@ -118,7 +123,8 @@
 
 // Verifies the check for non-null capture block.
 TEST(EchoRemover, NullCapture) {
-  std::unique_ptr<EchoRemover> remover(EchoRemover::Create(8000));
+  std::unique_ptr<EchoRemover> remover(
+      EchoRemover::Create(AudioProcessing::Config::EchoCanceller3(), 8000));
   std::unique_ptr<RenderDelayBuffer> render_buffer(
       RenderDelayBuffer::Create(3));
   EchoPathVariability echo_path_variability(false, false);
@@ -144,7 +150,8 @@
     EchoPathVariability echo_path_variability(false, false);
     for (size_t delay_samples : {0, 64, 150, 200, 301}) {
       SCOPED_TRACE(ProduceDebugText(rate, delay_samples));
-      std::unique_ptr<EchoRemover> remover(EchoRemover::Create(rate));
+      std::unique_ptr<EchoRemover> remover(
+          EchoRemover::Create(AudioProcessing::Config::EchoCanceller3(), rate));
       std::unique_ptr<RenderDelayBuffer> render_buffer(
           RenderDelayBuffer::Create(NumBandsForRate(rate)));
       std::vector<std::unique_ptr<DelayBuffer<float>>> delay_buffers(x.size());
diff --git a/webrtc/modules/audio_processing/aec3/main_filter_update_gain_unittest.cc b/webrtc/modules/audio_processing/aec3/main_filter_update_gain_unittest.cc
index 581856b..8b958a5 100644
--- a/webrtc/modules/audio_processing/aec3/main_filter_update_gain_unittest.cc
+++ b/webrtc/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;
+  AecState aec_state(0.f);
   RenderSignalAnalyzer render_signal_analyzer;
   std::array<float, kFftLength> s;
   FftData S;
diff --git a/webrtc/modules/audio_processing/aec3/residual_echo_estimator_unittest.cc b/webrtc/modules/audio_processing/aec3/residual_echo_estimator_unittest.cc
index 824467d..6d34128 100644
--- a/webrtc/modules/audio_processing/aec3/residual_echo_estimator_unittest.cc
+++ b/webrtc/modules/audio_processing/aec3/residual_echo_estimator_unittest.cc
@@ -22,7 +22,7 @@
 
 // Verifies that the check for non-null output residual echo power works.
 TEST(ResidualEchoEstimator, NullResidualEchoPowerOutput) {
-  AecState aec_state;
+  AecState aec_state(0.f);
   RenderBuffer render_buffer(Aec3Optimization::kNone, 3, 10,
                              std::vector<size_t>(1, 10));
   std::vector<std::array<float, kFftLengthBy2Plus1>> H2;
@@ -37,7 +37,7 @@
 
 TEST(ResidualEchoEstimator, BasicTest) {
   ResidualEchoEstimator estimator;
-  AecState aec_state;
+  AecState aec_state(0.f);
   RenderBuffer render_buffer(Aec3Optimization::kNone, 3, 10,
                              std::vector<size_t>(1, 10));
   std::array<float, kFftLengthBy2Plus1> E2_main;
diff --git a/webrtc/modules/audio_processing/aec3/shadow_filter_update_gain_unittest.cc b/webrtc/modules/audio_processing/aec3/shadow_filter_update_gain_unittest.cc
index 40bee42..4783855 100644
--- a/webrtc/modules/audio_processing/aec3/shadow_filter_update_gain_unittest.cc
+++ b/webrtc/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;
+  AecState aec_state(0.f);
   RenderSignalAnalyzer render_signal_analyzer;
   std::array<float, kFftLength> s;
   FftData S;
diff --git a/webrtc/modules/audio_processing/aec3/subtractor_unittest.cc b/webrtc/modules/audio_processing/aec3/subtractor_unittest.cc
index 48c9c57..0c43923 100644
--- a/webrtc/modules/audio_processing/aec3/subtractor_unittest.cc
+++ b/webrtc/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;
+  AecState aec_state(0.f);
   x_old.fill(0.f);
   Y2.fill(0.f);
   E2_main.fill(0.f);
@@ -109,7 +109,7 @@
   std::vector<float> y(kBlockSize, 0.f);
 
   EXPECT_DEATH(subtractor.Process(render_buffer, y, render_signal_analyzer,
-                                  AecState(), nullptr),
+                                  AecState(0.f), nullptr),
                "");
 }
 
@@ -124,7 +124,7 @@
   SubtractorOutput output;
 
   EXPECT_DEATH(subtractor.Process(render_buffer, y, render_signal_analyzer,
-                                  AecState(), &output),
+                                  AecState(0.f), &output),
                "");
 }
 
diff --git a/webrtc/modules/audio_processing/audio_processing_impl.cc b/webrtc/modules/audio_processing/audio_processing_impl.cc
index 39fb723..292611e 100644
--- a/webrtc/modules/audio_processing/audio_processing_impl.cc
+++ b/webrtc/modules/audio_processing/audio_processing_impl.cc
@@ -1881,8 +1881,8 @@
 
 void AudioProcessingImpl::InitializeEchoCanceller3() {
   if (capture_nonlocked_.echo_canceller3_enabled) {
-    private_submodules_->echo_canceller3.reset(
-        new EchoCanceller3(proc_sample_rate_hz(), true));
+    private_submodules_->echo_canceller3.reset(new EchoCanceller3(
+        config_.echo_canceller3, proc_sample_rate_hz(), true));
   } else {
     private_submodules_->echo_canceller3.reset();
   }
diff --git a/webrtc/modules/audio_processing/include/audio_processing.h b/webrtc/modules/audio_processing/include/audio_processing.h
index 05be5fe..6dc6e3f 100644
--- a/webrtc/modules/audio_processing/include/audio_processing.h
+++ b/webrtc/modules/audio_processing/include/audio_processing.h
@@ -268,6 +268,7 @@
     // does not yet have the desired behavior.
     struct EchoCanceller3 {
       bool enabled = false;
+      float echo_decay = 0.f;
     } echo_canceller3;
 
     // Enables the next generation AGC functionality. This feature replaces the