Separate AEC3 config from AudioProcessing::Config.

The struct containing the config for AEC3 is removed from
AudioProcessing::Config and is put in a new struct called
EchoCanceller3Config.

AEC3 should no longer be activated through
AudioProcessing::ApplyConfig. Instead an EchoCanceller3Factory
can be injected at AudioProcessing creation.

Bug: webrtc:8346
Change-Id: I27e3592e675eec3632a60c45d9e0d12514c2c567
Reviewed-on: https://webrtc-review.googlesource.com/11420
Reviewed-by: Per Åhgren <peah@webrtc.org>
Reviewed-by: Henrik Lundin <henrik.lundin@webrtc.org>
Commit-Queue: Gustaf Ullberg <gustaf@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#20342}
This commit is contained in:
Gustaf Ullberg
2017-10-18 12:32:42 +02:00
committed by Commit Bot
parent 737e073f8d
commit bd83b914c3
36 changed files with 285 additions and 323 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<std::vector<float>> x(3, std::vector<float>(kBlockSize, 0.f));
std::vector<float> n(kBlockSize, 0.f); std::vector<float> n(kBlockSize, 0.f);
std::vector<float> y(kBlockSize, 0.f); std::vector<float> y(kBlockSize, 0.f);
AecState aec_state(AudioProcessing::Config::EchoCanceller3{}); AecState aec_state(EchoCanceller3Config{});
RenderSignalAnalyzer render_signal_analyzer; RenderSignalAnalyzer render_signal_analyzer;
std::vector<float> e(kBlockSize, 0.f); std::vector<float> e(kBlockSize, 0.f);
std::array<float, kFftLength> s_scratch; std::array<float, kFftLength> s_scratch;

View File

