diff options
Diffstat (limited to 'apps/codecs/libfaad/filtbank.c')
-rw-r--r-- | apps/codecs/libfaad/filtbank.c | 404 |
1 files changed, 404 insertions, 0 deletions
diff --git a/apps/codecs/libfaad/filtbank.c b/apps/codecs/libfaad/filtbank.c new file mode 100644 index 0000000000..13cc265e21 --- /dev/null +++ b/apps/codecs/libfaad/filtbank.c | |||
@@ -0,0 +1,404 @@ | |||
1 | /* | ||
2 | ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding | ||
3 | ** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com | ||
4 | ** | ||
5 | ** This program is free software; you can redistribute it and/or modify | ||
6 | ** it under the terms of the GNU General Public License as published by | ||
7 | ** the Free Software Foundation; either version 2 of the License, or | ||
8 | ** (at your option) any later version. | ||
9 | ** | ||
10 | ** This program is distributed in the hope that it will be useful, | ||
11 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | ** GNU General Public License for more details. | ||
14 | ** | ||
15 | ** You should have received a copy of the GNU General Public License | ||
16 | ** along with this program; if not, write to the Free Software | ||
17 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
18 | ** | ||
19 | ** Any non-GPL usage of this software or parts of this software is strictly | ||
20 | ** forbidden. | ||
21 | ** | ||
22 | ** Commercial non-GPL licensing of this software is possible. | ||
23 | ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. | ||
24 | ** | ||
25 | ** $Id$ | ||
26 | **/ | ||
27 | |||
28 | #include "common.h" | ||
29 | #include "structs.h" | ||
30 | |||
31 | #include <stdlib.h> | ||
32 | #include <string.h> | ||
33 | #ifdef _WIN32_WCE | ||
34 | #define assert(x) | ||
35 | #else | ||
36 | #include <assert.h> | ||
37 | #endif | ||
38 | |||
39 | #include "filtbank.h" | ||
40 | #include "decoder.h" | ||
41 | #include "syntax.h" | ||
42 | #include "kbd_win.h" | ||
43 | #include "sine_win.h" | ||
44 | #include "mdct.h" | ||
45 | |||
46 | |||
47 | fb_info *filter_bank_init(uint16_t frame_len) | ||
48 | { | ||
49 | uint16_t nshort = frame_len/8; | ||
50 | #ifdef LD_DEC | ||
51 | uint16_t frame_len_ld = frame_len/2; | ||
52 | #endif | ||
53 | |||
54 | fb_info *fb = (fb_info*)faad_malloc(sizeof(fb_info)); | ||
55 | memset(fb, 0, sizeof(fb_info)); | ||
56 | |||
57 | /* normal */ | ||
58 | fb->mdct256 = faad_mdct_init(2*nshort); | ||
59 | fb->mdct2048 = faad_mdct_init(2*frame_len); | ||
60 | #ifdef LD_DEC | ||
61 | /* LD */ | ||
62 | fb->mdct1024 = faad_mdct_init(2*frame_len_ld); | ||
63 | #endif | ||
64 | |||
65 | #ifdef ALLOW_SMALL_FRAMELENGTH | ||
66 | if (frame_len == 1024) | ||
67 | { | ||
68 | #endif | ||
69 | fb->long_window[0] = sine_long_1024; | ||
70 | fb->short_window[0] = sine_short_128; | ||
71 | fb->long_window[1] = kbd_long_1024; | ||
72 | fb->short_window[1] = kbd_short_128; | ||
73 | #ifdef LD_DEC | ||
74 | fb->ld_window[0] = sine_mid_512; | ||
75 | fb->ld_window[1] = ld_mid_512; | ||
76 | #endif | ||
77 | #ifdef ALLOW_SMALL_FRAMELENGTH | ||
78 | } else /* (frame_len == 960) */ { | ||
79 | fb->long_window[0] = sine_long_960; | ||
80 | fb->short_window[0] = sine_short_120; | ||
81 | fb->long_window[1] = kbd_long_960; | ||
82 | fb->short_window[1] = kbd_short_120; | ||
83 | #ifdef LD_DEC | ||
84 | fb->ld_window[0] = sine_mid_480; | ||
85 | fb->ld_window[1] = ld_mid_480; | ||
86 | #endif | ||
87 | } | ||
88 | #endif | ||
89 | |||
90 | return fb; | ||
91 | } | ||
92 | |||
93 | void filter_bank_end(fb_info *fb) | ||
94 | { | ||
95 | if (fb != NULL) | ||
96 | { | ||
97 | #ifdef PROFILE | ||
98 | printf("FB: %I64d cycles\n", fb->cycles); | ||
99 | #endif | ||
100 | |||
101 | faad_mdct_end(fb->mdct256); | ||
102 | faad_mdct_end(fb->mdct2048); | ||
103 | #ifdef LD_DEC | ||
104 | faad_mdct_end(fb->mdct1024); | ||
105 | #endif | ||
106 | |||
107 | faad_free(fb); | ||
108 | } | ||
109 | } | ||
110 | |||
111 | static INLINE void imdct_long(fb_info *fb, real_t *in_data, real_t *out_data, uint16_t len) | ||
112 | { | ||
113 | #ifdef LD_DEC | ||
114 | mdct_info *mdct = NULL; | ||
115 | |||
116 | switch (len) | ||
117 | { | ||
118 | case 2048: | ||
119 | case 1920: | ||
120 | mdct = fb->mdct2048; | ||
121 | break; | ||
122 | case 1024: | ||
123 | case 960: | ||
124 | mdct = fb->mdct1024; | ||
125 | break; | ||
126 | } | ||
127 | |||
128 | faad_imdct(mdct, in_data, out_data); | ||
129 | #else | ||
130 | faad_imdct(fb->mdct2048, in_data, out_data); | ||
131 | #endif | ||
132 | } | ||
133 | |||
134 | |||
135 | #ifdef LTP_DEC | ||
136 | static INLINE void mdct(fb_info *fb, real_t *in_data, real_t *out_data, uint16_t len) | ||
137 | { | ||
138 | mdct_info *mdct = NULL; | ||
139 | |||
140 | switch (len) | ||
141 | { | ||
142 | case 2048: | ||
143 | case 1920: | ||
144 | mdct = fb->mdct2048; | ||
145 | break; | ||
146 | case 256: | ||
147 | case 240: | ||
148 | mdct = fb->mdct256; | ||
149 | break; | ||
150 | #ifdef LD_DEC | ||
151 | case 1024: | ||
152 | case 960: | ||
153 | mdct = fb->mdct1024; | ||
154 | break; | ||
155 | #endif | ||
156 | } | ||
157 | |||
158 | faad_mdct(mdct, in_data, out_data); | ||
159 | } | ||
160 | #endif | ||
161 | |||
162 | void ifilter_bank(fb_info *fb, uint8_t window_sequence, uint8_t window_shape, | ||
163 | uint8_t window_shape_prev, real_t *freq_in, | ||
164 | real_t *time_out, real_t *overlap, | ||
165 | uint8_t object_type, uint16_t frame_len) | ||
166 | { | ||
167 | int16_t i; | ||
168 | ALIGN real_t transf_buf[2*1024] = {0}; | ||
169 | |||
170 | const real_t *window_long = NULL; | ||
171 | const real_t *window_long_prev = NULL; | ||
172 | const real_t *window_short = NULL; | ||
173 | const real_t *window_short_prev = NULL; | ||
174 | |||
175 | uint16_t nlong = frame_len; | ||
176 | uint16_t nshort = frame_len/8; | ||
177 | uint16_t trans = nshort/2; | ||
178 | |||
179 | uint16_t nflat_ls = (nlong-nshort)/2; | ||
180 | |||
181 | #ifdef PROFILE | ||
182 | int64_t count = faad_get_ts(); | ||
183 | #endif | ||
184 | |||
185 | /* select windows of current frame and previous frame (Sine or KBD) */ | ||
186 | #ifdef LD_DEC | ||
187 | if (object_type == LD) | ||
188 | { | ||
189 | window_long = fb->ld_window[window_shape]; | ||
190 | window_long_prev = fb->ld_window[window_shape_prev]; | ||
191 | } else { | ||
192 | #endif | ||
193 | window_long = fb->long_window[window_shape]; | ||
194 | window_long_prev = fb->long_window[window_shape_prev]; | ||
195 | window_short = fb->short_window[window_shape]; | ||
196 | window_short_prev = fb->short_window[window_shape_prev]; | ||
197 | #ifdef LD_DEC | ||
198 | } | ||
199 | #endif | ||
200 | |||
201 | #if 0 | ||
202 | for (i = 0; i < 1024; i++) | ||
203 | { | ||
204 | printf("%d\n", freq_in[i]); | ||
205 | } | ||
206 | #endif | ||
207 | |||
208 | #if 0 | ||
209 | printf("%d %d\n", window_sequence, window_shape); | ||
210 | #endif | ||
211 | |||
212 | switch (window_sequence) | ||
213 | { | ||
214 | case ONLY_LONG_SEQUENCE: | ||
215 | /* perform iMDCT */ | ||
216 | imdct_long(fb, freq_in, transf_buf, 2*nlong); | ||
217 | |||
218 | /* add second half output of previous frame to windowed output of current frame */ | ||
219 | for (i = 0; i < nlong; i+=4) | ||
220 | { | ||
221 | time_out[i] = overlap[i] + MUL_F(transf_buf[i],window_long_prev[i]); | ||
222 | time_out[i+1] = overlap[i+1] + MUL_F(transf_buf[i+1],window_long_prev[i+1]); | ||
223 | time_out[i+2] = overlap[i+2] + MUL_F(transf_buf[i+2],window_long_prev[i+2]); | ||
224 | time_out[i+3] = overlap[i+3] + MUL_F(transf_buf[i+3],window_long_prev[i+3]); | ||
225 | } | ||
226 | |||
227 | /* window the second half and save as overlap for next frame */ | ||
228 | for (i = 0; i < nlong; i+=4) | ||
229 | { | ||
230 | overlap[i] = MUL_F(transf_buf[nlong+i],window_long[nlong-1-i]); | ||
231 | overlap[i+1] = MUL_F(transf_buf[nlong+i+1],window_long[nlong-2-i]); | ||
232 | overlap[i+2] = MUL_F(transf_buf[nlong+i+2],window_long[nlong-3-i]); | ||
233 | overlap[i+3] = MUL_F(transf_buf[nlong+i+3],window_long[nlong-4-i]); | ||
234 | } | ||
235 | break; | ||
236 | |||
237 | case LONG_START_SEQUENCE: | ||
238 | /* perform iMDCT */ | ||
239 | imdct_long(fb, freq_in, transf_buf, 2*nlong); | ||
240 | |||
241 | /* add second half output of previous frame to windowed output of current frame */ | ||
242 | for (i = 0; i < nlong; i+=4) | ||
243 | { | ||
244 | time_out[i] = overlap[i] + MUL_F(transf_buf[i],window_long_prev[i]); | ||
245 | time_out[i+1] = overlap[i+1] + MUL_F(transf_buf[i+1],window_long_prev[i+1]); | ||
246 | time_out[i+2] = overlap[i+2] + MUL_F(transf_buf[i+2],window_long_prev[i+2]); | ||
247 | time_out[i+3] = overlap[i+3] + MUL_F(transf_buf[i+3],window_long_prev[i+3]); | ||
248 | } | ||
249 | |||
250 | /* window the second half and save as overlap for next frame */ | ||
251 | /* construct second half window using padding with 1's and 0's */ | ||
252 | for (i = 0; i < nflat_ls; i++) | ||
253 | overlap[i] = transf_buf[nlong+i]; | ||
254 | for (i = 0; i < nshort; i++) | ||
255 | overlap[nflat_ls+i] = MUL_F(transf_buf[nlong+nflat_ls+i],window_short[nshort-i-1]); | ||
256 | for (i = 0; i < nflat_ls; i++) | ||
257 | overlap[nflat_ls+nshort+i] = 0; | ||
258 | break; | ||
259 | |||
260 | case EIGHT_SHORT_SEQUENCE: | ||
261 | /* perform iMDCT for each short block */ | ||
262 | faad_imdct(fb->mdct256, freq_in+0*nshort, transf_buf+2*nshort*0); | ||
263 | faad_imdct(fb->mdct256, freq_in+1*nshort, transf_buf+2*nshort*1); | ||
264 | faad_imdct(fb->mdct256, freq_in+2*nshort, transf_buf+2*nshort*2); | ||
265 | faad_imdct(fb->mdct256, freq_in+3*nshort, transf_buf+2*nshort*3); | ||
266 | faad_imdct(fb->mdct256, freq_in+4*nshort, transf_buf+2*nshort*4); | ||
267 | faad_imdct(fb->mdct256, freq_in+5*nshort, transf_buf+2*nshort*5); | ||
268 | faad_imdct(fb->mdct256, freq_in+6*nshort, transf_buf+2*nshort*6); | ||
269 | faad_imdct(fb->mdct256, freq_in+7*nshort, transf_buf+2*nshort*7); | ||
270 | |||
271 | /* add second half output of previous frame to windowed output of current frame */ | ||
272 | for (i = 0; i < nflat_ls; i++) | ||
273 | time_out[i] = overlap[i]; | ||
274 | for(i = 0; i < nshort; i++) | ||
275 | { | ||
276 | time_out[nflat_ls+ i] = overlap[nflat_ls+ i] + MUL_F(transf_buf[nshort*0+i],window_short_prev[i]); | ||
277 | time_out[nflat_ls+1*nshort+i] = overlap[nflat_ls+nshort*1+i] + MUL_F(transf_buf[nshort*1+i],window_short[nshort-1-i]) + MUL_F(transf_buf[nshort*2+i],window_short[i]); | ||
278 | time_out[nflat_ls+2*nshort+i] = overlap[nflat_ls+nshort*2+i] + MUL_F(transf_buf[nshort*3+i],window_short[nshort-1-i]) + MUL_F(transf_buf[nshort*4+i],window_short[i]); | ||
279 | time_out[nflat_ls+3*nshort+i] = overlap[nflat_ls+nshort*3+i] + MUL_F(transf_buf[nshort*5+i],window_short[nshort-1-i]) + MUL_F(transf_buf[nshort*6+i],window_short[i]); | ||
280 | if (i < trans) | ||
281 | time_out[nflat_ls+4*nshort+i] = overlap[nflat_ls+nshort*4+i] + MUL_F(transf_buf[nshort*7+i],window_short[nshort-1-i]) + MUL_F(transf_buf[nshort*8+i],window_short[i]); | ||
282 | } | ||
283 | |||
284 | /* window the second half and save as overlap for next frame */ | ||
285 | for(i = 0; i < nshort; i++) | ||
286 | { | ||
287 | if (i >= trans) | ||
288 | overlap[nflat_ls+4*nshort+i-nlong] = MUL_F(transf_buf[nshort*7+i],window_short[nshort-1-i]) + MUL_F(transf_buf[nshort*8+i],window_short[i]); | ||
289 | overlap[nflat_ls+5*nshort+i-nlong] = MUL_F(transf_buf[nshort*9+i],window_short[nshort-1-i]) + MUL_F(transf_buf[nshort*10+i],window_short[i]); | ||
290 | overlap[nflat_ls+6*nshort+i-nlong] = MUL_F(transf_buf[nshort*11+i],window_short[nshort-1-i]) + MUL_F(transf_buf[nshort*12+i],window_short[i]); | ||
291 | overlap[nflat_ls+7*nshort+i-nlong] = MUL_F(transf_buf[nshort*13+i],window_short[nshort-1-i]) + MUL_F(transf_buf[nshort*14+i],window_short[i]); | ||
292 | overlap[nflat_ls+8*nshort+i-nlong] = MUL_F(transf_buf[nshort*15+i],window_short[nshort-1-i]); | ||
293 | } | ||
294 | for (i = 0; i < nflat_ls; i++) | ||
295 | overlap[nflat_ls+nshort+i] = 0; | ||
296 | break; | ||
297 | |||
298 | case LONG_STOP_SEQUENCE: | ||
299 | /* perform iMDCT */ | ||
300 | imdct_long(fb, freq_in, transf_buf, 2*nlong); | ||
301 | |||
302 | /* add second half output of previous frame to windowed output of current frame */ | ||
303 | /* construct first half window using padding with 1's and 0's */ | ||
304 | for (i = 0; i < nflat_ls; i++) | ||
305 | time_out[i] = overlap[i]; | ||
306 | for (i = 0; i < nshort; i++) | ||
307 | time_out[nflat_ls+i] = overlap[nflat_ls+i] + MUL_F(transf_buf[nflat_ls+i],window_short_prev[i]); | ||
308 | for (i = 0; i < nflat_ls; i++) | ||
309 | time_out[nflat_ls+nshort+i] = overlap[nflat_ls+nshort+i] + transf_buf[nflat_ls+nshort+i]; | ||
310 | |||
311 | /* window the second half and save as overlap for next frame */ | ||
312 | for (i = 0; i < nlong; i++) | ||
313 | overlap[i] = MUL_F(transf_buf[nlong+i],window_long[nlong-1-i]); | ||
314 | break; | ||
315 | } | ||
316 | |||
317 | #if 0 | ||
318 | for (i = 0; i < 1024; i++) | ||
319 | { | ||
320 | printf("%d\n", time_out[i]); | ||
321 | //printf("0x%.8X\n", time_out[i]); | ||
322 | } | ||
323 | #endif | ||
324 | |||
325 | |||
326 | #ifdef PROFILE | ||
327 | count = faad_get_ts() - count; | ||
328 | fb->cycles += count; | ||
329 | #endif | ||
330 | } | ||
331 | |||
332 | |||
333 | #ifdef LTP_DEC | ||
334 | /* only works for LTP -> no overlapping, no short blocks */ | ||
335 | void filter_bank_ltp(fb_info *fb, uint8_t window_sequence, uint8_t window_shape, | ||
336 | uint8_t window_shape_prev, real_t *in_data, real_t *out_mdct, | ||
337 | uint8_t object_type, uint16_t frame_len) | ||
338 | { | ||
339 | int16_t i; | ||
340 | ALIGN real_t windowed_buf[2*1024] = {0}; | ||
341 | |||
342 | const real_t *window_long = NULL; | ||
343 | const real_t *window_long_prev = NULL; | ||
344 | const real_t *window_short = NULL; | ||
345 | const real_t *window_short_prev = NULL; | ||
346 | |||
347 | uint16_t nlong = frame_len; | ||
348 | uint16_t nshort = frame_len/8; | ||
349 | uint16_t nflat_ls = (nlong-nshort)/2; | ||
350 | |||
351 | assert(window_sequence != EIGHT_SHORT_SEQUENCE); | ||
352 | |||
353 | #ifdef LD_DEC | ||
354 | if (object_type == LD) | ||
355 | { | ||
356 | window_long = fb->ld_window[window_shape]; | ||
357 | window_long_prev = fb->ld_window[window_shape_prev]; | ||
358 | } else { | ||
359 | #endif | ||
360 | window_long = fb->long_window[window_shape]; | ||
361 | window_long_prev = fb->long_window[window_shape_prev]; | ||
362 | window_short = fb->short_window[window_shape]; | ||
363 | window_short_prev = fb->short_window[window_shape_prev]; | ||
364 | #ifdef LD_DEC | ||
365 | } | ||
366 | #endif | ||
367 | |||
368 | switch(window_sequence) | ||
369 | { | ||
370 | case ONLY_LONG_SEQUENCE: | ||
371 | for (i = nlong-1; i >= 0; i--) | ||
372 | { | ||
373 | windowed_buf[i] = MUL_F(in_data[i], window_long_prev[i]); | ||
374 | windowed_buf[i+nlong] = MUL_F(in_data[i+nlong], window_long[nlong-1-i]); | ||
375 | } | ||
376 | mdct(fb, windowed_buf, out_mdct, 2*nlong); | ||
377 | break; | ||
378 | |||
379 | case LONG_START_SEQUENCE: | ||
380 | for (i = 0; i < nlong; i++) | ||
381 | windowed_buf[i] = MUL_F(in_data[i], window_long_prev[i]); | ||
382 | for (i = 0; i < nflat_ls; i++) | ||
383 | windowed_buf[i+nlong] = in_data[i+nlong]; | ||
384 | for (i = 0; i < nshort; i++) | ||
385 | windowed_buf[i+nlong+nflat_ls] = MUL_F(in_data[i+nlong+nflat_ls], window_short[nshort-1-i]); | ||
386 | for (i = 0; i < nflat_ls; i++) | ||
387 | windowed_buf[i+nlong+nflat_ls+nshort] = 0; | ||
388 | mdct(fb, windowed_buf, out_mdct, 2*nlong); | ||
389 | break; | ||
390 | |||
391 | case LONG_STOP_SEQUENCE: | ||
392 | for (i = 0; i < nflat_ls; i++) | ||
393 | windowed_buf[i] = 0; | ||
394 | for (i = 0; i < nshort; i++) | ||
395 | windowed_buf[i+nflat_ls] = MUL_F(in_data[i+nflat_ls], window_short_prev[i]); | ||
396 | for (i = 0; i < nflat_ls; i++) | ||
397 | windowed_buf[i+nflat_ls+nshort] = in_data[i+nflat_ls+nshort]; | ||
398 | for (i = 0; i < nlong; i++) | ||
399 | windowed_buf[i+nlong] = MUL_F(in_data[i+nlong], window_long[nlong-1-i]); | ||
400 | mdct(fb, windowed_buf, out_mdct, 2*nlong); | ||
401 | break; | ||
402 | } | ||
403 | } | ||
404 | #endif | ||