Only create AEC2 when needed
This CL ensures that the AEC2 is only created when needed.
The changes in the CL are bitexact when running AEC2 via
audioproc_f
Bug: webrtc:8671
Change-Id: I5f6d33e45a7031c69ac53098781635c415668e49
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/129740
Reviewed-by: Sam Zackrisson <saza@webrtc.org>
Commit-Queue: Per Åhgren <peah@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#27772}
diff --git a/modules/audio_processing/audio_processing_impl.cc b/modules/audio_processing/audio_processing_impl.cc
index 4d24ee6..6950623 100644
--- a/modules/audio_processing/audio_processing_impl.cc
+++ b/modules/audio_processing/audio_processing_impl.cc
@@ -429,7 +429,6 @@
new rtc::RefCountedObject<ResidualEchoDetector>();
}
- private_submodules_->echo_cancellation.reset(new EchoCancellationImpl());
private_submodules_->echo_control_mobile.reset(new EchoControlMobileImpl());
// TODO(alessiob): Move the injected gain controller once injection is
// implemented.
@@ -548,15 +547,8 @@
formats_.api_format.output_stream().num_channels(),
formats_.api_format.output_stream().num_frames()));
- private_submodules_->echo_cancellation->Initialize(
- proc_sample_rate_hz(), num_reverse_channels(), num_output_channels(),
- num_proc_channels());
AllocateRenderQueue();
- int success = private_submodules_->echo_cancellation->enable_metrics(true);
- RTC_DCHECK_EQ(0, success);
- success = private_submodules_->echo_cancellation->enable_delay_logging(true);
- RTC_DCHECK_EQ(0, success);
private_submodules_->echo_control_mobile->Initialize(
proc_split_sample_rate_hz(), num_reverse_channels(),
num_output_channels());
@@ -802,7 +794,12 @@
rtc::CritScope cs_render(&crit_render_);
rtc::CritScope cs_capture(&crit_capture_);
- private_submodules_->echo_cancellation->SetExtraOptions(config);
+ capture_nonlocked_.use_aec2_extended_filter =
+ config.Get<ExtendedFilter>().enabled;
+ capture_nonlocked_.use_aec2_delay_agnostic =
+ config.Get<DelayAgnostic>().enabled;
+ capture_nonlocked_.use_aec2_refined_adaptive_filter =
+ config.Get<RefinedAdaptiveFilter>().enabled;
if (capture_.transient_suppressor_enabled !=
config.Get<ExperimentalNs>().enabled) {
@@ -1035,13 +1032,16 @@
RTC_DCHECK_GE(160, audio->num_frames_per_band());
// Insert the samples into the queue.
- if (!aec_render_signal_queue_->Insert(&aec_render_queue_buffer_)) {
- // The data queue is full and needs to be emptied.
- EmptyQueuedRenderAudio();
+ if (private_submodules_->echo_cancellation) {
+ RTC_DCHECK(aec_render_signal_queue_);
+ if (!aec_render_signal_queue_->Insert(&aec_render_queue_buffer_)) {
+ // The data queue is full and needs to be emptied.
+ EmptyQueuedRenderAudio();
- // Retry the insert (should always work).
- bool result = aec_render_signal_queue_->Insert(&aec_render_queue_buffer_);
- RTC_DCHECK(result);
+ // Retry the insert (should always work).
+ bool result = aec_render_signal_queue_->Insert(&aec_render_queue_buffer_);
+ RTC_DCHECK(result);
+ }
}
EchoControlMobileImpl::PackRenderAudioBuffer(audio, num_output_channels(),
@@ -1087,12 +1087,6 @@
}
void AudioProcessingImpl::AllocateRenderQueue() {
- const size_t new_aec_render_queue_element_max_size =
- std::max(static_cast<size_t>(1),
- kMaxAllowedValuesOfSamplesPerBand *
- EchoCancellationImpl::NumCancellersRequired(
- num_output_channels(), num_reverse_channels()));
-
const size_t new_aecm_render_queue_element_max_size =
std::max(static_cast<size_t>(1),
kMaxAllowedValuesOfSamplesPerBand *
@@ -1107,25 +1101,6 @@
// Reallocate the queues if the queue item sizes are too small to fit the
// data to put in the queues.
- if (aec_render_queue_element_max_size_ <
- new_aec_render_queue_element_max_size) {
- aec_render_queue_element_max_size_ = new_aec_render_queue_element_max_size;
-
- std::vector<float> template_queue_element(
- aec_render_queue_element_max_size_);
-
- aec_render_signal_queue_.reset(
- new SwapQueue<std::vector<float>, RenderQueueItemVerifier<float>>(
- kMaxNumFramesToBuffer, template_queue_element,
- RenderQueueItemVerifier<float>(
- aec_render_queue_element_max_size_)));
-
- aec_render_queue_buffer_.resize(aec_render_queue_element_max_size_);
- aec_capture_queue_buffer_.resize(aec_render_queue_element_max_size_);
- } else {
- aec_render_signal_queue_->Clear();
- }
-
if (aecm_render_queue_element_max_size_ <
new_aecm_render_queue_element_max_size) {
aecm_render_queue_element_max_size_ =
@@ -1187,9 +1162,12 @@
void AudioProcessingImpl::EmptyQueuedRenderAudio() {
rtc::CritScope cs_capture(&crit_capture_);
- while (aec_render_signal_queue_->Remove(&aec_capture_queue_buffer_)) {
- private_submodules_->echo_cancellation->ProcessRenderAudio(
- aec_capture_queue_buffer_);
+ if (private_submodules_->echo_cancellation) {
+ RTC_DCHECK(aec_render_signal_queue_);
+ while (aec_render_signal_queue_->Remove(&aec_capture_queue_buffer_)) {
+ private_submodules_->echo_cancellation->ProcessRenderAudio(
+ aec_capture_queue_buffer_);
+ }
}
while (aecm_render_signal_queue_->Remove(&aecm_capture_queue_buffer_)) {
@@ -1283,7 +1261,8 @@
// Ensure that not both the AEC and AECM are active at the same time.
// TODO(peah): Simplify once the public API Enable functions for these
// are moved to APM.
- RTC_DCHECK(!(private_submodules_->echo_cancellation->is_enabled() &&
+ RTC_DCHECK(!((private_submodules_->echo_cancellation &&
+ private_submodules_->echo_cancellation->is_enabled()) &&
private_submodules_->echo_control_mobile->is_enabled()));
MaybeUpdateHistograms();
@@ -1368,7 +1347,8 @@
// Ensure that the stream delay was set before the call to the
// AEC ProcessCaptureAudio function.
- if (private_submodules_->echo_cancellation->is_enabled() &&
+ if (private_submodules_->echo_cancellation &&
+ private_submodules_->echo_cancellation->is_enabled() &&
!private_submodules_->echo_controller && !was_stream_delay_set()) {
return AudioProcessing::kStreamParameterNotSetError;
}
@@ -1383,7 +1363,7 @@
private_submodules_->echo_controller->ProcessCapture(
capture_buffer, capture_.echo_path_gain_change);
- } else {
+ } else if (private_submodules_->echo_cancellation) {
RETURN_ON_ERR(private_submodules_->echo_cancellation->ProcessCaptureAudio(
capture_buffer, stream_delay_ms()));
}
@@ -1402,7 +1382,8 @@
}
if (!(private_submodules_->echo_controller ||
- private_submodules_->echo_cancellation->is_enabled())) {
+ (private_submodules_->echo_cancellation &&
+ private_submodules_->echo_cancellation->is_enabled()))) {
RETURN_ON_ERR(private_submodules_->echo_control_mobile->ProcessCaptureAudio(
capture_buffer, stream_delay_ms()));
}
@@ -1426,7 +1407,8 @@
// TODO(peah): Add reporting from AEC3 whether there is echo.
RETURN_ON_ERR(public_submodules_->gain_control->ProcessCaptureAudio(
capture_buffer,
- private_submodules_->echo_cancellation->stream_has_echo()));
+ private_submodules_->echo_cancellation &&
+ private_submodules_->echo_cancellation->stream_has_echo()));
if (submodule_states_.CaptureMultiBandProcessingActive() &&
SampleRateSupportsMultiBand(
@@ -1756,20 +1738,6 @@
stats.echo_return_loss_enhancement =
ec_metrics.echo_return_loss_enhancement;
stats.delay_ms = ec_metrics.delay_ms;
- } else if (private_submodules_->echo_cancellation->GetMetrics(&metrics) ==
- Error::kNoError) {
- if (metrics.divergent_filter_fraction != -1.0f) {
- stats.divergent_filter_fraction =
- absl::optional<double>(metrics.divergent_filter_fraction);
- }
- if (metrics.echo_return_loss.instant != -100) {
- stats.echo_return_loss =
- absl::optional<double>(metrics.echo_return_loss.instant);
- }
- if (metrics.echo_return_loss_enhancement.instant != -100) {
- stats.echo_return_loss_enhancement =
- absl::optional<double>(metrics.echo_return_loss_enhancement.instant);
- }
}
if (config_.residual_echo_detector.enabled) {
RTC_DCHECK(private_submodules_->echo_detector);
@@ -1778,18 +1746,6 @@
stats.residual_echo_likelihood_recent_max =
ed_metrics.echo_likelihood_recent_max;
}
- int delay_median, delay_std;
- float fraction_poor_delays;
- if (private_submodules_->echo_cancellation->GetDelayMetrics(
- &delay_median, &delay_std, &fraction_poor_delays) ==
- Error::kNoError) {
- if (delay_median >= 0) {
- stats.delay_median_ms = absl::optional<int32_t>(delay_median);
- }
- if (delay_std >= 0) {
- stats.delay_standard_deviation_ms = absl::optional<int32_t>(delay_std);
- }
- }
return stats;
}
@@ -1826,7 +1782,8 @@
bool AudioProcessingImpl::UpdateActiveSubmoduleStates() {
return submodule_states_.Update(
config_.high_pass_filter.enabled,
- private_submodules_->echo_cancellation->is_enabled(),
+ private_submodules_->echo_cancellation &&
+ private_submodules_->echo_cancellation->is_enabled(),
private_submodules_->echo_control_mobile->is_enabled(),
config_.residual_echo_detector.enabled,
public_submodules_->noise_suppression->is_enabled(),
@@ -1872,20 +1829,82 @@
}
capture_nonlocked_.echo_controller_enabled = true;
- } else {
- private_submodules_->echo_cancellation->Enable(
- config_.echo_canceller.enabled && !config_.echo_canceller.mobile_mode);
- private_submodules_->echo_control_mobile->Enable(
- config_.echo_canceller.enabled && config_.echo_canceller.mobile_mode);
- private_submodules_->echo_cancellation->set_suppression_level(
- config_.echo_canceller.legacy_moderate_suppression_level
- ? EchoCancellationImpl::SuppressionLevel::kModerateSuppression
- : EchoCancellationImpl::SuppressionLevel::kHighSuppression);
-
- private_submodules_->echo_controller.reset();
- capture_nonlocked_.echo_controller_enabled = false;
+ private_submodules_->echo_cancellation.reset();
+ aec_render_signal_queue_.reset();
+ private_submodules_->echo_control_mobile->Enable(false);
+ return;
}
+
+ private_submodules_->echo_controller.reset();
+ capture_nonlocked_.echo_controller_enabled = false;
+
+ if (!config_.echo_canceller.enabled) {
+ private_submodules_->echo_cancellation.reset();
+ aec_render_signal_queue_.reset();
+ private_submodules_->echo_control_mobile->Enable(false);
+ return;
+ }
+
+ if (config_.echo_canceller.mobile_mode) {
+ // Create and activate AECM.
+ // TODO(peah): Add an on-demand creation of AECmobile similar to AEC2.
+ private_submodules_->echo_control_mobile->Enable(true);
+
+ private_submodules_->echo_cancellation.reset();
+ aec_render_signal_queue_.reset();
+ return;
+ }
+
+ // Create and activate AEC2.
+ private_submodules_->echo_control_mobile->Enable(false);
+ private_submodules_->echo_cancellation.reset(new EchoCancellationImpl());
+ private_submodules_->echo_cancellation->SetExtraOptions(
+ capture_nonlocked_.use_aec2_extended_filter,
+ capture_nonlocked_.use_aec2_delay_agnostic,
+ capture_nonlocked_.use_aec2_refined_adaptive_filter);
+
+ const size_t new_aec_render_queue_element_max_size =
+ std::max(static_cast<size_t>(1),
+ kMaxAllowedValuesOfSamplesPerBand *
+ EchoCancellationImpl::NumCancellersRequired(
+ num_output_channels(), num_reverse_channels()));
+
+ // Reallocate the queues if the queue item sizes are too small to fit the
+ // data to put in the queues.
+ if (aec_render_queue_element_max_size_ <
+ new_aec_render_queue_element_max_size ||
+ !aec_render_signal_queue_) {
+ aec_render_queue_element_max_size_ = new_aec_render_queue_element_max_size;
+
+ std::vector<float> template_queue_element(
+ aec_render_queue_element_max_size_);
+
+ aec_render_signal_queue_.reset(
+ new SwapQueue<std::vector<float>, RenderQueueItemVerifier<float>>(
+ kMaxNumFramesToBuffer, template_queue_element,
+ RenderQueueItemVerifier<float>(
+ aec_render_queue_element_max_size_)));
+
+ aec_render_queue_buffer_.resize(aec_render_queue_element_max_size_);
+ aec_capture_queue_buffer_.resize(aec_render_queue_element_max_size_);
+ } else {
+ aec_render_signal_queue_->Clear();
+ }
+
+ private_submodules_->echo_cancellation->Initialize(
+ proc_sample_rate_hz(), num_reverse_channels(), num_output_channels(),
+ num_proc_channels());
+
+ private_submodules_->echo_cancellation->Enable(true);
+
+ private_submodules_->echo_cancellation->set_suppression_level(
+ config_.echo_canceller.legacy_moderate_suppression_level
+ ? EchoCancellationImpl::SuppressionLevel::kModerateSuppression
+ : EchoCancellationImpl::SuppressionLevel::kHighSuppression);
+
+ private_submodules_->echo_controller.reset();
+ capture_nonlocked_.echo_controller_enabled = false;
}
void AudioProcessingImpl::InitializeGainController2() {
@@ -1935,7 +1954,8 @@
void AudioProcessingImpl::MaybeUpdateHistograms() {
static const int kMinDiffDelayMs = 60;
- if (private_submodules_->echo_cancellation->is_enabled()) {
+ if (private_submodules_->echo_cancellation &&
+ private_submodules_->echo_cancellation->is_enabled()) {
// Activate delay_jumps_ counters if we know echo_cancellation is running.
// If a stream has echo we know that the echo_cancellation is in process.
if (capture_.stream_delay_jumps == -1 &&
@@ -2009,8 +2029,12 @@
if (!aec_dump_) {
return;
}
- std::string experiments_description =
- private_submodules_->echo_cancellation->GetExperimentsDescription();
+
+ std::string experiments_description = "";
+ if (private_submodules_->echo_cancellation) {
+ experiments_description +=
+ private_submodules_->echo_cancellation->GetExperimentsDescription();
+ }
// TODO(peah): Add semicolon-separated concatenations of experiment
// descriptions for other submodules.
if (constants_.agc_clipped_level_min != kClippedLevelMin) {
@@ -2027,13 +2051,19 @@
apm_config.aec_enabled = config_.echo_canceller.enabled;
apm_config.aec_delay_agnostic_enabled =
+ private_submodules_->echo_cancellation &&
private_submodules_->echo_cancellation->is_delay_agnostic_enabled();
apm_config.aec_drift_compensation_enabled =
+ private_submodules_->echo_cancellation &&
private_submodules_->echo_cancellation->is_drift_compensation_enabled();
apm_config.aec_extended_filter_enabled =
+ private_submodules_->echo_cancellation &&
private_submodules_->echo_cancellation->is_extended_filter_enabled();
- apm_config.aec_suppression_level = static_cast<int>(
- private_submodules_->echo_cancellation->suppression_level());
+ apm_config.aec_suppression_level =
+ private_submodules_->echo_cancellation
+ ? static_cast<int>(
+ private_submodules_->echo_cancellation->suppression_level())
+ : 0;
apm_config.aecm_enabled =
private_submodules_->echo_control_mobile->is_enabled();
@@ -2115,7 +2145,9 @@
AecDump::AudioProcessingState audio_proc_state;
audio_proc_state.delay = capture_nonlocked_.stream_delay_ms;
audio_proc_state.drift =
- private_submodules_->echo_cancellation->stream_drift_samples();
+ private_submodules_->echo_cancellation
+ ? private_submodules_->echo_cancellation->stream_drift_samples()
+ : 0;
audio_proc_state.level = agc1()->stream_analog_level();
audio_proc_state.keypress = capture_.key_pressed;
aec_dump_->AddAudioProcessingState(audio_proc_state);
diff --git a/modules/audio_processing/audio_processing_impl.h b/modules/audio_processing/audio_processing_impl.h
index 9cd4f78..33cc559 100644
--- a/modules/audio_processing/audio_processing_impl.h
+++ b/modules/audio_processing/audio_processing_impl.h
@@ -246,7 +246,8 @@
void InitializeResidualEchoDetector()
RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_render_, crit_capture_);
void InitializeLowCutFilter() RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_capture_);
- void InitializeEchoController() RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_capture_);
+ void InitializeEchoController()
+ RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_render_, crit_capture_);
void InitializeGainController2() RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_capture_);
void InitializePreAmplifier() RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_capture_);
void InitializePostProcessor() RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_capture_);
@@ -417,6 +418,9 @@
int split_rate;
int stream_delay_ms;
bool echo_controller_enabled = false;
+ bool use_aec2_extended_filter = false;
+ bool use_aec2_delay_agnostic = false;
+ bool use_aec2_refined_adaptive_filter = false;
} capture_nonlocked_;
struct ApmRenderState {
diff --git a/modules/audio_processing/echo_cancellation_bit_exact_unittest.cc b/modules/audio_processing/echo_cancellation_bit_exact_unittest.cc
index af0741e..37898c0 100644
--- a/modules/audio_processing/echo_cancellation_bit_exact_unittest.cc
+++ b/modules/audio_processing/echo_cancellation_bit_exact_unittest.cc
@@ -33,7 +33,7 @@
Config config;
config.Set<DelayAgnostic>(new DelayAgnostic(true));
config.Set<ExtendedFilter>(new ExtendedFilter(true));
- echo_canceller->SetExtraOptions(config);
+ echo_canceller->SetExtraOptions(true, true, false);
}
void ProcessOneFrame(int sample_rate_hz,
diff --git a/modules/audio_processing/echo_cancellation_impl.cc b/modules/audio_processing/echo_cancellation_impl.cc
index 96b9789..ac13ebe 100644
--- a/modules/audio_processing/echo_cancellation_impl.cc
+++ b/modules/audio_processing/echo_cancellation_impl.cc
@@ -16,7 +16,6 @@
#include "modules/audio_processing/aec/aec_core.h"
#include "modules/audio_processing/aec/echo_cancellation.h"
#include "modules/audio_processing/audio_buffer.h"
-#include "modules/audio_processing/include/config.h"
#include "rtc_base/checks.h"
#include "system_wrappers/include/field_trial.h"
@@ -432,13 +431,12 @@
}
}
-void EchoCancellationImpl::SetExtraOptions(const webrtc::Config& config) {
- {
- extended_filter_enabled_ = config.Get<ExtendedFilter>().enabled;
- delay_agnostic_enabled_ = config.Get<DelayAgnostic>().enabled;
- refined_adaptive_filter_enabled_ =
- config.Get<RefinedAdaptiveFilter>().enabled;
- }
+void EchoCancellationImpl::SetExtraOptions(bool use_extended_filter,
+ bool use_delay_agnostic,
+ bool use_refined_adaptive_filter) {
+ extended_filter_enabled_ = use_extended_filter;
+ delay_agnostic_enabled_ = use_delay_agnostic;
+ refined_adaptive_filter_enabled_ = use_refined_adaptive_filter;
Configure();
}
diff --git a/modules/audio_processing/echo_cancellation_impl.h b/modules/audio_processing/echo_cancellation_impl.h
index 79be73b..25412cd 100644
--- a/modules/audio_processing/echo_cancellation_impl.h
+++ b/modules/audio_processing/echo_cancellation_impl.h
@@ -17,10 +17,7 @@
#include <vector>
#include "api/array_view.h"
-#include "modules/audio_processing/include/audio_processing.h"
#include "rtc_base/constructor_magic.h"
-#include "rtc_base/critical_section.h"
-#include "rtc_base/thread_annotations.h"
namespace webrtc {
@@ -136,7 +133,9 @@
size_t num_reverse_channels_,
size_t num_output_channels_,
size_t num_proc_channels_);
- void SetExtraOptions(const webrtc::Config& config);
+ void SetExtraOptions(bool use_extended_filter,
+ bool use_delay_agnostic,
+ bool use_refined_adaptive_filter);
bool is_delay_agnostic_enabled() const;
bool is_extended_filter_enabled() const;
std::string GetExperimentsDescription();
diff --git a/modules/audio_processing/echo_cancellation_impl_unittest.cc b/modules/audio_processing/echo_cancellation_impl_unittest.cc
index 841ea0d..22741ee 100644
--- a/modules/audio_processing/echo_cancellation_impl_unittest.cc
+++ b/modules/audio_processing/echo_cancellation_impl_unittest.cc
@@ -31,16 +31,14 @@
EXPECT_EQ(0, WebRtcAec_extended_filter_enabled(aec_core));
Config config;
- config.Set<ExtendedFilter>(new ExtendedFilter(true));
- echo_canceller.SetExtraOptions(config);
+ echo_canceller.SetExtraOptions(true, false, false);
EXPECT_EQ(1, WebRtcAec_extended_filter_enabled(aec_core));
// Retains setting after initialization.
echo_canceller.Initialize(AudioProcessing::kSampleRate16kHz, 2, 2, 2);
EXPECT_EQ(1, WebRtcAec_extended_filter_enabled(aec_core));
- config.Set<ExtendedFilter>(new ExtendedFilter(false));
- echo_canceller.SetExtraOptions(config);
+ echo_canceller.SetExtraOptions(false, false, false);
EXPECT_EQ(0, WebRtcAec_extended_filter_enabled(aec_core));
// Retains setting after initialization.
@@ -63,8 +61,7 @@
EXPECT_EQ(0, WebRtcAec_delay_agnostic_enabled(aec_core));
Config config;
- config.Set<DelayAgnostic>(new DelayAgnostic(true));
- echo_canceller.SetExtraOptions(config);
+ echo_canceller.SetExtraOptions(false, true, false);
EXPECT_EQ(1, WebRtcAec_delay_agnostic_enabled(aec_core));
// Retains setting after initialization.
@@ -72,7 +69,7 @@
EXPECT_EQ(1, WebRtcAec_delay_agnostic_enabled(aec_core));
config.Set<DelayAgnostic>(new DelayAgnostic(false));
- echo_canceller.SetExtraOptions(config);
+ echo_canceller.SetExtraOptions(false, false, false);
EXPECT_EQ(0, WebRtcAec_delay_agnostic_enabled(aec_core));
// Retains setting after initialization.