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