Home | History | Annotate | Download | only in agc
      1 /*
      2  *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
      3  *
      4  *  Use of this source code is governed by a BSD-style license
      5  *  that can be found in the LICENSE file in the root of the source
      6  *  tree. An additional intellectual property rights grant can be found
      7  *  in the file PATENTS.  All contributing project authors may
      8  *  be found in the AUTHORS file in the root of the source tree.
      9  */
     10 
     11 /* analog_agc.c
     12  *
     13  * Using a feedback system, determines an appropriate analog volume level
     14  * given an input signal and current volume level. Targets a conservative
     15  * signal level and is intended for use with a digital AGC to apply
     16  * additional gain.
     17  *
     18  */
     19 
     20 #include <assert.h>
     21 #include <stdlib.h>
     22 #ifdef WEBRTC_AGC_DEBUG_DUMP
     23 #include <stdio.h>
     24 #endif
     25 #include "webrtc/modules/audio_processing/agc/analog_agc.h"
     26 
     27 /* The slope of in Q13*/
     28 static const int16_t kSlope1[8] = {21793, 12517, 7189, 4129, 2372, 1362, 472, 78};
     29 
     30 /* The offset in Q14 */
     31 static const int16_t kOffset1[8] = {25395, 23911, 22206, 20737, 19612, 18805, 17951,
     32         17367};
     33 
     34 /* The slope of in Q13*/
     35 static const int16_t kSlope2[8] = {2063, 1731, 1452, 1218, 1021, 857, 597, 337};
     36 
     37 /* The offset in Q14 */
     38 static const int16_t kOffset2[8] = {18432, 18379, 18290, 18177, 18052, 17920, 17670,
     39         17286};
     40 
     41 static const int16_t kMuteGuardTimeMs = 8000;
     42 static const int16_t 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 uint16_t kGainTableAnalog[GAIN_TBL_LEN] = {4096, 4251, 4412, 4579, 4752,
     76         4932, 5118, 5312, 5513, 5722, 5938, 6163, 6396, 6638, 6889, 7150, 7420, 7701, 7992,
     77         8295, 8609, 8934, 9273, 9623, 9987, 10365, 10758, 11165, 11587, 12025, 12480, 12953};
     78 
     79 /* Gain/Suppression tables for virtual Mic (in Q10) */
     80 static const uint16_t kGainTableVirtualMic[128] = {1052, 1081, 1110, 1141, 1172, 1204,
     81         1237, 1271, 1305, 1341, 1378, 1416, 1454, 1494, 1535, 1577, 1620, 1664, 1710, 1757,
     82         1805, 1854, 1905, 1957, 2010, 2065, 2122, 2180, 2239, 2301, 2364, 2428, 2495, 2563,
     83         2633, 2705, 2779, 2855, 2933, 3013, 3096, 3180, 3267, 3357, 3449, 3543, 3640, 3739,
     84         3842, 3947, 4055, 4166, 4280, 4397, 4517, 4640, 4767, 4898, 5032, 5169, 5311, 5456,
     85         5605, 5758, 5916, 6078, 6244, 6415, 6590, 6770, 6956, 7146, 7341, 7542, 7748, 7960,
     86         8178, 8402, 8631, 8867, 9110, 9359, 9615, 9878, 10148, 10426, 10711, 11004, 11305,
     87         11614, 11932, 12258, 12593, 12938, 13292, 13655, 14029, 14412, 14807, 15212, 15628,
     88         16055, 16494, 16945, 17409, 17885, 18374, 18877, 19393, 19923, 20468, 21028, 21603,
     89         22194, 22801, 23425, 24065, 24724, 25400, 26095, 26808, 27541, 28295, 29069, 29864,
     90         30681, 31520, 32382};
     91 static const uint16_t kSuppressionTableVirtualMic[128] = {1024, 1006, 988, 970, 952,
     92         935, 918, 902, 886, 870, 854, 839, 824, 809, 794, 780, 766, 752, 739, 726, 713, 700,
     93         687, 675, 663, 651, 639, 628, 616, 605, 594, 584, 573, 563, 553, 543, 533, 524, 514,
     94         505, 496, 487, 478, 470, 461, 453, 445, 437, 429, 421, 414, 406, 399, 392, 385, 378,
     95         371, 364, 358, 351, 345, 339, 333, 327, 321, 315, 309, 304, 298, 293, 288, 283, 278,
     96         273, 268, 263, 258, 254, 249, 244, 240, 236, 232, 227, 223, 219, 215, 211, 208, 204,
     97         200, 197, 193, 190, 186, 183, 180, 176, 173, 170, 167, 164, 161, 158, 155, 153, 150,
     98         147, 145, 142, 139, 137, 134, 132, 130, 127, 125, 123, 121, 118, 116, 114, 112, 110,
     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 int32_t kTargetLevelTable[64] = {134209536, 106606424, 84680493, 67264106,
    106         53429779, 42440782, 33711911, 26778323, 21270778, 16895980, 13420954, 10660642,
    107         8468049, 6726411, 5342978, 4244078, 3371191, 2677832, 2127078, 1689598, 1342095,
    108         1066064, 846805, 672641, 534298, 424408, 337119, 267783, 212708, 168960, 134210,
    109         106606, 84680, 67264, 53430, 42441, 33712, 26778, 21271, 16896, 13421, 10661, 8468,
    110         6726, 5343, 4244, 3371, 2678, 2127, 1690, 1342, 1066, 847, 673, 534, 424, 337, 268,
    111         213, 169, 134, 107, 85, 67};
    112 
    113 int WebRtcAgc_AddMic(void *state, int16_t *in_mic, int16_t *in_mic_H,
    114                      int16_t samples)
    115 {
    116     int32_t nrg, max_nrg, sample, tmp32;
    117     int32_t *ptr;
    118     uint16_t targetGainIdx, gain;
    119     int16_t 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 WEBRTC_AGC_DEBUG_DUMP
    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 WEBRTC_AGC_DEBUG_DUMP
    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 WEBRTC_AGC_DEBUG_DUMP
    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 = (int16_t)(stt->micVol - stt->maxAnalog);
    209         tmp32 = WEBRTC_SPL_MUL_16_16(GAIN_TBL_LEN - 1, tmp16);
    210         tmp16 = (int16_t)(stt->maxLevel - stt->maxAnalog);
    211         targetGainIdx = tmp32 / tmp16;
    212         assert(targetGainIdx < GAIN_TBL_LEN);
    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] = (int16_t)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] = (int16_t)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 
    330 int WebRtcAgc_AddFarend(void *state, const int16_t *in_far, int16_t samples)
    331 {
    332     int32_t errHandle = 0;
    333     int16_t 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 WEBRTC_AGC_DEBUG_DUMP
    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 WEBRTC_AGC_DEBUG_DUMP
    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 WEBRTC_AGC_DEBUG_DUMP
    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 WEBRTC_AGC_DEBUG_DUMP
    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 
    396 int WebRtcAgc_VirtualMic(void *agcInst, int16_t *in_near, int16_t *in_near_H,
    397                          int16_t samples, int32_t micLevelIn,
    398                          int32_t *micLevelOut)
    399 {
    400     int32_t tmpFlt, micLevelTmp, gainIdx;
    401     uint16_t gain;
    402     int16_t ii;
    403     Agc_t *stt;
    404 
    405     uint32_t nrg;
    406     int16_t sampleCntr;
    407     uint32_t frameNrg = 0;
    408     uint32_t frameNrgLimit = 5500;
    409     int16_t numZeroCrossing = 0;
    410     const int16_t kZeroCrossingLowLim = 15;
    411     const int16_t 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] = (int16_t)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] = (int16_t)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 
    538 void WebRtcAgc_UpdateAgcThresholds(Agc_t *stt)
    539 {
    540 
    541     int16_t 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((int32_t)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 
    590 void WebRtcAgc_SaturationCtrl(Agc_t *stt, uint8_t *saturated, int32_t *env)
    591 {
    592     int16_t i, tmpW16;
    593 
    594     /* Check if the signal is saturated */
    595     for (i = 0; i < 10; i++)
    596     {
    597         tmpW16 = (int16_t)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 = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(stt->envSum,
    612             (int16_t)32440, 15);
    613 }
    614 
    615 void WebRtcAgc_ZeroCtrl(Agc_t *stt, int32_t *inMicLevel, int32_t *env)
    616 {
    617     int16_t i;
    618     int32_t tmp32 = 0;
    619     int32_t 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 WEBRTC_AGC_DEBUG_DUMP
    661         fprintf(stt->fpt,
    662                 "\t\tAGC->zeroCntrl, frame %d: 500 ms under threshold,"
    663                 " micVol: %d\n",
    664                 stt->fcount,
    665                 stt->micVol);
    666 #endif
    667 
    668         stt->activeSpeech = 0;
    669         stt->Rxx16_LPw32Max = 0;
    670 
    671         /* The AGC has a tendency (due to problems with the VAD parameters), to
    672          * vastly increase the volume after a muting event. This timer prevents
    673          * upwards adaptation for a short period. */
    674         stt->muteGuardMs = kMuteGuardTimeMs;
    675     }
    676 }
    677 
    678 void WebRtcAgc_SpeakerInactiveCtrl(Agc_t *stt)
    679 {
    680     /* Check if the near end speaker is inactive.
    681      * If that is the case the VAD threshold is
    682      * increased since the VAD speech model gets
    683      * more sensitive to any sound after a long
    684      * silence.
    685      */
    686 
    687     int32_t tmp32;
    688     int16_t vadThresh;
    689 
    690     if (stt->vadMic.stdLongTerm < 2500)
    691     {
    692         stt->vadThreshold = 1500;
    693     } else
    694     {
    695         vadThresh = kNormalVadThreshold;
    696         if (stt->vadMic.stdLongTerm < 4500)
    697         {
    698             /* Scale between min and max threshold */
    699             vadThresh += WEBRTC_SPL_RSHIFT_W16(4500 - stt->vadMic.stdLongTerm, 1);
    700         }
    701 
    702         /* stt->vadThreshold = (31 * stt->vadThreshold + vadThresh) / 32; */
    703         tmp32 = (int32_t)vadThresh;
    704         tmp32 += WEBRTC_SPL_MUL_16_16((int16_t)31, stt->vadThreshold);
    705         stt->vadThreshold = (int16_t)WEBRTC_SPL_RSHIFT_W32(tmp32, 5);
    706     }
    707 }
    708 
    709 void WebRtcAgc_ExpCurve(int16_t volume, int16_t *index)
    710 {
    711     // volume in Q14
    712     // index in [0-7]
    713     /* 8 different curves */
    714     if (volume > 5243)
    715     {
    716         if (volume > 7864)
    717         {
    718             if (volume > 12124)
    719             {
    720                 *index = 7;
    721             } else
    722             {
    723                 *index = 6;
    724             }
    725         } else
    726         {
    727             if (volume > 6554)
    728             {
    729                 *index = 5;
    730             } else
    731             {
    732                 *index = 4;
    733             }
    734         }
    735     } else
    736     {
    737         if (volume > 2621)
    738         {
    739             if (volume > 3932)
    740             {
    741                 *index = 3;
    742             } else
    743             {
    744                 *index = 2;
    745             }
    746         } else
    747         {
    748             if (volume > 1311)
    749             {
    750                 *index = 1;
    751             } else
    752             {
    753                 *index = 0;
    754             }
    755         }
    756     }
    757 }
    758 
    759 int32_t WebRtcAgc_ProcessAnalog(void *state, int32_t inMicLevel,
    760                                 int32_t *outMicLevel,
    761                                 int16_t vadLogRatio,
    762                                 int16_t echo, uint8_t *saturationWarning)
    763 {
    764     uint32_t tmpU32;
    765     int32_t Rxx16w32, tmp32;
    766     int32_t inMicLevelTmp, lastMicVol;
    767     int16_t i;
    768     uint8_t saturated = 0;
    769     Agc_t *stt;
    770 
    771     stt = (Agc_t *)state;
    772     inMicLevelTmp = WEBRTC_SPL_LSHIFT_W32(inMicLevel, stt->scale);
    773 
    774     if (inMicLevelTmp > stt->maxAnalog)
    775     {
    776 #ifdef WEBRTC_AGC_DEBUG_DUMP
    777         fprintf(stt->fpt,
    778                 "\tAGC->ProcessAnalog, frame %d: micLvl > maxAnalog\n",
    779                 stt->fcount);
    780 #endif
    781         return -1;
    782     } else if (inMicLevelTmp < stt->minLevel)
    783     {
    784 #ifdef WEBRTC_AGC_DEBUG_DUMP
    785         fprintf(stt->fpt,
    786                 "\tAGC->ProcessAnalog, frame %d: micLvl < minLevel\n",
    787                 stt->fcount);
    788 #endif
    789         return -1;
    790     }
    791 
    792     if (stt->firstCall == 0)
    793     {
    794         int32_t tmpVol;
    795         stt->firstCall = 1;
    796         tmp32 = WEBRTC_SPL_RSHIFT_W32((stt->maxLevel - stt->minLevel) * (int32_t)51, 9);
    797         tmpVol = (stt->minLevel + tmp32);
    798 
    799         /* If the mic level is very low at start, increase it! */
    800         if ((inMicLevelTmp < tmpVol) && (stt->agcMode == kAgcModeAdaptiveAnalog))
    801         {
    802             inMicLevelTmp = tmpVol;
    803         }
    804         stt->micVol = inMicLevelTmp;
    805     }
    806 
    807     /* Set the mic level to the previous output value if there is digital input gain */
    808     if ((inMicLevelTmp == stt->maxAnalog) && (stt->micVol > stt->maxAnalog))
    809     {
    810         inMicLevelTmp = stt->micVol;
    811     }
    812 
    813     /* If the mic level was manually changed to a very low value raise it! */
    814     if ((inMicLevelTmp != stt->micVol) && (inMicLevelTmp < stt->minOutput))
    815     {
    816         tmp32 = WEBRTC_SPL_RSHIFT_W32((stt->maxLevel - stt->minLevel) * (int32_t)51, 9);
    817         inMicLevelTmp = (stt->minLevel + tmp32);
    818         stt->micVol = inMicLevelTmp;
    819 #ifdef MIC_LEVEL_FEEDBACK
    820         //stt->numBlocksMicLvlSat = 0;
    821 #endif
    822 #ifdef WEBRTC_AGC_DEBUG_DUMP
    823         fprintf(stt->fpt,
    824                 "\tAGC->ProcessAnalog, frame %d: micLvl < minLevel by manual"
    825                 " decrease, raise vol\n",
    826                 stt->fcount);
    827 #endif
    828     }
    829 
    830     if (inMicLevelTmp != stt->micVol)
    831     {
    832         if (inMicLevel == stt->lastInMicLevel) {
    833             // We requested a volume adjustment, but it didn't occur. This is
    834             // probably due to a coarse quantization of the volume slider.
    835             // Restore the requested value to prevent getting stuck.
    836             inMicLevelTmp = stt->micVol;
    837         }
    838         else {
    839             // As long as the value changed, update to match.
    840             stt->micVol = inMicLevelTmp;
    841         }
    842     }
    843 
    844     if (inMicLevelTmp > stt->maxLevel)
    845     {
    846         // Always allow the user to raise the volume above the maxLevel.
    847         stt->maxLevel = inMicLevelTmp;
    848     }
    849 
    850     // Store last value here, after we've taken care of manual updates etc.
    851     stt->lastInMicLevel = inMicLevel;
    852     lastMicVol = stt->micVol;
    853 
    854     /* Checks if the signal is saturated. Also a check if individual samples
    855      * are larger than 12000 is done. If they are the counter for increasing
    856      * the volume level is set to -100ms
    857      */
    858     WebRtcAgc_SaturationCtrl(stt, &saturated, stt->env[0]);
    859 
    860     /* The AGC is always allowed to lower the level if the signal is saturated */
    861     if (saturated == 1)
    862     {
    863         /* Lower the recording level
    864          * Rxx160_LP is adjusted down because it is so slow it could
    865          * cause the AGC to make wrong decisions. */
    866         /* stt->Rxx160_LPw32 *= 0.875; */
    867         stt->Rxx160_LPw32 = WEBRTC_SPL_MUL(WEBRTC_SPL_RSHIFT_W32(stt->Rxx160_LPw32, 3), 7);
    868 
    869         stt->zeroCtrlMax = stt->micVol;
    870 
    871         /* stt->micVol *= 0.903; */
    872         tmp32 = inMicLevelTmp - stt->minLevel;
    873         tmpU32 = WEBRTC_SPL_UMUL(29591, (uint32_t)(tmp32));
    874         stt->micVol = (int32_t)WEBRTC_SPL_RSHIFT_U32(tmpU32, 15) + stt->minLevel;
    875         if (stt->micVol > lastMicVol - 2)
    876         {
    877             stt->micVol = lastMicVol - 2;
    878         }
    879         inMicLevelTmp = stt->micVol;
    880 
    881 #ifdef WEBRTC_AGC_DEBUG_DUMP
    882         fprintf(stt->fpt,
    883                 "\tAGC->ProcessAnalog, frame %d: saturated, micVol = %d\n",
    884                 stt->fcount,
    885                 stt->micVol);
    886 #endif
    887 
    888         if (stt->micVol < stt->minOutput)
    889         {
    890             *saturationWarning = 1;
    891         }
    892 
    893         /* Reset counter for decrease of volume level to avoid
    894          * decreasing too much. The saturation control can still
    895          * lower the level if needed. */
    896         stt->msTooHigh = -100;
    897 
    898         /* Enable the control mechanism to ensure that our measure,
    899          * Rxx160_LP, is in the correct range. This must be done since
    900          * the measure is very slow. */
    901         stt->activeSpeech = 0;
    902         stt->Rxx16_LPw32Max = 0;
    903 
    904         /* Reset to initial values */
    905         stt->msecSpeechInnerChange = kMsecSpeechInner;
    906         stt->msecSpeechOuterChange = kMsecSpeechOuter;
    907         stt->changeToSlowMode = 0;
    908 
    909         stt->muteGuardMs = 0;
    910 
    911         stt->upperLimit = stt->startUpperLimit;
    912         stt->lowerLimit = stt->startLowerLimit;
    913 #ifdef MIC_LEVEL_FEEDBACK
    914         //stt->numBlocksMicLvlSat = 0;
    915 #endif
    916     }
    917 
    918     /* Check if the input speech is zero. If so the mic volume
    919      * is increased. On some computers the input is zero up as high
    920      * level as 17% */
    921     WebRtcAgc_ZeroCtrl(stt, &inMicLevelTmp, stt->env[0]);
    922 
    923     /* Check if the near end speaker is inactive.
    924      * If that is the case the VAD threshold is
    925      * increased since the VAD speech model gets
    926      * more sensitive to any sound after a long
    927      * silence.
    928      */
    929     WebRtcAgc_SpeakerInactiveCtrl(stt);
    930 
    931     for (i = 0; i < 5; i++)
    932     {
    933         /* Computed on blocks of 16 samples */
    934 
    935         Rxx16w32 = stt->Rxx16w32_array[0][i];
    936 
    937         /* Rxx160w32 in Q(-7) */
    938         tmp32 = WEBRTC_SPL_RSHIFT_W32(Rxx16w32 - stt->Rxx16_vectorw32[stt->Rxx16pos], 3);
    939         stt->Rxx160w32 = stt->Rxx160w32 + tmp32;
    940         stt->Rxx16_vectorw32[stt->Rxx16pos] = Rxx16w32;
    941 
    942         /* Circular buffer */
    943         stt->Rxx16pos++;
    944         if (stt->Rxx16pos == RXX_BUFFER_LEN)
    945         {
    946             stt->Rxx16pos = 0;
    947         }
    948 
    949         /* Rxx16_LPw32 in Q(-4) */
    950         tmp32 = WEBRTC_SPL_RSHIFT_W32(Rxx16w32 - stt->Rxx16_LPw32, kAlphaShortTerm);
    951         stt->Rxx16_LPw32 = (stt->Rxx16_LPw32) + tmp32;
    952 
    953         if (vadLogRatio > stt->vadThreshold)
    954         {
    955             /* Speech detected! */
    956 
    957             /* Check if Rxx160_LP is in the correct range. If
    958              * it is too high/low then we set it to the maximum of
    959              * Rxx16_LPw32 during the first 200ms of speech.
    960              */
    961             if (stt->activeSpeech < 250)
    962             {
    963                 stt->activeSpeech += 2;
    964 
    965                 if (stt->Rxx16_LPw32 > stt->Rxx16_LPw32Max)
    966                 {
    967                     stt->Rxx16_LPw32Max = stt->Rxx16_LPw32;
    968                 }
    969             } else if (stt->activeSpeech == 250)
    970             {
    971                 stt->activeSpeech += 2;
    972                 tmp32 = WEBRTC_SPL_RSHIFT_W32(stt->Rxx16_LPw32Max, 3);
    973                 stt->Rxx160_LPw32 = WEBRTC_SPL_MUL(tmp32, RXX_BUFFER_LEN);
    974             }
    975 
    976             tmp32 = WEBRTC_SPL_RSHIFT_W32(stt->Rxx160w32 - stt->Rxx160_LPw32, kAlphaLongTerm);
    977             stt->Rxx160_LPw32 = stt->Rxx160_LPw32 + tmp32;
    978 
    979             if (stt->Rxx160_LPw32 > stt->upperSecondaryLimit)
    980             {
    981                 stt->msTooHigh += 2;
    982                 stt->msTooLow = 0;
    983                 stt->changeToSlowMode = 0;
    984 
    985                 if (stt->msTooHigh > stt->msecSpeechOuterChange)
    986                 {
    987                     stt->msTooHigh = 0;
    988 
    989                     /* Lower the recording level */
    990                     /* Multiply by 0.828125 which corresponds to decreasing ~0.8dB */
    991                     tmp32 = WEBRTC_SPL_RSHIFT_W32(stt->Rxx160_LPw32, 6);
    992                     stt->Rxx160_LPw32 = WEBRTC_SPL_MUL(tmp32, 53);
    993 
    994                     /* Reduce the max gain to avoid excessive oscillation
    995                      * (but never drop below the maximum analog level).
    996                      * stt->maxLevel = (15 * stt->maxLevel + stt->micVol) / 16;
    997                      */
    998                     tmp32 = (15 * stt->maxLevel) + stt->micVol;
    999                     stt->maxLevel = WEBRTC_SPL_RSHIFT_W32(tmp32, 4);
   1000                     stt->maxLevel = WEBRTC_SPL_MAX(stt->maxLevel, stt->maxAnalog);
   1001 
   1002                     stt->zeroCtrlMax = stt->micVol;
   1003 
   1004                     /* 0.95 in Q15 */
   1005                     tmp32 = inMicLevelTmp - stt->minLevel;
   1006                     tmpU32 = WEBRTC_SPL_UMUL(31130, (uint32_t)(tmp32));
   1007                     stt->micVol = (int32_t)WEBRTC_SPL_RSHIFT_U32(tmpU32, 15) + stt->minLevel;
   1008                     if (stt->micVol > lastMicVol - 1)
   1009                     {
   1010                         stt->micVol = lastMicVol - 1;
   1011                     }
   1012                     inMicLevelTmp = stt->micVol;
   1013 
   1014                     /* Enable the control mechanism to ensure that our measure,
   1015                      * Rxx160_LP, is in the correct range.
   1016                      */
   1017                     stt->activeSpeech = 0;
   1018                     stt->Rxx16_LPw32Max = 0;
   1019 #ifdef MIC_LEVEL_FEEDBACK
   1020                     //stt->numBlocksMicLvlSat = 0;
   1021 #endif
   1022 #ifdef WEBRTC_AGC_DEBUG_DUMP
   1023                     fprintf(stt->fpt,
   1024                             "\tAGC->ProcessAnalog, frame %d: measure >"
   1025                             " 2ndUpperLim, micVol = %d, maxLevel = %d\n",
   1026                             stt->fcount,
   1027                             stt->micVol,
   1028                             stt->maxLevel);
   1029 #endif
   1030                 }
   1031             } else if (stt->Rxx160_LPw32 > stt->upperLimit)
   1032             {
   1033                 stt->msTooHigh += 2;
   1034                 stt->msTooLow = 0;
   1035                 stt->changeToSlowMode = 0;
   1036 
   1037                 if (stt->msTooHigh > stt->msecSpeechInnerChange)
   1038                 {
   1039                     /* Lower the recording level */
   1040                     stt->msTooHigh = 0;
   1041                     /* Multiply by 0.828125 which corresponds to decreasing ~0.8dB */
   1042                     tmp32 = WEBRTC_SPL_RSHIFT_W32(stt->Rxx160_LPw32, 6);
   1043                     stt->Rxx160_LPw32 = WEBRTC_SPL_MUL(tmp32, 53);
   1044 
   1045                     /* Reduce the max gain to avoid excessive oscillation
   1046                      * (but never drop below the maximum analog level).
   1047                      * stt->maxLevel = (15 * stt->maxLevel + stt->micVol) / 16;
   1048                      */
   1049                     tmp32 = (15 * stt->maxLevel) + stt->micVol;
   1050                     stt->maxLevel = WEBRTC_SPL_RSHIFT_W32(tmp32, 4);
   1051                     stt->maxLevel = WEBRTC_SPL_MAX(stt->maxLevel, stt->maxAnalog);
   1052 
   1053                     stt->zeroCtrlMax = stt->micVol;
   1054 
   1055                     /* 0.965 in Q15 */
   1056                     tmp32 = inMicLevelTmp - stt->minLevel;
   1057                     tmpU32 = WEBRTC_SPL_UMUL(31621, (uint32_t)(inMicLevelTmp - stt->minLevel));
   1058                     stt->micVol = (int32_t)WEBRTC_SPL_RSHIFT_U32(tmpU32, 15) + stt->minLevel;
   1059                     if (stt->micVol > lastMicVol - 1)
   1060                     {
   1061                         stt->micVol = lastMicVol - 1;
   1062                     }
   1063                     inMicLevelTmp = stt->micVol;
   1064 
   1065 #ifdef MIC_LEVEL_FEEDBACK
   1066                     //stt->numBlocksMicLvlSat = 0;
   1067 #endif
   1068 #ifdef WEBRTC_AGC_DEBUG_DUMP
   1069                     fprintf(stt->fpt,
   1070                             "\tAGC->ProcessAnalog, frame %d: measure >"
   1071                             " UpperLim, micVol = %d, maxLevel = %d\n",
   1072                             stt->fcount,
   1073                             stt->micVol,
   1074                             stt->maxLevel);
   1075 #endif
   1076                 }
   1077             } else if (stt->Rxx160_LPw32 < stt->lowerSecondaryLimit)
   1078             {
   1079                 stt->msTooHigh = 0;
   1080                 stt->changeToSlowMode = 0;
   1081                 stt->msTooLow += 2;
   1082 
   1083                 if (stt->msTooLow > stt->msecSpeechOuterChange)
   1084                 {
   1085                     /* Raise the recording level */
   1086                     int16_t index, weightFIX;
   1087                     int16_t volNormFIX = 16384; // =1 in Q14.
   1088 
   1089                     stt->msTooLow = 0;
   1090 
   1091                     /* Normalize the volume level */
   1092                     tmp32 = WEBRTC_SPL_LSHIFT_W32(inMicLevelTmp - stt->minLevel, 14);
   1093                     if (stt->maxInit != stt->minLevel)
   1094                     {
   1095                         volNormFIX = tmp32 / (stt->maxInit - stt->minLevel);
   1096                     }
   1097 
   1098                     /* Find correct curve */
   1099                     WebRtcAgc_ExpCurve(volNormFIX, &index);
   1100 
   1101                     /* Compute weighting factor for the volume increase, 32^(-2*X)/2+1.05 */
   1102                     weightFIX = kOffset1[index]
   1103                               - (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(kSlope1[index],
   1104                                                                          volNormFIX, 13);
   1105 
   1106                     /* stt->Rxx160_LPw32 *= 1.047 [~0.2 dB]; */
   1107                     tmp32 = WEBRTC_SPL_RSHIFT_W32(stt->Rxx160_LPw32, 6);
   1108                     stt->Rxx160_LPw32 = WEBRTC_SPL_MUL(tmp32, 67);
   1109 
   1110                     tmp32 = inMicLevelTmp - stt->minLevel;
   1111                     tmpU32 = ((uint32_t)weightFIX * (uint32_t)(inMicLevelTmp - stt->minLevel));
   1112                     stt->micVol = (int32_t)WEBRTC_SPL_RSHIFT_U32(tmpU32, 14) + stt->minLevel;
   1113                     if (stt->micVol < lastMicVol + 2)
   1114                     {
   1115                         stt->micVol = lastMicVol + 2;
   1116                     }
   1117 
   1118                     inMicLevelTmp = stt->micVol;
   1119 
   1120 #ifdef MIC_LEVEL_FEEDBACK
   1121                     /* Count ms in level saturation */
   1122                     //if (stt->micVol > stt->maxAnalog) {
   1123                     if (stt->micVol > 150)
   1124                     {
   1125                         /* mic level is saturated */
   1126                         stt->numBlocksMicLvlSat++;
   1127                         fprintf(stderr, "Sat mic Level: %d\n", stt->numBlocksMicLvlSat);
   1128                     }
   1129 #endif
   1130 #ifdef WEBRTC_AGC_DEBUG_DUMP
   1131                     fprintf(stt->fpt,
   1132                             "\tAGC->ProcessAnalog, frame %d: measure <"
   1133                             " 2ndLowerLim, micVol = %d\n",
   1134                             stt->fcount,
   1135                             stt->micVol);
   1136 #endif
   1137                 }
   1138             } else if (stt->Rxx160_LPw32 < stt->lowerLimit)
   1139             {
   1140                 stt->msTooHigh = 0;
   1141                 stt->changeToSlowMode = 0;
   1142                 stt->msTooLow += 2;
   1143 
   1144                 if (stt->msTooLow > stt->msecSpeechInnerChange)
   1145                 {
   1146                     /* Raise the recording level */
   1147                     int16_t index, weightFIX;
   1148                     int16_t volNormFIX = 16384; // =1 in Q14.
   1149 
   1150                     stt->msTooLow = 0;
   1151 
   1152                     /* Normalize the volume level */
   1153                     tmp32 = WEBRTC_SPL_LSHIFT_W32(inMicLevelTmp - stt->minLevel, 14);
   1154                     if (stt->maxInit != stt->minLevel)
   1155                     {
   1156                         volNormFIX = tmp32 / (stt->maxInit - stt->minLevel);
   1157                     }
   1158 
   1159                     /* Find correct curve */
   1160                     WebRtcAgc_ExpCurve(volNormFIX, &index);
   1161 
   1162                     /* Compute weighting factor for the volume increase, (3.^(-2.*X))/8+1 */
   1163                     weightFIX = kOffset2[index]
   1164                               - (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(kSlope2[index],
   1165                                                                          volNormFIX, 13);
   1166 
   1167                     /* stt->Rxx160_LPw32 *= 1.047 [~0.2 dB]; */
   1168                     tmp32 = WEBRTC_SPL_RSHIFT_W32(stt->Rxx160_LPw32, 6);
   1169                     stt->Rxx160_LPw32 = WEBRTC_SPL_MUL(tmp32, 67);
   1170 
   1171                     tmp32 = inMicLevelTmp - stt->minLevel;
   1172                     tmpU32 = ((uint32_t)weightFIX * (uint32_t)(inMicLevelTmp - stt->minLevel));
   1173                     stt->micVol = (int32_t)WEBRTC_SPL_RSHIFT_U32(tmpU32, 14) + stt->minLevel;
   1174                     if (stt->micVol < lastMicVol + 1)
   1175                     {
   1176                         stt->micVol = lastMicVol + 1;
   1177                     }
   1178 
   1179                     inMicLevelTmp = stt->micVol;
   1180 
   1181 #ifdef MIC_LEVEL_FEEDBACK
   1182                     /* Count ms in level saturation */
   1183                     //if (stt->micVol > stt->maxAnalog) {
   1184                     if (stt->micVol > 150)
   1185                     {
   1186                         /* mic level is saturated */
   1187                         stt->numBlocksMicLvlSat++;
   1188                         fprintf(stderr, "Sat mic Level: %d\n", stt->numBlocksMicLvlSat);
   1189                     }
   1190 #endif
   1191 #ifdef WEBRTC_AGC_DEBUG_DUMP
   1192                     fprintf(stt->fpt,
   1193                             "\tAGC->ProcessAnalog, frame %d: measure < LowerLim, micVol = %d\n",
   1194                             stt->fcount,
   1195                             stt->micVol);
   1196 #endif
   1197 
   1198                 }
   1199             } else
   1200             {
   1201                 /* The signal is inside the desired range which is:
   1202                  * lowerLimit < Rxx160_LP/640 < upperLimit
   1203                  */
   1204                 if (stt->changeToSlowMode > 4000)
   1205                 {
   1206                     stt->msecSpeechInnerChange = 1000;
   1207                     stt->msecSpeechOuterChange = 500;
   1208                     stt->upperLimit = stt->upperPrimaryLimit;
   1209                     stt->lowerLimit = stt->lowerPrimaryLimit;
   1210                 } else
   1211                 {
   1212                     stt->changeToSlowMode += 2; // in milliseconds
   1213                 }
   1214                 stt->msTooLow = 0;
   1215                 stt->msTooHigh = 0;
   1216 
   1217                 stt->micVol = inMicLevelTmp;
   1218 
   1219             }
   1220 #ifdef MIC_LEVEL_FEEDBACK
   1221             if (stt->numBlocksMicLvlSat > NUM_BLOCKS_IN_SAT_BEFORE_CHANGE_TARGET)
   1222             {
   1223                 stt->micLvlSat = 1;
   1224                 fprintf(stderr, "target before = %d (%d)\n", stt->analogTargetLevel, stt->targetIdx);
   1225                 WebRtcAgc_UpdateAgcThresholds(stt);
   1226                 WebRtcAgc_CalculateGainTable(&(stt->digitalAgc.gainTable[0]),
   1227                         stt->compressionGaindB, stt->targetLevelDbfs, stt->limiterEnable,
   1228                         stt->analogTarget);
   1229                 stt->numBlocksMicLvlSat = 0;
   1230                 stt->micLvlSat = 0;
   1231                 fprintf(stderr, "target offset = %d\n", stt->targetIdxOffset);
   1232                 fprintf(stderr, "target after  = %d (%d)\n", stt->analogTargetLevel, stt->targetIdx);
   1233             }
   1234 #endif
   1235         }
   1236     }
   1237 
   1238     /* Ensure gain is not increased in presence of echo or after a mute event
   1239      * (but allow the zeroCtrl() increase on the frame of a mute detection).
   1240      */
   1241     if (echo == 1 || (stt->muteGuardMs > 0 && stt->muteGuardMs < kMuteGuardTimeMs))
   1242     {
   1243         if (stt->micVol > lastMicVol)
   1244         {
   1245             stt->micVol = lastMicVol;
   1246         }
   1247     }
   1248 
   1249     /* limit the gain */
   1250     if (stt->micVol > stt->maxLevel)
   1251     {
   1252         stt->micVol = stt->maxLevel;
   1253     } else if (stt->micVol < stt->minOutput)
   1254     {
   1255         stt->micVol = stt->minOutput;
   1256     }
   1257 
   1258     *outMicLevel = WEBRTC_SPL_RSHIFT_W32(stt->micVol, stt->scale);
   1259     if (*outMicLevel > WEBRTC_SPL_RSHIFT_W32(stt->maxAnalog, stt->scale))
   1260     {
   1261         *outMicLevel = WEBRTC_SPL_RSHIFT_W32(stt->maxAnalog, stt->scale);
   1262     }
   1263 
   1264     return 0;
   1265 }
   1266 
   1267 int WebRtcAgc_Process(void *agcInst, const int16_t *in_near,
   1268                       const int16_t *in_near_H, int16_t samples,
   1269                       int16_t *out, int16_t *out_H, int32_t inMicLevel,
   1270                       int32_t *outMicLevel, int16_t echo,
   1271                       uint8_t *saturationWarning)
   1272 {
   1273     Agc_t *stt;
   1274     int32_t inMicLevelTmp;
   1275     int16_t subFrames, i;
   1276     uint8_t satWarningTmp = 0;
   1277 
   1278     stt = (Agc_t *)agcInst;
   1279 
   1280     //
   1281     if (stt == NULL)
   1282     {
   1283         return -1;
   1284     }
   1285     //
   1286 
   1287 
   1288     if (stt->fs == 8000)
   1289     {
   1290         if ((samples != 80) && (samples != 160))
   1291         {
   1292 #ifdef WEBRTC_AGC_DEBUG_DUMP
   1293             fprintf(stt->fpt,
   1294                     "AGC->Process, frame %d: Invalid number of samples\n\n",
   1295                     stt->fcount);
   1296 #endif
   1297             return -1;
   1298         }
   1299         subFrames = 80;
   1300     } else if (stt->fs == 16000)
   1301     {
   1302         if ((samples != 160) && (samples != 320))
   1303         {
   1304 #ifdef WEBRTC_AGC_DEBUG_DUMP
   1305             fprintf(stt->fpt,
   1306                     "AGC->Process, frame %d: Invalid number of samples\n\n",
   1307                     stt->fcount);
   1308 #endif
   1309             return -1;
   1310         }
   1311         subFrames = 160;
   1312     } else if (stt->fs == 32000)
   1313     {
   1314         if ((samples != 160) && (samples != 320))
   1315         {
   1316 #ifdef WEBRTC_AGC_DEBUG_DUMP
   1317             fprintf(stt->fpt,
   1318                     "AGC->Process, frame %d: Invalid number of samples\n\n",
   1319                     stt->fcount);
   1320 #endif
   1321             return -1;
   1322         }
   1323         subFrames = 160;
   1324     } else
   1325     {
   1326 #ifdef WEBRTC_AGC_DEBUG_DUMP
   1327         fprintf(stt->fpt,
   1328                 "AGC->Process, frame %d: Invalid sample rate\n\n",
   1329                 stt->fcount);
   1330 #endif
   1331         return -1;
   1332     }
   1333 
   1334     /* Check for valid pointers based on sampling rate */
   1335     if (stt->fs == 32000 && in_near_H == NULL)
   1336     {
   1337         return -1;
   1338     }
   1339     /* Check for valid pointers for low band */
   1340     if (in_near == NULL)
   1341     {
   1342         return -1;
   1343     }
   1344 
   1345     *saturationWarning = 0;
   1346     //TODO: PUT IN RANGE CHECKING FOR INPUT LEVELS
   1347     *outMicLevel = inMicLevel;
   1348     inMicLevelTmp = inMicLevel;
   1349 
   1350     // TODO(andrew): clearly we don't need input and output pointers...
   1351     //   Change the interface to take a shared input/output.
   1352     if (in_near != out)
   1353     {
   1354         // Only needed if they don't already point to the same place.
   1355         memcpy(out, in_near, samples * sizeof(int16_t));
   1356     }
   1357     if (stt->fs == 32000)
   1358     {
   1359         if (in_near_H != out_H)
   1360         {
   1361             memcpy(out_H, in_near_H, samples * sizeof(int16_t));
   1362         }
   1363     }
   1364 
   1365 #ifdef WEBRTC_AGC_DEBUG_DUMP
   1366     stt->fcount++;
   1367 #endif
   1368 
   1369     for (i = 0; i < samples; i += subFrames)
   1370     {
   1371         if (WebRtcAgc_ProcessDigital(&stt->digitalAgc, &in_near[i], &in_near_H[i], &out[i], &out_H[i],
   1372                            stt->fs, stt->lowLevelSignal) == -1)
   1373         {
   1374 #ifdef WEBRTC_AGC_DEBUG_DUMP
   1375             fprintf(stt->fpt,
   1376                     "AGC->Process, frame %d: Error from DigAGC\n\n",
   1377                     stt->fcount);
   1378 #endif
   1379             return -1;
   1380         }
   1381         if ((stt->agcMode < kAgcModeFixedDigital) && ((stt->lowLevelSignal == 0)
   1382                 || (stt->agcMode != kAgcModeAdaptiveDigital)))
   1383         {
   1384             if (WebRtcAgc_ProcessAnalog(agcInst, inMicLevelTmp, outMicLevel,
   1385                                           stt->vadMic.logRatio, echo, saturationWarning) == -1)
   1386             {
   1387                 return -1;
   1388             }
   1389         }
   1390 #ifdef WEBRTC_AGC_DEBUG_DUMP
   1391         fprintf(stt->agcLog,
   1392                 "%5d\t%d\t%d\t%d\t%d\n",
   1393                 stt->fcount,
   1394                 inMicLevelTmp,
   1395                 *outMicLevel,
   1396                 stt->maxLevel,
   1397                 stt->micVol);
   1398 #endif
   1399 
   1400         /* update queue */
   1401         if (stt->inQueue > 1)
   1402         {
   1403             memcpy(stt->env[0], stt->env[1], 10 * sizeof(int32_t));
   1404             memcpy(stt->Rxx16w32_array[0], stt->Rxx16w32_array[1], 5 * sizeof(int32_t));
   1405         }
   1406 
   1407         if (stt->inQueue > 0)
   1408         {
   1409             stt->inQueue--;
   1410         }
   1411 
   1412         /* If 20ms frames are used the input mic level must be updated so that
   1413          * the analog AGC does not think that there has been a manual volume
   1414          * change. */
   1415         inMicLevelTmp = *outMicLevel;
   1416 
   1417         /* Store a positive saturation warning. */
   1418         if (*saturationWarning == 1)
   1419         {
   1420             satWarningTmp = 1;
   1421         }
   1422     }
   1423 
   1424     /* Trigger the saturation warning if displayed by any of the frames. */
   1425     *saturationWarning = satWarningTmp;
   1426 
   1427     return 0;
   1428 }
   1429 
   1430 int WebRtcAgc_set_config(void *agcInst, WebRtcAgc_config_t agcConfig)
   1431 {
   1432     Agc_t *stt;
   1433     stt = (Agc_t *)agcInst;
   1434 
   1435     if (stt == NULL)
   1436     {
   1437         return -1;
   1438     }
   1439 
   1440     if (stt->initFlag != kInitCheck)
   1441     {
   1442         stt->lastError = AGC_UNINITIALIZED_ERROR;
   1443         return -1;
   1444     }
   1445 
   1446     if (agcConfig.limiterEnable != kAgcFalse && agcConfig.limiterEnable != kAgcTrue)
   1447     {
   1448         stt->lastError = AGC_BAD_PARAMETER_ERROR;
   1449         return -1;
   1450     }
   1451     stt->limiterEnable = agcConfig.limiterEnable;
   1452     stt->compressionGaindB = agcConfig.compressionGaindB;
   1453     if ((agcConfig.targetLevelDbfs < 0) || (agcConfig.targetLevelDbfs > 31))
   1454     {
   1455         stt->lastError = AGC_BAD_PARAMETER_ERROR;
   1456         return -1;
   1457     }
   1458     stt->targetLevelDbfs = agcConfig.targetLevelDbfs;
   1459 
   1460     if (stt->agcMode == kAgcModeFixedDigital)
   1461     {
   1462         /* Adjust for different parameter interpretation in FixedDigital mode */
   1463         stt->compressionGaindB += agcConfig.targetLevelDbfs;
   1464     }
   1465 
   1466     /* Update threshold levels for analog adaptation */
   1467     WebRtcAgc_UpdateAgcThresholds(stt);
   1468 
   1469     /* Recalculate gain table */
   1470     if (WebRtcAgc_CalculateGainTable(&(stt->digitalAgc.gainTable[0]), stt->compressionGaindB,
   1471                            stt->targetLevelDbfs, stt->limiterEnable, stt->analogTarget) == -1)
   1472     {
   1473 #ifdef WEBRTC_AGC_DEBUG_DUMP
   1474         fprintf(stt->fpt,
   1475                 "AGC->set_config, frame %d: Error from calcGainTable\n\n",
   1476                 stt->fcount);
   1477 #endif
   1478         return -1;
   1479     }
   1480     /* Store the config in a WebRtcAgc_config_t */
   1481     stt->usedConfig.compressionGaindB = agcConfig.compressionGaindB;
   1482     stt->usedConfig.limiterEnable = agcConfig.limiterEnable;
   1483     stt->usedConfig.targetLevelDbfs = agcConfig.targetLevelDbfs;
   1484 
   1485     return 0;
   1486 }
   1487 
   1488 int WebRtcAgc_get_config(void *agcInst, WebRtcAgc_config_t *config)
   1489 {
   1490     Agc_t *stt;
   1491     stt = (Agc_t *)agcInst;
   1492 
   1493     if (stt == NULL)
   1494     {
   1495         return -1;
   1496     }
   1497 
   1498     if (config == NULL)
   1499     {
   1500         stt->lastError = AGC_NULL_POINTER_ERROR;
   1501         return -1;
   1502     }
   1503 
   1504     if (stt->initFlag != kInitCheck)
   1505     {
   1506         stt->lastError = AGC_UNINITIALIZED_ERROR;
   1507         return -1;
   1508     }
   1509 
   1510     config->limiterEnable = stt->usedConfig.limiterEnable;
   1511     config->targetLevelDbfs = stt->usedConfig.targetLevelDbfs;
   1512     config->compressionGaindB = stt->usedConfig.compressionGaindB;
   1513 
   1514     return 0;
   1515 }
   1516 
   1517 int WebRtcAgc_Create(void **agcInst)
   1518 {
   1519     Agc_t *stt;
   1520     if (agcInst == NULL)
   1521     {
   1522         return -1;
   1523     }
   1524     stt = (Agc_t *)malloc(sizeof(Agc_t));
   1525 
   1526     *agcInst = stt;
   1527     if (stt == NULL)
   1528     {
   1529         return -1;
   1530     }
   1531 
   1532 #ifdef WEBRTC_AGC_DEBUG_DUMP
   1533     stt->fpt = fopen("./agc_test_log.txt", "wt");
   1534     stt->agcLog = fopen("./agc_debug_log.txt", "wt");
   1535     stt->digitalAgc.logFile = fopen("./agc_log.txt", "wt");
   1536 #endif
   1537 
   1538     stt->initFlag = 0;
   1539     stt->lastError = 0;
   1540 
   1541     return 0;
   1542 }
   1543 
   1544 int WebRtcAgc_Free(void *state)
   1545 {
   1546     Agc_t *stt;
   1547 
   1548     stt = (Agc_t *)state;
   1549 #ifdef WEBRTC_AGC_DEBUG_DUMP
   1550     fclose(stt->fpt);
   1551     fclose(stt->agcLog);
   1552     fclose(stt->digitalAgc.logFile);
   1553 #endif
   1554     free(stt);
   1555 
   1556     return 0;
   1557 }
   1558 
   1559 /* minLevel     - Minimum volume level
   1560  * maxLevel     - Maximum volume level
   1561  */
   1562 int WebRtcAgc_Init(void *agcInst, int32_t minLevel, int32_t maxLevel,
   1563                    int16_t agcMode, uint32_t fs)
   1564 {
   1565     int32_t max_add, tmp32;
   1566     int16_t i;
   1567     int tmpNorm;
   1568     Agc_t *stt;
   1569 
   1570     /* typecast state pointer */
   1571     stt = (Agc_t *)agcInst;
   1572 
   1573     if (WebRtcAgc_InitDigital(&stt->digitalAgc, agcMode) != 0)
   1574     {
   1575         stt->lastError = AGC_UNINITIALIZED_ERROR;
   1576         return -1;
   1577     }
   1578 
   1579     /* Analog AGC variables */
   1580     stt->envSum = 0;
   1581 
   1582     /* mode     = 0 - Only saturation protection
   1583      *            1 - Analog Automatic Gain Control [-targetLevelDbfs (default -3 dBOv)]
   1584      *            2 - Digital Automatic Gain Control [-targetLevelDbfs (default -3 dBOv)]
   1585      *            3 - Fixed Digital Gain [compressionGaindB (default 8 dB)]
   1586      */
   1587 #ifdef WEBRTC_AGC_DEBUG_DUMP
   1588     stt->fcount = 0;
   1589     fprintf(stt->fpt, "AGC->Init\n");
   1590 #endif
   1591     if (agcMode < kAgcModeUnchanged || agcMode > kAgcModeFixedDigital)
   1592     {
   1593 #ifdef WEBRTC_AGC_DEBUG_DUMP
   1594         fprintf(stt->fpt, "AGC->Init: error, incorrect mode\n\n");
   1595 #endif
   1596         return -1;
   1597     }
   1598     stt->agcMode = agcMode;
   1599     stt->fs = fs;
   1600 
   1601     /* initialize input VAD */
   1602     WebRtcAgc_InitVad(&stt->vadMic);
   1603 
   1604     /* If the volume range is smaller than 0-256 then
   1605      * the levels are shifted up to Q8-domain */
   1606     tmpNorm = WebRtcSpl_NormU32((uint32_t)maxLevel);
   1607     stt->scale = tmpNorm - 23;
   1608     if (stt->scale < 0)
   1609     {
   1610         stt->scale = 0;
   1611     }
   1612     // TODO(bjornv): Investigate if we really need to scale up a small range now when we have
   1613     // a guard against zero-increments. For now, we do not support scale up (scale = 0).
   1614     stt->scale = 0;
   1615     maxLevel = WEBRTC_SPL_LSHIFT_W32(maxLevel, stt->scale);
   1616     minLevel = WEBRTC_SPL_LSHIFT_W32(minLevel, stt->scale);
   1617 
   1618     /* Make minLevel and maxLevel static in AdaptiveDigital */
   1619     if (stt->agcMode == kAgcModeAdaptiveDigital)
   1620     {
   1621         minLevel = 0;
   1622         maxLevel = 255;
   1623         stt->scale = 0;
   1624     }
   1625     /* The maximum supplemental volume range is based on a vague idea
   1626      * of how much lower the gain will be than the real analog gain. */
   1627     max_add = WEBRTC_SPL_RSHIFT_W32(maxLevel - minLevel, 2);
   1628 
   1629     /* Minimum/maximum volume level that can be set */
   1630     stt->minLevel = minLevel;
   1631     stt->maxAnalog = maxLevel;
   1632     stt->maxLevel = maxLevel + max_add;
   1633     stt->maxInit = stt->maxLevel;
   1634 
   1635     stt->zeroCtrlMax = stt->maxAnalog;
   1636     stt->lastInMicLevel = 0;
   1637 
   1638     /* Initialize micVol parameter */
   1639     stt->micVol = stt->maxAnalog;
   1640     if (stt->agcMode == kAgcModeAdaptiveDigital)
   1641     {
   1642         stt->micVol = 127; /* Mid-point of mic level */
   1643     }
   1644     stt->micRef = stt->micVol;
   1645     stt->micGainIdx = 127;
   1646 #ifdef MIC_LEVEL_FEEDBACK
   1647     stt->numBlocksMicLvlSat = 0;
   1648     stt->micLvlSat = 0;
   1649 #endif
   1650 #ifdef WEBRTC_AGC_DEBUG_DUMP
   1651     fprintf(stt->fpt,
   1652             "AGC->Init: minLevel = %d, maxAnalog = %d, maxLevel = %d\n",
   1653             stt->minLevel,
   1654             stt->maxAnalog,
   1655             stt->maxLevel);
   1656 #endif
   1657 
   1658     /* Minimum output volume is 4% higher than the available lowest volume level */
   1659     tmp32 = WEBRTC_SPL_RSHIFT_W32((stt->maxLevel - stt->minLevel) * (int32_t)10, 8);
   1660     stt->minOutput = (stt->minLevel + tmp32);
   1661 
   1662     stt->msTooLow = 0;
   1663     stt->msTooHigh = 0;
   1664     stt->changeToSlowMode = 0;
   1665     stt->firstCall = 0;
   1666     stt->msZero = 0;
   1667     stt->muteGuardMs = 0;
   1668     stt->gainTableIdx = 0;
   1669 
   1670     stt->msecSpeechInnerChange = kMsecSpeechInner;
   1671     stt->msecSpeechOuterChange = kMsecSpeechOuter;
   1672 
   1673     stt->activeSpeech = 0;
   1674     stt->Rxx16_LPw32Max = 0;
   1675 
   1676     stt->vadThreshold = kNormalVadThreshold;
   1677     stt->inActive = 0;
   1678 
   1679     for (i = 0; i < RXX_BUFFER_LEN; i++)
   1680     {
   1681         stt->Rxx16_vectorw32[i] = (int32_t)1000; /* -54dBm0 */
   1682     }
   1683     stt->Rxx160w32 = 125 * RXX_BUFFER_LEN; /* (stt->Rxx16_vectorw32[0]>>3) = 125 */
   1684 
   1685     stt->Rxx16pos = 0;
   1686     stt->Rxx16_LPw32 = (int32_t)16284; /* Q(-4) */
   1687 
   1688     for (i = 0; i < 5; i++)
   1689     {
   1690         stt->Rxx16w32_array[0][i] = 0;
   1691     }
   1692     for (i = 0; i < 10; i++)
   1693     {
   1694         stt->env[0][i] = 0;
   1695         stt->env[1][i] = 0;
   1696     }
   1697     stt->inQueue = 0;
   1698 
   1699 #ifdef MIC_LEVEL_FEEDBACK
   1700     stt->targetIdxOffset = 0;
   1701 #endif
   1702 
   1703     WebRtcSpl_MemSetW32(stt->filterState, 0, 8);
   1704 
   1705     stt->initFlag = kInitCheck;
   1706     // Default config settings.
   1707     stt->defaultConfig.limiterEnable = kAgcTrue;
   1708     stt->defaultConfig.targetLevelDbfs = AGC_DEFAULT_TARGET_LEVEL;
   1709     stt->defaultConfig.compressionGaindB = AGC_DEFAULT_COMP_GAIN;
   1710 
   1711     if (WebRtcAgc_set_config(stt, stt->defaultConfig) == -1)
   1712     {
   1713         stt->lastError = AGC_UNSPECIFIED_ERROR;
   1714         return -1;
   1715     }
   1716     stt->Rxx160_LPw32 = stt->analogTargetLevel; // Initialize rms value
   1717 
   1718     stt->lowLevelSignal = 0;
   1719 
   1720     /* Only positive values are allowed that are not too large */
   1721     if ((minLevel >= maxLevel) || (maxLevel & 0xFC000000))
   1722     {
   1723 #ifdef WEBRTC_AGC_DEBUG_DUMP
   1724         fprintf(stt->fpt, "minLevel, maxLevel value(s) are invalid\n\n");
   1725 #endif
   1726         return -1;
   1727     } else
   1728     {
   1729 #ifdef WEBRTC_AGC_DEBUG_DUMP
   1730         fprintf(stt->fpt, "\n");
   1731 #endif
   1732         return 0;
   1733     }
   1734 }
   1735