1 /*
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 
11 #include "modules/audio_processing/aec/aec_core.h"
12 #include "modules/audio_processing/aec/echo_cancellation.h"
13 #include "rtc_base/numerics/safe_conversions.h"
14 #include "test/gtest.h"
15 #include "typedefs.h"  // NOLINT(build/include)
16 namespace webrtc {
17 namespace {
18 
19 class 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.
33   size_t BufferFillUp();
34 
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.
40   int MapBufferSizeToSamples(int size_in_ms, bool extended_filter);
41 
42   void* handle_;
43   Aec* self_;
44   size_t samples_per_frame_;
45   // Dummy input/output speech data.
46   static const int kSamplesPerChunk = 160;
47   float far_[kSamplesPerChunk];
48   float near_[kSamplesPerChunk];
49   float out_[kSamplesPerChunk];
50   const float* near_ptr_;
51   float* out_ptr_;
52 };
53 
SystemDelayTest()54 SystemDelayTest::SystemDelayTest()
55     : handle_(NULL), self_(NULL), samples_per_frame_(0) {
56   // Dummy input data are set with more or less arbitrary non-zero values.
57   for (int i = 0; i < kSamplesPerChunk; i++) {
58     far_[i] = 257.0;
59     near_[i] = 514.0;
60   }
61   memset(out_, 0, sizeof(out_));
62   near_ptr_ = near_;
63   out_ptr_ = out_;
64 }
65 
SetUp()66 void SystemDelayTest::SetUp() {
67   handle_ = WebRtcAec_Create();
68   ASSERT_TRUE(handle_);
69   self_ = reinterpret_cast<Aec*>(handle_);
70 }
71 
TearDown()72 void SystemDelayTest::TearDown() {
73   // Free AEC
74   WebRtcAec_Free(handle_);
75   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.
80 static const int kSampleRateHz[] = {8000, 16000};
81 static const size_t kNumSampleRates =
82     sizeof(kSampleRateHz) / sizeof(*kSampleRateHz);
83 
84 // Default audio device buffer size used.
85 static const int kDeviceBufMs = 100;
86 
87 // Requirement for a stable device convergence time in ms. Should converge in
88 // less than |kStableConvergenceMs|.
89 static 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.
94 static const int kMaxConvergenceMs = 500;
95 
Init(int sample_rate_hz)96 void SystemDelayTest::Init(int sample_rate_hz) {
97   // Initialize AEC
98   EXPECT_EQ(0, WebRtcAec_Init(handle_, sample_rate_hz, 48000));
99   EXPECT_EQ(0, WebRtcAec_system_delay(self_->aec));
100 
101   // One frame equals 10 ms of data.
102   samples_per_frame_ = static_cast<size_t>(sample_rate_hz / 100);
103 }
104 
RenderAndCapture(int device_buffer_ms)105 void SystemDelayTest::RenderAndCapture(int device_buffer_ms) {
106   EXPECT_EQ(0, WebRtcAec_BufferFarend(handle_, far_, samples_per_frame_));
107   EXPECT_EQ(0,
108             WebRtcAec_Process(handle_,
109                               &near_ptr_,
110                               1,
111                               &out_ptr_,
112                               samples_per_frame_,
113                               device_buffer_ms,
114                               0));
115 }
116 
BufferFillUp()117 size_t SystemDelayTest::BufferFillUp() {
118   // To make sure we have a full buffer when we verify stability we first fill
119   // up the far-end buffer with the same amount as we will report in through
120   // Process().
121   size_t buffer_size = 0;
122   for (int i = 0; i < kDeviceBufMs / 10; i++) {
123     EXPECT_EQ(0, WebRtcAec_BufferFarend(handle_, far_, samples_per_frame_));
124     buffer_size += samples_per_frame_;
125     EXPECT_EQ(static_cast<int>(buffer_size),
126               WebRtcAec_system_delay(self_->aec));
127   }
128   return buffer_size;
129 }
130 
RunStableStartup()131 void SystemDelayTest::RunStableStartup() {
132   // To make sure we have a full buffer when we verify stability we first fill
133   // up the far-end buffer with the same amount as we will report in through
134   // Process().
135   size_t buffer_size = BufferFillUp();
136 
137   if (WebRtcAec_delay_agnostic_enabled(self_->aec) == 1) {
138     // In extended_filter mode we set the buffer size after the first processed
139     // 10 ms chunk. Hence, we don't need to wait for the reported system delay
140     // values to become stable.
141     RenderAndCapture(kDeviceBufMs);
142     buffer_size += samples_per_frame_;
143     EXPECT_EQ(0, self_->startup_phase);
144   } else {
145     // A stable device should be accepted and put in a regular process mode
146     // within |kStableConvergenceMs|.
147     int process_time_ms = 0;
148     for (; process_time_ms < kStableConvergenceMs; process_time_ms += 10) {
149       RenderAndCapture(kDeviceBufMs);
150       buffer_size += samples_per_frame_;
151       if (self_->startup_phase == 0) {
152         // We have left the startup phase.
153         break;
154       }
155     }
156     // Verify convergence time.
157     EXPECT_GT(kStableConvergenceMs, process_time_ms);
158   }
159   // Verify that the buffer has been flushed.
160   EXPECT_GE(static_cast<int>(buffer_size),
161             WebRtcAec_system_delay(self_->aec));
162 }
163 
MapBufferSizeToSamples(int size_in_ms,bool extended_filter)164   int SystemDelayTest::MapBufferSizeToSamples(int size_in_ms,
165                                               bool extended_filter) {
166   // If extended_filter is disabled we add an extra 10 ms for the unprocessed
167   // frame. That is simply how the algorithm is constructed.
168   return static_cast<int>(
169       (size_in_ms + (extended_filter ? 0 : 10)) * samples_per_frame_ / 10);
170 }
171 
172 // The tests should meet basic requirements and not be adjusted to what is
173 // actually implemented. If we don't get good code coverage this way we either
174 // lack in tests or have unnecessary code.
175 // General requirements:
176 // 1) If we add far-end data the system delay should be increased with the same
177 //    amount we add.
178 // 2) If the far-end buffer is full we should flush the oldest data to make room
179 //    for the new. In this case the system delay is unaffected.
180 // 3) There should exist a startup phase in which the buffer size is to be
181 //    determined. In this phase no cancellation should be performed.
182 // 4) Under stable conditions (small variations in device buffer sizes) the AEC
183 //    should determine an appropriate local buffer size within
184 //    |kStableConvergenceMs| ms.
185 // 5) Under unstable conditions the AEC should make a decision within
186 //    |kMaxConvergenceMs| ms.
187 // 6) If the local buffer runs out of data we should stuff the buffer with older
188 //    frames.
189 // 7) The system delay should within |kMaxConvergenceMs| ms heal from
190 //    disturbances like drift, data glitches, toggling events and outliers.
191 // 8) The system delay should never become negative.
192 
TEST_F(SystemDelayTest,CorrectIncreaseWhenBufferFarend)193 TEST_F(SystemDelayTest, CorrectIncreaseWhenBufferFarend) {
194   // When we add data to the AEC buffer the internal system delay should be
195   // incremented with the same amount as the size of data.
196   // This process should be independent of DA-AEC and extended_filter mode.
197   for (int extended_filter = 0; extended_filter <= 1; ++extended_filter) {
198     WebRtcAec_enable_extended_filter(self_->aec, extended_filter);
199     EXPECT_EQ(extended_filter, WebRtcAec_extended_filter_enabled(self_->aec));
200     for (int da_aec = 0; da_aec <= 1; ++da_aec) {
201       WebRtcAec_enable_delay_agnostic(self_->aec, da_aec);
202       EXPECT_EQ(da_aec, WebRtcAec_delay_agnostic_enabled(self_->aec));
203       for (size_t i = 0; i < kNumSampleRates; i++) {
204         Init(kSampleRateHz[i]);
205         // Loop through a couple of calls to make sure the system delay
206         // increments correctly.
207         for (int j = 1; j <= 5; j++) {
208           EXPECT_EQ(0,
209                     WebRtcAec_BufferFarend(handle_, far_, samples_per_frame_));
210           EXPECT_EQ(static_cast<int>(j * samples_per_frame_),
211                     WebRtcAec_system_delay(self_->aec));
212         }
213       }
214     }
215   }
216 }
217 
218 // TODO(bjornv): Add a test to verify behavior if the far-end buffer is full
219 // when adding new data.
220 
TEST_F(SystemDelayTest,CorrectDelayAfterStableStartup)221 TEST_F(SystemDelayTest, CorrectDelayAfterStableStartup) {
222   // We run the system in a stable startup. After that we verify that the system
223   // delay meets the requirements.
224   // This process should be independent of DA-AEC and extended_filter mode.
225   for (int extended_filter = 0; extended_filter <= 1; ++extended_filter) {
226     WebRtcAec_enable_extended_filter(self_->aec, extended_filter);
227     EXPECT_EQ(extended_filter, WebRtcAec_extended_filter_enabled(self_->aec));
228     for (int da_aec = 0; da_aec <= 1; ++da_aec) {
229       WebRtcAec_enable_delay_agnostic(self_->aec, da_aec);
230       EXPECT_EQ(da_aec, WebRtcAec_delay_agnostic_enabled(self_->aec));
231       for (size_t i = 0; i < kNumSampleRates; i++) {
232         Init(kSampleRateHz[i]);
233         RunStableStartup();
234 
235         // Verify system delay with respect to requirements, i.e., the
236         // |system_delay| is in the interval [75%, 100%] of what's reported on
237         // the average.
238         // In extended_filter mode we target 50% and measure after one processed
239         // 10 ms chunk.
240         int average_reported_delay =
241             static_cast<int>(kDeviceBufMs * samples_per_frame_ / 10);
242         EXPECT_GE(average_reported_delay, WebRtcAec_system_delay(self_->aec));
243         int lower_bound = WebRtcAec_extended_filter_enabled(self_->aec)
244             ? (average_reported_delay / 2 -
245                rtc::checked_cast<int>(samples_per_frame_))
246             : average_reported_delay * 3 / 4;
247         EXPECT_LE(lower_bound, WebRtcAec_system_delay(self_->aec));
248       }
249     }
250   }
251 }
252 
TEST_F(SystemDelayTest,CorrectDelayAfterUnstableStartup)253 TEST_F(SystemDelayTest, CorrectDelayAfterUnstableStartup) {
254   // This test does not apply in extended_filter mode, since we only use the
255   // the first 10 ms chunk to determine a reasonable buffer size. Neither does
256   // it apply if DA-AEC is on because that overrides the startup procedure.
257   WebRtcAec_enable_extended_filter(self_->aec, 0);
258   EXPECT_EQ(0, WebRtcAec_extended_filter_enabled(self_->aec));
259   WebRtcAec_enable_delay_agnostic(self_->aec, 0);
260   EXPECT_EQ(0, WebRtcAec_delay_agnostic_enabled(self_->aec));
261 
262   // In an unstable system we would start processing after |kMaxConvergenceMs|.
263   // On the last frame the AEC buffer is adjusted to 60% of the last reported
264   // device buffer size.
265   // We construct an unstable system by altering the device buffer size between
266   // two values |kDeviceBufMs| +- 25 ms.
267   for (size_t i = 0; i < kNumSampleRates; i++) {
268     Init(kSampleRateHz[i]);
269 
270     // To make sure we have a full buffer when we verify stability we first fill
271     // up the far-end buffer with the same amount as we will report in on the
272     // average through Process().
273     size_t buffer_size = BufferFillUp();
274 
275     int buffer_offset_ms = 25;
276     int reported_delay_ms = 0;
277     int process_time_ms = 0;
278     for (; process_time_ms <= kMaxConvergenceMs; process_time_ms += 10) {
279       reported_delay_ms = kDeviceBufMs + buffer_offset_ms;
280       RenderAndCapture(reported_delay_ms);
281       buffer_size += samples_per_frame_;
282       buffer_offset_ms = -buffer_offset_ms;
283       if (self_->startup_phase == 0) {
284         // We have left the startup phase.
285         break;
286       }
287     }
288     // Verify convergence time.
289     EXPECT_GE(kMaxConvergenceMs, process_time_ms);
290     // Verify that the buffer has been flushed.
291     EXPECT_GE(static_cast<int>(buffer_size),
292               WebRtcAec_system_delay(self_->aec));
293 
294     // Verify system delay with respect to requirements, i.e., the
295     // |system_delay| is in the interval [60%, 100%] of what's last reported.
296     EXPECT_GE(static_cast<int>(reported_delay_ms * samples_per_frame_ / 10),
297               WebRtcAec_system_delay(self_->aec));
298     EXPECT_LE(
299         static_cast<int>(reported_delay_ms * samples_per_frame_ / 10 * 3 / 5),
300         WebRtcAec_system_delay(self_->aec));
301   }
302 }
303 
TEST_F(SystemDelayTest,CorrectDelayAfterStableBufferBuildUp)304 TEST_F(SystemDelayTest, CorrectDelayAfterStableBufferBuildUp) {
305   // This test does not apply in extended_filter mode, since we only use the
306   // the first 10 ms chunk to determine a reasonable buffer size. Neither does
307   // it apply if DA-AEC is on because that overrides the startup procedure.
308   WebRtcAec_enable_extended_filter(self_->aec, 0);
309   EXPECT_EQ(0, WebRtcAec_extended_filter_enabled(self_->aec));
310   WebRtcAec_enable_delay_agnostic(self_->aec, 0);
311   EXPECT_EQ(0, WebRtcAec_delay_agnostic_enabled(self_->aec));
312 
313   // In this test we start by establishing the device buffer size during stable
314   // conditions, but with an empty internal far-end buffer. Once that is done we
315   // verify that the system delay is increased correctly until we have reach an
316   // internal buffer size of 75% of what's been reported.
317   for (size_t i = 0; i < kNumSampleRates; i++) {
318     Init(kSampleRateHz[i]);
319 
320     // We assume that running |kStableConvergenceMs| calls will put the
321     // algorithm in a state where the device buffer size has been determined. We
322     // can make that assumption since we have a separate stability test.
323     int process_time_ms = 0;
324     for (; process_time_ms < kStableConvergenceMs; process_time_ms += 10) {
325       EXPECT_EQ(0,
326                 WebRtcAec_Process(handle_,
327                                   &near_ptr_,
328                                   1,
329                                   &out_ptr_,
330                                   samples_per_frame_,
331                                   kDeviceBufMs,
332                                   0));
333     }
334     // Verify that a buffer size has been established.
335     EXPECT_EQ(0, self_->checkBuffSize);
336 
337     // We now have established the required buffer size. Let us verify that we
338     // fill up before leaving the startup phase for normal processing.
339     size_t buffer_size = 0;
340     size_t target_buffer_size = kDeviceBufMs * samples_per_frame_ / 10 * 3 / 4;
341     process_time_ms = 0;
342     for (; process_time_ms <= kMaxConvergenceMs; process_time_ms += 10) {
343       RenderAndCapture(kDeviceBufMs);
344       buffer_size += samples_per_frame_;
345       if (self_->startup_phase == 0) {
346         // We have left the startup phase.
347         break;
348       }
349     }
350     // Verify convergence time.
351     EXPECT_GT(kMaxConvergenceMs, process_time_ms);
352     // Verify that the buffer has reached the desired size.
353     EXPECT_LE(static_cast<int>(target_buffer_size),
354               WebRtcAec_system_delay(self_->aec));
355 
356     // Verify normal behavior (system delay is kept constant) after startup by
357     // running a couple of calls to BufferFarend() and Process().
358     for (int j = 0; j < 6; j++) {
359       int system_delay_before_calls = WebRtcAec_system_delay(self_->aec);
360       RenderAndCapture(kDeviceBufMs);
361       EXPECT_EQ(system_delay_before_calls, WebRtcAec_system_delay(self_->aec));
362     }
363   }
364 }
365 
TEST_F(SystemDelayTest,CorrectDelayWhenBufferUnderrun)366 TEST_F(SystemDelayTest, CorrectDelayWhenBufferUnderrun) {
367   // Here we test a buffer under run scenario. If we keep on calling
368   // WebRtcAec_Process() we will finally run out of data, but should
369   // automatically stuff the buffer. We verify this behavior by checking if the
370   // system delay goes negative.
371   // This process should be independent of DA-AEC and extended_filter mode.
372   for (int extended_filter = 0; extended_filter <= 1; ++extended_filter) {
373     WebRtcAec_enable_extended_filter(self_->aec, extended_filter);
374     EXPECT_EQ(extended_filter, WebRtcAec_extended_filter_enabled(self_->aec));
375     for (int da_aec = 0; da_aec <= 1; ++da_aec) {
376       WebRtcAec_enable_delay_agnostic(self_->aec, da_aec);
377       EXPECT_EQ(da_aec, WebRtcAec_delay_agnostic_enabled(self_->aec));
378       for (size_t i = 0; i < kNumSampleRates; i++) {
379         Init(kSampleRateHz[i]);
380         RunStableStartup();
381 
382         // The AEC has now left the Startup phase. We now have at most
383         // |kStableConvergenceMs| in the buffer. Keep on calling Process() until
384         // we run out of data and verify that the system delay is non-negative.
385         for (int j = 0; j <= kStableConvergenceMs; j += 10) {
386           EXPECT_EQ(0, WebRtcAec_Process(handle_, &near_ptr_, 1, &out_ptr_,
387                                          samples_per_frame_, kDeviceBufMs, 0));
388           EXPECT_LE(0, WebRtcAec_system_delay(self_->aec));
389         }
390       }
391     }
392   }
393 }
394 
TEST_F(SystemDelayTest,CorrectDelayDuringDrift)395 TEST_F(SystemDelayTest, CorrectDelayDuringDrift) {
396   // This drift test should verify that the system delay is never exceeding the
397   // device buffer. The drift is simulated by decreasing the reported device
398   // buffer size by 1 ms every 100 ms. If the device buffer size goes below 30
399   // ms we jump (add) 10 ms to give a repeated pattern.
400 
401   // This process should be independent of DA-AEC and extended_filter mode.
402   for (int extended_filter = 0; extended_filter <= 1; ++extended_filter) {
403     WebRtcAec_enable_extended_filter(self_->aec, extended_filter);
404     EXPECT_EQ(extended_filter, WebRtcAec_extended_filter_enabled(self_->aec));
405     for (int da_aec = 0; da_aec <= 1; ++da_aec) {
406       WebRtcAec_enable_delay_agnostic(self_->aec, da_aec);
407       EXPECT_EQ(da_aec, WebRtcAec_delay_agnostic_enabled(self_->aec));
408       for (size_t i = 0; i < kNumSampleRates; i++) {
409         Init(kSampleRateHz[i]);
410         RunStableStartup();
411 
412         // We have left the startup phase and proceed with normal processing.
413         int jump = 0;
414         for (int j = 0; j < 1000; j++) {
415           // Drift = -1 ms per 100 ms of data.
416           int device_buf_ms = kDeviceBufMs - (j / 10) + jump;
417           int device_buf = MapBufferSizeToSamples(device_buf_ms,
418                                                   extended_filter == 1);
419 
420           if (device_buf_ms < 30) {
421             // Add 10 ms data, taking affect next frame.
422             jump += 10;
423           }
424           RenderAndCapture(device_buf_ms);
425 
426           // Verify that the system delay does not exceed the device buffer.
427           EXPECT_GE(device_buf, WebRtcAec_system_delay(self_->aec));
428 
429           // Verify that the system delay is non-negative.
430           EXPECT_LE(0, WebRtcAec_system_delay(self_->aec));
431         }
432       }
433     }
434   }
435 }
436 
TEST_F(SystemDelayTest,ShouldRecoverAfterGlitch)437 TEST_F(SystemDelayTest, ShouldRecoverAfterGlitch) {
438   // This glitch test should verify that the system delay recovers if there is
439   // a glitch in data. The data glitch is constructed as 200 ms of buffering
440   // after which the stable procedure continues. The glitch is never reported by
441   // the device.
442   // The system is said to be in a non-causal state if the difference between
443   // the device buffer and system delay is less than a block (64 samples).
444 
445   // This process should be independent of DA-AEC and extended_filter mode.
446   for (int extended_filter = 0; extended_filter <= 1; ++extended_filter) {
447     WebRtcAec_enable_extended_filter(self_->aec, extended_filter);
448     EXPECT_EQ(extended_filter, WebRtcAec_extended_filter_enabled(self_->aec));
449     for (int da_aec = 0; da_aec <= 1; ++da_aec) {
450       WebRtcAec_enable_delay_agnostic(self_->aec, da_aec);
451       EXPECT_EQ(da_aec, WebRtcAec_delay_agnostic_enabled(self_->aec));
452       for (size_t i = 0; i < kNumSampleRates; i++) {
453         Init(kSampleRateHz[i]);
454         RunStableStartup();
455         int device_buf = MapBufferSizeToSamples(kDeviceBufMs,
456                                                 extended_filter == 1);
457         // Glitch state.
458         for (int j = 0; j < 20; j++) {
459           EXPECT_EQ(0,
460                     WebRtcAec_BufferFarend(handle_, far_, samples_per_frame_));
461           // No need to verify system delay, since that is done in a separate
462           // test.
463         }
464         // Verify that we are in a non-causal state, i.e.,
465         // |system_delay| > |device_buf|.
466         EXPECT_LT(device_buf, WebRtcAec_system_delay(self_->aec));
467 
468         // Recover state. Should recover at least 4 ms of data per 10 ms, hence
469         // a glitch of 200 ms will take at most 200 * 10 / 4 = 500 ms to recover
470         // from.
471         bool non_causal = true;  // We are currently in a non-causal state.
472         for (int j = 0; j < 50; j++) {
473           int system_delay_before = WebRtcAec_system_delay(self_->aec);
474           RenderAndCapture(kDeviceBufMs);
475           int system_delay_after = WebRtcAec_system_delay(self_->aec);
476           // We have recovered if
477           // |device_buf| - |system_delay_after| >= PART_LEN (1 block).
478           // During recovery, |system_delay_after| < |system_delay_before|,
479           // otherwise they are equal.
480           if (non_causal) {
481             EXPECT_LT(system_delay_after, system_delay_before);
482             if (device_buf - system_delay_after >= PART_LEN) {
483               non_causal = false;
484             }
485           } else {
486             EXPECT_EQ(system_delay_before, system_delay_after);
487           }
488           // Verify that the system delay is non-negative.
489           EXPECT_LE(0, WebRtcAec_system_delay(self_->aec));
490         }
491         // Check that we have recovered.
492         EXPECT_FALSE(non_causal);
493       }
494     }
495   }
496 }
497 
TEST_F(SystemDelayTest,UnaffectedWhenSpuriousDeviceBufferValues)498 TEST_F(SystemDelayTest, UnaffectedWhenSpuriousDeviceBufferValues) {
499   // This test does not apply in extended_filter mode, since we only use the
500   // the first 10 ms chunk to determine a reasonable buffer size.
501   const int extended_filter = 0;
502   WebRtcAec_enable_extended_filter(self_->aec, extended_filter);
503   EXPECT_EQ(extended_filter, WebRtcAec_extended_filter_enabled(self_->aec));
504 
505   // Should be DA-AEC independent.
506   for (int da_aec = 0; da_aec <= 1; ++da_aec) {
507     WebRtcAec_enable_delay_agnostic(self_->aec, da_aec);
508     EXPECT_EQ(da_aec, WebRtcAec_delay_agnostic_enabled(self_->aec));
509     // This spurious device buffer data test aims at verifying that the system
510     // delay is unaffected by large outliers.
511     // The system is said to be in a non-causal state if the difference between
512     // the device buffer and system delay is less than a block (64 samples).
513     for (size_t i = 0; i < kNumSampleRates; i++) {
514       Init(kSampleRateHz[i]);
515       RunStableStartup();
516       int device_buf = MapBufferSizeToSamples(kDeviceBufMs,
517                                               extended_filter == 1);
518 
519       // Normal state. We are currently not in a non-causal state.
520       bool non_causal = false;
521 
522       // Run 1 s and replace device buffer size with 500 ms every 100 ms.
523       for (int j = 0; j < 100; j++) {
524         int system_delay_before_calls = WebRtcAec_system_delay(self_->aec);
525         int device_buf_ms = j % 10 == 0 ? 500 : kDeviceBufMs;
526         RenderAndCapture(device_buf_ms);
527 
528         // Check for non-causality.
529         if (device_buf - WebRtcAec_system_delay(self_->aec) < PART_LEN) {
530           non_causal = true;
531         }
532         EXPECT_FALSE(non_causal);
533         EXPECT_EQ(system_delay_before_calls,
534                   WebRtcAec_system_delay(self_->aec));
535 
536         // Verify that the system delay is non-negative.
537         EXPECT_LE(0, WebRtcAec_system_delay(self_->aec));
538       }
539     }
540   }
541 }
542 
TEST_F(SystemDelayTest,CorrectImpactWhenTogglingDeviceBufferValues)543 TEST_F(SystemDelayTest, CorrectImpactWhenTogglingDeviceBufferValues) {
544   // This test aims at verifying that the system delay is "unaffected" by
545   // toggling values reported by the device.
546   // The test is constructed such that every other device buffer value is zero
547   // and then 2 * |kDeviceBufMs|, hence the size is constant on the average. The
548   // zero values will force us into a non-causal state and thereby lowering the
549   // system delay until we basically run out of data. Once that happens the
550   // buffer will be stuffed.
551   // TODO(bjornv): This test will have a better impact if we verified that the
552   // delay estimate goes up when the system delay goes down to meet the average
553   // device buffer size.
554 
555   // This test does not apply if DA-AEC is enabled and extended_filter mode
556   // disabled.
557   for (int extended_filter = 0; extended_filter <= 1; ++extended_filter) {
558     WebRtcAec_enable_extended_filter(self_->aec, extended_filter);
559     EXPECT_EQ(extended_filter, WebRtcAec_extended_filter_enabled(self_->aec));
560     for (int da_aec = 0; da_aec <= 1; ++da_aec) {
561       WebRtcAec_enable_delay_agnostic(self_->aec, da_aec);
562       EXPECT_EQ(da_aec, WebRtcAec_delay_agnostic_enabled(self_->aec));
563       if (extended_filter == 0 && da_aec == 1) {
564         continue;
565       }
566       for (size_t i = 0; i < kNumSampleRates; i++) {
567         Init(kSampleRateHz[i]);
568         RunStableStartup();
569         const int device_buf = MapBufferSizeToSamples(kDeviceBufMs,
570                                                       extended_filter == 1);
571 
572         // Normal state. We are currently not in a non-causal state.
573         bool non_causal = false;
574 
575         // Loop through 100 frames (both render and capture), which equals 1 s
576         // of data. Every odd frame we set the device buffer size to
577         // 2 * |kDeviceBufMs| and even frames we set the device buffer size to
578         // zero.
579         for (int j = 0; j < 100; j++) {
580           int system_delay_before_calls = WebRtcAec_system_delay(self_->aec);
581           int device_buf_ms = 2 * (j % 2) * kDeviceBufMs;
582           RenderAndCapture(device_buf_ms);
583 
584           // Check for non-causality, compared with the average device buffer
585           // size.
586           non_causal |= (device_buf - WebRtcAec_system_delay(self_->aec) < 64);
587           EXPECT_GE(system_delay_before_calls,
588                     WebRtcAec_system_delay(self_->aec));
589 
590           // Verify that the system delay is non-negative.
591           EXPECT_LE(0, WebRtcAec_system_delay(self_->aec));
592         }
593         // Verify we are not in a non-causal state.
594         EXPECT_FALSE(non_causal);
595       }
596     }
597   }
598 }
599 
600 }  // namespace
601 }  // namespace webrtc
602