Vorbis audio packet decoder progress, Vorbis codebook progress

This commit is contained in:
Alex Iadicicco 2022-12-08 04:27:53 -08:00 committed by Alexis King
parent 073f29c3b0
commit 058b140b28
6 changed files with 358 additions and 407 deletions

View File

@ -18,9 +18,9 @@ public final class Synth {
private static final int[] harmFreqMin_idk; private static final int[] harmFreqMin_idk;
static { static {
final Random var0 = new Random(0L); final Random rng = new Random(0L);
for (int i = 0; i < 0x8000; ++i) { for (int i = 0; i < 0x8000; ++i) {
NOISE[i] = (var0.nextInt() & 2) - 1; NOISE[i] = (rng.nextInt() & 2) - 1;
} }
for (int i = 0; i < 0x8000; ++i) { for (int i = 0; i < 0x8000; ++i) {
SINE[i] = (int) (Math.sin((double) i * Math.PI / 0x4000) * 0x4000); SINE[i] = (int) (Math.sin((double) i * Math.PI / 0x4000) * 0x4000);

View File

@ -7,7 +7,7 @@ public final class VorbisCodebook {
private final int cbSize; private final int cbSize;
private final int[] cwLengths; private final int[] cwLengths;
private float[][] vectors; private float[][] vectors;
private int[] _f; private int[] tree;
public VorbisCodebook() { public VorbisCodebook() {
VorbisFormat.readBits(24); VorbisFormat.readBits(24);
@ -37,7 +37,7 @@ public final class VorbisCodebook {
} }
} }
this.b797(); this.initHuffmanTree();
int lookupTableType = VorbisFormat.readBits(4); int lookupTableType = VorbisFormat.readBits(4);
if (lookupTableType > 0) { if (lookupTableType > 0) {
@ -104,60 +104,55 @@ public final class VorbisCodebook {
private static int pow(int base, int exp) { private static int pow(int base, int exp) {
int res; int res;
for (res = 1; exp > 1; base *= base) { for (res = 1; exp > 1; base *= base) {
if ((exp & 1) != 0) { if ((exp & 1) != 0) {
res *= base; res *= base;
} }
exp >>= 1; exp >>= 1;
} }
return exp == 1 ? res * base : res;
if (exp == 1) {
return res * base;
} else {
return res;
}
} }
public float[] c932() { public float[] decodeVector() {
return this.vectors[this.a784()]; return this.vectors[this.decodeScalar()];
} }
public int a784() { public int decodeScalar() {
int var1 = 0; int i = 0;
while (this._f[var1] >= 0) { while (this.tree[i] >= 0) {
var1 = VorbisFormat.readBit() != 0 ? this._f[var1] : var1 + 1; i = VorbisFormat.readBit() != 0 ? this.tree[i] : i + 1;
} }
return ~this._f[var1]; return ~this.tree[i];
} }
private void b797() { private void initHuffmanTree() {
final int[] var1 = new int[this.cbSize]; final int[] var1 = new int[this.cbSize];
final int[] var2 = new int[33]; final int[] var2 = new int[33];
int var4;
int var5; int var5;
int var6; int var6;
int var7;
int var10;
for (int i = 0; i < this.cbSize; ++i) { for (int i = 0; i < this.cbSize; ++i) {
var4 = this.cwLengths[i]; int cwLength = this.cwLengths[i];
if (var4 != 0) { if (cwLength == 0) {
var5 = 1 << 32 - var4; continue;
var6 = var2[var4]; }
var5 = 1 << 32 - cwLength;
var6 = var2[cwLength];
var1[i] = var6; var1[i] = var6;
int var9; int var9;
int var7;
if ((var6 & var5) == 0) { if ((var6 & var5) == 0) {
var7 = var6 | var5; var7 = var6 | var5;
for (int j = var4 - 1; j >= 1; --j) { for (int j = cwLength - 1; j >= 1; --j) {
var9 = var2[j]; var9 = var2[j];
if (var9 != var6) { if (var9 != var6) {
break; break;
} }
var10 = 1 << 32 - j; int var10 = 1 << 32 - j;
if ((var9 & var10) != 0) { if ((var9 & var10) != 0) {
var2[j] = var2[j - 1]; var2[j] = var2[j - 1];
break; break;
@ -166,59 +161,57 @@ public final class VorbisCodebook {
var2[j] = var9 | var10; var2[j] = var9 | var10;
} }
} else { } else {
var7 = var2[var4 - 1]; var7 = var2[cwLength - 1];
} }
var2[var4] = var7; var2[cwLength] = var7;
for (int j = var4 + 1; j <= 32; ++j) { for (int j = cwLength + 1; j <= 32; ++j) {
var9 = var2[j]; var9 = var2[j];
if (var9 == var6) { if (var9 == var6) {
var2[j] = var7; var2[j] = var7;
} }
} }
} }
}
this._f = new int[8]; this.tree = new int[8];
int var11 = 0; int var11 = 0;
for (int i = 0; i < this.cbSize; ++i) { for (int i = 0; i < this.cbSize; ++i) {
var4 = this.cwLengths[i]; int len = this.cwLengths[i];
if (var4 != 0) { if (len == 0) {
continue;
}
var5 = var1[i]; var5 = var1[i];
var6 = 0; var6 = 0;
for (var7 = 0; var7 < var4; ++var7) { for (int j = 0; j < len; ++j) {
int var8 = Integer.MIN_VALUE >>> var7; int var8 = Integer.MIN_VALUE >>> j;
if ((var5 & var8) == 0) { if ((var5 & var8) == 0) {
++var6; ++var6;
} else { } else {
if (this._f[var6] == 0) { if (this.tree[var6] == 0) {
this._f[var6] = var11; this.tree[var6] = var11;
} }
var6 = this._f[var6]; var6 = this.tree[var6];
} }
if (var6 >= this._f.length) { if (var6 >= this.tree.length) {
final int[] var12 = new int[this._f.length * 2]; final int[] newTree = new int[this.tree.length * 2];
for (int k = 0; k < this.tree.length; ++k) {
for (var10 = 0; var10 < this._f.length; ++var10) { newTree[k] = this.tree[k];
var12[var10] = this._f[var10]; }
this.tree = newTree;
}
} }
this._f = var12; this.tree[var6] = ~i;
}
}
this._f[var6] = ~i;
if (var6 >= var11) { if (var6 >= var11) {
var11 = var6 + 1; var11 = var6 + 1;
} }
} }
}
} }
} }

View File

@ -206,12 +206,12 @@ public final class VorbisFloor1 {
final int cSub = (1 << cBits) - 1; final int cSub = (1 << cBits) - 1;
int cVal = 0; int cVal = 0;
if (cBits > 0) { if (cBits > 0) {
cVal = VorbisFormat.codebooks[this.classMasterbooks[cls]].a784(); cVal = VorbisFormat.codebooks[this.classMasterbooks[cls]].decodeScalar();
} }
for (int i = 0; i < cDim; ++i) { for (int i = 0; i < cDim; ++i) {
final int book = this.subclassBooks[cls][cVal & cSub]; final int book = this.subclassBooks[cls][cVal & cSub];
cVal >>>= cBits; cVal >>>= cBits;
floorY[offset++] = book >= 0 ? VorbisFormat.codebooks[book].a784() : 0; floorY[offset++] = book >= 0 ? VorbisFormat.codebooks[book].decodeScalar() : 0;
} }
} }

View File

@ -9,23 +9,23 @@ import java.util.stream.IntStream;
public final class VorbisFormat { public final class VorbisFormat {
public static VorbisCodebook[] codebooks; public static VorbisCodebook[] codebooks;
private static float[] _k; private static float[] window;
private static VorbisResidues[] residues; private static VorbisResidue[] residues;
private static int[] modeMapping; private static int[] modeMapping;
private static int[] _D; private static int[] blocksize0Invbit;
private static VorbisMapping[] mappings; private static VorbisMapping[] mappings;
private static float[] _u; private static float[] blocksize1Tbl3;
private static float[] _C; private static float[] blocksize0Tbl3;
private static boolean setupFinished_idk = false; private static boolean setupFinished_idk = false;
private static byte[] buffer; private static byte[] buffer;
private static float[] _z; private static float[] blocksize0Tbl2;
private static boolean[] modeBlockFlag; private static boolean[] modeBlockFlag;
private static float[] _y; private static float[] blocksize1Tbl2;
private static float[] _j; private static float[] blocksize1Tbl1;
private static int blocksize1; private static int blocksize1;
private static float[] _l; private static float[] blocksize0Tbl1;
private static int curBit; private static int curBit;
private static int[] _F; private static int[] blocksize1Invbit;
private static int blocksize0; private static int blocksize0;
private static VorbisFloor1[] floors; private static VorbisFloor1[] floors;
private static int curByte; private static int curByte;
@ -33,14 +33,14 @@ public final class VorbisFormat {
private int loopEnd; private int loopEnd;
private boolean isLooped; private boolean isLooped;
private int loopStart; private int loopStart;
private int _i; private int lastWindowStart;
private int outputOffset; private int outputOffset;
private boolean _A; private boolean lastWindowZero;
private byte[][] packets; private byte[][] packets;
private int _M; private int lastWindowN;
private int sampleRate; private int sampleRate;
private byte[] sampleData; private byte[] sampleData;
private float[] prevWindow; private float[] lastWindow;
private int packet; private int packet;
private VorbisFormat(final byte[] data) throws IOException { private VorbisFormat(final byte[] data) throws IOException {
@ -69,47 +69,45 @@ public final class VorbisFormat {
setCurrentPacket(section); setCurrentPacket(section);
blocksize0 = 1 << readBits(4); blocksize0 = 1 << readBits(4);
blocksize1 = 1 << readBits(4); blocksize1 = 1 << readBits(4);
_k = new float[blocksize1]; window = new float[blocksize1];
for (int i = 0; i < 2; ++i) { for (int i = 0; i < 2; ++i) {
int var2 = i != 0 ? blocksize1 : blocksize0; int n = i == 0 ? blocksize0 : blocksize1;
int var3 = var2 >> 1; int n2 = n >> 1;
int var4 = var2 >> 2; int n4 = n >> 2;
int var5 = var2 >> 3; int n8 = n >> 3;
final float[] var6 = new float[var3];
for (int var7 = 0; var7 < var4; ++var7) { final float[] tbl1 = new float[n2];
var6[2 * var7] = (float) Math.cos((double) (4 * var7) * Math.PI / (double) var2); for (int j = 0; j < n4; ++j) {
var6[2 * var7 + 1] = -((float) Math.sin((double) (4 * var7) * Math.PI / (double) var2)); tbl1[2 * j] = (float) Math.cos((double) (4 * j) * Math.PI / (double) n);
tbl1[2 * j + 1] = -((float) Math.sin((double) (4 * j) * Math.PI / (double) n));
} }
final float[] var13 = new float[var3]; final float[] tbl2 = new float[n2];
for (int j = 0; j < n4; ++j) {
for (int var8 = 0; var8 < var4; ++var8) { tbl2[2 * j] = (float) Math.cos((double) (2 * j + 1) * Math.PI / (double) (2 * n));
var13[2 * var8] = (float) Math.cos((double) (2 * var8 + 1) * Math.PI / (double) (2 * var2)); tbl2[2 * j + 1] = (float) Math.sin((double) (2 * j + 1) * Math.PI / (double) (2 * n));
var13[2 * var8 + 1] = (float) Math.sin((double) (2 * var8 + 1) * Math.PI / (double) (2 * var2));
} }
final float[] var14 = new float[var4]; final float[] tbl3 = new float[n4];
for (int j = 0; j < n8; ++j) {
for (int var9 = 0; var9 < var5; ++var9) { tbl3[2 * j] = (float) Math.cos((double) (4 * j + 2) * Math.PI / (double) n);
var14[2 * var9] = (float) Math.cos((double) (4 * var9 + 2) * Math.PI / (double) var2); tbl3[2 * j + 1] = -((float) Math.sin((double) (4 * j + 2) * Math.PI / (double) n));
var14[2 * var9 + 1] = -((float) Math.sin((double) (4 * var9 + 2) * Math.PI / (double) var2));
} }
final int var10 = BitMath.lastSet(var5 - 1); final int bits = BitMath.lastSet(n8 - 1);
final int[] var15 = IntStream.range(0, var5).map(var11 -> reverseBits(var11, var10)).toArray(); final int[] invbit = IntStream.range(0, n8).map(j -> reverseBits(j, bits)).toArray();
if (i == 0) { if (i == 0) {
_l = var6; blocksize0Tbl1 = tbl1;
_z = var13; blocksize0Tbl2 = tbl2;
_C = var14; blocksize0Tbl3 = tbl3;
_D = var15; blocksize0Invbit = invbit;
} else { } else {
_j = var6; blocksize1Tbl1 = tbl1;
_y = var13; blocksize1Tbl2 = tbl2;
_u = var14; blocksize1Tbl3 = tbl3;
_F = var15; blocksize1Invbit = invbit;
} }
} }
@ -131,9 +129,9 @@ public final class VorbisFormat {
} }
int numResidues = readBits(6) + 1; int numResidues = readBits(6) + 1;
residues = new VorbisResidues[numResidues]; residues = new VorbisResidue[numResidues];
for (int i = 0; i < numResidues; ++i) { for (int i = 0; i < numResidues; ++i) {
residues[i] = new VorbisResidues(); residues[i] = new VorbisResidue();
} }
int numMappings = readBits(6) + 1; int numMappings = readBits(6) + 1;
@ -248,8 +246,8 @@ public final class VorbisFormat {
public RawSampleS8 toRawSample() { public RawSampleS8 toRawSample() {
if (this.sampleData == null) { if (this.sampleData == null) {
this._M = 0; this.lastWindowN = 0;
this.prevWindow = new float[blocksize1]; this.lastWindow = new float[blocksize1];
this.sampleData = new byte[this.sampleLength]; this.sampleData = new byte[this.sampleLength];
this.outputOffset = 0; this.outputOffset = 0;
this.packet = 0; this.packet = 0;
@ -274,7 +272,7 @@ public final class VorbisFormat {
} }
} }
this.prevWindow = null; this.lastWindow = null;
final byte[] sampleData = this.sampleData; final byte[] sampleData = this.sampleData;
this.sampleData = null; this.sampleData = null;
return new RawSampleS8(this.sampleRate, sampleData, this.loopStart, this.loopEnd, this.isLooped); return new RawSampleS8(this.sampleRate, sampleData, this.loopStart, this.loopEnd, this.isLooped);
@ -323,210 +321,184 @@ public final class VorbisFormat {
rightN = n >> 1; rightN = n >> 1;
} }
// compute spectrum
final VorbisMapping mapping = mappings[modeMapping[modeNumber]]; final VorbisMapping mapping = mappings[modeMapping[modeNumber]];
final boolean var15 = !floors[mapping.floor[mapping.mux]].decode(); final boolean thisWindowZero = !floors[mapping.floor[mapping.mux]].decode();
for (int i = 0; i < mapping.submaps; ++i) { for (int i = 0; i < mapping.submaps; ++i) {
final VorbisResidues residue = residues[mapping.residues[i]]; residues[mapping.residues[i]].computeResidue(window, n >> 1, thisWindowZero);
final float[] var19 = _k; }
residue.a623(var19, n >> 1, var15); if (!thisWindowZero) {
floors[mapping.floor[mapping.mux]].computeCurve(window, n >> 1);
} }
if (!var15) { // mdct and windowing
floors[mapping.floor[mapping.mux]].computeCurve(_k, n >> 1); if (thisWindowZero) {
} for (int i = n >> 1; i < n; ++i) {
window[i] = 0.0F;
int var42;
if (var15) {
for (int var17 = n >> 1; var17 < n; ++var17) {
_k[var17] = 0.0F;
} }
} else { } else {
final int i = n >> 1; final int n2 = n >> 1;
int var41 = n >> 2; final int n4 = n >> 2;
var42 = n >> 3; final int n8 = n >> 3;
final float[] var20 = _k; final float[] v = window;
int var21; for (int i = 0; i < n2; ++i) {
for (var21 = 0; var21 < i; ++var21) { v[i] *= 0.5F;
var20[var21] *= 0.5F; }
for (int i = n2; i < n; ++i) {
v[i] = -v[n - i - 1];
} }
for (var21 = i; var21 < n; ++var21) { final float[] tbl1 = isLongWindow ? blocksize1Tbl1 : blocksize0Tbl1;
var20[var21] = -var20[n - var21 - 1]; final float[] tbl2 = isLongWindow ? blocksize1Tbl2 : blocksize0Tbl2;
final float[] tbl3 = isLongWindow ? blocksize1Tbl3 : blocksize0Tbl3;
final int[] invbit = isLongWindow ? blocksize1Invbit : blocksize0Invbit;
for (int i = 0; i < n4; ++i) {
final float a = v[4 * i] - v[n - 4 * i - 1];
final float b = v[4 * i + 2] - v[n - 4 * i - 3];
final float c = tbl1[2 * i];
final float d = tbl1[2 * i + 1];
v[n - 4 * i - 1] = a * c - b * d;
v[n - 4 * i - 3] = a * d + b * c;
} }
final float[] var46 = isLongWindow ? _j : _l; for (int i = 0; i < n8; ++i) {
final float[] var22 = isLongWindow ? _y : _z; final float a = v[n2 + 3 + 4 * i];
final float[] var23 = isLongWindow ? _u : _C; final float b = v[n2 + 1 + 4 * i];
final int[] var24 = isLongWindow ? _F : _D; final float c = v[4 * i + 3];
final float d = v[4 * i + 1];
int var25; v[n2 + 3 + 4 * i] = a + c;
float var26; v[n2 + 1 + 4 * i] = b + d;
float var27; final float e = tbl1[n2 - 4 - 4 * i];
float var28; final float f = tbl1[n2 - 3 - 4 * i];
float var29; v[4 * i + 3] = (a - c) * e - (b - d) * f;
for (var25 = 0; var25 < var41; ++var25) { v[4 * i + 1] = (b - d) * e + (a - c) * f;
var26 = var20[4 * var25] - var20[n - 4 * var25 - 1];
var27 = var20[4 * var25 + 2] - var20[n - 4 * var25 - 3];
var28 = var46[2 * var25];
var29 = var46[2 * var25 + 1];
var20[n - 4 * var25 - 1] = var26 * var28 - var27 * var29;
var20[n - 4 * var25 - 3] = var26 * var29 + var27 * var28;
} }
float var30; int bits = BitMath.lastSet(n - 1);
float var31;
for (var25 = 0; var25 < var42; ++var25) {
var26 = var20[i + 3 + 4 * var25];
var27 = var20[i + 1 + 4 * var25];
var28 = var20[4 * var25 + 3];
var29 = var20[4 * var25 + 1];
var20[i + 3 + 4 * var25] = var26 + var28;
var20[i + 1 + 4 * var25] = var27 + var29;
var30 = var46[i - 4 - 4 * var25];
var31 = var46[i - 3 - 4 * var25];
var20[4 * var25 + 3] = (var26 - var28) * var30 - (var27 - var29) * var31;
var20[4 * var25 + 1] = (var27 - var29) * var30 + (var26 - var28) * var31;
}
var25 = BitMath.lastSet(n - 1); for (int i = 0; i < bits - 3; ++i) {
final int nI = n >> i + 2;
final int coeff = 8 << i;
int var47; for (int j = 0; j < 2 << i; ++j) {
int var48; final int i0 = n - nI * 2 * j;
int var49; final int i1 = n - nI * (2 * j + 1);
int var50;
for (var47 = 0; var47 < var25 - 3; ++var47) {
var48 = n >> var47 + 2;
var49 = 8 << var47;
for (var50 = 0; var50 < 2 << var47; ++var50) { for (int k = 0; k < n >> i + 4; ++k) {
final int var51 = n - var48 * 2 * var50; final int k4 = 4 * k;
final int var52 = n - var48 * (2 * var50 + 1); final float a = v[i0 - 1 - k4];
final float b = v[i0 - 3 - k4];
for (int var32 = 0; var32 < n >> var47 + 4; ++var32) { final float c = v[i1 - 1 - k4];
final int var33 = 4 * var32; final float d = v[i1 - 3 - k4];
final float var34 = var20[var51 - 1 - var33]; v[i0 - 1 - k4] = a + c;
final float var35 = var20[var51 - 3 - var33]; v[i0 - 3 - k4] = b + d;
final float var36 = var20[var52 - 1 - var33]; final float e = tbl1[k * coeff];
final float var37 = var20[var52 - 3 - var33]; final float f = tbl1[k * coeff + 1];
var20[var51 - 1 - var33] = var34 + var36; v[i1 - 1 - k4] = (a - c) * e - (b - d) * f;
var20[var51 - 3 - var33] = var35 + var37; v[i1 - 3 - k4] = (b - d) * e + (a - c) * f;
final float var38 = var46[var32 * var49];
final float var39 = var46[var32 * var49 + 1];
var20[var52 - 1 - var33] = (var34 - var36) * var38 - (var35 - var37) * var39;
var20[var52 - 3 - var33] = (var35 - var37) * var38 + (var34 - var36) * var39;
} }
} }
} }
for (var47 = 1; var47 < var42 - 1; ++var47) { for (int i = 1; i < n8 - 1; ++i) {
var48 = var24[var47]; final int j = invbit[i];
if (var47 < var48) { if (i < j) {
var49 = 8 * var47; final int i8 = 8 * i;
var50 = 8 * var48; final int j8 = 8 * j;
var30 = var20[var49 + 1]; float a;
var20[var49 + 1] = var20[var50 + 1]; a = v[i8 + 1];
var20[var50 + 1] = var30; v[i8 + 1] = v[j8 + 1];
var30 = var20[var49 + 3]; v[j8 + 1] = a;
var20[var49 + 3] = var20[var50 + 3]; a = v[i8 + 3];
var20[var50 + 3] = var30; v[i8 + 3] = v[j8 + 3];
var30 = var20[var49 + 5]; v[j8 + 3] = a;
var20[var49 + 5] = var20[var50 + 5]; a = v[i8 + 5];
var20[var50 + 5] = var30; v[i8 + 5] = v[j8 + 5];
var30 = var20[var49 + 7]; v[j8 + 5] = a;
var20[var49 + 7] = var20[var50 + 7]; a = v[i8 + 7];
var20[var50 + 7] = var30; v[i8 + 7] = v[j8 + 7];
v[j8 + 7] = a;
} }
} }
for (var47 = 0; var47 < i; ++var47) { for (int i = 0; i < n2; ++i) {
var20[var47] = var20[2 * var47 + 1]; v[i] = v[2 * i + 1];
} }
for (var47 = 0; var47 < var42; ++var47) { for (int i = 0; i < n8; ++i) {
var20[n - 1 - 2 * var47] = var20[4 * var47]; v[n - 1 - 2 * i] = v[4 * i];
var20[n - 2 - 2 * var47] = var20[4 * var47 + 1]; v[n - 2 - 2 * i] = v[4 * i + 1];
var20[n - var41 - 1 - 2 * var47] = var20[4 * var47 + 2]; v[n - n4 - 1 - 2 * i] = v[4 * i + 2];
var20[n - var41 - 2 - 2 * var47] = var20[4 * var47 + 3]; v[n - n4 - 2 - 2 * i] = v[4 * i + 3];
} }
for (var47 = 0; var47 < var42; ++var47) { for (int i = 0; i < n8; ++i) {
var27 = var23[2 * var47]; final float a = tbl3[2 * i];
var28 = var23[2 * var47 + 1]; final float b = tbl3[2 * i + 1];
var29 = var20[i + 2 * var47]; final float c = v[n2 + 2 * i];
var30 = var20[i + 2 * var47 + 1]; final float d = v[n2 + 2 * i + 1];
var31 = var20[n - 2 - 2 * var47]; final float e = v[n - 2 - 2 * i];
final float var53 = var20[n - 1 - 2 * var47]; final float f = v[n - 1 - 2 * i];
final float var54 = var28 * (var29 - var31) + var27 * (var30 + var53); final float g = b * (c - e) + a * (d + f);
var20[i + 2 * var47] = (var29 + var31 + var54) * 0.5F; v[n2 + 2 * i] = (c + e + g) * 0.5F;
var20[n - 2 - 2 * var47] = (var29 + var31 - var54) * 0.5F; v[n - 2 - 2 * i] = (c + e - g) * 0.5F;
final float v = var28 * (var30 + var53) - var27 * (var29 - var31); final float h = b * (d + f) - a * (c - e);
var20[i + 2 * var47 + 1] = (var30 - var53 + v) * 0.5F; v[n2 + 2 * i + 1] = (d - f + h) * 0.5F;
var20[n - 1 - 2 * var47] = (-var30 + var53 + v) * 0.5F; v[n - 1 - 2 * i] = (-d + f + h) * 0.5F;
} }
for (var47 = 0; var47 < var41; ++var47) { for (int i = 0; i < n4; ++i) {
var20[var47] = var20[2 * var47 + i] * var22[2 * var47] + var20[2 * var47 + 1 + i] * var22[2 * var47 + 1]; v[i] = v[2 * i + n2] * tbl2[2 * i] + v[2 * i + 1 + n2] * tbl2[2 * i + 1];
var20[i - 1 - var47] = var20[2 * var47 + i] * var22[2 * var47 + 1] - var20[2 * var47 + 1 + i] * var22[2 * var47]; v[n2 - 1 - i] = v[2 * i + n2] * tbl2[2 * i + 1] - v[2 * i + 1 + n2] * tbl2[2 * i];
}
for (int i = 0; i < n4; ++i) {
v[n - n4 + i] = -v[i];
}
for (int i = 0; i < n4; ++i) {
v[i] = v[n4 + i];
}
for (int i = 0; i < n4; ++i) {
v[n4 + i] = -v[n4 - i - 1];
}
for (int i = 0; i < n4; ++i) {
v[n2 + i] = v[n - i - 1];
} }
for (var47 = 0; var47 < var41; ++var47) { for (int i = leftWindowStart; i < leftWindowEnd; ++i) {
var20[n - var41 + var47] = -var20[var47]; final float a = (float) Math.sin(((double) (i - leftWindowStart) + 0.5D) / (double) leftN * 0.5D * Math.PI);
window[i] *= (float) Math.sin(1.5707963267948966D * (double) a * (double) a);
} }
for (var47 = 0; var47 < var41; ++var47) { for (int i = rightWindowStart; i < rightWindowEnd; ++i) {
var20[var47] = var20[var41 + var47]; final float a = (float) Math.sin(((double) (i - rightWindowStart) + 0.5D) / (double) rightN * 0.5D * Math.PI + (Math.PI / 2));
} window[i] *= (float) Math.sin(1.5707963267948966D * (double) a * (double) a);
for (var47 = 0; var47 < var41; ++var47) {
var20[var41 + var47] = -var20[var41 - var47 - 1];
}
for (var47 = 0; var47 < var41; ++var47) {
var20[i + var47] = var20[n - var47 - 1];
}
float[] var10000;
for (var47 = leftWindowStart; var47 < leftWindowEnd; ++var47) {
var27 = (float) Math.sin(((double) (var47 - leftWindowStart) + 0.5D) / (double) leftN * 0.5D * Math.PI);
var10000 = _k;
var10000[var47] *= (float) Math.sin(1.5707963267948966D * (double) var27 * (double) var27);
}
for (var47 = rightWindowStart; var47 < rightWindowEnd; ++var47) {
var27 = (float) Math.sin(((double) (var47 - rightWindowStart) + 0.5D) / (double) rightN * 0.5D * Math.PI + (Math.PI / 2));
var10000 = _k;
var10000[var47] *= (float) Math.sin(1.5707963267948966D * (double) var27 * (double) var27);
} }
} }
float[] var43 = null; // lapping
if (this._M > 0) { float[] output = null;
var43 = new float[this._M + n >> 2]; if (this.lastWindowN > 0) {
int var45; output = new float[this.lastWindowN + n >> 2];
if (!this._A) { if (!this.lastWindowZero) {
for (var42 = 0; var42 < this._i; ++var42) { for (int i = 0; i < this.lastWindowStart; ++i) {
var45 = (this._M >> 1) + var42; output[i] += this.lastWindow[(this.lastWindowN >> 1) + i];
var43[var42] += this.prevWindow[var45];
} }
} }
if (!thisWindowZero) {
if (!var15) { for (int i = leftWindowStart; i < n >> 1; ++i) {
for (var42 = leftWindowStart; var42 < n >> 1; ++var42) { output[output.length - (n >> 1) + i] += window[i];
var45 = var43.length - (n >> 1) + var42;
var43[var45] += _k[var42];
} }
} }
} }
final float[] var44 = this.prevWindow; this.lastWindow = window;
this.prevWindow = _k; this.lastWindowN = n;
_k = var44; this.lastWindowStart = rightWindowEnd - (n >> 1);
this._M = n; this.lastWindowZero = thisWindowZero;
this._i = rightWindowEnd - (n >> 1);
this._A = var15; return output;
return var43;
} }
private void load(final byte[] data) throws IOException { private void load(final byte[] data) throws IOException {
@ -560,8 +532,8 @@ public final class VorbisFormat {
} }
public void b720() { public void b720() {
this._M = 0; this.lastWindowN = 0;
this.prevWindow = new float[blocksize1]; this.lastWindow = new float[blocksize1];
for (int i = 0; i < this.packets.length; ++i) { for (int i = 0; i < this.packets.length; ++i) {
this.decodeAudioPacket(i); this.decodeAudioPacket(i);
} }

View File

@ -0,0 +1,98 @@
package funorb.audio;
public final class VorbisResidue {
// vorbis spec uses a [resClassifications][8] array of ints, but resBook
// is a flattened array containing [resClassifications*8] entries
private final int[] books;
private final int type;
private final int begin;
private final int end;
private final int partitionSize;
private final int classifications;
private final int classbook;
public VorbisResidue() {
this.type = VorbisFormat.readBits(16);
this.begin = VorbisFormat.readBits(24);
this.end = VorbisFormat.readBits(24);
this.partitionSize = VorbisFormat.readBits(24) + 1;
this.classifications = VorbisFormat.readBits(6) + 1;
this.classbook = VorbisFormat.readBits(8);
final int[] resCascade = new int[this.classifications];
for (int i = 0; i < this.classifications; ++i) {
int highBits = 0;
final int lowBits = VorbisFormat.readBits(3);
final boolean bitflag = VorbisFormat.readBit() != 0;
if (bitflag) {
highBits = VorbisFormat.readBits(5);
}
resCascade[i] = highBits << 3 | lowBits;
}
this.books = new int[this.classifications * 8];
for (int i = 0; i < this.classifications * 8; ++i) {
this.books[i] = (resCascade[i >> 3] & 1 << (i & 7)) != 0
? VorbisFormat.readBits(8)
: -1;
}
}
public void computeResidue(final float[] window, final int len, final boolean thisWindowZero) {
for (int i = 0; i < len; ++i) {
window[i] = 0.0F;
}
if (thisWindowZero) {
return;
}
final int cbDim = VorbisFormat.codebooks[this.classbook].cbDim;
final int range = this.end - this.begin;
final int numChunks = range / this.partitionSize;
final int[] classes = new int[numChunks];
for (int i = 0; i < 8; ++i) {
for (int chunk = 0; chunk < numChunks; ++chunk) {
if (i == 0) {
int value = VorbisFormat.codebooks[this.classbook].decodeScalar();
for (int j = cbDim - 1; j >= 0; --j) {
if (chunk + j < numChunks) {
classes[chunk + j] = value % this.classifications;
}
value /= this.classifications;
}
}
for (int dim = 0; dim < cbDim; ++dim) {
int cls = classes[chunk];
final int bookIndex = this.books[cls * 8 + i];
if (bookIndex < 0) {
continue;
}
final int offset = this.begin + chunk * this.partitionSize;
final VorbisCodebook book = VorbisFormat.codebooks[bookIndex];
if (this.type == 0) {
int n = this.partitionSize / book.cbDim;
for (int a = 0; a < n; ++a) {
final float[] var20 = book.decodeVector();
for (int b = 0; b < book.cbDim; ++b) {
window[offset + a + b * n] += var20[b];
}
}
} else {
for (int a = 0; a < this.partitionSize; ) {
final float[] var16 = book.decodeVector();
for (int b = 0; b < book.cbDim; ++b) {
window[offset + a] += var16[b];
++a;
}
}
}
}
}
}
}
}

View File

@ -1,112 +0,0 @@
package funorb.audio;
public final class VorbisResidues {
// vorbis spec uses a [resClassifications][8] array of ints, but resBook
// is a flattened array containing [resClassifications*8] entries
private final int[] resBooks;
private final int _c;
private final int resBegin;
private final int resEnd;
private final int resPartitionSize;
private final int resClassifications;
private final int resClassbook;
public VorbisResidues() {
this._c = VorbisFormat.readBits(16);
this.resBegin = VorbisFormat.readBits(24);
this.resEnd = VorbisFormat.readBits(24);
this.resPartitionSize = VorbisFormat.readBits(24) + 1;
this.resClassifications = VorbisFormat.readBits(6) + 1;
this.resClassbook = VorbisFormat.readBits(8);
final int[] resCascade = new int[this.resClassifications];
for (int i = 0; i < this.resClassifications; ++i) {
int highBits = 0;
final int lowBits = VorbisFormat.readBits(3);
final boolean bitflag = VorbisFormat.readBit() != 0;
if (bitflag) {
highBits = VorbisFormat.readBits(5);
}
resCascade[i] = highBits << 3 | lowBits;
}
this.resBooks = new int[this.resClassifications * 8];
for (int i = 0; i < this.resClassifications * 8; ++i) {
this.resBooks[i] = (resCascade[i >> 3] & 1 << (i & 7)) != 0
? VorbisFormat.readBits(8)
: -1;
}
}
public void a623(final float[] var1, final int var2, final boolean var3) {
int var4;
for (var4 = 0; var4 < var2; ++var4) {
var1[var4] = 0.0F;
}
if (!var3) {
var4 = VorbisFormat.codebooks[this.resClassbook].cbDim;
final int var5 = this.resEnd - this.resBegin;
final int var6 = var5 / this.resPartitionSize;
final int[] var7 = new int[var6];
for (int var8 = 0; var8 < 8; ++var8) {
int var9 = 0;
while (var9 < var6) {
int var10;
int var11;
if (var8 == 0) {
var10 = VorbisFormat.codebooks[this.resClassbook].a784();
for (var11 = var4 - 1; var11 >= 0; --var11) {
if (var9 + var11 < var6) {
var7[var9 + var11] = var10 % this.resClassifications;
}
var10 /= this.resClassifications;
}
}
for (var10 = 0; var10 < var4; ++var10) {
var11 = var7[var9];
final int var12 = this.resBooks[var11 * 8 + var8];
if (var12 >= 0) {
final int var13 = this.resBegin + var9 * this.resPartitionSize;
final VorbisCodebook var14 = VorbisFormat.codebooks[var12];
int var15;
if (this._c == 0) {
var15 = this.resPartitionSize / var14.cbDim;
for (int var19 = 0; var19 < var15; ++var19) {
final float[] var20 = var14.c932();
for (int var18 = 0; var18 < var14.cbDim; ++var18) {
var1[var13 + var19 + var18 * var15] += var20[var18];
}
}
} else {
var15 = 0;
while (var15 < this.resPartitionSize) {
final float[] var16 = var14.c932();
for (int var17 = 0; var17 < var14.cbDim; ++var17) {
var1[var13 + var15] += var16[var17];
++var15;
}
}
}
}
++var9;
if (var9 >= var6) {
break;
}
}
}
}
}
}
}