diff --git a/modules/audio_processing/aec3/adaptive_fir_filter_unittest.cc b/modules/audio_processing/aec3/adaptive_fir_filter_unittest.cc index f6a2f35852..47566c2928 100644 --- a/modules/audio_processing/aec3/adaptive_fir_filter_unittest.cc +++ b/modules/audio_processing/aec3/adaptive_fir_filter_unittest.cc @@ -316,7 +316,8 @@ TEST(AdaptiveFirFilter, FilterAndAdapt) { config.delay.default_delay = 1; std::unique_ptr render_delay_buffer( RenderDelayBuffer::Create(config, 3)); - ShadowFilterUpdateGain gain; + 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/main_filter_update_gain.cc b/modules/audio_processing/aec3/main_filter_update_gain.cc index 45253cd927..a9b4999faf 100644 --- a/modules/audio_processing/aec3/main_filter_update_gain.cc +++ b/modules/audio_processing/aec3/main_filter_update_gain.cc @@ -28,9 +28,14 @@ constexpr int kPoorExcitationCounterInitial = 1000; int MainFilterUpdateGain::instance_count_ = 0; -MainFilterUpdateGain::MainFilterUpdateGain() +MainFilterUpdateGain::MainFilterUpdateGain(float leakage_converged, + float leakage_diverged, + float noise_gate_power) : data_dumper_( new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))), + leakage_converged_(leakage_converged), + leakage_diverged_(leakage_diverged), + noise_gate_power_(noise_gate_power), poor_excitation_counter_(kPoorExcitationCounterInitial) { H_error_.fill(kHErrorInitial); } @@ -75,11 +80,10 @@ void MainFilterUpdateGain::Compute( G->im.fill(0.f); } else { // Corresponds to WGN of power -39 dBFS. - constexpr float kNoiseGatePower = 220075344.f; std::array mu; // mu = H_error / (0.5* H_error* X2 + n * E2). for (size_t k = 0; k < kFftLengthBy2Plus1; ++k) { - mu[k] = X2[k] > kNoiseGatePower + mu[k] = X2[k] > noise_gate_power_ ? H_error_[k] / (0.5f * H_error_[k] * X2[k] + size_partitions * E2_main[k]) : 0.f; @@ -102,11 +106,9 @@ void MainFilterUpdateGain::Compute( // H_error = H_error + factor * erl. std::array H_error_increase; - constexpr float kErlScaleAccurate = 1.f / 100.0f; - constexpr float kErlScaleInaccurate = 1.f / 60.0f; std::transform(E2_shadow.begin(), E2_shadow.end(), E2_main.begin(), H_error_increase.begin(), [&](float a, float b) { - return a >= b ? kErlScaleAccurate : kErlScaleInaccurate; + return a >= b ? leakage_converged_ : leakage_diverged_; }); std::transform(erl.begin(), erl.end(), H_error_increase.begin(), H_error_increase.begin(), std::multiplies()); diff --git a/modules/audio_processing/aec3/main_filter_update_gain.h b/modules/audio_processing/aec3/main_filter_update_gain.h index 92ec02afd0..138402dc17 100644 --- a/modules/audio_processing/aec3/main_filter_update_gain.h +++ b/modules/audio_processing/aec3/main_filter_update_gain.h @@ -28,7 +28,9 @@ class ApmDataDumper; // Provides functionality for computing the adaptive gain for the main filter. class MainFilterUpdateGain { public: - MainFilterUpdateGain(); + MainFilterUpdateGain(float leakage_converged, + float leakage_diverged, + float noise_gate_power); ~MainFilterUpdateGain(); // Takes action in the case of a known echo path change. @@ -45,6 +47,9 @@ class MainFilterUpdateGain { private: static int instance_count_; std::unique_ptr data_dumper_; + const float leakage_converged_; + const float leakage_diverged_; + const float noise_gate_power_; std::array H_error_; size_t poor_excitation_counter_; size_t call_counter_ = 0; 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 a873d1979e..297b9b1d33 100644 --- a/modules/audio_processing/aec3/main_filter_update_gain_unittest.cc +++ b/modules/audio_processing/aec3/main_filter_update_gain_unittest.cc @@ -50,8 +50,11 @@ void RunFilterUpdateTest(int num_blocks_to_process, Aec3Fft fft; std::array x_old; x_old.fill(0.f); - ShadowFilterUpdateGain shadow_gain; - MainFilterUpdateGain main_gain; + 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); Random random_generator(42U); std::vector> x(3, std::vector(kBlockSize, 0.f)); std::vector y(kBlockSize, 0.f); @@ -190,7 +193,9 @@ TEST(MainFilterUpdateGain, NullDataOutputGain) { RenderDelayBuffer::Create(config, 3)); RenderSignalAnalyzer analyzer; SubtractorOutput output; - MainFilterUpdateGain gain; + MainFilterUpdateGain gain(config.filter.leakage_converged, + config.filter.leakage_diverged, + config.filter.main_noise_gate); EXPECT_DEATH(gain.Compute(*render_delay_buffer->GetRenderBuffer(), analyzer, output, filter, false, nullptr), ""); diff --git a/modules/audio_processing/aec3/shadow_filter_update_gain.cc b/modules/audio_processing/aec3/shadow_filter_update_gain.cc index 464a0261d9..8fdf2587c2 100644 --- a/modules/audio_processing/aec3/shadow_filter_update_gain.cc +++ b/modules/audio_processing/aec3/shadow_filter_update_gain.cc @@ -17,6 +17,10 @@ namespace webrtc { +ShadowFilterUpdateGain::ShadowFilterUpdateGain(float rate, + float noise_gate_power) + : rate_(rate), noise_gate_power_(noise_gate_power) {} + void ShadowFilterUpdateGain::HandleEchoPathChange() { // TODO(peah): Check whether this counter should instead be initialized to a // large value. @@ -47,13 +51,10 @@ void ShadowFilterUpdateGain::Compute( } // Compute mu. - // Corresponds to WGN of power -39 dBFS. - constexpr float kNoiseGatePower = 220075344.f; - constexpr float kMuFixed = .5f; std::array mu; auto X2 = render_buffer.SpectralSum(size_partitions); std::transform(X2.begin(), X2.end(), mu.begin(), [&](float a) { - return a > kNoiseGatePower ? kMuFixed / a : 0.f; + return a > noise_gate_power_ ? rate_ / a : 0.f; }); // Avoid updating the filter close to narrow bands in the render signals. diff --git a/modules/audio_processing/aec3/shadow_filter_update_gain.h b/modules/audio_processing/aec3/shadow_filter_update_gain.h index 8c72cf487b..5cc4b02095 100644 --- a/modules/audio_processing/aec3/shadow_filter_update_gain.h +++ b/modules/audio_processing/aec3/shadow_filter_update_gain.h @@ -21,6 +21,8 @@ namespace webrtc { // Provides functionality for computing the fixed gain for the shadow filter. class ShadowFilterUpdateGain { public: + ShadowFilterUpdateGain(float rate, float noise_gate_power); + // Takes action in the case of a known echo path change. void HandleEchoPathChange(); @@ -33,6 +35,8 @@ class ShadowFilterUpdateGain { FftData* G); private: + const float rate_; + const float noise_gate_power_; // TODO(peah): Check whether this counter should instead be initialized to a // large value. size_t poor_signal_excitation_counter_ = 0; 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 596cb86ee2..4c7f76ec25 100644 --- a/modules/audio_processing/aec3/shadow_filter_update_gain_unittest.cc +++ b/modules/audio_processing/aec3/shadow_filter_update_gain_unittest.cc @@ -52,7 +52,8 @@ void RunFilterUpdateTest(int num_blocks_to_process, std::array x_old; x_old.fill(0.f); - ShadowFilterUpdateGain shadow_gain; + 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); @@ -134,7 +135,7 @@ TEST(ShadowFilterUpdateGain, NullDataOutputGain) { RenderBuffer render_buffer(1, &block_buffer, &spectrum_buffer, &fft_buffer); RenderSignalAnalyzer analyzer; FftData E; - ShadowFilterUpdateGain gain; + ShadowFilterUpdateGain gain(0.5f, 220075344.f); EXPECT_DEATH(gain.Compute(render_buffer, analyzer, E, 1, false, nullptr), ""); } diff --git a/modules/audio_processing/aec3/subtractor.cc b/modules/audio_processing/aec3/subtractor.cc index 9e690f8491..cd2d9ac1c7 100644 --- a/modules/audio_processing/aec3/subtractor.cc +++ b/modules/audio_processing/aec3/subtractor.cc @@ -52,7 +52,11 @@ Subtractor::Subtractor(const EchoCanceller3Config& config, data_dumper_(data_dumper), optimization_(optimization), main_filter_(config.filter.length_blocks, optimization, data_dumper_), - shadow_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), + G_shadow_(config.filter.shadow_rate, config.filter.shadow_noise_gate) { RTC_DCHECK(data_dumper_); } diff --git a/modules/audio_processing/include/audio_processing.h b/modules/audio_processing/include/audio_processing.h index 4aeb9f44a2..b750c6960e 100644 --- a/modules/audio_processing/include/audio_processing.h +++ b/modules/audio_processing/include/audio_processing.h @@ -1160,6 +1160,11 @@ struct EchoCanceller3Config { struct Filter { size_t length_blocks = 12; + float shadow_rate = 0.5f; + float leakage_converged = 0.01f; + float leakage_diverged = 1.f / 60.f; + float main_noise_gate = 220075344.f; + float shadow_noise_gate = 220075344.f; } filter; struct Erle {