From 08ea5898ff9ff6f6d8d3f1f80cc91f08a716fe82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Per=20=C3=85hgren?= Date: Mon, 15 Jan 2018 08:07:41 +0100 Subject: [PATCH] Separated the AEC3 adaptive filter parameters into sub-structs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bug: webrtc:8671 Change-Id: I02bceceb85da6db65f65c1a2366a2d5021f148ef Reviewed-on: https://webrtc-review.googlesource.com/39502 Reviewed-by: Gustaf Ullberg Commit-Queue: Per Ã…hgren Cr-Commit-Position: refs/heads/master@{#21617} --- .../aec3/adaptive_fir_filter_unittest.cc | 8 +++---- modules/audio_processing/aec3/aec_state.cc | 11 +++++---- .../aec3/aec_state_unittest.cc | 4 ++-- .../aec3/main_filter_update_gain_unittest.cc | 23 ++++++++++--------- .../aec3/render_delay_buffer.cc | 4 ++-- .../aec3/residual_echo_estimator.cc | 5 ++-- .../aec3/residual_echo_estimator_unittest.cc | 3 ++- .../shadow_filter_update_gain_unittest.cc | 10 ++++---- modules/audio_processing/aec3/subtractor.cc | 22 ++++++++++++------ .../aec3/subtractor_unittest.cc | 3 ++- .../include/audio_processing.h | 23 +++++++++++++------ 11 files changed, 69 insertions(+), 47 deletions(-) diff --git a/modules/audio_processing/aec3/adaptive_fir_filter_unittest.cc b/modules/audio_processing/aec3/adaptive_fir_filter_unittest.cc index eecb244242..8d06ee8afe 100644 --- a/modules/audio_processing/aec3/adaptive_fir_filter_unittest.cc +++ b/modules/audio_processing/aec3/adaptive_fir_filter_unittest.cc @@ -307,15 +307,15 @@ TEST(AdaptiveFirFilter, FilterAndAdapt) { constexpr size_t kNumBlocksToProcess = 1000; ApmDataDumper data_dumper(42); EchoCanceller3Config config; - AdaptiveFirFilter filter(config.filter.length_blocks, DetectOptimization(), - &data_dumper); + AdaptiveFirFilter filter(config.filter.main.length_blocks, + DetectOptimization(), &data_dumper); Aec3Fft fft; config.delay.min_echo_path_delay_blocks = 0; config.delay.default_delay = 1; std::unique_ptr render_delay_buffer( RenderDelayBuffer::Create(config, 3)); - ShadowFilterUpdateGain gain(config.filter.shadow_rate, - config.filter.shadow_noise_gate); + ShadowFilterUpdateGain gain(config.filter.shadow.rate, + config.filter.shadow.noise_gate); Random random_generator(42U); std::vector> x(3, std::vector(kBlockSize, 0.f)); std::vector n(kBlockSize, 0.f); diff --git a/modules/audio_processing/aec3/aec_state.cc b/modules/audio_processing/aec3/aec_state.cc index 25bb5be688..0fd035b6e0 100644 --- a/modules/audio_processing/aec3/aec_state.cc +++ b/modules/audio_processing/aec3/aec_state.cc @@ -56,7 +56,7 @@ AecState::AecState(const EchoCanceller3Config& config) new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))), erle_estimator_(config.erle.min, config.erle.max_l, config.erle.max_h), config_(config), - max_render_(config_.filter.length_blocks, 0.f), + max_render_(config_.filter.main.length_blocks, 0.f), reverb_decay_(config_.ep_strength.default_len) {} AecState::~AecState() = default; @@ -175,7 +175,8 @@ void AecState::Update( void AecState::UpdateReverb(const std::vector& impulse_response) { if ((!(filter_delay_ && usable_linear_estimate_)) || - (filter_delay_ > static_cast(config_.filter.length_blocks) - 4)) { + (filter_delay_ > + static_cast(config_.filter.main.length_blocks) - 4)) { return; } @@ -183,11 +184,11 @@ void AecState::UpdateReverb(const std::vector& impulse_response) { // coefficients. std::array matching_data_data; - RTC_DCHECK_LE(GetTimeDomainLength(config_.filter.length_blocks), + RTC_DCHECK_LE(GetTimeDomainLength(config_.filter.main.length_blocks), matching_data_data.size()); rtc::ArrayView matching_data( matching_data_data.data(), - GetTimeDomainLength(config_.filter.length_blocks)); + GetTimeDomainLength(config_.filter.main.length_blocks)); std::transform(impulse_response.begin(), impulse_response.end(), matching_data.begin(), [](float a) { return a * a; }); @@ -195,7 +196,7 @@ void AecState::UpdateReverb(const std::vector& impulse_response) { // model noise power. constexpr size_t kTailLength = 64; const size_t tail_index = - GetTimeDomainLength(config_.filter.length_blocks) - kTailLength; + GetTimeDomainLength(config_.filter.main.length_blocks) - kTailLength; const float tail_power = *std::max_element(matching_data.begin() + tail_index, matching_data.end()); std::for_each(matching_data.begin(), matching_data.begin() + tail_index, diff --git a/modules/audio_processing/aec3/aec_state_unittest.cc b/modules/audio_processing/aec3/aec_state_unittest.cc index 9222a911e8..846a83c79d 100644 --- a/modules/audio_processing/aec3/aec_state_unittest.cc +++ b/modules/audio_processing/aec3/aec_state_unittest.cc @@ -44,7 +44,7 @@ TEST(AecState, NormalUsage) { converged_filter_frequency_response[2][0] = 1.f; std::vector impulse_response( - GetTimeDomainLength(config.filter.length_blocks), 0.f); + GetTimeDomainLength(config.filter.main.length_blocks), 0.f); // Verify that linear AEC usability is false when the filter is diverged. state.Update(diverged_filter_frequency_response, impulse_response, true, @@ -190,7 +190,7 @@ TEST(AecState, ConvergedFilterDelay) { kFilterLength); std::vector impulse_response( - GetTimeDomainLength(config.filter.length_blocks), 0.f); + GetTimeDomainLength(config.filter.main.length_blocks), 0.f); // Verify that the filter delay for a converged filter is properly identified. for (int k = 0; k < kFilterLength; ++k) { diff --git a/modules/audio_processing/aec3/main_filter_update_gain_unittest.cc b/modules/audio_processing/aec3/main_filter_update_gain_unittest.cc index 7120cc2096..1bfc0653ac 100644 --- a/modules/audio_processing/aec3/main_filter_update_gain_unittest.cc +++ b/modules/audio_processing/aec3/main_filter_update_gain_unittest.cc @@ -42,19 +42,20 @@ void RunFilterUpdateTest(int num_blocks_to_process, FftData* G_last_block) { ApmDataDumper data_dumper(42); EchoCanceller3Config config; - config.filter.length_blocks = filter_length_blocks; - AdaptiveFirFilter main_filter(config.filter.length_blocks, + config.filter.main.length_blocks = filter_length_blocks; + config.filter.shadow.length_blocks = filter_length_blocks; + AdaptiveFirFilter main_filter(config.filter.main.length_blocks, DetectOptimization(), &data_dumper); - AdaptiveFirFilter shadow_filter(config.filter.length_blocks, + AdaptiveFirFilter shadow_filter(config.filter.shadow.length_blocks, DetectOptimization(), &data_dumper); Aec3Fft fft; std::array x_old; x_old.fill(0.f); - ShadowFilterUpdateGain shadow_gain(config.filter.shadow_rate, - config.filter.shadow_noise_gate); + ShadowFilterUpdateGain shadow_gain(config.filter.shadow.rate, + config.filter.shadow.noise_gate); MainFilterUpdateGain main_gain( - config.filter.leakage_converged, config.filter.leakage_diverged, - config.filter.main_noise_gate, config.filter.error_floor); + config.filter.main.leakage_converged, config.filter.main.leakage_diverged, + config.filter.main.noise_gate, config.filter.main.error_floor); Random random_generator(42U); std::vector> x(3, std::vector(kBlockSize, 0.f)); std::vector y(kBlockSize, 0.f); @@ -189,13 +190,13 @@ std::string ProduceDebugText(size_t delay, int filter_length_blocks) { TEST(MainFilterUpdateGain, NullDataOutputGain) { ApmDataDumper data_dumper(42); EchoCanceller3Config config; - AdaptiveFirFilter filter(config.filter.length_blocks, DetectOptimization(), - &data_dumper); + AdaptiveFirFilter filter(config.filter.main.length_blocks, + DetectOptimization(), &data_dumper); RenderSignalAnalyzer analyzer; SubtractorOutput output; MainFilterUpdateGain gain( - config.filter.leakage_converged, config.filter.leakage_diverged, - config.filter.main_noise_gate, config.filter.error_floor); + config.filter.main.leakage_converged, config.filter.main.leakage_diverged, + config.filter.main.noise_gate, config.filter.main.error_floor); std::array render_power; render_power.fill(0.f); EXPECT_DEATH( diff --git a/modules/audio_processing/aec3/render_delay_buffer.cc b/modules/audio_processing/aec3/render_delay_buffer.cc index cdc90788f1..3181bae2cb 100644 --- a/modules/audio_processing/aec3/render_delay_buffer.cc +++ b/modules/audio_processing/aec3/render_delay_buffer.cc @@ -158,7 +158,7 @@ RenderDelayBufferImpl::RenderDelayBufferImpl(const EchoCanceller3Config& config, : kBlockSize)), blocks_(GetRenderDelayBufferSize(config.delay.down_sampling_factor, config.delay.num_filters, - config.filter.length_blocks), + config.filter.main.length_blocks), num_bands, kBlockSize), spectra_(blocks_.buffer.size(), kFftLengthBy2Plus1), @@ -171,7 +171,7 @@ RenderDelayBufferImpl::RenderDelayBufferImpl(const EchoCanceller3Config& config, zero_block_(num_bands, std::vector(kBlockSize, 0.f)), fft_(), render_ds_(sub_block_size_, 0.f), - buffer_headroom_(config.filter.length_blocks) { + buffer_headroom_(config.filter.main.length_blocks) { RTC_DCHECK_EQ(blocks_.buffer.size(), ffts_.buffer.size()); RTC_DCHECK_EQ(spectra_.buffer.size(), ffts_.buffer.size()); diff --git a/modules/audio_processing/aec3/residual_echo_estimator.cc b/modules/audio_processing/aec3/residual_echo_estimator.cc index e34d7abac5..17a70e1b1f 100644 --- a/modules/audio_processing/aec3/residual_echo_estimator.cc +++ b/modules/audio_processing/aec3/residual_echo_estimator.cc @@ -77,7 +77,7 @@ void RenderNoisePower( } // namespace ResidualEchoEstimator::ResidualEchoEstimator(const EchoCanceller3Config& config) - : config_(config), S2_old_(config_.filter.length_blocks) { + : config_(config), S2_old_(config_.filter.main.length_blocks) { Reset(); } @@ -131,7 +131,8 @@ void ResidualEchoEstimator::Estimate( if (aec_state.SaturatedEcho()) { // TODO(peah): Modify to make sense theoretically. AddEchoReverb(*R2, aec_state.SaturatedEcho(), - config_.filter.length_blocks, aec_state.ReverbDecay(), R2); + config_.filter.main.length_blocks, aec_state.ReverbDecay(), + R2); } } diff --git a/modules/audio_processing/aec3/residual_echo_estimator_unittest.cc b/modules/audio_processing/aec3/residual_echo_estimator_unittest.cc index 80b6cd6fe5..e617a168ea 100644 --- a/modules/audio_processing/aec3/residual_echo_estimator_unittest.cc +++ b/modules/audio_processing/aec3/residual_echo_estimator_unittest.cc @@ -70,7 +70,8 @@ TEST(ResidualEchoEstimator, DISABLED_BasicTest) { H2[2].fill(10.f); H2[2][0] = 0.1f; - std::vector h(GetTimeDomainLength(config.filter.length_blocks), 0.f); + std::vector h(GetTimeDomainLength(config.filter.main.length_blocks), + 0.f); s.fill(100.f); diff --git a/modules/audio_processing/aec3/shadow_filter_update_gain_unittest.cc b/modules/audio_processing/aec3/shadow_filter_update_gain_unittest.cc index 34d4a7b8af..5270cea9c5 100644 --- a/modules/audio_processing/aec3/shadow_filter_update_gain_unittest.cc +++ b/modules/audio_processing/aec3/shadow_filter_update_gain_unittest.cc @@ -38,10 +38,10 @@ void RunFilterUpdateTest(int num_blocks_to_process, FftData* G_last_block) { ApmDataDumper data_dumper(42); EchoCanceller3Config config; - config.filter.length_blocks = filter_length_blocks; - AdaptiveFirFilter main_filter(config.filter.length_blocks, + config.filter.main.length_blocks = filter_length_blocks; + AdaptiveFirFilter main_filter(config.filter.main.length_blocks, DetectOptimization(), &data_dumper); - AdaptiveFirFilter shadow_filter(config.filter.length_blocks, + AdaptiveFirFilter shadow_filter(config.filter.shadow.length_blocks, DetectOptimization(), &data_dumper); Aec3Fft fft; @@ -52,8 +52,8 @@ void RunFilterUpdateTest(int num_blocks_to_process, std::array x_old; x_old.fill(0.f); - ShadowFilterUpdateGain shadow_gain(config.filter.shadow_rate, - config.filter.shadow_noise_gate); + ShadowFilterUpdateGain shadow_gain(config.filter.shadow.rate, + config.filter.shadow.noise_gate); Random random_generator(42U); std::vector> x(3, std::vector(kBlockSize, 0.f)); std::vector y(kBlockSize, 0.f); diff --git a/modules/audio_processing/aec3/subtractor.cc b/modules/audio_processing/aec3/subtractor.cc index 81aba7f5e5..6024a1a8f4 100644 --- a/modules/audio_processing/aec3/subtractor.cc +++ b/modules/audio_processing/aec3/subtractor.cc @@ -51,14 +51,22 @@ Subtractor::Subtractor(const EchoCanceller3Config& config, : fft_(), data_dumper_(data_dumper), optimization_(optimization), - main_filter_(config.filter.length_blocks, optimization, data_dumper_), - shadow_filter_(config.filter.length_blocks, optimization, data_dumper_), - G_main_(config.filter.leakage_converged, - config.filter.leakage_diverged, - config.filter.main_noise_gate, - config.filter.error_floor), - G_shadow_(config.filter.shadow_rate, config.filter.shadow_noise_gate) { + main_filter_(config.filter.main.length_blocks, + optimization, + data_dumper_), + shadow_filter_(config.filter.shadow.length_blocks, + optimization, + data_dumper_), + G_main_(config.filter.main.leakage_converged, + config.filter.main.leakage_diverged, + config.filter.main.noise_gate, + config.filter.main.error_floor), + G_shadow_(config.filter.shadow.rate, config.filter.shadow.noise_gate) { RTC_DCHECK(data_dumper_); + // Currently, the rest of AEC3 requires the main and shadow filter lengths to + // be identical. + RTC_DCHECK_EQ(config.filter.main.length_blocks, + config.filter.shadow.length_blocks); } Subtractor::~Subtractor() = default; diff --git a/modules/audio_processing/aec3/subtractor_unittest.cc b/modules/audio_processing/aec3/subtractor_unittest.cc index 11cb2e46d9..32221563a9 100644 --- a/modules/audio_processing/aec3/subtractor_unittest.cc +++ b/modules/audio_processing/aec3/subtractor_unittest.cc @@ -30,7 +30,8 @@ float RunSubtractorTest(int num_blocks_to_process, const std::vector& blocks_with_echo_path_changes) { ApmDataDumper data_dumper(42); EchoCanceller3Config config; - config.filter.length_blocks = filter_length_blocks; + config.filter.main.length_blocks = config.filter.shadow.length_blocks = + filter_length_blocks; Subtractor subtractor(config, &data_dumper, DetectOptimization()); std::vector> x(3, std::vector(kBlockSize, 0.f)); std::vector y(kBlockSize, 0.f); diff --git a/modules/audio_processing/include/audio_processing.h b/modules/audio_processing/include/audio_processing.h index 6f7cda0da1..4f68a6d0cb 100644 --- a/modules/audio_processing/include/audio_processing.h +++ b/modules/audio_processing/include/audio_processing.h @@ -1244,13 +1244,22 @@ struct EchoCanceller3Config { } delay; struct Filter { - size_t length_blocks = 12; - float shadow_rate = 0.1f; - float leakage_converged = 0.005f; - float leakage_diverged = 0.05f; - float error_floor = 0.001f; - float main_noise_gate = 20075344.f; - float shadow_noise_gate = 20075344.f; + struct MainConfiguration { + size_t length_blocks; + float leakage_converged; + float leakage_diverged; + float error_floor; + float noise_gate; + }; + + struct ShadowConfiguration { + size_t length_blocks; + float rate; + float noise_gate; + }; + + MainConfiguration main = {12, 0.005f, 0.05f, 0.001f, 20075344.f}; + ShadowConfiguration shadow = {12, 0.1f, 20075344.f}; } filter; struct Erle {