From c9b89aaa16ef8c2c58ef1a4b21880b92ae7c850a Mon Sep 17 00:00:00 2001 From: Gustaf Ullberg Date: Thu, 16 Nov 2017 11:20:59 +0100 Subject: [PATCH] Compute ERLE over all frequency bins in AEC3. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bug: webrtc:8533 Change-Id: I0a373f22ec377b226d3bc7d88d3245a99e18c7a0 Reviewed-on: https://webrtc-review.googlesource.com/23621 Reviewed-by: Per Ã…hgren Commit-Queue: Gustaf Ullberg Cr-Commit-Position: refs/heads/master@{#20709} --- .../audio_processing/aec3/erle_estimator.cc | 21 +++++++++++++++++++ .../audio_processing/aec3/erle_estimator.h | 3 +++ .../aec3/erle_estimator_unittest.cc | 10 +++++---- 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/modules/audio_processing/aec3/erle_estimator.cc b/modules/audio_processing/aec3/erle_estimator.cc index 2b669c93d8..9f7efd4295 100644 --- a/modules/audio_processing/aec3/erle_estimator.cc +++ b/modules/audio_processing/aec3/erle_estimator.cc @@ -11,6 +11,7 @@ #include "modules/audio_processing/aec3/erle_estimator.h" #include +#include #include "rtc_base/safe_minmax.h" @@ -24,6 +25,8 @@ ErleEstimator::ErleEstimator(float min_erle, max_erle_hf_(max_erle_hf) { erle_.fill(min_erle_); hold_counters_.fill(0); + erle_time_domain_ = min_erle_; + hold_counter_time_domain_ = 0; } ErleEstimator::~ErleEstimator() = default; @@ -64,6 +67,24 @@ void ErleEstimator::Update( erle_[0] = erle_[1]; erle_[kFftLengthBy2] = erle_[kFftLengthBy2 - 1]; + + // Compute ERLE over all frequency bins. + const float X2_sum = std::accumulate(X2.begin(), X2.end(), 0.0f); + const float E2_sum = std::accumulate(E2.begin(), E2.end(), 0.0f); + if (X2_sum > kX2Min * X2.size() && E2_sum > 0.f) { + const float Y2_sum = std::accumulate(Y2.begin(), Y2.end(), 0.0f); + const float new_erle = Y2_sum / E2_sum; + if (new_erle > erle_time_domain_) { + hold_counter_time_domain_ = 100; + erle_time_domain_ += 0.1f * (new_erle - erle_time_domain_); + erle_time_domain_ = + rtc::SafeClamp(erle_time_domain_, min_erle_, max_erle_lf_); + } + } + --hold_counter_time_domain_; + erle_time_domain_ = (hold_counter_time_domain_ > 0) + ? erle_time_domain_ + : std::max(min_erle_, 0.97f * erle_time_domain_); } } // namespace webrtc diff --git a/modules/audio_processing/aec3/erle_estimator.h b/modules/audio_processing/aec3/erle_estimator.h index 80c0387981..71fdfb50a5 100644 --- a/modules/audio_processing/aec3/erle_estimator.h +++ b/modules/audio_processing/aec3/erle_estimator.h @@ -31,10 +31,13 @@ class ErleEstimator { // Returns the most recent ERLE estimate. const std::array& Erle() const { return erle_; } + float ErleTimeDomain() { return erle_time_domain_; } private: std::array erle_; std::array hold_counters_; + float erle_time_domain_; + int hold_counter_time_domain_; const float min_erle_; const float max_erle_lf_; const float max_erle_hf_; diff --git a/modules/audio_processing/aec3/erle_estimator_unittest.cc b/modules/audio_processing/aec3/erle_estimator_unittest.cc index bc5ac193c5..f3dd7d9bbb 100644 --- a/modules/audio_processing/aec3/erle_estimator_unittest.cc +++ b/modules/audio_processing/aec3/erle_estimator_unittest.cc @@ -18,6 +18,7 @@ namespace { constexpr int kLowFrequencyLimit = kFftLengthBy2 / 2; void VerifyErle(const std::array& erle, + float erle_time_domain, float reference_lf, float reference_hf) { std::for_each( @@ -26,6 +27,7 @@ void VerifyErle(const std::array& erle, std::for_each( erle.begin() + kLowFrequencyLimit, erle.end(), [reference_hf](float a) { EXPECT_NEAR(reference_hf, a, 0.001); }); + EXPECT_NEAR(reference_lf, erle_time_domain, 0.001); } } // namespace @@ -45,7 +47,7 @@ TEST(ErleEstimator, Estimates) { for (size_t k = 0; k < 200; ++k) { estimator.Update(X2, Y2, E2); } - VerifyErle(estimator.Erle(), 8.f, 1.5f); + VerifyErle(estimator.Erle(), estimator.ErleTimeDomain(), 8.f, 1.5f); // Verifies that the ERLE is not immediately decreased when the ERLE in the // data decreases. @@ -53,13 +55,13 @@ TEST(ErleEstimator, Estimates) { for (size_t k = 0; k < 98; ++k) { estimator.Update(X2, Y2, E2); } - VerifyErle(estimator.Erle(), 8.f, 1.5f); + VerifyErle(estimator.Erle(), estimator.ErleTimeDomain(), 8.f, 1.5f); // Verifies that the minimum ERLE is eventually achieved. for (size_t k = 0; k < 1000; ++k) { estimator.Update(X2, Y2, E2); } - VerifyErle(estimator.Erle(), 1.f, 1.f); + VerifyErle(estimator.Erle(), estimator.ErleTimeDomain(), 1.f, 1.f); // Verifies that the ERLE estimate is is not updated for low-level render // signals. @@ -68,6 +70,6 @@ TEST(ErleEstimator, Estimates) { for (size_t k = 0; k < 200; ++k) { estimator.Update(X2, Y2, E2); } - VerifyErle(estimator.Erle(), 1.f, 1.f); + VerifyErle(estimator.Erle(), estimator.ErleTimeDomain(), 1.f, 1.f); } } // namespace webrtc