@ -51,14 +51,12 @@ int EstimateFilterDelay(
int AecState::instance_count_ = 0; int AecState::instance_count_ = 0;
AecState::AecState(const AudioProcessing::Config::EchoCanceller3& config) AecState::AecState(const EchoCanceller3Config& config)
: data_dumper_( : data_dumper_(
new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))), new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))),
erle_estimator_(config.param.erle.min, erle_estimator_(config.erle.min, config.erle.max_l, config.erle.max_h),
config.param.erle.max_l,
config.param.erle.max_h),
config_(config), config_(config),
reverb_decay_(config_.param.ep_strength.default_len) {} reverb_decay_(config_.ep_strength.default_len) {}
AecState::~AecState() = default; AecState::~AecState() = default;
@ -133,7 +131,7 @@ void AecState::Update(const std::vector<std::array<float, kFftLengthBy2Plus1>>&
const float max_sample = fabs(*std::max_element( const float max_sample = fabs(*std::max_element(
x.begin(), x.end(), [](float a, float b) { return a * a < b * b; })); x.begin(), x.end(), [](float a, float b) { return a * a < b * b; }));
if (config_.param.ep_strength.echo_can_saturate) { if (config_.ep_strength.echo_can_saturate) {
const bool saturated_echo = const bool saturated_echo =
(previous_max_sample_ > 200.f) && SaturatedCapture(); (previous_max_sample_ > 200.f) && SaturatedCapture();
@ -158,8 +156,8 @@ void AecState::Update(const std::vector<std::array<float, kFftLengthBy2Plus1>>&
// transparent mode should be entered. // transparent mode should be entered.
const float x_energy = std::inner_product(x.begin(), x.end(), x.begin(), 0.f); const float x_energy = std::inner_product(x.begin(), x.end(), x.begin(), 0.f);
const bool active_render_block = const bool active_render_block =
x_energy > (config_.param.render_levels.active_render_limit * x_energy > (config_.render_levels.active_render_limit *
config_.param.render_levels.active_render_limit) * config_.render_levels.active_render_limit) *
kFftLengthBy2; kFftLengthBy2;
if (active_render_block) { if (active_render_block) {
render_received_ = true; render_received_ = true;
@ -238,8 +236,7 @@ void AecState::UpdateReverb(
// Limit the estimated reverb_decay_ to the maximum one needed in practice // Limit the estimated reverb_decay_ to the maximum one needed in practice
// to minimize the impact of incorrect estimates. // to minimize the impact of incorrect estimates.
reverb_decay_ = reverb_decay_ = std::min(config_.ep_strength.default_len, reverb_decay_);
std::min(config_.param.ep_strength.default_len, reverb_decay_);
} }
reverb_decay_to_test_ = 0.9f; reverb_decay_to_test_ = 0.9f;
reverb_decay_candidate_residual_ = -1.f; reverb_decay_candidate_residual_ = -1.f;
@ -247,7 +244,7 @@ void AecState::UpdateReverb(
// For noisy impulse responses, assume a fixed tail length. // For noisy impulse responses, assume a fixed tail length.
if (tail_power > 0.0005f) { if (tail_power > 0.0005f) {
reverb_decay_ = config_.param.ep_strength.default_len; reverb_decay_ = config_.ep_strength.default_len;
} }
data_dumper_->DumpRaw("aec3_reverb_decay", reverb_decay_); data_dumper_->DumpRaw("aec3_reverb_decay", reverb_decay_);
data_dumper_->DumpRaw("aec3_tail_power", tail_power); data_dumper_->DumpRaw("aec3_tail_power", tail_power);

View File

@ -32,7 +32,7 @@ class ApmDataDumper;
// Handles the state and the conditions for the echo removal functionality. // Handles the state and the conditions for the echo removal functionality.
class AecState { class AecState {
public: public:
explicit AecState(const AudioProcessing::Config::EchoCanceller3& config); explicit AecState(const EchoCanceller3Config& config);
~AecState(); ~AecState();
// Returns whether the linear filter estimate is usable. // Returns whether the linear filter estimate is usable.
@ -163,7 +163,7 @@ class AecState {
float reverb_decay_candidate_ = 0.f; float reverb_decay_candidate_ = 0.f;
float reverb_decay_candidate_residual_ = -1.f; float reverb_decay_candidate_residual_ = -1.f;
EchoAudibility echo_audibility_; EchoAudibility echo_audibility_;
const AudioProcessing::Config::EchoCanceller3 config_; const EchoCanceller3Config config_;
float reverb_decay_; float reverb_decay_;
RTC_DISALLOW_COPY_AND_ASSIGN(AecState); RTC_DISALLOW_COPY_AND_ASSIGN(AecState);

View File

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

View File

@ -181,9 +181,8 @@ void BlockProcessorImpl::UpdateEchoLeakageStatus(bool leakage_detected) {
} // namespace } // namespace
BlockProcessor* BlockProcessor::Create( BlockProcessor* BlockProcessor::Create(const EchoCanceller3Config& config,
const AudioProcessing::Config::EchoCanceller3& config, int sample_rate_hz) {
int sample_rate_hz) {
std::unique_ptr<RenderDelayBuffer> render_buffer( std::unique_ptr<RenderDelayBuffer> render_buffer(
RenderDelayBuffer::Create(NumBandsForRate(sample_rate_hz))); RenderDelayBuffer::Create(NumBandsForRate(sample_rate_hz)));
std::unique_ptr<RenderDelayController> delay_controller( std::unique_ptr<RenderDelayController> delay_controller(
@ -195,7 +194,7 @@ BlockProcessor* BlockProcessor::Create(
} }
BlockProcessor* BlockProcessor::Create( BlockProcessor* BlockProcessor::Create(
const AudioProcessing::Config::EchoCanceller3& config, const EchoCanceller3Config& config,
int sample_rate_hz, int sample_rate_hz,
std::unique_ptr<RenderDelayBuffer> render_buffer) { std::unique_ptr<RenderDelayBuffer> render_buffer) {
std::unique_ptr<RenderDelayController> delay_controller( std::unique_ptr<RenderDelayController> delay_controller(
@ -207,7 +206,7 @@ BlockProcessor* BlockProcessor::Create(
} }
BlockProcessor* BlockProcessor::Create( BlockProcessor* BlockProcessor::Create(
const AudioProcessing::Config::EchoCanceller3& config, const EchoCanceller3Config& config,
int sample_rate_hz, int sample_rate_hz,
std::unique_ptr<RenderDelayBuffer> render_buffer, std::unique_ptr<RenderDelayBuffer> render_buffer,
std::unique_ptr<RenderDelayController> delay_controller, std::unique_ptr<RenderDelayController> delay_controller,

View File

@ -23,16 +23,15 @@ namespace webrtc {
// Class for performing echo cancellation on 64 sample blocks of audio data. // Class for performing echo cancellation on 64 sample blocks of audio data.
class BlockProcessor { class BlockProcessor {
public: public:
static BlockProcessor* Create( static BlockProcessor* Create(const EchoCanceller3Config& config,
const AudioProcessing::Config::EchoCanceller3& config, int sample_rate_hz);
int sample_rate_hz);
// Only used for testing purposes. // Only used for testing purposes.
static BlockProcessor* Create( static BlockProcessor* Create(
const AudioProcessing::Config::EchoCanceller3& config, const EchoCanceller3Config& config,
int sample_rate_hz, int sample_rate_hz,
std::unique_ptr<RenderDelayBuffer> render_buffer); std::unique_ptr<RenderDelayBuffer> render_buffer);
static BlockProcessor* Create( static BlockProcessor* Create(
const AudioProcessing::Config::EchoCanceller3& config, const EchoCanceller3Config& config,
int sample_rate_hz, int sample_rate_hz,
std::unique_ptr<RenderDelayBuffer> render_buffer, std::unique_ptr<RenderDelayBuffer> render_buffer,
std::unique_ptr<RenderDelayController> delay_controller, 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 // Verifies that the basic BlockProcessor functionality works and that the API
// methods are callable. // methods are callable.
void RunBasicSetupAndApiCallTest(int sample_rate_hz) { void RunBasicSetupAndApiCallTest(int sample_rate_hz) {
std::unique_ptr<BlockProcessor> block_processor(BlockProcessor::Create( std::unique_ptr<BlockProcessor> block_processor(
AudioProcessing::Config::EchoCanceller3(), sample_rate_hz)); BlockProcessor::Create(EchoCanceller3Config(), sample_rate_hz));
std::vector<std::vector<float>> block(NumBandsForRate(sample_rate_hz), std::vector<std::vector<float>> block(NumBandsForRate(sample_rate_hz),
std::vector<float>(kBlockSize, 0.f)); 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) #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
void RunRenderBlockSizeVerificationTest(int sample_rate_hz) { void RunRenderBlockSizeVerificationTest(int sample_rate_hz) {
std::unique_ptr<BlockProcessor> block_processor(BlockProcessor::Create( std::unique_ptr<BlockProcessor> block_processor(
AudioProcessing::Config::EchoCanceller3(), sample_rate_hz)); BlockProcessor::Create(EchoCanceller3Config(), sample_rate_hz));
std::vector<std::vector<float>> block( std::vector<std::vector<float>> block(
NumBandsForRate(sample_rate_hz), std::vector<float>(kBlockSize - 1, 0.f)); 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) { void RunCaptureBlockSizeVerificationTest(int sample_rate_hz) {
std::unique_ptr<BlockProcessor> block_processor(BlockProcessor::Create( std::unique_ptr<BlockProcessor> block_processor(
AudioProcessing::Config::EchoCanceller3(), sample_rate_hz)); BlockProcessor::Create(EchoCanceller3Config(), sample_rate_hz));
std::vector<std::vector<float>> block( std::vector<std::vector<float>> block(
NumBandsForRate(sample_rate_hz), std::vector<float>(kBlockSize - 1, 0.f)); 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 const size_t wrong_num_bands = NumBandsForRate(sample_rate_hz) < 3
? NumBandsForRate(sample_rate_hz) + 1 ? NumBandsForRate(sample_rate_hz) + 1
: 1; : 1;
std::unique_ptr<BlockProcessor> block_processor(BlockProcessor::Create( std::unique_ptr<BlockProcessor> block_processor(
AudioProcessing::Config::EchoCanceller3(), sample_rate_hz)); BlockProcessor::Create(EchoCanceller3Config(), sample_rate_hz));
std::vector<std::vector<float>> block(wrong_num_bands, std::vector<std::vector<float>> block(wrong_num_bands,
std::vector<float>(kBlockSize, 0.f)); 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 const size_t wrong_num_bands = NumBandsForRate(sample_rate_hz) < 3
? NumBandsForRate(sample_rate_hz) + 1 ? NumBandsForRate(sample_rate_hz) + 1
: 1; : 1;
std::unique_ptr<BlockProcessor> block_processor(BlockProcessor::Create( std::unique_ptr<BlockProcessor> block_processor(
AudioProcessing::Config::EchoCanceller3(), sample_rate_hz)); BlockProcessor::Create(EchoCanceller3Config(), sample_rate_hz));
std::vector<std::vector<float>> block(wrong_num_bands, std::vector<std::vector<float>> block(wrong_num_bands,
std::vector<float>(kBlockSize, 0.f)); std::vector<float>(kBlockSize, 0.f));
@ -125,9 +125,8 @@ TEST(BlockProcessor, DISABLED_DelayControllerIntegration) {
EXPECT_CALL(*render_delay_buffer_mock, Delay()) EXPECT_CALL(*render_delay_buffer_mock, Delay())
.Times(kNumBlocks + 1) .Times(kNumBlocks + 1)
.WillRepeatedly(Return(0)); .WillRepeatedly(Return(0));
std::unique_ptr<BlockProcessor> block_processor( std::unique_ptr<BlockProcessor> block_processor(BlockProcessor::Create(
BlockProcessor::Create(AudioProcessing::Config::EchoCanceller3(), rate, EchoCanceller3Config(), rate, std::move(render_delay_buffer_mock)));
std::move(render_delay_buffer_mock)));
std::vector<std::vector<float>> render_block( std::vector<std::vector<float>> render_block(
NumBandsForRate(rate), std::vector<float>(kBlockSize, 0.f)); NumBandsForRate(rate), std::vector<float>(kBlockSize, 0.f));
@ -181,8 +180,7 @@ TEST(BlockProcessor, DISABLED_SubmoduleIntegration) {
.Times(kNumBlocks); .Times(kNumBlocks);
std::unique_ptr<BlockProcessor> block_processor(BlockProcessor::Create( std::unique_ptr<BlockProcessor> block_processor(BlockProcessor::Create(
AudioProcessing::Config::EchoCanceller3(), rate, EchoCanceller3Config(), rate, std::move(render_delay_buffer_mock),
std::move(render_delay_buffer_mock),
std::move(render_delay_controller_mock), std::move(echo_remover_mock))); std::move(render_delay_controller_mock), std::move(echo_remover_mock)));
std::vector<std::vector<float>> render_block( std::vector<std::vector<float>> render_block(
@ -241,8 +239,7 @@ TEST(BlockProcessor, VerifyCaptureNumBandsCheck) {
// Verifiers that the verification for null ProcessCapture input works. // Verifiers that the verification for null ProcessCapture input works.
TEST(BlockProcessor, NullProcessCaptureParameter) { TEST(BlockProcessor, NullProcessCaptureParameter) {
EXPECT_DEATH(std::unique_ptr<BlockProcessor>( EXPECT_DEATH(std::unique_ptr<BlockProcessor>(
BlockProcessor::Create( BlockProcessor::Create(EchoCanceller3Config(), 8000))
AudioProcessing::Config::EchoCanceller3(), 8000))
->ProcessCapture(false, false, nullptr), ->ProcessCapture(false, false, nullptr),
""); "");
} }
@ -251,8 +248,8 @@ TEST(BlockProcessor, NullProcessCaptureParameter) {
// TODO(peah): Re-enable the test once the issue with memory leaks during DEATH // TODO(peah): Re-enable the test once the issue with memory leaks during DEATH
// tests on test bots has been fixed. // tests on test bots has been fixed.
TEST(BlockProcessor, DISABLED_WrongSampleRate) { TEST(BlockProcessor, DISABLED_WrongSampleRate) {
EXPECT_DEATH(std::unique_ptr<BlockProcessor>(BlockProcessor::Create( EXPECT_DEATH(std::unique_ptr<BlockProcessor>(
AudioProcessing::Config::EchoCanceller3(), 8001)), BlockProcessor::Create(EchoCanceller3Config(), 8001)),
""); "");
} }

View File

@ -35,19 +35,19 @@ float Power(const FftData& N) {
TEST(ComfortNoiseGenerator, NullLowerBandNoise) { TEST(ComfortNoiseGenerator, NullLowerBandNoise) {
std::array<float, kFftLengthBy2Plus1> N2; std::array<float, kFftLengthBy2Plus1> N2;
FftData noise; FftData noise;
EXPECT_DEATH(ComfortNoiseGenerator(DetectOptimization()) EXPECT_DEATH(
.Compute(AecState(AudioProcessing::Config::EchoCanceller3{}), ComfortNoiseGenerator(DetectOptimization())
N2, nullptr, &noise), .Compute(AecState(EchoCanceller3Config{}), N2, nullptr, &noise),
""); "");
} }
TEST(ComfortNoiseGenerator, NullUpperBandNoise) { TEST(ComfortNoiseGenerator, NullUpperBandNoise) {
std::array<float, kFftLengthBy2Plus1> N2; std::array<float, kFftLengthBy2Plus1> N2;
FftData noise; FftData noise;
EXPECT_DEATH(ComfortNoiseGenerator(DetectOptimization()) EXPECT_DEATH(
.Compute(AecState(AudioProcessing::Config::EchoCanceller3{}), ComfortNoiseGenerator(DetectOptimization())
N2, &noise, nullptr), .Compute(AecState(EchoCanceller3Config{}), N2, &noise, nullptr),
""); "");
} }
#endif #endif
@ -93,7 +93,7 @@ TEST(ComfortNoiseGenerator, TestOptimizations) {
TEST(ComfortNoiseGenerator, CorrectLevel) { TEST(ComfortNoiseGenerator, CorrectLevel) {
ComfortNoiseGenerator cng(DetectOptimization()); ComfortNoiseGenerator cng(DetectOptimization());
AecState aec_state(AudioProcessing::Config::EchoCanceller3{}); AecState aec_state(EchoCanceller3Config{});
std::array<float, kFftLengthBy2Plus1> N2; std::array<float, kFftLengthBy2Plus1> N2;
N2.fill(1000.f * 1000.f); N2.fill(1000.f * 1000.f);

View File

@ -200,10 +200,9 @@ void EchoCanceller3::RenderWriter::Insert(AudioBuffer* input) {
int EchoCanceller3::instance_count_ = 0; int EchoCanceller3::instance_count_ = 0;
EchoCanceller3::EchoCanceller3( EchoCanceller3::EchoCanceller3(const EchoCanceller3Config& config,
const AudioProcessing::Config::EchoCanceller3& config, int sample_rate_hz,
int sample_rate_hz, bool use_highpass_filter)
bool use_highpass_filter)
: EchoCanceller3(sample_rate_hz, : EchoCanceller3(sample_rate_hz,
use_highpass_filter, use_highpass_filter,
std::unique_ptr<BlockProcessor>( std::unique_ptr<BlockProcessor>(
@ -324,16 +323,7 @@ void EchoCanceller3::ProcessCapture(AudioBuffer* capture, bool level_change) {
LowestBandRate(sample_rate_hz_), 1); LowestBandRate(sample_rate_hz_), 1);
} }
std::string EchoCanceller3::ToString( bool EchoCanceller3::Validate(const EchoCanceller3Config& config) {
const AudioProcessing::Config::EchoCanceller3& config) {
std::stringstream ss;
ss << "{"
<< "enabled: " << (config.enabled ? "true" : "false") << "}";
return ss.str();
}
bool EchoCanceller3::Validate(
const AudioProcessing::Config::EchoCanceller3& config) {
return true; return true;
} }
@ -359,12 +349,13 @@ void EchoCanceller3::EmptyRenderQueue() {
} }
} }
EchoCanceller3Factory::EchoCanceller3Factory( EchoCanceller3Factory::EchoCanceller3Factory() {}
const AudioProcessing::Config::EchoCanceller3& config)
EchoCanceller3Factory::EchoCanceller3Factory(const EchoCanceller3Config& config)
: config_(config) { : config_(config) {
// Revert to default configuration if needed. // Revert to default configuration if needed.
if (!EchoCanceller3::Validate(config_)) { if (!EchoCanceller3::Validate(config_)) {
config_ = AudioProcessing::Config::EchoCanceller3(); config_ = EchoCanceller3Config();
} }
} }

View File

@ -63,7 +63,7 @@ class Aec3RenderQueueItemVerifier {
class EchoCanceller3 : public EchoControl { class EchoCanceller3 : public EchoControl {
public: public:
// Normal c-tor to use. // Normal c-tor to use.
EchoCanceller3(const AudioProcessing::Config::EchoCanceller3& config, EchoCanceller3(const EchoCanceller3Config& config,
int sample_rate_hz, int sample_rate_hz,
bool use_highpass_filter); bool use_highpass_filter);
// Testing c-tor that is used only for testing purposes. // Testing c-tor that is used only for testing purposes.
@ -90,10 +90,7 @@ class EchoCanceller3 : public EchoControl {
} }
// Validates a config. // Validates a config.
static bool Validate(const AudioProcessing::Config::EchoCanceller3& config); static bool Validate(const EchoCanceller3Config& config);
// Dumps a config to a string.
static std::string ToString(
const AudioProcessing::Config::EchoCanceller3& config);
private: private:
class RenderWriter; class RenderWriter;
@ -133,16 +130,6 @@ class EchoCanceller3 : public EchoControl {
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(EchoCanceller3); RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(EchoCanceller3);
}; };
class EchoCanceller3Factory : public EchoControlFactory {
public:
EchoCanceller3Factory();
EchoCanceller3Factory(const AudioProcessing::Config::EchoCanceller3& config);
std::unique_ptr<EchoControl> Create(int sample_rate_hz) override;
private:
AudioProcessing::Config::EchoCanceller3 config_;
};
} // namespace webrtc } // namespace webrtc
#endif // MODULES_AUDIO_PROCESSING_AEC3_ECHO_CANCELLER3_H_ #endif // MODULES_AUDIO_PROCESSING_AEC3_ECHO_CANCELLER3_H_

View File

@ -494,8 +494,7 @@ class EchoCanceller3Tester {
// This test verifies that a buffer overrun in the render swapqueue is // This test verifies that a buffer overrun in the render swapqueue is
// properly reported. // properly reported.
void RunRenderPipelineSwapQueueOverrunReturnValueTest() { void RunRenderPipelineSwapQueueOverrunReturnValueTest() {
EchoCanceller3 aec3(AudioProcessing::Config::EchoCanceller3(), EchoCanceller3 aec3(EchoCanceller3Config(), sample_rate_hz_, false);
sample_rate_hz_, false);
constexpr size_t kRenderTransferQueueSize = 30; constexpr size_t kRenderTransferQueueSize = 30;
for (size_t k = 0; k < 2; ++k) { for (size_t k = 0; k < 2; ++k) {
@ -524,8 +523,7 @@ class EchoCanceller3Tester {
// Set aec3_sample_rate_hz to be different from sample_rate_hz_ in such a // 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. // way that the number of bands for the rates are different.
const int aec3_sample_rate_hz = sample_rate_hz_ == 48000 ? 32000 : 48000; const int aec3_sample_rate_hz = sample_rate_hz_ == 48000 ? 32000 : 48000;
EchoCanceller3 aec3(AudioProcessing::Config::EchoCanceller3(), EchoCanceller3 aec3(EchoCanceller3Config(), aec3_sample_rate_hz, false);
aec3_sample_rate_hz, false);
PopulateInputFrame(frame_length_, 0, &render_buffer_.channels_f()[0][0], 0); PopulateInputFrame(frame_length_, 0, &render_buffer_.channels_f()[0][0], 0);
EXPECT_DEATH(aec3.AnalyzeRender(&render_buffer_), ""); EXPECT_DEATH(aec3.AnalyzeRender(&render_buffer_), "");
@ -538,8 +536,7 @@ class EchoCanceller3Tester {
// Set aec3_sample_rate_hz to be different from sample_rate_hz_ in such a // 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. // way that the number of bands for the rates are different.
const int aec3_sample_rate_hz = sample_rate_hz_ == 48000 ? 32000 : 48000; const int aec3_sample_rate_hz = sample_rate_hz_ == 48000 ? 32000 : 48000;
EchoCanceller3 aec3(AudioProcessing::Config::EchoCanceller3(), EchoCanceller3 aec3(EchoCanceller3Config(), aec3_sample_rate_hz, false);
aec3_sample_rate_hz, false);
PopulateInputFrame(frame_length_, num_bands_, 0, PopulateInputFrame(frame_length_, num_bands_, 0,
&capture_buffer_.split_bands_f(0)[0], 100); &capture_buffer_.split_bands_f(0)[0], 100);
EXPECT_DEATH(aec3.ProcessCapture(&capture_buffer_, false), ""); EXPECT_DEATH(aec3.ProcessCapture(&capture_buffer_, false), "");
@ -552,8 +549,7 @@ class EchoCanceller3Tester {
// Set aec3_sample_rate_hz to be different from sample_rate_hz_ in such a // Set aec3_sample_rate_hz to be different from sample_rate_hz_ in such a
// way that the band frame lengths are different. // way that the band frame lengths are different.
const int aec3_sample_rate_hz = sample_rate_hz_ == 8000 ? 16000 : 8000; const int aec3_sample_rate_hz = sample_rate_hz_ == 8000 ? 16000 : 8000;
EchoCanceller3 aec3(AudioProcessing::Config::EchoCanceller3(), EchoCanceller3 aec3(EchoCanceller3Config(), aec3_sample_rate_hz, false);
aec3_sample_rate_hz, false);
OptionalBandSplit(); OptionalBandSplit();
PopulateInputFrame(frame_length_, 0, &render_buffer_.channels_f()[0][0], 0); PopulateInputFrame(frame_length_, 0, &render_buffer_.channels_f()[0][0], 0);
@ -568,8 +564,7 @@ class EchoCanceller3Tester {
// Set aec3_sample_rate_hz to be different from sample_rate_hz_ in such a // Set aec3_sample_rate_hz to be different from sample_rate_hz_ in such a
// way that the band frame lengths are different. // way that the band frame lengths are different.
const int aec3_sample_rate_hz = sample_rate_hz_ == 8000 ? 16000 : 8000; const int aec3_sample_rate_hz = sample_rate_hz_ == 8000 ? 16000 : 8000;
EchoCanceller3 aec3(AudioProcessing::Config::EchoCanceller3(), EchoCanceller3 aec3(EchoCanceller3Config(), aec3_sample_rate_hz, false);
aec3_sample_rate_hz, false);
OptionalBandSplit(); OptionalBandSplit();
PopulateInputFrame(frame_length_, num_bands_, 0, PopulateInputFrame(frame_length_, num_bands_, 0,
@ -682,7 +677,7 @@ TEST(EchoCanceller3Messaging, EchoLeakage) {
} }
TEST(EchoCanceller3, ConfigValidation) { TEST(EchoCanceller3, ConfigValidation) {
AudioProcessing::Config::EchoCanceller3 config; EchoCanceller3Config config;
EXPECT_TRUE(EchoCanceller3::Validate(config)); EXPECT_TRUE(EchoCanceller3::Validate(config));
} }
@ -715,28 +710,25 @@ TEST(EchoCanceller3InputCheck, WrongCaptureFrameLengthCheckVerification) {
// Verifiers that the verification for null input to the render analysis api // Verifiers that the verification for null input to the render analysis api
// call works. // call works.
TEST(EchoCanceller3InputCheck, NullRenderAnalysisParameter) { TEST(EchoCanceller3InputCheck, NullRenderAnalysisParameter) {
EXPECT_DEATH( EXPECT_DEATH(EchoCanceller3(EchoCanceller3Config(), 8000, false)
EchoCanceller3(AudioProcessing::Config::EchoCanceller3(), 8000, false) .AnalyzeRender(nullptr),
.AnalyzeRender(nullptr), "");
"");
} }
// Verifiers that the verification for null input to the capture analysis api // Verifiers that the verification for null input to the capture analysis api
// call works. // call works.
TEST(EchoCanceller3InputCheck, NullCaptureAnalysisParameter) { TEST(EchoCanceller3InputCheck, NullCaptureAnalysisParameter) {
EXPECT_DEATH( EXPECT_DEATH(EchoCanceller3(EchoCanceller3Config(), 8000, false)
EchoCanceller3(AudioProcessing::Config::EchoCanceller3(), 8000, false) .AnalyzeCapture(nullptr),
.AnalyzeCapture(nullptr), "");
"");
} }
// Verifiers that the verification for null input to the capture processing api // Verifiers that the verification for null input to the capture processing api
// call works. // call works.
TEST(EchoCanceller3InputCheck, NullCaptureProcessingParameter) { TEST(EchoCanceller3InputCheck, NullCaptureProcessingParameter) {
EXPECT_DEATH( EXPECT_DEATH(EchoCanceller3(EchoCanceller3Config(), 8000, false)
EchoCanceller3(AudioProcessing::Config::EchoCanceller3(), 8000, false) .ProcessCapture(nullptr, false),
.ProcessCapture(nullptr, false), "");
"");
} }
// Verifies the check for correct sample rate. // Verifies the check for correct sample rate.
@ -744,9 +736,7 @@ TEST(EchoCanceller3InputCheck, NullCaptureProcessingParameter) {
// tests on test bots has been fixed. // tests on test bots has been fixed.
TEST(EchoCanceller3InputCheck, DISABLED_WrongSampleRate) { TEST(EchoCanceller3InputCheck, DISABLED_WrongSampleRate) {
ApmDataDumper data_dumper(0); ApmDataDumper data_dumper(0);
EXPECT_DEATH( EXPECT_DEATH(EchoCanceller3(EchoCanceller3Config(), 8001, false), "");
EchoCanceller3(AudioProcessing::Config::EchoCanceller3(), 8001, false),
"");
} }
#endif #endif

View File

@ -26,14 +26,14 @@ constexpr int kDownSamplingFactor = 4;
EchoPathDelayEstimator::EchoPathDelayEstimator( EchoPathDelayEstimator::EchoPathDelayEstimator(
ApmDataDumper* data_dumper, ApmDataDumper* data_dumper,
const AudioProcessing::Config::EchoCanceller3& config) const EchoCanceller3Config& config)
: data_dumper_(data_dumper), : data_dumper_(data_dumper),
matched_filter_(data_dumper_, matched_filter_(data_dumper_,
DetectOptimization(), DetectOptimization(),
kMatchedFilterWindowSizeSubBlocks, kMatchedFilterWindowSizeSubBlocks,
kNumMatchedFilters, kNumMatchedFilters,
kMatchedFilterAlignmentShiftSizeSubBlocks, kMatchedFilterAlignmentShiftSizeSubBlocks,
config.param.render_levels.poor_excitation_render_limit), config.render_levels.poor_excitation_render_limit),
matched_filter_lag_aggregator_(data_dumper_) { matched_filter_lag_aggregator_(data_dumper_) {
RTC_DCHECK(data_dumper); RTC_DCHECK(data_dumper);
} }

View File

@ -29,7 +29,7 @@ class ApmDataDumper;
class EchoPathDelayEstimator { class EchoPathDelayEstimator {
public: public:
EchoPathDelayEstimator(ApmDataDumper* data_dumper, EchoPathDelayEstimator(ApmDataDumper* data_dumper,
const AudioProcessing::Config::EchoCanceller3& config); const EchoCanceller3Config& config);
~EchoPathDelayEstimator(); ~EchoPathDelayEstimator();
// Resets the estimation. // Resets the estimation.

View File

@ -37,8 +37,7 @@ TEST(EchoPathDelayEstimator, BasicApiCalls) {
ApmDataDumper data_dumper(0); ApmDataDumper data_dumper(0);
std::unique_ptr<RenderDelayBuffer> render_delay_buffer( std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
RenderDelayBuffer::Create(3)); RenderDelayBuffer::Create(3));
EchoPathDelayEstimator estimator(&data_dumper, EchoPathDelayEstimator estimator(&data_dumper, EchoCanceller3Config());
AudioProcessing::Config::EchoCanceller3());
std::vector<std::vector<float>> render(3, std::vector<float>(kBlockSize)); std::vector<std::vector<float>> render(3, std::vector<float>(kBlockSize));
std::vector<float> capture(kBlockSize); std::vector<float> capture(kBlockSize);
for (size_t k = 0; k < 100; ++k) { for (size_t k = 0; k < 100; ++k) {
@ -60,8 +59,7 @@ TEST(EchoPathDelayEstimator, DelayEstimation) {
std::unique_ptr<RenderDelayBuffer> render_delay_buffer( std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
RenderDelayBuffer::Create(3)); RenderDelayBuffer::Create(3));
DelayBuffer<float> signal_delay_buffer(delay_samples); DelayBuffer<float> signal_delay_buffer(delay_samples);
EchoPathDelayEstimator estimator(&data_dumper, EchoPathDelayEstimator estimator(&data_dumper, EchoCanceller3Config());
AudioProcessing::Config::EchoCanceller3());
rtc::Optional<size_t> estimated_delay_samples; rtc::Optional<size_t> estimated_delay_samples;
for (size_t k = 0; k < (100 + delay_samples / kBlockSize); ++k) { for (size_t k = 0; k < (100 + delay_samples / kBlockSize); ++k) {
@ -93,8 +91,7 @@ TEST(EchoPathDelayEstimator, NoInitialDelayestimates) {
std::unique_ptr<RenderDelayBuffer> render_delay_buffer( std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
RenderDelayBuffer::Create(3)); RenderDelayBuffer::Create(3));
EchoPathDelayEstimator estimator(&data_dumper, EchoPathDelayEstimator estimator(&data_dumper, EchoCanceller3Config());
AudioProcessing::Config::EchoCanceller3());
for (size_t k = 0; k < 19; ++k) { for (size_t k = 0; k < 19; ++k) {
RandomizeSampleVector(&random_generator, render[0]); RandomizeSampleVector(&random_generator, render[0]);
std::copy(render[0].begin(), render[0].end(), capture.begin()); std::copy(render[0].begin(), render[0].end(), capture.begin());
@ -112,8 +109,7 @@ TEST(EchoPathDelayEstimator, NoDelayEstimatesForLowLevelRenderSignals) {
std::vector<std::vector<float>> render(3, std::vector<float>(kBlockSize)); std::vector<std::vector<float>> render(3, std::vector<float>(kBlockSize));
std::vector<float> capture(kBlockSize); std::vector<float> capture(kBlockSize);
ApmDataDumper data_dumper(0); ApmDataDumper data_dumper(0);
EchoPathDelayEstimator estimator(&data_dumper, EchoPathDelayEstimator estimator(&data_dumper, EchoCanceller3Config());
AudioProcessing::Config::EchoCanceller3());
std::unique_ptr<RenderDelayBuffer> render_delay_buffer( std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
RenderDelayBuffer::Create(3)); RenderDelayBuffer::Create(3));
for (size_t k = 0; k < 100; ++k) { for (size_t k = 0; k < 100; ++k) {
@ -136,8 +132,7 @@ TEST(EchoPathDelayEstimator, NoDelayEstimatesForUncorrelatedSignals) {
std::vector<std::vector<float>> render(3, std::vector<float>(kBlockSize)); std::vector<std::vector<float>> render(3, std::vector<float>(kBlockSize));
std::vector<float> capture(kBlockSize); std::vector<float> capture(kBlockSize);
ApmDataDumper data_dumper(0); ApmDataDumper data_dumper(0);
EchoPathDelayEstimator estimator(&data_dumper, EchoPathDelayEstimator estimator(&data_dumper, EchoCanceller3Config());
AudioProcessing::Config::EchoCanceller3());
std::unique_ptr<RenderDelayBuffer> render_delay_buffer( std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
RenderDelayBuffer::Create(3)); RenderDelayBuffer::Create(3));
for (size_t k = 0; k < 100; ++k) { for (size_t k = 0; k < 100; ++k) {
@ -157,8 +152,7 @@ TEST(EchoPathDelayEstimator, NoDelayEstimatesForUncorrelatedSignals) {
// tests on test bots has been fixed. // tests on test bots has been fixed.
TEST(EchoPathDelayEstimator, DISABLED_WrongRenderBlockSize) { TEST(EchoPathDelayEstimator, DISABLED_WrongRenderBlockSize) {
ApmDataDumper data_dumper(0); ApmDataDumper data_dumper(0);
EchoPathDelayEstimator estimator(&data_dumper, EchoPathDelayEstimator estimator(&data_dumper, EchoCanceller3Config());
AudioProcessing::Config::EchoCanceller3());
std::unique_ptr<RenderDelayBuffer> render_delay_buffer( std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
RenderDelayBuffer::Create(3)); RenderDelayBuffer::Create(3));
std::vector<float> capture(kBlockSize); std::vector<float> capture(kBlockSize);
@ -172,8 +166,7 @@ TEST(EchoPathDelayEstimator, DISABLED_WrongRenderBlockSize) {
// tests on test bots has been fixed. // tests on test bots has been fixed.
TEST(EchoPathDelayEstimator, WrongCaptureBlockSize) { TEST(EchoPathDelayEstimator, WrongCaptureBlockSize) {
ApmDataDumper data_dumper(0); ApmDataDumper data_dumper(0);
EchoPathDelayEstimator estimator(&data_dumper, EchoPathDelayEstimator estimator(&data_dumper, EchoCanceller3Config());
AudioProcessing::Config::EchoCanceller3());
std::unique_ptr<RenderDelayBuffer> render_delay_buffer( std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
RenderDelayBuffer::Create(3)); RenderDelayBuffer::Create(3));
std::vector<float> capture(std::vector<float>(kBlockSize - 1)); std::vector<float> capture(std::vector<float>(kBlockSize - 1));
@ -184,9 +177,7 @@ TEST(EchoPathDelayEstimator, WrongCaptureBlockSize) {
// Verifies the check for non-null data dumper. // Verifies the check for non-null data dumper.
TEST(EchoPathDelayEstimator, NullDataDumper) { TEST(EchoPathDelayEstimator, NullDataDumper) {
EXPECT_DEATH(EchoPathDelayEstimator( EXPECT_DEATH(EchoPathDelayEstimator(nullptr, EchoCanceller3Config()), "");
nullptr, AudioProcessing::Config::EchoCanceller3()),
"");
} }
#endif #endif

View File

@ -49,9 +49,8 @@ void LinearEchoPower(const FftData& E,
// Class for removing the echo from the capture signal. // Class for removing the echo from the capture signal.
class EchoRemoverImpl final : public EchoRemover { class EchoRemoverImpl final : public EchoRemover {
public: public:
explicit EchoRemoverImpl( explicit EchoRemoverImpl(const EchoCanceller3Config& config,
const AudioProcessing::Config::EchoCanceller3& config, int sample_rate_hz);
int sample_rate_hz);
~EchoRemoverImpl() override; ~EchoRemoverImpl() override;
// Removes the echo from a block of samples from the capture signal. The // Removes the echo from a block of samples from the capture signal. The
@ -71,7 +70,7 @@ class EchoRemoverImpl final : public EchoRemover {
private: private:
static int instance_count_; static int instance_count_;
const AudioProcessing::Config::EchoCanceller3 config_; const EchoCanceller3Config config_;
const Aec3Fft fft_; const Aec3Fft fft_;
std::unique_ptr<ApmDataDumper> data_dumper_; std::unique_ptr<ApmDataDumper> data_dumper_;
const Aec3Optimization optimization_; const Aec3Optimization optimization_;
@ -92,9 +91,8 @@ class EchoRemoverImpl final : public EchoRemover {
int EchoRemoverImpl::instance_count_ = 0; int EchoRemoverImpl::instance_count_ = 0;
EchoRemoverImpl::EchoRemoverImpl( EchoRemoverImpl::EchoRemoverImpl(const EchoCanceller3Config& config,
const AudioProcessing::Config::EchoCanceller3& config, int sample_rate_hz)
int sample_rate_hz)
: config_(config), : config_(config),
fft_(), fft_(),
data_dumper_( data_dumper_(
@ -242,9 +240,8 @@ void EchoRemoverImpl::ProcessCapture(
} // namespace } // namespace
EchoRemover* EchoRemover::Create( EchoRemover* EchoRemover::Create(const EchoCanceller3Config& config,
const AudioProcessing::Config::EchoCanceller3& config, int sample_rate_hz) {
int sample_rate_hz) {
return new EchoRemoverImpl(config, sample_rate_hz); return new EchoRemoverImpl(config, sample_rate_hz);
} }

View File

@ -23,9 +23,8 @@ namespace webrtc {
// Class for removing the echo from the capture signal. // Class for removing the echo from the capture signal.
class EchoRemover { class EchoRemover {
public: public:
static EchoRemover* Create( static EchoRemover* Create(const EchoCanceller3Config& config,
const AudioProcessing::Config::EchoCanceller3& config, int sample_rate_hz);
int sample_rate_hz);
virtual ~EchoRemover() = default; virtual ~EchoRemover() = default;
// Removes the echo from a block of samples from the capture signal. The // 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. // Verify the general functionality of EchoRemoverMetrics.
TEST(EchoRemoverMetrics, NormalUsage) { TEST(EchoRemoverMetrics, NormalUsage) {
EchoRemoverMetrics metrics; EchoRemoverMetrics metrics;
AecState aec_state(AudioProcessing::Config::EchoCanceller3{}); AecState aec_state(EchoCanceller3Config{});
std::array<float, kFftLengthBy2Plus1> comfort_noise_spectrum; std::array<float, kFftLengthBy2Plus1> comfort_noise_spectrum;
std::array<float, kFftLengthBy2Plus1> suppressor_gain; std::array<float, kFftLengthBy2Plus1> suppressor_gain;
comfort_noise_spectrum.fill(10.f); comfort_noise_spectrum.fill(10.f);

View File

@ -46,7 +46,7 @@ TEST(EchoRemover, BasicApiCalls) {
for (auto rate : {8000, 16000, 32000, 48000}) { for (auto rate : {8000, 16000, 32000, 48000}) {
SCOPED_TRACE(ProduceDebugText(rate)); SCOPED_TRACE(ProduceDebugText(rate));
std::unique_ptr<EchoRemover> remover( std::unique_ptr<EchoRemover> remover(
EchoRemover::Create(AudioProcessing::Config::EchoCanceller3(), rate)); EchoRemover::Create(EchoCanceller3Config(), rate));
std::unique_ptr<RenderDelayBuffer> render_buffer( std::unique_ptr<RenderDelayBuffer> render_buffer(
RenderDelayBuffer::Create(NumBandsForRate(rate))); RenderDelayBuffer::Create(NumBandsForRate(rate)));
@ -75,8 +75,8 @@ TEST(EchoRemover, BasicApiCalls) {
// TODO(peah): Re-enable the test once the issue with memory leaks during DEATH // TODO(peah): Re-enable the test once the issue with memory leaks during DEATH
// tests on test bots has been fixed. // tests on test bots has been fixed.
TEST(EchoRemover, DISABLED_WrongSampleRate) { TEST(EchoRemover, DISABLED_WrongSampleRate) {
EXPECT_DEATH(std::unique_ptr<EchoRemover>(EchoRemover::Create( EXPECT_DEATH(std::unique_ptr<EchoRemover>(
AudioProcessing::Config::EchoCanceller3(), 8001)), EchoRemover::Create(EchoCanceller3Config(), 8001)),
""); "");
} }
@ -85,7 +85,7 @@ TEST(EchoRemover, WrongCaptureBlockSize) {
for (auto rate : {8000, 16000, 32000, 48000}) { for (auto rate : {8000, 16000, 32000, 48000}) {
SCOPED_TRACE(ProduceDebugText(rate)); SCOPED_TRACE(ProduceDebugText(rate));
std::unique_ptr<EchoRemover> remover( std::unique_ptr<EchoRemover> remover(
EchoRemover::Create(AudioProcessing::Config::EchoCanceller3(), rate)); EchoRemover::Create(EchoCanceller3Config(), rate));
std::unique_ptr<RenderDelayBuffer> render_buffer( std::unique_ptr<RenderDelayBuffer> render_buffer(
RenderDelayBuffer::Create(NumBandsForRate(rate))); RenderDelayBuffer::Create(NumBandsForRate(rate)));
std::vector<std::vector<float>> capture( std::vector<std::vector<float>> capture(
@ -106,7 +106,7 @@ TEST(EchoRemover, DISABLED_WrongCaptureNumBands) {
for (auto rate : {16000, 32000, 48000}) { for (auto rate : {16000, 32000, 48000}) {
SCOPED_TRACE(ProduceDebugText(rate)); SCOPED_TRACE(ProduceDebugText(rate));
std::unique_ptr<EchoRemover> remover( std::unique_ptr<EchoRemover> remover(
EchoRemover::Create(AudioProcessing::Config::EchoCanceller3(), rate)); EchoRemover::Create(EchoCanceller3Config(), rate));
std::unique_ptr<RenderDelayBuffer> render_buffer( std::unique_ptr<RenderDelayBuffer> render_buffer(
RenderDelayBuffer::Create(NumBandsForRate(rate))); RenderDelayBuffer::Create(NumBandsForRate(rate)));
std::vector<std::vector<float>> capture( std::vector<std::vector<float>> capture(
@ -124,7 +124,7 @@ TEST(EchoRemover, DISABLED_WrongCaptureNumBands) {
// Verifies the check for non-null capture block. // Verifies the check for non-null capture block.
TEST(EchoRemover, NullCapture) { TEST(EchoRemover, NullCapture) {
std::unique_ptr<EchoRemover> remover( std::unique_ptr<EchoRemover> remover(
EchoRemover::Create(AudioProcessing::Config::EchoCanceller3(), 8000)); EchoRemover::Create(EchoCanceller3Config(), 8000));
std::unique_ptr<RenderDelayBuffer> render_buffer( std::unique_ptr<RenderDelayBuffer> render_buffer(
RenderDelayBuffer::Create(3)); RenderDelayBuffer::Create(3));
EchoPathVariability echo_path_variability(false, false); EchoPathVariability echo_path_variability(false, false);
@ -151,7 +151,7 @@ TEST(EchoRemover, BasicEchoRemoval) {
for (size_t delay_samples : {0, 64, 150, 200, 301}) { for (size_t delay_samples : {0, 64, 150, 200, 301}) {
SCOPED_TRACE(ProduceDebugText(rate, delay_samples)); SCOPED_TRACE(ProduceDebugText(rate, delay_samples));
std::unique_ptr<EchoRemover> remover( std::unique_ptr<EchoRemover> remover(
EchoRemover::Create(AudioProcessing::Config::EchoCanceller3(), rate)); EchoRemover::Create(EchoCanceller3Config(), rate));
std::unique_ptr<RenderDelayBuffer> render_buffer( std::unique_ptr<RenderDelayBuffer> render_buffer(
RenderDelayBuffer::Create(NumBandsForRate(rate))); RenderDelayBuffer::Create(NumBandsForRate(rate)));
std::vector<std::unique_ptr<DelayBuffer<float>>> delay_buffers(x.size()); 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); Random random_generator(42U);
std::vector<std::vector<float>> x(3, std::vector<float>(kBlockSize, 0.f)); std::vector<std::vector<float>> x(3, std::vector<float>(kBlockSize, 0.f));
std::vector<float> y(kBlockSize, 0.f); std::vector<float> y(kBlockSize, 0.f);
AecState aec_state(AudioProcessing::Config::EchoCanceller3{}); AecState aec_state(EchoCanceller3Config{});
RenderSignalAnalyzer render_signal_analyzer; RenderSignalAnalyzer render_signal_analyzer;
std::array<float, kFftLength> s_scratch; std::array<float, kFftLength> s_scratch;
std::array<float, kBlockSize> s; std::array<float, kBlockSize> s;

View File

@ -27,9 +27,8 @@ namespace {
class RenderDelayControllerImpl final : public RenderDelayController { class RenderDelayControllerImpl final : public RenderDelayController {
public: public:
RenderDelayControllerImpl( RenderDelayControllerImpl(const EchoCanceller3Config& config,
const AudioProcessing::Config::EchoCanceller3& config, int sample_rate_hz);
int sample_rate_hz);
~RenderDelayControllerImpl() override; ~RenderDelayControllerImpl() override;
void Reset() override; void Reset() override;
void SetDelay(size_t render_delay) override; void SetDelay(size_t render_delay) override;
@ -75,12 +74,12 @@ size_t ComputeNewBufferDelay(size_t current_delay,
int RenderDelayControllerImpl::instance_count_ = 0; int RenderDelayControllerImpl::instance_count_ = 0;
RenderDelayControllerImpl::RenderDelayControllerImpl( RenderDelayControllerImpl::RenderDelayControllerImpl(
const AudioProcessing::Config::EchoCanceller3& config, const EchoCanceller3Config& config,
int sample_rate_hz) int sample_rate_hz)
: data_dumper_( : data_dumper_(
new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))), new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))),
default_delay_( default_delay_(
std::max(config.param.delay.default_delay, kMinEchoPathDelayBlocks)), std::max(config.delay.default_delay, kMinEchoPathDelayBlocks)),
delay_(default_delay_), delay_(default_delay_),
delay_estimator_(data_dumper_.get(), config), delay_estimator_(data_dumper_.get(), config),
echo_path_delay_samples_(default_delay_ * kBlockSize), echo_path_delay_samples_(default_delay_ * kBlockSize),
@ -170,7 +169,7 @@ size_t RenderDelayControllerImpl::GetDelay(
} // namespace } // namespace
RenderDelayController* RenderDelayController::Create( RenderDelayController* RenderDelayController::Create(
const AudioProcessing::Config::EchoCanceller3& config, const EchoCanceller3Config& config,
int sample_rate_hz) { int sample_rate_hz) {
return new RenderDelayControllerImpl(config, sample_rate_hz); return new RenderDelayControllerImpl(config, sample_rate_hz);
} }

View File

@ -23,9 +23,8 @@ namespace webrtc {
// Class for aligning the render and capture signal using a RenderDelayBuffer. // Class for aligning the render and capture signal using a RenderDelayBuffer.
class RenderDelayController { class RenderDelayController {
public: public:
static RenderDelayController* Create( static RenderDelayController* Create(const EchoCanceller3Config& config,
const AudioProcessing::Config::EchoCanceller3& config, int sample_rate_hz);
int sample_rate_hz);
virtual ~RenderDelayController() = default; virtual ~RenderDelayController() = default;
// Resets the delay controller. // Resets the delay controller.

View File

@ -50,8 +50,7 @@ TEST(RenderDelayController, NoRenderSignal) {
std::unique_ptr<RenderDelayBuffer> delay_buffer( std::unique_ptr<RenderDelayBuffer> delay_buffer(
RenderDelayBuffer::Create(NumBandsForRate(rate))); RenderDelayBuffer::Create(NumBandsForRate(rate)));
std::unique_ptr<RenderDelayController> delay_controller( std::unique_ptr<RenderDelayController> delay_controller(
RenderDelayController::Create(AudioProcessing::Config::EchoCanceller3(), RenderDelayController::Create(EchoCanceller3Config(), rate));
rate));
for (size_t k = 0; k < 100; ++k) { for (size_t k = 0; k < 100; ++k) {
EXPECT_EQ(kMinEchoPathDelayBlocks, EXPECT_EQ(kMinEchoPathDelayBlocks,
delay_controller->GetDelay( delay_controller->GetDelay(
@ -70,8 +69,7 @@ TEST(RenderDelayController, BasicApiCalls) {
std::unique_ptr<RenderDelayBuffer> render_delay_buffer( std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
RenderDelayBuffer::Create(NumBandsForRate(rate))); RenderDelayBuffer::Create(NumBandsForRate(rate)));
std::unique_ptr<RenderDelayController> delay_controller( std::unique_ptr<RenderDelayController> delay_controller(
RenderDelayController::Create(AudioProcessing::Config::EchoCanceller3(), RenderDelayController::Create(EchoCanceller3Config(), rate));
rate));
for (size_t k = 0; k < 10; ++k) { for (size_t k = 0; k < 10; ++k) {
render_delay_buffer->Insert(render_block); render_delay_buffer->Insert(render_block);
render_delay_buffer->UpdateBuffers(); render_delay_buffer->UpdateBuffers();
@ -98,8 +96,7 @@ TEST(RenderDelayController, Alignment) {
std::unique_ptr<RenderDelayBuffer> render_delay_buffer( std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
RenderDelayBuffer::Create(NumBandsForRate(rate))); RenderDelayBuffer::Create(NumBandsForRate(rate)));
std::unique_ptr<RenderDelayController> delay_controller( std::unique_ptr<RenderDelayController> delay_controller(
RenderDelayController::Create( RenderDelayController::Create(EchoCanceller3Config(), rate));
AudioProcessing::Config::EchoCanceller3(), rate));
DelayBuffer<float> signal_delay_buffer(delay_samples); DelayBuffer<float> signal_delay_buffer(delay_samples);
for (size_t k = 0; k < (400 + delay_samples / kBlockSize); ++k) { for (size_t k = 0; k < (400 + delay_samples / kBlockSize); ++k) {
RandomizeSampleVector(&random_generator, render_block[0]); RandomizeSampleVector(&random_generator, render_block[0]);
@ -142,8 +139,7 @@ TEST(RenderDelayController, NonCausalAlignment) {
std::unique_ptr<RenderDelayBuffer> render_delay_buffer( std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
RenderDelayBuffer::Create(NumBandsForRate(rate))); RenderDelayBuffer::Create(NumBandsForRate(rate)));
std::unique_ptr<RenderDelayController> delay_controller( std::unique_ptr<RenderDelayController> delay_controller(
RenderDelayController::Create( RenderDelayController::Create(EchoCanceller3Config(), rate));
AudioProcessing::Config::EchoCanceller3(), rate));
DelayBuffer<float> signal_delay_buffer(-delay_samples); DelayBuffer<float> signal_delay_buffer(-delay_samples);
for (int k = 0; k < (400 - delay_samples / static_cast<int>(kBlockSize)); for (int k = 0; k < (400 - delay_samples / static_cast<int>(kBlockSize));
++k) { ++k) {
@ -179,8 +175,7 @@ TEST(RenderDelayController, AlignmentWithJitter) {
std::unique_ptr<RenderDelayBuffer> render_delay_buffer( std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
RenderDelayBuffer::Create(NumBandsForRate(rate))); RenderDelayBuffer::Create(NumBandsForRate(rate)));
std::unique_ptr<RenderDelayController> delay_controller( std::unique_ptr<RenderDelayController> delay_controller(
RenderDelayController::Create( RenderDelayController::Create(EchoCanceller3Config(), rate));
AudioProcessing::Config::EchoCanceller3(), rate));
DelayBuffer<float> signal_delay_buffer(delay_samples); DelayBuffer<float> signal_delay_buffer(delay_samples);
for (size_t j = 0; for (size_t j = 0;
j < j <
@ -229,8 +224,7 @@ TEST(RenderDelayController, InitialHeadroom) {
std::unique_ptr<RenderDelayBuffer> render_delay_buffer( std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
RenderDelayBuffer::Create(NumBandsForRate(rate))); RenderDelayBuffer::Create(NumBandsForRate(rate)));
std::unique_ptr<RenderDelayController> delay_controller( std::unique_ptr<RenderDelayController> delay_controller(
RenderDelayController::Create(AudioProcessing::Config::EchoCanceller3(), RenderDelayController::Create(EchoCanceller3Config(), rate));
rate));
EXPECT_FALSE(delay_controller->AlignmentHeadroomSamples()); EXPECT_FALSE(delay_controller->AlignmentHeadroomSamples());
} }
} }
@ -246,8 +240,7 @@ TEST(RenderDelayController, WrongCaptureSize) {
RenderDelayBuffer::Create(NumBandsForRate(rate))); RenderDelayBuffer::Create(NumBandsForRate(rate)));
EXPECT_DEATH( EXPECT_DEATH(
std::unique_ptr<RenderDelayController>( std::unique_ptr<RenderDelayController>(
RenderDelayController::Create( RenderDelayController::Create(EchoCanceller3Config(), rate))
AudioProcessing::Config::EchoCanceller3(), rate))
->GetDelay(render_delay_buffer->GetDownsampledRenderBuffer(), ->GetDelay(render_delay_buffer->GetDownsampledRenderBuffer(),
block), block),
""); "");
@ -263,8 +256,8 @@ TEST(RenderDelayController, DISABLED_WrongSampleRate) {
std::unique_ptr<RenderDelayBuffer> render_delay_buffer( std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
RenderDelayBuffer::Create(NumBandsForRate(rate))); RenderDelayBuffer::Create(NumBandsForRate(rate)));
EXPECT_DEATH( EXPECT_DEATH(
std::unique_ptr<RenderDelayController>(RenderDelayController::Create( std::unique_ptr<RenderDelayController>(
AudioProcessing::Config::EchoCanceller3(), rate)), RenderDelayController::Create(EchoCanceller3Config(), rate)),
""); "");
} }
} }

View File

@ -76,8 +76,7 @@ void RenderNoisePower(
} // namespace } // namespace
ResidualEchoEstimator::ResidualEchoEstimator( ResidualEchoEstimator::ResidualEchoEstimator(const EchoCanceller3Config& config)
const AudioProcessing::Config::EchoCanceller3& config)
: config_(config) { : config_(config) {
Reset(); Reset();
} }
@ -143,7 +142,7 @@ void ResidualEchoEstimator::Estimate(
NonLinearEstimate( NonLinearEstimate(
aec_state.SufficientFilterUpdates(), aec_state.SaturatedEcho(), aec_state.SufficientFilterUpdates(), aec_state.SaturatedEcho(),
config_.param.ep_strength.bounded_erl, aec_state.TransparentMode(), config_.ep_strength.bounded_erl, aec_state.TransparentMode(),
aec_state.InitialState(), X2, Y2, R2); aec_state.InitialState(), X2, Y2, R2);
if (aec_state.ExternalDelay() && aec_state.FilterDelay() && if (aec_state.ExternalDelay() && aec_state.FilterDelay() &&
@ -219,9 +218,9 @@ void ResidualEchoEstimator::NonLinearEstimate(
echo_path_gain_lf = echo_path_gain_mf = echo_path_gain_hf = 0.01f; echo_path_gain_lf = echo_path_gain_mf = echo_path_gain_hf = 0.01f;
} else { } else {
// In the initial state, use conservative gains. // In the initial state, use conservative gains.
echo_path_gain_lf = config_.param.ep_strength.lf; echo_path_gain_lf = config_.ep_strength.lf;
echo_path_gain_mf = config_.param.ep_strength.mf; echo_path_gain_mf = config_.ep_strength.mf;
echo_path_gain_hf = config_.param.ep_strength.hf; echo_path_gain_hf = config_.ep_strength.hf;
} }
// Compute preliminary residual echo. // Compute preliminary residual echo.

View File

@ -26,8 +26,7 @@ namespace webrtc {
class ResidualEchoEstimator { class ResidualEchoEstimator {
public: public:
explicit ResidualEchoEstimator( explicit ResidualEchoEstimator(const EchoCanceller3Config& config);
const AudioProcessing::Config::EchoCanceller3& config);
~ResidualEchoEstimator(); ~ResidualEchoEstimator();
void Estimate(const AecState& aec_state, void Estimate(const AecState& aec_state,
@ -74,7 +73,7 @@ class ResidualEchoEstimator {
S2_old_; S2_old_;
std::array<float, kFftLengthBy2Plus1> X2_noise_floor_; std::array<float, kFftLengthBy2Plus1> X2_noise_floor_;
std::array<int, kFftLengthBy2Plus1> X2_noise_floor_counter_; std::array<int, kFftLengthBy2Plus1> X2_noise_floor_counter_;
const AudioProcessing::Config::EchoCanceller3 config_; const EchoCanceller3Config config_;
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(ResidualEchoEstimator); RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(ResidualEchoEstimator);
}; };

View File

@ -23,13 +23,13 @@ namespace webrtc {
// Verifies that the check for non-null output residual echo power works. // Verifies that the check for non-null output residual echo power works.
TEST(ResidualEchoEstimator, NullResidualEchoPowerOutput) { TEST(ResidualEchoEstimator, NullResidualEchoPowerOutput) {
AecState aec_state(AudioProcessing::Config::EchoCanceller3{}); AecState aec_state(EchoCanceller3Config{});
RenderBuffer render_buffer(Aec3Optimization::kNone, 3, 10, RenderBuffer render_buffer(Aec3Optimization::kNone, 3, 10,
std::vector<size_t>(1, 10)); std::vector<size_t>(1, 10));
std::vector<std::array<float, kFftLengthBy2Plus1>> H2; std::vector<std::array<float, kFftLengthBy2Plus1>> H2;
std::array<float, kFftLengthBy2Plus1> S2_linear; std::array<float, kFftLengthBy2Plus1> S2_linear;
std::array<float, kFftLengthBy2Plus1> Y2; std::array<float, kFftLengthBy2Plus1> Y2;
EXPECT_DEATH(ResidualEchoEstimator(AudioProcessing::Config::EchoCanceller3{}) EXPECT_DEATH(ResidualEchoEstimator(EchoCanceller3Config{})
.Estimate(aec_state, render_buffer, S2_linear, Y2, nullptr), .Estimate(aec_state, render_buffer, S2_linear, Y2, nullptr),
""); "");
} }
@ -37,9 +37,9 @@ TEST(ResidualEchoEstimator, NullResidualEchoPowerOutput) {
#endif #endif
TEST(ResidualEchoEstimator, BasicTest) { TEST(ResidualEchoEstimator, BasicTest) {
ResidualEchoEstimator estimator(AudioProcessing::Config::EchoCanceller3{}); ResidualEchoEstimator estimator(EchoCanceller3Config{});
AudioProcessing::Config::EchoCanceller3 config; EchoCanceller3Config config;
config.param.ep_strength.default_len = 0.f; config.ep_strength.default_len = 0.f;
AecState aec_state(config); AecState aec_state(config);
RenderBuffer render_buffer(Aec3Optimization::kNone, 3, 10, RenderBuffer render_buffer(Aec3Optimization::kNone, 3, 10,
std::vector<size_t>(1, 10)); std::vector<size_t>(1, 10));

View File

@ -47,7 +47,7 @@ void RunFilterUpdateTest(int num_blocks_to_process,
Random random_generator(42U); Random random_generator(42U);
std::vector<std::vector<float>> x(3, std::vector<float>(kBlockSize, 0.f)); std::vector<std::vector<float>> x(3, std::vector<float>(kBlockSize, 0.f));
std::vector<float> y(kBlockSize, 0.f); std::vector<float> y(kBlockSize, 0.f);
AecState aec_state(AudioProcessing::Config::EchoCanceller3{}); AecState aec_state(EchoCanceller3Config{});
RenderSignalAnalyzer render_signal_analyzer; RenderSignalAnalyzer render_signal_analyzer;
std::array<float, kFftLength> s; std::array<float, kFftLength> s;
FftData 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> Y2;
std::array<float, kFftLengthBy2Plus1> E2_main; std::array<float, kFftLengthBy2Plus1> E2_main;
std::array<float, kFftLengthBy2Plus1> E2_shadow; std::array<float, kFftLengthBy2Plus1> E2_shadow;
AecState aec_state(AudioProcessing::Config::EchoCanceller3{}); AecState aec_state(EchoCanceller3Config{});
x_old.fill(0.f); x_old.fill(0.f);
Y2.fill(0.f); Y2.fill(0.f);
E2_main.fill(0.f); E2_main.fill(0.f);
@ -110,11 +110,9 @@ TEST(Subtractor, DISABLED_NullOutput) {
RenderSignalAnalyzer render_signal_analyzer; RenderSignalAnalyzer render_signal_analyzer;
std::vector<float> y(kBlockSize, 0.f); std::vector<float> y(kBlockSize, 0.f);
EXPECT_DEATH( EXPECT_DEATH(subtractor.Process(render_buffer, y, render_signal_analyzer,
subtractor.Process(render_buffer, y, render_signal_analyzer, AecState(EchoCanceller3Config{}), nullptr),
AecState(AudioProcessing::Config::EchoCanceller3{}), "");
nullptr),
"");
} }
// Verifies the check for the capture signal size. // Verifies the check for the capture signal size.
@ -127,11 +125,9 @@ TEST(Subtractor, WrongCaptureSize) {
std::vector<float> y(kBlockSize - 1, 0.f); std::vector<float> y(kBlockSize - 1, 0.f);
SubtractorOutput output; SubtractorOutput output;
EXPECT_DEATH( EXPECT_DEATH(subtractor.Process(render_buffer, y, render_signal_analyzer,
subtractor.Process(render_buffer, y, render_signal_analyzer, AecState(EchoCanceller3Config{}), &output),
AecState(AudioProcessing::Config::EchoCanceller3{}), "");
&output),
"");
} }
#endif #endif

View File

@ -109,7 +109,7 @@ float UpperBandsGain(
// Limits the gain increase. // Limits the gain increase.
void UpdateMaxGainIncrease( void UpdateMaxGainIncrease(
const AudioProcessing::Config::EchoCanceller3& config, const EchoCanceller3Config& config,
size_t no_saturation_counter, size_t no_saturation_counter,
bool low_noise_render, bool low_noise_render,
bool linear_echo_estimate, bool linear_echo_estimate,
@ -125,7 +125,7 @@ void UpdateMaxGainIncrease(
float min_increasing; float min_increasing;
float min_decreasing; float min_decreasing;
auto& param = config.param.gain_updates; auto& param = config.gain_updates;
if (!linear_echo_estimate) { if (!linear_echo_estimate) {
max_increasing = param.nonlinear.max_inc; max_increasing = param.nonlinear.max_inc;
max_decreasing = param.nonlinear.max_dec; max_decreasing = param.nonlinear.max_dec;
@ -173,7 +173,7 @@ void UpdateMaxGainIncrease(
// Computes the gain to reduce the echo to a non audible level. // Computes the gain to reduce the echo to a non audible level.
void GainToNoAudibleEcho( void GainToNoAudibleEcho(
const AudioProcessing::Config::EchoCanceller3& config, const EchoCanceller3Config& config,
bool low_noise_render, bool low_noise_render,
bool saturated_echo, bool saturated_echo,
bool linear_echo_estimate, bool linear_echo_estimate,
@ -186,20 +186,20 @@ void GainToNoAudibleEcho(
std::array<float, kFftLengthBy2Plus1>* gain) { std::array<float, kFftLengthBy2Plus1>* gain) {
float nearend_masking_margin = 0.f; float nearend_masking_margin = 0.f;
if (linear_echo_estimate) { if (linear_echo_estimate) {
nearend_masking_margin = low_noise_render nearend_masking_margin =
? config.param.gain_mask.m9 low_noise_render
: (saturated_echo ? config.param.gain_mask.m2 ? config.gain_mask.m9
: config.param.gain_mask.m3); : (saturated_echo ? config.gain_mask.m2 : config.gain_mask.m3);
} else { } else {
nearend_masking_margin = config.param.gain_mask.m7; nearend_masking_margin = config.gain_mask.m7;
} }
RTC_DCHECK_LE(0.f, nearend_masking_margin); RTC_DCHECK_LE(0.f, nearend_masking_margin);
RTC_DCHECK_GT(1.f, nearend_masking_margin); RTC_DCHECK_GT(1.f, nearend_masking_margin);
const float one_by_one_minus_nearend_masking_margin = const float one_by_one_minus_nearend_masking_margin =
1.f / (1.0f - nearend_masking_margin); 1.f / (1.0f - nearend_masking_margin);
const float masker_margin = linear_echo_estimate ? config.param.gain_mask.m1 const float masker_margin =
: config.param.gain_mask.m8; linear_echo_estimate ? config.gain_mask.m1 : config.gain_mask.m8;
for (size_t k = 0; k < gain->size(); ++k) { for (size_t k = 0; k < gain->size(); ++k) {
const float unity_gain_masker = std::max(nearend[k], masker[k]); const float unity_gain_masker = std::max(nearend[k], masker[k]);
@ -223,7 +223,7 @@ void GainToNoAudibleEcho(
constexpr size_t kUpperAccurateBandPlus1 = 29; constexpr size_t kUpperAccurateBandPlus1 = 29;
// Computes the signal output power that masks the echo signal. // Computes the signal output power that masks the echo signal.
void MaskingPower(const AudioProcessing::Config::EchoCanceller3& config, void MaskingPower(const EchoCanceller3Config& config,
const std::array<float, kFftLengthBy2Plus1>& nearend, const std::array<float, kFftLengthBy2Plus1>& nearend,
const std::array<float, kFftLengthBy2Plus1>& comfort_noise, const std::array<float, kFftLengthBy2Plus1>& comfort_noise,
const std::array<float, kFftLengthBy2Plus1>& last_masker, const std::array<float, kFftLengthBy2Plus1>& last_masker,
@ -236,19 +236,18 @@ void MaskingPower(const AudioProcessing::Config::EchoCanceller3& config,
max_nearend_after_gain = max_nearend_after_gain =
std::max(max_nearend_after_gain, nearend_after_gain); std::max(max_nearend_after_gain, nearend_after_gain);
side_band_masker[k] = nearend_after_gain + comfort_noise[k]; side_band_masker[k] = nearend_after_gain + comfort_noise[k];
(*masker)[k] = (*masker)[k] = comfort_noise[k] + config.gain_mask.m4 * last_masker[k];
comfort_noise[k] + config.param.gain_mask.m4 * last_masker[k];
} }
// Apply masking only between lower frequency bands. // Apply masking only between lower frequency bands.
RTC_DCHECK_LT(kUpperAccurateBandPlus1, gain.size()); RTC_DCHECK_LT(kUpperAccurateBandPlus1, gain.size());
for (size_t k = 1; k < kUpperAccurateBandPlus1; ++k) { for (size_t k = 1; k < kUpperAccurateBandPlus1; ++k) {
(*masker)[k] += config.param.gain_mask.m5 * (*masker)[k] += config.gain_mask.m5 *
(side_band_masker[k - 1] + side_band_masker[k + 1]); (side_band_masker[k - 1] + side_band_masker[k + 1]);
} }
// Add full-band masking as a minimum value for the masker. // Add full-band masking as a minimum value for the masker.
const float min_masker = max_nearend_after_gain * config.param.gain_mask.m6; const float min_masker = max_nearend_after_gain * config.gain_mask.m6;
std::for_each(masker->begin(), masker->end(), std::for_each(masker->begin(), masker->end(),
[min_masker](float& a) { a = std::max(a, min_masker); }); [min_masker](float& a) { a = std::max(a, min_masker); });
} }
@ -295,8 +294,8 @@ void SuppressionGain::LowerBandGain(
// above the zero sample values. // above the zero sample values.
std::array<float, kFftLengthBy2Plus1> min_gain; std::array<float, kFftLengthBy2Plus1> min_gain;
const float min_echo_power = const float min_echo_power =
low_noise_render ? config_.param.echo_audibility.low_render_limit low_noise_render ? config_.echo_audibility.low_render_limit
: config_.param.echo_audibility.normal_render_limit; : config_.echo_audibility.normal_render_limit;
if (no_saturation_counter_ > 10) { if (no_saturation_counter_ > 10) {
for (size_t k = 0; k < nearend.size(); ++k) { for (size_t k = 0; k < nearend.size(); ++k) {
const float denom = std::min(nearend[k], echo[k]); const float denom = std::min(nearend[k], echo[k]);
@ -311,10 +310,9 @@ void SuppressionGain::LowerBandGain(
// gain. // gain.
std::array<float, kFftLengthBy2Plus1> max_gain; std::array<float, kFftLengthBy2Plus1> max_gain;
for (size_t k = 0; k < gain->size(); ++k) { for (size_t k = 0; k < gain->size(); ++k) {
max_gain[k] = max_gain[k] = std::min(std::max(last_gain_[k] * gain_increase_[k],
std::min(std::max(last_gain_[k] * gain_increase_[k], config_.gain_updates.floor_first_increase),
config_.param.gain_updates.floor_first_increase), 1.f);
1.f);
} }
// Iteratively compute the gain required to attenuate the echo to a non // Iteratively compute the gain required to attenuate the echo to a non
@ -354,9 +352,8 @@ void SuppressionGain::LowerBandGain(
aec3::VectorMath(optimization_).Sqrt(*gain); aec3::VectorMath(optimization_).Sqrt(*gain);
} }
SuppressionGain::SuppressionGain( SuppressionGain::SuppressionGain(const EchoCanceller3Config& config,
const AudioProcessing::Config::EchoCanceller3& config, Aec3Optimization optimization)
Aec3Optimization optimization)
: optimization_(optimization), config_(config) { : optimization_(optimization), config_(config) {
last_gain_.fill(1.f); last_gain_.fill(1.f);
last_masker_.fill(0.f); last_masker_.fill(0.f);

View File

@ -23,7 +23,7 @@ namespace webrtc {
class SuppressionGain { class SuppressionGain {
public: public:
SuppressionGain(const AudioProcessing::Config::EchoCanceller3& config, SuppressionGain(const EchoCanceller3Config& config,
Aec3Optimization optimization); Aec3Optimization optimization);
void GetGain(const std::array<float, kFftLengthBy2Plus1>& nearend, void GetGain(const std::array<float, kFftLengthBy2Plus1>& nearend,
const std::array<float, kFftLengthBy2Plus1>& echo, const std::array<float, kFftLengthBy2Plus1>& echo,
@ -62,7 +62,7 @@ class SuppressionGain {
LowNoiseRenderDetector low_render_detector_; LowNoiseRenderDetector low_render_detector_;
size_t no_saturation_counter_ = 0; size_t no_saturation_counter_ = 0;
const AudioProcessing::Config::EchoCanceller3 config_; const EchoCanceller3Config config_;
RTC_DISALLOW_COPY_AND_ASSIGN(SuppressionGain); RTC_DISALLOW_COPY_AND_ASSIGN(SuppressionGain);
}; };

View File

@ -29,8 +29,7 @@ TEST(SuppressionGain, NullOutputGains) {
R2.fill(0.f); R2.fill(0.f);
N2.fill(0.f); N2.fill(0.f);
float high_bands_gain; float high_bands_gain;
EXPECT_DEATH(SuppressionGain(AudioProcessing::Config::EchoCanceller3{}, EXPECT_DEATH(SuppressionGain(EchoCanceller3Config{}, DetectOptimization())
DetectOptimization())
.GetGain(E2, R2, N2, RenderSignalAnalyzer(), false, .GetGain(E2, R2, N2, RenderSignalAnalyzer(), false,
std::vector<std::vector<float>>( std::vector<std::vector<float>>(
3, std::vector<float>(kBlockSize, 0.f)), 3, std::vector<float>(kBlockSize, 0.f)),
@ -42,7 +41,7 @@ TEST(SuppressionGain, NullOutputGains) {
// Does a sanity check that the gains are correctly computed. // Does a sanity check that the gains are correctly computed.
TEST(SuppressionGain, BasicGainComputation) { TEST(SuppressionGain, BasicGainComputation) {
SuppressionGain suppression_gain(AudioProcessing::Config::EchoCanceller3(), SuppressionGain suppression_gain(EchoCanceller3Config(),
DetectOptimization()); DetectOptimization());
RenderSignalAnalyzer analyzer; RenderSignalAnalyzer analyzer;
float high_bands_gain; float high_bands_gain;

View File

@ -603,7 +603,7 @@ int AudioProcessingImpl::InitializeLocked(const ProcessingConfig& config) {
StreamConfig(capture_processing_rate); StreamConfig(capture_processing_rate);
int render_processing_rate; int render_processing_rate;
if (!config_.echo_canceller3.enabled) { if (!capture_nonlocked_.echo_controller_enabled) {
render_processing_rate = FindNativeProcessRateToUse( render_processing_rate = FindNativeProcessRateToUse(
std::min(formats_.api_format.reverse_input_stream().sample_rate_hz(), std::min(formats_.api_format.reverse_input_stream().sample_rate_hz(),
formats_.api_format.reverse_output_stream().sample_rate_hz()), formats_.api_format.reverse_output_stream().sample_rate_hz()),
@ -616,7 +616,7 @@ int AudioProcessingImpl::InitializeLocked(const ProcessingConfig& config) {
// TODO(aluebs): Remove this restriction once we figure out why the 3-band // TODO(aluebs): Remove this restriction once we figure out why the 3-band
// splitting filter degrades the AEC performance. // splitting filter degrades the AEC performance.
if (render_processing_rate > kSampleRate32kHz && if (render_processing_rate > kSampleRate32kHz &&
!config_.echo_canceller3.enabled) { !capture_nonlocked_.echo_controller_enabled) {
render_processing_rate = submodule_states_.RenderMultiBandProcessingActive() render_processing_rate = submodule_states_.RenderMultiBandProcessingActive()
? kSampleRate32kHz ? kSampleRate32kHz
: kSampleRate16kHz; : kSampleRate16kHz;
@ -692,12 +692,13 @@ void AudioProcessingImpl::ApplyConfig(const AudioProcessing::Config& config) {
LOG(LS_INFO) << "Highpass filter activated: " LOG(LS_INFO) << "Highpass filter activated: "
<< config_.high_pass_filter.enabled; << config_.high_pass_filter.enabled;
// Inject EchoCanceller3 if requested. // Deprecated way of activating AEC3.
// TODO(gustaf): Remove when possible.
if (config.echo_canceller3.enabled && !echo_control_factory_) { if (config.echo_canceller3.enabled && !echo_control_factory_) {
capture_nonlocked_.echo_controller_enabled = capture_nonlocked_.echo_controller_enabled =
config_.echo_canceller3.enabled; config_.echo_canceller3.enabled;
echo_control_factory_ = std::unique_ptr<EchoControlFactory>( echo_control_factory_ =
new EchoCanceller3Factory(config.echo_canceller3)); std::unique_ptr<EchoControlFactory>(new EchoCanceller3Factory());
InitializeEchoController(); InitializeEchoController();
LOG(LS_INFO) << "Echo canceller 3 activated: " LOG(LS_INFO) << "Echo canceller 3 activated: "
<< capture_nonlocked_.echo_controller_enabled; << capture_nonlocked_.echo_controller_enabled;

View File

@ -267,71 +267,9 @@ class AudioProcessing : public rtc::RefCountInterface {
bool enabled = false; bool enabled = false;
} high_pass_filter; } high_pass_filter;
// Enables the next generation AEC functionality. This feature replaces the // Deprecated way of activating AEC3.
// standard methods for echo removal in the AEC. // TODO(gustaf): Remove when possible.
// The functionality is not yet activated in the code and turning this on
// does not yet have the desired behavior.
struct EchoCanceller3 { struct EchoCanceller3 {
struct Param {
struct Delay {
size_t default_delay = 5;
} delay;
struct Erle {
float min = 1.f;
float max_l = 8.f;
float max_h = 1.5f;
} erle;
struct EpStrength {
float lf = 10.f;
float mf = 10.f;
float hf = 10.f;
float default_len = 0.f;
bool echo_can_saturate = true;
bool bounded_erl = false;
} ep_strength;
struct Mask {
float m1 = 0.01f;
float m2 = 0.0001f;
float m3 = 0.01f;
float m4 = 0.1f;
float m5 = 0.3f;
float m6 = 0.0001f;
float m7 = 0.01f;
float m8 = 0.0001f;
float m9 = 0.1f;
} gain_mask;
struct EchoAudibility {
float low_render_limit = 4 * 64.f;
float normal_render_limit = 64.f;
} echo_audibility;
struct RenderLevels {
float active_render_limit = 100.f;
float poor_excitation_render_limit = 150.f;
} render_levels;
struct GainUpdates {
struct GainChanges {
float max_inc;
float max_dec;
float rate_inc;
float rate_dec;
float min_inc;
float min_dec;
};
GainChanges low_noise = {3.f, 3.f, 1.5f, 1.5f, 1.5f, 1.5f};
GainChanges normal = {2.f, 2.f, 1.5f, 1.5f, 1.2f, 1.2f};
GainChanges saturation = {1.2f, 1.2f, 1.5f, 1.5f, 1.f, 1.f};
GainChanges nonlinear = {1.5f, 1.5f, 1.2f, 1.2f, 1.1f, 1.1f};
float floor_first_increase = 0.0001f;
} gain_updates;
} param;
bool enabled = false; bool enabled = false;
} echo_canceller3; } echo_canceller3;
@ -1194,6 +1132,78 @@ class VoiceDetection {
protected: protected:
virtual ~VoiceDetection() {} virtual ~VoiceDetection() {}
}; };
// Configuration struct for EchoCanceller3
struct EchoCanceller3Config {
struct Delay {
size_t default_delay = 5;
} delay;
struct Erle {
float min = 1.f;
float max_l = 8.f;
float max_h = 1.5f;
} erle;
struct EpStrength {
float lf = 10.f;
float mf = 10.f;
float hf = 10.f;
float default_len = 0.f;
bool echo_can_saturate = true;
bool bounded_erl = false;
} ep_strength;
struct Mask {
float m1 = 0.01f;
float m2 = 0.0001f;
float m3 = 0.01f;
float m4 = 0.1f;
float m5 = 0.3f;
float m6 = 0.0001f;
float m7 = 0.01f;
float m8 = 0.0001f;
float m9 = 0.1f;
} gain_mask;
struct EchoAudibility {
float low_render_limit = 4 * 64.f;
float normal_render_limit = 64.f;
} echo_audibility;
struct RenderLevels {
float active_render_limit = 100.f;
float poor_excitation_render_limit = 150.f;
} render_levels;
struct GainUpdates {
struct GainChanges {
float max_inc;
float max_dec;
float rate_inc;
float rate_dec;
float min_inc;
float min_dec;
};
GainChanges low_noise = {3.f, 3.f, 1.5f, 1.5f, 1.5f, 1.5f};
GainChanges normal = {2.f, 2.f, 1.5f, 1.5f, 1.2f, 1.2f};
GainChanges saturation = {1.2f, 1.2f, 1.5f, 1.5f, 1.f, 1.f};
GainChanges nonlinear = {1.5f, 1.5f, 1.2f, 1.2f, 1.1f, 1.1f};
float floor_first_increase = 0.0001f;
} gain_updates;
};
class EchoCanceller3Factory : public EchoControlFactory {
public:
EchoCanceller3Factory();
EchoCanceller3Factory(const EchoCanceller3Config& config);
std::unique_ptr<EchoControl> Create(int sample_rate_hz) override;
private:
EchoCanceller3Config config_;
};
} // namespace webrtc } // namespace webrtc
#endif // MODULES_AUDIO_PROCESSING_INCLUDE_AUDIO_PROCESSING_H_ #endif // MODULES_AUDIO_PROCESSING_INCLUDE_AUDIO_PROCESSING_H_

View File

@ -473,10 +473,6 @@ void AecDumpBasedSimulator::HandleMessage(
new RefinedAdaptiveFilter(*settings_.use_refined_adaptive_filter)); new RefinedAdaptiveFilter(*settings_.use_refined_adaptive_filter));
} }
if (settings_.use_aec3) {
apm_config.echo_canceller3.enabled = *settings_.use_aec3;
}
if (settings_.use_lc) { if (settings_.use_lc) {
apm_config.level_controller.enabled = *settings_.use_lc; apm_config.level_controller.enabled = *settings_.use_lc;
} }

View File

@ -306,6 +306,7 @@ void AudioProcessingSimulator::DestroyAudioProcessor() {
void AudioProcessingSimulator::CreateAudioProcessor() { void AudioProcessingSimulator::CreateAudioProcessor() {
Config config; Config config;
AudioProcessing::Config apm_config; AudioProcessing::Config apm_config;
std::unique_ptr<EchoControlFactory> echo_control_factory;
if (settings_.use_bf && *settings_.use_bf) { if (settings_.use_bf && *settings_.use_bf) {
config.Set<Beamforming>(new Beamforming( config.Set<Beamforming>(new Beamforming(
true, ParseArrayGeometry(*settings_.microphone_positions), true, ParseArrayGeometry(*settings_.microphone_positions),
@ -318,13 +319,13 @@ void AudioProcessingSimulator::CreateAudioProcessor() {
if (settings_.use_ie) { if (settings_.use_ie) {
config.Set<Intelligibility>(new Intelligibility(*settings_.use_ie)); config.Set<Intelligibility>(new Intelligibility(*settings_.use_ie));
} }
if (settings_.use_aec3) {
apm_config.echo_canceller3.enabled = *settings_.use_aec3;
}
if (settings_.use_agc2) { if (settings_.use_agc2) {
apm_config.gain_controller2.enabled = *settings_.use_agc2; apm_config.gain_controller2.enabled = *settings_.use_agc2;
apm_config.gain_controller2.fixed_gain_db = settings_.agc2_fixed_gain_db; apm_config.gain_controller2.fixed_gain_db = settings_.agc2_fixed_gain_db;
} }
if (settings_.use_aec3 && *settings_.use_aec3) {
echo_control_factory.reset(new EchoCanceller3Factory());
}
if (settings_.use_lc) { if (settings_.use_lc) {
apm_config.level_controller.enabled = *settings_.use_lc; apm_config.level_controller.enabled = *settings_.use_lc;
} }
@ -346,7 +347,8 @@ void AudioProcessingSimulator::CreateAudioProcessor() {
apm_config.residual_echo_detector.enabled = *settings_.use_ed; apm_config.residual_echo_detector.enabled = *settings_.use_ed;
} }
ap_.reset(AudioProcessing::Create(config)); ap_.reset(AudioProcessing::Create(config, nullptr,
std::move(echo_control_factory), nullptr));
RTC_CHECK(ap_); RTC_CHECK(ap_);
ap_->ApplyConfig(apm_config); ap_->ApplyConfig(apm_config);

View File

@ -46,9 +46,14 @@ class DebugDumpGenerator {
int reverse_rate_hz, int reverse_rate_hz,
int reverse_channels, int reverse_channels,
const Config& config, const Config& config,
const std::string& dump_file_name); const std::string& dump_file_name,
bool enable_aec3);
// Constructor that uses default input files. // Constructor that uses default input files.
explicit DebugDumpGenerator(const Config& config,
const AudioProcessing::Config& apm_config,
bool enable_aec3);
explicit DebugDumpGenerator(const Config& config, explicit DebugDumpGenerator(const Config& config,
const AudioProcessing::Config& apm_config); const AudioProcessing::Config& apm_config);
@ -118,7 +123,8 @@ DebugDumpGenerator::DebugDumpGenerator(const std::string& input_file_name,
int reverse_rate_hz, int reverse_rate_hz,
int reverse_channels, int reverse_channels,
const Config& config, const Config& config,
const std::string& dump_file_name) const std::string& dump_file_name,
bool enable_aec3)
: input_config_(input_rate_hz, input_channels), : input_config_(input_rate_hz, input_channels),
reverse_config_(reverse_rate_hz, reverse_channels), reverse_config_(reverse_rate_hz, reverse_channels),
output_config_(input_rate_hz, input_channels), output_config_(input_rate_hz, input_channels),
@ -133,12 +139,19 @@ DebugDumpGenerator::DebugDumpGenerator(const std::string& input_file_name,
output_(new ChannelBuffer<float>(output_config_.num_frames(), output_(new ChannelBuffer<float>(output_config_.num_frames(),
output_config_.num_channels())), output_config_.num_channels())),
worker_queue_("debug_dump_generator_worker_queue"), worker_queue_("debug_dump_generator_worker_queue"),
apm_(AudioProcessing::Create(config)), apm_(AudioProcessing::Create(
config,
nullptr,
(enable_aec3 ? std::unique_ptr<EchoControlFactory>(
new EchoCanceller3Factory())
: nullptr),
nullptr)),
dump_file_name_(dump_file_name) {} dump_file_name_(dump_file_name) {}
DebugDumpGenerator::DebugDumpGenerator( DebugDumpGenerator::DebugDumpGenerator(
const Config& config, const Config& config,
const AudioProcessing::Config& apm_config) const AudioProcessing::Config& apm_config,
bool enable_aec3)
: DebugDumpGenerator(ResourcePath("near32_stereo", "pcm"), : DebugDumpGenerator(ResourcePath("near32_stereo", "pcm"),
32000, 32000,
2, 2,
@ -146,7 +159,15 @@ DebugDumpGenerator::DebugDumpGenerator(
32000, 32000,
2, 2,
config, config,
TempFilename(OutputPath(), "debug_aec")) { TempFilename(OutputPath(), "debug_aec"),
enable_aec3) {
apm_->ApplyConfig(apm_config);
}
DebugDumpGenerator::DebugDumpGenerator(
const Config& config,
const AudioProcessing::Config& apm_config)
: DebugDumpGenerator(config, apm_config, false) {
apm_->ApplyConfig(apm_config); apm_->ApplyConfig(apm_config);
} }
@ -384,8 +405,8 @@ TEST_F(DebugDumpTest, VerifyCombinedExperimentalStringInclusive) {
config.Set<RefinedAdaptiveFilter>(new RefinedAdaptiveFilter(true)); config.Set<RefinedAdaptiveFilter>(new RefinedAdaptiveFilter(true));
// Arbitrarily set clipping gain to 17, which will never be the default. // Arbitrarily set clipping gain to 17, which will never be the default.
config.Set<ExperimentalAgc>(new ExperimentalAgc(true, 0, 17)); config.Set<ExperimentalAgc>(new ExperimentalAgc(true, 0, 17));
apm_config.echo_canceller3.enabled = true; bool enable_aec3 = true;
DebugDumpGenerator generator(config, apm_config); DebugDumpGenerator generator(config, apm_config, enable_aec3);
generator.StartRecording(); generator.StartRecording();
generator.Process(100); generator.Process(100);
generator.StopRecording(); generator.StopRecording();
@ -441,8 +462,7 @@ TEST_F(DebugDumpTest, VerifyCombinedExperimentalStringExclusive) {
TEST_F(DebugDumpTest, VerifyAec3ExperimentalString) { TEST_F(DebugDumpTest, VerifyAec3ExperimentalString) {
Config config; Config config;
AudioProcessing::Config apm_config; AudioProcessing::Config apm_config;
apm_config.echo_canceller3.enabled = true; DebugDumpGenerator generator(config, apm_config, true);
DebugDumpGenerator generator(config, apm_config);
generator.StartRecording(); generator.StartRecording();
generator.Process(100); generator.Process(100);
generator.StopRecording(); generator.StopRecording();

View File

@ -49,6 +49,11 @@ std::unique_ptr<AudioProcessing> CreateAPM(const uint8_t** data,
// webrtc::AudioProcessingConfig. // webrtc::AudioProcessingConfig.
Config config; Config config;
std::unique_ptr<EchoControlFactory> echo_control_factory;
if (*aec3) {
echo_control_factory.reset(new EchoCanceller3Factory());
}
config.Set<ExperimentalAgc>(new ExperimentalAgc(*exp_agc)); config.Set<ExperimentalAgc>(new ExperimentalAgc(*exp_agc));
config.Set<ExperimentalNs>(new ExperimentalNs(*exp_ns)); config.Set<ExperimentalNs>(new ExperimentalNs(*exp_ns));
if (*bf) { if (*bf) {
@ -59,13 +64,13 @@ std::unique_ptr<AudioProcessing> CreateAPM(const uint8_t** data,
config.Set<DelayAgnostic>(new DelayAgnostic(*da)); config.Set<DelayAgnostic>(new DelayAgnostic(*da));
config.Set<Intelligibility>(new Intelligibility(*ie)); config.Set<Intelligibility>(new Intelligibility(*ie));
std::unique_ptr<AudioProcessing> apm(AudioProcessing::Create(config)); std::unique_ptr<AudioProcessing> apm(AudioProcessing::Create(
config, nullptr, std::move(echo_control_factory), nullptr));
webrtc::AudioProcessing::Config apm_config; webrtc::AudioProcessing::Config apm_config;
apm_config.residual_echo_detector.enabled = *red; apm_config.residual_echo_detector.enabled = *red;
apm_config.level_controller.enabled = *lc; apm_config.level_controller.enabled = *lc;
apm_config.high_pass_filter.enabled = *hpf; apm_config.high_pass_filter.enabled = *hpf;
apm_config.echo_canceller3.enabled = *aec3;
apm->ApplyConfig(apm_config); apm->ApplyConfig(apm_config);