Home | History | Annotate | Download | only in aecm
      1 /*
      2  *  Copyright (c) 2011 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 "aecm_core.h"
     12 
     13 #include <assert.h>
     14 #include <stdlib.h>
     15 
     16 #include "cpu_features_wrapper.h"
     17 #include "delay_estimator_wrapper.h"
     18 #include "echo_control_mobile.h"
     19 #include "ring_buffer.h"
     20 #include "typedefs.h"
     21 
     22 #ifdef ARM_WINM_LOG
     23 #include <stdio.h>
     24 #include <windows.h>
     25 #endif
     26 
     27 #ifdef AEC_DEBUG
     28 FILE *dfile;
     29 FILE *testfile;
     30 #endif
     31 
     32 #ifdef _MSC_VER // visual c++
     33 #define ALIGN8_BEG __declspec(align(8))
     34 #define ALIGN8_END
     35 #else // gcc or icc
     36 #define ALIGN8_BEG
     37 #define ALIGN8_END __attribute__((aligned(8)))
     38 #endif
     39 
     40 #ifdef AECM_SHORT
     41 
     42 // Square root of Hanning window in Q14
     43 const WebRtc_Word16 WebRtcAecm_kSqrtHanning[] =
     44 {
     45     0, 804, 1606, 2404, 3196, 3981, 4756, 5520,
     46     6270, 7005, 7723, 8423, 9102, 9760, 10394, 11003,
     47     11585, 12140, 12665, 13160, 13623, 14053, 14449, 14811,
     48     15137, 15426, 15679, 15893, 16069, 16207, 16305, 16364,
     49     16384
     50 };
     51 
     52 #else
     53 
     54 // Square root of Hanning window in Q14
     55 const ALIGN8_BEG WebRtc_Word16 WebRtcAecm_kSqrtHanning[] ALIGN8_END =
     56 {
     57     0, 399, 798, 1196, 1594, 1990, 2386, 2780, 3172,
     58     3562, 3951, 4337, 4720, 5101, 5478, 5853, 6224, 6591, 6954, 7313, 7668, 8019, 8364,
     59     8705, 9040, 9370, 9695, 10013, 10326, 10633, 10933, 11227, 11514, 11795, 12068, 12335,
     60     12594, 12845, 13089, 13325, 13553, 13773, 13985, 14189, 14384, 14571, 14749, 14918,
     61     15079, 15231, 15373, 15506, 15631, 15746, 15851, 15947, 16034, 16111, 16179, 16237,
     62     16286, 16325, 16354, 16373, 16384
     63 };
     64 
     65 #endif
     66 
     67 //Q15 alpha = 0.99439986968132  const Factor for magnitude approximation
     68 static const WebRtc_UWord16 kAlpha1 = 32584;
     69 //Q15 beta = 0.12967166976970   const Factor for magnitude approximation
     70 static const WebRtc_UWord16 kBeta1 = 4249;
     71 //Q15 alpha = 0.94234827210087  const Factor for magnitude approximation
     72 static const WebRtc_UWord16 kAlpha2 = 30879;
     73 //Q15 beta = 0.33787806009150   const Factor for magnitude approximation
     74 static const WebRtc_UWord16 kBeta2 = 11072;
     75 //Q15 alpha = 0.82247698684306  const Factor for magnitude approximation
     76 static const WebRtc_UWord16 kAlpha3 = 26951;
     77 //Q15 beta = 0.57762063060713   const Factor for magnitude approximation
     78 static const WebRtc_UWord16 kBeta3 = 18927;
     79 
     80 // Initialization table for echo channel in 8 kHz
     81 static const WebRtc_Word16 kChannelStored8kHz[PART_LEN1] = {
     82     2040,   1815,   1590,   1498,   1405,   1395,   1385,   1418,
     83     1451,   1506,   1562,   1644,   1726,   1804,   1882,   1918,
     84     1953,   1982,   2010,   2025,   2040,   2034,   2027,   2021,
     85     2014,   1997,   1980,   1925,   1869,   1800,   1732,   1683,
     86     1635,   1604,   1572,   1545,   1517,   1481,   1444,   1405,
     87     1367,   1331,   1294,   1270,   1245,   1239,   1233,   1247,
     88     1260,   1282,   1303,   1338,   1373,   1407,   1441,   1470,
     89     1499,   1524,   1549,   1565,   1582,   1601,   1621,   1649,
     90     1676
     91 };
     92 
     93 // Initialization table for echo channel in 16 kHz
     94 static const WebRtc_Word16 kChannelStored16kHz[PART_LEN1] = {
     95     2040,   1590,   1405,   1385,   1451,   1562,   1726,   1882,
     96     1953,   2010,   2040,   2027,   2014,   1980,   1869,   1732,
     97     1635,   1572,   1517,   1444,   1367,   1294,   1245,   1233,
     98     1260,   1303,   1373,   1441,   1499,   1549,   1582,   1621,
     99     1676,   1741,   1802,   1861,   1921,   1983,   2040,   2102,
    100     2170,   2265,   2375,   2515,   2651,   2781,   2922,   3075,
    101     3253,   3471,   3738,   3976,   4151,   4258,   4308,   4288,
    102     4270,   4253,   4237,   4179,   4086,   3947,   3757,   3484,
    103     3153
    104 };
    105 
    106 static const WebRtc_Word16 kCosTable[] = {
    107     8192,  8190,  8187,  8180,  8172,  8160,  8147,  8130,  8112,
    108     8091,  8067,  8041,  8012,  7982,  7948,  7912,  7874,  7834,
    109     7791,  7745,  7697,  7647,  7595,  7540,  7483,  7424,  7362,
    110     7299,  7233,  7164,  7094,  7021,  6947,  6870,  6791,  6710,
    111     6627,  6542,  6455,  6366,  6275,  6182,  6087,  5991,  5892,
    112     5792,  5690,  5586,  5481,  5374,  5265,  5155,  5043,  4930,
    113     4815,  4698,  4580,  4461,  4341,  4219,  4096,  3971,  3845,
    114     3719,  3591,  3462,  3331,  3200,  3068,  2935,  2801,  2667,
    115     2531,  2395,  2258,  2120,  1981,  1842,  1703,  1563,  1422,
    116     1281,  1140,   998,   856,   713,   571,   428,   285,   142,
    117        0,  -142,  -285,  -428,  -571,  -713,  -856,  -998, -1140,
    118    -1281, -1422, -1563, -1703, -1842, -1981, -2120, -2258, -2395,
    119    -2531, -2667, -2801, -2935, -3068, -3200, -3331, -3462, -3591,
    120    -3719, -3845, -3971, -4095, -4219, -4341, -4461, -4580, -4698,
    121    -4815, -4930, -5043, -5155, -5265, -5374, -5481, -5586, -5690,
    122    -5792, -5892, -5991, -6087, -6182, -6275, -6366, -6455, -6542,
    123    -6627, -6710, -6791, -6870, -6947, -7021, -7094, -7164, -7233,
    124    -7299, -7362, -7424, -7483, -7540, -7595, -7647, -7697, -7745,
    125    -7791, -7834, -7874, -7912, -7948, -7982, -8012, -8041, -8067,
    126    -8091, -8112, -8130, -8147, -8160, -8172, -8180, -8187, -8190,
    127    -8191, -8190, -8187, -8180, -8172, -8160, -8147, -8130, -8112,
    128    -8091, -8067, -8041, -8012, -7982, -7948, -7912, -7874, -7834,
    129    -7791, -7745, -7697, -7647, -7595, -7540, -7483, -7424, -7362,
    130    -7299, -7233, -7164, -7094, -7021, -6947, -6870, -6791, -6710,
    131    -6627, -6542, -6455, -6366, -6275, -6182, -6087, -5991, -5892,
    132    -5792, -5690, -5586, -5481, -5374, -5265, -5155, -5043, -4930,
    133    -4815, -4698, -4580, -4461, -4341, -4219, -4096, -3971, -3845,
    134    -3719, -3591, -3462, -3331, -3200, -3068, -2935, -2801, -2667,
    135    -2531, -2395, -2258, -2120, -1981, -1842, -1703, -1563, -1422,
    136    -1281, -1140,  -998,  -856,  -713,  -571,  -428,  -285,  -142,
    137        0,   142,   285,   428,   571,   713,   856,   998,  1140,
    138     1281,  1422,  1563,  1703,  1842,  1981,  2120,  2258,  2395,
    139     2531,  2667,  2801,  2935,  3068,  3200,  3331,  3462,  3591,
    140     3719,  3845,  3971,  4095,  4219,  4341,  4461,  4580,  4698,
    141     4815,  4930,  5043,  5155,  5265,  5374,  5481,  5586,  5690,
    142     5792,  5892,  5991,  6087,  6182,  6275,  6366,  6455,  6542,
    143     6627,  6710,  6791,  6870,  6947,  7021,  7094,  7164,  7233,
    144     7299,  7362,  7424,  7483,  7540,  7595,  7647,  7697,  7745,
    145     7791,  7834,  7874,  7912,  7948,  7982,  8012,  8041,  8067,
    146     8091,  8112,  8130,  8147,  8160,  8172,  8180,  8187,  8190
    147 };
    148 
    149 static const WebRtc_Word16 kSinTable[] = {
    150        0,    142,    285,    428,    571,    713,    856,    998,
    151     1140,   1281,   1422,   1563,   1703,   1842,   1981,   2120,
    152     2258,   2395,   2531,   2667,   2801,   2935,   3068,   3200,
    153     3331,   3462,   3591,   3719,   3845,   3971,   4095,   4219,
    154     4341,   4461,   4580,   4698,   4815,   4930,   5043,   5155,
    155     5265,   5374,   5481,   5586,   5690,   5792,   5892,   5991,
    156     6087,   6182,   6275,   6366,   6455,   6542,   6627,   6710,
    157     6791,   6870,   6947,   7021,   7094,   7164,   7233,   7299,
    158     7362,   7424,   7483,   7540,   7595,   7647,   7697,   7745,
    159     7791,   7834,   7874,   7912,   7948,   7982,   8012,   8041,
    160     8067,   8091,   8112,   8130,   8147,   8160,   8172,   8180,
    161     8187,   8190,   8191,   8190,   8187,   8180,   8172,   8160,
    162     8147,   8130,   8112,   8091,   8067,   8041,   8012,   7982,
    163     7948,   7912,   7874,   7834,   7791,   7745,   7697,   7647,
    164     7595,   7540,   7483,   7424,   7362,   7299,   7233,   7164,
    165     7094,   7021,   6947,   6870,   6791,   6710,   6627,   6542,
    166     6455,   6366,   6275,   6182,   6087,   5991,   5892,   5792,
    167     5690,   5586,   5481,   5374,   5265,   5155,   5043,   4930,
    168     4815,   4698,   4580,   4461,   4341,   4219,   4096,   3971,
    169     3845,   3719,   3591,   3462,   3331,   3200,   3068,   2935,
    170     2801,   2667,   2531,   2395,   2258,   2120,   1981,   1842,
    171     1703,   1563,   1422,   1281,   1140,    998,    856,    713,
    172      571,    428,    285,    142,      0,   -142,   -285,   -428,
    173     -571,   -713,   -856,   -998,  -1140,  -1281,  -1422,  -1563,
    174    -1703,  -1842,  -1981,  -2120,  -2258,  -2395,  -2531,  -2667,
    175    -2801,  -2935,  -3068,  -3200,  -3331,  -3462,  -3591,  -3719,
    176    -3845,  -3971,  -4095,  -4219,  -4341,  -4461,  -4580,  -4698,
    177    -4815,  -4930,  -5043,  -5155,  -5265,  -5374,  -5481,  -5586,
    178    -5690,  -5792,  -5892,  -5991,  -6087,  -6182,  -6275,  -6366,
    179    -6455,  -6542,  -6627,  -6710,  -6791,  -6870,  -6947,  -7021,
    180    -7094,  -7164,  -7233,  -7299,  -7362,  -7424,  -7483,  -7540,
    181    -7595,  -7647,  -7697,  -7745,  -7791,  -7834,  -7874,  -7912,
    182    -7948,  -7982,  -8012,  -8041,  -8067,  -8091,  -8112,  -8130,
    183    -8147,  -8160,  -8172,  -8180,  -8187,  -8190,  -8191,  -8190,
    184    -8187,  -8180,  -8172,  -8160,  -8147,  -8130,  -8112,  -8091,
    185    -8067,  -8041,  -8012,  -7982,  -7948,  -7912,  -7874,  -7834,
    186    -7791,  -7745,  -7697,  -7647,  -7595,  -7540,  -7483,  -7424,
    187    -7362,  -7299,  -7233,  -7164,  -7094,  -7021,  -6947,  -6870,
    188    -6791,  -6710,  -6627,  -6542,  -6455,  -6366,  -6275,  -6182,
    189    -6087,  -5991,  -5892,  -5792,  -5690,  -5586,  -5481,  -5374,
    190    -5265,  -5155,  -5043,  -4930,  -4815,  -4698,  -4580,  -4461,
    191    -4341,  -4219,  -4096,  -3971,  -3845,  -3719,  -3591,  -3462,
    192    -3331,  -3200,  -3068,  -2935,  -2801,  -2667,  -2531,  -2395,
    193    -2258,  -2120,  -1981,  -1842,  -1703,  -1563,  -1422,  -1281,
    194    -1140,   -998,   -856,   -713,   -571,   -428,   -285,   -142
    195 };
    196 
    197 static const WebRtc_Word16 kNoiseEstQDomain = 15;
    198 static const WebRtc_Word16 kNoiseEstIncCount = 5;
    199 
    200 static void ComfortNoise(AecmCore_t* aecm,
    201                          const WebRtc_UWord16* dfa,
    202                          complex16_t* out,
    203                          const WebRtc_Word16* lambda);
    204 
    205 static WebRtc_Word16 CalcSuppressionGain(AecmCore_t * const aecm);
    206 
    207 // Moves the pointer to the next entry and inserts |far_spectrum| and
    208 // corresponding Q-domain in its buffer.
    209 //
    210 // Inputs:
    211 //      - self          : Pointer to the delay estimation instance
    212 //      - far_spectrum  : Pointer to the far end spectrum
    213 //      - far_q         : Q-domain of far end spectrum
    214 //
    215 static void UpdateFarHistory(AecmCore_t* self,
    216                              uint16_t* far_spectrum,
    217                              int far_q) {
    218   // Get new buffer position
    219   self->far_history_pos++;
    220   if (self->far_history_pos >= MAX_DELAY) {
    221     self->far_history_pos = 0;
    222   }
    223   // Update Q-domain buffer
    224   self->far_q_domains[self->far_history_pos] = far_q;
    225   // Update far end spectrum buffer
    226   memcpy(&(self->far_history[self->far_history_pos * PART_LEN1]),
    227          far_spectrum,
    228          sizeof(uint16_t) * PART_LEN1);
    229 }
    230 
    231 // Returns a pointer to the far end spectrum aligned to current near end
    232 // spectrum. The function WebRtc_DelayEstimatorProcessFix(...) should have been
    233 // called before AlignedFarend(...). Otherwise, you get the pointer to the
    234 // previous frame. The memory is only valid until the next call of
    235 // WebRtc_DelayEstimatorProcessFix(...).
    236 //
    237 // Inputs:
    238 //      - self              : Pointer to the AECM instance.
    239 //      - delay             : Current delay estimate.
    240 //
    241 // Output:
    242 //      - far_q             : The Q-domain of the aligned far end spectrum
    243 //
    244 // Return value:
    245 //      - far_spectrum      : Pointer to the aligned far end spectrum
    246 //                            NULL - Error
    247 //
    248 static const uint16_t* AlignedFarend(AecmCore_t* self, int* far_q, int delay) {
    249   int buffer_position = 0;
    250   assert(self != NULL);
    251   buffer_position = self->far_history_pos - delay;
    252 
    253   // Check buffer position
    254   if (buffer_position < 0) {
    255     buffer_position += MAX_DELAY;
    256   }
    257   // Get Q-domain
    258   *far_q = self->far_q_domains[buffer_position];
    259   // Return far end spectrum
    260   return &(self->far_history[buffer_position * PART_LEN1]);
    261 }
    262 
    263 #ifdef ARM_WINM_LOG
    264 HANDLE logFile = NULL;
    265 #endif
    266 
    267 // Declare function pointers.
    268 CalcLinearEnergies WebRtcAecm_CalcLinearEnergies;
    269 StoreAdaptiveChannel WebRtcAecm_StoreAdaptiveChannel;
    270 ResetAdaptiveChannel WebRtcAecm_ResetAdaptiveChannel;
    271 WindowAndFFT WebRtcAecm_WindowAndFFT;
    272 InverseFFTAndWindow WebRtcAecm_InverseFFTAndWindow;
    273 
    274 int WebRtcAecm_CreateCore(AecmCore_t **aecmInst)
    275 {
    276     AecmCore_t *aecm = malloc(sizeof(AecmCore_t));
    277     *aecmInst = aecm;
    278     if (aecm == NULL)
    279     {
    280         return -1;
    281     }
    282 
    283     if (WebRtc_CreateBuffer(&aecm->farFrameBuf, FRAME_LEN + PART_LEN,
    284                             sizeof(int16_t)) == -1)
    285     {
    286         WebRtcAecm_FreeCore(aecm);
    287         aecm = NULL;
    288         return -1;
    289     }
    290 
    291     if (WebRtc_CreateBuffer(&aecm->nearNoisyFrameBuf, FRAME_LEN + PART_LEN,
    292                             sizeof(int16_t)) == -1)
    293     {
    294         WebRtcAecm_FreeCore(aecm);
    295         aecm = NULL;
    296         return -1;
    297     }
    298 
    299     if (WebRtc_CreateBuffer(&aecm->nearCleanFrameBuf, FRAME_LEN + PART_LEN,
    300                             sizeof(int16_t)) == -1)
    301     {
    302         WebRtcAecm_FreeCore(aecm);
    303         aecm = NULL;
    304         return -1;
    305     }
    306 
    307     if (WebRtc_CreateBuffer(&aecm->outFrameBuf, FRAME_LEN + PART_LEN,
    308                             sizeof(int16_t)) == -1)
    309     {
    310         WebRtcAecm_FreeCore(aecm);
    311         aecm = NULL;
    312         return -1;
    313     }
    314 
    315     if (WebRtc_CreateDelayEstimator(&aecm->delay_estimator,
    316                                     PART_LEN1,
    317                                     MAX_DELAY,
    318                                     0) == -1) {
    319       WebRtcAecm_FreeCore(aecm);
    320       aecm = NULL;
    321       return -1;
    322     }
    323 
    324     // Init some aecm pointers. 16 and 32 byte alignment is only necessary
    325     // for Neon code currently.
    326     aecm->xBuf = (WebRtc_Word16*) (((uintptr_t)aecm->xBuf_buf + 31) & ~ 31);
    327     aecm->dBufClean = (WebRtc_Word16*) (((uintptr_t)aecm->dBufClean_buf + 31) & ~ 31);
    328     aecm->dBufNoisy = (WebRtc_Word16*) (((uintptr_t)aecm->dBufNoisy_buf + 31) & ~ 31);
    329     aecm->outBuf = (WebRtc_Word16*) (((uintptr_t)aecm->outBuf_buf + 15) & ~ 15);
    330     aecm->channelStored = (WebRtc_Word16*) (((uintptr_t)
    331                                              aecm->channelStored_buf + 15) & ~ 15);
    332     aecm->channelAdapt16 = (WebRtc_Word16*) (((uintptr_t)
    333                                               aecm->channelAdapt16_buf + 15) & ~ 15);
    334     aecm->channelAdapt32 = (WebRtc_Word32*) (((uintptr_t)
    335                                               aecm->channelAdapt32_buf + 31) & ~ 31);
    336 
    337     return 0;
    338 }
    339 
    340 void WebRtcAecm_InitEchoPathCore(AecmCore_t* aecm, const WebRtc_Word16* echo_path)
    341 {
    342     int i = 0;
    343 
    344     // Reset the stored channel
    345     memcpy(aecm->channelStored, echo_path, sizeof(WebRtc_Word16) * PART_LEN1);
    346     // Reset the adapted channels
    347     memcpy(aecm->channelAdapt16, echo_path, sizeof(WebRtc_Word16) * PART_LEN1);
    348     for (i = 0; i < PART_LEN1; i++)
    349     {
    350         aecm->channelAdapt32[i] = WEBRTC_SPL_LSHIFT_W32(
    351             (WebRtc_Word32)(aecm->channelAdapt16[i]), 16);
    352     }
    353 
    354     // Reset channel storing variables
    355     aecm->mseAdaptOld = 1000;
    356     aecm->mseStoredOld = 1000;
    357     aecm->mseThreshold = WEBRTC_SPL_WORD32_MAX;
    358     aecm->mseChannelCount = 0;
    359 }
    360 
    361 static void WindowAndFFTC(WebRtc_Word16* fft,
    362                           const WebRtc_Word16* time_signal,
    363                           complex16_t* freq_signal,
    364                           int time_signal_scaling)
    365 {
    366     int i, j;
    367 
    368     memset(fft, 0, sizeof(WebRtc_Word16) * PART_LEN4);
    369     // FFT of signal
    370     for (i = 0, j = 0; i < PART_LEN; i++, j += 2)
    371     {
    372         // Window time domain signal and insert into real part of
    373         // transformation array |fft|
    374         fft[j] = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(
    375             (time_signal[i] << time_signal_scaling),
    376             WebRtcAecm_kSqrtHanning[i],
    377             14);
    378         fft[PART_LEN2 + j] = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(
    379             (time_signal[i + PART_LEN] << time_signal_scaling),
    380             WebRtcAecm_kSqrtHanning[PART_LEN - i],
    381             14);
    382         // Inserting zeros in imaginary parts not necessary since we
    383         // initialized the array with all zeros
    384     }
    385 
    386     WebRtcSpl_ComplexBitReverse(fft, PART_LEN_SHIFT);
    387     WebRtcSpl_ComplexFFT(fft, PART_LEN_SHIFT, 1);
    388 
    389     // Take only the first PART_LEN2 samples
    390     for (i = 0, j = 0; j < PART_LEN2; i += 1, j += 2)
    391     {
    392         freq_signal[i].real = fft[j];
    393 
    394         // The imaginary part has to switch sign
    395         freq_signal[i].imag = - fft[j+1];
    396     }
    397 }
    398 
    399 static void InverseFFTAndWindowC(AecmCore_t* aecm,
    400                                  WebRtc_Word16* fft,
    401                                  complex16_t* efw,
    402                                  WebRtc_Word16* output,
    403                                  const WebRtc_Word16* nearendClean)
    404 {
    405     int i, j, outCFFT;
    406     WebRtc_Word32 tmp32no1;
    407 
    408     // Synthesis
    409     for (i = 1; i < PART_LEN; i++)
    410     {
    411         j = WEBRTC_SPL_LSHIFT_W32(i, 1);
    412         fft[j] = efw[i].real;
    413 
    414         // mirrored data, even
    415         fft[PART_LEN4 - j] = efw[i].real;
    416         fft[j + 1] = -efw[i].imag;
    417 
    418         //mirrored data, odd
    419         fft[PART_LEN4 - (j - 1)] = efw[i].imag;
    420     }
    421     fft[0] = efw[0].real;
    422     fft[1] = -efw[0].imag;
    423 
    424     fft[PART_LEN2] = efw[PART_LEN].real;
    425     fft[PART_LEN2 + 1] = -efw[PART_LEN].imag;
    426 
    427     // inverse FFT, result should be scaled with outCFFT
    428     WebRtcSpl_ComplexBitReverse(fft, PART_LEN_SHIFT);
    429     outCFFT = WebRtcSpl_ComplexIFFT(fft, PART_LEN_SHIFT, 1);
    430 
    431     //take only the real values and scale with outCFFT
    432     for (i = 0; i < PART_LEN2; i++)
    433     {
    434         j = WEBRTC_SPL_LSHIFT_W32(i, 1);
    435         fft[i] = fft[j];
    436     }
    437 
    438     for (i = 0; i < PART_LEN; i++)
    439     {
    440         fft[i] = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND(
    441                 fft[i],
    442                 WebRtcAecm_kSqrtHanning[i],
    443                 14);
    444         tmp32no1 = WEBRTC_SPL_SHIFT_W32((WebRtc_Word32)fft[i],
    445                 outCFFT - aecm->dfaCleanQDomain);
    446         fft[i] = (WebRtc_Word16)WEBRTC_SPL_SAT(WEBRTC_SPL_WORD16_MAX,
    447                 tmp32no1 + aecm->outBuf[i],
    448                 WEBRTC_SPL_WORD16_MIN);
    449         output[i] = fft[i];
    450 
    451         tmp32no1 = WEBRTC_SPL_MUL_16_16_RSFT(
    452                 fft[PART_LEN + i],
    453                 WebRtcAecm_kSqrtHanning[PART_LEN - i],
    454                 14);
    455         tmp32no1 = WEBRTC_SPL_SHIFT_W32(tmp32no1,
    456                 outCFFT - aecm->dfaCleanQDomain);
    457         aecm->outBuf[i] = (WebRtc_Word16)WEBRTC_SPL_SAT(
    458                 WEBRTC_SPL_WORD16_MAX,
    459                 tmp32no1,
    460                 WEBRTC_SPL_WORD16_MIN);
    461     }
    462 
    463 #ifdef ARM_WINM_LOG_
    464     // measure tick end
    465     QueryPerformanceCounter((LARGE_INTEGER*)&end);
    466     diff__ = ((end - start) * 1000) / (freq/1000);
    467     milliseconds = (unsigned int)(diff__ & 0xffffffff);
    468     WriteFile (logFile, &milliseconds, sizeof(unsigned int), &temp, NULL);
    469 #endif
    470 
    471     // Copy the current block to the old position (aecm->outBuf is shifted elsewhere)
    472     memcpy(aecm->xBuf, aecm->xBuf + PART_LEN, sizeof(WebRtc_Word16) * PART_LEN);
    473     memcpy(aecm->dBufNoisy, aecm->dBufNoisy + PART_LEN, sizeof(WebRtc_Word16) * PART_LEN);
    474     if (nearendClean != NULL)
    475     {
    476         memcpy(aecm->dBufClean, aecm->dBufClean + PART_LEN, sizeof(WebRtc_Word16) * PART_LEN);
    477     }
    478 }
    479 
    480 static void CalcLinearEnergiesC(AecmCore_t* aecm,
    481                                 const WebRtc_UWord16* far_spectrum,
    482                                 WebRtc_Word32* echo_est,
    483                                 WebRtc_UWord32* far_energy,
    484                                 WebRtc_UWord32* echo_energy_adapt,
    485                                 WebRtc_UWord32* echo_energy_stored)
    486 {
    487     int i;
    488 
    489     // Get energy for the delayed far end signal and estimated
    490     // echo using both stored and adapted channels.
    491     for (i = 0; i < PART_LEN1; i++)
    492     {
    493         echo_est[i] = WEBRTC_SPL_MUL_16_U16(aecm->channelStored[i],
    494                                            far_spectrum[i]);
    495         (*far_energy) += (WebRtc_UWord32)(far_spectrum[i]);
    496         (*echo_energy_adapt) += WEBRTC_SPL_UMUL_16_16(aecm->channelAdapt16[i],
    497                                           far_spectrum[i]);
    498         (*echo_energy_stored) += (WebRtc_UWord32)echo_est[i];
    499     }
    500 }
    501 
    502 static void StoreAdaptiveChannelC(AecmCore_t* aecm,
    503                                   const WebRtc_UWord16* far_spectrum,
    504                                   WebRtc_Word32* echo_est)
    505 {
    506     int i;
    507 
    508     // During startup we store the channel every block.
    509     memcpy(aecm->channelStored, aecm->channelAdapt16, sizeof(WebRtc_Word16) * PART_LEN1);
    510     // Recalculate echo estimate
    511     for (i = 0; i < PART_LEN; i += 4)
    512     {
    513         echo_est[i] = WEBRTC_SPL_MUL_16_U16(aecm->channelStored[i],
    514                                            far_spectrum[i]);
    515         echo_est[i + 1] = WEBRTC_SPL_MUL_16_U16(aecm->channelStored[i + 1],
    516                                            far_spectrum[i + 1]);
    517         echo_est[i + 2] = WEBRTC_SPL_MUL_16_U16(aecm->channelStored[i + 2],
    518                                            far_spectrum[i + 2]);
    519         echo_est[i + 3] = WEBRTC_SPL_MUL_16_U16(aecm->channelStored[i + 3],
    520                                            far_spectrum[i + 3]);
    521     }
    522     echo_est[i] = WEBRTC_SPL_MUL_16_U16(aecm->channelStored[i],
    523                                        far_spectrum[i]);
    524 }
    525 
    526 static void ResetAdaptiveChannelC(AecmCore_t* aecm)
    527 {
    528     int i;
    529 
    530     // The stored channel has a significantly lower MSE than the adaptive one for
    531     // two consecutive calculations. Reset the adaptive channel.
    532     memcpy(aecm->channelAdapt16, aecm->channelStored,
    533            sizeof(WebRtc_Word16) * PART_LEN1);
    534     // Restore the W32 channel
    535     for (i = 0; i < PART_LEN; i += 4)
    536     {
    537         aecm->channelAdapt32[i] = WEBRTC_SPL_LSHIFT_W32(
    538                 (WebRtc_Word32)aecm->channelStored[i], 16);
    539         aecm->channelAdapt32[i + 1] = WEBRTC_SPL_LSHIFT_W32(
    540                 (WebRtc_Word32)aecm->channelStored[i + 1], 16);
    541         aecm->channelAdapt32[i + 2] = WEBRTC_SPL_LSHIFT_W32(
    542                 (WebRtc_Word32)aecm->channelStored[i + 2], 16);
    543         aecm->channelAdapt32[i + 3] = WEBRTC_SPL_LSHIFT_W32(
    544                 (WebRtc_Word32)aecm->channelStored[i + 3], 16);
    545     }
    546     aecm->channelAdapt32[i] = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)aecm->channelStored[i], 16);
    547 }
    548 
    549 // WebRtcAecm_InitCore(...)
    550 //
    551 // This function initializes the AECM instant created with WebRtcAecm_CreateCore(...)
    552 // Input:
    553 //      - aecm            : Pointer to the Echo Suppression instance
    554 //      - samplingFreq   : Sampling Frequency
    555 //
    556 // Output:
    557 //      - aecm            : Initialized instance
    558 //
    559 // Return value         :  0 - Ok
    560 //                        -1 - Error
    561 //
    562 int WebRtcAecm_InitCore(AecmCore_t * const aecm, int samplingFreq)
    563 {
    564     int i = 0;
    565     WebRtc_Word32 tmp32 = PART_LEN1 * PART_LEN1;
    566     WebRtc_Word16 tmp16 = PART_LEN1;
    567 
    568     if (samplingFreq != 8000 && samplingFreq != 16000)
    569     {
    570         samplingFreq = 8000;
    571         return -1;
    572     }
    573     // sanity check of sampling frequency
    574     aecm->mult = (WebRtc_Word16)samplingFreq / 8000;
    575 
    576     aecm->farBufWritePos = 0;
    577     aecm->farBufReadPos = 0;
    578     aecm->knownDelay = 0;
    579     aecm->lastKnownDelay = 0;
    580 
    581     WebRtc_InitBuffer(aecm->farFrameBuf);
    582     WebRtc_InitBuffer(aecm->nearNoisyFrameBuf);
    583     WebRtc_InitBuffer(aecm->nearCleanFrameBuf);
    584     WebRtc_InitBuffer(aecm->outFrameBuf);
    585 
    586     memset(aecm->xBuf_buf, 0, sizeof(aecm->xBuf_buf));
    587     memset(aecm->dBufClean_buf, 0, sizeof(aecm->dBufClean_buf));
    588     memset(aecm->dBufNoisy_buf, 0, sizeof(aecm->dBufNoisy_buf));
    589     memset(aecm->outBuf_buf, 0, sizeof(aecm->outBuf_buf));
    590 
    591     aecm->seed = 666;
    592     aecm->totCount = 0;
    593 
    594     if (WebRtc_InitDelayEstimator(aecm->delay_estimator) != 0) {
    595       return -1;
    596     }
    597     // Set far end histories to zero
    598     memset(aecm->far_history, 0, sizeof(uint16_t) * PART_LEN1 * MAX_DELAY);
    599     memset(aecm->far_q_domains, 0, sizeof(int) * MAX_DELAY);
    600     aecm->far_history_pos = MAX_DELAY;
    601 
    602     aecm->nlpFlag = 1;
    603     aecm->fixedDelay = -1;
    604 
    605     aecm->dfaCleanQDomain = 0;
    606     aecm->dfaCleanQDomainOld = 0;
    607     aecm->dfaNoisyQDomain = 0;
    608     aecm->dfaNoisyQDomainOld = 0;
    609 
    610     memset(aecm->nearLogEnergy, 0, sizeof(aecm->nearLogEnergy));
    611     aecm->farLogEnergy = 0;
    612     memset(aecm->echoAdaptLogEnergy, 0, sizeof(aecm->echoAdaptLogEnergy));
    613     memset(aecm->echoStoredLogEnergy, 0, sizeof(aecm->echoStoredLogEnergy));
    614 
    615     // Initialize the echo channels with a stored shape.
    616     if (samplingFreq == 8000)
    617     {
    618         WebRtcAecm_InitEchoPathCore(aecm, kChannelStored8kHz);
    619     }
    620     else
    621     {
    622         WebRtcAecm_InitEchoPathCore(aecm, kChannelStored16kHz);
    623     }
    624 
    625     memset(aecm->echoFilt, 0, sizeof(aecm->echoFilt));
    626     memset(aecm->nearFilt, 0, sizeof(aecm->nearFilt));
    627     aecm->noiseEstCtr = 0;
    628 
    629     aecm->cngMode = AecmTrue;
    630 
    631     memset(aecm->noiseEstTooLowCtr, 0, sizeof(aecm->noiseEstTooLowCtr));
    632     memset(aecm->noiseEstTooHighCtr, 0, sizeof(aecm->noiseEstTooHighCtr));
    633     // Shape the initial noise level to an approximate pink noise.
    634     for (i = 0; i < (PART_LEN1 >> 1) - 1; i++)
    635     {
    636         aecm->noiseEst[i] = (tmp32 << 8);
    637         tmp16--;
    638         tmp32 -= (WebRtc_Word32)((tmp16 << 1) + 1);
    639     }
    640     for (; i < PART_LEN1; i++)
    641     {
    642         aecm->noiseEst[i] = (tmp32 << 8);
    643     }
    644 
    645     aecm->farEnergyMin = WEBRTC_SPL_WORD16_MAX;
    646     aecm->farEnergyMax = WEBRTC_SPL_WORD16_MIN;
    647     aecm->farEnergyMaxMin = 0;
    648     aecm->farEnergyVAD = FAR_ENERGY_MIN; // This prevents false speech detection at the
    649                                          // beginning.
    650     aecm->farEnergyMSE = 0;
    651     aecm->currentVADValue = 0;
    652     aecm->vadUpdateCount = 0;
    653     aecm->firstVAD = 1;
    654 
    655     aecm->startupState = 0;
    656     aecm->supGain = SUPGAIN_DEFAULT;
    657     aecm->supGainOld = SUPGAIN_DEFAULT;
    658 
    659     aecm->supGainErrParamA = SUPGAIN_ERROR_PARAM_A;
    660     aecm->supGainErrParamD = SUPGAIN_ERROR_PARAM_D;
    661     aecm->supGainErrParamDiffAB = SUPGAIN_ERROR_PARAM_A - SUPGAIN_ERROR_PARAM_B;
    662     aecm->supGainErrParamDiffBD = SUPGAIN_ERROR_PARAM_B - SUPGAIN_ERROR_PARAM_D;
    663 
    664     assert(PART_LEN % 16 == 0);
    665 
    666     // Initialize function pointers.
    667     WebRtcAecm_WindowAndFFT = WindowAndFFTC;
    668     WebRtcAecm_InverseFFTAndWindow = InverseFFTAndWindowC;
    669     WebRtcAecm_CalcLinearEnergies = CalcLinearEnergiesC;
    670     WebRtcAecm_StoreAdaptiveChannel = StoreAdaptiveChannelC;
    671     WebRtcAecm_ResetAdaptiveChannel = ResetAdaptiveChannelC;
    672 
    673 #ifdef WEBRTC_DETECT_ARM_NEON
    674     uint64_t features = WebRtc_GetCPUFeaturesARM();
    675     if ((features & kCPUFeatureNEON) != 0)
    676     {
    677         WebRtcAecm_InitNeon();
    678     }
    679 #elif defined(WEBRTC_ARCH_ARM_NEON)
    680     WebRtcAecm_InitNeon();
    681 #endif
    682 
    683     return 0;
    684 }
    685 
    686 // TODO(bjornv): This function is currently not used. Add support for these
    687 // parameters from a higher level
    688 int WebRtcAecm_Control(AecmCore_t *aecm, int delay, int nlpFlag)
    689 {
    690     aecm->nlpFlag = nlpFlag;
    691     aecm->fixedDelay = delay;
    692 
    693     return 0;
    694 }
    695 
    696 int WebRtcAecm_FreeCore(AecmCore_t *aecm)
    697 {
    698     if (aecm == NULL)
    699     {
    700         return -1;
    701     }
    702 
    703     WebRtc_FreeBuffer(aecm->farFrameBuf);
    704     WebRtc_FreeBuffer(aecm->nearNoisyFrameBuf);
    705     WebRtc_FreeBuffer(aecm->nearCleanFrameBuf);
    706     WebRtc_FreeBuffer(aecm->outFrameBuf);
    707 
    708     WebRtc_FreeDelayEstimator(aecm->delay_estimator);
    709     free(aecm);
    710 
    711     return 0;
    712 }
    713 
    714 int WebRtcAecm_ProcessFrame(AecmCore_t * aecm,
    715                             const WebRtc_Word16 * farend,
    716                             const WebRtc_Word16 * nearendNoisy,
    717                             const WebRtc_Word16 * nearendClean,
    718                             WebRtc_Word16 * out)
    719 {
    720     WebRtc_Word16 outBlock_buf[PART_LEN + 8]; // Align buffer to 8-byte boundary.
    721     WebRtc_Word16* outBlock = (WebRtc_Word16*) (((uintptr_t) outBlock_buf + 15) & ~ 15);
    722 
    723     WebRtc_Word16 farFrame[FRAME_LEN];
    724     const int16_t* out_ptr = NULL;
    725     int size = 0;
    726 
    727     // Buffer the current frame.
    728     // Fetch an older one corresponding to the delay.
    729     WebRtcAecm_BufferFarFrame(aecm, farend, FRAME_LEN);
    730     WebRtcAecm_FetchFarFrame(aecm, farFrame, FRAME_LEN, aecm->knownDelay);
    731 
    732     // Buffer the synchronized far and near frames,
    733     // to pass the smaller blocks individually.
    734     WebRtc_WriteBuffer(aecm->farFrameBuf, farFrame, FRAME_LEN);
    735     WebRtc_WriteBuffer(aecm->nearNoisyFrameBuf, nearendNoisy, FRAME_LEN);
    736     if (nearendClean != NULL)
    737     {
    738         WebRtc_WriteBuffer(aecm->nearCleanFrameBuf, nearendClean, FRAME_LEN);
    739     }
    740 
    741     // Process as many blocks as possible.
    742     while (WebRtc_available_read(aecm->farFrameBuf) >= PART_LEN)
    743     {
    744         int16_t far_block[PART_LEN];
    745         const int16_t* far_block_ptr = NULL;
    746         int16_t near_noisy_block[PART_LEN];
    747         const int16_t* near_noisy_block_ptr = NULL;
    748 
    749         WebRtc_ReadBuffer(aecm->farFrameBuf, (void**) &far_block_ptr, far_block,
    750                           PART_LEN);
    751         WebRtc_ReadBuffer(aecm->nearNoisyFrameBuf,
    752                           (void**) &near_noisy_block_ptr,
    753                           near_noisy_block,
    754                           PART_LEN);
    755         if (nearendClean != NULL)
    756         {
    757             int16_t near_clean_block[PART_LEN];
    758             const int16_t* near_clean_block_ptr = NULL;
    759 
    760             WebRtc_ReadBuffer(aecm->nearCleanFrameBuf,
    761                               (void**) &near_clean_block_ptr,
    762                               near_clean_block,
    763                               PART_LEN);
    764             if (WebRtcAecm_ProcessBlock(aecm,
    765                                         far_block_ptr,
    766                                         near_noisy_block_ptr,
    767                                         near_clean_block_ptr,
    768                                         outBlock) == -1)
    769             {
    770                 return -1;
    771             }
    772         } else
    773         {
    774             if (WebRtcAecm_ProcessBlock(aecm,
    775                                         far_block_ptr,
    776                                         near_noisy_block_ptr,
    777                                         NULL,
    778                                         outBlock) == -1)
    779             {
    780                 return -1;
    781             }
    782         }
    783 
    784         WebRtc_WriteBuffer(aecm->outFrameBuf, outBlock, PART_LEN);
    785     }
    786 
    787     // Stuff the out buffer if we have less than a frame to output.
    788     // This should only happen for the first frame.
    789     size = (int) WebRtc_available_read(aecm->outFrameBuf);
    790     if (size < FRAME_LEN)
    791     {
    792         WebRtc_MoveReadPtr(aecm->outFrameBuf, size - FRAME_LEN);
    793     }
    794 
    795     // Obtain an output frame.
    796     WebRtc_ReadBuffer(aecm->outFrameBuf, (void**) &out_ptr, out, FRAME_LEN);
    797     if (out_ptr != out) {
    798       // ReadBuffer() hasn't copied to |out| in this case.
    799       memcpy(out, out_ptr, FRAME_LEN * sizeof(int16_t));
    800     }
    801 
    802     return 0;
    803 }
    804 
    805 // WebRtcAecm_AsymFilt(...)
    806 //
    807 // Performs asymmetric filtering.
    808 //
    809 // Inputs:
    810 //      - filtOld       : Previous filtered value.
    811 //      - inVal         : New input value.
    812 //      - stepSizePos   : Step size when we have a positive contribution.
    813 //      - stepSizeNeg   : Step size when we have a negative contribution.
    814 //
    815 // Output:
    816 //
    817 // Return: - Filtered value.
    818 //
    819 WebRtc_Word16 WebRtcAecm_AsymFilt(const WebRtc_Word16 filtOld, const WebRtc_Word16 inVal,
    820                                   const WebRtc_Word16 stepSizePos,
    821                                   const WebRtc_Word16 stepSizeNeg)
    822 {
    823     WebRtc_Word16 retVal;
    824 
    825     if ((filtOld == WEBRTC_SPL_WORD16_MAX) | (filtOld == WEBRTC_SPL_WORD16_MIN))
    826     {
    827         return inVal;
    828     }
    829     retVal = filtOld;
    830     if (filtOld > inVal)
    831     {
    832         retVal -= WEBRTC_SPL_RSHIFT_W16(filtOld - inVal, stepSizeNeg);
    833     } else
    834     {
    835         retVal += WEBRTC_SPL_RSHIFT_W16(inVal - filtOld, stepSizePos);
    836     }
    837 
    838     return retVal;
    839 }
    840 
    841 // WebRtcAecm_CalcEnergies(...)
    842 //
    843 // This function calculates the log of energies for nearend, farend and estimated
    844 // echoes. There is also an update of energy decision levels, i.e. internal VAD.
    845 //
    846 //
    847 // @param  aecm         [i/o]   Handle of the AECM instance.
    848 // @param  far_spectrum [in]    Pointer to farend spectrum.
    849 // @param  far_q        [in]    Q-domain of farend spectrum.
    850 // @param  nearEner     [in]    Near end energy for current block in
    851 //                              Q(aecm->dfaQDomain).
    852 // @param  echoEst      [out]   Estimated echo in Q(xfa_q+RESOLUTION_CHANNEL16).
    853 //
    854 void WebRtcAecm_CalcEnergies(AecmCore_t * aecm,
    855                              const WebRtc_UWord16* far_spectrum,
    856                              const WebRtc_Word16 far_q,
    857                              const WebRtc_UWord32 nearEner,
    858                              WebRtc_Word32 * echoEst)
    859 {
    860     // Local variables
    861     WebRtc_UWord32 tmpAdapt = 0;
    862     WebRtc_UWord32 tmpStored = 0;
    863     WebRtc_UWord32 tmpFar = 0;
    864 
    865     int i;
    866 
    867     WebRtc_Word16 zeros, frac;
    868     WebRtc_Word16 tmp16;
    869     WebRtc_Word16 increase_max_shifts = 4;
    870     WebRtc_Word16 decrease_max_shifts = 11;
    871     WebRtc_Word16 increase_min_shifts = 11;
    872     WebRtc_Word16 decrease_min_shifts = 3;
    873     WebRtc_Word16 kLogLowValue = WEBRTC_SPL_LSHIFT_W16(PART_LEN_SHIFT, 7);
    874 
    875     // Get log of near end energy and store in buffer
    876 
    877     // Shift buffer
    878     memmove(aecm->nearLogEnergy + 1, aecm->nearLogEnergy,
    879             sizeof(WebRtc_Word16) * (MAX_BUF_LEN - 1));
    880 
    881     // Logarithm of integrated magnitude spectrum (nearEner)
    882     tmp16 = kLogLowValue;
    883     if (nearEner)
    884     {
    885         zeros = WebRtcSpl_NormU32(nearEner);
    886         frac = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_U32(
    887                               (WEBRTC_SPL_LSHIFT_U32(nearEner, zeros) & 0x7FFFFFFF),
    888                               23);
    889         // log2 in Q8
    890         tmp16 += WEBRTC_SPL_LSHIFT_W16((31 - zeros), 8) + frac;
    891         tmp16 -= WEBRTC_SPL_LSHIFT_W16(aecm->dfaNoisyQDomain, 8);
    892     }
    893     aecm->nearLogEnergy[0] = tmp16;
    894     // END: Get log of near end energy
    895 
    896     WebRtcAecm_CalcLinearEnergies(aecm, far_spectrum, echoEst, &tmpFar, &tmpAdapt, &tmpStored);
    897 
    898     // Shift buffers
    899     memmove(aecm->echoAdaptLogEnergy + 1, aecm->echoAdaptLogEnergy,
    900             sizeof(WebRtc_Word16) * (MAX_BUF_LEN - 1));
    901     memmove(aecm->echoStoredLogEnergy + 1, aecm->echoStoredLogEnergy,
    902             sizeof(WebRtc_Word16) * (MAX_BUF_LEN - 1));
    903 
    904     // Logarithm of delayed far end energy
    905     tmp16 = kLogLowValue;
    906     if (tmpFar)
    907     {
    908         zeros = WebRtcSpl_NormU32(tmpFar);
    909         frac = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_U32((WEBRTC_SPL_LSHIFT_U32(tmpFar, zeros)
    910                         & 0x7FFFFFFF), 23);
    911         // log2 in Q8
    912         tmp16 += WEBRTC_SPL_LSHIFT_W16((31 - zeros), 8) + frac;
    913         tmp16 -= WEBRTC_SPL_LSHIFT_W16(far_q, 8);
    914     }
    915     aecm->farLogEnergy = tmp16;
    916 
    917     // Logarithm of estimated echo energy through adapted channel
    918     tmp16 = kLogLowValue;
    919     if (tmpAdapt)
    920     {
    921         zeros = WebRtcSpl_NormU32(tmpAdapt);
    922         frac = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_U32((WEBRTC_SPL_LSHIFT_U32(tmpAdapt, zeros)
    923                         & 0x7FFFFFFF), 23);
    924         //log2 in Q8
    925         tmp16 += WEBRTC_SPL_LSHIFT_W16((31 - zeros), 8) + frac;
    926         tmp16 -= WEBRTC_SPL_LSHIFT_W16(RESOLUTION_CHANNEL16 + far_q, 8);
    927     }
    928     aecm->echoAdaptLogEnergy[0] = tmp16;
    929 
    930     // Logarithm of estimated echo energy through stored channel
    931     tmp16 = kLogLowValue;
    932     if (tmpStored)
    933     {
    934         zeros = WebRtcSpl_NormU32(tmpStored);
    935         frac = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_U32((WEBRTC_SPL_LSHIFT_U32(tmpStored, zeros)
    936                         & 0x7FFFFFFF), 23);
    937         //log2 in Q8
    938         tmp16 += WEBRTC_SPL_LSHIFT_W16((31 - zeros), 8) + frac;
    939         tmp16 -= WEBRTC_SPL_LSHIFT_W16(RESOLUTION_CHANNEL16 + far_q, 8);
    940     }
    941     aecm->echoStoredLogEnergy[0] = tmp16;
    942 
    943     // Update farend energy levels (min, max, vad, mse)
    944     if (aecm->farLogEnergy > FAR_ENERGY_MIN)
    945     {
    946         if (aecm->startupState == 0)
    947         {
    948             increase_max_shifts = 2;
    949             decrease_min_shifts = 2;
    950             increase_min_shifts = 8;
    951         }
    952 
    953         aecm->farEnergyMin = WebRtcAecm_AsymFilt(aecm->farEnergyMin, aecm->farLogEnergy,
    954                                                  increase_min_shifts, decrease_min_shifts);
    955         aecm->farEnergyMax = WebRtcAecm_AsymFilt(aecm->farEnergyMax, aecm->farLogEnergy,
    956                                                  increase_max_shifts, decrease_max_shifts);
    957         aecm->farEnergyMaxMin = (aecm->farEnergyMax - aecm->farEnergyMin);
    958 
    959         // Dynamic VAD region size
    960         tmp16 = 2560 - aecm->farEnergyMin;
    961         if (tmp16 > 0)
    962         {
    963             tmp16 = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(tmp16, FAR_ENERGY_VAD_REGION, 9);
    964         } else
    965         {
    966             tmp16 = 0;
    967         }
    968         tmp16 += FAR_ENERGY_VAD_REGION;
    969 
    970         if ((aecm->startupState == 0) | (aecm->vadUpdateCount > 1024))
    971         {
    972             // In startup phase or VAD update halted
    973             aecm->farEnergyVAD = aecm->farEnergyMin + tmp16;
    974         } else
    975         {
    976             if (aecm->farEnergyVAD > aecm->farLogEnergy)
    977             {
    978                 aecm->farEnergyVAD += WEBRTC_SPL_RSHIFT_W16(aecm->farLogEnergy +
    979                                                             tmp16 -
    980                                                             aecm->farEnergyVAD,
    981                                                             6);
    982                 aecm->vadUpdateCount = 0;
    983             } else
    984             {
    985                 aecm->vadUpdateCount++;
    986             }
    987         }
    988         // Put MSE threshold higher than VAD
    989         aecm->farEnergyMSE = aecm->farEnergyVAD + (1 << 8);
    990     }
    991 
    992     // Update VAD variables
    993     if (aecm->farLogEnergy > aecm->farEnergyVAD)
    994     {
    995         if ((aecm->startupState == 0) | (aecm->farEnergyMaxMin > FAR_ENERGY_DIFF))
    996         {
    997             // We are in startup or have significant dynamics in input speech level
    998             aecm->currentVADValue = 1;
    999         }
   1000     } else
   1001     {
   1002         aecm->currentVADValue = 0;
   1003     }
   1004     if ((aecm->currentVADValue) && (aecm->firstVAD))
   1005     {
   1006         aecm->firstVAD = 0;
   1007         if (aecm->echoAdaptLogEnergy[0] > aecm->nearLogEnergy[0])
   1008         {
   1009             // The estimated echo has higher energy than the near end signal.
   1010             // This means that the initialization was too aggressive. Scale
   1011             // down by a factor 8
   1012             for (i = 0; i < PART_LEN1; i++)
   1013             {
   1014                 aecm->channelAdapt16[i] >>= 3;
   1015             }
   1016             // Compensate the adapted echo energy level accordingly.
   1017             aecm->echoAdaptLogEnergy[0] -= (3 << 8);
   1018             aecm->firstVAD = 1;
   1019         }
   1020     }
   1021 }
   1022 
   1023 // WebRtcAecm_CalcStepSize(...)
   1024 //
   1025 // This function calculates the step size used in channel estimation
   1026 //
   1027 //
   1028 // @param  aecm  [in]    Handle of the AECM instance.
   1029 // @param  mu    [out]   (Return value) Stepsize in log2(), i.e. number of shifts.
   1030 //
   1031 //
   1032 WebRtc_Word16 WebRtcAecm_CalcStepSize(AecmCore_t * const aecm)
   1033 {
   1034 
   1035     WebRtc_Word32 tmp32;
   1036     WebRtc_Word16 tmp16;
   1037     WebRtc_Word16 mu = MU_MAX;
   1038 
   1039     // Here we calculate the step size mu used in the
   1040     // following NLMS based Channel estimation algorithm
   1041     if (!aecm->currentVADValue)
   1042     {
   1043         // Far end energy level too low, no channel update
   1044         mu = 0;
   1045     } else if (aecm->startupState > 0)
   1046     {
   1047         if (aecm->farEnergyMin >= aecm->farEnergyMax)
   1048         {
   1049             mu = MU_MIN;
   1050         } else
   1051         {
   1052             tmp16 = (aecm->farLogEnergy - aecm->farEnergyMin);
   1053             tmp32 = WEBRTC_SPL_MUL_16_16(tmp16, MU_DIFF);
   1054             tmp32 = WebRtcSpl_DivW32W16(tmp32, aecm->farEnergyMaxMin);
   1055             mu = MU_MIN - 1 - (WebRtc_Word16)(tmp32);
   1056             // The -1 is an alternative to rounding. This way we get a larger
   1057             // stepsize, so we in some sense compensate for truncation in NLMS
   1058         }
   1059         if (mu < MU_MAX)
   1060         {
   1061             mu = MU_MAX; // Equivalent with maximum step size of 2^-MU_MAX
   1062         }
   1063     }
   1064 
   1065     return mu;
   1066 }
   1067 
   1068 // WebRtcAecm_UpdateChannel(...)
   1069 //
   1070 // This function performs channel estimation. NLMS and decision on channel storage.
   1071 //
   1072 //
   1073 // @param  aecm         [i/o]   Handle of the AECM instance.
   1074 // @param  far_spectrum [in]    Absolute value of the farend signal in Q(far_q)
   1075 // @param  far_q        [in]    Q-domain of the farend signal
   1076 // @param  dfa          [in]    Absolute value of the nearend signal (Q[aecm->dfaQDomain])
   1077 // @param  mu           [in]    NLMS step size.
   1078 // @param  echoEst      [i/o]   Estimated echo in Q(far_q+RESOLUTION_CHANNEL16).
   1079 //
   1080 void WebRtcAecm_UpdateChannel(AecmCore_t * aecm,
   1081                               const WebRtc_UWord16* far_spectrum,
   1082                               const WebRtc_Word16 far_q,
   1083                               const WebRtc_UWord16 * const dfa,
   1084                               const WebRtc_Word16 mu,
   1085                               WebRtc_Word32 * echoEst)
   1086 {
   1087 
   1088     WebRtc_UWord32 tmpU32no1, tmpU32no2;
   1089     WebRtc_Word32 tmp32no1, tmp32no2;
   1090     WebRtc_Word32 mseStored;
   1091     WebRtc_Word32 mseAdapt;
   1092 
   1093     int i;
   1094 
   1095     WebRtc_Word16 zerosFar, zerosNum, zerosCh, zerosDfa;
   1096     WebRtc_Word16 shiftChFar, shiftNum, shift2ResChan;
   1097     WebRtc_Word16 tmp16no1;
   1098     WebRtc_Word16 xfaQ, dfaQ;
   1099 
   1100     // This is the channel estimation algorithm. It is base on NLMS but has a variable step
   1101     // length, which was calculated above.
   1102     if (mu)
   1103     {
   1104         for (i = 0; i < PART_LEN1; i++)
   1105         {
   1106             // Determine norm of channel and farend to make sure we don't get overflow in
   1107             // multiplication
   1108             zerosCh = WebRtcSpl_NormU32(aecm->channelAdapt32[i]);
   1109             zerosFar = WebRtcSpl_NormU32((WebRtc_UWord32)far_spectrum[i]);
   1110             if (zerosCh + zerosFar > 31)
   1111             {
   1112                 // Multiplication is safe
   1113                 tmpU32no1 = WEBRTC_SPL_UMUL_32_16(aecm->channelAdapt32[i],
   1114                         far_spectrum[i]);
   1115                 shiftChFar = 0;
   1116             } else
   1117             {
   1118                 // We need to shift down before multiplication
   1119                 shiftChFar = 32 - zerosCh - zerosFar;
   1120                 tmpU32no1 = WEBRTC_SPL_UMUL_32_16(
   1121                     WEBRTC_SPL_RSHIFT_W32(aecm->channelAdapt32[i], shiftChFar),
   1122                     far_spectrum[i]);
   1123             }
   1124             // Determine Q-domain of numerator
   1125             zerosNum = WebRtcSpl_NormU32(tmpU32no1);
   1126             if (dfa[i])
   1127             {
   1128                 zerosDfa = WebRtcSpl_NormU32((WebRtc_UWord32)dfa[i]);
   1129             } else
   1130             {
   1131                 zerosDfa = 32;
   1132             }
   1133             tmp16no1 = zerosDfa - 2 + aecm->dfaNoisyQDomain -
   1134                 RESOLUTION_CHANNEL32 - far_q + shiftChFar;
   1135             if (zerosNum > tmp16no1 + 1)
   1136             {
   1137                 xfaQ = tmp16no1;
   1138                 dfaQ = zerosDfa - 2;
   1139             } else
   1140             {
   1141                 xfaQ = zerosNum - 2;
   1142                 dfaQ = RESOLUTION_CHANNEL32 + far_q - aecm->dfaNoisyQDomain -
   1143                     shiftChFar + xfaQ;
   1144             }
   1145             // Add in the same Q-domain
   1146             tmpU32no1 = WEBRTC_SPL_SHIFT_W32(tmpU32no1, xfaQ);
   1147             tmpU32no2 = WEBRTC_SPL_SHIFT_W32((WebRtc_UWord32)dfa[i], dfaQ);
   1148             tmp32no1 = (WebRtc_Word32)tmpU32no2 - (WebRtc_Word32)tmpU32no1;
   1149             zerosNum = WebRtcSpl_NormW32(tmp32no1);
   1150             if ((tmp32no1) && (far_spectrum[i] > (CHANNEL_VAD << far_q)))
   1151             {
   1152                 //
   1153                 // Update is needed
   1154                 //
   1155                 // This is what we would like to compute
   1156                 //
   1157                 // tmp32no1 = dfa[i] - (aecm->channelAdapt[i] * far_spectrum[i])
   1158                 // tmp32norm = (i + 1)
   1159                 // aecm->channelAdapt[i] += (2^mu) * tmp32no1
   1160                 //                        / (tmp32norm * far_spectrum[i])
   1161                 //
   1162 
   1163                 // Make sure we don't get overflow in multiplication.
   1164                 if (zerosNum + zerosFar > 31)
   1165                 {
   1166                     if (tmp32no1 > 0)
   1167                     {
   1168                         tmp32no2 = (WebRtc_Word32)WEBRTC_SPL_UMUL_32_16(tmp32no1,
   1169                                                                         far_spectrum[i]);
   1170                     } else
   1171                     {
   1172                         tmp32no2 = -(WebRtc_Word32)WEBRTC_SPL_UMUL_32_16(-tmp32no1,
   1173                                                                          far_spectrum[i]);
   1174                     }
   1175                     shiftNum = 0;
   1176                 } else
   1177                 {
   1178                     shiftNum = 32 - (zerosNum + zerosFar);
   1179                     if (tmp32no1 > 0)
   1180                     {
   1181                         tmp32no2 = (WebRtc_Word32)WEBRTC_SPL_UMUL_32_16(
   1182                                 WEBRTC_SPL_RSHIFT_W32(tmp32no1, shiftNum),
   1183                                 far_spectrum[i]);
   1184                     } else
   1185                     {
   1186                         tmp32no2 = -(WebRtc_Word32)WEBRTC_SPL_UMUL_32_16(
   1187                                 WEBRTC_SPL_RSHIFT_W32(-tmp32no1, shiftNum),
   1188                                 far_spectrum[i]);
   1189                     }
   1190                 }
   1191                 // Normalize with respect to frequency bin
   1192                 tmp32no2 = WebRtcSpl_DivW32W16(tmp32no2, i + 1);
   1193                 // Make sure we are in the right Q-domain
   1194                 shift2ResChan = shiftNum + shiftChFar - xfaQ - mu - ((30 - zerosFar) << 1);
   1195                 if (WebRtcSpl_NormW32(tmp32no2) < shift2ResChan)
   1196                 {
   1197                     tmp32no2 = WEBRTC_SPL_WORD32_MAX;
   1198                 } else
   1199                 {
   1200                     tmp32no2 = WEBRTC_SPL_SHIFT_W32(tmp32no2, shift2ResChan);
   1201                 }
   1202                 aecm->channelAdapt32[i] = WEBRTC_SPL_ADD_SAT_W32(aecm->channelAdapt32[i],
   1203                         tmp32no2);
   1204                 if (aecm->channelAdapt32[i] < 0)
   1205                 {
   1206                     // We can never have negative channel gain
   1207                     aecm->channelAdapt32[i] = 0;
   1208                 }
   1209                 aecm->channelAdapt16[i]
   1210                         = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(aecm->channelAdapt32[i], 16);
   1211             }
   1212         }
   1213     }
   1214     // END: Adaptive channel update
   1215 
   1216     // Determine if we should store or restore the channel
   1217     if ((aecm->startupState == 0) & (aecm->currentVADValue))
   1218     {
   1219         // During startup we store the channel every block,
   1220         // and we recalculate echo estimate
   1221         WebRtcAecm_StoreAdaptiveChannel(aecm, far_spectrum, echoEst);
   1222     } else
   1223     {
   1224         if (aecm->farLogEnergy < aecm->farEnergyMSE)
   1225         {
   1226             aecm->mseChannelCount = 0;
   1227         } else
   1228         {
   1229             aecm->mseChannelCount++;
   1230         }
   1231         // Enough data for validation. Store channel if we can.
   1232         if (aecm->mseChannelCount >= (MIN_MSE_COUNT + 10))
   1233         {
   1234             // We have enough data.
   1235             // Calculate MSE of "Adapt" and "Stored" versions.
   1236             // It is actually not MSE, but average absolute error.
   1237             mseStored = 0;
   1238             mseAdapt = 0;
   1239             for (i = 0; i < MIN_MSE_COUNT; i++)
   1240             {
   1241                 tmp32no1 = ((WebRtc_Word32)aecm->echoStoredLogEnergy[i]
   1242                         - (WebRtc_Word32)aecm->nearLogEnergy[i]);
   1243                 tmp32no2 = WEBRTC_SPL_ABS_W32(tmp32no1);
   1244                 mseStored += tmp32no2;
   1245 
   1246                 tmp32no1 = ((WebRtc_Word32)aecm->echoAdaptLogEnergy[i]
   1247                         - (WebRtc_Word32)aecm->nearLogEnergy[i]);
   1248                 tmp32no2 = WEBRTC_SPL_ABS_W32(tmp32no1);
   1249                 mseAdapt += tmp32no2;
   1250             }
   1251             if (((mseStored << MSE_RESOLUTION) < (MIN_MSE_DIFF * mseAdapt))
   1252                     & ((aecm->mseStoredOld << MSE_RESOLUTION) < (MIN_MSE_DIFF
   1253                             * aecm->mseAdaptOld)))
   1254             {
   1255                 // The stored channel has a significantly lower MSE than the adaptive one for
   1256                 // two consecutive calculations. Reset the adaptive channel.
   1257                 WebRtcAecm_ResetAdaptiveChannel(aecm);
   1258             } else if (((MIN_MSE_DIFF * mseStored) > (mseAdapt << MSE_RESOLUTION)) & (mseAdapt
   1259                     < aecm->mseThreshold) & (aecm->mseAdaptOld < aecm->mseThreshold))
   1260             {
   1261                 // The adaptive channel has a significantly lower MSE than the stored one.
   1262                 // The MSE for the adaptive channel has also been low for two consecutive
   1263                 // calculations. Store the adaptive channel.
   1264                 WebRtcAecm_StoreAdaptiveChannel(aecm, far_spectrum, echoEst);
   1265 
   1266                 // Update threshold
   1267                 if (aecm->mseThreshold == WEBRTC_SPL_WORD32_MAX)
   1268                 {
   1269                     aecm->mseThreshold = (mseAdapt + aecm->mseAdaptOld);
   1270                 } else
   1271                 {
   1272                     aecm->mseThreshold += WEBRTC_SPL_MUL_16_16_RSFT(mseAdapt
   1273                             - WEBRTC_SPL_MUL_16_16_RSFT(aecm->mseThreshold, 5, 3), 205, 8);
   1274                 }
   1275 
   1276             }
   1277 
   1278             // Reset counter
   1279             aecm->mseChannelCount = 0;
   1280 
   1281             // Store the MSE values.
   1282             aecm->mseStoredOld = mseStored;
   1283             aecm->mseAdaptOld = mseAdapt;
   1284         }
   1285     }
   1286     // END: Determine if we should store or reset channel estimate.
   1287 }
   1288 
   1289 // CalcSuppressionGain(...)
   1290 //
   1291 // This function calculates the suppression gain that is used in the Wiener filter.
   1292 //
   1293 //
   1294 // @param  aecm     [i/n]   Handle of the AECM instance.
   1295 // @param  supGain  [out]   (Return value) Suppression gain with which to scale the noise
   1296 //                          level (Q14).
   1297 //
   1298 //
   1299 static WebRtc_Word16 CalcSuppressionGain(AecmCore_t * const aecm)
   1300 {
   1301     WebRtc_Word32 tmp32no1;
   1302 
   1303     WebRtc_Word16 supGain = SUPGAIN_DEFAULT;
   1304     WebRtc_Word16 tmp16no1;
   1305     WebRtc_Word16 dE = 0;
   1306 
   1307     // Determine suppression gain used in the Wiener filter. The gain is based on a mix of far
   1308     // end energy and echo estimation error.
   1309     // Adjust for the far end signal level. A low signal level indicates no far end signal,
   1310     // hence we set the suppression gain to 0
   1311     if (!aecm->currentVADValue)
   1312     {
   1313         supGain = 0;
   1314     } else
   1315     {
   1316         // Adjust for possible double talk. If we have large variations in estimation error we
   1317         // likely have double talk (or poor channel).
   1318         tmp16no1 = (aecm->nearLogEnergy[0] - aecm->echoStoredLogEnergy[0] - ENERGY_DEV_OFFSET);
   1319         dE = WEBRTC_SPL_ABS_W16(tmp16no1);
   1320 
   1321         if (dE < ENERGY_DEV_TOL)
   1322         {
   1323             // Likely no double talk. The better estimation, the more we can suppress signal.
   1324             // Update counters
   1325             if (dE < SUPGAIN_EPC_DT)
   1326             {
   1327                 tmp32no1 = WEBRTC_SPL_MUL_16_16(aecm->supGainErrParamDiffAB, dE);
   1328                 tmp32no1 += (SUPGAIN_EPC_DT >> 1);
   1329                 tmp16no1 = (WebRtc_Word16)WebRtcSpl_DivW32W16(tmp32no1, SUPGAIN_EPC_DT);
   1330                 supGain = aecm->supGainErrParamA - tmp16no1;
   1331             } else
   1332             {
   1333                 tmp32no1 = WEBRTC_SPL_MUL_16_16(aecm->supGainErrParamDiffBD,
   1334                                                 (ENERGY_DEV_TOL - dE));
   1335                 tmp32no1 += ((ENERGY_DEV_TOL - SUPGAIN_EPC_DT) >> 1);
   1336                 tmp16no1 = (WebRtc_Word16)WebRtcSpl_DivW32W16(tmp32no1, (ENERGY_DEV_TOL
   1337                         - SUPGAIN_EPC_DT));
   1338                 supGain = aecm->supGainErrParamD + tmp16no1;
   1339             }
   1340         } else
   1341         {
   1342             // Likely in double talk. Use default value
   1343             supGain = aecm->supGainErrParamD;
   1344         }
   1345     }
   1346 
   1347     if (supGain > aecm->supGainOld)
   1348     {
   1349         tmp16no1 = supGain;
   1350     } else
   1351     {
   1352         tmp16no1 = aecm->supGainOld;
   1353     }
   1354     aecm->supGainOld = supGain;
   1355     if (tmp16no1 < aecm->supGain)
   1356     {
   1357         aecm->supGain += (WebRtc_Word16)((tmp16no1 - aecm->supGain) >> 4);
   1358     } else
   1359     {
   1360         aecm->supGain += (WebRtc_Word16)((tmp16no1 - aecm->supGain) >> 4);
   1361     }
   1362 
   1363     // END: Update suppression gain
   1364 
   1365     return aecm->supGain;
   1366 }
   1367 
   1368 // Transforms a time domain signal into the frequency domain, outputting the
   1369 // complex valued signal, absolute value and sum of absolute values.
   1370 //
   1371 // time_signal          [in]    Pointer to time domain signal
   1372 // freq_signal_real     [out]   Pointer to real part of frequency domain array
   1373 // freq_signal_imag     [out]   Pointer to imaginary part of frequency domain
   1374 //                              array
   1375 // freq_signal_abs      [out]   Pointer to absolute value of frequency domain
   1376 //                              array
   1377 // freq_signal_sum_abs  [out]   Pointer to the sum of all absolute values in
   1378 //                              the frequency domain array
   1379 // return value                 The Q-domain of current frequency values
   1380 //
   1381 static int TimeToFrequencyDomain(const WebRtc_Word16* time_signal,
   1382                                  complex16_t* freq_signal,
   1383                                  WebRtc_UWord16* freq_signal_abs,
   1384                                  WebRtc_UWord32* freq_signal_sum_abs)
   1385 {
   1386     int i = 0;
   1387     int time_signal_scaling = 0;
   1388 
   1389     WebRtc_Word32 tmp32no1;
   1390     WebRtc_Word32 tmp32no2;
   1391 
   1392     // In fft_buf, +16 for 32-byte alignment.
   1393     WebRtc_Word16 fft_buf[PART_LEN4 + 16];
   1394     WebRtc_Word16 *fft = (WebRtc_Word16 *) (((uintptr_t) fft_buf + 31) & ~31);
   1395 
   1396     WebRtc_Word16 tmp16no1;
   1397     WebRtc_Word16 tmp16no2;
   1398 #ifdef AECM_WITH_ABS_APPROX
   1399     WebRtc_Word16 max_value = 0;
   1400     WebRtc_Word16 min_value = 0;
   1401     WebRtc_UWord16 alpha = 0;
   1402     WebRtc_UWord16 beta = 0;
   1403 #endif
   1404 
   1405 #ifdef AECM_DYNAMIC_Q
   1406     tmp16no1 = WebRtcSpl_MaxAbsValueW16(time_signal, PART_LEN2);
   1407     time_signal_scaling = WebRtcSpl_NormW16(tmp16no1);
   1408 #endif
   1409 
   1410     WebRtcAecm_WindowAndFFT(fft, time_signal, freq_signal, time_signal_scaling);
   1411 
   1412     // Extract imaginary and real part, calculate the magnitude for all frequency bins
   1413     freq_signal[0].imag = 0;
   1414     freq_signal[PART_LEN].imag = 0;
   1415     freq_signal[PART_LEN].real = fft[PART_LEN2];
   1416     freq_signal_abs[0] = (WebRtc_UWord16)WEBRTC_SPL_ABS_W16(
   1417         freq_signal[0].real);
   1418     freq_signal_abs[PART_LEN] = (WebRtc_UWord16)WEBRTC_SPL_ABS_W16(
   1419         freq_signal[PART_LEN].real);
   1420     (*freq_signal_sum_abs) = (WebRtc_UWord32)(freq_signal_abs[0]) +
   1421         (WebRtc_UWord32)(freq_signal_abs[PART_LEN]);
   1422 
   1423     for (i = 1; i < PART_LEN; i++)
   1424     {
   1425         if (freq_signal[i].real == 0)
   1426         {
   1427             freq_signal_abs[i] = (WebRtc_UWord16)WEBRTC_SPL_ABS_W16(
   1428                 freq_signal[i].imag);
   1429         }
   1430         else if (freq_signal[i].imag == 0)
   1431         {
   1432             freq_signal_abs[i] = (WebRtc_UWord16)WEBRTC_SPL_ABS_W16(
   1433                 freq_signal[i].real);
   1434         }
   1435         else
   1436         {
   1437             // Approximation for magnitude of complex fft output
   1438             // magn = sqrt(real^2 + imag^2)
   1439             // magn ~= alpha * max(|imag|,|real|) + beta * min(|imag|,|real|)
   1440             //
   1441             // The parameters alpha and beta are stored in Q15
   1442 
   1443 #ifdef AECM_WITH_ABS_APPROX
   1444             tmp16no1 = WEBRTC_SPL_ABS_W16(freq_signal[i].real);
   1445             tmp16no2 = WEBRTC_SPL_ABS_W16(freq_signal[i].imag);
   1446 
   1447             if(tmp16no1 > tmp16no2)
   1448             {
   1449                 max_value = tmp16no1;
   1450                 min_value = tmp16no2;
   1451             } else
   1452             {
   1453                 max_value = tmp16no2;
   1454                 min_value = tmp16no1;
   1455             }
   1456 
   1457             // Magnitude in Q(-6)
   1458             if ((max_value >> 2) > min_value)
   1459             {
   1460                 alpha = kAlpha1;
   1461                 beta = kBeta1;
   1462             } else if ((max_value >> 1) > min_value)
   1463             {
   1464                 alpha = kAlpha2;
   1465                 beta = kBeta2;
   1466             } else
   1467             {
   1468                 alpha = kAlpha3;
   1469                 beta = kBeta3;
   1470             }
   1471             tmp16no1 = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(max_value,
   1472                                                                 alpha,
   1473                                                                 15);
   1474             tmp16no2 = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(min_value,
   1475                                                                 beta,
   1476                                                                 15);
   1477             freq_signal_abs[i] = (WebRtc_UWord16)tmp16no1 +
   1478                 (WebRtc_UWord16)tmp16no2;
   1479 #else
   1480 #ifdef WEBRTC_ARCH_ARM_V7A
   1481            __asm__("smulbb %0, %1, %2" : "=r"(tmp32no1) : "r"(freq_signal[i].real),
   1482                                                 "r"(freq_signal[i].real));
   1483            __asm__("smlabb %0, %1, %2, %3" :: "r"(tmp32no2), "r"(freq_signal[i].imag),
   1484                                                 "r"(freq_signal[i].imag), "r"(tmp32no1));
   1485 #else
   1486             tmp16no1 = WEBRTC_SPL_ABS_W16(freq_signal[i].real);
   1487             tmp16no2 = WEBRTC_SPL_ABS_W16(freq_signal[i].imag);
   1488             tmp32no1 = WEBRTC_SPL_MUL_16_16(tmp16no1, tmp16no1);
   1489             tmp32no2 = WEBRTC_SPL_MUL_16_16(tmp16no2, tmp16no2);
   1490             tmp32no2 = WEBRTC_SPL_ADD_SAT_W32(tmp32no1, tmp32no2);
   1491 #endif // WEBRTC_ARCH_ARM_V7A
   1492             tmp32no1 = WebRtcSpl_SqrtFloor(tmp32no2);
   1493 
   1494             freq_signal_abs[i] = (WebRtc_UWord16)tmp32no1;
   1495 #endif // AECM_WITH_ABS_APPROX
   1496         }
   1497         (*freq_signal_sum_abs) += (WebRtc_UWord32)freq_signal_abs[i];
   1498     }
   1499 
   1500     return time_signal_scaling;
   1501 }
   1502 
   1503 int WebRtcAecm_ProcessBlock(AecmCore_t * aecm,
   1504                             const WebRtc_Word16 * farend,
   1505                             const WebRtc_Word16 * nearendNoisy,
   1506                             const WebRtc_Word16 * nearendClean,
   1507                             WebRtc_Word16 * output)
   1508 {
   1509     int i;
   1510 
   1511     WebRtc_UWord32 xfaSum;
   1512     WebRtc_UWord32 dfaNoisySum;
   1513     WebRtc_UWord32 dfaCleanSum;
   1514     WebRtc_UWord32 echoEst32Gained;
   1515     WebRtc_UWord32 tmpU32;
   1516 
   1517     WebRtc_Word32 tmp32no1;
   1518 
   1519     WebRtc_UWord16 xfa[PART_LEN1];
   1520     WebRtc_UWord16 dfaNoisy[PART_LEN1];
   1521     WebRtc_UWord16 dfaClean[PART_LEN1];
   1522     WebRtc_UWord16* ptrDfaClean = dfaClean;
   1523     const WebRtc_UWord16* far_spectrum_ptr = NULL;
   1524 
   1525     // 32 byte aligned buffers (with +8 or +16).
   1526     // TODO (kma): define fft with complex16_t.
   1527     WebRtc_Word16 fft_buf[PART_LEN4 + 2 + 16]; // +2 to make a loop safe.
   1528     WebRtc_Word32 echoEst32_buf[PART_LEN1 + 8];
   1529     WebRtc_Word32 dfw_buf[PART_LEN1 + 8];
   1530     WebRtc_Word32 efw_buf[PART_LEN1 + 8];
   1531 
   1532     WebRtc_Word16* fft = (WebRtc_Word16*) (((uintptr_t) fft_buf + 31) & ~ 31);
   1533     WebRtc_Word32* echoEst32 = (WebRtc_Word32*) (((uintptr_t) echoEst32_buf + 31) & ~ 31);
   1534     complex16_t* dfw = (complex16_t*) (((uintptr_t) dfw_buf + 31) & ~ 31);
   1535     complex16_t* efw = (complex16_t*) (((uintptr_t) efw_buf + 31) & ~ 31);
   1536 
   1537     WebRtc_Word16 hnl[PART_LEN1];
   1538     WebRtc_Word16 numPosCoef = 0;
   1539     WebRtc_Word16 nlpGain = ONE_Q14;
   1540     int delay;
   1541     WebRtc_Word16 tmp16no1;
   1542     WebRtc_Word16 tmp16no2;
   1543     WebRtc_Word16 mu;
   1544     WebRtc_Word16 supGain;
   1545     WebRtc_Word16 zeros32, zeros16;
   1546     WebRtc_Word16 zerosDBufNoisy, zerosDBufClean, zerosXBuf;
   1547     int far_q;
   1548     WebRtc_Word16 resolutionDiff, qDomainDiff;
   1549 
   1550     const int kMinPrefBand = 4;
   1551     const int kMaxPrefBand = 24;
   1552     WebRtc_Word32 avgHnl32 = 0;
   1553 
   1554 #ifdef ARM_WINM_LOG_
   1555     DWORD temp;
   1556     static int flag0 = 0;
   1557     __int64 freq, start, end, diff__;
   1558     unsigned int milliseconds;
   1559 #endif
   1560 
   1561     // Determine startup state. There are three states:
   1562     // (0) the first CONV_LEN blocks
   1563     // (1) another CONV_LEN blocks
   1564     // (2) the rest
   1565 
   1566     if (aecm->startupState < 2)
   1567     {
   1568         aecm->startupState = (aecm->totCount >= CONV_LEN) + (aecm->totCount >= CONV_LEN2);
   1569     }
   1570     // END: Determine startup state
   1571 
   1572     // Buffer near and far end signals
   1573     memcpy(aecm->xBuf + PART_LEN, farend, sizeof(WebRtc_Word16) * PART_LEN);
   1574     memcpy(aecm->dBufNoisy + PART_LEN, nearendNoisy, sizeof(WebRtc_Word16) * PART_LEN);
   1575     if (nearendClean != NULL)
   1576     {
   1577         memcpy(aecm->dBufClean + PART_LEN, nearendClean, sizeof(WebRtc_Word16) * PART_LEN);
   1578     }
   1579 
   1580 #ifdef ARM_WINM_LOG_
   1581     // measure tick start
   1582     QueryPerformanceFrequency((LARGE_INTEGER*)&freq);
   1583     QueryPerformanceCounter((LARGE_INTEGER*)&start);
   1584 #endif
   1585 
   1586     // Transform far end signal from time domain to frequency domain.
   1587     far_q = TimeToFrequencyDomain(aecm->xBuf,
   1588                                   dfw,
   1589                                   xfa,
   1590                                   &xfaSum);
   1591 
   1592     // Transform noisy near end signal from time domain to frequency domain.
   1593     zerosDBufNoisy = TimeToFrequencyDomain(aecm->dBufNoisy,
   1594                                            dfw,
   1595                                            dfaNoisy,
   1596                                            &dfaNoisySum);
   1597     aecm->dfaNoisyQDomainOld = aecm->dfaNoisyQDomain;
   1598     aecm->dfaNoisyQDomain = (WebRtc_Word16)zerosDBufNoisy;
   1599 
   1600 
   1601     if (nearendClean == NULL)
   1602     {
   1603         ptrDfaClean = dfaNoisy;
   1604         aecm->dfaCleanQDomainOld = aecm->dfaNoisyQDomainOld;
   1605         aecm->dfaCleanQDomain = aecm->dfaNoisyQDomain;
   1606         dfaCleanSum = dfaNoisySum;
   1607     } else
   1608     {
   1609         // Transform clean near end signal from time domain to frequency domain.
   1610         zerosDBufClean = TimeToFrequencyDomain(aecm->dBufClean,
   1611                                                dfw,
   1612                                                dfaClean,
   1613                                                &dfaCleanSum);
   1614         aecm->dfaCleanQDomainOld = aecm->dfaCleanQDomain;
   1615         aecm->dfaCleanQDomain = (WebRtc_Word16)zerosDBufClean;
   1616     }
   1617 
   1618 #ifdef ARM_WINM_LOG_
   1619     // measure tick end
   1620     QueryPerformanceCounter((LARGE_INTEGER*)&end);
   1621     diff__ = ((end - start) * 1000) / (freq/1000);
   1622     milliseconds = (unsigned int)(diff__ & 0xffffffff);
   1623     WriteFile (logFile, &milliseconds, sizeof(unsigned int), &temp, NULL);
   1624     // measure tick start
   1625     QueryPerformanceCounter((LARGE_INTEGER*)&start);
   1626 #endif
   1627 
   1628     // Get the delay
   1629     // Save far-end history and estimate delay
   1630     UpdateFarHistory(aecm, xfa, far_q);
   1631     delay = WebRtc_DelayEstimatorProcessFix(aecm->delay_estimator,
   1632                                             xfa,
   1633                                             dfaNoisy,
   1634                                             PART_LEN1,
   1635                                             far_q,
   1636                                             zerosDBufNoisy);
   1637     if (delay == -1)
   1638     {
   1639         return -1;
   1640     }
   1641     else if (delay == -2)
   1642     {
   1643         // If the delay is unknown, we assume zero.
   1644         // NOTE: this will have to be adjusted if we ever add lookahead.
   1645         delay = 0;
   1646     }
   1647 
   1648     if (aecm->fixedDelay >= 0)
   1649     {
   1650         // Use fixed delay
   1651         delay = aecm->fixedDelay;
   1652     }
   1653 
   1654 #ifdef ARM_WINM_LOG_
   1655     // measure tick end
   1656     QueryPerformanceCounter((LARGE_INTEGER*)&end);
   1657     diff__ = ((end - start) * 1000) / (freq/1000);
   1658     milliseconds = (unsigned int)(diff__ & 0xffffffff);
   1659     WriteFile (logFile, &milliseconds, sizeof(unsigned int), &temp, NULL);
   1660     // measure tick start
   1661     QueryPerformanceCounter((LARGE_INTEGER*)&start);
   1662 #endif
   1663     // Get aligned far end spectrum
   1664     far_spectrum_ptr = AlignedFarend(aecm, &far_q, delay);
   1665     zerosXBuf = (WebRtc_Word16) far_q;
   1666     if (far_spectrum_ptr == NULL)
   1667     {
   1668         return -1;
   1669     }
   1670 
   1671     // Calculate log(energy) and update energy threshold levels
   1672     WebRtcAecm_CalcEnergies(aecm,
   1673                             far_spectrum_ptr,
   1674                             zerosXBuf,
   1675                             dfaNoisySum,
   1676                             echoEst32);
   1677 
   1678     // Calculate stepsize
   1679     mu = WebRtcAecm_CalcStepSize(aecm);
   1680 
   1681     // Update counters
   1682     aecm->totCount++;
   1683 
   1684     // This is the channel estimation algorithm.
   1685     // It is base on NLMS but has a variable step length, which was calculated above.
   1686     WebRtcAecm_UpdateChannel(aecm, far_spectrum_ptr, zerosXBuf, dfaNoisy, mu, echoEst32);
   1687     supGain = CalcSuppressionGain(aecm);
   1688 
   1689 #ifdef ARM_WINM_LOG_
   1690     // measure tick end
   1691     QueryPerformanceCounter((LARGE_INTEGER*)&end);
   1692     diff__ = ((end - start) * 1000) / (freq/1000);
   1693     milliseconds = (unsigned int)(diff__ & 0xffffffff);
   1694     WriteFile (logFile, &milliseconds, sizeof(unsigned int), &temp, NULL);
   1695     // measure tick start
   1696     QueryPerformanceCounter((LARGE_INTEGER*)&start);
   1697 #endif
   1698 
   1699     // Calculate Wiener filter hnl[]
   1700     for (i = 0; i < PART_LEN1; i++)
   1701     {
   1702         // Far end signal through channel estimate in Q8
   1703         // How much can we shift right to preserve resolution
   1704         tmp32no1 = echoEst32[i] - aecm->echoFilt[i];
   1705         aecm->echoFilt[i] += WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_32_16(tmp32no1, 50), 8);
   1706 
   1707         zeros32 = WebRtcSpl_NormW32(aecm->echoFilt[i]) + 1;
   1708         zeros16 = WebRtcSpl_NormW16(supGain) + 1;
   1709         if (zeros32 + zeros16 > 16)
   1710         {
   1711             // Multiplication is safe
   1712             // Result in Q(RESOLUTION_CHANNEL+RESOLUTION_SUPGAIN+aecm->xfaQDomainBuf[diff])
   1713             echoEst32Gained = WEBRTC_SPL_UMUL_32_16((WebRtc_UWord32)aecm->echoFilt[i],
   1714                                                     (WebRtc_UWord16)supGain);
   1715             resolutionDiff = 14 - RESOLUTION_CHANNEL16 - RESOLUTION_SUPGAIN;
   1716             resolutionDiff += (aecm->dfaCleanQDomain - zerosXBuf);
   1717         } else
   1718         {
   1719             tmp16no1 = 17 - zeros32 - zeros16;
   1720             resolutionDiff = 14 + tmp16no1 - RESOLUTION_CHANNEL16 - RESOLUTION_SUPGAIN;
   1721             resolutionDiff += (aecm->dfaCleanQDomain - zerosXBuf);
   1722             if (zeros32 > tmp16no1)
   1723             {
   1724                 echoEst32Gained = WEBRTC_SPL_UMUL_32_16((WebRtc_UWord32)aecm->echoFilt[i],
   1725                         (WebRtc_UWord16)WEBRTC_SPL_RSHIFT_W16(supGain,
   1726                                 tmp16no1)); // Q-(RESOLUTION_CHANNEL+RESOLUTION_SUPGAIN-16)
   1727             } else
   1728             {
   1729                 // Result in Q-(RESOLUTION_CHANNEL+RESOLUTION_SUPGAIN-16)
   1730                 echoEst32Gained = WEBRTC_SPL_UMUL_32_16(
   1731                         (WebRtc_UWord32)WEBRTC_SPL_RSHIFT_W32(aecm->echoFilt[i], tmp16no1),
   1732                         (WebRtc_UWord16)supGain);
   1733             }
   1734         }
   1735 
   1736         zeros16 = WebRtcSpl_NormW16(aecm->nearFilt[i]);
   1737         if ((zeros16 < (aecm->dfaCleanQDomain - aecm->dfaCleanQDomainOld))
   1738                 & (aecm->nearFilt[i]))
   1739         {
   1740             tmp16no1 = WEBRTC_SPL_SHIFT_W16(aecm->nearFilt[i], zeros16);
   1741             qDomainDiff = zeros16 - aecm->dfaCleanQDomain + aecm->dfaCleanQDomainOld;
   1742         } else
   1743         {
   1744             tmp16no1 = WEBRTC_SPL_SHIFT_W16(aecm->nearFilt[i],
   1745                                             aecm->dfaCleanQDomain - aecm->dfaCleanQDomainOld);
   1746             qDomainDiff = 0;
   1747         }
   1748         tmp16no2 = WEBRTC_SPL_SHIFT_W16(ptrDfaClean[i], qDomainDiff);
   1749         tmp32no1 = (WebRtc_Word32)(tmp16no2 - tmp16no1);
   1750         tmp16no2 = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmp32no1, 4);
   1751         tmp16no2 += tmp16no1;
   1752         zeros16 = WebRtcSpl_NormW16(tmp16no2);
   1753         if ((tmp16no2) & (-qDomainDiff > zeros16))
   1754         {
   1755             aecm->nearFilt[i] = WEBRTC_SPL_WORD16_MAX;
   1756         } else
   1757         {
   1758             aecm->nearFilt[i] = WEBRTC_SPL_SHIFT_W16(tmp16no2, -qDomainDiff);
   1759         }
   1760 
   1761         // Wiener filter coefficients, resulting hnl in Q14
   1762         if (echoEst32Gained == 0)
   1763         {
   1764             hnl[i] = ONE_Q14;
   1765         } else if (aecm->nearFilt[i] == 0)
   1766         {
   1767             hnl[i] = 0;
   1768         } else
   1769         {
   1770             // Multiply the suppression gain
   1771             // Rounding
   1772             echoEst32Gained += (WebRtc_UWord32)(aecm->nearFilt[i] >> 1);
   1773             tmpU32 = WebRtcSpl_DivU32U16(echoEst32Gained, (WebRtc_UWord16)aecm->nearFilt[i]);
   1774 
   1775             // Current resolution is
   1776             // Q-(RESOLUTION_CHANNEL + RESOLUTION_SUPGAIN - max(0, 17 - zeros16 - zeros32))
   1777             // Make sure we are in Q14
   1778             tmp32no1 = (WebRtc_Word32)WEBRTC_SPL_SHIFT_W32(tmpU32, resolutionDiff);
   1779             if (tmp32no1 > ONE_Q14)
   1780             {
   1781                 hnl[i] = 0;
   1782             } else if (tmp32no1 < 0)
   1783             {
   1784                 hnl[i] = ONE_Q14;
   1785             } else
   1786             {
   1787                 // 1-echoEst/dfa
   1788                 hnl[i] = ONE_Q14 - (WebRtc_Word16)tmp32no1;
   1789                 if (hnl[i] < 0)
   1790                 {
   1791                     hnl[i] = 0;
   1792                 }
   1793             }
   1794         }
   1795         if (hnl[i])
   1796         {
   1797             numPosCoef++;
   1798         }
   1799     }
   1800     // Only in wideband. Prevent the gain in upper band from being larger than
   1801     // in lower band.
   1802     if (aecm->mult == 2)
   1803     {
   1804         // TODO(bjornv): Investigate if the scaling of hnl[i] below can cause
   1805         //               speech distortion in double-talk.
   1806         for (i = 0; i < PART_LEN1; i++)
   1807         {
   1808             hnl[i] = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(hnl[i], hnl[i], 14);
   1809         }
   1810 
   1811         for (i = kMinPrefBand; i <= kMaxPrefBand; i++)
   1812         {
   1813             avgHnl32 += (WebRtc_Word32)hnl[i];
   1814         }
   1815         assert(kMaxPrefBand - kMinPrefBand + 1 > 0);
   1816         avgHnl32 /= (kMaxPrefBand - kMinPrefBand + 1);
   1817 
   1818         for (i = kMaxPrefBand; i < PART_LEN1; i++)
   1819         {
   1820             if (hnl[i] > (WebRtc_Word16)avgHnl32)
   1821             {
   1822                 hnl[i] = (WebRtc_Word16)avgHnl32;
   1823             }
   1824         }
   1825     }
   1826 
   1827 #ifdef ARM_WINM_LOG_
   1828     // measure tick end
   1829     QueryPerformanceCounter((LARGE_INTEGER*)&end);
   1830     diff__ = ((end - start) * 1000) / (freq/1000);
   1831     milliseconds = (unsigned int)(diff__ & 0xffffffff);
   1832     WriteFile (logFile, &milliseconds, sizeof(unsigned int), &temp, NULL);
   1833     // measure tick start
   1834     QueryPerformanceCounter((LARGE_INTEGER*)&start);
   1835 #endif
   1836 
   1837     // Calculate NLP gain, result is in Q14
   1838     if (aecm->nlpFlag)
   1839     {
   1840         for (i = 0; i < PART_LEN1; i++)
   1841         {
   1842             // Truncate values close to zero and one.
   1843             if (hnl[i] > NLP_COMP_HIGH)
   1844             {
   1845                 hnl[i] = ONE_Q14;
   1846             } else if (hnl[i] < NLP_COMP_LOW)
   1847             {
   1848                 hnl[i] = 0;
   1849             }
   1850 
   1851             // Remove outliers
   1852             if (numPosCoef < 3)
   1853             {
   1854                 nlpGain = 0;
   1855             } else
   1856             {
   1857                 nlpGain = ONE_Q14;
   1858             }
   1859 
   1860             // NLP
   1861             if ((hnl[i] == ONE_Q14) && (nlpGain == ONE_Q14))
   1862             {
   1863                 hnl[i] = ONE_Q14;
   1864             } else
   1865             {
   1866                 hnl[i] = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(hnl[i], nlpGain, 14);
   1867             }
   1868 
   1869             // multiply with Wiener coefficients
   1870             efw[i].real = (WebRtc_Word16)(WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND(dfw[i].real,
   1871                                                                             hnl[i], 14));
   1872             efw[i].imag = (WebRtc_Word16)(WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND(dfw[i].imag,
   1873                                                                             hnl[i], 14));
   1874         }
   1875     }
   1876     else
   1877     {
   1878         // multiply with Wiener coefficients
   1879         for (i = 0; i < PART_LEN1; i++)
   1880         {
   1881             efw[i].real = (WebRtc_Word16)(WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND(dfw[i].real,
   1882                                                                            hnl[i], 14));
   1883             efw[i].imag = (WebRtc_Word16)(WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND(dfw[i].imag,
   1884                                                                            hnl[i], 14));
   1885         }
   1886     }
   1887 
   1888     if (aecm->cngMode == AecmTrue)
   1889     {
   1890         ComfortNoise(aecm, ptrDfaClean, efw, hnl);
   1891     }
   1892 
   1893 #ifdef ARM_WINM_LOG_
   1894     // measure tick end
   1895     QueryPerformanceCounter((LARGE_INTEGER*)&end);
   1896     diff__ = ((end - start) * 1000) / (freq/1000);
   1897     milliseconds = (unsigned int)(diff__ & 0xffffffff);
   1898     WriteFile (logFile, &milliseconds, sizeof(unsigned int), &temp, NULL);
   1899     // measure tick start
   1900     QueryPerformanceCounter((LARGE_INTEGER*)&start);
   1901 #endif
   1902 
   1903     WebRtcAecm_InverseFFTAndWindow(aecm, fft, efw, output, nearendClean);
   1904 
   1905     return 0;
   1906 }
   1907 
   1908 
   1909 // Generate comfort noise and add to output signal.
   1910 //
   1911 // \param[in]     aecm     Handle of the AECM instance.
   1912 // \param[in]     dfa     Absolute value of the nearend signal (Q[aecm->dfaQDomain]).
   1913 // \param[in,out] outReal Real part of the output signal (Q[aecm->dfaQDomain]).
   1914 // \param[in,out] outImag Imaginary part of the output signal (Q[aecm->dfaQDomain]).
   1915 // \param[in]     lambda  Suppression gain with which to scale the noise level (Q14).
   1916 //
   1917 static void ComfortNoise(AecmCore_t* aecm,
   1918                          const WebRtc_UWord16* dfa,
   1919                          complex16_t* out,
   1920                          const WebRtc_Word16* lambda)
   1921 {
   1922     WebRtc_Word16 i;
   1923     WebRtc_Word16 tmp16;
   1924     WebRtc_Word32 tmp32;
   1925 
   1926     WebRtc_Word16 randW16[PART_LEN];
   1927     WebRtc_Word16 uReal[PART_LEN1];
   1928     WebRtc_Word16 uImag[PART_LEN1];
   1929     WebRtc_Word32 outLShift32;
   1930     WebRtc_Word16 noiseRShift16[PART_LEN1];
   1931 
   1932     WebRtc_Word16 shiftFromNearToNoise = kNoiseEstQDomain - aecm->dfaCleanQDomain;
   1933     WebRtc_Word16 minTrackShift;
   1934 
   1935     assert(shiftFromNearToNoise >= 0);
   1936     assert(shiftFromNearToNoise < 16);
   1937 
   1938     if (aecm->noiseEstCtr < 100)
   1939     {
   1940         // Track the minimum more quickly initially.
   1941         aecm->noiseEstCtr++;
   1942         minTrackShift = 6;
   1943     } else
   1944     {
   1945         minTrackShift = 9;
   1946     }
   1947 
   1948     // Estimate noise power.
   1949     for (i = 0; i < PART_LEN1; i++)
   1950     {
   1951 
   1952         // Shift to the noise domain.
   1953         tmp32 = (WebRtc_Word32)dfa[i];
   1954         outLShift32 = WEBRTC_SPL_LSHIFT_W32(tmp32, shiftFromNearToNoise);
   1955 
   1956         if (outLShift32 < aecm->noiseEst[i])
   1957         {
   1958             // Reset "too low" counter
   1959             aecm->noiseEstTooLowCtr[i] = 0;
   1960             // Track the minimum.
   1961             if (aecm->noiseEst[i] < (1 << minTrackShift))
   1962             {
   1963                 // For small values, decrease noiseEst[i] every
   1964                 // |kNoiseEstIncCount| block. The regular approach below can not
   1965                 // go further down due to truncation.
   1966                 aecm->noiseEstTooHighCtr[i]++;
   1967                 if (aecm->noiseEstTooHighCtr[i] >= kNoiseEstIncCount)
   1968                 {
   1969                     aecm->noiseEst[i]--;
   1970                     aecm->noiseEstTooHighCtr[i] = 0; // Reset the counter
   1971                 }
   1972             }
   1973             else
   1974             {
   1975                 aecm->noiseEst[i] -= ((aecm->noiseEst[i] - outLShift32) >> minTrackShift);
   1976             }
   1977         } else
   1978         {
   1979             // Reset "too high" counter
   1980             aecm->noiseEstTooHighCtr[i] = 0;
   1981             // Ramp slowly upwards until we hit the minimum again.
   1982             if ((aecm->noiseEst[i] >> 19) > 0)
   1983             {
   1984                 // Avoid overflow.
   1985                 // Multiplication with 2049 will cause wrap around. Scale
   1986                 // down first and then multiply
   1987                 aecm->noiseEst[i] >>= 11;
   1988                 aecm->noiseEst[i] *= 2049;
   1989             }
   1990             else if ((aecm->noiseEst[i] >> 11) > 0)
   1991             {
   1992                 // Large enough for relative increase
   1993                 aecm->noiseEst[i] *= 2049;
   1994                 aecm->noiseEst[i] >>= 11;
   1995             }
   1996             else
   1997             {
   1998                 // Make incremental increases based on size every
   1999                 // |kNoiseEstIncCount| block
   2000                 aecm->noiseEstTooLowCtr[i]++;
   2001                 if (aecm->noiseEstTooLowCtr[i] >= kNoiseEstIncCount)
   2002                 {
   2003                     aecm->noiseEst[i] += (aecm->noiseEst[i] >> 9) + 1;
   2004                     aecm->noiseEstTooLowCtr[i] = 0; // Reset counter
   2005                 }
   2006             }
   2007         }
   2008     }
   2009 
   2010     for (i = 0; i < PART_LEN1; i++)
   2011     {
   2012         tmp32 = WEBRTC_SPL_RSHIFT_W32(aecm->noiseEst[i], shiftFromNearToNoise);
   2013         if (tmp32 > 32767)
   2014         {
   2015             tmp32 = 32767;
   2016             aecm->noiseEst[i] = WEBRTC_SPL_LSHIFT_W32(tmp32, shiftFromNearToNoise);
   2017         }
   2018         noiseRShift16[i] = (WebRtc_Word16)tmp32;
   2019 
   2020         tmp16 = ONE_Q14 - lambda[i];
   2021         noiseRShift16[i]
   2022                 = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(tmp16, noiseRShift16[i], 14);
   2023     }
   2024 
   2025     // Generate a uniform random array on [0 2^15-1].
   2026     WebRtcSpl_RandUArray(randW16, PART_LEN, &aecm->seed);
   2027 
   2028     // Generate noise according to estimated energy.
   2029     uReal[0] = 0; // Reject LF noise.
   2030     uImag[0] = 0;
   2031     for (i = 1; i < PART_LEN1; i++)
   2032     {
   2033         // Get a random index for the cos and sin tables over [0 359].
   2034         tmp16 = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(359, randW16[i - 1], 15);
   2035 
   2036         // Tables are in Q13.
   2037         uReal[i] = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(noiseRShift16[i],
   2038                 kCosTable[tmp16], 13);
   2039         uImag[i] = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(-noiseRShift16[i],
   2040                 kSinTable[tmp16], 13);
   2041     }
   2042     uImag[PART_LEN] = 0;
   2043 
   2044 #if (!defined ARM_WINM) && (!defined ARM9E_GCC) && (!defined ANDROID_AECOPT)
   2045     for (i = 0; i < PART_LEN1; i++)
   2046     {
   2047         out[i].real = WEBRTC_SPL_ADD_SAT_W16(out[i].real, uReal[i]);
   2048         out[i].imag = WEBRTC_SPL_ADD_SAT_W16(out[i].imag, uImag[i]);
   2049     }
   2050 #else
   2051     for (i = 0; i < PART_LEN1 -1; )
   2052     {
   2053         out[i].real = WEBRTC_SPL_ADD_SAT_W16(out[i].real, uReal[i]);
   2054         out[i].imag = WEBRTC_SPL_ADD_SAT_W16(out[i].imag, uImag[i]);
   2055         i++;
   2056 
   2057         out[i].real = WEBRTC_SPL_ADD_SAT_W16(out[i].real, uReal[i]);
   2058         out[i].imag = WEBRTC_SPL_ADD_SAT_W16(out[i].imag, uImag[i]);
   2059         i++;
   2060     }
   2061     out[i].real = WEBRTC_SPL_ADD_SAT_W16(out[i].real, uReal[i]);
   2062     out[i].imag = WEBRTC_SPL_ADD_SAT_W16(out[i].imag, uImag[i]);
   2063 #endif
   2064 }
   2065 
   2066 void WebRtcAecm_BufferFarFrame(AecmCore_t* const aecm,
   2067                                const WebRtc_Word16* const farend,
   2068                                const int farLen)
   2069 {
   2070     int writeLen = farLen, writePos = 0;
   2071 
   2072     // Check if the write position must be wrapped
   2073     while (aecm->farBufWritePos + writeLen > FAR_BUF_LEN)
   2074     {
   2075         // Write to remaining buffer space before wrapping
   2076         writeLen = FAR_BUF_LEN - aecm->farBufWritePos;
   2077         memcpy(aecm->farBuf + aecm->farBufWritePos, farend + writePos,
   2078                sizeof(WebRtc_Word16) * writeLen);
   2079         aecm->farBufWritePos = 0;
   2080         writePos = writeLen;
   2081         writeLen = farLen - writeLen;
   2082     }
   2083 
   2084     memcpy(aecm->farBuf + aecm->farBufWritePos, farend + writePos,
   2085            sizeof(WebRtc_Word16) * writeLen);
   2086     aecm->farBufWritePos += writeLen;
   2087 }
   2088 
   2089 void WebRtcAecm_FetchFarFrame(AecmCore_t * const aecm, WebRtc_Word16 * const farend,
   2090                               const int farLen, const int knownDelay)
   2091 {
   2092     int readLen = farLen;
   2093     int readPos = 0;
   2094     int delayChange = knownDelay - aecm->lastKnownDelay;
   2095 
   2096     aecm->farBufReadPos -= delayChange;
   2097 
   2098     // Check if delay forces a read position wrap
   2099     while (aecm->farBufReadPos < 0)
   2100     {
   2101         aecm->farBufReadPos += FAR_BUF_LEN;
   2102     }
   2103     while (aecm->farBufReadPos > FAR_BUF_LEN - 1)
   2104     {
   2105         aecm->farBufReadPos -= FAR_BUF_LEN;
   2106     }
   2107 
   2108     aecm->lastKnownDelay = knownDelay;
   2109 
   2110     // Check if read position must be wrapped
   2111     while (aecm->farBufReadPos + readLen > FAR_BUF_LEN)
   2112     {
   2113 
   2114         // Read from remaining buffer space before wrapping
   2115         readLen = FAR_BUF_LEN - aecm->farBufReadPos;
   2116         memcpy(farend + readPos, aecm->farBuf + aecm->farBufReadPos,
   2117                sizeof(WebRtc_Word16) * readLen);
   2118         aecm->farBufReadPos = 0;
   2119         readPos = readLen;
   2120         readLen = farLen - readLen;
   2121     }
   2122     memcpy(farend + readPos, aecm->farBuf + aecm->farBufReadPos,
   2123            sizeof(WebRtc_Word16) * readLen);
   2124     aecm->farBufReadPos += readLen;
   2125 }
   2126 
   2127