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