diff --git a/webrtc/common.h b/webrtc/common.h index 58aba517e9..f2a868241d 100644 --- a/webrtc/common.h +++ b/webrtc/common.h @@ -32,7 +32,8 @@ enum class ConfigOptionID { kExperimentalNs, kBeamforming, kIntelligibility, - kEchoCanceller3 + kEchoCanceller3, + kAecRefinedAdaptiveFilter }; // Class Config is designed to ease passing a set of options across webrtc code. diff --git a/webrtc/modules/audio_processing/aec/aec_core.cc b/webrtc/modules/audio_processing/aec/aec_core.cc index 4b5abedd5a..f13cf94c2b 100644 --- a/webrtc/modules/audio_processing/aec/aec_core.cc +++ b/webrtc/modules/audio_processing/aec/aec_core.cc @@ -25,6 +25,7 @@ #include #include +#include "webrtc/base/checks.h" extern "C" { #include "webrtc/common_audio/ring_buffer.h" } @@ -238,15 +239,10 @@ static void FilterFar(int num_partitions, } } -static void ScaleErrorSignal(int extended_filter_enabled, - float normal_mu, - float normal_error_threshold, +static void ScaleErrorSignal(float mu, + float error_threshold, float x_pow[PART_LEN1], float ef[2][PART_LEN1]) { - const float mu = extended_filter_enabled ? kExtendedMu : normal_mu; - const float error_threshold = extended_filter_enabled - ? kExtendedErrorThreshold - : normal_error_threshold; int i; float abs_ef; for (i = 0; i < (PART_LEN1); i++) { @@ -936,11 +932,38 @@ static int SignalBasedDelayCorrection(AecCore* self) { return delay_correction; } +static void RegressorPower(int num_partitions, + int latest_added_partition, + float x_fft_buf[2] + [kExtendedNumPartitions * PART_LEN1], + float x_pow[PART_LEN1]) { + RTC_DCHECK_LT(latest_added_partition, num_partitions); + memset(x_pow, 0, PART_LEN1 * sizeof(x_pow[0])); + + int partition = latest_added_partition; + int x_fft_buf_position = partition * PART_LEN1; + for (int i = 0; i < num_partitions; ++i) { + for (int bin = 0; bin < PART_LEN1; ++bin) { + float re = x_fft_buf[0][x_fft_buf_position]; + float im = x_fft_buf[1][x_fft_buf_position]; + x_pow[bin] += re * re + im * im; + ++x_fft_buf_position; + } + + ++partition; + if (partition == num_partitions) { + partition = 0; + RTC_DCHECK_EQ(num_partitions * PART_LEN1, x_fft_buf_position); + x_fft_buf_position = 0; + } + } +} + static void EchoSubtraction(AecCore* aec, int num_partitions, int extended_filter_enabled, - float normal_mu, - float normal_error_threshold, + float filter_step_size, + float error_threshold, float* x_fft, int* x_fft_buf_block_pos, float x_fft_buf[2] @@ -1001,8 +1024,7 @@ static void EchoSubtraction(AecCore* aec, sizeof(e_fft[0][0]) * PART_LEN1 * 2); // Scale error signal inversely with far power. - WebRtcAec_ScaleErrorSignal(extended_filter_enabled, normal_mu, - normal_error_threshold, x_pow, e_fft); + WebRtcAec_ScaleErrorSignal(filter_step_size, error_threshold, x_pow, e_fft); WebRtcAec_FilterAdaptation(num_partitions, *x_fft_buf_block_pos, x_fft_buf, e_fft, h_fft_buf); memcpy(echo_subtractor_output, e, sizeof(float) * PART_LEN); @@ -1315,18 +1337,31 @@ static void ProcessBlock(AecCore* aec) { memcpy(fft, aec->dBuf, sizeof(float) * PART_LEN2); Fft(fft, df); - // Power smoothing - for (i = 0; i < PART_LEN1; i++) { - far_spectrum = (x_fft_ptr[i] * x_fft_ptr[i]) + - (x_fft_ptr[PART_LEN1 + i] * x_fft_ptr[PART_LEN1 + i]); - aec->xPow[i] = - gPow[0] * aec->xPow[i] + gPow[1] * aec->num_partitions * far_spectrum; - // Calculate absolute spectra - abs_far_spectrum[i] = sqrtf(far_spectrum); + // Power smoothing. + if (aec->refined_adaptive_filter_enabled) { + for (i = 0; i < PART_LEN1; ++i) { + far_spectrum = (x_fft_ptr[i] * x_fft_ptr[i]) + + (x_fft_ptr[PART_LEN1 + i] * x_fft_ptr[PART_LEN1 + i]); + // Calculate the magnitude spectrum. + abs_far_spectrum[i] = sqrtf(far_spectrum); + } + RegressorPower(aec->num_partitions, aec->xfBufBlockPos, aec->xfBuf, + aec->xPow); + } else { + for (i = 0; i < PART_LEN1; ++i) { + far_spectrum = (x_fft_ptr[i] * x_fft_ptr[i]) + + (x_fft_ptr[PART_LEN1 + i] * x_fft_ptr[PART_LEN1 + i]); + aec->xPow[i] = + gPow[0] * aec->xPow[i] + gPow[1] * aec->num_partitions * far_spectrum; + // Calculate the magnitude spectrum. + abs_far_spectrum[i] = sqrtf(far_spectrum); + } + } + for (i = 0; i < PART_LEN1; ++i) { near_spectrum = df[0][i] * df[0][i] + df[1][i] * df[1][i]; aec->dPow[i] = gPow[0] * aec->dPow[i] + gPow[1] * near_spectrum; - // Calculate absolute spectra + // Calculate the magnitude spectrum. abs_near_spectrum[i] = sqrtf(near_spectrum); } @@ -1379,7 +1414,7 @@ static void ProcessBlock(AecCore* aec) { // Perform echo subtraction. EchoSubtraction(aec, aec->num_partitions, aec->extended_filter_enabled, - aec->normal_mu, aec->normal_error_threshold, &x_fft[0][0], + aec->filter_step_size, aec->error_threshold, &x_fft[0][0], &aec->xfBufBlockPos, aec->xfBuf, nearend_ptr, aec->xPow, aec->wfBuf, echo_subtractor_output); @@ -1485,6 +1520,7 @@ AecCore* WebRtcAec_CreateAec() { #endif aec->extended_filter_enabled = 0; aec->aec3_enabled = 0; + aec->refined_adaptive_filter_enabled = false; // Assembly optimization WebRtcAec_FilterFar = FilterFar; @@ -1548,18 +1584,53 @@ void WebRtcAec_FreeAec(AecCore* aec) { delete aec; } +static void SetAdaptiveFilterStepSize(AecCore* aec) { + // Extended filter adaptation parameter. + // TODO(ajm): No narrowband tuning yet. + const float kExtendedMu = 0.4f; + + if (aec->refined_adaptive_filter_enabled) { + aec->filter_step_size = 0.05f; + } else { + if (aec->extended_filter_enabled) { + aec->filter_step_size = kExtendedMu; + } else { + if (aec->sampFreq == 8000) { + aec->filter_step_size = 0.6f; + } else { + aec->filter_step_size = 0.5f; + } + } + } +} + +static void SetErrorThreshold(AecCore* aec) { + // Extended filter adaptation parameter. + // TODO(ajm): No narrowband tuning yet. + static const float kExtendedErrorThreshold = 1.0e-6f; + + if (aec->extended_filter_enabled) { + aec->error_threshold = kExtendedErrorThreshold; + } else { + if (aec->sampFreq == 8000) { + aec->error_threshold = 2e-6f; + } else { + aec->error_threshold = 1.5e-6f; + } + } +} + int WebRtcAec_InitAec(AecCore* aec, int sampFreq) { int i; aec->sampFreq = sampFreq; + SetAdaptiveFilterStepSize(aec); + SetErrorThreshold(aec); + if (sampFreq == 8000) { - aec->normal_mu = 0.6f; - aec->normal_error_threshold = 2e-6f; aec->num_bands = 1; } else { - aec->normal_mu = 0.5f; - aec->normal_error_threshold = 1.5e-6f; aec->num_bands = (size_t)(sampFreq / 16000); } @@ -1930,9 +2001,20 @@ int WebRtcAec_aec3_enabled(AecCore* self) { return self->aec3_enabled; } +void WebRtcAec_enable_refined_adaptive_filter(AecCore* self, bool enable) { + self->refined_adaptive_filter_enabled = enable; + SetAdaptiveFilterStepSize(self); + SetErrorThreshold(self); +} + +bool WebRtcAec_refined_adaptive_filter_enabled(const AecCore* self) { + return self->refined_adaptive_filter_enabled; +} void WebRtcAec_enable_extended_filter(AecCore* self, int enable) { self->extended_filter_enabled = enable; + SetAdaptiveFilterStepSize(self); + SetErrorThreshold(self); self->num_partitions = enable ? kExtendedNumPartitions : kNormalNumPartitions; // Update the delay estimator with filter length. See InitAEC() for details. WebRtc_set_allowed_offset(self->delay_estimator, self->num_partitions / 2); diff --git a/webrtc/modules/audio_processing/aec/aec_core.h b/webrtc/modules/audio_processing/aec/aec_core.h index 71f02d6a3e..bd5b283eca 100644 --- a/webrtc/modules/audio_processing/aec/aec_core.h +++ b/webrtc/modules/audio_processing/aec/aec_core.h @@ -120,6 +120,12 @@ void WebRtcAec_enable_aec3(AecCore* self, int enable); // Returns 1 if the next generation aec is enabled and zero if disabled. int WebRtcAec_aec3_enabled(AecCore* self); +// Turns on/off the refined adaptive filter feature. +void WebRtcAec_enable_refined_adaptive_filter(AecCore* self, bool enable); + +// Returns whether the refined adaptive filter is enabled. +bool WebRtcAec_refined_adaptive_filter(const AecCore* self); + // Enables or disables extended filter mode. Non-zero enables, zero disables. void WebRtcAec_enable_extended_filter(AecCore* self, int enable); diff --git a/webrtc/modules/audio_processing/aec/aec_core_internal.h b/webrtc/modules/audio_processing/aec/aec_core_internal.h index 05f5083c4a..1f7b6b541f 100644 --- a/webrtc/modules/audio_processing/aec/aec_core_internal.h +++ b/webrtc/modules/audio_processing/aec/aec_core_internal.h @@ -35,11 +35,6 @@ enum { kHistorySizeBlocks = 125 }; -// Extended filter adaptation parameters. -// TODO(ajm): No narrowband tuning yet. -static const float kExtendedMu = 0.4f; -static const float kExtendedErrorThreshold = 1.0e-6f; - typedef struct PowerLevel { PowerLevel(); @@ -126,12 +121,12 @@ struct AecCore { int system_delay; // Current system delay buffered in AEC. int mult; // sampling frequency multiple - int sampFreq; + int sampFreq = 16000; size_t num_bands; uint32_t seed; - float normal_mu; // stepsize - float normal_error_threshold; // error threshold + float filter_step_size; // stepsize + float error_threshold; // error threshold int noiseEstCtr; @@ -178,6 +173,7 @@ struct AecCore { int extended_filter_enabled; // 1 = next generation aec mode enabled, 0 = disabled. int aec3_enabled; + bool refined_adaptive_filter_enabled; // Runtime selection of number of filter partitions. int num_partitions; @@ -210,9 +206,8 @@ typedef void (*WebRtcAecFilterFar)( float h_fft_buf[2][kExtendedNumPartitions * PART_LEN1], float y_fft[2][PART_LEN1]); extern WebRtcAecFilterFar WebRtcAec_FilterFar; -typedef void (*WebRtcAecScaleErrorSignal)(int extended_filter_enabled, - float normal_mu, - float normal_error_threshold, +typedef void (*WebRtcAecScaleErrorSignal)(float mu, + float error_threshold, float x_pow[PART_LEN1], float ef[2][PART_LEN1]); extern WebRtcAecScaleErrorSignal WebRtcAec_ScaleErrorSignal; diff --git a/webrtc/modules/audio_processing/aec/aec_core_mips.cc b/webrtc/modules/audio_processing/aec/aec_core_mips.cc index 4699e35baf..e12f2ef28a 100644 --- a/webrtc/modules/audio_processing/aec/aec_core_mips.cc +++ b/webrtc/modules/audio_processing/aec/aec_core_mips.cc @@ -707,15 +707,10 @@ void WebRtcAec_OverdriveAndSuppress_mips(AecCore* aec, } } -void WebRtcAec_ScaleErrorSignal_mips(int extended_filter_enabled, - float normal_mu, - float normal_error_threshold, +void WebRtcAec_ScaleErrorSignal_mips(float mu, + float error_threshold, float x_pow[PART_LEN1], float ef[2][PART_LEN1]) { - const float mu = extended_filter_enabled ? kExtendedMu : normal_mu; - const float error_threshold = extended_filter_enabled - ? kExtendedErrorThreshold - : normal_error_threshold; int len = (PART_LEN1); float* ef0 = ef[0]; float* ef1 = ef[1]; diff --git a/webrtc/modules/audio_processing/aec/aec_core_neon.cc b/webrtc/modules/audio_processing/aec/aec_core_neon.cc index 69e8d52c91..12b9359a91 100644 --- a/webrtc/modules/audio_processing/aec/aec_core_neon.cc +++ b/webrtc/modules/audio_processing/aec/aec_core_neon.cc @@ -127,15 +127,10 @@ static float32x4_t vsqrtq_f32(float32x4_t s) { } #endif // WEBRTC_ARCH_ARM64 -static void ScaleErrorSignalNEON(int extended_filter_enabled, - float normal_mu, - float normal_error_threshold, +static void ScaleErrorSignalNEON(float mu, + float error_threshold, float x_pow[PART_LEN1], float ef[2][PART_LEN1]) { - const float mu = extended_filter_enabled ? kExtendedMu : normal_mu; - const float error_threshold = extended_filter_enabled - ? kExtendedErrorThreshold - : normal_error_threshold; const float32x4_t k1e_10f = vdupq_n_f32(1e-10f); const float32x4_t kMu = vmovq_n_f32(mu); const float32x4_t kThresh = vmovq_n_f32(error_threshold); diff --git a/webrtc/modules/audio_processing/aec/aec_core_sse2.cc b/webrtc/modules/audio_processing/aec/aec_core_sse2.cc index 254dbf10e3..8fa0166ea1 100644 --- a/webrtc/modules/audio_processing/aec/aec_core_sse2.cc +++ b/webrtc/modules/audio_processing/aec/aec_core_sse2.cc @@ -79,17 +79,13 @@ static void FilterFarSSE2(int num_partitions, } } -static void ScaleErrorSignalSSE2(int extended_filter_enabled, - float normal_mu, - float normal_error_threshold, +static void ScaleErrorSignalSSE2(float mu, + float error_threshold, float x_pow[PART_LEN1], float ef[2][PART_LEN1]) { const __m128 k1e_10f = _mm_set1_ps(1e-10f); - const __m128 kMu = extended_filter_enabled ? _mm_set1_ps(kExtendedMu) - : _mm_set1_ps(normal_mu); - const __m128 kThresh = extended_filter_enabled - ? _mm_set1_ps(kExtendedErrorThreshold) - : _mm_set1_ps(normal_error_threshold); + const __m128 kMu = _mm_set1_ps(mu); + const __m128 kThresh = _mm_set1_ps(error_threshold); int i; // vectorized code (four at once) @@ -124,10 +120,6 @@ static void ScaleErrorSignalSSE2(int extended_filter_enabled, } // scalar code for the remaining items. { - const float mu = extended_filter_enabled ? kExtendedMu : normal_mu; - const float error_threshold = extended_filter_enabled - ? kExtendedErrorThreshold - : normal_error_threshold; for (; i < (PART_LEN1); i++) { float abs_ef; ef[0][i] /= (x_pow[i] + 1e-10f); diff --git a/webrtc/modules/audio_processing/echo_cancellation_impl.cc b/webrtc/modules/audio_processing/echo_cancellation_impl.cc index 12ea75efe1..c18ed94bd2 100644 --- a/webrtc/modules/audio_processing/echo_cancellation_impl.cc +++ b/webrtc/modules/audio_processing/echo_cancellation_impl.cc @@ -415,7 +415,16 @@ bool EchoCancellationImpl::is_aec3_enabled() const { std::string EchoCancellationImpl::GetExperimentsDescription() { rtc::CritScope cs(crit_capture_); - return aec3_enabled_ ? "AEC3" : ""; + std::string description = (aec3_enabled_ ? "AEC3" : ""); + if (refined_adaptive_filter_enabled_) { + description += ";RefinedAdaptiveFilter"; + } + return description; +} + +bool EchoCancellationImpl::is_refined_adaptive_filter_enabled() const { + rtc::CritScope cs(crit_capture_); + return refined_adaptive_filter_enabled_; } bool EchoCancellationImpl::is_extended_filter_enabled() const { @@ -534,6 +543,8 @@ void EchoCancellationImpl::SetExtraOptions(const Config& config) { rtc::CritScope cs(crit_capture_); extended_filter_enabled_ = config.Get().enabled; delay_agnostic_enabled_ = config.Get().enabled; + refined_adaptive_filter_enabled_ = + config.Get().enabled; aec3_enabled_ = config.Get().enabled; } Configure(); @@ -556,6 +567,9 @@ int EchoCancellationImpl::Configure() { delay_agnostic_enabled_ ? 1 : 0); WebRtcAec_enable_aec3(WebRtcAec_aec_core(canceller->state()), aec3_enabled_ ? 1 : 0); + WebRtcAec_enable_refined_adaptive_filter( + WebRtcAec_aec_core(canceller->state()), + refined_adaptive_filter_enabled_); const int handle_error = WebRtcAec_set_config(canceller->state(), config); if (handle_error != AudioProcessing::kNoError) { error = AudioProcessing::kNoError; diff --git a/webrtc/modules/audio_processing/echo_cancellation_impl.h b/webrtc/modules/audio_processing/echo_cancellation_impl.h index b58ba596ea..f67ef7b7da 100644 --- a/webrtc/modules/audio_processing/echo_cancellation_impl.h +++ b/webrtc/modules/audio_processing/echo_cancellation_impl.h @@ -48,6 +48,7 @@ class EchoCancellationImpl : public EchoCancellation { bool is_extended_filter_enabled() const; bool is_aec3_enabled() const; std::string GetExperimentsDescription(); + bool is_refined_adaptive_filter_enabled() const; // Checks whether the module is enabled. Must only be // called from the render side of APM as otherwise @@ -102,6 +103,7 @@ class EchoCancellationImpl : public EchoCancellation { bool extended_filter_enabled_ GUARDED_BY(crit_capture_); bool delay_agnostic_enabled_ GUARDED_BY(crit_capture_); bool aec3_enabled_ GUARDED_BY(crit_capture_); + bool refined_adaptive_filter_enabled_ GUARDED_BY(crit_capture_) = false; size_t render_queue_element_max_size_ GUARDED_BY(crit_render_) GUARDED_BY(crit_capture_); diff --git a/webrtc/modules/audio_processing/include/audio_processing.h b/webrtc/modules/audio_processing/include/audio_processing.h index ad95fadb1a..0c93a984b2 100644 --- a/webrtc/modules/audio_processing/include/audio_processing.h +++ b/webrtc/modules/audio_processing/include/audio_processing.h @@ -80,6 +80,18 @@ struct EchoCanceller3 { bool enabled; }; +// Enables the refined linear filter adaptation in the echo canceller. +// This configuration only applies to EchoCancellation and not +// EchoControlMobile. It can be set in the constructor +// or using AudioProcessing::SetExtraOptions(). +struct RefinedAdaptiveFilter { + RefinedAdaptiveFilter() : enabled(false) {} + explicit RefinedAdaptiveFilter(bool enabled) : enabled(enabled) {} + static const ConfigOptionID identifier = + ConfigOptionID::kAecRefinedAdaptiveFilter; + bool enabled; +}; + // Enables delay-agnostic echo cancellation. This feature relies on internally // estimated delays between the process and reverse streams, thus not relying // on reported system delays. This configuration only applies to diff --git a/webrtc/modules/audio_processing/test/debug_dump_test.cc b/webrtc/modules/audio_processing/test/debug_dump_test.cc index 60c1eb9511..3acb69444d 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 @@ TEST_F(DebugDumpTest, ToggleDelayAgnosticAec) { VerifyDebugDump(generator.dump_file_name()); } +TEST_F(DebugDumpTest, VerifyRefinedAdaptiveFilterExperimentalString) { + Config config; + config.Set(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 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(new RefinedAdaptiveFilter(true)); + config.Set(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 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(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 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(new EchoCanceller3(true)); @@ -358,8 +435,9 @@ TEST_F(DebugDumpTest, VerifyAec3ExperimentalString) { 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 @@ TEST_F(DebugDumpTest, VerifyEmptyExperimentalString) { 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 0d3921ba18..185bc142d5 100644 --- a/webrtc/modules/audio_processing/test/process_test.cc +++ b/webrtc/modules/audio_processing/test/process_test.cc @@ -82,6 +82,7 @@ void usage() { 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 @@ void void_main(int argc, char* argv[]) { } else if (strcmp(argv[i], "--aec3") == 0) { config.Set(new EchoCanceller3(true)); + } else if (strcmp(argv[i], "--refined_adaptive_filter") == 0) { + config.Set(new RefinedAdaptiveFilter(true)); + } else if (strcmp(argv[i], "-aecm") == 0) { ASSERT_EQ(apm->kNoError, apm->echo_control_mobile()->Enable(true));