Separated the AEC3 adaptive filter parameters into sub-structs

Bug: webrtc:8671
Change-Id: I02bceceb85da6db65f65c1a2366a2d5021f148ef
Reviewed-on: https://webrtc-review.googlesource.com/39502
Reviewed-by: Gustaf Ullberg <gustaf@webrtc.org>
Commit-Queue: Per Åhgren <peah@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#21617}
This commit is contained in:
Per Åhgren
2018-01-15 08:07:41 +01:00
committed by Commit Bot
parent a2ac1b4b22
commit 08ea5898ff
11 changed files with 69 additions and 47 deletions

View File

@ -307,15 +307,15 @@ TEST(AdaptiveFirFilter, FilterAndAdapt) {
constexpr size_t kNumBlocksToProcess = 1000;
ApmDataDumper data_dumper(42);
EchoCanceller3Config config;
AdaptiveFirFilter filter(config.filter.length_blocks, DetectOptimization(),
&data_dumper);
AdaptiveFirFilter filter(config.filter.main.length_blocks,
DetectOptimization(), &data_dumper);
Aec3Fft fft;
config.delay.min_echo_path_delay_blocks = 0;
config.delay.default_delay = 1;
std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
RenderDelayBuffer::Create(config, 3));
ShadowFilterUpdateGain gain(config.filter.shadow_rate,
config.filter.shadow_noise_gate);
ShadowFilterUpdateGain gain(config.filter.shadow.rate,
config.filter.shadow.noise_gate);
Random random_generator(42U);
std::vector<std::vector<float>> x(3, std::vector<float>(kBlockSize, 0.f));
std::vector<float> n(kBlockSize, 0.f);

View File

