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_;