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:
@ -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);
|
||||||
|
@ -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_;
|
||||||
|
@ -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
|
||||||
|
Reference in New Issue
Block a user