1 /* 2 * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 /* analog_agc.c 12 * 13 * Using a feedback system, determines an appropriate analog volume level 14 * given an input signal and current volume level. Targets a conservative 15 * signal level and is intended for use with a digital AGC to apply 16 * additional gain. 17 * 18 */ 19 20 #include <assert.h> 21 #include <stdlib.h> 22 #ifdef AGC_DEBUG //test log 23 #include <stdio.h> 24 #endif 25 #include "analog_agc.h" 26 27 /* The slope of in Q13*/ 28 static const WebRtc_Word16 kSlope1[8] = {21793, 12517, 7189, 4129, 2372, 1362, 472, 78}; 29 30 /* The offset in Q14 */ 31 static const WebRtc_Word16 kOffset1[8] = {25395, 23911, 22206, 20737, 19612, 18805, 17951, 32 17367}; 33 34 /* The slope of in Q13*/ 35 static const WebRtc_Word16 kSlope2[8] = {2063, 1731, 1452, 1218, 1021, 857, 597, 337}; 36 37 /* The offset in Q14 */ 38 static const WebRtc_Word16 kOffset2[8] = {18432, 18379, 18290, 18177, 18052, 17920, 17670, 39 17286}; 40 41 static const WebRtc_Word16 kMuteGuardTimeMs = 8000; 42 static const WebRtc_Word16 kInitCheck = 42; 43 44 /* Default settings if config is not used */ 45 #define AGC_DEFAULT_TARGET_LEVEL 3 46 #define AGC_DEFAULT_COMP_GAIN 9 47 /* This is the target level for the analog part in ENV scale. To convert to RMS scale you 48 * have to add OFFSET_ENV_TO_RMS. 49 */ 50 #define ANALOG_TARGET_LEVEL 11 51 #define ANALOG_TARGET_LEVEL_2 5 // ANALOG_TARGET_LEVEL / 2 52 /* Offset between RMS scale (analog part) and ENV scale (digital part). This value actually 53 * varies with the FIXED_ANALOG_TARGET_LEVEL, hence we should in the future replace it with 54 * a table. 55 */ 56 #define OFFSET_ENV_TO_RMS 9 57 /* The reference input level at which the digital part gives an output of targetLevelDbfs 58 * (desired level) if we have no compression gain. This level should be set high enough not 59 * to compress the peaks due to the dynamics. 60 */ 61 #define DIGITAL_REF_AT_0_COMP_GAIN 4 62 /* Speed of reference level decrease. 63 */ 64 #define DIFF_REF_TO_ANALOG 5 65 66 #ifdef MIC_LEVEL_FEEDBACK 67 #define NUM_BLOCKS_IN_SAT_BEFORE_CHANGE_TARGET 7 68 #endif 69 /* Size of analog gain table */ 70 #define GAIN_TBL_LEN 32 71 /* Matlab code: 72 * fprintf(1, '\t%i, %i, %i, %i,\n', round(10.^(linspace(0,10,32)/20) * 2^12)); 73 */ 74 /* Q12 */ 75 static const WebRtc_UWord16 kGainTableAnalog[GAIN_TBL_LEN] = {4096, 4251, 4412, 4579, 4752, 76 4932, 5118, 5312, 5513, 5722, 5938, 6163, 6396, 6638, 6889, 7150, 7420, 7701, 7992, 77 8295, 8609, 8934, 9273, 9623, 9987, 10365, 10758, 11165, 11587, 12025, 12480, 12953}; 78 79 /* Gain/Suppression tables for virtual Mic (in Q10) */ 80 static const WebRtc_UWord16 kGainTableVirtualMic[128] = {1052, 1081, 1110, 1141, 1172, 1204, 81 1237, 1271, 1305, 1341, 1378, 1416, 1454, 1494, 1535, 1577, 1620, 1664, 1710, 1757, 82 1805, 1854, 1905, 1957, 2010, 2065, 2122, 2180, 2239, 2301, 2364, 2428, 2495, 2563, 83 2633, 2705, 2779, 2855, 2933, 3013, 3096, 3180, 3267, 3357, 3449, 3543, 3640, 3739, 84 3842, 3947, 4055, 4166, 4280, 4397, 4517, 4640, 4767, 4898, 5032, 5169, 5311, 5456, 85 5605, 5758, 5916, 6078, 6244, 6415, 6590, 6770, 6956, 7146, 7341, 7542, 7748, 7960, 86 8178, 8402, 8631, 8867, 9110, 9359, 9615, 9878, 10148, 10426, 10711, 11004, 11305, 87 11614, 11932, 12258, 12593, 12938, 13292, 13655, 14029, 14412, 14807, 15212, 15628, 88 16055, 16494, 16945, 17409, 17885, 18374, 18877, 19393, 19923, 20468, 21028, 21603, 89 22194, 22801, 23425, 24065, 24724, 25400, 26095, 26808, 27541, 28295, 29069, 29864, 90 30681, 31520, 32382}; 91 static const WebRtc_UWord16 kSuppressionTableVirtualMic[128] = {1024, 1006, 988, 970, 952, 92 935, 918, 902, 886, 870, 854, 839, 824, 809, 794, 780, 766, 752, 739, 726, 713, 700, 93 687, 675, 663, 651, 639, 628, 616, 605, 594, 584, 573, 563, 553, 543, 533, 524, 514, 94 505, 496, 487, 478, 470, 461, 453, 445, 437, 429, 421, 414, 406, 399, 392, 385, 378, 95 371, 364, 358, 351, 345, 339, 333, 327, 321, 315, 309, 304, 298, 293, 288, 283, 278, 96 273, 268, 263, 258, 254, 249, 244, 240, 236, 232, 227, 223, 219, 215, 211, 208, 204, 97 200, 197, 193, 190, 186, 183, 180, 176, 173, 170, 167, 164, 161, 158, 155, 153, 150, 98 147, 145, 142, 139, 137, 134, 132, 130, 127, 125, 123, 121, 118, 116, 114, 112, 110, 99 108, 106, 104, 102}; 100 101 /* Table for target energy levels. Values in Q(-7) 102 * Matlab code 103 * targetLevelTable = fprintf('%d,\t%d,\t%d,\t%d,\n', round((32767*10.^(-(0:63)'/20)).^2*16/2^7) */ 104 105 static const WebRtc_Word32 kTargetLevelTable[64] = {134209536, 106606424, 84680493, 67264106, 106 53429779, 42440782, 33711911, 26778323, 21270778, 16895980, 13420954, 10660642, 107 8468049, 6726411, 5342978, 4244078, 3371191, 2677832, 2127078, 1689598, 1342095, 108 1066064, 846805, 672641, 534298, 424408, 337119, 267783, 212708, 168960, 134210, 109 106606, 84680, 67264, 53430, 42441, 33712, 26778, 21271, 16896, 13421, 10661, 8468, 110 6726, 5343, 4244, 3371, 2678, 2127, 1690, 1342, 1066, 847, 673, 534, 424, 337, 268, 111 213, 169, 134, 107, 85, 67}; 112 113 int WebRtcAgc_AddMic(void *state, WebRtc_Word16 *in_mic, WebRtc_Word16 *in_mic_H, 114 WebRtc_Word16 samples) 115 { 116 WebRtc_Word32 nrg, max_nrg, sample, tmp32; 117 WebRtc_Word32 *ptr; 118 WebRtc_UWord16 targetGainIdx, gain; 119 WebRtc_Word16 i, n, L, M, subFrames, tmp16, tmp_speech[16]; 120 Agc_t *stt; 121 stt = (Agc_t *)state; 122 123 //default/initial values corresponding to 10ms for wb and swb 124 M = 10; 125 L = 16; 126 subFrames = 160; 127 128 if (stt->fs == 8000) 129 { 130 if (samples == 80) 131 { 132 subFrames = 80; 133 M = 10; 134 L = 8; 135 } else if (samples == 160) 136 { 137 subFrames = 80; 138 M = 20; 139 L = 8; 140 } else 141 { 142 #ifdef AGC_DEBUG //test log 143 fprintf(stt->fpt, 144 "AGC->add_mic, frame %d: Invalid number of samples\n\n", 145 (stt->fcount + 1)); 146 #endif 147 return -1; 148 } 149 } else if (stt->fs == 16000) 150 { 151 if (samples == 160) 152 { 153 subFrames = 160; 154 M = 10; 155 L = 16; 156 } else if (samples == 320) 157 { 158 subFrames = 160; 159 M = 20; 160 L = 16; 161 } else 162 { 163 #ifdef AGC_DEBUG //test log 164 fprintf(stt->fpt, 165 "AGC->add_mic, frame %d: Invalid number of samples\n\n", 166 (stt->fcount + 1)); 167 #endif 168 return -1; 169 } 170 } else if (stt->fs == 32000) 171 { 172 /* SWB is processed as 160 sample for L and H bands */ 173 if (samples == 160) 174 { 175 subFrames = 160; 176 M = 10; 177 L = 16; 178 } else 179 { 180 #ifdef AGC_DEBUG 181 fprintf(stt->fpt, 182 "AGC->add_mic, frame %d: Invalid sample rate\n\n", 183 (stt->fcount + 1)); 184 #endif 185 return -1; 186 } 187 } 188 189 /* Check for valid pointers based on sampling rate */ 190 if ((stt->fs == 32000) && (in_mic_H == NULL)) 191 { 192 return -1; 193 } 194 /* Check for valid pointer for low band */ 195 if (in_mic == NULL) 196 { 197 return -1; 198 } 199 200 /* apply slowly varying digital gain */ 201 if (stt->micVol > stt->maxAnalog) 202 { 203 /* Q1 */ 204 tmp16 = (WebRtc_Word16)(stt->micVol - stt->maxAnalog); 205 tmp32 = WEBRTC_SPL_MUL_16_16(GAIN_TBL_LEN - 1, tmp16); 206 tmp16 = (WebRtc_Word16)(stt->maxLevel - stt->maxAnalog); 207 targetGainIdx = (WebRtc_UWord16)WEBRTC_SPL_DIV(tmp32, tmp16); 208 assert(targetGainIdx < GAIN_TBL_LEN); 209 210 /* Increment through the table towards the target gain. 211 * If micVol drops below maxAnalog, we allow the gain 212 * to be dropped immediately. */ 213 if (stt->gainTableIdx < targetGainIdx) 214 { 215 stt->gainTableIdx++; 216 } else if (stt->gainTableIdx > targetGainIdx) 217 { 218 stt->gainTableIdx--; 219 } 220 221 /* Q12 */ 222 gain = kGainTableAnalog[stt->gainTableIdx]; 223 224 for (i = 0; i < samples; i++) 225 { 226 // For lower band 227 tmp32 = WEBRTC_SPL_MUL_16_U16(in_mic[i], gain); 228 sample = WEBRTC_SPL_RSHIFT_W32(tmp32, 12); 229 if (sample > 32767) 230 { 231 in_mic[i] = 32767; 232 } else if (sample < -32768) 233 { 234 in_mic[i] = -32768; 235 } else 236 { 237 in_mic[i] = (WebRtc_Word16)sample; 238 } 239 240 // For higher band 241 if (stt->fs == 32000) 242 { 243 tmp32 = WEBRTC_SPL_MUL_16_U16(in_mic_H[i], gain); 244 sample = WEBRTC_SPL_RSHIFT_W32(tmp32, 12); 245 if (sample > 32767) 246 { 247 in_mic_H[i] = 32767; 248 } else if (sample < -32768) 249 { 250 in_mic_H[i] = -32768; 251 } else 252 { 253 in_mic_H[i] = (WebRtc_Word16)sample; 254 } 255 } 256 } 257 } else 258 { 259 stt->gainTableIdx = 0; 260 } 261 262 /* compute envelope */ 263 if ((M == 10) && (stt->inQueue > 0)) 264 { 265 ptr = stt->env[1]; 266 } else 267 { 268 ptr = stt->env[0]; 269 } 270 271 for (i = 0; i < M; i++) 272 { 273 /* iterate over samples */ 274 max_nrg = 0; 275 for (n = 0; n < L; n++) 276 { 277 nrg = WEBRTC_SPL_MUL_16_16(in_mic[i * L + n], in_mic[i * L + n]); 278 if (nrg > max_nrg) 279 { 280 max_nrg = nrg; 281 } 282 } 283 ptr[i] = max_nrg; 284 } 285 286 /* compute energy */ 287 if ((M == 10) && (stt->inQueue > 0)) 288 { 289 ptr = stt->Rxx16w32_array[1]; 290 } else 291 { 292 ptr = stt->Rxx16w32_array[0]; 293 } 294 295 for (i = 0; i < WEBRTC_SPL_RSHIFT_W16(M, 1); i++) 296 { 297 if (stt->fs == 16000) 298 { 299 WebRtcSpl_DownsampleBy2(&in_mic[i * 32], 32, tmp_speech, stt->filterState); 300 } else 301 { 302 memcpy(tmp_speech, &in_mic[i * 16], 16 * sizeof(short)); 303 } 304 /* Compute energy in blocks of 16 samples */ 305 ptr[i] = WebRtcSpl_DotProductWithScale(tmp_speech, tmp_speech, 16, 4); 306 } 307 308 /* update queue information */ 309 if ((stt->inQueue == 0) && (M == 10)) 310 { 311 stt->inQueue = 1; 312 } else 313 { 314 stt->inQueue = 2; 315 } 316 317 /* call VAD (use low band only) */ 318 for (i = 0; i < samples; i += subFrames) 319 { 320 WebRtcAgc_ProcessVad(&stt->vadMic, &in_mic[i], subFrames); 321 } 322 323 return 0; 324 } 325 326 int WebRtcAgc_AddFarend(void *state, const WebRtc_Word16 *in_far, WebRtc_Word16 samples) 327 { 328 WebRtc_Word32 errHandle = 0; 329 WebRtc_Word16 i, subFrames; 330 Agc_t *stt; 331 stt = (Agc_t *)state; 332 333 if (stt == NULL) 334 { 335 return -1; 336 } 337 338 if (stt->fs == 8000) 339 { 340 if ((samples != 80) && (samples != 160)) 341 { 342 #ifdef AGC_DEBUG //test log 343 fprintf(stt->fpt, 344 "AGC->add_far_end, frame %d: Invalid number of samples\n\n", 345 stt->fcount); 346 #endif 347 return -1; 348 } 349 subFrames = 80; 350 } else if (stt->fs == 16000) 351 { 352 if ((samples != 160) && (samples != 320)) 353 { 354 #ifdef AGC_DEBUG //test log 355 fprintf(stt->fpt, 356 "AGC->add_far_end, frame %d: Invalid number of samples\n\n", 357 stt->fcount); 358 #endif 359 return -1; 360 } 361 subFrames = 160; 362 } else if (stt->fs == 32000) 363 { 364 if ((samples != 160) && (samples != 320)) 365 { 366 #ifdef AGC_DEBUG //test log 367 fprintf(stt->fpt, 368 "AGC->add_far_end, frame %d: Invalid number of samples\n\n", 369 stt->fcount); 370 #endif 371 return -1; 372 } 373 subFrames = 160; 374 } else 375 { 376 #ifdef AGC_DEBUG //test log 377 fprintf(stt->fpt, 378 "AGC->add_far_end, frame %d: Invalid sample rate\n\n", 379 stt->fcount + 1); 380 #endif 381 return -1; 382 } 383 384 for (i = 0; i < samples; i += subFrames) 385 { 386 errHandle += WebRtcAgc_AddFarendToDigital(&stt->digitalAgc, &in_far[i], subFrames); 387 } 388 389 return errHandle; 390 } 391 392 int WebRtcAgc_VirtualMic(void *agcInst, WebRtc_Word16 *in_near, WebRtc_Word16 *in_near_H, 393 WebRtc_Word16 samples, WebRtc_Word32 micLevelIn, 394 WebRtc_Word32 *micLevelOut) 395 { 396 WebRtc_Word32 tmpFlt, micLevelTmp, gainIdx; 397 WebRtc_UWord16 gain; 398 WebRtc_Word16 ii; 399 Agc_t *stt; 400 401 WebRtc_UWord32 nrg; 402 WebRtc_Word16 sampleCntr; 403 WebRtc_UWord32 frameNrg = 0; 404 WebRtc_UWord32 frameNrgLimit = 5500; 405 WebRtc_Word16 numZeroCrossing = 0; 406 const WebRtc_Word16 kZeroCrossingLowLim = 15; 407 const WebRtc_Word16 kZeroCrossingHighLim = 20; 408 409 stt = (Agc_t *)agcInst; 410 411 /* 412 * Before applying gain decide if this is a low-level signal. 413 * The idea is that digital AGC will not adapt to low-level 414 * signals. 415 */ 416 if (stt->fs != 8000) 417 { 418 frameNrgLimit = frameNrgLimit << 1; 419 } 420 421 frameNrg = WEBRTC_SPL_MUL_16_16(in_near[0], in_near[0]); 422 for (sampleCntr = 1; sampleCntr < samples; sampleCntr++) 423 { 424 425 // increment frame energy if it is less than the limit 426 // the correct value of the energy is not important 427 if (frameNrg < frameNrgLimit) 428 { 429 nrg = WEBRTC_SPL_MUL_16_16(in_near[sampleCntr], in_near[sampleCntr]); 430 frameNrg += nrg; 431 } 432 433 // Count the zero crossings 434 numZeroCrossing += ((in_near[sampleCntr] ^ in_near[sampleCntr - 1]) < 0); 435 } 436 437 if ((frameNrg < 500) || (numZeroCrossing <= 5)) 438 { 439 stt->lowLevelSignal = 1; 440 } else if (numZeroCrossing <= kZeroCrossingLowLim) 441 { 442 stt->lowLevelSignal = 0; 443 } else if (frameNrg <= frameNrgLimit) 444 { 445 stt->lowLevelSignal = 1; 446 } else if (numZeroCrossing >= kZeroCrossingHighLim) 447 { 448 stt->lowLevelSignal = 1; 449 } else 450 { 451 stt->lowLevelSignal = 0; 452 } 453 454 micLevelTmp = WEBRTC_SPL_LSHIFT_W32(micLevelIn, stt->scale); 455 /* Set desired level */ 456 gainIdx = stt->micVol; 457 if (stt->micVol > stt->maxAnalog) 458 { 459 gainIdx = stt->maxAnalog; 460 } 461 if (micLevelTmp != stt->micRef) 462 { 463 /* Something has happened with the physical level, restart. */ 464 stt->micRef = micLevelTmp; 465 stt->micVol = 127; 466 *micLevelOut = 127; 467 stt->micGainIdx = 127; 468 gainIdx = 127; 469 } 470 /* Pre-process the signal to emulate the microphone level. */ 471 /* Take one step at a time in the gain table. */ 472 if (gainIdx > 127) 473 { 474 gain = kGainTableVirtualMic[gainIdx - 128]; 475 } else 476 { 477 gain = kSuppressionTableVirtualMic[127 - gainIdx]; 478 } 479 for (ii = 0; ii < samples; ii++) 480 { 481 tmpFlt = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_U16(in_near[ii], gain), 10); 482 if (tmpFlt > 32767) 483 { 484 tmpFlt = 32767; 485 gainIdx--; 486 if (gainIdx >= 127) 487 { 488 gain = kGainTableVirtualMic[gainIdx - 127]; 489 } else 490 { 491 gain = kSuppressionTableVirtualMic[127 - gainIdx]; 492 } 493 } 494 if (tmpFlt < -32768) 495 { 496 tmpFlt = -32768; 497 gainIdx--; 498 if (gainIdx >= 127) 499 { 500 gain = kGainTableVirtualMic[gainIdx - 127]; 501 } else 502 { 503 gain = kSuppressionTableVirtualMic[127 - gainIdx]; 504 } 505 } 506 in_near[ii] = (WebRtc_Word16)tmpFlt; 507 if (stt->fs == 32000) 508 { 509 tmpFlt = WEBRTC_SPL_MUL_16_U16(in_near_H[ii], gain); 510 tmpFlt = WEBRTC_SPL_RSHIFT_W32(tmpFlt, 10); 511 if (tmpFlt > 32767) 512 { 513 tmpFlt = 32767; 514 } 515 if (tmpFlt < -32768) 516 { 517 tmpFlt = -32768; 518 } 519 in_near_H[ii] = (WebRtc_Word16)tmpFlt; 520 } 521 } 522 /* Set the level we (finally) used */ 523 stt->micGainIdx = gainIdx; 524 // *micLevelOut = stt->micGainIdx; 525 *micLevelOut = WEBRTC_SPL_RSHIFT_W32(stt->micGainIdx, stt->scale); 526 /* Add to Mic as if it was the output from a true microphone */ 527 if (WebRtcAgc_AddMic(agcInst, in_near, in_near_H, samples) != 0) 528 { 529 return -1; 530 } 531 return 0; 532 } 533 534 void WebRtcAgc_UpdateAgcThresholds(Agc_t *stt) 535 { 536 537 WebRtc_Word16 tmp16; 538 #ifdef MIC_LEVEL_FEEDBACK 539 int zeros; 540 541 if (stt->micLvlSat) 542 { 543 /* Lower the analog target level since we have reached its maximum */ 544 zeros = WebRtcSpl_NormW32(stt->Rxx160_LPw32); 545 stt->targetIdxOffset = WEBRTC_SPL_RSHIFT_W16((3 * zeros) - stt->targetIdx - 2, 2); 546 } 547 #endif 548 549 /* Set analog target level in envelope dBOv scale */ 550 tmp16 = (DIFF_REF_TO_ANALOG * stt->compressionGaindB) + ANALOG_TARGET_LEVEL_2; 551 tmp16 = WebRtcSpl_DivW32W16ResW16((WebRtc_Word32)tmp16, ANALOG_TARGET_LEVEL); 552 stt->analogTarget = DIGITAL_REF_AT_0_COMP_GAIN + tmp16; 553 if (stt->analogTarget < DIGITAL_REF_AT_0_COMP_GAIN) 554 { 555 stt->analogTarget = DIGITAL_REF_AT_0_COMP_GAIN; 556 } 557 if (stt->agcMode == kAgcModeFixedDigital) 558 { 559 /* Adjust for different parameter interpretation in FixedDigital mode */ 560 stt->analogTarget = stt->compressionGaindB; 561 } 562 #ifdef MIC_LEVEL_FEEDBACK 563 stt->analogTarget += stt->targetIdxOffset; 564 #endif 565 /* Since the offset between RMS and ENV is not constant, we should make this into a 566 * table, but for now, we'll stick with a constant, tuned for the chosen analog 567 * target level. 568 */ 569 stt->targetIdx = ANALOG_TARGET_LEVEL + OFFSET_ENV_TO_RMS; 570 #ifdef MIC_LEVEL_FEEDBACK 571 stt->targetIdx += stt->targetIdxOffset; 572 #endif 573 /* Analog adaptation limits */ 574 /* analogTargetLevel = round((32767*10^(-targetIdx/20))^2*16/2^7) */ 575 stt->analogTargetLevel = RXX_BUFFER_LEN * kTargetLevelTable[stt->targetIdx]; /* ex. -20 dBov */ 576 stt->startUpperLimit = RXX_BUFFER_LEN * kTargetLevelTable[stt->targetIdx - 1];/* -19 dBov */ 577 stt->startLowerLimit = RXX_BUFFER_LEN * kTargetLevelTable[stt->targetIdx + 1];/* -21 dBov */ 578 stt->upperPrimaryLimit = RXX_BUFFER_LEN * kTargetLevelTable[stt->targetIdx - 2];/* -18 dBov */ 579 stt->lowerPrimaryLimit = RXX_BUFFER_LEN * kTargetLevelTable[stt->targetIdx + 2];/* -22 dBov */ 580 stt->upperSecondaryLimit = RXX_BUFFER_LEN * kTargetLevelTable[stt->targetIdx - 5];/* -15 dBov */ 581 stt->lowerSecondaryLimit = RXX_BUFFER_LEN * kTargetLevelTable[stt->targetIdx + 5];/* -25 dBov */ 582 stt->upperLimit = stt->startUpperLimit; 583 stt->lowerLimit = stt->startLowerLimit; 584 } 585 586 void WebRtcAgc_SaturationCtrl(Agc_t *stt, WebRtc_UWord8 *saturated, WebRtc_Word32 *env) 587 { 588 WebRtc_Word16 i, tmpW16; 589 590 /* Check if the signal is saturated */ 591 for (i = 0; i < 10; i++) 592 { 593 tmpW16 = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(env[i], 20); 594 if (tmpW16 > 875) 595 { 596 stt->envSum += tmpW16; 597 } 598 } 599 600 if (stt->envSum > 25000) 601 { 602 *saturated = 1; 603 stt->envSum = 0; 604 } 605 606 /* stt->envSum *= 0.99; */ 607 stt->envSum = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(stt->envSum, 608 (WebRtc_Word16)32440, 15); 609 } 610 611 void WebRtcAgc_ZeroCtrl(Agc_t *stt, WebRtc_Word32 *inMicLevel, WebRtc_Word32 *env) 612 { 613 WebRtc_Word16 i; 614 WebRtc_Word32 tmp32 = 0; 615 WebRtc_Word32 midVal; 616 617 /* Is the input signal zero? */ 618 for (i = 0; i < 10; i++) 619 { 620 tmp32 += env[i]; 621 } 622 623 /* Each block is allowed to have a few non-zero 624 * samples. 625 */ 626 if (tmp32 < 500) 627 { 628 stt->msZero += 10; 629 } else 630 { 631 stt->msZero = 0; 632 } 633 634 if (stt->muteGuardMs > 0) 635 { 636 stt->muteGuardMs -= 10; 637 } 638 639 if (stt->msZero > 500) 640 { 641 stt->msZero = 0; 642 643 /* Increase microphone level only if it's less than 50% */ 644 midVal = WEBRTC_SPL_RSHIFT_W32(stt->maxAnalog + stt->minLevel + 1, 1); 645 if (*inMicLevel < midVal) 646 { 647 /* *inMicLevel *= 1.1; */ 648 tmp32 = WEBRTC_SPL_MUL(1126, *inMicLevel); 649 *inMicLevel = WEBRTC_SPL_RSHIFT_W32(tmp32, 10); 650 /* Reduces risk of a muted mic repeatedly triggering excessive levels due 651 * to zero signal detection. */ 652 *inMicLevel = WEBRTC_SPL_MIN(*inMicLevel, stt->zeroCtrlMax); 653 stt->micVol = *inMicLevel; 654 } 655 656 #ifdef AGC_DEBUG //test log 657 fprintf(stt->fpt, 658 "\t\tAGC->zeroCntrl, frame %d: 500 ms under threshold, micVol:\n", 659 stt->fcount, stt->micVol); 660 #endif 661 662 stt->activeSpeech = 0; 663 stt->Rxx16_LPw32Max = 0; 664 665 /* The AGC has a tendency (due to problems with the VAD parameters), to 666 * vastly increase the volume after a muting event. This timer prevents 667 * upwards adaptation for a short period. */ 668 stt->muteGuardMs = kMuteGuardTimeMs; 669 } 670 } 671 672 void WebRtcAgc_SpeakerInactiveCtrl(Agc_t *stt) 673 { 674 /* Check if the near end speaker is inactive. 675 * If that is the case the VAD threshold is 676 * increased since the VAD speech model gets 677 * more sensitive to any sound after a long 678 * silence. 679 */ 680 681 WebRtc_Word32 tmp32; 682 WebRtc_Word16 vadThresh; 683 684 if (stt->vadMic.stdLongTerm < 2500) 685 { 686 stt->vadThreshold = 1500; 687 } else 688 { 689 vadThresh = kNormalVadThreshold; 690 if (stt->vadMic.stdLongTerm < 4500) 691 { 692 /* Scale between min and max threshold */ 693 vadThresh += WEBRTC_SPL_RSHIFT_W16(4500 - stt->vadMic.stdLongTerm, 1); 694 } 695 696 /* stt->vadThreshold = (31 * stt->vadThreshold + vadThresh) / 32; */ 697 tmp32 = (WebRtc_Word32)vadThresh; 698 tmp32 += WEBRTC_SPL_MUL_16_16((WebRtc_Word16)31, stt->vadThreshold); 699 stt->vadThreshold = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmp32, 5); 700 } 701 } 702 703 void WebRtcAgc_ExpCurve(WebRtc_Word16 volume, WebRtc_Word16 *index) 704 { 705 // volume in Q14 706 // index in [0-7] 707 /* 8 different curves */ 708 if (volume > 5243) 709 { 710 if (volume > 7864) 711 { 712 if (volume > 12124) 713 { 714 *index = 7; 715 } else 716 { 717 *index = 6; 718 } 719 } else 720 { 721 if (volume > 6554) 722 { 723 *index = 5; 724 } else 725 { 726 *index = 4; 727 } 728 } 729 } else 730 { 731 if (volume > 2621) 732 { 733 if (volume > 3932) 734 { 735 *index = 3; 736 } else 737 { 738 *index = 2; 739 } 740 } else 741 { 742 if (volume > 1311) 743 { 744 *index = 1; 745 } else 746 { 747 *index = 0; 748 } 749 } 750 } 751 } 752 753 WebRtc_Word32 WebRtcAgc_ProcessAnalog(void *state, WebRtc_Word32 inMicLevel, 754 WebRtc_Word32 *outMicLevel, 755 WebRtc_Word16 vadLogRatio, 756 WebRtc_Word16 echo, WebRtc_UWord8 *saturationWarning) 757 { 758 WebRtc_UWord32 tmpU32; 759 WebRtc_Word32 Rxx16w32, tmp32; 760 WebRtc_Word32 inMicLevelTmp, lastMicVol; 761 WebRtc_Word16 i; 762 WebRtc_UWord8 saturated = 0; 763 Agc_t *stt; 764 765 stt = (Agc_t *)state; 766 inMicLevelTmp = WEBRTC_SPL_LSHIFT_W32(inMicLevel, stt->scale); 767 768 if (inMicLevelTmp > stt->maxAnalog) 769 { 770 #ifdef AGC_DEBUG //test log 771 fprintf(stt->fpt, "\tAGC->ProcessAnalog, frame %d: micLvl > maxAnalog\n", stt->fcount); 772 #endif 773 return -1; 774 } else if (inMicLevelTmp < stt->minLevel) 775 { 776 #ifdef AGC_DEBUG //test log 777 fprintf(stt->fpt, "\tAGC->ProcessAnalog, frame %d: micLvl < minLevel\n", stt->fcount); 778 #endif 779 return -1; 780 } 781 782 if (stt->firstCall == 0) 783 { 784 WebRtc_Word32 tmpVol; 785 stt->firstCall = 1; 786 tmp32 = WEBRTC_SPL_RSHIFT_W32((stt->maxLevel - stt->minLevel) * (WebRtc_Word32)51, 9); 787 tmpVol = (stt->minLevel + tmp32); 788 789 /* If the mic level is very low at start, increase it! */ 790 if ((inMicLevelTmp < tmpVol) && (stt->agcMode == kAgcModeAdaptiveAnalog)) 791 { 792 inMicLevelTmp = tmpVol; 793 } 794 stt->micVol = inMicLevelTmp; 795 } 796 797 /* Set the mic level to the previous output value if there is digital input gain */ 798 if ((inMicLevelTmp == stt->maxAnalog) && (stt->micVol > stt->maxAnalog)) 799 { 800 inMicLevelTmp = stt->micVol; 801 } 802 803 /* If the mic level was manually changed to a very low value raise it! */ 804 if ((inMicLevelTmp != stt->micVol) && (inMicLevelTmp < stt->minOutput)) 805 { 806 tmp32 = WEBRTC_SPL_RSHIFT_W32((stt->maxLevel - stt->minLevel) * (WebRtc_Word32)51, 9); 807 inMicLevelTmp = (stt->minLevel + tmp32); 808 stt->micVol = inMicLevelTmp; 809 #ifdef MIC_LEVEL_FEEDBACK 810 //stt->numBlocksMicLvlSat = 0; 811 #endif 812 #ifdef AGC_DEBUG //test log 813 fprintf(stt->fpt, 814 "\tAGC->ProcessAnalog, frame %d: micLvl < minLevel by manual decrease, raise vol\n", 815 stt->fcount); 816 #endif 817 } 818 819 if (inMicLevelTmp != stt->micVol) 820 { 821 // Incoming level mismatch; update our level. 822 // This could be the case if the volume is changed manually, or if the 823 // sound device has a low volume resolution. 824 stt->micVol = inMicLevelTmp; 825 } 826 827 if (inMicLevelTmp > stt->maxLevel) 828 { 829 // Always allow the user to raise the volume above the maxLevel. 830 stt->maxLevel = inMicLevelTmp; 831 } 832 833 // Store last value here, after we've taken care of manual updates etc. 834 lastMicVol = stt->micVol; 835 836 /* Checks if the signal is saturated. Also a check if individual samples 837 * are larger than 12000 is done. If they are the counter for increasing 838 * the volume level is set to -100ms 839 */ 840 WebRtcAgc_SaturationCtrl(stt, &saturated, stt->env[0]); 841 842 /* The AGC is always allowed to lower the level if the signal is saturated */ 843 if (saturated == 1) 844 { 845 /* Lower the recording level 846 * Rxx160_LP is adjusted down because it is so slow it could 847 * cause the AGC to make wrong decisions. */ 848 /* stt->Rxx160_LPw32 *= 0.875; */ 849 stt->Rxx160_LPw32 = WEBRTC_SPL_MUL(WEBRTC_SPL_RSHIFT_W32(stt->Rxx160_LPw32, 3), 7); 850 851 stt->zeroCtrlMax = stt->micVol; 852 853 /* stt->micVol *= 0.903; */ 854 tmp32 = inMicLevelTmp - stt->minLevel; 855 tmpU32 = WEBRTC_SPL_UMUL(29591, (WebRtc_UWord32)(tmp32)); 856 stt->micVol = (WebRtc_Word32)WEBRTC_SPL_RSHIFT_U32(tmpU32, 15) + stt->minLevel; 857 if (stt->micVol > lastMicVol - 2) 858 { 859 stt->micVol = lastMicVol - 2; 860 } 861 inMicLevelTmp = stt->micVol; 862 863 #ifdef AGC_DEBUG //test log 864 fprintf(stt->fpt, 865 "\tAGC->ProcessAnalog, frame %d: saturated, micVol = %d\n", 866 stt->fcount, stt->micVol); 867 #endif 868 869 if (stt->micVol < stt->minOutput) 870 { 871 *saturationWarning = 1; 872 } 873 874 /* Reset counter for decrease of volume level to avoid 875 * decreasing too much. The saturation control can still 876 * lower the level if needed. */ 877 stt->msTooHigh = -100; 878 879 /* Enable the control mechanism to ensure that our measure, 880 * Rxx160_LP, is in the correct range. This must be done since 881 * the measure is very slow. */ 882 stt->activeSpeech = 0; 883 stt->Rxx16_LPw32Max = 0; 884 885 /* Reset to initial values */ 886 stt->msecSpeechInnerChange = kMsecSpeechInner; 887 stt->msecSpeechOuterChange = kMsecSpeechOuter; 888 stt->changeToSlowMode = 0; 889 890 stt->muteGuardMs = 0; 891 892 stt->upperLimit = stt->startUpperLimit; 893 stt->lowerLimit = stt->startLowerLimit; 894 #ifdef MIC_LEVEL_FEEDBACK 895 //stt->numBlocksMicLvlSat = 0; 896 #endif 897 } 898 899 /* Check if the input speech is zero. If so the mic volume 900 * is increased. On some computers the input is zero up as high 901 * level as 17% */ 902 WebRtcAgc_ZeroCtrl(stt, &inMicLevelTmp, stt->env[0]); 903 904 /* Check if the near end speaker is inactive. 905 * If that is the case the VAD threshold is 906 * increased since the VAD speech model gets 907 * more sensitive to any sound after a long 908 * silence. 909 */ 910 WebRtcAgc_SpeakerInactiveCtrl(stt); 911 912 for (i = 0; i < 5; i++) 913 { 914 /* Computed on blocks of 16 samples */ 915 916 Rxx16w32 = stt->Rxx16w32_array[0][i]; 917 918 /* Rxx160w32 in Q(-7) */ 919 tmp32 = WEBRTC_SPL_RSHIFT_W32(Rxx16w32 - stt->Rxx16_vectorw32[stt->Rxx16pos], 3); 920 stt->Rxx160w32 = stt->Rxx160w32 + tmp32; 921 stt->Rxx16_vectorw32[stt->Rxx16pos] = Rxx16w32; 922 923 /* Circular buffer */ 924 if (++(stt->Rxx16pos) == RXX_BUFFER_LEN) 925 { 926 stt->Rxx16pos = 0; 927 } 928 929 /* Rxx16_LPw32 in Q(-4) */ 930 tmp32 = WEBRTC_SPL_RSHIFT_W32(Rxx16w32 - stt->Rxx16_LPw32, kAlphaShortTerm); 931 stt->Rxx16_LPw32 = (stt->Rxx16_LPw32) + tmp32; 932 933 if (vadLogRatio > stt->vadThreshold) 934 { 935 /* Speech detected! */ 936 937 /* Check if Rxx160_LP is in the correct range. If 938 * it is too high/low then we set it to the maximum of 939 * Rxx16_LPw32 during the first 200ms of speech. 940 */ 941 if (stt->activeSpeech < 250) 942 { 943 stt->activeSpeech += 2; 944 945 if (stt->Rxx16_LPw32 > stt->Rxx16_LPw32Max) 946 { 947 stt->Rxx16_LPw32Max = stt->Rxx16_LPw32; 948 } 949 } else if (stt->activeSpeech == 250) 950 { 951 stt->activeSpeech += 2; 952 tmp32 = WEBRTC_SPL_RSHIFT_W32(stt->Rxx16_LPw32Max, 3); 953 stt->Rxx160_LPw32 = WEBRTC_SPL_MUL(tmp32, RXX_BUFFER_LEN); 954 } 955 956 tmp32 = WEBRTC_SPL_RSHIFT_W32(stt->Rxx160w32 - stt->Rxx160_LPw32, kAlphaLongTerm); 957 stt->Rxx160_LPw32 = stt->Rxx160_LPw32 + tmp32; 958 959 if (stt->Rxx160_LPw32 > stt->upperSecondaryLimit) 960 { 961 stt->msTooHigh += 2; 962 stt->msTooLow = 0; 963 stt->changeToSlowMode = 0; 964 965 if (stt->msTooHigh > stt->msecSpeechOuterChange) 966 { 967 stt->msTooHigh = 0; 968 969 /* Lower the recording level */ 970 /* Multiply by 0.828125 which corresponds to decreasing ~0.8dB */ 971 tmp32 = WEBRTC_SPL_RSHIFT_W32(stt->Rxx160_LPw32, 6); 972 stt->Rxx160_LPw32 = WEBRTC_SPL_MUL(tmp32, 53); 973 974 /* Reduce the max gain to avoid excessive oscillation 975 * (but never drop below the maximum analog level). 976 * stt->maxLevel = (15 * stt->maxLevel + stt->micVol) / 16; 977 */ 978 tmp32 = (15 * stt->maxLevel) + stt->micVol; 979 stt->maxLevel = WEBRTC_SPL_RSHIFT_W32(tmp32, 4); 980 stt->maxLevel = WEBRTC_SPL_MAX(stt->maxLevel, stt->maxAnalog); 981 982 stt->zeroCtrlMax = stt->micVol; 983 984 /* 0.95 in Q15 */ 985 tmp32 = inMicLevelTmp - stt->minLevel; 986 tmpU32 = WEBRTC_SPL_UMUL(31130, (WebRtc_UWord32)(tmp32)); 987 stt->micVol = (WebRtc_Word32)WEBRTC_SPL_RSHIFT_U32(tmpU32, 15) + stt->minLevel; 988 if (stt->micVol > lastMicVol - 1) 989 { 990 stt->micVol = lastMicVol - 1; 991 } 992 inMicLevelTmp = stt->micVol; 993 994 /* Enable the control mechanism to ensure that our measure, 995 * Rxx160_LP, is in the correct range. 996 */ 997 stt->activeSpeech = 0; 998 stt->Rxx16_LPw32Max = 0; 999 #ifdef MIC_LEVEL_FEEDBACK 1000 //stt->numBlocksMicLvlSat = 0; 1001 #endif 1002 #ifdef AGC_DEBUG //test log 1003 fprintf(stt->fpt, 1004 "\tAGC->ProcessAnalog, frame %d: measure > 2ndUpperLim, micVol = %d, maxLevel = %d\n", 1005 stt->fcount, stt->micVol, stt->maxLevel); 1006 #endif 1007 } 1008 } else if (stt->Rxx160_LPw32 > stt->upperLimit) 1009 { 1010 stt->msTooHigh += 2; 1011 stt->msTooLow = 0; 1012 stt->changeToSlowMode = 0; 1013 1014 if (stt->msTooHigh > stt->msecSpeechInnerChange) 1015 { 1016 /* Lower the recording level */ 1017 stt->msTooHigh = 0; 1018 /* Multiply by 0.828125 which corresponds to decreasing ~0.8dB */ 1019 tmp32 = WEBRTC_SPL_RSHIFT_W32(stt->Rxx160_LPw32, 6); 1020 stt->Rxx160_LPw32 = WEBRTC_SPL_MUL(tmp32, 53); 1021 1022 /* Reduce the max gain to avoid excessive oscillation 1023 * (but never drop below the maximum analog level). 1024 * stt->maxLevel = (15 * stt->maxLevel + stt->micVol) / 16; 1025 */ 1026 tmp32 = (15 * stt->maxLevel) + stt->micVol; 1027 stt->maxLevel = WEBRTC_SPL_RSHIFT_W32(tmp32, 4); 1028 stt->maxLevel = WEBRTC_SPL_MAX(stt->maxLevel, stt->maxAnalog); 1029 1030 stt->zeroCtrlMax = stt->micVol; 1031 1032 /* 0.965 in Q15 */ 1033 tmp32 = inMicLevelTmp - stt->minLevel; 1034 tmpU32 = WEBRTC_SPL_UMUL(31621, (WebRtc_UWord32)(inMicLevelTmp - stt->minLevel)); 1035 stt->micVol = (WebRtc_Word32)WEBRTC_SPL_RSHIFT_U32(tmpU32, 15) + stt->minLevel; 1036 if (stt->micVol > lastMicVol - 1) 1037 { 1038 stt->micVol = lastMicVol - 1; 1039 } 1040 inMicLevelTmp = stt->micVol; 1041 1042 #ifdef MIC_LEVEL_FEEDBACK 1043 //stt->numBlocksMicLvlSat = 0; 1044 #endif 1045 #ifdef AGC_DEBUG //test log 1046 fprintf(stt->fpt, 1047 "\tAGC->ProcessAnalog, frame %d: measure > UpperLim, micVol = %d, maxLevel = %d\n", 1048 stt->fcount, stt->micVol, stt->maxLevel); 1049 #endif 1050 } 1051 } else if (stt->Rxx160_LPw32 < stt->lowerSecondaryLimit) 1052 { 1053 stt->msTooHigh = 0; 1054 stt->changeToSlowMode = 0; 1055 stt->msTooLow += 2; 1056 1057 if (stt->msTooLow > stt->msecSpeechOuterChange) 1058 { 1059 /* Raise the recording level */ 1060 WebRtc_Word16 index, weightFIX; 1061 WebRtc_Word16 volNormFIX = 16384; // =1 in Q14. 1062 1063 stt->msTooLow = 0; 1064 1065 /* Normalize the volume level */ 1066 tmp32 = WEBRTC_SPL_LSHIFT_W32(inMicLevelTmp - stt->minLevel, 14); 1067 if (stt->maxInit != stt->minLevel) 1068 { 1069 volNormFIX = (WebRtc_Word16)WEBRTC_SPL_DIV(tmp32, 1070 (stt->maxInit - stt->minLevel)); 1071 } 1072 1073 /* Find correct curve */ 1074 WebRtcAgc_ExpCurve(volNormFIX, &index); 1075 1076 /* Compute weighting factor for the volume increase, 32^(-2*X)/2+1.05 */ 1077 weightFIX = kOffset1[index] 1078 - (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(kSlope1[index], 1079 volNormFIX, 13); 1080 1081 /* stt->Rxx160_LPw32 *= 1.047 [~0.2 dB]; */ 1082 tmp32 = WEBRTC_SPL_RSHIFT_W32(stt->Rxx160_LPw32, 6); 1083 stt->Rxx160_LPw32 = WEBRTC_SPL_MUL(tmp32, 67); 1084 1085 tmp32 = inMicLevelTmp - stt->minLevel; 1086 tmpU32 = ((WebRtc_UWord32)weightFIX * (WebRtc_UWord32)(inMicLevelTmp - stt->minLevel)); 1087 stt->micVol = (WebRtc_Word32)WEBRTC_SPL_RSHIFT_U32(tmpU32, 14) + stt->minLevel; 1088 if (stt->micVol < lastMicVol + 2) 1089 { 1090 stt->micVol = lastMicVol + 2; 1091 } 1092 1093 inMicLevelTmp = stt->micVol; 1094 1095 #ifdef MIC_LEVEL_FEEDBACK 1096 /* Count ms in level saturation */ 1097 //if (stt->micVol > stt->maxAnalog) { 1098 if (stt->micVol > 150) 1099 { 1100 /* mic level is saturated */ 1101 stt->numBlocksMicLvlSat++; 1102 fprintf(stderr, "Sat mic Level: %d\n", stt->numBlocksMicLvlSat); 1103 } 1104 #endif 1105 #ifdef AGC_DEBUG //test log 1106 fprintf(stt->fpt, 1107 "\tAGC->ProcessAnalog, frame %d: measure < 2ndLowerLim, micVol = %d\n", 1108 stt->fcount, stt->micVol); 1109 #endif 1110 } 1111 } else if (stt->Rxx160_LPw32 < stt->lowerLimit) 1112 { 1113 stt->msTooHigh = 0; 1114 stt->changeToSlowMode = 0; 1115 stt->msTooLow += 2; 1116 1117 if (stt->msTooLow > stt->msecSpeechInnerChange) 1118 { 1119 /* Raise the recording level */ 1120 WebRtc_Word16 index, weightFIX; 1121 WebRtc_Word16 volNormFIX = 16384; // =1 in Q14. 1122 1123 stt->msTooLow = 0; 1124 1125 /* Normalize the volume level */ 1126 tmp32 = WEBRTC_SPL_LSHIFT_W32(inMicLevelTmp - stt->minLevel, 14); 1127 if (stt->maxInit != stt->minLevel) 1128 { 1129 volNormFIX = (WebRtc_Word16)WEBRTC_SPL_DIV(tmp32, 1130 (stt->maxInit - stt->minLevel)); 1131 } 1132 1133 /* Find correct curve */ 1134 WebRtcAgc_ExpCurve(volNormFIX, &index); 1135 1136 /* Compute weighting factor for the volume increase, (3.^(-2.*X))/8+1 */ 1137 weightFIX = kOffset2[index] 1138 - (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(kSlope2[index], 1139 volNormFIX, 13); 1140 1141 /* stt->Rxx160_LPw32 *= 1.047 [~0.2 dB]; */ 1142 tmp32 = WEBRTC_SPL_RSHIFT_W32(stt->Rxx160_LPw32, 6); 1143 stt->Rxx160_LPw32 = WEBRTC_SPL_MUL(tmp32, 67); 1144 1145 tmp32 = inMicLevelTmp - stt->minLevel; 1146 tmpU32 = ((WebRtc_UWord32)weightFIX * (WebRtc_UWord32)(inMicLevelTmp - stt->minLevel)); 1147 stt->micVol = (WebRtc_Word32)WEBRTC_SPL_RSHIFT_U32(tmpU32, 14) + stt->minLevel; 1148 if (stt->micVol < lastMicVol + 1) 1149 { 1150 stt->micVol = lastMicVol + 1; 1151 } 1152 1153 inMicLevelTmp = stt->micVol; 1154 1155 #ifdef MIC_LEVEL_FEEDBACK 1156 /* Count ms in level saturation */ 1157 //if (stt->micVol > stt->maxAnalog) { 1158 if (stt->micVol > 150) 1159 { 1160 /* mic level is saturated */ 1161 stt->numBlocksMicLvlSat++; 1162 fprintf(stderr, "Sat mic Level: %d\n", stt->numBlocksMicLvlSat); 1163 } 1164 #endif 1165 #ifdef AGC_DEBUG //test log 1166 fprintf(stt->fpt, 1167 "\tAGC->ProcessAnalog, frame %d: measure < LowerLim, micVol = %d\n", 1168 stt->fcount, stt->micVol); 1169 #endif 1170 1171 } 1172 } else 1173 { 1174 /* The signal is inside the desired range which is: 1175 * lowerLimit < Rxx160_LP/640 < upperLimit 1176 */ 1177 if (stt->changeToSlowMode > 4000) 1178 { 1179 stt->msecSpeechInnerChange = 1000; 1180 stt->msecSpeechOuterChange = 500; 1181 stt->upperLimit = stt->upperPrimaryLimit; 1182 stt->lowerLimit = stt->lowerPrimaryLimit; 1183 } else 1184 { 1185 stt->changeToSlowMode += 2; // in milliseconds 1186 } 1187 stt->msTooLow = 0; 1188 stt->msTooHigh = 0; 1189 1190 stt->micVol = inMicLevelTmp; 1191 1192 } 1193 #ifdef MIC_LEVEL_FEEDBACK 1194 if (stt->numBlocksMicLvlSat > NUM_BLOCKS_IN_SAT_BEFORE_CHANGE_TARGET) 1195 { 1196 stt->micLvlSat = 1; 1197 fprintf(stderr, "target before = %d (%d)\n", stt->analogTargetLevel, stt->targetIdx); 1198 WebRtcAgc_UpdateAgcThresholds(stt); 1199 WebRtcAgc_CalculateGainTable(&(stt->digitalAgc.gainTable[0]), 1200 stt->compressionGaindB, stt->targetLevelDbfs, stt->limiterEnable, 1201 stt->analogTarget); 1202 stt->numBlocksMicLvlSat = 0; 1203 stt->micLvlSat = 0; 1204 fprintf(stderr, "target offset = %d\n", stt->targetIdxOffset); 1205 fprintf(stderr, "target after = %d (%d)\n", stt->analogTargetLevel, stt->targetIdx); 1206 } 1207 #endif 1208 } 1209 } 1210 1211 /* Ensure gain is not increased in presence of echo or after a mute event 1212 * (but allow the zeroCtrl() increase on the frame of a mute detection). 1213 */ 1214 if (echo == 1 || (stt->muteGuardMs > 0 && stt->muteGuardMs < kMuteGuardTimeMs)) 1215 { 1216 if (stt->micVol > lastMicVol) 1217 { 1218 stt->micVol = lastMicVol; 1219 } 1220 } 1221 1222 /* limit the gain */ 1223 if (stt->micVol > stt->maxLevel) 1224 { 1225 stt->micVol = stt->maxLevel; 1226 } else if (stt->micVol < stt->minOutput) 1227 { 1228 stt->micVol = stt->minOutput; 1229 } 1230 1231 *outMicLevel = WEBRTC_SPL_RSHIFT_W32(stt->micVol, stt->scale); 1232 if (*outMicLevel > WEBRTC_SPL_RSHIFT_W32(stt->maxAnalog, stt->scale)) 1233 { 1234 *outMicLevel = WEBRTC_SPL_RSHIFT_W32(stt->maxAnalog, stt->scale); 1235 } 1236 1237 return 0; 1238 } 1239 1240 int WebRtcAgc_Process(void *agcInst, const WebRtc_Word16 *in_near, 1241 const WebRtc_Word16 *in_near_H, WebRtc_Word16 samples, 1242 WebRtc_Word16 *out, WebRtc_Word16 *out_H, WebRtc_Word32 inMicLevel, 1243 WebRtc_Word32 *outMicLevel, WebRtc_Word16 echo, 1244 WebRtc_UWord8 *saturationWarning) 1245 { 1246 Agc_t *stt; 1247 WebRtc_Word32 inMicLevelTmp; 1248 WebRtc_Word16 subFrames, i; 1249 WebRtc_UWord8 satWarningTmp = 0; 1250 1251 stt = (Agc_t *)agcInst; 1252 1253 // 1254 if (stt == NULL) 1255 { 1256 return -1; 1257 } 1258 // 1259 1260 1261 if (stt->fs == 8000) 1262 { 1263 if ((samples != 80) && (samples != 160)) 1264 { 1265 #ifdef AGC_DEBUG //test log 1266 fprintf(stt->fpt, 1267 "AGC->Process, frame %d: Invalid number of samples\n\n", stt->fcount); 1268 #endif 1269 return -1; 1270 } 1271 subFrames = 80; 1272 } else if (stt->fs == 16000) 1273 { 1274 if ((samples != 160) && (samples != 320)) 1275 { 1276 #ifdef AGC_DEBUG //test log 1277 fprintf(stt->fpt, 1278 "AGC->Process, frame %d: Invalid number of samples\n\n", stt->fcount); 1279 #endif 1280 return -1; 1281 } 1282 subFrames = 160; 1283 } else if (stt->fs == 32000) 1284 { 1285 if ((samples != 160) && (samples != 320)) 1286 { 1287 #ifdef AGC_DEBUG //test log 1288 fprintf(stt->fpt, 1289 "AGC->Process, frame %d: Invalid number of samples\n\n", stt->fcount); 1290 #endif 1291 return -1; 1292 } 1293 subFrames = 160; 1294 } else 1295 { 1296 #ifdef AGC_DEBUG// test log 1297 fprintf(stt->fpt, 1298 "AGC->Process, frame %d: Invalid sample rate\n\n", stt->fcount); 1299 #endif 1300 return -1; 1301 } 1302 1303 /* Check for valid pointers based on sampling rate */ 1304 if (stt->fs == 32000 && in_near_H == NULL) 1305 { 1306 return -1; 1307 } 1308 /* Check for valid pointers for low band */ 1309 if (in_near == NULL) 1310 { 1311 return -1; 1312 } 1313 1314 *saturationWarning = 0; 1315 //TODO: PUT IN RANGE CHECKING FOR INPUT LEVELS 1316 *outMicLevel = inMicLevel; 1317 inMicLevelTmp = inMicLevel; 1318 1319 memcpy(out, in_near, samples * sizeof(WebRtc_Word16)); 1320 if (stt->fs == 32000) 1321 { 1322 memcpy(out_H, in_near_H, samples * sizeof(WebRtc_Word16)); 1323 } 1324 1325 #ifdef AGC_DEBUG//test log 1326 stt->fcount++; 1327 #endif 1328 1329 for (i = 0; i < samples; i += subFrames) 1330 { 1331 if (WebRtcAgc_ProcessDigital(&stt->digitalAgc, &in_near[i], &in_near_H[i], &out[i], &out_H[i], 1332 stt->fs, stt->lowLevelSignal) == -1) 1333 { 1334 #ifdef AGC_DEBUG//test log 1335 fprintf(stt->fpt, "AGC->Process, frame %d: Error from DigAGC\n\n", stt->fcount); 1336 #endif 1337 return -1; 1338 } 1339 if ((stt->agcMode < kAgcModeFixedDigital) && ((stt->lowLevelSignal == 0) 1340 || (stt->agcMode != kAgcModeAdaptiveDigital))) 1341 { 1342 if (WebRtcAgc_ProcessAnalog(agcInst, inMicLevelTmp, outMicLevel, 1343 stt->vadMic.logRatio, echo, saturationWarning) == -1) 1344 { 1345 return -1; 1346 } 1347 } 1348 #ifdef AGC_DEBUG//test log 1349 fprintf(stt->agcLog, "%5d\t%d\t%d\t%d\n", stt->fcount, inMicLevelTmp, *outMicLevel, stt->maxLevel, stt->micVol); 1350 #endif 1351 1352 /* update queue */ 1353 if (stt->inQueue > 1) 1354 { 1355 memcpy(stt->env[0], stt->env[1], 10 * sizeof(WebRtc_Word32)); 1356 memcpy(stt->Rxx16w32_array[0], stt->Rxx16w32_array[1], 5 * sizeof(WebRtc_Word32)); 1357 } 1358 1359 if (stt->inQueue > 0) 1360 { 1361 stt->inQueue--; 1362 } 1363 1364 /* If 20ms frames are used the input mic level must be updated so that 1365 * the analog AGC does not think that there has been a manual volume 1366 * change. */ 1367 inMicLevelTmp = *outMicLevel; 1368 1369 /* Store a positive saturation warning. */ 1370 if (*saturationWarning == 1) 1371 { 1372 satWarningTmp = 1; 1373 } 1374 } 1375 1376 /* Trigger the saturation warning if displayed by any of the frames. */ 1377 *saturationWarning = satWarningTmp; 1378 1379 return 0; 1380 } 1381 1382 int WebRtcAgc_set_config(void *agcInst, WebRtcAgc_config_t agcConfig) 1383 { 1384 Agc_t *stt; 1385 stt = (Agc_t *)agcInst; 1386 1387 if (stt == NULL) 1388 { 1389 return -1; 1390 } 1391 1392 if (stt->initFlag != kInitCheck) 1393 { 1394 stt->lastError = AGC_UNINITIALIZED_ERROR; 1395 return -1; 1396 } 1397 1398 if (agcConfig.limiterEnable != kAgcFalse && agcConfig.limiterEnable != kAgcTrue) 1399 { 1400 stt->lastError = AGC_BAD_PARAMETER_ERROR; 1401 return -1; 1402 } 1403 stt->limiterEnable = agcConfig.limiterEnable; 1404 stt->compressionGaindB = agcConfig.compressionGaindB; 1405 if ((agcConfig.targetLevelDbfs < 0) || (agcConfig.targetLevelDbfs > 31)) 1406 { 1407 stt->lastError = AGC_BAD_PARAMETER_ERROR; 1408 return -1; 1409 } 1410 stt->targetLevelDbfs = agcConfig.targetLevelDbfs; 1411 1412 if (stt->agcMode == kAgcModeFixedDigital) 1413 { 1414 /* Adjust for different parameter interpretation in FixedDigital mode */ 1415 stt->compressionGaindB += agcConfig.targetLevelDbfs; 1416 } 1417 1418 /* Update threshold levels for analog adaptation */ 1419 WebRtcAgc_UpdateAgcThresholds(stt); 1420 1421 /* Recalculate gain table */ 1422 if (WebRtcAgc_CalculateGainTable(&(stt->digitalAgc.gainTable[0]), stt->compressionGaindB, 1423 stt->targetLevelDbfs, stt->limiterEnable, stt->analogTarget) == -1) 1424 { 1425 #ifdef AGC_DEBUG//test log 1426 fprintf(stt->fpt, "AGC->set_config, frame %d: Error from calcGainTable\n\n", stt->fcount); 1427 #endif 1428 return -1; 1429 } 1430 /* Store the config in a WebRtcAgc_config_t */ 1431 stt->usedConfig.compressionGaindB = agcConfig.compressionGaindB; 1432 stt->usedConfig.limiterEnable = agcConfig.limiterEnable; 1433 stt->usedConfig.targetLevelDbfs = agcConfig.targetLevelDbfs; 1434 1435 return 0; 1436 } 1437 1438 int WebRtcAgc_get_config(void *agcInst, WebRtcAgc_config_t *config) 1439 { 1440 Agc_t *stt; 1441 stt = (Agc_t *)agcInst; 1442 1443 if (stt == NULL) 1444 { 1445 return -1; 1446 } 1447 1448 if (config == NULL) 1449 { 1450 stt->lastError = AGC_NULL_POINTER_ERROR; 1451 return -1; 1452 } 1453 1454 if (stt->initFlag != kInitCheck) 1455 { 1456 stt->lastError = AGC_UNINITIALIZED_ERROR; 1457 return -1; 1458 } 1459 1460 config->limiterEnable = stt->usedConfig.limiterEnable; 1461 config->targetLevelDbfs = stt->usedConfig.targetLevelDbfs; 1462 config->compressionGaindB = stt->usedConfig.compressionGaindB; 1463 1464 return 0; 1465 } 1466 1467 int WebRtcAgc_Create(void **agcInst) 1468 { 1469 Agc_t *stt; 1470 if (agcInst == NULL) 1471 { 1472 return -1; 1473 } 1474 stt = (Agc_t *)malloc(sizeof(Agc_t)); 1475 1476 *agcInst = stt; 1477 if (stt == NULL) 1478 { 1479 return -1; 1480 } 1481 1482 #ifdef AGC_DEBUG 1483 stt->fpt = fopen("./agc_test_log.txt", "wt"); 1484 stt->agcLog = fopen("./agc_debug_log.txt", "wt"); 1485 stt->digitalAgc.logFile = fopen("./agc_log.txt", "wt"); 1486 #endif 1487 1488 stt->initFlag = 0; 1489 stt->lastError = 0; 1490 1491 return 0; 1492 } 1493 1494 int WebRtcAgc_Free(void *state) 1495 { 1496 Agc_t *stt; 1497 1498 stt = (Agc_t *)state; 1499 #ifdef AGC_DEBUG 1500 fclose(stt->fpt); 1501 fclose(stt->agcLog); 1502 fclose(stt->digitalAgc.logFile); 1503 #endif 1504 free(stt); 1505 1506 return 0; 1507 } 1508 1509 /* minLevel - Minimum volume level 1510 * maxLevel - Maximum volume level 1511 */ 1512 int WebRtcAgc_Init(void *agcInst, WebRtc_Word32 minLevel, WebRtc_Word32 maxLevel, 1513 WebRtc_Word16 agcMode, WebRtc_UWord32 fs) 1514 { 1515 WebRtc_Word32 max_add, tmp32; 1516 WebRtc_Word16 i; 1517 int tmpNorm; 1518 Agc_t *stt; 1519 1520 /* typecast state pointer */ 1521 stt = (Agc_t *)agcInst; 1522 1523 if (WebRtcAgc_InitDigital(&stt->digitalAgc, agcMode) != 0) 1524 { 1525 stt->lastError = AGC_UNINITIALIZED_ERROR; 1526 return -1; 1527 } 1528 1529 /* Analog AGC variables */ 1530 stt->envSum = 0; 1531 1532 /* mode = 0 - Only saturation protection 1533 * 1 - Analog Automatic Gain Control [-targetLevelDbfs (default -3 dBOv)] 1534 * 2 - Digital Automatic Gain Control [-targetLevelDbfs (default -3 dBOv)] 1535 * 3 - Fixed Digital Gain [compressionGaindB (default 8 dB)] 1536 */ 1537 #ifdef AGC_DEBUG//test log 1538 stt->fcount = 0; 1539 fprintf(stt->fpt, "AGC->Init\n"); 1540 #endif 1541 if (agcMode < kAgcModeUnchanged || agcMode > kAgcModeFixedDigital) 1542 { 1543 #ifdef AGC_DEBUG//test log 1544 fprintf(stt->fpt, "AGC->Init: error, incorrect mode\n\n"); 1545 #endif 1546 return -1; 1547 } 1548 stt->agcMode = agcMode; 1549 stt->fs = fs; 1550 1551 /* initialize input VAD */ 1552 WebRtcAgc_InitVad(&stt->vadMic); 1553 1554 /* If the volume range is smaller than 0-256 then 1555 * the levels are shifted up to Q8-domain */ 1556 tmpNorm = WebRtcSpl_NormU32((WebRtc_UWord32)maxLevel); 1557 stt->scale = tmpNorm - 23; 1558 if (stt->scale < 0) 1559 { 1560 stt->scale = 0; 1561 } 1562 // TODO(bjornv): Investigate if we really need to scale up a small range now when we have 1563 // a guard against zero-increments. For now, we do not support scale up (scale = 0). 1564 stt->scale = 0; 1565 maxLevel = WEBRTC_SPL_LSHIFT_W32(maxLevel, stt->scale); 1566 minLevel = WEBRTC_SPL_LSHIFT_W32(minLevel, stt->scale); 1567 1568 /* Make minLevel and maxLevel static in AdaptiveDigital */ 1569 if (stt->agcMode == kAgcModeAdaptiveDigital) 1570 { 1571 minLevel = 0; 1572 maxLevel = 255; 1573 stt->scale = 0; 1574 } 1575 /* The maximum supplemental volume range is based on a vague idea 1576 * of how much lower the gain will be than the real analog gain. */ 1577 max_add = WEBRTC_SPL_RSHIFT_W32(maxLevel - minLevel, 2); 1578 1579 /* Minimum/maximum volume level that can be set */ 1580 stt->minLevel = minLevel; 1581 stt->maxAnalog = maxLevel; 1582 stt->maxLevel = maxLevel + max_add; 1583 stt->maxInit = stt->maxLevel; 1584 1585 stt->zeroCtrlMax = stt->maxAnalog; 1586 1587 /* Initialize micVol parameter */ 1588 stt->micVol = stt->maxAnalog; 1589 if (stt->agcMode == kAgcModeAdaptiveDigital) 1590 { 1591 stt->micVol = 127; /* Mid-point of mic level */ 1592 } 1593 stt->micRef = stt->micVol; 1594 stt->micGainIdx = 127; 1595 #ifdef MIC_LEVEL_FEEDBACK 1596 stt->numBlocksMicLvlSat = 0; 1597 stt->micLvlSat = 0; 1598 #endif 1599 #ifdef AGC_DEBUG//test log 1600 fprintf(stt->fpt, 1601 "AGC->Init: minLevel = %d, maxAnalog = %d, maxLevel = %d\n", 1602 stt->minLevel, stt->maxAnalog, stt->maxLevel); 1603 #endif 1604 1605 /* Minimum output volume is 4% higher than the available lowest volume level */ 1606 tmp32 = WEBRTC_SPL_RSHIFT_W32((stt->maxLevel - stt->minLevel) * (WebRtc_Word32)10, 8); 1607 stt->minOutput = (stt->minLevel + tmp32); 1608 1609 stt->msTooLow = 0; 1610 stt->msTooHigh = 0; 1611 stt->changeToSlowMode = 0; 1612 stt->firstCall = 0; 1613 stt->msZero = 0; 1614 stt->muteGuardMs = 0; 1615 stt->gainTableIdx = 0; 1616 1617 stt->msecSpeechInnerChange = kMsecSpeechInner; 1618 stt->msecSpeechOuterChange = kMsecSpeechOuter; 1619 1620 stt->activeSpeech = 0; 1621 stt->Rxx16_LPw32Max = 0; 1622 1623 stt->vadThreshold = kNormalVadThreshold; 1624 stt->inActive = 0; 1625 1626 for (i = 0; i < RXX_BUFFER_LEN; i++) 1627 { 1628 stt->Rxx16_vectorw32[i] = (WebRtc_Word32)1000; /* -54dBm0 */ 1629 } 1630 stt->Rxx160w32 = 125 * RXX_BUFFER_LEN; /* (stt->Rxx16_vectorw32[0]>>3) = 125 */ 1631 1632 stt->Rxx16pos = 0; 1633 stt->Rxx16_LPw32 = (WebRtc_Word32)16284; /* Q(-4) */ 1634 1635 for (i = 0; i < 5; i++) 1636 { 1637 stt->Rxx16w32_array[0][i] = 0; 1638 } 1639 for (i = 0; i < 20; i++) 1640 { 1641 stt->env[0][i] = 0; 1642 } 1643 stt->inQueue = 0; 1644 1645 #ifdef MIC_LEVEL_FEEDBACK 1646 stt->targetIdxOffset = 0; 1647 #endif 1648 1649 WebRtcSpl_MemSetW32(stt->filterState, 0, 8); 1650 1651 stt->initFlag = kInitCheck; 1652 // Default config settings. 1653 stt->defaultConfig.limiterEnable = kAgcTrue; 1654 stt->defaultConfig.targetLevelDbfs = AGC_DEFAULT_TARGET_LEVEL; 1655 stt->defaultConfig.compressionGaindB = AGC_DEFAULT_COMP_GAIN; 1656 1657 if (WebRtcAgc_set_config(stt, stt->defaultConfig) == -1) 1658 { 1659 stt->lastError = AGC_UNSPECIFIED_ERROR; 1660 return -1; 1661 } 1662 stt->Rxx160_LPw32 = stt->analogTargetLevel; // Initialize rms value 1663 1664 stt->lowLevelSignal = 0; 1665 1666 /* Only positive values are allowed that are not too large */ 1667 if ((minLevel >= maxLevel) || (maxLevel & 0xFC000000)) 1668 { 1669 #ifdef AGC_DEBUG//test log 1670 fprintf(stt->fpt, "minLevel, maxLevel value(s) are invalid\n\n"); 1671 #endif 1672 return -1; 1673 } else 1674 { 1675 #ifdef AGC_DEBUG//test log 1676 fprintf(stt->fpt, "\n"); 1677 #endif 1678 return 0; 1679 } 1680 } 1681 1682 int WebRtcAgc_Version(WebRtc_Word8 *versionStr, WebRtc_Word16 length) 1683 { 1684 const WebRtc_Word8 version[] = "AGC 1.7.0"; 1685 const WebRtc_Word16 versionLen = (WebRtc_Word16)strlen(version) + 1; 1686 1687 if (versionStr == NULL) 1688 { 1689 return -1; 1690 } 1691 1692 if (versionLen > length) 1693 { 1694 return -1; 1695 } 1696 1697 strncpy(versionStr, version, versionLen); 1698 return 0; 1699 } 1700