From 04c6053f46edacf6fe9871dac3ab407821fe5a50 Mon Sep 17 00:00:00 2001 From: Sam Zackrisson Date: Tue, 5 Apr 2022 15:57:22 +0200 Subject: [PATCH] AEC3: Simplify the EchoCanceller3 construction MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Apart from making the construction more straightforward, this change allows recreating the BlockProcessor at runtime. This is used to change parameterization at runtime in an upcoming CL [1]. [1] https://webrtc-review.googlesource.com/c/src/+/258129 Tested: Bitexact on a large number of aecdumps. Bug: chromium:1295710 Change-Id: I2e0275c5c97044cb4370042633266b193c06b960 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/258100 Reviewed-by: Per Ã…hgren Commit-Queue: Sam Zackrisson Cr-Commit-Position: refs/heads/main@{#36473} --- .../audio_processing/aec3/echo_canceller3.cc | 28 ++++----- .../audio_processing/aec3/echo_canceller3.h | 15 ++--- .../aec3/echo_canceller3_unittest.cc | 61 +++++++++---------- 3 files changed, 48 insertions(+), 56 deletions(-) diff --git a/modules/audio_processing/aec3/echo_canceller3.cc b/modules/audio_processing/aec3/echo_canceller3.cc index 419a056d20..fcc941b0db 100644 --- a/modules/audio_processing/aec3/echo_canceller3.cc +++ b/modules/audio_processing/aec3/echo_canceller3.cc @@ -294,7 +294,6 @@ EchoCanceller3Config AdjustConfig(const EchoCanceller3Config& config) { adjusted_cfg.ep_strength.use_conservative_tail_frequency_response = false; } - if (field_trial::IsEnabled("WebRTC-Aec3ShortHeadroomKillSwitch")) { // Two blocks headroom. adjusted_cfg.delay.delay_headroom_samples = kBlockSize * 2; @@ -672,23 +671,9 @@ EchoCanceller3::EchoCanceller3(const EchoCanceller3Config& config, int sample_rate_hz, size_t num_render_channels, size_t num_capture_channels) - : EchoCanceller3(AdjustConfig(config), - sample_rate_hz, - num_render_channels, - num_capture_channels, - std::unique_ptr( - BlockProcessor::Create(AdjustConfig(config), - sample_rate_hz, - num_render_channels, - num_capture_channels))) {} -EchoCanceller3::EchoCanceller3(const EchoCanceller3Config& config, - int sample_rate_hz, - size_t num_render_channels, - size_t num_capture_channels, - std::unique_ptr block_processor) : data_dumper_( new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))), - config_(config), + config_(AdjustConfig(config)), sample_rate_hz_(sample_rate_hz), num_bands_(NumBandsForRate(sample_rate_hz_)), num_render_channels_(num_render_channels), @@ -706,7 +691,6 @@ EchoCanceller3::EchoCanceller3(const EchoCanceller3Config& config, Aec3RenderQueueItemVerifier(num_bands_, num_render_channels_, AudioBuffer::kSplitBandSize)), - block_processor_(std::move(block_processor)), render_queue_output_frame_( num_bands_, std::vector>( @@ -728,6 +712,9 @@ EchoCanceller3::EchoCanceller3(const EchoCanceller3Config& config, std::vector>(num_capture_channels_)) { RTC_DCHECK(ValidFullBandRate(sample_rate_hz_)); + block_processor_.reset(BlockProcessor::Create( + config_, sample_rate_hz_, num_render_channels_, num_capture_channels_)); + if (config_.delay.fixed_capture_delay_samples > 0) { block_delay_buffer_.reset(new BlockDelayBuffer( num_capture_channels_, num_bands_, AudioBuffer::kSplitBandSize, @@ -885,6 +872,13 @@ EchoCanceller3Config EchoCanceller3::CreateDefaultConfig( return cfg; } +void EchoCanceller3::SetBlockProcessorForTesting( + std::unique_ptr block_processor) { + RTC_DCHECK_RUNS_SERIALIZED(&capture_race_checker_); + RTC_DCHECK(block_processor); + block_processor_ = std::move(block_processor); +} + void EchoCanceller3::EmptyRenderQueue() { RTC_DCHECK_RUNS_SERIALIZED(&capture_race_checker_); bool frame_to_buffer = diff --git a/modules/audio_processing/aec3/echo_canceller3.h b/modules/audio_processing/aec3/echo_canceller3.h index a4aab4987f..44e0f38cb9 100644 --- a/modules/audio_processing/aec3/echo_canceller3.h +++ b/modules/audio_processing/aec3/echo_canceller3.h @@ -84,18 +84,13 @@ class Aec3RenderQueueItemVerifier { // AnalyzeRender call which can be called concurrently with the other methods. class EchoCanceller3 : public EchoControl { public: - // Normal c-tor to use. EchoCanceller3(const EchoCanceller3Config& config, int sample_rate_hz, size_t num_render_channels, size_t num_capture_channels); - // Testing c-tor that is used only for testing purposes. - EchoCanceller3(const EchoCanceller3Config& config, - int sample_rate_hz, - size_t num_render_channels, - size_t num_capture_channels, - std::unique_ptr block_processor); + ~EchoCanceller3() override; + EchoCanceller3(const EchoCanceller3&) = delete; EchoCanceller3& operator=(const EchoCanceller3&) = delete; @@ -142,6 +137,12 @@ class EchoCanceller3 : public EchoControl { private: class RenderWriter; + friend class EchoCanceller3Tester; + FRIEND_TEST_ALL_PREFIXES(EchoCanceller3Metrics, EchoReturnLossEnhancement); + + // Replaces the internal block processor with a custom one for testing. + void SetBlockProcessorForTesting( + std::unique_ptr block_processor); // Empties the render SwapQueue. void EmptyRenderQueue(); diff --git a/modules/audio_processing/aec3/echo_canceller3_unittest.cc b/modules/audio_processing/aec3/echo_canceller3_unittest.cc index b405e0ca61..ce0fa50c88 100644 --- a/modules/audio_processing/aec3/echo_canceller3_unittest.cc +++ b/modules/audio_processing/aec3/echo_canceller3_unittest.cc @@ -178,6 +178,20 @@ class RenderTransportVerificationProcessor : public BlockProcessor { received_render_blocks_; }; +std::string ProduceDebugText(int sample_rate_hz) { + rtc::StringBuilder ss; + ss << "Sample rate: " << sample_rate_hz; + return ss.Release(); +} + +std::string ProduceDebugText(int sample_rate_hz, int variant) { + rtc::StringBuilder ss; + ss << "Sample rate: " << sample_rate_hz << ", variant: " << variant; + return ss.Release(); +} + +} // namespace + class EchoCanceller3Tester { public: explicit EchoCanceller3Tester(int sample_rate_hz) @@ -206,10 +220,9 @@ class EchoCanceller3Tester { // and that the processor data is properly passed to the EchoCanceller3 // output. void RunCaptureTransportVerificationTest() { - EchoCanceller3 aec3( - EchoCanceller3Config(), sample_rate_hz_, 1, 1, - std::unique_ptr( - new CaptureTransportVerificationProcessor(num_bands_))); + EchoCanceller3 aec3(EchoCanceller3Config(), sample_rate_hz_, 1, 1); + aec3.SetBlockProcessorForTesting( + std::make_unique(num_bands_)); for (size_t frame_index = 0; frame_index < kNumFramesToProcess; ++frame_index) { @@ -231,10 +244,9 @@ class EchoCanceller3Tester { // Test method for testing that the render data is properly received by the // block processor. void RunRenderTransportVerificationTest() { - EchoCanceller3 aec3( - EchoCanceller3Config(), sample_rate_hz_, 1, 1, - std::unique_ptr( - new RenderTransportVerificationProcessor(num_bands_))); + EchoCanceller3 aec3(EchoCanceller3Config(), sample_rate_hz_, 1, 1); + aec3.SetBlockProcessorForTesting( + std::make_unique(num_bands_)); std::vector> render_input(1); std::vector capture_output; @@ -301,8 +313,8 @@ class EchoCanceller3Tester { break; } - EchoCanceller3 aec3(EchoCanceller3Config(), sample_rate_hz_, 1, 1, - std::move(block_processor_mock)); + EchoCanceller3 aec3(EchoCanceller3Config(), sample_rate_hz_, 1, 1); + aec3.SetBlockProcessorForTesting(std::move(block_processor_mock)); for (size_t frame_index = 0; frame_index < kNumFramesToProcess; ++frame_index) { @@ -381,8 +393,8 @@ class EchoCanceller3Tester { } break; } - EchoCanceller3 aec3(EchoCanceller3Config(), sample_rate_hz_, 1, 1, - std::move(block_processor_mock)); + EchoCanceller3 aec3(EchoCanceller3Config(), sample_rate_hz_, 1, 1); + aec3.SetBlockProcessorForTesting(std::move(block_processor_mock)); for (size_t frame_index = 0; frame_index < kNumFramesToProcess; ++frame_index) { @@ -467,8 +479,8 @@ class EchoCanceller3Tester { } break; } - EchoCanceller3 aec3(EchoCanceller3Config(), sample_rate_hz_, 1, 1, - std::move(block_processor_mock)); + EchoCanceller3 aec3(EchoCanceller3Config(), sample_rate_hz_, 1, 1); + aec3.SetBlockProcessorForTesting(std::move(block_processor_mock)); for (size_t frame_index = 0; frame_index < kNumFramesToProcess; ++frame_index) { for (int k = 0; k < fullband_frame_length_; ++k) { @@ -506,10 +518,9 @@ class EchoCanceller3Tester { // capture and render API calls. void RunRenderSwapQueueVerificationTest() { const EchoCanceller3Config config; - EchoCanceller3 aec3( - config, sample_rate_hz_, 1, 1, - std::unique_ptr( - new RenderTransportVerificationProcessor(num_bands_))); + EchoCanceller3 aec3(config, sample_rate_hz_, 1, 1); + aec3.SetBlockProcessorForTesting( + std::make_unique(num_bands_)); std::vector> render_input(1); std::vector capture_output; @@ -618,20 +629,6 @@ class EchoCanceller3Tester { AudioBuffer render_buffer_; }; -std::string ProduceDebugText(int sample_rate_hz) { - rtc::StringBuilder ss; - ss << "Sample rate: " << sample_rate_hz; - return ss.Release(); -} - -std::string ProduceDebugText(int sample_rate_hz, int variant) { - rtc::StringBuilder ss; - ss << "Sample rate: " << sample_rate_hz << ", variant: " << variant; - return ss.Release(); -} - -} // namespace - TEST(EchoCanceller3Buffering, CaptureBitexactness) { for (auto rate : {16000, 32000, 48000}) { SCOPED_TRACE(ProduceDebugText(rate));