/* ***** BEGIN LICENSE BLOCK ***** * Version: RCSL 1.0/RPSL 1.0 * * Portions Copyright (c) 1995-2002 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 * Version 1.0 (the "RPSL") available at * http://www.helixcommunity.org/content/rpsl unless you have licensed * the file under the RealNetworks Community Source License Version 1.0 * (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 MP3 decoder * Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com) * June 2003 * * trigtabs.c - global ROM tables for pre-calculated trig coefficients **************************************************************************************/ // constants in RAM are not significantly faster #include "coder.h" #include /* post-IMDCT window, win[blockType][i] * format = Q31 * Fused sin window with final stage of IMDCT * includes 1/sqrt(2) scaling, since we scale by sqrt(2) in dequant in order * for fast IMDCT36 to be usable * * for(i=0;i<9;i++) win[0][i] = sin(pi/36 *(i+0.5)); * for(i=9;i<36;i++) win[0][i] = -sin(pi/36 *(i+0.5)); * * for(i=0;i<9;i++) win[1][i] = sin(pi/36 *(i+0.5)); * for(i=9;i<18;i++) win[1][i] = -sin(pi/36 *(i+0.5)); * for(i=18;i<24;i++) win[1][i] = -1; * for(i=24;i<30;i++) win[1][i] = -sin(pi/12 *(i+0.5-18)); * for(i=30;i<36;i++) win[1][i] = 0; * * for(i=0;i<6;i++) win[3][i] = 0; * for(i=6;i<9;i++) win[3][i] = sin(pi/12 *(i+0.5-6)); * for(i=9;i<12;i++) win[3][i] = -sin(pi/12 *(i+0.5-6)); * for(i=12;i<18;i++) win[3][i] = -1; * for(i=18;i<36;i++) win[3][i] = -sin(pi/36*(i+0.5)); * * for(i=0;i<3;i++) win[2][i] = sin(pi/12*(i+0.5)); * for(i=3;i<12;i++) win[2][i] = -sin(pi/12*(i+0.5)); * for(i=12;i<36;i++) win[2][i] = 0; * * for (i = 0; i < 4; i++) { * if (i == 2) { * win[i][8] *= cos(pi/12 * (0+0.5)); * win[i][9] *= cos(pi/12 * (0+0.5)); * win[i][7] *= cos(pi/12 * (1+0.5)); * win[i][10] *= cos(pi/12 * (1+0.5)); * win[i][6] *= cos(pi/12 * (2+0.5)); * win[i][11] *= cos(pi/12 * (2+0.5)); * win[i][0] *= cos(pi/12 * (3+0.5)); * win[i][5] *= cos(pi/12 * (3+0.5)); * win[i][1] *= cos(pi/12 * (4+0.5)); * win[i][4] *= cos(pi/12 * (4+0.5)); * win[i][2] *= cos(pi/12 * (5+0.5)); * win[i][3] *= cos(pi/12 * (5+0.5)); * } else { * for (j = 0; j < 9; j++) { * win[i][8-j] *= cos(pi/36 * (17-j+0.5)); * win[i][9+j] *= cos(pi/36 * (17-j+0.5)); * } * for (j = 0; j < 9; j++) { * win[i][18+8-j] *= cos(pi/36 * (j+0.5)); * win[i][18+9+j] *= cos(pi/36 * (j+0.5)); * } * } * } * for (i = 0; i < 4; i++) * for (j = 0; j < 36; j++) * win[i][j] *= 1.0 / sqrt(2); */ const int imdctWin[4][36] = { { (int32_t)0x02aace8b, (int32_t)0x07311c28, (int32_t)0x0a868fec, (int32_t)0x0c913b52, (int32_t)0x0d413ccd, (int32_t)0x0c913b52, (int32_t)0x0a868fec, (int32_t)0x07311c28, (int32_t)0x02aace8b, (int32_t)0xfd16d8dd, (int32_t)0xf6a09e66, (int32_t)0xef7a6275, (int32_t)0xe7dbc161, (int32_t)0xe0000000, (int32_t)0xd8243e9f, (int32_t)0xd0859d8b, (int32_t)0xc95f619a, (int32_t)0xc2e92723, (int32_t)0xbd553175, (int32_t)0xb8cee3d8, (int32_t)0xb5797014, (int32_t)0xb36ec4ae, (int32_t)0xb2bec333, (int32_t)0xb36ec4ae, (int32_t)0xb5797014, (int32_t)0xb8cee3d8, (int32_t)0xbd553175, (int32_t)0xc2e92723, (int32_t)0xc95f619a, (int32_t)0xd0859d8b, (int32_t)0xd8243e9f, (int32_t)0xe0000000, (int32_t)0xe7dbc161, (int32_t)0xef7a6275, (int32_t)0xf6a09e66, (int32_t)0xfd16d8dd, }, { (int32_t)0x02aace8b, (int32_t)0x07311c28, (int32_t)0x0a868fec, (int32_t)0x0c913b52, (int32_t)0x0d413ccd, (int32_t)0x0c913b52, (int32_t)0x0a868fec, (int32_t)0x07311c28, (int32_t)0x02aace8b, (int32_t)0xfd16d8dd, (int32_t)0xf6a09e66, (int32_t)0xef7a6275, (int32_t)0xe7dbc161, (int32_t)0xe0000000, (int32_t)0xd8243e9f, (int32_t)0xd0859d8b, (int32_t)0xc95f619a, (int32_t)0xc2e92723, (int32_t)0xbd44ef14, (int32_t)0xb831a052, (int32_t)0xb3aa3837, (int32_t)0xafb789a4, (int32_t)0xac6145bb, (int32_t)0xa9adecdc, (int32_t)0xa864491f, (int32_t)0xad1868f0, (int32_t)0xb8431f49, (int32_t)0xc8f42236, (int32_t)0xdda8e6b1, (int32_t)0xf47755dc, (int32_t)0x00000000, (int32_t)0x00000000, (int32_t)0x00000000, (int32_t)0x00000000, (int32_t)0x00000000, (int32_t)0x00000000, }, { (int32_t)0x07311c28, (int32_t)0x0d413ccd, (int32_t)0x07311c28, (int32_t)0xf6a09e66, (int32_t)0xe0000000, (int32_t)0xc95f619a, (int32_t)0xb8cee3d8, (int32_t)0xb2bec333, (int32_t)0xb8cee3d8, (int32_t)0xc95f619a, (int32_t)0xe0000000, (int32_t)0xf6a09e66, (int32_t)0x00000000, (int32_t)0x00000000, (int32_t)0x00000000, (int32_t)0x00000000, (int32_t)0x00000000, (int32_t)0x00000000, (int32_t)0x00000000, (int32_t)0x00000000, (int32_t)0x00000000, (int32_t)0x00000000, (int32_t)0x00000000, (int32_t)0x00000000, (int32_t)0x00000000, (int32_t)0x00000000, (int32_t)0x00000000, (int32_t)0x00000000, (int32_t)0x00000000, (int32_t)0x00000000, (int32_t)0x00000000, (int32_t)0x00000000, (int32_t)0x00000000, (int32_t)0x00000000, (int32_t)0x00000000, (int32_t)0x00000000, }, { (int32_t)0x00000000, (int32_t)0x00000000, (int32_t)0x00000000, (int32_t)0x00000000, (int32_t)0x00000000, (int32_t)0x00000000, (int32_t)0x028e9709, (int32_t)0x04855ec0, (int32_t)0x026743a1, (int32_t)0xfcde2c10, (int32_t)0xf515dc82, (int32_t)0xec93e53b, (int32_t)0xe4c880f8, (int32_t)0xdd5d0b08, (int32_t)0xd63510b7, (int32_t)0xcf5e834a, (int32_t)0xc8e6b562, (int32_t)0xc2da4105, (int32_t)0xbd553175, (int32_t)0xb8cee3d8, (int32_t)0xb5797014, (int32_t)0xb36ec4ae, (int32_t)0xb2bec333, (int32_t)0xb36ec4ae, (int32_t)0xb5797014, (int32_t)0xb8cee3d8, (int32_t)0xbd553175, (int32_t)0xc2e92723, (int32_t)0xc95f619a, (int32_t)0xd0859d8b, (int32_t)0xd8243e9f, (int32_t)0xe0000000, (int32_t)0xe7dbc161, (int32_t)0xef7a6275, (int32_t)0xf6a09e66, (int32_t)0xfd16d8dd, }, }; /* indexing = [mid-side off/on][intensity scale factor] * format = Q30, range = [0.0, 1.414] * * mid-side off: * ISFMpeg1[0][i] = tan(i*pi/12) / [1 + tan(i*pi/12)] (left scalefactor) * = 1 / [1 + tan(i*pi/12)] (right scalefactor) * * mid-side on: * ISFMpeg1[1][i] = sqrt(2) * ISFMpeg1[0][i] * * output L = ISFMpeg1[midSide][isf][0] * input L * output R = ISFMpeg1[midSide][isf][1] * input L * * obviously left scalefactor + right scalefactor = 1 (m-s off) or sqrt(2) (m-s on) * so just store left and calculate right as 1 - left * (can derive as right = ISFMpeg1[x][6] - left) * * if mid-side enabled, multiply joint stereo scale factors by sqrt(2) * - we scaled whole spectrum by 1/sqrt(2) in Dequant for the M+S/sqrt(2) in MidSideProc * - but the joint stereo part of the spectrum doesn't need this, so we have to undo it * * if scale factor is and illegal intensity position, this becomes a passthrough * - gain = [1, 0] if mid-side off, since L is coded directly and R = 0 in this region * - gain = [1, 1] if mid-side on, since L = (M+S)/sqrt(2), R = (M-S)/sqrt(2) * - and since S = 0 in the joint stereo region (above NZB right) then L = R = M * 1.0 */ const int ISFMpeg1[2][7] = { {(int32_t)0x00000000, (int32_t)0x0d8658ba, (int32_t)0x176cf5d0, (int32_t)0x20000000, (int32_t)0x28930a2f, (int32_t)0x3279a745, (int32_t)0x40000000}, {(int32_t)0x00000000, (int32_t)0x13207f5c, (int32_t)0x2120fb83, (int32_t)0x2d413ccc, (int32_t)0x39617e16, (int32_t)0x4761fa3d, (int32_t)0x5a827999} }; /* indexing = [intensity scale on/off][mid-side off/on][intensity scale factor] * format = Q30, range = [0.0, 1.414] * * if (isf == 0) kl = 1.0 kr = 1.0 * else if (isf & (int32_t)0x01 == (int32_t)0x01) kl = i0^((isf+1)/2), kr = 1.0 * else if (isf & (int32_t)0x01 == (int32_t)0x00) kl = 1.0, kr = i0^(isf/2) * * if (intensityScale == 1) i0 = 1/sqrt(2) = (int32_t)0x2d413ccc (Q30) * else i0 = 1/sqrt(sqrt(2)) = (int32_t)0x35d13f32 (Q30) * * see comments for ISFMpeg1 (just above) regarding scaling, sqrt(2), etc. * * compress the MPEG2 table using the obvious identities above... * for isf = [0, 1, 2, ... 30], let sf = table[(isf+1) >> 1] * - if isf odd, L = sf*L, R = tab[0]*R * - if isf even, L = tab[0]*L, R = sf*R */ const int ISFMpeg2[2][2][16] = { { { /* intensityScale off, mid-side off */ (int32_t)0x40000000, (int32_t)0x35d13f32, (int32_t)0x2d413ccc, (int32_t)0x260dfc14, (int32_t)0x1fffffff, (int32_t)0x1ae89f99, (int32_t)0x16a09e66, (int32_t)0x1306fe0a, (int32_t)0x0fffffff, (int32_t)0x0d744fcc, (int32_t)0x0b504f33, (int32_t)0x09837f05, (int32_t)0x07ffffff, (int32_t)0x06ba27e6, (int32_t)0x05a82799, (int32_t)0x04c1bf82, }, { /* intensityScale off, mid-side on */ (int32_t)0x5a827999, (int32_t)0x4c1bf827, (int32_t)0x3fffffff, (int32_t)0x35d13f32, (int32_t)0x2d413ccc, (int32_t)0x260dfc13, (int32_t)0x1fffffff, (int32_t)0x1ae89f99, (int32_t)0x16a09e66, (int32_t)0x1306fe09, (int32_t)0x0fffffff, (int32_t)0x0d744fcc, (int32_t)0x0b504f33, (int32_t)0x09837f04, (int32_t)0x07ffffff, (int32_t)0x06ba27e6, }, }, { { /* intensityScale on, mid-side off */ (int32_t)0x40000000, (int32_t)0x2d413ccc, (int32_t)0x20000000, (int32_t)0x16a09e66, (int32_t)0x10000000, (int32_t)0x0b504f33, (int32_t)0x08000000, (int32_t)0x05a82799, (int32_t)0x04000000, (int32_t)0x02d413cc, (int32_t)0x02000000, (int32_t)0x016a09e6, (int32_t)0x01000000, (int32_t)0x00b504f3, (int32_t)0x00800000, (int32_t)0x005a8279, }, /* intensityScale on, mid-side on */ { (int32_t)0x5a827999, (int32_t)0x3fffffff, (int32_t)0x2d413ccc, (int32_t)0x1fffffff, (int32_t)0x16a09e66, (int32_t)0x0fffffff, (int32_t)0x0b504f33, (int32_t)0x07ffffff, (int32_t)0x05a82799, (int32_t)0x03ffffff, (int32_t)0x02d413cc, (int32_t)0x01ffffff, (int32_t)0x016a09e6, (int32_t)0x00ffffff, (int32_t)0x00b504f3, (int32_t)0x007fffff, } } }; /* indexing = [intensity scale on/off][left/right] * format = Q30, range = [0.0, 1.414] * * illegal intensity position scalefactors (see comments on ISFMpeg1) */ const int ISFIIP[2][2] = { {(int32_t)0x40000000, (int32_t)0x00000000}, /* mid-side off */ {(int32_t)0x40000000, (int32_t)0x40000000}, /* mid-side on */ }; const unsigned char uniqueIDTab[8] = {(int32_t)0x5f, (int32_t)0x4b, (int32_t)0x43, (int32_t)0x5f, (int32_t)0x5f, (int32_t)0x4a, (int32_t)0x52, (int32_t)0x5f}; /* anti-alias coefficients - see spec Annex B, table 3-B.9 * csa[0][i] = CSi, csa[1][i] = CAi * format = Q31 */ const int csa[8][2] = { {(int32_t)0x6dc253f0, (int32_t)0xbe2500aa}, {(int32_t)0x70dcebe4, (int32_t)0xc39e4949}, {(int32_t)0x798d6e73, (int32_t)0xd7e33f4a}, {(int32_t)0x7ddd40a7, (int32_t)0xe8b71176}, {(int32_t)0x7f6d20b7, (int32_t)0xf3e4fe2f}, {(int32_t)0x7fe47e40, (int32_t)0xfac1a3c7}, {(int32_t)0x7ffcb263, (int32_t)0xfe2ebdc6}, {(int32_t)0x7fffc694, (int32_t)0xff86c25d}, }; /* format = Q30, range = [0.0981, 1.9976] * * n = 16; * k = 0; * for(i=0; i<5; i++, n=n/2) { * for(p=0; p