mirror of
https://github.com/claunia/cuetools.net.git
synced 2025-12-16 18:14:25 +00:00
180 lines
3.3 KiB
C#
180 lines
3.3 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
|
|
namespace CUETools.Codecs.FLAKE
|
|
{
|
|
class BitWriter
|
|
{
|
|
uint bit_buf;
|
|
int bit_left;
|
|
byte[] buffer;
|
|
int buf_start, buf_ptr, buf_end;
|
|
bool eof;
|
|
|
|
public BitWriter(byte[] buf, int pos, int len)
|
|
{
|
|
buffer = buf;
|
|
buf_start = pos;
|
|
buf_ptr = pos;
|
|
buf_end = pos + len;
|
|
bit_left = 32;
|
|
bit_buf = 0;
|
|
eof = false;
|
|
}
|
|
|
|
public void writebits_signed(int bits, int val)
|
|
{
|
|
writebits(bits, val & ((1 << bits) - 1));
|
|
}
|
|
|
|
public void writebits_signed(uint bits, int val)
|
|
{
|
|
writebits((int) bits, val & ((1 << (int) bits) - 1));
|
|
}
|
|
|
|
public void writebits(int bits, int val)
|
|
{
|
|
writebits(bits, (uint)val);
|
|
}
|
|
|
|
public void writebits64(int bits, ulong val)
|
|
{
|
|
if (bits > 32)
|
|
{
|
|
writebits(bits - 32, (uint)(val >> 32));
|
|
val &= 0xffffffffL;
|
|
bits = 32;
|
|
}
|
|
writebits(bits, (uint)val);
|
|
}
|
|
|
|
public void writebits(int bits, uint val)
|
|
{
|
|
//assert(bits == 32 || val < (1U << bits));
|
|
|
|
if (bits == 0 || eof) return;
|
|
if ((buf_ptr + 3) >= buf_end)
|
|
{
|
|
eof = true;
|
|
return;
|
|
}
|
|
if (bits < bit_left)
|
|
{
|
|
bit_buf = (bit_buf << bits) | val;
|
|
bit_left -= bits;
|
|
}
|
|
else
|
|
{
|
|
uint bb = 0;
|
|
if (bit_left == 32)
|
|
{
|
|
//assert(bits == 32);
|
|
bb = val;
|
|
}
|
|
else
|
|
{
|
|
bb = (bit_buf << bit_left) | (val >> (bits - bit_left));
|
|
bit_left += (32 - bits);
|
|
}
|
|
if (buffer != null)
|
|
{
|
|
buffer[buf_ptr + 3] = (byte)(bb & 0xFF); bb >>= 8;
|
|
buffer[buf_ptr + 2] = (byte)(bb & 0xFF); bb >>= 8;
|
|
buffer[buf_ptr + 1] = (byte)(bb & 0xFF); bb >>= 8;
|
|
buffer[buf_ptr + 0] = (byte)(bb & 0xFF);
|
|
}
|
|
buf_ptr += 4;
|
|
bit_buf = val;
|
|
}
|
|
}
|
|
|
|
public void write_utf8(int val)
|
|
{
|
|
write_utf8((uint)val);
|
|
}
|
|
|
|
public void write_utf8(uint val)
|
|
{
|
|
if (val < 0x80)
|
|
{
|
|
writebits(8, val);
|
|
return;
|
|
}
|
|
int bytes = (Flake.log2i(val) + 4) / 5;
|
|
int shift = (bytes - 1) * 6;
|
|
writebits(8, (256U - (256U >> bytes)) | (val >> shift));
|
|
while (shift >= 6)
|
|
{
|
|
shift -= 6;
|
|
writebits(8, 0x80 | ((val >> shift) & 0x3F));
|
|
}
|
|
}
|
|
|
|
public void write_unary_signed(int val)
|
|
{
|
|
// convert signed to unsigned
|
|
int v = -2 * val - 1;
|
|
v ^= (v >> 31);
|
|
|
|
// write quotient in unary
|
|
int q = v + 1;
|
|
while (q > 31)
|
|
{
|
|
writebits(31, 0);
|
|
q -= 31;
|
|
}
|
|
writebits(q, 1);
|
|
}
|
|
|
|
public void write_rice_signed(int k, int val)
|
|
{
|
|
int v, q;
|
|
|
|
// convert signed to unsigned
|
|
v = -2 * val - 1;
|
|
v ^= (v >> 31);
|
|
|
|
// write quotient in unary
|
|
q = (v >> k) + 1;
|
|
while (q > 31)
|
|
{
|
|
writebits(31, 0);
|
|
q -= 31;
|
|
}
|
|
writebits(q, 1);
|
|
|
|
// write write remainder in binary using 'k' bits
|
|
writebits(k, v & ((1 << k) - 1));
|
|
}
|
|
|
|
public void flush()
|
|
{
|
|
bit_buf <<= bit_left;
|
|
while (bit_left < 32 && !eof)
|
|
{
|
|
if (buf_ptr >= buf_end)
|
|
{
|
|
eof = true;
|
|
break;
|
|
}
|
|
if (buffer != null)
|
|
buffer[buf_ptr] = (byte)(bit_buf >> 24);
|
|
buf_ptr++;
|
|
bit_buf <<= 8;
|
|
bit_left += 8;
|
|
}
|
|
bit_left = 32;
|
|
bit_buf = 0;
|
|
}
|
|
|
|
public int Length
|
|
{
|
|
get
|
|
{
|
|
return buf_ptr - buf_start;
|
|
}
|
|
}
|
|
}
|
|
}
|