Remove AudioProcessing::level_estimator() getter

The new configuration path is via AudioProcessing::ApplyConfig and
AudioProcessing::GetStatistics.

Bug: webrtc:9878
Change-Id: Ic912d67455fcef4895566edb8fef62baf62d7cfe
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/156440
Commit-Queue: Sam Zackrisson <saza@webrtc.org>
Reviewed-by: Ivo Creusen <ivoc@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#29454}
diff --git a/modules/audio_processing/BUILD.gn b/modules/audio_processing/BUILD.gn
index 4ca9188..6fa6585 100644
--- a/modules/audio_processing/BUILD.gn
+++ b/modules/audio_processing/BUILD.gn
@@ -132,8 +132,8 @@
     "gain_controller2.h",
     "include/aec_dump.cc",
     "include/aec_dump.h",
-    "level_estimator_impl.cc",
-    "level_estimator_impl.h",
+    "level_estimator.cc",
+    "level_estimator.h",
     "noise_suppression_impl.cc",
     "noise_suppression_impl.h",
     "render_queue_item_verifier.h",
diff --git a/modules/audio_processing/audio_processing_impl.cc b/modules/audio_processing/audio_processing_impl.cc
index 564a980..0582ece 100644
--- a/modules/audio_processing/audio_processing_impl.cc
+++ b/modules/audio_processing/audio_processing_impl.cc
@@ -34,7 +34,7 @@
 #include "modules/audio_processing/gain_controller2.h"
 #include "modules/audio_processing/high_pass_filter.h"
 #include "modules/audio_processing/include/audio_frame_view.h"
-#include "modules/audio_processing/level_estimator_impl.h"
+#include "modules/audio_processing/level_estimator.h"
 #include "modules/audio_processing/logging/apm_data_dumper.h"
 #include "modules/audio_processing/noise_suppression_impl.h"
 #include "modules/audio_processing/noise_suppression_proxy.h"
@@ -166,7 +166,6 @@
     bool pre_amplifier_enabled,
     bool echo_controller_enabled,
     bool voice_detector_enabled,
-    bool level_estimator_enabled,
     bool transient_suppressor_enabled) {
   bool changed = false;
   changed |= (high_pass_filter_enabled != high_pass_filter_enabled_);
@@ -181,7 +180,6 @@
   changed |= (gain_controller2_enabled != gain_controller2_enabled_);
   changed |= (pre_amplifier_enabled_ != pre_amplifier_enabled);
   changed |= (echo_controller_enabled != echo_controller_enabled_);
-  changed |= (level_estimator_enabled != level_estimator_enabled_);
   changed |= (voice_detector_enabled != voice_detector_enabled_);
   changed |= (transient_suppressor_enabled != transient_suppressor_enabled_);
   if (changed) {
@@ -194,7 +192,6 @@
     gain_controller2_enabled_ = gain_controller2_enabled;
     pre_amplifier_enabled_ = pre_amplifier_enabled;
     echo_controller_enabled_ = echo_controller_enabled;
-    level_estimator_enabled_ = level_estimator_enabled;
     voice_detector_enabled_ = voice_detector_enabled;
     transient_suppressor_enabled_ = transient_suppressor_enabled;
   }
@@ -261,7 +258,6 @@
   // Accessed externally of APM without any lock acquired.
   // TODO(bugs.webrtc.org/9947): Move these submodules into private_submodules_
   // when their pointer-to-submodule API functions are gone.
-  std::unique_ptr<LevelEstimatorImpl> level_estimator;
   std::unique_ptr<NoiseSuppressionImpl> noise_suppression;
   std::unique_ptr<NoiseSuppressionProxy> noise_suppression_proxy;
   std::unique_ptr<GainControlImpl> gain_control;
@@ -294,7 +290,7 @@
   std::unique_ptr<CustomProcessing> render_pre_processor;
   std::unique_ptr<GainApplier> pre_amplifier;
   std::unique_ptr<CustomAudioAnalyzer> capture_analyzer;
-  std::unique_ptr<LevelEstimatorImpl> output_level_estimator;
+  std::unique_ptr<LevelEstimator> output_level_estimator;
   std::unique_ptr<VoiceDetection> voice_detector;
 };
 
