Corrected the behavior in AEC3 during buffer overruns and underruns

This CL corrects the behavior in AEC3 during buffer overruns
and underruns in three ways.
1) When there is no render signal available (due to a buffering
 issues, a zero block is inserted instead of the previous render
 block. This avoids the same block being repeatedly inserted when
 there are many back-to-back calls.
2) The internal counters in the main adaptive filter gain are also
 reset when the filter is reset.
3) The internal counters in the shadow adaptive filter gain are
 reset when the filter is reset.

BUG=chromium:717920,webrtc:7559

Review-Url: https://codereview.webrtc.org/2862533002
Cr-Commit-Position: refs/heads/master@{#17991}
This commit is contained in:
peah 2017-05-03 05:39:09 -07:00 committed by Commit bot
parent 5af6e25b10
commit debaa442ed
5 changed files with 34 additions and 9 deletions

View File

@ -22,6 +22,7 @@ namespace webrtc {
namespace {
constexpr float kHErrorInitial = 10000.f;
constexpr int kPoorExcitationCounterInitial = 1000;
} // namespace
@ -30,7 +31,7 @@ int MainFilterUpdateGain::instance_count_ = 0;
MainFilterUpdateGain::MainFilterUpdateGain()
: data_dumper_(
new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))),
poor_excitation_counter_(1000) {
poor_excitation_counter_(kPoorExcitationCounterInitial) {
H_error_.fill(kHErrorInitial);
}
@ -38,6 +39,8 @@ MainFilterUpdateGain::~MainFilterUpdateGain() {}
void MainFilterUpdateGain::HandleEchoPathChange() {
H_error_.fill(kHErrorInitial);
poor_excitation_counter_ = kPoorExcitationCounterInitial;
call_counter_ = 0;
}
void MainFilterUpdateGain::Compute(

View File

@ -97,6 +97,7 @@ class RenderDelayBufferImpl final : public RenderDelayBuffer {
DownsampledRenderBuffer downsampled_render_buffer_;
DecimatorBy4 render_decimator_;
ApiCallJitterBuffer api_call_jitter_buffer_;
const std::vector<std::vector<float>> zero_block_;
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RenderDelayBufferImpl);
};
@ -107,7 +108,8 @@ RenderDelayBufferImpl::RenderDelayBufferImpl(size_t num_bands)
num_bands,
std::max(kResidualEchoPowerRenderWindowSize, kAdaptiveFilterLength),
std::vector<size_t>(1, kAdaptiveFilterLength)),
api_call_jitter_buffer_(num_bands) {
api_call_jitter_buffer_(num_bands),
zero_block_(num_bands, std::vector<float>(kBlockSize, 0.f)) {
buffer_.fill(std::vector<std::vector<float>>(
num_bands, std::vector<float>(kBlockSize, 0.f)));
@ -147,12 +149,11 @@ bool RenderDelayBufferImpl::Insert(
bool RenderDelayBufferImpl::UpdateBuffers() {
bool underrun = true;
// Update the buffers with a new block if such is available, otherwise repeat
// the previous block.
// Update the buffers with a new block if such is available, otherwise insert
// a block of silence.
if (api_call_jitter_buffer_.Size() > 0) {
last_insert_index_ = (last_insert_index_ + 1) % buffer_.size();
api_call_jitter_buffer_.Remove(&buffer_[last_insert_index_]);
underrun = false;
}
@ -162,14 +163,22 @@ bool RenderDelayBufferImpl::UpdateBuffers() {
downsampled_render_buffer_.buffer.size();
std::array<float, kSubBlockSize> render_downsampled;
render_decimator_.Decimate(buffer_[last_insert_index_][0],
render_downsampled);
if (underrun) {
render_decimator_.Decimate(zero_block_[0], render_downsampled);
} else {
render_decimator_.Decimate(buffer_[last_insert_index_][0],
render_downsampled);
}
std::copy(render_downsampled.rbegin(), render_downsampled.rend(),
downsampled_render_buffer_.buffer.begin() +
downsampled_render_buffer_.position);
fft_buffer_.Insert(
buffer_[(last_insert_index_ - delay_ + buffer_.size()) % buffer_.size()]);
if (underrun) {
fft_buffer_.Insert(zero_block_);
} else {
fft_buffer_.Insert(buffer_[(last_insert_index_ - delay_ + buffer_.size()) %
buffer_.size()]);
}
return !underrun;
}

View File

@ -17,6 +17,13 @@
namespace webrtc {
void ShadowFilterUpdateGain::HandleEchoPathChange() {
// TODO(peah): Check whether this counter should instead be initialized to a
// large value.
poor_signal_excitation_counter_ = 0;
call_counter_ = 0;
}
void ShadowFilterUpdateGain::Compute(
const RenderBuffer& render_buffer,
const RenderSignalAnalyzer& render_signal_analyzer,

View File

@ -21,6 +21,9 @@ namespace webrtc {
// Provides functionality for computing the fixed gain for the shadow filter.
class ShadowFilterUpdateGain {
public:
// Takes action in the case of a known echo path change.
void HandleEchoPathChange();
// Computes the gain.
void Compute(const RenderBuffer& render_buffer,
const RenderSignalAnalyzer& render_signal_analyzer,
@ -30,6 +33,8 @@ class ShadowFilterUpdateGain {
FftData* G);
private:
// TODO(peah): Check whether this counter should instead be initialized to a
// large value.
size_t poor_signal_excitation_counter_ = 0;
size_t call_counter_ = 0;
};

View File

@ -55,6 +55,7 @@ void Subtractor::HandleEchoPathChange(
main_filter_.HandleEchoPathChange();
shadow_filter_.HandleEchoPathChange();
G_main_.HandleEchoPathChange();
G_shadow_.HandleEchoPathChange();
}
}