mirror of
https://github.com/claunia/cuetools.net.git
synced 2025-12-16 18:14:25 +00:00
Managed FLAC encoder/decoder based on Flake, initial revision
This commit is contained in:
154
CUETools.Codecs.FLAKE/BitWriter.cs
Normal file
154
CUETools.Codecs.FLAKE/BitWriter.cs
Normal file
@@ -0,0 +1,154 @@
|
||||
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 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_rice_signed(int k, int val)
|
||||
{
|
||||
int v, q;
|
||||
|
||||
if (k < 0) return;
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user