Home | History | Annotate | Download | only in aecm
      1 /*
      2  *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
      3  *
      4  *  Use of this source code is governed by a BSD-style license
      5  *  that can be found in the LICENSE file in the root of the source
      6  *  tree. An additional intellectual property rights grant can be found
      7  *  in the file PATENTS.  All contributing project authors may
      8  *  be found in the AUTHORS file in the root of the source tree.
      9  */
     10 
     11 // Performs echo control (suppression) with fft routines in fixed-point
     12 
     13 #ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AECM_MAIN_SOURCE_AECM_CORE_H_
     14 #define WEBRTC_MODULES_AUDIO_PROCESSING_AECM_MAIN_SOURCE_AECM_CORE_H_
     15 
     16 #define AECM_DYNAMIC_Q // turn on/off dynamic Q-domain
     17 //#define AECM_WITH_ABS_APPROX
     18 //#define AECM_SHORT                // for 32 sample partition length (otherwise 64)
     19 
     20 #include "typedefs.h"
     21 #include "signal_processing_library.h"
     22 
     23 // Algorithm parameters
     24 
     25 #define FRAME_LEN       80              // Total frame length, 10 ms
     26 #ifdef AECM_SHORT
     27 
     28 #define PART_LEN        32              // Length of partition
     29 #define PART_LEN_SHIFT  6               // Length of (PART_LEN * 2) in base 2
     30 
     31 #else
     32 
     33 #define PART_LEN        64              // Length of partition
     34 #define PART_LEN_SHIFT  7               // Length of (PART_LEN * 2) in base 2
     35 
     36 #endif
     37 
     38 #define PART_LEN1       (PART_LEN + 1)  // Unique fft coefficients
     39 #define PART_LEN2       (PART_LEN << 1) // Length of partition * 2
     40 #define PART_LEN4       (PART_LEN << 2) // Length of partition * 4
     41 #define FAR_BUF_LEN     PART_LEN4       // Length of buffers
     42 #define MAX_DELAY 100
     43 
     44 // Counter parameters
     45 #ifdef AECM_SHORT
     46 
     47 #define CONV_LEN        1024            // Convergence length used at startup
     48 #else
     49 
     50 #define CONV_LEN        512             // Convergence length used at startup
     51 #endif
     52 
     53 #define CONV_LEN2       (CONV_LEN << 1) // Convergence length * 2 used at startup
     54 // Energy parameters
     55 #define MAX_BUF_LEN     64              // History length of energy signals
     56 
     57 #define FAR_ENERGY_MIN  1025            // Lowest Far energy level: At least 2 in energy
     58 #define FAR_ENERGY_DIFF 929             // Allowed difference between max and min
     59 
     60 #define ENERGY_DEV_OFFSET       0       // The energy error offset in Q8
     61 #define ENERGY_DEV_TOL  400             // The energy estimation tolerance in Q8
     62 #define FAR_ENERGY_VAD_REGION   230     // Far VAD tolerance region
     63 // Stepsize parameters
     64 #define MU_MIN          10              // Min stepsize 2^-MU_MIN (far end energy dependent)
     65 #define MU_MAX          1               // Max stepsize 2^-MU_MAX (far end energy dependent)
     66 #define MU_DIFF         9               // MU_MIN - MU_MAX
     67 // Channel parameters
     68 #define MIN_MSE_COUNT   20              // Min number of consecutive blocks with enough far end
     69                                         // energy to compare channel estimates
     70 #define MIN_MSE_DIFF    29              // The ratio between adapted and stored channel to
     71                                         // accept a new storage (0.8 in Q-MSE_RESOLUTION)
     72 #define MSE_RESOLUTION  5               // MSE parameter resolution
     73 #define RESOLUTION_CHANNEL16    12      // W16 Channel in Q-RESOLUTION_CHANNEL16
     74 #define RESOLUTION_CHANNEL32    28      // W32 Channel in Q-RESOLUTION_CHANNEL
     75 #define CHANNEL_VAD     16              // Minimum energy in frequency band to update channel
     76 // Suppression gain parameters: SUPGAIN_ parameters in Q-(RESOLUTION_SUPGAIN)
     77 #define RESOLUTION_SUPGAIN      8       // Channel in Q-(RESOLUTION_SUPGAIN)
     78 #define SUPGAIN_DEFAULT (1 << RESOLUTION_SUPGAIN)   // Default suppression gain
     79 #define SUPGAIN_ERROR_PARAM_A   3072    // Estimation error parameter (Maximum gain) (8 in Q8)
     80 #define SUPGAIN_ERROR_PARAM_B   1536    // Estimation error parameter (Gain before going down)
     81 #define SUPGAIN_ERROR_PARAM_D   SUPGAIN_DEFAULT // Estimation error parameter
     82                                                 // (Should be the same as Default) (1 in Q8)
     83 #define SUPGAIN_EPC_DT  200             // = SUPGAIN_ERROR_PARAM_C * ENERGY_DEV_TOL
     84 // Defines for "check delay estimation"
     85 #define CORR_WIDTH      31              // Number of samples to correlate over.
     86 #define CORR_MAX        16              // Maximum correlation offset
     87 #define CORR_MAX_BUF    63
     88 #define CORR_DEV        4
     89 #define CORR_MAX_LEVEL  20
     90 #define CORR_MAX_LOW    4
     91 #define CORR_BUF_LEN    (CORR_MAX << 1) + 1
     92 // Note that CORR_WIDTH + 2*CORR_MAX <= MAX_BUF_LEN
     93 
     94 #define ONE_Q14         (1 << 14)
     95 
     96 // NLP defines
     97 #define NLP_COMP_LOW    3277            // 0.2 in Q14
     98 #define NLP_COMP_HIGH   ONE_Q14         // 1 in Q14
     99 
    100 extern const WebRtc_Word16 WebRtcAecm_kSqrtHanning[];
    101 
    102 typedef struct {
    103     WebRtc_Word16 real;
    104     WebRtc_Word16 imag;
    105 } complex16_t;
    106 
    107 typedef struct
    108 {
    109     int farBufWritePos;
    110     int farBufReadPos;
    111     int knownDelay;
    112     int lastKnownDelay;
    113     int firstVAD; // Parameter to control poorly initialized channels
    114 
    115     void *farFrameBuf;
    116     void *nearNoisyFrameBuf;
    117     void *nearCleanFrameBuf;
    118     void *outFrameBuf;
    119 
    120     WebRtc_Word16 farBuf[FAR_BUF_LEN];
    121 
    122     WebRtc_Word16 mult;
    123     WebRtc_UWord32 seed;
    124 
    125     // Delay estimation variables
    126     void* delay_estimator;
    127     WebRtc_UWord16 currentDelay;
    128     // Far end history variables
    129     // TODO(bjornv): Replace |far_history| with ring_buffer.
    130     uint16_t far_history[PART_LEN1 * MAX_DELAY];
    131     int far_history_pos;
    132     int far_q_domains[MAX_DELAY];
    133 
    134     WebRtc_Word16 nlpFlag;
    135     WebRtc_Word16 fixedDelay;
    136 
    137     WebRtc_UWord32 totCount;
    138 
    139     WebRtc_Word16 dfaCleanQDomain;
    140     WebRtc_Word16 dfaCleanQDomainOld;
    141     WebRtc_Word16 dfaNoisyQDomain;
    142     WebRtc_Word16 dfaNoisyQDomainOld;
    143 
    144     WebRtc_Word16 nearLogEnergy[MAX_BUF_LEN];
    145     WebRtc_Word16 farLogEnergy;
    146     WebRtc_Word16 echoAdaptLogEnergy[MAX_BUF_LEN];
    147     WebRtc_Word16 echoStoredLogEnergy[MAX_BUF_LEN];
    148 
    149     // The extra 16 or 32 bytes in the following buffers are for alignment based Neon code.
    150     // It's designed this way since the current GCC compiler can't align a buffer in 16 or 32
    151     // byte boundaries properly.
    152     WebRtc_Word16 channelStored_buf[PART_LEN1 + 8];
    153     WebRtc_Word16 channelAdapt16_buf[PART_LEN1 + 8];
    154     WebRtc_Word32 channelAdapt32_buf[PART_LEN1 + 8];
    155     WebRtc_Word16 xBuf_buf[PART_LEN2 + 16]; // farend
    156     WebRtc_Word16 dBufClean_buf[PART_LEN2 + 16]; // nearend
    157     WebRtc_Word16 dBufNoisy_buf[PART_LEN2 + 16]; // nearend
    158     WebRtc_Word16 outBuf_buf[PART_LEN + 8];
    159 
    160     // Pointers to the above buffers
    161     WebRtc_Word16 *channelStored;
    162     WebRtc_Word16 *channelAdapt16;
    163     WebRtc_Word32 *channelAdapt32;
    164     WebRtc_Word16 *xBuf;
    165     WebRtc_Word16 *dBufClean;
    166     WebRtc_Word16 *dBufNoisy;
    167     WebRtc_Word16 *outBuf;
    168 
    169     WebRtc_Word32 echoFilt[PART_LEN1];
    170     WebRtc_Word16 nearFilt[PART_LEN1];
    171     WebRtc_Word32 noiseEst[PART_LEN1];
    172     int           noiseEstTooLowCtr[PART_LEN1];
    173     int           noiseEstTooHighCtr[PART_LEN1];
    174     WebRtc_Word16 noiseEstCtr;
    175     WebRtc_Word16 cngMode;
    176 
    177     WebRtc_Word32 mseAdaptOld;
    178     WebRtc_Word32 mseStoredOld;
    179     WebRtc_Word32 mseThreshold;
    180 
    181     WebRtc_Word16 farEnergyMin;
    182     WebRtc_Word16 farEnergyMax;
    183     WebRtc_Word16 farEnergyMaxMin;
    184     WebRtc_Word16 farEnergyVAD;
    185     WebRtc_Word16 farEnergyMSE;
    186     int currentVADValue;
    187     WebRtc_Word16 vadUpdateCount;
    188 
    189     WebRtc_Word16 startupState;
    190     WebRtc_Word16 mseChannelCount;
    191     WebRtc_Word16 supGain;
    192     WebRtc_Word16 supGainOld;
    193 
    194     WebRtc_Word16 supGainErrParamA;
    195     WebRtc_Word16 supGainErrParamD;
    196     WebRtc_Word16 supGainErrParamDiffAB;
    197     WebRtc_Word16 supGainErrParamDiffBD;
    198 
    199 #ifdef AEC_DEBUG
    200     FILE *farFile;
    201     FILE *nearFile;
    202     FILE *outFile;
    203 #endif
    204 } AecmCore_t;
    205 
    206 ///////////////////////////////////////////////////////////////////////////////////////////////
    207 // WebRtcAecm_CreateCore(...)
    208 //
    209 // Allocates the memory needed by the AECM. The memory needs to be
    210 // initialized separately using the WebRtcAecm_InitCore() function.
    211 //
    212 // Input:
    213 //      - aecm          : Instance that should be created
    214 //
    215 // Output:
    216 //      - aecm          : Created instance
    217 //
    218 // Return value         :  0 - Ok
    219 //                        -1 - Error
    220 //
    221 int WebRtcAecm_CreateCore(AecmCore_t **aecm);
    222 
    223 ///////////////////////////////////////////////////////////////////////////////////////////////
    224 // WebRtcAecm_InitCore(...)
    225 //
    226 // This function initializes the AECM instant created with WebRtcAecm_CreateCore(...)
    227 // Input:
    228 //      - aecm          : Pointer to the AECM instance
    229 //      - samplingFreq  : Sampling Frequency
    230 //
    231 // Output:
    232 //      - aecm          : Initialized instance
    233 //
    234 // Return value         :  0 - Ok
    235 //                        -1 - Error
    236 //
    237 int WebRtcAecm_InitCore(AecmCore_t * const aecm, int samplingFreq);
    238 
    239 ///////////////////////////////////////////////////////////////////////////////////////////////
    240 // WebRtcAecm_FreeCore(...)
    241 //
    242 // This function releases the memory allocated by WebRtcAecm_CreateCore()
    243 // Input:
    244 //      - aecm          : Pointer to the AECM instance
    245 //
    246 // Return value         :  0 - Ok
    247 //                        -1 - Error
    248 //           11001-11016: Error
    249 //
    250 int WebRtcAecm_FreeCore(AecmCore_t *aecm);
    251 
    252 int WebRtcAecm_Control(AecmCore_t *aecm, int delay, int nlpFlag);
    253 
    254 ///////////////////////////////////////////////////////////////////////////////////////////////
    255 // WebRtcAecm_InitEchoPathCore(...)
    256 //
    257 // This function resets the echo channel adaptation with the specified channel.
    258 // Input:
    259 //      - aecm          : Pointer to the AECM instance
    260 //      - echo_path     : Pointer to the data that should initialize the echo path
    261 //
    262 // Output:
    263 //      - aecm          : Initialized instance
    264 //
    265 void WebRtcAecm_InitEchoPathCore(AecmCore_t* aecm, const WebRtc_Word16* echo_path);
    266 
    267 ///////////////////////////////////////////////////////////////////////////////////////////////
    268 // WebRtcAecm_ProcessFrame(...)
    269 //
    270 // This function processes frames and sends blocks to WebRtcAecm_ProcessBlock(...)
    271 //
    272 // Inputs:
    273 //      - aecm          : Pointer to the AECM instance
    274 //      - farend        : In buffer containing one frame of echo signal
    275 //      - nearendNoisy  : In buffer containing one frame of nearend+echo signal without NS
    276 //      - nearendClean  : In buffer containing one frame of nearend+echo signal with NS
    277 //
    278 // Output:
    279 //      - out           : Out buffer, one frame of nearend signal          :
    280 //
    281 //
    282 int WebRtcAecm_ProcessFrame(AecmCore_t * aecm, const WebRtc_Word16 * farend,
    283                             const WebRtc_Word16 * nearendNoisy,
    284                             const WebRtc_Word16 * nearendClean,
    285                             WebRtc_Word16 * out);
    286 
    287 ///////////////////////////////////////////////////////////////////////////////////////////////
    288 // WebRtcAecm_ProcessBlock(...)
    289 //
    290 // This function is called for every block within one frame
    291 // This function is called by WebRtcAecm_ProcessFrame(...)
    292 //
    293 // Inputs:
    294 //      - aecm          : Pointer to the AECM instance
    295 //      - farend        : In buffer containing one block of echo signal
    296 //      - nearendNoisy  : In buffer containing one frame of nearend+echo signal without NS
    297 //      - nearendClean  : In buffer containing one frame of nearend+echo signal with NS
    298 //
    299 // Output:
    300 //      - out           : Out buffer, one block of nearend signal          :
    301 //
    302 //
    303 int WebRtcAecm_ProcessBlock(AecmCore_t * aecm, const WebRtc_Word16 * farend,
    304                             const WebRtc_Word16 * nearendNoisy,
    305                             const WebRtc_Word16 * noisyClean,
    306                             WebRtc_Word16 * out);
    307 
    308 ///////////////////////////////////////////////////////////////////////////////////////////////
    309 // WebRtcAecm_BufferFarFrame()
    310 //
    311 // Inserts a frame of data into farend buffer.
    312 //
    313 // Inputs:
    314 //      - aecm          : Pointer to the AECM instance
    315 //      - farend        : In buffer containing one frame of farend signal
    316 //      - farLen        : Length of frame
    317 //
    318 void WebRtcAecm_BufferFarFrame(AecmCore_t * const aecm, const WebRtc_Word16 * const farend,
    319                                const int farLen);
    320 
    321 ///////////////////////////////////////////////////////////////////////////////////////////////
    322 // WebRtcAecm_FetchFarFrame()
    323 //
    324 // Read the farend buffer to account for known delay
    325 //
    326 // Inputs:
    327 //      - aecm          : Pointer to the AECM instance
    328 //      - farend        : In buffer containing one frame of farend signal
    329 //      - farLen        : Length of frame
    330 //      - knownDelay    : known delay
    331 //
    332 void WebRtcAecm_FetchFarFrame(AecmCore_t * const aecm, WebRtc_Word16 * const farend,
    333                               const int farLen, const int knownDelay);
    334 
    335 ///////////////////////////////////////////////////////////////////////////////
    336 // Some function pointers, for internal functions shared by ARM NEON and
    337 // generic C code.
    338 //
    339 typedef void (*CalcLinearEnergies)(
    340     AecmCore_t* aecm,
    341     const WebRtc_UWord16* far_spectrum,
    342     WebRtc_Word32* echoEst,
    343     WebRtc_UWord32* far_energy,
    344     WebRtc_UWord32* echo_energy_adapt,
    345     WebRtc_UWord32* echo_energy_stored);
    346 extern CalcLinearEnergies WebRtcAecm_CalcLinearEnergies;
    347 
    348 typedef void (*StoreAdaptiveChannel)(
    349     AecmCore_t* aecm,
    350     const WebRtc_UWord16* far_spectrum,
    351     WebRtc_Word32* echo_est);
    352 extern StoreAdaptiveChannel WebRtcAecm_StoreAdaptiveChannel;
    353 
    354 typedef void (*ResetAdaptiveChannel)(AecmCore_t* aecm);
    355 extern ResetAdaptiveChannel WebRtcAecm_ResetAdaptiveChannel;
    356 
    357 typedef void (*WindowAndFFT)(
    358     WebRtc_Word16* fft,
    359     const WebRtc_Word16* time_signal,
    360     complex16_t* freq_signal,
    361     int time_signal_scaling);
    362 extern WindowAndFFT WebRtcAecm_WindowAndFFT;
    363 
    364 typedef void (*InverseFFTAndWindow)(
    365     AecmCore_t* aecm,
    366     WebRtc_Word16* fft, complex16_t* efw,
    367     WebRtc_Word16* output,
    368     const WebRtc_Word16* nearendClean);
    369 extern InverseFFTAndWindow WebRtcAecm_InverseFFTAndWindow;
    370 
    371 // Initialization of the above function pointers for ARM Neon.
    372 void WebRtcAecm_InitNeon(void);
    373 
    374 
    375 #endif
    376