1 /*
2 * Copyright (c) 2011 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 "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 "aec_core.h"
24 #include "aec_resampler.h"
25 #include "ring_buffer.h"
26 #include "typedefs.h"
27
28 // Maximum length of resampled signal. Must be an integer multiple of frames
29 // (ceil(1/(1 + MIN_SKEW)*2) + 1)*FRAME_LEN
30 // The factor of 2 handles wb, and the + 1 is as a safety margin
31 // TODO(bjornv): Replace with kResamplerBufferSize
32 #define MAX_RESAMP_LEN (5 * FRAME_LEN)
33
34 static const int kMaxBufSizeStart = 62; // In partitions
35 static const int sampMsNb = 8; // samples per ms in nb
36 // Target suppression levels for nlp modes
37 // log{0.001, 0.00001, 0.00000001}
38 static const float targetSupp[3] = {-6.9f, -11.5f, -18.4f};
39 static const float minOverDrive[3] = {1.0f, 2.0f, 5.0f};
40 static const int initCheck = 42;
41
42 #ifdef WEBRTC_AEC_DEBUG_DUMP
43 static int instance_count = 0;
44 #endif
45
46 typedef struct {
47 int delayCtr;
48 int sampFreq;
49 int splitSampFreq;
50 int scSampFreq;
51 float sampFactor; // scSampRate / sampFreq
52 short nlpMode;
53 short autoOnOff;
54 short activity;
55 short skewMode;
56 int bufSizeStart;
57 //short bufResetCtr; // counts number of noncausal frames
58 int knownDelay;
59
60 short initFlag; // indicates if AEC has been initialized
61
62 // Variables used for averaging far end buffer size
63 short counter;
64 int sum;
65 short firstVal;
66 short checkBufSizeCtr;
67
68 // Variables used for delay shifts
69 short msInSndCardBuf;
70 short filtDelay; // Filtered delay estimate.
71 int timeForDelayChange;
72 int ECstartup;
73 int checkBuffSize;
74 short lastDelayDiff;
75
76 #ifdef WEBRTC_AEC_DEBUG_DUMP
77 void* far_pre_buf_s16; // Time domain far-end pre-buffer in int16_t.
78 FILE *bufFile;
79 FILE *delayFile;
80 FILE *skewFile;
81 #endif
82
83 // Structures
84 void *resampler;
85
86 int skewFrCtr;
87 int resample; // if the skew is small enough we don't resample
88 int highSkewCtr;
89 float skew;
90
91 void* far_pre_buf; // Time domain far-end pre-buffer.
92
93 int lastError;
94
95 aec_t *aec;
96 } aecpc_t;
97
98 // Estimates delay to set the position of the far-end buffer read pointer
99 // (controlled by knownDelay)
100 static int EstBufDelay(aecpc_t *aecInst);
101
WebRtcAec_Create(void ** aecInst)102 WebRtc_Word32 WebRtcAec_Create(void **aecInst)
103 {
104 aecpc_t *aecpc;
105 if (aecInst == NULL) {
106 return -1;
107 }
108
109 aecpc = malloc(sizeof(aecpc_t));
110 *aecInst = aecpc;
111 if (aecpc == NULL) {
112 return -1;
113 }
114
115 if (WebRtcAec_CreateAec(&aecpc->aec) == -1) {
116 WebRtcAec_Free(aecpc);
117 aecpc = NULL;
118 return -1;
119 }
120
121 if (WebRtcAec_CreateResampler(&aecpc->resampler) == -1) {
122 WebRtcAec_Free(aecpc);
123 aecpc = NULL;
124 return -1;
125 }
126 // Create far-end pre-buffer. The buffer size has to be large enough for
127 // largest possible drift compensation (kResamplerBufferSize) + "almost" an
128 // FFT buffer (PART_LEN2 - 1).
129 if (WebRtc_CreateBuffer(&aecpc->far_pre_buf,
130 PART_LEN2 + kResamplerBufferSize,
131 sizeof(float)) == -1) {
132 WebRtcAec_Free(aecpc);
133 aecpc = NULL;
134 return -1;
135 }
136
137 aecpc->initFlag = 0;
138 aecpc->lastError = 0;
139
140 #ifdef WEBRTC_AEC_DEBUG_DUMP
141 if (WebRtc_CreateBuffer(&aecpc->far_pre_buf_s16,
142 PART_LEN2 + kResamplerBufferSize,
143 sizeof(int16_t)) == -1) {
144 WebRtcAec_Free(aecpc);
145 aecpc = NULL;
146 return -1;
147 }
148 {
149 char filename[64];
150 sprintf(filename, "aec_far%d.pcm", instance_count);
151 aecpc->aec->farFile = fopen(filename, "wb");
152 sprintf(filename, "aec_near%d.pcm", instance_count);
153 aecpc->aec->nearFile = fopen(filename, "wb");
154 sprintf(filename, "aec_out%d.pcm", instance_count);
155 aecpc->aec->outFile = fopen(filename, "wb");
156 sprintf(filename, "aec_out_linear%d.pcm", instance_count);
157 aecpc->aec->outLinearFile = fopen(filename, "wb");
158 sprintf(filename, "aec_buf%d.dat", instance_count);
159 aecpc->bufFile = fopen(filename, "wb");
160 sprintf(filename, "aec_skew%d.dat", instance_count);
161 aecpc->skewFile = fopen(filename, "wb");
162 sprintf(filename, "aec_delay%d.dat", instance_count);
163 aecpc->delayFile = fopen(filename, "wb");
164 instance_count++;
165 }
166 #endif
167
168 return 0;
169 }
170
WebRtcAec_Free(void * aecInst)171 WebRtc_Word32 WebRtcAec_Free(void *aecInst)
172 {
173 aecpc_t *aecpc = aecInst;
174
175 if (aecpc == NULL) {
176 return -1;
177 }
178
179 WebRtc_FreeBuffer(aecpc->far_pre_buf);
180
181 #ifdef WEBRTC_AEC_DEBUG_DUMP
182 WebRtc_FreeBuffer(aecpc->far_pre_buf_s16);
183 fclose(aecpc->aec->farFile);
184 fclose(aecpc->aec->nearFile);
185 fclose(aecpc->aec->outFile);
186 fclose(aecpc->aec->outLinearFile);
187 fclose(aecpc->bufFile);
188 fclose(aecpc->skewFile);
189 fclose(aecpc->delayFile);
190 #endif
191
192 WebRtcAec_FreeAec(aecpc->aec);
193 WebRtcAec_FreeResampler(aecpc->resampler);
194 free(aecpc);
195
196 return 0;
197 }
198
WebRtcAec_Init(void * aecInst,WebRtc_Word32 sampFreq,WebRtc_Word32 scSampFreq)199 WebRtc_Word32 WebRtcAec_Init(void *aecInst, WebRtc_Word32 sampFreq, WebRtc_Word32 scSampFreq)
200 {
201 aecpc_t *aecpc = aecInst;
202 AecConfig aecConfig;
203
204 if (aecpc == NULL) {
205 return -1;
206 }
207
208 if (sampFreq != 8000 && sampFreq != 16000 && sampFreq != 32000) {
209 aecpc->lastError = AEC_BAD_PARAMETER_ERROR;
210 return -1;
211 }
212 aecpc->sampFreq = sampFreq;
213
214 if (scSampFreq < 1 || scSampFreq > 96000) {
215 aecpc->lastError = AEC_BAD_PARAMETER_ERROR;
216 return -1;
217 }
218 aecpc->scSampFreq = scSampFreq;
219
220 // Initialize echo canceller core
221 if (WebRtcAec_InitAec(aecpc->aec, aecpc->sampFreq) == -1) {
222 aecpc->lastError = AEC_UNSPECIFIED_ERROR;
223 return -1;
224 }
225
226 if (WebRtcAec_InitResampler(aecpc->resampler, aecpc->scSampFreq) == -1) {
227 aecpc->lastError = AEC_UNSPECIFIED_ERROR;
228 return -1;
229 }
230
231 if (WebRtc_InitBuffer(aecpc->far_pre_buf) == -1) {
232 aecpc->lastError = AEC_UNSPECIFIED_ERROR;
233 return -1;
234 }
235 WebRtc_MoveReadPtr(aecpc->far_pre_buf, -PART_LEN); // Start overlap.
236
237 aecpc->initFlag = initCheck; // indicates that initialization has been done
238
239 if (aecpc->sampFreq == 32000) {
240 aecpc->splitSampFreq = 16000;
241 }
242 else {
243 aecpc->splitSampFreq = sampFreq;
244 }
245
246 aecpc->skewFrCtr = 0;
247 aecpc->activity = 0;
248
249 aecpc->delayCtr = 0;
250
251 aecpc->sum = 0;
252 aecpc->counter = 0;
253 aecpc->checkBuffSize = 1;
254 aecpc->firstVal = 0;
255
256 aecpc->ECstartup = 1;
257 aecpc->bufSizeStart = 0;
258 aecpc->checkBufSizeCtr = 0;
259 aecpc->filtDelay = 0;
260 aecpc->timeForDelayChange = 0;
261 aecpc->knownDelay = 0;
262 aecpc->lastDelayDiff = 0;
263
264 aecpc->skew = 0;
265 aecpc->resample = kAecFalse;
266 aecpc->highSkewCtr = 0;
267 aecpc->sampFactor = (aecpc->scSampFreq * 1.0f) / aecpc->splitSampFreq;
268
269 // Default settings.
270 aecConfig.nlpMode = kAecNlpModerate;
271 aecConfig.skewMode = kAecFalse;
272 aecConfig.metricsMode = kAecFalse;
273 aecConfig.delay_logging = kAecFalse;
274
275 if (WebRtcAec_set_config(aecpc, aecConfig) == -1) {
276 aecpc->lastError = AEC_UNSPECIFIED_ERROR;
277 return -1;
278 }
279
280 #ifdef WEBRTC_AEC_DEBUG_DUMP
281 if (WebRtc_InitBuffer(aecpc->far_pre_buf_s16) == -1) {
282 aecpc->lastError = AEC_UNSPECIFIED_ERROR;
283 return -1;
284 }
285 WebRtc_MoveReadPtr(aecpc->far_pre_buf_s16, -PART_LEN); // Start overlap.
286 #endif
287
288 return 0;
289 }
290
291 // only buffer L band for farend
WebRtcAec_BufferFarend(void * aecInst,const WebRtc_Word16 * farend,WebRtc_Word16 nrOfSamples)292 WebRtc_Word32 WebRtcAec_BufferFarend(void *aecInst, const WebRtc_Word16 *farend,
293 WebRtc_Word16 nrOfSamples)
294 {
295 aecpc_t *aecpc = aecInst;
296 WebRtc_Word32 retVal = 0;
297 int newNrOfSamples = (int) nrOfSamples;
298 short newFarend[MAX_RESAMP_LEN];
299 const int16_t* farend_ptr = farend;
300 float tmp_farend[MAX_RESAMP_LEN];
301 const float* farend_float = tmp_farend;
302 float skew;
303 int i = 0;
304
305 if (aecpc == NULL) {
306 return -1;
307 }
308
309 if (farend == NULL) {
310 aecpc->lastError = AEC_NULL_POINTER_ERROR;
311 return -1;
312 }
313
314 if (aecpc->initFlag != initCheck) {
315 aecpc->lastError = AEC_UNINITIALIZED_ERROR;
316 return -1;
317 }
318
319 // number of samples == 160 for SWB input
320 if (nrOfSamples != 80 && nrOfSamples != 160) {
321 aecpc->lastError = AEC_BAD_PARAMETER_ERROR;
322 return -1;
323 }
324
325 skew = aecpc->skew;
326
327 if (aecpc->skewMode == kAecTrue && aecpc->resample == kAecTrue) {
328 // Resample and get a new number of samples
329 newNrOfSamples = WebRtcAec_ResampleLinear(aecpc->resampler,
330 farend,
331 nrOfSamples,
332 skew,
333 newFarend);
334 farend_ptr = (const int16_t*) newFarend;
335 }
336
337 aecpc->aec->system_delay += newNrOfSamples;
338
339 #ifdef WEBRTC_AEC_DEBUG_DUMP
340 WebRtc_WriteBuffer(aecpc->far_pre_buf_s16, farend_ptr,
341 (size_t) newNrOfSamples);
342 #endif
343 // Cast to float and write the time-domain data to |far_pre_buf|.
344 for (i = 0; i < newNrOfSamples; i++) {
345 tmp_farend[i] = (float) farend_ptr[i];
346 }
347 WebRtc_WriteBuffer(aecpc->far_pre_buf, farend_float,
348 (size_t) newNrOfSamples);
349
350 // Transform to frequency domain if we have enough data.
351 while (WebRtc_available_read(aecpc->far_pre_buf) >= PART_LEN2) {
352 // We have enough data to pass to the FFT, hence read PART_LEN2 samples.
353 WebRtc_ReadBuffer(aecpc->far_pre_buf, (void**) &farend_float, tmp_farend,
354 PART_LEN2);
355
356 WebRtcAec_BufferFarendPartition(aecpc->aec, farend_float);
357
358 // Rewind |far_pre_buf| PART_LEN samples for overlap before continuing.
359 WebRtc_MoveReadPtr(aecpc->far_pre_buf, -PART_LEN);
360 #ifdef WEBRTC_AEC_DEBUG_DUMP
361 WebRtc_ReadBuffer(aecpc->far_pre_buf_s16, (void**) &farend_ptr, newFarend,
362 PART_LEN2);
363 WebRtc_WriteBuffer(aecpc->aec->far_time_buf, &farend_ptr[PART_LEN], 1);
364 WebRtc_MoveReadPtr(aecpc->far_pre_buf_s16, -PART_LEN);
365 #endif
366 }
367
368 return retVal;
369 }
370
WebRtcAec_Process(void * aecInst,const WebRtc_Word16 * nearend,const WebRtc_Word16 * nearendH,WebRtc_Word16 * out,WebRtc_Word16 * outH,WebRtc_Word16 nrOfSamples,WebRtc_Word16 msInSndCardBuf,WebRtc_Word32 skew)371 WebRtc_Word32 WebRtcAec_Process(void *aecInst, const WebRtc_Word16 *nearend,
372 const WebRtc_Word16 *nearendH, WebRtc_Word16 *out, WebRtc_Word16 *outH,
373 WebRtc_Word16 nrOfSamples, WebRtc_Word16 msInSndCardBuf, WebRtc_Word32 skew)
374 {
375 aecpc_t *aecpc = aecInst;
376 WebRtc_Word32 retVal = 0;
377 short i;
378 short nBlocks10ms;
379 short nFrames;
380 // Limit resampling to doubling/halving of signal
381 const float minSkewEst = -0.5f;
382 const float maxSkewEst = 1.0f;
383
384 if (aecpc == NULL) {
385 return -1;
386 }
387
388 if (nearend == NULL) {
389 aecpc->lastError = AEC_NULL_POINTER_ERROR;
390 return -1;
391 }
392
393 if (out == NULL) {
394 aecpc->lastError = AEC_NULL_POINTER_ERROR;
395 return -1;
396 }
397
398 if (aecpc->initFlag != initCheck) {
399 aecpc->lastError = AEC_UNINITIALIZED_ERROR;
400 return -1;
401 }
402
403 // number of samples == 160 for SWB input
404 if (nrOfSamples != 80 && nrOfSamples != 160) {
405 aecpc->lastError = AEC_BAD_PARAMETER_ERROR;
406 return -1;
407 }
408
409 // Check for valid pointers based on sampling rate
410 if (aecpc->sampFreq == 32000 && nearendH == NULL) {
411 aecpc->lastError = AEC_NULL_POINTER_ERROR;
412 return -1;
413 }
414
415 if (msInSndCardBuf < 0) {
416 msInSndCardBuf = 0;
417 aecpc->lastError = AEC_BAD_PARAMETER_WARNING;
418 retVal = -1;
419 }
420 else if (msInSndCardBuf > 500) {
421 msInSndCardBuf = 500;
422 aecpc->lastError = AEC_BAD_PARAMETER_WARNING;
423 retVal = -1;
424 }
425 // TODO(andrew): we need to investigate if this +10 is really wanted.
426 msInSndCardBuf += 10;
427 aecpc->msInSndCardBuf = msInSndCardBuf;
428
429 if (aecpc->skewMode == kAecTrue) {
430 if (aecpc->skewFrCtr < 25) {
431 aecpc->skewFrCtr++;
432 }
433 else {
434 retVal = WebRtcAec_GetSkew(aecpc->resampler, skew, &aecpc->skew);
435 if (retVal == -1) {
436 aecpc->skew = 0;
437 aecpc->lastError = AEC_BAD_PARAMETER_WARNING;
438 }
439
440 aecpc->skew /= aecpc->sampFactor*nrOfSamples;
441
442 if (aecpc->skew < 1.0e-3 && aecpc->skew > -1.0e-3) {
443 aecpc->resample = kAecFalse;
444 }
445 else {
446 aecpc->resample = kAecTrue;
447 }
448
449 if (aecpc->skew < minSkewEst) {
450 aecpc->skew = minSkewEst;
451 }
452 else if (aecpc->skew > maxSkewEst) {
453 aecpc->skew = maxSkewEst;
454 }
455
456 #ifdef WEBRTC_AEC_DEBUG_DUMP
457 fwrite(&aecpc->skew, sizeof(aecpc->skew), 1, aecpc->skewFile);
458 #endif
459 }
460 }
461
462 nFrames = nrOfSamples / FRAME_LEN;
463 nBlocks10ms = nFrames / aecpc->aec->mult;
464
465 if (aecpc->ECstartup) {
466 if (nearend != out) {
467 // Only needed if they don't already point to the same place.
468 memcpy(out, nearend, sizeof(short) * nrOfSamples);
469 }
470
471 // The AEC is in the start up mode
472 // AEC is disabled until the system delay is OK
473
474 // Mechanism to ensure that the system delay is reasonably stable.
475 if (aecpc->checkBuffSize) {
476 aecpc->checkBufSizeCtr++;
477 // Before we fill up the far-end buffer we require the system delay
478 // to be stable (+/-8 ms) compared to the first value. This
479 // comparison is made during the following 6 consecutive 10 ms
480 // blocks. If it seems to be stable then we start to fill up the
481 // far-end buffer.
482 if (aecpc->counter == 0) {
483 aecpc->firstVal = aecpc->msInSndCardBuf;
484 aecpc->sum = 0;
485 }
486
487 if (abs(aecpc->firstVal - aecpc->msInSndCardBuf) <
488 WEBRTC_SPL_MAX(0.2 * aecpc->msInSndCardBuf, sampMsNb)) {
489 aecpc->sum += aecpc->msInSndCardBuf;
490 aecpc->counter++;
491 }
492 else {
493 aecpc->counter = 0;
494 }
495
496 if (aecpc->counter * nBlocks10ms >= 6) {
497 // The far-end buffer size is determined in partitions of
498 // PART_LEN samples. Use 75% of the average value of the system
499 // delay as buffer size to start with.
500 aecpc->bufSizeStart = WEBRTC_SPL_MIN((3 * aecpc->sum *
501 aecpc->aec->mult * 8) / (4 * aecpc->counter * PART_LEN),
502 kMaxBufSizeStart);
503 // Buffer size has now been determined.
504 aecpc->checkBuffSize = 0;
505 }
506
507 if (aecpc->checkBufSizeCtr * nBlocks10ms > 50) {
508 // For really bad systems, don't disable the echo canceller for
509 // more than 0.5 sec.
510 aecpc->bufSizeStart = WEBRTC_SPL_MIN((aecpc->msInSndCardBuf *
511 aecpc->aec->mult * 3) / 40, kMaxBufSizeStart);
512 aecpc->checkBuffSize = 0;
513 }
514 }
515
516 // If |checkBuffSize| changed in the if-statement above.
517 if (!aecpc->checkBuffSize) {
518 // The system delay is now reasonably stable (or has been unstable
519 // for too long). When the far-end buffer is filled with
520 // approximately the same amount of data as reported by the system
521 // we end the startup phase.
522 int overhead_elements = aecpc->aec->system_delay / PART_LEN -
523 aecpc->bufSizeStart;
524 if (overhead_elements == 0) {
525 // Enable the AEC
526 aecpc->ECstartup = 0;
527 } else if (overhead_elements > 0) {
528 WebRtc_MoveReadPtr(aecpc->aec->far_buf_windowed,
529 overhead_elements);
530 WebRtc_MoveReadPtr(aecpc->aec->far_buf, overhead_elements);
531 #ifdef WEBRTC_AEC_DEBUG_DUMP
532 WebRtc_MoveReadPtr(aecpc->aec->far_time_buf, overhead_elements);
533 #endif
534 // TODO(bjornv): Do we need a check on how much we actually
535 // moved the read pointer? It should always be possible to move
536 // the pointer |overhead_elements| since we have only added data
537 // to the buffer and no delay compensation nor AEC processing
538 // has been done.
539 aecpc->aec->system_delay -= overhead_elements * PART_LEN;
540
541 // Enable the AEC
542 aecpc->ECstartup = 0;
543 }
544 }
545 } else {
546 // AEC is enabled.
547
548 int out_elements = 0;
549
550 EstBufDelay(aecpc);
551
552 // Note that 1 frame is supported for NB and 2 frames for WB.
553 for (i = 0; i < nFrames; i++) {
554 int16_t* out_ptr = NULL;
555 int16_t out_tmp[FRAME_LEN];
556
557 // Call the AEC.
558 WebRtcAec_ProcessFrame(aecpc->aec,
559 &nearend[FRAME_LEN * i],
560 &nearendH[FRAME_LEN * i],
561 aecpc->knownDelay);
562 // TODO(bjornv): Re-structure such that we don't have to pass
563 // |aecpc->knownDelay| as input. Change name to something like
564 // |system_buffer_diff|.
565
566 // Stuff the out buffer if we have less than a frame to output.
567 // This should only happen for the first frame.
568 out_elements = (int) WebRtc_available_read(aecpc->aec->outFrBuf);
569 if (out_elements < FRAME_LEN) {
570 WebRtc_MoveReadPtr(aecpc->aec->outFrBuf,
571 out_elements - FRAME_LEN);
572 if (aecpc->sampFreq == 32000) {
573 WebRtc_MoveReadPtr(aecpc->aec->outFrBufH,
574 out_elements - FRAME_LEN);
575 }
576 }
577
578 // Obtain an output frame.
579 WebRtc_ReadBuffer(aecpc->aec->outFrBuf, (void**) &out_ptr,
580 out_tmp, FRAME_LEN);
581 memcpy(&out[FRAME_LEN * i], out_ptr, sizeof(int16_t) * FRAME_LEN);
582 // For H band
583 if (aecpc->sampFreq == 32000) {
584 WebRtc_ReadBuffer(aecpc->aec->outFrBufH, (void**) &out_ptr,
585 out_tmp, FRAME_LEN);
586 memcpy(&outH[FRAME_LEN * i], out_ptr,
587 sizeof(int16_t) * FRAME_LEN);
588 }
589 }
590 }
591
592 #ifdef WEBRTC_AEC_DEBUG_DUMP
593 {
594 int16_t far_buf_size_ms = (int16_t) (aecpc->aec->system_delay /
595 (sampMsNb * aecpc->aec->mult));
596 fwrite(&far_buf_size_ms, 2, 1, aecpc->bufFile);
597 fwrite(&(aecpc->knownDelay), sizeof(aecpc->knownDelay), 1, aecpc->delayFile);
598 }
599 #endif
600
601 return retVal;
602 }
603
WebRtcAec_set_config(void * aecInst,AecConfig config)604 WebRtc_Word32 WebRtcAec_set_config(void *aecInst, AecConfig config)
605 {
606 aecpc_t *aecpc = aecInst;
607
608 if (aecpc == NULL) {
609 return -1;
610 }
611
612 if (aecpc->initFlag != initCheck) {
613 aecpc->lastError = AEC_UNINITIALIZED_ERROR;
614 return -1;
615 }
616
617 if (config.skewMode != kAecFalse && config.skewMode != kAecTrue) {
618 aecpc->lastError = AEC_BAD_PARAMETER_ERROR;
619 return -1;
620 }
621 aecpc->skewMode = config.skewMode;
622
623 if (config.nlpMode != kAecNlpConservative && config.nlpMode !=
624 kAecNlpModerate && config.nlpMode != kAecNlpAggressive) {
625 aecpc->lastError = AEC_BAD_PARAMETER_ERROR;
626 return -1;
627 }
628 aecpc->nlpMode = config.nlpMode;
629 aecpc->aec->targetSupp = targetSupp[aecpc->nlpMode];
630 aecpc->aec->minOverDrive = minOverDrive[aecpc->nlpMode];
631
632 if (config.metricsMode != kAecFalse && config.metricsMode != kAecTrue) {
633 aecpc->lastError = AEC_BAD_PARAMETER_ERROR;
634 return -1;
635 }
636 aecpc->aec->metricsMode = config.metricsMode;
637 if (aecpc->aec->metricsMode == kAecTrue) {
638 WebRtcAec_InitMetrics(aecpc->aec);
639 }
640
641 if (config.delay_logging != kAecFalse && config.delay_logging != kAecTrue) {
642 aecpc->lastError = AEC_BAD_PARAMETER_ERROR;
643 return -1;
644 }
645 aecpc->aec->delay_logging_enabled = config.delay_logging;
646 if (aecpc->aec->delay_logging_enabled == kAecTrue) {
647 memset(aecpc->aec->delay_histogram, 0, sizeof(aecpc->aec->delay_histogram));
648 }
649
650 return 0;
651 }
652
WebRtcAec_get_config(void * aecInst,AecConfig * config)653 WebRtc_Word32 WebRtcAec_get_config(void *aecInst, AecConfig *config)
654 {
655 aecpc_t *aecpc = aecInst;
656
657 if (aecpc == NULL) {
658 return -1;
659 }
660
661 if (config == NULL) {
662 aecpc->lastError = AEC_NULL_POINTER_ERROR;
663 return -1;
664 }
665
666 if (aecpc->initFlag != initCheck) {
667 aecpc->lastError = AEC_UNINITIALIZED_ERROR;
668 return -1;
669 }
670
671 config->nlpMode = aecpc->nlpMode;
672 config->skewMode = aecpc->skewMode;
673 config->metricsMode = aecpc->aec->metricsMode;
674 config->delay_logging = aecpc->aec->delay_logging_enabled;
675
676 return 0;
677 }
678
WebRtcAec_get_echo_status(void * aecInst,WebRtc_Word16 * status)679 WebRtc_Word32 WebRtcAec_get_echo_status(void *aecInst, WebRtc_Word16 *status)
680 {
681 aecpc_t *aecpc = aecInst;
682
683 if (aecpc == NULL) {
684 return -1;
685 }
686
687 if (status == NULL) {
688 aecpc->lastError = AEC_NULL_POINTER_ERROR;
689 return -1;
690 }
691
692 if (aecpc->initFlag != initCheck) {
693 aecpc->lastError = AEC_UNINITIALIZED_ERROR;
694 return -1;
695 }
696
697 *status = aecpc->aec->echoState;
698
699 return 0;
700 }
701
WebRtcAec_GetMetrics(void * aecInst,AecMetrics * metrics)702 WebRtc_Word32 WebRtcAec_GetMetrics(void *aecInst, AecMetrics *metrics)
703 {
704 const float upweight = 0.7f;
705 float dtmp;
706 short stmp;
707 aecpc_t *aecpc = aecInst;
708
709 if (aecpc == NULL) {
710 return -1;
711 }
712
713 if (metrics == NULL) {
714 aecpc->lastError = AEC_NULL_POINTER_ERROR;
715 return -1;
716 }
717
718 if (aecpc->initFlag != initCheck) {
719 aecpc->lastError = AEC_UNINITIALIZED_ERROR;
720 return -1;
721 }
722
723 // ERL
724 metrics->erl.instant = (short) aecpc->aec->erl.instant;
725
726 if ((aecpc->aec->erl.himean > offsetLevel) && (aecpc->aec->erl.average > offsetLevel)) {
727 // Use a mix between regular average and upper part average
728 dtmp = upweight * aecpc->aec->erl.himean + (1 - upweight) * aecpc->aec->erl.average;
729 metrics->erl.average = (short) dtmp;
730 }
731 else {
732 metrics->erl.average = offsetLevel;
733 }
734
735 metrics->erl.max = (short) aecpc->aec->erl.max;
736
737 if (aecpc->aec->erl.min < (offsetLevel * (-1))) {
738 metrics->erl.min = (short) aecpc->aec->erl.min;
739 }
740 else {
741 metrics->erl.min = offsetLevel;
742 }
743
744 // ERLE
745 metrics->erle.instant = (short) aecpc->aec->erle.instant;
746
747 if ((aecpc->aec->erle.himean > offsetLevel) && (aecpc->aec->erle.average > offsetLevel)) {
748 // Use a mix between regular average and upper part average
749 dtmp = upweight * aecpc->aec->erle.himean + (1 - upweight) * aecpc->aec->erle.average;
750 metrics->erle.average = (short) dtmp;
751 }
752 else {
753 metrics->erle.average = offsetLevel;
754 }
755
756 metrics->erle.max = (short) aecpc->aec->erle.max;
757
758 if (aecpc->aec->erle.min < (offsetLevel * (-1))) {
759 metrics->erle.min = (short) aecpc->aec->erle.min;
760 } else {
761 metrics->erle.min = offsetLevel;
762 }
763
764 // RERL
765 if ((metrics->erl.average > offsetLevel) && (metrics->erle.average > offsetLevel)) {
766 stmp = metrics->erl.average + metrics->erle.average;
767 }
768 else {
769 stmp = offsetLevel;
770 }
771 metrics->rerl.average = stmp;
772
773 // No other statistics needed, but returned for completeness
774 metrics->rerl.instant = stmp;
775 metrics->rerl.max = stmp;
776 metrics->rerl.min = stmp;
777
778 // A_NLP
779 metrics->aNlp.instant = (short) aecpc->aec->aNlp.instant;
780
781 if ((aecpc->aec->aNlp.himean > offsetLevel) && (aecpc->aec->aNlp.average > offsetLevel)) {
782 // Use a mix between regular average and upper part average
783 dtmp = upweight * aecpc->aec->aNlp.himean + (1 - upweight) * aecpc->aec->aNlp.average;
784 metrics->aNlp.average = (short) dtmp;
785 }
786 else {
787 metrics->aNlp.average = offsetLevel;
788 }
789
790 metrics->aNlp.max = (short) aecpc->aec->aNlp.max;
791
792 if (aecpc->aec->aNlp.min < (offsetLevel * (-1))) {
793 metrics->aNlp.min = (short) aecpc->aec->aNlp.min;
794 }
795 else {
796 metrics->aNlp.min = offsetLevel;
797 }
798
799 return 0;
800 }
801
WebRtcAec_GetDelayMetrics(void * handle,int * median,int * std)802 int WebRtcAec_GetDelayMetrics(void* handle, int* median, int* std) {
803 aecpc_t* self = handle;
804 int i = 0;
805 int delay_values = 0;
806 int num_delay_values = 0;
807 int my_median = 0;
808 const int kMsPerBlock = (PART_LEN * 1000) / self->splitSampFreq;
809 float l1_norm = 0;
810
811 if (self == NULL) {
812 return -1;
813 }
814 if (median == NULL) {
815 self->lastError = AEC_NULL_POINTER_ERROR;
816 return -1;
817 }
818 if (std == NULL) {
819 self->lastError = AEC_NULL_POINTER_ERROR;
820 return -1;
821 }
822 if (self->initFlag != initCheck) {
823 self->lastError = AEC_UNINITIALIZED_ERROR;
824 return -1;
825 }
826 if (self->aec->delay_logging_enabled == 0) {
827 // Logging disabled
828 self->lastError = AEC_UNSUPPORTED_FUNCTION_ERROR;
829 return -1;
830 }
831
832 // Get number of delay values since last update
833 for (i = 0; i < kHistorySizeBlocks; i++) {
834 num_delay_values += self->aec->delay_histogram[i];
835 }
836 if (num_delay_values == 0) {
837 // We have no new delay value data. Even though -1 is a valid estimate, it
838 // will practically never be used since multiples of |kMsPerBlock| will
839 // always be returned.
840 *median = -1;
841 *std = -1;
842 return 0;
843 }
844
845 delay_values = num_delay_values >> 1; // Start value for median count down
846 // Get median of delay values since last update
847 for (i = 0; i < kHistorySizeBlocks; i++) {
848 delay_values -= self->aec->delay_histogram[i];
849 if (delay_values < 0) {
850 my_median = i;
851 break;
852 }
853 }
854 // Account for lookahead.
855 *median = (my_median - kLookaheadBlocks) * kMsPerBlock;
856
857 // Calculate the L1 norm, with median value as central moment
858 for (i = 0; i < kHistorySizeBlocks; i++) {
859 l1_norm += (float) (fabs(i - my_median) * self->aec->delay_histogram[i]);
860 }
861 *std = (int) (l1_norm / (float) num_delay_values + 0.5f) * kMsPerBlock;
862
863 // Reset histogram
864 memset(self->aec->delay_histogram, 0, sizeof(self->aec->delay_histogram));
865
866 return 0;
867 }
868
WebRtcAec_get_version(WebRtc_Word8 * versionStr,WebRtc_Word16 len)869 WebRtc_Word32 WebRtcAec_get_version(WebRtc_Word8 *versionStr, WebRtc_Word16 len)
870 {
871 const char version[] = "AEC 2.5.0";
872 const short versionLen = (short)strlen(version) + 1; // +1 for null-termination
873
874 if (versionStr == NULL) {
875 return -1;
876 }
877
878 if (versionLen > len) {
879 return -1;
880 }
881
882 strncpy(versionStr, version, versionLen);
883 return 0;
884 }
885
WebRtcAec_get_error_code(void * aecInst)886 WebRtc_Word32 WebRtcAec_get_error_code(void *aecInst)
887 {
888 aecpc_t *aecpc = aecInst;
889
890 if (aecpc == NULL) {
891 return -1;
892 }
893
894 return aecpc->lastError;
895 }
896
EstBufDelay(aecpc_t * aecpc)897 static int EstBufDelay(aecpc_t* aecpc) {
898 int nSampSndCard = aecpc->msInSndCardBuf * sampMsNb * aecpc->aec->mult;
899 int current_delay = nSampSndCard - aecpc->aec->system_delay;
900 int delay_difference = 0;
901
902 // Before we proceed with the delay estimate filtering we:
903 // 1) Compensate for the frame that will be read.
904 // 2) Compensate for drift resampling.
905
906 // 1) Compensating for the frame(s) that will be read/processed.
907 current_delay += FRAME_LEN * aecpc->aec->mult;
908
909 // 2) Account for resampling frame delay.
910 if (aecpc->skewMode == kAecTrue && aecpc->resample == kAecTrue) {
911 current_delay -= kResamplingDelay;
912 }
913
914 aecpc->filtDelay = WEBRTC_SPL_MAX(0, (short) (0.8 * aecpc->filtDelay +
915 0.2 * current_delay));
916
917 delay_difference = aecpc->filtDelay - aecpc->knownDelay;
918 if (delay_difference > 224) {
919 if (aecpc->lastDelayDiff < 96) {
920 aecpc->timeForDelayChange = 0;
921 } else {
922 aecpc->timeForDelayChange++;
923 }
924 } else if (delay_difference < 96 && aecpc->knownDelay > 0) {
925 if (aecpc->lastDelayDiff > 224) {
926 aecpc->timeForDelayChange = 0;
927 } else {
928 aecpc->timeForDelayChange++;
929 }
930 } else {
931 aecpc->timeForDelayChange = 0;
932 }
933 aecpc->lastDelayDiff = delay_difference;
934
935 if (aecpc->timeForDelayChange > 25) {
936 aecpc->knownDelay = WEBRTC_SPL_MAX((int) aecpc->filtDelay - 160, 0);
937 }
938
939 return 0;
940 }
941