Files
cuetools.net/CUETools.Processor/CUESheetAudio.cs

124 lines
3.8 KiB
C#
Raw Permalink Normal View History

using System;
using CUETools.Codecs;
namespace CUETools.Processor
{
public class CUESheetAudio : IAudioSource
{
private CUESheet cueSheet;
private IAudioSource currentAudio;
private int currentSource;
private long nextPos;
private long _samplePos, _sampleLen;
public IAudioDecoderSettings Settings => null;
public TimeSpan Duration => Length < 0 ? TimeSpan.Zero : TimeSpan.FromSeconds((double)Length / PCM.SampleRate);
public long Length
{
get { return _sampleLen; }
}
public long Remaining
{
get { return _sampleLen - _samplePos; }
}
public AudioPCMConfig PCM
{
get { return AudioPCMConfig.RedBook; }
}
public string Path
{
get { return cueSheet.InputPath; }
}
public long Position
{
get
{
return _samplePos;
}
set
{
SetPosition(value);
}
}
public CUESheetAudio(CUESheet cueSheet)
{
this.cueSheet = cueSheet;
this.currentAudio = null;
this._samplePos = 0;
this._sampleLen = 0;
this.currentSource = -1;
this.nextPos = 0;
cueSheet._sources.ForEach(s => this._sampleLen += s.Length);
}
private void SetPosition(long value)
{
if (value == _samplePos)
return;
long sourceStart = 0;
for (int iSource = 0; iSource < cueSheet._sources.Count; iSource++)
{
if (value >= sourceStart && value < sourceStart + cueSheet._sources[iSource].Length)
{
if (iSource != currentSource)
{
if (currentAudio != null)
currentAudio.Close();
currentSource = iSource;
currentAudio = cueSheet.GetAudioSource(currentSource, false);
nextPos = sourceStart + cueSheet._sources[currentSource].Length;
}
currentAudio.Position = value - sourceStart + cueSheet._sources[currentSource].Offset;
_samplePos = value;
return;
}
sourceStart += cueSheet._sources[iSource].Length;
}
throw new Exception("Invalid position");
}
public void Close()
{
if (currentAudio != null)
{
currentAudio.Close();
currentAudio = null;
}
}
public int Read(AudioBuffer buff, int maxLength)
{
buff.Prepare(this, maxLength);
while (_samplePos >= nextPos)
{
currentSource++;
if (currentSource >= cueSheet._sources.Count)
{
buff.Length = 0;
return 0;
}
if (currentAudio != null)
currentAudio.Close();
currentAudio = cueSheet.GetAudioSource(currentSource, false);
int offset = (int)(_samplePos - nextPos);
if (offset != 0)
currentAudio.Position += offset;
nextPos += cueSheet._sources[currentSource].Length;
}
int count = (int)(nextPos - _samplePos);
if (maxLength >= 0)
count = Math.Min(count, maxLength);
count = currentAudio.Read(buff, count);
_samplePos += count;
return count;
}
}
}