From 02e9e44c0c2c84b52d18395a1eac0112719616a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20de=20Vicente=20Pe=C3=B1a?= Date: Wed, 29 Aug 2018 13:34:07 +0200 Subject: [PATCH] AEC3: Adding a reset of the ERLE estimator after going out from the initial state. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bug: webrtc:9685 Change-Id: Ifc6019811c3d90df91df07e68f1d04cb39cb3545 Reviewed-on: https://webrtc-review.googlesource.com/96661 Reviewed-by: Per Ã…hgren Commit-Queue: Jesus de Vicente Pena Cr-Commit-Position: refs/heads/master@{#24484} --- modules/audio_processing/aec3/aec_state.cc | 7 ++++++- modules/audio_processing/aec3/aec_state.h | 6 ++++-- modules/audio_processing/aec3/echo_remover.cc | 11 ++++------- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/modules/audio_processing/aec3/aec_state.cc b/modules/audio_processing/aec3/aec_state.cc index a3fd67997c..62232ac104 100644 --- a/modules/audio_processing/aec3/aec_state.cc +++ b/modules/audio_processing/aec3/aec_state.cc @@ -235,6 +235,9 @@ void AecState::Update( } // Update the ERL and ERLE measures. + if (reset_erle_after_echo_path_changes_ && transition_triggered_) { + erle_estimator_.Reset(); + } if (blocks_since_reset_ >= 2 * kNumBlocksPerSecond) { const auto& X2 = render_buffer.Spectrum(filter_delay_blocks_); erle_estimator_.Update(X2, Y2, E2_main, converged_filter, @@ -267,6 +270,7 @@ void AecState::Update( } // Flag whether the initial state is still active. + bool prev_initial_state = initial_state_; if (use_short_initial_state_) { initial_state_ = blocks_with_proper_filter_adaptation_ < config_.filter.initial_state_seconds * kNumBlocksPerSecond; @@ -274,6 +278,7 @@ void AecState::Update( initial_state_ = blocks_with_proper_filter_adaptation_ < 5 * kNumBlocksPerSecond; } + transition_triggered_ = !initial_state_ && prev_initial_state; // Update counters for the filter divergence and convergence. diverged_blocks_ = diverged_filter ? diverged_blocks_ + 1 : 0; @@ -382,7 +387,7 @@ void AecState::Update( data_dumper_->DumpRaw("aec3_consistent_filter", filter_analyzer_.Consistent()); data_dumper_->DumpRaw("aec3_suppression_gain_limit", SuppressionGainLimit()); - data_dumper_->DumpRaw("aec3_initial_state", InitialState()); + data_dumper_->DumpRaw("aec3_initial_state", initial_state_); data_dumper_->DumpRaw("aec3_capture_saturation", SaturatedCapture()); data_dumper_->DumpRaw("aec3_echo_saturation", echo_saturation_); data_dumper_->DumpRaw("aec3_converged_filter", converged_filter); diff --git a/modules/audio_processing/aec3/aec_state.h b/modules/audio_processing/aec3/aec_state.h index 772ed90938..ea30daf0ea 100644 --- a/modules/audio_processing/aec3/aec_state.h +++ b/modules/audio_processing/aec3/aec_state.h @@ -140,8 +140,9 @@ class AecState { return filter_has_had_time_to_converge_; } - // Returns whether the filter adaptation is still in the initial state. - bool InitialState() const { return initial_state_; } + // Returns whether the transition for going out of the initial stated has + // been triggered. + bool TransitionTriggered() const { return transition_triggered_; } // Updates the aec state. void Update(const absl::optional& external_delay, @@ -197,6 +198,7 @@ class AecState { std::vector max_render_; bool filter_has_had_time_to_converge_ = false; bool initial_state_ = true; + bool transition_triggered_ = false; const float gain_rampup_increase_; SuppressionGainUpperLimiter suppression_gain_limiter_; FilterAnalyzer filter_analyzer_; diff --git a/modules/audio_processing/aec3/echo_remover.cc b/modules/audio_processing/aec3/echo_remover.cc index b916880736..e52bc62586 100644 --- a/modules/audio_processing/aec3/echo_remover.cc +++ b/modules/audio_processing/aec3/echo_remover.cc @@ -141,7 +141,6 @@ class EchoRemoverImpl final : public EchoRemover { bool echo_leakage_detected_ = false; AecState aec_state_; EchoRemoverMetrics metrics_; - bool initial_state_ = true; std::array e_old_; std::array x_old_; std::array y_old_; @@ -233,7 +232,6 @@ void EchoRemoverImpl::ProcessCapture( if (echo_path_variability.delay_change != EchoPathVariability::DelayAdjustment::kNone) { suppression_gain_.SetInitialState(true); - initial_state_ = true; } } if (gain_change_hangover_ > 0) { @@ -257,10 +255,9 @@ void EchoRemoverImpl::ProcessCapture( aec_state_.FilterDelayBlocks()); // Perform linear echo cancellation. - if (initial_state_ && !aec_state_.InitialState()) { + if (aec_state_.TransitionTriggered()) { subtractor_.ExitInitialState(); suppression_gain_.SetInitialState(false); - initial_state_ = false; } // If the delay is known, use the echo subtractor. @@ -357,9 +354,9 @@ void EchoRemoverImpl::FormLinearFilterOutput( RTC_DCHECK_EQ(subtractor_output.e_shadow.size(), output.size()); bool use_main_output = true; if (use_shadow_filter_output_) { - // As the output of the main adaptive filter generally should be better than - // the shadow filter output, add a margin and threshold for when choosing - // the shadow filter output. + // As the output of the main adaptive filter generally should be better + // than the shadow filter output, add a margin and threshold for when + // choosing the shadow filter output. if (subtractor_output.e2_shadow < 0.9f * subtractor_output.e2_main && subtractor_output.y2 > 30.f * 30.f * kBlockSize && (subtractor_output.s2_main > 60.f * 60.f * kBlockSize ||