diff --git a/media/engine/apm_helpers_unittest.cc b/media/engine/apm_helpers_unittest.cc index 70ac0c1c21..464e053dc0 100644 --- a/media/engine/apm_helpers_unittest.cc +++ b/media/engine/apm_helpers_unittest.cc @@ -164,4 +164,11 @@ TEST(ApmHelpersTest, TypingDetectionStatus_EnableDisable) { EXPECT_EQ(VoiceDetection::kVeryLowLikelihood, vd->likelihood()); EXPECT_FALSE(vd->is_enabled()); } + +// TODO(solenberg): Move this test to a better place - added here for the sake +// of duplicating all relevant tests from audio_processing_test.cc. +TEST(ApmHelpersTest, HighPassFilter_DefaultMode) { + TestHelper helper; + EXPECT_FALSE(helper.apm()->high_pass_filter()->is_enabled()); +} } // namespace webrtc diff --git a/modules/audio_processing/audio_processing_impl.cc b/modules/audio_processing/audio_processing_impl.cc index 328c4cb5da..9015319057 100644 --- a/modules/audio_processing/audio_processing_impl.cc +++ b/modules/audio_processing/audio_processing_impl.cc @@ -115,6 +115,29 @@ static const size_t kMaxAllowedValuesOfSamplesPerFrame = 480; // TODO(peah): Decrease this once we properly handle hugely unbalanced // reverse and forward call numbers. static const size_t kMaxNumFramesToBuffer = 100; + +class HighPassFilterImpl : public HighPassFilter { + public: + explicit HighPassFilterImpl(AudioProcessingImpl* apm) : apm_(apm) {} + ~HighPassFilterImpl() override = default; + + // HighPassFilter implementation. + int Enable(bool enable) override { + apm_->MutateConfig([enable](AudioProcessing::Config* config) { + config->high_pass_filter.enabled = enable; + }); + + return AudioProcessing::kNoError; + } + + bool is_enabled() const override { + return apm_->GetConfig().high_pass_filter.enabled; + } + + private: + AudioProcessingImpl* apm_; + RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(HighPassFilterImpl); +}; } // namespace // Throughout webrtc, it's assumed that success is represented by zero. @@ -329,6 +352,7 @@ AudioProcessingImpl::AudioProcessingImpl( render_runtime_settings_(kRuntimeSettingQueueSize), capture_runtime_settings_enqueuer_(&capture_runtime_settings_), render_runtime_settings_enqueuer_(&render_runtime_settings_), + high_pass_filter_impl_(new HighPassFilterImpl(this)), echo_control_factory_(std::move(echo_control_factory)), submodule_states_(!!capture_post_processor, !!render_pre_processor, @@ -1703,6 +1727,10 @@ GainControl* AudioProcessingImpl::gain_control() const { return public_submodules_->gain_control.get(); } +HighPassFilter* AudioProcessingImpl::high_pass_filter() const { + return high_pass_filter_impl_.get(); +} + LevelEstimator* AudioProcessingImpl::level_estimator() const { return public_submodules_->level_estimator.get(); } diff --git a/modules/audio_processing/audio_processing_impl.h b/modules/audio_processing/audio_processing_impl.h index 45b6c5729c..50cb82bf13 100644 --- a/modules/audio_processing/audio_processing_impl.h +++ b/modules/audio_processing/audio_processing_impl.h @@ -118,6 +118,8 @@ class AudioProcessingImpl : public AudioProcessing { // created only once in a single-treaded manner // during APM creation). GainControl* gain_control() const override; + // TODO(peah): Deprecate this API call. + HighPassFilter* high_pass_filter() const override; LevelEstimator* level_estimator() const override; NoiseSuppression* noise_suppression() const override; VoiceDetection* voice_detection() const override; @@ -162,6 +164,9 @@ class AudioProcessingImpl : public AudioProcessing { RuntimeSettingEnqueuer capture_runtime_settings_enqueuer_; RuntimeSettingEnqueuer render_runtime_settings_enqueuer_; + // Submodule interface implementations. + std::unique_ptr high_pass_filter_impl_; + // EchoControl factory. std::unique_ptr echo_control_factory_; diff --git a/modules/audio_processing/audio_processing_unittest.cc b/modules/audio_processing/audio_processing_unittest.cc index 18e669f7f8..3f0decc957 100644 --- a/modules/audio_processing/audio_processing_unittest.cc +++ b/modules/audio_processing/audio_processing_unittest.cc @@ -1278,6 +1278,7 @@ TEST_F(ApmTest, AllProcessingDisabledByDefault) { EXPECT_FALSE(config.echo_canceller.enabled); EXPECT_FALSE(config.high_pass_filter.enabled); EXPECT_FALSE(apm_->gain_control()->is_enabled()); + EXPECT_FALSE(apm_->high_pass_filter()->is_enabled()); EXPECT_FALSE(apm_->level_estimator()->is_enabled()); EXPECT_FALSE(apm_->noise_suppression()->is_enabled()); EXPECT_FALSE(apm_->voice_detection()->is_enabled()); diff --git a/modules/audio_processing/include/audio_processing.h b/modules/audio_processing/include/audio_processing.h index e428516567..8af0cb23d5 100644 --- a/modules/audio_processing/include/audio_processing.h +++ b/modules/audio_processing/include/audio_processing.h @@ -49,6 +49,7 @@ class ProcessingConfig; class EchoDetector; class GainControl; +class HighPassFilter; class LevelEstimator; class NoiseSuppression; class CustomAudioAnalyzer; @@ -597,6 +598,8 @@ 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; + // TODO(peah): Deprecate this API call. + virtual HighPassFilter* high_pass_filter() const = 0; virtual LevelEstimator* level_estimator() const = 0; virtual NoiseSuppression* noise_suppression() const = 0; virtual VoiceDetection* voice_detection() const = 0; @@ -786,6 +789,17 @@ class ProcessingConfig { StreamConfig streams[StreamName::kNumStreamNames]; }; +// TODO(peah): Remove this interface. +// A filtering component which removes DC offset and low-frequency noise. +// Recommended to be enabled on the client-side. +class HighPassFilter { + public: + virtual int Enable(bool enable) = 0; + virtual bool is_enabled() const = 0; + + virtual ~HighPassFilter() {} +}; + // An estimation component used to retrieve level metrics. class LevelEstimator { public: diff --git a/modules/audio_processing/include/mock_audio_processing.h b/modules/audio_processing/include/mock_audio_processing.h index 767af0a7b0..4a1fe626bd 100644 --- a/modules/audio_processing/include/mock_audio_processing.h +++ b/modules/audio_processing/include/mock_audio_processing.h @@ -42,6 +42,13 @@ class MockGainControl : public GainControl { MOCK_CONST_METHOD0(stream_is_saturated, bool()); }; +class MockHighPassFilter : public HighPassFilter { + public: + virtual ~MockHighPassFilter() {} + MOCK_METHOD1(Enable, int(bool enable)); + MOCK_CONST_METHOD0(is_enabled, bool()); +}; + class MockLevelEstimator : public LevelEstimator { public: virtual ~MockLevelEstimator() {} @@ -107,6 +114,7 @@ class MockAudioProcessing : public testing::NiceMock { public: MockAudioProcessing() : gain_control_(new testing::NiceMock()), + high_pass_filter_(new testing::NiceMock()), level_estimator_(new testing::NiceMock()), noise_suppression_(new testing::NiceMock()), voice_detection_(new testing::NiceMock()) {} @@ -175,6 +183,9 @@ class MockAudioProcessing : public testing::NiceMock { MOCK_CONST_METHOD0(GetStatistics, AudioProcessingStatistics()); MOCK_CONST_METHOD1(GetStatistics, AudioProcessingStats(bool)); virtual MockGainControl* gain_control() const { return gain_control_.get(); } + virtual MockHighPassFilter* high_pass_filter() const { + return high_pass_filter_.get(); + } virtual MockLevelEstimator* level_estimator() const { return level_estimator_.get(); } @@ -189,6 +200,7 @@ class MockAudioProcessing : public testing::NiceMock { private: std::unique_ptr gain_control_; + std::unique_ptr high_pass_filter_; std::unique_ptr level_estimator_; std::unique_ptr noise_suppression_; std::unique_ptr voice_detection_;