mirror of
https://github.com/claunia/cuetools.net.git
synced 2025-12-16 18:14:25 +00:00
optimizations, AudioSource.Read now reads FLAC samples (int [,]).
This commit is contained in:
@@ -40,7 +40,7 @@ namespace ALACDotNet
|
|||||||
_saved_mdat_pos = m_spIO.Position;
|
_saved_mdat_pos = m_spIO.Position;
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint Read(byte[] buff, uint sampleCount)
|
public uint Read(int[,] buff, uint sampleCount)
|
||||||
{
|
{
|
||||||
if (_predicterror_buffer_a == null)
|
if (_predicterror_buffer_a == null)
|
||||||
{
|
{
|
||||||
@@ -62,24 +62,23 @@ namespace ALACDotNet
|
|||||||
_outputsamples_buffer_b = new int[setinfo_max_samples_per_frame];
|
_outputsamples_buffer_b = new int[setinfo_max_samples_per_frame];
|
||||||
|
|
||||||
_samplesInBuffer = 0;
|
_samplesInBuffer = 0;
|
||||||
_samplesBuffer = new byte[setinfo_max_samples_per_frame*4];
|
|
||||||
_framesBuffer = new byte[65536];
|
_framesBuffer = new byte[65536];
|
||||||
}
|
}
|
||||||
|
|
||||||
ulong offset = 0;
|
uint offset = 0;
|
||||||
|
|
||||||
while (_samplesInBuffer < sampleCount)
|
while (_samplesInBuffer < sampleCount)
|
||||||
{
|
{
|
||||||
if (_samplesInBuffer > 0)
|
if (_samplesInBuffer > 0)
|
||||||
{
|
{
|
||||||
Array.Copy(_samplesBuffer, (long) _samplesBufferOffset * 4, buff, (long)offset * 4, (long)_samplesInBuffer * 4);
|
deinterlace(buff, offset);
|
||||||
sampleCount -= (uint) _samplesInBuffer;
|
sampleCount -= (uint) _samplesInBuffer;
|
||||||
offset += _samplesInBuffer;
|
offset += _samplesInBuffer;
|
||||||
_samplesInBuffer = 0;
|
_samplesInBuffer = 0;
|
||||||
_samplesBufferOffset = 0;
|
_samplesBufferOffset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ulong sampleDuration;
|
uint sampleDuration;
|
||||||
uint sampleSize;
|
uint sampleSize;
|
||||||
if ((int) _iSample >= _sample_byte_size.Length)
|
if ((int) _iSample >= _sample_byte_size.Length)
|
||||||
return (uint)offset;
|
return (uint)offset;
|
||||||
@@ -93,7 +92,7 @@ namespace ALACDotNet
|
|||||||
_iSample++;
|
_iSample++;
|
||||||
}
|
}
|
||||||
|
|
||||||
Array.Copy(_samplesBuffer, (long) _samplesBufferOffset * 4, buff, (long)offset * 4, (long)sampleCount * 4);
|
deinterlace(buff, offset);
|
||||||
_samplesInBuffer -= sampleCount;
|
_samplesInBuffer -= sampleCount;
|
||||||
_samplesBufferOffset += sampleCount;
|
_samplesBufferOffset += sampleCount;
|
||||||
if (_samplesInBuffer == 0)
|
if (_samplesInBuffer == 0)
|
||||||
@@ -136,7 +135,7 @@ namespace ALACDotNet
|
|||||||
|
|
||||||
_iSample = 0;
|
_iSample = 0;
|
||||||
ulong durOffs = 0;
|
ulong durOffs = 0;
|
||||||
ulong sampleDuration;
|
uint sampleDuration;
|
||||||
long fileOffs = 0;
|
long fileOffs = 0;
|
||||||
uint sampleSize;
|
uint sampleSize;
|
||||||
do
|
do
|
||||||
@@ -152,7 +151,7 @@ namespace ALACDotNet
|
|||||||
_iSample++;
|
_iSample++;
|
||||||
} while (durOffs <= value);
|
} while (durOffs <= value);
|
||||||
m_spIO.Position = _saved_mdat_pos + fileOffs - sampleSize;
|
m_spIO.Position = _saved_mdat_pos + fileOffs - sampleSize;
|
||||||
_samplesBufferOffset = sampleDuration - durOffs + value;
|
_samplesBufferOffset = (uint) (value + sampleDuration - durOffs);
|
||||||
_iSample--;
|
_iSample--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -201,7 +200,7 @@ namespace ALACDotNet
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void get_sample_info(ulong iSample, out ulong sampleDuration, out uint sampleSize)
|
private void get_sample_info(ulong iSample, out uint sampleDuration, out uint sampleSize)
|
||||||
{
|
{
|
||||||
// if (iSample >= _sample_byte_size.Length)
|
// if (iSample >= _sample_byte_size.Length)
|
||||||
uint duration_index_accum = 0;
|
uint duration_index_accum = 0;
|
||||||
@@ -590,43 +589,39 @@ namespace ALACDotNet
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private unsafe void deinterlace(uint numsamples, byte interlacing_shift, byte interlacing_leftweight)
|
private unsafe void deinterlace(int [,] samplesBuffer, uint offset)
|
||||||
{
|
{
|
||||||
if (numsamples <= 0)
|
if (_samplesInBuffer <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
fixed (int* buf_a = &_outputsamples_buffer_a[0], buf_b = _outputsamples_buffer_b)
|
fixed (int* buf_a = &_outputsamples_buffer_a[_samplesBufferOffset], buf_b = &_outputsamples_buffer_b[_samplesBufferOffset])
|
||||||
fixed (byte* buf_s = &_samplesBuffer[0])
|
fixed (int* buf_s = &samplesBuffer[offset, 0])
|
||||||
{
|
{
|
||||||
/* weighted interlacing */
|
/* weighted interlacing */
|
||||||
if (interlacing_leftweight != 0)
|
if (_interlacing_leftweight != 0)
|
||||||
{
|
{
|
||||||
for (i = 0; i < numsamples; i++)
|
for (i = 0; i < _samplesInBuffer; i++)
|
||||||
{
|
{
|
||||||
int a = buf_a[i];
|
int a = buf_a[i];
|
||||||
int b = buf_b[i];
|
int b = buf_b[i];
|
||||||
|
|
||||||
a -= (b * interlacing_leftweight) >> interlacing_shift;
|
a -= (b * _interlacing_leftweight) >> _interlacing_shift;
|
||||||
b += a;
|
b += a;
|
||||||
|
|
||||||
buf_s[i * 4] = (byte)(b & 0xff);
|
buf_s[i * 2] = b;
|
||||||
buf_s[i * 4 + 1] = (byte)((b >> 8) & 0xff);
|
buf_s[i * 2 + 1] = a;
|
||||||
buf_s[i * 4 + 2] = (byte)(a & 0xff);
|
|
||||||
buf_s[i * 4 + 3] = (byte)((a >> 8) & 0xff);
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* otherwise basic interlacing took place */
|
/* otherwise basic interlacing took place */
|
||||||
for (i = 0; i < numsamples; i++)
|
for (i = 0; i < _samplesInBuffer; i++)
|
||||||
{
|
{
|
||||||
int a = buf_a[i];
|
int a = buf_a[i];
|
||||||
int b = buf_b[i];
|
int b = buf_b[i];
|
||||||
buf_s[i * 4] = (byte)(a & 0xff);
|
buf_s[i * 2] = a;
|
||||||
buf_s[i * 4 + 1] = (byte)((a >> 8) & 0xff);
|
buf_s[i * 2 + 1] = b;
|
||||||
buf_s[i * 4 + 2] = (byte)(b & 0xff);
|
|
||||||
buf_s[i * 4 + 3] = (byte)((b >> 8) & 0xff);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -640,8 +635,6 @@ namespace ALACDotNet
|
|||||||
if (channels != 1)
|
if (channels != 1)
|
||||||
throw new Exception("Not stereo");
|
throw new Exception("Not stereo");
|
||||||
|
|
||||||
byte interlacing_shift;
|
|
||||||
byte interlacing_leftweight;
|
|
||||||
readbits(_framesBuffer, ref pos, 4);
|
readbits(_framesBuffer, ref pos, 4);
|
||||||
readbits(_framesBuffer, ref pos, 12); /* unknown, skip 12 bits */
|
readbits(_framesBuffer, ref pos, 12); /* unknown, skip 12 bits */
|
||||||
bool hassize = 0 != readbits(_framesBuffer, ref pos, 1); /* the output sample size is stored soon */
|
bool hassize = 0 != readbits(_framesBuffer, ref pos, 1); /* the output sample size is stored soon */
|
||||||
@@ -654,8 +647,8 @@ namespace ALACDotNet
|
|||||||
{
|
{
|
||||||
/* compressed */
|
/* compressed */
|
||||||
|
|
||||||
interlacing_shift = (byte)readbits(_framesBuffer, ref pos, 8);
|
_interlacing_shift = (byte)readbits(_framesBuffer, ref pos, 8);
|
||||||
interlacing_leftweight = (byte)readbits(_framesBuffer, ref pos, 8);
|
_interlacing_leftweight = (byte)readbits(_framesBuffer, ref pos, 8);
|
||||||
|
|
||||||
if (wasted_bytes != 0)
|
if (wasted_bytes != 0)
|
||||||
throw new Exception("FIXME: unimplemented, unhandling of wasted_bytes");
|
throw new Exception("FIXME: unimplemented, unhandling of wasted_bytes");
|
||||||
@@ -684,15 +677,13 @@ namespace ALACDotNet
|
|||||||
_outputsamples_buffer_b[i] = extend_sign32((int)readbits(_framesBuffer, ref pos, _bitsPerSample), _bitsPerSample);
|
_outputsamples_buffer_b[i] = extend_sign32((int)readbits(_framesBuffer, ref pos, _bitsPerSample), _bitsPerSample);
|
||||||
}
|
}
|
||||||
/* wasted_bytes = 0; */
|
/* wasted_bytes = 0; */
|
||||||
interlacing_shift = 0;
|
_interlacing_shift = 0;
|
||||||
interlacing_leftweight = 0;
|
_interlacing_leftweight = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_bitsPerSample != 16)
|
if (_bitsPerSample != 16)
|
||||||
throw new Exception("Not 16 bit");
|
throw new Exception("Not 16 bit");
|
||||||
|
|
||||||
deinterlace(outputSamples, interlacing_shift, interlacing_leftweight);
|
|
||||||
|
|
||||||
_samplesInBuffer = outputSamples;
|
_samplesInBuffer = outputSamples;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1245,16 +1236,16 @@ namespace ALACDotNet
|
|||||||
predictor_t predictor_info_b;
|
predictor_t predictor_info_b;
|
||||||
|
|
||||||
NameValueCollection _tags;
|
NameValueCollection _tags;
|
||||||
ulong _samplesInBuffer;
|
uint _samplesInBuffer, _samplesBufferOffset;
|
||||||
byte[] _samplesBuffer;
|
|
||||||
byte[] _framesBuffer;
|
byte[] _framesBuffer;
|
||||||
byte[] _buff;
|
byte[] _buff;
|
||||||
|
byte _interlacing_shift;
|
||||||
|
byte _interlacing_leftweight;
|
||||||
int _sampleRate;
|
int _sampleRate;
|
||||||
int _channelCount;
|
int _channelCount;
|
||||||
int _bitsPerSample;
|
int _bitsPerSample;
|
||||||
ulong _sampleCount;
|
ulong _sampleCount;
|
||||||
ulong _sampleOffset;
|
ulong _sampleOffset;
|
||||||
ulong _samplesBufferOffset;
|
|
||||||
ulong _iSample;
|
ulong _iSample;
|
||||||
|
|
||||||
Dictionary<string, qtmovie_read_atom> _qtmovie_parsers;
|
Dictionary<string, qtmovie_read_atom> _qtmovie_parsers;
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ namespace AudioCodecsDotNet
|
|||||||
{
|
{
|
||||||
public interface IAudioSource
|
public interface IAudioSource
|
||||||
{
|
{
|
||||||
uint Read(byte[] buff, uint sampleCount);
|
uint Read(int[,] buff, uint sampleCount);
|
||||||
ulong Length { get; }
|
ulong Length { get; }
|
||||||
ulong Position { get; set; }
|
ulong Position { get; set; }
|
||||||
NameValueCollection Tags { get; set; }
|
NameValueCollection Tags { get; set; }
|
||||||
@@ -228,24 +228,17 @@ namespace AudioCodecsDotNet
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint Read(byte[] buff, uint sampleCount)
|
public uint Read(int [,] buff, uint sampleCount)
|
||||||
{
|
{
|
||||||
uint samplesRemaining, byteCount, i;
|
uint samplesRemaining = (uint)(_sampleCount - _sampleOffset);
|
||||||
|
|
||||||
samplesRemaining = (uint)(_sampleCount - _sampleOffset);
|
|
||||||
if (sampleCount > samplesRemaining)
|
if (sampleCount > samplesRemaining)
|
||||||
{
|
|
||||||
sampleCount = samplesRemaining;
|
sampleCount = samplesRemaining;
|
||||||
}
|
|
||||||
|
|
||||||
byteCount = sampleCount * 2 * 2;
|
for (uint i = 0; i < sampleCount; i++)
|
||||||
for (i = 0; i < byteCount; i++)
|
for (int j = 0; j < buff.GetLength(1); j++)
|
||||||
{
|
buff[i,j] = 0;
|
||||||
buff[i] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
_sampleOffset += sampleCount;
|
_sampleOffset += sampleCount;
|
||||||
|
|
||||||
return sampleCount;
|
return sampleCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -265,6 +258,7 @@ namespace AudioCodecsDotNet
|
|||||||
int _bitsPerSample, _channelCount, _sampleRate, _blockAlign;
|
int _bitsPerSample, _channelCount, _sampleRate, _blockAlign;
|
||||||
bool _largeFile;
|
bool _largeFile;
|
||||||
string _path;
|
string _path;
|
||||||
|
private byte[] _sampleBuffer;
|
||||||
|
|
||||||
public WAVReader(string path)
|
public WAVReader(string path)
|
||||||
{
|
{
|
||||||
@@ -476,22 +470,21 @@ namespace AudioCodecsDotNet
|
|||||||
values = new List<string>();
|
values = new List<string>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint Read(byte[] buff, uint sampleCount)
|
public uint Read(int[,] buff, uint sampleCount)
|
||||||
{
|
{
|
||||||
if (sampleCount > Remaining)
|
if (sampleCount > Remaining)
|
||||||
sampleCount = (uint)Remaining;
|
sampleCount = (uint)Remaining;
|
||||||
|
|
||||||
uint byteCount = sampleCount * (uint)_blockAlign;
|
if (sampleCount == 0)
|
||||||
|
return 0;
|
||||||
if (sampleCount != 0)
|
int byteCount = (int) sampleCount * _blockAlign;
|
||||||
{
|
if (_sampleBuffer == null || _sampleBuffer.Length < byteCount)
|
||||||
if (_fs.Read(buff, 0, (int)byteCount) != byteCount)
|
_sampleBuffer = new byte[byteCount];
|
||||||
{
|
if (_fs.Read(_sampleBuffer, 0, (int)byteCount) != byteCount)
|
||||||
throw new Exception("Incomplete file read.");
|
throw new Exception("Incomplete file read.");
|
||||||
}
|
AudioCodecsDotNet.BytesToFLACSamples_16 (_sampleBuffer, 0, buff, 0,
|
||||||
|
sampleCount, _channelCount);
|
||||||
_samplePos += sampleCount;
|
_samplePos += sampleCount;
|
||||||
}
|
|
||||||
|
|
||||||
return sampleCount;
|
return sampleCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -600,7 +593,7 @@ namespace AudioCodecsDotNet
|
|||||||
{
|
{
|
||||||
if (sampleCount == 0)
|
if (sampleCount == 0)
|
||||||
return;
|
return;
|
||||||
if (_sampleBuffer == null || _sampleBuffer.Length < sampleCount * _channelCount)
|
if (_sampleBuffer == null || _sampleBuffer.Length < sampleCount * _blockAlign)
|
||||||
_sampleBuffer = new byte[sampleCount * _blockAlign];
|
_sampleBuffer = new byte[sampleCount * _blockAlign];
|
||||||
AudioCodecsDotNet.FLACSamplesToBytes(buff, 0, _sampleBuffer, 0,
|
AudioCodecsDotNet.FLACSamplesToBytes(buff, 0, _sampleBuffer, 0,
|
||||||
sampleCount, _channelCount, _bitsPerSample);
|
sampleCount, _channelCount, _bitsPerSample);
|
||||||
|
|||||||
@@ -130,6 +130,7 @@ namespace JDP
|
|||||||
progressBar2.Value = 0;
|
progressBar2.Value = 0;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
#if !DEBUG
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
this.Invoke((MethodInvoker)delegate()
|
this.Invoke((MethodInvoker)delegate()
|
||||||
@@ -141,6 +142,7 @@ namespace JDP
|
|||||||
textBox1.Select(0, 0);
|
textBox1.Select(0, 0);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (_batchPaths.Count != 0)
|
if (_batchPaths.Count != 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ namespace CUEToolsLib {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint Read(byte[] buff, uint sampleCount) {
|
public uint Read(int [,] buff, uint sampleCount) {
|
||||||
if (_flacReader.BitsPerSample != 16) {
|
if (_flacReader.BitsPerSample != 16) {
|
||||||
throw new Exception("Reading is only supported for 16 bit sample depth.");
|
throw new Exception("Reading is only supported for 16 bit sample depth.");
|
||||||
}
|
}
|
||||||
@@ -142,12 +142,10 @@ namespace CUEToolsLib {
|
|||||||
}
|
}
|
||||||
|
|
||||||
copyCount = Math.Min(samplesNeeded, SamplesInBuffer);
|
copyCount = Math.Min(samplesNeeded, SamplesInBuffer);
|
||||||
|
Array.Copy(_sampleBuffer, _bufferOffset * chanCount, buff, buffOffset * chanCount, copyCount * chanCount);
|
||||||
AudioCodecsDotNet.AudioCodecsDotNet.FLACSamplesToBytes_16(_sampleBuffer, _bufferOffset, buff, buffOffset,
|
|
||||||
copyCount, chanCount);
|
|
||||||
|
|
||||||
samplesNeeded -= copyCount;
|
samplesNeeded -= copyCount;
|
||||||
buffOffset += copyCount * (uint) chanCount * 2;
|
buffOffset += copyCount;
|
||||||
_bufferOffset += copyCount;
|
_bufferOffset += copyCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -288,30 +286,30 @@ namespace CUEToolsLib {
|
|||||||
set { _apeReader.Tags = value; }
|
set { _apeReader.Tags = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
private unsafe void APESamplesToBytes_16(int[,] inSamples, uint inSampleOffset,
|
private unsafe void APESamplesToFLACSamples(int[,] inSamples, uint inSampleOffset,
|
||||||
byte[] outSamples, uint outByteOffset, uint sampleCount, int channelCount)
|
int[,] outSamples, uint outSampleOffset, uint sampleCount, int channelCount)
|
||||||
{
|
{
|
||||||
uint loopCount = sampleCount * (uint) channelCount;
|
uint loopCount = sampleCount * (uint) channelCount;
|
||||||
|
|
||||||
if ((inSamples.GetLength(0) - inSampleOffset < sampleCount) ||
|
if ((inSamples.GetLength(0) - inSampleOffset < sampleCount) ||
|
||||||
(outSamples.Length - outByteOffset < loopCount * 2))
|
(outSamples.GetLength(0) - outSampleOffset < sampleCount))
|
||||||
{
|
{
|
||||||
throw new IndexOutOfRangeException();
|
throw new IndexOutOfRangeException();
|
||||||
}
|
}
|
||||||
|
|
||||||
fixed (int* pInSamplesFixed = &inSamples[inSampleOffset, 0]) {
|
fixed (int* pInSamplesFixed = &inSamples[inSampleOffset, 0]) {
|
||||||
fixed (byte* pOutSamplesFixed = &outSamples[outByteOffset]) {
|
fixed (int * pOutSamplesFixed = &outSamples[outSampleOffset, 0]) {
|
||||||
int* pInSamples = pInSamplesFixed;
|
int* pInSamples = pInSamplesFixed;
|
||||||
short* pOutSamples = (short*)pOutSamplesFixed;
|
int* pOutSamples = pOutSamplesFixed;
|
||||||
|
|
||||||
for (int i = 0; i < loopCount; i++) {
|
for (int i = 0; i < loopCount; i++) {
|
||||||
*(pOutSamples++) = (short)*(pInSamples++);
|
*(pOutSamples++) = *(pInSamples++);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint Read(byte[] buff, uint sampleCount) {
|
public uint Read(int[,] buff, uint sampleCount) {
|
||||||
if (_apeReader.BitsPerSample != 16) {
|
if (_apeReader.BitsPerSample != 16) {
|
||||||
throw new Exception("Reading is only supported for 16 bit sample depth.");
|
throw new Exception("Reading is only supported for 16 bit sample depth.");
|
||||||
}
|
}
|
||||||
@@ -329,11 +327,11 @@ namespace CUEToolsLib {
|
|||||||
|
|
||||||
copyCount = Math.Min(samplesNeeded, SamplesInBuffer);
|
copyCount = Math.Min(samplesNeeded, SamplesInBuffer);
|
||||||
|
|
||||||
APESamplesToBytes_16(_sampleBuffer, _bufferOffset, buff, buffOffset,
|
APESamplesToFLACSamples(_sampleBuffer, _bufferOffset, buff, buffOffset,
|
||||||
copyCount, chanCount);
|
copyCount, chanCount);
|
||||||
|
|
||||||
samplesNeeded -= copyCount;
|
samplesNeeded -= copyCount;
|
||||||
buffOffset += copyCount * (uint) chanCount * 2;
|
buffOffset += copyCount;
|
||||||
_bufferOffset += copyCount;
|
_bufferOffset += copyCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -452,16 +450,11 @@ namespace CUEToolsLib {
|
|||||||
set { _wavPackReader.Tags = value; }
|
set { _wavPackReader.Tags = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint Read(byte[] buff, uint sampleCount) {
|
public uint Read(int[,] buff, uint sampleCount) {
|
||||||
if (_wavPackReader.BitsPerSample != 16) {
|
if (_wavPackReader.BitsPerSample != 16) {
|
||||||
throw new Exception("Reading is only supported for 16 bit sample depth.");
|
throw new Exception("Reading is only supported for 16 bit sample depth.");
|
||||||
}
|
}
|
||||||
int chanCount = _wavPackReader.ChannelCount;
|
_wavPackReader.Read(buff, (int) sampleCount);
|
||||||
int[,] sampleBuffer;
|
|
||||||
|
|
||||||
sampleBuffer = new int[sampleCount * 2, chanCount];
|
|
||||||
_wavPackReader.Read(sampleBuffer, (int) sampleCount);
|
|
||||||
AudioCodecsDotNet.AudioCodecsDotNet.FLACSamplesToBytes_16(sampleBuffer, 0, buff, 0, sampleCount, chanCount);
|
|
||||||
return sampleCount;
|
return sampleCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -628,6 +628,7 @@ namespace CUEToolsLib
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
sr.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (trackNumber == 0) {
|
if (trackNumber == 0) {
|
||||||
@@ -1179,7 +1180,7 @@ namespace CUEToolsLib
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe private void CalculateAccurateRipCRCsSemifast(UInt32* samples, uint count, int iTrack, uint currentOffset, uint previousOffset, uint trackLength)
|
unsafe private void CalculateAccurateRipCRCsSemifast(int* samples, uint count, int iTrack, uint currentOffset, uint previousOffset, uint trackLength)
|
||||||
{
|
{
|
||||||
fixed (uint* CRCsA = iTrack != 0 ? _tracks[iTrack - 1].OffsetedCRC : null,
|
fixed (uint* CRCsA = iTrack != 0 ? _tracks[iTrack - 1].OffsetedCRC : null,
|
||||||
CRCsB = _tracks[iTrack].OffsetedCRC,
|
CRCsB = _tracks[iTrack].OffsetedCRC,
|
||||||
@@ -1187,7 +1188,7 @@ namespace CUEToolsLib
|
|||||||
{
|
{
|
||||||
for (uint si = 0; si < count; si++)
|
for (uint si = 0; si < count; si++)
|
||||||
{
|
{
|
||||||
uint sampleValue = samples[si];
|
uint sampleValue = (uint) ((samples[2 * si] & 0xffff) + (samples[2 * si + 1] << 16));
|
||||||
int i;
|
int i;
|
||||||
int iB = Math.Max(0, _arOffsetRange - (int)(currentOffset + si));
|
int iB = Math.Max(0, _arOffsetRange - (int)(currentOffset + si));
|
||||||
int iC = Math.Min(2 * _arOffsetRange + 1, _arOffsetRange + (int)trackLength - (int)(currentOffset + si));
|
int iC = Math.Min(2 * _arOffsetRange + 1, _arOffsetRange + (int)trackLength - (int)(currentOffset + si));
|
||||||
@@ -1215,13 +1216,15 @@ namespace CUEToolsLib
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe private void CalculateAccurateRipCRCs(UInt32* samples, uint count, int iTrack, uint currentOffset, uint previousOffset, uint trackLength)
|
unsafe private void CalculateAccurateRipCRCs(int* samples, uint count, int iTrack, uint currentOffset, uint previousOffset, uint trackLength)
|
||||||
{
|
{
|
||||||
for (int si = 0; si < count; si++)
|
for (int si = 0; si < count; si++)
|
||||||
|
{
|
||||||
|
uint sampleValue = (uint)((samples[2 * si] & 0xffff) + (samples[2 * si + 1] << 16));
|
||||||
for (int oi = -_arOffsetRange; oi <= _arOffsetRange; oi++)
|
for (int oi = -_arOffsetRange; oi <= _arOffsetRange; oi++)
|
||||||
{
|
{
|
||||||
int iTrack2 = iTrack;
|
int iTrack2 = iTrack;
|
||||||
int currentOffset2 = (int) currentOffset + si - oi;
|
int currentOffset2 = (int)currentOffset + si - oi;
|
||||||
|
|
||||||
if (currentOffset2 < 5 * 588 - 1 && iTrack == 0)
|
if (currentOffset2 < 5 * 588 - 1 && iTrack == 0)
|
||||||
// we are in the skipped area at the start of the disk
|
// we are in the skipped area at the start of the disk
|
||||||
@@ -1232,7 +1235,7 @@ namespace CUEToolsLib
|
|||||||
// offset takes us to previous track
|
// offset takes us to previous track
|
||||||
{
|
{
|
||||||
iTrack2--;
|
iTrack2--;
|
||||||
currentOffset2 += (int) previousOffset;
|
currentOffset2 += (int)previousOffset;
|
||||||
}
|
}
|
||||||
else if (currentOffset2 >= trackLength - 5 * 588 && iTrack == TrackCount - 1)
|
else if (currentOffset2 >= trackLength - 5 * 588 && iTrack == TrackCount - 1)
|
||||||
// we are in the skipped area at the end of the disc
|
// we are in the skipped area at the end of the disc
|
||||||
@@ -1243,13 +1246,14 @@ namespace CUEToolsLib
|
|||||||
// offset takes us to the next track
|
// offset takes us to the next track
|
||||||
{
|
{
|
||||||
iTrack2++;
|
iTrack2++;
|
||||||
currentOffset2 -= (int) trackLength;
|
currentOffset2 -= (int)trackLength;
|
||||||
|
}
|
||||||
|
_tracks[iTrack2].OffsetedCRC[_arOffsetRange - oi] += sampleValue * (uint) (currentOffset2 + 1);
|
||||||
}
|
}
|
||||||
_tracks[iTrack2].OffsetedCRC[_arOffsetRange - oi] += (uint)(samples [si] * (currentOffset2 + 1));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe private void CalculateAccurateRipCRCsFast(UInt32* samples, uint count, int iTrack, uint currentOffset)
|
unsafe private void CalculateAccurateRipCRCsFast(int* samples, uint count, int iTrack, uint currentOffset)
|
||||||
{
|
{
|
||||||
int s1 = (int) Math.Min(count, Math.Max(0, 450 * 588 - _arOffsetRange - (int)currentOffset));
|
int s1 = (int) Math.Min(count, Math.Max(0, 450 * 588 - _arOffsetRange - (int)currentOffset));
|
||||||
int s2 = (int) Math.Min(count, Math.Max(0, 451 * 588 + _arOffsetRange - (int)currentOffset));
|
int s2 = (int) Math.Min(count, Math.Max(0, 451 * 588 + _arOffsetRange - (int)currentOffset));
|
||||||
@@ -1260,8 +1264,9 @@ namespace CUEToolsLib
|
|||||||
int magicFrameOffset = (int)currentOffset + sj - 450 * 588 + 1;
|
int magicFrameOffset = (int)currentOffset + sj - 450 * 588 + 1;
|
||||||
int firstOffset = Math.Max(-_arOffsetRange, magicFrameOffset - 588);
|
int firstOffset = Math.Max(-_arOffsetRange, magicFrameOffset - 588);
|
||||||
int lastOffset = Math.Min(magicFrameOffset - 1, _arOffsetRange);
|
int lastOffset = Math.Min(magicFrameOffset - 1, _arOffsetRange);
|
||||||
|
uint sampleValue = (uint)((samples[2 * sj] & 0xffff) + (samples[2 * sj + 1] << 16));
|
||||||
for (int oi = firstOffset; oi <= lastOffset; oi++)
|
for (int oi = firstOffset; oi <= lastOffset; oi++)
|
||||||
FrameCRCs[_arOffsetRange - oi] += (uint)(samples[sj] * (magicFrameOffset - oi));
|
FrameCRCs[_arOffsetRange - oi] += sampleValue * (uint)(magicFrameOffset - oi);
|
||||||
}
|
}
|
||||||
fixed (uint* CRCs = _tracks[iTrack].OffsetedCRC)
|
fixed (uint* CRCs = _tracks[iTrack].OffsetedCRC)
|
||||||
{
|
{
|
||||||
@@ -1269,7 +1274,7 @@ namespace CUEToolsLib
|
|||||||
currentOffset += (uint) _arOffsetRange + 1;
|
currentOffset += (uint) _arOffsetRange + 1;
|
||||||
for (uint si = 0; si < count; si++)
|
for (uint si = 0; si < count; si++)
|
||||||
{
|
{
|
||||||
uint sampleValue = samples[si];
|
uint sampleValue = (uint)((samples[2 * si] & 0xffff) + (samples[2 * si + 1] << 16));
|
||||||
stepSum += sampleValue;
|
stepSum += sampleValue;
|
||||||
baseSum += sampleValue * (uint)(currentOffset + si);
|
baseSum += sampleValue * (uint)(currentOffset + si);
|
||||||
}
|
}
|
||||||
@@ -1747,6 +1752,7 @@ namespace CUEToolsLib
|
|||||||
|
|
||||||
destTags.Remove("CUESHEET");
|
destTags.Remove("CUESHEET");
|
||||||
destTags.Remove("TITLE");
|
destTags.Remove("TITLE");
|
||||||
|
destTags.Remove("TRACKNUMBER");
|
||||||
CleanupTags(destTags, "ACCURATERIP");
|
CleanupTags(destTags, "ACCURATERIP");
|
||||||
CleanupTags(destTags, "REPLAYGAIN");
|
CleanupTags(destTags, "REPLAYGAIN");
|
||||||
|
|
||||||
@@ -1781,7 +1787,7 @@ namespace CUEToolsLib
|
|||||||
{
|
{
|
||||||
const int buffLen = 16384;
|
const int buffLen = 16384;
|
||||||
int iTrack, iIndex;
|
int iTrack, iIndex;
|
||||||
byte[] buff = new byte[buffLen * 2 * 2];
|
int[,] sampleBuffer = new int[buffLen, 2];
|
||||||
TrackInfo track;
|
TrackInfo track;
|
||||||
IAudioSource audioSource = null;
|
IAudioSource audioSource = null;
|
||||||
IAudioDest audioDest = null;
|
IAudioDest audioDest = null;
|
||||||
@@ -1854,8 +1860,6 @@ namespace CUEToolsLib
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int[,] sampleBuffer = null;
|
|
||||||
|
|
||||||
if (_accurateRip && noOutput)
|
if (_accurateRip && noOutput)
|
||||||
for (iTrack = 0; iTrack < TrackCount; iTrack++)
|
for (iTrack = 0; iTrack < TrackCount; iTrack++)
|
||||||
for (int iCRC = 0; iCRC < 10 * 588; iCRC++)
|
for (int iCRC = 0; iCRC < 10 * 588; iCRC++)
|
||||||
@@ -1966,10 +1970,7 @@ namespace CUEToolsLib
|
|||||||
lastTrackPercent = trackPercent;
|
lastTrackPercent = trackPercent;
|
||||||
}
|
}
|
||||||
|
|
||||||
audioSource.Read(buff, copyCount);
|
audioSource.Read(sampleBuffer, copyCount);
|
||||||
if (sampleBuffer == null || sampleBuffer.GetLength(0) < copyCount)
|
|
||||||
sampleBuffer = new int[copyCount, audioSource.ChannelCount];
|
|
||||||
AudioCodecsDotNet.AudioCodecsDotNet.BytesToFLACSamples_16(buff, 0, sampleBuffer, 0, copyCount, audioSource.ChannelCount);
|
|
||||||
if (!discardOutput) audioDest.Write(sampleBuffer, copyCount);
|
if (!discardOutput) audioDest.Write(sampleBuffer, copyCount);
|
||||||
if (_config.detectHDCD && hdcdDecoder != null)
|
if (_config.detectHDCD && hdcdDecoder != null)
|
||||||
{
|
{
|
||||||
@@ -1987,23 +1988,22 @@ namespace CUEToolsLib
|
|||||||
}
|
}
|
||||||
if (_accurateRip && noOutput && (iTrack != 0 || iIndex != 0))
|
if (_accurateRip && noOutput && (iTrack != 0 || iIndex != 0))
|
||||||
unsafe {
|
unsafe {
|
||||||
fixed (byte * pBuff = &buff[0])
|
fixed (int *pSampleBuff = &sampleBuffer[0,0])
|
||||||
{
|
{
|
||||||
UInt32 * samples = (UInt32*) pBuff;
|
|
||||||
int iTrack2 = iTrack - (iIndex == 0 ? 1 : 0);
|
int iTrack2 = iTrack - (iIndex == 0 ? 1 : 0);
|
||||||
|
|
||||||
uint si1 = (uint) Math.Min(copyCount, Math.Max(0, 588*(iTrack2 == 0?10:5) - (int) currentOffset));
|
uint si1 = (uint) Math.Min(copyCount, Math.Max(0, 588*(iTrack2 == 0?10:5) - (int) currentOffset));
|
||||||
uint si2 = (uint) Math.Min(copyCount, Math.Max(si1, trackLength - (int) currentOffset - 588 * (iTrack2 == TrackCount - 1?10:5)));
|
uint si2 = (uint) Math.Min(copyCount, Math.Max(si1, trackLength - (int) currentOffset - 588 * (iTrack2 == TrackCount - 1?10:5)));
|
||||||
if (iTrack2 == 0)
|
if (iTrack2 == 0)
|
||||||
CalculateAccurateRipCRCs (samples, si1, iTrack2, currentOffset, previousOffset, trackLength);
|
CalculateAccurateRipCRCs (pSampleBuff, si1, iTrack2, currentOffset, previousOffset, trackLength);
|
||||||
else
|
else
|
||||||
CalculateAccurateRipCRCsSemifast (samples, si1, iTrack2, currentOffset, previousOffset, trackLength);
|
CalculateAccurateRipCRCsSemifast(pSampleBuff, si1, iTrack2, currentOffset, previousOffset, trackLength);
|
||||||
if (si2 > si1)
|
if (si2 > si1)
|
||||||
CalculateAccurateRipCRCsFast (samples+si1, (uint)(si2 - si1), iTrack2, currentOffset + si1);
|
CalculateAccurateRipCRCsFast(pSampleBuff + si1 * 2, (uint)(si2 - si1), iTrack2, currentOffset + si1);
|
||||||
if (iTrack2 == TrackCount - 1)
|
if (iTrack2 == TrackCount - 1)
|
||||||
CalculateAccurateRipCRCs (samples+si2, copyCount-si2, iTrack2, currentOffset+si2, previousOffset, trackLength);
|
CalculateAccurateRipCRCs(pSampleBuff + si2*2, copyCount - si2, iTrack2, currentOffset + si2, previousOffset, trackLength);
|
||||||
else
|
else
|
||||||
CalculateAccurateRipCRCsSemifast (samples + si2, copyCount - si2, iTrack2, currentOffset + si2, previousOffset, trackLength);
|
CalculateAccurateRipCRCsSemifast(pSampleBuff + si2*2, copyCount - si2, iTrack2, currentOffset + si2, previousOffset, trackLength);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
currentOffset += copyCount;
|
currentOffset += copyCount;
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ namespace FLACDotNet {
|
|||||||
_decoderActive = false;
|
_decoderActive = false;
|
||||||
|
|
||||||
_sampleOffset = 0;
|
_sampleOffset = 0;
|
||||||
_samplesWaiting = false;
|
_samplesWaiting = 0;
|
||||||
_sampleBuffer = nullptr;
|
_sampleBuffer = nullptr;
|
||||||
_path = path;
|
_path = path;
|
||||||
|
|
||||||
@@ -138,7 +138,7 @@ namespace FLACDotNet {
|
|||||||
}
|
}
|
||||||
void set(Int64 offset) {
|
void set(Int64 offset) {
|
||||||
_sampleOffset = offset;
|
_sampleOffset = offset;
|
||||||
_samplesWaiting = false;
|
_samplesWaiting = 0;
|
||||||
if (!FLAC__stream_decoder_seek_absolute(_decoder, offset)) {
|
if (!FLAC__stream_decoder_seek_absolute(_decoder, offset)) {
|
||||||
throw gcnew Exception("Unable to seek.");
|
throw gcnew Exception("Unable to seek.");
|
||||||
}
|
}
|
||||||
@@ -237,20 +237,18 @@ namespace FLACDotNet {
|
|||||||
_decoderActive = false;
|
_decoderActive = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Int32 Read([Out] array<Int32, 2>^% sampleBuffer) {
|
Int32 Read([Out] array<Int32, 2>^% sampleBuffer)
|
||||||
int sampleCount;
|
{
|
||||||
|
while (_samplesWaiting == 0) {
|
||||||
while (!_samplesWaiting) {
|
|
||||||
if (!FLAC__stream_decoder_process_single(_decoder)) {
|
if (!FLAC__stream_decoder_process_single(_decoder)) {
|
||||||
throw gcnew Exception("An error occurred while decoding.");
|
throw gcnew Exception("An error occurred while decoding.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sampleCount = _sampleBuffer->GetLength(0);
|
int sampleCount = _samplesWaiting;
|
||||||
sampleBuffer = _sampleBuffer;
|
sampleBuffer = _sampleBuffer;
|
||||||
_sampleOffset += sampleCount;
|
_sampleOffset += sampleCount;
|
||||||
_samplesWaiting = false;
|
_samplesWaiting = 0;
|
||||||
|
|
||||||
return sampleCount;
|
return sampleCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -262,7 +260,7 @@ namespace FLACDotNet {
|
|||||||
Int64 _sampleCount, _sampleOffset;
|
Int64 _sampleCount, _sampleOffset;
|
||||||
Int32 _bitsPerSample, _channelCount, _sampleRate;
|
Int32 _bitsPerSample, _channelCount, _sampleRate;
|
||||||
array<Int32, 2>^ _sampleBuffer;
|
array<Int32, 2>^ _sampleBuffer;
|
||||||
bool _samplesWaiting;
|
int _samplesWaiting;
|
||||||
NameValueCollection^ _tags;
|
NameValueCollection^ _tags;
|
||||||
String^ _path;
|
String^ _path;
|
||||||
bool _decoderActive;
|
bool _decoderActive;
|
||||||
@@ -272,7 +270,7 @@ namespace FLACDotNet {
|
|||||||
{
|
{
|
||||||
Int32 sampleCount = frame->header.blocksize;
|
Int32 sampleCount = frame->header.blocksize;
|
||||||
|
|
||||||
if (_samplesWaiting) {
|
if (_samplesWaiting > 0) {
|
||||||
throw gcnew Exception("Received unrequested samples.");
|
throw gcnew Exception("Received unrequested samples.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -283,7 +281,7 @@ namespace FLACDotNet {
|
|||||||
throw gcnew Exception("Format changes within a file are not allowed.");
|
throw gcnew Exception("Format changes within a file are not allowed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((_sampleBuffer == nullptr) || (_sampleBuffer->GetLength(0) != sampleCount)) {
|
if ((_sampleBuffer == nullptr) || (_sampleBuffer->GetLength(0) < sampleCount)) {
|
||||||
_sampleBuffer = gcnew array<Int32, 2>(sampleCount, _channelCount);
|
_sampleBuffer = gcnew array<Int32, 2>(sampleCount, _channelCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -299,7 +297,7 @@ namespace FLACDotNet {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_samplesWaiting = true;
|
_samplesWaiting = sampleCount;
|
||||||
|
|
||||||
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
|
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user