From a2d8b75f291a3c33e337bbf7a527f8b4e9e32f19 Mon Sep 17 00:00:00 2001
From: "bjornv@webrtc.org"
 <bjornv@webrtc.org@4adac7df-926f-26a2-2b94-8c16560cd09d>
Date: Fri, 18 Jan 2013 21:54:15 +0000
Subject: [PATCH] An API to get the internal estimation quality in the delay
 estimator has been added. Unit tests have been updated. There is no impact to
 other parts in WebRTC.

BUG=None

Review URL: https://webrtc-codereview.appspot.com/1036004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@3390 4adac7df-926f-26a2-2b94-8c16560cd09d
---
 .../audio_processing/utility/delay_estimator.c   | 14 +++++++++++++-
 .../audio_processing/utility/delay_estimator.h   | 14 ++++++++++++++
 .../utility/delay_estimator_unittest.cc          | 11 +++++++++++
 .../utility/delay_estimator_wrapper.c            | 10 ++++++++++
 .../utility/delay_estimator_wrapper.h            | 16 ++++++++++++++++
 5 files changed, 64 insertions(+), 1 deletion(-)

diff --git a/webrtc/modules/audio_processing/utility/delay_estimator.c b/webrtc/modules/audio_processing/utility/delay_estimator.c
index 3d1d7c49e..355a6b944 100644
--- a/webrtc/modules/audio_processing/utility/delay_estimator.c
+++ b/webrtc/modules/audio_processing/utility/delay_estimator.c
@@ -157,7 +157,7 @@ int WebRtc_ProcessBinarySpectrum(BinaryDelayEstimator* handle,
   int i = 0;
   int candidate_delay = -1;
 
-  int32_t value_best_candidate = 16384;  // 32 in Q9, (max |mean_bit_counts|).
+  int32_t value_best_candidate = 32 << 9;  // 32 in Q9, (max |mean_bit_counts|).
   int32_t value_worst_candidate = 0;
 
   assert(handle != NULL);
@@ -269,6 +269,18 @@ int WebRtc_binary_last_delay(BinaryDelayEstimator* handle) {
   return handle->last_delay;
 }
 
+int WebRtc_binary_last_delay_quality(BinaryDelayEstimator* handle) {
+  assert(handle != NULL);
+  // |last_delay_probability| is the opposite of quality and states how deep the
+  // minimum of the cost function is. The value states how many non-matching
+  // bits we have between the binary spectra for the corresponding delay
+  // estimate. The range is thus from 0 to 32, since we use 32 bits in the
+  // binary spectra.
+
+  // Return the quality = 1 - |last_delay_probability| / 32 (in Q14).
+  return (32 << 9) - handle->last_delay_probability;
+}
+
 void WebRtc_MeanEstimatorFix(int32_t new_value,
                              int factor,
                              int32_t* mean_value) {
diff --git a/webrtc/modules/audio_processing/utility/delay_estimator.h b/webrtc/modules/audio_processing/utility/delay_estimator.h
index 93c4b4e93..97456d195 100644
--- a/webrtc/modules/audio_processing/utility/delay_estimator.h
+++ b/webrtc/modules/audio_processing/utility/delay_estimator.h
@@ -98,6 +98,20 @@ int WebRtc_ProcessBinarySpectrum(BinaryDelayEstimator* handle,
 //
 int WebRtc_binary_last_delay(BinaryDelayEstimator* handle);
 
+// Returns the estimation quality of the last calculated delay updated by the
+// function WebRtc_ProcessBinarySpectrum(...). The estimation quality is a value
+// in the interval [0, 1] in Q14. The higher the value, the better quality.
+//
+// Input:
+//    - handle                : Pointer to the delay estimation instance.
+//
+// Return value:
+//    - delay_quality         :  >= 0 - Estimation quality (in Q14) of last
+//                                      calculated delay value.
+//                              -2    - Insufficient data for estimation.
+//
+int WebRtc_binary_last_delay_quality(BinaryDelayEstimator* handle);
+
 // Updates the |mean_value| recursively with a step size of 2^-|factor|. This
 // function is used internally in the Binary Delay Estimator as well as the
 // Fixed point wrapper.
diff --git a/webrtc/modules/audio_processing/utility/delay_estimator_unittest.cc b/webrtc/modules/audio_processing/utility/delay_estimator_unittest.cc
index aaaeff42d..58599a35e 100644
--- a/webrtc/modules/audio_processing/utility/delay_estimator_unittest.cc
+++ b/webrtc/modules/audio_processing/utility/delay_estimator_unittest.cc
@@ -77,6 +77,8 @@ void DelayEstimatorTest::Init() {
   // Verify initialization.
   EXPECT_EQ(0, self_->far_spectrum_initialized);
   EXPECT_EQ(0, self_->near_spectrum_initialized);
+  EXPECT_EQ(-2, WebRtc_last_delay(handle_));  // Delay in initial state.
+  EXPECT_EQ(0, WebRtc_last_delay_quality(handle_));  // Zero quality.
 }
 
 void DelayEstimatorTest::InitBinary() {
@@ -150,6 +152,10 @@ TEST_F(DelayEstimatorTest, CorrectErrorReturnsOfWrapper) {
   // WebRtc_last_delay() should return -1 if we have a NULL pointer as |handle|.
   EXPECT_EQ(-1, WebRtc_last_delay(NULL));
 
+  // WebRtc_last_delay_quality() should return -1 if we have a NULL pointer as
+  // |handle|.
+  EXPECT_EQ(-1, WebRtc_last_delay_quality(NULL));
+
   // Free any local memory if needed.
   WebRtc_FreeDelayEstimator(handle);
 }
@@ -189,11 +195,13 @@ TEST_F(DelayEstimatorTest, CorrectLastDelay) {
                                                    spectrum_size_);
     if (last_delay != -2) {
       EXPECT_EQ(last_delay, WebRtc_last_delay(handle_));
+      EXPECT_EQ(7203, WebRtc_last_delay_quality(handle_));
       break;
     }
   }
   // Verify that we have left the initialized state.
   EXPECT_NE(-2, WebRtc_last_delay(handle_));
+  EXPECT_NE(0, WebRtc_last_delay_quality(handle_));
 
   // Fixed point operations.
   Init();
@@ -202,11 +210,13 @@ TEST_F(DelayEstimatorTest, CorrectLastDelay) {
                                                  spectrum_size_, 0, 0);
     if (last_delay != -2) {
       EXPECT_EQ(last_delay, WebRtc_last_delay(handle_));
+      EXPECT_EQ(7203, WebRtc_last_delay_quality(handle_));
       break;
     }
   }
   // Verify that we have left the initialized state.
   EXPECT_NE(-2, WebRtc_last_delay(handle_));
+  EXPECT_NE(0, WebRtc_last_delay_quality(handle_));
 }
 
 TEST_F(DelayEstimatorTest, CorrectErrorReturnsOfBinaryEstimator) {
@@ -296,6 +306,7 @@ TEST_F(DelayEstimatorTest, ExactDelayEstimate) {
     }
     // Verify that we have left the initialized state.
     EXPECT_NE(-2, WebRtc_binary_last_delay(binary_handle_));
+    EXPECT_NE(0, WebRtc_binary_last_delay_quality(binary_handle_));
   }
 }
 
