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 /*
     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