ALAC can also be read from RAR archive

This commit is contained in:
chudov
2008-11-10 10:31:35 +00:00
parent df34997334
commit 9f4ceab16e
3 changed files with 42 additions and 35 deletions

View File

@@ -28,16 +28,16 @@ namespace ALACDotNet
{ {
public class ALACReader : IAudioSource public class ALACReader : IAudioSource
{ {
public ALACReader(string path) public ALACReader(string path, Stream IO)
{ {
_path = path; _path = path;
m_spIO = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read); _IO = IO != null ? IO : new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read);
_buff = new byte[512]; _buff = new byte[512];
_tags = new NameValueCollection(); _tags = new NameValueCollection();
qtmovie_read(); qtmovie_read();
if (!_formatRead || _bitsPerSample != 16 || _channelCount != 2 || _sampleRate != 44100) if (!_formatRead || _bitsPerSample != 16 || _channelCount != 2 || _sampleRate != 44100)
throw new Exception("Invalid ALAC file."); throw new Exception("Invalid ALAC file.");
_saved_mdat_pos = m_spIO.Position; _saved_mdat_pos = _IO.Position;
} }
public uint Read(int[,] buff, uint sampleCount) public uint Read(int[,] buff, uint sampleCount)
@@ -83,7 +83,7 @@ namespace ALACDotNet
if ((int) _iSample >= _sample_byte_size.Length) if ((int) _iSample >= _sample_byte_size.Length)
return (uint)offset; return (uint)offset;
get_sample_info(_iSample, out sampleDuration, out sampleSize); get_sample_info(_iSample, out sampleDuration, out sampleSize);
m_spIO.Read(_framesBuffer, 0, (int) sampleSize); _IO.Read(_framesBuffer, 0, (int) sampleSize);
decodeFrame(sampleDuration, sampleSize); decodeFrame(sampleDuration, sampleSize);
if (sampleDuration != _samplesInBuffer) if (sampleDuration != _samplesInBuffer)
throw new Exception("sample count mismatch"); throw new Exception("sample count mismatch");
@@ -102,7 +102,7 @@ namespace ALACDotNet
public void Close() public void Close()
{ {
m_spIO.Close(); _IO.Close();
} }
public ulong Length public ulong Length
@@ -142,7 +142,7 @@ namespace ALACDotNet
{ {
if (durOffs == value) if (durOffs == value)
{ {
m_spIO.Position = _saved_mdat_pos + fileOffs; _IO.Position = _saved_mdat_pos + fileOffs;
return; return;
} }
get_sample_info(_iSample, out sampleDuration, out sampleSize); get_sample_info(_iSample, out sampleDuration, out sampleSize);
@@ -150,7 +150,7 @@ namespace ALACDotNet
fileOffs += sampleSize; fileOffs += sampleSize;
_iSample++; _iSample++;
} while (durOffs <= value); } while (durOffs <= value);
m_spIO.Position = _saved_mdat_pos + fileOffs - sampleSize; _IO.Position = _saved_mdat_pos + fileOffs - sampleSize;
_samplesBufferOffset = (uint) (value + sampleDuration - durOffs); _samplesBufferOffset = (uint) (value + sampleDuration - durOffs);
_iSample--; _iSample--;
} }
@@ -218,7 +218,7 @@ namespace ALACDotNet
{ {
if (len > 512) if (len > 512)
throw new Exception("Decoding failed."); throw new Exception("Decoding failed.");
if (m_spIO.Read(_buff, 0, len) != len) if (_IO.Read(_buff, 0, len) != len)
throw new Exception("Decoding failed."); throw new Exception("Decoding failed.");
return _buff; return _buff;
} }
@@ -255,7 +255,7 @@ namespace ALACDotNet
private void stream_skip (UInt32 skip) private void stream_skip (UInt32 skip)
{ {
m_spIO.Position += skip; _IO.Position += skip;
} }
/* supports reading 1 to 24 bits, in big endian format */ /* supports reading 1 to 24 bits, in big endian format */
@@ -834,7 +834,7 @@ namespace ALACDotNet
_codecData[0] = 0; _codecData[1] = 0; _codecData[2] = 0; _codecData[3] = 0x0C; _codecData[0] = 0; _codecData[1] = 0; _codecData[2] = 0; _codecData[3] = 0x0C;
_codecData[4] = (byte)'f'; _codecData[5] = (byte)'r'; _codecData[6] = (byte)'m'; _codecData[7] = (byte)'a'; _codecData[4] = (byte)'f'; _codecData[5] = (byte)'r'; _codecData[6] = (byte)'m'; _codecData[7] = (byte)'a';
_codecData[8] = (byte)'a'; _codecData[9] = (byte)'l'; _codecData[10] = (byte)'a'; _codecData[11] = (byte)'c'; _codecData[8] = (byte)'a'; _codecData[9] = (byte)'l'; _codecData[10] = (byte)'a'; _codecData[11] = (byte)'c';
m_spIO.Read(_codecData, 12, (int)entry_remaining); _IO.Read(_codecData, 12, (int)entry_remaining);
entry_remaining -= entry_remaining; entry_remaining -= entry_remaining;
//#endif //#endif
@@ -957,7 +957,7 @@ namespace ALACDotNet
/* name */ /* name */
UInt32 strlen = stream_read_uint8(); UInt32 strlen = stream_read_uint8();
byte[] str = new byte[strlen]; byte[] str = new byte[strlen];
m_spIO.Read(str, 0, (int)strlen); _IO.Read(str, 0, (int)strlen);
size_remaining -= 1 + strlen; size_remaining -= 1 + strlen;
if (size_remaining > 0) if (size_remaining > 0)
@@ -989,7 +989,7 @@ namespace ALACDotNet
return; return;
if (skip_mdat) if (skip_mdat)
{ {
_saved_mdat_pos = m_spIO.Position; _saved_mdat_pos = _IO.Position;
stream_skip(size_remaining); stream_skip(size_remaining);
} }
//#if 0 //#if 0
@@ -1049,7 +1049,7 @@ namespace ALACDotNet
if (str_size <= 0) return; if (str_size <= 0) return;
if (tag_format != 0) throw new Exception(path + " not a binary"); if (tag_format != 0) throw new Exception(path + " not a binary");
byte[] value = new byte[str_size]; byte[] value = new byte[str_size];
if (m_spIO.Read(value, 0, str_size) != str_size) if (_IO.Read(value, 0, str_size) != str_size)
throw new Exception("Decoding failed."); throw new Exception("Decoding failed.");
if (path.EndsWith(".trkn.data")) if (path.EndsWith(".trkn.data"))
{ {
@@ -1189,7 +1189,7 @@ namespace ALACDotNet
qtmovie_read_lst("top.moov", chunk_len - 8, null); qtmovie_read_lst("top.moov", chunk_len - 8, null);
if (found_mdat) if (found_mdat)
{ {
m_spIO.Position = _saved_mdat_pos; _IO.Position = _saved_mdat_pos;
return; return;
} }
found_moov = true; found_moov = true;
@@ -1216,7 +1216,7 @@ namespace ALACDotNet
} }
string _path; string _path;
FileStream m_spIO; Stream _IO;
byte[] _codecData; byte[] _codecData;
uint[] _time_to_sample_count, _time_to_sample_duration, _sample_byte_size; uint[] _time_to_sample_count, _time_to_sample_duration, _sample_byte_size;

