Separate AEC3 config from AudioProcessing::Config.

The struct containing the config for AEC3 is removed from
AudioProcessing::Config and is put in a new struct called
EchoCanceller3Config.

AEC3 should no longer be activated through
AudioProcessing::ApplyConfig. Instead an EchoCanceller3Factory
can be injected at AudioProcessing creation.

Bug: webrtc:8346
Change-Id: I27e3592e675eec3632a60c45d9e0d12514c2c567
Reviewed-on: https://webrtc-review.googlesource.com/11420
Reviewed-by: Per Ã…hgren <peah@webrtc.org>
Reviewed-by: Henrik Lundin <henrik.lundin@webrtc.org>
Commit-Queue: Gustaf Ullberg <gustaf@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#20342}
diff --git a/modules/audio_processing/aec3/adaptive_fir_filter_unittest.cc b/modules/audio_processing/aec3/adaptive_fir_filter_unittest.cc
index 40f64fd..ffac7d1 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(AudioProcessing::Config::EchoCanceller3{});
+  AecState aec_state(EchoCanceller3Config{});
   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 92ad5cf..2f91cfb 100644
--- a/modules/audio_processing/aec3/aec_state.cc
+++ b/modules/audio_processing/aec3/aec_state.cc
@@ -51,14 +51,12 @@
 
 int AecState::instance_count_ = 0;
 
-AecState::AecState(const AudioProcessing::Config::EchoCanceller3& config)
+AecState::AecState(const EchoCanceller3Config& 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),
+      erle_estimator_(config.erle.min, config.erle.max_l, config.erle.max_h),
       config_(config),
-      reverb_decay_(config_.param.ep_strength.default_len) {}
+      reverb_decay_(config_.ep_strength.default_len) {}
 
 AecState::~AecState() = default;
 
@@ -133,7 +131,7 @@
   const float max_sample = fabs(*std::max_element(
       x.begin(), x.end(), [](float a, float b) { return a * a < b * b; }));
 
