1 /*
2  *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "aecm_core.h"
12 
13 #include <assert.h>
14 #include <stdlib.h>
15 
16 #include "cpu_features_wrapper.h"
17 #include "delay_estimator_wrapper.h"
18 #include "echo_control_mobile.h"
19 #include "ring_buffer.h"
20 #include "typedefs.h"
21 
22 #ifdef ARM_WINM_LOG
23 #include <stdio.h>
24 #include <windows.h>
25 #endif
26 
27 #ifdef AEC_DEBUG
28 FILE *dfile;
29 FILE *testfile;
30 #endif
31 
32 #ifdef _MSC_VER // visual c++
33 #define ALIGN8_BEG __declspec(align(8))
34 #define ALIGN8_END
35 #else // gcc or icc
36 #define ALIGN8_BEG
37 #define ALIGN8_END __attribute__((aligned(8)))
38 #endif
39 
40 #ifdef AECM_SHORT
41 
42 // Square root of Hanning window in Q14
43 const WebRtc_Word16 WebRtcAecm_kSqrtHanning[] =
44 {
45     0, 804, 1606, 2404, 3196, 3981, 4756, 5520,
46     6270, 7005, 7723, 8423, 9102, 9760, 10394, 11003,
47     11585, 12140, 12665, 13160, 13623, 14053, 14449, 14811,
48     15137, 15426, 15679, 15893, 16069, 16207, 16305, 16364,
49     16384
50 };
51 
52 #else
53 
54 // Square root of Hanning window in Q14
55 const ALIGN8_BEG WebRtc_Word16 WebRtcAecm_kSqrtHanning[] ALIGN8_END =
56 {
57     0, 399, 798, 1196, 1594, 1990, 2386, 2780, 3172,
58     3562, 3951, 4337, 4720, 5101, 5478, 5853, 6224, 6591, 6954, 7313, 7668, 8019, 8364,
59     8705, 9040, 9370, 9695, 10013, 10326, 10633, 10933, 11227, 11514, 11795, 12068, 12335,
60     12594, 12845, 13089, 13325, 13553, 13773, 13985, 14189, 14384, 14571, 14749, 14918,
61     15079, 15231, 15373, 15506, 15631, 15746, 15851, 15947, 16034, 16111, 16179, 16237,
62     16286, 16325, 16354, 16373, 16384
63 };
64 
65 #endif
66 
67 //Q15 alpha = 0.99439986968132  const Factor for magnitude approximation
68 static const WebRtc_UWord16 kAlpha1 = 32584;
69 //Q15 beta = 0.12967166976970   const Factor for magnitude approximation
70 static const WebRtc_UWord16 kBeta1 = 4249;
71 //Q15 alpha = 0.94234827210087  const Factor for magnitude approximation
72 static const WebRtc_UWord16 kAlpha2 = 30879;
73 //Q15 beta = 0.33787806009150   const Factor for magnitude approximation
74 static const WebRtc_UWord16 kBeta2 = 11072;
75 //Q15 alpha = 0.82247698684306  const Factor for magnitude approximation
76 static const WebRtc_UWord16 kAlpha3 = 26951;
77 //Q15 beta = 0.57762063060713   const Factor for magnitude approximation
78 static const WebRtc_UWord16 kBeta3 = 18927;
79 
80 // Initialization table for echo channel in 8 kHz
81 static const WebRtc_Word16 kChannelStored8kHz[PART_LEN1] = {
82     2040,   1815,   1590,   1498,   1405,   1395,   1385,   1418,
83     1451,   1506,   1562,   1644,   1726,   1804,   1882,   1918,
84     1953,   1982,   2010,   2025,   2040,   2034,   2027,   2021,
85     2014,   1997,   1980,   1925,   1869,   1800,   1732,   1683,
86     1635,   1604,   1572,   1545,   1517,   1481,   1444,   1405,
87     1367,   1331,   1294,   1270,   1245,   1239,   1233,   1247,
88     1260,   1282,   1303,   1338,   1373,   1407,   1441,   1470,
89     1499,   1524,   1549,   1565,   1582,   1601,   1621,   1649,
90     1676
91 };
92 
93 // Initialization table for echo channel in 16 kHz
94 static const WebRtc_Word16 kChannelStored16kHz[PART_LEN1] = {
95     2040,   1590,   1405,   1385,   1451,   1562,   1726,   1882,
96     1953,   2010,   2040,   2027,   2014,   1980,   1869,   1732,
97     1635,   1572,   1517,   1444,   1367,   1294,   1245,   1233,
98     1260,   1303,   1373,   1441,   1499,   1549,   1582,   1621,
99     1676,   1741,   1802,   1861,   1921,   1983,   2040,   2102,
100     2170,   2265,   2375,   2515,   2651,   2781,   2922,   3075,
101     3253,   3471,   3738,   3976,   4151,   4258,   4308,   4288,
102     4270,   4253,   4237,   4179,   4086,   3947,   3757,   3484,
103     3153
104 };
105 
106 static const WebRtc_Word16 kCosTable[] = {
107     8192,  8190,  8187,  8180,  8172,  8160,  8147,  8130,  8112,
108     8091,  8067,  8041,  8012,  7982,  7948,  7912,  7874,  7834,
109     7791,  7745,  7697,  7647,  7595,  7540,  7483,  7424,  7362,
110     7299,  7233,  7164,  7094,  7021,  6947,  6870,  6791,  6710,
111     6627,  6542,  6455,  6366,  6275,  6182,  6087,  5991,  5892,
112     5792,  5690,  5586,  5481,  5374,  5265,  5155,  5043,  4930,
113     4815,  4698,  4580,  4461,  4341,  4219,  4096,  3971,  3845,
114     3719,  3591,  3462,  3331,  3200,  3068,  2935,  2801,  2667,
115     2531,  2395,  2258,  2120,  1981,  1842,  1703,  1563,  1422,
116     1281,  1140,   998,   856,   713,   571,   428,   285,   142,
117        0,  -142,  -285,  -428,  -571,  -713,  -856,  -998, -1140,
118    -1281, -1422, -1563, -1703, -1842, -1981, -2120, -2258, -2395,
119    -2531, -2667, -2801, -2935, -3068, -3200, -3331, -3462, -3591,
120    -3719, -3845, -3971, -4095, -4219, -4341, -4461, -4580, -4698,
121    -4815, -4930, -5043, -5155, -5265, -5374, -5481, -5586, -5690,
122    -5792, -5892, -5991, -6087, -6182, -6275, -6366, -6455, -6542,
123    -6627, -6710, -6791, -6870, -6947, -7021, -7094, -7164, -7233,
124    -7299, -7362, -7424, -7483, -7540, -7595, -7647, -7697, -7745,
125    -7791, -7834, -7874, -7912, -7948, -7982, -8012, -8041, -8067,
126    -8091, -8112, -8130, -8147, -8160, -8172, -8180, -8187, -8190,
127    -8191, -8190, -8187, -8180, -8172, -8160, -8147, -8130, -8112,
128    -8091, -8067, -8041, -8012, -7982, -7948, -7912, -7874, -7834,
129    -7791, -7745, -7697, -7647, -7595, -7540, -7483, -7424, -7362,
130    -7299, -7233, -7164, -7094, -7021, -6947, -6870, -6791, -6710,
131    -6627, -6542, -6455, -6366, -6275, -6182, -6087, -5991, -5892,
132    -5792, -5690, -5586, -5481, -5374, -5265, -5155, -5043, -4930,
133    -4815, -4698, -4580, -4461, -4341, -4219, -4096, -3971, -3845,
134    -3719, -3591, -3462, -3331, -3200, -3068, -2935, -2801, -2667,
135    -2531, -2395, -2258, -2120, -1981, -1842, -1703, -1563, -1422,
136    -1281, -1140,  -998,  -856,  -713,  -571,  -428,  -285,  -142,
137        0,   142,   285,   428,   571,   713,   856,   998,  1140,
138     1281,  1422,  1563,  1703,  1842,  1981,  2120,  2258,  2395,
139     2531,  2667,  2801,  2935,  3068,  3200,  3331,  3462,  3591,
140     3719,  3845,  3971,  4095,  4219,  4341,  4461,  4580,  4698,
141     4815,  4930,  5043,  5155,  5265,  5374,  5481,  5586,  5690,
142     5792,  5892,  5991,  6087,  6182,  6275,  6366,  6455,  6542,
143     6627,  6710,  6791,  6870,  6947,  7021,  7094,  7164,  7233,
144     7299,  7362,  7424,  7483,  7540,  7595,  7647,  7697,  7745,
145     7791,  7834,  7874,  7912,  7948,  7982,  8012,  8041,  8067,
146     8091,  8112,  8130,  8147,  8160,  8172,  8180,  8187,  8190
147 };
148 
149 static const WebRtc_Word16 kSinTable[] = {
150        0,    142,    285,    428,    571,    713,    856,    998,
151     1140,   1281,   1422,   1563,   1703,   1842,   1981,   2120,
152     2258,   2395,   2531,   2667,   2801,   2935,   3068,   3200,
153     3331,   3462,   3591,   3719,   3845,   3971,   4095,   4219,
154     4341,   4461,   4580,   4698,   4815,   4930,   5043,   5155,
155     5265,   5374,   5481,   5586,   5690,   5792,   5892,   5991,
156     6087,   6182,   6275,   6366,   6455,   6542,   6627,   6710,
157     6791,   6870,   6947,   7021,   7094,   7164,   7233,   7299,
158     7362,   7424,   7483,   7540,   7595,   7647,   7697,   7745,
159     7791,   7834,   7874,   7912,   7948,   7982,   8012,   8041,
160     8067,   8091,   8112,   8130,   8147,   8160,   8172,   8180,
161     8187,   8190,   8191,   8190,   8187,   8180,   8172,   8160,
162     8147,   8130,   8112,   8091,   8067,   8041,   8012,   7982,
163     7948,   7912,   7874,   7834,   7791,   7745,   7697,   7647,
164     7595,   7540,   7483,   7424,   7362,   7299,   7233,   7164,
165     7094,   7021,   6947,   6870,   6791,   6710,   6627,   6542,
166     6455,   6366,   6275,   6182,   6087,   5991,   5892,   5792,
167     5690,   5586,   5481,   5374,   5265,   5155,   5043,   4930,
168     4815,   4698,   4580,   4461,   4341,   4219,   4096,   3971,
169     3845,   3719,   3591,   3462,   3331,   3200,   3068,   2935,
170     2801,   2667,   2531,   2395,   2258,   2120,   1981,   1842,
171     1703,   1563,   1422,   1281,   1140,    998,    856,    713,
172      571,    428,    285,    142,      0,   -142,   -285,   -428,
173     -571,   -713,   -856,   -998,  -1140,  -1281,  -1422,  -1563,
174    -1703,  -1842,  -1981,  -2120,  -2258,  -2395,  -2531,  -2667,
175    -2801,  -2935,  -3068,  -3200,  -3331,  -3462,  -3591,  -3719,
176    -3845,  -3971,  -4095,  -4219,  -4341,  -4461,  -4580,  -4698,
177    -4815,  -4930,  -5043,  -5155,  -5265,  -5374,  -5481,  -5586,
178    -5690,  -5792,  -5892,  -5991,  -6087,  -6182,  -6275,  -6366,
179    -6455,  -6542,  -6627,  -6710,  -6791,  -6870,  -6947,  -7021,
180    -7094,  -7164,  -7233,  -7299,  -7362,  -7424,  -7483,  -7540,
181    -7595,  -7647,  -7697,  -7745,  -7791,  -7834,  -7874,  -7912,
182    -7948,  -7982,  -8012,  -8041,  -8067,  -8091,  -8112,  -8130,
183    -8147,  -8160,  -8172,  -8180,  -8187,  -8190,  -8191,  -8190,
184    -8187,  -8180,  -8172,  -8160,  -8147,  -8130,  -8112,  -8091,
185    -8067,  -8041,  -8012,  -7982,  -7948,  -7912,  -7874,  -7834,
186    -7791,  -7745,  -7697,  -7647,  -7595,  -7540,  -7483,  -7424,
187    -7362,  -7299,  -7233,  -7164,  -7094,  -7021,  -6947,  -6870,
188    -6791,  -6710,  -6627,  -6542,  -6455,  -6366,  -6275,  -6182,
189    -6087,  -5991,  -5892,  -5792,  -5690,  -5586,  -5481,  -5374,
190    -5265,  -5155,  -5043,  -4930,  -4815,  -4698,  -4580,  -4461,
191    -4341,  -4219,  -4096,  -3971,  -3845,  -3719,  -3591,  -3462,
192    -3331,  -3200,  -3068,  -2935,  -2801,  -2667,  -2531,  -2395,
193    -2258,  -2120,  -1981,  -1842,  -1703,  -1563,  -1422,  -1281,
194    -1140,   -998,   -856,   -713,   -571,   -428,   -285,   -142
195 };
196 
197 static const WebRtc_Word16 kNoiseEstQDomain = 15;
198 static const WebRtc_Word16 kNoiseEstIncCount = 5;
199 
200 static void ComfortNoise(AecmCore_t* aecm,
201                          const WebRtc_UWord16* dfa,
202                          complex16_t* out,
203                          const WebRtc_Word16* lambda);
204 
205 static WebRtc_Word16 CalcSuppressionGain(AecmCore_t * const aecm);
206 
207 // Moves the pointer to the next entry and inserts |far_spectrum| and
208 // corresponding Q-domain in its buffer.
209 //
210 // Inputs:
211 //      - self          : Pointer to the delay estimation instance
212 //      - far_spectrum  : Pointer to the far end spectrum
213 //      - far_q         : Q-domain of far end spectrum
214 //
UpdateFarHistory(AecmCore_t * self,uint16_t * far_spectrum,int far_q)215 static void UpdateFarHistory(AecmCore_t* self,
216                              uint16_t* far_spectrum,
217                              int far_q) {
218   // Get new buffer position
219   self->far_history_pos++;
220   if (self->far_history_pos >= MAX_DELAY) {
221     self->far_history_pos = 0;
222   }
223   // Update Q-domain buffer
224   self->far_q_domains[self->far_history_pos] = far_q;
225   // Update far end spectrum buffer
226   memcpy(&(self->far_history[self->far_history_pos * PART_LEN1]),
227          far_spectrum,
228          sizeof(uint16_t) * PART_LEN1);
229 }
230 
231 // Returns a pointer to the far end spectrum aligned to current near end
232 // spectrum. The function WebRtc_DelayEstimatorProcessFix(...) should have been
233 // called before AlignedFarend(...). Otherwise, you get the pointer to the
234 // previous frame. The memory is only valid until the next call of
235 // WebRtc_DelayEstimatorProcessFix(...).
236 //
237 // Inputs:
238 //      - self              : Pointer to the AECM instance.
239 //      - delay             : Current delay estimate.
240 //
241 // Output:
242 //      - far_q             : The Q-domain of the aligned far end spectrum
243 //
244 // Return value:
245 //      - far_spectrum      : Pointer to the aligned far end spectrum
246 //                            NULL - Error
247 //
AlignedFarend(AecmCore_t * self,int * far_q,int delay)248 static const uint16_t* AlignedFarend(AecmCore_t* self, int* far_q, int delay) {
249   int buffer_position = 0;
250   assert(self != NULL);
251   buffer_position = self->far_history_pos - delay;
252 
253   // Check buffer position
254   if (buffer_position < 0) {
255     buffer_position += MAX_DELAY;
256   }
257   // Get Q-domain
258   *far_q = self->far_q_domains[buffer_position];
259   // Return far end spectrum
260   return &(self->far_history[buffer_position * PART_LEN1]);
261 }
262 
263 #ifdef ARM_WINM_LOG
264 HANDLE logFile = NULL;
265 #endif
266 
267 // Declare function pointers.
268 CalcLinearEnergies WebRtcAecm_CalcLinearEnergies;
269 StoreAdaptiveChannel WebRtcAecm_StoreAdaptiveChannel;
270 ResetAdaptiveChannel WebRtcAecm_ResetAdaptiveChannel;
271 WindowAndFFT WebRtcAecm_WindowAndFFT;
272 InverseFFTAndWindow WebRtcAecm_InverseFFTAndWindow;
273 
WebRtcAecm_CreateCore(AecmCore_t ** aecmInst)274 int WebRtcAecm_CreateCore(AecmCore_t **aecmInst)
275 {
276     AecmCore_t *aecm = malloc(sizeof(AecmCore_t));
277     *aecmInst = aecm;
278     if (aecm == NULL)
279     {
280         return -1;
281     }
282 
283     if (WebRtc_CreateBuffer(&aecm->farFrameBuf, FRAME_LEN + PART_LEN,
284                             sizeof(int16_t)) == -1)
285     {
286         WebRtcAecm_FreeCore(aecm);
287         aecm = NULL;
288         return -1;
289     }
290 
291     if (WebRtc_CreateBuffer(&aecm->nearNoisyFrameBuf, FRAME_LEN + PART_LEN,
292                             sizeof(int16_t)) == -1)
293     {
294         WebRtcAecm_FreeCore(aecm);
295         aecm = NULL;
296         return -1;
297     }
298 
299     if (WebRtc_CreateBuffer(&aecm->nearCleanFrameBuf, FRAME_LEN + PART_LEN,
300                             sizeof(int16_t)) == -1)
301     {
302         WebRtcAecm_FreeCore(aecm);
303         aecm = NULL;
304         return -1;
305     }
306 
307     if (WebRtc_CreateBuffer(&aecm->outFrameBuf, FRAME_LEN + PART_LEN,
308                             sizeof(int16_t)) == -1)
309     {
310         WebRtcAecm_FreeCore(aecm);
311         aecm = NULL;
312         return -1;
313     }
314 
315     if (WebRtc_CreateDelayEstimator(&aecm->delay_estimator,
316                                     PART_LEN1,
317                                     MAX_DELAY,
318                                     0) == -1) {
319       WebRtcAecm_FreeCore(aecm);
320       aecm = NULL;
321       return -1;
322     }
323 
324     // Init some aecm pointers. 16 and 32 byte alignment is only necessary
325     // for Neon code currently.
326     aecm->xBuf = (WebRtc_Word16*) (((uintptr_t)aecm->xBuf_buf + 31) & ~ 31);
327     aecm->dBufClean = (WebRtc_Word16*) (((uintptr_t)aecm->dBufClean_buf + 31) & ~ 31);
328     aecm->dBufNoisy = (WebRtc_Word16*) (((uintptr_t)aecm->dBufNoisy_buf + 31) & ~ 31);
329     aecm->outBuf = (WebRtc_Word16*) (((uintptr_t)aecm->outBuf_buf + 15) & ~ 15);
330     aecm->channelStored = (WebRtc_Word16*) (((uintptr_t)
331                                              aecm->channelStored_buf + 15) & ~ 15);
332     aecm->channelAdapt16 = (WebRtc_Word16*) (((uintptr_t)
333                                               aecm->channelAdapt16_buf + 15) & ~ 15);
334     aecm->channelAdapt32 = (WebRtc_Word32*) (((uintptr_t)
335                                               aecm->channelAdapt32_buf + 31) & ~ 31);
336 
337     return 0;
338 }
339 
WebRtcAecm_InitEchoPathCore(AecmCore_t * aecm,const WebRtc_Word16 * echo_path)340 void WebRtcAecm_InitEchoPathCore(AecmCore_t* aecm, const WebRtc_Word16* echo_path)
341 {
342     int i = 0;
343 
344     // Reset the stored channel
345     memcpy(aecm->channelStored, echo_path, sizeof(WebRtc_Word16) * PART_LEN1);
346     // Reset the adapted channels
347     memcpy(aecm->channelAdapt16, echo_path, sizeof(WebRtc_Word16) * PART_LEN1);
348     for (i = 0; i < PART_LEN1; i++)
349     {
350         aecm->channelAdapt32[i] = WEBRTC_SPL_LSHIFT_W32(
351             (WebRtc_Word32)(aecm->channelAdapt16[i]), 16);
352     }
353 
354     // Reset channel storing variables
355     aecm->mseAdaptOld = 1000;
356     aecm->mseStoredOld = 1000;
357     aecm->mseThreshold = WEBRTC_SPL_WORD32_MAX;
358     aecm->mseChannelCount = 0;
359 }
360 
WindowAndFFTC(WebRtc_Word16 * fft,const WebRtc_Word16 * time_signal,complex16_t * freq_signal,int time_signal_scaling)361 static void WindowAndFFTC(WebRtc_Word16* fft,
362                           const WebRtc_Word16* time_signal,
363                           complex16_t* freq_signal,
364                           int time_signal_scaling)
365 {
366     int i, j;
367 
368     memset(fft, 0, sizeof(WebRtc_Word16) * PART_LEN4);
369     // FFT of signal
370     for (i = 0, j = 0; i < PART_LEN; i++, j += 2)
371     {
372         // Window time domain signal and insert into real part of
373         // transformation array |fft|
374         fft[j] = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(
375             (time_signal[i] << time_signal_scaling),
376             WebRtcAecm_kSqrtHanning[i],
377             14);
378         fft[PART_LEN2 + j] = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(
379             (time_signal[i + PART_LEN] << time_signal_scaling),
380             WebRtcAecm_kSqrtHanning[PART_LEN - i],
381             14);
382         // Inserting zeros in imaginary parts not necessary since we
383         // initialized the array with all zeros
384     }
385 
386     WebRtcSpl_ComplexBitReverse(fft, PART_LEN_SHIFT);
387     WebRtcSpl_ComplexFFT(fft, PART_LEN_SHIFT, 1);
388 
389     // Take only the first PART_LEN2 samples
390     for (i = 0, j = 0; j < PART_LEN2; i += 1, j += 2)
391     {
392         freq_signal[i].real = fft[j];
393 
394         // The imaginary part has to switch sign
395         freq_signal[i].imag = - fft[j+1];
396     }
397 }
398 
InverseFFTAndWindowC(AecmCore_t * aecm,WebRtc_Word16 * fft,complex16_t * efw,WebRtc_Word16 * output,const WebRtc_Word16 * nearendClean)399 static void InverseFFTAndWindowC(AecmCore_t* aecm,
400                                  WebRtc_Word16* fft,
401                                  complex16_t* efw,
402                                  WebRtc_Word16* output,
403                                  const WebRtc_Word16* nearendClean)
404 {
405     int i, j, outCFFT;
406     WebRtc_Word32 tmp32no1;
407 
408     // Synthesis
409     for (i = 1; i < PART_LEN; i++)
410     {
411         j = WEBRTC_SPL_LSHIFT_W32(i, 1);
412         fft[j] = efw[i].real;
413 
414         // mirrored data, even
415         fft[PART_LEN4 - j] = efw[i].real;
416         fft[j + 1] = -efw[i].imag;
417 
418         //mirrored data, odd
419         fft[PART_LEN4 - (j - 1)] = efw[i].imag;
420     }
421     fft[0] = efw[0].real;
422     fft[1] = -efw[0].imag;
423 
424     fft[PART_LEN2] = efw[PART_LEN].real;
425     fft[PART_LEN2 + 1] = -efw[PART_LEN].imag;
426 
427     // inverse FFT, result should be scaled with outCFFT
428     WebRtcSpl_ComplexBitReverse(fft, PART_LEN_SHIFT);
429     outCFFT = WebRtcSpl_ComplexIFFT(fft, PART_LEN_SHIFT, 1);
430 
431     //take only the real values and scale with outCFFT
432     for (i = 0; i < PART_LEN2; i++)
433     {
434         j = WEBRTC_SPL_LSHIFT_W32(i, 1);
435         fft[i] = fft[j];
436     }
437 
438     for (i = 0; i < PART_LEN; i++)
439     {
440         fft[i] = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND(
441                 fft[i],
442                 WebRtcAecm_kSqrtHanning[i],
443                 14);
444         tmp32no1 = WEBRTC_SPL_SHIFT_W32((WebRtc_Word32)fft[i],
445                 outCFFT - aecm->dfaCleanQDomain);
446         fft[i] = (WebRtc_Word16)WEBRTC_SPL_SAT(WEBRTC_SPL_WORD16_MAX,
447                 tmp32no1 + aecm->outBuf[i],
448                 WEBRTC_SPL_WORD16_MIN);
449         output[i] = fft[i];
450 
451         tmp32no1 = WEBRTC_SPL_MUL_16_16_RSFT(
452                 fft[PART_LEN + i],
453                 WebRtcAecm_kSqrtHanning[PART_LEN - i],
454                 14);
455         tmp32no1 = WEBRTC_SPL_SHIFT_W32(tmp32no1,
456                 outCFFT - aecm->dfaCleanQDomain);
457         aecm->outBuf[i] = (WebRtc_Word16)WEBRTC_SPL_SAT(
458                 WEBRTC_SPL_WORD16_MAX,
459                 tmp32no1,
460                 WEBRTC_SPL_WORD16_MIN);
461     }
462 
463 #ifdef ARM_WINM_LOG_
464     // measure tick end
465     QueryPerformanceCounter((LARGE_INTEGER*)&end);
466     diff__ = ((end - start) * 1000) / (freq/1000);
467     milliseconds = (unsigned int)(diff__ & 0xffffffff);
468     WriteFile (logFile, &milliseconds, sizeof(unsigned int), &temp, NULL);
469 #endif
470 
471     // Copy the current block to the old position (aecm->outBuf is shifted elsewhere)
472     memcpy(aecm->xBuf, aecm->xBuf + PART_LEN, sizeof(WebRtc_Word16) * PART_LEN);
473     memcpy(aecm->dBufNoisy, aecm->dBufNoisy + PART_LEN, sizeof(WebRtc_Word16) * PART_LEN);
474     if (nearendClean != NULL)
475     {
476         memcpy(aecm->dBufClean, aecm->dBufClean + PART_LEN, sizeof(WebRtc_Word16) * PART_LEN);
477     }
478 }
479 
CalcLinearEnergiesC(AecmCore_t * aecm,const WebRtc_UWord16 * far_spectrum,WebRtc_Word32 * echo_est,WebRtc_UWord32 * far_energy,WebRtc_UWord32 * echo_energy_adapt,WebRtc_UWord32 * echo_energy_stored)480 static void CalcLinearEnergiesC(AecmCore_t* aecm,
481                                 const WebRtc_UWord16* far_spectrum,
482                                 WebRtc_Word32* echo_est,
483                                 WebRtc_UWord32* far_energy,
484                                 WebRtc_UWord32* echo_energy_adapt,
485                                 WebRtc_UWord32* echo_energy_stored)
486 {
487     int i;
488 
489     // Get energy for the delayed far end signal and estimated
490     // echo using both stored and adapted channels.
491     for (i = 0; i < PART_LEN1; i++)
492     {
493         echo_est[i] = WEBRTC_SPL_MUL_16_U16(aecm->channelStored[i],
494                                            far_spectrum[i]);
495         (*far_energy) += (WebRtc_UWord32)(far_spectrum[i]);
496         (*echo_energy_adapt) += WEBRTC_SPL_UMUL_16_16(aecm->channelAdapt16[i],
497                                           far_spectrum[i]);
498         (*echo_energy_stored) += (WebRtc_UWord32)echo_est[i];
499     }
500 }
501 
StoreAdaptiveChannelC(AecmCore_t * aecm,const WebRtc_UWord16 * far_spectrum,WebRtc_Word32 * echo_est)502 static void StoreAdaptiveChannelC(AecmCore_t* aecm,
503                                   const WebRtc_UWord16* far_spectrum,
504                                   WebRtc_Word32* echo_est)
505 {
506     int i;
507 
508     // During startup we store the channel every block.
509     memcpy(aecm->channelStored, aecm->channelAdapt16, sizeof(WebRtc_Word16) * PART_LEN1);
510     // Recalculate echo estimate
511     for (i = 0; i < PART_LEN; i += 4)
512     {
513         echo_est[i] = WEBRTC_SPL_MUL_16_U16(aecm->channelStored[i],
514                                            far_spectrum[i]);
515         echo_est[i + 1] = WEBRTC_SPL_MUL_16_U16(aecm->channelStored[i + 1],
516                                            far_spectrum[i + 1]);
517         echo_est[i + 2] = WEBRTC_SPL_MUL_16_U16(aecm->channelStored[i + 2],
518                                            far_spectrum[i + 2]);
519         echo_est[i + 3] = WEBRTC_SPL_MUL_16_U16(aecm->channelStored[i + 3],
520                                            far_spectrum[i + 3]);
521     }
522     echo_est[i] = WEBRTC_SPL_MUL_16_U16(aecm->channelStored[i],
523                                        far_spectrum[i]);
524 }
525 
ResetAdaptiveChannelC(AecmCore_t * aecm)526 static void ResetAdaptiveChannelC(AecmCore_t* aecm)
527 {
528     int i;
529 
530     // The stored channel has a significantly lower MSE than the adaptive one for
531     // two consecutive calculations. Reset the adaptive channel.
532     memcpy(aecm->channelAdapt16, aecm->channelStored,
533            sizeof(WebRtc_Word16) * PART_LEN1);
534     // Restore the W32 channel
535     for (i = 0; i < PART_LEN; i += 4)
536     {
537         aecm->channelAdapt32[i] = WEBRTC_SPL_LSHIFT_W32(
538                 (WebRtc_Word32)aecm->channelStored[i], 16);
539         aecm->channelAdapt32[i + 1] = WEBRTC_SPL_LSHIFT_W32(
540                 (WebRtc_Word32)aecm->channelStored[i + 1], 16);
541         aecm->channelAdapt32[i + 2] = WEBRTC_SPL_LSHIFT_W32(
542                 (WebRtc_Word32)aecm->channelStored[i + 2], 16);
543         aecm->channelAdapt32[i + 3] = WEBRTC_SPL_LSHIFT_W32(
544                 (WebRtc_Word32)aecm->channelStored[i + 3], 16);
545     }
546     aecm->channelAdapt32[i] = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)aecm->channelStored[i], 16);
547 }
548 
549 // WebRtcAecm_InitCore(...)
550 //
551 // This function initializes the AECM instant created with WebRtcAecm_CreateCore(...)
552 // Input:
553 //      - aecm            : Pointer to the Echo Suppression instance
554 //      - samplingFreq   : Sampling Frequency
555 //
556 // Output:
557 //      - aecm            : Initialized instance
558 //
559 // Return value         :  0 - Ok
560 //                        -1 - Error
561 //
WebRtcAecm_InitCore(AecmCore_t * const aecm,int samplingFreq)562 int WebRtcAecm_InitCore(AecmCore_t * const aecm, int samplingFreq)
563 {
564     int i = 0;
565     WebRtc_Word32 tmp32 = PART_LEN1 * PART_LEN1;
566     WebRtc_Word16 tmp16 = PART_LEN1;
567 
568     if (samplingFreq != 8000 && samplingFreq != 16000)
569     {
570         samplingFreq = 8000;
571         return -1;
572     }
573     // sanity check of sampling frequency
574     aecm->mult = (WebRtc_Word16)samplingFreq / 8000;
575 
576     aecm->farBufWritePos = 0;
577     aecm->farBufReadPos = 0;
578     aecm->knownDelay = 0;
579     aecm->lastKnownDelay = 0;
580 
581     WebRtc_InitBuffer(aecm->farFrameBuf);
582     WebRtc_InitBuffer(aecm->nearNoisyFrameBuf);
583     WebRtc_InitBuffer(aecm->nearCleanFrameBuf);
584     WebRtc_InitBuffer(aecm->outFrameBuf);
585 
586     memset(aecm->xBuf_buf, 0, sizeof(aecm->xBuf_buf));
587     memset(aecm->dBufClean_buf, 0, sizeof(aecm->dBufClean_buf));
588     memset(aecm->dBufNoisy_buf, 0, sizeof(aecm->dBufNoisy_buf));
589     memset(aecm->outBuf_buf, 0, sizeof(aecm->outBuf_buf));
590 
591     aecm->seed = 666;
592     aecm->totCount = 0;
593 
594     if (WebRtc_InitDelayEstimator(aecm->delay_estimator) != 0) {
595       return -1;
596     }
597     // Set far end histories to zero
598     memset(aecm->far_history, 0, sizeof(uint16_t) * PART_LEN1 * MAX_DELAY);
599     memset(aecm->far_q_domains, 0, sizeof(int) * MAX_DELAY);
600     aecm->far_history_pos = MAX_DELAY;
601 
602     aecm->nlpFlag = 1;
603     aecm->fixedDelay = -1;
604 
605     aecm->dfaCleanQDomain = 0;
606     aecm->dfaCleanQDomainOld = 0;
607     aecm->dfaNoisyQDomain = 0;
608     aecm->dfaNoisyQDomainOld = 0;
609 
610     memset(aecm->nearLogEnergy, 0, sizeof(aecm->nearLogEnergy));
611     aecm->farLogEnergy = 0;
612     memset(aecm->echoAdaptLogEnergy, 0, sizeof(aecm->echoAdaptLogEnergy));
613     memset(aecm->echoStoredLogEnergy, 0, sizeof(aecm->echoStoredLogEnergy));
614 
615     // Initialize the echo channels with a stored shape.
616     if (samplingFreq == 8000)
617     {
618         WebRtcAecm_InitEchoPathCore(aecm, kChannelStored8kHz);
619     }
620     else
621     {
622         WebRtcAecm_InitEchoPathCore(aecm, kChannelStored16kHz);
623     }
624 
625     memset(aecm->echoFilt, 0, sizeof(aecm->echoFilt));
626     memset(aecm->nearFilt, 0, sizeof(aecm->nearFilt));
627     aecm->noiseEstCtr = 0;
628 
629     aecm->cngMode = AecmTrue;
630 
631     memset(aecm->noiseEstTooLowCtr, 0, sizeof(aecm->noiseEstTooLowCtr));
632     memset(aecm->noiseEstTooHighCtr, 0, sizeof(aecm->noiseEstTooHighCtr));
633     // Shape the initial noise level to an approximate pink noise.
634     for (i = 0; i < (PART_LEN1 >> 1) - 1; i++)
635     {
636         aecm->noiseEst[i] = (tmp32 << 8);
637         tmp16--;
638         tmp32 -= (WebRtc_Word32)((tmp16 << 1) + 1);
639     }
640     for (; i < PART_LEN1; i++)
641     {
642         aecm->noiseEst[i] = (tmp32 << 8);
643     }
644 
645     aecm->farEnergyMin = WEBRTC_SPL_WORD16_MAX;
646     aecm->farEnergyMax = WEBRTC_SPL_WORD16_MIN;
647     aecm->farEnergyMaxMin = 0;
648     aecm->farEnergyVAD = FAR_ENERGY_MIN; // This prevents false speech detection at the
649                                          // beginning.
650     aecm->farEnergyMSE = 0;
651     aecm->currentVADValue = 0;
652     aecm->vadUpdateCount = 0;
653     aecm->firstVAD = 1;
654 
655     aecm->startupState = 0;
656     aecm->supGain = SUPGAIN_DEFAULT;
657     aecm->supGainOld = SUPGAIN_DEFAULT;
658 
659     aecm->supGainErrParamA = SUPGAIN_ERROR_PARAM_A;
660     aecm->supGainErrParamD = SUPGAIN_ERROR_PARAM_D;
661     aecm->supGainErrParamDiffAB = SUPGAIN_ERROR_PARAM_A - SUPGAIN_ERROR_PARAM_B;
662     aecm->supGainErrParamDiffBD = SUPGAIN_ERROR_PARAM_B - SUPGAIN_ERROR_PARAM_D;
663 
664     assert(PART_LEN % 16 == 0);
665 
666     // Initialize function pointers.
667     WebRtcAecm_WindowAndFFT = WindowAndFFTC;
668     WebRtcAecm_InverseFFTAndWindow = InverseFFTAndWindowC;
669     WebRtcAecm_CalcLinearEnergies = CalcLinearEnergiesC;
670     WebRtcAecm_StoreAdaptiveChannel = StoreAdaptiveChannelC;
671     WebRtcAecm_ResetAdaptiveChannel = ResetAdaptiveChannelC;
672 
673 #ifdef WEBRTC_DETECT_ARM_NEON
674     uint64_t features = WebRtc_GetCPUFeaturesARM();
675     if ((features & kCPUFeatureNEON) != 0)
676     {
677         WebRtcAecm_InitNeon();
678     }
679 #elif defined(WEBRTC_ARCH_ARM_NEON)
680     WebRtcAecm_InitNeon();
681 #endif
682 
683     return 0;
684 }
685 
686 // TODO(bjornv): This function is currently not used. Add support for these
687 // parameters from a higher level
WebRtcAecm_Control(AecmCore_t * aecm,int delay,int nlpFlag)688 int WebRtcAecm_Control(AecmCore_t *aecm, int delay, int nlpFlag)
689 {
690     aecm->nlpFlag = nlpFlag;
691     aecm->fixedDelay = delay;
692 
693     return 0;
694 }
695 
WebRtcAecm_FreeCore(AecmCore_t * aecm)696 int WebRtcAecm_FreeCore(AecmCore_t *aecm)
697 {
698     if (aecm == NULL)
699     {
700         return -1;
701     }
702 
703     WebRtc_FreeBuffer(aecm->farFrameBuf);
704     WebRtc_FreeBuffer(aecm->nearNoisyFrameBuf);
705     WebRtc_FreeBuffer(aecm->nearCleanFrameBuf);
706     WebRtc_FreeBuffer(aecm->outFrameBuf);
707 
708     WebRtc_FreeDelayEstimator(aecm->delay_estimator);
709     free(aecm);
710 
711     return 0;
712 }
713 
WebRtcAecm_ProcessFrame(AecmCore_t * aecm,const WebRtc_Word16 * farend,const WebRtc_Word16 * nearendNoisy,const WebRtc_Word16 * nearendClean,WebRtc_Word16 * out)714 int WebRtcAecm_ProcessFrame(AecmCore_t * aecm,
715                             const WebRtc_Word16 * farend,
716                             const WebRtc_Word16 * nearendNoisy,
717                             const WebRtc_Word16 * nearendClean,
718                             WebRtc_Word16 * out)
719 {
720     WebRtc_Word16 outBlock_buf[PART_LEN + 8]; // Align buffer to 8-byte boundary.
721     WebRtc_Word16* outBlock = (WebRtc_Word16*) (((uintptr_t) outBlock_buf + 15) & ~ 15);
722 
723     WebRtc_Word16 farFrame[FRAME_LEN];
724     const int16_t* out_ptr = NULL;
725     int size = 0;
726 
727     // Buffer the current frame.
728     // Fetch an older one corresponding to the delay.
729     WebRtcAecm_BufferFarFrame(aecm, farend, FRAME_LEN);
730     WebRtcAecm_FetchFarFrame(aecm, farFrame, FRAME_LEN, aecm->knownDelay);
731 
732     // Buffer the synchronized far and near frames,
733     // to pass the smaller blocks individually.
734     WebRtc_WriteBuffer(aecm->farFrameBuf, farFrame, FRAME_LEN);
735     WebRtc_WriteBuffer(aecm->nearNoisyFrameBuf, nearendNoisy, FRAME_LEN);
736     if (nearendClean != NULL)
737     {
738         WebRtc_WriteBuffer(aecm->nearCleanFrameBuf, nearendClean, FRAME_LEN);
739     }
740 
741     // Process as many blocks as possible.
742     while (WebRtc_available_read(aecm->farFrameBuf) >= PART_LEN)
743     {
744         int16_t far_block[PART_LEN];
745         const int16_t* far_block_ptr = NULL;
746         int16_t near_noisy_block[PART_LEN];
747         const int16_t* near_noisy_block_ptr = NULL;
748 
749         WebRtc_ReadBuffer(aecm->farFrameBuf, (void**) &far_block_ptr, far_block,
750                           PART_LEN);
751         WebRtc_ReadBuffer(aecm->nearNoisyFrameBuf,
752                           (void**) &near_noisy_block_ptr,
753                           near_noisy_block,
754                           PART_LEN);
755         if (nearendClean != NULL)
756         {
757             int16_t near_clean_block[PART_LEN];
758             const int16_t* near_clean_block_ptr = NULL;
759 
760             WebRtc_ReadBuffer(aecm->nearCleanFrameBuf,
761                               (void**) &near_clean_block_ptr,
762                               near_clean_block,
763                               PART_LEN);
764             if (WebRtcAecm_ProcessBlock(aecm,
765                                         far_block_ptr,
766                                         near_noisy_block_ptr,
767                                         near_clean_block_ptr,
768                                         outBlock) == -1)
769             {
770                 return -1;
771             }
772         } else
773         {
774             if (WebRtcAecm_ProcessBlock(aecm,
775                                         far_block_ptr,
776                                         near_noisy_block_ptr,
777                                         NULL,
778                                         outBlock) == -1)
779             {
780                 return -1;
781             }
782         }
783 
784         WebRtc_WriteBuffer(aecm->outFrameBuf, outBlock, PART_LEN);
785     }
786 
787     // Stuff the out buffer if we have less than a frame to output.
788     // This should only happen for the first frame.
789     size = (int) WebRtc_available_read(aecm->outFrameBuf);
790     if (size < FRAME_LEN)
791     {
792         WebRtc_MoveReadPtr(aecm->outFrameBuf, size - FRAME_LEN);
793     }
794 
795     // Obtain an output frame.
796     WebRtc_ReadBuffer(aecm->outFrameBuf, (void**) &out_ptr, out, FRAME_LEN);
797     if (out_ptr != out) {
798       // ReadBuffer() hasn't copied to |out| in this case.
799       memcpy(out, out_ptr, FRAME_LEN * sizeof(int16_t));
800     }
801 
802     return 0;
803 }
804 
805 // WebRtcAecm_AsymFilt(...)
806 //
807 // Performs asymmetric filtering.
808 //
809 // Inputs:
810 //      - filtOld       : Previous filtered value.
811 //      - inVal         : New input value.
812 //      - stepSizePos   : Step size when we have a positive contribution.
813 //      - stepSizeNeg   : Step size when we have a negative contribution.
814 //
815 // Output:
816 //
817 // Return: - Filtered value.
818 //
WebRtcAecm_AsymFilt(const WebRtc_Word16 filtOld,const WebRtc_Word16 inVal,const WebRtc_Word16 stepSizePos,const WebRtc_Word16 stepSizeNeg)819 WebRtc_Word16 WebRtcAecm_AsymFilt(const WebRtc_Word16 filtOld, const WebRtc_Word16 inVal,
820                                   const WebRtc_Word16 stepSizePos,
821                                   const WebRtc_Word16 stepSizeNeg)
822 {
823     WebRtc_Word16 retVal;
824 
825     if ((filtOld == WEBRTC_SPL_WORD16_MAX) | (filtOld == WEBRTC_SPL_WORD16_MIN))
826     {
827         return inVal;
828     }
829     retVal = filtOld;
830     if (filtOld > inVal)
831     {
832         retVal -= WEBRTC_SPL_RSHIFT_W16(filtOld - inVal, stepSizeNeg);
833     } else
834     {
835         retVal += WEBRTC_SPL_RSHIFT_W16(inVal - filtOld, stepSizePos);
836     }
837 
838     return retVal;
839 }
840 
841 // WebRtcAecm_CalcEnergies(...)
842 //
843 // This function calculates the log of energies for nearend, farend and estimated
844 // echoes. There is also an update of energy decision levels, i.e. internal VAD.
845 //
846 //
847 // @param  aecm         [i/o]   Handle of the AECM instance.
848 // @param  far_spectrum [in]    Pointer to farend spectrum.
849 // @param  far_q        [in]    Q-domain of farend spectrum.
850 // @param  nearEner     [in]    Near end energy for current block in
851 //                              Q(aecm->dfaQDomain).
852 // @param  echoEst      [out]   Estimated echo in Q(xfa_q+RESOLUTION_CHANNEL16).
853 //
WebRtcAecm_CalcEnergies(AecmCore_t * aecm,const WebRtc_UWord16 * far_spectrum,const WebRtc_Word16 far_q,const WebRtc_UWord32 nearEner,WebRtc_Word32 * echoEst)854 void WebRtcAecm_CalcEnergies(AecmCore_t * aecm,
855                              const WebRtc_UWord16* far_spectrum,
856                              const WebRtc_Word16 far_q,
857                              const WebRtc_UWord32 nearEner,
858                              WebRtc_Word32 * echoEst)
859 {
860     // Local variables
861     WebRtc_UWord32 tmpAdapt = 0;
862     WebRtc_UWord32 tmpStored = 0;
863     WebRtc_UWord32 tmpFar = 0;
864 
865     int i;
866 
867     WebRtc_Word16 zeros, frac;
868     WebRtc_Word16 tmp16;
869     WebRtc_Word16 increase_max_shifts = 4;
870     WebRtc_Word16 decrease_max_shifts = 11;
871     WebRtc_Word16 increase_min_shifts = 11;
872     WebRtc_Word16 decrease_min_shifts = 3;
873     WebRtc_Word16 kLogLowValue = WEBRTC_SPL_LSHIFT_W16(PART_LEN_SHIFT, 7);
874 
875     // Get log of near end energy and store in buffer
876 
877     // Shift buffer
878     memmove(aecm->nearLogEnergy + 1, aecm->nearLogEnergy,
879             sizeof(WebRtc_Word16) * (MAX_BUF_LEN - 1));
880 
881     // Logarithm of integrated magnitude spectrum (nearEner)
882     tmp16 = kLogLowValue;
883     if (nearEner)
884     {
885         zeros = WebRtcSpl_NormU32(nearEner);
886         frac = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_U32(
887                               (WEBRTC_SPL_LSHIFT_U32(nearEner, zeros) & 0x7FFFFFFF),
888                               23);
889         // log2 in Q8
890         tmp16 += WEBRTC_SPL_LSHIFT_W16((31 - zeros), 8) + frac;
891         tmp16 -= WEBRTC_SPL_LSHIFT_W16(aecm->dfaNoisyQDomain, 8);
892     }
893     aecm->nearLogEnergy[0] = tmp16;
894     // END: Get log of near end energy
895 
896     WebRtcAecm_CalcLinearEnergies(aecm, far_spectrum, echoEst, &tmpFar, &tmpAdapt, &tmpStored);
897 
898     // Shift buffers
899     memmove(aecm->echoAdaptLogEnergy + 1, aecm->echoAdaptLogEnergy,
900             sizeof(WebRtc_Word16) * (MAX_BUF_LEN - 1));
901     memmove(aecm->echoStoredLogEnergy + 1, aecm->echoStoredLogEnergy,
902             sizeof(WebRtc_Word16) * (MAX_BUF_LEN - 1));
903 
904     // Logarithm of delayed far end energy
905     tmp16 = kLogLowValue;
906     if (tmpFar)
907     {
908         zeros = WebRtcSpl_NormU32(tmpFar);
909         frac = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_U32((WEBRTC_SPL_LSHIFT_U32(tmpFar, zeros)
910                         & 0x7FFFFFFF), 23);
911         // log2 in Q8
912         tmp16 += WEBRTC_SPL_LSHIFT_W16((31 - zeros), 8) + frac;
913         tmp16 -= WEBRTC_SPL_LSHIFT_W16(far_q, 8);
914     }
915     aecm->farLogEnergy = tmp16;
916 
917     // Logarithm of estimated echo energy through adapted channel
918     tmp16 = kLogLowValue;
919     if (tmpAdapt)
920     {
921         zeros = WebRtcSpl_NormU32(tmpAdapt);
922         frac = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_U32((WEBRTC_SPL_LSHIFT_U32(tmpAdapt, zeros)
923                         & 0x7FFFFFFF), 23);
924         //log2 in Q8
925         tmp16 += WEBRTC_SPL_LSHIFT_W16((31 - zeros), 8) + frac;
926         tmp16 -= WEBRTC_SPL_LSHIFT_W16(RESOLUTION_CHANNEL16 + far_q, 8);
927     }
928     aecm->echoAdaptLogEnergy[0] = tmp16;
929 
930     // Logarithm of estimated echo energy through stored channel
931     tmp16 = kLogLowValue;
932     if (tmpStored)
933     {
934         zeros = WebRtcSpl_NormU32(tmpStored);
935         frac = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_U32((WEBRTC_SPL_LSHIFT_U32(tmpStored, zeros)
936                         & 0x7FFFFFFF), 23);
937         //log2 in Q8
938         tmp16 += WEBRTC_SPL_LSHIFT_W16((31 - zeros), 8) + frac;
939         tmp16 -= WEBRTC_SPL_LSHIFT_W16(RESOLUTION_CHANNEL16 + far_q, 8);
940     }
941     aecm->echoStoredLogEnergy[0] = tmp16;
942 
943     // Update farend energy levels (min, max, vad, mse)
944     if (aecm->farLogEnergy > FAR_ENERGY_MIN)
945     {
946         if (aecm->startupState == 0)
947         {
948             increase_max_shifts = 2;
949             decrease_min_shifts = 2;
950             increase_min_shifts = 8;
951         }
952 
953         aecm->farEnergyMin = WebRtcAecm_AsymFilt(aecm->farEnergyMin, aecm->farLogEnergy,
954                                                  increase_min_shifts, decrease_min_shifts);
955         aecm->farEnergyMax = WebRtcAecm_AsymFilt(aecm->farEnergyMax, aecm->farLogEnergy,
956                                                  increase_max_shifts, decrease_max_shifts);
957         aecm->farEnergyMaxMin = (aecm->farEnergyMax - aecm->farEnergyMin);
958 
959         // Dynamic VAD region size
960         tmp16 = 2560 - aecm->farEnergyMin;
961         if (tmp16 > 0)
962         {
963             tmp16 = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(tmp16, FAR_ENERGY_VAD_REGION, 9);
964         } else
965         {
966             tmp16 = 0;
967         }
968         tmp16 += FAR_ENERGY_VAD_REGION;
969 
970         if ((aecm->startupState == 0) | (aecm->vadUpdateCount > 1024))
971         {
972             // In startup phase or VAD update halted
973             aecm->farEnergyVAD = aecm->farEnergyMin + tmp16;
974         } else
975         {
976             if (aecm->farEnergyVAD > aecm->farLogEnergy)
977             {
978                 aecm->farEnergyVAD += WEBRTC_SPL_RSHIFT_W16(aecm->farLogEnergy +
979                                                             tmp16 -
980                                                             aecm->farEnergyVAD,
981                                                             6);
982                 aecm->vadUpdateCount = 0;
983             } else
984             {
985                 aecm->vadUpdateCount++;
986             }
987         }
988         // Put MSE threshold higher than VAD
989         aecm->farEnergyMSE = aecm->farEnergyVAD + (1 << 8);
990     }
991 
992     // Update VAD variables
993     if (aecm->farLogEnergy > aecm->farEnergyVAD)
994     {
995         if ((aecm->startupState == 0) | (aecm->farEnergyMaxMin > FAR_ENERGY_DIFF))
996         {
997             // We are in startup or have significant dynamics in input speech level
998             aecm->currentVADValue = 1;
999         }
1000     } else
1001     {
1002         aecm->currentVADValue = 0;
1003     }
1004     if ((aecm->currentVADValue) && (aecm->firstVAD))
1005     {
1006         aecm->firstVAD = 0;
1007         if (aecm->echoAdaptLogEnergy[0] > aecm->nearLogEnergy[0])
1008         {
1009             // The estimated echo has higher energy than the near end signal.
1010             // This means that the initialization was too aggressive. Scale
1011             // down by a factor 8
1012             for (i = 0; i < PART_LEN1; i++)
1013             {
1014                 aecm->channelAdapt16[i] >>= 3;
1015             }
1016             // Compensate the adapted echo energy level accordingly.
1017             aecm->echoAdaptLogEnergy[0] -= (3 << 8);
1018             aecm->firstVAD = 1;
1019         }
1020     }
1021 }
1022 
1023 // WebRtcAecm_CalcStepSize(...)
1024 //
1025 // This function calculates the step size used in channel estimation
1026 //
1027 //
1028 // @param  aecm  [in]    Handle of the AECM instance.
1029 // @param  mu    [out]   (Return value) Stepsize in log2(), i.e. number of shifts.
1030 //
1031 //
WebRtcAecm_CalcStepSize(AecmCore_t * const aecm)1032 WebRtc_Word16 WebRtcAecm_CalcStepSize(AecmCore_t * const aecm)
1033 {
1034 
1035     WebRtc_Word32 tmp32;
1036     WebRtc_Word16 tmp16;
1037     WebRtc_Word16 mu = MU_MAX;
1038 
1039     // Here we calculate the step size mu used in the
1040     // following NLMS based Channel estimation algorithm
1041     if (!aecm->currentVADValue)
1042     {
1043         // Far end energy level too low, no channel update
1044         mu = 0;
1045     } else if (aecm->startupState > 0)
1046     {
1047         if (aecm->farEnergyMin >= aecm->farEnergyMax)
1048         {
1049             mu = MU_MIN;
1050         } else
1051         {
1052             tmp16 = (aecm->farLogEnergy - aecm->farEnergyMin);
1053             tmp32 = WEBRTC_SPL_MUL_16_16(tmp16, MU_DIFF);
1054             tmp32 = WebRtcSpl_DivW32W16(tmp32, aecm->farEnergyMaxMin);
1055             mu = MU_MIN - 1 - (WebRtc_Word16)(tmp32);
1056             // The -1 is an alternative to rounding. This way we get a larger
1057             // stepsize, so we in some sense compensate for truncation in NLMS
1058         }
1059         if (mu < MU_MAX)
1060         {
1061             mu = MU_MAX; // Equivalent with maximum step size of 2^-MU_MAX
1062         }
1063     }
1064 
1065     return mu;
1066 }
1067 
1068 // WebRtcAecm_UpdateChannel(...)
1069 //
1070 // This function performs channel estimation. NLMS and decision on channel storage.
1071 //
1072 //
1073 // @param  aecm         [i/o]   Handle of the AECM instance.
1074 // @param  far_spectrum [in]    Absolute value of the farend signal in Q(far_q)
1075 // @param  far_q        [in]    Q-domain of the farend signal
1076 // @param  dfa          [in]    Absolute value of the nearend signal (Q[aecm->dfaQDomain])
1077 // @param  mu           [in]    NLMS step size.
1078 // @param  echoEst      [i/o]   Estimated echo in Q(far_q+RESOLUTION_CHANNEL16).
1079 //
WebRtcAecm_UpdateChannel(AecmCore_t * aecm,const WebRtc_UWord16 * far_spectrum,const WebRtc_Word16 far_q,const WebRtc_UWord16 * const dfa,const WebRtc_Word16 mu,WebRtc_Word32 * echoEst)1080 void WebRtcAecm_UpdateChannel(AecmCore_t * aecm,
1081                               const WebRtc_UWord16* far_spectrum,
1082                               const WebRtc_Word16 far_q,
1083                               const WebRtc_UWord16 * const dfa,
1084                               const WebRtc_Word16 mu,
1085                               WebRtc_Word32 * echoEst)
1086 {
1087 
1088     WebRtc_UWord32 tmpU32no1, tmpU32no2;
1089     WebRtc_Word32 tmp32no1, tmp32no2;
1090     WebRtc_Word32 mseStored;
1091     WebRtc_Word32 mseAdapt;
1092 
1093     int i;
1094 
1095     WebRtc_Word16 zerosFar, zerosNum, zerosCh, zerosDfa;
1096     WebRtc_Word16 shiftChFar, shiftNum, shift2ResChan;
1097     WebRtc_Word16 tmp16no1;
1098     WebRtc_Word16 xfaQ, dfaQ;
1099 
1100     // This is the channel estimation algorithm. It is base on NLMS but has a variable step
1101     // length, which was calculated above.
1102     if (mu)
1103     {
1104         for (i = 0; i < PART_LEN1; i++)
1105         {
1106             // Determine norm of channel and farend to make sure we don't get overflow in
1107             // multiplication
1108             zerosCh = WebRtcSpl_NormU32(aecm->channelAdapt32[i]);
1109             zerosFar = WebRtcSpl_NormU32((WebRtc_UWord32)far_spectrum[i]);
1110             if (zerosCh + zerosFar > 31)
1111             {
1112                 // Multiplication is safe
1113                 tmpU32no1 = WEBRTC_SPL_UMUL_32_16(aecm->channelAdapt32[i],
1114                         far_spectrum[i]);
1115                 shiftChFar = 0;
1116             } else
1117             {
1118                 // We need to shift down before multiplication
1119                 shiftChFar = 32 - zerosCh - zerosFar;
1120                 tmpU32no1 = WEBRTC_SPL_UMUL_32_16(
1121                     WEBRTC_SPL_RSHIFT_W32(aecm->channelAdapt32[i], shiftChFar),
1122                     far_spectrum[i]);
1123             }
1124             // Determine Q-domain of numerator
1125             zerosNum = WebRtcSpl_NormU32(tmpU32no1);
1126             if (dfa[i])
1127             {
1128                 zerosDfa = WebRtcSpl_NormU32((WebRtc_UWord32)dfa[i]);
1129             } else
1130             {
1131                 zerosDfa = 32;
1132             }
1133             tmp16no1 = zerosDfa - 2 + aecm->dfaNoisyQDomain -
1134                 RESOLUTION_CHANNEL32 - far_q + shiftChFar;
1135             if (zerosNum > tmp16no1 + 1)
1136             {
1137                 xfaQ = tmp16no1;
1138                 dfaQ = zerosDfa - 2;
1139             } else
1140             {
1141                 xfaQ = zerosNum - 2;
1142                 dfaQ = RESOLUTION_CHANNEL32 + far_q - aecm->dfaNoisyQDomain -
1143                     shiftChFar + xfaQ;
1144             }
1145             // Add in the same Q-domain
1146             tmpU32no1 = WEBRTC_SPL_SHIFT_W32(tmpU32no1, xfaQ);
1147             tmpU32no2 = WEBRTC_SPL_SHIFT_W32((WebRtc_UWord32)dfa[i], dfaQ);
1148             tmp32no1 = (WebRtc_Word32)tmpU32no2 - (WebRtc_Word32)tmpU32no1;
1149             zerosNum = WebRtcSpl_NormW32(tmp32no1);
1150             if ((tmp32no1) && (far_spectrum[i] > (CHANNEL_VAD << far_q)))
1151             {
1152                 //
1153                 // Update is needed
1154                 //
1155                 // This is what we would like to compute
1156                 //
1157                 // tmp32no1 = dfa[i] - (aecm->channelAdapt[i] * far_spectrum[i])
1158                 // tmp32norm = (i + 1)
1159                 // aecm->channelAdapt[i] += (2^mu) * tmp32no1
1160                 //                        / (tmp32norm * far_spectrum[i])
1161                 //
1162 
1163                 // Make sure we don't get overflow in multiplication.
1164                 if (zerosNum + zerosFar > 31)
1165                 {
1166                     if (tmp32no1 > 0)
1167                     {
1168                         tmp32no2 = (WebRtc_Word32)WEBRTC_SPL_UMUL_32_16(tmp32no1,
1169                                                                         far_spectrum[i]);
1170                     } else
1171                     {
1172                         tmp32no2 = -(WebRtc_Word32)WEBRTC_SPL_UMUL_32_16(-tmp32no1,
1173                                                                          far_spectrum[i]);
1174                     }
1175                     shiftNum = 0;
1176                 } else
1177                 {
1178                     shiftNum = 32 - (zerosNum + zerosFar);
1179                     if (tmp32no1 > 0)
1180                     {
1181                         tmp32no2 = (WebRtc_Word32)WEBRTC_SPL_UMUL_32_16(
1182                                 WEBRTC_SPL_RSHIFT_W32(tmp32no1, shiftNum),
1183                                 far_spectrum[i]);
1184                     } else
1185                     {
1186                         tmp32no2 = -(WebRtc_Word32)WEBRTC_SPL_UMUL_32_16(
1187                                 WEBRTC_SPL_RSHIFT_W32(-tmp32no1, shiftNum),
1188                                 far_spectrum[i]);
1189                     }
1190                 }
1191                 // Normalize with respect to frequency bin
1192                 tmp32no2 = WebRtcSpl_DivW32W16(tmp32no2, i + 1);
1193                 // Make sure we are in the right Q-domain
1194                 shift2ResChan = shiftNum + shiftChFar - xfaQ - mu - ((30 - zerosFar) << 1);
1195                 if (WebRtcSpl_NormW32(tmp32no2) < shift2ResChan)
1196                 {
1197                     tmp32no2 = WEBRTC_SPL_WORD32_MAX;
1198                 } else
1199                 {
1200                     tmp32no2 = WEBRTC_SPL_SHIFT_W32(tmp32no2, shift2ResChan);
1201                 }
1202                 aecm->channelAdapt32[i] = WEBRTC_SPL_ADD_SAT_W32(aecm->channelAdapt32[i],
1203                         tmp32no2);
1204                 if (aecm->channelAdapt32[i] < 0)
1205                 {
1206                     // We can never have negative channel gain
1207                     aecm->channelAdapt32[i] = 0;
1208                 }
1209                 aecm->channelAdapt16[i]
1210                         = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(aecm->channelAdapt32[i], 16);
1211             }
1212         }
1213     }
1214     // END: Adaptive channel update
1215 
1216     // Determine if we should store or restore the channel
1217     if ((aecm->startupState == 0) & (aecm->currentVADValue))
1218     {
1219         // During startup we store the channel every block,
1220         // and we recalculate echo estimate
1221         WebRtcAecm_StoreAdaptiveChannel(aecm, far_spectrum, echoEst);
1222     } else
1223     {
1224         if (aecm->farLogEnergy < aecm->farEnergyMSE)
1225         {
1226             aecm->mseChannelCount = 0;
1227         } else
1228         {
1229             aecm->mseChannelCount++;
1230         }
1231         // Enough data for validation. Store channel if we can.
1232         if (aecm->mseChannelCount >= (MIN_MSE_COUNT + 10))
1233         {
1234             // We have enough data.
1235             // Calculate MSE of "Adapt" and "Stored" versions.
1236             // It is actually not MSE, but average absolute error.
1237             mseStored = 0;
1238             mseAdapt = 0;
1239             for (i = 0; i < MIN_MSE_COUNT; i++)
1240             {
1241                 tmp32no1 = ((WebRtc_Word32)aecm->echoStoredLogEnergy[i]
1242                         - (WebRtc_Word32)aecm->nearLogEnergy[i]);
1243                 tmp32no2 = WEBRTC_SPL_ABS_W32(tmp32no1);
1244                 mseStored += tmp32no2;
1245 
1246                 tmp32no1 = ((WebRtc_Word32)aecm->echoAdaptLogEnergy[i]
1247                         - (WebRtc_Word32)aecm->nearLogEnergy[i]);
1248                 tmp32no2 = WEBRTC_SPL_ABS_W32(tmp32no1);
1249                 mseAdapt += tmp32no2;
1250             }
1251             if (((mseStored << MSE_RESOLUTION) < (MIN_MSE_DIFF * mseAdapt))
1252                     & ((aecm->mseStoredOld << MSE_RESOLUTION) < (MIN_MSE_DIFF
1253                             * aecm->mseAdaptOld)))
1254             {
1255                 // The stored channel has a significantly lower MSE than the adaptive one for
1256                 // two consecutive calculations. Reset the adaptive channel.
1257                 WebRtcAecm_ResetAdaptiveChannel(aecm);
1258             } else if (((MIN_MSE_DIFF * mseStored) > (mseAdapt << MSE_RESOLUTION)) & (mseAdapt
1259                     < aecm->mseThreshold) & (aecm->mseAdaptOld < aecm->mseThreshold))
1260             {
1261                 // The adaptive channel has a significantly lower MSE than the stored one.
1262                 // The MSE for the adaptive channel has also been low for two consecutive
1263                 // calculations. Store the adaptive channel.
1264                 WebRtcAecm_StoreAdaptiveChannel(aecm, far_spectrum, echoEst);
1265 
1266                 // Update threshold
1267                 if (aecm->mseThreshold == WEBRTC_SPL_WORD32_MAX)
1268                 {
1269                     aecm->mseThreshold = (mseAdapt + aecm->mseAdaptOld);
1270                 } else
1271                 {
1272                     aecm->mseThreshold += WEBRTC_SPL_MUL_16_16_RSFT(mseAdapt
1273                             - WEBRTC_SPL_MUL_16_16_RSFT(aecm->mseThreshold, 5, 3), 205, 8);
1274                 }
1275 
1276             }
1277 
1278             // Reset counter
1279             aecm->mseChannelCount = 0;
1280 
1281             // Store the MSE values.
1282             aecm->mseStoredOld = mseStored;
1283             aecm->mseAdaptOld = mseAdapt;
1284         }
1285     }
1286     // END: Determine if we should store or reset channel estimate.
1287 }
1288 
1289 // CalcSuppressionGain(...)
1290 //
1291 // This function calculates the suppression gain that is used in the Wiener filter.
1292 //
1293 //
1294 // @param  aecm     [i/n]   Handle of the AECM instance.
1295 // @param  supGain  [out]   (Return value) Suppression gain with which to scale the noise
1296 //                          level (Q14).
1297 //
1298 //
CalcSuppressionGain(AecmCore_t * const aecm)1299 static WebRtc_Word16 CalcSuppressionGain(AecmCore_t * const aecm)
1300 {
1301     WebRtc_Word32 tmp32no1;
1302 
1303     WebRtc_Word16 supGain = SUPGAIN_DEFAULT;
1304     WebRtc_Word16 tmp16no1;
1305     WebRtc_Word16 dE = 0;
1306 
1307     // Determine suppression gain used in the Wiener filter. The gain is based on a mix of far
1308     // end energy and echo estimation error.
1309     // Adjust for the far end signal level. A low signal level indicates no far end signal,
1310     // hence we set the suppression gain to 0
1311     if (!aecm->currentVADValue)
1312     {
1313         supGain = 0;
1314     } else
1315     {
1316         // Adjust for possible double talk. If we have large variations in estimation error we
1317         // likely have double talk (or poor channel).
1318         tmp16no1 = (aecm->nearLogEnergy[0] - aecm->echoStoredLogEnergy[0] - ENERGY_DEV_OFFSET);
1319         dE = WEBRTC_SPL_ABS_W16(tmp16no1);
1320 
1321         if (dE < ENERGY_DEV_TOL)
1322         {
1323             // Likely no double talk. The better estimation, the more we can suppress signal.
1324             // Update counters
1325             if (dE < SUPGAIN_EPC_DT)
1326             {
1327                 tmp32no1 = WEBRTC_SPL_MUL_16_16(aecm->supGainErrParamDiffAB, dE);
1328                 tmp32no1 += (SUPGAIN_EPC_DT >> 1);
1329                 tmp16no1 = (WebRtc_Word16)WebRtcSpl_DivW32W16(tmp32no1, SUPGAIN_EPC_DT);
1330                 supGain = aecm->supGainErrParamA - tmp16no1;
1331             } else
1332             {
1333                 tmp32no1 = WEBRTC_SPL_MUL_16_16(aecm->supGainErrParamDiffBD,
1334                                                 (ENERGY_DEV_TOL - dE));
1335                 tmp32no1 += ((ENERGY_DEV_TOL - SUPGAIN_EPC_DT) >> 1);
1336                 tmp16no1 = (WebRtc_Word16)WebRtcSpl_DivW32W16(tmp32no1, (ENERGY_DEV_TOL
1337                         - SUPGAIN_EPC_DT));
1338                 supGain = aecm->supGainErrParamD + tmp16no1;
1339             }
1340         } else
1341         {
1342             // Likely in double talk. Use default value
1343             supGain = aecm->supGainErrParamD;
1344         }
1345     }
1346 
1347     if (supGain > aecm->supGainOld)
1348     {
1349         tmp16no1 = supGain;
1350     } else
1351     {
1352         tmp16no1 = aecm->supGainOld;
1353     }
1354     aecm->supGainOld = supGain;
1355     if (tmp16no1 < aecm->supGain)
1356     {
1357         aecm->supGain += (WebRtc_Word16)((tmp16no1 - aecm->supGain) >> 4);
1358     } else
1359     {
1360         aecm->supGain += (WebRtc_Word16)((tmp16no1 - aecm->supGain) >> 4);
1361     }
1362 
1363     // END: Update suppression gain
1364 
1365     return aecm->supGain;
1366 }
1367 
1368 // Transforms a time domain signal into the frequency domain, outputting the
1369 // complex valued signal, absolute value and sum of absolute values.
1370 //
1371 // time_signal          [in]    Pointer to time domain signal
1372 // freq_signal_real     [out]   Pointer to real part of frequency domain array
1373 // freq_signal_imag     [out]   Pointer to imaginary part of frequency domain
1374 //                              array
1375 // freq_signal_abs      [out]   Pointer to absolute value of frequency domain
1376 //                              array
1377 // freq_signal_sum_abs  [out]   Pointer to the sum of all absolute values in
1378 //                              the frequency domain array
1379 // return value                 The Q-domain of current frequency values
1380 //
TimeToFrequencyDomain(const WebRtc_Word16 * time_signal,complex16_t * freq_signal,WebRtc_UWord16 * freq_signal_abs,WebRtc_UWord32 * freq_signal_sum_abs)1381 static int TimeToFrequencyDomain(const WebRtc_Word16* time_signal,
1382                                  complex16_t* freq_signal,
1383                                  WebRtc_UWord16* freq_signal_abs,
1384                                  WebRtc_UWord32* freq_signal_sum_abs)
1385 {
1386     int i = 0;
1387     int time_signal_scaling = 0;
1388 
1389     WebRtc_Word32 tmp32no1;
1390     WebRtc_Word32 tmp32no2;
1391 
1392     // In fft_buf, +16 for 32-byte alignment.
1393     WebRtc_Word16 fft_buf[PART_LEN4 + 16];
1394     WebRtc_Word16 *fft = (WebRtc_Word16 *) (((uintptr_t) fft_buf + 31) & ~31);
1395 
1396     WebRtc_Word16 tmp16no1;
1397     WebRtc_Word16 tmp16no2;
1398 #ifdef AECM_WITH_ABS_APPROX
1399     WebRtc_Word16 max_value = 0;
1400     WebRtc_Word16 min_value = 0;
1401     WebRtc_UWord16 alpha = 0;
1402     WebRtc_UWord16 beta = 0;
1403 #endif
1404 
1405 #ifdef AECM_DYNAMIC_Q
1406     tmp16no1 = WebRtcSpl_MaxAbsValueW16(time_signal, PART_LEN2);
1407     time_signal_scaling = WebRtcSpl_NormW16(tmp16no1);
1408 #endif
1409 
1410     WebRtcAecm_WindowAndFFT(fft, time_signal, freq_signal, time_signal_scaling);
1411 
1412     // Extract imaginary and real part, calculate the magnitude for all frequency bins
1413     freq_signal[0].imag = 0;
1414     freq_signal[PART_LEN].imag = 0;
1415     freq_signal[PART_LEN].real = fft[PART_LEN2];
1416     freq_signal_abs[0] = (WebRtc_UWord16)WEBRTC_SPL_ABS_W16(
1417         freq_signal[0].real);
1418     freq_signal_abs[PART_LEN] = (WebRtc_UWord16)WEBRTC_SPL_ABS_W16(
1419         freq_signal[PART_LEN].real);
1420     (*freq_signal_sum_abs) = (WebRtc_UWord32)(freq_signal_abs[0]) +
1421         (WebRtc_UWord32)(freq_signal_abs[PART_LEN]);
1422 
1423     for (i = 1; i < PART_LEN; i++)
1424     {
1425         if (freq_signal[i].real == 0)
1426         {
1427             freq_signal_abs[i] = (WebRtc_UWord16)WEBRTC_SPL_ABS_W16(
1428                 freq_signal[i].imag);
1429         }
1430         else if (freq_signal[i].imag == 0)
1431         {
1432             freq_signal_abs[i] = (WebRtc_UWord16)WEBRTC_SPL_ABS_W16(
1433                 freq_signal[i].real);
1434         }
1435         else
1436         {
1437             // Approximation for magnitude of complex fft output
1438             // magn = sqrt(real^2 + imag^2)
1439             // magn ~= alpha * max(|imag|,|real|) + beta * min(|imag|,|real|)
1440             //
1441             // The parameters alpha and beta are stored in Q15
1442 
1443 #ifdef AECM_WITH_ABS_APPROX
1444             tmp16no1 = WEBRTC_SPL_ABS_W16(freq_signal[i].real);
1445             tmp16no2 = WEBRTC_SPL_ABS_W16(freq_signal[i].imag);
1446 
1447             if(tmp16no1 > tmp16no2)
1448             {
1449                 max_value = tmp16no1;
1450                 min_value = tmp16no2;
1451             } else
1452             {
1453                 max_value = tmp16no2;
1454                 min_value = tmp16no1;
1455             }
1456 
1457             // Magnitude in Q(-6)
1458             if ((max_value >> 2) > min_value)
1459             {
1460                 alpha = kAlpha1;
1461                 beta = kBeta1;
1462             } else if ((max_value >> 1) > min_value)
1463             {
1464                 alpha = kAlpha2;
1465                 beta = kBeta2;
1466             } else
1467             {
1468                 alpha = kAlpha3;
1469                 beta = kBeta3;
1470             }
1471             tmp16no1 = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(max_value,
1472                                                                 alpha,
1473                                                                 15);
1474             tmp16no2 = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(min_value,
1475                                                                 beta,
1476                                                                 15);
1477             freq_signal_abs[i] = (WebRtc_UWord16)tmp16no1 +
1478                 (WebRtc_UWord16)tmp16no2;
1479 #else
1480 #ifdef WEBRTC_ARCH_ARM_V7A
1481            __asm__("smulbb %0, %1, %2" : "=r"(tmp32no1) : "r"(freq_signal[i].real),
1482                                                 "r"(freq_signal[i].real));
1483            __asm__("smlabb %0, %1, %2, %3" :: "r"(tmp32no2), "r"(freq_signal[i].imag),
1484                                                 "r"(freq_signal[i].imag), "r"(tmp32no1));
1485 #else
1486             tmp16no1 = WEBRTC_SPL_ABS_W16(freq_signal[i].real);
1487             tmp16no2 = WEBRTC_SPL_ABS_W16(freq_signal[i].imag);
1488             tmp32no1 = WEBRTC_SPL_MUL_16_16(tmp16no1, tmp16no1);
1489             tmp32no2 = WEBRTC_SPL_MUL_16_16(tmp16no2, tmp16no2);
1490             tmp32no2 = WEBRTC_SPL_ADD_SAT_W32(tmp32no1, tmp32no2);
1491 #endif // WEBRTC_ARCH_ARM_V7A
1492             tmp32no1 = WebRtcSpl_SqrtFloor(tmp32no2);
1493 
1494             freq_signal_abs[i] = (WebRtc_UWord16)tmp32no1;
1495 #endif // AECM_WITH_ABS_APPROX
1496         }
1497         (*freq_signal_sum_abs) += (WebRtc_UWord32)freq_signal_abs[i];
1498     }
1499 
1500     return time_signal_scaling;
1501 }
1502 
WebRtcAecm_ProcessBlock(AecmCore_t * aecm,const WebRtc_Word16 * farend,const WebRtc_Word16 * nearendNoisy,const WebRtc_Word16 * nearendClean,WebRtc_Word16 * output)1503 int WebRtcAecm_ProcessBlock(AecmCore_t * aecm,
1504                             const WebRtc_Word16 * farend,
1505                             const WebRtc_Word16 * nearendNoisy,
1506                             const WebRtc_Word16 * nearendClean,
1507                             WebRtc_Word16 * output)
1508 {
1509     int i;
1510 
1511     WebRtc_UWord32 xfaSum;
1512     WebRtc_UWord32 dfaNoisySum;
1513     WebRtc_UWord32 dfaCleanSum;
1514     WebRtc_UWord32 echoEst32Gained;
1515     WebRtc_UWord32 tmpU32;
1516 
1517     WebRtc_Word32 tmp32no1;
1518 
1519     WebRtc_UWord16 xfa[PART_LEN1];
1520     WebRtc_UWord16 dfaNoisy[PART_LEN1];
1521     WebRtc_UWord16 dfaClean[PART_LEN1];
1522     WebRtc_UWord16* ptrDfaClean = dfaClean;
1523     const WebRtc_UWord16* far_spectrum_ptr = NULL;
1524 
1525     // 32 byte aligned buffers (with +8 or +16).
1526     // TODO (kma): define fft with complex16_t.
1527     WebRtc_Word16 fft_buf[PART_LEN4 + 2 + 16]; // +2 to make a loop safe.
1528     WebRtc_Word32 echoEst32_buf[PART_LEN1 + 8];
1529     WebRtc_Word32 dfw_buf[PART_LEN1 + 8];
1530     WebRtc_Word32 efw_buf[PART_LEN1 + 8];
1531 
1532     WebRtc_Word16* fft = (WebRtc_Word16*) (((uintptr_t) fft_buf + 31) & ~ 31);
1533     WebRtc_Word32* echoEst32 = (WebRtc_Word32*) (((uintptr_t) echoEst32_buf + 31) & ~ 31);
1534     complex16_t* dfw = (complex16_t*) (((uintptr_t) dfw_buf + 31) & ~ 31);
1535     complex16_t* efw = (complex16_t*) (((uintptr_t) efw_buf + 31) & ~ 31);
1536 
1537     WebRtc_Word16 hnl[PART_LEN1];
1538     WebRtc_Word16 numPosCoef = 0;
1539     WebRtc_Word16 nlpGain = ONE_Q14;
1540     int delay;
1541     WebRtc_Word16 tmp16no1;
1542     WebRtc_Word16 tmp16no2;
1543     WebRtc_Word16 mu;
1544     WebRtc_Word16 supGain;
1545     WebRtc_Word16 zeros32, zeros16;
1546     WebRtc_Word16 zerosDBufNoisy, zerosDBufClean, zerosXBuf;
1547     int far_q;
1548     WebRtc_Word16 resolutionDiff, qDomainDiff;
1549 
1550     const int kMinPrefBand = 4;
1551     const int kMaxPrefBand = 24;
1552     WebRtc_Word32 avgHnl32 = 0;
1553 
1554 #ifdef ARM_WINM_LOG_
1555     DWORD temp;
1556     static int flag0 = 0;
1557     __int64 freq, start, end, diff__;
1558     unsigned int milliseconds;
1559 #endif
1560 
1561     // Determine startup state. There are three states:
1562     // (0) the first CONV_LEN blocks
1563     // (1) another CONV_LEN blocks
1564     // (2) the rest
1565 
1566     if (aecm->startupState < 2)
1567     {
1568         aecm->startupState = (aecm->totCount >= CONV_LEN) + (aecm->totCount >= CONV_LEN2);
1569     }
1570     // END: Determine startup state
1571 
1572     // Buffer near and far end signals
1573     memcpy(aecm->xBuf + PART_LEN, farend, sizeof(WebRtc_Word16) * PART_LEN);
1574     memcpy(aecm->dBufNoisy + PART_LEN, nearendNoisy, sizeof(WebRtc_Word16) * PART_LEN);
1575     if (nearendClean != NULL)
1576     {
1577         memcpy(aecm->dBufClean + PART_LEN, nearendClean, sizeof(WebRtc_Word16) * PART_LEN);
1578     }
1579 
1580 #ifdef ARM_WINM_LOG_
1581     // measure tick start
1582     QueryPerformanceFrequency((LARGE_INTEGER*)&freq);
1583     QueryPerformanceCounter((LARGE_INTEGER*)&start);
1584 #endif
1585 
1586     // Transform far end signal from time domain to frequency domain.
1587     far_q = TimeToFrequencyDomain(aecm->xBuf,
1588                                   dfw,
1589                                   xfa,
1590                                   &xfaSum);
1591 
1592     // Transform noisy near end signal from time domain to frequency domain.
1593     zerosDBufNoisy = TimeToFrequencyDomain(aecm->dBufNoisy,
1594                                            dfw,
1595                                            dfaNoisy,
1596                                            &dfaNoisySum);
1597     aecm->dfaNoisyQDomainOld = aecm->dfaNoisyQDomain;
1598     aecm->dfaNoisyQDomain = (WebRtc_Word16)zerosDBufNoisy;
1599 
1600 
1601     if (nearendClean == NULL)
1602     {
1603         ptrDfaClean = dfaNoisy;
1604         aecm->dfaCleanQDomainOld = aecm->dfaNoisyQDomainOld;
1605         aecm->dfaCleanQDomain = aecm->dfaNoisyQDomain;
1606         dfaCleanSum = dfaNoisySum;
1607     } else
1608     {
1609         // Transform clean near end signal from time domain to frequency domain.
1610         zerosDBufClean = TimeToFrequencyDomain(aecm->dBufClean,
1611                                                dfw,
1612                                                dfaClean,
1613                                                &dfaCleanSum);
1614         aecm->dfaCleanQDomainOld = aecm->dfaCleanQDomain;
1615         aecm->dfaCleanQDomain = (WebRtc_Word16)zerosDBufClean;
1616     }
1617 
1618 #ifdef ARM_WINM_LOG_
1619     // measure tick end
1620     QueryPerformanceCounter((LARGE_INTEGER*)&end);
1621     diff__ = ((end - start) * 1000) / (freq/1000);
1622     milliseconds = (unsigned int)(diff__ & 0xffffffff);
1623     WriteFile (logFile, &milliseconds, sizeof(unsigned int), &temp, NULL);
1624     // measure tick start
1625     QueryPerformanceCounter((LARGE_INTEGER*)&start);
1626 #endif
1627 
1628     // Get the delay
1629     // Save far-end history and estimate delay
1630     UpdateFarHistory(aecm, xfa, far_q);
1631     delay = WebRtc_DelayEstimatorProcessFix(aecm->delay_estimator,
1632                                             xfa,
1633                                             dfaNoisy,
1634                                             PART_LEN1,
1635                                             far_q,
1636                                             zerosDBufNoisy);
1637     if (delay == -1)
1638     {
1639         return -1;
1640     }
1641     else if (delay == -2)
1642     {
1643         // If the delay is unknown, we assume zero.
1644         // NOTE: this will have to be adjusted if we ever add lookahead.
1645         delay = 0;
1646     }
1647 
1648     if (aecm->fixedDelay >= 0)
1649     {
1650         // Use fixed delay
1651         delay = aecm->fixedDelay;
1652     }
1653 
1654 #ifdef ARM_WINM_LOG_
1655     // measure tick end
1656     QueryPerformanceCounter((LARGE_INTEGER*)&end);
1657     diff__ = ((end - start) * 1000) / (freq/1000);
1658     milliseconds = (unsigned int)(diff__ & 0xffffffff);
1659     WriteFile (logFile, &milliseconds, sizeof(unsigned int), &temp, NULL);
1660     // measure tick start
1661     QueryPerformanceCounter((LARGE_INTEGER*)&start);
1662 #endif
1663     // Get aligned far end spectrum
1664     far_spectrum_ptr = AlignedFarend(aecm, &far_q, delay);
1665     zerosXBuf = (WebRtc_Word16) far_q;
1666     if (far_spectrum_ptr == NULL)
1667     {
1668         return -1;
1669     }
1670 
1671     // Calculate log(energy) and update energy threshold levels
1672     WebRtcAecm_CalcEnergies(aecm,
1673                             far_spectrum_ptr,
1674                             zerosXBuf,
1675                             dfaNoisySum,
1676                             echoEst32);
1677 
1678     // Calculate stepsize
1679     mu = WebRtcAecm_CalcStepSize(aecm);
1680 
1681     // Update counters
1682     aecm->totCount++;
1683 
1684     // This is the channel estimation algorithm.
1685     // It is base on NLMS but has a variable step length, which was calculated above.
1686     WebRtcAecm_UpdateChannel(aecm, far_spectrum_ptr, zerosXBuf, dfaNoisy, mu, echoEst32);
1687     supGain = CalcSuppressionGain(aecm);
1688 
1689 #ifdef ARM_WINM_LOG_
1690     // measure tick end
1691     QueryPerformanceCounter((LARGE_INTEGER*)&end);
1692     diff__ = ((end - start) * 1000) / (freq/1000);
1693     milliseconds = (unsigned int)(diff__ & 0xffffffff);
1694     WriteFile (logFile, &milliseconds, sizeof(unsigned int), &temp, NULL);
1695     // measure tick start
1696     QueryPerformanceCounter((LARGE_INTEGER*)&start);
1697 #endif
1698 
1699     // Calculate Wiener filter hnl[]
1700     for (i = 0; i < PART_LEN1; i++)
1701     {
1702         // Far end signal through channel estimate in Q8
1703         // How much can we shift right to preserve resolution
1704         tmp32no1 = echoEst32[i] - aecm->echoFilt[i];
1705         aecm->echoFilt[i] += WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_32_16(tmp32no1, 50), 8);
1706 
1707         zeros32 = WebRtcSpl_NormW32(aecm->echoFilt[i]) + 1;
1708         zeros16 = WebRtcSpl_NormW16(supGain) + 1;
1709         if (zeros32 + zeros16 > 16)
1710         {
1711             // Multiplication is safe
1712             // Result in Q(RESOLUTION_CHANNEL+RESOLUTION_SUPGAIN+aecm->xfaQDomainBuf[diff])
1713             echoEst32Gained = WEBRTC_SPL_UMUL_32_16((WebRtc_UWord32)aecm->echoFilt[i],
1714                                                     (WebRtc_UWord16)supGain);
1715             resolutionDiff = 14 - RESOLUTION_CHANNEL16 - RESOLUTION_SUPGAIN;
1716             resolutionDiff += (aecm->dfaCleanQDomain - zerosXBuf);
1717         } else
1718         {
1719             tmp16no1 = 17 - zeros32 - zeros16;
1720             resolutionDiff = 14 + tmp16no1 - RESOLUTION_CHANNEL16 - RESOLUTION_SUPGAIN;
1721             resolutionDiff += (aecm->dfaCleanQDomain - zerosXBuf);
1722             if (zeros32 > tmp16no1)
1723             {
1724                 echoEst32Gained = WEBRTC_SPL_UMUL_32_16((WebRtc_UWord32)aecm->echoFilt[i],
1725                         (WebRtc_UWord16)WEBRTC_SPL_RSHIFT_W16(supGain,
1726                                 tmp16no1)); // Q-(RESOLUTION_CHANNEL+RESOLUTION_SUPGAIN-16)
1727             } else
1728             {
1729                 // Result in Q-(RESOLUTION_CHANNEL+RESOLUTION_SUPGAIN-16)
1730                 echoEst32Gained = WEBRTC_SPL_UMUL_32_16(
1731                         (WebRtc_UWord32)WEBRTC_SPL_RSHIFT_W32(aecm->echoFilt[i], tmp16no1),
1732                         (WebRtc_UWord16)supGain);
1733             }
1734         }
1735 
1736         zeros16 = WebRtcSpl_NormW16(aecm->nearFilt[i]);
1737         if ((zeros16 < (aecm->dfaCleanQDomain - aecm->dfaCleanQDomainOld))
1738                 & (aecm->nearFilt[i]))
1739         {
1740             tmp16no1 = WEBRTC_SPL_SHIFT_W16(aecm->nearFilt[i], zeros16);
1741             qDomainDiff = zeros16 - aecm->dfaCleanQDomain + aecm->dfaCleanQDomainOld;
1742         } else
1743         {
1744             tmp16no1 = WEBRTC_SPL_SHIFT_W16(aecm->nearFilt[i],
1745                                             aecm->dfaCleanQDomain - aecm->dfaCleanQDomainOld);
1746             qDomainDiff = 0;
1747         }
1748         tmp16no2 = WEBRTC_SPL_SHIFT_W16(ptrDfaClean[i], qDomainDiff);
1749         tmp32no1 = (WebRtc_Word32)(tmp16no2 - tmp16no1);
1750         tmp16no2 = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmp32no1, 4);
1751         tmp16no2 += tmp16no1;
1752         zeros16 = WebRtcSpl_NormW16(tmp16no2);
1753         if ((tmp16no2) & (-qDomainDiff > zeros16))
1754         {
1755             aecm->nearFilt[i] = WEBRTC_SPL_WORD16_MAX;
1756         } else
1757         {
1758             aecm->nearFilt[i] = WEBRTC_SPL_SHIFT_W16(tmp16no2, -qDomainDiff);
1759         }
1760 
1761         // Wiener filter coefficients, resulting hnl in Q14
1762         if (echoEst32Gained == 0)
1763         {
1764             hnl[i] = ONE_Q14;
1765         } else if (aecm->nearFilt[i] == 0)
1766         {
1767             hnl[i] = 0;
1768         } else
1769         {
1770             // Multiply the suppression gain
1771             // Rounding
1772             echoEst32Gained += (WebRtc_UWord32)(aecm->nearFilt[i] >> 1);
1773             tmpU32 = WebRtcSpl_DivU32U16(echoEst32Gained, (WebRtc_UWord16)aecm->nearFilt[i]);
1774 
1775             // Current resolution is
1776             // Q-(RESOLUTION_CHANNEL + RESOLUTION_SUPGAIN - max(0, 17 - zeros16 - zeros32))
1777             // Make sure we are in Q14
1778             tmp32no1 = (WebRtc_Word32)WEBRTC_SPL_SHIFT_W32(tmpU32, resolutionDiff);
1779             if (tmp32no1 > ONE_Q14)
1780             {
1781                 hnl[i] = 0;
1782             } else if (tmp32no1 < 0)
1783             {
1784                 hnl[i] = ONE_Q14;
1785             } else
1786             {
1787                 // 1-echoEst/dfa
1788                 hnl[i] = ONE_Q14 - (WebRtc_Word16)tmp32no1;
1789                 if (hnl[i] < 0)
1790                 {
1791                     hnl[i] = 0;
1792                 }
1793             }
1794         }
1795         if (hnl[i])
1796         {
1797             numPosCoef++;
1798         }
1799     }
1800     // Only in wideband. Prevent the gain in upper band from being larger than
1801     // in lower band.
1802     if (aecm->mult == 2)
1803     {
1804         // TODO(bjornv): Investigate if the scaling of hnl[i] below can cause
1805         //               speech distortion in double-talk.
1806         for (i = 0; i < PART_LEN1; i++)
1807         {
1808             hnl[i] = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(hnl[i], hnl[i], 14);
1809         }
1810 
1811         for (i = kMinPrefBand; i <= kMaxPrefBand; i++)
1812         {
1813             avgHnl32 += (WebRtc_Word32)hnl[i];
1814         }
1815         assert(kMaxPrefBand - kMinPrefBand + 1 > 0);
1816         avgHnl32 /= (kMaxPrefBand - kMinPrefBand + 1);
1817 
1818         for (i = kMaxPrefBand; i < PART_LEN1; i++)
1819         {
1820             if (hnl[i] > (WebRtc_Word16)avgHnl32)
1821             {
1822                 hnl[i] = (WebRtc_Word16)avgHnl32;
1823             }
1824         }
1825     }
1826 
1827 #ifdef ARM_WINM_LOG_
1828     // measure tick end
1829     QueryPerformanceCounter((LARGE_INTEGER*)&end);
1830     diff__ = ((end - start) * 1000) / (freq/1000);
1831     milliseconds = (unsigned int)(diff__ & 0xffffffff);
1832     WriteFile (logFile, &milliseconds, sizeof(unsigned int), &temp, NULL);
1833     // measure tick start
1834     QueryPerformanceCounter((LARGE_INTEGER*)&start);
1835 #endif
1836 
1837     // Calculate NLP gain, result is in Q14
1838     if (aecm->nlpFlag)
1839     {
1840         for (i = 0; i < PART_LEN1; i++)
1841         {
1842             // Truncate values close to zero and one.
1843             if (hnl[i] > NLP_COMP_HIGH)
1844             {
1845                 hnl[i] = ONE_Q14;
1846             } else if (hnl[i] < NLP_COMP_LOW)
1847             {
1848                 hnl[i] = 0;
1849             }
1850 
1851             // Remove outliers
1852             if (numPosCoef < 3)
1853             {
1854                 nlpGain = 0;
1855             } else
1856             {
1857                 nlpGain = ONE_Q14;
1858             }
1859 
1860             // NLP
1861             if ((hnl[i] == ONE_Q14) && (nlpGain == ONE_Q14))
1862             {
1863                 hnl[i] = ONE_Q14;
1864             } else
1865             {
1866                 hnl[i] = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(hnl[i], nlpGain, 14);
1867             }
1868 
1869             // multiply with Wiener coefficients
1870             efw[i].real = (WebRtc_Word16)(WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND(dfw[i].real,
1871                                                                             hnl[i], 14));
1872             efw[i].imag = (WebRtc_Word16)(WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND(dfw[i].imag,
1873                                                                             hnl[i], 14));
1874         }
1875     }
1876     else
1877     {
1878         // multiply with Wiener coefficients
1879         for (i = 0; i < PART_LEN1; i++)
1880         {
1881             efw[i].real = (WebRtc_Word16)(WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND(dfw[i].real,
1882                                                                            hnl[i], 14));
1883             efw[i].imag = (WebRtc_Word16)(WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND(dfw[i].imag,
1884                                                                            hnl[i], 14));
1885         }
1886     }
1887 
1888     if (aecm->cngMode == AecmTrue)
1889     {
1890         ComfortNoise(aecm, ptrDfaClean, efw, hnl);
1891     }
1892 
1893 #ifdef ARM_WINM_LOG_
1894     // measure tick end
1895     QueryPerformanceCounter((LARGE_INTEGER*)&end);
1896     diff__ = ((end - start) * 1000) / (freq/1000);
1897     milliseconds = (unsigned int)(diff__ & 0xffffffff);
1898     WriteFile (logFile, &milliseconds, sizeof(unsigned int), &temp, NULL);
1899     // measure tick start
1900     QueryPerformanceCounter((LARGE_INTEGER*)&start);
1901 #endif
1902 
1903     WebRtcAecm_InverseFFTAndWindow(aecm, fft, efw, output, nearendClean);
1904 
1905     return 0;
1906 }
1907 
1908 
1909 // Generate comfort noise and add to output signal.
1910 //
1911 // \param[in]     aecm     Handle of the AECM instance.
1912 // \param[in]     dfa     Absolute value of the nearend signal (Q[aecm->dfaQDomain]).
1913 // \param[in,out] outReal Real part of the output signal (Q[aecm->dfaQDomain]).
1914 // \param[in,out] outImag Imaginary part of the output signal (Q[aecm->dfaQDomain]).
1915 // \param[in]     lambda  Suppression gain with which to scale the noise level (Q14).
1916 //
ComfortNoise(AecmCore_t * aecm,const WebRtc_UWord16 * dfa,complex16_t * out,const WebRtc_Word16 * lambda)1917 static void ComfortNoise(AecmCore_t* aecm,
1918                          const WebRtc_UWord16* dfa,
1919                          complex16_t* out,
1920                          const WebRtc_Word16* lambda)
1921 {
1922     WebRtc_Word16 i;
1923     WebRtc_Word16 tmp16;
1924     WebRtc_Word32 tmp32;
1925 
1926     WebRtc_Word16 randW16[PART_LEN];
1927     WebRtc_Word16 uReal[PART_LEN1];
1928     WebRtc_Word16 uImag[PART_LEN1];
1929     WebRtc_Word32 outLShift32;
1930     WebRtc_Word16 noiseRShift16[PART_LEN1];
1931 
1932     WebRtc_Word16 shiftFromNearToNoise = kNoiseEstQDomain - aecm->dfaCleanQDomain;
1933     WebRtc_Word16 minTrackShift;
1934 
1935     assert(shiftFromNearToNoise >= 0);
1936     assert(shiftFromNearToNoise < 16);
1937 
1938     if (aecm->noiseEstCtr < 100)
1939     {
1940         // Track the minimum more quickly initially.
1941         aecm->noiseEstCtr++;
1942         minTrackShift = 6;
1943     } else
1944     {
1945         minTrackShift = 9;
1946     }
1947 
1948     // Estimate noise power.
1949     for (i = 0; i < PART_LEN1; i++)
1950     {
1951 
1952         // Shift to the noise domain.
1953         tmp32 = (WebRtc_Word32)dfa[i];
1954         outLShift32 = WEBRTC_SPL_LSHIFT_W32(tmp32, shiftFromNearToNoise);
1955 
1956         if (outLShift32 < aecm->noiseEst[i])
1957         {
1958             // Reset "too low" counter
1959             aecm->noiseEstTooLowCtr[i] = 0;
1960             // Track the minimum.
1961             if (aecm->noiseEst[i] < (1 << minTrackShift))
1962             {
1963                 // For small values, decrease noiseEst[i] every
1964                 // |kNoiseEstIncCount| block. The regular approach below can not
1965                 // go further down due to truncation.
1966                 aecm->noiseEstTooHighCtr[i]++;
1967                 if (aecm->noiseEstTooHighCtr[i] >= kNoiseEstIncCount)
1968                 {
1969                     aecm->noiseEst[i]--;
1970                     aecm->noiseEstTooHighCtr[i] = 0; // Reset the counter
1971                 }
1972             }
1973             else
1974             {
1975                 aecm->noiseEst[i] -= ((aecm->noiseEst[i] - outLShift32) >> minTrackShift);
1976             }
1977         } else
1978         {
1979             // Reset "too high" counter
1980             aecm->noiseEstTooHighCtr[i] = 0;
1981             // Ramp slowly upwards until we hit the minimum again.
1982             if ((aecm->noiseEst[i] >> 19) > 0)
1983             {
1984                 // Avoid overflow.
1985                 // Multiplication with 2049 will cause wrap around. Scale
1986                 // down first and then multiply
1987                 aecm->noiseEst[i] >>= 11;
1988                 aecm->noiseEst[i] *= 2049;
1989             }
1990             else if ((aecm->noiseEst[i] >> 11) > 0)
1991             {
1992                 // Large enough for relative increase
1993                 aecm->noiseEst[i] *= 2049;
1994                 aecm->noiseEst[i] >>= 11;
1995             }
1996             else
1997             {
1998                 // Make incremental increases based on size every
1999                 // |kNoiseEstIncCount| block
2000                 aecm->noiseEstTooLowCtr[i]++;
2001                 if (aecm->noiseEstTooLowCtr[i] >= kNoiseEstIncCount)
2002                 {
2003                     aecm->noiseEst[i] += (aecm->noiseEst[i] >> 9) + 1;
2004                     aecm->noiseEstTooLowCtr[i] = 0; // Reset counter
2005                 }
2006             }
2007         }
2008     }
2009 
2010     for (i = 0; i < PART_LEN1; i++)
2011     {
2012         tmp32 = WEBRTC_SPL_RSHIFT_W32(aecm->noiseEst[i], shiftFromNearToNoise);
2013         if (tmp32 > 32767)
2014         {
2015             tmp32 = 32767;
2016             aecm->noiseEst[i] = WEBRTC_SPL_LSHIFT_W32(tmp32, shiftFromNearToNoise);
2017         }
2018         noiseRShift16[i] = (WebRtc_Word16)tmp32;
2019 
2020         tmp16 = ONE_Q14 - lambda[i];
2021         noiseRShift16[i]
2022                 = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(tmp16, noiseRShift16[i], 14);
2023     }
2024 
2025     // Generate a uniform random array on [0 2^15-1].
2026     WebRtcSpl_RandUArray(randW16, PART_LEN, &aecm->seed);
2027 
2028     // Generate noise according to estimated energy.
2029     uReal[0] = 0; // Reject LF noise.
2030     uImag[0] = 0;
2031     for (i = 1; i < PART_LEN1; i++)
2032     {
2033         // Get a random index for the cos and sin tables over [0 359].
2034         tmp16 = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(359, randW16[i - 1], 15);
2035 
2036         // Tables are in Q13.
2037         uReal[i] = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(noiseRShift16[i],
2038                 kCosTable[tmp16], 13);
2039         uImag[i] = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(-noiseRShift16[i],
2040                 kSinTable[tmp16], 13);
2041     }
2042     uImag[PART_LEN] = 0;
2043 
2044 #if (!defined ARM_WINM) && (!defined ARM9E_GCC) && (!defined ANDROID_AECOPT)
2045     for (i = 0; i < PART_LEN1; i++)
2046     {
2047         out[i].real = WEBRTC_SPL_ADD_SAT_W16(out[i].real, uReal[i]);
2048         out[i].imag = WEBRTC_SPL_ADD_SAT_W16(out[i].imag, uImag[i]);
2049     }
2050 #else
2051     for (i = 0; i < PART_LEN1 -1; )
2052     {
2053         out[i].real = WEBRTC_SPL_ADD_SAT_W16(out[i].real, uReal[i]);
2054         out[i].imag = WEBRTC_SPL_ADD_SAT_W16(out[i].imag, uImag[i]);
2055         i++;
2056 
2057         out[i].real = WEBRTC_SPL_ADD_SAT_W16(out[i].real, uReal[i]);
2058         out[i].imag = WEBRTC_SPL_ADD_SAT_W16(out[i].imag, uImag[i]);
2059         i++;
2060     }
2061     out[i].real = WEBRTC_SPL_ADD_SAT_W16(out[i].real, uReal[i]);
2062     out[i].imag = WEBRTC_SPL_ADD_SAT_W16(out[i].imag, uImag[i]);
2063 #endif
2064 }
2065 
WebRtcAecm_BufferFarFrame(AecmCore_t * const aecm,const WebRtc_Word16 * const farend,const int farLen)2066 void WebRtcAecm_BufferFarFrame(AecmCore_t* const aecm,
2067                                const WebRtc_Word16* const farend,
2068                                const int farLen)
2069 {
2070     int writeLen = farLen, writePos = 0;
2071 
2072     // Check if the write position must be wrapped
2073     while (aecm->farBufWritePos + writeLen > FAR_BUF_LEN)
2074     {
2075         // Write to remaining buffer space before wrapping
2076         writeLen = FAR_BUF_LEN - aecm->farBufWritePos;
2077         memcpy(aecm->farBuf + aecm->farBufWritePos, farend + writePos,
2078                sizeof(WebRtc_Word16) * writeLen);
2079         aecm->farBufWritePos = 0;
2080         writePos = writeLen;
2081         writeLen = farLen - writeLen;
2082     }
2083 
2084     memcpy(aecm->farBuf + aecm->farBufWritePos, farend + writePos,
2085            sizeof(WebRtc_Word16) * writeLen);
2086     aecm->farBufWritePos += writeLen;
2087 }
2088 
WebRtcAecm_FetchFarFrame(AecmCore_t * const aecm,WebRtc_Word16 * const farend,const int farLen,const int knownDelay)2089 void WebRtcAecm_FetchFarFrame(AecmCore_t * const aecm, WebRtc_Word16 * const farend,
2090                               const int farLen, const int knownDelay)
2091 {
2092     int readLen = farLen;
2093     int readPos = 0;
2094     int delayChange = knownDelay - aecm->lastKnownDelay;
2095 
2096     aecm->farBufReadPos -= delayChange;
2097 
2098     // Check if delay forces a read position wrap
2099     while (aecm->farBufReadPos < 0)
2100     {
2101         aecm->farBufReadPos += FAR_BUF_LEN;
2102     }
2103     while (aecm->farBufReadPos > FAR_BUF_LEN - 1)
2104     {
2105         aecm->farBufReadPos -= FAR_BUF_LEN;
2106     }
2107 
2108     aecm->lastKnownDelay = knownDelay;
2109 
2110     // Check if read position must be wrapped
2111     while (aecm->farBufReadPos + readLen > FAR_BUF_LEN)
2112     {
2113 
2114         // Read from remaining buffer space before wrapping
2115         readLen = FAR_BUF_LEN - aecm->farBufReadPos;
2116         memcpy(farend + readPos, aecm->farBuf + aecm->farBufReadPos,
2117                sizeof(WebRtc_Word16) * readLen);
2118         aecm->farBufReadPos = 0;
2119         readPos = readLen;
2120         readLen = farLen - readLen;
2121     }
2122     memcpy(farend + readPos, aecm->farBuf + aecm->farBufReadPos,
2123            sizeof(WebRtc_Word16) * readLen);
2124     aecm->farBufReadPos += readLen;
2125 }
2126 
2127