Added support in the AEC for refined filter adaptation.
The following algorithmic functionality was added:
-Add support for an exact regressor power to be computed
which avoids the issue with the updating of the filter
sometimes being unstable.
-Lowered the fixed step size of the adaptive filter to 0.05
which significantly reduces the sensitivity of the
adaptive filter to near-end noise, nonlinearities,
doubletalk and the unmodelled echo path tail. It also
reduces the tracking speed of the adaptive filter but the
chosen value proved to give a sufficient tradeoff for the
requirements on the adaptive filter.
To allow the new functionality to be selectively applied the following was done:
-A new Config was added for selectively activating the functionality.
-Functionality was added in the audioprocessing and echocancellationimpl classes
for passing the activation of the functionality down to the AEC algorithms.
To make the code for the introduction of the functionality clean,
the following refactoring was done:
-The selection of the step size was moved to a single place.
-The constant for the step size of the adaptive filter in extended filter mode was
made local.
-The state variable storing the step-size was renamed to a more describing name.
When the new functionality is not activated, the changes
have been tested for bitexactness on Linux.
TBR=minyue@webrtc.org
BUG=webrtc:5778, webrtc:5777
Review URL: https://codereview.webrtc.org/1887003002
Cr-Commit-Position: refs/heads/master@{#12384}
diff --git a/webrtc/modules/audio_processing/test/debug_dump_test.cc b/webrtc/modules/audio_processing/test/debug_dump_test.cc
index 60c1eb9..3acb694 100644
--- a/webrtc/modules/audio_processing/test/debug_dump_test.cc
+++ b/webrtc/modules/audio_processing/test/debug_dump_test.cc
@@ -341,6 +341,83 @@
VerifyDebugDump(generator.dump_file_name());
}
+TEST_F(DebugDumpTest, VerifyRefinedAdaptiveFilterExperimentalString) {
+ Config config;
+ config.Set<RefinedAdaptiveFilter>(new RefinedAdaptiveFilter(true));
+ DebugDumpGenerator generator(config);
+ generator.StartRecording();
+ generator.Process(100);
+ generator.StopRecording();
+
+ DebugDumpReplayer debug_dump_replayer_;
+
+ ASSERT_TRUE(debug_dump_replayer_.SetDumpFile(generator.dump_file_name()));
+
+ while (const rtc::Optional<audioproc::Event> event =
+ debug_dump_replayer_.GetNextEvent()) {
+ debug_dump_replayer_.RunNextEvent();
+ if (event->type() == audioproc::Event::CONFIG) {
+ const audioproc::Config* msg = &event->config();
+ ASSERT_TRUE(msg->has_experiments_description());
+ EXPECT_PRED_FORMAT2(testing::IsSubstring, "RefinedAdaptiveFilter",
+ msg->experiments_description().c_str());
+ }
+ }
+}
+
+TEST_F(DebugDumpTest, VerifyCombinedExperimentalStringInclusive) {
+ Config config;
+ config.Set<RefinedAdaptiveFilter>(new RefinedAdaptiveFilter(true));
+ config.Set<EchoCanceller3>(new EchoCanceller3(true));
+ DebugDumpGenerator generator(config);
+ generator.StartRecording();
+ generator.Process(100);
+ generator.StopRecording();
+
+ DebugDumpReplayer debug_dump_replayer_;
+
+ ASSERT_TRUE(debug_dump_replayer_.SetDumpFile(generator.dump_file_name()));
+
+ while (const rtc::Optional<audioproc::Event> event =
+ debug_dump_replayer_.GetNextEvent()) {
+ debug_dump_replayer_.RunNextEvent();
+ if (event->type() == audioproc::Event::CONFIG) {
+ const audioproc::Config* msg = &event->config();
+ ASSERT_TRUE(msg->has_experiments_description());
+ EXPECT_PRED_FORMAT2(testing::IsSubstring, "RefinedAdaptiveFilter",
+ msg->experiments_description().c_str());
+ EXPECT_PRED_FORMAT2(testing::IsSubstring, "AEC3",
+ msg->experiments_description().c_str());
+ }
+ }
+}
+
+TEST_F(DebugDumpTest, VerifyCombinedExperimentalStringExclusive) {
+ Config config;
+ config.Set<RefinedAdaptiveFilter>(new RefinedAdaptiveFilter(true));
+ DebugDumpGenerator generator(config);
+ generator.StartRecording();
+ generator.Process(100);
+ generator.StopRecording();
+
+ DebugDumpReplayer debug_dump_replayer_;
+
+ ASSERT_TRUE(debug_dump_replayer_.SetDumpFile(generator.dump_file_name()));
+
+ while (const rtc::Optional<audioproc::Event> event =
+ debug_dump_replayer_.GetNextEvent()) {
+ debug_dump_replayer_.RunNextEvent();
+ if (event->type() == audioproc::Event::CONFIG) {
+ const audioproc::Config* msg = &event->config();
+ ASSERT_TRUE(msg->has_experiments_description());
+ EXPECT_PRED_FORMAT2(testing::IsSubstring, "RefinedAdaptiveFilter",
+ msg->experiments_description().c_str());
+ EXPECT_PRED_FORMAT2(testing::IsNotSubstring, "AEC3",
+ msg->experiments_description().c_str());
+ }
+ }
+}
+
TEST_F(DebugDumpTest, VerifyAec3ExperimentalString) {
Config config;
config.Set<EchoCanceller3>(new EchoCanceller3(true));
@@ -358,8 +435,9 @@
debug_dump_replayer_.RunNextEvent();
if (event->type() == audioproc::Event::CONFIG) {
const audioproc::Config* msg = &event->config();
- EXPECT_TRUE(msg->has_experiments_description());
- EXPECT_NE(std::string::npos, msg->experiments_description().find("AEC3"));
+ ASSERT_TRUE(msg->has_experiments_description());
+ EXPECT_PRED_FORMAT2(testing::IsSubstring, "AEC3",
+ msg->experiments_description().c_str());
}
}
}
@@ -380,7 +458,7 @@
debug_dump_replayer_.RunNextEvent();
if (event->type() == audioproc::Event::CONFIG) {
const audioproc::Config* msg = &event->config();
- EXPECT_TRUE(msg->has_experiments_description());
+ ASSERT_TRUE(msg->has_experiments_description());
EXPECT_EQ(0u, msg->experiments_description().size());
}
}
diff --git a/webrtc/modules/audio_processing/test/process_test.cc b/webrtc/modules/audio_processing/test/process_test.cc
index 0d3921b..185bc14 100644
--- a/webrtc/modules/audio_processing/test/process_test.cc
+++ b/webrtc/modules/audio_processing/test/process_test.cc
@@ -82,6 +82,7 @@
printf(" --extended_filter\n");
printf(" --no_reported_delay\n");
printf(" --aec3\n");
+ printf(" --refined_adaptive_filter\n");
printf("\n -aecm Echo control mobile\n");
printf(" --aecm_echo_path_in_file FILE\n");
printf(" --aecm_echo_path_out_file FILE\n");
@@ -271,6 +272,9 @@
} else if (strcmp(argv[i], "--aec3") == 0) {
config.Set<EchoCanceller3>(new EchoCanceller3(true));
+ } else if (strcmp(argv[i], "--refined_adaptive_filter") == 0) {
+ config.Set<RefinedAdaptiveFilter>(new RefinedAdaptiveFilter(true));
+
} else if (strcmp(argv[i], "-aecm") == 0) {
ASSERT_EQ(apm->kNoError, apm->echo_control_mobile()->Enable(true));