mirror of
https://github.com/claunia/cuetools.net.git
synced 2025-12-16 18:14:25 +00:00
148 lines
4.9 KiB
C#
148 lines
4.9 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Runtime.InteropServices;
|
|
|
|
namespace CUETools.Codecs.MACLib
|
|
{
|
|
public unsafe class AudioDecoder : IAudioSource, IDisposable
|
|
{
|
|
public AudioDecoder(DecoderSettings settings, string path, Stream IO)
|
|
{
|
|
m_settings = settings;
|
|
|
|
_path = path;
|
|
|
|
m_stream = (IO != null) ? IO : new FileStream (path, FileMode.Open, FileAccess.Read, FileShare.Read);
|
|
m_StreamIO = new StreamIO(m_stream);
|
|
|
|
int errorCode = 0;
|
|
pAPEDecompress = MACLibDll.c_APEDecompress_CreateEx(m_StreamIO.CIO, out errorCode);
|
|
if (pAPEDecompress == null) {
|
|
throw new Exception("Unable to initialize the decoder: " + errorCode);
|
|
}
|
|
|
|
pcm = new AudioPCMConfig(
|
|
MACLibDll.c_APEDecompress_GetInfo(pAPEDecompress, APE_DECOMPRESS_FIELDS.APE_INFO_BITS_PER_SAMPLE, 0, 0).ToInt32(),
|
|
MACLibDll.c_APEDecompress_GetInfo(pAPEDecompress, APE_DECOMPRESS_FIELDS.APE_INFO_CHANNELS, 0, 0).ToInt32(),
|
|
MACLibDll.c_APEDecompress_GetInfo(pAPEDecompress, APE_DECOMPRESS_FIELDS.APE_INFO_SAMPLE_RATE, 0, 0).ToInt32(),
|
|
(AudioPCMConfig.SpeakerConfig)0);
|
|
_samplesBuffer = new byte[16384 * pcm.BlockAlign];
|
|
_sampleCount = MACLibDll.c_APEDecompress_GetInfo(pAPEDecompress, APE_DECOMPRESS_FIELDS.APE_DECOMPRESS_TOTAL_BLOCKS, 0, 0).ToInt64();
|
|
_sampleOffset = 0;
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
Dispose(true);
|
|
GC.SuppressFinalize(this);
|
|
}
|
|
|
|
protected virtual void Dispose(bool disposing)
|
|
{
|
|
if (disposing)
|
|
{
|
|
if (m_StreamIO != null)
|
|
{
|
|
m_StreamIO.Dispose();
|
|
m_StreamIO = null;
|
|
}
|
|
if (m_stream != null)
|
|
{
|
|
m_stream.Dispose();
|
|
m_stream = null;
|
|
}
|
|
if (_samplesBuffer != null)
|
|
{
|
|
_samplesBuffer = null;
|
|
}
|
|
}
|
|
|
|
if (pAPEDecompress != null) MACLibDll.c_APEDecompress_Destroy(pAPEDecompress);
|
|
pAPEDecompress = IntPtr.Zero;
|
|
}
|
|
|
|
~AudioDecoder()
|
|
{
|
|
Dispose(false);
|
|
}
|
|
|
|
private DecoderSettings m_settings;
|
|
|
|
public IAudioDecoderSettings Settings => m_settings;
|
|
|
|
public AudioPCMConfig PCM => pcm;
|
|
|
|
public string Path => _path;
|
|
|
|
public TimeSpan Duration => Length < 0 ? TimeSpan.Zero : TimeSpan.FromSeconds((double)Length / PCM.SampleRate);
|
|
|
|
public long Length => _sampleCount;
|
|
|
|
internal long SamplesInBuffer => _bufferLength - _bufferOffset;
|
|
|
|
public long Position
|
|
{
|
|
get => _sampleOffset - SamplesInBuffer;
|
|
|
|
set
|
|
{
|
|
_bufferOffset = 0;
|
|
_bufferLength = 0;
|
|
_sampleOffset = value;
|
|
int res = MACLibDll.c_APEDecompress_Seek(pAPEDecompress, (int)value);
|
|
if (0 != res)
|
|
throw new Exception("unable to seek:" + res.ToString());
|
|
}
|
|
}
|
|
|
|
public long Remaining => _sampleCount - _sampleOffset + SamplesInBuffer;
|
|
|
|
public void Close()
|
|
{
|
|
Dispose(true);
|
|
}
|
|
|
|
public int Read(AudioBuffer buff, int maxLength)
|
|
{
|
|
buff.Prepare(this, maxLength);
|
|
|
|
long buffOffset = 0;
|
|
long samplesNeeded = buff.Length;
|
|
long _channelCount = pcm.ChannelCount;
|
|
|
|
while (samplesNeeded != 0)
|
|
{
|
|
if (SamplesInBuffer == 0)
|
|
{
|
|
long nBlocksRetrieved;
|
|
fixed (byte* pSampleBuffer = &_samplesBuffer[0])
|
|
{
|
|
int res = MACLibDll.c_APEDecompress_GetData(pAPEDecompress, (char*)pSampleBuffer, (IntPtr)16384, out nBlocksRetrieved);
|
|
if (res != 0)
|
|
throw new Exception("An error occurred while decoding: " + res.ToString());
|
|
}
|
|
_bufferOffset = 0;
|
|
_bufferLength = nBlocksRetrieved;
|
|
_sampleOffset += nBlocksRetrieved;
|
|
}
|
|
long copyCount = Math.Min(samplesNeeded, SamplesInBuffer);
|
|
AudioBuffer.BytesToFLACSamples_16(_samplesBuffer, (int)(_bufferOffset * pcm.BlockAlign), buff.Samples, (int)buffOffset, (int)copyCount, (int)_channelCount);
|
|
samplesNeeded -= copyCount;
|
|
buffOffset += copyCount;
|
|
_bufferOffset += copyCount;
|
|
}
|
|
|
|
return buff.Length;
|
|
}
|
|
|
|
IntPtr pAPEDecompress;
|
|
long _sampleCount, _sampleOffset;
|
|
AudioPCMConfig pcm;
|
|
string _path;
|
|
Stream m_stream;
|
|
long _bufferOffset, _bufferLength;
|
|
byte[] _samplesBuffer;
|
|
StreamIO m_StreamIO;
|
|
}
|
|
}
|