From fe4d67339339066f14d84c2c37661a6d013c9d7c Mon Sep 17 00:00:00 2001 From: Gustaf Ullberg Date: Thu, 16 Nov 2017 09:31:27 +0100 Subject: [PATCH] Compute ERL 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: I7160361b3468bb24cef9e6d390f10b23b988edd3 Reviewed-on: https://webrtc-review.googlesource.com/23242 Reviewed-by: Per Ã…hgren Commit-Queue: Gustaf Ullberg Cr-Commit-Position: refs/heads/master@{#20713} --- .../audio_processing/aec3/erl_estimator.cc | 23 ++++++++++++++++++- modules/audio_processing/aec3/erl_estimator.h | 3 +++ .../aec3/erl_estimator_unittest.cc | 12 ++++++---- 3 files changed, 32 insertions(+), 6 deletions(-) diff --git a/modules/audio_processing/aec3/erl_estimator.cc b/modules/audio_processing/aec3/erl_estimator.cc index 7923c0da50..3f12ba41a1 100644 --- a/modules/audio_processing/aec3/erl_estimator.cc +++ b/modules/audio_processing/aec3/erl_estimator.cc @@ -11,6 +11,7 @@ #include "modules/audio_processing/aec3/erl_estimator.h" #include +#include namespace webrtc { @@ -24,6 +25,8 @@ constexpr float kMaxErl = 1000.f; ErlEstimator::ErlEstimator() { erl_.fill(kMaxErl); hold_counters_.fill(0); + erl_time_domain_ = kMaxErl; + hold_counter_time_domain_ = 0; } ErlEstimator::~ErlEstimator() = default; @@ -43,7 +46,7 @@ void ErlEstimator::Update( const float new_erl = Y2[k] / X2[k]; if (new_erl < erl_[k]) { hold_counters_[k - 1] = 1000; - erl_[k] += 0.1 * (new_erl - erl_[k]); + erl_[k] += 0.1f * (new_erl - erl_[k]); erl_[k] = std::max(erl_[k], kMinErl); } } @@ -58,6 +61,24 @@ void ErlEstimator::Update( erl_[0] = erl_[1]; erl_[kFftLengthBy2] = erl_[kFftLengthBy2 - 1]; + + // Compute ERL over all frequency bins. + const float X2_sum = std::accumulate(X2.begin(), X2.end(), 0.0f); + + if (X2_sum > kX2Min * X2.size()) { + const float Y2_sum = std::accumulate(Y2.begin(), Y2.end(), 0.0f); + const float new_erl = Y2_sum / X2_sum; + if (new_erl < erl_time_domain_) { + hold_counter_time_domain_ = 1000; + erl_time_domain_ += 0.1f * (new_erl - erl_time_domain_); + erl_time_domain_ = std::max(erl_time_domain_, kMinErl); + } + } + + --hold_counter_time_domain_; + erl_time_domain_ = (hold_counter_time_domain_ > 0) + ? erl_time_domain_ + : std::min(kMaxErl, 2.f * erl_time_domain_); } } // namespace webrtc diff --git a/modules/audio_processing/aec3/erl_estimator.h b/modules/audio_processing/aec3/erl_estimator.h index 1fe12fb6dd..24b3f4b104 100644 --- a/modules/audio_processing/aec3/erl_estimator.h +++ b/modules/audio_processing/aec3/erl_estimator.h @@ -30,10 +30,13 @@ class ErlEstimator { // Returns the most recent ERL estimate. const std::array& Erl() const { return erl_; } + float ErlTimeDomain() const { return erl_time_domain_; } private: std::array erl_; std::array hold_counters_; + float erl_time_domain_; + int hold_counter_time_domain_; RTC_DISALLOW_COPY_AND_ASSIGN(ErlEstimator); }; diff --git a/modules/audio_processing/aec3/erl_estimator_unittest.cc b/modules/audio_processing/aec3/erl_estimator_unittest.cc index 3fbaec0e98..a406581001 100644 --- a/modules/audio_processing/aec3/erl_estimator_unittest.cc +++ b/modules/audio_processing/aec3/erl_estimator_unittest.cc @@ -17,9 +17,11 @@ namespace webrtc { namespace { void VerifyErl(const std::array& erl, + float erl_time_domain, float reference) { std::for_each(erl.begin(), erl.end(), [reference](float a) { EXPECT_NEAR(reference, a, 0.001); }); + EXPECT_NEAR(reference, erl_time_domain, 0.001); } } // namespace @@ -37,7 +39,7 @@ TEST(ErlEstimator, Estimates) { for (size_t k = 0; k < 200; ++k) { estimator.Update(X2, Y2); } - VerifyErl(estimator.Erl(), 10.f); + VerifyErl(estimator.Erl(), estimator.ErlTimeDomain(), 10.f); // Verifies that the ERL is not immediately increased when the ERL in the data // increases. @@ -45,18 +47,18 @@ TEST(ErlEstimator, Estimates) { for (size_t k = 0; k < 998; ++k) { estimator.Update(X2, Y2); } - VerifyErl(estimator.Erl(), 10.f); + VerifyErl(estimator.Erl(), estimator.ErlTimeDomain(), 10.f); // Verifies that the rate of increase is 3 dB. estimator.Update(X2, Y2); - VerifyErl(estimator.Erl(), 20.f); + VerifyErl(estimator.Erl(), estimator.ErlTimeDomain(), 20.f); // Verifies that the maximum ERL is achieved when there are no low RLE // estimates. for (size_t k = 0; k < 1000; ++k) { estimator.Update(X2, Y2); } - VerifyErl(estimator.Erl(), 1000.f); + VerifyErl(estimator.Erl(), estimator.ErlTimeDomain(), 1000.f); // Verifies that the ERL estimate is is not updated for low-level signals X2.fill(1000.f * 1000.f); @@ -64,7 +66,7 @@ TEST(ErlEstimator, Estimates) { for (size_t k = 0; k < 200; ++k) { estimator.Update(X2, Y2); } - VerifyErl(estimator.Erl(), 1000.f); + VerifyErl(estimator.Erl(), estimator.ErlTimeDomain(), 1000.f); } } // namespace webrtc