From 2f2633d90c3ec0f0b42f5270d9a65987ff93f962 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20de=20Vicente=20Pe=C3=B1a?= Date: Wed, 2 May 2018 09:47:22 +0200 Subject: [PATCH] AEC3: Audility: Avoid the initialization of the noise estimator in pure zeroes signals at the render. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bug: webrtc:9193,chromium:836790 Change-Id: Ic162dd72947f1d075b55df6725a17b66c782930a Reviewed-on: https://webrtc-review.googlesource.com/73200 Reviewed-by: Per Ã…hgren Commit-Queue: Jesus de Vicente Pena Cr-Commit-Position: refs/heads/master@{#23075} --- modules/audio_processing/aec3/aec_state.cc | 2 +- .../audio_processing/aec3/echo_audibility.cc | 112 ++++++++++++------ .../audio_processing/aec3/echo_audibility.h | 23 ++-- modules/audio_processing/aec3/render_buffer.h | 21 +--- 4 files changed, 92 insertions(+), 66 deletions(-) diff --git a/modules/audio_processing/aec3/aec_state.cc b/modules/audio_processing/aec3/aec_state.cc index 1f1eaceaeb..5f36e6518e 100644 --- a/modules/audio_processing/aec3/aec_state.cc +++ b/modules/audio_processing/aec3/aec_state.cc @@ -135,7 +135,7 @@ void AecState::Update( if (UseStationaryProperties()) { // Update the echo audibility evaluator. echo_audibility_.Update(render_buffer, FilterDelayBlocks(), - capture_block_counter_, external_delay_seen_); + external_delay_seen_); } // Update the ERL and ERLE measures. diff --git a/modules/audio_processing/aec3/echo_audibility.cc b/modules/audio_processing/aec3/echo_audibility.cc index 6f2a8f121c..68d2dd11e6 100644 --- a/modules/audio_processing/aec3/echo_audibility.cc +++ b/modules/audio_processing/aec3/echo_audibility.cc @@ -10,62 +10,96 @@ #include "modules/audio_processing/aec3/echo_audibility.h" +#include +#include + #include "modules/audio_processing/aec3/aec3_common.h" +#include "modules/audio_processing/aec3/matrix_buffer.h" #include "modules/audio_processing/aec3/stationarity_estimator.h" +#include "modules/audio_processing/aec3/vector_buffer.h" namespace webrtc { -namespace { -constexpr int kUnitializedIndex = -1; -} // namespace - EchoAudibility::EchoAudibility() { Reset(); } -void EchoAudibility::Reset() { - render_stationarity_.Reset(); - render_write_prev_ = kUnitializedIndex; -} - EchoAudibility::~EchoAudibility() = default; -void EchoAudibility::UpdateRenderStationarityFlags( - const RenderBuffer& render_buffer, - size_t delay_blocks) { - int idx_at_delay = - render_buffer.OffsetSpectrumIndex(render_buffer.Position(), delay_blocks); - size_t num_lookahead = render_buffer.Headroom() - delay_blocks + 1; - render_stationarity_.UpdateStationarityFlags( - render_buffer.GetSpectrumBuffer(), idx_at_delay, num_lookahead); -} - -void EchoAudibility::UpdateRenderNoiseEstimator( - const RenderBuffer& render_buffer) { - if (render_write_prev_ == kUnitializedIndex) { - render_write_prev_ = render_buffer.GetWritePositionSpectrum(); - return; - } - int render_write_current = render_buffer.GetWritePositionSpectrum(); - - for (int idx = render_write_prev_; idx != render_write_current; - idx = render_buffer.DecIdx(idx)) { - render_stationarity_.UpdateNoiseEstimator( - render_buffer.SpectrumAtIndex(idx)); - } - - render_write_prev_ = render_write_current; -} - void EchoAudibility::Update(const RenderBuffer& render_buffer, - size_t delay_blocks, - size_t capture_block_counter, + int delay_blocks, bool external_delay_seen) { - UpdateRenderNoiseEstimator(render_buffer); + UpdateRenderNoiseEstimator(render_buffer.GetSpectrumBuffer(), + render_buffer.GetBlockBuffer(), + external_delay_seen); if (external_delay_seen) { UpdateRenderStationarityFlags(render_buffer, delay_blocks); } } +void EchoAudibility::Reset() { + render_stationarity_.Reset(); + non_zero_render_seen_ = false; + render_spectrum_write_prev_ = rtc::nullopt; +} + +void EchoAudibility::UpdateRenderStationarityFlags( + const RenderBuffer& render_buffer, + int delay_blocks) { + const VectorBuffer& spectrum_buffer = render_buffer.GetSpectrumBuffer(); + int idx_at_delay = + spectrum_buffer.OffsetIndex(spectrum_buffer.read, delay_blocks); + + int num_lookahead = render_buffer.Headroom() - delay_blocks + 1; + num_lookahead = std::max(0, num_lookahead); + + render_stationarity_.UpdateStationarityFlags(spectrum_buffer, idx_at_delay, + num_lookahead); +} + +void EchoAudibility::UpdateRenderNoiseEstimator( + const VectorBuffer& spectrum_buffer, + const MatrixBuffer& block_buffer, + bool external_delay_seen) { + if (!render_spectrum_write_prev_) { + render_spectrum_write_prev_ = spectrum_buffer.write; + render_block_write_prev_ = block_buffer.write; + return; + } + int render_spectrum_write_current = spectrum_buffer.write; + if (!non_zero_render_seen_ && !external_delay_seen) { + non_zero_render_seen_ = !IsRenderTooLow(block_buffer); + } + if (non_zero_render_seen_) { + for (int idx = render_spectrum_write_prev_.value(); + idx != render_spectrum_write_current; + idx = spectrum_buffer.DecIndex(idx)) { + render_stationarity_.UpdateNoiseEstimator(spectrum_buffer.buffer[idx]); + } + } + render_spectrum_write_prev_ = render_spectrum_write_current; +} + +bool EchoAudibility::IsRenderTooLow(const MatrixBuffer& block_buffer) { + bool too_low = false; + const int render_block_write_current = block_buffer.write; + if (render_block_write_current == render_block_write_prev_) { + too_low = true; + } else { + for (int idx = render_block_write_prev_; idx != render_block_write_current; + idx = block_buffer.IncIndex(idx)) { + auto block = block_buffer.buffer[idx][0]; + auto r = std::minmax_element(block.cbegin(), block.cend()); + float max_abs = std::max(std::fabs(*r.first), std::fabs(*r.second)); + if (max_abs < 10) { + too_low = true; // Discards all blocks if one of them is too low. + break; + } + } + } + render_block_write_prev_ = render_block_write_current; + return too_low; +} + } // namespace webrtc diff --git a/modules/audio_processing/aec3/echo_audibility.h b/modules/audio_processing/aec3/echo_audibility.h index 7b9f283257..038951e987 100644 --- a/modules/audio_processing/aec3/echo_audibility.h +++ b/modules/audio_processing/aec3/echo_audibility.h @@ -18,8 +18,11 @@ #include #include "api/array_view.h" +#include "api/optional.h" +#include "modules/audio_processing/aec3/matrix_buffer.h" #include "modules/audio_processing/aec3/render_buffer.h" #include "modules/audio_processing/aec3/stationarity_estimator.h" +#include "modules/audio_processing/aec3/vector_buffer.h" #include "rtc_base/constructormagic.h" namespace webrtc { @@ -33,8 +36,7 @@ class EchoAudibility { // Feed new render data to the echo audibility estimator. void Update(const RenderBuffer& render_buffer, - size_t delay_blocks, - size_t capture_block_counter_, + int delay_blocks, bool external_delay_seen); // Get the residual echo scaling. @@ -52,18 +54,23 @@ class EchoAudibility { // Reset the EchoAudibility class. void Reset(); - // Compute the residual scaling per frequency for the current frame. - void ComputeResidualScaling(); - // Updates the render stationarity flags for the current frame. void UpdateRenderStationarityFlags(const RenderBuffer& render_buffer, - size_t delay_blocks); + int delay_blocks); // Updates the noise estimator with the new render data since the previous // call to this method. - void UpdateRenderNoiseEstimator(const RenderBuffer& render_buffer); + void UpdateRenderNoiseEstimator(const VectorBuffer& spectrum_buffer, + const MatrixBuffer& block_buffer, + bool external_delay_seen); - int render_write_prev_; + // Returns a bool being true if the render signal contains just close to zero + // values. + bool IsRenderTooLow(const MatrixBuffer& block_buffer); + + rtc::Optional render_spectrum_write_prev_; + int render_block_write_prev_; + bool non_zero_render_seen_; StationarityEstimator render_stationarity_; RTC_DISALLOW_COPY_AND_ASSIGN(EchoAudibility); }; diff --git a/modules/audio_processing/aec3/render_buffer.h b/modules/audio_processing/aec3/render_buffer.h index 292cb9d2c3..9419b30aa9 100644 --- a/modules/audio_processing/aec3/render_buffer.h +++ b/modules/audio_processing/aec3/render_buffer.h @@ -45,14 +45,6 @@ class RenderBuffer { return spectrum_buffer_->buffer[position]; } - // Get the spectrum directly from an index in the buffer. - rtc::ArrayView SpectrumAtIndex(int index) const { - RTC_CHECK_LT(index, spectrum_buffer_->size); - int position_bound = std::min(index, spectrum_buffer_->size - 1); - position_bound = std::max(0, position_bound); - return spectrum_buffer_->buffer[position_bound]; - } - // Returns the circular fft buffer. rtc::ArrayView GetFftBuffer() const { return fft_buffer_->buffer; @@ -65,14 +57,6 @@ class RenderBuffer { return fft_buffer_->read; } - // Applies an offset to a buffer index and returns it. - int OffsetSpectrumIndex(int index, int offset) const { - return spectrum_buffer_->OffsetIndex(index, offset); - } - - // Returns the write postion in the circular buffer. - int GetWritePositionSpectrum() const { return spectrum_buffer_->write; } - // Returns the sum of the spectrums for a certain number of FFTs. void SpectralSum(size_t num_spectra, std::array* X2) const; @@ -98,12 +82,13 @@ class RenderBuffer { return headroom; } - // Decreases an index that is used for accessing the buffer. - int DecIdx(int idx) const { return spectrum_buffer_->DecIndex(idx); } // Returns a reference to the spectrum buffer. const VectorBuffer& GetSpectrumBuffer() const { return *spectrum_buffer_; } + // Returns a reference to the block buffer. + const MatrixBuffer& GetBlockBuffer() const { return *block_buffer_; } + private: const MatrixBuffer* const block_buffer_; const VectorBuffer* const spectrum_buffer_;