From 2bab5ad3b10bf9b0bfa5379d53e29ddf7aa7dcf5 Mon Sep 17 00:00:00 2001 From: Gustaf Ullberg Date: Mon, 15 Apr 2019 17:15:37 +0200 Subject: [PATCH] AEC3: Avoid using filter output in suppression gain computation in non-linear mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As non-linear mode uses a suppressed version of y (not e) as output, this change uses Y2, rather than E2, as nearend spectrum when computing the suppression gains. E2 is still used in linear mode. This change also affects how the minimum suppression gains are calculated. The minimum gain is now min_echo_power / weighted_residual_echo. Bug: webrtc:10550 Change-Id: I2904c5a09dd64b06bf25eb5a37c18dab50297794 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/133023 Commit-Queue: Gustaf Ullberg Reviewed-by: Per Ã…hgren Cr-Commit-Position: refs/heads/master@{#27629} --- modules/audio_processing/aec3/echo_remover.cc | 17 ++++++++++++----- .../audio_processing/aec3/suppression_gain.cc | 19 ++++++++----------- .../audio_processing/aec3/suppression_gain.h | 4 +--- .../aec3/suppression_gain_unittest.cc | 8 ++++---- .../output_data_float.pb.sha1 | 2 +- 5 files changed, 26 insertions(+), 24 deletions(-) diff --git a/modules/audio_processing/aec3/echo_remover.cc b/modules/audio_processing/aec3/echo_remover.cc index cb24248292..493916c585 100644 --- a/modules/audio_processing/aec3/echo_remover.cc +++ b/modules/audio_processing/aec3/echo_remover.cc @@ -290,15 +290,22 @@ void EchoRemoverImpl::ProcessCapture( // Estimate the comfort noise. cng_.Compute(aec_state_, Y2, &comfort_noise, &high_band_comfort_noise); - // Compute and apply the suppression gain. + // Suppressor echo estimate. const auto& echo_spectrum = aec_state_.UsableLinearEstimate() ? S2_linear : R2; - std::array E2_bounded; - std::transform(E2.begin(), E2.end(), Y2.begin(), E2_bounded.begin(), - [](float a, float b) { return std::min(a, b); }); + // Suppressor nearend estimate. + std::array nearend_spectrum_bounded; + if (aec_state_.UsableLinearEstimate()) { + std::transform(E2.begin(), E2.end(), Y2.begin(), + nearend_spectrum_bounded.begin(), + [](float a, float b) { return std::min(a, b); }); + } + auto& nearend_spectrum = + aec_state_.UsableLinearEstimate() ? nearend_spectrum_bounded : Y2; - suppression_gain_.GetGain(E2, E2_bounded, echo_spectrum, R2, + // Compute and apply the suppression gain. + suppression_gain_.GetGain(nearend_spectrum, echo_spectrum, R2, cng_.NoiseSpectrum(), render_signal_analyzer_, aec_state_, x, &high_bands_gain, &G); diff --git a/modules/audio_processing/aec3/suppression_gain.cc b/modules/audio_processing/aec3/suppression_gain.cc index 935980f6f1..b741a71651 100644 --- a/modules/audio_processing/aec3/suppression_gain.cc +++ b/modules/audio_processing/aec3/suppression_gain.cc @@ -197,7 +197,6 @@ void SuppressionGain::GainToNoAudibleEcho( // Compute the minimum gain as the attenuating gain to put the signal just // above the zero sample values. void SuppressionGain::GetMinGain( - rtc::ArrayView suppressor_input, rtc::ArrayView weighted_residual_echo, bool low_noise_render, bool saturated_echo, @@ -207,10 +206,10 @@ void SuppressionGain::GetMinGain( low_noise_render ? config_.echo_audibility.low_render_limit : config_.echo_audibility.normal_render_limit; - for (size_t k = 0; k < suppressor_input.size(); ++k) { - const float denom = - std::min(suppressor_input[k], weighted_residual_echo[k]); - min_gain[k] = denom > 0.f ? min_echo_power / denom : 1.f; + for (size_t k = 0; k < min_gain.size(); ++k) { + min_gain[k] = weighted_residual_echo[k] > 0.f + ? min_echo_power / weighted_residual_echo[k] + : 1.f; min_gain[k] = std::min(min_gain[k], 1.f); } for (size_t k = 0; k < 6; ++k) { @@ -259,8 +258,8 @@ void SuppressionGain::LowerBandGain( WeightEchoForAudibility(config_, residual_echo, weighted_residual_echo); std::array min_gain; - GetMinGain(suppressor_input, weighted_residual_echo, low_noise_render, - saturated_echo, min_gain); + GetMinGain(weighted_residual_echo, low_noise_render, saturated_echo, + min_gain); std::array max_gain; GetMaxGain(max_gain); @@ -311,7 +310,6 @@ SuppressionGain::SuppressionGain(const EchoCanceller3Config& config, SuppressionGain::~SuppressionGain() = default; void SuppressionGain::GetGain( - const std::array& suppressor_input_spectrum, const std::array& nearend_spectrum, const std::array& echo_spectrum, const std::array& residual_echo_spectrum, @@ -340,9 +338,8 @@ void SuppressionGain::GetGain( // Compute gain for the lower band. bool low_noise_render = low_render_detector_.Detect(render); - LowerBandGain(low_noise_render, aec_state, suppressor_input_spectrum, - nearend_average, residual_echo_spectrum, comfort_noise_spectrum, - low_band_gain); + LowerBandGain(low_noise_render, aec_state, nearend_spectrum, nearend_average, + residual_echo_spectrum, comfort_noise_spectrum, low_band_gain); // Compute the gain for the upper bands. const absl::optional narrow_peak_band = diff --git a/modules/audio_processing/aec3/suppression_gain.h b/modules/audio_processing/aec3/suppression_gain.h index 317f43c5f0..2b34dbe46b 100644 --- a/modules/audio_processing/aec3/suppression_gain.h +++ b/modules/audio_processing/aec3/suppression_gain.h @@ -35,7 +35,6 @@ class SuppressionGain { int sample_rate_hz); ~SuppressionGain(); void GetGain( - const std::array& suppressor_input_spectrum, const std::array& nearend_spectrum, const std::array& echo_spectrum, const std::array& residual_echo_spectrum, @@ -76,8 +75,7 @@ class SuppressionGain { const std::array& comfort_noise, std::array* gain); - void GetMinGain(rtc::ArrayView suppressor_input, - rtc::ArrayView weighted_residual_echo, + void GetMinGain(rtc::ArrayView weighted_residual_echo, bool low_noise_render, bool saturated_echo, rtc::ArrayView min_gain) const; diff --git a/modules/audio_processing/aec3/suppression_gain_unittest.cc b/modules/audio_processing/aec3/suppression_gain_unittest.cc index fc721fe009..b110e0a00a 100644 --- a/modules/audio_processing/aec3/suppression_gain_unittest.cc +++ b/modules/audio_processing/aec3/suppression_gain_unittest.cc @@ -45,7 +45,7 @@ TEST(SuppressionGain, NullOutputGains) { AecState aec_state(EchoCanceller3Config{}); EXPECT_DEATH( SuppressionGain(EchoCanceller3Config{}, DetectOptimization(), 16000) - .GetGain(E2, E2, S2, R2, N2, + .GetGain(E2, S2, R2, N2, RenderSignalAnalyzer((EchoCanceller3Config{})), aec_state, std::vector>( 3, std::vector(kBlockSize, 0.f)), @@ -100,7 +100,7 @@ TEST(SuppressionGain, BasicGainComputation) { subtractor.FilterImpulseResponse(), *render_delay_buffer->GetRenderBuffer(), E2, Y2, output, y); - suppression_gain.GetGain(E2, E2, S2, R2, N2, analyzer, aec_state, x, + suppression_gain.GetGain(E2, S2, R2, N2, analyzer, aec_state, x, &high_bands_gain, &g); } std::for_each(g.begin(), g.end(), @@ -118,7 +118,7 @@ TEST(SuppressionGain, BasicGainComputation) { subtractor.FilterImpulseResponse(), *render_delay_buffer->GetRenderBuffer(), E2, Y2, output, y); - suppression_gain.GetGain(E2, E2, S2, R2, N2, analyzer, aec_state, x, + suppression_gain.GetGain(E2, S2, R2, N2, analyzer, aec_state, x, &high_bands_gain, &g); } std::for_each(g.begin(), g.end(), @@ -129,7 +129,7 @@ TEST(SuppressionGain, BasicGainComputation) { R2.fill(10000000000000.f); for (int k = 0; k < 10; ++k) { - suppression_gain.GetGain(E2, E2, S2, R2, N2, analyzer, aec_state, x, + suppression_gain.GetGain(E2, S2, R2, N2, analyzer, aec_state, x, &high_bands_gain, &g); } std::for_each(g.begin(), g.end(), diff --git a/resources/audio_processing/output_data_float.pb.sha1 b/resources/audio_processing/output_data_float.pb.sha1 index 907ebfd9a9..e9c065b7e2 100644 --- a/resources/audio_processing/output_data_float.pb.sha1 +++ b/resources/audio_processing/output_data_float.pb.sha1 @@ -1 +1 @@ -169276fe22bbeb1c06e0ed1a9df8149c5dbf8f80 \ No newline at end of file +bc19d9e9fd9503cad02f3b0c21cbd63ed3c5f22c \ No newline at end of file