AEC3: Loosen the echo removal requirements in conservative mode
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 <peah@webrtc.org> Reviewed-by: Jesus de Vicente Pena <devicentepena@webrtc.org> Reviewed-by: Henrik Lundin <henrik.lundin@webrtc.org> Cr-Commit-Position: refs/heads/master@{#24333}
This commit is contained in:
@ -72,6 +72,41 @@ bool TreatTransparentModeAsNonlinear() {
|
|||||||
"WebRTC-Aec3TreatTransparentModeAsNonlinearKillSwitch");
|
"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) {
|
float ComputeGainRampupIncrease(const EchoCanceller3Config& config) {
|
||||||
const auto& c = config.echo_removal_control.gain_rampup;
|
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);
|
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()),
|
EnableUncertaintyUntilSufficientAdapted()),
|
||||||
transparent_mode_enforces_nonlinear_mode_(
|
transparent_mode_enforces_nonlinear_mode_(
|
||||||
TreatTransparentModeAsNonlinear()),
|
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),
|
erle_estimator_(config.erle.min, config.erle.max_l, config.erle.max_h),
|
||||||
max_render_(config_.filter.main.length_blocks, 0.f),
|
max_render_(config_.filter.main.length_blocks, 0.f),
|
||||||
gain_rampup_increase_(ComputeGainRampupIncrease(config_)),
|
gain_rampup_increase_(ComputeGainRampupIncrease(config_)),
|
||||||
@ -201,6 +240,9 @@ void AecState::Update(
|
|||||||
// an initial echo burst.
|
// an initial echo burst.
|
||||||
suppression_gain_limiter_.Update(render_buffer.GetRenderActivity(),
|
suppression_gain_limiter_.Update(render_buffer.GetRenderActivity(),
|
||||||
transparent_mode_);
|
transparent_mode_);
|
||||||
|
if (converged_filter && early_limiter_deactivation_) {
|
||||||
|
suppression_gain_limiter_.Deactivate();
|
||||||
|
}
|
||||||
|
|
||||||
if (UseStationaryProperties()) {
|
if (UseStationaryProperties()) {
|
||||||
// Update the echo audibility evaluator.
|
// Update the echo audibility evaluator.
|
||||||
@ -231,6 +273,10 @@ void AecState::Update(
|
|||||||
blocks_with_proper_filter_adaptation_ >= 1.5f * kNumBlocksPerSecond;
|
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_) {
|
if (!filter_should_have_converged_) {
|
||||||
filter_should_have_converged_ =
|
filter_should_have_converged_ =
|
||||||
blocks_with_proper_filter_adaptation_ > 6 * kNumBlocksPerSecond;
|
blocks_with_proper_filter_adaptation_ > 6 * kNumBlocksPerSecond;
|
||||||
@ -335,7 +381,14 @@ void AecState::Update(
|
|||||||
}
|
}
|
||||||
|
|
||||||
use_linear_filter_output_ = usable_linear_estimate_ && !TransparentMode();
|
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 =
|
const bool stationary_block =
|
||||||
use_stationary_properties_ && echo_audibility_.IsBlockStationary();
|
use_stationary_properties_ && echo_audibility_.IsBlockStationary();
|
||||||
|
@ -80,7 +80,7 @@ class AecState {
|
|||||||
|
|
||||||
if (!filter_has_had_time_to_converge_ &&
|
if (!filter_has_had_time_to_converge_ &&
|
||||||
use_uncertainty_until_sufficiently_adapted_) {
|
use_uncertainty_until_sufficiently_adapted_) {
|
||||||
return 10.f;
|
return uncertainty_before_convergence_;
|
||||||
}
|
}
|
||||||
return absl::nullopt;
|
return absl::nullopt;
|
||||||
}
|
}
|
||||||
@ -182,6 +182,10 @@ class AecState {
|
|||||||
const bool no_alignment_required_for_linear_mode_;
|
const bool no_alignment_required_for_linear_mode_;
|
||||||
const bool use_uncertainty_until_sufficiently_adapted_;
|
const bool use_uncertainty_until_sufficiently_adapted_;
|
||||||
const bool transparent_mode_enforces_nonlinear_mode_;
|
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_;
|
ErlEstimator erl_estimator_;
|
||||||
ErleEstimator erle_estimator_;
|
ErleEstimator erle_estimator_;
|
||||||
size_t capture_block_counter_ = 0;
|
size_t capture_block_counter_ = 0;
|
||||||
|
@ -54,9 +54,18 @@ bool EnableShadowFilterJumpstart() {
|
|||||||
return !field_trial::IsEnabled("WebRTC-Aec3ShadowFilterJumpstartKillSwitch");
|
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..
|
// Method for adjusting config parameter dependencies..
|
||||||
EchoCanceller3Config AdjustConfig(const EchoCanceller3Config& config) {
|
EchoCanceller3Config AdjustConfig(const EchoCanceller3Config& config) {
|
||||||
EchoCanceller3Config adjusted_cfg = config;
|
EchoCanceller3Config adjusted_cfg = config;
|
||||||
|
const EchoCanceller3Config default_cfg;
|
||||||
|
|
||||||
if (!EnableReverbModelling()) {
|
if (!EnableReverbModelling()) {
|
||||||
adjusted_cfg.ep_strength.default_len = 0.f;
|
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;
|
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;
|
return adjusted_cfg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,12 +40,15 @@ void SubtractorOutputAnalyzer::Update(
|
|||||||
float min_e2 =
|
float min_e2 =
|
||||||
strict_divergence_check_ ? std::min(e2_main, e2_shadow) : e2_main;
|
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_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() {
|
void SubtractorOutputAnalyzer::HandleEchoPathChange() {
|
||||||
shadow_filter_converged_ = false;
|
shadow_filter_converged_ = false;
|
||||||
main_filter_converged_ = false;
|
main_filter_converged_ = false;
|
||||||
filter_diverged_ = false;
|
filter_diverged_ = false;
|
||||||
|
filter_severely_diverged_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
@ -30,6 +30,7 @@ class SubtractorOutputAnalyzer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool DivergedFilter() const { return filter_diverged_; }
|
bool DivergedFilter() const { return filter_diverged_; }
|
||||||
|
bool SeverelyDivergedFilter() const { return filter_severely_diverged_; }
|
||||||
|
|
||||||
// Handle echo path change.
|
// Handle echo path change.
|
||||||
void HandleEchoPathChange();
|
void HandleEchoPathChange();
|
||||||
@ -39,6 +40,7 @@ class SubtractorOutputAnalyzer {
|
|||||||
bool shadow_filter_converged_ = false;
|
bool shadow_filter_converged_ = false;
|
||||||
bool main_filter_converged_ = false;
|
bool main_filter_converged_ = false;
|
||||||
bool filter_diverged_ = false;
|
bool filter_diverged_ = false;
|
||||||
|
bool filter_severely_diverged_ = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
@ -35,6 +35,12 @@ class SuppressionGainUpperLimiter {
|
|||||||
// Return whether the suppressor gain limit is active.
|
// Return whether the suppressor gain limit is active.
|
||||||
bool IsActive() const { return (realignment_counter_ > 0); }
|
bool IsActive() const { return (realignment_counter_ > 0); }
|
||||||
|
|
||||||
|
// Inactivate limiter.
|
||||||
|
void Deactivate() {
|
||||||
|
realignment_counter_ = 0;
|
||||||
|
suppressor_gain_limit_ = 1.f;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const EchoCanceller3Config::EchoRemovalControl::GainRampup rampup_config_;
|
const EchoCanceller3Config::EchoRemovalControl::GainRampup rampup_config_;
|
||||||
const float gain_rampup_increase_;
|
const float gain_rampup_increase_;
|
||||||
|
Reference in New Issue
Block a user