/* ***** BEGIN LICENSE BLOCK ***** * Source last modified: $Id: trigtabs_fltgen.c,v 1.2 2006/12/05 03:36:53 ehyche Exp $ * * Portions Copyright (c) 1995-2005 RealNetworks, Inc. All Rights Reserved. * * The contents of this file, and the files included with this file, * are subject to the current version of the RealNetworks Public * Source License (the "RPSL") available at * http://www.helixcommunity.org/content/rpsl unless you have licensed * the file under the current version of the RealNetworks Community * Source License (the "RCSL") available at * http://www.helixcommunity.org/content/rcsl, in which case the RCSL * will apply. You may also obtain the license terms directly from * RealNetworks. You may not use this file except in compliance with * the RPSL or, if you have a valid RCSL with RealNetworks applicable * to this file, the RCSL. Please see the applicable RPSL or RCSL for * the rights, obligations and limitations governing use of the * contents of the file. * * This file is part of the Helix DNA Technology. RealNetworks is the * developer of the Original Code and owns the copyrights in the * portions it created. * * This file, and the files included with this file, is distributed * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET * ENJOYMENT OR NON-INFRINGEMENT. * * Technology Compatibility Kit Test Suite(s) Location: * http://www.helixcommunity.org/content/tck * * Contributor(s): * * ***** END LICENSE BLOCK ***** */ /************************************************************************************** * Fixed-point HE-AAC decoder * Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com) * June 2005 * * trigtabs_fltgen.c - low-ROM alternative to trigtabs.c * generates large trig tables at runtime using floating-point * math library * MUST VERIFY that runtime-generated tables are bit-exact matches * with ROM tables in trigtabs.c **************************************************************************************/ #ifdef HELIX_CONFIG_AAC_GENERATE_TRIGTABS_FLOAT #include #include "coder.h" /* read-only tables */ const int cos4sin4tabOffset[NUM_IMDCT_SIZES] = {0, 128}; const int sinWindowOffset[NUM_IMDCT_SIZES] = {0, 128}; const int kbdWindowOffset[NUM_IMDCT_SIZES] = {0, 128}; const int bitrevtabOffset[NUM_IMDCT_SIZES] = {0, 17}; const unsigned char bitrevtab[17 + 129] = { /* nfft = 64 */ 0x01, 0x08, 0x02, 0x04, 0x03, 0x0c, 0x05, 0x0a, 0x07, 0x0e, 0x0b, 0x0d, 0x00, 0x06, 0x09, 0x0f, 0x00, /* nfft = 512 */ 0x01, 0x40, 0x02, 0x20, 0x03, 0x60, 0x04, 0x10, 0x05, 0x50, 0x06, 0x30, 0x07, 0x70, 0x09, 0x48, 0x0a, 0x28, 0x0b, 0x68, 0x0c, 0x18, 0x0d, 0x58, 0x0e, 0x38, 0x0f, 0x78, 0x11, 0x44, 0x12, 0x24, 0x13, 0x64, 0x15, 0x54, 0x16, 0x34, 0x17, 0x74, 0x19, 0x4c, 0x1a, 0x2c, 0x1b, 0x6c, 0x1d, 0x5c, 0x1e, 0x3c, 0x1f, 0x7c, 0x21, 0x42, 0x23, 0x62, 0x25, 0x52, 0x26, 0x32, 0x27, 0x72, 0x29, 0x4a, 0x2b, 0x6a, 0x2d, 0x5a, 0x2e, 0x3a, 0x2f, 0x7a, 0x31, 0x46, 0x33, 0x66, 0x35, 0x56, 0x37, 0x76, 0x39, 0x4e, 0x3b, 0x6e, 0x3d, 0x5e, 0x3f, 0x7e, 0x43, 0x61, 0x45, 0x51, 0x47, 0x71, 0x4b, 0x69, 0x4d, 0x59, 0x4f, 0x79, 0x53, 0x65, 0x57, 0x75, 0x5b, 0x6d, 0x5f, 0x7d, 0x67, 0x73, 0x6f, 0x7b, 0x00, 0x08, 0x14, 0x1c, 0x22, 0x2a, 0x36, 0x3e, 0x41, 0x49, 0x55, 0x5d, 0x63, 0x6b, 0x77, 0x7f, 0x00, }; /* tables generated at runtime */ int cos4sin4tab[128 + 1024]; int cos1sin1tab[514]; int sinWindow[128 + 1024]; int kbdWindow[128 + 1024]; int twidTabEven[4 * 6 + 16 * 6 + 64 * 6]; int twidTabOdd[8 * 6 + 32 * 6 + 128 * 6]; #define M_PI 3.14159265358979323846 #define M2_30 1073741824.0 #define M2_31 2147483648.0 #define MAX_DBL 2147483647.0 #define MIN_DBL -2147483648.0 static int NormAndRound(double x, double q, double n) { if (x >= 0.0) { x = (x * q * n + 0.5); } else { x = (x * q * n - 0.5); } /* clip */ if (x > MAX_DBL) { x = MAX_DBL; } if (x < MIN_DBL) { x = MIN_DBL; } return (int)x; } static void Init_cos4sin4tab(int *tPtr, int nmdct) { int i; double angle1, angle2, invM, x1, x2, x3, x4; invM = -1.0 / (double)nmdct; for (i = 0; i < nmdct / 4; i++) { angle1 = (i + 0.25) * M_PI / nmdct; angle2 = (nmdct / 2 - 1 - i + 0.25) * M_PI / nmdct; x1 = invM * (cos(angle1) + sin(angle1)); x2 = invM * sin(angle1); x3 = invM * (cos(angle2) + sin(angle2)); x4 = invM * sin(angle2); tPtr[0] = NormAndRound(x1, M2_30, nmdct); tPtr[1] = NormAndRound(x2, M2_30, nmdct); tPtr[2] = NormAndRound(x3, M2_30, nmdct); tPtr[3] = NormAndRound(x4, M2_30, nmdct); tPtr += 4; } } static void Init_cos1sin1tab(int *tPtr) { int i; double angle, x1, x2; for (i = 0; i <= (512 / 2); i++) { angle = i * M_PI / 1024; x1 = (cos(angle) + sin(angle)); x2 = sin(angle); tPtr[0] = NormAndRound(x1, M2_30, 1); tPtr[1] = NormAndRound(x2, M2_30, 1); tPtr += 2; } } static void Init_sinWindow(int *tPtr, int nmdct) { int i; double angle1, angle2, x1, x2; for (i = 0; i < nmdct / 2; i++) { angle1 = (i + 0.5) * M_PI / (2.0 * nmdct); angle2 = (nmdct - 1 - i + 0.5) * M_PI / (2.0 * nmdct); x1 = sin(angle1); x2 = sin(angle2); tPtr[0] = NormAndRound(x1, M2_31, 1); tPtr[1] = NormAndRound(x2, M2_31, 1); tPtr += 2; } } #define KBD_THRESH 1e-12 static double CalcI0(double x) { int k; double i0, iTmp, iLast, x2, xPow, kFact; x2 = x / 2.0; i0 = 0.0; k = 0; kFact = 1; xPow = 1; do { iLast = i0; iTmp = xPow / kFact; i0 += (iTmp * iTmp); k++; kFact *= k; xPow *= x2; } while (fabs(i0 - iLast) > KBD_THRESH); return i0; } static double CalcW(double nRef, double n, double a) { double i0Base, i0Curr, nTemp; i0Base = CalcI0(M_PI * a); nTemp = (n - nRef / 4) / (nRef / 4); i0Curr = CalcI0(M_PI * a * sqrt(1.0 - nTemp * nTemp)); return i0Curr / i0Base; } static void Init_kbdWindow(int *tPtr, int nmdct) { int n, nRef; double a, wBase, wCurr, x1; nRef = nmdct * 2; /* kbd window */ if (nmdct == 128) { a = 6.0; } else { a = 4.0; } wBase = 0; for (n = 0; n <= nRef / 2; n++) { wBase += CalcW(nRef, n, a); } /* left */ wCurr = 0; for (n = 0; n < nmdct / 2; n++) { wCurr += CalcW(nRef, n, a); x1 = sqrt(wCurr / wBase); tPtr[0] = NormAndRound(x1, M2_31, 1); tPtr += 2; } tPtr--; /* right */ for (n = nmdct / 2; n < nmdct; n++) { wCurr += CalcW(nRef, n, a); x1 = sqrt(wCurr / wBase); tPtr[0] = NormAndRound(x1, M2_31, 1); tPtr -= 2; } /* symmetry: * kbd_right(n) = kbd_ldef(N_REF - 1 - n), n = [N_REF/2, N_REF - 1] * * wCurr = 0; * for (n = N_REF-1; n >= N_REF/2; n--) { * wCurr += CalcW(N_REF-n-1, a); * kbdWindowRef[n] = sqrt(wCurr / wBase); * } * */ return; } static void Init_twidTabs(int *tPtrEven, int *tPtrOdd, int nfft) { int j, k; double wr1, wi1, wr2, wi2, wr3, wi3; for (k = 4; k <= nfft / 4; k <<= 1) { for (j = 0; j < k; j++) { wr1 = cos(1.0 * M_PI * j / (2 * k)); wi1 = sin(1.0 * M_PI * j / (2 * k)); wr1 = (wr1 + wi1); wi1 = -wi1; wr2 = cos(2.0 * M_PI * j / (2 * k)); wi2 = sin(2.0 * M_PI * j / (2 * k)); wr2 = (wr2 + wi2); wi2 = -wi2; wr3 = cos(3.0 * M_PI * j / (2 * k)); wi3 = sin(3.0 * M_PI * j / (2 * k)); wr3 = (wr3 + wi3); wi3 = -wi3; if (k & 0xaaaaaaaa) { tPtrOdd[0] = NormAndRound(wr2, M2_30, 1); tPtrOdd[1] = NormAndRound(wi2, M2_30, 1); tPtrOdd[2] = NormAndRound(wr1, M2_30, 1); tPtrOdd[3] = NormAndRound(wi1, M2_30, 1); tPtrOdd[4] = NormAndRound(wr3, M2_30, 1); tPtrOdd[5] = NormAndRound(wi3, M2_30, 1); tPtrOdd += 6; } else { tPtrEven[0] = NormAndRound(wr2, M2_30, 1); tPtrEven[1] = NormAndRound(wi2, M2_30, 1); tPtrEven[2] = NormAndRound(wr1, M2_30, 1); tPtrEven[3] = NormAndRound(wi1, M2_30, 1); tPtrEven[4] = NormAndRound(wr3, M2_30, 1); tPtrEven[5] = NormAndRound(wi3, M2_30, 1); tPtrEven += 6; } } } } /************************************************************************************** * Function: AACInitTrigtabsFloat * * Description: generate AAC decoder tables using floating-point math library * * Inputs: none * * Outputs: initialized tables * * Return: 0 on success * * Notes: this function should ONLY be called when double-precision * floating-point math is supported * the generated tables must be bit-exact matches with read-only * tables stored in trigtabs.c * this initializes global tables in RAM, and is NOT thread-safe, * so the caller must ensure that this function is not called * from multiple threads * this should be called exactly once, before the entrypoint function * for the application or DLL is called **************************************************************************************/ int AACInitTrigtabsFloat(void) { /* cos4sin4tab */ Init_cos4sin4tab(cos4sin4tab + cos4sin4tabOffset[0], 128); Init_cos4sin4tab(cos4sin4tab + cos4sin4tabOffset[1], 1024); /* cos1sin1tab */ Init_cos1sin1tab(cos1sin1tab); /* sinWindow */ Init_sinWindow(sinWindow + sinWindowOffset[0], 128); Init_sinWindow(sinWindow + sinWindowOffset[1], 1024); /* kbdWindow */ Init_kbdWindow(kbdWindow + kbdWindowOffset[0], 128); Init_kbdWindow(kbdWindow + kbdWindowOffset[1], 1024); /* twidTabEven, twidTabOdd */ Init_twidTabs(twidTabEven, twidTabOdd, 512); return 0; } /************************************************************************************** * Function: AACFreeTrigtabsFloat * * Description: free any memory allocated by AACInitTrigtabsFloat() * * Inputs: none * * Outputs: none * * Return: none **************************************************************************************/ void AACFreeTrigtabsFloat(void) { return; } #endif /* HELIX_CONFIG_AAC_GENERATE_TRIGTABS_FLOAT */