@ -56,7 +56,7 @@ AecState::AecState(const EchoCanceller3Config& config)
new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))),
erle_estimator_(config.erle.min, config.erle.max_l, config.erle.max_h),
config_(config),
max_render_(config_.filter.length_blocks, 0.f),
max_render_(config_.filter.main.length_blocks, 0.f),
reverb_decay_(config_.ep_strength.default_len) {}
AecState::~AecState() = default;
@ -175,7 +175,8 @@ void AecState::Update(
void AecState::UpdateReverb(const std::vector<float>& impulse_response) {
if ((!(filter_delay_ && usable_linear_estimate_)) ||
(filter_delay_ > static_cast<int>(config_.filter.length_blocks) - 4)) {
(filter_delay_ >
static_cast<int>(config_.filter.main.length_blocks) - 4)) {
return;
}
@ -183,11 +184,11 @@ void AecState::UpdateReverb(const std::vector<float>& impulse_response) {
// coefficients.
std::array<float, GetTimeDomainLength(kMaxAdaptiveFilterLength)>
matching_data_data;
RTC_DCHECK_LE(GetTimeDomainLength(config_.filter.length_blocks),
RTC_DCHECK_LE(GetTimeDomainLength(config_.filter.main.length_blocks),
matching_data_data.size());
rtc::ArrayView<float> matching_data(
matching_data_data.data(),
GetTimeDomainLength(config_.filter.length_blocks));
GetTimeDomainLength(config_.filter.main.length_blocks));
std::transform(impulse_response.begin(), impulse_response.end(),
matching_data.begin(), [](float a) { return a * a; });
@ -195,7 +196,7 @@ void AecState::UpdateReverb(const std::vector<float>& impulse_response) {
// model noise power.
constexpr size_t kTailLength = 64;
const size_t tail_index =
GetTimeDomainLength(config_.filter.length_blocks) - kTailLength;
GetTimeDomainLength(config_.filter.main.length_blocks) - kTailLength;
const float tail_power = *std::max_element(matching_data.begin() + tail_index,
matching_data.end());
std::for_each(matching_data.begin(), matching_data.begin() + tail_index,

View File

@ -44,7 +44,7 @@ TEST(AecState, NormalUsage) {
converged_filter_frequency_response[2][0] = 1.f;
std::vector<float> impulse_response(
GetTimeDomainLength(config.filter.length_blocks), 0.f);
GetTimeDomainLength(config.filter.main.length_blocks), 0.f);
// Verify that linear AEC usability is false when the filter is diverged.
state.Update(diverged_filter_frequency_response, impulse_response, true,
@ -190,7 +190,7 @@ TEST(AecState, ConvergedFilterDelay) {
kFilterLength);
std::vector<float> impulse_response(
GetTimeDomainLength(config.filter.length_blocks), 0.f);
GetTimeDomainLength(config.filter.main.length_blocks), 0.f);
// Verify that the filter delay for a converged filter is properly identified.
for (int k = 0; k < kFilterLength; ++k) {

View File

@ -42,19 +42,20 @@ void RunFilterUpdateTest(int num_blocks_to_process,
FftData* G_last_block) {
ApmDataDumper data_dumper(42);
EchoCanceller3Config config;
config.filter.length_blocks = filter_length_blocks;
AdaptiveFirFilter main_filter(config.filter.length_blocks,
config.filter.main.length_blocks = filter_length_blocks;
config.filter.shadow.length_blocks = filter_length_blocks;
AdaptiveFirFilter main_filter(config.filter.main.length_blocks,
DetectOptimization(), &data_dumper);
AdaptiveFirFilter shadow_filter(config.filter.length_blocks,
AdaptiveFirFilter shadow_filter(config.filter.shadow.length_blocks,
DetectOptimization(), &data_dumper);
Aec3Fft fft;
std::array<float, kBlockSize> x_old;
x_old.fill(0.f);
ShadowFilterUpdateGain shadow_gain(config.filter.shadow_rate,
config.filter.shadow_noise_gate);
ShadowFilterUpdateGain shadow_gain(config.filter.shadow.rate,
config.filter.shadow.noise_gate);
MainFilterUpdateGain main_gain(
config.filter.leakage_converged, config.filter.leakage_diverged,
config.filter.main_noise_gate, config.filter.error_floor);
config.filter.main.leakage_converged, config.filter.main.leakage_diverged,
config.filter.main.noise_gate, config.filter.main.error_floor);
Random random_generator(42U);
std::vector<std::vector<float>> x(3, std::vector<float>(kBlockSize, 0.f));
std::vector<float> y(kBlockSize, 0.f);
@ -189,13 +190,13 @@ std::string ProduceDebugText(size_t delay, int filter_length_blocks) {
TEST(MainFilterUpdateGain, NullDataOutputGain) {
ApmDataDumper data_dumper(42);
EchoCanceller3Config config;
AdaptiveFirFilter filter(config.filter.length_blocks, DetectOptimization(),
&data_dumper);
AdaptiveFirFilter filter(config.filter.main.length_blocks,
DetectOptimization(), &data_dumper);
RenderSignalAnalyzer analyzer;
SubtractorOutput output;
MainFilterUpdateGain gain(
config.filter.leakage_converged, config.filter.leakage_diverged,
config.filter.main_noise_gate, config.filter.error_floor);
config.filter.main.leakage_converged, config.filter.main.leakage_diverged,
config.filter.main.noise_gate, config.filter.main.error_floor);
std::array<float, kFftLengthBy2Plus1> render_power;
render_power.fill(0.f);
EXPECT_DEATH(

View File

@ -158,7 +158,7 @@ RenderDelayBufferImpl::RenderDelayBufferImpl(const EchoCanceller3Config& config,
: kBlockSize)),
blocks_(GetRenderDelayBufferSize(config.delay.down_sampling_factor,
config.delay.num_filters,
config.filter.length_blocks),
config.filter.main.length_blocks),
num_bands,
kBlockSize),
spectra_(blocks_.buffer.size(), kFftLengthBy2Plus1),
@ -171,7 +171,7 @@ RenderDelayBufferImpl::RenderDelayBufferImpl(const EchoCanceller3Config& config,
zero_block_(num_bands, std::vector<float>(kBlockSize, 0.f)),
fft_(),
render_ds_(sub_block_size_, 0.f),
buffer_headroom_(config.filter.length_blocks) {
buffer_headroom_(config.filter.main.length_blocks) {
RTC_DCHECK_EQ(blocks_.buffer.size(), ffts_.buffer.size());
RTC_DCHECK_EQ(spectra_.buffer.size(), ffts_.buffer.size());

View File

@ -77,7 +77,7 @@ void RenderNoisePower(
} // namespace
ResidualEchoEstimator::ResidualEchoEstimator(const EchoCanceller3Config& config)
: config_(config), S2_old_(config_.filter.length_blocks) {
: config_(config), S2_old_(config_.filter.main.length_blocks) {
Reset();
}
@ -131,7 +131,8 @@ void ResidualEchoEstimator::Estimate(
if (aec_state.SaturatedEcho()) {
// TODO(peah): Modify to make sense theoretically.
AddEchoReverb(*R2, aec_state.SaturatedEcho(),
config_.filter.length_blocks, aec_state.ReverbDecay(), R2);
config_.filter.main.length_blocks, aec_state.ReverbDecay(),
R2);
}
}

View File

@ -70,7 +70,8 @@ TEST(ResidualEchoEstimator, DISABLED_BasicTest) {
H2[2].fill(10.f);
H2[2][0] = 0.1f;
std::vector<float> h(GetTimeDomainLength(config.filter.length_blocks), 0.f);
std::vector<float> h(GetTimeDomainLength(config.filter.main.length_blocks),
0.f);
s.fill(100.f);

View File

@ -38,10 +38,10 @@ void RunFilterUpdateTest(int num_blocks_to_process,
FftData* G_last_block) {
ApmDataDumper data_dumper(42);
EchoCanceller3Config config;
config.filter.length_blocks = filter_length_blocks;
AdaptiveFirFilter main_filter(config.filter.length_blocks,
config.filter.main.length_blocks = filter_length_blocks;
AdaptiveFirFilter main_filter(config.filter.main.length_blocks,
DetectOptimization(), &data_dumper);
AdaptiveFirFilter shadow_filter(config.filter.length_blocks,
AdaptiveFirFilter shadow_filter(config.filter.shadow.length_blocks,
DetectOptimization(), &data_dumper);
Aec3Fft fft;
@ -52,8 +52,8 @@ void RunFilterUpdateTest(int num_blocks_to_process,
std::array<float, kBlockSize> x_old;
x_old.fill(0.f);
ShadowFilterUpdateGain shadow_gain(config.filter.shadow_rate,
config.filter.shadow_noise_gate);
ShadowFilterUpdateGain shadow_gain(config.filter.shadow.rate,
config.filter.shadow.noise_gate);
Random random_generator(42U);
std::vector<std::vector<float>> x(3, std::vector<float>(kBlockSize, 0.f));
std::vector<float> y(kBlockSize, 0.f);

View File

@ -51,14 +51,22 @@ Subtractor::Subtractor(const EchoCanceller3Config& config,
: fft_(),
data_dumper_(data_dumper),
optimization_(optimization),
main_filter_(config.filter.length_blocks, optimization, data_dumper_),
shadow_filter_(config.filter.length_blocks, optimization, data_dumper_),
G_main_(config.filter.leakage_converged,
config.filter.leakage_diverged,
config.filter.main_noise_gate,
config.filter.error_floor),
G_shadow_(config.filter.shadow_rate, config.filter.shadow_noise_gate) {
main_filter_(config.filter.main.length_blocks,
optimization,
data_dumper_),
shadow_filter_(config.filter.shadow.length_blocks,
optimization,
data_dumper_),
G_main_(config.filter.main.leakage_converged,
config.filter.main.leakage_diverged,
config.filter.main.noise_gate,
config.filter.main.error_floor),
G_shadow_(config.filter.shadow.rate, config.filter.shadow.noise_gate) {
RTC_DCHECK(data_dumper_);
// Currently, the rest of AEC3 requires the main and shadow filter lengths to
// be identical.
RTC_DCHECK_EQ(config.filter.main.length_blocks,
config.filter.shadow.length_blocks);
}
Subtractor::~Subtractor() = default;

View File

@ -30,7 +30,8 @@ float RunSubtractorTest(int num_blocks_to_process,
const std::vector<int>& blocks_with_echo_path_changes) {
ApmDataDumper data_dumper(42);
EchoCanceller3Config config;
config.filter.length_blocks = filter_length_blocks;
config.filter.main.length_blocks = config.filter.shadow.length_blocks =
filter_length_blocks;
Subtractor subtractor(config, &data_dumper, DetectOptimization());
std::vector<std::vector<float>> x(3, std::vector<float>(kBlockSize, 0.f));
std::vector<float> y(kBlockSize, 0.f);

View File

@ -1244,13 +1244,22 @@ struct EchoCanceller3Config {
} delay;
struct Filter {
size_t length_blocks = 12;
float shadow_rate = 0.1f;
float leakage_converged = 0.005f;
float leakage_diverged = 0.05f;
float error_floor = 0.001f;
float main_noise_gate = 20075344.f;
float shadow_noise_gate = 20075344.f;
struct MainConfiguration {
size_t length_blocks;
float leakage_converged;
float leakage_diverged;
float error_floor;
float noise_gate;
};
struct ShadowConfiguration {
size_t length_blocks;
float rate;
float noise_gate;
};
MainConfiguration main = {12, 0.005f, 0.05f, 0.001f, 20075344.f};
ShadowConfiguration shadow = {12, 0.1f, 20075344.f};
} filter;
struct Erle {