diff --git a/webrtc/modules/audio_processing/utility/delay_estimator_wrapper.c b/webrtc/modules/audio_processing/utility/delay_estimator_wrapper.c
index 74918076c..474cb69ba 100644
--- a/webrtc/modules/audio_processing/utility/delay_estimator_wrapper.c
+++ b/webrtc/modules/audio_processing/utility/delay_estimator_wrapper.c
@@ -299,3 +299,13 @@ int WebRtc_last_delay(void* handle) {
 
   return WebRtc_binary_last_delay(self->binary_handle);
 }
+
+int WebRtc_last_delay_quality(void* handle) {
+  DelayEstimator* self = (DelayEstimator*) handle;
+
+  if (self == NULL) {
+    return -1;
+  }
+
+  return WebRtc_binary_last_delay_quality(self->binary_handle);
+}
diff --git a/webrtc/modules/audio_processing/utility/delay_estimator_wrapper.h b/webrtc/modules/audio_processing/utility/delay_estimator_wrapper.h
index 4591e4bf7..3d243db06 100644
--- a/webrtc/modules/audio_processing/utility/delay_estimator_wrapper.h
+++ b/webrtc/modules/audio_processing/utility/delay_estimator_wrapper.h
@@ -106,4 +106,20 @@ int WebRtc_DelayEstimatorProcessFloat(void* handle,
 //
 int WebRtc_last_delay(void* handle);
 
+// Returns the estimation quality/probability of the last calculated delay
+// updated by the function WebRtc_DelayEstimatorProcess(...). The estimation
+// quality is a value in the interval [0, 1] in Q9. The higher the value, the
+// better quality.
+//
+// Input:
+//      - handle        : Pointer to the delay estimation instance.
+//
+// Return value:
+//      - delay_quality :  >= 0 - Estimation quality (in Q9) of last calculated
+//                                delay value.
+//                        -1    - Error.
+//                        -2    - Insufficient data for estimation.
+//
+int WebRtc_last_delay_quality(void* handle);
+
 #endif  // WEBRTC_MODULES_AUDIO_PROCESSING_UTILITY_DELAY_ESTIMATOR_WRAPPER_H_