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