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