mirror of
https://github.com/claunia/cuetools.net.git
synced 2025-12-16 18:14:25 +00:00
246 lines
6.0 KiB
C#
246 lines
6.0 KiB
C#
|
|
using System;
|
||
|
|
using System.Collections.Generic;
|
||
|
|
using System.Text;
|
||
|
|
|
||
|
|
namespace CUETools.Codecs.FLAKE
|
||
|
|
{
|
||
|
|
class BitReader
|
||
|
|
{
|
||
|
|
byte[] buffer;
|
||
|
|
byte[] byte_to_unary_table;
|
||
|
|
int pos, len;
|
||
|
|
int _bitaccumulator;
|
||
|
|
|
||
|
|
public int Position
|
||
|
|
{
|
||
|
|
get { return pos; }
|
||
|
|
}
|
||
|
|
|
||
|
|
public byte[] Buffer
|
||
|
|
{
|
||
|
|
get
|
||
|
|
{
|
||
|
|
return buffer;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public BitReader(byte[] _buffer, int _pos, int _len)
|
||
|
|
{
|
||
|
|
buffer = _buffer;
|
||
|
|
pos = _pos;
|
||
|
|
len = _len;
|
||
|
|
_bitaccumulator = 0;
|
||
|
|
|
||
|
|
byte_to_unary_table = new byte[] {
|
||
|
|
8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
|
||
|
|
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||
|
|
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||
|
|
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 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, 1, 1,
|
||
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
/* supports reading 1 to 24 bits, in big endian format */
|
||
|
|
public uint readbits_24(int bits)
|
||
|
|
{
|
||
|
|
uint result = (((uint)buffer[pos]) << 24) | (((uint)buffer[pos + 1]) << 16) | (((uint)buffer[pos + 2]) << 8) | ((uint)buffer[pos + 3]);
|
||
|
|
result <<= _bitaccumulator;
|
||
|
|
result >>= 32 - bits;
|
||
|
|
|
||
|
|
int new_accumulator = (_bitaccumulator + bits);
|
||
|
|
pos += (new_accumulator >> 3);
|
||
|
|
_bitaccumulator = (new_accumulator & 7);
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
public uint readbits_8(int bits)
|
||
|
|
{
|
||
|
|
uint result = (((uint)buffer[pos]) << 24) | (((uint)buffer[pos + 1]) << 16);
|
||
|
|
result <<= _bitaccumulator;
|
||
|
|
result >>= 32 - bits;
|
||
|
|
|
||
|
|
int new_accumulator = (_bitaccumulator + bits);
|
||
|
|
pos += (new_accumulator >> 3);
|
||
|
|
_bitaccumulator = (new_accumulator & 7);
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
public uint peekbits_24(int bits)
|
||
|
|
{
|
||
|
|
uint result = (((uint)buffer[pos]) << 24) | (((uint)buffer[pos + 1]) << 16) | (((uint)buffer[pos + 2]) << 8) | ((uint)buffer[pos + 3]);
|
||
|
|
result <<= _bitaccumulator;
|
||
|
|
result >>= 32 - bits;
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
///* supports reading 1 to 16 bits, in big endian format */
|
||
|
|
//private unsafe uint peekbits_9(byte* buff, int pos)
|
||
|
|
//{
|
||
|
|
// uint result = (((uint)buff[pos]) << 8) | (((uint)buff[pos + 1]));
|
||
|
|
// result <<= _bitaccumulator;
|
||
|
|
// result &= 0x0000ffff;
|
||
|
|
// result >>= 7;
|
||
|
|
// return result;
|
||
|
|
//}
|
||
|
|
|
||
|
|
/* supports reading 1 to 16 bits, in big endian format */
|
||
|
|
public void skipbits(int bits)
|
||
|
|
{
|
||
|
|
int new_accumulator = (_bitaccumulator + bits);
|
||
|
|
pos += (new_accumulator >> 3);
|
||
|
|
_bitaccumulator = (new_accumulator & 7);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* supports reading 1 to 32 bits, in big endian format */
|
||
|
|
public uint readbits(int bits)
|
||
|
|
{
|
||
|
|
if (bits <= 24)
|
||
|
|
return readbits_24(bits);
|
||
|
|
|
||
|
|
ulong result = (((ulong)buffer[pos]) << 32) | (((ulong)buffer[pos + 1]) << 24) | (((ulong)buffer[pos + 2]) << 16) | (((ulong)buffer[pos + 3]) << 8) | ((ulong)buffer[pos + 4]);
|
||
|
|
result <<= _bitaccumulator;
|
||
|
|
result &= 0x00ffffffffff;
|
||
|
|
result >>= 40 - bits;
|
||
|
|
int new_accumulator = (_bitaccumulator + bits);
|
||
|
|
pos += (new_accumulator >> 3);
|
||
|
|
_bitaccumulator = (new_accumulator & 7);
|
||
|
|
return (uint)result;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* reads a single bit */
|
||
|
|
public uint readbit()
|
||
|
|
{
|
||
|
|
int new_accumulator;
|
||
|
|
uint result = buffer[pos];
|
||
|
|
result <<= _bitaccumulator;
|
||
|
|
result = result >> 7 & 1;
|
||
|
|
new_accumulator = (_bitaccumulator + 1);
|
||
|
|
pos += (new_accumulator / 8);
|
||
|
|
_bitaccumulator = (new_accumulator % 8);
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
public uint read_unary()
|
||
|
|
{
|
||
|
|
uint val = 0;
|
||
|
|
|
||
|
|
int result = (buffer[pos] << _bitaccumulator) & 0xff;
|
||
|
|
if (result == 0)
|
||
|
|
{
|
||
|
|
val = 8 - (uint)_bitaccumulator;
|
||
|
|
_bitaccumulator = 0;
|
||
|
|
pos++;
|
||
|
|
return val + read_unary();
|
||
|
|
// check eof
|
||
|
|
}
|
||
|
|
|
||
|
|
val = byte_to_unary_table[result];
|
||
|
|
|
||
|
|
int new_accumulator = (_bitaccumulator + (int)val + 1);
|
||
|
|
pos += (new_accumulator / 8);
|
||
|
|
_bitaccumulator = (new_accumulator % 8);
|
||
|
|
return val;
|
||
|
|
}
|
||
|
|
|
||
|
|
public void flush()
|
||
|
|
{
|
||
|
|
if (_bitaccumulator > 0)
|
||
|
|
readbits(8 - _bitaccumulator);
|
||
|
|
}
|
||
|
|
|
||
|
|
public int readbits_signed(int bits)
|
||
|
|
{
|
||
|
|
int val = (int) readbits(bits);
|
||
|
|
val <<= (32 - bits);
|
||
|
|
val >>= (32 - bits);
|
||
|
|
return val;
|
||
|
|
}
|
||
|
|
|
||
|
|
public uint read_utf8()
|
||
|
|
{
|
||
|
|
uint x = readbits(8);
|
||
|
|
uint v;
|
||
|
|
int i;
|
||
|
|
if (0 == (x & 0x80))
|
||
|
|
{
|
||
|
|
v = x;
|
||
|
|
i = 0;
|
||
|
|
}
|
||
|
|
else if (0xC0 == (x & 0xE0)) /* 110xxxxx */
|
||
|
|
{
|
||
|
|
v = x & 0x1F;
|
||
|
|
i = 1;
|
||
|
|
}
|
||
|
|
else if (0xE0 == (x & 0xF0)) /* 1110xxxx */
|
||
|
|
{
|
||
|
|
v = x & 0x0F;
|
||
|
|
i = 2;
|
||
|
|
}
|
||
|
|
else if (0xF0 == (x & 0xF8)) /* 11110xxx */
|
||
|
|
{
|
||
|
|
v = x & 0x07;
|
||
|
|
i = 3;
|
||
|
|
}
|
||
|
|
else if (0xF8 == (x & 0xFC)) /* 111110xx */
|
||
|
|
{
|
||
|
|
v = x & 0x03;
|
||
|
|
i = 4;
|
||
|
|
}
|
||
|
|
else if (0xFC == (x & 0xFE)) /* 1111110x */
|
||
|
|
{
|
||
|
|
v = x & 0x01;
|
||
|
|
i = 5;
|
||
|
|
}
|
||
|
|
else if (0xFE == x) /* 11111110 */
|
||
|
|
{
|
||
|
|
v = 0;
|
||
|
|
i = 6;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
throw new Exception("invalid utf8 encoding");
|
||
|
|
for (; i > 0; i--)
|
||
|
|
{
|
||
|
|
x = readbits(8);
|
||
|
|
if (0x80 != (x & 0xC0)) /* 10xxxxxx */
|
||
|
|
throw new Exception("invalid utf8 encoding");
|
||
|
|
v <<= 6;
|
||
|
|
v |= (x & 0x3F);
|
||
|
|
}
|
||
|
|
return v;
|
||
|
|
}
|
||
|
|
|
||
|
|
public int read_rice_signed(int k)
|
||
|
|
{
|
||
|
|
uint msbs = read_unary();
|
||
|
|
uint lsbs = readbits_24(k);
|
||
|
|
uint uval = (msbs << k) | lsbs;
|
||
|
|
return (int)(uval >> 1 ^ -(int)(uval & 1));
|
||
|
|
}
|
||
|
|
|
||
|
|
public int read_rice_signed8(int k)
|
||
|
|
{
|
||
|
|
uint msbs = read_unary();
|
||
|
|
uint lsbs = readbits_8(k);
|
||
|
|
uint uval = (msbs << k) | lsbs;
|
||
|
|
return (int)(uval >> 1 ^ -(int)(uval & 1));
|
||
|
|
}
|
||
|
|
|
||
|
|
public int read_unary_signed()
|
||
|
|
{
|
||
|
|
uint uval = read_unary();
|
||
|
|
return (int)(uval >> 1 ^ -(int)(uval & 1));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|