OLD | NEW |
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 } |
OLD | NEW |