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