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