Added the ability to adjust the AEC3 performance for large rooms

This CL exposes the parameter for adjusting the AEC3 performance
for large rooms.

Bug: webrtc:7519
Review-Url: https://codereview.webrtc.org/2967603002
Cr-Commit-Position: refs/heads/master@{#18862}
This commit is contained in:
peah 2017-06-30 07:06:10 -07:00 committed by Commit Bot
parent 4583db4967
commit 697a590314
21 changed files with 137 additions and 69 deletions

View File

@ -305,7 +305,7 @@ TEST(AdaptiveFirFilter, FilterAndAdapt) {
std::vector<std::vector<float>> x(3, std::vector<float>(kBlockSize, 0.f));
std::vector<float> n(kBlockSize, 0.f);
std::vector<float> y(kBlockSize, 0.f);
AecState aec_state;
AecState aec_state(0.f);
RenderSignalAnalyzer render_signal_analyzer;
std::vector<float> e(kBlockSize, 0.f);
std::array<float, kFftLength> s;

View File

@ -78,10 +78,11 @@ constexpr int kEchoPathChangeCounterMax = 2 * kNumBlocksPerSecond;
int AecState::instance_count_ = 0;
AecState::AecState()
AecState::AecState(float echo_decay)
: data_dumper_(
new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))),
echo_path_change_counter_(kEchoPathChangeCounterInitial) {}
echo_path_change_counter_(kEchoPathChangeCounterInitial),
echo_decay_factor_(echo_decay) {}
AecState::~AecState() = default;

View File

