package net.sourceforge.jaad.aac.error;
import net.sourceforge.jaad.aac.AACException;
import net.sourceforge.jaad.aac.syntax.IBitStream;
/**
* This class is part of JAAD ( jaadec.sourceforge.net ) that is distributed
* under the Public Domain license. Code changes provided by the JCodec project
* are distributed under FreeBSD license.
*
* @author in-somnia
*/
public class BitsBuffer {
int bufa, bufb, len;
//bit-twiddling helpers
static final int[] S = {1, 2, 4, 8, 16};
static final int[] B = {0x55555555, 0x33333333, 0x0F0F0F0F, 0x00FF00FF, 0x0000FFFF};
public BitsBuffer() {
len = 0;
}
public int getLength() {
return len;
}
public int showBits(int bits) {
if(bits==0) return 0;
if(len<=32) {
//huffman_spectral_data_2 needs to read more than may be available,
//bits maybe > len, deliver 0 than
if(len>=bits) return ((bufa>>(len-bits))&(0xFFFFFFFF>>(32-bits)));
else return ((bufa<<(bits-len))&(0xFFFFFFFF>>(32-bits)));
}
else {
if((len-bits)<32) return ((bufb&(0xFFFFFFFF>>(64-len)))<<(bits-len+32))|(bufa>>(len-bits));
else return ((bufb>>(len-bits-32))&(0xFFFFFFFF>>(32-bits)));
}
}
public boolean flushBits(int bits) {
len -= bits;
boolean b;
if(len<0) {
len = 0;
b = false;
}
else b = true;
return b;
}
public int getBits(int n) {
int i = showBits(n);
if(!flushBits(n)) i = -1;
return i;
}
public int getBit() {
int i = showBits(1);
if(!flushBits(1)) i = -1;
return i;
}
public void rewindReverse() {
if(len==0) return;
final int[] i = BitsBuffer.rewindReverse64(bufb, bufa, len);
bufb = i[0];
bufa = i[1];
}
//merge bits of a to b
public void concatBits(BitsBuffer a) {
if(a.len==0) return;
int al = a.bufa;
int ah = a.bufb;
int bl, bh;
if(len>32) {
//mask off superfluous high b bits
bl = bufa;
bh = bufb&((1<<(len-32))-1);
//left shift a len bits
ah = al<<(len-32);
al = 0;
}
else {
bl = bufa&((1<<(len))-1);
bh = 0;
ah = (ah<<(len))|(al>>(32-len));
al = al<<len;
}
//merge
bufa = bl|al;
bufb = bh|ah;
len += a.len;
}
public void readSegment(int segwidth, IBitStream _in) throws AACException {
len = segwidth;
if(segwidth>32) {
bufb = _in.readBits(segwidth-32);
bufa = _in.readBits(32);
}
else {
bufa = _in.readBits(segwidth);
bufb = 0;
}
}
//32 bit rewind and reverse
static int rewindReverse32(int v, int len) {
v = ((v>>S[0])&B[0])|((v<<S[0])&~B[0]);
v = ((v>>S[1])&B[1])|((v<<S[1])&~B[1]);
v = ((v>>S[2])&B[2])|((v<<S[2])&~B[2]);
v = ((v>>S[3])&B[3])|((v<<S[3])&~B[3]);
v = ((v>>S[4])&B[4])|((v<<S[4])&~B[4]);
//shift off low bits
v >>= (32-len);
return v;
}
//64 bit rewind and reverse
static int[] rewindReverse64(int hi, int lo, int len) {
int[] i = new int[2];
if(len<=32) {
i[0] = 0;
i[1] = rewindReverse32(lo, len);
}
else {
lo = ((lo>>S[0])&B[0])|((lo<<S[0])&~B[0]);
hi = ((hi>>S[0])&B[0])|((hi<<S[0])&~B[0]);
lo = ((lo>>S[1])&B[1])|((lo<<S[1])&~B[1]);
hi = ((hi>>S[1])&B[1])|((hi<<S[1])&~B[1]);
lo = ((lo>>S[2])&B[2])|((lo<<S[2])&~B[2]);
hi = ((hi>>S[2])&B[2])|((hi<<S[2])&~B[2]);
lo = ((lo>>S[3])&B[3])|((lo<<S[3])&~B[3]);
hi = ((hi>>S[3])&B[3])|((hi<<S[3])&~B[3]);
lo = ((lo>>S[4])&B[4])|((lo<<S[4])&~B[4]);
hi = ((hi>>S[4])&B[4])|((hi<<S[4])&~B[4]);
//shift off low bits
i[1] = (hi>>(64-len))|(lo<<(len-32));
i[1] = lo>>(64-len);
}
return i;
}
}