Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(461)

Side by Side Diff: webrtc/modules/audio_processing/agc/legacy/analog_agc.c

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

Powered by Google App Engine
This is Rietveld 408576698