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