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:
parent
3c30c9cb9f
commit
2f2633d90c
@ -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.
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
};
|
||||
|
||||
@ -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_;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user