1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/*
2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *  Use of this source code is governed by a BSD-style license
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *  that can be found in the LICENSE file in the root of the source
6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *  tree. An additional intellectual property rights grant can be found
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *  in the file PATENTS.  All contributing project authors may
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *  be found in the AUTHORS file in the root of the source tree.
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)extern "C" {
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "webrtc/modules/audio_processing/utility/delay_estimator.h"
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "webrtc/modules/audio_processing/utility/delay_estimator_internal.h"
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "webrtc/modules/audio_processing/utility/delay_estimator_wrapper.h"
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "webrtc/typedefs.h"
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace {
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)enum { kSpectrumSize = 65 };
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Delay history sizes.
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)enum { kMaxDelay = 100 };
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)enum { kLookahead = 10 };
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)enum { kHistorySize = kMaxDelay + kLookahead };
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Length of binary spectrum sequence.
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)enum { kSequenceLength = 400 };
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const int kDifferentHistorySize = 3;
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const int kDifferentLookahead = 1;
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const int kEnable[] = { 0, 1 };
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const size_t kSizeEnable = sizeof(kEnable) / sizeof(*kEnable);
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class DelayEstimatorTest : public ::testing::Test {
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) protected:
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DelayEstimatorTest();
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void SetUp();
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void TearDown();
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void Init();
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void InitBinary();
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void VerifyDelay(BinaryDelayEstimator* binary_handle, int offset, int delay);
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void RunBinarySpectra(BinaryDelayEstimator* binary1,
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                        BinaryDelayEstimator* binary2,
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                        int near_offset, int lookahead_offset, int far_offset);
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void RunBinarySpectraTest(int near_offset, int lookahead_offset,
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                            int ref_robust_validation, int robust_validation);
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void* handle_;
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DelayEstimator* self_;
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void* farend_handle_;
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DelayEstimatorFarend* farend_self_;
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  BinaryDelayEstimator* binary_;
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  BinaryDelayEstimatorFarend* binary_farend_;
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int spectrum_size_;
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Dummy input spectra.
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  float far_f_[kSpectrumSize];
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  float near_f_[kSpectrumSize];
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  uint16_t far_u16_[kSpectrumSize];
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  uint16_t near_u16_[kSpectrumSize];
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  uint32_t binary_spectrum_[kSequenceLength + kHistorySize];
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)DelayEstimatorTest::DelayEstimatorTest()
67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : handle_(NULL),
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      self_(NULL),
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      farend_handle_(NULL),
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      farend_self_(NULL),
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      binary_(NULL),
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      binary_farend_(NULL),
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      spectrum_size_(kSpectrumSize) {
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Dummy input data are set with more or less arbitrary non-zero values.
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  memset(far_f_, 1, sizeof(far_f_));
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  memset(near_f_, 2, sizeof(near_f_));
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  memset(far_u16_, 1, sizeof(far_u16_));
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  memset(near_u16_, 2, sizeof(near_u16_));
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Construct a sequence of binary spectra used to verify delay estimate. The
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // |kSequenceLength| has to be long enough for the delay estimation to leave
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // the initialized state.
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  binary_spectrum_[0] = 1;
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (int i = 1; i < (kSequenceLength + kHistorySize); i++) {
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    binary_spectrum_[i] = 3 * binary_spectrum_[i - 1];
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
87
88void DelayEstimatorTest::SetUp() {
89  farend_handle_ = WebRtc_CreateDelayEstimatorFarend(kSpectrumSize,
90                                                     kHistorySize);
91  ASSERT_TRUE(farend_handle_ != NULL);
92  farend_self_ = reinterpret_cast<DelayEstimatorFarend*>(farend_handle_);
93  handle_ = WebRtc_CreateDelayEstimator(farend_handle_, kLookahead);
94  ASSERT_TRUE(handle_ != NULL);
95  self_ = reinterpret_cast<DelayEstimator*>(handle_);
96  binary_farend_ = WebRtc_CreateBinaryDelayEstimatorFarend(kHistorySize);
97  ASSERT_TRUE(binary_farend_ != NULL);
98  binary_ = WebRtc_CreateBinaryDelayEstimator(binary_farend_, kLookahead);
99  ASSERT_TRUE(binary_ != NULL);
100}
101
102void DelayEstimatorTest::TearDown() {
103  WebRtc_FreeDelayEstimator(handle_);
104  handle_ = NULL;
105  self_ = NULL;
106  WebRtc_FreeDelayEstimatorFarend(farend_handle_);
107  farend_handle_ = NULL;
108  farend_self_ = NULL;
109  WebRtc_FreeBinaryDelayEstimator(binary_);
110  binary_ = NULL;
111  WebRtc_FreeBinaryDelayEstimatorFarend(binary_farend_);
112  binary_farend_ = NULL;
113}
114
115void DelayEstimatorTest::Init() {
116  // Initialize Delay Estimator
117  EXPECT_EQ(0, WebRtc_InitDelayEstimatorFarend(farend_handle_));
118  EXPECT_EQ(0, WebRtc_InitDelayEstimator(handle_));
119  // Verify initialization.
120  EXPECT_EQ(0, farend_self_->far_spectrum_initialized);
121  EXPECT_EQ(0, self_->near_spectrum_initialized);
122  EXPECT_EQ(-2, WebRtc_last_delay(handle_));  // Delay in initial state.
123  EXPECT_FLOAT_EQ(0, WebRtc_last_delay_quality(handle_));  // Zero quality.
124}
125
126void DelayEstimatorTest::InitBinary() {
127  // Initialize Binary Delay Estimator (far-end part).
128  WebRtc_InitBinaryDelayEstimatorFarend(binary_farend_);
129  // Initialize Binary Delay Estimator
130  WebRtc_InitBinaryDelayEstimator(binary_);
131  // Verify initialization. This does not guarantee a complete check, since
132  // |last_delay| may be equal to -2 before initialization if done on the fly.
133  EXPECT_EQ(-2, binary_->last_delay);
134}
135
136void DelayEstimatorTest::VerifyDelay(BinaryDelayEstimator* binary_handle,
137                                     int offset, int delay) {
138  // Verify that we WebRtc_binary_last_delay() returns correct delay.
139  EXPECT_EQ(delay, WebRtc_binary_last_delay(binary_handle));
140
141  if (delay != -2) {
142    // Verify correct delay estimate. In the non-causal case the true delay
143    // is equivalent with the |offset|.
144    EXPECT_EQ(offset, delay);
145  }
146}
147
148void DelayEstimatorTest::RunBinarySpectra(BinaryDelayEstimator* binary1,
149                                          BinaryDelayEstimator* binary2,
150                                          int near_offset,
151                                          int lookahead_offset,
152                                          int far_offset) {
153  int different_validations = binary1->robust_validation_enabled ^
154      binary2->robust_validation_enabled;
155  WebRtc_InitBinaryDelayEstimatorFarend(binary_farend_);
156  WebRtc_InitBinaryDelayEstimator(binary1);
157  WebRtc_InitBinaryDelayEstimator(binary2);
158  // Verify initialization. This does not guarantee a complete check, since
159  // |last_delay| may be equal to -2 before initialization if done on the fly.
160  EXPECT_EQ(-2, binary1->last_delay);
161  EXPECT_EQ(-2, binary2->last_delay);
162  for (int i = kLookahead; i < (kSequenceLength + kLookahead); i++) {
163    WebRtc_AddBinaryFarSpectrum(binary_farend_,
164                                binary_spectrum_[i + far_offset]);
165    int delay_1 = WebRtc_ProcessBinarySpectrum(binary1, binary_spectrum_[i]);
166    int delay_2 =
167        WebRtc_ProcessBinarySpectrum(binary2,
168                                     binary_spectrum_[i - near_offset]);
169
170    VerifyDelay(binary1, far_offset + kLookahead, delay_1);
171    VerifyDelay(binary2,
172                far_offset + kLookahead + lookahead_offset + near_offset,
173                delay_2);
174    // Expect the two delay estimates to be offset by |lookahead_offset| +
175    // |near_offset| when we have left the initial state.
176    if ((delay_1 != -2) && (delay_2 != -2)) {
177      EXPECT_EQ(delay_1, delay_2 - lookahead_offset - near_offset);
178    }
179    // For the case of identical signals |delay_1| and |delay_2| should match
180    // all the time, unless one of them has robust validation turned on.  In
181    // that case the robust validation leaves the initial state faster.
182    if ((near_offset == 0) && (lookahead_offset == 0)) {
183      if  (!different_validations) {
184        EXPECT_EQ(delay_1, delay_2);
185      } else {
186        if (binary1->robust_validation_enabled) {
187          EXPECT_GE(delay_1, delay_2);
188        } else {
189          EXPECT_GE(delay_2, delay_1);
190        }
191      }
192    }
193  }
194  // Verify that we have left the initialized state.
195  EXPECT_NE(-2, WebRtc_binary_last_delay(binary1));
196  EXPECT_LT(0, WebRtc_binary_last_delay_quality(binary1));
197  EXPECT_NE(-2, WebRtc_binary_last_delay(binary2));
198  EXPECT_LT(0, WebRtc_binary_last_delay_quality(binary2));
199}
200
201void DelayEstimatorTest::RunBinarySpectraTest(int near_offset,
202                                              int lookahead_offset,
203                                              int ref_robust_validation,
204                                              int robust_validation) {
205  BinaryDelayEstimator* binary2 =
206      WebRtc_CreateBinaryDelayEstimator(binary_farend_,
207                                        kLookahead + lookahead_offset);
208  // Verify the delay for both causal and non-causal systems. For causal systems
209  // the delay is equivalent with a positive |offset| of the far-end sequence.
210  // For non-causal systems the delay is equivalent with a negative |offset| of
211  // the far-end sequence.
212  binary_->robust_validation_enabled = ref_robust_validation;
213  binary2->robust_validation_enabled = robust_validation;
214  for (int offset = -kLookahead;
215      offset < kMaxDelay - lookahead_offset - near_offset;
216      offset++) {
217    RunBinarySpectra(binary_, binary2, near_offset, lookahead_offset, offset);
218  }
219  WebRtc_FreeBinaryDelayEstimator(binary2);
220  binary2 = NULL;
221  binary_->robust_validation_enabled = 0;  // Reset reference.
222}
223
224TEST_F(DelayEstimatorTest, CorrectErrorReturnsOfWrapper) {
225  // In this test we verify correct error returns on invalid API calls.
226
227  // WebRtc_CreateDelayEstimatorFarend() and WebRtc_CreateDelayEstimator()
228  // should return a NULL pointer on invalid input values.
229  // Make sure we have a non-NULL value at start, so we can detect NULL after
230  // create failure.
231  void* handle = farend_handle_;
232  handle = WebRtc_CreateDelayEstimatorFarend(33, kHistorySize);
233  EXPECT_TRUE(handle == NULL);
234  handle = WebRtc_CreateDelayEstimatorFarend(kSpectrumSize, 1);
235  EXPECT_TRUE(handle == NULL);
236
237  handle = handle_;
238  handle = WebRtc_CreateDelayEstimator(NULL, kLookahead);
239  EXPECT_TRUE(handle == NULL);
240  handle = WebRtc_CreateDelayEstimator(farend_handle_, -1);
241  EXPECT_TRUE(handle == NULL);
242
243  // WebRtc_InitDelayEstimatorFarend() and WebRtc_InitDelayEstimator() should
244  // return -1 if we have a NULL pointer as |handle|.
245  EXPECT_EQ(-1, WebRtc_InitDelayEstimatorFarend(NULL));
246  EXPECT_EQ(-1, WebRtc_InitDelayEstimator(NULL));
247
248  // WebRtc_AddFarSpectrumFloat() should return -1 if we have:
249  // 1) NULL pointer as |handle|.
250  // 2) NULL pointer as far-end spectrum.
251  // 3) Incorrect spectrum size.
252  EXPECT_EQ(-1, WebRtc_AddFarSpectrumFloat(NULL, far_f_, spectrum_size_));
253  // Use |farend_handle_| which is properly created at SetUp().
254  EXPECT_EQ(-1, WebRtc_AddFarSpectrumFloat(farend_handle_, NULL,
255                                           spectrum_size_));
256  EXPECT_EQ(-1, WebRtc_AddFarSpectrumFloat(farend_handle_, far_f_,
257                                           spectrum_size_ + 1));
258
259  // WebRtc_AddFarSpectrumFix() should return -1 if we have:
260  // 1) NULL pointer as |handle|.
261  // 2) NULL pointer as far-end spectrum.
262  // 3) Incorrect spectrum size.
263  // 4) Too high precision in far-end spectrum (Q-domain > 15).
264  EXPECT_EQ(-1, WebRtc_AddFarSpectrumFix(NULL, far_u16_, spectrum_size_, 0));
265  EXPECT_EQ(-1, WebRtc_AddFarSpectrumFix(farend_handle_, NULL, spectrum_size_,
266                                         0));
267  EXPECT_EQ(-1, WebRtc_AddFarSpectrumFix(farend_handle_, far_u16_,
268                                         spectrum_size_ + 1, 0));
269  EXPECT_EQ(-1, WebRtc_AddFarSpectrumFix(farend_handle_, far_u16_,
270                                         spectrum_size_, 16));
271
272  // WebRtc_set_history_size() should return -1 if:
273  // 1) |handle| is a NULL.
274  // 2) |history_size| <= 1.
275  EXPECT_EQ(-1, WebRtc_set_history_size(NULL, 1));
276  EXPECT_EQ(-1, WebRtc_set_history_size(handle_, 1));
277  // WebRtc_history_size() should return -1 if:
278  // 1) NULL pointer input.
279  EXPECT_EQ(-1, WebRtc_history_size(NULL));
280  // 2) there is a mismatch between history size.
281  void* tmp_handle = WebRtc_CreateDelayEstimator(farend_handle_, kHistorySize);
282  EXPECT_EQ(0, WebRtc_InitDelayEstimator(tmp_handle));
283  EXPECT_EQ(kDifferentHistorySize,
284            WebRtc_set_history_size(tmp_handle, kDifferentHistorySize));
285  EXPECT_EQ(kDifferentHistorySize, WebRtc_history_size(tmp_handle));
286  EXPECT_EQ(kHistorySize, WebRtc_set_history_size(handle_, kHistorySize));
287  EXPECT_EQ(-1, WebRtc_history_size(tmp_handle));
288
289  // WebRtc_set_lookahead() should return -1 if we try a value outside the
290  /// buffer.
291  EXPECT_EQ(-1, WebRtc_set_lookahead(handle_, kLookahead + 1));
292  EXPECT_EQ(-1, WebRtc_set_lookahead(handle_, -1));
293
294  // WebRtc_set_allowed_offset() should return -1 if we have:
295  // 1) NULL pointer as |handle|.
296  // 2) |allowed_offset| < 0.
297  EXPECT_EQ(-1, WebRtc_set_allowed_offset(NULL, 0));
298  EXPECT_EQ(-1, WebRtc_set_allowed_offset(handle_, -1));
299
300  EXPECT_EQ(-1, WebRtc_get_allowed_offset(NULL));
301
302  // WebRtc_enable_robust_validation() should return -1 if we have:
303  // 1) NULL pointer as |handle|.
304  // 2) Incorrect |enable| value (not 0 or 1).
305  EXPECT_EQ(-1, WebRtc_enable_robust_validation(NULL, kEnable[0]));
306  EXPECT_EQ(-1, WebRtc_enable_robust_validation(handle_, -1));
307  EXPECT_EQ(-1, WebRtc_enable_robust_validation(handle_, 2));
308
309  // WebRtc_is_robust_validation_enabled() should return -1 if we have NULL
310  // pointer as |handle|.
311  EXPECT_EQ(-1, WebRtc_is_robust_validation_enabled(NULL));
312
313  // WebRtc_DelayEstimatorProcessFloat() should return -1 if we have:
314  // 1) NULL pointer as |handle|.
315  // 2) NULL pointer as near-end spectrum.
316  // 3) Incorrect spectrum size.
317  // 4) Non matching history sizes if multiple delay estimators using the same
318  //    far-end reference.
319  EXPECT_EQ(-1, WebRtc_DelayEstimatorProcessFloat(NULL, near_f_,
320                                                  spectrum_size_));
321  // Use |handle_| which is properly created at SetUp().
322  EXPECT_EQ(-1, WebRtc_DelayEstimatorProcessFloat(handle_, NULL,
323                                                  spectrum_size_));
324  EXPECT_EQ(-1, WebRtc_DelayEstimatorProcessFloat(handle_, near_f_,
325                                                  spectrum_size_ + 1));
326  // |tmp_handle| is already in a non-matching state.
327  EXPECT_EQ(-1, WebRtc_DelayEstimatorProcessFloat(tmp_handle,
328                                                  near_f_,
329                                                  spectrum_size_));
330
331  // WebRtc_DelayEstimatorProcessFix() should return -1 if we have:
332  // 1) NULL pointer as |handle|.
333  // 2) NULL pointer as near-end spectrum.
334  // 3) Incorrect spectrum size.
335  // 4) Too high precision in near-end spectrum (Q-domain > 15).
336  // 5) Non matching history sizes if multiple delay estimators using the same
337  //    far-end reference.
338  EXPECT_EQ(-1, WebRtc_DelayEstimatorProcessFix(NULL, near_u16_, spectrum_size_,
339                                                0));
340  EXPECT_EQ(-1, WebRtc_DelayEstimatorProcessFix(handle_, NULL, spectrum_size_,
341                                                0));
342  EXPECT_EQ(-1, WebRtc_DelayEstimatorProcessFix(handle_, near_u16_,
343                                                spectrum_size_ + 1, 0));
344  EXPECT_EQ(-1, WebRtc_DelayEstimatorProcessFix(handle_, near_u16_,
345                                                spectrum_size_, 16));
346  // |tmp_handle| is already in a non-matching state.
347  EXPECT_EQ(-1, WebRtc_DelayEstimatorProcessFix(tmp_handle,
348                                                near_u16_,
349                                                spectrum_size_,
350                                                0));
351  WebRtc_FreeDelayEstimator(tmp_handle);
352
353  // WebRtc_last_delay() should return -1 if we have a NULL pointer as |handle|.
354  EXPECT_EQ(-1, WebRtc_last_delay(NULL));
355
356  // Free any local memory if needed.
357  WebRtc_FreeDelayEstimator(handle);
358}
359
360TEST_F(DelayEstimatorTest, VerifyAllowedOffset) {
361  // Is set to zero by default.
362  EXPECT_EQ(0, WebRtc_get_allowed_offset(handle_));
363  for (int i = 1; i >= 0; i--) {
364    EXPECT_EQ(0, WebRtc_set_allowed_offset(handle_, i));
365    EXPECT_EQ(i, WebRtc_get_allowed_offset(handle_));
366    Init();
367    // Unaffected over a reset.
368    EXPECT_EQ(i, WebRtc_get_allowed_offset(handle_));
369  }
370}
371
372TEST_F(DelayEstimatorTest, VerifyEnableRobustValidation) {
373  // Disabled by default.
374  EXPECT_EQ(0, WebRtc_is_robust_validation_enabled(handle_));
375  for (size_t i = 0; i < kSizeEnable; ++i) {
376    EXPECT_EQ(0, WebRtc_enable_robust_validation(handle_, kEnable[i]));
377    EXPECT_EQ(kEnable[i], WebRtc_is_robust_validation_enabled(handle_));
378    Init();
379    // Unaffected over a reset.
380    EXPECT_EQ(kEnable[i], WebRtc_is_robust_validation_enabled(handle_));
381  }
382}
383
384TEST_F(DelayEstimatorTest, InitializedSpectrumAfterProcess) {
385  // In this test we verify that the mean spectra are initialized after first
386  // time we call WebRtc_AddFarSpectrum() and Process() respectively. The test
387  // also verifies the state is not left for zero spectra.
388  const float kZerosFloat[kSpectrumSize] = { 0.0 };
389  const uint16_t kZerosU16[kSpectrumSize] = { 0 };
390
391  // For floating point operations, process one frame and verify initialization
392  // flag.
393  Init();
394  EXPECT_EQ(0, WebRtc_AddFarSpectrumFloat(farend_handle_, kZerosFloat,
395                                          spectrum_size_));
396  EXPECT_EQ(0, farend_self_->far_spectrum_initialized);
397  EXPECT_EQ(0, WebRtc_AddFarSpectrumFloat(farend_handle_, far_f_,
398                                           spectrum_size_));
399  EXPECT_EQ(1, farend_self_->far_spectrum_initialized);
400  EXPECT_EQ(-2, WebRtc_DelayEstimatorProcessFloat(handle_, kZerosFloat,
401                                                  spectrum_size_));
402  EXPECT_EQ(0, self_->near_spectrum_initialized);
403  EXPECT_EQ(-2, WebRtc_DelayEstimatorProcessFloat(handle_, near_f_,
404                                                  spectrum_size_));
405  EXPECT_EQ(1, self_->near_spectrum_initialized);
406
407  // For fixed point operations, process one frame and verify initialization
408  // flag.
409  Init();
410  EXPECT_EQ(0, WebRtc_AddFarSpectrumFix(farend_handle_, kZerosU16,
411                                        spectrum_size_, 0));
412  EXPECT_EQ(0, farend_self_->far_spectrum_initialized);
413  EXPECT_EQ(0, WebRtc_AddFarSpectrumFix(farend_handle_, far_u16_,
414                                         spectrum_size_, 0));
415  EXPECT_EQ(1, farend_self_->far_spectrum_initialized);
416  EXPECT_EQ(-2, WebRtc_DelayEstimatorProcessFix(handle_, kZerosU16,
417                                                spectrum_size_, 0));
418  EXPECT_EQ(0, self_->near_spectrum_initialized);
419  EXPECT_EQ(-2, WebRtc_DelayEstimatorProcessFix(handle_, near_u16_,
420                                                spectrum_size_, 0));
421  EXPECT_EQ(1, self_->near_spectrum_initialized);
422}
423
424TEST_F(DelayEstimatorTest, CorrectLastDelay) {
425  // In this test we verify that we get the correct last delay upon valid call.
426  // We simply process the same data until we leave the initialized state
427  // (|last_delay| = -2). Then we compare the Process() output with the
428  // last_delay() call.
429
430  // TODO(bjornv): Update quality values for robust validation.
431  int last_delay = 0;
432  // Floating point operations.
433  Init();
434  for (int i = 0; i < 200; i++) {
435    EXPECT_EQ(0, WebRtc_AddFarSpectrumFloat(farend_handle_, far_f_,
436                                            spectrum_size_));
437    last_delay = WebRtc_DelayEstimatorProcessFloat(handle_, near_f_,
438                                                   spectrum_size_);
439    if (last_delay != -2) {
440      EXPECT_EQ(last_delay, WebRtc_last_delay(handle_));
441      if (!WebRtc_is_robust_validation_enabled(handle_)) {
442        EXPECT_FLOAT_EQ(7203.f / kMaxBitCountsQ9,
443                        WebRtc_last_delay_quality(handle_));
444      }
445      break;
446    }
447  }
448  // Verify that we have left the initialized state.
449  EXPECT_NE(-2, WebRtc_last_delay(handle_));
450  EXPECT_LT(0, WebRtc_last_delay_quality(handle_));
451
452  // Fixed point operations.
453  Init();
454  for (int i = 0; i < 200; i++) {
455    EXPECT_EQ(0, WebRtc_AddFarSpectrumFix(farend_handle_, far_u16_,
456                                          spectrum_size_, 0));
457    last_delay = WebRtc_DelayEstimatorProcessFix(handle_, near_u16_,
458                                                 spectrum_size_, 0);
459    if (last_delay != -2) {
460      EXPECT_EQ(last_delay, WebRtc_last_delay(handle_));
461      if (!WebRtc_is_robust_validation_enabled(handle_)) {
462        EXPECT_FLOAT_EQ(7203.f / kMaxBitCountsQ9,
463                        WebRtc_last_delay_quality(handle_));
464      }
465      break;
466    }
467  }
468  // Verify that we have left the initialized state.
469  EXPECT_NE(-2, WebRtc_last_delay(handle_));
470  EXPECT_LT(0, WebRtc_last_delay_quality(handle_));
471}
472
473TEST_F(DelayEstimatorTest, CorrectErrorReturnsOfBinaryEstimatorFarend) {
474  // In this test we verify correct output on invalid API calls to the Binary
475  // Delay Estimator (far-end part).
476
477  BinaryDelayEstimatorFarend* binary = binary_farend_;
478  // WebRtc_CreateBinaryDelayEstimatorFarend() should return -1 if the input
479  // history size is less than 2. This is to make sure the buffer shifting
480  // applies properly.
481  // Make sure we have a non-NULL value at start, so we can detect NULL after
482  // create failure.
483  binary = WebRtc_CreateBinaryDelayEstimatorFarend(1);
484  EXPECT_TRUE(binary == NULL);
485}
486
487TEST_F(DelayEstimatorTest, CorrectErrorReturnsOfBinaryEstimator) {
488  // In this test we verify correct output on invalid API calls to the Binary
489  // Delay Estimator.
490
491  BinaryDelayEstimator* binary_handle = binary_;
492  // WebRtc_CreateBinaryDelayEstimator() should return -1 if we have a NULL
493  // pointer as |binary_farend| or invalid input values. Upon failure, the
494  // |binary_handle| should be NULL.
495  // Make sure we have a non-NULL value at start, so we can detect NULL after
496  // create failure.
497  binary_handle = WebRtc_CreateBinaryDelayEstimator(NULL, kLookahead);
498  EXPECT_TRUE(binary_handle == NULL);
499  binary_handle = WebRtc_CreateBinaryDelayEstimator(binary_farend_, -1);
500  EXPECT_TRUE(binary_handle == NULL);
501}
502
503TEST_F(DelayEstimatorTest, MeanEstimatorFix) {
504  // In this test we verify that we update the mean value in correct direction
505  // only. With "direction" we mean increase or decrease.
506
507  int32_t mean_value = 4000;
508  int32_t mean_value_before = mean_value;
509  int32_t new_mean_value = mean_value * 2;
510
511  // Increasing |mean_value|.
512  WebRtc_MeanEstimatorFix(new_mean_value, 10, &mean_value);
513  EXPECT_LT(mean_value_before, mean_value);
514  EXPECT_GT(new_mean_value, mean_value);
515
516  // Decreasing |mean_value|.
517  new_mean_value = mean_value / 2;
518  mean_value_before = mean_value;
519  WebRtc_MeanEstimatorFix(new_mean_value, 10, &mean_value);
520  EXPECT_GT(mean_value_before, mean_value);
521  EXPECT_LT(new_mean_value, mean_value);
522}
523
524TEST_F(DelayEstimatorTest, ExactDelayEstimateMultipleNearSameSpectrum) {
525  // In this test we verify that we get the correct delay estimates if we shift
526  // the signal accordingly. We create two Binary Delay Estimators and feed them
527  // with the same signals, so they should output the same results.
528  // We verify both causal and non-causal delays.
529  // For these noise free signals, the robust validation should not have an
530  // impact, hence we turn robust validation on/off for both reference and
531  // delayed near end.
532
533  for (size_t i = 0; i < kSizeEnable; ++i) {
534    for (size_t j = 0; j < kSizeEnable; ++j) {
535      RunBinarySpectraTest(0, 0, kEnable[i], kEnable[j]);
536    }
537  }
538}
539
540TEST_F(DelayEstimatorTest, ExactDelayEstimateMultipleNearDifferentSpectrum) {
541  // In this test we use the same setup as above, but we now feed the two Binary
542  // Delay Estimators with different signals, so they should output different
543  // results.
544  // For these noise free signals, the robust validation should not have an
545  // impact, hence we turn robust validation on/off for both reference and
546  // delayed near end.
547
548  const int kNearOffset = 1;
549  for (size_t i = 0; i < kSizeEnable; ++i) {
550    for (size_t j = 0; j < kSizeEnable; ++j) {
551      RunBinarySpectraTest(kNearOffset, 0, kEnable[i], kEnable[j]);
552    }
553  }
554}
555
556TEST_F(DelayEstimatorTest, ExactDelayEstimateMultipleNearDifferentLookahead) {
557  // In this test we use the same setup as above, feeding the two Binary
558  // Delay Estimators with the same signals. The difference is that we create
559  // them with different lookahead.
560  // For these noise free signals, the robust validation should not have an
561  // impact, hence we turn robust validation on/off for both reference and
562  // delayed near end.
563
564  const int kLookaheadOffset = 1;
565  for (size_t i = 0; i < kSizeEnable; ++i) {
566    for (size_t j = 0; j < kSizeEnable; ++j) {
567      RunBinarySpectraTest(0, kLookaheadOffset, kEnable[i], kEnable[j]);
568    }
569  }
570}
571
572TEST_F(DelayEstimatorTest, AllowedOffsetNoImpactWhenRobustValidationDisabled) {
573  // The same setup as in ExactDelayEstimateMultipleNearSameSpectrum with the
574  // difference that |allowed_offset| is set for the reference binary delay
575  // estimator.
576
577  binary_->allowed_offset = 10;
578  RunBinarySpectraTest(0, 0, 0, 0);
579  binary_->allowed_offset = 0;  // Reset reference.
580}
581
582TEST_F(DelayEstimatorTest, VerifyLookaheadAtCreate) {
583  void* farend_handle = WebRtc_CreateDelayEstimatorFarend(kSpectrumSize,
584                                                          kMaxDelay);
585  ASSERT_TRUE(farend_handle != NULL);
586  void* handle = WebRtc_CreateDelayEstimator(farend_handle, kLookahead);
587  ASSERT_TRUE(handle != NULL);
588  EXPECT_EQ(kLookahead, WebRtc_lookahead(handle));
589  WebRtc_FreeDelayEstimator(handle);
590  WebRtc_FreeDelayEstimatorFarend(farend_handle);
591}
592
593TEST_F(DelayEstimatorTest, VerifyLookaheadIsSetAndKeptAfterInit) {
594  EXPECT_EQ(kLookahead, WebRtc_lookahead(handle_));
595  EXPECT_EQ(kDifferentLookahead,
596            WebRtc_set_lookahead(handle_, kDifferentLookahead));
597  EXPECT_EQ(kDifferentLookahead, WebRtc_lookahead(handle_));
598  EXPECT_EQ(0, WebRtc_InitDelayEstimatorFarend(farend_handle_));
599  EXPECT_EQ(kDifferentLookahead, WebRtc_lookahead(handle_));
600  EXPECT_EQ(0, WebRtc_InitDelayEstimator(handle_));
601  EXPECT_EQ(kDifferentLookahead, WebRtc_lookahead(handle_));
602}
603
604TEST_F(DelayEstimatorTest, VerifyHistorySizeAtCreate) {
605  EXPECT_EQ(kHistorySize, WebRtc_history_size(handle_));
606}
607
608TEST_F(DelayEstimatorTest, VerifyHistorySizeIsSetAndKeptAfterInit) {
609  EXPECT_EQ(kHistorySize, WebRtc_history_size(handle_));
610  EXPECT_EQ(kDifferentHistorySize,
611            WebRtc_set_history_size(handle_, kDifferentHistorySize));
612  EXPECT_EQ(kDifferentHistorySize, WebRtc_history_size(handle_));
613  EXPECT_EQ(0, WebRtc_InitDelayEstimator(handle_));
614  EXPECT_EQ(kDifferentHistorySize, WebRtc_history_size(handle_));
615  EXPECT_EQ(0, WebRtc_InitDelayEstimatorFarend(farend_handle_));
616  EXPECT_EQ(kDifferentHistorySize, WebRtc_history_size(handle_));
617}
618
619// TODO(bjornv): Add tests for SoftReset...(...).
620
621}  // namespace
622