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/signal_processing/include/real_fft.h"
18#include "webrtc/modules/audio_processing/aecm/include/echo_control_mobile.h"
19#include "webrtc/modules/audio_processing/utility/delay_estimator_wrapper.h"
20#include "webrtc/modules/audio_processing/utility/ring_buffer.h"
21#include "webrtc/system_wrappers/interface/compile_assert_c.h"
22#include "webrtc/system_wrappers/interface/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_t* 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_t* 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
210int WebRtcAecm_CreateCore(AecmCore_t **aecmInst)
211{
212    AecmCore_t *aecm = malloc(sizeof(AecmCore_t));
213    *aecmInst = aecm;
214    if (aecm == NULL)
215    {
216        return -1;
217    }
218
219    aecm->farFrameBuf = WebRtc_CreateBuffer(FRAME_LEN + PART_LEN,
220                                            sizeof(int16_t));
221    if (!aecm->farFrameBuf)
222    {
223        WebRtcAecm_FreeCore(aecm);
224        aecm = NULL;
225        return -1;
226    }
227
228    aecm->nearNoisyFrameBuf = WebRtc_CreateBuffer(FRAME_LEN + PART_LEN,
229                                                  sizeof(int16_t));
230    if (!aecm->nearNoisyFrameBuf)
231    {
232        WebRtcAecm_FreeCore(aecm);
233        aecm = NULL;
234        return -1;
235    }
236
237    aecm->nearCleanFrameBuf = WebRtc_CreateBuffer(FRAME_LEN + PART_LEN,
238                                                  sizeof(int16_t));
239    if (!aecm->nearCleanFrameBuf)
240    {
241        WebRtcAecm_FreeCore(aecm);
242        aecm = NULL;
243        return -1;
244    }
245
246    aecm->outFrameBuf = WebRtc_CreateBuffer(FRAME_LEN + PART_LEN,
247                                            sizeof(int16_t));
248    if (!aecm->outFrameBuf)
249    {
250        WebRtcAecm_FreeCore(aecm);
251        aecm = NULL;
252        return -1;
253    }
254
255    aecm->delay_estimator_farend = WebRtc_CreateDelayEstimatorFarend(PART_LEN1,
256                                                                     MAX_DELAY);
257    if (aecm->delay_estimator_farend == NULL) {
258      WebRtcAecm_FreeCore(aecm);
259      aecm = NULL;
260      return -1;
261    }
262    aecm->delay_estimator =
263        WebRtc_CreateDelayEstimator(aecm->delay_estimator_farend, 0);
264    if (aecm->delay_estimator == NULL) {
265      WebRtcAecm_FreeCore(aecm);
266      aecm = NULL;
267      return -1;
268    }
269    // TODO(bjornv): Explicitly disable robust delay validation until no
270    // performance regression has been established.  Then remove the line.
271    WebRtc_enable_robust_validation(aecm->delay_estimator, 0);
272
273    aecm->real_fft = WebRtcSpl_CreateRealFFT(PART_LEN_SHIFT);
274    if (aecm->real_fft == NULL) {
275      WebRtcAecm_FreeCore(aecm);
276      aecm = NULL;
277      return -1;
278    }
279
280    // Init some aecm pointers. 16 and 32 byte alignment is only necessary
281    // for Neon code currently.
282    aecm->xBuf = (int16_t*) (((uintptr_t)aecm->xBuf_buf + 31) & ~ 31);
283    aecm->dBufClean = (int16_t*) (((uintptr_t)aecm->dBufClean_buf + 31) & ~ 31);
284    aecm->dBufNoisy = (int16_t*) (((uintptr_t)aecm->dBufNoisy_buf + 31) & ~ 31);
285    aecm->outBuf = (int16_t*) (((uintptr_t)aecm->outBuf_buf + 15) & ~ 15);
286    aecm->channelStored = (int16_t*) (((uintptr_t)
287                                             aecm->channelStored_buf + 15) & ~ 15);
288    aecm->channelAdapt16 = (int16_t*) (((uintptr_t)
289                                              aecm->channelAdapt16_buf + 15) & ~ 15);
290    aecm->channelAdapt32 = (int32_t*) (((uintptr_t)
291                                              aecm->channelAdapt32_buf + 31) & ~ 31);
292
293    return 0;
294}
295
296void WebRtcAecm_InitEchoPathCore(AecmCore_t* aecm, const int16_t* echo_path)
297{
298    int i = 0;
299
300    // Reset the stored channel
301    memcpy(aecm->channelStored, echo_path, sizeof(int16_t) * PART_LEN1);
302    // Reset the adapted channels
303    memcpy(aecm->channelAdapt16, echo_path, sizeof(int16_t) * PART_LEN1);
304    for (i = 0; i < PART_LEN1; i++)
305    {
306        aecm->channelAdapt32[i] = WEBRTC_SPL_LSHIFT_W32(
307            (int32_t)(aecm->channelAdapt16[i]), 16);
308    }
309
310    // Reset channel storing variables
311    aecm->mseAdaptOld = 1000;
312    aecm->mseStoredOld = 1000;
313    aecm->mseThreshold = WEBRTC_SPL_WORD32_MAX;
314    aecm->mseChannelCount = 0;
315}
316
317static void CalcLinearEnergiesC(AecmCore_t* aecm,
318                                const uint16_t* far_spectrum,
319                                int32_t* echo_est,
320                                uint32_t* far_energy,
321                                uint32_t* echo_energy_adapt,
322                                uint32_t* echo_energy_stored)
323{
324    int i;
325
326    // Get energy for the delayed far end signal and estimated
327    // echo using both stored and adapted channels.
328    for (i = 0; i < PART_LEN1; i++)
329    {
330        echo_est[i] = WEBRTC_SPL_MUL_16_U16(aecm->channelStored[i],
331                                           far_spectrum[i]);
332        (*far_energy) += (uint32_t)(far_spectrum[i]);
333        (*echo_energy_adapt) += WEBRTC_SPL_UMUL_16_16(aecm->channelAdapt16[i],
334                                          far_spectrum[i]);
335        (*echo_energy_stored) += (uint32_t)echo_est[i];
336    }
337}
338
339static void StoreAdaptiveChannelC(AecmCore_t* aecm,
340                                  const uint16_t* far_spectrum,
341                                  int32_t* echo_est)
342{
343    int i;
344
345    // During startup we store the channel every block.
346    memcpy(aecm->channelStored, aecm->channelAdapt16, sizeof(int16_t) * PART_LEN1);
347    // Recalculate echo estimate
348    for (i = 0; i < PART_LEN; i += 4)
349    {
350        echo_est[i] = WEBRTC_SPL_MUL_16_U16(aecm->channelStored[i],
351                                           far_spectrum[i]);
352        echo_est[i + 1] = WEBRTC_SPL_MUL_16_U16(aecm->channelStored[i + 1],
353                                           far_spectrum[i + 1]);
354        echo_est[i + 2] = WEBRTC_SPL_MUL_16_U16(aecm->channelStored[i + 2],
355                                           far_spectrum[i + 2]);
356        echo_est[i + 3] = WEBRTC_SPL_MUL_16_U16(aecm->channelStored[i + 3],
357                                           far_spectrum[i + 3]);
358    }
359    echo_est[i] = WEBRTC_SPL_MUL_16_U16(aecm->channelStored[i],
360                                       far_spectrum[i]);
361}
362
363static void ResetAdaptiveChannelC(AecmCore_t* aecm)
364{
365    int i;
366
367    // The stored channel has a significantly lower MSE than the adaptive one for
368    // two consecutive calculations. Reset the adaptive channel.
369    memcpy(aecm->channelAdapt16, aecm->channelStored,
370           sizeof(int16_t) * PART_LEN1);
371    // Restore the W32 channel
372    for (i = 0; i < PART_LEN; i += 4)
373    {
374        aecm->channelAdapt32[i] = WEBRTC_SPL_LSHIFT_W32(
375                (int32_t)aecm->channelStored[i], 16);
376        aecm->channelAdapt32[i + 1] = WEBRTC_SPL_LSHIFT_W32(
377                (int32_t)aecm->channelStored[i + 1], 16);
378        aecm->channelAdapt32[i + 2] = WEBRTC_SPL_LSHIFT_W32(
379                (int32_t)aecm->channelStored[i + 2], 16);
380        aecm->channelAdapt32[i + 3] = WEBRTC_SPL_LSHIFT_W32(
381                (int32_t)aecm->channelStored[i + 3], 16);
382    }
383    aecm->channelAdapt32[i] = WEBRTC_SPL_LSHIFT_W32((int32_t)aecm->channelStored[i], 16);
384}
385
386// Initialize function pointers for ARM Neon platform.
387#if (defined WEBRTC_DETECT_ARM_NEON || defined WEBRTC_ARCH_ARM_NEON)
388static void WebRtcAecm_InitNeon(void)
389{
390  WebRtcAecm_StoreAdaptiveChannel = WebRtcAecm_StoreAdaptiveChannelNeon;
391  WebRtcAecm_ResetAdaptiveChannel = WebRtcAecm_ResetAdaptiveChannelNeon;
392  WebRtcAecm_CalcLinearEnergies = WebRtcAecm_CalcLinearEnergiesNeon;
393}
394#endif
395
396// Initialize function pointers for MIPS platform.
397#if defined(MIPS32_LE)
398static void WebRtcAecm_InitMips(void)
399{
400#if defined(MIPS_DSP_R1_LE)
401  WebRtcAecm_StoreAdaptiveChannel = WebRtcAecm_StoreAdaptiveChannel_mips;
402  WebRtcAecm_ResetAdaptiveChannel = WebRtcAecm_ResetAdaptiveChannel_mips;
403#endif
404  WebRtcAecm_CalcLinearEnergies = WebRtcAecm_CalcLinearEnergies_mips;
405}
406#endif
407
408// WebRtcAecm_InitCore(...)
409//
410// This function initializes the AECM instant created with WebRtcAecm_CreateCore(...)
411// Input:
412//      - aecm            : Pointer to the Echo Suppression instance
413//      - samplingFreq   : Sampling Frequency
414//
415// Output:
416//      - aecm            : Initialized instance
417//
418// Return value         :  0 - Ok
419//                        -1 - Error
420//
421int WebRtcAecm_InitCore(AecmCore_t * const aecm, int samplingFreq)
422{
423    int i = 0;
424    int32_t tmp32 = PART_LEN1 * PART_LEN1;
425    int16_t tmp16 = PART_LEN1;
426
427    if (samplingFreq != 8000 && samplingFreq != 16000)
428    {
429        samplingFreq = 8000;
430        return -1;
431    }
432    // sanity check of sampling frequency
433    aecm->mult = (int16_t)samplingFreq / 8000;
434
435    aecm->farBufWritePos = 0;
436    aecm->farBufReadPos = 0;
437    aecm->knownDelay = 0;
438    aecm->lastKnownDelay = 0;
439
440    WebRtc_InitBuffer(aecm->farFrameBuf);
441    WebRtc_InitBuffer(aecm->nearNoisyFrameBuf);
442    WebRtc_InitBuffer(aecm->nearCleanFrameBuf);
443    WebRtc_InitBuffer(aecm->outFrameBuf);
444
445    memset(aecm->xBuf_buf, 0, sizeof(aecm->xBuf_buf));
446    memset(aecm->dBufClean_buf, 0, sizeof(aecm->dBufClean_buf));
447    memset(aecm->dBufNoisy_buf, 0, sizeof(aecm->dBufNoisy_buf));
448    memset(aecm->outBuf_buf, 0, sizeof(aecm->outBuf_buf));
449
450    aecm->seed = 666;
451    aecm->totCount = 0;
452
453    if (WebRtc_InitDelayEstimatorFarend(aecm->delay_estimator_farend) != 0) {
454      return -1;
455    }
456    if (WebRtc_InitDelayEstimator(aecm->delay_estimator) != 0) {
457      return -1;
458    }
459    // Set far end histories to zero
460    memset(aecm->far_history, 0, sizeof(uint16_t) * PART_LEN1 * MAX_DELAY);
461    memset(aecm->far_q_domains, 0, sizeof(int) * MAX_DELAY);
462    aecm->far_history_pos = MAX_DELAY;
463
464    aecm->nlpFlag = 1;
465    aecm->fixedDelay = -1;
466
467    aecm->dfaCleanQDomain = 0;
468    aecm->dfaCleanQDomainOld = 0;
469    aecm->dfaNoisyQDomain = 0;
470    aecm->dfaNoisyQDomainOld = 0;
471
472    memset(aecm->nearLogEnergy, 0, sizeof(aecm->nearLogEnergy));
473    aecm->farLogEnergy = 0;
474    memset(aecm->echoAdaptLogEnergy, 0, sizeof(aecm->echoAdaptLogEnergy));
475    memset(aecm->echoStoredLogEnergy, 0, sizeof(aecm->echoStoredLogEnergy));
476
477    // Initialize the echo channels with a stored shape.
478    if (samplingFreq == 8000)
479    {
480        WebRtcAecm_InitEchoPathCore(aecm, kChannelStored8kHz);
481    }
482    else
483    {
484        WebRtcAecm_InitEchoPathCore(aecm, kChannelStored16kHz);
485    }
486
487    memset(aecm->echoFilt, 0, sizeof(aecm->echoFilt));
488    memset(aecm->nearFilt, 0, sizeof(aecm->nearFilt));
489    aecm->noiseEstCtr = 0;
490
491    aecm->cngMode = AecmTrue;
492
493    memset(aecm->noiseEstTooLowCtr, 0, sizeof(aecm->noiseEstTooLowCtr));
494    memset(aecm->noiseEstTooHighCtr, 0, sizeof(aecm->noiseEstTooHighCtr));
495    // Shape the initial noise level to an approximate pink noise.
496    for (i = 0; i < (PART_LEN1 >> 1) - 1; i++)
497    {
498        aecm->noiseEst[i] = (tmp32 << 8);
499        tmp16--;
500        tmp32 -= (int32_t)((tmp16 << 1) + 1);
501    }
502    for (; i < PART_LEN1; i++)
503    {
504        aecm->noiseEst[i] = (tmp32 << 8);
505    }
506
507    aecm->farEnergyMin = WEBRTC_SPL_WORD16_MAX;
508    aecm->farEnergyMax = WEBRTC_SPL_WORD16_MIN;
509    aecm->farEnergyMaxMin = 0;
510    aecm->farEnergyVAD = FAR_ENERGY_MIN; // This prevents false speech detection at the
511                                         // beginning.
512    aecm->farEnergyMSE = 0;
513    aecm->currentVADValue = 0;
514    aecm->vadUpdateCount = 0;
515    aecm->firstVAD = 1;
516
517    aecm->startupState = 0;
518    aecm->supGain = SUPGAIN_DEFAULT;
519    aecm->supGainOld = SUPGAIN_DEFAULT;
520
521    aecm->supGainErrParamA = SUPGAIN_ERROR_PARAM_A;
522    aecm->supGainErrParamD = SUPGAIN_ERROR_PARAM_D;
523    aecm->supGainErrParamDiffAB = SUPGAIN_ERROR_PARAM_A - SUPGAIN_ERROR_PARAM_B;
524    aecm->supGainErrParamDiffBD = SUPGAIN_ERROR_PARAM_B - SUPGAIN_ERROR_PARAM_D;
525
526    // Assert a preprocessor definition at compile-time. It's an assumption
527    // used in assembly code, so check the assembly files before any change.
528    COMPILE_ASSERT(PART_LEN % 16 == 0);
529
530    // Initialize function pointers.
531    WebRtcAecm_CalcLinearEnergies = CalcLinearEnergiesC;
532    WebRtcAecm_StoreAdaptiveChannel = StoreAdaptiveChannelC;
533    WebRtcAecm_ResetAdaptiveChannel = ResetAdaptiveChannelC;
534
535#ifdef WEBRTC_DETECT_ARM_NEON
536    uint64_t features = WebRtc_GetCPUFeaturesARM();
537    if ((features & kCPUFeatureNEON) != 0)
538    {
539      WebRtcAecm_InitNeon();
540    }
541#elif defined(WEBRTC_ARCH_ARM_NEON)
542    WebRtcAecm_InitNeon();
543#endif
544
545#if defined(MIPS32_LE)
546    WebRtcAecm_InitMips();
547#endif
548    return 0;
549}
550
551// TODO(bjornv): This function is currently not used. Add support for these
552// parameters from a higher level
553int WebRtcAecm_Control(AecmCore_t *aecm, int delay, int nlpFlag)
554{
555    aecm->nlpFlag = nlpFlag;
556    aecm->fixedDelay = delay;
557
558    return 0;
559}
560
561int WebRtcAecm_FreeCore(AecmCore_t *aecm)
562{
563    if (aecm == NULL)
564    {
565        return -1;
566    }
567
568    WebRtc_FreeBuffer(aecm->farFrameBuf);
569    WebRtc_FreeBuffer(aecm->nearNoisyFrameBuf);
570    WebRtc_FreeBuffer(aecm->nearCleanFrameBuf);
571    WebRtc_FreeBuffer(aecm->outFrameBuf);
572
573    WebRtc_FreeDelayEstimator(aecm->delay_estimator);
574    WebRtc_FreeDelayEstimatorFarend(aecm->delay_estimator_farend);
575    WebRtcSpl_FreeRealFFT(aecm->real_fft);
576
577    free(aecm);
578
579    return 0;
580}
581
582int WebRtcAecm_ProcessFrame(AecmCore_t * aecm,
583                            const int16_t * farend,
584                            const int16_t * nearendNoisy,
585                            const int16_t * nearendClean,
586                            int16_t * out)
587{
588    int16_t outBlock_buf[PART_LEN + 8]; // Align buffer to 8-byte boundary.
589    int16_t* outBlock = (int16_t*) (((uintptr_t) outBlock_buf + 15) & ~ 15);
590
591    int16_t farFrame[FRAME_LEN];
592    const int16_t* out_ptr = NULL;
593    int size = 0;
594
595    // Buffer the current frame.
596    // Fetch an older one corresponding to the delay.
597    WebRtcAecm_BufferFarFrame(aecm, farend, FRAME_LEN);
598    WebRtcAecm_FetchFarFrame(aecm, farFrame, FRAME_LEN, aecm->knownDelay);
599
600    // Buffer the synchronized far and near frames,
601    // to pass the smaller blocks individually.
602    WebRtc_WriteBuffer(aecm->farFrameBuf, farFrame, FRAME_LEN);
603    WebRtc_WriteBuffer(aecm->nearNoisyFrameBuf, nearendNoisy, FRAME_LEN);
604    if (nearendClean != NULL)
605    {
606        WebRtc_WriteBuffer(aecm->nearCleanFrameBuf, nearendClean, FRAME_LEN);
607    }
608
609    // Process as many blocks as possible.
610    while (WebRtc_available_read(aecm->farFrameBuf) >= PART_LEN)
611    {
612        int16_t far_block[PART_LEN];
613        const int16_t* far_block_ptr = NULL;
614        int16_t near_noisy_block[PART_LEN];
615        const int16_t* near_noisy_block_ptr = NULL;
616
617        WebRtc_ReadBuffer(aecm->farFrameBuf, (void**) &far_block_ptr, far_block,
618                          PART_LEN);
619        WebRtc_ReadBuffer(aecm->nearNoisyFrameBuf,
620                          (void**) &near_noisy_block_ptr,
621                          near_noisy_block,
622                          PART_LEN);
623        if (nearendClean != NULL)
624        {
625            int16_t near_clean_block[PART_LEN];
626            const int16_t* near_clean_block_ptr = NULL;
627
628            WebRtc_ReadBuffer(aecm->nearCleanFrameBuf,
629                              (void**) &near_clean_block_ptr,
630                              near_clean_block,
631                              PART_LEN);
632            if (WebRtcAecm_ProcessBlock(aecm,
633                                        far_block_ptr,
634                                        near_noisy_block_ptr,
635                                        near_clean_block_ptr,
636                                        outBlock) == -1)
637            {
638                return -1;
639            }
640        } else
641        {
642            if (WebRtcAecm_ProcessBlock(aecm,
643                                        far_block_ptr,
644                                        near_noisy_block_ptr,
645                                        NULL,
646                                        outBlock) == -1)
647            {
648                return -1;
649            }
650        }
651
652        WebRtc_WriteBuffer(aecm->outFrameBuf, outBlock, PART_LEN);
653    }
654
655    // Stuff the out buffer if we have less than a frame to output.
656    // This should only happen for the first frame.
657    size = (int) WebRtc_available_read(aecm->outFrameBuf);
658    if (size < FRAME_LEN)
659    {
660        WebRtc_MoveReadPtr(aecm->outFrameBuf, size - FRAME_LEN);
661    }
662
663    // Obtain an output frame.
664    WebRtc_ReadBuffer(aecm->outFrameBuf, (void**) &out_ptr, out, FRAME_LEN);
665    if (out_ptr != out) {
666      // ReadBuffer() hasn't copied to |out| in this case.
667      memcpy(out, out_ptr, FRAME_LEN * sizeof(int16_t));
668    }
669
670    return 0;
671}
672
673// WebRtcAecm_AsymFilt(...)
674//
675// Performs asymmetric filtering.
676//
677// Inputs:
678//      - filtOld       : Previous filtered value.
679//      - inVal         : New input value.
680//      - stepSizePos   : Step size when we have a positive contribution.
681//      - stepSizeNeg   : Step size when we have a negative contribution.
682//
683// Output:
684//
685// Return: - Filtered value.
686//
687int16_t WebRtcAecm_AsymFilt(const int16_t filtOld, const int16_t inVal,
688                            const int16_t stepSizePos,
689                            const int16_t stepSizeNeg)
690{
691    int16_t retVal;
692
693    if ((filtOld == WEBRTC_SPL_WORD16_MAX) | (filtOld == WEBRTC_SPL_WORD16_MIN))
694    {
695        return inVal;
696    }
697    retVal = filtOld;
698    if (filtOld > inVal)
699    {
700        retVal -= WEBRTC_SPL_RSHIFT_W16(filtOld - inVal, stepSizeNeg);
701    } else
702    {
703        retVal += WEBRTC_SPL_RSHIFT_W16(inVal - filtOld, stepSizePos);
704    }
705
706    return retVal;
707}
708
709// WebRtcAecm_CalcEnergies(...)
710//
711// This function calculates the log of energies for nearend, farend and estimated
712// echoes. There is also an update of energy decision levels, i.e. internal VAD.
713//
714//
715// @param  aecm         [i/o]   Handle of the AECM instance.
716// @param  far_spectrum [in]    Pointer to farend spectrum.
717// @param  far_q        [in]    Q-domain of farend spectrum.
718// @param  nearEner     [in]    Near end energy for current block in
719//                              Q(aecm->dfaQDomain).
720// @param  echoEst      [out]   Estimated echo in Q(xfa_q+RESOLUTION_CHANNEL16).
721//
722void WebRtcAecm_CalcEnergies(AecmCore_t * aecm,
723                             const uint16_t* far_spectrum,
724                             const int16_t far_q,
725                             const uint32_t nearEner,
726                             int32_t * echoEst)
727{
728    // Local variables
729    uint32_t tmpAdapt = 0;
730    uint32_t tmpStored = 0;
731    uint32_t tmpFar = 0;
732
733    int i;
734
735    int16_t zeros, frac;
736    int16_t tmp16;
737    int16_t increase_max_shifts = 4;
738    int16_t decrease_max_shifts = 11;
739    int16_t increase_min_shifts = 11;
740    int16_t decrease_min_shifts = 3;
741    int16_t kLogLowValue = WEBRTC_SPL_LSHIFT_W16(PART_LEN_SHIFT, 7);
742
743    // Get log of near end energy and store in buffer
744
745    // Shift buffer
746    memmove(aecm->nearLogEnergy + 1, aecm->nearLogEnergy,
747            sizeof(int16_t) * (MAX_BUF_LEN - 1));
748
749    // Logarithm of integrated magnitude spectrum (nearEner)
750    tmp16 = kLogLowValue;
751    if (nearEner)
752    {
753        zeros = WebRtcSpl_NormU32(nearEner);
754        frac = (int16_t)WEBRTC_SPL_RSHIFT_U32(
755                              (WEBRTC_SPL_LSHIFT_U32(nearEner, zeros) & 0x7FFFFFFF),
756                              23);
757        // log2 in Q8
758        tmp16 += WEBRTC_SPL_LSHIFT_W16((31 - zeros), 8) + frac;
759        tmp16 -= WEBRTC_SPL_LSHIFT_W16(aecm->dfaNoisyQDomain, 8);
760    }
761    aecm->nearLogEnergy[0] = tmp16;
762    // END: Get log of near end energy
763
764    WebRtcAecm_CalcLinearEnergies(aecm, far_spectrum, echoEst, &tmpFar, &tmpAdapt, &tmpStored);
765
766    // Shift buffers
767    memmove(aecm->echoAdaptLogEnergy + 1, aecm->echoAdaptLogEnergy,
768            sizeof(int16_t) * (MAX_BUF_LEN - 1));
769    memmove(aecm->echoStoredLogEnergy + 1, aecm->echoStoredLogEnergy,
770            sizeof(int16_t) * (MAX_BUF_LEN - 1));
771
772    // Logarithm of delayed far end energy
773    tmp16 = kLogLowValue;
774    if (tmpFar)
775    {
776        zeros = WebRtcSpl_NormU32(tmpFar);
777        frac = (int16_t)WEBRTC_SPL_RSHIFT_U32((WEBRTC_SPL_LSHIFT_U32(tmpFar, zeros)
778                        & 0x7FFFFFFF), 23);
779        // log2 in Q8
780        tmp16 += WEBRTC_SPL_LSHIFT_W16((31 - zeros), 8) + frac;
781        tmp16 -= WEBRTC_SPL_LSHIFT_W16(far_q, 8);
782    }
783    aecm->farLogEnergy = tmp16;
784
785    // Logarithm of estimated echo energy through adapted channel
786    tmp16 = kLogLowValue;
787    if (tmpAdapt)
788    {
789        zeros = WebRtcSpl_NormU32(tmpAdapt);
790        frac = (int16_t)WEBRTC_SPL_RSHIFT_U32((WEBRTC_SPL_LSHIFT_U32(tmpAdapt, zeros)
791                        & 0x7FFFFFFF), 23);
792        //log2 in Q8
793        tmp16 += WEBRTC_SPL_LSHIFT_W16((31 - zeros), 8) + frac;
794        tmp16 -= WEBRTC_SPL_LSHIFT_W16(RESOLUTION_CHANNEL16 + far_q, 8);
795    }
796    aecm->echoAdaptLogEnergy[0] = tmp16;
797
798    // Logarithm of estimated echo energy through stored channel
799    tmp16 = kLogLowValue;
800    if (tmpStored)
801    {
802        zeros = WebRtcSpl_NormU32(tmpStored);
803        frac = (int16_t)WEBRTC_SPL_RSHIFT_U32((WEBRTC_SPL_LSHIFT_U32(tmpStored, zeros)
804                        & 0x7FFFFFFF), 23);
805        //log2 in Q8
806        tmp16 += WEBRTC_SPL_LSHIFT_W16((31 - zeros), 8) + frac;
807        tmp16 -= WEBRTC_SPL_LSHIFT_W16(RESOLUTION_CHANNEL16 + far_q, 8);
808    }
809    aecm->echoStoredLogEnergy[0] = tmp16;
810
811    // Update farend energy levels (min, max, vad, mse)
812    if (aecm->farLogEnergy > FAR_ENERGY_MIN)
813    {
814        if (aecm->startupState == 0)
815        {
816            increase_max_shifts = 2;
817            decrease_min_shifts = 2;
818            increase_min_shifts = 8;
819        }
820
821        aecm->farEnergyMin = WebRtcAecm_AsymFilt(aecm->farEnergyMin, aecm->farLogEnergy,
822                                                 increase_min_shifts, decrease_min_shifts);
823        aecm->farEnergyMax = WebRtcAecm_AsymFilt(aecm->farEnergyMax, aecm->farLogEnergy,
824                                                 increase_max_shifts, decrease_max_shifts);
825        aecm->farEnergyMaxMin = (aecm->farEnergyMax - aecm->farEnergyMin);
826
827        // Dynamic VAD region size
828        tmp16 = 2560 - aecm->farEnergyMin;
829        if (tmp16 > 0)
830        {
831            tmp16 = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(tmp16, FAR_ENERGY_VAD_REGION, 9);
832        } else
833        {
834            tmp16 = 0;
835        }
836        tmp16 += FAR_ENERGY_VAD_REGION;
837
838        if ((aecm->startupState == 0) | (aecm->vadUpdateCount > 1024))
839        {
840            // In startup phase or VAD update halted
841            aecm->farEnergyVAD = aecm->farEnergyMin + tmp16;
842        } else
843        {
844            if (aecm->farEnergyVAD > aecm->farLogEnergy)
845            {
846                aecm->farEnergyVAD += WEBRTC_SPL_RSHIFT_W16(aecm->farLogEnergy +
847                                                            tmp16 -
848                                                            aecm->farEnergyVAD,
849                                                            6);
850                aecm->vadUpdateCount = 0;
851            } else
852            {
853                aecm->vadUpdateCount++;
854            }
855        }
856        // Put MSE threshold higher than VAD
857        aecm->farEnergyMSE = aecm->farEnergyVAD + (1 << 8);
858    }
859
860    // Update VAD variables
861    if (aecm->farLogEnergy > aecm->farEnergyVAD)
862    {
863        if ((aecm->startupState == 0) | (aecm->farEnergyMaxMin > FAR_ENERGY_DIFF))
864        {
865            // We are in startup or have significant dynamics in input speech level
866            aecm->currentVADValue = 1;
867        }
868    } else
869    {
870        aecm->currentVADValue = 0;
871    }
872    if ((aecm->currentVADValue) && (aecm->firstVAD))
873    {
874        aecm->firstVAD = 0;
875        if (aecm->echoAdaptLogEnergy[0] > aecm->nearLogEnergy[0])
876        {
877            // The estimated echo has higher energy than the near end signal.
878            // This means that the initialization was too aggressive. Scale
879            // down by a factor 8
880            for (i = 0; i < PART_LEN1; i++)
881            {
882                aecm->channelAdapt16[i] >>= 3;
883            }
884            // Compensate the adapted echo energy level accordingly.
885            aecm->echoAdaptLogEnergy[0] -= (3 << 8);
886            aecm->firstVAD = 1;
887        }
888    }
889}
890
891// WebRtcAecm_CalcStepSize(...)
892//
893// This function calculates the step size used in channel estimation
894//
895//
896// @param  aecm  [in]    Handle of the AECM instance.
897// @param  mu    [out]   (Return value) Stepsize in log2(), i.e. number of shifts.
898//
899//
900int16_t WebRtcAecm_CalcStepSize(AecmCore_t * const aecm)
901{
902
903    int32_t tmp32;
904    int16_t tmp16;
905    int16_t mu = MU_MAX;
906
907    // Here we calculate the step size mu used in the
908    // following NLMS based Channel estimation algorithm
909    if (!aecm->currentVADValue)
910    {
911        // Far end energy level too low, no channel update
912        mu = 0;
913    } else if (aecm->startupState > 0)
914    {
915        if (aecm->farEnergyMin >= aecm->farEnergyMax)
916        {
917            mu = MU_MIN;
918        } else
919        {
920            tmp16 = (aecm->farLogEnergy - aecm->farEnergyMin);
921            tmp32 = WEBRTC_SPL_MUL_16_16(tmp16, MU_DIFF);
922            tmp32 = WebRtcSpl_DivW32W16(tmp32, aecm->farEnergyMaxMin);
923            mu = MU_MIN - 1 - (int16_t)(tmp32);
924            // The -1 is an alternative to rounding. This way we get a larger
925            // stepsize, so we in some sense compensate for truncation in NLMS
926        }
927        if (mu < MU_MAX)
928        {
929            mu = MU_MAX; // Equivalent with maximum step size of 2^-MU_MAX
930        }
931    }
932
933    return mu;
934}
935
936// WebRtcAecm_UpdateChannel(...)
937//
938// This function performs channel estimation. NLMS and decision on channel storage.
939//
940//
941// @param  aecm         [i/o]   Handle of the AECM instance.
942// @param  far_spectrum [in]    Absolute value of the farend signal in Q(far_q)
943// @param  far_q        [in]    Q-domain of the farend signal
944// @param  dfa          [in]    Absolute value of the nearend signal (Q[aecm->dfaQDomain])
945// @param  mu           [in]    NLMS step size.
946// @param  echoEst      [i/o]   Estimated echo in Q(far_q+RESOLUTION_CHANNEL16).
947//
948void WebRtcAecm_UpdateChannel(AecmCore_t * aecm,
949                              const uint16_t* far_spectrum,
950                              const int16_t far_q,
951                              const uint16_t * const dfa,
952                              const int16_t mu,
953                              int32_t * echoEst)
954{
955
956    uint32_t tmpU32no1, tmpU32no2;
957    int32_t tmp32no1, tmp32no2;
958    int32_t mseStored;
959    int32_t mseAdapt;
960
961    int i;
962
963    int16_t zerosFar, zerosNum, zerosCh, zerosDfa;
964    int16_t shiftChFar, shiftNum, shift2ResChan;
965    int16_t tmp16no1;
966    int16_t xfaQ, dfaQ;
967
968    // This is the channel estimation algorithm. It is base on NLMS but has a variable step
969    // length, which was calculated above.
970    if (mu)
971    {
972        for (i = 0; i < PART_LEN1; i++)
973        {
974            // Determine norm of channel and farend to make sure we don't get overflow in
975            // multiplication
976            zerosCh = WebRtcSpl_NormU32(aecm->channelAdapt32[i]);
977            zerosFar = WebRtcSpl_NormU32((uint32_t)far_spectrum[i]);
978            if (zerosCh + zerosFar > 31)
979            {
980                // Multiplication is safe
981                tmpU32no1 = WEBRTC_SPL_UMUL_32_16(aecm->channelAdapt32[i],
982                        far_spectrum[i]);
983                shiftChFar = 0;
984            } else
985            {
986                // We need to shift down before multiplication
987                shiftChFar = 32 - zerosCh - zerosFar;
988                tmpU32no1 = WEBRTC_SPL_UMUL_32_16(
989                    WEBRTC_SPL_RSHIFT_W32(aecm->channelAdapt32[i], shiftChFar),
990                    far_spectrum[i]);
991            }
992            // Determine Q-domain of numerator
993            zerosNum = WebRtcSpl_NormU32(tmpU32no1);
994            if (dfa[i])
995            {
996                zerosDfa = WebRtcSpl_NormU32((uint32_t)dfa[i]);
997            } else
998            {
999                zerosDfa = 32;
1000            }
1001            tmp16no1 = zerosDfa - 2 + aecm->dfaNoisyQDomain -
1002                RESOLUTION_CHANNEL32 - far_q + shiftChFar;
1003            if (zerosNum > tmp16no1 + 1)
1004            {
1005                xfaQ = tmp16no1;
1006                dfaQ = zerosDfa - 2;
1007            } else
1008            {
1009                xfaQ = zerosNum - 2;
1010                dfaQ = RESOLUTION_CHANNEL32 + far_q - aecm->dfaNoisyQDomain -
1011                    shiftChFar + xfaQ;
1012            }
1013            // Add in the same Q-domain
1014            tmpU32no1 = WEBRTC_SPL_SHIFT_W32(tmpU32no1, xfaQ);
1015            tmpU32no2 = WEBRTC_SPL_SHIFT_W32((uint32_t)dfa[i], dfaQ);
1016            tmp32no1 = (int32_t)tmpU32no2 - (int32_t)tmpU32no1;
1017            zerosNum = WebRtcSpl_NormW32(tmp32no1);
1018            if ((tmp32no1) && (far_spectrum[i] > (CHANNEL_VAD << far_q)))
1019            {
1020                //
1021                // Update is needed
1022                //
1023                // This is what we would like to compute
1024                //
1025                // tmp32no1 = dfa[i] - (aecm->channelAdapt[i] * far_spectrum[i])
1026                // tmp32norm = (i + 1)
1027                // aecm->channelAdapt[i] += (2^mu) * tmp32no1
1028                //                        / (tmp32norm * far_spectrum[i])
1029                //
1030
1031                // Make sure we don't get overflow in multiplication.
1032                if (zerosNum + zerosFar > 31)
1033                {
1034                    if (tmp32no1 > 0)
1035                    {
1036                        tmp32no2 = (int32_t)WEBRTC_SPL_UMUL_32_16(tmp32no1,
1037                                                                        far_spectrum[i]);
1038                    } else
1039                    {
1040                        tmp32no2 = -(int32_t)WEBRTC_SPL_UMUL_32_16(-tmp32no1,
1041                                                                         far_spectrum[i]);
1042                    }
1043                    shiftNum = 0;
1044                } else
1045                {
1046                    shiftNum = 32 - (zerosNum + zerosFar);
1047                    if (tmp32no1 > 0)
1048                    {
1049                        tmp32no2 = (int32_t)WEBRTC_SPL_UMUL_32_16(
1050                                WEBRTC_SPL_RSHIFT_W32(tmp32no1, shiftNum),
1051                                far_spectrum[i]);
1052                    } else
1053                    {
1054                        tmp32no2 = -(int32_t)WEBRTC_SPL_UMUL_32_16(
1055                                WEBRTC_SPL_RSHIFT_W32(-tmp32no1, shiftNum),
1056                                far_spectrum[i]);
1057                    }
1058                }
1059                // Normalize with respect to frequency bin
1060                tmp32no2 = WebRtcSpl_DivW32W16(tmp32no2, i + 1);
1061                // Make sure we are in the right Q-domain
1062                shift2ResChan = shiftNum + shiftChFar - xfaQ - mu - ((30 - zerosFar) << 1);
1063                if (WebRtcSpl_NormW32(tmp32no2) < shift2ResChan)
1064                {
1065                    tmp32no2 = WEBRTC_SPL_WORD32_MAX;
1066                } else
1067                {
1068                    tmp32no2 = WEBRTC_SPL_SHIFT_W32(tmp32no2, shift2ResChan);
1069                }
1070                aecm->channelAdapt32[i] = WEBRTC_SPL_ADD_SAT_W32(aecm->channelAdapt32[i],
1071                        tmp32no2);
1072                if (aecm->channelAdapt32[i] < 0)
1073                {
1074                    // We can never have negative channel gain
1075                    aecm->channelAdapt32[i] = 0;
1076                }
1077                aecm->channelAdapt16[i]
1078                        = (int16_t)WEBRTC_SPL_RSHIFT_W32(aecm->channelAdapt32[i], 16);
1079            }
1080        }
1081    }
1082    // END: Adaptive channel update
1083
1084    // Determine if we should store or restore the channel
1085    if ((aecm->startupState == 0) & (aecm->currentVADValue))
1086    {
1087        // During startup we store the channel every block,
1088        // and we recalculate echo estimate
1089        WebRtcAecm_StoreAdaptiveChannel(aecm, far_spectrum, echoEst);
1090    } else
1091    {
1092        if (aecm->farLogEnergy < aecm->farEnergyMSE)
1093        {
1094            aecm->mseChannelCount = 0;
1095        } else
1096        {
1097            aecm->mseChannelCount++;
1098        }
1099        // Enough data for validation. Store channel if we can.
1100        if (aecm->mseChannelCount >= (MIN_MSE_COUNT + 10))
1101        {
1102            // We have enough data.
1103            // Calculate MSE of "Adapt" and "Stored" versions.
1104            // It is actually not MSE, but average absolute error.
1105            mseStored = 0;
1106            mseAdapt = 0;
1107            for (i = 0; i < MIN_MSE_COUNT; i++)
1108            {
1109                tmp32no1 = ((int32_t)aecm->echoStoredLogEnergy[i]
1110                        - (int32_t)aecm->nearLogEnergy[i]);
1111                tmp32no2 = WEBRTC_SPL_ABS_W32(tmp32no1);
1112                mseStored += tmp32no2;
1113
1114                tmp32no1 = ((int32_t)aecm->echoAdaptLogEnergy[i]
1115                        - (int32_t)aecm->nearLogEnergy[i]);
1116                tmp32no2 = WEBRTC_SPL_ABS_W32(tmp32no1);
1117                mseAdapt += tmp32no2;
1118            }
1119            if (((mseStored << MSE_RESOLUTION) < (MIN_MSE_DIFF * mseAdapt))
1120                    & ((aecm->mseStoredOld << MSE_RESOLUTION) < (MIN_MSE_DIFF
1121                            * aecm->mseAdaptOld)))
1122            {
1123                // The stored channel has a significantly lower MSE than the adaptive one for
1124                // two consecutive calculations. Reset the adaptive channel.
1125                WebRtcAecm_ResetAdaptiveChannel(aecm);
1126            } else if (((MIN_MSE_DIFF * mseStored) > (mseAdapt << MSE_RESOLUTION)) & (mseAdapt
1127                    < aecm->mseThreshold) & (aecm->mseAdaptOld < aecm->mseThreshold))
1128            {
1129                // The adaptive channel has a significantly lower MSE than the stored one.
1130                // The MSE for the adaptive channel has also been low for two consecutive
1131                // calculations. Store the adaptive channel.
1132                WebRtcAecm_StoreAdaptiveChannel(aecm, far_spectrum, echoEst);
1133
1134                // Update threshold
1135                if (aecm->mseThreshold == WEBRTC_SPL_WORD32_MAX)
1136                {
1137                    aecm->mseThreshold = (mseAdapt + aecm->mseAdaptOld);
1138                } else
1139                {
1140                    aecm->mseThreshold += WEBRTC_SPL_MUL_16_16_RSFT(mseAdapt
1141                            - WEBRTC_SPL_MUL_16_16_RSFT(aecm->mseThreshold, 5, 3), 205, 8);
1142                }
1143
1144            }
1145
1146            // Reset counter
1147            aecm->mseChannelCount = 0;
1148
1149            // Store the MSE values.
1150            aecm->mseStoredOld = mseStored;
1151            aecm->mseAdaptOld = mseAdapt;
1152        }
1153    }
1154    // END: Determine if we should store or reset channel estimate.
1155}
1156
1157// CalcSuppressionGain(...)
1158//
1159// This function calculates the suppression gain that is used in the Wiener filter.
1160//
1161//
1162// @param  aecm     [i/n]   Handle of the AECM instance.
1163// @param  supGain  [out]   (Return value) Suppression gain with which to scale the noise
1164//                          level (Q14).
1165//
1166//
1167int16_t WebRtcAecm_CalcSuppressionGain(AecmCore_t * const aecm)
1168{
1169    int32_t tmp32no1;
1170
1171    int16_t supGain = SUPGAIN_DEFAULT;
1172    int16_t tmp16no1;
1173    int16_t dE = 0;
1174
1175    // Determine suppression gain used in the Wiener filter. The gain is based on a mix of far
1176    // end energy and echo estimation error.
1177    // Adjust for the far end signal level. A low signal level indicates no far end signal,
1178    // hence we set the suppression gain to 0
1179    if (!aecm->currentVADValue)
1180    {
1181        supGain = 0;
1182    } else
1183    {
1184        // Adjust for possible double talk. If we have large variations in estimation error we
1185        // likely have double talk (or poor channel).
1186        tmp16no1 = (aecm->nearLogEnergy[0] - aecm->echoStoredLogEnergy[0] - ENERGY_DEV_OFFSET);
1187        dE = WEBRTC_SPL_ABS_W16(tmp16no1);
1188
1189        if (dE < ENERGY_DEV_TOL)
1190        {
1191            // Likely no double talk. The better estimation, the more we can suppress signal.
1192            // Update counters
1193            if (dE < SUPGAIN_EPC_DT)
1194            {
1195                tmp32no1 = WEBRTC_SPL_MUL_16_16(aecm->supGainErrParamDiffAB, dE);
1196                tmp32no1 += (SUPGAIN_EPC_DT >> 1);
1197                tmp16no1 = (int16_t)WebRtcSpl_DivW32W16(tmp32no1, SUPGAIN_EPC_DT);
1198                supGain = aecm->supGainErrParamA - tmp16no1;
1199            } else
1200            {
1201                tmp32no1 = WEBRTC_SPL_MUL_16_16(aecm->supGainErrParamDiffBD,
1202                                                (ENERGY_DEV_TOL - dE));
1203                tmp32no1 += ((ENERGY_DEV_TOL - SUPGAIN_EPC_DT) >> 1);
1204                tmp16no1 = (int16_t)WebRtcSpl_DivW32W16(tmp32no1, (ENERGY_DEV_TOL
1205                        - SUPGAIN_EPC_DT));
1206                supGain = aecm->supGainErrParamD + tmp16no1;
1207            }
1208        } else
1209        {
1210            // Likely in double talk. Use default value
1211            supGain = aecm->supGainErrParamD;
1212        }
1213    }
1214
1215    if (supGain > aecm->supGainOld)
1216    {
1217        tmp16no1 = supGain;
1218    } else
1219    {
1220        tmp16no1 = aecm->supGainOld;
1221    }
1222    aecm->supGainOld = supGain;
1223    if (tmp16no1 < aecm->supGain)
1224    {
1225        aecm->supGain += (int16_t)((tmp16no1 - aecm->supGain) >> 4);
1226    } else
1227    {
1228        aecm->supGain += (int16_t)((tmp16no1 - aecm->supGain) >> 4);
1229    }
1230
1231    // END: Update suppression gain
1232
1233    return aecm->supGain;
1234}
1235
1236void WebRtcAecm_BufferFarFrame(AecmCore_t* const aecm,
1237                               const int16_t* const farend,
1238                               const int farLen)
1239{
1240    int writeLen = farLen, writePos = 0;
1241
1242    // Check if the write position must be wrapped
1243    while (aecm->farBufWritePos + writeLen > FAR_BUF_LEN)
1244    {
1245        // Write to remaining buffer space before wrapping
1246        writeLen = FAR_BUF_LEN - aecm->farBufWritePos;
1247        memcpy(aecm->farBuf + aecm->farBufWritePos, farend + writePos,
1248               sizeof(int16_t) * writeLen);
1249        aecm->farBufWritePos = 0;
1250        writePos = writeLen;
1251        writeLen = farLen - writeLen;
1252    }
1253
1254    memcpy(aecm->farBuf + aecm->farBufWritePos, farend + writePos,
1255           sizeof(int16_t) * writeLen);
1256    aecm->farBufWritePos += writeLen;
1257}
1258
1259void WebRtcAecm_FetchFarFrame(AecmCore_t * const aecm, int16_t * const farend,
1260                              const int farLen, const int knownDelay)
1261{
1262    int readLen = farLen;
1263    int readPos = 0;
1264    int delayChange = knownDelay - aecm->lastKnownDelay;
1265
1266    aecm->farBufReadPos -= delayChange;
1267
1268    // Check if delay forces a read position wrap
1269    while (aecm->farBufReadPos < 0)
1270    {
1271        aecm->farBufReadPos += FAR_BUF_LEN;
1272    }
1273    while (aecm->farBufReadPos > FAR_BUF_LEN - 1)
1274    {
1275        aecm->farBufReadPos -= FAR_BUF_LEN;
1276    }
1277
1278    aecm->lastKnownDelay = knownDelay;
1279
1280    // Check if read position must be wrapped
1281    while (aecm->farBufReadPos + readLen > FAR_BUF_LEN)
1282    {
1283
1284        // Read from remaining buffer space before wrapping
1285        readLen = FAR_BUF_LEN - aecm->farBufReadPos;
1286        memcpy(farend + readPos, aecm->farBuf + aecm->farBufReadPos,
1287               sizeof(int16_t) * readLen);
1288        aecm->farBufReadPos = 0;
1289        readPos = readLen;
1290        readLen = farLen - readLen;
1291    }
1292    memcpy(farend + readPos, aecm->farBuf + aecm->farBufReadPos,
1293           sizeof(int16_t) * readLen);
1294    aecm->farBufReadPos += readLen;
1295}
1296