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