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