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:
committed by
Commit Bot
parent
d941c09bc0
commit
a687812c70
@ -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 {
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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_; }
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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", §ion)) {
|
||||
|
||||
Reference in New Issue
Block a user