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 += aecm->channelAdapt16[i] * far_spectrum[i]; 334 (*echo_energy_stored) += (uint32_t)echo_est[i]; 335 } 336 } 337 338 static void StoreAdaptiveChannelC(AecmCore_t* aecm, 339 const uint16_t* far_spectrum, 340 int32_t* echo_est) 341 { 342 int i; 343 344 // During startup we store the channel every block. 345 memcpy(aecm->channelStored, aecm->channelAdapt16, sizeof(int16_t) * PART_LEN1); 346 // Recalculate echo estimate 347 for (i = 0; i < PART_LEN; i += 4) 348 { 349 echo_est[i] = WEBRTC_SPL_MUL_16_U16(aecm->channelStored[i], 350 far_spectrum[i]); 351 echo_est[i + 1] = WEBRTC_SPL_MUL_16_U16(aecm->channelStored[i + 1], 352 far_spectrum[i + 1]); 353 echo_est[i + 2] = WEBRTC_SPL_MUL_16_U16(aecm->channelStored[i + 2], 354 far_spectrum[i + 2]); 355 echo_est[i + 3] = WEBRTC_SPL_MUL_16_U16(aecm->channelStored[i + 3], 356 far_spectrum[i + 3]); 357 } 358 echo_est[i] = WEBRTC_SPL_MUL_16_U16(aecm->channelStored[i], 359 far_spectrum[i]); 360 } 361 362 static void ResetAdaptiveChannelC(AecmCore_t* aecm) 363 { 364 int i; 365 366 // The stored channel has a significantly lower MSE than the adaptive one for 367 // two consecutive calculations. Reset the adaptive channel. 368 memcpy(aecm->channelAdapt16, aecm->channelStored, 369 sizeof(int16_t) * PART_LEN1); 370 // Restore the W32 channel 371 for (i = 0; i < PART_LEN; i += 4) 372 { 373 aecm->channelAdapt32[i] = WEBRTC_SPL_LSHIFT_W32( 374 (int32_t)aecm->channelStored[i], 16); 375 aecm->channelAdapt32[i + 1] = WEBRTC_SPL_LSHIFT_W32( 376 (int32_t)aecm->channelStored[i + 1], 16); 377 aecm->channelAdapt32[i + 2] = WEBRTC_SPL_LSHIFT_W32( 378 (int32_t)aecm->channelStored[i + 2], 16); 379 aecm->channelAdapt32[i + 3] = WEBRTC_SPL_LSHIFT_W32( 380 (int32_t)aecm->channelStored[i + 3], 16); 381 } 382 aecm->channelAdapt32[i] = WEBRTC_SPL_LSHIFT_W32((int32_t)aecm->channelStored[i], 16); 383 } 384 385 // Initialize function pointers for ARM Neon platform. 386 #if (defined WEBRTC_DETECT_ARM_NEON || defined WEBRTC_ARCH_ARM_NEON) 387 static void WebRtcAecm_InitNeon(void) 388 { 389 WebRtcAecm_StoreAdaptiveChannel = WebRtcAecm_StoreAdaptiveChannelNeon; 390 WebRtcAecm_ResetAdaptiveChannel = WebRtcAecm_ResetAdaptiveChannelNeon; 391 WebRtcAecm_CalcLinearEnergies = WebRtcAecm_CalcLinearEnergiesNeon; 392 } 393 #endif 394 395 // Initialize function pointers for MIPS platform. 396 #if defined(MIPS32_LE) 397 static void WebRtcAecm_InitMips(void) 398 { 399 #if defined(MIPS_DSP_R1_LE) 400 WebRtcAecm_StoreAdaptiveChannel = WebRtcAecm_StoreAdaptiveChannel_mips; 401 WebRtcAecm_ResetAdaptiveChannel = WebRtcAecm_ResetAdaptiveChannel_mips; 402 #endif 403 WebRtcAecm_CalcLinearEnergies = WebRtcAecm_CalcLinearEnergies_mips; 404 } 405 #endif 406 407 // WebRtcAecm_InitCore(...) 408 // 409 // This function initializes the AECM instant created with WebRtcAecm_CreateCore(...) 410 // Input: 411 // - aecm : Pointer to the Echo Suppression instance 412 // - samplingFreq : Sampling Frequency 413 // 414 // Output: 415 // - aecm : Initialized instance 416 // 417 // Return value : 0 - Ok 418 // -1 - Error 419 // 420 int WebRtcAecm_InitCore(AecmCore_t * const aecm, int samplingFreq) 421 { 422 int i = 0; 423 int32_t tmp32 = PART_LEN1 * PART_LEN1; 424 int16_t tmp16 = PART_LEN1; 425 426 if (samplingFreq != 8000 && samplingFreq != 16000) 427 { 428 samplingFreq = 8000; 429 return -1; 430 } 431 // sanity check of sampling frequency 432 aecm->mult = (int16_t)samplingFreq / 8000; 433 434 aecm->farBufWritePos = 0; 435 aecm->farBufReadPos = 0; 436 aecm->knownDelay = 0; 437 aecm->lastKnownDelay = 0; 438 439 WebRtc_InitBuffer(aecm->farFrameBuf); 440 WebRtc_InitBuffer(aecm->nearNoisyFrameBuf); 441 WebRtc_InitBuffer(aecm->nearCleanFrameBuf); 442 WebRtc_InitBuffer(aecm->outFrameBuf); 443 444 memset(aecm->xBuf_buf, 0, sizeof(aecm->xBuf_buf)); 445 memset(aecm->dBufClean_buf, 0, sizeof(aecm->dBufClean_buf)); 446 memset(aecm->dBufNoisy_buf, 0, sizeof(aecm->dBufNoisy_buf)); 447 memset(aecm->outBuf_buf, 0, sizeof(aecm->outBuf_buf)); 448 449 aecm->seed = 666; 450 aecm->totCount = 0; 451 452 if (WebRtc_InitDelayEstimatorFarend(aecm->delay_estimator_farend) != 0) { 453 return -1; 454 } 455 if (WebRtc_InitDelayEstimator(aecm->delay_estimator) != 0) { 456 return -1; 457 } 458 // Set far end histories to zero 459 memset(aecm->far_history, 0, sizeof(uint16_t) * PART_LEN1 * MAX_DELAY); 460 memset(aecm->far_q_domains, 0, sizeof(int) * MAX_DELAY); 461 aecm->far_history_pos = MAX_DELAY; 462 463 aecm->nlpFlag = 1; 464 aecm->fixedDelay = -1; 465 466 aecm->dfaCleanQDomain = 0; 467 aecm->dfaCleanQDomainOld = 0; 468 aecm->dfaNoisyQDomain = 0; 469 aecm->dfaNoisyQDomainOld = 0; 470 471 memset(aecm->nearLogEnergy, 0, sizeof(aecm->nearLogEnergy)); 472 aecm->farLogEnergy = 0; 473 memset(aecm->echoAdaptLogEnergy, 0, sizeof(aecm->echoAdaptLogEnergy)); 474 memset(aecm->echoStoredLogEnergy, 0, sizeof(aecm->echoStoredLogEnergy)); 475 476 // Initialize the echo channels with a stored shape. 477 if (samplingFreq == 8000) 478 { 479 WebRtcAecm_InitEchoPathCore(aecm, kChannelStored8kHz); 480 } 481 else 482 { 483 WebRtcAecm_InitEchoPathCore(aecm, kChannelStored16kHz); 484 } 485 486 memset(aecm->echoFilt, 0, sizeof(aecm->echoFilt)); 487 memset(aecm->nearFilt, 0, sizeof(aecm->nearFilt)); 488 aecm->noiseEstCtr = 0; 489 490 aecm->cngMode = AecmTrue; 491 492 memset(aecm->noiseEstTooLowCtr, 0, sizeof(aecm->noiseEstTooLowCtr)); 493 memset(aecm->noiseEstTooHighCtr, 0, sizeof(aecm->noiseEstTooHighCtr)); 494 // Shape the initial noise level to an approximate pink noise. 495 for (i = 0; i < (PART_LEN1 >> 1) - 1; i++) 496 { 497 aecm->noiseEst[i] = (tmp32 << 8); 498 tmp16--; 499 tmp32 -= (int32_t)((tmp16 << 1) + 1); 500 } 501 for (; i < PART_LEN1; i++) 502 { 503 aecm->noiseEst[i] = (tmp32 << 8); 504 } 505 506 aecm->farEnergyMin = WEBRTC_SPL_WORD16_MAX; 507 aecm->farEnergyMax = WEBRTC_SPL_WORD16_MIN; 508 aecm->farEnergyMaxMin = 0; 509 aecm->farEnergyVAD = FAR_ENERGY_MIN; // This prevents false speech detection at the 510 // beginning. 511 aecm->farEnergyMSE = 0; 512 aecm->currentVADValue = 0; 513 aecm->vadUpdateCount = 0; 514 aecm->firstVAD = 1; 515 516 aecm->startupState = 0; 517 aecm->supGain = SUPGAIN_DEFAULT; 518 aecm->supGainOld = SUPGAIN_DEFAULT; 519 520 aecm->supGainErrParamA = SUPGAIN_ERROR_PARAM_A; 521 aecm->supGainErrParamD = SUPGAIN_ERROR_PARAM_D; 522 aecm->supGainErrParamDiffAB = SUPGAIN_ERROR_PARAM_A - SUPGAIN_ERROR_PARAM_B; 523 aecm->supGainErrParamDiffBD = SUPGAIN_ERROR_PARAM_B - SUPGAIN_ERROR_PARAM_D; 524 525 // Assert a preprocessor definition at compile-time. It's an assumption 526 // used in assembly code, so check the assembly files before any change. 527 COMPILE_ASSERT(PART_LEN % 16 == 0); 528 529 // Initialize function pointers. 530 WebRtcAecm_CalcLinearEnergies = CalcLinearEnergiesC; 531 WebRtcAecm_StoreAdaptiveChannel = StoreAdaptiveChannelC; 532 WebRtcAecm_ResetAdaptiveChannel = ResetAdaptiveChannelC; 533 534 #ifdef WEBRTC_DETECT_ARM_NEON 535 uint64_t features = WebRtc_GetCPUFeaturesARM(); 536 if ((features & kCPUFeatureNEON) != 0) 537 { 538 WebRtcAecm_InitNeon(); 539 } 540 #elif defined(WEBRTC_ARCH_ARM_NEON) 541 WebRtcAecm_InitNeon(); 542 #endif 543 544 #if defined(MIPS32_LE) 545 WebRtcAecm_InitMips(); 546 #endif 547 return 0; 548 } 549 550 // TODO(bjornv): This function is currently not used. Add support for these 551 // parameters from a higher level 552 int WebRtcAecm_Control(AecmCore_t *aecm, int delay, int nlpFlag) 553 { 554 aecm->nlpFlag = nlpFlag; 555 aecm->fixedDelay = delay; 556 557 return 0; 558 } 559 560 int WebRtcAecm_FreeCore(AecmCore_t *aecm) 561 { 562 if (aecm == NULL) 563 { 564 return -1; 565 } 566 567 WebRtc_FreeBuffer(aecm->farFrameBuf); 568 WebRtc_FreeBuffer(aecm->nearNoisyFrameBuf); 569 WebRtc_FreeBuffer(aecm->nearCleanFrameBuf); 570 WebRtc_FreeBuffer(aecm->outFrameBuf); 571 572 WebRtc_FreeDelayEstimator(aecm->delay_estimator); 573 WebRtc_FreeDelayEstimatorFarend(aecm->delay_estimator_farend); 574 WebRtcSpl_FreeRealFFT(aecm->real_fft); 575 576 free(aecm); 577 578 return 0; 579 } 580 581 int WebRtcAecm_ProcessFrame(AecmCore_t * aecm, 582 const int16_t * farend, 583 const int16_t * nearendNoisy, 584 const int16_t * nearendClean, 585 int16_t * out) 586 { 587 int16_t outBlock_buf[PART_LEN + 8]; // Align buffer to 8-byte boundary. 588 int16_t* outBlock = (int16_t*) (((uintptr_t) outBlock_buf + 15) & ~ 15); 589 590 int16_t farFrame[FRAME_LEN]; 591 const int16_t* out_ptr = NULL; 592 int size = 0; 593 594 // Buffer the current frame. 595 // Fetch an older one corresponding to the delay. 596 WebRtcAecm_BufferFarFrame(aecm, farend, FRAME_LEN); 597 WebRtcAecm_FetchFarFrame(aecm, farFrame, FRAME_LEN, aecm->knownDelay); 598 599 // Buffer the synchronized far and near frames, 600 // to pass the smaller blocks individually. 601 WebRtc_WriteBuffer(aecm->farFrameBuf, farFrame, FRAME_LEN); 602 WebRtc_WriteBuffer(aecm->nearNoisyFrameBuf, nearendNoisy, FRAME_LEN); 603 if (nearendClean != NULL) 604 { 605 WebRtc_WriteBuffer(aecm->nearCleanFrameBuf, nearendClean, FRAME_LEN); 606 } 607 608 // Process as many blocks as possible. 609 while (WebRtc_available_read(aecm->farFrameBuf) >= PART_LEN) 610 { 611 int16_t far_block[PART_LEN]; 612 const int16_t* far_block_ptr = NULL; 613 int16_t near_noisy_block[PART_LEN]; 614 const int16_t* near_noisy_block_ptr = NULL; 615 616 WebRtc_ReadBuffer(aecm->farFrameBuf, (void**) &far_block_ptr, far_block, 617 PART_LEN); 618 WebRtc_ReadBuffer(aecm->nearNoisyFrameBuf, 619 (void**) &near_noisy_block_ptr, 620 near_noisy_block, 621 PART_LEN); 622 if (nearendClean != NULL) 623 { 624 int16_t near_clean_block[PART_LEN]; 625 const int16_t* near_clean_block_ptr = NULL; 626 627 WebRtc_ReadBuffer(aecm->nearCleanFrameBuf, 628 (void**) &near_clean_block_ptr, 629 near_clean_block, 630 PART_LEN); 631 if (WebRtcAecm_ProcessBlock(aecm, 632 far_block_ptr, 633 near_noisy_block_ptr, 634 near_clean_block_ptr, 635 outBlock) == -1) 636 { 637 return -1; 638 } 639 } else 640 { 641 if (WebRtcAecm_ProcessBlock(aecm, 642 far_block_ptr, 643 near_noisy_block_ptr, 644 NULL, 645 outBlock) == -1) 646 { 647 return -1; 648 } 649 } 650 651 WebRtc_WriteBuffer(aecm->outFrameBuf, outBlock, PART_LEN); 652 } 653 654 // Stuff the out buffer if we have less than a frame to output. 655 // This should only happen for the first frame. 656 size = (int) WebRtc_available_read(aecm->outFrameBuf); 657 if (size < FRAME_LEN) 658 { 659 WebRtc_MoveReadPtr(aecm->outFrameBuf, size - FRAME_LEN); 660 } 661 662 // Obtain an output frame. 663 WebRtc_ReadBuffer(aecm->outFrameBuf, (void**) &out_ptr, out, FRAME_LEN); 664 if (out_ptr != out) { 665 // ReadBuffer() hasn't copied to |out| in this case. 666 memcpy(out, out_ptr, FRAME_LEN * sizeof(int16_t)); 667 } 668 669 return 0; 670 } 671 672 // WebRtcAecm_AsymFilt(...) 673 // 674 // Performs asymmetric filtering. 675 // 676 // Inputs: 677 // - filtOld : Previous filtered value. 678 // - inVal : New input value. 679 // - stepSizePos : Step size when we have a positive contribution. 680 // - stepSizeNeg : Step size when we have a negative contribution. 681 // 682 // Output: 683 // 684 // Return: - Filtered value. 685 // 686 int16_t WebRtcAecm_AsymFilt(const int16_t filtOld, const int16_t inVal, 687 const int16_t stepSizePos, 688 const int16_t stepSizeNeg) 689 { 690 int16_t retVal; 691 692 if ((filtOld == WEBRTC_SPL_WORD16_MAX) | (filtOld == WEBRTC_SPL_WORD16_MIN)) 693 { 694 return inVal; 695 } 696 retVal = filtOld; 697 if (filtOld > inVal) 698 { 699 retVal -= WEBRTC_SPL_RSHIFT_W16(filtOld - inVal, stepSizeNeg); 700 } else 701 { 702 retVal += WEBRTC_SPL_RSHIFT_W16(inVal - filtOld, stepSizePos); 703 } 704 705 return retVal; 706 } 707 708 // ExtractFractionPart(a, zeros) 709 // 710 // returns the fraction part of |a|, with |zeros| number of leading zeros, as an 711 // int16_t scaled to Q8. There is no sanity check of |a| in the sense that the 712 // number of zeros match. 713 static int16_t ExtractFractionPart(uint32_t a, int zeros) { 714 return (int16_t)(((a << zeros) & 0x7FFFFFFF) >> 23); 715 } 716 717 // WebRtcAecm_CalcEnergies(...) 718 // 719 // This function calculates the log of energies for nearend, farend and estimated 720 // echoes. There is also an update of energy decision levels, i.e. internal VAD. 721 // 722 // 723 // @param aecm [i/o] Handle of the AECM instance. 724 // @param far_spectrum [in] Pointer to farend spectrum. 725 // @param far_q [in] Q-domain of farend spectrum. 726 // @param nearEner [in] Near end energy for current block in 727 // Q(aecm->dfaQDomain). 728 // @param echoEst [out] Estimated echo in Q(xfa_q+RESOLUTION_CHANNEL16). 729 // 730 void WebRtcAecm_CalcEnergies(AecmCore_t * aecm, 731 const uint16_t* far_spectrum, 732 const int16_t far_q, 733 const uint32_t nearEner, 734 int32_t * echoEst) 735 { 736 // Local variables 737 uint32_t tmpAdapt = 0; 738 uint32_t tmpStored = 0; 739 uint32_t tmpFar = 0; 740 741 int i; 742 743 int16_t zeros, frac; 744 int16_t tmp16; 745 int16_t increase_max_shifts = 4; 746 int16_t decrease_max_shifts = 11; 747 int16_t increase_min_shifts = 11; 748 int16_t decrease_min_shifts = 3; 749 int16_t kLogLowValue = WEBRTC_SPL_LSHIFT_W16(PART_LEN_SHIFT, 7); 750 751 // Get log of near end energy and store in buffer 752 753 // Shift buffer 754 memmove(aecm->nearLogEnergy + 1, aecm->nearLogEnergy, 755 sizeof(int16_t) * (MAX_BUF_LEN - 1)); 756 757 // Logarithm of integrated magnitude spectrum (nearEner) 758 tmp16 = kLogLowValue; 759 if (nearEner) 760 { 761 zeros = WebRtcSpl_NormU32(nearEner); 762 frac = ExtractFractionPart(nearEner, zeros); 763 // log2 in Q8 764 tmp16 += WEBRTC_SPL_LSHIFT_W16((31 - zeros), 8) + frac; 765 tmp16 -= WEBRTC_SPL_LSHIFT_W16(aecm->dfaNoisyQDomain, 8); 766 } 767 aecm->nearLogEnergy[0] = tmp16; 768 // END: Get log of near end energy 769 770 WebRtcAecm_CalcLinearEnergies(aecm, far_spectrum, echoEst, &tmpFar, &tmpAdapt, &tmpStored); 771 772 // Shift buffers 773 memmove(aecm->echoAdaptLogEnergy + 1, aecm->echoAdaptLogEnergy, 774 sizeof(int16_t) * (MAX_BUF_LEN - 1)); 775 memmove(aecm->echoStoredLogEnergy + 1, aecm->echoStoredLogEnergy, 776 sizeof(int16_t) * (MAX_BUF_LEN - 1)); 777 778 // Logarithm of delayed far end energy 779 tmp16 = kLogLowValue; 780 if (tmpFar) 781 { 782 zeros = WebRtcSpl_NormU32(tmpFar); 783 frac = ExtractFractionPart(tmpFar, zeros); 784 // log2 in Q8 785 tmp16 += WEBRTC_SPL_LSHIFT_W16((31 - zeros), 8) + frac; 786 tmp16 -= WEBRTC_SPL_LSHIFT_W16(far_q, 8); 787 } 788 aecm->farLogEnergy = tmp16; 789 790 // Logarithm of estimated echo energy through adapted channel 791 tmp16 = kLogLowValue; 792 if (tmpAdapt) 793 { 794 zeros = WebRtcSpl_NormU32(tmpAdapt); 795 frac = ExtractFractionPart(tmpAdapt, zeros); 796 //log2 in Q8 797 tmp16 += WEBRTC_SPL_LSHIFT_W16((31 - zeros), 8) + frac; 798 tmp16 -= WEBRTC_SPL_LSHIFT_W16(RESOLUTION_CHANNEL16 + far_q, 8); 799 } 800 aecm->echoAdaptLogEnergy[0] = tmp16; 801 802 // Logarithm of estimated echo energy through stored channel 803 tmp16 = kLogLowValue; 804 if (tmpStored) 805 { 806 zeros = WebRtcSpl_NormU32(tmpStored); 807 frac = ExtractFractionPart(tmpStored, zeros); 808 //log2 in Q8 809 tmp16 += WEBRTC_SPL_LSHIFT_W16((31 - zeros), 8) + frac; 810 tmp16 -= WEBRTC_SPL_LSHIFT_W16(RESOLUTION_CHANNEL16 + far_q, 8); 811 } 812 aecm->echoStoredLogEnergy[0] = tmp16; 813 814 // Update farend energy levels (min, max, vad, mse) 815 if (aecm->farLogEnergy > FAR_ENERGY_MIN) 816 { 817 if (aecm->startupState == 0) 818 { 819 increase_max_shifts = 2; 820 decrease_min_shifts = 2; 821 increase_min_shifts = 8; 822 } 823 824 aecm->farEnergyMin = WebRtcAecm_AsymFilt(aecm->farEnergyMin, aecm->farLogEnergy, 825 increase_min_shifts, decrease_min_shifts); 826 aecm->farEnergyMax = WebRtcAecm_AsymFilt(aecm->farEnergyMax, aecm->farLogEnergy, 827 increase_max_shifts, decrease_max_shifts); 828 aecm->farEnergyMaxMin = (aecm->farEnergyMax - aecm->farEnergyMin); 829 830 // Dynamic VAD region size 831 tmp16 = 2560 - aecm->farEnergyMin; 832 if (tmp16 > 0) 833 { 834 tmp16 = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(tmp16, FAR_ENERGY_VAD_REGION, 9); 835 } else 836 { 837 tmp16 = 0; 838 } 839 tmp16 += FAR_ENERGY_VAD_REGION; 840 841 if ((aecm->startupState == 0) | (aecm->vadUpdateCount > 1024)) 842 { 843 // In startup phase or VAD update halted 844 aecm->farEnergyVAD = aecm->farEnergyMin + tmp16; 845 } else 846 { 847 if (aecm->farEnergyVAD > aecm->farLogEnergy) 848 { 849 aecm->farEnergyVAD += WEBRTC_SPL_RSHIFT_W16(aecm->farLogEnergy + 850 tmp16 - 851 aecm->farEnergyVAD, 852 6); 853 aecm->vadUpdateCount = 0; 854 } else 855 { 856 aecm->vadUpdateCount++; 857 } 858 } 859 // Put MSE threshold higher than VAD 860 aecm->farEnergyMSE = aecm->farEnergyVAD + (1 << 8); 861 } 862 863 // Update VAD variables 864 if (aecm->farLogEnergy > aecm->farEnergyVAD) 865 { 866 if ((aecm->startupState == 0) | (aecm->farEnergyMaxMin > FAR_ENERGY_DIFF)) 867 { 868 // We are in startup or have significant dynamics in input speech level 869 aecm->currentVADValue = 1; 870 } 871 } else 872 { 873 aecm->currentVADValue = 0; 874 } 875 if ((aecm->currentVADValue) && (aecm->firstVAD)) 876 { 877 aecm->firstVAD = 0; 878 if (aecm->echoAdaptLogEnergy[0] > aecm->nearLogEnergy[0]) 879 { 880 // The estimated echo has higher energy than the near end signal. 881 // This means that the initialization was too aggressive. Scale 882 // down by a factor 8 883 for (i = 0; i < PART_LEN1; i++) 884 { 885 aecm->channelAdapt16[i] >>= 3; 886 } 887 // Compensate the adapted echo energy level accordingly. 888 aecm->echoAdaptLogEnergy[0] -= (3 << 8); 889 aecm->firstVAD = 1; 890 } 891 } 892 } 893 894 // WebRtcAecm_CalcStepSize(...) 895 // 896 // This function calculates the step size used in channel estimation 897 // 898 // 899 // @param aecm [in] Handle of the AECM instance. 900 // @param mu [out] (Return value) Stepsize in log2(), i.e. number of shifts. 901 // 902 // 903 int16_t WebRtcAecm_CalcStepSize(AecmCore_t * const aecm) 904 { 905 906 int32_t tmp32; 907 int16_t tmp16; 908 int16_t mu = MU_MAX; 909 910 // Here we calculate the step size mu used in the 911 // following NLMS based Channel estimation algorithm 912 if (!aecm->currentVADValue) 913 { 914 // Far end energy level too low, no channel update 915 mu = 0; 916 } else if (aecm->startupState > 0) 917 { 918 if (aecm->farEnergyMin >= aecm->farEnergyMax) 919 { 920 mu = MU_MIN; 921 } else 922 { 923 tmp16 = (aecm->farLogEnergy - aecm->farEnergyMin); 924 tmp32 = WEBRTC_SPL_MUL_16_16(tmp16, MU_DIFF); 925 tmp32 = WebRtcSpl_DivW32W16(tmp32, aecm->farEnergyMaxMin); 926 mu = MU_MIN - 1 - (int16_t)(tmp32); 927 // The -1 is an alternative to rounding. This way we get a larger 928 // stepsize, so we in some sense compensate for truncation in NLMS 929 } 930 if (mu < MU_MAX) 931 { 932 mu = MU_MAX; // Equivalent with maximum step size of 2^-MU_MAX 933 } 934 } 935 936 return mu; 937 } 938 939 // WebRtcAecm_UpdateChannel(...) 940 // 941 // This function performs channel estimation. NLMS and decision on channel storage. 942 // 943 // 944 // @param aecm [i/o] Handle of the AECM instance. 945 // @param far_spectrum [in] Absolute value of the farend signal in Q(far_q) 946 // @param far_q [in] Q-domain of the farend signal 947 // @param dfa [in] Absolute value of the nearend signal (Q[aecm->dfaQDomain]) 948 // @param mu [in] NLMS step size. 949 // @param echoEst [i/o] Estimated echo in Q(far_q+RESOLUTION_CHANNEL16). 950 // 951 void WebRtcAecm_UpdateChannel(AecmCore_t * aecm, 952 const uint16_t* far_spectrum, 953 const int16_t far_q, 954 const uint16_t * const dfa, 955 const int16_t mu, 956 int32_t * echoEst) 957 { 958 959 uint32_t tmpU32no1, tmpU32no2; 960 int32_t tmp32no1, tmp32no2; 961 int32_t mseStored; 962 int32_t mseAdapt; 963 964 int i; 965 966 int16_t zerosFar, zerosNum, zerosCh, zerosDfa; 967 int16_t shiftChFar, shiftNum, shift2ResChan; 968 int16_t tmp16no1; 969 int16_t xfaQ, dfaQ; 970 971 // This is the channel estimation algorithm. It is base on NLMS but has a variable step 972 // length, which was calculated above. 973 if (mu) 974 { 975 for (i = 0; i < PART_LEN1; i++) 976 { 977 // Determine norm of channel and farend to make sure we don't get overflow in 978 // multiplication 979 zerosCh = WebRtcSpl_NormU32(aecm->channelAdapt32[i]); 980 zerosFar = WebRtcSpl_NormU32((uint32_t)far_spectrum[i]); 981 if (zerosCh + zerosFar > 31) 982 { 983 // Multiplication is safe 984 tmpU32no1 = WEBRTC_SPL_UMUL_32_16(aecm->channelAdapt32[i], 985 far_spectrum[i]); 986 shiftChFar = 0; 987 } else 988 { 989 // We need to shift down before multiplication 990 shiftChFar = 32 - zerosCh - zerosFar; 991 tmpU32no1 = WEBRTC_SPL_UMUL_32_16( 992 WEBRTC_SPL_RSHIFT_W32(aecm->channelAdapt32[i], shiftChFar), 993 far_spectrum[i]); 994 } 995 // Determine Q-domain of numerator 996 zerosNum = WebRtcSpl_NormU32(tmpU32no1); 997 if (dfa[i]) 998 { 999 zerosDfa = WebRtcSpl_NormU32((uint32_t)dfa[i]); 1000 } else 1001 { 1002 zerosDfa = 32; 1003 } 1004 tmp16no1 = zerosDfa - 2 + aecm->dfaNoisyQDomain - 1005 RESOLUTION_CHANNEL32 - far_q + shiftChFar; 1006 if (zerosNum > tmp16no1 + 1) 1007 { 1008 xfaQ = tmp16no1; 1009 dfaQ = zerosDfa - 2; 1010 } else 1011 { 1012 xfaQ = zerosNum - 2; 1013 dfaQ = RESOLUTION_CHANNEL32 + far_q - aecm->dfaNoisyQDomain - 1014 shiftChFar + xfaQ; 1015 } 1016 // Add in the same Q-domain 1017 tmpU32no1 = WEBRTC_SPL_SHIFT_W32(tmpU32no1, xfaQ); 1018 tmpU32no2 = WEBRTC_SPL_SHIFT_W32((uint32_t)dfa[i], dfaQ); 1019 tmp32no1 = (int32_t)tmpU32no2 - (int32_t)tmpU32no1; 1020 zerosNum = WebRtcSpl_NormW32(tmp32no1); 1021 if ((tmp32no1) && (far_spectrum[i] > (CHANNEL_VAD << far_q))) 1022 { 1023 // 1024 // Update is needed 1025 // 1026 // This is what we would like to compute 1027 // 1028 // tmp32no1 = dfa[i] - (aecm->channelAdapt[i] * far_spectrum[i]) 1029 // tmp32norm = (i + 1) 1030 // aecm->channelAdapt[i] += (2^mu) * tmp32no1 1031 // / (tmp32norm * far_spectrum[i]) 1032 // 1033 1034 // Make sure we don't get overflow in multiplication. 1035 if (zerosNum + zerosFar > 31) 1036 { 1037 if (tmp32no1 > 0) 1038 { 1039 tmp32no2 = (int32_t)WEBRTC_SPL_UMUL_32_16(tmp32no1, 1040 far_spectrum[i]); 1041 } else 1042 { 1043 tmp32no2 = -(int32_t)WEBRTC_SPL_UMUL_32_16(-tmp32no1, 1044 far_spectrum[i]); 1045 } 1046 shiftNum = 0; 1047 } else 1048 { 1049 shiftNum = 32 - (zerosNum + zerosFar); 1050 if (tmp32no1 > 0) 1051 { 1052 tmp32no2 = (int32_t)WEBRTC_SPL_UMUL_32_16( 1053 WEBRTC_SPL_RSHIFT_W32(tmp32no1, shiftNum), 1054 far_spectrum[i]); 1055 } else 1056 { 1057 tmp32no2 = -(int32_t)WEBRTC_SPL_UMUL_32_16( 1058 WEBRTC_SPL_RSHIFT_W32(-tmp32no1, shiftNum), 1059 far_spectrum[i]); 1060 } 1061 } 1062 // Normalize with respect to frequency bin 1063 tmp32no2 = WebRtcSpl_DivW32W16(tmp32no2, i + 1); 1064 // Make sure we are in the right Q-domain 1065 shift2ResChan = shiftNum + shiftChFar - xfaQ - mu - ((30 - zerosFar) << 1); 1066 if (WebRtcSpl_NormW32(tmp32no2) < shift2ResChan) 1067 { 1068 tmp32no2 = WEBRTC_SPL_WORD32_MAX; 1069 } else 1070 { 1071 tmp32no2 = WEBRTC_SPL_SHIFT_W32(tmp32no2, shift2ResChan); 1072 } 1073 aecm->channelAdapt32[i] = 1074 WebRtcSpl_AddSatW32(aecm->channelAdapt32[i], tmp32no2); 1075 if (aecm->channelAdapt32[i] < 0) 1076 { 1077 // We can never have negative channel gain 1078 aecm->channelAdapt32[i] = 0; 1079 } 1080 aecm->channelAdapt16[i] 1081 = (int16_t)WEBRTC_SPL_RSHIFT_W32(aecm->channelAdapt32[i], 16); 1082 } 1083 } 1084 } 1085 // END: Adaptive channel update 1086 1087 // Determine if we should store or restore the channel 1088 if ((aecm->startupState == 0) & (aecm->currentVADValue)) 1089 { 1090 // During startup we store the channel every block, 1091 // and we recalculate echo estimate 1092 WebRtcAecm_StoreAdaptiveChannel(aecm, far_spectrum, echoEst); 1093 } else 1094 { 1095 if (aecm->farLogEnergy < aecm->farEnergyMSE) 1096 { 1097 aecm->mseChannelCount = 0; 1098 } else 1099 { 1100 aecm->mseChannelCount++; 1101 } 1102 // Enough data for validation. Store channel if we can. 1103 if (aecm->mseChannelCount >= (MIN_MSE_COUNT + 10)) 1104 { 1105 // We have enough data. 1106 // Calculate MSE of "Adapt" and "Stored" versions. 1107 // It is actually not MSE, but average absolute error. 1108 mseStored = 0; 1109 mseAdapt = 0; 1110 for (i = 0; i < MIN_MSE_COUNT; i++) 1111 { 1112 tmp32no1 = ((int32_t)aecm->echoStoredLogEnergy[i] 1113 - (int32_t)aecm->nearLogEnergy[i]); 1114 tmp32no2 = WEBRTC_SPL_ABS_W32(tmp32no1); 1115 mseStored += tmp32no2; 1116 1117 tmp32no1 = ((int32_t)aecm->echoAdaptLogEnergy[i] 1118 - (int32_t)aecm->nearLogEnergy[i]); 1119 tmp32no2 = WEBRTC_SPL_ABS_W32(tmp32no1); 1120 mseAdapt += tmp32no2; 1121 } 1122 if (((mseStored << MSE_RESOLUTION) < (MIN_MSE_DIFF * mseAdapt)) 1123 & ((aecm->mseStoredOld << MSE_RESOLUTION) < (MIN_MSE_DIFF 1124 * aecm->mseAdaptOld))) 1125 { 1126 // The stored channel has a significantly lower MSE than the adaptive one for 1127 // two consecutive calculations. Reset the adaptive channel. 1128 WebRtcAecm_ResetAdaptiveChannel(aecm); 1129 } else if (((MIN_MSE_DIFF * mseStored) > (mseAdapt << MSE_RESOLUTION)) & (mseAdapt 1130 < aecm->mseThreshold) & (aecm->mseAdaptOld < aecm->mseThreshold)) 1131 { 1132 // The adaptive channel has a significantly lower MSE than the stored one. 1133 // The MSE for the adaptive channel has also been low for two consecutive 1134 // calculations. Store the adaptive channel. 1135 WebRtcAecm_StoreAdaptiveChannel(aecm, far_spectrum, echoEst); 1136 1137 // Update threshold 1138 if (aecm->mseThreshold == WEBRTC_SPL_WORD32_MAX) 1139 { 1140 aecm->mseThreshold = (mseAdapt + aecm->mseAdaptOld); 1141 } else 1142 { 1143 aecm->mseThreshold += WEBRTC_SPL_MUL_16_16_RSFT(mseAdapt 1144 - WEBRTC_SPL_MUL_16_16_RSFT(aecm->mseThreshold, 5, 3), 205, 8); 1145 } 1146 1147 } 1148 1149 // Reset counter 1150 aecm->mseChannelCount = 0; 1151 1152 // Store the MSE values. 1153 aecm->mseStoredOld = mseStored; 1154 aecm->mseAdaptOld = mseAdapt; 1155 } 1156 } 1157 // END: Determine if we should store or reset channel estimate. 1158 } 1159 1160 // CalcSuppressionGain(...) 1161 // 1162 // This function calculates the suppression gain that is used in the Wiener filter. 1163 // 1164 // 1165 // @param aecm [i/n] Handle of the AECM instance. 1166 // @param supGain [out] (Return value) Suppression gain with which to scale the noise 1167 // level (Q14). 1168 // 1169 // 1170 int16_t WebRtcAecm_CalcSuppressionGain(AecmCore_t * const aecm) 1171 { 1172 int32_t tmp32no1; 1173 1174 int16_t supGain = SUPGAIN_DEFAULT; 1175 int16_t tmp16no1; 1176 int16_t dE = 0; 1177 1178 // Determine suppression gain used in the Wiener filter. The gain is based on a mix of far 1179 // end energy and echo estimation error. 1180 // Adjust for the far end signal level. A low signal level indicates no far end signal, 1181 // hence we set the suppression gain to 0 1182 if (!aecm->currentVADValue) 1183 { 1184 supGain = 0; 1185 } else 1186 { 1187 // Adjust for possible double talk. If we have large variations in estimation error we 1188 // likely have double talk (or poor channel). 1189 tmp16no1 = (aecm->nearLogEnergy[0] - aecm->echoStoredLogEnergy[0] - ENERGY_DEV_OFFSET); 1190 dE = WEBRTC_SPL_ABS_W16(tmp16no1); 1191 1192 if (dE < ENERGY_DEV_TOL) 1193 { 1194 // Likely no double talk. The better estimation, the more we can suppress signal. 1195 // Update counters 1196 if (dE < SUPGAIN_EPC_DT) 1197 { 1198 tmp32no1 = WEBRTC_SPL_MUL_16_16(aecm->supGainErrParamDiffAB, dE); 1199 tmp32no1 += (SUPGAIN_EPC_DT >> 1); 1200 tmp16no1 = (int16_t)WebRtcSpl_DivW32W16(tmp32no1, SUPGAIN_EPC_DT); 1201 supGain = aecm->supGainErrParamA - tmp16no1; 1202 } else 1203 { 1204 tmp32no1 = WEBRTC_SPL_MUL_16_16(aecm->supGainErrParamDiffBD, 1205 (ENERGY_DEV_TOL - dE)); 1206 tmp32no1 += ((ENERGY_DEV_TOL - SUPGAIN_EPC_DT) >> 1); 1207 tmp16no1 = (int16_t)WebRtcSpl_DivW32W16(tmp32no1, (ENERGY_DEV_TOL 1208 - SUPGAIN_EPC_DT)); 1209 supGain = aecm->supGainErrParamD + tmp16no1; 1210 } 1211 } else 1212 { 1213 // Likely in double talk. Use default value 1214 supGain = aecm->supGainErrParamD; 1215 } 1216 } 1217 1218 if (supGain > aecm->supGainOld) 1219 { 1220 tmp16no1 = supGain; 1221 } else 1222 { 1223 tmp16no1 = aecm->supGainOld; 1224 } 1225 aecm->supGainOld = supGain; 1226 if (tmp16no1 < aecm->supGain) 1227 { 1228 aecm->supGain += (int16_t)((tmp16no1 - aecm->supGain) >> 4); 1229 } else 1230 { 1231 aecm->supGain += (int16_t)((tmp16no1 - aecm->supGain) >> 4); 1232 } 1233 1234 // END: Update suppression gain 1235 1236 return aecm->supGain; 1237 } 1238 1239 void WebRtcAecm_BufferFarFrame(AecmCore_t* const aecm, 1240 const int16_t* const farend, 1241 const int farLen) 1242 { 1243 int writeLen = farLen, writePos = 0; 1244 1245 // Check if the write position must be wrapped 1246 while (aecm->farBufWritePos + writeLen > FAR_BUF_LEN) 1247 { 1248 // Write to remaining buffer space before wrapping 1249 writeLen = FAR_BUF_LEN - aecm->farBufWritePos; 1250 memcpy(aecm->farBuf + aecm->farBufWritePos, farend + writePos, 1251 sizeof(int16_t) * writeLen); 1252 aecm->farBufWritePos = 0; 1253 writePos = writeLen; 1254 writeLen = farLen - writeLen; 1255 } 1256 1257 memcpy(aecm->farBuf + aecm->farBufWritePos, farend + writePos, 1258 sizeof(int16_t) * writeLen); 1259 aecm->farBufWritePos += writeLen; 1260 } 1261 1262 void WebRtcAecm_FetchFarFrame(AecmCore_t * const aecm, int16_t * const farend, 1263 const int farLen, const int knownDelay) 1264 { 1265 int readLen = farLen; 1266 int readPos = 0; 1267 int delayChange = knownDelay - aecm->lastKnownDelay; 1268 1269 aecm->farBufReadPos -= delayChange; 1270 1271 // Check if delay forces a read position wrap 1272 while (aecm->farBufReadPos < 0) 1273 { 1274 aecm->farBufReadPos += FAR_BUF_LEN; 1275 } 1276 while (aecm->farBufReadPos > FAR_BUF_LEN - 1) 1277 { 1278 aecm->farBufReadPos -= FAR_BUF_LEN; 1279 } 1280 1281 aecm->lastKnownDelay = knownDelay; 1282 1283 // Check if read position must be wrapped 1284 while (aecm->farBufReadPos + readLen > FAR_BUF_LEN) 1285 { 1286 1287 // Read from remaining buffer space before wrapping 1288 readLen = FAR_BUF_LEN - aecm->farBufReadPos; 1289 memcpy(farend + readPos, aecm->farBuf + aecm->farBufReadPos, 1290 sizeof(int16_t) * readLen); 1291 aecm->farBufReadPos = 0; 1292 readPos = readLen; 1293 readLen = farLen - readLen; 1294 } 1295 memcpy(farend + readPos, aecm->farBuf + aecm->farBufReadPos, 1296 sizeof(int16_t) * readLen); 1297 aecm->farBufReadPos += readLen; 1298 } 1299