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/signal_processing/include/signal_processing_library.h"
     17 #include "webrtc/modules/audio_processing/aecm/aecm_defines.h"
     18 #include "webrtc/modules/audio_processing/utility/ring_buffer.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 } complex16_t;
     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_t;
    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 //
    142 // Input:
    143 //      - aecm          : Instance that should be created
    144 //
    145 // Output:
    146 //      - aecm          : Created instance
    147 //
    148 // Return value         :  0 - Ok
    149 //                        -1 - Error
    150 //
    151 int WebRtcAecm_CreateCore(AecmCore_t **aecm);
    152 
    153 ////////////////////////////////////////////////////////////////////////////////
    154 // WebRtcAecm_InitCore(...)
    155 //
    156 // This function initializes the AECM instant created with
    157 // WebRtcAecm_CreateCore(...)
    158 // Input:
    159 //      - aecm          : Pointer to the AECM instance
    160 //      - samplingFreq  : Sampling Frequency
    161 //
    162 // Output:
    163 //      - aecm          : Initialized instance
    164 //
    165 // Return value         :  0 - Ok
    166 //                        -1 - Error
    167 //
    168 int WebRtcAecm_InitCore(AecmCore_t * const aecm, int samplingFreq);
    169 
    170 ////////////////////////////////////////////////////////////////////////////////
    171 // WebRtcAecm_FreeCore(...)
    172 //
    173 // This function releases the memory allocated by WebRtcAecm_CreateCore()
    174 // Input:
    175 //      - aecm          : Pointer to the AECM instance
    176 //
    177 // Return value         :  0 - Ok
    178 //                        -1 - Error
    179 //           11001-11016: Error
    180 //
    181 int WebRtcAecm_FreeCore(AecmCore_t *aecm);
    182 
    183 int WebRtcAecm_Control(AecmCore_t *aecm, int delay, int nlpFlag);
    184 
    185 ////////////////////////////////////////////////////////////////////////////////
    186 // WebRtcAecm_InitEchoPathCore(...)
    187 //
    188 // This function resets the echo channel adaptation with the specified channel.
    189 // Input:
    190 //      - aecm          : Pointer to the AECM instance
    191 //      - echo_path     : Pointer to the data that should initialize the echo
    192 //                        path
    193 //
    194 // Output:
    195 //      - aecm          : Initialized instance
    196 //
    197 void WebRtcAecm_InitEchoPathCore(AecmCore_t* aecm,
    198                                  const int16_t* echo_path);
    199 
    200 ////////////////////////////////////////////////////////////////////////////////
    201 // WebRtcAecm_ProcessFrame(...)
    202 //
    203 // This function processes frames and sends blocks to
    204 // WebRtcAecm_ProcessBlock(...)
    205 //
    206 // Inputs:
    207 //      - aecm          : Pointer to the AECM instance
    208 //      - farend        : In buffer containing one frame of echo signal
    209 //      - nearendNoisy  : In buffer containing one frame of nearend+echo signal
    210 //                        without NS
    211 //      - nearendClean  : In buffer containing one frame of nearend+echo signal
    212 //                        with NS
    213 //
    214 // Output:
    215 //      - out           : Out buffer, one frame of nearend signal          :
    216 //
    217 //
    218 int WebRtcAecm_ProcessFrame(AecmCore_t * aecm, const int16_t * farend,
    219                             const int16_t * nearendNoisy,
    220                             const int16_t * nearendClean,
    221                             int16_t * out);
    222 
    223 ////////////////////////////////////////////////////////////////////////////////
    224 // WebRtcAecm_ProcessBlock(...)
    225 //
    226 // This function is called for every block within one frame
    227 // This function is called by WebRtcAecm_ProcessFrame(...)
    228 //
    229 // Inputs:
    230 //      - aecm          : Pointer to the AECM instance
    231 //      - farend        : In buffer containing one block of echo signal
    232 //      - nearendNoisy  : In buffer containing one frame of nearend+echo signal
    233 //                        without NS
    234 //      - nearendClean  : In buffer containing one frame of nearend+echo signal
    235 //                        with NS
    236 //
    237 // Output:
    238 //      - out           : Out buffer, one block of nearend signal          :
    239 //
    240 //
    241 int WebRtcAecm_ProcessBlock(AecmCore_t * aecm, const int16_t * farend,
    242                             const int16_t * nearendNoisy,
    243                             const int16_t * noisyClean,
    244                             int16_t * out);
    245 
    246 ////////////////////////////////////////////////////////////////////////////////
    247 // WebRtcAecm_BufferFarFrame()
    248 //
    249 // Inserts a frame of data into farend buffer.
    250 //
    251 // Inputs:
    252 //      - aecm          : Pointer to the AECM instance
    253 //      - farend        : In buffer containing one frame of farend signal
    254 //      - farLen        : Length of frame
    255 //
    256 void WebRtcAecm_BufferFarFrame(AecmCore_t * const aecm,
    257                                const int16_t * const farend,
    258                                const int farLen);
    259 
    260 ////////////////////////////////////////////////////////////////////////////////
    261 // WebRtcAecm_FetchFarFrame()
    262 //
    263 // Read the farend buffer to account for known delay
    264 //
    265 // Inputs:
    266 //      - aecm          : Pointer to the AECM instance
    267 //      - farend        : In buffer containing one frame of farend signal
    268 //      - farLen        : Length of frame
    269 //      - knownDelay    : known delay
    270 //
    271 void WebRtcAecm_FetchFarFrame(AecmCore_t * const aecm,
    272                               int16_t * const farend,
    273                               const int farLen, const int knownDelay);
    274 
    275 
    276 // All the functions below are intended to be private
    277 
    278 ////////////////////////////////////////////////////////////////////////////////
    279 // WebRtcAecm_UpdateFarHistory()
    280 //
    281 // Moves the pointer to the next entry and inserts |far_spectrum| and
    282 // corresponding Q-domain in its buffer.
    283 //
    284 // Inputs:
    285 //      - self          : Pointer to the delay estimation instance
    286 //      - far_spectrum  : Pointer to the far end spectrum
    287 //      - far_q         : Q-domain of far end spectrum
    288 //
    289 void WebRtcAecm_UpdateFarHistory(AecmCore_t* self,
    290                                  uint16_t* far_spectrum,
    291                                  int far_q);
    292 
    293 ////////////////////////////////////////////////////////////////////////////////
    294 // WebRtcAecm_AlignedFarend()
    295 //
    296 // Returns a pointer to the far end spectrum aligned to current near end
    297 // spectrum. The function WebRtc_DelayEstimatorProcessFix(...) should have been
    298 // called before AlignedFarend(...). Otherwise, you get the pointer to the
    299 // previous frame. The memory is only valid until the next call of
    300 // WebRtc_DelayEstimatorProcessFix(...).
    301 //
    302 // Inputs:
    303 //      - self              : Pointer to the AECM instance.
    304 //      - delay             : Current delay estimate.
    305 //
    306 // Output:
    307 //      - far_q             : The Q-domain of the aligned far end spectrum
    308 //
    309 // Return value:
    310 //      - far_spectrum      : Pointer to the aligned far end spectrum
    311 //                            NULL - Error
    312 //
    313 const uint16_t* WebRtcAecm_AlignedFarend(AecmCore_t* self,
    314                                          int* far_q,
    315                                          int delay);
    316 
    317 ///////////////////////////////////////////////////////////////////////////////
    318 // WebRtcAecm_CalcSuppressionGain()
    319 //
    320 // This function calculates the suppression gain that is used in the
    321 // Wiener filter.
    322 //
    323 // Inputs:
    324 //      - aecm              : Pointer to the AECM instance.
    325 //
    326 // Return value:
    327 //      - supGain           : Suppression gain with which to scale the noise
    328 //                            level (Q14).
    329 //
    330 int16_t WebRtcAecm_CalcSuppressionGain(AecmCore_t * const aecm);
    331 
    332 ///////////////////////////////////////////////////////////////////////////////
    333 // WebRtcAecm_CalcEnergies()
    334 //
    335 // This function calculates the log of energies for nearend, farend and
    336 // estimated echoes. There is also an update of energy decision levels,
    337 // i.e. internal VAD.
    338 //
    339 // Inputs:
    340 //      - aecm              : Pointer to the AECM instance.
    341 //      - far_spectrum      : Pointer to farend spectrum.
    342 //      - far_q             : Q-domain of farend spectrum.
    343 //      - nearEner          : Near end energy for current block in
    344 //                            Q(aecm->dfaQDomain).
    345 //
    346 // Output:
    347 //     - echoEst            : Estimated echo in Q(xfa_q+RESOLUTION_CHANNEL16).
    348 //
    349 void WebRtcAecm_CalcEnergies(AecmCore_t * aecm,
    350                              const uint16_t* far_spectrum,
    351                              const int16_t far_q,
    352                              const uint32_t nearEner,
    353                              int32_t * echoEst);
    354 
    355 ///////////////////////////////////////////////////////////////////////////////
    356 // WebRtcAecm_CalcStepSize()
    357 //
    358 // This function calculates the step size used in channel estimation
    359 //
    360 // Inputs:
    361 //      - aecm              : Pointer to the AECM instance.
    362 //
    363 // Return value:
    364 //      - mu                : Stepsize in log2(), i.e. number of shifts.
    365 //
    366 int16_t WebRtcAecm_CalcStepSize(AecmCore_t * const aecm);
    367 
    368 ///////////////////////////////////////////////////////////////////////////////
    369 // WebRtcAecm_UpdateChannel(...)
    370 //
    371 // This function performs channel estimation.
    372 // NLMS and decision on channel storage.
    373 //
    374 // Inputs:
    375 //      - aecm              : Pointer to the AECM instance.
    376 //      - far_spectrum      : Absolute value of the farend signal in Q(far_q)
    377 //      - far_q             : Q-domain of the farend signal
    378 //      - dfa               : Absolute value of the nearend signal
    379 //                            (Q[aecm->dfaQDomain])
    380 //      - mu                : NLMS step size.
    381 // Input/Output:
    382 //      - echoEst           : Estimated echo in Q(far_q+RESOLUTION_CHANNEL16).
    383 //
    384 void WebRtcAecm_UpdateChannel(AecmCore_t * aecm,
    385                               const uint16_t* far_spectrum,
    386                               const int16_t far_q,
    387                               const uint16_t * const dfa,
    388                               const int16_t mu,
    389                               int32_t * echoEst);
    390 
    391 extern const int16_t WebRtcAecm_kCosTable[];
    392 extern const int16_t WebRtcAecm_kSinTable[];
    393 
    394 ///////////////////////////////////////////////////////////////////////////////
    395 // Some function pointers, for internal functions shared by ARM NEON and
    396 // generic C code.
    397 //
    398 typedef void (*CalcLinearEnergies)(
    399     AecmCore_t* aecm,
    400     const uint16_t* far_spectrum,
    401     int32_t* echoEst,
    402     uint32_t* far_energy,
    403     uint32_t* echo_energy_adapt,
    404     uint32_t* echo_energy_stored);
    405 extern CalcLinearEnergies WebRtcAecm_CalcLinearEnergies;
    406 
    407 typedef void (*StoreAdaptiveChannel)(
    408     AecmCore_t* aecm,
    409     const uint16_t* far_spectrum,
    410     int32_t* echo_est);
    411 extern StoreAdaptiveChannel WebRtcAecm_StoreAdaptiveChannel;
    412 
    413 typedef void (*ResetAdaptiveChannel)(AecmCore_t* aecm);
    414 extern ResetAdaptiveChannel WebRtcAecm_ResetAdaptiveChannel;
    415 
    416 // For the above function pointers, functions for generic platforms are declared
    417 // and defined as static in file aecm_core.c, while those for ARM Neon platforms
    418 // are declared below and defined in file aecm_core_neon.s.
    419 #if (defined WEBRTC_DETECT_ARM_NEON) || defined (WEBRTC_ARCH_ARM_NEON)
    420 void WebRtcAecm_CalcLinearEnergiesNeon(AecmCore_t* aecm,
    421                                        const uint16_t* far_spectrum,
    422                                        int32_t* echo_est,
    423                                        uint32_t* far_energy,
    424                                        uint32_t* echo_energy_adapt,
    425                                        uint32_t* echo_energy_stored);
    426 
    427 void WebRtcAecm_StoreAdaptiveChannelNeon(AecmCore_t* aecm,
    428                                          const uint16_t* far_spectrum,
    429                                          int32_t* echo_est);
    430 
    431 void WebRtcAecm_ResetAdaptiveChannelNeon(AecmCore_t* aecm);
    432 #endif
    433 
    434 #if defined(MIPS32_LE)
    435 void WebRtcAecm_CalcLinearEnergies_mips(AecmCore_t* aecm,
    436                                         const uint16_t* far_spectrum,
    437                                         int32_t* echo_est,
    438                                         uint32_t* far_energy,
    439                                         uint32_t* echo_energy_adapt,
    440                                         uint32_t* echo_energy_stored);
    441 #if defined(MIPS_DSP_R1_LE)
    442 void WebRtcAecm_StoreAdaptiveChannel_mips(AecmCore_t* aecm,
    443                                           const uint16_t* far_spectrum,
    444                                           int32_t* echo_est);
    445 
    446 void WebRtcAecm_ResetAdaptiveChannel_mips(AecmCore_t* aecm);
    447 #endif
    448 #endif
    449 
    450 #endif
    451