bug fixes in ALACEnc

This commit is contained in:
chudov
2010-04-18 22:42:23 +00:00
parent 08722c0255
commit 80fe7def42
12 changed files with 197 additions and 115 deletions

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
This file is automatically generated by Visual Studio .Net. It is
used to store generic object data source configuration information.
Renaming the file extension or editing the content of this file may
cause the file to be unrecognizable by the program.
-->
<GenericObjectDataSource DisplayName="IcecastSettingsData" Version="1.0" xmlns="urn:schemas-microsoft-com:xml-msdatasource">
<TypeInfo>CUETools.Codecs.Icecast.IcecastSettingsData, CUETools.Codecs.Icecast, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null</TypeInfo>
</GenericObjectDataSource>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
This file is automatically generated by Visual Studio .Net. It is
used to store generic object data source configuration information.
Renaming the file extension or editing the content of this file may
cause the file to be unrecognizable by the program.
-->
<GenericObjectDataSource DisplayName="Output" Version="1.0" xmlns="urn:schemas-microsoft-com:xml-msdatasource">
<TypeInfo>CUEPlayer.Output, CUEPlayer, Version=2.0.7.0, Culture=neutral, PublicKeyToken=null</TypeInfo>
</GenericObjectDataSource>

View File

@@ -24,7 +24,8 @@ namespace CUETools.ALACEnc
Console.WriteLine(); Console.WriteLine();
Console.WriteLine("Advanced Options:"); Console.WriteLine("Advanced Options:");
Console.WriteLine(); Console.WriteLine();
Console.WriteLine(" -b # Block size."); Console.WriteLine(" -b # Block size (samples).");
Console.WriteLine(" -p # Padding (bytes).");
Console.WriteLine(" -s <method> Stereo decorrelation (independent,estimate,evaluate,search)."); Console.WriteLine(" -s <method> Stereo decorrelation (independent,estimate,evaluate,search).");
Console.WriteLine(" --history-modifier # Rice history modifier {max} or {min},{max}, default 4,4."); Console.WriteLine(" --history-modifier # Rice history modifier {max} or {min},{max}, default 4,4.");
Console.WriteLine(); Console.WriteLine();
@@ -169,7 +170,7 @@ namespace CUETools.ALACEnc
output_file == "-" ? Console.OpenStandardOutput() : output_file == "-" ? Console.OpenStandardOutput() :
output_file == "nul" ? new NullStream() : null, output_file == "nul" ? new NullStream() : null,
audioSource.PCM); audioSource.PCM);
alac.FinalSampleCount = (long)audioSource.Length; alac.FinalSampleCount = audioSource.Length;
IAudioDest audioDest = alac; IAudioDest audioDest = alac;
AudioBuffer buff = new AudioBuffer(audioSource, 0x10000); AudioBuffer buff = new AudioBuffer(audioSource, 0x10000);

View File

