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 {