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