delay_estimator: Allows dynamically used history sizes

Gives the user a possibility to dynamically change the history size. The main advantage is, for example, that you now can start with a wide delay range and over time decrease the search window to lower complexity.

Adds
- two new APIs.
- and updates unit tests.
- a history_size member variable to BinaryDelayEstimator.
- two help function re-allocating buffer memory.

One thing that makes this a little complicated is that you are allowed to have multiple delay estimators with the same reference, so changing the buffer sizes at one place will automatically give you a mismatch at other places.

BUG=3532, 3504
TESTED=trybots and manually
R=aluebs@webrtc.org, kwiberg@webrtc.org

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

git-svn-id: http://webrtc.googlecode.com/svn/trunk@6593 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/webrtc/modules/audio_processing/utility/delay_estimator.c b/webrtc/modules/audio_processing/utility/delay_estimator.c
index 3b20432..60c7a04 100644
--- a/webrtc/modules/audio_processing/utility/delay_estimator.c
+++ b/webrtc/modules/audio_processing/utility/delay_estimator.c
@@ -98,6 +98,7 @@
       kMaxHitsWhenPossiblyNonCausal : kMaxHitsWhenPossiblyCausal;
   int i = 0;
 
+  assert(self->history_size == self->farend->history_size);
   // Reset |candidate_hits| if we have a new candidate.
   if (candidate_delay != self->last_candidate_delay) {
     self->candidate_hits = 0;
@@ -130,7 +131,7 @@
   // 4. All other bins are decreased with |valley_depth|.
   // TODO(bjornv): Investigate how to make this loop more efficient.  Split up
   // the loop?  Remove parts that doesn't add too much.
-  for (i = 0; i < self->farend->history_size; ++i) {
+  for (i = 0; i < self->history_size; ++i) {
     int is_in_last_set = (i >= self->last_delay - 2) &&
         (i <= self->last_delay + 1) && (i != candidate_delay);
     int is_in_candidate_set = (i >= candidate_delay - 2) &&
@@ -277,27 +278,47 @@
     // Sanity conditions fulfilled.
     self = malloc(sizeof(BinaryDelayEstimatorFarend));
   }
-  if (self != NULL) {
-    int malloc_fail = 0;
-
-    self->history_size = history_size;
-
-    // Allocate memory for history buffers.
-    self->binary_far_history = malloc(history_size * sizeof(uint32_t));
-    malloc_fail |= (self->binary_far_history == NULL);
-
-    self->far_bit_counts = malloc(history_size * sizeof(int));
-    malloc_fail |= (self->far_bit_counts == NULL);
-
-    if (malloc_fail) {
-      WebRtc_FreeBinaryDelayEstimatorFarend(self);
-      self = NULL;
-    }
+  if (self == NULL) {
+    return NULL;
   }
 
+  self->history_size = 0;
+  self->binary_far_history = NULL;
+  self->far_bit_counts = NULL;
+  if (WebRtc_AllocateFarendBufferMemory(self, history_size) == 0) {
+    WebRtc_FreeBinaryDelayEstimatorFarend(self);
+    self = NULL;
+  }
   return self;
 }
 
+int WebRtc_AllocateFarendBufferMemory(BinaryDelayEstimatorFarend* self,
+                                      int history_size) {
+  assert(self != NULL);
+  // (Re-)Allocate memory for history buffers.
+  self->binary_far_history =
+      realloc(self->binary_far_history,
+              history_size * sizeof(*self->binary_far_history));
+  self->far_bit_counts = realloc(self->far_bit_counts,
+                                 history_size * sizeof(*self->far_bit_counts));
+  if ((self->binary_far_history == NULL) || (self->far_bit_counts == NULL)) {
+    history_size = 0;
+  }
+  // Fill with zeros if we have expanded the buffers.
+  if (history_size > self->history_size) {
+    int size_diff = history_size - self->history_size;
+    memset(&self->binary_far_history[self->history_size],
+           0,
+           sizeof(*self->binary_far_history) * size_diff);
+    memset(&self->far_bit_counts[self->history_size],
+           0,
+           sizeof(*self->far_bit_counts) * size_diff);
+  }
+  self->history_size = history_size;
+
+  return self->history_size;
+}
+
 void WebRtc_InitBinaryDelayEstimatorFarend(BinaryDelayEstimatorFarend* self) {
   assert(self != NULL);
   memset(self->binary_far_history, 0, sizeof(uint32_t) * self->history_size);
@@ -385,51 +406,84 @@
     // Sanity conditions fulfilled.
     self = malloc(sizeof(BinaryDelayEstimator));
   }
+  if (self == NULL) {
+    return NULL;
+  }
 
-  if (self != NULL) {
-    int malloc_fail = 0;
+  self->farend = farend;
+  self->near_history_size = max_lookahead + 1;
+  self->history_size = 0;
+  self->robust_validation_enabled = 0;  // Disabled by default.
+  self->allowed_offset = 0;
 
-    self->farend = farend;
-    self->near_history_size = max_lookahead + 1;
-    self->robust_validation_enabled = 0;  // Disabled by default.
-    self->allowed_offset = 0;
+  self->lookahead = max_lookahead;
 
-    self->lookahead = max_lookahead;
-
-    // Allocate memory for spectrum buffers.  The extra array element in
-    // |mean_bit_counts| and |histogram| is a dummy element only used while
-    // |last_delay| == -2, i.e., before we have a valid estimate.
-    self->mean_bit_counts =
-        malloc((farend->history_size + 1) * sizeof(int32_t));
-    malloc_fail |= (self->mean_bit_counts == NULL);
-
-    self->bit_counts = malloc(farend->history_size * sizeof(int32_t));
-    malloc_fail |= (self->bit_counts == NULL);
-
-    // Allocate memory for history buffers.
-    self->binary_near_history = malloc((max_lookahead + 1) * sizeof(uint32_t));
-    malloc_fail |= (self->binary_near_history == NULL);
-
-    self->histogram = malloc((farend->history_size + 1) * sizeof(float));
-    malloc_fail |= (self->histogram == NULL);
-
-    if (malloc_fail) {
-      WebRtc_FreeBinaryDelayEstimator(self);
-      self = NULL;
-    }
+  // Allocate memory for spectrum and history buffers.
+  self->mean_bit_counts = NULL;
+  self->bit_counts = NULL;
+  self->histogram = NULL;
+  self->binary_near_history =
+      malloc((max_lookahead + 1) * sizeof(*self->binary_near_history));
+  if (self->binary_near_history == NULL ||
+      WebRtc_AllocateHistoryBufferMemory(self, farend->history_size) == 0) {
+    WebRtc_FreeBinaryDelayEstimator(self);
+    self = NULL;
   }
 
   return self;
 }
 
+int WebRtc_AllocateHistoryBufferMemory(BinaryDelayEstimator* self,
+                                       int history_size) {
+  BinaryDelayEstimatorFarend* far = self->farend;
+  // (Re-)Allocate memory for spectrum and history buffers.
+  if (history_size != far->history_size) {
+    // Only update far-end buffers if we need.
+    history_size = WebRtc_AllocateFarendBufferMemory(far, history_size);
+  }
+  // The extra array element in |mean_bit_counts| and |histogram| is a dummy
+  // element only used while |last_delay| == -2, i.e., before we have a valid
+  // estimate.
+  self->mean_bit_counts =
+      realloc(self->mean_bit_counts,
+              (history_size + 1) * sizeof(*self->mean_bit_counts));
+  self->bit_counts =
+      realloc(self->bit_counts, history_size * sizeof(*self->bit_counts));
+  self->histogram =
+      realloc(self->histogram, (history_size + 1) * sizeof(*self->histogram));
+
+  if ((self->mean_bit_counts == NULL) ||
+      (self->bit_counts == NULL) ||
+      (self->histogram == NULL)) {
+    history_size = 0;
+  }
+  // Fill with zeros if we have expanded the buffers.
+  if (history_size > self->history_size) {
+    int size_diff = history_size - self->history_size;
+    memset(&self->mean_bit_counts[self->history_size],
+           0,
+           sizeof(*self->mean_bit_counts) * size_diff);
+    memset(&self->bit_counts[self->history_size],
+           0,
+           sizeof(*self->bit_counts) * size_diff);
+    memset(&self->histogram[self->history_size],
+           0,
+           sizeof(*self->histogram) * size_diff);
+  }
+  self->history_size = history_size;
+
+  return self->history_size;
+}
+
 void WebRtc_InitBinaryDelayEstimator(BinaryDelayEstimator* self) {
   int i = 0;
   assert(self != NULL);
 
-  memset(self->bit_counts, 0, sizeof(int32_t) * self->farend->history_size);
-  memset(self->binary_near_history, 0,
+  memset(self->bit_counts, 0, sizeof(int32_t) * self->history_size);
+  memset(self->binary_near_history,
+         0,
          sizeof(uint32_t) * self->near_history_size);
-  for (i = 0; i <= self->farend->history_size; ++i) {
+  for (i = 0; i <= self->history_size; ++i) {
     self->mean_bit_counts[i] = (20 << 9);  // 20 in Q9.
     self->histogram[i] = 0.f;
   }
@@ -440,7 +494,7 @@
   self->last_delay = -2;
 
   self->last_candidate_delay = -2;
-  self->compare_delay = self->farend->history_size;
+  self->compare_delay = self->history_size;
   self->candidate_hits = 0;
   self->last_delay_histogram = 0.f;
 }
@@ -471,6 +525,10 @@
   int32_t valley_depth = 0;
 
   assert(self != NULL);
+  if (self->farend->history_size != self->history_size) {
+    // Non matching history sizes.
+    return -1;
+  }
   if (self->near_history_size > 1) {
     // If we apply lookahead, shift near-end binary spectrum history. Insert
     // current |binary_near_spectrum| and pull out the delayed one.
@@ -482,10 +540,10 @@
 
   // Compare with delayed spectra and store the |bit_counts| for each delay.
   BitCountComparison(binary_near_spectrum, self->farend->binary_far_history,
-                     self->farend->history_size, self->bit_counts);
+                     self->history_size, self->bit_counts);
 
   // Update |mean_bit_counts|, which is the smoothed version of |bit_counts|.
-  for (i = 0; i < self->farend->history_size; i++) {
+  for (i = 0; i < self->history_size; i++) {
     // |bit_counts| is constrained to [0, 32], meaning we can smooth with a
     // factor up to 2^26. We use Q9.
     int32_t bit_count = (self->bit_counts[i] << 9);  // Q9.
@@ -503,7 +561,7 @@
 
   // Find |candidate_delay|, |value_best_candidate| and |value_worst_candidate|
   // of |mean_bit_counts|.
-  for (i = 0; i < self->farend->history_size; i++) {
+  for (i = 0; i < self->history_size; i++) {
     if (self->mean_bit_counts[i] < value_best_candidate) {
       value_best_candidate = self->mean_bit_counts[i];
       candidate_delay = i;
diff --git a/webrtc/modules/audio_processing/utility/delay_estimator.h b/webrtc/modules/audio_processing/utility/delay_estimator.h
index 3d5ffce..65c3f03 100644
--- a/webrtc/modules/audio_processing/utility/delay_estimator.h
+++ b/webrtc/modules/audio_processing/utility/delay_estimator.h
@@ -36,6 +36,7 @@
   // Binary history variables.
   uint32_t* binary_near_history;
   int near_history_size;
+  int history_size;
 
   // Delay estimation variables.
   int32_t minimum_probability;
@@ -85,6 +86,19 @@
 BinaryDelayEstimatorFarend* WebRtc_CreateBinaryDelayEstimatorFarend(
     int history_size);
 
+// Re-allocates the buffers.
+//
+// Inputs:
+//      - self            : Pointer to the binary estimation far-end instance
+//                          which is the return value of
+//                          WebRtc_CreateBinaryDelayEstimatorFarend().
+//      - history_size    : Size of the far-end binary spectrum history.
+//
+// Return value:
+//      - history_size    : The history size allocated.
+int WebRtc_AllocateFarendBufferMemory(BinaryDelayEstimatorFarend* self,
+                                      int history_size);
+
 // Initializes the delay estimation far-end instance created with
 // WebRtc_CreateBinaryDelayEstimatorFarend(...).
 //
@@ -141,6 +155,20 @@
 BinaryDelayEstimator* WebRtc_CreateBinaryDelayEstimator(
     BinaryDelayEstimatorFarend* farend, int max_lookahead);
 
+// Re-allocates |history_size| dependent buffers. The far-end buffers will be
+// updated at the same time if needed.
+//
+// Input:
+//      - self            : Pointer to the binary estimation instance which is
+//                          the return value of
+//                          WebRtc_CreateBinaryDelayEstimator().
+//      - history_size    : Size of the history buffers.
+//
+// Return value:
+//      - history_size    : The history size allocated.
+int WebRtc_AllocateHistoryBufferMemory(BinaryDelayEstimator* self,
+                                       int history_size);
+
 // Initializes the delay estimation instance created with
 // WebRtc_CreateBinaryDelayEstimator(...).
 //
@@ -220,5 +248,4 @@
                              int factor,
                              int32_t* mean_value);
 
-
 #endif  // WEBRTC_MODULES_AUDIO_PROCESSING_UTILITY_DELAY_ESTIMATOR_H_
diff --git a/webrtc/modules/audio_processing/utility/delay_estimator_unittest.cc b/webrtc/modules/audio_processing/utility/delay_estimator_unittest.cc
index ca0901d..3b354d0 100644
--- a/webrtc/modules/audio_processing/utility/delay_estimator_unittest.cc
+++ b/webrtc/modules/audio_processing/utility/delay_estimator_unittest.cc
@@ -23,9 +23,13 @@
 // Delay history sizes.
 enum { kMaxDelay = 100 };
 enum { kLookahead = 10 };
+enum { kHistorySize = kMaxDelay + kLookahead };
 // Length of binary spectrum sequence.
 enum { kSequenceLength = 400 };
 
+const int kDifferentHistorySize = 3;
+const int kDifferentLookahead = 1;
+
 const int kEnable[] = { 0, 1 };
 const size_t kSizeEnable = sizeof(kEnable) / sizeof(*kEnable);
 
@@ -56,7 +60,7 @@
   float near_f_[kSpectrumSize];
   uint16_t far_u16_[kSpectrumSize];
   uint16_t near_u16_[kSpectrumSize];
-  uint32_t binary_spectrum_[kSequenceLength + kMaxDelay + kLookahead];
+  uint32_t binary_spectrum_[kSequenceLength + kHistorySize];
 };
 
 DelayEstimatorTest::DelayEstimatorTest()
@@ -76,21 +80,20 @@
   // |kSequenceLength| has to be long enough for the delay estimation to leave
   // the initialized state.
   binary_spectrum_[0] = 1;
-  for (int i = 1; i < (kSequenceLength + kMaxDelay + kLookahead); i++) {
+  for (int i = 1; i < (kSequenceLength + kHistorySize); i++) {
     binary_spectrum_[i] = 3 * binary_spectrum_[i - 1];
   }
 }
 
 void DelayEstimatorTest::SetUp() {
   farend_handle_ = WebRtc_CreateDelayEstimatorFarend(kSpectrumSize,
-                                                     kMaxDelay + kLookahead);
+                                                     kHistorySize);
   ASSERT_TRUE(farend_handle_ != NULL);
   farend_self_ = reinterpret_cast<DelayEstimatorFarend*>(farend_handle_);
   handle_ = WebRtc_CreateDelayEstimator(farend_handle_, kLookahead);
   ASSERT_TRUE(handle_ != NULL);
   self_ = reinterpret_cast<DelayEstimator*>(handle_);
-  binary_farend_ = WebRtc_CreateBinaryDelayEstimatorFarend(kMaxDelay +
-                                                           kLookahead);
+  binary_farend_ = WebRtc_CreateBinaryDelayEstimatorFarend(kHistorySize);
   ASSERT_TRUE(binary_farend_ != NULL);
   binary_ = WebRtc_CreateBinaryDelayEstimator(binary_farend_, kLookahead);
   ASSERT_TRUE(binary_ != NULL);
@@ -226,7 +229,7 @@
   // Make sure we have a non-NULL value at start, so we can detect NULL after
   // create failure.
   void* handle = farend_handle_;
-  handle = WebRtc_CreateDelayEstimatorFarend(33, kMaxDelay + kLookahead);
+  handle = WebRtc_CreateDelayEstimatorFarend(33, kHistorySize);
   EXPECT_TRUE(handle == NULL);
   handle = WebRtc_CreateDelayEstimatorFarend(kSpectrumSize, 1);
   EXPECT_TRUE(handle == NULL);
@@ -266,6 +269,28 @@
   EXPECT_EQ(-1, WebRtc_AddFarSpectrumFix(farend_handle_, far_u16_,
                                          spectrum_size_, 16));
 
+  // WebRtc_set_history_size() should return -1 if:
+  // 1) |handle| is a NULL.
+  // 2) |history_size| <= 1.
+  EXPECT_EQ(-1, WebRtc_set_history_size(NULL, 1));
+  EXPECT_EQ(-1, WebRtc_set_history_size(handle_, 1));
+  // WebRtc_history_size() should return -1 if:
+  // 1) NULL pointer input.
+  EXPECT_EQ(-1, WebRtc_history_size(NULL));
+  // 2) there is a mismatch between history size.
+  void* tmp_handle = WebRtc_CreateDelayEstimator(farend_handle_, kHistorySize);
+  EXPECT_EQ(0, WebRtc_InitDelayEstimator(tmp_handle));
+  EXPECT_EQ(kDifferentHistorySize,
+            WebRtc_set_history_size(tmp_handle, kDifferentHistorySize));
+  EXPECT_EQ(kDifferentHistorySize, WebRtc_history_size(tmp_handle));
+  EXPECT_EQ(kHistorySize, WebRtc_set_history_size(handle_, kHistorySize));
+  EXPECT_EQ(-1, WebRtc_history_size(tmp_handle));
+
+  // WebRtc_set_lookahead() should return -1 if we try a value outside the
+  /// buffer.
+  EXPECT_EQ(-1, WebRtc_set_lookahead(handle_, kLookahead + 1));
+  EXPECT_EQ(-1, WebRtc_set_lookahead(handle_, -1));
+
   // WebRtc_set_allowed_offset() should return -1 if we have:
   // 1) NULL pointer as |handle|.
   // 2) |allowed_offset| < 0.
@@ -289,6 +314,8 @@
   // 1) NULL pointer as |handle|.
   // 2) NULL pointer as near-end spectrum.
   // 3) Incorrect spectrum size.
+  // 4) Non matching history sizes if multiple delay estimators using the same
+  //    far-end reference.
   EXPECT_EQ(-1, WebRtc_DelayEstimatorProcessFloat(NULL, near_f_,
                                                   spectrum_size_));
   // Use |handle_| which is properly created at SetUp().
@@ -296,12 +323,18 @@
                                                   spectrum_size_));
   EXPECT_EQ(-1, WebRtc_DelayEstimatorProcessFloat(handle_, near_f_,
                                                   spectrum_size_ + 1));
+  // |tmp_handle| is already in a non-matching state.
+  EXPECT_EQ(-1, WebRtc_DelayEstimatorProcessFloat(tmp_handle,
+                                                  near_f_,
+                                                  spectrum_size_));
 
   // WebRtc_DelayEstimatorProcessFix() should return -1 if we have:
   // 1) NULL pointer as |handle|.
-  // 3) NULL pointer as near-end spectrum.
-  // 4) Incorrect spectrum size.
-  // 6) Too high precision in near-end spectrum (Q-domain > 15).
+  // 2) NULL pointer as near-end spectrum.
+  // 3) Incorrect spectrum size.
+  // 4) Too high precision in near-end spectrum (Q-domain > 15).
+  // 5) Non matching history sizes if multiple delay estimators using the same
+  //    far-end reference.
   EXPECT_EQ(-1, WebRtc_DelayEstimatorProcessFix(NULL, near_u16_, spectrum_size_,
                                                 0));
   EXPECT_EQ(-1, WebRtc_DelayEstimatorProcessFix(handle_, NULL, spectrum_size_,
@@ -310,6 +343,12 @@
                                                 spectrum_size_ + 1, 0));
   EXPECT_EQ(-1, WebRtc_DelayEstimatorProcessFix(handle_, near_u16_,
                                                 spectrum_size_, 16));
+  // |tmp_handle| is already in a non-matching state.
+  EXPECT_EQ(-1, WebRtc_DelayEstimatorProcessFix(tmp_handle,
+                                                near_u16_,
+                                                spectrum_size_,
+                                                0));
+  WebRtc_FreeDelayEstimator(tmp_handle);
 
   // WebRtc_last_delay() should return -1 if we have a NULL pointer as |handle|.
   EXPECT_EQ(-1, WebRtc_last_delay(NULL));
@@ -536,6 +575,32 @@
   WebRtc_FreeDelayEstimatorFarend(farend_handle);
 }
 
+TEST_F(DelayEstimatorTest, VerifyLookaheadIsSetAndKeptAfterInit) {
+  EXPECT_EQ(kLookahead, WebRtc_lookahead(handle_));
+  EXPECT_EQ(kDifferentLookahead,
+            WebRtc_set_lookahead(handle_, kDifferentLookahead));
+  EXPECT_EQ(kDifferentLookahead, WebRtc_lookahead(handle_));
+  EXPECT_EQ(0, WebRtc_InitDelayEstimatorFarend(farend_handle_));
+  EXPECT_EQ(kDifferentLookahead, WebRtc_lookahead(handle_));
+  EXPECT_EQ(0, WebRtc_InitDelayEstimator(handle_));
+  EXPECT_EQ(kDifferentLookahead, WebRtc_lookahead(handle_));
+}
+
+TEST_F(DelayEstimatorTest, VerifyHistorySizeAtCreate) {
+  EXPECT_EQ(kHistorySize, WebRtc_history_size(handle_));
+}
+
+TEST_F(DelayEstimatorTest, VerifyHistorySizeIsSetAndKeptAfterInit) {
+  EXPECT_EQ(kHistorySize, WebRtc_history_size(handle_));
+  EXPECT_EQ(kDifferentHistorySize,
+            WebRtc_set_history_size(handle_, kDifferentHistorySize));
+  EXPECT_EQ(kDifferentHistorySize, WebRtc_history_size(handle_));
+  EXPECT_EQ(0, WebRtc_InitDelayEstimator(handle_));
+  EXPECT_EQ(kDifferentHistorySize, WebRtc_history_size(handle_));
+  EXPECT_EQ(0, WebRtc_InitDelayEstimatorFarend(farend_handle_));
+  EXPECT_EQ(kDifferentHistorySize, WebRtc_history_size(handle_));
+}
+
 // TODO(bjornv): Add tests for SoftReset...(...).
 
 }  // namespace
diff --git a/webrtc/modules/audio_processing/utility/delay_estimator_wrapper.c b/webrtc/modules/audio_processing/utility/delay_estimator_wrapper.c
index 6ec894e..5c8be67 100644
--- a/webrtc/modules/audio_processing/utility/delay_estimator_wrapper.c
+++ b/webrtc/modules/audio_processing/utility/delay_estimator_wrapper.c
@@ -147,7 +147,7 @@
   COMPILE_ASSERT(kBandLast - kBandFirst < 32);
 
   if (spectrum_size >= kBandLast) {
-    self = malloc(sizeof(DelayEstimator));
+    self = malloc(sizeof(DelayEstimatorFarend));
   }
 
   if (self != NULL) {
@@ -324,6 +324,29 @@
   return WebRtc_SoftResetBinaryDelayEstimator(self->binary_handle, delay_shift);
 }
 
+int WebRtc_set_history_size(void* handle, int history_size) {
+  DelayEstimator* self = handle;
+
+  if ((self == NULL) || (history_size <= 1)) {
+    return -1;
+  }
+  return WebRtc_AllocateHistoryBufferMemory(self->binary_handle, history_size);
+}
+
+int WebRtc_history_size(const void* handle) {
+  const DelayEstimator* self = handle;
+
+  if (self == NULL) {
+    return -1;
+  }
+  if (self->binary_handle->farend->history_size !=
+      self->binary_handle->history_size) {
+    // Non matching history sizes.
+    return -1;
+  }
+  return self->binary_handle->history_size;
+}
+
 int WebRtc_set_lookahead(void* handle, int lookahead) {
   DelayEstimator* self = (DelayEstimator*) handle;
   assert(self != NULL);
diff --git a/webrtc/modules/audio_processing/utility/delay_estimator_wrapper.h b/webrtc/modules/audio_processing/utility/delay_estimator_wrapper.h
index 13e86bd..68463d2 100644
--- a/webrtc/modules/audio_processing/utility/delay_estimator_wrapper.h
+++ b/webrtc/modules/audio_processing/utility/delay_estimator_wrapper.h
@@ -17,9 +17,6 @@
 #include "webrtc/typedefs.h"
 
 // Releases the memory allocated by WebRtc_CreateDelayEstimatorFarend(...)
-// Input:
-//      - handle        : Pointer to the delay estimation far-end instance.
-//
 void WebRtc_FreeDelayEstimatorFarend(void* handle);
 
 // Allocates the memory needed by the far-end part of the delay estimation. The
@@ -27,36 +24,28 @@
 // WebRtc_InitDelayEstimatorFarend(...).
 //
 // Inputs:
-//      - spectrum_size : Size of the spectrum used both in far-end and
+//  - spectrum_size     : Size of the spectrum used both in far-end and
 //                        near-end. Used to allocate memory for spectrum
 //                        specific buffers.
-//      - history_size  : The far-end history buffer size. Note that the maximum
-//                        delay which can be estimated is controlled together
-//                        with |lookahead| through
-//                        WebRtc_CreateDelayEstimator().
+//  - history_size      : The far-end history buffer size. A change in buffer
+//                        size can be forced with WebRtc_set_history_size().
+//                        Note that the maximum delay which can be estimated is
+//                        determined together with WebRtc_set_lookahead().
 //
 // Return value:
-//      - void*         : Created |handle|. If the memory can't be allocated or
+//  - void*             : Created |handle|. If the memory can't be allocated or
 //                        if any of the input parameters are invalid NULL is
 //                        returned.
-//
 void* WebRtc_CreateDelayEstimatorFarend(int spectrum_size, int history_size);
 
 // Initializes the far-end part of the delay estimation instance returned by
 // WebRtc_CreateDelayEstimatorFarend(...)
-// Input:
-//      - handle        : Pointer to the delay estimation far-end instance.
-//
-// Output:
-//      - handle        : Initialized instance.
-//
 int WebRtc_InitDelayEstimatorFarend(void* handle);
 
 // Soft resets the far-end part of the delay estimation instance returned by
 // WebRtc_CreateDelayEstimatorFarend(...).
 // Input:
 //      - delay_shift   : The amount of blocks to shift history buffers.
-//
 void WebRtc_SoftResetDelayEstimatorFarend(void* handle, int delay_shift);
 
 // Adds the far-end spectrum to the far-end history buffer. This spectrum is
@@ -64,15 +53,10 @@
 // WebRtc_ProcessSpectrum().
 //
 // Inputs:
-//    - handle          : Pointer to the delay estimation far-end instance.
 //    - far_spectrum    : Far-end spectrum.
 //    - spectrum_size   : The size of the data arrays (same for both far- and
 //                        near-end).
 //    - far_q           : The Q-domain of the far-end data.
-//
-// Output:
-//    - handle          : Updated far-end instance.
-//
 int WebRtc_AddFarSpectrumFix(void* handle, uint16_t* far_spectrum,
                              int spectrum_size, int far_q);
 
@@ -81,9 +65,6 @@
                                int spectrum_size);
 
 // Releases the memory allocated by WebRtc_CreateDelayEstimator(...)
-// Input:
-//      - handle        : Pointer to the delay estimation instance.
-//
 void WebRtc_FreeDelayEstimator(void* handle);
 
 // Allocates the memory needed by the delay estimation. The memory needs to be
@@ -117,24 +98,17 @@
 //
 //                        Note that the effective range of delay estimates is
 //                        [-|lookahead|,... ,|history_size|-|lookahead|)
-//                        where |history_size| was set upon creating the far-end
-//                        history buffer size.
+//                        where |history_size| is set through
+//                        WebRtc_set_history_size().
 //
 // Return value:
 //      - void*         : Created |handle|. If the memory can't be allocated or
 //                        if any of the input parameters are invalid NULL is
 //                        returned.
-//
 void* WebRtc_CreateDelayEstimator(void* farend_handle, int max_lookahead);
 
 // Initializes the delay estimation instance returned by
 // WebRtc_CreateDelayEstimator(...)
-// Input:
-//      - handle        : Pointer to the delay estimation instance.
-//
-// Output:
-//      - handle        : Initialized instance.
-//
 int WebRtc_InitDelayEstimator(void* handle);
 
 // Soft resets the delay estimation instance returned by
@@ -144,22 +118,44 @@
 //
 // Return value:
 //      - actual_shifts : The actual number of shifts performed.
-//
 int WebRtc_SoftResetDelayEstimator(void* handle, int delay_shift);
 
+// Sets the effective |history_size| used. Valid values from 2. We simply need
+// at least two delays to compare to perform an estimate. If |history_size| is
+// changed, buffers are reallocated filling in with zeros if necessary.
+// Note that changing the |history_size| affects both buffers in far-end and
+// near-end. Hence it is important to change all DelayEstimators that use the
+// same reference far-end, to the same |history_size| value.
+// Inputs:
+//  - handle            : Pointer to the delay estimation instance.
+//  - history_size      : Effective history size to be used.
+// Return value:
+//  - new_history_size  : The new history size used. If the memory was not able
+//                        to be allocated 0 is returned.
+int WebRtc_set_history_size(void* handle, int history_size);
+
+// Returns the history_size currently used.
+// Input:
+//      - handle        : Pointer to the delay estimation instance.
+int WebRtc_history_size(const void* handle);
+
 // Sets the amount of |lookahead| to use. Valid values are [0, max_lookahead]
 // where |max_lookahead| was set at create time through
 // WebRtc_CreateDelayEstimator(...).
 //
 // Input:
-//      - lookahead     : The amount of blocks to shift history buffers.
+//      - handle        : Pointer to the delay estimation instance.
+//      - lookahead     : The amount of lookahead to be used.
 //
 // Return value:
-//      - new_lookahead : The actual number of shifts performed.
-//
+//      - new_lookahead : The actual amount of lookahead set, unless |handle| is
+//                        a NULL pointer or |lookahead| is invalid, for which an
+//                        error is returned.
 int WebRtc_set_lookahead(void* handle, int lookahead);
 
 // Returns the amount of lookahead we currently use.
+// Input:
+//      - handle        : Pointer to the delay estimation instance.
 int WebRtc_lookahead(void* handle);
 
 // Sets the |allowed_offset| used in the robust validation scheme.  If the
@@ -178,8 +174,6 @@
 // Returns the |allowed_offset| in number of partitions.
 int WebRtc_get_allowed_offset(const void* handle);
 
-// TODO(bjornv): Implement this functionality.  Currently, enabling it has no
-// impact, hence this is an empty API.
 // Enables/Disables a robust validation functionality in the delay estimation.
 // This is by default set to disabled at create time.  The state is preserved
 // over a reset.
@@ -209,7 +203,6 @@
 //      - delay         :  >= 0 - Calculated delay value.
 //                        -1    - Error.
 //                        -2    - Insufficient data for estimation.
-//
 int WebRtc_DelayEstimatorProcessFix(void* handle,
                                     uint16_t* near_spectrum,
                                     int spectrum_size,
@@ -230,7 +223,6 @@
 //      - delay         : >= 0  - Last calculated delay value.
 //                        -1    - Error.
 //                        -2    - Insufficient data for estimation.
-//
 int WebRtc_last_delay(void* handle);
 
 // Returns the estimation quality/probability of the last calculated delay