AEC3: Remove remaining kill-switches

This CL concludes the post-launch removal of kill-switches is AEC3.

Kill-switches removed:
WebRTC-Aec3AdaptErleOnLowRenderKillSwitch
WebRTC-Aec3AgcGainChangeResponseKillSwitch
WebRTC-Aec3BoundedNearendKillSwitch
WebRTC-Aec3EarlyShadowFilterJumpstartKillSwitch
WebRTC-Aec3EnableAdaptiveEchoReverbEstimation
WebRTC-Aec3EnforceSkewHysteresis1
WebRTC-Aec3EnforceSkewHysteresis2
WebRTC-Aec3FilterAnalyzerPreprocessorKillSwitch
WebRTC-Aec3MisadjustmentEstimatorKillSwitch
WebRTC-Aec3OverrideEchoPathGainKillSwitch
WebRTC-Aec3RapidAgcGainRecoveryKillSwitch
WebRTC-Aec3ResetErleAtGainChangesKillSwitch
WebRTC-Aec3ShadowFilterBoostedJumpstartKillSwitch
WebRTC-Aec3ShadowFilterJumpstartKillSwitch
WebRTC-Aec3SmoothSignalTransitionsKillSwitch
WebRTC-Aec3SmoothUpdatesTailFreqRespKillSwitch
WebRTC-Aec3SoftTransparentModeKillSwitch
WebRTC-Aec3StandardNonlinearReverbModelKillSwitch
WebRTC-Aec3StrictDivergenceCheckKillSwitch
WebRTC-Aec3UseOffsetBlocks
WebRTC-Aec3UseStationarityPropertiesKillSwitch
WebRTC-Aec3UtilizeShadowFilterOutputKillSwitch
WebRTC-Aec3ZeroExternalDelayHeadroomKillSwitch
WebRTC-Aec3FilterQualityStateKillSwitch
WebRTC-Aec3NewSaturationBehaviorKillSwitch
WebRTC-Aec3GainLimiterDeactivationKillSwitch
WebRTC-Aec3EnableErleUpdatesDuringReverbKillSwitch

The change has been tested for bit-exactness.

Bug: webrtc:8671
Change-Id: I42816b9d1c875cec0347034c6e2ed4ff5db6ec0f
Reviewed-on: https://webrtc-review.googlesource.com/c/119942
Commit-Queue: Gustaf Ullberg <gustaf@webrtc.org>
Reviewed-by: Sam Zackrisson <saza@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#26443}
This commit is contained in:
Gustaf Ullberg
2019-01-29 10:08:15 +01:00
committed by Commit Bot
parent 649a4c2ea3
commit 68d6d44197
28 changed files with 84 additions and 634 deletions

View File