-  if (config_.param.ep_strength.echo_can_saturate) {
+  if (config_.ep_strength.echo_can_saturate) {
     const bool saturated_echo =
         (previous_max_sample_ > 200.f) && SaturatedCapture();
 
@@ -158,8 +156,8 @@
   // transparent mode should be entered.
   const float x_energy = std::inner_product(x.begin(), x.end(), x.begin(), 0.f);
   const bool active_render_block =
-      x_energy > (config_.param.render_levels.active_render_limit *
-                  config_.param.render_levels.active_render_limit) *
+      x_energy > (config_.render_levels.active_render_limit *
+                  config_.render_levels.active_render_limit) *
                      kFftLengthBy2;
   if (active_render_block) {
     render_received_ = true;
@@ -238,8 +236,7 @@
 
       // Limit the estimated reverb_decay_ to the maximum one needed in practice
       // to minimize the impact of incorrect estimates.
-      reverb_decay_ =
-          std::min(config_.param.ep_strength.default_len, reverb_decay_);
+      reverb_decay_ = std::min(config_.ep_strength.default_len, reverb_decay_);
     }
     reverb_decay_to_test_ = 0.9f;
     reverb_decay_candidate_residual_ = -1.f;
@@ -247,7 +244,7 @@
 
   // For noisy impulse responses, assume a fixed tail length.
   if (tail_power > 0.0005f) {
-    reverb_decay_ = config_.param.ep_strength.default_len;
+    reverb_decay_ = config_.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 358c74d..3feddd9 100644
--- a/modules/audio_processing/aec3/aec_state.h
+++ b/modules/audio_processing/aec3/aec_state.h
@@ -32,7 +32,7 @@
 // Handles the state and the conditions for the echo removal functionality.
 class AecState {
  public:
-  explicit AecState(const AudioProcessing::Config::EchoCanceller3& config);
+  explicit AecState(const EchoCanceller3Config& config);
   ~AecState();
 
   // Returns whether the linear filter estimate is usable.
@@ -163,7 +163,7 @@
   float reverb_decay_candidate_ = 0.f;
   float reverb_decay_candidate_residual_ = -1.f;
   EchoAudibility echo_audibility_;
-  const AudioProcessing::Config::EchoCanceller3 config_;
+  const EchoCanceller3Config config_;
   float reverb_decay_;
 
   RTC_DISALLOW_COPY_AND_ASSIGN(AecState);
diff --git a/modules/audio_processing/aec3/aec_state_unittest.cc b/modules/audio_processing/aec3/aec_state_unittest.cc
index 4956456..fd6a34b 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(AudioProcessing::Config::EchoCanceller3{});
+  AecState state(EchoCanceller3Config{});
   RenderBuffer render_buffer(Aec3Optimization::kNone, 3, 30,
                              std::vector<size_t>(1, 30));
   std::array<float, kFftLengthBy2Plus1> E2_main = {};
@@ -164,7 +164,7 @@
 // Verifies the delay for a converged filter is correctly identified.
 TEST(AecState, ConvergedFilterDelay) {
   constexpr int kFilterLength = 10;
-  AecState state(AudioProcessing::Config::EchoCanceller3{});
+  AecState state(EchoCanceller3Config{});
   RenderBuffer render_buffer(Aec3Optimization::kNone, 3, 30,
                              std::vector<size_t>(1, 30));
   std::array<float, kFftLengthBy2Plus1> E2_main;
@@ -201,7 +201,7 @@
 
 // Verify that the externally reported delay is properly reported and converted.
 TEST(AecState, ExternalDelay) {
-  AecState state(AudioProcessing::Config::EchoCanceller3{});
+  AecState state(EchoCanceller3Config{});
   std::array<float, kFftLengthBy2Plus1> E2_main;
   std::array<float, kFftLengthBy2Plus1> E2_shadow;
   std::array<float, kFftLengthBy2Plus1> Y2;
diff --git a/modules/audio_processing/aec3/block_processor.cc b/modules/audio_processing/aec3/block_processor.cc
index 1bdd71f..1629785 100644
--- a/modules/audio_processing/aec3/block_processor.cc
+++ b/modules/audio_processing/aec3/block_processor.cc
@@ -181,9 +181,8 @@
 
 }  // namespace
 
-BlockProcessor* BlockProcessor::Create(
-    const AudioProcessing::Config::EchoCanceller3& config,
-    int sample_rate_hz) {
+BlockProcessor* BlockProcessor::Create(const EchoCanceller3Config& config,
+                                       int sample_rate_hz) {
   std::unique_ptr<RenderDelayBuffer> render_buffer(
       RenderDelayBuffer::Create(NumBandsForRate(sample_rate_hz)));
   std::unique_ptr<RenderDelayController> delay_controller(
@@ -195,7 +194,7 @@
 }
 
 BlockProcessor* BlockProcessor::Create(
-    const AudioProcessing::Config::EchoCanceller3& config,
+    const EchoCanceller3Config& config,
     int sample_rate_hz,
     std::unique_ptr<RenderDelayBuffer> render_buffer) {
   std::unique_ptr<RenderDelayController> delay_controller(
@@ -207,7 +206,7 @@
 }
 
 BlockProcessor* BlockProcessor::Create(
-    const AudioProcessing::Config::EchoCanceller3& config,
+    const EchoCanceller3Config& config,
     int sample_rate_hz,
     std::unique_ptr<RenderDelayBuffer> render_buffer,
     std::unique_ptr<RenderDelayController> delay_controller,
diff --git a/modules/audio_processing/aec3/block_processor.h b/modules/audio_processing/aec3/block_processor.h
index 5f95e00..845e081 100644
--- a/modules/audio_processing/aec3/block_processor.h
+++ b/modules/audio_processing/aec3/block_processor.h
@@ -23,16 +23,15 @@
 // Class for performing echo cancellation on 64 sample blocks of audio data.
 class BlockProcessor {
  public:
-  static BlockProcessor* Create(
-      const AudioProcessing::Config::EchoCanceller3& config,
-      int sample_rate_hz);
+  static BlockProcessor* Create(const EchoCanceller3Config& config,
+                                int sample_rate_hz);
   // Only used for testing purposes.
   static BlockProcessor* Create(
-      const AudioProcessing::Config::EchoCanceller3& config,
+      const EchoCanceller3Config& config,
       int sample_rate_hz,
       std::unique_ptr<RenderDelayBuffer> render_buffer);
   static BlockProcessor* Create(
-      const AudioProcessing::Config::EchoCanceller3& config,
+      const EchoCanceller3Config& config,
       int sample_rate_hz,
       std::unique_ptr<RenderDelayBuffer> render_buffer,
       std::unique_ptr<RenderDelayController> delay_controller,
diff --git a/modules/audio_processing/aec3/block_processor_unittest.cc b/modules/audio_processing/aec3/block_processor_unittest.cc
index 57cd430c..985873d 100644
--- a/modules/audio_processing/aec3/block_processor_unittest.cc
+++ b/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(
-      AudioProcessing::Config::EchoCanceller3(), sample_rate_hz));
+  std::unique_ptr<BlockProcessor> block_processor(
+      BlockProcessor::Create(EchoCanceller3Config(), 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(
-      AudioProcessing::Config::EchoCanceller3(), sample_rate_hz));
+  std::unique_ptr<BlockProcessor> block_processor(
+      BlockProcessor::Create(EchoCanceller3Config(), 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(
-      AudioProcessing::Config::EchoCanceller3(), sample_rate_hz));
+  std::unique_ptr<BlockProcessor> block_processor(
+      BlockProcessor::Create(EchoCanceller3Config(), 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(
-      AudioProcessing::Config::EchoCanceller3(), sample_rate_hz));
+  std::unique_ptr<BlockProcessor> block_processor(
+      BlockProcessor::Create(EchoCanceller3Config(), 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(
-      AudioProcessing::Config::EchoCanceller3(), sample_rate_hz));
+  std::unique_ptr<BlockProcessor> block_processor(
+      BlockProcessor::Create(EchoCanceller3Config(), sample_rate_hz));
   std::vector<std::vector<float>> block(wrong_num_bands,
                                         std::vector<float>(kBlockSize, 0.f));
 
@@ -125,9 +125,8 @@
     EXPECT_CALL(*render_delay_buffer_mock, Delay())
         .Times(kNumBlocks + 1)
         .WillRepeatedly(Return(0));
-    std::unique_ptr<BlockProcessor> block_processor(
-        BlockProcessor::Create(AudioProcessing::Config::EchoCanceller3(), rate,
-                               std::move(render_delay_buffer_mock)));
+    std::unique_ptr<BlockProcessor> block_processor(BlockProcessor::Create(
+        EchoCanceller3Config(), rate, std::move(render_delay_buffer_mock)));
 
     std::vector<std::vector<float>> render_block(
         NumBandsForRate(rate), std::vector<float>(kBlockSize, 0.f));
@@ -181,8 +180,7 @@
         .Times(kNumBlocks);
 
     std::unique_ptr<BlockProcessor> block_processor(BlockProcessor::Create(
-        AudioProcessing::Config::EchoCanceller3(), rate,
-        std::move(render_delay_buffer_mock),
+        EchoCanceller3Config(), 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(
@@ -241,8 +239,7 @@
 // Verifiers that the verification for null ProcessCapture input works.
 TEST(BlockProcessor, NullProcessCaptureParameter) {
   EXPECT_DEATH(std::unique_ptr<BlockProcessor>(
-                   BlockProcessor::Create(
-                       AudioProcessing::Config::EchoCanceller3(), 8000))
+                   BlockProcessor::Create(EchoCanceller3Config(), 8000))
                    ->ProcessCapture(false, false, nullptr),
                "");
 }
@@ -251,8 +248,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(
-                   AudioProcessing::Config::EchoCanceller3(), 8001)),
+  EXPECT_DEATH(std::unique_ptr<BlockProcessor>(
+                   BlockProcessor::Create(EchoCanceller3Config(), 8001)),
                "");
 }
 
diff --git a/modules/audio_processing/aec3/comfort_noise_generator_unittest.cc b/modules/audio_processing/aec3/comfort_noise_generator_unittest.cc
index 333910b..46da3ec 100644
--- a/modules/audio_processing/aec3/comfort_noise_generator_unittest.cc
+++ b/modules/audio_processing/aec3/comfort_noise_generator_unittest.cc
@@ -35,19 +35,19 @@
 TEST(ComfortNoiseGenerator, NullLowerBandNoise) {
   std::array<float, kFftLengthBy2Plus1> N2;
   FftData noise;
-  EXPECT_DEATH(ComfortNoiseGenerator(DetectOptimization())
-                   .Compute(AecState(AudioProcessing::Config::EchoCanceller3{}),
-                            N2, nullptr, &noise),
-               "");
+  EXPECT_DEATH(
+      ComfortNoiseGenerator(DetectOptimization())
+          .Compute(AecState(EchoCanceller3Config{}), N2, nullptr, &noise),
+      "");
 }
 
 TEST(ComfortNoiseGenerator, NullUpperBandNoise) {
   std::array<float, kFftLengthBy2Plus1> N2;
   FftData noise;
-  EXPECT_DEATH(ComfortNoiseGenerator(DetectOptimization())
-                   .Compute(AecState(AudioProcessing::Config::EchoCanceller3{}),
-                            N2, &noise, nullptr),
-               "");
+  EXPECT_DEATH(
+      ComfortNoiseGenerator(DetectOptimization())
+          .Compute(AecState(EchoCanceller3Config{}), N2, &noise, nullptr),
+      "");
 }
 
 #endif
@@ -93,7 +93,7 @@
 
 TEST(ComfortNoiseGenerator, CorrectLevel) {
   ComfortNoiseGenerator cng(DetectOptimization());
-  AecState aec_state(AudioProcessing::Config::EchoCanceller3{});
+  AecState aec_state(EchoCanceller3Config{});
 
   std::array<float, kFftLengthBy2Plus1> N2;
   N2.fill(1000.f * 1000.f);
diff --git a/modules/audio_processing/aec3/echo_canceller3.cc b/modules/audio_processing/aec3/echo_canceller3.cc
index d34a98b..93c98e4 100644
--- a/modules/audio_processing/aec3/echo_canceller3.cc
+++ b/modules/audio_processing/aec3/echo_canceller3.cc
@@ -200,10 +200,9 @@
 
 int EchoCanceller3::instance_count_ = 0;
 
-EchoCanceller3::EchoCanceller3(
-    const AudioProcessing::Config::EchoCanceller3& config,
-    int sample_rate_hz,
-    bool use_highpass_filter)
+EchoCanceller3::EchoCanceller3(const EchoCanceller3Config& config,
+                               int sample_rate_hz,
+                               bool use_highpass_filter)
     : EchoCanceller3(sample_rate_hz,
                      use_highpass_filter,
                      std::unique_ptr<BlockProcessor>(
@@ -324,16 +323,7 @@
                         LowestBandRate(sample_rate_hz_), 1);
 }
 
-std::string EchoCanceller3::ToString(
-    const AudioProcessing::Config::EchoCanceller3& config) {
-  std::stringstream ss;
-  ss << "{"
-     << "enabled: " << (config.enabled ? "true" : "false") << "}";
-  return ss.str();
-}
-
-bool EchoCanceller3::Validate(
-    const AudioProcessing::Config::EchoCanceller3& config) {
+bool EchoCanceller3::Validate(const EchoCanceller3Config& config) {
   return true;
 }
 
@@ -359,12 +349,13 @@
   }
 }
 
-EchoCanceller3Factory::EchoCanceller3Factory(
-    const AudioProcessing::Config::EchoCanceller3& config)
+EchoCanceller3Factory::EchoCanceller3Factory() {}
+
+EchoCanceller3Factory::EchoCanceller3Factory(const EchoCanceller3Config& config)
     : config_(config) {
   // Revert to default configuration if needed.
   if (!EchoCanceller3::Validate(config_)) {
-    config_ = AudioProcessing::Config::EchoCanceller3();
+    config_ = EchoCanceller3Config();
   }
 }
 
diff --git a/modules/audio_processing/aec3/echo_canceller3.h b/modules/audio_processing/aec3/echo_canceller3.h
index 07b0f70..f62016f 100644
--- a/modules/audio_processing/aec3/echo_canceller3.h
+++ b/modules/audio_processing/aec3/echo_canceller3.h
@@ -63,7 +63,7 @@
 class EchoCanceller3 : public EchoControl {
  public:
   // Normal c-tor to use.
-  EchoCanceller3(const AudioProcessing::Config::EchoCanceller3& config,
+  EchoCanceller3(const EchoCanceller3Config& config,
                  int sample_rate_hz,
                  bool use_highpass_filter);
   // Testing c-tor that is used only for testing purposes.
@@ -90,10 +90,7 @@
   }
 
   // Validates a config.
-  static bool Validate(const AudioProcessing::Config::EchoCanceller3& config);
-  // Dumps a config to a string.
-  static std::string ToString(
-      const AudioProcessing::Config::EchoCanceller3& config);
+  static bool Validate(const EchoCanceller3Config& config);
 
  private:
   class RenderWriter;
@@ -133,16 +130,6 @@
 
   RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(EchoCanceller3);
 };
-
-class EchoCanceller3Factory : public EchoControlFactory {
- public:
-  EchoCanceller3Factory();
-  EchoCanceller3Factory(const AudioProcessing::Config::EchoCanceller3& config);
-  std::unique_ptr<EchoControl> Create(int sample_rate_hz) override;
-
- private:
-  AudioProcessing::Config::EchoCanceller3 config_;
-};
 }  // namespace webrtc
 
 #endif  // MODULES_AUDIO_PROCESSING_AEC3_ECHO_CANCELLER3_H_
diff --git a/modules/audio_processing/aec3/echo_canceller3_unittest.cc b/modules/audio_processing/aec3/echo_canceller3_unittest.cc
index fbe6559..66f5304 100644
--- a/modules/audio_processing/aec3/echo_canceller3_unittest.cc
+++ b/modules/audio_processing/aec3/echo_canceller3_unittest.cc
@@ -494,8 +494,7 @@
   // This test verifies that a buffer overrun in the render swapqueue is
   // properly reported.
   void RunRenderPipelineSwapQueueOverrunReturnValueTest() {
-    EchoCanceller3 aec3(AudioProcessing::Config::EchoCanceller3(),
-                        sample_rate_hz_, false);
+    EchoCanceller3 aec3(EchoCanceller3Config(), sample_rate_hz_, false);
 
     constexpr size_t kRenderTransferQueueSize = 30;
     for (size_t k = 0; k < 2; ++k) {
@@ -524,8 +523,7 @@
     // 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(AudioProcessing::Config::EchoCanceller3(),
-                        aec3_sample_rate_hz, false);
+    EchoCanceller3 aec3(EchoCanceller3Config(), aec3_sample_rate_hz, false);
     PopulateInputFrame(frame_length_, 0, &render_buffer_.channels_f()[0][0], 0);
 
     EXPECT_DEATH(aec3.AnalyzeRender(&render_buffer_), "");
@@ -538,8 +536,7 @@
     // 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(AudioProcessing::Config::EchoCanceller3(),
-                        aec3_sample_rate_hz, false);
+    EchoCanceller3 aec3(EchoCanceller3Config(), 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), "");
@@ -552,8 +549,7 @@
     // 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(AudioProcessing::Config::EchoCanceller3(),
-                        aec3_sample_rate_hz, false);
+    EchoCanceller3 aec3(EchoCanceller3Config(), aec3_sample_rate_hz, false);
 
     OptionalBandSplit();
     PopulateInputFrame(frame_length_, 0, &render_buffer_.channels_f()[0][0], 0);
@@ -568,8 +564,7 @@
     // 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(AudioProcessing::Config::EchoCanceller3(),
-                        aec3_sample_rate_hz, false);
+    EchoCanceller3 aec3(EchoCanceller3Config(), aec3_sample_rate_hz, false);
 
     OptionalBandSplit();
     PopulateInputFrame(frame_length_, num_bands_, 0,
@@ -682,7 +677,7 @@
 }
 
 TEST(EchoCanceller3, ConfigValidation) {
-  AudioProcessing::Config::EchoCanceller3 config;
+  EchoCanceller3Config config;
   EXPECT_TRUE(EchoCanceller3::Validate(config));
 }
 
@@ -715,28 +710,25 @@
 // Verifiers that the verification for null input to the render analysis api
 // call works.
 TEST(EchoCanceller3InputCheck, NullRenderAnalysisParameter) {
-  EXPECT_DEATH(
-      EchoCanceller3(AudioProcessing::Config::EchoCanceller3(), 8000, false)
-          .AnalyzeRender(nullptr),
-      "");
+  EXPECT_DEATH(EchoCanceller3(EchoCanceller3Config(), 8000, false)
+                   .AnalyzeRender(nullptr),
+               "");
 }
 
 // Verifiers that the verification for null input to the capture analysis api
 // call works.
 TEST(EchoCanceller3InputCheck, NullCaptureAnalysisParameter) {
-  EXPECT_DEATH(
-      EchoCanceller3(AudioProcessing::Config::EchoCanceller3(), 8000, false)
-          .AnalyzeCapture(nullptr),
-      "");
+  EXPECT_DEATH(EchoCanceller3(EchoCanceller3Config(), 8000, false)
+                   .AnalyzeCapture(nullptr),
+               "");
 }
 
 // Verifiers that the verification for null input to the capture processing api
 // call works.
 TEST(EchoCanceller3InputCheck, NullCaptureProcessingParameter) {
-  EXPECT_DEATH(
-      EchoCanceller3(AudioProcessing::Config::EchoCanceller3(), 8000, false)
-          .ProcessCapture(nullptr, false),
-      "");
+  EXPECT_DEATH(EchoCanceller3(EchoCanceller3Config(), 8000, false)
+                   .ProcessCapture(nullptr, false),
+               "");
 }
 
 // Verifies the check for correct sample rate.
@@ -744,9 +736,7 @@
 // tests on test bots has been fixed.
 TEST(EchoCanceller3InputCheck, DISABLED_WrongSampleRate) {
   ApmDataDumper data_dumper(0);
-  EXPECT_DEATH(
-      EchoCanceller3(AudioProcessing::Config::EchoCanceller3(), 8001, false),
-      "");
+  EXPECT_DEATH(EchoCanceller3(EchoCanceller3Config(), 8001, false), "");
 }
 
 #endif
diff --git a/modules/audio_processing/aec3/echo_path_delay_estimator.cc b/modules/audio_processing/aec3/echo_path_delay_estimator.cc
index b95ef12..d1bb7ee 100644
--- a/modules/audio_processing/aec3/echo_path_delay_estimator.cc
+++ b/modules/audio_processing/aec3/echo_path_delay_estimator.cc
@@ -26,14 +26,14 @@
 
 EchoPathDelayEstimator::EchoPathDelayEstimator(
     ApmDataDumper* data_dumper,
-    const AudioProcessing::Config::EchoCanceller3& config)
+    const EchoCanceller3Config& config)
     : data_dumper_(data_dumper),
       matched_filter_(data_dumper_,
                       DetectOptimization(),
                       kMatchedFilterWindowSizeSubBlocks,
                       kNumMatchedFilters,
                       kMatchedFilterAlignmentShiftSizeSubBlocks,
-                      config.param.render_levels.poor_excitation_render_limit),
+                      config.render_levels.poor_excitation_render_limit),
       matched_filter_lag_aggregator_(data_dumper_) {
   RTC_DCHECK(data_dumper);
 }
diff --git a/modules/audio_processing/aec3/echo_path_delay_estimator.h b/modules/audio_processing/aec3/echo_path_delay_estimator.h
index 34c7ad4..9819007 100644
--- a/modules/audio_processing/aec3/echo_path_delay_estimator.h
+++ b/modules/audio_processing/aec3/echo_path_delay_estimator.h
@@ -29,7 +29,7 @@
 class EchoPathDelayEstimator {
  public:
   EchoPathDelayEstimator(ApmDataDumper* data_dumper,
-                         const AudioProcessing::Config::EchoCanceller3& config);
+                         const EchoCanceller3Config& config);
   ~EchoPathDelayEstimator();
 
   // Resets the estimation.
diff --git a/modules/audio_processing/aec3/echo_path_delay_estimator_unittest.cc b/modules/audio_processing/aec3/echo_path_delay_estimator_unittest.cc
index 97abdc0..2c7b9a5 100644
--- a/modules/audio_processing/aec3/echo_path_delay_estimator_unittest.cc
+++ b/modules/audio_processing/aec3/echo_path_delay_estimator_unittest.cc
@@ -37,8 +37,7 @@
   ApmDataDumper data_dumper(0);
   std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
       RenderDelayBuffer::Create(3));
-  EchoPathDelayEstimator estimator(&data_dumper,
-                                   AudioProcessing::Config::EchoCanceller3());
+  EchoPathDelayEstimator estimator(&data_dumper, EchoCanceller3Config());
   std::vector<std::vector<float>> render(3, std::vector<float>(kBlockSize));
   std::vector<float> capture(kBlockSize);
   for (size_t k = 0; k < 100; ++k) {
@@ -60,8 +59,7 @@
     std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
         RenderDelayBuffer::Create(3));
     DelayBuffer<float> signal_delay_buffer(delay_samples);
-    EchoPathDelayEstimator estimator(&data_dumper,
-                                     AudioProcessing::Config::EchoCanceller3());
+    EchoPathDelayEstimator estimator(&data_dumper, EchoCanceller3Config());
 
     rtc::Optional<size_t> estimated_delay_samples;
     for (size_t k = 0; k < (100 + delay_samples / kBlockSize); ++k) {
@@ -93,8 +91,7 @@
   std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
       RenderDelayBuffer::Create(3));
 
-  EchoPathDelayEstimator estimator(&data_dumper,
-                                   AudioProcessing::Config::EchoCanceller3());
+  EchoPathDelayEstimator estimator(&data_dumper, EchoCanceller3Config());
   for (size_t k = 0; k < 19; ++k) {
     RandomizeSampleVector(&random_generator, render[0]);
     std::copy(render[0].begin(), render[0].end(), capture.begin());
@@ -112,8 +109,7 @@
   std::vector<std::vector<float>> render(3, std::vector<float>(kBlockSize));
   std::vector<float> capture(kBlockSize);
   ApmDataDumper data_dumper(0);
-  EchoPathDelayEstimator estimator(&data_dumper,
-                                   AudioProcessing::Config::EchoCanceller3());
+  EchoPathDelayEstimator estimator(&data_dumper, EchoCanceller3Config());
   std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
       RenderDelayBuffer::Create(3));
   for (size_t k = 0; k < 100; ++k) {
@@ -136,8 +132,7 @@
   std::vector<std::vector<float>> render(3, std::vector<float>(kBlockSize));
   std::vector<float> capture(kBlockSize);
   ApmDataDumper data_dumper(0);
-  EchoPathDelayEstimator estimator(&data_dumper,
-                                   AudioProcessing::Config::EchoCanceller3());
+  EchoPathDelayEstimator estimator(&data_dumper, EchoCanceller3Config());
   std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
       RenderDelayBuffer::Create(3));
   for (size_t k = 0; k < 100; ++k) {
@@ -157,8 +152,7 @@
 // tests on test bots has been fixed.
 TEST(EchoPathDelayEstimator, DISABLED_WrongRenderBlockSize) {
   ApmDataDumper data_dumper(0);
-  EchoPathDelayEstimator estimator(&data_dumper,
-                                   AudioProcessing::Config::EchoCanceller3());
+  EchoPathDelayEstimator estimator(&data_dumper, EchoCanceller3Config());
   std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
       RenderDelayBuffer::Create(3));
   std::vector<float> capture(kBlockSize);
@@ -172,8 +166,7 @@
 // tests on test bots has been fixed.
 TEST(EchoPathDelayEstimator, WrongCaptureBlockSize) {
   ApmDataDumper data_dumper(0);
-  EchoPathDelayEstimator estimator(&data_dumper,
-                                   AudioProcessing::Config::EchoCanceller3());
+  EchoPathDelayEstimator estimator(&data_dumper, EchoCanceller3Config());
   std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
       RenderDelayBuffer::Create(3));
   std::vector<float> capture(std::vector<float>(kBlockSize - 1));
@@ -184,9 +177,7 @@
 
 // Verifies the check for non-null data dumper.
 TEST(EchoPathDelayEstimator, NullDataDumper) {
-  EXPECT_DEATH(EchoPathDelayEstimator(
-                   nullptr, AudioProcessing::Config::EchoCanceller3()),
-               "");
+  EXPECT_DEATH(EchoPathDelayEstimator(nullptr, EchoCanceller3Config()), "");
 }
 
 #endif
diff --git a/modules/audio_processing/aec3/echo_remover.cc b/modules/audio_processing/aec3/echo_remover.cc
index 341c89a..9914bc8 100644
--- a/modules/audio_processing/aec3/echo_remover.cc
+++ b/modules/audio_processing/aec3/echo_remover.cc
@@ -49,9 +49,8 @@
 // Class for removing the echo from the capture signal.
 class EchoRemoverImpl final : public EchoRemover {
  public:
-  explicit EchoRemoverImpl(
-      const AudioProcessing::Config::EchoCanceller3& config,
-      int sample_rate_hz);
+  explicit EchoRemoverImpl(const EchoCanceller3Config& config,
+                           int sample_rate_hz);
   ~EchoRemoverImpl() override;
 
   // Removes the echo from a block of samples from the capture signal. The
@@ -71,7 +70,7 @@
 
  private:
   static int instance_count_;
-  const AudioProcessing::Config::EchoCanceller3 config_;
+  const EchoCanceller3Config config_;
   const Aec3Fft fft_;
   std::unique_ptr<ApmDataDumper> data_dumper_;
   const Aec3Optimization optimization_;
@@ -92,9 +91,8 @@
 
 int EchoRemoverImpl::instance_count_ = 0;
 
-EchoRemoverImpl::EchoRemoverImpl(
-    const AudioProcessing::Config::EchoCanceller3& config,
-    int sample_rate_hz)
+EchoRemoverImpl::EchoRemoverImpl(const EchoCanceller3Config& config,
+                                 int sample_rate_hz)
     : config_(config),
       fft_(),
       data_dumper_(
@@ -242,9 +240,8 @@
 
 }  // namespace
 
-EchoRemover* EchoRemover::Create(
-    const AudioProcessing::Config::EchoCanceller3& config,
-    int sample_rate_hz) {
+EchoRemover* EchoRemover::Create(const EchoCanceller3Config& config,
+                                 int sample_rate_hz) {
   return new EchoRemoverImpl(config, sample_rate_hz);
 }
 
diff --git a/modules/audio_processing/aec3/echo_remover.h b/modules/audio_processing/aec3/echo_remover.h
index 83e869e..ab56e38 100644
--- a/modules/audio_processing/aec3/echo_remover.h
+++ b/modules/audio_processing/aec3/echo_remover.h
@@ -23,9 +23,8 @@
 // Class for removing the echo from the capture signal.
 class EchoRemover {
  public:
-  static EchoRemover* Create(
-      const AudioProcessing::Config::EchoCanceller3& config,
-      int sample_rate_hz);
+  static EchoRemover* Create(const EchoCanceller3Config& config,
+                             int sample_rate_hz);
   virtual ~EchoRemover() = default;
 
   // Removes the echo from a block of samples from the capture signal. The
diff --git a/modules/audio_processing/aec3/echo_remover_metrics_unittest.cc b/modules/audio_processing/aec3/echo_remover_metrics_unittest.cc
index baab10f..b8b20d7 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(AudioProcessing::Config::EchoCanceller3{});
+  AecState aec_state(EchoCanceller3Config{});
   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/echo_remover_unittest.cc b/modules/audio_processing/aec3/echo_remover_unittest.cc
index 4638f90..b253efc 100644
--- a/modules/audio_processing/aec3/echo_remover_unittest.cc
+++ b/modules/audio_processing/aec3/echo_remover_unittest.cc
@@ -46,7 +46,7 @@
   for (auto rate : {8000, 16000, 32000, 48000}) {
     SCOPED_TRACE(ProduceDebugText(rate));
     std::unique_ptr<EchoRemover> remover(
-        EchoRemover::Create(AudioProcessing::Config::EchoCanceller3(), rate));
+        EchoRemover::Create(EchoCanceller3Config(), rate));
     std::unique_ptr<RenderDelayBuffer> render_buffer(
         RenderDelayBuffer::Create(NumBandsForRate(rate)));
 
@@ -75,8 +75,8 @@
 // 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(
-                   AudioProcessing::Config::EchoCanceller3(), 8001)),
+  EXPECT_DEATH(std::unique_ptr<EchoRemover>(
+                   EchoRemover::Create(EchoCanceller3Config(), 8001)),
                "");
 }
 
@@ -85,7 +85,7 @@
   for (auto rate : {8000, 16000, 32000, 48000}) {
     SCOPED_TRACE(ProduceDebugText(rate));
     std::unique_ptr<EchoRemover> remover(
-        EchoRemover::Create(AudioProcessing::Config::EchoCanceller3(), rate));
+        EchoRemover::Create(EchoCanceller3Config(), rate));
     std::unique_ptr<RenderDelayBuffer> render_buffer(
         RenderDelayBuffer::Create(NumBandsForRate(rate)));
     std::vector<std::vector<float>> capture(
@@ -106,7 +106,7 @@
   for (auto rate : {16000, 32000, 48000}) {
     SCOPED_TRACE(ProduceDebugText(rate));
     std::unique_ptr<EchoRemover> remover(
-        EchoRemover::Create(AudioProcessing::Config::EchoCanceller3(), rate));
+        EchoRemover::Create(EchoCanceller3Config(), rate));
     std::unique_ptr<RenderDelayBuffer> render_buffer(
         RenderDelayBuffer::Create(NumBandsForRate(rate)));
     std::vector<std::vector<float>> capture(
@@ -124,7 +124,7 @@
 // Verifies the check for non-null capture block.
 TEST(EchoRemover, NullCapture) {
   std::unique_ptr<EchoRemover> remover(
-      EchoRemover::Create(AudioProcessing::Config::EchoCanceller3(), 8000));
+      EchoRemover::Create(EchoCanceller3Config(), 8000));
   std::unique_ptr<RenderDelayBuffer> render_buffer(
       RenderDelayBuffer::Create(3));
   EchoPathVariability echo_path_variability(false, false);
@@ -151,7 +151,7 @@
     for (size_t delay_samples : {0, 64, 150, 200, 301}) {
       SCOPED_TRACE(ProduceDebugText(rate, delay_samples));
       std::unique_ptr<EchoRemover> remover(
-          EchoRemover::Create(AudioProcessing::Config::EchoCanceller3(), rate));
+          EchoRemover::Create(EchoCanceller3Config(), 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/modules/audio_processing/aec3/main_filter_update_gain_unittest.cc b/modules/audio_processing/aec3/main_filter_update_gain_unittest.cc
index e3f968c..9e794de 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(AudioProcessing::Config::EchoCanceller3{});
+  AecState aec_state(EchoCanceller3Config{});
   RenderSignalAnalyzer render_signal_analyzer;
   std::array<float, kFftLength> s_scratch;
   std::array<float, kBlockSize> s;
diff --git a/modules/audio_processing/aec3/render_delay_controller.cc b/modules/audio_processing/aec3/render_delay_controller.cc
index 1a30cdf..c29954e 100644
--- a/modules/audio_processing/aec3/render_delay_controller.cc
+++ b/modules/audio_processing/aec3/render_delay_controller.cc
@@ -27,9 +27,8 @@
 
 class RenderDelayControllerImpl final : public RenderDelayController {
  public:
-  RenderDelayControllerImpl(
-      const AudioProcessing::Config::EchoCanceller3& config,
-      int sample_rate_hz);
+  RenderDelayControllerImpl(const EchoCanceller3Config& config,
+                            int sample_rate_hz);
   ~RenderDelayControllerImpl() override;
   void Reset() override;
   void SetDelay(size_t render_delay) override;
@@ -75,12 +74,12 @@
 int RenderDelayControllerImpl::instance_count_ = 0;
 
 RenderDelayControllerImpl::RenderDelayControllerImpl(
-    const AudioProcessing::Config::EchoCanceller3& config,
+    const EchoCanceller3Config& config,
     int sample_rate_hz)
     : data_dumper_(
           new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))),
       default_delay_(
-          std::max(config.param.delay.default_delay, kMinEchoPathDelayBlocks)),
+          std::max(config.delay.default_delay, kMinEchoPathDelayBlocks)),
       delay_(default_delay_),
       delay_estimator_(data_dumper_.get(), config),
       echo_path_delay_samples_(default_delay_ * kBlockSize),
@@ -170,7 +169,7 @@
 }  // namespace
 
 RenderDelayController* RenderDelayController::Create(
-    const AudioProcessing::Config::EchoCanceller3& config,
+    const EchoCanceller3Config& config,
     int sample_rate_hz) {
   return new RenderDelayControllerImpl(config, sample_rate_hz);
 }
diff --git a/modules/audio_processing/aec3/render_delay_controller.h b/modules/audio_processing/aec3/render_delay_controller.h
index a3d8d12..e971b56 100644
--- a/modules/audio_processing/aec3/render_delay_controller.h
+++ b/modules/audio_processing/aec3/render_delay_controller.h
@@ -23,9 +23,8 @@
 // Class for aligning the render and capture signal using a RenderDelayBuffer.
 class RenderDelayController {
  public:
-  static RenderDelayController* Create(
-      const AudioProcessing::Config::EchoCanceller3& config,
-      int sample_rate_hz);
+  static RenderDelayController* Create(const EchoCanceller3Config& config,
+                                       int sample_rate_hz);
   virtual ~RenderDelayController() = default;
 
   // Resets the delay controller.
diff --git a/modules/audio_processing/aec3/render_delay_controller_unittest.cc b/modules/audio_processing/aec3/render_delay_controller_unittest.cc
index 7776b09..7219b0b 100644
--- a/modules/audio_processing/aec3/render_delay_controller_unittest.cc
+++ b/modules/audio_processing/aec3/render_delay_controller_unittest.cc
@@ -50,8 +50,7 @@
     std::unique_ptr<RenderDelayBuffer> delay_buffer(
         RenderDelayBuffer::Create(NumBandsForRate(rate)));
     std::unique_ptr<RenderDelayController> delay_controller(
-        RenderDelayController::Create(AudioProcessing::Config::EchoCanceller3(),
-                                      rate));
+        RenderDelayController::Create(EchoCanceller3Config(), rate));
     for (size_t k = 0; k < 100; ++k) {
       EXPECT_EQ(kMinEchoPathDelayBlocks,
                 delay_controller->GetDelay(
@@ -70,8 +69,7 @@
     std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
         RenderDelayBuffer::Create(NumBandsForRate(rate)));
     std::unique_ptr<RenderDelayController> delay_controller(
-        RenderDelayController::Create(AudioProcessing::Config::EchoCanceller3(),
-                                      rate));
+        RenderDelayController::Create(EchoCanceller3Config(), rate));
     for (size_t k = 0; k < 10; ++k) {
       render_delay_buffer->Insert(render_block);
       render_delay_buffer->UpdateBuffers();
@@ -98,8 +96,7 @@
       std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
           RenderDelayBuffer::Create(NumBandsForRate(rate)));
       std::unique_ptr<RenderDelayController> delay_controller(
-          RenderDelayController::Create(
-              AudioProcessing::Config::EchoCanceller3(), rate));
+          RenderDelayController::Create(EchoCanceller3Config(), rate));
       DelayBuffer<float> signal_delay_buffer(delay_samples);
       for (size_t k = 0; k < (400 + delay_samples / kBlockSize); ++k) {
         RandomizeSampleVector(&random_generator, render_block[0]);
@@ -142,8 +139,7 @@
       std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
           RenderDelayBuffer::Create(NumBandsForRate(rate)));
       std::unique_ptr<RenderDelayController> delay_controller(
-          RenderDelayController::Create(
-              AudioProcessing::Config::EchoCanceller3(), rate));
+          RenderDelayController::Create(EchoCanceller3Config(), rate));
       DelayBuffer<float> signal_delay_buffer(-delay_samples);
       for (int k = 0; k < (400 - delay_samples / static_cast<int>(kBlockSize));
            ++k) {
@@ -179,8 +175,7 @@
       std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
           RenderDelayBuffer::Create(NumBandsForRate(rate)));
       std::unique_ptr<RenderDelayController> delay_controller(
-          RenderDelayController::Create(
-              AudioProcessing::Config::EchoCanceller3(), rate));
+          RenderDelayController::Create(EchoCanceller3Config(), rate));
       DelayBuffer<float> signal_delay_buffer(delay_samples);
       for (size_t j = 0;
            j <
@@ -229,8 +224,7 @@
     std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
         RenderDelayBuffer::Create(NumBandsForRate(rate)));
     std::unique_ptr<RenderDelayController> delay_controller(
-        RenderDelayController::Create(AudioProcessing::Config::EchoCanceller3(),
-                                      rate));
+        RenderDelayController::Create(EchoCanceller3Config(), rate));
     EXPECT_FALSE(delay_controller->AlignmentHeadroomSamples());
   }
 }
@@ -246,8 +240,7 @@
         RenderDelayBuffer::Create(NumBandsForRate(rate)));
     EXPECT_DEATH(
         std::unique_ptr<RenderDelayController>(
-            RenderDelayController::Create(
-                AudioProcessing::Config::EchoCanceller3(), rate))
+            RenderDelayController::Create(EchoCanceller3Config(), rate))
             ->GetDelay(render_delay_buffer->GetDownsampledRenderBuffer(),
                        block),
         "");
@@ -263,8 +256,8 @@
     std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
         RenderDelayBuffer::Create(NumBandsForRate(rate)));
     EXPECT_DEATH(
-        std::unique_ptr<RenderDelayController>(RenderDelayController::Create(
-            AudioProcessing::Config::EchoCanceller3(), rate)),
+        std::unique_ptr<RenderDelayController>(
+            RenderDelayController::Create(EchoCanceller3Config(), rate)),
         "");
   }
 }
