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