Compute ERLE over all frequency bins in AEC3.

Bug: webrtc:8533
Change-Id: I0a373f22ec377b226d3bc7d88d3245a99e18c7a0
Reviewed-on: https://webrtc-review.googlesource.com/23621
Reviewed-by: Per Åhgren <peah@webrtc.org>
Commit-Queue: Gustaf Ullberg <gustaf@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#20709}
This commit is contained in:
Gustaf Ullberg
2017-11-16 11:20:59 +01:00
committed by Commit Bot
parent 8b64fd8a85
commit c9b89aaa16
3 changed files with 30 additions and 4 deletions

View File

@ -11,6 +11,7 @@
#include "modules/audio_processing/aec3/erle_estimator.h"
#include <algorithm>
#include <numeric>
#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

View File

@ -31,10 +31,13 @@ class ErleEstimator {
// Returns the most recent ERLE estimate.
const std::array<float, kFftLengthBy2Plus1>& Erle() const { return erle_; }
float ErleTimeDomain() { return erle_time_domain_; }
private:
std::array<float, kFftLengthBy2Plus1> erle_;
std::array<int, kFftLengthBy2Minus1> 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_;

View File

@ -18,6 +18,7 @@ namespace {
constexpr int kLowFrequencyLimit = kFftLengthBy2 / 2;
void VerifyErle(const std::array<float, kFftLengthBy2Plus1>& erle,
float erle_time_domain,
float reference_lf,
float reference_hf) {
std::for_each(
@ -26,6 +27,7 @@ void VerifyErle(const std::array<float, kFftLengthBy2Plus1>& 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