diff --git a/modules/audio_processing/aec3/residual_echo_estimator.cc b/modules/audio_processing/aec3/residual_echo_estimator.cc
index 04251a4..7b306ba 100644
--- a/modules/audio_processing/aec3/residual_echo_estimator.cc
+++ b/modules/audio_processing/aec3/residual_echo_estimator.cc
@@ -76,8 +76,7 @@
 
 }  // namespace
 
-ResidualEchoEstimator::ResidualEchoEstimator(
-    const AudioProcessing::Config::EchoCanceller3& config)
+ResidualEchoEstimator::ResidualEchoEstimator(const EchoCanceller3Config& config)
     : config_(config) {
   Reset();
 }
@@ -143,7 +142,7 @@
 
     NonLinearEstimate(
         aec_state.SufficientFilterUpdates(), aec_state.SaturatedEcho(),
-        config_.param.ep_strength.bounded_erl, aec_state.TransparentMode(),
+        config_.ep_strength.bounded_erl, aec_state.TransparentMode(),
         aec_state.InitialState(), X2, Y2, R2);
 
     if (aec_state.ExternalDelay() && aec_state.FilterDelay() &&
@@ -219,9 +218,9 @@
     echo_path_gain_lf = echo_path_gain_mf = echo_path_gain_hf = 0.01f;
   } else {
     // In the initial state, use conservative gains.
-    echo_path_gain_lf = config_.param.ep_strength.lf;
-    echo_path_gain_mf = config_.param.ep_strength.mf;
-    echo_path_gain_hf = config_.param.ep_strength.hf;
+    echo_path_gain_lf = config_.ep_strength.lf;
+    echo_path_gain_mf = config_.ep_strength.mf;
+    echo_path_gain_hf = config_.ep_strength.hf;
   }
 
   // Compute preliminary residual echo.