View File

@@ -22,7 +22,7 @@ namespace CUEToolsLib {
case ".ape": case ".ape":
return new APEReader(path); return new APEReader(path);
case ".m4a": case ".m4a":
return new ALACReader(path); return new ALACReader(path, null);
#endif #endif
default: default:
throw new Exception("Unsupported audio type."); throw new Exception("Unsupported audio type.");
@@ -37,6 +37,8 @@ namespace CUEToolsLib {
#if !MONO #if !MONO
case ".flac": case ".flac":
return new FLACReader(path, IO); return new FLACReader(path, IO);
case ".m4a":
return new ALACReader(path, IO);
#endif #endif
default: default:
throw new Exception("Unsupported audio type in archive."); throw new Exception("Unsupported audio type in archive.");

View File

@@ -58,7 +58,7 @@ namespace UnRarDotNet
} }
public override long Position public override long Position
{ {
get { return _pos; } get { return _seek_to == null ? _pos : _seek_to.Value; }
set { Seek(value, SeekOrigin.Begin); } set { Seek(value, SeekOrigin.Begin); }
} }
public override void Close() public override void Close()
@@ -143,13 +143,14 @@ namespace UnRarDotNet
Monitor.Wait(this); Monitor.Wait(this);
if (_size == null) if (_size == null)
throw new NotSupportedException(); throw new NotSupportedException();
}
switch (origin) switch (origin)
{ {
case SeekOrigin.Begin: case SeekOrigin.Begin:
_seek_to = offset; _seek_to = offset;
break; break;
case SeekOrigin.Current: case SeekOrigin.Current:
_seek_to = _pos + offset; _seek_to = Position + offset;
break; break;
case SeekOrigin.End: case SeekOrigin.End:
_seek_to = _size.Value + offset; _seek_to = _size.Value + offset;
@@ -160,8 +161,12 @@ namespace UnRarDotNet
_seek_to = null; _seek_to = null;
return _pos; return _pos;
} }
return _seek_to.Value; if (_seek_to.Value < _pos)
{
_seek_to = null;
throw new NotSupportedException("cannot seek backwards");
} }
return _seek_to.Value;
} }
public override void Write(byte[] array, int offset, int count) public override void Write(byte[] array, int offset, int count)
{ {