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}
This commit is contained in:
Gustaf Ullberg 2017-11-22 14:17:39 +01:00 committed by Commit Bot
parent 63e232a2cf
commit 332150d7df
14 changed files with 62 additions and 3 deletions

View File

@ -50,11 +50,17 @@ class AecState {
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_; }

View File

@ -40,6 +40,8 @@ class BlockProcessorImpl final : public BlockProcessor {
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 @@ void BlockProcessorImpl::UpdateEchoLeakageStatus(bool leakage_detected) {
echo_remover_->UpdateEchoLeakageStatus(leakage_detected);
}
void BlockProcessorImpl::GetMetrics(EchoControl::Metrics* metrics) const {
echo_remover_->GetMetrics(metrics);
}
} // namespace
BlockProcessor* BlockProcessor::Create(const EchoCanceller3Config& config,

View File

@ -39,6 +39,9 @@ class BlockProcessor {
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,

View File

@ -323,6 +323,13 @@ void EchoCanceller3::ProcessCapture(AudioBuffer* capture, bool level_change) {
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;
}

View File

@ -79,6 +79,8 @@ class EchoCanceller3 : public EchoControl {
// 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.

View File

@ -102,6 +102,8 @@ class CaptureTransportVerificationProcessor : public BlockProcessor {
void UpdateEchoLeakageStatus(bool leakage_detected) override {}
void GetMetrics(EchoControl::Metrics* metrics) const override {}
private:
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(CaptureTransportVerificationProcessor);
};
@ -128,6 +130,8 @@ class RenderTransportVerificationProcessor : public BlockProcessor {
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);

View File

@ -53,6 +53,8 @@ class EchoRemoverImpl final : public EchoRemover {
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(const EchoCanceller3Config& config,
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,

View File

@ -27,6 +27,9 @@ class EchoRemover {
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.

View File

@ -31,7 +31,7 @@ class ErleEstimator {
// 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_;

View File

@ -30,6 +30,7 @@ class MockBlockProcessor : public BlockProcessor {
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

View File

@ -34,6 +34,7 @@ class MockEchoRemover : public EchoRemover {
std::vector<std::vector<float>>* capture));
MOCK_METHOD1(UpdateEchoLeakageStatus, void(bool leakage_detected));
MOCK_CONST_METHOD1(GetMetrics, void(EchoControl::Metrics* metrics));
};
} // namespace test

View File

@ -1608,8 +1608,16 @@ AudioProcessing::AudioProcessingStats AudioProcessingImpl::GetStatistics(
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);

View File

@ -940,6 +940,14 @@ class EchoControl {
// 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() {}
};

View File

@ -119,6 +119,7 @@ class MockEchoControl : public EchoControl {
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 {