Make AEC3 recover more quickly for lost capture data
This CL ensures that AEC3 recovers more quickly when capture data is
lost in such a manner that the echo path, as seen by AEC3, becomes
noncausal due to the AEC3 buffer misalignment caused by the data loss.
The CL adds the assumption of a minimum echo path delay of 5 blocks
and makes the hysteresis in the delay selection one-sided.
BUG=chromium:757796, webrtc:8131
Review-Url: https://codereview.webrtc.org/2998223002
Cr-Commit-Position: refs/heads/master@{#19454}
diff --git a/webrtc/modules/audio_processing/aec3/aec3_common.h b/webrtc/modules/audio_processing/aec3/aec3_common.h
index b781183..bf62c0e 100644
--- a/webrtc/modules/audio_processing/aec3/aec3_common.h
+++ b/webrtc/modules/audio_processing/aec3/aec3_common.h
@@ -63,6 +63,7 @@
constexpr size_t kRenderDelayBufferSize =
(3 * kDownsampledRenderBufferSize) / (4 * kSubBlockSize);
+constexpr size_t kMinEchoPathDelayBlocks = 5;
constexpr size_t kMaxApiCallsJitterBlocks = 30;
constexpr size_t kRenderTransferQueueSize = kMaxApiCallsJitterBlocks / 2;
static_assert(2 * kRenderTransferQueueSize >= kMaxApiCallsJitterBlocks,
diff --git a/webrtc/modules/audio_processing/aec3/block_processor.cc b/webrtc/modules/audio_processing/aec3/block_processor.cc
index 3a32f3c..52bc4ef1 100644
--- a/webrtc/modules/audio_processing/aec3/block_processor.cc
+++ b/webrtc/modules/audio_processing/aec3/block_processor.cc
@@ -112,20 +112,27 @@
const size_t old_delay = render_buffer_->Delay();
const size_t new_delay = delay_controller_->GetDelay(
render_buffer_->GetDownsampledRenderBuffer(), (*capture_block)[0]);
- render_buffer_->SetDelay(new_delay);
- const size_t achieved_delay = render_buffer_->Delay();
- // Inform the delay controller of the actually set delay to allow it to
- // properly react to a non-feasible delay.
- delay_controller_->SetDelay(achieved_delay);
+ bool delay_change;
+ if (new_delay >= kMinEchoPathDelayBlocks) {
+ render_buffer_->SetDelay(new_delay);
+ const size_t achieved_delay = render_buffer_->Delay();
+ delay_change = old_delay != achieved_delay || old_delay != new_delay ||
+ render_buffer_overrun_occurred_;
+
+ // Inform the delay controller of the actually set delay to allow it to
+ // properly react to a non-feasible delay.
+ delay_controller_->SetDelay(achieved_delay);
+ } else {
+ delay_controller_->Reset();
+ render_buffer_->Reset();
+ delay_change = true;
+ }
// Remove the echo from the capture signal.
echo_remover_->ProcessCapture(
delay_controller_->AlignmentHeadroomSamples(),
- EchoPathVariability(echo_path_gain_change,
- old_delay != achieved_delay ||
- old_delay != new_delay ||
- render_buffer_overrun_occurred_),
+ EchoPathVariability(echo_path_gain_change, delay_change),
capture_signal_saturation, render_buffer_->GetRenderBuffer(),
capture_block);
diff --git a/webrtc/modules/audio_processing/aec3/render_delay_controller.cc b/webrtc/modules/audio_processing/aec3/render_delay_controller.cc
index 06074e2..a88540e 100644
--- a/webrtc/modules/audio_processing/aec3/render_delay_controller.cc
+++ b/webrtc/modules/audio_processing/aec3/render_delay_controller.cc
@@ -59,7 +59,7 @@
size_t new_delay = std::max(echo_path_delay_blocks - kDelayHeadroomBlocks, 0);
// Add hysteresis.
- if (new_delay == current_delay + 1 || new_delay + 1 == current_delay) {
+ if (new_delay == current_delay + 1) {
new_delay = current_delay;
}
@@ -78,7 +78,7 @@
RenderDelayControllerImpl::~RenderDelayControllerImpl() = default;
void RenderDelayControllerImpl::Reset() {
- delay_ = 0;
+ delay_ = kMinEchoPathDelayBlocks;
blocks_since_last_delay_estimate_ = 300000;
echo_path_delay_samples_ = 0;
align_call_counter_ = 0;