@@ -409,8 +405,6 @@
       static_cast<bool>(echo_control_factory_);
 
   public_submodules_->gain_control.reset(new GainControlImpl());
-  public_submodules_->level_estimator.reset(
-      new LevelEstimatorImpl(&crit_capture_));
   public_submodules_->noise_suppression.reset(
       new NoiseSuppressionImpl(&crit_capture_));
   public_submodules_->noise_suppression_proxy.reset(new NoiseSuppressionProxy(
@@ -569,7 +563,6 @@
   public_submodules_->noise_suppression->Initialize(num_proc_channels(),
                                                     proc_sample_rate_hz());
   InitializeVoiceDetector();
-  public_submodules_->level_estimator->Initialize();
   InitializeResidualEchoDetector();
   InitializeEchoController();
   InitializeGainController2();
@@ -751,9 +744,8 @@
 
   if (config_.level_estimation.enabled &&
       !private_submodules_->output_level_estimator) {
-    private_submodules_->output_level_estimator.reset(
-        new LevelEstimatorImpl(&crit_capture_));
-    private_submodules_->output_level_estimator->Enable(true);
+    private_submodules_->output_level_estimator =
+        std::make_unique<LevelEstimator>();
   }
 
   if (voice_detection_config_changed) {
@@ -1541,7 +1533,6 @@
   }
 
   // The level estimator operates on the recombined data.
-  public_submodules_->level_estimator->ProcessStream(*capture_buffer);
   if (config_.level_estimation.enabled) {
     private_submodules_->output_level_estimator->ProcessStream(*capture_buffer);
     capture_.stats.output_rms_dbfs =
@@ -1841,10 +1832,6 @@
   return public_submodules_->gain_control_config_proxy.get();
 }
 
-LevelEstimator* AudioProcessingImpl::level_estimator() const {
-  return public_submodules_->level_estimator.get();
-}
-
 NoiseSuppression* AudioProcessingImpl::noise_suppression() const {
   return public_submodules_->noise_suppression_proxy.get();
 }
@@ -1874,7 +1861,6 @@
       config_.gain_controller2.enabled, config_.pre_amplifier.enabled,
       capture_nonlocked_.echo_controller_enabled,
       config_.voice_detection.enabled,
-      public_submodules_->level_estimator->is_enabled(),
       capture_.transient_suppressor_enabled);
 }
 
diff --git a/modules/audio_processing/audio_processing_impl.h b/modules/audio_processing/audio_processing_impl.h
index 5d07fe3..aa577a0 100644
--- a/modules/audio_processing/audio_processing_impl.h
+++ b/modules/audio_processing/audio_processing_impl.h
@@ -120,7 +120,6 @@
   // created only once in a single-treaded manner
   // during APM creation).
   GainControl* gain_control() const override;
-  LevelEstimator* level_estimator() const override;
   NoiseSuppression* noise_suppression() const override;
 
   // TODO(peah): Remove MutateConfig once the new API allows that.
@@ -182,7 +181,6 @@
                 bool pre_amplifier_enabled,
                 bool echo_controller_enabled,
                 bool voice_detector_enabled,
-                bool level_estimator_enabled,
                 bool transient_suppressor_enabled);
     bool CaptureMultiBandSubModulesActive() const;
     bool CaptureMultiBandProcessingPresent() const;
@@ -207,7 +205,6 @@
     bool gain_controller2_enabled_ = false;
     bool pre_amplifier_enabled_ = false;
     bool echo_controller_enabled_ = false;
-    bool level_estimator_enabled_ = false;
     bool voice_detector_enabled_ = false;
     bool transient_suppressor_enabled_ = false;
     bool first_update_ = true;
diff --git a/modules/audio_processing/audio_processing_performance_unittest.cc b/modules/audio_processing/audio_processing_performance_unittest.cc
index 4e297a5..24026f1 100644
--- a/modules/audio_processing/audio_processing_performance_unittest.cc
+++ b/modules/audio_processing/audio_processing_performance_unittest.cc
@@ -446,7 +446,6 @@
   void SetUp() override {
     // Lambda function for setting the default APM runtime settings for desktop.
     auto set_default_desktop_apm_runtime_settings = [](AudioProcessing* apm) {
-      ASSERT_EQ(apm->kNoError, apm->level_estimator()->Enable(true));
       ASSERT_EQ(apm->kNoError, apm->gain_control()->Enable(true));
       ASSERT_EQ(apm->kNoError,
                 apm->gain_control()->set_mode(GainControl::kAdaptiveDigital));
@@ -455,13 +454,13 @@
       AudioProcessing::Config apm_config = apm->GetConfig();
       apm_config.echo_canceller.enabled = true;
       apm_config.echo_canceller.mobile_mode = false;
+      apm_config.level_estimation.enabled = true;
       apm_config.voice_detection.enabled = true;
       apm->ApplyConfig(apm_config);
     };
 
     // Lambda function for setting the default APM runtime settings for mobile.
     auto set_default_mobile_apm_runtime_settings = [](AudioProcessing* apm) {
-      ASSERT_EQ(apm->kNoError, apm->level_estimator()->Enable(true));
       ASSERT_EQ(apm->kNoError, apm->gain_control()->Enable(true));
       ASSERT_EQ(apm->kNoError,
                 apm->gain_control()->set_mode(GainControl::kAdaptiveDigital));
@@ -470,6 +469,7 @@
       AudioProcessing::Config apm_config = apm->GetConfig();
       apm_config.echo_canceller.enabled = true;
       apm_config.echo_canceller.mobile_mode = true;
+      apm_config.level_estimation.enabled = true;
       apm_config.voice_detection.enabled = true;
       apm->ApplyConfig(apm_config);
     };
@@ -477,7 +477,6 @@
     // Lambda function for turning off all of the APM runtime settings
     // submodules.
     auto turn_off_default_apm_runtime_settings = [](AudioProcessing* apm) {
-      ASSERT_EQ(apm->kNoError, apm->level_estimator()->Enable(false));
       ASSERT_EQ(apm->kNoError, apm->gain_control()->Enable(false));
       ASSERT_EQ(apm->kNoError,
                 apm->gain_control()->set_mode(GainControl::kAdaptiveDigital));
@@ -485,6 +484,7 @@
       ASSERT_EQ(apm->kNoError, apm->noise_suppression()->Enable(false));
       AudioProcessing::Config apm_config = apm->GetConfig();
       apm_config.echo_canceller.enabled = false;
+      apm_config.level_estimation.enabled = false;
       apm_config.voice_detection.enabled = false;
       apm->ApplyConfig(apm_config);
     };
diff --git a/modules/audio_processing/audio_processing_unittest.cc b/modules/audio_processing/audio_processing_unittest.cc
index 2b8abd9..caa7bab 100644
--- a/modules/audio_processing/audio_processing_unittest.cc
+++ b/modules/audio_processing/audio_processing_unittest.cc
@@ -196,7 +196,6 @@
   apm_config.voice_detection.enabled = true;
   ap->ApplyConfig(apm_config);
 
-  EXPECT_NOERR(ap->level_estimator()->Enable(true));
   EXPECT_NOERR(ap->noise_suppression()->Enable(true));
 }
 
@@ -1048,71 +1047,6 @@
   apm_->ApplyConfig(apm_config);
 }
 
-TEST_F(ApmTest, LevelEstimator) {
-  // Turn level estimator on/off
-  EXPECT_EQ(apm_->kNoError, apm_->level_estimator()->Enable(false));
-  EXPECT_FALSE(apm_->level_estimator()->is_enabled());
-
-  EXPECT_EQ(apm_->kNotEnabledError, apm_->level_estimator()->RMS());
-
-  EXPECT_EQ(apm_->kNoError, apm_->level_estimator()->Enable(true));
-  EXPECT_TRUE(apm_->level_estimator()->is_enabled());
-
-  // Run this test in wideband; in super-wb, the splitting filter distorts the
-  // audio enough to cause deviation from the expectation for small values.
-  frame_->samples_per_channel_ = 160;
-  frame_->num_channels_ = 2;
-  frame_->sample_rate_hz_ = 16000;
-
-  // Min value if no frames have been processed.
-  EXPECT_EQ(127, apm_->level_estimator()->RMS());
-
-  // Min value on zero frames.
-  SetFrameTo(frame_, 0);
-  EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
-  EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
-  EXPECT_EQ(127, apm_->level_estimator()->RMS());
-
-  // Try a few RMS values.
-  // (These also test that the value resets after retrieving it.)
-  SetFrameTo(frame_, 32767);
-  EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
-  EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
-  EXPECT_EQ(0, apm_->level_estimator()->RMS());
-
-  SetFrameTo(frame_, 30000);
-  EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
-  EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
-  EXPECT_EQ(1, apm_->level_estimator()->RMS());
-
-  SetFrameTo(frame_, 10000);
-  EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
-  EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
-  EXPECT_EQ(10, apm_->level_estimator()->RMS());
-
-  SetFrameTo(frame_, 10);
-  EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
-  EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
-  EXPECT_EQ(70, apm_->level_estimator()->RMS());
-
-  // Verify reset after enable/disable.
-  SetFrameTo(frame_, 32767);
-  EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
-  EXPECT_EQ(apm_->kNoError, apm_->level_estimator()->Enable(false));
-  EXPECT_EQ(apm_->kNoError, apm_->level_estimator()->Enable(true));
-  SetFrameTo(frame_, 1);
-  EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
-  EXPECT_EQ(90, apm_->level_estimator()->RMS());
-
-  // Verify reset after initialize.
-  SetFrameTo(frame_, 32767);
-  EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
-  EXPECT_EQ(apm_->kNoError, apm_->Initialize());
-  SetFrameTo(frame_, 1);
-  EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
-  EXPECT_EQ(90, apm_->level_estimator()->RMS());
-}
-
 TEST_F(ApmTest, AllProcessingDisabledByDefault) {
   AudioProcessing::Config config = apm_->GetConfig();
   EXPECT_FALSE(config.echo_canceller.enabled);
@@ -1120,7 +1054,6 @@
   EXPECT_FALSE(config.level_estimation.enabled);
   EXPECT_FALSE(config.voice_detection.enabled);
   EXPECT_FALSE(apm_->gain_control()->is_enabled());
-  EXPECT_FALSE(apm_->level_estimator()->is_enabled());
   EXPECT_FALSE(apm_->noise_suppression()->is_enabled());
 }
 
@@ -1215,18 +1148,20 @@
   EXPECT_TRUE(FrameDataAreEqual(*frame_, frame_copy));
 
   // 2. Only the level estimator is enabled...
+  auto apm_config = apm_->GetConfig();
   SetFrameTo(frame_, 1000);
   frame_copy.CopyFrom(*frame_);
-  EXPECT_EQ(apm_->kNoError, apm_->level_estimator()->Enable(true));
+  apm_config.level_estimation.enabled = true;
+  apm_->ApplyConfig(apm_config);
   EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
   EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
   EXPECT_TRUE(FrameDataAreEqual(*frame_, frame_copy));
-  EXPECT_EQ(apm_->kNoError, apm_->level_estimator()->Enable(false));
+  apm_config.level_estimation.enabled = false;
+  apm_->ApplyConfig(apm_config);
 
   // 3. Only GetStatistics-reporting VAD is enabled...
   SetFrameTo(frame_, 1000);
   frame_copy.CopyFrom(*frame_);
-  auto apm_config = apm_->GetConfig();
   apm_config.voice_detection.enabled = true;
   apm_->ApplyConfig(apm_config);
   EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
@@ -1238,14 +1173,14 @@
   // 4. Both the VAD and the level estimator are enabled...
   SetFrameTo(frame_, 1000);
   frame_copy.CopyFrom(*frame_);
-  EXPECT_EQ(apm_->kNoError, apm_->level_estimator()->Enable(true));
   apm_config.voice_detection.enabled = true;
+  apm_config.level_estimation.enabled = true;
   apm_->ApplyConfig(apm_config);
   EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
   EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
   EXPECT_TRUE(FrameDataAreEqual(*frame_, frame_copy));
-  EXPECT_EQ(apm_->kNoError, apm_->level_estimator()->Enable(false));
   apm_config.voice_detection.enabled = false;
+  apm_config.level_estimation.enabled = false;
   apm_->ApplyConfig(apm_config);
 
   // Check the test is valid. We should have distortion from the filter
@@ -2491,7 +2426,6 @@
   apm_config.echo_canceller.mobile_mode = mobile_aec;
   apm->ApplyConfig(apm_config);
   EXPECT_EQ(apm->gain_control()->Enable(false), 0);
-  EXPECT_EQ(apm->level_estimator()->Enable(false), 0);
   EXPECT_EQ(apm->noise_suppression()->Enable(false), 0);
   return apm;
 }
diff --git a/modules/audio_processing/include/audio_processing.h b/modules/audio_processing/include/audio_processing.h
index ec2f32b..6fc1057 100644
--- a/modules/audio_processing/include/audio_processing.h
+++ b/modules/audio_processing/include/audio_processing.h
@@ -49,7 +49,6 @@
 
 class EchoDetector;
 class GainControl;
-class LevelEstimator;
 class NoiseSuppression;
 class CustomAudioAnalyzer;
 class CustomProcessing;
@@ -685,7 +684,6 @@
   // NULL. The pointers will be valid for the lifetime of the APM instance.
   // The memory for these objects is entirely managed internally.
   virtual GainControl* gain_control() const = 0;
-  virtual LevelEstimator* level_estimator() const = 0;
   virtual NoiseSuppression* noise_suppression() const = 0;
 
   // Returns the last applied configuration.
@@ -874,28 +872,6 @@
   StreamConfig streams[StreamName::kNumStreamNames];
 };
 
-// An estimation component used to retrieve level metrics.
-class LevelEstimator {
- public:
-  virtual int Enable(bool enable) = 0;
-  virtual bool is_enabled() const = 0;
-
-  // Returns the root mean square (RMS) level in dBFs (decibels from digital
-  // full-scale), or alternately dBov. It is computed over all primary stream
-  // frames since the last call to RMS(). The returned value is positive but
-  // should be interpreted as negative. It is constrained to [0, 127].
-  //
-  // The computation follows: https://tools.ietf.org/html/rfc6465
-  // with the intent that it can provide the RTP audio level indication.
-  //
-  // Frames passed to ProcessStream() with an |_energy| of zero are considered
-  // to have been muted. The RMS of the frame will be interpreted as -127.
-  virtual int RMS() = 0;
-
- protected:
-  virtual ~LevelEstimator() {}
-};
-
 // The noise suppression (NS) component attempts to remove noise while
 // retaining speech. Recommended to be enabled on the client-side.
 //
diff --git a/modules/audio_processing/include/mock_audio_processing.h b/modules/audio_processing/include/mock_audio_processing.h
index c5a1f09..a404dca 100644
--- a/modules/audio_processing/include/mock_audio_processing.h
+++ b/modules/audio_processing/include/mock_audio_processing.h
@@ -43,14 +43,6 @@
   MOCK_CONST_METHOD0(stream_is_saturated, bool());
 };
 
-class MockLevelEstimator : public LevelEstimator {
- public:
-  virtual ~MockLevelEstimator() {}
-  MOCK_METHOD1(Enable, int(bool enable));
-  MOCK_CONST_METHOD0(is_enabled, bool());
-  MOCK_METHOD0(RMS, int());
-};
-
 class MockNoiseSuppression : public NoiseSuppression {
  public:
   virtual ~MockNoiseSuppression() {}
@@ -96,7 +88,6 @@
  public:
   MockAudioProcessing()
       : gain_control_(new ::testing::NiceMock<MockGainControl>()),
-        level_estimator_(new ::testing::NiceMock<MockLevelEstimator>()),
         noise_suppression_(new ::testing::NiceMock<MockNoiseSuppression>()) {}
 
   virtual ~MockAudioProcessing() {}
@@ -164,9 +155,6 @@
   MOCK_METHOD0(UpdateHistogramsOnCallEnd, void());
   MOCK_CONST_METHOD1(GetStatistics, AudioProcessingStats(bool));
   virtual MockGainControl* gain_control() const { return gain_control_.get(); }
-  virtual MockLevelEstimator* level_estimator() const {
-    return level_estimator_.get();
-  }
   virtual MockNoiseSuppression* noise_suppression() const {
     return noise_suppression_.get();
   }
@@ -175,7 +163,6 @@
 
  private:
   std::unique_ptr<MockGainControl> gain_control_;
-  std::unique_ptr<MockLevelEstimator> level_estimator_;
   std::unique_ptr<MockNoiseSuppression> noise_suppression_;
 };
 
diff --git a/modules/audio_processing/level_estimator.cc b/modules/audio_processing/level_estimator.cc
new file mode 100644
index 0000000..e707288
--- /dev/null
+++ b/modules/audio_processing/level_estimator.cc
@@ -0,0 +1,29 @@
+/*
+ *  Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_processing/level_estimator.h"
+
+#include "api/array_view.h"
+
+namespace webrtc {
+
+LevelEstimator::LevelEstimator() {
+  rms_.Reset();
+}
+
+LevelEstimator::~LevelEstimator() = default;
+
+void LevelEstimator::ProcessStream(const AudioBuffer& audio) {
+  for (size_t i = 0; i < audio.num_channels(); i++) {
+    rms_.Analyze(rtc::ArrayView<const float>(audio.channels_const()[i],
+                                             audio.num_frames()));
+  }
+}
+}  // namespace webrtc
diff --git a/modules/audio_processing/level_estimator.h b/modules/audio_processing/level_estimator.h
new file mode 100644
index 0000000..1d8a071
--- /dev/null
+++ b/modules/audio_processing/level_estimator.h
@@ -0,0 +1,47 @@
+/*
+ *  Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_PROCESSING_LEVEL_ESTIMATOR_H_
+#define MODULES_AUDIO_PROCESSING_LEVEL_ESTIMATOR_H_
+
+#include "modules/audio_processing/audio_buffer.h"
+#include "modules/audio_processing/rms_level.h"
+
+namespace webrtc {
+
+// An estimation component used to retrieve level metrics.
+class LevelEstimator {
+ public:
+  LevelEstimator();
+  ~LevelEstimator();
+
+  LevelEstimator(LevelEstimator&) = delete;
+  LevelEstimator& operator=(LevelEstimator&) = delete;
+
+  void ProcessStream(const AudioBuffer& audio);
+
+  // Returns the root mean square (RMS) level in dBFs (decibels from digital
+  // full-scale), or alternately dBov. It is computed over all primary stream
+  // frames since the last call to RMS(). The returned value is positive but
+  // should be interpreted as negative. It is constrained to [0, 127].
+  //
+  // The computation follows: https://tools.ietf.org/html/rfc6465
+  // with the intent that it can provide the RTP audio level indication.
+  //
+  // Frames passed to ProcessStream() with an |_energy| of zero are considered
+  // to have been muted. The RMS of the frame will be interpreted as -127.
+  int RMS() { return rms_.Average(); }
+
+ private:
+  RmsLevel rms_;
+};
+}  // namespace webrtc
+
+#endif  // MODULES_AUDIO_PROCESSING_LEVEL_ESTIMATOR_H_
diff --git a/modules/audio_processing/level_estimator_impl.cc b/modules/audio_processing/level_estimator_impl.cc
deleted file mode 100644
index e796095..0000000
--- a/modules/audio_processing/level_estimator_impl.cc
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
- *
- *  Use of this source code is governed by a BSD-style license
- *  that can be found in the LICENSE file in the root of the source
- *  tree. An additional intellectual property rights grant can be found
- *  in the file PATENTS.  All contributing project authors may
- *  be found in the AUTHORS file in the root of the source tree.
- */
-
-#include "modules/audio_processing/level_estimator_impl.h"
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include "api/array_view.h"
-#include "modules/audio_processing/audio_buffer.h"
-#include "modules/audio_processing/rms_level.h"
-#include "rtc_base/checks.h"
-
-namespace webrtc {
-
-LevelEstimatorImpl::LevelEstimatorImpl(rtc::CriticalSection* crit)
-    : crit_(crit), rms_(new RmsLevel()) {
-  RTC_DCHECK(crit);
-}
-
-LevelEstimatorImpl::~LevelEstimatorImpl() {}
-
-void LevelEstimatorImpl::Initialize() {
-  rtc::CritScope cs(crit_);
-  rms_->Reset();
-}
-
-void LevelEstimatorImpl::ProcessStream(const AudioBuffer& audio) {
-  rtc::CritScope cs(crit_);
-  if (!enabled_) {
-    return;
-  }
-
-  for (size_t i = 0; i < audio.num_channels(); i++) {
-    rms_->Analyze(rtc::ArrayView<const float>(audio.channels_const()[i],
-                                              audio.num_frames()));
-  }
-}
-
-int LevelEstimatorImpl::Enable(bool enable) {
-  rtc::CritScope cs(crit_);
-  if (enable && !enabled_) {
-    rms_->Reset();
-  }
-  enabled_ = enable;
-  return AudioProcessing::kNoError;
-}
-
-bool LevelEstimatorImpl::is_enabled() const {
-  rtc::CritScope cs(crit_);
-  return enabled_;
-}
-
-int LevelEstimatorImpl::RMS() {
-  rtc::CritScope cs(crit_);
-  if (!enabled_) {
-    return AudioProcessing::kNotEnabledError;
-  }
-
-  return rms_->Average();
-}
-}  // namespace webrtc
diff --git a/modules/audio_processing/level_estimator_impl.h b/modules/audio_processing/level_estimator_impl.h
deleted file mode 100644
index 4e482f4..0000000
--- a/modules/audio_processing/level_estimator_impl.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
- *
- *  Use of this source code is governed by a BSD-style license
- *  that can be found in the LICENSE file in the root of the source
- *  tree. An additional intellectual property rights grant can be found
- *  in the file PATENTS.  All contributing project authors may
- *  be found in the AUTHORS file in the root of the source tree.
- */
-
-#ifndef MODULES_AUDIO_PROCESSING_LEVEL_ESTIMATOR_IMPL_H_
-#define MODULES_AUDIO_PROCESSING_LEVEL_ESTIMATOR_IMPL_H_
-
-#include <memory>
-
-#include "modules/audio_processing/include/audio_processing.h"
-#include "rtc_base/constructor_magic.h"
-#include "rtc_base/critical_section.h"
-
-namespace webrtc {
-
-class AudioBuffer;
-class RmsLevel;
-
-class LevelEstimatorImpl : public LevelEstimator {
- public:
-  explicit LevelEstimatorImpl(rtc::CriticalSection* crit);
-  ~LevelEstimatorImpl() override;
-
-  // TODO(peah): Fold into ctor, once public API is removed.
-  void Initialize();
-  void ProcessStream(const AudioBuffer& audio);
-
-  // LevelEstimator implementation.
-  int Enable(bool enable) override;
-  bool is_enabled() const override;
-  int RMS() override;
-
- private:
-  rtc::CriticalSection* const crit_ = nullptr;
-  bool enabled_ RTC_GUARDED_BY(crit_) = false;
-  std::unique_ptr<RmsLevel> rms_ RTC_GUARDED_BY(crit_);
-  RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(LevelEstimatorImpl);
-};
-}  // namespace webrtc
-
-#endif  // MODULES_AUDIO_PROCESSING_LEVEL_ESTIMATOR_IMPL_H_
diff --git a/modules/audio_processing/level_estimator_unittest.cc b/modules/audio_processing/level_estimator_unittest.cc
index 5f72ea5..7660b67 100644
--- a/modules/audio_processing/level_estimator_unittest.cc
+++ b/modules/audio_processing/level_estimator_unittest.cc
@@ -11,7 +11,7 @@
 
 #include "api/array_view.h"
 #include "modules/audio_processing/audio_buffer.h"
-#include "modules/audio_processing/level_estimator_impl.h"
+#include "modules/audio_processing/level_estimator.h"
 #include "modules/audio_processing/test/audio_buffer_tools.h"
 #include "modules/audio_processing/test/bitexactness_tools.h"
 #include "test/gtest.h"
@@ -26,11 +26,7 @@
 void RunBitexactnessTest(int sample_rate_hz,
                          size_t num_channels,
                          int rms_reference) {
-  rtc::CriticalSection crit_capture;
-  LevelEstimatorImpl level_estimator(&crit_capture);
-  level_estimator.Initialize();
-  level_estimator.Enable(true);
-
+  LevelEstimator level_estimator;
   int samples_per_channel = rtc::CheckedDivExact(sample_rate_hz, 100);
   StreamConfig capture_config(sample_rate_hz, num_channels, false);
   AudioBuffer capture_buffer(
diff --git a/modules/audio_processing/test/audio_processing_simulator.cc b/modules/audio_processing/test/audio_processing_simulator.cc
index 5cda89a..4a0e007 100644
--- a/modules/audio_processing/test/audio_processing_simulator.cc
+++ b/modules/audio_processing/test/audio_processing_simulator.cc
@@ -455,6 +455,10 @@
     apm_config.high_pass_filter.enabled = *settings_.use_hpf;
   }
 
+  if (settings_.use_le) {
+    apm_config.level_estimation.enabled = *settings_.use_le;
+  }
+
   if (settings_.use_vad) {
     apm_config.voice_detection.enabled = *settings_.use_vad;
   }
@@ -502,10 +506,6 @@
     RTC_CHECK_EQ(AudioProcessing::kNoError,
                  ap_->noise_suppression()->Enable(*settings_.use_ns));
   }
-  if (settings_.use_le) {
-    RTC_CHECK_EQ(AudioProcessing::kNoError,
-                 ap_->level_estimator()->Enable(*settings_.use_le));
-  }
   if (settings_.use_agc_limiter) {
     RTC_CHECK_EQ(AudioProcessing::kNoError, ap_->gain_control()->enable_limiter(
                                                 *settings_.use_agc_limiter));
diff --git a/test/fuzzers/audio_processing_configs_fuzzer.cc b/test/fuzzers/audio_processing_configs_fuzzer.cc
index 0dee80e..8dd0e29 100644
--- a/test/fuzzers/audio_processing_configs_fuzzer.cc
+++ b/test/fuzzers/audio_processing_configs_fuzzer.cc
@@ -142,10 +142,9 @@
       use_agc2_adaptive_digital_saturation_protector;
   apm_config.noise_suppression.enabled = use_ns;
   apm_config.voice_detection.enabled = use_vad;
+  apm_config.level_estimation.enabled = use_le;
   apm->ApplyConfig(apm_config);
 
-  apm->level_estimator()->Enable(use_le);
-
   return apm;
 }