blob: b5ffa8e900a4a059d927db048f1dbb58880b8e0c
1 | /* ***** BEGIN LICENSE BLOCK ***** |
2 | * Source last modified: $Id: trigtabs_fltgen.c,v 1.2 2006/12/05 03:36:53 ehyche Exp $ |
3 | * |
4 | * Portions Copyright (c) 1995-2005 RealNetworks, Inc. All Rights Reserved. |
5 | * |
6 | * The contents of this file, and the files included with this file, |
7 | * are subject to the current version of the RealNetworks Public |
8 | * Source License (the "RPSL") available at |
9 | * http://www.helixcommunity.org/content/rpsl unless you have licensed |
10 | * the file under the current version of the RealNetworks Community |
11 | * Source License (the "RCSL") available at |
12 | * http://www.helixcommunity.org/content/rcsl, in which case the RCSL |
13 | * will apply. You may also obtain the license terms directly from |
14 | * RealNetworks. You may not use this file except in compliance with |
15 | * the RPSL or, if you have a valid RCSL with RealNetworks applicable |
16 | * to this file, the RCSL. Please see the applicable RPSL or RCSL for |
17 | * the rights, obligations and limitations governing use of the |
18 | * contents of the file. |
19 | * |
20 | * This file is part of the Helix DNA Technology. RealNetworks is the |
21 | * developer of the Original Code and owns the copyrights in the |
22 | * portions it created. |
23 | * |
24 | * This file, and the files included with this file, is distributed |
25 | * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY |
26 | * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS |
27 | * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES |
28 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET |
29 | * ENJOYMENT OR NON-INFRINGEMENT. |
30 | * |
31 | * Technology Compatibility Kit Test Suite(s) Location: |
32 | * http://www.helixcommunity.org/content/tck |
33 | * |
34 | * Contributor(s): |
35 | * |
36 | * ***** END LICENSE BLOCK ***** */ |
37 | |
38 | /************************************************************************************** |
39 | * Fixed-point HE-AAC decoder |
40 | * Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com) |
41 | * June 2005 |
42 | * |
43 | * trigtabs_fltgen.c - low-ROM alternative to trigtabs.c |
44 | * generates large trig tables at runtime using floating-point |
45 | * math library |
46 | * MUST VERIFY that runtime-generated tables are bit-exact matches |
47 | * with ROM tables in trigtabs.c |
48 | **************************************************************************************/ |
49 | #ifdef HELIX_CONFIG_AAC_GENERATE_TRIGTABS_FLOAT |
50 | |
51 | #include <math.h> |
52 | #include "coder.h" |
53 | |
54 | /* read-only tables */ |
55 | const int cos4sin4tabOffset[NUM_IMDCT_SIZES] = {0, 128}; |
56 | const int sinWindowOffset[NUM_IMDCT_SIZES] = {0, 128}; |
57 | const int kbdWindowOffset[NUM_IMDCT_SIZES] = {0, 128}; |
58 | const int bitrevtabOffset[NUM_IMDCT_SIZES] = {0, 17}; |
59 | const unsigned char bitrevtab[17 + 129] = { |
60 | /* nfft = 64 */ |
61 | 0x01, 0x08, 0x02, 0x04, 0x03, 0x0c, 0x05, 0x0a, 0x07, 0x0e, 0x0b, 0x0d, 0x00, 0x06, 0x09, 0x0f, |
62 | 0x00, |
63 | |
64 | /* nfft = 512 */ |
65 | 0x01, 0x40, 0x02, 0x20, 0x03, 0x60, 0x04, 0x10, 0x05, 0x50, 0x06, 0x30, 0x07, 0x70, 0x09, 0x48, |
66 | 0x0a, 0x28, 0x0b, 0x68, 0x0c, 0x18, 0x0d, 0x58, 0x0e, 0x38, 0x0f, 0x78, 0x11, 0x44, 0x12, 0x24, |
67 | 0x13, 0x64, 0x15, 0x54, 0x16, 0x34, 0x17, 0x74, 0x19, 0x4c, 0x1a, 0x2c, 0x1b, 0x6c, 0x1d, 0x5c, |
68 | 0x1e, 0x3c, 0x1f, 0x7c, 0x21, 0x42, 0x23, 0x62, 0x25, 0x52, 0x26, 0x32, 0x27, 0x72, 0x29, 0x4a, |
69 | 0x2b, 0x6a, 0x2d, 0x5a, 0x2e, 0x3a, 0x2f, 0x7a, 0x31, 0x46, 0x33, 0x66, 0x35, 0x56, 0x37, 0x76, |
70 | 0x39, 0x4e, 0x3b, 0x6e, 0x3d, 0x5e, 0x3f, 0x7e, 0x43, 0x61, 0x45, 0x51, 0x47, 0x71, 0x4b, 0x69, |
71 | 0x4d, 0x59, 0x4f, 0x79, 0x53, 0x65, 0x57, 0x75, 0x5b, 0x6d, 0x5f, 0x7d, 0x67, 0x73, 0x6f, 0x7b, |
72 | 0x00, 0x08, 0x14, 0x1c, 0x22, 0x2a, 0x36, 0x3e, 0x41, 0x49, 0x55, 0x5d, 0x63, 0x6b, 0x77, 0x7f, |
73 | 0x00, |
74 | |
75 | }; |
76 | |
77 | /* tables generated at runtime */ |
78 | int cos4sin4tab[128 + 1024]; |
79 | int cos1sin1tab[514]; |
80 | int sinWindow[128 + 1024]; |
81 | int kbdWindow[128 + 1024]; |
82 | int twidTabEven[4 * 6 + 16 * 6 + 64 * 6]; |
83 | int twidTabOdd[8 * 6 + 32 * 6 + 128 * 6]; |
84 | |
85 | #define M_PI 3.14159265358979323846 |
86 | #define M2_30 1073741824.0 |
87 | #define M2_31 2147483648.0 |
88 | |
89 | #define MAX_DBL 2147483647.0 |
90 | #define MIN_DBL -2147483648.0 |
91 | |
92 | static int NormAndRound(double x, double q, double n) |
93 | { |
94 | if (x >= 0.0) { |
95 | x = (x * q * n + 0.5); |
96 | } else { |
97 | x = (x * q * n - 0.5); |
98 | } |
99 | |
100 | /* clip */ |
101 | if (x > MAX_DBL) { |
102 | x = MAX_DBL; |
103 | } |
104 | if (x < MIN_DBL) { |
105 | x = MIN_DBL; |
106 | } |
107 | |
108 | return (int)x; |
109 | } |
110 | |
111 | static void Init_cos4sin4tab(int *tPtr, int nmdct) |
112 | { |
113 | int i; |
114 | double angle1, angle2, invM, x1, x2, x3, x4; |
115 | |
116 | invM = -1.0 / (double)nmdct; |
117 | for (i = 0; i < nmdct / 4; i++) { |
118 | angle1 = (i + 0.25) * M_PI / nmdct; |
119 | angle2 = (nmdct / 2 - 1 - i + 0.25) * M_PI / nmdct; |
120 | |
121 | x1 = invM * (cos(angle1) + sin(angle1)); |
122 | x2 = invM * sin(angle1); |
123 | x3 = invM * (cos(angle2) + sin(angle2)); |
124 | x4 = invM * sin(angle2); |
125 | |
126 | tPtr[0] = NormAndRound(x1, M2_30, nmdct); |
127 | tPtr[1] = NormAndRound(x2, M2_30, nmdct); |
128 | tPtr[2] = NormAndRound(x3, M2_30, nmdct); |
129 | tPtr[3] = NormAndRound(x4, M2_30, nmdct); |
130 | tPtr += 4; |
131 | } |
132 | } |
133 | |
134 | static void Init_cos1sin1tab(int *tPtr) |
135 | { |
136 | int i; |
137 | double angle, x1, x2; |
138 | |
139 | for (i = 0; i <= (512 / 2); i++) { |
140 | angle = i * M_PI / 1024; |
141 | x1 = (cos(angle) + sin(angle)); |
142 | x2 = sin(angle); |
143 | |
144 | tPtr[0] = NormAndRound(x1, M2_30, 1); |
145 | tPtr[1] = NormAndRound(x2, M2_30, 1); |
146 | tPtr += 2; |
147 | } |
148 | } |
149 | |
150 | static void Init_sinWindow(int *tPtr, int nmdct) |
151 | { |
152 | int i; |
153 | double angle1, angle2, x1, x2; |
154 | |
155 | for (i = 0; i < nmdct / 2; i++) { |
156 | angle1 = (i + 0.5) * M_PI / (2.0 * nmdct); |
157 | angle2 = (nmdct - 1 - i + 0.5) * M_PI / (2.0 * nmdct); |
158 | x1 = sin(angle1); |
159 | x2 = sin(angle2); |
160 | |
161 | tPtr[0] = NormAndRound(x1, M2_31, 1); |
162 | tPtr[1] = NormAndRound(x2, M2_31, 1); |
163 | tPtr += 2; |
164 | } |
165 | } |
166 | |
167 | |
168 | #define KBD_THRESH 1e-12 |
169 | |
170 | static double CalcI0(double x) |
171 | { |
172 | int k; |
173 | double i0, iTmp, iLast, x2, xPow, kFact; |
174 | |
175 | x2 = x / 2.0; |
176 | i0 = 0.0; |
177 | k = 0; |
178 | kFact = 1; |
179 | xPow = 1; |
180 | do { |
181 | iLast = i0; |
182 | iTmp = xPow / kFact; |
183 | i0 += (iTmp * iTmp); |
184 | k++; |
185 | kFact *= k; |
186 | xPow *= x2; |
187 | } while (fabs(i0 - iLast) > KBD_THRESH); |
188 | |
189 | return i0; |
190 | } |
191 | |
192 | static double CalcW(double nRef, double n, double a) |
193 | { |
194 | double i0Base, i0Curr, nTemp; |
195 | |
196 | i0Base = CalcI0(M_PI * a); |
197 | |
198 | nTemp = (n - nRef / 4) / (nRef / 4); |
199 | i0Curr = CalcI0(M_PI * a * sqrt(1.0 - nTemp * nTemp)); |
200 | |
201 | return i0Curr / i0Base; |
202 | } |
203 | |
204 | static void Init_kbdWindow(int *tPtr, int nmdct) |
205 | { |
206 | int n, nRef; |
207 | double a, wBase, wCurr, x1; |
208 | |
209 | nRef = nmdct * 2; |
210 | |
211 | /* kbd window */ |
212 | if (nmdct == 128) { |
213 | a = 6.0; |
214 | } else { |
215 | a = 4.0; |
216 | } |
217 | |
218 | wBase = 0; |
219 | for (n = 0; n <= nRef / 2; n++) { |
220 | wBase += CalcW(nRef, n, a); |
221 | } |
222 | |
223 | /* left */ |
224 | wCurr = 0; |
225 | for (n = 0; n < nmdct / 2; n++) { |
226 | wCurr += CalcW(nRef, n, a); |
227 | x1 = sqrt(wCurr / wBase); |
228 | tPtr[0] = NormAndRound(x1, M2_31, 1); |
229 | tPtr += 2; |
230 | } |
231 | tPtr--; |
232 | |
233 | /* right */ |
234 | for (n = nmdct / 2; n < nmdct; n++) { |
235 | wCurr += CalcW(nRef, n, a); |
236 | x1 = sqrt(wCurr / wBase); |
237 | tPtr[0] = NormAndRound(x1, M2_31, 1); |
238 | tPtr -= 2; |
239 | } |
240 | |
241 | /* symmetry: |
242 | * kbd_right(n) = kbd_ldef(N_REF - 1 - n), n = [N_REF/2, N_REF - 1] |
243 | * |
244 | * wCurr = 0; |
245 | * for (n = N_REF-1; n >= N_REF/2; n--) { |
246 | * wCurr += CalcW(N_REF-n-1, a); |
247 | * kbdWindowRef[n] = sqrt(wCurr / wBase); |
248 | * } |
249 | * |
250 | */ |
251 | return; |
252 | } |
253 | |
254 | static void Init_twidTabs(int *tPtrEven, int *tPtrOdd, int nfft) |
255 | { |
256 | int j, k; |
257 | double wr1, wi1, wr2, wi2, wr3, wi3; |
258 | |
259 | for (k = 4; k <= nfft / 4; k <<= 1) { |
260 | for (j = 0; j < k; j++) { |
261 | wr1 = cos(1.0 * M_PI * j / (2 * k)); |
262 | wi1 = sin(1.0 * M_PI * j / (2 * k)); |
263 | wr1 = (wr1 + wi1); |
264 | wi1 = -wi1; |
265 | |
266 | wr2 = cos(2.0 * M_PI * j / (2 * k)); |
267 | wi2 = sin(2.0 * M_PI * j / (2 * k)); |
268 | wr2 = (wr2 + wi2); |
269 | wi2 = -wi2; |
270 | |
271 | wr3 = cos(3.0 * M_PI * j / (2 * k)); |
272 | wi3 = sin(3.0 * M_PI * j / (2 * k)); |
273 | wr3 = (wr3 + wi3); |
274 | wi3 = -wi3; |
275 | |
276 | if (k & 0xaaaaaaaa) { |
277 | tPtrOdd[0] = NormAndRound(wr2, M2_30, 1); |
278 | tPtrOdd[1] = NormAndRound(wi2, M2_30, 1); |
279 | tPtrOdd[2] = NormAndRound(wr1, M2_30, 1); |
280 | tPtrOdd[3] = NormAndRound(wi1, M2_30, 1); |
281 | tPtrOdd[4] = NormAndRound(wr3, M2_30, 1); |
282 | tPtrOdd[5] = NormAndRound(wi3, M2_30, 1); |
283 | tPtrOdd += 6; |
284 | } else { |
285 | tPtrEven[0] = NormAndRound(wr2, M2_30, 1); |
286 | tPtrEven[1] = NormAndRound(wi2, M2_30, 1); |
287 | tPtrEven[2] = NormAndRound(wr1, M2_30, 1); |
288 | tPtrEven[3] = NormAndRound(wi1, M2_30, 1); |
289 | tPtrEven[4] = NormAndRound(wr3, M2_30, 1); |
290 | tPtrEven[5] = NormAndRound(wi3, M2_30, 1); |
291 | tPtrEven += 6; |
292 | } |
293 | } |
294 | } |
295 | } |
296 | |
297 | /************************************************************************************** |
298 | * Function: AACInitTrigtabsFloat |
299 | * |
300 | * Description: generate AAC decoder tables using floating-point math library |
301 | * |
302 | * Inputs: none |
303 | * |
304 | * Outputs: initialized tables |
305 | * |
306 | * Return: 0 on success |
307 | * |
308 | * Notes: this function should ONLY be called when double-precision |
309 | * floating-point math is supported |
310 | * the generated tables must be bit-exact matches with read-only |
311 | * tables stored in trigtabs.c |
312 | * this initializes global tables in RAM, and is NOT thread-safe, |
313 | * so the caller must ensure that this function is not called |
314 | * from multiple threads |
315 | * this should be called exactly once, before the entrypoint function |
316 | * for the application or DLL is called |
317 | **************************************************************************************/ |
318 | int AACInitTrigtabsFloat(void) |
319 | { |
320 | /* cos4sin4tab */ |
321 | Init_cos4sin4tab(cos4sin4tab + cos4sin4tabOffset[0], 128); |
322 | Init_cos4sin4tab(cos4sin4tab + cos4sin4tabOffset[1], 1024); |
323 | |
324 | /* cos1sin1tab */ |
325 | Init_cos1sin1tab(cos1sin1tab); |
326 | |
327 | /* sinWindow */ |
328 | Init_sinWindow(sinWindow + sinWindowOffset[0], 128); |
329 | Init_sinWindow(sinWindow + sinWindowOffset[1], 1024); |
330 | |
331 | /* kbdWindow */ |
332 | Init_kbdWindow(kbdWindow + kbdWindowOffset[0], 128); |
333 | Init_kbdWindow(kbdWindow + kbdWindowOffset[1], 1024); |
334 | |
335 | /* twidTabEven, twidTabOdd */ |
336 | Init_twidTabs(twidTabEven, twidTabOdd, 512); |
337 | |
338 | return 0; |
339 | } |
340 | |
341 | /************************************************************************************** |
342 | * Function: AACFreeTrigtabsFloat |
343 | * |
344 | * Description: free any memory allocated by AACInitTrigtabsFloat() |
345 | * |
346 | * Inputs: none |
347 | * |
348 | * Outputs: none |
349 | * |
350 | * Return: none |
351 | **************************************************************************************/ |
352 | void AACFreeTrigtabsFloat(void) |
353 | { |
354 | return; |
355 | } |
356 | |
357 | #endif /* HELIX_CONFIG_AAC_GENERATE_TRIGTABS_FLOAT */ |
358 |