blob: 71273dabf4f9fd45eebe2596919aed9472f2cb81
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: mdct.c,v 1.47 2007/11/01 12:33:31 menno Exp $ |
29 | **/ |
30 | |
31 | /* |
32 | * Fast (I)MDCT Implementation using (I)FFT ((Inverse) Fast Fourier Transform) |
33 | * and consists of three steps: pre-(I)FFT complex multiplication, complex |
34 | * (I)FFT, post-(I)FFT complex multiplication, |
35 | * |
36 | * As described in: |
37 | * P. Duhamel, Y. Mahieux, and J.P. Petit, "A Fast Algorithm for the |
38 | * Implementation of Filter Banks Based on 'Time Domain Aliasing |
39 | * Cancellation’," IEEE Proc. on ICASSP‘91, 1991, pp. 2209-2212. |
40 | * |
41 | * |
42 | * As of April 6th 2002 completely rewritten. |
43 | * This (I)MDCT can now be used for any data size n, where n is divisible by 8. |
44 | * |
45 | */ |
46 | #include <stdlib.h> |
47 | #include "common.h" |
48 | #include "structs.h" |
49 | |
50 | |
51 | #ifdef _WIN32_WCE |
52 | #define assert(x) |
53 | #else |
54 | #include <assert.h> |
55 | #endif |
56 | |
57 | #include "cfft.h" |
58 | #include "mdct.h" |
59 | #include "mdct_tab.h" |
60 | |
61 | |
62 | mdct_info *faad_mdct_init(uint16_t N) |
63 | { |
64 | mdct_info *mdct = (mdct_info*)faad_malloc(sizeof(mdct_info)); |
65 | |
66 | assert(N % 8 == 0); |
67 | |
68 | mdct->N = N; |
69 | |
70 | /* NOTE: For "small framelengths" in FIXED_POINT the coefficients need to be |
71 | * scaled by sqrt("(nearest power of 2) > N" / N) */ |
72 | |
73 | /* RE(mdct->sincos[k]) = scale*(real_t)(cos(2.0*M_PI*(k+1./8.) / (real_t)N)); |
74 | * IM(mdct->sincos[k]) = scale*(real_t)(sin(2.0*M_PI*(k+1./8.) / (real_t)N)); */ |
75 | /* scale is 1 for fixed point, sqrt(N) for floating point */ |
76 | switch (N) { |
77 | case 2048: |
78 | mdct->sincos = (complex_t*)mdct_tab_2048; |
79 | break; |
80 | case 256: |
81 | mdct->sincos = (complex_t*)mdct_tab_256; |
82 | break; |
83 | #ifdef LD_DEC |
84 | case 1024: |
85 | mdct->sincos = (complex_t*)mdct_tab_1024; |
86 | break; |
87 | #endif |
88 | #ifdef ALLOW_SMALL_FRAMELENGTH |
89 | case 1920: |
90 | mdct->sincos = (complex_t*)mdct_tab_1920; |
91 | break; |
92 | case 240: |
93 | mdct->sincos = (complex_t*)mdct_tab_240; |
94 | break; |
95 | #ifdef LD_DEC |
96 | case 960: |
97 | mdct->sincos = (complex_t*)mdct_tab_960; |
98 | break; |
99 | #endif |
100 | #endif |
101 | #ifdef SSR_DEC |
102 | case 512: |
103 | mdct->sincos = (complex_t*)mdct_tab_512; |
104 | break; |
105 | case 64: |
106 | mdct->sincos = (complex_t*)mdct_tab_64; |
107 | break; |
108 | #endif |
109 | } |
110 | |
111 | /* initialise fft */ |
112 | mdct->cfft = cffti(N / 4); |
113 | |
114 | #ifdef PROFILE |
115 | mdct->cycles = 0; |
116 | mdct->fft_cycles = 0; |
117 | #endif |
118 | |
119 | return mdct; |
120 | } |
121 | |
122 | void faad_mdct_end(mdct_info *mdct) |
123 | { |
124 | if (mdct != NULL) { |
125 | #ifdef PROFILE |
126 | printf("MDCT[%.4d]: %I64d cycles\n", mdct->N, mdct->cycles); |
127 | printf("CFFT[%.4d]: %I64d cycles\n", mdct->N / 4, mdct->fft_cycles); |
128 | #endif |
129 | |
130 | cfftu(mdct->cfft); |
131 | |
132 | faad_free(mdct); |
133 | } |
134 | } |
135 | |
136 | void faad_imdct(mdct_info *mdct, real_t *X_in, real_t *X_out) |
137 | { |
138 | uint16_t k; |
139 | |
140 | complex_t x; |
141 | #ifdef ALLOW_SMALL_FRAMELENGTH |
142 | #ifdef FIXED_POINT |
143 | real_t scale, b_scale = 0; |
144 | #endif |
145 | #endif |
146 | ALIGN complex_t Z1[512]; |
147 | complex_t *sincos = mdct->sincos; |
148 | |
149 | uint16_t N = mdct->N; |
150 | uint16_t N2 = N >> 1; |
151 | uint16_t N4 = N >> 2; |
152 | uint16_t N8 = N >> 3; |
153 | |
154 | #ifdef PROFILE |
155 | int64_t count1, count2 = faad_get_ts(); |
156 | #endif |
157 | |
158 | #ifdef ALLOW_SMALL_FRAMELENGTH |
159 | #ifdef FIXED_POINT |
160 | /* detect non-power of 2 */ |
161 | if (N & (N - 1)) { |
162 | /* adjust scale for non-power of 2 MDCT */ |
163 | /* 2048/1920 */ |
164 | b_scale = 1; |
165 | scale = COEF_CONST(1.0666666666666667); |
166 | } |
167 | #endif |
168 | #endif |
169 | |
170 | /* pre-IFFT complex multiplication */ |
171 | for (k = 0; k < N4; k++) { |
172 | ComplexMult(&IM(Z1[k]), &RE(Z1[k]), |
173 | X_in[2 * k], X_in[N2 - 1 - 2 * k], RE(sincos[k]), IM(sincos[k])); |
174 | } |
175 | |
176 | #ifdef PROFILE |
177 | count1 = faad_get_ts(); |
178 | #endif |
179 | |
180 | /* complex IFFT, any non-scaling FFT can be used here */ |
181 | cfftb(mdct->cfft, Z1); |
182 | |
183 | #ifdef PROFILE |
184 | count1 = faad_get_ts() - count1; |
185 | #endif |
186 | |
187 | /* post-IFFT complex multiplication */ |
188 | for (k = 0; k < N4; k++) { |
189 | RE(x) = RE(Z1[k]); |
190 | IM(x) = IM(Z1[k]); |
191 | ComplexMult(&IM(Z1[k]), &RE(Z1[k]), |
192 | IM(x), RE(x), RE(sincos[k]), IM(sincos[k])); |
193 | |
194 | #ifdef ALLOW_SMALL_FRAMELENGTH |
195 | #ifdef FIXED_POINT |
196 | /* non-power of 2 MDCT scaling */ |
197 | if (b_scale) { |
198 | RE(Z1[k]) = MUL_C(RE(Z1[k]), scale); |
199 | IM(Z1[k]) = MUL_C(IM(Z1[k]), scale); |
200 | } |
201 | #endif |
202 | #endif |
203 | } |
204 | |
205 | /* reordering */ |
206 | for (k = 0; k < N8; k += 2) { |
207 | X_out[ 2 * k] = IM(Z1[N8 + k]); |
208 | X_out[ 2 + 2 * k] = IM(Z1[N8 + 1 + k]); |
209 | |
210 | X_out[ 1 + 2 * k] = -RE(Z1[N8 - 1 - k]); |
211 | X_out[ 3 + 2 * k] = -RE(Z1[N8 - 2 - k]); |
212 | |
213 | X_out[N4 + 2 * k] = RE(Z1[ k]); |
214 | X_out[N4 + + 2 + 2 * k] = RE(Z1[ 1 + k]); |
215 | |
216 | X_out[N4 + 1 + 2 * k] = -IM(Z1[N4 - 1 - k]); |
217 | X_out[N4 + 3 + 2 * k] = -IM(Z1[N4 - 2 - k]); |
218 | |
219 | X_out[N2 + 2 * k] = RE(Z1[N8 + k]); |
220 | X_out[N2 + + 2 + 2 * k] = RE(Z1[N8 + 1 + k]); |
221 | |
222 | X_out[N2 + 1 + 2 * k] = -IM(Z1[N8 - 1 - k]); |
223 | X_out[N2 + 3 + 2 * k] = -IM(Z1[N8 - 2 - k]); |
224 | |
225 | X_out[N2 + N4 + 2 * k] = -IM(Z1[ k]); |
226 | X_out[N2 + N4 + 2 + 2 * k] = -IM(Z1[ 1 + k]); |
227 | |
228 | X_out[N2 + N4 + 1 + 2 * k] = RE(Z1[N4 - 1 - k]); |
229 | X_out[N2 + N4 + 3 + 2 * k] = RE(Z1[N4 - 2 - k]); |
230 | } |
231 | |
232 | #ifdef PROFILE |
233 | count2 = faad_get_ts() - count2; |
234 | mdct->fft_cycles += count1; |
235 | mdct->cycles += (count2 - count1); |
236 | #endif |
237 | } |
238 | |
239 | #ifdef LTP_DEC |
240 | void faad_mdct(mdct_info *mdct, real_t *X_in, real_t *X_out) |
241 | { |
242 | uint16_t k; |
243 | |
244 | complex_t x; |
245 | ALIGN complex_t Z1[512]; |
246 | complex_t *sincos = mdct->sincos; |
247 | |
248 | uint16_t N = mdct->N; |
249 | uint16_t N2 = N >> 1; |
250 | uint16_t N4 = N >> 2; |
251 | uint16_t N8 = N >> 3; |
252 | |
253 | #ifndef FIXED_POINT |
254 | real_t scale = REAL_CONST(N); |
255 | #else |
256 | real_t scale = REAL_CONST(4.0 / N); |
257 | #endif |
258 | |
259 | #ifdef ALLOW_SMALL_FRAMELENGTH |
260 | #ifdef FIXED_POINT |
261 | /* detect non-power of 2 */ |
262 | if (N & (N - 1)) { |
263 | /* adjust scale for non-power of 2 MDCT */ |
264 | /* *= sqrt(2048/1920) */ |
265 | scale = MUL_C(scale, COEF_CONST(1.0327955589886444)); |
266 | } |
267 | #endif |
268 | #endif |
269 | |
270 | /* pre-FFT complex multiplication */ |
271 | for (k = 0; k < N8; k++) { |
272 | uint16_t n = k << 1; |
273 | RE(x) = X_in[N - N4 - 1 - n] + X_in[N - N4 + n]; |
274 | IM(x) = X_in[ N4 + n] - X_in[ N4 - 1 - n]; |
275 | |
276 | ComplexMult(&RE(Z1[k]), &IM(Z1[k]), |
277 | RE(x), IM(x), RE(sincos[k]), IM(sincos[k])); |
278 | |
279 | RE(Z1[k]) = MUL_R(RE(Z1[k]), scale); |
280 | IM(Z1[k]) = MUL_R(IM(Z1[k]), scale); |
281 | |
282 | RE(x) = X_in[N2 - 1 - n] - X_in[ n]; |
283 | IM(x) = X_in[N2 + n] + X_in[N - 1 - n]; |
284 | |
285 | ComplexMult(&RE(Z1[k + N8]), &IM(Z1[k + N8]), |
286 | RE(x), IM(x), RE(sincos[k + N8]), IM(sincos[k + N8])); |
287 | |
288 | RE(Z1[k + N8]) = MUL_R(RE(Z1[k + N8]), scale); |
289 | IM(Z1[k + N8]) = MUL_R(IM(Z1[k + N8]), scale); |
290 | } |
291 | |
292 | /* complex FFT, any non-scaling FFT can be used here */ |
293 | cfftf(mdct->cfft, Z1); |
294 | |
295 | /* post-FFT complex multiplication */ |
296 | for (k = 0; k < N4; k++) { |
297 | uint16_t n = k << 1; |
298 | ComplexMult(&RE(x), &IM(x), |
299 | RE(Z1[k]), IM(Z1[k]), RE(sincos[k]), IM(sincos[k])); |
300 | |
301 | X_out[ n] = -RE(x); |
302 | X_out[N2 - 1 - n] = IM(x); |
303 | X_out[N2 + n] = -IM(x); |
304 | X_out[N - 1 - n] = RE(x); |
305 | } |
306 | } |
307 | #endif |
308 |