Separating the AEC3 suppressor gain rampup behavior for call startup and in-call resets
This CL introduces a different rampup behavir for the call startup and after resets that may occur due to delay changes, clock-drift and audio path glitches. Bug: chromium:819111, webrtc:8979 Change-Id: Ied1d7896be7f0c69aa6deb61475117021ca6ab09 Reviewed-on: https://webrtc-review.googlesource.com/60002 Reviewed-by: Gustaf Ullberg <gustaf@webrtc.org> Reviewed-by: Jesus de Vicente Pena <devicentepena@webrtc.org> Commit-Queue: Per Åhgren <peah@webrtc.org> Cr-Commit-Position: refs/heads/master@{#22312}
This commit is contained in:
@ -88,6 +88,8 @@ rtc_static_library("aec3") {
|
||||
"suppression_filter.h",
|
||||
"suppression_gain.cc",
|
||||
"suppression_gain.h",
|
||||
"suppression_gain_limiter.cc",
|
||||
"suppression_gain_limiter.h",
|
||||
"vector_buffer.cc",
|
||||
"vector_buffer.h",
|
||||
"vector_math.h",
|
||||
|
@ -63,7 +63,8 @@ AecState::AecState(const EchoCanceller3Config& config)
|
||||
config_(config),
|
||||
max_render_(config_.filter.main.length_blocks, 0.f),
|
||||
reverb_decay_(fabsf(config_.ep_strength.default_len)),
|
||||
gain_rampup_increase_(ComputeGainRampupIncrease(config_)) {}
|
||||
gain_rampup_increase_(ComputeGainRampupIncrease(config_)),
|
||||
suppression_gain_limiter_(config_) {}
|
||||
|
||||
AecState::~AecState() = default;
|
||||
|
||||
@ -83,6 +84,7 @@ void AecState::HandleEchoPathChange(
|
||||
render_received_ = false;
|
||||
blocks_with_active_render_ = 0;
|
||||
initial_state_ = true;
|
||||
suppression_gain_limiter_.Reset();
|
||||
};
|
||||
|
||||
// TODO(peah): Refine the reset scheme according to the type of gain and
|
||||
@ -96,7 +98,6 @@ void AecState::HandleEchoPathChange(
|
||||
full_reset();
|
||||
} else if (echo_path_variability.delay_change !=
|
||||
EchoPathVariability::DelayAdjustment::kBufferFlush) {
|
||||
active_render_seen_ = false;
|
||||
full_reset();
|
||||
} else if (echo_path_variability.delay_change !=
|
||||
EchoPathVariability::DelayAdjustment::kDelayReset) {
|
||||
@ -136,7 +137,7 @@ void AecState::Update(
|
||||
|
||||
// Update the limit on the echo suppression after an echo path change to avoid
|
||||
// an initial echo burst.
|
||||
UpdateSuppressorGainLimit(render_buffer.GetRenderActivity());
|
||||
suppression_gain_limiter_.Update(render_buffer.GetRenderActivity());
|
||||
|
||||
// Update the ERL and ERLE measures.
|
||||
if (converged_filter && capture_block_counter_ >= 2 * kNumBlocksPerSecond) {
|
||||
@ -360,6 +361,7 @@ void AecState::UpdateReverb(const std::vector<float>& impulse_response) {
|
||||
|
||||
data_dumper_->DumpRaw("aec3_reverb_decay", reverb_decay_);
|
||||
data_dumper_->DumpRaw("aec3_reverb_tail_energy", tail_energy_);
|
||||
data_dumper_->DumpRaw("aec3_suppression_gain_limit", SuppressionGainLimit());
|
||||
}
|
||||
|
||||
bool AecState::DetectActiveRender(rtc::ArrayView<const float> x) const {
|
||||
@ -369,37 +371,6 @@ bool AecState::DetectActiveRender(rtc::ArrayView<const float> x) const {
|
||||
kFftLengthBy2;
|
||||
}
|
||||
|
||||
// Updates the suppressor gain limit.
|
||||
void AecState::UpdateSuppressorGainLimit(bool render_activity) {
|
||||
const auto& rampup_conf = config_.echo_removal_control.gain_rampup;
|
||||
if (!active_render_seen_ && render_activity) {
|
||||
active_render_seen_ = true;
|
||||
realignment_counter_ = rampup_conf.full_gain_blocks;
|
||||
} else if (realignment_counter_ > 0) {
|
||||
--realignment_counter_;
|
||||
}
|
||||
|
||||
if (realignment_counter_ <= 0) {
|
||||
suppressor_gain_limit_ = 1.f;
|
||||
return;
|
||||
}
|
||||
|
||||
if (realignment_counter_ > rampup_conf.non_zero_gain_blocks) {
|
||||
suppressor_gain_limit_ = 0.f;
|
||||
return;
|
||||
}
|
||||
|
||||
if (realignment_counter_ == rampup_conf.non_zero_gain_blocks) {
|
||||
suppressor_gain_limit_ = rampup_conf.first_non_zero_gain;
|
||||
return;
|
||||
}
|
||||
|
||||
RTC_DCHECK_LT(0.f, suppressor_gain_limit_);
|
||||
suppressor_gain_limit_ =
|
||||
std::min(1.f, suppressor_gain_limit_ * gain_rampup_increase_);
|
||||
RTC_DCHECK_GE(1.f, suppressor_gain_limit_);
|
||||
}
|
||||
|
||||
bool AecState::DetectEchoSaturation(rtc::ArrayView<const float> x) {
|
||||
RTC_DCHECK_LT(0, x.size());
|
||||
const float max_sample = fabs(*std::max_element(
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "modules/audio_processing/aec3/erl_estimator.h"
|
||||
#include "modules/audio_processing/aec3/erle_estimator.h"
|
||||
#include "modules/audio_processing/aec3/render_buffer.h"
|
||||
#include "modules/audio_processing/aec3/suppression_gain_limiter.h"
|
||||
#include "rtc_base/constructormagic.h"
|
||||
|
||||
namespace webrtc {
|
||||
@ -91,7 +92,9 @@ class AecState {
|
||||
float ReverbDecay() const { return reverb_decay_; }
|
||||
|
||||
// Returns the upper limit for the echo suppression gain.
|
||||
float SuppressionGainLimit() const { return suppressor_gain_limit_; }
|
||||
float SuppressionGainLimit() const {
|
||||
return suppression_gain_limiter_.Limit();
|
||||
}
|
||||
|
||||
// Returns whether the echo in the capture signal is audible.
|
||||
bool InaudibleEcho() const { return echo_audibility_.InaudibleEcho(); }
|
||||
@ -156,9 +159,6 @@ class AecState {
|
||||
bool transparent_mode_ = false;
|
||||
float previous_max_sample_ = 0.f;
|
||||
bool render_received_ = false;
|
||||
int realignment_counter_ = 0;
|
||||
float suppressor_gain_limit_ = 1.f;
|
||||
bool active_render_seen_ = false;
|
||||
int filter_delay_ = 0;
|
||||
size_t blocks_since_last_saturation_ = 1000;
|
||||
float tail_energy_ = 0.f;
|
||||
@ -179,6 +179,7 @@ class AecState {
|
||||
bool filter_has_had_time_to_converge_ = false;
|
||||
bool initial_state_ = true;
|
||||
const float gain_rampup_increase_;
|
||||
SuppressionGainUpperLimiter suppression_gain_limiter_;
|
||||
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(AecState);
|
||||
};
|
||||
|
83
modules/audio_processing/aec3/suppression_gain_limiter.cc
Normal file
83
modules/audio_processing/aec3/suppression_gain_limiter.cc
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "modules/audio_processing/aec3/suppression_gain_limiter.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <algorithm>
|
||||
|
||||
#include "modules/audio_processing/aec3/aec3_common.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace {
|
||||
|
||||
// Computes the gain rampup factor to use.
|
||||
float ComputeGainRampupIncrease(
|
||||
const EchoCanceller3Config::EchoRemovalControl::GainRampup& rampup_config) {
|
||||
return powf(1.f / rampup_config.first_non_zero_gain,
|
||||
1.f / rampup_config.non_zero_gain_blocks);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
SuppressionGainUpperLimiter::SuppressionGainUpperLimiter(
|
||||
const EchoCanceller3Config& config)
|
||||
: rampup_config_(config.echo_removal_control.gain_rampup),
|
||||
gain_rampup_increase_(ComputeGainRampupIncrease(rampup_config_)) {
|
||||
Reset();
|
||||
}
|
||||
|
||||
void SuppressionGainUpperLimiter::Reset() {
|
||||
recent_reset_ = true;
|
||||
}
|
||||
|
||||
void SuppressionGainUpperLimiter::Update(bool render_activity) {
|
||||
if (recent_reset_ && !call_startup_phase_) {
|
||||
// Only enforce 250 ms full suppression after in-call resets,
|
||||
constexpr int kMuteFramesAfterReset = kNumBlocksPerSecond / 4;
|
||||
realignment_counter_ = kMuteFramesAfterReset;
|
||||
} else if (!active_render_seen_ && render_activity) {
|
||||
// Enforce a tailormade suppression limiting during call startup.
|
||||
active_render_seen_ = true;
|
||||
realignment_counter_ = rampup_config_.full_gain_blocks;
|
||||
} else if (realignment_counter_ > 0) {
|
||||
if (--realignment_counter_ == 0) {
|
||||
call_startup_phase_ = false;
|
||||
}
|
||||
}
|
||||
recent_reset_ = false;
|
||||
|
||||
// Do not enforce any gain limit on the suppressor.
|
||||
if (realignment_counter_ <= 0) {
|
||||
suppressor_gain_limit_ = 1.f;
|
||||
return;
|
||||
}
|
||||
|
||||
// Enforce full suppression.
|
||||
if (realignment_counter_ > rampup_config_.non_zero_gain_blocks ||
|
||||
(!call_startup_phase_ && realignment_counter_ > 0)) {
|
||||
suppressor_gain_limit_ = 0.f;
|
||||
return;
|
||||
}
|
||||
|
||||
// Start increasing the gain limit.
|
||||
if (realignment_counter_ == rampup_config_.non_zero_gain_blocks) {
|
||||
suppressor_gain_limit_ = rampup_config_.first_non_zero_gain;
|
||||
return;
|
||||
}
|
||||
|
||||
// Increase the gain limit until it reaches 1.f.
|
||||
RTC_DCHECK_LT(0.f, suppressor_gain_limit_);
|
||||
suppressor_gain_limit_ =
|
||||
std::min(1.f, suppressor_gain_limit_ * gain_rampup_increase_);
|
||||
RTC_DCHECK_GE(1.f, suppressor_gain_limit_);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
49
modules/audio_processing/aec3/suppression_gain_limiter.h
Normal file
49
modules/audio_processing/aec3/suppression_gain_limiter.h
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef MODULES_AUDIO_PROCESSING_AEC3_SUPPRESSION_GAIN_LIMITER_H_
|
||||
#define MODULES_AUDIO_PROCESSING_AEC3_SUPPRESSION_GAIN_LIMITER_H_
|
||||
|
||||
#include "api/array_view.h"
|
||||
#include "api/audio/echo_canceller3_config.h"
|
||||
#include "rtc_base/constructormagic.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// Class for applying a smoothly increasing limit for the suppression gain
|
||||
// during call startup and after in-call resets.
|
||||
class SuppressionGainUpperLimiter {
|
||||
public:
|
||||
explicit SuppressionGainUpperLimiter(const EchoCanceller3Config& config);
|
||||
|
||||
// Reset the limiting behavior.
|
||||
void Reset();
|
||||
|
||||
// Updates the limiting behavior for the current capture bloc.
|
||||
void Update(bool render_activity);
|
||||
|
||||
// Returns the current suppressor gain limit.
|
||||
float Limit() const { return suppressor_gain_limit_; }
|
||||
|
||||
private:
|
||||
const EchoCanceller3Config::EchoRemovalControl::GainRampup rampup_config_;
|
||||
const float gain_rampup_increase_;
|
||||
bool call_startup_phase_ = true;
|
||||
int realignment_counter_ = 0;
|
||||
bool active_render_seen_ = false;
|
||||
float suppressor_gain_limit_ = 1.f;
|
||||
bool recent_reset_ = false;
|
||||
|
||||
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(SuppressionGainUpperLimiter);
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // MODULES_AUDIO_PROCESSING_AEC3_SUPPRESSION_GAIN_LIMITER_H_
|
Reference in New Issue
Block a user