Updated the behavior for the filter adaptation in echo canceller 3

This CL adjusts the filter adaptation behavior to better handle
reverberant environments and environments with poor SNR.

It furthermore updates the unittests to handle the reduced adaptation
speed.

Bug: webrtc:8661
Change-Id: I5f1b5a4a34b333bd6c643ed3727899d0838dbf90
Reviewed-on: https://webrtc-review.googlesource.com/34184
Reviewed-by: Gustaf Ullberg <gustaf@webrtc.org>
Commit-Queue: Per Åhgren <peah@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#21323}
This commit is contained in:
Per Åhgren
2017-12-18 11:38:39 +01:00
committed by Commit Bot
parent e98c3de793
commit 019008bd93
5 changed files with 38 additions and 26 deletions

View File

@ -306,7 +306,7 @@ TEST(AdaptiveFirFilter, FilterSize) {
// Verifies that the filter is being able to properly filter a signal and to
// adapt its coefficients.
TEST(AdaptiveFirFilter, FilterAndAdapt) {
constexpr size_t kNumBlocksToProcess = 500;
constexpr size_t kNumBlocksToProcess = 1000;
ApmDataDumper data_dumper(42);
EchoCanceller3Config config;
AdaptiveFirFilter filter(config.filter.length_blocks, DetectOptimization(),

View File

@ -220,8 +220,14 @@ TEST(MainFilterUpdateGain, GainCausesFilterToConverge) {
false, &e, &y, &G);
// Verify that the main filter is able to perform well.
EXPECT_LT(1000 * std::inner_product(e.begin(), e.end(), e.begin(), 0.f),
std::inner_product(y.begin(), y.end(), y.begin(), 0.f));
// Use different criteria to take overmodelling into account.
if (filter_length_blocks == 12) {
EXPECT_LT(1000 * std::inner_product(e.begin(), e.end(), e.begin(), 0.f),
std::inner_product(y.begin(), y.end(), y.begin(), 0.f));
} else {
EXPECT_LT(std::inner_product(e.begin(), e.end(), e.begin(), 0.f),
std::inner_product(y.begin(), y.end(), y.begin(), 0.f));
}
}
}
}
@ -229,8 +235,6 @@ TEST(MainFilterUpdateGain, GainCausesFilterToConverge) {
// Verifies that the magnitude of the gain on average decreases for a
// persistently exciting signal.
TEST(MainFilterUpdateGain, DecreasingGain) {
for (size_t filter_length_blocks : {12, 20, 30}) {
SCOPED_TRACE(ProduceDebugText(filter_length_blocks));
std::vector<int> blocks_with_echo_path_changes;
std::vector<int> blocks_with_saturation;
@ -243,15 +247,12 @@ TEST(MainFilterUpdateGain, DecreasingGain) {
std::array<float, kFftLengthBy2Plus1> G_b_power;
std::array<float, kFftLengthBy2Plus1> G_c_power;
RunFilterUpdateTest(100, 65, filter_length_blocks,
blocks_with_echo_path_changes, blocks_with_saturation,
false, &e, &y, &G_a);
RunFilterUpdateTest(300, 65, filter_length_blocks,
blocks_with_echo_path_changes, blocks_with_saturation,
false, &e, &y, &G_b);
RunFilterUpdateTest(600, 65, filter_length_blocks,
blocks_with_echo_path_changes, blocks_with_saturation,
false, &e, &y, &G_c);
RunFilterUpdateTest(100, 65, 12, blocks_with_echo_path_changes,
blocks_with_saturation, false, &e, &y, &G_a);
RunFilterUpdateTest(300, 65, 12, blocks_with_echo_path_changes,
blocks_with_saturation, false, &e, &y, &G_b);
RunFilterUpdateTest(600, 65, 12, blocks_with_echo_path_changes,
blocks_with_saturation, false, &e, &y, &G_c);
G_a.Spectrum(Aec3Optimization::kNone, G_a_power);
G_b.Spectrum(Aec3Optimization::kNone, G_b_power);
@ -262,7 +263,6 @@ TEST(MainFilterUpdateGain, DecreasingGain) {
EXPECT_GT(std::accumulate(G_b_power.begin(), G_b_power.end(), 0.),
std::accumulate(G_c_power.begin(), G_c_power.end(), 0.));
}
}
// Verifies that the gain is zero when there is saturation and that the internal

View File

@ -157,8 +157,14 @@ TEST(ShadowFilterUpdateGain, GainCausesFilterToConverge) {
blocks_with_saturation, &e, &y, &G);
// Verify that the main filter is able to perform well.
EXPECT_LT(1000 * std::inner_product(e.begin(), e.end(), e.begin(), 0.f),
std::inner_product(y.begin(), y.end(), y.begin(), 0.f));
// Use different criteria to take overmodelling into account.
if (filter_length_blocks == 12) {
EXPECT_LT(1000 * std::inner_product(e.begin(), e.end(), e.begin(), 0.f),
std::inner_product(y.begin(), y.end(), y.begin(), 0.f));
} else {
EXPECT_LT(std::inner_product(e.begin(), e.end(), e.begin(), 0.f),
std::inner_product(y.begin(), y.end(), y.begin(), 0.f));
}
}
}
}

View File

@ -164,7 +164,13 @@ TEST(Subtractor, Convergence) {
float echo_to_nearend_power =
RunSubtractorTest(300, delay_samples, filter_length_blocks, false,
blocks_with_echo_path_changes);
EXPECT_GT(0.1f, echo_to_nearend_power);
// Use different criteria to take overmodelling into account.
if (filter_length_blocks == 12) {
EXPECT_GT(0.1f, echo_to_nearend_power);
} else {
EXPECT_GT(1.f, echo_to_nearend_power);
}
}
}
}
@ -177,9 +183,9 @@ TEST(Subtractor, NonConvergenceOnUncorrelatedSignals) {
SCOPED_TRACE(ProduceDebugText(delay_samples, filter_length_blocks));
float echo_to_nearend_power =
RunSubtractorTest(100, delay_samples, filter_length_blocks, true,
RunSubtractorTest(300, delay_samples, filter_length_blocks, true,
blocks_with_echo_path_changes);
EXPECT_NEAR(1.f, echo_to_nearend_power, 0.05);
EXPECT_NEAR(1.f, echo_to_nearend_power, 0.1);
}
}
}

View File

@ -1162,12 +1162,12 @@ struct EchoCanceller3Config {
struct Filter {
size_t length_blocks = 12;
float shadow_rate = 0.5f;
float leakage_converged = 0.01f;
float leakage_diverged = 1.f / 60.f;
float error_floor = 0.1f;
float main_noise_gate = 220075344.f;
float shadow_noise_gate = 220075344.f;
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;
} filter;
struct Erle {