/*
* Layer3.java -- 解码Layer3(MPEG 2.0/2.5 Audio Layer III)
* Copyright (C) 2010
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* If you would like to negotiate alternate licensing terms, you may do
* so by contacting the author: <http://jmp123.sourceforge.net/>
*/
package jmp123.decoder;
public final class Layer3 implements ILayer123 {
private static Header objHeader;
private static Synthesis objFilter;
private static BitStream objInBitStream;
private static int intWhichChannel;
private static int intMaxGr;
private static int intChannels;
private static int intFirstChannel;
private static int intLastChannel;
private static int[] intSfbIdxLong;
private static int[] intSfbIdxShort;
private static boolean boolIntensityStereo; //强度立体声:true
public Layer3(BitStream bs,Header h, Synthesis filter, int wch) {
objInBitStream = bs;
objHeader = h;
intChannels = objHeader.getChannels();
intWhichChannel = wch;
intMaxGr = (objHeader.getVersion() == Header.MPEG1) ? 2 : 1;
objFilter = filter;
objSI = new SideInfo();
objHuffBits = new HuffmanBits(objInBitStream);
objSideBS = new BitStream(36);
scfL = new int[2][23];
scfS = new int[2][3][13];
is = new int[32 * 18 + 4];
xr = new float[2][32][18];
intWidthLong = new int[22];
intWidthShort = new int[13];
floatRawOut = new float[36];
floatPrevBlck = new float[2][32][18];
cs = new float[] { 0.857492925712f, 0.881741997318f, 0.949628649103f,
0.983314592492f, 0.995517816065f, 0.999160558175f,
0.999899195243f, 0.999993155067f };
ca = new float[] { -0.5144957554270f, -0.4717319685650f,
-0.3133774542040f, -0.1819131996110f, -0.0945741925262f,
-0.0409655828852f, -0.0141985685725f, -0.00369997467375f };
int i;
/*
* floatPowIS[]:用于查表求 v^(4/3),v是经哈夫曼解码出的一个(正)值,该值的范围是0..8191
*/
floatPowIS = new float[8207];
for (i = 0; i < 8207; i++)
floatPowIS[i] = (float) Math.pow(i, 4.0 / 3.0);
/*
* pow_2[] -- 用于查表求 2 ^ exp, exp 是长块(long block)逆量化的指数
*/
floatPow2 = new float[256 + 118 + 4];
for (i = -256; i < 118 + 4; i++)
floatPow2[i + 256] = (float) Math.pow(2.0, -0.25 * (i + 210));
if (intChannels == 2)
switch (intWhichChannel) {
case Decoder.CH_LEFT:
intFirstChannel = intLastChannel = 0;
break;
case Decoder.CH_RIGHT:
intFirstChannel = intLastChannel = 1;
break;
case Decoder.CH_BOTH:
default:
intFirstChannel = 0;
intLastChannel = 1;
break;
}
else
intFirstChannel = intLastChannel = 0;
//---------------------------------------------------------------------
//待解码文件的不同特征用到不同的变量.初始化:
//---------------------------------------------------------------------
int intSfreq = objHeader.getSampleFrequency();
intSfreq += (objHeader.getVersion() == Header.MPEG1) ? 0 : ((objHeader.getVersion() == Header.MPEG2) ? 3 : 6);
/*
* ANNEX B,Table 3-B.8. Layer III scalefactor bands
*/
switch (intSfreq) {
case 0:
/* MPEG 1, sampling_frequency=0, 44.1kHz */
intSfbIdxLong = new int[] { 0, 4, 8, 12, 16, 20, 24, 30, 36, 44,
52, 62, 74, 90, 110, 134, 162, 196, 238, 288, 342, 418, 576 };
intSfbIdxShort = new int[] { 0, 4, 8, 12, 16, 22, 30, 40, 52, 66,
84, 106, 136, 192 };
break;
case 1:
/* MPEG 1, sampling_frequency=1, 48kHz */
intSfbIdxLong = new int[] { 0, 4, 8, 12, 16, 20, 24, 30, 36, 42,
50, 60, 72, 88, 106, 128, 156, 190, 230, 276, 330, 384, 576 };
intSfbIdxShort = new int[] { 0, 4, 8, 12, 16, 22, 28, 38, 50, 64,
80, 100, 126, 192 };
break;
case 2:
/* MPEG 1, sampling_frequency=2, 32kHz */
intSfbIdxLong = new int[] { 0, 4, 8, 12, 16, 20, 24, 30, 36, 44,
54, 66, 82, 102, 126, 156, 194, 240, 296, 364, 448, 550,
576 };
intSfbIdxShort = new int[] { 0, 4, 8, 12, 16, 22, 30, 42, 58, 78,
104, 138, 180, 192 };
break;
case 3:
/* MPEG 2, sampling_frequency=0, 22.05kHz */
intSfbIdxLong = new int[] { 0, 6, 12, 18, 24, 30, 36, 44, 54, 66,
80, 96, 116, 140, 168, 200, 238, 284, 336, 396, 464, 522,
576 };
intSfbIdxShort = new int[] { 0, 4, 8, 12, 18, 24, 32, 42, 56, 74,
100, 132, 174, 192 };
break;
case 4:
/* MPEG 2, sampling_frequency=1, 24kHz */
intSfbIdxLong = new int[] { 0, 6, 12, 18, 24, 30, 36, 44, 54, 66,
80, 96, 114, 136, 162, 194, 232, 278, 330, 394, 464, 540,
576 };
intSfbIdxShort = new int[] { 0, 4, 8, 12, 18, 26, 36, 48, 62, 80,
104, 136, 180, 192 };
break;
case 5:
/* MPEG 2, sampling_frequency=2, 16kHz */
intSfbIdxLong = new int[] { 0, 6, 12, 18, 24, 30, 36, 44, 54, 66,
80, 96, 116, 140, 168, 200, 238, 284, 336, 396, 464, 522,
576 };
intSfbIdxShort = new int[] { 0, 4, 8, 12, 18, 26, 36, 48, 62, 80,
104, 134, 174, 192 };
break;
case 6:
/* MPEG 2.5, sampling_frequency=0, 11.025kHz */
intSfbIdxLong = new int[] { 0, 6, 12, 18, 24, 30, 36, 44, 54, 66,
80, 96, 116, 140, 168, 200, 238, 284, 336, 396, 464, 522,
576 };
intSfbIdxShort = new int[] { 0, 4, 8, 12, 18, 26, 36, 48, 62, 80,
104, 134, 174, 192 };
break;
case 7:
/* MPEG 2.5, sampling_frequency=1, 12kHz */
intSfbIdxLong = new int[] { 0, 6, 12, 18, 24, 30, 36, 44, 54, 66,
80, 96, 116, 140, 168, 200, 238, 284, 336, 396, 464, 522,
576 };
intSfbIdxShort = new int[] { 0, 4, 8, 12, 18, 26, 36, 48, 62, 80,
104, 134, 174, 192 };
break;
case 8:
/* MPEG 2.5, sampling_frequency=2, 8kHz */
intSfbIdxLong = new int[] { 0, 12, 24, 36, 48, 60, 72, 88, 108,
132, 160, 192, 232, 280, 336, 400, 476, 566, 568, 570, 572,
574, 576 };
intSfbIdxShort = new int[] { 0, 8, 16, 24, 36, 52, 72, 96, 124,
160, 162, 164, 166, 192 };
break;
}
for (i = 0; i < 22; i++)
intWidthLong[i] = intSfbIdxLong[i + 1] - intSfbIdxLong[i];
for (i = 0; i < 13; i++)
intWidthShort[i] = intSfbIdxShort[i + 1] - intSfbIdxShort[i];
//---------------------------------------------------------------------
//强度立体声:
boolIntensityStereo = objHeader.isIStereo();
if(boolIntensityStereo) {
if (objHeader.getVersion() == Header.MPEG1) //MPEG 1.0
is_coef = new float[] { 0.0f, 0.211324865f, 0.366025404f, 0.5f,
0.633974596f, 0.788675135f, 1.0f };
else //MPEG 2.0/2.5
lsf_is_coef = new float[][] {
{ 0.840896415f, 0.707106781f, 0.594603558f, 0.5f,
0.420448208f, 0.353553391f, 0.297301779f,
0.25f, 0.210224104f, 0.176776695f,
0.148650889f, 0.125f, 0.105112052f,
0.088388348f, 0.074325445f },
{ 0.707106781f, 0.5f, 0.353553391f, 0.25f,
0.176776695f, 0.125f, 0.088388348f, 0.0625f,
0.044194174f, 0.03125f, 0.022097087f,
0.015625f, 0.011048543f, 0.0078125f,
0.005524272f } };
}
//-----------------------------------------------------------------
//MPEG 2.0/2.5
if (objHeader.getVersion() != Header.MPEG1) {
i_slen2 = new int[256]; // MPEG 2.0 slen for intensity stereo
n_slen2 = new int[512]; // MPEG 2.0 slen for 'normal' mode
slen_tab2 = new byte[][][] {
{ { 6, 5, 5, 5 }, { 6, 5, 7, 3 }, { 11, 10, 0, 0 },
{ 7, 7, 7, 0 }, { 6, 6, 6, 3 }, { 8, 8, 5, 0 } },
{ { 9, 9, 9, 9 }, { 9, 9, 12, 6 },