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