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 MODULES_AUDIO_PROCESSING_AECM_AECM_CORE_H_ 14 #define MODULES_AUDIO_PROCESSING_AECM_AECM_CORE_H_ 15 16 extern "C" { 17 #include "common_audio/ring_buffer.h" 18 #include "common_audio/signal_processing/include/signal_processing_library.h" 19 } 20 #include "modules/audio_processing/aecm/aecm_defines.h" 21 22 struct RealFFT; 23 24 namespace webrtc { 25 26 #ifdef _MSC_VER // visual c++ 27 #define ALIGN8_BEG __declspec(align(8)) 28 #define ALIGN8_END 29 #else // gcc or icc 30 #define ALIGN8_BEG 31 #define ALIGN8_END __attribute__((aligned(8))) 32 #endif 33 34 typedef struct { 35 int16_t real; 36 int16_t imag; 37 } ComplexInt16; 38 39 typedef struct { 40 int farBufWritePos; 41 int farBufReadPos; 42 int knownDelay; 43 int lastKnownDelay; 44 int firstVAD; // Parameter to control poorly initialized channels 45 46 RingBuffer* farFrameBuf; 47 RingBuffer* nearNoisyFrameBuf; 48 RingBuffer* nearCleanFrameBuf; 49 RingBuffer* outFrameBuf; 50 51 int16_t farBuf[FAR_BUF_LEN]; 52 53 int16_t mult; 54 uint32_t seed; 55 56 // Delay estimation variables 57 void* delay_estimator_farend; 58 void* delay_estimator; 59 uint16_t currentDelay; 60 // Far end history variables 61 // TODO(bjornv): Replace |far_history| with ring_buffer. 62 uint16_t far_history[PART_LEN1 * MAX_DELAY]; 63 int far_history_pos; 64 int far_q_domains[MAX_DELAY]; 65 66 int16_t nlpFlag; 67 int16_t fixedDelay; 68 69 uint32_t totCount; 70 71 int16_t dfaCleanQDomain; 72 int16_t dfaCleanQDomainOld; 73 int16_t dfaNoisyQDomain; 74 int16_t dfaNoisyQDomainOld; 75 76 int16_t nearLogEnergy[MAX_BUF_LEN]; 77 int16_t farLogEnergy; 78 int16_t echoAdaptLogEnergy[MAX_BUF_LEN]; 79 int16_t echoStoredLogEnergy[MAX_BUF_LEN]; 80 81 // The extra 16 or 32 bytes in the following buffers are for alignment based 82 // Neon code. 83 // It's designed this way since the current GCC compiler can't align a 84 // buffer in 16 or 32 byte boundaries properly. 85 int16_t channelStored_buf[PART_LEN1 + 8]; 86 int16_t channelAdapt16_buf[PART_LEN1 + 8]; 87 int32_t channelAdapt32_buf[PART_LEN1 + 8]; 88 int16_t xBuf_buf[PART_LEN2 + 16]; // farend 89 int16_t dBufClean_buf[PART_LEN2 + 16]; // nearend 90 int16_t dBufNoisy_buf[PART_LEN2 + 16]; // nearend 91 int16_t outBuf_buf[PART_LEN + 8]; 92 93 // Pointers to the above buffers 94 int16_t* channelStored; 95 int16_t* channelAdapt16; 96 int32_t* channelAdapt32; 97 int16_t* xBuf; 98 int16_t* dBufClean; 99 int16_t* dBufNoisy; 100 int16_t* outBuf; 101 102 int32_t echoFilt[PART_LEN1]; 103 int16_t nearFilt[PART_LEN1]; 104 int32_t noiseEst[PART_LEN1]; 105 int noiseEstTooLowCtr[PART_LEN1]; 106 int noiseEstTooHighCtr[PART_LEN1]; 107 int16_t noiseEstCtr; 108 int16_t cngMode; 109 110 int32_t mseAdaptOld; 111 int32_t mseStoredOld; 112 int32_t mseThreshold; 113 114 int16_t farEnergyMin; 115 int16_t farEnergyMax; 116 int16_t farEnergyMaxMin; 117 int16_t farEnergyVAD; 118 int16_t farEnergyMSE; 119 int currentVADValue; 120 int16_t vadUpdateCount; 121 122 int16_t startupState; 123 int16_t mseChannelCount; 124 int16_t supGain; 125 int16_t supGainOld; 126 127 int16_t supGainErrParamA; 128 int16_t supGainErrParamD; 129 int16_t supGainErrParamDiffAB; 130 int16_t supGainErrParamDiffBD; 131 132 struct RealFFT* real_fft; 133 134 #ifdef AEC_DEBUG 135 FILE* farFile; 136 FILE* nearFile; 137 FILE* outFile; 138 #endif 139 } AecmCore; 140 141 //////////////////////////////////////////////////////////////////////////////// 142 // WebRtcAecm_CreateCore() 143 // 144 // Allocates the memory needed by the AECM. The memory needs to be 145 // initialized separately using the WebRtcAecm_InitCore() function. 146 // Returns a pointer to the instance and a nullptr at failure. 147 AecmCore* WebRtcAecm_CreateCore(); 148 149 //////////////////////////////////////////////////////////////////////////////// 150 // WebRtcAecm_InitCore(...) 151 // 152 // This function initializes the AECM instant created with 153 // WebRtcAecm_CreateCore() 154 // Input: 155 // - aecm : Pointer to the AECM instance 156 // - samplingFreq : Sampling Frequency 157 // 158 // Output: 159 // - aecm : Initialized instance 160 // 161 // Return value : 0 - Ok 162 // -1 - Error 163 // 164 int WebRtcAecm_InitCore(AecmCore* const aecm, int samplingFreq); 165 166 //////////////////////////////////////////////////////////////////////////////// 167 // WebRtcAecm_FreeCore(...) 168 // 169 // This function releases the memory allocated by WebRtcAecm_CreateCore() 170 // Input: 171 // - aecm : Pointer to the AECM instance 172 // 173 void WebRtcAecm_FreeCore(AecmCore* aecm); 174 175 int WebRtcAecm_Control(AecmCore* aecm, int delay, int nlpFlag); 176 177 //////////////////////////////////////////////////////////////////////////////// 178 // WebRtcAecm_InitEchoPathCore(...) 179 // 180 // This function resets the echo channel adaptation with the specified channel. 181 // Input: 182 // - aecm : Pointer to the AECM instance 183 // - echo_path : Pointer to the data that should initialize the echo 184 // path 185 // 186 // Output: 187 // - aecm : Initialized instance 188 // 189 void WebRtcAecm_InitEchoPathCore(AecmCore* aecm, const int16_t* echo_path); 190 191 //////////////////////////////////////////////////////////////////////////////// 192 // WebRtcAecm_ProcessFrame(...) 193 // 194 // This function processes frames and sends blocks to 195 // WebRtcAecm_ProcessBlock(...) 196 // 197 // Inputs: 198 // - aecm : Pointer to the AECM instance 199 // - farend : In buffer containing one frame of echo signal 200 // - nearendNoisy : In buffer containing one frame of nearend+echo signal 201 // without NS 202 // - nearendClean : In buffer containing one frame of nearend+echo signal 203 // with NS 204 // 205 // Output: 206 // - out : Out buffer, one frame of nearend signal : 207 // 208 // 209 int WebRtcAecm_ProcessFrame(AecmCore* aecm, 210 const int16_t* farend, 211 const int16_t* nearendNoisy, 212 const int16_t* nearendClean, 213 int16_t* out); 214 215 //////////////////////////////////////////////////////////////////////////////// 216 // WebRtcAecm_ProcessBlock(...) 217 // 218 // This function is called for every block within one frame 219 // This function is called by WebRtcAecm_ProcessFrame(...) 220 // 221 // Inputs: 222 // - aecm : Pointer to the AECM instance 223 // - farend : In buffer containing one block of echo signal 224 // - nearendNoisy : In buffer containing one frame of nearend+echo signal 225 // without NS 226 // - nearendClean : In buffer containing one frame of nearend+echo signal 227 // with NS 228 // 229 // Output: 230 // - out : Out buffer, one block of nearend signal : 231 // 232 // 233 int WebRtcAecm_ProcessBlock(AecmCore* aecm, 234 const int16_t* farend, 235 const int16_t* nearendNoisy, 236 const int16_t* noisyClean, 237 int16_t* out); 238 239 //////////////////////////////////////////////////////////////////////////////// 240 // WebRtcAecm_BufferFarFrame() 241 // 242 // Inserts a frame of data into farend buffer. 243 // 244 // Inputs: 245 // - aecm : Pointer to the AECM instance 246 // - farend : In buffer containing one frame of farend signal 247 // - farLen : Length of frame 248 // 249 void WebRtcAecm_BufferFarFrame(AecmCore* const aecm, 250 const int16_t* const farend, 251 const int farLen); 252 253 //////////////////////////////////////////////////////////////////////////////// 254 // WebRtcAecm_FetchFarFrame() 255 // 256 // Read the farend buffer to account for known delay 257 // 258 // Inputs: 259 // - aecm : Pointer to the AECM instance 260 // - farend : In buffer containing one frame of farend signal 261 // - farLen : Length of frame 262 // - knownDelay : known delay 263 // 264 void WebRtcAecm_FetchFarFrame(AecmCore* const aecm, 265 int16_t* const farend, 266 const int farLen, 267 const int knownDelay); 268 269 // All the functions below are intended to be private 270 271 //////////////////////////////////////////////////////////////////////////////// 272 // WebRtcAecm_UpdateFarHistory() 273 // 274 // Moves the pointer to the next entry and inserts |far_spectrum| and 275 // corresponding Q-domain in its buffer. 276 // 277 // Inputs: 278 // - self : Pointer to the delay estimation instance 279 // - far_spectrum : Pointer to the far end spectrum 280 // - far_q : Q-domain of far end spectrum 281 // 282 void WebRtcAecm_UpdateFarHistory(AecmCore* self, 283 uint16_t* far_spectrum, 284 int far_q); 285 286 //////////////////////////////////////////////////////////////////////////////// 287 // WebRtcAecm_AlignedFarend() 288 // 289 // Returns a pointer to the far end spectrum aligned to current near end 290 // spectrum. The function WebRtc_DelayEstimatorProcessFix(...) should have been 291 // called before AlignedFarend(...). Otherwise, you get the pointer to the 292 // previous frame. The memory is only valid until the next call of 293 // WebRtc_DelayEstimatorProcessFix(...). 294 // 295 // Inputs: 296 // - self : Pointer to the AECM instance. 297 // - delay : Current delay estimate. 298 // 299 // Output: 300 // - far_q : The Q-domain of the aligned far end spectrum 301 // 302 // Return value: 303 // - far_spectrum : Pointer to the aligned far end spectrum 304 // NULL - Error 305 // 306 const uint16_t* WebRtcAecm_AlignedFarend(AecmCore* self, int* far_q, int delay); 307 308 /////////////////////////////////////////////////////////////////////////////// 309 // WebRtcAecm_CalcSuppressionGain() 310 // 311 // This function calculates the suppression gain that is used in the 312 // Wiener filter. 313 // 314 // Inputs: 315 // - aecm : Pointer to the AECM instance. 316 // 317 // Return value: 318 // - supGain : Suppression gain with which to scale the noise 319 // level (Q14). 320 // 321 int16_t WebRtcAecm_CalcSuppressionGain(AecmCore* const aecm); 322 323 /////////////////////////////////////////////////////////////////////////////// 324 // WebRtcAecm_CalcEnergies() 325 // 326 // This function calculates the log of energies for nearend, farend and 327 // estimated echoes. There is also an update of energy decision levels, 328 // i.e. internal VAD. 329 // 330 // Inputs: 331 // - aecm : Pointer to the AECM instance. 332 // - far_spectrum : Pointer to farend spectrum. 333 // - far_q : Q-domain of farend spectrum. 334 // - nearEner : Near end energy for current block in 335 // Q(aecm->dfaQDomain). 336 // 337 // Output: 338 // - echoEst : Estimated echo in Q(xfa_q+RESOLUTION_CHANNEL16). 339 // 340 void WebRtcAecm_CalcEnergies(AecmCore* aecm, 341 const uint16_t* far_spectrum, 342 const int16_t far_q, 343 const uint32_t nearEner, 344 int32_t* echoEst); 345 346 /////////////////////////////////////////////////////////////////////////////// 347 // WebRtcAecm_CalcStepSize() 348 // 349 // This function calculates the step size used in channel estimation 350 // 351 // Inputs: 352 // - aecm : Pointer to the AECM instance. 353 // 354 // Return value: 355 // - mu : Stepsize in log2(), i.e. number of shifts. 356 // 357 int16_t WebRtcAecm_CalcStepSize(AecmCore* const aecm); 358 359 /////////////////////////////////////////////////////////////////////////////// 360 // WebRtcAecm_UpdateChannel(...) 361 // 362 // This function performs channel estimation. 363 // NLMS and decision on channel storage. 364 // 365 // Inputs: 366 // - aecm : Pointer to the AECM instance. 367 // - far_spectrum : Absolute value of the farend signal in Q(far_q) 368 // - far_q : Q-domain of the farend signal 369 // - dfa : Absolute value of the nearend signal 370 // (Q[aecm->dfaQDomain]) 371 // - mu : NLMS step size. 372 // Input/Output: 373 // - echoEst : Estimated echo in Q(far_q+RESOLUTION_CHANNEL16). 374 // 375 void WebRtcAecm_UpdateChannel(AecmCore* aecm, 376 const uint16_t* far_spectrum, 377 const int16_t far_q, 378 const uint16_t* const dfa, 379 const int16_t mu, 380 int32_t* echoEst); 381 382 extern const int16_t WebRtcAecm_kCosTable[]; 383 extern const int16_t WebRtcAecm_kSinTable[]; 384 385 /////////////////////////////////////////////////////////////////////////////// 386 // Some function pointers, for internal functions shared by ARM NEON and 387 // generic C code. 388 // 389 typedef void (*CalcLinearEnergies)(AecmCore* aecm, 390 const uint16_t* far_spectrum, 391 int32_t* echoEst, 392 uint32_t* far_energy, 393 uint32_t* echo_energy_adapt, 394 uint32_t* echo_energy_stored); 395 extern CalcLinearEnergies WebRtcAecm_CalcLinearEnergies; 396 397 typedef void (*StoreAdaptiveChannel)(AecmCore* aecm, 398 const uint16_t* far_spectrum, 399 int32_t* echo_est); 400 extern StoreAdaptiveChannel WebRtcAecm_StoreAdaptiveChannel; 401 402 typedef void (*ResetAdaptiveChannel)(AecmCore* aecm); 403 extern ResetAdaptiveChannel WebRtcAecm_ResetAdaptiveChannel; 404 405 // For the above function pointers, functions for generic platforms are declared 406 // and defined as static in file aecm_core.c, while those for ARM Neon platforms 407 // are declared below and defined in file aecm_core_neon.c. 408 #if defined(WEBRTC_HAS_NEON) 409 void WebRtcAecm_CalcLinearEnergiesNeon(AecmCore* aecm, 410 const uint16_t* far_spectrum, 411 int32_t* echo_est, 412 uint32_t* far_energy, 413 uint32_t* echo_energy_adapt, 414 uint32_t* echo_energy_stored); 415 416 void WebRtcAecm_StoreAdaptiveChannelNeon(AecmCore* aecm, 417 const uint16_t* far_spectrum, 418 int32_t* echo_est); 419 420 void WebRtcAecm_ResetAdaptiveChannelNeon(AecmCore* aecm); 421 #endif 422 423 #if defined(MIPS32_LE) 424 void WebRtcAecm_CalcLinearEnergies_mips(AecmCore* aecm, 425 const uint16_t* far_spectrum, 426 int32_t* echo_est, 427 uint32_t* far_energy, 428 uint32_t* echo_energy_adapt, 429 uint32_t* echo_energy_stored); 430 #if defined(MIPS_DSP_R1_LE) 431 void WebRtcAecm_StoreAdaptiveChannel_mips(AecmCore* aecm, 432 const uint16_t* far_spectrum, 433 int32_t* echo_est); 434 435 void WebRtcAecm_ResetAdaptiveChannel_mips(AecmCore* aecm); 436 #endif 437 #endif 438 439 } // namespace webrtc 440 441 #endif 442