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