From 9845a67bc56a41b657c5c77b3f294b8b5dcd2a74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Per=20=C3=85hgren?= Date: Mon, 15 Jan 2018 13:09:02 +0100 Subject: [PATCH] Corrected the handling of saturated echoes inside AEC3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bug: webrtc:8747 Change-Id: I644e00c5cc73c8c7b5893725fa15fc018de3cc91 Reviewed-on: https://webrtc-review.googlesource.com/39508 Commit-Queue: Per Ã…hgren Reviewed-by: Gustaf Ullberg Cr-Commit-Position: refs/heads/master@{#21620} --- modules/audio_processing/aec3/subtractor.cc | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/modules/audio_processing/aec3/subtractor.cc b/modules/audio_processing/aec3/subtractor.cc index b19bd64792..6fbef9e222 100644 --- a/modules/audio_processing/aec3/subtractor.cc +++ b/modules/audio_processing/aec3/subtractor.cc @@ -26,17 +26,26 @@ void PredictionError(const Aec3Fft& fft, const FftData& S, rtc::ArrayView y, std::array* e, - std::array* s) { + std::array* s, + bool* saturation) { std::array tmp; fft.Ifft(S, &tmp); constexpr float kScale = 1.0f / kFftLengthBy2; std::transform(y.begin(), y.end(), tmp.begin() + kFftLengthBy2, e->begin(), [&](float a, float b) { return a - b * kScale; }); + *saturation = false; + if (s) { for (size_t k = 0; k < s->size(); ++k) { (*s)[k] = kScale * tmp[k + kFftLengthBy2]; } + auto result = std::minmax_element(s->begin(), s->end()); + *saturation = *result.first <= -32768 || *result.first >= 32767; + } + if (!(*saturation)) { + auto result = std::minmax_element(e->begin(), e->end()); + *saturation = *result.first <= -32768 || *result.first >= 32767; } std::for_each(e->begin(), e->end(), @@ -135,14 +144,16 @@ void Subtractor::Process(const RenderBuffer& render_buffer, // Form the output of the main filter. main_filter_.Filter(render_buffer, &S); - PredictionError(fft_, S, y, &e_main, &output->s_main); + bool main_saturation = false; + PredictionError(fft_, S, y, &e_main, &output->s_main, &main_saturation); fft_.ZeroPaddedFft(e_main, Aec3Fft::Window::kHanning, &E_main); fft_.ZeroPaddedFft(e_main, Aec3Fft::Window::kRectangular, &E_main_nonwindowed); // Form the output of the shadow filter. shadow_filter_.Filter(render_buffer, &S); - PredictionError(fft_, S, y, &e_shadow, nullptr); + bool shadow_saturation = false; + PredictionError(fft_, S, y, &e_shadow, nullptr, &shadow_saturation); fft_.ZeroPaddedFft(e_shadow, Aec3Fft::Window::kHanning, &E_shadow); if (!converged_filter_) { @@ -167,7 +178,7 @@ void Subtractor::Process(const RenderBuffer& render_buffer, std::array X2; render_buffer.SpectralSum(main_filter_.SizePartitions(), &X2); G_main_.Compute(X2, render_signal_analyzer, *output, main_filter_, - aec_state.SaturatedCapture(), &G); + aec_state.SaturatedCapture() || main_saturation, &G); main_filter_.Adapt(render_buffer, G); data_dumper_->DumpRaw("aec3_subtractor_G_main", G.re); data_dumper_->DumpRaw("aec3_subtractor_G_main", G.im); @@ -178,7 +189,7 @@ void Subtractor::Process(const RenderBuffer& render_buffer, } G_shadow_.Compute(X2, render_signal_analyzer, E_shadow, shadow_filter_.SizePartitions(), - aec_state.SaturatedCapture(), &G); + aec_state.SaturatedCapture() || shadow_saturation, &G); shadow_filter_.Adapt(render_buffer, G); data_dumper_->DumpRaw("aec3_subtractor_G_shadow", G.re);