AEC3: Audility: Avoid the initialization of the noise estimator in pure zeroes signals at the render.

Bug: webrtc:9193,chromium:836790
Change-Id: Ic162dd72947f1d075b55df6725a17b66c782930a
Reviewed-on: https://webrtc-review.googlesource.com/73200
Reviewed-by: Per Åhgren <peah@webrtc.org>
Commit-Queue: Jesus de Vicente Pena <devicentepena@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#23075}
This commit is contained in:
Jesús de Vicente Peña 2018-05-02 09:47:22 +02:00 committed by Commit Bot
parent 3c30c9cb9f
commit 2f2633d90c
4 changed files with 92 additions and 66 deletions

View File

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

View File

@ -10,62 +10,96 @@
#include "modules/audio_processing/aec3/echo_audibility.h"
#include <algorithm>
#include <cmath>
#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

View File

@ -18,8 +18,11 @@
#include <vector>
#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<int> render_spectrum_write_prev_;
int render_block_write_prev_;
bool non_zero_render_seen_;
StationarityEstimator render_stationarity_;
RTC_DISALLOW_COPY_AND_ASSIGN(EchoAudibility);
};

View File

@ -45,14 +45,6 @@ class RenderBuffer {
return spectrum_buffer_->buffer[position];
}
// Get the spectrum directly from an index in the buffer.
rtc::ArrayView<const float> 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<const FftData> 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<float, kFftLengthBy2Plus1>* 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_;