APM reports ERL and ERLE metrics for AEC3.
The audio processing module reports the metrics 'echo return loss'
and 'echo return loss enhancement' for AEC3.
Bug: webrtc:8533
Change-Id: I166c504adf013d6cb5d6d3c9717d0622c3454bb7
Reviewed-on: https://webrtc-review.googlesource.com/24880
Commit-Queue: Gustaf Ullberg <gustaf@webrtc.org>
Reviewed-by: Ivo Creusen <ivoc@webrtc.org>
Reviewed-by: Per Ã…hgren <peah@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#20835}
diff --git a/modules/audio_processing/aec3/aec_state.h b/modules/audio_processing/aec3/aec_state.h
index 9c87133..e9a46b4 100644
--- a/modules/audio_processing/aec3/aec_state.h
+++ b/modules/audio_processing/aec3/aec_state.h
@@ -50,11 +50,17 @@
return erle_estimator_.Erle();
}
+ // Returns the time-domain ERLE.
+ float ErleTimeDomain() const { return erle_estimator_.ErleTimeDomain(); }
+
// Returns the ERL.
const std::array<float, kFftLengthBy2Plus1>& Erl() const {
return erl_estimator_.Erl();
}
+ // Returns the time-domain ERL.
+ float ErlTimeDomain() const { return erl_estimator_.ErlTimeDomain(); }
+
// Returns the delay estimate based on the linear filter.
rtc::Optional<size_t> FilterDelay() const { return filter_delay_; }
diff --git a/modules/audio_processing/aec3/block_processor.cc b/modules/audio_processing/aec3/block_processor.cc
index 7de6dc2..20c3669 100644
--- a/modules/audio_processing/aec3/block_processor.cc
+++ b/modules/audio_processing/aec3/block_processor.cc
@@ -40,6 +40,8 @@
void UpdateEchoLeakageStatus(bool leakage_detected) override;
+ void GetMetrics(EchoControl::Metrics* metrics) const override;
+
private:
static int instance_count_;
bool no_capture_data_received_ = true;
@@ -179,6 +181,10 @@
echo_remover_->UpdateEchoLeakageStatus(leakage_detected);
}
+void BlockProcessorImpl::GetMetrics(EchoControl::Metrics* metrics) const {
+ echo_remover_->GetMetrics(metrics);
+}
+
} // namespace
BlockProcessor* BlockProcessor::Create(const EchoCanceller3Config& config,
diff --git a/modules/audio_processing/aec3/block_processor.h b/modules/audio_processing/aec3/block_processor.h
index 845e081..8687bc2 100644
--- a/modules/audio_processing/aec3/block_processor.h
+++ b/modules/audio_processing/aec3/block_processor.h
@@ -39,6 +39,9 @@
virtual ~BlockProcessor() = default;
+ // Get current metrics.
+ virtual void GetMetrics(EchoControl::Metrics* metrics) const = 0;
+
// Processes a block of capture data.
virtual void ProcessCapture(
bool echo_path_gain_change,
diff --git a/modules/audio_processing/aec3/echo_canceller3.cc b/modules/audio_processing/aec3/echo_canceller3.cc
index 93c98e4..491faa0 100644
--- a/modules/audio_processing/aec3/echo_canceller3.cc
+++ b/modules/audio_processing/aec3/echo_canceller3.cc
@@ -323,6 +323,13 @@
LowestBandRate(sample_rate_hz_), 1);
}
+EchoControl::Metrics EchoCanceller3::GetMetrics() const {
+ RTC_DCHECK_RUNS_SERIALIZED(&capture_race_checker_);
+ Metrics metrics;
+ block_processor_->GetMetrics(&metrics);
+ return metrics;
+}
+
bool EchoCanceller3::Validate(const EchoCanceller3Config& config) {
return true;
}
diff --git a/modules/audio_processing/aec3/echo_canceller3.h b/modules/audio_processing/aec3/echo_canceller3.h
index f62016f..475bacb 100644
--- a/modules/audio_processing/aec3/echo_canceller3.h
+++ b/modules/audio_processing/aec3/echo_canceller3.h
@@ -79,6 +79,8 @@
// Processes the split-band domain capture signal in order to remove any echo
// present in the signal.
void ProcessCapture(AudioBuffer* capture, bool level_change) override;
+ // Collect current metrics from the echo canceller.
+ Metrics GetMetrics() const override;
// Signals whether an external detector has detected echo leakage from the
// echo canceller.
diff --git a/modules/audio_processing/aec3/echo_canceller3_unittest.cc b/modules/audio_processing/aec3/echo_canceller3_unittest.cc
index 66f5304..75de48b 100644
--- a/modules/audio_processing/aec3/echo_canceller3_unittest.cc
+++ b/modules/audio_processing/aec3/echo_canceller3_unittest.cc
@@ -102,6 +102,8 @@
void UpdateEchoLeakageStatus(bool leakage_detected) override {}
+ void GetMetrics(EchoControl::Metrics* metrics) const override {}
+
private:
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(CaptureTransportVerificationProcessor);
};
@@ -128,6 +130,8 @@
void UpdateEchoLeakageStatus(bool leakage_detected) override {}
+ void GetMetrics(EchoControl::Metrics* metrics) const override {}
+
private:
std::deque<std::vector<std::vector<float>>> received_render_blocks_;
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RenderTransportVerificationProcessor);
diff --git a/modules/audio_processing/aec3/echo_remover.cc b/modules/audio_processing/aec3/echo_remover.cc
index 72c629b..9adcec5 100644
--- a/modules/audio_processing/aec3/echo_remover.cc
+++ b/modules/audio_processing/aec3/echo_remover.cc
@@ -53,6 +53,8 @@
int sample_rate_hz);
~EchoRemoverImpl() override;
+ void GetMetrics(EchoControl::Metrics* metrics) const override;
+
// Removes the echo from a block of samples from the capture signal. The
// supplied render signal is assumed to be pre-aligned with the capture
// signal.
@@ -110,6 +112,13 @@
EchoRemoverImpl::~EchoRemoverImpl() = default;
+void EchoRemoverImpl::GetMetrics(EchoControl::Metrics* metrics) const {
+ // Echo return loss (ERL) is inverted to go from gain to attenuation.
+ metrics->echo_return_loss = -10.0 * log10(aec_state_.ErlTimeDomain());
+ metrics->echo_return_loss_enhancement =
+ 10.0 * log10(aec_state_.ErleTimeDomain());
+}
+
void EchoRemoverImpl::ProcessCapture(
const rtc::Optional<size_t>& echo_path_delay_samples,
const EchoPathVariability& echo_path_variability,
diff --git a/modules/audio_processing/aec3/echo_remover.h b/modules/audio_processing/aec3/echo_remover.h
index ab56e38..7411b5c 100644
--- a/modules/audio_processing/aec3/echo_remover.h
+++ b/modules/audio_processing/aec3/echo_remover.h
@@ -27,6 +27,9 @@
int sample_rate_hz);
virtual ~EchoRemover() = default;
+ // Get current metrics.
+ virtual void GetMetrics(EchoControl::Metrics* metrics) const = 0;
+
// Removes the echo from a block of samples from the capture signal. The
// supplied render signal is assumed to be pre-aligned with the capture
// signal.
diff --git a/modules/audio_processing/aec3/erle_estimator.h b/modules/audio_processing/aec3/erle_estimator.h
index 71fdfb5..d88b11b 100644
--- a/modules/audio_processing/aec3/erle_estimator.h
+++ b/modules/audio_processing/aec3/erle_estimator.h
@@ -31,7 +31,7 @@
// Returns the most recent ERLE estimate.
const std::array<float, kFftLengthBy2Plus1>& Erle() const { return erle_; }
- float ErleTimeDomain() { return erle_time_domain_; }
+ float ErleTimeDomain() const { return erle_time_domain_; }
private:
std::array<float, kFftLengthBy2Plus1> erle_;
diff --git a/modules/audio_processing/aec3/mock/mock_block_processor.h b/modules/audio_processing/aec3/mock/mock_block_processor.h
index 89adc8e..5fff456 100644
--- a/modules/audio_processing/aec3/mock/mock_block_processor.h
+++ b/modules/audio_processing/aec3/mock/mock_block_processor.h
@@ -30,6 +30,7 @@
MOCK_METHOD1(BufferRender,
void(const std::vector<std::vector<float>>& block));
MOCK_METHOD1(UpdateEchoLeakageStatus, void(bool leakage_detected));
+ MOCK_CONST_METHOD1(GetMetrics, void(EchoControl::Metrics* metrics));
};
} // namespace test
diff --git a/modules/audio_processing/aec3/mock/mock_echo_remover.h b/modules/audio_processing/aec3/mock/mock_echo_remover.h
index 06f6b87..44d3778 100644
--- a/modules/audio_processing/aec3/mock/mock_echo_remover.h
+++ b/modules/audio_processing/aec3/mock/mock_echo_remover.h
@@ -34,6 +34,7 @@
std::vector<std::vector<float>>* capture));
MOCK_METHOD1(UpdateEchoLeakageStatus, void(bool leakage_detected));
+ MOCK_CONST_METHOD1(GetMetrics, void(EchoControl::Metrics* metrics));
};
} // namespace test
diff --git a/modules/audio_processing/audio_processing_impl.cc b/modules/audio_processing/audio_processing_impl.cc
index c8d0970..8dac602 100644
--- a/modules/audio_processing/audio_processing_impl.cc
+++ b/modules/audio_processing/audio_processing_impl.cc
@@ -1608,8 +1608,16 @@
AudioProcessingStats stats;
if (has_remote_tracks) {
EchoCancellation::Metrics metrics;
- if (public_submodules_->echo_cancellation->GetMetrics(&metrics) ==
- Error::kNoError) {
+ if (private_submodules_->echo_controller) {
+ rtc::CritScope cs_capture(&crit_capture_);
+ EchoControl::Metrics ec_metrics =
+ private_submodules_->echo_controller->GetMetrics();
+ stats.echo_return_loss =
+ rtc::Optional<double>(ec_metrics.echo_return_loss);
+ stats.echo_return_loss_enhancement =
+ rtc::Optional<double>(ec_metrics.echo_return_loss_enhancement);
+ } else if (public_submodules_->echo_cancellation->GetMetrics(&metrics) ==
+ Error::kNoError) {
if (metrics.divergent_filter_fraction != -1.0f) {
stats.divergent_filter_fraction =
rtc::Optional<double>(metrics.divergent_filter_fraction);
diff --git a/modules/audio_processing/include/audio_processing.h b/modules/audio_processing/include/audio_processing.h
index 09fecab..a4245c6 100644
--- a/modules/audio_processing/include/audio_processing.h
+++ b/modules/audio_processing/include/audio_processing.h
@@ -940,6 +940,14 @@
// Processes the capture signal in order to remove the echo.
virtual void ProcessCapture(AudioBuffer* capture, bool echo_path_change) = 0;
+ struct Metrics {
+ double echo_return_loss;
+ double echo_return_loss_enhancement;
+ };
+
+ // Collect current metrics from the echo controller.
+ virtual Metrics GetMetrics() const = 0;
+
virtual ~EchoControl() {}
};
diff --git a/modules/audio_processing/include/mock_audio_processing.h b/modules/audio_processing/include/mock_audio_processing.h
index d037e56..7cbd166 100644
--- a/modules/audio_processing/include/mock_audio_processing.h
+++ b/modules/audio_processing/include/mock_audio_processing.h
@@ -119,6 +119,7 @@
MOCK_METHOD1(AnalyzeCapture, void(AudioBuffer* capture));
MOCK_METHOD2(ProcessCapture,
void(AudioBuffer* capture, bool echo_path_change));
+ MOCK_CONST_METHOD0(GetMetrics, Metrics());
};
class MockVoiceDetection : public VoiceDetection {