2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
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.
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
22 #ifdef WEBRTC_AGC_DEBUG_DUMP
25 #include "webrtc/modules/audio_processing/agc/analog_agc.h"
27 /* The slope of in Q13*/
28 static const int16_t kSlope1[8] = {21793, 12517, 7189, 4129, 2372, 1362, 472, 78};
30 /* The offset in Q14 */
31 static const int16_t kOffset1[8] = {25395, 23911, 22206, 20737, 19612, 18805, 17951,
34 /* The slope of in Q13*/
35 static const int16_t kSlope2[8] = {2063, 1731, 1452, 1218, 1021, 857, 597, 337};
37 /* The offset in Q14 */
38 static const int16_t kOffset2[8] = {18432, 18379, 18290, 18177, 18052, 17920, 17670,
41 static const int16_t kMuteGuardTimeMs = 8000;
42 static const int16_t kInitCheck = 42;
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.
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
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.
61 #define DIGITAL_REF_AT_0_COMP_GAIN 4
62 /* Speed of reference level decrease.
64 #define DIFF_REF_TO_ANALOG 5
66 #ifdef MIC_LEVEL_FEEDBACK
67 #define NUM_BLOCKS_IN_SAT_BEFORE_CHANGE_TARGET 7
69 /* Size of analog gain table */
70 #define GAIN_TBL_LEN 32
72 * fprintf(1, '\t%i, %i, %i, %i,\n', round(10.^(linspace(0,10,32)/20) * 2^12));
75 static const uint16_t 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};
79 /* Gain/Suppression tables for virtual Mic (in Q10) */
80 static const uint16_t 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,
91 static const uint16_t 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,
101 /* Table for target energy levels. Values in Q(-7)
103 * targetLevelTable = fprintf('%d,\t%d,\t%d,\t%d,\n', round((32767*10.^(-(0:63)'/20)).^2*16/2^7) */
105 static const int32_t 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};
113 int WebRtcAgc_AddMic(void *state, int16_t *in_mic, int16_t *in_mic_H,
116 int32_t nrg, max_nrg, sample, tmp32;
118 uint16_t targetGainIdx, gain;
119 int16_t i, n, L, M, subFrames, tmp16, tmp_speech[16];
121 stt = (Agc_t *)state;
123 //default/initial values corresponding to 10ms for wb and swb
135 } else if (samples == 160)
142 #ifdef WEBRTC_AGC_DEBUG_DUMP
144 "AGC->add_mic, frame %d: Invalid number of samples\n\n",
149 } else if (stt->fs == 16000)
156 } else if (samples == 320)
163 #ifdef WEBRTC_AGC_DEBUG_DUMP
165 "AGC->add_mic, frame %d: Invalid number of samples\n\n",
170 } else if (stt->fs == 32000)
172 /* SWB is processed as 160 sample for L and H bands */
180 #ifdef WEBRTC_AGC_DEBUG_DUMP
182 "AGC->add_mic, frame %d: Invalid sample rate\n\n",
189 /* Check for valid pointers based on sampling rate */
190 if ((stt->fs == 32000) && (in_mic_H == NULL))
194 /* Check for valid pointer for low band */
200 /* apply slowly varying digital gain */
201 if (stt->micVol > stt->maxAnalog)
203 /* |maxLevel| is strictly >= |micVol|, so this condition should be
204 * satisfied here, ensuring there is no divide-by-zero. */
205 assert(stt->maxLevel > stt->maxAnalog);
208 tmp16 = (int16_t)(stt->micVol - stt->maxAnalog);
209 tmp32 = WEBRTC_SPL_MUL_16_16(GAIN_TBL_LEN - 1, tmp16);
210 tmp16 = (int16_t)(stt->maxLevel - stt->maxAnalog);
211 targetGainIdx = tmp32 / tmp16;
212 assert(targetGainIdx < GAIN_TBL_LEN);
214 /* Increment through the table towards the target gain.
215 * If micVol drops below maxAnalog, we allow the gain
216 * to be dropped immediately. */
217 if (stt->gainTableIdx < targetGainIdx)
220 } else if (stt->gainTableIdx > targetGainIdx)
226 gain = kGainTableAnalog[stt->gainTableIdx];
228 for (i = 0; i < samples; i++)
231 sample = (in_mic[i] * gain) >> 12;
235 } else if (sample < -32768)
240 in_mic[i] = (int16_t)sample;
244 if (stt->fs == 32000)
246 sample = (in_mic_H[i] * gain) >> 12;
250 } else if (sample < -32768)
252 in_mic_H[i] = -32768;
255 in_mic_H[i] = (int16_t)sample;
261 stt->gainTableIdx = 0;
264 /* compute envelope */
265 if ((M == 10) && (stt->inQueue > 0))
273 for (i = 0; i < M; i++)
275 /* iterate over samples */
277 for (n = 0; n < L; n++)
279 nrg = WEBRTC_SPL_MUL_16_16(in_mic[i * L + n], in_mic[i * L + n]);
289 if ((M == 10) && (stt->inQueue > 0))
291 ptr = stt->Rxx16w32_array[1];
294 ptr = stt->Rxx16w32_array[0];
297 for (i = 0; i < M / 2; i++)
299 if (stt->fs == 16000)
301 WebRtcSpl_DownsampleBy2(&in_mic[i * 32], 32, tmp_speech, stt->filterState);
304 memcpy(tmp_speech, &in_mic[i * 16], 16 * sizeof(short));
306 /* Compute energy in blocks of 16 samples */
307 ptr[i] = WebRtcSpl_DotProductWithScale(tmp_speech, tmp_speech, 16, 4);
310 /* update queue information */
311 if ((stt->inQueue == 0) && (M == 10))
319 /* call VAD (use low band only) */
320 for (i = 0; i < samples; i += subFrames)
322 WebRtcAgc_ProcessVad(&stt->vadMic, &in_mic[i], subFrames);
328 int WebRtcAgc_AddFarend(void *state, const int16_t *in_far, int16_t samples)
330 int32_t errHandle = 0;
331 int16_t i, subFrames;
333 stt = (Agc_t *)state;
342 if ((samples != 80) && (samples != 160))
344 #ifdef WEBRTC_AGC_DEBUG_DUMP
346 "AGC->add_far_end, frame %d: Invalid number of samples\n\n",
352 } else if (stt->fs == 16000)
354 if ((samples != 160) && (samples != 320))
356 #ifdef WEBRTC_AGC_DEBUG_DUMP
358 "AGC->add_far_end, frame %d: Invalid number of samples\n\n",
364 } else if (stt->fs == 32000)
366 if ((samples != 160) && (samples != 320))
368 #ifdef WEBRTC_AGC_DEBUG_DUMP
370 "AGC->add_far_end, frame %d: Invalid number of samples\n\n",
378 #ifdef WEBRTC_AGC_DEBUG_DUMP
380 "AGC->add_far_end, frame %d: Invalid sample rate\n\n",
386 for (i = 0; i < samples; i += subFrames)
388 errHandle += WebRtcAgc_AddFarendToDigital(&stt->digitalAgc, &in_far[i], subFrames);
394 int WebRtcAgc_VirtualMic(void *agcInst, int16_t *in_near, int16_t *in_near_H,
395 int16_t samples, int32_t micLevelIn,
396 int32_t *micLevelOut)
398 int32_t tmpFlt, micLevelTmp, gainIdx;
405 uint32_t frameNrg = 0;
406 uint32_t frameNrgLimit = 5500;
407 int16_t numZeroCrossing = 0;
408 const int16_t kZeroCrossingLowLim = 15;
409 const int16_t kZeroCrossingHighLim = 20;
411 stt = (Agc_t *)agcInst;
414 * Before applying gain decide if this is a low-level signal.
415 * The idea is that digital AGC will not adapt to low-level
420 frameNrgLimit = frameNrgLimit << 1;
423 frameNrg = WEBRTC_SPL_MUL_16_16(in_near[0], in_near[0]);
424 for (sampleCntr = 1; sampleCntr < samples; sampleCntr++)
427 // increment frame energy if it is less than the limit
428 // the correct value of the energy is not important
429 if (frameNrg < frameNrgLimit)
431 nrg = WEBRTC_SPL_MUL_16_16(in_near[sampleCntr], in_near[sampleCntr]);
435 // Count the zero crossings
436 numZeroCrossing += ((in_near[sampleCntr] ^ in_near[sampleCntr - 1]) < 0);
439 if ((frameNrg < 500) || (numZeroCrossing <= 5))
441 stt->lowLevelSignal = 1;
442 } else if (numZeroCrossing <= kZeroCrossingLowLim)
444 stt->lowLevelSignal = 0;
445 } else if (frameNrg <= frameNrgLimit)
447 stt->lowLevelSignal = 1;
448 } else if (numZeroCrossing >= kZeroCrossingHighLim)
450 stt->lowLevelSignal = 1;
453 stt->lowLevelSignal = 0;
456 micLevelTmp = micLevelIn << stt->scale;
457 /* Set desired level */
458 gainIdx = stt->micVol;
459 if (stt->micVol > stt->maxAnalog)
461 gainIdx = stt->maxAnalog;
463 if (micLevelTmp != stt->micRef)
465 /* Something has happened with the physical level, restart. */
466 stt->micRef = micLevelTmp;
469 stt->micGainIdx = 127;
472 /* Pre-process the signal to emulate the microphone level. */
473 /* Take one step at a time in the gain table. */
476 gain = kGainTableVirtualMic[gainIdx - 128];
479 gain = kSuppressionTableVirtualMic[127 - gainIdx];
481 for (ii = 0; ii < samples; ii++)
483 tmpFlt = (in_near[ii] * gain) >> 10;
490 gain = kGainTableVirtualMic[gainIdx - 127];
493 gain = kSuppressionTableVirtualMic[127 - gainIdx];
502 gain = kGainTableVirtualMic[gainIdx - 127];
505 gain = kSuppressionTableVirtualMic[127 - gainIdx];
508 in_near[ii] = (int16_t)tmpFlt;
509 if (stt->fs == 32000)
511 tmpFlt = (in_near_H[ii] * gain) >> 10;
520 in_near_H[ii] = (int16_t)tmpFlt;
523 /* Set the level we (finally) used */
524 stt->micGainIdx = gainIdx;
525 // *micLevelOut = stt->micGainIdx;
526 *micLevelOut = stt->micGainIdx >> stt->scale;
527 /* Add to Mic as if it was the output from a true microphone */
528 if (WebRtcAgc_AddMic(agcInst, in_near, in_near_H, samples) != 0)
535 void WebRtcAgc_UpdateAgcThresholds(Agc_t *stt)
539 #ifdef MIC_LEVEL_FEEDBACK
544 /* Lower the analog target level since we have reached its maximum */
545 zeros = WebRtcSpl_NormW32(stt->Rxx160_LPw32);
546 stt->targetIdxOffset = (3 * zeros - stt->targetIdx - 2) / 4;
550 /* Set analog target level in envelope dBOv scale */
551 tmp16 = (DIFF_REF_TO_ANALOG * stt->compressionGaindB) + ANALOG_TARGET_LEVEL_2;
552 tmp16 = WebRtcSpl_DivW32W16ResW16((int32_t)tmp16, ANALOG_TARGET_LEVEL);
553 stt->analogTarget = DIGITAL_REF_AT_0_COMP_GAIN + tmp16;
554 if (stt->analogTarget < DIGITAL_REF_AT_0_COMP_GAIN)
556 stt->analogTarget = DIGITAL_REF_AT_0_COMP_GAIN;
558 if (stt->agcMode == kAgcModeFixedDigital)
560 /* Adjust for different parameter interpretation in FixedDigital mode */
561 stt->analogTarget = stt->compressionGaindB;
563 #ifdef MIC_LEVEL_FEEDBACK
564 stt->analogTarget += stt->targetIdxOffset;
566 /* Since the offset between RMS and ENV is not constant, we should make this into a
567 * table, but for now, we'll stick with a constant, tuned for the chosen analog
570 stt->targetIdx = ANALOG_TARGET_LEVEL + OFFSET_ENV_TO_RMS;
571 #ifdef MIC_LEVEL_FEEDBACK
572 stt->targetIdx += stt->targetIdxOffset;
574 /* Analog adaptation limits */
575 /* analogTargetLevel = round((32767*10^(-targetIdx/20))^2*16/2^7) */
576 stt->analogTargetLevel = RXX_BUFFER_LEN * kTargetLevelTable[stt->targetIdx]; /* ex. -20 dBov */
577 stt->startUpperLimit = RXX_BUFFER_LEN * kTargetLevelTable[stt->targetIdx - 1];/* -19 dBov */
578 stt->startLowerLimit = RXX_BUFFER_LEN * kTargetLevelTable[stt->targetIdx + 1];/* -21 dBov */
579 stt->upperPrimaryLimit = RXX_BUFFER_LEN * kTargetLevelTable[stt->targetIdx - 2];/* -18 dBov */
580 stt->lowerPrimaryLimit = RXX_BUFFER_LEN * kTargetLevelTable[stt->targetIdx + 2];/* -22 dBov */
581 stt->upperSecondaryLimit = RXX_BUFFER_LEN * kTargetLevelTable[stt->targetIdx - 5];/* -15 dBov */
582 stt->lowerSecondaryLimit = RXX_BUFFER_LEN * kTargetLevelTable[stt->targetIdx + 5];/* -25 dBov */
583 stt->upperLimit = stt->startUpperLimit;
584 stt->lowerLimit = stt->startLowerLimit;
587 void WebRtcAgc_SaturationCtrl(Agc_t *stt, uint8_t *saturated, int32_t *env)
591 /* Check if the signal is saturated */
592 for (i = 0; i < 10; i++)
594 tmpW16 = (int16_t)(env[i] >> 20);
597 stt->envSum += tmpW16;
601 if (stt->envSum > 25000)
607 /* stt->envSum *= 0.99; */
608 stt->envSum = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(stt->envSum,
612 void WebRtcAgc_ZeroCtrl(Agc_t *stt, int32_t *inMicLevel, int32_t *env)
618 /* Is the input signal zero? */
619 for (i = 0; i < 10; i++)
624 /* Each block is allowed to have a few non-zero
635 if (stt->muteGuardMs > 0)
637 stt->muteGuardMs -= 10;
640 if (stt->msZero > 500)
644 /* Increase microphone level only if it's less than 50% */
645 midVal = (stt->maxAnalog + stt->minLevel + 1) / 2;
646 if (*inMicLevel < midVal)
648 /* *inMicLevel *= 1.1; */
649 *inMicLevel = (1126 * *inMicLevel) >> 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;
656 #ifdef WEBRTC_AGC_DEBUG_DUMP
658 "\t\tAGC->zeroCntrl, frame %d: 500 ms under threshold,"
664 stt->activeSpeech = 0;
665 stt->Rxx16_LPw32Max = 0;
667 /* The AGC has a tendency (due to problems with the VAD parameters), to
668 * vastly increase the volume after a muting event. This timer prevents
669 * upwards adaptation for a short period. */
670 stt->muteGuardMs = kMuteGuardTimeMs;
674 void WebRtcAgc_SpeakerInactiveCtrl(Agc_t *stt)
676 /* Check if the near end speaker is inactive.
677 * If that is the case the VAD threshold is
678 * increased since the VAD speech model gets
679 * more sensitive to any sound after a long
686 if (stt->vadMic.stdLongTerm < 2500)
688 stt->vadThreshold = 1500;
691 vadThresh = kNormalVadThreshold;
692 if (stt->vadMic.stdLongTerm < 4500)
694 /* Scale between min and max threshold */
695 vadThresh += (4500 - stt->vadMic.stdLongTerm) / 2;
698 /* stt->vadThreshold = (31 * stt->vadThreshold + vadThresh) / 32; */
699 tmp32 = (int32_t)vadThresh;
700 tmp32 += WEBRTC_SPL_MUL_16_16((int16_t)31, stt->vadThreshold);
701 stt->vadThreshold = (int16_t)(tmp32 >> 5);
705 void WebRtcAgc_ExpCurve(int16_t volume, int16_t *index)
709 /* 8 different curves */
755 int32_t WebRtcAgc_ProcessAnalog(void *state, int32_t inMicLevel,
756 int32_t *outMicLevel,
758 int16_t echo, uint8_t *saturationWarning)
761 int32_t Rxx16w32, tmp32;
762 int32_t inMicLevelTmp, lastMicVol;
764 uint8_t saturated = 0;
767 stt = (Agc_t *)state;
768 inMicLevelTmp = inMicLevel << stt->scale;
770 if (inMicLevelTmp > stt->maxAnalog)
772 #ifdef WEBRTC_AGC_DEBUG_DUMP
774 "\tAGC->ProcessAnalog, frame %d: micLvl > maxAnalog\n",
778 } else if (inMicLevelTmp < stt->minLevel)
780 #ifdef WEBRTC_AGC_DEBUG_DUMP
782 "\tAGC->ProcessAnalog, frame %d: micLvl < minLevel\n",
788 if (stt->firstCall == 0)
792 tmp32 = ((stt->maxLevel - stt->minLevel) * 51) >> 9;
793 tmpVol = (stt->minLevel + tmp32);
795 /* If the mic level is very low at start, increase it! */
796 if ((inMicLevelTmp < tmpVol) && (stt->agcMode == kAgcModeAdaptiveAnalog))
798 inMicLevelTmp = tmpVol;
800 stt->micVol = inMicLevelTmp;
803 /* Set the mic level to the previous output value if there is digital input gain */
804 if ((inMicLevelTmp == stt->maxAnalog) && (stt->micVol > stt->maxAnalog))
806 inMicLevelTmp = stt->micVol;
809 /* If the mic level was manually changed to a very low value raise it! */
810 if ((inMicLevelTmp != stt->micVol) && (inMicLevelTmp < stt->minOutput))
812 tmp32 = ((stt->maxLevel - stt->minLevel) * 51) >> 9;
813 inMicLevelTmp = (stt->minLevel + tmp32);
814 stt->micVol = inMicLevelTmp;
815 #ifdef MIC_LEVEL_FEEDBACK
816 //stt->numBlocksMicLvlSat = 0;
818 #ifdef WEBRTC_AGC_DEBUG_DUMP
820 "\tAGC->ProcessAnalog, frame %d: micLvl < minLevel by manual"
821 " decrease, raise vol\n",
826 if (inMicLevelTmp != stt->micVol)
828 if (inMicLevel == stt->lastInMicLevel) {
829 // We requested a volume adjustment, but it didn't occur. This is
830 // probably due to a coarse quantization of the volume slider.
831 // Restore the requested value to prevent getting stuck.
832 inMicLevelTmp = stt->micVol;
835 // As long as the value changed, update to match.
836 stt->micVol = inMicLevelTmp;
840 if (inMicLevelTmp > stt->maxLevel)
842 // Always allow the user to raise the volume above the maxLevel.
843 stt->maxLevel = inMicLevelTmp;
846 // Store last value here, after we've taken care of manual updates etc.
847 stt->lastInMicLevel = inMicLevel;
848 lastMicVol = stt->micVol;
850 /* Checks if the signal is saturated. Also a check if individual samples
851 * are larger than 12000 is done. If they are the counter for increasing
852 * the volume level is set to -100ms
854 WebRtcAgc_SaturationCtrl(stt, &saturated, stt->env[0]);
856 /* The AGC is always allowed to lower the level if the signal is saturated */
859 /* Lower the recording level
860 * Rxx160_LP is adjusted down because it is so slow it could
861 * cause the AGC to make wrong decisions. */
862 /* stt->Rxx160_LPw32 *= 0.875; */
863 stt->Rxx160_LPw32 = (stt->Rxx160_LPw32 / 8) * 7;
865 stt->zeroCtrlMax = stt->micVol;
867 /* stt->micVol *= 0.903; */
868 tmp32 = inMicLevelTmp - stt->minLevel;
869 tmpU32 = WEBRTC_SPL_UMUL(29591, (uint32_t)(tmp32));
870 stt->micVol = (tmpU32 >> 15) + stt->minLevel;
871 if (stt->micVol > lastMicVol - 2)
873 stt->micVol = lastMicVol - 2;
875 inMicLevelTmp = stt->micVol;
877 #ifdef WEBRTC_AGC_DEBUG_DUMP
879 "\tAGC->ProcessAnalog, frame %d: saturated, micVol = %d\n",
884 if (stt->micVol < stt->minOutput)
886 *saturationWarning = 1;
889 /* Reset counter for decrease of volume level to avoid
890 * decreasing too much. The saturation control can still
891 * lower the level if needed. */
892 stt->msTooHigh = -100;
894 /* Enable the control mechanism to ensure that our measure,
895 * Rxx160_LP, is in the correct range. This must be done since
896 * the measure is very slow. */
897 stt->activeSpeech = 0;
898 stt->Rxx16_LPw32Max = 0;
900 /* Reset to initial values */
901 stt->msecSpeechInnerChange = kMsecSpeechInner;
902 stt->msecSpeechOuterChange = kMsecSpeechOuter;
903 stt->changeToSlowMode = 0;
905 stt->muteGuardMs = 0;
907 stt->upperLimit = stt->startUpperLimit;
908 stt->lowerLimit = stt->startLowerLimit;
909 #ifdef MIC_LEVEL_FEEDBACK
910 //stt->numBlocksMicLvlSat = 0;
914 /* Check if the input speech is zero. If so the mic volume
915 * is increased. On some computers the input is zero up as high
917 WebRtcAgc_ZeroCtrl(stt, &inMicLevelTmp, stt->env[0]);
919 /* Check if the near end speaker is inactive.
920 * If that is the case the VAD threshold is
921 * increased since the VAD speech model gets
922 * more sensitive to any sound after a long
925 WebRtcAgc_SpeakerInactiveCtrl(stt);
927 for (i = 0; i < 5; i++)
929 /* Computed on blocks of 16 samples */
931 Rxx16w32 = stt->Rxx16w32_array[0][i];
933 /* Rxx160w32 in Q(-7) */
934 tmp32 = (Rxx16w32 - stt->Rxx16_vectorw32[stt->Rxx16pos]) >> 3;
935 stt->Rxx160w32 = stt->Rxx160w32 + tmp32;
936 stt->Rxx16_vectorw32[stt->Rxx16pos] = Rxx16w32;
938 /* Circular buffer */
940 if (stt->Rxx16pos == RXX_BUFFER_LEN)
945 /* Rxx16_LPw32 in Q(-4) */
946 tmp32 = (Rxx16w32 - stt->Rxx16_LPw32) >> kAlphaShortTerm;
947 stt->Rxx16_LPw32 = (stt->Rxx16_LPw32) + tmp32;
949 if (vadLogRatio > stt->vadThreshold)
951 /* Speech detected! */
953 /* Check if Rxx160_LP is in the correct range. If
954 * it is too high/low then we set it to the maximum of
955 * Rxx16_LPw32 during the first 200ms of speech.
957 if (stt->activeSpeech < 250)
959 stt->activeSpeech += 2;
961 if (stt->Rxx16_LPw32 > stt->Rxx16_LPw32Max)
963 stt->Rxx16_LPw32Max = stt->Rxx16_LPw32;
965 } else if (stt->activeSpeech == 250)
967 stt->activeSpeech += 2;
968 tmp32 = stt->Rxx16_LPw32Max >> 3;
969 stt->Rxx160_LPw32 = tmp32 * RXX_BUFFER_LEN;
972 tmp32 = (stt->Rxx160w32 - stt->Rxx160_LPw32) >> kAlphaLongTerm;
973 stt->Rxx160_LPw32 = stt->Rxx160_LPw32 + tmp32;
975 if (stt->Rxx160_LPw32 > stt->upperSecondaryLimit)
979 stt->changeToSlowMode = 0;
981 if (stt->msTooHigh > stt->msecSpeechOuterChange)
985 /* Lower the recording level */
986 /* Multiply by 0.828125 which corresponds to decreasing ~0.8dB */
987 tmp32 = stt->Rxx160_LPw32 >> 6;
988 stt->Rxx160_LPw32 = tmp32 * 53;
990 /* Reduce the max gain to avoid excessive oscillation
991 * (but never drop below the maximum analog level).
993 stt->maxLevel = (15 * stt->maxLevel + stt->micVol) / 16;
994 stt->maxLevel = WEBRTC_SPL_MAX(stt->maxLevel, stt->maxAnalog);
996 stt->zeroCtrlMax = stt->micVol;
999 tmp32 = inMicLevelTmp - stt->minLevel;
1000 tmpU32 = WEBRTC_SPL_UMUL(31130, (uint32_t)(tmp32));
1001 stt->micVol = (tmpU32 >> 15) + stt->minLevel;
1002 if (stt->micVol > lastMicVol - 1)
1004 stt->micVol = lastMicVol - 1;
1006 inMicLevelTmp = stt->micVol;
1008 /* Enable the control mechanism to ensure that our measure,
1009 * Rxx160_LP, is in the correct range.
1011 stt->activeSpeech = 0;
1012 stt->Rxx16_LPw32Max = 0;
1013 #ifdef MIC_LEVEL_FEEDBACK
1014 //stt->numBlocksMicLvlSat = 0;
1016 #ifdef WEBRTC_AGC_DEBUG_DUMP
1018 "\tAGC->ProcessAnalog, frame %d: measure >"
1019 " 2ndUpperLim, micVol = %d, maxLevel = %d\n",
1025 } else if (stt->Rxx160_LPw32 > stt->upperLimit)
1027 stt->msTooHigh += 2;
1029 stt->changeToSlowMode = 0;
1031 if (stt->msTooHigh > stt->msecSpeechInnerChange)
1033 /* Lower the recording level */
1035 /* Multiply by 0.828125 which corresponds to decreasing ~0.8dB */
1036 stt->Rxx160_LPw32 = (stt->Rxx160_LPw32 / 64) * 53;
1038 /* Reduce the max gain to avoid excessive oscillation
1039 * (but never drop below the maximum analog level).
1041 stt->maxLevel = (15 * stt->maxLevel + stt->micVol) / 16;
1042 stt->maxLevel = WEBRTC_SPL_MAX(stt->maxLevel, stt->maxAnalog);
1044 stt->zeroCtrlMax = stt->micVol;
1047 tmp32 = inMicLevelTmp - stt->minLevel;
1048 tmpU32 = WEBRTC_SPL_UMUL(31621, (uint32_t)(inMicLevelTmp - stt->minLevel));
1049 stt->micVol = (tmpU32 >> 15) + stt->minLevel;
1050 if (stt->micVol > lastMicVol - 1)
1052 stt->micVol = lastMicVol - 1;
1054 inMicLevelTmp = stt->micVol;
1056 #ifdef MIC_LEVEL_FEEDBACK
1057 //stt->numBlocksMicLvlSat = 0;
1059 #ifdef WEBRTC_AGC_DEBUG_DUMP
1061 "\tAGC->ProcessAnalog, frame %d: measure >"
1062 " UpperLim, micVol = %d, maxLevel = %d\n",
1068 } else if (stt->Rxx160_LPw32 < stt->lowerSecondaryLimit)
1071 stt->changeToSlowMode = 0;
1074 if (stt->msTooLow > stt->msecSpeechOuterChange)
1076 /* Raise the recording level */
1077 int16_t index, weightFIX;
1078 int16_t volNormFIX = 16384; // =1 in Q14.
1082 /* Normalize the volume level */
1083 tmp32 = (inMicLevelTmp - stt->minLevel) << 14;
1084 if (stt->maxInit != stt->minLevel)
1086 volNormFIX = tmp32 / (stt->maxInit - stt->minLevel);
1089 /* Find correct curve */
1090 WebRtcAgc_ExpCurve(volNormFIX, &index);
1092 /* Compute weighting factor for the volume increase, 32^(-2*X)/2+1.05 */
1093 weightFIX = kOffset1[index]
1094 - (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(kSlope1[index],
1097 /* stt->Rxx160_LPw32 *= 1.047 [~0.2 dB]; */
1098 stt->Rxx160_LPw32 = (stt->Rxx160_LPw32 / 64) * 67;
1100 tmp32 = inMicLevelTmp - stt->minLevel;
1101 tmpU32 = ((uint32_t)weightFIX * (uint32_t)(inMicLevelTmp - stt->minLevel));
1102 stt->micVol = (tmpU32 >> 14) + stt->minLevel;
1103 if (stt->micVol < lastMicVol + 2)
1105 stt->micVol = lastMicVol + 2;
1108 inMicLevelTmp = stt->micVol;
1110 #ifdef MIC_LEVEL_FEEDBACK
1111 /* Count ms in level saturation */
1112 //if (stt->micVol > stt->maxAnalog) {
1113 if (stt->micVol > 150)
1115 /* mic level is saturated */
1116 stt->numBlocksMicLvlSat++;
1117 fprintf(stderr, "Sat mic Level: %d\n", stt->numBlocksMicLvlSat);
1120 #ifdef WEBRTC_AGC_DEBUG_DUMP
1122 "\tAGC->ProcessAnalog, frame %d: measure <"
1123 " 2ndLowerLim, micVol = %d\n",
1128 } else if (stt->Rxx160_LPw32 < stt->lowerLimit)
1131 stt->changeToSlowMode = 0;
1134 if (stt->msTooLow > stt->msecSpeechInnerChange)
1136 /* Raise the recording level */
1137 int16_t index, weightFIX;
1138 int16_t volNormFIX = 16384; // =1 in Q14.
1142 /* Normalize the volume level */
1143 tmp32 = (inMicLevelTmp - stt->minLevel) << 14;
1144 if (stt->maxInit != stt->minLevel)
1146 volNormFIX = tmp32 / (stt->maxInit - stt->minLevel);
1149 /* Find correct curve */
1150 WebRtcAgc_ExpCurve(volNormFIX, &index);
1152 /* Compute weighting factor for the volume increase, (3.^(-2.*X))/8+1 */
1153 weightFIX = kOffset2[index]
1154 - (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(kSlope2[index],
1157 /* stt->Rxx160_LPw32 *= 1.047 [~0.2 dB]; */
1158 stt->Rxx160_LPw32 = (stt->Rxx160_LPw32 / 64) * 67;
1160 tmp32 = inMicLevelTmp - stt->minLevel;
1161 tmpU32 = ((uint32_t)weightFIX * (uint32_t)(inMicLevelTmp - stt->minLevel));
1162 stt->micVol = (tmpU32 >> 14) + stt->minLevel;
1163 if (stt->micVol < lastMicVol + 1)
1165 stt->micVol = lastMicVol + 1;
1168 inMicLevelTmp = stt->micVol;
1170 #ifdef MIC_LEVEL_FEEDBACK
1171 /* Count ms in level saturation */
1172 //if (stt->micVol > stt->maxAnalog) {
1173 if (stt->micVol > 150)
1175 /* mic level is saturated */
1176 stt->numBlocksMicLvlSat++;
1177 fprintf(stderr, "Sat mic Level: %d\n", stt->numBlocksMicLvlSat);
1180 #ifdef WEBRTC_AGC_DEBUG_DUMP
1182 "\tAGC->ProcessAnalog, frame %d: measure < LowerLim, micVol = %d\n",
1190 /* The signal is inside the desired range which is:
1191 * lowerLimit < Rxx160_LP/640 < upperLimit
1193 if (stt->changeToSlowMode > 4000)
1195 stt->msecSpeechInnerChange = 1000;
1196 stt->msecSpeechOuterChange = 500;
1197 stt->upperLimit = stt->upperPrimaryLimit;
1198 stt->lowerLimit = stt->lowerPrimaryLimit;
1201 stt->changeToSlowMode += 2; // in milliseconds
1206 stt->micVol = inMicLevelTmp;
1209 #ifdef MIC_LEVEL_FEEDBACK
1210 if (stt->numBlocksMicLvlSat > NUM_BLOCKS_IN_SAT_BEFORE_CHANGE_TARGET)
1213 fprintf(stderr, "target before = %d (%d)\n", stt->analogTargetLevel, stt->targetIdx);
1214 WebRtcAgc_UpdateAgcThresholds(stt);
1215 WebRtcAgc_CalculateGainTable(&(stt->digitalAgc.gainTable[0]),
1216 stt->compressionGaindB, stt->targetLevelDbfs, stt->limiterEnable,
1218 stt->numBlocksMicLvlSat = 0;
1220 fprintf(stderr, "target offset = %d\n", stt->targetIdxOffset);
1221 fprintf(stderr, "target after = %d (%d)\n", stt->analogTargetLevel, stt->targetIdx);
1227 /* Ensure gain is not increased in presence of echo or after a mute event
1228 * (but allow the zeroCtrl() increase on the frame of a mute detection).
1230 if (echo == 1 || (stt->muteGuardMs > 0 && stt->muteGuardMs < kMuteGuardTimeMs))
1232 if (stt->micVol > lastMicVol)
1234 stt->micVol = lastMicVol;
1238 /* limit the gain */
1239 if (stt->micVol > stt->maxLevel)
1241 stt->micVol = stt->maxLevel;
1242 } else if (stt->micVol < stt->minOutput)
1244 stt->micVol = stt->minOutput;
1247 *outMicLevel = WEBRTC_SPL_MIN(stt->micVol, stt->maxAnalog) >> stt->scale;
1252 int WebRtcAgc_Process(void *agcInst, const int16_t *in_near,
1253 const int16_t *in_near_H, int16_t samples,
1254 int16_t *out, int16_t *out_H, int32_t inMicLevel,
1255 int32_t *outMicLevel, int16_t echo,
1256 uint8_t *saturationWarning)
1259 int32_t inMicLevelTmp;
1260 int16_t subFrames, i;
1261 uint8_t satWarningTmp = 0;
1263 stt = (Agc_t *)agcInst;
1273 if (stt->fs == 8000)
1275 if ((samples != 80) && (samples != 160))
1277 #ifdef WEBRTC_AGC_DEBUG_DUMP
1279 "AGC->Process, frame %d: Invalid number of samples\n\n",
1285 } else if (stt->fs == 16000)
1287 if ((samples != 160) && (samples != 320))
1289 #ifdef WEBRTC_AGC_DEBUG_DUMP
1291 "AGC->Process, frame %d: Invalid number of samples\n\n",
1297 } else if (stt->fs == 32000)
1299 if ((samples != 160) && (samples != 320))
1301 #ifdef WEBRTC_AGC_DEBUG_DUMP
1303 "AGC->Process, frame %d: Invalid number of samples\n\n",
1311 #ifdef WEBRTC_AGC_DEBUG_DUMP
1313 "AGC->Process, frame %d: Invalid sample rate\n\n",
1319 /* Check for valid pointers based on sampling rate */
1320 if (stt->fs == 32000 && in_near_H == NULL)
1324 /* Check for valid pointers for low band */
1325 if (in_near == NULL)
1330 *saturationWarning = 0;
1331 //TODO: PUT IN RANGE CHECKING FOR INPUT LEVELS
1332 *outMicLevel = inMicLevel;
1333 inMicLevelTmp = inMicLevel;
1335 // TODO(andrew): clearly we don't need input and output pointers...
1336 // Change the interface to take a shared input/output.
1339 // Only needed if they don't already point to the same place.
1340 memcpy(out, in_near, samples * sizeof(int16_t));
1342 if (stt->fs == 32000)
1344 if (in_near_H != out_H)
1346 memcpy(out_H, in_near_H, samples * sizeof(int16_t));
1350 #ifdef WEBRTC_AGC_DEBUG_DUMP
1354 for (i = 0; i < samples; i += subFrames)
1356 if (WebRtcAgc_ProcessDigital(&stt->digitalAgc, &in_near[i], &in_near_H[i], &out[i], &out_H[i],
1357 stt->fs, stt->lowLevelSignal) == -1)
1359 #ifdef WEBRTC_AGC_DEBUG_DUMP
1361 "AGC->Process, frame %d: Error from DigAGC\n\n",
1366 if ((stt->agcMode < kAgcModeFixedDigital) && ((stt->lowLevelSignal == 0)
1367 || (stt->agcMode != kAgcModeAdaptiveDigital)))
1369 if (WebRtcAgc_ProcessAnalog(agcInst, inMicLevelTmp, outMicLevel,
1370 stt->vadMic.logRatio, echo, saturationWarning) == -1)
1375 #ifdef WEBRTC_AGC_DEBUG_DUMP
1376 fprintf(stt->agcLog,
1377 "%5d\t%d\t%d\t%d\t%d\n",
1386 if (stt->inQueue > 1)
1388 memcpy(stt->env[0], stt->env[1], 10 * sizeof(int32_t));
1389 memcpy(stt->Rxx16w32_array[0], stt->Rxx16w32_array[1], 5 * sizeof(int32_t));
1392 if (stt->inQueue > 0)
1397 /* If 20ms frames are used the input mic level must be updated so that
1398 * the analog AGC does not think that there has been a manual volume
1400 inMicLevelTmp = *outMicLevel;
1402 /* Store a positive saturation warning. */
1403 if (*saturationWarning == 1)
1409 /* Trigger the saturation warning if displayed by any of the frames. */
1410 *saturationWarning = satWarningTmp;
1415 int WebRtcAgc_set_config(void *agcInst, WebRtcAgc_config_t agcConfig)
1418 stt = (Agc_t *)agcInst;
1425 if (stt->initFlag != kInitCheck)
1427 stt->lastError = AGC_UNINITIALIZED_ERROR;
1431 if (agcConfig.limiterEnable != kAgcFalse && agcConfig.limiterEnable != kAgcTrue)
1433 stt->lastError = AGC_BAD_PARAMETER_ERROR;
1436 stt->limiterEnable = agcConfig.limiterEnable;
1437 stt->compressionGaindB = agcConfig.compressionGaindB;
1438 if ((agcConfig.targetLevelDbfs < 0) || (agcConfig.targetLevelDbfs > 31))
1440 stt->lastError = AGC_BAD_PARAMETER_ERROR;
1443 stt->targetLevelDbfs = agcConfig.targetLevelDbfs;
1445 if (stt->agcMode == kAgcModeFixedDigital)
1447 /* Adjust for different parameter interpretation in FixedDigital mode */
1448 stt->compressionGaindB += agcConfig.targetLevelDbfs;
1451 /* Update threshold levels for analog adaptation */
1452 WebRtcAgc_UpdateAgcThresholds(stt);
1454 /* Recalculate gain table */
1455 if (WebRtcAgc_CalculateGainTable(&(stt->digitalAgc.gainTable[0]), stt->compressionGaindB,
1456 stt->targetLevelDbfs, stt->limiterEnable, stt->analogTarget) == -1)
1458 #ifdef WEBRTC_AGC_DEBUG_DUMP
1460 "AGC->set_config, frame %d: Error from calcGainTable\n\n",
1465 /* Store the config in a WebRtcAgc_config_t */
1466 stt->usedConfig.compressionGaindB = agcConfig.compressionGaindB;
1467 stt->usedConfig.limiterEnable = agcConfig.limiterEnable;
1468 stt->usedConfig.targetLevelDbfs = agcConfig.targetLevelDbfs;
1473 int WebRtcAgc_get_config(void *agcInst, WebRtcAgc_config_t *config)
1476 stt = (Agc_t *)agcInst;
1485 stt->lastError = AGC_NULL_POINTER_ERROR;
1489 if (stt->initFlag != kInitCheck)
1491 stt->lastError = AGC_UNINITIALIZED_ERROR;
1495 config->limiterEnable = stt->usedConfig.limiterEnable;
1496 config->targetLevelDbfs = stt->usedConfig.targetLevelDbfs;
1497 config->compressionGaindB = stt->usedConfig.compressionGaindB;
1502 int WebRtcAgc_Create(void **agcInst)
1505 if (agcInst == NULL)
1509 stt = (Agc_t *)malloc(sizeof(Agc_t));
1517 #ifdef WEBRTC_AGC_DEBUG_DUMP
1518 stt->fpt = fopen("./agc_test_log.txt", "wt");
1519 stt->agcLog = fopen("./agc_debug_log.txt", "wt");
1520 stt->digitalAgc.logFile = fopen("./agc_log.txt", "wt");
1529 int WebRtcAgc_Free(void *state)
1533 stt = (Agc_t *)state;
1534 #ifdef WEBRTC_AGC_DEBUG_DUMP
1536 fclose(stt->agcLog);
1537 fclose(stt->digitalAgc.logFile);
1544 /* minLevel - Minimum volume level
1545 * maxLevel - Maximum volume level
1547 int WebRtcAgc_Init(void *agcInst, int32_t minLevel, int32_t maxLevel,
1548 int16_t agcMode, uint32_t fs)
1550 int32_t max_add, tmp32;
1555 /* typecast state pointer */
1556 stt = (Agc_t *)agcInst;
1558 if (WebRtcAgc_InitDigital(&stt->digitalAgc, agcMode) != 0)
1560 stt->lastError = AGC_UNINITIALIZED_ERROR;
1564 /* Analog AGC variables */
1567 /* mode = 0 - Only saturation protection
1568 * 1 - Analog Automatic Gain Control [-targetLevelDbfs (default -3 dBOv)]
1569 * 2 - Digital Automatic Gain Control [-targetLevelDbfs (default -3 dBOv)]
1570 * 3 - Fixed Digital Gain [compressionGaindB (default 8 dB)]
1572 #ifdef WEBRTC_AGC_DEBUG_DUMP
1574 fprintf(stt->fpt, "AGC->Init\n");
1576 if (agcMode < kAgcModeUnchanged || agcMode > kAgcModeFixedDigital)
1578 #ifdef WEBRTC_AGC_DEBUG_DUMP
1579 fprintf(stt->fpt, "AGC->Init: error, incorrect mode\n\n");
1583 stt->agcMode = agcMode;
1586 /* initialize input VAD */
1587 WebRtcAgc_InitVad(&stt->vadMic);
1589 /* If the volume range is smaller than 0-256 then
1590 * the levels are shifted up to Q8-domain */
1591 tmpNorm = WebRtcSpl_NormU32((uint32_t)maxLevel);
1592 stt->scale = tmpNorm - 23;
1597 // TODO(bjornv): Investigate if we really need to scale up a small range now when we have
1598 // a guard against zero-increments. For now, we do not support scale up (scale = 0).
1600 maxLevel <<= stt->scale;
1601 minLevel <<= stt->scale;
1603 /* Make minLevel and maxLevel static in AdaptiveDigital */
1604 if (stt->agcMode == kAgcModeAdaptiveDigital)
1610 /* The maximum supplemental volume range is based on a vague idea
1611 * of how much lower the gain will be than the real analog gain. */
1612 max_add = (maxLevel - minLevel) / 4;
1614 /* Minimum/maximum volume level that can be set */
1615 stt->minLevel = minLevel;
1616 stt->maxAnalog = maxLevel;
1617 stt->maxLevel = maxLevel + max_add;
1618 stt->maxInit = stt->maxLevel;
1620 stt->zeroCtrlMax = stt->maxAnalog;
1621 stt->lastInMicLevel = 0;
1623 /* Initialize micVol parameter */
1624 stt->micVol = stt->maxAnalog;
1625 if (stt->agcMode == kAgcModeAdaptiveDigital)
1627 stt->micVol = 127; /* Mid-point of mic level */
1629 stt->micRef = stt->micVol;
1630 stt->micGainIdx = 127;
1631 #ifdef MIC_LEVEL_FEEDBACK
1632 stt->numBlocksMicLvlSat = 0;
1635 #ifdef WEBRTC_AGC_DEBUG_DUMP
1637 "AGC->Init: minLevel = %d, maxAnalog = %d, maxLevel = %d\n",
1643 /* Minimum output volume is 4% higher than the available lowest volume level */
1644 tmp32 = ((stt->maxLevel - stt->minLevel) * 10) >> 8;
1645 stt->minOutput = (stt->minLevel + tmp32);
1649 stt->changeToSlowMode = 0;
1652 stt->muteGuardMs = 0;
1653 stt->gainTableIdx = 0;
1655 stt->msecSpeechInnerChange = kMsecSpeechInner;
1656 stt->msecSpeechOuterChange = kMsecSpeechOuter;
1658 stt->activeSpeech = 0;
1659 stt->Rxx16_LPw32Max = 0;
1661 stt->vadThreshold = kNormalVadThreshold;
1664 for (i = 0; i < RXX_BUFFER_LEN; i++)
1666 stt->Rxx16_vectorw32[i] = (int32_t)1000; /* -54dBm0 */
1668 stt->Rxx160w32 = 125 * RXX_BUFFER_LEN; /* (stt->Rxx16_vectorw32[0]>>3) = 125 */
1671 stt->Rxx16_LPw32 = (int32_t)16284; /* Q(-4) */
1673 for (i = 0; i < 5; i++)
1675 stt->Rxx16w32_array[0][i] = 0;
1677 for (i = 0; i < 10; i++)
1684 #ifdef MIC_LEVEL_FEEDBACK
1685 stt->targetIdxOffset = 0;
1688 WebRtcSpl_MemSetW32(stt->filterState, 0, 8);
1690 stt->initFlag = kInitCheck;
1691 // Default config settings.
1692 stt->defaultConfig.limiterEnable = kAgcTrue;
1693 stt->defaultConfig.targetLevelDbfs = AGC_DEFAULT_TARGET_LEVEL;
1694 stt->defaultConfig.compressionGaindB = AGC_DEFAULT_COMP_GAIN;
1696 if (WebRtcAgc_set_config(stt, stt->defaultConfig) == -1)
1698 stt->lastError = AGC_UNSPECIFIED_ERROR;
1701 stt->Rxx160_LPw32 = stt->analogTargetLevel; // Initialize rms value
1703 stt->lowLevelSignal = 0;
1705 /* Only positive values are allowed that are not too large */
1706 if ((minLevel >= maxLevel) || (maxLevel & 0xFC000000))
1708 #ifdef WEBRTC_AGC_DEBUG_DUMP
1709 fprintf(stt->fpt, "minLevel, maxLevel value(s) are invalid\n\n");
1714 #ifdef WEBRTC_AGC_DEBUG_DUMP
1715 fprintf(stt->fpt, "\n");