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}
168 lines
5.3 KiB
C++
168 lines
5.3 KiB
C++
/*
|
|
* 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/subband_erle_estimator.h"
|
|
|
|
#include <algorithm>
|
|
#include <functional>
|
|
|
|
#include "rtc_base/checks.h"
|
|
#include "rtc_base/numerics/safe_minmax.h"
|
|
|
|
namespace webrtc {
|
|
|
|
namespace {
|
|
|
|
constexpr float kX2BandEnergyThreshold = 44015068.0f;
|
|
constexpr int kBlocksToHoldErle = 100;
|
|
constexpr int kBlocksForOnsetDetection = kBlocksToHoldErle + 150;
|
|
constexpr int kPointsToAccumulate = 6;
|
|
|
|
std::array<float, kFftLengthBy2Plus1> SetMaxErleBands(float max_erle_l,
|
|
float max_erle_h) {
|
|
std::array<float, kFftLengthBy2Plus1> max_erle;
|
|
std::fill(max_erle.begin(), max_erle.begin() + kFftLengthBy2 / 2, max_erle_l);
|
|
std::fill(max_erle.begin() + kFftLengthBy2 / 2, max_erle.end(), max_erle_h);
|
|
return max_erle;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
SubbandErleEstimator::SubbandErleEstimator(const EchoCanceller3Config& config)
|
|
: min_erle_(config.erle.min),
|
|
max_erle_(SetMaxErleBands(config.erle.max_l, config.erle.max_h)) {
|
|
Reset();
|
|
}
|
|
|
|
SubbandErleEstimator::~SubbandErleEstimator() = default;
|
|
|
|
void SubbandErleEstimator::Reset() {
|
|
erle_.fill(min_erle_);
|
|
erle_onsets_.fill(min_erle_);
|
|
coming_onset_.fill(true);
|
|
hold_counters_.fill(0);
|
|
ResetAccumulatedSpectra();
|
|
}
|
|
|
|
void SubbandErleEstimator::Update(rtc::ArrayView<const float> X2,
|
|
rtc::ArrayView<const float> Y2,
|
|
rtc::ArrayView<const float> E2,
|
|
bool converged_filter,
|
|
bool onset_detection) {
|
|
if (converged_filter) {
|
|
// Note that the use of the converged_filter flag already imposed
|
|
// a minimum of the erle that can be estimated as that flag would
|
|
// be false if the filter is performing poorly.
|
|
UpdateAccumulatedSpectra(X2, Y2, E2);
|
|
UpdateBands(onset_detection);
|
|
}
|
|
|
|
if (onset_detection) {
|
|
DecreaseErlePerBandForLowRenderSignals();
|
|
}
|
|
|
|
erle_[0] = erle_[1];
|
|
erle_[kFftLengthBy2] = erle_[kFftLengthBy2 - 1];
|
|
}
|
|
|
|
void SubbandErleEstimator::Dump(
|
|
const std::unique_ptr<ApmDataDumper>& data_dumper) const {
|
|
data_dumper->DumpRaw("aec3_erle_onset", ErleOnsets());
|
|
}
|
|
|
|
void SubbandErleEstimator::UpdateBands(bool onset_detection) {
|
|
std::array<float, kFftLengthBy2> new_erle;
|
|
std::array<bool, kFftLengthBy2> is_erle_updated;
|
|
is_erle_updated.fill(false);
|
|
|
|
for (size_t k = 1; k < kFftLengthBy2; ++k) {
|
|
if (accum_spectra_.num_points_[k] == kPointsToAccumulate &&
|
|
accum_spectra_.E2_[k] > 0.f) {
|
|
new_erle[k] = accum_spectra_.Y2_[k] / accum_spectra_.E2_[k];
|
|
is_erle_updated[k] = true;
|
|
}
|
|
}
|
|
|
|
if (onset_detection) {
|
|
for (size_t k = 1; k < kFftLengthBy2; ++k) {
|
|
if (is_erle_updated[k] && !accum_spectra_.low_render_energy_[k]) {
|
|
if (coming_onset_[k]) {
|
|
coming_onset_[k] = false;
|
|
float alpha = new_erle[k] < erle_onsets_[k] ? 0.3f : 0.15f;
|
|
erle_onsets_[k] = rtc::SafeClamp(
|
|
erle_onsets_[k] + alpha * (new_erle[k] - erle_onsets_[k]),
|
|
min_erle_, max_erle_[k]);
|
|
}
|
|
hold_counters_[k] = kBlocksForOnsetDetection;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (size_t k = 1; k < kFftLengthBy2; ++k) {
|
|
if (is_erle_updated[k]) {
|
|
float alpha = 0.05f;
|
|
if (new_erle[k] < erle_[k]) {
|
|
alpha = accum_spectra_.low_render_energy_[k] ? 0.f : 0.1f;
|
|
}
|
|
erle_[k] = rtc::SafeClamp(erle_[k] + alpha * (new_erle[k] - erle_[k]),
|
|
min_erle_, max_erle_[k]);
|
|
}
|
|
}
|
|
}
|
|
|
|
void SubbandErleEstimator::DecreaseErlePerBandForLowRenderSignals() {
|
|
for (size_t k = 1; k < kFftLengthBy2; ++k) {
|
|
hold_counters_[k]--;
|
|
if (hold_counters_[k] <= (kBlocksForOnsetDetection - kBlocksToHoldErle)) {
|
|
if (erle_[k] > erle_onsets_[k]) {
|
|
erle_[k] = std::max(erle_onsets_[k], 0.97f * erle_[k]);
|
|
RTC_DCHECK_LE(min_erle_, erle_[k]);
|
|
}
|
|
if (hold_counters_[k] <= 0) {
|
|
coming_onset_[k] = true;
|
|
hold_counters_[k] = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void SubbandErleEstimator::ResetAccumulatedSpectra() {
|
|
accum_spectra_.Y2_.fill(0.f);
|
|
accum_spectra_.E2_.fill(0.f);
|
|
accum_spectra_.num_points_.fill(0);
|
|
accum_spectra_.low_render_energy_.fill(false);
|
|
}
|
|
|
|
void SubbandErleEstimator::UpdateAccumulatedSpectra(
|
|
rtc::ArrayView<const float> X2,
|
|
rtc::ArrayView<const float> Y2,
|
|
rtc::ArrayView<const float> E2) {
|
|
auto& st = accum_spectra_;
|
|
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
|