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