diff --git a/modules/audio_processing/aec3/residual_echo_estimator.h b/modules/audio_processing/aec3/residual_echo_estimator.h
index d2eada3..d4c4307 100644
--- a/modules/audio_processing/aec3/residual_echo_estimator.h
+++ b/modules/audio_processing/aec3/residual_echo_estimator.h
@@ -26,8 +26,7 @@
 
 class ResidualEchoEstimator {
  public:
-  explicit ResidualEchoEstimator(
-      const AudioProcessing::Config::EchoCanceller3& config);
+  explicit ResidualEchoEstimator(const EchoCanceller3Config& config);
   ~ResidualEchoEstimator();
 
   void Estimate(const AecState& aec_state,
@@ -74,7 +73,7 @@
       S2_old_;
   std::array<float, kFftLengthBy2Plus1> X2_noise_floor_;
   std::array<int, kFftLengthBy2Plus1> X2_noise_floor_counter_;
-  const AudioProcessing::Config::EchoCanceller3 config_;
+  const EchoCanceller3Config config_;
 
   RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(ResidualEchoEstimator);
 };
diff --git a/modules/audio_processing/aec3/residual_echo_estimator_unittest.cc b/modules/audio_processing/aec3/residual_echo_estimator_unittest.cc
index a44a548..76a9739 100644
--- a/modules/audio_processing/aec3/residual_echo_estimator_unittest.cc
+++ b/modules/audio_processing/aec3/residual_echo_estimator_unittest.cc
@@ -23,13 +23,13 @@
 
 // Verifies that the check for non-null output residual echo power works.
 TEST(ResidualEchoEstimator, NullResidualEchoPowerOutput) {
-  AecState aec_state(AudioProcessing::Config::EchoCanceller3{});
+  AecState aec_state(EchoCanceller3Config{});
   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(AudioProcessing::Config::EchoCanceller3{})
+  EXPECT_DEATH(ResidualEchoEstimator(EchoCanceller3Config{})
                    .Estimate(aec_state, render_buffer, S2_linear, Y2, nullptr),
                "");
 }
@@ -37,9 +37,9 @@
 #endif
 
 TEST(ResidualEchoEstimator, BasicTest) {
-  ResidualEchoEstimator estimator(AudioProcessing::Config::EchoCanceller3{});
-  AudioProcessing::Config::EchoCanceller3 config;
-  config.param.ep_strength.default_len = 0.f;
+  ResidualEchoEstimator estimator(EchoCanceller3Config{});
+  EchoCanceller3Config config;
+  config.ep_strength.default_len = 0.f;
   AecState aec_state(config);
   RenderBuffer render_buffer(Aec3Optimization::kNone, 3, 10,
                              std::vector<size_t>(1, 10));
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 a1249e0..da514d9 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(AudioProcessing::Config::EchoCanceller3{});
+  AecState aec_state(EchoCanceller3Config{});
   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 0450b6c..0c296a7 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(AudioProcessing::Config::EchoCanceller3{});
+  AecState aec_state(EchoCanceller3Config{});
   x_old.fill(0.f);
   Y2.fill(0.f);
   E2_main.fill(0.f);
@@ -110,11 +110,9 @@
   RenderSignalAnalyzer render_signal_analyzer;
   std::vector<float> y(kBlockSize, 0.f);
 
-  EXPECT_DEATH(
-      subtractor.Process(render_buffer, y, render_signal_analyzer,
-                         AecState(AudioProcessing::Config::EchoCanceller3{}),
-                         nullptr),
-      "");
+  EXPECT_DEATH(subtractor.Process(render_buffer, y, render_signal_analyzer,
+                                  AecState(EchoCanceller3Config{}), nullptr),
+               "");
 }
 
 // Verifies the check for the capture signal size.
@@ -127,11 +125,9 @@
   std::vector<float> y(kBlockSize - 1, 0.f);
   SubtractorOutput output;
 
-  EXPECT_DEATH(
-      subtractor.Process(render_buffer, y, render_signal_analyzer,
-                         AecState(AudioProcessing::Config::EchoCanceller3{}),
-                         &output),
-      "");
+  EXPECT_DEATH(subtractor.Process(render_buffer, y, render_signal_analyzer,
+                                  AecState(EchoCanceller3Config{}), &output),
+               "");
 }
 
 #endif
