The current scheme for setting parameters and specifying the behavior
of the audio processing module is quite complex and hard to implement
in a threadsafe and efficient manner. Therefore a new scheme for setting
the parameters in the audio processing module is introduced in this CL.

The idea is to roll this scheme out gradually and as a first functionality
in the audio processing module where this is applied the level controller
was chosen. This CL includes the replacement of the Config-based
level controller scheme with the new scheme.

BUG=webrtc:5298

Review-Url: https://codereview.webrtc.org/2292863002
Cr-Commit-Position: refs/heads/master@{#14171}
diff --git a/webrtc/media/engine/fakewebrtcvoiceengine.h b/webrtc/media/engine/fakewebrtcvoiceengine.h
index 33ea7ca..f1e63a5 100644
--- a/webrtc/media/engine/fakewebrtcvoiceengine.h
+++ b/webrtc/media/engine/fakewebrtcvoiceengine.h
@@ -70,6 +70,7 @@
   WEBRTC_STUB(Initialize, (
       const webrtc::ProcessingConfig& processing_config));
 
+  WEBRTC_VOID_STUB(ApplyConfig, (const AudioProcessing::Config& config));
   WEBRTC_VOID_FUNC(SetExtraOptions, (const webrtc::Config& config)) {
     experimental_ns_enabled_ = config.Get<webrtc::ExperimentalNs>().enabled;
   }
diff --git a/webrtc/media/engine/webrtcvoiceengine.cc b/webrtc/media/engine/webrtcvoiceengine.cc
index 2992411..4343612 100644
--- a/webrtc/media/engine/webrtcvoiceengine.cc
+++ b/webrtc/media/engine/webrtcvoiceengine.cc
@@ -868,8 +868,9 @@
 
   LOG(LS_INFO) << "Level control: "
                << (!!level_control_ ? *level_control_ : -1);
+  webrtc::AudioProcessing::Config apm_config;
   if (level_control_) {
-    config.Set<webrtc::LevelControl>(new webrtc::LevelControl(*level_control_));
+    apm_config.level_controller.enabled = *level_control_;
   }
 
   // We check audioproc for the benefit of tests, since FakeWebRtcVoiceEngine
@@ -877,6 +878,7 @@
   webrtc::AudioProcessing* audioproc = voe_wrapper_->base()->audio_processing();
   if (audioproc) {
     audioproc->SetExtraOptions(config);
+    audioproc->ApplyConfig(apm_config);
   }
 
   if (options.recording_sample_rate) {
diff --git a/webrtc/modules/audio_processing/audio_processing_impl.cc b/webrtc/modules/audio_processing/audio_processing_impl.cc
index 222f749..dabc4b8 100644
--- a/webrtc/modules/audio_processing/audio_processing_impl.cc
+++ b/webrtc/modules/audio_processing/audio_processing_impl.cc
@@ -154,15 +154,15 @@
 };
 
 AudioProcessing* AudioProcessing::Create() {
-  Config config;
+  webrtc::Config config;
   return Create(config, nullptr);
 }
 
-AudioProcessing* AudioProcessing::Create(const Config& config) {
+AudioProcessing* AudioProcessing::Create(const webrtc::Config& config) {
   return Create(config, nullptr);
 }
 
-AudioProcessing* AudioProcessing::Create(const Config& config,
+AudioProcessing* AudioProcessing::Create(const webrtc::Config& config,
                                          NonlinearBeamformer* beamformer) {
   AudioProcessingImpl* apm = new AudioProcessingImpl(config, beamformer);
   if (apm->Initialize() != kNoError) {
@@ -173,10 +173,10 @@
   return apm;
 }
 
-AudioProcessingImpl::AudioProcessingImpl(const Config& config)
+AudioProcessingImpl::AudioProcessingImpl(const webrtc::Config& config)
     : AudioProcessingImpl(config, nullptr) {}
 
-AudioProcessingImpl::AudioProcessingImpl(const Config& config,
+AudioProcessingImpl::AudioProcessingImpl(const webrtc::Config& config,
                                          NonlinearBeamformer* beamformer)
     : public_submodules_(new ApmPublicSubmodules()),
       private_submodules_(new ApmPrivateSubmodules(beamformer)),
@@ -194,8 +194,7 @@
                config.Get<Beamforming>().array_geometry,
                config.Get<Beamforming>().target_direction),
       capture_nonlocked_(config.Get<Beamforming>().enabled,
-                         config.Get<Intelligibility>().enabled,
-                         config.Get<LevelControl>().enabled) {
+                         config.Get<Intelligibility>().enabled) {
   {
     rtc::CritScope cs_render(&crit_render_);
     rtc::CritScope cs_capture(&crit_capture_);
@@ -432,7 +431,34 @@
   return InitializeLocked();
 }
 
-void AudioProcessingImpl::SetExtraOptions(const Config& config) {
+void AudioProcessingImpl::ApplyConfig(const AudioProcessing::Config& config) {
+  AudioProcessing::Config config_to_use = config;
+
+  bool config_ok = LevelController::Validate(config_to_use.level_controller);
+  if (!config_ok) {
+    LOG(LS_ERROR) << "AudioProcessing module config error" << std::endl
+                  << "level_controller: "
+                  << LevelController::ToString(config_to_use.level_controller)
+                  << std::endl
+                  << "Reverting to default parameter set";
+    config_to_use.level_controller = AudioProcessing::Config::LevelController();
+  }
+
+  // Run in a single-threaded manner when applying the settings.
+  rtc::CritScope cs_render(&crit_render_);
+  rtc::CritScope cs_capture(&crit_capture_);
+
+  if (config.level_controller.enabled !=
+      capture_nonlocked_.level_controller_enabled) {
+    InitializeLevelController();
+    LOG(LS_INFO) << "Level controller activated: "
+                 << capture_nonlocked_.level_controller_enabled;
+    capture_nonlocked_.level_controller_enabled =
+        config.level_controller.enabled;
+  }
+}
+
+void AudioProcessingImpl::SetExtraOptions(const webrtc::Config& config) {
   // Run in a single-threaded manner when setting the extra options.
   rtc::CritScope cs_render(&crit_render_);
   rtc::CritScope cs_capture(&crit_capture_);
@@ -446,16 +472,6 @@
     InitializeTransient();
   }
 
-  if (capture_nonlocked_.level_controller_enabled !=
-      config.Get<LevelControl>().enabled) {
-    capture_nonlocked_.level_controller_enabled =
-        config.Get<LevelControl>().enabled;
-    LOG(LS_INFO) << "Level controller activated: "
-                 << config.Get<LevelControl>().enabled;
-
-    InitializeLevelController();
-  }
-
 #if WEBRTC_INTELLIGIBILITY_ENHANCER
   if(capture_nonlocked_.intelligibility_enabled !=
      config.Get<Intelligibility>().enabled) {
diff --git a/webrtc/modules/audio_processing/audio_processing_impl.h b/webrtc/modules/audio_processing/audio_processing_impl.h
index 87e2224..00484c2 100644
--- a/webrtc/modules/audio_processing/audio_processing_impl.h
+++ b/webrtc/modules/audio_processing/audio_processing_impl.h
@@ -42,9 +42,10 @@
  public:
   // Methods forcing APM to run in a single-threaded manner.
   // Acquires both the render and capture locks.
-  explicit AudioProcessingImpl(const Config& config);
+  explicit AudioProcessingImpl(const webrtc::Config& config);
   // AudioProcessingImpl takes ownership of beamformer.
-  AudioProcessingImpl(const Config& config, NonlinearBeamformer* beamformer);
+  AudioProcessingImpl(const webrtc::Config& config,
+                      NonlinearBeamformer* beamformer);
   ~AudioProcessingImpl() override;
   int Initialize() override;
   int Initialize(int input_sample_rate_hz,
@@ -54,7 +55,8 @@
                  ChannelLayout output_layout,
                  ChannelLayout reverse_layout) override;
   int Initialize(const ProcessingConfig& processing_config) override;
-  void SetExtraOptions(const Config& config) override;
+  void ApplyConfig(const AudioProcessing::Config& config) override;
+  void SetExtraOptions(const webrtc::Config& config) override;
   void UpdateHistogramsOnCallEnd() override;
   int StartDebugRecording(const char filename[kMaxFilenameSize],
                           int64_t max_log_size_bytes) override;
@@ -312,14 +314,12 @@
 
   struct ApmCaptureNonLockedState {
     ApmCaptureNonLockedState(bool beamformer_enabled,
-                             bool intelligibility_enabled,
-                             bool level_controller_enabled)
+                             bool intelligibility_enabled)
         : fwd_proc_format(kSampleRate16kHz),
           split_rate(kSampleRate16kHz),
           stream_delay_ms(0),
           beamformer_enabled(beamformer_enabled),
-          intelligibility_enabled(intelligibility_enabled),
-          level_controller_enabled(level_controller_enabled) {}
+          intelligibility_enabled(intelligibility_enabled) {}
     // Only the rate and samples fields of fwd_proc_format_ are used because the
     // forward processing number of channels is mutable and is tracked by the
     // capture_audio_.
@@ -328,7 +328,7 @@
     int stream_delay_ms;
     bool beamformer_enabled;
     bool intelligibility_enabled;
-    bool level_controller_enabled;
+    bool level_controller_enabled = false;
   } capture_nonlocked_;
 
   struct ApmRenderState {
diff --git a/webrtc/modules/audio_processing/audio_processing_impl_unittest.cc b/webrtc/modules/audio_processing/audio_processing_impl_unittest.cc
index 54e0331..d91457c 100644
--- a/webrtc/modules/audio_processing/audio_processing_impl_unittest.cc
+++ b/webrtc/modules/audio_processing/audio_processing_impl_unittest.cc
@@ -23,8 +23,8 @@
 
 class MockInitialize : public AudioProcessingImpl {
  public:
-  explicit MockInitialize(const Config& config) : AudioProcessingImpl(config) {
-  }
+  explicit MockInitialize(const webrtc::Config& config)
+      : AudioProcessingImpl(config) {}
 
   MOCK_METHOD0(InitializeLocked, int());
   int RealInitializeLocked() NO_THREAD_SAFETY_ANALYSIS {
@@ -33,7 +33,7 @@
 };
 
 TEST(AudioProcessingImplTest, AudioParameterChangeTriggersInit) {
-  Config config;
+  webrtc::Config config;
   MockInitialize mock(config);
   ON_CALL(mock, InitializeLocked())
       .WillByDefault(Invoke(&mock, &MockInitialize::RealInitializeLocked));
diff --git a/webrtc/modules/audio_processing/echo_cancellation_impl.cc b/webrtc/modules/audio_processing/echo_cancellation_impl.cc
index 5a7aef6..9cfa043 100644
--- a/webrtc/modules/audio_processing/echo_cancellation_impl.cc
+++ b/webrtc/modules/audio_processing/echo_cancellation_impl.cc
@@ -538,7 +538,7 @@
   }
 }
 
-void EchoCancellationImpl::SetExtraOptions(const Config& config) {
+void EchoCancellationImpl::SetExtraOptions(const webrtc::Config& config) {
   {
     rtc::CritScope cs(crit_capture_);
     extended_filter_enabled_ = config.Get<ExtendedFilter>().enabled;
diff --git a/webrtc/modules/audio_processing/echo_cancellation_impl.h b/webrtc/modules/audio_processing/echo_cancellation_impl.h
index 0f0945f..8216c50 100644
--- a/webrtc/modules/audio_processing/echo_cancellation_impl.h
+++ b/webrtc/modules/audio_processing/echo_cancellation_impl.h
@@ -43,7 +43,7 @@
                   size_t num_reverse_channels_,
                   size_t num_output_channels_,
                   size_t num_proc_channels_);
-  void SetExtraOptions(const Config& config);
+  void SetExtraOptions(const webrtc::Config& config);
   bool is_delay_agnostic_enabled() const;
   bool is_extended_filter_enabled() const;
   bool is_aec3_enabled() const;
diff --git a/webrtc/modules/audio_processing/include/audio_processing.h b/webrtc/modules/audio_processing/include/audio_processing.h
index 44ff732..035fa32 100644
--- a/webrtc/modules/audio_processing/include/audio_processing.h
+++ b/webrtc/modules/audio_processing/include/audio_processing.h
@@ -91,14 +91,6 @@
   bool enabled;
 };
 
-// Enables the adaptive level controller.
-struct LevelControl {
-  LevelControl() : enabled(false) {}
-  explicit LevelControl(bool enabled) : enabled(enabled) {}
-  static const ConfigOptionID identifier = ConfigOptionID::kLevelControl;
-  bool enabled;
-};
-
 // Enables delay-agnostic echo cancellation. This feature relies on internally
 // estimated delays between the process and reverse streams, thus not relying
 // on reported system delays. This configuration only applies to
@@ -205,6 +197,10 @@
 // Usage example, omitting error checking:
 // AudioProcessing* apm = AudioProcessing::Create(0);
 //
+// AudioProcessing::Config config;
+// config.level_controller.enabled = true;
+// apm->ApplyConfig(config)
+//
 // apm->high_pass_filter()->Enable(true);
 //
 // apm->echo_cancellation()->enable_drift_compensation(false);
@@ -244,14 +240,29 @@
 //
 class AudioProcessing {
  public:
+  // The struct below constitutes the new parameter scheme for the audio
+  // processing. It is being introduced gradually and until it is fully
+  // introduced, it is prone to change.
+  // TODO(peah): Remove this comment once the new config scheme is fully rolled
+  // out.
+  //
+  // The parameters and behavior of the audio processing module are controlled
+  // by changing the default values in the AudioProcessing::Config struct.
+  // The config is applied by passing the struct to the ApplyConfig method.
+  struct Config {
+    struct LevelController {
+      bool enabled = false;
+    } level_controller;
+  };
+
   // TODO(mgraczyk): Remove once all methods that use ChannelLayout are gone.
   enum ChannelLayout {
     kMono,
     // Left, right.
     kStereo,
-    // Mono, keyboard mic.
+    // Mono, keyboard, and mic.
     kMonoAndKeyboard,
-    // Left, right, keyboard mic.
+    // Left, right, keyboard, and mic.
     kStereoAndKeyboard
   };
 
@@ -262,9 +273,9 @@
   // be one instance for every incoming stream.
   static AudioProcessing* Create();
   // Allows passing in an optional configuration at create-time.
-  static AudioProcessing* Create(const Config& config);
+  static AudioProcessing* Create(const webrtc::Config& config);
   // Only for testing.
-  static AudioProcessing* Create(const Config& config,
+  static AudioProcessing* Create(const webrtc::Config& config,
                                  NonlinearBeamformer* beamformer);
   virtual ~AudioProcessing() {}
 
@@ -300,9 +311,13 @@
                          ChannelLayout output_layout,
                          ChannelLayout reverse_layout) = 0;
 
+  // TODO(peah): This method is a temporary solution used to take control
+  // over the parameters in the audio processing module and is likely to change.
+  virtual void ApplyConfig(const Config& config) = 0;
+
   // Pass down additional options which don't have explicit setters. This
   // ensures the options are applied immediately.
-  virtual void SetExtraOptions(const Config& config) = 0;
+  virtual void SetExtraOptions(const webrtc::Config& config) = 0;
 
   // TODO(ajm): Only intended for internal use. Make private and friend the
   // necessary classes?
diff --git a/webrtc/modules/audio_processing/include/mock_audio_processing.h b/webrtc/modules/audio_processing/include/mock_audio_processing.h
index b5ea587..0566e85 100644
--- a/webrtc/modules/audio_processing/include/mock_audio_processing.h
+++ b/webrtc/modules/audio_processing/include/mock_audio_processing.h
@@ -190,8 +190,8 @@
           ChannelLayout reverse_layout));
   MOCK_METHOD1(Initialize,
       int(const ProcessingConfig& processing_config));
-  MOCK_METHOD1(SetExtraOptions,
-      void(const Config& config));
+  MOCK_METHOD1(ApplyConfig, void(const Config& config));
+  MOCK_METHOD1(SetExtraOptions, void(const webrtc::Config& config));
   MOCK_METHOD1(set_sample_rate_hz,
       int(int rate));
   MOCK_CONST_METHOD0(input_sample_rate_hz,
diff --git a/webrtc/modules/audio_processing/level_controller/level_controller.cc b/webrtc/modules/audio_processing/level_controller/level_controller.cc
index 2294396..c0edeb9 100644
--- a/webrtc/modules/audio_processing/level_controller/level_controller.cc
+++ b/webrtc/modules/audio_processing/level_controller/level_controller.cc
@@ -262,4 +262,17 @@
                         audio->channels_f()[0], *sample_rate_hz_, 1);
 }
 
+std::string LevelController::ToString(
+    const AudioProcessing::Config::LevelController& config) {
+  std::stringstream ss;
+  ss << "{"
+     << "enabled: " << (config.enabled ? "true" : "false") << "}";
+  return ss.str();
+}
+
+bool LevelController::Validate(
+    const AudioProcessing::Config::LevelController& config) {
+  return true;
+}
+
 }  // namespace webrtc
diff --git a/webrtc/modules/audio_processing/level_controller/level_controller.h b/webrtc/modules/audio_processing/level_controller/level_controller.h
index 65fc360..1d8e043 100644
--- a/webrtc/modules/audio_processing/level_controller/level_controller.h
+++ b/webrtc/modules/audio_processing/level_controller/level_controller.h
@@ -38,6 +38,12 @@
   void Process(AudioBuffer* audio);
   float GetLastGain() { return last_gain_; }
 
+  // Validates a config.
+  static bool Validate(const AudioProcessing::Config::LevelController& config);
+  // Dumps a config to a string.
+  static std::string ToString(
+      const AudioProcessing::Config::LevelController& config);
+
  private:
   class Metrics {
    public:
diff --git a/webrtc/modules/audio_processing/level_controller/level_controller_complexity_unittest.cc b/webrtc/modules/audio_processing/level_controller/level_controller_complexity_unittest.cc
index a90774f..b8033aa 100644
--- a/webrtc/modules/audio_processing/level_controller/level_controller_complexity_unittest.cc
+++ b/webrtc/modules/audio_processing/level_controller/level_controller_complexity_unittest.cc
@@ -198,16 +198,18 @@
   SubmodulePerformanceTimer capture_timer;
   SubmodulePerformanceTimer total_timer;
 
-  Config config;
+  webrtc::Config config;
+  AudioProcessing::Config apm_config;
   if (include_default_apm_processing) {
     config.Set<DelayAgnostic>(new DelayAgnostic(true));
     config.Set<ExtendedFilter>(new ExtendedFilter(true));
   }
-  config.Set<LevelControl>(new LevelControl(true));
+  apm_config.level_controller.enabled = true;
 
   std::unique_ptr<AudioProcessing> apm;
   apm.reset(AudioProcessing::Create(config));
   ASSERT_TRUE(apm.get());
+  apm->ApplyConfig(apm_config);
 
   ASSERT_EQ(AudioProcessing::kNoError,
             apm->gain_control()->Enable(include_default_apm_processing));
diff --git a/webrtc/modules/audio_processing/level_controller/level_controller_unittest.cc b/webrtc/modules/audio_processing/level_controller/level_controller_unittest.cc
index c470c2f..f5cea0d 100644
--- a/webrtc/modules/audio_processing/level_controller/level_controller_unittest.cc
+++ b/webrtc/modules/audio_processing/level_controller/level_controller_unittest.cc
@@ -68,6 +68,25 @@
 
 }  // namespace
 
+TEST(LevelControlConfigTest, ToStringEnabled) {
+  AudioProcessing::Config config;
+  config.level_controller.enabled = true;
+  EXPECT_EQ("{enabled: true}",
+            LevelController::ToString(config.level_controller));
+}
+
+TEST(LevelControlConfigTest, ToStringNotEnabled) {
+  AudioProcessing::Config config;
+  config.level_controller.enabled = false;
+  EXPECT_EQ("{enabled: false}",
+            LevelController::ToString(config.level_controller));
+}
+
+TEST(LevelControlConfigTest, DefaultValue) {
+  AudioProcessing::Config config;
+  EXPECT_FALSE(config.level_controller.enabled);
+}
+
 TEST(LevelControlBitExactnessTest, DISABLED_Mono8kHz) {
   const float kOutputReference[] = {-0.013939f, -0.012154f, -0.009054f};
   RunBitexactnessTest(AudioProcessing::kSampleRate8kHz, 1,
diff --git a/webrtc/modules/audio_processing/test/aec_dump_based_simulator.cc b/webrtc/modules/audio_processing/test/aec_dump_based_simulator.cc
index e21f42a..d2b05ad 100644
--- a/webrtc/modules/audio_processing/test/aec_dump_based_simulator.cc
+++ b/webrtc/modules/audio_processing/test/aec_dump_based_simulator.cc
@@ -236,6 +236,7 @@
       std::cout << "Setting used in config:" << std::endl;
     }
     Config config;
+    AudioProcessing::Config apm_config;
 
     if (msg.has_aec_enabled() || settings_.use_aec) {
       bool enable = settings_.use_aec ? *settings_.use_aec : msg.aec_enabled();
@@ -442,9 +443,10 @@
     }
 
     if (settings_.use_lc) {
-      config.Set<LevelControl>(new LevelControl(true));
+      apm_config.level_controller.enabled = true;
     }
 
+    ap_->ApplyConfig(apm_config);
     ap_->SetExtraOptions(config);
   }
 }
diff --git a/webrtc/modules/audio_processing/test/audio_processing_simulator.cc b/webrtc/modules/audio_processing/test/audio_processing_simulator.cc
index a34c3ca..778b347 100644
--- a/webrtc/modules/audio_processing/test/audio_processing_simulator.cc
+++ b/webrtc/modules/audio_processing/test/audio_processing_simulator.cc
@@ -218,6 +218,7 @@
 
 void AudioProcessingSimulator::CreateAudioProcessor() {
   Config config;
+  AudioProcessing::Config apm_config;
   if (settings_.use_bf && *settings_.use_bf) {
     config.Set<Beamforming>(new Beamforming(
         true, ParseArrayGeometry(*settings_.microphone_positions),
@@ -234,7 +235,7 @@
     config.Set<EchoCanceller3>(new EchoCanceller3(*settings_.use_aec3));
   }
   if (settings_.use_lc) {
-    config.Set<LevelControl>(new LevelControl(true));
+    apm_config.level_controller.enabled = *settings_.use_lc;
   }
   if (settings_.use_refined_adaptive_filter) {
     config.Set<RefinedAdaptiveFilter>(
@@ -246,6 +247,9 @@
                                               *settings_.use_delay_agnostic));
 
   ap_.reset(AudioProcessing::Create(config));
+  RTC_CHECK(ap_);
+
+  ap_->ApplyConfig(apm_config);
 
   if (settings_.use_aec) {
     RTC_CHECK_EQ(AudioProcessing::kNoError,
diff --git a/webrtc/modules/audio_processing/test/debug_dump_test.cc b/webrtc/modules/audio_processing/test/debug_dump_test.cc
index 103f8e1..9987342 100644
--- a/webrtc/modules/audio_processing/test/debug_dump_test.cc
+++ b/webrtc/modules/audio_processing/test/debug_dump_test.cc
@@ -48,7 +48,8 @@
                      const std::string& dump_file_name);
 
   // Constructor that uses default input files.
-  explicit DebugDumpGenerator(const Config& config);
+  explicit DebugDumpGenerator(const Config& config,
+                              const AudioProcessing::Config& apm_config);
 
   ~DebugDumpGenerator();
 
@@ -133,11 +134,18 @@
       dump_file_name_(dump_file_name) {
 }
 
-DebugDumpGenerator::DebugDumpGenerator(const Config& config)
-  : DebugDumpGenerator(ResourcePath("near32_stereo", "pcm"), 32000, 2,
-                       ResourcePath("far32_stereo", "pcm"), 32000, 2,
-                       config,
-                       TempFilename(OutputPath(), "debug_aec")) {
+DebugDumpGenerator::DebugDumpGenerator(
+    const Config& config,
+    const AudioProcessing::Config& apm_config)
+    : DebugDumpGenerator(ResourcePath("near32_stereo", "pcm"),
+                         32000,
+                         2,
+                         ResourcePath("far32_stereo", "pcm"),
+                         32000,
+                         2,
+                         config,
+                         TempFilename(OutputPath(), "debug_aec")) {
+  apm_->ApplyConfig(apm_config);
 }
 
 DebugDumpGenerator::~DebugDumpGenerator() {
@@ -265,7 +273,7 @@
 
 TEST_F(DebugDumpTest, SimpleCase) {
   Config config;
-  DebugDumpGenerator generator(config);
+  DebugDumpGenerator generator(config, AudioProcessing::Config());
   generator.StartRecording();
   generator.Process(100);
   generator.StopRecording();
@@ -274,7 +282,8 @@
 
 TEST_F(DebugDumpTest, ChangeInputFormat) {
   Config config;
-  DebugDumpGenerator generator(config);
+  DebugDumpGenerator generator(config, AudioProcessing::Config());
+
   generator.StartRecording();
   generator.Process(100);
   generator.SetInputRate(48000);
@@ -291,7 +300,7 @@
 
 TEST_F(DebugDumpTest, ChangeReverseFormat) {
   Config config;
-  DebugDumpGenerator generator(config);
+  DebugDumpGenerator generator(config, AudioProcessing::Config());
   generator.StartRecording();
   generator.Process(100);
   generator.SetReverseRate(48000);
@@ -303,7 +312,7 @@
 
 TEST_F(DebugDumpTest, ChangeOutputFormat) {
   Config config;
-  DebugDumpGenerator generator(config);
+  DebugDumpGenerator generator(config, AudioProcessing::Config());
   generator.StartRecording();
   generator.Process(100);
   generator.SetOutputRate(48000);
@@ -315,7 +324,7 @@
 
 TEST_F(DebugDumpTest, ToggleAec) {
   Config config;
-  DebugDumpGenerator generator(config);
+  DebugDumpGenerator generator(config, AudioProcessing::Config());
   generator.StartRecording();
   generator.Process(100);
 
@@ -330,7 +339,7 @@
 TEST_F(DebugDumpTest, ToggleDelayAgnosticAec) {
   Config config;
   config.Set<DelayAgnostic>(new DelayAgnostic(true));
-  DebugDumpGenerator generator(config);
+  DebugDumpGenerator generator(config, AudioProcessing::Config());
   generator.StartRecording();
   generator.Process(100);
 
@@ -345,7 +354,7 @@
 TEST_F(DebugDumpTest, VerifyRefinedAdaptiveFilterExperimentalString) {
   Config config;
   config.Set<RefinedAdaptiveFilter>(new RefinedAdaptiveFilter(true));
-  DebugDumpGenerator generator(config);
+  DebugDumpGenerator generator(config, AudioProcessing::Config());
   generator.StartRecording();
   generator.Process(100);
   generator.StopRecording();
@@ -370,7 +379,7 @@
   Config config;
   config.Set<RefinedAdaptiveFilter>(new RefinedAdaptiveFilter(true));
   config.Set<EchoCanceller3>(new EchoCanceller3(true));
-  DebugDumpGenerator generator(config);
+  DebugDumpGenerator generator(config, AudioProcessing::Config());
   generator.StartRecording();
   generator.Process(100);
   generator.StopRecording();
@@ -396,7 +405,7 @@
 TEST_F(DebugDumpTest, VerifyCombinedExperimentalStringExclusive) {
   Config config;
   config.Set<RefinedAdaptiveFilter>(new RefinedAdaptiveFilter(true));
-  DebugDumpGenerator generator(config);
+  DebugDumpGenerator generator(config, AudioProcessing::Config());
   generator.StartRecording();
   generator.Process(100);
   generator.StopRecording();
@@ -422,7 +431,7 @@
 TEST_F(DebugDumpTest, VerifyAec3ExperimentalString) {
   Config config;
   config.Set<EchoCanceller3>(new EchoCanceller3(true));
-  DebugDumpGenerator generator(config);
+  DebugDumpGenerator generator(config, AudioProcessing::Config());
   generator.StartRecording();
   generator.Process(100);
   generator.StopRecording();
@@ -445,8 +454,9 @@
 
 TEST_F(DebugDumpTest, VerifyLevelControllerExperimentalString) {
   Config config;
-  config.Set<LevelControl>(new LevelControl(true));
-  DebugDumpGenerator generator(config);
+  AudioProcessing::Config apm_config;
+  apm_config.level_controller.enabled = true;
+  DebugDumpGenerator generator(config, apm_config);
   generator.StartRecording();
   generator.Process(100);
   generator.StopRecording();
@@ -469,7 +479,7 @@
 
 TEST_F(DebugDumpTest, VerifyEmptyExperimentalString) {
   Config config;
-  DebugDumpGenerator generator(config);
+  DebugDumpGenerator generator(config, AudioProcessing::Config());
   generator.StartRecording();
   generator.Process(100);
   generator.StopRecording();
@@ -491,7 +501,7 @@
 
 TEST_F(DebugDumpTest, ToggleAecLevel) {
   Config config;
-  DebugDumpGenerator generator(config);
+  DebugDumpGenerator generator(config, AudioProcessing::Config());
   EchoCancellation* aec = generator.apm()->echo_cancellation();
   EXPECT_EQ(AudioProcessing::kNoError, aec->Enable(true));
   EXPECT_EQ(AudioProcessing::kNoError,
@@ -514,7 +524,7 @@
 #endif
 TEST_F(DebugDumpTest, MAYBE_ToggleAgc) {
   Config config;
-  DebugDumpGenerator generator(config);
+  DebugDumpGenerator generator(config, AudioProcessing::Config());
   generator.StartRecording();
   generator.Process(100);
 
@@ -528,7 +538,7 @@
 
 TEST_F(DebugDumpTest, ToggleNs) {
   Config config;
-  DebugDumpGenerator generator(config);
+  DebugDumpGenerator generator(config, AudioProcessing::Config());
   generator.StartRecording();
   generator.Process(100);
 
@@ -543,7 +553,7 @@
 TEST_F(DebugDumpTest, TransientSuppressionOn) {
   Config config;
   config.Set<ExperimentalNs>(new ExperimentalNs(true));
-  DebugDumpGenerator generator(config);
+  DebugDumpGenerator generator(config, AudioProcessing::Config());
   generator.StartRecording();
   generator.Process(100);
   generator.StopRecording();
diff --git a/webrtc/modules/audio_processing/test/process_test.cc b/webrtc/modules/audio_processing/test/process_test.cc
index ad769ad..f1ac717 100644
--- a/webrtc/modules/audio_processing/test/process_test.cc
+++ b/webrtc/modules/audio_processing/test/process_test.cc
@@ -177,6 +177,7 @@
   int extra_delay_ms = 0;
   int override_delay_ms = 0;
   Config config;
+  AudioProcessing::Config apm_config;
 
   ASSERT_EQ(apm->kNoError, apm->level_estimator()->Enable(true));
   for (int i = 1; i < argc; i++) {
@@ -262,8 +263,7 @@
                         suppression_level)));
 
     } else if (strcmp(argv[i], "--level_control") == 0) {
-      config.Set<LevelControl>(new LevelControl(true));
-
+      apm_config.level_controller.enabled = true;
     } else if (strcmp(argv[i], "--extended_filter") == 0) {
       config.Set<ExtendedFilter>(new ExtendedFilter(true));
 
@@ -452,6 +452,7 @@
       FAIL() << "Unrecognized argument " << argv[i];
     }
   }
+  apm->ApplyConfig(apm_config);
   apm->SetExtraOptions(config);
 
   // If we're reading a protobuf file, ensure a simulation hasn't also