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