Compute ERL over all frequency bins in AEC3.
Bug: webrtc:8533 Change-Id: I7160361b3468bb24cef9e6d390f10b23b988edd3 Reviewed-on: https://webrtc-review.googlesource.com/23242 Reviewed-by: Per Åhgren <peah@webrtc.org> Commit-Queue: Gustaf Ullberg <gustaf@webrtc.org> Cr-Commit-Position: refs/heads/master@{#20713}
This commit is contained in:
committed by
Commit Bot
parent
8d9c5406c7
commit
fe4d673393
@ -11,6 +11,7 @@
|
||||
#include "modules/audio_processing/aec3/erl_estimator.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <numeric>
|
||||
|
||||
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
|
||||
|
||||
@ -30,10 +30,13 @@ class ErlEstimator {
|
||||
|
||||
// Returns the most recent ERL estimate.
|
||||
const std::array<float, kFftLengthBy2Plus1>& Erl() const { return erl_; }
|
||||
float ErlTimeDomain() const { return erl_time_domain_; }
|
||||
|
||||
private:
|
||||
std::array<float, kFftLengthBy2Plus1> erl_;
|
||||
std::array<int, kFftLengthBy2Minus1> hold_counters_;
|
||||
float erl_time_domain_;
|
||||
int hold_counter_time_domain_;
|
||||
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(ErlEstimator);
|
||||
};
|
||||
|
||||
@ -17,9 +17,11 @@ namespace webrtc {
|
||||
namespace {
|
||||
|
||||
void VerifyErl(const std::array<float, kFftLengthBy2Plus1>& 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
|
||||
|
||||
Reference in New Issue
Block a user