Update to current webrtc library
This is from the upstream library commit id 3326535126e435f1ba647885ce43a8f0f3d317eb, corresponding to Chromium 88.0.4290.1.
This commit is contained in:
216
webrtc/modules/audio_processing/aec3/subband_erle_estimator.cc
Normal file
216
webrtc/modules/audio_processing/aec3/subband_erle_estimator.cc
Normal file
@ -0,0 +1,216 @@
|
||||
/*
|
||||
* 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"
|
||||
#include "system_wrappers/include/field_trial.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;
|
||||
}
|
||||
|
||||
bool EnableMinErleDuringOnsets() {
|
||||
return !field_trial::IsEnabled("WebRTC-Aec3MinErleDuringOnsetsKillSwitch");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
SubbandErleEstimator::SubbandErleEstimator(const EchoCanceller3Config& config,
|
||||
size_t num_capture_channels)
|
||||
: use_onset_detection_(config.erle.onset_detection),
|
||||
min_erle_(config.erle.min),
|
||||
max_erle_(SetMaxErleBands(config.erle.max_l, config.erle.max_h)),
|
||||
use_min_erle_during_onsets_(EnableMinErleDuringOnsets()),
|
||||
accum_spectra_(num_capture_channels),
|
||||
erle_(num_capture_channels),
|
||||
erle_onsets_(num_capture_channels),
|
||||
coming_onset_(num_capture_channels),
|
||||
hold_counters_(num_capture_channels) {
|
||||
Reset();
|
||||
}
|
||||
|
||||
SubbandErleEstimator::~SubbandErleEstimator() = default;
|
||||
|
||||
void SubbandErleEstimator::Reset() {
|
||||
for (auto& erle : erle_) {
|
||||
erle.fill(min_erle_);
|
||||
}
|
||||
for (size_t ch = 0; ch < erle_onsets_.size(); ++ch) {
|
||||
erle_onsets_[ch].fill(min_erle_);
|
||||
coming_onset_[ch].fill(true);
|
||||
hold_counters_[ch].fill(0);
|
||||
}
|
||||
ResetAccumulatedSpectra();
|
||||
}
|
||||
|
||||
void SubbandErleEstimator::Update(
|
||||
rtc::ArrayView<const float, kFftLengthBy2Plus1> X2,
|
||||
rtc::ArrayView<const std::array<float, kFftLengthBy2Plus1>> Y2,
|
||||
rtc::ArrayView<const std::array<float, kFftLengthBy2Plus1>> E2,
|
||||
const std::vector<bool>& converged_filters) {
|
||||
UpdateAccumulatedSpectra(X2, Y2, E2, converged_filters);
|
||||
UpdateBands(converged_filters);
|
||||
|
||||
if (use_onset_detection_) {
|
||||
DecreaseErlePerBandForLowRenderSignals();
|
||||
}
|
||||
|
||||
for (auto& erle : erle_) {
|
||||
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()[0]);
|
||||
}
|
||||
|
||||
void SubbandErleEstimator::UpdateBands(
|
||||
const std::vector<bool>& converged_filters) {
|
||||
const int num_capture_channels = static_cast<int>(accum_spectra_.Y2.size());
|
||||
for (int ch = 0; ch < num_capture_channels; ++ch) {
|
||||
// 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.
|
||||
if (!converged_filters[ch]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
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[ch] == kPointsToAccumulate &&
|
||||
accum_spectra_.E2[ch][k] > 0.f) {
|
||||
new_erle[k] = accum_spectra_.Y2[ch][k] / accum_spectra_.E2[ch][k];
|
||||
is_erle_updated[k] = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (use_onset_detection_) {
|
||||
for (size_t k = 1; k < kFftLengthBy2; ++k) {
|
||||
if (is_erle_updated[k] && !accum_spectra_.low_render_energy[ch][k]) {
|
||||
if (coming_onset_[ch][k]) {
|
||||
coming_onset_[ch][k] = false;
|
||||
if (!use_min_erle_during_onsets_) {
|
||||
float alpha = new_erle[k] < erle_onsets_[ch][k] ? 0.3f : 0.15f;
|
||||
erle_onsets_[ch][k] = rtc::SafeClamp(
|
||||
erle_onsets_[ch][k] +
|
||||
alpha * (new_erle[k] - erle_onsets_[ch][k]),
|
||||
min_erle_, max_erle_[k]);
|
||||
}
|
||||
}
|
||||
hold_counters_[ch][k] = kBlocksForOnsetDetection;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t k = 1; k < kFftLengthBy2; ++k) {
|
||||
if (is_erle_updated[k]) {
|
||||
float alpha = 0.05f;
|
||||
if (new_erle[k] < erle_[ch][k]) {
|
||||
alpha = accum_spectra_.low_render_energy[ch][k] ? 0.f : 0.1f;
|
||||
}
|
||||
erle_[ch][k] =
|
||||
rtc::SafeClamp(erle_[ch][k] + alpha * (new_erle[k] - erle_[ch][k]),
|
||||
min_erle_, max_erle_[k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SubbandErleEstimator::DecreaseErlePerBandForLowRenderSignals() {
|
||||
const int num_capture_channels = static_cast<int>(accum_spectra_.Y2.size());
|
||||
for (int ch = 0; ch < num_capture_channels; ++ch) {
|
||||
for (size_t k = 1; k < kFftLengthBy2; ++k) {
|
||||
--hold_counters_[ch][k];
|
||||
if (hold_counters_[ch][k] <=
|
||||
(kBlocksForOnsetDetection - kBlocksToHoldErle)) {
|
||||
if (erle_[ch][k] > erle_onsets_[ch][k]) {
|
||||
erle_[ch][k] = std::max(erle_onsets_[ch][k], 0.97f * erle_[ch][k]);
|
||||
RTC_DCHECK_LE(min_erle_, erle_[ch][k]);
|
||||
}
|
||||
if (hold_counters_[ch][k] <= 0) {
|
||||
coming_onset_[ch][k] = true;
|
||||
hold_counters_[ch][k] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SubbandErleEstimator::ResetAccumulatedSpectra() {
|
||||
for (size_t ch = 0; ch < erle_onsets_.size(); ++ch) {
|
||||
accum_spectra_.Y2[ch].fill(0.f);
|
||||
accum_spectra_.E2[ch].fill(0.f);
|
||||
accum_spectra_.num_points[ch] = 0;
|
||||
accum_spectra_.low_render_energy[ch].fill(false);
|
||||
}
|
||||
}
|
||||
|
||||
void SubbandErleEstimator::UpdateAccumulatedSpectra(
|
||||
rtc::ArrayView<const float, kFftLengthBy2Plus1> X2,
|
||||
rtc::ArrayView<const std::array<float, kFftLengthBy2Plus1>> Y2,
|
||||
rtc::ArrayView<const std::array<float, kFftLengthBy2Plus1>> E2,
|
||||
const std::vector<bool>& converged_filters) {
|
||||
auto& st = accum_spectra_;
|
||||
RTC_DCHECK_EQ(st.E2.size(), E2.size());
|
||||
RTC_DCHECK_EQ(st.E2.size(), E2.size());
|
||||
const int num_capture_channels = static_cast<int>(Y2.size());
|
||||
for (int ch = 0; ch < num_capture_channels; ++ch) {
|
||||
// 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.
|
||||
if (!converged_filters[ch]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (st.num_points[ch] == kPointsToAccumulate) {
|
||||
st.num_points[ch] = 0;
|
||||
st.Y2[ch].fill(0.f);
|
||||
st.E2[ch].fill(0.f);
|
||||
st.low_render_energy[ch].fill(false);
|
||||
}
|
||||
|
||||
std::transform(Y2[ch].begin(), Y2[ch].end(), st.Y2[ch].begin(),
|
||||
st.Y2[ch].begin(), std::plus<float>());
|
||||
std::transform(E2[ch].begin(), E2[ch].end(), st.E2[ch].begin(),
|
||||
st.E2[ch].begin(), std::plus<float>());
|
||||
|
||||
for (size_t k = 0; k < X2.size(); ++k) {
|
||||
st.low_render_energy[ch][k] =
|
||||
st.low_render_energy[ch][k] || X2[k] < kX2BandEnergyThreshold;
|
||||
}
|
||||
|
||||
++st.num_points[ch];
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
Reference in New Issue
Block a user