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 /* 12 * Contains the API functions for the AEC. 13 */ 14 #include "webrtc/modules/audio_processing/aec/include/echo_cancellation.h" 15 16 #include <math.h> 17 #ifdef WEBRTC_AEC_DEBUG_DUMP 18 #include <stdio.h> 19 #endif 20 #include <stdlib.h> 21 #include <string.h> 22 23 #include "webrtc/common_audio/signal_processing/include/signal_processing_library.h" 24 #include "webrtc/modules/audio_processing/aec/aec_core.h" 25 #include "webrtc/modules/audio_processing/aec/aec_resampler.h" 26 #include "webrtc/modules/audio_processing/aec/echo_cancellation_internal.h" 27 #include "webrtc/modules/audio_processing/utility/ring_buffer.h" 28 #include "webrtc/typedefs.h" 29 30 // Measured delays [ms] 31 // Device Chrome GTP 32 // MacBook Air 10 33 // MacBook Retina 10 100 34 // MacPro 30? 35 // 36 // Win7 Desktop 70 80? 37 // Win7 T430s 110 38 // Win8 T420s 70 39 // 40 // Daisy 50 41 // Pixel (w/ preproc?) 240 42 // Pixel (w/o preproc?) 110 110 43 44 // The extended filter mode gives us the flexibility to ignore the system's 45 // reported delays. We do this for platforms which we believe provide results 46 // which are incompatible with the AEC's expectations. Based on measurements 47 // (some provided above) we set a conservative (i.e. lower than measured) 48 // fixed delay. 49 // 50 // WEBRTC_UNTRUSTED_DELAY will only have an impact when |extended_filter_mode| 51 // is enabled. See the note along with |DelayCorrection| in 52 // echo_cancellation_impl.h for more details on the mode. 53 // 54 // Justification: 55 // Chromium/Mac: Here, the true latency is so low (~10-20 ms), that it plays 56 // havoc with the AEC's buffering. To avoid this, we set a fixed delay of 20 ms 57 // and then compensate by rewinding by 10 ms (in wideband) through 58 // kDelayDiffOffsetSamples. This trick does not seem to work for larger rewind 59 // values, but fortunately this is sufficient. 60 // 61 // Chromium/Linux(ChromeOS): The values we get on this platform don't correspond 62 // well to reality. The variance doesn't match the AEC's buffer changes, and the 63 // bulk values tend to be too low. However, the range across different hardware 64 // appears to be too large to choose a single value. 65 // 66 // GTP/Linux(ChromeOS): TBD, but for the moment we will trust the values. 67 #if defined(WEBRTC_CHROMIUM_BUILD) && defined(WEBRTC_MAC) 68 #define WEBRTC_UNTRUSTED_DELAY 69 #endif 70 71 #if defined(WEBRTC_UNTRUSTED_DELAY) && defined(WEBRTC_MAC) 72 static const int kDelayDiffOffsetSamples = -160; 73 #else 74 // Not enabled for now. 75 static const int kDelayDiffOffsetSamples = 0; 76 #endif 77 78 #if defined(WEBRTC_MAC) 79 static const int kFixedDelayMs = 20; 80 #else 81 static const int kFixedDelayMs = 50; 82 #endif 83 #if !defined(WEBRTC_UNTRUSTED_DELAY) 84 static const int kMinTrustedDelayMs = 20; 85 #endif 86 static const int kMaxTrustedDelayMs = 500; 87 88 // Maximum length of resampled signal. Must be an integer multiple of frames 89 // (ceil(1/(1 + MIN_SKEW)*2) + 1)*FRAME_LEN 90 // The factor of 2 handles wb, and the + 1 is as a safety margin 91 // TODO(bjornv): Replace with kResamplerBufferSize 92 #define MAX_RESAMP_LEN (5 * FRAME_LEN) 93 94 static const int kMaxBufSizeStart = 62; // In partitions 95 static const int sampMsNb = 8; // samples per ms in nb 96 static const int initCheck = 42; 97 98 #ifdef WEBRTC_AEC_DEBUG_DUMP 99 int webrtc_aec_instance_count = 0; 100 #endif 101 102 // Estimates delay to set the position of the far-end buffer read pointer 103 // (controlled by knownDelay) 104 static void EstBufDelayNormal(aecpc_t* aecInst); 105 static void EstBufDelayExtended(aecpc_t* aecInst); 106 static int ProcessNormal(aecpc_t* self, 107 const float* near, 108 const float* near_high, 109 float* out, 110 float* out_high, 111 int16_t num_samples, 112 int16_t reported_delay_ms, 113 int32_t skew); 114 static void ProcessExtended(aecpc_t* self, 115 const float* near, 116 const float* near_high, 117 float* out, 118 float* out_high, 119 int16_t num_samples, 120 int16_t reported_delay_ms, 121 int32_t skew); 122 123 int32_t WebRtcAec_Create(void** aecInst) { 124 aecpc_t* aecpc; 125 if (aecInst == NULL) { 126 return -1; 127 } 128 129 aecpc = malloc(sizeof(aecpc_t)); 130 *aecInst = aecpc; 131 if (aecpc == NULL) { 132 return -1; 133 } 134 135 if (WebRtcAec_CreateAec(&aecpc->aec) == -1) { 136 WebRtcAec_Free(aecpc); 137 aecpc = NULL; 138 return -1; 139 } 140 141 if (WebRtcAec_CreateResampler(&aecpc->resampler) == -1) { 142 WebRtcAec_Free(aecpc); 143 aecpc = NULL; 144 return -1; 145 } 146 // Create far-end pre-buffer. The buffer size has to be large enough for 147 // largest possible drift compensation (kResamplerBufferSize) + "almost" an 148 // FFT buffer (PART_LEN2 - 1). 149 aecpc->far_pre_buf = 150 WebRtc_CreateBuffer(PART_LEN2 + kResamplerBufferSize, sizeof(float)); 151 if (!aecpc->far_pre_buf) { 152 WebRtcAec_Free(aecpc); 153 aecpc = NULL; 154 return -1; 155 } 156 157 aecpc->initFlag = 0; 158 aecpc->lastError = 0; 159 160 #ifdef WEBRTC_AEC_DEBUG_DUMP 161 { 162 char filename[64]; 163 sprintf(filename, "aec_buf%d.dat", webrtc_aec_instance_count); 164 aecpc->bufFile = fopen(filename, "wb"); 165 sprintf(filename, "aec_skew%d.dat", webrtc_aec_instance_count); 166 aecpc->skewFile = fopen(filename, "wb"); 167 sprintf(filename, "aec_delay%d.dat", webrtc_aec_instance_count); 168 aecpc->delayFile = fopen(filename, "wb"); 169 webrtc_aec_instance_count++; 170 } 171 #endif 172 173 return 0; 174 } 175 176 int32_t WebRtcAec_Free(void* aecInst) { 177 aecpc_t* aecpc = aecInst; 178 179 if (aecpc == NULL) { 180 return -1; 181 } 182 183 WebRtc_FreeBuffer(aecpc->far_pre_buf); 184 185 #ifdef WEBRTC_AEC_DEBUG_DUMP 186 fclose(aecpc->bufFile); 187 fclose(aecpc->skewFile); 188 fclose(aecpc->delayFile); 189 #endif 190 191 WebRtcAec_FreeAec(aecpc->aec); 192 WebRtcAec_FreeResampler(aecpc->resampler); 193 free(aecpc); 194 195 return 0; 196 } 197 198 int32_t WebRtcAec_Init(void* aecInst, int32_t sampFreq, int32_t scSampFreq) { 199 aecpc_t* aecpc = aecInst; 200 AecConfig aecConfig; 201 202 if (sampFreq != 8000 && sampFreq != 16000 && sampFreq != 32000) { 203 aecpc->lastError = AEC_BAD_PARAMETER_ERROR; 204 return -1; 205 } 206 aecpc->sampFreq = sampFreq; 207 208 if (scSampFreq < 1 || scSampFreq > 96000) { 209 aecpc->lastError = AEC_BAD_PARAMETER_ERROR; 210 return -1; 211 } 212 aecpc->scSampFreq = scSampFreq; 213 214 // Initialize echo canceller core 215 if (WebRtcAec_InitAec(aecpc->aec, aecpc->sampFreq) == -1) { 216 aecpc->lastError = AEC_UNSPECIFIED_ERROR; 217 return -1; 218 } 219 220 if (WebRtcAec_InitResampler(aecpc->resampler, aecpc->scSampFreq) == -1) { 221 aecpc->lastError = AEC_UNSPECIFIED_ERROR; 222 return -1; 223 } 224 225 if (WebRtc_InitBuffer(aecpc->far_pre_buf) == -1) { 226 aecpc->lastError = AEC_UNSPECIFIED_ERROR; 227 return -1; 228 } 229 WebRtc_MoveReadPtr(aecpc->far_pre_buf, -PART_LEN); // Start overlap. 230 231 aecpc->initFlag = initCheck; // indicates that initialization has been done 232 233 if (aecpc->sampFreq == 32000) { 234 aecpc->splitSampFreq = 16000; 235 } else { 236 aecpc->splitSampFreq = sampFreq; 237 } 238 239 aecpc->delayCtr = 0; 240 aecpc->sampFactor = (aecpc->scSampFreq * 1.0f) / aecpc->splitSampFreq; 241 // Sampling frequency multiplier (SWB is processed as 160 frame size). 242 aecpc->rate_factor = aecpc->splitSampFreq / 8000; 243 244 aecpc->sum = 0; 245 aecpc->counter = 0; 246 aecpc->checkBuffSize = 1; 247 aecpc->firstVal = 0; 248 249 aecpc->startup_phase = WebRtcAec_reported_delay_enabled(aecpc->aec); 250 aecpc->bufSizeStart = 0; 251 aecpc->checkBufSizeCtr = 0; 252 aecpc->msInSndCardBuf = 0; 253 aecpc->filtDelay = -1; // -1 indicates an initialized state. 254 aecpc->timeForDelayChange = 0; 255 aecpc->knownDelay = 0; 256 aecpc->lastDelayDiff = 0; 257 258 aecpc->skewFrCtr = 0; 259 aecpc->resample = kAecFalse; 260 aecpc->highSkewCtr = 0; 261 aecpc->skew = 0; 262 263 aecpc->farend_started = 0; 264 265 // Default settings. 266 aecConfig.nlpMode = kAecNlpModerate; 267 aecConfig.skewMode = kAecFalse; 268 aecConfig.metricsMode = kAecFalse; 269 aecConfig.delay_logging = kAecFalse; 270 271 if (WebRtcAec_set_config(aecpc, aecConfig) == -1) { 272 aecpc->lastError = AEC_UNSPECIFIED_ERROR; 273 return -1; 274 } 275 276 return 0; 277 } 278 279 // only buffer L band for farend 280 int32_t WebRtcAec_BufferFarend(void* aecInst, 281 const float* farend, 282 int16_t nrOfSamples) { 283 aecpc_t* aecpc = aecInst; 284 int newNrOfSamples = (int)nrOfSamples; 285 float new_farend[MAX_RESAMP_LEN]; 286 const float* farend_ptr = farend; 287 288 if (farend == NULL) { 289 aecpc->lastError = AEC_NULL_POINTER_ERROR; 290 return -1; 291 } 292 293 if (aecpc->initFlag != initCheck) { 294 aecpc->lastError = AEC_UNINITIALIZED_ERROR; 295 return -1; 296 } 297 298 // number of samples == 160 for SWB input 299 if (nrOfSamples != 80 && nrOfSamples != 160) { 300 aecpc->lastError = AEC_BAD_PARAMETER_ERROR; 301 return -1; 302 } 303 304 if (aecpc->skewMode == kAecTrue && aecpc->resample == kAecTrue) { 305 // Resample and get a new number of samples 306 WebRtcAec_ResampleLinear(aecpc->resampler, 307 farend, 308 nrOfSamples, 309 aecpc->skew, 310 new_farend, 311 &newNrOfSamples); 312 farend_ptr = new_farend; 313 } 314 315 aecpc->farend_started = 1; 316 WebRtcAec_SetSystemDelay(aecpc->aec, 317 WebRtcAec_system_delay(aecpc->aec) + newNrOfSamples); 318 319 // Write the time-domain data to |far_pre_buf|. 320 WebRtc_WriteBuffer(aecpc->far_pre_buf, farend_ptr, (size_t)newNrOfSamples); 321 322 // Transform to frequency domain if we have enough data. 323 while (WebRtc_available_read(aecpc->far_pre_buf) >= PART_LEN2) { 324 // We have enough data to pass to the FFT, hence read PART_LEN2 samples. 325 { 326 float* ptmp; 327 float tmp[PART_LEN2]; 328 WebRtc_ReadBuffer(aecpc->far_pre_buf, (void**)&ptmp, tmp, PART_LEN2); 329 WebRtcAec_BufferFarendPartition(aecpc->aec, ptmp); 330 #ifdef WEBRTC_AEC_DEBUG_DUMP 331 WebRtc_WriteBuffer( 332 WebRtcAec_far_time_buf(aecpc->aec), &ptmp[PART_LEN], 1); 333 #endif 334 } 335 336 // Rewind |far_pre_buf| PART_LEN samples for overlap before continuing. 337 WebRtc_MoveReadPtr(aecpc->far_pre_buf, -PART_LEN); 338 } 339 340 return 0; 341 } 342 343 int32_t WebRtcAec_Process(void* aecInst, 344 const float* nearend, 345 const float* nearendH, 346 float* out, 347 float* outH, 348 int16_t nrOfSamples, 349 int16_t msInSndCardBuf, 350 int32_t skew) { 351 aecpc_t* aecpc = aecInst; 352 int32_t retVal = 0; 353 if (nearend == NULL) { 354 aecpc->lastError = AEC_NULL_POINTER_ERROR; 355 return -1; 356 } 357 358 if (out == NULL) { 359 aecpc->lastError = AEC_NULL_POINTER_ERROR; 360 return -1; 361 } 362 363 if (aecpc->initFlag != initCheck) { 364 aecpc->lastError = AEC_UNINITIALIZED_ERROR; 365 return -1; 366 } 367 368 // number of samples == 160 for SWB input 369 if (nrOfSamples != 80 && nrOfSamples != 160) { 370 aecpc->lastError = AEC_BAD_PARAMETER_ERROR; 371 return -1; 372 } 373 374 // Check for valid pointers based on sampling rate 375 if (aecpc->sampFreq == 32000 && nearendH == NULL) { 376 aecpc->lastError = AEC_NULL_POINTER_ERROR; 377 return -1; 378 } 379 380 if (msInSndCardBuf < 0) { 381 msInSndCardBuf = 0; 382 aecpc->lastError = AEC_BAD_PARAMETER_WARNING; 383 retVal = -1; 384 } else if (msInSndCardBuf > kMaxTrustedDelayMs) { 385 // The clamping is now done in ProcessExtended/Normal(). 386 aecpc->lastError = AEC_BAD_PARAMETER_WARNING; 387 retVal = -1; 388 } 389 390 // This returns the value of aec->extended_filter_enabled. 391 if (WebRtcAec_delay_correction_enabled(aecpc->aec)) { 392 ProcessExtended( 393 aecpc, nearend, nearendH, out, outH, nrOfSamples, msInSndCardBuf, skew); 394 } else { 395 if (ProcessNormal(aecpc, 396 nearend, 397 nearendH, 398 out, 399 outH, 400 nrOfSamples, 401 msInSndCardBuf, 402 skew) != 0) { 403 retVal = -1; 404 } 405 } 406 407 #ifdef WEBRTC_AEC_DEBUG_DUMP 408 { 409 int16_t far_buf_size_ms = (int16_t)(WebRtcAec_system_delay(aecpc->aec) / 410 (sampMsNb * aecpc->rate_factor)); 411 (void)fwrite(&far_buf_size_ms, 2, 1, aecpc->bufFile); 412 (void)fwrite( 413 &aecpc->knownDelay, sizeof(aecpc->knownDelay), 1, aecpc->delayFile); 414 } 415 #endif 416 417 return retVal; 418 } 419 420 int WebRtcAec_set_config(void* handle, AecConfig config) { 421 aecpc_t* self = (aecpc_t*)handle; 422 if (self->initFlag != initCheck) { 423 self->lastError = AEC_UNINITIALIZED_ERROR; 424 return -1; 425 } 426 427 if (config.skewMode != kAecFalse && config.skewMode != kAecTrue) { 428 self->lastError = AEC_BAD_PARAMETER_ERROR; 429 return -1; 430 } 431 self->skewMode = config.skewMode; 432 433 if (config.nlpMode != kAecNlpConservative && 434 config.nlpMode != kAecNlpModerate && 435 config.nlpMode != kAecNlpAggressive) { 436 self->lastError = AEC_BAD_PARAMETER_ERROR; 437 return -1; 438 } 439 440 if (config.metricsMode != kAecFalse && config.metricsMode != kAecTrue) { 441 self->lastError = AEC_BAD_PARAMETER_ERROR; 442 return -1; 443 } 444 445 if (config.delay_logging != kAecFalse && config.delay_logging != kAecTrue) { 446 self->lastError = AEC_BAD_PARAMETER_ERROR; 447 return -1; 448 } 449 450 WebRtcAec_SetConfigCore( 451 self->aec, config.nlpMode, config.metricsMode, config.delay_logging); 452 return 0; 453 } 454 455 int WebRtcAec_get_echo_status(void* handle, int* status) { 456 aecpc_t* self = (aecpc_t*)handle; 457 if (status == NULL) { 458 self->lastError = AEC_NULL_POINTER_ERROR; 459 return -1; 460 } 461 if (self->initFlag != initCheck) { 462 self->lastError = AEC_UNINITIALIZED_ERROR; 463 return -1; 464 } 465 466 *status = WebRtcAec_echo_state(self->aec); 467 468 return 0; 469 } 470 471 int WebRtcAec_GetMetrics(void* handle, AecMetrics* metrics) { 472 const float kUpWeight = 0.7f; 473 float dtmp; 474 int stmp; 475 aecpc_t* self = (aecpc_t*)handle; 476 Stats erl; 477 Stats erle; 478 Stats a_nlp; 479 480 if (handle == NULL) { 481 return -1; 482 } 483 if (metrics == NULL) { 484 self->lastError = AEC_NULL_POINTER_ERROR; 485 return -1; 486 } 487 if (self->initFlag != initCheck) { 488 self->lastError = AEC_UNINITIALIZED_ERROR; 489 return -1; 490 } 491 492 WebRtcAec_GetEchoStats(self->aec, &erl, &erle, &a_nlp); 493 494 // ERL 495 metrics->erl.instant = (int)erl.instant; 496 497 if ((erl.himean > kOffsetLevel) && (erl.average > kOffsetLevel)) { 498 // Use a mix between regular average and upper part average. 499 dtmp = kUpWeight * erl.himean + (1 - kUpWeight) * erl.average; 500 metrics->erl.average = (int)dtmp; 501 } else { 502 metrics->erl.average = kOffsetLevel; 503 } 504 505 metrics->erl.max = (int)erl.max; 506 507 if (erl.min < (kOffsetLevel * (-1))) { 508 metrics->erl.min = (int)erl.min; 509 } else { 510 metrics->erl.min = kOffsetLevel; 511 } 512 513 // ERLE 514 metrics->erle.instant = (int)erle.instant; 515 516 if ((erle.himean > kOffsetLevel) && (erle.average > kOffsetLevel)) { 517 // Use a mix between regular average and upper part average. 518 dtmp = kUpWeight * erle.himean + (1 - kUpWeight) * erle.average; 519 metrics->erle.average = (int)dtmp; 520 } else { 521 metrics->erle.average = kOffsetLevel; 522 } 523 524 metrics->erle.max = (int)erle.max; 525 526 if (erle.min < (kOffsetLevel * (-1))) { 527 metrics->erle.min = (int)erle.min; 528 } else { 529 metrics->erle.min = kOffsetLevel; 530 } 531 532 // RERL 533 if ((metrics->erl.average > kOffsetLevel) && 534 (metrics->erle.average > kOffsetLevel)) { 535 stmp = metrics->erl.average + metrics->erle.average; 536 } else { 537 stmp = kOffsetLevel; 538 } 539 metrics->rerl.average = stmp; 540 541 // No other statistics needed, but returned for completeness. 542 metrics->rerl.instant = stmp; 543 metrics->rerl.max = stmp; 544 metrics->rerl.min = stmp; 545 546 // A_NLP 547 metrics->aNlp.instant = (int)a_nlp.instant; 548 549 if ((a_nlp.himean > kOffsetLevel) && (a_nlp.average > kOffsetLevel)) { 550 // Use a mix between regular average and upper part average. 551 dtmp = kUpWeight * a_nlp.himean + (1 - kUpWeight) * a_nlp.average; 552 metrics->aNlp.average = (int)dtmp; 553 } else { 554 metrics->aNlp.average = kOffsetLevel; 555 } 556 557 metrics->aNlp.max = (int)a_nlp.max; 558 559 if (a_nlp.min < (kOffsetLevel * (-1))) { 560 metrics->aNlp.min = (int)a_nlp.min; 561 } else { 562 metrics->aNlp.min = kOffsetLevel; 563 } 564 565 return 0; 566 } 567 568 int WebRtcAec_GetDelayMetrics(void* handle, int* median, int* std) { 569 aecpc_t* self = handle; 570 if (median == NULL) { 571 self->lastError = AEC_NULL_POINTER_ERROR; 572 return -1; 573 } 574 if (std == NULL) { 575 self->lastError = AEC_NULL_POINTER_ERROR; 576 return -1; 577 } 578 if (self->initFlag != initCheck) { 579 self->lastError = AEC_UNINITIALIZED_ERROR; 580 return -1; 581 } 582 if (WebRtcAec_GetDelayMetricsCore(self->aec, median, std) == -1) { 583 // Logging disabled. 584 self->lastError = AEC_UNSUPPORTED_FUNCTION_ERROR; 585 return -1; 586 } 587 588 return 0; 589 } 590 591 int32_t WebRtcAec_get_error_code(void* aecInst) { 592 aecpc_t* aecpc = aecInst; 593 return aecpc->lastError; 594 } 595 596 AecCore* WebRtcAec_aec_core(void* handle) { 597 if (!handle) { 598 return NULL; 599 } 600 return ((aecpc_t*)handle)->aec; 601 } 602 603 static int ProcessNormal(aecpc_t* aecpc, 604 const float* nearend, 605 const float* nearendH, 606 float* out, 607 float* outH, 608 int16_t nrOfSamples, 609 int16_t msInSndCardBuf, 610 int32_t skew) { 611 int retVal = 0; 612 short i; 613 short nBlocks10ms; 614 short nFrames; 615 // Limit resampling to doubling/halving of signal 616 const float minSkewEst = -0.5f; 617 const float maxSkewEst = 1.0f; 618 619 msInSndCardBuf = 620 msInSndCardBuf > kMaxTrustedDelayMs ? kMaxTrustedDelayMs : msInSndCardBuf; 621 // TODO(andrew): we need to investigate if this +10 is really wanted. 622 msInSndCardBuf += 10; 623 aecpc->msInSndCardBuf = msInSndCardBuf; 624 625 if (aecpc->skewMode == kAecTrue) { 626 if (aecpc->skewFrCtr < 25) { 627 aecpc->skewFrCtr++; 628 } else { 629 retVal = WebRtcAec_GetSkew(aecpc->resampler, skew, &aecpc->skew); 630 if (retVal == -1) { 631 aecpc->skew = 0; 632 aecpc->lastError = AEC_BAD_PARAMETER_WARNING; 633 } 634 635 aecpc->skew /= aecpc->sampFactor * nrOfSamples; 636 637 if (aecpc->skew < 1.0e-3 && aecpc->skew > -1.0e-3) { 638 aecpc->resample = kAecFalse; 639 } else { 640 aecpc->resample = kAecTrue; 641 } 642 643 if (aecpc->skew < minSkewEst) { 644 aecpc->skew = minSkewEst; 645 } else if (aecpc->skew > maxSkewEst) { 646 aecpc->skew = maxSkewEst; 647 } 648 649 #ifdef WEBRTC_AEC_DEBUG_DUMP 650 (void)fwrite(&aecpc->skew, sizeof(aecpc->skew), 1, aecpc->skewFile); 651 #endif 652 } 653 } 654 655 nFrames = nrOfSamples / FRAME_LEN; 656 nBlocks10ms = nFrames / aecpc->rate_factor; 657 658 if (aecpc->startup_phase) { 659 // Only needed if they don't already point to the same place. 660 if (nearend != out) { 661 memcpy(out, nearend, sizeof(*out) * nrOfSamples); 662 } 663 if (nearendH != outH) { 664 memcpy(outH, nearendH, sizeof(*outH) * nrOfSamples); 665 } 666 667 // The AEC is in the start up mode 668 // AEC is disabled until the system delay is OK 669 670 // Mechanism to ensure that the system delay is reasonably stable. 671 if (aecpc->checkBuffSize) { 672 aecpc->checkBufSizeCtr++; 673 // Before we fill up the far-end buffer we require the system delay 674 // to be stable (+/-8 ms) compared to the first value. This 675 // comparison is made during the following 6 consecutive 10 ms 676 // blocks. If it seems to be stable then we start to fill up the 677 // far-end buffer. 678 if (aecpc->counter == 0) { 679 aecpc->firstVal = aecpc->msInSndCardBuf; 680 aecpc->sum = 0; 681 } 682 683 if (abs(aecpc->firstVal - aecpc->msInSndCardBuf) < 684 WEBRTC_SPL_MAX(0.2 * aecpc->msInSndCardBuf, sampMsNb)) { 685 aecpc->sum += aecpc->msInSndCardBuf; 686 aecpc->counter++; 687 } else { 688 aecpc->counter = 0; 689 } 690 691 if (aecpc->counter * nBlocks10ms >= 6) { 692 // The far-end buffer size is determined in partitions of 693 // PART_LEN samples. Use 75% of the average value of the system 694 // delay as buffer size to start with. 695 aecpc->bufSizeStart = 696 WEBRTC_SPL_MIN((3 * aecpc->sum * aecpc->rate_factor * 8) / 697 (4 * aecpc->counter * PART_LEN), 698 kMaxBufSizeStart); 699 // Buffer size has now been determined. 700 aecpc->checkBuffSize = 0; 701 } 702 703 if (aecpc->checkBufSizeCtr * nBlocks10ms > 50) { 704 // For really bad systems, don't disable the echo canceller for 705 // more than 0.5 sec. 706 aecpc->bufSizeStart = WEBRTC_SPL_MIN( 707 (aecpc->msInSndCardBuf * aecpc->rate_factor * 3) / 40, 708 kMaxBufSizeStart); 709 aecpc->checkBuffSize = 0; 710 } 711 } 712 713 // If |checkBuffSize| changed in the if-statement above. 714 if (!aecpc->checkBuffSize) { 715 // The system delay is now reasonably stable (or has been unstable 716 // for too long). When the far-end buffer is filled with 717 // approximately the same amount of data as reported by the system 718 // we end the startup phase. 719 int overhead_elements = 720 WebRtcAec_system_delay(aecpc->aec) / PART_LEN - aecpc->bufSizeStart; 721 if (overhead_elements == 0) { 722 // Enable the AEC 723 aecpc->startup_phase = 0; 724 } else if (overhead_elements > 0) { 725 // TODO(bjornv): Do we need a check on how much we actually 726 // moved the read pointer? It should always be possible to move 727 // the pointer |overhead_elements| since we have only added data 728 // to the buffer and no delay compensation nor AEC processing 729 // has been done. 730 WebRtcAec_MoveFarReadPtr(aecpc->aec, overhead_elements); 731 732 // Enable the AEC 733 aecpc->startup_phase = 0; 734 } 735 } 736 } else { 737 // AEC is enabled. 738 if (WebRtcAec_reported_delay_enabled(aecpc->aec)) { 739 EstBufDelayNormal(aecpc); 740 } 741 742 // Note that 1 frame is supported for NB and 2 frames for WB. 743 for (i = 0; i < nFrames; i++) { 744 // Call the AEC. 745 WebRtcAec_ProcessFrame(aecpc->aec, 746 &nearend[FRAME_LEN * i], 747 &nearendH[FRAME_LEN * i], 748 aecpc->knownDelay, 749 &out[FRAME_LEN * i], 750 &outH[FRAME_LEN * i]); 751 // TODO(bjornv): Re-structure such that we don't have to pass 752 // |aecpc->knownDelay| as input. Change name to something like 753 // |system_buffer_diff|. 754 } 755 } 756 757 return retVal; 758 } 759 760 static void ProcessExtended(aecpc_t* self, 761 const float* near, 762 const float* near_high, 763 float* out, 764 float* out_high, 765 int16_t num_samples, 766 int16_t reported_delay_ms, 767 int32_t skew) { 768 int i; 769 const int num_frames = num_samples / FRAME_LEN; 770 const int delay_diff_offset = kDelayDiffOffsetSamples; 771 #if defined(WEBRTC_UNTRUSTED_DELAY) 772 reported_delay_ms = kFixedDelayMs; 773 #else 774 // This is the usual mode where we trust the reported system delay values. 775 // Due to the longer filter, we no longer add 10 ms to the reported delay 776 // to reduce chance of non-causality. Instead we apply a minimum here to avoid 777 // issues with the read pointer jumping around needlessly. 778 reported_delay_ms = reported_delay_ms < kMinTrustedDelayMs 779 ? kMinTrustedDelayMs 780 : reported_delay_ms; 781 // If the reported delay appears to be bogus, we attempt to recover by using 782 // the measured fixed delay values. We use >= here because higher layers 783 // may already clamp to this maximum value, and we would otherwise not 784 // detect it here. 785 reported_delay_ms = reported_delay_ms >= kMaxTrustedDelayMs 786 ? kFixedDelayMs 787 : reported_delay_ms; 788 #endif 789 self->msInSndCardBuf = reported_delay_ms; 790 791 if (!self->farend_started) { 792 // Only needed if they don't already point to the same place. 793 if (near != out) { 794 memcpy(out, near, sizeof(*out) * num_samples); 795 } 796 if (near_high != out_high) { 797 memcpy(out_high, near_high, sizeof(*out_high) * num_samples); 798 } 799 return; 800 } 801 if (self->startup_phase) { 802 // In the extended mode, there isn't a startup "phase", just a special 803 // action on the first frame. In the trusted delay case, we'll take the 804 // current reported delay, unless it's less then our conservative 805 // measurement. 806 int startup_size_ms = 807 reported_delay_ms < kFixedDelayMs ? kFixedDelayMs : reported_delay_ms; 808 int overhead_elements = (WebRtcAec_system_delay(self->aec) - 809 startup_size_ms / 2 * self->rate_factor * 8) / 810 PART_LEN; 811 WebRtcAec_MoveFarReadPtr(self->aec, overhead_elements); 812 self->startup_phase = 0; 813 } 814 815 if (WebRtcAec_reported_delay_enabled(self->aec)) { 816 EstBufDelayExtended(self); 817 } 818 819 { 820 // |delay_diff_offset| gives us the option to manually rewind the delay on 821 // very low delay platforms which can't be expressed purely through 822 // |reported_delay_ms|. 823 const int adjusted_known_delay = 824 WEBRTC_SPL_MAX(0, self->knownDelay + delay_diff_offset); 825 826 for (i = 0; i < num_frames; ++i) { 827 WebRtcAec_ProcessFrame(self->aec, 828 &near[FRAME_LEN * i], 829 &near_high[FRAME_LEN * i], 830 adjusted_known_delay, 831 &out[FRAME_LEN * i], 832 &out_high[FRAME_LEN * i]); 833 } 834 } 835 } 836 837 static void EstBufDelayNormal(aecpc_t* aecpc) { 838 int nSampSndCard = aecpc->msInSndCardBuf * sampMsNb * aecpc->rate_factor; 839 int current_delay = nSampSndCard - WebRtcAec_system_delay(aecpc->aec); 840 int delay_difference = 0; 841 842 // Before we proceed with the delay estimate filtering we: 843 // 1) Compensate for the frame that will be read. 844 // 2) Compensate for drift resampling. 845 // 3) Compensate for non-causality if needed, since the estimated delay can't 846 // be negative. 847 848 // 1) Compensating for the frame(s) that will be read/processed. 849 current_delay += FRAME_LEN * aecpc->rate_factor; 850 851 // 2) Account for resampling frame delay. 852 if (aecpc->skewMode == kAecTrue && aecpc->resample == kAecTrue) { 853 current_delay -= kResamplingDelay; 854 } 855 856 // 3) Compensate for non-causality, if needed, by flushing one block. 857 if (current_delay < PART_LEN) { 858 current_delay += WebRtcAec_MoveFarReadPtr(aecpc->aec, 1) * PART_LEN; 859 } 860 861 // We use -1 to signal an initialized state in the "extended" implementation; 862 // compensate for that. 863 aecpc->filtDelay = aecpc->filtDelay < 0 ? 0 : aecpc->filtDelay; 864 aecpc->filtDelay = 865 WEBRTC_SPL_MAX(0, (short)(0.8 * aecpc->filtDelay + 0.2 * current_delay)); 866 867 delay_difference = aecpc->filtDelay - aecpc->knownDelay; 868 if (delay_difference > 224) { 869 if (aecpc->lastDelayDiff < 96) { 870 aecpc->timeForDelayChange = 0; 871 } else { 872 aecpc->timeForDelayChange++; 873 } 874 } else if (delay_difference < 96 && aecpc->knownDelay > 0) { 875 if (aecpc->lastDelayDiff > 224) { 876 aecpc->timeForDelayChange = 0; 877 } else { 878 aecpc->timeForDelayChange++; 879 } 880 } else { 881 aecpc->timeForDelayChange = 0; 882 } 883 aecpc->lastDelayDiff = delay_difference; 884 885 if (aecpc->timeForDelayChange > 25) { 886 aecpc->knownDelay = WEBRTC_SPL_MAX((int)aecpc->filtDelay - 160, 0); 887 } 888 } 889 890 static void EstBufDelayExtended(aecpc_t* self) { 891 int reported_delay = self->msInSndCardBuf * sampMsNb * self->rate_factor; 892 int current_delay = reported_delay - WebRtcAec_system_delay(self->aec); 893 int delay_difference = 0; 894 895 // Before we proceed with the delay estimate filtering we: 896 // 1) Compensate for the frame that will be read. 897 // 2) Compensate for drift resampling. 898 // 3) Compensate for non-causality if needed, since the estimated delay can't 899 // be negative. 900 901 // 1) Compensating for the frame(s) that will be read/processed. 902 current_delay += FRAME_LEN * self->rate_factor; 903 904 // 2) Account for resampling frame delay. 905 if (self->skewMode == kAecTrue && self->resample == kAecTrue) { 906 current_delay -= kResamplingDelay; 907 } 908 909 // 3) Compensate for non-causality, if needed, by flushing two blocks. 910 if (current_delay < PART_LEN) { 911 current_delay += WebRtcAec_MoveFarReadPtr(self->aec, 2) * PART_LEN; 912 } 913 914 if (self->filtDelay == -1) { 915 self->filtDelay = WEBRTC_SPL_MAX(0, 0.5 * current_delay); 916 } else { 917 self->filtDelay = WEBRTC_SPL_MAX( 918 0, (short)(0.95 * self->filtDelay + 0.05 * current_delay)); 919 } 920 921 delay_difference = self->filtDelay - self->knownDelay; 922 if (delay_difference > 384) { 923 if (self->lastDelayDiff < 128) { 924 self->timeForDelayChange = 0; 925 } else { 926 self->timeForDelayChange++; 927 } 928 } else if (delay_difference < 128 && self->knownDelay > 0) { 929 if (self->lastDelayDiff > 384) { 930 self->timeForDelayChange = 0; 931 } else { 932 self->timeForDelayChange++; 933 } 934 } else { 935 self->timeForDelayChange = 0; 936 } 937 self->lastDelayDiff = delay_difference; 938 939 if (self->timeForDelayChange > 25) { 940 self->knownDelay = WEBRTC_SPL_MAX((int)self->filtDelay - 256, 0); 941 } 942 } 943