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