AEC3: Introduce partial adaptive filter resets at echo path changes

With this CL, the main and shadow filters are no longer fully reset to
0 as the delay changes. This allows for more robust echo removal for
some scenarios.

Bug: webrtc:9879,chromium:895838
Change-Id: I859aa3df3ae41648bc8efde01ec2e2a5cb392279
Reviewed-on: https://webrtc-review.googlesource.com/c/106345
Reviewed-by: Gustaf Ullberg <gustaf@webrtc.org>
Commit-Queue: Per Åhgren <peah@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#25251}
This commit is contained in:
Per Åhgren
2018-10-16 16:08:28 +02:00
committed by Commit Bot
parent 1ffee36cb9
commit 65faede3b0
3 changed files with 21 additions and 25 deletions

View File

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

View File

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

View File

@ -210,21 +210,4 @@ TEST(Subtractor, NonConvergenceOnUncorrelatedSignals) {
} }
} }
// Verifies that the subtractor is properly reset when there is an echo path
// change.
TEST(Subtractor, EchoPathChangeReset) {
std::vector<int> blocks_with_echo_path_changes;
blocks_with_echo_path_changes.push_back(99);
for (size_t filter_length_blocks : {12, 20, 30}) {
for (size_t delay_samples : {0, 64, 150, 200, 301}) {
SCOPED_TRACE(ProduceDebugText(delay_samples, filter_length_blocks));
float echo_to_nearend_power = RunSubtractorTest(
100, delay_samples, filter_length_blocks, filter_length_blocks, false,
blocks_with_echo_path_changes);
EXPECT_NEAR(1.f, echo_to_nearend_power, 0.0000001f);
}
}
}
} // namespace webrtc } // namespace webrtc