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 #include "modules/audio_processing/aecm/aecm_core.h"
12 
13 #include <stddef.h>
14 #include <stdlib.h>
15 
16 extern "C" {
17 #include "common_audio/ring_buffer.h"
18 #include "common_audio/signal_processing/include/real_fft.h"
19 }
20 #include "modules/audio_processing/aecm/echo_control_mobile.h"
21 #include "modules/audio_processing/utility/delay_estimator_wrapper.h"
22 extern "C" {
23 #include "system_wrappers/include/cpu_features_wrapper.h"
24 }
25 
26 #include "rtc_base/checks.h"
27 #include "rtc_base/numerics/safe_conversions.h"
28 #include "typedefs.h"  // NOLINT(build/include)
29 
30 #ifdef AEC_DEBUG
31 FILE *dfile;
32 FILE *testfile;
33 #endif
34 
35 const int16_t WebRtcAecm_kCosTable[] = {
36     8192,  8190,  8187,  8180,  8172,  8160,  8147,  8130,  8112,
37     8091,  8067,  8041,  8012,  7982,  7948,  7912,  7874,  7834,
38     7791,  7745,  7697,  7647,  7595,  7540,  7483,  7424,  7362,
39     7299,  7233,  7164,  7094,  7021,  6947,  6870,  6791,  6710,
40     6627,  6542,  6455,  6366,  6275,  6182,  6087,  5991,  5892,
41     5792,  5690,  5586,  5481,  5374,  5265,  5155,  5043,  4930,
42     4815,  4698,  4580,  4461,  4341,  4219,  4096,  3971,  3845,
43     3719,  3591,  3462,  3331,  3200,  3068,  2935,  2801,  2667,
44     2531,  2395,  2258,  2120,  1981,  1842,  1703,  1563,  1422,
45     1281,  1140,   998,   856,   713,   571,   428,   285,   142,
46        0,  -142,  -285,  -428,  -571,  -713,  -856,  -998, -1140,
47    -1281, -1422, -1563, -1703, -1842, -1981, -2120, -2258, -2395,
48    -2531, -2667, -2801, -2935, -3068, -3200, -3331, -3462, -3591,
49    -3719, -3845, -3971, -4095, -4219, -4341, -4461, -4580, -4698,
50    -4815, -4930, -5043, -5155, -5265, -5374, -5481, -5586, -5690,
51    -5792, -5892, -5991, -6087, -6182, -6275, -6366, -6455, -6542,
52    -6627, -6710, -6791, -6870, -6947, -7021, -7094, -7164, -7233,
53    -7299, -7362, -7424, -7483, -7540, -7595, -7647, -7697, -7745,
54    -7791, -7834, -7874, -7912, -7948, -7982, -8012, -8041, -8067,
55    -8091, -8112, -8130, -8147, -8160, -8172, -8180, -8187, -8190,
56    -8191, -8190, -8187, -8180, -8172, -8160, -8147, -8130, -8112,
57    -8091, -8067, -8041, -8012, -7982, -7948, -7912, -7874, -7834,
58    -7791, -7745, -7697, -7647, -7595, -7540, -7483, -7424, -7362,
59    -7299, -7233, -7164, -7094, -7021, -6947, -6870, -6791, -6710,
60    -6627, -6542, -6455, -6366, -6275, -6182, -6087, -5991, -5892,
61    -5792, -5690, -5586, -5481, -5374, -5265, -5155, -5043, -4930,
62    -4815, -4698, -4580, -4461, -4341, -4219, -4096, -3971, -3845,
63    -3719, -3591, -3462, -3331, -3200, -3068, -2935, -2801, -2667,
64    -2531, -2395, -2258, -2120, -1981, -1842, -1703, -1563, -1422,
65    -1281, -1140,  -998,  -856,  -713,  -571,  -428,  -285,  -142,
66        0,   142,   285,   428,   571,   713,   856,   998,  1140,
67     1281,  1422,  1563,  1703,  1842,  1981,  2120,  2258,  2395,
68     2531,  2667,  2801,  2935,  3068,  3200,  3331,  3462,  3591,
69     3719,  3845,  3971,  4095,  4219,  4341,  4461,  4580,  4698,
70     4815,  4930,  5043,  5155,  5265,  5374,  5481,  5586,  5690,
71     5792,  5892,  5991,  6087,  6182,  6275,  6366,  6455,  6542,
72     6627,  6710,  6791,  6870,  6947,  7021,  7094,  7164,  7233,
73     7299,  7362,  7424,  7483,  7540,  7595,  7647,  7697,  7745,
74     7791,  7834,  7874,  7912,  7948,  7982,  8012,  8041,  8067,
75     8091,  8112,  8130,  8147,  8160,  8172,  8180,  8187,  8190
76 };
77 
78 const int16_t WebRtcAecm_kSinTable[] = {
79        0,    142,    285,    428,    571,    713,    856,    998,
80     1140,   1281,   1422,   1563,   1703,   1842,   1981,   2120,
81     2258,   2395,   2531,   2667,   2801,   2935,   3068,   3200,
82     3331,   3462,   3591,   3719,   3845,   3971,   4095,   4219,
83     4341,   4461,   4580,   4698,   4815,   4930,   5043,   5155,
84     5265,   5374,   5481,   5586,   5690,   5792,   5892,   5991,
85     6087,   6182,   6275,   6366,   6455,   6542,   6627,   6710,
86     6791,   6870,   6947,   7021,   7094,   7164,   7233,   7299,
87     7362,   7424,   7483,   7540,   7595,   7647,   7697,   7745,
88     7791,   7834,   7874,   7912,   7948,   7982,   8012,   8041,
89     8067,   8091,   8112,   8130,   8147,   8160,   8172,   8180,
90     8187,   8190,   8191,   8190,   8187,   8180,   8172,   8160,
91     8147,   8130,   8112,   8091,   8067,   8041,   8012,   7982,
92     7948,   7912,   7874,   7834,   7791,   7745,   7697,   7647,
93     7595,   7540,   7483,   7424,   7362,   7299,   7233,   7164,
94     7094,   7021,   6947,   6870,   6791,   6710,   6627,   6542,
95     6455,   6366,   6275,   6182,   6087,   5991,   5892,   5792,
96     5690,   5586,   5481,   5374,   5265,   5155,   5043,   4930,
97     4815,   4698,   4580,   4461,   4341,   4219,   4096,   3971,
98     3845,   3719,   3591,   3462,   3331,   3200,   3068,   2935,
99     2801,   2667,   2531,   2395,   2258,   2120,   1981,   1842,
100     1703,   1563,   1422,   1281,   1140,    998,    856,    713,
101      571,    428,    285,    142,      0,   -142,   -285,   -428,
102     -571,   -713,   -856,   -998,  -1140,  -1281,  -1422,  -1563,
103    -1703,  -1842,  -1981,  -2120,  -2258,  -2395,  -2531,  -2667,
104    -2801,  -2935,  -3068,  -3200,  -3331,  -3462,  -3591,  -3719,
105    -3845,  -3971,  -4095,  -4219,  -4341,  -4461,  -4580,  -4698,
106    -4815,  -4930,  -5043,  -5155,  -5265,  -5374,  -5481,  -5586,
107    -5690,  -5792,  -5892,  -5991,  -6087,  -6182,  -6275,  -6366,
108    -6455,  -6542,  -6627,  -6710,  -6791,  -6870,  -6947,  -7021,
109    -7094,  -7164,  -7233,  -7299,  -7362,  -7424,  -7483,  -7540,
110    -7595,  -7647,  -7697,  -7745,  -7791,  -7834,  -7874,  -7912,
111    -7948,  -7982,  -8012,  -8041,  -8067,  -8091,  -8112,  -8130,
112    -8147,  -8160,  -8172,  -8180,  -8187,  -8190,  -8191,  -8190,
113    -8187,  -8180,  -8172,  -8160,  -8147,  -8130,  -8112,  -8091,
114    -8067,  -8041,  -8012,  -7982,  -7948,  -7912,  -7874,  -7834,
115    -7791,  -7745,  -7697,  -7647,  -7595,  -7540,  -7483,  -7424,
116    -7362,  -7299,  -7233,  -7164,  -7094,  -7021,  -6947,  -6870,
117    -6791,  -6710,  -6627,  -6542,  -6455,  -6366,  -6275,  -6182,
118    -6087,  -5991,  -5892,  -5792,  -5690,  -5586,  -5481,  -5374,
119    -5265,  -5155,  -5043,  -4930,  -4815,  -4698,  -4580,  -4461,
120    -4341,  -4219,  -4096,  -3971,  -3845,  -3719,  -3591,  -3462,
121    -3331,  -3200,  -3068,  -2935,  -2801,  -2667,  -2531,  -2395,
122    -2258,  -2120,  -1981,  -1842,  -1703,  -1563,  -1422,  -1281,
123    -1140,   -998,   -856,   -713,   -571,   -428,   -285,   -142
124 };
125 
126 // Initialization table for echo channel in 8 kHz
127 static const int16_t kChannelStored8kHz[PART_LEN1] = {
128     2040,   1815,   1590,   1498,   1405,   1395,   1385,   1418,
129     1451,   1506,   1562,   1644,   1726,   1804,   1882,   1918,
130     1953,   1982,   2010,   2025,   2040,   2034,   2027,   2021,
131     2014,   1997,   1980,   1925,   1869,   1800,   1732,   1683,
132     1635,   1604,   1572,   1545,   1517,   1481,   1444,   1405,
133     1367,   1331,   1294,   1270,   1245,   1239,   1233,   1247,
134     1260,   1282,   1303,   1338,   1373,   1407,   1441,   1470,
135     1499,   1524,   1549,   1565,   1582,   1601,   1621,   1649,
136     1676
137 };
138 
139 // Initialization table for echo channel in 16 kHz
140 static const int16_t kChannelStored16kHz[PART_LEN1] = {
141     2040,   1590,   1405,   1385,   1451,   1562,   1726,   1882,
142     1953,   2010,   2040,   2027,   2014,   1980,   1869,   1732,
143     1635,   1572,   1517,   1444,   1367,   1294,   1245,   1233,
144     1260,   1303,   1373,   1441,   1499,   1549,   1582,   1621,
145     1676,   1741,   1802,   1861,   1921,   1983,   2040,   2102,
146     2170,   2265,   2375,   2515,   2651,   2781,   2922,   3075,
147     3253,   3471,   3738,   3976,   4151,   4258,   4308,   4288,
148     4270,   4253,   4237,   4179,   4086,   3947,   3757,   3484,
149     3153
150 };
151 
152 // Moves the pointer to the next entry and inserts |far_spectrum| and
153 // corresponding Q-domain in its buffer.
154 //
155 // Inputs:
156 //      - self          : Pointer to the delay estimation instance
157 //      - far_spectrum  : Pointer to the far end spectrum
158 //      - far_q         : Q-domain of far end spectrum
159 //
WebRtcAecm_UpdateFarHistory(AecmCore * self,uint16_t * far_spectrum,int far_q)160 void WebRtcAecm_UpdateFarHistory(AecmCore* self,
161                                  uint16_t* far_spectrum,
162                                  int far_q) {
163   // Get new buffer position
164   self->far_history_pos++;
165   if (self->far_history_pos >= MAX_DELAY) {
166     self->far_history_pos = 0;
167   }
168   // Update Q-domain buffer
169   self->far_q_domains[self->far_history_pos] = far_q;
170   // Update far end spectrum buffer
171   memcpy(&(self->far_history[self->far_history_pos * PART_LEN1]),
172          far_spectrum,
173          sizeof(uint16_t) * PART_LEN1);
174 }
175 
176 // Returns a pointer to the far end spectrum aligned to current near end
177 // spectrum. The function WebRtc_DelayEstimatorProcessFix(...) should have been
178 // called before AlignedFarend(...). Otherwise, you get the pointer to the
179 // previous frame. The memory is only valid until the next call of
180 // WebRtc_DelayEstimatorProcessFix(...).
181 //
182 // Inputs:
183 //      - self              : Pointer to the AECM instance.
184 //      - delay             : Current delay estimate.
185 //
186 // Output:
187 //      - far_q             : The Q-domain of the aligned far end spectrum
188 //
189 // Return value:
190 //      - far_spectrum      : Pointer to the aligned far end spectrum
191 //                            NULL - Error
192 //
WebRtcAecm_AlignedFarend(AecmCore * self,int * far_q,int delay)193 const uint16_t* WebRtcAecm_AlignedFarend(AecmCore* self,
194                                          int* far_q,
195                                          int delay) {
196   int buffer_position = 0;
197   RTC_DCHECK(self);
198   buffer_position = self->far_history_pos - delay;
199 
200   // Check buffer position
201   if (buffer_position < 0) {
202     buffer_position += MAX_DELAY;
203   }
204   // Get Q-domain
205   *far_q = self->far_q_domains[buffer_position];
206   // Return far end spectrum
207   return &(self->far_history[buffer_position * PART_LEN1]);
208 }
209 
210 // Declare function pointers.
211 CalcLinearEnergies WebRtcAecm_CalcLinearEnergies;
212 StoreAdaptiveChannel WebRtcAecm_StoreAdaptiveChannel;
213 ResetAdaptiveChannel WebRtcAecm_ResetAdaptiveChannel;
214 
WebRtcAecm_CreateCore()215 AecmCore* WebRtcAecm_CreateCore() {
216     AecmCore* aecm = static_cast<AecmCore*>(malloc(sizeof(AecmCore)));
217 
218     aecm->farFrameBuf = WebRtc_CreateBuffer(FRAME_LEN + PART_LEN,
219                                             sizeof(int16_t));
220     if (!aecm->farFrameBuf)
221     {
222         WebRtcAecm_FreeCore(aecm);
223         return NULL;
224     }
225 
226     aecm->nearNoisyFrameBuf = WebRtc_CreateBuffer(FRAME_LEN + PART_LEN,
227                                                   sizeof(int16_t));
228     if (!aecm->nearNoisyFrameBuf)
229     {
230         WebRtcAecm_FreeCore(aecm);
231         return NULL;
232     }
233 
234     aecm->nearCleanFrameBuf = WebRtc_CreateBuffer(FRAME_LEN + PART_LEN,
235                                                   sizeof(int16_t));
236     if (!aecm->nearCleanFrameBuf)
237     {
238         WebRtcAecm_FreeCore(aecm);
239         return NULL;
240     }
241 
242     aecm->outFrameBuf = WebRtc_CreateBuffer(FRAME_LEN + PART_LEN,
243                                             sizeof(int16_t));
244     if (!aecm->outFrameBuf)
245     {
246         WebRtcAecm_FreeCore(aecm);
247         return NULL;
248     }
249 
250     aecm->delay_estimator_farend = WebRtc_CreateDelayEstimatorFarend(PART_LEN1,
251                                                                      MAX_DELAY);
252     if (aecm->delay_estimator_farend == NULL) {
253       WebRtcAecm_FreeCore(aecm);
254       return NULL;
255     }
256     aecm->delay_estimator =
257         WebRtc_CreateDelayEstimator(aecm->delay_estimator_farend, 0);
258     if (aecm->delay_estimator == NULL) {
259       WebRtcAecm_FreeCore(aecm);
260       return NULL;
261     }
262     // TODO(bjornv): Explicitly disable robust delay validation until no
263     // performance regression has been established.  Then remove the line.
264     WebRtc_enable_robust_validation(aecm->delay_estimator, 0);
265 
266     aecm->real_fft = WebRtcSpl_CreateRealFFT(PART_LEN_SHIFT);
267     if (aecm->real_fft == NULL) {
268       WebRtcAecm_FreeCore(aecm);
269       return NULL;
270     }
271 
272     // Init some aecm pointers. 16 and 32 byte alignment is only necessary
273     // for Neon code currently.
274     aecm->xBuf = (int16_t*) (((uintptr_t)aecm->xBuf_buf + 31) & ~ 31);
275     aecm->dBufClean = (int16_t*) (((uintptr_t)aecm->dBufClean_buf + 31) & ~ 31);
276     aecm->dBufNoisy = (int16_t*) (((uintptr_t)aecm->dBufNoisy_buf + 31) & ~ 31);
277     aecm->outBuf = (int16_t*) (((uintptr_t)aecm->outBuf_buf + 15) & ~ 15);
278     aecm->channelStored = (int16_t*) (((uintptr_t)
279                                              aecm->channelStored_buf + 15) & ~ 15);
280     aecm->channelAdapt16 = (int16_t*) (((uintptr_t)
281                                               aecm->channelAdapt16_buf + 15) & ~ 15);
282     aecm->channelAdapt32 = (int32_t*) (((uintptr_t)
283                                               aecm->channelAdapt32_buf + 31) & ~ 31);
284 
285     return aecm;
286 }
287 
WebRtcAecm_InitEchoPathCore(AecmCore * aecm,const int16_t * echo_path)288 void WebRtcAecm_InitEchoPathCore(AecmCore* aecm, const int16_t* echo_path) {
289     int i = 0;
290 
291     // Reset the stored channel
292     memcpy(aecm->channelStored, echo_path, sizeof(int16_t) * PART_LEN1);
293     // Reset the adapted channels
294     memcpy(aecm->channelAdapt16, echo_path, sizeof(int16_t) * PART_LEN1);
295     for (i = 0; i < PART_LEN1; i++)
296     {
297         aecm->channelAdapt32[i] = (int32_t)aecm->channelAdapt16[i] << 16;
298     }
299 
300     // Reset channel storing variables
301     aecm->mseAdaptOld = 1000;
302     aecm->mseStoredOld = 1000;
303     aecm->mseThreshold = WEBRTC_SPL_WORD32_MAX;
304     aecm->mseChannelCount = 0;
305 }
306 
CalcLinearEnergiesC(AecmCore * aecm,const uint16_t * far_spectrum,int32_t * echo_est,uint32_t * far_energy,uint32_t * echo_energy_adapt,uint32_t * echo_energy_stored)307 static void CalcLinearEnergiesC(AecmCore* aecm,
308                                 const uint16_t* far_spectrum,
309                                 int32_t* echo_est,
310                                 uint32_t* far_energy,
311                                 uint32_t* echo_energy_adapt,
312                                 uint32_t* echo_energy_stored) {
313     int i;
314 
315     // Get energy for the delayed far end signal and estimated
316     // echo using both stored and adapted channels.
317     for (i = 0; i < PART_LEN1; i++)
318     {
319         echo_est[i] = WEBRTC_SPL_MUL_16_U16(aecm->channelStored[i],
320                                            far_spectrum[i]);
321         (*far_energy) += (uint32_t)(far_spectrum[i]);
322         *echo_energy_adapt += aecm->channelAdapt16[i] * far_spectrum[i];
323         (*echo_energy_stored) += (uint32_t)echo_est[i];
324     }
325 }
326 
StoreAdaptiveChannelC(AecmCore * aecm,const uint16_t * far_spectrum,int32_t * echo_est)327 static void StoreAdaptiveChannelC(AecmCore* aecm,
328                                   const uint16_t* far_spectrum,
329                                   int32_t* echo_est) {
330     int i;
331 
332     // During startup we store the channel every block.
333     memcpy(aecm->channelStored, aecm->channelAdapt16, sizeof(int16_t) * PART_LEN1);
334     // Recalculate echo estimate
335     for (i = 0; i < PART_LEN; i += 4)
336     {
337         echo_est[i] = WEBRTC_SPL_MUL_16_U16(aecm->channelStored[i],
338                                            far_spectrum[i]);
339         echo_est[i + 1] = WEBRTC_SPL_MUL_16_U16(aecm->channelStored[i + 1],
340                                            far_spectrum[i + 1]);
341         echo_est[i + 2] = WEBRTC_SPL_MUL_16_U16(aecm->channelStored[i + 2],
342                                            far_spectrum[i + 2]);
343         echo_est[i + 3] = WEBRTC_SPL_MUL_16_U16(aecm->channelStored[i + 3],
344                                            far_spectrum[i + 3]);
345     }
346     echo_est[i] = WEBRTC_SPL_MUL_16_U16(aecm->channelStored[i],
347                                        far_spectrum[i]);
348 }
349 
ResetAdaptiveChannelC(AecmCore * aecm)350 static void ResetAdaptiveChannelC(AecmCore* aecm) {
351     int i;
352 
353     // The stored channel has a significantly lower MSE than the adaptive one for
354     // two consecutive calculations. Reset the adaptive channel.
355     memcpy(aecm->channelAdapt16, aecm->channelStored,
356            sizeof(int16_t) * PART_LEN1);
357     // Restore the W32 channel
358     for (i = 0; i < PART_LEN; i += 4)
359     {
360         aecm->channelAdapt32[i] = (int32_t)aecm->channelStored[i] << 16;
361         aecm->channelAdapt32[i + 1] = (int32_t)aecm->channelStored[i + 1] << 16;
362         aecm->channelAdapt32[i + 2] = (int32_t)aecm->channelStored[i + 2] << 16;
363         aecm->channelAdapt32[i + 3] = (int32_t)aecm->channelStored[i + 3] << 16;
364     }
365     aecm->channelAdapt32[i] = (int32_t)aecm->channelStored[i] << 16;
366 }
367 
368 // Initialize function pointers for ARM Neon platform.
369 #if defined(WEBRTC_HAS_NEON)
WebRtcAecm_InitNeon(void)370 static void WebRtcAecm_InitNeon(void)
371 {
372   WebRtcAecm_StoreAdaptiveChannel = WebRtcAecm_StoreAdaptiveChannelNeon;
373   WebRtcAecm_ResetAdaptiveChannel = WebRtcAecm_ResetAdaptiveChannelNeon;
374   WebRtcAecm_CalcLinearEnergies = WebRtcAecm_CalcLinearEnergiesNeon;
375 }
376 #endif
377 
378 // Initialize function pointers for MIPS platform.
379 #if defined(MIPS32_LE)
WebRtcAecm_InitMips(void)380 static void WebRtcAecm_InitMips(void)
381 {
382 #if defined(MIPS_DSP_R1_LE)
383   WebRtcAecm_StoreAdaptiveChannel = WebRtcAecm_StoreAdaptiveChannel_mips;
384   WebRtcAecm_ResetAdaptiveChannel = WebRtcAecm_ResetAdaptiveChannel_mips;
385 #endif
386   WebRtcAecm_CalcLinearEnergies = WebRtcAecm_CalcLinearEnergies_mips;
387 }
388 #endif
389 
390 // WebRtcAecm_InitCore(...)
391 //
392 // This function initializes the AECM instant created with WebRtcAecm_CreateCore(...)
393 // Input:
394 //      - aecm            : Pointer to the Echo Suppression instance
395 //      - samplingFreq   : Sampling Frequency
396 //
397 // Output:
398 //      - aecm            : Initialized instance
399 //
400 // Return value         :  0 - Ok
401 //                        -1 - Error
402 //
WebRtcAecm_InitCore(AecmCore * const aecm,int samplingFreq)403 int WebRtcAecm_InitCore(AecmCore* const aecm, int samplingFreq) {
404     int i = 0;
405     int32_t tmp32 = PART_LEN1 * PART_LEN1;
406     int16_t tmp16 = PART_LEN1;
407 
408     if (samplingFreq != 8000 && samplingFreq != 16000)
409     {
410         samplingFreq = 8000;
411         return -1;
412     }
413     // sanity check of sampling frequency
414     aecm->mult = (int16_t)samplingFreq / 8000;
415 
416     aecm->farBufWritePos = 0;
417     aecm->farBufReadPos = 0;
418     aecm->knownDelay = 0;
419     aecm->lastKnownDelay = 0;
420 
421     WebRtc_InitBuffer(aecm->farFrameBuf);
422     WebRtc_InitBuffer(aecm->nearNoisyFrameBuf);
423     WebRtc_InitBuffer(aecm->nearCleanFrameBuf);
424     WebRtc_InitBuffer(aecm->outFrameBuf);
425 
426     memset(aecm->xBuf_buf, 0, sizeof(aecm->xBuf_buf));
427     memset(aecm->dBufClean_buf, 0, sizeof(aecm->dBufClean_buf));
428     memset(aecm->dBufNoisy_buf, 0, sizeof(aecm->dBufNoisy_buf));
429     memset(aecm->outBuf_buf, 0, sizeof(aecm->outBuf_buf));
430 
431     aecm->seed = 666;
432     aecm->totCount = 0;
433 
434     if (WebRtc_InitDelayEstimatorFarend(aecm->delay_estimator_farend) != 0) {
435       return -1;
436     }
437     if (WebRtc_InitDelayEstimator(aecm->delay_estimator) != 0) {
438       return -1;
439     }
440     // Set far end histories to zero
441     memset(aecm->far_history, 0, sizeof(uint16_t) * PART_LEN1 * MAX_DELAY);
442     memset(aecm->far_q_domains, 0, sizeof(int) * MAX_DELAY);
443     aecm->far_history_pos = MAX_DELAY;
444 
445     aecm->nlpFlag = 1;
446     aecm->fixedDelay = -1;
447 
448     aecm->dfaCleanQDomain = 0;
449     aecm->dfaCleanQDomainOld = 0;
450     aecm->dfaNoisyQDomain = 0;
451     aecm->dfaNoisyQDomainOld = 0;
452 
453     memset(aecm->nearLogEnergy, 0, sizeof(aecm->nearLogEnergy));
454     aecm->farLogEnergy = 0;
455     memset(aecm->echoAdaptLogEnergy, 0, sizeof(aecm->echoAdaptLogEnergy));
456     memset(aecm->echoStoredLogEnergy, 0, sizeof(aecm->echoStoredLogEnergy));
457 
458     // Initialize the echo channels with a stored shape.
459     if (samplingFreq == 8000)
460     {
461         WebRtcAecm_InitEchoPathCore(aecm, kChannelStored8kHz);
462     }
463     else
464     {
465         WebRtcAecm_InitEchoPathCore(aecm, kChannelStored16kHz);
466     }
467 
468     memset(aecm->echoFilt, 0, sizeof(aecm->echoFilt));
469     memset(aecm->nearFilt, 0, sizeof(aecm->nearFilt));
470     aecm->noiseEstCtr = 0;
471 
472     aecm->cngMode = AecmTrue;
473 
474     memset(aecm->noiseEstTooLowCtr, 0, sizeof(aecm->noiseEstTooLowCtr));
475     memset(aecm->noiseEstTooHighCtr, 0, sizeof(aecm->noiseEstTooHighCtr));
476     // Shape the initial noise level to an approximate pink noise.
477     for (i = 0; i < (PART_LEN1 >> 1) - 1; i++)
478     {
479         aecm->noiseEst[i] = (tmp32 << 8);
480         tmp16--;
481         tmp32 -= (int32_t)((tmp16 << 1) + 1);
482     }
483     for (; i < PART_LEN1; i++)
484     {
485         aecm->noiseEst[i] = (tmp32 << 8);
486     }
487 
488     aecm->farEnergyMin = WEBRTC_SPL_WORD16_MAX;
489     aecm->farEnergyMax = WEBRTC_SPL_WORD16_MIN;
490     aecm->farEnergyMaxMin = 0;
491     aecm->farEnergyVAD = FAR_ENERGY_MIN; // This prevents false speech detection at the
492                                          // beginning.
493     aecm->farEnergyMSE = 0;
494     aecm->currentVADValue = 0;
495     aecm->vadUpdateCount = 0;
496     aecm->firstVAD = 1;
497 
498     aecm->startupState = 0;
499     aecm->supGain = SUPGAIN_DEFAULT;
500     aecm->supGainOld = SUPGAIN_DEFAULT;
501 
502     aecm->supGainErrParamA = SUPGAIN_ERROR_PARAM_A;
503     aecm->supGainErrParamD = SUPGAIN_ERROR_PARAM_D;
504     aecm->supGainErrParamDiffAB = SUPGAIN_ERROR_PARAM_A - SUPGAIN_ERROR_PARAM_B;
505     aecm->supGainErrParamDiffBD = SUPGAIN_ERROR_PARAM_B - SUPGAIN_ERROR_PARAM_D;
506 
507     // Assert a preprocessor definition at compile-time. It's an assumption
508     // used in assembly code, so check the assembly files before any change.
509     static_assert(PART_LEN % 16 == 0, "PART_LEN is not a multiple of 16");
510 
511     // Initialize function pointers.
512     WebRtcAecm_CalcLinearEnergies = CalcLinearEnergiesC;
513     WebRtcAecm_StoreAdaptiveChannel = StoreAdaptiveChannelC;
514     WebRtcAecm_ResetAdaptiveChannel = ResetAdaptiveChannelC;
515 
516 #if defined(WEBRTC_HAS_NEON)
517     WebRtcAecm_InitNeon();
518 #endif
519 
520 #if defined(MIPS32_LE)
521     WebRtcAecm_InitMips();
522 #endif
523     return 0;
524 }
525 
526 // TODO(bjornv): This function is currently not used. Add support for these
527 // parameters from a higher level
WebRtcAecm_Control(AecmCore * aecm,int delay,int nlpFlag)528 int WebRtcAecm_Control(AecmCore* aecm, int delay, int nlpFlag) {
529     aecm->nlpFlag = nlpFlag;
530     aecm->fixedDelay = delay;
531 
532     return 0;
533 }
534 
WebRtcAecm_FreeCore(AecmCore * aecm)535 void WebRtcAecm_FreeCore(AecmCore* aecm) {
536     if (aecm == NULL) {
537       return;
538     }
539 
540     WebRtc_FreeBuffer(aecm->farFrameBuf);
541     WebRtc_FreeBuffer(aecm->nearNoisyFrameBuf);
542     WebRtc_FreeBuffer(aecm->nearCleanFrameBuf);
543     WebRtc_FreeBuffer(aecm->outFrameBuf);
544 
545     WebRtc_FreeDelayEstimator(aecm->delay_estimator);
546     WebRtc_FreeDelayEstimatorFarend(aecm->delay_estimator_farend);
547     WebRtcSpl_FreeRealFFT(aecm->real_fft);
548 
549     free(aecm);
550 }
551 
WebRtcAecm_ProcessFrame(AecmCore * aecm,const int16_t * farend,const int16_t * nearendNoisy,const int16_t * nearendClean,int16_t * out)552 int WebRtcAecm_ProcessFrame(AecmCore* aecm,
553                             const int16_t* farend,
554                             const int16_t* nearendNoisy,
555                             const int16_t* nearendClean,
556                             int16_t* out) {
557     int16_t outBlock_buf[PART_LEN + 8]; // Align buffer to 8-byte boundary.
558     int16_t* outBlock = (int16_t*) (((uintptr_t) outBlock_buf + 15) & ~ 15);
559 
560     int16_t farFrame[FRAME_LEN];
561     const int16_t* out_ptr = NULL;
562     int size = 0;
563 
564     // Buffer the current frame.
565     // Fetch an older one corresponding to the delay.
566     WebRtcAecm_BufferFarFrame(aecm, farend, FRAME_LEN);
567     WebRtcAecm_FetchFarFrame(aecm, farFrame, FRAME_LEN, aecm->knownDelay);
568 
569     // Buffer the synchronized far and near frames,
570     // to pass the smaller blocks individually.
571     WebRtc_WriteBuffer(aecm->farFrameBuf, farFrame, FRAME_LEN);
572     WebRtc_WriteBuffer(aecm->nearNoisyFrameBuf, nearendNoisy, FRAME_LEN);
573     if (nearendClean != NULL)
574     {
575         WebRtc_WriteBuffer(aecm->nearCleanFrameBuf, nearendClean, FRAME_LEN);
576     }
577 
578     // Process as many blocks as possible.
579     while (WebRtc_available_read(aecm->farFrameBuf) >= PART_LEN)
580     {
581         int16_t far_block[PART_LEN];
582         const int16_t* far_block_ptr = NULL;
583         int16_t near_noisy_block[PART_LEN];
584         const int16_t* near_noisy_block_ptr = NULL;
585 
586         WebRtc_ReadBuffer(aecm->farFrameBuf, (void**) &far_block_ptr, far_block,
587                           PART_LEN);
588         WebRtc_ReadBuffer(aecm->nearNoisyFrameBuf,
589                           (void**) &near_noisy_block_ptr,
590                           near_noisy_block,
591                           PART_LEN);
592         if (nearendClean != NULL)
593         {
594             int16_t near_clean_block[PART_LEN];
595             const int16_t* near_clean_block_ptr = NULL;
596 
597             WebRtc_ReadBuffer(aecm->nearCleanFrameBuf,
598                               (void**) &near_clean_block_ptr,
599                               near_clean_block,
600                               PART_LEN);
601             if (WebRtcAecm_ProcessBlock(aecm,
602                                         far_block_ptr,
603                                         near_noisy_block_ptr,
604                                         near_clean_block_ptr,
605                                         outBlock) == -1)
606             {
607                 return -1;
608             }
609         } else
610         {
611             if (WebRtcAecm_ProcessBlock(aecm,
612                                         far_block_ptr,
613                                         near_noisy_block_ptr,
614                                         NULL,
615                                         outBlock) == -1)
616             {
617                 return -1;
618             }
619         }
620 
621         WebRtc_WriteBuffer(aecm->outFrameBuf, outBlock, PART_LEN);
622     }
623 
624     // Stuff the out buffer if we have less than a frame to output.
625     // This should only happen for the first frame.
626     size = (int) WebRtc_available_read(aecm->outFrameBuf);
627     if (size < FRAME_LEN)
628     {
629         WebRtc_MoveReadPtr(aecm->outFrameBuf, size - FRAME_LEN);
630     }
631 
632     // Obtain an output frame.
633     WebRtc_ReadBuffer(aecm->outFrameBuf, (void**) &out_ptr, out, FRAME_LEN);
634     if (out_ptr != out) {
635       // ReadBuffer() hasn't copied to |out| in this case.
636       memcpy(out, out_ptr, FRAME_LEN * sizeof(int16_t));
637     }
638 
639     return 0;
640 }
641 
642 // WebRtcAecm_AsymFilt(...)
643 //
644 // Performs asymmetric filtering.
645 //
646 // Inputs:
647 //      - filtOld       : Previous filtered value.
648 //      - inVal         : New input value.
649 //      - stepSizePos   : Step size when we have a positive contribution.
650 //      - stepSizeNeg   : Step size when we have a negative contribution.
651 //
652 // Output:
653 //
654 // Return: - Filtered value.
655 //
WebRtcAecm_AsymFilt(const int16_t filtOld,const int16_t inVal,const int16_t stepSizePos,const int16_t stepSizeNeg)656 int16_t WebRtcAecm_AsymFilt(const int16_t filtOld, const int16_t inVal,
657                             const int16_t stepSizePos,
658                             const int16_t stepSizeNeg)
659 {
660     int16_t retVal;
661 
662     if ((filtOld == WEBRTC_SPL_WORD16_MAX) | (filtOld == WEBRTC_SPL_WORD16_MIN))
663     {
664         return inVal;
665     }
666     retVal = filtOld;
667     if (filtOld > inVal)
668     {
669         retVal -= (filtOld - inVal) >> stepSizeNeg;
670     } else
671     {
672         retVal += (inVal - filtOld) >> stepSizePos;
673     }
674 
675     return retVal;
676 }
677 
678 // ExtractFractionPart(a, zeros)
679 //
680 // returns the fraction part of |a|, with |zeros| number of leading zeros, as an
681 // int16_t scaled to Q8. There is no sanity check of |a| in the sense that the
682 // number of zeros match.
ExtractFractionPart(uint32_t a,int zeros)683 static int16_t ExtractFractionPart(uint32_t a, int zeros) {
684   return (int16_t)(((a << zeros) & 0x7FFFFFFF) >> 23);
685 }
686 
687 // Calculates and returns the log of |energy| in Q8. The input |energy| is
688 // supposed to be in Q(|q_domain|).
LogOfEnergyInQ8(uint32_t energy,int q_domain)689 static int16_t LogOfEnergyInQ8(uint32_t energy, int q_domain) {
690   static const int16_t kLogLowValue = PART_LEN_SHIFT << 7;
691   int16_t log_energy_q8 = kLogLowValue;
692   if (energy > 0) {
693     int zeros = WebRtcSpl_NormU32(energy);
694     int16_t frac = ExtractFractionPart(energy, zeros);
695     // log2 of |energy| in Q8.
696     log_energy_q8 += ((31 - zeros) << 8) + frac - (q_domain << 8);
697   }
698   return log_energy_q8;
699 }
700 
701 // WebRtcAecm_CalcEnergies(...)
702 //
703 // This function calculates the log of energies for nearend, farend and estimated
704 // echoes. There is also an update of energy decision levels, i.e. internal VAD.
705 //
706 //
707 // @param  aecm         [i/o]   Handle of the AECM instance.
708 // @param  far_spectrum [in]    Pointer to farend spectrum.
709 // @param  far_q        [in]    Q-domain of farend spectrum.
710 // @param  nearEner     [in]    Near end energy for current block in
711 //                              Q(aecm->dfaQDomain).
712 // @param  echoEst      [out]   Estimated echo in Q(xfa_q+RESOLUTION_CHANNEL16).
713 //
WebRtcAecm_CalcEnergies(AecmCore * aecm,const uint16_t * far_spectrum,const int16_t far_q,const uint32_t nearEner,int32_t * echoEst)714 void WebRtcAecm_CalcEnergies(AecmCore* aecm,
715                              const uint16_t* far_spectrum,
716                              const int16_t far_q,
717                              const uint32_t nearEner,
718                              int32_t* echoEst) {
719     // Local variables
720     uint32_t tmpAdapt = 0;
721     uint32_t tmpStored = 0;
722     uint32_t tmpFar = 0;
723 
724     int i;
725 
726     int16_t tmp16;
727     int16_t increase_max_shifts = 4;
728     int16_t decrease_max_shifts = 11;
729     int16_t increase_min_shifts = 11;
730     int16_t decrease_min_shifts = 3;
731 
732     // Get log of near end energy and store in buffer
733 
734     // Shift buffer
735     memmove(aecm->nearLogEnergy + 1, aecm->nearLogEnergy,
736             sizeof(int16_t) * (MAX_BUF_LEN - 1));
737 
738     // Logarithm of integrated magnitude spectrum (nearEner)
739     aecm->nearLogEnergy[0] = LogOfEnergyInQ8(nearEner, aecm->dfaNoisyQDomain);
740 
741     WebRtcAecm_CalcLinearEnergies(aecm, far_spectrum, echoEst, &tmpFar, &tmpAdapt, &tmpStored);
742 
743     // Shift buffers
744     memmove(aecm->echoAdaptLogEnergy + 1, aecm->echoAdaptLogEnergy,
745             sizeof(int16_t) * (MAX_BUF_LEN - 1));
746     memmove(aecm->echoStoredLogEnergy + 1, aecm->echoStoredLogEnergy,
747             sizeof(int16_t) * (MAX_BUF_LEN - 1));
748 
749     // Logarithm of delayed far end energy
750     aecm->farLogEnergy = LogOfEnergyInQ8(tmpFar, far_q);
751 
752     // Logarithm of estimated echo energy through adapted channel
753     aecm->echoAdaptLogEnergy[0] = LogOfEnergyInQ8(tmpAdapt,
754                                                   RESOLUTION_CHANNEL16 + far_q);
755 
756     // Logarithm of estimated echo energy through stored channel
757     aecm->echoStoredLogEnergy[0] =
758         LogOfEnergyInQ8(tmpStored, RESOLUTION_CHANNEL16 + far_q);
759 
760     // Update farend energy levels (min, max, vad, mse)
761     if (aecm->farLogEnergy > FAR_ENERGY_MIN)
762     {
763         if (aecm->startupState == 0)
764         {
765             increase_max_shifts = 2;
766             decrease_min_shifts = 2;
767             increase_min_shifts = 8;
768         }
769 
770         aecm->farEnergyMin = WebRtcAecm_AsymFilt(aecm->farEnergyMin, aecm->farLogEnergy,
771                                                  increase_min_shifts, decrease_min_shifts);
772         aecm->farEnergyMax = WebRtcAecm_AsymFilt(aecm->farEnergyMax, aecm->farLogEnergy,
773                                                  increase_max_shifts, decrease_max_shifts);
774         aecm->farEnergyMaxMin = (aecm->farEnergyMax - aecm->farEnergyMin);
775 
776         // Dynamic VAD region size
777         tmp16 = 2560 - aecm->farEnergyMin;
778         if (tmp16 > 0)
779         {
780           tmp16 = (int16_t)((tmp16 * FAR_ENERGY_VAD_REGION) >> 9);
781         } else
782         {
783             tmp16 = 0;
784         }
785         tmp16 += FAR_ENERGY_VAD_REGION;
786 
787         if ((aecm->startupState == 0) | (aecm->vadUpdateCount > 1024))
788         {
789             // In startup phase or VAD update halted
790             aecm->farEnergyVAD = aecm->farEnergyMin + tmp16;
791         } else
792         {
793             if (aecm->farEnergyVAD > aecm->farLogEnergy)
794             {
795                 aecm->farEnergyVAD +=
796                     (aecm->farLogEnergy + tmp16 - aecm->farEnergyVAD) >> 6;
797                 aecm->vadUpdateCount = 0;
798             } else
799             {
800                 aecm->vadUpdateCount++;
801             }
802         }
803         // Put MSE threshold higher than VAD
804         aecm->farEnergyMSE = aecm->farEnergyVAD + (1 << 8);
805     }
806 
807     // Update VAD variables
808     if (aecm->farLogEnergy > aecm->farEnergyVAD)
809     {
810         if ((aecm->startupState == 0) | (aecm->farEnergyMaxMin > FAR_ENERGY_DIFF))
811         {
812             // We are in startup or have significant dynamics in input speech level
813             aecm->currentVADValue = 1;
814         }
815     } else
816     {
817         aecm->currentVADValue = 0;
818     }
819     if ((aecm->currentVADValue) && (aecm->firstVAD))
820     {
821         aecm->firstVAD = 0;
822         if (aecm->echoAdaptLogEnergy[0] > aecm->nearLogEnergy[0])
823         {
824             // The estimated echo has higher energy than the near end signal.
825             // This means that the initialization was too aggressive. Scale
826             // down by a factor 8
827             for (i = 0; i < PART_LEN1; i++)
828             {
829                 aecm->channelAdapt16[i] >>= 3;
830             }
831             // Compensate the adapted echo energy level accordingly.
832             aecm->echoAdaptLogEnergy[0] -= (3 << 8);
833             aecm->firstVAD = 1;
834         }
835     }
836 }
837 
838 // WebRtcAecm_CalcStepSize(...)
839 //
840 // This function calculates the step size used in channel estimation
841 //
842 //
843 // @param  aecm  [in]    Handle of the AECM instance.
844 // @param  mu    [out]   (Return value) Stepsize in log2(), i.e. number of shifts.
845 //
846 //
WebRtcAecm_CalcStepSize(AecmCore * const aecm)847 int16_t WebRtcAecm_CalcStepSize(AecmCore* const aecm) {
848     int32_t tmp32;
849     int16_t tmp16;
850     int16_t mu = MU_MAX;
851 
852     // Here we calculate the step size mu used in the
853     // following NLMS based Channel estimation algorithm
854     if (!aecm->currentVADValue)
855     {
856         // Far end energy level too low, no channel update
857         mu = 0;
858     } else if (aecm->startupState > 0)
859     {
860         if (aecm->farEnergyMin >= aecm->farEnergyMax)
861         {
862             mu = MU_MIN;
863         } else
864         {
865             tmp16 = (aecm->farLogEnergy - aecm->farEnergyMin);
866             tmp32 = tmp16 * MU_DIFF;
867             tmp32 = WebRtcSpl_DivW32W16(tmp32, aecm->farEnergyMaxMin);
868             mu = MU_MIN - 1 - (int16_t)(tmp32);
869             // The -1 is an alternative to rounding. This way we get a larger
870             // stepsize, so we in some sense compensate for truncation in NLMS
871         }
872         if (mu < MU_MAX)
873         {
874             mu = MU_MAX; // Equivalent with maximum step size of 2^-MU_MAX
875         }
876     }
877 
878     return mu;
879 }
880 
881 // WebRtcAecm_UpdateChannel(...)
882 //
883 // This function performs channel estimation. NLMS and decision on channel storage.
884 //
885 //
886 // @param  aecm         [i/o]   Handle of the AECM instance.
887 // @param  far_spectrum [in]    Absolute value of the farend signal in Q(far_q)
888 // @param  far_q        [in]    Q-domain of the farend signal
889 // @param  dfa          [in]    Absolute value of the nearend signal (Q[aecm->dfaQDomain])
890 // @param  mu           [in]    NLMS step size.
891 // @param  echoEst      [i/o]   Estimated echo in Q(far_q+RESOLUTION_CHANNEL16).
892 //
WebRtcAecm_UpdateChannel(AecmCore * aecm,const uint16_t * far_spectrum,const int16_t far_q,const uint16_t * const dfa,const int16_t mu,int32_t * echoEst)893 void WebRtcAecm_UpdateChannel(AecmCore* aecm,
894                               const uint16_t* far_spectrum,
895                               const int16_t far_q,
896                               const uint16_t* const dfa,
897                               const int16_t mu,
898                               int32_t* echoEst) {
899     uint32_t tmpU32no1, tmpU32no2;
900     int32_t tmp32no1, tmp32no2;
901     int32_t mseStored;
902     int32_t mseAdapt;
903 
904     int i;
905 
906     int16_t zerosFar, zerosNum, zerosCh, zerosDfa;
907     int16_t shiftChFar, shiftNum, shift2ResChan;
908     int16_t tmp16no1;
909     int16_t xfaQ, dfaQ;
910 
911     // This is the channel estimation algorithm. It is base on NLMS but has a variable step
912     // length, which was calculated above.
913     if (mu)
914     {
915         for (i = 0; i < PART_LEN1; i++)
916         {
917             // Determine norm of channel and farend to make sure we don't get overflow in
918             // multiplication
919             zerosCh = WebRtcSpl_NormU32(aecm->channelAdapt32[i]);
920             zerosFar = WebRtcSpl_NormU32((uint32_t)far_spectrum[i]);
921             if (zerosCh + zerosFar > 31)
922             {
923                 // Multiplication is safe
924                 tmpU32no1 = WEBRTC_SPL_UMUL_32_16(aecm->channelAdapt32[i],
925                         far_spectrum[i]);
926                 shiftChFar = 0;
927             } else
928             {
929                 // We need to shift down before multiplication
930                 shiftChFar = 32 - zerosCh - zerosFar;
931                 tmpU32no1 = rtc::dchecked_cast<uint32_t>(
932                     aecm->channelAdapt32[i] >> shiftChFar) * far_spectrum[i];
933             }
934             // Determine Q-domain of numerator
935             zerosNum = WebRtcSpl_NormU32(tmpU32no1);
936             if (dfa[i])
937             {
938                 zerosDfa = WebRtcSpl_NormU32((uint32_t)dfa[i]);
939             } else
940             {
941                 zerosDfa = 32;
942             }
943             tmp16no1 = zerosDfa - 2 + aecm->dfaNoisyQDomain -
944                 RESOLUTION_CHANNEL32 - far_q + shiftChFar;
945             if (zerosNum > tmp16no1 + 1)
946             {
947                 xfaQ = tmp16no1;
948                 dfaQ = zerosDfa - 2;
949             } else
950             {
951                 xfaQ = zerosNum - 2;
952                 dfaQ = RESOLUTION_CHANNEL32 + far_q - aecm->dfaNoisyQDomain -
953                     shiftChFar + xfaQ;
954             }
955             // Add in the same Q-domain
956             tmpU32no1 = WEBRTC_SPL_SHIFT_W32(tmpU32no1, xfaQ);
957             tmpU32no2 = WEBRTC_SPL_SHIFT_W32((uint32_t)dfa[i], dfaQ);
958             tmp32no1 = (int32_t)tmpU32no2 - (int32_t)tmpU32no1;
959             zerosNum = WebRtcSpl_NormW32(tmp32no1);
960             if ((tmp32no1) && (far_spectrum[i] > (CHANNEL_VAD << far_q)))
961             {
962                 //
963                 // Update is needed
964                 //
965                 // This is what we would like to compute
966                 //
967                 // tmp32no1 = dfa[i] - (aecm->channelAdapt[i] * far_spectrum[i])
968                 // tmp32norm = (i + 1)
969                 // aecm->channelAdapt[i] += (2^mu) * tmp32no1
970                 //                        / (tmp32norm * far_spectrum[i])
971                 //
972 
973                 // Make sure we don't get overflow in multiplication.
974                 if (zerosNum + zerosFar > 31)
975                 {
976                     if (tmp32no1 > 0)
977                     {
978                         tmp32no2 = (int32_t)WEBRTC_SPL_UMUL_32_16(tmp32no1,
979                                                                         far_spectrum[i]);
980                     } else
981                     {
982                         tmp32no2 = -(int32_t)WEBRTC_SPL_UMUL_32_16(-tmp32no1,
983                                                                          far_spectrum[i]);
984                     }
985                     shiftNum = 0;
986                 } else
987                 {
988                     shiftNum = 32 - (zerosNum + zerosFar);
989                     if (tmp32no1 > 0)
990                     {
991                         tmp32no2 = (tmp32no1 >> shiftNum) * far_spectrum[i];
992                     } else
993                     {
994                         tmp32no2 = -((-tmp32no1 >> shiftNum) * far_spectrum[i]);
995                     }
996                 }
997                 // Normalize with respect to frequency bin
998                 tmp32no2 = WebRtcSpl_DivW32W16(tmp32no2, i + 1);
999                 // Make sure we are in the right Q-domain
1000                 shift2ResChan = shiftNum + shiftChFar - xfaQ - mu - ((30 - zerosFar) << 1);
1001                 if (WebRtcSpl_NormW32(tmp32no2) < shift2ResChan)
1002                 {
1003                     tmp32no2 = WEBRTC_SPL_WORD32_MAX;
1004                 } else
1005                 {
1006                     tmp32no2 = WEBRTC_SPL_SHIFT_W32(tmp32no2, shift2ResChan);
1007                 }
1008                 aecm->channelAdapt32[i] =
1009                     WebRtcSpl_AddSatW32(aecm->channelAdapt32[i], tmp32no2);
1010                 if (aecm->channelAdapt32[i] < 0)
1011                 {
1012                     // We can never have negative channel gain
1013                     aecm->channelAdapt32[i] = 0;
1014                 }
1015                 aecm->channelAdapt16[i] =
1016                     (int16_t)(aecm->channelAdapt32[i] >> 16);
1017             }
1018         }
1019     }
1020     // END: Adaptive channel update
1021 
1022     // Determine if we should store or restore the channel
1023     if ((aecm->startupState == 0) & (aecm->currentVADValue))
1024     {
1025         // During startup we store the channel every block,
1026         // and we recalculate echo estimate
1027         WebRtcAecm_StoreAdaptiveChannel(aecm, far_spectrum, echoEst);
1028     } else
1029     {
1030         if (aecm->farLogEnergy < aecm->farEnergyMSE)
1031         {
1032             aecm->mseChannelCount = 0;
1033         } else
1034         {
1035             aecm->mseChannelCount++;
1036         }
1037         // Enough data for validation. Store channel if we can.
1038         if (aecm->mseChannelCount >= (MIN_MSE_COUNT + 10))
1039         {
1040             // We have enough data.
1041             // Calculate MSE of "Adapt" and "Stored" versions.
1042             // It is actually not MSE, but average absolute error.
1043             mseStored = 0;
1044             mseAdapt = 0;
1045             for (i = 0; i < MIN_MSE_COUNT; i++)
1046             {
1047                 tmp32no1 = ((int32_t)aecm->echoStoredLogEnergy[i]
1048                         - (int32_t)aecm->nearLogEnergy[i]);
1049                 tmp32no2 = WEBRTC_SPL_ABS_W32(tmp32no1);
1050                 mseStored += tmp32no2;
1051 
1052                 tmp32no1 = ((int32_t)aecm->echoAdaptLogEnergy[i]
1053                         - (int32_t)aecm->nearLogEnergy[i]);
1054                 tmp32no2 = WEBRTC_SPL_ABS_W32(tmp32no1);
1055                 mseAdapt += tmp32no2;
1056             }
1057             if (((mseStored << MSE_RESOLUTION) < (MIN_MSE_DIFF * mseAdapt))
1058                     & ((aecm->mseStoredOld << MSE_RESOLUTION) < (MIN_MSE_DIFF
1059                             * aecm->mseAdaptOld)))
1060             {
1061                 // The stored channel has a significantly lower MSE than the adaptive one for
1062                 // two consecutive calculations. Reset the adaptive channel.
1063                 WebRtcAecm_ResetAdaptiveChannel(aecm);
1064             } else if (((MIN_MSE_DIFF * mseStored) > (mseAdapt << MSE_RESOLUTION)) & (mseAdapt
1065                     < aecm->mseThreshold) & (aecm->mseAdaptOld < aecm->mseThreshold))
1066             {
1067                 // The adaptive channel has a significantly lower MSE than the stored one.
1068                 // The MSE for the adaptive channel has also been low for two consecutive
1069                 // calculations. Store the adaptive channel.
1070                 WebRtcAecm_StoreAdaptiveChannel(aecm, far_spectrum, echoEst);
1071 
1072                 // Update threshold
1073                 if (aecm->mseThreshold == WEBRTC_SPL_WORD32_MAX)
1074                 {
1075                     aecm->mseThreshold = (mseAdapt + aecm->mseAdaptOld);
1076                 } else
1077                 {
1078                   int scaled_threshold = aecm->mseThreshold * 5 / 8;
1079                   aecm->mseThreshold +=
1080                       ((mseAdapt - scaled_threshold) * 205) >> 8;
1081                 }
1082 
1083             }
1084 
1085             // Reset counter
1086             aecm->mseChannelCount = 0;
1087 
1088             // Store the MSE values.
1089             aecm->mseStoredOld = mseStored;
1090             aecm->mseAdaptOld = mseAdapt;
1091         }
1092     }
1093     // END: Determine if we should store or reset channel estimate.
1094 }
1095 
1096 // CalcSuppressionGain(...)
1097 //
1098 // This function calculates the suppression gain that is used in the Wiener filter.
1099 //
1100 //
1101 // @param  aecm     [i/n]   Handle of the AECM instance.
1102 // @param  supGain  [out]   (Return value) Suppression gain with which to scale the noise
1103 //                          level (Q14).
1104 //
1105 //
WebRtcAecm_CalcSuppressionGain(AecmCore * const aecm)1106 int16_t WebRtcAecm_CalcSuppressionGain(AecmCore* const aecm) {
1107     int32_t tmp32no1;
1108 
1109     int16_t supGain = SUPGAIN_DEFAULT;
1110     int16_t tmp16no1;
1111     int16_t dE = 0;
1112 
1113     // Determine suppression gain used in the Wiener filter. The gain is based on a mix of far
1114     // end energy and echo estimation error.
1115     // Adjust for the far end signal level. A low signal level indicates no far end signal,
1116     // hence we set the suppression gain to 0
1117     if (!aecm->currentVADValue)
1118     {
1119         supGain = 0;
1120     } else
1121     {
1122         // Adjust for possible double talk. If we have large variations in estimation error we
1123         // likely have double talk (or poor channel).
1124         tmp16no1 = (aecm->nearLogEnergy[0] - aecm->echoStoredLogEnergy[0] - ENERGY_DEV_OFFSET);
1125         dE = WEBRTC_SPL_ABS_W16(tmp16no1);
1126 
1127         if (dE < ENERGY_DEV_TOL)
1128         {
1129             // Likely no double talk. The better estimation, the more we can suppress signal.
1130             // Update counters
1131             if (dE < SUPGAIN_EPC_DT)
1132             {
1133                 tmp32no1 = aecm->supGainErrParamDiffAB * dE;
1134                 tmp32no1 += (SUPGAIN_EPC_DT >> 1);
1135                 tmp16no1 = (int16_t)WebRtcSpl_DivW32W16(tmp32no1, SUPGAIN_EPC_DT);
1136                 supGain = aecm->supGainErrParamA - tmp16no1;
1137             } else
1138             {
1139                 tmp32no1 = aecm->supGainErrParamDiffBD * (ENERGY_DEV_TOL - dE);
1140                 tmp32no1 += ((ENERGY_DEV_TOL - SUPGAIN_EPC_DT) >> 1);
1141                 tmp16no1 = (int16_t)WebRtcSpl_DivW32W16(tmp32no1, (ENERGY_DEV_TOL
1142                         - SUPGAIN_EPC_DT));
1143                 supGain = aecm->supGainErrParamD + tmp16no1;
1144             }
1145         } else
1146         {
1147             // Likely in double talk. Use default value
1148             supGain = aecm->supGainErrParamD;
1149         }
1150     }
1151 
1152     if (supGain > aecm->supGainOld)
1153     {
1154         tmp16no1 = supGain;
1155     } else
1156     {
1157         tmp16no1 = aecm->supGainOld;
1158     }
1159     aecm->supGainOld = supGain;
1160     if (tmp16no1 < aecm->supGain)
1161     {
1162         aecm->supGain += (int16_t)((tmp16no1 - aecm->supGain) >> 4);
1163     } else
1164     {
1165         aecm->supGain += (int16_t)((tmp16no1 - aecm->supGain) >> 4);
1166     }
1167 
1168     // END: Update suppression gain
1169 
1170     return aecm->supGain;
1171 }
1172 
WebRtcAecm_BufferFarFrame(AecmCore * const aecm,const int16_t * const farend,const int farLen)1173 void WebRtcAecm_BufferFarFrame(AecmCore* const aecm,
1174                                const int16_t* const farend,
1175                                const int farLen) {
1176     int writeLen = farLen, writePos = 0;
1177 
1178     // Check if the write position must be wrapped
1179     while (aecm->farBufWritePos + writeLen > FAR_BUF_LEN)
1180     {
1181         // Write to remaining buffer space before wrapping
1182         writeLen = FAR_BUF_LEN - aecm->farBufWritePos;
1183         memcpy(aecm->farBuf + aecm->farBufWritePos, farend + writePos,
1184                sizeof(int16_t) * writeLen);
1185         aecm->farBufWritePos = 0;
1186         writePos = writeLen;
1187         writeLen = farLen - writeLen;
1188     }
1189 
1190     memcpy(aecm->farBuf + aecm->farBufWritePos, farend + writePos,
1191            sizeof(int16_t) * writeLen);
1192     aecm->farBufWritePos += writeLen;
1193 }
1194 
WebRtcAecm_FetchFarFrame(AecmCore * const aecm,int16_t * const farend,const int farLen,const int knownDelay)1195 void WebRtcAecm_FetchFarFrame(AecmCore* const aecm,
1196                               int16_t* const farend,
1197                               const int farLen,
1198                               const int knownDelay) {
1199     int readLen = farLen;
1200     int readPos = 0;
1201     int delayChange = knownDelay - aecm->lastKnownDelay;
1202 
1203     aecm->farBufReadPos -= delayChange;
1204 
1205     // Check if delay forces a read position wrap
1206     while (aecm->farBufReadPos < 0)
1207     {
1208         aecm->farBufReadPos += FAR_BUF_LEN;
1209     }
1210     while (aecm->farBufReadPos > FAR_BUF_LEN - 1)
1211     {
1212         aecm->farBufReadPos -= FAR_BUF_LEN;
1213     }
1214 
1215     aecm->lastKnownDelay = knownDelay;
1216 
1217     // Check if read position must be wrapped
1218     while (aecm->farBufReadPos + readLen > FAR_BUF_LEN)
1219     {
1220 
1221         // Read from remaining buffer space before wrapping
1222         readLen = FAR_BUF_LEN - aecm->farBufReadPos;
1223         memcpy(farend + readPos, aecm->farBuf + aecm->farBufReadPos,
1224                sizeof(int16_t) * readLen);
1225         aecm->farBufReadPos = 0;
1226         readPos = readLen;
1227         readLen = farLen - readLen;
1228     }
1229     memcpy(farend + readPos, aecm->farBuf + aecm->farBufReadPos,
1230            sizeof(int16_t) * readLen);
1231     aecm->farBufReadPos += readLen;
1232 }
1233