blob: 9c57e8b84ef81df109c87d14c66a8fac02d43b67 [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"
peah50e21bd2016-03-05 08:39:21 -080015namespace webrtc {
bjornv@webrtc.org70569082012-04-12 12:13:50 +000016namespace {
17
18class SystemDelayTest : public ::testing::Test {
19 protected:
20 SystemDelayTest();
Sam Zackrisson7219d052018-07-09 14:28:15 +020021 void SetUp() override;
22 void TearDown() override;
bjornv@webrtc.org70569082012-04-12 12:13:50 +000023
24 // Initialization of AEC handle with respect to |sample_rate_hz|. Since the
25 // device sample rate is unimportant we set that value to 48000 Hz.
26 void Init(int sample_rate_hz);
27
28 // Makes one render call and one capture call in that specific order.
29 void RenderAndCapture(int device_buffer_ms);
30
31 // Fills up the far-end buffer with respect to the default device buffer size.
Peter Kastingdce40cf2015-08-24 14:52:23 -070032 size_t BufferFillUp();
bjornv@webrtc.org70569082012-04-12 12:13:50 +000033
34 // Runs and verifies the behavior in a stable startup procedure.
35 void RunStableStartup();
36
37 // Maps buffer size in ms into samples, taking the unprocessed frame into
38 // account.
Bjorn Volcker71012692015-06-18 11:04:56 +020039 int MapBufferSizeToSamples(int size_in_ms, bool extended_filter);
bjornv@webrtc.org70569082012-04-12 12:13:50 +000040
41 void* handle_;
pbos@webrtc.orge468bc92014-12-18 09:11:33 +000042 Aec* self_;
Peter Kastingdce40cf2015-08-24 14:52:23 -070043 size_t samples_per_frame_;
bjornv@webrtc.org70569082012-04-12 12:13:50 +000044 // Dummy input/output speech data.
mflodman@webrtc.orgd5da2502014-05-15 11:17:21 +000045 static const int kSamplesPerChunk = 160;
kwiberg@webrtc.org38214d52014-07-03 09:47:33 +000046 float far_[kSamplesPerChunk];
mflodman@webrtc.orgd5da2502014-05-15 11:17:21 +000047 float near_[kSamplesPerChunk];
48 float out_[kSamplesPerChunk];
aluebs@webrtc.orgc78d81a2015-01-21 19:10:55 +000049 const float* near_ptr_;
50 float* out_ptr_;
bjornv@webrtc.org70569082012-04-12 12:13:50 +000051};
52
53SystemDelayTest::SystemDelayTest()
andrew@webrtc.org13b2d462013-10-08 23:41:42 +000054 : handle_(NULL), self_(NULL), samples_per_frame_(0) {
bjornv@webrtc.org70569082012-04-12 12:13:50 +000055 // Dummy input data are set with more or less arbitrary non-zero values.
kwiberg@webrtc.org38214d52014-07-03 09:47:33 +000056 for (int i = 0; i < kSamplesPerChunk; i++) {
57 far_[i] = 257.0;
mflodman@webrtc.orgd5da2502014-05-15 11:17:21 +000058 near_[i] = 514.0;
kwiberg@webrtc.org38214d52014-07-03 09:47:33 +000059 }
bjornv@webrtc.org70569082012-04-12 12:13:50 +000060 memset(out_, 0, sizeof(out_));
aluebs@webrtc.orgc78d81a2015-01-21 19:10:55 +000061 near_ptr_ = near_;
62 out_ptr_ = out_;
bjornv@webrtc.org70569082012-04-12 12:13:50 +000063}
64
65void SystemDelayTest::SetUp() {
Bjorn Volcker9345e862015-06-10 21:43:36 +020066 handle_ = WebRtcAec_Create();
67 ASSERT_TRUE(handle_);
pbos@webrtc.orge468bc92014-12-18 09:11:33 +000068 self_ = reinterpret_cast<Aec*>(handle_);
bjornv@webrtc.org70569082012-04-12 12:13:50 +000069}
70
71void SystemDelayTest::TearDown() {
72 // Free AEC
Bjorn Volckerf6a99e62015-04-10 07:56:57 +020073 WebRtcAec_Free(handle_);
bjornv@webrtc.org70569082012-04-12 12:13:50 +000074 handle_ = NULL;
75}
76
77// In SWB mode nothing is added to the buffer handling with respect to
78// functionality compared to WB. We therefore only verify behavior in NB and WB.
andrew@webrtc.org13b2d462013-10-08 23:41:42 +000079static const int kSampleRateHz[] = {8000, 16000};
bjornv@webrtc.org70569082012-04-12 12:13:50 +000080static const size_t kNumSampleRates =
81 sizeof(kSampleRateHz) / sizeof(*kSampleRateHz);
82
83// Default audio device buffer size used.
84static const int kDeviceBufMs = 100;
85
86// Requirement for a stable device convergence time in ms. Should converge in
87// less than |kStableConvergenceMs|.
88static const int kStableConvergenceMs = 100;
89
90// Maximum convergence time in ms. This means that we should leave the startup
91// phase after |kMaxConvergenceMs| independent of device buffer stability
92// conditions.
93static const int kMaxConvergenceMs = 500;
94
95void SystemDelayTest::Init(int sample_rate_hz) {
96 // Initialize AEC
97 EXPECT_EQ(0, WebRtcAec_Init(handle_, sample_rate_hz, 48000));
Bjorn Volcker71012692015-06-18 11:04:56 +020098 EXPECT_EQ(0, WebRtcAec_system_delay(self_->aec));
bjornv@webrtc.org70569082012-04-12 12:13:50 +000099
100 // One frame equals 10 ms of data.
Peter Kastingdce40cf2015-08-24 14:52:23 -0700101 samples_per_frame_ = static_cast<size_t>(sample_rate_hz / 100);
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000102}
103
104void SystemDelayTest::RenderAndCapture(int device_buffer_ms) {
105 EXPECT_EQ(0, WebRtcAec_BufferFarend(handle_, far_, samples_per_frame_));
Yves Gerey665174f2018-06-19 15:03:05 +0200106 EXPECT_EQ(0, WebRtcAec_Process(handle_, &near_ptr_, 1, &out_ptr_,
107 samples_per_frame_, device_buffer_ms, 0));
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000108}
109
Peter Kastingdce40cf2015-08-24 14:52:23 -0700110size_t SystemDelayTest::BufferFillUp() {
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000111 // To make sure we have a full buffer when we verify stability we first fill
112 // up the far-end buffer with the same amount as we will report in through
113 // Process().
Peter Kastingdce40cf2015-08-24 14:52:23 -0700114 size_t buffer_size = 0;
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000115 for (int i = 0; i < kDeviceBufMs / 10; i++) {
116 EXPECT_EQ(0, WebRtcAec_BufferFarend(handle_, far_, samples_per_frame_));
117 buffer_size += samples_per_frame_;
Peter Kastingdce40cf2015-08-24 14:52:23 -0700118 EXPECT_EQ(static_cast<int>(buffer_size),
119 WebRtcAec_system_delay(self_->aec));
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000120 }
121 return buffer_size;
122}
123
124void SystemDelayTest::RunStableStartup() {
125 // To make sure we have a full buffer when we verify stability we first fill
126 // up the far-end buffer with the same amount as we will report in through
127 // Process().
Peter Kastingdce40cf2015-08-24 14:52:23 -0700128 size_t buffer_size = BufferFillUp();
Bjorn Volcker71012692015-06-18 11:04:56 +0200129
henrik.lundin0f133b92015-07-02 00:17:55 -0700130 if (WebRtcAec_delay_agnostic_enabled(self_->aec) == 1) {
Bjorn Volcker71012692015-06-18 11:04:56 +0200131 // In extended_filter mode we set the buffer size after the first processed
132 // 10 ms chunk. Hence, we don't need to wait for the reported system delay
133 // values to become stable.
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000134 RenderAndCapture(kDeviceBufMs);
135 buffer_size += samples_per_frame_;
Bjorn Volcker71012692015-06-18 11:04:56 +0200136 EXPECT_EQ(0, self_->startup_phase);
137 } else {
138 // A stable device should be accepted and put in a regular process mode
139 // within |kStableConvergenceMs|.
140 int process_time_ms = 0;
141 for (; process_time_ms < kStableConvergenceMs; process_time_ms += 10) {
142 RenderAndCapture(kDeviceBufMs);
143 buffer_size += samples_per_frame_;
144 if (self_->startup_phase == 0) {
145 // We have left the startup phase.
146 break;
147 }
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000148 }
Bjorn Volcker71012692015-06-18 11:04:56 +0200149 // Verify convergence time.
150 EXPECT_GT(kStableConvergenceMs, process_time_ms);
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000151 }
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000152 // Verify that the buffer has been flushed.
Yves Gerey665174f2018-06-19 15:03:05 +0200153 EXPECT_GE(static_cast<int>(buffer_size), WebRtcAec_system_delay(self_->aec));
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000154}
155
Yves Gerey665174f2018-06-19 15:03:05 +0200156int SystemDelayTest::MapBufferSizeToSamples(int size_in_ms,
157 bool extended_filter) {
Bjorn Volcker71012692015-06-18 11:04:56 +0200158 // If extended_filter is disabled we add an extra 10 ms for the unprocessed
159 // frame. That is simply how the algorithm is constructed.
Yves Gerey665174f2018-06-19 15:03:05 +0200160 return static_cast<int>((size_in_ms + (extended_filter ? 0 : 10)) *
161 samples_per_frame_ / 10);
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000162}
163
164// The tests should meet basic requirements and not be adjusted to what is
165// actually implemented. If we don't get good code coverage this way we either
166// lack in tests or have unnecessary code.
167// General requirements:
168// 1) If we add far-end data the system delay should be increased with the same
169// amount we add.
170// 2) If the far-end buffer is full we should flush the oldest data to make room
171// for the new. In this case the system delay is unaffected.
172// 3) There should exist a startup phase in which the buffer size is to be
173// determined. In this phase no cancellation should be performed.
174// 4) Under stable conditions (small variations in device buffer sizes) the AEC
175// should determine an appropriate local buffer size within
176// |kStableConvergenceMs| ms.
177// 5) Under unstable conditions the AEC should make a decision within
178// |kMaxConvergenceMs| ms.
179// 6) If the local buffer runs out of data we should stuff the buffer with older
180// frames.
181// 7) The system delay should within |kMaxConvergenceMs| ms heal from
182// disturbances like drift, data glitches, toggling events and outliers.
183// 8) The system delay should never become negative.
184
185TEST_F(SystemDelayTest, CorrectIncreaseWhenBufferFarend) {
186 // When we add data to the AEC buffer the internal system delay should be
187 // incremented with the same amount as the size of data.
Bjorn Volcker71012692015-06-18 11:04:56 +0200188 // This process should be independent of DA-AEC and extended_filter mode.
189 for (int extended_filter = 0; extended_filter <= 1; ++extended_filter) {
190 WebRtcAec_enable_extended_filter(self_->aec, extended_filter);
191 EXPECT_EQ(extended_filter, WebRtcAec_extended_filter_enabled(self_->aec));
192 for (int da_aec = 0; da_aec <= 1; ++da_aec) {
henrik.lundin0f133b92015-07-02 00:17:55 -0700193 WebRtcAec_enable_delay_agnostic(self_->aec, da_aec);
194 EXPECT_EQ(da_aec, WebRtcAec_delay_agnostic_enabled(self_->aec));
Bjorn Volcker71012692015-06-18 11:04:56 +0200195 for (size_t i = 0; i < kNumSampleRates; i++) {
196 Init(kSampleRateHz[i]);
197 // Loop through a couple of calls to make sure the system delay
198 // increments correctly.
199 for (int j = 1; j <= 5; j++) {
200 EXPECT_EQ(0,
201 WebRtcAec_BufferFarend(handle_, far_, samples_per_frame_));
Peter Kastingdce40cf2015-08-24 14:52:23 -0700202 EXPECT_EQ(static_cast<int>(j * samples_per_frame_),
203 WebRtcAec_system_delay(self_->aec));
Bjorn Volcker71012692015-06-18 11:04:56 +0200204 }
205 }
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000206 }
207 }
208}
209
210// TODO(bjornv): Add a test to verify behavior if the far-end buffer is full
211// when adding new data.
212
213TEST_F(SystemDelayTest, CorrectDelayAfterStableStartup) {
214 // We run the system in a stable startup. After that we verify that the system
215 // delay meets the requirements.
Bjorn Volcker71012692015-06-18 11:04:56 +0200216 // This process should be independent of DA-AEC and extended_filter mode.
217 for (int extended_filter = 0; extended_filter <= 1; ++extended_filter) {
218 WebRtcAec_enable_extended_filter(self_->aec, extended_filter);
219 EXPECT_EQ(extended_filter, WebRtcAec_extended_filter_enabled(self_->aec));
220 for (int da_aec = 0; da_aec <= 1; ++da_aec) {
henrik.lundin0f133b92015-07-02 00:17:55 -0700221 WebRtcAec_enable_delay_agnostic(self_->aec, da_aec);
222 EXPECT_EQ(da_aec, WebRtcAec_delay_agnostic_enabled(self_->aec));
Bjorn Volcker71012692015-06-18 11:04:56 +0200223 for (size_t i = 0; i < kNumSampleRates; i++) {
224 Init(kSampleRateHz[i]);
225 RunStableStartup();
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000226
Bjorn Volcker71012692015-06-18 11:04:56 +0200227 // Verify system delay with respect to requirements, i.e., the
228 // |system_delay| is in the interval [75%, 100%] of what's reported on
229 // the average.
230 // In extended_filter mode we target 50% and measure after one processed
231 // 10 ms chunk.
Peter Kastingdce40cf2015-08-24 14:52:23 -0700232 int average_reported_delay =
233 static_cast<int>(kDeviceBufMs * samples_per_frame_ / 10);
Bjorn Volcker71012692015-06-18 11:04:56 +0200234 EXPECT_GE(average_reported_delay, WebRtcAec_system_delay(self_->aec));
235 int lower_bound = WebRtcAec_extended_filter_enabled(self_->aec)
Yves Gerey665174f2018-06-19 15:03:05 +0200236 ? (average_reported_delay / 2 -
237 rtc::checked_cast<int>(samples_per_frame_))
238 : average_reported_delay * 3 / 4;
Bjorn Volcker71012692015-06-18 11:04:56 +0200239 EXPECT_LE(lower_bound, WebRtcAec_system_delay(self_->aec));
240 }
241 }
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000242 }
243}
244
245TEST_F(SystemDelayTest, CorrectDelayAfterUnstableStartup) {
Bjorn Volcker71012692015-06-18 11:04:56 +0200246 // This test does not apply in extended_filter mode, since we only use the
247 // the first 10 ms chunk to determine a reasonable buffer size. Neither does
248 // it apply if DA-AEC is on because that overrides the startup procedure.
249 WebRtcAec_enable_extended_filter(self_->aec, 0);
250 EXPECT_EQ(0, WebRtcAec_extended_filter_enabled(self_->aec));
henrik.lundin0f133b92015-07-02 00:17:55 -0700251 WebRtcAec_enable_delay_agnostic(self_->aec, 0);
252 EXPECT_EQ(0, WebRtcAec_delay_agnostic_enabled(self_->aec));
Bjorn Volcker71012692015-06-18 11:04:56 +0200253
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000254 // In an unstable system we would start processing after |kMaxConvergenceMs|.
255 // On the last frame the AEC buffer is adjusted to 60% of the last reported
256 // device buffer size.
257 // We construct an unstable system by altering the device buffer size between
258 // two values |kDeviceBufMs| +- 25 ms.
259 for (size_t i = 0; i < kNumSampleRates; i++) {
260 Init(kSampleRateHz[i]);
261
262 // To make sure we have a full buffer when we verify stability we first fill
263 // up the far-end buffer with the same amount as we will report in on the
264 // average through Process().
Peter Kastingdce40cf2015-08-24 14:52:23 -0700265 size_t buffer_size = BufferFillUp();
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000266
267 int buffer_offset_ms = 25;
268 int reported_delay_ms = 0;
269 int process_time_ms = 0;
270 for (; process_time_ms <= kMaxConvergenceMs; process_time_ms += 10) {
271 reported_delay_ms = kDeviceBufMs + buffer_offset_ms;
272 RenderAndCapture(reported_delay_ms);
273 buffer_size += samples_per_frame_;
274 buffer_offset_ms = -buffer_offset_ms;
andrew@webrtc.org1760a172013-09-25 23:17:38 +0000275 if (self_->startup_phase == 0) {
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000276 // We have left the startup phase.
277 break;
278 }
279 }
280 // Verify convergence time.
281 EXPECT_GE(kMaxConvergenceMs, process_time_ms);
282 // Verify that the buffer has been flushed.
Peter Kastingdce40cf2015-08-24 14:52:23 -0700283 EXPECT_GE(static_cast<int>(buffer_size),
284 WebRtcAec_system_delay(self_->aec));
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000285
286 // Verify system delay with respect to requirements, i.e., the
287 // |system_delay| is in the interval [60%, 100%] of what's last reported.
Peter Kastingdce40cf2015-08-24 14:52:23 -0700288 EXPECT_GE(static_cast<int>(reported_delay_ms * samples_per_frame_ / 10),
bjornv@webrtc.org4d1cfae2013-02-20 17:31:38 +0000289 WebRtcAec_system_delay(self_->aec));
Peter Kastingdce40cf2015-08-24 14:52:23 -0700290 EXPECT_LE(
291 static_cast<int>(reported_delay_ms * samples_per_frame_ / 10 * 3 / 5),
292 WebRtcAec_system_delay(self_->aec));
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000293 }
294}
295
Bjorn Volcker71012692015-06-18 11:04:56 +0200296TEST_F(SystemDelayTest, CorrectDelayAfterStableBufferBuildUp) {
297 // This test does not apply in extended_filter mode, since we only use the
298 // the first 10 ms chunk to determine a reasonable buffer size. Neither does
299 // it apply if DA-AEC is on because that overrides the startup procedure.
300 WebRtcAec_enable_extended_filter(self_->aec, 0);
301 EXPECT_EQ(0, WebRtcAec_extended_filter_enabled(self_->aec));
henrik.lundin0f133b92015-07-02 00:17:55 -0700302 WebRtcAec_enable_delay_agnostic(self_->aec, 0);
303 EXPECT_EQ(0, WebRtcAec_delay_agnostic_enabled(self_->aec));
Bjorn Volcker71012692015-06-18 11:04:56 +0200304
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000305 // In this test we start by establishing the device buffer size during stable
306 // conditions, but with an empty internal far-end buffer. Once that is done we
307 // verify that the system delay is increased correctly until we have reach an
308 // internal buffer size of 75% of what's been reported.
309 for (size_t i = 0; i < kNumSampleRates; i++) {
310 Init(kSampleRateHz[i]);
311
312 // We assume that running |kStableConvergenceMs| calls will put the
313 // algorithm in a state where the device buffer size has been determined. We
314 // can make that assumption since we have a separate stability test.
315 int process_time_ms = 0;
316 for (; process_time_ms < kStableConvergenceMs; process_time_ms += 10) {
Yves Gerey665174f2018-06-19 15:03:05 +0200317 EXPECT_EQ(0, WebRtcAec_Process(handle_, &near_ptr_, 1, &out_ptr_,
318 samples_per_frame_, kDeviceBufMs, 0));
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000319 }
bjornv@webrtc.orgb51d3ea2014-06-05 13:41:33 +0000320 // Verify that a buffer size has been established.
321 EXPECT_EQ(0, self_->checkBuffSize);
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000322
bjornv@webrtc.orgb51d3ea2014-06-05 13:41:33 +0000323 // We now have established the required buffer size. Let us verify that we
324 // fill up before leaving the startup phase for normal processing.
Peter Kastingdce40cf2015-08-24 14:52:23 -0700325 size_t buffer_size = 0;
326 size_t target_buffer_size = kDeviceBufMs * samples_per_frame_ / 10 * 3 / 4;
bjornv@webrtc.orgb51d3ea2014-06-05 13:41:33 +0000327 process_time_ms = 0;
328 for (; process_time_ms <= kMaxConvergenceMs; process_time_ms += 10) {
329 RenderAndCapture(kDeviceBufMs);
330 buffer_size += samples_per_frame_;
331 if (self_->startup_phase == 0) {
332 // We have left the startup phase.
333 break;
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000334 }
335 }
bjornv@webrtc.orgb51d3ea2014-06-05 13:41:33 +0000336 // Verify convergence time.
337 EXPECT_GT(kMaxConvergenceMs, process_time_ms);
338 // Verify that the buffer has reached the desired size.
Peter Kastingdce40cf2015-08-24 14:52:23 -0700339 EXPECT_LE(static_cast<int>(target_buffer_size),
340 WebRtcAec_system_delay(self_->aec));
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000341
342 // Verify normal behavior (system delay is kept constant) after startup by
343 // running a couple of calls to BufferFarend() and Process().
344 for (int j = 0; j < 6; j++) {
bjornv@webrtc.org4d1cfae2013-02-20 17:31:38 +0000345 int system_delay_before_calls = WebRtcAec_system_delay(self_->aec);
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000346 RenderAndCapture(kDeviceBufMs);
bjornv@webrtc.org4d1cfae2013-02-20 17:31:38 +0000347 EXPECT_EQ(system_delay_before_calls, WebRtcAec_system_delay(self_->aec));
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000348 }
349 }
350}
351
352TEST_F(SystemDelayTest, CorrectDelayWhenBufferUnderrun) {
353 // Here we test a buffer under run scenario. If we keep on calling
354 // WebRtcAec_Process() we will finally run out of data, but should
355 // automatically stuff the buffer. We verify this behavior by checking if the
356 // system delay goes negative.
Bjorn Volcker71012692015-06-18 11:04:56 +0200357 // This process should be independent of DA-AEC and extended_filter mode.
358 for (int extended_filter = 0; extended_filter <= 1; ++extended_filter) {
359 WebRtcAec_enable_extended_filter(self_->aec, extended_filter);
360 EXPECT_EQ(extended_filter, WebRtcAec_extended_filter_enabled(self_->aec));
361 for (int da_aec = 0; da_aec <= 1; ++da_aec) {
henrik.lundin0f133b92015-07-02 00:17:55 -0700362 WebRtcAec_enable_delay_agnostic(self_->aec, da_aec);
363 EXPECT_EQ(da_aec, WebRtcAec_delay_agnostic_enabled(self_->aec));
Bjorn Volcker71012692015-06-18 11:04:56 +0200364 for (size_t i = 0; i < kNumSampleRates; i++) {
365 Init(kSampleRateHz[i]);
366 RunStableStartup();
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000367
Bjorn Volcker71012692015-06-18 11:04:56 +0200368 // The AEC has now left the Startup phase. We now have at most
369 // |kStableConvergenceMs| in the buffer. Keep on calling Process() until
370 // we run out of data and verify that the system delay is non-negative.
371 for (int j = 0; j <= kStableConvergenceMs; j += 10) {
372 EXPECT_EQ(0, WebRtcAec_Process(handle_, &near_ptr_, 1, &out_ptr_,
373 samples_per_frame_, kDeviceBufMs, 0));
374 EXPECT_LE(0, WebRtcAec_system_delay(self_->aec));
375 }
376 }
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000377 }
378 }
379}
380
Bjorn Volcker71012692015-06-18 11:04:56 +0200381TEST_F(SystemDelayTest, CorrectDelayDuringDrift) {
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000382 // This drift test should verify that the system delay is never exceeding the
383 // device buffer. The drift is simulated by decreasing the reported device
384 // buffer size by 1 ms every 100 ms. If the device buffer size goes below 30
385 // ms we jump (add) 10 ms to give a repeated pattern.
bjornv@webrtc.org5c3f4e32014-06-19 09:51:29 +0000386
Bjorn Volcker71012692015-06-18 11:04:56 +0200387 // This process should be independent of DA-AEC and extended_filter mode.
388 for (int extended_filter = 0; extended_filter <= 1; ++extended_filter) {
389 WebRtcAec_enable_extended_filter(self_->aec, extended_filter);
390 EXPECT_EQ(extended_filter, WebRtcAec_extended_filter_enabled(self_->aec));
391 for (int da_aec = 0; da_aec <= 1; ++da_aec) {
henrik.lundin0f133b92015-07-02 00:17:55 -0700392 WebRtcAec_enable_delay_agnostic(self_->aec, da_aec);
393 EXPECT_EQ(da_aec, WebRtcAec_delay_agnostic_enabled(self_->aec));
Bjorn Volcker71012692015-06-18 11:04:56 +0200394 for (size_t i = 0; i < kNumSampleRates; i++) {
395 Init(kSampleRateHz[i]);
396 RunStableStartup();
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000397
Bjorn Volcker71012692015-06-18 11:04:56 +0200398 // We have left the startup phase and proceed with normal processing.
399 int jump = 0;
400 for (int j = 0; j < 1000; j++) {
401 // Drift = -1 ms per 100 ms of data.
402 int device_buf_ms = kDeviceBufMs - (j / 10) + jump;
Yves Gerey665174f2018-06-19 15:03:05 +0200403 int device_buf =
404 MapBufferSizeToSamples(device_buf_ms, extended_filter == 1);
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000405
Bjorn Volcker71012692015-06-18 11:04:56 +0200406 if (device_buf_ms < 30) {
407 // Add 10 ms data, taking affect next frame.
408 jump += 10;
409 }
410 RenderAndCapture(device_buf_ms);
411
412 // Verify that the system delay does not exceed the device buffer.
413 EXPECT_GE(device_buf, WebRtcAec_system_delay(self_->aec));
414
415 // Verify that the system delay is non-negative.
416 EXPECT_LE(0, WebRtcAec_system_delay(self_->aec));
417 }
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000418 }
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000419 }
420 }
421}
422
Bjorn Volcker71012692015-06-18 11:04:56 +0200423TEST_F(SystemDelayTest, ShouldRecoverAfterGlitch) {
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000424 // This glitch test should verify that the system delay recovers if there is
425 // a glitch in data. The data glitch is constructed as 200 ms of buffering
426 // after which the stable procedure continues. The glitch is never reported by
427 // the device.
428 // The system is said to be in a non-causal state if the difference between
429 // the device buffer and system delay is less than a block (64 samples).
bjornv@webrtc.org5c3f4e32014-06-19 09:51:29 +0000430
Bjorn Volcker71012692015-06-18 11:04:56 +0200431 // This process should be independent of DA-AEC and extended_filter mode.
432 for (int extended_filter = 0; extended_filter <= 1; ++extended_filter) {
433 WebRtcAec_enable_extended_filter(self_->aec, extended_filter);
434 EXPECT_EQ(extended_filter, WebRtcAec_extended_filter_enabled(self_->aec));
435 for (int da_aec = 0; da_aec <= 1; ++da_aec) {
henrik.lundin0f133b92015-07-02 00:17:55 -0700436 WebRtcAec_enable_delay_agnostic(self_->aec, da_aec);
437 EXPECT_EQ(da_aec, WebRtcAec_delay_agnostic_enabled(self_->aec));
Bjorn Volcker71012692015-06-18 11:04:56 +0200438 for (size_t i = 0; i < kNumSampleRates; i++) {
439 Init(kSampleRateHz[i]);
440 RunStableStartup();
Yves Gerey665174f2018-06-19 15:03:05 +0200441 int device_buf =
442 MapBufferSizeToSamples(kDeviceBufMs, extended_filter == 1);
Bjorn Volcker71012692015-06-18 11:04:56 +0200443 // Glitch state.
444 for (int j = 0; j < 20; j++) {
445 EXPECT_EQ(0,
446 WebRtcAec_BufferFarend(handle_, far_, samples_per_frame_));
447 // No need to verify system delay, since that is done in a separate
448 // test.
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000449 }
Bjorn Volcker71012692015-06-18 11:04:56 +0200450 // Verify that we are in a non-causal state, i.e.,
451 // |system_delay| > |device_buf|.
452 EXPECT_LT(device_buf, WebRtcAec_system_delay(self_->aec));
453
454 // Recover state. Should recover at least 4 ms of data per 10 ms, hence
455 // a glitch of 200 ms will take at most 200 * 10 / 4 = 500 ms to recover
456 // from.
457 bool non_causal = true; // We are currently in a non-causal state.
458 for (int j = 0; j < 50; j++) {
459 int system_delay_before = WebRtcAec_system_delay(self_->aec);
460 RenderAndCapture(kDeviceBufMs);
461 int system_delay_after = WebRtcAec_system_delay(self_->aec);
462 // We have recovered if
463 // |device_buf| - |system_delay_after| >= PART_LEN (1 block).
464 // During recovery, |system_delay_after| < |system_delay_before|,
465 // otherwise they are equal.
466 if (non_causal) {
467 EXPECT_LT(system_delay_after, system_delay_before);
468 if (device_buf - system_delay_after >= PART_LEN) {
469 non_causal = false;
470 }
471 } else {
472 EXPECT_EQ(system_delay_before, system_delay_after);
473 }
474 // Verify that the system delay is non-negative.
475 EXPECT_LE(0, WebRtcAec_system_delay(self_->aec));
476 }
477 // Check that we have recovered.
478 EXPECT_FALSE(non_causal);
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000479 }
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000480 }
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000481 }
482}
483
484TEST_F(SystemDelayTest, UnaffectedWhenSpuriousDeviceBufferValues) {
Bjorn Volcker71012692015-06-18 11:04:56 +0200485 // This test does not apply in extended_filter mode, since we only use the
486 // the first 10 ms chunk to determine a reasonable buffer size.
487 const int extended_filter = 0;
488 WebRtcAec_enable_extended_filter(self_->aec, extended_filter);
489 EXPECT_EQ(extended_filter, WebRtcAec_extended_filter_enabled(self_->aec));
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000490
Bjorn Volcker71012692015-06-18 11:04:56 +0200491 // Should be DA-AEC independent.
492 for (int da_aec = 0; da_aec <= 1; ++da_aec) {
henrik.lundin0f133b92015-07-02 00:17:55 -0700493 WebRtcAec_enable_delay_agnostic(self_->aec, da_aec);
494 EXPECT_EQ(da_aec, WebRtcAec_delay_agnostic_enabled(self_->aec));
Bjorn Volcker71012692015-06-18 11:04:56 +0200495 // This spurious device buffer data test aims at verifying that the system
496 // delay is unaffected by large outliers.
497 // The system is said to be in a non-causal state if the difference between
498 // the device buffer and system delay is less than a block (64 samples).
499 for (size_t i = 0; i < kNumSampleRates; i++) {
500 Init(kSampleRateHz[i]);
501 RunStableStartup();
Yves Gerey665174f2018-06-19 15:03:05 +0200502 int device_buf =
503 MapBufferSizeToSamples(kDeviceBufMs, extended_filter == 1);
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000504
Bjorn Volcker71012692015-06-18 11:04:56 +0200505 // Normal state. We are currently not in a non-causal state.
506 bool non_causal = false;
507
508 // Run 1 s and replace device buffer size with 500 ms every 100 ms.
509 for (int j = 0; j < 100; j++) {
510 int system_delay_before_calls = WebRtcAec_system_delay(self_->aec);
511 int device_buf_ms = j % 10 == 0 ? 500 : kDeviceBufMs;
512 RenderAndCapture(device_buf_ms);
513
514 // Check for non-causality.
515 if (device_buf - WebRtcAec_system_delay(self_->aec) < PART_LEN) {
516 non_causal = true;
517 }
518 EXPECT_FALSE(non_causal);
519 EXPECT_EQ(system_delay_before_calls,
520 WebRtcAec_system_delay(self_->aec));
521
522 // Verify that the system delay is non-negative.
523 EXPECT_LE(0, WebRtcAec_system_delay(self_->aec));
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000524 }
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000525 }
526 }
527}
528
529TEST_F(SystemDelayTest, CorrectImpactWhenTogglingDeviceBufferValues) {
530 // This test aims at verifying that the system delay is "unaffected" by
531 // toggling values reported by the device.
532 // The test is constructed such that every other device buffer value is zero
533 // and then 2 * |kDeviceBufMs|, hence the size is constant on the average. The
534 // zero values will force us into a non-causal state and thereby lowering the
Bjorn Volcker71012692015-06-18 11:04:56 +0200535 // system delay until we basically run out of data. Once that happens the
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000536 // buffer will be stuffed.
537 // TODO(bjornv): This test will have a better impact if we verified that the
Bjorn Volcker71012692015-06-18 11:04:56 +0200538 // delay estimate goes up when the system delay goes down to meet the average
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000539 // device buffer size.
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000540
Bjorn Volcker71012692015-06-18 11:04:56 +0200541 // This test does not apply if DA-AEC is enabled and extended_filter mode
542 // disabled.
543 for (int extended_filter = 0; extended_filter <= 1; ++extended_filter) {
544 WebRtcAec_enable_extended_filter(self_->aec, extended_filter);
545 EXPECT_EQ(extended_filter, WebRtcAec_extended_filter_enabled(self_->aec));
546 for (int da_aec = 0; da_aec <= 1; ++da_aec) {
henrik.lundin0f133b92015-07-02 00:17:55 -0700547 WebRtcAec_enable_delay_agnostic(self_->aec, da_aec);
548 EXPECT_EQ(da_aec, WebRtcAec_delay_agnostic_enabled(self_->aec));
Bjorn Volcker71012692015-06-18 11:04:56 +0200549 if (extended_filter == 0 && da_aec == 1) {
550 continue;
551 }
552 for (size_t i = 0; i < kNumSampleRates; i++) {
553 Init(kSampleRateHz[i]);
554 RunStableStartup();
Yves Gerey665174f2018-06-19 15:03:05 +0200555 const int device_buf =
556 MapBufferSizeToSamples(kDeviceBufMs, extended_filter == 1);
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000557
Bjorn Volcker71012692015-06-18 11:04:56 +0200558 // Normal state. We are currently not in a non-causal state.
559 bool non_causal = false;
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000560
Bjorn Volcker71012692015-06-18 11:04:56 +0200561 // Loop through 100 frames (both render and capture), which equals 1 s
562 // of data. Every odd frame we set the device buffer size to
563 // 2 * |kDeviceBufMs| and even frames we set the device buffer size to
564 // zero.
565 for (int j = 0; j < 100; j++) {
566 int system_delay_before_calls = WebRtcAec_system_delay(self_->aec);
567 int device_buf_ms = 2 * (j % 2) * kDeviceBufMs;
568 RenderAndCapture(device_buf_ms);
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000569
Bjorn Volcker71012692015-06-18 11:04:56 +0200570 // Check for non-causality, compared with the average device buffer
571 // size.
572 non_causal |= (device_buf - WebRtcAec_system_delay(self_->aec) < 64);
573 EXPECT_GE(system_delay_before_calls,
574 WebRtcAec_system_delay(self_->aec));
575
576 // Verify that the system delay is non-negative.
577 EXPECT_LE(0, WebRtcAec_system_delay(self_->aec));
578 }
579 // Verify we are not in a non-causal state.
580 EXPECT_FALSE(non_causal);
581 }
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000582 }
bjornv@webrtc.org70569082012-04-12 12:13:50 +0000583 }
584}
585
586} // namespace
peah50e21bd2016-03-05 08:39:21 -0800587} // namespace webrtc