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",
"../../system_wrappers",
"../../system_wrappers:denormal_disabler",
"../../system_wrappers:field_trial",
"../../system_wrappers:metrics",
"aec3",
"aec_dump",

View File

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

View File

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

View File

@ -18,25 +18,28 @@
#include <vector>
#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/logging/apm_data_dumper.h"
#include "rtc_base/checks.h"
#include "system_wrappers/include/field_trial.h"
namespace webrtc {
namespace {
bool DeactivateInitialStateResetAtEchoPathChange() {
return field_trial::IsEnabled(
bool DeactivateInitialStateResetAtEchoPathChange(
const FieldTrialsView& field_trials) {
return field_trials.IsEnabled(
"WebRTC-Aec3DeactivateInitialStateResetKillSwitch");
}
bool FullResetAtEchoPathChange() {
return !field_trial::IsEnabled("WebRTC-Aec3AecStateFullResetKillSwitch");
bool FullResetAtEchoPathChange(const FieldTrialsView& field_trials) {
return !field_trials.IsEnabled("WebRTC-Aec3AecStateFullResetKillSwitch");
}
bool SubtractorAnalyzerResetAtEchoPathChange() {
return !field_trial::IsEnabled(
bool SubtractorAnalyzerResetAtEchoPathChange(
const FieldTrialsView& field_trials) {
return !field_trials.IsEnabled(
"WebRTC-Aec3AecStateSubtractorAnalyzerResetKillSwitch");
}
@ -112,22 +115,27 @@ void AecState::GetResidualEchoScaling(
residual_scaling);
}
AecState::AecState(const EchoCanceller3Config& config,
AecState::AecState(const Environment& env,
const EchoCanceller3Config& config,
size_t num_capture_channels)
: data_dumper_(new ApmDataDumper(instance_count_.fetch_add(1) + 1)),
config_(config),
num_capture_channels_(num_capture_channels),
deactivate_initial_state_reset_at_echo_path_change_(
DeactivateInitialStateResetAtEchoPathChange()),
full_reset_at_echo_path_change_(FullResetAtEchoPathChange()),
DeactivateInitialStateResetAtEchoPathChange(env.field_trials())),
full_reset_at_echo_path_change_(
FullResetAtEchoPathChange(env.field_trials())),
subtractor_analyzer_reset_at_echo_path_change_(
SubtractorAnalyzerResetAtEchoPathChange()),
SubtractorAnalyzerResetAtEchoPathChange(env.field_trials())),
initial_state_(config_),
delay_state_(config_, num_capture_channels_),
transparent_state_(TransparentMode::Create(config_)),
transparent_state_(TransparentMode::Create(env, config_)),
filter_quality_state_(config_, num_capture_channels_),
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_),
echo_audibility_(
config_.echo_audibility.use_stationarity_properties_at_init),

View File

@ -21,6 +21,7 @@
#include "api/array_view.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/delay_estimate.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.
class AecState {
public:
AecState(const EchoCanceller3Config& config, size_t num_capture_channels);
AecState(const Environment& env,
const EchoCanceller3Config& config,
size_t num_capture_channels);
~AecState();
// 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 "api/environment/environment.h"
#include "api/environment/environment_factory.h"
#include "modules/audio_processing/aec3/aec3_fft.h"
#include "modules/audio_processing/aec3/render_delay_buffer.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);
ApmDataDumper data_dumper(42);
EchoCanceller3Config config;
AecState state(config, num_capture_channels);
AecState state(CreateEnvironment(), config, num_capture_channels);
std::optional<DelayEstimate> delay_estimate =
DelayEstimate(DelayEstimate::Quality::kRefined, 10);
std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
@ -244,7 +246,7 @@ TEST(AecState, ConvergedFilterDelay) {
constexpr int kFilterLengthBlocks = 10;
constexpr size_t kNumCaptureChannels = 1;
EchoCanceller3Config config;
AecState state(config, kNumCaptureChannels);
AecState state(CreateEnvironment(), config, kNumCaptureChannels);
std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
RenderDelayBuffer::Create(config, 48000, 1));
std::optional<DelayEstimate> delay_estimate;

View File

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

View File

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

View File

@ -14,6 +14,8 @@
#include <string>
#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/mock/mock_echo_remover.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
// 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 kNumCaptureChannels = 1;
std::unique_ptr<BlockProcessor> block_processor(
BlockProcessor::Create(EchoCanceller3Config(), sample_rate_hz,
kNumRenderChannels, kNumCaptureChannels));
std::unique_ptr<BlockProcessor> block_processor =
BlockProcessor::Create(env, EchoCanceller3Config(), sample_rate_hz,
kNumRenderChannels, kNumCaptureChannels);
Block block(NumBandsForRate(sample_rate_hz), kNumRenderChannels, 1000.f);
for (int k = 0; k < num_iterations; ++k) {
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)
void RunRenderBlockSizeVerificationTest(int sample_rate_hz) {
void RunRenderBlockSizeVerificationTest(const Environment& env,
int sample_rate_hz) {
constexpr size_t kNumRenderChannels = 1;
constexpr size_t kNumCaptureChannels = 1;
std::unique_ptr<BlockProcessor> block_processor(
BlockProcessor::Create(EchoCanceller3Config(), sample_rate_hz,
kNumRenderChannels, kNumCaptureChannels));
std::unique_ptr<BlockProcessor> block_processor =
BlockProcessor::Create(env, EchoCanceller3Config(), sample_rate_hz,
kNumRenderChannels, kNumCaptureChannels);
Block block(NumBandsForRate(sample_rate_hz), kNumRenderChannels);
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 kNumCaptureChannels = 1;
const size_t wrong_num_bands = NumBandsForRate(sample_rate_hz) < 3
? NumBandsForRate(sample_rate_hz) + 1
: 1;
std::unique_ptr<BlockProcessor> block_processor(
BlockProcessor::Create(EchoCanceller3Config(), sample_rate_hz,
kNumRenderChannels, kNumCaptureChannels));
std::unique_ptr<BlockProcessor> block_processor =
BlockProcessor::Create(env, EchoCanceller3Config(), sample_rate_hz,
kNumRenderChannels, kNumCaptureChannels);
Block block(wrong_num_bands, kNumRenderChannels);
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 kNumCaptureChannels = 1;
const size_t wrong_num_bands = NumBandsForRate(sample_rate_hz) < 3
? NumBandsForRate(sample_rate_hz) + 1
: 1;
std::unique_ptr<BlockProcessor> block_processor(
BlockProcessor::Create(EchoCanceller3Config(), sample_rate_hz,
kNumRenderChannels, kNumCaptureChannels));
std::unique_ptr<BlockProcessor> block_processor =
BlockProcessor::Create(env, EchoCanceller3Config(), sample_rate_hz,
kNumRenderChannels, kNumCaptureChannels);
Block block(wrong_num_bands, kNumRenderChannels);
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 kDelayInBlocks =
kDelayInSamples / kBlockSize - kDelayHeadroom;
const Environment env = CreateEnvironment();
Random random_generator(42U);
for (auto rate : {16000, 32000, 48000}) {
SCOPED_TRACE(ProduceDebugText(rate));
@ -138,9 +146,9 @@ TEST(BlockProcessor, DISABLED_DelayControllerIntegration) {
EXPECT_CALL(*render_delay_buffer_mock, Delay())
.Times(kNumBlocks + 1)
.WillRepeatedly(Return(0));
std::unique_ptr<BlockProcessor> block_processor(BlockProcessor::Create(
EchoCanceller3Config(), rate, kNumRenderChannels, kNumCaptureChannels,
std::move(render_delay_buffer_mock)));
std::unique_ptr<BlockProcessor> block_processor = BlockProcessor::Create(
env, EchoCanceller3Config(), rate, kNumRenderChannels,
kNumCaptureChannels, std::move(render_delay_buffer_mock));
Block render_block(NumBandsForRate(rate), kNumRenderChannels);
Block capture_block(NumBandsForRate(rate), kNumCaptureChannels);
@ -212,46 +220,51 @@ TEST(BlockProcessor, DISABLED_SubmoduleIntegration) {
}
TEST(BlockProcessor, BasicSetupAndApiCalls) {
const Environment env = CreateEnvironment();
for (auto rate : {16000, 32000, 48000}) {
SCOPED_TRACE(ProduceDebugText(rate));
RunBasicSetupAndApiCallTest(rate, 1);
RunBasicSetupAndApiCallTest(env, rate, 1);
}
}
TEST(BlockProcessor, TestLongerCall) {
RunBasicSetupAndApiCallTest(16000, 20 * kNumBlocksPerSecond);
RunBasicSetupAndApiCallTest(CreateEnvironment(), 16000,
20 * kNumBlocksPerSecond);
}
#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
// DEATH tests on test bots has been fixed.
TEST(BlockProcessorDeathTest, DISABLED_VerifyRenderBlockSizeCheck) {
const Environment env = CreateEnvironment();
for (auto rate : {16000, 32000, 48000}) {
SCOPED_TRACE(ProduceDebugText(rate));
RunRenderBlockSizeVerificationTest(rate);
RunRenderBlockSizeVerificationTest(env, rate);
}
}
TEST(BlockProcessorDeathTest, VerifyRenderNumBandsCheck) {
const Environment env = CreateEnvironment();
for (auto rate : {16000, 32000, 48000}) {
SCOPED_TRACE(ProduceDebugText(rate));
RunRenderNumBandsVerificationTest(rate);
RunRenderNumBandsVerificationTest(env, rate);
}
}
// TODO(peah): Verify the check for correct number of bands in the capture
// signal.
TEST(BlockProcessorDeathTest, VerifyCaptureNumBandsCheck) {
const Environment env = CreateEnvironment();
for (auto rate : {16000, 32000, 48000}) {
SCOPED_TRACE(ProduceDebugText(rate));
RunCaptureNumBandsVerificationTest(rate);
RunCaptureNumBandsVerificationTest(env, rate);
}
}
// Verifiers that the verification for null ProcessCapture input works.
TEST(BlockProcessorDeathTest, NullProcessCaptureParameter) {
EXPECT_DEATH(std::unique_ptr<BlockProcessor>(
BlockProcessor::Create(EchoCanceller3Config(), 16000, 1, 1))
EXPECT_DEATH(BlockProcessor::Create(CreateEnvironment(),
EchoCanceller3Config(), 16000, 1, 1)
->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
// tests on test bots has been fixed.
TEST(BlockProcessor, DISABLED_WrongSampleRate) {
EXPECT_DEATH(std::unique_ptr<BlockProcessor>(
BlockProcessor::Create(EchoCanceller3Config(), 8001, 1, 1)),
EXPECT_DEATH(BlockProcessor::Create(CreateEnvironment(),
EchoCanceller3Config(), 8001, 1, 1),
"");
}

View File

@ -14,6 +14,7 @@
#include <numeric>
#include "api/audio/echo_canceller3_config.h"
#include "api/environment/environment_factory.h"
#include "modules/audio_processing/aec3/aec_state.h"
#include "rtc_base/random.h"
#include "rtc_base/system/arch.h"
@ -36,7 +37,7 @@ TEST(ComfortNoiseGenerator, CorrectLevel) {
constexpr size_t kNumChannels = 5;
EchoCanceller3Config config;
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<FftData> n_lower(kNumChannels);

View File

@ -735,7 +735,8 @@ EchoCanceller3::EchoCanceller3(
int sample_rate_hz,
size_t num_render_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())),
sample_rate_hz_(sample_rate_hz),
num_bands_(NumBandsForRate(sample_rate_hz_)),
@ -825,9 +826,9 @@ void EchoCanceller3::Initialize() {
render_blocker_.reset(
new FrameBlocker(num_bands_, num_render_channels_to_aec_));
block_processor_.reset(BlockProcessor::Create(
config_selector_.active_config(), sample_rate_hz_,
num_render_channels_to_aec_, num_capture_channels_));
block_processor_ = BlockProcessor::Create(
env_, config_selector_.active_config(), sample_rate_hz_,
num_render_channels_to_aec_, num_capture_channels_);
render_sub_frame_view_ = std::vector<std::vector<rtc::ArrayView<float>>>(
num_bands_,

View File

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

View File

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

View File

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

View File

@ -14,6 +14,7 @@
#include <cmath>
#include "api/environment/environment_factory.h"
#include "modules/audio_processing/aec3/aec3_fft.h"
#include "modules/audio_processing/aec3/aec_state.h"
#include "test/gtest.h"
@ -138,7 +139,7 @@ TEST(DbMetric, Constructor) {
// Verify the general functionality of EchoRemoverMetrics.
TEST(EchoRemoverMetrics, NormalUsage) {
EchoRemoverMetrics metrics;
AecState aec_state(EchoCanceller3Config{}, 1);
AecState aec_state(CreateEnvironment(), EchoCanceller3Config{}, 1);
std::array<float, kFftLengthBy2Plus1> comfort_noise_spectrum;
std::array<float, kFftLengthBy2Plus1> suppressor_gain;
comfort_noise_spectrum.fill(10.f);

View File

@ -15,6 +15,8 @@
#include <numeric>
#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/render_buffer.h"
#include "modules/audio_processing/aec3/render_delay_buffer.h"
@ -53,12 +55,13 @@ INSTANTIATE_TEST_SUITE_P(MultiChannel,
TEST_P(EchoRemoverMultiChannel, BasicApiCalls) {
const size_t num_render_channels = std::get<0>(GetParam());
const size_t num_capture_channels = std::get<1>(GetParam());
const Environment env = CreateEnvironment();
std::optional<DelayEstimate> delay_estimate;
for (auto rate : {16000, 32000, 48000}) {
SCOPED_TRACE(ProduceDebugText(rate));
std::unique_ptr<EchoRemover> remover(
EchoRemover::Create(EchoCanceller3Config(), rate, num_render_channels,
num_capture_channels));
std::unique_ptr<EchoRemover> remover =
EchoRemover::Create(env, EchoCanceller3Config(), rate,
num_render_channels, num_capture_channels);
std::unique_ptr<RenderDelayBuffer> render_buffer(RenderDelayBuffer::Create(
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
// tests on test bots has been fixed.
TEST(EchoRemoverDeathTest, DISABLED_WrongSampleRate) {
EXPECT_DEATH(std::unique_ptr<EchoRemover>(
EchoRemover::Create(EchoCanceller3Config(), 8001, 1, 1)),
EXPECT_DEATH(EchoRemover::Create(CreateEnvironment(), EchoCanceller3Config(),
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
// tests on test bots has been fixed.c
TEST(EchoRemoverDeathTest, DISABLED_WrongCaptureNumBands) {
const Environment env = CreateEnvironment();
std::optional<DelayEstimate> delay_estimate;
for (auto rate : {16000, 32000, 48000}) {
SCOPED_TRACE(ProduceDebugText(rate));
std::unique_ptr<EchoRemover> remover(
EchoRemover::Create(EchoCanceller3Config(), rate, 1, 1));
std::unique_ptr<EchoRemover> remover =
EchoRemover::Create(env, EchoCanceller3Config(), rate, 1, 1);
std::unique_ptr<RenderDelayBuffer> render_buffer(
RenderDelayBuffer::Create(EchoCanceller3Config(), rate, 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.
TEST(EchoRemoverDeathTest, NullCapture) {
std::optional<DelayEstimate> delay_estimate;
std::unique_ptr<EchoRemover> remover(
EchoRemover::Create(EchoCanceller3Config(), 16000, 1, 1));
std::unique_ptr<EchoRemover> remover = EchoRemover::Create(
CreateEnvironment(), EchoCanceller3Config(), 16000, 1, 1);
std::unique_ptr<RenderDelayBuffer> render_buffer(
RenderDelayBuffer::Create(EchoCanceller3Config(), 16000, 1));
EchoPathVariability echo_path_variability(
@ -133,6 +137,7 @@ TEST(EchoRemoverDeathTest, NullCapture) {
// remove echoes.
TEST(EchoRemover, BasicEchoRemoval) {
constexpr int kNumBlocksToProcess = 500;
const Environment env = CreateEnvironment();
Random random_generator(42U);
std::optional<DelayEstimate> delay_estimate;
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}) {
SCOPED_TRACE(ProduceDebugText(rate, delay_samples));
EchoCanceller3Config config;
std::unique_ptr<EchoRemover> remover(
EchoRemover::Create(config, rate, num_channels, num_channels));
std::unique_ptr<EchoRemover> remover =
EchoRemover::Create(env, config, rate, num_channels, num_channels);
std::unique_ptr<RenderDelayBuffer> render_buffer(
RenderDelayBuffer::Create(config, rate, num_channels));
render_buffer->AlignFromDelay(delay_samples / kBlockSize);

View File

@ -15,12 +15,13 @@
namespace webrtc {
ErleEstimator::ErleEstimator(size_t startup_phase_length_blocks,
ErleEstimator::ErleEstimator(const Environment& env,
size_t startup_phase_length_blocks,
const EchoCanceller3Config& config,
size_t num_capture_channels)
: startup_phase_length_blocks_(startup_phase_length_blocks),
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) {
signal_dependent_erle_estimator_ =
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.
class ErleEstimator {
public:
ErleEstimator(size_t startup_phase_length_blocks,
ErleEstimator(const Environment& env,
size_t startup_phase_length_blocks,
const EchoCanceller3Config& config,
size_t num_capture_channels);
~ErleEstimator();

View File

@ -13,6 +13,7 @@
#include <cmath>
#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/spectrum_buffer.h"
#include "rtc_base/random.h"
@ -173,7 +174,7 @@ TEST_P(ErleEstimatorMultiChannel, VerifyErleIncreaseAndHold) {
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);
render_delay_buffer->Insert(x);
@ -236,7 +237,8 @@ TEST_P(ErleEstimatorMultiChannel, VerifyErleTrackingOnOnsets) {
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);
FormFarendTimeFrame(&x);

View File

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

View File

@ -15,6 +15,8 @@
#include <string>
#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_erl.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
// update gain functionality.
void RunFilterUpdateTest(int num_blocks_to_process,
void RunFilterUpdateTest(const Environment& env,
int num_blocks_to_process,
size_t delay_samples,
int filter_length_blocks,
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;
std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
RenderDelayBuffer::Create(config, kSampleRateHz, kNumRenderChannels));
AecState aec_state(config, kNumCaptureChannels);
AecState aec_state(env, config, kNumCaptureChannels);
RenderSignalAnalyzer render_signal_analyzer(config);
std::optional<DelayEstimate> delay_estimate;
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.
TEST(RefinedFilterUpdateGain, GainCausesFilterToConverge) {
const Environment env = CreateEnvironment();
std::vector<int> blocks_with_echo_path_changes;
std::vector<int> blocks_with_saturation;
for (size_t filter_length_blocks : {12, 20, 30}) {
@ -264,7 +268,7 @@ TEST(RefinedFilterUpdateGain, GainCausesFilterToConverge) {
std::array<float, kBlockSize> y;
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,
false, &e, &y, &G);
@ -284,6 +288,7 @@ TEST(RefinedFilterUpdateGain, GainCausesFilterToConverge) {
// Verifies that the magnitude of the gain on average decreases for a
// persistently exciting signal.
TEST(RefinedFilterUpdateGain, DecreasingGain) {
const Environment env = CreateEnvironment();
std::vector<int> blocks_with_echo_path_changes;
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_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);
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);
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);
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
// error estimates cause the gain to increase after a period of saturation.
TEST(RefinedFilterUpdateGain, SaturationBehavior) {
const Environment env = CreateEnvironment();
std::vector<int> blocks_with_echo_path_changes;
std::vector<int> blocks_with_saturation;
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_b_power;
RunFilterUpdateTest(100, 65, filter_length_blocks,
RunFilterUpdateTest(env, 100, 65, filter_length_blocks,
blocks_with_echo_path_changes, blocks_with_saturation,
false, &e, &y, &G_a);
EXPECT_EQ(G_a_ref.re, G_a.re);
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,
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,
false, &e, &y, &G_b);
@ -361,6 +367,7 @@ TEST(RefinedFilterUpdateGain, SaturationBehavior) {
// Verifies that the gain increases after an echo path change.
// TODO(peah): Correct and reactivate this test.
TEST(RefinedFilterUpdateGain, DISABLED_EchoPathChangeBehavior) {
const Environment env = CreateEnvironment();
for (size_t filter_length_blocks : {12, 20, 30}) {
SCOPED_TRACE(ProduceDebugText(filter_length_blocks));
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_b_power;
RunFilterUpdateTest(100, 65, filter_length_blocks,
RunFilterUpdateTest(env, 100, 65, filter_length_blocks,
blocks_with_echo_path_changes, blocks_with_saturation,
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,
false, &e, &y, &G_b);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -19,6 +19,7 @@
#include "api/array_view.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/logging/apm_data_dumper.h"
@ -27,7 +28,8 @@ namespace webrtc {
// Estimates the echo return loss enhancement for each frequency subband.
class SubbandErleEstimator {
public:
SubbandErleEstimator(const EchoCanceller3Config& config,
SubbandErleEstimator(const Environment& env,
const EchoCanceller3Config& config,
size_t num_capture_channels);
~SubbandErleEstimator();

View File

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

View File

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

View File

@ -15,6 +15,8 @@
#include <numeric>
#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/render_delay_buffer.h"
#include "modules/audio_processing/test/echo_canceller_test_tools.h"
@ -27,6 +29,7 @@ namespace webrtc {
namespace {
std::vector<float> RunSubtractorTest(
const Environment& env,
size_t num_render_channels,
size_t num_capture_channels,
int num_blocks_to_process,
@ -42,7 +45,7 @@ std::vector<float> RunSubtractorTest(
config.filter.refined.length_blocks = refined_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());
std::optional<DelayEstimate> delay_estimate;
Block x(kNumBands, num_render_channels);
@ -59,7 +62,7 @@ std::vector<float> RunSubtractorTest(
std::vector<std::array<float, kFftLengthBy2Plus1>> E2_refined(
num_capture_channels);
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);
for (auto& Y2_ch : Y2) {
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.
TEST(SubtractorDeathTest, NullDataDumper) {
EXPECT_DEATH(
Subtractor(EchoCanceller3Config(), 1, 1, nullptr, DetectOptimization()),
"");
EXPECT_DEATH(Subtractor(CreateEnvironment(), EchoCanceller3Config(), 1, 1,
nullptr, DetectOptimization()),
"");
}
#endif
// Verifies that the subtractor is able to converge on correlated data.
TEST(Subtractor, Convergence) {
const Environment env = CreateEnvironment();
std::vector<int> blocks_with_echo_path_changes;
for (size_t filter_length_blocks : {12, 20, 30}) {
for (size_t delay_samples : {0, 64, 150, 200, 301}) {
SCOPED_TRACE(ProduceDebugText(1, 1, delay_samples, filter_length_blocks));
std::vector<float> echo_to_nearend_powers = RunSubtractorTest(
1, 1, 2500, delay_samples, filter_length_blocks, filter_length_blocks,
false, blocks_with_echo_path_changes);
env, 1, 1, 2500, delay_samples, filter_length_blocks,
filter_length_blocks, false, blocks_with_echo_path_changes);
for (float echo_to_nearend_power : echo_to_nearend_powers) {
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
// filter is longer than the coarse filter.
TEST(Subtractor, RefinedFilterLongerThanCoarseFilter) {
const Environment env = CreateEnvironment();
std::vector<int> blocks_with_echo_path_changes;
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) {
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
// filter is longer than the refined filter.
TEST(Subtractor, CoarseFilterLongerThanRefinedFilter) {
const Environment env = CreateEnvironment();
std::vector<int> blocks_with_echo_path_changes;
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) {
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.
TEST(Subtractor, NonConvergenceOnUncorrelatedSignals) {
const Environment env = CreateEnvironment();
std::vector<int> blocks_with_echo_path_changes;
for (size_t filter_length_blocks : {12, 20, 30}) {
for (size_t delay_samples : {0, 64, 150, 200, 301}) {
SCOPED_TRACE(ProduceDebugText(1, 1, delay_samples, filter_length_blocks));
std::vector<float> echo_to_nearend_powers = RunSubtractorTest(
1, 1, 3000, delay_samples, filter_length_blocks, filter_length_blocks,
true, blocks_with_echo_path_changes);
env, 1, 1, 3000, delay_samples, filter_length_blocks,
filter_length_blocks, true, blocks_with_echo_path_changes);
for (float echo_to_nearend_power : echo_to_nearend_powers) {
EXPECT_NEAR(1.f, echo_to_nearend_power, 0.1);
}
@ -273,12 +280,13 @@ INSTANTIATE_TEST_SUITE_P(DebugMultiChannel,
TEST_P(SubtractorMultiChannelUpToEightRender, Convergence) {
const size_t num_render_channels = std::get<0>(GetParam());
const size_t num_capture_channels = std::get<1>(GetParam());
const Environment env = CreateEnvironment();
std::vector<int> blocks_with_echo_path_changes;
size_t num_blocks_to_process = 2500 * num_render_channels;
std::vector<float> echo_to_nearend_powers = RunSubtractorTest(
num_render_channels, num_capture_channels, num_blocks_to_process, 64, 20,
20, false, blocks_with_echo_path_changes);
env, num_render_channels, num_capture_channels, num_blocks_to_process, 64,
20, 20, false, blocks_with_echo_path_changes);
for (float echo_to_nearend_power : echo_to_nearend_powers) {
EXPECT_GT(0.1f, echo_to_nearend_power);
@ -306,12 +314,13 @@ TEST_P(SubtractorMultiChannelUpToFourRender,
NonConvergenceOnUncorrelatedSignals) {
const size_t num_render_channels = std::get<0>(GetParam());
const size_t num_capture_channels = std::get<1>(GetParam());
const Environment env = CreateEnvironment();
std::vector<int> blocks_with_echo_path_changes;
size_t num_blocks_to_process = 5000 * num_render_channels;
std::vector<float> echo_to_nearend_powers = RunSubtractorTest(
num_render_channels, num_capture_channels, num_blocks_to_process, 64, 20,
20, true, blocks_with_echo_path_changes);
env, num_render_channels, num_capture_channels, num_blocks_to_process, 64,
20, 20, true, blocks_with_echo_path_changes);
for (float echo_to_nearend_power : echo_to_nearend_powers) {
EXPECT_LT(.8f, echo_to_nearend_power);
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/logging/apm_data_dumper.h"
#include "rtc_base/checks.h"
#include "system_wrappers/include/field_trial.h"
namespace webrtc {
namespace {

View File

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

View File

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

View File

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

View File

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