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:

committed by
Commit Bot

parent
737e073f8d
commit
bd83b914c3
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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,
|
||||||
|
@ -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,
|
||||||
|
@ -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)),
|
||||||
"");
|
"");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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_
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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.
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -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());
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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.
|
||||||
|
@ -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)),
|
||||||
"");
|
"");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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.
|
||||||
|
@ -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);
|
||||||
};
|
};
|
||||||
|
@ -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));
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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_
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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();
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user