@ -31,7 +31,7 @@ class ApmDataDumper;
// Handles the state and the conditions for the echo removal functionality.
class AecState {
public:
AecState();
explicit AecState(float echo_decay);
~AecState();
// Returns whether the linear filter estimate is usable.
@ -79,7 +79,7 @@ class AecState {
// Returns the decay factor for the echo reverberation.
// TODO(peah): Make this adaptive.
float ReverbDecayFactor() const { return 0.f; }
float ReverbDecayFactor() const { return echo_decay_factor_; }
// Returns whether the echo suppression gain should be forced to zero.
bool ForcedZeroGain() const { return force_zero_gain_; }
@ -113,8 +113,8 @@ class AecState {
rtc::Optional<size_t> filter_delay_;
rtc::Optional<size_t> external_delay_;
size_t blocks_since_last_saturation_ = 1000;
RTC_DISALLOW_COPY_AND_ASSIGN(AecState);
const float echo_decay_factor_;
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(AecState);
};
} // namespace webrtc

View File

@ -18,7 +18,7 @@ namespace webrtc {
// Verify the general functionality of AecState
TEST(AecState, NormalUsage) {
ApmDataDumper data_dumper(42);
AecState state;
AecState state(0.f);
RenderBuffer render_buffer(Aec3Optimization::kNone, 3, 30,
std::vector<size_t>(1, 30));
std::array<float, kFftLengthBy2Plus1> E2_main = {};
@ -148,7 +148,7 @@ TEST(AecState, NormalUsage) {
// Verifies the a non-significant delay is correctly identified.
TEST(AecState, NonSignificantDelay) {
AecState state;
AecState state(0.f);
RenderBuffer render_buffer(Aec3Optimization::kNone, 3, 30,
std::vector<size_t>(1, 30));
std::array<float, kFftLengthBy2Plus1> E2_main;
@ -172,7 +172,7 @@ TEST(AecState, NonSignificantDelay) {
// Verifies the delay for a converged filter is correctly identified.
TEST(AecState, ConvergedFilterDelay) {
constexpr int kFilterLength = 10;
AecState state;
AecState state(0.f);
RenderBuffer render_buffer(Aec3Optimization::kNone, 3, 30,
std::vector<size_t>(1, 30));
std::array<float, kFftLengthBy2Plus1> E2_main;
@ -203,7 +203,7 @@ TEST(AecState, ConvergedFilterDelay) {
// Verify that the externally reported delay is properly reported and converted.
TEST(AecState, ExternalDelay) {
AecState state;
AecState state(0.f);
std::array<float, kFftLengthBy2Plus1> E2_main;
std::array<float, kFftLengthBy2Plus1> E2_shadow;
std::array<float, kFftLengthBy2Plus1> Y2;

View File

@ -168,29 +168,33 @@ void BlockProcessorImpl::UpdateEchoLeakageStatus(bool leakage_detected) {
} // namespace
BlockProcessor* BlockProcessor::Create(int sample_rate_hz) {
BlockProcessor* BlockProcessor::Create(
const AudioProcessing::Config::EchoCanceller3& config,
int sample_rate_hz) {
std::unique_ptr<RenderDelayBuffer> render_buffer(
RenderDelayBuffer::Create(NumBandsForRate(sample_rate_hz)));
std::unique_ptr<RenderDelayController> delay_controller(
RenderDelayController::Create(sample_rate_hz));
std::unique_ptr<EchoRemover> echo_remover(
EchoRemover::Create(sample_rate_hz));
return Create(sample_rate_hz, std::move(render_buffer),
EchoRemover::Create(config, sample_rate_hz));
return Create(config, sample_rate_hz, std::move(render_buffer),
std::move(delay_controller), std::move(echo_remover));
}
BlockProcessor* BlockProcessor::Create(
const AudioProcessing::Config::EchoCanceller3& config,
int sample_rate_hz,
std::unique_ptr<RenderDelayBuffer> render_buffer) {
std::unique_ptr<RenderDelayController> delay_controller(
RenderDelayController::Create(sample_rate_hz));
std::unique_ptr<EchoRemover> echo_remover(
EchoRemover::Create(sample_rate_hz));
return Create(sample_rate_hz, std::move(render_buffer),
EchoRemover::Create(config, sample_rate_hz));
return Create(config, sample_rate_hz, std::move(render_buffer),
std::move(delay_controller), std::move(echo_remover));
}
BlockProcessor* BlockProcessor::Create(
const AudioProcessing::Config::EchoCanceller3& config,
int sample_rate_hz,
std::unique_ptr<RenderDelayBuffer> render_buffer,
std::unique_ptr<RenderDelayController> delay_controller,

View File

@ -23,12 +23,16 @@ namespace webrtc {
// Class for performing echo cancellation on 64 sample blocks of audio data.
class BlockProcessor {
public:
static BlockProcessor* Create(int sample_rate_hz);
static BlockProcessor* Create(
const AudioProcessing::Config::EchoCanceller3& config,
int sample_rate_hz);
// Only used for testing purposes.
static BlockProcessor* Create(
const AudioProcessing::Config::EchoCanceller3& config,
int sample_rate_hz,
std::unique_ptr<RenderDelayBuffer> render_buffer);
static BlockProcessor* Create(
const AudioProcessing::Config::EchoCanceller3& config,
int sample_rate_hz,
std::unique_ptr<RenderDelayBuffer> render_buffer,
std::unique_ptr<RenderDelayController> delay_controller,

View File

@ -36,8 +36,8 @@ using testing::_;
// Verifies that the basic BlockProcessor functionality works and that the API
// methods are callable.
void RunBasicSetupAndApiCallTest(int sample_rate_hz) {
std::unique_ptr<BlockProcessor> block_processor(
BlockProcessor::Create(sample_rate_hz));
std::unique_ptr<BlockProcessor> block_processor(BlockProcessor::Create(
AudioProcessing::Config::EchoCanceller3(), sample_rate_hz));
std::vector<std::vector<float>> block(NumBandsForRate(sample_rate_hz),
std::vector<float>(kBlockSize, 0.f));
@ -48,8 +48,8 @@ void RunBasicSetupAndApiCallTest(int sample_rate_hz) {
#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
void RunRenderBlockSizeVerificationTest(int sample_rate_hz) {
std::unique_ptr<BlockProcessor> block_processor(
BlockProcessor::Create(sample_rate_hz));
std::unique_ptr<BlockProcessor> block_processor(BlockProcessor::Create(
AudioProcessing::Config::EchoCanceller3(), sample_rate_hz));
std::vector<std::vector<float>> block(
NumBandsForRate(sample_rate_hz), std::vector<float>(kBlockSize - 1, 0.f));
@ -57,8 +57,8 @@ void RunRenderBlockSizeVerificationTest(int sample_rate_hz) {
}
void RunCaptureBlockSizeVerificationTest(int sample_rate_hz) {
std::unique_ptr<BlockProcessor> block_processor(
BlockProcessor::Create(sample_rate_hz));
std::unique_ptr<BlockProcessor> block_processor(BlockProcessor::Create(
AudioProcessing::Config::EchoCanceller3(), sample_rate_hz));
std::vector<std::vector<float>> block(
NumBandsForRate(sample_rate_hz), std::vector<float>(kBlockSize - 1, 0.f));
@ -69,8 +69,8 @@ void RunRenderNumBandsVerificationTest(int sample_rate_hz) {
const size_t wrong_num_bands = NumBandsForRate(sample_rate_hz) < 3
? NumBandsForRate(sample_rate_hz) + 1
: 1;
std::unique_ptr<BlockProcessor> block_processor(
BlockProcessor::Create(sample_rate_hz));
std::unique_ptr<BlockProcessor> block_processor(BlockProcessor::Create(
AudioProcessing::Config::EchoCanceller3(), sample_rate_hz));
std::vector<std::vector<float>> block(wrong_num_bands,
std::vector<float>(kBlockSize, 0.f));
@ -81,8 +81,8 @@ void RunCaptureNumBandsVerificationTest(int sample_rate_hz) {
const size_t wrong_num_bands = NumBandsForRate(sample_rate_hz) < 3
? NumBandsForRate(sample_rate_hz) + 1
: 1;
std::unique_ptr<BlockProcessor> block_processor(
BlockProcessor::Create(sample_rate_hz));
std::unique_ptr<BlockProcessor> block_processor(BlockProcessor::Create(
AudioProcessing::Config::EchoCanceller3(), sample_rate_hz));
std::vector<std::vector<float>> block(wrong_num_bands,
std::vector<float>(kBlockSize, 0.f));
@ -126,7 +126,8 @@ TEST(BlockProcessor, DISABLED_DelayControllerIntegration) {
.Times(kNumBlocks + 1)
.WillRepeatedly(Return(0));
std::unique_ptr<BlockProcessor> block_processor(
BlockProcessor::Create(rate, std::move(render_delay_buffer_mock)));
BlockProcessor::Create(AudioProcessing::Config::EchoCanceller3(), rate,
std::move(render_delay_buffer_mock)));
std::vector<std::vector<float>> render_block(
NumBandsForRate(rate), std::vector<float>(kBlockSize, 0.f));
@ -180,7 +181,8 @@ TEST(BlockProcessor, DISABLED_SubmoduleIntegration) {
.Times(kNumBlocks);
std::unique_ptr<BlockProcessor> block_processor(BlockProcessor::Create(
rate, std::move(render_delay_buffer_mock),
AudioProcessing::Config::EchoCanceller3(), rate,
std::move(render_delay_buffer_mock),
std::move(render_delay_controller_mock), std::move(echo_remover_mock)));
std::vector<std::vector<float>> render_block(
@ -238,7 +240,9 @@ TEST(BlockProcessor, VerifyCaptureNumBandsCheck) {
// Verifiers that the verification for null ProcessCapture input works.
TEST(BlockProcessor, NullProcessCaptureParameter) {
EXPECT_DEATH(std::unique_ptr<BlockProcessor>(BlockProcessor::Create(8000))
EXPECT_DEATH(std::unique_ptr<BlockProcessor>(
BlockProcessor::Create(
AudioProcessing::Config::EchoCanceller3(), 8000))
->ProcessCapture(false, false, nullptr),
"");
}
@ -247,7 +251,8 @@ TEST(BlockProcessor, NullProcessCaptureParameter) {
// TODO(peah): Re-enable the test once the issue with memory leaks during DEATH
// tests on test bots has been fixed.
TEST(BlockProcessor, DISABLED_WrongSampleRate) {
EXPECT_DEATH(std::unique_ptr<BlockProcessor>(BlockProcessor::Create(8001)),
EXPECT_DEATH(std::unique_ptr<BlockProcessor>(BlockProcessor::Create(
AudioProcessing::Config::EchoCanceller3(), 8001)),
"");
}

View File

@ -36,7 +36,7 @@ TEST(ComfortNoiseGenerator, NullLowerBandNoise) {
std::array<float, kFftLengthBy2Plus1> N2;
FftData noise;
EXPECT_DEATH(ComfortNoiseGenerator(DetectOptimization())
.Compute(AecState(), N2, nullptr, &noise),
.Compute(AecState(0.f), N2, nullptr, &noise),
"");
}
@ -44,7 +44,7 @@ TEST(ComfortNoiseGenerator, NullUpperBandNoise) {
std::array<float, kFftLengthBy2Plus1> N2;
FftData noise;
EXPECT_DEATH(ComfortNoiseGenerator(DetectOptimization())
.Compute(AecState(), N2, &noise, nullptr),
.Compute(AecState(0.f), N2, &noise, nullptr),
"");
}
@ -91,7 +91,7 @@ TEST(ComfortNoiseGenerator, TestOptimizations) {
TEST(ComfortNoiseGenerator, CorrectLevel) {
ComfortNoiseGenerator cng(DetectOptimization());
AecState aec_state;
AecState aec_state(0.f);
std::array<float, kFftLengthBy2Plus1> N2;
N2.fill(1000.f * 1000.f);

View File

@ -200,11 +200,14 @@ void EchoCanceller3::RenderWriter::Insert(AudioBuffer* input) {
int EchoCanceller3::instance_count_ = 0;
EchoCanceller3::EchoCanceller3(int sample_rate_hz, bool use_highpass_filter)
EchoCanceller3::EchoCanceller3(
const AudioProcessing::Config::EchoCanceller3& config,
int sample_rate_hz,
bool use_highpass_filter)
: EchoCanceller3(sample_rate_hz,
use_highpass_filter,
std::unique_ptr<BlockProcessor>(
BlockProcessor::Create(sample_rate_hz))) {}
BlockProcessor::Create(config, sample_rate_hz))) {}
EchoCanceller3::EchoCanceller3(int sample_rate_hz,
bool use_highpass_filter,
std::unique_ptr<BlockProcessor> block_processor)
@ -331,7 +334,7 @@ std::string EchoCanceller3::ToString(
bool EchoCanceller3::Validate(
const AudioProcessing::Config::EchoCanceller3& config) {
return true;
return (config.echo_decay >= 0.f && config.echo_decay < 1.f);
}
void EchoCanceller3::EmptyRenderQueue() {

View File

@ -63,7 +63,9 @@ class Aec3RenderQueueItemVerifier {
class EchoCanceller3 {
public:
// Normal c-tor to use.
EchoCanceller3(int sample_rate_hz, bool use_highpass_filter);
EchoCanceller3(const AudioProcessing::Config::EchoCanceller3& config,
int sample_rate_hz,
bool use_highpass_filter);
// Testing c-tor that is used only for testing purposes.
EchoCanceller3(int sample_rate_hz,
bool use_highpass_filter,

View File

@ -495,7 +495,8 @@ class EchoCanceller3Tester {
// This test verifies that a buffer overrun in the render swapqueue is
// properly reported.
void RunRenderPipelineSwapQueueOverrunReturnValueTest() {
EchoCanceller3 aec3(sample_rate_hz_, false);
EchoCanceller3 aec3(AudioProcessing::Config::EchoCanceller3(),
sample_rate_hz_, false);
constexpr size_t kRenderTransferQueueSize = 30;
for (size_t k = 0; k < 2; ++k) {
@ -524,7 +525,8 @@ class EchoCanceller3Tester {
// Set aec3_sample_rate_hz to be different from sample_rate_hz_ in such a
// way that the number of bands for the rates are different.
const int aec3_sample_rate_hz = sample_rate_hz_ == 48000 ? 32000 : 48000;
EchoCanceller3 aec3(aec3_sample_rate_hz, false);
EchoCanceller3 aec3(AudioProcessing::Config::EchoCanceller3(),
aec3_sample_rate_hz, false);
PopulateInputFrame(frame_length_, 0, &render_buffer_.channels_f()[0][0], 0);
EXPECT_DEATH(aec3.AnalyzeRender(&render_buffer_), "");
@ -537,7 +539,8 @@ class EchoCanceller3Tester {
// Set aec3_sample_rate_hz to be different from sample_rate_hz_ in such a
// way that the number of bands for the rates are different.
const int aec3_sample_rate_hz = sample_rate_hz_ == 48000 ? 32000 : 48000;
EchoCanceller3 aec3(aec3_sample_rate_hz, false);
EchoCanceller3 aec3(AudioProcessing::Config::EchoCanceller3(),
aec3_sample_rate_hz, false);
PopulateInputFrame(frame_length_, num_bands_, 0,
&capture_buffer_.split_bands_f(0)[0], 100);
EXPECT_DEATH(aec3.ProcessCapture(&capture_buffer_, false), "");
@ -550,7 +553,8 @@ class EchoCanceller3Tester {
// Set aec3_sample_rate_hz to be different from sample_rate_hz_ in such a
// way that the band frame lengths are different.
const int aec3_sample_rate_hz = sample_rate_hz_ == 8000 ? 16000 : 8000;
EchoCanceller3 aec3(aec3_sample_rate_hz, false);
EchoCanceller3 aec3(AudioProcessing::Config::EchoCanceller3(),
aec3_sample_rate_hz, false);
OptionalBandSplit();
PopulateInputFrame(frame_length_, 0, &render_buffer_.channels_f()[0][0], 0);
@ -565,7 +569,8 @@ class EchoCanceller3Tester {
// Set aec3_sample_rate_hz to be different from sample_rate_hz_ in such a
// way that the band frame lengths are different.
const int aec3_sample_rate_hz = sample_rate_hz_ == 8000 ? 16000 : 8000;
EchoCanceller3 aec3(aec3_sample_rate_hz, false);
EchoCanceller3 aec3(AudioProcessing::Config::EchoCanceller3(),
aec3_sample_rate_hz, false);
OptionalBandSplit();
PopulateInputFrame(frame_length_, num_bands_, 0,
@ -677,6 +682,21 @@ TEST(EchoCanceller3Messaging, EchoLeakage) {
}
}
TEST(EchoCanceller3, ConfigValidation) {
AudioProcessing::Config::EchoCanceller3 config;
config.echo_decay = 0.f;
EXPECT_TRUE(EchoCanceller3::Validate(config));
config.echo_decay = 0.9f;
EXPECT_TRUE(EchoCanceller3::Validate(config));
config.echo_decay = -0.1f;
EXPECT_FALSE(EchoCanceller3::Validate(config));
config.echo_decay = 1.0f;
EXPECT_FALSE(EchoCanceller3::Validate(config));
config.echo_decay = 1.1f;
EXPECT_FALSE(EchoCanceller3::Validate(config));
}
#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
TEST(EchoCanceller3InputCheck, WrongCaptureNumBandsCheckVerification) {
@ -706,19 +726,28 @@ TEST(EchoCanceller3InputCheck, WrongCaptureFrameLengthCheckVerification) {
// Verifiers that the verification for null input to the render analysis api
// call works.
TEST(EchoCanceller3InputCheck, NullRenderAnalysisParameter) {
EXPECT_DEATH(EchoCanceller3(8000, false).AnalyzeRender(nullptr), "");
EXPECT_DEATH(
EchoCanceller3(AudioProcessing::Config::EchoCanceller3(), 8000, false)
.AnalyzeRender(nullptr),
"");
}
// Verifiers that the verification for null input to the capture analysis api
// call works.
TEST(EchoCanceller3InputCheck, NullCaptureAnalysisParameter) {
EXPECT_DEATH(EchoCanceller3(8000, false).AnalyzeCapture(nullptr), "");
EXPECT_DEATH(
EchoCanceller3(AudioProcessing::Config::EchoCanceller3(), 8000, false)
.AnalyzeCapture(nullptr),
"");
}
// Verifiers that the verification for null input to the capture processing api
// call works.
TEST(EchoCanceller3InputCheck, NullCaptureProcessingParameter) {
EXPECT_DEATH(EchoCanceller3(8000, false).ProcessCapture(nullptr, false), "");
EXPECT_DEATH(
EchoCanceller3(AudioProcessing::Config::EchoCanceller3(), 8000, false)
.ProcessCapture(nullptr, false),
"");
}
// Verifies the check for correct sample rate.
@ -726,7 +755,9 @@ TEST(EchoCanceller3InputCheck, NullCaptureProcessingParameter) {
// tests on test bots has been fixed.
TEST(EchoCanceller3InputCheck, DISABLED_WrongSampleRate) {
ApmDataDumper data_dumper(0);
EXPECT_DEATH(EchoCanceller3(8001, false), "");
EXPECT_DEATH(
EchoCanceller3(AudioProcessing::Config::EchoCanceller3(), 8001, false),
"");
}
#endif

View File

@ -49,7 +49,9 @@ void LinearEchoPower(const FftData& E,
// Class for removing the echo from the capture signal.
class EchoRemoverImpl final : public EchoRemover {
public:
explicit EchoRemoverImpl(int sample_rate_hz);
explicit EchoRemoverImpl(
const AudioProcessing::Config::EchoCanceller3& config,
int sample_rate_hz);
~EchoRemoverImpl() override;
// Removes the echo from a block of samples from the capture signal. The
@ -90,7 +92,9 @@ class EchoRemoverImpl final : public EchoRemover {
int EchoRemoverImpl::instance_count_ = 0;
EchoRemoverImpl::EchoRemoverImpl(int sample_rate_hz)
EchoRemoverImpl::EchoRemoverImpl(
const AudioProcessing::Config::EchoCanceller3& config,
int sample_rate_hz)
: fft_(),
data_dumper_(
new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))),
@ -99,7 +103,8 @@ EchoRemoverImpl::EchoRemoverImpl(int sample_rate_hz)
subtractor_(data_dumper_.get(), optimization_),
suppression_gain_(optimization_),
cng_(optimization_),
suppression_filter_(sample_rate_hz_) {
suppression_filter_(sample_rate_hz_),
aec_state_(config.echo_decay) {
RTC_DCHECK(ValidFullBandRate(sample_rate_hz));
}
@ -221,8 +226,10 @@ void EchoRemoverImpl::ProcessCapture(
} // namespace
EchoRemover* EchoRemover::Create(int sample_rate_hz) {
return new EchoRemoverImpl(sample_rate_hz);
EchoRemover* EchoRemover::Create(
const AudioProcessing::Config::EchoCanceller3& config,
int sample_rate_hz) {
return new EchoRemoverImpl(config, sample_rate_hz);
}
} // namespace webrtc

View File

@ -16,13 +16,16 @@
#include "webrtc/base/optional.h"
#include "webrtc/modules/audio_processing/aec3/echo_path_variability.h"
#include "webrtc/modules/audio_processing/aec3/render_buffer.h"
#include "webrtc/modules/audio_processing/include/audio_processing.h"
namespace webrtc {
// Class for removing the echo from the capture signal.
class EchoRemover {
public:
static EchoRemover* Create(int sample_rate_hz);
static EchoRemover* Create(
const AudioProcessing::Config::EchoCanceller3& config,
int sample_rate_hz);
virtual ~EchoRemover() = default;
// Removes the echo from a block of samples from the capture signal. The

View File

@ -126,7 +126,7 @@ TEST(DbMetric, Constructor) {
// Verify the general functionality of EchoRemoverMetrics.
TEST(EchoRemoverMetrics, NormalUsage) {
EchoRemoverMetrics metrics;
AecState aec_state;
AecState aec_state(0.f);
std::array<float, kFftLengthBy2Plus1> comfort_noise_spectrum;
std::array<float, kFftLengthBy2Plus1> suppressor_gain;
comfort_noise_spectrum.fill(10.f);

View File

@ -45,7 +45,8 @@ std::string ProduceDebugText(int sample_rate_hz, int delay) {
TEST(EchoRemover, BasicApiCalls) {
for (auto rate : {8000, 16000, 32000, 48000}) {
SCOPED_TRACE(ProduceDebugText(rate));
std::unique_ptr<EchoRemover> remover(EchoRemover::Create(rate));
std::unique_ptr<EchoRemover> remover(
EchoRemover::Create(AudioProcessing::Config::EchoCanceller3(), rate));
std::unique_ptr<RenderDelayBuffer> render_buffer(
RenderDelayBuffer::Create(NumBandsForRate(rate)));
@ -74,14 +75,17 @@ TEST(EchoRemover, BasicApiCalls) {
// TODO(peah): Re-enable the test once the issue with memory leaks during DEATH
// tests on test bots has been fixed.
TEST(EchoRemover, DISABLED_WrongSampleRate) {
EXPECT_DEATH(std::unique_ptr<EchoRemover>(EchoRemover::Create(8001)), "");
EXPECT_DEATH(std::unique_ptr<EchoRemover>(EchoRemover::Create(
AudioProcessing::Config::EchoCanceller3(), 8001)),
"");
}
// Verifies the check for the capture block size.
TEST(EchoRemover, WrongCaptureBlockSize) {
for (auto rate : {8000, 16000, 32000, 48000}) {
SCOPED_TRACE(ProduceDebugText(rate));
std::unique_ptr<EchoRemover> remover(EchoRemover::Create(rate));
std::unique_ptr<EchoRemover> remover(
EchoRemover::Create(AudioProcessing::Config::EchoCanceller3(), rate));
std::unique_ptr<RenderDelayBuffer> render_buffer(
RenderDelayBuffer::Create(NumBandsForRate(rate)));
std::vector<std::vector<float>> capture(
@ -101,7 +105,8 @@ TEST(EchoRemover, WrongCaptureBlockSize) {
TEST(EchoRemover, DISABLED_WrongCaptureNumBands) {
for (auto rate : {16000, 32000, 48000}) {
SCOPED_TRACE(ProduceDebugText(rate));
std::unique_ptr<EchoRemover> remover(EchoRemover::Create(rate));
std::unique_ptr<EchoRemover> remover(
EchoRemover::Create(AudioProcessing::Config::EchoCanceller3(), rate));
std::unique_ptr<RenderDelayBuffer> render_buffer(
RenderDelayBuffer::Create(NumBandsForRate(rate)));
std::vector<std::vector<float>> capture(
@ -118,7 +123,8 @@ TEST(EchoRemover, DISABLED_WrongCaptureNumBands) {
// Verifies the check for non-null capture block.
TEST(EchoRemover, NullCapture) {
std::unique_ptr<EchoRemover> remover(EchoRemover::Create(8000));
std::unique_ptr<EchoRemover> remover(
EchoRemover::Create(AudioProcessing::Config::EchoCanceller3(), 8000));
std::unique_ptr<RenderDelayBuffer> render_buffer(
RenderDelayBuffer::Create(3));
EchoPathVariability echo_path_variability(false, false);
@ -144,7 +150,8 @@ TEST(EchoRemover, BasicEchoRemoval) {
EchoPathVariability echo_path_variability(false, false);
for (size_t delay_samples : {0, 64, 150, 200, 301}) {
SCOPED_TRACE(ProduceDebugText(rate, delay_samples));
std::unique_ptr<EchoRemover> remover(EchoRemover::Create(rate));
std::unique_ptr<EchoRemover> remover(
EchoRemover::Create(AudioProcessing::Config::EchoCanceller3(), rate));
std::unique_ptr<RenderDelayBuffer> render_buffer(
RenderDelayBuffer::Create(NumBandsForRate(rate)));
std::vector<std::unique_ptr<DelayBuffer<float>>> delay_buffers(x.size());

View File

@ -53,7 +53,7 @@ void RunFilterUpdateTest(int num_blocks_to_process,
Random random_generator(42U);
std::vector<std::vector<float>> x(3, std::vector<float>(kBlockSize, 0.f));
std::vector<float> y(kBlockSize, 0.f);
AecState aec_state;
AecState aec_state(0.f);
RenderSignalAnalyzer render_signal_analyzer;
std::array<float, kFftLength> s;
FftData S;

View File

@ -22,7 +22,7 @@ namespace webrtc {
// Verifies that the check for non-null output residual echo power works.
TEST(ResidualEchoEstimator, NullResidualEchoPowerOutput) {
AecState aec_state;
AecState aec_state(0.f);
RenderBuffer render_buffer(Aec3Optimization::kNone, 3, 10,
std::vector<size_t>(1, 10));
std::vector<std::array<float, kFftLengthBy2Plus1>> H2;
@ -37,7 +37,7 @@ TEST(ResidualEchoEstimator, NullResidualEchoPowerOutput) {
TEST(ResidualEchoEstimator, BasicTest) {
ResidualEchoEstimator estimator;
AecState aec_state;
AecState aec_state(0.f);
RenderBuffer render_buffer(Aec3Optimization::kNone, 3, 10,
std::vector<size_t>(1, 10));
std::array<float, kFftLengthBy2Plus1> E2_main;

View File

@ -47,7 +47,7 @@ void RunFilterUpdateTest(int num_blocks_to_process,
Random random_generator(42U);
std::vector<std::vector<float>> x(3, std::vector<float>(kBlockSize, 0.f));
std::vector<float> y(kBlockSize, 0.f);
AecState aec_state;
AecState aec_state(0.f);
RenderSignalAnalyzer render_signal_analyzer;
std::array<float, kFftLength> s;
FftData S;

View File

@ -40,7 +40,7 @@ float RunSubtractorTest(int num_blocks_to_process,
std::array<float, kFftLengthBy2Plus1> Y2;
std::array<float, kFftLengthBy2Plus1> E2_main;
std::array<float, kFftLengthBy2Plus1> E2_shadow;
AecState aec_state;
AecState aec_state(0.f);
x_old.fill(0.f);
Y2.fill(0.f);
E2_main.fill(0.f);
@ -109,7 +109,7 @@ TEST(Subtractor, DISABLED_NullOutput) {
std::vector<float> y(kBlockSize, 0.f);
EXPECT_DEATH(subtractor.Process(render_buffer, y, render_signal_analyzer,
AecState(), nullptr),
AecState(0.f), nullptr),
"");
}
@ -124,7 +124,7 @@ TEST(Subtractor, WrongCaptureSize) {
SubtractorOutput output;
EXPECT_DEATH(subtractor.Process(render_buffer, y, render_signal_analyzer,
AecState(), &output),
AecState(0.f), &output),
"");
}

View File

@ -1881,8 +1881,8 @@ void AudioProcessingImpl::InitializeLowCutFilter() {
void AudioProcessingImpl::InitializeEchoCanceller3() {
if (capture_nonlocked_.echo_canceller3_enabled) {
private_submodules_->echo_canceller3.reset(
new EchoCanceller3(proc_sample_rate_hz(), true));
private_submodules_->echo_canceller3.reset(new EchoCanceller3(
config_.echo_canceller3, proc_sample_rate_hz(), true));
} else {
private_submodules_->echo_canceller3.reset();
}

View File

@ -268,6 +268,7 @@ class AudioProcessing : public rtc::RefCountInterface {
// does not yet have the desired behavior.
struct EchoCanceller3 {
bool enabled = false;
float echo_decay = 0.f;
} echo_canceller3;
// Enables the next generation AGC functionality. This feature replaces the