diff --git a/modules/audio_processing/aec3/suppression_gain.cc b/modules/audio_processing/aec3/suppression_gain.cc
index 5b4dfcd..90e0ab8 100644
--- a/modules/audio_processing/aec3/suppression_gain.cc
+++ b/modules/audio_processing/aec3/suppression_gain.cc
@@ -109,7 +109,7 @@
 
 // Limits the gain increase.
 void UpdateMaxGainIncrease(
-    const AudioProcessing::Config::EchoCanceller3& config,
+    const EchoCanceller3Config& config,
     size_t no_saturation_counter,
     bool low_noise_render,
     bool linear_echo_estimate,
@@ -125,7 +125,7 @@
   float min_increasing;
   float min_decreasing;
 
-  auto& param = config.param.gain_updates;
+  auto& param = config.gain_updates;
   if (!linear_echo_estimate) {
     max_increasing = param.nonlinear.max_inc;
     max_decreasing = param.nonlinear.max_dec;
@@ -173,7 +173,7 @@
 
 // Computes the gain to reduce the echo to a non audible level.
 void GainToNoAudibleEcho(
-    const AudioProcessing::Config::EchoCanceller3& config,
+    const EchoCanceller3Config& config,
     bool low_noise_render,
     bool saturated_echo,
     bool linear_echo_estimate,
@@ -186,20 +186,20 @@
     std::array<float, kFftLengthBy2Plus1>* gain) {
   float nearend_masking_margin = 0.f;
   if (linear_echo_estimate) {
-    nearend_masking_margin = low_noise_render
-                                 ? config.param.gain_mask.m9
-                                 : (saturated_echo ? config.param.gain_mask.m2
-                                                   : config.param.gain_mask.m3);
+    nearend_masking_margin =
+        low_noise_render
+            ? config.gain_mask.m9
+            : (saturated_echo ? config.gain_mask.m2 : config.gain_mask.m3);
   } else {
-    nearend_masking_margin = config.param.gain_mask.m7;
+    nearend_masking_margin = config.gain_mask.m7;
   }
   RTC_DCHECK_LE(0.f, nearend_masking_margin);
   RTC_DCHECK_GT(1.f, nearend_masking_margin);
   const float one_by_one_minus_nearend_masking_margin =
       1.f / (1.0f - nearend_masking_margin);
 
-  const float masker_margin = linear_echo_estimate ? config.param.gain_mask.m1
-                                                   : config.param.gain_mask.m8;
+  const float masker_margin =
+      linear_echo_estimate ? config.gain_mask.m1 : config.gain_mask.m8;
 
   for (size_t k = 0; k < gain->size(); ++k) {
     const float unity_gain_masker = std::max(nearend[k], masker[k]);
@@ -223,7 +223,7 @@
 constexpr size_t kUpperAccurateBandPlus1 = 29;
 
 // Computes the signal output power that masks the echo signal.
-void MaskingPower(const AudioProcessing::Config::EchoCanceller3& config,
+void MaskingPower(const EchoCanceller3Config& config,
                   const std::array<float, kFftLengthBy2Plus1>& nearend,
                   const std::array<float, kFftLengthBy2Plus1>& comfort_noise,
                   const std::array<float, kFftLengthBy2Plus1>& last_masker,
@@ -236,19 +236,18 @@
     max_nearend_after_gain =
         std::max(max_nearend_after_gain, nearend_after_gain);
     side_band_masker[k] = nearend_after_gain + comfort_noise[k];
-    (*masker)[k] =
-        comfort_noise[k] + config.param.gain_mask.m4 * last_masker[k];
+    (*masker)[k] = comfort_noise[k] + config.gain_mask.m4 * last_masker[k];
   }
 
   // Apply masking only between lower frequency bands.
   RTC_DCHECK_LT(kUpperAccurateBandPlus1, gain.size());
   for (size_t k = 1; k < kUpperAccurateBandPlus1; ++k) {
-    (*masker)[k] += config.param.gain_mask.m5 *
+    (*masker)[k] += config.gain_mask.m5 *
                     (side_band_masker[k - 1] + side_band_masker[k + 1]);
   }
 
   // Add full-band masking as a minimum value for the masker.
-  const float min_masker = max_nearend_after_gain * config.param.gain_mask.m6;
+  const float min_masker = max_nearend_after_gain * config.gain_mask.m6;
   std::for_each(masker->begin(), masker->end(),
                 [min_masker](float& a) { a = std::max(a, min_masker); });
 }
@@ -295,8 +294,8 @@
   // above the zero sample values.
   std::array<float, kFftLengthBy2Plus1> min_gain;
   const float min_echo_power =
-      low_noise_render ? config_.param.echo_audibility.low_render_limit
-                       : config_.param.echo_audibility.normal_render_limit;
+      low_noise_render ? config_.echo_audibility.low_render_limit
+                       : config_.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]);
@@ -311,10 +310,9 @@
   // gain.
   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],
-                          config_.param.gain_updates.floor_first_increase),
-                 1.f);
+    max_gain[k] = std::min(std::max(last_gain_[k] * gain_increase_[k],
+                                    config_.gain_updates.floor_first_increase),
+                           1.f);
   }
 
   // Iteratively compute the gain required to attenuate the echo to a non
