Note: We no longer publish the latest version of our code here. We primarily use a kumc-bmi github organization. The heron ETL repository, in particular, is not public. Peers in the informatics community should see MultiSiteDev for details on requesting access.
source:
webrtc/webrtc/modules/audio_coding/codecs/isac/fix/source/filterbanks.c
@
0:4bda6873e34c
Last change on this file since 0:4bda6873e34c was 0:4bda6873e34c, checked in by , 6 years ago | |
---|---|
File size: 16.1 KB |
Line | |
---|---|
1 | /* |
2 | * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
3 | * |
4 | * Use of this source code is governed by a BSD-style license |
5 | * that can be found in the LICENSE file in the root of the source |
6 | * tree. An additional intellectual property rights grant can be found |
7 | * in the file PATENTS. All contributing project authors may |
8 | * be found in the AUTHORS file in the root of the source tree. |
9 | */ |
10 | |
11 | /* |
12 | * filterbanks.c |
13 | * |
14 | * This file contains function |
15 | * WebRtcIsacfix_SplitAndFilter, and WebRtcIsacfix_FilterAndCombine |
16 | * which implement filterbanks that produce decimated lowpass and |
17 | * highpass versions of a signal, and performs reconstruction. |
18 | * |
19 | */ |
20 | |
21 | #include "filterbank_internal.h" |
22 | |
23 | #include <assert.h> |
24 | |
25 | #include "codec.h" |
26 | #include "filterbank_tables.h" |
27 | #include "settings.h" |
28 | |
29 | // Declare a function pointer. |
30 | AllpassFilter2FixDec16 WebRtcIsacfix_AllpassFilter2FixDec16; |
31 | |
32 | void WebRtcIsacfix_AllpassFilter2FixDec16C( |
33 | int16_t *data_ch1, // Input and output in channel 1, in Q0 |
34 | int16_t *data_ch2, // Input and output in channel 2, in Q0 |
35 | const int16_t *factor_ch1, // Scaling factor for channel 1, in Q15 |
36 | const int16_t *factor_ch2, // Scaling factor for channel 2, in Q15 |
37 | const int length, // Length of the data buffers |
38 | int32_t *filter_state_ch1, // Filter state for channel 1, in Q16 |
39 | int32_t *filter_state_ch2) { // Filter state for channel 2, in Q16 |
40 | int n = 0; |
41 | int32_t state0_ch1 = filter_state_ch1[0], state1_ch1 = filter_state_ch1[1]; |
42 | int32_t state0_ch2 = filter_state_ch2[0], state1_ch2 = filter_state_ch2[1]; |
43 | int16_t in_out = 0; |
44 | int32_t a = 0, b = 0; |
45 | |
46 | // Assembly file assumption. |
47 | assert(length % 2 == 0); |
48 | |
49 | for (n = 0; n < length; n++) { |
50 | // Process channel 1: |
51 | in_out = data_ch1[n]; |
52 | a = WEBRTC_SPL_MUL_16_16(factor_ch1[0], in_out); // Q15 * Q0 = Q15 |
53 | a <<= 1; // Q15 -> Q16 |
54 | b = WEBRTC_SPL_ADD_SAT_W32(a, state0_ch1); |
55 | a = WEBRTC_SPL_MUL_16_16(-factor_ch1[0], (int16_t) (b >> 16)); // Q15 |
56 | state0_ch1 = WEBRTC_SPL_ADD_SAT_W32(a << 1, (uint32_t)in_out << 16); // Q16 |
57 | in_out = (int16_t) (b >> 16); // Save as Q0 |
58 | |
59 | a = WEBRTC_SPL_MUL_16_16(factor_ch1[1], in_out); // Q15 * Q0 = Q15 |
60 | a <<= 1; // Q15 -> Q16 |
61 | b = WEBRTC_SPL_ADD_SAT_W32(a, state1_ch1); // Q16 |
62 | a = WEBRTC_SPL_MUL_16_16(-factor_ch1[1], (int16_t) (b >> 16)); // Q15 |
63 | state1_ch1 = WEBRTC_SPL_ADD_SAT_W32(a << 1, (uint32_t)in_out << 16); // Q16 |
64 | data_ch1[n] = (int16_t) (b >> 16); // Save as Q0 |
65 | |
66 | // Process channel 2: |
67 | in_out = data_ch2[n]; |
68 | a = WEBRTC_SPL_MUL_16_16(factor_ch2[0], in_out); // Q15 * Q0 = Q15 |
69 | a <<= 1; // Q15 -> Q16 |
70 | b = WEBRTC_SPL_ADD_SAT_W32(a, state0_ch2); // Q16 |
71 | a = WEBRTC_SPL_MUL_16_16(-factor_ch2[0], (int16_t) (b >> 16)); // Q15 |
72 | state0_ch2 = WEBRTC_SPL_ADD_SAT_W32(a << 1, (uint32_t)in_out << 16); // Q16 |
73 | in_out = (int16_t) (b >> 16); // Save as Q0 |
74 | |
75 | a = WEBRTC_SPL_MUL_16_16(factor_ch2[1], in_out); // Q15 * Q0 = Q15 |
76 | a <<= 1; // Q15 -> Q16 |
77 | b = WEBRTC_SPL_ADD_SAT_W32(a, state1_ch2); // Q16 |
78 | a = WEBRTC_SPL_MUL_16_16(-factor_ch2[1], (int16_t) (b >> 16)); // Q15 |
79 | state1_ch2 = WEBRTC_SPL_ADD_SAT_W32(a << 1, (uint32_t)in_out << 16); // Q16 |
80 | data_ch2[n] = (int16_t) (b >> 16); // Save as Q0 |
81 | } |
82 | |
83 | filter_state_ch1[0] = state0_ch1; |
84 | filter_state_ch1[1] = state1_ch1; |
85 | filter_state_ch2[0] = state0_ch2; |
86 | filter_state_ch2[1] = state1_ch2; |
87 | } |
88 | |
89 | void WebRtcIsacfix_HighpassFilterFixDec32(int16_t *io, |
90 | int16_t len, |
91 | const int16_t *coefficient, |
92 | int32_t *state) |
93 | { |
94 | int k; |
95 | int32_t a1 = 0, b1 = 0, c = 0, in = 0; |
96 | int32_t a2 = 0, b2 = 0; |
97 | int32_t state0 = state[0]; |
98 | int32_t state1 = state[1]; |
99 | |
100 | for (k=0; k<len; k++) { |
101 | in = (int32_t)io[k]; |
102 | |
103 | #ifdef WEBRTC_ARCH_ARM_V7 |
104 | { |
105 | int tmp_coeff0 = 0; |
106 | int tmp_coeff1 = 0; |
107 | __asm __volatile( |
108 | "ldr %[tmp_coeff0], [%[coeff]]\n\t" |
109 | "ldr %[tmp_coeff1], [%[coeff], #4]\n\t" |
110 | "smmulr %[a2], %[tmp_coeff0], %[state0]\n\t" |
111 | "smmulr %[b2], %[tmp_coeff1], %[state1]\n\t" |
112 | "ldr %[tmp_coeff0], [%[coeff], #8]\n\t" |
113 | "ldr %[tmp_coeff1], [%[coeff], #12]\n\t" |
114 | "smmulr %[a1], %[tmp_coeff0], %[state0]\n\t" |
115 | "smmulr %[b1], %[tmp_coeff1], %[state1]\n\t" |
116 | :[a2]"+r"(a2), |
117 | [b2]"+r"(b2), |
118 | [a1]"+r"(a1), |
119 | [b1]"+r"(b1), |
120 | [tmp_coeff0]"+r"(tmp_coeff0), |
121 | [tmp_coeff1]"+r"(tmp_coeff1) |
122 | :[coeff]"r"(coefficient), |
123 | [state0]"r"(state0), |
124 | [state1]"r"(state1) |
125 | ); |
126 | } |
127 | #else |
128 | /* Q35 * Q4 = Q39 ; shift 32 bit => Q7 */ |
129 | a1 = WEBRTC_SPL_MUL_32_32_RSFT32(coefficient[5], coefficient[4], state0); |
130 | b1 = WEBRTC_SPL_MUL_32_32_RSFT32(coefficient[7], coefficient[6], state1); |
131 | |
132 | /* Q30 * Q4 = Q34 ; shift 32 bit => Q2 */ |
133 | a2 = WEBRTC_SPL_MUL_32_32_RSFT32(coefficient[1], coefficient[0], state0); |
134 | b2 = WEBRTC_SPL_MUL_32_32_RSFT32(coefficient[3], coefficient[2], state1); |
135 | #endif |
136 | |
137 | c = ((int32_t)in) + WEBRTC_SPL_RSHIFT_W32(a1+b1, 7); // Q0 |
138 | io[k] = (int16_t)WebRtcSpl_SatW32ToW16(c); // Write output as Q0. |
139 | |
140 | c = WEBRTC_SPL_LSHIFT_W32((int32_t)in, 2) - a2 - b2; // In Q2. |
141 | c = (int32_t)WEBRTC_SPL_SAT(536870911, c, -536870912); |
142 | |
143 | state1 = state0; |
144 | state0 = WEBRTC_SPL_LSHIFT_W32(c, 2); // Write state as Q4 |
145 | } |
146 | state[0] = state0; |
147 | state[1] = state1; |
148 | } |
149 | |
150 | |
151 | void WebRtcIsacfix_SplitAndFilter1(int16_t *pin, |
152 | int16_t *LP16, |
153 | int16_t *HP16, |
154 | PreFiltBankstr *prefiltdata) |
155 | { |
156 | /* Function WebRtcIsacfix_SplitAndFilter */ |
157 | /* This function creates low-pass and high-pass decimated versions of part of |
158 | the input signal, and part of the signal in the input 'lookahead buffer'. */ |
159 | |
160 | int k; |
161 | |
162 | int16_t tempin_ch1[FRAMESAMPLES/2 + QLOOKAHEAD]; |
163 | int16_t tempin_ch2[FRAMESAMPLES/2 + QLOOKAHEAD]; |
164 | int32_t tmpState_ch1[2 * (QORDER-1)]; /* 4 */ |
165 | int32_t tmpState_ch2[2 * (QORDER-1)]; /* 4 */ |
166 | |
167 | /* High pass filter */ |
168 | WebRtcIsacfix_HighpassFilterFixDec32(pin, FRAMESAMPLES, WebRtcIsacfix_kHpStCoeffInQ30, prefiltdata->HPstates_fix); |
169 | |
170 | |
171 | /* First Channel */ |
172 | for (k=0;k<FRAMESAMPLES/2;k++) { |
173 | tempin_ch1[QLOOKAHEAD + k] = pin[1+WEBRTC_SPL_MUL_16_16(2, k)]; |
174 | } |
175 | for (k=0;k<QLOOKAHEAD;k++) { |
176 | tempin_ch1[k]=prefiltdata->INLABUF1_fix[k]; |
177 | prefiltdata->INLABUF1_fix[k]=pin[FRAMESAMPLES+1-WEBRTC_SPL_MUL_16_16(2, QLOOKAHEAD)+WEBRTC_SPL_MUL_16_16(2, k)]; |
178 | } |
179 | |
180 | /* Second Channel. This is exactly like the first channel, except that the |
181 | even samples are now filtered instead (lower channel). */ |
182 | for (k=0;k<FRAMESAMPLES/2;k++) { |
183 | tempin_ch2[QLOOKAHEAD+k] = pin[WEBRTC_SPL_MUL_16_16(2, k)]; |
184 | } |
185 | for (k=0;k<QLOOKAHEAD;k++) { |
186 | tempin_ch2[k]=prefiltdata->INLABUF2_fix[k]; |
187 | prefiltdata->INLABUF2_fix[k]=pin[FRAMESAMPLES-WEBRTC_SPL_MUL_16_16(2, QLOOKAHEAD)+WEBRTC_SPL_MUL_16_16(2, k)]; |
188 | } |
189 | |
190 | |
191 | /*obtain polyphase components by forward all-pass filtering through each channel */ |
192 | /* The all pass filtering automatically updates the filter states which are exported in the |
193 | prefiltdata structure */ |
194 | WebRtcIsacfix_AllpassFilter2FixDec16(tempin_ch1, |
195 | tempin_ch2, |
196 | WebRtcIsacfix_kUpperApFactorsQ15, |
197 | WebRtcIsacfix_kLowerApFactorsQ15, |
198 | FRAMESAMPLES/2, |
199 | prefiltdata->INSTAT1_fix, |
200 | prefiltdata->INSTAT2_fix); |
201 | |
202 | for (k=0;k<WEBRTC_SPL_MUL_16_16(2, (QORDER-1));k++) { |
203 | tmpState_ch1[k] = prefiltdata->INSTAT1_fix[k]; |
204 | tmpState_ch2[k] = prefiltdata->INSTAT2_fix[k]; |
205 | } |
206 | WebRtcIsacfix_AllpassFilter2FixDec16(tempin_ch1 + FRAMESAMPLES/2, |
207 | tempin_ch2 + FRAMESAMPLES/2, |
208 | WebRtcIsacfix_kUpperApFactorsQ15, |
209 | WebRtcIsacfix_kLowerApFactorsQ15, |
210 | QLOOKAHEAD, |
211 | tmpState_ch1, |
212 | tmpState_ch2); |
213 | |
214 | /* Now Construct low-pass and high-pass signals as combinations of polyphase components */ |
215 | for (k=0; k<FRAMESAMPLES/2 + QLOOKAHEAD; k++) { |
216 | int32_t tmp1, tmp2, tmp3; |
217 | tmp1 = (int32_t)tempin_ch1[k]; // Q0 -> Q0 |
218 | tmp2 = (int32_t)tempin_ch2[k]; // Q0 -> Q0 |
219 | tmp3 = (int32_t)WEBRTC_SPL_RSHIFT_W32((tmp1 + tmp2), 1);/* low pass signal*/ |
220 | LP16[k] = (int16_t)WebRtcSpl_SatW32ToW16(tmp3); /*low pass */ |
221 | tmp3 = (int32_t)WEBRTC_SPL_RSHIFT_W32((tmp1 - tmp2), 1);/* high pass signal*/ |
222 | HP16[k] = (int16_t)WebRtcSpl_SatW32ToW16(tmp3); /*high pass */ |
223 | } |
224 | |
225 | }/*end of WebRtcIsacfix_SplitAndFilter */ |
226 | |
227 | |
228 | #ifdef WEBRTC_ISAC_FIX_NB_CALLS_ENABLED |
229 | |
230 | /* Without lookahead */ |
231 | void WebRtcIsacfix_SplitAndFilter2(int16_t *pin, |
232 | int16_t *LP16, |
233 | int16_t *HP16, |
234 | PreFiltBankstr *prefiltdata) |
235 | { |
236 | /* Function WebRtcIsacfix_SplitAndFilter2 */ |
237 | /* This function creates low-pass and high-pass decimated versions of part of |
238 | the input signal. */ |
239 | |
240 | int k; |
241 | |
242 | int16_t tempin_ch1[FRAMESAMPLES/2]; |
243 | int16_t tempin_ch2[FRAMESAMPLES/2]; |
244 | |
245 | |
246 | /* High pass filter */ |
247 | WebRtcIsacfix_HighpassFilterFixDec32(pin, FRAMESAMPLES, WebRtcIsacfix_kHpStCoeffInQ30, prefiltdata->HPstates_fix); |
248 | |
249 | |
250 | /* First Channel */ |
251 | for (k=0;k<FRAMESAMPLES/2;k++) { |
252 | tempin_ch1[k] = pin[1+WEBRTC_SPL_MUL_16_16(2, k)]; |
253 | } |
254 | |
255 | /* Second Channel. This is exactly like the first channel, except that the |
256 | even samples are now filtered instead (lower channel). */ |
257 | for (k=0;k<FRAMESAMPLES/2;k++) { |
258 | tempin_ch2[k] = pin[WEBRTC_SPL_MUL_16_16(2, k)]; |
259 | } |
260 | |
261 | |
262 | /*obtain polyphase components by forward all-pass filtering through each channel */ |
263 | /* The all pass filtering automatically updates the filter states which are exported in the |
264 | prefiltdata structure */ |
265 | WebRtcIsacfix_AllpassFilter2FixDec16(tempin_ch1, |
266 | tempin_ch2, |
267 | WebRtcIsacfix_kUpperApFactorsQ15, |
268 | WebRtcIsacfix_kLowerApFactorsQ15, |
269 | FRAMESAMPLES/2, |
270 | prefiltdata->INSTAT1_fix, |
271 | prefiltdata->INSTAT2_fix); |
272 | |
273 | /* Now Construct low-pass and high-pass signals as combinations of polyphase components */ |
274 | for (k=0; k<FRAMESAMPLES/2; k++) { |
275 | int32_t tmp1, tmp2, tmp3; |
276 | tmp1 = (int32_t)tempin_ch1[k]; // Q0 -> Q0 |
277 | tmp2 = (int32_t)tempin_ch2[k]; // Q0 -> Q0 |
278 | tmp3 = (int32_t)WEBRTC_SPL_RSHIFT_W32((tmp1 + tmp2), 1);/* low pass signal*/ |
279 | LP16[k] = (int16_t)WebRtcSpl_SatW32ToW16(tmp3); /*low pass */ |
280 | tmp3 = (int32_t)WEBRTC_SPL_RSHIFT_W32((tmp1 - tmp2), 1);/* high pass signal*/ |
281 | HP16[k] = (int16_t)WebRtcSpl_SatW32ToW16(tmp3); /*high pass */ |
282 | } |
283 | |
284 | }/*end of WebRtcIsacfix_SplitAndFilter */ |
285 | |
286 | #endif |
287 | |
288 | |
289 | |
290 | ////////////////////////////////////////////////////////// |
291 | ////////// Combining |
292 | /* Function WebRtcIsacfix_FilterAndCombine */ |
293 | /* This is a decoder function that takes the decimated |
294 | length FRAMESAMPLES/2 input low-pass and |
295 | high-pass signals and creates a reconstructed fullband |
296 | output signal of length FRAMESAMPLES. WebRtcIsacfix_FilterAndCombine |
297 | is the sibling function of WebRtcIsacfix_SplitAndFilter */ |
298 | /* INPUTS: |
299 | inLP: a length FRAMESAMPLES/2 array of input low-pass |
300 | samples. |
301 | inHP: a length FRAMESAMPLES/2 array of input high-pass |
302 | samples. |
303 | postfiltdata: input data structure containing the filterbank |
304 | states from the previous decoding iteration. |
305 | OUTPUTS: |
306 | Out: a length FRAMESAMPLES array of output reconstructed |
307 | samples (fullband) based on the input low-pass and |
308 | high-pass signals. |
309 | postfiltdata: the input data structure containing the filterbank |
310 | states is updated for the next decoding iteration */ |
311 | void WebRtcIsacfix_FilterAndCombine1(int16_t *tempin_ch1, |
312 | int16_t *tempin_ch2, |
313 | int16_t *out16, |
314 | PostFiltBankstr *postfiltdata) |
315 | { |
316 | int k; |
317 | int16_t in[FRAMESAMPLES]; |
318 | |
319 | /* all-pass filter the new upper and lower channel signal. |
320 | For upper channel, use the all-pass filter factors that were used as a |
321 | lower channel at the encoding side. So at the decoder, the corresponding |
322 | all-pass filter factors for each channel are swapped. |
323 | For lower channel signal, since all-pass filter factors at the decoder are |
324 | swapped from the ones at the encoder, the 'upper' channel all-pass filter |
325 | factors (kUpperApFactors) are used to filter this new lower channel signal. |
326 | */ |
327 | WebRtcIsacfix_AllpassFilter2FixDec16(tempin_ch1, |
328 | tempin_ch2, |
329 | WebRtcIsacfix_kLowerApFactorsQ15, |
330 | WebRtcIsacfix_kUpperApFactorsQ15, |
331 | FRAMESAMPLES/2, |
332 | postfiltdata->STATE_0_UPPER_fix, |
333 | postfiltdata->STATE_0_LOWER_fix); |
334 | |
335 | /* Merge outputs to form the full length output signal.*/ |
336 | for (k=0;k<FRAMESAMPLES/2;k++) { |
337 | in[WEBRTC_SPL_MUL_16_16(2, k)]=tempin_ch2[k]; |
338 | in[WEBRTC_SPL_MUL_16_16(2, k)+1]=tempin_ch1[k]; |
339 | } |
340 | |
341 | /* High pass filter */ |
342 | WebRtcIsacfix_HighpassFilterFixDec32(in, FRAMESAMPLES, WebRtcIsacfix_kHPStCoeffOut1Q30, postfiltdata->HPstates1_fix); |
343 | WebRtcIsacfix_HighpassFilterFixDec32(in, FRAMESAMPLES, WebRtcIsacfix_kHPStCoeffOut2Q30, postfiltdata->HPstates2_fix); |
344 | |
345 | for (k=0;k<FRAMESAMPLES;k++) { |
346 | out16[k] = in[k]; |
347 | } |
348 | } |
349 | |
350 | |
351 | #ifdef WEBRTC_ISAC_FIX_NB_CALLS_ENABLED |
352 | /* Function WebRtcIsacfix_FilterAndCombine */ |
353 | /* This is a decoder function that takes the decimated |
354 | length len/2 input low-pass and |
355 | high-pass signals and creates a reconstructed fullband |
356 | output signal of length len. WebRtcIsacfix_FilterAndCombine |
357 | is the sibling function of WebRtcIsacfix_SplitAndFilter */ |
358 | /* INPUTS: |
359 | inLP: a length len/2 array of input low-pass |
360 | samples. |
361 | inHP: a length len/2 array of input high-pass |
362 | samples. |
363 | postfiltdata: input data structure containing the filterbank |
364 | states from the previous decoding iteration. |
365 | OUTPUTS: |
366 | Out: a length len array of output reconstructed |
367 | samples (fullband) based on the input low-pass and |
368 | high-pass signals. |
369 | postfiltdata: the input data structure containing the filterbank |
370 | states is updated for the next decoding iteration */ |
371 | void WebRtcIsacfix_FilterAndCombine2(int16_t *tempin_ch1, |
372 | int16_t *tempin_ch2, |
373 | int16_t *out16, |
374 | PostFiltBankstr *postfiltdata, |
375 | int16_t len) |
376 | { |
377 | int k; |
378 | int16_t in[FRAMESAMPLES]; |
379 | |
380 | /* all-pass filter the new upper and lower channel signal. |
381 | For upper channel, use the all-pass filter factors that were used as a |
382 | lower channel at the encoding side. So at the decoder, the corresponding |
383 | all-pass filter factors for each channel are swapped. |
384 | For lower channel signal, since all-pass filter factors at the decoder are |
385 | swapped from the ones at the encoder, the 'upper' channel all-pass filter |
386 | factors (kUpperApFactors) are used to filter this new lower channel signal. |
387 | */ |
388 | WebRtcIsacfix_AllpassFilter2FixDec16(tempin_ch1, |
389 | tempin_ch2, |
390 | WebRtcIsacfix_kLowerApFactorsQ15, |
391 | WebRtcIsacfix_kUpperApFactorsQ15, |
392 | len / 2, |
393 | postfiltdata->STATE_0_UPPER_fix, |
394 | postfiltdata->STATE_0_LOWER_fix); |
395 | |
396 | /* Merge outputs to form the full length output signal.*/ |
397 | for (k=0;k<len/2;k++) { |
398 | in[WEBRTC_SPL_MUL_16_16(2, k)]=tempin_ch2[k]; |
399 | in[WEBRTC_SPL_MUL_16_16(2, k)+1]=tempin_ch1[k]; |
400 | } |
401 | |
402 | /* High pass filter */ |
403 | WebRtcIsacfix_HighpassFilterFixDec32(in, len, WebRtcIsacfix_kHPStCoeffOut1Q30, postfiltdata->HPstates1_fix); |
404 | WebRtcIsacfix_HighpassFilterFixDec32(in, len, WebRtcIsacfix_kHPStCoeffOut2Q30, postfiltdata->HPstates2_fix); |
405 | |
406 | for (k=0;k<len;k++) { |
407 | out16[k] = in[k]; |
408 | } |
409 | } |
410 | |
411 | #endif |
Note: See TracBrowser
for help on using the repository browser.