mirror of
https://github.com/claunia/cuetools.net.git
synced 2025-12-16 18:14:25 +00:00
124 lines
3.8 KiB
C#
124 lines
3.8 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|