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 // Performs echo control (suppression) with fft routines in fixed-point.
     12 
     13 #ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AECM_AECM_CORE_H_
     14 #define WEBRTC_MODULES_AUDIO_PROCESSING_AECM_AECM_CORE_H_
     15 
     16 #include "webrtc/common_audio/ring_buffer.h"
     17 #include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
     18 #include "webrtc/modules/audio_processing/aecm/aecm_defines.h"
     19 #include "webrtc/typedefs.h"
     20 
     21 #ifdef _MSC_VER  // visual c++
     22 #define ALIGN8_BEG __declspec(align(8))
     23 #define ALIGN8_END
     24 #else  // gcc or icc
     25 #define ALIGN8_BEG
     26 #define ALIGN8_END __attribute__((aligned(8)))
     27 #endif
     28 
     29 typedef struct {
     30     int16_t real;
     31     int16_t imag;
     32 } ComplexInt16;
     33 
     34 typedef struct {
     35     int farBufWritePos;
     36     int farBufReadPos;
     37     int knownDelay;
     38     int lastKnownDelay;
     39     int firstVAD;  // Parameter to control poorly initialized channels
     40 
     41     RingBuffer* farFrameBuf;
     42     RingBuffer* nearNoisyFrameBuf;
     43     RingBuffer* nearCleanFrameBuf;
     44     RingBuffer* outFrameBuf;
     45 
     46     int16_t farBuf[FAR_BUF_LEN];
     47 
     48     int16_t mult;
     49     uint32_t seed;
     50 
     51     // Delay estimation variables
     52     void* delay_estimator_farend;
     53     void* delay_estimator;
     54     uint16_t currentDelay;
     55     // Far end history variables
     56     // TODO(bjornv): Replace |far_history| with ring_buffer.
     57     uint16_t far_history[PART_LEN1 * MAX_DELAY];
     58     int far_history_pos;
     59     int far_q_domains[MAX_DELAY];
     60 
     61     int16_t nlpFlag;
     62     int16_t fixedDelay;
     63 
     64     uint32_t totCount;
     65 
     66     int16_t dfaCleanQDomain;
     67     int16_t dfaCleanQDomainOld;
     68     int16_t dfaNoisyQDomain;
     69     int16_t dfaNoisyQDomainOld;
     70 
     71     int16_t nearLogEnergy[MAX_BUF_LEN];
     72     int16_t farLogEnergy;
     73     int16_t echoAdaptLogEnergy[MAX_BUF_LEN];
     74     int16_t echoStoredLogEnergy[MAX_BUF_LEN];
     75 
     76     // The extra 16 or 32 bytes in the following buffers are for alignment based
     77     // Neon code.
     78     // It's designed this way since the current GCC compiler can't align a
     79     // buffer in 16 or 32 byte boundaries properly.
     80     int16_t channelStored_buf[PART_LEN1 + 8];
     81     int16_t channelAdapt16_buf[PART_LEN1 + 8];
     82     int32_t channelAdapt32_buf[PART_LEN1 + 8];
     83     int16_t xBuf_buf[PART_LEN2 + 16];  // farend
     84     int16_t dBufClean_buf[PART_LEN2 + 16];  // nearend
     85     int16_t dBufNoisy_buf[PART_LEN2 + 16];  // nearend
     86     int16_t outBuf_buf[PART_LEN + 8];
     87 
     88     // Pointers to the above buffers
     89     int16_t *channelStored;
     90     int16_t *channelAdapt16;
     91     int32_t *channelAdapt32;
     92     int16_t *xBuf;
     93     int16_t *dBufClean;
     94     int16_t *dBufNoisy;
     95     int16_t *outBuf;
     96 
     97     int32_t echoFilt[PART_LEN1];
     98     int16_t nearFilt[PART_LEN1];
     99     int32_t noiseEst[PART_LEN1];
    100     int           noiseEstTooLowCtr[PART_LEN1];
    101     int           noiseEstTooHighCtr[PART_LEN1];
    102     int16_t noiseEstCtr;
    103     int16_t cngMode;
    104 
    105     int32_t mseAdaptOld;
    106     int32_t mseStoredOld;
    107     int32_t mseThreshold;
    108 
    109     int16_t farEnergyMin;
    110     int16_t farEnergyMax;
    111     int16_t farEnergyMaxMin;
    112     int16_t farEnergyVAD;
    113     int16_t farEnergyMSE;
    114     int currentVADValue;
    115     int16_t vadUpdateCount;
    116 
    117     int16_t startupState;
    118     int16_t mseChannelCount;
    119     int16_t supGain;
    120     int16_t supGainOld;
    121 
    122     int16_t supGainErrParamA;
    123     int16_t supGainErrParamD;
    124     int16_t supGainErrParamDiffAB;
    125     int16_t supGainErrParamDiffBD;
    126 
    127     struct RealFFT* real_fft;
    128 
    129 #ifdef AEC_DEBUG
    130     FILE *farFile;
    131     FILE *nearFile;
    132     FILE *outFile;
    133 #endif
    134 } AecmCore;
    135 
    136 ////////////////////////////////////////////////////////////////////////////////
    137 // WebRtcAecm_CreateCore()
    138 //
    139 // Allocates the memory needed by the AECM. The memory needs to be
    140 // initialized separately using the WebRtcAecm_InitCore() function.
    141 // Returns a pointer to the instance and a nullptr at failure.
    142 AecmCore* WebRtcAecm_CreateCore();
    143 
    144 ////////////////////////////////////////////////////////////////////////////////
    145 // WebRtcAecm_InitCore(...)
    146 //
    147 // This function initializes the AECM instant created with
    148 // WebRtcAecm_CreateCore()
    149 // Input:
    150 //      - aecm          : Pointer to the AECM instance
    151 //      - samplingFreq  : Sampling Frequency
    152 //
    153 // Output:
    154 //      - aecm          : Initialized instance
    155 //
    156 // Return value         :  0 - Ok
    157 //                        -1 - Error
    158 //
    159 int WebRtcAecm_InitCore(AecmCore* const aecm, int samplingFreq);
    160 
    161 ////////////////////////////////////////////////////////////////////////////////
    162 // WebRtcAecm_FreeCore(...)
    163 //
    164 // This function releases the memory allocated by WebRtcAecm_CreateCore()
    165 // Input:
    166 //      - aecm          : Pointer to the AECM instance
    167 //
    168 void WebRtcAecm_FreeCore(AecmCore* aecm);
    169 
    170 int WebRtcAecm_Control(AecmCore* aecm, int delay, int nlpFlag);
    171 
    172 ////////////////////////////////////////////////////////////////////////////////
    173 // WebRtcAecm_InitEchoPathCore(...)
    174 //
    175 // This function resets the echo channel adaptation with the specified channel.
    176 // Input:
    177 //      - aecm          : Pointer to the AECM instance
    178 //      - echo_path     : Pointer to the data that should initialize the echo
    179 //                        path
    180 //
    181 // Output:
    182 //      - aecm          : Initialized instance
    183 //
    184 void WebRtcAecm_InitEchoPathCore(AecmCore* aecm, const int16_t* echo_path);
    185 
    186 ////////////////////////////////////////////////////////////////////////////////
    187 // WebRtcAecm_ProcessFrame(...)
    188 //
    189 // This function processes frames and sends blocks to
    190 // WebRtcAecm_ProcessBlock(...)
    191 //
    192 // Inputs:
    193 //      - aecm          : Pointer to the AECM instance
    194 //      - farend        : In buffer containing one frame of echo signal
    195 //      - nearendNoisy  : In buffer containing one frame of nearend+echo signal
    196 //                        without NS
    197 //      - nearendClean  : In buffer containing one frame of nearend+echo signal
    198 //                        with NS
    199 //
    200 // Output:
    201 //      - out           : Out buffer, one frame of nearend signal          :
    202 //
    203 //
    204 int WebRtcAecm_ProcessFrame(AecmCore* aecm,
    205                             const int16_t* farend,
    206                             const int16_t* nearendNoisy,
    207                             const int16_t* nearendClean,
    208                             int16_t* out);
    209 
    210 ////////////////////////////////////////////////////////////////////////////////
    211 // WebRtcAecm_ProcessBlock(...)
    212 //
    213 // This function is called for every block within one frame
    214 // This function is called by WebRtcAecm_ProcessFrame(...)
    215 //
    216 // Inputs:
    217 //      - aecm          : Pointer to the AECM instance
    218 //      - farend        : In buffer containing one block of echo signal
    219 //      - nearendNoisy  : In buffer containing one frame of nearend+echo signal
    220 //                        without NS
    221 //      - nearendClean  : In buffer containing one frame of nearend+echo signal
    222 //                        with NS
    223 //
    224 // Output:
    225 //      - out           : Out buffer, one block of nearend signal          :
    226 //
    227 //
    228 int WebRtcAecm_ProcessBlock(AecmCore* aecm,
    229                             const int16_t* farend,
    230                             const int16_t* nearendNoisy,
    231                             const int16_t* noisyClean,
    232                             int16_t* out);
    233 
    234 ////////////////////////////////////////////////////////////////////////////////
    235 // WebRtcAecm_BufferFarFrame()
    236 //
    237 // Inserts a frame of data into farend buffer.
    238 //
    239 // Inputs:
    240 //      - aecm          : Pointer to the AECM instance
    241 //      - farend        : In buffer containing one frame of farend signal
    242 //      - farLen        : Length of frame
    243 //
    244 void WebRtcAecm_BufferFarFrame(AecmCore* const aecm,
    245                                const int16_t* const farend,
    246                                const int farLen);
    247 
    248 ////////////////////////////////////////////////////////////////////////////////
    249 // WebRtcAecm_FetchFarFrame()
    250 //
    251 // Read the farend buffer to account for known delay
    252 //
    253 // Inputs:
    254 //      - aecm          : Pointer to the AECM instance
    255 //      - farend        : In buffer containing one frame of farend signal
    256 //      - farLen        : Length of frame
    257 //      - knownDelay    : known delay
    258 //
    259 void WebRtcAecm_FetchFarFrame(AecmCore* const aecm,
    260                               int16_t* const farend,
    261                               const int farLen,
    262                               const int knownDelay);
    263 
    264 // All the functions below are intended to be private
    265 
    266 ////////////////////////////////////////////////////////////////////////////////
    267 // WebRtcAecm_UpdateFarHistory()
    268 //
    269 // Moves the pointer to the next entry and inserts |far_spectrum| and
    270 // corresponding Q-domain in its buffer.
    271 //
    272 // Inputs:
    273 //      - self          : Pointer to the delay estimation instance
    274 //      - far_spectrum  : Pointer to the far end spectrum
    275 //      - far_q         : Q-domain of far end spectrum
    276 //
    277 void WebRtcAecm_UpdateFarHistory(AecmCore* self,
    278                                  uint16_t* far_spectrum,
    279                                  int far_q);
    280 
    281 ////////////////////////////////////////////////////////////////////////////////
    282 // WebRtcAecm_AlignedFarend()
    283 //
    284 // Returns a pointer to the far end spectrum aligned to current near end
    285 // spectrum. The function WebRtc_DelayEstimatorProcessFix(...) should have been
    286 // called before AlignedFarend(...). Otherwise, you get the pointer to the
    287 // previous frame. The memory is only valid until the next call of
    288 // WebRtc_DelayEstimatorProcessFix(...).
    289 //
    290 // Inputs:
    291 //      - self              : Pointer to the AECM instance.
    292 //      - delay             : Current delay estimate.
    293 //
    294 // Output:
    295 //      - far_q             : The Q-domain of the aligned far end spectrum
    296 //
    297 // Return value:
    298 //      - far_spectrum      : Pointer to the aligned far end spectrum
    299 //                            NULL - Error
    300 //
    301 const uint16_t* WebRtcAecm_AlignedFarend(AecmCore* self, int* far_q, int delay);
    302 
    303 ///////////////////////////////////////////////////////////////////////////////
    304 // WebRtcAecm_CalcSuppressionGain()
    305 //
    306 // This function calculates the suppression gain that is used in the
    307 // Wiener filter.
    308 //
    309 // Inputs:
    310 //      - aecm              : Pointer to the AECM instance.
    311 //
    312 // Return value:
    313 //      - supGain           : Suppression gain with which to scale the noise
    314 //                            level (Q14).
    315 //
    316 int16_t WebRtcAecm_CalcSuppressionGain(AecmCore* const aecm);
    317 
    318 ///////////////////////////////////////////////////////////////////////////////
    319 // WebRtcAecm_CalcEnergies()
    320 //
    321 // This function calculates the log of energies for nearend, farend and
    322 // estimated echoes. There is also an update of energy decision levels,
    323 // i.e. internal VAD.
    324 //
    325 // Inputs:
    326 //      - aecm              : Pointer to the AECM instance.
    327 //      - far_spectrum      : Pointer to farend spectrum.
    328 //      - far_q             : Q-domain of farend spectrum.
    329 //      - nearEner          : Near end energy for current block in
    330 //                            Q(aecm->dfaQDomain).
    331 //
    332 // Output:
    333 //     - echoEst            : Estimated echo in Q(xfa_q+RESOLUTION_CHANNEL16).
    334 //
    335 void WebRtcAecm_CalcEnergies(AecmCore* aecm,
    336                              const uint16_t* far_spectrum,
    337                              const int16_t far_q,
    338                              const uint32_t nearEner,
    339                              int32_t* echoEst);
    340 
    341 ///////////////////////////////////////////////////////////////////////////////
    342 // WebRtcAecm_CalcStepSize()
    343 //
    344 // This function calculates the step size used in channel estimation
    345 //
    346 // Inputs:
    347 //      - aecm              : Pointer to the AECM instance.
    348 //
    349 // Return value:
    350 //      - mu                : Stepsize in log2(), i.e. number of shifts.
    351 //
    352 int16_t WebRtcAecm_CalcStepSize(AecmCore* const aecm);
    353 
    354 ///////////////////////////////////////////////////////////////////////////////
    355 // WebRtcAecm_UpdateChannel(...)
    356 //
    357 // This function performs channel estimation.
    358 // NLMS and decision on channel storage.
    359 //
    360 // Inputs:
    361 //      - aecm              : Pointer to the AECM instance.
    362 //      - far_spectrum      : Absolute value of the farend signal in Q(far_q)
    363 //      - far_q             : Q-domain of the farend signal
    364 //      - dfa               : Absolute value of the nearend signal
    365 //                            (Q[aecm->dfaQDomain])
    366 //      - mu                : NLMS step size.
    367 // Input/Output:
    368 //      - echoEst           : Estimated echo in Q(far_q+RESOLUTION_CHANNEL16).
    369 //
    370 void WebRtcAecm_UpdateChannel(AecmCore* aecm,
    371                               const uint16_t* far_spectrum,
    372                               const int16_t far_q,
    373                               const uint16_t* const dfa,
    374                               const int16_t mu,
    375                               int32_t* echoEst);
    376 
    377 extern const int16_t WebRtcAecm_kCosTable[];
    378 extern const int16_t WebRtcAecm_kSinTable[];
    379 
    380 ///////////////////////////////////////////////////////////////////////////////
    381 // Some function pointers, for internal functions shared by ARM NEON and
    382 // generic C code.
    383 //
    384 typedef void (*CalcLinearEnergies)(AecmCore* aecm,
    385                                    const uint16_t* far_spectrum,
    386                                    int32_t* echoEst,
    387                                    uint32_t* far_energy,
    388                                    uint32_t* echo_energy_adapt,
    389                                    uint32_t* echo_energy_stored);
    390 extern CalcLinearEnergies WebRtcAecm_CalcLinearEnergies;
    391 
    392 typedef void (*StoreAdaptiveChannel)(AecmCore* aecm,
    393                                      const uint16_t* far_spectrum,
    394                                      int32_t* echo_est);
    395 extern StoreAdaptiveChannel WebRtcAecm_StoreAdaptiveChannel;
    396 
    397 typedef void (*ResetAdaptiveChannel)(AecmCore* aecm);
    398 extern ResetAdaptiveChannel WebRtcAecm_ResetAdaptiveChannel;
    399 
    400 // For the above function pointers, functions for generic platforms are declared
    401 // and defined as static in file aecm_core.c, while those for ARM Neon platforms
    402 // are declared below and defined in file aecm_core_neon.c.
    403 #if defined(WEBRTC_DETECT_NEON) || defined(WEBRTC_HAS_NEON)
    404 void WebRtcAecm_CalcLinearEnergiesNeon(AecmCore* aecm,
    405                                        const uint16_t* far_spectrum,
    406                                        int32_t* echo_est,
    407                                        uint32_t* far_energy,
    408                                        uint32_t* echo_energy_adapt,
    409                                        uint32_t* echo_energy_stored);
    410 
    411 void WebRtcAecm_StoreAdaptiveChannelNeon(AecmCore* aecm,
    412                                          const uint16_t* far_spectrum,
    413                                          int32_t* echo_est);
    414 
    415 void WebRtcAecm_ResetAdaptiveChannelNeon(AecmCore* aecm);
    416 #endif
    417 
    418 #if defined(MIPS32_LE)
    419 void WebRtcAecm_CalcLinearEnergies_mips(AecmCore* aecm,
    420                                         const uint16_t* far_spectrum,
    421                                         int32_t* echo_est,
    422                                         uint32_t* far_energy,
    423                                         uint32_t* echo_energy_adapt,
    424                                         uint32_t* echo_energy_stored);
    425 #if defined(MIPS_DSP_R1_LE)
    426 void WebRtcAecm_StoreAdaptiveChannel_mips(AecmCore* aecm,
    427                                           const uint16_t* far_spectrum,
    428                                           int32_t* echo_est);
    429 
    430 void WebRtcAecm_ResetAdaptiveChannel_mips(AecmCore* aecm);
    431 #endif
    432 #endif
    433 
    434 #endif
    435