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