Propagate field trials to aec3 sub components

Bug: webrtc:369904700
Change-Id: I17264de11346838b70ab2c47d6f6dc768e74b41a
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/374361
Reviewed-by: Sam Zackrisson <saza@webrtc.org>
Commit-Queue: Danil Chapovalov <danilchap@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#43746}
This commit is contained in:
Danil Chapovalov 2025-01-14 18:10:57 +01:00 committed by WebRTC LUCI CQ
parent 1ba220a816
commit 23b95d4fe4
35 changed files with 265 additions and 168 deletions

View File

@ -182,7 +182,6 @@ rtc_library("audio_processing") {
"../../rtc_base/system:rtc_export", "../../rtc_base/system:rtc_export",
"../../system_wrappers", "../../system_wrappers",
"../../system_wrappers:denormal_disabler", "../../system_wrappers:denormal_disabler",
"../../system_wrappers:field_trial",
"../../system_wrappers:metrics", "../../system_wrappers:metrics",
"aec3", "aec3",
"aec_dump", "aec_dump",

View File

@ -155,7 +155,6 @@ rtc_library("aec3") {
"../../../rtc_base/experiments:field_trial_parser", "../../../rtc_base/experiments:field_trial_parser",
"../../../rtc_base/system:arch", "../../../rtc_base/system:arch",
"../../../system_wrappers", "../../../system_wrappers",
"../../../system_wrappers:field_trial",
"../../../system_wrappers:metrics", "../../../system_wrappers:metrics",
"../utility:cascaded_biquad_filter", "../utility:cascaded_biquad_filter",
"//third_party/abseil-cpp/absl/strings:string_view", "//third_party/abseil-cpp/absl/strings:string_view",

View File

@ -22,6 +22,7 @@
#include <emmintrin.h> #include <emmintrin.h>
#endif #endif
#include "api/environment/environment_factory.h"
#include "modules/audio_processing/aec3/adaptive_fir_filter_erl.h" #include "modules/audio_processing/aec3/adaptive_fir_filter_erl.h"
#include "modules/audio_processing/aec3/aec3_fft.h" #include "modules/audio_processing/aec3/aec3_fft.h"
#include "modules/audio_processing/aec3/aec_state.h" #include "modules/audio_processing/aec3/aec_state.h"
@ -482,7 +483,8 @@ TEST_P(AdaptiveFirFilterMultiChannel, FilterAndAdapt) {
Block x(kNumBands, num_render_channels); Block x(kNumBands, num_render_channels);
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(EchoCanceller3Config{}, num_capture_channels); AecState aec_state(CreateEnvironment(), EchoCanceller3Config{},
num_capture_channels);
RenderSignalAnalyzer render_signal_analyzer(config); RenderSignalAnalyzer render_signal_analyzer(config);
std::optional<DelayEstimate> delay_estimate; std::optional<DelayEstimate> delay_estimate;
std::vector<float> e(kBlockSize, 0.f); std::vector<float> e(kBlockSize, 0.f);

View File

@ -18,25 +18,28 @@
#include <vector> #include <vector>
#include "api/array_view.h" #include "api/array_view.h"
#include "api/environment/environment.h"
#include "api/field_trials_view.h"
#include "modules/audio_processing/aec3/aec3_common.h" #include "modules/audio_processing/aec3/aec3_common.h"
#include "modules/audio_processing/logging/apm_data_dumper.h" #include "modules/audio_processing/logging/apm_data_dumper.h"
#include "rtc_base/checks.h" #include "rtc_base/checks.h"
#include "system_wrappers/include/field_trial.h"
namespace webrtc { namespace webrtc {
namespace { namespace {
bool DeactivateInitialStateResetAtEchoPathChange() { bool DeactivateInitialStateResetAtEchoPathChange(
return field_trial::IsEnabled( const FieldTrialsView& field_trials) {
return field_trials.IsEnabled(
"WebRTC-Aec3DeactivateInitialStateResetKillSwitch"); "WebRTC-Aec3DeactivateInitialStateResetKillSwitch");
} }
bool FullResetAtEchoPathChange() { bool FullResetAtEchoPathChange(const FieldTrialsView& field_trials) {
return !field_trial::IsEnabled("WebRTC-Aec3AecStateFullResetKillSwitch"); return !field_trials.IsEnabled("WebRTC-Aec3AecStateFullResetKillSwitch");
} }
bool SubtractorAnalyzerResetAtEchoPathChange() { bool SubtractorAnalyzerResetAtEchoPathChange(
return !field_trial::IsEnabled( const FieldTrialsView& field_trials) {
return !field_trials.IsEnabled(
"WebRTC-Aec3AecStateSubtractorAnalyzerResetKillSwitch"); "WebRTC-Aec3AecStateSubtractorAnalyzerResetKillSwitch");
} }
@ -112,22 +115,27 @@ void AecState::GetResidualEchoScaling(
residual_scaling); residual_scaling);
} }
AecState::AecState(const EchoCanceller3Config& config, AecState::AecState(const Environment& env,
const EchoCanceller3Config& config,
size_t num_capture_channels) size_t num_capture_channels)
: data_dumper_(new ApmDataDumper(instance_count_.fetch_add(1) + 1)), : data_dumper_(new ApmDataDumper(instance_count_.fetch_add(1) + 1)),
config_(config), config_(config),
num_capture_channels_(num_capture_channels), num_capture_channels_(num_capture_channels),
deactivate_initial_state_reset_at_echo_path_change_( deactivate_initial_state_reset_at_echo_path_change_(
DeactivateInitialStateResetAtEchoPathChange()), DeactivateInitialStateResetAtEchoPathChange(env.field_trials())),
full_reset_at_echo_path_change_(FullResetAtEchoPathChange()), full_reset_at_echo_path_change_(
FullResetAtEchoPathChange(env.field_trials())),
subtractor_analyzer_reset_at_echo_path_change_( subtractor_analyzer_reset_at_echo_path_change_(
SubtractorAnalyzerResetAtEchoPathChange()), SubtractorAnalyzerResetAtEchoPathChange(env.field_trials())),
initial_state_(config_), initial_state_(config_),
delay_state_(config_, num_capture_channels_), delay_state_(config_, num_capture_channels_),
transparent_state_(TransparentMode::Create(config_)), transparent_state_(TransparentMode::Create(env, config_)),
filter_quality_state_(config_, num_capture_channels_), filter_quality_state_(config_, num_capture_channels_),
erl_estimator_(2 * kNumBlocksPerSecond), erl_estimator_(2 * kNumBlocksPerSecond),
erle_estimator_(2 * kNumBlocksPerSecond, config_, num_capture_channels_), erle_estimator_(env,
2 * kNumBlocksPerSecond,
config_,
num_capture_channels_),
filter_analyzer_(config_, num_capture_channels_), filter_analyzer_(config_, num_capture_channels_),
echo_audibility_( echo_audibility_(
config_.echo_audibility.use_stationarity_properties_at_init), config_.echo_audibility.use_stationarity_properties_at_init),

View File

@ -21,6 +21,7 @@
#include "api/array_view.h" #include "api/array_view.h"
#include "api/audio/echo_canceller3_config.h" #include "api/audio/echo_canceller3_config.h"
#include "api/environment/environment.h"
#include "modules/audio_processing/aec3/aec3_common.h" #include "modules/audio_processing/aec3/aec3_common.h"
#include "modules/audio_processing/aec3/delay_estimate.h" #include "modules/audio_processing/aec3/delay_estimate.h"
#include "modules/audio_processing/aec3/echo_audibility.h" #include "modules/audio_processing/aec3/echo_audibility.h"
@ -41,7 +42,9 @@ 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:
AecState(const EchoCanceller3Config& config, size_t num_capture_channels); AecState(const Environment& env,
const EchoCanceller3Config& config,
size_t num_capture_channels);
~AecState(); ~AecState();
// Returns whether the echo subtractor can be used to determine the residual // Returns whether the echo subtractor can be used to determine the residual

View File

@ -10,6 +10,8 @@
#include "modules/audio_processing/aec3/aec_state.h" #include "modules/audio_processing/aec3/aec_state.h"
#include "api/environment/environment.h"
#include "api/environment/environment_factory.h"
#include "modules/audio_processing/aec3/aec3_fft.h" #include "modules/audio_processing/aec3/aec3_fft.h"
#include "modules/audio_processing/aec3/render_delay_buffer.h" #include "modules/audio_processing/aec3/render_delay_buffer.h"
#include "modules/audio_processing/logging/apm_data_dumper.h" #include "modules/audio_processing/logging/apm_data_dumper.h"
@ -27,7 +29,7 @@ void RunNormalUsageTest(size_t num_render_channels,
constexpr size_t kNumBands = NumBandsForRate(kSampleRateHz); constexpr size_t kNumBands = NumBandsForRate(kSampleRateHz);
ApmDataDumper data_dumper(42); ApmDataDumper data_dumper(42);
EchoCanceller3Config config; EchoCanceller3Config config;
AecState state(config, num_capture_channels); AecState state(CreateEnvironment(), config, num_capture_channels);
std::optional<DelayEstimate> delay_estimate = std::optional<DelayEstimate> delay_estimate =
DelayEstimate(DelayEstimate::Quality::kRefined, 10); DelayEstimate(DelayEstimate::Quality::kRefined, 10);
std::unique_ptr<RenderDelayBuffer> render_delay_buffer( std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
@ -244,7 +246,7 @@ TEST(AecState, ConvergedFilterDelay) {
constexpr int kFilterLengthBlocks = 10; constexpr int kFilterLengthBlocks = 10;
constexpr size_t kNumCaptureChannels = 1; constexpr size_t kNumCaptureChannels = 1;
EchoCanceller3Config config; EchoCanceller3Config config;
AecState state(config, kNumCaptureChannels); AecState state(CreateEnvironment(), config, kNumCaptureChannels);
std::unique_ptr<RenderDelayBuffer> render_delay_buffer( std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
RenderDelayBuffer::Create(config, 48000, 1)); RenderDelayBuffer::Create(config, 48000, 1));
std::optional<DelayEstimate> delay_estimate; std::optional<DelayEstimate> delay_estimate;

View File

@ -237,10 +237,12 @@ void BlockProcessorImpl::SetCaptureOutputUsage(bool capture_output_used) {
} // namespace } // namespace
BlockProcessor* BlockProcessor::Create(const EchoCanceller3Config& config, std::unique_ptr<BlockProcessor> BlockProcessor::Create(
int sample_rate_hz, const Environment& env,
size_t num_render_channels, const EchoCanceller3Config& config,
size_t num_capture_channels) { int sample_rate_hz,
size_t num_render_channels,
size_t num_capture_channels) {
std::unique_ptr<RenderDelayBuffer> render_buffer( std::unique_ptr<RenderDelayBuffer> render_buffer(
RenderDelayBuffer::Create(config, sample_rate_hz, num_render_channels)); RenderDelayBuffer::Create(config, sample_rate_hz, num_render_channels));
std::unique_ptr<RenderDelayController> delay_controller; std::unique_ptr<RenderDelayController> delay_controller;
@ -248,14 +250,15 @@ BlockProcessor* BlockProcessor::Create(const EchoCanceller3Config& config,
delay_controller.reset(RenderDelayController::Create(config, sample_rate_hz, delay_controller.reset(RenderDelayController::Create(config, sample_rate_hz,
num_capture_channels)); num_capture_channels));
} }
std::unique_ptr<EchoRemover> echo_remover(EchoRemover::Create( std::unique_ptr<EchoRemover> echo_remover = EchoRemover::Create(
config, sample_rate_hz, num_render_channels, num_capture_channels)); env, config, sample_rate_hz, num_render_channels, num_capture_channels);
return Create(config, sample_rate_hz, num_render_channels, return Create(config, sample_rate_hz, num_render_channels,
num_capture_channels, std::move(render_buffer), num_capture_channels, std::move(render_buffer),
std::move(delay_controller), std::move(echo_remover)); std::move(delay_controller), std::move(echo_remover));
} }
BlockProcessor* BlockProcessor::Create( std::unique_ptr<BlockProcessor> BlockProcessor::Create(
const Environment& env,
const EchoCanceller3Config& config, const EchoCanceller3Config& config,
int sample_rate_hz, int sample_rate_hz,
size_t num_render_channels, size_t num_render_channels,
@ -266,14 +269,14 @@ BlockProcessor* BlockProcessor::Create(
delay_controller.reset(RenderDelayController::Create(config, sample_rate_hz, delay_controller.reset(RenderDelayController::Create(config, sample_rate_hz,
num_capture_channels)); num_capture_channels));
} }
std::unique_ptr<EchoRemover> echo_remover(EchoRemover::Create( std::unique_ptr<EchoRemover> echo_remover = EchoRemover::Create(
config, sample_rate_hz, num_render_channels, num_capture_channels)); env, config, sample_rate_hz, num_render_channels, num_capture_channels);
return Create(config, sample_rate_hz, num_render_channels, return Create(config, sample_rate_hz, num_render_channels,
num_capture_channels, std::move(render_buffer), num_capture_channels, std::move(render_buffer),
std::move(delay_controller), std::move(echo_remover)); std::move(delay_controller), std::move(echo_remover));
} }
BlockProcessor* BlockProcessor::Create( std::unique_ptr<BlockProcessor> BlockProcessor::Create(
const EchoCanceller3Config& config, const EchoCanceller3Config& config,
int sample_rate_hz, int sample_rate_hz,
size_t num_render_channels, size_t num_render_channels,
@ -281,10 +284,10 @@ BlockProcessor* BlockProcessor::Create(
std::unique_ptr<RenderDelayBuffer> render_buffer, std::unique_ptr<RenderDelayBuffer> render_buffer,
std::unique_ptr<RenderDelayController> delay_controller, std::unique_ptr<RenderDelayController> delay_controller,
std::unique_ptr<EchoRemover> echo_remover) { std::unique_ptr<EchoRemover> echo_remover) {
return new BlockProcessorImpl(config, sample_rate_hz, num_render_channels, return std::make_unique<BlockProcessorImpl>(
num_capture_channels, std::move(render_buffer), config, sample_rate_hz, num_render_channels, num_capture_channels,
std::move(delay_controller), std::move(render_buffer), std::move(delay_controller),
std::move(echo_remover)); std::move(echo_remover));
} }
} // namespace webrtc } // namespace webrtc

View File

@ -18,6 +18,7 @@
#include "api/audio/echo_canceller3_config.h" #include "api/audio/echo_canceller3_config.h"
#include "api/audio/echo_control.h" #include "api/audio/echo_control.h"
#include "api/environment/environment.h"
#include "modules/audio_processing/aec3/block.h" #include "modules/audio_processing/aec3/block.h"
#include "modules/audio_processing/aec3/echo_remover.h" #include "modules/audio_processing/aec3/echo_remover.h"
#include "modules/audio_processing/aec3/render_delay_buffer.h" #include "modules/audio_processing/aec3/render_delay_buffer.h"
@ -28,18 +29,21 @@ 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(const EchoCanceller3Config& config, static std::unique_ptr<BlockProcessor> Create(
int sample_rate_hz, const Environment& env,
size_t num_render_channels, const EchoCanceller3Config& config,
size_t num_capture_channels); int sample_rate_hz,
size_t num_render_channels,
size_t num_capture_channels);
// Only used for testing purposes. // Only used for testing purposes.
static BlockProcessor* Create( static std::unique_ptr<BlockProcessor> Create(
const Environment& env,
const EchoCanceller3Config& config, const EchoCanceller3Config& config,
int sample_rate_hz, int sample_rate_hz,
size_t num_render_channels, size_t num_render_channels,
size_t num_capture_channels, size_t num_capture_channels,
std::unique_ptr<RenderDelayBuffer> render_buffer); std::unique_ptr<RenderDelayBuffer> render_buffer);
static BlockProcessor* Create( static std::unique_ptr<BlockProcessor> Create(
const EchoCanceller3Config& config, const EchoCanceller3Config& config,
int sample_rate_hz, int sample_rate_hz,
size_t num_render_channels, size_t num_render_channels,

View File

@ -14,6 +14,8 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "api/environment/environment.h"
#include "api/environment/environment_factory.h"
#include "modules/audio_processing/aec3/aec3_common.h" #include "modules/audio_processing/aec3/aec3_common.h"
#include "modules/audio_processing/aec3/mock/mock_echo_remover.h" #include "modules/audio_processing/aec3/mock/mock_echo_remover.h"
#include "modules/audio_processing/aec3/mock/mock_render_delay_buffer.h" #include "modules/audio_processing/aec3/mock/mock_render_delay_buffer.h"
@ -36,13 +38,15 @@ using ::testing::StrictMock;
// 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, int num_iterations) { void RunBasicSetupAndApiCallTest(const Environment& env,
int sample_rate_hz,
int num_iterations) {
constexpr size_t kNumRenderChannels = 1; constexpr size_t kNumRenderChannels = 1;
constexpr size_t kNumCaptureChannels = 1; constexpr size_t kNumCaptureChannels = 1;
std::unique_ptr<BlockProcessor> block_processor( std::unique_ptr<BlockProcessor> block_processor =
BlockProcessor::Create(EchoCanceller3Config(), sample_rate_hz, BlockProcessor::Create(env, EchoCanceller3Config(), sample_rate_hz,
kNumRenderChannels, kNumCaptureChannels)); kNumRenderChannels, kNumCaptureChannels);
Block block(NumBandsForRate(sample_rate_hz), kNumRenderChannels, 1000.f); Block block(NumBandsForRate(sample_rate_hz), kNumRenderChannels, 1000.f);
for (int k = 0; k < num_iterations; ++k) { for (int k = 0; k < num_iterations; ++k) {
block_processor->BufferRender(block); block_processor->BufferRender(block);
@ -52,43 +56,46 @@ void RunBasicSetupAndApiCallTest(int sample_rate_hz, int num_iterations) {
} }
#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(const Environment& env,
int sample_rate_hz) {
constexpr size_t kNumRenderChannels = 1; constexpr size_t kNumRenderChannels = 1;
constexpr size_t kNumCaptureChannels = 1; constexpr size_t kNumCaptureChannels = 1;
std::unique_ptr<BlockProcessor> block_processor( std::unique_ptr<BlockProcessor> block_processor =
BlockProcessor::Create(EchoCanceller3Config(), sample_rate_hz, BlockProcessor::Create(env, EchoCanceller3Config(), sample_rate_hz,
kNumRenderChannels, kNumCaptureChannels)); kNumRenderChannels, kNumCaptureChannels);
Block block(NumBandsForRate(sample_rate_hz), kNumRenderChannels); Block block(NumBandsForRate(sample_rate_hz), kNumRenderChannels);
EXPECT_DEATH(block_processor->BufferRender(block), ""); EXPECT_DEATH(block_processor->BufferRender(block), "");
} }
void RunRenderNumBandsVerificationTest(int sample_rate_hz) { void RunRenderNumBandsVerificationTest(const Environment& env,
int sample_rate_hz) {
constexpr size_t kNumRenderChannels = 1; constexpr size_t kNumRenderChannels = 1;
constexpr size_t kNumCaptureChannels = 1; constexpr size_t kNumCaptureChannels = 1;
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( std::unique_ptr<BlockProcessor> block_processor =
BlockProcessor::Create(EchoCanceller3Config(), sample_rate_hz, BlockProcessor::Create(env, EchoCanceller3Config(), sample_rate_hz,
kNumRenderChannels, kNumCaptureChannels)); kNumRenderChannels, kNumCaptureChannels);
Block block(wrong_num_bands, kNumRenderChannels); Block block(wrong_num_bands, kNumRenderChannels);
EXPECT_DEATH(block_processor->BufferRender(block), ""); EXPECT_DEATH(block_processor->BufferRender(block), "");
} }
void RunCaptureNumBandsVerificationTest(int sample_rate_hz) { void RunCaptureNumBandsVerificationTest(const Environment& env,
int sample_rate_hz) {
constexpr size_t kNumRenderChannels = 1; constexpr size_t kNumRenderChannels = 1;
constexpr size_t kNumCaptureChannels = 1; constexpr size_t kNumCaptureChannels = 1;
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( std::unique_ptr<BlockProcessor> block_processor =
BlockProcessor::Create(EchoCanceller3Config(), sample_rate_hz, BlockProcessor::Create(env, EchoCanceller3Config(), sample_rate_hz,
kNumRenderChannels, kNumCaptureChannels)); kNumRenderChannels, kNumCaptureChannels);
Block block(wrong_num_bands, kNumRenderChannels); Block block(wrong_num_bands, kNumRenderChannels);
EXPECT_DEATH(block_processor->ProcessCapture(false, false, nullptr, &block), EXPECT_DEATH(block_processor->ProcessCapture(false, false, nullptr, &block),
@ -123,6 +130,7 @@ TEST(BlockProcessor, DISABLED_DelayControllerIntegration) {
constexpr size_t kDelayHeadroom = 1; constexpr size_t kDelayHeadroom = 1;
constexpr size_t kDelayInBlocks = constexpr size_t kDelayInBlocks =
kDelayInSamples / kBlockSize - kDelayHeadroom; kDelayInSamples / kBlockSize - kDelayHeadroom;
const Environment env = CreateEnvironment();
Random random_generator(42U); Random random_generator(42U);
for (auto rate : {16000, 32000, 48000}) { for (auto rate : {16000, 32000, 48000}) {
SCOPED_TRACE(ProduceDebugText(rate)); SCOPED_TRACE(ProduceDebugText(rate));
@ -138,9 +146,9 @@ 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(BlockProcessor::Create( std::unique_ptr<BlockProcessor> block_processor = BlockProcessor::Create(
EchoCanceller3Config(), rate, kNumRenderChannels, kNumCaptureChannels, env, EchoCanceller3Config(), rate, kNumRenderChannels,
std::move(render_delay_buffer_mock))); kNumCaptureChannels, std::move(render_delay_buffer_mock));
Block render_block(NumBandsForRate(rate), kNumRenderChannels); Block render_block(NumBandsForRate(rate), kNumRenderChannels);
Block capture_block(NumBandsForRate(rate), kNumCaptureChannels); Block capture_block(NumBandsForRate(rate), kNumCaptureChannels);
@ -212,46 +220,51 @@ TEST(BlockProcessor, DISABLED_SubmoduleIntegration) {
} }
TEST(BlockProcessor, BasicSetupAndApiCalls) { TEST(BlockProcessor, BasicSetupAndApiCalls) {
const Environment env = CreateEnvironment();
for (auto rate : {16000, 32000, 48000}) { for (auto rate : {16000, 32000, 48000}) {
SCOPED_TRACE(ProduceDebugText(rate)); SCOPED_TRACE(ProduceDebugText(rate));
RunBasicSetupAndApiCallTest(rate, 1); RunBasicSetupAndApiCallTest(env, rate, 1);
} }
} }
TEST(BlockProcessor, TestLongerCall) { TEST(BlockProcessor, TestLongerCall) {
RunBasicSetupAndApiCallTest(16000, 20 * kNumBlocksPerSecond); RunBasicSetupAndApiCallTest(CreateEnvironment(), 16000,
20 * kNumBlocksPerSecond);
} }
#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
// TODO(gustaf): Re-enable the test once the issue with memory leaks during // TODO(gustaf): Re-enable the test once the issue with memory leaks during
// DEATH tests on test bots has been fixed. // DEATH tests on test bots has been fixed.
TEST(BlockProcessorDeathTest, DISABLED_VerifyRenderBlockSizeCheck) { TEST(BlockProcessorDeathTest, DISABLED_VerifyRenderBlockSizeCheck) {
const Environment env = CreateEnvironment();
for (auto rate : {16000, 32000, 48000}) { for (auto rate : {16000, 32000, 48000}) {
SCOPED_TRACE(ProduceDebugText(rate)); SCOPED_TRACE(ProduceDebugText(rate));
RunRenderBlockSizeVerificationTest(rate); RunRenderBlockSizeVerificationTest(env, rate);
} }
} }
TEST(BlockProcessorDeathTest, VerifyRenderNumBandsCheck) { TEST(BlockProcessorDeathTest, VerifyRenderNumBandsCheck) {
const Environment env = CreateEnvironment();
for (auto rate : {16000, 32000, 48000}) { for (auto rate : {16000, 32000, 48000}) {
SCOPED_TRACE(ProduceDebugText(rate)); SCOPED_TRACE(ProduceDebugText(rate));
RunRenderNumBandsVerificationTest(rate); RunRenderNumBandsVerificationTest(env, rate);
} }
} }
// TODO(peah): Verify the check for correct number of bands in the capture // TODO(peah): Verify the check for correct number of bands in the capture
// signal. // signal.
TEST(BlockProcessorDeathTest, VerifyCaptureNumBandsCheck) { TEST(BlockProcessorDeathTest, VerifyCaptureNumBandsCheck) {
const Environment env = CreateEnvironment();
for (auto rate : {16000, 32000, 48000}) { for (auto rate : {16000, 32000, 48000}) {
SCOPED_TRACE(ProduceDebugText(rate)); SCOPED_TRACE(ProduceDebugText(rate));
RunCaptureNumBandsVerificationTest(rate); RunCaptureNumBandsVerificationTest(env, rate);
} }
} }
// Verifiers that the verification for null ProcessCapture input works. // Verifiers that the verification for null ProcessCapture input works.
TEST(BlockProcessorDeathTest, NullProcessCaptureParameter) { TEST(BlockProcessorDeathTest, NullProcessCaptureParameter) {
EXPECT_DEATH(std::unique_ptr<BlockProcessor>( EXPECT_DEATH(BlockProcessor::Create(CreateEnvironment(),
BlockProcessor::Create(EchoCanceller3Config(), 16000, 1, 1)) EchoCanceller3Config(), 16000, 1, 1)
->ProcessCapture(false, false, nullptr, nullptr), ->ProcessCapture(false, false, nullptr, nullptr),
""); "");
} }
@ -260,8 +273,8 @@ TEST(BlockProcessorDeathTest, 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>( EXPECT_DEATH(BlockProcessor::Create(CreateEnvironment(),
BlockProcessor::Create(EchoCanceller3Config(), 8001, 1, 1)), EchoCanceller3Config(), 8001, 1, 1),
""); "");
} }

View File

@ -14,6 +14,7 @@
#include <numeric> #include <numeric>
#include "api/audio/echo_canceller3_config.h" #include "api/audio/echo_canceller3_config.h"
#include "api/environment/environment_factory.h"
#include "modules/audio_processing/aec3/aec_state.h" #include "modules/audio_processing/aec3/aec_state.h"
#include "rtc_base/random.h" #include "rtc_base/random.h"
#include "rtc_base/system/arch.h" #include "rtc_base/system/arch.h"
@ -36,7 +37,7 @@ TEST(ComfortNoiseGenerator, CorrectLevel) {
constexpr size_t kNumChannels = 5; constexpr size_t kNumChannels = 5;
EchoCanceller3Config config; EchoCanceller3Config config;
ComfortNoiseGenerator cng(config, DetectOptimization(), kNumChannels); ComfortNoiseGenerator cng(config, DetectOptimization(), kNumChannels);
AecState aec_state(config, kNumChannels); AecState aec_state(CreateEnvironment(), config, kNumChannels);
std::vector<std::array<float, kFftLengthBy2Plus1>> N2(kNumChannels); std::vector<std::array<float, kFftLengthBy2Plus1>> N2(kNumChannels);
std::vector<FftData> n_lower(kNumChannels); std::vector<FftData> n_lower(kNumChannels);

View File

@ -735,7 +735,8 @@ EchoCanceller3::EchoCanceller3(
int sample_rate_hz, int sample_rate_hz,
size_t num_render_channels, size_t num_render_channels,
size_t num_capture_channels) size_t num_capture_channels)
: data_dumper_(new ApmDataDumper(instance_count_.fetch_add(1) + 1)), : env_(env),
data_dumper_(new ApmDataDumper(instance_count_.fetch_add(1) + 1)),
config_(AdjustConfig(config, env.field_trials())), config_(AdjustConfig(config, env.field_trials())),
sample_rate_hz_(sample_rate_hz), sample_rate_hz_(sample_rate_hz),
num_bands_(NumBandsForRate(sample_rate_hz_)), num_bands_(NumBandsForRate(sample_rate_hz_)),
@ -825,9 +826,9 @@ void EchoCanceller3::Initialize() {
render_blocker_.reset( render_blocker_.reset(
new FrameBlocker(num_bands_, num_render_channels_to_aec_)); new FrameBlocker(num_bands_, num_render_channels_to_aec_));
block_processor_.reset(BlockProcessor::Create( block_processor_ = BlockProcessor::Create(
config_selector_.active_config(), sample_rate_hz_, env_, config_selector_.active_config(), sample_rate_hz_,
num_render_channels_to_aec_, num_capture_channels_)); num_render_channels_to_aec_, num_capture_channels_);
render_sub_frame_view_ = std::vector<std::vector<rtc::ArrayView<float>>>( render_sub_frame_view_ = std::vector<std::vector<rtc::ArrayView<float>>>(
num_bands_, num_bands_,

View File

@ -181,6 +181,7 @@ class EchoCanceller3 : public EchoControl {
// Analyzes the full-band domain capture signal to detect signal saturation. // Analyzes the full-band domain capture signal to detect signal saturation.
void AnalyzeCapture(const AudioBuffer& capture); void AnalyzeCapture(const AudioBuffer& capture);
const Environment env_;
rtc::RaceChecker capture_race_checker_; rtc::RaceChecker capture_race_checker_;
rtc::RaceChecker render_race_checker_; rtc::RaceChecker render_race_checker_;

View File

@ -19,6 +19,7 @@
#include <memory> #include <memory>
#include "api/array_view.h" #include "api/array_view.h"
#include "api/environment/environment.h"
#include "modules/audio_processing/aec3/aec3_common.h" #include "modules/audio_processing/aec3/aec3_common.h"
#include "modules/audio_processing/aec3/aec3_fft.h" #include "modules/audio_processing/aec3/aec3_fft.h"
#include "modules/audio_processing/aec3/aec_state.h" #include "modules/audio_processing/aec3/aec_state.h"
@ -105,7 +106,8 @@ void WindowedPaddedFft(const Aec3Fft& fft,
// 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:
EchoRemoverImpl(const EchoCanceller3Config& config, EchoRemoverImpl(const Environment& env,
const EchoCanceller3Config& config,
int sample_rate_hz, int sample_rate_hz,
size_t num_render_channels, size_t num_render_channels,
size_t num_capture_channels); size_t num_capture_channels);
@ -182,7 +184,8 @@ class EchoRemoverImpl final : public EchoRemover {
std::atomic<int> EchoRemoverImpl::instance_count_(0); std::atomic<int> EchoRemoverImpl::instance_count_(0);
EchoRemoverImpl::EchoRemoverImpl(const EchoCanceller3Config& config, EchoRemoverImpl::EchoRemoverImpl(const Environment& env,
const EchoCanceller3Config& config,
int sample_rate_hz, int sample_rate_hz,
size_t num_render_channels, size_t num_render_channels,
size_t num_capture_channels) size_t num_capture_channels)
@ -195,7 +198,8 @@ EchoRemoverImpl::EchoRemoverImpl(const EchoCanceller3Config& config,
num_capture_channels_(num_capture_channels), num_capture_channels_(num_capture_channels),
use_coarse_filter_output_( use_coarse_filter_output_(
config_.filter.enable_coarse_filter_output_usage), config_.filter.enable_coarse_filter_output_usage),
subtractor_(config, subtractor_(env,
config,
num_render_channels_, num_render_channels_,
num_capture_channels_, num_capture_channels_,
data_dumper_.get(), data_dumper_.get(),
@ -209,8 +213,8 @@ EchoRemoverImpl::EchoRemoverImpl(const EchoCanceller3Config& config,
sample_rate_hz_, sample_rate_hz_,
num_capture_channels_), num_capture_channels_),
render_signal_analyzer_(config_), render_signal_analyzer_(config_),
residual_echo_estimator_(config_, num_render_channels), residual_echo_estimator_(env, config_, num_render_channels),
aec_state_(config_, num_capture_channels_), aec_state_(env, config_, num_capture_channels_),
e_old_(num_capture_channels_, {0.f}), e_old_(num_capture_channels_, {0.f}),
y_old_(num_capture_channels_, {0.f}), y_old_(num_capture_channels_, {0.f}),
e_heap_(NumChannelsOnHeap(num_capture_channels_), {0.f}), e_heap_(NumChannelsOnHeap(num_capture_channels_), {0.f}),
@ -510,12 +514,14 @@ void EchoRemoverImpl::FormLinearFilterOutput(
} // namespace } // namespace
EchoRemover* EchoRemover::Create(const EchoCanceller3Config& config, std::unique_ptr<EchoRemover> EchoRemover::Create(
int sample_rate_hz, const Environment& env,
size_t num_render_channels, const EchoCanceller3Config& config,
size_t num_capture_channels) { int sample_rate_hz,
return new EchoRemoverImpl(config, sample_rate_hz, num_render_channels, size_t num_render_channels,
num_capture_channels); size_t num_capture_channels) {
return std::make_unique<EchoRemoverImpl>(
env, config, sample_rate_hz, num_render_channels, num_capture_channels);
} }
} // namespace webrtc } // namespace webrtc

View File

@ -11,11 +11,13 @@
#ifndef MODULES_AUDIO_PROCESSING_AEC3_ECHO_REMOVER_H_ #ifndef MODULES_AUDIO_PROCESSING_AEC3_ECHO_REMOVER_H_
#define MODULES_AUDIO_PROCESSING_AEC3_ECHO_REMOVER_H_ #define MODULES_AUDIO_PROCESSING_AEC3_ECHO_REMOVER_H_
#include <memory>
#include <optional> #include <optional>
#include <vector> #include <vector>
#include "api/audio/echo_canceller3_config.h" #include "api/audio/echo_canceller3_config.h"
#include "api/audio/echo_control.h" #include "api/audio/echo_control.h"
#include "api/environment/environment.h"
#include "modules/audio_processing/aec3/block.h" #include "modules/audio_processing/aec3/block.h"
#include "modules/audio_processing/aec3/delay_estimate.h" #include "modules/audio_processing/aec3/delay_estimate.h"
#include "modules/audio_processing/aec3/echo_path_variability.h" #include "modules/audio_processing/aec3/echo_path_variability.h"
@ -26,10 +28,11 @@ 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(const EchoCanceller3Config& config, static std::unique_ptr<EchoRemover> Create(const Environment& env,
int sample_rate_hz, const EchoCanceller3Config& config,
size_t num_render_channels, int sample_rate_hz,
size_t num_capture_channels); size_t num_render_channels,
size_t num_capture_channels);
virtual ~EchoRemover() = default; virtual ~EchoRemover() = default;
// Get current metrics. // Get current metrics.

View File

@ -14,6 +14,7 @@
#include <cmath> #include <cmath>
#include "api/environment/environment_factory.h"
#include "modules/audio_processing/aec3/aec3_fft.h" #include "modules/audio_processing/aec3/aec3_fft.h"
#include "modules/audio_processing/aec3/aec_state.h" #include "modules/audio_processing/aec3/aec_state.h"
#include "test/gtest.h" #include "test/gtest.h"
@ -138,7 +139,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(EchoCanceller3Config{}, 1); AecState aec_state(CreateEnvironment(), EchoCanceller3Config{}, 1);
std::array<float, kFftLengthBy2Plus1> comfort_noise_spectrum; std::array<float, kFftLengthBy2Plus1> comfort_noise_spectrum;
std::array<float, kFftLengthBy2Plus1> suppressor_gain; std::array<float, kFftLengthBy2Plus1> suppressor_gain;
comfort_noise_spectrum.fill(10.f); comfort_noise_spectrum.fill(10.f);

View File

@ -15,6 +15,8 @@
#include <numeric> #include <numeric>
#include <string> #include <string>
#include "api/environment/environment.h"
#include "api/environment/environment_factory.h"
#include "modules/audio_processing/aec3/aec3_common.h" #include "modules/audio_processing/aec3/aec3_common.h"
#include "modules/audio_processing/aec3/render_buffer.h" #include "modules/audio_processing/aec3/render_buffer.h"
#include "modules/audio_processing/aec3/render_delay_buffer.h" #include "modules/audio_processing/aec3/render_delay_buffer.h"
@ -53,12 +55,13 @@ INSTANTIATE_TEST_SUITE_P(MultiChannel,
TEST_P(EchoRemoverMultiChannel, BasicApiCalls) { TEST_P(EchoRemoverMultiChannel, BasicApiCalls) {
const size_t num_render_channels = std::get<0>(GetParam()); const size_t num_render_channels = std::get<0>(GetParam());
const size_t num_capture_channels = std::get<1>(GetParam()); const size_t num_capture_channels = std::get<1>(GetParam());
const Environment env = CreateEnvironment();
std::optional<DelayEstimate> delay_estimate; std::optional<DelayEstimate> delay_estimate;
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(EchoCanceller3Config(), rate, num_render_channels, EchoRemover::Create(env, EchoCanceller3Config(), rate,
num_capture_channels)); num_render_channels, num_capture_channels);
std::unique_ptr<RenderDelayBuffer> render_buffer(RenderDelayBuffer::Create( std::unique_ptr<RenderDelayBuffer> render_buffer(RenderDelayBuffer::Create(
EchoCanceller3Config(), rate, num_render_channels)); EchoCanceller3Config(), rate, num_render_channels));
@ -86,8 +89,8 @@ TEST_P(EchoRemoverMultiChannel, 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(EchoRemoverDeathTest, DISABLED_WrongSampleRate) { TEST(EchoRemoverDeathTest, DISABLED_WrongSampleRate) {
EXPECT_DEATH(std::unique_ptr<EchoRemover>( EXPECT_DEATH(EchoRemover::Create(CreateEnvironment(), EchoCanceller3Config(),
EchoRemover::Create(EchoCanceller3Config(), 8001, 1, 1)), 8001, 1, 1),
""); "");
} }
@ -95,11 +98,12 @@ TEST(EchoRemoverDeathTest, DISABLED_WrongSampleRate) {
// 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.c // tests on test bots has been fixed.c
TEST(EchoRemoverDeathTest, DISABLED_WrongCaptureNumBands) { TEST(EchoRemoverDeathTest, DISABLED_WrongCaptureNumBands) {
const Environment env = CreateEnvironment();
std::optional<DelayEstimate> delay_estimate; std::optional<DelayEstimate> delay_estimate;
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(EchoCanceller3Config(), rate, 1, 1)); EchoRemover::Create(env, EchoCanceller3Config(), rate, 1, 1);
std::unique_ptr<RenderDelayBuffer> render_buffer( std::unique_ptr<RenderDelayBuffer> render_buffer(
RenderDelayBuffer::Create(EchoCanceller3Config(), rate, 1)); RenderDelayBuffer::Create(EchoCanceller3Config(), rate, 1));
Block capture(NumBandsForRate(rate == 48000 ? 16000 : rate + 16000), 1); Block capture(NumBandsForRate(rate == 48000 ? 16000 : rate + 16000), 1);
@ -115,8 +119,8 @@ TEST(EchoRemoverDeathTest, DISABLED_WrongCaptureNumBands) {
// Verifies the check for non-null capture block. // Verifies the check for non-null capture block.
TEST(EchoRemoverDeathTest, NullCapture) { TEST(EchoRemoverDeathTest, NullCapture) {
std::optional<DelayEstimate> delay_estimate; std::optional<DelayEstimate> delay_estimate;
std::unique_ptr<EchoRemover> remover( std::unique_ptr<EchoRemover> remover = EchoRemover::Create(
EchoRemover::Create(EchoCanceller3Config(), 16000, 1, 1)); CreateEnvironment(), EchoCanceller3Config(), 16000, 1, 1);
std::unique_ptr<RenderDelayBuffer> render_buffer( std::unique_ptr<RenderDelayBuffer> render_buffer(
RenderDelayBuffer::Create(EchoCanceller3Config(), 16000, 1)); RenderDelayBuffer::Create(EchoCanceller3Config(), 16000, 1));
EchoPathVariability echo_path_variability( EchoPathVariability echo_path_variability(
@ -133,6 +137,7 @@ TEST(EchoRemoverDeathTest, NullCapture) {
// remove echoes. // remove echoes.
TEST(EchoRemover, BasicEchoRemoval) { TEST(EchoRemover, BasicEchoRemoval) {
constexpr int kNumBlocksToProcess = 500; constexpr int kNumBlocksToProcess = 500;
const Environment env = CreateEnvironment();
Random random_generator(42U); Random random_generator(42U);
std::optional<DelayEstimate> delay_estimate; std::optional<DelayEstimate> delay_estimate;
for (size_t num_channels : {1, 2, 4}) { for (size_t num_channels : {1, 2, 4}) {
@ -144,8 +149,8 @@ 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));
EchoCanceller3Config config; EchoCanceller3Config config;
std::unique_ptr<EchoRemover> remover( std::unique_ptr<EchoRemover> remover =
EchoRemover::Create(config, rate, num_channels, num_channels)); EchoRemover::Create(env, config, rate, num_channels, num_channels);
std::unique_ptr<RenderDelayBuffer> render_buffer( std::unique_ptr<RenderDelayBuffer> render_buffer(
RenderDelayBuffer::Create(config, rate, num_channels)); RenderDelayBuffer::Create(config, rate, num_channels));
render_buffer->AlignFromDelay(delay_samples / kBlockSize); render_buffer->AlignFromDelay(delay_samples / kBlockSize);

View File

@ -15,12 +15,13 @@
namespace webrtc { namespace webrtc {
ErleEstimator::ErleEstimator(size_t startup_phase_length_blocks, ErleEstimator::ErleEstimator(const Environment& env,
size_t startup_phase_length_blocks,
const EchoCanceller3Config& config, const EchoCanceller3Config& config,
size_t num_capture_channels) size_t num_capture_channels)
: startup_phase_length_blocks_(startup_phase_length_blocks), : startup_phase_length_blocks_(startup_phase_length_blocks),
fullband_erle_estimator_(config.erle, num_capture_channels), fullband_erle_estimator_(config.erle, num_capture_channels),
subband_erle_estimator_(config, num_capture_channels) { subband_erle_estimator_(env, config, num_capture_channels) {
if (config.erle.num_sections > 1) { if (config.erle.num_sections > 1) {
signal_dependent_erle_estimator_ = signal_dependent_erle_estimator_ =
std::make_unique<SignalDependentErleEstimator>(config, std::make_unique<SignalDependentErleEstimator>(config,

View File

@ -33,7 +33,8 @@ namespace webrtc {
// and another one is done using the aggreation of energy over all the subbands. // and another one is done using the aggreation of energy over all the subbands.
class ErleEstimator { class ErleEstimator {
public: public:
ErleEstimator(size_t startup_phase_length_blocks, ErleEstimator(const Environment& env,
size_t startup_phase_length_blocks,
const EchoCanceller3Config& config, const EchoCanceller3Config& config,
size_t num_capture_channels); size_t num_capture_channels);
~ErleEstimator(); ~ErleEstimator();

View File

@ -13,6 +13,7 @@
#include <cmath> #include <cmath>
#include "api/array_view.h" #include "api/array_view.h"
#include "api/environment/environment_factory.h"
#include "modules/audio_processing/aec3/render_delay_buffer.h" #include "modules/audio_processing/aec3/render_delay_buffer.h"
#include "modules/audio_processing/aec3/spectrum_buffer.h" #include "modules/audio_processing/aec3/spectrum_buffer.h"
#include "rtc_base/random.h" #include "rtc_base/random.h"
@ -173,7 +174,7 @@ TEST_P(ErleEstimatorMultiChannel, VerifyErleIncreaseAndHold) {
GetFilterFreq(config.delay.delay_headroom_samples, filter_frequency_response); GetFilterFreq(config.delay.delay_headroom_samples, filter_frequency_response);
ErleEstimator estimator(0, config, num_capture_channels); ErleEstimator estimator(CreateEnvironment(), 0, config, num_capture_channels);
FormFarendTimeFrame(&x); FormFarendTimeFrame(&x);
render_delay_buffer->Insert(x); render_delay_buffer->Insert(x);
@ -236,7 +237,8 @@ TEST_P(ErleEstimatorMultiChannel, VerifyErleTrackingOnOnsets) {
GetFilterFreq(config.delay.delay_headroom_samples, filter_frequency_response); GetFilterFreq(config.delay.delay_headroom_samples, filter_frequency_response);
ErleEstimator estimator(/*startup_phase_length_blocks=*/0, config, ErleEstimator estimator(CreateEnvironment(),
/*startup_phase_length_blocks=*/0, config,
num_capture_channels); num_capture_channels);
FormFarendTimeFrame(&x); FormFarendTimeFrame(&x);

View File

@ -29,9 +29,7 @@
#include "modules/audio_processing/aec3/downsampled_render_buffer.h" #include "modules/audio_processing/aec3/downsampled_render_buffer.h"
#include "modules/audio_processing/logging/apm_data_dumper.h" #include "modules/audio_processing/logging/apm_data_dumper.h"
#include "rtc_base/checks.h" #include "rtc_base/checks.h"
#include "rtc_base/experiments/field_trial_parser.h"
#include "rtc_base/logging.h" #include "rtc_base/logging.h"
#include "system_wrappers/include/field_trial.h"
namespace { namespace {

View File

@ -15,6 +15,8 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "api/environment/environment.h"
#include "api/environment/environment_factory.h"
#include "modules/audio_processing/aec3/adaptive_fir_filter.h" #include "modules/audio_processing/aec3/adaptive_fir_filter.h"
#include "modules/audio_processing/aec3/adaptive_fir_filter_erl.h" #include "modules/audio_processing/aec3/adaptive_fir_filter_erl.h"
#include "modules/audio_processing/aec3/aec_state.h" #include "modules/audio_processing/aec3/aec_state.h"
@ -34,7 +36,8 @@ namespace {
// Method for performing the simulations needed to test the refined filter // Method for performing the simulations needed to test the refined filter
// update gain functionality. // update gain functionality.
void RunFilterUpdateTest(int num_blocks_to_process, void RunFilterUpdateTest(const Environment& env,
int num_blocks_to_process,
size_t delay_samples, size_t delay_samples,
int filter_length_blocks, int filter_length_blocks,
const std::vector<int>& blocks_with_echo_path_changes, const std::vector<int>& blocks_with_echo_path_changes,
@ -89,7 +92,7 @@ void RunFilterUpdateTest(int num_blocks_to_process,
config.delay.default_delay = 1; config.delay.default_delay = 1;
std::unique_ptr<RenderDelayBuffer> render_delay_buffer( std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
RenderDelayBuffer::Create(config, kSampleRateHz, kNumRenderChannels)); RenderDelayBuffer::Create(config, kSampleRateHz, kNumRenderChannels));
AecState aec_state(config, kNumCaptureChannels); AecState aec_state(env, config, kNumCaptureChannels);
RenderSignalAnalyzer render_signal_analyzer(config); RenderSignalAnalyzer render_signal_analyzer(config);
std::optional<DelayEstimate> delay_estimate; std::optional<DelayEstimate> delay_estimate;
std::array<float, kFftLength> s_scratch; std::array<float, kFftLength> s_scratch;
@ -254,6 +257,7 @@ TEST(RefinedFilterUpdateGainDeathTest, NullDataOutputGain) {
// Verifies that the gain formed causes the filter using it to converge. // Verifies that the gain formed causes the filter using it to converge.
TEST(RefinedFilterUpdateGain, GainCausesFilterToConverge) { TEST(RefinedFilterUpdateGain, GainCausesFilterToConverge) {
const Environment env = CreateEnvironment();
std::vector<int> blocks_with_echo_path_changes; std::vector<int> blocks_with_echo_path_changes;
std::vector<int> blocks_with_saturation; std::vector<int> blocks_with_saturation;
for (size_t filter_length_blocks : {12, 20, 30}) { for (size_t filter_length_blocks : {12, 20, 30}) {
@ -264,7 +268,7 @@ TEST(RefinedFilterUpdateGain, GainCausesFilterToConverge) {
std::array<float, kBlockSize> y; std::array<float, kBlockSize> y;
FftData G; FftData G;
RunFilterUpdateTest(600, delay_samples, filter_length_blocks, RunFilterUpdateTest(env, 600, delay_samples, filter_length_blocks,
blocks_with_echo_path_changes, blocks_with_saturation, blocks_with_echo_path_changes, blocks_with_saturation,
false, &e, &y, &G); false, &e, &y, &G);
@ -284,6 +288,7 @@ TEST(RefinedFilterUpdateGain, GainCausesFilterToConverge) {
// Verifies that the magnitude of the gain on average decreases for a // Verifies that the magnitude of the gain on average decreases for a
// persistently exciting signal. // persistently exciting signal.
TEST(RefinedFilterUpdateGain, DecreasingGain) { TEST(RefinedFilterUpdateGain, DecreasingGain) {
const Environment env = CreateEnvironment();
std::vector<int> blocks_with_echo_path_changes; std::vector<int> blocks_with_echo_path_changes;
std::vector<int> blocks_with_saturation; std::vector<int> blocks_with_saturation;
@ -296,11 +301,11 @@ TEST(RefinedFilterUpdateGain, DecreasingGain) {
std::array<float, kFftLengthBy2Plus1> G_b_power; std::array<float, kFftLengthBy2Plus1> G_b_power;
std::array<float, kFftLengthBy2Plus1> G_c_power; std::array<float, kFftLengthBy2Plus1> G_c_power;
RunFilterUpdateTest(250, 65, 12, blocks_with_echo_path_changes, RunFilterUpdateTest(env, 250, 65, 12, blocks_with_echo_path_changes,
blocks_with_saturation, false, &e, &y, &G_a); blocks_with_saturation, false, &e, &y, &G_a);
RunFilterUpdateTest(500, 65, 12, blocks_with_echo_path_changes, RunFilterUpdateTest(env, 500, 65, 12, blocks_with_echo_path_changes,
blocks_with_saturation, false, &e, &y, &G_b); blocks_with_saturation, false, &e, &y, &G_b);
RunFilterUpdateTest(750, 65, 12, blocks_with_echo_path_changes, RunFilterUpdateTest(env, 750, 65, 12, blocks_with_echo_path_changes,
blocks_with_saturation, false, &e, &y, &G_c); blocks_with_saturation, false, &e, &y, &G_c);
G_a.Spectrum(Aec3Optimization::kNone, G_a_power); G_a.Spectrum(Aec3Optimization::kNone, G_a_power);
@ -317,6 +322,7 @@ TEST(RefinedFilterUpdateGain, DecreasingGain) {
// Verifies that the gain is zero when there is saturation and that the internal // Verifies that the gain is zero when there is saturation and that the internal
// error estimates cause the gain to increase after a period of saturation. // error estimates cause the gain to increase after a period of saturation.
TEST(RefinedFilterUpdateGain, SaturationBehavior) { TEST(RefinedFilterUpdateGain, SaturationBehavior) {
const Environment env = CreateEnvironment();
std::vector<int> blocks_with_echo_path_changes; std::vector<int> blocks_with_echo_path_changes;
std::vector<int> blocks_with_saturation; std::vector<int> blocks_with_saturation;
for (int k = 99; k < 200; ++k) { for (int k = 99; k < 200; ++k) {
@ -336,17 +342,17 @@ TEST(RefinedFilterUpdateGain, SaturationBehavior) {
std::array<float, kFftLengthBy2Plus1> G_a_power; std::array<float, kFftLengthBy2Plus1> G_a_power;
std::array<float, kFftLengthBy2Plus1> G_b_power; std::array<float, kFftLengthBy2Plus1> G_b_power;
RunFilterUpdateTest(100, 65, filter_length_blocks, RunFilterUpdateTest(env, 100, 65, filter_length_blocks,
blocks_with_echo_path_changes, blocks_with_saturation, blocks_with_echo_path_changes, blocks_with_saturation,
false, &e, &y, &G_a); false, &e, &y, &G_a);
EXPECT_EQ(G_a_ref.re, G_a.re); EXPECT_EQ(G_a_ref.re, G_a.re);
EXPECT_EQ(G_a_ref.im, G_a.im); EXPECT_EQ(G_a_ref.im, G_a.im);
RunFilterUpdateTest(99, 65, filter_length_blocks, RunFilterUpdateTest(env, 99, 65, filter_length_blocks,
blocks_with_echo_path_changes, blocks_with_saturation, blocks_with_echo_path_changes, blocks_with_saturation,
false, &e, &y, &G_a); false, &e, &y, &G_a);
RunFilterUpdateTest(201, 65, filter_length_blocks, RunFilterUpdateTest(env, 201, 65, filter_length_blocks,
blocks_with_echo_path_changes, blocks_with_saturation, blocks_with_echo_path_changes, blocks_with_saturation,
false, &e, &y, &G_b); false, &e, &y, &G_b);
@ -361,6 +367,7 @@ TEST(RefinedFilterUpdateGain, SaturationBehavior) {
// Verifies that the gain increases after an echo path change. // Verifies that the gain increases after an echo path change.
// TODO(peah): Correct and reactivate this test. // TODO(peah): Correct and reactivate this test.
TEST(RefinedFilterUpdateGain, DISABLED_EchoPathChangeBehavior) { TEST(RefinedFilterUpdateGain, DISABLED_EchoPathChangeBehavior) {
const Environment env = CreateEnvironment();
for (size_t filter_length_blocks : {12, 20, 30}) { for (size_t filter_length_blocks : {12, 20, 30}) {
SCOPED_TRACE(ProduceDebugText(filter_length_blocks)); SCOPED_TRACE(ProduceDebugText(filter_length_blocks));
std::vector<int> blocks_with_echo_path_changes; std::vector<int> blocks_with_echo_path_changes;
@ -374,10 +381,10 @@ TEST(RefinedFilterUpdateGain, DISABLED_EchoPathChangeBehavior) {
std::array<float, kFftLengthBy2Plus1> G_a_power; std::array<float, kFftLengthBy2Plus1> G_a_power;
std::array<float, kFftLengthBy2Plus1> G_b_power; std::array<float, kFftLengthBy2Plus1> G_b_power;
RunFilterUpdateTest(100, 65, filter_length_blocks, RunFilterUpdateTest(env, 100, 65, filter_length_blocks,
blocks_with_echo_path_changes, blocks_with_saturation, blocks_with_echo_path_changes, blocks_with_saturation,
false, &e, &y, &G_a); false, &e, &y, &G_a);
RunFilterUpdateTest(101, 65, filter_length_blocks, RunFilterUpdateTest(env, 101, 65, filter_length_blocks,
blocks_with_echo_path_changes, blocks_with_saturation, blocks_with_echo_path_changes, blocks_with_saturation,
false, &e, &y, &G_b); false, &e, &y, &G_b);

View File

@ -35,7 +35,6 @@
#include "modules/audio_processing/logging/apm_data_dumper.h" #include "modules/audio_processing/logging/apm_data_dumper.h"
#include "rtc_base/checks.h" #include "rtc_base/checks.h"
#include "rtc_base/logging.h" #include "rtc_base/logging.h"
#include "system_wrappers/include/field_trial.h"
namespace webrtc { namespace webrtc {
namespace { namespace {

View File

@ -16,9 +16,10 @@
#include <vector> #include <vector>
#include "api/array_view.h" #include "api/array_view.h"
#include "api/environment/environment.h"
#include "api/field_trials_view.h"
#include "modules/audio_processing/aec3/reverb_model.h" #include "modules/audio_processing/aec3/reverb_model.h"
#include "rtc_base/checks.h" #include "rtc_base/checks.h"
#include "system_wrappers/include/field_trial.h"
namespace webrtc { namespace webrtc {
namespace { namespace {
@ -30,25 +31,28 @@ float GetTransparentModeGain() {
} }
float GetEarlyReflectionsDefaultModeGain( float GetEarlyReflectionsDefaultModeGain(
const FieldTrialsView& field_trials,
const EchoCanceller3Config::EpStrength& config) { const EchoCanceller3Config::EpStrength& config) {
if (field_trial::IsEnabled("WebRTC-Aec3UseLowEarlyReflectionsDefaultGain")) { if (field_trials.IsEnabled("WebRTC-Aec3UseLowEarlyReflectionsDefaultGain")) {
return 0.1f; return 0.1f;
} }
return config.default_gain; return config.default_gain;
} }
float GetLateReflectionsDefaultModeGain( float GetLateReflectionsDefaultModeGain(
const FieldTrialsView& field_trials,
const EchoCanceller3Config::EpStrength& config) { const EchoCanceller3Config::EpStrength& config) {
if (field_trial::IsEnabled("WebRTC-Aec3UseLowLateReflectionsDefaultGain")) { if (field_trials.IsEnabled("WebRTC-Aec3UseLowLateReflectionsDefaultGain")) {
return 0.1f; return 0.1f;
} }
return config.default_gain; return config.default_gain;
} }
bool UseErleOnsetCompensationInDominantNearend( bool UseErleOnsetCompensationInDominantNearend(
const FieldTrialsView& field_trials,
const EchoCanceller3Config::EpStrength& config) { const EchoCanceller3Config::EpStrength& config) {
return config.erle_onset_compensation_in_dominant_nearend || return config.erle_onset_compensation_in_dominant_nearend ||
field_trial::IsEnabled( field_trials.IsEnabled(
"WebRTC-Aec3UseErleOnsetCompensationInDominantNearend"); "WebRTC-Aec3UseErleOnsetCompensationInDominantNearend");
} }
@ -154,18 +158,22 @@ void EchoGeneratingPower(size_t num_render_channels,
} // namespace } // namespace
ResidualEchoEstimator::ResidualEchoEstimator(const EchoCanceller3Config& config, ResidualEchoEstimator::ResidualEchoEstimator(const Environment& env,
const EchoCanceller3Config& config,
size_t num_render_channels) size_t num_render_channels)
: config_(config), : config_(config),
num_render_channels_(num_render_channels), num_render_channels_(num_render_channels),
early_reflections_transparent_mode_gain_(GetTransparentModeGain()), early_reflections_transparent_mode_gain_(GetTransparentModeGain()),
late_reflections_transparent_mode_gain_(GetTransparentModeGain()), late_reflections_transparent_mode_gain_(GetTransparentModeGain()),
early_reflections_general_gain_( early_reflections_general_gain_(
GetEarlyReflectionsDefaultModeGain(config_.ep_strength)), GetEarlyReflectionsDefaultModeGain(env.field_trials(),
config_.ep_strength)),
late_reflections_general_gain_( late_reflections_general_gain_(
GetLateReflectionsDefaultModeGain(config_.ep_strength)), GetLateReflectionsDefaultModeGain(env.field_trials(),
config_.ep_strength)),
erle_onset_compensation_in_dominant_nearend_( erle_onset_compensation_in_dominant_nearend_(
UseErleOnsetCompensationInDominantNearend(config_.ep_strength)) { UseErleOnsetCompensationInDominantNearend(env.field_trials(),
config_.ep_strength)) {
Reset(); Reset();
} }

View File

@ -16,6 +16,7 @@
#include <optional> #include <optional>
#include "api/audio/echo_canceller3_config.h" #include "api/audio/echo_canceller3_config.h"
#include "api/environment/environment.h"
#include "modules/audio_processing/aec3/aec3_common.h" #include "modules/audio_processing/aec3/aec3_common.h"
#include "modules/audio_processing/aec3/aec_state.h" #include "modules/audio_processing/aec3/aec_state.h"
#include "modules/audio_processing/aec3/render_buffer.h" #include "modules/audio_processing/aec3/render_buffer.h"
@ -27,7 +28,8 @@ namespace webrtc {
class ResidualEchoEstimator { class ResidualEchoEstimator {
public: public:
ResidualEchoEstimator(const EchoCanceller3Config& config, ResidualEchoEstimator(const Environment& env,
const EchoCanceller3Config& config,
size_t num_render_channels); size_t num_render_channels);
~ResidualEchoEstimator(); ~ResidualEchoEstimator();

View File

@ -13,6 +13,8 @@
#include <numeric> #include <numeric>
#include "api/audio/echo_canceller3_config.h" #include "api/audio/echo_canceller3_config.h"
#include "api/environment/environment.h"
#include "api/environment/environment_factory.h"
#include "modules/audio_processing/aec3/aec3_fft.h" #include "modules/audio_processing/aec3/aec3_fft.h"
#include "modules/audio_processing/aec3/aec_state.h" #include "modules/audio_processing/aec3/aec_state.h"
#include "modules/audio_processing/aec3/render_delay_buffer.h" #include "modules/audio_processing/aec3/render_delay_buffer.h"
@ -37,8 +39,8 @@ class ResidualEchoEstimatorTest {
: num_render_channels_(num_render_channels), : num_render_channels_(num_render_channels),
num_capture_channels_(num_capture_channels), num_capture_channels_(num_capture_channels),
config_(config), config_(config),
estimator_(config_, num_render_channels_), estimator_(env_, config_, num_render_channels_),
aec_state_(config_, num_capture_channels_), aec_state_(env_, config_, num_capture_channels_),
render_delay_buffer_(RenderDelayBuffer::Create(config_, render_delay_buffer_(RenderDelayBuffer::Create(config_,
kSampleRateHz, kSampleRateHz,
num_render_channels_)), num_render_channels_)),
@ -105,6 +107,7 @@ class ResidualEchoEstimatorTest {
private: private:
const size_t num_render_channels_; const size_t num_render_channels_;
const size_t num_capture_channels_; const size_t num_capture_channels_;
const Environment env_ = CreateEnvironment();
const EchoCanceller3Config& config_; const EchoCanceller3Config& config_;
ResidualEchoEstimator estimator_; ResidualEchoEstimator estimator_;
AecState aec_state_; AecState aec_state_;

View File

@ -13,9 +13,10 @@
#include <algorithm> #include <algorithm>
#include <functional> #include <functional>
#include "api/environment/environment.h"
#include "api/field_trials_view.h"
#include "rtc_base/checks.h" #include "rtc_base/checks.h"
#include "rtc_base/numerics/safe_minmax.h" #include "rtc_base/numerics/safe_minmax.h"
#include "system_wrappers/include/field_trial.h"
namespace webrtc { namespace webrtc {
@ -34,18 +35,20 @@ std::array<float, kFftLengthBy2Plus1> SetMaxErleBands(float max_erle_l,
return max_erle; return max_erle;
} }
bool EnableMinErleDuringOnsets() { bool EnableMinErleDuringOnsets(const FieldTrialsView& field_trials) {
return !field_trial::IsEnabled("WebRTC-Aec3MinErleDuringOnsetsKillSwitch"); return !field_trials.IsEnabled("WebRTC-Aec3MinErleDuringOnsetsKillSwitch");
} }
} // namespace } // namespace
SubbandErleEstimator::SubbandErleEstimator(const EchoCanceller3Config& config, SubbandErleEstimator::SubbandErleEstimator(const Environment& env,
const EchoCanceller3Config& config,
size_t num_capture_channels) size_t num_capture_channels)
: use_onset_detection_(config.erle.onset_detection), : use_onset_detection_(config.erle.onset_detection),
min_erle_(config.erle.min), min_erle_(config.erle.min),
max_erle_(SetMaxErleBands(config.erle.max_l, config.erle.max_h)), max_erle_(SetMaxErleBands(config.erle.max_l, config.erle.max_h)),
use_min_erle_during_onsets_(EnableMinErleDuringOnsets()), use_min_erle_during_onsets_(
EnableMinErleDuringOnsets(env.field_trials())),
accum_spectra_(num_capture_channels), accum_spectra_(num_capture_channels),
erle_(num_capture_channels), erle_(num_capture_channels),
erle_onset_compensated_(num_capture_channels), erle_onset_compensated_(num_capture_channels),

View File

@ -19,6 +19,7 @@
#include "api/array_view.h" #include "api/array_view.h"
#include "api/audio/echo_canceller3_config.h" #include "api/audio/echo_canceller3_config.h"
#include "api/environment/environment.h"
#include "modules/audio_processing/aec3/aec3_common.h" #include "modules/audio_processing/aec3/aec3_common.h"
#include "modules/audio_processing/logging/apm_data_dumper.h" #include "modules/audio_processing/logging/apm_data_dumper.h"
@ -27,7 +28,8 @@ namespace webrtc {
// Estimates the echo return loss enhancement for each frequency subband. // Estimates the echo return loss enhancement for each frequency subband.
class SubbandErleEstimator { class SubbandErleEstimator {
public: public:
SubbandErleEstimator(const EchoCanceller3Config& config, SubbandErleEstimator(const Environment& env,
const EchoCanceller3Config& config,
size_t num_capture_channels); size_t num_capture_channels);
~SubbandErleEstimator(); ~SubbandErleEstimator();

View File

@ -14,19 +14,20 @@
#include <utility> #include <utility>
#include "api/array_view.h" #include "api/array_view.h"
#include "api/environment/environment.h"
#include "api/field_trials_view.h"
#include "modules/audio_processing/aec3/adaptive_fir_filter_erl.h" #include "modules/audio_processing/aec3/adaptive_fir_filter_erl.h"
#include "modules/audio_processing/aec3/fft_data.h" #include "modules/audio_processing/aec3/fft_data.h"
#include "modules/audio_processing/logging/apm_data_dumper.h" #include "modules/audio_processing/logging/apm_data_dumper.h"
#include "rtc_base/checks.h" #include "rtc_base/checks.h"
#include "rtc_base/numerics/safe_minmax.h" #include "rtc_base/numerics/safe_minmax.h"
#include "system_wrappers/include/field_trial.h"
namespace webrtc { namespace webrtc {
namespace { namespace {
bool UseCoarseFilterResetHangover() { bool UseCoarseFilterResetHangover(const FieldTrialsView& field_trials) {
return !field_trial::IsEnabled( return !field_trials.IsEnabled(
"WebRTC-Aec3CoarseFilterResetHangoverKillSwitch"); "WebRTC-Aec3CoarseFilterResetHangoverKillSwitch");
} }
@ -62,7 +63,8 @@ void ScaleFilterOutput(rtc::ArrayView<const float> y,
} // namespace } // namespace
Subtractor::Subtractor(const EchoCanceller3Config& config, Subtractor::Subtractor(const Environment& env,
const EchoCanceller3Config& config,
size_t num_render_channels, size_t num_render_channels,
size_t num_capture_channels, size_t num_capture_channels,
ApmDataDumper* data_dumper, ApmDataDumper* data_dumper,
@ -72,7 +74,8 @@ Subtractor::Subtractor(const EchoCanceller3Config& config,
optimization_(optimization), optimization_(optimization),
config_(config), config_(config),
num_capture_channels_(num_capture_channels), num_capture_channels_(num_capture_channels),
use_coarse_filter_reset_hangover_(UseCoarseFilterResetHangover()), use_coarse_filter_reset_hangover_(
UseCoarseFilterResetHangover(env.field_trials())),
refined_filters_(num_capture_channels_), refined_filters_(num_capture_channels_),
coarse_filter_(num_capture_channels_), coarse_filter_(num_capture_channels_),
refined_gains_(num_capture_channels_), refined_gains_(num_capture_channels_),

View File

@ -19,6 +19,7 @@
#include "api/array_view.h" #include "api/array_view.h"
#include "api/audio/echo_canceller3_config.h" #include "api/audio/echo_canceller3_config.h"
#include "api/environment/environment.h"
#include "modules/audio_processing/aec3/adaptive_fir_filter.h" #include "modules/audio_processing/aec3/adaptive_fir_filter.h"
#include "modules/audio_processing/aec3/aec3_common.h" #include "modules/audio_processing/aec3/aec3_common.h"
#include "modules/audio_processing/aec3/aec3_fft.h" #include "modules/audio_processing/aec3/aec3_fft.h"
@ -38,7 +39,8 @@ namespace webrtc {
// Proves linear echo cancellation functionality // Proves linear echo cancellation functionality
class Subtractor { class Subtractor {
public: public:
Subtractor(const EchoCanceller3Config& config, Subtractor(const Environment& env,
const EchoCanceller3Config& config,
size_t num_render_channels, size_t num_render_channels,
size_t num_capture_channels, size_t num_capture_channels,
ApmDataDumper* data_dumper, ApmDataDumper* data_dumper,

View File

@ -15,6 +15,8 @@
#include <numeric> #include <numeric>
#include <string> #include <string>
#include "api/environment/environment.h"
#include "api/environment/environment_factory.h"
#include "modules/audio_processing/aec3/aec_state.h" #include "modules/audio_processing/aec3/aec_state.h"
#include "modules/audio_processing/aec3/render_delay_buffer.h" #include "modules/audio_processing/aec3/render_delay_buffer.h"
#include "modules/audio_processing/test/echo_canceller_test_tools.h" #include "modules/audio_processing/test/echo_canceller_test_tools.h"
@ -27,6 +29,7 @@ namespace webrtc {
namespace { namespace {
std::vector<float> RunSubtractorTest( std::vector<float> RunSubtractorTest(
const Environment& env,
size_t num_render_channels, size_t num_render_channels,
size_t num_capture_channels, size_t num_capture_channels,
int num_blocks_to_process, int num_blocks_to_process,
@ -42,7 +45,7 @@ std::vector<float> RunSubtractorTest(
config.filter.refined.length_blocks = refined_filter_length_blocks; config.filter.refined.length_blocks = refined_filter_length_blocks;
config.filter.coarse.length_blocks = coarse_filter_length_blocks; config.filter.coarse.length_blocks = coarse_filter_length_blocks;
Subtractor subtractor(config, num_render_channels, num_capture_channels, Subtractor subtractor(env, config, num_render_channels, num_capture_channels,
&data_dumper, DetectOptimization()); &data_dumper, DetectOptimization());
std::optional<DelayEstimate> delay_estimate; std::optional<DelayEstimate> delay_estimate;
Block x(kNumBands, num_render_channels); Block x(kNumBands, num_render_channels);
@ -59,7 +62,7 @@ std::vector<float> RunSubtractorTest(
std::vector<std::array<float, kFftLengthBy2Plus1>> E2_refined( std::vector<std::array<float, kFftLengthBy2Plus1>> E2_refined(
num_capture_channels); num_capture_channels);
std::array<float, kFftLengthBy2Plus1> E2_coarse; std::array<float, kFftLengthBy2Plus1> E2_coarse;
AecState aec_state(config, num_capture_channels); AecState aec_state(env, config, num_capture_channels);
x_old.fill(0.f); x_old.fill(0.f);
for (auto& Y2_ch : Y2) { for (auto& Y2_ch : Y2) {
Y2_ch.fill(0.f); Y2_ch.fill(0.f);
@ -190,22 +193,23 @@ std::string ProduceDebugText(size_t num_render_channels,
// Verifies that the check for non data dumper works. // Verifies that the check for non data dumper works.
TEST(SubtractorDeathTest, NullDataDumper) { TEST(SubtractorDeathTest, NullDataDumper) {
EXPECT_DEATH( EXPECT_DEATH(Subtractor(CreateEnvironment(), EchoCanceller3Config(), 1, 1,
Subtractor(EchoCanceller3Config(), 1, 1, nullptr, DetectOptimization()), nullptr, DetectOptimization()),
""); "");
} }
#endif #endif
// Verifies that the subtractor is able to converge on correlated data. // Verifies that the subtractor is able to converge on correlated data.
TEST(Subtractor, Convergence) { TEST(Subtractor, Convergence) {
const Environment env = CreateEnvironment();
std::vector<int> blocks_with_echo_path_changes; std::vector<int> blocks_with_echo_path_changes;
for (size_t filter_length_blocks : {12, 20, 30}) { for (size_t filter_length_blocks : {12, 20, 30}) {
for (size_t delay_samples : {0, 64, 150, 200, 301}) { for (size_t delay_samples : {0, 64, 150, 200, 301}) {
SCOPED_TRACE(ProduceDebugText(1, 1, delay_samples, filter_length_blocks)); SCOPED_TRACE(ProduceDebugText(1, 1, delay_samples, filter_length_blocks));
std::vector<float> echo_to_nearend_powers = RunSubtractorTest( std::vector<float> echo_to_nearend_powers = RunSubtractorTest(
1, 1, 2500, delay_samples, filter_length_blocks, filter_length_blocks, env, 1, 1, 2500, delay_samples, filter_length_blocks,
false, blocks_with_echo_path_changes); filter_length_blocks, false, blocks_with_echo_path_changes);
for (float echo_to_nearend_power : echo_to_nearend_powers) { for (float echo_to_nearend_power : echo_to_nearend_powers) {
EXPECT_GT(0.1f, echo_to_nearend_power); EXPECT_GT(0.1f, echo_to_nearend_power);
@ -217,9 +221,10 @@ TEST(Subtractor, Convergence) {
// Verifies that the subtractor is able to handle the case when the refined // Verifies that the subtractor is able to handle the case when the refined
// filter is longer than the coarse filter. // filter is longer than the coarse filter.
TEST(Subtractor, RefinedFilterLongerThanCoarseFilter) { TEST(Subtractor, RefinedFilterLongerThanCoarseFilter) {
const Environment env = CreateEnvironment();
std::vector<int> blocks_with_echo_path_changes; std::vector<int> blocks_with_echo_path_changes;
std::vector<float> echo_to_nearend_powers = RunSubtractorTest( std::vector<float> echo_to_nearend_powers = RunSubtractorTest(
1, 1, 400, 64, 20, 15, false, blocks_with_echo_path_changes); env, 1, 1, 400, 64, 20, 15, false, blocks_with_echo_path_changes);
for (float echo_to_nearend_power : echo_to_nearend_powers) { for (float echo_to_nearend_power : echo_to_nearend_powers) {
EXPECT_GT(0.5f, echo_to_nearend_power); EXPECT_GT(0.5f, echo_to_nearend_power);
} }
@ -228,9 +233,10 @@ TEST(Subtractor, RefinedFilterLongerThanCoarseFilter) {
// Verifies that the subtractor is able to handle the case when the coarse // Verifies that the subtractor is able to handle the case when the coarse
// filter is longer than the refined filter. // filter is longer than the refined filter.
TEST(Subtractor, CoarseFilterLongerThanRefinedFilter) { TEST(Subtractor, CoarseFilterLongerThanRefinedFilter) {
const Environment env = CreateEnvironment();
std::vector<int> blocks_with_echo_path_changes; std::vector<int> blocks_with_echo_path_changes;
std::vector<float> echo_to_nearend_powers = RunSubtractorTest( std::vector<float> echo_to_nearend_powers = RunSubtractorTest(
1, 1, 400, 64, 15, 20, false, blocks_with_echo_path_changes); env, 1, 1, 400, 64, 15, 20, false, blocks_with_echo_path_changes);
for (float echo_to_nearend_power : echo_to_nearend_powers) { for (float echo_to_nearend_power : echo_to_nearend_powers) {
EXPECT_GT(0.5f, echo_to_nearend_power); EXPECT_GT(0.5f, echo_to_nearend_power);
} }
@ -238,14 +244,15 @@ TEST(Subtractor, CoarseFilterLongerThanRefinedFilter) {
// Verifies that the subtractor does not converge on uncorrelated signals. // Verifies that the subtractor does not converge on uncorrelated signals.
TEST(Subtractor, NonConvergenceOnUncorrelatedSignals) { TEST(Subtractor, NonConvergenceOnUncorrelatedSignals) {
const Environment env = CreateEnvironment();
std::vector<int> blocks_with_echo_path_changes; std::vector<int> blocks_with_echo_path_changes;
for (size_t filter_length_blocks : {12, 20, 30}) { for (size_t filter_length_blocks : {12, 20, 30}) {
for (size_t delay_samples : {0, 64, 150, 200, 301}) { for (size_t delay_samples : {0, 64, 150, 200, 301}) {
SCOPED_TRACE(ProduceDebugText(1, 1, delay_samples, filter_length_blocks)); SCOPED_TRACE(ProduceDebugText(1, 1, delay_samples, filter_length_blocks));
std::vector<float> echo_to_nearend_powers = RunSubtractorTest( std::vector<float> echo_to_nearend_powers = RunSubtractorTest(
1, 1, 3000, delay_samples, filter_length_blocks, filter_length_blocks, env, 1, 1, 3000, delay_samples, filter_length_blocks,
true, blocks_with_echo_path_changes); filter_length_blocks, true, blocks_with_echo_path_changes);
for (float echo_to_nearend_power : echo_to_nearend_powers) { for (float echo_to_nearend_power : echo_to_nearend_powers) {
EXPECT_NEAR(1.f, echo_to_nearend_power, 0.1); EXPECT_NEAR(1.f, echo_to_nearend_power, 0.1);
} }
@ -273,12 +280,13 @@ INSTANTIATE_TEST_SUITE_P(DebugMultiChannel,
TEST_P(SubtractorMultiChannelUpToEightRender, Convergence) { TEST_P(SubtractorMultiChannelUpToEightRender, Convergence) {
const size_t num_render_channels = std::get<0>(GetParam()); const size_t num_render_channels = std::get<0>(GetParam());
const size_t num_capture_channels = std::get<1>(GetParam()); const size_t num_capture_channels = std::get<1>(GetParam());
const Environment env = CreateEnvironment();
std::vector<int> blocks_with_echo_path_changes; std::vector<int> blocks_with_echo_path_changes;
size_t num_blocks_to_process = 2500 * num_render_channels; size_t num_blocks_to_process = 2500 * num_render_channels;
std::vector<float> echo_to_nearend_powers = RunSubtractorTest( std::vector<float> echo_to_nearend_powers = RunSubtractorTest(
num_render_channels, num_capture_channels, num_blocks_to_process, 64, 20, env, num_render_channels, num_capture_channels, num_blocks_to_process, 64,
20, false, blocks_with_echo_path_changes); 20, 20, false, blocks_with_echo_path_changes);
for (float echo_to_nearend_power : echo_to_nearend_powers) { for (float echo_to_nearend_power : echo_to_nearend_powers) {
EXPECT_GT(0.1f, echo_to_nearend_power); EXPECT_GT(0.1f, echo_to_nearend_power);
@ -306,12 +314,13 @@ TEST_P(SubtractorMultiChannelUpToFourRender,
NonConvergenceOnUncorrelatedSignals) { NonConvergenceOnUncorrelatedSignals) {
const size_t num_render_channels = std::get<0>(GetParam()); const size_t num_render_channels = std::get<0>(GetParam());
const size_t num_capture_channels = std::get<1>(GetParam()); const size_t num_capture_channels = std::get<1>(GetParam());
const Environment env = CreateEnvironment();
std::vector<int> blocks_with_echo_path_changes; std::vector<int> blocks_with_echo_path_changes;
size_t num_blocks_to_process = 5000 * num_render_channels; size_t num_blocks_to_process = 5000 * num_render_channels;
std::vector<float> echo_to_nearend_powers = RunSubtractorTest( std::vector<float> echo_to_nearend_powers = RunSubtractorTest(
num_render_channels, num_capture_channels, num_blocks_to_process, 64, 20, env, num_render_channels, num_capture_channels, num_blocks_to_process, 64,
20, true, blocks_with_echo_path_changes); 20, 20, true, blocks_with_echo_path_changes);
for (float echo_to_nearend_power : echo_to_nearend_powers) { for (float echo_to_nearend_power : echo_to_nearend_powers) {
EXPECT_LT(.8f, echo_to_nearend_power); EXPECT_LT(.8f, echo_to_nearend_power);
EXPECT_NEAR(1.f, echo_to_nearend_power, 0.25f); EXPECT_NEAR(1.f, echo_to_nearend_power, 0.25f);

View File

@ -22,7 +22,6 @@
#include "modules/audio_processing/aec3/vector_math.h" #include "modules/audio_processing/aec3/vector_math.h"
#include "modules/audio_processing/logging/apm_data_dumper.h" #include "modules/audio_processing/logging/apm_data_dumper.h"
#include "rtc_base/checks.h" #include "rtc_base/checks.h"
#include "system_wrappers/include/field_trial.h"
namespace webrtc { namespace webrtc {
namespace { namespace {

View File

@ -10,6 +10,8 @@
#include "modules/audio_processing/aec3/suppression_gain.h" #include "modules/audio_processing/aec3/suppression_gain.h"
#include "api/environment/environment.h"
#include "api/environment/environment_factory.h"
#include "modules/audio_processing/aec3/aec_state.h" #include "modules/audio_processing/aec3/aec_state.h"
#include "modules/audio_processing/aec3/render_delay_buffer.h" #include "modules/audio_processing/aec3/render_delay_buffer.h"
#include "modules/audio_processing/aec3/subtractor.h" #include "modules/audio_processing/aec3/subtractor.h"
@ -42,7 +44,7 @@ TEST(SuppressionGainDeathTest, NullOutputGains) {
Y.im.fill(0.0f); Y.im.fill(0.0f);
float high_bands_gain; float high_bands_gain;
AecState aec_state(EchoCanceller3Config{}, 1); AecState aec_state(CreateEnvironment(), EchoCanceller3Config{}, 1);
EXPECT_DEATH( EXPECT_DEATH(
SuppressionGain(EchoCanceller3Config{}, DetectOptimization(), 16000, 1) SuppressionGain(EchoCanceller3Config{}, DetectOptimization(), 16000, 1)
.GetGain(E2, S2, R2, R2_unbounded, N2, .GetGain(E2, S2, R2, R2_unbounded, N2,
@ -74,10 +76,11 @@ TEST(SuppressionGain, BasicGainComputation) {
std::array<float, kFftLengthBy2Plus1> g; std::array<float, kFftLengthBy2Plus1> g;
std::vector<SubtractorOutput> output(kNumCaptureChannels); std::vector<SubtractorOutput> output(kNumCaptureChannels);
Block x(kNumBands, kNumRenderChannels); Block x(kNumBands, kNumRenderChannels);
const Environment env = CreateEnvironment();
EchoCanceller3Config config; EchoCanceller3Config config;
AecState aec_state(config, kNumCaptureChannels); AecState aec_state(env, config, kNumCaptureChannels);
ApmDataDumper data_dumper(42); ApmDataDumper data_dumper(42);
Subtractor subtractor(config, kNumRenderChannels, kNumCaptureChannels, Subtractor subtractor(env, config, kNumRenderChannels, kNumCaptureChannels,
&data_dumper, DetectOptimization()); &data_dumper, DetectOptimization());
std::unique_ptr<RenderDelayBuffer> render_delay_buffer( std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
RenderDelayBuffer::Create(config, kSampleRateHz, kNumRenderChannels)); RenderDelayBuffer::Create(config, kSampleRateHz, kNumRenderChannels));

View File

@ -10,9 +10,10 @@
#include "modules/audio_processing/aec3/transparent_mode.h" #include "modules/audio_processing/aec3/transparent_mode.h"
#include "api/environment/environment.h"
#include "api/field_trials_view.h"
#include "rtc_base/checks.h" #include "rtc_base/checks.h"
#include "rtc_base/logging.h" #include "rtc_base/logging.h"
#include "system_wrappers/include/field_trial.h"
namespace webrtc { namespace webrtc {
namespace { namespace {
@ -21,12 +22,12 @@ constexpr size_t kBlocksSinceConvergencedFilterInit = 10000;
constexpr size_t kBlocksSinceConsistentEstimateInit = 10000; constexpr size_t kBlocksSinceConsistentEstimateInit = 10000;
constexpr float kInitialTransparentStateProbability = 0.2f; constexpr float kInitialTransparentStateProbability = 0.2f;
bool DeactivateTransparentMode() { bool DeactivateTransparentMode(const FieldTrialsView& field_trials) {
return field_trial::IsEnabled("WebRTC-Aec3TransparentModeKillSwitch"); return field_trials.IsEnabled("WebRTC-Aec3TransparentModeKillSwitch");
} }
bool ActivateTransparentModeHmm() { bool ActivateTransparentModeHmm(const FieldTrialsView& field_trials) {
return field_trial::IsEnabled("WebRTC-Aec3TransparentModeHmm"); return field_trials.IsEnabled("WebRTC-Aec3TransparentModeHmm");
} }
} // namespace } // namespace
@ -228,12 +229,14 @@ class LegacyTransparentModeImpl : public TransparentMode {
}; };
std::unique_ptr<TransparentMode> TransparentMode::Create( std::unique_ptr<TransparentMode> TransparentMode::Create(
const Environment& env,
const EchoCanceller3Config& config) { const EchoCanceller3Config& config) {
if (config.ep_strength.bounded_erl || DeactivateTransparentMode()) { if (config.ep_strength.bounded_erl ||
DeactivateTransparentMode(env.field_trials())) {
RTC_LOG(LS_INFO) << "AEC3 Transparent Mode: Disabled"; RTC_LOG(LS_INFO) << "AEC3 Transparent Mode: Disabled";
return nullptr; return nullptr;
} }
if (ActivateTransparentModeHmm()) { if (ActivateTransparentModeHmm(env.field_trials())) {
RTC_LOG(LS_INFO) << "AEC3 Transparent Mode: HMM"; RTC_LOG(LS_INFO) << "AEC3 Transparent Mode: HMM";
return std::make_unique<TransparentModeImpl>(); return std::make_unique<TransparentModeImpl>();
} }

View File

@ -14,6 +14,7 @@
#include <memory> #include <memory>
#include "api/audio/echo_canceller3_config.h" #include "api/audio/echo_canceller3_config.h"
#include "api/environment/environment.h"
#include "modules/audio_processing/aec3/aec3_common.h" #include "modules/audio_processing/aec3/aec3_common.h"
namespace webrtc { namespace webrtc {
@ -23,6 +24,7 @@ namespace webrtc {
class TransparentMode { class TransparentMode {
public: public:
static std::unique_ptr<TransparentMode> Create( static std::unique_ptr<TransparentMode> Create(
const Environment& env,
const EchoCanceller3Config& config); const EchoCanceller3Config& config);
virtual ~TransparentMode() {} virtual ~TransparentMode() {}

View File

@ -19,7 +19,6 @@
#include "modules/audio_processing/logging/apm_data_dumper.h" #include "modules/audio_processing/logging/apm_data_dumper.h"
#include "rtc_base/checks.h" #include "rtc_base/checks.h"
#include "rtc_base/logging.h" #include "rtc_base/logging.h"
#include "system_wrappers/include/field_trial.h"
namespace webrtc { namespace webrtc {