@@ -354,9 +352,8 @@
   aec3::VectorMath(optimization_).Sqrt(*gain);
 }
 
-SuppressionGain::SuppressionGain(
-    const AudioProcessing::Config::EchoCanceller3& config,
-    Aec3Optimization optimization)
+SuppressionGain::SuppressionGain(const EchoCanceller3Config& config,
+                                 Aec3Optimization optimization)
     : optimization_(optimization), config_(config) {
   last_gain_.fill(1.f);
   last_masker_.fill(0.f);
diff --git a/modules/audio_processing/aec3/suppression_gain.h b/modules/audio_processing/aec3/suppression_gain.h
index 03c4d2d..45d4ee7 100644
--- a/modules/audio_processing/aec3/suppression_gain.h
+++ b/modules/audio_processing/aec3/suppression_gain.h
@@ -23,7 +23,7 @@
 
 class SuppressionGain {
  public:
-  SuppressionGain(const AudioProcessing::Config::EchoCanceller3& config,
+  SuppressionGain(const EchoCanceller3Config& config,
                   Aec3Optimization optimization);
   void GetGain(const std::array<float, kFftLengthBy2Plus1>& nearend,
                const std::array<float, kFftLengthBy2Plus1>& echo,
@@ -62,7 +62,7 @@
 
   LowNoiseRenderDetector low_render_detector_;
   size_t no_saturation_counter_ = 0;
-  const AudioProcessing::Config::EchoCanceller3 config_;
+  const EchoCanceller3Config config_;
   RTC_DISALLOW_COPY_AND_ASSIGN(SuppressionGain);
 };
 
diff --git a/modules/audio_processing/aec3/suppression_gain_unittest.cc b/modules/audio_processing/aec3/suppression_gain_unittest.cc
index 8348399..f0e13af 100644
--- a/modules/audio_processing/aec3/suppression_gain_unittest.cc
+++ b/modules/audio_processing/aec3/suppression_gain_unittest.cc
@@ -29,8 +29,7 @@
   R2.fill(0.f);
   N2.fill(0.f);
   float high_bands_gain;
-  EXPECT_DEATH(SuppressionGain(AudioProcessing::Config::EchoCanceller3{},
-                               DetectOptimization())
+  EXPECT_DEATH(SuppressionGain(EchoCanceller3Config{}, DetectOptimization())
                    .GetGain(E2, R2, N2, RenderSignalAnalyzer(), false,
                             std::vector<std::vector<float>>(
                                 3, std::vector<float>(kBlockSize, 0.f)),
@@ -42,7 +41,7 @@
 
 // Does a sanity check that the gains are correctly computed.
 TEST(SuppressionGain, BasicGainComputation) {
-  SuppressionGain suppression_gain(AudioProcessing::Config::EchoCanceller3(),
+  SuppressionGain suppression_gain(EchoCanceller3Config(),
                                    DetectOptimization());
   RenderSignalAnalyzer analyzer;
   float high_bands_gain;
diff --git a/modules/audio_processing/audio_processing_impl.cc b/modules/audio_processing/audio_processing_impl.cc
index 3db71c1..5e53853 100644
--- a/modules/audio_processing/audio_processing_impl.cc
+++ b/modules/audio_processing/audio_processing_impl.cc
@@ -603,7 +603,7 @@
       StreamConfig(capture_processing_rate);
 
   int render_processing_rate;
-  if (!config_.echo_canceller3.enabled) {
+  if (!capture_nonlocked_.echo_controller_enabled) {
     render_processing_rate = FindNativeProcessRateToUse(
         std::min(formats_.api_format.reverse_input_stream().sample_rate_hz(),
                  formats_.api_format.reverse_output_stream().sample_rate_hz()),
@@ -616,7 +616,7 @@
   // TODO(aluebs): Remove this restriction once we figure out why the 3-band
   // splitting filter degrades the AEC performance.
   if (render_processing_rate > kSampleRate32kHz &&
-      !config_.echo_canceller3.enabled) {
+      !capture_nonlocked_.echo_controller_enabled) {
     render_processing_rate = submodule_states_.RenderMultiBandProcessingActive()
                                  ? kSampleRate32kHz
                                  : kSampleRate16kHz;
@@ -692,12 +692,13 @@
   LOG(LS_INFO) << "Highpass filter activated: "
                << config_.high_pass_filter.enabled;
 
-  // Inject EchoCanceller3 if requested.
+  // Deprecated way of activating AEC3.
+  // TODO(gustaf): Remove when possible.
   if (config.echo_canceller3.enabled && !echo_control_factory_) {
     capture_nonlocked_.echo_controller_enabled =
         config_.echo_canceller3.enabled;
-    echo_control_factory_ = std::unique_ptr<EchoControlFactory>(
-        new EchoCanceller3Factory(config.echo_canceller3));
+    echo_control_factory_ =
+        std::unique_ptr<EchoControlFactory>(new EchoCanceller3Factory());
     InitializeEchoController();
     LOG(LS_INFO) << "Echo canceller 3 activated: "
                  << capture_nonlocked_.echo_controller_enabled;
diff --git a/modules/audio_processing/include/audio_processing.h b/modules/audio_processing/include/audio_processing.h
index 7276712..28bd7ad 100644
--- a/modules/audio_processing/include/audio_processing.h
+++ b/modules/audio_processing/include/audio_processing.h
@@ -267,71 +267,9 @@
       bool enabled = false;
     } high_pass_filter;
 
-    // Enables the next generation AEC functionality. This feature replaces the
-    // standard methods for echo removal in the AEC.
-    // The functionality is not yet activated in the code and turning this on
-    // does not yet have the desired behavior.
+    // Deprecated way of activating AEC3.
+    // TODO(gustaf): Remove when possible.
     struct EchoCanceller3 {
-      struct Param {
-        struct Delay {
-          size_t default_delay = 5;
-        } delay;
-
-        struct Erle {
-          float min = 1.f;
-          float max_l = 8.f;
-          float max_h = 1.5f;
-        } erle;
-
-        struct EpStrength {
-          float lf = 10.f;
-          float mf = 10.f;
-          float hf = 10.f;
-          float default_len = 0.f;
-          bool echo_can_saturate = true;
-          bool bounded_erl = false;
-        } ep_strength;
-
-        struct Mask {
-          float m1 = 0.01f;
-          float m2 = 0.0001f;
-          float m3 = 0.01f;
-          float m4 = 0.1f;
-          float m5 = 0.3f;
-          float m6 = 0.0001f;
-          float m7 = 0.01f;
-          float m8 = 0.0001f;
-          float m9 = 0.1f;
-        } gain_mask;
-
-        struct EchoAudibility {
-          float low_render_limit = 4 * 64.f;
-          float normal_render_limit = 64.f;
-        } echo_audibility;
-
-        struct RenderLevels {
-          float active_render_limit = 100.f;
-          float poor_excitation_render_limit = 150.f;
-        } render_levels;
-
-        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 = {3.f, 3.f, 1.5f, 1.5f, 1.5f, 1.5f};
-          GainChanges normal = {2.f, 2.f, 1.5f, 1.5f, 1.2f, 1.2f};
-          GainChanges saturation = {1.2f, 1.2f, 1.5f, 1.5f, 1.f, 1.f};
-          GainChanges nonlinear = {1.5f, 1.5f, 1.2f, 1.2f, 1.1f, 1.1f};
-
-          float floor_first_increase = 0.0001f;
-        } gain_updates;
-      } param;
       bool enabled = false;
     } echo_canceller3;
 
@@ -1194,6 +1132,78 @@
  protected:
   virtual ~VoiceDetection() {}
 };
+
+// Configuration struct for EchoCanceller3
+struct EchoCanceller3Config {
+  struct Delay {
+    size_t default_delay = 5;
+  } delay;
+
+  struct Erle {
+    float min = 1.f;
+    float max_l = 8.f;
+    float max_h = 1.5f;
+  } erle;
+
+  struct EpStrength {
+    float lf = 10.f;
+    float mf = 10.f;
+    float hf = 10.f;
+    float default_len = 0.f;
+    bool echo_can_saturate = true;
+    bool bounded_erl = false;
+  } ep_strength;
+
+  struct Mask {
+    float m1 = 0.01f;
+    float m2 = 0.0001f;
+    float m3 = 0.01f;
+    float m4 = 0.1f;
+    float m5 = 0.3f;
+    float m6 = 0.0001f;
+    float m7 = 0.01f;
+    float m8 = 0.0001f;
+    float m9 = 0.1f;
+  } gain_mask;
+
+  struct EchoAudibility {
+    float low_render_limit = 4 * 64.f;
+    float normal_render_limit = 64.f;
+  } echo_audibility;
+
+  struct RenderLevels {
+    float active_render_limit = 100.f;
+    float poor_excitation_render_limit = 150.f;
+  } render_levels;
+
+  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 = {3.f, 3.f, 1.5f, 1.5f, 1.5f, 1.5f};
+    GainChanges normal = {2.f, 2.f, 1.5f, 1.5f, 1.2f, 1.2f};
+    GainChanges saturation = {1.2f, 1.2f, 1.5f, 1.5f, 1.f, 1.f};
+    GainChanges nonlinear = {1.5f, 1.5f, 1.2f, 1.2f, 1.1f, 1.1f};
+
+    float floor_first_increase = 0.0001f;
+  } gain_updates;
+};
+
+class EchoCanceller3Factory : public EchoControlFactory {
+ public:
+  EchoCanceller3Factory();
+  EchoCanceller3Factory(const EchoCanceller3Config& config);
+  std::unique_ptr<EchoControl> Create(int sample_rate_hz) override;
+
+ private:
+  EchoCanceller3Config config_;
+};
 }  // namespace webrtc
 
 #endif  // MODULES_AUDIO_PROCESSING_INCLUDE_AUDIO_PROCESSING_H_
diff --git a/modules/audio_processing/test/aec_dump_based_simulator.cc b/modules/audio_processing/test/aec_dump_based_simulator.cc
index 23b7afb..6d0b07c 100644
--- a/modules/audio_processing/test/aec_dump_based_simulator.cc
+++ b/modules/audio_processing/test/aec_dump_based_simulator.cc
@@ -473,10 +473,6 @@
           new RefinedAdaptiveFilter(*settings_.use_refined_adaptive_filter));
     }
 
-    if (settings_.use_aec3) {
-      apm_config.echo_canceller3.enabled = *settings_.use_aec3;
-    }
-
     if (settings_.use_lc) {
       apm_config.level_controller.enabled = *settings_.use_lc;
     }
diff --git a/modules/audio_processing/test/audio_processing_simulator.cc b/modules/audio_processing/test/audio_processing_simulator.cc
index 1683010..20bad81 100644
--- a/modules/audio_processing/test/audio_processing_simulator.cc
+++ b/modules/audio_processing/test/audio_processing_simulator.cc
@@ -306,6 +306,7 @@
 void AudioProcessingSimulator::CreateAudioProcessor() {
   Config config;
   AudioProcessing::Config apm_config;
+  std::unique_ptr<EchoControlFactory> echo_control_factory;
   if (settings_.use_bf && *settings_.use_bf) {
     config.Set<Beamforming>(new Beamforming(
         true, ParseArrayGeometry(*settings_.microphone_positions),
@@ -318,13 +319,13 @@
   if (settings_.use_ie) {
     config.Set<Intelligibility>(new Intelligibility(*settings_.use_ie));
   }
-  if (settings_.use_aec3) {
-    apm_config.echo_canceller3.enabled = *settings_.use_aec3;
-  }
   if (settings_.use_agc2) {
     apm_config.gain_controller2.enabled = *settings_.use_agc2;
     apm_config.gain_controller2.fixed_gain_db = settings_.agc2_fixed_gain_db;
   }
+  if (settings_.use_aec3 && *settings_.use_aec3) {
+    echo_control_factory.reset(new EchoCanceller3Factory());
+  }
   if (settings_.use_lc) {
     apm_config.level_controller.enabled = *settings_.use_lc;
   }
@@ -346,7 +347,8 @@
     apm_config.residual_echo_detector.enabled = *settings_.use_ed;
   }
 
-  ap_.reset(AudioProcessing::Create(config));
+  ap_.reset(AudioProcessing::Create(config, nullptr,
+                                    std::move(echo_control_factory), nullptr));
   RTC_CHECK(ap_);
 
   ap_->ApplyConfig(apm_config);
diff --git a/modules/audio_processing/test/debug_dump_test.cc b/modules/audio_processing/test/debug_dump_test.cc
index a450950..2c839d3 100644
--- a/modules/audio_processing/test/debug_dump_test.cc
+++ b/modules/audio_processing/test/debug_dump_test.cc
@@ -46,10 +46,15 @@
                      int reverse_rate_hz,
                      int reverse_channels,
                      const Config& config,
-                     const std::string& dump_file_name);
+                     const std::string& dump_file_name,
+                     bool enable_aec3);
 
   // Constructor that uses default input files.
   explicit DebugDumpGenerator(const Config& config,
+                              const AudioProcessing::Config& apm_config,
+                              bool enable_aec3);
+
+  explicit DebugDumpGenerator(const Config& config,
                               const AudioProcessing::Config& apm_config);
 
   ~DebugDumpGenerator();
@@ -118,7 +123,8 @@
                                        int reverse_rate_hz,
                                        int reverse_channels,
                                        const Config& config,
-                                       const std::string& dump_file_name)
+                                       const std::string& dump_file_name,
+                                       bool enable_aec3)
     : input_config_(input_rate_hz, input_channels),
       reverse_config_(reverse_rate_hz, reverse_channels),
       output_config_(input_rate_hz, input_channels),
@@ -133,12 +139,19 @@
       output_(new ChannelBuffer<float>(output_config_.num_frames(),
                                        output_config_.num_channels())),
       worker_queue_("debug_dump_generator_worker_queue"),
-      apm_(AudioProcessing::Create(config)),
+      apm_(AudioProcessing::Create(
+          config,
+          nullptr,
+          (enable_aec3 ? std::unique_ptr<EchoControlFactory>(
+                             new EchoCanceller3Factory())
+                       : nullptr),
+          nullptr)),
       dump_file_name_(dump_file_name) {}
 
 DebugDumpGenerator::DebugDumpGenerator(
     const Config& config,
-    const AudioProcessing::Config& apm_config)
+    const AudioProcessing::Config& apm_config,
+    bool enable_aec3)
     : DebugDumpGenerator(ResourcePath("near32_stereo", "pcm"),
                          32000,
                          2,
@@ -146,7 +159,15 @@
                          32000,
                          2,
                          config,
-                         TempFilename(OutputPath(), "debug_aec")) {
+                         TempFilename(OutputPath(), "debug_aec"),
+                         enable_aec3) {
+  apm_->ApplyConfig(apm_config);
+}
+
+DebugDumpGenerator::DebugDumpGenerator(
+    const Config& config,
+    const AudioProcessing::Config& apm_config)
+    : DebugDumpGenerator(config, apm_config, false) {
   apm_->ApplyConfig(apm_config);
 }
 
@@ -384,8 +405,8 @@
   config.Set<RefinedAdaptiveFilter>(new RefinedAdaptiveFilter(true));
   // Arbitrarily set clipping gain to 17, which will never be the default.
   config.Set<ExperimentalAgc>(new ExperimentalAgc(true, 0, 17));
-  apm_config.echo_canceller3.enabled = true;
-  DebugDumpGenerator generator(config, apm_config);
+  bool enable_aec3 = true;
+  DebugDumpGenerator generator(config, apm_config, enable_aec3);
   generator.StartRecording();
   generator.Process(100);
   generator.StopRecording();
@@ -441,8 +462,7 @@
 TEST_F(DebugDumpTest, VerifyAec3ExperimentalString) {
   Config config;
   AudioProcessing::Config apm_config;
-  apm_config.echo_canceller3.enabled = true;
-  DebugDumpGenerator generator(config, apm_config);
+  DebugDumpGenerator generator(config, apm_config, true);
   generator.StartRecording();
   generator.Process(100);
   generator.StopRecording();
diff --git a/test/fuzzers/audio_processing_fuzzer_configs.cc b/test/fuzzers/audio_processing_fuzzer_configs.cc
index 294090f..ed34c35 100644
--- a/test/fuzzers/audio_processing_fuzzer_configs.cc
+++ b/test/fuzzers/audio_processing_fuzzer_configs.cc
@@ -49,6 +49,11 @@
   // webrtc::AudioProcessingConfig.
   Config config;
 
+  std::unique_ptr<EchoControlFactory> echo_control_factory;
+  if (*aec3) {
+    echo_control_factory.reset(new EchoCanceller3Factory());
+  }
+
   config.Set<ExperimentalAgc>(new ExperimentalAgc(*exp_agc));
   config.Set<ExperimentalNs>(new ExperimentalNs(*exp_ns));
   if (*bf) {
@@ -59,13 +64,13 @@
   config.Set<DelayAgnostic>(new DelayAgnostic(*da));
   config.Set<Intelligibility>(new Intelligibility(*ie));
 
-  std::unique_ptr<AudioProcessing> apm(AudioProcessing::Create(config));
+  std::unique_ptr<AudioProcessing> apm(AudioProcessing::Create(
+      config, nullptr, std::move(echo_control_factory), nullptr));
 
   webrtc::AudioProcessing::Config apm_config;
   apm_config.residual_echo_detector.enabled = *red;
   apm_config.level_controller.enabled = *lc;
   apm_config.high_pass_filter.enabled = *hpf;
-  apm_config.echo_canceller3.enabled = *aec3;
 
   apm->ApplyConfig(apm_config);