From d8579e0133fdc7afdd7fb10520f195646cee5754 Mon Sep 17 00:00:00 2001 From: Gustaf Ullberg Date: Wed, 11 Oct 2017 16:29:02 +0200 Subject: [PATCH] EchoControl factory injectable in AudioProcessing. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This CL enables a factory method creating acoustic echo cancellers that inherit EchoControl to be injected into the audio processing module. AudioProcessing will call the factory method to create an instance of the EchoControl subclass when needed. In the event of sample rate changes, AudioProcessing will recreate the object using the factory method. Bug: webrtc:8346 Change-Id: I0c508b4d4cdb35569864cefaa0e3aea2555cc9b9 Reviewed-on: https://webrtc-review.googlesource.com/7742 Commit-Queue: Gustaf Ullberg Reviewed-by: Per Ã…hgren Cr-Commit-Position: refs/heads/master@{#20251} --- modules/audio_processing/BUILD.gn | 1 + .../audio_processing/audio_processing_impl.cc | 34 +++++++++++++++---- .../audio_processing/audio_processing_impl.h | 4 +++ .../audio_processing_unittest.cc | 11 +++--- .../include/audio_processing.h | 7 ++++ 5 files changed, 46 insertions(+), 11 deletions(-) diff --git a/modules/audio_processing/BUILD.gn b/modules/audio_processing/BUILD.gn index dd2ded6945..027e1ed719 100644 --- a/modules/audio_processing/BUILD.gn +++ b/modules/audio_processing/BUILD.gn @@ -242,6 +242,7 @@ rtc_static_library("audio_processing") { "../../audio/utility:audio_frame_operations", "../../rtc_base:gtest_prod", "../../rtc_base:protobuf_utils", + "../../rtc_base:rtc_base", "../audio_coding:isac", ] public_deps = [ diff --git a/modules/audio_processing/audio_processing_impl.cc b/modules/audio_processing/audio_processing_impl.cc index 68a24d27c9..c1010669b0 100644 --- a/modules/audio_processing/audio_processing_impl.cc +++ b/modules/audio_processing/audio_processing_impl.cc @@ -309,24 +309,35 @@ struct AudioProcessingImpl::ApmPrivateSubmodules { AudioProcessing* AudioProcessing::Create() { webrtc::Config config; - return Create(config, nullptr, nullptr); + return Create(config, nullptr, rtc::Callback1(), nullptr); } AudioProcessing* AudioProcessing::Create(const webrtc::Config& config) { - return Create(config, nullptr, nullptr); + return Create(config, nullptr, rtc::Callback1(), nullptr); } AudioProcessing* AudioProcessing::Create(const webrtc::Config& config, NonlinearBeamformer* beamformer) { - return Create(config, nullptr, beamformer); + return Create(config, nullptr, rtc::Callback1(), + beamformer); } AudioProcessing* AudioProcessing::Create( const webrtc::Config& config, std::unique_ptr capture_post_processor, NonlinearBeamformer* beamformer) { + return Create(config, std::move(capture_post_processor), + rtc::Callback1(), beamformer); +} + +AudioProcessing* AudioProcessing::Create( + const webrtc::Config& config, + std::unique_ptr capture_post_processor, + rtc::Callback1 echo_control_factory, + NonlinearBeamformer* beamformer) { AudioProcessingImpl* apm = new rtc::RefCountedObject( - config, std::move(capture_post_processor), beamformer); + config, std::move(capture_post_processor), echo_control_factory, + beamformer); if (apm->Initialize() != kNoError) { delete apm; apm = nullptr; @@ -336,13 +347,18 @@ AudioProcessing* AudioProcessing::Create( } AudioProcessingImpl::AudioProcessingImpl(const webrtc::Config& config) - : AudioProcessingImpl(config, nullptr, nullptr) {} + : AudioProcessingImpl(config, + nullptr, + rtc::Callback1(), + nullptr) {} AudioProcessingImpl::AudioProcessingImpl( const webrtc::Config& config, std::unique_ptr capture_post_processor, + rtc::Callback1 echo_control_factory, NonlinearBeamformer* beamformer) : high_pass_filter_impl_(new HighPassFilterImpl(this)), + echo_control_factory_(echo_control_factory), submodule_states_(!!capture_post_processor), public_submodules_(new ApmPublicSubmodules()), private_submodules_( @@ -679,6 +695,7 @@ void AudioProcessingImpl::ApplyConfig(const AudioProcessing::Config& config) { LOG(LS_INFO) << "Highpass filter activated: " << config_.high_pass_filter.enabled; + // TODO(gustaf): Do this outside of APM. config_ok = EchoCanceller3::Validate(config_.echo_canceller3); if (!config_ok) { LOG(LS_ERROR) << "AudioProcessing module config error" << std::endl @@ -689,6 +706,7 @@ void AudioProcessingImpl::ApplyConfig(const AudioProcessing::Config& config) { config_.echo_canceller3 = AudioProcessing::Config::EchoCanceller3(); } + // TODO(gustaf): Enable EchoCanceller3 by injection, not configuration. if (config.echo_canceller3.enabled != capture_nonlocked_.echo_canceller3_enabled) { capture_nonlocked_.echo_canceller3_enabled = @@ -1697,7 +1715,11 @@ void AudioProcessingImpl::InitializeLowCutFilter() { } void AudioProcessingImpl::InitializeEchoCanceller3() { - if (capture_nonlocked_.echo_canceller3_enabled) { + if (!echo_control_factory_.empty()) { + private_submodules_->echo_controller.reset( + echo_control_factory_(proc_sample_rate_hz())); + } else if (capture_nonlocked_.echo_canceller3_enabled) { + // TODO(gustaf): Remove once injection is used. private_submodules_->echo_controller.reset(new EchoCanceller3( config_.echo_canceller3, proc_sample_rate_hz(), true)); } else { diff --git a/modules/audio_processing/audio_processing_impl.h b/modules/audio_processing/audio_processing_impl.h index 1e5695ca5a..a5e16cbbf8 100644 --- a/modules/audio_processing/audio_processing_impl.h +++ b/modules/audio_processing/audio_processing_impl.h @@ -43,6 +43,7 @@ class AudioProcessingImpl : public AudioProcessing { // beamformer. AudioProcessingImpl(const webrtc::Config& config, std::unique_ptr capture_post_processor, + rtc::Callback1 echo_control_factory, NonlinearBeamformer* beamformer); ~AudioProcessingImpl() override; int Initialize() override; @@ -141,6 +142,9 @@ class AudioProcessingImpl : public AudioProcessing { // Submodule interface implementations. std::unique_ptr high_pass_filter_impl_; + // EchoControl factory method. + rtc::Callback1 echo_control_factory_; + class ApmSubmoduleStates { public: explicit ApmSubmoduleStates(bool capture_post_processor_enabled); diff --git a/modules/audio_processing/audio_processing_unittest.cc b/modules/audio_processing/audio_processing_unittest.cc index 854d6a552c..4540a6a3a3 100644 --- a/modules/audio_processing/audio_processing_unittest.cc +++ b/modules/audio_processing/audio_processing_unittest.cc @@ -1316,8 +1316,8 @@ TEST_F(ApmTest, AgcOnlyAdaptsWhenTargetSignalIsPresent) { config.Set(new Beamforming(true, geometry)); testing::NiceMock* beamformer = new testing::NiceMock(geometry, 1u); - std::unique_ptr apm( - AudioProcessing::Create(config, nullptr, beamformer)); + std::unique_ptr apm(AudioProcessing::Create( + config, nullptr, rtc::Callback1(), beamformer)); EXPECT_EQ(kNoErr, apm->gain_control()->Enable(true)); ChannelBuffer src_buf(kSamplesPerChannel, kNumInputChannels); ChannelBuffer dest_buf(kSamplesPerChannel, kNumOutputChannels); @@ -2915,15 +2915,16 @@ TEST(ApmConfiguration, EnablePostProcessing) { new testing::NiceMock(); auto mock_post_processor = std::unique_ptr(mock_post_processor_ptr); - rtc::scoped_refptr apm = AudioProcessing::Create( - webrtc_config, std::move(mock_post_processor), nullptr); + rtc::scoped_refptr apm = + AudioProcessing::Create(webrtc_config, std::move(mock_post_processor), + rtc::Callback1(), nullptr); AudioFrame audio; audio.num_channels_ = 1; SetFrameSampleRate(&audio, AudioProcessing::NativeRate::kSampleRate16kHz); EXPECT_CALL(*mock_post_processor_ptr, Process(testing::_)).Times(1); - std::cout << apm->ProcessStream(&audio) << std::endl; + apm->ProcessStream(&audio); } } // namespace webrtc diff --git a/modules/audio_processing/include/audio_processing.h b/modules/audio_processing/include/audio_processing.h index 54aed341b6..2cbea501c6 100644 --- a/modules/audio_processing/include/audio_processing.h +++ b/modules/audio_processing/include/audio_processing.h @@ -23,6 +23,7 @@ #include "modules/audio_processing/beamformer/array_util.h" #include "modules/audio_processing/include/config.h" #include "rtc_base/arraysize.h" +#include "rtc_base/callback.h" #include "rtc_base/deprecation.h" #include "rtc_base/platform_file.h" #include "rtc_base/refcount.h" @@ -43,6 +44,7 @@ class ProcessingConfig; class EchoCancellation; class EchoControlMobile; +class EchoControl; class GainControl; class HighPassFilter; class LevelEstimator; @@ -376,10 +378,15 @@ class AudioProcessing : public rtc::RefCountInterface { RTC_DEPRECATED static AudioProcessing* Create(const webrtc::Config& config, NonlinearBeamformer* beamformer); + static AudioProcessing* Create( + const webrtc::Config& config, + std::unique_ptr capture_post_processor, + NonlinearBeamformer* beamformer); // Allows passing in optional user-defined processing modules. static AudioProcessing* Create( const webrtc::Config& config, std::unique_ptr capture_post_processor, + rtc::Callback1 echo_control_factory, NonlinearBeamformer* beamformer); ~AudioProcessing() override {}