@@ -604,8 +604,8 @@ namespace CUETools.Codecs.ALAC
buf_s[i * 2 + 1] = midright; buf_s[i * 2 + 1] = midright;
#if DEBUG #if DEBUG
if (buf_s[i * 2] >= (1 << _bitsPerSample) || buf_s[i * 2] < -(1 << _bitsPerSample) || if (buf_s[i * 2] >= (1 << pcm.BitsPerSample) || buf_s[i * 2] < -(1 << pcm.BitsPerSample) ||
buf_s[i * 2 + 1] >= (1 << _bitsPerSample) || buf_s[i * 2 + 1] < -(1 << _bitsPerSample) buf_s[i * 2 + 1] >= (1 << pcm.BitsPerSample) || buf_s[i * 2 + 1] < -(1 << pcm.BitsPerSample)
) )
throw new Exception("overflow in ALAC decoder"); throw new Exception("overflow in ALAC decoder");
#endif #endif
@@ -641,7 +641,7 @@ namespace CUETools.Codecs.ALAC
bool isnotcompressed = 0 != readbits(_framesBuffer, ref pos, 1); /* whether the frame is compressed */ bool isnotcompressed = 0 != readbits(_framesBuffer, ref pos, 1); /* whether the frame is compressed */
int outputSamples = hassize ? (int)readbits(_framesBuffer, ref pos, 32) : setinfo_max_samples_per_frame; int outputSamples = hassize ? (int)readbits(_framesBuffer, ref pos, 32) : setinfo_max_samples_per_frame;
int readsamplesize = pcm.BitsPerSample - (wasted_bytes * 8) + pcm.ChannelCount; int readsamplesize = pcm.BitsPerSample - (wasted_bytes * 8) + pcm.ChannelCount - 1;
if (!isnotcompressed) if (!isnotcompressed)
{ {
/* compressed */ /* compressed */

View File

@@ -36,9 +36,12 @@ namespace CUETools.Codecs.ALAC
public class ALACWriter : IAudioDest public class ALACWriter : IAudioDest
{ {
Stream _IO = null; Stream _IO = null;
bool _pathGiven = false;
string _path; string _path;
long _position; long _position;
const int max_header_len = 709 + 38; // minimum 38 bytes in padding
// total stream samples // total stream samples
// if < 0, stream length is unknown // if < 0, stream length is unknown
int sample_count = -1; int sample_count = -1;
@@ -55,15 +58,12 @@ namespace CUETools.Codecs.ALAC
int frame_count = 0; int frame_count = 0;
long first_frame_offset = 0; int first_frame_offset = 0;
#if INTEROP #if INTEROP
TimeSpan _userProcessorTime; TimeSpan _userProcessorTime;
#endif #endif
// header bytes
byte[] header;
uint[] _sample_byte_size; uint[] _sample_byte_size;
int[] samplesBuffer; int[] samplesBuffer;
int[] verifyBuffer; int[] verifyBuffer;
@@ -81,8 +81,6 @@ namespace CUETools.Codecs.ALAC
ALACFrame frame; ALACFrame frame;
ALACReader verify; ALACReader verify;
int mdat_pos;
bool inited = false; bool inited = false;
List<int> chunk_pos; List<int> chunk_pos;
@@ -100,13 +98,16 @@ namespace CUETools.Codecs.ALAC
_path = path; _path = path;
_IO = IO; _IO = IO;
_pathGiven = _IO == null;
if (_IO != null && !_IO.CanSeek)
throw new NotSupportedException("stream doesn't support seeking");
samplesBuffer = new int[Alac.MAX_BLOCKSIZE * (_pcm.ChannelCount == 2 ? 5 : _pcm.ChannelCount)]; samplesBuffer = new int[Alac.MAX_BLOCKSIZE * (_pcm.ChannelCount == 2 ? 5 : _pcm.ChannelCount)];
residualBuffer = new int[Alac.MAX_BLOCKSIZE * (_pcm.ChannelCount == 2 ? 6 : _pcm.ChannelCount + 1)]; residualBuffer = new int[Alac.MAX_BLOCKSIZE * (_pcm.ChannelCount == 2 ? 6 : _pcm.ChannelCount + 1)];
windowBuffer = new float[Alac.MAX_BLOCKSIZE * 2 * Alac.MAX_LPC_WINDOWS]; windowBuffer = new float[Alac.MAX_BLOCKSIZE * 2 * Alac.MAX_LPC_WINDOWS];
eparams.set_defaults(_compressionLevel); eparams.set_defaults(_compressionLevel);
eparams.padding_size = 8192; eparams.padding_size = 4096;
crc8 = new Crc8(); crc8 = new Crc8();
crc16 = new Crc16(); crc16 = new Crc16();
@@ -209,23 +210,57 @@ namespace CUETools.Codecs.ALAC
while (samplesInBuffer > 0) while (samplesInBuffer > 0)
output_frame(samplesInBuffer); output_frame(samplesInBuffer);
if (_IO.CanSeek) int mdat_len = (int)_IO.Position - first_frame_offset;
int header_len = first_frame_offset;
if (sample_count <= 0 && _position != 0)
{ {
int mdat_len = (int)_IO.Position - mdat_pos; sample_count = (int)_position;
_IO.Position = mdat_pos; header_len = max_header_len
BitWriter bitwriter = new BitWriter(header, 0, 4); + eparams.padding_size
bitwriter.writebits(32, mdat_len); + frame_count * 4 // stsz
bitwriter.flush(); + frame_count * 4 / eparams.chunk_size; // stco
_IO.Write(header, 0, 4); //if (header_len % 0x400 != 0)
// header_len += 0x400 - (header_len % 0x400);
if (sample_count <= 0 && _position != 0) }
sample_count = (int)_position;
if (!_creationTime.HasValue)
_IO.Position = _IO.Length; _creationTime = DateTime.Now;
int trailer_len = write_trailers();
_IO.Write(header, 0, trailer_len); if (header_len > first_frame_offset)
{
// if frame_count is high, need to rewrite
// the whole file to increase first_frame_offset
//System.Diagnostics.Trace.WriteLine(String.Format("Rewriting whole file: {0}/{1} + {2}", header_len, first_frame_offset, mdat_len));
// assert(_pathGiven);
string tmpPath = _path + ".tmp"; // TODO: make sure tmpPath is unique?
FileStream IO2 = new FileStream(tmpPath, FileMode.Create, FileAccess.ReadWrite, FileShare.Read);
byte[] header = write_headers(header_len, mdat_len);
IO2.Write(header, 0, header_len);
_IO.Position = first_frame_offset;
int bufSize = Math.Min(mdat_len, 0x2000);
byte[] buffer = new byte[bufSize];
int n;
do
{
n = _IO.Read(buffer, 0, buffer.Length);
IO2.Write(buffer, 0, n);
} while (n != 0);
IO2.Close();
_IO.Close();
File.Delete(_path);
File.Move(tmpPath, _path);
}
else
{
//System.Diagnostics.Trace.WriteLine(String.Format("{0}/{1}", header_len, first_frame_offset));
byte[] header = write_headers(first_frame_offset, mdat_len);
_IO.Position = 0;
_IO.Write(header, 0, first_frame_offset);
_IO.Close();
} }
_IO.Close();
inited = false; inited = false;
} }
@@ -1143,12 +1178,13 @@ namespace CUETools.Codecs.ALAC
{ {
if (!inited) if (!inited)
{ {
if (!_pathGiven && sample_count <= 0)
throw new NotSupportedException("input and output are both pipes");
if (_IO == null) if (_IO == null)
_IO = new FileStream(_path, FileMode.Create, FileAccess.Write, FileShare.Read); _IO = new FileStream(_path, FileMode.Create, FileAccess.ReadWrite, FileShare.Read);
int header_size = encode_init(); if (_IO != null && !_IO.CanSeek)
_IO.Write(header, 0, header_size); throw new NotSupportedException("stream doesn't support seeking");
if (_IO.CanSeek) encode_init();
first_frame_offset = _IO.Position;
inited = true; inited = true;
} }
@@ -1205,15 +1241,15 @@ namespace CUETools.Codecs.ALAC
return blocksize >> 1; return blocksize >> 1;
} }
void write_chunk_mvhd(BitWriter bitwriter, TimeSpan UnixTime) void write_chunk_mvhd(BitWriter bitwriter)
{ {
chunk_start(bitwriter); chunk_start(bitwriter);
{ {
bitwriter.write('m', 'v', 'h', 'd'); bitwriter.write('m', 'v', 'h', 'd');
bitwriter.writebits(32, 0); bitwriter.writebits(32, 0);
bitwriter.writebits(32, (int)UnixTime.TotalSeconds); bitwriter.writebits(_creationTime.Value);
bitwriter.writebits(32, (int)UnixTime.TotalSeconds); bitwriter.writebits(_creationTime.Value);
bitwriter.writebits(32, 1000); bitwriter.writebits(32, _pcm.SampleRate);
bitwriter.writebits(32, sample_count); bitwriter.writebits(32, sample_count);
bitwriter.writebits(32, 0x00010000); // reserved (preferred rate) 1.0 = normal bitwriter.writebits(32, 0x00010000); // reserved (preferred rate) 1.0 = normal
bitwriter.writebits(16, 0x0100); // reserved (preferred volume) 1.0 = normal bitwriter.writebits(16, 0x0100); // reserved (preferred volume) 1.0 = normal
@@ -1238,7 +1274,7 @@ namespace CUETools.Codecs.ALAC
chunk_end(bitwriter); chunk_end(bitwriter);
} }
void write_chunk_minf(BitWriter bitwriter) void write_chunk_minf(BitWriter bitwriter, int header_len)
{ {
chunk_start(bitwriter); chunk_start(bitwriter);
{ {
@@ -1294,6 +1330,13 @@ namespace CUETools.Codecs.ALAC
bitwriter.writebits(16, 0); // reserved bitwriter.writebits(16, 0); // reserved
chunk_start(bitwriter); chunk_start(bitwriter);
{ {
int max_fs = 0;
long sum_fs = 0;
for (int i = 0; i < frame_count; i++)
{
max_fs = Math.Max(max_fs, (int)_sample_byte_size[i]);
sum_fs += (int)_sample_byte_size[i];
}
bitwriter.write('a', 'l', 'a', 'c'); bitwriter.write('a', 'l', 'a', 'c');
bitwriter.writebits(32, 0); // reserved bitwriter.writebits(32, 0); // reserved
bitwriter.writebits(32, eparams.block_size); // max frame size bitwriter.writebits(32, eparams.block_size); // max frame size
@@ -1303,9 +1346,9 @@ namespace CUETools.Codecs.ALAC
bitwriter.writebits(8, initial_history); bitwriter.writebits(8, initial_history);
bitwriter.writebits(8, k_modifier); bitwriter.writebits(8, k_modifier);
bitwriter.writebits(8, _pcm.ChannelCount); // channels bitwriter.writebits(8, _pcm.ChannelCount); // channels
bitwriter.writebits(16, 0); // reserved bitwriter.writebits(16, 0); // reserved or 0x00 0xff????
bitwriter.writebits(32, max_frame_size); bitwriter.writebits(32, max_fs);
bitwriter.writebits(32, _pcm.SampleRate * _pcm.ChannelCount * _pcm.BitsPerSample); // average bitrate bitwriter.writebits(32, (int)(8 * sum_fs * _pcm.SampleRate / sample_count)); // average bitrate
bitwriter.writebits(32, _pcm.SampleRate); bitwriter.writebits(32, _pcm.SampleRate);
} }
chunk_end(bitwriter); chunk_end(bitwriter);
@@ -1337,15 +1380,28 @@ namespace CUETools.Codecs.ALAC
{ {
bitwriter.write('s', 't', 's', 'c'); bitwriter.write('s', 't', 's', 'c');
bitwriter.writebits(32, 0); // version & flags bitwriter.writebits(32, 0); // version & flags
bitwriter.writebits(32, 1); // entry count if (frame_count % eparams.chunk_size == 0)
bitwriter.writebits(32, 1); // first chunk {
bitwriter.writebits(32, 1); // samples in chunk bitwriter.writebits(32, 1); // entries
bitwriter.writebits(32, 1); // sample description index bitwriter.writebits(32, 1); // first chunk
bitwriter.writebits(32, eparams.chunk_size); // samples in chunk
bitwriter.writebits(32, 1); // sample description index
}
else
{
bitwriter.writebits(32, 2); // entries
bitwriter.writebits(32, 1); // first chunk
bitwriter.writebits(32, eparams.chunk_size); // samples in chunk
bitwriter.writebits(32, 1); // sample description index
bitwriter.writebits(32, 1 + frame_count / eparams.chunk_size); // first chunk
bitwriter.writebits(32, frame_count % eparams.chunk_size); // samples in chunk
bitwriter.writebits(32, 1); // sample description index
}
} }
chunk_end(bitwriter); chunk_end(bitwriter);
chunk_start(bitwriter); chunk_start(bitwriter);
{ {
bitwriter.write('s', 't', 's', 'z'); bitwriter.write('s', 't', 's', 'z'); // stsz
bitwriter.writebits(32, 0); // version & flags bitwriter.writebits(32, 0); // version & flags
bitwriter.writebits(32, 0); // sample size (0 == variable) bitwriter.writebits(32, 0); // sample size (0 == variable)
bitwriter.writebits(32, frame_count); // entry count bitwriter.writebits(32, frame_count); // entry count
@@ -1355,14 +1411,14 @@ namespace CUETools.Codecs.ALAC
chunk_end(bitwriter); chunk_end(bitwriter);
chunk_start(bitwriter); chunk_start(bitwriter);
{ {
bitwriter.write('s', 't', 'c', 'o'); bitwriter.write('s', 't', 'c', 'o'); // stco
bitwriter.writebits(32, 0); // version & flags bitwriter.writebits(32, 0); // version & flags
bitwriter.writebits(32, frame_count); // entry count bitwriter.writebits(32, (frame_count + eparams.chunk_size - 1) / eparams.chunk_size); // entry count
uint pos = (uint)mdat_pos + 8; int pos = header_len;
for (int i = 0; i < frame_count; i++) for (int i = 0; i < frame_count; i++)
{ {
bitwriter.writebits(32, pos); if (i % eparams.chunk_size == 0) bitwriter.writebits(32, pos);
pos += _sample_byte_size[i]; pos += (int)_sample_byte_size[i];
} }
} }
chunk_end(bitwriter); chunk_end(bitwriter);
@@ -1372,7 +1428,7 @@ namespace CUETools.Codecs.ALAC
chunk_end(bitwriter); chunk_end(bitwriter);
} }
void write_chunk_mdia(BitWriter bitwriter, TimeSpan UnixTime) void write_chunk_mdia(BitWriter bitwriter, int header_len)
{ {
chunk_start(bitwriter); chunk_start(bitwriter);
{ {
@@ -1381,8 +1437,8 @@ namespace CUETools.Codecs.ALAC
{ {
bitwriter.write('m', 'd', 'h', 'd'); bitwriter.write('m', 'd', 'h', 'd');
bitwriter.writebits(32, 0); // version & flags bitwriter.writebits(32, 0); // version & flags
bitwriter.writebits(32, (int)UnixTime.TotalSeconds); bitwriter.writebits(_creationTime.Value);
bitwriter.writebits(32, (int)UnixTime.TotalSeconds); bitwriter.writebits(_creationTime.Value);
bitwriter.writebits(32, _pcm.SampleRate); bitwriter.writebits(32, _pcm.SampleRate);
bitwriter.writebits(32, sample_count); bitwriter.writebits(32, sample_count);
bitwriter.writebits(16, 0x55c4); // language bitwriter.writebits(16, 0x55c4); // language
@@ -1398,16 +1454,16 @@ namespace CUETools.Codecs.ALAC
bitwriter.writebits(32, 0); // reserved bitwriter.writebits(32, 0); // reserved
bitwriter.writebits(32, 0); // reserved bitwriter.writebits(32, 0); // reserved
bitwriter.writebits(32, 0); // reserved bitwriter.writebits(32, 0); // reserved
bitwriter.writebits(8, "SoundHandler".Length); bitwriter.writebits(8, 0); //bitwriter.writebits(8, "SoundHandler".Length);
bitwriter.write("SoundHandler"); bitwriter.writebits(8, 0); //bitwriter.write("SoundHandler");
} }
chunk_end(bitwriter); chunk_end(bitwriter);
write_chunk_minf(bitwriter); write_chunk_minf(bitwriter, header_len);
} }
chunk_end(bitwriter); chunk_end(bitwriter);
} }
void write_chunk_trak(BitWriter bitwriter, TimeSpan UnixTime) void write_chunk_trak(BitWriter bitwriter, int header_len)
{ {
chunk_start(bitwriter); chunk_start(bitwriter);
{ {
@@ -1415,12 +1471,12 @@ namespace CUETools.Codecs.ALAC
chunk_start(bitwriter); chunk_start(bitwriter);
{ {
bitwriter.write('t', 'k', 'h', 'd'); bitwriter.write('t', 'k', 'h', 'd');
bitwriter.writebits(32, 15); // version bitwriter.writebits(32, 7); // version
bitwriter.writebits(32, (int)UnixTime.TotalSeconds); bitwriter.writebits(_creationTime.Value);
bitwriter.writebits(32, (int)UnixTime.TotalSeconds); bitwriter.writebits(_creationTime.Value);
bitwriter.writebits(32, 1); // track ID bitwriter.writebits(32, 1); // track ID
bitwriter.writebits(32, 0); // reserved bitwriter.writebits(32, 0); // reserved
bitwriter.writebits(32, sample_count / _pcm.SampleRate); bitwriter.writebits(32, sample_count);
bitwriter.writebits(32, 0); // reserved bitwriter.writebits(32, 0); // reserved
bitwriter.writebits(32, 0); // reserved bitwriter.writebits(32, 0); // reserved
bitwriter.writebits(32, 0); // reserved (layer & alternate group) bitwriter.writebits(32, 0); // reserved (layer & alternate group)
@@ -1439,7 +1495,7 @@ namespace CUETools.Codecs.ALAC
bitwriter.writebits(32, 0); // reserved (height) bitwriter.writebits(32, 0); // reserved (height)
} }
chunk_end(bitwriter); chunk_end(bitwriter);
write_chunk_mdia(bitwriter, UnixTime); write_chunk_mdia(bitwriter, header_len);
} }
chunk_end(bitwriter); chunk_end(bitwriter);
} }
@@ -1483,72 +1539,64 @@ namespace CUETools.Codecs.ALAC
chunk_end(bitwriter); chunk_end(bitwriter);
} }
chunk_end(bitwriter); chunk_end(bitwriter);
chunk_start(bitwriter); // padding
{
bitwriter.write('f', 'r', 'e', 'e');
bitwriter.writebytes(eparams.padding_size, 0);
}
chunk_end(bitwriter);
} }
chunk_end(bitwriter); chunk_end(bitwriter);
} }
chunk_end(bitwriter); chunk_end(bitwriter);
} }
int write_trailers() byte[] write_headers(int header_len, int mdat_len)
{ {
TimeSpan UnixTime = (_creationTime ?? DateTime.Now) - new DateTime(1970, 1, 1, 0, 0, 0, 0).ToLocalTime(); byte[] header = new byte[header_len];
header = new byte[0x1000 + frame_count * 8 + eparams.padding_size]; // FIXME!!! Possible buffer overrun
BitWriter bitwriter = new BitWriter(header, 0, header.Length); BitWriter bitwriter = new BitWriter(header, 0, header.Length);
chunk_start(bitwriter);
{
bitwriter.write('f', 't', 'y', 'p');
bitwriter.write('M', '4', 'A', ' ');
bitwriter.writebits(32, 0x200); // minor version
bitwriter.write('M', '4', 'A', ' ');
bitwriter.write('m', 'p', '4', '2');
bitwriter.write('i', 's', 'o', 'm');
bitwriter.writebits(32, 0);
}
chunk_end(bitwriter);
chunk_start(bitwriter); chunk_start(bitwriter);
{ {
bitwriter.write('m', 'o', 'o', 'v'); bitwriter.write('m', 'o', 'o', 'v');
write_chunk_mvhd(bitwriter, UnixTime); write_chunk_mvhd(bitwriter);
write_chunk_trak(bitwriter, UnixTime); write_chunk_trak(bitwriter, header_len);
write_chunk_udta(bitwriter); write_chunk_udta(bitwriter);
} }
chunk_end(bitwriter); chunk_end(bitwriter);
chunk_start(bitwriter); // padding
{
bitwriter.write('f', 'r', 'e', 'e');
bitwriter.writebytes(eparams.padding_size, 0);
}
chunk_end(bitwriter);
return bitwriter.Length;
}
int write_headers()
{
BitWriter bitwriter = new BitWriter(header, 0, header.Length);
chunk_start(bitwriter);
bitwriter.write('f', 't', 'y', 'p');
bitwriter.write('M', '4', 'A', ' ');
bitwriter.writebits(32, 0x200); // minor version
bitwriter.write('M', '4', 'A', ' ');
bitwriter.write('m', 'p', '4', '2');
bitwriter.write('i', 's', 'o', 'm');
bitwriter.writebits(32, 0);
chunk_end(bitwriter);
chunk_start(bitwriter); // padding chunk_start(bitwriter); // padding
{ {
bitwriter.write('f', 'r', 'e', 'e'); bitwriter.write('f', 'r', 'e', 'e');
bitwriter.writebytes(eparams.padding_size, 0); int padding_len = header_len - bitwriter.Length - 8;
if (padding_len < 0)
throw new Exception("padding length too small");
bitwriter.writebytes(padding_len, 0);
} }
chunk_end(bitwriter); chunk_end(bitwriter);
chunk_start(bitwriter); // padding in case we need extended mdat len bitwriter.writebits(32, mdat_len + 8);
bitwriter.write('f', 'r', 'e', 'e');
chunk_end(bitwriter);
mdat_pos = bitwriter.Length;
chunk_start(bitwriter); // mdat len placeholder
bitwriter.write('m', 'd', 'a', 't'); bitwriter.write('m', 'd', 'a', 't');
chunk_end(bitwriter); bitwriter.flush();
return bitwriter.Length; return header;
} }
int encode_init() void encode_init()
{ {
int i, header_len;
//if(flake_validate_params(s) < 0) //if(flake_validate_params(s) < 0)
// FIXME: For now, only 44100 samplerate is supported // FIXME: For now, only 44100 samplerate is supported
@@ -1574,14 +1622,6 @@ namespace CUETools.Codecs.ALAC
else else
max_frame_size = 16 + ((eparams.block_size * _pcm.ChannelCount * _pcm.BitsPerSample + 7) >> 3); max_frame_size = 16 + ((eparams.block_size * _pcm.ChannelCount * _pcm.BitsPerSample + 7) >> 3);
//if (_IO.CanSeek && eparams.do_seektable)
//{
//}
// output header bytes
header = new byte[eparams.padding_size + 0x1000];
header_len = write_headers();
frame_buffer = new byte[max_frame_size]; frame_buffer = new byte[max_frame_size];
_sample_byte_size = new uint[Math.Max(0x100, sample_count / eparams.block_size + 1)]; _sample_byte_size = new uint[Math.Max(0x100, sample_count / eparams.block_size + 1)];
@@ -1591,7 +1631,15 @@ namespace CUETools.Codecs.ALAC
verifyBuffer = new int[Alac.MAX_BLOCKSIZE * _pcm.ChannelCount]; verifyBuffer = new int[Alac.MAX_BLOCKSIZE * _pcm.ChannelCount];
} }
return header_len; int frames = sample_count / eparams.block_size;
int header_len = max_header_len
+ eparams.padding_size
+ frames * 4 // stsz
+ frames * 4 / eparams.chunk_size; // stco
//if (header_len % 0x400 != 0)
// header_len += 0x400 - (header_len % 0x400);
first_frame_offset = header_len;
_IO.Write(new byte[first_frame_offset], 0, first_frame_offset);
} }
} }
@@ -1636,6 +1684,8 @@ namespace CUETools.Codecs.ALAC
// can also be changed by user before encoding a frame // can also be changed by user before encoding a frame
public int block_size; public int block_size;
public int chunk_size;
// block time in milliseconds // block time in milliseconds
// set by the user prior to calling encode_init // set by the user prior to calling encode_init
// used to calculate block_size based on sample rate // used to calculate block_size based on sample rate
@@ -1698,6 +1748,7 @@ namespace CUETools.Codecs.ALAC
adaptive_passes = 0; adaptive_passes = 0;
do_verify = false; do_verify = false;
do_seektable = false; do_seektable = false;
chunk_size = 5;
// differences from level 6 // differences from level 6
switch (lvl) switch (lvl)