@ -120,8 +120,6 @@ 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",
@ -145,7 +143,6 @@ rtc_static_library("aec3") {
"../../../rtc_base:safe_minmax",
"../../../rtc_base/system:arch",
"../../../system_wrappers:cpu_features_api",
"../../../system_wrappers:field_trial",
"../../../system_wrappers:metrics",
"../utility:ooura_fft",
"//third_party/abseil-cpp/absl/types:optional",

View File

@ -24,7 +24,6 @@
#include "modules/audio_processing/aec3/fft_data.h"
#include "rtc_base/checks.h"
#include "system_wrappers/include/field_trial.h"
namespace webrtc {
@ -417,21 +416,12 @@ void ApplyFilter_SSE2(const RenderBuffer& render_buffer,
} // namespace aec3
namespace {
bool EnablePartialFilterReset() {
return !field_trial::IsEnabled("WebRTC-Aec3PartialFilterResetKillSwitch");
}
} // namespace
AdaptiveFirFilter::AdaptiveFirFilter(size_t max_size_partitions,
size_t initial_size_partitions,
size_t size_change_duration_blocks,
Aec3Optimization optimization,
ApmDataDumper* data_dumper)
: data_dumper_(data_dumper),
use_partial_filter_reset_(EnablePartialFilterReset()),
fft_(),
optimization_(optimization),
max_size_partitions_(max_size_partitions),
@ -464,18 +454,14 @@ AdaptiveFirFilter::~AdaptiveFirFilter() = default;
void AdaptiveFirFilter::HandleEchoPathChange() {
size_t current_h_size = h_.size();
h_.resize(GetTimeDomainLength(max_size_partitions_));
const size_t begin_coeffficient =
use_partial_filter_reset_ ? current_h_size : 0;
std::fill(h_.begin() + begin_coeffficient, h_.end(), 0.f);
std::fill(h_.begin() + current_h_size, h_.end(), 0.f);
h_.resize(current_h_size);
size_t current_size_partitions = H_.size();
H_.resize(max_size_partitions_);
H2_.resize(max_size_partitions_);
const size_t begin_partition =
use_partial_filter_reset_ ? current_size_partitions : 0;
for (size_t k = begin_partition; k < max_size_partitions_; ++k) {
for (size_t k = current_size_partitions; k < max_size_partitions_; ++k) {
H_[k].Clear();
H2_[k].fill(0.f);
}

View File

@ -164,7 +164,6 @@ class AdaptiveFirFilter {
void UpdateSize();
ApmDataDumper* const data_dumper_;
const bool use_partial_filter_reset_;
const Aec3Fft fft_;
const Aec3Optimization optimization_;
const size_t max_size_partitions_;

View File

@ -21,31 +21,10 @@
#include "modules/audio_processing/logging/apm_data_dumper.h"
#include "rtc_base/atomic_ops.h"
#include "rtc_base/checks.h"
#include "system_wrappers/include/field_trial.h"
namespace webrtc {
namespace {
bool EnableErleResetsAtGainChanges() {
return !field_trial::IsEnabled("WebRTC-Aec3ResetErleAtGainChangesKillSwitch");
}
bool UseLegacyFilterQualityState() {
return field_trial::IsEnabled("WebRTC-Aec3FilterQualityStateKillSwitch");
}
bool EnableLegacySaturationBehavior() {
return field_trial::IsEnabled("WebRTC-Aec3NewSaturationBehaviorKillSwitch");
}
bool UseSuppressionGainLimiter() {
return field_trial::IsEnabled("WebRTC-Aec3GainLimiterDeactivationKillSwitch");
}
bool EnableErleUpdatesDuringReverb() {
return !field_trial::IsEnabled(
"WebRTC-Aec3EnableErleUpdatesDuringReverbKillSwitch");
}
constexpr size_t kBlocksSinceConvergencedFilterInit = 10000;
constexpr size_t kBlocksSinceConsistentEstimateInit = 10000;
@ -68,7 +47,7 @@ void AecState::GetResidualEchoScaling(
}
absl::optional<float> AecState::ErleUncertainty() const {
if (SaturatedEcho() && use_legacy_saturation_behavior_) {
if (SaturatedEcho()) {
return 1.f;
}
@ -79,11 +58,6 @@ AecState::AecState(const EchoCanceller3Config& config)
: data_dumper_(
new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))),
config_(config),
use_legacy_saturation_behavior_(EnableLegacySaturationBehavior()),
enable_erle_resets_at_gain_changes_(EnableErleResetsAtGainChanges()),
enable_erle_updates_during_reverb_(EnableErleUpdatesDuringReverb()),
use_legacy_filter_quality_(UseLegacyFilterQualityState()),
use_suppressor_gain_limiter_(UseSuppressionGainLimiter()),
initial_state_(config_),
delay_state_(config_),
transparent_state_(config_),
@ -92,7 +66,6 @@ AecState::AecState(const EchoCanceller3Config& config)
legacy_saturation_detector_(config_),
erl_estimator_(2 * kNumBlocksPerSecond),
erle_estimator_(2 * kNumBlocksPerSecond, config_),
suppression_gain_limiter_(config_),
filter_analyzer_(config_),
echo_audibility_(
config_.echo_audibility.use_stationarity_properties_at_init),
@ -107,21 +80,12 @@ void AecState::HandleEchoPathChange(
capture_signal_saturation_ = false;
strong_not_saturated_render_blocks_ = 0;
blocks_with_active_render_ = 0;
if (use_suppressor_gain_limiter_) {
suppression_gain_limiter_.Reset();
}
initial_state_.Reset();
transparent_state_.Reset();
if (use_legacy_saturation_behavior_) {
legacy_saturation_detector_.Reset();
}
erle_estimator_.Reset(true);
erl_estimator_.Reset();
if (use_legacy_filter_quality_) {
legacy_filter_quality_state_.Reset();
} else {
filter_quality_state_.Reset();
}
};
// TODO(peah): Refine the reset scheme according to the type of gain and
@ -130,8 +94,7 @@ void AecState::HandleEchoPathChange(
if (echo_path_variability.delay_change !=
EchoPathVariability::DelayAdjustment::kNone) {
full_reset();
} else if (enable_erle_resets_at_gain_changes_ &&
echo_path_variability.gain_change) {
} else if (echo_path_variability.gain_change) {
erle_estimator_.Reset(false);
}
subtractor_output_analyzer_.HandleEchoPathChange();
@ -172,17 +135,6 @@ void AecState::Update(
strong_not_saturated_render_blocks_ +=
active_render && !SaturatedCapture() ? 1 : 0;
if (use_suppressor_gain_limiter_) {
// Update the limit on the echo suppression after an echo path change to
// avoid an initial echo burst.
suppression_gain_limiter_.Update(render_buffer.GetRenderActivity(),
TransparentMode());
if (subtractor_output_analyzer_.ConvergedFilter()) {
suppression_gain_limiter_.Deactivate();
}
}
std::array<float, kFftLengthBy2Plus1> X2_reverb;
render_reverb_.Apply(
render_buffer.GetSpectrumBuffer(), delay_state_.DirectPathFilterDelay(),
@ -203,8 +155,7 @@ void AecState::Update(
}
const auto& X2 = render_buffer.Spectrum(delay_state_.DirectPathFilterDelay());
const auto& X2_input_erle =
enable_erle_updates_during_reverb_ ? X2_reverb : X2;
const auto& X2_input_erle = X2_reverb;
erle_estimator_.Update(render_buffer, adaptive_filter_frequency_response,
X2_input_erle, Y2, E2_main,
@ -214,14 +165,9 @@ void AecState::Update(
erl_estimator_.Update(subtractor_output_analyzer_.ConvergedFilter(), X2, Y2);
// Detect and flag echo saturation.
if (use_legacy_saturation_behavior_) {
legacy_saturation_detector_.Update(aligned_render_block, SaturatedCapture(),
EchoPathGain());
} else {
saturation_detector_.Update(aligned_render_block, SaturatedCapture(),
UsableLinearEstimate(), subtractor_output,
EchoPathGain());
}
saturation_detector_.Update(aligned_render_block, SaturatedCapture(),
UsableLinearEstimate(), subtractor_output,
EchoPathGain());
// Update the decision on whether to use the initial state parameter set.
initial_state_.Update(active_render, SaturatedCapture());
@ -234,17 +180,10 @@ void AecState::Update(
active_render, SaturatedCapture());
// Analyze the quality of the filter.
if (use_legacy_filter_quality_) {
legacy_filter_quality_state_.Update(
SaturatedEcho(), active_render, SaturatedCapture(), TransparentMode(),
external_delay, subtractor_output_analyzer_.ConvergedFilter(),
subtractor_output_analyzer_.DivergedFilter());
} else {
filter_quality_state_.Update(active_render, TransparentMode(),
SaturatedCapture(),
filter_analyzer_.Consistent(), external_delay,
subtractor_output_analyzer_.ConvergedFilter());
}
filter_quality_state_.Update(active_render, TransparentMode(),
SaturatedCapture(),
filter_analyzer_.Consistent(), external_delay,
subtractor_output_analyzer_.ConvergedFilter());
// Update the reverb estimate.
const bool stationary_block =
@ -268,7 +207,6 @@ void AecState::Update(
data_dumper_->DumpRaw("aec3_consistent_filter",
filter_analyzer_.Consistent());
data_dumper_->DumpRaw("aec3_suppression_gain_limit", SuppressionGainLimit());
data_dumper_->DumpRaw("aec3_initial_state",
initial_state_.InitialStateActive());
data_dumper_->DumpRaw("aec3_capture_saturation", SaturatedCapture());
@ -280,8 +218,6 @@ void AecState::Update(
data_dumper_->DumpRaw("aec3_external_delay_avaliable",
external_delay ? 1 : 0);
data_dumper_->DumpRaw("aec3_suppresion_gain_limiter_running",
IsSuppressionGainLimitActive());
data_dumper_->DumpRaw("aec3_filter_tail_freq_resp_est",
GetReverbFrequencyResponse());
}

View File

@ -31,7 +31,6 @@
#include "modules/audio_processing/aec3/reverb_model_estimator.h"
#include "modules/audio_processing/aec3/subtractor_output.h"
#include "modules/audio_processing/aec3/subtractor_output_analyzer.h"
#include "modules/audio_processing/aec3/suppression_gain_limiter.h"
namespace webrtc {
@ -46,17 +45,11 @@ class AecState {
// Returns whether the echo subtractor can be used to determine the residual
// echo.
bool UsableLinearEstimate() const {
if (use_legacy_filter_quality_) {
return legacy_filter_quality_state_.LinearFilterUsable();
}
return filter_quality_state_.LinearFilterUsable();
}
// Returns whether the echo subtractor output should be used as output.
bool UseLinearFilterOutput() const {
if (use_legacy_filter_quality_) {
return legacy_filter_quality_state_.LinearFilterUsable();
}
return filter_quality_state_.LinearFilterUsable();
}
@ -105,11 +98,7 @@ class AecState {
bool SaturatedCapture() const { return capture_signal_saturation_; }
// Returns whether the echo signal is saturated.
bool SaturatedEcho() const {
return use_legacy_saturation_behavior_
? legacy_saturation_detector_.SaturatedEcho()
: saturation_detector_.SaturatedEcho();
}
bool SaturatedEcho() const { return saturation_detector_.SaturatedEcho(); }
// Updates the capture signal saturation.
void UpdateCaptureSaturation(bool capture_signal_saturation) {
@ -130,20 +119,6 @@ class AecState {
return reverb_model_estimator_.GetReverbFrequencyResponse();
}
// Returns the upper limit for the echo suppression gain.
float SuppressionGainLimit() const {
if (use_suppressor_gain_limiter_) {
return suppression_gain_limiter_.Limit();
} else {
return 1.f;
}
}
// Returns whether the suppression gain limiter is active.
bool IsSuppressionGainLimitActive() const {
return suppression_gain_limiter_.IsActive();
}
// Returns whether the transition for going out of the initial stated has
// been triggered.
bool TransitionTriggered() const {
@ -170,11 +145,6 @@ class AecState {
static int instance_count_;
std::unique_ptr<ApmDataDumper> data_dumper_;
const EchoCanceller3Config config_;
const bool use_legacy_saturation_behavior_;
const bool enable_erle_resets_at_gain_changes_;
const bool enable_erle_updates_during_reverb_;
const bool use_legacy_filter_quality_;
const bool use_suppressor_gain_limiter_;
// Class for controlling the transition from the intial state, which in turn
// controls when the filter parameters for the initial state should be used.
@ -378,8 +348,6 @@ class AecState {
size_t strong_not_saturated_render_blocks_ = 0;
size_t blocks_with_active_render_ = 0;
bool capture_signal_saturation_ = false;
SuppressionGainUpperLimiter suppression_gain_limiter_;
FilterAnalyzer filter_analyzer_;
absl::optional<DelayEstimate> external_delay_;
EchoAudibility echo_audibility_;

View File

@ -15,7 +15,6 @@
#include "modules/audio_processing/aec3/aec3_common.h"
#include "modules/audio_processing/logging/apm_data_dumper.h"
#include "rtc_base/atomic_ops.h"
#include "system_wrappers/include/field_trial.h"
namespace webrtc {

View File

@ -35,26 +35,11 @@
#include "rtc_base/checks.h"
#include "rtc_base/constructor_magic.h"
#include "rtc_base/logging.h"
#include "system_wrappers/include/field_trial.h"
namespace webrtc {
namespace {
bool UseShadowFilterOutput() {
return !field_trial::IsEnabled(
"WebRTC-Aec3UtilizeShadowFilterOutputKillSwitch");
}
bool UseSmoothSignalTransitions() {
return !field_trial::IsEnabled(
"WebRTC-Aec3SmoothSignalTransitionsKillSwitch");
}
bool EnableBoundedNearend() {
return !field_trial::IsEnabled("WebRTC-Aec3BoundedNearendKillSwitch");
}
void LinearEchoPower(const FftData& E,
const FftData& Y,
std::array<float, kFftLengthBy2Plus1>* S2) {
@ -127,8 +112,7 @@ class EchoRemoverImpl final : public EchoRemover {
// Selects which of the shadow and main linear filter outputs that is most
// appropriate to pass to the suppressor and forms the linear filter output by
// smoothly transition between those.
void FormLinearFilterOutput(bool smooth_transition,
const SubtractorOutput& subtractor_output,
void FormLinearFilterOutput(const SubtractorOutput& subtractor_output,
rtc::ArrayView<float> output);
static int instance_count_;
@ -138,8 +122,6 @@ class EchoRemoverImpl final : public EchoRemover {
const Aec3Optimization optimization_;
const int sample_rate_hz_;
const bool use_shadow_filter_output_;
const bool use_smooth_signal_transitions_;
const bool enable_bounded_nearend_;
Subtractor subtractor_;
SuppressionGain suppression_gain_;
ComfortNoiseGenerator cng_;
@ -171,10 +153,7 @@ EchoRemoverImpl::EchoRemoverImpl(const EchoCanceller3Config& config,
optimization_(DetectOptimization()),
sample_rate_hz_(sample_rate_hz),
use_shadow_filter_output_(
UseShadowFilterOutput() &&
config_.filter.enable_shadow_filter_output_usage),
use_smooth_signal_transitions_(UseSmoothSignalTransitions()),
enable_bounded_nearend_(EnableBoundedNearend()),
subtractor_(config, data_dumper_.get(), optimization_),
suppression_gain_(config_, optimization_, sample_rate_hz),
cng_(optimization_),
@ -275,7 +254,7 @@ void EchoRemoverImpl::ProcessCapture(
subtractor_.Process(*render_buffer, y0, render_signal_analyzer_, aec_state_,
&subtractor_output);
std::array<float, kBlockSize> e;
FormLinearFilterOutput(use_smooth_signal_transitions_, subtractor_output, e);
FormLinearFilterOutput(subtractor_output, e);
// Compute spectra.
WindowedPaddedFft(fft_, y0, y_old_, &Y);
@ -293,14 +272,13 @@ void EchoRemoverImpl::ProcessCapture(
data_dumper_->DumpWav("aec3_output_linear2", kBlockSize, &e[0],
LowestBandRate(sample_rate_hz_), 1);
if (aec_state_.UseLinearFilterOutput()) {
if (!linear_filter_output_last_selected_ &&
use_smooth_signal_transitions_) {
if (!linear_filter_output_last_selected_) {
SignalTransition(y0, e, y0);
} else {
std::copy(e.begin(), e.end(), y0.begin());
}
} else {
if (linear_filter_output_last_selected_ && use_smooth_signal_transitions_) {
if (linear_filter_output_last_selected_) {
SignalTransition(e, y0, y0);
}
}
@ -322,12 +300,8 @@ void EchoRemoverImpl::ProcessCapture(
aec_state_.UsableLinearEstimate() ? S2_linear : R2;
std::array<float, kFftLengthBy2Plus1> E2_bounded;
if (enable_bounded_nearend_) {
std::transform(E2.begin(), E2.end(), Y2.begin(), E2_bounded.begin(),
[](float a, float b) { return std::min(a, b); });
} else {
std::copy(E2.begin(), E2.end(), E2_bounded.begin());
}
std::transform(E2.begin(), E2.end(), Y2.begin(), E2_bounded.begin(),
[](float a, float b) { return std::min(a, b); });
suppression_gain_.GetGain(E2, E2_bounded, echo_spectrum, R2,
cng_.NoiseSpectrum(), E, Y, render_signal_analyzer_,
@ -367,7 +341,6 @@ void EchoRemoverImpl::ProcessCapture(
}
void EchoRemoverImpl::FormLinearFilterOutput(
bool smooth_transition,
const SubtractorOutput& subtractor_output,
rtc::ArrayView<float> output) {
RTC_DCHECK_EQ(subtractor_output.e_main.size(), output.size());
@ -393,7 +366,7 @@ void EchoRemoverImpl::FormLinearFilterOutput(
}
if (use_main_output) {
if (!main_filter_output_last_selected_ && smooth_transition) {
if (!main_filter_output_last_selected_) {
SignalTransition(subtractor_output.e_shadow, subtractor_output.e_main,
output);
} else {
@ -401,7 +374,7 @@ void EchoRemoverImpl::FormLinearFilterOutput(
subtractor_output.e_main.end(), output.begin());
}
} else {
if (main_filter_output_last_selected_ && smooth_transition) {
if (main_filter_output_last_selected_) {
SignalTransition(subtractor_output.e_main, subtractor_output.e_shadow,
output);
} else {

View File

@ -20,7 +20,6 @@
#include "modules/audio_processing/logging/apm_data_dumper.h"
#include "rtc_base/atomic_ops.h"
#include "rtc_base/checks.h"
#include "system_wrappers/include/field_trial.h"
namespace webrtc {
namespace {
@ -43,16 +42,6 @@ size_t FindPeakIndex(rtc::ArrayView<const float> filter_time_domain,
return peak_index_out;
}
bool EnableFilterPreprocessing() {
return !field_trial::IsEnabled(
"WebRTC-Aec3FilterAnalyzerPreprocessorKillSwitch");
}
bool EnableIncrementalAnalysis() {
return !field_trial::IsEnabled(
"WebRTC-Aec3FilterAnalyzerIncrementalAnalysisKillSwitch");
}
} // namespace
int FilterAnalyzer::instance_count_ = 0;
@ -60,10 +49,8 @@ int FilterAnalyzer::instance_count_ = 0;
FilterAnalyzer::FilterAnalyzer(const EchoCanceller3Config& config)
: data_dumper_(
new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))),
use_preprocessed_filter_(EnableFilterPreprocessing()),
bounded_erl_(config.ep_strength.bounded_erl),
default_gain_(config.ep_strength.lf),
use_incremental_analysis_(EnableIncrementalAnalysis()),
h_highpass_(GetTimeDomainLength(config.filter.main.length_blocks), 0.f),
filter_length_blocks_(config.filter.main_initial.length_blocks),
consistent_filter_detector_(config) {
@ -99,19 +86,17 @@ void FilterAnalyzer::AnalyzeRegion(
PreProcessFilter(filter_time_domain);
data_dumper_->DumpRaw("aec3_linear_filter_processed_td", h_highpass_);
const auto& filter_to_analyze =
use_preprocessed_filter_ ? h_highpass_ : filter_time_domain;
RTC_DCHECK_EQ(filter_to_analyze.size(), filter_time_domain.size());
RTC_DCHECK_EQ(h_highpass_.size(), filter_time_domain.size());
peak_index_ = FindPeakIndex(filter_to_analyze, peak_index_,
region_.start_sample_, region_.end_sample_);
peak_index_ = FindPeakIndex(h_highpass_, peak_index_, region_.start_sample_,
region_.end_sample_);
delay_blocks_ = peak_index_ >> kBlockSizeLog2;
UpdateFilterGain(filter_to_analyze, peak_index_);
UpdateFilterGain(h_highpass_, peak_index_);
filter_length_blocks_ = filter_time_domain.size() * (1.f / kBlockSize);
consistent_estimate_ = consistent_filter_detector_.Detect(
filter_to_analyze, region_, render_buffer.Block(-delay_blocks_)[0],
peak_index_, delay_blocks_);
h_highpass_, region_, render_buffer.Block(-delay_blocks_)[0], peak_index_,
delay_blocks_);
}
void FilterAnalyzer::UpdateFilterGain(
@ -159,17 +144,11 @@ void FilterAnalyzer::SetRegionToAnalyze(
rtc::ArrayView<const float> filter_time_domain) {
constexpr size_t kNumberBlocksToUpdate = 1;
auto& r = region_;
if (use_incremental_analysis_) {
r.start_sample_ =
r.end_sample_ == filter_time_domain.size() - 1 ? 0 : r.end_sample_ + 1;
r.end_sample_ =
std::min(r.start_sample_ + kNumberBlocksToUpdate * kBlockSize - 1,
filter_time_domain.size() - 1);
} else {
r.start_sample_ = 0;
r.end_sample_ = filter_time_domain.size() - 1;
}
}
FilterAnalyzer::ConsistentFilterDetector::ConsistentFilterDetector(

View File

@ -97,10 +97,8 @@ class FilterAnalyzer {
static int instance_count_;
std::unique_ptr<ApmDataDumper> data_dumper_;
const bool use_preprocessed_filter_;
const bool bounded_erl_;
const float default_gain_;
const bool use_incremental_analysis_;
std::vector<float> h_highpass_;
int delay_blocks_ = 0;
size_t blocks_since_reset_ = 0;

View File

@ -24,7 +24,6 @@
#include "rtc_base/atomic_ops.h"
#include "rtc_base/checks.h"
#include "rtc_base/constructor_magic.h"
#include "system_wrappers/include/field_trial.h"
namespace webrtc {

View File

@ -1,4 +1,3 @@
/*
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
*
@ -19,70 +18,36 @@
#include "modules/audio_processing/aec3/reverb_model.h"
#include "modules/audio_processing/aec3/reverb_model_fallback.h"
#include "rtc_base/checks.h"
#include "system_wrappers/include/field_trial.h"
namespace webrtc {
namespace {
bool EnableSoftTransparentMode() {
return !field_trial::IsEnabled("WebRTC-Aec3SoftTransparentModeKillSwitch");
}
bool OverrideEstimatedEchoPathGain() {
return !field_trial::IsEnabled("WebRTC-Aec3OverrideEchoPathGainKillSwitch");
}
bool UseFixedNonLinearReverbModel() {
return field_trial::IsEnabled(
"WebRTC-Aec3StandardNonlinearReverbModelKillSwitch");
}
// Computes the indexes that will be used for computing spectral power over
// the blocks surrounding the delay.
void GetRenderIndexesToAnalyze(
const VectorBuffer& spectrum_buffer,
const EchoCanceller3Config::EchoModel& echo_model,
int filter_delay_blocks,
bool gain_limiter_running,
int headroom,
int* idx_start,
int* idx_stop) {
RTC_DCHECK(idx_start);
RTC_DCHECK(idx_stop);
if (gain_limiter_running) {
if (static_cast<size_t>(headroom) >
echo_model.render_post_window_size_init) {
*idx_start = spectrum_buffer.OffsetIndex(
spectrum_buffer.read,
-static_cast<int>(echo_model.render_post_window_size_init));
} else {
*idx_start = spectrum_buffer.IncIndex(spectrum_buffer.write);
}
*idx_stop = spectrum_buffer.OffsetIndex(
spectrum_buffer.read, echo_model.render_pre_window_size_init);
} else {
size_t window_start;
size_t window_end;
window_start =
std::max(0, filter_delay_blocks -
static_cast<int>(echo_model.render_pre_window_size));
window_end = filter_delay_blocks +
static_cast<int>(echo_model.render_post_window_size);
*idx_start =
spectrum_buffer.OffsetIndex(spectrum_buffer.read, window_start);
*idx_stop =
spectrum_buffer.OffsetIndex(spectrum_buffer.read, window_end + 1);
}
size_t window_start;
size_t window_end;
window_start =
std::max(0, filter_delay_blocks -
static_cast<int>(echo_model.render_pre_window_size));
window_end = filter_delay_blocks +
static_cast<int>(echo_model.render_post_window_size);
*idx_start = spectrum_buffer.OffsetIndex(spectrum_buffer.read, window_start);
*idx_stop = spectrum_buffer.OffsetIndex(spectrum_buffer.read, window_end + 1);
}
} // namespace
ResidualEchoEstimator::ResidualEchoEstimator(const EchoCanceller3Config& config)
: config_(config),
soft_transparent_mode_(EnableSoftTransparentMode()),
override_estimated_echo_path_gain_(OverrideEstimatedEchoPathGain()),
use_fixed_nonlinear_reverb_model_(UseFixedNonLinearReverbModel()) {
: config_(config) {
if (config_.ep_strength.reverb_based_on_render) {
echo_reverb_.reset(new ReverbModel());
} else {
@ -136,7 +101,6 @@ void ResidualEchoEstimator::Estimate(
EchoGeneratingPower(render_buffer.GetSpectrumBuffer(), config_.echo_model,
render_buffer.Headroom(), aec_state.FilterDelayBlocks(),
aec_state.IsSuppressionGainLimitActive(),
!aec_state.UseStationaryProperties(), &X2);
// Subtract the stationary noise power to avoid stationary noise causing
@ -148,15 +112,8 @@ void ResidualEchoEstimator::Estimate(
});
float echo_path_gain;
if (override_estimated_echo_path_gain_) {
echo_path_gain = aec_state.TransparentMode() && soft_transparent_mode_
? 0.01f
: config_.ep_strength.lf;
} else {
echo_path_gain = aec_state.TransparentMode() && soft_transparent_mode_
? 0.01f
: aec_state.EchoPathGain();
}
echo_path_gain =
aec_state.TransparentMode() ? 0.01f : config_.ep_strength.lf;
NonLinearEstimate(echo_path_gain, X2, Y2, R2);
// When there is saturated echo, assume the same spectral content as is
@ -165,7 +122,7 @@ void ResidualEchoEstimator::Estimate(
std::copy(Y2.begin(), Y2.end(), R2->begin());
}
if (!(aec_state.TransparentMode() && soft_transparent_mode_)) {
if (!(aec_state.TransparentMode())) {
if (echo_reverb_) {
echo_reverb_->AddReverbNoFreqShaping(
render_buffer.Spectrum(aec_state.FilterDelayBlocks() + 1),
@ -190,14 +147,6 @@ void ResidualEchoEstimator::Estimate(
}
}
}
if (!soft_transparent_mode_) {
// If the echo is deemed inaudible, set the residual echo to zero.
if (aec_state.TransparentMode()) {
R2->fill(0.f);
R2_old_.fill(0.f);
R2_hold_counter_.fill(0.f);
}
}
std::copy(R2->begin(), R2->end(), R2_old_.begin());
}
@ -243,22 +192,6 @@ void ResidualEchoEstimator::NonLinearEstimate(
std::transform(X2.begin(), X2.end(), R2->begin(), [echo_path_gain](float a) {
return a * echo_path_gain * echo_path_gain;
});
if (use_fixed_nonlinear_reverb_model_) {
for (size_t k = 0; k < R2->size(); ++k) {
// Update hold counter.
R2_hold_counter_[k] = R2_old_[k] < (*R2)[k] ? 0 : R2_hold_counter_[k] + 1;
// Compute the residual echo by holding a maximum echo powers and an echo
// fading corresponding to a room with an RT60 value of about 50 ms.
(*R2)[k] =
R2_hold_counter_[k] < config_.echo_model.nonlinear_hold
? std::max((*R2)[k], R2_old_[k])
: std::min((*R2)[k] +
R2_old_[k] * config_.echo_model.nonlinear_release,
Y2[k]);
}
}
}
void ResidualEchoEstimator::EchoGeneratingPower(
@ -266,15 +199,14 @@ void ResidualEchoEstimator::EchoGeneratingPower(
const EchoCanceller3Config::EchoModel& echo_model,
int headroom_spectrum_buffer,
int filter_delay_blocks,
bool gain_limiter_running,
bool apply_noise_gating,
std::array<float, kFftLengthBy2Plus1>* X2) const {
int idx_stop, idx_start;
RTC_DCHECK(X2);
GetRenderIndexesToAnalyze(spectrum_buffer, config_.echo_model,
filter_delay_blocks, gain_limiter_running,
headroom_spectrum_buffer, &idx_start, &idx_stop);
filter_delay_blocks, headroom_spectrum_buffer,
&idx_start, &idx_stop);
X2->fill(0.f);
for (int k = idx_start; k != idx_stop; k = spectrum_buffer.IncIndex(k)) {

View File

@ -72,7 +72,6 @@ class ResidualEchoEstimator {
const EchoCanceller3Config::EchoModel& echo_model,
int headroom_spectrum_buffer,
int filter_delay_blocks,
bool gain_limiter_running,
bool apply_noise_gating,
std::array<float, kFftLengthBy2Plus1>* X2) const;
@ -88,9 +87,6 @@ class ResidualEchoEstimator {
std::array<int, kFftLengthBy2Plus1> R2_hold_counter_;
std::array<float, kFftLengthBy2Plus1> X2_noise_floor_;
std::array<int, kFftLengthBy2Plus1> X2_noise_floor_counter_;
const bool soft_transparent_mode_;
const bool override_estimated_echo_path_gain_;
const bool use_fixed_nonlinear_reverb_model_;
std::unique_ptr<ReverbModel> echo_reverb_;
std::unique_ptr<ReverbModelFallback> echo_reverb_fallback;
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(ResidualEchoEstimator);

View File

@ -19,17 +19,11 @@
#include "api/audio/echo_canceller3_config.h"
#include "modules/audio_processing/logging/apm_data_dumper.h"
#include "rtc_base/checks.h"
#include "system_wrappers/include/field_trial.h"
namespace webrtc {
namespace {
bool EnforceAdaptiveEchoReverbEstimation() {
return field_trial::IsEnabled(
"WebRTC-Aec3EnableAdaptiveEchoReverbEstimation");
}
constexpr int kEarlyReverbMinSizeBlocks = 3;
constexpr int kBlocksPerSection = 6;
// Linear regression approach assumes symmetric index around 0.
@ -92,8 +86,7 @@ float BlockEnergyAverage(rtc::ArrayView<const float> h, int block_index) {
ReverbDecayEstimator::ReverbDecayEstimator(const EchoCanceller3Config& config)
: filter_length_blocks_(config.filter.main.length_blocks),
filter_length_coefficients_(GetTimeDomainLength(filter_length_blocks_)),
use_adaptive_echo_decay_(config.ep_strength.default_len < 0.f ||
EnforceAdaptiveEchoReverbEstimation()),
use_adaptive_echo_decay_(config.ep_strength.default_len < 0.f),
early_reverb_estimator_(config.filter.main.length_blocks -
kEarlyReverbMinSizeBlocks),
late_reverb_start_(kEarlyReverbMinSizeBlocks),

View File

@ -18,17 +18,11 @@
#include "api/array_view.h"
#include "modules/audio_processing/aec3/aec3_common.h"
#include "rtc_base/checks.h"
#include "system_wrappers/include/field_trial.h"
namespace webrtc {
namespace {
bool EnableSmoothUpdatesTailFreqResp() {
return !field_trial::IsEnabled(
"WebRTC-Aec3SmoothUpdatesTailFreqRespKillSwitch");
}
// Computes the ratio of the energies between the direct path and the tail. The
// energy is computed in the power spectrum domain discarding the DC
// contributions.
@ -54,8 +48,7 @@ float AverageDecayWithinFilter(
} // namespace
ReverbFrequencyResponse::ReverbFrequencyResponse()
: enable_smooth_tail_response_updates_(EnableSmoothUpdatesTailFreqResp()) {
ReverbFrequencyResponse::ReverbFrequencyResponse() {
tail_response_.fill(0.f);
}
ReverbFrequencyResponse::~ReverbFrequencyResponse() = default;
@ -66,10 +59,6 @@ void ReverbFrequencyResponse::Update(
int filter_delay_blocks,
const absl::optional<float>& linear_filter_quality,
bool stationary_block) {
if (!enable_smooth_tail_response_updates_) {
Update(frequency_response, filter_delay_blocks, 0.5f);
return;
}
if (stationary_block || !linear_filter_quality) {
return;

View File

@ -44,7 +44,6 @@ class ReverbFrequencyResponse {
int filter_delay_blocks,
float linear_filter_quality);
const bool enable_smooth_tail_response_updates_;
float average_decay_ = 0.f;
std::array<float, kFftLengthBy2Plus1> tail_response_;
};

View File

@ -15,7 +15,6 @@
#include "rtc_base/checks.h"
#include "rtc_base/numerics/safe_minmax.h"
#include "system_wrappers/include/field_trial.h"
namespace webrtc {
@ -26,10 +25,6 @@ constexpr int kBlocksToHoldErle = 100;
constexpr int kBlocksForOnsetDetection = kBlocksToHoldErle + 150;
constexpr int kPointsToAccumulate = 6;
bool EnableAdaptErleOnLowRender() {
return !field_trial::IsEnabled("WebRTC-Aec3AdaptErleOnLowRenderKillSwitch");
}
std::array<float, kFftLengthBy2Plus1> SetMaxErleBands(float max_erle_l,
float max_erle_h) {
std::array<float, kFftLengthBy2Plus1> max_erle;
@ -42,8 +37,7 @@ std::array<float, kFftLengthBy2Plus1> SetMaxErleBands(float max_erle_l,
SubbandErleEstimator::SubbandErleEstimator(const EchoCanceller3Config& config)
: min_erle_(config.erle.min),
max_erle_(SetMaxErleBands(config.erle.max_l, config.erle.max_h)),
adapt_on_low_render_(EnableAdaptErleOnLowRender()) {
max_erle_(SetMaxErleBands(config.erle.max_l, config.erle.max_h)) {
Reset();
}
@ -151,43 +145,23 @@ void SubbandErleEstimator::UpdateAccumulatedSpectra(
rtc::ArrayView<const float> Y2,
rtc::ArrayView<const float> E2) {
auto& st = accum_spectra_;
if (adapt_on_low_render_) {
if (st.num_points_[0] == kPointsToAccumulate) {
st.num_points_[0] = 0;
st.Y2_.fill(0.f);
st.E2_.fill(0.f);
st.low_render_energy_.fill(false);
}
std::transform(Y2.begin(), Y2.end(), st.Y2_.begin(), st.Y2_.begin(),
std::plus<float>());
std::transform(E2.begin(), E2.end(), st.E2_.begin(), st.E2_.begin(),
std::plus<float>());
for (size_t k = 0; k < X2.size(); ++k) {
st.low_render_energy_[k] =
st.low_render_energy_[k] || X2[k] < kX2BandEnergyThreshold;
}
st.num_points_[0]++;
st.num_points_.fill(st.num_points_[0]);
} else {
// The update is always done using high render energy signals and
// therefore the field accum_spectra_.low_render_energy_ does not need to
// be modified.
for (size_t k = 0; k < X2.size(); ++k) {
if (X2[k] > kX2BandEnergyThreshold) {
if (st.num_points_[k] == kPointsToAccumulate) {
st.Y2_[k] = 0.f;
st.E2_[k] = 0.f;
st.num_points_[k] = 0;
}
st.Y2_[k] += Y2[k];
st.E2_[k] += E2[k];
st.num_points_[k]++;
}
RTC_DCHECK_EQ(st.low_render_energy_[k], false);
}
if (st.num_points_[0] == kPointsToAccumulate) {
st.num_points_[0] = 0;
st.Y2_.fill(0.f);
st.E2_.fill(0.f);
st.low_render_energy_.fill(false);
}
std::transform(Y2.begin(), Y2.end(), st.Y2_.begin(), st.Y2_.begin(),
std::plus<float>());
std::transform(E2.begin(), E2.end(), st.E2_.begin(), st.E2_.begin(),
std::plus<float>());
for (size_t k = 0; k < X2.size(); ++k) {
st.low_render_energy_[k] =
st.low_render_energy_[k] || X2[k] < kX2BandEnergyThreshold;
}
st.num_points_[0]++;
st.num_points_.fill(st.num_points_[0]);
}
} // namespace webrtc

View File

@ -66,7 +66,6 @@ class SubbandErleEstimator {
const float min_erle_;
const std::array<float, kFftLengthBy2Plus1> max_erle_;
const bool adapt_on_low_render_;
AccumulatedSpectra accum_spectra_;
std::array<float, kFftLengthBy2Plus1> erle_;
std::array<float, kFftLengthBy2Plus1> erle_onsets_;

View File

@ -18,44 +18,16 @@
#include "modules/audio_processing/logging/apm_data_dumper.h"
#include "rtc_base/checks.h"
#include "rtc_base/numerics/safe_minmax.h"
#include "system_wrappers/include/field_trial.h"
namespace webrtc {
namespace {
bool EnableAgcGainChangeResponse() {
return !field_trial::IsEnabled("WebRTC-Aec3AgcGainChangeResponseKillSwitch");
}
bool EnableAdaptationDuringSaturation() {
return !field_trial::IsEnabled("WebRTC-Aec3RapidAgcGainRecoveryKillSwitch");
}
bool EnableMisadjustmentEstimator() {
return !field_trial::IsEnabled("WebRTC-Aec3MisadjustmentEstimatorKillSwitch");
}
bool EnableShadowFilterJumpstart() {
return !field_trial::IsEnabled("WebRTC-Aec3ShadowFilterJumpstartKillSwitch");
}
bool EnableShadowFilterBoostedJumpstart() {
return !field_trial::IsEnabled(
"WebRTC-Aec3ShadowFilterBoostedJumpstartKillSwitch");
}
bool EnableEarlyShadowFilterJumpstart() {
return !field_trial::IsEnabled(
"WebRTC-Aec3EarlyShadowFilterJumpstartKillSwitch");
}
void PredictionError(const Aec3Fft& fft,
const FftData& S,
rtc::ArrayView<const float> y,
std::array<float, kBlockSize>* e,
std::array<float, kBlockSize>* s,
bool adaptation_during_saturation,
bool* saturation) {
std::array<float, kFftLength> tmp;
fft.Ifft(S, &tmp);
@ -77,12 +49,7 @@ void PredictionError(const Aec3Fft& fft,
*saturation = *result.first <= -32768 || *result.first >= 32767;
}
if (!adaptation_during_saturation) {
std::for_each(e->begin(), e->end(),
[](float& a) { a = rtc::SafeClamp(a, -32768.f, 32767.f); });
} else {
*saturation = false;
}
*saturation = false;
}
void ScaleFilterOutput(rtc::ArrayView<const float> y,
@ -106,13 +73,6 @@ Subtractor::Subtractor(const EchoCanceller3Config& config,
data_dumper_(data_dumper),
optimization_(optimization),
config_(config),
adaptation_during_saturation_(EnableAdaptationDuringSaturation()),
enable_misadjustment_estimator_(EnableMisadjustmentEstimator()),
enable_agc_gain_change_response_(EnableAgcGainChangeResponse()),
enable_shadow_filter_jumpstart_(EnableShadowFilterJumpstart()),
enable_shadow_filter_boosted_jumpstart_(
EnableShadowFilterBoostedJumpstart()),
enable_early_shadow_filter_jumpstart_(EnableEarlyShadowFilterJumpstart()),
main_filter_(config_.filter.main.length_blocks,
config_.filter.main_initial.length_blocks,
config.filter.config_change_duration_blocks,
@ -152,7 +112,7 @@ void Subtractor::HandleEchoPathChange(
full_reset();
}
if (echo_path_variability.gain_change && enable_agc_gain_change_response_) {
if (echo_path_variability.gain_change) {
G_main_.HandleEchoPathChange(echo_path_variability);
}
}
@ -182,28 +142,24 @@ void Subtractor::Process(const RenderBuffer& render_buffer,
// Form the outputs of the main and shadow filters.
main_filter_.Filter(render_buffer, &S);
bool main_saturation = false;
PredictionError(fft_, S, y, &e_main, &output->s_main,
adaptation_during_saturation_, &main_saturation);
PredictionError(fft_, S, y, &e_main, &output->s_main, &main_saturation);
shadow_filter_.Filter(render_buffer, &S);
bool shadow_saturation = false;
PredictionError(fft_, S, y, &e_shadow, &output->s_shadow,
adaptation_during_saturation_, &shadow_saturation);
PredictionError(fft_, S, y, &e_shadow, &output->s_shadow, &shadow_saturation);
// Compute the signal powers in the subtractor output.
output->ComputeMetrics(y);
// Adjust the filter if needed.
bool main_filter_adjusted = false;
if (enable_misadjustment_estimator_) {
filter_misadjustment_estimator_.Update(*output);
if (filter_misadjustment_estimator_.IsAdjustmentNeeded()) {
float scale = filter_misadjustment_estimator_.GetMisadjustment();
main_filter_.ScaleFilter(scale);
ScaleFilterOutput(y, scale, e_main, output->s_main);
filter_misadjustment_estimator_.Reset();
main_filter_adjusted = true;
}
filter_misadjustment_estimator_.Update(*output);
if (filter_misadjustment_estimator_.IsAdjustmentNeeded()) {
float scale = filter_misadjustment_estimator_.GetMisadjustment();
main_filter_.ScaleFilter(scale);
ScaleFilterOutput(y, scale, e_main, output->s_main);
filter_misadjustment_estimator_.Reset();
main_filter_adjusted = true;
}
// Compute the FFts of the main and shadow filter outputs.
@ -248,40 +204,26 @@ void Subtractor::Process(const RenderBuffer& render_buffer,
// Update the shadow filter.
poor_shadow_filter_counter_ =
output->e2_main < output->e2_shadow ? poor_shadow_filter_counter_ + 1 : 0;
if (((poor_shadow_filter_counter_ < 5 &&
enable_early_shadow_filter_jumpstart_) ||
(poor_shadow_filter_counter_ < 10 &&
!enable_early_shadow_filter_jumpstart_)) ||
!enable_shadow_filter_jumpstart_) {
if (poor_shadow_filter_counter_ < 5) {
G_shadow_.Compute(X2_shadow, render_signal_analyzer, E_shadow,
shadow_filter_.SizePartitions(),
aec_state.SaturatedCapture() || shadow_saturation, &G);
shadow_filter_.Adapt(render_buffer, G);
} else {
poor_shadow_filter_counter_ = 0;
if (enable_shadow_filter_boosted_jumpstart_) {
shadow_filter_.SetFilter(main_filter_.GetFilter());
G_shadow_.Compute(X2_shadow, render_signal_analyzer, E_main,
shadow_filter_.SizePartitions(),
aec_state.SaturatedCapture() || main_saturation, &G);
shadow_filter_.Adapt(render_buffer, G);
} else {
G.re.fill(0.f);
G.im.fill(0.f);
shadow_filter_.Adapt(render_buffer, G);
shadow_filter_.SetFilter(main_filter_.GetFilter());
}
shadow_filter_.SetFilter(main_filter_.GetFilter());
G_shadow_.Compute(X2_shadow, render_signal_analyzer, E_main,
shadow_filter_.SizePartitions(),
aec_state.SaturatedCapture() || main_saturation, &G);
}
shadow_filter_.Adapt(render_buffer, G);
data_dumper_->DumpRaw("aec3_subtractor_G_shadow", G.re);
data_dumper_->DumpRaw("aec3_subtractor_G_shadow", G.im);
filter_misadjustment_estimator_.Dump(data_dumper_);
DumpFilters();
if (adaptation_during_saturation_) {
std::for_each(e_main.begin(), e_main.end(),
[](float& a) { a = rtc::SafeClamp(a, -32768.f, 32767.f); });
}
std::for_each(e_main.begin(), e_main.end(),
[](float& a) { a = rtc::SafeClamp(a, -32768.f, 32767.f); });
data_dumper_->DumpWav("aec3_main_filter_output", kBlockSize, &e_main[0],
16000, 1);

View File

@ -107,12 +107,6 @@ class Subtractor {
ApmDataDumper* data_dumper_;
const Aec3Optimization optimization_;
const EchoCanceller3Config config_;
const bool adaptation_during_saturation_;
const bool enable_misadjustment_estimator_;
const bool enable_agc_gain_change_response_;
const bool enable_shadow_filter_jumpstart_;
const bool enable_shadow_filter_boosted_jumpstart_;
const bool enable_early_shadow_filter_jumpstart_;
AdaptiveFirFilter main_filter_;
AdaptiveFirFilter shadow_filter_;

View File

@ -13,19 +13,10 @@
#include <algorithm>
#include "modules/audio_processing/aec3/aec3_common.h"
#include "system_wrappers/include/field_trial.h"
namespace webrtc {
namespace {
bool EnableStrictDivergenceCheck() {
return !field_trial::IsEnabled("WebRTC-Aec3StrictDivergenceCheckKillSwitch");
}
} // namespace
SubtractorOutputAnalyzer::SubtractorOutputAnalyzer()
: strict_divergence_check_(EnableStrictDivergenceCheck()) {}
SubtractorOutputAnalyzer::SubtractorOutputAnalyzer() {}
void SubtractorOutputAnalyzer::Update(
const SubtractorOutput& subtractor_output) {
@ -37,8 +28,7 @@ void SubtractorOutputAnalyzer::Update(
main_filter_converged_ = e2_main < 0.5f * y2 && y2 > kConvergenceThreshold;
shadow_filter_converged_ =
e2_shadow < 0.05f * y2 && y2 > kConvergenceThreshold;
float min_e2 =
strict_divergence_check_ ? std::min(e2_main, e2_shadow) : e2_main;
float min_e2 = std::min(e2_main, e2_shadow);
filter_diverged_ = min_e2 > 1.5f * y2 && y2 > 30.f * 30.f * kBlockSize;
}

View File

@ -34,7 +34,6 @@ class SubtractorOutputAnalyzer {
void HandleEchoPathChange();
private:
const bool strict_divergence_check_;
bool shadow_filter_converged_ = false;
bool main_filter_converged_ = false;
bool filter_diverged_ = false;

View File

@ -346,14 +346,6 @@ void SuppressionGain::GetGain(
nearend_average, residual_echo_spectrum, comfort_noise_spectrum,
low_band_gain);
// Limit the gain of the lower bands during start up and after resets.
const float gain_upper_bound = aec_state.SuppressionGainLimit();
if (gain_upper_bound < 1.f) {
for (size_t k = 0; k < low_band_gain->size(); ++k) {
(*low_band_gain)[k] = std::min((*low_band_gain)[k], gain_upper_bound);
}
}
// Compute the gain for the upper bands.
const absl::optional<int> narrow_peak_band =
render_signal_analyzer.NarrowPeakBand();

View File

@ -1,93 +0,0 @@
/*
* 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"
#include "rtc_base/checks.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,
bool transparent_mode) {
if (transparent_mode) {
active_render_seen_ = true;
call_startup_phase_ = false;
recent_reset_ = false;
suppressor_gain_limit_ = 1.f;
return;
}
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 (!IsActive()) {
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_ = rampup_config_.initial_gain;
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

View File

@ -1,58 +0,0 @@
/*
* 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/constructor_magic.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, bool transparent_mode);
// Returns the current suppressor gain limit.
float Limit() const { return suppressor_gain_limit_; }
// 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_;
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_