From 6204adf2ede6bbe65e14334669b934291bf8a998 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Per=20=C3=85hgren?= Date: Sun, 19 Aug 2018 11:12:00 +0200 Subject: [PATCH] AEC3: Loosen the echo removal requirements in conservative mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This CL lowers the margins in the AEC3 conservative mode to increase the transparency when there are audio buffer issues, and during call startup. In particular, this CL adjusts the parameters and thresholds to -Make the requirements for filter divergence more strict, to minimize the transparency loss during minor filter divergence. -Decrease the echo power uncertainty used during initial filter convergence, to increase transparency after audio buffer issues. -Deactivate the enforcement of conservative suppressor gain after audio buffer. Bug: webrtc:9641,chromium:875611 Change-Id: Ie171bb411f17a1e8661c291118debd334f65c74f Reviewed-on: https://webrtc-review.googlesource.com/94776 Commit-Queue: Per Ã…hgren Reviewed-by: Jesus de Vicente Pena Reviewed-by: Henrik Lundin Cr-Commit-Position: refs/heads/master@{#24333} --- modules/audio_processing/aec3/aec_state.cc | 55 ++++++++++++++++++- modules/audio_processing/aec3/aec_state.h | 6 +- .../audio_processing/aec3/echo_canceller3.cc | 21 +++++++ .../aec3/subtractor_output_analyzer.cc | 3 + .../aec3/subtractor_output_analyzer.h | 2 + .../aec3/suppression_gain_limiter.h | 6 ++ 6 files changed, 91 insertions(+), 2 deletions(-) diff --git a/modules/audio_processing/aec3/aec_state.cc b/modules/audio_processing/aec3/aec_state.cc index 0ca8618bee..afeea4bee9 100644 --- a/modules/audio_processing/aec3/aec_state.cc +++ b/modules/audio_processing/aec3/aec_state.cc @@ -72,6 +72,41 @@ bool TreatTransparentModeAsNonlinear() { "WebRTC-Aec3TreatTransparentModeAsNonlinearKillSwitch"); } +bool LowUncertaintyBeforeConvergence() { + return !field_trial::IsEnabled( + "WebRTC-Aec3LowUncertaintyBeforeConvergenceKillSwitch"); +} + +bool MediumUncertaintyBeforeConvergence() { + return !field_trial::IsEnabled( + "WebRTC-Aec3MediumUncertaintyBeforeConvergenceKillSwitch"); +} + +bool EarlyEntryToConvergedMode() { + return !field_trial::IsEnabled( + "WebRTC-Aec3EarlyEntryToConvergedModeKillSwitch"); +} + +bool ConservativeFilterDivergence() { + return !field_trial::IsEnabled( + "WebRTC-Aec3ConservativeFilterDivergenceKillSwitch"); +} + +bool UseEarlyLimiterDeactivation() { + return !field_trial::IsEnabled( + "WebRTC-Aec3EarlyLimiterDeactivationKillSwitch"); +} + +float UncertaintyBeforeConvergence() { + if (LowUncertaintyBeforeConvergence()) { + return 1.f; + } else if (MediumUncertaintyBeforeConvergence()) { + return 4.f; + } else { + return 10.f; + } +} + float ComputeGainRampupIncrease(const EchoCanceller3Config& config) { const auto& c = config.echo_removal_control.gain_rampup; return powf(1.f / c.first_non_zero_gain, 1.f / c.non_zero_gain_blocks); @@ -103,6 +138,10 @@ AecState::AecState(const EchoCanceller3Config& config) EnableUncertaintyUntilSufficientAdapted()), transparent_mode_enforces_nonlinear_mode_( TreatTransparentModeAsNonlinear()), + uncertainty_before_convergence_(UncertaintyBeforeConvergence()), + early_entry_to_converged_mode_(EarlyEntryToConvergedMode()), + conservative_filter_divergence_(ConservativeFilterDivergence()), + early_limiter_deactivation_(UseEarlyLimiterDeactivation()), erle_estimator_(config.erle.min, config.erle.max_l, config.erle.max_h), max_render_(config_.filter.main.length_blocks, 0.f), gain_rampup_increase_(ComputeGainRampupIncrease(config_)), @@ -201,6 +240,9 @@ void AecState::Update( // an initial echo burst. suppression_gain_limiter_.Update(render_buffer.GetRenderActivity(), transparent_mode_); + if (converged_filter && early_limiter_deactivation_) { + suppression_gain_limiter_.Deactivate(); + } if (UseStationaryProperties()) { // Update the echo audibility evaluator. @@ -231,6 +273,10 @@ void AecState::Update( blocks_with_proper_filter_adaptation_ >= 1.5f * kNumBlocksPerSecond; } + if (converged_filter && early_entry_to_converged_mode_) { + filter_has_had_time_to_converge_ = true; + } + if (!filter_should_have_converged_) { filter_should_have_converged_ = blocks_with_proper_filter_adaptation_ > 6 * kNumBlocksPerSecond; @@ -335,7 +381,14 @@ void AecState::Update( } use_linear_filter_output_ = usable_linear_estimate_ && !TransparentMode(); - diverged_linear_filter_ = diverged_filter; + + if (conservative_filter_divergence_) { + diverged_linear_filter_ = + subtractor_output_analyzer_.SeverelyDivergedFilter() && + active_render_block; + } else { + diverged_linear_filter_ = diverged_filter; + } const bool stationary_block = use_stationary_properties_ && echo_audibility_.IsBlockStationary(); diff --git a/modules/audio_processing/aec3/aec_state.h b/modules/audio_processing/aec3/aec_state.h index 99353b34a0..656548585e 100644 --- a/modules/audio_processing/aec3/aec_state.h +++ b/modules/audio_processing/aec3/aec_state.h @@ -80,7 +80,7 @@ class AecState { if (!filter_has_had_time_to_converge_ && use_uncertainty_until_sufficiently_adapted_) { - return 10.f; + return uncertainty_before_convergence_; } return absl::nullopt; } @@ -182,6 +182,10 @@ class AecState { const bool no_alignment_required_for_linear_mode_; const bool use_uncertainty_until_sufficiently_adapted_; const bool transparent_mode_enforces_nonlinear_mode_; + const float uncertainty_before_convergence_; + const bool early_entry_to_converged_mode_; + const bool conservative_filter_divergence_; + const bool early_limiter_deactivation_; ErlEstimator erl_estimator_; ErleEstimator erle_estimator_; size_t capture_block_counter_ = 0; diff --git a/modules/audio_processing/aec3/echo_canceller3.cc b/modules/audio_processing/aec3/echo_canceller3.cc index 07d8b254aa..c02bc14863 100644 --- a/modules/audio_processing/aec3/echo_canceller3.cc +++ b/modules/audio_processing/aec3/echo_canceller3.cc @@ -54,9 +54,18 @@ bool EnableShadowFilterJumpstart() { return !field_trial::IsEnabled("WebRTC-Aec3ShadowFilterJumpstartKillSwitch"); } +bool EnableUnityInitialRampupGain() { + return field_trial::IsEnabled("WebRTC-Aec3EnableUnityInitialRampupGain"); +} + +bool EnableUnityNonZeroRampupGain() { + return field_trial::IsEnabled("WebRTC-Aec3EnableUnityNonZeroRampupGain"); +} + // Method for adjusting config parameter dependencies.. EchoCanceller3Config AdjustConfig(const EchoCanceller3Config& config) { EchoCanceller3Config adjusted_cfg = config; + const EchoCanceller3Config default_cfg; if (!EnableReverbModelling()) { adjusted_cfg.ep_strength.default_len = 0.f; @@ -126,6 +135,18 @@ EchoCanceller3Config AdjustConfig(const EchoCanceller3Config& config) { adjusted_cfg.filter.main.error_floor = 0.001f; } + if (EnableUnityInitialRampupGain() && + adjusted_cfg.echo_removal_control.gain_rampup.initial_gain == + default_cfg.echo_removal_control.gain_rampup.initial_gain) { + adjusted_cfg.echo_removal_control.gain_rampup.initial_gain = 1.f; + } + + if (EnableUnityNonZeroRampupGain() && + adjusted_cfg.echo_removal_control.gain_rampup.first_non_zero_gain == + default_cfg.echo_removal_control.gain_rampup.first_non_zero_gain) { + adjusted_cfg.echo_removal_control.gain_rampup.first_non_zero_gain = 1.f; + } + return adjusted_cfg; } diff --git a/modules/audio_processing/aec3/subtractor_output_analyzer.cc b/modules/audio_processing/aec3/subtractor_output_analyzer.cc index ff49585759..93675f5f6b 100644 --- a/modules/audio_processing/aec3/subtractor_output_analyzer.cc +++ b/modules/audio_processing/aec3/subtractor_output_analyzer.cc @@ -40,12 +40,15 @@ void SubtractorOutputAnalyzer::Update( float min_e2 = strict_divergence_check_ ? std::min(e2_main, e2_shadow) : e2_main; filter_diverged_ = min_e2 > 1.5f * y2 && y2 > 30.f * 30.f * kBlockSize; + filter_severely_diverged_ = + min_e2 > 1.5f * y2 && y2 > 200.f * 200.f * kBlockSize; } void SubtractorOutputAnalyzer::HandleEchoPathChange() { shadow_filter_converged_ = false; main_filter_converged_ = false; filter_diverged_ = false; + filter_severely_diverged_ = false; } } // namespace webrtc diff --git a/modules/audio_processing/aec3/subtractor_output_analyzer.h b/modules/audio_processing/aec3/subtractor_output_analyzer.h index b59a68e5e6..b9a2445ea6 100644 --- a/modules/audio_processing/aec3/subtractor_output_analyzer.h +++ b/modules/audio_processing/aec3/subtractor_output_analyzer.h @@ -30,6 +30,7 @@ class SubtractorOutputAnalyzer { } bool DivergedFilter() const { return filter_diverged_; } + bool SeverelyDivergedFilter() const { return filter_severely_diverged_; } // Handle echo path change. void HandleEchoPathChange(); @@ -39,6 +40,7 @@ class SubtractorOutputAnalyzer { bool shadow_filter_converged_ = false; bool main_filter_converged_ = false; bool filter_diverged_ = false; + bool filter_severely_diverged_ = false; }; } // namespace webrtc diff --git a/modules/audio_processing/aec3/suppression_gain_limiter.h b/modules/audio_processing/aec3/suppression_gain_limiter.h index 717868ac0a..eade949605 100644 --- a/modules/audio_processing/aec3/suppression_gain_limiter.h +++ b/modules/audio_processing/aec3/suppression_gain_limiter.h @@ -35,6 +35,12 @@ class SuppressionGainUpperLimiter { // Return whether the suppressor gain limit is active. bool IsActive() const { return (realignment_counter_ > 0); } + // Inactivate limiter. + void Deactivate() { + realignment_counter_ = 0; + suppressor_gain_limit_ = 1.f; + } + private: const EchoCanceller3Config::EchoRemovalControl::GainRampup rampup_config_; const float gain_rampup_increase_;