mirror of
https://github.com/claunia/cuetools.net.git
synced 2025-12-16 18:14:25 +00:00
cleanup, optimizations
This commit is contained in:
@@ -4,34 +4,15 @@ using System.Text;
|
|||||||
|
|
||||||
namespace CUETools.Codecs.FLAKE
|
namespace CUETools.Codecs.FLAKE
|
||||||
{
|
{
|
||||||
class BitReader
|
unsafe class BitReader
|
||||||
{
|
{
|
||||||
byte[] buffer;
|
byte* buffer;
|
||||||
byte[] byte_to_unary_table;
|
|
||||||
int pos, len;
|
int pos, len;
|
||||||
int _bitaccumulator;
|
int _bitaccumulator;
|
||||||
|
uint cache;
|
||||||
|
|
||||||
public int Position
|
static readonly byte[] byte_to_unary_table = new byte[]
|
||||||
{
|
{
|
||||||
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,
|
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,
|
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,
|
||||||
@@ -49,85 +30,107 @@ namespace CUETools.Codecs.FLAKE
|
|||||||
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
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public int Position
|
||||||
|
{
|
||||||
|
get { return pos; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/* supports reading 1 to 24 bits, in big endian format */
|
public byte* Buffer
|
||||||
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]);
|
get
|
||||||
result <<= _bitaccumulator;
|
{
|
||||||
result >>= 32 - bits;
|
return buffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int new_accumulator = (_bitaccumulator + bits);
|
public BitReader(byte* _buffer, int _pos, int _len)
|
||||||
pos += (new_accumulator >> 3);
|
{
|
||||||
_bitaccumulator = (new_accumulator & 7);
|
buffer = _buffer;
|
||||||
|
pos = _pos;
|
||||||
|
len = _len;
|
||||||
|
_bitaccumulator = 0;
|
||||||
|
cache = peek4();
|
||||||
|
}
|
||||||
|
|
||||||
|
public uint peek4()
|
||||||
|
{
|
||||||
|
//uint result = ((((uint)buffer[pos]) << 24) | (((uint)buffer[pos + 1]) << 16) | (((uint)buffer[pos + 2]) << 8) | ((uint)buffer[pos + 3])) << _bitaccumulator;
|
||||||
|
byte* b = buffer + pos;
|
||||||
|
uint result = *(b++);
|
||||||
|
result = (result << 8) + *(b++);
|
||||||
|
result = (result << 8) + *(b++);
|
||||||
|
result = (result << 8) + *(b++);
|
||||||
|
result <<= _bitaccumulator;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint readbits_8(int bits)
|
/* skip any number of 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)
|
public void skipbits(int bits)
|
||||||
{
|
{
|
||||||
int new_accumulator = (_bitaccumulator + bits);
|
int new_accumulator = (_bitaccumulator + bits);
|
||||||
pos += (new_accumulator >> 3);
|
pos += (new_accumulator >> 3);
|
||||||
_bitaccumulator = (new_accumulator & 7);
|
_bitaccumulator = (new_accumulator & 7);
|
||||||
|
cache = peek4();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* skip up to 8 bits */
|
||||||
|
public void skipbits8(int bits)
|
||||||
|
{
|
||||||
|
cache <<= bits;
|
||||||
|
int new_accumulator = (_bitaccumulator + bits);
|
||||||
|
pos += (new_accumulator >> 3);
|
||||||
|
_bitaccumulator = (new_accumulator & 7);
|
||||||
|
cache |= ((uint)buffer[pos + 3] << _bitaccumulator);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* supports reading 1 to 24 bits, in big endian format */
|
||||||
|
public uint readbits24(int bits)
|
||||||
|
{
|
||||||
|
//uint result = peek4() >> (32 - bits);
|
||||||
|
uint result = cache >> (32 - bits);
|
||||||
|
skipbits(bits);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public uint peekbits24(int bits)
|
||||||
|
{
|
||||||
|
return cache >> 32 - bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* supports reading 1 to 32 bits, in big endian format */
|
/* supports reading 1 to 32 bits, in big endian format */
|
||||||
public uint readbits(int bits)
|
public uint readbits(int bits)
|
||||||
{
|
{
|
||||||
|
uint result = cache >> 32 - bits;
|
||||||
if (bits <= 24)
|
if (bits <= 24)
|
||||||
return readbits_24(bits);
|
{
|
||||||
|
skipbits(bits);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
skipbits(24);
|
||||||
|
result |= cache >> 56 - bits;
|
||||||
|
skipbits(bits - 24);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
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]);
|
public ulong readbits64(int bits)
|
||||||
result <<= _bitaccumulator;
|
{
|
||||||
result &= 0x00ffffffffff;
|
if (bits <= 24)
|
||||||
result >>= 40 - bits;
|
return readbits24(bits);
|
||||||
int new_accumulator = (_bitaccumulator + bits);
|
ulong result = readbits24(24);
|
||||||
pos += (new_accumulator >> 3);
|
bits -= 24;
|
||||||
_bitaccumulator = (new_accumulator & 7);
|
if (bits <= 24)
|
||||||
return (uint)result;
|
return (result << bits) | readbits24(bits);
|
||||||
|
result = (result << 24) | readbits24(24);
|
||||||
|
bits -= 24;
|
||||||
|
return (result << bits) | readbits24(bits);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* reads a single bit */
|
/* reads a single bit */
|
||||||
public uint readbit()
|
public uint readbit()
|
||||||
{
|
{
|
||||||
int new_accumulator;
|
uint result = cache >> 31;
|
||||||
uint result = buffer[pos];
|
skipbits8(1);
|
||||||
result <<= _bitaccumulator;
|
|
||||||
result = result >> 7 & 1;
|
|
||||||
new_accumulator = (_bitaccumulator + 1);
|
|
||||||
pos += (new_accumulator / 8);
|
|
||||||
_bitaccumulator = (new_accumulator % 8);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,28 +138,23 @@ namespace CUETools.Codecs.FLAKE
|
|||||||
{
|
{
|
||||||
uint val = 0;
|
uint val = 0;
|
||||||
|
|
||||||
int result = (buffer[pos] << _bitaccumulator) & 0xff;
|
uint result = cache >> 24;
|
||||||
if (result == 0)
|
while (result == 0)
|
||||||
{
|
{
|
||||||
val = 8 - (uint)_bitaccumulator;
|
val += 8;
|
||||||
_bitaccumulator = 0;
|
skipbits8(8);
|
||||||
pos++;
|
result = cache >> 24;
|
||||||
return val + read_unary();
|
|
||||||
// check eof
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val = byte_to_unary_table[result];
|
val += byte_to_unary_table[result];
|
||||||
|
skipbits8((int)(val & 7) + 1);
|
||||||
int new_accumulator = (_bitaccumulator + (int)val + 1);
|
|
||||||
pos += (new_accumulator / 8);
|
|
||||||
_bitaccumulator = (new_accumulator % 8);
|
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void flush()
|
public void flush()
|
||||||
{
|
{
|
||||||
if (_bitaccumulator > 0)
|
if (_bitaccumulator > 0)
|
||||||
readbits(8 - _bitaccumulator);
|
skipbits8(8 - _bitaccumulator);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int readbits_signed(int bits)
|
public int readbits_signed(int bits)
|
||||||
@@ -223,15 +221,7 @@ namespace CUETools.Codecs.FLAKE
|
|||||||
public int read_rice_signed(int k)
|
public int read_rice_signed(int k)
|
||||||
{
|
{
|
||||||
uint msbs = read_unary();
|
uint msbs = read_unary();
|
||||||
uint lsbs = readbits_24(k);
|
uint lsbs = readbits24(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;
|
uint uval = (msbs << k) | lsbs;
|
||||||
return (int)(uval >> 1 ^ -(int)(uval & 1));
|
return (int)(uval >> 1 ^ -(int)(uval & 1));
|
||||||
}
|
}
|
||||||
@@ -241,5 +231,49 @@ namespace CUETools.Codecs.FLAKE
|
|||||||
uint uval = read_unary();
|
uint uval = read_unary();
|
||||||
return (int)(uval >> 1 ^ -(int)(uval & 1));
|
return (int)(uval >> 1 ^ -(int)(uval & 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void read_rice_block(int n, int k, int* r)
|
||||||
|
{
|
||||||
|
fixed (byte* unary_table = byte_to_unary_table)
|
||||||
|
{
|
||||||
|
if (k == 0)
|
||||||
|
for (int i = n; i > 0; i--)
|
||||||
|
*(r++) = read_unary_signed();
|
||||||
|
else if (k <= 8)
|
||||||
|
for (int i = n; i > 0; i--)
|
||||||
|
{
|
||||||
|
//*(r++) = read_rice_signed((int)k);
|
||||||
|
uint bits = unary_table[cache >> 24];
|
||||||
|
uint msbs = bits;
|
||||||
|
while (bits == 8)
|
||||||
|
{
|
||||||
|
skipbits8(8);
|
||||||
|
bits = unary_table[cache >> 24];
|
||||||
|
msbs += bits;
|
||||||
|
}
|
||||||
|
skipbits8((int)(msbs & 7) + 1);
|
||||||
|
uint uval = (msbs << k) | (cache >> (32 - k));
|
||||||
|
skipbits8(k);
|
||||||
|
*(r++) = (int)(uval >> 1 ^ -(int)(uval & 1));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
for (int i = n; i > 0; i--)
|
||||||
|
{
|
||||||
|
//*(r++) = read_rice_signed((int)k);
|
||||||
|
uint bits = unary_table[cache >> 24];
|
||||||
|
uint msbs = bits;
|
||||||
|
while (bits == 8)
|
||||||
|
{
|
||||||
|
skipbits8(8);
|
||||||
|
bits = unary_table[cache >> 24];
|
||||||
|
msbs += bits;
|
||||||
|
}
|
||||||
|
skipbits8((int)(msbs & 7) + 1);
|
||||||
|
uint uval = (msbs << k) | (cache >> (32 - k));
|
||||||
|
skipbits(k);
|
||||||
|
*(r++) = (int)(uval >> 1 ^ -(int)(uval & 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,15 @@ namespace CUETools.Codecs.FLAKE
|
|||||||
public const int MAX_RICE_PARAM = 14;
|
public const int MAX_RICE_PARAM = 14;
|
||||||
public const int MAX_PARTITION_ORDER = 8;
|
public const int MAX_PARTITION_ORDER = 8;
|
||||||
public const int MAX_PARTITIONS = 1 << MAX_PARTITION_ORDER;
|
public const int MAX_PARTITIONS = 1 << MAX_PARTITION_ORDER;
|
||||||
|
|
||||||
|
public static readonly int[] flac_samplerates = new int[16] {
|
||||||
|
0, 0, 0, 0,
|
||||||
|
8000, 16000, 22050, 24000, 32000, 44100, 48000, 96000,
|
||||||
|
0, 0, 0, 0
|
||||||
|
};
|
||||||
|
public static readonly int[] flac_blocksizes = new int[15] { 0, 192, 576, 1152, 2304, 4608, 0, 0, 256, 512, 1024, 2048, 4096, 8192, 16384 };
|
||||||
|
public static readonly int[] flac_bitdepths = new int[8] { 0, 8, 12, 0, 16, 20, 24, 0 };
|
||||||
|
|
||||||
public static int log2i(int v)
|
public static int log2i(int v)
|
||||||
{
|
{
|
||||||
return log2i((uint)v);
|
return log2i((uint)v);
|
||||||
@@ -97,17 +106,30 @@ namespace CUETools.Codecs.FLAKE
|
|||||||
for (int i = n; i > 0; i--)
|
for (int i = n; i > 0; i--)
|
||||||
*(res++) = *(smp++);
|
*(res++) = *(smp++);
|
||||||
}
|
}
|
||||||
|
unsafe public static void memcpy(byte* res, byte* smp, int n)
|
||||||
|
{
|
||||||
|
for (int i = n; i > 0; i--)
|
||||||
|
*(res++) = *(smp++);
|
||||||
|
}
|
||||||
unsafe public static void memset(int* res, int smp, int n)
|
unsafe public static void memset(int* res, int smp, int n)
|
||||||
{
|
{
|
||||||
for (int i = n; i > 0; i--)
|
for (int i = n; i > 0; i--)
|
||||||
*(res++) = smp;
|
*(res++) = smp;
|
||||||
}
|
}
|
||||||
|
unsafe public static void interlace(int* res, int* src1, int* src2, int n)
|
||||||
|
{
|
||||||
|
for (int i = n; i > 0; i--)
|
||||||
|
{
|
||||||
|
*(res++) = *(src1++);
|
||||||
|
*(res++) = *(src2++);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe struct RiceContext
|
unsafe struct RiceContext
|
||||||
{
|
{
|
||||||
public int porder; /* partition order */
|
public int porder; /* partition order */
|
||||||
public fixed uint rparams[Flake.MAX_PARTITIONS]; /* Rice parameters */
|
public fixed int rparams[Flake.MAX_PARTITIONS]; /* Rice parameters */
|
||||||
public fixed int esc_bps[Flake.MAX_PARTITIONS]; /* bps if using escape code */
|
public fixed int esc_bps[Flake.MAX_PARTITIONS]; /* bps if using escape code */
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -214,6 +236,13 @@ namespace CUETools.Codecs.FLAKE
|
|||||||
Flattop = 8
|
Flattop = 8
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public struct SeekPoint
|
||||||
|
{
|
||||||
|
public ulong number;
|
||||||
|
public ulong offset;
|
||||||
|
public uint framesize;
|
||||||
|
}
|
||||||
|
|
||||||
public enum MetadataType
|
public enum MetadataType
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -227,22 +256,34 @@ namespace CUETools.Codecs.FLAKE
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
FLAC__METADATA_TYPE_PADDING = 1,
|
FLAC__METADATA_TYPE_PADDING = 1,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <A HREF="../format.html#metadata_block_application">APPLICATION</A> block
|
||||||
|
/// </summary>
|
||||||
FLAC__METADATA_TYPE_APPLICATION = 2,
|
FLAC__METADATA_TYPE_APPLICATION = 2,
|
||||||
/**< <A HREF="../format.html#metadata_block_application">APPLICATION</A> block */
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <A HREF="../format.html#metadata_block_seektable">SEEKTABLE</A> block
|
||||||
|
/// </summary>
|
||||||
FLAC__METADATA_TYPE_SEEKTABLE = 3,
|
FLAC__METADATA_TYPE_SEEKTABLE = 3,
|
||||||
/**< <A HREF="../format.html#metadata_block_seektable">SEEKTABLE</A> block */
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <A HREF="../format.html#metadata_block_vorbis_comment">VORBISCOMMENT</A> block (a.k.a. FLAC tags)
|
||||||
|
/// </summary>
|
||||||
FLAC__METADATA_TYPE_VORBIS_COMMENT = 4,
|
FLAC__METADATA_TYPE_VORBIS_COMMENT = 4,
|
||||||
/**< <A HREF="../format.html#metadata_block_vorbis_comment">VORBISCOMMENT</A> block (a.k.a. FLAC tags) */
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <A HREF="../format.html#metadata_block_cuesheet">CUESHEET</A> block
|
||||||
|
/// </summary>
|
||||||
FLAC__METADATA_TYPE_CUESHEET = 5,
|
FLAC__METADATA_TYPE_CUESHEET = 5,
|
||||||
/**< <A HREF="../format.html#metadata_block_cuesheet">CUESHEET</A> block */
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <A HREF="../format.html#metadata_block_picture">PICTURE</A> block
|
||||||
|
/// </summary>
|
||||||
FLAC__METADATA_TYPE_PICTURE = 6,
|
FLAC__METADATA_TYPE_PICTURE = 6,
|
||||||
/**< <A HREF="../format.html#metadata_block_picture">PICTURE</A> block */
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// marker to denote beginning of undefined type range; this number will increase as new metadata types are added
|
||||||
|
/// </summary>
|
||||||
FLAC__METADATA_TYPE_UNDEFINED = 7
|
FLAC__METADATA_TYPE_UNDEFINED = 7
|
||||||
/**< marker to denote beginning of undefined type range; this number will increase as new metadata types are added */
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,14 +7,14 @@ namespace CUETools.Codecs.FLAKE
|
|||||||
{
|
{
|
||||||
public class FlakeReader: IAudioSource
|
public class FlakeReader: IAudioSource
|
||||||
{
|
{
|
||||||
int[] flac_blocksizes;
|
|
||||||
int[] flac_bitdepths;
|
|
||||||
|
|
||||||
int[] samplesBuffer;
|
int[] samplesBuffer;
|
||||||
int[] residualBuffer;
|
int[] residualBuffer;
|
||||||
|
|
||||||
byte[] _framesBuffer;
|
byte[] _framesBuffer;
|
||||||
int _framesBufferLength = 0, _framesBufferOffset = 0;
|
int _framesBufferLength = 0, _framesBufferOffset = 0;
|
||||||
|
long first_frame_offset;
|
||||||
|
|
||||||
|
SeekPoint[] seek_table;
|
||||||
|
|
||||||
Crc8 crc8;
|
Crc8 crc8;
|
||||||
Crc16 crc16;
|
Crc16 crc16;
|
||||||
@@ -45,22 +45,19 @@ namespace CUETools.Codecs.FLAKE
|
|||||||
public FlakeReader(string path, Stream IO)
|
public FlakeReader(string path, Stream IO)
|
||||||
{
|
{
|
||||||
_path = path;
|
_path = path;
|
||||||
_IO = IO != null ? IO : new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read);
|
_IO = IO != null ? IO : new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, 0x10000);
|
||||||
|
|
||||||
flac_bitdepths = new int[8] { 0, 8, 12, 0, 16, 20, 24, 0 };
|
|
||||||
flac_blocksizes = new int[15] { 0, 192, 576, 1152, 2304, 4608, 0, 0, 256, 512, 1024, 2048, 4096, 8192, 16384 };
|
|
||||||
|
|
||||||
crc8 = new Crc8();
|
crc8 = new Crc8();
|
||||||
crc16 = new Crc16();
|
crc16 = new Crc16();
|
||||||
|
|
||||||
_framesBuffer = new byte[0x10000];
|
_framesBuffer = new byte[0x20000];
|
||||||
decode_metadata();
|
decode_metadata();
|
||||||
|
|
||||||
//max_frame_size = 16 + ((Flake.MAX_BLOCKSIZE * (int)(bits_per_sample * channels + 1) + 7) >> 3);
|
//max_frame_size = 16 + ((Flake.MAX_BLOCKSIZE * (int)(bits_per_sample * channels + 1) + 7) >> 3);
|
||||||
if (max_frame_size * 2 > _framesBuffer.Length)
|
if (((int)max_frame_size * (int)bits_per_sample * channels * 2 >> 3) > _framesBuffer.Length)
|
||||||
{
|
{
|
||||||
byte[] temp = _framesBuffer;
|
byte[] temp = _framesBuffer;
|
||||||
_framesBuffer = new byte[max_frame_size * 2];
|
_framesBuffer = new byte[((int)max_frame_size * (int)bits_per_sample * channels * 2 >> 3)];
|
||||||
if (_framesBufferLength > 0)
|
if (_framesBufferLength > 0)
|
||||||
Array.Copy(temp, _framesBufferOffset, _framesBuffer, 0, _framesBufferLength);
|
Array.Copy(temp, _framesBufferOffset, _framesBuffer, 0, _framesBufferLength);
|
||||||
_framesBufferOffset = 0;
|
_framesBufferOffset = 0;
|
||||||
@@ -76,9 +73,6 @@ namespace CUETools.Codecs.FLAKE
|
|||||||
|
|
||||||
public FlakeReader(int _channels, uint _bits_per_sample)
|
public FlakeReader(int _channels, uint _bits_per_sample)
|
||||||
{
|
{
|
||||||
flac_bitdepths = new int[8] { 0, 8, 12, 0, 16, 20, 24, 0 };
|
|
||||||
flac_blocksizes = new int[15] { 0, 192, 576, 1152, 2304, 4608, 0, 0, 256, 512, 1024, 2048, 4096, 8192, 16384 };
|
|
||||||
|
|
||||||
crc8 = new Crc8();
|
crc8 = new Crc8();
|
||||||
crc16 = new Crc16();
|
crc16 = new Crc16();
|
||||||
|
|
||||||
@@ -110,7 +104,7 @@ namespace CUETools.Codecs.FLAKE
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return _sampleCount - _sampleOffset + _samplesInBuffer;
|
return Length - Position;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,7 +116,33 @@ namespace CUETools.Codecs.FLAKE
|
|||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
throw new Exception("seeking not yet supported");
|
if (value > _sampleCount)
|
||||||
|
throw new Exception("seeking past end of stream");
|
||||||
|
if (value < Position)
|
||||||
|
throw new Exception("backwards seeking not yet supported");
|
||||||
|
if (seek_table != null)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
while (value > _sampleOffset)
|
||||||
|
{
|
||||||
|
_samplesInBuffer = 0;
|
||||||
|
_samplesBufferOffset = 0;
|
||||||
|
|
||||||
|
fill_frames_buffer();
|
||||||
|
if (_framesBufferLength == 0)
|
||||||
|
throw new Exception("seek failed");
|
||||||
|
|
||||||
|
int bytesDecoded = DecodeFrame(_framesBuffer, _framesBufferOffset, _framesBufferLength);
|
||||||
|
_framesBufferLength -= bytesDecoded;
|
||||||
|
_framesBufferOffset += bytesDecoded;
|
||||||
|
|
||||||
|
_sampleOffset += _samplesInBuffer;
|
||||||
|
};
|
||||||
|
uint diff = _samplesInBuffer - (uint)(_sampleOffset - value);
|
||||||
|
_samplesInBuffer -= diff;
|
||||||
|
_samplesBufferOffset += diff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,11 +178,23 @@ namespace CUETools.Codecs.FLAKE
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void interlace(int [,] buff, int offset, int count)
|
unsafe void interlace(int [,] buff, int offset, int count)
|
||||||
|
{
|
||||||
|
if (channels == 2)
|
||||||
|
{
|
||||||
|
fixed (int* res = &buff[offset, 0], src = &samplesBuffer[_samplesBufferOffset])
|
||||||
|
Flake.interlace(res, src, src + Flake.MAX_BLOCKSIZE, count);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
for (int ch = 0; ch < channels; ch++)
|
for (int ch = 0; ch < channels; ch++)
|
||||||
|
fixed (int* res = &buff[offset, ch], src = &samplesBuffer[_samplesBufferOffset + ch * Flake.MAX_BLOCKSIZE])
|
||||||
|
{
|
||||||
|
int* psrc = src;
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
buff[offset + i, ch] = samplesBuffer[_samplesBufferOffset + i + ch * Flake.MAX_BLOCKSIZE];
|
res[i + i] = *(psrc++);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint Read(int[,] buff, uint sampleCount)
|
public uint Read(int[,] buff, uint sampleCount)
|
||||||
@@ -201,13 +233,14 @@ namespace CUETools.Codecs.FLAKE
|
|||||||
return (uint)offset + sampleCount;
|
return (uint)offset + sampleCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
void fill_frames_buffer()
|
unsafe void fill_frames_buffer()
|
||||||
{
|
{
|
||||||
if (_framesBufferLength == 0)
|
if (_framesBufferLength == 0)
|
||||||
_framesBufferOffset = 0;
|
_framesBufferOffset = 0;
|
||||||
else if (_framesBufferLength < _framesBuffer.Length / 2 && _framesBufferOffset >= _framesBuffer.Length / 2)
|
else if (_framesBufferLength < _framesBuffer.Length / 2 && _framesBufferOffset >= _framesBuffer.Length / 2)
|
||||||
{
|
{
|
||||||
Array.Copy(_framesBuffer, _framesBufferOffset, _framesBuffer, 0, _framesBufferLength);
|
fixed (byte* buff = _framesBuffer)
|
||||||
|
Flake.memcpy(buff, buff + _framesBufferOffset, _framesBufferLength);
|
||||||
_framesBufferOffset = 0;
|
_framesBufferOffset = 0;
|
||||||
}
|
}
|
||||||
while (_framesBufferLength < _framesBuffer.Length / 2)
|
while (_framesBufferLength < _framesBuffer.Length / 2)
|
||||||
@@ -230,7 +263,7 @@ namespace CUETools.Codecs.FLAKE
|
|||||||
uint sr_code0 = bitreader.readbits(4);
|
uint sr_code0 = bitreader.readbits(4);
|
||||||
frame->ch_mode = (ChannelMode)bitreader.readbits(4);
|
frame->ch_mode = (ChannelMode)bitreader.readbits(4);
|
||||||
uint bps_code = bitreader.readbits(3);
|
uint bps_code = bitreader.readbits(3);
|
||||||
if (flac_bitdepths[bps_code] != bits_per_sample)
|
if (Flake.flac_bitdepths[bps_code] != bits_per_sample)
|
||||||
throw new Exception("unsupported bps coding");
|
throw new Exception("unsupported bps coding");
|
||||||
uint t1 = bitreader.readbit(); // == 0?????
|
uint t1 = bitreader.readbit(); // == 0?????
|
||||||
if (t1 != 0)
|
if (t1 != 0)
|
||||||
@@ -249,7 +282,7 @@ namespace CUETools.Codecs.FLAKE
|
|||||||
frame->blocksize = frame->bs_code1 + 1;
|
frame->blocksize = frame->bs_code1 + 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
frame->blocksize = flac_blocksizes[frame->bs_code0];
|
frame->blocksize = Flake.flac_blocksizes[frame->bs_code0];
|
||||||
|
|
||||||
// custom sample rate
|
// custom sample rate
|
||||||
if (sr_code0 < 4 || sr_code0 > 11)
|
if (sr_code0 < 4 || sr_code0 > 11)
|
||||||
@@ -294,7 +327,7 @@ namespace CUETools.Codecs.FLAKE
|
|||||||
{
|
{
|
||||||
// rice-encoded block
|
// rice-encoded block
|
||||||
uint coding_method = bitreader.readbits(2); // ????? == 0
|
uint coding_method = bitreader.readbits(2); // ????? == 0
|
||||||
if (coding_method != 0) // if 1, then parameter length == 5 bits instead of 4
|
if (coding_method != 0 && coding_method != 1) // if 1, then parameter length == 5 bits instead of 4
|
||||||
throw new Exception("unsupported residual coding");
|
throw new Exception("unsupported residual coding");
|
||||||
// partition order
|
// partition order
|
||||||
frame->subframes[ch].rc.porder = (int)bitreader.readbits(4);
|
frame->subframes[ch].rc.porder = (int)bitreader.readbits(4);
|
||||||
@@ -303,23 +336,27 @@ namespace CUETools.Codecs.FLAKE
|
|||||||
int psize = frame->blocksize >> frame->subframes[ch].rc.porder;
|
int psize = frame->blocksize >> frame->subframes[ch].rc.porder;
|
||||||
int res_cnt = psize - frame->subframes[ch].order;
|
int res_cnt = psize - frame->subframes[ch].order;
|
||||||
|
|
||||||
|
int rice_len = 4 + (int)coding_method;
|
||||||
// residual
|
// residual
|
||||||
int j = frame->subframes[ch].order;
|
int j = frame->subframes[ch].order;
|
||||||
int* r = frame->subframes[ch].residual + j;
|
int* r = frame->subframes[ch].residual + j;
|
||||||
for (int p = 0; p < (1 << frame->subframes[ch].rc.porder); p++)
|
for (int p = 0; p < (1 << frame->subframes[ch].rc.porder); p++)
|
||||||
{
|
{
|
||||||
uint k = frame->subframes[ch].rc.rparams[p] = bitreader.readbits(4);
|
|
||||||
if (p == 1) res_cnt = psize;
|
if (p == 1) res_cnt = psize;
|
||||||
int n = Math.Min(res_cnt, frame->blocksize - j);
|
int n = Math.Min(res_cnt, frame->blocksize - j);
|
||||||
if (k == 0)
|
|
||||||
|
int k = frame->subframes[ch].rc.rparams[p] = (int)bitreader.readbits(rice_len);
|
||||||
|
if (k == (1 << rice_len) - 1)
|
||||||
|
{
|
||||||
|
k = frame->subframes[ch].rc.esc_bps[p] = (int)bitreader.readbits(5);
|
||||||
for (int i = n; i > 0; i--)
|
for (int i = n; i > 0; i--)
|
||||||
*(r++) = bitreader.read_unary_signed();
|
*(r++) = bitreader.readbits_signed((int)k);
|
||||||
else if (k <= 8)
|
}
|
||||||
for (int i = n; i > 0; i--)
|
|
||||||
*(r++) = bitreader.read_rice_signed8((int)k);
|
|
||||||
else
|
else
|
||||||
for (int i = n; i > 0; i--)
|
{
|
||||||
*(r++) = bitreader.read_rice_signed((int)k);
|
bitreader.read_rice_block(n, (int)k, r);
|
||||||
|
r += n;
|
||||||
|
}
|
||||||
j += n;
|
j += n;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -420,18 +457,32 @@ namespace CUETools.Codecs.FLAKE
|
|||||||
int* data = sub->samples + sub->order;
|
int* data = sub->samples + sub->order;
|
||||||
int* residual = sub->residual + sub->order;
|
int* residual = sub->residual + sub->order;
|
||||||
int data_len = frame->blocksize - sub->order;
|
int data_len = frame->blocksize - sub->order;
|
||||||
|
int s0, s1, s2;
|
||||||
switch (sub->order)
|
switch (sub->order)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
Flake.memcpy(data, residual, data_len);
|
Flake.memcpy(data, residual, data_len);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
for (int i = 0; i < data_len; i++)
|
s1 = data[-1];
|
||||||
data[i] = residual[i] + data[i - 1];
|
for (int i = data_len; i > 0; i--)
|
||||||
|
{
|
||||||
|
s1 += *(residual++);
|
||||||
|
*(data++) = s1;
|
||||||
|
}
|
||||||
|
//data[i] = residual[i] + data[i - 1];
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
for (int i = 0; i < data_len; i++)
|
s2 = data[-2];
|
||||||
data[i] = residual[i] + (data[i - 1] << 1) - data[i - 2];
|
s1 = data[-1];
|
||||||
|
for (int i = data_len; i > 0; i--)
|
||||||
|
{
|
||||||
|
s0 = *(residual++) + (s1 << 1) - s2;
|
||||||
|
*(data++) = s0;
|
||||||
|
s2 = s1;
|
||||||
|
s1 = s0;
|
||||||
|
}
|
||||||
|
//data[i] = residual[i] + data[i - 1] * 2 - data[i - 2];
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
for (int i = 0; i < data_len; i++)
|
for (int i = 0; i < data_len; i++)
|
||||||
@@ -447,8 +498,10 @@ namespace CUETools.Codecs.FLAKE
|
|||||||
unsafe void restore_samples_lpc(FlacFrame* frame, int ch)
|
unsafe void restore_samples_lpc(FlacFrame* frame, int ch)
|
||||||
{
|
{
|
||||||
FlacSubframe* sub = frame->subframes + ch;
|
FlacSubframe* sub = frame->subframes + ch;
|
||||||
|
ulong csum = 0;
|
||||||
if ((ulong)sub->order * ((1UL << (int)sub->obits) - 1) * ((1U << sub->cbits) - 1) >= (1UL << 32))
|
for (int i = sub->order; i > 0; i--)
|
||||||
|
csum += (ulong)Math.Abs(sub->coefs[i - 1]);
|
||||||
|
if ((csum << (int)sub->obits) >= 1UL << 32)
|
||||||
lpc.decode_residual_long(sub->residual, sub->samples, frame->blocksize, sub->order, sub->coefs, sub->shift);
|
lpc.decode_residual_long(sub->residual, sub->samples, frame->blocksize, sub->order, sub->coefs, sub->shift);
|
||||||
else
|
else
|
||||||
lpc.decode_residual(sub->residual, sub->samples, frame->blocksize, sub->order, sub->coefs, sub->shift);
|
lpc.decode_residual(sub->residual, sub->samples, frame->blocksize, sub->order, sub->coefs, sub->shift);
|
||||||
@@ -475,42 +528,51 @@ namespace CUETools.Codecs.FLAKE
|
|||||||
}
|
}
|
||||||
if (frame->subframes[ch].wbits != 0)
|
if (frame->subframes[ch].wbits != 0)
|
||||||
{
|
{
|
||||||
|
int* s = frame->subframes[ch].samples;
|
||||||
int x = (int) frame->subframes[ch].wbits;
|
int x = (int) frame->subframes[ch].wbits;
|
||||||
for (int i = 0; i < frame->blocksize; i++)
|
for (int i = frame->blocksize; i > 0; i--)
|
||||||
frame->subframes[ch].samples[i] <<= x;
|
*(s++) <<= x;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (frame->ch_mode != ChannelMode.NotStereo)
|
||||||
|
{
|
||||||
|
int* l = frame->subframes[0].samples;
|
||||||
|
int* r = frame->subframes[1].samples;
|
||||||
switch (frame->ch_mode)
|
switch (frame->ch_mode)
|
||||||
{
|
{
|
||||||
case ChannelMode.NotStereo:
|
|
||||||
break;
|
|
||||||
case ChannelMode.LeftRight:
|
case ChannelMode.LeftRight:
|
||||||
break;
|
break;
|
||||||
case ChannelMode.MidSide:
|
case ChannelMode.MidSide:
|
||||||
for (int i = 0; i < frame->blocksize; i++)
|
for (int i = frame->blocksize; i > 0; i--)
|
||||||
{
|
{
|
||||||
int mid = frame->subframes[0].samples[i];
|
int mid = *l;
|
||||||
int side = frame->subframes[1].samples[i];
|
int side = *r;
|
||||||
mid <<= 1;
|
mid <<= 1;
|
||||||
mid |= (side & 1); /* i.e. if 'side' is odd... */
|
mid |= (side & 1); /* i.e. if 'side' is odd... */
|
||||||
frame->subframes[0].samples[i] = (mid + side) >> 1;
|
*(l++) = (mid + side) >> 1;
|
||||||
frame->subframes[1].samples[i] = (mid - side) >> 1;
|
*(r++) = (mid - side) >> 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ChannelMode.LeftSide:
|
case ChannelMode.LeftSide:
|
||||||
for (int i = 0; i < frame->blocksize; i++)
|
for (int i = frame->blocksize; i > 0; i--)
|
||||||
frame->subframes[1].samples[i] = frame->subframes[0].samples[i] - frame->subframes[1].samples[i];
|
{
|
||||||
|
int _l = *(l++), _r = *r;
|
||||||
|
*(r++) = _l - _r;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case ChannelMode.RightSide:
|
case ChannelMode.RightSide:
|
||||||
for (int i = 0; i < frame->blocksize; i++)
|
for (int i = frame->blocksize; i > 0; i--)
|
||||||
frame->subframes[0].samples[i] += frame->subframes[1].samples[i];
|
*(l++) += *(r++);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public unsafe int DecodeFrame(byte[] buffer, int pos, int len)
|
public unsafe int DecodeFrame(byte[] buffer, int pos, int len)
|
||||||
{
|
{
|
||||||
BitReader bitreader = new BitReader(buffer, pos, len);
|
fixed (byte* buf = buffer)
|
||||||
|
{
|
||||||
|
BitReader bitreader = new BitReader(buf, pos, len);
|
||||||
FlacFrame frame;
|
FlacFrame frame;
|
||||||
FlacSubframe* subframes = stackalloc FlacSubframe[channels];
|
FlacSubframe* subframes = stackalloc FlacSubframe[channels];
|
||||||
frame.subframes = subframes;
|
frame.subframes = subframes;
|
||||||
@@ -521,10 +583,10 @@ namespace CUETools.Codecs.FLAKE
|
|||||||
if (crc != bitreader.readbits(16))
|
if (crc != bitreader.readbits(16))
|
||||||
throw new Exception("frame crc mismatch");
|
throw new Exception("frame crc mismatch");
|
||||||
restore_samples(&frame);
|
restore_samples(&frame);
|
||||||
restore_samples(&frame);
|
|
||||||
_samplesInBuffer = (uint)frame.blocksize;
|
_samplesInBuffer = (uint)frame.blocksize;
|
||||||
return bitreader.Position - pos;
|
return bitreader.Position - pos;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool skip_bytes(int bytes)
|
bool skip_bytes(int bytes)
|
||||||
@@ -535,7 +597,7 @@ namespace CUETools.Codecs.FLAKE
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void decode_metadata()
|
unsafe void decode_metadata()
|
||||||
{
|
{
|
||||||
byte x;
|
byte x;
|
||||||
int i, id;
|
int i, id;
|
||||||
@@ -597,9 +659,10 @@ namespace CUETools.Codecs.FLAKE
|
|||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
long pos = _IO.Position;
|
|
||||||
fill_frames_buffer();
|
fill_frames_buffer();
|
||||||
BitReader bitreader = new BitReader(_framesBuffer, _framesBufferOffset, _framesBufferLength - _framesBufferOffset);
|
fixed (byte* buf = _framesBuffer)
|
||||||
|
{
|
||||||
|
BitReader bitreader = new BitReader(buf, _framesBufferOffset, _framesBufferLength - _framesBufferOffset);
|
||||||
bool is_last = bitreader.readbit() != 0;
|
bool is_last = bitreader.readbit() != 0;
|
||||||
MetadataType type = (MetadataType)bitreader.readbits(7);
|
MetadataType type = (MetadataType)bitreader.readbits(7);
|
||||||
int len = (int)bitreader.readbits(24);
|
int len = (int)bitreader.readbits(24);
|
||||||
@@ -623,12 +686,27 @@ namespace CUETools.Codecs.FLAKE
|
|||||||
sample_rate = (int)bitreader.readbits(FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN);
|
sample_rate = (int)bitreader.readbits(FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN);
|
||||||
channels = 1 + (int)bitreader.readbits(FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN);
|
channels = 1 + (int)bitreader.readbits(FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN);
|
||||||
bits_per_sample = 1 + bitreader.readbits(FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN);
|
bits_per_sample = 1 + bitreader.readbits(FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN);
|
||||||
_sampleCount = (((ulong)bitreader.readbits(4)) << 4) + (ulong)bitreader.readbits(32);
|
_sampleCount = bitreader.readbits64(FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN);
|
||||||
bitreader.skipbits(FLAC__STREAM_METADATA_STREAMINFO_MD5SUM_LEN);
|
bitreader.skipbits(FLAC__STREAM_METADATA_STREAMINFO_MD5SUM_LEN);
|
||||||
}
|
}
|
||||||
|
else if (type == MetadataType.FLAC__METADATA_TYPE_SEEKTABLE)
|
||||||
|
{
|
||||||
|
const int FLAC__STREAM_METADATA_SEEKPOINT_SAMPLE_NUMBER_LEN = 64; /* bits */
|
||||||
|
const int FLAC__STREAM_METADATA_SEEKPOINT_STREAM_OFFSET_LEN = 64; /* bits */
|
||||||
|
const int FLAC__STREAM_METADATA_SEEKPOINT_FRAME_SAMPLES_LEN = 16; /* bits */
|
||||||
|
|
||||||
|
int num_entries = len / 18;
|
||||||
|
seek_table = new SeekPoint[num_entries];
|
||||||
|
for (int e = 0; e < num_entries; e++)
|
||||||
|
{
|
||||||
|
seek_table[e].number = bitreader.readbits64(FLAC__STREAM_METADATA_SEEKPOINT_SAMPLE_NUMBER_LEN);
|
||||||
|
seek_table[e].offset = bitreader.readbits64(FLAC__STREAM_METADATA_SEEKPOINT_STREAM_OFFSET_LEN);
|
||||||
|
seek_table[e].framesize = bitreader.readbits24(FLAC__STREAM_METADATA_SEEKPOINT_FRAME_SAMPLES_LEN);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (_framesBufferLength < 4 + len)
|
if (_framesBufferLength < 4 + len)
|
||||||
{
|
{
|
||||||
_IO.Position = pos + 4 + len;
|
_IO.Position += 4 + len - _framesBufferLength;
|
||||||
_framesBufferLength = 0;
|
_framesBufferLength = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -638,7 +716,9 @@ namespace CUETools.Codecs.FLAKE
|
|||||||
}
|
}
|
||||||
if (is_last)
|
if (is_last)
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
} while (true);
|
} while (true);
|
||||||
|
first_frame_offset = _IO.Position - _framesBufferLength;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,14 +80,6 @@ namespace CUETools.Codecs.FLAKE
|
|||||||
if (channelCount != 2)
|
if (channelCount != 2)
|
||||||
throw new Exception("ChannelCount must be 2.");
|
throw new Exception("ChannelCount must be 2.");
|
||||||
|
|
||||||
flac_samplerates = new int[16] {
|
|
||||||
0, 0, 0, 0,
|
|
||||||
8000, 16000, 22050, 24000, 32000, 44100, 48000, 96000,
|
|
||||||
0, 0, 0, 0
|
|
||||||
};
|
|
||||||
flac_bitdepths = new int[8] { 0, 8, 12, 0, 16, 20, 24, 0 };
|
|
||||||
flac_blocksizes = new int[15] { 0, 192, 576, 1152, 2304, 4608, 0, 0, 256, 512, 1024, 2048, 4096, 8192, 16384 };
|
|
||||||
|
|
||||||
channels = channelCount;
|
channels = channelCount;
|
||||||
sample_rate = sampleRate;
|
sample_rate = sampleRate;
|
||||||
bits_per_sample = (uint) bitsPerSample;
|
bits_per_sample = (uint) bitsPerSample;
|
||||||
@@ -334,9 +326,9 @@ namespace CUETools.Codecs.FLAKE
|
|||||||
{
|
{
|
||||||
for (i = 0; i < 15; i++)
|
for (i = 0; i < 15; i++)
|
||||||
{
|
{
|
||||||
if (eparams.block_size == flac_blocksizes[i])
|
if (eparams.block_size == Flake.flac_blocksizes[i])
|
||||||
{
|
{
|
||||||
frame->blocksize = flac_blocksizes[i];
|
frame->blocksize = Flake.flac_blocksizes[i];
|
||||||
frame->bs_code0 = i;
|
frame->bs_code0 = i;
|
||||||
frame->bs_code1 = -1;
|
frame->bs_code1 = -1;
|
||||||
break;
|
break;
|
||||||
@@ -394,7 +386,7 @@ namespace CUETools.Codecs.FLAKE
|
|||||||
// return (uint)k_opt;
|
// return (uint)k_opt;
|
||||||
//}
|
//}
|
||||||
|
|
||||||
static unsafe uint find_optimal_rice_param(uint sum, uint n, out uint nbits_best)
|
static unsafe int find_optimal_rice_param(uint sum, uint n, out uint nbits_best)
|
||||||
{
|
{
|
||||||
int k_opt = 0;
|
int k_opt = 0;
|
||||||
uint a = n;
|
uint a = n;
|
||||||
@@ -412,7 +404,7 @@ namespace CUETools.Codecs.FLAKE
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
nbits_best = nbits;
|
nbits_best = nbits;
|
||||||
return (uint)k_opt;
|
return k_opt;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe uint calc_decorr_score(FlacFrame* frame, int ch, FlacSubframe* sub)
|
unsafe uint calc_decorr_score(FlacFrame* frame, int ch, FlacSubframe* sub)
|
||||||
@@ -845,7 +837,7 @@ namespace CUETools.Codecs.FLAKE
|
|||||||
int j = sub->order;
|
int j = sub->order;
|
||||||
for (int p = 0; p < (1 << porder); p++)
|
for (int p = 0; p < (1 << porder); p++)
|
||||||
{
|
{
|
||||||
int k = (int) sub->rc.rparams[p];
|
int k = sub->rc.rparams[p];
|
||||||
bitwriter.writebits(4, k);
|
bitwriter.writebits(4, k);
|
||||||
if (p == 1) res_cnt = psize;
|
if (p == 1) res_cnt = psize;
|
||||||
for (int i = 0; i < res_cnt && j < frame->blocksize; i++, j++)
|
for (int i = 0; i < res_cnt && j < frame->blocksize; i++, j++)
|
||||||
@@ -1247,19 +1239,16 @@ namespace CUETools.Codecs.FLAKE
|
|||||||
|
|
||||||
public string Path { get { return _path; } }
|
public string Path { get { return _path; } }
|
||||||
|
|
||||||
int[] flac_samplerates;
|
|
||||||
int[] flac_bitdepths;
|
|
||||||
int[] flac_blocksizes;
|
|
||||||
string vendor_string = "Flake#0.1";
|
string vendor_string = "Flake#0.1";
|
||||||
|
|
||||||
int select_blocksize(int samplerate, int time_ms)
|
int select_blocksize(int samplerate, int time_ms)
|
||||||
{
|
{
|
||||||
int blocksize = flac_blocksizes[1];
|
int blocksize = Flake.flac_blocksizes[1];
|
||||||
int target = (samplerate * time_ms) / 1000;
|
int target = (samplerate * time_ms) / 1000;
|
||||||
for (int i = 0; i < flac_blocksizes.Length; i++)
|
for (int i = 0; i < Flake.flac_blocksizes.Length; i++)
|
||||||
if (target >= flac_blocksizes[i] && flac_blocksizes[i] > blocksize)
|
if (target >= Flake.flac_blocksizes[i] && Flake.flac_blocksizes[i] > blocksize)
|
||||||
{
|
{
|
||||||
blocksize = flac_blocksizes[i];
|
blocksize = Flake.flac_blocksizes[i];
|
||||||
}
|
}
|
||||||
return blocksize;
|
return blocksize;
|
||||||
}
|
}
|
||||||
@@ -1271,7 +1260,7 @@ namespace CUETools.Codecs.FLAKE
|
|||||||
|
|
||||||
// metadata header
|
// metadata header
|
||||||
bitwriter.writebits(1, last);
|
bitwriter.writebits(1, last);
|
||||||
bitwriter.writebits(7, 0);
|
bitwriter.writebits(7, (int)MetadataType.FLAC__METADATA_TYPE_STREAMINFO);
|
||||||
bitwriter.writebits(24, 34);
|
bitwriter.writebits(24, 34);
|
||||||
|
|
||||||
if (eparams.variable_block_size > 0)
|
if (eparams.variable_block_size > 0)
|
||||||
@@ -1312,7 +1301,7 @@ namespace CUETools.Codecs.FLAKE
|
|||||||
|
|
||||||
// metadata header
|
// metadata header
|
||||||
bitwriter.writebits(1, last);
|
bitwriter.writebits(1, last);
|
||||||
bitwriter.writebits(7, 4);
|
bitwriter.writebits(7, (int)MetadataType.FLAC__METADATA_TYPE_VORBIS_COMMENT);
|
||||||
bitwriter.writebits(24, vendor_len + 8);
|
bitwriter.writebits(24, vendor_len + 8);
|
||||||
|
|
||||||
comment[pos + 4] = (byte)(vendor_len & 0xFF);
|
comment[pos + 4] = (byte)(vendor_len & 0xFF);
|
||||||
@@ -1337,7 +1326,7 @@ namespace CUETools.Codecs.FLAKE
|
|||||||
|
|
||||||
// metadata header
|
// metadata header
|
||||||
bitwriter.writebits(1, last);
|
bitwriter.writebits(1, last);
|
||||||
bitwriter.writebits(7, 1);
|
bitwriter.writebits(7, (int)MetadataType.FLAC__METADATA_TYPE_PADDING);
|
||||||
bitwriter.writebits(24, padlen);
|
bitwriter.writebits(24, padlen);
|
||||||
|
|
||||||
return padlen + 4;
|
return padlen + 4;
|
||||||
@@ -1384,7 +1373,7 @@ namespace CUETools.Codecs.FLAKE
|
|||||||
// find samplerate in table
|
// find samplerate in table
|
||||||
for (i = 4; i < 12; i++)
|
for (i = 4; i < 12; i++)
|
||||||
{
|
{
|
||||||
if (sample_rate == flac_samplerates[i])
|
if (sample_rate == Flake.flac_samplerates[i])
|
||||||
{
|
{
|
||||||
sr_code0 = i;
|
sr_code0 = i;
|
||||||
break;
|
break;
|
||||||
@@ -1397,7 +1386,7 @@ namespace CUETools.Codecs.FLAKE
|
|||||||
|
|
||||||
for (i = 1; i < 8; i++)
|
for (i = 1; i < 8; i++)
|
||||||
{
|
{
|
||||||
if (bits_per_sample == flac_bitdepths[i])
|
if (bits_per_sample == Flake.flac_bitdepths[i])
|
||||||
{
|
{
|
||||||
bps_code = i;
|
bps_code = i;
|
||||||
break;
|
break;
|
||||||
|
|||||||
Reference in New Issue
Block a user