mirror of
https://github.com/claunia/cuetools.net.git
synced 2025-12-16 18:14:25 +00:00
bug fixes in ALACEnc
This commit is contained in:
@@ -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>
|
||||||
10
CUEPlayer/Properties/DataSources/Output.datasource
Normal file
10
CUEPlayer/Properties/DataSources/Output.datasource
Normal 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>
|
||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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" />
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user