www in docker support
This commit is contained in:
parent
539a848e95
commit
c227fce036
2145 changed files with 399596 additions and 58 deletions
|
|
@ -0,0 +1,39 @@
|
|||
package org.jcodec.codecs.mpa;
|
||||
|
||||
class ChannelSynthesizer {
|
||||
private float[][] v;
|
||||
|
||||
private int pos;
|
||||
|
||||
private float scalefactor;
|
||||
|
||||
private int current;
|
||||
|
||||
public ChannelSynthesizer(int channelnumber, float factor) {
|
||||
this.v = new float[2][512];
|
||||
this.scalefactor = factor;
|
||||
this.pos = 15;
|
||||
}
|
||||
|
||||
private static void distributeSamples(int pos, float[] dest, float[] next, float[] s) {
|
||||
for (int m = 0; m < 16; m++)
|
||||
dest[(m << 4) + pos] = s[m];
|
||||
for (int k = 1; k < 17; k++)
|
||||
next[(k << 4) + pos] = s[15 + k];
|
||||
dest[256 + pos] = 0.0F;
|
||||
next[0 + pos] = -s[0];
|
||||
for (int j = 0; j < 15; j++)
|
||||
dest[272 + (j << 4) + pos] = -s[15 - j];
|
||||
for (int i = 0; i < 15; i++)
|
||||
next[272 + (i << 4) + pos] = s[30 - i];
|
||||
}
|
||||
|
||||
public void synthesize(float[] coeffs, short[] out, int off) {
|
||||
MpaPqmf.computeButterfly(this.pos, coeffs);
|
||||
int next = (this.current ^ 0xFFFFFFFF) & 0x1;
|
||||
distributeSamples(this.pos, this.v[this.current], this.v[next], coeffs);
|
||||
MpaPqmf.computeFilter(this.pos, this.v[this.current], out, off, this.scalefactor);
|
||||
this.pos = this.pos + 1 & 0xF;
|
||||
this.current = next;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,400 @@
|
|||
package org.jcodec.codecs.mpa;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import org.jcodec.common.Vector2Int;
|
||||
import org.jcodec.common.Vector4Int;
|
||||
import org.jcodec.common.io.BitReader;
|
||||
import org.jcodec.common.tools.MathUtil;
|
||||
|
||||
public class Mp3Bitstream {
|
||||
static class MP3SideInfo {
|
||||
int mainDataBegin;
|
||||
|
||||
int privateBits;
|
||||
|
||||
boolean[][] scfsi = new boolean[2][4];
|
||||
|
||||
Mp3Bitstream.Granule[][] granule = new Mp3Bitstream.Granule[][] { new Mp3Bitstream.Granule[] { new Mp3Bitstream.Granule(), new Mp3Bitstream.Granule() }, new Mp3Bitstream.Granule[] { new Mp3Bitstream.Granule(), new Mp3Bitstream.Granule() } };
|
||||
}
|
||||
|
||||
static class Granule {
|
||||
int part23Length;
|
||||
|
||||
int bigValues;
|
||||
|
||||
int globalGain;
|
||||
|
||||
int scalefacCompress;
|
||||
|
||||
boolean windowSwitchingFlag;
|
||||
|
||||
int blockType;
|
||||
|
||||
boolean mixedBlockFlag;
|
||||
|
||||
int[] tableSelect = new int[3];
|
||||
|
||||
int[] subblockGain = new int[3];
|
||||
|
||||
int region0Count;
|
||||
|
||||
int region1Count;
|
||||
|
||||
boolean preflag;
|
||||
|
||||
int scalefacScale;
|
||||
|
||||
int count1tableSelect;
|
||||
}
|
||||
|
||||
static class ScaleFactors {
|
||||
int[] large = new int[23];
|
||||
|
||||
int[][] small = new int[3][13];
|
||||
}
|
||||
|
||||
static MP3SideInfo readSideInfo(MpaHeader header, ByteBuffer src, int channels) {
|
||||
MP3SideInfo si = new MP3SideInfo();
|
||||
BitReader stream = BitReader.createBitReader(src);
|
||||
if (header.version == 1) {
|
||||
si.mainDataBegin = stream.readNBit(9);
|
||||
if (channels == 1) {
|
||||
si.privateBits = stream.readNBit(5);
|
||||
} else {
|
||||
si.privateBits = stream.readNBit(3);
|
||||
}
|
||||
for (int ch = 0; ch < channels; ch++) {
|
||||
si.scfsi[ch][0] = (stream.read1Bit() == 0);
|
||||
si.scfsi[ch][1] = (stream.read1Bit() == 0);
|
||||
si.scfsi[ch][2] = (stream.read1Bit() == 0);
|
||||
si.scfsi[ch][3] = (stream.read1Bit() == 0);
|
||||
}
|
||||
for (int gr = 0; gr < 2; gr++) {
|
||||
for (int i = 0; i < channels; i++) {
|
||||
Granule granule = si.granule[i][gr];
|
||||
granule.part23Length = stream.readNBit(12);
|
||||
granule.bigValues = stream.readNBit(9);
|
||||
granule.globalGain = stream.readNBit(8);
|
||||
granule.scalefacCompress = stream.readNBit(4);
|
||||
granule.windowSwitchingFlag = (stream.readNBit(1) != 0);
|
||||
if (granule.windowSwitchingFlag) {
|
||||
granule.blockType = stream.readNBit(2);
|
||||
granule.mixedBlockFlag = (stream.readNBit(1) != 0);
|
||||
granule.tableSelect[0] = stream.readNBit(5);
|
||||
granule.tableSelect[1] = stream.readNBit(5);
|
||||
granule.subblockGain[0] = stream.readNBit(3);
|
||||
granule.subblockGain[1] = stream.readNBit(3);
|
||||
granule.subblockGain[2] = stream.readNBit(3);
|
||||
if (granule.blockType == 0)
|
||||
return null;
|
||||
if (granule.blockType == 2 && !granule.mixedBlockFlag) {
|
||||
granule.region0Count = 8;
|
||||
} else {
|
||||
granule.region0Count = 7;
|
||||
}
|
||||
granule.region1Count = 20 - granule.region0Count;
|
||||
} else {
|
||||
granule.tableSelect[0] = stream.readNBit(5);
|
||||
granule.tableSelect[1] = stream.readNBit(5);
|
||||
granule.tableSelect[2] = stream.readNBit(5);
|
||||
granule.region0Count = stream.readNBit(4);
|
||||
granule.region1Count = stream.readNBit(3);
|
||||
granule.blockType = 0;
|
||||
}
|
||||
granule.preflag = (stream.readNBit(1) != 0);
|
||||
granule.scalefacScale = stream.readNBit(1);
|
||||
granule.count1tableSelect = stream.readNBit(1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
si.mainDataBegin = stream.readNBit(8);
|
||||
if (channels == 1) {
|
||||
si.privateBits = stream.readNBit(1);
|
||||
} else {
|
||||
si.privateBits = stream.readNBit(2);
|
||||
}
|
||||
for (int ch = 0; ch < channels; ch++) {
|
||||
Granule granule = si.granule[ch][0];
|
||||
granule.part23Length = stream.readNBit(12);
|
||||
granule.bigValues = stream.readNBit(9);
|
||||
granule.globalGain = stream.readNBit(8);
|
||||
granule.scalefacCompress = stream.readNBit(9);
|
||||
granule.windowSwitchingFlag = (stream.readNBit(1) != 0);
|
||||
if (granule.windowSwitchingFlag) {
|
||||
granule.blockType = stream.readNBit(2);
|
||||
granule.mixedBlockFlag = (stream.readNBit(1) != 0);
|
||||
granule.tableSelect[0] = stream.readNBit(5);
|
||||
granule.tableSelect[1] = stream.readNBit(5);
|
||||
granule.subblockGain[0] = stream.readNBit(3);
|
||||
granule.subblockGain[1] = stream.readNBit(3);
|
||||
granule.subblockGain[2] = stream.readNBit(3);
|
||||
if (granule.blockType == 0)
|
||||
return null;
|
||||
if (granule.blockType == 2 && !granule.mixedBlockFlag) {
|
||||
granule.region0Count = 8;
|
||||
} else {
|
||||
granule.region0Count = 7;
|
||||
granule.region1Count = 20 - granule.region0Count;
|
||||
}
|
||||
} else {
|
||||
granule.tableSelect[0] = stream.readNBit(5);
|
||||
granule.tableSelect[1] = stream.readNBit(5);
|
||||
granule.tableSelect[2] = stream.readNBit(5);
|
||||
granule.region0Count = stream.readNBit(4);
|
||||
granule.region1Count = stream.readNBit(3);
|
||||
granule.blockType = 0;
|
||||
}
|
||||
granule.scalefacScale = stream.readNBit(1);
|
||||
granule.count1tableSelect = stream.readNBit(1);
|
||||
}
|
||||
}
|
||||
stream.terminate();
|
||||
return si;
|
||||
}
|
||||
|
||||
static ScaleFactors readScaleFactors(BitReader br, Granule granule, boolean[] b) {
|
||||
if (granule.windowSwitchingFlag && granule.blockType == 2) {
|
||||
if (granule.mixedBlockFlag)
|
||||
return readScaleFacMixed(br, granule);
|
||||
return readScaleFacShort(br, granule);
|
||||
}
|
||||
return readScaleFacNonSwitch(br, granule, b);
|
||||
}
|
||||
|
||||
private static ScaleFactors readScaleFacMixed(BitReader br, Granule granule) {
|
||||
ScaleFactors sf = new ScaleFactors();
|
||||
for (int k = 0; k < 8; k++)
|
||||
sf.large[k] = br.readNBit(MpaConst.scaleFactorLen[0][granule.scalefacCompress]);
|
||||
for (int j = 3; j < 6; j++) {
|
||||
for (int m = 0; m < 3; m++)
|
||||
sf.small[m][j] = br.readNBit(MpaConst.scaleFactorLen[0][granule.scalefacCompress]);
|
||||
}
|
||||
for (int i = 6; i < 12; i++) {
|
||||
for (int m = 0; m < 3; m++)
|
||||
sf.small[m][i] = br.readNBit(MpaConst.scaleFactorLen[1][granule.scalefacCompress]);
|
||||
}
|
||||
for (int sfb = 12, window = 0; window < 3; window++)
|
||||
sf.small[window][sfb] = 0;
|
||||
return sf;
|
||||
}
|
||||
|
||||
private static ScaleFactors readScaleFacNonSwitch(BitReader br, Granule granule, boolean[] b) {
|
||||
ScaleFactors sf = new ScaleFactors();
|
||||
int length0 = MpaConst.scaleFactorLen[0][granule.scalefacCompress];
|
||||
int length1 = MpaConst.scaleFactorLen[1][granule.scalefacCompress];
|
||||
if (b[0])
|
||||
for (int i = 0; i < 6; i++)
|
||||
sf.large[i] = br.readNBit(length0);
|
||||
if (b[1])
|
||||
for (int i = 6; i < 11; i++)
|
||||
sf.large[i] = br.readNBit(length0);
|
||||
if (b[2])
|
||||
for (int i = 11; i < 16; i++)
|
||||
sf.large[i] = br.readNBit(length1);
|
||||
if (b[3])
|
||||
for (int i = 16; i < 21; i++)
|
||||
sf.large[i] = br.readNBit(length1);
|
||||
sf.large[21] = 0;
|
||||
sf.large[22] = 0;
|
||||
return sf;
|
||||
}
|
||||
|
||||
private static ScaleFactors readScaleFacShort(BitReader br, Granule granule) {
|
||||
ScaleFactors sf = new ScaleFactors();
|
||||
int length0 = MpaConst.scaleFactorLen[0][granule.scalefacCompress];
|
||||
int length1 = MpaConst.scaleFactorLen[1][granule.scalefacCompress];
|
||||
for (int j = 0; j < 6; j++) {
|
||||
for (int k = 0; k < 3; k++)
|
||||
sf.small[k][j] = br.readNBit(length0);
|
||||
}
|
||||
for (int i = 6; i < 12; i++) {
|
||||
for (int k = 0; k < 3; k++)
|
||||
sf.small[k][i] = br.readNBit(length1);
|
||||
}
|
||||
sf.small[0][12] = 0;
|
||||
sf.small[1][12] = 0;
|
||||
sf.small[2][12] = 0;
|
||||
return sf;
|
||||
}
|
||||
|
||||
static ScaleFactors readLSFScaleFactors(BitReader br, MpaHeader header, Granule granule, int ch) {
|
||||
ScaleFactors scalefac = new ScaleFactors();
|
||||
int[] scalefacBuffer = readLSFScaleData(br, header, granule, ch);
|
||||
int m = 0;
|
||||
if (granule.windowSwitchingFlag && granule.blockType == 2) {
|
||||
if (granule.mixedBlockFlag) {
|
||||
for (int i = 0; i < 8; i++) {
|
||||
scalefac.large[i] = scalefacBuffer[m];
|
||||
m++;
|
||||
}
|
||||
for (int sfb = 3; sfb < 12; sfb++) {
|
||||
for (int j = 0; j < 3; j++) {
|
||||
scalefac.small[j][sfb] = scalefacBuffer[m];
|
||||
m++;
|
||||
}
|
||||
}
|
||||
for (int window = 0; window < 3; window++)
|
||||
scalefac.small[window][12] = 0;
|
||||
} else {
|
||||
for (int sfb = 0; sfb < 12; sfb++) {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
scalefac.small[i][sfb] = scalefacBuffer[m];
|
||||
m++;
|
||||
}
|
||||
}
|
||||
for (int window = 0; window < 3; window++)
|
||||
scalefac.small[window][12] = 0;
|
||||
}
|
||||
} else {
|
||||
for (int sfb = 0; sfb < 21; sfb++) {
|
||||
scalefac.large[sfb] = scalefacBuffer[m];
|
||||
m++;
|
||||
}
|
||||
scalefac.large[21] = 0;
|
||||
scalefac.large[22] = 0;
|
||||
}
|
||||
return scalefac;
|
||||
}
|
||||
|
||||
private static int[] readLSFScaleData(BitReader br, MpaHeader header, Granule granule, int ch) {
|
||||
int[] result = new int[54];
|
||||
int[] scaleFacLen = new int[4];
|
||||
int comp = granule.scalefacCompress;
|
||||
int blockType = (granule.blockType == 2) ? (granule.mixedBlockFlag ? 2 : 1) : 0;
|
||||
boolean ch1 = ((header.modeExtension == 1 || header.modeExtension == 3) && ch == 1);
|
||||
int lenType = 0;
|
||||
if (!ch1) {
|
||||
if (comp < 400) {
|
||||
scaleFacLen[0] = (comp >>> 4) / 5;
|
||||
scaleFacLen[1] = (comp >>> 4) % 5;
|
||||
scaleFacLen[2] = (comp & 0xF) >>> 2;
|
||||
scaleFacLen[3] = comp & 0x3;
|
||||
granule.preflag = false;
|
||||
lenType = 0;
|
||||
} else if (comp < 500) {
|
||||
scaleFacLen[0] = (comp - 400 >>> 2) / 5;
|
||||
scaleFacLen[1] = (comp - 400 >>> 2) % 5;
|
||||
scaleFacLen[2] = comp - 400 & 0x3;
|
||||
scaleFacLen[3] = 0;
|
||||
granule.preflag = false;
|
||||
lenType = 1;
|
||||
} else if (comp < 512) {
|
||||
scaleFacLen[0] = (comp - 500) / 3;
|
||||
scaleFacLen[1] = (comp - 500) % 3;
|
||||
scaleFacLen[2] = 0;
|
||||
scaleFacLen[3] = 0;
|
||||
granule.preflag = true;
|
||||
lenType = 2;
|
||||
}
|
||||
} else {
|
||||
int halfComp = comp >>> 1;
|
||||
if (halfComp < 180) {
|
||||
scaleFacLen[0] = halfComp / 36;
|
||||
scaleFacLen[1] = halfComp % 36 / 6;
|
||||
scaleFacLen[2] = halfComp % 36 % 6;
|
||||
scaleFacLen[3] = 0;
|
||||
granule.preflag = false;
|
||||
lenType = 3;
|
||||
} else if (halfComp < 244) {
|
||||
scaleFacLen[0] = (halfComp - 180 & 0x3F) >>> 4;
|
||||
scaleFacLen[1] = (halfComp - 180 & 0xF) >>> 2;
|
||||
scaleFacLen[2] = halfComp - 180 & 0x3;
|
||||
scaleFacLen[3] = 0;
|
||||
granule.preflag = false;
|
||||
lenType = 4;
|
||||
} else if (halfComp < 255) {
|
||||
scaleFacLen[0] = (halfComp - 244) / 3;
|
||||
scaleFacLen[1] = (halfComp - 244) % 3;
|
||||
scaleFacLen[2] = 0;
|
||||
scaleFacLen[3] = 0;
|
||||
granule.preflag = false;
|
||||
lenType = 5;
|
||||
}
|
||||
}
|
||||
for (int i = 0, m = 0; i < 4; i++) {
|
||||
for (int j = 0; j < MpaConst.numberOfScaleFactors[lenType][blockType][i]; j++, m++)
|
||||
result[m] = (scaleFacLen[i] == 0) ? 0 : br.readNBit(scaleFacLen[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static int readCoeffs(BitReader br, Granule granule, int ch, int part2_start, int sfreq, int[] out) {
|
||||
int part23End = part2_start + granule.part23Length;
|
||||
int region1Start = (sfreq == 8) ? 72 : 36;
|
||||
int region2Start = 576;
|
||||
if (!granule.windowSwitchingFlag || granule.blockType != 2) {
|
||||
int region1StartIdx = MathUtil.clip(granule.region0Count + granule.region1Count + 2, 0, (MpaConst.sfbLong[sfreq]).length - 1);
|
||||
region1Start = MpaConst.sfbLong[sfreq][granule.region0Count + 1];
|
||||
region2Start = MpaConst.sfbLong[sfreq][region1StartIdx];
|
||||
}
|
||||
int index = 0;
|
||||
for (int i = 0; i < granule.bigValues << 1; i += 2) {
|
||||
int tab = 0;
|
||||
if (i < region1Start) {
|
||||
tab = granule.tableSelect[0];
|
||||
} else if (i < region2Start) {
|
||||
tab = granule.tableSelect[1];
|
||||
} else {
|
||||
tab = granule.tableSelect[2];
|
||||
}
|
||||
if (tab == 0 || tab == 4 || tab == 14) {
|
||||
out[index++] = 0;
|
||||
out[index++] = 0;
|
||||
} else {
|
||||
int packed = readBigVal(tab, br);
|
||||
out[index++] = Vector2Int.el16_0(packed);
|
||||
out[index++] = Vector2Int.el16_1(packed);
|
||||
}
|
||||
}
|
||||
while (br.position() < part23End && index < 576) {
|
||||
int packed = readCount1(granule.count1tableSelect, br);
|
||||
out[index++] = Vector4Int.el8_0(packed);
|
||||
out[index++] = Vector4Int.el8_1(packed);
|
||||
out[index++] = Vector4Int.el8_2(packed);
|
||||
out[index++] = Vector4Int.el8_3(packed);
|
||||
}
|
||||
if (br.position() < part23End)
|
||||
br.readNBit(part23End - br.position());
|
||||
return MathUtil.clip(index, 0, 576);
|
||||
}
|
||||
|
||||
static int readBigVal(int tab, BitReader br) {
|
||||
int res = MpaConst.bigValVlc[tab].readVLC(br);
|
||||
int x = res >>> 4;
|
||||
int y = res & 0xF;
|
||||
if (MpaConst.bigValEscBits[tab] != 0 &&
|
||||
MpaConst.bigValMaxval[tab] - 1 == x)
|
||||
x += br.readNBit(MpaConst.bigValEscBits[tab]);
|
||||
if (x != 0 &&
|
||||
br.read1Bit() != 0)
|
||||
x = -x;
|
||||
if (MpaConst.bigValEscBits[tab] != 0 &&
|
||||
MpaConst.bigValMaxval[tab] - 1 == y)
|
||||
y += br.readNBit(MpaConst.bigValEscBits[tab]);
|
||||
if (y != 0 &&
|
||||
br.read1Bit() != 0)
|
||||
y = -y;
|
||||
return Vector2Int.pack16(x, y);
|
||||
}
|
||||
|
||||
static int readCount1(int tab, BitReader br) {
|
||||
int res = ((tab == 0) ? MpaConst.cnt1A : MpaConst.cnt1B).readVLC(br);
|
||||
int v = res >> 3 & 0x1;
|
||||
int w = res >> 2 & 0x1;
|
||||
int x = res >> 1 & 0x1;
|
||||
int y = res & 0x1;
|
||||
if (v != 0 &&
|
||||
br.read1Bit() != 0)
|
||||
v = -v;
|
||||
if (w != 0 &&
|
||||
br.read1Bit() != 0)
|
||||
w = -w;
|
||||
if (x != 0 &&
|
||||
br.read1Bit() != 0)
|
||||
x = -x;
|
||||
if (y != 0 &&
|
||||
br.read1Bit() != 0)
|
||||
y = -y;
|
||||
return Vector4Int.pack8(v, w, x, y);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,271 @@
|
|||
package org.jcodec.codecs.mpa;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.Arrays;
|
||||
import org.jcodec.common.AudioCodecMeta;
|
||||
import org.jcodec.common.AudioDecoder;
|
||||
import org.jcodec.common.AudioFormat;
|
||||
import org.jcodec.common.io.BitReader;
|
||||
import org.jcodec.common.io.NIOUtils;
|
||||
import org.jcodec.common.model.AudioBuffer;
|
||||
import org.jcodec.common.tools.MathUtil;
|
||||
|
||||
public class Mp3Decoder implements AudioDecoder {
|
||||
private static final boolean[] ALL_TRUE = new boolean[] { true, true, true, true };
|
||||
|
||||
private static final int SAMPLES_PER_BAND = 18;
|
||||
|
||||
private static final int NUM_BANDS = 32;
|
||||
|
||||
private ChannelSynthesizer[] filter = new ChannelSynthesizer[] { null, null };
|
||||
|
||||
private boolean initialized;
|
||||
|
||||
private static final double fourByThree = 1.3333333333333333D;
|
||||
|
||||
private float[][] prevBlk;
|
||||
|
||||
private ByteBuffer frameData = ByteBuffer.allocate(4096);
|
||||
|
||||
private int channels;
|
||||
|
||||
private int sfreq;
|
||||
|
||||
private float[] samples = new float[32];
|
||||
|
||||
private float[] mdctIn = new float[18];
|
||||
|
||||
private float[] mdctOut = new float[36];
|
||||
|
||||
private float[][] dequant = new float[2][576];
|
||||
|
||||
private short[][] tmpOut = new short[2][576];
|
||||
|
||||
private void init(MpaHeader header) {
|
||||
float scalefactor = 32700.0F;
|
||||
this.channels = (header.mode == 3) ? 1 : 2;
|
||||
this.filter[0] = new ChannelSynthesizer(0, scalefactor);
|
||||
if (this.channels == 2)
|
||||
this.filter[1] = new ChannelSynthesizer(1, scalefactor);
|
||||
this.prevBlk = new float[2][576];
|
||||
this.sfreq = header.sampleFreq + ((header.version == 1) ? 3 : ((header.version == 2) ? 6 : 0));
|
||||
for (int ch = 0; ch < 2; ch++)
|
||||
Arrays.fill(this.prevBlk[ch], 0.0F);
|
||||
this.initialized = true;
|
||||
}
|
||||
|
||||
private void decodeGranule(MpaHeader header, ByteBuffer output, Mp3Bitstream.MP3SideInfo si, BitReader br, Mp3Bitstream.ScaleFactors[] scalefac, int grInd) {
|
||||
Arrays.fill(this.dequant[0], 0.0F);
|
||||
Arrays.fill(this.dequant[1], 0.0F);
|
||||
for (int ch = 0; ch < this.channels; ch++) {
|
||||
int part2Start = br.position();
|
||||
Mp3Bitstream.Granule granule = si.granule[ch][grInd];
|
||||
if (header.version == 1) {
|
||||
Mp3Bitstream.ScaleFactors old = scalefac[ch];
|
||||
boolean[] scfi = (grInd == 0) ? ALL_TRUE : si.scfsi[ch];
|
||||
scalefac[ch] = Mp3Bitstream.readScaleFactors(br, si.granule[ch][grInd], scfi);
|
||||
mergeScaleFac(scalefac[ch], old, scfi);
|
||||
} else {
|
||||
scalefac[ch] = Mp3Bitstream.readLSFScaleFactors(br, header, granule, ch);
|
||||
}
|
||||
int[] coeffs = new int[580];
|
||||
int nonzero = Mp3Bitstream.readCoeffs(br, granule, ch, part2Start, this.sfreq, coeffs);
|
||||
dequantizeCoeffs(coeffs, nonzero, granule, scalefac[ch], this.dequant[ch]);
|
||||
}
|
||||
boolean msStereo = (header.mode == 1 && (header.modeExtension & 0x2) != 0);
|
||||
if (msStereo && this.channels == 2)
|
||||
decodeMsStereo(header, si.granule[0][grInd], scalefac, this.dequant);
|
||||
for (int i = 0; i < this.channels; i++) {
|
||||
float[] out = this.dequant[i];
|
||||
Mp3Bitstream.Granule granule = si.granule[i][grInd];
|
||||
antialias(granule, out);
|
||||
mdctDecode(i, granule, out);
|
||||
for (int sb18 = 18; sb18 < 576; sb18 += 36) {
|
||||
for (int j = 1; j < 18; j += 2)
|
||||
out[sb18 + j] = -out[sb18 + j];
|
||||
}
|
||||
for (int ss = 0, off = 0; ss < 18; ss++, off += 32) {
|
||||
for (int j = 0, sb = 0; j < 576; j += 18, sb++)
|
||||
this.samples[sb] = out[j + ss];
|
||||
this.filter[i].synthesize(this.samples, this.tmpOut[i], off);
|
||||
}
|
||||
}
|
||||
if (this.channels == 2) {
|
||||
appendSamplesInterleave(output, this.tmpOut[0], this.tmpOut[1], 576);
|
||||
} else {
|
||||
appendSamples(output, this.tmpOut[0], 576);
|
||||
}
|
||||
}
|
||||
|
||||
public static void appendSamples(ByteBuffer buf, short[] f, int n) {
|
||||
for (int i = 0; i < n; i++)
|
||||
buf.putShort(f[i]);
|
||||
}
|
||||
|
||||
public static void appendSamplesInterleave(ByteBuffer buf, short[] f0, short[] f1, int n) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
buf.putShort(f0[i]);
|
||||
buf.putShort(f1[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private void mergeScaleFac(Mp3Bitstream.ScaleFactors sf, Mp3Bitstream.ScaleFactors old, boolean[] scfsi) {
|
||||
if (!scfsi[0])
|
||||
for (int i = 0; i < 6; i++)
|
||||
sf.large[i] = old.large[i];
|
||||
if (!scfsi[1])
|
||||
for (int i = 6; i < 11; i++)
|
||||
sf.large[i] = old.large[i];
|
||||
if (!scfsi[2])
|
||||
for (int i = 11; i < 16; i++)
|
||||
sf.large[i] = old.large[i];
|
||||
if (!scfsi[3])
|
||||
for (int i = 16; i < 21; i++)
|
||||
sf.large[i] = old.large[i];
|
||||
}
|
||||
|
||||
private void dequantizeCoeffs(int[] input, int nonzero, Mp3Bitstream.Granule granule, Mp3Bitstream.ScaleFactors scalefac, float[] out) {
|
||||
float globalGain = (float)Math.pow(2.0D, 0.25D * ((double)granule.globalGain - 210.0D));
|
||||
if (granule.windowSwitchingFlag && granule.blockType == 2) {
|
||||
if (granule.mixedBlockFlag) {
|
||||
dequantMixed(input, nonzero, granule, scalefac, globalGain, out);
|
||||
} else {
|
||||
dequantShort(input, nonzero, granule, scalefac, globalGain, out);
|
||||
}
|
||||
} else {
|
||||
dequantLong(input, nonzero, granule, scalefac, globalGain, out);
|
||||
}
|
||||
}
|
||||
|
||||
private void dequantMixed(int[] input, int nonzero, Mp3Bitstream.Granule granule, Mp3Bitstream.ScaleFactors scalefac, float globalGain, float[] out) {
|
||||
int i = 0;
|
||||
for (int j = 0; j < 8 && i < nonzero; j++) {
|
||||
for (; i < MpaConst.sfbLong[this.sfreq][j + 1] && i < nonzero; i++) {
|
||||
int idx = scalefac.large[j] + (granule.preflag ? MpaConst.pretab[j] : 0) << granule.scalefacScale;
|
||||
out[i] = globalGain * pow43(input[i]) * MpaConst.quantizerTab[idx];
|
||||
}
|
||||
}
|
||||
for (int sfb = 3; sfb < 12 && i < nonzero; sfb++) {
|
||||
int sfbSz = MpaConst.sfbShort[this.sfreq][sfb + 1] - MpaConst.sfbShort[this.sfreq][sfb];
|
||||
int sfbStart = i;
|
||||
for (int wnd = 0; wnd < 3; wnd++) {
|
||||
for (int k = 0; k < sfbSz && i < nonzero; k++, i++) {
|
||||
int idx = (scalefac.small[wnd][sfb] << granule.scalefacScale) + (granule.subblockGain[wnd] << 2);
|
||||
out[sfbStart + k * 3 + wnd] = globalGain * pow43(input[i]) * MpaConst.quantizerTab[idx];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void dequantShort(int[] input, int nonzero, Mp3Bitstream.Granule granule, Mp3Bitstream.ScaleFactors scalefac, float globalGain, float[] out) {
|
||||
for (int sfb = 0, i = 0; i < nonzero; sfb++) {
|
||||
int sfbSz = MpaConst.sfbShort[this.sfreq][sfb + 1] - MpaConst.sfbShort[this.sfreq][sfb];
|
||||
int sfbStart = i;
|
||||
for (int wnd = 0; wnd < 3; wnd++) {
|
||||
for (int j = 0; j < sfbSz && i < nonzero; j++, i++) {
|
||||
int idx = (scalefac.small[wnd][sfb] << granule.scalefacScale) + (granule.subblockGain[wnd] << 2);
|
||||
out[sfbStart + j * 3 + wnd] = globalGain * pow43(input[i]) * MpaConst.quantizerTab[idx];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void dequantLong(int[] input, int nonzero, Mp3Bitstream.Granule granule, Mp3Bitstream.ScaleFactors scalefac, float globalGain, float[] out) {
|
||||
for (int i = 0, sfb = 0; i < nonzero; i++) {
|
||||
if (i == MpaConst.sfbLong[this.sfreq][sfb + 1])
|
||||
sfb++;
|
||||
int idx = scalefac.large[sfb] + (granule.preflag ? MpaConst.pretab[sfb] : 0) << granule.scalefacScale;
|
||||
out[i] = globalGain * pow43(input[i]) * MpaConst.quantizerTab[idx];
|
||||
}
|
||||
}
|
||||
|
||||
private float pow43(int val) {
|
||||
if (val == 0)
|
||||
return 0.0F;
|
||||
int sign = 1 - (val >>> 31 << 1);
|
||||
int abs = MathUtil.abs(val);
|
||||
if (abs < MpaConst.power43Tab.length)
|
||||
return (float)sign * MpaConst.power43Tab[abs];
|
||||
return (float)sign * (float)Math.pow((double)abs, 1.3333333333333333D);
|
||||
}
|
||||
|
||||
private void decodeMsStereo(MpaHeader header, Mp3Bitstream.Granule granule, Mp3Bitstream.ScaleFactors[] scalefac, float[][] ro) {
|
||||
for (int i = 0; i < 576; i++) {
|
||||
float a = ro[0][i];
|
||||
float b = ro[1][i];
|
||||
ro[0][i] = (a + b) * 0.70710677F;
|
||||
ro[1][i] = (a - b) * 0.70710677F;
|
||||
}
|
||||
}
|
||||
|
||||
private void antialias(Mp3Bitstream.Granule granule, float[] out) {
|
||||
if (granule.windowSwitchingFlag && granule.blockType == 2 && !granule.mixedBlockFlag)
|
||||
return;
|
||||
int bands = (granule.windowSwitchingFlag && granule.mixedBlockFlag && granule.blockType == 2) ? 1 : 31;
|
||||
for (int band = 0, bandStart = 0; band < bands; band++, bandStart += 18) {
|
||||
for (int sample = 0; sample < 8; sample++) {
|
||||
int src_idx1 = bandStart + 17 - sample;
|
||||
int src_idx2 = bandStart + 18 + sample;
|
||||
float bu = out[src_idx1];
|
||||
float bd = out[src_idx2];
|
||||
out[src_idx1] = bu * MpaConst.cs[sample] - bd * MpaConst.ca[sample];
|
||||
out[src_idx2] = bd * MpaConst.cs[sample] + bu * MpaConst.ca[sample];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void mdctDecode(int ch, Mp3Bitstream.Granule granule, float[] out) {
|
||||
for (int sb18 = 0; sb18 < 576; sb18 += 18) {
|
||||
int blockType = (granule.windowSwitchingFlag && granule.mixedBlockFlag && sb18 < 36) ? 0 :
|
||||
granule.blockType;
|
||||
for (int cc = 0; cc < 18; cc++)
|
||||
this.mdctIn[cc] = out[cc + sb18];
|
||||
if (blockType == 2) {
|
||||
Mp3Mdct.threeShort(this.mdctIn, this.mdctOut);
|
||||
} else {
|
||||
Mp3Mdct.oneLong(this.mdctIn, this.mdctOut);
|
||||
for (int j = 0; j < 36; j++)
|
||||
this.mdctOut[j] = this.mdctOut[j] * MpaConst.win[blockType][j];
|
||||
}
|
||||
for (int i = 0; i < 18; i++) {
|
||||
out[i + sb18] = this.mdctOut[i] + this.prevBlk[ch][sb18 + i];
|
||||
this.prevBlk[ch][sb18 + i] = this.mdctOut[18 + i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public AudioBuffer decodeFrame(ByteBuffer frame, ByteBuffer dst) throws IOException {
|
||||
MpaHeader header = MpaHeader.read_header(frame);
|
||||
if (!this.initialized)
|
||||
init(header);
|
||||
boolean intensityStereo = (header.mode == 1 && (header.modeExtension & 0x1) != 0);
|
||||
if (intensityStereo)
|
||||
throw new RuntimeException("Intensity stereo is not supported.");
|
||||
dst.order(ByteOrder.LITTLE_ENDIAN);
|
||||
Mp3Bitstream.MP3SideInfo si = Mp3Bitstream.readSideInfo(header, frame, this.channels);
|
||||
int reserve = this.frameData.position();
|
||||
this.frameData.put(NIOUtils.read(frame, header.frameBytes));
|
||||
this.frameData.flip();
|
||||
if (header.protectionBit == 0)
|
||||
frame.getShort();
|
||||
NIOUtils.skip(this.frameData, reserve - si.mainDataBegin);
|
||||
BitReader br = BitReader.createBitReader(this.frameData);
|
||||
Mp3Bitstream.ScaleFactors[] scalefac = new Mp3Bitstream.ScaleFactors[2];
|
||||
decodeGranule(header, dst, si, br, scalefac, 0);
|
||||
if (header.version == 1)
|
||||
decodeGranule(header, dst, si, br, scalefac, 1);
|
||||
br.terminate();
|
||||
NIOUtils.relocateLeftover(this.frameData);
|
||||
dst.flip();
|
||||
return new AudioBuffer(dst, null, 1);
|
||||
}
|
||||
|
||||
public AudioCodecMeta getCodecMeta(ByteBuffer data) throws IOException {
|
||||
MpaHeader header = MpaHeader.read_header(data.duplicate());
|
||||
AudioFormat format = new AudioFormat(MpaConst.frequencies[header.version][header.sampleFreq], 16,
|
||||
(header.mode == 3) ? 1 : 2, true, false);
|
||||
return AudioCodecMeta.fromAudioFormat(format);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,147 @@
|
|||
package org.jcodec.codecs.mpa;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class Mp3Mdct {
|
||||
private static final float factor36pt0 = 0.34729636F;
|
||||
|
||||
private static final float factor36pt1 = 1.5320889F;
|
||||
|
||||
private static final float factor36pt2 = 1.8793852F;
|
||||
|
||||
private static final float factor36pt3 = 1.7320508F;
|
||||
|
||||
private static final float factor36pt4 = 1.9696155F;
|
||||
|
||||
private static final float factor36pt5 = 1.2855753F;
|
||||
|
||||
private static final float factor36pt6 = 0.6840403F;
|
||||
|
||||
private static final float[] factor36 = new float[] { 0.5019099F, 0.5176381F, 0.55168897F, 0.61038727F, 0.8717234F, 1.1831008F, 1.9318516F, 5.7368565F };
|
||||
|
||||
private static final float cos075 = 0.9914449F;
|
||||
|
||||
private static final float cos225 = 0.9238795F;
|
||||
|
||||
private static final float cos300 = 0.8660254F;
|
||||
|
||||
private static final float cos375 = 0.7933533F;
|
||||
|
||||
private static final float cos450 = 0.70710677F;
|
||||
|
||||
private static final float cos525 = 0.6087614F;
|
||||
|
||||
private static final float cos600 = 0.5F;
|
||||
|
||||
private static final float cos675 = 0.38268343F;
|
||||
|
||||
private static final float cos825 = 0.13052619F;
|
||||
|
||||
private static final float factor12pt0 = 1.9318516F;
|
||||
|
||||
private static final float factor12pt1 = 0.5176381F;
|
||||
|
||||
private static final float[] factor12 = new float[] { 0.5043145F, 0.5411961F, 0.6302362F, 0.8213398F, 1.306563F, 3.830649F };
|
||||
|
||||
private static float[] tmp = new float[16];
|
||||
|
||||
static void oneLong(float[] src, float[] dst) {
|
||||
for (int i3 = 17; i3 > 0; i3--)
|
||||
src[i3] = src[i3] + src[i3 - 1];
|
||||
for (int i2 = 17; i2 > 2; i2 -= 2)
|
||||
src[i2] = src[i2] + src[i2 - 2];
|
||||
for (int i1 = 0, k = 0; i1 < 2; i1++, k += 8) {
|
||||
float f1 = src[i1] + src[i1];
|
||||
float f2 = f1 + src[12 + i1];
|
||||
float tmp2 = src[6 + i1] * 1.7320508F;
|
||||
tmp[k + 0] = f2 + src[4 + i1] * 1.8793852F + src[8 + i1] * 1.5320889F + src[16 + i1] * 0.34729636F;
|
||||
tmp[k + 1] = f1 + src[4 + i1] - src[8 + i1] - src[12 + i1] - src[12 + i1] - src[16 + i1];
|
||||
tmp[k + 2] = f2 - src[4 + i1] * 0.34729636F - src[8 + i1] * 1.8793852F + src[16 + i1] * 1.5320889F;
|
||||
tmp[k + 3] = f2 - src[4 + i1] * 1.5320889F + src[8 + i1] * 0.34729636F - src[16 + i1] * 1.8793852F;
|
||||
tmp[k + 4] = src[2 + i1] * 1.9696155F + tmp2 + src[10 + i1] * 1.2855753F + src[14 + i1] * 0.6840403F;
|
||||
tmp[k + 5] = (src[2 + i1] - src[10 + i1] - src[14 + i1]) * 1.7320508F;
|
||||
tmp[k + 6] = src[2 + i1] * 1.2855753F - tmp2 - src[10 + i1] * 0.6840403F + src[14 + i1] * 1.9696155F;
|
||||
tmp[k + 7] = src[2 + i1] * 0.6840403F - tmp2 + src[10 + i1] * 1.9696155F - src[14 + i1] * 1.2855753F;
|
||||
}
|
||||
for (int n = 0, j = 4, i4 = 8, l = 12; n < 4; n++, j++, i4++, l++) {
|
||||
float q1 = tmp[n];
|
||||
float q2 = tmp[i4];
|
||||
tmp[n] = tmp[n] + tmp[j];
|
||||
tmp[j] = q1 - tmp[j];
|
||||
tmp[i4] = (tmp[i4] + tmp[l]) * factor36[n];
|
||||
tmp[l] = (q2 - tmp[l]) * factor36[7 - n];
|
||||
}
|
||||
for (int m = 0; m < 4; m++) {
|
||||
dst[26 - m] = tmp[m] + tmp[8 + m];
|
||||
dst[8 - m] = tmp[8 + m] - tmp[m];
|
||||
dst[27 + m] = dst[26 - m];
|
||||
dst[9 + m] = -dst[8 - m];
|
||||
}
|
||||
for (int i = 0; i < 4; i++) {
|
||||
dst[21 - i] = tmp[7 - i] + tmp[15 - i];
|
||||
dst[3 - i] = tmp[15 - i] - tmp[7 - i];
|
||||
dst[32 + i] = dst[21 - i];
|
||||
dst[14 + i] = -dst[3 - i];
|
||||
}
|
||||
float tmp0 = src[0] - src[4] + src[8] - src[12] + src[16];
|
||||
float tmp1 = (src[1] - src[5] + src[9] - src[13] + src[17]) * 0.70710677F;
|
||||
dst[4] = tmp1 - tmp0;
|
||||
dst[13] = -dst[4];
|
||||
dst[22] = tmp0 + tmp1;
|
||||
dst[31] = tmp0 + tmp1;
|
||||
}
|
||||
|
||||
static void threeShort(float[] src, float[] dst) {
|
||||
Arrays.fill(dst, 0.0F);
|
||||
for (int i = 0, outOff = 0; i < 3; i++, outOff += 6)
|
||||
imdct12(src, dst, outOff, i);
|
||||
}
|
||||
|
||||
private static void imdct12(float[] src, float[] dst, int outOff, int wndIdx) {
|
||||
for (int j = 15 + wndIdx, k = 12 + wndIdx; j >= 3 + wndIdx; j -= 3, k -= 3)
|
||||
src[j] = src[j] + src[k];
|
||||
src[15 + wndIdx] = src[15 + wndIdx] + src[9 + wndIdx];
|
||||
src[9 + wndIdx] = src[9 + wndIdx] + src[3 + wndIdx];
|
||||
float pp2 = src[12 + wndIdx] * 0.5F;
|
||||
float pp1 = src[6 + wndIdx] * 0.8660254F;
|
||||
float sum = src[0 + wndIdx] + pp2;
|
||||
tmp[1] = src[wndIdx] - src[12 + wndIdx];
|
||||
tmp[0] = sum + pp1;
|
||||
tmp[2] = sum - pp1;
|
||||
pp2 = src[15 + wndIdx] * 0.5F;
|
||||
pp1 = src[9 + wndIdx] * 0.8660254F;
|
||||
sum = src[3 + wndIdx] + pp2;
|
||||
tmp[4] = src[3 + wndIdx] - src[15 + wndIdx];
|
||||
tmp[5] = sum + pp1;
|
||||
tmp[3] = sum - pp1;
|
||||
tmp[3] = tmp[3] * 1.9318516F;
|
||||
tmp[4] = tmp[4] * 0.70710677F;
|
||||
tmp[5] = tmp[5] * 0.5176381F;
|
||||
float t = tmp[0];
|
||||
tmp[0] = tmp[0] + tmp[5];
|
||||
tmp[5] = t - tmp[5];
|
||||
t = tmp[1];
|
||||
tmp[1] = tmp[1] + tmp[4];
|
||||
tmp[4] = t - tmp[4];
|
||||
t = tmp[2];
|
||||
tmp[2] = tmp[2] + tmp[3];
|
||||
tmp[3] = t - tmp[3];
|
||||
for (int m = 0; m < 6; m++)
|
||||
tmp[m] = tmp[m] * factor12[m];
|
||||
tmp[8] = -tmp[0] * 0.7933533F;
|
||||
tmp[9] = -tmp[0] * 0.6087614F;
|
||||
tmp[7] = -tmp[1] * 0.9238795F;
|
||||
tmp[10] = -tmp[1] * 0.38268343F;
|
||||
tmp[6] = -tmp[2] * 0.9914449F;
|
||||
tmp[11] = -tmp[2] * 0.13052619F;
|
||||
tmp[0] = tmp[3];
|
||||
tmp[1] = tmp[4] * 0.38268343F;
|
||||
tmp[2] = tmp[5] * 0.6087614F;
|
||||
tmp[3] = -tmp[5] * 0.7933533F;
|
||||
tmp[4] = -tmp[4] * 0.9238795F;
|
||||
tmp[5] = -tmp[0] * 0.9914449F;
|
||||
tmp[0] = tmp[0] * 0.13052619F;
|
||||
for (int i = 0, n = outOff + 6; i < 12; i++, n++)
|
||||
dst[n] = dst[n] + tmp[i];
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,116 @@
|
|||
package org.jcodec.codecs.mpa;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
class MpaHeader {
|
||||
int layer;
|
||||
|
||||
int protectionBit;
|
||||
|
||||
int bitrateIndex;
|
||||
|
||||
int paddingBit;
|
||||
|
||||
int modeExtension;
|
||||
|
||||
int version;
|
||||
|
||||
int mode;
|
||||
|
||||
int sampleFreq;
|
||||
|
||||
int numSubbands;
|
||||
|
||||
int intensityStereoBound;
|
||||
|
||||
boolean copyright;
|
||||
|
||||
boolean original;
|
||||
|
||||
int framesize;
|
||||
|
||||
int frameBytes;
|
||||
|
||||
static MpaHeader read_header(ByteBuffer bb) {
|
||||
MpaHeader ret = new MpaHeader();
|
||||
int headerstring = bb.getInt();
|
||||
ret.version = headerstring >>> 19 & 0x1;
|
||||
if ((headerstring >>> 20 & 0x1) == 0)
|
||||
if (ret.version == 0) {
|
||||
ret.version = 2;
|
||||
} else {
|
||||
throw new RuntimeException("UNKNOWN_ERROR");
|
||||
}
|
||||
if ((ret.sampleFreq = headerstring >>> 10 & 0x3) == 3)
|
||||
throw new RuntimeException("UNKNOWN_ERROR");
|
||||
ret.layer = 4 - (headerstring >>> 17) & 0x3;
|
||||
ret.protectionBit = headerstring >>> 16 & 0x1;
|
||||
ret.bitrateIndex = headerstring >>> 12 & 0xF;
|
||||
ret.paddingBit = headerstring >>> 9 & 0x1;
|
||||
ret.mode = headerstring >>> 6 & 0x3;
|
||||
ret.modeExtension = headerstring >>> 4 & 0x3;
|
||||
if (ret.mode == 1) {
|
||||
ret.intensityStereoBound = (ret.modeExtension << 2) + 4;
|
||||
} else {
|
||||
ret.intensityStereoBound = 0;
|
||||
}
|
||||
if ((headerstring >>> 3 & 0x1) == 1)
|
||||
ret.copyright = true;
|
||||
if ((headerstring >>> 2 & 0x1) == 1)
|
||||
ret.original = true;
|
||||
if (ret.layer == 1) {
|
||||
ret.numSubbands = 32;
|
||||
} else {
|
||||
int channel_bitrate = ret.bitrateIndex;
|
||||
if (ret.mode != 3)
|
||||
if (channel_bitrate == 4) {
|
||||
channel_bitrate = 1;
|
||||
} else {
|
||||
channel_bitrate -= 4;
|
||||
}
|
||||
if (channel_bitrate == 1 || channel_bitrate == 2) {
|
||||
if (ret.sampleFreq == 2) {
|
||||
ret.numSubbands = 12;
|
||||
} else {
|
||||
ret.numSubbands = 8;
|
||||
}
|
||||
} else if (ret.sampleFreq == 1 || (channel_bitrate >= 3 && channel_bitrate <= 5)) {
|
||||
ret.numSubbands = 27;
|
||||
} else {
|
||||
ret.numSubbands = 30;
|
||||
}
|
||||
}
|
||||
if (ret.intensityStereoBound > ret.numSubbands)
|
||||
ret.intensityStereoBound = ret.numSubbands;
|
||||
calculateFramesize(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static void calculateFramesize(MpaHeader ret) {
|
||||
if (ret.layer == 1) {
|
||||
ret.framesize = 12 * MpaConst.bitrates[ret.version][0][ret.bitrateIndex] / MpaConst.frequencies[ret.version][ret.sampleFreq];
|
||||
if (ret.paddingBit != 0)
|
||||
ret.framesize++;
|
||||
ret.framesize <<= 2;
|
||||
ret.frameBytes = 0;
|
||||
} else {
|
||||
ret.framesize = 144 * MpaConst.bitrates[ret.version][ret.layer - 1][ret.bitrateIndex] / MpaConst.frequencies[ret.version][ret.sampleFreq];
|
||||
if (ret.version == 0 || ret.version == 2)
|
||||
ret.framesize >>= 1;
|
||||
if (ret.paddingBit != 0)
|
||||
ret.framesize++;
|
||||
if (ret.layer == 3) {
|
||||
if (ret.version == 1) {
|
||||
ret
|
||||
.frameBytes = ret.framesize - ((ret.mode == 3) ? 17 : 32) - ((ret.protectionBit != 0) ? 0 : 2) - 4;
|
||||
} else {
|
||||
ret
|
||||
.frameBytes = ret.framesize - ((ret.mode == 3) ? 9 : 17) - ((ret.protectionBit != 0) ? 0 : 2) - 4;
|
||||
}
|
||||
} else {
|
||||
ret.frameBytes = 0;
|
||||
}
|
||||
}
|
||||
ret.framesize -= 4;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,254 @@
|
|||
package org.jcodec.codecs.mpa;
|
||||
|
||||
import org.jcodec.common.tools.MathUtil;
|
||||
|
||||
public class MpaPqmf {
|
||||
private static final double MY_PI = 3.141592653589793D;
|
||||
|
||||
private static final float cos1_64 = (float)(1.0D / (2.0D * Math.cos(0.04908738521234052D)));
|
||||
|
||||
private static final float cos3_64 = (float)(1.0D / (2.0D * Math.cos(0.14726215563702155D)));
|
||||
|
||||
private static final float cos5_64 = (float)(1.0D / (2.0D * Math.cos(0.2454369260617026D)));
|
||||
|
||||
private static final float cos7_64 = (float)(1.0D / (2.0D * Math.cos(0.3436116964863836D)));
|
||||
|
||||
private static final float cos9_64 = (float)(1.0D / (2.0D * Math.cos(0.44178646691106466D)));
|
||||
|
||||
private static final float cos11_64 = (float)(1.0D / (2.0D * Math.cos(0.5399612373357456D)));
|
||||
|
||||
private static final float cos13_64 = (float)(1.0D / (2.0D * Math.cos(0.6381360077604268D)));
|
||||
|
||||
private static final float cos15_64 = (float)(1.0D / (2.0D * Math.cos(0.7363107781851077D)));
|
||||
|
||||
private static final float cos17_64 = (float)(1.0D / (2.0D * Math.cos(0.8344855486097889D)));
|
||||
|
||||
private static final float cos19_64 = (float)(1.0D / (2.0D * Math.cos(0.9326603190344698D)));
|
||||
|
||||
private static final float cos21_64 = (float)(1.0D / (2.0D * Math.cos(1.030835089459151D)));
|
||||
|
||||
private static final float cos23_64 = (float)(1.0D / (2.0D * Math.cos(1.1290098598838318D)));
|
||||
|
||||
private static final float cos25_64 = (float)(1.0D / (2.0D * Math.cos(1.227184630308513D)));
|
||||
|
||||
private static final float cos27_64 = (float)(1.0D / (2.0D * Math.cos(1.325359400733194D)));
|
||||
|
||||
private static final float cos29_64 = (float)(1.0D / (2.0D * Math.cos(1.423534171157875D)));
|
||||
|
||||
private static final float cos31_64 = (float)(1.0D / (2.0D * Math.cos(1.521708941582556D)));
|
||||
|
||||
private static final float cos1_32 = (float)(1.0D / (2.0D * Math.cos(0.09817477042468103D)));
|
||||
|
||||
private static final float cos3_32 = (float)(1.0D / (2.0D * Math.cos(0.2945243112740431D)));
|
||||
|
||||
private static final float cos5_32 = (float)(1.0D / (2.0D * Math.cos(0.4908738521234052D)));
|
||||
|
||||
private static final float cos7_32 = (float)(1.0D / (2.0D * Math.cos(0.6872233929727672D)));
|
||||
|
||||
private static final float cos9_32 = (float)(1.0D / (2.0D * Math.cos(0.8835729338221293D)));
|
||||
|
||||
private static final float cos11_32 = (float)(1.0D / (2.0D * Math.cos(1.0799224746714913D)));
|
||||
|
||||
private static final float cos13_32 = (float)(1.0D / (2.0D * Math.cos(1.2762720155208536D)));
|
||||
|
||||
private static final float cos15_32 = (float)(1.0D / (2.0D * Math.cos(1.4726215563702154D)));
|
||||
|
||||
private static final float cos1_16 = (float)(1.0D / (2.0D * Math.cos(0.19634954084936207D)));
|
||||
|
||||
private static final float cos3_16 = (float)(1.0D / (2.0D * Math.cos(0.5890486225480862D)));
|
||||
|
||||
private static final float cos5_16 = (float)(1.0D / (2.0D * Math.cos(0.9817477042468103D)));
|
||||
|
||||
private static final float cos7_16 = (float)(1.0D / (2.0D * Math.cos(1.3744467859455345D)));
|
||||
|
||||
private static final float cos1_8 = (float)(1.0D / (2.0D * Math.cos(0.39269908169872414D)));
|
||||
|
||||
private static final float cos3_8 = (float)(1.0D / (2.0D * Math.cos(1.1780972450961724D)));
|
||||
|
||||
private static final float cos1_4 = (float)(1.0D / (2.0D * Math.cos(0.7853981633974483D)));
|
||||
|
||||
private static final float[] bf32 = new float[] {
|
||||
cos1_64, cos3_64, cos5_64, cos7_64, cos9_64, cos11_64, cos13_64, cos15_64, cos17_64, cos19_64,
|
||||
cos21_64, cos23_64, cos25_64, cos27_64, cos29_64, cos31_64 };
|
||||
|
||||
private static final float[] bf16 = new float[] { cos1_32, cos3_32, cos5_32, cos7_32, cos9_32, cos11_32, cos13_32, cos15_32 };
|
||||
|
||||
private static final float[] bf8 = new float[] { cos1_16, cos3_16, cos5_16, cos7_16 };
|
||||
|
||||
static void computeFilter(int sampleOff, float[] samples, short[] out, int outOff, float scalefactor) {
|
||||
int dvp = 0;
|
||||
for (int i = 0; i < 32; i++) {
|
||||
int b = i << 4;
|
||||
float pcm_sample = (samples[(16 + sampleOff & 0xF) + dvp] * MpaConst.dp[b + 0] + samples[(15 + sampleOff & 0xF) + dvp] * MpaConst.dp[b + 1] + samples[(14 + sampleOff & 0xF) + dvp] * MpaConst.dp[b + 2] + samples[(13 + sampleOff & 0xF) + dvp] * MpaConst.dp[b + 3] + samples[(12 + sampleOff & 0xF) + dvp] * MpaConst.dp[b + 4] + samples[(11 + sampleOff & 0xF) + dvp] * MpaConst.dp[b + 5] + samples[(10 + sampleOff & 0xF) + dvp] * MpaConst.dp[b + 6] + samples[(9 + sampleOff & 0xF) + dvp] * MpaConst.dp[b + 7] + samples[(8 + sampleOff & 0xF) + dvp] * MpaConst.dp[b + 8] + samples[(7 + sampleOff & 0xF) + dvp] * MpaConst.dp[b + 9] + samples[(6 + sampleOff & 0xF) + dvp] * MpaConst.dp[b + 10] + samples[(5 + sampleOff & 0xF) + dvp] * MpaConst.dp[b + 11] + samples[(4 + sampleOff & 0xF) + dvp] * MpaConst.dp[b + 12] + samples[(3 + sampleOff & 0xF) + dvp] * MpaConst.dp[b + 13] + samples[(2 + sampleOff & 0xF) + dvp] * MpaConst.dp[b + 14] + samples[(1 + sampleOff & 0xF) + dvp] * MpaConst.dp[b + 15]) * scalefactor;
|
||||
out[outOff + i] = (short)MathUtil.clip((int)pcm_sample, -32768, 32767);
|
||||
dvp += 16;
|
||||
}
|
||||
}
|
||||
|
||||
static void computeButterfly(int pos, float[] s) {
|
||||
butterfly32(s);
|
||||
butterfly16L(s);
|
||||
butterfly16H(s);
|
||||
butterfly8L(s, 0);
|
||||
butterfly8H(s, 0);
|
||||
butterfly8L(s, 16);
|
||||
butterfly8H(s, 16);
|
||||
for (int j = 0; j < 32; j += 8) {
|
||||
butterfly4L(s, j);
|
||||
butterfly4H(s, j);
|
||||
}
|
||||
for (int i = 0; i < 32; i += 4) {
|
||||
butterfly2L(s, i);
|
||||
butterfly2H(s, i);
|
||||
}
|
||||
float k0 = -s[14] - s[15] - s[10] - s[11];
|
||||
float k1 = s[29] + s[31] + s[25];
|
||||
float k2 = k1 + s[17];
|
||||
float k3 = k1 + s[21] + s[23];
|
||||
float k4 = s[15] + s[11];
|
||||
float k5 = s[15] + s[13] + s[9];
|
||||
float k6 = s[7] + s[5];
|
||||
float k7 = s[31] + s[23];
|
||||
float k8 = k7 + s[27];
|
||||
float k9 = s[31] + s[27] + s[19];
|
||||
float k10 = -s[26] - s[27] - s[30] - s[31];
|
||||
float k11 = -s[24] - s[28] - s[30] - s[31];
|
||||
float k12 = s[20] + s[22] + s[23];
|
||||
float k13 = s[21] + s[29];
|
||||
float s0 = s[0];
|
||||
float s1 = s[1];
|
||||
float s2 = s[2];
|
||||
float s3 = s[3];
|
||||
float s4 = s[4];
|
||||
float s6 = s[6];
|
||||
float s7 = s[7];
|
||||
float s8 = s[8];
|
||||
float s12 = s[12];
|
||||
float s13 = s[13];
|
||||
float s14 = s[14];
|
||||
float s15 = s[15];
|
||||
float s16 = s[16];
|
||||
float s18 = s[18];
|
||||
float s19 = s[19];
|
||||
float s21 = s[21];
|
||||
float s22 = s[22];
|
||||
float s23 = s[23];
|
||||
float s28 = s[28];
|
||||
float s29 = s[29];
|
||||
float s30 = s[30];
|
||||
float s31 = s[31];
|
||||
s[0] = s1;
|
||||
s[1] = k2;
|
||||
s[2] = k5;
|
||||
s[3] = k3;
|
||||
s[4] = k6;
|
||||
s[5] = k8 + k13;
|
||||
s[6] = k4 + s13;
|
||||
s[7] = k9 + s29;
|
||||
s[8] = s3;
|
||||
s[9] = k9;
|
||||
s[10] = k4;
|
||||
s[11] = k8;
|
||||
s[12] = s7;
|
||||
s[13] = k7;
|
||||
s[14] = s15;
|
||||
s[15] = s31;
|
||||
s[16] = -k2 - s30;
|
||||
s[17] = -k5 - s14;
|
||||
s[18] = -k3 - s22 - s30;
|
||||
s[19] = -k6 - s6;
|
||||
s[20] = k10 - s29 - s21 - s22 - s23;
|
||||
s[21] = k0 - s13;
|
||||
s[22] = k10 - s29 - s18 - s19;
|
||||
s[23] = -s3 - s2;
|
||||
s[24] = k10 - s28 - s18 - s19;
|
||||
s[25] = k0 - s12;
|
||||
s[26] = k10 - s28 - k12;
|
||||
s[27] = -s6 - s7 - s4;
|
||||
s[28] = k11 - k12;
|
||||
s[29] = -s14 - s15 - s12 - s8;
|
||||
s[30] = k11 - s16;
|
||||
s[31] = -s0;
|
||||
}
|
||||
|
||||
private static void butterfly16H(float[] s) {
|
||||
for (int i = 0; i < 8; i++) {
|
||||
float tmp0 = s[16 + i];
|
||||
float tmp1 = s[31 - i];
|
||||
s[16 + i] = tmp0 + tmp1;
|
||||
s[31 - i] = -(tmp0 - tmp1) * bf16[i];
|
||||
}
|
||||
}
|
||||
|
||||
private static void butterfly16L(float[] s) {
|
||||
for (int i = 0; i < 8; i++) {
|
||||
float tmp0 = s[i];
|
||||
float tmp1 = s[15 - i];
|
||||
s[i] = tmp0 + tmp1;
|
||||
s[15 - i] = (tmp0 - tmp1) * bf16[i];
|
||||
}
|
||||
}
|
||||
|
||||
private static void butterfly8H(float[] s, int o) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
float tmp0 = s[o + 8 + i];
|
||||
float tmp1 = s[o + 15 - i];
|
||||
s[o + 8 + i] = tmp0 + tmp1;
|
||||
s[o + 15 - i] = -(tmp0 - tmp1) * bf8[i];
|
||||
}
|
||||
}
|
||||
|
||||
private static void butterfly8L(float[] s, int o) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
float tmp0 = s[o + i];
|
||||
float tmp1 = s[o + 7 - i];
|
||||
s[o + i] = tmp0 + tmp1;
|
||||
s[o + 7 - i] = (tmp0 - tmp1) * bf8[i];
|
||||
}
|
||||
}
|
||||
|
||||
private static void butterfly4H(float[] s, int o) {
|
||||
float tmp0 = s[o + 4];
|
||||
float tmp1 = s[o + 7];
|
||||
s[o + 4] = tmp0 + tmp1;
|
||||
s[o + 7] = -(tmp0 - tmp1) * cos1_8;
|
||||
float tmp2 = s[o + 5];
|
||||
float tmp3 = s[o + 6];
|
||||
s[o + 5] = tmp2 + tmp3;
|
||||
s[o + 6] = -(tmp2 - tmp3) * cos3_8;
|
||||
}
|
||||
|
||||
private static void butterfly4L(float[] s, int o) {
|
||||
float tmp0 = s[o];
|
||||
float tmp1 = s[o + 3];
|
||||
s[o + 0] = tmp0 + tmp1;
|
||||
s[o + 3] = (tmp0 - tmp1) * cos1_8;
|
||||
float tmp2 = s[o + 1];
|
||||
float tmp3 = s[o + 2];
|
||||
s[o + 1] = tmp2 + tmp3;
|
||||
s[o + 2] = (tmp2 - tmp3) * cos3_8;
|
||||
}
|
||||
|
||||
private static void butterfly2H(float[] s, int o) {
|
||||
float tmp0 = s[o + 2];
|
||||
float tmp1 = s[o + 3];
|
||||
s[o + 2] = tmp0 + tmp1;
|
||||
s[o + 3] = -(tmp0 - tmp1) * cos1_4;
|
||||
}
|
||||
|
||||
private static void butterfly2L(float[] s, int o) {
|
||||
float tmp0 = s[o];
|
||||
float tmp1 = s[o + 1];
|
||||
s[o + 0] = tmp0 + tmp1;
|
||||
s[o + 1] = (tmp0 - tmp1) * cos1_4;
|
||||
}
|
||||
|
||||
private static void butterfly32(float[] s) {
|
||||
for (int i = 0; i < 16; i++) {
|
||||
float tmp0 = s[i];
|
||||
float tmp1 = s[31 - i];
|
||||
s[i] = tmp0 + tmp1;
|
||||
s[31 - i] = (tmp0 - tmp1) * bf32[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue