-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathWebRtcAgc_ProcessDigital.m
263 lines (242 loc) · 8.96 KB
/
WebRtcAgc_ProcessDigital.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
function [y, stt, out] = WebRtcAgc_ProcessDigital(stt, in_near, num_bands, FS, lowlevelSignal, param)
% array for gains (one value per ms, incl start & end)
% global ii
% global decay3_mb
gains = zeros(11,1);
env = zeros(10,1);
% // determine number of samples per ms
if (FS == 8000)
L = 8;
L2 = 3;
elseif (FS == 16000 || FS == 32000 || FS == 48000)
L = 16;
L2 = 4;
else
y = -1;
return;
end
out = NaN(num_bands,10*L);
for i = 0:num_bands - 1
% // Only needed if they don't already point to the same place.
out(i + 1,1:10*L) = in_near(i + 1, 1:10*L);%Ðè´¦Àí¶þ¼¶Ö¸Õë
end
% // VAD for near end
[logratio, stt.vadNearend] = WebRtcAgc_ProcessVad(stt.vadNearend, out, L * 10, param);
% // Account for far end VAD
if (stt.vadFarend.counter > 10)
tmp32 = 3 * logratio;
logratio = floor((tmp32 - stt.vadFarend.logRatio)/4);
end
% // Determine decay factor depending on VAD
% // upper_thr = 1.0f;
% // lower_thr = 0.25f;
upper_thr = int16(1024); % // Q10
lower_thr = int16(0); % // Q10
logratio = int16(logratio);
if (logratio > upper_thr)
% // decay = -2^17 / DecayTime; -> -65
decay = -65;
elseif (logratio < lower_thr)
decay = 0;
else
% // decay = (int16_t)(((lower_thr - logratio)
% // * (2^27/(DecayTime*(upper_thr-lower_thr)))) >> 10);
% // SUBSTITUTED: 2^27/(DecayTime*(upper_thr-lower_thr)) -> 65
tmp32 = int32((lower_thr - logratio) * 65);
decay = double(int16(tmp32/1024));
end
% ii = ii + 1;
% decay3_mb(ii) = decay;
% // adjust decay factor for long silence (detected as low standard deviation)
% // This is only done in the adaptive modes
% if (stt.agcMode ~= param.kAgcModeFixedDigital)
% if (stt.vadNearend.stdLongTerm < 4000)
% decay = 0;
% elseif (stt.vadNearend.stdLongTerm < 8096)
% % // decay = (int16_t)(((stt->vadNearend.stdLongTerm - 4000) * decay) >>
% % // 12);
% tmp32 = (stt.vadNearend.stdLongTerm - 4000) * decay;
% decay = floor(tmp32 / 4096);
% end
%
% if (lowlevelSignal ~= 0)
% decay = 0;
% end
% end
% #ifdef WEBRTC_AGC_DEBUG_DUMP
% stt->frameCounter++;
% fprintf(stt->logFile, "%5.2f\t%d\t%d\t%d\t", (float)(stt->frameCounter) / 100,
% logratio, decay, stt->vadNearend.stdLongTerm);
% #endif
% // Find max amplitude per sub frame
% // iterate over sub frames
for k = 0:1:9
% // iterate over samples
max_nrg = 0;
for n = 0:1:L-1
nrg = out(1, k * L + n + 1) * out(1, k * L + n + 1);
if (nrg > max_nrg)
max_nrg = nrg;
end
end
env(k + 1) = int32(max_nrg);
end
% // Calculate gain per sub frame
gains(1) = stt.gain;
for k = 0:1:9
% // Fast envelope follower
% // decay time = -131000 / -1000 = 131 (ms)
stt.capacitorFast =...
AGC_SCALEDIFF32(int32(-1000), stt.capacitorFast, stt.capacitorFast);
if (env(k + 1) > stt.capacitorFast)
stt.capacitorFast = env(k + 1);
end
% // Slow envelope follower
if (env(k + 1) > stt.capacitorSlow)
% // increase capacitorSlow
stt.capacitorSlow = AGC_SCALEDIFF32(int32(500), (env(k + 1) - stt.capacitorSlow),...
stt.capacitorSlow);
else
% // decrease capacitorSlow
stt.capacitorSlow =...
AGC_SCALEDIFF32(decay, stt.capacitorSlow, stt.capacitorSlow);
end
% // use maximum of both capacitors as current level
if (stt.capacitorFast > stt.capacitorSlow)
cur_level = stt.capacitorFast;
else
cur_level = stt.capacitorSlow;
end
% // Translate signal level into gain, using a piecewise linear approximation
% // find number of leading zeros
mzeros = NormU32(cur_level);
if (mzeros == 0)
mzeros = 31;
end
tmp32 = bitand(cur_level * 2^mzeros , hex2dec('7FFFFFFF'));
frac = floor(tmp32 / 524288); % // Q12.//notice
tmp32 = (stt.gainTable(mzeros) - stt.gainTable(mzeros + 1)) * frac;
gains(k + 2) = stt.gainTable(mzeros + 1) + floor(tmp32/2^12);
% #ifdef WEBRTC_AGC_DEBUG_DUMP
% if (k == 0) {
% fprintf(stt->logFile, "%d\t%d\t%d\t%d\t%d\n", env[0], cur_level,
% stt->capacitorFast, stt->capacitorSlow, zeros);
% }
% #endif
end
% // Gate processing (lower gain during absence of speech)
mzeros = mzeros*512 - floor(frac/8);
% % // find number of leading zeros
zeros_fast = NormU32(stt.capacitorFast);
if (stt.capacitorFast == 0)
zeros_fast = 31;
end
tmp32 = bitand(bitshift(stt.capacitorFast , zeros_fast) , hex2dec('7FFFFFFF'));
zeros_fast = zeros_fast*512;
zeros_fast = zeros_fast - floor(tmp32 / 4194304);
%
gate = 1000 + zeros_fast - mzeros - stt.vadNearend.stdShortTerm;
if (gate < 0)
stt.gatePrevious = 0;
else
tmp32 = stt.gatePrevious * 7;
gate = floor((gate + tmp32)/ 8);
stt.gatePrevious = gate;
end
% % % // gate < 0 -> no gate
% % % // gate > 2500 -> max gate
if (gate > 0)
if (gate < 2500)
gain_adj = floor((2500 - gate) / 2^6);
else
gain_adj = 0;
end
for k = 0:1:9
if ((gains(k + 2) - stt.gainTable(1)) > 8388608)
% % // To prevent wraparound
tmp32 = fix((gains(k + 2) - stt.gainTable(1)) / 256);
tmp32 = tmp32*(178 + gain_adj);
else
tmp32 = (gains(k + 2) - stt.gainTable(1)) * (178 + gain_adj);
tmp32 = fix(tmp32 / 256);
end
gains(k + 2) = stt.gainTable(1) + tmp32;
end
end
% %
% % % // Limit gain to avoid overload distortion
% for k = 0:1:9
% % % // To prevent wrap around
% mzeros = 10;
% if (gains(k + 2) > 47453132)
% mzeros = 16 - gains(k + 2);
% end
% gain32 = floor(gains(k + 2) / 2^mzeros) + 1;
% gain32 = gain32*gain32;
% % % // check for overflow
% while (AGC_MUL32(bitshift(round(env(k+1)) , -12) + 1, gain32) >...
% SHIFT_W32( 32767, 2 * (1 - mzeros + 10)))
% % % // multiply by 253/256 ==> -0.1 dB
% if (gains(k + 2) > 8388607)
% % % // Prevent wrap around
% gains(k + 2) = floor(gains(k + 2) / 256) * 253;
% gains(k + 2) = gains(k + 2);
% %
% else
% gains(k + 2) = floor((gains(k + 2) * 253) / 256);
% %
% end
% gain32 = floor(gains(k + 2) / 2^mzeros) + 1;
% gain32 = gain32*gain32;
% end
% end
% % % // gain reductions should be done 1 ms earlier than gain increases
for k = 1:1:9
if (gains(k + 1) > gains(k + 2))
gains(k + 1) = gains(k + 2);
end
end
% // save start gain for next frame
stt.gain = gains(11);
% // Apply gain
% // handle first sub frame separately
delta = (gains(2) - gains(1)) * bitshift(1 , (4 - L2));
gain32 = gains(1) * 16;
% // iterate over samples
for n = 0:1:L-1
for i = 0:num_bands-1
tmp32 = out(i + 1,n + 1) * floor((gain32 + 127)/128);
out_tmp = floor(tmp32 /2^16);
if (out_tmp > 4095)
out(i + 1,n + 1) = 32767;
elseif (out_tmp < -4096)
out(i + 1,n + 1) = -32768;
else
tmp32 = out(i + 1,n + 1) * floor(gain32/16);
out(i + 1,n + 1) = floor(tmp32 /65536);
end
end
gain32 = gain32 + delta;
end
% // iterate over subframes
for k = 1:1:9
delta = (gains(k + 2) - gains(k + 1)) * 2^(4 - L2);
gain32 = gains(k + 1) * 16;
% // iterate over samples
for n3 = 0:L - 1
for i3 = 0:num_bands - 1
tmp64 = out(i3 + 1,k * L + n3 + 1) * floor(gain32/16);
tmp64 = floor(tmp64/65536);
if (tmp64 > 32767)
out(i3 + 1,k * L + n3 + 1) = 32767;
elseif (tmp64 < -32768)
out(i3 + 1,k * L + n3 + 1) = -32768;
else
out(i3 + 1,k * L + n3 + 1) = tmp64;
end
end
gain32 = gain32 + delta;
end
end
y = 0;
end