1/* 2 * Copyright (c) 2011 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_MAIN_SOURCE_AECM_CORE_H_ 14#define WEBRTC_MODULES_AUDIO_PROCESSING_AECM_MAIN_SOURCE_AECM_CORE_H_ 15 16#define AECM_DYNAMIC_Q // turn on/off dynamic Q-domain 17//#define AECM_WITH_ABS_APPROX 18//#define AECM_SHORT // for 32 sample partition length (otherwise 64) 19 20#include "typedefs.h" 21#include "signal_processing_library.h" 22 23// Algorithm parameters 24 25#define FRAME_LEN 80 // Total frame length, 10 ms 26#ifdef AECM_SHORT 27 28#define PART_LEN 32 // Length of partition 29#define PART_LEN_SHIFT 6 // Length of (PART_LEN * 2) in base 2 30 31#else 32 33#define PART_LEN 64 // Length of partition 34#define PART_LEN_SHIFT 7 // Length of (PART_LEN * 2) in base 2 35 36#endif 37 38#define PART_LEN1 (PART_LEN + 1) // Unique fft coefficients 39#define PART_LEN2 (PART_LEN << 1) // Length of partition * 2 40#define PART_LEN4 (PART_LEN << 2) // Length of partition * 4 41#define FAR_BUF_LEN PART_LEN4 // Length of buffers 42#define MAX_DELAY 100 43 44// Counter parameters 45#ifdef AECM_SHORT 46 47#define CONV_LEN 1024 // Convergence length used at startup 48#else 49 50#define CONV_LEN 512 // Convergence length used at startup 51#endif 52 53#define CONV_LEN2 (CONV_LEN << 1) // Convergence length * 2 used at startup 54// Energy parameters 55#define MAX_BUF_LEN 64 // History length of energy signals 56 57#define FAR_ENERGY_MIN 1025 // Lowest Far energy level: At least 2 in energy 58#define FAR_ENERGY_DIFF 929 // Allowed difference between max and min 59 60#define ENERGY_DEV_OFFSET 0 // The energy error offset in Q8 61#define ENERGY_DEV_TOL 400 // The energy estimation tolerance in Q8 62#define FAR_ENERGY_VAD_REGION 230 // Far VAD tolerance region 63// Stepsize parameters 64#define MU_MIN 10 // Min stepsize 2^-MU_MIN (far end energy dependent) 65#define MU_MAX 1 // Max stepsize 2^-MU_MAX (far end energy dependent) 66#define MU_DIFF 9 // MU_MIN - MU_MAX 67// Channel parameters 68#define MIN_MSE_COUNT 20 // Min number of consecutive blocks with enough far end 69 // energy to compare channel estimates 70#define MIN_MSE_DIFF 29 // The ratio between adapted and stored channel to 71 // accept a new storage (0.8 in Q-MSE_RESOLUTION) 72#define MSE_RESOLUTION 5 // MSE parameter resolution 73#define RESOLUTION_CHANNEL16 12 // W16 Channel in Q-RESOLUTION_CHANNEL16 74#define RESOLUTION_CHANNEL32 28 // W32 Channel in Q-RESOLUTION_CHANNEL 75#define CHANNEL_VAD 16 // Minimum energy in frequency band to update channel 76// Suppression gain parameters: SUPGAIN_ parameters in Q-(RESOLUTION_SUPGAIN) 77#define RESOLUTION_SUPGAIN 8 // Channel in Q-(RESOLUTION_SUPGAIN) 78#define SUPGAIN_DEFAULT (1 << RESOLUTION_SUPGAIN) // Default suppression gain 79#define SUPGAIN_ERROR_PARAM_A 3072 // Estimation error parameter (Maximum gain) (8 in Q8) 80#define SUPGAIN_ERROR_PARAM_B 1536 // Estimation error parameter (Gain before going down) 81#define SUPGAIN_ERROR_PARAM_D SUPGAIN_DEFAULT // Estimation error parameter 82 // (Should be the same as Default) (1 in Q8) 83#define SUPGAIN_EPC_DT 200 // = SUPGAIN_ERROR_PARAM_C * ENERGY_DEV_TOL 84// Defines for "check delay estimation" 85#define CORR_WIDTH 31 // Number of samples to correlate over. 86#define CORR_MAX 16 // Maximum correlation offset 87#define CORR_MAX_BUF 63 88#define CORR_DEV 4 89#define CORR_MAX_LEVEL 20 90#define CORR_MAX_LOW 4 91#define CORR_BUF_LEN (CORR_MAX << 1) + 1 92// Note that CORR_WIDTH + 2*CORR_MAX <= MAX_BUF_LEN 93 94#define ONE_Q14 (1 << 14) 95 96// NLP defines 97#define NLP_COMP_LOW 3277 // 0.2 in Q14 98#define NLP_COMP_HIGH ONE_Q14 // 1 in Q14 99 100extern const WebRtc_Word16 WebRtcAecm_kSqrtHanning[]; 101 102typedef struct { 103 WebRtc_Word16 real; 104 WebRtc_Word16 imag; 105} complex16_t; 106 107typedef struct 108{ 109 int farBufWritePos; 110 int farBufReadPos; 111 int knownDelay; 112 int lastKnownDelay; 113 int firstVAD; // Parameter to control poorly initialized channels 114 115 void *farFrameBuf; 116 void *nearNoisyFrameBuf; 117 void *nearCleanFrameBuf; 118 void *outFrameBuf; 119 120 WebRtc_Word16 farBuf[FAR_BUF_LEN]; 121 122 WebRtc_Word16 mult; 123 WebRtc_UWord32 seed; 124 125 // Delay estimation variables 126 void* delay_estimator; 127 WebRtc_UWord16 currentDelay; 128 // Far end history variables 129 // TODO(bjornv): Replace |far_history| with ring_buffer. 130 uint16_t far_history[PART_LEN1 * MAX_DELAY]; 131 int far_history_pos; 132 int far_q_domains[MAX_DELAY]; 133 134 WebRtc_Word16 nlpFlag; 135 WebRtc_Word16 fixedDelay; 136 137 WebRtc_UWord32 totCount; 138 139 WebRtc_Word16 dfaCleanQDomain; 140 WebRtc_Word16 dfaCleanQDomainOld; 141 WebRtc_Word16 dfaNoisyQDomain; 142 WebRtc_Word16 dfaNoisyQDomainOld; 143 144 WebRtc_Word16 nearLogEnergy[MAX_BUF_LEN]; 145 WebRtc_Word16 farLogEnergy; 146 WebRtc_Word16 echoAdaptLogEnergy[MAX_BUF_LEN]; 147 WebRtc_Word16 echoStoredLogEnergy[MAX_BUF_LEN]; 148 149 // The extra 16 or 32 bytes in the following buffers are for alignment based Neon code. 150 // It's designed this way since the current GCC compiler can't align a buffer in 16 or 32 151 // byte boundaries properly. 152 WebRtc_Word16 channelStored_buf[PART_LEN1 + 8]; 153 WebRtc_Word16 channelAdapt16_buf[PART_LEN1 + 8]; 154 WebRtc_Word32 channelAdapt32_buf[PART_LEN1 + 8]; 155 WebRtc_Word16 xBuf_buf[PART_LEN2 + 16]; // farend 156 WebRtc_Word16 dBufClean_buf[PART_LEN2 + 16]; // nearend 157 WebRtc_Word16 dBufNoisy_buf[PART_LEN2 + 16]; // nearend 158 WebRtc_Word16 outBuf_buf[PART_LEN + 8]; 159 160 // Pointers to the above buffers 161 WebRtc_Word16 *channelStored; 162 WebRtc_Word16 *channelAdapt16; 163 WebRtc_Word32 *channelAdapt32; 164 WebRtc_Word16 *xBuf; 165 WebRtc_Word16 *dBufClean; 166 WebRtc_Word16 *dBufNoisy; 167 WebRtc_Word16 *outBuf; 168 169 WebRtc_Word32 echoFilt[PART_LEN1]; 170 WebRtc_Word16 nearFilt[PART_LEN1]; 171 WebRtc_Word32 noiseEst[PART_LEN1]; 172 int noiseEstTooLowCtr[PART_LEN1]; 173 int noiseEstTooHighCtr[PART_LEN1]; 174 WebRtc_Word16 noiseEstCtr; 175 WebRtc_Word16 cngMode; 176 177 WebRtc_Word32 mseAdaptOld; 178 WebRtc_Word32 mseStoredOld; 179 WebRtc_Word32 mseThreshold; 180 181 WebRtc_Word16 farEnergyMin; 182 WebRtc_Word16 farEnergyMax; 183 WebRtc_Word16 farEnergyMaxMin; 184 WebRtc_Word16 farEnergyVAD; 185 WebRtc_Word16 farEnergyMSE; 186 int currentVADValue; 187 WebRtc_Word16 vadUpdateCount; 188 189 WebRtc_Word16 startupState; 190 WebRtc_Word16 mseChannelCount; 191 WebRtc_Word16 supGain; 192 WebRtc_Word16 supGainOld; 193 194 WebRtc_Word16 supGainErrParamA; 195 WebRtc_Word16 supGainErrParamD; 196 WebRtc_Word16 supGainErrParamDiffAB; 197 WebRtc_Word16 supGainErrParamDiffBD; 198 199#ifdef AEC_DEBUG 200 FILE *farFile; 201 FILE *nearFile; 202 FILE *outFile; 203#endif 204} AecmCore_t; 205 206/////////////////////////////////////////////////////////////////////////////////////////////// 207// WebRtcAecm_CreateCore(...) 208// 209// Allocates the memory needed by the AECM. The memory needs to be 210// initialized separately using the WebRtcAecm_InitCore() function. 211// 212// Input: 213// - aecm : Instance that should be created 214// 215// Output: 216// - aecm : Created instance 217// 218// Return value : 0 - Ok 219// -1 - Error 220// 221int WebRtcAecm_CreateCore(AecmCore_t **aecm); 222 223/////////////////////////////////////////////////////////////////////////////////////////////// 224// WebRtcAecm_InitCore(...) 225// 226// This function initializes the AECM instant created with WebRtcAecm_CreateCore(...) 227// Input: 228// - aecm : Pointer to the AECM instance 229// - samplingFreq : Sampling Frequency 230// 231// Output: 232// - aecm : Initialized instance 233// 234// Return value : 0 - Ok 235// -1 - Error 236// 237int WebRtcAecm_InitCore(AecmCore_t * const aecm, int samplingFreq); 238 239/////////////////////////////////////////////////////////////////////////////////////////////// 240// WebRtcAecm_FreeCore(...) 241// 242// This function releases the memory allocated by WebRtcAecm_CreateCore() 243// Input: 244// - aecm : Pointer to the AECM instance 245// 246// Return value : 0 - Ok 247// -1 - Error 248// 11001-11016: Error 249// 250int WebRtcAecm_FreeCore(AecmCore_t *aecm); 251 252int WebRtcAecm_Control(AecmCore_t *aecm, int delay, int nlpFlag); 253 254/////////////////////////////////////////////////////////////////////////////////////////////// 255// WebRtcAecm_InitEchoPathCore(...) 256// 257// This function resets the echo channel adaptation with the specified channel. 258// Input: 259// - aecm : Pointer to the AECM instance 260// - echo_path : Pointer to the data that should initialize the echo path 261// 262// Output: 263// - aecm : Initialized instance 264// 265void WebRtcAecm_InitEchoPathCore(AecmCore_t* aecm, const WebRtc_Word16* echo_path); 266 267/////////////////////////////////////////////////////////////////////////////////////////////// 268// WebRtcAecm_ProcessFrame(...) 269// 270// This function processes frames and sends blocks to WebRtcAecm_ProcessBlock(...) 271// 272// Inputs: 273// - aecm : Pointer to the AECM instance 274// - farend : In buffer containing one frame of echo signal 275// - nearendNoisy : In buffer containing one frame of nearend+echo signal without NS 276// - nearendClean : In buffer containing one frame of nearend+echo signal with NS 277// 278// Output: 279// - out : Out buffer, one frame of nearend signal : 280// 281// 282int WebRtcAecm_ProcessFrame(AecmCore_t * aecm, const WebRtc_Word16 * farend, 283 const WebRtc_Word16 * nearendNoisy, 284 const WebRtc_Word16 * nearendClean, 285 WebRtc_Word16 * out); 286 287/////////////////////////////////////////////////////////////////////////////////////////////// 288// WebRtcAecm_ProcessBlock(...) 289// 290// This function is called for every block within one frame 291// This function is called by WebRtcAecm_ProcessFrame(...) 292// 293// Inputs: 294// - aecm : Pointer to the AECM instance 295// - farend : In buffer containing one block of echo signal 296// - nearendNoisy : In buffer containing one frame of nearend+echo signal without NS 297// - nearendClean : In buffer containing one frame of nearend+echo signal with NS 298// 299// Output: 300// - out : Out buffer, one block of nearend signal : 301// 302// 303int WebRtcAecm_ProcessBlock(AecmCore_t * aecm, const WebRtc_Word16 * farend, 304 const WebRtc_Word16 * nearendNoisy, 305 const WebRtc_Word16 * noisyClean, 306 WebRtc_Word16 * out); 307 308/////////////////////////////////////////////////////////////////////////////////////////////// 309// WebRtcAecm_BufferFarFrame() 310// 311// Inserts a frame of data into farend buffer. 312// 313// Inputs: 314// - aecm : Pointer to the AECM instance 315// - farend : In buffer containing one frame of farend signal 316// - farLen : Length of frame 317// 318void WebRtcAecm_BufferFarFrame(AecmCore_t * const aecm, const WebRtc_Word16 * const farend, 319 const int farLen); 320 321/////////////////////////////////////////////////////////////////////////////////////////////// 322// WebRtcAecm_FetchFarFrame() 323// 324// Read the farend buffer to account for known delay 325// 326// Inputs: 327// - aecm : Pointer to the AECM instance 328// - farend : In buffer containing one frame of farend signal 329// - farLen : Length of frame 330// - knownDelay : known delay 331// 332void WebRtcAecm_FetchFarFrame(AecmCore_t * const aecm, WebRtc_Word16 * const farend, 333 const int farLen, const int knownDelay); 334 335/////////////////////////////////////////////////////////////////////////////// 336// Some function pointers, for internal functions shared by ARM NEON and 337// generic C code. 338// 339typedef void (*CalcLinearEnergies)( 340 AecmCore_t* aecm, 341 const WebRtc_UWord16* far_spectrum, 342 WebRtc_Word32* echoEst, 343 WebRtc_UWord32* far_energy, 344 WebRtc_UWord32* echo_energy_adapt, 345 WebRtc_UWord32* echo_energy_stored); 346extern CalcLinearEnergies WebRtcAecm_CalcLinearEnergies; 347 348typedef void (*StoreAdaptiveChannel)( 349 AecmCore_t* aecm, 350 const WebRtc_UWord16* far_spectrum, 351 WebRtc_Word32* echo_est); 352extern StoreAdaptiveChannel WebRtcAecm_StoreAdaptiveChannel; 353 354typedef void (*ResetAdaptiveChannel)(AecmCore_t* aecm); 355extern ResetAdaptiveChannel WebRtcAecm_ResetAdaptiveChannel; 356 357typedef void (*WindowAndFFT)( 358 WebRtc_Word16* fft, 359 const WebRtc_Word16* time_signal, 360 complex16_t* freq_signal, 361 int time_signal_scaling); 362extern WindowAndFFT WebRtcAecm_WindowAndFFT; 363 364typedef void (*InverseFFTAndWindow)( 365 AecmCore_t* aecm, 366 WebRtc_Word16* fft, complex16_t* efw, 367 WebRtc_Word16* output, 368 const WebRtc_Word16* nearendClean); 369extern InverseFFTAndWindow WebRtcAecm_InverseFFTAndWindow; 370 371// Initialization of the above function pointers for ARM Neon. 372void WebRtcAecm_InitNeon(void); 373 374 375#endif 376