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