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