blob: e7e79fe723d2851d5fd7a4c0c52db86eb32400d1 [file] [log] [blame]
bjornv@webrtc.org70569082012-04-12 12:13:50 +00001/*
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "modules/audio_processing/aec/aec_core.h"
12#include "modules/audio_processing/aec/echo_cancellation.h"
Karl Wiberge40468b2017-11-22 10:42:26 +010013#include "rtc_base/numerics/safe_conversions.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020014#include "test/gtest.h"
Mirko Bonadei71207422017-09-15 13:58:09 +020015#include "typedefs.h" // NOLINT(build/include)
peah50e21bd2016-03-05 08:39:21 -080016namespace webrtc {
bjornv@webrtc.org70569082012-04-12 12:13:50 +000017namespace {
18
19class SystemDelayTest : public ::testing::Test {
20 protected:
21 SystemDelayTest();
22 virtual void SetUp();
23 virtual void TearDown();
24
25 // Initialization of AEC handle with respect to |sample_rate_hz|. Since the
26 // device sample rate is unimportant we set that value to 48000 Hz.
27 void Init(int sample_rate_hz);
28
29 // Makes one render call and one capture call in that specific order.
30 void RenderAndCapture(int device_buffer_ms);
31
32 // Fills up the far-end buffer with respect to the default device buffer size.
Peter Kastingdce40cf2015-08-24 14:52:23 -070033 size_t BufferFillUp();
bjornv@webrtc.org70569082012-04-12 12:13:50 +000034
35 // Runs and verifies the behavior in a stable startup procedure.
36 void RunStableStartup();
37
38 // Maps buffer size in ms into samples, taking the unprocessed frame into
39 // account.
Bjorn Volcker71012692015-06-18 11:04:56 +020040 int MapBufferSizeToSamples(int size_in_ms, bool extended_filter);
bjornv@webrtc.org70569082012-04-12 12:13:50 +000041
42 void* handle_;
pbos@webrtc.orge468bc92014-12-18 09:11:33 +000043 Aec* self_;
Peter Kastingdce40cf2015-08-24 14:52:23 -070044 size_t samples_per_frame_;
bjornv@webrtc.org70569082012-04-12 12:13:50 +000045 // Dummy input/output speech data.
mflodman@webrtc.orgd5da2502014-05-15 11:17:21 +000046 static const int kSamplesPerChunk = 160;
kwiberg@webrtc.org38214d52014-07-03 09:47:33 +000047 float far_[kSamplesPerChunk];
mflodman@webrtc.orgd5da2502014-05-15 11:17:21 +000048 float near_[kSamplesPerChunk];
49 float out_[kSamplesPerChunk];
aluebs@webrtc.orgc78d81a2015-01-21 19:10:55 +000050 const float* near_ptr_;
51 float* out_ptr_;
bjornv@webrtc.org70569082012-04-12 12:13:50 +000052};
53
54SystemDelayTest::SystemDelayTest()
andrew@webrtc.org13b2d462013-10-08 23:41:42 +000055 : handle_(NULL), self_(NULL), samples_per_frame_(0) {
bjornv@webrtc.org70569082012-04-12 12:13:50 +000056 // Dummy input data are set with more or less arbitrary non-zero values.
kwiberg@webrtc.org38214d52014-07-03 09:47:33 +000057 for (int i = 0; i < kSamplesPerChunk; i++) {
58 far_[i] = 257.0;
mflodman@webrtc.orgd5da2502014-05-15 11:17:21 +000059 near_[i] = 514.0;
kwiberg@webrtc.org38214d52014-07-03 09:47:33 +000060 }
bjornv@webrtc.org70569082012-04-12 12:13:50 +000061 memset(out_, 0, sizeof(out_));
aluebs@webrtc.orgc78d81a2015-01-21 19:10:55 +000062 near_ptr_ = near_;
63 out_ptr_ = out_;
bjornv@webrtc.org70569082012-04-12 12:13:50 +000064}
65
66void SystemDelayTest::SetUp() {
Bjorn Volcker9345e862015-06-10 21:43:36 +020067 handle_ = WebRtcAec_Create();
68 ASSERT_TRUE(handle_);
pbos@webrtc.orge468bc92014-12-18 09:11:33 +000069 self_ = reinterpret_cast<Aec*>(handle_);
bjornv@webrtc.org70569082012-04-12 12:13:50 +000070}
71
72void SystemDelayTest::TearDown() {
73 // Free AEC
Bjorn Volckerf6a99e62015-04-10 07:56:57 +020074 WebRtcAec_Free(handle_);
bjornv@webrtc.org70569082012-04-12 12:13:50 +000075 handle_ = NULL;
76}
77
78// In SWB mode nothing is added to the buffer handling with respect to
79// functionality compared to WB. We therefore only verify behavior in NB and WB.
andrew@webrtc.org13b2d462013-10-08 23:41:42 +000080static const int kSampleRateHz[] = {8000, 16000};
bjornv@webrtc.org70569082012-04-12 12:13:50 +000081static const size_t kNumSampleRates =
82 sizeof(kSampleRateHz) / sizeof(*kSampleRateHz);
83
84// Default audio device buffer size used.
85static const int kDeviceBufMs = 100;
86
87// Requirement for a stable device convergence time in ms. Should converge in
88// less than |kStableConvergenceMs|.
89static const int kStableConvergenceMs = 100;
90
91// Maximum convergence time in ms. This means that we should leave the startup
92// phase after |kMaxConvergenceMs| independent of device buffer stability
93// conditions.
94static const int kMaxConvergenceMs = 500;
95
96void SystemDelayTest::Init(int sample_rate_hz) {
97 // Initialize AEC
98 EXPECT_EQ(0, WebRtcAec_Init(handle_, sample_rate_hz, 48000));
Bjorn Volcker71012692015-06-18 11:04:56 +020099 EXPECT_EQ(0, WebRtcAec_system_delay(self_->aec));
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000100
101 // One frame equals 10 ms of data.
Peter Kastingdce40cf2015-08-24 14:52:23 -0700102 samples_per_frame_ = static_cast<size_t>(sample_rate_hz / 100);
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000103}
104
105void SystemDelayTest::RenderAndCapture(int device_buffer_ms) {
106 EXPECT_EQ(0, WebRtcAec_BufferFarend(handle_, far_, samples_per_frame_));
Yves Gerey665174f2018-06-19 15:03:05 +0200107 EXPECT_EQ(0, WebRtcAec_Process(handle_, &near_ptr_, 1, &out_ptr_,
108 samples_per_frame_, device_buffer_ms, 0));
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000109}
110
Peter Kastingdce40cf2015-08-24 14:52:23 -0700111size_t SystemDelayTest::BufferFillUp() {
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000112 // To make sure we have a full buffer when we verify stability we first fill
113 // up the far-end buffer with the same amount as we will report in through
114 // Process().
Peter Kastingdce40cf2015-08-24 14:52:23 -0700115 size_t buffer_size = 0;
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000116 for (int i = 0; i < kDeviceBufMs / 10; i++) {
117 EXPECT_EQ(0, WebRtcAec_BufferFarend(handle_, far_, samples_per_frame_));
118 buffer_size += samples_per_frame_;
Peter Kastingdce40cf2015-08-24 14:52:23 -0700119 EXPECT_EQ(static_cast<int>(buffer_size),
120 WebRtcAec_system_delay(self_->aec));
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000121 }
122 return buffer_size;
123}
124
125void SystemDelayTest::RunStableStartup() {
126 // To make sure we have a full buffer when we verify stability we first fill
127 // up the far-end buffer with the same amount as we will report in through
128 // Process().
Peter Kastingdce40cf2015-08-24 14:52:23 -0700129 size_t buffer_size = BufferFillUp();
Bjorn Volcker71012692015-06-18 11:04:56 +0200130
henrik.lundin0f133b92015-07-02 00:17:55 -0700131 if (WebRtcAec_delay_agnostic_enabled(self_->aec) == 1) {
Bjorn Volcker71012692015-06-18 11:04:56 +0200132 // In extended_filter mode we set the buffer size after the first processed
133 // 10 ms chunk. Hence, we don't need to wait for the reported system delay
134 // values to become stable.
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000135 RenderAndCapture(kDeviceBufMs);
136 buffer_size += samples_per_frame_;
Bjorn Volcker71012692015-06-18 11:04:56 +0200137 EXPECT_EQ(0, self_->startup_phase);
138 } else {
139 // A stable device should be accepted and put in a regular process mode
140 // within |kStableConvergenceMs|.
141 int process_time_ms = 0;
142 for (; process_time_ms < kStableConvergenceMs; process_time_ms += 10) {
143 RenderAndCapture(kDeviceBufMs);
144 buffer_size += samples_per_frame_;
145 if (self_->startup_phase == 0) {
146 // We have left the startup phase.
147 break;
148 }
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000149 }
Bjorn Volcker71012692015-06-18 11:04:56 +0200150 // Verify convergence time.
151 EXPECT_GT(kStableConvergenceMs, process_time_ms);
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000152 }
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000153 // Verify that the buffer has been flushed.
Yves Gerey665174f2018-06-19 15:03:05 +0200154 EXPECT_GE(static_cast<int>(buffer_size), WebRtcAec_system_delay(self_->aec));
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000155}
156
Yves Gerey665174f2018-06-19 15:03:05 +0200157int SystemDelayTest::MapBufferSizeToSamples(int size_in_ms,
158 bool extended_filter) {
Bjorn Volcker71012692015-06-18 11:04:56 +0200159 // If extended_filter is disabled we add an extra 10 ms for the unprocessed
160 // frame. That is simply how the algorithm is constructed.
Yves Gerey665174f2018-06-19 15:03:05 +0200161 return static_cast<int>((size_in_ms + (extended_filter ? 0 : 10)) *
162 samples_per_frame_ / 10);
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000163}
164
165// The tests should meet basic requirements and not be adjusted to what is
166// actually implemented. If we don't get good code coverage this way we either
167// lack in tests or have unnecessary code.
168// General requirements:
169// 1) If we add far-end data the system delay should be increased with the same
170// amount we add.
171// 2) If the far-end buffer is full we should flush the oldest data to make room
172// for the new. In this case the system delay is unaffected.
173// 3) There should exist a startup phase in which the buffer size is to be
174// determined. In this phase no cancellation should be performed.
175// 4) Under stable conditions (small variations in device buffer sizes) the AEC
176// should determine an appropriate local buffer size within
177// |kStableConvergenceMs| ms.
178// 5) Under unstable conditions the AEC should make a decision within
179// |kMaxConvergenceMs| ms.
180// 6) If the local buffer runs out of data we should stuff the buffer with older
181// frames.
182// 7) The system delay should within |kMaxConvergenceMs| ms heal from
183// disturbances like drift, data glitches, toggling events and outliers.
184// 8) The system delay should never become negative.
185
186TEST_F(SystemDelayTest, CorrectIncreaseWhenBufferFarend) {
187 // When we add data to the AEC buffer the internal system delay should be
188 // incremented with the same amount as the size of data.
Bjorn Volcker71012692015-06-18 11:04:56 +0200189 // This process should be independent of DA-AEC and extended_filter mode.
190 for (int extended_filter = 0; extended_filter <= 1; ++extended_filter) {
191 WebRtcAec_enable_extended_filter(self_->aec, extended_filter);
192 EXPECT_EQ(extended_filter, WebRtcAec_extended_filter_enabled(self_->aec));
193 for (int da_aec = 0; da_aec <= 1; ++da_aec) {
henrik.lundin0f133b92015-07-02 00:17:55 -0700194 WebRtcAec_enable_delay_agnostic(self_->aec, da_aec);
195 EXPECT_EQ(da_aec, WebRtcAec_delay_agnostic_enabled(self_->aec));
Bjorn Volcker71012692015-06-18 11:04:56 +0200196 for (size_t i = 0; i < kNumSampleRates; i++) {
197 Init(kSampleRateHz[i]);
198 // Loop through a couple of calls to make sure the system delay
199 // increments correctly.
200 for (int j = 1; j <= 5; j++) {
201 EXPECT_EQ(0,
202 WebRtcAec_BufferFarend(handle_, far_, samples_per_frame_));
Peter Kastingdce40cf2015-08-24 14:52:23 -0700203 EXPECT_EQ(static_cast<int>(j * samples_per_frame_),
204 WebRtcAec_system_delay(self_->aec));
Bjorn Volcker71012692015-06-18 11:04:56 +0200205 }
206 }
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000207 }
208 }
209}
210
211// TODO(bjornv): Add a test to verify behavior if the far-end buffer is full
212// when adding new data.
213
214TEST_F(SystemDelayTest, CorrectDelayAfterStableStartup) {
215 // We run the system in a stable startup. After that we verify that the system
216 // delay meets the requirements.
Bjorn Volcker71012692015-06-18 11:04:56 +0200217 // This process should be independent of DA-AEC and extended_filter mode.
218 for (int extended_filter = 0; extended_filter <= 1; ++extended_filter) {
219 WebRtcAec_enable_extended_filter(self_->aec, extended_filter);
220 EXPECT_EQ(extended_filter, WebRtcAec_extended_filter_enabled(self_->aec));
221 for (int da_aec = 0; da_aec <= 1; ++da_aec) {
henrik.lundin0f133b92015-07-02 00:17:55 -0700222 WebRtcAec_enable_delay_agnostic(self_->aec, da_aec);
223 EXPECT_EQ(da_aec, WebRtcAec_delay_agnostic_enabled(self_->aec));
Bjorn Volcker71012692015-06-18 11:04:56 +0200224 for (size_t i = 0; i < kNumSampleRates; i++) {
225 Init(kSampleRateHz[i]);
226 RunStableStartup();
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000227
Bjorn Volcker71012692015-06-18 11:04:56 +0200228 // Verify system delay with respect to requirements, i.e., the
229 // |system_delay| is in the interval [75%, 100%] of what's reported on
230 // the average.
231 // In extended_filter mode we target 50% and measure after one processed
232 // 10 ms chunk.
Peter Kastingdce40cf2015-08-24 14:52:23 -0700233 int average_reported_delay =
234 static_cast<int>(kDeviceBufMs * samples_per_frame_ / 10);
Bjorn Volcker71012692015-06-18 11:04:56 +0200235 EXPECT_GE(average_reported_delay, WebRtcAec_system_delay(self_->aec));
236 int lower_bound = WebRtcAec_extended_filter_enabled(self_->aec)
Yves Gerey665174f2018-06-19 15:03:05 +0200237 ? (average_reported_delay / 2 -
238 rtc::checked_cast<int>(samples_per_frame_))
239 : average_reported_delay * 3 / 4;
Bjorn Volcker71012692015-06-18 11:04:56 +0200240 EXPECT_LE(lower_bound, WebRtcAec_system_delay(self_->aec));
241 }
242 }
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000243 }
244}
245
246TEST_F(SystemDelayTest, CorrectDelayAfterUnstableStartup) {
Bjorn Volcker71012692015-06-18 11:04:56 +0200247 // This test does not apply in extended_filter mode, since we only use the
248 // the first 10 ms chunk to determine a reasonable buffer size. Neither does
249 // it apply if DA-AEC is on because that overrides the startup procedure.
250 WebRtcAec_enable_extended_filter(self_->aec, 0);
251 EXPECT_EQ(0, WebRtcAec_extended_filter_enabled(self_->aec));
henrik.lundin0f133b92015-07-02 00:17:55 -0700252 WebRtcAec_enable_delay_agnostic(self_->aec, 0);
253 EXPECT_EQ(0, WebRtcAec_delay_agnostic_enabled(self_->aec));
Bjorn Volcker71012692015-06-18 11:04:56 +0200254
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000255 // In an unstable system we would start processing after |kMaxConvergenceMs|.
256 // On the last frame the AEC buffer is adjusted to 60% of the last reported
257 // device buffer size.
258 // We construct an unstable system by altering the device buffer size between
259 // two values |kDeviceBufMs| +- 25 ms.
260 for (size_t i = 0; i < kNumSampleRates; i++) {
261 Init(kSampleRateHz[i]);
262
263 // To make sure we have a full buffer when we verify stability we first fill
264 // up the far-end buffer with the same amount as we will report in on the
265 // average through Process().
Peter Kastingdce40cf2015-08-24 14:52:23 -0700266 size_t buffer_size = BufferFillUp();
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000267
268 int buffer_offset_ms = 25;
269 int reported_delay_ms = 0;
270 int process_time_ms = 0;
271 for (; process_time_ms <= kMaxConvergenceMs; process_time_ms += 10) {
272 reported_delay_ms = kDeviceBufMs + buffer_offset_ms;
273 RenderAndCapture(reported_delay_ms);
274 buffer_size += samples_per_frame_;
275 buffer_offset_ms = -buffer_offset_ms;
andrew@webrtc.org1760a172013-09-25 23:17:38 +0000276 if (self_->startup_phase == 0) {
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000277 // We have left the startup phase.
278 break;
279 }
280 }
281 // Verify convergence time.
282 EXPECT_GE(kMaxConvergenceMs, process_time_ms);
283 // Verify that the buffer has been flushed.
Peter Kastingdce40cf2015-08-24 14:52:23 -0700284 EXPECT_GE(static_cast<int>(buffer_size),
285 WebRtcAec_system_delay(self_->aec));
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000286
287 // Verify system delay with respect to requirements, i.e., the
288 // |system_delay| is in the interval [60%, 100%] of what's last reported.
Peter Kastingdce40cf2015-08-24 14:52:23 -0700289 EXPECT_GE(static_cast<int>(reported_delay_ms * samples_per_frame_ / 10),
bjornv@webrtc.org4d1cfae2013-02-20 17:31:38 +0000290 WebRtcAec_system_delay(self_->aec));
Peter Kastingdce40cf2015-08-24 14:52:23 -0700291 EXPECT_LE(
292 static_cast<int>(reported_delay_ms * samples_per_frame_ / 10 * 3 / 5),
293 WebRtcAec_system_delay(self_->aec));
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000294 }
295}
296
Bjorn Volcker71012692015-06-18 11:04:56 +0200297TEST_F(SystemDelayTest, CorrectDelayAfterStableBufferBuildUp) {
298 // This test does not apply in extended_filter mode, since we only use the
299 // the first 10 ms chunk to determine a reasonable buffer size. Neither does
300 // it apply if DA-AEC is on because that overrides the startup procedure.
301 WebRtcAec_enable_extended_filter(self_->aec, 0);
302 EXPECT_EQ(0, WebRtcAec_extended_filter_enabled(self_->aec));
henrik.lundin0f133b92015-07-02 00:17:55 -0700303 WebRtcAec_enable_delay_agnostic(self_->aec, 0);
304 EXPECT_EQ(0, WebRtcAec_delay_agnostic_enabled(self_->aec));
Bjorn Volcker71012692015-06-18 11:04:56 +0200305
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000306 // In this test we start by establishing the device buffer size during stable
307 // conditions, but with an empty internal far-end buffer. Once that is done we
308 // verify that the system delay is increased correctly until we have reach an
309 // internal buffer size of 75% of what's been reported.
310 for (size_t i = 0; i < kNumSampleRates; i++) {
311 Init(kSampleRateHz[i]);
312
313 // We assume that running |kStableConvergenceMs| calls will put the
314 // algorithm in a state where the device buffer size has been determined. We
315 // can make that assumption since we have a separate stability test.
316 int process_time_ms = 0;
317 for (; process_time_ms < kStableConvergenceMs; process_time_ms += 10) {
Yves Gerey665174f2018-06-19 15:03:05 +0200318 EXPECT_EQ(0, WebRtcAec_Process(handle_, &near_ptr_, 1, &out_ptr_,
319 samples_per_frame_, kDeviceBufMs, 0));
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000320 }
bjornv@webrtc.orgb51d3ea2014-06-05 13:41:33 +0000321 // Verify that a buffer size has been established.
322 EXPECT_EQ(0, self_->checkBuffSize);
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000323
bjornv@webrtc.orgb51d3ea2014-06-05 13:41:33 +0000324 // We now have established the required buffer size. Let us verify that we
325 // fill up before leaving the startup phase for normal processing.
Peter Kastingdce40cf2015-08-24 14:52:23 -0700326 size_t buffer_size = 0;
327 size_t target_buffer_size = kDeviceBufMs * samples_per_frame_ / 10 * 3 / 4;
bjornv@webrtc.orgb51d3ea2014-06-05 13:41:33 +0000328 process_time_ms = 0;
329 for (; process_time_ms <= kMaxConvergenceMs; process_time_ms += 10) {
330 RenderAndCapture(kDeviceBufMs);
331 buffer_size += samples_per_frame_;
332 if (self_->startup_phase == 0) {
333 // We have left the startup phase.
334 break;
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000335 }
336 }
bjornv@webrtc.orgb51d3ea2014-06-05 13:41:33 +0000337 // Verify convergence time.
338 EXPECT_GT(kMaxConvergenceMs, process_time_ms);
339 // Verify that the buffer has reached the desired size.
Peter Kastingdce40cf2015-08-24 14:52:23 -0700340 EXPECT_LE(static_cast<int>(target_buffer_size),
341 WebRtcAec_system_delay(self_->aec));
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000342
343 // Verify normal behavior (system delay is kept constant) after startup by
344 // running a couple of calls to BufferFarend() and Process().
345 for (int j = 0; j < 6; j++) {
bjornv@webrtc.org4d1cfae2013-02-20 17:31:38 +0000346 int system_delay_before_calls = WebRtcAec_system_delay(self_->aec);
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000347 RenderAndCapture(kDeviceBufMs);
bjornv@webrtc.org4d1cfae2013-02-20 17:31:38 +0000348 EXPECT_EQ(system_delay_before_calls, WebRtcAec_system_delay(self_->aec));
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000349 }
350 }
351}
352
353TEST_F(SystemDelayTest, CorrectDelayWhenBufferUnderrun) {
354 // Here we test a buffer under run scenario. If we keep on calling
355 // WebRtcAec_Process() we will finally run out of data, but should
356 // automatically stuff the buffer. We verify this behavior by checking if the
357 // system delay goes negative.
Bjorn Volcker71012692015-06-18 11:04:56 +0200358 // This process should be independent of DA-AEC and extended_filter mode.
359 for (int extended_filter = 0; extended_filter <= 1; ++extended_filter) {
360 WebRtcAec_enable_extended_filter(self_->aec, extended_filter);
361 EXPECT_EQ(extended_filter, WebRtcAec_extended_filter_enabled(self_->aec));
362 for (int da_aec = 0; da_aec <= 1; ++da_aec) {
henrik.lundin0f133b92015-07-02 00:17:55 -0700363 WebRtcAec_enable_delay_agnostic(self_->aec, da_aec);
364 EXPECT_EQ(da_aec, WebRtcAec_delay_agnostic_enabled(self_->aec));
Bjorn Volcker71012692015-06-18 11:04:56 +0200365 for (size_t i = 0; i < kNumSampleRates; i++) {
366 Init(kSampleRateHz[i]);
367 RunStableStartup();
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000368
Bjorn Volcker71012692015-06-18 11:04:56 +0200369 // The AEC has now left the Startup phase. We now have at most
370 // |kStableConvergenceMs| in the buffer. Keep on calling Process() until
371 // we run out of data and verify that the system delay is non-negative.
372 for (int j = 0; j <= kStableConvergenceMs; j += 10) {
373 EXPECT_EQ(0, WebRtcAec_Process(handle_, &near_ptr_, 1, &out_ptr_,
374 samples_per_frame_, kDeviceBufMs, 0));
375 EXPECT_LE(0, WebRtcAec_system_delay(self_->aec));
376 }
377 }
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000378 }
379 }
380}
381
Bjorn Volcker71012692015-06-18 11:04:56 +0200382TEST_F(SystemDelayTest, CorrectDelayDuringDrift) {
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000383 // This drift test should verify that the system delay is never exceeding the
384 // device buffer. The drift is simulated by decreasing the reported device
385 // buffer size by 1 ms every 100 ms. If the device buffer size goes below 30
386 // ms we jump (add) 10 ms to give a repeated pattern.
bjornv@webrtc.org5c3f4e32014-06-19 09:51:29 +0000387
Bjorn Volcker71012692015-06-18 11:04:56 +0200388 // This process should be independent of DA-AEC and extended_filter mode.
389 for (int extended_filter = 0; extended_filter <= 1; ++extended_filter) {
390 WebRtcAec_enable_extended_filter(self_->aec, extended_filter);
391 EXPECT_EQ(extended_filter, WebRtcAec_extended_filter_enabled(self_->aec));
392 for (int da_aec = 0; da_aec <= 1; ++da_aec) {
henrik.lundin0f133b92015-07-02 00:17:55 -0700393 WebRtcAec_enable_delay_agnostic(self_->aec, da_aec);
394 EXPECT_EQ(da_aec, WebRtcAec_delay_agnostic_enabled(self_->aec));
Bjorn Volcker71012692015-06-18 11:04:56 +0200395 for (size_t i = 0; i < kNumSampleRates; i++) {
396 Init(kSampleRateHz[i]);
397 RunStableStartup();
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000398
Bjorn Volcker71012692015-06-18 11:04:56 +0200399 // We have left the startup phase and proceed with normal processing.
400 int jump = 0;
401 for (int j = 0; j < 1000; j++) {
402 // Drift = -1 ms per 100 ms of data.
403 int device_buf_ms = kDeviceBufMs - (j / 10) + jump;
Yves Gerey665174f2018-06-19 15:03:05 +0200404 int device_buf =
405 MapBufferSizeToSamples(device_buf_ms, extended_filter == 1);
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000406
Bjorn Volcker71012692015-06-18 11:04:56 +0200407 if (device_buf_ms < 30) {
408 // Add 10 ms data, taking affect next frame.
409 jump += 10;
410 }
411 RenderAndCapture(device_buf_ms);
412
413 // Verify that the system delay does not exceed the device buffer.
414 EXPECT_GE(device_buf, WebRtcAec_system_delay(self_->aec));
415
416 // Verify that the system delay is non-negative.
417 EXPECT_LE(0, WebRtcAec_system_delay(self_->aec));
418 }
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000419 }
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000420 }
421 }
422}
423
Bjorn Volcker71012692015-06-18 11:04:56 +0200424TEST_F(SystemDelayTest, ShouldRecoverAfterGlitch) {
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000425 // This glitch test should verify that the system delay recovers if there is
426 // a glitch in data. The data glitch is constructed as 200 ms of buffering
427 // after which the stable procedure continues. The glitch is never reported by
428 // the device.
429 // The system is said to be in a non-causal state if the difference between
430 // the device buffer and system delay is less than a block (64 samples).
bjornv@webrtc.org5c3f4e32014-06-19 09:51:29 +0000431
Bjorn Volcker71012692015-06-18 11:04:56 +0200432 // This process should be independent of DA-AEC and extended_filter mode.
433 for (int extended_filter = 0; extended_filter <= 1; ++extended_filter) {
434 WebRtcAec_enable_extended_filter(self_->aec, extended_filter);
435 EXPECT_EQ(extended_filter, WebRtcAec_extended_filter_enabled(self_->aec));
436 for (int da_aec = 0; da_aec <= 1; ++da_aec) {
henrik.lundin0f133b92015-07-02 00:17:55 -0700437 WebRtcAec_enable_delay_agnostic(self_->aec, da_aec);
438 EXPECT_EQ(da_aec, WebRtcAec_delay_agnostic_enabled(self_->aec));
Bjorn Volcker71012692015-06-18 11:04:56 +0200439 for (size_t i = 0; i < kNumSampleRates; i++) {
440 Init(kSampleRateHz[i]);
441 RunStableStartup();
Yves Gerey665174f2018-06-19 15:03:05 +0200442 int device_buf =
443 MapBufferSizeToSamples(kDeviceBufMs, extended_filter == 1);
Bjorn Volcker71012692015-06-18 11:04:56 +0200444 // Glitch state.
445 for (int j = 0; j < 20; j++) {
446 EXPECT_EQ(0,
447 WebRtcAec_BufferFarend(handle_, far_, samples_per_frame_));
448 // No need to verify system delay, since that is done in a separate
449 // test.
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000450 }
Bjorn Volcker71012692015-06-18 11:04:56 +0200451 // Verify that we are in a non-causal state, i.e.,
452 // |system_delay| > |device_buf|.
453 EXPECT_LT(device_buf, WebRtcAec_system_delay(self_->aec));
454
455 // Recover state. Should recover at least 4 ms of data per 10 ms, hence
456 // a glitch of 200 ms will take at most 200 * 10 / 4 = 500 ms to recover
457 // from.
458 bool non_causal = true; // We are currently in a non-causal state.
459 for (int j = 0; j < 50; j++) {
460 int system_delay_before = WebRtcAec_system_delay(self_->aec);
461 RenderAndCapture(kDeviceBufMs);
462 int system_delay_after = WebRtcAec_system_delay(self_->aec);
463 // We have recovered if
464 // |device_buf| - |system_delay_after| >= PART_LEN (1 block).
465 // During recovery, |system_delay_after| < |system_delay_before|,
466 // otherwise they are equal.
467 if (non_causal) {
468 EXPECT_LT(system_delay_after, system_delay_before);
469 if (device_buf - system_delay_after >= PART_LEN) {
470 non_causal = false;
471 }
472 } else {
473 EXPECT_EQ(system_delay_before, system_delay_after);
474 }
475 // Verify that the system delay is non-negative.
476 EXPECT_LE(0, WebRtcAec_system_delay(self_->aec));
477 }
478 // Check that we have recovered.
479 EXPECT_FALSE(non_causal);
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000480 }
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000481 }
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000482 }
483}
484
485TEST_F(SystemDelayTest, UnaffectedWhenSpuriousDeviceBufferValues) {
Bjorn Volcker71012692015-06-18 11:04:56 +0200486 // This test does not apply in extended_filter mode, since we only use the
487 // the first 10 ms chunk to determine a reasonable buffer size.
488 const int extended_filter = 0;
489 WebRtcAec_enable_extended_filter(self_->aec, extended_filter);
490 EXPECT_EQ(extended_filter, WebRtcAec_extended_filter_enabled(self_->aec));
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000491
Bjorn Volcker71012692015-06-18 11:04:56 +0200492 // Should be DA-AEC independent.
493 for (int da_aec = 0; da_aec <= 1; ++da_aec) {
henrik.lundin0f133b92015-07-02 00:17:55 -0700494 WebRtcAec_enable_delay_agnostic(self_->aec, da_aec);
495 EXPECT_EQ(da_aec, WebRtcAec_delay_agnostic_enabled(self_->aec));
Bjorn Volcker71012692015-06-18 11:04:56 +0200496 // This spurious device buffer data test aims at verifying that the system
497 // delay is unaffected by large outliers.
498 // The system is said to be in a non-causal state if the difference between
499 // the device buffer and system delay is less than a block (64 samples).
500 for (size_t i = 0; i < kNumSampleRates; i++) {
501 Init(kSampleRateHz[i]);
502 RunStableStartup();
Yves Gerey665174f2018-06-19 15:03:05 +0200503 int device_buf =
504 MapBufferSizeToSamples(kDeviceBufMs, extended_filter == 1);
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000505
Bjorn Volcker71012692015-06-18 11:04:56 +0200506 // Normal state. We are currently not in a non-causal state.
507 bool non_causal = false;
508
509 // Run 1 s and replace device buffer size with 500 ms every 100 ms.
510 for (int j = 0; j < 100; j++) {
511 int system_delay_before_calls = WebRtcAec_system_delay(self_->aec);
512 int device_buf_ms = j % 10 == 0 ? 500 : kDeviceBufMs;
513 RenderAndCapture(device_buf_ms);
514
515 // Check for non-causality.
516 if (device_buf - WebRtcAec_system_delay(self_->aec) < PART_LEN) {
517 non_causal = true;
518 }
519 EXPECT_FALSE(non_causal);
520 EXPECT_EQ(system_delay_before_calls,
521 WebRtcAec_system_delay(self_->aec));
522
523 // Verify that the system delay is non-negative.
524 EXPECT_LE(0, WebRtcAec_system_delay(self_->aec));
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000525 }
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000526 }
527 }
528}
529
530TEST_F(SystemDelayTest, CorrectImpactWhenTogglingDeviceBufferValues) {
531 // This test aims at verifying that the system delay is "unaffected" by
532 // toggling values reported by the device.
533 // The test is constructed such that every other device buffer value is zero
534 // and then 2 * |kDeviceBufMs|, hence the size is constant on the average. The
535 // zero values will force us into a non-causal state and thereby lowering the
Bjorn Volcker71012692015-06-18 11:04:56 +0200536 // system delay until we basically run out of data. Once that happens the
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000537 // buffer will be stuffed.
538 // TODO(bjornv): This test will have a better impact if we verified that the
Bjorn Volcker71012692015-06-18 11:04:56 +0200539 // delay estimate goes up when the system delay goes down to meet the average
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000540 // device buffer size.
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000541
Bjorn Volcker71012692015-06-18 11:04:56 +0200542 // This test does not apply if DA-AEC is enabled and extended_filter mode
543 // disabled.
544 for (int extended_filter = 0; extended_filter <= 1; ++extended_filter) {
545 WebRtcAec_enable_extended_filter(self_->aec, extended_filter);
546 EXPECT_EQ(extended_filter, WebRtcAec_extended_filter_enabled(self_->aec));
547 for (int da_aec = 0; da_aec <= 1; ++da_aec) {
henrik.lundin0f133b92015-07-02 00:17:55 -0700548 WebRtcAec_enable_delay_agnostic(self_->aec, da_aec);
549 EXPECT_EQ(da_aec, WebRtcAec_delay_agnostic_enabled(self_->aec));
Bjorn Volcker71012692015-06-18 11:04:56 +0200550 if (extended_filter == 0 && da_aec == 1) {
551 continue;
552 }
553 for (size_t i = 0; i < kNumSampleRates; i++) {
554 Init(kSampleRateHz[i]);
555 RunStableStartup();
Yves Gerey665174f2018-06-19 15:03:05 +0200556 const int device_buf =
557 MapBufferSizeToSamples(kDeviceBufMs, extended_filter == 1);
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000558
Bjorn Volcker71012692015-06-18 11:04:56 +0200559 // Normal state. We are currently not in a non-causal state.
560 bool non_causal = false;
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000561
Bjorn Volcker71012692015-06-18 11:04:56 +0200562 // Loop through 100 frames (both render and capture), which equals 1 s
563 // of data. Every odd frame we set the device buffer size to
564 // 2 * |kDeviceBufMs| and even frames we set the device buffer size to
565 // zero.
566 for (int j = 0; j < 100; j++) {
567 int system_delay_before_calls = WebRtcAec_system_delay(self_->aec);
568 int device_buf_ms = 2 * (j % 2) * kDeviceBufMs;
569 RenderAndCapture(device_buf_ms);
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000570
Bjorn Volcker71012692015-06-18 11:04:56 +0200571 // Check for non-causality, compared with the average device buffer
572 // size.
573 non_causal |= (device_buf - WebRtcAec_system_delay(self_->aec) < 64);
574 EXPECT_GE(system_delay_before_calls,
575 WebRtcAec_system_delay(self_->aec));
576
577 // Verify that the system delay is non-negative.
578 EXPECT_LE(0, WebRtcAec_system_delay(self_->aec));
579 }
580 // Verify we are not in a non-causal state.
581 EXPECT_FALSE(non_causal);
582 }
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000583 }
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000584 }
585}
586
587} // namespace
peah50e21bd2016-03-05 08:39:21 -0800588} // namespace webrtc