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