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