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}
This commit is contained in:
@ -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.
|
||||
|
||||
@ -25,6 +25,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#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);
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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];
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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<ExtendedFilter>().enabled;
|
||||
delay_agnostic_enabled_ = config.Get<DelayAgnostic>().enabled;
|
||||
refined_adaptive_filter_enabled_ =
|
||||
config.Get<RefinedAdaptiveFilter>().enabled;
|
||||
aec3_enabled_ = config.Get<EchoCanceller3>().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;
|
||||
|
||||
@ -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_);
|
||||
|
||||
@ -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
|
||||
|
||||
@ -341,6 +341,83 @@ TEST_F(DebugDumpTest, ToggleDelayAgnosticAec) {
|
||||
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 @@ 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());
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<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));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user