AEC3: Adding a reset of the ERLE estimator after going out from the initial state.

Bug: webrtc:9685
Change-Id: Ifc6019811c3d90df91df07e68f1d04cb39cb3545
Reviewed-on: https://webrtc-review.googlesource.com/96661
Reviewed-by: Per Åhgren <peah@webrtc.org>
Commit-Queue: Jesus de Vicente Pena <devicentepena@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#24484}
This commit is contained in:
Jesús de Vicente Peña
2018-08-29 13:34:07 +02:00
committed by Commit Bot
parent 8fdcac3f06
commit 02e9e44c0c
3 changed files with 14 additions and 10 deletions

View File

@ -235,6 +235,9 @@ void AecState::Update(
} }
// Update the ERL and ERLE measures. // Update the ERL and ERLE measures.
if (reset_erle_after_echo_path_changes_ && transition_triggered_) {
erle_estimator_.Reset();
}
if (blocks_since_reset_ >= 2 * kNumBlocksPerSecond) { if (blocks_since_reset_ >= 2 * kNumBlocksPerSecond) {
const auto& X2 = render_buffer.Spectrum(filter_delay_blocks_); const auto& X2 = render_buffer.Spectrum(filter_delay_blocks_);
erle_estimator_.Update(X2, Y2, E2_main, converged_filter, erle_estimator_.Update(X2, Y2, E2_main, converged_filter,
@ -267,6 +270,7 @@ void AecState::Update(
} }
// Flag whether the initial state is still active. // Flag whether the initial state is still active.
bool prev_initial_state = initial_state_;
if (use_short_initial_state_) { if (use_short_initial_state_) {
initial_state_ = blocks_with_proper_filter_adaptation_ < initial_state_ = blocks_with_proper_filter_adaptation_ <
config_.filter.initial_state_seconds * kNumBlocksPerSecond; config_.filter.initial_state_seconds * kNumBlocksPerSecond;
@ -274,6 +278,7 @@ void AecState::Update(
initial_state_ = initial_state_ =
blocks_with_proper_filter_adaptation_ < 5 * kNumBlocksPerSecond; blocks_with_proper_filter_adaptation_ < 5 * kNumBlocksPerSecond;
} }
transition_triggered_ = !initial_state_ && prev_initial_state;
// Update counters for the filter divergence and convergence. // Update counters for the filter divergence and convergence.
diverged_blocks_ = diverged_filter ? diverged_blocks_ + 1 : 0; diverged_blocks_ = diverged_filter ? diverged_blocks_ + 1 : 0;
@ -382,7 +387,7 @@ void AecState::Update(
data_dumper_->DumpRaw("aec3_consistent_filter", data_dumper_->DumpRaw("aec3_consistent_filter",
filter_analyzer_.Consistent()); filter_analyzer_.Consistent());
data_dumper_->DumpRaw("aec3_suppression_gain_limit", SuppressionGainLimit()); 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_capture_saturation", SaturatedCapture());
data_dumper_->DumpRaw("aec3_echo_saturation", echo_saturation_); data_dumper_->DumpRaw("aec3_echo_saturation", echo_saturation_);
data_dumper_->DumpRaw("aec3_converged_filter", converged_filter); data_dumper_->DumpRaw("aec3_converged_filter", converged_filter);

View File

@ -140,8 +140,9 @@ class AecState {
return filter_has_had_time_to_converge_; return filter_has_had_time_to_converge_;
} }
// Returns whether the filter adaptation is still in the initial state. // Returns whether the transition for going out of the initial stated has
bool InitialState() const { return initial_state_; } // been triggered.
bool TransitionTriggered() const { return transition_triggered_; }
// Updates the aec state. // Updates the aec state.
void Update(const absl::optional<DelayEstimate>& external_delay, void Update(const absl::optional<DelayEstimate>& external_delay,
@ -197,6 +198,7 @@ class AecState {
std::vector<float> max_render_; std::vector<float> max_render_;
bool filter_has_had_time_to_converge_ = false; bool filter_has_had_time_to_converge_ = false;
bool initial_state_ = true; bool initial_state_ = true;
bool transition_triggered_ = false;
const float gain_rampup_increase_; const float gain_rampup_increase_;
SuppressionGainUpperLimiter suppression_gain_limiter_; SuppressionGainUpperLimiter suppression_gain_limiter_;
FilterAnalyzer filter_analyzer_; FilterAnalyzer filter_analyzer_;

View File

@ -141,7 +141,6 @@ class EchoRemoverImpl final : public EchoRemover {
bool echo_leakage_detected_ = false; bool echo_leakage_detected_ = false;
AecState aec_state_; AecState aec_state_;
EchoRemoverMetrics metrics_; EchoRemoverMetrics metrics_;
bool initial_state_ = true;
std::array<float, kFftLengthBy2> e_old_; std::array<float, kFftLengthBy2> e_old_;
std::array<float, kFftLengthBy2> x_old_; std::array<float, kFftLengthBy2> x_old_;
std::array<float, kFftLengthBy2> y_old_; std::array<float, kFftLengthBy2> y_old_;
@ -233,7 +232,6 @@ void EchoRemoverImpl::ProcessCapture(
if (echo_path_variability.delay_change != if (echo_path_variability.delay_change !=
EchoPathVariability::DelayAdjustment::kNone) { EchoPathVariability::DelayAdjustment::kNone) {
suppression_gain_.SetInitialState(true); suppression_gain_.SetInitialState(true);
initial_state_ = true;
} }
} }
if (gain_change_hangover_ > 0) { if (gain_change_hangover_ > 0) {
@ -257,10 +255,9 @@ void EchoRemoverImpl::ProcessCapture(
aec_state_.FilterDelayBlocks()); aec_state_.FilterDelayBlocks());
// Perform linear echo cancellation. // Perform linear echo cancellation.
if (initial_state_ && !aec_state_.InitialState()) { if (aec_state_.TransitionTriggered()) {
subtractor_.ExitInitialState(); subtractor_.ExitInitialState();
suppression_gain_.SetInitialState(false); suppression_gain_.SetInitialState(false);
initial_state_ = false;
} }
// If the delay is known, use the echo subtractor. // 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()); RTC_DCHECK_EQ(subtractor_output.e_shadow.size(), output.size());
bool use_main_output = true; bool use_main_output = true;
if (use_shadow_filter_output_) { if (use_shadow_filter_output_) {
// As the output of the main adaptive filter generally should be better than // As the output of the main adaptive filter generally should be better
// the shadow filter output, add a margin and threshold for when choosing // than the shadow filter output, add a margin and threshold for when
// the shadow filter output. // choosing the shadow filter output.
if (subtractor_output.e2_shadow < 0.9f * subtractor_output.e2_main && if (subtractor_output.e2_shadow < 0.9f * subtractor_output.e2_main &&
subtractor_output.y2 > 30.f * 30.f * kBlockSize && subtractor_output.y2 > 30.f * 30.f * kBlockSize &&
(subtractor_output.s2_main > 60.f * 60.f * kBlockSize || (subtractor_output.s2_main > 60.f * 60.f * kBlockSize ||