audio_processing: Use fixed aggregation window in delay metrics

Previously, the delay estimate history was reset every time the metrics were pulled. This required all clients to be on the same thread and make use of one call.

Now we use a fixed aggregation window of one second and when a client pulls the metrics you get the latest value.
Under certain circumstances like tests you would like to have the aggregation window set to the recording length. We therefore turn on the fixed aggregation window after the first call.

BUG=2994
TESTED=locally on Mac and trybots
R=kwiberg@webrtc.org

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

Cr-Commit-Position: refs/heads/master@{#8170}
git-svn-id: http://webrtc.googlecode.com/svn/trunk@8170 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/webrtc/modules/audio_processing/aec/aec_core.c b/webrtc/modules/audio_processing/aec/aec_core.c
index 5af3651..1f864fc 100644
--- a/webrtc/modules/audio_processing/aec/aec_core.c
+++ b/webrtc/modules/audio_processing/aec/aec_core.c
@@ -39,6 +39,7 @@
 // Metrics
 static const int subCountLen = 4;
 static const int countLen = 50;
+static const int kDelayMetricsAggregationWindow = 250;  // One second at 16 kHz.
 
 // Quantities to control H band scaling for SWB input
 static const int flagHbandCn = 1;  // flag for adding comfort noise in H band
@@ -772,16 +773,11 @@
 static void UpdateDelayMetrics(AecCore* self) {
   int i = 0;
   int delay_values = 0;
-  int num_delay_values = 0;
   int median = 0;
   const int kMsPerBlock = PART_LEN / (self->mult * 8);
   int64_t l1_norm = 0;
 
-  // Get number of delay values since last update.
-  for (i = 0; i < kHistorySizeBlocks; i++) {
-    num_delay_values += self->delay_histogram[i];
-  }
-  if (num_delay_values == 0) {
+  if (self->num_delay_values == 0) {
     // We have no new delay value data. Even though -1 is a valid |median| in
     // the sense that we allow negative values, it will practically never be
     // used since multiples of |kMsPerBlock| will always be returned.
@@ -792,7 +788,8 @@
     return;
   }
 
-  delay_values = num_delay_values >> 1;  // Start value for median count down.
+  // Start value for median count down.
+  delay_values = self->num_delay_values >> 1;
   // Get median of delay values since last update.
   for (i = 0; i < kHistorySizeBlocks; i++) {
     delay_values -= self->delay_histogram[i];
@@ -809,11 +806,12 @@
   for (i = 0; i < kHistorySizeBlocks; i++) {
     l1_norm += abs(i - median) * self->delay_histogram[i];
   }
-  self->delay_std = (int)((l1_norm + num_delay_values / 2) / num_delay_values) *
-      kMsPerBlock;
+  self->delay_std = (int)((l1_norm + self->num_delay_values / 2) /
+      self->num_delay_values) * kMsPerBlock;
 
   // Reset histogram.
   memset(self->delay_histogram, 0, sizeof(self->delay_histogram));
+  self->num_delay_values = 0;
 
   return;
 }
@@ -1247,6 +1245,11 @@
       if (delay_estimate >= 0) {
         // Update delay estimate buffer.
         aec->delay_histogram[delay_estimate]++;
+        aec->num_delay_values++;
+      }
+      if (aec->delay_metrics_delivered == 1 &&
+          aec->num_delay_values >= kDelayMetricsAggregationWindow) {
+        UpdateDelayMetrics(aec);
       }
     }
   }
@@ -1555,7 +1558,9 @@
     return -1;
   }
   aec->delay_logging_enabled = 0;
+  aec->delay_metrics_delivered = 0;
   memset(aec->delay_histogram, 0, sizeof(aec->delay_histogram));
+  aec->num_delay_values = 0;
   aec->delay_median = -1;
   aec->delay_std = -1;
 
@@ -1838,7 +1843,10 @@
     return -1;
   }
 
-  UpdateDelayMetrics(self);
+  if (self->delay_metrics_delivered == 0) {
+    UpdateDelayMetrics(self);
+    self->delay_metrics_delivered = 1;
+  }
   *median = self->delay_median;
   *std = self->delay_std;
 
diff --git a/webrtc/modules/audio_processing/aec/aec_core_internal.h b/webrtc/modules/audio_processing/aec/aec_core_internal.h
index e0ae193..b9950f6 100644
--- a/webrtc/modules/audio_processing/aec/aec_core_internal.h
+++ b/webrtc/modules/audio_processing/aec/aec_core_internal.h
@@ -126,7 +126,9 @@
   int flag_Hband_cn;     // for comfort noise
   float cn_scale_Hband;  // scale for comfort noise in H band
 
+  int delay_metrics_delivered;
   int delay_histogram[kHistorySizeBlocks];
+  int num_delay_values;
   int delay_median;
   int delay_std;
   int delay_logging_enabled;