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