Optimizing AccurateRip

This commit is contained in:
chudov
2010-02-10 02:15:36 +00:00
parent 8373c83c78
commit f09d5bab6d
2 changed files with 212 additions and 279 deletions

View File

@@ -23,103 +23,7 @@ namespace CUETools.AccurateRip
Init(); Init();
} }
unsafe private void CalculateFrame450CRCs(int* samples, int count, int iTrack, int currentOffset)
/*
Like in the slow function, the outer loop enumerates samples, and the inner loops enumerate offsets.
I move the IF's out of the innter loop by breaking up offsets into three categories.
First range of offsets are those offsets, which can move our current sample into previous track.
Second range of offsets are those offsets, which don't move our current sample out of current track.
And the third range of offsets are those offsets, which move our current sample into next track.
The first boundary is the (positive) distance from the track start to the current sample. E.G. the 13th sample of a track (currentOffset + si == 13) will be moved into previous track by any offset > 13, and will stay in the current track when offset is <= 13.
The second boundary is the (negative) distance from the next track start to the current sample. (trackLength - (currentOffset + si)).
I use Max/Min functions to make sure the boundaries don't leave the offset range that i'm using.
For each range i calculate baseSum, which is an AR CRC of the current sample, using the last offset in this range.
All the other CRC's in this offset range are calculated by consequently adding sampleValue to the previous sum.
*/
unsafe private void CalculateAccurateRipCRCsSemifast(int* samples, int count, int iTrack, int currentOffset, int previousOffset, int trackLength)
{
fixed (uint* CRCsA = &_offsetedCRC[Math.Max(0, iTrack - 1), 0],
CRCsB = &_offsetedCRC[iTrack, 0],
CRCsC = &_offsetedCRC[Math.Min(_toc.AudioTracks - 1, iTrack + 1), 0]
)
{
for (int si = 0; si < count; si++)
{
uint sampleValue = (uint)((samples[2 * si] & 0xffff) + (samples[2 * si + 1] << 16));
int i;
int iB = Math.Max(0, _arOffsetRange - (int)(currentOffset + si));
int iC = Math.Min(2 * _arOffsetRange + 1, _arOffsetRange + (int)trackLength - (int)(currentOffset + si));
uint baseSumA = sampleValue * (uint)(previousOffset + 1 - iB);
for (i = 0; i < iB; i++)
{
CRCsA[i] += baseSumA;
baseSumA += sampleValue;
//CRC32A[i] = _crc32.ComputeChecksum(CRC32A[i], sampleValue);
}
uint baseSumB = sampleValue * (uint)Math.Max(1, (int)(currentOffset + si) - _arOffsetRange + 1);
for (i = iB; i < iC; i++)
{
CRCsB[i] += baseSumB;
baseSumB += sampleValue;
//CRC32B[i] = _crc32.ComputeChecksum(CRC32B[i], sampleValue);
}
uint baseSumC = sampleValue;
for (i = iC; i <= 2 * _arOffsetRange; i++)
{
CRCsC[i] += baseSumC;
baseSumC += sampleValue;
//CRC32C[i] = _crc32.ComputeChecksum(CRC32C[i], sampleValue);
}
}
return;
}
}
unsafe private void CalculateAccurateRipCRCs(int* samples, int count, int iTrack, int currentOffset, int previousOffset, int trackLength)
{
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++)
{
int iTrack2 = iTrack;
int currentOffset2 = (int)currentOffset + si - oi;
if (currentOffset2 < 5 * 588 - 1 && iTrack == 0)
// we are in the skipped area at the start of the disk
{
continue;
}
else if (currentOffset2 < 0)
// offset takes us to previous track
{
iTrack2--;
currentOffset2 += (int)previousOffset;
}
else if (currentOffset2 >= trackLength - 5 * 588 && iTrack == _toc.AudioTracks - 1)
// we are in the skipped area at the end of the disc
{
continue;
}
else if (currentOffset2 >= trackLength)
// offset takes us to the next track
{
iTrack2++;
currentOffset2 -= (int)trackLength;
}
_offsetedCRC[iTrack2, _arOffsetRange - oi] += sampleValue * (uint)(currentOffset2 + 1);
}
}
}
unsafe private void CalculateAccurateRipCRCsFast(int* samples, int count, int iTrack, int currentOffset)
{ {
int s1 = Math.Min(count, Math.Max(0, 450 * 588 - _arOffsetRange - currentOffset)); int s1 = Math.Min(count, Math.Max(0, 450 * 588 - _arOffsetRange - currentOffset));
int s2 = Math.Min(count, Math.Max(0, 451 * 588 + _arOffsetRange - currentOffset)); int s2 = Math.Min(count, Math.Max(0, 451 * 588 + _arOffsetRange - currentOffset));
@@ -134,56 +38,6 @@ All the other CRC's in this offset range are calculated by consequently adding s
for (int oi = firstOffset; oi <= lastOffset; oi++) for (int oi = firstOffset; oi <= lastOffset; oi++)
FrameCRCs[_arOffsetRange - oi] += sampleValue * (uint)(magicFrameOffset - oi); FrameCRCs[_arOffsetRange - oi] += sampleValue * (uint)(magicFrameOffset - oi);
} }
uint crc32 = _offsetedCRC32[_currentTrack, 10 * 588 - 1];
uint crcwn = _offsetedCRCWN[_currentTrack, 10 * 588 - 1];
int crcnulls = _offsetedCRCNulls[_currentTrack, 10 * 588 - 1];
fixed (uint* CRCs = &_offsetedCRC[iTrack, 0], t = _crc32.table)
{
uint baseSum = 0, stepSum = 0;
int* s = samples;
for (uint mult = 0; mult < count; mult++)
{
uint lo = (uint)*(s++) & 0xffff;
crc32 = (crc32 >> 8) ^ t[(byte)(crc32 ^ lo)];
crc32 = (crc32 >> 8) ^ t[(byte)(crc32 ^ (lo >> 8))];
if (lo != 0)
{
crcwn = (crcwn >> 8) ^ t[(byte)(crcwn ^ lo)];
crcwn = (crcwn >> 8) ^ t[(byte)(crcwn ^ (lo >> 8))];
}
else crcnulls++;
uint hi = (uint)*(s++) & 0xffff;
crc32 = (crc32 >> 8) ^ t[(byte)(crc32 ^ hi)];
crc32 = (crc32 >> 8) ^ t[(byte)(crc32 ^ (hi >> 8))];
if (hi != 0)
{
crcwn = (crcwn >> 8) ^ t[(byte)(crcwn ^ hi)];
crcwn = (crcwn >> 8) ^ t[(byte)(crcwn ^ (hi >> 8))];
}
else crcnulls++;
uint sampleValue = lo + (hi << 16);
stepSum += sampleValue;
baseSum += sampleValue * mult;
}
currentOffset += _arOffsetRange + 1;
baseSum += stepSum * (uint)currentOffset;
for (int i = 2 * _arOffsetRange; i >= 0; i--)
{
CRCs[i] += baseSum;
baseSum -= stepSum;
}
}
_offsetedCRC32[_currentTrack, 10 * 588 - 1] = crc32;
_offsetedCRCWN[_currentTrack, 10 * 588 - 1] = crcwn;
_offsetedCRCNulls[_currentTrack, 10 * 588 - 1] = crcnulls;
}
public uint CRC(int iTrack)
{
return _offsetedCRC[iTrack, _arOffsetRange];
} }
public uint Confidence(int iTrack) public uint Confidence(int iTrack)
@@ -264,9 +118,77 @@ All the other CRC's in this offset range are calculated by consequently adding s
return _backupCRC[iTrack]; return _backupCRC[iTrack];
} }
public uint CRC(int iTrack)
{
return CRC(iTrack, 0);
}
public uint CRC(int iTrack, int oi) public uint CRC(int iTrack, int oi)
{ {
return _offsetedCRC[iTrack, _arOffsetRange - oi]; if (oi == 0)
{
return
((iTrack == _toc.AudioTracks - 1)
? _offsetedCRCAR[iTrack + 1, 20 * 588 - 5 * 588]
: _offsetedCRCAR[iTrack + 1, 20 * 588]) -
((iTrack == 0)
? _offsetedCRCAR[iTrack + 1, 5 * 588 - 1]
: 0);
}
if (oi < 0)
{
uint crc = 0;
if (iTrack > 0)
{
uint crcA = _offsetedCRCAR[iTrack, 20 * 588] - _offsetedCRCAR[iTrack, 20 * 588 + oi];
uint sumA = _offsetedCRCSM[iTrack, 20 * 588] - _offsetedCRCSM[iTrack, 20 * 588 + oi];
uint posA = _toc[iTrack + _toc.FirstAudio - 1].Length * 588 + (uint)oi;
crc = crcA - sumA * posA;
}
uint crcB
= ((iTrack == _toc.AudioTracks - 1)
? _offsetedCRCAR[iTrack + 1, 20 * 588 - 5 * 588 + oi]
: _offsetedCRCAR[iTrack + 1, 20 * 588 + oi])
- ((iTrack == 0)
? _offsetedCRCAR[iTrack + 1, 5 * 588 - 1 + oi]
: 0);
uint sumB
= ((iTrack == _toc.AudioTracks - 1)
? _offsetedCRCSM[iTrack + 1, 20 * 588 - 5 * 588 + oi]
: _offsetedCRCSM[iTrack + 1, 20 * 588 + oi])
- ((iTrack == 0)
? _offsetedCRCSM[iTrack + 1, 5 * 588 - 1 + oi]
: 0);
uint posB = (uint)-oi;
return crc + crcB + sumB * posB;
}
else
{
uint crcA
= ((iTrack == _toc.AudioTracks - 1)
? _offsetedCRCAR[iTrack + 1, 20 * 588 - 5 * 588 + oi]
: _offsetedCRCAR[iTrack + 1, 20 * 588])
- ((iTrack == 0)
? _offsetedCRCAR[iTrack + 1, 5 * 588 + oi - 1]
: _offsetedCRCAR[iTrack + 1, oi]);
uint sumA
= ((iTrack == _toc.AudioTracks - 1)
? _offsetedCRCSM[iTrack + 1, 20 * 588 - 5 * 588 + oi]
: _offsetedCRCSM[iTrack + 1, 20 * 588])
- ((iTrack == 0)
? _offsetedCRCSM[iTrack + 1, 5 * 588 + oi - 1]
: _offsetedCRCSM[iTrack + 1, oi]);
uint posA = (uint)oi;
uint crc = crcA - sumA * posA;
if (iTrack < _toc.AudioTracks - 1)
{
uint crcB = _offsetedCRCAR[iTrack + 2, oi];
uint sumB = _offsetedCRCSM[iTrack + 2, oi];
uint posB = _toc[iTrack + _toc.FirstAudio].Length * 588 + (uint)-oi;
crc += crcB + sumB * posB;
}
return crc;
}
} }
public uint CRC32(int iTrack) public uint CRC32(int iTrack)
@@ -291,17 +213,17 @@ All the other CRC's in this offset range are calculated by consequently adding s
if (oi > 0 && (iTrack == 0 || (iTrack == 1 && _toc[_toc.FirstAudio].Pregap == 0))) if (oi > 0 && (iTrack == 0 || (iTrack == 1 && _toc[_toc.FirstAudio].Pregap == 0)))
{ {
// Calculate track CRC skipping first oi samples by 'subtracting' their CRC // Calculate track CRC skipping first oi samples by 'subtracting' their CRC
crc = _crc32.Combine(_offsetedCRC32[iTrack, oi - 1], _offsetedCRC32[iTrack, 10 * 588 - 1], trackLength - oi * 4); crc = _crc32.Combine(_offsetedCRC32[iTrack, oi], _offsetedCRC32[iTrack, 20 * 588], trackLength - oi * 4);
// Use 0xffffffff as an initial state // Use 0xffffffff as an initial state
crc = _crc32.Combine(0xffffffff, crc, trackLength - oi * 4); crc = _crc32.Combine(0xffffffff, crc, trackLength - oi * 4);
} }
else if (oi < 0 && iTrack == _toc.AudioTracks) else if (oi < 0 && iTrack == _toc.AudioTracks)
{ {
crc = _crc32.Combine(crc, _offsetedCRC32[iTrack, 10 * 588 + oi - 1], trackLength + oi * 4); crc = _crc32.Combine(crc, _offsetedCRC32[iTrack, 20 * 588 + oi], trackLength + oi * 4);
} }
else else
{ {
crc = _crc32.Combine(crc, _offsetedCRC32[iTrack, 10 * 588 - 1], trackLength); crc = _crc32.Combine(crc, _offsetedCRC32[iTrack, 20 * 588], trackLength);
} }
if (oi > 0 && iTrack == _toc.AudioTracks) if (oi > 0 && iTrack == _toc.AudioTracks)
crc = _crc32.Combine(crc, 0, oi * 4); crc = _crc32.Combine(crc, 0, oi * 4);
@@ -314,28 +236,28 @@ All the other CRC's in this offset range are calculated by consequently adding s
if (oi > 0) if (oi > 0)
{ {
// Calculate track CRC skipping first oi samples by 'subtracting' their CRC // Calculate track CRC skipping first oi samples by 'subtracting' their CRC
crc = _crc32.Combine(_offsetedCRC32[iTrack, oi - 1], _offsetedCRC32[iTrack, 10 * 588 - 1], trackLength - oi * 4); crc = _crc32.Combine(_offsetedCRC32[iTrack, oi], _offsetedCRC32[iTrack, 20 * 588], trackLength - oi * 4);
// Use 0xffffffff as an initial state // Use 0xffffffff as an initial state
crc = _crc32.Combine(0xffffffff, crc, trackLength - oi * 4); crc = _crc32.Combine(0xffffffff, crc, trackLength - oi * 4);
// Add oi samples from next track CRC // Add oi samples from next track CRC
if (iTrack < _toc.AudioTracks) if (iTrack < _toc.AudioTracks)
crc = _crc32.Combine(crc, _offsetedCRC32[iTrack + 1, oi - 1], oi * 4); crc = _crc32.Combine(crc, _offsetedCRC32[iTrack + 1, oi], oi * 4);
else else
crc = _crc32.Combine(crc, 0, oi * 4); crc = _crc32.Combine(crc, 0, oi * 4);
} }
else if (oi < 0) else if (oi < 0)
{ {
// Calculate CRC of previous track's last oi samples by 'subtracting' it's last CRCs // Calculate CRC of previous track's last oi samples by 'subtracting' it's last CRCs
crc = _crc32.Combine(_offsetedCRC32[iTrack - 1, 10 * 588 + oi - 1], _offsetedCRC32[iTrack - 1, 10 * 588 - 1], -oi * 4); crc = _crc32.Combine(_offsetedCRC32[iTrack - 1, 20 * 588 + oi], _offsetedCRC32[iTrack - 1, 20 * 588], -oi * 4);
// Use 0xffffffff as an initial state // Use 0xffffffff as an initial state
crc = _crc32.Combine(0xffffffff, crc, -oi * 4); crc = _crc32.Combine(0xffffffff, crc, -oi * 4);
// Add this track's CRC without last oi samples // Add this track's CRC without last oi samples
crc = _crc32.Combine(crc, _offsetedCRC32[iTrack, 10 * 588 + oi - 1], trackLength + oi * 4); crc = _crc32.Combine(crc, _offsetedCRC32[iTrack, 20 * 588 + oi], trackLength + oi * 4);
} }
else // oi == 0 else // oi == 0
{ {
// Use 0xffffffff as an initial state // Use 0xffffffff as an initial state
crc = _crc32.Combine(0xffffffff, _offsetedCRC32[iTrack, 10 * 588 - 1], trackLength); crc = _crc32.Combine(0xffffffff, _offsetedCRC32[iTrack, 20 * 588], trackLength);
} }
} }
_offsetedCRC32Res[iTrack, _arOffsetRange + oi] = crc ^ 0xffffffff; _offsetedCRC32Res[iTrack, _arOffsetRange + oi] = crc ^ 0xffffffff;
@@ -345,7 +267,7 @@ All the other CRC's in this offset range are calculated by consequently adding s
public uint CRCWONULL(int iTrack) public uint CRCWONULL(int iTrack)
{ {
return CRCWONULL(iTrack, 0); return CRCWONULL(iTrack, 0);
} }
public uint CRCWONULL(int iTrack, int oi) public uint CRCWONULL(int iTrack, int oi)
@@ -358,8 +280,8 @@ All the other CRC's in this offset range are calculated by consequently adding s
for (iTrack = 0; iTrack <= _toc.AudioTracks; iTrack++) for (iTrack = 0; iTrack <= _toc.AudioTracks; iTrack++)
{ {
int trackLength = (int)(iTrack > 0 ? _toc[iTrack + _toc.FirstAudio - 1].Length : _toc[_toc.FirstAudio].Pregap) * 588 * 4 int trackLength = (int)(iTrack > 0 ? _toc[iTrack + _toc.FirstAudio - 1].Length : _toc[_toc.FirstAudio].Pregap) * 588 * 4
- _offsetedCRCNulls[iTrack, 10 * 588 - 1] * 2; - _offsetedCRCNulls[iTrack, 20 * 588] * 2;
crc = _crc32.Combine(crc, _offsetedCRCWN[iTrack, 10 * 588 - 1], trackLength); crc = _crc32.Combine(crc, _offsetedCRCWN[iTrack, 20 * 588], trackLength);
} }
iTrack = 0; iTrack = 0;
} }
@@ -368,41 +290,41 @@ All the other CRC's in this offset range are calculated by consequently adding s
int trackLength = (int)(iTrack > 0 ? _toc[iTrack + _toc.FirstAudio - 1].Length : _toc[_toc.FirstAudio].Pregap) * 588 * 4; int trackLength = (int)(iTrack > 0 ? _toc[iTrack + _toc.FirstAudio - 1].Length : _toc[_toc.FirstAudio].Pregap) * 588 * 4;
if (oi > 0) if (oi > 0)
{ {
int nonzeroPrevLength = trackLength - oi * 4 - int nonzeroPrevLength = trackLength - oi * 4 -
(_offsetedCRCNulls[iTrack, 10 * 588 - 1] - _offsetedCRCNulls[iTrack, oi - 1]) * 2; (_offsetedCRCNulls[iTrack, 20 * 588] - _offsetedCRCNulls[iTrack, oi]) * 2;
// Calculate track CRC skipping first oi samples by 'subtracting' their CRC // Calculate track CRC skipping first oi samples by 'subtracting' their CRC
crc = _crc32.Combine( crc = _crc32.Combine(
_offsetedCRCWN[iTrack, oi - 1], _offsetedCRCWN[iTrack, oi],
_offsetedCRCWN[iTrack, 10 * 588 - 1], _offsetedCRCWN[iTrack, 20 * 588],
nonzeroPrevLength); nonzeroPrevLength);
// Use 0xffffffff as an initial state // Use 0xffffffff as an initial state
crc = _crc32.Combine(0xffffffff, crc, nonzeroPrevLength); crc = _crc32.Combine(0xffffffff, crc, nonzeroPrevLength);
// Add oi samples from next track CRC // Add oi samples from next track CRC
if (iTrack < _toc.AudioTracks) if (iTrack < _toc.AudioTracks)
crc = _crc32.Combine(crc, crc = _crc32.Combine(crc,
_offsetedCRCWN[iTrack + 1, oi - 1], _offsetedCRCWN[iTrack + 1, oi],
oi * 4 - _offsetedCRCNulls[iTrack + 1, oi - 1] * 2); oi * 4 - _offsetedCRCNulls[iTrack + 1, oi] * 2);
} }
else if (oi < 0) else if (oi < 0)
{ {
int nonzeroPrevLength = -oi * 4 - int nonzeroPrevLength = -oi * 4 -
(_offsetedCRCNulls[iTrack - 1, 10 * 588 - 1] - _offsetedCRCNulls[iTrack - 1, 10 * 588 + oi - 1]) * 2; (_offsetedCRCNulls[iTrack - 1, 20 * 588] - _offsetedCRCNulls[iTrack - 1, 20 * 588 + oi]) * 2;
// Calculate CRC of previous track's last oi samples by 'subtracting' it's last CRCs // Calculate CRC of previous track's last oi samples by 'subtracting' it's last CRCs
crc = _crc32.Combine( crc = _crc32.Combine(
_offsetedCRCWN[iTrack - 1, 10 * 588 + oi - 1], _offsetedCRCWN[iTrack - 1, 20 * 588 + oi],
_offsetedCRCWN[iTrack - 1, 10 * 588 - 1], _offsetedCRCWN[iTrack - 1, 20 * 588],
nonzeroPrevLength); nonzeroPrevLength);
// Use 0xffffffff as an initial state // Use 0xffffffff as an initial state
crc = _crc32.Combine(0xffffffff, crc, nonzeroPrevLength); crc = _crc32.Combine(0xffffffff, crc, nonzeroPrevLength);
// Add this track's CRC without last oi samples // Add this track's CRC without last oi samples
crc = _crc32.Combine(crc, crc = _crc32.Combine(crc,
_offsetedCRCWN[iTrack, 10 * 588 + oi - 1], _offsetedCRCWN[iTrack, 20 * 588 + oi],
trackLength + oi * 4 - _offsetedCRCNulls[iTrack, 10 * 588 + oi - 1] * 2); trackLength + oi * 4 - _offsetedCRCNulls[iTrack, 20 * 588 + oi] * 2);
} }
else // oi == 0 else // oi == 0
{ {
// Use 0xffffffff as an initial state // Use 0xffffffff as an initial state
crc = _crc32.Combine(0xffffffff, _offsetedCRCWN[iTrack, 10 * 588 - 1], trackLength - _offsetedCRCNulls[iTrack, 10 * 588 - 1] * 2); crc = _crc32.Combine(0xffffffff, _offsetedCRCWN[iTrack, 20 * 588], trackLength - _offsetedCRCNulls[iTrack, 20 * 588] * 2);
} }
} }
_offsetedCRCWNRes[iTrack, _arOffsetRange + oi] = crc ^ 0xffffffff; _offsetedCRCWNRes[iTrack, _arOffsetRange + oi] = crc ^ 0xffffffff;
@@ -426,92 +348,99 @@ All the other CRC's in this offset range are calculated by consequently adding s
return _offsetedFrame450CRC[iTrack, _arOffsetRange - oi]; return _offsetedFrame450CRC[iTrack, _arOffsetRange - oi];
} }
public unsafe void CalculateCRCs(int* pSampleBuff, int count, int currentOffset) public unsafe void CalculateCRCs(int* pSampleBuff, int count, int currentOffset, int offs)
{ {
uint crc = _offsetedCRC32[_currentTrack, 10 * 588 - 1]; uint crcar = _offsetedCRCAR[_currentTrack, 20 * 588];
uint crcwn = _offsetedCRCWN[_currentTrack, 10 * 588 - 1]; uint crcsm = _offsetedCRCSM[_currentTrack, 20 * 588];
int crcnulls = _offsetedCRCNulls[_currentTrack, 10 * 588 - 1]; uint crc = _offsetedCRC32[_currentTrack, 20 * 588];
uint crcwn = _offsetedCRCWN[_currentTrack, 20 * 588];
int crcnulls = _offsetedCRCNulls[_currentTrack, 20 * 588];
fixed (uint* t = _crc32.table) fixed (uint* t = _crc32.table)
{ {
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++)
{ {
int s; _offsetedCRCAR[_currentTrack, offs + i] = crcar;
byte s0, s1; _offsetedCRCSM[_currentTrack, offs + i] = crcsm;
_offsetedCRC32[_currentTrack, offs + i] = crc;
_offsetedCRCWN[_currentTrack, offs + i] = crcwn;
_offsetedCRCNulls[_currentTrack, offs + i] = crcnulls;
s = *(pSampleBuff++); uint lo = (uint)*(pSampleBuff++);
s0 = (byte)s; crc = (crc >> 8) ^ t[(byte)(crc ^ lo)];
s1 = (byte)(s >> 8); crc = (crc >> 8) ^ t[(byte)(crc ^ (lo >> 8))];
crc = (crc >> 8) ^ t[((byte)crc) ^ s0]; if (lo != 0)
crc = (crc >> 8) ^ t[((byte)crc) ^ s1];
if (s != 0)
{ {
crcwn = (crcwn >> 8) ^ t[(byte)(crcwn ^ s0)]; crcwn = (crcwn >> 8) ^ t[(byte)(crcwn ^ lo)];
crcwn = (crcwn >> 8) ^ t[(byte)(crcwn ^ s1)]; crcwn = (crcwn >> 8) ^ t[(byte)(crcwn ^ (lo >> 8))];
} }
else crcnulls++; else crcnulls++;
s = *(pSampleBuff++); uint hi = (uint)*(pSampleBuff++);
s0 = (byte)s; crc = (crc >> 8) ^ t[(byte)(crc ^ hi)];
s1 = (byte)(s >> 8); crc = (crc >> 8) ^ t[(byte)(crc ^ (hi >> 8))];
crc = (crc >> 8) ^ t[((byte)crc) ^ s0]; if (hi != 0)
crc = (crc >> 8) ^ t[((byte)crc) ^ s1];
if (s != 0)
{ {
crcwn = (crcwn >> 8) ^ t[(byte)(crcwn ^ s0)]; crcwn = (crcwn >> 8) ^ t[(byte)(crcwn ^ hi)];
crcwn = (crcwn >> 8) ^ t[(byte)(crcwn ^ s1)]; crcwn = (crcwn >> 8) ^ t[(byte)(crcwn ^ (hi >> 8))];
} }
else crcnulls++; else crcnulls++;
_offsetedCRC32[_currentTrack, currentOffset + i] = crc; uint sampleValue = (lo & 0xffff) + (hi << 16);
_offsetedCRCWN[_currentTrack, currentOffset + i] = crcwn; crcsm += sampleValue;
_offsetedCRCNulls[_currentTrack, currentOffset + i] = crcnulls; crcar += sampleValue * (uint)(currentOffset + i + 1);
} }
} }
_offsetedCRC32[_currentTrack, 10 * 588 - 1] = crc; //_offsetedCRCAR[_currentTrack, offs + count] = crcar;
_offsetedCRCWN[_currentTrack, 10 * 588 - 1] = crcwn; //_offsetedCRCSM[_currentTrack, offs + count] = crcsm;
_offsetedCRCNulls[_currentTrack, 10 * 588 - 1] = crcnulls;
_offsetedCRCAR[_currentTrack, 20 * 588] = crcar;
_offsetedCRCSM[_currentTrack, 20 * 588] = crcsm;
_offsetedCRC32[_currentTrack, 20 * 588] = crc;
_offsetedCRCWN[_currentTrack, 20 * 588] = crcwn;
_offsetedCRCNulls[_currentTrack, 20 * 588] = crcnulls;
} }
public unsafe void CalculateCRCs(int* pSampleBuff, int count) public unsafe void CalculateCRCs(int* pSampleBuff, int count, int currentOffset)
{ {
uint crc = _offsetedCRC32[_currentTrack, 10 * 588 - 1]; uint crcar = _offsetedCRCAR[_currentTrack, 20 * 588];
uint crcwn = _offsetedCRCWN[_currentTrack, 10 * 588 - 1]; uint crcsm = _offsetedCRCSM[_currentTrack, 20 * 588];
int crcnulls = _offsetedCRCNulls[_currentTrack, 10 * 588 - 1]; uint crc = _offsetedCRC32[_currentTrack, 20 * 588];
uint crcwn = _offsetedCRCWN[_currentTrack, 20 * 588];
int crcnulls = _offsetedCRCNulls[_currentTrack, 20 * 588];
fixed (uint* t = _crc32.table) fixed (uint* t = _crc32.table)
{ {
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++)
{ {
int s; uint lo = (uint)*(pSampleBuff++);
byte s0, s1; crc = (crc >> 8) ^ t[(byte)(crc ^ lo)];
crc = (crc >> 8) ^ t[(byte)(crc ^ (lo >> 8))];
s = *(pSampleBuff++); if (lo != 0)
s0 = (byte)s;
s1 = (byte)(s >> 8);
crc = (crc >> 8) ^ t[((byte)crc) ^ s0];
crc = (crc >> 8) ^ t[((byte)crc) ^ s1];
if (s != 0)
{ {
crcwn = (crcwn >> 8) ^ t[(byte)(crcwn ^ s0)]; crcwn = (crcwn >> 8) ^ t[(byte)(crcwn ^ lo)];
crcwn = (crcwn >> 8) ^ t[(byte)(crcwn ^ s1)]; crcwn = (crcwn >> 8) ^ t[(byte)(crcwn ^ (lo >> 8))];
} }
else crcnulls++; else crcnulls++;
s = *(pSampleBuff++); uint hi = (uint)*(pSampleBuff++);
s0 = (byte)s; crc = (crc >> 8) ^ t[(byte)(crc ^ hi)];
s1 = (byte)(s >> 8); crc = (crc >> 8) ^ t[(byte)(crc ^ (hi >> 8))];
crc = (crc >> 8) ^ t[((byte)crc) ^ s0]; if (hi != 0)
crc = (crc >> 8) ^ t[((byte)crc) ^ s1];
if (s != 0)
{ {
crcwn = (crcwn >> 8) ^ t[(byte)(crcwn ^ s0)]; crcwn = (crcwn >> 8) ^ t[(byte)(crcwn ^ hi)];
crcwn = (crcwn >> 8) ^ t[(byte)(crcwn ^ s1)]; crcwn = (crcwn >> 8) ^ t[(byte)(crcwn ^ (hi >> 8))];
} }
else crcnulls++; else crcnulls++;
uint sampleValue = (lo & 0xffff) + (hi << 16);
crcsm += sampleValue;
crcar += sampleValue * (uint)(currentOffset + i + 1);
} }
} }
_offsetedCRC32[_currentTrack, 10 * 588 - 1] = crc; _offsetedCRCAR[_currentTrack, 20 * 588] = crcar;
_offsetedCRCWN[_currentTrack, 10 * 588 - 1] = crcwn; _offsetedCRCSM[_currentTrack, 20 * 588] = crcsm;
_offsetedCRCNulls[_currentTrack, 10 * 588 - 1] = crcnulls; _offsetedCRC32[_currentTrack, 20 * 588] = crc;
_offsetedCRCWN[_currentTrack, 20 * 588] = crcwn;
_offsetedCRCNulls[_currentTrack, 20 * 588] = crcnulls;
} }
public void Write(AudioBuffer sampleBuffer) public void Write(AudioBuffer sampleBuffer)
@@ -527,30 +456,21 @@ All the other CRC's in this offset range are calculated by consequently adding s
int currentOffset = (int)_sampleCount - (int)(_currentTrack > 0 ? _toc[_currentTrack + _toc.FirstAudio - 1].Start * 588 : 0); int currentOffset = (int)_sampleCount - (int)(_currentTrack > 0 ? _toc[_currentTrack + _toc.FirstAudio - 1].Start * 588 : 0);
int currentSector = currentOffset / 588; int currentSector = currentOffset / 588;
int remaingSectors = (int)(_samplesRemTrack - 1) / 588; int remaingSectors = (int)(_samplesRemTrack - 1) / 588;
unsafe unsafe
{ {
fixed (int* pSampleBuff = &sampleBuffer.Samples[pos, 0]) fixed (int* pSampleBuff = &sampleBuffer.Samples[pos, 0])
//fixed (byte* pByteBuff = &sampleBuffer.Bytes[pos * sampleBuffer.BlockAlign]) //fixed (byte* pByteBuff = &sampleBuffer.Bytes[pos * sampleBuffer.BlockAlign])
{ {
if (currentSector < 5) if (currentSector < 5 || (_currentTrack == 1 && currentSector < 10))
CalculateCRCs(pSampleBuff, copyCount, currentOffset, currentOffset);
else if (remaingSectors < 5 || (_currentTrack == _toc.AudioTracks && remaingSectors < 10))
CalculateCRCs(pSampleBuff, copyCount, currentOffset, 20 * 588 - (int)_samplesRemTrack);
else
CalculateCRCs(pSampleBuff, copyCount, currentOffset); CalculateCRCs(pSampleBuff, copyCount, currentOffset);
else if (remaingSectors < 5)
CalculateCRCs(pSampleBuff, copyCount, 10 * 588 - (int)_samplesRemTrack);
else if (_currentTrack == 0 || (_currentTrack == 1 && currentSector < 10) || (_currentTrack == _toc.AudioTracks && remaingSectors < 10))
CalculateCRCs(pSampleBuff, copyCount);
if (_currentTrack > 0) if (currentSector >= 440 && currentSector <= 460)
{ CalculateFrame450CRCs(pSampleBuff, copyCount, _currentTrack - 1, currentOffset);
int trackLength = (int)_toc[_currentTrack + _toc.FirstAudio - 1].Length * 588;
int previousOffset = _currentTrack > 1 ? (int)_toc[_currentTrack + _toc.FirstAudio - 2].Length * 588 : (int)_toc[_toc.FirstAudio].Pregap * 588;
if ((_currentTrack == 1 && currentSector < 10) || (_currentTrack == _toc.AudioTracks && remaingSectors < 10))
CalculateAccurateRipCRCs(pSampleBuff, copyCount, _currentTrack - 1, currentOffset, previousOffset, trackLength);
else if (currentSector < 5 || remaingSectors < 5)
CalculateAccurateRipCRCsSemifast(pSampleBuff, copyCount, _currentTrack - 1, currentOffset, previousOffset, trackLength);
else
CalculateAccurateRipCRCsFast(pSampleBuff, copyCount, _currentTrack - 1, currentOffset);
}
} }
} }
pos += copyCount; pos += copyCount;
@@ -562,13 +482,14 @@ All the other CRC's in this offset range are calculated by consequently adding s
public void Init() public void Init()
{ {
_offsetedCRC = new uint[_toc.AudioTracks, 10 * 588]; _offsetedCRCAR = new uint[_toc.AudioTracks + 1, 20 * 588 + 1];
_offsetedCRC32 = new uint[_toc.AudioTracks + 1, 10 * 588]; _offsetedCRCSM = new uint[_toc.AudioTracks + 1, 20 * 588 + 1];
_offsetedCRC32Res = new uint[_toc.AudioTracks + 1, 10 * 588]; _offsetedCRC32 = new uint[_toc.AudioTracks + 1, 20 * 588 + 1];
_offsetedCRCWN = new uint[_toc.AudioTracks + 1, 10 * 588]; _offsetedCRC32Res = new uint[_toc.AudioTracks + 1, 20 * 588 + 1];
_offsetedCRCWNRes = new uint[_toc.AudioTracks + 1, 10 * 588]; _offsetedCRCWN = new uint[_toc.AudioTracks + 1, 20 * 588 + 1];
_offsetedCRCNulls = new int[_toc.AudioTracks + 1, 10 * 588]; _offsetedCRCWNRes = new uint[_toc.AudioTracks + 1, 20 * 588 + 1];
_offsetedFrame450CRC = new uint[_toc.AudioTracks, 10 * 588]; _offsetedCRCNulls = new int[_toc.AudioTracks + 1, 20 * 588 + 1];
_offsetedFrame450CRC = new uint[_toc.AudioTracks, 20 * 588];
_currentTrack = 0; _currentTrack = 0;
_sampleCount = _toc[_toc.FirstAudio][0].Start * 588; _sampleCount = _toc[_toc.FirstAudio][0].Start * 588;
_samplesRemTrack = _toc[_toc.FirstAudio].Pregap * 588; _samplesRemTrack = _toc[_toc.FirstAudio].Pregap * 588;
@@ -812,7 +733,7 @@ All the other CRC's in this offset range are calculated by consequently adding s
{ {
if ((CRC(iTrack, oi) == AccDisks[di].tracks[iTrack].CRC && AccDisks[di].tracks[iTrack].CRC != 0)) if ((CRC(iTrack, oi) == AccDisks[di].tracks[iTrack].CRC && AccDisks[di].tracks[iTrack].CRC != 0))
{ {
matches ++; matches++;
break; break;
} }
if ((CRC450(iTrack, oi) == AccDisks[di].tracks[iTrack].Frame450CRC && AccDisks[di].tracks[iTrack].Frame450CRC != 0)) if ((CRC450(iTrack, oi) == AccDisks[di].tracks[iTrack].Frame450CRC && AccDisks[di].tracks[iTrack].Frame450CRC != 0))
@@ -958,7 +879,7 @@ All the other CRC's in this offset range are calculated by consequently adding s
} }
Stream respStream = resp.GetResponseStream(); Stream respStream = resp.GetResponseStream();
FileStream myOffsetsSaved = new FileStream(fileName, FileMode.CreateNew, FileAccess.Write); FileStream myOffsetsSaved = new FileStream(fileName, FileMode.CreateNew, FileAccess.Write);
byte [] buff = new byte[0x8000]; byte[] buff = new byte[0x8000];
do do
{ {
int count = respStream.Read(buff, 0, buff.Length); int count = respStream.Read(buff, 0, buff.Length);
@@ -983,7 +904,7 @@ All the other CRC's in this offset range are calculated by consequently adding s
byte[] misc = offsetReader.ReadBytes(0x22); byte[] misc = offsetReader.ReadBytes(0x22);
int len = name.Length; int len = name.Length;
while (len > 0 && name[len - 1] == '\0') len--; while (len > 0 && name[len - 1] == '\0') len--;
string strname = Encoding.ASCII.GetString(name,0,len); string strname = Encoding.ASCII.GetString(name, 0, len);
if (strname == driveName) if (strname == driveName)
{ {
driveReadOffset = readOffset; driveReadOffset = readOffset;
@@ -1064,12 +985,13 @@ All the other CRC's in this offset range are calculated by consequently adding s
int _currentTrack; int _currentTrack;
private List<AccDisk> _accDisks; private List<AccDisk> _accDisks;
private HttpStatusCode _accResult; private HttpStatusCode _accResult;
private uint[,] _offsetedCRCAR;
private uint[,] _offsetedCRCSM;
private uint[,] _offsetedCRC32; private uint[,] _offsetedCRC32;
private uint[,] _offsetedCRCWN; private uint[,] _offsetedCRCWN;
private uint[,] _offsetedCRCWNRes; private uint[,] _offsetedCRCWNRes;
private int[,] _offsetedCRCNulls; private int[,] _offsetedCRCNulls;
private uint[,] _offsetedCRC32Res; private uint[,] _offsetedCRC32Res;
private uint[,] _offsetedCRC;
private uint[,] _offsetedFrame450CRC; private uint[,] _offsetedFrame450CRC;
private uint[] _CRCLOG; private uint[] _CRCLOG;
private uint[] _backupCRC; private uint[] _backupCRC;

View File

@@ -61,18 +61,20 @@ namespace CUETools.TestCodecs
public void MyTestInitialize() public void MyTestInitialize()
{ {
toc = new CDImageLayout(); toc = new CDImageLayout();
toc.AddTrack(new CDTrack(1, 03, 20, true, false)); toc.AddTrack(new CDTrack(1, 13, 55, true, false));
toc.AddTrack(new CDTrack(2, 23, 20, true, false)); toc.AddTrack(new CDTrack(2, 68, 31, true, false));
toc.AddTrack(new CDTrack(3, 43, 20, true, false)); toc.AddTrack(new CDTrack(3, 99, 37, true, false));
toc[1][0].Start = 0;
ar = new AccurateRipVerify(toc); ar = new AccurateRipVerify(toc);
Random rnd = new Random(2314);
for (int sector = 0; sector < toc.AudioLength; sector++) for (int sector = 0; sector < toc.AudioLength; sector++)
{ {
AudioBuffer buff = new AudioBuffer(AudioPCMConfig.RedBook, 588); AudioBuffer buff = new AudioBuffer(AudioPCMConfig.RedBook, 588);
buff.Length = 588; buff.Length = 588;
for (int i = 0; i < buff.Length; i++) for (int i = 0; i < buff.Length; i++)
{ {
buff.Samples[i, 0] = sector * 588 + i; buff.Samples[i, 0] = rnd.Next(-32768, 32767);
buff.Samples[i, 1] = sector * 588; buff.Samples[i, 1] = rnd.Next(-32768, 32767);
} }
ar.Write(buff); ar.Write(buff);
} }
@@ -94,10 +96,10 @@ namespace CUETools.TestCodecs
[TestMethod()] [TestMethod()]
public void CRC32Test() public void CRC32Test()
{ {
Assert.AreEqual<uint>(3233779629, ar.CRC32(0), "CRC32[0] was not set correctly."); Assert.AreEqual<uint>(2884775698, ar.CRC32(0), "CRC32[0] was not set correctly.");
Assert.AreEqual<uint>(0408974480, ar.CRC32(1), "CRC32[1] was not set correctly."); Assert.AreEqual<uint>(0474131972, ar.CRC32(1), "CRC32[1] was not set correctly.");
Assert.AreEqual<uint>(4123211700, ar.CRC32(2), "CRC32[2] was not set correctly."); Assert.AreEqual<uint>(1685633822, ar.CRC32(2), "CRC32[2] was not set correctly.");
Assert.AreEqual<uint>(0564210909, ar.CRC32(3), "CRC32[3] was not set correctly."); Assert.AreEqual<uint>(2747309238, ar.CRC32(3), "CRC32[3] was not set correctly.");
} }
/// <summary> /// <summary>
@@ -106,10 +108,14 @@ namespace CUETools.TestCodecs
[TestMethod()] [TestMethod()]
public void CRC32Test1() public void CRC32Test1()
{ {
Assert.AreEqual<uint>(3753760724, ar.CRC32(0, 13), "CRC32[0][13] was not set correctly."); Assert.AreEqual<uint>(2802501111, ar.CRC32(0, 13), "CRC32[0][13] was not set correctly.");
Assert.AreEqual<uint>(3153592639, ar.CRC32(0, -7), "CRC32[0][-7] was not set correctly."); Assert.AreEqual<uint>(1987827634, ar.CRC32(0, -7), "CRC32[0][-7] was not set correctly.");
Assert.AreEqual<uint>(0297562037, ar.CRC32(2, 15), "CRC32[2][15] was not set correctly."); Assert.AreEqual<uint>(1624004597, ar.CRC32(1, 13), "CRC32[1][13] was not set correctly.");
Assert.AreEqual<uint>(0398293317, ar.CRC32(2, -1), "CRC32[2][-1] was not set correctly."); Assert.AreEqual<uint>(2300462193, ar.CRC32(1, -7), "CRC32[1][-7] was not set correctly.");
Assert.AreEqual<uint>(0685357040, ar.CRC32(2, 15), "CRC32[2][15] was not set correctly.");
Assert.AreEqual<uint>(4050516109, ar.CRC32(2, -1), "CRC32[2][-1] was not set correctly.");
Assert.AreEqual<uint>(1860362251, ar.CRC32(3, 15), "CRC32[3][15] was not set correctly.");
Assert.AreEqual<uint>(0761448415, ar.CRC32(3, -1), "CRC32[3][-1] was not set correctly.");
} }
/// <summary> /// <summary>
@@ -118,7 +124,12 @@ namespace CUETools.TestCodecs
[TestMethod()] [TestMethod()]
public void CRCTest1() public void CRCTest1()
{ {
Assert.AreEqual<uint>(3206462296, ar.CRC(1, 11), "CRC[1][11] was not set correctly."); Assert.AreEqual<uint>(0095215819, ar.CRC(0, -1), "CRC[0][-1] was not set correctly.");
Assert.AreEqual<uint>(4179900079, ar.CRC(0, 99), "CRC[0][99] was not set correctly.");
Assert.AreEqual<uint>(3756565509, ar.CRC(1, -3), "CRC[1][-3] was not set correctly.");
Assert.AreEqual<uint>(1882341590, ar.CRC(1, 11), "CRC[1][11] was not set correctly.");
Assert.AreEqual<uint>(4121006760, ar.CRC(2, -4), "CRC[2][-4] was not set correctly.");
Assert.AreEqual<uint>(3648746406, ar.CRC(2, 55), "CRC[2][55] was not set correctly.");
} }
/// <summary> /// <summary>
@@ -127,9 +138,9 @@ namespace CUETools.TestCodecs
[TestMethod()] [TestMethod()]
public void CRCTest() public void CRCTest()
{ {
Assert.AreEqual<uint>(3762425816, ar.CRC(0), "CRC[0] was not set correctly."); Assert.AreEqual<uint>(1190199900, ar.CRC(0), "CRC[0] was not set correctly.");
Assert.AreEqual<uint>(3103217968, ar.CRC(1), "CRC[1] was not set correctly."); Assert.AreEqual<uint>(1914801336, ar.CRC(1), "CRC[1] was not set correctly.");
Assert.AreEqual<uint>(3068174852, ar.CRC(2), "CRC[2] was not set correctly."); Assert.AreEqual<uint>(1759975763, ar.CRC(2), "CRC[2] was not set correctly.");
} }
/// <summary> /// <summary>
@@ -138,8 +149,8 @@ namespace CUETools.TestCodecs
[TestMethod()] [TestMethod()]
public void CRCWONULLTest1() public void CRCWONULLTest1()
{ {
Assert.AreEqual<uint>(0062860870, ar.CRCWONULL(2, 19), "CRC32WONULL[2][19] was not set correctly."); Assert.AreEqual<uint>(3376349517, ar.CRCWONULL(2, 19), "CRC32WONULL[2][19] was not set correctly.");
Assert.AreEqual<uint>(0950746738, ar.CRCWONULL(2, -2), "CRC32WONULL[2][-2] was not set correctly."); Assert.AreEqual<uint>(0162318931, ar.CRCWONULL(2, -2), "CRC32WONULL[2][-2] was not set correctly.");
} }
/// <summary> /// <summary>
@@ -148,10 +159,10 @@ namespace CUETools.TestCodecs
[TestMethod()] [TestMethod()]
public void CRCWONULLTest() public void CRCWONULLTest()
{ {
Assert.AreEqual<uint>(2395016718, ar.CRCWONULL(0), "CRC32WONULL[0] was not set correctly."); Assert.AreEqual<uint>(0509527097, ar.CRCWONULL(0), "CRC32WONULL[0] was not set correctly.");
Assert.AreEqual<uint>(0834934371, ar.CRCWONULL(1), "CRC32WONULL[1] was not set correctly."); Assert.AreEqual<uint>(0474131972, ar.CRCWONULL(1), "CRC32WONULL[1] was not set correctly.");
Assert.AreEqual<uint>(4123211700, ar.CRCWONULL(2), "CRC32WONULL[2] was not set correctly."); Assert.AreEqual<uint>(1405611463, ar.CRCWONULL(2), "CRC32WONULL[2] was not set correctly.");
Assert.AreEqual<uint>(0564210909, ar.CRCWONULL(3), "CRC32WONULL[3] was not set correctly."); Assert.AreEqual<uint>(2747309238, ar.CRCWONULL(3), "CRC32WONULL[3] was not set correctly.");
} }
} }