From 697a5903148af9da80d815212387563eac4c5052 Mon Sep 17 00:00:00 2001 From: peah Date: Fri, 30 Jun 2017 07:06:10 -0700 Subject: [PATCH] Added the ability to adjust the AEC3 performance for large rooms This CL exposes the parameter for adjusting the AEC3 performance for large rooms. Bug: webrtc:7519 Review-Url: https://codereview.webrtc.org/2967603002 Cr-Commit-Position: refs/heads/master@{#18862} --- .../aec3/adaptive_fir_filter_unittest.cc | 2 +- .../audio_processing/aec3/aec_state.cc | 5 +- .../modules/audio_processing/aec3/aec_state.h | 8 +-- .../aec3/aec_state_unittest.cc | 8 +-- .../audio_processing/aec3/block_processor.cc | 14 ++++-- .../audio_processing/aec3/block_processor.h | 6 ++- .../aec3/block_processor_unittest.cc | 33 +++++++------ .../aec3/comfort_noise_generator_unittest.cc | 6 +-- .../audio_processing/aec3/echo_canceller3.cc | 9 ++-- .../audio_processing/aec3/echo_canceller3.h | 4 +- .../aec3/echo_canceller3_unittest.cc | 49 +++++++++++++++---- .../audio_processing/aec3/echo_remover.cc | 17 +++++-- .../audio_processing/aec3/echo_remover.h | 5 +- .../aec3/echo_remover_metrics_unittest.cc | 2 +- .../aec3/echo_remover_unittest.cc | 19 ++++--- .../aec3/main_filter_update_gain_unittest.cc | 2 +- .../aec3/residual_echo_estimator_unittest.cc | 4 +- .../shadow_filter_update_gain_unittest.cc | 2 +- .../aec3/subtractor_unittest.cc | 6 +-- .../audio_processing/audio_processing_impl.cc | 4 +- .../include/audio_processing.h | 1 + 21 files changed, 137 insertions(+), 69 deletions(-) diff --git a/webrtc/modules/audio_processing/aec3/adaptive_fir_filter_unittest.cc b/webrtc/modules/audio_processing/aec3/adaptive_fir_filter_unittest.cc index 2402d91d0e..83c3ac8a8c 100644 --- a/webrtc/modules/audio_processing/aec3/adaptive_fir_filter_unittest.cc +++ b/webrtc/modules/audio_processing/aec3/adaptive_fir_filter_unittest.cc @@ -305,7 +305,7 @@ TEST(AdaptiveFirFilter, FilterAndAdapt) { std::vector> x(3, std::vector(kBlockSize, 0.f)); std::vector n(kBlockSize, 0.f); std::vector y(kBlockSize, 0.f); - AecState aec_state; + AecState aec_state(0.f); RenderSignalAnalyzer render_signal_analyzer; std::vector e(kBlockSize, 0.f); std::array s; diff --git a/webrtc/modules/audio_processing/aec3/aec_state.cc b/webrtc/modules/audio_processing/aec3/aec_state.cc index de4a0c16eb..316f888717 100644 --- a/webrtc/modules/audio_processing/aec3/aec_state.cc +++ b/webrtc/modules/audio_processing/aec3/aec_state.cc @@ -78,10 +78,11 @@ constexpr int kEchoPathChangeCounterMax = 2 * kNumBlocksPerSecond; int AecState::instance_count_ = 0; -AecState::AecState() +AecState::AecState(float echo_decay) : data_dumper_( new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))), - echo_path_change_counter_(kEchoPathChangeCounterInitial) {} + echo_path_change_counter_(kEchoPathChangeCounterInitial), + echo_decay_factor_(echo_decay) {} AecState::~AecState() = default; diff --git a/webrtc/modules/audio_processing/aec3/aec_state.h b/webrtc/modules/audio_processing/aec3/aec_state.h index 519665f3a2..87089360a4 100644 --- a/webrtc/modules/audio_processing/aec3/aec_state.h +++ b/webrtc/modules/audio_processing/aec3/aec_state.h @@ -31,7 +31,7 @@ class ApmDataDumper; // Handles the state and the conditions for the echo removal functionality. class AecState { public: - AecState(); + explicit AecState(float echo_decay); ~AecState(); // Returns whether the linear filter estimate is usable. @@ -79,7 +79,7 @@ class AecState { // Returns the decay factor for the echo reverberation. // TODO(peah): Make this adaptive. - float ReverbDecayFactor() const { return 0.f; } + float ReverbDecayFactor() const { return echo_decay_factor_; } // Returns whether the echo suppression gain should be forced to zero. bool ForcedZeroGain() const { return force_zero_gain_; } @@ -113,8 +113,8 @@ class AecState { rtc::Optional filter_delay_; rtc::Optional external_delay_; size_t blocks_since_last_saturation_ = 1000; - - RTC_DISALLOW_COPY_AND_ASSIGN(AecState); + const float echo_decay_factor_; + RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(AecState); }; } // namespace webrtc diff --git a/webrtc/modules/audio_processing/aec3/aec_state_unittest.cc b/webrtc/modules/audio_processing/aec3/aec_state_unittest.cc index 90b7cb9269..682126e1ce 100644 --- a/webrtc/modules/audio_processing/aec3/aec_state_unittest.cc +++ b/webrtc/modules/audio_processing/aec3/aec_state_unittest.cc @@ -18,7 +18,7 @@ namespace webrtc { // Verify the general functionality of AecState TEST(AecState, NormalUsage) { ApmDataDumper data_dumper(42); - AecState state; + AecState state(0.f); RenderBuffer render_buffer(Aec3Optimization::kNone, 3, 30, std::vector(1, 30)); std::array E2_main = {}; @@ -148,7 +148,7 @@ TEST(AecState, NormalUsage) { // Verifies the a non-significant delay is correctly identified. TEST(AecState, NonSignificantDelay) { - AecState state; + AecState state(0.f); RenderBuffer render_buffer(Aec3Optimization::kNone, 3, 30, std::vector(1, 30)); std::array E2_main; @@ -172,7 +172,7 @@ TEST(AecState, NonSignificantDelay) { // Verifies the delay for a converged filter is correctly identified. TEST(AecState, ConvergedFilterDelay) { constexpr int kFilterLength = 10; - AecState state; + AecState state(0.f); RenderBuffer render_buffer(Aec3Optimization::kNone, 3, 30, std::vector(1, 30)); std::array E2_main; @@ -203,7 +203,7 @@ TEST(AecState, ConvergedFilterDelay) { // Verify that the externally reported delay is properly reported and converted. TEST(AecState, ExternalDelay) { - AecState state; + AecState state(0.f); std::array E2_main; std::array E2_shadow; std::array Y2; diff --git a/webrtc/modules/audio_processing/aec3/block_processor.cc b/webrtc/modules/audio_processing/aec3/block_processor.cc index bb1286cd43..2cf56066bd 100644 --- a/webrtc/modules/audio_processing/aec3/block_processor.cc +++ b/webrtc/modules/audio_processing/aec3/block_processor.cc @@ -168,29 +168,33 @@ void BlockProcessorImpl::UpdateEchoLeakageStatus(bool leakage_detected) { } // namespace -BlockProcessor* BlockProcessor::Create(int sample_rate_hz) { +BlockProcessor* BlockProcessor::Create( + const AudioProcessing::Config::EchoCanceller3& config, + int sample_rate_hz) { std::unique_ptr render_buffer( RenderDelayBuffer::Create(NumBandsForRate(sample_rate_hz))); std::unique_ptr delay_controller( RenderDelayController::Create(sample_rate_hz)); std::unique_ptr echo_remover( - EchoRemover::Create(sample_rate_hz)); - return Create(sample_rate_hz, std::move(render_buffer), + EchoRemover::Create(config, sample_rate_hz)); + return Create(config, sample_rate_hz, std::move(render_buffer), std::move(delay_controller), std::move(echo_remover)); } BlockProcessor* BlockProcessor::Create( + const AudioProcessing::Config::EchoCanceller3& config, int sample_rate_hz, std::unique_ptr render_buffer) { std::unique_ptr delay_controller( RenderDelayController::Create(sample_rate_hz)); std::unique_ptr echo_remover( - EchoRemover::Create(sample_rate_hz)); - return Create(sample_rate_hz, std::move(render_buffer), + EchoRemover::Create(config, sample_rate_hz)); + return Create(config, sample_rate_hz, std::move(render_buffer), std::move(delay_controller), std::move(echo_remover)); } BlockProcessor* BlockProcessor::Create( + const AudioProcessing::Config::EchoCanceller3& config, int sample_rate_hz, std::unique_ptr render_buffer, std::unique_ptr delay_controller, diff --git a/webrtc/modules/audio_processing/aec3/block_processor.h b/webrtc/modules/audio_processing/aec3/block_processor.h index 830fec7e66..92359314a1 100644 --- a/webrtc/modules/audio_processing/aec3/block_processor.h +++ b/webrtc/modules/audio_processing/aec3/block_processor.h @@ -23,12 +23,16 @@ namespace webrtc { // Class for performing echo cancellation on 64 sample blocks of audio data. class BlockProcessor { public: - static BlockProcessor* Create(int sample_rate_hz); + static BlockProcessor* Create( + const AudioProcessing::Config::EchoCanceller3& config, + int sample_rate_hz); // Only used for testing purposes. static BlockProcessor* Create( + const AudioProcessing::Config::EchoCanceller3& config, int sample_rate_hz, std::unique_ptr render_buffer); static BlockProcessor* Create( + const AudioProcessing::Config::EchoCanceller3& config, int sample_rate_hz, std::unique_ptr render_buffer, std::unique_ptr delay_controller, diff --git a/webrtc/modules/audio_processing/aec3/block_processor_unittest.cc b/webrtc/modules/audio_processing/aec3/block_processor_unittest.cc index 01db98259a..1c04536723 100644 --- a/webrtc/modules/audio_processing/aec3/block_processor_unittest.cc +++ b/webrtc/modules/audio_processing/aec3/block_processor_unittest.cc @@ -36,8 +36,8 @@ using testing::_; // Verifies that the basic BlockProcessor functionality works and that the API // methods are callable. void RunBasicSetupAndApiCallTest(int sample_rate_hz) { - std::unique_ptr block_processor( - BlockProcessor::Create(sample_rate_hz)); + std::unique_ptr block_processor(BlockProcessor::Create( + AudioProcessing::Config::EchoCanceller3(), sample_rate_hz)); std::vector> block(NumBandsForRate(sample_rate_hz), std::vector(kBlockSize, 0.f)); @@ -48,8 +48,8 @@ void RunBasicSetupAndApiCallTest(int sample_rate_hz) { #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) void RunRenderBlockSizeVerificationTest(int sample_rate_hz) { - std::unique_ptr block_processor( - BlockProcessor::Create(sample_rate_hz)); + std::unique_ptr block_processor(BlockProcessor::Create( + AudioProcessing::Config::EchoCanceller3(), sample_rate_hz)); std::vector> block( NumBandsForRate(sample_rate_hz), std::vector(kBlockSize - 1, 0.f)); @@ -57,8 +57,8 @@ void RunRenderBlockSizeVerificationTest(int sample_rate_hz) { } void RunCaptureBlockSizeVerificationTest(int sample_rate_hz) { - std::unique_ptr block_processor( - BlockProcessor::Create(sample_rate_hz)); + std::unique_ptr block_processor(BlockProcessor::Create( + AudioProcessing::Config::EchoCanceller3(), sample_rate_hz)); std::vector> block( NumBandsForRate(sample_rate_hz), std::vector(kBlockSize - 1, 0.f)); @@ -69,8 +69,8 @@ void RunRenderNumBandsVerificationTest(int sample_rate_hz) { const size_t wrong_num_bands = NumBandsForRate(sample_rate_hz) < 3 ? NumBandsForRate(sample_rate_hz) + 1 : 1; - std::unique_ptr block_processor( - BlockProcessor::Create(sample_rate_hz)); + std::unique_ptr block_processor(BlockProcessor::Create( + AudioProcessing::Config::EchoCanceller3(), sample_rate_hz)); std::vector> block(wrong_num_bands, std::vector(kBlockSize, 0.f)); @@ -81,8 +81,8 @@ void RunCaptureNumBandsVerificationTest(int sample_rate_hz) { const size_t wrong_num_bands = NumBandsForRate(sample_rate_hz) < 3 ? NumBandsForRate(sample_rate_hz) + 1 : 1; - std::unique_ptr block_processor( - BlockProcessor::Create(sample_rate_hz)); + std::unique_ptr block_processor(BlockProcessor::Create( + AudioProcessing::Config::EchoCanceller3(), sample_rate_hz)); std::vector> block(wrong_num_bands, std::vector(kBlockSize, 0.f)); @@ -126,7 +126,8 @@ TEST(BlockProcessor, DISABLED_DelayControllerIntegration) { .Times(kNumBlocks + 1) .WillRepeatedly(Return(0)); std::unique_ptr block_processor( - BlockProcessor::Create(rate, std::move(render_delay_buffer_mock))); + BlockProcessor::Create(AudioProcessing::Config::EchoCanceller3(), rate, + std::move(render_delay_buffer_mock))); std::vector> render_block( NumBandsForRate(rate), std::vector(kBlockSize, 0.f)); @@ -180,7 +181,8 @@ TEST(BlockProcessor, DISABLED_SubmoduleIntegration) { .Times(kNumBlocks); std::unique_ptr block_processor(BlockProcessor::Create( - rate, std::move(render_delay_buffer_mock), + AudioProcessing::Config::EchoCanceller3(), rate, + std::move(render_delay_buffer_mock), std::move(render_delay_controller_mock), std::move(echo_remover_mock))); std::vector> render_block( @@ -238,7 +240,9 @@ TEST(BlockProcessor, VerifyCaptureNumBandsCheck) { // Verifiers that the verification for null ProcessCapture input works. TEST(BlockProcessor, NullProcessCaptureParameter) { - EXPECT_DEATH(std::unique_ptr(BlockProcessor::Create(8000)) + EXPECT_DEATH(std::unique_ptr( + BlockProcessor::Create( + AudioProcessing::Config::EchoCanceller3(), 8000)) ->ProcessCapture(false, false, nullptr), ""); } @@ -247,7 +251,8 @@ TEST(BlockProcessor, NullProcessCaptureParameter) { // TODO(peah): Re-enable the test once the issue with memory leaks during DEATH // tests on test bots has been fixed. TEST(BlockProcessor, DISABLED_WrongSampleRate) { - EXPECT_DEATH(std::unique_ptr(BlockProcessor::Create(8001)), + EXPECT_DEATH(std::unique_ptr(BlockProcessor::Create( + AudioProcessing::Config::EchoCanceller3(), 8001)), ""); } diff --git a/webrtc/modules/audio_processing/aec3/comfort_noise_generator_unittest.cc b/webrtc/modules/audio_processing/aec3/comfort_noise_generator_unittest.cc index dcdbab38eb..ce86f2db2c 100644 --- a/webrtc/modules/audio_processing/aec3/comfort_noise_generator_unittest.cc +++ b/webrtc/modules/audio_processing/aec3/comfort_noise_generator_unittest.cc @@ -36,7 +36,7 @@ TEST(ComfortNoiseGenerator, NullLowerBandNoise) { std::array N2; FftData noise; EXPECT_DEATH(ComfortNoiseGenerator(DetectOptimization()) - .Compute(AecState(), N2, nullptr, &noise), + .Compute(AecState(0.f), N2, nullptr, &noise), ""); } @@ -44,7 +44,7 @@ TEST(ComfortNoiseGenerator, NullUpperBandNoise) { std::array N2; FftData noise; EXPECT_DEATH(ComfortNoiseGenerator(DetectOptimization()) - .Compute(AecState(), N2, &noise, nullptr), + .Compute(AecState(0.f), N2, &noise, nullptr), ""); } @@ -91,7 +91,7 @@ TEST(ComfortNoiseGenerator, TestOptimizations) { TEST(ComfortNoiseGenerator, CorrectLevel) { ComfortNoiseGenerator cng(DetectOptimization()); - AecState aec_state; + AecState aec_state(0.f); std::array N2; N2.fill(1000.f * 1000.f); diff --git a/webrtc/modules/audio_processing/aec3/echo_canceller3.cc b/webrtc/modules/audio_processing/aec3/echo_canceller3.cc index 4cd9c39729..3175c5414c 100644 --- a/webrtc/modules/audio_processing/aec3/echo_canceller3.cc +++ b/webrtc/modules/audio_processing/aec3/echo_canceller3.cc @@ -200,11 +200,14 @@ void EchoCanceller3::RenderWriter::Insert(AudioBuffer* input) { int EchoCanceller3::instance_count_ = 0; -EchoCanceller3::EchoCanceller3(int sample_rate_hz, bool use_highpass_filter) +EchoCanceller3::EchoCanceller3( + const AudioProcessing::Config::EchoCanceller3& config, + int sample_rate_hz, + bool use_highpass_filter) : EchoCanceller3(sample_rate_hz, use_highpass_filter, std::unique_ptr( - BlockProcessor::Create(sample_rate_hz))) {} + BlockProcessor::Create(config, sample_rate_hz))) {} EchoCanceller3::EchoCanceller3(int sample_rate_hz, bool use_highpass_filter, std::unique_ptr block_processor) @@ -331,7 +334,7 @@ std::string EchoCanceller3::ToString( bool EchoCanceller3::Validate( const AudioProcessing::Config::EchoCanceller3& config) { - return true; + return (config.echo_decay >= 0.f && config.echo_decay < 1.f); } void EchoCanceller3::EmptyRenderQueue() { diff --git a/webrtc/modules/audio_processing/aec3/echo_canceller3.h b/webrtc/modules/audio_processing/aec3/echo_canceller3.h index aa19c05001..6324cc6bda 100644 --- a/webrtc/modules/audio_processing/aec3/echo_canceller3.h +++ b/webrtc/modules/audio_processing/aec3/echo_canceller3.h @@ -63,7 +63,9 @@ class Aec3RenderQueueItemVerifier { class EchoCanceller3 { public: // Normal c-tor to use. - EchoCanceller3(int sample_rate_hz, bool use_highpass_filter); + EchoCanceller3(const AudioProcessing::Config::EchoCanceller3& config, + int sample_rate_hz, + bool use_highpass_filter); // Testing c-tor that is used only for testing purposes. EchoCanceller3(int sample_rate_hz, bool use_highpass_filter, diff --git a/webrtc/modules/audio_processing/aec3/echo_canceller3_unittest.cc b/webrtc/modules/audio_processing/aec3/echo_canceller3_unittest.cc index 78a10c006c..376cf1edfb 100644 --- a/webrtc/modules/audio_processing/aec3/echo_canceller3_unittest.cc +++ b/webrtc/modules/audio_processing/aec3/echo_canceller3_unittest.cc @@ -495,7 +495,8 @@ class EchoCanceller3Tester { // This test verifies that a buffer overrun in the render swapqueue is // properly reported. void RunRenderPipelineSwapQueueOverrunReturnValueTest() { - EchoCanceller3 aec3(sample_rate_hz_, false); + EchoCanceller3 aec3(AudioProcessing::Config::EchoCanceller3(), + sample_rate_hz_, false); constexpr size_t kRenderTransferQueueSize = 30; for (size_t k = 0; k < 2; ++k) { @@ -524,7 +525,8 @@ class EchoCanceller3Tester { // Set aec3_sample_rate_hz to be different from sample_rate_hz_ in such a // way that the number of bands for the rates are different. const int aec3_sample_rate_hz = sample_rate_hz_ == 48000 ? 32000 : 48000; - EchoCanceller3 aec3(aec3_sample_rate_hz, false); + EchoCanceller3 aec3(AudioProcessing::Config::EchoCanceller3(), + aec3_sample_rate_hz, false); PopulateInputFrame(frame_length_, 0, &render_buffer_.channels_f()[0][0], 0); EXPECT_DEATH(aec3.AnalyzeRender(&render_buffer_), ""); @@ -537,7 +539,8 @@ class EchoCanceller3Tester { // Set aec3_sample_rate_hz to be different from sample_rate_hz_ in such a // way that the number of bands for the rates are different. const int aec3_sample_rate_hz = sample_rate_hz_ == 48000 ? 32000 : 48000; - EchoCanceller3 aec3(aec3_sample_rate_hz, false); + EchoCanceller3 aec3(AudioProcessing::Config::EchoCanceller3(), + aec3_sample_rate_hz, false); PopulateInputFrame(frame_length_, num_bands_, 0, &capture_buffer_.split_bands_f(0)[0], 100); EXPECT_DEATH(aec3.ProcessCapture(&capture_buffer_, false), ""); @@ -550,7 +553,8 @@ class EchoCanceller3Tester { // Set aec3_sample_rate_hz to be different from sample_rate_hz_ in such a // way that the band frame lengths are different. const int aec3_sample_rate_hz = sample_rate_hz_ == 8000 ? 16000 : 8000; - EchoCanceller3 aec3(aec3_sample_rate_hz, false); + EchoCanceller3 aec3(AudioProcessing::Config::EchoCanceller3(), + aec3_sample_rate_hz, false); OptionalBandSplit(); PopulateInputFrame(frame_length_, 0, &render_buffer_.channels_f()[0][0], 0); @@ -565,7 +569,8 @@ class EchoCanceller3Tester { // Set aec3_sample_rate_hz to be different from sample_rate_hz_ in such a // way that the band frame lengths are different. const int aec3_sample_rate_hz = sample_rate_hz_ == 8000 ? 16000 : 8000; - EchoCanceller3 aec3(aec3_sample_rate_hz, false); + EchoCanceller3 aec3(AudioProcessing::Config::EchoCanceller3(), + aec3_sample_rate_hz, false); OptionalBandSplit(); PopulateInputFrame(frame_length_, num_bands_, 0, @@ -677,6 +682,21 @@ TEST(EchoCanceller3Messaging, EchoLeakage) { } } +TEST(EchoCanceller3, ConfigValidation) { + AudioProcessing::Config::EchoCanceller3 config; + + config.echo_decay = 0.f; + EXPECT_TRUE(EchoCanceller3::Validate(config)); + config.echo_decay = 0.9f; + EXPECT_TRUE(EchoCanceller3::Validate(config)); + config.echo_decay = -0.1f; + EXPECT_FALSE(EchoCanceller3::Validate(config)); + config.echo_decay = 1.0f; + EXPECT_FALSE(EchoCanceller3::Validate(config)); + config.echo_decay = 1.1f; + EXPECT_FALSE(EchoCanceller3::Validate(config)); +} + #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) TEST(EchoCanceller3InputCheck, WrongCaptureNumBandsCheckVerification) { @@ -706,19 +726,28 @@ TEST(EchoCanceller3InputCheck, WrongCaptureFrameLengthCheckVerification) { // Verifiers that the verification for null input to the render analysis api // call works. TEST(EchoCanceller3InputCheck, NullRenderAnalysisParameter) { - EXPECT_DEATH(EchoCanceller3(8000, false).AnalyzeRender(nullptr), ""); + EXPECT_DEATH( + EchoCanceller3(AudioProcessing::Config::EchoCanceller3(), 8000, false) + .AnalyzeRender(nullptr), + ""); } // Verifiers that the verification for null input to the capture analysis api // call works. TEST(EchoCanceller3InputCheck, NullCaptureAnalysisParameter) { - EXPECT_DEATH(EchoCanceller3(8000, false).AnalyzeCapture(nullptr), ""); + EXPECT_DEATH( + EchoCanceller3(AudioProcessing::Config::EchoCanceller3(), 8000, false) + .AnalyzeCapture(nullptr), + ""); } // Verifiers that the verification for null input to the capture processing api // call works. TEST(EchoCanceller3InputCheck, NullCaptureProcessingParameter) { - EXPECT_DEATH(EchoCanceller3(8000, false).ProcessCapture(nullptr, false), ""); + EXPECT_DEATH( + EchoCanceller3(AudioProcessing::Config::EchoCanceller3(), 8000, false) + .ProcessCapture(nullptr, false), + ""); } // Verifies the check for correct sample rate. @@ -726,7 +755,9 @@ TEST(EchoCanceller3InputCheck, NullCaptureProcessingParameter) { // tests on test bots has been fixed. TEST(EchoCanceller3InputCheck, DISABLED_WrongSampleRate) { ApmDataDumper data_dumper(0); - EXPECT_DEATH(EchoCanceller3(8001, false), ""); + EXPECT_DEATH( + EchoCanceller3(AudioProcessing::Config::EchoCanceller3(), 8001, false), + ""); } #endif diff --git a/webrtc/modules/audio_processing/aec3/echo_remover.cc b/webrtc/modules/audio_processing/aec3/echo_remover.cc index 973725108f..0c6184e3bb 100644 --- a/webrtc/modules/audio_processing/aec3/echo_remover.cc +++ b/webrtc/modules/audio_processing/aec3/echo_remover.cc @@ -49,7 +49,9 @@ void LinearEchoPower(const FftData& E, // Class for removing the echo from the capture signal. class EchoRemoverImpl final : public EchoRemover { public: - explicit EchoRemoverImpl(int sample_rate_hz); + explicit EchoRemoverImpl( + const AudioProcessing::Config::EchoCanceller3& config, + int sample_rate_hz); ~EchoRemoverImpl() override; // Removes the echo from a block of samples from the capture signal. The @@ -90,7 +92,9 @@ class EchoRemoverImpl final : public EchoRemover { int EchoRemoverImpl::instance_count_ = 0; -EchoRemoverImpl::EchoRemoverImpl(int sample_rate_hz) +EchoRemoverImpl::EchoRemoverImpl( + const AudioProcessing::Config::EchoCanceller3& config, + int sample_rate_hz) : fft_(), data_dumper_( new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))), @@ -99,7 +103,8 @@ EchoRemoverImpl::EchoRemoverImpl(int sample_rate_hz) subtractor_(data_dumper_.get(), optimization_), suppression_gain_(optimization_), cng_(optimization_), - suppression_filter_(sample_rate_hz_) { + suppression_filter_(sample_rate_hz_), + aec_state_(config.echo_decay) { RTC_DCHECK(ValidFullBandRate(sample_rate_hz)); } @@ -221,8 +226,10 @@ void EchoRemoverImpl::ProcessCapture( } // namespace -EchoRemover* EchoRemover::Create(int sample_rate_hz) { - return new EchoRemoverImpl(sample_rate_hz); +EchoRemover* EchoRemover::Create( + const AudioProcessing::Config::EchoCanceller3& config, + int sample_rate_hz) { + return new EchoRemoverImpl(config, sample_rate_hz); } } // namespace webrtc diff --git a/webrtc/modules/audio_processing/aec3/echo_remover.h b/webrtc/modules/audio_processing/aec3/echo_remover.h index 4e25b25215..4704f316bf 100644 --- a/webrtc/modules/audio_processing/aec3/echo_remover.h +++ b/webrtc/modules/audio_processing/aec3/echo_remover.h @@ -16,13 +16,16 @@ #include "webrtc/base/optional.h" #include "webrtc/modules/audio_processing/aec3/echo_path_variability.h" #include "webrtc/modules/audio_processing/aec3/render_buffer.h" +#include "webrtc/modules/audio_processing/include/audio_processing.h" namespace webrtc { // Class for removing the echo from the capture signal. class EchoRemover { public: - static EchoRemover* Create(int sample_rate_hz); + static EchoRemover* Create( + const AudioProcessing::Config::EchoCanceller3& config, + int sample_rate_hz); virtual ~EchoRemover() = default; // Removes the echo from a block of samples from the capture signal. The diff --git a/webrtc/modules/audio_processing/aec3/echo_remover_metrics_unittest.cc b/webrtc/modules/audio_processing/aec3/echo_remover_metrics_unittest.cc index 8030f812f6..21a5af2735 100644 --- a/webrtc/modules/audio_processing/aec3/echo_remover_metrics_unittest.cc +++ b/webrtc/modules/audio_processing/aec3/echo_remover_metrics_unittest.cc @@ -126,7 +126,7 @@ TEST(DbMetric, Constructor) { // Verify the general functionality of EchoRemoverMetrics. TEST(EchoRemoverMetrics, NormalUsage) { EchoRemoverMetrics metrics; - AecState aec_state; + AecState aec_state(0.f); std::array comfort_noise_spectrum; std::array suppressor_gain; comfort_noise_spectrum.fill(10.f); diff --git a/webrtc/modules/audio_processing/aec3/echo_remover_unittest.cc b/webrtc/modules/audio_processing/aec3/echo_remover_unittest.cc index dd43b3737c..d5ffb667df 100644 --- a/webrtc/modules/audio_processing/aec3/echo_remover_unittest.cc +++ b/webrtc/modules/audio_processing/aec3/echo_remover_unittest.cc @@ -45,7 +45,8 @@ std::string ProduceDebugText(int sample_rate_hz, int delay) { TEST(EchoRemover, BasicApiCalls) { for (auto rate : {8000, 16000, 32000, 48000}) { SCOPED_TRACE(ProduceDebugText(rate)); - std::unique_ptr remover(EchoRemover::Create(rate)); + std::unique_ptr remover( + EchoRemover::Create(AudioProcessing::Config::EchoCanceller3(), rate)); std::unique_ptr render_buffer( RenderDelayBuffer::Create(NumBandsForRate(rate))); @@ -74,14 +75,17 @@ TEST(EchoRemover, BasicApiCalls) { // TODO(peah): Re-enable the test once the issue with memory leaks during DEATH // tests on test bots has been fixed. TEST(EchoRemover, DISABLED_WrongSampleRate) { - EXPECT_DEATH(std::unique_ptr(EchoRemover::Create(8001)), ""); + EXPECT_DEATH(std::unique_ptr(EchoRemover::Create( + AudioProcessing::Config::EchoCanceller3(), 8001)), + ""); } // Verifies the check for the capture block size. TEST(EchoRemover, WrongCaptureBlockSize) { for (auto rate : {8000, 16000, 32000, 48000}) { SCOPED_TRACE(ProduceDebugText(rate)); - std::unique_ptr remover(EchoRemover::Create(rate)); + std::unique_ptr remover( + EchoRemover::Create(AudioProcessing::Config::EchoCanceller3(), rate)); std::unique_ptr render_buffer( RenderDelayBuffer::Create(NumBandsForRate(rate))); std::vector> capture( @@ -101,7 +105,8 @@ TEST(EchoRemover, WrongCaptureBlockSize) { TEST(EchoRemover, DISABLED_WrongCaptureNumBands) { for (auto rate : {16000, 32000, 48000}) { SCOPED_TRACE(ProduceDebugText(rate)); - std::unique_ptr remover(EchoRemover::Create(rate)); + std::unique_ptr remover( + EchoRemover::Create(AudioProcessing::Config::EchoCanceller3(), rate)); std::unique_ptr render_buffer( RenderDelayBuffer::Create(NumBandsForRate(rate))); std::vector> capture( @@ -118,7 +123,8 @@ TEST(EchoRemover, DISABLED_WrongCaptureNumBands) { // Verifies the check for non-null capture block. TEST(EchoRemover, NullCapture) { - std::unique_ptr remover(EchoRemover::Create(8000)); + std::unique_ptr remover( + EchoRemover::Create(AudioProcessing::Config::EchoCanceller3(), 8000)); std::unique_ptr render_buffer( RenderDelayBuffer::Create(3)); EchoPathVariability echo_path_variability(false, false); @@ -144,7 +150,8 @@ TEST(EchoRemover, BasicEchoRemoval) { EchoPathVariability echo_path_variability(false, false); for (size_t delay_samples : {0, 64, 150, 200, 301}) { SCOPED_TRACE(ProduceDebugText(rate, delay_samples)); - std::unique_ptr remover(EchoRemover::Create(rate)); + std::unique_ptr remover( + EchoRemover::Create(AudioProcessing::Config::EchoCanceller3(), rate)); std::unique_ptr render_buffer( RenderDelayBuffer::Create(NumBandsForRate(rate))); std::vector>> delay_buffers(x.size()); diff --git a/webrtc/modules/audio_processing/aec3/main_filter_update_gain_unittest.cc b/webrtc/modules/audio_processing/aec3/main_filter_update_gain_unittest.cc index 581856b03f..8b958a5051 100644 --- a/webrtc/modules/audio_processing/aec3/main_filter_update_gain_unittest.cc +++ b/webrtc/modules/audio_processing/aec3/main_filter_update_gain_unittest.cc @@ -53,7 +53,7 @@ void RunFilterUpdateTest(int num_blocks_to_process, Random random_generator(42U); std::vector> x(3, std::vector(kBlockSize, 0.f)); std::vector y(kBlockSize, 0.f); - AecState aec_state; + AecState aec_state(0.f); RenderSignalAnalyzer render_signal_analyzer; std::array s; FftData S; diff --git a/webrtc/modules/audio_processing/aec3/residual_echo_estimator_unittest.cc b/webrtc/modules/audio_processing/aec3/residual_echo_estimator_unittest.cc index 824467d9dd..6d34128829 100644 --- a/webrtc/modules/audio_processing/aec3/residual_echo_estimator_unittest.cc +++ b/webrtc/modules/audio_processing/aec3/residual_echo_estimator_unittest.cc @@ -22,7 +22,7 @@ namespace webrtc { // Verifies that the check for non-null output residual echo power works. TEST(ResidualEchoEstimator, NullResidualEchoPowerOutput) { - AecState aec_state; + AecState aec_state(0.f); RenderBuffer render_buffer(Aec3Optimization::kNone, 3, 10, std::vector(1, 10)); std::vector> H2; @@ -37,7 +37,7 @@ TEST(ResidualEchoEstimator, NullResidualEchoPowerOutput) { TEST(ResidualEchoEstimator, BasicTest) { ResidualEchoEstimator estimator; - AecState aec_state; + AecState aec_state(0.f); RenderBuffer render_buffer(Aec3Optimization::kNone, 3, 10, std::vector(1, 10)); std::array E2_main; diff --git a/webrtc/modules/audio_processing/aec3/shadow_filter_update_gain_unittest.cc b/webrtc/modules/audio_processing/aec3/shadow_filter_update_gain_unittest.cc index 40bee42985..47838555c8 100644 --- a/webrtc/modules/audio_processing/aec3/shadow_filter_update_gain_unittest.cc +++ b/webrtc/modules/audio_processing/aec3/shadow_filter_update_gain_unittest.cc @@ -47,7 +47,7 @@ void RunFilterUpdateTest(int num_blocks_to_process, Random random_generator(42U); std::vector> x(3, std::vector(kBlockSize, 0.f)); std::vector y(kBlockSize, 0.f); - AecState aec_state; + AecState aec_state(0.f); RenderSignalAnalyzer render_signal_analyzer; std::array s; FftData S; diff --git a/webrtc/modules/audio_processing/aec3/subtractor_unittest.cc b/webrtc/modules/audio_processing/aec3/subtractor_unittest.cc index 48c9c57444..0c4392332f 100644 --- a/webrtc/modules/audio_processing/aec3/subtractor_unittest.cc +++ b/webrtc/modules/audio_processing/aec3/subtractor_unittest.cc @@ -40,7 +40,7 @@ float RunSubtractorTest(int num_blocks_to_process, std::array Y2; std::array E2_main; std::array E2_shadow; - AecState aec_state; + AecState aec_state(0.f); x_old.fill(0.f); Y2.fill(0.f); E2_main.fill(0.f); @@ -109,7 +109,7 @@ TEST(Subtractor, DISABLED_NullOutput) { std::vector y(kBlockSize, 0.f); EXPECT_DEATH(subtractor.Process(render_buffer, y, render_signal_analyzer, - AecState(), nullptr), + AecState(0.f), nullptr), ""); } @@ -124,7 +124,7 @@ TEST(Subtractor, WrongCaptureSize) { SubtractorOutput output; EXPECT_DEATH(subtractor.Process(render_buffer, y, render_signal_analyzer, - AecState(), &output), + AecState(0.f), &output), ""); } diff --git a/webrtc/modules/audio_processing/audio_processing_impl.cc b/webrtc/modules/audio_processing/audio_processing_impl.cc index 39fb723e0a..292611e099 100644 --- a/webrtc/modules/audio_processing/audio_processing_impl.cc +++ b/webrtc/modules/audio_processing/audio_processing_impl.cc @@ -1881,8 +1881,8 @@ void AudioProcessingImpl::InitializeLowCutFilter() { void AudioProcessingImpl::InitializeEchoCanceller3() { if (capture_nonlocked_.echo_canceller3_enabled) { - private_submodules_->echo_canceller3.reset( - new EchoCanceller3(proc_sample_rate_hz(), true)); + private_submodules_->echo_canceller3.reset(new EchoCanceller3( + config_.echo_canceller3, proc_sample_rate_hz(), true)); } else { private_submodules_->echo_canceller3.reset(); } diff --git a/webrtc/modules/audio_processing/include/audio_processing.h b/webrtc/modules/audio_processing/include/audio_processing.h index 05be5feeb1..6dc6e3fc76 100644 --- a/webrtc/modules/audio_processing/include/audio_processing.h +++ b/webrtc/modules/audio_processing/include/audio_processing.h @@ -268,6 +268,7 @@ class AudioProcessing : public rtc::RefCountInterface { // does not yet have the desired behavior. struct EchoCanceller3 { bool enabled = false; + float echo_decay = 0.f; } echo_canceller3; // Enables the next generation AGC functionality. This feature replaces the