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