View File

@@ -2,7 +2,7 @@
<PropertyGroup> <PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.50727</ProductVersion> <ProductVersion>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion> <SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{F2EC7193-D5E5-4252-9803-5CEB407E910F}</ProjectGuid> <ProjectGuid>{F2EC7193-D5E5-4252-9803-5CEB407E910F}</ProjectGuid>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
@@ -19,7 +19,7 @@
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType> <DebugType>full</DebugType>
<Optimize>false</Optimize> <Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath> <OutputPath>..\bin\Debug\plugins\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants> <DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>

View File

@@ -2,7 +2,7 @@
<PropertyGroup> <PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.50727</ProductVersion> <ProductVersion>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion> <SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{32338A04-5B6B-4C63-8EE7-C6400F73B5D7}</ProjectGuid> <ProjectGuid>{32338A04-5B6B-4C63-8EE7-C6400F73B5D7}</ProjectGuid>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
@@ -23,6 +23,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants> <DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType> <DebugType>pdbonly</DebugType>

View File

@@ -44,6 +44,7 @@
<ProjectReference Include="..\CUETools.Codecs\CUETools.Codecs.csproj"> <ProjectReference Include="..\CUETools.Codecs\CUETools.Codecs.csproj">
<Project>{6458A13A-30EF-45A9-9D58-E5031B17BEE2}</Project> <Project>{6458A13A-30EF-45A9-9D58-E5031B17BEE2}</Project>
<Name>CUETools.Codecs</Name> <Name>CUETools.Codecs</Name>
<Private>False</Private>
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

