From 6787f232aedd5e529c1825bbb3c2ddd864059d63 Mon Sep 17 00:00:00 2001 From: saza Date: Fri, 11 Oct 2019 19:31:07 +0200 Subject: [PATCH] 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 Reviewed-by: Ivo Creusen Cr-Commit-Position: refs/heads/master@{#29454} --- modules/audio_processing/BUILD.gn | 4 +- .../audio_processing/audio_processing_impl.cc | 22 +---- .../audio_processing/audio_processing_impl.h | 3 - .../audio_processing_performance_unittest.cc | 6 +- .../audio_processing_unittest.cc | 80 ++----------------- .../include/audio_processing.h | 24 ------ .../include/mock_audio_processing.h | 13 --- modules/audio_processing/level_estimator.cc | 29 +++++++ modules/audio_processing/level_estimator.h | 47 +++++++++++ .../audio_processing/level_estimator_impl.cc | 69 ---------------- .../audio_processing/level_estimator_impl.h | 47 ----------- .../level_estimator_unittest.cc | 8 +- .../test/audio_processing_simulator.cc | 8 +- .../audio_processing_configs_fuzzer.cc | 3 +- 14 files changed, 99 insertions(+), 264 deletions(-) create mode 100644 modules/audio_processing/level_estimator.cc create mode 100644 modules/audio_processing/level_estimator.h delete mode 100644 modules/audio_processing/level_estimator_impl.cc delete mode 100644 modules/audio_processing/level_estimator_impl.h diff --git a/modules/audio_processing/BUILD.gn b/modules/audio_processing/BUILD.gn index 4ca918865a..6fa6585c5c 100644 --- a/modules/audio_processing/BUILD.gn +++ b/modules/audio_processing/BUILD.gn @@ -132,8 +132,8 @@ rtc_static_library("audio_processing") { "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 564a9804e8..0582eceb5e 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 AudioProcessingImpl::ApmSubmoduleStates::Update( 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 @@ bool AudioProcessingImpl::ApmSubmoduleStates::Update( 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 @@ bool AudioProcessingImpl::ApmSubmoduleStates::Update( 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 @@ struct AudioProcessingImpl::ApmPublicSubmodules { // 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 level_estimator; std::unique_ptr noise_suppression; std::unique_ptr noise_suppression_proxy; std::unique_ptr gain_control; @@ -294,7 +290,7 @@ struct AudioProcessingImpl::ApmPrivateSubmodules { std::unique_ptr render_pre_processor; std::unique_ptr pre_amplifier; std::unique_ptr capture_analyzer; - std::unique_ptr output_level_estimator; + std::unique_ptr output_level_estimator; std::unique_ptr voice_detector; }; @@ -409,8 +405,6 @@ AudioProcessingImpl::AudioProcessingImpl( static_cast(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 @@ int AudioProcessingImpl::InitializeLocked() { 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 @@ void AudioProcessingImpl::ApplyConfig(const AudioProcessing::Config& config) { 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(); } if (voice_detection_config_changed) { @@ -1541,7 +1533,6 @@ int AudioProcessingImpl::ProcessCaptureStreamLocked() { } // 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 @@ GainControl* AudioProcessingImpl::gain_control() const { 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 @@ bool AudioProcessingImpl::UpdateActiveSubmoduleStates() { 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 5d07fe3930..aa577a09c4 100644 --- a/modules/audio_processing/audio_processing_impl.h +++ b/modules/audio_processing/audio_processing_impl.h @@ -120,7 +120,6 @@ class AudioProcessingImpl : public AudioProcessing { // 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 @@ class AudioProcessingImpl : public AudioProcessing { 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 @@ class AudioProcessingImpl : public AudioProcessing { 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 4e297a50d2..24026f11da 100644 --- a/modules/audio_processing/audio_processing_performance_unittest.cc +++ b/modules/audio_processing/audio_processing_performance_unittest.cc @@ -446,7 +446,6 @@ class CallSimulator : public ::testing::TestWithParam { 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 @@ class CallSimulator : public ::testing::TestWithParam { 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 @@ class CallSimulator : public ::testing::TestWithParam { 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 @@ class CallSimulator : public ::testing::TestWithParam { // 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 @@ class CallSimulator : public ::testing::TestWithParam { 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 2b8abd9294..caa7bab50a 100644 --- a/modules/audio_processing/audio_processing_unittest.cc +++ b/modules/audio_processing/audio_processing_unittest.cc @@ -196,7 +196,6 @@ void EnableAllAPComponents(AudioProcessing* ap) { 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 @@ TEST_F(ApmTest, HighPassFilter) { 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 @@ TEST_F(ApmTest, AllProcessingDisabledByDefault) { 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 @@ TEST_F(ApmTest, SplittingFilter) { 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 @@ TEST_F(ApmTest, SplittingFilter) { // 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 @@ std::unique_ptr CreateApm(bool mobile_aec) { 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 ec2f32b9bf..6fc1057361 100644 --- a/modules/audio_processing/include/audio_processing.h +++ b/modules/audio_processing/include/audio_processing.h @@ -49,7 +49,6 @@ class ProcessingConfig; class EchoDetector; class GainControl; -class LevelEstimator; class NoiseSuppression; class CustomAudioAnalyzer; class CustomProcessing; @@ -685,7 +684,6 @@ class AudioProcessing : public rtc::RefCountInterface { // 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 @@ class ProcessingConfig { 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 c5a1f0925a..a404dca5bb 100644 --- a/modules/audio_processing/include/mock_audio_processing.h +++ b/modules/audio_processing/include/mock_audio_processing.h @@ -43,14 +43,6 @@ class MockGainControl : public GainControl { 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 @@ class MockAudioProcessing : public ::testing::NiceMock { public: MockAudioProcessing() : gain_control_(new ::testing::NiceMock()), - level_estimator_(new ::testing::NiceMock()), noise_suppression_(new ::testing::NiceMock()) {} virtual ~MockAudioProcessing() {} @@ -164,9 +155,6 @@ class MockAudioProcessing : public ::testing::NiceMock { 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 @@ class MockAudioProcessing : public ::testing::NiceMock { private: std::unique_ptr gain_control_; - std::unique_ptr level_estimator_; std::unique_ptr noise_suppression_; }; diff --git a/modules/audio_processing/level_estimator.cc b/modules/audio_processing/level_estimator.cc new file mode 100644 index 0000000000..e70728843a --- /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(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 0000000000..1d8a0712b5 --- /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 e796095170..0000000000 --- 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 -#include - -#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(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 4e482f428c..0000000000 --- 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 - -#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 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 5f72ea52d3..7660b677fd 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 @@ const int kNumFramesToProcess = 1000; 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 5cda89afa1..4a0e007d74 100644 --- a/modules/audio_processing/test/audio_processing_simulator.cc +++ b/modules/audio_processing/test/audio_processing_simulator.cc @@ -455,6 +455,10 @@ void AudioProcessingSimulator::CreateAudioProcessor() { 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 @@ void AudioProcessingSimulator::CreateAudioProcessor() { 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 0dee80e27d..8dd0e29634 100644 --- a/test/fuzzers/audio_processing_configs_fuzzer.cc +++ b/test/fuzzers/audio_processing_configs_fuzzer.cc @@ -142,10 +142,9 @@ std::unique_ptr CreateApm(test::FuzzDataHelper* fuzz_data, 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; }