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