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