From a687812c7087ade6b9c92f1fc4d68eafe9180f02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20de=20Vicente=20Pe=C3=B1a?= Date: Tue, 28 Aug 2018 14:27:45 +0200 Subject: [PATCH] AEC3: option for enabling/disabling the onset detection for the ERLE in the configuration file. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit During this work a parameter is added to the configuration file for the AEC3 that allows to enable or disable the use of a different ERLE estimation for the render onsets. Bug: webrtc:9677 Change-Id: I467f2cd20683fee06b69c0ba51a90816c9e14f29 Reviewed-on: https://webrtc-review.googlesource.com/96082 Reviewed-by: Per Åhgren Commit-Queue: Per Åhgren Cr-Commit-Position: refs/heads/master@{#24470} --- api/audio/echo_canceller3_config.h | 1 + modules/audio_processing/aec3/aec_state.cc | 3 +- .../audio_processing/aec3/erle_estimator.cc | 46 +++++++++++-------- .../audio_processing/aec3/erle_estimator.h | 3 +- .../aec3/erle_estimator_unittest.cc | 16 +++---- .../test/audio_processing_simulator.cc | 1 + 6 files changed, 40 insertions(+), 30 deletions(-) diff --git a/api/audio/echo_canceller3_config.h b/api/audio/echo_canceller3_config.h index 67fe755c33..a142d52dd5 100644 --- a/api/audio/echo_canceller3_config.h +++ b/api/audio/echo_canceller3_config.h @@ -64,6 +64,7 @@ struct EchoCanceller3Config { float min = 1.f; float max_l = 4.f; float max_h = 1.5f; + bool onset_detection = true; } erle; struct EpStrength { diff --git a/modules/audio_processing/aec3/aec_state.cc b/modules/audio_processing/aec3/aec_state.cc index cfe4bdf39f..634df68818 100644 --- a/modules/audio_processing/aec3/aec_state.cc +++ b/modules/audio_processing/aec3/aec_state.cc @@ -228,7 +228,8 @@ void AecState::Update( // Update the ERL and ERLE measures. if (blocks_since_reset_ >= 2 * kNumBlocksPerSecond) { const auto& X2 = render_buffer.Spectrum(filter_delay_blocks_); - erle_estimator_.Update(X2, Y2, E2_main, converged_filter); + erle_estimator_.Update(X2, Y2, E2_main, converged_filter, + config_.erle.onset_detection); if (converged_filter) { erl_estimator_.Update(X2, Y2); } diff --git a/modules/audio_processing/aec3/erle_estimator.cc b/modules/audio_processing/aec3/erle_estimator.cc index 52ef8edf2f..317f00a38c 100644 --- a/modules/audio_processing/aec3/erle_estimator.cc +++ b/modules/audio_processing/aec3/erle_estimator.cc @@ -167,7 +167,8 @@ void ErleEstimator::ErleFreqInstantaneous::Reset() { void ErleEstimator::Update(rtc::ArrayView render_spectrum, rtc::ArrayView capture_spectrum, rtc::ArrayView subtractor_spectrum, - bool converged_filter) { + bool converged_filter, + bool onset_detection) { RTC_DCHECK_EQ(kFftLengthBy2Plus1, render_spectrum.size()); RTC_DCHECK_EQ(kFftLengthBy2Plus1, capture_spectrum.size()); RTC_DCHECK_EQ(kFftLengthBy2Plus1, subtractor_spectrum.size()); @@ -191,19 +192,22 @@ void ErleEstimator::Update(rtc::ArrayView render_spectrum, }; // Update the estimates in a clamped minimum statistics manner. - auto erle_update = [&](size_t start, size_t stop, float max_erle) { + auto erle_update = [&](size_t start, size_t stop, float max_erle, + bool onset_detection) { for (size_t k = start; k < stop; ++k) { if (X2[k] > kX2Min) { absl::optional new_erle = erle_freq_inst_.Update(Y2[k], E2[k], k); if (new_erle) { - if (coming_onset_[k]) { - coming_onset_[k] = false; - erle_onsets_[k] = - erle_band_update(erle_onsets_[k], new_erle.value(), 0.15f, 0.3f, - min_erle_, max_erle); + if (onset_detection) { + if (coming_onset_[k]) { + coming_onset_[k] = false; + erle_onsets_[k] = + erle_band_update(erle_onsets_[k], new_erle.value(), 0.15f, + 0.3f, min_erle_, max_erle); + } + hold_counters_[k] = kBlocksForOnsetDetection; } - hold_counters_[k] = kBlocksForOnsetDetection; erle_[k] = erle_band_update(erle_[k], new_erle.value(), 0.05f, 0.1f, min_erle_, max_erle); } @@ -216,20 +220,22 @@ void ErleEstimator::Update(rtc::ArrayView render_spectrum, // a minimum of the erle that can be estimated as that flag would // be false if the filter is performing poorly. constexpr size_t kFftLengthBy4 = kFftLengthBy2 / 2; - erle_update(1, kFftLengthBy4, max_erle_lf_); - erle_update(kFftLengthBy4, kFftLengthBy2, max_erle_hf_); + erle_update(1, kFftLengthBy4, max_erle_lf_, onset_detection); + erle_update(kFftLengthBy4, kFftLengthBy2, max_erle_hf_, onset_detection); } - for (size_t k = 1; k < kFftLengthBy2; ++k) { - hold_counters_[k]--; - if (hold_counters_[k] <= (kBlocksForOnsetDetection - kErleHold)) { - if (erle_[k] > erle_onsets_[k]) { - erle_[k] = std::max(erle_onsets_[k], 0.97f * erle_[k]); - RTC_DCHECK_LE(min_erle_, erle_[k]); - } - if (hold_counters_[k] <= 0) { - coming_onset_[k] = true; - hold_counters_[k] = 0; + if (onset_detection) { + for (size_t k = 1; k < kFftLengthBy2; ++k) { + hold_counters_[k]--; + if (hold_counters_[k] <= (kBlocksForOnsetDetection - kErleHold)) { + if (erle_[k] > erle_onsets_[k]) { + erle_[k] = std::max(erle_onsets_[k], 0.97f * erle_[k]); + RTC_DCHECK_LE(min_erle_, erle_[k]); + } + if (hold_counters_[k] <= 0) { + coming_onset_[k] = true; + hold_counters_[k] = 0; + } } } } diff --git a/modules/audio_processing/aec3/erle_estimator.h b/modules/audio_processing/aec3/erle_estimator.h index 19bc7b407d..32550f64df 100644 --- a/modules/audio_processing/aec3/erle_estimator.h +++ b/modules/audio_processing/aec3/erle_estimator.h @@ -31,7 +31,8 @@ class ErleEstimator { void Update(rtc::ArrayView render_spectrum, rtc::ArrayView capture_spectrum, rtc::ArrayView subtractor_spectrum, - bool converged_filter); + bool converged_filter, + bool onset_detection); // Returns the most recent ERLE estimate. const std::array& Erle() const { return erle_; } diff --git a/modules/audio_processing/aec3/erle_estimator_unittest.cc b/modules/audio_processing/aec3/erle_estimator_unittest.cc index 86ac5dfd1f..1687568529 100644 --- a/modules/audio_processing/aec3/erle_estimator_unittest.cc +++ b/modules/audio_processing/aec3/erle_estimator_unittest.cc @@ -10,8 +10,8 @@ #include -#include "modules/audio_processing/aec3/erle_estimator.h" #include "api/array_view.h" +#include "modules/audio_processing/aec3/erle_estimator.h" #include "test/gtest.h" namespace webrtc { @@ -74,7 +74,7 @@ TEST(ErleEstimator, VerifyErleIncreaseAndHold) { FormFarendFrame(&X2, &E2, &Y2, kTrueErle); for (size_t k = 0; k < 200; ++k) { - estimator.Update(X2, Y2, E2, true); + estimator.Update(X2, Y2, E2, true, true); } VerifyErle(estimator.Erle(), std::pow(2.f, estimator.ErleTimeDomainLog2()), kMaxErleLf, kMaxErleHf); @@ -83,7 +83,7 @@ TEST(ErleEstimator, VerifyErleIncreaseAndHold) { // Verifies that the ERLE is not immediately decreased during nearend // activity. for (size_t k = 0; k < 50; ++k) { - estimator.Update(X2, Y2, E2, true); + estimator.Update(X2, Y2, E2, true, true); } VerifyErle(estimator.Erle(), std::pow(2.f, estimator.ErleTimeDomainLog2()), kMaxErleLf, kMaxErleHf); @@ -99,21 +99,21 @@ TEST(ErleEstimator, VerifyErleTrackingOnOnsets) { for (size_t burst = 0; burst < 20; ++burst) { FormFarendFrame(&X2, &E2, &Y2, kTrueErleOnsets); for (size_t k = 0; k < 10; ++k) { - estimator.Update(X2, Y2, E2, true); + estimator.Update(X2, Y2, E2, true, true); } FormFarendFrame(&X2, &E2, &Y2, kTrueErle); for (size_t k = 0; k < 200; ++k) { - estimator.Update(X2, Y2, E2, true); + estimator.Update(X2, Y2, E2, true, true); } FormNearendFrame(&X2, &E2, &Y2); for (size_t k = 0; k < 300; ++k) { - estimator.Update(X2, Y2, E2, true); + estimator.Update(X2, Y2, E2, true, true); } } VerifyErleBands(estimator.ErleOnsets(), kMinErle, kMinErle); FormNearendFrame(&X2, &E2, &Y2); for (size_t k = 0; k < 1000; k++) { - estimator.Update(X2, Y2, E2, true); + estimator.Update(X2, Y2, E2, true, true); } // Verifies that during ne activity, Erle converges to the Erle for onsets. VerifyErle(estimator.Erle(), std::pow(2.f, estimator.ErleTimeDomainLog2()), @@ -131,7 +131,7 @@ TEST(ErleEstimator, VerifyNoErleUpdateDuringLowActivity) { X2.fill(1000.f * 1000.f); Y2.fill(10 * E2[0]); for (size_t k = 0; k < 200; ++k) { - estimator.Update(X2, Y2, E2, true); + estimator.Update(X2, Y2, E2, true, true); } VerifyErle(estimator.Erle(), std::pow(2.f, estimator.ErleTimeDomainLog2()), kMinErle, kMinErle); diff --git a/modules/audio_processing/test/audio_processing_simulator.cc b/modules/audio_processing/test/audio_processing_simulator.cc index 1ee907806b..c860251518 100644 --- a/modules/audio_processing/test/audio_processing_simulator.cc +++ b/modules/audio_processing/test/audio_processing_simulator.cc @@ -241,6 +241,7 @@ class Aec3ParametersParser { ReadParam(section, "min", &cfg.erle.min); ReadParam(section, "max_l", &cfg.erle.max_l); ReadParam(section, "max_h", &cfg.erle.max_h); + ReadParam(section, "onset_detection", &cfg.erle.onset_detection); } if (rtc::GetValueFromJsonObject(root, "ep_strength", §ion)) {