/*
* 21.04.2004 Original verion. davagin@udm.ru.
*-----------------------------------------------------------------------
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*----------------------------------------------------------------------
*/
package davaguine.jmac.decoder;
import davaguine.jmac.tools.File;
import java.io.IOException;
/**
* Author: Dmitry Vaguine
* Date: 04.03.2004
* Time: 14:51:31
*/
public class UnBitArray extends UnBitArrayBase {
private final static long RANGE_TOTAL_1[] = {0, 14824, 28224, 39348, 47855, 53994, 58171, 60926, 62682, 63786, 64463, 64878, 65126, 65276, 65365, 65419, 65450, 65469, 65480, 65487, 65491, 65493, 65494, 65495, 65496, 65497, 65498, 65499, 65500, 65501, 65502, 65503, 65504, 65505, 65506, 65507, 65508, 65509, 65510, 65511, 65512, 65513, 65514, 65515, 65516, 65517, 65518, 65519, 65520, 65521, 65522, 65523, 65524, 65525, 65526, 65527, 65528, 65529, 65530, 65531, 65532, 65533, 65534, 65535, 65536};
private final static long RANGE_WIDTH_1[] = {14824, 13400, 11124, 8507, 6139, 4177, 2755, 1756, 1104, 677, 415, 248, 150, 89, 54, 31, 19, 11, 7, 4, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
private final static long RANGE_TOTAL_2[] = {0, 19578, 36160, 48417, 56323, 60899, 63265, 64435, 64971, 65232, 65351, 65416, 65447, 65466, 65476, 65482, 65485, 65488, 65490, 65491, 65492, 65493, 65494, 65495, 65496, 65497, 65498, 65499, 65500, 65501, 65502, 65503, 65504, 65505, 65506, 65507, 65508, 65509, 65510, 65511, 65512, 65513, 65514, 65515, 65516, 65517, 65518, 65519, 65520, 65521, 65522, 65523, 65524, 65525, 65526, 65527, 65528, 65529, 65530, 65531, 65532, 65533, 65534, 65535, 65536};
private final static long RANGE_WIDTH_2[] = {19578, 16582, 12257, 7906, 4576, 2366, 1170, 536, 261, 119, 65, 31, 19, 10, 6, 3, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, };
private final static long K_SUM_MIN_BOUNDARY[] = {0, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304, 8388608, 16777216, 33554432, 67108864, 134217728, 268435456, 536870912, 1073741824, 2147483648L, 0, 0, 0, 0};
private final static long CODE_BITS = 32;
private final static long TOP_VALUE = ((long) 1 << (CODE_BITS - 1));
private final static long EXTRA_BITS = ((CODE_BITS - 2) % 8 + 1);
private final static long BOTTOM_VALUE = (TOP_VALUE >> 8);
private final static int RANGE_OVERFLOW_SHIFT = 16;
private final static int MODEL_ELEMENTS = 64;
//construction/destruction
public UnBitArray(File pIO, int nVersion) {
CreateHelper(pIO, 16384, nVersion);
}
public long DecodeValue(int DecodeMethod, int nParam1, int nParam2) throws IOException {
if (DecodeMethod == DecodeValueMethod.DECODE_VALUE_METHOD_UNSIGNED_INT)
return DecodeValueXBits(32);
return 0;
}
public void GenerateArray(int[] pOutputArray, int nElements) throws IOException {
GenerateArray(pOutputArray, nElements, -1);
}
public void GenerateArray(int[] pOutputArray, int nElements, int nBytesRequired) throws IOException {
GenerateArrayRange(pOutputArray, nElements);
}
public int DecodeValueRange(UnBitArrayState BitArrayState) throws IOException {
// make sure there is room for the data
// this is a little slower than ensuring a huge block to start with, but it's safer
if (m_nCurrentBitIndex > m_nRefillBitThreshold)
FillBitArray();
int nValue = 0;
if (m_nVersion >= 3990) {
// figure the pivot value
int nPivotValue = Math.max(BitArrayState.nKSum / 32, 1);
// get the overflow
int nOverflow = 0;
{
// decode
int nRangeTotal = RangeDecodeFast(RANGE_OVERFLOW_SHIFT);
// lookup the symbol (must be a faster way than this)
long al1[] = RANGE_TOTAL_2;
if (nRangeTotal > 65416) {
int low = 12;
nOverflow = 64;
int mid = 38;
long midVal = al1[38];
do {
if (midVal < nRangeTotal)
low = mid + 1;
else if (midVal > nRangeTotal)
nOverflow = mid - 1;
else {
nOverflow = mid;
break;
}
mid = (low + nOverflow) >> 1;
midVal = al1[mid];
} while (low <= nOverflow);
} else {
nOverflow = 1;
while (nRangeTotal >= al1[nOverflow])
nOverflow++;
nOverflow--;
}
// update
RangeCoderStructDecompress range = m_RangeCoderInfo;
range.low -= range.range * al1[nOverflow];
range.range *= RANGE_WIDTH_2[nOverflow];
// get the working k
if (nOverflow == (MODEL_ELEMENTS - 1)) {
nOverflow = RangeDecodeFastWithUpdate(16);
nOverflow <<= 16;
nOverflow |= RangeDecodeFastWithUpdate(16);
}
}
// get the value
int nBase = 0;
{
if (nPivotValue >= (1 << 16)) {
int nPivotValueBits = 0;
while ((nPivotValue >> nPivotValueBits) > 0) {
nPivotValueBits++;
}
int nSplitFactor = 1 << (nPivotValueBits - 16);
int nPivotValueA = (nPivotValue / nSplitFactor) + 1;
int nPivotValueB = nSplitFactor;
RangeCoderStructDecompress range = m_RangeCoderInfo;
while (range.range <= BOTTOM_VALUE) {
range.buffer = (range.buffer << 8) | ((m_pBitArray[(int) (m_nCurrentBitIndex >> 5)] >> (24 - (m_nCurrentBitIndex & 31))) & 0xFF);
m_nCurrentBitIndex += 8;
range.low = (range.low << 8) | ((range.buffer >> 1) & 0xFF);
range.range <<= 8;
}
range.range = range.range / nPivotValueA;
int nBaseA = (int) (range.low / range.range);
range.low -= range.range * nBaseA;
while (range.range <= BOTTOM_VALUE) {
range.buffer = (range.buffer << 8) | ((m_pBitArray[(int) (m_nCurrentBitIndex >> 5)] >> (24 - (m_nCurrentBitIndex & 31))) & 0xFF);
m_nCurrentBitIndex += 8;
range.low = (range.low << 8) | ((range.buffer >> 1) & 0xFF);
range.range <<= 8;
}
range.range = range.range / nPivotValueB;
int nBaseB = (int) (range.low / range.range);
range.low -= range.range * nBaseB;
nBase = nBaseA * nSplitFactor + nBaseB;
} else {
RangeCoderStructDecompress range = m_RangeCoderInfo;
while (range.range <= BOTTOM_VALUE) {
range.buffer = (range.buffer << 8) | ((m_pBitArray[(int) (m_nCurrentBitIndex >> 5)] >> (24 - (m_nCurrentBitIndex & 31))) & 0xFF);
m_nCurrentBitIndex += 8;
range.low = (range.low << 8) | ((range.buffer >> 1) & 0xFF);
range.range <<= 8;
}
// decode
range.range = range.range / nPivotValue;
int nBaseLower = (int) (range.low / range.range);
range.low -= range.range * nBaseLower;
nBase = nBaseLower;
}
}
// build the value
nValue = nBase + (nOverflow * nPivotValue);
} else {
// decode
int nRangeTotal = RangeDecodeFast(RANGE_OVERFLOW_SHIFT);
// lookup the symbol (must be a faster way than this)
long al1[] = RANGE_TOTAL_1;
int nOverflow;
if (nRangeTotal > 64878) {
int low = 12;
nOverflow = 64;
int mid = 38;
long midVal = al1[38];
do {
if (midVal < nRangeTotal)
low = mid + 1;
else if (midVal > nRangeTotal)
nOverflow = mid - 1;
else {
nOverflow = mid;
break;
}
mid = (low + nOverflow) >> 1;
midVal = al1[mid];
} while (low <= nOverflow);
} else {
nOverflow = 1;
while (nRangeTotal >= al1[nOverflow])
nOverflow++;
nOverflow--;
}
// update
RangeCoderStructDecompress range = m_RangeCoderInfo;
range.low -= range.range * al1[nOverflow];
range.range *= RANGE_WIDTH_1[nOverflow];
// get the working k
int nTempK;
if (nOverflow == (MODEL_ELEMENTS - 1)) {
nTempK = RangeDecodeFastWithUpdate(5);
nOverflow = 0;
} else
nTempK = (BitArrayState.k < 1) ? 0 : BitArrayState.k - 1;
// figure the extra bits on the left and the left value
if (nTempK <= 16 || m_nVersion < 3910)
nValue = RangeDecodeFastWithUpdate(nTempK);
else {
int nX1 = RangeDecodeFastWithUpdate(16);
int nX2 = RangeDecodeFastWithUpdate(nTempK - 16);
nValue = nX1 | (nX2 << 16);
}
// build the value and output it
nValue += (nOverflow << nTempK);
}
// update nKSum
BitArrayState.nKSum += ((nValue + 1) / 2) - ((BitArrayState.nKSum + 16) >> 5);
// update k
if (BitArrayState.nKSum < K_SUM_MIN_BOUNDARY[BitArrayState.k])
BitArrayState.k--;
else if (BitArrayState.nKSum >= K_SUM_MIN_BOUNDARY[BitArrayState.k + 1])
BitArrayState.k++;
// output the value (converted to signed)
return (nValue & 1) > 0 ? (nValue >> 1) + 1 : -(nValue >> 1);
}
public void FlushState(UnBitArrayState BitArrayState) {
BitArrayState.k = 10;
BitArrayState.nKSum = (1 << BitArrayState.k) * 16;
}
public void FlushBitArray() {
AdvanceToByteBoundary();
RangeCoderStructDecompress struct = m_RangeCoderInfo;
m_nCurrentBitIndex += 8; // ignore the first byte... (slows compression too much to not output this dummy byte)
struct.buffer = GetC();
struct.low = struct.buffer >> (8 - EXTRA_BITS);
struct.range = (long) 1 << EXTRA_BITS;
m_nRefillBitThreshold = (m_nBits - 512);
}
public void Finalize() {
RangeCoderStructDecompress struct = m_RangeCoderInfo;
long i = m_nCurrentBitIndex;
long range = struct.range;
// normalize
while (range <= BOTTOM_VALUE) {
i += 8;
range <<= 8;
}
// used to back-pedal the last two bytes out
// this should never have been a problem because we've outputted and normalized beforehand
// but stopped doing it as of 3.96 in case it accounted for rare decompression failures
if (m_nVersion <= 3950)
i -= 16;
m_nCurrentBitIndex = i;
struct.range = range;
}
private UnBitArrayState GenerateArrayRangeBitArrayState = new UnBitArrayState();
private void GenerateArrayRange(int[] pOutputArray, int nElements) throws IOException {
FlushState(GenerateArrayRangeBitArrayState);
FlushBitArray();
for (int z = 0; z < nElements; z++)
pOutputArray[z] = DecodeValueRange(GenerateArrayRangeBitArrayState);
Finalize();
}
private RangeCoderStructDecompress m_RangeCoderInfo = new RangeCoderStructDecompress();
private long m_nRefillBitThreshold;
//functions
private final int RangeDecodeFast(int nShift) {
RangeCoderStructDecompress struct = m_RangeCoderInfo;
long a1[] = m_pBitArray;
long i = m_nCurrentBitIndex;
long buffer = struct.buffer;
long low = struct.low;
long range = struct.range;
while (range <= BOTTOM_VALUE) {
buffer = (buffer << 8) | ((a1[(int) (i >> 5)] >> (24 - (i & 31))) & 0xFF);
i += 8;
low = (low << 8) | ((buffer >> 1) & 0xFF);
range <<= 8;
}
m_nCurrentBitIndex = i;
struct.low = low;
struct.buffer = buffer;
// decode
range >>= nShift;
struct.range = range;
return (int) (low / range);
}
private final int RangeDecodeFastWithUpdate(int nShift) {
RangeCoderStructDecompress struct = m_RangeCoderInfo;
long a1[] = m_pBitArray;
long i = m_nCurrentBitIndex;
long buffer = struct.buffer;
long low = struct.low;
long range = struct.range;
while (range <= BOTTOM_VALUE) {
buffer = (buffer << 8L) | ((a1[(int) (i >> 5)] >> (24 - (i & 31))) & 0xFF);
i += 8;
low = (low << 8) | ((buffer >> 1) & 0xFF);
range <<= 8;
}
m_nCurrentBitIndex = i;
// decode
range >>= nShift;
int nRetVal = (int) (low / range);
low -= range * nRetVal;
struct.range = range;
struct.low = low;
struct.buffer = buffer;
return nRetVal;
}
private final short GetC() {
long l = m_nCurrentBitIndex;
short nValue = (short) (m_pBitArray[(int) (l >> 5)] >> (24 - (l & 31)));
m_nCurrentBitIndex = l + 8;
return nValue;
}
}