View File

@@ -83,6 +83,12 @@ namespace CUETools.Codecs
writebits(bits, (uint)val); writebits(bits, (uint)val);
} }
public void writebits(DateTime val)
{
TimeSpan span = val.ToUniversalTime() - new DateTime(1904, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
writebits(32, (uint)span.TotalSeconds);
}
public void writebits64(int bits, ulong val) public void writebits64(int bits, ulong val)
{ {
if (bits > 32) if (bits > 32)

View File

@@ -21,6 +21,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants> <DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType> <DebugType>pdbonly</DebugType>

View File

@@ -12,7 +12,7 @@
<ApplicationIcon>cue2.ico</ApplicationIcon> <ApplicationIcon>cue2.ico</ApplicationIcon>
<ManifestCertificateThumbprint>611F49E043614FEDCFF1B128868CC8DC0B6656C5</ManifestCertificateThumbprint> <ManifestCertificateThumbprint>611F49E043614FEDCFF1B128868CC8DC0B6656C5</ManifestCertificateThumbprint>
<ManifestKeyFile>CUETools_TemporaryKey.pfx</ManifestKeyFile> <ManifestKeyFile>CUETools_TemporaryKey.pfx</ManifestKeyFile>
<GenerateManifests>true</GenerateManifests> <GenerateManifests>false</GenerateManifests>
<SignManifests>true</SignManifests> <SignManifests>true</SignManifests>
<IsWebBootstrapper>true</IsWebBootstrapper> <IsWebBootstrapper>true</IsWebBootstrapper>
<TargetZone>LocalIntranet</TargetZone> <TargetZone>LocalIntranet</TargetZone>

View File

@@ -273,6 +273,7 @@ Global
{32338A04-5B6B-4C63-8EE7-C6400F73B5D7}.Debug|x64.ActiveCfg = Debug|x64 {32338A04-5B6B-4C63-8EE7-C6400F73B5D7}.Debug|x64.ActiveCfg = Debug|x64
{32338A04-5B6B-4C63-8EE7-C6400F73B5D7}.Debug|x64.Build.0 = Debug|x64 {32338A04-5B6B-4C63-8EE7-C6400F73B5D7}.Debug|x64.Build.0 = Debug|x64
{32338A04-5B6B-4C63-8EE7-C6400F73B5D7}.Release|Any CPU.ActiveCfg = Release|Any CPU {32338A04-5B6B-4C63-8EE7-C6400F73B5D7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{32338A04-5B6B-4C63-8EE7-C6400F73B5D7}.Release|Any CPU.Build.0 = Release|Any CPU
{32338A04-5B6B-4C63-8EE7-C6400F73B5D7}.Release|Win32.ActiveCfg = Release|Any CPU {32338A04-5B6B-4C63-8EE7-C6400F73B5D7}.Release|Win32.ActiveCfg = Release|Any CPU
{32338A04-5B6B-4C63-8EE7-C6400F73B5D7}.Release|x64.ActiveCfg = Release|Any CPU {32338A04-5B6B-4C63-8EE7-C6400F73B5D7}.Release|x64.ActiveCfg = Release|Any CPU
{6458A13A-30EF-45A9-9D58-E5031B17BEE2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {6458A13A-30EF-45A9-9D58-E5031B17BEE2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU