mirror of
https://git.zelz.net/catfoolyou/Project164.git
synced 2025-12-14 15:07:41 +00:00
250 errors
This commit is contained in:
118
src/lwjgl/java/com/jcraft/jzlib/Adler32.java
Normal file
118
src/lwjgl/java/com/jcraft/jzlib/Adler32.java
Normal file
@@ -0,0 +1,118 @@
|
||||
/* -*-mode:java; c-basic-offset:2; -*- */
|
||||
/*
|
||||
Copyright (c) 2000-2011 ymnk, JCraft,Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. The names of the authors may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
|
||||
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/*
|
||||
* This program is based on zlib-1.1.3, so all credit should go authors
|
||||
* Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
|
||||
* and contributors of zlib.
|
||||
*/
|
||||
|
||||
package com.jcraft.jzlib;
|
||||
|
||||
final public class Adler32 implements Checksum {
|
||||
|
||||
// largest prime smaller than 65536
|
||||
static final private int BASE=65521;
|
||||
// NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1
|
||||
static final private int NMAX=5552;
|
||||
|
||||
private long s1=1L;
|
||||
private long s2=0L;
|
||||
|
||||
public void reset(long init){
|
||||
s1=init&0xffff;
|
||||
s2=(init>>16)&0xffff;
|
||||
}
|
||||
|
||||
public void reset(){
|
||||
s1=1L;
|
||||
s2=0L;
|
||||
}
|
||||
|
||||
public long getValue(){
|
||||
return ((s2<<16)|s1);
|
||||
}
|
||||
|
||||
public void update(byte[] buf, int index, int len){
|
||||
|
||||
if(len==1){
|
||||
s1+=buf[index++]&0xff; s2+=s1;
|
||||
s1%=BASE;
|
||||
s2%=BASE;
|
||||
return;
|
||||
}
|
||||
|
||||
int len1 = len/NMAX;
|
||||
int len2 = len%NMAX;
|
||||
while(len1-->0) {
|
||||
int k=NMAX;
|
||||
len-=k;
|
||||
while(k-->0){
|
||||
s1+=buf[index++]&0xff; s2+=s1;
|
||||
}
|
||||
s1%=BASE;
|
||||
s2%=BASE;
|
||||
}
|
||||
|
||||
int k=len2;
|
||||
len-=k;
|
||||
while(k-->0){
|
||||
s1+=buf[index++]&0xff; s2+=s1;
|
||||
}
|
||||
s1%=BASE;
|
||||
s2%=BASE;
|
||||
}
|
||||
|
||||
public Adler32 copy(){
|
||||
Adler32 foo = new Adler32();
|
||||
foo.s1 = this.s1;
|
||||
foo.s2 = this.s2;
|
||||
return foo;
|
||||
}
|
||||
|
||||
// The following logic has come from zlib.1.2.
|
||||
static long combine(long adler1, long adler2, long len2){
|
||||
long BASEL = (long)BASE;
|
||||
long sum1;
|
||||
long sum2;
|
||||
long rem; // unsigned int
|
||||
|
||||
rem = len2 % BASEL;
|
||||
sum1 = adler1 & 0xffffL;
|
||||
sum2 = rem * sum1;
|
||||
sum2 %= BASEL; // MOD(sum2);
|
||||
sum1 += (adler2 & 0xffffL) + BASEL - 1;
|
||||
sum2 += ((adler1 >> 16) & 0xffffL) + ((adler2 >> 16) & 0xffffL) + BASEL - rem;
|
||||
if (sum1 >= BASEL) sum1 -= BASEL;
|
||||
if (sum1 >= BASEL) sum1 -= BASEL;
|
||||
if (sum2 >= (BASEL << 1)) sum2 -= (BASEL << 1);
|
||||
if (sum2 >= BASEL) sum2 -= BASEL;
|
||||
return sum1 | (sum2 << 16);
|
||||
}
|
||||
|
||||
}
|
||||
157
src/lwjgl/java/com/jcraft/jzlib/CRC32.java
Normal file
157
src/lwjgl/java/com/jcraft/jzlib/CRC32.java
Normal file
@@ -0,0 +1,157 @@
|
||||
/* -*-mode:java; c-basic-offset:2; -*- */
|
||||
/*
|
||||
Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. The names of the authors may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
|
||||
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/*
|
||||
* This program is based on zlib-1.1.3, so all credit should go authors
|
||||
* Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
|
||||
* and contributors of zlib.
|
||||
*/
|
||||
|
||||
package com.jcraft.jzlib;
|
||||
|
||||
final public class CRC32 implements Checksum {
|
||||
|
||||
/*
|
||||
* The following logic has come from RFC1952.
|
||||
*/
|
||||
private int v = 0;
|
||||
private static int[] crc_table = null;
|
||||
static {
|
||||
crc_table = new int[256];
|
||||
for (int n = 0; n < 256; n++) {
|
||||
int c = n;
|
||||
for (int k = 8; --k >= 0; ) {
|
||||
if ((c & 1) != 0)
|
||||
c = 0xedb88320 ^ (c >>> 1);
|
||||
else
|
||||
c = c >>> 1;
|
||||
}
|
||||
crc_table[n] = c;
|
||||
}
|
||||
}
|
||||
|
||||
public void update (byte[] buf, int index, int len) {
|
||||
int c = ~v;
|
||||
while (--len >= 0)
|
||||
c = crc_table[(c^buf[index++])&0xff]^(c >>> 8);
|
||||
v = ~c;
|
||||
}
|
||||
|
||||
public void reset(){
|
||||
v = 0;
|
||||
}
|
||||
|
||||
public void reset(long vv){
|
||||
v = (int)(vv&0xffffffffL);
|
||||
}
|
||||
|
||||
public long getValue(){
|
||||
return (long)(v&0xffffffffL);
|
||||
}
|
||||
|
||||
// The following logic has come from zlib.1.2.
|
||||
private static final int GF2_DIM = 32;
|
||||
static long combine(long crc1, long crc2, long len2){
|
||||
long row;
|
||||
long[] even = new long[GF2_DIM];
|
||||
long[] odd = new long[GF2_DIM];
|
||||
|
||||
// degenerate case (also disallow negative lengths)
|
||||
if (len2 <= 0)
|
||||
return crc1;
|
||||
|
||||
// put operator for one zero bit in odd
|
||||
odd[0] = 0xedb88320L; // CRC-32 polynomial
|
||||
row = 1;
|
||||
for (int n = 1; n < GF2_DIM; n++) {
|
||||
odd[n] = row;
|
||||
row <<= 1;
|
||||
}
|
||||
|
||||
// put operator for two zero bits in even
|
||||
gf2_matrix_square(even, odd);
|
||||
|
||||
// put operator for four zero bits in odd
|
||||
gf2_matrix_square(odd, even);
|
||||
|
||||
// apply len2 zeros to crc1 (first square will put the operator for one
|
||||
// zero byte, eight zero bits, in even)
|
||||
do {
|
||||
// apply zeros operator for this bit of len2
|
||||
gf2_matrix_square(even, odd);
|
||||
if ((len2 & 1)!=0)
|
||||
crc1 = gf2_matrix_times(even, crc1);
|
||||
len2 >>= 1;
|
||||
|
||||
// if no more bits set, then done
|
||||
if (len2 == 0)
|
||||
break;
|
||||
|
||||
// another iteration of the loop with odd and even swapped
|
||||
gf2_matrix_square(odd, even);
|
||||
if ((len2 & 1)!=0)
|
||||
crc1 = gf2_matrix_times(odd, crc1);
|
||||
len2 >>= 1;
|
||||
|
||||
// if no more bits set, then done
|
||||
} while (len2 != 0);
|
||||
|
||||
/* return combined crc */
|
||||
crc1 ^= crc2;
|
||||
return crc1;
|
||||
}
|
||||
|
||||
private static long gf2_matrix_times(long[] mat, long vec){
|
||||
long sum = 0;
|
||||
int index = 0;
|
||||
while (vec!=0) {
|
||||
if ((vec & 1)!=0)
|
||||
sum ^= mat[index];
|
||||
vec >>= 1;
|
||||
index++;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
static final void gf2_matrix_square(long[] square, long[] mat) {
|
||||
for (int n = 0; n < GF2_DIM; n++)
|
||||
square[n] = gf2_matrix_times(mat, mat[n]);
|
||||
}
|
||||
|
||||
public CRC32 copy(){
|
||||
CRC32 foo = new CRC32();
|
||||
foo.v = this.v;
|
||||
return foo;
|
||||
}
|
||||
|
||||
public static int[] getCRC32Table(){
|
||||
int[] tmp = new int[crc_table.length];
|
||||
System.arraycopy(crc_table, 0, tmp, 0, tmp.length);
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
43
src/lwjgl/java/com/jcraft/jzlib/Checksum.java
Normal file
43
src/lwjgl/java/com/jcraft/jzlib/Checksum.java
Normal file
@@ -0,0 +1,43 @@
|
||||
/* -*-mode:java; c-basic-offset:2; -*- */
|
||||
/*
|
||||
Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. The names of the authors may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
|
||||
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/*
|
||||
* This program is based on zlib-1.1.3, so all credit should go authors
|
||||
* Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
|
||||
* and contributors of zlib.
|
||||
*/
|
||||
|
||||
package com.jcraft.jzlib;
|
||||
|
||||
interface Checksum {
|
||||
void update(byte[] buf, int index, int len);
|
||||
void reset();
|
||||
void reset(long init);
|
||||
long getValue();
|
||||
Checksum copy();
|
||||
}
|
||||
1757
src/lwjgl/java/com/jcraft/jzlib/Deflate.java
Normal file
1757
src/lwjgl/java/com/jcraft/jzlib/Deflate.java
Normal file
File diff suppressed because it is too large
Load Diff
171
src/lwjgl/java/com/jcraft/jzlib/Deflater.java
Normal file
171
src/lwjgl/java/com/jcraft/jzlib/Deflater.java
Normal file
@@ -0,0 +1,171 @@
|
||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
|
||||
/*
|
||||
Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. The names of the authors may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
|
||||
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/*
|
||||
* This program is based on zlib-1.1.3, so all credit should go authors
|
||||
* Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
|
||||
* and contributors of zlib.
|
||||
*/
|
||||
|
||||
package com.jcraft.jzlib;
|
||||
|
||||
final public class Deflater extends ZStream{
|
||||
|
||||
static final private int MAX_WBITS=15; // 32K LZ77 window
|
||||
static final private int DEF_WBITS=MAX_WBITS;
|
||||
|
||||
static final private int Z_NO_FLUSH=0;
|
||||
static final private int Z_PARTIAL_FLUSH=1;
|
||||
static final private int Z_SYNC_FLUSH=2;
|
||||
static final private int Z_FULL_FLUSH=3;
|
||||
static final private int Z_FINISH=4;
|
||||
|
||||
static final private int MAX_MEM_LEVEL=9;
|
||||
|
||||
static final private int Z_OK=0;
|
||||
static final private int Z_STREAM_END=1;
|
||||
static final private int Z_NEED_DICT=2;
|
||||
static final private int Z_ERRNO=-1;
|
||||
static final private int Z_STREAM_ERROR=-2;
|
||||
static final private int Z_DATA_ERROR=-3;
|
||||
static final private int Z_MEM_ERROR=-4;
|
||||
static final private int Z_BUF_ERROR=-5;
|
||||
static final private int Z_VERSION_ERROR=-6;
|
||||
|
||||
private boolean finished = false;
|
||||
|
||||
public Deflater(){
|
||||
super();
|
||||
}
|
||||
|
||||
public Deflater(int level) throws GZIPException {
|
||||
this(level, MAX_WBITS);
|
||||
}
|
||||
|
||||
public Deflater(int level, boolean nowrap) throws GZIPException {
|
||||
this(level, MAX_WBITS, nowrap);
|
||||
}
|
||||
|
||||
public Deflater(int level, int bits) throws GZIPException {
|
||||
this(level, bits, false);
|
||||
}
|
||||
|
||||
public Deflater(int level, int bits, boolean nowrap) throws GZIPException {
|
||||
super();
|
||||
int ret = init(level, bits, nowrap);
|
||||
if(ret!=Z_OK)
|
||||
throw new GZIPException(ret+": "+msg);
|
||||
}
|
||||
|
||||
public Deflater(int level, int bits, int memlevel, JZlib.WrapperType wrapperType) throws GZIPException {
|
||||
super();
|
||||
int ret = init(level, bits, memlevel, wrapperType);
|
||||
if(ret!=Z_OK)
|
||||
throw new GZIPException(ret+": "+msg);
|
||||
}
|
||||
|
||||
public Deflater(int level, int bits, int memlevel) throws GZIPException {
|
||||
super();
|
||||
int ret = init(level, bits, memlevel);
|
||||
if(ret!=Z_OK)
|
||||
throw new GZIPException(ret+": "+msg);
|
||||
}
|
||||
|
||||
public int init(int level){
|
||||
return init(level, MAX_WBITS);
|
||||
}
|
||||
public int init(int level, boolean nowrap){
|
||||
return init(level, MAX_WBITS, nowrap);
|
||||
}
|
||||
public int init(int level, int bits){
|
||||
return init(level, bits, false);
|
||||
}
|
||||
public int init(int level, int bits, int memlevel, JZlib.WrapperType wrapperType){
|
||||
if(bits < 9 || bits > 15){
|
||||
return Z_STREAM_ERROR;
|
||||
}
|
||||
if(wrapperType == JZlib.W_NONE) {
|
||||
bits *= -1;
|
||||
}
|
||||
else if(wrapperType == JZlib.W_GZIP) {
|
||||
bits += 16;
|
||||
}
|
||||
else if(wrapperType == JZlib.W_ANY) {
|
||||
return Z_STREAM_ERROR;
|
||||
}
|
||||
else if(wrapperType == JZlib.W_ZLIB) {
|
||||
}
|
||||
return init(level, bits, memlevel);
|
||||
}
|
||||
public int init(int level, int bits, int memlevel){
|
||||
finished = false;
|
||||
dstate=new Deflate(this);
|
||||
return dstate.deflateInit(level, bits, memlevel);
|
||||
}
|
||||
public int init(int level, int bits, boolean nowrap){
|
||||
finished = false;
|
||||
dstate=new Deflate(this);
|
||||
return dstate.deflateInit(level, nowrap?-bits:bits);
|
||||
}
|
||||
|
||||
public int deflate(int flush){
|
||||
if(dstate==null){
|
||||
return Z_STREAM_ERROR;
|
||||
}
|
||||
int ret = dstate.deflate(flush);
|
||||
if(ret == Z_STREAM_END)
|
||||
finished = true;
|
||||
return ret;
|
||||
}
|
||||
public int end(){
|
||||
finished = true;
|
||||
if(dstate==null) return Z_STREAM_ERROR;
|
||||
int ret=dstate.deflateEnd();
|
||||
dstate=null;
|
||||
free();
|
||||
return ret;
|
||||
}
|
||||
public int params(int level, int strategy){
|
||||
if(dstate==null) return Z_STREAM_ERROR;
|
||||
return dstate.deflateParams(level, strategy);
|
||||
}
|
||||
public int setDictionary (byte[] dictionary, int dictLength){
|
||||
if(dstate == null)
|
||||
return Z_STREAM_ERROR;
|
||||
return dstate.deflateSetDictionary(dictionary, dictLength);
|
||||
}
|
||||
|
||||
public boolean finished(){
|
||||
return finished;
|
||||
}
|
||||
|
||||
public int copy(Deflater src){
|
||||
this.finished = src.finished;
|
||||
return Deflate.deflateCopy(this, src);
|
||||
}
|
||||
}
|
||||
181
src/lwjgl/java/com/jcraft/jzlib/DeflaterOutputStream.java
Normal file
181
src/lwjgl/java/com/jcraft/jzlib/DeflaterOutputStream.java
Normal file
@@ -0,0 +1,181 @@
|
||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
|
||||
/*
|
||||
Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. The names of the authors may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
|
||||
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package com.jcraft.jzlib;
|
||||
import java.io.*;
|
||||
|
||||
public class DeflaterOutputStream extends FilterOutputStream {
|
||||
|
||||
protected final Deflater deflater;
|
||||
|
||||
protected byte[] buffer;
|
||||
|
||||
private boolean closed = false;
|
||||
|
||||
private boolean syncFlush = false;
|
||||
|
||||
private final byte[] buf1 = new byte[1];
|
||||
|
||||
protected boolean mydeflater = false;
|
||||
|
||||
private boolean close_out = true;
|
||||
|
||||
protected static final int DEFAULT_BUFSIZE = 512;
|
||||
|
||||
public DeflaterOutputStream(OutputStream out) throws IOException {
|
||||
this(out,
|
||||
new Deflater(JZlib.Z_DEFAULT_COMPRESSION),
|
||||
DEFAULT_BUFSIZE, true);
|
||||
mydeflater = true;
|
||||
}
|
||||
|
||||
public DeflaterOutputStream(OutputStream out, Deflater def) throws IOException {
|
||||
this(out, def, DEFAULT_BUFSIZE, true);
|
||||
}
|
||||
|
||||
public DeflaterOutputStream(OutputStream out,
|
||||
Deflater deflater,
|
||||
int size) throws IOException {
|
||||
this(out, deflater, size, true);
|
||||
}
|
||||
public DeflaterOutputStream(OutputStream out,
|
||||
Deflater deflater,
|
||||
int size,
|
||||
boolean close_out) throws IOException {
|
||||
super(out);
|
||||
if (out == null || deflater == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
else if (size <= 0) {
|
||||
throw new IllegalArgumentException("buffer size must be greater than 0");
|
||||
}
|
||||
this.deflater = deflater;
|
||||
buffer = new byte[size];
|
||||
this.close_out = close_out;
|
||||
}
|
||||
|
||||
public void write(int b) throws IOException {
|
||||
buf1[0] = (byte)(b & 0xff);
|
||||
write(buf1, 0, 1);
|
||||
}
|
||||
|
||||
public void write(byte[] b, int off, int len) throws IOException {
|
||||
if (deflater.finished()) {
|
||||
throw new IOException("finished");
|
||||
}
|
||||
else if (off<0 | len<0 | off+len>b.length) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
else if (len == 0) {
|
||||
return;
|
||||
}
|
||||
else {
|
||||
int flush = syncFlush ? JZlib.Z_SYNC_FLUSH : JZlib.Z_NO_FLUSH;
|
||||
deflater.setInput(b, off, len, true);
|
||||
while (deflater.avail_in>0) {
|
||||
int err = deflate(flush);
|
||||
if (err == JZlib.Z_STREAM_END)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void finish() throws IOException {
|
||||
while (!deflater.finished()) {
|
||||
deflate(JZlib.Z_FINISH);
|
||||
}
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
if (!closed) {
|
||||
finish();
|
||||
if (mydeflater){
|
||||
deflater.end();
|
||||
}
|
||||
if(close_out)
|
||||
out.close();
|
||||
closed = true;
|
||||
}
|
||||
}
|
||||
|
||||
protected int deflate(int flush) throws IOException {
|
||||
deflater.setOutput(buffer, 0, buffer.length);
|
||||
int err = deflater.deflate(flush);
|
||||
switch(err) {
|
||||
case JZlib.Z_OK:
|
||||
case JZlib.Z_STREAM_END:
|
||||
break;
|
||||
case JZlib.Z_BUF_ERROR:
|
||||
if(deflater.avail_in<=0 && flush!=JZlib.Z_FINISH){
|
||||
// flush() without any data
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new IOException("failed to deflate: error="+err+" avail_out="+deflater.avail_out);
|
||||
}
|
||||
int len = deflater.next_out_index;
|
||||
if (len > 0) {
|
||||
out.write(buffer, 0, len);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
public void flush() throws IOException {
|
||||
if (syncFlush && !deflater.finished()) {
|
||||
while (true) {
|
||||
int err = deflate(JZlib.Z_SYNC_FLUSH);
|
||||
if (deflater.next_out_index < buffer.length)
|
||||
break;
|
||||
if (err == JZlib.Z_STREAM_END)
|
||||
break;
|
||||
}
|
||||
}
|
||||
out.flush();
|
||||
}
|
||||
|
||||
public long getTotalIn() {
|
||||
return deflater.getTotalIn();
|
||||
}
|
||||
|
||||
public long getTotalOut() {
|
||||
return deflater.getTotalOut();
|
||||
}
|
||||
|
||||
public void setSyncFlush(boolean syncFlush){
|
||||
this.syncFlush = syncFlush;
|
||||
}
|
||||
|
||||
public boolean getSyncFlush(){
|
||||
return this.syncFlush;
|
||||
}
|
||||
|
||||
public Deflater getDeflater(){
|
||||
return deflater;
|
||||
}
|
||||
}
|
||||
44
src/lwjgl/java/com/jcraft/jzlib/GZIPException.java
Normal file
44
src/lwjgl/java/com/jcraft/jzlib/GZIPException.java
Normal file
@@ -0,0 +1,44 @@
|
||||
/* -*-mode:java; c-basic-offset:2; -*- */
|
||||
/*
|
||||
Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. The names of the authors may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
|
||||
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/*
|
||||
* This program is based on zlib-1.1.3, so all credit should go authors
|
||||
* Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
|
||||
* and contributors of zlib.
|
||||
*/
|
||||
|
||||
package com.jcraft.jzlib;
|
||||
|
||||
public class GZIPException extends java.io.IOException {
|
||||
public GZIPException() {
|
||||
super();
|
||||
}
|
||||
public GZIPException(String s) {
|
||||
super(s);
|
||||
}
|
||||
}
|
||||
214
src/lwjgl/java/com/jcraft/jzlib/GZIPHeader.java
Normal file
214
src/lwjgl/java/com/jcraft/jzlib/GZIPHeader.java
Normal file
@@ -0,0 +1,214 @@
|
||||
/* -*-mode:java; c-basic-offset:2; -*- */
|
||||
/*
|
||||
Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. The names of the authors may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
|
||||
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/*
|
||||
* This program is based on zlib-1.1.3, so all credit should go authors
|
||||
* Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
|
||||
* and contributors of zlib.
|
||||
*/
|
||||
|
||||
package com.jcraft.jzlib;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
||||
/**
|
||||
* @see "http://www.ietf.org/rfc/rfc1952.txt"
|
||||
*/
|
||||
public class GZIPHeader implements Cloneable {
|
||||
|
||||
public static final byte OS_MSDOS = (byte) 0x00;
|
||||
public static final byte OS_AMIGA = (byte) 0x01;
|
||||
public static final byte OS_VMS = (byte) 0x02;
|
||||
public static final byte OS_UNIX = (byte) 0x03;
|
||||
public static final byte OS_ATARI = (byte) 0x05;
|
||||
public static final byte OS_OS2 = (byte) 0x06;
|
||||
public static final byte OS_MACOS = (byte) 0x07;
|
||||
public static final byte OS_TOPS20 = (byte) 0x0a;
|
||||
public static final byte OS_WIN32 = (byte) 0x0b;
|
||||
public static final byte OS_VMCMS = (byte) 0x04;
|
||||
public static final byte OS_ZSYSTEM = (byte) 0x08;
|
||||
public static final byte OS_CPM = (byte) 0x09;
|
||||
public static final byte OS_QDOS = (byte) 0x0c;
|
||||
public static final byte OS_RISCOS = (byte) 0x0d;
|
||||
public static final byte OS_UNKNOWN = (byte) 0xff;
|
||||
|
||||
boolean text = false;
|
||||
private boolean fhcrc = false;
|
||||
long time;
|
||||
int xflags;
|
||||
int os = 255;
|
||||
byte[] extra;
|
||||
byte[] name;
|
||||
byte[] comment;
|
||||
int hcrc;
|
||||
long crc;
|
||||
boolean done = false;
|
||||
long mtime = 0;
|
||||
|
||||
public void setModifiedTime(long mtime) {
|
||||
this.mtime = mtime;
|
||||
}
|
||||
|
||||
public long getModifiedTime() {
|
||||
return mtime;
|
||||
}
|
||||
|
||||
public void setOS(int os) {
|
||||
if((0<=os && os <=13) || os==255)
|
||||
this.os=os;
|
||||
else
|
||||
throw new IllegalArgumentException("os: "+os);
|
||||
}
|
||||
|
||||
public int getOS(){
|
||||
return os;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
try{
|
||||
this.name=name.getBytes("ISO-8859-1");
|
||||
}
|
||||
catch(UnsupportedEncodingException e){
|
||||
throw new IllegalArgumentException("name must be in ISO-8859-1 "+name);
|
||||
}
|
||||
}
|
||||
|
||||
public String getName(){
|
||||
if(name==null) return "";
|
||||
try {
|
||||
return new String(name, "ISO-8859-1");
|
||||
}
|
||||
catch (UnsupportedEncodingException e) {
|
||||
throw new InternalError(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
public void setComment(String comment) {
|
||||
try{
|
||||
this.comment=comment.getBytes("ISO-8859-1");
|
||||
}
|
||||
catch(UnsupportedEncodingException e){
|
||||
throw new IllegalArgumentException("comment must be in ISO-8859-1 "+name);
|
||||
}
|
||||
}
|
||||
|
||||
public String getComment(){
|
||||
if(comment==null) return "";
|
||||
try {
|
||||
return new String(comment, "ISO-8859-1");
|
||||
}
|
||||
catch (UnsupportedEncodingException e) {
|
||||
throw new InternalError(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
public void setCRC(long crc){
|
||||
this.crc = crc;
|
||||
}
|
||||
|
||||
public long getCRC(){
|
||||
return crc;
|
||||
}
|
||||
|
||||
void put(Deflate d){
|
||||
int flag = 0;
|
||||
if(text){
|
||||
flag |= 1; // FTEXT
|
||||
}
|
||||
if(fhcrc){
|
||||
flag |= 2; // FHCRC
|
||||
}
|
||||
if(extra!=null){
|
||||
flag |= 4; // FEXTRA
|
||||
}
|
||||
if(name!=null){
|
||||
flag |= 8; // FNAME
|
||||
}
|
||||
if(comment!=null){
|
||||
flag |= 16; // FCOMMENT
|
||||
}
|
||||
int xfl = 0;
|
||||
if(d.level == JZlib.Z_BEST_SPEED){
|
||||
xfl |= 4;
|
||||
}
|
||||
else if (d.level == JZlib.Z_BEST_COMPRESSION){
|
||||
xfl |= 2;
|
||||
}
|
||||
|
||||
d.put_short((short)0x8b1f); // ID1 ID2
|
||||
d.put_byte((byte)8); // CM(Compression Method)
|
||||
d.put_byte((byte)flag);
|
||||
d.put_byte((byte)mtime);
|
||||
d.put_byte((byte)(mtime>>8));
|
||||
d.put_byte((byte)(mtime>>16));
|
||||
d.put_byte((byte)(mtime>>24));
|
||||
d.put_byte((byte)xfl);
|
||||
d.put_byte((byte)os);
|
||||
|
||||
if(extra!=null){
|
||||
d.put_byte((byte)extra.length);
|
||||
d.put_byte((byte)(extra.length>>8));
|
||||
d.put_byte(extra, 0, extra.length);
|
||||
}
|
||||
|
||||
if(name!=null){
|
||||
d.put_byte(name, 0, name.length);
|
||||
d.put_byte((byte)0);
|
||||
}
|
||||
|
||||
if(comment!=null){
|
||||
d.put_byte(comment, 0, comment.length);
|
||||
d.put_byte((byte)0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object clone() throws CloneNotSupportedException {
|
||||
GZIPHeader gheader = (GZIPHeader)super.clone();
|
||||
byte[] tmp;
|
||||
if(gheader.extra!=null){
|
||||
tmp=new byte[gheader.extra.length];
|
||||
System.arraycopy(gheader.extra, 0, tmp, 0, tmp.length);
|
||||
gheader.extra = tmp;
|
||||
}
|
||||
|
||||
if(gheader.name!=null){
|
||||
tmp=new byte[gheader.name.length];
|
||||
System.arraycopy(gheader.name, 0, tmp, 0, tmp.length);
|
||||
gheader.name = tmp;
|
||||
}
|
||||
|
||||
if(gheader.comment!=null){
|
||||
tmp=new byte[gheader.comment.length];
|
||||
System.arraycopy(gheader.comment, 0, tmp, 0, tmp.length);
|
||||
gheader.comment = tmp;
|
||||
}
|
||||
|
||||
return gheader;
|
||||
}
|
||||
}
|
||||
145
src/lwjgl/java/com/jcraft/jzlib/GZIPInputStream.java
Normal file
145
src/lwjgl/java/com/jcraft/jzlib/GZIPInputStream.java
Normal file
@@ -0,0 +1,145 @@
|
||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
|
||||
/*
|
||||
Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. The names of the authors may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
|
||||
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package com.jcraft.jzlib;
|
||||
import java.io.*;
|
||||
|
||||
public class GZIPInputStream extends InflaterInputStream {
|
||||
|
||||
public GZIPInputStream(InputStream in) throws IOException {
|
||||
this(in, DEFAULT_BUFSIZE, true);
|
||||
}
|
||||
|
||||
public GZIPInputStream(InputStream in,
|
||||
int size,
|
||||
boolean close_in) throws IOException {
|
||||
this(in, new Inflater(15+16), size, close_in);
|
||||
myinflater = true;
|
||||
}
|
||||
|
||||
public GZIPInputStream(InputStream in,
|
||||
Inflater inflater,
|
||||
int size,
|
||||
boolean close_in) throws IOException {
|
||||
super(in, inflater, size, close_in);
|
||||
}
|
||||
|
||||
public long getModifiedtime() {
|
||||
return inflater.istate.getGZIPHeader().getModifiedTime();
|
||||
}
|
||||
|
||||
public int getOS() {
|
||||
return inflater.istate.getGZIPHeader().getOS();
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return inflater.istate.getGZIPHeader().getName();
|
||||
}
|
||||
|
||||
public String getComment() {
|
||||
return inflater.istate.getGZIPHeader().getComment();
|
||||
}
|
||||
|
||||
public long getCRC() throws GZIPException {
|
||||
if(inflater.istate.mode != 12 /*DONE*/)
|
||||
throw new GZIPException("checksum is not calculated yet.");
|
||||
return inflater.istate.getGZIPHeader().getCRC();
|
||||
}
|
||||
|
||||
public void readHeader() throws IOException {
|
||||
|
||||
byte[] empty = "".getBytes();
|
||||
inflater.setOutput(empty, 0, 0);
|
||||
inflater.setInput(empty, 0, 0, false);
|
||||
|
||||
byte[] b = new byte[10];
|
||||
|
||||
int n = fill(b);
|
||||
if(n!=10){
|
||||
if(n>0){
|
||||
inflater.setInput(b, 0, n, false);
|
||||
//inflater.next_in_index = n;
|
||||
inflater.next_in_index = 0;
|
||||
inflater.avail_in = n;
|
||||
}
|
||||
throw new IOException("no input");
|
||||
}
|
||||
|
||||
inflater.setInput(b, 0, n, false);
|
||||
|
||||
byte[] b1 = new byte[1];
|
||||
do{
|
||||
if(inflater.avail_in<=0){
|
||||
int i = in.read(b1);
|
||||
if(i<=0)
|
||||
throw new IOException("no input");
|
||||
inflater.setInput(b1, 0, 1, true);
|
||||
}
|
||||
|
||||
int err = inflater.inflate(JZlib.Z_NO_FLUSH);
|
||||
|
||||
if(err!=0/*Z_OK*/){
|
||||
int len = 2048-inflater.next_in.length;
|
||||
if(len>0){
|
||||
byte[] tmp = new byte[len];
|
||||
n = fill(tmp);
|
||||
if(n>0){
|
||||
inflater.avail_in += inflater.next_in_index;
|
||||
inflater.next_in_index = 0;
|
||||
inflater.setInput(tmp, 0, n, true);
|
||||
}
|
||||
}
|
||||
//inflater.next_in_index = inflater.next_in.length;
|
||||
inflater.avail_in += inflater.next_in_index;
|
||||
inflater.next_in_index = 0;
|
||||
throw new IOException(inflater.msg);
|
||||
}
|
||||
}
|
||||
while(inflater.istate.inParsingHeader());
|
||||
}
|
||||
|
||||
private int fill(byte[] buf) {
|
||||
int len = buf.length;
|
||||
int n = 0;
|
||||
do{
|
||||
int i = -1;
|
||||
try {
|
||||
i = in.read(buf, n, buf.length - n);
|
||||
}
|
||||
catch(IOException e){
|
||||
}
|
||||
if(i == -1){
|
||||
break;
|
||||
}
|
||||
n+=i;
|
||||
}
|
||||
while(n<len);
|
||||
return n;
|
||||
}
|
||||
}
|
||||
90
src/lwjgl/java/com/jcraft/jzlib/GZIPOutputStream.java
Normal file
90
src/lwjgl/java/com/jcraft/jzlib/GZIPOutputStream.java
Normal file
@@ -0,0 +1,90 @@
|
||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
|
||||
/*
|
||||
Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. The names of the authors may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
|
||||
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package com.jcraft.jzlib;
|
||||
import java.io.*;
|
||||
|
||||
public class GZIPOutputStream extends DeflaterOutputStream {
|
||||
|
||||
public GZIPOutputStream(OutputStream out) throws IOException {
|
||||
this(out, DEFAULT_BUFSIZE);
|
||||
}
|
||||
|
||||
public GZIPOutputStream(OutputStream out, int size) throws IOException {
|
||||
this(out, size, true);
|
||||
}
|
||||
|
||||
public GZIPOutputStream(OutputStream out,
|
||||
int size,
|
||||
boolean close_out) throws IOException {
|
||||
this(out,
|
||||
new Deflater(JZlib.Z_DEFAULT_COMPRESSION, 15+16),
|
||||
size, close_out);
|
||||
mydeflater=true;
|
||||
}
|
||||
|
||||
public GZIPOutputStream(OutputStream out,
|
||||
Deflater deflater,
|
||||
int size,
|
||||
boolean close_out) throws IOException{
|
||||
super(out, deflater, size, close_out);
|
||||
}
|
||||
|
||||
|
||||
private void check() throws GZIPException {
|
||||
if(deflater.dstate.status != 42 /*INIT_STATUS*/)
|
||||
throw new GZIPException("header is already written.");
|
||||
}
|
||||
|
||||
public void setModifiedTime(long mtime) throws GZIPException {
|
||||
check();
|
||||
deflater.dstate.getGZIPHeader().setModifiedTime(mtime);
|
||||
}
|
||||
|
||||
public void setOS(int os) throws GZIPException {
|
||||
check();
|
||||
deflater.dstate.getGZIPHeader().setOS(os);
|
||||
}
|
||||
|
||||
public void setName(String name) throws GZIPException {
|
||||
check();
|
||||
deflater.dstate.getGZIPHeader().setName(name);
|
||||
}
|
||||
|
||||
public void setComment(String comment) throws GZIPException {
|
||||
check();
|
||||
deflater.dstate.getGZIPHeader().setComment(comment);
|
||||
}
|
||||
|
||||
public long getCRC() throws GZIPException {
|
||||
if(deflater.dstate.status != 666 /*FINISH_STATE*/)
|
||||
throw new GZIPException("checksum is not calculated yet.");
|
||||
return deflater.dstate.getGZIPHeader().getCRC();
|
||||
}
|
||||
}
|
||||
614
src/lwjgl/java/com/jcraft/jzlib/InfBlocks.java
Normal file
614
src/lwjgl/java/com/jcraft/jzlib/InfBlocks.java
Normal file
@@ -0,0 +1,614 @@
|
||||
/* -*-mode:java; c-basic-offset:2; -*- */
|
||||
/*
|
||||
Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. The names of the authors may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
|
||||
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/*
|
||||
* This program is based on zlib-1.1.3, so all credit should go authors
|
||||
* Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
|
||||
* and contributors of zlib.
|
||||
*/
|
||||
|
||||
package com.jcraft.jzlib;
|
||||
|
||||
final class InfBlocks{
|
||||
static final private int MANY=1440;
|
||||
|
||||
// And'ing with mask[n] masks the lower n bits
|
||||
static final private int[] inflate_mask = {
|
||||
0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f,
|
||||
0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff,
|
||||
0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff,
|
||||
0x00007fff, 0x0000ffff
|
||||
};
|
||||
|
||||
// Table for deflate from PKZIP's appnote.txt.
|
||||
static final int[] border = { // Order of the bit length code lengths
|
||||
16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
|
||||
};
|
||||
|
||||
static final private int Z_OK=0;
|
||||
static final private int Z_STREAM_END=1;
|
||||
static final private int Z_NEED_DICT=2;
|
||||
static final private int Z_ERRNO=-1;
|
||||
static final private int Z_STREAM_ERROR=-2;
|
||||
static final private int Z_DATA_ERROR=-3;
|
||||
static final private int Z_MEM_ERROR=-4;
|
||||
static final private int Z_BUF_ERROR=-5;
|
||||
static final private int Z_VERSION_ERROR=-6;
|
||||
|
||||
static final private int TYPE=0; // get type bits (3, including end bit)
|
||||
static final private int LENS=1; // get lengths for stored
|
||||
static final private int STORED=2;// processing stored block
|
||||
static final private int TABLE=3; // get table lengths
|
||||
static final private int BTREE=4; // get bit lengths tree for a dynamic block
|
||||
static final private int DTREE=5; // get length, distance trees for a dynamic block
|
||||
static final private int CODES=6; // processing fixed or dynamic block
|
||||
static final private int DRY=7; // output remaining window bytes
|
||||
static final private int DONE=8; // finished last block, done
|
||||
static final private int BAD=9; // ot a data error--stuck here
|
||||
|
||||
int mode; // current inflate_block mode
|
||||
|
||||
int left; // if STORED, bytes left to copy
|
||||
|
||||
int table; // table lengths (14 bits)
|
||||
int index; // index into blens (or border)
|
||||
int[] blens; // bit lengths of codes
|
||||
int[] bb=new int[1]; // bit length tree depth
|
||||
int[] tb=new int[1]; // bit length decoding tree
|
||||
|
||||
int[] bl=new int[1];
|
||||
int[] bd=new int[1];
|
||||
|
||||
int[][] tl=new int[1][];
|
||||
int[][] td=new int[1][];
|
||||
int[] tli=new int[1]; // tl_index
|
||||
int[] tdi=new int[1]; // td_index
|
||||
|
||||
private final InfCodes codes; // if CODES, current state
|
||||
|
||||
int last; // true if this block is the last block
|
||||
|
||||
// mode independent information
|
||||
int bitk; // bits in bit buffer
|
||||
int bitb; // bit buffer
|
||||
int[] hufts; // single malloc for tree space
|
||||
byte[] window; // sliding window
|
||||
int end; // one byte after sliding window
|
||||
int read; // window read pointer
|
||||
int write; // window write pointer
|
||||
private boolean check;
|
||||
|
||||
private final InfTree inftree=new InfTree();
|
||||
|
||||
private final ZStream z;
|
||||
|
||||
InfBlocks(ZStream z, int w){
|
||||
this.z=z;
|
||||
this.codes=new InfCodes(this.z, this);
|
||||
hufts=new int[MANY*3];
|
||||
window=new byte[w];
|
||||
end=w;
|
||||
this.check = (z.istate.wrap==0) ? false : true;
|
||||
mode = TYPE;
|
||||
reset();
|
||||
}
|
||||
|
||||
void reset(){
|
||||
if(mode==BTREE || mode==DTREE){
|
||||
}
|
||||
if(mode==CODES){
|
||||
codes.free(z);
|
||||
}
|
||||
mode=TYPE;
|
||||
bitk=0;
|
||||
bitb=0;
|
||||
read=write=0;
|
||||
if(check){
|
||||
z.adler.reset();
|
||||
}
|
||||
}
|
||||
|
||||
int proc(int r){
|
||||
int t; // temporary storage
|
||||
int b; // bit buffer
|
||||
int k; // bits in bit buffer
|
||||
int p; // input data pointer
|
||||
int n; // bytes available there
|
||||
int q; // output window write pointer
|
||||
int m; // bytes to end of window or read pointer
|
||||
|
||||
// copy input/output information to locals (UPDATE macro restores)
|
||||
{p=z.next_in_index;n=z.avail_in;b=bitb;k=bitk;}
|
||||
{q=write;m=(int)(q<read?read-q-1:end-q);}
|
||||
|
||||
// process input based on current state
|
||||
while(true){
|
||||
switch (mode){
|
||||
case TYPE:
|
||||
|
||||
while(k<(3)){
|
||||
if(n!=0){
|
||||
r=Z_OK;
|
||||
}
|
||||
else{
|
||||
bitb=b; bitk=k;
|
||||
z.avail_in=n;
|
||||
z.total_in+=p-z.next_in_index;z.next_in_index=p;
|
||||
write=q;
|
||||
return inflate_flush(r);
|
||||
};
|
||||
n--;
|
||||
b|=(z.next_in[p++]&0xff)<<k;
|
||||
k+=8;
|
||||
}
|
||||
t = (int)(b & 7);
|
||||
last = t & 1;
|
||||
|
||||
switch (t >>> 1){
|
||||
case 0: // stored
|
||||
{b>>>=(3);k-=(3);}
|
||||
t = k & 7; // go to byte boundary
|
||||
|
||||
{b>>>=(t);k-=(t);}
|
||||
mode = LENS; // get length of stored block
|
||||
break;
|
||||
case 1: // fixed
|
||||
InfTree.inflate_trees_fixed(bl, bd, tl, td, z);
|
||||
codes.init(bl[0], bd[0], tl[0], 0, td[0], 0);
|
||||
|
||||
{b>>>=(3);k-=(3);}
|
||||
|
||||
mode = CODES;
|
||||
break;
|
||||
case 2: // dynamic
|
||||
|
||||
{b>>>=(3);k-=(3);}
|
||||
|
||||
mode = TABLE;
|
||||
break;
|
||||
case 3: // illegal
|
||||
|
||||
{b>>>=(3);k-=(3);}
|
||||
mode = BAD;
|
||||
z.msg = "invalid block type";
|
||||
r = Z_DATA_ERROR;
|
||||
|
||||
bitb=b; bitk=k;
|
||||
z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
|
||||
write=q;
|
||||
return inflate_flush(r);
|
||||
}
|
||||
break;
|
||||
case LENS:
|
||||
|
||||
while(k<(32)){
|
||||
if(n!=0){
|
||||
r=Z_OK;
|
||||
}
|
||||
else{
|
||||
bitb=b; bitk=k;
|
||||
z.avail_in=n;
|
||||
z.total_in+=p-z.next_in_index;z.next_in_index=p;
|
||||
write=q;
|
||||
return inflate_flush(r);
|
||||
};
|
||||
n--;
|
||||
b|=(z.next_in[p++]&0xff)<<k;
|
||||
k+=8;
|
||||
}
|
||||
|
||||
if ((((~b) >>> 16) & 0xffff) != (b & 0xffff)){
|
||||
mode = BAD;
|
||||
z.msg = "invalid stored block lengths";
|
||||
r = Z_DATA_ERROR;
|
||||
|
||||
bitb=b; bitk=k;
|
||||
z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
|
||||
write=q;
|
||||
return inflate_flush(r);
|
||||
}
|
||||
left = (b & 0xffff);
|
||||
b = k = 0; // dump bits
|
||||
mode = left!=0 ? STORED : (last!=0 ? DRY : TYPE);
|
||||
break;
|
||||
case STORED:
|
||||
if (n == 0){
|
||||
bitb=b; bitk=k;
|
||||
z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
|
||||
write=q;
|
||||
return inflate_flush(r);
|
||||
}
|
||||
|
||||
if(m==0){
|
||||
if(q==end&&read!=0){
|
||||
q=0; m=(int)(q<read?read-q-1:end-q);
|
||||
}
|
||||
if(m==0){
|
||||
write=q;
|
||||
r=inflate_flush(r);
|
||||
q=write;m=(int)(q<read?read-q-1:end-q);
|
||||
if(q==end&&read!=0){
|
||||
q=0; m=(int)(q<read?read-q-1:end-q);
|
||||
}
|
||||
if(m==0){
|
||||
bitb=b; bitk=k;
|
||||
z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
|
||||
write=q;
|
||||
return inflate_flush(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
r=Z_OK;
|
||||
|
||||
t = left;
|
||||
if(t>n) t = n;
|
||||
if(t>m) t = m;
|
||||
System.arraycopy(z.next_in, p, window, q, t);
|
||||
p += t; n -= t;
|
||||
q += t; m -= t;
|
||||
if ((left -= t) != 0)
|
||||
break;
|
||||
mode = last!=0 ? DRY : TYPE;
|
||||
break;
|
||||
case TABLE:
|
||||
|
||||
while(k<(14)){
|
||||
if(n!=0){
|
||||
r=Z_OK;
|
||||
}
|
||||
else{
|
||||
bitb=b; bitk=k;
|
||||
z.avail_in=n;
|
||||
z.total_in+=p-z.next_in_index;z.next_in_index=p;
|
||||
write=q;
|
||||
return inflate_flush(r);
|
||||
};
|
||||
n--;
|
||||
b|=(z.next_in[p++]&0xff)<<k;
|
||||
k+=8;
|
||||
}
|
||||
|
||||
table = t = (b & 0x3fff);
|
||||
if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29)
|
||||
{
|
||||
mode = BAD;
|
||||
z.msg = "too many length or distance symbols";
|
||||
r = Z_DATA_ERROR;
|
||||
|
||||
bitb=b; bitk=k;
|
||||
z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
|
||||
write=q;
|
||||
return inflate_flush(r);
|
||||
}
|
||||
t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);
|
||||
if(blens==null || blens.length<t){
|
||||
blens=new int[t];
|
||||
}
|
||||
else{
|
||||
for(int i=0; i<t; i++){blens[i]=0;}
|
||||
}
|
||||
|
||||
{b>>>=(14);k-=(14);}
|
||||
|
||||
index = 0;
|
||||
mode = BTREE;
|
||||
case BTREE:
|
||||
while (index < 4 + (table >>> 10)){
|
||||
while(k<(3)){
|
||||
if(n!=0){
|
||||
r=Z_OK;
|
||||
}
|
||||
else{
|
||||
bitb=b; bitk=k;
|
||||
z.avail_in=n;
|
||||
z.total_in+=p-z.next_in_index;z.next_in_index=p;
|
||||
write=q;
|
||||
return inflate_flush(r);
|
||||
};
|
||||
n--;
|
||||
b|=(z.next_in[p++]&0xff)<<k;
|
||||
k+=8;
|
||||
}
|
||||
|
||||
blens[border[index++]] = b&7;
|
||||
|
||||
{b>>>=(3);k-=(3);}
|
||||
}
|
||||
|
||||
while(index < 19){
|
||||
blens[border[index++]] = 0;
|
||||
}
|
||||
|
||||
bb[0] = 7;
|
||||
t = inftree.inflate_trees_bits(blens, bb, tb, hufts, z);
|
||||
if (t != Z_OK){
|
||||
r = t;
|
||||
if (r == Z_DATA_ERROR){
|
||||
blens=null;
|
||||
mode = BAD;
|
||||
}
|
||||
|
||||
bitb=b; bitk=k;
|
||||
z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
|
||||
write=q;
|
||||
return inflate_flush(r);
|
||||
}
|
||||
|
||||
index = 0;
|
||||
mode = DTREE;
|
||||
case DTREE:
|
||||
while (true){
|
||||
t = table;
|
||||
if(!(index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))){
|
||||
break;
|
||||
}
|
||||
|
||||
int[] h;
|
||||
int i, j, c;
|
||||
|
||||
t = bb[0];
|
||||
|
||||
while(k<(t)){
|
||||
if(n!=0){
|
||||
r=Z_OK;
|
||||
}
|
||||
else{
|
||||
bitb=b; bitk=k;
|
||||
z.avail_in=n;
|
||||
z.total_in+=p-z.next_in_index;z.next_in_index=p;
|
||||
write=q;
|
||||
return inflate_flush(r);
|
||||
};
|
||||
n--;
|
||||
b|=(z.next_in[p++]&0xff)<<k;
|
||||
k+=8;
|
||||
}
|
||||
|
||||
if(tb[0]==-1){
|
||||
//System.err.println("null...");
|
||||
}
|
||||
|
||||
t=hufts[(tb[0]+(b&inflate_mask[t]))*3+1];
|
||||
c=hufts[(tb[0]+(b&inflate_mask[t]))*3+2];
|
||||
|
||||
if (c < 16){
|
||||
b>>>=(t);k-=(t);
|
||||
blens[index++] = c;
|
||||
}
|
||||
else { // c == 16..18
|
||||
i = c == 18 ? 7 : c - 14;
|
||||
j = c == 18 ? 11 : 3;
|
||||
|
||||
while(k<(t+i)){
|
||||
if(n!=0){
|
||||
r=Z_OK;
|
||||
}
|
||||
else{
|
||||
bitb=b; bitk=k;
|
||||
z.avail_in=n;
|
||||
z.total_in+=p-z.next_in_index;z.next_in_index=p;
|
||||
write=q;
|
||||
return inflate_flush(r);
|
||||
};
|
||||
n--;
|
||||
b|=(z.next_in[p++]&0xff)<<k;
|
||||
k+=8;
|
||||
}
|
||||
|
||||
b>>>=(t);k-=(t);
|
||||
|
||||
j += (b & inflate_mask[i]);
|
||||
|
||||
b>>>=(i);k-=(i);
|
||||
|
||||
i = index;
|
||||
t = table;
|
||||
if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) ||
|
||||
(c == 16 && i < 1)){
|
||||
blens=null;
|
||||
mode = BAD;
|
||||
z.msg = "invalid bit length repeat";
|
||||
r = Z_DATA_ERROR;
|
||||
|
||||
bitb=b; bitk=k;
|
||||
z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
|
||||
write=q;
|
||||
return inflate_flush(r);
|
||||
}
|
||||
|
||||
c = c == 16 ? blens[i-1] : 0;
|
||||
do{
|
||||
blens[i++] = c;
|
||||
}
|
||||
while (--j!=0);
|
||||
index = i;
|
||||
}
|
||||
}
|
||||
|
||||
tb[0]=-1;
|
||||
{
|
||||
bl[0] = 9; // must be <= 9 for lookahead assumptions
|
||||
bd[0] = 6; // must be <= 9 for lookahead assumptions
|
||||
t = table;
|
||||
t = inftree.inflate_trees_dynamic(257 + (t & 0x1f),
|
||||
1 + ((t >> 5) & 0x1f),
|
||||
blens, bl, bd, tli, tdi, hufts, z);
|
||||
|
||||
if (t != Z_OK){
|
||||
if (t == Z_DATA_ERROR){
|
||||
blens=null;
|
||||
mode = BAD;
|
||||
}
|
||||
r = t;
|
||||
|
||||
bitb=b; bitk=k;
|
||||
z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
|
||||
write=q;
|
||||
return inflate_flush(r);
|
||||
}
|
||||
codes.init(bl[0], bd[0], hufts, tli[0], hufts, tdi[0]);
|
||||
}
|
||||
mode = CODES;
|
||||
case CODES:
|
||||
bitb=b; bitk=k;
|
||||
z.avail_in=n; z.total_in+=p-z.next_in_index;z.next_in_index=p;
|
||||
write=q;
|
||||
|
||||
if ((r = codes.proc(r)) != Z_STREAM_END){
|
||||
return inflate_flush(r);
|
||||
}
|
||||
r = Z_OK;
|
||||
codes.free(z);
|
||||
|
||||
p=z.next_in_index; n=z.avail_in;b=bitb;k=bitk;
|
||||
q=write;m=(int)(q<read?read-q-1:end-q);
|
||||
|
||||
if (last==0){
|
||||
mode = TYPE;
|
||||
break;
|
||||
}
|
||||
mode = DRY;
|
||||
case DRY:
|
||||
write=q;
|
||||
r=inflate_flush(r);
|
||||
q=write; m=(int)(q<read?read-q-1:end-q);
|
||||
if (read != write){
|
||||
bitb=b; bitk=k;
|
||||
z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
|
||||
write=q;
|
||||
return inflate_flush(r);
|
||||
}
|
||||
mode = DONE;
|
||||
case DONE:
|
||||
r = Z_STREAM_END;
|
||||
|
||||
bitb=b; bitk=k;
|
||||
z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
|
||||
write=q;
|
||||
return inflate_flush(r);
|
||||
case BAD:
|
||||
r = Z_DATA_ERROR;
|
||||
|
||||
bitb=b; bitk=k;
|
||||
z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
|
||||
write=q;
|
||||
return inflate_flush(r);
|
||||
|
||||
default:
|
||||
r = Z_STREAM_ERROR;
|
||||
|
||||
bitb=b; bitk=k;
|
||||
z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
|
||||
write=q;
|
||||
return inflate_flush(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void free(){
|
||||
reset();
|
||||
window=null;
|
||||
hufts=null;
|
||||
//ZFREE(z, s);
|
||||
}
|
||||
|
||||
void set_dictionary(byte[] d, int start, int n){
|
||||
System.arraycopy(d, start, window, 0, n);
|
||||
read = write = n;
|
||||
}
|
||||
|
||||
// Returns true if inflate is currently at the end of a block generated
|
||||
// by Z_SYNC_FLUSH or Z_FULL_FLUSH.
|
||||
int sync_point(){
|
||||
return mode == LENS ? 1 : 0;
|
||||
}
|
||||
|
||||
// copy as much as possible from the sliding window to the output area
|
||||
int inflate_flush(int r){
|
||||
int n;
|
||||
int p;
|
||||
int q;
|
||||
|
||||
// local copies of source and destination pointers
|
||||
p = z.next_out_index;
|
||||
q = read;
|
||||
|
||||
// compute number of bytes to copy as far as end of window
|
||||
n = (int)((q <= write ? write : end) - q);
|
||||
if(n > z.avail_out) n = z.avail_out;
|
||||
if(n!=0 && r == Z_BUF_ERROR) r = Z_OK;
|
||||
|
||||
// update counters
|
||||
z.avail_out -= n;
|
||||
z.total_out += n;
|
||||
|
||||
// update check information
|
||||
if(check && n>0){
|
||||
z.adler.update(window, q, n);
|
||||
}
|
||||
|
||||
// copy as far as end of window
|
||||
System.arraycopy(window, q, z.next_out, p, n);
|
||||
p += n;
|
||||
q += n;
|
||||
|
||||
// see if more to copy at beginning of window
|
||||
if (q == end){
|
||||
// wrap pointers
|
||||
q = 0;
|
||||
if (write == end)
|
||||
write = 0;
|
||||
|
||||
// compute bytes to copy
|
||||
n = write - q;
|
||||
if (n > z.avail_out) n = z.avail_out;
|
||||
if (n!=0 && r == Z_BUF_ERROR) r = Z_OK;
|
||||
|
||||
// update counters
|
||||
z.avail_out -= n;
|
||||
z.total_out += n;
|
||||
|
||||
// update check information
|
||||
if(check && n>0){
|
||||
z.adler.update(window, q, n);
|
||||
}
|
||||
|
||||
// copy
|
||||
System.arraycopy(window, q, z.next_out, p, n);
|
||||
p += n;
|
||||
q += n;
|
||||
}
|
||||
|
||||
// update pointers
|
||||
z.next_out_index = p;
|
||||
read = q;
|
||||
|
||||
// done
|
||||
return r;
|
||||
}
|
||||
}
|
||||
610
src/lwjgl/java/com/jcraft/jzlib/InfCodes.java
Normal file
610
src/lwjgl/java/com/jcraft/jzlib/InfCodes.java
Normal file
@@ -0,0 +1,610 @@
|
||||
/* -*-mode:java; c-basic-offset:2; -*- */
|
||||
/*
|
||||
Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. The names of the authors may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
|
||||
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/*
|
||||
* This program is based on zlib-1.1.3, so all credit should go authors
|
||||
* Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
|
||||
* and contributors of zlib.
|
||||
*/
|
||||
|
||||
package com.jcraft.jzlib;
|
||||
|
||||
final class InfCodes{
|
||||
|
||||
static final private int[] inflate_mask = {
|
||||
0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f,
|
||||
0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff,
|
||||
0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff,
|
||||
0x00007fff, 0x0000ffff
|
||||
};
|
||||
|
||||
static final private int Z_OK=0;
|
||||
static final private int Z_STREAM_END=1;
|
||||
static final private int Z_NEED_DICT=2;
|
||||
static final private int Z_ERRNO=-1;
|
||||
static final private int Z_STREAM_ERROR=-2;
|
||||
static final private int Z_DATA_ERROR=-3;
|
||||
static final private int Z_MEM_ERROR=-4;
|
||||
static final private int Z_BUF_ERROR=-5;
|
||||
static final private int Z_VERSION_ERROR=-6;
|
||||
|
||||
// waiting for "i:"=input,
|
||||
// "o:"=output,
|
||||
// "x:"=nothing
|
||||
static final private int START=0; // x: set up for LEN
|
||||
static final private int LEN=1; // i: get length/literal/eob next
|
||||
static final private int LENEXT=2; // i: getting length extra (have base)
|
||||
static final private int DIST=3; // i: get distance next
|
||||
static final private int DISTEXT=4;// i: getting distance extra
|
||||
static final private int COPY=5; // o: copying bytes in window, waiting for space
|
||||
static final private int LIT=6; // o: got literal, waiting for output space
|
||||
static final private int WASH=7; // o: got eob, possibly still output waiting
|
||||
static final private int END=8; // x: got eob and all data flushed
|
||||
static final private int BADCODE=9;// x: got error
|
||||
|
||||
int mode; // current inflate_codes mode
|
||||
|
||||
// mode dependent information
|
||||
int len;
|
||||
|
||||
int[] tree; // pointer into tree
|
||||
int tree_index=0;
|
||||
int need; // bits needed
|
||||
|
||||
int lit;
|
||||
|
||||
// if EXT or COPY, where and how much
|
||||
int get; // bits to get for extra
|
||||
int dist; // distance back to copy from
|
||||
|
||||
byte lbits; // ltree bits decoded per branch
|
||||
byte dbits; // dtree bits decoder per branch
|
||||
int[] ltree; // literal/length/eob tree
|
||||
int ltree_index; // literal/length/eob tree
|
||||
int[] dtree; // distance tree
|
||||
int dtree_index; // distance tree
|
||||
|
||||
private final ZStream z;
|
||||
private final InfBlocks s;
|
||||
InfCodes(ZStream z, InfBlocks s){
|
||||
this.z=z;
|
||||
this.s=s;
|
||||
}
|
||||
|
||||
void init(int bl, int bd,
|
||||
int[] tl, int tl_index,
|
||||
int[] td, int td_index){
|
||||
mode=START;
|
||||
lbits=(byte)bl;
|
||||
dbits=(byte)bd;
|
||||
ltree=tl;
|
||||
ltree_index=tl_index;
|
||||
dtree = td;
|
||||
dtree_index=td_index;
|
||||
tree=null;
|
||||
}
|
||||
|
||||
int proc(int r){
|
||||
int j; // temporary storage
|
||||
int[] t; // temporary pointer
|
||||
int tindex; // temporary pointer
|
||||
int e; // extra bits or operation
|
||||
int b=0; // bit buffer
|
||||
int k=0; // bits in bit buffer
|
||||
int p=0; // input data pointer
|
||||
int n; // bytes available there
|
||||
int q; // output window write pointer
|
||||
int m; // bytes to end of window or read pointer
|
||||
int f; // pointer to copy strings from
|
||||
|
||||
// copy input/output information to locals (UPDATE macro restores)
|
||||
p=z.next_in_index;n=z.avail_in;b=s.bitb;k=s.bitk;
|
||||
q=s.write;m=q<s.read?s.read-q-1:s.end-q;
|
||||
|
||||
// process input and output based on current state
|
||||
while (true){
|
||||
switch (mode){
|
||||
// waiting for "i:"=input, "o:"=output, "x:"=nothing
|
||||
case START: // x: set up for LEN
|
||||
if (m >= 258 && n >= 10){
|
||||
|
||||
s.bitb=b;s.bitk=k;
|
||||
z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
|
||||
s.write=q;
|
||||
r = inflate_fast(lbits, dbits,
|
||||
ltree, ltree_index,
|
||||
dtree, dtree_index,
|
||||
s, z);
|
||||
|
||||
p=z.next_in_index;n=z.avail_in;b=s.bitb;k=s.bitk;
|
||||
q=s.write;m=q<s.read?s.read-q-1:s.end-q;
|
||||
|
||||
if (r != Z_OK){
|
||||
mode = r == Z_STREAM_END ? WASH : BADCODE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
need = lbits;
|
||||
tree = ltree;
|
||||
tree_index=ltree_index;
|
||||
|
||||
mode = LEN;
|
||||
case LEN: // i: get length/literal/eob next
|
||||
j = need;
|
||||
|
||||
while(k<(j)){
|
||||
if(n!=0)r=Z_OK;
|
||||
else{
|
||||
|
||||
s.bitb=b;s.bitk=k;
|
||||
z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
|
||||
s.write=q;
|
||||
return s.inflate_flush(r);
|
||||
}
|
||||
n--;
|
||||
b|=(z.next_in[p++]&0xff)<<k;
|
||||
k+=8;
|
||||
}
|
||||
|
||||
tindex=(tree_index+(b&inflate_mask[j]))*3;
|
||||
|
||||
b>>>=(tree[tindex+1]);
|
||||
k-=(tree[tindex+1]);
|
||||
|
||||
e=tree[tindex];
|
||||
|
||||
if(e == 0){ // literal
|
||||
lit = tree[tindex+2];
|
||||
mode = LIT;
|
||||
break;
|
||||
}
|
||||
if((e & 16)!=0 ){ // length
|
||||
get = e & 15;
|
||||
len = tree[tindex+2];
|
||||
mode = LENEXT;
|
||||
break;
|
||||
}
|
||||
if ((e & 64) == 0){ // next table
|
||||
need = e;
|
||||
tree_index = tindex/3+tree[tindex+2];
|
||||
break;
|
||||
}
|
||||
if ((e & 32)!=0){ // end of block
|
||||
mode = WASH;
|
||||
break;
|
||||
}
|
||||
mode = BADCODE; // invalid code
|
||||
z.msg = "invalid literal/length code";
|
||||
r = Z_DATA_ERROR;
|
||||
|
||||
s.bitb=b;s.bitk=k;
|
||||
z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
|
||||
s.write=q;
|
||||
return s.inflate_flush(r);
|
||||
|
||||
case LENEXT: // i: getting length extra (have base)
|
||||
j = get;
|
||||
|
||||
while(k<(j)){
|
||||
if(n!=0)r=Z_OK;
|
||||
else{
|
||||
|
||||
s.bitb=b;s.bitk=k;
|
||||
z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
|
||||
s.write=q;
|
||||
return s.inflate_flush(r);
|
||||
}
|
||||
n--; b|=(z.next_in[p++]&0xff)<<k;
|
||||
k+=8;
|
||||
}
|
||||
|
||||
len += (b & inflate_mask[j]);
|
||||
|
||||
b>>=j;
|
||||
k-=j;
|
||||
|
||||
need = dbits;
|
||||
tree = dtree;
|
||||
tree_index=dtree_index;
|
||||
mode = DIST;
|
||||
case DIST: // i: get distance next
|
||||
j = need;
|
||||
|
||||
while(k<(j)){
|
||||
if(n!=0)r=Z_OK;
|
||||
else{
|
||||
|
||||
s.bitb=b;s.bitk=k;
|
||||
z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
|
||||
s.write=q;
|
||||
return s.inflate_flush(r);
|
||||
}
|
||||
n--; b|=(z.next_in[p++]&0xff)<<k;
|
||||
k+=8;
|
||||
}
|
||||
|
||||
tindex=(tree_index+(b & inflate_mask[j]))*3;
|
||||
|
||||
b>>=tree[tindex+1];
|
||||
k-=tree[tindex+1];
|
||||
|
||||
e = (tree[tindex]);
|
||||
if((e & 16)!=0){ // distance
|
||||
get = e & 15;
|
||||
dist = tree[tindex+2];
|
||||
mode = DISTEXT;
|
||||
break;
|
||||
}
|
||||
if ((e & 64) == 0){ // next table
|
||||
need = e;
|
||||
tree_index = tindex/3 + tree[tindex+2];
|
||||
break;
|
||||
}
|
||||
mode = BADCODE; // invalid code
|
||||
z.msg = "invalid distance code";
|
||||
r = Z_DATA_ERROR;
|
||||
|
||||
s.bitb=b;s.bitk=k;
|
||||
z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
|
||||
s.write=q;
|
||||
return s.inflate_flush(r);
|
||||
|
||||
case DISTEXT: // i: getting distance extra
|
||||
j = get;
|
||||
|
||||
while(k<(j)){
|
||||
if(n!=0)r=Z_OK;
|
||||
else{
|
||||
|
||||
s.bitb=b;s.bitk=k;
|
||||
z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
|
||||
s.write=q;
|
||||
return s.inflate_flush(r);
|
||||
}
|
||||
n--; b|=(z.next_in[p++]&0xff)<<k;
|
||||
k+=8;
|
||||
}
|
||||
|
||||
dist += (b & inflate_mask[j]);
|
||||
|
||||
b>>=j;
|
||||
k-=j;
|
||||
|
||||
mode = COPY;
|
||||
case COPY: // o: copying bytes in window, waiting for space
|
||||
f = q - dist;
|
||||
while(f < 0){ // modulo window size-"while" instead
|
||||
f += s.end; // of "if" handles invalid distances
|
||||
}
|
||||
while (len!=0){
|
||||
|
||||
if(m==0){
|
||||
if(q==s.end&&s.read!=0){q=0;m=q<s.read?s.read-q-1:s.end-q;}
|
||||
if(m==0){
|
||||
s.write=q; r=s.inflate_flush(r);
|
||||
q=s.write;m=q<s.read?s.read-q-1:s.end-q;
|
||||
|
||||
if(q==s.end&&s.read!=0){q=0;m=q<s.read?s.read-q-1:s.end-q;}
|
||||
|
||||
if(m==0){
|
||||
s.bitb=b;s.bitk=k;
|
||||
z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
|
||||
s.write=q;
|
||||
return s.inflate_flush(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s.window[q++]=s.window[f++]; m--;
|
||||
|
||||
if (f == s.end)
|
||||
f = 0;
|
||||
len--;
|
||||
}
|
||||
mode = START;
|
||||
break;
|
||||
case LIT: // o: got literal, waiting for output space
|
||||
if(m==0){
|
||||
if(q==s.end&&s.read!=0){q=0;m=q<s.read?s.read-q-1:s.end-q;}
|
||||
if(m==0){
|
||||
s.write=q; r=s.inflate_flush(r);
|
||||
q=s.write;m=q<s.read?s.read-q-1:s.end-q;
|
||||
|
||||
if(q==s.end&&s.read!=0){q=0;m=q<s.read?s.read-q-1:s.end-q;}
|
||||
if(m==0){
|
||||
s.bitb=b;s.bitk=k;
|
||||
z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
|
||||
s.write=q;
|
||||
return s.inflate_flush(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
r=Z_OK;
|
||||
|
||||
s.window[q++]=(byte)lit; m--;
|
||||
|
||||
mode = START;
|
||||
break;
|
||||
case WASH: // o: got eob, possibly more output
|
||||
if (k > 7){ // return unused byte, if any
|
||||
k -= 8;
|
||||
n++;
|
||||
p--; // can always return one
|
||||
}
|
||||
|
||||
s.write=q; r=s.inflate_flush(r);
|
||||
q=s.write;m=q<s.read?s.read-q-1:s.end-q;
|
||||
|
||||
if (s.read != s.write){
|
||||
s.bitb=b;s.bitk=k;
|
||||
z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
|
||||
s.write=q;
|
||||
return s.inflate_flush(r);
|
||||
}
|
||||
mode = END;
|
||||
case END:
|
||||
r = Z_STREAM_END;
|
||||
s.bitb=b;s.bitk=k;
|
||||
z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
|
||||
s.write=q;
|
||||
return s.inflate_flush(r);
|
||||
|
||||
case BADCODE: // x: got error
|
||||
|
||||
r = Z_DATA_ERROR;
|
||||
|
||||
s.bitb=b;s.bitk=k;
|
||||
z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
|
||||
s.write=q;
|
||||
return s.inflate_flush(r);
|
||||
|
||||
default:
|
||||
r = Z_STREAM_ERROR;
|
||||
|
||||
s.bitb=b;s.bitk=k;
|
||||
z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
|
||||
s.write=q;
|
||||
return s.inflate_flush(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void free(ZStream z){
|
||||
// ZFREE(z, c);
|
||||
}
|
||||
|
||||
// Called with number of bytes left to write in window at least 258
|
||||
// (the maximum string length) and number of input bytes available
|
||||
// at least ten. The ten bytes are six bytes for the longest length/
|
||||
// distance pair plus four bytes for overloading the bit buffer.
|
||||
|
||||
int inflate_fast(int bl, int bd,
|
||||
int[] tl, int tl_index,
|
||||
int[] td, int td_index,
|
||||
InfBlocks s, ZStream z){
|
||||
int t; // temporary pointer
|
||||
int[] tp; // temporary pointer
|
||||
int tp_index; // temporary pointer
|
||||
int e; // extra bits or operation
|
||||
int b; // bit buffer
|
||||
int k; // bits in bit buffer
|
||||
int p; // input data pointer
|
||||
int n; // bytes available there
|
||||
int q; // output window write pointer
|
||||
int m; // bytes to end of window or read pointer
|
||||
int ml; // mask for literal/length tree
|
||||
int md; // mask for distance tree
|
||||
int c; // bytes to copy
|
||||
int d; // distance back to copy from
|
||||
int r; // copy source pointer
|
||||
|
||||
int tp_index_t_3; // (tp_index+t)*3
|
||||
|
||||
// load input, output, bit values
|
||||
p=z.next_in_index;n=z.avail_in;b=s.bitb;k=s.bitk;
|
||||
q=s.write;m=q<s.read?s.read-q-1:s.end-q;
|
||||
|
||||
// initialize masks
|
||||
ml = inflate_mask[bl];
|
||||
md = inflate_mask[bd];
|
||||
|
||||
// do until not enough input or output space for fast loop
|
||||
do { // assume called with m >= 258 && n >= 10
|
||||
// get literal/length code
|
||||
while(k<(20)){ // max bits for literal/length code
|
||||
n--;
|
||||
b|=(z.next_in[p++]&0xff)<<k;k+=8;
|
||||
}
|
||||
|
||||
t= b&ml;
|
||||
tp=tl;
|
||||
tp_index=tl_index;
|
||||
tp_index_t_3=(tp_index+t)*3;
|
||||
if ((e = tp[tp_index_t_3]) == 0){
|
||||
b>>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]);
|
||||
|
||||
s.window[q++] = (byte)tp[tp_index_t_3+2];
|
||||
m--;
|
||||
continue;
|
||||
}
|
||||
do {
|
||||
|
||||
b>>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]);
|
||||
|
||||
if((e&16)!=0){
|
||||
e &= 15;
|
||||
c = tp[tp_index_t_3+2] + ((int)b & inflate_mask[e]);
|
||||
|
||||
b>>=e; k-=e;
|
||||
|
||||
// decode distance base of block to copy
|
||||
while(k<(15)){ // max bits for distance code
|
||||
n--;
|
||||
b|=(z.next_in[p++]&0xff)<<k;k+=8;
|
||||
}
|
||||
|
||||
t= b&md;
|
||||
tp=td;
|
||||
tp_index=td_index;
|
||||
tp_index_t_3=(tp_index+t)*3;
|
||||
e = tp[tp_index_t_3];
|
||||
|
||||
do {
|
||||
|
||||
b>>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]);
|
||||
|
||||
if((e&16)!=0){
|
||||
// get extra bits to add to distance base
|
||||
e &= 15;
|
||||
while(k<(e)){ // get extra bits (up to 13)
|
||||
n--;
|
||||
b|=(z.next_in[p++]&0xff)<<k;k+=8;
|
||||
}
|
||||
|
||||
d = tp[tp_index_t_3+2] + (b&inflate_mask[e]);
|
||||
|
||||
b>>=(e); k-=(e);
|
||||
|
||||
// do the copy
|
||||
m -= c;
|
||||
if (q >= d){ // offset before dest
|
||||
// just copy
|
||||
r=q-d;
|
||||
if(q-r>0 && 2>(q-r)){
|
||||
s.window[q++]=s.window[r++]; // minimum count is three,
|
||||
s.window[q++]=s.window[r++]; // so unroll loop a little
|
||||
c-=2;
|
||||
}
|
||||
else{
|
||||
System.arraycopy(s.window, r, s.window, q, 2);
|
||||
q+=2; r+=2; c-=2;
|
||||
}
|
||||
}
|
||||
else{ // else offset after destination
|
||||
r=q-d;
|
||||
do{
|
||||
r+=s.end; // force pointer in window
|
||||
}while(r<0); // covers invalid distances
|
||||
e=s.end-r;
|
||||
if(c>e){ // if source crosses,
|
||||
c-=e; // wrapped copy
|
||||
if(q-r>0 && e>(q-r)){
|
||||
do{s.window[q++] = s.window[r++];}
|
||||
while(--e!=0);
|
||||
}
|
||||
else{
|
||||
System.arraycopy(s.window, r, s.window, q, e);
|
||||
q+=e; r+=e; e=0;
|
||||
}
|
||||
r = 0; // copy rest from start of window
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// copy all or what's left
|
||||
if(q-r>0 && c>(q-r)){
|
||||
do{s.window[q++] = s.window[r++];}
|
||||
while(--c!=0);
|
||||
}
|
||||
else{
|
||||
System.arraycopy(s.window, r, s.window, q, c);
|
||||
q+=c; r+=c; c=0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if((e&64)==0){
|
||||
t+=tp[tp_index_t_3+2];
|
||||
t+=(b&inflate_mask[e]);
|
||||
tp_index_t_3=(tp_index+t)*3;
|
||||
e=tp[tp_index_t_3];
|
||||
}
|
||||
else{
|
||||
z.msg = "invalid distance code";
|
||||
|
||||
c=z.avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;
|
||||
|
||||
s.bitb=b;s.bitk=k;
|
||||
z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
|
||||
s.write=q;
|
||||
|
||||
return Z_DATA_ERROR;
|
||||
}
|
||||
}
|
||||
while(true);
|
||||
break;
|
||||
}
|
||||
|
||||
if((e&64)==0){
|
||||
t+=tp[tp_index_t_3+2];
|
||||
t+=(b&inflate_mask[e]);
|
||||
tp_index_t_3=(tp_index+t)*3;
|
||||
if((e=tp[tp_index_t_3])==0){
|
||||
|
||||
b>>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]);
|
||||
|
||||
s.window[q++]=(byte)tp[tp_index_t_3+2];
|
||||
m--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if((e&32)!=0){
|
||||
|
||||
c=z.avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;
|
||||
|
||||
s.bitb=b;s.bitk=k;
|
||||
z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
|
||||
s.write=q;
|
||||
|
||||
return Z_STREAM_END;
|
||||
}
|
||||
else{
|
||||
z.msg="invalid literal/length code";
|
||||
|
||||
c=z.avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;
|
||||
|
||||
s.bitb=b;s.bitk=k;
|
||||
z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
|
||||
s.write=q;
|
||||
|
||||
return Z_DATA_ERROR;
|
||||
}
|
||||
}
|
||||
while(true);
|
||||
}
|
||||
while(m>=258 && n>= 10);
|
||||
|
||||
// not enough input or output--restore pointers and return
|
||||
c=z.avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;
|
||||
|
||||
s.bitb=b;s.bitk=k;
|
||||
z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
|
||||
s.write=q;
|
||||
|
||||
return Z_OK;
|
||||
}
|
||||
}
|
||||
518
src/lwjgl/java/com/jcraft/jzlib/InfTree.java
Normal file
518
src/lwjgl/java/com/jcraft/jzlib/InfTree.java
Normal file
@@ -0,0 +1,518 @@
|
||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
|
||||
/*
|
||||
Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. The names of the authors may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
|
||||
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/*
|
||||
* This program is based on zlib-1.1.3, so all credit should go authors
|
||||
* Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
|
||||
* and contributors of zlib.
|
||||
*/
|
||||
|
||||
package com.jcraft.jzlib;
|
||||
|
||||
final class InfTree{
|
||||
|
||||
static final private int MANY=1440;
|
||||
|
||||
static final private int Z_OK=0;
|
||||
static final private int Z_STREAM_END=1;
|
||||
static final private int Z_NEED_DICT=2;
|
||||
static final private int Z_ERRNO=-1;
|
||||
static final private int Z_STREAM_ERROR=-2;
|
||||
static final private int Z_DATA_ERROR=-3;
|
||||
static final private int Z_MEM_ERROR=-4;
|
||||
static final private int Z_BUF_ERROR=-5;
|
||||
static final private int Z_VERSION_ERROR=-6;
|
||||
|
||||
static final int fixed_bl = 9;
|
||||
static final int fixed_bd = 5;
|
||||
|
||||
static final int[] fixed_tl = {
|
||||
96,7,256, 0,8,80, 0,8,16, 84,8,115,
|
||||
82,7,31, 0,8,112, 0,8,48, 0,9,192,
|
||||
80,7,10, 0,8,96, 0,8,32, 0,9,160,
|
||||
0,8,0, 0,8,128, 0,8,64, 0,9,224,
|
||||
80,7,6, 0,8,88, 0,8,24, 0,9,144,
|
||||
83,7,59, 0,8,120, 0,8,56, 0,9,208,
|
||||
81,7,17, 0,8,104, 0,8,40, 0,9,176,
|
||||
0,8,8, 0,8,136, 0,8,72, 0,9,240,
|
||||
80,7,4, 0,8,84, 0,8,20, 85,8,227,
|
||||
83,7,43, 0,8,116, 0,8,52, 0,9,200,
|
||||
81,7,13, 0,8,100, 0,8,36, 0,9,168,
|
||||
0,8,4, 0,8,132, 0,8,68, 0,9,232,
|
||||
80,7,8, 0,8,92, 0,8,28, 0,9,152,
|
||||
84,7,83, 0,8,124, 0,8,60, 0,9,216,
|
||||
82,7,23, 0,8,108, 0,8,44, 0,9,184,
|
||||
0,8,12, 0,8,140, 0,8,76, 0,9,248,
|
||||
80,7,3, 0,8,82, 0,8,18, 85,8,163,
|
||||
83,7,35, 0,8,114, 0,8,50, 0,9,196,
|
||||
81,7,11, 0,8,98, 0,8,34, 0,9,164,
|
||||
0,8,2, 0,8,130, 0,8,66, 0,9,228,
|
||||
80,7,7, 0,8,90, 0,8,26, 0,9,148,
|
||||
84,7,67, 0,8,122, 0,8,58, 0,9,212,
|
||||
82,7,19, 0,8,106, 0,8,42, 0,9,180,
|
||||
0,8,10, 0,8,138, 0,8,74, 0,9,244,
|
||||
80,7,5, 0,8,86, 0,8,22, 192,8,0,
|
||||
83,7,51, 0,8,118, 0,8,54, 0,9,204,
|
||||
81,7,15, 0,8,102, 0,8,38, 0,9,172,
|
||||
0,8,6, 0,8,134, 0,8,70, 0,9,236,
|
||||
80,7,9, 0,8,94, 0,8,30, 0,9,156,
|
||||
84,7,99, 0,8,126, 0,8,62, 0,9,220,
|
||||
82,7,27, 0,8,110, 0,8,46, 0,9,188,
|
||||
0,8,14, 0,8,142, 0,8,78, 0,9,252,
|
||||
96,7,256, 0,8,81, 0,8,17, 85,8,131,
|
||||
82,7,31, 0,8,113, 0,8,49, 0,9,194,
|
||||
80,7,10, 0,8,97, 0,8,33, 0,9,162,
|
||||
0,8,1, 0,8,129, 0,8,65, 0,9,226,
|
||||
80,7,6, 0,8,89, 0,8,25, 0,9,146,
|
||||
83,7,59, 0,8,121, 0,8,57, 0,9,210,
|
||||
81,7,17, 0,8,105, 0,8,41, 0,9,178,
|
||||
0,8,9, 0,8,137, 0,8,73, 0,9,242,
|
||||
80,7,4, 0,8,85, 0,8,21, 80,8,258,
|
||||
83,7,43, 0,8,117, 0,8,53, 0,9,202,
|
||||
81,7,13, 0,8,101, 0,8,37, 0,9,170,
|
||||
0,8,5, 0,8,133, 0,8,69, 0,9,234,
|
||||
80,7,8, 0,8,93, 0,8,29, 0,9,154,
|
||||
84,7,83, 0,8,125, 0,8,61, 0,9,218,
|
||||
82,7,23, 0,8,109, 0,8,45, 0,9,186,
|
||||
0,8,13, 0,8,141, 0,8,77, 0,9,250,
|
||||
80,7,3, 0,8,83, 0,8,19, 85,8,195,
|
||||
83,7,35, 0,8,115, 0,8,51, 0,9,198,
|
||||
81,7,11, 0,8,99, 0,8,35, 0,9,166,
|
||||
0,8,3, 0,8,131, 0,8,67, 0,9,230,
|
||||
80,7,7, 0,8,91, 0,8,27, 0,9,150,
|
||||
84,7,67, 0,8,123, 0,8,59, 0,9,214,
|
||||
82,7,19, 0,8,107, 0,8,43, 0,9,182,
|
||||
0,8,11, 0,8,139, 0,8,75, 0,9,246,
|
||||
80,7,5, 0,8,87, 0,8,23, 192,8,0,
|
||||
83,7,51, 0,8,119, 0,8,55, 0,9,206,
|
||||
81,7,15, 0,8,103, 0,8,39, 0,9,174,
|
||||
0,8,7, 0,8,135, 0,8,71, 0,9,238,
|
||||
80,7,9, 0,8,95, 0,8,31, 0,9,158,
|
||||
84,7,99, 0,8,127, 0,8,63, 0,9,222,
|
||||
82,7,27, 0,8,111, 0,8,47, 0,9,190,
|
||||
0,8,15, 0,8,143, 0,8,79, 0,9,254,
|
||||
96,7,256, 0,8,80, 0,8,16, 84,8,115,
|
||||
82,7,31, 0,8,112, 0,8,48, 0,9,193,
|
||||
|
||||
80,7,10, 0,8,96, 0,8,32, 0,9,161,
|
||||
0,8,0, 0,8,128, 0,8,64, 0,9,225,
|
||||
80,7,6, 0,8,88, 0,8,24, 0,9,145,
|
||||
83,7,59, 0,8,120, 0,8,56, 0,9,209,
|
||||
81,7,17, 0,8,104, 0,8,40, 0,9,177,
|
||||
0,8,8, 0,8,136, 0,8,72, 0,9,241,
|
||||
80,7,4, 0,8,84, 0,8,20, 85,8,227,
|
||||
83,7,43, 0,8,116, 0,8,52, 0,9,201,
|
||||
81,7,13, 0,8,100, 0,8,36, 0,9,169,
|
||||
0,8,4, 0,8,132, 0,8,68, 0,9,233,
|
||||
80,7,8, 0,8,92, 0,8,28, 0,9,153,
|
||||
84,7,83, 0,8,124, 0,8,60, 0,9,217,
|
||||
82,7,23, 0,8,108, 0,8,44, 0,9,185,
|
||||
0,8,12, 0,8,140, 0,8,76, 0,9,249,
|
||||
80,7,3, 0,8,82, 0,8,18, 85,8,163,
|
||||
83,7,35, 0,8,114, 0,8,50, 0,9,197,
|
||||
81,7,11, 0,8,98, 0,8,34, 0,9,165,
|
||||
0,8,2, 0,8,130, 0,8,66, 0,9,229,
|
||||
80,7,7, 0,8,90, 0,8,26, 0,9,149,
|
||||
84,7,67, 0,8,122, 0,8,58, 0,9,213,
|
||||
82,7,19, 0,8,106, 0,8,42, 0,9,181,
|
||||
0,8,10, 0,8,138, 0,8,74, 0,9,245,
|
||||
80,7,5, 0,8,86, 0,8,22, 192,8,0,
|
||||
83,7,51, 0,8,118, 0,8,54, 0,9,205,
|
||||
81,7,15, 0,8,102, 0,8,38, 0,9,173,
|
||||
0,8,6, 0,8,134, 0,8,70, 0,9,237,
|
||||
80,7,9, 0,8,94, 0,8,30, 0,9,157,
|
||||
84,7,99, 0,8,126, 0,8,62, 0,9,221,
|
||||
82,7,27, 0,8,110, 0,8,46, 0,9,189,
|
||||
0,8,14, 0,8,142, 0,8,78, 0,9,253,
|
||||
96,7,256, 0,8,81, 0,8,17, 85,8,131,
|
||||
82,7,31, 0,8,113, 0,8,49, 0,9,195,
|
||||
80,7,10, 0,8,97, 0,8,33, 0,9,163,
|
||||
0,8,1, 0,8,129, 0,8,65, 0,9,227,
|
||||
80,7,6, 0,8,89, 0,8,25, 0,9,147,
|
||||
83,7,59, 0,8,121, 0,8,57, 0,9,211,
|
||||
81,7,17, 0,8,105, 0,8,41, 0,9,179,
|
||||
0,8,9, 0,8,137, 0,8,73, 0,9,243,
|
||||
80,7,4, 0,8,85, 0,8,21, 80,8,258,
|
||||
83,7,43, 0,8,117, 0,8,53, 0,9,203,
|
||||
81,7,13, 0,8,101, 0,8,37, 0,9,171,
|
||||
0,8,5, 0,8,133, 0,8,69, 0,9,235,
|
||||
80,7,8, 0,8,93, 0,8,29, 0,9,155,
|
||||
84,7,83, 0,8,125, 0,8,61, 0,9,219,
|
||||
82,7,23, 0,8,109, 0,8,45, 0,9,187,
|
||||
0,8,13, 0,8,141, 0,8,77, 0,9,251,
|
||||
80,7,3, 0,8,83, 0,8,19, 85,8,195,
|
||||
83,7,35, 0,8,115, 0,8,51, 0,9,199,
|
||||
81,7,11, 0,8,99, 0,8,35, 0,9,167,
|
||||
0,8,3, 0,8,131, 0,8,67, 0,9,231,
|
||||
80,7,7, 0,8,91, 0,8,27, 0,9,151,
|
||||
84,7,67, 0,8,123, 0,8,59, 0,9,215,
|
||||
82,7,19, 0,8,107, 0,8,43, 0,9,183,
|
||||
0,8,11, 0,8,139, 0,8,75, 0,9,247,
|
||||
80,7,5, 0,8,87, 0,8,23, 192,8,0,
|
||||
83,7,51, 0,8,119, 0,8,55, 0,9,207,
|
||||
81,7,15, 0,8,103, 0,8,39, 0,9,175,
|
||||
0,8,7, 0,8,135, 0,8,71, 0,9,239,
|
||||
80,7,9, 0,8,95, 0,8,31, 0,9,159,
|
||||
84,7,99, 0,8,127, 0,8,63, 0,9,223,
|
||||
82,7,27, 0,8,111, 0,8,47, 0,9,191,
|
||||
0,8,15, 0,8,143, 0,8,79, 0,9,255
|
||||
};
|
||||
static final int[] fixed_td = {
|
||||
80,5,1, 87,5,257, 83,5,17, 91,5,4097,
|
||||
81,5,5, 89,5,1025, 85,5,65, 93,5,16385,
|
||||
80,5,3, 88,5,513, 84,5,33, 92,5,8193,
|
||||
82,5,9, 90,5,2049, 86,5,129, 192,5,24577,
|
||||
80,5,2, 87,5,385, 83,5,25, 91,5,6145,
|
||||
81,5,7, 89,5,1537, 85,5,97, 93,5,24577,
|
||||
80,5,4, 88,5,769, 84,5,49, 92,5,12289,
|
||||
82,5,13, 90,5,3073, 86,5,193, 192,5,24577
|
||||
};
|
||||
|
||||
// Tables for deflate from PKZIP's appnote.txt.
|
||||
static final int[] cplens = { // Copy lengths for literal codes 257..285
|
||||
3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
|
||||
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0
|
||||
};
|
||||
|
||||
// see note #13 above about 258
|
||||
static final int[] cplext = { // Extra bits for literal codes 257..285
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
|
||||
3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112 // 112==invalid
|
||||
};
|
||||
|
||||
static final int[] cpdist = { // Copy offsets for distance codes 0..29
|
||||
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
|
||||
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
|
||||
8193, 12289, 16385, 24577
|
||||
};
|
||||
|
||||
static final int[] cpdext = { // Extra bits for distance codes
|
||||
0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
|
||||
7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
|
||||
12, 12, 13, 13};
|
||||
|
||||
// If BMAX needs to be larger than 16, then h and x[] should be uLong.
|
||||
static final int BMAX=15; // maximum bit length of any code
|
||||
|
||||
int[] hn = null; // hufts used in space
|
||||
int[] v = null; // work area for huft_build
|
||||
int[] c = null; // bit length count table
|
||||
int[] r = null; // table entry for structure assignment
|
||||
int[] u = null; // table stack
|
||||
int[] x = null; // bit offsets, then code stack
|
||||
|
||||
private int huft_build(int[] b, // code lengths in bits (all assumed <= BMAX)
|
||||
int bindex,
|
||||
int n, // number of codes (assumed <= 288)
|
||||
int s, // number of simple-valued codes (0..s-1)
|
||||
int[] d, // list of base values for non-simple codes
|
||||
int[] e, // list of extra bits for non-simple codes
|
||||
int[] t, // result: starting table
|
||||
int[] m, // maximum lookup bits, returns actual
|
||||
int[] hp,// space for trees
|
||||
int[] hn,// hufts used in space
|
||||
int[] v // working area: values in order of bit length
|
||||
){
|
||||
// Given a list of code lengths and a maximum table size, make a set of
|
||||
// tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR
|
||||
// if the given code set is incomplete (the tables are still built in this
|
||||
// case), Z_DATA_ERROR if the input is invalid (an over-subscribed set of
|
||||
// lengths), or Z_MEM_ERROR if not enough memory.
|
||||
|
||||
int a; // counter for codes of length k
|
||||
int f; // i repeats in table every f entries
|
||||
int g; // maximum code length
|
||||
int h; // table level
|
||||
int i; // counter, current code
|
||||
int j; // counter
|
||||
int k; // number of bits in current code
|
||||
int l; // bits per table (returned in m)
|
||||
int mask; // (1 << w) - 1, to avoid cc -O bug on HP
|
||||
int p; // pointer into c[], b[], or v[]
|
||||
int q; // points to current table
|
||||
int w; // bits before this table == (l * h)
|
||||
int xp; // pointer into x
|
||||
int y; // number of dummy codes added
|
||||
int z; // number of entries in current table
|
||||
|
||||
// Generate counts for each bit length
|
||||
|
||||
p = 0; i = n;
|
||||
do {
|
||||
c[b[bindex+p]]++; p++; i--; // assume all entries <= BMAX
|
||||
}while(i!=0);
|
||||
|
||||
if(c[0] == n){ // null input--all zero length codes
|
||||
t[0] = -1;
|
||||
m[0] = 0;
|
||||
return Z_OK;
|
||||
}
|
||||
|
||||
// Find minimum and maximum length, bound *m by those
|
||||
l = m[0];
|
||||
for (j = 1; j <= BMAX; j++)
|
||||
if(c[j]!=0) break;
|
||||
k = j; // minimum code length
|
||||
if(l < j){
|
||||
l = j;
|
||||
}
|
||||
for (i = BMAX; i!=0; i--){
|
||||
if(c[i]!=0) break;
|
||||
}
|
||||
g = i; // maximum code length
|
||||
if(l > i){
|
||||
l = i;
|
||||
}
|
||||
m[0] = l;
|
||||
|
||||
// Adjust last length count to fill out codes, if needed
|
||||
for (y = 1 << j; j < i; j++, y <<= 1){
|
||||
if ((y -= c[j]) < 0){
|
||||
return Z_DATA_ERROR;
|
||||
}
|
||||
}
|
||||
if ((y -= c[i]) < 0){
|
||||
return Z_DATA_ERROR;
|
||||
}
|
||||
c[i] += y;
|
||||
|
||||
// Generate starting offsets into the value table for each length
|
||||
x[1] = j = 0;
|
||||
p = 1; xp = 2;
|
||||
while (--i!=0) { // note that i == g from above
|
||||
x[xp] = (j += c[p]);
|
||||
xp++;
|
||||
p++;
|
||||
}
|
||||
|
||||
// Make a table of values in order of bit lengths
|
||||
i = 0; p = 0;
|
||||
do {
|
||||
if ((j = b[bindex+p]) != 0){
|
||||
v[x[j]++] = i;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
while (++i < n);
|
||||
n = x[g]; // set n to length of v
|
||||
|
||||
// Generate the Huffman codes and for each, make the table entries
|
||||
x[0] = i = 0; // first Huffman code is zero
|
||||
p = 0; // grab values in bit order
|
||||
h = -1; // no tables yet--level -1
|
||||
w = -l; // bits decoded == (l * h)
|
||||
u[0] = 0; // just to keep compilers happy
|
||||
q = 0; // ditto
|
||||
z = 0; // ditto
|
||||
|
||||
// go through the bit lengths (k already is bits in shortest code)
|
||||
for (; k <= g; k++){
|
||||
a = c[k];
|
||||
while (a--!=0){
|
||||
// here i is the Huffman code of length k bits for value *p
|
||||
// make tables up to required level
|
||||
while (k > w + l){
|
||||
h++;
|
||||
w += l; // previous table always l bits
|
||||
// compute minimum size table less than or equal to l bits
|
||||
z = g - w;
|
||||
z = (z > l) ? l : z; // table size upper limit
|
||||
if((f=1<<(j=k-w))>a+1){ // try a k-w bit table
|
||||
// too few codes for k-w bit table
|
||||
f -= a + 1; // deduct codes from patterns left
|
||||
xp = k;
|
||||
if(j < z){
|
||||
while (++j < z){ // try smaller tables up to z bits
|
||||
if((f <<= 1) <= c[++xp])
|
||||
break; // enough codes to use up j bits
|
||||
f -= c[xp]; // else deduct codes from patterns
|
||||
}
|
||||
}
|
||||
}
|
||||
z = 1 << j; // table entries for j-bit table
|
||||
|
||||
// allocate new table
|
||||
if (hn[0] + z > MANY){ // (note: doesn't matter for fixed)
|
||||
return Z_DATA_ERROR; // overflow of MANY
|
||||
}
|
||||
u[h] = q = /*hp+*/ hn[0]; // DEBUG
|
||||
hn[0] += z;
|
||||
|
||||
// connect to last table, if there is one
|
||||
if(h!=0){
|
||||
x[h]=i; // save pattern for backing up
|
||||
r[0]=(byte)j; // bits in this table
|
||||
r[1]=(byte)l; // bits to dump before this table
|
||||
j=i>>>(w - l);
|
||||
r[2] = (int)(q - u[h-1] - j); // offset to this table
|
||||
System.arraycopy(r, 0, hp, (u[h-1]+j)*3, 3); // connect to last table
|
||||
}
|
||||
else{
|
||||
t[0] = q; // first table is returned result
|
||||
}
|
||||
}
|
||||
|
||||
// set up table entry in r
|
||||
r[1] = (byte)(k - w);
|
||||
if (p >= n){
|
||||
r[0] = 128 + 64; // out of values--invalid code
|
||||
}
|
||||
else if (v[p] < s){
|
||||
r[0] = (byte)(v[p] < 256 ? 0 : 32 + 64); // 256 is end-of-block
|
||||
r[2] = v[p++]; // simple code is just the value
|
||||
}
|
||||
else{
|
||||
r[0]=(byte)(e[v[p]-s]+16+64); // non-simple--look up in lists
|
||||
r[2]=d[v[p++] - s];
|
||||
}
|
||||
|
||||
// fill code-like entries with r
|
||||
f=1<<(k-w);
|
||||
for (j=i>>>w;j<z;j+=f){
|
||||
System.arraycopy(r, 0, hp, (q+j)*3, 3);
|
||||
}
|
||||
|
||||
// backwards increment the k-bit code i
|
||||
for (j = 1 << (k - 1); (i & j)!=0; j >>>= 1){
|
||||
i ^= j;
|
||||
}
|
||||
i ^= j;
|
||||
|
||||
// backup over finished tables
|
||||
mask = (1 << w) - 1; // needed on HP, cc -O bug
|
||||
while ((i & mask) != x[h]){
|
||||
h--; // don't need to update q
|
||||
w -= l;
|
||||
mask = (1 << w) - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Return Z_BUF_ERROR if we were given an incomplete table
|
||||
return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK;
|
||||
}
|
||||
|
||||
int inflate_trees_bits(int[] c, // 19 code lengths
|
||||
int[] bb, // bits tree desired/actual depth
|
||||
int[] tb, // bits tree result
|
||||
int[] hp, // space for trees
|
||||
ZStream z // for messages
|
||||
){
|
||||
int result;
|
||||
initWorkArea(19);
|
||||
hn[0]=0;
|
||||
result = huft_build(c, 0, 19, 19, null, null, tb, bb, hp, hn, v);
|
||||
|
||||
if(result == Z_DATA_ERROR){
|
||||
z.msg = "oversubscribed dynamic bit lengths tree";
|
||||
}
|
||||
else if(result == Z_BUF_ERROR || bb[0] == 0){
|
||||
z.msg = "incomplete dynamic bit lengths tree";
|
||||
result = Z_DATA_ERROR;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int inflate_trees_dynamic(int nl, // number of literal/length codes
|
||||
int nd, // number of distance codes
|
||||
int[] c, // that many (total) code lengths
|
||||
int[] bl, // literal desired/actual bit depth
|
||||
int[] bd, // distance desired/actual bit depth
|
||||
int[] tl, // literal/length tree result
|
||||
int[] td, // distance tree result
|
||||
int[] hp, // space for trees
|
||||
ZStream z // for messages
|
||||
){
|
||||
int result;
|
||||
|
||||
// build literal/length tree
|
||||
initWorkArea(288);
|
||||
hn[0]=0;
|
||||
result = huft_build(c, 0, nl, 257, cplens, cplext, tl, bl, hp, hn, v);
|
||||
if (result != Z_OK || bl[0] == 0){
|
||||
if(result == Z_DATA_ERROR){
|
||||
z.msg = "oversubscribed literal/length tree";
|
||||
}
|
||||
else if (result != Z_MEM_ERROR){
|
||||
z.msg = "incomplete literal/length tree";
|
||||
result = Z_DATA_ERROR;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// build distance tree
|
||||
initWorkArea(288);
|
||||
result = huft_build(c, nl, nd, 0, cpdist, cpdext, td, bd, hp, hn, v);
|
||||
|
||||
if (result != Z_OK || (bd[0] == 0 && nl > 257)){
|
||||
if (result == Z_DATA_ERROR){
|
||||
z.msg = "oversubscribed distance tree";
|
||||
}
|
||||
else if (result == Z_BUF_ERROR) {
|
||||
z.msg = "incomplete distance tree";
|
||||
result = Z_DATA_ERROR;
|
||||
}
|
||||
else if (result != Z_MEM_ERROR){
|
||||
z.msg = "empty distance tree with lengths";
|
||||
result = Z_DATA_ERROR;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
return Z_OK;
|
||||
}
|
||||
|
||||
static int inflate_trees_fixed(int[] bl, //literal desired/actual bit depth
|
||||
int[] bd, //distance desired/actual bit depth
|
||||
int[][] tl,//literal/length tree result
|
||||
int[][] td,//distance tree result
|
||||
ZStream z //for memory allocation
|
||||
){
|
||||
bl[0]=fixed_bl;
|
||||
bd[0]=fixed_bd;
|
||||
tl[0]=fixed_tl;
|
||||
td[0]=fixed_td;
|
||||
return Z_OK;
|
||||
}
|
||||
|
||||
private void initWorkArea(int vsize){
|
||||
if(hn==null){
|
||||
hn=new int[1];
|
||||
v=new int[vsize];
|
||||
c=new int[BMAX+1];
|
||||
r=new int[3];
|
||||
u=new int[BMAX];
|
||||
x=new int[BMAX+1];
|
||||
}
|
||||
if(v.length<vsize){ v=new int[vsize]; }
|
||||
for(int i=0; i<vsize; i++){v[i]=0;}
|
||||
for(int i=0; i<BMAX+1; i++){c[i]=0;}
|
||||
for(int i=0; i<3; i++){r[i]=0;}
|
||||
System.arraycopy(c, 0, u, 0, BMAX);
|
||||
System.arraycopy(c, 0, x, 0, BMAX+1);
|
||||
}
|
||||
}
|
||||
751
src/lwjgl/java/com/jcraft/jzlib/Inflate.java
Normal file
751
src/lwjgl/java/com/jcraft/jzlib/Inflate.java
Normal file
@@ -0,0 +1,751 @@
|
||||
/* -*-mode:java; c-basic-offset:2; -*- */
|
||||
/*
|
||||
Copyright (c) 2000-2011 ymnk, JCraft,Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. The names of the authors may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
|
||||
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/*
|
||||
* This program is based on zlib-1.1.3, so all credit should go authors
|
||||
* Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
|
||||
* and contributors of zlib.
|
||||
*/
|
||||
|
||||
package com.jcraft.jzlib;
|
||||
|
||||
final class Inflate{
|
||||
|
||||
static final private int MAX_WBITS=15; // 32K LZ77 window
|
||||
|
||||
// preset dictionary flag in zlib header
|
||||
static final private int PRESET_DICT=0x20;
|
||||
|
||||
static final int Z_NO_FLUSH=0;
|
||||
static final int Z_PARTIAL_FLUSH=1;
|
||||
static final int Z_SYNC_FLUSH=2;
|
||||
static final int Z_FULL_FLUSH=3;
|
||||
static final int Z_FINISH=4;
|
||||
|
||||
static final private int Z_DEFLATED=8;
|
||||
|
||||
static final private int Z_OK=0;
|
||||
static final private int Z_STREAM_END=1;
|
||||
static final private int Z_NEED_DICT=2;
|
||||
static final private int Z_ERRNO=-1;
|
||||
static final private int Z_STREAM_ERROR=-2;
|
||||
static final private int Z_DATA_ERROR=-3;
|
||||
static final private int Z_MEM_ERROR=-4;
|
||||
static final private int Z_BUF_ERROR=-5;
|
||||
static final private int Z_VERSION_ERROR=-6;
|
||||
|
||||
static final private int METHOD=0; // waiting for method byte
|
||||
static final private int FLAG=1; // waiting for flag byte
|
||||
static final private int DICT4=2; // four dictionary check bytes to go
|
||||
static final private int DICT3=3; // three dictionary check bytes to go
|
||||
static final private int DICT2=4; // two dictionary check bytes to go
|
||||
static final private int DICT1=5; // one dictionary check byte to go
|
||||
static final private int DICT0=6; // waiting for inflateSetDictionary
|
||||
static final private int BLOCKS=7; // decompressing blocks
|
||||
static final private int CHECK4=8; // four check bytes to go
|
||||
static final private int CHECK3=9; // three check bytes to go
|
||||
static final private int CHECK2=10; // two check bytes to go
|
||||
static final private int CHECK1=11; // one check byte to go
|
||||
static final private int DONE=12; // finished check, done
|
||||
static final private int BAD=13; // got an error--stay here
|
||||
|
||||
static final private int HEAD=14;
|
||||
static final private int LENGTH=15;
|
||||
static final private int TIME=16;
|
||||
static final private int OS=17;
|
||||
static final private int EXLEN=18;
|
||||
static final private int EXTRA=19;
|
||||
static final private int NAME=20;
|
||||
static final private int COMMENT=21;
|
||||
static final private int HCRC=22;
|
||||
static final private int FLAGS=23;
|
||||
|
||||
static final int INFLATE_ANY=0x40000000;
|
||||
|
||||
int mode; // current inflate mode
|
||||
|
||||
// mode dependent information
|
||||
int method; // if FLAGS, method byte
|
||||
|
||||
// if CHECK, check values to compare
|
||||
long was = -1; // computed check value
|
||||
long need; // stream check value
|
||||
|
||||
// if BAD, inflateSync's marker bytes count
|
||||
int marker;
|
||||
|
||||
// mode independent information
|
||||
int wrap; // flag for no wrapper
|
||||
// 0: no wrapper
|
||||
// 1: zlib header
|
||||
// 2: gzip header
|
||||
// 4: auto detection
|
||||
|
||||
int wbits; // log2(window size) (8..15, defaults to 15)
|
||||
|
||||
InfBlocks blocks; // current inflate_blocks state
|
||||
|
||||
private final ZStream z;
|
||||
|
||||
private int flags;
|
||||
|
||||
private int need_bytes = -1;
|
||||
private byte[] crcbuf=new byte[4];
|
||||
|
||||
GZIPHeader gheader = null;
|
||||
|
||||
int inflateReset(){
|
||||
if(z == null) return Z_STREAM_ERROR;
|
||||
|
||||
z.total_in = z.total_out = 0;
|
||||
z.msg = null;
|
||||
this.mode = HEAD;
|
||||
this.need_bytes = -1;
|
||||
this.blocks.reset();
|
||||
return Z_OK;
|
||||
}
|
||||
|
||||
int inflateEnd(){
|
||||
if(blocks != null){
|
||||
blocks.free();
|
||||
}
|
||||
return Z_OK;
|
||||
}
|
||||
|
||||
Inflate(ZStream z){
|
||||
this.z=z;
|
||||
}
|
||||
|
||||
int inflateInit(int w){
|
||||
z.msg = null;
|
||||
blocks = null;
|
||||
|
||||
// handle undocumented wrap option (no zlib header or check)
|
||||
wrap = 0;
|
||||
if(w < 0){
|
||||
w = - w;
|
||||
}
|
||||
else if((w&INFLATE_ANY) != 0){
|
||||
wrap = 4;
|
||||
w &= ~INFLATE_ANY;
|
||||
if(w < 48)
|
||||
w &= 15;
|
||||
}
|
||||
else if((w & ~31) != 0) { // for example, DEF_WBITS + 32
|
||||
wrap = 4; // zlib and gzip wrapped data should be accepted.
|
||||
w &= 15;
|
||||
}
|
||||
else {
|
||||
wrap = (w >> 4) + 1;
|
||||
if(w < 48)
|
||||
w &= 15;
|
||||
}
|
||||
|
||||
if(w<8 ||w>15){
|
||||
inflateEnd();
|
||||
return Z_STREAM_ERROR;
|
||||
}
|
||||
if(blocks != null && wbits != w){
|
||||
blocks.free();
|
||||
blocks=null;
|
||||
}
|
||||
|
||||
// set window size
|
||||
wbits=w;
|
||||
|
||||
this.blocks=new InfBlocks(z, 1<<w);
|
||||
|
||||
// reset state
|
||||
inflateReset();
|
||||
|
||||
return Z_OK;
|
||||
}
|
||||
|
||||
int inflate(int f){
|
||||
int hold = 0;
|
||||
|
||||
int r;
|
||||
int b;
|
||||
|
||||
if(z == null || z.next_in == null){
|
||||
if(f == Z_FINISH && this.mode==HEAD)
|
||||
return Z_OK;
|
||||
return Z_STREAM_ERROR;
|
||||
}
|
||||
|
||||
f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK;
|
||||
r = Z_BUF_ERROR;
|
||||
while (true){
|
||||
|
||||
switch (this.mode){
|
||||
case HEAD:
|
||||
if(wrap==0){
|
||||
this.mode = BLOCKS;
|
||||
break;
|
||||
}
|
||||
|
||||
try { r=readBytes(2, r, f); }
|
||||
catch(Return e){ return e.r; }
|
||||
|
||||
if((wrap == 4 || (wrap&2)!=0) &&
|
||||
this.need == 0x8b1fL) { // gzip header
|
||||
if(wrap == 4){
|
||||
wrap = 2;
|
||||
}
|
||||
z.adler=new CRC32();
|
||||
checksum(2, this.need);
|
||||
|
||||
if(gheader==null)
|
||||
gheader=new GZIPHeader();
|
||||
|
||||
this.mode = FLAGS;
|
||||
break;
|
||||
}
|
||||
|
||||
if((wrap&2) != 0){
|
||||
this.mode = BAD;
|
||||
z.msg = "incorrect header check";
|
||||
break;
|
||||
}
|
||||
|
||||
flags = 0;
|
||||
|
||||
this.method = ((int)this.need)&0xff;
|
||||
b=((int)(this.need>>8))&0xff;
|
||||
|
||||
if(((wrap&1)==0 || // check if zlib header allowed
|
||||
(((this.method << 8)+b) % 31)!=0) &&
|
||||
(this.method&0xf)!=Z_DEFLATED){
|
||||
if(wrap == 4){
|
||||
z.next_in_index -= 2;
|
||||
z.avail_in += 2;
|
||||
z.total_in -= 2;
|
||||
wrap = 0;
|
||||
this.mode = BLOCKS;
|
||||
break;
|
||||
}
|
||||
this.mode = BAD;
|
||||
z.msg = "incorrect header check";
|
||||
// since zlib 1.2, it is allowted to inflateSync for this case.
|
||||
/*
|
||||
this.marker = 5; // can't try inflateSync
|
||||
*/
|
||||
break;
|
||||
}
|
||||
|
||||
if((this.method&0xf)!=Z_DEFLATED){
|
||||
this.mode = BAD;
|
||||
z.msg="unknown compression method";
|
||||
// since zlib 1.2, it is allowted to inflateSync for this case.
|
||||
/*
|
||||
this.marker = 5; // can't try inflateSync
|
||||
*/
|
||||
break;
|
||||
}
|
||||
|
||||
if(wrap == 4){
|
||||
wrap = 1;
|
||||
}
|
||||
|
||||
if((this.method>>4)+8>this.wbits){
|
||||
this.mode = BAD;
|
||||
z.msg="invalid window size";
|
||||
// since zlib 1.2, it is allowted to inflateSync for this case.
|
||||
/*
|
||||
this.marker = 5; // can't try inflateSync
|
||||
*/
|
||||
break;
|
||||
}
|
||||
|
||||
z.adler=new Adler32();
|
||||
|
||||
if((b&PRESET_DICT)==0){
|
||||
this.mode = BLOCKS;
|
||||
break;
|
||||
}
|
||||
this.mode = DICT4;
|
||||
case DICT4:
|
||||
|
||||
if(z.avail_in==0)return r;r=f;
|
||||
|
||||
z.avail_in--; z.total_in++;
|
||||
this.need=((z.next_in[z.next_in_index++]&0xff)<<24)&0xff000000L;
|
||||
this.mode=DICT3;
|
||||
case DICT3:
|
||||
|
||||
if(z.avail_in==0)return r;r=f;
|
||||
|
||||
z.avail_in--; z.total_in++;
|
||||
this.need+=((z.next_in[z.next_in_index++]&0xff)<<16)&0xff0000L;
|
||||
this.mode=DICT2;
|
||||
case DICT2:
|
||||
|
||||
if(z.avail_in==0)return r;r=f;
|
||||
|
||||
z.avail_in--; z.total_in++;
|
||||
this.need+=((z.next_in[z.next_in_index++]&0xff)<<8)&0xff00L;
|
||||
this.mode=DICT1;
|
||||
case DICT1:
|
||||
|
||||
if(z.avail_in==0)return r;r=f;
|
||||
|
||||
z.avail_in--; z.total_in++;
|
||||
this.need += (z.next_in[z.next_in_index++]&0xffL);
|
||||
z.adler.reset(this.need);
|
||||
this.mode = DICT0;
|
||||
return Z_NEED_DICT;
|
||||
case DICT0:
|
||||
this.mode = BAD;
|
||||
z.msg = "need dictionary";
|
||||
this.marker = 0; // can try inflateSync
|
||||
return Z_STREAM_ERROR;
|
||||
case BLOCKS:
|
||||
r = this.blocks.proc(r);
|
||||
if(r == Z_DATA_ERROR){
|
||||
this.mode = BAD;
|
||||
this.marker = 0; // can try inflateSync
|
||||
break;
|
||||
}
|
||||
if(r == Z_OK){
|
||||
r = f;
|
||||
}
|
||||
if(r != Z_STREAM_END){
|
||||
return r;
|
||||
}
|
||||
r = f;
|
||||
this.was=z.adler.getValue();
|
||||
this.blocks.reset();
|
||||
if(this.wrap==0){
|
||||
this.mode=DONE;
|
||||
break;
|
||||
}
|
||||
this.mode=CHECK4;
|
||||
case CHECK4:
|
||||
|
||||
if(z.avail_in==0)return r;r=f;
|
||||
|
||||
z.avail_in--; z.total_in++;
|
||||
this.need=((z.next_in[z.next_in_index++]&0xff)<<24)&0xff000000L;
|
||||
this.mode=CHECK3;
|
||||
case CHECK3:
|
||||
|
||||
if(z.avail_in==0)return r;r=f;
|
||||
|
||||
z.avail_in--; z.total_in++;
|
||||
this.need+=((z.next_in[z.next_in_index++]&0xff)<<16)&0xff0000L;
|
||||
this.mode = CHECK2;
|
||||
case CHECK2:
|
||||
|
||||
if(z.avail_in==0)return r;r=f;
|
||||
|
||||
z.avail_in--; z.total_in++;
|
||||
this.need+=((z.next_in[z.next_in_index++]&0xff)<<8)&0xff00L;
|
||||
this.mode = CHECK1;
|
||||
case CHECK1:
|
||||
|
||||
if(z.avail_in==0)return r;r=f;
|
||||
|
||||
z.avail_in--; z.total_in++;
|
||||
this.need+=(z.next_in[z.next_in_index++]&0xffL);
|
||||
|
||||
if(flags!=0){ // gzip
|
||||
this.need = ((this.need&0xff000000)>>24 |
|
||||
(this.need&0x00ff0000)>>8 |
|
||||
(this.need&0x0000ff00)<<8 |
|
||||
(this.need&0x0000ffff)<<24)&0xffffffffL;
|
||||
}
|
||||
|
||||
if(((int)(this.was)) != ((int)(this.need))){
|
||||
z.msg = "incorrect data check";
|
||||
// chack is delayed
|
||||
/*
|
||||
this.mode = BAD;
|
||||
this.marker = 5; // can't try inflateSync
|
||||
break;
|
||||
*/
|
||||
}
|
||||
else if(flags!=0 && gheader!=null){
|
||||
gheader.crc = this.need;
|
||||
}
|
||||
|
||||
this.mode = LENGTH;
|
||||
case LENGTH:
|
||||
if (wrap!=0 && flags!=0) {
|
||||
|
||||
try { r=readBytes(4, r, f); }
|
||||
catch(Return e){ return e.r; }
|
||||
|
||||
if(z.msg!=null && z.msg.equals("incorrect data check")){
|
||||
this.mode = BAD;
|
||||
this.marker = 5; // can't try inflateSync
|
||||
break;
|
||||
}
|
||||
|
||||
if (this.need != (z.total_out & 0xffffffffL)) {
|
||||
z.msg = "incorrect length check";
|
||||
this.mode = BAD;
|
||||
break;
|
||||
}
|
||||
z.msg = null;
|
||||
}
|
||||
else {
|
||||
if(z.msg!=null && z.msg.equals("incorrect data check")){
|
||||
this.mode = BAD;
|
||||
this.marker = 5; // can't try inflateSync
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this.mode = DONE;
|
||||
case DONE:
|
||||
return Z_STREAM_END;
|
||||
case BAD:
|
||||
return Z_DATA_ERROR;
|
||||
|
||||
case FLAGS:
|
||||
|
||||
try { r=readBytes(2, r, f); }
|
||||
catch(Return e){ return e.r; }
|
||||
|
||||
flags = ((int)this.need)&0xffff;
|
||||
|
||||
if ((flags & 0xff) != Z_DEFLATED) {
|
||||
z.msg = "unknown compression method";
|
||||
this.mode = BAD;
|
||||
break;
|
||||
}
|
||||
if ((flags & 0xe000)!=0) {
|
||||
z.msg = "unknown header flags set";
|
||||
this.mode = BAD;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((flags & 0x0200)!=0){
|
||||
checksum(2, this.need);
|
||||
}
|
||||
|
||||
this.mode = TIME;
|
||||
|
||||
case TIME:
|
||||
try { r=readBytes(4, r, f); }
|
||||
catch(Return e){ return e.r; }
|
||||
if(gheader!=null)
|
||||
gheader.time = this.need;
|
||||
if ((flags & 0x0200)!=0){
|
||||
checksum(4, this.need);
|
||||
}
|
||||
this.mode = OS;
|
||||
case OS:
|
||||
try { r=readBytes(2, r, f); }
|
||||
catch(Return e){ return e.r; }
|
||||
if(gheader!=null){
|
||||
gheader.xflags = ((int)this.need)&0xff;
|
||||
gheader.os = (((int)this.need)>>8)&0xff;
|
||||
}
|
||||
if ((flags & 0x0200)!=0){
|
||||
checksum(2, this.need);
|
||||
}
|
||||
this.mode = EXLEN;
|
||||
case EXLEN:
|
||||
if ((flags & 0x0400)!=0) {
|
||||
try { r=readBytes(2, r, f); }
|
||||
catch(Return e){ return e.r; }
|
||||
if(gheader!=null){
|
||||
gheader.extra = new byte[((int)this.need)&0xffff];
|
||||
}
|
||||
if ((flags & 0x0200)!=0){
|
||||
checksum(2, this.need);
|
||||
}
|
||||
}
|
||||
else if(gheader!=null){
|
||||
gheader.extra=null;
|
||||
}
|
||||
this.mode = EXTRA;
|
||||
|
||||
case EXTRA:
|
||||
if ((flags & 0x0400)!=0) {
|
||||
try {
|
||||
r=readBytes(r, f);
|
||||
if(gheader!=null){
|
||||
byte[] foo = tmp_string.toByteArray();
|
||||
tmp_string=null;
|
||||
if(foo.length == gheader.extra.length){
|
||||
System.arraycopy(foo, 0, gheader.extra, 0, foo.length);
|
||||
}
|
||||
else{
|
||||
z.msg = "bad extra field length";
|
||||
this.mode = BAD;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(Return e){ return e.r; }
|
||||
}
|
||||
else if(gheader!=null){
|
||||
gheader.extra=null;
|
||||
}
|
||||
this.mode = NAME;
|
||||
case NAME:
|
||||
if ((flags & 0x0800)!=0) {
|
||||
try {
|
||||
r=readString(r, f);
|
||||
if(gheader!=null){
|
||||
gheader.name=tmp_string.toByteArray();
|
||||
}
|
||||
tmp_string=null;
|
||||
}
|
||||
catch(Return e){ return e.r; }
|
||||
}
|
||||
else if(gheader!=null){
|
||||
gheader.name=null;
|
||||
}
|
||||
this.mode = COMMENT;
|
||||
case COMMENT:
|
||||
if ((flags & 0x1000)!=0) {
|
||||
try {
|
||||
r=readString(r, f);
|
||||
if(gheader!=null){
|
||||
gheader.comment=tmp_string.toByteArray();
|
||||
}
|
||||
tmp_string=null;
|
||||
}
|
||||
catch(Return e){ return e.r; }
|
||||
}
|
||||
else if(gheader!=null){
|
||||
gheader.comment=null;
|
||||
}
|
||||
this.mode = HCRC;
|
||||
case HCRC:
|
||||
if ((flags & 0x0200)!=0) {
|
||||
try { r=readBytes(2, r, f); }
|
||||
catch(Return e){ return e.r; }
|
||||
if(gheader!=null){
|
||||
gheader.hcrc=(int)(this.need&0xffff);
|
||||
}
|
||||
if(this.need != (z.adler.getValue()&0xffffL)){
|
||||
this.mode = BAD;
|
||||
z.msg = "header crc mismatch";
|
||||
this.marker = 5; // can't try inflateSync
|
||||
break;
|
||||
}
|
||||
}
|
||||
z.adler = new CRC32();
|
||||
|
||||
this.mode = BLOCKS;
|
||||
break;
|
||||
default:
|
||||
return Z_STREAM_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int inflateSetDictionary(byte[] dictionary, int dictLength){
|
||||
if(z==null || (this.mode != DICT0 && this.wrap != 0)){
|
||||
return Z_STREAM_ERROR;
|
||||
}
|
||||
|
||||
int index=0;
|
||||
int length = dictLength;
|
||||
|
||||
if(this.mode==DICT0){
|
||||
long adler_need=z.adler.getValue();
|
||||
z.adler.reset();
|
||||
z.adler.update(dictionary, 0, dictLength);
|
||||
if(z.adler.getValue()!=adler_need){
|
||||
return Z_DATA_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
z.adler.reset();
|
||||
|
||||
if(length >= (1<<this.wbits)){
|
||||
length = (1<<this.wbits)-1;
|
||||
index=dictLength - length;
|
||||
}
|
||||
this.blocks.set_dictionary(dictionary, index, length);
|
||||
this.mode = BLOCKS;
|
||||
return Z_OK;
|
||||
}
|
||||
|
||||
static private byte[] mark = {(byte)0, (byte)0, (byte)0xff, (byte)0xff};
|
||||
|
||||
int inflateSync(){
|
||||
int n; // number of bytes to look at
|
||||
int p; // pointer to bytes
|
||||
int m; // number of marker bytes found in a row
|
||||
long r, w; // temporaries to save total_in and total_out
|
||||
|
||||
// set up
|
||||
if(z == null)
|
||||
return Z_STREAM_ERROR;
|
||||
if(this.mode != BAD){
|
||||
this.mode = BAD;
|
||||
this.marker = 0;
|
||||
}
|
||||
if((n=z.avail_in)==0)
|
||||
return Z_BUF_ERROR;
|
||||
|
||||
p=z.next_in_index;
|
||||
m=this.marker;
|
||||
// search
|
||||
while (n!=0 && m < 4){
|
||||
if(z.next_in[p] == mark[m]){
|
||||
m++;
|
||||
}
|
||||
else if(z.next_in[p]!=0){
|
||||
m = 0;
|
||||
}
|
||||
else{
|
||||
m = 4 - m;
|
||||
}
|
||||
p++; n--;
|
||||
}
|
||||
|
||||
// restore
|
||||
z.total_in += p-z.next_in_index;
|
||||
z.next_in_index = p;
|
||||
z.avail_in = n;
|
||||
this.marker = m;
|
||||
|
||||
// return no joy or set up to restart on a new block
|
||||
if(m != 4){
|
||||
return Z_DATA_ERROR;
|
||||
}
|
||||
r=z.total_in; w=z.total_out;
|
||||
inflateReset();
|
||||
z.total_in=r; z.total_out = w;
|
||||
this.mode = BLOCKS;
|
||||
|
||||
return Z_OK;
|
||||
}
|
||||
|
||||
// Returns true if inflate is currently at the end of a block generated
|
||||
// by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
|
||||
// implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH
|
||||
// but removes the length bytes of the resulting empty stored block. When
|
||||
// decompressing, PPP checks that at the end of input packet, inflate is
|
||||
// waiting for these length bytes.
|
||||
int inflateSyncPoint(){
|
||||
if(z == null || this.blocks == null)
|
||||
return Z_STREAM_ERROR;
|
||||
return this.blocks.sync_point();
|
||||
}
|
||||
|
||||
private int readBytes(int n, int r, int f) throws Return{
|
||||
if(need_bytes == -1){
|
||||
need_bytes=n;
|
||||
this.need=0;
|
||||
}
|
||||
while(need_bytes>0){
|
||||
if(z.avail_in==0){ throw new Return(r); }; r=f;
|
||||
z.avail_in--; z.total_in++;
|
||||
this.need = this.need |
|
||||
((z.next_in[z.next_in_index++]&0xff)<<((n-need_bytes)*8));
|
||||
need_bytes--;
|
||||
}
|
||||
if(n==2){
|
||||
this.need&=0xffffL;
|
||||
}
|
||||
else if(n==4) {
|
||||
this.need&=0xffffffffL;
|
||||
}
|
||||
need_bytes=-1;
|
||||
return r;
|
||||
}
|
||||
class Return extends Exception{
|
||||
int r;
|
||||
Return(int r){this.r=r; }
|
||||
}
|
||||
|
||||
private java.io.ByteArrayOutputStream tmp_string = null;
|
||||
private int readString(int r, int f) throws Return{
|
||||
if(tmp_string == null){
|
||||
tmp_string=new java.io.ByteArrayOutputStream();
|
||||
}
|
||||
int b=0;
|
||||
do {
|
||||
if(z.avail_in==0){ throw new Return(r); }; r=f;
|
||||
z.avail_in--; z.total_in++;
|
||||
b = z.next_in[z.next_in_index];
|
||||
if(b!=0) tmp_string.write(z.next_in, z.next_in_index, 1);
|
||||
z.adler.update(z.next_in, z.next_in_index, 1);
|
||||
z.next_in_index++;
|
||||
}while(b!=0);
|
||||
return r;
|
||||
}
|
||||
|
||||
private int readBytes(int r, int f) throws Return{
|
||||
if(tmp_string == null){
|
||||
tmp_string=new java.io.ByteArrayOutputStream();
|
||||
}
|
||||
int b=0;
|
||||
while(this.need>0){
|
||||
if(z.avail_in==0){ throw new Return(r); }; r=f;
|
||||
z.avail_in--; z.total_in++;
|
||||
b = z.next_in[z.next_in_index];
|
||||
tmp_string.write(z.next_in, z.next_in_index, 1);
|
||||
z.adler.update(z.next_in, z.next_in_index, 1);
|
||||
z.next_in_index++;
|
||||
this.need--;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
private void checksum(int n, long v){
|
||||
for(int i=0; i<n; i++){
|
||||
crcbuf[i]=(byte)(v&0xff);
|
||||
v>>=8;
|
||||
}
|
||||
z.adler.update(crcbuf, 0, n);
|
||||
}
|
||||
|
||||
public GZIPHeader getGZIPHeader(){
|
||||
return gheader;
|
||||
}
|
||||
|
||||
boolean inParsingHeader(){
|
||||
switch(mode){
|
||||
case HEAD:
|
||||
case DICT4:
|
||||
case DICT3:
|
||||
case DICT2:
|
||||
case DICT1:
|
||||
case FLAGS:
|
||||
case TIME:
|
||||
case OS:
|
||||
case EXLEN:
|
||||
case EXTRA:
|
||||
case NAME:
|
||||
case COMMENT:
|
||||
case HCRC:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
168
src/lwjgl/java/com/jcraft/jzlib/Inflater.java
Normal file
168
src/lwjgl/java/com/jcraft/jzlib/Inflater.java
Normal file
@@ -0,0 +1,168 @@
|
||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
|
||||
/*
|
||||
Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. The names of the authors may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
|
||||
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/*
|
||||
* This program is based on zlib-1.1.3, so all credit should go authors
|
||||
* Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
|
||||
* and contributors of zlib.
|
||||
*/
|
||||
|
||||
package com.jcraft.jzlib;
|
||||
|
||||
final public class Inflater extends ZStream{
|
||||
|
||||
static final private int MAX_WBITS=15; // 32K LZ77 window
|
||||
static final private int DEF_WBITS=MAX_WBITS;
|
||||
|
||||
static final private int Z_NO_FLUSH=0;
|
||||
static final private int Z_PARTIAL_FLUSH=1;
|
||||
static final private int Z_SYNC_FLUSH=2;
|
||||
static final private int Z_FULL_FLUSH=3;
|
||||
static final private int Z_FINISH=4;
|
||||
|
||||
static final private int MAX_MEM_LEVEL=9;
|
||||
|
||||
static final private int Z_OK=0;
|
||||
static final private int Z_STREAM_END=1;
|
||||
static final private int Z_NEED_DICT=2;
|
||||
static final private int Z_ERRNO=-1;
|
||||
static final private int Z_STREAM_ERROR=-2;
|
||||
static final private int Z_DATA_ERROR=-3;
|
||||
static final private int Z_MEM_ERROR=-4;
|
||||
static final private int Z_BUF_ERROR=-5;
|
||||
static final private int Z_VERSION_ERROR=-6;
|
||||
|
||||
public Inflater() {
|
||||
super();
|
||||
init();
|
||||
}
|
||||
|
||||
public Inflater(JZlib.WrapperType wrapperType) throws GZIPException {
|
||||
this(DEF_WBITS, wrapperType);
|
||||
}
|
||||
|
||||
public Inflater(int w, JZlib.WrapperType wrapperType) throws GZIPException {
|
||||
super();
|
||||
int ret = init(w, wrapperType);
|
||||
if(ret!=Z_OK)
|
||||
throw new GZIPException(ret+": "+msg);
|
||||
}
|
||||
|
||||
public Inflater(int w) throws GZIPException {
|
||||
this(w, false);
|
||||
}
|
||||
|
||||
public Inflater(boolean nowrap) throws GZIPException {
|
||||
this(DEF_WBITS, nowrap);
|
||||
}
|
||||
|
||||
public Inflater(int w, boolean nowrap) throws GZIPException {
|
||||
super();
|
||||
int ret = init(w, nowrap);
|
||||
if(ret!=Z_OK)
|
||||
throw new GZIPException(ret+": "+msg);
|
||||
}
|
||||
|
||||
private boolean finished = false;
|
||||
|
||||
public int init(){
|
||||
return init(DEF_WBITS);
|
||||
}
|
||||
|
||||
public int init(JZlib.WrapperType wrapperType){
|
||||
return init(DEF_WBITS, wrapperType);
|
||||
}
|
||||
|
||||
public int init(int w, JZlib.WrapperType wrapperType) {
|
||||
boolean nowrap = false;
|
||||
if(wrapperType == JZlib.W_NONE){
|
||||
nowrap = true;
|
||||
}
|
||||
else if(wrapperType == JZlib.W_GZIP) {
|
||||
w += 16;
|
||||
}
|
||||
else if(wrapperType == JZlib.W_ANY) {
|
||||
w |= Inflate.INFLATE_ANY;
|
||||
}
|
||||
else if(wrapperType == JZlib.W_ZLIB) {
|
||||
}
|
||||
return init(w, nowrap);
|
||||
}
|
||||
|
||||
public int init(boolean nowrap){
|
||||
return init(DEF_WBITS, nowrap);
|
||||
}
|
||||
|
||||
public int init(int w){
|
||||
return init(w, false);
|
||||
}
|
||||
|
||||
public int init(int w, boolean nowrap){
|
||||
finished = false;
|
||||
istate=new Inflate(this);
|
||||
return istate.inflateInit(nowrap?-w:w);
|
||||
}
|
||||
|
||||
public int inflate(int f){
|
||||
if(istate==null) return Z_STREAM_ERROR;
|
||||
int ret = istate.inflate(f);
|
||||
if(ret == Z_STREAM_END)
|
||||
finished = true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
public int end(){
|
||||
finished = true;
|
||||
if(istate==null) return Z_STREAM_ERROR;
|
||||
int ret=istate.inflateEnd();
|
||||
// istate = null;
|
||||
return ret;
|
||||
}
|
||||
|
||||
public int sync(){
|
||||
if(istate == null)
|
||||
return Z_STREAM_ERROR;
|
||||
return istate.inflateSync();
|
||||
}
|
||||
|
||||
public int syncPoint(){
|
||||
if(istate == null)
|
||||
return Z_STREAM_ERROR;
|
||||
return istate.inflateSyncPoint();
|
||||
}
|
||||
|
||||
public int setDictionary(byte[] dictionary, int dictLength){
|
||||
if(istate == null)
|
||||
return Z_STREAM_ERROR;
|
||||
return istate.inflateSetDictionary(dictionary, dictLength);
|
||||
}
|
||||
|
||||
public boolean finished(){
|
||||
return istate.mode==12 /*DONE*/;
|
||||
}
|
||||
}
|
||||
247
src/lwjgl/java/com/jcraft/jzlib/InflaterInputStream.java
Normal file
247
src/lwjgl/java/com/jcraft/jzlib/InflaterInputStream.java
Normal file
@@ -0,0 +1,247 @@
|
||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
|
||||
/*
|
||||
Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. The names of the authors may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
|
||||
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package com.jcraft.jzlib;
|
||||
import java.io.*;
|
||||
|
||||
public class InflaterInputStream extends FilterInputStream {
|
||||
protected final Inflater inflater;
|
||||
protected byte[] buf;
|
||||
|
||||
private boolean closed = false;
|
||||
|
||||
private boolean eof = false;
|
||||
|
||||
private boolean close_in = true;
|
||||
|
||||
protected static final int DEFAULT_BUFSIZE = 512;
|
||||
|
||||
public InflaterInputStream(InputStream in) throws IOException {
|
||||
this(in, false);
|
||||
}
|
||||
|
||||
public InflaterInputStream(InputStream in, boolean nowrap) throws IOException {
|
||||
this(in, new Inflater(nowrap));
|
||||
myinflater = true;
|
||||
}
|
||||
|
||||
public InflaterInputStream(InputStream in, Inflater inflater) throws IOException {
|
||||
this(in, inflater, DEFAULT_BUFSIZE);
|
||||
}
|
||||
|
||||
public InflaterInputStream(InputStream in,
|
||||
Inflater inflater, int size) throws IOException {
|
||||
this(in, inflater, size, true);
|
||||
}
|
||||
|
||||
public InflaterInputStream(InputStream in,
|
||||
Inflater inflater,
|
||||
int size, boolean close_in) throws IOException {
|
||||
super(in);
|
||||
if (in == null || inflater == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
else if (size <= 0) {
|
||||
throw new IllegalArgumentException("buffer size must be greater than 0");
|
||||
}
|
||||
this.inflater = inflater;
|
||||
buf = new byte[size];
|
||||
this.close_in = close_in;
|
||||
}
|
||||
|
||||
protected boolean myinflater = false;
|
||||
|
||||
private byte[] byte1 = new byte[1];
|
||||
|
||||
public int read() throws IOException {
|
||||
if (closed) { throw new IOException("Stream closed"); }
|
||||
return read(byte1, 0, 1) == -1 ? -1 : byte1[0] & 0xff;
|
||||
}
|
||||
|
||||
public int read(byte[] b, int off, int len) throws IOException {
|
||||
if (closed) { throw new IOException("Stream closed"); }
|
||||
if (b == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
else if (off < 0 || len < 0 || len > b.length - off) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
else if (len == 0) {
|
||||
return 0;
|
||||
}
|
||||
else if (eof) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int n = 0;
|
||||
inflater.setOutput(b, off, len);
|
||||
while(!eof) {
|
||||
if(inflater.avail_in==0)
|
||||
fill();
|
||||
int err = inflater.inflate(JZlib.Z_NO_FLUSH);
|
||||
n += inflater.next_out_index - off;
|
||||
off = inflater.next_out_index;
|
||||
switch(err) {
|
||||
case JZlib.Z_DATA_ERROR:
|
||||
throw new IOException(inflater.msg);
|
||||
case JZlib.Z_STREAM_END:
|
||||
case JZlib.Z_NEED_DICT:
|
||||
eof = true;
|
||||
if(err == JZlib.Z_NEED_DICT)
|
||||
return -1;
|
||||
break;
|
||||
default:
|
||||
}
|
||||
if(inflater.avail_out==0)
|
||||
break;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
public int available() throws IOException {
|
||||
if (closed) { throw new IOException("Stream closed"); }
|
||||
if (eof) {
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] b = new byte[512];
|
||||
|
||||
public long skip(long n) throws IOException {
|
||||
if (n < 0) {
|
||||
throw new IllegalArgumentException("negative skip length");
|
||||
}
|
||||
|
||||
if (closed) { throw new IOException("Stream closed"); }
|
||||
|
||||
int max = (int)Math.min(n, Integer.MAX_VALUE);
|
||||
int total = 0;
|
||||
while (total < max) {
|
||||
int len = max - total;
|
||||
if (len > b.length) {
|
||||
len = b.length;
|
||||
}
|
||||
len = read(b, 0, len);
|
||||
if (len == -1) {
|
||||
eof = true;
|
||||
break;
|
||||
}
|
||||
total += len;
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
if (!closed) {
|
||||
if (myinflater)
|
||||
inflater.end();
|
||||
if(close_in)
|
||||
in.close();
|
||||
closed = true;
|
||||
}
|
||||
}
|
||||
|
||||
protected void fill() throws IOException {
|
||||
if (closed) { throw new IOException("Stream closed"); }
|
||||
int len = in.read(buf, 0, buf.length);
|
||||
if (len == -1) {
|
||||
if(inflater.istate.wrap == 0 &&
|
||||
!inflater.finished()){
|
||||
buf[0]=0;
|
||||
len=1;
|
||||
}
|
||||
else if(inflater.istate.was != -1){ // in reading trailer
|
||||
throw new IOException("footer is not found");
|
||||
}
|
||||
else{
|
||||
throw new EOFException("Unexpected end of ZLIB input stream");
|
||||
}
|
||||
}
|
||||
inflater.setInput(buf, 0, len, true);
|
||||
}
|
||||
|
||||
public boolean markSupported() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public synchronized void mark(int readlimit) {
|
||||
}
|
||||
|
||||
public synchronized void reset() throws IOException {
|
||||
throw new IOException("mark/reset not supported");
|
||||
}
|
||||
|
||||
public long getTotalIn() {
|
||||
return inflater.getTotalIn();
|
||||
}
|
||||
|
||||
public long getTotalOut() {
|
||||
return inflater.getTotalOut();
|
||||
}
|
||||
|
||||
public byte[] getAvailIn() {
|
||||
if(inflater.avail_in<=0)
|
||||
return null;
|
||||
byte[] tmp = new byte[inflater.avail_in];
|
||||
System.arraycopy(inflater.next_in, inflater.next_in_index,
|
||||
tmp, 0, inflater.avail_in);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
public void readHeader() throws IOException {
|
||||
|
||||
byte[] empty = "".getBytes();
|
||||
inflater.setInput(empty, 0, 0, false);
|
||||
inflater.setOutput(empty, 0, 0);
|
||||
|
||||
int err = inflater.inflate(JZlib.Z_NO_FLUSH);
|
||||
if(!inflater.istate.inParsingHeader()){
|
||||
return;
|
||||
}
|
||||
|
||||
byte[] b1 = new byte[1];
|
||||
do{
|
||||
int i = in.read(b1);
|
||||
if(i<=0)
|
||||
throw new IOException("no input");
|
||||
inflater.setInput(b1);
|
||||
err = inflater.inflate(JZlib.Z_NO_FLUSH);
|
||||
if(err!=0/*Z_OK*/)
|
||||
throw new IOException(inflater.msg);
|
||||
}
|
||||
while(inflater.istate.inParsingHeader());
|
||||
}
|
||||
|
||||
public Inflater getInflater(){
|
||||
return inflater;
|
||||
}
|
||||
}
|
||||
92
src/lwjgl/java/com/jcraft/jzlib/JZlib.java
Normal file
92
src/lwjgl/java/com/jcraft/jzlib/JZlib.java
Normal file
@@ -0,0 +1,92 @@
|
||||
/* -*-mode:java; c-basic-offset:2; -*- */
|
||||
/*
|
||||
Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. The names of the authors may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
|
||||
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/*
|
||||
* This program is based on zlib-1.1.3, so all credit should go authors
|
||||
* Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
|
||||
* and contributors of zlib.
|
||||
*/
|
||||
|
||||
package com.jcraft.jzlib;
|
||||
|
||||
final public class JZlib{
|
||||
private static final String version="1.1.0";
|
||||
public static String version(){return version;}
|
||||
|
||||
static final public int MAX_WBITS=15; // 32K LZ77 window
|
||||
static final public int DEF_WBITS=MAX_WBITS;
|
||||
|
||||
public enum WrapperType {
|
||||
NONE, ZLIB, GZIP, ANY
|
||||
}
|
||||
|
||||
public static final WrapperType W_NONE = WrapperType.NONE;
|
||||
public static final WrapperType W_ZLIB = WrapperType.ZLIB;
|
||||
public static final WrapperType W_GZIP = WrapperType.GZIP;
|
||||
public static final WrapperType W_ANY = WrapperType.ANY;
|
||||
|
||||
// compression levels
|
||||
static final public int Z_NO_COMPRESSION=0;
|
||||
static final public int Z_BEST_SPEED=1;
|
||||
static final public int Z_BEST_COMPRESSION=9;
|
||||
static final public int Z_DEFAULT_COMPRESSION=(-1);
|
||||
|
||||
// compression strategy
|
||||
static final public int Z_FILTERED=1;
|
||||
static final public int Z_HUFFMAN_ONLY=2;
|
||||
static final public int Z_DEFAULT_STRATEGY=0;
|
||||
|
||||
static final public int Z_NO_FLUSH=0;
|
||||
static final public int Z_PARTIAL_FLUSH=1;
|
||||
static final public int Z_SYNC_FLUSH=2;
|
||||
static final public int Z_FULL_FLUSH=3;
|
||||
static final public int Z_FINISH=4;
|
||||
|
||||
static final public int Z_OK=0;
|
||||
static final public int Z_STREAM_END=1;
|
||||
static final public int Z_NEED_DICT=2;
|
||||
static final public int Z_ERRNO=-1;
|
||||
static final public int Z_STREAM_ERROR=-2;
|
||||
static final public int Z_DATA_ERROR=-3;
|
||||
static final public int Z_MEM_ERROR=-4;
|
||||
static final public int Z_BUF_ERROR=-5;
|
||||
static final public int Z_VERSION_ERROR=-6;
|
||||
|
||||
// The three kinds of block type
|
||||
static final public byte Z_BINARY = 0;
|
||||
static final public byte Z_ASCII = 1;
|
||||
static final public byte Z_UNKNOWN = 2;
|
||||
|
||||
public static long adler32_combine(long adler1, long adler2, long len2){
|
||||
return Adler32.combine(adler1, adler2, len2);
|
||||
}
|
||||
|
||||
public static long crc32_combine(long crc1, long crc2, long len2){
|
||||
return CRC32.combine(crc1, crc2, len2);
|
||||
}
|
||||
}
|
||||
148
src/lwjgl/java/com/jcraft/jzlib/StaticTree.java
Normal file
148
src/lwjgl/java/com/jcraft/jzlib/StaticTree.java
Normal file
@@ -0,0 +1,148 @@
|
||||
/* -*-mode:java; c-basic-offset:2; -*- */
|
||||
/*
|
||||
Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. The names of the authors may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
|
||||
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/*
|
||||
* This program is based on zlib-1.1.3, so all credit should go authors
|
||||
* Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
|
||||
* and contributors of zlib.
|
||||
*/
|
||||
|
||||
package com.jcraft.jzlib;
|
||||
|
||||
final class StaticTree{
|
||||
static final private int MAX_BITS=15;
|
||||
|
||||
static final private int BL_CODES=19;
|
||||
static final private int D_CODES=30;
|
||||
static final private int LITERALS=256;
|
||||
static final private int LENGTH_CODES=29;
|
||||
static final private int L_CODES=(LITERALS+1+LENGTH_CODES);
|
||||
|
||||
// Bit length codes must not exceed MAX_BL_BITS bits
|
||||
static final int MAX_BL_BITS=7;
|
||||
|
||||
static final short[] static_ltree = {
|
||||
12, 8, 140, 8, 76, 8, 204, 8, 44, 8,
|
||||
172, 8, 108, 8, 236, 8, 28, 8, 156, 8,
|
||||
92, 8, 220, 8, 60, 8, 188, 8, 124, 8,
|
||||
252, 8, 2, 8, 130, 8, 66, 8, 194, 8,
|
||||
34, 8, 162, 8, 98, 8, 226, 8, 18, 8,
|
||||
146, 8, 82, 8, 210, 8, 50, 8, 178, 8,
|
||||
114, 8, 242, 8, 10, 8, 138, 8, 74, 8,
|
||||
202, 8, 42, 8, 170, 8, 106, 8, 234, 8,
|
||||
26, 8, 154, 8, 90, 8, 218, 8, 58, 8,
|
||||
186, 8, 122, 8, 250, 8, 6, 8, 134, 8,
|
||||
70, 8, 198, 8, 38, 8, 166, 8, 102, 8,
|
||||
230, 8, 22, 8, 150, 8, 86, 8, 214, 8,
|
||||
54, 8, 182, 8, 118, 8, 246, 8, 14, 8,
|
||||
142, 8, 78, 8, 206, 8, 46, 8, 174, 8,
|
||||
110, 8, 238, 8, 30, 8, 158, 8, 94, 8,
|
||||
222, 8, 62, 8, 190, 8, 126, 8, 254, 8,
|
||||
1, 8, 129, 8, 65, 8, 193, 8, 33, 8,
|
||||
161, 8, 97, 8, 225, 8, 17, 8, 145, 8,
|
||||
81, 8, 209, 8, 49, 8, 177, 8, 113, 8,
|
||||
241, 8, 9, 8, 137, 8, 73, 8, 201, 8,
|
||||
41, 8, 169, 8, 105, 8, 233, 8, 25, 8,
|
||||
153, 8, 89, 8, 217, 8, 57, 8, 185, 8,
|
||||
121, 8, 249, 8, 5, 8, 133, 8, 69, 8,
|
||||
197, 8, 37, 8, 165, 8, 101, 8, 229, 8,
|
||||
21, 8, 149, 8, 85, 8, 213, 8, 53, 8,
|
||||
181, 8, 117, 8, 245, 8, 13, 8, 141, 8,
|
||||
77, 8, 205, 8, 45, 8, 173, 8, 109, 8,
|
||||
237, 8, 29, 8, 157, 8, 93, 8, 221, 8,
|
||||
61, 8, 189, 8, 125, 8, 253, 8, 19, 9,
|
||||
275, 9, 147, 9, 403, 9, 83, 9, 339, 9,
|
||||
211, 9, 467, 9, 51, 9, 307, 9, 179, 9,
|
||||
435, 9, 115, 9, 371, 9, 243, 9, 499, 9,
|
||||
11, 9, 267, 9, 139, 9, 395, 9, 75, 9,
|
||||
331, 9, 203, 9, 459, 9, 43, 9, 299, 9,
|
||||
171, 9, 427, 9, 107, 9, 363, 9, 235, 9,
|
||||
491, 9, 27, 9, 283, 9, 155, 9, 411, 9,
|
||||
91, 9, 347, 9, 219, 9, 475, 9, 59, 9,
|
||||
315, 9, 187, 9, 443, 9, 123, 9, 379, 9,
|
||||
251, 9, 507, 9, 7, 9, 263, 9, 135, 9,
|
||||
391, 9, 71, 9, 327, 9, 199, 9, 455, 9,
|
||||
39, 9, 295, 9, 167, 9, 423, 9, 103, 9,
|
||||
359, 9, 231, 9, 487, 9, 23, 9, 279, 9,
|
||||
151, 9, 407, 9, 87, 9, 343, 9, 215, 9,
|
||||
471, 9, 55, 9, 311, 9, 183, 9, 439, 9,
|
||||
119, 9, 375, 9, 247, 9, 503, 9, 15, 9,
|
||||
271, 9, 143, 9, 399, 9, 79, 9, 335, 9,
|
||||
207, 9, 463, 9, 47, 9, 303, 9, 175, 9,
|
||||
431, 9, 111, 9, 367, 9, 239, 9, 495, 9,
|
||||
31, 9, 287, 9, 159, 9, 415, 9, 95, 9,
|
||||
351, 9, 223, 9, 479, 9, 63, 9, 319, 9,
|
||||
191, 9, 447, 9, 127, 9, 383, 9, 255, 9,
|
||||
511, 9, 0, 7, 64, 7, 32, 7, 96, 7,
|
||||
16, 7, 80, 7, 48, 7, 112, 7, 8, 7,
|
||||
72, 7, 40, 7, 104, 7, 24, 7, 88, 7,
|
||||
56, 7, 120, 7, 4, 7, 68, 7, 36, 7,
|
||||
100, 7, 20, 7, 84, 7, 52, 7, 116, 7,
|
||||
3, 8, 131, 8, 67, 8, 195, 8, 35, 8,
|
||||
163, 8, 99, 8, 227, 8
|
||||
};
|
||||
|
||||
static final short[] static_dtree = {
|
||||
0, 5, 16, 5, 8, 5, 24, 5, 4, 5,
|
||||
20, 5, 12, 5, 28, 5, 2, 5, 18, 5,
|
||||
10, 5, 26, 5, 6, 5, 22, 5, 14, 5,
|
||||
30, 5, 1, 5, 17, 5, 9, 5, 25, 5,
|
||||
5, 5, 21, 5, 13, 5, 29, 5, 3, 5,
|
||||
19, 5, 11, 5, 27, 5, 7, 5, 23, 5
|
||||
};
|
||||
|
||||
static StaticTree static_l_desc =
|
||||
new StaticTree(static_ltree, Tree.extra_lbits,
|
||||
LITERALS+1, L_CODES, MAX_BITS);
|
||||
|
||||
static StaticTree static_d_desc =
|
||||
new StaticTree(static_dtree, Tree.extra_dbits,
|
||||
0, D_CODES, MAX_BITS);
|
||||
|
||||
static StaticTree static_bl_desc =
|
||||
new StaticTree(null, Tree.extra_blbits,
|
||||
0, BL_CODES, MAX_BL_BITS);
|
||||
|
||||
short[] static_tree; // static tree or null
|
||||
int[] extra_bits; // extra bits for each code or null
|
||||
int extra_base; // base index for extra_bits
|
||||
int elems; // max number of elements in the tree
|
||||
int max_length; // max bit length for the codes
|
||||
|
||||
private StaticTree(short[] static_tree,
|
||||
int[] extra_bits,
|
||||
int extra_base,
|
||||
int elems,
|
||||
int max_length){
|
||||
this.static_tree=static_tree;
|
||||
this.extra_bits=extra_bits;
|
||||
this.extra_base=extra_base;
|
||||
this.elems=elems;
|
||||
this.max_length=max_length;
|
||||
}
|
||||
}
|
||||
367
src/lwjgl/java/com/jcraft/jzlib/Tree.java
Normal file
367
src/lwjgl/java/com/jcraft/jzlib/Tree.java
Normal file
@@ -0,0 +1,367 @@
|
||||
/* -*-mode:java; c-basic-offset:2; -*- */
|
||||
/*
|
||||
Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. The names of the authors may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
|
||||
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/*
|
||||
* This program is based on zlib-1.1.3, so all credit should go authors
|
||||
* Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
|
||||
* and contributors of zlib.
|
||||
*/
|
||||
|
||||
package com.jcraft.jzlib;
|
||||
|
||||
final class Tree{
|
||||
static final private int MAX_BITS=15;
|
||||
static final private int BL_CODES=19;
|
||||
static final private int D_CODES=30;
|
||||
static final private int LITERALS=256;
|
||||
static final private int LENGTH_CODES=29;
|
||||
static final private int L_CODES=(LITERALS+1+LENGTH_CODES);
|
||||
static final private int HEAP_SIZE=(2*L_CODES+1);
|
||||
|
||||
// Bit length codes must not exceed MAX_BL_BITS bits
|
||||
static final int MAX_BL_BITS=7;
|
||||
|
||||
// end of block literal code
|
||||
static final int END_BLOCK=256;
|
||||
|
||||
// repeat previous bit length 3-6 times (2 bits of repeat count)
|
||||
static final int REP_3_6=16;
|
||||
|
||||
// repeat a zero length 3-10 times (3 bits of repeat count)
|
||||
static final int REPZ_3_10=17;
|
||||
|
||||
// repeat a zero length 11-138 times (7 bits of repeat count)
|
||||
static final int REPZ_11_138=18;
|
||||
|
||||
// extra bits for each length code
|
||||
static final int[] extra_lbits={
|
||||
0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0
|
||||
};
|
||||
|
||||
// extra bits for each distance code
|
||||
static final int[] extra_dbits={
|
||||
0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13
|
||||
};
|
||||
|
||||
// extra bits for each bit length code
|
||||
static final int[] extra_blbits={
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7
|
||||
};
|
||||
|
||||
static final byte[] bl_order={
|
||||
16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15};
|
||||
|
||||
|
||||
// The lengths of the bit length codes are sent in order of decreasing
|
||||
// probability, to avoid transmitting the lengths for unused bit
|
||||
// length codes.
|
||||
|
||||
static final int Buf_size=8*2;
|
||||
|
||||
// see definition of array dist_code below
|
||||
static final int DIST_CODE_LEN=512;
|
||||
|
||||
static final byte[] _dist_code = {
|
||||
0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10,
|
||||
10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
|
||||
11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
|
||||
12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13,
|
||||
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
|
||||
13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
|
||||
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
|
||||
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
|
||||
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17,
|
||||
18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22,
|
||||
23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
||||
24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
|
||||
26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
|
||||
26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27,
|
||||
27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
|
||||
27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
|
||||
28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
|
||||
28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
|
||||
28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
|
||||
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
|
||||
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
|
||||
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29
|
||||
};
|
||||
|
||||
static final byte[] _length_code={
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12,
|
||||
13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,
|
||||
17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
|
||||
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22,
|
||||
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,
|
||||
23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
||||
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
||||
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
|
||||
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26,
|
||||
26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
|
||||
26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
|
||||
27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28
|
||||
};
|
||||
|
||||
static final int[] base_length = {
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56,
|
||||
64, 80, 96, 112, 128, 160, 192, 224, 0
|
||||
};
|
||||
|
||||
static final int[] base_dist = {
|
||||
0, 1, 2, 3, 4, 6, 8, 12, 16, 24,
|
||||
32, 48, 64, 96, 128, 192, 256, 384, 512, 768,
|
||||
1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576
|
||||
};
|
||||
|
||||
// Mapping from a distance to a distance code. dist is the distance - 1 and
|
||||
// must not have side effects. _dist_code[256] and _dist_code[257] are never
|
||||
// used.
|
||||
static int d_code(int dist){
|
||||
return ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>>7)]);
|
||||
}
|
||||
|
||||
short[] dyn_tree; // the dynamic tree
|
||||
int max_code; // largest code with non zero frequency
|
||||
StaticTree stat_desc; // the corresponding static tree
|
||||
|
||||
// Compute the optimal bit lengths for a tree and update the total bit length
|
||||
// for the current block.
|
||||
// IN assertion: the fields freq and dad are set, heap[heap_max] and
|
||||
// above are the tree nodes sorted by increasing frequency.
|
||||
// OUT assertions: the field len is set to the optimal bit length, the
|
||||
// array bl_count contains the frequencies for each bit length.
|
||||
// The length opt_len is updated; static_len is also updated if stree is
|
||||
// not null.
|
||||
void gen_bitlen(Deflate s){
|
||||
short[] tree = dyn_tree;
|
||||
short[] stree = stat_desc.static_tree;
|
||||
int[] extra = stat_desc.extra_bits;
|
||||
int base = stat_desc.extra_base;
|
||||
int max_length = stat_desc.max_length;
|
||||
int h; // heap index
|
||||
int n, m; // iterate over the tree elements
|
||||
int bits; // bit length
|
||||
int xbits; // extra bits
|
||||
short f; // frequency
|
||||
int overflow = 0; // number of elements with bit length too large
|
||||
|
||||
for (bits = 0; bits <= MAX_BITS; bits++) s.bl_count[bits] = 0;
|
||||
|
||||
// In a first pass, compute the optimal bit lengths (which may
|
||||
// overflow in the case of the bit length tree).
|
||||
tree[s.heap[s.heap_max]*2+1] = 0; // root of the heap
|
||||
|
||||
for(h=s.heap_max+1; h<HEAP_SIZE; h++){
|
||||
n = s.heap[h];
|
||||
bits = tree[tree[n*2+1]*2+1] + 1;
|
||||
if (bits > max_length){ bits = max_length; overflow++; }
|
||||
tree[n*2+1] = (short)bits;
|
||||
// We overwrite tree[n*2+1] which is no longer needed
|
||||
|
||||
if (n > max_code) continue; // not a leaf node
|
||||
|
||||
s.bl_count[bits]++;
|
||||
xbits = 0;
|
||||
if (n >= base) xbits = extra[n-base];
|
||||
f = tree[n*2];
|
||||
s.opt_len += f * (bits + xbits);
|
||||
if (stree!=null) s.static_len += f * (stree[n*2+1] + xbits);
|
||||
}
|
||||
if (overflow == 0) return;
|
||||
|
||||
// This happens for example on obj2 and pic of the Calgary corpus
|
||||
// Find the first bit length which could increase:
|
||||
do {
|
||||
bits = max_length-1;
|
||||
while(s.bl_count[bits]==0) bits--;
|
||||
s.bl_count[bits]--; // move one leaf down the tree
|
||||
s.bl_count[bits+1]+=2; // move one overflow item as its brother
|
||||
s.bl_count[max_length]--;
|
||||
// The brother of the overflow item also moves one step up,
|
||||
// but this does not affect bl_count[max_length]
|
||||
overflow -= 2;
|
||||
}
|
||||
while (overflow > 0);
|
||||
|
||||
for (bits = max_length; bits != 0; bits--) {
|
||||
n = s.bl_count[bits];
|
||||
while (n != 0) {
|
||||
m = s.heap[--h];
|
||||
if (m > max_code) continue;
|
||||
if (tree[m*2+1] != bits) {
|
||||
s.opt_len += ((long)bits - (long)tree[m*2+1])*(long)tree[m*2];
|
||||
tree[m*2+1] = (short)bits;
|
||||
}
|
||||
n--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Construct one Huffman tree and assigns the code bit strings and lengths.
|
||||
// Update the total bit length for the current block.
|
||||
// IN assertion: the field freq is set for all tree elements.
|
||||
// OUT assertions: the fields len and code are set to the optimal bit length
|
||||
// and corresponding code. The length opt_len is updated; static_len is
|
||||
// also updated if stree is not null. The field max_code is set.
|
||||
void build_tree(Deflate s){
|
||||
short[] tree=dyn_tree;
|
||||
short[] stree=stat_desc.static_tree;
|
||||
int elems=stat_desc.elems;
|
||||
int n, m; // iterate over heap elements
|
||||
int max_code=-1; // largest code with non zero frequency
|
||||
int node; // new node being created
|
||||
|
||||
// Construct the initial heap, with least frequent element in
|
||||
// heap[1]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
|
||||
// heap[0] is not used.
|
||||
s.heap_len = 0;
|
||||
s.heap_max = HEAP_SIZE;
|
||||
|
||||
for(n=0; n<elems; n++) {
|
||||
if(tree[n*2] != 0) {
|
||||
s.heap[++s.heap_len] = max_code = n;
|
||||
s.depth[n] = 0;
|
||||
}
|
||||
else{
|
||||
tree[n*2+1] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// The pkzip format requires that at least one distance code exists,
|
||||
// and that at least one bit should be sent even if there is only one
|
||||
// possible code. So to avoid special checks later on we force at least
|
||||
// two codes of non zero frequency.
|
||||
while (s.heap_len < 2) {
|
||||
node = s.heap[++s.heap_len] = (max_code < 2 ? ++max_code : 0);
|
||||
tree[node*2] = 1;
|
||||
s.depth[node] = 0;
|
||||
s.opt_len--; if (stree!=null) s.static_len -= stree[node*2+1];
|
||||
// node is 0 or 1 so it does not have extra bits
|
||||
}
|
||||
this.max_code = max_code;
|
||||
|
||||
// The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
|
||||
// establish sub-heaps of increasing lengths:
|
||||
|
||||
for(n=s.heap_len/2;n>=1; n--)
|
||||
s.pqdownheap(tree, n);
|
||||
|
||||
// Construct the Huffman tree by repeatedly combining the least two
|
||||
// frequent nodes.
|
||||
|
||||
node=elems; // next internal node of the tree
|
||||
do{
|
||||
// n = node of least frequency
|
||||
n=s.heap[1];
|
||||
s.heap[1]=s.heap[s.heap_len--];
|
||||
s.pqdownheap(tree, 1);
|
||||
m=s.heap[1]; // m = node of next least frequency
|
||||
|
||||
s.heap[--s.heap_max] = n; // keep the nodes sorted by frequency
|
||||
s.heap[--s.heap_max] = m;
|
||||
|
||||
// Create a new node father of n and m
|
||||
tree[node*2] = (short)(tree[n*2] + tree[m*2]);
|
||||
s.depth[node] = (byte)(Math.max(s.depth[n],s.depth[m])+1);
|
||||
tree[n*2+1] = tree[m*2+1] = (short)node;
|
||||
|
||||
// and insert the new node in the heap
|
||||
s.heap[1] = node++;
|
||||
s.pqdownheap(tree, 1);
|
||||
}
|
||||
while(s.heap_len>=2);
|
||||
|
||||
s.heap[--s.heap_max] = s.heap[1];
|
||||
|
||||
// At this point, the fields freq and dad are set. We can now
|
||||
// generate the bit lengths.
|
||||
|
||||
gen_bitlen(s);
|
||||
|
||||
// The field len is now set, we can generate the bit codes
|
||||
gen_codes(tree, max_code, s.bl_count, s.next_code);
|
||||
}
|
||||
|
||||
// Generate the codes for a given tree and bit counts (which need not be
|
||||
// optimal).
|
||||
// IN assertion: the array bl_count contains the bit length statistics for
|
||||
// the given tree and the field len is set for all tree elements.
|
||||
// OUT assertion: the field code is set for all tree elements of non
|
||||
// zero code length.
|
||||
private final static void gen_codes(
|
||||
short[] tree, // the tree to decorate
|
||||
int max_code, // largest code with non zero frequency
|
||||
short[] bl_count, // number of codes at each bit length
|
||||
short[] next_code){
|
||||
short code = 0; // running code value
|
||||
int bits; // bit index
|
||||
int n; // code index
|
||||
|
||||
// The distribution counts are first used to generate the code values
|
||||
// without bit reversal.
|
||||
next_code[0]=0;
|
||||
for (bits = 1; bits <= MAX_BITS; bits++) {
|
||||
next_code[bits] = code = (short)((code + bl_count[bits-1]) << 1);
|
||||
}
|
||||
|
||||
// Check that the bit counts in bl_count are consistent. The last code
|
||||
// must be all ones.
|
||||
//Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1,
|
||||
// "inconsistent bit counts");
|
||||
//Tracev((stderr,"\ngen_codes: max_code %d ", max_code));
|
||||
|
||||
for (n = 0; n <= max_code; n++) {
|
||||
int len = tree[n*2+1];
|
||||
if (len == 0) continue;
|
||||
// Now reverse the bits
|
||||
tree[n*2] = (short)(bi_reverse(next_code[len]++, len));
|
||||
}
|
||||
}
|
||||
|
||||
// Reverse the first len bits of a code, using straightforward code (a faster
|
||||
// method would use a table)
|
||||
// IN assertion: 1 <= len <= 15
|
||||
private final static int bi_reverse(
|
||||
int code, // the value to invert
|
||||
int len // its bit length
|
||||
){
|
||||
int res = 0;
|
||||
do{
|
||||
res|=code&1;
|
||||
code>>>=1;
|
||||
res<<=1;
|
||||
}
|
||||
while(--len>0);
|
||||
return res>>>1;
|
||||
}
|
||||
}
|
||||
|
||||
126
src/lwjgl/java/com/jcraft/jzlib/ZInputStream.java
Normal file
126
src/lwjgl/java/com/jcraft/jzlib/ZInputStream.java
Normal file
@@ -0,0 +1,126 @@
|
||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
|
||||
/*
|
||||
Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. The names of the authors may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
|
||||
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package com.jcraft.jzlib;
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* ZInputStream
|
||||
*
|
||||
* @deprecated use DeflaterOutputStream or InflaterInputStream
|
||||
*/
|
||||
@Deprecated
|
||||
public class ZInputStream extends FilterInputStream {
|
||||
|
||||
protected int flush=JZlib.Z_NO_FLUSH;
|
||||
protected boolean compress;
|
||||
protected InputStream in=null;
|
||||
|
||||
protected Deflater deflater;
|
||||
protected InflaterInputStream iis;
|
||||
|
||||
public ZInputStream(InputStream in) throws IOException {
|
||||
this(in, false);
|
||||
}
|
||||
public ZInputStream(InputStream in, boolean nowrap) throws IOException {
|
||||
super(in);
|
||||
iis = new InflaterInputStream(in, nowrap);
|
||||
compress=false;
|
||||
}
|
||||
|
||||
public ZInputStream(InputStream in, int level) throws IOException {
|
||||
super(in);
|
||||
this.in=in;
|
||||
deflater = new Deflater();
|
||||
deflater.init(level);
|
||||
compress=true;
|
||||
}
|
||||
|
||||
private byte[] buf1 = new byte[1];
|
||||
public int read() throws IOException {
|
||||
if(read(buf1, 0, 1)==-1) return -1;
|
||||
return(buf1[0]&0xFF);
|
||||
}
|
||||
|
||||
private byte[] buf = new byte[512];
|
||||
|
||||
public int read(byte[] b, int off, int len) throws IOException {
|
||||
if(compress){
|
||||
deflater.setOutput(b, off, len);
|
||||
while(true){
|
||||
int datalen = in.read(buf, 0, buf.length);
|
||||
if(datalen == -1) return -1;
|
||||
deflater.setInput(buf, 0, datalen, true);
|
||||
int err = deflater.deflate(flush);
|
||||
if(deflater.next_out_index>0)
|
||||
return deflater.next_out_index;
|
||||
if(err == JZlib.Z_STREAM_END)
|
||||
return 0;
|
||||
if(err == JZlib.Z_STREAM_ERROR ||
|
||||
err == JZlib.Z_DATA_ERROR){
|
||||
throw new ZStreamException("deflating: "+deflater.msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
return iis.read(b, off, len);
|
||||
}
|
||||
}
|
||||
|
||||
public long skip(long n) throws IOException {
|
||||
int len=512;
|
||||
if(n<len)
|
||||
len=(int)n;
|
||||
byte[] tmp=new byte[len];
|
||||
return((long)read(tmp));
|
||||
}
|
||||
|
||||
public int getFlushMode() {
|
||||
return flush;
|
||||
}
|
||||
|
||||
public void setFlushMode(int flush) {
|
||||
this.flush=flush;
|
||||
}
|
||||
|
||||
public long getTotalIn() {
|
||||
if(compress) return deflater.total_in;
|
||||
else return iis.getTotalIn();
|
||||
}
|
||||
|
||||
public long getTotalOut() {
|
||||
if(compress) return deflater.total_out;
|
||||
else return iis.getTotalOut();
|
||||
}
|
||||
|
||||
public void close() throws IOException{
|
||||
if(compress) deflater.end();
|
||||
else iis.close();
|
||||
}
|
||||
}
|
||||
159
src/lwjgl/java/com/jcraft/jzlib/ZOutputStream.java
Normal file
159
src/lwjgl/java/com/jcraft/jzlib/ZOutputStream.java
Normal file
@@ -0,0 +1,159 @@
|
||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
|
||||
/*
|
||||
Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. The names of the authors may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
|
||||
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package com.jcraft.jzlib;
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* ZOutputStream
|
||||
*
|
||||
* @deprecated use DeflaterOutputStream or InflaterInputStream
|
||||
*/
|
||||
@Deprecated
|
||||
public class ZOutputStream extends FilterOutputStream {
|
||||
|
||||
protected int bufsize=512;
|
||||
protected int flush=JZlib.Z_NO_FLUSH;
|
||||
protected byte[] buf=new byte[bufsize];
|
||||
protected boolean compress;
|
||||
|
||||
protected OutputStream out;
|
||||
private boolean end=false;
|
||||
|
||||
private DeflaterOutputStream dos;
|
||||
private Inflater inflater;
|
||||
|
||||
public ZOutputStream(OutputStream out) throws IOException {
|
||||
super(out);
|
||||
this.out=out;
|
||||
inflater = new Inflater();
|
||||
inflater.init();
|
||||
compress=false;
|
||||
}
|
||||
|
||||
public ZOutputStream(OutputStream out, int level) throws IOException {
|
||||
this(out, level, false);
|
||||
}
|
||||
|
||||
public ZOutputStream(OutputStream out, int level, boolean nowrap) throws IOException {
|
||||
super(out);
|
||||
this.out=out;
|
||||
Deflater deflater = new Deflater(level, nowrap);
|
||||
dos = new DeflaterOutputStream(out, deflater);
|
||||
compress=true;
|
||||
}
|
||||
|
||||
private byte[] buf1 = new byte[1];
|
||||
public void write(int b) throws IOException {
|
||||
buf1[0]=(byte)b;
|
||||
write(buf1, 0, 1);
|
||||
}
|
||||
|
||||
public void write(byte b[], int off, int len) throws IOException {
|
||||
if(len==0) return;
|
||||
if(compress){
|
||||
dos.write(b, off, len);
|
||||
}
|
||||
else {
|
||||
inflater.setInput(b, off, len, true);
|
||||
int err = JZlib.Z_OK;
|
||||
while(inflater.avail_in>0){
|
||||
inflater.setOutput(buf, 0, buf.length);
|
||||
err = inflater.inflate(flush);
|
||||
if(inflater.next_out_index>0)
|
||||
out.write(buf, 0, inflater.next_out_index);
|
||||
if(err != JZlib.Z_OK)
|
||||
break;
|
||||
}
|
||||
if(err != JZlib.Z_OK)
|
||||
throw new ZStreamException("inflating: "+inflater.msg);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public int getFlushMode() {
|
||||
return flush;
|
||||
}
|
||||
|
||||
public void setFlushMode(int flush) {
|
||||
this.flush=flush;
|
||||
}
|
||||
|
||||
public void finish() throws IOException {
|
||||
int err;
|
||||
if(compress){
|
||||
int tmp = flush;
|
||||
int flush = JZlib.Z_FINISH;
|
||||
try{
|
||||
write("".getBytes(), 0, 0);
|
||||
}
|
||||
finally { flush = tmp; }
|
||||
}
|
||||
else{
|
||||
dos.finish();
|
||||
}
|
||||
flush();
|
||||
}
|
||||
public synchronized void end() {
|
||||
if(end) return;
|
||||
if(compress){
|
||||
try { dos.finish(); } catch(Exception e){}
|
||||
}
|
||||
else{
|
||||
inflater.end();
|
||||
}
|
||||
end=true;
|
||||
}
|
||||
public void close() throws IOException {
|
||||
try{
|
||||
try{finish();}
|
||||
catch (IOException ignored) {}
|
||||
}
|
||||
finally{
|
||||
end();
|
||||
out.close();
|
||||
out=null;
|
||||
}
|
||||
}
|
||||
|
||||
public long getTotalIn() {
|
||||
if(compress) return dos.getTotalIn();
|
||||
else return inflater.total_in;
|
||||
}
|
||||
|
||||
public long getTotalOut() {
|
||||
if(compress) return dos.getTotalOut();
|
||||
else return inflater.total_out;
|
||||
}
|
||||
|
||||
public void flush() throws IOException {
|
||||
out.flush();
|
||||
}
|
||||
|
||||
}
|
||||
377
src/lwjgl/java/com/jcraft/jzlib/ZStream.java
Normal file
377
src/lwjgl/java/com/jcraft/jzlib/ZStream.java
Normal file
@@ -0,0 +1,377 @@
|
||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
|
||||
/*
|
||||
Copyright (c) 2000-2011 ymnk, JCraft,Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. The names of the authors may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
|
||||
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/*
|
||||
* This program is based on zlib-1.1.3, so all credit should go authors
|
||||
* Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
|
||||
* and contributors of zlib.
|
||||
*/
|
||||
|
||||
package com.jcraft.jzlib;
|
||||
|
||||
/**
|
||||
* ZStream
|
||||
*
|
||||
* @deprecated Not for public use in the future.
|
||||
*/
|
||||
@Deprecated
|
||||
public class ZStream{
|
||||
|
||||
static final private int MAX_WBITS=15; // 32K LZ77 window
|
||||
static final private int DEF_WBITS=MAX_WBITS;
|
||||
|
||||
static final private int Z_NO_FLUSH=0;
|
||||
static final private int Z_PARTIAL_FLUSH=1;
|
||||
static final private int Z_SYNC_FLUSH=2;
|
||||
static final private int Z_FULL_FLUSH=3;
|
||||
static final private int Z_FINISH=4;
|
||||
|
||||
static final private int MAX_MEM_LEVEL=9;
|
||||
|
||||
static final private int Z_OK=0;
|
||||
static final private int Z_STREAM_END=1;
|
||||
static final private int Z_NEED_DICT=2;
|
||||
static final private int Z_ERRNO=-1;
|
||||
static final private int Z_STREAM_ERROR=-2;
|
||||
static final private int Z_DATA_ERROR=-3;
|
||||
static final private int Z_MEM_ERROR=-4;
|
||||
static final private int Z_BUF_ERROR=-5;
|
||||
static final private int Z_VERSION_ERROR=-6;
|
||||
|
||||
public byte[] next_in; // next input byte
|
||||
public int next_in_index;
|
||||
public int avail_in; // number of bytes available at next_in
|
||||
public long total_in; // total nb of input bytes read so far
|
||||
|
||||
public byte[] next_out; // next output byte should be put there
|
||||
public int next_out_index;
|
||||
public int avail_out; // remaining free space at next_out
|
||||
public long total_out; // total nb of bytes output so far
|
||||
|
||||
public String msg;
|
||||
|
||||
Deflate dstate;
|
||||
Inflate istate;
|
||||
|
||||
int data_type; // best guess about the data type: ascii or binary
|
||||
|
||||
Checksum adler;
|
||||
|
||||
public ZStream(){
|
||||
this(new Adler32());
|
||||
}
|
||||
|
||||
public ZStream(Checksum adler){
|
||||
this.adler=adler;
|
||||
}
|
||||
|
||||
public int inflateInit(){
|
||||
return inflateInit(DEF_WBITS);
|
||||
}
|
||||
public int inflateInit(boolean nowrap){
|
||||
return inflateInit(DEF_WBITS, nowrap);
|
||||
}
|
||||
public int inflateInit(int w){
|
||||
return inflateInit(w, false);
|
||||
}
|
||||
public int inflateInit(JZlib.WrapperType wrapperType) {
|
||||
return inflateInit(DEF_WBITS, wrapperType);
|
||||
}
|
||||
public int inflateInit(int w, JZlib.WrapperType wrapperType) {
|
||||
boolean nowrap = false;
|
||||
if(wrapperType == JZlib.W_NONE){
|
||||
nowrap = true;
|
||||
}
|
||||
else if(wrapperType == JZlib.W_GZIP) {
|
||||
w += 16;
|
||||
}
|
||||
else if(wrapperType == JZlib.W_ANY) {
|
||||
w |= Inflate.INFLATE_ANY;
|
||||
}
|
||||
else if(wrapperType == JZlib.W_ZLIB) {
|
||||
}
|
||||
return inflateInit(w, nowrap);
|
||||
}
|
||||
public int inflateInit(int w, boolean nowrap){
|
||||
istate=new Inflate(this);
|
||||
return istate.inflateInit(nowrap?-w:w);
|
||||
}
|
||||
|
||||
public int inflate(int f){
|
||||
if(istate==null) return Z_STREAM_ERROR;
|
||||
return istate.inflate(f);
|
||||
}
|
||||
public int inflateEnd(){
|
||||
if(istate==null) return Z_STREAM_ERROR;
|
||||
int ret=istate.inflateEnd();
|
||||
// istate = null;
|
||||
return ret;
|
||||
}
|
||||
public int inflateSync(){
|
||||
if(istate == null)
|
||||
return Z_STREAM_ERROR;
|
||||
return istate.inflateSync();
|
||||
}
|
||||
public int inflateSyncPoint(){
|
||||
if(istate == null)
|
||||
return Z_STREAM_ERROR;
|
||||
return istate.inflateSyncPoint();
|
||||
}
|
||||
public int inflateSetDictionary(byte[] dictionary, int dictLength){
|
||||
if(istate == null)
|
||||
return Z_STREAM_ERROR;
|
||||
return istate.inflateSetDictionary(dictionary, dictLength);
|
||||
}
|
||||
public boolean inflateFinished(){
|
||||
return istate.mode==12 /*DONE*/;
|
||||
}
|
||||
|
||||
public int deflateInit(int level){
|
||||
return deflateInit(level, MAX_WBITS);
|
||||
}
|
||||
public int deflateInit(int level, boolean nowrap){
|
||||
return deflateInit(level, MAX_WBITS, nowrap);
|
||||
}
|
||||
public int deflateInit(int level, int bits){
|
||||
return deflateInit(level, bits, false);
|
||||
}
|
||||
public int deflateInit(int level, int bits, int memlevel, JZlib.WrapperType wrapperType){
|
||||
if(bits < 9 || bits > 15){
|
||||
return Z_STREAM_ERROR;
|
||||
}
|
||||
if(wrapperType == JZlib.W_NONE) {
|
||||
bits *= -1;
|
||||
}
|
||||
else if(wrapperType == JZlib.W_GZIP) {
|
||||
bits += 16;
|
||||
}
|
||||
else if(wrapperType == JZlib.W_ANY) {
|
||||
return Z_STREAM_ERROR;
|
||||
}
|
||||
else if(wrapperType == JZlib.W_ZLIB) {
|
||||
}
|
||||
return this.deflateInit(level, bits, memlevel);
|
||||
}
|
||||
public int deflateInit(int level, int bits, int memlevel){
|
||||
dstate=new Deflate(this);
|
||||
return dstate.deflateInit(level, bits, memlevel);
|
||||
}
|
||||
public int deflateInit(int level, int bits, boolean nowrap){
|
||||
dstate=new Deflate(this);
|
||||
return dstate.deflateInit(level, nowrap?-bits:bits);
|
||||
}
|
||||
public int deflate(int flush){
|
||||
if(dstate==null){
|
||||
return Z_STREAM_ERROR;
|
||||
}
|
||||
return dstate.deflate(flush);
|
||||
}
|
||||
public int deflateEnd(){
|
||||
if(dstate==null) return Z_STREAM_ERROR;
|
||||
int ret=dstate.deflateEnd();
|
||||
dstate=null;
|
||||
return ret;
|
||||
}
|
||||
public int deflateParams(int level, int strategy){
|
||||
if(dstate==null) return Z_STREAM_ERROR;
|
||||
return dstate.deflateParams(level, strategy);
|
||||
}
|
||||
public int deflateSetDictionary (byte[] dictionary, int dictLength){
|
||||
if(dstate == null)
|
||||
return Z_STREAM_ERROR;
|
||||
return dstate.deflateSetDictionary(dictionary, dictLength);
|
||||
}
|
||||
|
||||
// Flush as much pending output as possible. All deflate() output goes
|
||||
// through this function so some applications may wish to modify it
|
||||
// to avoid allocating a large strm->next_out buffer and copying into it.
|
||||
// (See also read_buf()).
|
||||
void flush_pending(){
|
||||
int len=dstate.pending;
|
||||
|
||||
if(len>avail_out) len=avail_out;
|
||||
if(len==0) return;
|
||||
|
||||
if(dstate.pending_buf.length<=dstate.pending_out ||
|
||||
next_out.length<=next_out_index ||
|
||||
dstate.pending_buf.length<(dstate.pending_out+len) ||
|
||||
next_out.length<(next_out_index+len)){
|
||||
//System.out.println(dstate.pending_buf.length+", "+dstate.pending_out+
|
||||
// ", "+next_out.length+", "+next_out_index+", "+len);
|
||||
//System.out.println("avail_out="+avail_out);
|
||||
}
|
||||
|
||||
System.arraycopy(dstate.pending_buf, dstate.pending_out,
|
||||
next_out, next_out_index, len);
|
||||
|
||||
next_out_index+=len;
|
||||
dstate.pending_out+=len;
|
||||
total_out+=len;
|
||||
avail_out-=len;
|
||||
dstate.pending-=len;
|
||||
if(dstate.pending==0){
|
||||
dstate.pending_out=0;
|
||||
}
|
||||
}
|
||||
|
||||
// Read a new buffer from the current input stream, update the adler32
|
||||
// and total number of bytes read. All deflate() input goes through
|
||||
// this function so some applications may wish to modify it to avoid
|
||||
// allocating a large strm->next_in buffer and copying from it.
|
||||
// (See also flush_pending()).
|
||||
int read_buf(byte[] buf, int start, int size) {
|
||||
int len=avail_in;
|
||||
|
||||
if(len>size) len=size;
|
||||
if(len==0) return 0;
|
||||
|
||||
avail_in-=len;
|
||||
|
||||
if(dstate.wrap!=0) {
|
||||
adler.update(next_in, next_in_index, len);
|
||||
}
|
||||
System.arraycopy(next_in, next_in_index, buf, start, len);
|
||||
next_in_index += len;
|
||||
total_in += len;
|
||||
return len;
|
||||
}
|
||||
|
||||
public long getAdler(){
|
||||
return adler.getValue();
|
||||
}
|
||||
|
||||
public void free(){
|
||||
next_in=null;
|
||||
next_out=null;
|
||||
msg=null;
|
||||
}
|
||||
|
||||
public void setOutput(byte[] buf){
|
||||
setOutput(buf, 0, buf.length);
|
||||
}
|
||||
|
||||
public void setOutput(byte[] buf, int off, int len){
|
||||
next_out = buf;
|
||||
next_out_index = off;
|
||||
avail_out = len;
|
||||
}
|
||||
|
||||
public void setInput(byte[] buf){
|
||||
setInput(buf, 0, buf.length, false);
|
||||
}
|
||||
|
||||
public void setInput(byte[] buf, boolean append){
|
||||
setInput(buf, 0, buf.length, append);
|
||||
}
|
||||
|
||||
public void setInput(byte[] buf, int off, int len, boolean append){
|
||||
if(len<=0 && append && next_in!=null) return;
|
||||
|
||||
if(avail_in>0 && append){
|
||||
byte[] tmp = new byte[avail_in+len];
|
||||
System.arraycopy(next_in, next_in_index, tmp, 0, avail_in);
|
||||
System.arraycopy(buf, off, tmp, avail_in, len);
|
||||
next_in=tmp;
|
||||
next_in_index=0;
|
||||
avail_in+=len;
|
||||
}
|
||||
else{
|
||||
next_in=buf;
|
||||
next_in_index=off;
|
||||
avail_in=len;
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] getNextIn(){
|
||||
return next_in;
|
||||
}
|
||||
|
||||
public void setNextIn(byte[] next_in){
|
||||
this.next_in = next_in;
|
||||
}
|
||||
|
||||
public int getNextInIndex(){
|
||||
return next_in_index;
|
||||
}
|
||||
|
||||
public void setNextInIndex(int next_in_index){
|
||||
this.next_in_index = next_in_index;
|
||||
}
|
||||
|
||||
public int getAvailIn(){
|
||||
return avail_in;
|
||||
}
|
||||
|
||||
public void setAvailIn(int avail_in){
|
||||
this.avail_in = avail_in;
|
||||
}
|
||||
|
||||
public byte[] getNextOut(){
|
||||
return next_out;
|
||||
}
|
||||
|
||||
public void setNextOut(byte[] next_out){
|
||||
this.next_out = next_out;
|
||||
}
|
||||
|
||||
public int getNextOutIndex(){
|
||||
return next_out_index;
|
||||
}
|
||||
|
||||
public void setNextOutIndex(int next_out_index){
|
||||
this.next_out_index = next_out_index;
|
||||
}
|
||||
|
||||
public int getAvailOut(){
|
||||
return avail_out;
|
||||
|
||||
}
|
||||
|
||||
public void setAvailOut(int avail_out){
|
||||
this.avail_out = avail_out;
|
||||
}
|
||||
|
||||
public long getTotalOut(){
|
||||
return total_out;
|
||||
}
|
||||
|
||||
public long getTotalIn(){
|
||||
return total_in;
|
||||
}
|
||||
|
||||
public String getMessage(){
|
||||
return msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Those methods are expected to be override by Inflater and Deflater.
|
||||
* In the future, they will become abstract methods.
|
||||
*/
|
||||
public int end(){ return Z_OK; }
|
||||
public boolean finished(){ return false; }
|
||||
}
|
||||
44
src/lwjgl/java/com/jcraft/jzlib/ZStreamException.java
Normal file
44
src/lwjgl/java/com/jcraft/jzlib/ZStreamException.java
Normal file
@@ -0,0 +1,44 @@
|
||||
/* -*-mode:java; c-basic-offset:2; -*- */
|
||||
/*
|
||||
Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. The names of the authors may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
|
||||
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/*
|
||||
* This program is based on zlib-1.1.3, so all credit should go authors
|
||||
* Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
|
||||
* and contributors of zlib.
|
||||
*/
|
||||
|
||||
package com.jcraft.jzlib;
|
||||
|
||||
public class ZStreamException extends java.io.IOException {
|
||||
public ZStreamException() {
|
||||
super();
|
||||
}
|
||||
public ZStreamException(String s) {
|
||||
super(s);
|
||||
}
|
||||
}
|
||||
586
src/lwjgl/java/de/cuina/fireandfuel/CodecJLayerMP3.java
Normal file
586
src/lwjgl/java/de/cuina/fireandfuel/CodecJLayerMP3.java
Normal file
@@ -0,0 +1,586 @@
|
||||
package de.cuina.fireandfuel;
|
||||
|
||||
/*
|
||||
* CodecJLayerMP3 - an ICodec interface for Paulscode Sound System
|
||||
* Copyright (C) 2012 by fireandfuel from Cuina Team (http://www.cuina.byethost12.com/)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser 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 on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied. See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this program; if not, see http://www.gnu.org/licenses/lgpl.txt
|
||||
*/
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
|
||||
import javax.sound.sampled.AudioFormat;
|
||||
import javax.sound.sampled.AudioInputStream;
|
||||
|
||||
import javazoom.jl.decoder.Bitstream;
|
||||
import javazoom.jl.decoder.Decoder;
|
||||
import javazoom.jl.decoder.Header;
|
||||
import javazoom.jl.decoder.Obuffer;
|
||||
import javazoom.mp3spi.DecodedMpegAudioInputStream;
|
||||
|
||||
import paulscode.sound.ICodec;
|
||||
import paulscode.sound.SoundBuffer;
|
||||
import paulscode.sound.SoundSystemConfig;
|
||||
import paulscode.sound.SoundSystemLogger;
|
||||
|
||||
/**
|
||||
* The CodecJLayer class provides an ICodec interface to the external JLayer
|
||||
* library.
|
||||
*
|
||||
* <b><br>
|
||||
* <br>
|
||||
* This software is based on or using the JLayer and mp3spi library from
|
||||
* http://www.javazoom.net/javalayer/javalayer.html and Tritonus library from
|
||||
* http://www.tritonus.org/.
|
||||
*
|
||||
* JLayer, mp3spi and Tritonus library are released under the conditions of
|
||||
* GNU Library General Public License version 2 or (at your option)
|
||||
* any later version of the License.
|
||||
* </b><br>
|
||||
*/
|
||||
|
||||
public class CodecJLayerMP3 implements ICodec
|
||||
{
|
||||
/**
|
||||
* Used to return a current value from one of the synchronized
|
||||
* boolean-interface methods.
|
||||
*/
|
||||
private static final boolean GET = false;
|
||||
|
||||
/**
|
||||
* Used to set the value in one of the synchronized boolean-interface
|
||||
* methods.
|
||||
*/
|
||||
private static final boolean SET = true;
|
||||
|
||||
/**
|
||||
* Used when a parameter for one of the synchronized boolean-interface
|
||||
* methods is not applicable.
|
||||
*/
|
||||
private static final boolean XXX = false;
|
||||
|
||||
/**
|
||||
* True if there is no more data to read in.
|
||||
*/
|
||||
private boolean endOfStream = false;
|
||||
|
||||
/**
|
||||
* True if the stream has finished initializing.
|
||||
*/
|
||||
private boolean initialized = false;
|
||||
|
||||
private Decoder decoder;
|
||||
private Bitstream bitstream;
|
||||
private DMAISObuffer buffer;
|
||||
|
||||
private Header mainHeader;
|
||||
|
||||
/**
|
||||
* Audio format to use when playing back the wave data.
|
||||
*/
|
||||
private AudioFormat myAudioFormat = null;
|
||||
|
||||
/**
|
||||
* Input stream to use for reading in pcm data.
|
||||
*/
|
||||
private DecodedMpegAudioInputStream myAudioInputStream = null;
|
||||
|
||||
/**
|
||||
* Processes status messages, warnings, and error messages.
|
||||
*/
|
||||
private SoundSystemLogger logger;
|
||||
|
||||
public CodecJLayerMP3()
|
||||
{
|
||||
logger = SoundSystemConfig.getLogger();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reverseByteOrder(boolean b)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean initialize(URL url)
|
||||
{
|
||||
initialized(SET, false);
|
||||
cleanup();
|
||||
if(url == null)
|
||||
{
|
||||
errorMessage("url null in method 'initialize'");
|
||||
cleanup();
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
bitstream = new Bitstream(new BufferedInputStream(url.openStream()));
|
||||
decoder = new Decoder();
|
||||
|
||||
mainHeader = bitstream.readFrame();
|
||||
|
||||
buffer = new DMAISObuffer(2);
|
||||
decoder.setOutputBuffer(buffer);
|
||||
|
||||
int channels;
|
||||
if(mainHeader.mode() < 3)
|
||||
channels = 2;
|
||||
else channels = 1;
|
||||
|
||||
bitstream.closeFrame();
|
||||
bitstream.close();
|
||||
|
||||
myAudioFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED,
|
||||
mainHeader.frequency(), 16, channels, channels * 2, mainHeader.frequency(),
|
||||
false);
|
||||
|
||||
AudioFormat mpegAudioFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, -1.0f,
|
||||
16, channels, channels * 2, -1.0f, false);
|
||||
|
||||
myAudioInputStream = new DecodedMpegAudioInputStream(myAudioFormat,
|
||||
new AudioInputStream(new BufferedInputStream(url.openStream()),
|
||||
mpegAudioFormat, -1));
|
||||
myAudioInputStream.skip((int)(myAudioInputStream.getFormat().getFrameRate() * 0.018f) * myAudioInputStream.getFormat().getFrameSize());
|
||||
} catch (Exception e)
|
||||
{
|
||||
errorMessage("Unable to set up input streams in method " + "'initialize'");
|
||||
printStackTrace(e);
|
||||
cleanup();
|
||||
return false;
|
||||
}
|
||||
|
||||
if(myAudioInputStream == null)
|
||||
{
|
||||
errorMessage("Unable to set up audio input stream in method " + "'initialize'");
|
||||
cleanup();
|
||||
return false;
|
||||
}
|
||||
|
||||
endOfStream(SET, false);
|
||||
initialized(SET, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean initialized()
|
||||
{
|
||||
return initialized(GET, XXX);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SoundBuffer read()
|
||||
{
|
||||
if(myAudioInputStream == null)
|
||||
{
|
||||
endOfStream(SET, true);
|
||||
return null;
|
||||
}
|
||||
|
||||
// Get the format for the audio data:
|
||||
AudioFormat audioFormat = myAudioInputStream.getFormat();
|
||||
|
||||
// Check to make sure there is an audio format:
|
||||
if(audioFormat == null)
|
||||
{
|
||||
errorMessage("Audio Format null in method 'read'");
|
||||
endOfStream(SET, true);
|
||||
return null;
|
||||
}
|
||||
|
||||
// Variables used when reading from the audio input stream:
|
||||
int bytesRead = 0, cnt = 0;
|
||||
|
||||
// Allocate memory for the audio data:
|
||||
byte[] streamBuffer = new byte[SoundSystemConfig.getStreamingBufferSize()];
|
||||
|
||||
try
|
||||
{
|
||||
// Read until buffer is full or end of stream is reached:
|
||||
while((!endOfStream(GET, XXX)) && (bytesRead < streamBuffer.length))
|
||||
{
|
||||
myAudioInputStream.execute();
|
||||
if((cnt = myAudioInputStream.read(streamBuffer, bytesRead, streamBuffer.length
|
||||
- bytesRead)) < 0)
|
||||
{
|
||||
endOfStream(SET, true);
|
||||
break;
|
||||
}
|
||||
// keep track of how many bytes were read:
|
||||
bytesRead += cnt;
|
||||
}
|
||||
} catch (IOException ioe)
|
||||
{
|
||||
|
||||
/*
|
||||
* errorMessage( "Exception thrown while reading from the " +
|
||||
* "AudioInputStream (location #3)." ); printStackTrace( e ); return
|
||||
* null;
|
||||
*/// TODO: Figure out why this exceptions is being thrown at end of
|
||||
// MP3 files!
|
||||
endOfStream(SET, true);
|
||||
return null;
|
||||
} catch (ArrayIndexOutOfBoundsException e)
|
||||
{
|
||||
//this exception is thrown at the end of the mp3's
|
||||
endOfStream(SET, true);
|
||||
return null;
|
||||
}
|
||||
|
||||
// Return null if no data was read:
|
||||
if(bytesRead <= 0)
|
||||
{
|
||||
endOfStream(SET, true);
|
||||
return null;
|
||||
}
|
||||
|
||||
// Insert the converted data into a ByteBuffer:
|
||||
// byte[] data = convertAudioBytes(streamBuffer,
|
||||
// audioFormat.getSampleSizeInBits() == 16);
|
||||
|
||||
// Wrap the data into a SoundBuffer:
|
||||
SoundBuffer buffer = new SoundBuffer(streamBuffer, audioFormat);
|
||||
|
||||
// Return the result:
|
||||
return buffer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SoundBuffer readAll()
|
||||
{
|
||||
// Check to make sure there is an audio format:
|
||||
if(myAudioFormat == null)
|
||||
{
|
||||
errorMessage("Audio Format null in method 'readAll'");
|
||||
return null;
|
||||
}
|
||||
|
||||
// Array to contain the audio data:
|
||||
byte[] fullBuffer = null;
|
||||
|
||||
// Determine how much data will be read in:
|
||||
int fileSize = myAudioFormat.getChannels() * (int) myAudioInputStream.getFrameLength()
|
||||
* myAudioFormat.getSampleSizeInBits() / 8;
|
||||
if(fileSize > 0)
|
||||
{
|
||||
// Allocate memory for the audio data:
|
||||
fullBuffer = new byte[myAudioFormat.getChannels()
|
||||
* (int) myAudioInputStream.getFrameLength()
|
||||
* myAudioFormat.getSampleSizeInBits() / 8];
|
||||
int read = 0, total = 0;
|
||||
try
|
||||
{
|
||||
// Read until the end of the stream is reached:
|
||||
while((read = myAudioInputStream.read(fullBuffer, total, fullBuffer.length - total)) != -1
|
||||
&& total < fullBuffer.length)
|
||||
{
|
||||
total += read;
|
||||
}
|
||||
} catch (IOException e)
|
||||
{
|
||||
errorMessage("Exception thrown while reading from the "
|
||||
+ "AudioInputStream (location #1).");
|
||||
printStackTrace(e);
|
||||
return null;
|
||||
}
|
||||
} else
|
||||
{
|
||||
// Total file size unknown.
|
||||
|
||||
// Variables used when reading from the audio input stream:
|
||||
int totalBytes = 0, bytesRead = 0, cnt = 0;
|
||||
byte[] smallBuffer = null;
|
||||
|
||||
// Allocate memory for a chunk of data:
|
||||
smallBuffer = new byte[SoundSystemConfig.getFileChunkSize()];
|
||||
|
||||
// Read until end of file or maximum file size is reached:
|
||||
while((!endOfStream(GET, XXX)) && (totalBytes < SoundSystemConfig.getMaxFileSize()))
|
||||
{
|
||||
bytesRead = 0;
|
||||
cnt = 0;
|
||||
|
||||
try
|
||||
{
|
||||
// Read until small buffer is filled or end of file reached:
|
||||
while(bytesRead < smallBuffer.length)
|
||||
{
|
||||
myAudioInputStream.execute();
|
||||
if((cnt = myAudioInputStream.read(smallBuffer, bytesRead,
|
||||
smallBuffer.length - bytesRead)) < 0)
|
||||
{
|
||||
endOfStream(SET, true);
|
||||
break;
|
||||
}
|
||||
bytesRead += cnt;
|
||||
}
|
||||
} catch (IOException e)
|
||||
{
|
||||
errorMessage("Exception thrown while reading from the "
|
||||
+ "AudioInputStream (location #2).");
|
||||
printStackTrace(e);
|
||||
return null;
|
||||
}
|
||||
|
||||
// Reverse byte order if necessary:
|
||||
// if( reverseBytes )
|
||||
// reverseBytes( smallBuffer, 0, bytesRead );
|
||||
|
||||
// Keep track of the total number of bytes read:
|
||||
totalBytes += bytesRead;
|
||||
|
||||
// Append the small buffer to the full buffer:
|
||||
fullBuffer = appendByteArrays(fullBuffer, smallBuffer, bytesRead);
|
||||
}
|
||||
}
|
||||
|
||||
// Insert the converted data into a ByteBuffer
|
||||
// byte[] data = convertAudioBytes( fullBuffer,
|
||||
// myAudioFormat.getSampleSizeInBits() == 16 );
|
||||
|
||||
// Wrap the data into an SoundBuffer:
|
||||
SoundBuffer soundBuffer = new SoundBuffer(fullBuffer, myAudioFormat);
|
||||
|
||||
// Close the audio input stream
|
||||
try
|
||||
{
|
||||
myAudioInputStream.close();
|
||||
} catch (IOException e)
|
||||
{
|
||||
}
|
||||
|
||||
// Return the result:
|
||||
return soundBuffer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean endOfStream()
|
||||
{
|
||||
return endOfStream(GET, XXX);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanup()
|
||||
{
|
||||
if(myAudioInputStream != null)
|
||||
try
|
||||
{
|
||||
myAudioInputStream.close();
|
||||
} catch (Exception e)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AudioFormat getAudioFormat()
|
||||
{
|
||||
return myAudioFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal method for synchronizing access to the boolean 'initialized'.
|
||||
*
|
||||
* @param action
|
||||
* GET or SET.
|
||||
* @param value
|
||||
* New value if action == SET, or XXX if action == GET.
|
||||
* @return True if steam is initialized.
|
||||
*/
|
||||
private synchronized boolean initialized(boolean action, boolean value)
|
||||
{
|
||||
if(action == SET)
|
||||
initialized = value;
|
||||
return initialized;
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal method for synchronizing access to the boolean 'endOfStream'.
|
||||
*
|
||||
* @param action
|
||||
* GET or SET.
|
||||
* @param value
|
||||
* New value if action == SET, or XXX if action == GET.
|
||||
* @return True if end of stream was reached.
|
||||
*/
|
||||
private synchronized boolean endOfStream(boolean action, boolean value)
|
||||
{
|
||||
if(action == SET)
|
||||
endOfStream = value;
|
||||
return endOfStream;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse-orders all bytes contained in the specified array.
|
||||
*
|
||||
* @param buffer
|
||||
* Array containing audio data.
|
||||
*/
|
||||
public static void reverseBytes(byte[] buffer)
|
||||
{
|
||||
reverseBytes(buffer, 0, buffer.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse-orders the specified range of bytes contained in the specified
|
||||
* array.
|
||||
*
|
||||
* @param buffer
|
||||
* Array containing audio data.
|
||||
* @param offset
|
||||
* Array index to begin.
|
||||
* @param size
|
||||
* number of bytes to reverse-order.
|
||||
*/
|
||||
public static void reverseBytes(byte[] buffer, int offset, int size)
|
||||
{
|
||||
|
||||
byte b;
|
||||
for(int i = offset; i < (offset + size); i += 2)
|
||||
{
|
||||
b = buffer[i];
|
||||
buffer[i] = buffer[i + 1];
|
||||
buffer[i + 1] = b;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints an error message.
|
||||
*
|
||||
* @param message
|
||||
* Message to print.
|
||||
*/
|
||||
private void errorMessage(String message)
|
||||
{
|
||||
logger.errorMessage("CodecJLayerMP3", message, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints an exception's error message followed by the stack trace.
|
||||
*
|
||||
* @param e
|
||||
* Exception containing the information to print.
|
||||
*/
|
||||
private void printStackTrace(Exception e)
|
||||
{
|
||||
logger.printStackTrace(e, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new array with the second array appended to the end of the
|
||||
* first array.
|
||||
*
|
||||
* @param arrayOne
|
||||
* The first array.
|
||||
* @param arrayTwo
|
||||
* The second array.
|
||||
* @param length
|
||||
* How many bytes to append from the second array.
|
||||
* @return Byte array containing information from both arrays.
|
||||
*/
|
||||
private static byte[] appendByteArrays(byte[] arrayOne, byte[] arrayTwo, int length)
|
||||
{
|
||||
byte[] newArray;
|
||||
if(arrayOne == null && arrayTwo == null)
|
||||
{
|
||||
// no data, just return
|
||||
return null;
|
||||
} else if(arrayOne == null)
|
||||
{
|
||||
// create the new array, same length as arrayTwo:
|
||||
newArray = new byte[length];
|
||||
// fill the new array with the contents of arrayTwo:
|
||||
System.arraycopy(arrayTwo, 0, newArray, 0, length);
|
||||
arrayTwo = null;
|
||||
} else if(arrayTwo == null)
|
||||
{
|
||||
// create the new array, same length as arrayOne:
|
||||
newArray = new byte[arrayOne.length];
|
||||
// fill the new array with the contents of arrayOne:
|
||||
System.arraycopy(arrayOne, 0, newArray, 0, arrayOne.length);
|
||||
arrayOne = null;
|
||||
} else
|
||||
{
|
||||
// create the new array large enough to hold both arrays:
|
||||
newArray = new byte[arrayOne.length + length];
|
||||
System.arraycopy(arrayOne, 0, newArray, 0, arrayOne.length);
|
||||
// fill the new array with the contents of both arrays:
|
||||
System.arraycopy(arrayTwo, 0, newArray, arrayOne.length, length);
|
||||
arrayOne = null;
|
||||
arrayTwo = null;
|
||||
}
|
||||
|
||||
return newArray;
|
||||
}
|
||||
|
||||
private static class DMAISObuffer extends Obuffer
|
||||
{
|
||||
private int m_nChannels;
|
||||
private byte[] m_abBuffer;
|
||||
private int[] m_anBufferPointers;
|
||||
private boolean m_bIsBigEndian;
|
||||
|
||||
public DMAISObuffer(int nChannels)
|
||||
{
|
||||
m_nChannels = nChannels;
|
||||
m_abBuffer = new byte[OBUFFERSIZE * nChannels];
|
||||
m_anBufferPointers = new int[nChannels];
|
||||
reset();
|
||||
}
|
||||
|
||||
public void append(int nChannel, short sValue)
|
||||
{
|
||||
byte bFirstByte;
|
||||
byte bSecondByte;
|
||||
if(m_bIsBigEndian)
|
||||
{
|
||||
bFirstByte = (byte) ((sValue >>> 8) & 0xFF);
|
||||
bSecondByte = (byte) (sValue & 0xFF);
|
||||
} else
|
||||
// little endian
|
||||
{
|
||||
bFirstByte = (byte) (sValue & 0xFF);
|
||||
bSecondByte = (byte) ((sValue >>> 8) & 0xFF);
|
||||
}
|
||||
m_abBuffer[m_anBufferPointers[nChannel]] = bFirstByte;
|
||||
m_abBuffer[m_anBufferPointers[nChannel] + 1] = bSecondByte;
|
||||
m_anBufferPointers[nChannel] += m_nChannels * 2;
|
||||
}
|
||||
|
||||
public void set_stop_flag()
|
||||
{
|
||||
}
|
||||
|
||||
public void close()
|
||||
{
|
||||
}
|
||||
|
||||
public void write_buffer(int nValue)
|
||||
{
|
||||
}
|
||||
|
||||
public void clear_buffer()
|
||||
{
|
||||
}
|
||||
|
||||
public void reset()
|
||||
{
|
||||
for(int i = 0; i < m_nChannels; i++)
|
||||
{
|
||||
/*
|
||||
* Points to byte location, implicitly assuming 16 bit samples.
|
||||
*/
|
||||
m_anBufferPointers[i] = i * 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
224
src/lwjgl/java/javazoom/jl/decoder/BitReserve.java
Normal file
224
src/lwjgl/java/javazoom/jl/decoder/BitReserve.java
Normal file
@@ -0,0 +1,224 @@
|
||||
/*
|
||||
* 11/19/04 1.0 moved to LGPL.
|
||||
*
|
||||
* 12/12/99 0.0.7 Implementation stores single bits
|
||||
* as ints for better performance. mdm@techie.com.
|
||||
*
|
||||
* 02/28/99 0.0 Java Conversion by E.B, javalayer@javazoom.net
|
||||
*
|
||||
* Adapted from the public c code by Jeff Tsay.
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library General Public License as published
|
||||
* by the Free Software Foundation; either version 2 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 Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
package javazoom.jl.decoder;
|
||||
|
||||
/**
|
||||
* Implementation of Bit Reservoir for Layer III.
|
||||
* <p>
|
||||
* The implementation stores single bits as a word in the buffer. If
|
||||
* a bit is set, the corresponding word in the buffer will be non-zero.
|
||||
* If a bit is clear, the corresponding word is zero. Although this
|
||||
* may seem wasteful, this can be a factor of two quicker than
|
||||
* packing 8 bits to a byte and extracting.
|
||||
* <p>
|
||||
*/
|
||||
|
||||
// REVIEW: there is no range checking, so buffer underflow or overflow
|
||||
// can silently occur.
|
||||
final class BitReserve
|
||||
{
|
||||
/**
|
||||
* Size of the internal buffer to store the reserved bits.
|
||||
* Must be a power of 2. And x8, as each bit is stored as a single
|
||||
* entry.
|
||||
*/
|
||||
private static final int BUFSIZE = 4096*8;
|
||||
|
||||
/**
|
||||
* Mask that can be used to quickly implement the
|
||||
* modulus operation on BUFSIZE.
|
||||
*/
|
||||
private static final int BUFSIZE_MASK = BUFSIZE-1;
|
||||
|
||||
private int offset, totbit, buf_byte_idx;
|
||||
private final int[] buf = new int[BUFSIZE];
|
||||
private int buf_bit_idx;
|
||||
|
||||
BitReserve()
|
||||
{
|
||||
|
||||
offset = 0;
|
||||
totbit = 0;
|
||||
buf_byte_idx = 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return totbit Field.
|
||||
*/
|
||||
public int hsstell()
|
||||
{
|
||||
return(totbit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a number bits from the bit stream.
|
||||
* @param N the number of
|
||||
*/
|
||||
public int hgetbits(int N)
|
||||
{
|
||||
totbit += N;
|
||||
|
||||
int val = 0;
|
||||
|
||||
int pos = buf_byte_idx;
|
||||
if (pos+N < BUFSIZE)
|
||||
{
|
||||
while (N-- > 0)
|
||||
{
|
||||
val <<= 1;
|
||||
val |= ((buf[pos++]!=0) ? 1 : 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (N-- > 0)
|
||||
{
|
||||
val <<= 1;
|
||||
val |= ((buf[pos]!=0) ? 1 : 0);
|
||||
pos = (pos+1) & BUFSIZE_MASK;
|
||||
}
|
||||
}
|
||||
buf_byte_idx = pos;
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Read 1 bit from the bit stream.
|
||||
*/
|
||||
/*
|
||||
public int hget1bit_old()
|
||||
{
|
||||
int val;
|
||||
totbit++;
|
||||
if (buf_bit_idx == 0)
|
||||
{
|
||||
buf_bit_idx = 8;
|
||||
buf_byte_idx++;
|
||||
}
|
||||
// BUFSIZE = 4096 = 2^12, so
|
||||
// buf_byte_idx%BUFSIZE == buf_byte_idx & 0xfff
|
||||
val = buf[buf_byte_idx & BUFSIZE_MASK] & putmask[buf_bit_idx];
|
||||
buf_bit_idx--;
|
||||
val = val >>> buf_bit_idx;
|
||||
return val;
|
||||
}
|
||||
*/
|
||||
/**
|
||||
* Returns next bit from reserve.
|
||||
*
|
||||
* @return 0 if next bit is reset, or 1 if next bit is set.
|
||||
*/
|
||||
public int hget1bit()
|
||||
{
|
||||
totbit++;
|
||||
int val = buf[buf_byte_idx];
|
||||
buf_byte_idx = (buf_byte_idx+1) & BUFSIZE_MASK;
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves bits from the reserve.
|
||||
*/
|
||||
/*
|
||||
public int readBits(int[] out, int len)
|
||||
{
|
||||
if (buf_bit_idx == 0)
|
||||
{
|
||||
buf_bit_idx = 8;
|
||||
buf_byte_idx++;
|
||||
current = buf[buf_byte_idx & BUFSIZE_MASK];
|
||||
}
|
||||
|
||||
|
||||
|
||||
// save total number of bits returned
|
||||
len = buf_bit_idx;
|
||||
buf_bit_idx = 0;
|
||||
|
||||
int b = current;
|
||||
int count = len-1;
|
||||
|
||||
while (count >= 0)
|
||||
{
|
||||
out[count--] = (b & 0x1);
|
||||
b >>>= 1;
|
||||
}
|
||||
|
||||
totbit += len;
|
||||
return len;
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Write 8 bits into the bit stream.
|
||||
*/
|
||||
public void hputbuf(int val)
|
||||
{
|
||||
int ofs = offset;
|
||||
buf[ofs++] = val & 0x80;
|
||||
buf[ofs++] = val & 0x40;
|
||||
buf[ofs++] = val & 0x20;
|
||||
buf[ofs++] = val & 0x10;
|
||||
buf[ofs++] = val & 0x08;
|
||||
buf[ofs++] = val & 0x04;
|
||||
buf[ofs++] = val & 0x02;
|
||||
buf[ofs++] = val & 0x01;
|
||||
|
||||
if (ofs==BUFSIZE)
|
||||
offset = 0;
|
||||
else
|
||||
offset = ofs;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewind N bits in Stream.
|
||||
*/
|
||||
public void rewindNbits(int N)
|
||||
{
|
||||
totbit -= N;
|
||||
buf_byte_idx -= N;
|
||||
if (buf_byte_idx<0)
|
||||
buf_byte_idx += BUFSIZE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewind N bytes in Stream.
|
||||
*/
|
||||
public void rewindNbytes(int N)
|
||||
{
|
||||
int bits = (N << 3);
|
||||
totbit -= bits;
|
||||
buf_byte_idx -= bits;
|
||||
if (buf_byte_idx<0)
|
||||
buf_byte_idx += BUFSIZE;
|
||||
}
|
||||
}
|
||||
659
src/lwjgl/java/javazoom/jl/decoder/Bitstream.java
Normal file
659
src/lwjgl/java/javazoom/jl/decoder/Bitstream.java
Normal file
@@ -0,0 +1,659 @@
|
||||
/*
|
||||
* 11/19/04 1.0 moved to LGPL.
|
||||
*
|
||||
* 11/17/04 Uncomplete frames discarded. E.B, javalayer@javazoom.net
|
||||
*
|
||||
* 12/05/03 ID3v2 tag returned. E.B, javalayer@javazoom.net
|
||||
*
|
||||
* 12/12/99 Based on Ibitstream. Exceptions thrown on errors,
|
||||
* Temporary removed seek functionality. mdm@techie.com
|
||||
*
|
||||
* 02/12/99 : Java Conversion by E.B , javalayer@javazoom.net
|
||||
*
|
||||
* 04/14/97 : Added function prototypes for new syncing and seeking
|
||||
* mechanisms. Also made this file portable. Changes made by Jeff Tsay
|
||||
*
|
||||
* @(#) ibitstream.h 1.5, last edit: 6/15/94 16:55:34
|
||||
* @(#) Copyright (C) 1993, 1994 Tobias Bading (bading@cs.tu-berlin.de)
|
||||
* @(#) Berlin University of Technology
|
||||
*-----------------------------------------------------------------------
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library General Public License as published
|
||||
* by the Free Software Foundation; either version 2 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 Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
package javazoom.jl.decoder;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.PushbackInputStream;
|
||||
|
||||
|
||||
/**
|
||||
* The <code>Bistream</code> class is responsible for parsing
|
||||
* an MPEG audio bitstream.
|
||||
*
|
||||
* <b>REVIEW:</b> much of the parsing currently occurs in the
|
||||
* various decoders. This should be moved into this class and associated
|
||||
* inner classes.
|
||||
*/
|
||||
public final class Bitstream implements BitstreamErrors
|
||||
{
|
||||
/**
|
||||
* Synchronization control constant for the initial
|
||||
* synchronization to the start of a frame.
|
||||
*/
|
||||
static byte INITIAL_SYNC = 0;
|
||||
|
||||
/**
|
||||
* Synchronization control constant for non-initial frame
|
||||
* synchronizations.
|
||||
*/
|
||||
static byte STRICT_SYNC = 1;
|
||||
|
||||
// max. 1730 bytes per frame: 144 * 384kbit/s / 32000 Hz + 2 Bytes CRC
|
||||
/**
|
||||
* Maximum size of the frame buffer.
|
||||
*/
|
||||
private static final int BUFFER_INT_SIZE = 433;
|
||||
|
||||
/**
|
||||
* The frame buffer that holds the data for the current frame.
|
||||
*/
|
||||
private final int[] framebuffer = new int[BUFFER_INT_SIZE];
|
||||
|
||||
/**
|
||||
* Number of valid bytes in the frame buffer.
|
||||
*/
|
||||
private int framesize;
|
||||
|
||||
/**
|
||||
* The bytes read from the stream.
|
||||
*/
|
||||
private byte[] frame_bytes = new byte[BUFFER_INT_SIZE*4];
|
||||
|
||||
/**
|
||||
* Index into <code>framebuffer</code> where the next bits are
|
||||
* retrieved.
|
||||
*/
|
||||
private int wordpointer;
|
||||
|
||||
/**
|
||||
* Number (0-31, from MSB to LSB) of next bit for get_bits()
|
||||
*/
|
||||
private int bitindex;
|
||||
|
||||
/**
|
||||
* The current specified syncword
|
||||
*/
|
||||
private int syncword;
|
||||
|
||||
/**
|
||||
* Audio header position in stream.
|
||||
*/
|
||||
private int header_pos = 0;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private boolean single_ch_mode;
|
||||
//private int current_frame_number;
|
||||
//private int last_frame_number;
|
||||
|
||||
private final int bitmask[] = {0, // dummy
|
||||
0x00000001, 0x00000003, 0x00000007, 0x0000000F,
|
||||
0x0000001F, 0x0000003F, 0x0000007F, 0x000000FF,
|
||||
0x000001FF, 0x000003FF, 0x000007FF, 0x00000FFF,
|
||||
0x00001FFF, 0x00003FFF, 0x00007FFF, 0x0000FFFF,
|
||||
0x0001FFFF };
|
||||
|
||||
private final PushbackInputStream source;
|
||||
|
||||
private final Header header = new Header();
|
||||
|
||||
private final byte syncbuf[] = new byte[4];
|
||||
|
||||
private Crc16[] crc = new Crc16[1];
|
||||
|
||||
private byte[] rawid3v2 = null;
|
||||
|
||||
private boolean firstframe = true;
|
||||
|
||||
|
||||
/**
|
||||
* Construct a IBitstream that reads data from a
|
||||
* given InputStream.
|
||||
*
|
||||
* @param in The InputStream to read from.
|
||||
*/
|
||||
public Bitstream(InputStream in)
|
||||
{
|
||||
if (in==null) throw new NullPointerException("in");
|
||||
in = new BufferedInputStream(in);
|
||||
loadID3v2(in);
|
||||
firstframe = true;
|
||||
//source = new PushbackInputStream(in, 1024);
|
||||
source = new PushbackInputStream(in, BUFFER_INT_SIZE*4);
|
||||
|
||||
closeFrame();
|
||||
//current_frame_number = -1;
|
||||
//last_frame_number = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return position of the first audio header.
|
||||
* @return size of ID3v2 tag frames.
|
||||
*/
|
||||
public int header_pos()
|
||||
{
|
||||
return header_pos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load ID3v2 frames.
|
||||
* @param in MP3 InputStream.
|
||||
* @author JavaZOOM
|
||||
*/
|
||||
private void loadID3v2(InputStream in)
|
||||
{
|
||||
int size = -1;
|
||||
try
|
||||
{
|
||||
// Read ID3v2 header (10 bytes).
|
||||
in.mark(10);
|
||||
size = readID3v2Header(in);
|
||||
header_pos = size;
|
||||
}
|
||||
catch (IOException e)
|
||||
{}
|
||||
finally
|
||||
{
|
||||
try
|
||||
{
|
||||
// Unread ID3v2 header (10 bytes).
|
||||
in.reset();
|
||||
}
|
||||
catch (IOException e)
|
||||
{}
|
||||
}
|
||||
// Load ID3v2 tags.
|
||||
try
|
||||
{
|
||||
if (size > 0)
|
||||
{
|
||||
rawid3v2 = new byte[size];
|
||||
in.read(rawid3v2,0,rawid3v2.length);
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse ID3v2 tag header to find out size of ID3v2 frames.
|
||||
* @param in MP3 InputStream
|
||||
* @return size of ID3v2 frames + header
|
||||
* @throws IOException
|
||||
* @author JavaZOOM
|
||||
*/
|
||||
private int readID3v2Header(InputStream in) throws IOException
|
||||
{
|
||||
byte[] id3header = new byte[4];
|
||||
int size = -10;
|
||||
in.read(id3header,0,3);
|
||||
// Look for ID3v2
|
||||
if ( (id3header[0]=='I') && (id3header[1]=='D') && (id3header[2]=='3'))
|
||||
{
|
||||
in.read(id3header,0,3);
|
||||
int majorVersion = id3header[0];
|
||||
int revision = id3header[1];
|
||||
in.read(id3header,0,4);
|
||||
size = (int) (id3header[0] << 21) + (id3header[1] << 14) + (id3header[2] << 7) + (id3header[3]);
|
||||
}
|
||||
return (size+10);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return raw ID3v2 frames + header.
|
||||
* @return ID3v2 InputStream or null if ID3v2 frames are not available.
|
||||
*/
|
||||
public InputStream getRawID3v2()
|
||||
{
|
||||
if (rawid3v2 == null) return null;
|
||||
else
|
||||
{
|
||||
ByteArrayInputStream bain = new ByteArrayInputStream(rawid3v2);
|
||||
return bain;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the Bitstream.
|
||||
* @throws BitstreamException
|
||||
*/
|
||||
public void close() throws BitstreamException
|
||||
{
|
||||
try
|
||||
{
|
||||
source.close();
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
throw newBitstreamException(STREAM_ERROR, ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads and parses the next frame from the input source.
|
||||
*
|
||||
* @return the Header describing details of the frame read,
|
||||
* or null if the end of the stream has been reached.
|
||||
*/
|
||||
public Header readFrame() throws BitstreamException
|
||||
{
|
||||
Header result = null;
|
||||
try
|
||||
{
|
||||
result = readNextFrame();
|
||||
// E.B, Parse VBR (if any) first frame.
|
||||
if (firstframe == true)
|
||||
{
|
||||
result.parseVBR(frame_bytes);
|
||||
firstframe = false;
|
||||
}
|
||||
}
|
||||
catch (BitstreamException ex)
|
||||
{
|
||||
if ((ex.getErrorCode()==INVALIDFRAME))
|
||||
{
|
||||
// Try to skip this frame.
|
||||
//System.out.println("INVALIDFRAME");
|
||||
try
|
||||
{
|
||||
closeFrame();
|
||||
result = readNextFrame();
|
||||
}
|
||||
catch (BitstreamException e)
|
||||
{
|
||||
if ((e.getErrorCode()!=STREAM_EOF))
|
||||
{
|
||||
// wrap original exception so stack trace is maintained.
|
||||
throw newBitstreamException(e.getErrorCode(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ((ex.getErrorCode()!=STREAM_EOF))
|
||||
{
|
||||
// wrap original exception so stack trace is maintained.
|
||||
throw newBitstreamException(ex.getErrorCode(), ex);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read next MP3 frame.
|
||||
*
|
||||
* @return MP3 frame header.
|
||||
* @throws BitstreamException
|
||||
*/
|
||||
private Header readNextFrame() throws BitstreamException
|
||||
{
|
||||
if (framesize == -1)
|
||||
{
|
||||
nextFrame();
|
||||
}
|
||||
return header;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Read next MP3 frame.
|
||||
*
|
||||
* @throws BitstreamException
|
||||
*/
|
||||
private void nextFrame() throws BitstreamException
|
||||
{
|
||||
// entire frame is read by the header class.
|
||||
header.read_header(this, crc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unreads the bytes read from the frame.
|
||||
*
|
||||
* @throws BitstreamException
|
||||
*/
|
||||
// REVIEW: add new error codes for this.
|
||||
public void unreadFrame() throws BitstreamException
|
||||
{
|
||||
if (wordpointer==-1 && bitindex==-1 && (framesize>0))
|
||||
{
|
||||
try
|
||||
{
|
||||
source.unread(frame_bytes, 0, framesize);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
throw newBitstreamException(STREAM_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Close MP3 frame.
|
||||
*/
|
||||
public void closeFrame()
|
||||
{
|
||||
framesize = -1;
|
||||
wordpointer = -1;
|
||||
bitindex = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the next 4 bytes of the stream represent a
|
||||
* frame header.
|
||||
*/
|
||||
public boolean isSyncCurrentPosition(int syncmode) throws BitstreamException
|
||||
{
|
||||
int read = readBytes(syncbuf, 0, 4);
|
||||
int headerstring = ((syncbuf[0] << 24) & 0xFF000000) | ((syncbuf[1] << 16) & 0x00FF0000) | ((syncbuf[2] << 8) & 0x0000FF00) | ((syncbuf[3] << 0) & 0x000000FF);
|
||||
|
||||
try
|
||||
{
|
||||
source.unread(syncbuf, 0, read);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
}
|
||||
|
||||
boolean sync = false;
|
||||
switch (read)
|
||||
{
|
||||
case 0:
|
||||
sync = true;
|
||||
break;
|
||||
case 4:
|
||||
sync = isSyncMark(headerstring, syncmode, syncword);
|
||||
break;
|
||||
}
|
||||
|
||||
return sync;
|
||||
}
|
||||
|
||||
|
||||
// REVIEW: this class should provide inner classes to
|
||||
// parse the frame contents. Eventually, readBits will
|
||||
// be removed.
|
||||
public int readBits(int n)
|
||||
{
|
||||
return get_bits(n);
|
||||
}
|
||||
|
||||
public int readCheckedBits(int n)
|
||||
{
|
||||
// REVIEW: implement CRC check.
|
||||
return get_bits(n);
|
||||
}
|
||||
|
||||
protected BitstreamException newBitstreamException(int errorcode)
|
||||
{
|
||||
return new BitstreamException(errorcode, null);
|
||||
}
|
||||
protected BitstreamException newBitstreamException(int errorcode, Throwable throwable)
|
||||
{
|
||||
return new BitstreamException(errorcode, throwable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get next 32 bits from bitstream.
|
||||
* They are stored in the headerstring.
|
||||
* syncmod allows Synchro flag ID
|
||||
* The returned value is False at the end of stream.
|
||||
*/
|
||||
|
||||
int syncHeader(byte syncmode) throws BitstreamException
|
||||
{
|
||||
boolean sync;
|
||||
int headerstring;
|
||||
// read additional 2 bytes
|
||||
int bytesRead = readBytes(syncbuf, 0, 3);
|
||||
|
||||
if (bytesRead!=3) throw newBitstreamException(STREAM_EOF, null);
|
||||
|
||||
headerstring = ((syncbuf[0] << 16) & 0x00FF0000) | ((syncbuf[1] << 8) & 0x0000FF00) | ((syncbuf[2] << 0) & 0x000000FF);
|
||||
|
||||
do
|
||||
{
|
||||
headerstring <<= 8;
|
||||
|
||||
if (readBytes(syncbuf, 3, 1)!=1)
|
||||
throw newBitstreamException(STREAM_EOF, null);
|
||||
|
||||
headerstring |= (syncbuf[3] & 0x000000FF);
|
||||
|
||||
sync = isSyncMark(headerstring, syncmode, syncword);
|
||||
}
|
||||
while (!sync);
|
||||
|
||||
//current_frame_number++;
|
||||
//if (last_frame_number < current_frame_number) last_frame_number = current_frame_number;
|
||||
|
||||
return headerstring;
|
||||
}
|
||||
|
||||
public boolean isSyncMark(int headerstring, int syncmode, int word)
|
||||
{
|
||||
boolean sync = false;
|
||||
|
||||
if (syncmode == INITIAL_SYNC)
|
||||
{
|
||||
//sync = ((headerstring & 0xFFF00000) == 0xFFF00000);
|
||||
sync = ((headerstring & 0xFFE00000) == 0xFFE00000); // SZD: MPEG 2.5
|
||||
}
|
||||
else
|
||||
{
|
||||
sync = ((headerstring & 0xFFF80C00) == word) &&
|
||||
(((headerstring & 0x000000C0) == 0x000000C0) == single_ch_mode);
|
||||
}
|
||||
|
||||
// filter out invalid sample rate
|
||||
if (sync)
|
||||
sync = (((headerstring >>> 10) & 3)!=3);
|
||||
// filter out invalid layer
|
||||
if (sync)
|
||||
sync = (((headerstring >>> 17) & 3)!=0);
|
||||
// filter out invalid version
|
||||
if (sync)
|
||||
sync = (((headerstring >>> 19) & 3)!=1);
|
||||
|
||||
return sync;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the data for the next frame. The frame is not parsed
|
||||
* until parse frame is called.
|
||||
*/
|
||||
int read_frame_data(int bytesize) throws BitstreamException
|
||||
{
|
||||
int numread = 0;
|
||||
numread = readFully(frame_bytes, 0, bytesize);
|
||||
framesize = bytesize;
|
||||
wordpointer = -1;
|
||||
bitindex = -1;
|
||||
return numread;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the data previously read with read_frame_data().
|
||||
*/
|
||||
void parse_frame() throws BitstreamException
|
||||
{
|
||||
// Convert Bytes read to int
|
||||
int b=0;
|
||||
byte[] byteread = frame_bytes;
|
||||
int bytesize = framesize;
|
||||
|
||||
// Check ID3v1 TAG (True only if last frame).
|
||||
//for (int t=0;t<(byteread.length)-2;t++)
|
||||
//{
|
||||
// if ((byteread[t]=='T') && (byteread[t+1]=='A') && (byteread[t+2]=='G'))
|
||||
// {
|
||||
// System.out.println("ID3v1 detected at offset "+t);
|
||||
// throw newBitstreamException(INVALIDFRAME, null);
|
||||
// }
|
||||
//}
|
||||
|
||||
for (int k=0;k<bytesize;k=k+4)
|
||||
{
|
||||
int convert = 0;
|
||||
byte b0 = 0;
|
||||
byte b1 = 0;
|
||||
byte b2 = 0;
|
||||
byte b3 = 0;
|
||||
b0 = byteread[k];
|
||||
if (k+1<bytesize) b1 = byteread[k+1];
|
||||
if (k+2<bytesize) b2 = byteread[k+2];
|
||||
if (k+3<bytesize) b3 = byteread[k+3];
|
||||
framebuffer[b++] = ((b0 << 24) &0xFF000000) | ((b1 << 16) & 0x00FF0000) | ((b2 << 8) & 0x0000FF00) | (b3 & 0x000000FF);
|
||||
}
|
||||
wordpointer = 0;
|
||||
bitindex = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read bits from buffer into the lower bits of an unsigned int.
|
||||
* The LSB contains the latest read bit of the stream.
|
||||
* (1 <= number_of_bits <= 16)
|
||||
*/
|
||||
public int get_bits(int number_of_bits)
|
||||
{
|
||||
int returnvalue = 0;
|
||||
int sum = bitindex + number_of_bits;
|
||||
|
||||
// E.B
|
||||
// There is a problem here, wordpointer could be -1 ?!
|
||||
if (wordpointer < 0) wordpointer = 0;
|
||||
// E.B : End.
|
||||
|
||||
if (sum <= 32)
|
||||
{
|
||||
// all bits contained in *wordpointer
|
||||
returnvalue = (framebuffer[wordpointer] >>> (32 - sum)) & bitmask[number_of_bits];
|
||||
// returnvalue = (wordpointer[0] >> (32 - sum)) & bitmask[number_of_bits];
|
||||
if ((bitindex += number_of_bits) == 32)
|
||||
{
|
||||
bitindex = 0;
|
||||
wordpointer++; // added by me!
|
||||
}
|
||||
return returnvalue;
|
||||
}
|
||||
|
||||
// E.B : Check that ?
|
||||
//((short[])&returnvalue)[0] = ((short[])wordpointer + 1)[0];
|
||||
//wordpointer++; // Added by me!
|
||||
//((short[])&returnvalue + 1)[0] = ((short[])wordpointer)[0];
|
||||
int Right = (framebuffer[wordpointer] & 0x0000FFFF);
|
||||
wordpointer++;
|
||||
int Left = (framebuffer[wordpointer] & 0xFFFF0000);
|
||||
returnvalue = ((Right << 16) & 0xFFFF0000) | ((Left >>> 16)& 0x0000FFFF);
|
||||
|
||||
returnvalue >>>= 48 - sum; // returnvalue >>= 16 - (number_of_bits - (32 - bitindex))
|
||||
returnvalue &= bitmask[number_of_bits];
|
||||
bitindex = sum - 32;
|
||||
return returnvalue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the word we want to sync the header to.
|
||||
* In Big-Endian byte order
|
||||
*/
|
||||
void set_syncword(int syncword0)
|
||||
{
|
||||
syncword = syncword0 & 0xFFFFFF3F;
|
||||
single_ch_mode = ((syncword0 & 0x000000C0) == 0x000000C0);
|
||||
}
|
||||
/**
|
||||
* Reads the exact number of bytes from the source
|
||||
* input stream into a byte array.
|
||||
*
|
||||
* @param b The byte array to read the specified number
|
||||
* of bytes into.
|
||||
* @param offs The index in the array where the first byte
|
||||
* read should be stored.
|
||||
* @param len the number of bytes to read.
|
||||
*
|
||||
* @exception BitstreamException is thrown if the specified
|
||||
* number of bytes could not be read from the stream.
|
||||
*/
|
||||
private int readFully(byte[] b, int offs, int len)
|
||||
throws BitstreamException
|
||||
{
|
||||
int nRead = 0;
|
||||
try
|
||||
{
|
||||
while (len > 0)
|
||||
{
|
||||
int bytesread = source.read(b, offs, len);
|
||||
if (bytesread == -1)
|
||||
{
|
||||
while (len-->0)
|
||||
{
|
||||
b[offs++] = 0;
|
||||
}
|
||||
break;
|
||||
//throw newBitstreamException(UNEXPECTED_EOF, new EOFException());
|
||||
}
|
||||
nRead = nRead + bytesread;
|
||||
offs += bytesread;
|
||||
len -= bytesread;
|
||||
}
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
throw newBitstreamException(STREAM_ERROR, ex);
|
||||
}
|
||||
return nRead;
|
||||
}
|
||||
|
||||
/**
|
||||
* Similar to readFully, but doesn't throw exception when
|
||||
* EOF is reached.
|
||||
*/
|
||||
private int readBytes(byte[] b, int offs, int len)
|
||||
throws BitstreamException
|
||||
{
|
||||
int totalBytesRead = 0;
|
||||
try
|
||||
{
|
||||
while (len > 0)
|
||||
{
|
||||
int bytesread = source.read(b, offs, len);
|
||||
if (bytesread == -1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
totalBytesRead += bytesread;
|
||||
offs += bytesread;
|
||||
len -= bytesread;
|
||||
}
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
throw newBitstreamException(STREAM_ERROR, ex);
|
||||
}
|
||||
return totalBytesRead;
|
||||
}
|
||||
}
|
||||
72
src/lwjgl/java/javazoom/jl/decoder/BitstreamErrors.java
Normal file
72
src/lwjgl/java/javazoom/jl/decoder/BitstreamErrors.java
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* 11/19/04 1.0 moved to LGPL.
|
||||
* 11/17/04 INVALIDFRAME code added. javalayer@javazoom.net
|
||||
* 12/12/99 Initial version. mdm@techie.com
|
||||
*-----------------------------------------------------------------------
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library General Public License as published
|
||||
* by the Free Software Foundation; either version 2 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 Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
package javazoom.jl.decoder;
|
||||
|
||||
/**
|
||||
* This interface describes all error codes that can be thrown
|
||||
* in <code>BistreamException</code>s.
|
||||
*
|
||||
* @see BitstreamException
|
||||
*
|
||||
* @author MDM 12/12/99
|
||||
* @since 0.0.6
|
||||
*/
|
||||
|
||||
public interface BitstreamErrors extends JavaLayerErrors
|
||||
{
|
||||
|
||||
/**
|
||||
* An undetermined error occurred.
|
||||
*/
|
||||
public static final int UNKNOWN_ERROR = BITSTREAM_ERROR + 0;
|
||||
|
||||
/**
|
||||
* The header describes an unknown sample rate.
|
||||
*/
|
||||
public static final int UNKNOWN_SAMPLE_RATE = BITSTREAM_ERROR + 1;
|
||||
|
||||
/**
|
||||
* A problem occurred reading from the stream.
|
||||
*/
|
||||
public static final int STREAM_ERROR = BITSTREAM_ERROR + 2;
|
||||
|
||||
/**
|
||||
* The end of the stream was reached prematurely.
|
||||
*/
|
||||
public static final int UNEXPECTED_EOF = BITSTREAM_ERROR + 3;
|
||||
|
||||
/**
|
||||
* The end of the stream was reached.
|
||||
*/
|
||||
public static final int STREAM_EOF = BITSTREAM_ERROR + 4;
|
||||
|
||||
/**
|
||||
* Frame data are missing.
|
||||
*/
|
||||
public static final int INVALIDFRAME = BITSTREAM_ERROR + 5;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public static final int BITSTREAM_LAST = 0x1ff;
|
||||
|
||||
}
|
||||
71
src/lwjgl/java/javazoom/jl/decoder/BitstreamException.java
Normal file
71
src/lwjgl/java/javazoom/jl/decoder/BitstreamException.java
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* 11/19/04 1.0 moved to LGPL.
|
||||
* 12/12/99 Initial version. mdm@techie.com
|
||||
*-----------------------------------------------------------------------
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library General Public License as published
|
||||
* by the Free Software Foundation; either version 2 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 Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
package javazoom.jl.decoder;
|
||||
|
||||
/**
|
||||
* Instances of <code>BitstreamException</code> are thrown
|
||||
* when operations on a <code>Bitstream</code> fail.
|
||||
* <p>
|
||||
* The exception provides details of the exception condition
|
||||
* in two ways:
|
||||
* <ol><li>
|
||||
* as an error-code describing the nature of the error
|
||||
* </li><br></br><li>
|
||||
* as the <code>Throwable</code> instance, if any, that was thrown
|
||||
* indicating that an exceptional condition has occurred.
|
||||
* </li></ol></p>
|
||||
*
|
||||
* @since 0.0.6
|
||||
* @author MDM 12/12/99
|
||||
*/
|
||||
|
||||
public class BitstreamException extends JavaLayerException
|
||||
implements BitstreamErrors
|
||||
{
|
||||
private int errorcode = UNKNOWN_ERROR;
|
||||
|
||||
public BitstreamException(String msg, Throwable t)
|
||||
{
|
||||
super(msg, t);
|
||||
}
|
||||
|
||||
public BitstreamException(int errorcode, Throwable t)
|
||||
{
|
||||
this(getErrorString(errorcode), t);
|
||||
this.errorcode = errorcode;
|
||||
}
|
||||
|
||||
public int getErrorCode()
|
||||
{
|
||||
return errorcode;
|
||||
}
|
||||
|
||||
|
||||
public static String getErrorString(int errorcode)
|
||||
{
|
||||
// REVIEW: use resource bundle to map error codes
|
||||
// to locale-sensitive strings.
|
||||
|
||||
return "Bitstream errorcode "+Integer.toHexString(errorcode);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
57
src/lwjgl/java/javazoom/jl/decoder/Control.java
Normal file
57
src/lwjgl/java/javazoom/jl/decoder/Control.java
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 11/19/04 1.0 moved to LGPL.
|
||||
*-----------------------------------------------------------------------
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library General Public License as published
|
||||
* by the Free Software Foundation; either version 2 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 Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
package javazoom.jl.decoder;
|
||||
|
||||
/**
|
||||
* Work in progress.
|
||||
*/
|
||||
|
||||
public interface Control
|
||||
{
|
||||
|
||||
/**
|
||||
* Starts playback of the media presented by this control.
|
||||
*/
|
||||
public void start();
|
||||
|
||||
/**
|
||||
* Stops playback of the media presented by this control.
|
||||
*/
|
||||
public void stop();
|
||||
|
||||
public boolean isPlaying();
|
||||
|
||||
public void pause();
|
||||
|
||||
|
||||
public boolean isRandomAccess();
|
||||
|
||||
/**
|
||||
* Retrieves the current position.
|
||||
*/
|
||||
public double getPosition();
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public void setPosition(double d);
|
||||
|
||||
|
||||
}
|
||||
70
src/lwjgl/java/javazoom/jl/decoder/Crc16.java
Normal file
70
src/lwjgl/java/javazoom/jl/decoder/Crc16.java
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* 11/19/04 : 1.0 moved to LGPL.
|
||||
*
|
||||
* 02/12/99 : Java Conversion by E.B , javalayer@javazoom.net
|
||||
*
|
||||
* @(#) crc.h 1.5, last edit: 6/15/94 16:55:32
|
||||
* @(#) Copyright (C) 1993, 1994 Tobias Bading (bading@cs.tu-berlin.de)
|
||||
* @(#) Berlin University of Technology
|
||||
*-----------------------------------------------------------------------
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library General Public License as published
|
||||
* by the Free Software Foundation; either version 2 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 Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
package javazoom.jl.decoder;
|
||||
|
||||
/**
|
||||
* 16-Bit CRC checksum
|
||||
*/
|
||||
public final class Crc16
|
||||
{
|
||||
private static short polynomial=(short)0x8005;
|
||||
private short crc;
|
||||
|
||||
/**
|
||||
* Dummy Constructor
|
||||
*/
|
||||
public Crc16()
|
||||
{
|
||||
crc = (short) 0xFFFF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Feed a bitstring to the CRC calculation (0 < length <= 32).
|
||||
*/
|
||||
public void add_bits (int bitstring, int length)
|
||||
{
|
||||
int bitmask = 1 << (length - 1);
|
||||
do
|
||||
if (((crc & 0x8000) == 0) ^ ((bitstring & bitmask) == 0 ))
|
||||
{
|
||||
crc <<= 1;
|
||||
crc ^= polynomial;
|
||||
}
|
||||
else
|
||||
crc <<= 1;
|
||||
while ((bitmask >>>= 1) != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the calculated checksum.
|
||||
* Erase it for next calls to add_bits().
|
||||
*/
|
||||
public short checksum()
|
||||
{
|
||||
short sum = crc;
|
||||
crc = (short) 0xFFFF;
|
||||
return sum;
|
||||
}
|
||||
}
|
||||
356
src/lwjgl/java/javazoom/jl/decoder/Decoder.java
Normal file
356
src/lwjgl/java/javazoom/jl/decoder/Decoder.java
Normal file
@@ -0,0 +1,356 @@
|
||||
/*
|
||||
* 11/19/04 1.0 moved to LGPL.
|
||||
* 01/12/99 Initial version. mdm@techie.com
|
||||
*-----------------------------------------------------------------------
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library General Public License as published
|
||||
* by the Free Software Foundation; either version 2 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 Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
package javazoom.jl.decoder;
|
||||
|
||||
/**
|
||||
* The <code>Decoder</code> class encapsulates the details of
|
||||
* decoding an MPEG audio frame.
|
||||
*
|
||||
* @author MDM
|
||||
* @version 0.0.7 12/12/99
|
||||
* @since 0.0.5
|
||||
*/
|
||||
public class Decoder implements DecoderErrors
|
||||
{
|
||||
private static final Params DEFAULT_PARAMS = new Params();
|
||||
|
||||
/**
|
||||
* The Bitstream from which the MPEG audio frames are read.
|
||||
*/
|
||||
//private Bitstream stream;
|
||||
|
||||
/**
|
||||
* The Obuffer instance that will receive the decoded
|
||||
* PCM samples.
|
||||
*/
|
||||
private Obuffer output;
|
||||
|
||||
/**
|
||||
* Synthesis filter for the left channel.
|
||||
*/
|
||||
private SynthesisFilter filter1;
|
||||
|
||||
/**
|
||||
* Synthesis filter for the right channel.
|
||||
*/
|
||||
private SynthesisFilter filter2;
|
||||
|
||||
/**
|
||||
* The decoder used to decode layer III frames.
|
||||
*/
|
||||
private LayerIIIDecoder l3decoder;
|
||||
private LayerIIDecoder l2decoder;
|
||||
private LayerIDecoder l1decoder;
|
||||
|
||||
private int outputFrequency;
|
||||
private int outputChannels;
|
||||
|
||||
private Equalizer equalizer = new Equalizer();
|
||||
|
||||
private Params params;
|
||||
|
||||
private boolean initialized;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new <code>Decoder</code> instance with default
|
||||
* parameters.
|
||||
*/
|
||||
|
||||
public Decoder()
|
||||
{
|
||||
this(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>Decoder</code> instance with default
|
||||
* parameters.
|
||||
*
|
||||
* @param params The <code>Params</code> instance that describes
|
||||
* the customizable aspects of the decoder.
|
||||
*/
|
||||
public Decoder(Params params0)
|
||||
{
|
||||
if (params0==null)
|
||||
params0 = DEFAULT_PARAMS;
|
||||
|
||||
params = params0;
|
||||
|
||||
Equalizer eq = params.getInitialEqualizerSettings();
|
||||
if (eq!=null)
|
||||
{
|
||||
equalizer.setFrom(eq);
|
||||
}
|
||||
}
|
||||
|
||||
public static Params getDefaultParams() throws CloneNotSupportedException
|
||||
{
|
||||
return (Params)DEFAULT_PARAMS.clone();
|
||||
}
|
||||
|
||||
public void setEqualizer(Equalizer eq)
|
||||
{
|
||||
if (eq==null)
|
||||
eq = Equalizer.PASS_THRU_EQ;
|
||||
|
||||
equalizer.setFrom(eq);
|
||||
|
||||
float[] factors = equalizer.getBandFactors();
|
||||
|
||||
if (filter1!=null)
|
||||
filter1.setEQ(factors);
|
||||
|
||||
if (filter2!=null)
|
||||
filter2.setEQ(factors);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes one frame from an MPEG audio bitstream.
|
||||
*
|
||||
* @param header The header describing the frame to decode.
|
||||
* @param bitstream The bitstream that provides the bits for te body of the frame.
|
||||
*
|
||||
* @return A SampleBuffer containing the decoded samples.
|
||||
*/
|
||||
public Obuffer decodeFrame(Header header, Bitstream stream)
|
||||
throws DecoderException
|
||||
{
|
||||
if (!initialized)
|
||||
{
|
||||
initialize(header);
|
||||
}
|
||||
|
||||
int layer = header.layer();
|
||||
|
||||
output.clear_buffer();
|
||||
|
||||
FrameDecoder decoder = retrieveDecoder(header, stream, layer);
|
||||
|
||||
decoder.decodeFrame();
|
||||
|
||||
output.write_buffer(1);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the output buffer. This will take effect the next time
|
||||
* decodeFrame() is called.
|
||||
*/
|
||||
public void setOutputBuffer(Obuffer out)
|
||||
{
|
||||
output = out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the sample frequency of the PCM samples output
|
||||
* by this decoder. This typically corresponds to the sample
|
||||
* rate encoded in the MPEG audio stream.
|
||||
*
|
||||
* @param the sample rate (in Hz) of the samples written to the
|
||||
* output buffer when decoding.
|
||||
*/
|
||||
public int getOutputFrequency()
|
||||
{
|
||||
return outputFrequency;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the number of channels of PCM samples output by
|
||||
* this decoder. This usually corresponds to the number of
|
||||
* channels in the MPEG audio stream, although it may differ.
|
||||
*
|
||||
* @return The number of output channels in the decoded samples: 1
|
||||
* for mono, or 2 for stereo.
|
||||
*
|
||||
*/
|
||||
public int getOutputChannels()
|
||||
{
|
||||
return outputChannels;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the maximum number of samples that will be written to
|
||||
* the output buffer when one frame is decoded. This can be used to
|
||||
* help calculate the size of other buffers whose size is based upon
|
||||
* the number of samples written to the output buffer. NB: this is
|
||||
* an upper bound and fewer samples may actually be written, depending
|
||||
* upon the sample rate and number of channels.
|
||||
*
|
||||
* @return The maximum number of samples that are written to the
|
||||
* output buffer when decoding a single frame of MPEG audio.
|
||||
*/
|
||||
public int getOutputBlockSize()
|
||||
{
|
||||
return Obuffer.OBUFFERSIZE;
|
||||
}
|
||||
|
||||
|
||||
protected DecoderException newDecoderException(int errorcode)
|
||||
{
|
||||
return new DecoderException(errorcode, null);
|
||||
}
|
||||
|
||||
protected DecoderException newDecoderException(int errorcode, Throwable throwable)
|
||||
{
|
||||
return new DecoderException(errorcode, throwable);
|
||||
}
|
||||
|
||||
protected FrameDecoder retrieveDecoder(Header header, Bitstream stream, int layer)
|
||||
throws DecoderException
|
||||
{
|
||||
FrameDecoder decoder = null;
|
||||
|
||||
// REVIEW: allow channel output selection type
|
||||
// (LEFT, RIGHT, BOTH, DOWNMIX)
|
||||
switch (layer)
|
||||
{
|
||||
case 3:
|
||||
if (l3decoder==null)
|
||||
{
|
||||
l3decoder = new LayerIIIDecoder(stream,
|
||||
header, filter1, filter2,
|
||||
output, OutputChannels.BOTH_CHANNELS);
|
||||
}
|
||||
|
||||
decoder = l3decoder;
|
||||
break;
|
||||
case 2:
|
||||
if (l2decoder==null)
|
||||
{
|
||||
l2decoder = new LayerIIDecoder();
|
||||
l2decoder.create(stream,
|
||||
header, filter1, filter2,
|
||||
output, OutputChannels.BOTH_CHANNELS);
|
||||
}
|
||||
decoder = l2decoder;
|
||||
break;
|
||||
case 1:
|
||||
if (l1decoder==null)
|
||||
{
|
||||
l1decoder = new LayerIDecoder();
|
||||
l1decoder.create(stream,
|
||||
header, filter1, filter2,
|
||||
output, OutputChannels.BOTH_CHANNELS);
|
||||
}
|
||||
decoder = l1decoder;
|
||||
break;
|
||||
}
|
||||
|
||||
if (decoder==null)
|
||||
{
|
||||
throw newDecoderException(UNSUPPORTED_LAYER, null);
|
||||
}
|
||||
|
||||
return decoder;
|
||||
}
|
||||
|
||||
private void initialize(Header header)
|
||||
throws DecoderException
|
||||
{
|
||||
|
||||
// REVIEW: allow customizable scale factor
|
||||
float scalefactor = 32700.0f;
|
||||
|
||||
int mode = header.mode();
|
||||
int layer = header.layer();
|
||||
int channels = mode==Header.SINGLE_CHANNEL ? 1 : 2;
|
||||
|
||||
|
||||
// set up output buffer if not set up by client.
|
||||
if (output==null)
|
||||
output = new SampleBuffer(header.frequency(), channels);
|
||||
|
||||
float[] factors = equalizer.getBandFactors();
|
||||
filter1 = new SynthesisFilter(0, scalefactor, factors);
|
||||
|
||||
// REVIEW: allow mono output for stereo
|
||||
if (channels==2)
|
||||
filter2 = new SynthesisFilter(1, scalefactor, factors);
|
||||
|
||||
outputChannels = channels;
|
||||
outputFrequency = header.frequency();
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* The <code>Params</code> class presents the customizable
|
||||
* aspects of the decoder.
|
||||
* <p>
|
||||
* Instances of this class are not thread safe.
|
||||
*/
|
||||
public static class Params implements Cloneable
|
||||
{
|
||||
private OutputChannels outputChannels = OutputChannels.BOTH;
|
||||
|
||||
private Equalizer equalizer = new Equalizer();
|
||||
|
||||
public Params()
|
||||
{
|
||||
}
|
||||
|
||||
public Object clone() throws CloneNotSupportedException {
|
||||
try
|
||||
{
|
||||
return super.clone();
|
||||
}
|
||||
catch (CloneNotSupportedException ex)
|
||||
{
|
||||
throw new InternalError(this+": "+ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void setOutputChannels(OutputChannels out)
|
||||
{
|
||||
if (out==null)
|
||||
throw new NullPointerException("out");
|
||||
|
||||
outputChannels = out;
|
||||
}
|
||||
|
||||
public OutputChannels getOutputChannels()
|
||||
{
|
||||
return outputChannels;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the equalizer settings that the decoder's equalizer
|
||||
* will be initialized from.
|
||||
* <p>
|
||||
* The <code>Equalizer</code> instance returned
|
||||
* cannot be changed in real time to affect the
|
||||
* decoder output as it is used only to initialize the decoders
|
||||
* EQ settings. To affect the decoder's output in realtime,
|
||||
* use the Equalizer returned from the getEqualizer() method on
|
||||
* the decoder.
|
||||
*
|
||||
* @return The <code>Equalizer</code> used to initialize the
|
||||
* EQ settings of the decoder.
|
||||
*/
|
||||
public Equalizer getInitialEqualizerSettings()
|
||||
{
|
||||
return equalizer;
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
45
src/lwjgl/java/javazoom/jl/decoder/DecoderErrors.java
Normal file
45
src/lwjgl/java/javazoom/jl/decoder/DecoderErrors.java
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 09/26/08 throw exception on subbband alloc error: Christopher G. Jennings (cjennings@acm.org)
|
||||
* 11/19/04 1.0 moved to LGPL.
|
||||
* 01/12/99 Initial version. mdm@techie.com
|
||||
*-----------------------------------------------------------------------
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library General Public License as published
|
||||
* by the Free Software Foundation; either version 2 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 Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
package javazoom.jl.decoder;
|
||||
|
||||
/**
|
||||
* This interface provides constants describing the error
|
||||
* codes used by the Decoder to indicate errors.
|
||||
*
|
||||
* @author MDM
|
||||
*/
|
||||
public interface DecoderErrors extends JavaLayerErrors
|
||||
{
|
||||
|
||||
public static final int UNKNOWN_ERROR = DECODER_ERROR + 0;
|
||||
|
||||
/**
|
||||
* Layer not supported by the decoder.
|
||||
*/
|
||||
public static final int UNSUPPORTED_LAYER = DECODER_ERROR + 1;
|
||||
|
||||
/**
|
||||
* Illegal allocation in subband layer. Indicates a corrupt stream.
|
||||
*/
|
||||
public static final int ILLEGAL_SUBBAND_ALLOCATION = DECODER_ERROR + 2;
|
||||
|
||||
}
|
||||
59
src/lwjgl/java/javazoom/jl/decoder/DecoderException.java
Normal file
59
src/lwjgl/java/javazoom/jl/decoder/DecoderException.java
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 11/19/04 1.0 moved to LGPL.
|
||||
* 01/12/99 Initial version. mdm@techie.com
|
||||
*-----------------------------------------------------------------------
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library General Public License as published
|
||||
* by the Free Software Foundation; either version 2 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 Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
package javazoom.jl.decoder;
|
||||
|
||||
/**
|
||||
* The <code>DecoderException</code> represents the class of
|
||||
* errors that can occur when decoding MPEG audio.
|
||||
*
|
||||
* @author MDM
|
||||
*/
|
||||
public class DecoderException extends JavaLayerException
|
||||
implements DecoderErrors
|
||||
{
|
||||
private int errorcode = UNKNOWN_ERROR;
|
||||
|
||||
public DecoderException(String msg, Throwable t)
|
||||
{
|
||||
super(msg, t);
|
||||
}
|
||||
|
||||
public DecoderException(int errorcode, Throwable t)
|
||||
{
|
||||
this(getErrorString(errorcode), t);
|
||||
this.errorcode = errorcode;
|
||||
}
|
||||
|
||||
public int getErrorCode()
|
||||
{
|
||||
return errorcode;
|
||||
}
|
||||
|
||||
|
||||
public static String getErrorString(int errorcode)
|
||||
{
|
||||
// REVIEW: use resource file to map error codes
|
||||
// to locale-sensitive strings.
|
||||
|
||||
return "Decoder errorcode "+Integer.toHexString(errorcode);
|
||||
}
|
||||
}
|
||||
|
||||
227
src/lwjgl/java/javazoom/jl/decoder/Equalizer.java
Normal file
227
src/lwjgl/java/javazoom/jl/decoder/Equalizer.java
Normal file
@@ -0,0 +1,227 @@
|
||||
/*
|
||||
* 11/19/04 1.0 moved to LGPL.
|
||||
* 12/12/99 Initial version. mdm@techie.com
|
||||
*-----------------------------------------------------------------------
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library General Public License as published
|
||||
* by the Free Software Foundation; either version 2 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 Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
package javazoom.jl.decoder;
|
||||
|
||||
/**
|
||||
* The <code>Equalizer</code> class can be used to specify
|
||||
* equalization settings for the MPEG audio decoder.
|
||||
* <p>
|
||||
* The equalizer consists of 32 band-pass filters.
|
||||
* Each band of the equalizer can take on a fractional value between
|
||||
* -1.0 and +1.0.
|
||||
* At -1.0, the input signal is attenuated by 6dB, at +1.0 the signal is
|
||||
* amplified by 6dB.
|
||||
*
|
||||
* @see Decoder
|
||||
*
|
||||
* @author MDM
|
||||
*/
|
||||
public final class Equalizer
|
||||
{
|
||||
/**
|
||||
* Equalizer setting to denote that a given band will not be
|
||||
* present in the output signal.
|
||||
*/
|
||||
public static final float BAND_NOT_PRESENT = Float.NEGATIVE_INFINITY;
|
||||
|
||||
public static final Equalizer PASS_THRU_EQ = new Equalizer();
|
||||
|
||||
private static final int BANDS = 32;
|
||||
|
||||
private final float[] settings = new float[BANDS];
|
||||
|
||||
/**
|
||||
* Creates a new <code>Equalizer</code> instance.
|
||||
*/
|
||||
public Equalizer()
|
||||
{
|
||||
}
|
||||
|
||||
// private Equalizer(float b1, float b2, float b3, float b4, float b5,
|
||||
// float b6, float b7, float b8, float b9, float b10, float b11,
|
||||
// float b12, float b13, float b14, float b15, float b16,
|
||||
// float b17, float b18, float b19, float b20);
|
||||
|
||||
public Equalizer(float[] settings)
|
||||
{
|
||||
setFrom(settings);
|
||||
}
|
||||
|
||||
public Equalizer(EQFunction eq)
|
||||
{
|
||||
setFrom(eq);
|
||||
}
|
||||
|
||||
public void setFrom(float[] eq)
|
||||
{
|
||||
reset();
|
||||
int max = (eq.length > BANDS) ? BANDS : eq.length;
|
||||
|
||||
for (int i=0; i<max; i++)
|
||||
{
|
||||
settings[i] = limit(eq[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public void setFrom(EQFunction eq)
|
||||
{
|
||||
reset();
|
||||
int max = BANDS;
|
||||
|
||||
for (int i=0; i<max; i++)
|
||||
{
|
||||
settings[i] = limit(eq.getBand(i));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the bands of this equalizer to the value the bands of
|
||||
* another equalizer. Bands that are not present in both equalizers are ignored.
|
||||
*/
|
||||
public void setFrom(Equalizer eq)
|
||||
{
|
||||
if (eq!=this)
|
||||
{
|
||||
setFrom(eq.settings);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Sets all bands to 0.0
|
||||
*/
|
||||
public void reset()
|
||||
{
|
||||
for (int i=0; i<BANDS; i++)
|
||||
{
|
||||
settings[i] = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the number of bands present in this equalizer.
|
||||
*/
|
||||
public int getBandCount()
|
||||
{
|
||||
return settings.length;
|
||||
}
|
||||
|
||||
public float setBand(int band, float neweq)
|
||||
{
|
||||
float eq = 0.0f;
|
||||
|
||||
if ((band>=0) && (band<BANDS))
|
||||
{
|
||||
eq = settings[band];
|
||||
settings[band] = limit(neweq);
|
||||
}
|
||||
|
||||
return eq;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the EQ setting for a given band.
|
||||
*/
|
||||
public float getBand(int band)
|
||||
{
|
||||
float eq = 0.0f;
|
||||
|
||||
if ((band>=0) && (band<BANDS))
|
||||
{
|
||||
eq = settings[band];
|
||||
}
|
||||
|
||||
return eq;
|
||||
}
|
||||
|
||||
private float limit(float eq)
|
||||
{
|
||||
if (eq==BAND_NOT_PRESENT)
|
||||
return eq;
|
||||
if (eq > 1.0f)
|
||||
return 1.0f;
|
||||
if (eq < -1.0f)
|
||||
return -1.0f;
|
||||
|
||||
return eq;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves an array of floats whose values represent a
|
||||
* scaling factor that can be applied to linear samples
|
||||
* in each band to provide the equalization represented by
|
||||
* this instance.
|
||||
*
|
||||
* @return an array of factors that can be applied to the
|
||||
* subbands.
|
||||
*/
|
||||
float[] getBandFactors()
|
||||
{
|
||||
float[] factors = new float[BANDS];
|
||||
for (int i=0, maxCount=BANDS; i<maxCount; i++)
|
||||
{
|
||||
factors[i] = getBandFactor(settings[i]);
|
||||
}
|
||||
|
||||
return factors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an equalizer band setting to a sample factor.
|
||||
* The factor is determined by the function f = 2^n where
|
||||
* n is the equalizer band setting in the range [-1.0,1.0].
|
||||
*
|
||||
*/
|
||||
float getBandFactor(float eq)
|
||||
{
|
||||
if (eq==BAND_NOT_PRESENT)
|
||||
return 0.0f;
|
||||
|
||||
float f = (float)Math.pow(2.0, eq);
|
||||
return f;
|
||||
}
|
||||
|
||||
|
||||
public abstract static class EQFunction
|
||||
{
|
||||
/**
|
||||
* Returns the setting of a band in the equalizer.
|
||||
*
|
||||
* @param band The index of the band to retrieve the setting
|
||||
* for.
|
||||
*
|
||||
* @return the setting of the specified band. This is a value between
|
||||
* -1 and +1.
|
||||
*/
|
||||
public float getBand(int band)
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
39
src/lwjgl/java/javazoom/jl/decoder/FrameDecoder.java
Normal file
39
src/lwjgl/java/javazoom/jl/decoder/FrameDecoder.java
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 09/26/08 throw exception on subbband alloc error: Christopher G. Jennings (cjennings@acm.org)
|
||||
* 11/19/04 1.0 moved to LGPL.
|
||||
* 12/12/99 Initial version. mdm@techie.com
|
||||
*-----------------------------------------------------------------------
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library General Public License as published
|
||||
* by the Free Software Foundation; either version 2 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 Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
package javazoom.jl.decoder;
|
||||
|
||||
/**
|
||||
* Implementations of FrameDecoder are responsible for decoding
|
||||
* an MPEG audio frame.
|
||||
*
|
||||
*/
|
||||
//REVIEW: the interface currently is too thin. There should be
|
||||
// methods to specify the output buffer, the synthesis filters and
|
||||
// possibly other objects used by the decoder.
|
||||
public interface FrameDecoder
|
||||
{
|
||||
/**
|
||||
* Decodes one frame of MPEG audio.
|
||||
*/
|
||||
public void decodeFrame() throws DecoderException;
|
||||
|
||||
}
|
||||
778
src/lwjgl/java/javazoom/jl/decoder/Header.java
Normal file
778
src/lwjgl/java/javazoom/jl/decoder/Header.java
Normal file
@@ -0,0 +1,778 @@
|
||||
/*
|
||||
* 11/19/04 : 1.0 moved to LGPL.
|
||||
* VBRI header support added, E.B javalayer@javazoom.net
|
||||
*
|
||||
* 12/04/03 : VBR (XING) header support added, E.B javalayer@javazoom.net
|
||||
*
|
||||
* 02/13/99 : Java Conversion by JavaZOOM , E.B javalayer@javazoom.net
|
||||
*
|
||||
* Declarations for MPEG header class
|
||||
* A few layer III, MPEG-2 LSF, and seeking modifications made by Jeff Tsay.
|
||||
* Last modified : 04/19/97
|
||||
*
|
||||
* @(#) header.h 1.7, last edit: 6/15/94 16:55:33
|
||||
* @(#) Copyright (C) 1993, 1994 Tobias Bading (bading@cs.tu-berlin.de)
|
||||
* @(#) Berlin University of Technology
|
||||
*-----------------------------------------------------------------------
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library General Public License as published
|
||||
* by the Free Software Foundation; either version 2 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 Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
package javazoom.jl.decoder;
|
||||
|
||||
/**
|
||||
* Class for extracting information from a frame header.
|
||||
*/
|
||||
public final class Header
|
||||
{
|
||||
public static final int[][] frequencies =
|
||||
{{22050, 24000, 16000, 1},
|
||||
{44100, 48000, 32000, 1},
|
||||
{11025, 12000, 8000, 1}}; // SZD: MPEG25
|
||||
|
||||
/**
|
||||
* Constant for MPEG-2 LSF version
|
||||
*/
|
||||
public static final int MPEG2_LSF = 0;
|
||||
public static final int MPEG25_LSF = 2; // SZD
|
||||
|
||||
/**
|
||||
* Constant for MPEG-1 version
|
||||
*/
|
||||
public static final int MPEG1 = 1;
|
||||
|
||||
public static final int STEREO = 0;
|
||||
public static final int JOINT_STEREO = 1;
|
||||
public static final int DUAL_CHANNEL = 2;
|
||||
public static final int SINGLE_CHANNEL = 3;
|
||||
public static final int FOURTYFOUR_POINT_ONE = 0;
|
||||
public static final int FOURTYEIGHT=1;
|
||||
public static final int THIRTYTWO=2;
|
||||
|
||||
private int h_layer, h_protection_bit, h_bitrate_index,
|
||||
h_padding_bit, h_mode_extension;
|
||||
private int h_version;
|
||||
private int h_mode;
|
||||
private int h_sample_frequency;
|
||||
private int h_number_of_subbands, h_intensity_stereo_bound;
|
||||
private boolean h_copyright, h_original;
|
||||
// VBR support added by E.B
|
||||
private double[] h_vbr_time_per_frame = {-1, 384, 1152, 1152};
|
||||
private boolean h_vbr;
|
||||
private int h_vbr_frames;
|
||||
private int h_vbr_scale;
|
||||
private int h_vbr_bytes;
|
||||
private byte[] h_vbr_toc;
|
||||
|
||||
private byte syncmode = Bitstream.INITIAL_SYNC;
|
||||
private Crc16 crc;
|
||||
|
||||
public short checksum;
|
||||
public int framesize;
|
||||
public int nSlots;
|
||||
|
||||
private int _headerstring = -1; // E.B
|
||||
|
||||
Header()
|
||||
{
|
||||
}
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder buffer = new StringBuilder(200);
|
||||
buffer.append("Layer ");
|
||||
buffer.append(layer_string());
|
||||
buffer.append(" frame ");
|
||||
buffer.append(mode_string());
|
||||
buffer.append(' ');
|
||||
buffer.append(version_string());
|
||||
if (!checksums())
|
||||
buffer.append(" no");
|
||||
buffer.append(" checksums");
|
||||
buffer.append(' ');
|
||||
buffer.append(sample_frequency_string());
|
||||
buffer.append(',');
|
||||
buffer.append(' ');
|
||||
buffer.append(bitrate_string());
|
||||
|
||||
String s = buffer.toString();
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a 32-bit header from the bitstream.
|
||||
*/
|
||||
void read_header(Bitstream stream, Crc16[] crcp) throws BitstreamException
|
||||
{
|
||||
int headerstring;
|
||||
int channel_bitrate;
|
||||
boolean sync = false;
|
||||
do
|
||||
{
|
||||
headerstring = stream.syncHeader(syncmode);
|
||||
_headerstring = headerstring; // E.B
|
||||
if (syncmode == Bitstream.INITIAL_SYNC)
|
||||
{
|
||||
h_version = ((headerstring >>> 19) & 1);
|
||||
if (((headerstring >>> 20) & 1) == 0) // SZD: MPEG2.5 detection
|
||||
if (h_version == MPEG2_LSF)
|
||||
h_version = MPEG25_LSF;
|
||||
else
|
||||
throw stream.newBitstreamException(Bitstream.UNKNOWN_ERROR);
|
||||
if ((h_sample_frequency = ((headerstring >>> 10) & 3)) == 3)
|
||||
{
|
||||
throw stream.newBitstreamException(Bitstream.UNKNOWN_ERROR);
|
||||
}
|
||||
}
|
||||
h_layer = 4 - (headerstring >>> 17) & 3;
|
||||
h_protection_bit = (headerstring >>> 16) & 1;
|
||||
h_bitrate_index = (headerstring >>> 12) & 0xF;
|
||||
h_padding_bit = (headerstring >>> 9) & 1;
|
||||
h_mode = ((headerstring >>> 6) & 3);
|
||||
h_mode_extension = (headerstring >>> 4) & 3;
|
||||
if (h_mode == JOINT_STEREO)
|
||||
h_intensity_stereo_bound = (h_mode_extension << 2) + 4;
|
||||
else
|
||||
h_intensity_stereo_bound = 0; // should never be used
|
||||
if (((headerstring >>> 3) & 1) == 1)
|
||||
h_copyright = true;
|
||||
if (((headerstring >>> 2) & 1) == 1)
|
||||
h_original = true;
|
||||
// calculate number of subbands:
|
||||
if (h_layer == 1)
|
||||
h_number_of_subbands = 32;
|
||||
else
|
||||
{
|
||||
channel_bitrate = h_bitrate_index;
|
||||
// calculate bitrate per channel:
|
||||
if (h_mode != SINGLE_CHANNEL)
|
||||
if (channel_bitrate == 4)
|
||||
channel_bitrate = 1;
|
||||
else
|
||||
channel_bitrate -= 4;
|
||||
if ((channel_bitrate == 1) || (channel_bitrate == 2))
|
||||
if (h_sample_frequency == THIRTYTWO)
|
||||
h_number_of_subbands = 12;
|
||||
else
|
||||
h_number_of_subbands = 8;
|
||||
else if ((h_sample_frequency == FOURTYEIGHT) || ((channel_bitrate >= 3) && (channel_bitrate <= 5)))
|
||||
h_number_of_subbands = 27;
|
||||
else
|
||||
h_number_of_subbands = 30;
|
||||
}
|
||||
if (h_intensity_stereo_bound > h_number_of_subbands)
|
||||
h_intensity_stereo_bound = h_number_of_subbands;
|
||||
// calculate framesize and nSlots
|
||||
calculate_framesize();
|
||||
// read framedata:
|
||||
int framesizeloaded = stream.read_frame_data(framesize);
|
||||
if ((framesize >=0) && (framesizeloaded != framesize))
|
||||
{
|
||||
// Data loaded does not match to expected framesize,
|
||||
// it might be an ID3v1 TAG. (Fix 11/17/04).
|
||||
throw stream.newBitstreamException(Bitstream.INVALIDFRAME);
|
||||
}
|
||||
if (stream.isSyncCurrentPosition(syncmode))
|
||||
{
|
||||
if (syncmode == Bitstream.INITIAL_SYNC)
|
||||
{
|
||||
syncmode = Bitstream.STRICT_SYNC;
|
||||
stream.set_syncword(headerstring & 0xFFF80CC0);
|
||||
}
|
||||
sync = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
stream.unreadFrame();
|
||||
}
|
||||
}
|
||||
while (!sync);
|
||||
stream.parse_frame();
|
||||
if (h_protection_bit == 0)
|
||||
{
|
||||
// frame contains a crc checksum
|
||||
checksum = (short) stream.get_bits(16);
|
||||
if (crc == null)
|
||||
crc = new Crc16();
|
||||
crc.add_bits(headerstring, 16);
|
||||
crcp[0] = crc;
|
||||
}
|
||||
else
|
||||
crcp[0] = null;
|
||||
if (h_sample_frequency == FOURTYFOUR_POINT_ONE)
|
||||
{
|
||||
/*
|
||||
if (offset == null)
|
||||
{
|
||||
int max = max_number_of_frames(stream);
|
||||
offset = new int[max];
|
||||
for(int i=0; i<max; i++) offset[i] = 0;
|
||||
}
|
||||
// E.B : Investigate more
|
||||
int cf = stream.current_frame();
|
||||
int lf = stream.last_frame();
|
||||
if ((cf > 0) && (cf == lf))
|
||||
{
|
||||
offset[cf] = offset[cf-1] + h_padding_bit;
|
||||
}
|
||||
else
|
||||
{
|
||||
offset[0] = h_padding_bit;
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse frame to extract optional VBR frame.
|
||||
*
|
||||
* @param firstframe
|
||||
* @author E.B (javalayer@javazoom.net)
|
||||
*/
|
||||
void parseVBR(byte[] firstframe) throws BitstreamException
|
||||
{
|
||||
// Trying Xing header.
|
||||
String xing = "Xing";
|
||||
byte tmp[] = new byte[4];
|
||||
int offset = 0;
|
||||
// Compute "Xing" offset depending on MPEG version and channels.
|
||||
if (h_version == MPEG1)
|
||||
{
|
||||
if (h_mode == SINGLE_CHANNEL) offset=21-4;
|
||||
else offset=36-4;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (h_mode == SINGLE_CHANNEL) offset=13-4;
|
||||
else offset = 21-4;
|
||||
}
|
||||
try
|
||||
{
|
||||
System.arraycopy(firstframe, offset, tmp, 0, 4);
|
||||
// Is "Xing" ?
|
||||
if (xing.equals(new String(tmp)))
|
||||
{
|
||||
//Yes.
|
||||
h_vbr = true;
|
||||
h_vbr_frames = -1;
|
||||
h_vbr_bytes = -1;
|
||||
h_vbr_scale = -1;
|
||||
h_vbr_toc = new byte[100];
|
||||
|
||||
int length = 4;
|
||||
// Read flags.
|
||||
byte flags[] = new byte[4];
|
||||
System.arraycopy(firstframe, offset + length, flags, 0, flags.length);
|
||||
length += flags.length;
|
||||
// Read number of frames (if available).
|
||||
if ((flags[3] & (byte) (1 << 0)) != 0)
|
||||
{
|
||||
System.arraycopy(firstframe, offset + length, tmp, 0, tmp.length);
|
||||
h_vbr_frames = (tmp[0] << 24)&0xFF000000 | (tmp[1] << 16)&0x00FF0000 | (tmp[2] << 8)&0x0000FF00 | tmp[3]&0x000000FF;
|
||||
length += 4;
|
||||
}
|
||||
// Read size (if available).
|
||||
if ((flags[3] & (byte) (1 << 1)) != 0)
|
||||
{
|
||||
System.arraycopy(firstframe, offset + length, tmp, 0, tmp.length);
|
||||
h_vbr_bytes = (tmp[0] << 24)&0xFF000000 | (tmp[1] << 16)&0x00FF0000 | (tmp[2] << 8)&0x0000FF00 | tmp[3]&0x000000FF;
|
||||
length += 4;
|
||||
}
|
||||
// Read TOC (if available).
|
||||
if ((flags[3] & (byte) (1 << 2)) != 0)
|
||||
{
|
||||
System.arraycopy(firstframe, offset + length, h_vbr_toc, 0, h_vbr_toc.length);
|
||||
length += h_vbr_toc.length;
|
||||
}
|
||||
// Read scale (if available).
|
||||
if ((flags[3] & (byte) (1 << 3)) != 0)
|
||||
{
|
||||
System.arraycopy(firstframe, offset + length, tmp, 0, tmp.length);
|
||||
h_vbr_scale = (tmp[0] << 24)&0xFF000000 | (tmp[1] << 16)&0x00FF0000 | (tmp[2] << 8)&0x0000FF00 | tmp[3]&0x000000FF;
|
||||
length += 4;
|
||||
}
|
||||
//System.out.println("VBR:"+xing+" Frames:"+ h_vbr_frames +" Size:"+h_vbr_bytes);
|
||||
}
|
||||
}
|
||||
catch (ArrayIndexOutOfBoundsException e)
|
||||
{
|
||||
throw new BitstreamException("XingVBRHeader Corrupted",e);
|
||||
}
|
||||
|
||||
// Trying VBRI header.
|
||||
String vbri = "VBRI";
|
||||
offset = 36-4;
|
||||
try
|
||||
{
|
||||
System.arraycopy(firstframe, offset, tmp, 0, 4);
|
||||
// Is "VBRI" ?
|
||||
if (vbri.equals(new String(tmp)))
|
||||
{
|
||||
//Yes.
|
||||
h_vbr = true;
|
||||
h_vbr_frames = -1;
|
||||
h_vbr_bytes = -1;
|
||||
h_vbr_scale = -1;
|
||||
h_vbr_toc = new byte[100];
|
||||
// Bytes.
|
||||
int length = 4 + 6;
|
||||
System.arraycopy(firstframe, offset + length, tmp, 0, tmp.length);
|
||||
h_vbr_bytes = (tmp[0] << 24)&0xFF000000 | (tmp[1] << 16)&0x00FF0000 | (tmp[2] << 8)&0x0000FF00 | tmp[3]&0x000000FF;
|
||||
length += 4;
|
||||
// Frames.
|
||||
System.arraycopy(firstframe, offset + length, tmp, 0, tmp.length);
|
||||
h_vbr_frames = (tmp[0] << 24)&0xFF000000 | (tmp[1] << 16)&0x00FF0000 | (tmp[2] << 8)&0x0000FF00 | tmp[3]&0x000000FF;
|
||||
length += 4;
|
||||
//System.out.println("VBR:"+vbri+" Frames:"+ h_vbr_frames +" Size:"+h_vbr_bytes);
|
||||
// TOC
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
catch (ArrayIndexOutOfBoundsException e)
|
||||
{
|
||||
throw new BitstreamException("VBRIVBRHeader Corrupted",e);
|
||||
}
|
||||
}
|
||||
|
||||
// Functions to query header contents:
|
||||
/**
|
||||
* Returns version.
|
||||
*/
|
||||
public int version() { return h_version; }
|
||||
|
||||
/**
|
||||
* Returns Layer ID.
|
||||
*/
|
||||
public int layer() { return h_layer; }
|
||||
|
||||
/**
|
||||
* Returns bitrate index.
|
||||
*/
|
||||
public int bitrate_index() { return h_bitrate_index; }
|
||||
|
||||
/**
|
||||
* Returns Sample Frequency.
|
||||
*/
|
||||
public int sample_frequency() { return h_sample_frequency; }
|
||||
|
||||
/**
|
||||
* Returns Frequency.
|
||||
*/
|
||||
public int frequency() {return frequencies[h_version][h_sample_frequency];}
|
||||
|
||||
/**
|
||||
* Returns Mode.
|
||||
*/
|
||||
public int mode() { return h_mode; }
|
||||
|
||||
/**
|
||||
* Returns Protection bit.
|
||||
*/
|
||||
public boolean checksums()
|
||||
{
|
||||
if (h_protection_bit == 0) return true;
|
||||
else return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns Copyright.
|
||||
*/
|
||||
public boolean copyright() { return h_copyright; }
|
||||
|
||||
/**
|
||||
* Returns Original.
|
||||
*/
|
||||
public boolean original() { return h_original; }
|
||||
|
||||
/**
|
||||
* Return VBR.
|
||||
*
|
||||
* @return true if VBR header is found
|
||||
*/
|
||||
public boolean vbr() { return h_vbr; }
|
||||
|
||||
/**
|
||||
* Return VBR scale.
|
||||
*
|
||||
* @return scale of -1 if not available
|
||||
*/
|
||||
public int vbr_scale() { return h_vbr_scale; }
|
||||
|
||||
/**
|
||||
* Return VBR TOC.
|
||||
*
|
||||
* @return vbr toc ot null if not available
|
||||
*/
|
||||
public byte[] vbr_toc() { return h_vbr_toc; }
|
||||
|
||||
/**
|
||||
* Returns Checksum flag.
|
||||
* Compares computed checksum with stream checksum.
|
||||
*/
|
||||
public boolean checksum_ok () { return (checksum == crc.checksum()); }
|
||||
|
||||
// Seeking and layer III stuff
|
||||
/**
|
||||
* Returns Layer III Padding bit.
|
||||
*/
|
||||
public boolean padding()
|
||||
{
|
||||
if (h_padding_bit == 0) return false;
|
||||
else return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns Slots.
|
||||
*/
|
||||
public int slots() { return nSlots; }
|
||||
|
||||
/**
|
||||
* Returns Mode Extension.
|
||||
*/
|
||||
public int mode_extension() { return h_mode_extension; }
|
||||
|
||||
// E.B -> private to public
|
||||
public static final int bitrates[][][] = {
|
||||
{{0 /*free format*/, 32000, 48000, 56000, 64000, 80000, 96000,
|
||||
112000, 128000, 144000, 160000, 176000, 192000 ,224000, 256000, 0},
|
||||
{0 /*free format*/, 8000, 16000, 24000, 32000, 40000, 48000,
|
||||
56000, 64000, 80000, 96000, 112000, 128000, 144000, 160000, 0},
|
||||
{0 /*free format*/, 8000, 16000, 24000, 32000, 40000, 48000,
|
||||
56000, 64000, 80000, 96000, 112000, 128000, 144000, 160000, 0}},
|
||||
|
||||
{{0 /*free format*/, 32000, 64000, 96000, 128000, 160000, 192000,
|
||||
224000, 256000, 288000, 320000, 352000, 384000, 416000, 448000, 0},
|
||||
{0 /*free format*/, 32000, 48000, 56000, 64000, 80000, 96000,
|
||||
112000, 128000, 160000, 192000, 224000, 256000, 320000, 384000, 0},
|
||||
{0 /*free format*/, 32000, 40000, 48000, 56000, 64000, 80000,
|
||||
96000, 112000, 128000, 160000, 192000, 224000, 256000, 320000, 0}},
|
||||
// SZD: MPEG2.5
|
||||
{{0 /*free format*/, 32000, 48000, 56000, 64000, 80000, 96000,
|
||||
112000, 128000, 144000, 160000, 176000, 192000 ,224000, 256000, 0},
|
||||
{0 /*free format*/, 8000, 16000, 24000, 32000, 40000, 48000,
|
||||
56000, 64000, 80000, 96000, 112000, 128000, 144000, 160000, 0},
|
||||
{0 /*free format*/, 8000, 16000, 24000, 32000, 40000, 48000,
|
||||
56000, 64000, 80000, 96000, 112000, 128000, 144000, 160000, 0}},
|
||||
|
||||
};
|
||||
|
||||
// E.B -> private to public
|
||||
/**
|
||||
* Calculate Frame size.
|
||||
*
|
||||
* Calculates framesize in bytes excluding header size.
|
||||
*/
|
||||
public int calculate_framesize()
|
||||
{
|
||||
|
||||
if (h_layer == 1)
|
||||
{
|
||||
framesize = (12 * bitrates[h_version][0][h_bitrate_index]) /
|
||||
frequencies[h_version][h_sample_frequency];
|
||||
if (h_padding_bit != 0 ) framesize++;
|
||||
framesize <<= 2; // one slot is 4 bytes long
|
||||
nSlots = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
framesize = (144 * bitrates[h_version][h_layer - 1][h_bitrate_index]) /
|
||||
frequencies[h_version][h_sample_frequency];
|
||||
if (h_version == MPEG2_LSF || h_version == MPEG25_LSF) framesize >>= 1; // SZD
|
||||
if (h_padding_bit != 0) framesize++;
|
||||
// Layer III slots
|
||||
if (h_layer == 3)
|
||||
{
|
||||
if (h_version == MPEG1)
|
||||
{
|
||||
nSlots = framesize - ((h_mode == SINGLE_CHANNEL) ? 17 : 32) // side info size
|
||||
- ((h_protection_bit!=0) ? 0 : 2) // CRC size
|
||||
- 4; // header size
|
||||
}
|
||||
else
|
||||
{ // MPEG-2 LSF, SZD: MPEG-2.5 LSF
|
||||
nSlots = framesize - ((h_mode == SINGLE_CHANNEL) ? 9 : 17) // side info size
|
||||
- ((h_protection_bit!=0) ? 0 : 2) // CRC size
|
||||
- 4; // header size
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nSlots = 0;
|
||||
}
|
||||
}
|
||||
framesize -= 4; // subtract header size
|
||||
return framesize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the maximum number of frames in the stream.
|
||||
*
|
||||
* @param streamsize
|
||||
* @return number of frames
|
||||
*/
|
||||
public int max_number_of_frames(int streamsize) // E.B
|
||||
{
|
||||
if (h_vbr == true) return h_vbr_frames;
|
||||
else
|
||||
{
|
||||
if ((framesize + 4 - h_padding_bit) == 0) return 0;
|
||||
else return(streamsize / (framesize + 4 - h_padding_bit));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the maximum number of frames in the stream.
|
||||
*
|
||||
* @param streamsize
|
||||
* @return number of frames
|
||||
*/
|
||||
public int min_number_of_frames(int streamsize) // E.B
|
||||
{
|
||||
if (h_vbr == true) return h_vbr_frames;
|
||||
else
|
||||
{
|
||||
if ((framesize + 5 - h_padding_bit) == 0) return 0;
|
||||
else return(streamsize / (framesize + 5 - h_padding_bit));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns ms/frame.
|
||||
*
|
||||
* @return milliseconds per frame
|
||||
*/
|
||||
public float ms_per_frame() // E.B
|
||||
{
|
||||
if (h_vbr == true)
|
||||
{
|
||||
double tpf = h_vbr_time_per_frame[layer()] / frequency();
|
||||
if ((h_version == MPEG2_LSF) || (h_version == MPEG25_LSF)) tpf /= 2;
|
||||
return ((float) (tpf * 1000));
|
||||
}
|
||||
else
|
||||
{
|
||||
float ms_per_frame_array[][] = {{8.707483f, 8.0f, 12.0f},
|
||||
{26.12245f, 24.0f, 36.0f},
|
||||
{26.12245f, 24.0f, 36.0f}};
|
||||
return(ms_per_frame_array[h_layer-1][h_sample_frequency]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns total ms.
|
||||
*
|
||||
* @param streamsize
|
||||
* @return total milliseconds
|
||||
*/
|
||||
public float total_ms(int streamsize) // E.B
|
||||
{
|
||||
return(max_number_of_frames(streamsize) * ms_per_frame());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns synchronized header.
|
||||
*/
|
||||
public int getSyncHeader() // E.B
|
||||
{
|
||||
return _headerstring;
|
||||
}
|
||||
|
||||
// functions which return header informations as strings:
|
||||
/**
|
||||
* Return Layer version.
|
||||
*/
|
||||
public String layer_string()
|
||||
{
|
||||
switch (h_layer)
|
||||
{
|
||||
case 1:
|
||||
return "I";
|
||||
case 2:
|
||||
return "II";
|
||||
case 3:
|
||||
return "III";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// E.B -> private to public
|
||||
public static final String bitrate_str[][][] = {
|
||||
{{"free format", "32 kbit/s", "48 kbit/s", "56 kbit/s", "64 kbit/s",
|
||||
"80 kbit/s", "96 kbit/s", "112 kbit/s", "128 kbit/s", "144 kbit/s",
|
||||
"160 kbit/s", "176 kbit/s", "192 kbit/s", "224 kbit/s", "256 kbit/s",
|
||||
"forbidden"},
|
||||
{"free format", "8 kbit/s", "16 kbit/s", "24 kbit/s", "32 kbit/s",
|
||||
"40 kbit/s", "48 kbit/s", "56 kbit/s", "64 kbit/s", "80 kbit/s",
|
||||
"96 kbit/s", "112 kbit/s", "128 kbit/s", "144 kbit/s", "160 kbit/s",
|
||||
"forbidden"},
|
||||
{"free format", "8 kbit/s", "16 kbit/s", "24 kbit/s", "32 kbit/s",
|
||||
"40 kbit/s", "48 kbit/s", "56 kbit/s", "64 kbit/s", "80 kbit/s",
|
||||
"96 kbit/s", "112 kbit/s", "128 kbit/s", "144 kbit/s", "160 kbit/s",
|
||||
"forbidden"}},
|
||||
|
||||
{{"free format", "32 kbit/s", "64 kbit/s", "96 kbit/s", "128 kbit/s",
|
||||
"160 kbit/s", "192 kbit/s", "224 kbit/s", "256 kbit/s", "288 kbit/s",
|
||||
"320 kbit/s", "352 kbit/s", "384 kbit/s", "416 kbit/s", "448 kbit/s",
|
||||
"forbidden"},
|
||||
{"free format", "32 kbit/s", "48 kbit/s", "56 kbit/s", "64 kbit/s",
|
||||
"80 kbit/s", "96 kbit/s", "112 kbit/s", "128 kbit/s", "160 kbit/s",
|
||||
"192 kbit/s", "224 kbit/s", "256 kbit/s", "320 kbit/s", "384 kbit/s",
|
||||
"forbidden"},
|
||||
{"free format", "32 kbit/s", "40 kbit/s", "48 kbit/s", "56 kbit/s",
|
||||
"64 kbit/s", "80 kbit/s" , "96 kbit/s", "112 kbit/s", "128 kbit/s",
|
||||
"160 kbit/s", "192 kbit/s", "224 kbit/s", "256 kbit/s", "320 kbit/s",
|
||||
"forbidden"}},
|
||||
// SZD: MPEG2.5
|
||||
{{"free format", "32 kbit/s", "48 kbit/s", "56 kbit/s", "64 kbit/s",
|
||||
"80 kbit/s", "96 kbit/s", "112 kbit/s", "128 kbit/s", "144 kbit/s",
|
||||
"160 kbit/s", "176 kbit/s", "192 kbit/s", "224 kbit/s", "256 kbit/s",
|
||||
"forbidden"},
|
||||
{"free format", "8 kbit/s", "16 kbit/s", "24 kbit/s", "32 kbit/s",
|
||||
"40 kbit/s", "48 kbit/s", "56 kbit/s", "64 kbit/s", "80 kbit/s",
|
||||
"96 kbit/s", "112 kbit/s", "128 kbit/s", "144 kbit/s", "160 kbit/s",
|
||||
"forbidden"},
|
||||
{"free format", "8 kbit/s", "16 kbit/s", "24 kbit/s", "32 kbit/s",
|
||||
"40 kbit/s", "48 kbit/s", "56 kbit/s", "64 kbit/s", "80 kbit/s",
|
||||
"96 kbit/s", "112 kbit/s", "128 kbit/s", "144 kbit/s", "160 kbit/s",
|
||||
"forbidden"}},
|
||||
};
|
||||
|
||||
/**
|
||||
* Return Bitrate.
|
||||
*
|
||||
* @return bitrate in bps
|
||||
*/
|
||||
public String bitrate_string()
|
||||
{
|
||||
if (h_vbr == true)
|
||||
{
|
||||
return Integer.toString(bitrate()/1000)+" kb/s";
|
||||
}
|
||||
else return bitrate_str[h_version][h_layer - 1][h_bitrate_index];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return Bitrate.
|
||||
*
|
||||
* @return bitrate in bps and average bitrate for VBR header
|
||||
*/
|
||||
public int bitrate()
|
||||
{
|
||||
if (h_vbr == true)
|
||||
{
|
||||
return ((int) ((h_vbr_bytes * 8) / (ms_per_frame() * h_vbr_frames)))*1000;
|
||||
}
|
||||
else return bitrates[h_version][h_layer - 1][h_bitrate_index];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return Instant Bitrate.
|
||||
* Bitrate for VBR is not constant.
|
||||
*
|
||||
* @return bitrate in bps
|
||||
*/
|
||||
public int bitrate_instant()
|
||||
{
|
||||
return bitrates[h_version][h_layer - 1][h_bitrate_index];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns Frequency
|
||||
*
|
||||
* @return frequency string in kHz
|
||||
*/
|
||||
public String sample_frequency_string()
|
||||
{
|
||||
switch (h_sample_frequency)
|
||||
{
|
||||
case THIRTYTWO:
|
||||
if (h_version == MPEG1)
|
||||
return "32 kHz";
|
||||
else if (h_version == MPEG2_LSF)
|
||||
return "16 kHz";
|
||||
else // SZD
|
||||
return "8 kHz";
|
||||
case FOURTYFOUR_POINT_ONE:
|
||||
if (h_version == MPEG1)
|
||||
return "44.1 kHz";
|
||||
else if (h_version == MPEG2_LSF)
|
||||
return "22.05 kHz";
|
||||
else // SZD
|
||||
return "11.025 kHz";
|
||||
case FOURTYEIGHT:
|
||||
if (h_version == MPEG1)
|
||||
return "48 kHz";
|
||||
else if (h_version == MPEG2_LSF)
|
||||
return "24 kHz";
|
||||
else // SZD
|
||||
return "12 kHz";
|
||||
}
|
||||
return(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns Mode.
|
||||
*/
|
||||
public String mode_string()
|
||||
{
|
||||
switch (h_mode)
|
||||
{
|
||||
case STEREO:
|
||||
return "Stereo";
|
||||
case JOINT_STEREO:
|
||||
return "Joint stereo";
|
||||
case DUAL_CHANNEL:
|
||||
return "Dual channel";
|
||||
case SINGLE_CHANNEL:
|
||||
return "Single channel";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns Version.
|
||||
*
|
||||
* @return MPEG-1 or MPEG-2 LSF or MPEG-2.5 LSF
|
||||
*/
|
||||
public String version_string()
|
||||
{
|
||||
switch (h_version)
|
||||
{
|
||||
case MPEG1:
|
||||
return "MPEG-1";
|
||||
case MPEG2_LSF:
|
||||
return "MPEG-2 LSF";
|
||||
case MPEG25_LSF: // SZD
|
||||
return "MPEG-2.5 LSF";
|
||||
}
|
||||
return(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of subbands in the current frame.
|
||||
*
|
||||
* @return number of subbands
|
||||
*/
|
||||
public int number_of_subbands() {return h_number_of_subbands;}
|
||||
|
||||
/**
|
||||
* Returns Intensity Stereo.
|
||||
* (Layer II joint stereo only).
|
||||
* Returns the number of subbands which are in stereo mode,
|
||||
* subbands above that limit are in intensity stereo mode.
|
||||
*
|
||||
* @return intensity
|
||||
*/
|
||||
public int intensity_stereo_bound() {return h_intensity_stereo_bound;}
|
||||
}
|
||||
80
src/lwjgl/java/javazoom/jl/decoder/InputStreamSource.java
Normal file
80
src/lwjgl/java/javazoom/jl/decoder/InputStreamSource.java
Normal file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* 11/19/04 1.0 moved to LGPL.
|
||||
* 12/12/99 Initial version. mdm@techie.com
|
||||
*-----------------------------------------------------------------------
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library General Public License as published
|
||||
* by the Free Software Foundation; either version 2 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 Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
package javazoom.jl.decoder;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* <i>Work In Progress.</i>
|
||||
*
|
||||
* An instance of <code>InputStreamSource</code> implements a
|
||||
* <code>Source</code> that provides data from an <code>InputStream
|
||||
* </code>. Seeking functionality is not supported.
|
||||
*
|
||||
* @author MDM
|
||||
*/
|
||||
public class InputStreamSource implements Source
|
||||
{
|
||||
private final InputStream in;
|
||||
|
||||
public InputStreamSource(InputStream in)
|
||||
{
|
||||
if (in==null)
|
||||
throw new NullPointerException("in");
|
||||
|
||||
this.in = in;
|
||||
}
|
||||
|
||||
public int read(byte[] b, int offs, int len)
|
||||
throws IOException
|
||||
{
|
||||
int read = in.read(b, offs, len);
|
||||
return read;
|
||||
}
|
||||
|
||||
public boolean willReadBlock()
|
||||
{
|
||||
return true;
|
||||
//boolean block = (in.available()==0);
|
||||
//return block;
|
||||
}
|
||||
|
||||
public boolean isSeekable()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public long tell()
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
public long seek(long to)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
public long length()
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
31
src/lwjgl/java/javazoom/jl/decoder/JavaLayerError.java
Normal file
31
src/lwjgl/java/javazoom/jl/decoder/JavaLayerError.java
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 11/19/04 1.0 moved to LGPL.
|
||||
* 12/12/99 Initial version. mdm@techie.com
|
||||
*-----------------------------------------------------------------------
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library General Public License as published
|
||||
* by the Free Software Foundation; either version 2 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 Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
package javazoom.jl.decoder;
|
||||
|
||||
/**
|
||||
* Work in progress.
|
||||
*
|
||||
* API usage errors may be handled by throwing an instance of this
|
||||
* class, as per JMF 2.0.
|
||||
*/
|
||||
public class JavaLayerError extends Error
|
||||
{
|
||||
}
|
||||
40
src/lwjgl/java/javazoom/jl/decoder/JavaLayerErrors.java
Normal file
40
src/lwjgl/java/javazoom/jl/decoder/JavaLayerErrors.java
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 11/19/04 1.0 moved to LGPL.
|
||||
* 12/12/99 Initial version. mdm@techie.com
|
||||
*-----------------------------------------------------------------------
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library General Public License as published
|
||||
* by the Free Software Foundation; either version 2 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 Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
package javazoom.jl.decoder;
|
||||
|
||||
/**
|
||||
* Exception error codes for components of the JavaLayer API.
|
||||
*/
|
||||
public interface JavaLayerErrors
|
||||
{
|
||||
/**
|
||||
* The first bitstream error code. See the {@link DecoderErrors DecoderErrors}
|
||||
* interface for other bitstream error codes.
|
||||
*/
|
||||
public static final int BITSTREAM_ERROR = 0x100;
|
||||
|
||||
/**
|
||||
* The first decoder error code. See the {@link DecoderErrors DecoderErrors}
|
||||
* interface for other decoder error codes.
|
||||
*/
|
||||
public static final int DECODER_ERROR = 0x200;
|
||||
|
||||
}
|
||||
78
src/lwjgl/java/javazoom/jl/decoder/JavaLayerException.java
Normal file
78
src/lwjgl/java/javazoom/jl/decoder/JavaLayerException.java
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* 11/19/04 1.0 moved to LGPL.
|
||||
* 12/12/99 Initial version. mdm@techie.com
|
||||
*-----------------------------------------------------------------------
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library General Public License as published
|
||||
* by the Free Software Foundation; either version 2 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 Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
package javazoom.jl.decoder;
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
|
||||
/**
|
||||
* The JavaLayerException is the base class for all API-level
|
||||
* exceptions thrown by JavaLayer. To facilitate conversion and
|
||||
* common handling of exceptions from other domains, the class
|
||||
* can delegate some functionality to a contained Throwable instance.
|
||||
* <p>
|
||||
*
|
||||
* @author MDM
|
||||
*/
|
||||
public class JavaLayerException extends Exception
|
||||
{
|
||||
|
||||
private Throwable exception;
|
||||
|
||||
|
||||
public JavaLayerException()
|
||||
{
|
||||
}
|
||||
|
||||
public JavaLayerException(String msg)
|
||||
{
|
||||
super(msg);
|
||||
}
|
||||
|
||||
public JavaLayerException(String msg, Throwable t)
|
||||
{
|
||||
super(msg);
|
||||
exception = t;
|
||||
}
|
||||
|
||||
public Throwable getException()
|
||||
{
|
||||
return exception;
|
||||
}
|
||||
|
||||
|
||||
public void printStackTrace()
|
||||
{
|
||||
printStackTrace(System.err);
|
||||
}
|
||||
|
||||
public void printStackTrace(PrintStream ps)
|
||||
{
|
||||
if (this.exception==null)
|
||||
{
|
||||
super.printStackTrace(ps);
|
||||
}
|
||||
else
|
||||
{
|
||||
exception.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
36
src/lwjgl/java/javazoom/jl/decoder/JavaLayerHook.java
Normal file
36
src/lwjgl/java/javazoom/jl/decoder/JavaLayerHook.java
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 11/19/04 1.0 moved to LGPL.
|
||||
*-----------------------------------------------------------------------
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library General Public License as published
|
||||
* by the Free Software Foundation; either version 2 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 Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
package javazoom.jl.decoder;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* The <code>JavaLayerHooks</code> class allows developers to change
|
||||
* the way the JavaLayer library uses Resources.
|
||||
*/
|
||||
|
||||
public interface JavaLayerHook
|
||||
{
|
||||
/**
|
||||
* Retrieves the named resource. This allows resources to be
|
||||
* obtained without specifying how they are retrieved.
|
||||
*/
|
||||
public InputStream getResourceAsStream(String name);
|
||||
}
|
||||
208
src/lwjgl/java/javazoom/jl/decoder/JavaLayerUtils.java
Normal file
208
src/lwjgl/java/javazoom/jl/decoder/JavaLayerUtils.java
Normal file
@@ -0,0 +1,208 @@
|
||||
/*
|
||||
* 11/19/04 1.0 moved to LGPL.
|
||||
* 12/12/99 Initial version. mdm@techie.com
|
||||
*-----------------------------------------------------------------------
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library General Public License as published
|
||||
* by the Free Software Foundation; either version 2 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 Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
package javazoom.jl.decoder;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InvalidClassException;
|
||||
import java.io.InvalidObjectException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.lang.reflect.Array;
|
||||
|
||||
/**
|
||||
* The JavaLayerUtils class is not strictly part of the JavaLayer API.
|
||||
* It serves to provide useful methods and system-wide hooks.
|
||||
*
|
||||
* @author MDM
|
||||
*/
|
||||
public class JavaLayerUtils
|
||||
{
|
||||
private static JavaLayerHook hook = null;
|
||||
|
||||
/**
|
||||
* Deserializes the object contained in the given input stream.
|
||||
*
|
||||
* @param in The input stream to deserialize an object from.
|
||||
* @param cls The expected class of the deserialized object.
|
||||
*/
|
||||
public static Object deserialize(InputStream in, Class cls)
|
||||
throws IOException
|
||||
{
|
||||
if (cls==null)
|
||||
throw new NullPointerException("cls");
|
||||
|
||||
Object obj = deserialize(in, cls);
|
||||
if (!cls.isInstance(obj))
|
||||
{
|
||||
throw new InvalidObjectException("type of deserialized instance not of required class.");
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserializes an object from the given <code>InputStream</code>.
|
||||
* The deserialization is delegated to an <code>
|
||||
* ObjectInputStream</code> instance.
|
||||
*
|
||||
* @param in The <code>InputStream</code> to deserialize an object
|
||||
* from.
|
||||
*
|
||||
* @return The object deserialized from the stream.
|
||||
* @exception IOException is thrown if there was a problem reading
|
||||
* the underlying stream, or an object could not be deserialized
|
||||
* from the stream.
|
||||
*
|
||||
* @see java.io.ObjectInputStream
|
||||
*/
|
||||
public static Object deserialize(InputStream in)
|
||||
throws IOException
|
||||
{
|
||||
if (in==null)
|
||||
throw new NullPointerException("in");
|
||||
|
||||
ObjectInputStream objIn = new ObjectInputStream(in);
|
||||
|
||||
Object obj;
|
||||
|
||||
try
|
||||
{
|
||||
obj = objIn.readObject();
|
||||
}
|
||||
catch (ClassNotFoundException ex)
|
||||
{
|
||||
throw new InvalidClassException(ex.toString());
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserializes an array from a given <code>InputStream</code>.
|
||||
*
|
||||
* @param in The <code>InputStream</code> to
|
||||
* deserialize an object from.
|
||||
*
|
||||
* @param elemType The class denoting the type of the array
|
||||
* elements.
|
||||
* @param length The expected length of the array, or -1 if
|
||||
* any length is expected.
|
||||
*/
|
||||
public static Object deserializeArray(InputStream in, Class elemType, int length)
|
||||
throws IOException
|
||||
{
|
||||
if (elemType==null)
|
||||
throw new NullPointerException("elemType");
|
||||
|
||||
if (length<-1)
|
||||
throw new IllegalArgumentException("length");
|
||||
|
||||
Object obj = deserialize(in);
|
||||
|
||||
Class cls = obj.getClass();
|
||||
|
||||
|
||||
if (!cls.isArray())
|
||||
throw new InvalidObjectException("object is not an array");
|
||||
|
||||
Class arrayElemType = cls.getComponentType();
|
||||
if (arrayElemType!=elemType)
|
||||
throw new InvalidObjectException("unexpected array component type");
|
||||
|
||||
if (length != -1)
|
||||
{
|
||||
int arrayLength = Array.getLength(obj);
|
||||
if (arrayLength!=length)
|
||||
throw new InvalidObjectException("array length mismatch");
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
public static Object deserializeArrayResource(String name, Class elemType, int length)
|
||||
throws IOException
|
||||
{
|
||||
InputStream str = getResourceAsStream(name);
|
||||
if (str==null)
|
||||
throw new IOException("unable to load resource '"+name+"'");
|
||||
|
||||
Object obj = deserializeArray(str, elemType, length);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
public static void serialize(OutputStream out, Object obj)
|
||||
throws IOException
|
||||
{
|
||||
if (out==null)
|
||||
throw new NullPointerException("out");
|
||||
|
||||
if (obj==null)
|
||||
throw new NullPointerException("obj");
|
||||
|
||||
ObjectOutputStream objOut = new ObjectOutputStream(out);
|
||||
objOut.writeObject(obj);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the system-wide JavaLayer hook.
|
||||
*/
|
||||
public static synchronized void setHook(JavaLayerHook hook0)
|
||||
{
|
||||
hook = hook0;
|
||||
}
|
||||
|
||||
public static synchronized JavaLayerHook getHook()
|
||||
{
|
||||
return hook;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves an InputStream for a named resource.
|
||||
*
|
||||
* @param name The name of the resource. This must be a simple
|
||||
* name, and not a qualified package name.
|
||||
*
|
||||
* @return The InputStream for the named resource, or null if
|
||||
* the resource has not been found. If a hook has been
|
||||
* provided, its getResourceAsStream() method is called
|
||||
* to retrieve the resource.
|
||||
*/
|
||||
public static synchronized InputStream getResourceAsStream(String name)
|
||||
{
|
||||
InputStream is = null;
|
||||
|
||||
if (hook!=null)
|
||||
{
|
||||
is = hook.getResourceAsStream(name);
|
||||
}
|
||||
else
|
||||
{
|
||||
Class cls = JavaLayerUtils.class;
|
||||
is = cls.getResourceAsStream(name);
|
||||
}
|
||||
|
||||
return is;
|
||||
}
|
||||
}
|
||||
448
src/lwjgl/java/javazoom/jl/decoder/LayerIDecoder.java
Normal file
448
src/lwjgl/java/javazoom/jl/decoder/LayerIDecoder.java
Normal file
@@ -0,0 +1,448 @@
|
||||
/*
|
||||
* 09/26/08 throw exception on subbband alloc error: Christopher G. Jennings (cjennings@acm.org)
|
||||
*
|
||||
* 11/19/04 1.0 moved to LGPL.
|
||||
*
|
||||
* 12/12/99 Initial version. Adapted from javalayer.java
|
||||
* and Subband*.java. mdm@techie.com
|
||||
*
|
||||
* 02/28/99 Initial version : javalayer.java by E.B
|
||||
*-----------------------------------------------------------------------
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library General Public License as published
|
||||
* by the Free Software Foundation; either version 2 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 Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
package javazoom.jl.decoder;
|
||||
|
||||
/**
|
||||
* Implements decoding of MPEG Audio Layer I frames.
|
||||
*/
|
||||
class LayerIDecoder implements FrameDecoder
|
||||
{
|
||||
protected Bitstream stream;
|
||||
protected Header header;
|
||||
protected SynthesisFilter filter1, filter2;
|
||||
protected Obuffer buffer;
|
||||
protected int which_channels;
|
||||
protected int mode;
|
||||
|
||||
protected int num_subbands;
|
||||
protected Subband[] subbands;
|
||||
protected Crc16 crc = null; // new Crc16[1] to enable CRC checking.
|
||||
|
||||
public LayerIDecoder()
|
||||
{
|
||||
crc = new Crc16();
|
||||
}
|
||||
|
||||
public void create(Bitstream stream0, Header header0,
|
||||
SynthesisFilter filtera, SynthesisFilter filterb,
|
||||
Obuffer buffer0, int which_ch0)
|
||||
{
|
||||
stream = stream0;
|
||||
header = header0;
|
||||
filter1 = filtera;
|
||||
filter2 = filterb;
|
||||
buffer = buffer0;
|
||||
which_channels = which_ch0;
|
||||
|
||||
}
|
||||
|
||||
public void decodeFrame() throws DecoderException
|
||||
{
|
||||
|
||||
num_subbands = header.number_of_subbands();
|
||||
subbands = new Subband[32];
|
||||
mode = header.mode();
|
||||
|
||||
createSubbands();
|
||||
|
||||
readAllocation();
|
||||
readScaleFactorSelection();
|
||||
|
||||
if ((crc != null) || header.checksum_ok())
|
||||
{
|
||||
readScaleFactors();
|
||||
|
||||
readSampleData();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected void createSubbands()
|
||||
{
|
||||
int i;
|
||||
if (mode == Header.SINGLE_CHANNEL)
|
||||
for (i = 0; i < num_subbands; ++i)
|
||||
subbands[i] = new SubbandLayer1(i);
|
||||
else if (mode == Header.JOINT_STEREO)
|
||||
{
|
||||
for (i = 0; i < header.intensity_stereo_bound(); ++i)
|
||||
subbands[i] = new SubbandLayer1Stereo(i);
|
||||
for (; i < num_subbands; ++i)
|
||||
subbands[i] = new SubbandLayer1IntensityStereo(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < num_subbands; ++i)
|
||||
subbands[i] = new SubbandLayer1Stereo(i);
|
||||
}
|
||||
}
|
||||
|
||||
protected void readAllocation() throws DecoderException
|
||||
{
|
||||
// start to read audio data:
|
||||
for (int i = 0; i < num_subbands; ++i)
|
||||
subbands[i].read_allocation(stream, header, crc);
|
||||
|
||||
}
|
||||
|
||||
protected void readScaleFactorSelection()
|
||||
{
|
||||
// scale factor selection not present for layer I.
|
||||
}
|
||||
|
||||
protected void readScaleFactors()
|
||||
{
|
||||
for (int i = 0; i < num_subbands; ++i)
|
||||
subbands[i].read_scalefactor(stream, header);
|
||||
}
|
||||
|
||||
protected void readSampleData()
|
||||
{
|
||||
boolean read_ready = false;
|
||||
boolean write_ready = false;
|
||||
int mode = header.mode();
|
||||
int i;
|
||||
do
|
||||
{
|
||||
for (i = 0; i < num_subbands; ++i)
|
||||
read_ready = subbands[i].read_sampledata(stream);
|
||||
do
|
||||
{
|
||||
for (i = 0; i < num_subbands; ++i)
|
||||
write_ready = subbands[i].put_next_sample(which_channels,filter1, filter2);
|
||||
|
||||
filter1.calculate_pcm_samples(buffer);
|
||||
if ((which_channels == OutputChannels.BOTH_CHANNELS) && (mode != Header.SINGLE_CHANNEL))
|
||||
filter2.calculate_pcm_samples(buffer);
|
||||
} while (!write_ready);
|
||||
} while (!read_ready);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Abstract base class for subband classes of layer I and II
|
||||
*/
|
||||
abstract static class Subband
|
||||
{
|
||||
/*
|
||||
* Changes from version 1.1 to 1.2:
|
||||
* - array size increased by one, although a scalefactor with index 63
|
||||
* is illegal (to prevent segmentation faults)
|
||||
*/
|
||||
// Scalefactors for layer I and II, Annex 3-B.1 in ISO/IEC DIS 11172:
|
||||
public static final float scalefactors[] =
|
||||
{
|
||||
2.00000000000000f, 1.58740105196820f, 1.25992104989487f, 1.00000000000000f,
|
||||
0.79370052598410f, 0.62996052494744f, 0.50000000000000f, 0.39685026299205f,
|
||||
0.31498026247372f, 0.25000000000000f, 0.19842513149602f, 0.15749013123686f,
|
||||
0.12500000000000f, 0.09921256574801f, 0.07874506561843f, 0.06250000000000f,
|
||||
0.04960628287401f, 0.03937253280921f, 0.03125000000000f, 0.02480314143700f,
|
||||
0.01968626640461f, 0.01562500000000f, 0.01240157071850f, 0.00984313320230f,
|
||||
0.00781250000000f, 0.00620078535925f, 0.00492156660115f, 0.00390625000000f,
|
||||
0.00310039267963f, 0.00246078330058f, 0.00195312500000f, 0.00155019633981f,
|
||||
0.00123039165029f, 0.00097656250000f, 0.00077509816991f, 0.00061519582514f,
|
||||
0.00048828125000f, 0.00038754908495f, 0.00030759791257f, 0.00024414062500f,
|
||||
0.00019377454248f, 0.00015379895629f, 0.00012207031250f, 0.00009688727124f,
|
||||
0.00007689947814f, 0.00006103515625f, 0.00004844363562f, 0.00003844973907f,
|
||||
0.00003051757813f, 0.00002422181781f, 0.00001922486954f, 0.00001525878906f,
|
||||
0.00001211090890f, 0.00000961243477f, 0.00000762939453f, 0.00000605545445f,
|
||||
0.00000480621738f, 0.00000381469727f, 0.00000302772723f, 0.00000240310869f,
|
||||
0.00000190734863f, 0.00000151386361f, 0.00000120155435f, 0.00000000000000f /* illegal scalefactor */
|
||||
};
|
||||
|
||||
public abstract void read_allocation (Bitstream stream, Header header, Crc16 crc) throws DecoderException;
|
||||
public abstract void read_scalefactor (Bitstream stream, Header header);
|
||||
public abstract boolean read_sampledata (Bitstream stream);
|
||||
public abstract boolean put_next_sample (int channels, SynthesisFilter filter1, SynthesisFilter filter2);
|
||||
};
|
||||
|
||||
/**
|
||||
* Class for layer I subbands in single channel mode.
|
||||
* Used for single channel mode
|
||||
* and in derived class for intensity stereo mode
|
||||
*/
|
||||
static class SubbandLayer1 extends Subband
|
||||
{
|
||||
|
||||
// Factors and offsets for sample re-quantization
|
||||
public static final float table_factor[] = {
|
||||
0.0f, (1.0f/2.0f) * (4.0f/3.0f), (1.0f/4.0f) * (8.0f/7.0f), (1.0f/8.0f) * (16.0f/15.0f),
|
||||
(1.0f/16.0f) * (32.0f/31.0f), (1.0f/32.0f) * (64.0f/63.0f), (1.0f/64.0f) * (128.0f/127.0f),
|
||||
(1.0f/128.0f) * (256.0f/255.0f), (1.0f/256.0f) * (512.0f/511.0f),
|
||||
(1.0f/512.0f) * (1024.0f/1023.0f), (1.0f/1024.0f) * (2048.0f/2047.0f),
|
||||
(1.0f/2048.0f) * (4096.0f/4095.0f), (1.0f/4096.0f) * (8192.0f/8191.0f),
|
||||
(1.0f/8192.0f) * (16384.0f/16383.0f), (1.0f/16384.0f) * (32768.0f/32767.0f)
|
||||
};
|
||||
|
||||
public static final float table_offset[] = {
|
||||
0.0f, ((1.0f/2.0f)-1.0f) * (4.0f/3.0f), ((1.0f/4.0f)-1.0f) * (8.0f/7.0f), ((1.0f/8.0f)-1.0f) * (16.0f/15.0f),
|
||||
((1.0f/16.0f)-1.0f) * (32.0f/31.0f), ((1.0f/32.0f)-1.0f) * (64.0f/63.0f), ((1.0f/64.0f)-1.0f) * (128.0f/127.0f),
|
||||
((1.0f/128.0f)-1.0f) * (256.0f/255.0f), ((1.0f/256.0f)-1.0f) * (512.0f/511.0f),
|
||||
((1.0f/512.0f)-1.0f) * (1024.0f/1023.0f), ((1.0f/1024.0f)-1.0f) * (2048.0f/2047.0f),
|
||||
((1.0f/2048.0f)-1.0f) * (4096.0f/4095.0f), ((1.0f/4096.0f)-1.0f) * (8192.0f/8191.0f),
|
||||
((1.0f/8192.0f)-1.0f) * (16384.0f/16383.0f), ((1.0f/16384.0f)-1.0f) * (32768.0f/32767.0f)
|
||||
};
|
||||
|
||||
protected int subbandnumber;
|
||||
protected int samplenumber;
|
||||
protected int allocation;
|
||||
protected float scalefactor;
|
||||
protected int samplelength;
|
||||
protected float sample;
|
||||
protected float factor, offset;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public SubbandLayer1(int subbandnumber)
|
||||
{
|
||||
this.subbandnumber = subbandnumber;
|
||||
samplenumber = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public void read_allocation(Bitstream stream, Header header, Crc16 crc) throws DecoderException
|
||||
{
|
||||
if ((allocation = stream.get_bits (4)) == 15)
|
||||
{
|
||||
// CGJ: catch this condition and throw appropriate exception
|
||||
throw new DecoderException(DecoderErrors.ILLEGAL_SUBBAND_ALLOCATION, null);
|
||||
// cerr << "WARNING: stream contains an illegal allocation!\n";
|
||||
// MPEG-stream is corrupted!
|
||||
}
|
||||
|
||||
if (crc != null) crc.add_bits (allocation, 4);
|
||||
if (allocation != 0)
|
||||
{
|
||||
samplelength = allocation + 1;
|
||||
factor = table_factor[allocation];
|
||||
offset = table_offset[allocation];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public void read_scalefactor(Bitstream stream, Header header)
|
||||
{
|
||||
if (allocation != 0) scalefactor = scalefactors[stream.get_bits(6)];
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public boolean read_sampledata(Bitstream stream)
|
||||
{
|
||||
if (allocation != 0)
|
||||
{
|
||||
sample = (float) (stream.get_bits(samplelength));
|
||||
}
|
||||
if (++samplenumber == 12)
|
||||
{
|
||||
samplenumber = 0;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public boolean put_next_sample(int channels, SynthesisFilter filter1, SynthesisFilter filter2)
|
||||
{
|
||||
if ((allocation !=0) && (channels != OutputChannels.RIGHT_CHANNEL))
|
||||
{
|
||||
float scaled_sample = (sample * factor + offset) * scalefactor;
|
||||
filter1.input_sample (scaled_sample, subbandnumber);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Class for layer I subbands in joint stereo mode.
|
||||
*/
|
||||
static class SubbandLayer1IntensityStereo extends SubbandLayer1
|
||||
{
|
||||
protected float channel2_scalefactor;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public SubbandLayer1IntensityStereo(int subbandnumber)
|
||||
{
|
||||
super(subbandnumber);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public void read_allocation(Bitstream stream, Header header, Crc16 crc) throws DecoderException
|
||||
{
|
||||
super.read_allocation (stream, header, crc);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public void read_scalefactor (Bitstream stream, Header header)
|
||||
{
|
||||
if (allocation != 0)
|
||||
{
|
||||
scalefactor = scalefactors[stream.get_bits(6)];
|
||||
channel2_scalefactor = scalefactors[stream.get_bits(6)];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public boolean read_sampledata(Bitstream stream)
|
||||
{
|
||||
return super.read_sampledata (stream);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public boolean put_next_sample (int channels, SynthesisFilter filter1, SynthesisFilter filter2)
|
||||
{
|
||||
if (allocation !=0 )
|
||||
{
|
||||
sample = sample * factor + offset; // re-quantization
|
||||
if (channels == OutputChannels.BOTH_CHANNELS)
|
||||
{
|
||||
float sample1 = sample * scalefactor,
|
||||
sample2 = sample * channel2_scalefactor;
|
||||
filter1.input_sample(sample1, subbandnumber);
|
||||
filter2.input_sample(sample2, subbandnumber);
|
||||
}
|
||||
else if (channels == OutputChannels.LEFT_CHANNEL)
|
||||
{
|
||||
float sample1 = sample * scalefactor;
|
||||
filter1.input_sample(sample1, subbandnumber);
|
||||
}
|
||||
else
|
||||
{
|
||||
float sample2 = sample * channel2_scalefactor;
|
||||
filter1.input_sample(sample2, subbandnumber);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Class for layer I subbands in stereo mode.
|
||||
*/
|
||||
static class SubbandLayer1Stereo extends SubbandLayer1
|
||||
{
|
||||
protected int channel2_allocation;
|
||||
protected float channel2_scalefactor;
|
||||
protected int channel2_samplelength;
|
||||
protected float channel2_sample;
|
||||
protected float channel2_factor, channel2_offset;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public SubbandLayer1Stereo(int subbandnumber)
|
||||
{
|
||||
super(subbandnumber);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public void read_allocation (Bitstream stream, Header header, Crc16 crc) throws DecoderException
|
||||
{
|
||||
allocation = stream.get_bits(4);
|
||||
channel2_allocation = stream.get_bits(4);
|
||||
if (crc != null)
|
||||
{
|
||||
crc.add_bits (allocation, 4);
|
||||
crc.add_bits (channel2_allocation, 4);
|
||||
}
|
||||
if (allocation != 0)
|
||||
{
|
||||
samplelength = allocation + 1;
|
||||
factor = table_factor[allocation];
|
||||
offset = table_offset[allocation];
|
||||
}
|
||||
if (channel2_allocation != 0)
|
||||
{
|
||||
channel2_samplelength = channel2_allocation + 1;
|
||||
channel2_factor = table_factor[channel2_allocation];
|
||||
channel2_offset = table_offset[channel2_allocation];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public void read_scalefactor(Bitstream stream, Header header)
|
||||
{
|
||||
if (allocation != 0) scalefactor = scalefactors[stream.get_bits(6)];
|
||||
if (channel2_allocation != 0) channel2_scalefactor = scalefactors[stream.get_bits(6)];
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public boolean read_sampledata (Bitstream stream)
|
||||
{
|
||||
boolean returnvalue = super.read_sampledata(stream);
|
||||
if (channel2_allocation != 0)
|
||||
{
|
||||
channel2_sample = (float) (stream.get_bits(channel2_samplelength));
|
||||
}
|
||||
return(returnvalue);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public boolean put_next_sample(int channels, SynthesisFilter filter1, SynthesisFilter filter2)
|
||||
{
|
||||
super.put_next_sample (channels, filter1, filter2);
|
||||
if ((channel2_allocation != 0) && (channels != OutputChannels.LEFT_CHANNEL))
|
||||
{
|
||||
float sample2 = (channel2_sample * channel2_factor + channel2_offset) *
|
||||
channel2_scalefactor;
|
||||
if (channels == OutputChannels.BOTH_CHANNELS)
|
||||
filter2.input_sample (sample2, subbandnumber);
|
||||
else
|
||||
filter1.input_sample (sample2, subbandnumber);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
1064
src/lwjgl/java/javazoom/jl/decoder/LayerIIDecoder.java
Normal file
1064
src/lwjgl/java/javazoom/jl/decoder/LayerIIDecoder.java
Normal file
File diff suppressed because it is too large
Load Diff
2436
src/lwjgl/java/javazoom/jl/decoder/LayerIIIDecoder.java
Normal file
2436
src/lwjgl/java/javazoom/jl/decoder/LayerIIIDecoder.java
Normal file
File diff suppressed because it is too large
Load Diff
46
src/lwjgl/java/javazoom/jl/decoder/Manager.java
Normal file
46
src/lwjgl/java/javazoom/jl/decoder/Manager.java
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 11/19/04 1.0 moved to LGPL.
|
||||
*-----------------------------------------------------------------------
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library General Public License as published
|
||||
* by the Free Software Foundation; either version 2 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 Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
package javazoom.jl.decoder;
|
||||
|
||||
/**
|
||||
* Work in progress.
|
||||
*
|
||||
* Manages a number of controls.
|
||||
*/
|
||||
public class Manager //implements Control
|
||||
{
|
||||
public void addControl(Control c)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void removeControl(Control c)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void removeAll()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// control interface delegates to a managed control
|
||||
|
||||
}
|
||||
88
src/lwjgl/java/javazoom/jl/decoder/Obuffer.java
Normal file
88
src/lwjgl/java/javazoom/jl/decoder/Obuffer.java
Normal file
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* 11/19/04 1.0 moved to LGPL.
|
||||
* 12/12/99 Added appendSamples() method for efficiency. MDM.
|
||||
* 15/02/99 ,Java Conversion by E.B ,ebsp@iname.com, JavaLayer
|
||||
*
|
||||
* Declarations for output buffer, includes operating system
|
||||
* implementation of the virtual Obuffer. Optional routines
|
||||
* enabling seeks and stops added by Jeff Tsay.
|
||||
*
|
||||
* @(#) obuffer.h 1.8, last edit: 6/15/94 16:51:56
|
||||
* @(#) Copyright (C) 1993, 1994 Tobias Bading (bading@cs.tu-berlin.de)
|
||||
* @(#) Berlin University of Technology
|
||||
*
|
||||
* Idea and first implementation for u-law output with fast downsampling by
|
||||
* Jim Boucher (jboucher@flash.bu.edu)
|
||||
*
|
||||
* LinuxObuffer class written by
|
||||
* Louis P. Kruger (lpkruger@phoenix.princeton.edu)
|
||||
*-----------------------------------------------------------------------
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library General Public License as published
|
||||
* by the Free Software Foundation; either version 2 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 Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
package javazoom.jl.decoder;
|
||||
|
||||
/**
|
||||
* Base Class for audio output.
|
||||
*/
|
||||
public abstract class Obuffer
|
||||
{
|
||||
public static final int OBUFFERSIZE = 2 * 1152; // max. 2 * 1152 samples per frame
|
||||
public static final int MAXCHANNELS = 2; // max. number of channels
|
||||
|
||||
/**
|
||||
* Takes a 16 Bit PCM sample.
|
||||
*/
|
||||
public abstract void append(int channel, short value);
|
||||
|
||||
/**
|
||||
* Accepts 32 new PCM samples.
|
||||
*/
|
||||
public void appendSamples(int channel, float[] f)
|
||||
{
|
||||
short s;
|
||||
for (int i=0; i<32;)
|
||||
{
|
||||
s = clip(f[i++]);
|
||||
append(channel, s);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clip Sample to 16 Bits
|
||||
*/
|
||||
private final short clip(float sample)
|
||||
{
|
||||
return ((sample > 32767.0f) ? 32767 :
|
||||
((sample < -32768.0f) ? -32768 :
|
||||
(short) sample));
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the samples to the file or directly to the audio hardware.
|
||||
*/
|
||||
public abstract void write_buffer(int val);
|
||||
public abstract void close();
|
||||
|
||||
/**
|
||||
* Clears all data in the buffer (for seeking).
|
||||
*/
|
||||
public abstract void clear_buffer();
|
||||
|
||||
/**
|
||||
* Notify the buffer that the user has stopped the stream.
|
||||
*/
|
||||
public abstract void set_stop_flag();
|
||||
}
|
||||
143
src/lwjgl/java/javazoom/jl/decoder/OutputChannels.java
Normal file
143
src/lwjgl/java/javazoom/jl/decoder/OutputChannels.java
Normal file
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* 11/19/04 1.0 moved to LGPL.
|
||||
* 12/12/99 Initial implementation. mdm@techie.com.
|
||||
*-----------------------------------------------------------------------
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library General Public License as published
|
||||
* by the Free Software Foundation; either version 2 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 Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
package javazoom.jl.decoder;
|
||||
|
||||
|
||||
/**
|
||||
* A Type-safe representation of the the supported output channel
|
||||
* constants.
|
||||
*
|
||||
* This class is immutable and, hence, is thread safe.
|
||||
*
|
||||
* @author Mat McGowan 12/12/99
|
||||
* @since 0.0.7
|
||||
*/
|
||||
public class OutputChannels
|
||||
{
|
||||
/**
|
||||
* Flag to indicate output should include both channels.
|
||||
*/
|
||||
public static final int BOTH_CHANNELS = 0;
|
||||
|
||||
/**
|
||||
* Flag to indicate output should include the left channel only.
|
||||
*/
|
||||
public static final int LEFT_CHANNEL = 1;
|
||||
|
||||
/**
|
||||
* Flag to indicate output should include the right channel only.
|
||||
*/
|
||||
public static final int RIGHT_CHANNEL = 2;
|
||||
|
||||
/**
|
||||
* Flag to indicate output is mono.
|
||||
*/
|
||||
public static final int DOWNMIX_CHANNELS = 3;
|
||||
|
||||
|
||||
public static final OutputChannels LEFT = new OutputChannels(LEFT_CHANNEL);
|
||||
public static final OutputChannels RIGHT = new OutputChannels(RIGHT_CHANNEL);
|
||||
public static final OutputChannels BOTH = new OutputChannels(BOTH_CHANNELS);
|
||||
public static final OutputChannels DOWNMIX = new OutputChannels(DOWNMIX_CHANNELS);
|
||||
|
||||
|
||||
private /*final*/ int outputChannels;
|
||||
|
||||
/**
|
||||
* Creates an <code>OutputChannels</code> instance
|
||||
* corresponding to the given channel code.
|
||||
*
|
||||
* @param code one of the OutputChannels channel code constants.
|
||||
*
|
||||
* @throws IllegalArgumentException if code is not a valid
|
||||
* channel code.
|
||||
*/
|
||||
public static OutputChannels fromInt(int code)
|
||||
{
|
||||
switch (code)
|
||||
{
|
||||
case LEFT_CHANNEL:
|
||||
return LEFT;
|
||||
case RIGHT_CHANNEL:
|
||||
return RIGHT;
|
||||
case BOTH_CHANNELS:
|
||||
return BOTH;
|
||||
case DOWNMIX_CHANNELS:
|
||||
return DOWNMIX;
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid channel code: "+code);
|
||||
}
|
||||
}
|
||||
|
||||
private OutputChannels(int channels)
|
||||
{
|
||||
outputChannels = channels;
|
||||
|
||||
if (channels<0 || channels>3)
|
||||
throw new IllegalArgumentException("channels");
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the code representing the desired output channels.
|
||||
* Will be one of LEFT_CHANNEL, RIGHT_CHANNEL, BOTH_CHANNELS
|
||||
* or DOWNMIX_CHANNELS.
|
||||
*
|
||||
* @return the channel code represented by this instance.
|
||||
*/
|
||||
public int getChannelsOutputCode()
|
||||
{
|
||||
return outputChannels;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the number of output channels represented
|
||||
* by this channel output type.
|
||||
*
|
||||
* @return The number of output channels for this channel output
|
||||
* type. This will be 2 for BOTH_CHANNELS only, and 1
|
||||
* for all other types.
|
||||
*/
|
||||
public int getChannelCount()
|
||||
{
|
||||
int count = (outputChannels==BOTH_CHANNELS) ? 2 : 1;
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
boolean equals = false;
|
||||
|
||||
if (o instanceof OutputChannels)
|
||||
{
|
||||
OutputChannels oc = (OutputChannels)o;
|
||||
equals = (oc.outputChannels == outputChannels);
|
||||
}
|
||||
|
||||
return equals;
|
||||
}
|
||||
|
||||
public int hashCode()
|
||||
{
|
||||
return outputChannels;
|
||||
}
|
||||
|
||||
}
|
||||
132
src/lwjgl/java/javazoom/jl/decoder/SampleBuffer.java
Normal file
132
src/lwjgl/java/javazoom/jl/decoder/SampleBuffer.java
Normal file
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* 11/19/04 1.0 moved to LGPL.
|
||||
*
|
||||
* 12/12/99 Initial Version based on FileObuffer. mdm@techie.com.
|
||||
*
|
||||
* FileObuffer:
|
||||
* 15/02/99 Java Conversion by E.B ,javalayer@javazoom.net
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library General Public License as published
|
||||
* by the Free Software Foundation; either version 2 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 Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
package javazoom.jl.decoder;
|
||||
|
||||
/**
|
||||
* The <code>SampleBuffer</code> class implements an output buffer
|
||||
* that provides storage for a fixed size block of samples.
|
||||
*/
|
||||
public class SampleBuffer extends Obuffer
|
||||
{
|
||||
private short[] buffer;
|
||||
private int[] bufferp;
|
||||
private int channels;
|
||||
private int frequency;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public SampleBuffer(int sample_frequency, int number_of_channels)
|
||||
{
|
||||
buffer = new short[OBUFFERSIZE];
|
||||
bufferp = new int[MAXCHANNELS];
|
||||
channels = number_of_channels;
|
||||
frequency = sample_frequency;
|
||||
|
||||
for (int i = 0; i < number_of_channels; ++i)
|
||||
bufferp[i] = (short)i;
|
||||
|
||||
}
|
||||
|
||||
public int getChannelCount()
|
||||
{
|
||||
return this.channels;
|
||||
}
|
||||
|
||||
public int getSampleFrequency()
|
||||
{
|
||||
return this.frequency;
|
||||
}
|
||||
|
||||
public short[] getBuffer()
|
||||
{
|
||||
return this.buffer;
|
||||
}
|
||||
|
||||
public int getBufferLength()
|
||||
{
|
||||
return bufferp[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a 16 Bit PCM sample.
|
||||
*/
|
||||
public void append(int channel, short value)
|
||||
{
|
||||
buffer[bufferp[channel]] = value;
|
||||
bufferp[channel] += channels;
|
||||
}
|
||||
|
||||
public void appendSamples(int channel, float[] f)
|
||||
{
|
||||
int pos = bufferp[channel];
|
||||
|
||||
short s;
|
||||
float fs;
|
||||
for (int i=0; i<32;)
|
||||
{
|
||||
fs = f[i++];
|
||||
fs = (fs>32767.0f ? 32767.0f
|
||||
: (fs < -32767.0f ? -32767.0f : fs));
|
||||
|
||||
s = (short)fs;
|
||||
buffer[pos] = s;
|
||||
pos += channels;
|
||||
}
|
||||
|
||||
bufferp[channel] = pos;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Write the samples to the file (Random Access).
|
||||
*/
|
||||
public void write_buffer(int val)
|
||||
{
|
||||
|
||||
//for (int i = 0; i < channels; ++i)
|
||||
// bufferp[i] = (short)i;
|
||||
|
||||
}
|
||||
|
||||
public void close()
|
||||
{}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public void clear_buffer()
|
||||
{
|
||||
for (int i = 0; i < channels; ++i)
|
||||
bufferp[i] = (short)i;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public void set_stop_flag()
|
||||
{}
|
||||
}
|
||||
49
src/lwjgl/java/javazoom/jl/decoder/Source.java
Normal file
49
src/lwjgl/java/javazoom/jl/decoder/Source.java
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 11/19/04 1.0 moved to LGPL.
|
||||
*-----------------------------------------------------------------------
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library General Public License as published
|
||||
* by the Free Software Foundation; either version 2 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 Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
package javazoom.jl.decoder;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Work in progress.
|
||||
*
|
||||
* Class to describe a seekable data source.
|
||||
*
|
||||
*/
|
||||
public interface Source
|
||||
{
|
||||
|
||||
public static final long LENGTH_UNKNOWN = -1;
|
||||
|
||||
public int read(byte[] b, int offs, int len)
|
||||
throws IOException;
|
||||
|
||||
|
||||
public boolean willReadBlock();
|
||||
|
||||
public boolean isSeekable();
|
||||
|
||||
public long length();
|
||||
|
||||
public long tell();
|
||||
|
||||
public long seek(long pos);
|
||||
|
||||
}
|
||||
1815
src/lwjgl/java/javazoom/jl/decoder/SynthesisFilter.java
Normal file
1815
src/lwjgl/java/javazoom/jl/decoder/SynthesisFilter.java
Normal file
File diff suppressed because it is too large
Load Diff
BIN
src/lwjgl/java/javazoom/jl/decoder/au2lin.ser
Normal file
BIN
src/lwjgl/java/javazoom/jl/decoder/au2lin.ser
Normal file
Binary file not shown.
600
src/lwjgl/java/javazoom/jl/decoder/huffcodetab.java
Normal file
600
src/lwjgl/java/javazoom/jl/decoder/huffcodetab.java
Normal file
@@ -0,0 +1,600 @@
|
||||
/*
|
||||
* 11/19/04 1.0 moved to LGPL.
|
||||
* 16/11/99 Renamed class, added javadoc, and changed table
|
||||
* name from String to 3 chars. mdm@techie.com
|
||||
* 02/15/99 Java Conversion by E.B, javalayer@javazoom.net
|
||||
*
|
||||
* 04/19/97 : Adapted from the ISO MPEG Audio Subgroup Software Simulation
|
||||
* Group's public c source for its MPEG audio decoder. Miscellaneous
|
||||
* changes by Jeff Tsay (ctsay@pasteur.eecs.berkeley.edu).
|
||||
*-----------------------------------------------------------------------
|
||||
* Copyright (c) 1991 MPEG/audio software simulation group, All Rights Reserved
|
||||
* MPEG/audio coding/decoding software, work in progress
|
||||
* NOT for public distribution until verified and approved by the
|
||||
* MPEG/audio committee. For further information, please contact
|
||||
* Davis Pan, 508-493-2241, e-mail: pan@3d.enet.dec.com
|
||||
*
|
||||
* VERSION 4.1
|
||||
* changes made since last update:
|
||||
* date programmers comment
|
||||
* 27.2.92 F.O.Witte (ITT Intermetall)
|
||||
* 8/24/93 M. Iwadare Changed for 1 pass decoding.
|
||||
* 7/14/94 J. Koller useless 'typedef' before huffcodetab removed
|
||||
*-----------------------------------------------------------------------
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library General Public License as published
|
||||
* by the Free Software Foundation; either version 2 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 Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
package javazoom.jl.decoder;
|
||||
|
||||
/**
|
||||
* Class that implements a Huffman decoder.
|
||||
*/
|
||||
final class huffcodetab
|
||||
{
|
||||
private static final int MXOFF=250;
|
||||
private static final int HTN=34;
|
||||
|
||||
private char tablename0 = ' '; /* string, containing table_description */
|
||||
private char tablename1 = ' '; /* string, containing table_description */
|
||||
private char tablename2 = ' '; /* string, containing table_description */
|
||||
|
||||
private int xlen; /* max. x-index+ */
|
||||
private int ylen; /* max. y-index+ */
|
||||
private int linbits; /* number of linbits */
|
||||
private int linmax; /* max number to be stored in linbits */
|
||||
private int ref; /* a positive value indicates a reference */
|
||||
private int[] table=null; /* pointer to array[xlen][ylen] */
|
||||
private int[] hlen=null; /* pointer to array[xlen][ylen] */
|
||||
private int[][] val=null; /* decoder tree */
|
||||
private int treelen; /* length of decoder tree */
|
||||
|
||||
private static int ValTab0[][] = {
|
||||
{0,0} // dummy
|
||||
};
|
||||
|
||||
private static int ValTab1[][] = {
|
||||
{2,1},{0,0},{2,1},{0,16},{2,1},{0,1},{0,17},
|
||||
};
|
||||
|
||||
private static int ValTab2[][] = {
|
||||
{2,1},{0,0},{4,1},{2,1},{0,16},{0,1},{2,1},{0,17},{4,1},{2,1},
|
||||
{0,32},{0,33},{2,1},{0,18},{2,1},{0,2},{0,34},
|
||||
};
|
||||
|
||||
private static int ValTab3[][] = {
|
||||
{4,1},{2,1},{0,0},{0,1},{2,1},{0,17},{2,1},{0,16},{4,1},{2,1},
|
||||
{0,32},{0,33},{2,1},{0,18},{2,1},{0,2},{0,34},
|
||||
};
|
||||
|
||||
private static int ValTab4[][] = {{0,0}}; // dummy
|
||||
|
||||
private static int ValTab5[][] = {
|
||||
{2,1},{0,0},{4,1},{2,1},{0,16},{0,1},{2,1},{0,17},{8,1},{4,1},
|
||||
{2,1},{0,32},{0,2},{2,1},{0,33},{0,18},{8,1},{4,1},{2,1},{0,34},
|
||||
{0,48},{2,1},{0,3},{0,19},{2,1},{0,49},{2,1},{0,50},{2,1},{0,35},
|
||||
{0,51},
|
||||
};
|
||||
|
||||
private static int ValTab6[][] = {
|
||||
{6,1},{4,1},{2,1},{0,0},{0,16},{0,17},{6,1},{2,1},{0,1},{2,1},
|
||||
{0,32},{0,33},{6,1},{2,1},{0,18},{2,1},{0,2},{0,34},{4,1},{2,1},
|
||||
{0,49},{0,19},{4,1},{2,1},{0,48},{0,50},{2,1},{0,35},{2,1},{0,3},
|
||||
{0,51},
|
||||
};
|
||||
|
||||
private static int ValTab7[][] = {
|
||||
{2,1},{0,0},{4,1},{2,1},{0,16},{0,1},{8,1},{2,1},{0,17},{4,1},
|
||||
{2,1},{0,32},{0,2},{0,33},{18,1},{6,1},{2,1},{0,18},{2,1},{0,34},
|
||||
{0,48},{4,1},{2,1},{0,49},{0,19},{4,1},{2,1},{0,3},{0,50},{2,1},
|
||||
{0,35},{0,4},{10,1},{4,1},{2,1},{0,64},{0,65},{2,1},{0,20},{2,1},
|
||||
{0,66},{0,36},{12,1},{6,1},{4,1},{2,1},{0,51},{0,67},{0,80},{4,1},
|
||||
{2,1},{0,52},{0,5},{0,81},{6,1},{2,1},{0,21},{2,1},{0,82},{0,37},
|
||||
{4,1},{2,1},{0,68},{0,53},{4,1},{2,1},{0,83},{0,84},{2,1},{0,69},
|
||||
{0,85},
|
||||
};
|
||||
|
||||
private static int ValTab8[][] = {
|
||||
{6,1},{2,1},{0,0},{2,1},{0,16},{0,1},{2,1},{0,17},{4,1},{2,1},
|
||||
{0,33},{0,18},{14,1},{4,1},{2,1},{0,32},{0,2},{2,1},{0,34},{4,1},
|
||||
{2,1},{0,48},{0,3},{2,1},{0,49},{0,19},{14,1},{8,1},{4,1},{2,1},
|
||||
{0,50},{0,35},{2,1},{0,64},{0,4},{2,1},{0,65},{2,1},{0,20},{0,66},
|
||||
{12,1},{6,1},{2,1},{0,36},{2,1},{0,51},{0,80},{4,1},{2,1},{0,67},
|
||||
{0,52},{0,81},{6,1},{2,1},{0,21},{2,1},{0,5},{0,82},{6,1},{2,1},
|
||||
{0,37},{2,1},{0,68},{0,53},{2,1},{0,83},{2,1},{0,69},{2,1},{0,84},
|
||||
{0,85},
|
||||
};
|
||||
|
||||
private static int ValTab9[][] = {
|
||||
{8,1},{4,1},{2,1},{0,0},{0,16},{2,1},{0,1},{0,17},{10,1},{4,1},
|
||||
{2,1},{0,32},{0,33},{2,1},{0,18},{2,1},{0,2},{0,34},{12,1},{6,1},
|
||||
{4,1},{2,1},{0,48},{0,3},{0,49},{2,1},{0,19},{2,1},{0,50},{0,35},
|
||||
{12,1},{4,1},{2,1},{0,65},{0,20},{4,1},{2,1},{0,64},{0,51},{2,1},
|
||||
{0,66},{0,36},{10,1},{6,1},{4,1},{2,1},{0,4},{0,80},{0,67},{2,1},
|
||||
{0,52},{0,81},{8,1},{4,1},{2,1},{0,21},{0,82},{2,1},{0,37},{0,68},
|
||||
{6,1},{4,1},{2,1},{0,5},{0,84},{0,83},{2,1},{0,53},{2,1},{0,69},
|
||||
{0,85},
|
||||
};
|
||||
|
||||
private static int ValTab10[][] = {
|
||||
{2,1},{0,0},{4,1},{2,1},{0,16},{0,1},{10,1},{2,1},{0,17},{4,1},
|
||||
{2,1},{0,32},{0,2},{2,1},{0,33},{0,18},{28,1},{8,1},{4,1},{2,1},
|
||||
{0,34},{0,48},{2,1},{0,49},{0,19},{8,1},{4,1},{2,1},{0,3},{0,50},
|
||||
{2,1},{0,35},{0,64},{4,1},{2,1},{0,65},{0,20},{4,1},{2,1},{0,4},
|
||||
{0,51},{2,1},{0,66},{0,36},{28,1},{10,1},{6,1},{4,1},{2,1},{0,80},
|
||||
{0,5},{0,96},{2,1},{0,97},{0,22},{12,1},{6,1},{4,1},{2,1},{0,67},
|
||||
{0,52},{0,81},{2,1},{0,21},{2,1},{0,82},{0,37},{4,1},{2,1},{0,38},
|
||||
{0,54},{0,113},{20,1},{8,1},{2,1},{0,23},{4,1},{2,1},{0,68},{0,83},
|
||||
{0,6},{6,1},{4,1},{2,1},{0,53},{0,69},{0,98},{2,1},{0,112},{2,1},
|
||||
{0,7},{0,100},{14,1},{4,1},{2,1},{0,114},{0,39},{6,1},{2,1},{0,99},
|
||||
{2,1},{0,84},{0,85},{2,1},{0,70},{0,115},{8,1},{4,1},{2,1},{0,55},
|
||||
{0,101},{2,1},{0,86},{0,116},{6,1},{2,1},{0,71},{2,1},{0,102},{0,117},
|
||||
{4,1},{2,1},{0,87},{0,118},{2,1},{0,103},{0,119},
|
||||
};
|
||||
|
||||
private static int ValTab11[][] = {
|
||||
{6,1},{2,1},{0,0},{2,1},{0,16},{0,1},{8,1},{2,1},{0,17},{4,1},
|
||||
{2,1},{0,32},{0,2},{0,18},{24,1},{8,1},{2,1},{0,33},{2,1},{0,34},
|
||||
{2,1},{0,48},{0,3},{4,1},{2,1},{0,49},{0,19},{4,1},{2,1},{0,50},
|
||||
{0,35},{4,1},{2,1},{0,64},{0,4},{2,1},{0,65},{0,20},{30,1},{16,1},
|
||||
{10,1},{4,1},{2,1},{0,66},{0,36},{4,1},{2,1},{0,51},{0,67},{0,80},
|
||||
{4,1},{2,1},{0,52},{0,81},{0,97},{6,1},{2,1},{0,22},{2,1},{0,6},
|
||||
{0,38},{2,1},{0,98},{2,1},{0,21},{2,1},{0,5},{0,82},{16,1},{10,1},
|
||||
{6,1},{4,1},{2,1},{0,37},{0,68},{0,96},{2,1},{0,99},{0,54},{4,1},
|
||||
{2,1},{0,112},{0,23},{0,113},{16,1},{6,1},{4,1},{2,1},{0,7},{0,100},
|
||||
{0,114},{2,1},{0,39},{4,1},{2,1},{0,83},{0,53},{2,1},{0,84},{0,69},
|
||||
{10,1},{4,1},{2,1},{0,70},{0,115},{2,1},{0,55},{2,1},{0,101},{0,86},
|
||||
{10,1},{6,1},{4,1},{2,1},{0,85},{0,87},{0,116},{2,1},{0,71},{0,102},
|
||||
{4,1},{2,1},{0,117},{0,118},{2,1},{0,103},{0,119},
|
||||
};
|
||||
|
||||
private static int ValTab12[][] = {
|
||||
{12,1},{4,1},{2,1},{0,16},{0,1},{2,1},{0,17},{2,1},{0,0},{2,1},
|
||||
{0,32},{0,2},{16,1},{4,1},{2,1},{0,33},{0,18},{4,1},{2,1},{0,34},
|
||||
{0,49},{2,1},{0,19},{2,1},{0,48},{2,1},{0,3},{0,64},{26,1},{8,1},
|
||||
{4,1},{2,1},{0,50},{0,35},{2,1},{0,65},{0,51},{10,1},{4,1},{2,1},
|
||||
{0,20},{0,66},{2,1},{0,36},{2,1},{0,4},{0,80},{4,1},{2,1},{0,67},
|
||||
{0,52},{2,1},{0,81},{0,21},{28,1},{14,1},{8,1},{4,1},{2,1},{0,82},
|
||||
{0,37},{2,1},{0,83},{0,53},{4,1},{2,1},{0,96},{0,22},{0,97},{4,1},
|
||||
{2,1},{0,98},{0,38},{6,1},{4,1},{2,1},{0,5},{0,6},{0,68},{2,1},
|
||||
{0,84},{0,69},{18,1},{10,1},{4,1},{2,1},{0,99},{0,54},{4,1},{2,1},
|
||||
{0,112},{0,7},{0,113},{4,1},{2,1},{0,23},{0,100},{2,1},{0,70},{0,114},
|
||||
{10,1},{6,1},{2,1},{0,39},{2,1},{0,85},{0,115},{2,1},{0,55},{0,86},
|
||||
{8,1},{4,1},{2,1},{0,101},{0,116},{2,1},{0,71},{0,102},{4,1},{2,1},
|
||||
{0,117},{0,87},{2,1},{0,118},{2,1},{0,103},{0,119},
|
||||
};
|
||||
|
||||
private static int ValTab13[][] = {
|
||||
{2,1},{0,0},{6,1},{2,1},{0,16},{2,1},{0,1},{0,17},{28,1},{8,1},
|
||||
{4,1},{2,1},{0,32},{0,2},{2,1},{0,33},{0,18},{8,1},{4,1},{2,1},
|
||||
{0,34},{0,48},{2,1},{0,3},{0,49},{6,1},{2,1},{0,19},{2,1},{0,50},
|
||||
{0,35},{4,1},{2,1},{0,64},{0,4},{0,65},{70,1},{28,1},{14,1},{6,1},
|
||||
{2,1},{0,20},{2,1},{0,51},{0,66},{4,1},{2,1},{0,36},{0,80},{2,1},
|
||||
{0,67},{0,52},{4,1},{2,1},{0,81},{0,21},{4,1},{2,1},{0,5},{0,82},
|
||||
{2,1},{0,37},{2,1},{0,68},{0,83},{14,1},{8,1},{4,1},{2,1},{0,96},
|
||||
{0,6},{2,1},{0,97},{0,22},{4,1},{2,1},{0,128},{0,8},{0,129},{16,1},
|
||||
{8,1},{4,1},{2,1},{0,53},{0,98},{2,1},{0,38},{0,84},{4,1},{2,1},
|
||||
{0,69},{0,99},{2,1},{0,54},{0,112},{6,1},{4,1},{2,1},{0,7},{0,85},
|
||||
{0,113},{2,1},{0,23},{2,1},{0,39},{0,55},{72,1},{24,1},{12,1},{4,1},
|
||||
{2,1},{0,24},{0,130},{2,1},{0,40},{4,1},{2,1},{0,100},{0,70},{0,114},
|
||||
{8,1},{4,1},{2,1},{0,132},{0,72},{2,1},{0,144},{0,9},{2,1},{0,145},
|
||||
{0,25},{24,1},{14,1},{8,1},{4,1},{2,1},{0,115},{0,101},{2,1},{0,86},
|
||||
{0,116},{4,1},{2,1},{0,71},{0,102},{0,131},{6,1},{2,1},{0,56},{2,1},
|
||||
{0,117},{0,87},{2,1},{0,146},{0,41},{14,1},{8,1},{4,1},{2,1},{0,103},
|
||||
{0,133},{2,1},{0,88},{0,57},{2,1},{0,147},{2,1},{0,73},{0,134},{6,1},
|
||||
{2,1},{0,160},{2,1},{0,104},{0,10},{2,1},{0,161},{0,26},{68,1},{24,1},
|
||||
{12,1},{4,1},{2,1},{0,162},{0,42},{4,1},{2,1},{0,149},{0,89},{2,1},
|
||||
{0,163},{0,58},{8,1},{4,1},{2,1},{0,74},{0,150},{2,1},{0,176},{0,11},
|
||||
{2,1},{0,177},{0,27},{20,1},{8,1},{2,1},{0,178},{4,1},{2,1},{0,118},
|
||||
{0,119},{0,148},{6,1},{4,1},{2,1},{0,135},{0,120},{0,164},{4,1},{2,1},
|
||||
{0,105},{0,165},{0,43},{12,1},{6,1},{4,1},{2,1},{0,90},{0,136},{0,179},
|
||||
{2,1},{0,59},{2,1},{0,121},{0,166},{6,1},{4,1},{2,1},{0,106},{0,180},
|
||||
{0,192},{4,1},{2,1},{0,12},{0,152},{0,193},{60,1},{22,1},{10,1},{6,1},
|
||||
{2,1},{0,28},{2,1},{0,137},{0,181},{2,1},{0,91},{0,194},{4,1},{2,1},
|
||||
{0,44},{0,60},{4,1},{2,1},{0,182},{0,107},{2,1},{0,196},{0,76},{16,1},
|
||||
{8,1},{4,1},{2,1},{0,168},{0,138},{2,1},{0,208},{0,13},{2,1},{0,209},
|
||||
{2,1},{0,75},{2,1},{0,151},{0,167},{12,1},{6,1},{2,1},{0,195},{2,1},
|
||||
{0,122},{0,153},{4,1},{2,1},{0,197},{0,92},{0,183},{4,1},{2,1},{0,29},
|
||||
{0,210},{2,1},{0,45},{2,1},{0,123},{0,211},{52,1},{28,1},{12,1},{4,1},
|
||||
{2,1},{0,61},{0,198},{4,1},{2,1},{0,108},{0,169},{2,1},{0,154},{0,212},
|
||||
{8,1},{4,1},{2,1},{0,184},{0,139},{2,1},{0,77},{0,199},{4,1},{2,1},
|
||||
{0,124},{0,213},{2,1},{0,93},{0,224},{10,1},{4,1},{2,1},{0,225},{0,30},
|
||||
{4,1},{2,1},{0,14},{0,46},{0,226},{8,1},{4,1},{2,1},{0,227},{0,109},
|
||||
{2,1},{0,140},{0,228},{4,1},{2,1},{0,229},{0,186},{0,240},{38,1},{16,1},
|
||||
{4,1},{2,1},{0,241},{0,31},{6,1},{4,1},{2,1},{0,170},{0,155},{0,185},
|
||||
{2,1},{0,62},{2,1},{0,214},{0,200},{12,1},{6,1},{2,1},{0,78},{2,1},
|
||||
{0,215},{0,125},{2,1},{0,171},{2,1},{0,94},{0,201},{6,1},{2,1},{0,15},
|
||||
{2,1},{0,156},{0,110},{2,1},{0,242},{0,47},{32,1},{16,1},{6,1},{4,1},
|
||||
{2,1},{0,216},{0,141},{0,63},{6,1},{2,1},{0,243},{2,1},{0,230},{0,202},
|
||||
{2,1},{0,244},{0,79},{8,1},{4,1},{2,1},{0,187},{0,172},{2,1},{0,231},
|
||||
{0,245},{4,1},{2,1},{0,217},{0,157},{2,1},{0,95},{0,232},{30,1},{12,1},
|
||||
{6,1},{2,1},{0,111},{2,1},{0,246},{0,203},{4,1},{2,1},{0,188},{0,173},
|
||||
{0,218},{8,1},{2,1},{0,247},{4,1},{2,1},{0,126},{0,127},{0,142},{6,1},
|
||||
{4,1},{2,1},{0,158},{0,174},{0,204},{2,1},{0,248},{0,143},{18,1},{8,1},
|
||||
{4,1},{2,1},{0,219},{0,189},{2,1},{0,234},{0,249},{4,1},{2,1},{0,159},
|
||||
{0,235},{2,1},{0,190},{2,1},{0,205},{0,250},{14,1},{4,1},{2,1},{0,221},
|
||||
{0,236},{6,1},{4,1},{2,1},{0,233},{0,175},{0,220},{2,1},{0,206},{0,251},
|
||||
{8,1},{4,1},{2,1},{0,191},{0,222},{2,1},{0,207},{0,238},{4,1},{2,1},
|
||||
{0,223},{0,239},{2,1},{0,255},{2,1},{0,237},{2,1},{0,253},{2,1},{0,252},
|
||||
{0,254},
|
||||
};
|
||||
|
||||
private static int ValTab14[][] = {
|
||||
{0,0} // dummy
|
||||
};
|
||||
|
||||
private static int ValTab15[][] = {
|
||||
{16,1},{6,1},{2,1},{0,0},{2,1},{0,16},{0,1},{2,1},{0,17},{4,1},
|
||||
{2,1},{0,32},{0,2},{2,1},{0,33},{0,18},{50,1},{16,1},{6,1},{2,1},
|
||||
{0,34},{2,1},{0,48},{0,49},{6,1},{2,1},{0,19},{2,1},{0,3},{0,64},
|
||||
{2,1},{0,50},{0,35},{14,1},{6,1},{4,1},{2,1},{0,4},{0,20},{0,65},
|
||||
{4,1},{2,1},{0,51},{0,66},{2,1},{0,36},{0,67},{10,1},{6,1},{2,1},
|
||||
{0,52},{2,1},{0,80},{0,5},{2,1},{0,81},{0,21},{4,1},{2,1},{0,82},
|
||||
{0,37},{4,1},{2,1},{0,68},{0,83},{0,97},{90,1},{36,1},{18,1},{10,1},
|
||||
{6,1},{2,1},{0,53},{2,1},{0,96},{0,6},{2,1},{0,22},{0,98},{4,1},
|
||||
{2,1},{0,38},{0,84},{2,1},{0,69},{0,99},{10,1},{6,1},{2,1},{0,54},
|
||||
{2,1},{0,112},{0,7},{2,1},{0,113},{0,85},{4,1},{2,1},{0,23},{0,100},
|
||||
{2,1},{0,114},{0,39},{24,1},{16,1},{8,1},{4,1},{2,1},{0,70},{0,115},
|
||||
{2,1},{0,55},{0,101},{4,1},{2,1},{0,86},{0,128},{2,1},{0,8},{0,116},
|
||||
{4,1},{2,1},{0,129},{0,24},{2,1},{0,130},{0,40},{16,1},{8,1},{4,1},
|
||||
{2,1},{0,71},{0,102},{2,1},{0,131},{0,56},{4,1},{2,1},{0,117},{0,87},
|
||||
{2,1},{0,132},{0,72},{6,1},{4,1},{2,1},{0,144},{0,25},{0,145},{4,1},
|
||||
{2,1},{0,146},{0,118},{2,1},{0,103},{0,41},{92,1},{36,1},{18,1},{10,1},
|
||||
{4,1},{2,1},{0,133},{0,88},{4,1},{2,1},{0,9},{0,119},{0,147},{4,1},
|
||||
{2,1},{0,57},{0,148},{2,1},{0,73},{0,134},{10,1},{6,1},{2,1},{0,104},
|
||||
{2,1},{0,160},{0,10},{2,1},{0,161},{0,26},{4,1},{2,1},{0,162},{0,42},
|
||||
{2,1},{0,149},{0,89},{26,1},{14,1},{6,1},{2,1},{0,163},{2,1},{0,58},
|
||||
{0,135},{4,1},{2,1},{0,120},{0,164},{2,1},{0,74},{0,150},{6,1},{4,1},
|
||||
{2,1},{0,105},{0,176},{0,177},{4,1},{2,1},{0,27},{0,165},{0,178},{14,1},
|
||||
{8,1},{4,1},{2,1},{0,90},{0,43},{2,1},{0,136},{0,151},{2,1},{0,179},
|
||||
{2,1},{0,121},{0,59},{8,1},{4,1},{2,1},{0,106},{0,180},{2,1},{0,75},
|
||||
{0,193},{4,1},{2,1},{0,152},{0,137},{2,1},{0,28},{0,181},{80,1},{34,1},
|
||||
{16,1},{6,1},{4,1},{2,1},{0,91},{0,44},{0,194},{6,1},{4,1},{2,1},
|
||||
{0,11},{0,192},{0,166},{2,1},{0,167},{0,122},{10,1},{4,1},{2,1},{0,195},
|
||||
{0,60},{4,1},{2,1},{0,12},{0,153},{0,182},{4,1},{2,1},{0,107},{0,196},
|
||||
{2,1},{0,76},{0,168},{20,1},{10,1},{4,1},{2,1},{0,138},{0,197},{4,1},
|
||||
{2,1},{0,208},{0,92},{0,209},{4,1},{2,1},{0,183},{0,123},{2,1},{0,29},
|
||||
{2,1},{0,13},{0,45},{12,1},{4,1},{2,1},{0,210},{0,211},{4,1},{2,1},
|
||||
{0,61},{0,198},{2,1},{0,108},{0,169},{6,1},{4,1},{2,1},{0,154},{0,184},
|
||||
{0,212},{4,1},{2,1},{0,139},{0,77},{2,1},{0,199},{0,124},{68,1},{34,1},
|
||||
{18,1},{10,1},{4,1},{2,1},{0,213},{0,93},{4,1},{2,1},{0,224},{0,14},
|
||||
{0,225},{4,1},{2,1},{0,30},{0,226},{2,1},{0,170},{0,46},{8,1},{4,1},
|
||||
{2,1},{0,185},{0,155},{2,1},{0,227},{0,214},{4,1},{2,1},{0,109},{0,62},
|
||||
{2,1},{0,200},{0,140},{16,1},{8,1},{4,1},{2,1},{0,228},{0,78},{2,1},
|
||||
{0,215},{0,125},{4,1},{2,1},{0,229},{0,186},{2,1},{0,171},{0,94},{8,1},
|
||||
{4,1},{2,1},{0,201},{0,156},{2,1},{0,241},{0,31},{6,1},{4,1},{2,1},
|
||||
{0,240},{0,110},{0,242},{2,1},{0,47},{0,230},{38,1},{18,1},{8,1},{4,1},
|
||||
{2,1},{0,216},{0,243},{2,1},{0,63},{0,244},{6,1},{2,1},{0,79},{2,1},
|
||||
{0,141},{0,217},{2,1},{0,187},{0,202},{8,1},{4,1},{2,1},{0,172},{0,231},
|
||||
{2,1},{0,126},{0,245},{8,1},{4,1},{2,1},{0,157},{0,95},{2,1},{0,232},
|
||||
{0,142},{2,1},{0,246},{0,203},{34,1},{18,1},{10,1},{6,1},{4,1},{2,1},
|
||||
{0,15},{0,174},{0,111},{2,1},{0,188},{0,218},{4,1},{2,1},{0,173},{0,247},
|
||||
{2,1},{0,127},{0,233},{8,1},{4,1},{2,1},{0,158},{0,204},{2,1},{0,248},
|
||||
{0,143},{4,1},{2,1},{0,219},{0,189},{2,1},{0,234},{0,249},{16,1},{8,1},
|
||||
{4,1},{2,1},{0,159},{0,220},{2,1},{0,205},{0,235},{4,1},{2,1},{0,190},
|
||||
{0,250},{2,1},{0,175},{0,221},{14,1},{6,1},{4,1},{2,1},{0,236},{0,206},
|
||||
{0,251},{4,1},{2,1},{0,191},{0,237},{2,1},{0,222},{0,252},{6,1},{4,1},
|
||||
{2,1},{0,207},{0,253},{0,238},{4,1},{2,1},{0,223},{0,254},{2,1},{0,239},
|
||||
{0,255},
|
||||
};
|
||||
|
||||
private static int ValTab16[][] = {
|
||||
{2,1},{0,0},{6,1},{2,1},{0,16},{2,1},{0,1},{0,17},{42,1},{8,1},
|
||||
{4,1},{2,1},{0,32},{0,2},{2,1},{0,33},{0,18},{10,1},{6,1},{2,1},
|
||||
{0,34},{2,1},{0,48},{0,3},{2,1},{0,49},{0,19},{10,1},{4,1},{2,1},
|
||||
{0,50},{0,35},{4,1},{2,1},{0,64},{0,4},{0,65},{6,1},{2,1},{0,20},
|
||||
{2,1},{0,51},{0,66},{4,1},{2,1},{0,36},{0,80},{2,1},{0,67},{0,52},
|
||||
{138,1},{40,1},{16,1},{6,1},{4,1},{2,1},{0,5},{0,21},{0,81},{4,1},
|
||||
{2,1},{0,82},{0,37},{4,1},{2,1},{0,68},{0,53},{0,83},{10,1},{6,1},
|
||||
{4,1},{2,1},{0,96},{0,6},{0,97},{2,1},{0,22},{0,98},{8,1},{4,1},
|
||||
{2,1},{0,38},{0,84},{2,1},{0,69},{0,99},{4,1},{2,1},{0,54},{0,112},
|
||||
{0,113},{40,1},{18,1},{8,1},{2,1},{0,23},{2,1},{0,7},{2,1},{0,85},
|
||||
{0,100},{4,1},{2,1},{0,114},{0,39},{4,1},{2,1},{0,70},{0,101},{0,115},
|
||||
{10,1},{6,1},{2,1},{0,55},{2,1},{0,86},{0,8},{2,1},{0,128},{0,129},
|
||||
{6,1},{2,1},{0,24},{2,1},{0,116},{0,71},{2,1},{0,130},{2,1},{0,40},
|
||||
{0,102},{24,1},{14,1},{8,1},{4,1},{2,1},{0,131},{0,56},{2,1},{0,117},
|
||||
{0,132},{4,1},{2,1},{0,72},{0,144},{0,145},{6,1},{2,1},{0,25},{2,1},
|
||||
{0,9},{0,118},{2,1},{0,146},{0,41},{14,1},{8,1},{4,1},{2,1},{0,133},
|
||||
{0,88},{2,1},{0,147},{0,57},{4,1},{2,1},{0,160},{0,10},{0,26},{8,1},
|
||||
{2,1},{0,162},{2,1},{0,103},{2,1},{0,87},{0,73},{6,1},{2,1},{0,148},
|
||||
{2,1},{0,119},{0,134},{2,1},{0,161},{2,1},{0,104},{0,149},{220,1},{126,1},
|
||||
{50,1},{26,1},{12,1},{6,1},{2,1},{0,42},{2,1},{0,89},{0,58},{2,1},
|
||||
{0,163},{2,1},{0,135},{0,120},{8,1},{4,1},{2,1},{0,164},{0,74},{2,1},
|
||||
{0,150},{0,105},{4,1},{2,1},{0,176},{0,11},{0,177},{10,1},{4,1},{2,1},
|
||||
{0,27},{0,178},{2,1},{0,43},{2,1},{0,165},{0,90},{6,1},{2,1},{0,179},
|
||||
{2,1},{0,166},{0,106},{4,1},{2,1},{0,180},{0,75},{2,1},{0,12},{0,193},
|
||||
{30,1},{14,1},{6,1},{4,1},{2,1},{0,181},{0,194},{0,44},{4,1},{2,1},
|
||||
{0,167},{0,195},{2,1},{0,107},{0,196},{8,1},{2,1},{0,29},{4,1},{2,1},
|
||||
{0,136},{0,151},{0,59},{4,1},{2,1},{0,209},{0,210},{2,1},{0,45},{0,211},
|
||||
{18,1},{6,1},{4,1},{2,1},{0,30},{0,46},{0,226},{6,1},{4,1},{2,1},
|
||||
{0,121},{0,152},{0,192},{2,1},{0,28},{2,1},{0,137},{0,91},{14,1},{6,1},
|
||||
{2,1},{0,60},{2,1},{0,122},{0,182},{4,1},{2,1},{0,76},{0,153},{2,1},
|
||||
{0,168},{0,138},{6,1},{2,1},{0,13},{2,1},{0,197},{0,92},{4,1},{2,1},
|
||||
{0,61},{0,198},{2,1},{0,108},{0,154},{88,1},{86,1},{36,1},{16,1},{8,1},
|
||||
{4,1},{2,1},{0,139},{0,77},{2,1},{0,199},{0,124},{4,1},{2,1},{0,213},
|
||||
{0,93},{2,1},{0,224},{0,14},{8,1},{2,1},{0,227},{4,1},{2,1},{0,208},
|
||||
{0,183},{0,123},{6,1},{4,1},{2,1},{0,169},{0,184},{0,212},{2,1},{0,225},
|
||||
{2,1},{0,170},{0,185},{24,1},{10,1},{6,1},{4,1},{2,1},{0,155},{0,214},
|
||||
{0,109},{2,1},{0,62},{0,200},{6,1},{4,1},{2,1},{0,140},{0,228},{0,78},
|
||||
{4,1},{2,1},{0,215},{0,229},{2,1},{0,186},{0,171},{12,1},{4,1},{2,1},
|
||||
{0,156},{0,230},{4,1},{2,1},{0,110},{0,216},{2,1},{0,141},{0,187},{8,1},
|
||||
{4,1},{2,1},{0,231},{0,157},{2,1},{0,232},{0,142},{4,1},{2,1},{0,203},
|
||||
{0,188},{0,158},{0,241},{2,1},{0,31},{2,1},{0,15},{0,47},{66,1},{56,1},
|
||||
{2,1},{0,242},{52,1},{50,1},{20,1},{8,1},{2,1},{0,189},{2,1},{0,94},
|
||||
{2,1},{0,125},{0,201},{6,1},{2,1},{0,202},{2,1},{0,172},{0,126},{4,1},
|
||||
{2,1},{0,218},{0,173},{0,204},{10,1},{6,1},{2,1},{0,174},{2,1},{0,219},
|
||||
{0,220},{2,1},{0,205},{0,190},{6,1},{4,1},{2,1},{0,235},{0,237},{0,238},
|
||||
{6,1},{4,1},{2,1},{0,217},{0,234},{0,233},{2,1},{0,222},{4,1},{2,1},
|
||||
{0,221},{0,236},{0,206},{0,63},{0,240},{4,1},{2,1},{0,243},{0,244},{2,1},
|
||||
{0,79},{2,1},{0,245},{0,95},{10,1},{2,1},{0,255},{4,1},{2,1},{0,246},
|
||||
{0,111},{2,1},{0,247},{0,127},{12,1},{6,1},{2,1},{0,143},{2,1},{0,248},
|
||||
{0,249},{4,1},{2,1},{0,159},{0,250},{0,175},{8,1},{4,1},{2,1},{0,251},
|
||||
{0,191},{2,1},{0,252},{0,207},{4,1},{2,1},{0,253},{0,223},{2,1},{0,254},
|
||||
{0,239},
|
||||
};
|
||||
|
||||
private static int ValTab24[][] = {
|
||||
{60,1},{8,1},{4,1},{2,1},{0,0},{0,16},{2,1},{0,1},{0,17},{14,1},
|
||||
{6,1},{4,1},{2,1},{0,32},{0,2},{0,33},{2,1},{0,18},{2,1},{0,34},
|
||||
{2,1},{0,48},{0,3},{14,1},{4,1},{2,1},{0,49},{0,19},{4,1},{2,1},
|
||||
{0,50},{0,35},{4,1},{2,1},{0,64},{0,4},{0,65},{8,1},{4,1},{2,1},
|
||||
{0,20},{0,51},{2,1},{0,66},{0,36},{6,1},{4,1},{2,1},{0,67},{0,52},
|
||||
{0,81},{6,1},{4,1},{2,1},{0,80},{0,5},{0,21},{2,1},{0,82},{0,37},
|
||||
{250,1},{98,1},{34,1},{18,1},{10,1},{4,1},{2,1},{0,68},{0,83},{2,1},
|
||||
{0,53},{2,1},{0,96},{0,6},{4,1},{2,1},{0,97},{0,22},{2,1},{0,98},
|
||||
{0,38},{8,1},{4,1},{2,1},{0,84},{0,69},{2,1},{0,99},{0,54},{4,1},
|
||||
{2,1},{0,113},{0,85},{2,1},{0,100},{0,70},{32,1},{14,1},{6,1},{2,1},
|
||||
{0,114},{2,1},{0,39},{0,55},{2,1},{0,115},{4,1},{2,1},{0,112},{0,7},
|
||||
{0,23},{10,1},{4,1},{2,1},{0,101},{0,86},{4,1},{2,1},{0,128},{0,8},
|
||||
{0,129},{4,1},{2,1},{0,116},{0,71},{2,1},{0,24},{0,130},{16,1},{8,1},
|
||||
{4,1},{2,1},{0,40},{0,102},{2,1},{0,131},{0,56},{4,1},{2,1},{0,117},
|
||||
{0,87},{2,1},{0,132},{0,72},{8,1},{4,1},{2,1},{0,145},{0,25},{2,1},
|
||||
{0,146},{0,118},{4,1},{2,1},{0,103},{0,41},{2,1},{0,133},{0,88},{92,1},
|
||||
{34,1},{16,1},{8,1},{4,1},{2,1},{0,147},{0,57},{2,1},{0,148},{0,73},
|
||||
{4,1},{2,1},{0,119},{0,134},{2,1},{0,104},{0,161},{8,1},{4,1},{2,1},
|
||||
{0,162},{0,42},{2,1},{0,149},{0,89},{4,1},{2,1},{0,163},{0,58},{2,1},
|
||||
{0,135},{2,1},{0,120},{0,74},{22,1},{12,1},{4,1},{2,1},{0,164},{0,150},
|
||||
{4,1},{2,1},{0,105},{0,177},{2,1},{0,27},{0,165},{6,1},{2,1},{0,178},
|
||||
{2,1},{0,90},{0,43},{2,1},{0,136},{0,179},{16,1},{10,1},{6,1},{2,1},
|
||||
{0,144},{2,1},{0,9},{0,160},{2,1},{0,151},{0,121},{4,1},{2,1},{0,166},
|
||||
{0,106},{0,180},{12,1},{6,1},{2,1},{0,26},{2,1},{0,10},{0,176},{2,1},
|
||||
{0,59},{2,1},{0,11},{0,192},{4,1},{2,1},{0,75},{0,193},{2,1},{0,152},
|
||||
{0,137},{67,1},{34,1},{16,1},{8,1},{4,1},{2,1},{0,28},{0,181},{2,1},
|
||||
{0,91},{0,194},{4,1},{2,1},{0,44},{0,167},{2,1},{0,122},{0,195},{10,1},
|
||||
{6,1},{2,1},{0,60},{2,1},{0,12},{0,208},{2,1},{0,182},{0,107},{4,1},
|
||||
{2,1},{0,196},{0,76},{2,1},{0,153},{0,168},{16,1},{8,1},{4,1},{2,1},
|
||||
{0,138},{0,197},{2,1},{0,92},{0,209},{4,1},{2,1},{0,183},{0,123},{2,1},
|
||||
{0,29},{0,210},{9,1},{4,1},{2,1},{0,45},{0,211},{2,1},{0,61},{0,198},
|
||||
{85,250},{4,1},{2,1},{0,108},{0,169},{2,1},{0,154},{0,212},{32,1},{16,1},
|
||||
{8,1},{4,1},{2,1},{0,184},{0,139},{2,1},{0,77},{0,199},{4,1},{2,1},
|
||||
{0,124},{0,213},{2,1},{0,93},{0,225},{8,1},{4,1},{2,1},{0,30},{0,226},
|
||||
{2,1},{0,170},{0,185},{4,1},{2,1},{0,155},{0,227},{2,1},{0,214},{0,109},
|
||||
{20,1},{10,1},{6,1},{2,1},{0,62},{2,1},{0,46},{0,78},{2,1},{0,200},
|
||||
{0,140},{4,1},{2,1},{0,228},{0,215},{4,1},{2,1},{0,125},{0,171},{0,229},
|
||||
{10,1},{4,1},{2,1},{0,186},{0,94},{2,1},{0,201},{2,1},{0,156},{0,110},
|
||||
{8,1},{2,1},{0,230},{2,1},{0,13},{2,1},{0,224},{0,14},{4,1},{2,1},
|
||||
{0,216},{0,141},{2,1},{0,187},{0,202},{74,1},{2,1},{0,255},{64,1},{58,1},
|
||||
{32,1},{16,1},{8,1},{4,1},{2,1},{0,172},{0,231},{2,1},{0,126},{0,217},
|
||||
{4,1},{2,1},{0,157},{0,232},{2,1},{0,142},{0,203},{8,1},{4,1},{2,1},
|
||||
{0,188},{0,218},{2,1},{0,173},{0,233},{4,1},{2,1},{0,158},{0,204},{2,1},
|
||||
{0,219},{0,189},{16,1},{8,1},{4,1},{2,1},{0,234},{0,174},{2,1},{0,220},
|
||||
{0,205},{4,1},{2,1},{0,235},{0,190},{2,1},{0,221},{0,236},{8,1},{4,1},
|
||||
{2,1},{0,206},{0,237},{2,1},{0,222},{0,238},{0,15},{4,1},{2,1},{0,240},
|
||||
{0,31},{0,241},{4,1},{2,1},{0,242},{0,47},{2,1},{0,243},{0,63},{18,1},
|
||||
{8,1},{4,1},{2,1},{0,244},{0,79},{2,1},{0,245},{0,95},{4,1},{2,1},
|
||||
{0,246},{0,111},{2,1},{0,247},{2,1},{0,127},{0,143},{10,1},{4,1},{2,1},
|
||||
{0,248},{0,249},{4,1},{2,1},{0,159},{0,175},{0,250},{8,1},{4,1},{2,1},
|
||||
{0,251},{0,191},{2,1},{0,252},{0,207},{4,1},{2,1},{0,253},{0,223},{2,1},
|
||||
{0,254},{0,239},
|
||||
};
|
||||
|
||||
private static int ValTab32[][] = {
|
||||
{2,1},{0,0},{8,1},{4,1},{2,1},{0,8},{0,4},{2,1},{0,1},{0,2},
|
||||
{8,1},{4,1},{2,1},{0,12},{0,10},{2,1},{0,3},{0,6},{6,1},{2,1},
|
||||
{0,9},{2,1},{0,5},{0,7},{4,1},{2,1},{0,14},{0,13},{2,1},{0,15},
|
||||
{0,11},
|
||||
};
|
||||
|
||||
private static int ValTab33[][] = {
|
||||
{16,1},{8,1},{4,1},{2,1},{0,0},{0,1},{2,1},{0,2},{0,3},{4,1},
|
||||
{2,1},{0,4},{0,5},{2,1},{0,6},{0,7},{8,1},{4,1},{2,1},{0,8},
|
||||
{0,9},{2,1},{0,10},{0,11},{4,1},{2,1},{0,12},{0,13},{2,1},{0,14},
|
||||
{0,15},
|
||||
};
|
||||
|
||||
|
||||
public static huffcodetab[] ht = null; /* Simulate extern struct */
|
||||
|
||||
private static int[] bitbuf = new int[32];
|
||||
|
||||
/**
|
||||
* Big Constructor : Computes all Huffman Tables.
|
||||
*/
|
||||
private huffcodetab(String S,int XLEN, int YLEN, int LINBITS, int LINMAX, int REF,
|
||||
int[] TABLE, int[] HLEN, int[][] VAL, int TREELEN)
|
||||
{
|
||||
tablename0 = S.charAt(0);
|
||||
tablename1 = S.charAt(1);
|
||||
tablename2 = S.charAt(2);
|
||||
xlen = XLEN;
|
||||
ylen = YLEN;
|
||||
linbits = LINBITS;
|
||||
linmax = LINMAX;
|
||||
ref = REF;
|
||||
table = TABLE;
|
||||
hlen = HLEN;
|
||||
val = VAL;
|
||||
treelen = TREELEN;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Do the Huffman decoding.
|
||||
* note! for counta,countb -the 4 bit value is returned in y,
|
||||
* discard x.
|
||||
*/
|
||||
public static int huffman_decoder(huffcodetab h, int[] x, int[] y, int[] v, int[] w, BitReserve br)
|
||||
{
|
||||
// array of all huffcodtable headers
|
||||
// 0..31 Huffman code table 0..31
|
||||
// 32,33 count1-tables
|
||||
|
||||
int dmask = 1 << ((4 * 8) - 1);
|
||||
int hs = 4 * 8;
|
||||
int level;
|
||||
int point = 0;
|
||||
int error = 1;
|
||||
level = dmask;
|
||||
|
||||
if (h.val == null) return 2;
|
||||
|
||||
/* table 0 needs no bits */
|
||||
if ( h.treelen == 0)
|
||||
{
|
||||
x[0] = y[0] = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Lookup in Huffman table. */
|
||||
|
||||
/*int bitsAvailable = 0;
|
||||
int bitIndex = 0;
|
||||
|
||||
int bits[] = bitbuf;*/
|
||||
do
|
||||
{
|
||||
if (h.val[point][0]==0)
|
||||
{ /*end of tree*/
|
||||
x[0] = h.val[point][1] >>> 4;
|
||||
y[0] = h.val[point][1] & 0xf;
|
||||
error = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
// hget1bit() is called thousands of times, and so needs to be
|
||||
// ultra fast.
|
||||
/*
|
||||
if (bitIndex==bitsAvailable)
|
||||
{
|
||||
bitsAvailable = br.readBits(bits, 32);
|
||||
bitIndex = 0;
|
||||
}
|
||||
*/
|
||||
//if (bits[bitIndex++]!=0)
|
||||
if (br.hget1bit()!=0)
|
||||
{
|
||||
while (h.val[point][1] >= MXOFF) point += h.val[point][1];
|
||||
point += h.val[point][1];
|
||||
}
|
||||
else
|
||||
{
|
||||
while (h.val[point][0] >= MXOFF) point += h.val[point][0];
|
||||
point += h.val[point][0];
|
||||
}
|
||||
level >>>= 1;
|
||||
// MDM: ht[0] is always 0;
|
||||
} while ((level !=0 ) || (point < 0 /*ht[0].treelen*/) );
|
||||
|
||||
// put back any bits not consumed
|
||||
/*
|
||||
int unread = (bitsAvailable-bitIndex);
|
||||
if (unread>0)
|
||||
br.rewindNbits(unread);
|
||||
*/
|
||||
/* Process sign encodings for quadruples tables. */
|
||||
// System.out.println(h.tablename);
|
||||
if (h.tablename0 == '3' && (h.tablename1 == '2' || h.tablename1 == '3'))
|
||||
{
|
||||
v[0] = (y[0]>>3) & 1;
|
||||
w[0] = (y[0]>>2) & 1;
|
||||
x[0] = (y[0]>>1) & 1;
|
||||
y[0] = y[0] & 1;
|
||||
|
||||
/* v, w, x and y are reversed in the bitstream.
|
||||
switch them around to make test bistream work. */
|
||||
|
||||
if (v[0]!=0)
|
||||
if (br.hget1bit() != 0) v[0] = -v[0];
|
||||
if (w[0]!=0)
|
||||
if (br.hget1bit() != 0) w[0] = -w[0];
|
||||
if (x[0]!=0)
|
||||
if (br.hget1bit() != 0) x[0] = -x[0];
|
||||
if (y[0]!=0)
|
||||
if (br.hget1bit() != 0) y[0] = -y[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Process sign and escape encodings for dual tables.
|
||||
// x and y are reversed in the test bitstream.
|
||||
// Reverse x and y here to make test bitstream work.
|
||||
|
||||
if (h.linbits != 0)
|
||||
if ((h.xlen-1) == x[0])
|
||||
x[0] += br.hgetbits(h.linbits);
|
||||
if (x[0] != 0)
|
||||
if (br.hget1bit() != 0) x[0] = -x[0];
|
||||
if (h.linbits != 0)
|
||||
if ((h.ylen-1) == y[0])
|
||||
y[0] += br.hgetbits(h.linbits);
|
||||
if (y[0] != 0)
|
||||
if (br.hget1bit() != 0) y[0] = -y[0];
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
public static void inithuff()
|
||||
{
|
||||
|
||||
if (ht!=null)
|
||||
return;
|
||||
|
||||
ht = new huffcodetab[HTN];
|
||||
ht[0] = new huffcodetab("0 ",0,0,0,0,-1,null,null,ValTab0,0);
|
||||
ht[1] = new huffcodetab("1 ",2,2,0,0,-1,null,null,ValTab1,7);
|
||||
ht[2] = new huffcodetab("2 ",3,3,0,0,-1,null,null,ValTab2,17);
|
||||
ht[3] = new huffcodetab("3 ",3,3,0,0,-1,null,null,ValTab3,17);
|
||||
ht[4] = new huffcodetab("4 ",0,0,0,0,-1,null,null,ValTab4,0);
|
||||
ht[5] = new huffcodetab("5 ",4,4,0,0,-1,null,null,ValTab5,31);
|
||||
ht[6] = new huffcodetab("6 ",4,4,0,0,-1,null,null,ValTab6,31);
|
||||
ht[7] = new huffcodetab("7 ",6,6,0,0,-1,null,null,ValTab7,71);
|
||||
ht[8] = new huffcodetab("8 ",6,6,0,0,-1,null,null,ValTab8,71);
|
||||
ht[9] = new huffcodetab("9 ",6,6,0,0,-1,null,null,ValTab9,71);
|
||||
ht[10] = new huffcodetab("10 ",8,8,0,0,-1,null,null,ValTab10,127);
|
||||
ht[11] = new huffcodetab("11 ",8,8,0,0,-1,null,null,ValTab11,127);
|
||||
ht[12] = new huffcodetab("12 ",8,8,0,0,-1,null,null,ValTab12,127);
|
||||
ht[13] = new huffcodetab("13 ",16,16,0,0,-1,null,null,ValTab13,511);
|
||||
ht[14] = new huffcodetab("14 ",0,0,0,0,-1,null,null,ValTab14,0);
|
||||
ht[15] = new huffcodetab("15 ",16,16,0,0,-1,null,null,ValTab15,511);
|
||||
ht[16] = new huffcodetab("16 ",16,16,1,1,-1,null,null,ValTab16,511);
|
||||
ht[17] = new huffcodetab("17 ",16,16,2,3,16,null,null,ValTab16,511);
|
||||
ht[18] = new huffcodetab("18 ",16,16,3,7,16,null,null,ValTab16,511);
|
||||
ht[19] = new huffcodetab("19 ",16,16,4,15,16,null,null,ValTab16,511);
|
||||
ht[20] = new huffcodetab("20 ",16,16,6,63,16,null,null,ValTab16,511);
|
||||
ht[21] = new huffcodetab("21 ",16,16,8,255,16,null,null,ValTab16,511);
|
||||
ht[22] = new huffcodetab("22 ",16,16,10,1023,16,null,null,ValTab16,511);
|
||||
ht[23] = new huffcodetab("23 ",16,16,13,8191,16,null,null,ValTab16,511);
|
||||
ht[24] = new huffcodetab("24 ",16,16,4,15,-1,null,null,ValTab24,512);
|
||||
ht[25] = new huffcodetab("25 ",16,16,5,31,24,null,null,ValTab24,512);
|
||||
ht[26] = new huffcodetab("26 ",16,16,6,63,24,null,null,ValTab24,512);
|
||||
ht[27] = new huffcodetab("27 ",16,16,7,127,24,null,null,ValTab24,512);
|
||||
ht[28] = new huffcodetab("28 ",16,16,8,255,24,null,null,ValTab24,512);
|
||||
ht[29] = new huffcodetab("29 ",16,16,9,511,24,null,null,ValTab24,512);
|
||||
ht[30] = new huffcodetab("30 ",16,16,11,2047,24,null,null,ValTab24,512);
|
||||
ht[31] = new huffcodetab("31 ",16,16,13,8191,24,null,null,ValTab24,512);
|
||||
ht[32] = new huffcodetab("32 ",1,16,0,0,-1,null,null,ValTab32,31);
|
||||
ht[33] = new huffcodetab("33 ",1,16,0,0,-1,null,null,ValTab33,31);
|
||||
}
|
||||
}
|
||||
BIN
src/lwjgl/java/javazoom/jl/decoder/l3reorder.ser
Normal file
BIN
src/lwjgl/java/javazoom/jl/decoder/l3reorder.ser
Normal file
Binary file not shown.
BIN
src/lwjgl/java/javazoom/jl/decoder/lin2au.ser
Normal file
BIN
src/lwjgl/java/javazoom/jl/decoder/lin2au.ser
Normal file
Binary file not shown.
15
src/lwjgl/java/javazoom/jl/decoder/readme.txt
Normal file
15
src/lwjgl/java/javazoom/jl/decoder/readme.txt
Normal file
@@ -0,0 +1,15 @@
|
||||
|
||||
TODO:
|
||||
|
||||
|
||||
Implement high-level Player and Converter classes.
|
||||
|
||||
Add MP1 and MP2 support and test.
|
||||
|
||||
Add option to run each "stage" on own thread.
|
||||
E.g. read & parse input, decode subbands, subband synthesis, audio output.
|
||||
|
||||
Retrofit seek support (temporarily removed when reworking classes.)
|
||||
|
||||
|
||||
Document and give example code.
|
||||
BIN
src/lwjgl/java/javazoom/jl/decoder/sfd.ser
Normal file
BIN
src/lwjgl/java/javazoom/jl/decoder/sfd.ser
Normal file
Binary file not shown.
265
src/lwjgl/java/javazoom/mp3spi/DecodedMpegAudioInputStream.java
Normal file
265
src/lwjgl/java/javazoom/mp3spi/DecodedMpegAudioInputStream.java
Normal file
@@ -0,0 +1,265 @@
|
||||
/*
|
||||
* DecodedMpegAudioInputStream.
|
||||
*
|
||||
* JavaZOOM : mp3spi@javazoom.net
|
||||
* http://www.javazoom.net
|
||||
*
|
||||
* Copyright (c) 2012 by fireandfuel from Cuina Team (http://www.cuina.byethost12.com/)
|
||||
*
|
||||
*-----------------------------------------------------------------------------
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library General Public License as published
|
||||
* by the Free Software Foundation; either version 2 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 Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
package javazoom.mp3spi;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import javax.sound.sampled.AudioFormat;
|
||||
import javax.sound.sampled.AudioInputStream;
|
||||
|
||||
import tritonus.TAsynchronousFilteredAudioInputStream;
|
||||
|
||||
import javazoom.jl.decoder.Bitstream;
|
||||
import javazoom.jl.decoder.BitstreamException;
|
||||
import javazoom.jl.decoder.Decoder;
|
||||
import javazoom.jl.decoder.DecoderException;
|
||||
import javazoom.jl.decoder.Header;
|
||||
import javazoom.jl.decoder.Obuffer;
|
||||
|
||||
/**
|
||||
* Main decoder.
|
||||
*/
|
||||
public class DecodedMpegAudioInputStream extends TAsynchronousFilteredAudioInputStream
|
||||
{
|
||||
private InputStream m_encodedStream;
|
||||
private Bitstream m_bitstream;
|
||||
private Decoder m_decoder;
|
||||
private Header m_header;
|
||||
private DMAISObuffer m_oBuffer;
|
||||
|
||||
// Bytes info.
|
||||
private long byteslength = -1;
|
||||
private long currentByte = 0;
|
||||
// Frame info.
|
||||
private int frameslength = -1;
|
||||
private long currentFrame = 0;
|
||||
private int currentFramesize = 0;
|
||||
|
||||
public DecodedMpegAudioInputStream(AudioFormat outputFormat,
|
||||
AudioInputStream bufferedInputStream)
|
||||
{
|
||||
super(outputFormat, -1);
|
||||
|
||||
try
|
||||
{
|
||||
// Try to find out inputstream length to allow skip.
|
||||
byteslength = bufferedInputStream.available();
|
||||
} catch (IOException e)
|
||||
{
|
||||
byteslength = -1;
|
||||
}
|
||||
m_encodedStream = bufferedInputStream;
|
||||
m_bitstream = new Bitstream(bufferedInputStream);
|
||||
m_decoder = new Decoder(null);
|
||||
// m_equalizer = new Equalizer();
|
||||
// m_equalizer_values = new float[32];
|
||||
// for (int b=0;b<m_equalizer.getBandCount();b++)
|
||||
// {
|
||||
// m_equalizer_values[b] = m_equalizer.getBand(b);
|
||||
// }
|
||||
// m_decoder.setEqualizer(m_equalizer);
|
||||
m_oBuffer = new DMAISObuffer(outputFormat.getChannels());
|
||||
m_decoder.setOutputBuffer(m_oBuffer);
|
||||
try
|
||||
{
|
||||
m_header = m_bitstream.readFrame();
|
||||
if((m_header != null) && (frameslength == -1) && (byteslength > 0))
|
||||
frameslength = m_header.max_number_of_frames((int) byteslength);
|
||||
} catch (BitstreamException e)
|
||||
{
|
||||
|
||||
byteslength = -1;
|
||||
}
|
||||
}
|
||||
|
||||
public void execute()// if( reverseBytes )
|
||||
// reverseBytes( smallBuffer, 0, bytesRead );
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
// Following line hangs when FrameSize is available in AudioFormat.
|
||||
Header header = null;
|
||||
if(m_header == null)
|
||||
header = m_bitstream.readFrame();
|
||||
else header = m_header;
|
||||
|
||||
if(header == null)
|
||||
{
|
||||
|
||||
getCircularBuffer().close();
|
||||
return;
|
||||
}
|
||||
currentFrame++;
|
||||
currentFramesize = header.calculate_framesize();
|
||||
currentByte = currentByte + currentFramesize;
|
||||
// Obuffer decoderOutput =
|
||||
m_decoder.decodeFrame(header, m_bitstream);
|
||||
m_bitstream.closeFrame();
|
||||
getCircularBuffer().write(m_oBuffer.getBuffer(), 0, m_oBuffer.getCurrentBufferSize());
|
||||
m_oBuffer.reset();
|
||||
if(m_header != null)
|
||||
m_header = null;
|
||||
} catch (BitstreamException e)
|
||||
{
|
||||
|
||||
} catch (DecoderException e)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public long skip(long bytes)
|
||||
{
|
||||
if((byteslength > 0) && (frameslength > 0))
|
||||
{
|
||||
float ratio = bytes * 1.0f / byteslength * 1.0f;
|
||||
long bytesread = skipFrames((long) (ratio * frameslength));
|
||||
currentByte = currentByte + bytesread;
|
||||
m_header = null;
|
||||
return bytesread;
|
||||
} else return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Skip frames. You don't need to call it severals times, it will exactly
|
||||
* skip given frames number.
|
||||
*
|
||||
* @param frames
|
||||
* @return bytes length skipped matching to frames skipped.
|
||||
*/
|
||||
public long skipFrames(long frames)
|
||||
{
|
||||
|
||||
int framesRead = 0;
|
||||
int bytesReads = 0;
|
||||
try
|
||||
{
|
||||
for(int i = 0; i < frames; i++)
|
||||
{
|
||||
Header header = m_bitstream.readFrame();
|
||||
if(header != null)
|
||||
{
|
||||
int fsize = header.calculate_framesize();
|
||||
bytesReads = bytesReads + fsize;
|
||||
}
|
||||
m_bitstream.closeFrame();
|
||||
framesRead++;
|
||||
}
|
||||
} catch (BitstreamException e)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
currentFrame = currentFrame + framesRead;
|
||||
return bytesReads;
|
||||
}
|
||||
|
||||
private boolean isBigEndian()
|
||||
{
|
||||
return getFormat().isBigEndian();
|
||||
}
|
||||
|
||||
public void close() throws IOException
|
||||
{
|
||||
super.close();
|
||||
m_encodedStream.close();
|
||||
}
|
||||
|
||||
private class DMAISObuffer extends Obuffer
|
||||
{
|
||||
private int m_nChannels;
|
||||
private byte[] m_abBuffer;
|
||||
private int[] m_anBufferPointers;
|
||||
private boolean m_bIsBigEndian;
|
||||
|
||||
public DMAISObuffer(int nChannels)
|
||||
{
|
||||
m_nChannels = nChannels;
|
||||
m_abBuffer = new byte[OBUFFERSIZE * nChannels];
|
||||
m_anBufferPointers = new int[nChannels];
|
||||
reset();
|
||||
m_bIsBigEndian = DecodedMpegAudioInputStream.this.isBigEndian();
|
||||
}
|
||||
|
||||
public void append(int nChannel, short sValue)
|
||||
{
|
||||
byte bFirstByte;
|
||||
byte bSecondByte;
|
||||
if(m_bIsBigEndian)
|
||||
{
|
||||
bFirstByte = (byte) ((sValue >>> 8) & 0xFF);
|
||||
bSecondByte = (byte) (sValue & 0xFF);
|
||||
} else
|
||||
// little endian
|
||||
{
|
||||
bFirstByte = (byte) (sValue & 0xFF);
|
||||
bSecondByte = (byte) ((sValue >>> 8) & 0xFF);
|
||||
}
|
||||
m_abBuffer[m_anBufferPointers[nChannel]] = bFirstByte;
|
||||
m_abBuffer[m_anBufferPointers[nChannel] + 1] = bSecondByte;
|
||||
m_anBufferPointers[nChannel] += m_nChannels * 2;
|
||||
}
|
||||
|
||||
public void set_stop_flag()
|
||||
{
|
||||
}
|
||||
|
||||
public void close()
|
||||
{
|
||||
}
|
||||
|
||||
public void write_buffer(int nValue)
|
||||
{
|
||||
}
|
||||
|
||||
public void clear_buffer()
|
||||
{
|
||||
}
|
||||
|
||||
public byte[] getBuffer()
|
||||
{
|
||||
return m_abBuffer;
|
||||
}
|
||||
|
||||
public int getCurrentBufferSize()
|
||||
{
|
||||
return m_anBufferPointers[0];
|
||||
}
|
||||
|
||||
public void reset()
|
||||
{
|
||||
for(int i = 0; i < m_nChannels; i++)
|
||||
{
|
||||
/*
|
||||
* Points to byte location, implicitely assuming 16 bit samples.
|
||||
*/
|
||||
m_anBufferPointers[i] = i * 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
31
src/lwjgl/java/net/lax1dude/eaglercraft/MinecraftMain.java
Normal file
31
src/lwjgl/java/net/lax1dude/eaglercraft/MinecraftMain.java
Normal file
@@ -0,0 +1,31 @@
|
||||
package net.lax1dude.eaglercraft;
|
||||
|
||||
import java.lang.management.ManagementFactory;
|
||||
|
||||
import javax.swing.JOptionPane;
|
||||
|
||||
import net.minecraft.src.Minecraft;
|
||||
import net.minecraft.src.ServerList;
|
||||
|
||||
public class MinecraftMain {
|
||||
|
||||
public static void main(String[] par0ArrayOfStr) {
|
||||
|
||||
JOptionPane.showMessageDialog(null, "launch renderdoc (optionally) and press ok to continue", "eaglercraft: " + ManagementFactory.getRuntimeMXBean().getName(), JOptionPane.PLAIN_MESSAGE);
|
||||
|
||||
EaglerAdapter.initializeContext();
|
||||
LocalStorageManager.loadStorage();
|
||||
|
||||
byte[] b = EaglerAdapter.loadLocalStorage("forced");
|
||||
if(b != null) {
|
||||
ServerList.loadDefaultServers(Base64.encodeBase64String(b));
|
||||
}
|
||||
if(par0ArrayOfStr.length > 0) {
|
||||
EaglerAdapter.setServerToJoinOnLaunch(par0ArrayOfStr[0]);
|
||||
}
|
||||
|
||||
Minecraft mc = new Minecraft();
|
||||
mc.run();
|
||||
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,50 @@
|
||||
package net.lax1dude.eaglercraft.adapter;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
public class SimpleStorage {
|
||||
private static final Path directory;
|
||||
private static final boolean available = true;
|
||||
|
||||
public static boolean isAvailable() {
|
||||
return available;
|
||||
}
|
||||
|
||||
static {
|
||||
File file = new File("eagstorage");
|
||||
file.mkdirs();
|
||||
directory = file.toPath().toAbsolutePath();
|
||||
}
|
||||
|
||||
public static byte[] get(String key) {
|
||||
try {
|
||||
return Files.readAllBytes(directory.resolve(key));
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static Boolean set(String key, byte[] value) {
|
||||
try {
|
||||
if (value == null) {
|
||||
Files.deleteIfExists(directory.resolve(key));
|
||||
} else {
|
||||
Files.write(directory.resolve(key), value);
|
||||
}
|
||||
return Boolean.TRUE;
|
||||
} catch (IOException e) {
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
public static String[] list() {
|
||||
try {
|
||||
return Files.list(directory).map(Path::getFileName).toArray(String[]::new);
|
||||
} catch (IOException e) {
|
||||
return new String[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
384
src/lwjgl/java/net/lax1dude/eaglercraft/adapter/Tessellator.java
Normal file
384
src/lwjgl/java/net/lax1dude/eaglercraft/adapter/Tessellator.java
Normal file
@@ -0,0 +1,384 @@
|
||||
package net.lax1dude.eaglercraft.adapter;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.IntBuffer;
|
||||
|
||||
import net.lax1dude.eaglercraft.EaglerAdapter;
|
||||
import net.minecraft.src.MathHelper;
|
||||
|
||||
public class Tessellator {
|
||||
|
||||
/** The byte buffer used for GL allocation. */
|
||||
private ByteBuffer byteBuffer;
|
||||
private IntBuffer intBuffer;
|
||||
|
||||
/** Raw integer array. */
|
||||
private int[] rawBuffer;
|
||||
|
||||
/**
|
||||
* The number of vertices to be drawn in the next draw call. Reset to 0 between
|
||||
* draw calls.
|
||||
*/
|
||||
private int vertexCount = 0;
|
||||
|
||||
/** The first coordinate to be used for the texture. */
|
||||
private double textureU;
|
||||
|
||||
/** The second coordinate to be used for the texture. */
|
||||
private double textureV;
|
||||
private int brightness;
|
||||
|
||||
/** The color (RGBA) value to be used for the following draw call. */
|
||||
private int color;
|
||||
|
||||
/**
|
||||
* Whether the current draw object for this tessellator has color values.
|
||||
*/
|
||||
private boolean hasColor = false;
|
||||
|
||||
/**
|
||||
* Whether the current draw object for this tessellator has texture coordinates.
|
||||
*/
|
||||
private boolean hasTexture = false;
|
||||
private boolean hasBrightness = false;
|
||||
|
||||
/**
|
||||
* Whether the current draw object for this tessellator has normal values.
|
||||
*/
|
||||
private boolean hasNormals = false;
|
||||
|
||||
/** The index into the raw buffer to be used for the next data. */
|
||||
private int rawBufferIndex = 0;
|
||||
|
||||
/**
|
||||
* The number of vertices manually added to the given draw call. This differs
|
||||
* from vertexCount because it adds extra vertices when converting quads to
|
||||
* triangles.
|
||||
*/
|
||||
private int addedVertices = 0;
|
||||
|
||||
/** Disables all color information for the following draw call. */
|
||||
private boolean isColorDisabled = false;
|
||||
|
||||
/** The draw mode currently being used by the tessellator. */
|
||||
private int drawMode;
|
||||
|
||||
/**
|
||||
* An offset to be applied along the x-axis for all vertices in this draw call.
|
||||
*/
|
||||
private double xOffset;
|
||||
|
||||
/**
|
||||
* An offset to be applied along the y-axis for all vertices in this draw call.
|
||||
*/
|
||||
private double yOffset;
|
||||
|
||||
/**
|
||||
* An offset to be applied along the z-axis for all vertices in this draw call.
|
||||
*/
|
||||
private double zOffset;
|
||||
|
||||
/** The normal to be applied to the face being drawn. */
|
||||
private int normal;
|
||||
|
||||
/** The static instance of the Tessellator. */
|
||||
public static final Tessellator instance = new Tessellator(525000);
|
||||
|
||||
/** Whether this tessellator is currently in draw mode. */
|
||||
private boolean isDrawing = false;
|
||||
|
||||
/** Whether we are currently using VBO or not. */
|
||||
private boolean useVBO = false;
|
||||
|
||||
/** The size of the buffers used (in integers). */
|
||||
private int bufferSize;
|
||||
|
||||
private Tessellator(int par1) {
|
||||
this.bufferSize = par1;
|
||||
this.byteBuffer = ByteBuffer.allocateDirect(par1 * 4).order(ByteOrder.nativeOrder());
|
||||
this.intBuffer = this.byteBuffer.asIntBuffer();
|
||||
this.rawBuffer = new int[par1];
|
||||
this.useVBO = false;// tryVBO && GLContext.getCapabilities().GL_ARB_vertex_buffer_object;
|
||||
|
||||
//if (this.useVBO) {
|
||||
//this.vertexBuffers = GLAllocation.createDirectIntBuffer(this.vboCount);
|
||||
//ARBVertexBufferObject.glGenBuffersARB(this.vertexBuffers);
|
||||
//}
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws the data set up in this tessellator and resets the state to prepare for
|
||||
* new drawing.
|
||||
*/
|
||||
public int draw() {
|
||||
if (!this.isDrawing) {
|
||||
return 0;
|
||||
} else {
|
||||
this.isDrawing = false;
|
||||
|
||||
if (this.vertexCount > 0) {
|
||||
IntBuffer up = null;
|
||||
this.intBuffer.clear();
|
||||
this.intBuffer.put(rawBuffer, 0, this.rawBufferIndex);
|
||||
this.intBuffer.flip();
|
||||
up = this.intBuffer;
|
||||
|
||||
if (this.hasTexture) {
|
||||
EaglerAdapter.glEnableVertexAttrib(EaglerAdapter.GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
|
||||
if (this.hasColor) {
|
||||
EaglerAdapter.glEnableVertexAttrib(EaglerAdapter.GL_COLOR_ARRAY);
|
||||
}
|
||||
|
||||
if (this.hasNormals) {
|
||||
EaglerAdapter.glEnableVertexAttrib(EaglerAdapter.GL_NORMAL_ARRAY);
|
||||
}
|
||||
|
||||
if (this.hasBrightness) {
|
||||
EaglerAdapter.glClientActiveTexture(EaglerAdapter.GL_TEXTURE1);
|
||||
EaglerAdapter.glEnableVertexAttrib(EaglerAdapter.GL_TEXTURE_COORD_ARRAY);
|
||||
EaglerAdapter.glClientActiveTexture(EaglerAdapter.GL_TEXTURE0);
|
||||
}
|
||||
|
||||
EaglerAdapter.glDrawArrays(this.drawMode, 0, this.vertexCount, up);
|
||||
|
||||
if (this.hasTexture) {
|
||||
EaglerAdapter.glDisableVertexAttrib(EaglerAdapter.GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
|
||||
if (this.hasColor) {
|
||||
EaglerAdapter.glDisableVertexAttrib(EaglerAdapter.GL_COLOR_ARRAY);
|
||||
}
|
||||
|
||||
if (this.hasNormals) {
|
||||
EaglerAdapter.glDisableVertexAttrib(EaglerAdapter.GL_NORMAL_ARRAY);
|
||||
}
|
||||
|
||||
if (this.hasBrightness) {
|
||||
EaglerAdapter.glClientActiveTexture(EaglerAdapter.GL_TEXTURE1);
|
||||
EaglerAdapter.glDisableVertexAttrib(EaglerAdapter.GL_TEXTURE_COORD_ARRAY);
|
||||
EaglerAdapter.glClientActiveTexture(EaglerAdapter.GL_TEXTURE0);
|
||||
}
|
||||
}
|
||||
|
||||
int var1 = this.rawBufferIndex * 4;
|
||||
this.reset();
|
||||
return var1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the tessellator state in preparation for new drawing.
|
||||
*/
|
||||
private void reset() {
|
||||
this.vertexCount = 0;
|
||||
this.rawBufferIndex = 0;
|
||||
this.addedVertices = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets draw mode in the tessellator to draw quads.
|
||||
*/
|
||||
public void startDrawingQuads() {
|
||||
this.startDrawing(EaglerAdapter.GL_QUADS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets tessellator state and prepares for drawing (with the specified draw
|
||||
* mode).
|
||||
*/
|
||||
public void startDrawing(int par1) {
|
||||
if (this.isDrawing) {
|
||||
this.draw();
|
||||
}
|
||||
this.isDrawing = true;
|
||||
this.reset();
|
||||
this.drawMode = par1;
|
||||
this.hasNormals = false;
|
||||
this.hasColor = false;
|
||||
this.hasTexture = false;
|
||||
this.hasBrightness = false;
|
||||
this.isColorDisabled = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the texture coordinates.
|
||||
*/
|
||||
public void setTextureUV(double par1, double par3) {
|
||||
this.hasTexture = true;
|
||||
this.textureU = par1;
|
||||
this.textureV = par3;
|
||||
}
|
||||
|
||||
public void setBrightness(int par1) {
|
||||
this.hasBrightness = true;
|
||||
this.brightness = par1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the RGB values as specified, converting from floats between 0 and 1 to
|
||||
* integers from 0-255.
|
||||
*/
|
||||
public void setColorOpaque_F(float par1, float par2, float par3) {
|
||||
this.setColorOpaque((int) (par1 * 255.0F), (int) (par2 * 255.0F), (int) (par3 * 255.0F));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the RGBA values for the color, converting from floats between 0 and 1 to
|
||||
* integers from 0-255.
|
||||
*/
|
||||
public void setColorRGBA_F(float par1, float par2, float par3, float par4) {
|
||||
this.setColorRGBA((int) (par1 * 255.0F), (int) (par2 * 255.0F), (int) (par3 * 255.0F), (int) (par4 * 255.0F));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the RGB values as specified, and sets alpha to opaque.
|
||||
*/
|
||||
public void setColorOpaque(int par1, int par2, int par3) {
|
||||
this.setColorRGBA(par1, par2, par3, 255);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the RGBA values for the color. Also clamps them to 0-255.
|
||||
*/
|
||||
public void setColorRGBA(int par1, int par2, int par3, int par4) {
|
||||
if (!this.isColorDisabled) {
|
||||
if (par1 > 255) {
|
||||
par1 = 255;
|
||||
}
|
||||
|
||||
if (par2 > 255) {
|
||||
par2 = 255;
|
||||
}
|
||||
|
||||
if (par3 > 255) {
|
||||
par3 = 255;
|
||||
}
|
||||
|
||||
if (par4 > 255) {
|
||||
par4 = 255;
|
||||
}
|
||||
|
||||
if (par1 < 0) {
|
||||
par1 = 0;
|
||||
}
|
||||
|
||||
if (par2 < 0) {
|
||||
par2 = 0;
|
||||
}
|
||||
|
||||
if (par3 < 0) {
|
||||
par3 = 0;
|
||||
}
|
||||
|
||||
if (par4 < 0) {
|
||||
par4 = 0;
|
||||
}
|
||||
|
||||
this.hasColor = true;
|
||||
this.color = par4 << 24 | par3 << 16 | par2 << 8 | par1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a vertex specifying both x,y,z and the texture u,v for it.
|
||||
*/
|
||||
public void addVertexWithUV(double par1, double par3, double par5, double par7, double par9) {
|
||||
this.setTextureUV(par7, par9);
|
||||
this.addVertex(par1, par3, par5);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a vertex with the specified x,y,z to the current draw call. It will
|
||||
* trigger a draw() if the buffer gets full.
|
||||
*/
|
||||
public void addVertex(double par1, double par3, double par5) {
|
||||
if(this.addedVertices > 65534) return;
|
||||
++this.addedVertices;
|
||||
|
||||
this.rawBuffer[this.rawBufferIndex + 0] = Float.floatToRawIntBits((float) (par1 + this.xOffset));
|
||||
this.rawBuffer[this.rawBufferIndex + 1] = Float.floatToRawIntBits((float) (par3 + this.yOffset));
|
||||
this.rawBuffer[this.rawBufferIndex + 2] = Float.floatToRawIntBits((float) (par5 + this.zOffset));
|
||||
|
||||
if (this.hasTexture) {
|
||||
this.rawBuffer[this.rawBufferIndex + 3] = Float.floatToRawIntBits((float) this.textureU);
|
||||
this.rawBuffer[this.rawBufferIndex + 4] = Float.floatToRawIntBits((float) this.textureV);
|
||||
}
|
||||
|
||||
if (this.hasColor) {
|
||||
this.rawBuffer[this.rawBufferIndex + 5] = this.color;
|
||||
}
|
||||
|
||||
if (this.hasNormals) {
|
||||
this.rawBuffer[this.rawBufferIndex + 6] = this.normal;
|
||||
}
|
||||
|
||||
if (this.hasBrightness) {
|
||||
this.rawBuffer[this.rawBufferIndex + 7] = this.brightness;
|
||||
}
|
||||
|
||||
this.rawBufferIndex += 8;
|
||||
++this.vertexCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the color to the given opaque value (stored as byte values packed in an
|
||||
* integer).
|
||||
*/
|
||||
public void setColorOpaque_I(int par1) {
|
||||
int var2 = par1 >> 16 & 255;
|
||||
int var3 = par1 >> 8 & 255;
|
||||
int var4 = par1 & 255;
|
||||
this.setColorOpaque(var2, var3, var4);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the color to the given color (packed as bytes in integer) and alpha
|
||||
* values.
|
||||
*/
|
||||
public void setColorRGBA_I(int par1, int par2) {
|
||||
int var3 = par1 >> 16 & 255;
|
||||
int var4 = par1 >> 8 & 255;
|
||||
int var5 = par1 & 255;
|
||||
this.setColorRGBA(var3, var4, var5, par2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables colors for the current draw call.
|
||||
*/
|
||||
public void disableColor() {
|
||||
this.isColorDisabled = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the normal for the current draw call.
|
||||
*/
|
||||
public void setNormal(float par1, float par2, float par3) {
|
||||
this.hasNormals = true;
|
||||
float len = (float) Math.sqrt(par1 * par1 + par2 * par2 + par3 * par3);
|
||||
int var4 = (int)((par1 / len) * 127.0F) + 127;
|
||||
int var5 = (int)((par2 / len) * 127.0F) + 127;
|
||||
int var6 = (int)((par3 / len) * 127.0F) + 127;
|
||||
this.normal = var4 & 255 | (var5 & 255) << 8 | (var6 & 255) << 16;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the translation for all vertices in the current draw call.
|
||||
*/
|
||||
public void setTranslation(double par1, double par3, double par5) {
|
||||
this.xOffset = par1;
|
||||
this.yOffset = par3;
|
||||
this.zOffset = par5;
|
||||
}
|
||||
|
||||
/**
|
||||
* Offsets the translation for all vertices in the current draw call.
|
||||
*/
|
||||
public void addTranslation(float par1, float par2, float par3) {
|
||||
this.xOffset += (double) par1;
|
||||
this.yOffset += (double) par2;
|
||||
this.zOffset += (double) par3;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package net.lax1dude.eaglercraft.adapter.lwjgl;
|
||||
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
|
||||
import net.minecraft.src.Minecraft;
|
||||
|
||||
public final class GameWindowListener extends WindowAdapter {
|
||||
public void windowClosing(WindowEvent par1WindowEvent) {
|
||||
Minecraft.getMinecraft().shutdown();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package net.lax1dude.eaglercraft.adapter.vfs;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Comparator;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class VFile extends File {
|
||||
|
||||
public VFile(String pathname) {
|
||||
super(pathname);
|
||||
}
|
||||
|
||||
public VFile(String parent, String child) {
|
||||
super(parent, child);
|
||||
}
|
||||
|
||||
public VFile(File parent, String child) {
|
||||
super(parent, child);
|
||||
}
|
||||
|
||||
public VFile(String parent, String child, String child2) {
|
||||
super(new VFile(parent, child), child2);
|
||||
}
|
||||
|
||||
public InputStream getInputStream() {
|
||||
try {
|
||||
return Files.newInputStream(this.toPath());
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public String[] getAllLines() {
|
||||
try {
|
||||
return Files.readAllLines(this.toPath(), StandardCharsets.UTF_8).toArray(new String[0]);
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public String getAllChars() {
|
||||
try {
|
||||
return new String(Files.readAllBytes(this.toPath()), StandardCharsets.UTF_8);
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean setAllChars(String chars) {
|
||||
return setAllBytes(chars.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
public boolean setAllBytes(byte[] bytes) {
|
||||
try {
|
||||
File f = this.getParentFile();
|
||||
if (f != null) {
|
||||
f.mkdirs();
|
||||
}
|
||||
Files.write(this.toPath(), bytes);
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public int deleteAll() {
|
||||
try (Stream<Path> pathStream = Files.walk(this.toPath())) {
|
||||
pathStream.sorted(Comparator.reverseOrder())
|
||||
.map(Path::toFile)
|
||||
.forEach(File::delete);
|
||||
return 1;
|
||||
} catch (IOException e) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
270
src/lwjgl/java/paulscode/sound/Channel.java
Normal file
270
src/lwjgl/java/paulscode/sound/Channel.java
Normal file
@@ -0,0 +1,270 @@
|
||||
package paulscode.sound;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import javax.sound.sampled.AudioFormat;
|
||||
|
||||
/**
|
||||
* The Channel class is the base class which can be extended for
|
||||
* library-specific channels. It is also used in the "no-sound" library.
|
||||
* A channel is a reserved sound-card voice through which sources are played
|
||||
* back. Channels can be either streaming channels or normal (non-streaming)
|
||||
* ones. For consistant naming conventions, each sub-class should have the
|
||||
* name prefix "Channel".
|
||||
*<br><br>
|
||||
*<b><i> SoundSystem License:</b></i><br><b><br>
|
||||
* You are free to use this library for any purpose, commercial or otherwise.
|
||||
* You may modify this library or source code, and distribute it any way you
|
||||
* like, provided the following conditions are met:
|
||||
*<br>
|
||||
* 1) You may not falsely claim to be the author of this library or any
|
||||
* unmodified portion of it.
|
||||
*<br>
|
||||
* 2) You may not copyright this library or a modified version of it and then
|
||||
* sue me for copyright infringement.
|
||||
*<br>
|
||||
* 3) If you modify the source code, you must clearly document the changes
|
||||
* made before redistributing the modified source code, so other users know
|
||||
* it is not the original code.
|
||||
*<br>
|
||||
* 4) You are not required to give me credit for this library in any derived
|
||||
* work, but if you do, you must also mention my website:
|
||||
* http://www.paulscode.com
|
||||
*<br>
|
||||
* 5) I the author will not be responsible for any damages (physical,
|
||||
* financial, or otherwise) caused by the use if this library or any part
|
||||
* of it.
|
||||
*<br>
|
||||
* 6) I the author do not guarantee, warrant, or make any representations,
|
||||
* either expressed or implied, regarding the use of this library or any
|
||||
* part of it.
|
||||
* <br><br>
|
||||
* Author: Paul Lamb
|
||||
* <br>
|
||||
* http://www.paulscode.com
|
||||
* </b>
|
||||
*/
|
||||
public class Channel
|
||||
{
|
||||
/**
|
||||
* The library class associated with this type of channel.
|
||||
*/
|
||||
protected Class libraryType = Library.class;
|
||||
|
||||
/**
|
||||
* Global identifier for the type of channel (normal or streaming). Possible
|
||||
* values for this varriable can be found in the
|
||||
* {@link paulscode.sound.SoundSystemConfig SoundSystemConfig} class.
|
||||
*/
|
||||
public int channelType;
|
||||
|
||||
/**
|
||||
* Processes status messages, warnings, and error messages.
|
||||
*/
|
||||
private SoundSystemLogger logger;
|
||||
|
||||
/**
|
||||
* Whatever source is attached to this channel.
|
||||
*/
|
||||
public Source attachedSource = null;
|
||||
|
||||
/**
|
||||
* Cumulative counter of the buffers played then unqued.
|
||||
*/
|
||||
public int buffersUnqueued = 0;
|
||||
|
||||
/**
|
||||
* Constructor: Takes channelType identifier as a paramater. Possible values
|
||||
* for channel type can be found in the
|
||||
* {@link paulscode.sound.SoundSystemConfig SoundSystemConfig} class.
|
||||
* @param type Type of channel (normal or streaming).
|
||||
*/
|
||||
public Channel( int type )
|
||||
{
|
||||
// grab a handle to the message logger:
|
||||
logger = SoundSystemConfig.getLogger();
|
||||
|
||||
channelType = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shuts the channel down and removes references to all instantiated objects.
|
||||
*/
|
||||
public void cleanup()
|
||||
{
|
||||
logger = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Queues up the initial byte[] buffers of data to be streamed.
|
||||
* @param bufferList List of the first buffers to be played for a streaming source.
|
||||
* @return False if an error occurred or if end of stream was reached.
|
||||
*/
|
||||
public boolean preLoadBuffers( LinkedList<byte[]> bufferList )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Queues up a byte[] buffer of data to be streamed.
|
||||
* @param buffer The next buffer to be played for a streaming source.
|
||||
* @return False if an error occurred or if the channel is shutting down.
|
||||
*/
|
||||
public boolean queueBuffer( byte[] buffer )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Feeds raw data to the stream.
|
||||
* @param buffer Buffer containing raw audio data to stream.
|
||||
* @return Number of prior buffers that have been processed.
|
||||
*/
|
||||
public int feedRawAudioData( byte[] buffer )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of queued byte[] buffers that have finished playing.
|
||||
* @return Number of buffers processed.
|
||||
*/
|
||||
public int buffersProcessed()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the number of milliseconds since the channel began playing.
|
||||
* @return Milliseconds, or -1 if unable to calculate.
|
||||
*/
|
||||
public float millisecondsPlayed()
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
/**
|
||||
* Plays the next queued byte[] buffer. This method is run from the seperate
|
||||
* {@link paulscode.sound.StreamThread StreamThread}.
|
||||
* @return False when no more buffers are left to process.
|
||||
*/
|
||||
public boolean processBuffer()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the channel up to receive the specified audio format.
|
||||
*/
|
||||
public void setAudioFormat( AudioFormat audioFormat )
|
||||
{}
|
||||
|
||||
/**
|
||||
* Dequeues all previously queued data.
|
||||
*/
|
||||
public void flush()
|
||||
{}
|
||||
|
||||
/**
|
||||
* Stops the channel, dequeues any queued data, and closes the channel.
|
||||
*/
|
||||
public void close()
|
||||
{}
|
||||
|
||||
/**
|
||||
* Plays the currently attached normal source, opens this channel up for
|
||||
* streaming, or resumes playback if this channel was paused.
|
||||
*/
|
||||
public void play()
|
||||
{}
|
||||
|
||||
/**
|
||||
* Temporarily stops playback for this channel.
|
||||
*/
|
||||
public void pause()
|
||||
{}
|
||||
|
||||
/**
|
||||
* Stops playback for this channel and rewinds the attached source to the
|
||||
* beginning.
|
||||
*/
|
||||
public void stop()
|
||||
{}
|
||||
|
||||
/**
|
||||
* Rewinds the attached source to the beginning. Stops the source if it was
|
||||
* paused.
|
||||
*/
|
||||
public void rewind()
|
||||
{}
|
||||
|
||||
/**
|
||||
* Used to determine if a channel is actively playing a source. This method
|
||||
* will return false if the channel is paused or stopped and when no data is
|
||||
* queued to be streamed.
|
||||
* @return True if this channel is playing a source.
|
||||
*/
|
||||
public boolean playing()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the class.
|
||||
* @return "Channel" + library title.
|
||||
*/
|
||||
public String getClassName()
|
||||
{
|
||||
String libTitle = SoundSystemConfig.getLibraryTitle( libraryType );
|
||||
|
||||
if( libTitle.equals( "No Sound" ) )
|
||||
return "Channel";
|
||||
else
|
||||
return "Channel" + libTitle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a message.
|
||||
* @param message Message to print.
|
||||
*/
|
||||
protected void message( String message )
|
||||
{
|
||||
logger.message( message, 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints an important message.
|
||||
* @param message Message to print.
|
||||
*/
|
||||
protected void importantMessage( String message )
|
||||
{
|
||||
logger.importantMessage( message, 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the specified message if error is true.
|
||||
* @param error True or False.
|
||||
* @param message Message to print if error is true.
|
||||
* @return True if error is true.
|
||||
*/
|
||||
protected boolean errorCheck( boolean error, String message )
|
||||
{
|
||||
return logger.errorCheck( error, getClassName(), message, 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints an error message.
|
||||
* @param message Message to print.
|
||||
*/
|
||||
protected void errorMessage( String message )
|
||||
{
|
||||
logger.errorMessage( getClassName(), message, 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints an exception's error message followed by the stack trace.
|
||||
* @param e Exception containing the information to print.
|
||||
*/
|
||||
protected void printStackTrace( Exception e )
|
||||
{
|
||||
logger.printStackTrace( e, 1 );
|
||||
}
|
||||
}
|
||||
603
src/lwjgl/java/paulscode/sound/CommandObject.java
Normal file
603
src/lwjgl/java/paulscode/sound/CommandObject.java
Normal file
@@ -0,0 +1,603 @@
|
||||
package paulscode.sound;
|
||||
|
||||
/**
|
||||
* The CommandObject class is used to store arguments in the SoundSystem's
|
||||
* Command Queue. Queued CommandObjects are then processed by the
|
||||
* {@link paulscode.sound.CommandThread CommandThread}. Commands are queued
|
||||
* and executed in the background, so it is unlikely that the user will ever
|
||||
* need to use this class.
|
||||
*<br><br>
|
||||
*<b><i> SoundSystem License:</b></i><br><b><br>
|
||||
* You are free to use this library for any purpose, commercial or otherwise.
|
||||
* You may modify this library or source code, and distribute it any way you
|
||||
* like, provided the following conditions are met:
|
||||
*<br>
|
||||
* 1) You may not falsely claim to be the author of this library or any
|
||||
* unmodified portion of it.
|
||||
*<br>
|
||||
* 2) You may not copyright this library or a modified version of it and then
|
||||
* sue me for copyright infringement.
|
||||
*<br>
|
||||
* 3) If you modify the source code, you must clearly document the changes
|
||||
* made before redistributing the modified source code, so other users know
|
||||
* it is not the original code.
|
||||
*<br>
|
||||
* 4) You are not required to give me credit for this library in any derived
|
||||
* work, but if you do, you must also mention my website:
|
||||
* http://www.paulscode.com
|
||||
*<br>
|
||||
* 5) I the author will not be responsible for any damages (physical,
|
||||
* financial, or otherwise) caused by the use if this library or any part
|
||||
* of it.
|
||||
*<br>
|
||||
* 6) I the author do not guarantee, warrant, or make any representations,
|
||||
* either expressed or implied, regarding the use of this library or any
|
||||
* part of it.
|
||||
* <br><br>
|
||||
* Author: Paul Lamb
|
||||
* <br>
|
||||
* http://www.paulscode.com
|
||||
* </b>
|
||||
*/
|
||||
public class CommandObject
|
||||
{
|
||||
/**
|
||||
* Global identifier for the command to initialize the current sound library.
|
||||
*/
|
||||
public static final int INITIALIZE = 1;
|
||||
/**
|
||||
* Global identifier for the command to pre-load a sound file.
|
||||
*/
|
||||
public static final int LOAD_SOUND = 2;
|
||||
/**
|
||||
* Global identifier for the command to pre-load a sound file.
|
||||
*/
|
||||
public static final int LOAD_DATA = 3;
|
||||
/**
|
||||
* Global identifier for the command to remove a sound file from memory.
|
||||
*/
|
||||
public static final int UNLOAD_SOUND = 4;
|
||||
/**
|
||||
* Global identifier for the command to queue a sound file.
|
||||
*/
|
||||
public static final int QUEUE_SOUND = 5;
|
||||
/**
|
||||
* Global identifier for the command to dequeue a sound file.
|
||||
*/
|
||||
public static final int DEQUEUE_SOUND = 6;
|
||||
/**
|
||||
* Global identifier for the command to fade-out transition a source.
|
||||
*/
|
||||
public static final int FADE_OUT = 7;
|
||||
/**
|
||||
* Global identifier for the command to fade-out/in transition a source.
|
||||
*/
|
||||
public static final int FADE_OUT_IN = 8;
|
||||
/**
|
||||
* Global identifier for the command to check volume levels of fading sources.
|
||||
*/
|
||||
public static final int CHECK_FADE_VOLUMES = 9;
|
||||
/**
|
||||
* Global identifier for the command to create a new source.
|
||||
*/
|
||||
public static final int NEW_SOURCE = 10;
|
||||
/**
|
||||
* Global identifier for the command to create a new raw data stream.
|
||||
*/
|
||||
public static final int RAW_DATA_STREAM = 11;
|
||||
/**
|
||||
* Global identifier for the command to create a source and immediately play it.
|
||||
*/
|
||||
public static final int QUICK_PLAY = 12;
|
||||
/**
|
||||
* Global identifier for the command to set a source's position in 3D space.
|
||||
*/
|
||||
public static final int SET_POSITION = 13;
|
||||
/**
|
||||
* Global identifier for the command to change a source's volume.
|
||||
*/
|
||||
public static final int SET_VOLUME = 14;
|
||||
/**
|
||||
* Global identifier for the command to change a source's pitch.
|
||||
*/
|
||||
public static final int SET_PITCH = 15;
|
||||
/**
|
||||
* Global identifier for the command to change a source's priority.
|
||||
*/
|
||||
public static final int SET_PRIORITY = 16;
|
||||
/**
|
||||
* Global identifier for the command to tell a source whether or not to loop.
|
||||
*/
|
||||
public static final int SET_LOOPING = 17;
|
||||
/**
|
||||
* Global identifier for the command to set a source's attenuation model.
|
||||
*/
|
||||
public static final int SET_ATTENUATION = 18;
|
||||
/**
|
||||
* Global identifier for the command to set a source's fade distance or rolloff
|
||||
* factor.
|
||||
*/
|
||||
public static final int SET_DIST_OR_ROLL = 19;
|
||||
/**
|
||||
* Global identifier for the command to change the Doppler factor.
|
||||
*/
|
||||
public static final int CHANGE_DOPPLER_FACTOR = 20;
|
||||
/**
|
||||
* Global identifier for the command to change the Doppler velocity.
|
||||
*/
|
||||
public static final int CHANGE_DOPPLER_VELOCITY = 21;
|
||||
/**
|
||||
* Global identifier for the command to set a source's velocity.
|
||||
*/
|
||||
public static final int SET_VELOCITY = 22;
|
||||
/**
|
||||
* Global identifier for the command to set a source's velocity.
|
||||
*/
|
||||
public static final int SET_LISTENER_VELOCITY = 23;
|
||||
/**
|
||||
* Global identifier for the command to play a source.
|
||||
*/
|
||||
public static final int PLAY = 24;
|
||||
/**
|
||||
* Global identifier for the command to play a source.
|
||||
*/
|
||||
public static final int FEED_RAW_AUDIO_DATA = 25;
|
||||
/**
|
||||
* Global identifier for the command to pause a source.
|
||||
*/
|
||||
public static final int PAUSE = 26;
|
||||
/**
|
||||
* Global identifier for the command to stop a source.
|
||||
*/
|
||||
public static final int STOP = 27;
|
||||
/**
|
||||
* Global identifier for the command to rewind a source.
|
||||
*/
|
||||
public static final int REWIND = 28;
|
||||
/**
|
||||
* Global identifier for the command to flush all queued data.
|
||||
*/
|
||||
public static final int FLUSH = 29;
|
||||
/**
|
||||
* Global identifier for the command to cull a source.
|
||||
*/
|
||||
public static final int CULL = 30;
|
||||
/**
|
||||
* Global identifier for the command to activate a source.
|
||||
*/
|
||||
public static final int ACTIVATE = 31;
|
||||
/**
|
||||
* Global identifier for the command to set a source as permanant or temporary.
|
||||
*/
|
||||
public static final int SET_TEMPORARY = 32;
|
||||
/**
|
||||
* Global identifier for the command to delete a source.
|
||||
*/
|
||||
public static final int REMOVE_SOURCE = 33;
|
||||
/**
|
||||
* Global identifier for the command to move the listner.
|
||||
*/
|
||||
public static final int MOVE_LISTENER = 34;
|
||||
/**
|
||||
* Global identifier for the command to set the listener's position.
|
||||
*/
|
||||
public static final int SET_LISTENER_POSITION = 35;
|
||||
/**
|
||||
* Global identifier for the command to turn the listener.
|
||||
*/
|
||||
public static final int TURN_LISTENER = 36;
|
||||
/**
|
||||
* Global identifier for the command to set the listener's turn angle.
|
||||
*/
|
||||
public static final int SET_LISTENER_ANGLE = 37;
|
||||
/**
|
||||
* Global identifier for the command to change the listener's orientation.
|
||||
*/
|
||||
public static final int SET_LISTENER_ORIENTATION = 38;
|
||||
/**
|
||||
* Global identifier for the command to change the master volume.
|
||||
*/
|
||||
public static final int SET_MASTER_VOLUME = 39;
|
||||
/**
|
||||
* Global identifier for the command to create a new library.
|
||||
*/
|
||||
public static final int NEW_LIBRARY = 40;
|
||||
|
||||
/**
|
||||
* Any buffer required for a command.
|
||||
*/
|
||||
public byte[] buffer;
|
||||
/**
|
||||
* Any int arguments required for a command.
|
||||
*/
|
||||
public int[] intArgs;
|
||||
/**
|
||||
* Any float arguments required for a command.
|
||||
*/
|
||||
public float[] floatArgs;
|
||||
/**
|
||||
* Any long arguments required for a command.
|
||||
*/
|
||||
public long[] longArgs;
|
||||
/**
|
||||
* Any boolean arguments required for a command.
|
||||
*/
|
||||
public boolean[] boolArgs;
|
||||
/**
|
||||
* Any String arguments required for a command.
|
||||
*/
|
||||
public String[] stringArgs;
|
||||
|
||||
/**
|
||||
* Any Class arguments required for a command.
|
||||
*/
|
||||
public Class[] classArgs;
|
||||
|
||||
/**
|
||||
* Any Object arguments required for a command.
|
||||
*/
|
||||
public Object[] objectArgs;
|
||||
|
||||
/**
|
||||
* Which command to execute.
|
||||
*/
|
||||
public int Command;
|
||||
|
||||
/**
|
||||
* Constructor used to create a command which doesn't require any arguments.
|
||||
* @param cmd Which command to execute.
|
||||
*/
|
||||
public CommandObject( int cmd )
|
||||
{
|
||||
Command = cmd;
|
||||
}
|
||||
/**
|
||||
* Constructor used to create a command which requires one integer argument.
|
||||
* @param cmd Which command to execute.
|
||||
* @param i The integer argument needed to execute this command.
|
||||
*/
|
||||
public CommandObject( int cmd, int i )
|
||||
{
|
||||
Command = cmd;
|
||||
intArgs = new int[1];
|
||||
intArgs[0] = i;
|
||||
}
|
||||
/**
|
||||
* Constructor used to create a command which requires one Library Class
|
||||
* argument.
|
||||
* @param cmd Which command to execute.
|
||||
* @param c The Library Class argument needed to execute this command.
|
||||
*/
|
||||
public CommandObject( int cmd, Class c )
|
||||
{
|
||||
Command = cmd;
|
||||
classArgs = new Class[1];
|
||||
classArgs[0] = c;
|
||||
}
|
||||
/**
|
||||
* Constructor used to create a command which requires one float argument.
|
||||
* @param cmd Which command to execute.
|
||||
* @param f The float argument needed to execute this command.
|
||||
*/
|
||||
public CommandObject( int cmd, float f )
|
||||
{
|
||||
Command = cmd;
|
||||
floatArgs = new float[1];
|
||||
floatArgs[0] = f;
|
||||
}
|
||||
/**
|
||||
* Constructor used to create a command which requires one String argument.
|
||||
* @param cmd Which command to execute.
|
||||
* @param s The String argument needed to execute this command.
|
||||
*/
|
||||
public CommandObject( int cmd, String s )
|
||||
{
|
||||
Command = cmd;
|
||||
stringArgs = new String[1];
|
||||
stringArgs[0] = s;
|
||||
}
|
||||
/**
|
||||
* Constructor used to create a command which requires one Object argument.
|
||||
* @param cmd Which command to execute.
|
||||
* @param o The Object argument needed to execute this command.
|
||||
*/
|
||||
public CommandObject( int cmd, Object o )
|
||||
{
|
||||
Command = cmd;
|
||||
objectArgs = new Object[1];
|
||||
objectArgs[0] = o;
|
||||
}
|
||||
/**
|
||||
* Constructor used to create a command which requires one String argument and
|
||||
* one Object argument.
|
||||
* @param cmd Which command to execute.
|
||||
* @param s The String argument needed to execute this command.
|
||||
* @param o The Object argument needed to execute this command.
|
||||
*/
|
||||
public CommandObject( int cmd, String s, Object o )
|
||||
{
|
||||
Command = cmd;
|
||||
stringArgs = new String[1];
|
||||
stringArgs[0] = s;
|
||||
objectArgs = new Object[1];
|
||||
objectArgs[0] = o;
|
||||
}
|
||||
/**
|
||||
* Constructor used to create a command which requires one String argument and
|
||||
* one byte buffer argument.
|
||||
* @param cmd Which command to execute.
|
||||
* @param s The String argument needed to execute this command.
|
||||
* @param buff The byte buffer argument needed to execute this command.
|
||||
*/
|
||||
public CommandObject( int cmd, String s, byte[] buff )
|
||||
{
|
||||
Command = cmd;
|
||||
stringArgs = new String[1];
|
||||
stringArgs[0] = s;
|
||||
buffer = buff;
|
||||
}
|
||||
/**
|
||||
* Constructor used to create a command which requires one String argument, one
|
||||
* Object argument, and one long argument.
|
||||
* @param cmd Which command to execute.
|
||||
* @param s The String argument needed to execute this command.
|
||||
* @param o The Object argument needed to execute this command.
|
||||
* @param l The long argument needed to execute this command.
|
||||
*/
|
||||
public CommandObject( int cmd, String s, Object o, long l )
|
||||
{
|
||||
Command = cmd;
|
||||
stringArgs = new String[1];
|
||||
stringArgs[0] = s;
|
||||
objectArgs = new Object[1];
|
||||
objectArgs[0] = o;
|
||||
longArgs = new long[1];
|
||||
longArgs[0] = l;
|
||||
}
|
||||
/**
|
||||
* Constructor used to create a command which requires one String argument, one
|
||||
* Object argument, and two long arguments.
|
||||
* @param cmd Which command to execute.
|
||||
* @param s The String argument needed to execute this command.
|
||||
* @param o The Object argument needed to execute this command.
|
||||
* @param l1 The first long argument needed to execute this command.
|
||||
* @param l2 The second long argument needed to execute this command.
|
||||
*/
|
||||
public CommandObject( int cmd, String s, Object o, long l1, long l2 )
|
||||
{
|
||||
Command = cmd;
|
||||
stringArgs = new String[1];
|
||||
stringArgs[0] = s;
|
||||
objectArgs = new Object[1];
|
||||
objectArgs[0] = o;
|
||||
longArgs = new long[2];
|
||||
longArgs[0] = l1;
|
||||
longArgs[1] = l2;
|
||||
}
|
||||
/**
|
||||
* Constructor used to create a command which requires two String arguments.
|
||||
* @param cmd Which command to execute.
|
||||
* @param s1 The first String argument needed to execute this command.
|
||||
* @param s2 The second String argument needed to execute this command.
|
||||
*/
|
||||
public CommandObject( int cmd, String s1, String s2 )
|
||||
{
|
||||
Command = cmd;
|
||||
stringArgs = new String[2];
|
||||
stringArgs[0] = s1;
|
||||
stringArgs[1] = s2;
|
||||
}
|
||||
/**
|
||||
* Constructor used to create a command which requires a String and an int as
|
||||
* arguments.
|
||||
* @param cmd Which command to execute.
|
||||
* @param s The String argument needed to execute this command.
|
||||
* @param i The integer argument needed to execute this command.
|
||||
*/
|
||||
public CommandObject( int cmd, String s, int i )
|
||||
{
|
||||
Command = cmd;
|
||||
intArgs = new int[1];
|
||||
stringArgs = new String[1];
|
||||
intArgs[0] = i;
|
||||
stringArgs[0] = s;
|
||||
}
|
||||
/**
|
||||
* Constructor used to create a command which requires a String and a float as
|
||||
* arguments.
|
||||
* @param cmd Which command to execute.
|
||||
* @param s The String argument needed to execute this command.
|
||||
* @param f The float argument needed to execute this command.
|
||||
*/
|
||||
public CommandObject( int cmd, String s, float f )
|
||||
{
|
||||
Command = cmd;
|
||||
floatArgs = new float[1];
|
||||
stringArgs = new String[1];
|
||||
floatArgs[0] = f;
|
||||
stringArgs[0] = s;
|
||||
}
|
||||
/**
|
||||
* Constructor used to create a command which requires a String and a boolean
|
||||
* as arguments.
|
||||
* @param cmd Which command to execute.
|
||||
* @param s The String argument needed to execute this command.
|
||||
* @param b The boolean argument needed to execute this command.
|
||||
*/
|
||||
public CommandObject( int cmd, String s, boolean b )
|
||||
{
|
||||
Command = cmd;
|
||||
boolArgs = new boolean[1];
|
||||
stringArgs = new String[1];
|
||||
boolArgs[0] = b;
|
||||
stringArgs[0] = s;
|
||||
}
|
||||
/**
|
||||
* Constructor used to create a command which requires three float arguments.
|
||||
* @param cmd Which command to execute.
|
||||
* @param f1 The first float argument needed to execute this command.
|
||||
* @param f2 The second float argument needed to execute this command.
|
||||
* @param f3 The third float argument needed to execute this command.
|
||||
*/
|
||||
public CommandObject( int cmd, float f1, float f2, float f3 )
|
||||
{
|
||||
Command = cmd;
|
||||
floatArgs = new float[3];
|
||||
floatArgs[0] = f1;
|
||||
floatArgs[1] = f2;
|
||||
floatArgs[2] = f3;
|
||||
}
|
||||
/**
|
||||
* Constructor used to create a command which a String and three float
|
||||
* arguments.
|
||||
* @param cmd Which command to execute.
|
||||
* @param s The String argument needed to execute this command.
|
||||
* @param f1 The first float argument needed to execute this command.
|
||||
* @param f2 The second float argument needed to execute this command.
|
||||
* @param f3 The third float argument needed to execute this command.
|
||||
*/
|
||||
public CommandObject( int cmd, String s, float f1, float f2, float f3 )
|
||||
{
|
||||
Command = cmd;
|
||||
floatArgs = new float[3];
|
||||
stringArgs = new String[1];
|
||||
floatArgs[0] = f1;
|
||||
floatArgs[1] = f2;
|
||||
floatArgs[2] = f3;
|
||||
stringArgs[0] = s;
|
||||
}
|
||||
/**
|
||||
* Constructor used to create a command which requires six float arguments.
|
||||
* @param cmd Which command to execute.
|
||||
* @param f1 The first float argument needed to execute this command.
|
||||
* @param f2 The second float argument needed to execute this command.
|
||||
* @param f3 The third float argument needed to execute this command.
|
||||
* @param f4 The fourth float argument needed to execute this command.
|
||||
* @param f5 The fifth float argument needed to execute this command.
|
||||
* @param f6 The sixth float argument needed to execute this command.
|
||||
*/
|
||||
public CommandObject( int cmd, float f1, float f2, float f3, float f4,
|
||||
float f5, float f6 )
|
||||
{
|
||||
Command = cmd;
|
||||
floatArgs = new float[6];
|
||||
floatArgs[0] = f1;
|
||||
floatArgs[1] = f2;
|
||||
floatArgs[2] = f3;
|
||||
floatArgs[3] = f4;
|
||||
floatArgs[4] = f5;
|
||||
floatArgs[5] = f6;
|
||||
}
|
||||
/**
|
||||
* Constructor used to create a command which requires several arguments.
|
||||
* @param cmd Which command to execute.
|
||||
* @param b1 The first boolean argument needed to execute this command.
|
||||
* @param b2 The second boolean argument needed to execute this command.
|
||||
* @param b3 The third boolean argument needed to execute this command.
|
||||
* @param s The String argument needed to execute this command.
|
||||
* @param o The Object argument needed to execute this command.
|
||||
* @param f1 The first float argument needed to execute this command.
|
||||
* @param f2 The second float argument needed to execute this command.
|
||||
* @param f3 The third float argument needed to execute this command.
|
||||
* @param i The integer argument needed to execute this command.
|
||||
* @param f4 The fourth float argument needed to execute this command.
|
||||
*/
|
||||
public CommandObject( int cmd,
|
||||
boolean b1, boolean b2, boolean b3,
|
||||
String s, Object o,
|
||||
float f1, float f2, float f3,
|
||||
int i, float f4 )
|
||||
{
|
||||
Command = cmd;
|
||||
intArgs = new int[1];
|
||||
floatArgs = new float[4];
|
||||
boolArgs = new boolean[3];
|
||||
stringArgs = new String[1];
|
||||
objectArgs = new Object[1];
|
||||
intArgs[0] = i;
|
||||
floatArgs[0] = f1;
|
||||
floatArgs[1] = f2;
|
||||
floatArgs[2] = f3;
|
||||
floatArgs[3] = f4;
|
||||
boolArgs[0] = b1;
|
||||
boolArgs[1] = b2;
|
||||
boolArgs[2] = b3;
|
||||
stringArgs[0] = s;
|
||||
objectArgs[0] = o;
|
||||
}
|
||||
/**
|
||||
* Constructor used to create a command which requires several arguments.
|
||||
* @param cmd Which command to execute.
|
||||
* @param b1 The first boolean argument needed to execute this command.
|
||||
* @param b2 The second boolean argument needed to execute this command.
|
||||
* @param b3 The third boolean argument needed to execute this command.
|
||||
* @param s The String argument needed to execute this command.
|
||||
* @param o The Object argument needed to execute this command.
|
||||
* @param f1 The first float argument needed to execute this command.
|
||||
* @param f2 The second float argument needed to execute this command.
|
||||
* @param f3 The third float argument needed to execute this command.
|
||||
* @param i The integer argument needed to execute this command.
|
||||
* @param f4 The fourth float argument needed to execute this command.
|
||||
* @param b4 The fourth boolean argument needed to execute this command.
|
||||
*/
|
||||
public CommandObject( int cmd,
|
||||
boolean b1, boolean b2, boolean b3,
|
||||
String s,
|
||||
Object o,
|
||||
float f1, float f2, float f3,
|
||||
int i, float f4, boolean b4 )
|
||||
{
|
||||
Command = cmd;
|
||||
intArgs = new int[1];
|
||||
floatArgs = new float[4];
|
||||
boolArgs = new boolean[4];
|
||||
stringArgs = new String[1];
|
||||
objectArgs = new Object[1];
|
||||
intArgs[0] = i;
|
||||
floatArgs[0] = f1;
|
||||
floatArgs[1] = f2;
|
||||
floatArgs[2] = f3;
|
||||
floatArgs[3] = f4;
|
||||
boolArgs[0] = b1;
|
||||
boolArgs[1] = b2;
|
||||
boolArgs[2] = b3;
|
||||
boolArgs[3] = b4;
|
||||
stringArgs[0] = s;
|
||||
objectArgs[0] = o;
|
||||
}
|
||||
/**
|
||||
* Constructor used to create a command which requires several arguments.
|
||||
* @param cmd Which command to execute.
|
||||
* @param o The Object argument needed to execute this command.
|
||||
* @param b The first boolean argument needed to execute this command.
|
||||
* @param s The String argument needed to execute this command.
|
||||
* @param f1 The first float argument needed to execute this command.
|
||||
* @param f2 The second float argument needed to execute this command.
|
||||
* @param f3 The third float argument needed to execute this command.
|
||||
* @param i The integer argument needed to execute this command.
|
||||
* @param f4 The fourth float argument needed to execute this command.
|
||||
*/
|
||||
public CommandObject( int cmd,
|
||||
Object o,
|
||||
boolean b,
|
||||
String s,
|
||||
float f1, float f2, float f3,
|
||||
int i,
|
||||
float f4 )
|
||||
{
|
||||
Command = cmd;
|
||||
intArgs = new int[1];
|
||||
floatArgs = new float[4];
|
||||
boolArgs = new boolean[1];
|
||||
stringArgs = new String[1];
|
||||
objectArgs = new Object[1];
|
||||
intArgs[0] = i;
|
||||
floatArgs[0] = f1;
|
||||
floatArgs[1] = f2;
|
||||
floatArgs[2] = f3;
|
||||
floatArgs[3] = f4;
|
||||
boolArgs[0] = b;
|
||||
stringArgs[0] = s;
|
||||
objectArgs[0] = o;
|
||||
}
|
||||
}
|
||||
178
src/lwjgl/java/paulscode/sound/CommandThread.java
Normal file
178
src/lwjgl/java/paulscode/sound/CommandThread.java
Normal file
@@ -0,0 +1,178 @@
|
||||
package paulscode.sound;
|
||||
|
||||
import net.lax1dude.eaglercraft.EaglerAdapter;
|
||||
|
||||
/**
|
||||
* The CommandThread class is designed to move all command processing into a
|
||||
* single thread to be run in the background and avoid conflicts between
|
||||
* threads. Commands are processed in the order that they were queued. The
|
||||
* arguements for each command are stored in a
|
||||
* {@link paulscode.sound.CommandObject CommandObject}. The Command Queue is
|
||||
* located in the {@link paulscode.sound.SoundSystem SoundSystem} class.
|
||||
* Calling kill() stops the thread, and this should be immediatly followed
|
||||
* by a call to interrupt() to wake up the thread so it may end. This class
|
||||
* also checks for temporary sources that are finished playing, and removes
|
||||
* them.
|
||||
*
|
||||
* NOTE: The command thread is created automatically by the sound system, so it
|
||||
* is unlikely that the user would ever need to use this class.
|
||||
*<br><br>
|
||||
*<b><i> SoundSystem License:</b></i><br><b><br>
|
||||
* You are free to use this library for any purpose, commercial or otherwise.
|
||||
* You may modify this library or source code, and distribute it any way you
|
||||
* like, provided the following conditions are met:
|
||||
*<br>
|
||||
* 1) You may not falsely claim to be the author of this library or any
|
||||
* unmodified portion of it.
|
||||
*<br>
|
||||
* 2) You may not copyright this library or a modified version of it and then
|
||||
* sue me for copyright infringement.
|
||||
*<br>
|
||||
* 3) If you modify the source code, you must clearly document the changes
|
||||
* made before redistributing the modified source code, so other users know
|
||||
* it is not the original code.
|
||||
*<br>
|
||||
* 4) You are not required to give me credit for this library in any derived
|
||||
* work, but if you do, you must also mention my website:
|
||||
* http://www.paulscode.com
|
||||
*<br>
|
||||
* 5) I the author will not be responsible for any damages (physical,
|
||||
* financial, or otherwise) caused by the use if this library or any part
|
||||
* of it.
|
||||
*<br>
|
||||
* 6) I the author do not guarantee, warrant, or make any representations,
|
||||
* either expressed or implied, regarding the use of this library or any
|
||||
* part of it.
|
||||
* <br><br>
|
||||
* Author: Paul Lamb
|
||||
* <br>
|
||||
* http://www.paulscode.com
|
||||
* </b>
|
||||
*/
|
||||
public class CommandThread extends SimpleThread
|
||||
{
|
||||
/**
|
||||
* Processes status messages, warnings, and error messages.
|
||||
*/
|
||||
protected SoundSystemLogger logger;
|
||||
|
||||
/**
|
||||
* Handle to the Sound System. This is where the Command Queue is located.
|
||||
*/
|
||||
private SoundSystem soundSystem;
|
||||
|
||||
/**
|
||||
* Name of this class.
|
||||
*/
|
||||
protected String className = "CommandThread";
|
||||
|
||||
/**
|
||||
* Constructor: Takes a handle to the SoundSystem object as a parameter.
|
||||
* @param s Handle to the SoundSystem.
|
||||
*/
|
||||
public CommandThread( SoundSystem s )
|
||||
{
|
||||
// grab a handle to the message logger:
|
||||
logger = SoundSystemConfig.getLogger();
|
||||
|
||||
soundSystem = s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shuts the thread down and removes references to all instantiated objects.
|
||||
* NOTE: Method alive() will return false when cleanup() has finished.
|
||||
*/
|
||||
@Override
|
||||
protected void cleanup()
|
||||
{
|
||||
kill();
|
||||
|
||||
logger = null;
|
||||
soundSystem = null;
|
||||
|
||||
super.cleanup(); // Important!
|
||||
}
|
||||
|
||||
/**
|
||||
* The main loop for processing commands. The Command Thread starts out
|
||||
* asleep, and it sleeps again after it finishes processing commands, so it
|
||||
* must be interrupted when commands are queued for processing.
|
||||
*/
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
long previousTime = EaglerAdapter.steadyTimeMillis();
|
||||
long currentTime = previousTime;
|
||||
|
||||
if( soundSystem == null )
|
||||
{
|
||||
errorMessage( "SoundSystem was null in method run().", 0 );
|
||||
cleanup();
|
||||
return;
|
||||
}
|
||||
|
||||
// Start out asleep:
|
||||
snooze( 3600000 );
|
||||
|
||||
while( !dying() )
|
||||
{
|
||||
// Perform user-specific source management:
|
||||
soundSystem.ManageSources();
|
||||
|
||||
// Process all queued commands:
|
||||
soundSystem.CommandQueue( null );
|
||||
|
||||
// Remove temporary sources every ten seconds:
|
||||
currentTime = EaglerAdapter.steadyTimeMillis();
|
||||
if( (!dying()) && ((currentTime - previousTime) > 10000) )
|
||||
{
|
||||
previousTime = currentTime;
|
||||
soundSystem.removeTemporarySources();
|
||||
}
|
||||
|
||||
// Wait for more commands:
|
||||
if( !dying() )
|
||||
snooze( 3600000 );
|
||||
}
|
||||
|
||||
cleanup(); // Important!
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a message.
|
||||
* @param message Message to print.
|
||||
*/
|
||||
protected void message( String message, int indent )
|
||||
{
|
||||
logger.message( message, indent );
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints an important message.
|
||||
* @param message Message to print.
|
||||
*/
|
||||
protected void importantMessage( String message, int indent )
|
||||
{
|
||||
logger.importantMessage( message, indent );
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the specified message if error is true.
|
||||
* @param error True or False.
|
||||
* @param message Message to print if error is true.
|
||||
* @return True if error is true.
|
||||
*/
|
||||
protected boolean errorCheck( boolean error, String message )
|
||||
{
|
||||
return logger.errorCheck( error, className, message, 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints an error message.
|
||||
* @param message Message to print.
|
||||
*/
|
||||
protected void errorMessage( String message, int indent )
|
||||
{
|
||||
logger.errorMessage( className, message, indent );
|
||||
}
|
||||
}
|
||||
153
src/lwjgl/java/paulscode/sound/FilenameURL.java
Normal file
153
src/lwjgl/java/paulscode/sound/FilenameURL.java
Normal file
@@ -0,0 +1,153 @@
|
||||
package paulscode.sound;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
/**
|
||||
* The FilenameURL class is designed to associate a String filename/identifier
|
||||
* with a URL. Handles either case where user supplies a String path or user
|
||||
* supplies a URL instance.
|
||||
*<br><br>
|
||||
*<b><i> SoundSystem License:</b></i><br><b><br>
|
||||
* You are free to use this library for any purpose, commercial or otherwise.
|
||||
* You may modify this library or source code, and distribute it any way you
|
||||
* like, provided the following conditions are met:
|
||||
*<br>
|
||||
* 1) You may not falsely claim to be the author of this library or any
|
||||
* unmodified portion of it.
|
||||
*<br>
|
||||
* 2) You may not copyright this library or a modified version of it and then
|
||||
* sue me for copyright infringement.
|
||||
*<br>
|
||||
* 3) If you modify the source code, you must clearly document the changes
|
||||
* made before redistributing the modified source code, so other users know
|
||||
* it is not the original code.
|
||||
*<br>
|
||||
* 4) You are not required to give me credit for this library in any derived
|
||||
* work, but if you do, you must also mention my website:
|
||||
* http://www.paulscode.com
|
||||
*<br>
|
||||
* 5) I the author will not be responsible for any damages (physical,
|
||||
* financial, or otherwise) caused by the use if this library or any part
|
||||
* of it.
|
||||
*<br>
|
||||
* 6) I the author do not guarantee, warrant, or make any representations,
|
||||
* either expressed or implied, regarding the use of this library or any
|
||||
* part of it.
|
||||
* <br><br>
|
||||
* Author: Paul Lamb
|
||||
* <br>
|
||||
* http://www.paulscode.com
|
||||
* </b>
|
||||
*/
|
||||
public class FilenameURL
|
||||
{
|
||||
/**
|
||||
* Processes status messages, warnings, and error messages.
|
||||
*/
|
||||
private SoundSystemLogger logger;
|
||||
|
||||
/**
|
||||
* Filename or identifier for the file.
|
||||
*/
|
||||
private String filename = null;
|
||||
|
||||
/**
|
||||
* URL interface to the file.
|
||||
*/
|
||||
private URL url = null;
|
||||
|
||||
/**
|
||||
* Constructor: Saves handles to the url and identifier. The identifier should
|
||||
* look like a filename, and it must have the correct extension so SoundSystem
|
||||
* knows what format to use for the file referenced by the URL instance.
|
||||
* @param url URL interface to a file.
|
||||
* @param identifier Identifier (filename) for the file.
|
||||
*/
|
||||
public FilenameURL( URL url, String identifier )
|
||||
{
|
||||
// grab a handle to the message logger:
|
||||
logger = SoundSystemConfig.getLogger();
|
||||
|
||||
filename = identifier;
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor: Saves a handle to the filename (used later to generate a URL
|
||||
* instance). The file may either be located within the
|
||||
* JAR or at an online location. If the file is online, filename must begin
|
||||
* with "http://", since that is how SoundSystem recognizes URL names.
|
||||
* @param filename Name of the file.
|
||||
*/
|
||||
public FilenameURL( String filename )
|
||||
{
|
||||
// grab a handle to the message logger:
|
||||
logger = SoundSystemConfig.getLogger();
|
||||
|
||||
this.filename = filename;
|
||||
url = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the filename/identifier.
|
||||
* @return Filename or identifier for the file.
|
||||
*/
|
||||
public String getFilename()
|
||||
{
|
||||
return filename;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the URL interface to the file. If a URL was not originally specified
|
||||
* in the constructor, then the first time this method is called it creates a
|
||||
* URL instance using the previously specified filename.
|
||||
* @return URL interface to the file.
|
||||
*/
|
||||
public URL getURL()
|
||||
{
|
||||
if( url == null )
|
||||
{
|
||||
// Check if the file is online or inside the JAR:
|
||||
if( filename.matches( SoundSystemConfig.PREFIX_URL ) )
|
||||
{
|
||||
// Online
|
||||
try
|
||||
{
|
||||
url = new URL( filename );
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
errorMessage( "Unable to access online URL in " +
|
||||
"method 'getURL'" );
|
||||
printStackTrace( e );
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Inside the JAR
|
||||
url = getClass().getClassLoader().getResource(
|
||||
SoundSystemConfig.getSoundFilesPackage() + filename );
|
||||
}
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints an error message.
|
||||
* @param message Message to print.
|
||||
*/
|
||||
private void errorMessage( String message )
|
||||
{
|
||||
logger.errorMessage( "MidiChannel", message, 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints an exception's error message followed by the stack trace.
|
||||
* @param e Exception containing the information to print.
|
||||
*/
|
||||
private void printStackTrace( Exception e )
|
||||
{
|
||||
logger.printStackTrace( e, 1 );
|
||||
}
|
||||
}
|
||||
119
src/lwjgl/java/paulscode/sound/ICodec.java
Normal file
119
src/lwjgl/java/paulscode/sound/ICodec.java
Normal file
@@ -0,0 +1,119 @@
|
||||
package paulscode.sound;
|
||||
|
||||
import java.net.URL;
|
||||
import javax.sound.sampled.AudioFormat;
|
||||
|
||||
/**
|
||||
* The ICodec interface provides a common interface for SoundSystem to use
|
||||
* for accessing external codec libraries.
|
||||
*<br><br>
|
||||
*<b><i> SoundSystem License:</b></i><br><b><br>
|
||||
* You are free to use this library for any purpose, commercial or otherwise.
|
||||
* You may modify this library or source code, and distribute it any way you
|
||||
* like, provided the following conditions are met:
|
||||
*<br>
|
||||
* 1) You may not falsely claim to be the author of this library or any
|
||||
* unmodified portion of it.
|
||||
*<br>
|
||||
* 2) You may not copyright this library or a modified version of it and then
|
||||
* sue me for copyright infringement.
|
||||
*<br>
|
||||
* 3) If you modify the source code, you must clearly document the changes
|
||||
* made before redistributing the modified source code, so other users know
|
||||
* it is not the original code.
|
||||
*<br>
|
||||
* 4) You are not required to give me credit for this library in any derived
|
||||
* work, but if you do, you must also mention my website:
|
||||
* http://www.paulscode.com
|
||||
*<br>
|
||||
* 5) I the author will not be responsible for any damages (physical,
|
||||
* financial, or otherwise) caused by the use if this library or any part
|
||||
* of it.
|
||||
*<br>
|
||||
* 6) I the author do not guarantee, warrant, or make any representations,
|
||||
* either expressed or implied, regarding the use of this library or any
|
||||
* part of it.
|
||||
* <br><br>
|
||||
* Author: Paul Lamb
|
||||
* <br>
|
||||
* http://www.paulscode.com
|
||||
* </b>
|
||||
*/
|
||||
public interface ICodec
|
||||
{
|
||||
/**
|
||||
* Should tell derived classes when they may need to reverse the byte order of
|
||||
* the data before returning it in the read() and readAll() methods. The
|
||||
* reason for the reversBytOrder method is because some external codec
|
||||
* libraries produce audio data in a format that some external audio libraries
|
||||
* require to be reversed. Derivatives of the Library and Source classes for
|
||||
* audio libraries which require this type of data to be reversed should call
|
||||
* the reverseByteOrder() method for all instances of ICodec that they use.
|
||||
* Derivatives of the ICodec interface for codec libraries which which produce
|
||||
* this type of data should use the reverseByteOrder() method to know when the
|
||||
* data needs to be reversed before returning it in the read() and readAll()
|
||||
* methods. If a particular codec library does not produce this type of data,
|
||||
* its derived ICodec class may disregard any calls to the reverseByteOrder()
|
||||
* method.
|
||||
* @param b True if the calling audio library requires byte-reversal by some codec libraries.
|
||||
*/
|
||||
public void reverseByteOrder( boolean b );
|
||||
|
||||
/**
|
||||
* Should make any preperations required before reading from the audio stream.
|
||||
* If another stream is already opened, it should be closed and a new audio
|
||||
* stream opened in its place. This method is used internally by SoundSystem
|
||||
* not only to initialize a stream, but also to rewind streams and to switch
|
||||
* stream sources on the fly.
|
||||
* @return False if an error occurred or if end of stream was reached.
|
||||
*/
|
||||
public boolean initialize( URL url );
|
||||
|
||||
/**
|
||||
* Should return false if the stream is busy initializing. To prevent bad
|
||||
* data from being returned by this method, derived classes should internally
|
||||
* synchronize with any elements used by both the initialized() and initialize()
|
||||
* methods.
|
||||
* @return True if steam is initialized.
|
||||
*/
|
||||
public boolean initialized();
|
||||
|
||||
/**
|
||||
* Should read in one stream buffer worth of audio data. See
|
||||
* {@link paulscode.sound.SoundSystemConfig SoundSystemConfig} for more
|
||||
* information about accessing and changing default settings.
|
||||
* @return The audio data wrapped into a SoundBuffer context.
|
||||
*/
|
||||
public SoundBuffer read();
|
||||
|
||||
/**
|
||||
* Should read in all the audio data from the stream (up to the default
|
||||
* "maximum file size". See
|
||||
* {@link paulscode.sound.SoundSystemConfig SoundSystemConfig} for more
|
||||
* information about accessing and changing default settings.
|
||||
* @return the audio data wrapped into a SoundBuffer context.
|
||||
*/
|
||||
public SoundBuffer readAll();
|
||||
|
||||
/**
|
||||
* Should return false if there is still more data available to be read in. To
|
||||
* prevent bad data from being returned by this method, derived classes should
|
||||
* internally synchronize with any elements used in both the endOfStream() and
|
||||
* the read() or readAll() methods.
|
||||
* @return True if end of stream was reached.
|
||||
*/
|
||||
public boolean endOfStream();
|
||||
|
||||
/**
|
||||
* Should close any open streams and remove references to all instantiated
|
||||
* objects.
|
||||
*/
|
||||
public void cleanup();
|
||||
|
||||
/**
|
||||
* Should return the audio format of the data being returned by the read() and
|
||||
* readAll() methods.
|
||||
* @return Information wrapped into an AudioFormat context.
|
||||
*/
|
||||
public AudioFormat getAudioFormat();
|
||||
}
|
||||
11
src/lwjgl/java/paulscode/sound/IStreamListener.java
Normal file
11
src/lwjgl/java/paulscode/sound/IStreamListener.java
Normal file
@@ -0,0 +1,11 @@
|
||||
package paulscode.sound;
|
||||
|
||||
public interface IStreamListener
|
||||
{
|
||||
/**
|
||||
* Notifies implementation that an End Of Stream was reached.
|
||||
* @param sourcename String identifier of the source which reached the EOS.
|
||||
* @param queueSize Number of items left the the stream's play queue, or zero if none.
|
||||
*/
|
||||
public void endOfStream( String sourcename, int queueSize );
|
||||
}
|
||||
1615
src/lwjgl/java/paulscode/sound/Library.java
Normal file
1615
src/lwjgl/java/paulscode/sound/Library.java
Normal file
File diff suppressed because it is too large
Load Diff
282
src/lwjgl/java/paulscode/sound/ListenerData.java
Normal file
282
src/lwjgl/java/paulscode/sound/ListenerData.java
Normal file
@@ -0,0 +1,282 @@
|
||||
package paulscode.sound;
|
||||
|
||||
/**
|
||||
* The listenerData class is used to store information about the
|
||||
* listener's position and orientation. A ListenerData object can be obtained
|
||||
* using SoundSystem's getListenerData() method. See
|
||||
* {@link paulscode.sound.Vector3D Vector3D} for more information about 3D
|
||||
* coordinates and vectors.
|
||||
*<br><br>
|
||||
*<b><i> SoundSystem License:</b></i><br><b><br>
|
||||
* You are free to use this library for any purpose, commercial or otherwise.
|
||||
* You may modify this library or source code, and distribute it any way you
|
||||
* like, provided the following conditions are met:
|
||||
*<br>
|
||||
* 1) You may not falsely claim to be the author of this library or any
|
||||
* unmodified portion of it.
|
||||
*<br>
|
||||
* 2) You may not copyright this library or a modified version of it and then
|
||||
* sue me for copyright infringement.
|
||||
*<br>
|
||||
* 3) If you modify the source code, you must clearly document the changes
|
||||
* made before redistributing the modified source code, so other users know
|
||||
* it is not the original code.
|
||||
*<br>
|
||||
* 4) You are not required to give me credit for this library in any derived
|
||||
* work, but if you do, you must also mention my website:
|
||||
* http://www.paulscode.com
|
||||
*<br>
|
||||
* 5) I the author will not be responsible for any damages (physical,
|
||||
* financial, or otherwise) caused by the use if this library or any part
|
||||
* of it.
|
||||
*<br>
|
||||
* 6) I the author do not guarantee, warrant, or make any representations,
|
||||
* either expressed or implied, regarding the use of this library or any
|
||||
* part of it.
|
||||
* <br><br>
|
||||
* Author: Paul Lamb
|
||||
* <br>
|
||||
* http://www.paulscode.com
|
||||
* </b>
|
||||
*/
|
||||
public class ListenerData
|
||||
{
|
||||
/**
|
||||
* Listener's position in 3D space
|
||||
*/
|
||||
public Vector3D position;
|
||||
/**
|
||||
* A normalized vector indicating the direction the listener is facing
|
||||
*/
|
||||
public Vector3D lookAt;
|
||||
/**
|
||||
* A normalized vector indicating the up direction
|
||||
*/
|
||||
public Vector3D up;
|
||||
/**
|
||||
* Listener's velocity in world-space
|
||||
*/
|
||||
public Vector3D velocity;
|
||||
|
||||
/**
|
||||
* Used for easy rotation along the x/z plane (for use in a first-person
|
||||
* shooter type of application).
|
||||
*/
|
||||
public float angle = 0.0f;
|
||||
|
||||
/**
|
||||
* Constructor: Set this listener data to the origin facing along the z-axis
|
||||
*/
|
||||
public ListenerData()
|
||||
{
|
||||
position = new Vector3D( 0.0f, 0.0f, 0.0f );
|
||||
lookAt = new Vector3D( 0.0f, 0.0f, -1.0f );
|
||||
up = new Vector3D( 0.0f, 1.0f, 0.0f );
|
||||
velocity = new Vector3D( 0.0f, 0.0f, 0.0f );
|
||||
angle = 0.0f;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor: Set this listener data to the specified values for position and
|
||||
* orientation.
|
||||
* @param pX Listener's X coordinate.
|
||||
* @param pY Listener's Y coordinate.
|
||||
* @param pZ Listener's Z coordinate.
|
||||
* @param lX X element of the look-at direction.
|
||||
* @param lY Y element of the look-at direction.
|
||||
* @param lZ Z element of the look-at direction.
|
||||
* @param uX X element of the up direction.
|
||||
* @param uY Y element of the up direction.
|
||||
* @param uZ Z element of the up direction.
|
||||
* @param a Angle in radians that the listener is turned counterclockwise around the y-axis.
|
||||
*/
|
||||
public ListenerData( float pX, float pY, float pZ, float lX, float lY,
|
||||
float lZ, float uX, float uY, float uZ, float a )
|
||||
{
|
||||
position = new Vector3D( pX, pY, pZ );
|
||||
lookAt = new Vector3D( lX, lY, lZ );
|
||||
up = new Vector3D( uX, uY, uZ );
|
||||
velocity = new Vector3D( 0.0f, 0.0f, 0.0f );
|
||||
angle = a;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor: Set this listener data to the specified values for position and
|
||||
* orientation.
|
||||
* @param p Position of the listener in 3D space.
|
||||
* @param l Normalized vector indicating the direction which the listener is facing.
|
||||
* @param u Normalized vector indicating the up direction.
|
||||
* @param a Angle in radians that the listener is turned counterclockwise around the y-axis.
|
||||
*/
|
||||
public ListenerData( Vector3D p, Vector3D l, Vector3D u, float a )
|
||||
{
|
||||
position = p.clone();
|
||||
lookAt = l.clone();
|
||||
up = u.clone();
|
||||
velocity = new Vector3D( 0.0f, 0.0f, 0.0f );
|
||||
angle = a;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change this listener data using the specified coordinates for position and
|
||||
* orientation.
|
||||
* @param pX Listener's X coordinate.
|
||||
* @param pY Listener's Y coordinate.
|
||||
* @param pZ Listener's Z coordinate.
|
||||
* @param lX X element of the look-at direction.
|
||||
* @param lY Y element of the look-at direction.
|
||||
* @param lZ Z element of the look-at direction.
|
||||
* @param uX X element of the up direction.
|
||||
* @param uY Y element of the up direction.
|
||||
* @param uZ Z element of the up direction.
|
||||
* @param a Angle in radians that the listener is turned counterclockwise around the y-axis.
|
||||
*/
|
||||
public void setData( float pX, float pY, float pZ, float lX, float lY,
|
||||
float lZ, float uX, float uY, float uZ, float a )
|
||||
{
|
||||
position.x = pX;
|
||||
position.y = pY;
|
||||
position.z = pZ;
|
||||
lookAt.x = lX;
|
||||
lookAt.y = lY;
|
||||
lookAt.z = lZ;
|
||||
up.x = uX;
|
||||
up.y = uY;
|
||||
up.z = uZ;
|
||||
angle = a;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change this listener data using the specified 3D vectors for position and
|
||||
* orientation.
|
||||
* @param p Position of the listener in 3D space.
|
||||
* @param l Normalized vector indicating the direction which the listener is facing.
|
||||
* @param u Normalized vector indicating the up direction.
|
||||
* @param a Angle in radians that the listener is turned counterclockwise around the y-axis.
|
||||
*/
|
||||
public void setData( Vector3D p, Vector3D l, Vector3D u, float a )
|
||||
{
|
||||
position.x = p.x;
|
||||
position.y = p.y;
|
||||
position.z = p.z;
|
||||
lookAt.x = l.x;
|
||||
lookAt.y = l.y;
|
||||
lookAt.z = l.z;
|
||||
up.x = u.x;
|
||||
up.y = u.y;
|
||||
up.z = u.z;
|
||||
angle = a;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change this listener data to match the specified listener data.
|
||||
* @param l Listener data to use.
|
||||
*/
|
||||
public void setData( ListenerData l )
|
||||
{
|
||||
position.x = l.position.x;
|
||||
position.y = l.position.y;
|
||||
position.z = l.position.z;
|
||||
lookAt.x = l.lookAt.x;
|
||||
lookAt.y = l.lookAt.y;
|
||||
lookAt.z = l.lookAt.z;
|
||||
up.x = l.up.x;
|
||||
up.y = l.up.y;
|
||||
up.z = l.up.z;
|
||||
angle = l.angle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change this listener's position using the specified coordinates.
|
||||
* @param x Listener's X coordinate.
|
||||
* @param y Listener's Y coordinate.
|
||||
* @param z Listener's Z coordinate.
|
||||
*/
|
||||
public void setPosition( float x, float y, float z )
|
||||
{
|
||||
position.x = x;
|
||||
position.y = y;
|
||||
position.z = z;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change this listener's position using the specified vector.
|
||||
* @param p New position.
|
||||
*/
|
||||
public void setPosition( Vector3D p )
|
||||
{
|
||||
position.x = p.x;
|
||||
position.y = p.y;
|
||||
position.z = p.z;
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the listeners orientation using the specified coordinates.
|
||||
* @param lX X element of the look-at direction.
|
||||
* @param lY Y element of the look-at direction.
|
||||
* @param lZ Z element of the look-at direction.
|
||||
* @param uX X element of the up direction.
|
||||
* @param uY Y element of the up direction.
|
||||
* @param uZ Z element of the up direction.
|
||||
*/
|
||||
public void setOrientation( float lX, float lY, float lZ,
|
||||
float uX, float uY, float uZ )
|
||||
{
|
||||
lookAt.x = lX;
|
||||
lookAt.y = lY;
|
||||
lookAt.z = lZ;
|
||||
up.x = uX;
|
||||
up.y = uY;
|
||||
up.z = uZ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the listeners orientation using the specified vectors.
|
||||
* @param l Normalized vector representing the look-at direction.
|
||||
* @param u Normalized vector representing the up direction.
|
||||
*/
|
||||
public void setOrientation( Vector3D l, Vector3D u )
|
||||
{
|
||||
lookAt.x = l.x;
|
||||
lookAt.y = l.y;
|
||||
lookAt.z = l.z;
|
||||
up.x = u.x;
|
||||
up.y = u.y;
|
||||
up.z = u.z;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change this listener's velocity in world-space.
|
||||
* @param v New velocity.
|
||||
*/
|
||||
public void setVelocity( Vector3D v )
|
||||
{
|
||||
velocity.x = v.x;
|
||||
velocity.y = v.y;
|
||||
velocity.z = v.z;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change this listener's velocity in world-space.
|
||||
* @param x New velocity along world x-axis.
|
||||
* @param y New velocity along world y-axis.
|
||||
* @param z New velocity along world z-axis.
|
||||
*/
|
||||
public void setVelocity( float x, float y, float z )
|
||||
{
|
||||
velocity.x = x;
|
||||
velocity.y = y;
|
||||
velocity.z = z;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the listener's angle counterclockwise around the y-axis.
|
||||
* @param a Angle in radians.
|
||||
*/
|
||||
public void setAngle( float a )
|
||||
{
|
||||
angle = a;
|
||||
lookAt.x = -1.0f * (float) Math.sin( angle );
|
||||
lookAt.z = -1.0f * (float) Math.cos( angle );
|
||||
}
|
||||
}
|
||||
1603
src/lwjgl/java/paulscode/sound/MidiChannel.java
Normal file
1603
src/lwjgl/java/paulscode/sound/MidiChannel.java
Normal file
File diff suppressed because it is too large
Load Diff
200
src/lwjgl/java/paulscode/sound/SimpleThread.java
Normal file
200
src/lwjgl/java/paulscode/sound/SimpleThread.java
Normal file
@@ -0,0 +1,200 @@
|
||||
package paulscode.sound;
|
||||
|
||||
|
||||
/**
|
||||
* The SimpleThread class is the template used to create all thread classes
|
||||
* used by in the SoundSystem library. It provides methods for common actions
|
||||
* like sleeping, killing, and checking liveness. NOTE: super.cleanup() must
|
||||
* be called at the bottom of overriden cleanup() methods, and cleanup()
|
||||
* must be called at the bottom of the run() method for all extended classes.
|
||||
*<br><br>
|
||||
*<b><i> SoundSystem License:</b></i><br><b><br>
|
||||
* You are free to use this library for any purpose, commercial or otherwise.
|
||||
* You may modify this library or source code, and distribute it any way you
|
||||
* like, provided the following conditions are met:
|
||||
*<br>
|
||||
* 1) You may not falsely claim to be the author of this library or any
|
||||
* unmodified portion of it.
|
||||
*<br>
|
||||
* 2) You may not copyright this library or a modified version of it and then
|
||||
* sue me for copyright infringement.
|
||||
*<br>
|
||||
* 3) If you modify the source code, you must clearly document the changes
|
||||
* made before redistributing the modified source code, so other users know
|
||||
* it is not the original code.
|
||||
*<br>
|
||||
* 4) You are not required to give me credit for this library in any derived
|
||||
* work, but if you do, you must also mention my website:
|
||||
* http://www.paulscode.com
|
||||
*<br>
|
||||
* 5) I the author will not be responsible for any damages (physical,
|
||||
* financial, or otherwise) caused by the use if this library or any part
|
||||
* of it.
|
||||
*<br>
|
||||
* 6) I the author do not guarantee, warrant, or make any representations,
|
||||
* either expressed or implied, regarding the use of this library or any
|
||||
* part of it.
|
||||
* <br><br>
|
||||
* Author: Paul Lamb
|
||||
* <br>
|
||||
* http://www.paulscode.com
|
||||
* </b>
|
||||
*/
|
||||
public class SimpleThread extends Thread
|
||||
{
|
||||
/**
|
||||
* Used to return a current value from one of the synchronized
|
||||
* boolean-interface methods.
|
||||
*/
|
||||
private static final boolean GET = false;
|
||||
|
||||
/**
|
||||
* Used to set the value in one of the synchronized boolean-interface methods.
|
||||
*/
|
||||
private static final boolean SET = true;
|
||||
|
||||
/**
|
||||
* Used when a parameter for one of the synchronized boolean-interface methods
|
||||
* is not aplicable.
|
||||
*/
|
||||
private static final boolean XXX = false;
|
||||
|
||||
/**
|
||||
* True when thread is running.
|
||||
*/
|
||||
private boolean alive = true;
|
||||
|
||||
/**
|
||||
* True when thread should end.
|
||||
*/
|
||||
private boolean kill = false;
|
||||
|
||||
/**
|
||||
* Removes all references to instantiated objects, and changes the thread's
|
||||
* state to "not alive". Method alive() returns false when this method has
|
||||
* completed. NOTE: super.cleanup() must be called at the bottom of overriden
|
||||
* cleanup() methods, and cleanup() must be called at the bottom of the run()
|
||||
* method for all extended classes.
|
||||
*/
|
||||
protected void cleanup()
|
||||
{
|
||||
kill( SET, true ); // tread needs to shut down
|
||||
alive( SET, false ); // thread has ended
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the thread's main loop. NOTES: Extended classes should check
|
||||
* method dying() often to know when the user wants the thread to shut down.
|
||||
* Method cleanup() must be called at the bottom of the run() method for all
|
||||
* extended classes.
|
||||
*/
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
/* How the run() method should be set up: */
|
||||
|
||||
|
||||
// Do your stuff here. Remember to check dying() often to know when
|
||||
// the user wants the thread to shut down.
|
||||
|
||||
// MUST call cleanup() at the bottom of Overridden run() method!!!!!
|
||||
cleanup(); // clears memory and sets status to dead.
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the rerun() method on a seperate thread, which calls run() when the
|
||||
* previous thread finishes.
|
||||
*/
|
||||
public void restart()
|
||||
{
|
||||
new Thread()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
rerun();
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Kills the previous thread, waits for it to die, then calls run().
|
||||
*/
|
||||
private void rerun()
|
||||
{
|
||||
kill( SET, true );
|
||||
while( alive( GET, XXX ) )
|
||||
{
|
||||
snooze( 100 );
|
||||
}
|
||||
alive( SET, true );
|
||||
kill( SET, false );
|
||||
run();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns false when the cleanup() method has finished. This method should be
|
||||
* used to know when the thread has been safely shut down.
|
||||
* @return True while the thread is alive.
|
||||
*/
|
||||
public boolean alive()
|
||||
{
|
||||
return alive( GET, XXX );
|
||||
}
|
||||
|
||||
/**
|
||||
* Causes method dying() to return true, letting the thread know it needs to
|
||||
* shut down.
|
||||
*/
|
||||
public void kill()
|
||||
{
|
||||
kill( SET, true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true when the thread is supposed to shut down.
|
||||
* @return True if the thread should die.
|
||||
*/
|
||||
protected boolean dying()
|
||||
{
|
||||
return kill( GET, XXX );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets or returns the value of boolean 'alive'.
|
||||
* @param action GET or SET.
|
||||
* @param value New value if action == SET, or XXX if action == GET.
|
||||
* @return True while the thread is alive.
|
||||
*/
|
||||
private synchronized boolean alive( boolean action, boolean value )
|
||||
{
|
||||
if( action == SET )
|
||||
alive = value;
|
||||
return alive;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets or returns the value of boolean 'kill'.
|
||||
* @param action GET or SET.
|
||||
* @param value New value if action == SET, or XXX if action == GET.
|
||||
* @return True if the thread should die.
|
||||
*/
|
||||
private synchronized boolean kill( boolean action, boolean value )
|
||||
{
|
||||
if( action == SET )
|
||||
kill = value;
|
||||
return kill;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sleeps for the specified number of milliseconds.
|
||||
*/
|
||||
protected void snooze( long milliseconds )
|
||||
{
|
||||
try
|
||||
{
|
||||
Thread.sleep( milliseconds );
|
||||
}
|
||||
catch( InterruptedException e ){}
|
||||
}
|
||||
}
|
||||
91
src/lwjgl/java/paulscode/sound/SoundBuffer.java
Normal file
91
src/lwjgl/java/paulscode/sound/SoundBuffer.java
Normal file
@@ -0,0 +1,91 @@
|
||||
package paulscode.sound;
|
||||
|
||||
import javax.sound.sampled.AudioFormat;
|
||||
|
||||
/**
|
||||
* The SoundBuffer class is used to wrap audio data along with the format in
|
||||
* which the data is stored.
|
||||
*<br><br>
|
||||
*<b><i> SoundSystem License:</b></i><br><b><br>
|
||||
* You are free to use this library for any purpose, commercial or otherwise.
|
||||
* You may modify this library or source code, and distribute it any way you
|
||||
* like, provided the following conditions are met:
|
||||
*<br>
|
||||
* 1) You may not falsely claim to be the author of this library or any
|
||||
* unmodified portion of it.
|
||||
*<br>
|
||||
* 2) You may not copyright this library or a modified version of it and then
|
||||
* sue me for copyright infringement.
|
||||
*<br>
|
||||
* 3) If you modify the source code, you must clearly document the changes
|
||||
* made before redistributing the modified source code, so other users know
|
||||
* it is not the original code.
|
||||
*<br>
|
||||
* 4) You are not required to give me credit for this library in any derived
|
||||
* work, but if you do, you must also mention my website:
|
||||
* http://www.paulscode.com
|
||||
*<br>
|
||||
* 5) I the author will not be responsible for any damages (physical,
|
||||
* financial, or otherwise) caused by the use if this library or any part
|
||||
* of it.
|
||||
*<br>
|
||||
* 6) I the author do not guarantee, warrant, or make any representations,
|
||||
* either expressed or implied, regarding the use of this library or any
|
||||
* part of it.
|
||||
* <br><br>
|
||||
* Author: Paul Lamb
|
||||
* <br>
|
||||
* http://www.paulscode.com
|
||||
* </b>
|
||||
*/
|
||||
public class SoundBuffer
|
||||
{
|
||||
/**
|
||||
* The actual audio data.
|
||||
*/
|
||||
public byte[] audioData;
|
||||
/**
|
||||
* The audio format in which the data is stored.
|
||||
*/
|
||||
public AudioFormat audioFormat;
|
||||
|
||||
/**
|
||||
* Constructor: Wraps the specified data with the specified audio format.
|
||||
*
|
||||
* @param audioData The actual audio data.
|
||||
* @param audioFormat The audio format in which the data is stored.
|
||||
*/
|
||||
public SoundBuffer( byte[] audioData, AudioFormat audioFormat )
|
||||
{
|
||||
this.audioData = audioData;
|
||||
this.audioFormat = audioFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes handles to all instantiated objects.
|
||||
*/
|
||||
public void cleanup()
|
||||
{
|
||||
audioData = null;
|
||||
audioFormat = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Trims down the size of the audio data if it is larger than the specified
|
||||
* maximum length.
|
||||
*
|
||||
* @param maxLength Maximum size this buffer may be.
|
||||
*/
|
||||
public void trimData( int maxLength )
|
||||
{
|
||||
if( audioData == null || maxLength == 0 )
|
||||
audioData = null;
|
||||
else if( audioData.length > maxLength )
|
||||
{
|
||||
byte[] trimmedArray = new byte[maxLength];
|
||||
System.arraycopy( audioData, 0, trimmedArray, 0,
|
||||
maxLength );
|
||||
audioData = trimmedArray;
|
||||
}
|
||||
}
|
||||
}
|
||||
2895
src/lwjgl/java/paulscode/sound/SoundSystem.java
Normal file
2895
src/lwjgl/java/paulscode/sound/SoundSystem.java
Normal file
File diff suppressed because it is too large
Load Diff
1074
src/lwjgl/java/paulscode/sound/SoundSystemConfig.java
Normal file
1074
src/lwjgl/java/paulscode/sound/SoundSystemConfig.java
Normal file
File diff suppressed because it is too large
Load Diff
94
src/lwjgl/java/paulscode/sound/SoundSystemException.java
Normal file
94
src/lwjgl/java/paulscode/sound/SoundSystemException.java
Normal file
@@ -0,0 +1,94 @@
|
||||
package paulscode.sound;
|
||||
|
||||
/**
|
||||
* The SoundSystemException class is used to provide information about serious
|
||||
* errors.
|
||||
*<br><br>
|
||||
*<b><i> SoundSystem License:</b></i><br><b><br>
|
||||
* You are free to use this library for any purpose, commercial or otherwise.
|
||||
* You may modify this library or source code, and distribute it any way you
|
||||
* like, provided the following conditions are met:
|
||||
*<br>
|
||||
* 1) You may not falsely claim to be the author of this library or any
|
||||
* unmodified portion of it.
|
||||
*<br>
|
||||
* 2) You may not copyright this library or a modified version of it and then
|
||||
* sue me for copyright infringement.
|
||||
*<br>
|
||||
* 3) If you modify the source code, you must clearly document the changes
|
||||
* made before redistributing the modified source code, so other users know
|
||||
* it is not the original code.
|
||||
*<br>
|
||||
* 4) You are not required to give me credit for this library in any derived
|
||||
* work, but if you do, you must also mention my website:
|
||||
* http://www.paulscode.com
|
||||
*<br>
|
||||
* 5) I the author will not be responsible for any damages (physical,
|
||||
* financial, or otherwise) caused by the use if this library or any part
|
||||
* of it.
|
||||
*<br>
|
||||
* 6) I the author do not guarantee, warrant, or make any representations,
|
||||
* either expressed or implied, regarding the use of this library or any
|
||||
* part of it.
|
||||
* <br><br>
|
||||
* Author: Paul Lamb
|
||||
* <br>
|
||||
* http://www.paulscode.com
|
||||
* </b>
|
||||
*/
|
||||
public class SoundSystemException extends Exception
|
||||
{
|
||||
/**
|
||||
* Global identifier for no problem.
|
||||
*/
|
||||
public static final int ERROR_NONE = 0;
|
||||
/**
|
||||
* Global identifier for a generic exception.
|
||||
*/
|
||||
public static final int UNKNOWN_ERROR = 1;
|
||||
/**
|
||||
* Global identifier for a null parameter.
|
||||
*/
|
||||
public static final int NULL_PARAMETER = 2;
|
||||
/**
|
||||
* Global identifier for a class type mismatch.
|
||||
*/
|
||||
public static final int CLASS_TYPE_MISMATCH = 3;
|
||||
/**
|
||||
* Global identifier for the sound library does not exist.
|
||||
*/
|
||||
public static final int LIBRARY_NULL = 4;
|
||||
/**
|
||||
* Global identifier for the sound library does not exist.
|
||||
*/
|
||||
public static final int LIBRARY_TYPE = 5;
|
||||
|
||||
/**
|
||||
* Holds a global identifier indicating the type of exception.
|
||||
*/
|
||||
private int myType = UNKNOWN_ERROR;
|
||||
|
||||
/**
|
||||
* Constructor: Generic exception. Specify the error message.
|
||||
*/
|
||||
public SoundSystemException( String message )
|
||||
{
|
||||
super( message );
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor: Specify the error message and type of exception.
|
||||
* @param message Description of the problem.
|
||||
* @param type Global identifier for type of exception.
|
||||
*/
|
||||
public SoundSystemException( String message, int type )
|
||||
{
|
||||
super( message );
|
||||
myType = type;
|
||||
}
|
||||
|
||||
public int getType()
|
||||
{
|
||||
return myType;
|
||||
}
|
||||
}
|
||||
173
src/lwjgl/java/paulscode/sound/SoundSystemLogger.java
Normal file
173
src/lwjgl/java/paulscode/sound/SoundSystemLogger.java
Normal file
@@ -0,0 +1,173 @@
|
||||
package paulscode.sound;
|
||||
|
||||
/**
|
||||
* The SoundSystemLogger class handles all status messages, warnings, and error
|
||||
* messages for the SoundSystem library. This class can be extended and
|
||||
* methods overriden to change how messages are handled. To do this, the
|
||||
* overridden class should be instantiated, and a call should be made to method
|
||||
* SoundSystemConfig.setLogger() BEFORE creating the SoundSystem object. If
|
||||
* the setLogger() method is called after the SoundSystem has been created,
|
||||
* there will be handles floating around to two different message loggers, and
|
||||
* the results will be undesirable.
|
||||
* See {@link paulscode.sound.SoundSystemConfig SoundSystemConfig} for more
|
||||
* information about changing default settings. If an alternate logger is not
|
||||
* set by the user, then an instance of this base class will be automatically
|
||||
* created by default when the SoundSystem class is instantiated.
|
||||
*<br><br>
|
||||
*<b><i> SoundSystem License:</b></i><br><b><br>
|
||||
* You are free to use this library for any purpose, commercial or otherwise.
|
||||
* You may modify this library or source code, and distribute it any way you
|
||||
* like, provided the following conditions are met:
|
||||
*<br>
|
||||
* 1) You may not falsely claim to be the author of this library or any
|
||||
* unmodified portion of it.
|
||||
*<br>
|
||||
* 2) You may not copyright this library or a modified version of it and then
|
||||
* sue me for copyright infringement.
|
||||
*<br>
|
||||
* 3) If you modify the source code, you must clearly document the changes
|
||||
* made before redistributing the modified source code, so other users know
|
||||
* it is not the original code.
|
||||
*<br>
|
||||
* 4) You are not required to give me credit for this library in any derived
|
||||
* work, but if you do, you must also mention my website:
|
||||
* http://www.paulscode.com
|
||||
*<br>
|
||||
* 5) I the author will not be responsible for any damages (physical,
|
||||
* financial, or otherwise) caused by the use if this library or any part
|
||||
* of it.
|
||||
*<br>
|
||||
* 6) I the author do not guarantee, warrant, or make any representations,
|
||||
* either expressed or implied, regarding the use of this library or any
|
||||
* part of it.
|
||||
* <br><br>
|
||||
* Author: Paul Lamb
|
||||
* <br>
|
||||
* http://www.paulscode.com
|
||||
* </b>
|
||||
*/
|
||||
public class SoundSystemLogger
|
||||
{
|
||||
/**
|
||||
* Prints a message.
|
||||
* @param message Message to print.
|
||||
* @param indent Number of tabs to indent the message.
|
||||
*/
|
||||
public void message( String message, int indent )
|
||||
{
|
||||
String messageText;
|
||||
// Determine how many spaces to indent:
|
||||
String spacer = "";
|
||||
for( int x = 0; x < indent; x++ )
|
||||
{
|
||||
spacer += " ";
|
||||
}
|
||||
// indent the message:
|
||||
messageText = spacer + message;
|
||||
|
||||
// Print the message:
|
||||
System.out.println( messageText );
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints an important message.
|
||||
* @param message Message to print.
|
||||
* @param indent Number of tabs to indent the message.
|
||||
*/
|
||||
public void importantMessage( String message, int indent )
|
||||
{
|
||||
String messageText;
|
||||
// Determine how many spaces to indent:
|
||||
String spacer = "";
|
||||
for( int x = 0; x < indent; x++ )
|
||||
{
|
||||
spacer += " ";
|
||||
}
|
||||
// indent the message:
|
||||
messageText = spacer + message;
|
||||
|
||||
// Print the message:
|
||||
System.out.println( messageText );
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the specified message if error is true.
|
||||
* @param error True or False.
|
||||
* @param classname Name of the class checking for an error.
|
||||
* @param message Message to print if error is true.
|
||||
* @param indent Number of tabs to indent the message.
|
||||
* @return True if error is true.
|
||||
*/
|
||||
public boolean errorCheck( boolean error, String classname, String message,
|
||||
int indent )
|
||||
{
|
||||
if( error )
|
||||
errorMessage( classname, message, indent );
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the classname which generated the error, followed by the error
|
||||
* message.
|
||||
* @param classname Name of the class which generated the error.
|
||||
* @param message The actual error message.
|
||||
* @param indent Number of tabs to indent the message.
|
||||
*/
|
||||
public void errorMessage( String classname, String message, int indent )
|
||||
{
|
||||
String headerLine, messageText;
|
||||
// Determine how many spaces to indent:
|
||||
String spacer = "";
|
||||
for( int x = 0; x < indent; x++ )
|
||||
{
|
||||
spacer += " ";
|
||||
}
|
||||
// indent the header:
|
||||
headerLine = spacer + "Error in class '" + classname + "'";
|
||||
// indent the message one more than the header:
|
||||
messageText = " " + spacer + message;
|
||||
|
||||
// Print the error message:
|
||||
System.out.println( headerLine );
|
||||
System.out.println( messageText );
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints an exception's error message followed by the stack trace.
|
||||
* @param e Exception containing the information to print.
|
||||
* @param indent Number of tabs to indent the message and stack trace.
|
||||
*/
|
||||
public void printStackTrace( Exception e, int indent )
|
||||
{
|
||||
printExceptionMessage( e, indent );
|
||||
importantMessage( "STACK TRACE:", indent );
|
||||
if( e == null )
|
||||
return;
|
||||
|
||||
StackTraceElement[] stack = e.getStackTrace();
|
||||
if( stack == null )
|
||||
return;
|
||||
|
||||
StackTraceElement line;
|
||||
for( int x = 0; x < stack.length; x++ )
|
||||
{
|
||||
line = stack[x];
|
||||
if( line != null )
|
||||
message( line.toString(), indent + 1 );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints an exception's error message.
|
||||
* @param e Exception containing the message to print.
|
||||
* @param indent Number of tabs to indent the message.
|
||||
*/
|
||||
public void printExceptionMessage( Exception e, int indent )
|
||||
{
|
||||
importantMessage( "ERROR MESSAGE:", indent );
|
||||
if( e.getMessage() == null )
|
||||
message( "(none)", indent + 1 );
|
||||
else
|
||||
message( e.getMessage(), indent + 1 );
|
||||
}
|
||||
}
|
||||
1346
src/lwjgl/java/paulscode/sound/Source.java
Normal file
1346
src/lwjgl/java/paulscode/sound/Source.java
Normal file
File diff suppressed because it is too large
Load Diff
303
src/lwjgl/java/paulscode/sound/StreamThread.java
Normal file
303
src/lwjgl/java/paulscode/sound/StreamThread.java
Normal file
@@ -0,0 +1,303 @@
|
||||
package paulscode.sound;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
|
||||
/**
|
||||
* The StreamThread class is used to process all streaming sources. This
|
||||
* thread starts out asleep, and it sleeps when all streaming sources are
|
||||
* finished playing, so it is necessary to call interrupt() after adding new
|
||||
* streaming sources to the list.
|
||||
*<br><br>
|
||||
*<b><i> SoundSystem License:</b></i><br><b><br>
|
||||
* You are free to use this library for any purpose, commercial or otherwise.
|
||||
* You may modify this library or source code, and distribute it any way you
|
||||
* like, provided the following conditions are met:
|
||||
*<br>
|
||||
* 1) You may not falsely claim to be the author of this library or any
|
||||
* unmodified portion of it.
|
||||
*<br>
|
||||
* 2) You may not copyright this library or a modified version of it and then
|
||||
* sue me for copyright infringement.
|
||||
*<br>
|
||||
* 3) If you modify the source code, you must clearly document the changes
|
||||
* made before redistributing the modified source code, so other users know
|
||||
* it is not the original code.
|
||||
*<br>
|
||||
* 4) You are not required to give me credit for this library in any derived
|
||||
* work, but if you do, you must also mention my website:
|
||||
* http://www.paulscode.com
|
||||
*<br>
|
||||
* 5) I the author will not be responsible for any damages (physical,
|
||||
* financial, or otherwise) caused by the use if this library or any part
|
||||
* of it.
|
||||
*<br>
|
||||
* 6) I the author do not guarantee, warrant, or make any representations,
|
||||
* either expressed or implied, regarding the use of this library or any
|
||||
* part of it.
|
||||
* <br><br>
|
||||
* Author: Paul Lamb
|
||||
* <br>
|
||||
* http://www.paulscode.com
|
||||
* </b>
|
||||
*
|
||||
*/
|
||||
public class StreamThread extends SimpleThread
|
||||
{
|
||||
/**
|
||||
* Processes status messages, warnings, and error messages.
|
||||
*/
|
||||
private SoundSystemLogger logger;
|
||||
|
||||
/**
|
||||
* List of sources that are currently streaming.
|
||||
*/
|
||||
private List<Source> streamingSources;
|
||||
|
||||
/**
|
||||
* Used to synchronize access to the streaming sources list.
|
||||
*/
|
||||
private final Object listLock = new Object();
|
||||
|
||||
/**
|
||||
* Constructor: Grabs a handle to the message logger and instantiates the
|
||||
* streaming sources list.
|
||||
*/
|
||||
public StreamThread()
|
||||
{
|
||||
// grab a handle to the message logger:
|
||||
logger = SoundSystemConfig.getLogger();
|
||||
|
||||
streamingSources = new LinkedList<Source>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all references to instantiated objects, and changes the thread's
|
||||
* state to "not alive". Method alive() returns false when the cleanup()
|
||||
* method has completed.
|
||||
*/
|
||||
@Override
|
||||
protected void cleanup()
|
||||
{
|
||||
kill();
|
||||
super.cleanup(); // Important!!
|
||||
}
|
||||
|
||||
/**
|
||||
* The main loop for processing commands. The thread sleeps when it finishes
|
||||
* processing commands, and it must be interrupted to process more.
|
||||
*/
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
ListIterator<Source> iter;
|
||||
Source src;
|
||||
|
||||
// Start out asleep:
|
||||
snooze( 3600000 );
|
||||
|
||||
while( !dying() )
|
||||
{
|
||||
while( !dying() && !streamingSources.isEmpty() )
|
||||
{
|
||||
// Make sure noone else is accessing the list of sources:
|
||||
synchronized( listLock )
|
||||
{
|
||||
iter = streamingSources.listIterator();
|
||||
while( !dying() && iter.hasNext() )
|
||||
{
|
||||
src = iter.next();
|
||||
// If this is a removed source, we cleanup here and then let normal cleanup run - https://github.com/MinecraftForge/MinecraftForge/pull/4765
|
||||
if (src!=null && src.removed)
|
||||
{
|
||||
src.cleanup();
|
||||
src = null;
|
||||
}
|
||||
if( src == null )
|
||||
{
|
||||
iter.remove();
|
||||
}
|
||||
else if( src.stopped() )
|
||||
{
|
||||
if( !src.rawDataStream )
|
||||
iter.remove();
|
||||
}
|
||||
else if( !src.active() )
|
||||
{
|
||||
if( src.toLoop || src.rawDataStream )
|
||||
src.toPlay = true;
|
||||
iter.remove();
|
||||
}
|
||||
else if( !src.paused() )
|
||||
{
|
||||
src.checkFadeOut();
|
||||
if( (!src.stream()) && (!src.rawDataStream) )
|
||||
{
|
||||
if( src.channel == null
|
||||
|| !src.channel.processBuffer() )
|
||||
{
|
||||
if( src.nextCodec == null )
|
||||
{
|
||||
src.readBuffersFromNextSoundInSequence();
|
||||
}
|
||||
/*
|
||||
if( src.getSoundSequenceQueueSize() > 0 )
|
||||
{
|
||||
src.incrementSoundSequence();
|
||||
}
|
||||
|
||||
// check if this is a looping source
|
||||
else*/ if( src.toLoop )
|
||||
{
|
||||
// wait for stream to finish playing
|
||||
if( !src.playing() )
|
||||
{
|
||||
// Generate an EOS event:
|
||||
SoundSystemConfig.notifyEOS(
|
||||
src.sourcename,
|
||||
src.getSoundSequenceQueueSize()
|
||||
);
|
||||
// Check if the source is currently
|
||||
// in the process of fading out.
|
||||
if( src.checkFadeOut() )
|
||||
{
|
||||
// Source is fading out.
|
||||
// Keep looping until it
|
||||
// finishes.
|
||||
src.preLoad = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Source is not fading out.
|
||||
// If there is another sound in
|
||||
// the sequence, switch to it
|
||||
// before replaying.
|
||||
src.incrementSoundSequence();
|
||||
src.preLoad = true; // replay
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// wait for stream to finish playing
|
||||
if( !src.playing() )
|
||||
{
|
||||
// Generate an EOS event:
|
||||
SoundSystemConfig.notifyEOS(
|
||||
src.sourcename,
|
||||
src.getSoundSequenceQueueSize()
|
||||
);
|
||||
// Check if the source is currently
|
||||
// in the process of fading out
|
||||
if( !src.checkFadeOut() )
|
||||
{
|
||||
// Source is not fading out.
|
||||
// Play anything else that is
|
||||
// in the sound sequence queue.
|
||||
if(
|
||||
src.incrementSoundSequence() )
|
||||
src.preLoad = true;
|
||||
else
|
||||
iter.remove(); // finished
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if( !dying() && !streamingSources.isEmpty() )
|
||||
snooze( 20 ); // sleep a bit so we don't peg the cpu
|
||||
}
|
||||
if( !dying() && streamingSources.isEmpty() )
|
||||
snooze( 3600000 ); // sleep until there is more to do.
|
||||
}
|
||||
|
||||
cleanup(); // Important!!
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new streaming source to the list. If another source in the list is
|
||||
* already playing on the same channel, it is stopped and removed from the
|
||||
* list.
|
||||
* @param source New source to stream.
|
||||
*/
|
||||
public void watch( Source source )
|
||||
{
|
||||
// make sure the source exists:
|
||||
if( source == null )
|
||||
return;
|
||||
|
||||
// make sure we aren't already watching this source:
|
||||
if( streamingSources.contains( source ) )
|
||||
return;
|
||||
|
||||
ListIterator<Source> iter;
|
||||
Source src;
|
||||
|
||||
// Make sure noone else is accessing the list of sources:
|
||||
synchronized( listLock )
|
||||
{
|
||||
// Any currently watched source which is null or playing on the
|
||||
// same channel as the new source should be stopped and removed
|
||||
// from the list.
|
||||
iter = streamingSources.listIterator();
|
||||
while( iter.hasNext() )
|
||||
{
|
||||
src = iter.next();
|
||||
if( src == null )
|
||||
{
|
||||
iter.remove();
|
||||
}
|
||||
else if( source.channel == src.channel )
|
||||
{
|
||||
src.stop();
|
||||
iter.remove();
|
||||
}
|
||||
}
|
||||
|
||||
// Add the new source to the list:
|
||||
streamingSources.add( source );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a message.
|
||||
* @param message Message to print.
|
||||
*/
|
||||
private void message( String message )
|
||||
{
|
||||
logger.message( message, 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints an important message.
|
||||
* @param message Message to print.
|
||||
*/
|
||||
private void importantMessage( String message )
|
||||
{
|
||||
logger.importantMessage( message, 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the specified message if error is true.
|
||||
* @param error True or False.
|
||||
* @param message Message to print if error is true.
|
||||
* @return True if error is true.
|
||||
*/
|
||||
private boolean errorCheck( boolean error, String message )
|
||||
{
|
||||
return logger.errorCheck( error, "StreamThread", message, 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints an error message.
|
||||
* @param message Message to print.
|
||||
*/
|
||||
private void errorMessage( String message )
|
||||
{
|
||||
logger.errorMessage( "StreamThread", message, 0 );
|
||||
}
|
||||
}
|
||||
210
src/lwjgl/java/paulscode/sound/Vector3D.java
Normal file
210
src/lwjgl/java/paulscode/sound/Vector3D.java
Normal file
@@ -0,0 +1,210 @@
|
||||
package paulscode.sound;
|
||||
|
||||
/**
|
||||
* The Vector3D class contains methods to simplify common 3D vector functions,
|
||||
* such as cross and dot product, normalize, etc.
|
||||
*<br><br>
|
||||
*<b><i> SoundSystem License:</b></i><br><b><br>
|
||||
* You are free to use this library for any purpose, commercial or otherwise.
|
||||
* You may modify this library or source code, and distribute it any way you
|
||||
* like, provided the following conditions are met:
|
||||
*<br>
|
||||
* 1) You may not falsely claim to be the author of this library or any
|
||||
* unmodified portion of it.
|
||||
*<br>
|
||||
* 2) You may not copyright this library or a modified version of it and then
|
||||
* sue me for copyright infringement.
|
||||
*<br>
|
||||
* 3) If you modify the source code, you must clearly document the changes
|
||||
* made before redistributing the modified source code, so other users know
|
||||
* it is not the original code.
|
||||
*<br>
|
||||
* 4) You are not required to give me credit for this library in any derived
|
||||
* work, but if you do, you must also mention my website:
|
||||
* http://www.paulscode.com
|
||||
*<br>
|
||||
* 5) I the author will not be responsible for any damages (physical,
|
||||
* financial, or otherwise) caused by the use if this library or any part
|
||||
* of it.
|
||||
*<br>
|
||||
* 6) I the author do not guarantee, warrant, or make any representations,
|
||||
* either expressed or implied, regarding the use of this library or any
|
||||
* part of it.
|
||||
* <br><br>
|
||||
* Author: Paul Lamb
|
||||
* <br>
|
||||
* http://www.paulscode.com
|
||||
* </b>
|
||||
*/
|
||||
public class Vector3D
|
||||
{
|
||||
|
||||
/**
|
||||
* The vector's X coordinate.
|
||||
*/
|
||||
public float x;
|
||||
|
||||
/**
|
||||
* The vector's Y coordinate.
|
||||
*/
|
||||
public float y;
|
||||
|
||||
/**
|
||||
* The vector's Z coordinate.
|
||||
*/
|
||||
public float z;
|
||||
|
||||
/**
|
||||
* Constructor: Places the vector at the origin.
|
||||
*/
|
||||
public Vector3D()
|
||||
{
|
||||
x = 0.0f;
|
||||
y = 0.0f;
|
||||
z = 0.0f;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor: Places the vector at the specified 3D coordinates.
|
||||
* @param nx X coordinate for the new vector.
|
||||
* @param ny Y coordinate for the new vector.
|
||||
* @param nz Z coordinate for the new vector.
|
||||
*/
|
||||
public Vector3D( float nx, float ny, float nz )
|
||||
{
|
||||
x = nx;
|
||||
y = ny;
|
||||
z = nz;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new instance containing the same information as this one.
|
||||
* @return A new Vector3D.
|
||||
*/
|
||||
@Override
|
||||
public Vector3D clone()
|
||||
{
|
||||
return new Vector3D( x, y, z );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a vector containing the cross-product: A cross B.
|
||||
* @param A First vector in the cross product.
|
||||
* @param B Second vector in the cross product.
|
||||
* @return A new Vector3D.
|
||||
*/
|
||||
public Vector3D cross( Vector3D A, Vector3D B )
|
||||
{
|
||||
return new Vector3D(
|
||||
A.y * B.z - B.y * A.z,
|
||||
A.z * B.x - B.z * A.x,
|
||||
A.x * B.y - B.x * A.y );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a vector containing the cross-product: (this) cross B.
|
||||
* @param B Second vector in the cross product.
|
||||
* @return A new Vector3D.
|
||||
*/
|
||||
public Vector3D cross( Vector3D B )
|
||||
{
|
||||
return new Vector3D(
|
||||
y * B.z - B.y * z,
|
||||
z * B.x - B.z * x,
|
||||
x * B.y - B.x * y );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the dot-product result of: A dot B.
|
||||
* @param A First vector in the dot product.
|
||||
* @param B Second vector in the dot product.
|
||||
* @return Dot product.
|
||||
*/
|
||||
public float dot( Vector3D A, Vector3D B )
|
||||
{
|
||||
return( (A.x * B.x) + (A.y * B.y) + (A.z * B.z) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the dot-product result of: (this) dot B.
|
||||
* @param B Second vector in the dot product.
|
||||
* @return Dot product.
|
||||
*/
|
||||
public float dot( Vector3D B )
|
||||
{
|
||||
return( (x * B.x) + (y * B.y) + (z * B.z) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the vector represented by: A + B.
|
||||
* @param A First vector.
|
||||
* @param B Vector to add to A.
|
||||
* @return A new Vector3D.
|
||||
*/
|
||||
public Vector3D add( Vector3D A, Vector3D B )
|
||||
{
|
||||
return new Vector3D( A.x + B.x, A.y + B.y, A.z + B.z );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the vector represented by: (this) + B.
|
||||
* @param B Vector to add to this one.
|
||||
* @return A new Vector3D.
|
||||
*/
|
||||
public Vector3D add( Vector3D B )
|
||||
{
|
||||
return new Vector3D( x + B.x, y + B.y, z + B.z );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the vector represented by: A - B.
|
||||
* @param A First vector.
|
||||
* @param B Vector to subtract from A.
|
||||
* @return A new Vector3D.
|
||||
*/
|
||||
public Vector3D subtract( Vector3D A, Vector3D B )
|
||||
{
|
||||
return new Vector3D( A.x - B.x, A.y - B.y, A.z - B.z );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the vector represented by: (this) - B.
|
||||
* @param B Vector to subtract from this one.
|
||||
* @return A new Vector3D.
|
||||
*/
|
||||
public Vector3D subtract( Vector3D B )
|
||||
{
|
||||
return new Vector3D( x - B.x, y - B.y, z - B.z );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the length of this vector.
|
||||
* @return Length.
|
||||
*/
|
||||
public float length()
|
||||
{
|
||||
return (float) Math.sqrt( x * x + y * y + z * z );
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the length of this vector to 1.0.
|
||||
*/
|
||||
public void normalize()
|
||||
{
|
||||
double t = Math.sqrt( x*x + y*y + z*z );
|
||||
x = (float) (x / t);
|
||||
y = (float) (y / t);
|
||||
z = (float) (z / t);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string depicting this vector.
|
||||
* @return "Vector3D (x, y, z)".
|
||||
*/
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "Vector3D (" + x + ", " + y + ", " + z + ")";
|
||||
}
|
||||
}
|
||||
696
src/lwjgl/java/paulscode/sound/libraries/ChannelLWJGLOpenAL.java
Normal file
696
src/lwjgl/java/paulscode/sound/libraries/ChannelLWJGLOpenAL.java
Normal file
@@ -0,0 +1,696 @@
|
||||
package paulscode.sound.libraries;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
import java.util.LinkedList;
|
||||
import javax.sound.sampled.AudioFormat;
|
||||
|
||||
// From the lwjgl library, http://www.lwjgl.org
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.openal.AL10;
|
||||
import org.lwjgl.openal.AL11;
|
||||
|
||||
import paulscode.sound.Channel;
|
||||
import paulscode.sound.SoundSystemConfig;
|
||||
|
||||
/**
|
||||
* The ChannelLWJGLOpenAL class is used to reserve a sound-card voice using the
|
||||
* lwjgl binding of OpenAL. Channels can be either normal or streaming
|
||||
* channels.
|
||||
*<b><br><br>
|
||||
* This software is based on or using the LWJGL Lightweight Java Gaming
|
||||
* Library available from
|
||||
* http://www.lwjgl.org/.
|
||||
*</b><br><br>
|
||||
* LWJGL License:
|
||||
*<br><i>
|
||||
* Copyright (c) 2002-2008 Lightweight Java Game Library Project
|
||||
* All rights reserved.
|
||||
*<br>
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
* <br>
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*<br>
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*<br>
|
||||
* * Neither the name of 'Light Weight Java Game Library' nor the names of
|
||||
* its contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* <br>
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* <br><br><br></i>
|
||||
*<b><i> SoundSystem LibraryLWJGLOpenAL License:</b></i><br><b><br>
|
||||
*<b>
|
||||
* You are free to use this library for any purpose, commercial or otherwise.
|
||||
* You may modify this library or source code, and distribute it any way you
|
||||
* like, provided the following conditions are met:
|
||||
*<br>
|
||||
* 1) You must abide by the conditions of the aforementioned LWJGL License.
|
||||
*<br>
|
||||
* 2) You may not falsely claim to be the author of this library or any
|
||||
* unmodified portion of it.
|
||||
*<br>
|
||||
* 3) You may not copyright this library or a modified version of it and then
|
||||
* sue me for copyright infringement.
|
||||
*<br>
|
||||
* 4) If you modify the source code, you must clearly document the changes
|
||||
* made before redistributing the modified source code, so other users know
|
||||
* it is not the original code.
|
||||
*<br>
|
||||
* 5) You are not required to give me credit for this library in any derived
|
||||
* work, but if you do, you must also mention my website:
|
||||
* http://www.paulscode.com
|
||||
*<br>
|
||||
* 6) I the author will not be responsible for any damages (physical,
|
||||
* financial, or otherwise) caused by the use if this library or any part
|
||||
* of it.
|
||||
*<br>
|
||||
* 7) I the author do not guarantee, warrant, or make any representations,
|
||||
* either expressed or implied, regarding the use of this library or any
|
||||
* part of it.
|
||||
* <br><br>
|
||||
* Author: Paul Lamb
|
||||
* <br>
|
||||
* http://www.paulscode.com
|
||||
* </b>
|
||||
*/
|
||||
public class ChannelLWJGLOpenAL extends Channel
|
||||
{
|
||||
/**
|
||||
* OpenAL's IntBuffer identifier for this channel.
|
||||
*/
|
||||
public IntBuffer ALSource;
|
||||
|
||||
/**
|
||||
* OpenAL data format to use when playing back the assigned source.
|
||||
*/
|
||||
public int ALformat; // OpenAL data format
|
||||
|
||||
/**
|
||||
* Sample rate (speed) to use for play-back.
|
||||
*/
|
||||
public int sampleRate; // sample rate
|
||||
|
||||
/**
|
||||
* Miliseconds of buffers previously played (streaming sources).
|
||||
*/
|
||||
public float millisPreviouslyPlayed = 0;
|
||||
|
||||
/**
|
||||
* Constructor: takes channelType identifier and a handle to the OpenAL
|
||||
* IntBuffer identifier to use for this channel. Possible values for channel
|
||||
* type can be found in the
|
||||
* {@link paulscode.sound.SoundSystemConfig SoundSystemConfig} class.
|
||||
* @param type Type of channel (normal or streaming).
|
||||
* @param src Handle to the OpenAL source identifier.
|
||||
*/
|
||||
public ChannelLWJGLOpenAL( int type, IntBuffer src )
|
||||
{
|
||||
super( type );
|
||||
libraryType = LibraryLWJGLOpenAL.class;
|
||||
ALSource = src;
|
||||
}
|
||||
|
||||
/**
|
||||
* Empties the streamBuffers list, stops and deletes the ALSource, shuts the
|
||||
* channel down, and removes references to all instantiated objects.
|
||||
*/
|
||||
@Override
|
||||
public void cleanup()
|
||||
{
|
||||
if( ALSource != null )
|
||||
{
|
||||
try
|
||||
{
|
||||
// Stop playing the source:
|
||||
AL10.alSourceStop( ALSource );
|
||||
AL10.alGetError();
|
||||
}
|
||||
catch( Exception e )
|
||||
{}
|
||||
try
|
||||
{
|
||||
// Delete the source:
|
||||
AL10.alDeleteSources( ALSource );
|
||||
AL10.alGetError();
|
||||
}
|
||||
catch( Exception e )
|
||||
{}
|
||||
ALSource.clear();
|
||||
}
|
||||
ALSource = null;
|
||||
|
||||
super.cleanup();
|
||||
}
|
||||
|
||||
/**
|
||||
* Attaches an OpenAL sound-buffer identifier for the sound data to be played
|
||||
* back for a normal source.
|
||||
* @param buf Intbuffer identifier for the sound data to play.
|
||||
* @return False if an error occurred.
|
||||
*/
|
||||
public boolean attachBuffer( IntBuffer buf )
|
||||
{
|
||||
// A sound buffer can only be attached to a normal source:
|
||||
if( errorCheck( channelType != SoundSystemConfig.TYPE_NORMAL,
|
||||
"Sound buffers may only be attached to normal " +
|
||||
"sources." ) )
|
||||
return false;
|
||||
|
||||
// send the sound buffer to the channel:
|
||||
AL10.alSourcei( ALSource.get( 0 ), AL10.AL_BUFFER,
|
||||
buf.get(0) );
|
||||
|
||||
|
||||
// save the format for later, for determining milliseconds played
|
||||
if( attachedSource != null && attachedSource.soundBuffer != null &&
|
||||
attachedSource.soundBuffer.audioFormat != null )
|
||||
setAudioFormat( attachedSource.soundBuffer.audioFormat );
|
||||
|
||||
// Check for errors and return:
|
||||
return checkALError();
|
||||
}
|
||||
/**
|
||||
* Sets the channel up to receive the specified audio format.
|
||||
* @param audioFormat Format to use when playing the stream data.
|
||||
*/
|
||||
@Override
|
||||
public void setAudioFormat( AudioFormat audioFormat )
|
||||
{
|
||||
int soundFormat = 0;
|
||||
if( audioFormat.getChannels() == 1 )
|
||||
{
|
||||
if( audioFormat.getSampleSizeInBits() == 8 )
|
||||
{
|
||||
soundFormat = AL10.AL_FORMAT_MONO8;
|
||||
}
|
||||
else if( audioFormat.getSampleSizeInBits() == 16 )
|
||||
{
|
||||
soundFormat = AL10.AL_FORMAT_MONO16;
|
||||
}
|
||||
else
|
||||
{
|
||||
errorMessage( "Illegal sample size in method " +
|
||||
"'setAudioFormat'" );
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if( audioFormat.getChannels() == 2 )
|
||||
{
|
||||
if( audioFormat.getSampleSizeInBits() == 8 )
|
||||
{
|
||||
soundFormat = AL10.AL_FORMAT_STEREO8;
|
||||
}
|
||||
else if( audioFormat.getSampleSizeInBits() == 16 )
|
||||
{
|
||||
soundFormat = AL10.AL_FORMAT_STEREO16;
|
||||
}
|
||||
else
|
||||
{
|
||||
errorMessage( "Illegal sample size in method " +
|
||||
"'setAudioFormat'" );
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
errorMessage( "Audio data neither mono nor stereo in " +
|
||||
"method 'setAudioFormat'" );
|
||||
return;
|
||||
}
|
||||
ALformat = soundFormat;
|
||||
sampleRate = (int) audioFormat.getSampleRate();
|
||||
}
|
||||
/**
|
||||
* Sets the channel up to receive the specified OpenAL audio format and sample
|
||||
* rate.
|
||||
* @param format Format to use.
|
||||
* @param rate Sample rate (speed) to use.
|
||||
*/
|
||||
public void setFormat( int format, int rate )
|
||||
{
|
||||
ALformat = format;
|
||||
sampleRate = rate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Queues up the initial byte[] buffers of data to be streamed.
|
||||
* @param bufferList List of the first buffers to be played for a streaming source.
|
||||
* @return False if problem occurred or if end of stream was reached.
|
||||
*/
|
||||
@Override
|
||||
public boolean preLoadBuffers( LinkedList<byte[]> bufferList )
|
||||
{
|
||||
// Stream buffers can only be queued for streaming sources:
|
||||
if( errorCheck( channelType != SoundSystemConfig.TYPE_STREAMING,
|
||||
"Buffers may only be queued for streaming sources." ) )
|
||||
return false;
|
||||
|
||||
if( errorCheck( bufferList == null,
|
||||
"Buffer List null in method 'preLoadBuffers'" ) )
|
||||
return false;
|
||||
|
||||
IntBuffer streamBuffers;
|
||||
|
||||
// Remember if the channel was playing:
|
||||
boolean playing = playing();
|
||||
// stop the channel if it is playing:
|
||||
if( playing )
|
||||
{
|
||||
AL10.alSourceStop( ALSource.get( 0 ) );
|
||||
checkALError();
|
||||
}
|
||||
// Clear out any previously queued buffers:
|
||||
int processed = AL10.alGetSourcei( ALSource.get( 0 ),
|
||||
AL10.AL_BUFFERS_PROCESSED );
|
||||
if( processed > 0 )
|
||||
{
|
||||
streamBuffers = BufferUtils.createIntBuffer( processed );
|
||||
AL10.alGenBuffers( streamBuffers );
|
||||
if( errorCheck( checkALError(),
|
||||
"Error clearing stream buffers in method 'preLoadBuffers'" ) )
|
||||
return false;
|
||||
AL10.alSourceUnqueueBuffers( ALSource.get( 0 ), streamBuffers );
|
||||
if( errorCheck( checkALError(),
|
||||
"Error unqueuing stream buffers in method 'preLoadBuffers'" ) )
|
||||
return false;
|
||||
}
|
||||
|
||||
// restart the channel if it was previously playing:
|
||||
if( playing )
|
||||
{
|
||||
AL10.alSourcePlay( ALSource.get( 0 ) );
|
||||
checkALError();
|
||||
}
|
||||
|
||||
streamBuffers = BufferUtils.createIntBuffer( bufferList.size() );
|
||||
AL10.alGenBuffers( streamBuffers );
|
||||
if( errorCheck( checkALError(),
|
||||
"Error generating stream buffers in method 'preLoadBuffers'" ) )
|
||||
return false;
|
||||
|
||||
ByteBuffer byteBuffer = null;
|
||||
for( int i = 0; i < bufferList.size(); i++ )
|
||||
{
|
||||
//byteBuffer = ByteBuffer.wrap( bufferList.get(i), 0,
|
||||
// bufferList.get(i).length );
|
||||
byteBuffer = (ByteBuffer) BufferUtils.createByteBuffer(
|
||||
bufferList.get(i).length ).put( bufferList.get( i ) ).flip();
|
||||
|
||||
try
|
||||
{
|
||||
AL10.alBufferData( streamBuffers.get(i), ALformat, byteBuffer,
|
||||
sampleRate );
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
errorMessage( "Error creating buffers in method " +
|
||||
"'preLoadBuffers'" );
|
||||
printStackTrace( e );
|
||||
return false;
|
||||
}
|
||||
if( errorCheck( checkALError(),
|
||||
"Error creating buffers in method 'preLoadBuffers'" ) )
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
AL10.alSourceQueueBuffers( ALSource.get( 0 ), streamBuffers );
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
errorMessage( "Error queuing buffers in method 'preLoadBuffers'" );
|
||||
printStackTrace( e );
|
||||
return false;
|
||||
}
|
||||
if( errorCheck( checkALError(),
|
||||
"Error queuing buffers in method 'preLoadBuffers'" ) )
|
||||
return false;
|
||||
|
||||
AL10.alSourcePlay( ALSource.get( 0 ) );
|
||||
if( errorCheck( checkALError(),
|
||||
"Error playing source in method 'preLoadBuffers'" ) )
|
||||
return false;
|
||||
|
||||
// Success:
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Queues up a byte[] buffer of data to be streamed.
|
||||
* @param buffer The next buffer to be played for a streaming source.
|
||||
* @return False if an error occurred or if the channel is shutting down.
|
||||
*/
|
||||
@Override
|
||||
public boolean queueBuffer( byte[] buffer )
|
||||
{
|
||||
// Stream buffers can only be queued for streaming sources:
|
||||
if( errorCheck( channelType != SoundSystemConfig.TYPE_STREAMING,
|
||||
"Buffers may only be queued for streaming sources." ) )
|
||||
return false;
|
||||
|
||||
//ByteBuffer byteBuffer = ByteBuffer.wrap( buffer, 0, buffer.length );
|
||||
ByteBuffer byteBuffer = (ByteBuffer) BufferUtils.createByteBuffer(
|
||||
buffer.length ).put( buffer ).flip();
|
||||
|
||||
IntBuffer intBuffer = BufferUtils.createIntBuffer( 1 );
|
||||
|
||||
AL10.alSourceUnqueueBuffers( ALSource.get( 0 ), intBuffer );
|
||||
if( checkALError() )
|
||||
return false;
|
||||
|
||||
if( AL10.alIsBuffer( intBuffer.get( 0 ) ) )
|
||||
millisPreviouslyPlayed += millisInBuffer( intBuffer.get( 0 ) );
|
||||
checkALError();
|
||||
|
||||
AL10.alBufferData( intBuffer.get(0), ALformat, byteBuffer, sampleRate );
|
||||
if( checkALError() )
|
||||
return false;
|
||||
|
||||
AL10.alSourceQueueBuffers( ALSource.get( 0 ), intBuffer );
|
||||
if( checkALError() )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Feeds raw data to the stream.
|
||||
* @param buffer Buffer containing raw audio data to stream.
|
||||
* @return Number of prior buffers that have been processed., or -1 if error.
|
||||
*/
|
||||
@Override
|
||||
public int feedRawAudioData( byte[] buffer )
|
||||
{
|
||||
// Stream buffers can only be queued for streaming sources:
|
||||
if( errorCheck( channelType != SoundSystemConfig.TYPE_STREAMING,
|
||||
"Raw audio data can only be fed to streaming sources." ) )
|
||||
return -1;
|
||||
|
||||
//ByteBuffer byteBuffer = ByteBuffer.wrap( buffer, 0, buffer.length );
|
||||
ByteBuffer byteBuffer = (ByteBuffer) BufferUtils.createByteBuffer(
|
||||
buffer.length ).put( buffer ).flip();
|
||||
|
||||
IntBuffer intBuffer;
|
||||
|
||||
// Clear out any previously queued buffers:
|
||||
int processed = AL10.alGetSourcei( ALSource.get( 0 ),
|
||||
AL10.AL_BUFFERS_PROCESSED );
|
||||
if( processed > 0 )
|
||||
{
|
||||
intBuffer = BufferUtils.createIntBuffer( processed );
|
||||
AL10.alGenBuffers( intBuffer );
|
||||
if( errorCheck( checkALError(),
|
||||
"Error clearing stream buffers in method 'feedRawAudioData'" ) )
|
||||
return -1;
|
||||
AL10.alSourceUnqueueBuffers( ALSource.get( 0 ), intBuffer );
|
||||
if( errorCheck( checkALError(),
|
||||
"Error unqueuing stream buffers in method 'feedRawAudioData'" ) )
|
||||
return -1;
|
||||
int i;
|
||||
intBuffer.rewind();
|
||||
while( intBuffer.hasRemaining() )
|
||||
{
|
||||
i = intBuffer.get();
|
||||
if( AL10.alIsBuffer( i ) )
|
||||
{
|
||||
millisPreviouslyPlayed += millisInBuffer( i );
|
||||
}
|
||||
checkALError();
|
||||
}
|
||||
AL10.alDeleteBuffers( intBuffer );
|
||||
checkALError();
|
||||
}
|
||||
intBuffer = BufferUtils.createIntBuffer( 1 );
|
||||
AL10.alGenBuffers( intBuffer );
|
||||
if( errorCheck( checkALError(),
|
||||
"Error generating stream buffers in method 'preLoadBuffers'" ) )
|
||||
return -1;
|
||||
|
||||
AL10.alBufferData( intBuffer.get(0), ALformat, byteBuffer, sampleRate );
|
||||
if( checkALError() )
|
||||
return -1;
|
||||
|
||||
AL10.alSourceQueueBuffers( ALSource.get( 0 ), intBuffer );
|
||||
if( checkALError() )
|
||||
return -1;
|
||||
|
||||
if( attachedSource != null && attachedSource.channel == this &&
|
||||
attachedSource.active() )
|
||||
{
|
||||
// restart the channel if it was previously playing:
|
||||
if( !playing() )
|
||||
{
|
||||
AL10.alSourcePlay( ALSource.get( 0 ) );
|
||||
checkALError();
|
||||
}
|
||||
}
|
||||
|
||||
return processed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of milliseconds of audio contained in specified buffer.
|
||||
* @return milliseconds, or 0 if unable to calculate.
|
||||
*/
|
||||
public float millisInBuffer( int alBufferi )
|
||||
{
|
||||
return( ( (float) AL10.alGetBufferi( alBufferi, AL10.AL_SIZE ) /
|
||||
(float) AL10.alGetBufferi( alBufferi, AL10.AL_CHANNELS ) /
|
||||
( (float) AL10.alGetBufferi( alBufferi, AL10.AL_BITS ) / 8.0f ) /
|
||||
(float) sampleRate ) * 1000 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the number of milliseconds since the channel began playing.
|
||||
* @return Milliseconds, or -1 if unable to calculate.
|
||||
*/
|
||||
@Override
|
||||
public float millisecondsPlayed()
|
||||
{
|
||||
// get number of samples played in current buffer
|
||||
float offset = (float)AL10.alGetSourcei( ALSource.get( 0 ),
|
||||
AL11.AL_BYTE_OFFSET );
|
||||
|
||||
float bytesPerFrame = 1f;
|
||||
switch( ALformat )
|
||||
{
|
||||
case AL10.AL_FORMAT_MONO8 :
|
||||
bytesPerFrame = 1f;
|
||||
break;
|
||||
case AL10.AL_FORMAT_MONO16 :
|
||||
bytesPerFrame = 2f;
|
||||
break;
|
||||
case AL10.AL_FORMAT_STEREO8 :
|
||||
bytesPerFrame = 2f;
|
||||
break;
|
||||
case AL10.AL_FORMAT_STEREO16 :
|
||||
bytesPerFrame = 4f;
|
||||
break;
|
||||
default :
|
||||
break;
|
||||
}
|
||||
|
||||
offset = ( ( (float) offset / bytesPerFrame ) / (float) sampleRate )
|
||||
* 1000;
|
||||
|
||||
// add the milliseconds from stream-buffers that played previously
|
||||
if( channelType == SoundSystemConfig.TYPE_STREAMING )
|
||||
offset += millisPreviouslyPlayed;
|
||||
|
||||
// Return millis played:
|
||||
return( offset );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of queued byte[] buffers that have finished playing.
|
||||
* @return Number of buffers processed.
|
||||
*/
|
||||
@Override
|
||||
public int buffersProcessed()
|
||||
{
|
||||
// Only streaming sources process buffers:
|
||||
if( channelType != SoundSystemConfig.TYPE_STREAMING )
|
||||
return 0;
|
||||
|
||||
// determine how many have been processed:
|
||||
int processed = AL10.alGetSourcei( ALSource.get( 0 ),
|
||||
AL10.AL_BUFFERS_PROCESSED );
|
||||
|
||||
// Check for errors:
|
||||
if( checkALError() )
|
||||
return 0;
|
||||
|
||||
// Return how many were processed:
|
||||
return processed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dequeues all previously queued data.
|
||||
*/
|
||||
@Override
|
||||
public void flush()
|
||||
{
|
||||
// Only a streaming source can be flushed, because only streaming
|
||||
// sources have queued buffers:
|
||||
if( channelType != SoundSystemConfig.TYPE_STREAMING )
|
||||
return;
|
||||
|
||||
// determine how many buffers have been queued:
|
||||
int queued = AL10.alGetSourcei( ALSource.get( 0 ),
|
||||
AL10.AL_BUFFERS_QUEUED );
|
||||
// Check for errors:
|
||||
if( checkALError() )
|
||||
return;
|
||||
|
||||
IntBuffer intBuffer = BufferUtils.createIntBuffer( 1 );
|
||||
while( queued > 0 )
|
||||
{
|
||||
try
|
||||
{
|
||||
AL10.alSourceUnqueueBuffers( ALSource.get( 0 ), intBuffer );
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
return;
|
||||
}
|
||||
if( checkALError() )
|
||||
return;
|
||||
queued--;
|
||||
}
|
||||
millisPreviouslyPlayed = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops the channel, dequeues any queued data, and closes the channel.
|
||||
*/
|
||||
@Override
|
||||
public void close()
|
||||
{
|
||||
try
|
||||
{
|
||||
AL10.alSourceStop( ALSource.get( 0 ) );
|
||||
AL10.alGetError();
|
||||
}
|
||||
catch( Exception e )
|
||||
{}
|
||||
|
||||
if( channelType == SoundSystemConfig.TYPE_STREAMING )
|
||||
flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Plays the currently attached normal source, opens this channel up for
|
||||
* streaming, or resumes playback if this channel was paused.
|
||||
*/
|
||||
@Override
|
||||
public void play()
|
||||
{
|
||||
AL10.alSourcePlay( ALSource.get( 0 ) );
|
||||
checkALError();
|
||||
}
|
||||
|
||||
/**
|
||||
* Temporarily stops playback for this channel.
|
||||
*/
|
||||
@Override
|
||||
public void pause()
|
||||
{
|
||||
AL10.alSourcePause( ALSource.get( 0 ) );
|
||||
checkALError();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops playback for this channel and rewinds the attached source to the
|
||||
* beginning.
|
||||
*/
|
||||
@Override
|
||||
public void stop()
|
||||
{
|
||||
AL10.alSourceStop( ALSource.get( 0 ) );
|
||||
if( !checkALError() )
|
||||
millisPreviouslyPlayed = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewinds the attached source to the beginning. Stops the source if it was
|
||||
* paused.
|
||||
*/
|
||||
@Override
|
||||
public void rewind()
|
||||
{
|
||||
// rewinding for streaming sources is handled elsewhere
|
||||
if( channelType == SoundSystemConfig.TYPE_STREAMING )
|
||||
return;
|
||||
|
||||
AL10.alSourceRewind( ALSource.get( 0 ) );
|
||||
if( !checkALError() )
|
||||
millisPreviouslyPlayed = 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Used to determine if a channel is actively playing a source. This method
|
||||
* will return false if the channel is paused or stopped and when no data is
|
||||
* queued to be streamed.
|
||||
* @return True if this channel is playing a source.
|
||||
*/
|
||||
@Override
|
||||
public boolean playing()
|
||||
{
|
||||
int state = AL10.alGetSourcei( ALSource.get( 0 ),
|
||||
AL10.AL_SOURCE_STATE );
|
||||
if( checkALError() )
|
||||
return false;
|
||||
|
||||
return( state == AL10.AL_PLAYING );
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks for OpenAL errors, and prints a message if there is an error.
|
||||
* @return True if there was an error, False if not.
|
||||
*/
|
||||
private boolean checkALError()
|
||||
{
|
||||
switch( AL10.alGetError() )
|
||||
{
|
||||
case AL10.AL_NO_ERROR:
|
||||
return false;
|
||||
case AL10.AL_INVALID_NAME:
|
||||
errorMessage( "Invalid name parameter." );
|
||||
return true;
|
||||
case AL10.AL_INVALID_ENUM:
|
||||
errorMessage( "Invalid parameter." );
|
||||
return true;
|
||||
case AL10.AL_INVALID_VALUE:
|
||||
errorMessage( "Invalid enumerated parameter value." );
|
||||
return true;
|
||||
case AL10.AL_INVALID_OPERATION:
|
||||
errorMessage( "Illegal call." );
|
||||
return true;
|
||||
case AL10.AL_OUT_OF_MEMORY:
|
||||
errorMessage( "Unable to allocate memory." );
|
||||
return true;
|
||||
default:
|
||||
errorMessage( "An unrecognized error occurred." );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
1126
src/lwjgl/java/paulscode/sound/libraries/LibraryLWJGLOpenAL.java
Normal file
1126
src/lwjgl/java/paulscode/sound/libraries/LibraryLWJGLOpenAL.java
Normal file
File diff suppressed because it is too large
Load Diff
801
src/lwjgl/java/paulscode/sound/libraries/SourceLWJGLOpenAL.java
Normal file
801
src/lwjgl/java/paulscode/sound/libraries/SourceLWJGLOpenAL.java
Normal file
@@ -0,0 +1,801 @@
|
||||
package paulscode.sound.libraries;
|
||||
|
||||
import java.nio.IntBuffer;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.util.LinkedList;
|
||||
import javax.sound.sampled.AudioFormat;
|
||||
|
||||
// From the lwjgl library, http://www.lwjgl.org
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.openal.AL10;
|
||||
|
||||
import paulscode.sound.Channel;
|
||||
import paulscode.sound.FilenameURL;
|
||||
import paulscode.sound.Source;
|
||||
import paulscode.sound.SoundBuffer;
|
||||
import paulscode.sound.SoundSystemConfig;
|
||||
|
||||
/**
|
||||
* The SourceLWJGLOpenAL class provides an interface to the lwjgl binding of OpenAL.
|
||||
*<b><br><br>
|
||||
* This software is based on or using the LWJGL Lightweight Java Gaming
|
||||
* Library available from
|
||||
* http://www.lwjgl.org/.
|
||||
*</b><br><br>
|
||||
* LWJGL License:
|
||||
*<br><i>
|
||||
* Copyright (c) 2002-2008 Lightweight Java Game Library Project
|
||||
* All rights reserved.
|
||||
*<br>
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
* <br>
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*<br>
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*<br>
|
||||
* * Neither the name of 'Light Weight Java Game Library' nor the names of
|
||||
* its contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* <br>
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* <br><br><br></i>
|
||||
*<b><i> SoundSystem LibraryLWJGLOpenAL License:</b></i><br><b><br>
|
||||
*<b>
|
||||
* You are free to use this library for any purpose, commercial or otherwise.
|
||||
* You may modify this library or source code, and distribute it any way you
|
||||
* like, provided the following conditions are met:
|
||||
*<br>
|
||||
* 1) You must abide by the conditions of the aforementioned LWJGL License.
|
||||
*<br>
|
||||
* 2) You may not falsely claim to be the author of this library or any
|
||||
* unmodified portion of it.
|
||||
*<br>
|
||||
* 3) You may not copyright this library or a modified version of it and then
|
||||
* sue me for copyright infringement.
|
||||
*<br>
|
||||
* 4) If you modify the source code, you must clearly document the changes
|
||||
* made before redistributing the modified source code, so other users know
|
||||
* it is not the original code.
|
||||
*<br>
|
||||
* 5) You are not required to give me credit for this library in any derived
|
||||
* work, but if you do, you must also mention my website:
|
||||
* http://www.paulscode.com
|
||||
*<br>
|
||||
* 6) I the author will not be responsible for any damages (physical,
|
||||
* financial, or otherwise) caused by the use if this library or any part
|
||||
* of it.
|
||||
*<br>
|
||||
* 7) I the author do not guarantee, warrant, or make any representations,
|
||||
* either expressed or implied, regarding the use of this library or any
|
||||
* part of it.
|
||||
* <br><br>
|
||||
* Author: Paul Lamb
|
||||
* <br>
|
||||
* http://www.paulscode.com
|
||||
* </b>
|
||||
*/
|
||||
public class SourceLWJGLOpenAL extends Source
|
||||
{
|
||||
/**
|
||||
* The source's basic Channel type-cast to a ChannelLWJGLOpenAL.
|
||||
*/
|
||||
private ChannelLWJGLOpenAL channelOpenAL = (ChannelLWJGLOpenAL) channel;
|
||||
|
||||
/**
|
||||
* OpenAL IntBuffer sound-buffer identifier for this source if it is a normal
|
||||
* source.
|
||||
*/
|
||||
private IntBuffer myBuffer;
|
||||
|
||||
/**
|
||||
* FloatBuffer containing the listener's 3D coordinates.
|
||||
*/
|
||||
private FloatBuffer listenerPosition;
|
||||
|
||||
/**
|
||||
* FloatBuffer containing the source's 3D coordinates.
|
||||
*/
|
||||
private FloatBuffer sourcePosition;
|
||||
|
||||
/**
|
||||
* FloatBuffer containing the source's velocity vector.
|
||||
*/
|
||||
private FloatBuffer sourceVelocity;
|
||||
|
||||
/**
|
||||
* Constructor: Creates a new source using the specified parameters.
|
||||
* @param listenerPosition FloatBuffer containing the listener's 3D coordinates.
|
||||
* @param myBuffer OpenAL IntBuffer sound-buffer identifier to use for a new normal source.
|
||||
* @param priority Setting this to true will prevent other sounds from overriding this one.
|
||||
* @param toStream Setting this to true will create a streaming source.
|
||||
* @param toLoop Should this source loop, or play only once.
|
||||
* @param sourcename A unique identifier for this source. Two sources may not use the same sourcename.
|
||||
* @param filenameURL Filename/URL of the sound file to play at this source.
|
||||
* @param soundBuffer Buffer containing audio data, or null if not loaded yet.
|
||||
* @param x X position for this source.
|
||||
* @param y Y position for this source.
|
||||
* @param z Z position for this source.
|
||||
* @param attModel Attenuation model to use.
|
||||
* @param distOrRoll Either the fading distance or rolloff factor, depending on the value of 'att'.
|
||||
* @param temporary Whether or not to remove this source after it finishes playing.
|
||||
*/
|
||||
public SourceLWJGLOpenAL( FloatBuffer listenerPosition, IntBuffer myBuffer,
|
||||
boolean priority, boolean toStream,
|
||||
boolean toLoop, String sourcename,
|
||||
FilenameURL filenameURL, SoundBuffer soundBuffer,
|
||||
float x, float y, float z, int attModel,
|
||||
float distOrRoll, boolean temporary )
|
||||
{
|
||||
super( priority, toStream, toLoop, sourcename, filenameURL, soundBuffer,
|
||||
x, y, z, attModel, distOrRoll, temporary );
|
||||
if( codec != null )
|
||||
codec.reverseByteOrder( true );
|
||||
this.listenerPosition = listenerPosition;
|
||||
this.myBuffer = myBuffer;
|
||||
libraryType = LibraryLWJGLOpenAL.class;
|
||||
pitch = 1.0f;
|
||||
resetALInformation();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor: Creates a new source matching the specified source.
|
||||
* @param listenerPosition FloatBuffer containing the listener's 3D coordinates.
|
||||
* @param myBuffer OpenAL IntBuffer sound-buffer identifier to use for a new normal source.
|
||||
* @param old Source to copy information from.
|
||||
* @param soundBuffer Buffer containing audio data, or null if not loaded yet.
|
||||
*/
|
||||
public SourceLWJGLOpenAL( FloatBuffer listenerPosition, IntBuffer myBuffer,
|
||||
Source old, SoundBuffer soundBuffer )
|
||||
{
|
||||
super( old, soundBuffer );
|
||||
if( codec != null )
|
||||
codec.reverseByteOrder( true );
|
||||
this.listenerPosition = listenerPosition;
|
||||
this.myBuffer = myBuffer;
|
||||
libraryType = LibraryLWJGLOpenAL.class;
|
||||
pitch = 1.0f;
|
||||
resetALInformation();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor: Creates a new streaming source that will be directly fed with
|
||||
* raw audio data.
|
||||
* @param listenerPosition FloatBuffer containing the listener's 3D coordinates.
|
||||
* @param audioFormat Format that the data will be in.
|
||||
* @param priority Setting this to true will prevent other sounds from overriding this one.
|
||||
* @param sourcename A unique identifier for this source. Two sources may not use the same sourcename.
|
||||
* @param x X position for this source.
|
||||
* @param y Y position for this source.
|
||||
* @param z Z position for this source.
|
||||
* @param attModel Attenuation model to use.
|
||||
* @param distOrRoll Either the fading distance or rolloff factor, depending on the value of 'att'.
|
||||
*/
|
||||
public SourceLWJGLOpenAL( FloatBuffer listenerPosition,
|
||||
AudioFormat audioFormat, boolean priority,
|
||||
String sourcename, float x, float y, float z,
|
||||
int attModel, float distOrRoll )
|
||||
{
|
||||
super( audioFormat, priority, sourcename, x, y, z, attModel,
|
||||
distOrRoll );
|
||||
this.listenerPosition = listenerPosition;
|
||||
libraryType = LibraryLWJGLOpenAL.class;
|
||||
pitch = 1.0f;
|
||||
resetALInformation();
|
||||
}
|
||||
|
||||
/**
|
||||
* Shuts the source down and removes references to all instantiated objects.
|
||||
*/
|
||||
@Override
|
||||
public void cleanup()
|
||||
{
|
||||
|
||||
super.cleanup();
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the peripheral information about the source using the specified
|
||||
* parameters.
|
||||
* @param listenerPosition FloatBuffer containing the listener's 3D coordinates.
|
||||
* @param myBuffer OpenAL IntBuffer sound-buffer identifier to use for a new normal source.
|
||||
* @param priority Setting this to true will prevent other sounds from overriding this one.
|
||||
* @param toStream Setting this to true will create a streaming source.
|
||||
* @param toLoop Should this source loop, or play only once.
|
||||
* @param sourcename A unique identifier for this source. Two sources may not use the same sourcename.
|
||||
* @param filenameURL Filename/URL of the sound file to play at this source.
|
||||
* @param soundBuffer Buffer containing audio data, or null if not loaded yet.
|
||||
* @param x X position for this source.
|
||||
* @param y Y position for this source.
|
||||
* @param z Z position for this source.
|
||||
* @param attModel Attenuation model to use.
|
||||
* @param distOrRoll Either the fading distance or rolloff factor, depending on the value of 'att'.
|
||||
* @param temporary Whether or not to remove this source after it finishes playing.
|
||||
*/
|
||||
public void changeSource( FloatBuffer listenerPosition, IntBuffer myBuffer,
|
||||
boolean priority, boolean toStream,
|
||||
boolean toLoop, String sourcename,
|
||||
FilenameURL filenameURL, SoundBuffer soundBuffer,
|
||||
float x, float y, float z, int attModel,
|
||||
float distOrRoll, boolean temporary )
|
||||
{
|
||||
super.changeSource( priority, toStream, toLoop, sourcename,
|
||||
filenameURL, soundBuffer, x, y, z, attModel,
|
||||
distOrRoll, temporary );
|
||||
this.listenerPosition = listenerPosition;
|
||||
this.myBuffer = myBuffer;
|
||||
pitch = 1.0f;
|
||||
resetALInformation();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the next filename from the sound sequence queue and assigns it to
|
||||
* this source. This method has no effect on non-streaming sources. This
|
||||
* method is used internally by SoundSystem, and it is unlikely that the user
|
||||
* will ever need to use it.
|
||||
* @return True if there was something in the queue.
|
||||
*/
|
||||
@Override
|
||||
public boolean incrementSoundSequence()
|
||||
{
|
||||
if( !toStream )
|
||||
{
|
||||
errorMessage( "Method 'incrementSoundSequence' may only be used " +
|
||||
"for streaming sources." );
|
||||
return false;
|
||||
}
|
||||
synchronized( soundSequenceLock )
|
||||
{
|
||||
if( soundSequenceQueue != null && soundSequenceQueue.size() > 0 )
|
||||
{
|
||||
filenameURL = soundSequenceQueue.remove( 0 );
|
||||
if( codec != null )
|
||||
codec.cleanup();
|
||||
codec = SoundSystemConfig.getCodec( filenameURL.getFilename() );
|
||||
if( codec != null )
|
||||
{
|
||||
codec.reverseByteOrder( true );
|
||||
if( codec.getAudioFormat() == null )
|
||||
codec.initialize( filenameURL.getURL() );
|
||||
|
||||
AudioFormat audioFormat = codec.getAudioFormat();
|
||||
|
||||
if( audioFormat == null )
|
||||
{
|
||||
errorMessage( "Audio Format null in method " +
|
||||
"'incrementSoundSequence'" );
|
||||
return false;
|
||||
}
|
||||
|
||||
int soundFormat = 0;
|
||||
if( audioFormat.getChannels() == 1 )
|
||||
{
|
||||
if( audioFormat.getSampleSizeInBits() == 8 )
|
||||
{
|
||||
soundFormat = AL10.AL_FORMAT_MONO8;
|
||||
}
|
||||
else if( audioFormat.getSampleSizeInBits() == 16 )
|
||||
{
|
||||
soundFormat = AL10.AL_FORMAT_MONO16;
|
||||
}
|
||||
else
|
||||
{
|
||||
errorMessage( "Illegal sample size in method " +
|
||||
"'incrementSoundSequence'" );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if( audioFormat.getChannels() == 2 )
|
||||
{
|
||||
if( audioFormat.getSampleSizeInBits() == 8 )
|
||||
{
|
||||
soundFormat = AL10.AL_FORMAT_STEREO8;
|
||||
}
|
||||
else if( audioFormat.getSampleSizeInBits() == 16 )
|
||||
{
|
||||
soundFormat = AL10.AL_FORMAT_STEREO16;
|
||||
}
|
||||
else
|
||||
{
|
||||
errorMessage( "Illegal sample size in method " +
|
||||
"'incrementSoundSequence'" );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
errorMessage( "Audio data neither mono nor stereo in " +
|
||||
"method 'incrementSoundSequence'" );
|
||||
return false;
|
||||
}
|
||||
|
||||
// Let the channel know what format and sample rate to use:
|
||||
channelOpenAL.setFormat( soundFormat,
|
||||
(int) audioFormat.getSampleRate() );
|
||||
preLoad = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called every time the listener's position or orientation changes.
|
||||
*/
|
||||
@Override
|
||||
public void listenerMoved()
|
||||
{
|
||||
positionChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the source to the specified position.
|
||||
* @param x X coordinate to move to.
|
||||
* @param y Y coordinate to move to.
|
||||
* @param z Z coordinate to move to.
|
||||
*/
|
||||
@Override
|
||||
public void setPosition( float x, float y, float z )
|
||||
{
|
||||
super.setPosition( x, y, z );
|
||||
|
||||
// Make sure OpenAL information has been created
|
||||
if( sourcePosition == null )
|
||||
resetALInformation();
|
||||
else
|
||||
positionChanged();
|
||||
|
||||
// put the new position information into the buffer:
|
||||
sourcePosition.put( 0, x );
|
||||
sourcePosition.put( 1, y );
|
||||
sourcePosition.put( 2, z );
|
||||
|
||||
// make sure we are assigned to a channel:
|
||||
if( channel != null && channel.attachedSource == this &&
|
||||
channelOpenAL != null && channelOpenAL.ALSource != null )
|
||||
{
|
||||
// move the source:
|
||||
AL10.alSource( channelOpenAL.ALSource.get( 0 ), AL10.AL_POSITION,
|
||||
sourcePosition );
|
||||
checkALError();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recalculates the distance from the listner and the gain.
|
||||
*/
|
||||
@Override
|
||||
public void positionChanged()
|
||||
{
|
||||
calculateDistance();
|
||||
calculateGain();
|
||||
|
||||
if( channel != null && channel.attachedSource == this &&
|
||||
channelOpenAL != null && channelOpenAL.ALSource != null )
|
||||
{
|
||||
AL10.alSourcef( channelOpenAL.ALSource.get( 0 ),
|
||||
AL10.AL_GAIN, (gain * sourceVolume
|
||||
* (float) Math.abs( fadeOutGain )
|
||||
* fadeInGain) );
|
||||
checkALError();
|
||||
}
|
||||
checkPitch();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the source's pitch.
|
||||
*/
|
||||
private void checkPitch()
|
||||
{
|
||||
if( channel != null && channel.attachedSource == this &&
|
||||
LibraryLWJGLOpenAL.alPitchSupported() && channelOpenAL != null &&
|
||||
channelOpenAL.ALSource != null )
|
||||
{
|
||||
AL10.alSourcef( channelOpenAL.ALSource.get( 0 ),
|
||||
AL10.AL_PITCH, pitch );
|
||||
checkALError();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether this source should loop or only play once.
|
||||
* @param lp True or false.
|
||||
*/
|
||||
@Override
|
||||
public void setLooping( boolean lp )
|
||||
{
|
||||
super.setLooping( lp );
|
||||
|
||||
// make sure we are assigned to a channel:
|
||||
if( channel != null && channel.attachedSource == this &&
|
||||
channelOpenAL != null && channelOpenAL.ALSource != null )
|
||||
{
|
||||
if( lp )
|
||||
AL10.alSourcei( channelOpenAL.ALSource.get( 0 ),
|
||||
AL10.AL_LOOPING, AL10.AL_TRUE );
|
||||
else
|
||||
AL10.alSourcei( channelOpenAL.ALSource.get( 0 ),
|
||||
AL10.AL_LOOPING, AL10.AL_FALSE );
|
||||
checkALError();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets this source's attenuation model.
|
||||
* @param model Attenuation model to use.
|
||||
*/
|
||||
@Override
|
||||
public void setAttenuation( int model )
|
||||
{
|
||||
super.setAttenuation( model );
|
||||
// make sure we are assigned to a channel:
|
||||
if( channel != null && channel.attachedSource == this &&
|
||||
channelOpenAL != null && channelOpenAL.ALSource != null )
|
||||
{
|
||||
// attenuation changed, so update the rolloff factor accordingly
|
||||
if( model == SoundSystemConfig.ATTENUATION_ROLLOFF )
|
||||
AL10.alSourcef( channelOpenAL.ALSource.get( 0 ),
|
||||
AL10.AL_ROLLOFF_FACTOR, distOrRoll );
|
||||
else
|
||||
AL10.alSourcef( channelOpenAL.ALSource.get( 0 ),
|
||||
AL10.AL_ROLLOFF_FACTOR, 0.0f );
|
||||
checkALError();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets this source's fade distance or rolloff factor, depending on the
|
||||
* attenuation model.
|
||||
* @param dr New value for fade distance or rolloff factor.
|
||||
*/
|
||||
@Override
|
||||
public void setDistOrRoll( float dr)
|
||||
{
|
||||
super.setDistOrRoll( dr );
|
||||
// make sure we are assigned to a channel:
|
||||
if( channel != null && channel.attachedSource == this &&
|
||||
channelOpenAL != null && channelOpenAL.ALSource != null )
|
||||
{
|
||||
// if we are using rolloff attenuation, then dr is a rolloff factor:
|
||||
if( attModel == SoundSystemConfig.ATTENUATION_ROLLOFF )
|
||||
AL10.alSourcef( channelOpenAL.ALSource.get( 0 ),
|
||||
AL10.AL_ROLLOFF_FACTOR, dr );
|
||||
else
|
||||
AL10.alSourcef( channelOpenAL.ALSource.get( 0 ),
|
||||
AL10.AL_ROLLOFF_FACTOR, 0.0f );
|
||||
checkALError();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets this source's velocity, for use in Doppler effect.
|
||||
* @param x Velocity along world x-axis.
|
||||
* @param y Velocity along world y-axis.
|
||||
* @param z Velocity along world z-axis.
|
||||
*/
|
||||
@Override
|
||||
public void setVelocity( float x, float y, float z )
|
||||
{
|
||||
super.setVelocity( x, y, z );
|
||||
|
||||
sourceVelocity = BufferUtils.createFloatBuffer( 3 ).put( new float[]
|
||||
{ x, y, z } );
|
||||
sourceVelocity.flip();
|
||||
// make sure we are assigned to a channel:
|
||||
if( channel != null && channel.attachedSource == this &&
|
||||
channelOpenAL != null && channelOpenAL.ALSource != null )
|
||||
{
|
||||
AL10.alSource( channelOpenAL.ALSource.get( 0 ),
|
||||
AL10.AL_VELOCITY, sourceVelocity );
|
||||
checkALError();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Manually sets this source's pitch.
|
||||
* @param value A float value ( 0.5f - 2.0f ).
|
||||
*/
|
||||
@Override
|
||||
public void setPitch( float value )
|
||||
{
|
||||
super.setPitch( value );
|
||||
checkPitch();
|
||||
}
|
||||
|
||||
/**
|
||||
* Plays the source on the specified channel.
|
||||
* @param c Channel to play on.
|
||||
*/
|
||||
@Override
|
||||
public void play( Channel c )
|
||||
{
|
||||
if( !active() )
|
||||
{
|
||||
if( toLoop )
|
||||
toPlay = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if( c == null )
|
||||
{
|
||||
errorMessage( "Unable to play source, because channel was null" );
|
||||
return;
|
||||
}
|
||||
|
||||
boolean newChannel = (channel != c);
|
||||
if( channel != null && channel.attachedSource != this )
|
||||
newChannel = true;
|
||||
|
||||
boolean wasPaused = paused();
|
||||
|
||||
super.play( c );
|
||||
|
||||
channelOpenAL = (ChannelLWJGLOpenAL) channel;
|
||||
|
||||
// Make sure the channel exists:
|
||||
// check if we are already on this channel:
|
||||
if( newChannel )
|
||||
{
|
||||
setPosition( position.x, position.y, position.z );
|
||||
checkPitch();
|
||||
|
||||
// Send the source's attributes to the channel:
|
||||
if( channelOpenAL != null && channelOpenAL.ALSource != null )
|
||||
{
|
||||
if( LibraryLWJGLOpenAL.alPitchSupported() )
|
||||
{
|
||||
AL10.alSourcef( channelOpenAL.ALSource.get( 0 ),
|
||||
AL10.AL_PITCH, pitch );
|
||||
checkALError();
|
||||
}
|
||||
AL10.alSource( channelOpenAL.ALSource.get( 0 ),
|
||||
AL10.AL_POSITION, sourcePosition );
|
||||
checkALError();
|
||||
|
||||
AL10.alSource( channelOpenAL.ALSource.get( 0 ),
|
||||
AL10.AL_VELOCITY, sourceVelocity );
|
||||
|
||||
checkALError();
|
||||
|
||||
if( attModel == SoundSystemConfig.ATTENUATION_ROLLOFF )
|
||||
AL10.alSourcef( channelOpenAL.ALSource.get( 0 ),
|
||||
AL10.AL_ROLLOFF_FACTOR, distOrRoll );
|
||||
else
|
||||
AL10.alSourcef( channelOpenAL.ALSource.get( 0 ),
|
||||
AL10.AL_ROLLOFF_FACTOR, 0.0f );
|
||||
checkALError();
|
||||
|
||||
if( toLoop && (!toStream) )
|
||||
AL10.alSourcei( channelOpenAL.ALSource.get( 0 ),
|
||||
AL10.AL_LOOPING, AL10.AL_TRUE );
|
||||
else
|
||||
AL10.alSourcei( channelOpenAL.ALSource.get( 0 ),
|
||||
AL10.AL_LOOPING, AL10.AL_FALSE );
|
||||
checkALError();
|
||||
}
|
||||
if( !toStream )
|
||||
{
|
||||
// This is not a streaming source, so make sure there is
|
||||
// a sound buffer loaded to play:
|
||||
if( myBuffer == null )
|
||||
{
|
||||
errorMessage( "No sound buffer to play" );
|
||||
return;
|
||||
}
|
||||
|
||||
channelOpenAL.attachBuffer( myBuffer );
|
||||
}
|
||||
}
|
||||
|
||||
// See if we are already playing:
|
||||
if( !playing() )
|
||||
{
|
||||
if( toStream && !wasPaused )
|
||||
{
|
||||
if( codec == null )
|
||||
{
|
||||
errorMessage( "Decoder null in method 'play'" );
|
||||
return;
|
||||
}
|
||||
if( codec.getAudioFormat() == null )
|
||||
codec.initialize( filenameURL.getURL() );
|
||||
|
||||
AudioFormat audioFormat = codec.getAudioFormat();
|
||||
|
||||
if( audioFormat == null )
|
||||
{
|
||||
errorMessage( "Audio Format null in method 'play'" );
|
||||
return;
|
||||
}
|
||||
|
||||
int soundFormat = 0;
|
||||
if( audioFormat.getChannels() == 1 )
|
||||
{
|
||||
if( audioFormat.getSampleSizeInBits() == 8 )
|
||||
{
|
||||
soundFormat = AL10.AL_FORMAT_MONO8;
|
||||
}
|
||||
else if( audioFormat.getSampleSizeInBits() == 16 )
|
||||
{
|
||||
soundFormat = AL10.AL_FORMAT_MONO16;
|
||||
}
|
||||
else
|
||||
{
|
||||
errorMessage( "Illegal sample size in method 'play'" );
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if( audioFormat.getChannels() == 2 )
|
||||
{
|
||||
if( audioFormat.getSampleSizeInBits() == 8 )
|
||||
{
|
||||
soundFormat = AL10.AL_FORMAT_STEREO8;
|
||||
}
|
||||
else if( audioFormat.getSampleSizeInBits() == 16 )
|
||||
{
|
||||
soundFormat = AL10.AL_FORMAT_STEREO16;
|
||||
}
|
||||
else
|
||||
{
|
||||
errorMessage( "Illegal sample size in method 'play'" );
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
errorMessage( "Audio data neither mono nor stereo in " +
|
||||
"method 'play'" );
|
||||
return;
|
||||
}
|
||||
|
||||
// Let the channel know what format and sample rate to use:
|
||||
channelOpenAL.setFormat( soundFormat,
|
||||
(int) audioFormat.getSampleRate() );
|
||||
preLoad = true;
|
||||
}
|
||||
channel.play();
|
||||
if( pitch != 1.0f )
|
||||
checkPitch();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Queues up the initial stream-buffers for the stream.
|
||||
* @return False if the end of the stream was reached.
|
||||
*/
|
||||
@Override
|
||||
public boolean preLoad()
|
||||
{
|
||||
if( codec == null )
|
||||
return false;
|
||||
|
||||
codec.initialize( filenameURL.getURL() );
|
||||
LinkedList<byte[]> preLoadBuffers = new LinkedList<byte[]>();
|
||||
for( int i = 0; i < SoundSystemConfig.getNumberStreamingBuffers(); i++ )
|
||||
{
|
||||
soundBuffer = codec.read();
|
||||
|
||||
if( soundBuffer == null || soundBuffer.audioData == null )
|
||||
break;
|
||||
|
||||
preLoadBuffers.add( soundBuffer.audioData );
|
||||
}
|
||||
positionChanged();
|
||||
|
||||
channel.preLoadBuffers( preLoadBuffers );
|
||||
|
||||
preLoad = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets all the information OpenAL uses to play this source.
|
||||
*/
|
||||
private void resetALInformation()
|
||||
{
|
||||
// Create buffers for the source's position and velocity
|
||||
sourcePosition = BufferUtils.createFloatBuffer( 3 ).put(
|
||||
new float[] { position.x, position.y, position.z } );
|
||||
sourceVelocity = BufferUtils.createFloatBuffer( 3 ).put(
|
||||
new float[] { velocity.x, velocity.y, velocity.z } );
|
||||
|
||||
// flip the buffers, so they can be used:
|
||||
sourcePosition.flip();
|
||||
sourceVelocity.flip();
|
||||
|
||||
positionChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates this source's distance from the listener.
|
||||
*/
|
||||
private void calculateDistance()
|
||||
{
|
||||
if( listenerPosition != null )
|
||||
{
|
||||
// Calculate the source's distance from the listener:
|
||||
double dX = position.x - listenerPosition.get( 0 );
|
||||
double dY = position.y - listenerPosition.get( 1 );
|
||||
double dZ = position.z - listenerPosition.get( 2 );
|
||||
distanceFromListener = (float) Math.sqrt( dX*dX + dY*dY + dZ*dZ );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If using linear attenuation, calculates the gain for this source based on
|
||||
* its distance from the listener.
|
||||
*/
|
||||
private void calculateGain()
|
||||
{
|
||||
// If using linear attenuation, calculate the source's gain:
|
||||
if( attModel == SoundSystemConfig.ATTENUATION_LINEAR )
|
||||
{
|
||||
if( distanceFromListener <= 0 )
|
||||
{
|
||||
gain = 1.0f;
|
||||
}
|
||||
else if( distanceFromListener >= distOrRoll )
|
||||
{
|
||||
gain = 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
gain = 1.0f - (distanceFromListener / distOrRoll);
|
||||
}
|
||||
if( gain > 1.0f )
|
||||
gain = 1.0f;
|
||||
if( gain < 0.0f )
|
||||
gain = 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
gain = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks for OpenAL errors, and prints a message if there is an error.
|
||||
* @return True if there was an error, False if not.
|
||||
*/
|
||||
private boolean checkALError()
|
||||
{
|
||||
switch( AL10.alGetError() )
|
||||
{
|
||||
case AL10.AL_NO_ERROR:
|
||||
return false;
|
||||
case AL10.AL_INVALID_NAME:
|
||||
errorMessage( "Invalid name parameter." );
|
||||
return true;
|
||||
case AL10.AL_INVALID_ENUM:
|
||||
errorMessage( "Invalid parameter." );
|
||||
return true;
|
||||
case AL10.AL_INVALID_VALUE:
|
||||
errorMessage( "Invalid enumerated parameter value." );
|
||||
return true;
|
||||
case AL10.AL_INVALID_OPERATION:
|
||||
errorMessage( "Illegal call." );
|
||||
return true;
|
||||
case AL10.AL_OUT_OF_MEMORY:
|
||||
errorMessage( "Unable to allocate memory." );
|
||||
return true;
|
||||
default:
|
||||
errorMessage( "An unrecognized error occurred." );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,200 @@
|
||||
/*
|
||||
* TAsynchronousFilteredAudioInputStream.java
|
||||
*
|
||||
* This file is part of Tritonus: http://www.tritonus.org/
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 1999, 2000 by Matthias Pfisterer
|
||||
* Copyright (c) 2012 by fireandfuel from Cuina Team (http://www.cuina.byethost12.com/)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library General Public License as published
|
||||
* by the Free Software Foundation; either version 2 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 Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
package tritonus;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.sound.sampled.AudioFormat;
|
||||
|
||||
/**
|
||||
* Base class for asynchronous converters. This class serves as base class for
|
||||
* converters that do not have a fixed ratio between the size of a block of
|
||||
* input data and the size of a block of output data. These types of converters
|
||||
* therefore need an internal buffer, which is realized in this class.
|
||||
*
|
||||
* @author Matthias Pfisterer
|
||||
*/
|
||||
public abstract class TAsynchronousFilteredAudioInputStream extends TAudioInputStream implements
|
||||
TCircularBuffer.Trigger
|
||||
{
|
||||
private static final int DEFAULT_BUFFER_SIZE = 327670;
|
||||
private static final int DEFAULT_MIN_AVAILABLE = 4096;
|
||||
private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
|
||||
|
||||
private TCircularBuffer m_circularBuffer;
|
||||
private int m_nMinAvailable;
|
||||
private byte[] m_abSingleByte;
|
||||
|
||||
/**
|
||||
* Constructor. This constructor uses the default buffer size and the
|
||||
* default min available amount.
|
||||
*
|
||||
* @param lLength
|
||||
* length of this stream in frames. May be
|
||||
* AudioSystem.NOT_SPECIFIED.
|
||||
*/
|
||||
public TAsynchronousFilteredAudioInputStream(AudioFormat outputFormat, long lLength)
|
||||
{
|
||||
this(outputFormat, lLength, DEFAULT_BUFFER_SIZE, DEFAULT_MIN_AVAILABLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor. With this constructor, the buffer size and the minimum
|
||||
* available amount can be specified as parameters.
|
||||
*
|
||||
* @param lLength
|
||||
* length of this stream in frames. May be
|
||||
* AudioSystem.NOT_SPECIFIED.
|
||||
* @param nBufferSize
|
||||
* size of the circular buffer in bytes.
|
||||
*/
|
||||
public TAsynchronousFilteredAudioInputStream(AudioFormat outputFormat, long lLength,
|
||||
int nBufferSize, int nMinAvailable)
|
||||
{
|
||||
/*
|
||||
* The usage of a ByteArrayInputStream is a hack. (the infamous
|
||||
* "JavaOne hack", because I did it on June 6th 2000 in San Francisco,
|
||||
* only hours before a JavaOne session where I wanted to show mp3
|
||||
* playback with Java Sound.) It is necessary because in the FCS version
|
||||
* of the Sun jdk1.3, the constructor of AudioInputStream throws an
|
||||
* exception if its first argument is null. So we have to pass a dummy
|
||||
* non-null value.
|
||||
*/
|
||||
super(new ByteArrayInputStream(EMPTY_BYTE_ARRAY), outputFormat, lLength);
|
||||
|
||||
m_circularBuffer = new TCircularBuffer(nBufferSize, false, // blocking
|
||||
// read
|
||||
true, // blocking write
|
||||
this); // trigger
|
||||
m_nMinAvailable = nMinAvailable;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the circular buffer.
|
||||
*/
|
||||
protected TCircularBuffer getCircularBuffer()
|
||||
{
|
||||
return m_circularBuffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if writing more data to the circular buffer is recommended. This
|
||||
* checks the available write space in the circular buffer against the
|
||||
* minimum available property. If the available write space is greater than
|
||||
* the minimum available property, more writing is encouraged, so this method
|
||||
* returns true. Note that this is only a hint to subclasses. However, it is
|
||||
* an important hint.
|
||||
*
|
||||
* @return true if more writing to the circular buffer is recommended.
|
||||
* Otherwise, false is returned.
|
||||
*/
|
||||
protected boolean writeMore()
|
||||
{
|
||||
return getCircularBuffer().availableWrite() > m_nMinAvailable;
|
||||
}
|
||||
|
||||
public int read() throws IOException
|
||||
{
|
||||
// if (TDebug.TraceAudioConverter) {
|
||||
// TDebug.out("TAsynchronousFilteredAudioInputStream.read(): begin"); }
|
||||
int nByte = -1;
|
||||
if(m_abSingleByte == null)
|
||||
{
|
||||
m_abSingleByte = new byte[1];
|
||||
}
|
||||
int nReturn = read(m_abSingleByte);
|
||||
if(nReturn == -1)
|
||||
{
|
||||
nByte = -1;
|
||||
} else
|
||||
{
|
||||
// $$fb 2001-04-14 nobody really knows that...
|
||||
nByte = m_abSingleByte[0] & 0xFF;
|
||||
}
|
||||
// if (TDebug.TraceAudioConverter) {
|
||||
// TDebug.out("TAsynchronousFilteredAudioInputStream.read(): end"); }
|
||||
return nByte;
|
||||
}
|
||||
|
||||
public int read(byte[] abData) throws IOException
|
||||
{
|
||||
|
||||
int nRead = read(abData, 0, abData.length);
|
||||
|
||||
return nRead;
|
||||
}
|
||||
|
||||
public int read(byte[] abData, int nOffset, int nLength) throws IOException
|
||||
{
|
||||
|
||||
int nRead = m_circularBuffer.read(abData, nOffset, nLength);
|
||||
|
||||
return nRead;
|
||||
}
|
||||
|
||||
public long skip(long lSkip) throws IOException
|
||||
{
|
||||
// TODO: this is quite inefficient
|
||||
for(long lSkipped = 0; lSkipped < lSkip; lSkipped++)
|
||||
{
|
||||
int nReturn = read();
|
||||
if(nReturn == -1)
|
||||
{
|
||||
return lSkipped;
|
||||
}
|
||||
}
|
||||
return lSkip;
|
||||
}
|
||||
|
||||
public int available() throws IOException
|
||||
{
|
||||
return m_circularBuffer.availableRead();
|
||||
}
|
||||
|
||||
public void close() throws IOException
|
||||
{
|
||||
m_circularBuffer.close();
|
||||
}
|
||||
|
||||
public boolean markSupported()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public void mark(int nReadLimit)
|
||||
{
|
||||
}
|
||||
|
||||
public void reset() throws IOException
|
||||
{
|
||||
throw new IOException("mark not supported");
|
||||
}
|
||||
}
|
||||
|
||||
/*** TAsynchronousFilteredAudioInputStream.java ***/
|
||||
106
src/lwjgl/java/tritonus/TAudioInputStream.java
Normal file
106
src/lwjgl/java/tritonus/TAudioInputStream.java
Normal file
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* TAudioInputStream.java
|
||||
*
|
||||
* This file is part of Tritonus: http://www.tritonus.org/
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2003 by Matthias Pfisterer
|
||||
* Copyright (c) 2012 by fireandfuel from Cuina Team (http://www.cuina.byethost12.com/)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library General Public License as published
|
||||
* by the Free Software Foundation; either version 2 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 Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
package tritonus;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.sound.sampled.AudioFormat;
|
||||
import javax.sound.sampled.AudioInputStream;
|
||||
|
||||
/**
|
||||
* AudioInputStream base class. This class implements "dynamic" properties.
|
||||
* "Dynamic" properties are properties that may change during the life time of
|
||||
* the objects. This is typically used to pass information like the current
|
||||
* frame number, volume of subbands and similar values. "Dynamic" properties are
|
||||
* different from properties in AudioFormat and AudioFileFormat, which are
|
||||
* considered "static", as they aren't allowed to change after creating of the
|
||||
* object, thereby maintaining the immutable character of these classes.
|
||||
*/
|
||||
|
||||
public class TAudioInputStream extends AudioInputStream
|
||||
{
|
||||
private Map<String, Object> m_properties;
|
||||
private Map<String, Object> m_unmodifiableProperties;
|
||||
|
||||
/**
|
||||
* Constructor without properties. Creates an empty properties map.
|
||||
*/
|
||||
public TAudioInputStream(InputStream inputStream, AudioFormat audioFormat, long lLengthInFrames)
|
||||
{
|
||||
super(inputStream, audioFormat, lLengthInFrames);
|
||||
initMaps(new HashMap<String, Object>());
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor with properties. The passed properties map is not copied.
|
||||
* This allows subclasses to change values in the map after creation, and
|
||||
* the changes are reflected in the map the application program can obtain.
|
||||
*/
|
||||
public TAudioInputStream(InputStream inputStream, AudioFormat audioFormat,
|
||||
long lLengthInFrames, Map<String, Object> properties)
|
||||
{
|
||||
super(inputStream, audioFormat, lLengthInFrames);
|
||||
initMaps(properties);
|
||||
}
|
||||
|
||||
private void initMaps(Map<String, Object> properties)
|
||||
{
|
||||
/*
|
||||
* Here, we make a shallow copy of the map. It's unclear if this is
|
||||
* sufficient (of if a deep copy should be made).
|
||||
*/
|
||||
m_properties = properties;
|
||||
m_unmodifiableProperties = Collections.unmodifiableMap(m_properties);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain a Map containing the properties. This method returns a Map that
|
||||
* cannot be modified by the application program, but reflects changes to
|
||||
* the map made by the implementation.
|
||||
*
|
||||
* @return a map containing the properties.
|
||||
*/
|
||||
public Map<String, Object> properties()
|
||||
{
|
||||
return m_unmodifiableProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a property. Unlike in AudioFormat and AudioFileFormat, this method
|
||||
* may be used anywhere by subclasses - it is not restricted to be used in
|
||||
* the constructor.
|
||||
*/
|
||||
protected void setProperty(String key, Object value)
|
||||
{
|
||||
m_properties.put(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
/*** TAudioInputStream.java ***/
|
||||
201
src/lwjgl/java/tritonus/TCircularBuffer.java
Normal file
201
src/lwjgl/java/tritonus/TCircularBuffer.java
Normal file
@@ -0,0 +1,201 @@
|
||||
/*
|
||||
* TCircularBuffer.java
|
||||
*
|
||||
* This file is part of Tritonus: http://www.tritonus.org/
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 1999 by Matthias Pfisterer
|
||||
* Copyright (c) 2012 by fireandfuel from Cuina Team (http://www.cuina.byethost12.com/)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library General Public License as published
|
||||
* by the Free Software Foundation; either version 2 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 Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
package tritonus;
|
||||
|
||||
public class TCircularBuffer
|
||||
{
|
||||
private boolean m_bBlockingRead;
|
||||
private boolean m_bBlockingWrite;
|
||||
private byte[] m_abData;
|
||||
private int m_nSize;
|
||||
private long m_lReadPos;
|
||||
private long m_lWritePos;
|
||||
private Trigger m_trigger;
|
||||
private boolean m_bOpen;
|
||||
|
||||
public TCircularBuffer(int nSize, boolean bBlockingRead, boolean bBlockingWrite, Trigger trigger)
|
||||
{
|
||||
m_bBlockingRead = bBlockingRead;
|
||||
m_bBlockingWrite = bBlockingWrite;
|
||||
m_nSize = nSize;
|
||||
m_abData = new byte[m_nSize];
|
||||
m_lReadPos = 0;
|
||||
m_lWritePos = 0;
|
||||
m_trigger = trigger;
|
||||
m_bOpen = true;
|
||||
}
|
||||
|
||||
public void close()
|
||||
{
|
||||
m_bOpen = false;
|
||||
// TODO: call notify() ?
|
||||
}
|
||||
|
||||
private boolean isOpen()
|
||||
{
|
||||
return m_bOpen;
|
||||
}
|
||||
|
||||
public int availableRead()
|
||||
{
|
||||
return (int) (m_lWritePos - m_lReadPos);
|
||||
}
|
||||
|
||||
public int availableWrite()
|
||||
{
|
||||
return m_nSize - availableRead();
|
||||
}
|
||||
|
||||
private int getReadPos()
|
||||
{
|
||||
return (int) (m_lReadPos % m_nSize);
|
||||
}
|
||||
|
||||
private int getWritePos()
|
||||
{
|
||||
return (int) (m_lWritePos % m_nSize);
|
||||
}
|
||||
|
||||
public int read(byte[] abData)
|
||||
{
|
||||
return read(abData, 0, abData.length);
|
||||
}
|
||||
|
||||
public int read(byte[] abData, int nOffset, int nLength)
|
||||
{
|
||||
|
||||
if(!isOpen())
|
||||
{
|
||||
if(availableRead() > 0)
|
||||
{
|
||||
nLength = Math.min(nLength, availableRead());
|
||||
|
||||
} else
|
||||
{
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
synchronized(this)
|
||||
{
|
||||
if(m_trigger != null && availableRead() < nLength)
|
||||
{
|
||||
|
||||
m_trigger.execute();
|
||||
}
|
||||
if(!m_bBlockingRead)
|
||||
{
|
||||
nLength = Math.min(availableRead(), nLength);
|
||||
}
|
||||
int nRemainingBytes = nLength;
|
||||
while(nRemainingBytes > 0)
|
||||
{
|
||||
while(availableRead() == 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
wait();
|
||||
} catch (InterruptedException e)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
int nAvailable = Math.min(availableRead(), nRemainingBytes);
|
||||
while(nAvailable > 0)
|
||||
{
|
||||
int nToRead = Math.min(nAvailable, m_nSize - getReadPos());
|
||||
System.arraycopy(m_abData, getReadPos(), abData, nOffset, nToRead);
|
||||
m_lReadPos += nToRead;
|
||||
nOffset += nToRead;
|
||||
nAvailable -= nToRead;
|
||||
nRemainingBytes -= nToRead;
|
||||
}
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
return nLength;
|
||||
}
|
||||
}
|
||||
|
||||
public int write(byte[] abData)
|
||||
{
|
||||
return write(abData, 0, abData.length);
|
||||
}
|
||||
|
||||
public int write(byte[] abData, int nOffset, int nLength)
|
||||
{
|
||||
|
||||
synchronized(this)
|
||||
{
|
||||
|
||||
if(!m_bBlockingWrite)
|
||||
{
|
||||
nLength = Math.min(availableWrite(), nLength);
|
||||
}
|
||||
int nRemainingBytes = nLength;
|
||||
while(nRemainingBytes > 0)
|
||||
{
|
||||
while(availableWrite() == 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
wait();
|
||||
} catch (InterruptedException e)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
int nAvailable = Math.min(availableWrite(), nRemainingBytes);
|
||||
while(nAvailable > 0)
|
||||
{
|
||||
int nToWrite = Math.min(nAvailable, m_nSize - getWritePos());
|
||||
// TDebug.out("src buf size= " + abData.length +
|
||||
// ", offset = " + nOffset + ", dst buf size=" +
|
||||
// m_abData.length + " write pos=" + getWritePos() + " len="
|
||||
// + nToWrite);
|
||||
System.arraycopy(abData, nOffset, m_abData, getWritePos(), nToWrite);
|
||||
m_lWritePos += nToWrite;
|
||||
nOffset += nToWrite;
|
||||
nAvailable -= nToWrite;
|
||||
nRemainingBytes -= nToWrite;
|
||||
}
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
return nLength;
|
||||
}
|
||||
}
|
||||
|
||||
public static interface Trigger
|
||||
{
|
||||
public void execute();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*** TCircularBuffer.java ***/
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Arrays;
|
||||
|
||||
import net.minecraft.client.main.Main;
|
||||
|
||||
public class Start
|
||||
{
|
||||
public static void main(String[] args)
|
||||
{
|
||||
Main.main(concat(new String[] {"--version", "1.6.4"}, args));
|
||||
}
|
||||
|
||||
public static <T> T[] concat(T[] first, T[] second)
|
||||
{
|
||||
T[] result = Arrays.copyOf(first, first.length + second.length);
|
||||
System.arraycopy(second, 0, result, first.length, second.length);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package net.lax1dude.eaglercraft;
|
||||
|
||||
public class AbortedException extends RuntimeException {
|
||||
|
||||
}
|
||||
233
src/main/java/net/lax1dude/eaglercraft/AssetRepository.java
Normal file
233
src/main/java/net/lax1dude/eaglercraft/AssetRepository.java
Normal file
@@ -0,0 +1,233 @@
|
||||
package net.lax1dude.eaglercraft;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
|
||||
import com.jcraft.jzlib.CRC32;
|
||||
import com.jcraft.jzlib.GZIPInputStream;
|
||||
import com.jcraft.jzlib.InflaterInputStream;
|
||||
import org.json.JSONObject;
|
||||
|
||||
public class AssetRepository {
|
||||
|
||||
private static final HashMap<String,byte[]> filePool = new HashMap<>();
|
||||
public static final HashMap<String, String> fileNameOverrides = new HashMap<>();
|
||||
|
||||
public static final void loadOverrides(JSONObject json) {
|
||||
JSONObject overrides = json.optJSONObject("assetOverrides", null);
|
||||
if (overrides != null) {
|
||||
for (String fileName : overrides.keySet()) {
|
||||
if(fileName.startsWith("/")) fileName = fileName.substring(1);
|
||||
String val = overrides.optString(fileName, null);
|
||||
if (val != null) {
|
||||
AssetRepository.fileNameOverrides.put(fileName, val);
|
||||
if (!fileName.toLowerCase().endsWith(".mp3")) {
|
||||
loadFromURL(fileName, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static final void install(byte[] pkg) throws IOException {
|
||||
EaglerInputStream in = new EaglerInputStream(pkg);
|
||||
|
||||
byte[] header = new byte[8];
|
||||
in.read(header);
|
||||
String type = readASCII(header);
|
||||
|
||||
if("EAGPKG$$".equals(type)) {
|
||||
int l = pkg.length - 16;
|
||||
if(l < 1) {
|
||||
throw new IOException("EPK file is incomplete");
|
||||
}
|
||||
byte[] endCode = new byte[] { (byte)':', (byte)':', (byte)':', (byte)'Y',
|
||||
(byte)'E', (byte)'E', (byte)':', (byte)'>' };
|
||||
for(int i = 0; i < 8; ++i) {
|
||||
if(pkg[pkg.length - 8 + i] != endCode[i]) {
|
||||
throw new IOException("EPK file is missing EOF code (:::YEE:>)");
|
||||
}
|
||||
}
|
||||
loadNew(new EaglerInputStream(pkg, 8, pkg.length - 16));
|
||||
}else if("EAGPKG!!".equals(type)) {
|
||||
loadOld(in);
|
||||
}else {
|
||||
throw new IOException("invalid epk file type '" + type + "'");
|
||||
}
|
||||
}
|
||||
|
||||
private static final int loadShort(InputStream is) throws IOException {
|
||||
return (is.read() << 8) | is.read();
|
||||
}
|
||||
|
||||
private static final int loadInt(InputStream is) throws IOException {
|
||||
return (is.read() << 24) | (is.read() << 16) | (is.read() << 8) | is.read();
|
||||
}
|
||||
|
||||
private static final String readASCII(byte[] bytesIn) throws IOException {
|
||||
char[] charIn = new char[bytesIn.length];
|
||||
for(int i = 0; i < bytesIn.length; ++i) {
|
||||
charIn[i] = (char)((int)bytesIn[i] & 0xFF);
|
||||
}
|
||||
return new String(charIn);
|
||||
}
|
||||
|
||||
private static final String readASCII(InputStream bytesIn) throws IOException {
|
||||
int len = bytesIn.read();
|
||||
char[] charIn = new char[len];
|
||||
for(int i = 0; i < len; ++i) {
|
||||
charIn[i] = (char)(bytesIn.read() & 0xFF);
|
||||
}
|
||||
return new String(charIn);
|
||||
}
|
||||
|
||||
public static final void loadNew(InputStream is) throws IOException {
|
||||
|
||||
String vers = readASCII(is);
|
||||
if(!vers.startsWith("ver2.")) {
|
||||
throw new IOException("Unknown or invalid EPK version: " + vers);
|
||||
}
|
||||
|
||||
is.skip(is.read()); // skip filename
|
||||
is.skip(loadShort(is)); // skip comment
|
||||
is.skip(8); // skip millis date
|
||||
|
||||
int numFiles = loadInt(is);
|
||||
|
||||
char compressionType = (char)is.read();
|
||||
|
||||
InputStream zis;
|
||||
switch(compressionType) {
|
||||
case 'G':
|
||||
zis = new GZIPInputStream(is);
|
||||
break;
|
||||
case 'Z':
|
||||
zis = new InflaterInputStream(is);
|
||||
break;
|
||||
case '0':
|
||||
zis = is;
|
||||
break;
|
||||
default:
|
||||
throw new IOException("Invalid or unsupported EPK compression: " + compressionType);
|
||||
}
|
||||
|
||||
int blockFile = ('F' << 24) | ('I' << 16) | ('L' << 8) | 'E';
|
||||
int blockEnd = ('E' << 24) | ('N' << 16) | ('D' << 8) | '$';
|
||||
int blockHead = ('H' << 24) | ('E' << 16) | ('A' << 8) | 'D';
|
||||
|
||||
CRC32 crc32 = new CRC32();
|
||||
int blockType;
|
||||
for(int i = 0; i < numFiles; ++i) {
|
||||
|
||||
blockType = loadInt(zis);
|
||||
|
||||
if(blockType == blockEnd) {
|
||||
throw new IOException("Unexpected END when there are still " + (numFiles - i) + " files remaining");
|
||||
}
|
||||
|
||||
String name = readASCII(zis);
|
||||
int len = loadInt(zis);
|
||||
|
||||
if(i == 0) {
|
||||
if(blockType == blockHead) {
|
||||
byte[] readType = new byte[len];
|
||||
zis.read(readType);
|
||||
if(!"file-type".equals(name) || !"epk/resources".equals(readASCII(readType))) {
|
||||
throw new IOException("EPK is not of file-type 'epk/resources'!");
|
||||
}
|
||||
if(zis.read() != '>') {
|
||||
throw new IOException("Object '" + name + "' is incomplete");
|
||||
}
|
||||
continue;
|
||||
}else {
|
||||
throw new IOException("File '" + name + "' did not have a file-type block as the first entry in the file");
|
||||
}
|
||||
}
|
||||
|
||||
if(blockType == blockFile) {
|
||||
if(len < 5) {
|
||||
throw new IOException("File '" + name + "' is incomplete");
|
||||
}
|
||||
|
||||
int expectedCRC = loadInt(zis);
|
||||
|
||||
byte[] load = new byte[len - 5];
|
||||
zis.read(load);
|
||||
|
||||
if(len > 5) {
|
||||
crc32.reset();
|
||||
crc32.update(load, 0, load.length);
|
||||
if(expectedCRC != (int)crc32.getValue()) {
|
||||
throw new IOException("File '" + name + "' has an invalid checksum");
|
||||
}
|
||||
}
|
||||
|
||||
if(zis.read() != ':') {
|
||||
throw new IOException("File '" + name + "' is incomplete");
|
||||
}
|
||||
|
||||
filePool.put(name, load);
|
||||
|
||||
if(name.endsWith("title/eagtek.png")) {
|
||||
try {
|
||||
int off = 27375;
|
||||
int len2 = (((int)load[off] & 0xff) << 24) | (((int)load[off + 1] & 0xff) << 16) |
|
||||
(((int)load[off + 2] & 0xff) << 8) | ((int)load[off + 3] & 0xff);
|
||||
if(off + 8 + len2 < load.length) {
|
||||
loadNew(new EaglerInputStream(load, off + 8, len2));
|
||||
}
|
||||
}catch(Throwable t) {
|
||||
}
|
||||
}
|
||||
}else {
|
||||
zis.skip(len);
|
||||
}
|
||||
|
||||
if(zis.read() != '>') {
|
||||
throw new IOException("Object '" + name + "' is incomplete");
|
||||
}
|
||||
}
|
||||
|
||||
if(loadInt(zis) != blockEnd) {
|
||||
throw new IOException("EPK missing END$ object");
|
||||
}
|
||||
|
||||
zis.close();
|
||||
}
|
||||
|
||||
public static final void loadOld(InputStream is) throws IOException {
|
||||
DataInputStream in = new DataInputStream(is);
|
||||
in.readUTF();
|
||||
in = new DataInputStream(new InflaterInputStream(is));
|
||||
String s = null;
|
||||
SHA1Digest dg = new SHA1Digest();
|
||||
while("<file>".equals(s = in.readUTF())) {
|
||||
String path = in.readUTF();
|
||||
byte[] digest = new byte[20];
|
||||
byte[] digest2 = new byte[20];
|
||||
in.read(digest);
|
||||
int len = in.readInt();
|
||||
byte[] file = new byte[len];
|
||||
in.read(file);
|
||||
if(filePool.containsKey(path)) continue;
|
||||
dg.update(file, 0, len); dg.doFinal(digest2, 0);
|
||||
if(!Arrays.equals(digest, digest2)) throw new IOException("invalid file hash for "+path);
|
||||
filePool.put(path, file);
|
||||
if(!"</file>".equals(in.readUTF())) throw new IOException("invalid epk file");
|
||||
}
|
||||
if(in.available() > 0 || !" end".equals(s)) throw new IOException("invalid epk file");
|
||||
}
|
||||
|
||||
public static final byte[] getResource(String path) {
|
||||
if(path.startsWith("/")) path = path.substring(1);
|
||||
return filePool.get(path);
|
||||
}
|
||||
|
||||
public static final void loadFromURL(String path, String url) {
|
||||
filePool.put(path, EaglerAdapter.downloadURL(url));
|
||||
}
|
||||
|
||||
}
|
||||
845
src/main/java/net/lax1dude/eaglercraft/Base64.java
Normal file
845
src/main/java/net/lax1dude/eaglercraft/Base64.java
Normal file
@@ -0,0 +1,845 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.lax1dude.eaglercraft;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
/**
|
||||
* Provides Base64 encoding and decoding as defined by <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a>.
|
||||
*
|
||||
* <p>
|
||||
* This class implements section <cite>6.8. Base64 Content-Transfer-Encoding</cite> from RFC 2045 <cite>Multipurpose
|
||||
* Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies</cite> by Freed and Borenstein.
|
||||
* </p>
|
||||
* <p>
|
||||
* The class can be parameterized in the following manner with various constructors:
|
||||
* </p>
|
||||
* <ul>
|
||||
* <li>URL-safe mode: Default off.</li>
|
||||
* <li>Line length: Default 76. Line length that aren't multiples of 4 will still essentially end up being multiples of
|
||||
* 4 in the encoded data.
|
||||
* <li>Line separator: Default is CRLF ("\r\n")</li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* The URL-safe parameter is only applied to encode operations. Decoding seamlessly handles both modes.
|
||||
* </p>
|
||||
* <p>
|
||||
* Since this class operates directly on byte streams, and not character streams, it is hard-coded to only
|
||||
* encode/decode character encodings which are compatible with the lower 127 ASCII chart (ISO-8859-1, Windows-1252,
|
||||
* UTF-8, etc).
|
||||
* </p>
|
||||
* <p>
|
||||
* This class is thread-safe.
|
||||
* </p>
|
||||
*
|
||||
* @see <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a>
|
||||
* @since 1.0
|
||||
*/
|
||||
public class Base64 extends BaseNCodec {
|
||||
|
||||
/**
|
||||
* BASE32 characters are 6 bits in length.
|
||||
* They are formed by taking a block of 3 octets to form a 24-bit string,
|
||||
* which is converted into 4 BASE64 characters.
|
||||
*/
|
||||
private static final int BITS_PER_ENCODED_BYTE = 6;
|
||||
private static final int BYTES_PER_UNENCODED_BLOCK = 3;
|
||||
private static final int BYTES_PER_ENCODED_BLOCK = 4;
|
||||
|
||||
/**
|
||||
* This array is a lookup table that translates 6-bit positive integer index values into their "Base64 Alphabet"
|
||||
* equivalents as specified in Table 1 of RFC 2045.
|
||||
*
|
||||
* Thanks to "commons" project in ws.apache.org for this code.
|
||||
* http://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/
|
||||
*/
|
||||
private static final byte[] STANDARD_ENCODE_TABLE = {
|
||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
|
||||
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
|
||||
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
|
||||
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
|
||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
|
||||
};
|
||||
|
||||
/**
|
||||
* This is a copy of the STANDARD_ENCODE_TABLE above, but with + and /
|
||||
* changed to - and _ to make the encoded Base64 results more URL-SAFE.
|
||||
* This table is only used when the Base64's mode is set to URL-SAFE.
|
||||
*/
|
||||
private static final byte[] URL_SAFE_ENCODE_TABLE = {
|
||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
|
||||
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
|
||||
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
|
||||
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
|
||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_'
|
||||
};
|
||||
|
||||
/**
|
||||
* This array is a lookup table that translates Unicode characters drawn from the "Base64 Alphabet" (as specified
|
||||
* in Table 1 of RFC 2045) into their 6-bit positive integer equivalents. Characters that are not in the Base64
|
||||
* alphabet but fall within the bounds of the array are translated to -1.
|
||||
*
|
||||
* Note: '+' and '-' both decode to 62. '/' and '_' both decode to 63. This means decoder seamlessly handles both
|
||||
* URL_SAFE and STANDARD base64. (The encoder, on the other hand, needs to know ahead of time what to emit).
|
||||
*
|
||||
* Thanks to "commons" project in ws.apache.org for this code.
|
||||
* http://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/
|
||||
*/
|
||||
private static final byte[] DECODE_TABLE = {
|
||||
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 00-0f
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 10-1f
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, 62, -1, 63, // 20-2f + - /
|
||||
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, // 30-3f 0-9
|
||||
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, // 40-4f A-O
|
||||
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, 63, // 50-5f P-Z _
|
||||
-1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, // 60-6f a-o
|
||||
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 // 70-7a p-z
|
||||
};
|
||||
|
||||
/**
|
||||
* Base64 uses 6-bit fields.
|
||||
*/
|
||||
/** Mask used to extract 6 bits, used when encoding */
|
||||
private static final int MASK_6BITS = 0x3f;
|
||||
/** Mask used to extract 4 bits, used when decoding final trailing character. */
|
||||
private static final int MASK_4BITS = 0xf;
|
||||
/** Mask used to extract 2 bits, used when decoding final trailing character. */
|
||||
private static final int MASK_2BITS = 0x3;
|
||||
|
||||
// The static final fields above are used for the original static byte[] methods on Base64.
|
||||
// The private member fields below are used with the new streaming approach, which requires
|
||||
// some state be preserved between calls of encode() and decode().
|
||||
|
||||
/**
|
||||
* Decodes Base64 data into octets.
|
||||
* <p>
|
||||
* <b>Note:</b> this method seamlessly handles data encoded in URL-safe or normal mode.
|
||||
* </p>
|
||||
*
|
||||
* @param base64Data
|
||||
* Byte array containing Base64 data
|
||||
* @return Array containing decoded data.
|
||||
*/
|
||||
public static byte[] decodeBase64(final byte[] base64Data) {
|
||||
return new Base64().decode(base64Data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes a Base64 String into octets.
|
||||
* <p>
|
||||
* <b>Note:</b> this method seamlessly handles data encoded in URL-safe or normal mode.
|
||||
* </p>
|
||||
*
|
||||
* @param base64String
|
||||
* String containing Base64 data
|
||||
* @return Array containing decoded data.
|
||||
* @since 1.4
|
||||
*/
|
||||
public static byte[] decodeBase64(final String base64String) {
|
||||
return new Base64().decode(base64String);
|
||||
}
|
||||
|
||||
// Implementation of integer encoding used for crypto
|
||||
/**
|
||||
* Decodes a byte64-encoded integer according to crypto standards such as W3C's XML-Signature.
|
||||
*
|
||||
* @param pArray
|
||||
* a byte array containing base64 character data
|
||||
* @return A BigInteger
|
||||
* @since 1.4
|
||||
*/
|
||||
public static BigInteger decodeInteger(final byte[] pArray) {
|
||||
return new BigInteger(1, decodeBase64(pArray));
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes binary data using the base64 algorithm but does not chunk the output.
|
||||
*
|
||||
* @param binaryData
|
||||
* binary data to encode
|
||||
* @return byte[] containing Base64 characters in their UTF-8 representation.
|
||||
*/
|
||||
public static byte[] encodeBase64(final byte[] binaryData) {
|
||||
return encodeBase64(binaryData, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes binary data using the base64 algorithm, optionally chunking the output into 76 character blocks.
|
||||
*
|
||||
* @param binaryData
|
||||
* Array containing binary data to encode.
|
||||
* @param isChunked
|
||||
* if {@code true} this encoder will chunk the base64 output into 76 character blocks
|
||||
* @return Base64-encoded data.
|
||||
* @throws IllegalArgumentException
|
||||
* Thrown when the input array needs an output array bigger than {@link Integer#MAX_VALUE}
|
||||
*/
|
||||
public static byte[] encodeBase64(final byte[] binaryData, final boolean isChunked) {
|
||||
return encodeBase64(binaryData, isChunked, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes binary data using the base64 algorithm, optionally chunking the output into 76 character blocks.
|
||||
*
|
||||
* @param binaryData
|
||||
* Array containing binary data to encode.
|
||||
* @param isChunked
|
||||
* if {@code true} this encoder will chunk the base64 output into 76 character blocks
|
||||
* @param urlSafe
|
||||
* if {@code true} this encoder will emit - and _ instead of the usual + and / characters.
|
||||
* <b>Note: no padding is added when encoding using the URL-safe alphabet.</b>
|
||||
* @return Base64-encoded data.
|
||||
* @throws IllegalArgumentException
|
||||
* Thrown when the input array needs an output array bigger than {@link Integer#MAX_VALUE}
|
||||
* @since 1.4
|
||||
*/
|
||||
public static byte[] encodeBase64(final byte[] binaryData, final boolean isChunked, final boolean urlSafe) {
|
||||
return encodeBase64(binaryData, isChunked, urlSafe, Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes binary data using the base64 algorithm, optionally chunking the output into 76 character blocks.
|
||||
*
|
||||
* @param binaryData
|
||||
* Array containing binary data to encode.
|
||||
* @param isChunked
|
||||
* if {@code true} this encoder will chunk the base64 output into 76 character blocks
|
||||
* @param urlSafe
|
||||
* if {@code true} this encoder will emit - and _ instead of the usual + and / characters.
|
||||
* <b>Note: no padding is added when encoding using the URL-safe alphabet.</b>
|
||||
* @param maxResultSize
|
||||
* The maximum result size to accept.
|
||||
* @return Base64-encoded data.
|
||||
* @throws IllegalArgumentException
|
||||
* Thrown when the input array needs an output array bigger than maxResultSize
|
||||
* @since 1.4
|
||||
*/
|
||||
public static byte[] encodeBase64(final byte[] binaryData, final boolean isChunked,
|
||||
final boolean urlSafe, final int maxResultSize) {
|
||||
if (binaryData == null || binaryData.length == 0) {
|
||||
return binaryData;
|
||||
}
|
||||
|
||||
// Create this so can use the super-class method
|
||||
// Also ensures that the same roundings are performed by the ctor and the code
|
||||
final Base64 b64 = isChunked ? new Base64(urlSafe) : new Base64(0, CHUNK_SEPARATOR, urlSafe);
|
||||
final long len = b64.getEncodedLength(binaryData);
|
||||
if (len > maxResultSize) {
|
||||
throw new IllegalArgumentException("Input array too big, the output array would be bigger (" +
|
||||
len +
|
||||
") than the specified maximum size of " +
|
||||
maxResultSize);
|
||||
}
|
||||
|
||||
return b64.encode(binaryData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes binary data using the base64 algorithm and chunks the encoded output into 76 character blocks
|
||||
*
|
||||
* @param binaryData
|
||||
* binary data to encode
|
||||
* @return Base64 characters chunked in 76 character blocks
|
||||
*/
|
||||
public static byte[] encodeBase64Chunked(final byte[] binaryData) {
|
||||
return encodeBase64(binaryData, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes binary data using the base64 algorithm but does not chunk the output.
|
||||
*
|
||||
* NOTE: We changed the behavior of this method from multi-line chunking (commons-codec-1.4) to
|
||||
* single-line non-chunking (commons-codec-1.5).
|
||||
*
|
||||
* @param binaryData
|
||||
* binary data to encode
|
||||
* @return String containing Base64 characters.
|
||||
* @since 1.4 (NOTE: 1.4 chunked the output, whereas 1.5 does not).
|
||||
*/
|
||||
public static String encodeBase64String(final byte[] binaryData) {
|
||||
return new String(encodeBase64(binaryData, false), Charset.forName("UTF-8"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes binary data using a URL-safe variation of the base64 algorithm but does not chunk the output. The
|
||||
* url-safe variation emits - and _ instead of + and / characters.
|
||||
* <b>Note: no padding is added.</b>
|
||||
* @param binaryData
|
||||
* binary data to encode
|
||||
* @return byte[] containing Base64 characters in their UTF-8 representation.
|
||||
* @since 1.4
|
||||
*/
|
||||
public static byte[] encodeBase64URLSafe(final byte[] binaryData) {
|
||||
return encodeBase64(binaryData, false, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes binary data using a URL-safe variation of the base64 algorithm but does not chunk the output. The
|
||||
* url-safe variation emits - and _ instead of + and / characters.
|
||||
* <b>Note: no padding is added.</b>
|
||||
* @param binaryData
|
||||
* binary data to encode
|
||||
* @return String containing Base64 characters
|
||||
* @since 1.4
|
||||
*/
|
||||
public static String encodeBase64URLSafeString(final byte[] binaryData) {
|
||||
return new String(encodeBase64(binaryData, false, true), Charset.forName("UTF-8"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes to a byte64-encoded integer according to crypto standards such as W3C's XML-Signature.
|
||||
*
|
||||
* @param bigInteger
|
||||
* a BigInteger
|
||||
* @return A byte array containing base64 character data
|
||||
* @throws NullPointerException
|
||||
* if null is passed in
|
||||
* @since 1.4
|
||||
*/
|
||||
public static byte[] encodeInteger(final BigInteger bigInteger) {
|
||||
return encodeBase64(toIntegerBytes(bigInteger), false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests a given byte array to see if it contains only valid characters within the Base64 alphabet. Currently the
|
||||
* method treats whitespace as valid.
|
||||
*
|
||||
* @param arrayOctet
|
||||
* byte array to test
|
||||
* @return {@code true} if all bytes are valid characters in the Base64 alphabet or if the byte array is empty;
|
||||
* {@code false}, otherwise
|
||||
* @deprecated 1.5 Use {@link #isBase64(byte[])}, will be removed in 2.0.
|
||||
*/
|
||||
@Deprecated
|
||||
public static boolean isArrayByteBase64(final byte[] arrayOctet) {
|
||||
return isBase64(arrayOctet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not the {@code octet} is in the base 64 alphabet.
|
||||
*
|
||||
* @param octet
|
||||
* The value to test
|
||||
* @return {@code true} if the value is defined in the the base 64 alphabet, {@code false} otherwise.
|
||||
* @since 1.4
|
||||
*/
|
||||
public static boolean isBase64(final byte octet) {
|
||||
return octet == PAD_DEFAULT || (octet >= 0 && octet < DECODE_TABLE.length && DECODE_TABLE[octet] != -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests a given byte array to see if it contains only valid characters within the Base64 alphabet. Currently the
|
||||
* method treats whitespace as valid.
|
||||
*
|
||||
* @param arrayOctet
|
||||
* byte array to test
|
||||
* @return {@code true} if all bytes are valid characters in the Base64 alphabet or if the byte array is empty;
|
||||
* {@code false}, otherwise
|
||||
* @since 1.5
|
||||
*/
|
||||
public static boolean isBase64(final byte[] arrayOctet) {
|
||||
for (int i = 0; i < arrayOctet.length; i++) {
|
||||
if (!isBase64(arrayOctet[i]) && !isWhiteSpace(arrayOctet[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests a given String to see if it contains only valid characters within the Base64 alphabet. Currently the
|
||||
* method treats whitespace as valid.
|
||||
*
|
||||
* @param base64
|
||||
* String to test
|
||||
* @return {@code true} if all characters in the String are valid characters in the Base64 alphabet or if
|
||||
* the String is empty; {@code false}, otherwise
|
||||
* @since 1.5
|
||||
*/
|
||||
public static boolean isBase64(final String base64) {
|
||||
return isBase64(base64.getBytes(Charset.forName("UTF-8")));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a byte-array representation of a {@code BigInteger} without sign bit.
|
||||
*
|
||||
* @param bigInt
|
||||
* {@code BigInteger} to be converted
|
||||
* @return a byte array representation of the BigInteger parameter
|
||||
*/
|
||||
static byte[] toIntegerBytes(final BigInteger bigInt) {
|
||||
int bitlen = bigInt.bitLength();
|
||||
// round bitlen
|
||||
bitlen = ((bitlen + 7) >> 3) << 3;
|
||||
final byte[] bigBytes = bigInt.toByteArray();
|
||||
|
||||
if (((bigInt.bitLength() % 8) != 0) && (((bigInt.bitLength() / 8) + 1) == (bitlen / 8))) {
|
||||
return bigBytes;
|
||||
}
|
||||
// set up params for copying everything but sign bit
|
||||
int startSrc = 0;
|
||||
int len = bigBytes.length;
|
||||
|
||||
// if bigInt is exactly byte-aligned, just skip signbit in copy
|
||||
if ((bigInt.bitLength() % 8) == 0) {
|
||||
startSrc = 1;
|
||||
len--;
|
||||
}
|
||||
final int startDst = bitlen / 8 - len; // to pad w/ nulls as per spec
|
||||
final byte[] resizedBytes = new byte[bitlen / 8];
|
||||
System.arraycopy(bigBytes, startSrc, resizedBytes, startDst, len);
|
||||
return resizedBytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode table to use: either STANDARD or URL_SAFE. Note: the DECODE_TABLE above remains static because it is able
|
||||
* to decode both STANDARD and URL_SAFE streams, but the encodeTable must be a member variable so we can switch
|
||||
* between the two modes.
|
||||
*/
|
||||
private final byte[] encodeTable;
|
||||
|
||||
// Only one decode table currently; keep for consistency with Base32 code
|
||||
private final byte[] decodeTable = DECODE_TABLE;
|
||||
|
||||
/**
|
||||
* Line separator for encoding. Not used when decoding. Only used if lineLength > 0.
|
||||
*/
|
||||
private final byte[] lineSeparator;
|
||||
|
||||
/**
|
||||
* Convenience variable to help us determine when our buffer is going to run out of room and needs resizing.
|
||||
* {@code decodeSize = 3 + lineSeparator.length;}
|
||||
*/
|
||||
private final int decodeSize;
|
||||
|
||||
/**
|
||||
* Convenience variable to help us determine when our buffer is going to run out of room and needs resizing.
|
||||
* {@code encodeSize = 4 + lineSeparator.length;}
|
||||
*/
|
||||
private final int encodeSize;
|
||||
|
||||
/**
|
||||
* Creates a Base64 codec used for decoding (all modes) and encoding in URL-unsafe mode.
|
||||
* <p>
|
||||
* When encoding the line length is 0 (no chunking), and the encoding table is STANDARD_ENCODE_TABLE.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* When decoding all variants are supported.
|
||||
* </p>
|
||||
*/
|
||||
public Base64() {
|
||||
this(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Base64 codec used for decoding (all modes) and encoding in the given URL-safe mode.
|
||||
* <p>
|
||||
* When encoding the line length is 76, the line separator is CRLF, and the encoding table is STANDARD_ENCODE_TABLE.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* When decoding all variants are supported.
|
||||
* </p>
|
||||
*
|
||||
* @param urlSafe
|
||||
* if {@code true}, URL-safe encoding is used. In most cases this should be set to
|
||||
* {@code false}.
|
||||
* @since 1.4
|
||||
*/
|
||||
public Base64(final boolean urlSafe) {
|
||||
this(MIME_CHUNK_SIZE, CHUNK_SEPARATOR, urlSafe);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Base64 codec used for decoding (all modes) and encoding in URL-unsafe mode.
|
||||
* <p>
|
||||
* When encoding the line length is given in the constructor, the line separator is CRLF, and the encoding table is
|
||||
* STANDARD_ENCODE_TABLE.
|
||||
* </p>
|
||||
* <p>
|
||||
* Line lengths that aren't multiples of 4 will still essentially end up being multiples of 4 in the encoded data.
|
||||
* </p>
|
||||
* <p>
|
||||
* When decoding all variants are supported.
|
||||
* </p>
|
||||
*
|
||||
* @param lineLength
|
||||
* Each line of encoded data will be at most of the given length (rounded down to nearest multiple of
|
||||
* 4). If lineLength <= 0, then the output will not be divided into lines (chunks). Ignored when
|
||||
* decoding.
|
||||
* @since 1.4
|
||||
*/
|
||||
public Base64(final int lineLength) {
|
||||
this(lineLength, CHUNK_SEPARATOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Base64 codec used for decoding (all modes) and encoding in URL-unsafe mode.
|
||||
* <p>
|
||||
* When encoding the line length and line separator are given in the constructor, and the encoding table is
|
||||
* STANDARD_ENCODE_TABLE.
|
||||
* </p>
|
||||
* <p>
|
||||
* Line lengths that aren't multiples of 4 will still essentially end up being multiples of 4 in the encoded data.
|
||||
* </p>
|
||||
* <p>
|
||||
* When decoding all variants are supported.
|
||||
* </p>
|
||||
*
|
||||
* @param lineLength
|
||||
* Each line of encoded data will be at most of the given length (rounded down to nearest multiple of
|
||||
* 4). If lineLength <= 0, then the output will not be divided into lines (chunks). Ignored when
|
||||
* decoding.
|
||||
* @param lineSeparator
|
||||
* Each line of encoded data will end with this sequence of bytes.
|
||||
* @throws IllegalArgumentException
|
||||
* Thrown when the provided lineSeparator included some base64 characters.
|
||||
* @since 1.4
|
||||
*/
|
||||
public Base64(final int lineLength, final byte[] lineSeparator) {
|
||||
this(lineLength, lineSeparator, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Base64 codec used for decoding (all modes) and encoding in URL-unsafe mode.
|
||||
* <p>
|
||||
* When encoding the line length and line separator are given in the constructor, and the encoding table is
|
||||
* STANDARD_ENCODE_TABLE.
|
||||
* </p>
|
||||
* <p>
|
||||
* Line lengths that aren't multiples of 4 will still essentially end up being multiples of 4 in the encoded data.
|
||||
* </p>
|
||||
* <p>
|
||||
* When decoding all variants are supported.
|
||||
* </p>
|
||||
*
|
||||
* @param lineLength
|
||||
* Each line of encoded data will be at most of the given length (rounded down to nearest multiple of
|
||||
* 4). If lineLength <= 0, then the output will not be divided into lines (chunks). Ignored when
|
||||
* decoding.
|
||||
* @param lineSeparator
|
||||
* Each line of encoded data will end with this sequence of bytes.
|
||||
* @param urlSafe
|
||||
* Instead of emitting '+' and '/' we emit '-' and '_' respectively. urlSafe is only applied to encode
|
||||
* operations. Decoding seamlessly handles both modes.
|
||||
* <b>Note: no padding is added when using the URL-safe alphabet.</b>
|
||||
* @throws IllegalArgumentException
|
||||
* Thrown when the {@code lineSeparator} contains Base64 characters.
|
||||
* @since 1.4
|
||||
*/
|
||||
public Base64(final int lineLength, final byte[] lineSeparator, final boolean urlSafe) {
|
||||
this(lineLength, lineSeparator, urlSafe, CodecPolicy.LENIANT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Base64 codec used for decoding (all modes) and encoding in URL-unsafe mode.
|
||||
* <p>
|
||||
* When encoding the line length and line separator are given in the constructor, and the encoding table is
|
||||
* STANDARD_ENCODE_TABLE.
|
||||
* </p>
|
||||
* <p>
|
||||
* Line lengths that aren't multiples of 4 will still essentially end up being multiples of 4 in the encoded data.
|
||||
* </p>
|
||||
* <p>
|
||||
* When decoding all variants are supported.
|
||||
* </p>
|
||||
*
|
||||
* @param lineLength
|
||||
* Each line of encoded data will be at most of the given length (rounded down to nearest multiple of
|
||||
* 4). If lineLength <= 0, then the output will not be divided into lines (chunks). Ignored when
|
||||
* decoding.
|
||||
* @param lineSeparator
|
||||
* Each line of encoded data will end with this sequence of bytes.
|
||||
* @param urlSafe
|
||||
* Instead of emitting '+' and '/' we emit '-' and '_' respectively. urlSafe is only applied to encode
|
||||
* operations. Decoding seamlessly handles both modes.
|
||||
* <b>Note: no padding is added when using the URL-safe alphabet.</b>
|
||||
* @param decodingPolicy The decoding policy.
|
||||
* @throws IllegalArgumentException
|
||||
* Thrown when the {@code lineSeparator} contains Base64 characters.
|
||||
* @since 1.15
|
||||
*/
|
||||
public Base64(final int lineLength, final byte[] lineSeparator, final boolean urlSafe, final CodecPolicy decodingPolicy) {
|
||||
super(BYTES_PER_UNENCODED_BLOCK, BYTES_PER_ENCODED_BLOCK,
|
||||
lineLength,
|
||||
lineSeparator == null ? 0 : lineSeparator.length,
|
||||
PAD_DEFAULT,
|
||||
decodingPolicy);
|
||||
// TODO could be simplified if there is no requirement to reject invalid line sep when length <=0
|
||||
// @see test case Base64Test.testConstructors()
|
||||
if (lineSeparator != null) {
|
||||
if (containsAlphabetOrPad(lineSeparator)) {
|
||||
final String sep = new String(lineSeparator, Charset.forName("UTF-8"));
|
||||
throw new IllegalArgumentException("lineSeparator must not contain base64 characters: [" + sep + "]");
|
||||
}
|
||||
if (lineLength > 0){ // null line-sep forces no chunking rather than throwing IAE
|
||||
this.encodeSize = BYTES_PER_ENCODED_BLOCK + lineSeparator.length;
|
||||
this.lineSeparator = new byte[lineSeparator.length];
|
||||
System.arraycopy(lineSeparator, 0, this.lineSeparator, 0, lineSeparator.length);
|
||||
} else {
|
||||
this.encodeSize = BYTES_PER_ENCODED_BLOCK;
|
||||
this.lineSeparator = null;
|
||||
}
|
||||
} else {
|
||||
this.encodeSize = BYTES_PER_ENCODED_BLOCK;
|
||||
this.lineSeparator = null;
|
||||
}
|
||||
this.decodeSize = this.encodeSize - 1;
|
||||
this.encodeTable = urlSafe ? URL_SAFE_ENCODE_TABLE : STANDARD_ENCODE_TABLE;
|
||||
}
|
||||
|
||||
// Implementation of the Encoder Interface
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Decodes all of the provided data, starting at inPos, for inAvail bytes. Should be called at least twice: once
|
||||
* with the data to decode, and once with inAvail set to "-1" to alert decoder that EOF has been reached. The "-1"
|
||||
* call is not necessary when decoding, but it doesn't hurt, either.
|
||||
* </p>
|
||||
* <p>
|
||||
* Ignores all non-base64 characters. This is how chunked (e.g. 76 character) data is handled, since CR and LF are
|
||||
* silently ignored, but has implications for other bytes, too. This method subscribes to the garbage-in,
|
||||
* garbage-out philosophy: it will not check the provided data for validity.
|
||||
* </p>
|
||||
* <p>
|
||||
* Thanks to "commons" project in ws.apache.org for the bitwise operations, and general approach.
|
||||
* http://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/
|
||||
* </p>
|
||||
*
|
||||
* @param in
|
||||
* byte[] array of ascii data to base64 decode.
|
||||
* @param inPos
|
||||
* Position to start reading data from.
|
||||
* @param inAvail
|
||||
* Amount of bytes available from input for decoding.
|
||||
* @param context
|
||||
* the context to be used
|
||||
*/
|
||||
@Override
|
||||
void decode(final byte[] in, int inPos, final int inAvail, final Context context) {
|
||||
if (context.eof) {
|
||||
return;
|
||||
}
|
||||
if (inAvail < 0) {
|
||||
context.eof = true;
|
||||
}
|
||||
for (int i = 0; i < inAvail; i++) {
|
||||
final byte[] buffer = ensureBufferSize(decodeSize, context);
|
||||
final byte b = in[inPos++];
|
||||
if (b == pad) {
|
||||
// We're done.
|
||||
context.eof = true;
|
||||
break;
|
||||
}
|
||||
if (b >= 0 && b < DECODE_TABLE.length) {
|
||||
final int result = DECODE_TABLE[b];
|
||||
if (result >= 0) {
|
||||
context.modulus = (context.modulus+1) % BYTES_PER_ENCODED_BLOCK;
|
||||
context.ibitWorkArea = (context.ibitWorkArea << BITS_PER_ENCODED_BYTE) + result;
|
||||
if (context.modulus == 0) {
|
||||
buffer[context.pos++] = (byte) ((context.ibitWorkArea >> 16) & MASK_8BITS);
|
||||
buffer[context.pos++] = (byte) ((context.ibitWorkArea >> 8) & MASK_8BITS);
|
||||
buffer[context.pos++] = (byte) (context.ibitWorkArea & MASK_8BITS);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Two forms of EOF as far as base64 decoder is concerned: actual
|
||||
// EOF (-1) and first time '=' character is encountered in stream.
|
||||
// This approach makes the '=' padding characters completely optional.
|
||||
if (context.eof && context.modulus != 0) {
|
||||
final byte[] buffer = ensureBufferSize(decodeSize, context);
|
||||
|
||||
// We have some spare bits remaining
|
||||
// Output all whole multiples of 8 bits and ignore the rest
|
||||
switch (context.modulus) {
|
||||
// case 0 : // impossible, as excluded above
|
||||
case 1 : // 6 bits - either ignore entirely, or raise an exception
|
||||
validateTrailingCharacter();
|
||||
break;
|
||||
case 2 : // 12 bits = 8 + 4
|
||||
validateCharacter(MASK_4BITS, context);
|
||||
context.ibitWorkArea = context.ibitWorkArea >> 4; // dump the extra 4 bits
|
||||
buffer[context.pos++] = (byte) ((context.ibitWorkArea) & MASK_8BITS);
|
||||
break;
|
||||
case 3 : // 18 bits = 8 + 8 + 2
|
||||
validateCharacter(MASK_2BITS, context);
|
||||
context.ibitWorkArea = context.ibitWorkArea >> 2; // dump 2 bits
|
||||
buffer[context.pos++] = (byte) ((context.ibitWorkArea >> 8) & MASK_8BITS);
|
||||
buffer[context.pos++] = (byte) ((context.ibitWorkArea) & MASK_8BITS);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Impossible modulus " + context.modulus);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Encodes all of the provided data, starting at inPos, for inAvail bytes. Must be called at least twice: once with
|
||||
* the data to encode, and once with inAvail set to "-1" to alert encoder that EOF has been reached, to flush last
|
||||
* remaining bytes (if not multiple of 3).
|
||||
* </p>
|
||||
* <p><b>Note: no padding is added when encoding using the URL-safe alphabet.</b></p>
|
||||
* <p>
|
||||
* Thanks to "commons" project in ws.apache.org for the bitwise operations, and general approach.
|
||||
* http://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/
|
||||
* </p>
|
||||
*
|
||||
* @param in
|
||||
* byte[] array of binary data to base64 encode.
|
||||
* @param inPos
|
||||
* Position to start reading data from.
|
||||
* @param inAvail
|
||||
* Amount of bytes available from input for encoding.
|
||||
* @param context
|
||||
* the context to be used
|
||||
*/
|
||||
@Override
|
||||
void encode(final byte[] in, int inPos, final int inAvail, final Context context) {
|
||||
if (context.eof) {
|
||||
return;
|
||||
}
|
||||
// inAvail < 0 is how we're informed of EOF in the underlying data we're
|
||||
// encoding.
|
||||
if (inAvail < 0) {
|
||||
context.eof = true;
|
||||
if (0 == context.modulus && lineLength == 0) {
|
||||
return; // no leftovers to process and not using chunking
|
||||
}
|
||||
final byte[] buffer = ensureBufferSize(encodeSize, context);
|
||||
final int savedPos = context.pos;
|
||||
switch (context.modulus) { // 0-2
|
||||
case 0 : // nothing to do here
|
||||
break;
|
||||
case 1 : // 8 bits = 6 + 2
|
||||
// top 6 bits:
|
||||
buffer[context.pos++] = encodeTable[(context.ibitWorkArea >> 2) & MASK_6BITS];
|
||||
// remaining 2:
|
||||
buffer[context.pos++] = encodeTable[(context.ibitWorkArea << 4) & MASK_6BITS];
|
||||
// URL-SAFE skips the padding to further reduce size.
|
||||
if (encodeTable == STANDARD_ENCODE_TABLE) {
|
||||
buffer[context.pos++] = pad;
|
||||
buffer[context.pos++] = pad;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2 : // 16 bits = 6 + 6 + 4
|
||||
buffer[context.pos++] = encodeTable[(context.ibitWorkArea >> 10) & MASK_6BITS];
|
||||
buffer[context.pos++] = encodeTable[(context.ibitWorkArea >> 4) & MASK_6BITS];
|
||||
buffer[context.pos++] = encodeTable[(context.ibitWorkArea << 2) & MASK_6BITS];
|
||||
// URL-SAFE skips the padding to further reduce size.
|
||||
if (encodeTable == STANDARD_ENCODE_TABLE) {
|
||||
buffer[context.pos++] = pad;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Impossible modulus " + context.modulus);
|
||||
}
|
||||
context.currentLinePos += context.pos - savedPos; // keep track of current line position
|
||||
// if currentPos == 0 we are at the start of a line, so don't add CRLF
|
||||
if (lineLength > 0 && context.currentLinePos > 0) {
|
||||
System.arraycopy(lineSeparator, 0, buffer, context.pos, lineSeparator.length);
|
||||
context.pos += lineSeparator.length;
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < inAvail; i++) {
|
||||
final byte[] buffer = ensureBufferSize(encodeSize, context);
|
||||
context.modulus = (context.modulus+1) % BYTES_PER_UNENCODED_BLOCK;
|
||||
int b = in[inPos++];
|
||||
if (b < 0) {
|
||||
b += 256;
|
||||
}
|
||||
context.ibitWorkArea = (context.ibitWorkArea << 8) + b; // BITS_PER_BYTE
|
||||
if (0 == context.modulus) { // 3 bytes = 24 bits = 4 * 6 bits to extract
|
||||
buffer[context.pos++] = encodeTable[(context.ibitWorkArea >> 18) & MASK_6BITS];
|
||||
buffer[context.pos++] = encodeTable[(context.ibitWorkArea >> 12) & MASK_6BITS];
|
||||
buffer[context.pos++] = encodeTable[(context.ibitWorkArea >> 6) & MASK_6BITS];
|
||||
buffer[context.pos++] = encodeTable[context.ibitWorkArea & MASK_6BITS];
|
||||
context.currentLinePos += BYTES_PER_ENCODED_BLOCK;
|
||||
if (lineLength > 0 && lineLength <= context.currentLinePos) {
|
||||
System.arraycopy(lineSeparator, 0, buffer, context.pos, lineSeparator.length);
|
||||
context.pos += lineSeparator.length;
|
||||
context.currentLinePos = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not the {@code octet} is in the Base64 alphabet.
|
||||
*
|
||||
* @param octet
|
||||
* The value to test
|
||||
* @return {@code true} if the value is defined in the the Base64 alphabet {@code false} otherwise.
|
||||
*/
|
||||
@Override
|
||||
protected boolean isInAlphabet(final byte octet) {
|
||||
return octet >= 0 && octet < decodeTable.length && decodeTable[octet] != -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns our current encode mode. True if we're URL-SAFE, false otherwise.
|
||||
*
|
||||
* @return true if we're in URL-SAFE mode, false otherwise.
|
||||
* @since 1.4
|
||||
*/
|
||||
public boolean isUrlSafe() {
|
||||
return this.encodeTable == URL_SAFE_ENCODE_TABLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates whether decoding the final trailing character is possible in the context
|
||||
* of the set of possible base 64 values.
|
||||
*
|
||||
* <p>The character is valid if the lower bits within the provided mask are zero. This
|
||||
* is used to test the final trailing base-64 digit is zero in the bits that will be discarded.
|
||||
*
|
||||
* @param emptyBitsMask The mask of the lower bits that should be empty
|
||||
* @param context the context to be used
|
||||
*
|
||||
* @throws IllegalArgumentException if the bits being checked contain any non-zero value
|
||||
*/
|
||||
private void validateCharacter(final int emptyBitsMask, final Context context) {
|
||||
if (isStrictDecoding() && (context.ibitWorkArea & emptyBitsMask) != 0) {
|
||||
throw new IllegalArgumentException(
|
||||
"Strict decoding: Last encoded character (before the paddings if any) is a valid base 64 alphabet but not a possible encoding. " +
|
||||
"Expected the discarded bits from the character to be zero.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates whether decoding allows an entire final trailing character that cannot be
|
||||
* used for a complete byte.
|
||||
*
|
||||
* @throws IllegalArgumentException if strict decoding is enabled
|
||||
*/
|
||||
private void validateTrailingCharacter() {
|
||||
if (isStrictDecoding()) {
|
||||
throw new IllegalArgumentException(
|
||||
"Strict decoding: Last encoded character (before the paddings if any) is a valid base 64 alphabet but not a possible encoding. " +
|
||||
"Decoding requires at least two trailing 6-bit characters to create bytes.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
672
src/main/java/net/lax1dude/eaglercraft/BaseNCodec.java
Normal file
672
src/main/java/net/lax1dude/eaglercraft/BaseNCodec.java
Normal file
@@ -0,0 +1,672 @@
|
||||
package net.lax1dude.eaglercraft;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Arrays;
|
||||
|
||||
public abstract class BaseNCodec {
|
||||
|
||||
static enum CodecPolicy {
|
||||
STRICT,LENIANT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds thread context so classes can be thread-safe.
|
||||
*
|
||||
* This class is not itself thread-safe; each thread must allocate its own copy.
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
static class Context {
|
||||
|
||||
/**
|
||||
* Place holder for the bytes we're dealing with for our based logic.
|
||||
* Bitwise operations store and extract the encoding or decoding from this variable.
|
||||
*/
|
||||
int ibitWorkArea;
|
||||
|
||||
/**
|
||||
* Place holder for the bytes we're dealing with for our based logic.
|
||||
* Bitwise operations store and extract the encoding or decoding from this variable.
|
||||
*/
|
||||
long lbitWorkArea;
|
||||
|
||||
/**
|
||||
* Buffer for streaming.
|
||||
*/
|
||||
byte[] buffer;
|
||||
|
||||
/**
|
||||
* Position where next character should be written in the buffer.
|
||||
*/
|
||||
int pos;
|
||||
|
||||
/**
|
||||
* Position where next character should be read from the buffer.
|
||||
*/
|
||||
int readPos;
|
||||
|
||||
/**
|
||||
* Boolean flag to indicate the EOF has been reached. Once EOF has been reached, this object becomes useless,
|
||||
* and must be thrown away.
|
||||
*/
|
||||
boolean eof;
|
||||
|
||||
/**
|
||||
* Variable tracks how many characters have been written to the current line. Only used when encoding. We use
|
||||
* it to make sure each encoded line never goes beyond lineLength (if lineLength > 0).
|
||||
*/
|
||||
int currentLinePos;
|
||||
|
||||
/**
|
||||
* Writes to the buffer only occur after every 3/5 reads when encoding, and every 4/8 reads when decoding. This
|
||||
* variable helps track that.
|
||||
*/
|
||||
int modulus;
|
||||
|
||||
Context() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a String useful for debugging (especially within a debugger.)
|
||||
*
|
||||
* @return a String useful for debugging.
|
||||
*/
|
||||
@SuppressWarnings("boxing") // OK to ignore boxing here
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%s[buffer=%s, currentLinePos=%s, eof=%s, ibitWorkArea=%s, lbitWorkArea=%s, " +
|
||||
"modulus=%s, pos=%s, readPos=%s]", this.getClass().getSimpleName(), Arrays.toString(buffer),
|
||||
currentLinePos, eof, ibitWorkArea, lbitWorkArea, modulus, pos, readPos);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* EOF
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
static final int EOF = -1;
|
||||
|
||||
/**
|
||||
* MIME chunk size per RFC 2045 section 6.8.
|
||||
*
|
||||
* <p>
|
||||
* The {@value} character limit does not count the trailing CRLF, but counts all other characters, including any
|
||||
* equal signs.
|
||||
* </p>
|
||||
*
|
||||
* @see <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045 section 6.8</a>
|
||||
*/
|
||||
public static final int MIME_CHUNK_SIZE = 76;
|
||||
|
||||
/**
|
||||
* PEM chunk size per RFC 1421 section 4.3.2.4.
|
||||
*
|
||||
* <p>
|
||||
* The {@value} character limit does not count the trailing CRLF, but counts all other characters, including any
|
||||
* equal signs.
|
||||
* </p>
|
||||
*
|
||||
* @see <a href="http://tools.ietf.org/html/rfc1421">RFC 1421 section 4.3.2.4</a>
|
||||
*/
|
||||
public static final int PEM_CHUNK_SIZE = 64;
|
||||
|
||||
private static final int DEFAULT_BUFFER_RESIZE_FACTOR = 2;
|
||||
|
||||
/**
|
||||
* Defines the default buffer size - currently {@value}
|
||||
* - must be large enough for at least one encoded block+separator
|
||||
*/
|
||||
private static final int DEFAULT_BUFFER_SIZE = 8192;
|
||||
|
||||
/**
|
||||
* The maximum size buffer to allocate.
|
||||
*
|
||||
* <p>This is set to the same size used in the JDK {@code java.util.ArrayList}:</p>
|
||||
* <blockquote>
|
||||
* Some VMs reserve some header words in an array.
|
||||
* Attempts to allocate larger arrays may result in
|
||||
* OutOfMemoryError: Requested array size exceeds VM limit.
|
||||
* </blockquote>
|
||||
*/
|
||||
private static final int MAX_BUFFER_SIZE = Integer.MAX_VALUE - 8;
|
||||
|
||||
/** Mask used to extract 8 bits, used in decoding bytes */
|
||||
protected static final int MASK_8BITS = 0xff;
|
||||
|
||||
/**
|
||||
* Byte used to pad output.
|
||||
*/
|
||||
protected static final byte PAD_DEFAULT = '='; // Allow static access to default
|
||||
|
||||
/**
|
||||
* Chunk separator per RFC 2045 section 2.1.
|
||||
*
|
||||
* @see <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045 section 2.1</a>
|
||||
*/
|
||||
static final byte[] CHUNK_SEPARATOR = {'\r', '\n'};
|
||||
|
||||
/**
|
||||
* Compares two {@code int} values numerically treating the values
|
||||
* as unsigned. Taken from JDK 1.8.
|
||||
*
|
||||
* <p>TODO: Replace with JDK 1.8 Integer::compareUnsigned(int, int).</p>
|
||||
*
|
||||
* @param x the first {@code int} to compare
|
||||
* @param y the second {@code int} to compare
|
||||
* @return the value {@code 0} if {@code x == y}; a value less
|
||||
* than {@code 0} if {@code x < y} as unsigned values; and
|
||||
* a value greater than {@code 0} if {@code x > y} as
|
||||
* unsigned values
|
||||
*/
|
||||
private static int compareUnsigned(final int xx, final int yy) {
|
||||
int x = xx + Integer.MIN_VALUE;
|
||||
int y = yy + Integer.MIN_VALUE;
|
||||
return (x < y) ? -1 : ((x == y) ? 0 : 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a positive capacity at least as large the minimum required capacity.
|
||||
* If the minimum capacity is negative then this throws an OutOfMemoryError as no array
|
||||
* can be allocated.
|
||||
*
|
||||
* @param minCapacity the minimum capacity
|
||||
* @return the capacity
|
||||
* @throws OutOfMemoryError if the {@code minCapacity} is negative
|
||||
*/
|
||||
private static int createPositiveCapacity(final int minCapacity) {
|
||||
if (minCapacity < 0) {
|
||||
// overflow
|
||||
throw new OutOfMemoryError("Unable to allocate array size: " + (minCapacity & 0xffffffffL));
|
||||
}
|
||||
// This is called when we require buffer expansion to a very big array.
|
||||
// Use the conservative maximum buffer size if possible, otherwise the biggest required.
|
||||
//
|
||||
// Note: In this situation JDK 1.8 java.util.ArrayList returns Integer.MAX_VALUE.
|
||||
// This excludes some VMs that can exceed MAX_BUFFER_SIZE but not allocate a full
|
||||
// Integer.MAX_VALUE length array.
|
||||
// The result is that we may have to allocate an array of this size more than once if
|
||||
// the capacity must be expanded again.
|
||||
return (minCapacity > MAX_BUFFER_SIZE) ?
|
||||
minCapacity :
|
||||
MAX_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a copy of the chunk separator per RFC 2045 section 2.1.
|
||||
*
|
||||
* @return the chunk separator
|
||||
* @see <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045 section 2.1</a>
|
||||
* @since 1.15
|
||||
*/
|
||||
public static byte[] getChunkSeparator() {
|
||||
return CHUNK_SEPARATOR.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a byte value is whitespace or not.
|
||||
* Whitespace is taken to mean: space, tab, CR, LF
|
||||
* @param byteToCheck
|
||||
* the byte to check
|
||||
* @return true if byte is whitespace, false otherwise
|
||||
*/
|
||||
protected static boolean isWhiteSpace(final byte byteToCheck) {
|
||||
switch (byteToCheck) {
|
||||
case ' ' :
|
||||
case '\n' :
|
||||
case '\r' :
|
||||
case '\t' :
|
||||
return true;
|
||||
default :
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Increases our buffer by the {@link #DEFAULT_BUFFER_RESIZE_FACTOR}.
|
||||
* @param context the context to be used
|
||||
* @param minCapacity the minimum required capacity
|
||||
* @return the resized byte[] buffer
|
||||
* @throws OutOfMemoryError if the {@code minCapacity} is negative
|
||||
*/
|
||||
private static byte[] resizeBuffer(final Context context, final int minCapacity) {
|
||||
// Overflow-conscious code treats the min and new capacity as unsigned.
|
||||
final int oldCapacity = context.buffer.length;
|
||||
int newCapacity = oldCapacity * DEFAULT_BUFFER_RESIZE_FACTOR;
|
||||
if (compareUnsigned(newCapacity, minCapacity) < 0) {
|
||||
newCapacity = minCapacity;
|
||||
}
|
||||
if (compareUnsigned(newCapacity, MAX_BUFFER_SIZE) > 0) {
|
||||
newCapacity = createPositiveCapacity(minCapacity);
|
||||
}
|
||||
|
||||
final byte[] b = new byte[newCapacity];
|
||||
System.arraycopy(context.buffer, 0, b, 0, context.buffer.length);
|
||||
context.buffer = b;
|
||||
return b;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #pad}. Will be removed in 2.0.
|
||||
*/
|
||||
@Deprecated
|
||||
protected final byte PAD = PAD_DEFAULT; // instance variable just in case it needs to vary later
|
||||
|
||||
protected final byte pad; // instance variable just in case it needs to vary later
|
||||
|
||||
/** Number of bytes in each full block of unencoded data, e.g. 4 for Base64 and 5 for Base32 */
|
||||
private final int unencodedBlockSize;
|
||||
|
||||
/** Number of bytes in each full block of encoded data, e.g. 3 for Base64 and 8 for Base32 */
|
||||
private final int encodedBlockSize;
|
||||
|
||||
/**
|
||||
* Chunksize for encoding. Not used when decoding.
|
||||
* A value of zero or less implies no chunking of the encoded data.
|
||||
* Rounded down to nearest multiple of encodedBlockSize.
|
||||
*/
|
||||
protected final int lineLength;
|
||||
|
||||
/**
|
||||
* Size of chunk separator. Not used unless {@link #lineLength} > 0.
|
||||
*/
|
||||
private final int chunkSeparatorLength;
|
||||
|
||||
/**
|
||||
* Defines the decoding behavior when the input bytes contain leftover trailing bits that
|
||||
* cannot be created by a valid encoding. These can be bits that are unused from the final
|
||||
* character or entire characters. The default mode is lenient decoding. Set this to
|
||||
* {@code true} to enable strict decoding.
|
||||
* <ul>
|
||||
* <li>Lenient: Any trailing bits are composed into 8-bit bytes where possible.
|
||||
* The remainder are discarded.
|
||||
* <li>Strict: The decoding will raise an {@link IllegalArgumentException} if trailing bits
|
||||
* are not part of a valid encoding. Any unused bits from the final character must
|
||||
* be zero. Impossible counts of entire final characters are not allowed.
|
||||
* </ul>
|
||||
*
|
||||
* <p>When strict decoding is enabled it is expected that the decoded bytes will be re-encoded
|
||||
* to a byte array that matches the original, i.e. no changes occur on the final
|
||||
* character. This requires that the input bytes use the same padding and alphabet
|
||||
* as the encoder.
|
||||
*/
|
||||
private final CodecPolicy decodingPolicy;
|
||||
|
||||
/**
|
||||
* Note {@code lineLength} is rounded down to the nearest multiple of the encoded block size.
|
||||
* If {@code chunkSeparatorLength} is zero, then chunking is disabled.
|
||||
* @param unencodedBlockSize the size of an unencoded block (e.g. Base64 = 3)
|
||||
* @param encodedBlockSize the size of an encoded block (e.g. Base64 = 4)
|
||||
* @param lineLength if > 0, use chunking with a length {@code lineLength}
|
||||
* @param chunkSeparatorLength the chunk separator length, if relevant
|
||||
*/
|
||||
protected BaseNCodec(final int unencodedBlockSize, final int encodedBlockSize,
|
||||
final int lineLength, final int chunkSeparatorLength) {
|
||||
this(unencodedBlockSize, encodedBlockSize, lineLength, chunkSeparatorLength, PAD_DEFAULT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Note {@code lineLength} is rounded down to the nearest multiple of the encoded block size.
|
||||
* If {@code chunkSeparatorLength} is zero, then chunking is disabled.
|
||||
* @param unencodedBlockSize the size of an unencoded block (e.g. Base64 = 3)
|
||||
* @param encodedBlockSize the size of an encoded block (e.g. Base64 = 4)
|
||||
* @param lineLength if > 0, use chunking with a length {@code lineLength}
|
||||
* @param chunkSeparatorLength the chunk separator length, if relevant
|
||||
* @param pad byte used as padding byte.
|
||||
*/
|
||||
protected BaseNCodec(final int unencodedBlockSize, final int encodedBlockSize,
|
||||
final int lineLength, final int chunkSeparatorLength, final byte pad) {
|
||||
this(unencodedBlockSize, encodedBlockSize, lineLength, chunkSeparatorLength, pad, CodecPolicy.LENIANT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Note {@code lineLength} is rounded down to the nearest multiple of the encoded block size.
|
||||
* If {@code chunkSeparatorLength} is zero, then chunking is disabled.
|
||||
* @param unencodedBlockSize the size of an unencoded block (e.g. Base64 = 3)
|
||||
* @param encodedBlockSize the size of an encoded block (e.g. Base64 = 4)
|
||||
* @param lineLength if > 0, use chunking with a length {@code lineLength}
|
||||
* @param chunkSeparatorLength the chunk separator length, if relevant
|
||||
* @param pad byte used as padding byte.
|
||||
* @param decodingPolicy Decoding policy.
|
||||
* @since 1.15
|
||||
*/
|
||||
protected BaseNCodec(final int unencodedBlockSize, final int encodedBlockSize,
|
||||
final int lineLength, final int chunkSeparatorLength, final byte pad, final CodecPolicy decodingPolicy) {
|
||||
this.unencodedBlockSize = unencodedBlockSize;
|
||||
this.encodedBlockSize = encodedBlockSize;
|
||||
final boolean useChunking = lineLength > 0 && chunkSeparatorLength > 0;
|
||||
this.lineLength = useChunking ? (lineLength / encodedBlockSize) * encodedBlockSize : 0;
|
||||
this.chunkSeparatorLength = chunkSeparatorLength;
|
||||
this.pad = pad;
|
||||
this.decodingPolicy = decodingPolicy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the amount of buffered data available for reading.
|
||||
*
|
||||
* @param context the context to be used
|
||||
* @return The amount of buffered data available for reading.
|
||||
*/
|
||||
int available(final Context context) { // package protected for access from I/O streams
|
||||
return context.buffer != null ? context.pos - context.readPos : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests a given byte array to see if it contains any characters within the alphabet or PAD.
|
||||
*
|
||||
* Intended for use in checking line-ending arrays
|
||||
*
|
||||
* @param arrayOctet
|
||||
* byte array to test
|
||||
* @return {@code true} if any byte is a valid character in the alphabet or PAD; {@code false} otherwise
|
||||
*/
|
||||
protected boolean containsAlphabetOrPad(final byte[] arrayOctet) {
|
||||
if (arrayOctet == null) {
|
||||
return false;
|
||||
}
|
||||
for (final byte element : arrayOctet) {
|
||||
if (pad == element || isInAlphabet(element)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes a byte[] containing characters in the Base-N alphabet.
|
||||
*
|
||||
* @param pArray
|
||||
* A byte array containing Base-N character data
|
||||
* @return a byte array containing binary data
|
||||
*/
|
||||
public byte[] decode(final byte[] pArray) {
|
||||
if (pArray == null || pArray.length == 0) {
|
||||
return pArray;
|
||||
}
|
||||
final Context context = new Context();
|
||||
decode(pArray, 0, pArray.length, context);
|
||||
decode(pArray, 0, EOF, context); // Notify decoder of EOF.
|
||||
final byte[] result = new byte[context.pos];
|
||||
readResults(result, 0, result.length, context);
|
||||
return result;
|
||||
}
|
||||
|
||||
// package protected for access from I/O streams
|
||||
abstract void decode(byte[] pArray, int i, int length, Context context);
|
||||
|
||||
/**
|
||||
* Decodes an Object using the Base-N algorithm. This method is provided in order to satisfy the requirements of
|
||||
* the Decoder interface, and will throw a DecoderException if the supplied object is not of type byte[] or String.
|
||||
*
|
||||
* @param obj
|
||||
* Object to decode
|
||||
* @return An object (of type byte[]) containing the binary data which corresponds to the byte[] or String
|
||||
* supplied.
|
||||
* @throws DecoderException
|
||||
* if the parameter supplied is not of type byte[]
|
||||
*/
|
||||
public Object decode(final Object obj) {
|
||||
if (obj instanceof byte[]) {
|
||||
return decode((byte[]) obj);
|
||||
} else if (obj instanceof String) {
|
||||
return decode((String) obj);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes a String containing characters in the Base-N alphabet.
|
||||
*
|
||||
* @param pArray
|
||||
* A String containing Base-N character data
|
||||
* @return a byte array containing binary data
|
||||
*/
|
||||
public byte[] decode(final String pArray) {
|
||||
return decode(pArray.getBytes(Charset.forName("UTF-8")));
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes a byte[] containing binary data, into a byte[] containing characters in the alphabet.
|
||||
*
|
||||
* @param pArray
|
||||
* a byte array containing binary data
|
||||
* @return A byte array containing only the base N alphabetic character data
|
||||
*/
|
||||
public byte[] encode(final byte[] pArray) {
|
||||
if (pArray == null || pArray.length == 0) {
|
||||
return pArray;
|
||||
}
|
||||
return encode(pArray, 0, pArray.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes a byte[] containing binary data, into a byte[] containing
|
||||
* characters in the alphabet.
|
||||
*
|
||||
* @param pArray
|
||||
* a byte array containing binary data
|
||||
* @param offset
|
||||
* initial offset of the subarray.
|
||||
* @param length
|
||||
* length of the subarray.
|
||||
* @return A byte array containing only the base N alphabetic character data
|
||||
* @since 1.11
|
||||
*/
|
||||
public byte[] encode(final byte[] pArray, final int offset, final int length) {
|
||||
if (pArray == null || pArray.length == 0) {
|
||||
return pArray;
|
||||
}
|
||||
final Context context = new Context();
|
||||
encode(pArray, offset, length, context);
|
||||
encode(pArray, offset, EOF, context); // Notify encoder of EOF.
|
||||
final byte[] buf = new byte[context.pos - context.readPos];
|
||||
readResults(buf, 0, buf.length, context);
|
||||
return buf;
|
||||
}
|
||||
|
||||
// package protected for access from I/O streams
|
||||
abstract void encode(byte[] pArray, int i, int length, Context context);
|
||||
|
||||
/**
|
||||
* Encodes an Object using the Base-N algorithm. This method is provided in order to satisfy the requirements of
|
||||
* the Encoder interface, and will throw an EncoderException if the supplied object is not of type byte[].
|
||||
*
|
||||
* @param obj
|
||||
* Object to encode
|
||||
* @return An object (of type byte[]) containing the Base-N encoded data which corresponds to the byte[] supplied.
|
||||
* @throws EncoderException
|
||||
* if the parameter supplied is not of type byte[]
|
||||
*/
|
||||
public Object encode(final Object obj) {
|
||||
return encode((byte[]) obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes a byte[] containing binary data, into a String containing characters in the appropriate alphabet.
|
||||
* Uses UTF8 encoding.
|
||||
*
|
||||
* @param pArray a byte array containing binary data
|
||||
* @return String containing only character data in the appropriate alphabet.
|
||||
* @since 1.5
|
||||
* This is a duplicate of {@link #encodeToString(byte[])}; it was merged during refactoring.
|
||||
*/
|
||||
public String encodeAsString(final byte[] pArray){
|
||||
return new String(encode(pArray), Charset.forName("UTF-8"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes a byte[] containing binary data, into a String containing characters in the Base-N alphabet.
|
||||
* Uses UTF8 encoding.
|
||||
*
|
||||
* @param pArray
|
||||
* a byte array containing binary data
|
||||
* @return A String containing only Base-N character data
|
||||
*/
|
||||
public String encodeToString(final byte[] pArray) {
|
||||
return new String(encode(pArray), Charset.forName("UTF-8"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that the buffer has room for {@code size} bytes
|
||||
*
|
||||
* @param size minimum spare space required
|
||||
* @param context the context to be used
|
||||
* @return the buffer
|
||||
*/
|
||||
protected byte[] ensureBufferSize(final int size, final Context context){
|
||||
if (context.buffer == null) {
|
||||
context.buffer = new byte[Math.max(size, getDefaultBufferSize())];
|
||||
context.pos = 0;
|
||||
context.readPos = 0;
|
||||
|
||||
// Overflow-conscious:
|
||||
// x + y > z == x + y - z > 0
|
||||
} else if (context.pos + size - context.buffer.length > 0) {
|
||||
return resizeBuffer(context, context.pos + size);
|
||||
}
|
||||
return context.buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the decoding behavior policy.
|
||||
*
|
||||
* <p>
|
||||
* The default is lenient. If the decoding policy is strict, then decoding will raise an
|
||||
* {@link IllegalArgumentException} if trailing bits are not part of a valid encoding. Decoding will compose
|
||||
* trailing bits into 8-bit bytes and discard the remainder.
|
||||
* </p>
|
||||
*
|
||||
* @return true if using strict decoding
|
||||
* @since 1.15
|
||||
*/
|
||||
public CodecPolicy getCodecPolicy() {
|
||||
return decodingPolicy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default buffer size. Can be overridden.
|
||||
*
|
||||
* @return the default buffer size.
|
||||
*/
|
||||
protected int getDefaultBufferSize() {
|
||||
return DEFAULT_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the amount of space needed to encode the supplied array.
|
||||
*
|
||||
* @param pArray byte[] array which will later be encoded
|
||||
*
|
||||
* @return amount of space needed to encoded the supplied array.
|
||||
* Returns a long since a max-len array will require > Integer.MAX_VALUE
|
||||
*/
|
||||
public long getEncodedLength(final byte[] pArray) {
|
||||
// Calculate non-chunked size - rounded up to allow for padding
|
||||
// cast to long is needed to avoid possibility of overflow
|
||||
long len = ((pArray.length + unencodedBlockSize-1) / unencodedBlockSize) * (long) encodedBlockSize;
|
||||
if (lineLength > 0) { // We're using chunking
|
||||
// Round up to nearest multiple
|
||||
len += ((len + lineLength-1) / lineLength) * chunkSeparatorLength;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this object has buffered data for reading.
|
||||
*
|
||||
* @param context the context to be used
|
||||
* @return true if there is data still available for reading.
|
||||
*/
|
||||
boolean hasData(final Context context) { // package protected for access from I/O streams
|
||||
return context.buffer != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not the {@code octet} is in the current alphabet.
|
||||
* Does not allow whitespace or pad.
|
||||
*
|
||||
* @param value The value to test
|
||||
*
|
||||
* @return {@code true} if the value is defined in the current alphabet, {@code false} otherwise.
|
||||
*/
|
||||
protected abstract boolean isInAlphabet(byte value);
|
||||
|
||||
/**
|
||||
* Tests a given byte array to see if it contains only valid characters within the alphabet.
|
||||
* The method optionally treats whitespace and pad as valid.
|
||||
*
|
||||
* @param arrayOctet byte array to test
|
||||
* @param allowWSPad if {@code true}, then whitespace and PAD are also allowed
|
||||
*
|
||||
* @return {@code true} if all bytes are valid characters in the alphabet or if the byte array is empty;
|
||||
* {@code false}, otherwise
|
||||
*/
|
||||
public boolean isInAlphabet(final byte[] arrayOctet, final boolean allowWSPad) {
|
||||
for (final byte octet : arrayOctet) {
|
||||
if (!isInAlphabet(octet) &&
|
||||
(!allowWSPad || (octet != pad) && !isWhiteSpace(octet))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests a given String to see if it contains only valid characters within the alphabet.
|
||||
* The method treats whitespace and PAD as valid.
|
||||
*
|
||||
* @param basen String to test
|
||||
* @return {@code true} if all characters in the String are valid characters in the alphabet or if
|
||||
* the String is empty; {@code false}, otherwise
|
||||
* @see #isInAlphabet(byte[], boolean)
|
||||
*/
|
||||
public boolean isInAlphabet(final String basen) {
|
||||
return isInAlphabet(basen.getBytes(Charset.forName("UTF-8")), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if decoding behavior is strict. Decoding will raise an {@link IllegalArgumentException} if trailing
|
||||
* bits are not part of a valid encoding.
|
||||
*
|
||||
* <p>
|
||||
* The default is false for lenient decoding. Decoding will compose trailing bits into 8-bit bytes and discard the
|
||||
* remainder.
|
||||
* </p>
|
||||
*
|
||||
* @return true if using strict decoding
|
||||
* @since 1.15
|
||||
*/
|
||||
public boolean isStrictDecoding() {
|
||||
return decodingPolicy == CodecPolicy.STRICT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts buffered data into the provided byte[] array, starting at position bPos, up to a maximum of bAvail
|
||||
* bytes. Returns how many bytes were actually extracted.
|
||||
* <p>
|
||||
* Package protected for access from I/O streams.
|
||||
*
|
||||
* @param b
|
||||
* byte[] array to extract the buffered data into.
|
||||
* @param bPos
|
||||
* position in byte[] array to start extraction at.
|
||||
* @param bAvail
|
||||
* amount of bytes we're allowed to extract. We may extract fewer (if fewer are available).
|
||||
* @param context
|
||||
* the context to be used
|
||||
* @return The number of bytes successfully extracted into the provided byte[] array.
|
||||
*/
|
||||
int readResults(final byte[] b, final int bPos, final int bAvail, final Context context) {
|
||||
if (context.buffer != null) {
|
||||
final int len = Math.min(available(context), bAvail);
|
||||
System.arraycopy(context.buffer, context.readPos, b, bPos, len);
|
||||
context.readPos += len;
|
||||
if (context.readPos >= context.pos) {
|
||||
context.buffer = null; // so hasData() will return false, and this method can return -1
|
||||
}
|
||||
return len;
|
||||
}
|
||||
return context.eof ? EOF : 0;
|
||||
}
|
||||
}
|
||||
30
src/main/java/net/lax1dude/eaglercraft/ConfigConstants.java
Normal file
30
src/main/java/net/lax1dude/eaglercraft/ConfigConstants.java
Normal file
@@ -0,0 +1,30 @@
|
||||
package net.lax1dude.eaglercraft;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ConfigConstants {
|
||||
|
||||
public static boolean profanity = false;
|
||||
|
||||
public static final String version = "1.5.2-sp2.01";
|
||||
public static final String mainMenuString = "eaglercraft " + version;
|
||||
|
||||
public static final String forkMe = null;
|
||||
|
||||
public static String ayonullTitle = null;
|
||||
public static String ayonullLink = null;
|
||||
|
||||
public static String mainMenuItemLine0 = null;
|
||||
public static String mainMenuItemLine1 = null;
|
||||
public static String mainMenuItemLine2 = null;
|
||||
public static String mainMenuItemLink = null;
|
||||
|
||||
public static List<String> splashTexts = null;
|
||||
|
||||
public static List<RelayEntry> relays = null;
|
||||
|
||||
public static boolean eaglercraftTitleLogo = false;
|
||||
|
||||
public static boolean panoramaBlur = true;
|
||||
|
||||
}
|
||||
81
src/main/java/net/lax1dude/eaglercraft/DebugIconImpl.java
Normal file
81
src/main/java/net/lax1dude/eaglercraft/DebugIconImpl.java
Normal file
@@ -0,0 +1,81 @@
|
||||
package net.lax1dude.eaglercraft;
|
||||
|
||||
import net.minecraft.src.Icon;
|
||||
|
||||
public class DebugIconImpl implements Icon {
|
||||
|
||||
private final int sheetW;
|
||||
private final int sheetH;
|
||||
|
||||
public DebugIconImpl() {
|
||||
this(1024, 1024);
|
||||
}
|
||||
|
||||
public DebugIconImpl(int sheetW, int sheetH) {
|
||||
this.sheetW = sheetW;
|
||||
this.sheetH = sheetH;
|
||||
}
|
||||
|
||||
public int getOriginX() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int getOriginY() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIconWidth() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIconHeight() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getMinU() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getMaxU() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getInterpolatedU(double var1) {
|
||||
return (float)var1 / 16.0f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getMinV() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getMaxV() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getInterpolatedV(double var1) {
|
||||
return (float)var1 / 16.0f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIconName() {
|
||||
return "debug_icon";
|
||||
}
|
||||
|
||||
public int getSheetWidth() {
|
||||
return sheetW;
|
||||
}
|
||||
|
||||
public int getSheetHeight() {
|
||||
return sheetH;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
729
src/main/java/net/lax1dude/eaglercraft/DefaultSkinRenderer.java
Normal file
729
src/main/java/net/lax1dude/eaglercraft/DefaultSkinRenderer.java
Normal file
@@ -0,0 +1,729 @@
|
||||
package net.lax1dude.eaglercraft;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import net.lax1dude.eaglercraft.EaglerProfile.EaglerProfileCape;
|
||||
import net.minecraft.src.Minecraft;
|
||||
import net.minecraft.src.EntityClientPlayerMP;
|
||||
import net.minecraft.src.EntityOtherPlayerMP;
|
||||
import net.minecraft.src.EntityPlayer;
|
||||
import net.minecraft.src.ModelBiped;
|
||||
import net.minecraft.src.ModelBlaze;
|
||||
import net.minecraft.src.ModelEnderman;
|
||||
import net.minecraft.src.ModelSkeleton;
|
||||
import net.minecraft.src.ModelVillager;
|
||||
import net.minecraft.src.ModelZombie;
|
||||
import net.minecraft.src.OpenGlHelper;
|
||||
import net.minecraft.src.Packet250CustomPayload;
|
||||
import net.minecraft.src.RenderEnderman;
|
||||
import net.minecraft.src.RenderHelper;
|
||||
|
||||
public class DefaultSkinRenderer {
|
||||
|
||||
public static final TextureLocation[] defaultVanillaSkins = new TextureLocation[] {
|
||||
new TextureLocation("/skins/01.default_steve.png"),
|
||||
new TextureLocation("/skins/02.default_alex.png"),
|
||||
new TextureLocation("/skins/03.tennis_steve.png"),
|
||||
new TextureLocation("/skins/04.tennis_alex.png"),
|
||||
new TextureLocation("/skins/05.tuxedo_steve.png"),
|
||||
new TextureLocation("/skins/06.tuxedo_alex.png"),
|
||||
new TextureLocation("/skins/07.athlete_steve.png"),
|
||||
new TextureLocation("/skins/08.athlete_alex.png"),
|
||||
new TextureLocation("/skins/09.cyclist_steve.png"),
|
||||
new TextureLocation("/skins/10.cyclist_alex.png"),
|
||||
new TextureLocation("/skins/11.boxer_steve.png"),
|
||||
new TextureLocation("/skins/12.boxer_alex.png"),
|
||||
new TextureLocation("/skins/13.prisoner_steve.png"),
|
||||
new TextureLocation("/skins/14.prisoner_alex.png"),
|
||||
new TextureLocation("/skins/15.scottish_steve.png"),
|
||||
new TextureLocation("/skins/16.scottish_alex.png"),
|
||||
new TextureLocation("/skins/17.dev_steve.png"),
|
||||
new TextureLocation("/skins/18.dev_alex.png"),
|
||||
new TextureLocation("/skins/19.herobrine.png"),
|
||||
new TextureLocation("/mob/enderman.png"),
|
||||
new TextureLocation("/mob/skeleton.png"),
|
||||
new TextureLocation("/mob/fire.png"),
|
||||
new TextureLocation("/skins/20.barney.png"),
|
||||
new TextureLocation("/skins/21.slime.png"),
|
||||
new TextureLocation("/skins/22.noob.png"),
|
||||
new TextureLocation("/skins/23.trump.png"),
|
||||
new TextureLocation("/skins/24.notch.png"),
|
||||
new TextureLocation("/skins/25.creeper.png"),
|
||||
new TextureLocation("/skins/26.zombie.png"),
|
||||
new TextureLocation("/skins/27.pig.png"),
|
||||
new TextureLocation("/skins/28.squid.png"),
|
||||
new TextureLocation("/skins/29.mooshroom.png"),
|
||||
new TextureLocation("/mob/villager/villager.png"),
|
||||
null, null, null, null, null
|
||||
};
|
||||
|
||||
public static final TextureLocation[] defaultVanillaCapes = new TextureLocation[] {
|
||||
null,
|
||||
new TextureLocation("/skins/c01.minecon_2011.png"),
|
||||
new TextureLocation("/skins/c02.minecon_2012.png"),
|
||||
new TextureLocation("/skins/c03.minecon_2013.png"),
|
||||
new TextureLocation("/skins/c04.minecon_2015.png"),
|
||||
new TextureLocation("/skins/c05.minecon_2016.png"),
|
||||
new TextureLocation("/skins/c06.microsoft_account.png"),
|
||||
new TextureLocation("/skins/c07.mapmaker.png"),
|
||||
new TextureLocation("/skins/c08.mojang_old.png"),
|
||||
new TextureLocation("/skins/c09.mojang_new.png"),
|
||||
new TextureLocation("/skins/c10.jira_mod.png"),
|
||||
new TextureLocation("/skins/c11.mojang_very_old.png"),
|
||||
new TextureLocation("/skins/c12.scrolls.png"),
|
||||
new TextureLocation("/skins/c13.cobalt.png"),
|
||||
new TextureLocation("/skins/c14.translator.png"),
|
||||
new TextureLocation("/skins/c15.millionth_account.png"),
|
||||
new TextureLocation("/skins/c16.prismarine.png"),
|
||||
new TextureLocation("/skins/c17.snowman.png"),
|
||||
new TextureLocation("/skins/c18.spade.png"),
|
||||
new TextureLocation("/skins/c19.birthday.png"),
|
||||
new TextureLocation("/skins/c20.db.png")
|
||||
};
|
||||
|
||||
public static final HighPolySkin[] defaultHighPoly = new HighPolySkin[] {
|
||||
null, null, null, null, null, null, null, null, null, null,
|
||||
null, null, null, null, null, null, null, null, null, null,
|
||||
null, null, null, null, null, null, null, null, null, null,
|
||||
null, null, null,
|
||||
HighPolySkin.LONG_ARMS, HighPolySkin.WEIRD_CLIMBER_DUDE, HighPolySkin.LAXATIVE_DUDE,
|
||||
HighPolySkin.BABY_CHARLES, HighPolySkin.BABY_WINSTON
|
||||
};
|
||||
|
||||
public static final boolean[] defaultVanillaSkinClassicOrSlimVariants = new boolean[] {
|
||||
false, true,
|
||||
false, true,
|
||||
false, true,
|
||||
false, true,
|
||||
false, true,
|
||||
false, true,
|
||||
false, true,
|
||||
false, true,
|
||||
false, true
|
||||
};
|
||||
|
||||
private static final HashMap<Integer,EntityOtherPlayerMP> skinCookies = new HashMap<>();
|
||||
private static final HashMap<EntityOtherPlayerMP,Integer> skinGLUnits = new HashMap<>();
|
||||
private static final HashMap<EntityOtherPlayerMP,Integer> capeGLUnits = new HashMap<>();
|
||||
private static final HashMap<EntityOtherPlayerMP,Long> skinGLTimeout = new HashMap<>();
|
||||
|
||||
private static long lastClean = 0l;
|
||||
|
||||
public static void deleteOldSkins() {
|
||||
long now = EaglerAdapter.steadyTimeMillis();
|
||||
if(now - lastClean > 60000l) {
|
||||
lastClean = now;
|
||||
Iterator<Entry<EntityOtherPlayerMP,Long>> itr = skinGLTimeout.entrySet().iterator();
|
||||
while(itr.hasNext()) {
|
||||
Entry<EntityOtherPlayerMP,Long> ee = itr.next();
|
||||
if(now - ee.getValue() > 80000l) {
|
||||
itr.remove();
|
||||
if(skinGLUnits.containsKey(ee.getKey())) {
|
||||
Minecraft.getMinecraft().renderEngine.deleteTexture(skinGLUnits.remove(ee.getKey()));
|
||||
}
|
||||
if(capeGLUnits.containsKey(ee.getKey())) {
|
||||
Minecraft.getMinecraft().renderEngine.deleteTexture(capeGLUnits.remove(ee.getKey()));
|
||||
}
|
||||
}
|
||||
}
|
||||
Iterator<Entry<Integer, EntityOtherPlayerMP>> itr2 = skinCookies.entrySet().iterator();
|
||||
while(itr2.hasNext()) {
|
||||
Entry<Integer, EntityOtherPlayerMP> e = itr2.next();
|
||||
if(e.getValue().isDead) {
|
||||
itr2.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean bindSyncedSkin(EntityPlayer p) {
|
||||
if(p instanceof EntityClientPlayerMP) {
|
||||
return false;
|
||||
}else if(p instanceof EntityOtherPlayerMP) {
|
||||
EntityOtherPlayerMP pp = (EntityOtherPlayerMP) p;
|
||||
if(pp.skinPacket != null) {
|
||||
int type = ((int)pp.skinPacket[0] & 0xFF);
|
||||
if(type != 4 && type >= 0 && type < EaglerProfile.SKIN_DATA_SIZE.length) {
|
||||
if(!skinGLUnits.containsKey(pp)) {
|
||||
byte[] skinToLoad = new byte[EaglerProfile.SKIN_DATA_SIZE[type]];
|
||||
System.arraycopy(pp.skinPacket, 1, skinToLoad, 0, skinToLoad.length);
|
||||
int w, h;
|
||||
|
||||
switch((int)pp.skinPacket[0] & 0xFF) {
|
||||
default:
|
||||
case 0:
|
||||
w = 64;
|
||||
h = 32;
|
||||
break;
|
||||
case 1:
|
||||
case 5:
|
||||
w = 64;
|
||||
h = 64;
|
||||
break;
|
||||
}
|
||||
|
||||
if(skinToLoad.length / 4 == w * h) {
|
||||
skinGLUnits.put(pp, Minecraft.getMinecraft().renderEngine.setupTextureRaw(skinToLoad, w, h));
|
||||
}
|
||||
}
|
||||
skinGLTimeout.put(pp, EaglerAdapter.steadyTimeMillis());
|
||||
Integer i = skinGLUnits.get(pp);
|
||||
if(i != null && i.intValue() > 0) {
|
||||
Minecraft.getMinecraft().renderEngine.bindTexture(i.intValue());
|
||||
}else {
|
||||
defaultVanillaSkins[0].bindTexture();
|
||||
}
|
||||
}else {
|
||||
int type2 = (int)pp.skinPacket[1] & 0xFF;
|
||||
if(type2 < defaultVanillaSkins.length) {
|
||||
TextureLocation loc = defaultVanillaSkins[type2];
|
||||
if(loc != null) {
|
||||
loc.bindTexture();
|
||||
}else {
|
||||
if(defaultHighPoly[type2] != null) {
|
||||
defaultHighPoly[type2].fallbackTexture.bindTexture();
|
||||
return true;
|
||||
}else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}else {
|
||||
requestSkin(pp);
|
||||
}
|
||||
return false;
|
||||
}else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean bindSyncedCape(EntityPlayer p) {
|
||||
EaglerAdapter.glMatrixMode(EaglerAdapter.GL_TEXTURE);
|
||||
EaglerAdapter.glPushMatrix();
|
||||
EaglerAdapter.glMatrixMode(EaglerAdapter.GL_MODELVIEW);
|
||||
if(p instanceof EntityClientPlayerMP) {
|
||||
if(EaglerProfile.presetCapeId < 0) {
|
||||
EaglerProfileCape cp = EaglerProfile.capes.get(EaglerProfile.customCapeId);
|
||||
if(cp != null) {
|
||||
Minecraft.getMinecraft().renderEngine.bindTexture(cp.glTex);
|
||||
EaglerAdapter.glMatrixMode(EaglerAdapter.GL_TEXTURE);
|
||||
EaglerAdapter.glScalef(2.0f, 1.0f, 1.0f);
|
||||
EaglerAdapter.glMatrixMode(EaglerAdapter.GL_MODELVIEW);
|
||||
return true;
|
||||
}else {
|
||||
return false;
|
||||
}
|
||||
}else {
|
||||
if(EaglerProfile.presetCapeId < defaultVanillaCapes.length) {
|
||||
TextureLocation loc = defaultVanillaCapes[EaglerProfile.presetCapeId];
|
||||
if(loc == null) {
|
||||
return false;
|
||||
}else {
|
||||
loc.bindTexture();
|
||||
return true;
|
||||
}
|
||||
}else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}else if(p instanceof EntityOtherPlayerMP) {
|
||||
EntityOtherPlayerMP pp = (EntityOtherPlayerMP) p;
|
||||
if(pp.skinPacket != null) {
|
||||
int tp = ((int)pp.skinPacket[0] & 0xFF);
|
||||
if(tp >= 0 && tp < EaglerProfile.SKIN_DATA_SIZE.length) {
|
||||
int offset = 1 + EaglerProfile.SKIN_DATA_SIZE[tp];
|
||||
if(pp.skinPacket.length > offset + 1) {
|
||||
int capeType = (int)pp.skinPacket[offset] & 0xFF;
|
||||
if(capeType >= 0 && capeType < EaglerProfile.CAPE_DATA_SIZE.length) {
|
||||
int len = EaglerProfile.CAPE_DATA_SIZE[capeType];
|
||||
if(pp.skinPacket.length > offset + len + 1) {
|
||||
if(capeType != 2) {
|
||||
if(!capeGLUnits.containsKey(pp)) {
|
||||
byte[] dataToLoad = new byte[len];
|
||||
System.arraycopy(pp.skinPacket, offset + 2, dataToLoad, 0, len);
|
||||
int w, h;
|
||||
switch(capeType) {
|
||||
case 0:
|
||||
default:
|
||||
w = 32;
|
||||
h = 32;
|
||||
break;
|
||||
}
|
||||
|
||||
if(dataToLoad.length / 4 == w * h) {
|
||||
capeGLUnits.put(pp, Minecraft.getMinecraft().renderEngine.setupTextureRaw(dataToLoad, w, h));
|
||||
}
|
||||
}
|
||||
skinGLTimeout.put(pp, EaglerAdapter.steadyTimeMillis());
|
||||
Integer i = capeGLUnits.get(pp);
|
||||
if(i != null && i.intValue() > 0) {
|
||||
EaglerAdapter.glMatrixMode(EaglerAdapter.GL_TEXTURE);
|
||||
EaglerAdapter.glScalef(2.0f, 1.0f, 1.0f);
|
||||
EaglerAdapter.glMatrixMode(EaglerAdapter.GL_MODELVIEW);
|
||||
Minecraft.getMinecraft().renderEngine.bindTexture(i.intValue());
|
||||
return true;
|
||||
}else {
|
||||
return false;
|
||||
}
|
||||
}else {
|
||||
int preset = (int)pp.skinPacket[offset + 2] & 0xFF;
|
||||
if(preset < defaultVanillaCapes.length) {
|
||||
TextureLocation loc = defaultVanillaCapes[preset];
|
||||
if(loc == null) {
|
||||
return false;
|
||||
}else {
|
||||
loc.bindTexture();
|
||||
return true;
|
||||
}
|
||||
}else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}else {
|
||||
requestSkin(pp);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static int getSkinLayerByte(EntityPlayer p) {
|
||||
if(p instanceof EntityClientPlayerMP) {
|
||||
return Minecraft.getMinecraft().gameSettings.getSkinLayers();
|
||||
}else if(p instanceof EntityOtherPlayerMP) {
|
||||
EntityOtherPlayerMP pp = (EntityOtherPlayerMP) p;
|
||||
if(pp.skinPacket != null) {
|
||||
int tp = ((int)pp.skinPacket[0] & 0xFF);
|
||||
if(tp >= 0 && tp < EaglerProfile.SKIN_DATA_SIZE.length) {
|
||||
int offset = 1 + EaglerProfile.SKIN_DATA_SIZE[tp];
|
||||
if(pp.skinPacket.length > offset + 1) {
|
||||
return (int)pp.skinPacket[offset + 1] & 0xFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
public static void updateSkinLayerByte(int skinFlags, byte[] pkt) {
|
||||
if(pkt.length > 0) {
|
||||
int tp = ((int)pkt[0] & 0xFF);
|
||||
if(tp >= 0 && tp < EaglerProfile.SKIN_DATA_SIZE.length) {
|
||||
int offset = 1 + EaglerProfile.SKIN_DATA_SIZE[tp];
|
||||
if(pkt.length > offset + 1) {
|
||||
pkt[offset + 1] = (byte)skinFlags;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void requestSkin(EntityOtherPlayerMP pp) {
|
||||
if(!skinCookies.containsValue(pp)) {
|
||||
int cookie = (int)(System.nanoTime() % 65536);
|
||||
skinCookies.put(cookie, pp);
|
||||
byte[] n = pp.username.getBytes();
|
||||
byte[] pkt = new byte[n.length + 2];
|
||||
System.arraycopy(n, 0, pkt, 2, n.length);
|
||||
pkt[0] = (byte)(cookie & 0xFF);
|
||||
pkt[1] = (byte)((cookie >> 8) & 0xFF);
|
||||
Minecraft.getMinecraft().getNetHandler().addToSendQueue(new Packet250CustomPayload("EAG|FetchSkin", pkt));
|
||||
}
|
||||
}
|
||||
|
||||
public static void skinResponse(byte[] data) {
|
||||
int cookie = ((int)data[0] & 0xFF) | (((int)data[1] & 0xFF) << 8);
|
||||
if(skinCookies.containsKey(cookie) && (data.length > 3)) {
|
||||
EntityOtherPlayerMP p = skinCookies.remove(cookie);
|
||||
byte[] packet = new byte[data.length - 2];
|
||||
System.arraycopy(data, 2, packet, 0, packet.length);
|
||||
p.skinPacket = packet;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isNewSkin(int id) {
|
||||
return !(id == 0 || id == 2 || id == 4 || id == 6 || id == 8 || id == 10 || id == 12 || id == 14 || id == 18 || id == 28) && !isHighPoly(id);
|
||||
}
|
||||
|
||||
public static boolean isAlexSkin(int id) {
|
||||
return id < defaultVanillaSkinClassicOrSlimVariants.length && defaultVanillaSkinClassicOrSlimVariants[id];
|
||||
}
|
||||
|
||||
public static boolean isStandardModel(int id) {
|
||||
return !isZombieModel(id) && !(id == 19 || id == 20 || id == 21 || id == 32 || id == 33 || id == 34) && !isHighPoly(id);
|
||||
}
|
||||
|
||||
public static boolean isZombieModel(int id) {
|
||||
return id == 18 || id == 28;
|
||||
}
|
||||
|
||||
public static boolean isHighPoly(int id) {
|
||||
return !(defaultVanillaSkins.length > id && id >= 0) ? false : defaultHighPoly[id] != null;
|
||||
}
|
||||
|
||||
public static boolean isPlayerNewSkin(EntityPlayer p) {
|
||||
if(p instanceof EntityClientPlayerMP) {
|
||||
if(EaglerProfile.presetSkinId <= -1) {
|
||||
int type = EaglerProfile.getSkinSize(EaglerProfile.skins.get(EaglerProfile.customSkinId).data.length);
|
||||
return (type == 1 || type == 3);
|
||||
}else {
|
||||
return isNewSkin(EaglerProfile.presetSkinId);
|
||||
}
|
||||
}else if(p instanceof EntityOtherPlayerMP) {
|
||||
EntityOtherPlayerMP pp = (EntityOtherPlayerMP) p;
|
||||
if(pp.skinPacket != null) {
|
||||
if(pp.skinPacket[0] != (byte)4) {
|
||||
return (pp.skinPacket[0] == (byte)1) || (pp.skinPacket[0] == (byte)3) || (pp.skinPacket[0] == (byte)5) || (pp.skinPacket[0] == (byte)6);
|
||||
}else {
|
||||
return isNewSkin((int)pp.skinPacket[1] & 0xFF);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isPlayerNewSkinSlim(EntityPlayer p) {
|
||||
if(p instanceof EntityClientPlayerMP) {
|
||||
if(EaglerProfile.presetSkinId == -1) {
|
||||
return EaglerProfile.skins.get(EaglerProfile.customSkinId).slim;
|
||||
}else {
|
||||
return isAlexSkin(EaglerProfile.presetSkinId);
|
||||
}
|
||||
}else if(p instanceof EntityOtherPlayerMP) {
|
||||
EntityOtherPlayerMP pp = (EntityOtherPlayerMP) p;
|
||||
if(pp.skinPacket != null) {
|
||||
if(pp.skinPacket[0] != (byte)4) {
|
||||
return (pp.skinPacket[0] == (byte)5) || (pp.skinPacket[0] == (byte)6);
|
||||
}else {
|
||||
return isAlexSkin((int)pp.skinPacket[1] & 0xFF);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isPlayerHighPoly(EntityPlayer p) {
|
||||
if(p instanceof EntityClientPlayerMP) {
|
||||
if(EaglerProfile.presetSkinId == -1) {
|
||||
return false;
|
||||
}else {
|
||||
return isHighPoly(EaglerProfile.presetSkinId);
|
||||
}
|
||||
}else if(p instanceof EntityOtherPlayerMP) {
|
||||
EntityOtherPlayerMP pp = (EntityOtherPlayerMP) p;
|
||||
if(pp.skinPacket != null) {
|
||||
if(pp.skinPacket[0] != (byte)4) {
|
||||
return false;
|
||||
}else {
|
||||
return isHighPoly((int)pp.skinPacket[1] & 0xFF);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isPlayerStandard(EntityPlayer p) {
|
||||
if(p instanceof EntityClientPlayerMP) {
|
||||
if(EaglerProfile.presetSkinId == -1) {
|
||||
return true;
|
||||
}else {
|
||||
return isStandardModel(EaglerProfile.presetSkinId);
|
||||
}
|
||||
}else if(p instanceof EntityOtherPlayerMP) {
|
||||
EntityOtherPlayerMP pp = (EntityOtherPlayerMP) p;
|
||||
if(pp.skinPacket != null) {
|
||||
if(pp.skinPacket[0] != (byte)4) {
|
||||
return true;
|
||||
}else {
|
||||
return isStandardModel((int)pp.skinPacket[1] & 0xFF);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static int getPlayerRenderer(EntityPlayer p) {
|
||||
if(p instanceof EntityClientPlayerMP) {
|
||||
if(EaglerProfile.presetSkinId == -1) {
|
||||
return 0;
|
||||
}else {
|
||||
return EaglerProfile.presetSkinId;
|
||||
}
|
||||
}else if(p instanceof EntityOtherPlayerMP) {
|
||||
EntityOtherPlayerMP pp = (EntityOtherPlayerMP) p;
|
||||
if(pp.skinPacket != null) {
|
||||
if(pp.skinPacket[0] != (byte)4) {
|
||||
return 0;
|
||||
}else {
|
||||
if(((int)pp.skinPacket[1] & 0xFF) >= DefaultSkinRenderer.defaultVanillaSkins.length) {
|
||||
return 0;
|
||||
}else {
|
||||
return (int)pp.skinPacket[1] & 0xFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static ModelBiped oldSkinRenderer = null;
|
||||
public static ModelBipedNewSkins newSkinRenderer = null;
|
||||
public static ModelBipedNewSkins newSkinRendererSlim = null;
|
||||
public static ModelZombie zombieRenderer = null;
|
||||
public static ModelVillager villagerRenderer = null;
|
||||
public static ModelEnderman endermanRenderer = null;
|
||||
public static ModelBlaze blazeRenderer = null;
|
||||
public static ModelSkeleton skeletonRenderer = null;
|
||||
|
||||
public static void renderPlayerPreview(int x, int y, int mx, int my, int id2) {
|
||||
boolean capeMode = (id2 & 0x10000) == 0x10000;
|
||||
if(capeMode) {
|
||||
id2 -= 0x10000;
|
||||
}
|
||||
int id = id2 - EaglerProfile.skins.size();
|
||||
boolean highPoly = isHighPoly(id);
|
||||
|
||||
EaglerAdapter.glEnable(EaglerAdapter.GL_TEXTURE_2D);
|
||||
EaglerAdapter.glDisable(EaglerAdapter.GL_BLEND);
|
||||
if(highPoly) {
|
||||
EaglerAdapter.glEnable(EaglerAdapter.GL_CULL_FACE);
|
||||
}else {
|
||||
EaglerAdapter.glDisable(EaglerAdapter.GL_CULL_FACE);
|
||||
}
|
||||
EaglerAdapter.glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
EaglerAdapter.glPushMatrix();
|
||||
EaglerAdapter.glTranslatef((float) x, (float) (y - 80), 100.0F);
|
||||
EaglerAdapter.glScalef(50.0f, 50.0f, 50.0f);
|
||||
EaglerAdapter.glRotatef(180.0f, 1.0f, 0.0f, 0.0f);
|
||||
EaglerAdapter.glEnable(EaglerAdapter.GL_RESCALE_NORMAL);
|
||||
EaglerAdapter.glScalef(1.0F, -1.0F, 1.0F);
|
||||
RenderHelper.enableGUIStandardItemLighting();
|
||||
EaglerAdapter.glTranslatef(0.0F, 1.0F, 0.0F);
|
||||
if(capeMode) {
|
||||
EaglerAdapter.glRotatef(140.0f, 0.0f, 1.0f, 0.0f);
|
||||
mx = x - (x - mx) - 20;
|
||||
EaglerAdapter.glRotatef(((y - my) * -0.02f), 1.0f, 0.0f, 0.0f);
|
||||
}else {
|
||||
EaglerAdapter.glRotatef(((y - my) * -0.06f), 1.0f, 0.0f, 0.0f);
|
||||
}
|
||||
EaglerAdapter.glRotatef(((x - mx) * 0.06f), 0.0f, 1.0f, 0.0f);
|
||||
EaglerAdapter.glTranslatef(0.0F, -1.0F, 0.0F);
|
||||
|
||||
if(highPoly) {
|
||||
EaglerAdapter.flipLightMatrix();
|
||||
EaglerAdapter.glPushMatrix();
|
||||
EaglerAdapter.glRotatef(180.0f, 0.0f, 0.0f, 1.0f);
|
||||
EaglerAdapter.glTranslatef(0.0f, -1.5f, 0.0f);
|
||||
EaglerAdapter.glScalef(HighPolySkin.highPolyScale, HighPolySkin.highPolyScale, HighPolySkin.highPolyScale);
|
||||
HighPolySkin msh = defaultHighPoly[id];
|
||||
msh.texture.bindTexture();
|
||||
|
||||
if(msh.bodyModel != null) {
|
||||
EaglerAdapter.drawHighPoly(msh.bodyModel.getModel());
|
||||
}
|
||||
|
||||
if(msh.headModel != null) {
|
||||
EaglerAdapter.drawHighPoly(msh.headModel.getModel());
|
||||
}
|
||||
|
||||
if(msh.limbsModel != null && msh.limbsModel.length > 0) {
|
||||
for(int i = 0; i < msh.limbsModel.length; ++i) {
|
||||
float offset = 0.0f;
|
||||
if(msh.limbsOffset != null) {
|
||||
if(msh.limbsOffset.length == 1) {
|
||||
offset = msh.limbsOffset[0];
|
||||
}else {
|
||||
offset = msh.limbsOffset[i];
|
||||
}
|
||||
}
|
||||
if(offset != 0.0f || msh.limbsInitialRotation != 0.0f) {
|
||||
EaglerAdapter.glPushMatrix();
|
||||
if(offset != 0.0f) {
|
||||
EaglerAdapter.glTranslatef(0.0f, offset, 0.0f);
|
||||
}
|
||||
if(msh.limbsInitialRotation != 0.0f) {
|
||||
EaglerAdapter.glRotatef(msh.limbsInitialRotation, 1.0f, 0.0f, 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
EaglerAdapter.drawHighPoly(msh.limbsModel[i].getModel());
|
||||
|
||||
if(offset != 0.0f || msh.limbsInitialRotation != 0.0f) {
|
||||
EaglerAdapter.glPopMatrix();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EaglerAdapter.glPopMatrix();
|
||||
EaglerAdapter.flipLightMatrix();
|
||||
}else {
|
||||
if(id < 0) {
|
||||
Minecraft.getMinecraft().renderEngine.bindTexture(EaglerProfile.skins.get(id2).glTex);
|
||||
}else {
|
||||
defaultVanillaSkins[id].bindTexture();
|
||||
}
|
||||
|
||||
boolean gonnaShowCape = false;
|
||||
if(isStandardModel(id) || id < 0) {
|
||||
if(oldSkinRenderer == null) oldSkinRenderer = new ModelBiped(0.0F, 0.0F, 64, 32);
|
||||
if(newSkinRenderer == null) newSkinRenderer = new ModelBipedNewSkins(0.0F, false);
|
||||
if(newSkinRendererSlim == null) newSkinRendererSlim = new ModelBipedNewSkins(0.0F, true);
|
||||
oldSkinRenderer.isChild = false;
|
||||
newSkinRenderer.isChild = false;
|
||||
newSkinRendererSlim.isChild = false;
|
||||
boolean isNew = isNewSkin(id);
|
||||
if(id < 0) {
|
||||
int type = EaglerProfile.getSkinSize(EaglerProfile.skins.get(id2).data.length);
|
||||
isNew = (type == 1 || type == 3);
|
||||
}
|
||||
if(isNew) {
|
||||
if((id < 0 && EaglerProfile.skins.get(id2).slim) || (id >= 0 && isAlexSkin(id))) {
|
||||
newSkinRendererSlim.blockTransparentSkin = true;
|
||||
newSkinRendererSlim.render(null, 0.0f, 0.0f, (float)(EaglerAdapter.steadyTimeMillis() % 100000) / 50f, ((x - mx) * 0.06f), ((y - my) * -0.1f), 0.0625F);
|
||||
newSkinRendererSlim.blockTransparentSkin = false;
|
||||
}else {
|
||||
newSkinRenderer.blockTransparentSkin = true;
|
||||
newSkinRenderer.render(null, 0.0f, 0.0f, (float)(EaglerAdapter.steadyTimeMillis() % 100000) / 50f, ((x - mx) * 0.06f), ((y - my) * -0.1f), 0.0625F);
|
||||
newSkinRenderer.blockTransparentSkin = false;
|
||||
}
|
||||
}else {
|
||||
oldSkinRenderer.blockTransparentSkin = true;
|
||||
oldSkinRenderer.render(null, 0.0f, 0.0f, (float)(EaglerAdapter.steadyTimeMillis() % 100000) / 50f, ((x - mx) * 0.06f), ((y - my) * -0.1f), 0.0625F);
|
||||
oldSkinRenderer.blockTransparentSkin = false;
|
||||
}
|
||||
gonnaShowCape = capeMode;
|
||||
}else if(isZombieModel(id)) {
|
||||
if(zombieRenderer == null) zombieRenderer = new ModelZombie(0.0F, true);
|
||||
zombieRenderer.isChild = false;
|
||||
zombieRenderer.render(null, 0.0f, 0.0f, (float)(EaglerAdapter.steadyTimeMillis() % 100000) / 50f, ((x - mx) * 0.06f), ((y - my) * -0.1f), 0.0625F);
|
||||
gonnaShowCape = capeMode;
|
||||
}else if(id == 32) {
|
||||
if(villagerRenderer == null) villagerRenderer = new ModelVillager(0.0F);
|
||||
villagerRenderer.isChild = false;
|
||||
villagerRenderer.render(null, 0.0f, 0.0f, (float)(EaglerAdapter.steadyTimeMillis() % 100000) / 50f, ((x - mx) * 0.06f), ((y - my) * -0.1f), 0.0625F);
|
||||
}else if(id == 19) {
|
||||
if(endermanRenderer == null) endermanRenderer = new ModelEnderman();
|
||||
endermanRenderer.isChild = false;
|
||||
endermanRenderer.render(null, 0.0f, 0.0f, (float)(EaglerAdapter.steadyTimeMillis() % 100000) / 50f, ((x - mx) * 0.06f), ((y - my) * -0.1f), 0.0625F);
|
||||
EaglerAdapter.glColor4f(1.4f, 1.4f, 1.4f, 1.0f);
|
||||
//EaglerAdapter.glEnable(EaglerAdapter.GL_BLEND);
|
||||
//EaglerAdapter.glDisable(EaglerAdapter.GL_ALPHA_TEST);
|
||||
//EaglerAdapter.glBlendFunc(EaglerAdapter.GL_ONE, EaglerAdapter.GL_ONE);
|
||||
EaglerAdapter.glDisable(EaglerAdapter.GL_LIGHTING);
|
||||
EaglerAdapter.glEnable(EaglerAdapter.GL_TEXTURE_2D);
|
||||
EaglerAdapter.glDisable(EaglerAdapter.GL_DEPTH_TEST);
|
||||
RenderEnderman.tex_eyes.bindTexture();
|
||||
endermanRenderer.render(null, 0.0f, 0.0f, (float)(EaglerAdapter.steadyTimeMillis() % 100000) / 50f, ((x - mx) * 0.06f), ((y - my) * -0.1f), 0.0625F);
|
||||
EaglerAdapter.glBlendFunc(EaglerAdapter.GL_SRC_ALPHA, EaglerAdapter.GL_ONE_MINUS_SRC_ALPHA);
|
||||
EaglerAdapter.glEnable(EaglerAdapter.GL_ALPHA_TEST);
|
||||
EaglerAdapter.glEnable(EaglerAdapter.GL_DEPTH_TEST);
|
||||
EaglerAdapter.glDisable(EaglerAdapter.GL_TEXTURE_2D);
|
||||
EaglerAdapter.glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
}else if(id == 20) {
|
||||
if(skeletonRenderer == null) skeletonRenderer = new ModelSkeleton(0.0F);
|
||||
skeletonRenderer.isChild = false;
|
||||
skeletonRenderer.render(null, 0.0f, 0.0f, (float)(EaglerAdapter.steadyTimeMillis() % 100000) / 50f, ((x - mx) * 0.06f), ((y - my) * -0.1f), 0.0625F);
|
||||
}else if(id == 21) {
|
||||
if(blazeRenderer == null) blazeRenderer = new ModelBlaze();
|
||||
blazeRenderer.isChild = false;
|
||||
EaglerAdapter.glColor4f(1.5f, 1.5f, 1.5f, 1.0f);
|
||||
blazeRenderer.render(null, 0.0f, 0.0f, (float)(EaglerAdapter.steadyTimeMillis() % 100000) / 50f, ((x - mx) * 0.06f), ((y - my) * -0.1f), 0.0625F);
|
||||
}
|
||||
if(gonnaShowCape && !(EaglerProfile.presetCapeId >= 0 && defaultVanillaCapes[EaglerProfile.presetCapeId] == null)) {
|
||||
EaglerAdapter.glPushMatrix();
|
||||
EaglerAdapter.glTranslatef(0.0F, 0.0F, 0.150F);
|
||||
EaglerAdapter.glRotatef(180.0F, 0.0F, 1.0F, 0.0F);
|
||||
EaglerAdapter.glRotatef(-6.0F, 1.0F, 0.0F, 0.0F);
|
||||
|
||||
if(EaglerProfile.presetCapeId < 0) {
|
||||
Minecraft.getMinecraft().renderEngine.bindTexture(EaglerProfile.capes.get(EaglerProfile.customCapeId).glTex);
|
||||
EaglerAdapter.glMatrixMode(EaglerAdapter.GL_TEXTURE);
|
||||
EaglerAdapter.glPushMatrix();
|
||||
EaglerAdapter.glScalef(2.0f, 1.0f, 1.0f);
|
||||
EaglerAdapter.glMatrixMode(EaglerAdapter.GL_MODELVIEW);
|
||||
}else {
|
||||
defaultVanillaCapes[EaglerProfile.presetCapeId].bindTexture();
|
||||
}
|
||||
|
||||
if(oldSkinRenderer == null) oldSkinRenderer = new ModelBiped(0.0F, 0.0F, 64, 32);
|
||||
oldSkinRenderer.bipedCloak.render(0.0625F);
|
||||
|
||||
if(EaglerProfile.presetCapeId < 0) {
|
||||
EaglerAdapter.glMatrixMode(EaglerAdapter.GL_TEXTURE);
|
||||
EaglerAdapter.glPopMatrix();
|
||||
EaglerAdapter.glMatrixMode(EaglerAdapter.GL_MODELVIEW);
|
||||
}
|
||||
|
||||
EaglerAdapter.glPopMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
EaglerAdapter.glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
|
||||
EaglerAdapter.glPopMatrix();
|
||||
EaglerAdapter.glDisable(EaglerAdapter.GL_RESCALE_NORMAL);
|
||||
OpenGlHelper.setActiveTexture(OpenGlHelper.lightmapTexUnit);
|
||||
EaglerAdapter.glDisable(EaglerAdapter.GL_TEXTURE_2D);
|
||||
OpenGlHelper.setActiveTexture(OpenGlHelper.defaultTexUnit);
|
||||
EaglerAdapter.glDisable(EaglerAdapter.GL_LIGHTING);
|
||||
}
|
||||
|
||||
public static void renderAlexOrSteve(int x, int y, int mx, int my, boolean alex) {
|
||||
ModelBipedNewSkins bp;
|
||||
if(alex) {
|
||||
if(newSkinRendererSlim == null) {
|
||||
newSkinRendererSlim = new ModelBipedNewSkins(0.0F, true);
|
||||
}
|
||||
bp = newSkinRendererSlim;
|
||||
}else {
|
||||
if(newSkinRenderer == null) {
|
||||
newSkinRenderer = new ModelBipedNewSkins(0.0F, false);
|
||||
}
|
||||
bp = newSkinRenderer;
|
||||
}
|
||||
|
||||
EaglerAdapter.glEnable(EaglerAdapter.GL_TEXTURE_2D);
|
||||
EaglerAdapter.glDisable(EaglerAdapter.GL_BLEND);
|
||||
EaglerAdapter.glDisable(EaglerAdapter.GL_CULL_FACE);
|
||||
EaglerAdapter.glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
EaglerAdapter.glPushMatrix();
|
||||
EaglerAdapter.glTranslatef((float) x, (float) (y - 80), 100.0F);
|
||||
EaglerAdapter.glScalef(50.0f, 50.0f, 50.0f);
|
||||
EaglerAdapter.glRotatef(180.0f, 1.0f, 0.0f, 0.0f);
|
||||
EaglerAdapter.glEnable(EaglerAdapter.GL_RESCALE_NORMAL);
|
||||
EaglerAdapter.glScalef(1.0F, -1.0F, 1.0F);
|
||||
RenderHelper.enableGUIStandardItemLighting();
|
||||
EaglerAdapter.glTranslatef(0.0F, 1.0F, 0.0F);
|
||||
EaglerAdapter.glRotatef(((y - my) * -0.06f), 1.0f, 0.0f, 0.0f);
|
||||
EaglerAdapter.glRotatef(((x - mx) * 0.06f), 0.0f, 1.0f, 0.0f);
|
||||
EaglerAdapter.glTranslatef(0.0F, -1.0F, 0.0F);
|
||||
|
||||
bp.isChild = false;
|
||||
bp.render(null, 0.0f, 0.0f, (float)(EaglerAdapter.steadyTimeMillis() % 100000) / 50f, ((x - mx) * 0.06f), ((y - my) * -0.1f), 0.0625F);
|
||||
|
||||
EaglerAdapter.glPopMatrix();
|
||||
EaglerAdapter.glDisable(EaglerAdapter.GL_RESCALE_NORMAL);
|
||||
OpenGlHelper.setActiveTexture(OpenGlHelper.lightmapTexUnit);
|
||||
EaglerAdapter.glDisable(EaglerAdapter.GL_TEXTURE_2D);
|
||||
OpenGlHelper.setActiveTexture(OpenGlHelper.defaultTexUnit);
|
||||
EaglerAdapter.glDisable(EaglerAdapter.GL_LIGHTING);
|
||||
}
|
||||
|
||||
public static boolean isPlayerPreviewNew(int id2) {
|
||||
int id = id2 - EaglerProfile.skins.size();
|
||||
if(id < 0) {
|
||||
return EaglerProfile.skins.get(id2).data.length == EaglerProfile.SKIN_DATA_SIZE[1] || EaglerProfile.skins.get(id2).data.length == EaglerProfile.SKIN_DATA_SIZE[3];
|
||||
}else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
151
src/main/java/net/lax1dude/eaglercraft/EPK2Compiler.java
Normal file
151
src/main/java/net/lax1dude/eaglercraft/EPK2Compiler.java
Normal file
@@ -0,0 +1,151 @@
|
||||
package net.lax1dude.eaglercraft;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Date;
|
||||
|
||||
import com.jcraft.jzlib.CRC32;
|
||||
|
||||
public class EPK2Compiler {
|
||||
|
||||
private final ByteArrayOutputStream os;
|
||||
private final CRC32 checkSum = new CRC32();
|
||||
private int lengthIntegerOffset = 0;
|
||||
private int totalFileCount = 0;
|
||||
|
||||
public EPK2Compiler() {
|
||||
String name = "__TEXTUREPACK__";
|
||||
String owner = "__INTERNAL__";
|
||||
String type = "epk/resources";
|
||||
os = new ByteArrayOutputStream(0x200000);
|
||||
try {
|
||||
|
||||
os.write(new byte[]{(byte)69,(byte)65,(byte)71,(byte)80,(byte)75,(byte)71,(byte)36,(byte)36}); // EAGPKG$$
|
||||
os.write(new byte[]{(byte)6,(byte)118,(byte)101,(byte)114,(byte)50,(byte)46,(byte)48}); // 6 + ver2.0
|
||||
Date d = new Date();
|
||||
|
||||
byte[] filename = (name + ".epk").getBytes(StandardCharsets.UTF_8);
|
||||
os.write(filename.length);
|
||||
os.write(filename);
|
||||
|
||||
byte[] comment = ("\n\n # Eagler EPK v2.0\n\n")
|
||||
.getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
os.write((comment.length >> 8) & 255);
|
||||
os.write(comment.length & 255);
|
||||
os.write(comment);
|
||||
|
||||
writeLong(d.getTime(), os);
|
||||
|
||||
lengthIntegerOffset = os.size();
|
||||
os.write(new byte[]{(byte)255,(byte)255,(byte)255,(byte)255}); // this will be replaced with the file count
|
||||
|
||||
os.write('0'); // compression type: none
|
||||
|
||||
os.write(new byte[]{(byte)72,(byte)69,(byte)65,(byte)68}); // HEAD
|
||||
os.write(new byte[]{(byte)9,(byte)102,(byte)105,(byte)108,(byte)101,(byte)45,(byte)116,(byte)121,
|
||||
(byte)112,(byte)101}); // 9 + file-type
|
||||
|
||||
byte[] typeBytes = type.getBytes(StandardCharsets.UTF_8);
|
||||
writeInt(typeBytes.length, os);
|
||||
os.write(typeBytes); // write type
|
||||
os.write('>');
|
||||
|
||||
++totalFileCount;
|
||||
|
||||
os.write(new byte[]{(byte)72,(byte)69,(byte)65,(byte)68}); // HEAD
|
||||
os.write(new byte[]{(byte)10,(byte)119,(byte)111,(byte)114,(byte)108,(byte)100,(byte)45,(byte)110,
|
||||
(byte)97,(byte)109,(byte)101}); // 10 + name
|
||||
|
||||
byte[] nameBytes = name.getBytes(StandardCharsets.UTF_8);
|
||||
writeInt(nameBytes.length, os);
|
||||
os.write(nameBytes); // write name
|
||||
os.write('>');
|
||||
|
||||
++totalFileCount;
|
||||
|
||||
os.write(new byte[]{(byte)72,(byte)69,(byte)65,(byte)68}); // HEAD
|
||||
os.write(new byte[]{(byte)11,(byte)119,(byte)111,(byte)114,(byte)108,(byte)100,(byte)45,(byte)111,
|
||||
(byte)119,(byte)110,(byte)101,(byte)114}); // 11 + owner
|
||||
|
||||
byte[] ownerBytes = owner.getBytes(StandardCharsets.UTF_8);
|
||||
writeInt(ownerBytes.length, os);
|
||||
os.write(ownerBytes); // write owner
|
||||
os.write('>');
|
||||
|
||||
++totalFileCount;
|
||||
|
||||
}catch(IOException ex) {
|
||||
throw new RuntimeException("This happened somehow", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void append(String name, byte[] dat) {
|
||||
try {
|
||||
|
||||
checkSum.reset();
|
||||
checkSum.update(dat, 0, dat.length);
|
||||
long sum = checkSum.getValue();
|
||||
|
||||
os.write(new byte[]{(byte)70,(byte)73,(byte)76,(byte)69}); // FILE
|
||||
|
||||
byte[] nameBytes = name.getBytes(StandardCharsets.UTF_8);
|
||||
os.write(nameBytes.length);
|
||||
os.write(nameBytes);
|
||||
|
||||
writeInt(dat.length + 5, os);
|
||||
writeInt((int)sum, os);
|
||||
|
||||
os.write(dat);
|
||||
|
||||
os.write(':');
|
||||
os.write('>');
|
||||
|
||||
++totalFileCount;
|
||||
|
||||
}catch(IOException ex) {
|
||||
throw new RuntimeException("This happened somehow", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] complete() {
|
||||
try {
|
||||
|
||||
os.write(new byte[]{(byte)69,(byte)78,(byte)68,(byte)36}); // END$
|
||||
os.write(new byte[]{(byte)58,(byte)58,(byte)58,(byte)89,(byte)69,(byte)69,(byte)58,(byte)62}); // :::YEE:>
|
||||
|
||||
byte[] ret = os.toByteArray();
|
||||
|
||||
ret[lengthIntegerOffset] = (byte)((totalFileCount >> 24) & 0xFF);
|
||||
ret[lengthIntegerOffset + 1] = (byte)((totalFileCount >> 16) & 0xFF);
|
||||
ret[lengthIntegerOffset + 2] = (byte)((totalFileCount >> 8) & 0xFF);
|
||||
ret[lengthIntegerOffset + 3] = (byte)(totalFileCount & 0xFF);
|
||||
|
||||
return ret;
|
||||
|
||||
}catch(IOException ex) {
|
||||
throw new RuntimeException("This happened somehow", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static void writeInt(int i, OutputStream os) throws IOException {
|
||||
os.write((i >> 24) & 0xFF);
|
||||
os.write((i >> 16) & 0xFF);
|
||||
os.write((i >> 8) & 0xFF);
|
||||
os.write(i & 0xFF);
|
||||
}
|
||||
|
||||
public static void writeLong(long i, OutputStream os) throws IOException {
|
||||
os.write((int)((i >> 56) & 0xFF));
|
||||
os.write((int)((i >> 48) & 0xFF));
|
||||
os.write((int)((i >> 40) & 0xFF));
|
||||
os.write((int)((i >> 32) & 0xFF));
|
||||
os.write((int)((i >> 24) & 0xFF));
|
||||
os.write((int)((i >> 16) & 0xFF));
|
||||
os.write((int)((i >> 8) & 0xFF));
|
||||
os.write((int)(i & 0xFF));
|
||||
}
|
||||
|
||||
}
|
||||
216
src/main/java/net/lax1dude/eaglercraft/EPKDecompiler.java
Normal file
216
src/main/java/net/lax1dude/eaglercraft/EPKDecompiler.java
Normal file
@@ -0,0 +1,216 @@
|
||||
package net.lax1dude.eaglercraft;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Arrays;
|
||||
|
||||
import com.jcraft.jzlib.CRC32;
|
||||
import com.jcraft.jzlib.GZIPInputStream;
|
||||
import com.jcraft.jzlib.InflaterInputStream;
|
||||
|
||||
public class EPKDecompiler {
|
||||
|
||||
public static class FileEntry {
|
||||
public final String type;
|
||||
public final String name;
|
||||
public final byte[] data;
|
||||
protected FileEntry(String type, String name, byte[] data) {
|
||||
this.type = type;
|
||||
this.name = name;
|
||||
this.data = data;
|
||||
}
|
||||
}
|
||||
|
||||
private EaglerInputStream in2;
|
||||
private DataInputStream in;
|
||||
private InputStream zis;
|
||||
private SHA1Digest dg;
|
||||
private CRC32 crc32;
|
||||
private int numFiles;
|
||||
private boolean isFinished = false;
|
||||
private boolean isOldFormat = false;
|
||||
|
||||
public EPKDecompiler(byte[] data) throws IOException {
|
||||
in2 = new EaglerInputStream(data);
|
||||
|
||||
byte[] header = new byte[8];
|
||||
in2.read(header);
|
||||
|
||||
if(Arrays.equals(header, new byte[]{(byte)69,(byte)65,(byte)71,(byte)80,(byte)75,(byte)71,(byte)36,(byte)36})) {
|
||||
byte[] endCode = new byte[] { (byte)':', (byte)':', (byte)':', (byte)'Y',
|
||||
(byte)'E', (byte)'E', (byte)':', (byte)'>' };
|
||||
for(int i = 0; i < 8; ++i) {
|
||||
if(data[data.length - 8 + i] != endCode[i]) {
|
||||
throw new IOException("EPK file is missing EOF code (:::YEE:>)");
|
||||
}
|
||||
}
|
||||
in2 = new EaglerInputStream(data, 8, data.length - 16);
|
||||
initNew();
|
||||
}else if(Arrays.equals(header, new byte[]{(byte)69,(byte)65,(byte)71,(byte)80,(byte)75,(byte)71,(byte)33,(byte)33})) {
|
||||
initOld();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public boolean isOld() {
|
||||
return isOldFormat;
|
||||
}
|
||||
|
||||
public FileEntry readFile() throws IOException {
|
||||
if(!isOldFormat) {
|
||||
return readFileNew();
|
||||
}else {
|
||||
return readFileOld();
|
||||
}
|
||||
}
|
||||
|
||||
private void initNew() throws IOException {
|
||||
InputStream is = in2;
|
||||
|
||||
String vers = readASCII(is);
|
||||
if(!vers.startsWith("ver2.")) {
|
||||
throw new IOException("Unknown or invalid EPK version: " + vers);
|
||||
}
|
||||
|
||||
is.skip(is.read()); // skip filename
|
||||
is.skip(loadShort(is)); // skip comment
|
||||
is.skip(8); // skip millis date
|
||||
|
||||
numFiles = loadInt(is);
|
||||
|
||||
char compressionType = (char)is.read();
|
||||
|
||||
switch(compressionType) {
|
||||
case 'G':
|
||||
zis = new GZIPInputStream(is);
|
||||
break;
|
||||
case 'Z':
|
||||
zis = new InflaterInputStream(is);
|
||||
break;
|
||||
case '0':
|
||||
zis = is;
|
||||
break;
|
||||
default:
|
||||
throw new IOException("Invalid or unsupported EPK compression: " + compressionType);
|
||||
}
|
||||
|
||||
crc32 = new CRC32();
|
||||
|
||||
}
|
||||
|
||||
private FileEntry readFileNew() throws IOException {
|
||||
if(isFinished) {
|
||||
return null;
|
||||
}
|
||||
|
||||
byte[] typeBytes = new byte[4];
|
||||
zis.read(typeBytes);
|
||||
String type = readASCII(typeBytes);
|
||||
|
||||
if(numFiles == 0) {
|
||||
if(!"END$".equals(type)) {
|
||||
throw new IOException("EPK file is missing END code (END$)");
|
||||
}
|
||||
isFinished = true;
|
||||
return null;
|
||||
}else {
|
||||
if("END$".equals(type)) {
|
||||
throw new IOException("Unexpected END when there are still " + numFiles + " files remaining");
|
||||
}else {
|
||||
String name = readASCII(zis);
|
||||
int len = loadInt(zis);
|
||||
byte[] data;
|
||||
|
||||
if("FILE".equals(type)) {
|
||||
if(len < 5) {
|
||||
throw new IOException("File '" + name + "' is incomplete (no crc)");
|
||||
}
|
||||
|
||||
int loadedCrc = loadInt(zis);
|
||||
|
||||
data = new byte[len - 5];
|
||||
zis.read(data);
|
||||
|
||||
crc32.reset();
|
||||
crc32.update(data, 0, data.length);
|
||||
if((int)crc32.getValue() != loadedCrc) {
|
||||
throw new IOException("File '" + name + "' has an invalid checksum");
|
||||
}
|
||||
|
||||
if(zis.read() != ':') {
|
||||
throw new IOException("File '" + name + "' is incomplete");
|
||||
}
|
||||
}else {
|
||||
data = new byte[len];
|
||||
zis.read(data);
|
||||
}
|
||||
|
||||
if(zis.read() != '>') {
|
||||
throw new IOException("Object '" + name + "' is incomplete");
|
||||
}
|
||||
|
||||
--numFiles;
|
||||
return new FileEntry(type, name, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static final int loadShort(InputStream is) throws IOException {
|
||||
return (is.read() << 8) | is.read();
|
||||
}
|
||||
|
||||
private static final int loadInt(InputStream is) throws IOException {
|
||||
return (is.read() << 24) | (is.read() << 16) | (is.read() << 8) | is.read();
|
||||
}
|
||||
|
||||
public static final String readASCII(byte[] bytesIn) throws IOException {
|
||||
char[] charIn = new char[bytesIn.length];
|
||||
for(int i = 0; i < bytesIn.length; ++i) {
|
||||
charIn[i] = (char)((int)bytesIn[i] & 0xFF);
|
||||
}
|
||||
return new String(charIn);
|
||||
}
|
||||
|
||||
private static final String readASCII(InputStream bytesIn) throws IOException {
|
||||
int len = bytesIn.read();
|
||||
char[] charIn = new char[len];
|
||||
for(int i = 0; i < len; ++i) {
|
||||
charIn[i] = (char)(bytesIn.read() & 0xFF);
|
||||
}
|
||||
return new String(charIn);
|
||||
}
|
||||
|
||||
private void initOld() throws IOException {
|
||||
isOldFormat = true;
|
||||
dg = new SHA1Digest();
|
||||
in = new DataInputStream(in2);
|
||||
in.readUTF();
|
||||
in = new DataInputStream(new InflaterInputStream(in2));
|
||||
}
|
||||
|
||||
private FileEntry readFileOld() throws IOException {
|
||||
if(isFinished) {
|
||||
return null;
|
||||
}
|
||||
String s = in.readUTF();
|
||||
if(s.equals(" end")) {
|
||||
isFinished = true;
|
||||
return null;
|
||||
}else if(!s.equals("<file>")) {
|
||||
throw new IOException("invalid epk file");
|
||||
}
|
||||
String path = in.readUTF();
|
||||
byte[] digest = new byte[20];
|
||||
byte[] digest2 = new byte[20];
|
||||
in.read(digest);
|
||||
int len = in.readInt();
|
||||
byte[] file = new byte[len];
|
||||
in.read(file);
|
||||
dg.update(file, 0, len); dg.doFinal(digest2, 0);
|
||||
if(!Arrays.equals(digest, digest2)) throw new IOException("invalid file hash for "+path);
|
||||
if(!"</file>".equals(in.readUTF())) throw new IOException("invalid epk file");
|
||||
return new FileEntry("FILE", path, file);
|
||||
}
|
||||
|
||||
}
|
||||
11
src/main/java/net/lax1dude/eaglercraft/EaglerAdapter.java
Normal file
11
src/main/java/net/lax1dude/eaglercraft/EaglerAdapter.java
Normal file
@@ -0,0 +1,11 @@
|
||||
package net.lax1dude.eaglercraft;
|
||||
|
||||
import net.lax1dude.eaglercraft.glemu.EaglerAdapterGL30;
|
||||
|
||||
public class EaglerAdapter extends EaglerAdapterGL30 {
|
||||
|
||||
/*
|
||||
* YOU EAGLR!
|
||||
*/
|
||||
|
||||
}
|
||||
44
src/main/java/net/lax1dude/eaglercraft/EaglerImage.java
Normal file
44
src/main/java/net/lax1dude/eaglercraft/EaglerImage.java
Normal file
@@ -0,0 +1,44 @@
|
||||
package net.lax1dude.eaglercraft;
|
||||
|
||||
public class EaglerImage {
|
||||
|
||||
public final int[] data;
|
||||
public final int w;
|
||||
public final int h;
|
||||
public final boolean alpha;
|
||||
|
||||
public EaglerImage(int pw, int ph, boolean palpha) {
|
||||
this.w = pw;
|
||||
this.h = ph;
|
||||
this.alpha = palpha;
|
||||
this.data = new int[pw * ph];
|
||||
}
|
||||
|
||||
public EaglerImage(int[] pdata, int pw, int ph, boolean palpha) {
|
||||
if(pdata.length != pw*ph) {
|
||||
throw new IllegalArgumentException("array size does not equal image size");
|
||||
}
|
||||
this.w = pw;
|
||||
this.h = ph;
|
||||
this.alpha = palpha;
|
||||
if(!palpha) {
|
||||
for(int i = 0; i < pdata.length; ++i) {
|
||||
pdata[i] = pdata[i] | 0xFF000000;
|
||||
}
|
||||
}
|
||||
this.data = pdata;
|
||||
}
|
||||
|
||||
public static final EaglerImage loadImage(byte[] file) {
|
||||
return EaglerAdapter.loadPNG(file);
|
||||
}
|
||||
|
||||
public EaglerImage getSubImage(int x, int y, int pw, int ph) {
|
||||
int[] img = new int[pw * ph];
|
||||
for(int i = 0; i < ph; ++i) {
|
||||
System.arraycopy(data, (i + y) * this.w + x, img, i * pw, pw);
|
||||
}
|
||||
return new EaglerImage(img, pw, ph, alpha);
|
||||
}
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user