Make the echo detector injectable.
This adds a generic interface for an echo detector, and makes it possible to inject one into the audio processing module.
Bug: webrtc:8732
Change-Id: I30d97aeb829307b2ae9c4dbeb9a3e15ab7ec0912
Reviewed-on: https://webrtc-review.googlesource.com/38900
Commit-Queue: Ivo Creusen <ivoc@webrtc.org>
Reviewed-by: Per Ã…hgren <peah@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#21588}
diff --git a/modules/audio_processing/audio_processing_impl.cc b/modules/audio_processing/audio_processing_impl.cc
index 4629ebf..accd03b 100644
--- a/modules/audio_processing/audio_processing_impl.cc
+++ b/modules/audio_processing/audio_processing_impl.cc
@@ -302,8 +302,10 @@
struct AudioProcessingImpl::ApmPrivateSubmodules {
ApmPrivateSubmodules(NonlinearBeamformer* beamformer,
std::unique_ptr<CustomProcessing> capture_post_processor,
- std::unique_ptr<CustomProcessing> render_pre_processor)
+ std::unique_ptr<CustomProcessing> render_pre_processor,
+ std::unique_ptr<EchoDetector> echo_detector)
: beamformer(beamformer),
+ echo_detector(std::move(echo_detector)),
capture_post_processor(std::move(capture_post_processor)),
render_pre_processor(std::move(render_pre_processor)) {}
// Accessed internally from capture or during initialization
@@ -312,7 +314,7 @@
std::unique_ptr<GainController2> gain_controller2;
std::unique_ptr<LowCutFilter> low_cut_filter;
std::unique_ptr<LevelController> level_controller;
- std::unique_ptr<ResidualEchoDetector> residual_echo_detector;
+ std::unique_ptr<EchoDetector> echo_detector;
std::unique_ptr<EchoControl> echo_controller;
std::unique_ptr<CustomProcessing> capture_post_processor;
std::unique_ptr<CustomProcessing> render_pre_processor;
@@ -345,16 +347,27 @@
return *this;
}
+AudioProcessingBuilder& AudioProcessingBuilder::SetEchoDetector(
+ std::unique_ptr<EchoDetector> echo_detector) {
+ echo_detector_ = std::move(echo_detector);
+ return *this;
+}
+
AudioProcessing* AudioProcessingBuilder::Create() {
webrtc::Config config;
return Create(config);
}
AudioProcessing* AudioProcessingBuilder::Create(const webrtc::Config& config) {
- return AudioProcessing::Create(config, std::move(capture_post_processing_),
- std::move(render_pre_processing_),
- std::move(echo_control_factory_),
- nonlinear_beamformer_.release());
+ AudioProcessingImpl* apm = new rtc::RefCountedObject<AudioProcessingImpl>(
+ config, std::move(capture_post_processing_),
+ std::move(render_pre_processing_), std::move(echo_control_factory_),
+ std::move(echo_detector_), nonlinear_beamformer_.release());
+ if (apm->Initialize() != AudioProcessing::kNoError) {
+ delete apm;
+ apm = nullptr;
+ }
+ return apm;
}
AudioProcessing* AudioProcessing::Create() {
@@ -388,7 +401,7 @@
NonlinearBeamformer* beamformer) {
AudioProcessingImpl* apm = new rtc::RefCountedObject<AudioProcessingImpl>(
config, std::move(capture_post_processor),
- std::move(render_pre_processor), std::move(echo_control_factory),
+ std::move(render_pre_processor), std::move(echo_control_factory), nullptr,
beamformer);
if (apm->Initialize() != kNoError) {
delete apm;
@@ -399,13 +412,15 @@
}
AudioProcessingImpl::AudioProcessingImpl(const webrtc::Config& config)
- : AudioProcessingImpl(config, nullptr, nullptr, nullptr, nullptr) {}
+ : AudioProcessingImpl(config, nullptr, nullptr, nullptr, nullptr, nullptr) {
+}
AudioProcessingImpl::AudioProcessingImpl(
const webrtc::Config& config,
std::unique_ptr<CustomProcessing> capture_post_processor,
std::unique_ptr<CustomProcessing> render_pre_processor,
std::unique_ptr<EchoControlFactory> echo_control_factory,
+ std::unique_ptr<EchoDetector> echo_detector,
NonlinearBeamformer* beamformer)
: high_pass_filter_impl_(new HighPassFilterImpl(this)),
echo_control_factory_(std::move(echo_control_factory)),
@@ -414,7 +429,8 @@
private_submodules_(
new ApmPrivateSubmodules(beamformer,
std::move(capture_post_processor),
- std::move(render_pre_processor))),
+ std::move(render_pre_processor),
+ std::move(echo_detector))),
constants_(config.Get<ExperimentalAgc>().startup_min_volume,
config.Get<ExperimentalAgc>().clipped_level_min,
#if defined(WEBRTC_ANDROID) || defined(WEBRTC_IOS)
@@ -454,8 +470,11 @@
public_submodules_->gain_control_for_experimental_agc.reset(
new GainControlForExperimentalAgc(
public_submodules_->gain_control.get(), &crit_capture_));
- private_submodules_->residual_echo_detector.reset(
- new ResidualEchoDetector());
+
+ // If no echo detector is injected, use the ResidualEchoDetector.
+ if (!private_submodules_->echo_detector) {
+ private_submodules_->echo_detector.reset(new ResidualEchoDetector());
+ }
// TODO(peah): Move this creation to happen only when the level controller
// is enabled.
@@ -1121,7 +1140,8 @@
}
while (red_render_signal_queue_->Remove(&red_capture_queue_buffer_)) {
- private_submodules_->residual_echo_detector->AnalyzeRenderAudio(
+ RTC_DCHECK(private_submodules_->echo_detector);
+ private_submodules_->echo_detector->AnalyzeRenderAudio(
red_capture_queue_buffer_);
}
}
@@ -1337,7 +1357,8 @@
}
if (config_.residual_echo_detector.enabled) {
- private_submodules_->residual_echo_detector->AnalyzeCaptureAudio(
+ RTC_DCHECK(private_submodules_->echo_detector);
+ private_submodules_->echo_detector->AnalyzeCaptureAudio(
rtc::ArrayView<const float>(capture_buffer->channels_f()[0],
capture_buffer->num_frames()));
}
@@ -1664,11 +1685,11 @@
}
{
rtc::CritScope cs_capture(&crit_capture_);
- stats.residual_echo_likelihood =
- private_submodules_->residual_echo_detector->echo_likelihood();
+ RTC_DCHECK(private_submodules_->echo_detector);
+ auto ed_metrics = private_submodules_->echo_detector->GetMetrics();
+ stats.residual_echo_likelihood = ed_metrics.echo_likelihood;
stats.residual_echo_likelihood_recent_max =
- private_submodules_->residual_echo_detector
- ->echo_likelihood_recent_max();
+ ed_metrics.echo_likelihood_recent_max;
}
public_submodules_->echo_cancellation->GetDelayMetrics(
&stats.delay_median, &stats.delay_standard_deviation,
@@ -1705,11 +1726,11 @@
}
if (config_.residual_echo_detector.enabled) {
rtc::CritScope cs_capture(&crit_capture_);
- stats.residual_echo_likelihood = rtc::Optional<double>(
- private_submodules_->residual_echo_detector->echo_likelihood());
+ RTC_DCHECK(private_submodules_->echo_detector);
+ auto ed_metrics = private_submodules_->echo_detector->GetMetrics();
+ stats.residual_echo_likelihood = ed_metrics.echo_likelihood;
stats.residual_echo_likelihood_recent_max =
- rtc::Optional<double>(private_submodules_->residual_echo_detector
- ->echo_likelihood_recent_max());
+ ed_metrics.echo_likelihood_recent_max;
}
int delay_median, delay_std;
float fraction_poor_delays;
@@ -1854,7 +1875,9 @@
}
void AudioProcessingImpl::InitializeResidualEchoDetector() {
- private_submodules_->residual_echo_detector->Initialize();
+ RTC_DCHECK(private_submodules_->echo_detector);
+ private_submodules_->echo_detector->Initialize(proc_sample_rate_hz(),
+ num_proc_channels());
}
void AudioProcessingImpl::InitializePostProcessor() {