aecm_core.h revision 6b6301588ef2d7b5f5d442aa95bef442a43ead53
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 29typedef struct { 30 int16_t real; 31 int16_t imag; 32} ComplexInt16; 33 34typedef 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// 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// 151int WebRtcAecm_CreateCore(AecmCore** 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// 168int WebRtcAecm_InitCore(AecmCore* 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// 181int WebRtcAecm_FreeCore(AecmCore* aecm); 182 183int WebRtcAecm_Control(AecmCore* 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// 197void WebRtcAecm_InitEchoPathCore(AecmCore* aecm, const int16_t* echo_path); 198 199//////////////////////////////////////////////////////////////////////////////// 200// WebRtcAecm_ProcessFrame(...) 201// 202// This function processes frames and sends blocks to 203// WebRtcAecm_ProcessBlock(...) 204// 205// Inputs: 206// - aecm : Pointer to the AECM instance 207// - farend : In buffer containing one frame of echo signal 208// - nearendNoisy : In buffer containing one frame of nearend+echo signal 209// without NS 210// - nearendClean : In buffer containing one frame of nearend+echo signal 211// with NS 212// 213// Output: 214// - out : Out buffer, one frame of nearend signal : 215// 216// 217int WebRtcAecm_ProcessFrame(AecmCore* aecm, 218 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// 241int WebRtcAecm_ProcessBlock(AecmCore* aecm, 242 const int16_t* farend, 243 const int16_t* nearendNoisy, 244 const int16_t* noisyClean, 245 int16_t* out); 246 247//////////////////////////////////////////////////////////////////////////////// 248// WebRtcAecm_BufferFarFrame() 249// 250// Inserts a frame of data into farend buffer. 251// 252// Inputs: 253// - aecm : Pointer to the AECM instance 254// - farend : In buffer containing one frame of farend signal 255// - farLen : Length of frame 256// 257void WebRtcAecm_BufferFarFrame(AecmCore* const aecm, 258 const int16_t* const farend, 259 const int farLen); 260 261//////////////////////////////////////////////////////////////////////////////// 262// WebRtcAecm_FetchFarFrame() 263// 264// Read the farend buffer to account for known delay 265// 266// Inputs: 267// - aecm : Pointer to the AECM instance 268// - farend : In buffer containing one frame of farend signal 269// - farLen : Length of frame 270// - knownDelay : known delay 271// 272void WebRtcAecm_FetchFarFrame(AecmCore* const aecm, 273 int16_t* const farend, 274 const int farLen, 275 const int knownDelay); 276 277// All the functions below are intended to be private 278 279//////////////////////////////////////////////////////////////////////////////// 280// WebRtcAecm_UpdateFarHistory() 281// 282// Moves the pointer to the next entry and inserts |far_spectrum| and 283// corresponding Q-domain in its buffer. 284// 285// Inputs: 286// - self : Pointer to the delay estimation instance 287// - far_spectrum : Pointer to the far end spectrum 288// - far_q : Q-domain of far end spectrum 289// 290void WebRtcAecm_UpdateFarHistory(AecmCore* self, 291 uint16_t* far_spectrum, 292 int far_q); 293 294//////////////////////////////////////////////////////////////////////////////// 295// WebRtcAecm_AlignedFarend() 296// 297// Returns a pointer to the far end spectrum aligned to current near end 298// spectrum. The function WebRtc_DelayEstimatorProcessFix(...) should have been 299// called before AlignedFarend(...). Otherwise, you get the pointer to the 300// previous frame. The memory is only valid until the next call of 301// WebRtc_DelayEstimatorProcessFix(...). 302// 303// Inputs: 304// - self : Pointer to the AECM instance. 305// - delay : Current delay estimate. 306// 307// Output: 308// - far_q : The Q-domain of the aligned far end spectrum 309// 310// Return value: 311// - far_spectrum : Pointer to the aligned far end spectrum 312// NULL - Error 313// 314const uint16_t* WebRtcAecm_AlignedFarend(AecmCore* self, int* far_q, int delay); 315 316/////////////////////////////////////////////////////////////////////////////// 317// WebRtcAecm_CalcSuppressionGain() 318// 319// This function calculates the suppression gain that is used in the 320// Wiener filter. 321// 322// Inputs: 323// - aecm : Pointer to the AECM instance. 324// 325// Return value: 326// - supGain : Suppression gain with which to scale the noise 327// level (Q14). 328// 329int16_t WebRtcAecm_CalcSuppressionGain(AecmCore* const aecm); 330 331/////////////////////////////////////////////////////////////////////////////// 332// WebRtcAecm_CalcEnergies() 333// 334// This function calculates the log of energies for nearend, farend and 335// estimated echoes. There is also an update of energy decision levels, 336// i.e. internal VAD. 337// 338// Inputs: 339// - aecm : Pointer to the AECM instance. 340// - far_spectrum : Pointer to farend spectrum. 341// - far_q : Q-domain of farend spectrum. 342// - nearEner : Near end energy for current block in 343// Q(aecm->dfaQDomain). 344// 345// Output: 346// - echoEst : Estimated echo in Q(xfa_q+RESOLUTION_CHANNEL16). 347// 348void WebRtcAecm_CalcEnergies(AecmCore* aecm, 349 const uint16_t* far_spectrum, 350 const int16_t far_q, 351 const uint32_t nearEner, 352 int32_t* echoEst); 353 354/////////////////////////////////////////////////////////////////////////////// 355// WebRtcAecm_CalcStepSize() 356// 357// This function calculates the step size used in channel estimation 358// 359// Inputs: 360// - aecm : Pointer to the AECM instance. 361// 362// Return value: 363// - mu : Stepsize in log2(), i.e. number of shifts. 364// 365int16_t WebRtcAecm_CalcStepSize(AecmCore* const aecm); 366 367/////////////////////////////////////////////////////////////////////////////// 368// WebRtcAecm_UpdateChannel(...) 369// 370// This function performs channel estimation. 371// NLMS and decision on channel storage. 372// 373// Inputs: 374// - aecm : Pointer to the AECM instance. 375// - far_spectrum : Absolute value of the farend signal in Q(far_q) 376// - far_q : Q-domain of the farend signal 377// - dfa : Absolute value of the nearend signal 378// (Q[aecm->dfaQDomain]) 379// - mu : NLMS step size. 380// Input/Output: 381// - echoEst : Estimated echo in Q(far_q+RESOLUTION_CHANNEL16). 382// 383void WebRtcAecm_UpdateChannel(AecmCore* aecm, 384 const uint16_t* far_spectrum, 385 const int16_t far_q, 386 const uint16_t* const dfa, 387 const int16_t mu, 388 int32_t* echoEst); 389 390extern const int16_t WebRtcAecm_kCosTable[]; 391extern const int16_t WebRtcAecm_kSinTable[]; 392 393/////////////////////////////////////////////////////////////////////////////// 394// Some function pointers, for internal functions shared by ARM NEON and 395// generic C code. 396// 397typedef void (*CalcLinearEnergies)(AecmCore* aecm, 398 const uint16_t* far_spectrum, 399 int32_t* echoEst, 400 uint32_t* far_energy, 401 uint32_t* echo_energy_adapt, 402 uint32_t* echo_energy_stored); 403extern CalcLinearEnergies WebRtcAecm_CalcLinearEnergies; 404 405typedef void (*StoreAdaptiveChannel)(AecmCore* aecm, 406 const uint16_t* far_spectrum, 407 int32_t* echo_est); 408extern StoreAdaptiveChannel WebRtcAecm_StoreAdaptiveChannel; 409 410typedef void (*ResetAdaptiveChannel)(AecmCore* aecm); 411extern ResetAdaptiveChannel WebRtcAecm_ResetAdaptiveChannel; 412 413// For the above function pointers, functions for generic platforms are declared 414// and defined as static in file aecm_core.c, while those for ARM Neon platforms 415// are declared below and defined in file aecm_core_neon.c. 416#if (defined WEBRTC_DETECT_ARM_NEON) || defined (WEBRTC_ARCH_ARM_NEON) || \ 417 defined (WEBRTC_ARCH_ARM64_NEON) 418void WebRtcAecm_CalcLinearEnergiesNeon(AecmCore* aecm, 419 const uint16_t* far_spectrum, 420 int32_t* echo_est, 421 uint32_t* far_energy, 422 uint32_t* echo_energy_adapt, 423 uint32_t* echo_energy_stored); 424 425void WebRtcAecm_StoreAdaptiveChannelNeon(AecmCore* aecm, 426 const uint16_t* far_spectrum, 427 int32_t* echo_est); 428 429void WebRtcAecm_ResetAdaptiveChannelNeon(AecmCore* aecm); 430#endif 431 432#if defined(MIPS32_LE) 433void WebRtcAecm_CalcLinearEnergies_mips(AecmCore* aecm, 434 const uint16_t* far_spectrum, 435 int32_t* echo_est, 436 uint32_t* far_energy, 437 uint32_t* echo_energy_adapt, 438 uint32_t* echo_energy_stored); 439#if defined(MIPS_DSP_R1_LE) 440void WebRtcAecm_StoreAdaptiveChannel_mips(AecmCore* aecm, 441 const uint16_t* far_spectrum, 442 int32_t* echo_est); 443 444void WebRtcAecm_ResetAdaptiveChannel_mips(AecmCore* aecm); 445#endif 446#endif 447 448#endif 449