AEC3: option for enabling/disabling the onset detection for the ERLE in the configuration file.

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 <peah@webrtc.org>
Commit-Queue: Per Åhgren <peah@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#24470}
This commit is contained in:
Jesús de Vicente Peña
2018-08-28 14:27:45 +02:00
committed by Commit Bot
parent d941c09bc0
commit a687812c70
6 changed files with 40 additions and 30 deletions

View File

@ -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 {

View File

@ -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);
}

View File

@ -167,7 +167,8 @@ void ErleEstimator::ErleFreqInstantaneous::Reset() {
void ErleEstimator::Update(rtc::ArrayView<const float> render_spectrum,
rtc::ArrayView<const float> capture_spectrum,
rtc::ArrayView<const float> 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<const float> 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<float> 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<const float> 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;
}
}
}
}

View File

@ -31,7 +31,8 @@ class ErleEstimator {
void Update(rtc::ArrayView<const float> render_spectrum,
rtc::ArrayView<const float> capture_spectrum,
rtc::ArrayView<const float> subtractor_spectrum,
bool converged_filter);
bool converged_filter,
bool onset_detection);
// Returns the most recent ERLE estimate.
const std::array<float, kFftLengthBy2Plus1>& Erle() const { return erle_; }

View File

@ -10,8 +10,8 @@
#include <cmath>
#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);

View File

@ -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", &section)) {