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 #include "webrtc/modules/audio_processing/aecm/aecm_core.h" 12 13 #include <assert.h> 14 #include <stddef.h> 15 #include <stdlib.h> 16 17 #include "webrtc/common_audio/signal_processing/include/real_fft.h" 18 #include "webrtc/modules/audio_processing/aecm/include/echo_control_mobile.h" 19 #include "webrtc/modules/audio_processing/utility/delay_estimator_wrapper.h" 20 #include "webrtc/modules/audio_processing/utility/ring_buffer.h" 21 #include "webrtc/system_wrappers/interface/compile_assert_c.h" 22 #include "webrtc/system_wrappers/interface/cpu_features_wrapper.h" 23 #include "webrtc/typedefs.h" 24 25 #ifdef AEC_DEBUG 26 FILE *dfile; 27 FILE *testfile; 28 #endif 29 30 const int16_t WebRtcAecm_kCosTable[] = { 31 8192, 8190, 8187, 8180, 8172, 8160, 8147, 8130, 8112, 32 8091, 8067, 8041, 8012, 7982, 7948, 7912, 7874, 7834, 33 7791, 7745, 7697, 7647, 7595, 7540, 7483, 7424, 7362, 34 7299, 7233, 7164, 7094, 7021, 6947, 6870, 6791, 6710, 35 6627, 6542, 6455, 6366, 6275, 6182, 6087, 5991, 5892, 36 5792, 5690, 5586, 5481, 5374, 5265, 5155, 5043, 4930, 37 4815, 4698, 4580, 4461, 4341, 4219, 4096, 3971, 3845, 38 3719, 3591, 3462, 3331, 3200, 3068, 2935, 2801, 2667, 39 2531, 2395, 2258, 2120, 1981, 1842, 1703, 1563, 1422, 40 1281, 1140, 998, 856, 713, 571, 428, 285, 142, 41 0, -142, -285, -428, -571, -713, -856, -998, -1140, 42 -1281, -1422, -1563, -1703, -1842, -1981, -2120, -2258, -2395, 43 -2531, -2667, -2801, -2935, -3068, -3200, -3331, -3462, -3591, 44 -3719, -3845, -3971, -4095, -4219, -4341, -4461, -4580, -4698, 45 -4815, -4930, -5043, -5155, -5265, -5374, -5481, -5586, -5690, 46 -5792, -5892, -5991, -6087, -6182, -6275, -6366, -6455, -6542, 47 -6627, -6710, -6791, -6870, -6947, -7021, -7094, -7164, -7233, 48 -7299, -7362, -7424, -7483, -7540, -7595, -7647, -7697, -7745, 49 -7791, -7834, -7874, -7912, -7948, -7982, -8012, -8041, -8067, 50 -8091, -8112, -8130, -8147, -8160, -8172, -8180, -8187, -8190, 51 -8191, -8190, -8187, -8180, -8172, -8160, -8147, -8130, -8112, 52 -8091, -8067, -8041, -8012, -7982, -7948, -7912, -7874, -7834, 53 -7791, -7745, -7697, -7647, -7595, -7540, -7483, -7424, -7362, 54 -7299, -7233, -7164, -7094, -7021, -6947, -6870, -6791, -6710, 55 -6627, -6542, -6455, -6366, -6275, -6182, -6087, -5991, -5892, 56 -5792, -5690, -5586, -5481, -5374, -5265, -5155, -5043, -4930, 57 -4815, -4698, -4580, -4461, -4341, -4219, -4096, -3971, -3845, 58 -3719, -3591, -3462, -3331, -3200, -3068, -2935, -2801, -2667, 59 -2531, -2395, -2258, -2120, -1981, -1842, -1703, -1563, -1422, 60 -1281, -1140, -998, -856, -713, -571, -428, -285, -142, 61 0, 142, 285, 428, 571, 713, 856, 998, 1140, 62 1281, 1422, 1563, 1703, 1842, 1981, 2120, 2258, 2395, 63 2531, 2667, 2801, 2935, 3068, 3200, 3331, 3462, 3591, 64 3719, 3845, 3971, 4095, 4219, 4341, 4461, 4580, 4698, 65 4815, 4930, 5043, 5155, 5265, 5374, 5481, 5586, 5690, 66 5792, 5892, 5991, 6087, 6182, 6275, 6366, 6455, 6542, 67 6627, 6710, 6791, 6870, 6947, 7021, 7094, 7164, 7233, 68 7299, 7362, 7424, 7483, 7540, 7595, 7647, 7697, 7745, 69 7791, 7834, 7874, 7912, 7948, 7982, 8012, 8041, 8067, 70 8091, 8112, 8130, 8147, 8160, 8172, 8180, 8187, 8190 71 }; 72 73 const int16_t WebRtcAecm_kSinTable[] = { 74 0, 142, 285, 428, 571, 713, 856, 998, 75 1140, 1281, 1422, 1563, 1703, 1842, 1981, 2120, 76 2258, 2395, 2531, 2667, 2801, 2935, 3068, 3200, 77 3331, 3462, 3591, 3719, 3845, 3971, 4095, 4219, 78 4341, 4461, 4580, 4698, 4815, 4930, 5043, 5155, 79 5265, 5374, 5481, 5586, 5690, 5792, 5892, 5991, 80 6087, 6182, 6275, 6366, 6455, 6542, 6627, 6710, 81 6791, 6870, 6947, 7021, 7094, 7164, 7233, 7299, 82 7362, 7424, 7483, 7540, 7595, 7647, 7697, 7745, 83 7791, 7834, 7874, 7912, 7948, 7982, 8012, 8041, 84 8067, 8091, 8112, 8130, 8147, 8160, 8172, 8180, 85 8187, 8190, 8191, 8190, 8187, 8180, 8172, 8160, 86 8147, 8130, 8112, 8091, 8067, 8041, 8012, 7982, 87 7948, 7912, 7874, 7834, 7791, 7745, 7697, 7647, 88 7595, 7540, 7483, 7424, 7362, 7299, 7233, 7164, 89 7094, 7021, 6947, 6870, 6791, 6710, 6627, 6542, 90 6455, 6366, 6275, 6182, 6087, 5991, 5892, 5792, 91 5690, 5586, 5481, 5374, 5265, 5155, 5043, 4930, 92 4815, 4698, 4580, 4461, 4341, 4219, 4096, 3971, 93 3845, 3719, 3591, 3462, 3331, 3200, 3068, 2935, 94 2801, 2667, 2531, 2395, 2258, 2120, 1981, 1842, 95 1703, 1563, 1422, 1281, 1140, 998, 856, 713, 96 571, 428, 285, 142, 0, -142, -285, -428, 97 -571, -713, -856, -998, -1140, -1281, -1422, -1563, 98 -1703, -1842, -1981, -2120, -2258, -2395, -2531, -2667, 99 -2801, -2935, -3068, -3200, -3331, -3462, -3591, -3719, 100 -3845, -3971, -4095, -4219, -4341, -4461, -4580, -4698, 101 -4815, -4930, -5043, -5155, -5265, -5374, -5481, -5586, 102 -5690, -5792, -5892, -5991, -6087, -6182, -6275, -6366, 103 -6455, -6542, -6627, -6710, -6791, -6870, -6947, -7021, 104 -7094, -7164, -7233, -7299, -7362, -7424, -7483, -7540, 105 -7595, -7647, -7697, -7745, -7791, -7834, -7874, -7912, 106 -7948, -7982, -8012, -8041, -8067, -8091, -8112, -8130, 107 -8147, -8160, -8172, -8180, -8187, -8190, -8191, -8190, 108 -8187, -8180, -8172, -8160, -8147, -8130, -8112, -8091, 109 -8067, -8041, -8012, -7982, -7948, -7912, -7874, -7834, 110 -7791, -7745, -7697, -7647, -7595, -7540, -7483, -7424, 111 -7362, -7299, -7233, -7164, -7094, -7021, -6947, -6870, 112 -6791, -6710, -6627, -6542, -6455, -6366, -6275, -6182, 113 -6087, -5991, -5892, -5792, -5690, -5586, -5481, -5374, 114 -5265, -5155, -5043, -4930, -4815, -4698, -4580, -4461, 115 -4341, -4219, -4096, -3971, -3845, -3719, -3591, -3462, 116 -3331, -3200, -3068, -2935, -2801, -2667, -2531, -2395, 117 -2258, -2120, -1981, -1842, -1703, -1563, -1422, -1281, 118 -1140, -998, -856, -713, -571, -428, -285, -142 119 }; 120 121 // Initialization table for echo channel in 8 kHz 122 static const int16_t kChannelStored8kHz[PART_LEN1] = { 123 2040, 1815, 1590, 1498, 1405, 1395, 1385, 1418, 124 1451, 1506, 1562, 1644, 1726, 1804, 1882, 1918, 125 1953, 1982, 2010, 2025, 2040, 2034, 2027, 2021, 126 2014, 1997, 1980, 1925, 1869, 1800, 1732, 1683, 127 1635, 1604, 1572, 1545, 1517, 1481, 1444, 1405, 128 1367, 1331, 1294, 1270, 1245, 1239, 1233, 1247, 129 1260, 1282, 1303, 1338, 1373, 1407, 1441, 1470, 130 1499, 1524, 1549, 1565, 1582, 1601, 1621, 1649, 131 1676 132 }; 133 134 // Initialization table for echo channel in 16 kHz 135 static const int16_t kChannelStored16kHz[PART_LEN1] = { 136 2040, 1590, 1405, 1385, 1451, 1562, 1726, 1882, 137 1953, 2010, 2040, 2027, 2014, 1980, 1869, 1732, 138 1635, 1572, 1517, 1444, 1367, 1294, 1245, 1233, 139 1260, 1303, 1373, 1441, 1499, 1549, 1582, 1621, 140 1676, 1741, 1802, 1861, 1921, 1983, 2040, 2102, 141 2170, 2265, 2375, 2515, 2651, 2781, 2922, 3075, 142 3253, 3471, 3738, 3976, 4151, 4258, 4308, 4288, 143 4270, 4253, 4237, 4179, 4086, 3947, 3757, 3484, 144 3153 145 }; 146 147 // Moves the pointer to the next entry and inserts |far_spectrum| and 148 // corresponding Q-domain in its buffer. 149 // 150 // Inputs: 151 // - self : Pointer to the delay estimation instance 152 // - far_spectrum : Pointer to the far end spectrum 153 // - far_q : Q-domain of far end spectrum 154 // 155 void WebRtcAecm_UpdateFarHistory(AecmCore_t* self, 156 uint16_t* far_spectrum, 157 int far_q) { 158 // Get new buffer position 159 self->far_history_pos++; 160 if (self->far_history_pos >= MAX_DELAY) { 161 self->far_history_pos = 0; 162 } 163 // Update Q-domain buffer 164 self->far_q_domains[self->far_history_pos] = far_q; 165 // Update far end spectrum buffer 166 memcpy(&(self->far_history[self->far_history_pos * PART_LEN1]), 167 far_spectrum, 168 sizeof(uint16_t) * PART_LEN1); 169 } 170 171 // Returns a pointer to the far end spectrum aligned to current near end 172 // spectrum. The function WebRtc_DelayEstimatorProcessFix(...) should have been 173 // called before AlignedFarend(...). Otherwise, you get the pointer to the 174 // previous frame. The memory is only valid until the next call of 175 // WebRtc_DelayEstimatorProcessFix(...). 176 // 177 // Inputs: 178 // - self : Pointer to the AECM instance. 179 // - delay : Current delay estimate. 180 // 181 // Output: 182 // - far_q : The Q-domain of the aligned far end spectrum 183 // 184 // Return value: 185 // - far_spectrum : Pointer to the aligned far end spectrum 186 // NULL - Error 187 // 188 const uint16_t* WebRtcAecm_AlignedFarend(AecmCore_t* self, 189 int* far_q, 190 int delay) { 191 int buffer_position = 0; 192 assert(self != NULL); 193 buffer_position = self->far_history_pos - delay; 194 195 // Check buffer position 196 if (buffer_position < 0) { 197 buffer_position += MAX_DELAY; 198 } 199 // Get Q-domain 200 *far_q = self->far_q_domains[buffer_position]; 201 // Return far end spectrum 202 return &(self->far_history[buffer_position * PART_LEN1]); 203 } 204 205 // Declare function pointers. 206 CalcLinearEnergies WebRtcAecm_CalcLinearEnergies; 207 StoreAdaptiveChannel WebRtcAecm_StoreAdaptiveChannel; 208 ResetAdaptiveChannel WebRtcAecm_ResetAdaptiveChannel; 209 210 int WebRtcAecm_CreateCore(AecmCore_t **aecmInst) 211 { 212 AecmCore_t *aecm = malloc(sizeof(AecmCore_t)); 213 *aecmInst = aecm; 214 if (aecm == NULL) 215 { 216 return -1; 217 } 218 219 aecm->farFrameBuf = WebRtc_CreateBuffer(FRAME_LEN + PART_LEN, 220 sizeof(int16_t)); 221 if (!aecm->farFrameBuf) 222 { 223 WebRtcAecm_FreeCore(aecm); 224 aecm = NULL; 225 return -1; 226 } 227 228 aecm->nearNoisyFrameBuf = WebRtc_CreateBuffer(FRAME_LEN + PART_LEN, 229 sizeof(int16_t)); 230 if (!aecm->nearNoisyFrameBuf) 231 { 232 WebRtcAecm_FreeCore(aecm); 233 aecm = NULL; 234 return -1; 235 } 236 237 aecm->nearCleanFrameBuf = WebRtc_CreateBuffer(FRAME_LEN + PART_LEN, 238 sizeof(int16_t)); 239 if (!aecm->nearCleanFrameBuf) 240 { 241 WebRtcAecm_FreeCore(aecm); 242 aecm = NULL; 243 return -1; 244 } 245 246 aecm->outFrameBuf = WebRtc_CreateBuffer(FRAME_LEN + PART_LEN, 247 sizeof(int16_t)); 248 if (!aecm->outFrameBuf) 249 { 250 WebRtcAecm_FreeCore(aecm); 251 aecm = NULL; 252 return -1; 253 } 254 255 aecm->delay_estimator_farend = WebRtc_CreateDelayEstimatorFarend(PART_LEN1, 256 MAX_DELAY); 257 if (aecm->delay_estimator_farend == NULL) { 258 WebRtcAecm_FreeCore(aecm); 259 aecm = NULL; 260 return -1; 261 } 262 aecm->delay_estimator = 263 WebRtc_CreateDelayEstimator(aecm->delay_estimator_farend, 0); 264 if (aecm->delay_estimator == NULL) { 265 WebRtcAecm_FreeCore(aecm); 266 aecm = NULL; 267 return -1; 268 } 269 // TODO(bjornv): Explicitly disable robust delay validation until no 270 // performance regression has been established. Then remove the line. 271 WebRtc_enable_robust_validation(aecm->delay_estimator, 0); 272 273 aecm->real_fft = WebRtcSpl_CreateRealFFT(PART_LEN_SHIFT); 274 if (aecm->real_fft == NULL) { 275 WebRtcAecm_FreeCore(aecm); 276 aecm = NULL; 277 return -1; 278 } 279 280 // Init some aecm pointers. 16 and 32 byte alignment is only necessary 281 // for Neon code currently. 282 aecm->xBuf = (int16_t*) (((uintptr_t)aecm->xBuf_buf + 31) & ~ 31); 283 aecm->dBufClean = (int16_t*) (((uintptr_t)aecm->dBufClean_buf + 31) & ~ 31); 284 aecm->dBufNoisy = (int16_t*) (((uintptr_t)aecm->dBufNoisy_buf + 31) & ~ 31); 285 aecm->outBuf = (int16_t*) (((uintptr_t)aecm->outBuf_buf + 15) & ~ 15); 286 aecm->channelStored = (int16_t*) (((uintptr_t) 287 aecm->channelStored_buf + 15) & ~ 15); 288 aecm->channelAdapt16 = (int16_t*) (((uintptr_t) 289 aecm->channelAdapt16_buf + 15) & ~ 15); 290 aecm->channelAdapt32 = (int32_t*) (((uintptr_t) 291 aecm->channelAdapt32_buf + 31) & ~ 31); 292 293 return 0; 294 } 295 296 void WebRtcAecm_InitEchoPathCore(AecmCore_t* aecm, const int16_t* echo_path) 297 { 298 int i = 0; 299 300 // Reset the stored channel 301 memcpy(aecm->channelStored, echo_path, sizeof(int16_t) * PART_LEN1); 302 // Reset the adapted channels 303 memcpy(aecm->channelAdapt16, echo_path, sizeof(int16_t) * PART_LEN1); 304 for (i = 0; i < PART_LEN1; i++) 305 { 306 aecm->channelAdapt32[i] = WEBRTC_SPL_LSHIFT_W32( 307 (int32_t)(aecm->channelAdapt16[i]), 16); 308 } 309 310 // Reset channel storing variables 311 aecm->mseAdaptOld = 1000; 312 aecm->mseStoredOld = 1000; 313 aecm->mseThreshold = WEBRTC_SPL_WORD32_MAX; 314 aecm->mseChannelCount = 0; 315 } 316 317 static void CalcLinearEnergiesC(AecmCore_t* aecm, 318 const uint16_t* far_spectrum, 319 int32_t* echo_est, 320 uint32_t* far_energy, 321 uint32_t* echo_energy_adapt, 322 uint32_t* echo_energy_stored) 323 { 324 int i; 325 326 // Get energy for the delayed far end signal and estimated 327 // echo using both stored and adapted channels. 328 for (i = 0; i < PART_LEN1; i++) 329 { 330 echo_est[i] = WEBRTC_SPL_MUL_16_U16(aecm->channelStored[i], 331 far_spectrum[i]); 332 (*far_energy) += (uint32_t)(far_spectrum[i]); 333 (*echo_energy_adapt) += WEBRTC_SPL_UMUL_16_16(aecm->channelAdapt16[i], 334 far_spectrum[i]); 335 (*echo_energy_stored) += (uint32_t)echo_est[i]; 336 } 337 } 338 339 static void StoreAdaptiveChannelC(AecmCore_t* aecm, 340 const uint16_t* far_spectrum, 341 int32_t* echo_est) 342 { 343 int i; 344 345 // During startup we store the channel every block. 346 memcpy(aecm->channelStored, aecm->channelAdapt16, sizeof(int16_t) * PART_LEN1); 347 // Recalculate echo estimate 348 for (i = 0; i < PART_LEN; i += 4) 349 { 350 echo_est[i] = WEBRTC_SPL_MUL_16_U16(aecm->channelStored[i], 351 far_spectrum[i]); 352 echo_est[i + 1] = WEBRTC_SPL_MUL_16_U16(aecm->channelStored[i + 1], 353 far_spectrum[i + 1]); 354 echo_est[i + 2] = WEBRTC_SPL_MUL_16_U16(aecm->channelStored[i + 2], 355 far_spectrum[i + 2]); 356 echo_est[i + 3] = WEBRTC_SPL_MUL_16_U16(aecm->channelStored[i + 3], 357 far_spectrum[i + 3]); 358 } 359 echo_est[i] = WEBRTC_SPL_MUL_16_U16(aecm->channelStored[i], 360 far_spectrum[i]); 361 } 362 363 static void ResetAdaptiveChannelC(AecmCore_t* aecm) 364 { 365 int i; 366 367 // The stored channel has a significantly lower MSE than the adaptive one for 368 // two consecutive calculations. Reset the adaptive channel. 369 memcpy(aecm->channelAdapt16, aecm->channelStored, 370 sizeof(int16_t) * PART_LEN1); 371 // Restore the W32 channel 372 for (i = 0; i < PART_LEN; i += 4) 373 { 374 aecm->channelAdapt32[i] = WEBRTC_SPL_LSHIFT_W32( 375 (int32_t)aecm->channelStored[i], 16); 376 aecm->channelAdapt32[i + 1] = WEBRTC_SPL_LSHIFT_W32( 377 (int32_t)aecm->channelStored[i + 1], 16); 378 aecm->channelAdapt32[i + 2] = WEBRTC_SPL_LSHIFT_W32( 379 (int32_t)aecm->channelStored[i + 2], 16); 380 aecm->channelAdapt32[i + 3] = WEBRTC_SPL_LSHIFT_W32( 381 (int32_t)aecm->channelStored[i + 3], 16); 382 } 383 aecm->channelAdapt32[i] = WEBRTC_SPL_LSHIFT_W32((int32_t)aecm->channelStored[i], 16); 384 } 385 386 // Initialize function pointers for ARM Neon platform. 387 #if (defined WEBRTC_DETECT_ARM_NEON || defined WEBRTC_ARCH_ARM_NEON) 388 static void WebRtcAecm_InitNeon(void) 389 { 390 WebRtcAecm_StoreAdaptiveChannel = WebRtcAecm_StoreAdaptiveChannelNeon; 391 WebRtcAecm_ResetAdaptiveChannel = WebRtcAecm_ResetAdaptiveChannelNeon; 392 WebRtcAecm_CalcLinearEnergies = WebRtcAecm_CalcLinearEnergiesNeon; 393 } 394 #endif 395 396 // Initialize function pointers for MIPS platform. 397 #if defined(MIPS32_LE) 398 static void WebRtcAecm_InitMips(void) 399 { 400 #if defined(MIPS_DSP_R1_LE) 401 WebRtcAecm_StoreAdaptiveChannel = WebRtcAecm_StoreAdaptiveChannel_mips; 402 WebRtcAecm_ResetAdaptiveChannel = WebRtcAecm_ResetAdaptiveChannel_mips; 403 #endif 404 WebRtcAecm_CalcLinearEnergies = WebRtcAecm_CalcLinearEnergies_mips; 405 } 406 #endif 407 408 // WebRtcAecm_InitCore(...) 409 // 410 // This function initializes the AECM instant created with WebRtcAecm_CreateCore(...) 411 // Input: 412 // - aecm : Pointer to the Echo Suppression instance 413 // - samplingFreq : Sampling Frequency 414 // 415 // Output: 416 // - aecm : Initialized instance 417 // 418 // Return value : 0 - Ok 419 // -1 - Error 420 // 421 int WebRtcAecm_InitCore(AecmCore_t * const aecm, int samplingFreq) 422 { 423 int i = 0; 424 int32_t tmp32 = PART_LEN1 * PART_LEN1; 425 int16_t tmp16 = PART_LEN1; 426 427 if (samplingFreq != 8000 && samplingFreq != 16000) 428 { 429 samplingFreq = 8000; 430 return -1; 431 } 432 // sanity check of sampling frequency 433 aecm->mult = (int16_t)samplingFreq / 8000; 434 435 aecm->farBufWritePos = 0; 436 aecm->farBufReadPos = 0; 437 aecm->knownDelay = 0; 438 aecm->lastKnownDelay = 0; 439 440 WebRtc_InitBuffer(aecm->farFrameBuf); 441 WebRtc_InitBuffer(aecm->nearNoisyFrameBuf); 442 WebRtc_InitBuffer(aecm->nearCleanFrameBuf); 443 WebRtc_InitBuffer(aecm->outFrameBuf); 444 445 memset(aecm->xBuf_buf, 0, sizeof(aecm->xBuf_buf)); 446 memset(aecm->dBufClean_buf, 0, sizeof(aecm->dBufClean_buf)); 447 memset(aecm->dBufNoisy_buf, 0, sizeof(aecm->dBufNoisy_buf)); 448 memset(aecm->outBuf_buf, 0, sizeof(aecm->outBuf_buf)); 449 450 aecm->seed = 666; 451 aecm->totCount = 0; 452 453 if (WebRtc_InitDelayEstimatorFarend(aecm->delay_estimator_farend) != 0) { 454 return -1; 455 } 456 if (WebRtc_InitDelayEstimator(aecm->delay_estimator) != 0) { 457 return -1; 458 } 459 // Set far end histories to zero 460 memset(aecm->far_history, 0, sizeof(uint16_t) * PART_LEN1 * MAX_DELAY); 461 memset(aecm->far_q_domains, 0, sizeof(int) * MAX_DELAY); 462 aecm->far_history_pos = MAX_DELAY; 463 464 aecm->nlpFlag = 1; 465 aecm->fixedDelay = -1; 466 467 aecm->dfaCleanQDomain = 0; 468 aecm->dfaCleanQDomainOld = 0; 469 aecm->dfaNoisyQDomain = 0; 470 aecm->dfaNoisyQDomainOld = 0; 471 472 memset(aecm->nearLogEnergy, 0, sizeof(aecm->nearLogEnergy)); 473 aecm->farLogEnergy = 0; 474 memset(aecm->echoAdaptLogEnergy, 0, sizeof(aecm->echoAdaptLogEnergy)); 475 memset(aecm->echoStoredLogEnergy, 0, sizeof(aecm->echoStoredLogEnergy)); 476 477 // Initialize the echo channels with a stored shape. 478 if (samplingFreq == 8000) 479 { 480 WebRtcAecm_InitEchoPathCore(aecm, kChannelStored8kHz); 481 } 482 else 483 { 484 WebRtcAecm_InitEchoPathCore(aecm, kChannelStored16kHz); 485 } 486 487 memset(aecm->echoFilt, 0, sizeof(aecm->echoFilt)); 488 memset(aecm->nearFilt, 0, sizeof(aecm->nearFilt)); 489 aecm->noiseEstCtr = 0; 490 491 aecm->cngMode = AecmTrue; 492 493 memset(aecm->noiseEstTooLowCtr, 0, sizeof(aecm->noiseEstTooLowCtr)); 494 memset(aecm->noiseEstTooHighCtr, 0, sizeof(aecm->noiseEstTooHighCtr)); 495 // Shape the initial noise level to an approximate pink noise. 496 for (i = 0; i < (PART_LEN1 >> 1) - 1; i++) 497 { 498 aecm->noiseEst[i] = (tmp32 << 8); 499 tmp16--; 500 tmp32 -= (int32_t)((tmp16 << 1) + 1); 501 } 502 for (; i < PART_LEN1; i++) 503 { 504 aecm->noiseEst[i] = (tmp32 << 8); 505 } 506 507 aecm->farEnergyMin = WEBRTC_SPL_WORD16_MAX; 508 aecm->farEnergyMax = WEBRTC_SPL_WORD16_MIN; 509 aecm->farEnergyMaxMin = 0; 510 aecm->farEnergyVAD = FAR_ENERGY_MIN; // This prevents false speech detection at the 511 // beginning. 512 aecm->farEnergyMSE = 0; 513 aecm->currentVADValue = 0; 514 aecm->vadUpdateCount = 0; 515 aecm->firstVAD = 1; 516 517 aecm->startupState = 0; 518 aecm->supGain = SUPGAIN_DEFAULT; 519 aecm->supGainOld = SUPGAIN_DEFAULT; 520 521 aecm->supGainErrParamA = SUPGAIN_ERROR_PARAM_A; 522 aecm->supGainErrParamD = SUPGAIN_ERROR_PARAM_D; 523 aecm->supGainErrParamDiffAB = SUPGAIN_ERROR_PARAM_A - SUPGAIN_ERROR_PARAM_B; 524 aecm->supGainErrParamDiffBD = SUPGAIN_ERROR_PARAM_B - SUPGAIN_ERROR_PARAM_D; 525 526 // Assert a preprocessor definition at compile-time. It's an assumption 527 // used in assembly code, so check the assembly files before any change. 528 COMPILE_ASSERT(PART_LEN % 16 == 0); 529 530 // Initialize function pointers. 531 WebRtcAecm_CalcLinearEnergies = CalcLinearEnergiesC; 532 WebRtcAecm_StoreAdaptiveChannel = StoreAdaptiveChannelC; 533 WebRtcAecm_ResetAdaptiveChannel = ResetAdaptiveChannelC; 534 535 #ifdef WEBRTC_DETECT_ARM_NEON 536 uint64_t features = WebRtc_GetCPUFeaturesARM(); 537 if ((features & kCPUFeatureNEON) != 0) 538 { 539 WebRtcAecm_InitNeon(); 540 } 541 #elif defined(WEBRTC_ARCH_ARM_NEON) 542 WebRtcAecm_InitNeon(); 543 #endif 544 545 #if defined(MIPS32_LE) 546 WebRtcAecm_InitMips(); 547 #endif 548 return 0; 549 } 550 551 // TODO(bjornv): This function is currently not used. Add support for these 552 // parameters from a higher level 553 int WebRtcAecm_Control(AecmCore_t *aecm, int delay, int nlpFlag) 554 { 555 aecm->nlpFlag = nlpFlag; 556 aecm->fixedDelay = delay; 557 558 return 0; 559 } 560 561 int WebRtcAecm_FreeCore(AecmCore_t *aecm) 562 { 563 if (aecm == NULL) 564 { 565 return -1; 566 } 567 568 WebRtc_FreeBuffer(aecm->farFrameBuf); 569 WebRtc_FreeBuffer(aecm->nearNoisyFrameBuf); 570 WebRtc_FreeBuffer(aecm->nearCleanFrameBuf); 571 WebRtc_FreeBuffer(aecm->outFrameBuf); 572 573 WebRtc_FreeDelayEstimator(aecm->delay_estimator); 574 WebRtc_FreeDelayEstimatorFarend(aecm->delay_estimator_farend); 575 WebRtcSpl_FreeRealFFT(aecm->real_fft); 576 577 free(aecm); 578 579 return 0; 580 } 581 582 int WebRtcAecm_ProcessFrame(AecmCore_t * aecm, 583 const int16_t * farend, 584 const int16_t * nearendNoisy, 585 const int16_t * nearendClean, 586 int16_t * out) 587 { 588 int16_t outBlock_buf[PART_LEN + 8]; // Align buffer to 8-byte boundary. 589 int16_t* outBlock = (int16_t*) (((uintptr_t) outBlock_buf + 15) & ~ 15); 590 591 int16_t farFrame[FRAME_LEN]; 592 const int16_t* out_ptr = NULL; 593 int size = 0; 594 595 // Buffer the current frame. 596 // Fetch an older one corresponding to the delay. 597 WebRtcAecm_BufferFarFrame(aecm, farend, FRAME_LEN); 598 WebRtcAecm_FetchFarFrame(aecm, farFrame, FRAME_LEN, aecm->knownDelay); 599 600 // Buffer the synchronized far and near frames, 601 // to pass the smaller blocks individually. 602 WebRtc_WriteBuffer(aecm->farFrameBuf, farFrame, FRAME_LEN); 603 WebRtc_WriteBuffer(aecm->nearNoisyFrameBuf, nearendNoisy, FRAME_LEN); 604 if (nearendClean != NULL) 605 { 606 WebRtc_WriteBuffer(aecm->nearCleanFrameBuf, nearendClean, FRAME_LEN); 607 } 608 609 // Process as many blocks as possible. 610 while (WebRtc_available_read(aecm->farFrameBuf) >= PART_LEN) 611 { 612 int16_t far_block[PART_LEN]; 613 const int16_t* far_block_ptr = NULL; 614 int16_t near_noisy_block[PART_LEN]; 615 const int16_t* near_noisy_block_ptr = NULL; 616 617 WebRtc_ReadBuffer(aecm->farFrameBuf, (void**) &far_block_ptr, far_block, 618 PART_LEN); 619 WebRtc_ReadBuffer(aecm->nearNoisyFrameBuf, 620 (void**) &near_noisy_block_ptr, 621 near_noisy_block, 622 PART_LEN); 623 if (nearendClean != NULL) 624 { 625 int16_t near_clean_block[PART_LEN]; 626 const int16_t* near_clean_block_ptr = NULL; 627 628 WebRtc_ReadBuffer(aecm->nearCleanFrameBuf, 629 (void**) &near_clean_block_ptr, 630 near_clean_block, 631 PART_LEN); 632 if (WebRtcAecm_ProcessBlock(aecm, 633 far_block_ptr, 634 near_noisy_block_ptr, 635 near_clean_block_ptr, 636 outBlock) == -1) 637 { 638 return -1; 639 } 640 } else 641 { 642 if (WebRtcAecm_ProcessBlock(aecm, 643 far_block_ptr, 644 near_noisy_block_ptr, 645 NULL, 646 outBlock) == -1) 647 { 648 return -1; 649 } 650 } 651 652 WebRtc_WriteBuffer(aecm->outFrameBuf, outBlock, PART_LEN); 653 } 654 655 // Stuff the out buffer if we have less than a frame to output. 656 // This should only happen for the first frame. 657 size = (int) WebRtc_available_read(aecm->outFrameBuf); 658 if (size < FRAME_LEN) 659 { 660 WebRtc_MoveReadPtr(aecm->outFrameBuf, size - FRAME_LEN); 661 } 662 663 // Obtain an output frame. 664 WebRtc_ReadBuffer(aecm->outFrameBuf, (void**) &out_ptr, out, FRAME_LEN); 665 if (out_ptr != out) { 666 // ReadBuffer() hasn't copied to |out| in this case. 667 memcpy(out, out_ptr, FRAME_LEN * sizeof(int16_t)); 668 } 669 670 return 0; 671 } 672 673 // WebRtcAecm_AsymFilt(...) 674 // 675 // Performs asymmetric filtering. 676 // 677 // Inputs: 678 // - filtOld : Previous filtered value. 679 // - inVal : New input value. 680 // - stepSizePos : Step size when we have a positive contribution. 681 // - stepSizeNeg : Step size when we have a negative contribution. 682 // 683 // Output: 684 // 685 // Return: - Filtered value. 686 // 687 int16_t WebRtcAecm_AsymFilt(const int16_t filtOld, const int16_t inVal, 688 const int16_t stepSizePos, 689 const int16_t stepSizeNeg) 690 { 691 int16_t retVal; 692 693 if ((filtOld == WEBRTC_SPL_WORD16_MAX) | (filtOld == WEBRTC_SPL_WORD16_MIN)) 694 { 695 return inVal; 696 } 697 retVal = filtOld; 698 if (filtOld > inVal) 699 { 700 retVal -= WEBRTC_SPL_RSHIFT_W16(filtOld - inVal, stepSizeNeg); 701 } else 702 { 703 retVal += WEBRTC_SPL_RSHIFT_W16(inVal - filtOld, stepSizePos); 704 } 705 706 return retVal; 707 } 708 709 // WebRtcAecm_CalcEnergies(...) 710 // 711 // This function calculates the log of energies for nearend, farend and estimated 712 // echoes. There is also an update of energy decision levels, i.e. internal VAD. 713 // 714 // 715 // @param aecm [i/o] Handle of the AECM instance. 716 // @param far_spectrum [in] Pointer to farend spectrum. 717 // @param far_q [in] Q-domain of farend spectrum. 718 // @param nearEner [in] Near end energy for current block in 719 // Q(aecm->dfaQDomain). 720 // @param echoEst [out] Estimated echo in Q(xfa_q+RESOLUTION_CHANNEL16). 721 // 722 void WebRtcAecm_CalcEnergies(AecmCore_t * aecm, 723 const uint16_t* far_spectrum, 724 const int16_t far_q, 725 const uint32_t nearEner, 726 int32_t * echoEst) 727 { 728 // Local variables 729 uint32_t tmpAdapt = 0; 730 uint32_t tmpStored = 0; 731 uint32_t tmpFar = 0; 732 733 int i; 734 735 int16_t zeros, frac; 736 int16_t tmp16; 737 int16_t increase_max_shifts = 4; 738 int16_t decrease_max_shifts = 11; 739 int16_t increase_min_shifts = 11; 740 int16_t decrease_min_shifts = 3; 741 int16_t kLogLowValue = WEBRTC_SPL_LSHIFT_W16(PART_LEN_SHIFT, 7); 742 743 // Get log of near end energy and store in buffer 744 745 // Shift buffer 746 memmove(aecm->nearLogEnergy + 1, aecm->nearLogEnergy, 747 sizeof(int16_t) * (MAX_BUF_LEN - 1)); 748 749 // Logarithm of integrated magnitude spectrum (nearEner) 750 tmp16 = kLogLowValue; 751 if (nearEner) 752 { 753 zeros = WebRtcSpl_NormU32(nearEner); 754 frac = (int16_t)WEBRTC_SPL_RSHIFT_U32( 755 (WEBRTC_SPL_LSHIFT_U32(nearEner, zeros) & 0x7FFFFFFF), 756 23); 757 // log2 in Q8 758 tmp16 += WEBRTC_SPL_LSHIFT_W16((31 - zeros), 8) + frac; 759 tmp16 -= WEBRTC_SPL_LSHIFT_W16(aecm->dfaNoisyQDomain, 8); 760 } 761 aecm->nearLogEnergy[0] = tmp16; 762 // END: Get log of near end energy 763 764 WebRtcAecm_CalcLinearEnergies(aecm, far_spectrum, echoEst, &tmpFar, &tmpAdapt, &tmpStored); 765 766 // Shift buffers 767 memmove(aecm->echoAdaptLogEnergy + 1, aecm->echoAdaptLogEnergy, 768 sizeof(int16_t) * (MAX_BUF_LEN - 1)); 769 memmove(aecm->echoStoredLogEnergy + 1, aecm->echoStoredLogEnergy, 770 sizeof(int16_t) * (MAX_BUF_LEN - 1)); 771 772 // Logarithm of delayed far end energy 773 tmp16 = kLogLowValue; 774 if (tmpFar) 775 { 776 zeros = WebRtcSpl_NormU32(tmpFar); 777 frac = (int16_t)WEBRTC_SPL_RSHIFT_U32((WEBRTC_SPL_LSHIFT_U32(tmpFar, zeros) 778 & 0x7FFFFFFF), 23); 779 // log2 in Q8 780 tmp16 += WEBRTC_SPL_LSHIFT_W16((31 - zeros), 8) + frac; 781 tmp16 -= WEBRTC_SPL_LSHIFT_W16(far_q, 8); 782 } 783 aecm->farLogEnergy = tmp16; 784 785 // Logarithm of estimated echo energy through adapted channel 786 tmp16 = kLogLowValue; 787 if (tmpAdapt) 788 { 789 zeros = WebRtcSpl_NormU32(tmpAdapt); 790 frac = (int16_t)WEBRTC_SPL_RSHIFT_U32((WEBRTC_SPL_LSHIFT_U32(tmpAdapt, zeros) 791 & 0x7FFFFFFF), 23); 792 //log2 in Q8 793 tmp16 += WEBRTC_SPL_LSHIFT_W16((31 - zeros), 8) + frac; 794 tmp16 -= WEBRTC_SPL_LSHIFT_W16(RESOLUTION_CHANNEL16 + far_q, 8); 795 } 796 aecm->echoAdaptLogEnergy[0] = tmp16; 797 798 // Logarithm of estimated echo energy through stored channel 799 tmp16 = kLogLowValue; 800 if (tmpStored) 801 { 802 zeros = WebRtcSpl_NormU32(tmpStored); 803 frac = (int16_t)WEBRTC_SPL_RSHIFT_U32((WEBRTC_SPL_LSHIFT_U32(tmpStored, zeros) 804 & 0x7FFFFFFF), 23); 805 //log2 in Q8 806 tmp16 += WEBRTC_SPL_LSHIFT_W16((31 - zeros), 8) + frac; 807 tmp16 -= WEBRTC_SPL_LSHIFT_W16(RESOLUTION_CHANNEL16 + far_q, 8); 808 } 809 aecm->echoStoredLogEnergy[0] = tmp16; 810 811 // Update farend energy levels (min, max, vad, mse) 812 if (aecm->farLogEnergy > FAR_ENERGY_MIN) 813 { 814 if (aecm->startupState == 0) 815 { 816 increase_max_shifts = 2; 817 decrease_min_shifts = 2; 818 increase_min_shifts = 8; 819 } 820 821 aecm->farEnergyMin = WebRtcAecm_AsymFilt(aecm->farEnergyMin, aecm->farLogEnergy, 822 increase_min_shifts, decrease_min_shifts); 823 aecm->farEnergyMax = WebRtcAecm_AsymFilt(aecm->farEnergyMax, aecm->farLogEnergy, 824 increase_max_shifts, decrease_max_shifts); 825 aecm->farEnergyMaxMin = (aecm->farEnergyMax - aecm->farEnergyMin); 826 827 // Dynamic VAD region size 828 tmp16 = 2560 - aecm->farEnergyMin; 829 if (tmp16 > 0) 830 { 831 tmp16 = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(tmp16, FAR_ENERGY_VAD_REGION, 9); 832 } else 833 { 834 tmp16 = 0; 835 } 836 tmp16 += FAR_ENERGY_VAD_REGION; 837 838 if ((aecm->startupState == 0) | (aecm->vadUpdateCount > 1024)) 839 { 840 // In startup phase or VAD update halted 841 aecm->farEnergyVAD = aecm->farEnergyMin + tmp16; 842 } else 843 { 844 if (aecm->farEnergyVAD > aecm->farLogEnergy) 845 { 846 aecm->farEnergyVAD += WEBRTC_SPL_RSHIFT_W16(aecm->farLogEnergy + 847 tmp16 - 848 aecm->farEnergyVAD, 849 6); 850 aecm->vadUpdateCount = 0; 851 } else 852 { 853 aecm->vadUpdateCount++; 854 } 855 } 856 // Put MSE threshold higher than VAD 857 aecm->farEnergyMSE = aecm->farEnergyVAD + (1 << 8); 858 } 859 860 // Update VAD variables 861 if (aecm->farLogEnergy > aecm->farEnergyVAD) 862 { 863 if ((aecm->startupState == 0) | (aecm->farEnergyMaxMin > FAR_ENERGY_DIFF)) 864 { 865 // We are in startup or have significant dynamics in input speech level 866 aecm->currentVADValue = 1; 867 } 868 } else 869 { 870 aecm->currentVADValue = 0; 871 } 872 if ((aecm->currentVADValue) && (aecm->firstVAD)) 873 { 874 aecm->firstVAD = 0; 875 if (aecm->echoAdaptLogEnergy[0] > aecm->nearLogEnergy[0]) 876 { 877 // The estimated echo has higher energy than the near end signal. 878 // This means that the initialization was too aggressive. Scale 879 // down by a factor 8 880 for (i = 0; i < PART_LEN1; i++) 881 { 882 aecm->channelAdapt16[i] >>= 3; 883 } 884 // Compensate the adapted echo energy level accordingly. 885 aecm->echoAdaptLogEnergy[0] -= (3 << 8); 886 aecm->firstVAD = 1; 887 } 888 } 889 } 890 891 // WebRtcAecm_CalcStepSize(...) 892 // 893 // This function calculates the step size used in channel estimation 894 // 895 // 896 // @param aecm [in] Handle of the AECM instance. 897 // @param mu [out] (Return value) Stepsize in log2(), i.e. number of shifts. 898 // 899 // 900 int16_t WebRtcAecm_CalcStepSize(AecmCore_t * const aecm) 901 { 902 903 int32_t tmp32; 904 int16_t tmp16; 905 int16_t mu = MU_MAX; 906 907 // Here we calculate the step size mu used in the 908 // following NLMS based Channel estimation algorithm 909 if (!aecm->currentVADValue) 910 { 911 // Far end energy level too low, no channel update 912 mu = 0; 913 } else if (aecm->startupState > 0) 914 { 915 if (aecm->farEnergyMin >= aecm->farEnergyMax) 916 { 917 mu = MU_MIN; 918 } else 919 { 920 tmp16 = (aecm->farLogEnergy - aecm->farEnergyMin); 921 tmp32 = WEBRTC_SPL_MUL_16_16(tmp16, MU_DIFF); 922 tmp32 = WebRtcSpl_DivW32W16(tmp32, aecm->farEnergyMaxMin); 923 mu = MU_MIN - 1 - (int16_t)(tmp32); 924 // The -1 is an alternative to rounding. This way we get a larger 925 // stepsize, so we in some sense compensate for truncation in NLMS 926 } 927 if (mu < MU_MAX) 928 { 929 mu = MU_MAX; // Equivalent with maximum step size of 2^-MU_MAX 930 } 931 } 932 933 return mu; 934 } 935 936 // WebRtcAecm_UpdateChannel(...) 937 // 938 // This function performs channel estimation. NLMS and decision on channel storage. 939 // 940 // 941 // @param aecm [i/o] Handle of the AECM instance. 942 // @param far_spectrum [in] Absolute value of the farend signal in Q(far_q) 943 // @param far_q [in] Q-domain of the farend signal 944 // @param dfa [in] Absolute value of the nearend signal (Q[aecm->dfaQDomain]) 945 // @param mu [in] NLMS step size. 946 // @param echoEst [i/o] Estimated echo in Q(far_q+RESOLUTION_CHANNEL16). 947 // 948 void WebRtcAecm_UpdateChannel(AecmCore_t * aecm, 949 const uint16_t* far_spectrum, 950 const int16_t far_q, 951 const uint16_t * const dfa, 952 const int16_t mu, 953 int32_t * echoEst) 954 { 955 956 uint32_t tmpU32no1, tmpU32no2; 957 int32_t tmp32no1, tmp32no2; 958 int32_t mseStored; 959 int32_t mseAdapt; 960 961 int i; 962 963 int16_t zerosFar, zerosNum, zerosCh, zerosDfa; 964 int16_t shiftChFar, shiftNum, shift2ResChan; 965 int16_t tmp16no1; 966 int16_t xfaQ, dfaQ; 967 968 // This is the channel estimation algorithm. It is base on NLMS but has a variable step 969 // length, which was calculated above. 970 if (mu) 971 { 972 for (i = 0; i < PART_LEN1; i++) 973 { 974 // Determine norm of channel and farend to make sure we don't get overflow in 975 // multiplication 976 zerosCh = WebRtcSpl_NormU32(aecm->channelAdapt32[i]); 977 zerosFar = WebRtcSpl_NormU32((uint32_t)far_spectrum[i]); 978 if (zerosCh + zerosFar > 31) 979 { 980 // Multiplication is safe 981 tmpU32no1 = WEBRTC_SPL_UMUL_32_16(aecm->channelAdapt32[i], 982 far_spectrum[i]); 983 shiftChFar = 0; 984 } else 985 { 986 // We need to shift down before multiplication 987 shiftChFar = 32 - zerosCh - zerosFar; 988 tmpU32no1 = WEBRTC_SPL_UMUL_32_16( 989 WEBRTC_SPL_RSHIFT_W32(aecm->channelAdapt32[i], shiftChFar), 990 far_spectrum[i]); 991 } 992 // Determine Q-domain of numerator 993 zerosNum = WebRtcSpl_NormU32(tmpU32no1); 994 if (dfa[i]) 995 { 996 zerosDfa = WebRtcSpl_NormU32((uint32_t)dfa[i]); 997 } else 998 { 999 zerosDfa = 32; 1000 } 1001 tmp16no1 = zerosDfa - 2 + aecm->dfaNoisyQDomain - 1002 RESOLUTION_CHANNEL32 - far_q + shiftChFar; 1003 if (zerosNum > tmp16no1 + 1) 1004 { 1005 xfaQ = tmp16no1; 1006 dfaQ = zerosDfa - 2; 1007 } else 1008 { 1009 xfaQ = zerosNum - 2; 1010 dfaQ = RESOLUTION_CHANNEL32 + far_q - aecm->dfaNoisyQDomain - 1011 shiftChFar + xfaQ; 1012 } 1013 // Add in the same Q-domain 1014 tmpU32no1 = WEBRTC_SPL_SHIFT_W32(tmpU32no1, xfaQ); 1015 tmpU32no2 = WEBRTC_SPL_SHIFT_W32((uint32_t)dfa[i], dfaQ); 1016 tmp32no1 = (int32_t)tmpU32no2 - (int32_t)tmpU32no1; 1017 zerosNum = WebRtcSpl_NormW32(tmp32no1); 1018 if ((tmp32no1) && (far_spectrum[i] > (CHANNEL_VAD << far_q))) 1019 { 1020 // 1021 // Update is needed 1022 // 1023 // This is what we would like to compute 1024 // 1025 // tmp32no1 = dfa[i] - (aecm->channelAdapt[i] * far_spectrum[i]) 1026 // tmp32norm = (i + 1) 1027 // aecm->channelAdapt[i] += (2^mu) * tmp32no1 1028 // / (tmp32norm * far_spectrum[i]) 1029 // 1030 1031 // Make sure we don't get overflow in multiplication. 1032 if (zerosNum + zerosFar > 31) 1033 { 1034 if (tmp32no1 > 0) 1035 { 1036 tmp32no2 = (int32_t)WEBRTC_SPL_UMUL_32_16(tmp32no1, 1037 far_spectrum[i]); 1038 } else 1039 { 1040 tmp32no2 = -(int32_t)WEBRTC_SPL_UMUL_32_16(-tmp32no1, 1041 far_spectrum[i]); 1042 } 1043 shiftNum = 0; 1044 } else 1045 { 1046 shiftNum = 32 - (zerosNum + zerosFar); 1047 if (tmp32no1 > 0) 1048 { 1049 tmp32no2 = (int32_t)WEBRTC_SPL_UMUL_32_16( 1050 WEBRTC_SPL_RSHIFT_W32(tmp32no1, shiftNum), 1051 far_spectrum[i]); 1052 } else 1053 { 1054 tmp32no2 = -(int32_t)WEBRTC_SPL_UMUL_32_16( 1055 WEBRTC_SPL_RSHIFT_W32(-tmp32no1, shiftNum), 1056 far_spectrum[i]); 1057 } 1058 } 1059 // Normalize with respect to frequency bin 1060 tmp32no2 = WebRtcSpl_DivW32W16(tmp32no2, i + 1); 1061 // Make sure we are in the right Q-domain 1062 shift2ResChan = shiftNum + shiftChFar - xfaQ - mu - ((30 - zerosFar) << 1); 1063 if (WebRtcSpl_NormW32(tmp32no2) < shift2ResChan) 1064 { 1065 tmp32no2 = WEBRTC_SPL_WORD32_MAX; 1066 } else 1067 { 1068 tmp32no2 = WEBRTC_SPL_SHIFT_W32(tmp32no2, shift2ResChan); 1069 } 1070 aecm->channelAdapt32[i] = WEBRTC_SPL_ADD_SAT_W32(aecm->channelAdapt32[i], 1071 tmp32no2); 1072 if (aecm->channelAdapt32[i] < 0) 1073 { 1074 // We can never have negative channel gain 1075 aecm->channelAdapt32[i] = 0; 1076 } 1077 aecm->channelAdapt16[i] 1078 = (int16_t)WEBRTC_SPL_RSHIFT_W32(aecm->channelAdapt32[i], 16); 1079 } 1080 } 1081 } 1082 // END: Adaptive channel update 1083 1084 // Determine if we should store or restore the channel 1085 if ((aecm->startupState == 0) & (aecm->currentVADValue)) 1086 { 1087 // During startup we store the channel every block, 1088 // and we recalculate echo estimate 1089 WebRtcAecm_StoreAdaptiveChannel(aecm, far_spectrum, echoEst); 1090 } else 1091 { 1092 if (aecm->farLogEnergy < aecm->farEnergyMSE) 1093 { 1094 aecm->mseChannelCount = 0; 1095 } else 1096 { 1097 aecm->mseChannelCount++; 1098 } 1099 // Enough data for validation. Store channel if we can. 1100 if (aecm->mseChannelCount >= (MIN_MSE_COUNT + 10)) 1101 { 1102 // We have enough data. 1103 // Calculate MSE of "Adapt" and "Stored" versions. 1104 // It is actually not MSE, but average absolute error. 1105 mseStored = 0; 1106 mseAdapt = 0; 1107 for (i = 0; i < MIN_MSE_COUNT; i++) 1108 { 1109 tmp32no1 = ((int32_t)aecm->echoStoredLogEnergy[i] 1110 - (int32_t)aecm->nearLogEnergy[i]); 1111 tmp32no2 = WEBRTC_SPL_ABS_W32(tmp32no1); 1112 mseStored += tmp32no2; 1113 1114 tmp32no1 = ((int32_t)aecm->echoAdaptLogEnergy[i] 1115 - (int32_t)aecm->nearLogEnergy[i]); 1116 tmp32no2 = WEBRTC_SPL_ABS_W32(tmp32no1); 1117 mseAdapt += tmp32no2; 1118 } 1119 if (((mseStored << MSE_RESOLUTION) < (MIN_MSE_DIFF * mseAdapt)) 1120 & ((aecm->mseStoredOld << MSE_RESOLUTION) < (MIN_MSE_DIFF 1121 * aecm->mseAdaptOld))) 1122 { 1123 // The stored channel has a significantly lower MSE than the adaptive one for 1124 // two consecutive calculations. Reset the adaptive channel. 1125 WebRtcAecm_ResetAdaptiveChannel(aecm); 1126 } else if (((MIN_MSE_DIFF * mseStored) > (mseAdapt << MSE_RESOLUTION)) & (mseAdapt 1127 < aecm->mseThreshold) & (aecm->mseAdaptOld < aecm->mseThreshold)) 1128 { 1129 // The adaptive channel has a significantly lower MSE than the stored one. 1130 // The MSE for the adaptive channel has also been low for two consecutive 1131 // calculations. Store the adaptive channel. 1132 WebRtcAecm_StoreAdaptiveChannel(aecm, far_spectrum, echoEst); 1133 1134 // Update threshold 1135 if (aecm->mseThreshold == WEBRTC_SPL_WORD32_MAX) 1136 { 1137 aecm->mseThreshold = (mseAdapt + aecm->mseAdaptOld); 1138 } else 1139 { 1140 aecm->mseThreshold += WEBRTC_SPL_MUL_16_16_RSFT(mseAdapt 1141 - WEBRTC_SPL_MUL_16_16_RSFT(aecm->mseThreshold, 5, 3), 205, 8); 1142 } 1143 1144 } 1145 1146 // Reset counter 1147 aecm->mseChannelCount = 0; 1148 1149 // Store the MSE values. 1150 aecm->mseStoredOld = mseStored; 1151 aecm->mseAdaptOld = mseAdapt; 1152 } 1153 } 1154 // END: Determine if we should store or reset channel estimate. 1155 } 1156 1157 // CalcSuppressionGain(...) 1158 // 1159 // This function calculates the suppression gain that is used in the Wiener filter. 1160 // 1161 // 1162 // @param aecm [i/n] Handle of the AECM instance. 1163 // @param supGain [out] (Return value) Suppression gain with which to scale the noise 1164 // level (Q14). 1165 // 1166 // 1167 int16_t WebRtcAecm_CalcSuppressionGain(AecmCore_t * const aecm) 1168 { 1169 int32_t tmp32no1; 1170 1171 int16_t supGain = SUPGAIN_DEFAULT; 1172 int16_t tmp16no1; 1173 int16_t dE = 0; 1174 1175 // Determine suppression gain used in the Wiener filter. The gain is based on a mix of far 1176 // end energy and echo estimation error. 1177 // Adjust for the far end signal level. A low signal level indicates no far end signal, 1178 // hence we set the suppression gain to 0 1179 if (!aecm->currentVADValue) 1180 { 1181 supGain = 0; 1182 } else 1183 { 1184 // Adjust for possible double talk. If we have large variations in estimation error we 1185 // likely have double talk (or poor channel). 1186 tmp16no1 = (aecm->nearLogEnergy[0] - aecm->echoStoredLogEnergy[0] - ENERGY_DEV_OFFSET); 1187 dE = WEBRTC_SPL_ABS_W16(tmp16no1); 1188 1189 if (dE < ENERGY_DEV_TOL) 1190 { 1191 // Likely no double talk. The better estimation, the more we can suppress signal. 1192 // Update counters 1193 if (dE < SUPGAIN_EPC_DT) 1194 { 1195 tmp32no1 = WEBRTC_SPL_MUL_16_16(aecm->supGainErrParamDiffAB, dE); 1196 tmp32no1 += (SUPGAIN_EPC_DT >> 1); 1197 tmp16no1 = (int16_t)WebRtcSpl_DivW32W16(tmp32no1, SUPGAIN_EPC_DT); 1198 supGain = aecm->supGainErrParamA - tmp16no1; 1199 } else 1200 { 1201 tmp32no1 = WEBRTC_SPL_MUL_16_16(aecm->supGainErrParamDiffBD, 1202 (ENERGY_DEV_TOL - dE)); 1203 tmp32no1 += ((ENERGY_DEV_TOL - SUPGAIN_EPC_DT) >> 1); 1204 tmp16no1 = (int16_t)WebRtcSpl_DivW32W16(tmp32no1, (ENERGY_DEV_TOL 1205 - SUPGAIN_EPC_DT)); 1206 supGain = aecm->supGainErrParamD + tmp16no1; 1207 } 1208 } else 1209 { 1210 // Likely in double talk. Use default value 1211 supGain = aecm->supGainErrParamD; 1212 } 1213 } 1214 1215 if (supGain > aecm->supGainOld) 1216 { 1217 tmp16no1 = supGain; 1218 } else 1219 { 1220 tmp16no1 = aecm->supGainOld; 1221 } 1222 aecm->supGainOld = supGain; 1223 if (tmp16no1 < aecm->supGain) 1224 { 1225 aecm->supGain += (int16_t)((tmp16no1 - aecm->supGain) >> 4); 1226 } else 1227 { 1228 aecm->supGain += (int16_t)((tmp16no1 - aecm->supGain) >> 4); 1229 } 1230 1231 // END: Update suppression gain 1232 1233 return aecm->supGain; 1234 } 1235 1236 void WebRtcAecm_BufferFarFrame(AecmCore_t* const aecm, 1237 const int16_t* const farend, 1238 const int farLen) 1239 { 1240 int writeLen = farLen, writePos = 0; 1241 1242 // Check if the write position must be wrapped 1243 while (aecm->farBufWritePos + writeLen > FAR_BUF_LEN) 1244 { 1245 // Write to remaining buffer space before wrapping 1246 writeLen = FAR_BUF_LEN - aecm->farBufWritePos; 1247 memcpy(aecm->farBuf + aecm->farBufWritePos, farend + writePos, 1248 sizeof(int16_t) * writeLen); 1249 aecm->farBufWritePos = 0; 1250 writePos = writeLen; 1251 writeLen = farLen - writeLen; 1252 } 1253 1254 memcpy(aecm->farBuf + aecm->farBufWritePos, farend + writePos, 1255 sizeof(int16_t) * writeLen); 1256 aecm->farBufWritePos += writeLen; 1257 } 1258 1259 void WebRtcAecm_FetchFarFrame(AecmCore_t * const aecm, int16_t * const farend, 1260 const int farLen, const int knownDelay) 1261 { 1262 int readLen = farLen; 1263 int readPos = 0; 1264 int delayChange = knownDelay - aecm->lastKnownDelay; 1265 1266 aecm->farBufReadPos -= delayChange; 1267 1268 // Check if delay forces a read position wrap 1269 while (aecm->farBufReadPos < 0) 1270 { 1271 aecm->farBufReadPos += FAR_BUF_LEN; 1272 } 1273 while (aecm->farBufReadPos > FAR_BUF_LEN - 1) 1274 { 1275 aecm->farBufReadPos -= FAR_BUF_LEN; 1276 } 1277 1278 aecm->lastKnownDelay = knownDelay; 1279 1280 // Check if read position must be wrapped 1281 while (aecm->farBufReadPos + readLen > FAR_BUF_LEN) 1282 { 1283 1284 // Read from remaining buffer space before wrapping 1285 readLen = FAR_BUF_LEN - aecm->farBufReadPos; 1286 memcpy(farend + readPos, aecm->farBuf + aecm->farBufReadPos, 1287 sizeof(int16_t) * readLen); 1288 aecm->farBufReadPos = 0; 1289 readPos = readLen; 1290 readLen = farLen - readLen; 1291 } 1292 memcpy(farend + readPos, aecm->farBuf + aecm->farBufReadPos, 1293 sizeof(int16_t) * readLen); 1294 aecm->farBufReadPos += readLen; 1295 } 1296