summaryrefslogtreecommitdiff
path: root/audio_codec/libfaad/filtbank.c (plain)
blob: c115c51c545451ee8fc33bc9db7d46244a3455be
1/*
2** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding
3** Copyright (C) 2003-2005 M. Bakker, Nero 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** The "appropriate copyright message" mentioned in section 2c of the GPLv2
23** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com"
24**
25** Commercial non-GPL licensing of this software is possible.
26** For more info contact Nero AG through Mpeg4AAClicense@nero.com.
27**
28** $Id: filtbank.c,v 1.46 2009/01/26 23:51:15 menno Exp $
29**/
30#include <stdlib.h>
31#include "common.h"
32#include "structs.h"
33
34#include <string.h>
35#ifdef _WIN32_WCE
36#define assert(x)
37#else
38#include <assert.h>
39#endif
40
41#include "filtbank.h"
42#include "syntax.h"
43#include "kbd_win.h"
44#include "sine_win.h"
45#include "mdct.h"
46
47
48fb_info *filter_bank_init(uint16_t frame_len)
49{
50 uint16_t nshort = frame_len / 8;
51#ifdef LD_DEC
52 uint16_t frame_len_ld = frame_len / 2;
53#endif
54
55 fb_info *fb = (fb_info*)faad_malloc(sizeof(fb_info));
56 memset(fb, 0, sizeof(fb_info));
57
58 /* normal */
59 fb->mdct256 = faad_mdct_init(2 * nshort);
60 fb->mdct2048 = faad_mdct_init(2 * frame_len);
61#ifdef LD_DEC
62 /* LD */
63 fb->mdct1024 = faad_mdct_init(2 * frame_len_ld);
64#endif
65
66#ifdef ALLOW_SMALL_FRAMELENGTH
67 if (frame_len == 1024) {
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
93void filter_bank_end(fb_info *fb)
94{
95 if (fb != NULL) {
96#ifdef PROFILE
97 printf("FB: %I64d cycles\n", fb->cycles);
98#endif
99
100 faad_mdct_end(fb->mdct256);
101 faad_mdct_end(fb->mdct2048);
102#ifdef LD_DEC
103 faad_mdct_end(fb->mdct1024);
104#endif
105
106 faad_free(fb);
107 }
108}
109
110static INLINE void imdct_long(fb_info *fb, real_t *in_data, real_t *out_data, uint16_t len)
111{
112#ifdef LD_DEC
113 mdct_info *mdct = NULL;
114
115 switch (len) {
116 case 2048:
117 case 1920:
118 mdct = fb->mdct2048;
119 break;
120 case 1024:
121 case 960:
122 mdct = fb->mdct1024;
123 break;
124 }
125
126 faad_imdct(mdct, in_data, out_data);
127#else
128 faad_imdct(fb->mdct2048, in_data, out_data);
129#endif
130}
131
132
133#ifdef LTP_DEC
134static INLINE void mdct(fb_info *fb, real_t *in_data, real_t *out_data, uint16_t len)
135{
136 mdct_info *mdct = NULL;
137
138 switch (len) {
139 case 2048:
140 case 1920:
141 mdct = fb->mdct2048;
142 break;
143 case 256:
144 case 240:
145 mdct = fb->mdct256;
146 break;
147#ifdef LD_DEC
148 case 1024:
149 case 960:
150 mdct = fb->mdct1024;
151 break;
152#endif
153 }
154
155 faad_mdct(mdct, in_data, out_data);
156}
157#endif
158
159void ifilter_bank(fb_info *fb, uint8_t window_sequence, uint8_t window_shape,
160 uint8_t window_shape_prev, real_t *freq_in,
161 real_t *time_out, real_t *overlap,
162 uint8_t object_type, uint16_t frame_len)
163{
164 int16_t i;
165 ALIGN real_t transf_buf[2 * 1024] = {0};
166
167 const real_t *window_long = NULL;
168 const real_t *window_long_prev = NULL;
169 const real_t *window_short = NULL;
170 const real_t *window_short_prev = NULL;
171
172 uint16_t nlong = frame_len;
173 uint16_t nshort = frame_len / 8;
174 uint16_t trans = nshort / 2;
175
176 uint16_t nflat_ls = (nlong - nshort) / 2;
177
178#ifdef PROFILE
179 int64_t count = faad_get_ts();
180#endif
181
182 /* select windows of current frame and previous frame (Sine or KBD) */
183#ifdef LD_DEC
184 if (object_type == LD) {
185 window_long = fb->ld_window[window_shape];
186 window_long_prev = fb->ld_window[window_shape_prev];
187 } else {
188#endif
189 window_long = fb->long_window[window_shape];
190 window_long_prev = fb->long_window[window_shape_prev];
191 window_short = fb->short_window[window_shape];
192 window_short_prev = fb->short_window[window_shape_prev];
193#ifdef LD_DEC
194 }
195#endif
196
197#if 0
198 for (i = 0; i < 1024; i++) {
199 printf("%d\n", freq_in[i]);
200 }
201#endif
202
203#if 0
204 printf("%d %d\n", window_sequence, window_shape);
205#endif
206
207 switch (window_sequence) {
208 case ONLY_LONG_SEQUENCE:
209 /* perform iMDCT */
210 imdct_long(fb, freq_in, transf_buf, 2 * nlong);
211
212 /* add second half output of previous frame to windowed output of current frame */
213 for (i = 0; i < nlong; i += 4) {
214 time_out[i] = overlap[i] + MUL_F(transf_buf[i], window_long_prev[i]);
215 time_out[i + 1] = overlap[i + 1] + MUL_F(transf_buf[i + 1], window_long_prev[i + 1]);
216 time_out[i + 2] = overlap[i + 2] + MUL_F(transf_buf[i + 2], window_long_prev[i + 2]);
217 time_out[i + 3] = overlap[i + 3] + MUL_F(transf_buf[i + 3], window_long_prev[i + 3]);
218 }
219
220 /* window the second half and save as overlap for next frame */
221 for (i = 0; i < nlong; i += 4) {
222 overlap[i] = MUL_F(transf_buf[nlong + i], window_long[nlong - 1 - i]);
223 overlap[i + 1] = MUL_F(transf_buf[nlong + i + 1], window_long[nlong - 2 - i]);
224 overlap[i + 2] = MUL_F(transf_buf[nlong + i + 2], window_long[nlong - 3 - i]);
225 overlap[i + 3] = MUL_F(transf_buf[nlong + i + 3], window_long[nlong - 4 - i]);
226 }
227 break;
228
229 case LONG_START_SEQUENCE:
230 /* perform iMDCT */
231 imdct_long(fb, freq_in, transf_buf, 2 * nlong);
232
233 /* add second half output of previous frame to windowed output of current frame */
234 for (i = 0; i < nlong; i += 4) {
235 time_out[i] = overlap[i] + MUL_F(transf_buf[i], window_long_prev[i]);
236 time_out[i + 1] = overlap[i + 1] + MUL_F(transf_buf[i + 1], window_long_prev[i + 1]);
237 time_out[i + 2] = overlap[i + 2] + MUL_F(transf_buf[i + 2], window_long_prev[i + 2]);
238 time_out[i + 3] = overlap[i + 3] + MUL_F(transf_buf[i + 3], window_long_prev[i + 3]);
239 }
240
241 /* window the second half and save as overlap for next frame */
242 /* construct second half window using padding with 1's and 0's */
243 for (i = 0; i < nflat_ls; i++) {
244 overlap[i] = transf_buf[nlong + i];
245 }
246 for (i = 0; i < nshort; i++) {
247 overlap[nflat_ls + i] = MUL_F(transf_buf[nlong + nflat_ls + i], window_short[nshort - i - 1]);
248 }
249 for (i = 0; i < nflat_ls; i++) {
250 overlap[nflat_ls + nshort + i] = 0;
251 }
252 break;
253
254 case EIGHT_SHORT_SEQUENCE:
255 /* perform iMDCT for each short block */
256 faad_imdct(fb->mdct256, freq_in + 0 * nshort, transf_buf + 2 * nshort * 0);
257 faad_imdct(fb->mdct256, freq_in + 1 * nshort, transf_buf + 2 * nshort * 1);
258 faad_imdct(fb->mdct256, freq_in + 2 * nshort, transf_buf + 2 * nshort * 2);
259 faad_imdct(fb->mdct256, freq_in + 3 * nshort, transf_buf + 2 * nshort * 3);
260 faad_imdct(fb->mdct256, freq_in + 4 * nshort, transf_buf + 2 * nshort * 4);
261 faad_imdct(fb->mdct256, freq_in + 5 * nshort, transf_buf + 2 * nshort * 5);
262 faad_imdct(fb->mdct256, freq_in + 6 * nshort, transf_buf + 2 * nshort * 6);
263 faad_imdct(fb->mdct256, freq_in + 7 * nshort, transf_buf + 2 * nshort * 7);
264
265 /* add second half output of previous frame to windowed output of current frame */
266 for (i = 0; i < nflat_ls; i++) {
267 time_out[i] = overlap[i];
268 }
269 for (i = 0; i < nshort; i++) {
270 time_out[nflat_ls + i] = overlap[nflat_ls + i] + MUL_F(transf_buf[nshort * 0 + i], window_short_prev[i]);
271 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]);
272 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]);
273 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]);
274 if (i < trans) {
275 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]);
276 }
277 }
278
279 /* window the second half and save as overlap for next frame */
280 for (i = 0; i < nshort; i++) {
281 if (i >= trans) {
282 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]);
283 }
284 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]);
285 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]);
286 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]);
287 overlap[nflat_ls + 8 * nshort + i - nlong] = MUL_F(transf_buf[nshort * 15 + i], window_short[nshort - 1 - i]);
288 }
289 for (i = 0; i < nflat_ls; i++) {
290 overlap[nflat_ls + nshort + i] = 0;
291 }
292 break;
293
294 case LONG_STOP_SEQUENCE:
295 /* perform iMDCT */
296 imdct_long(fb, freq_in, transf_buf, 2 * nlong);
297
298 /* add second half output of previous frame to windowed output of current frame */
299 /* construct first half window using padding with 1's and 0's */
300 for (i = 0; i < nflat_ls; i++) {
301 time_out[i] = overlap[i];
302 }
303 for (i = 0; i < nshort; i++) {
304 time_out[nflat_ls + i] = overlap[nflat_ls + i] + MUL_F(transf_buf[nflat_ls + i], window_short_prev[i]);
305 }
306 for (i = 0; i < nflat_ls; i++) {
307 time_out[nflat_ls + nshort + i] = overlap[nflat_ls + nshort + i] + transf_buf[nflat_ls + nshort + i];
308 }
309
310 /* window the second half and save as overlap for next frame */
311 for (i = 0; i < nlong; i++) {
312 overlap[i] = MUL_F(transf_buf[nlong + i], window_long[nlong - 1 - i]);
313 }
314 break;
315 }
316
317#if 0
318 for (i = 0; i < 1024; i++) {
319 printf("%d\n", time_out[i]);
320 //printf("0x%.8X\n", time_out[i]);
321 }
322#endif
323
324
325#ifdef PROFILE
326 count = faad_get_ts() - count;
327 fb->cycles += count;
328#endif
329}
330
331
332#ifdef LTP_DEC
333/* only works for LTP -> no overlapping, no short blocks */
334void filter_bank_ltp(fb_info *fb, uint8_t window_sequence, uint8_t window_shape,
335 uint8_t window_shape_prev, real_t *in_data, real_t *out_mdct,
336 uint8_t object_type, uint16_t frame_len)
337{
338 int16_t i;
339 ALIGN real_t windowed_buf[2 * 1024] = {0};
340
341 const real_t *window_long = NULL;
342 const real_t *window_long_prev = NULL;
343 const real_t *window_short = NULL;
344 const real_t *window_short_prev = NULL;
345
346 uint16_t nlong = frame_len;
347 uint16_t nshort = frame_len / 8;
348 uint16_t nflat_ls = (nlong - nshort) / 2;
349
350 assert(window_sequence != EIGHT_SHORT_SEQUENCE);
351
352#ifdef LD_DEC
353 if (object_type == LD) {
354 window_long = fb->ld_window[window_shape];
355 window_long_prev = fb->ld_window[window_shape_prev];
356 } else {
357#endif
358 window_long = fb->long_window[window_shape];
359 window_long_prev = fb->long_window[window_shape_prev];
360 window_short = fb->short_window[window_shape];
361 window_short_prev = fb->short_window[window_shape_prev];
362#ifdef LD_DEC
363 }
364#endif
365
366 switch (window_sequence) {
367 case ONLY_LONG_SEQUENCE:
368 for (i = nlong - 1; i >= 0; i--) {
369 windowed_buf[i] = MUL_F(in_data[i], window_long_prev[i]);
370 windowed_buf[i + nlong] = MUL_F(in_data[i + nlong], window_long[nlong - 1 - i]);
371 }
372 mdct(fb, windowed_buf, out_mdct, 2 * nlong);
373 break;
374
375 case LONG_START_SEQUENCE:
376 for (i = 0; i < nlong; i++) {
377 windowed_buf[i] = MUL_F(in_data[i], window_long_prev[i]);
378 }
379 for (i = 0; i < nflat_ls; i++) {
380 windowed_buf[i + nlong] = in_data[i + nlong];
381 }
382 for (i = 0; i < nshort; i++) {
383 windowed_buf[i + nlong + nflat_ls] = MUL_F(in_data[i + nlong + nflat_ls], window_short[nshort - 1 - i]);
384 }
385 for (i = 0; i < nflat_ls; i++) {
386 windowed_buf[i + nlong + nflat_ls + nshort] = 0;
387 }
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 }
395 for (i = 0; i < nshort; i++) {
396 windowed_buf[i + nflat_ls] = MUL_F(in_data[i + nflat_ls], window_short_prev[i]);
397 }
398 for (i = 0; i < nflat_ls; i++) {
399 windowed_buf[i + nflat_ls + nshort] = in_data[i + nflat_ls + nshort];
400 }
401 for (i = 0; i < nlong; i++) {
402 windowed_buf[i + nlong] = MUL_F(in_data[i + nlong], window_long[nlong - 1 - i]);
403 }
404 mdct(fb, windowed_buf, out_mdct, 2 * nlong);
405 break;
406 }
407}
408#endif
409