mirror of
https://github.com/claunia/cuetools.net.git
synced 2025-12-16 18:14:25 +00:00
CTDB: fast parity/syndrome calculation
CTDB: initial submission without a parity file CTDB: track CRCs submission
This commit is contained in:
@@ -434,18 +434,53 @@ namespace CUETools.AccurateRip
|
||||
_CRCLOG[iTrack] = value;
|
||||
}
|
||||
|
||||
internal ushort[,] syndrome;
|
||||
public unsafe ushort[,] GetSyndrome()
|
||||
{
|
||||
if (!calcParity)
|
||||
throw new InvalidOperationException();
|
||||
var syndrome = new ushort[stride, npar];
|
||||
fixed (byte* pbpar = parity)
|
||||
fixed (ushort* psyn0 = syndrome, plog = Galois16.instance.LogTbl, pexp = Galois16.instance.ExpTbl)
|
||||
{
|
||||
ushort* ppar = (ushort*)pbpar;
|
||||
for (int y = 0; y < stride; y++)
|
||||
{
|
||||
ushort* syn = psyn0 + y * npar;
|
||||
for (int x1 = 0; x1 < npar; x1++)
|
||||
{
|
||||
ushort lo = ppar[y * npar + x1];
|
||||
if (lo != 0)
|
||||
{
|
||||
var llo = plog[lo] + 0xffff;
|
||||
for (int x = 0; x < npar; x++)
|
||||
syn[x] ^= pexp[llo - (1 + x1) * x];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return syndrome;
|
||||
}
|
||||
|
||||
public unsafe ushort[,] Syndrome
|
||||
{
|
||||
get
|
||||
{
|
||||
if (syndrome == null)
|
||||
syndrome = GetSyndrome();
|
||||
return syndrome;
|
||||
}
|
||||
}
|
||||
|
||||
private ushort[,] syndrome;
|
||||
internal byte[] parity;
|
||||
internal ushort[, ,] encodeTable;
|
||||
internal ushort[, ,] decodeTable;
|
||||
private int maxOffset;
|
||||
internal ushort[] leadin;
|
||||
internal ushort[] leadout;
|
||||
private int stride = 1, laststride = 1, stridecount = 1, npar = 1;
|
||||
private bool calcSyn = false;
|
||||
private bool calcParity = false;
|
||||
|
||||
internal void InitCDRepair(int stride, int laststride, int stridecount, int npar, bool calcSyn, bool calcParity)
|
||||
internal void InitCDRepair(int stride, int laststride, int stridecount, int npar, bool calcParity)
|
||||
{
|
||||
if (npar != 8)
|
||||
throw new ArgumentOutOfRangeException("npar");
|
||||
@@ -455,7 +490,6 @@ namespace CUETools.AccurateRip
|
||||
this.laststride = laststride;
|
||||
this.stridecount = stridecount;
|
||||
this.npar = npar;
|
||||
this.calcSyn = calcSyn;
|
||||
this.calcParity = calcParity;
|
||||
Init(_toc);
|
||||
}
|
||||
@@ -512,25 +546,14 @@ namespace CUETools.AccurateRip
|
||||
return CTDBCRC(0, offset, stride / 2, laststride / 2);
|
||||
}
|
||||
|
||||
private unsafe static void CalcSyn8(ushort* pt, ushort* syn, uint lo, uint hi)
|
||||
{
|
||||
syn[0] ^= (ushort)lo;
|
||||
syn[1] = (ushort)(lo ^ pt[(syn[1] & 255) * 16 + 1] ^ pt[(syn[1] >> 8) * 16 + 1 + 8]);
|
||||
syn[2] = (ushort)(lo ^ pt[(syn[2] & 255) * 16 + 2] ^ pt[(syn[2] >> 8) * 16 + 2 + 8]);
|
||||
syn[3] = (ushort)(lo ^ pt[(syn[3] & 255) * 16 + 3] ^ pt[(syn[3] >> 8) * 16 + 3 + 8]);
|
||||
syn[4] = (ushort)(lo ^ pt[(syn[4] & 255) * 16 + 4] ^ pt[(syn[4] >> 8) * 16 + 4 + 8]);
|
||||
syn[5] = (ushort)(lo ^ pt[(syn[5] & 255) * 16 + 5] ^ pt[(syn[5] >> 8) * 16 + 5 + 8]);
|
||||
syn[6] = (ushort)(lo ^ pt[(syn[6] & 255) * 16 + 6] ^ pt[(syn[6] >> 8) * 16 + 6 + 8]);
|
||||
syn[7] = (ushort)(lo ^ pt[(syn[7] & 255) * 16 + 7] ^ pt[(syn[7] >> 8) * 16 + 7 + 8]);
|
||||
syn[8] ^= (ushort)hi;
|
||||
syn[9] = (ushort)(hi ^ pt[(syn[9] & 255) * 16 + 1] ^ pt[(syn[9] >> 8) * 16 + 1 + 8]);
|
||||
syn[10] = (ushort)(hi ^ pt[(syn[10] & 255) * 16 + 2] ^ pt[(syn[10] >> 8) * 16 + 2 + 8]);
|
||||
syn[11] = (ushort)(hi ^ pt[(syn[11] & 255) * 16 + 3] ^ pt[(syn[11] >> 8) * 16 + 3 + 8]);
|
||||
syn[12] = (ushort)(hi ^ pt[(syn[12] & 255) * 16 + 4] ^ pt[(syn[12] >> 8) * 16 + 4 + 8]);
|
||||
syn[13] = (ushort)(hi ^ pt[(syn[13] & 255) * 16 + 5] ^ pt[(syn[13] >> 8) * 16 + 5 + 8]);
|
||||
syn[14] = (ushort)(hi ^ pt[(syn[14] & 255) * 16 + 6] ^ pt[(syn[14] >> 8) * 16 + 6 + 8]);
|
||||
syn[15] = (ushort)(hi ^ pt[(syn[15] & 255) * 16 + 7] ^ pt[(syn[15] >> 8) * 16 + 7 + 8]);
|
||||
}
|
||||
//private unsafe static void CalcPar8(ushort* pt, ushort* wr, uint lo)
|
||||
//{
|
||||
// uint wrlo = wr[0] ^ lo;
|
||||
// ushort* ptiblo0 = pt + (wrlo & 255) * 16;
|
||||
// ushort* ptiblo1 = pt + (wrlo >> 8) * 16 + 8;
|
||||
// ((ulong*)wr)[0] = ((ulong*)(wr + 1))[0] ^ ((ulong*)ptiblo0)[0] ^ ((ulong*)ptiblo1)[0];
|
||||
// ((ulong*)wr)[1] = (((ulong*)(wr))[1] >> 16) ^ ((ulong*)ptiblo0)[1] ^ ((ulong*)ptiblo1)[1];
|
||||
//}
|
||||
|
||||
private unsafe static void CalcPar8(ushort* pt, ushort* wr, uint lo, uint hi)
|
||||
{
|
||||
@@ -548,15 +571,22 @@ namespace CUETools.AccurateRip
|
||||
((ulong*)wr)[3] = (((ulong*)(wr))[3] >> 16) ^ ((ulong*)ptibhi0)[1] ^ ((ulong*)ptibhi1)[1];
|
||||
#else
|
||||
const int npar = 8;
|
||||
ushort* ptiblo = pt + (wr[0] ^ lo) * npar;
|
||||
ushort* ptibhi = pt + (wr[npar] ^ hi) * npar;
|
||||
|
||||
uint s = wr[0] ^ lo;
|
||||
ushort* ptib0 = pt + (s & 255) * 16;
|
||||
ushort* ptib1 = pt + (s >> 8) * 16 + 8;
|
||||
for (int i = 0; i < npar - 1; i++)
|
||||
{
|
||||
wr[i] = (ushort)(wr[i + 1] ^ ptiblo[i]);
|
||||
wr[npar + i] = (ushort)(wr[i + 1 + npar] ^ ptibhi[i]);
|
||||
}
|
||||
wr[npar - 1] = ptiblo[npar - 1];
|
||||
wr[2 * npar - 1] = ptibhi[npar - 1];
|
||||
wr[i] = (ushort)(wr[i + 1] ^ ptib0[i] ^ ptib1[i]);
|
||||
wr[npar - 1] = (ushort)(ptib0[npar - 1] ^ ptib1[npar - 1]);
|
||||
|
||||
wr += 8;
|
||||
|
||||
s = wr[0] ^ hi;
|
||||
ptib0 = pt + (s & 255) * 16;
|
||||
ptib1 = pt + (s >> 8) * 16 + 8;
|
||||
for (int i = 0; i < npar - 1; i++)
|
||||
wr[i] = (ushort)(wr[i + 1] ^ ptib0[i] ^ ptib1[i]);
|
||||
wr[npar - 1] = (ushort)(ptib0[npar - 1] ^ ptib1[npar - 1]);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -575,12 +605,10 @@ namespace CUETools.AccurateRip
|
||||
/// <param name="pSampleBuff"></param>
|
||||
/// <param name="count"></param>
|
||||
/// <param name="offs"></param>
|
||||
public unsafe void CalculateCRCs(uint* t, ushort* syn, ushort* wr, ushort* pte, ushort* ptd, uint* pSampleBuff, int count, int offs)
|
||||
public unsafe void CalculateCRCs(uint* t, ushort* wr, ushort* pte, uint* pSampleBuff, int count, int offs)
|
||||
{
|
||||
int currentStride = ((int)_sampleCount * 2) / stride;
|
||||
bool doSyn = currentStride >= 1 && currentStride <= stridecount && calcSyn;
|
||||
bool doPar = currentStride >= 1 && currentStride <= stridecount && calcParity;
|
||||
uint n = (uint)(stridecount - currentStride);
|
||||
|
||||
int crcTrack = _currentTrack + (_samplesDoneTrack == 0 && _currentTrack > 0 ? -1 : 0);
|
||||
uint crcar = _CRCAR[_currentTrack, 0];
|
||||
@@ -620,9 +648,9 @@ namespace CUETools.AccurateRip
|
||||
}
|
||||
|
||||
uint hi = sample >> 16;
|
||||
|
||||
if (doSyn) CalcSyn8(ptd, syn + i * 16, lo, hi);
|
||||
if (doPar) CalcPar8(pte, wr + i * 16, lo, hi);
|
||||
//if (doPar) CalcPar8(pte, wr + i * 16, lo);
|
||||
//uint hi = sample >> 16;
|
||||
|
||||
crc32 = (crc32 >> 8) ^ t[(byte)(crc32 ^ hi)];
|
||||
crc32 = (crc32 >> 8) ^ t[(byte)(crc32 ^ (hi >> 8))];
|
||||
@@ -632,6 +660,7 @@ namespace CUETools.AccurateRip
|
||||
crcwn = (crcwn >> 8) ^ t[(byte)(crcwn ^ (hi >> 8))];
|
||||
crcnl++;
|
||||
}
|
||||
//if (doPar) CalcPar8(pte, wr + i * 16 + 8, hi);
|
||||
|
||||
int pk = ((int)(lo << 16)) >> 16;
|
||||
peak = Math.Max(peak, (pk << 1) ^ (pk >> 31));
|
||||
@@ -683,7 +712,7 @@ namespace CUETools.AccurateRip
|
||||
|
||||
int pos = 0;
|
||||
fixed (uint* t = Crc32.table)
|
||||
fixed (ushort* synptr1 = syndrome, pte = encodeTable, ptd = decodeTable)
|
||||
fixed (ushort* pte = encodeTable)
|
||||
fixed (byte* pSampleBuff = &sampleBuffer.Bytes[0], bpar = parity)
|
||||
while (pos < sampleBuffer.Length)
|
||||
{
|
||||
@@ -691,7 +720,7 @@ namespace CUETools.AccurateRip
|
||||
int copyCount = Math.Min(Math.Min(sampleBuffer.Length - pos, (int)_samplesRemTrack), 588 - (int)_sampleCount % 588);
|
||||
uint* samples = ((uint*)pSampleBuff) + pos;
|
||||
int currentPart = ((int)_sampleCount * 2) % stride;
|
||||
ushort* synptr = synptr1 + npar * currentPart;
|
||||
//ushort* synptr = synptr1 + npar * currentPart;
|
||||
ushort* wr = ((ushort*)bpar) + npar * currentPart;
|
||||
int currentStride = ((int)_sampleCount * 2) / stride;
|
||||
|
||||
@@ -711,7 +740,7 @@ namespace CUETools.AccurateRip
|
||||
: _samplesDoneTrack >= 445 * 588 && _samplesDoneTrack <= 455 * 588 ? 2 * maxOffset + 1 + _samplesDoneTrack - 445 * 588
|
||||
: -1;
|
||||
|
||||
CalculateCRCs(t, synptr, wr, pte, ptd, samples, copyCount, offset);
|
||||
CalculateCRCs(t, wr, pte, samples, copyCount, offset);
|
||||
|
||||
// duplicate prefix to suffix
|
||||
if (_samplesDoneTrack < maxOffset && _samplesRemTrack <= maxOffset)
|
||||
@@ -755,7 +784,7 @@ namespace CUETools.AccurateRip
|
||||
}
|
||||
}
|
||||
|
||||
public void Combine(AccurateRipVerify part, int start, int end)
|
||||
public unsafe void Combine(AccurateRipVerify part, int start, int end)
|
||||
{
|
||||
for (int i = 0; i < leadin.Length; i++)
|
||||
{
|
||||
@@ -827,6 +856,33 @@ namespace CUETools.AccurateRip
|
||||
}
|
||||
_Peak[iTrack] = Math.Max(_Peak[iTrack], part._Peak[iTrack]);
|
||||
}
|
||||
|
||||
if (calcParity)
|
||||
{
|
||||
var newSyndrome1 = this.GetSyndrome();
|
||||
var newSyndrome2 = part.GetSyndrome();
|
||||
var i1 = Math.Max(0, start * 2 - stride);
|
||||
var i2 = Math.Min(2 * (int)_finalSampleCount - laststride - stride, end * 2 - stride);
|
||||
var diff = i2 / stride - i1 / stride;
|
||||
var i1s = i1 % stride;
|
||||
var i2s = i2 % stride;
|
||||
var imin = Math.Min(i1s, i2s);
|
||||
var imax = Math.Max(i1s, i2s);
|
||||
var diff1 = diff + (imin < i2s ? 1 : 0) - (imin < i1s ? 1 : 0);
|
||||
for (int i = 0; i < stride; i++)
|
||||
for (int j = 0; j < npar; j++)
|
||||
{
|
||||
var d1 = j * (i >= imin && i < imax ? diff1 : diff);
|
||||
newSyndrome1[i, j] = (ushort)(newSyndrome2[i, j] ^ Galois16.instance.mulExp(newSyndrome1[i, j], (d1 & 0xffff) + (d1 >> 16)));
|
||||
}
|
||||
fixed (byte* p = this.parity)
|
||||
fixed (ushort* syn = newSyndrome1)
|
||||
{
|
||||
ushort* p1 = (ushort*)p;
|
||||
for (int i = 0; i < stride; i++)
|
||||
Galois16.instance.Syndrome2Parity(syn + i * npar, p1 + i * npar, npar);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Init(CDImageLayout toc)
|
||||
@@ -838,7 +894,7 @@ namespace CUETools.AccurateRip
|
||||
for (int iTrack = 1; iTrack <= _toc.AudioTracks; iTrack++)
|
||||
_CRCMASK[iTrack] = 0xffffffff ^ Crc32.Combine(0xffffffff, 0, (int)_toc[iTrack + _toc.FirstAudio - 1].Length * 588 * 4);
|
||||
|
||||
maxOffset = Math.Max(4096 * 2, (calcSyn || calcParity) ? stride + laststride : 0);
|
||||
maxOffset = Math.Max(4096 * 2, calcParity ? stride + laststride : 0);
|
||||
if (maxOffset % 588 != 0)
|
||||
maxOffset += 588 - maxOffset % 588;
|
||||
_CRCAR = new uint[_toc.AudioTracks + 1, 3 * maxOffset];
|
||||
@@ -851,15 +907,13 @@ namespace CUETools.AccurateRip
|
||||
_CRCV2 = new uint[_toc.AudioTracks + 1, 3 * maxOffset];
|
||||
|
||||
_Peak = new int[_toc.AudioTracks + 1];
|
||||
syndrome = new ushort[calcSyn ? stride : 1, npar];
|
||||
parity = new byte[stride * npar * 2];
|
||||
syndrome = null;
|
||||
parity = calcParity ? new byte[stride * npar * 2] : null;
|
||||
if (calcParity && npar == 8)
|
||||
encodeTable = Galois16.instance.makeEncodeTable(npar);
|
||||
if (calcSyn && npar == 8)
|
||||
decodeTable = Galois16.instance.makeDecodeTable(npar);
|
||||
|
||||
int leadin_len = Math.Max(4096 * 4, (calcSyn || calcParity) ? stride * 2 : 0);
|
||||
int leadout_len = Math.Max(4096 * 4, (calcSyn || calcParity) ? stride + laststride : 0);
|
||||
int leadin_len = Math.Max(4096 * 4, calcParity ? stride * 2 : 0);
|
||||
int leadout_len = Math.Max(4096 * 4, calcParity ? stride + laststride : 0);
|
||||
leadin = new ushort[leadin_len];
|
||||
leadout = new ushort[leadout_len];
|
||||
_currentTrack = 0;
|
||||
@@ -1025,6 +1079,11 @@ namespace CUETools.AccurateRip
|
||||
get { return AudioPCMConfig.RedBook; }
|
||||
}
|
||||
|
||||
public CDImageLayout TOC
|
||||
{
|
||||
get { return _toc; }
|
||||
}
|
||||
|
||||
public long FinalSampleCount
|
||||
{
|
||||
get
|
||||
|
||||
@@ -57,6 +57,10 @@ namespace CUETools.AccurateRip
|
||||
|
||||
public long FinalSampleCount
|
||||
{
|
||||
get
|
||||
{
|
||||
return finalSampleCount;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value < 0) // != _toc.Length?
|
||||
@@ -72,22 +76,25 @@ namespace CUETools.AccurateRip
|
||||
return npar;
|
||||
}
|
||||
}
|
||||
|
||||
public int Stride
|
||||
{
|
||||
get
|
||||
{
|
||||
return stride;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class CDRepairEncode : CDRepair
|
||||
{
|
||||
internal bool verify;
|
||||
internal bool encode;
|
||||
protected AccurateRipVerify ar;
|
||||
|
||||
public CDRepairEncode(AccurateRipVerify ar, int stride, int npar, bool verify, bool encode)
|
||||
public CDRepairEncode(AccurateRipVerify ar, int stride, int npar)
|
||||
: base ((int)ar.FinalSampleCount, stride, npar)
|
||||
{
|
||||
this.ar = ar;
|
||||
this.verify = verify;
|
||||
this.encode = encode;
|
||||
|
||||
ar.InitCDRepair(stride, laststride, stridecount, npar, verify, encode);
|
||||
ar.InitCDRepair(stride, laststride, stridecount, npar, true);
|
||||
}
|
||||
|
||||
//private unsafe void ProcessStride(int currentStride, int currentPart, int count, ushort* data)
|
||||
@@ -265,6 +272,14 @@ namespace CUETools.AccurateRip
|
||||
return VerifyParity(npar, parity2, 0, parity2.Length, actualOffset);
|
||||
}
|
||||
|
||||
public AccurateRipVerify AR
|
||||
{
|
||||
get
|
||||
{
|
||||
return ar;
|
||||
}
|
||||
}
|
||||
|
||||
public uint CRC
|
||||
{
|
||||
get
|
||||
@@ -273,12 +288,21 @@ namespace CUETools.AccurateRip
|
||||
}
|
||||
}
|
||||
|
||||
public string TrackCRCs
|
||||
{
|
||||
get
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
for (int i = 1; i <= ar.TOC.AudioTracks; i++)
|
||||
sb.AppendFormat(" {0:x8}", ar.CTDBCRC(i, 0, stride / 2, laststride / 2));
|
||||
return sb.ToString().Substring(1);
|
||||
}
|
||||
}
|
||||
|
||||
public unsafe bool FindOffset(int npar2, byte[] parity2, int pos, uint expectedCRC, out int actualOffset, out bool hasErrors)
|
||||
{
|
||||
if (npar2 != npar)
|
||||
throw new Exception("npar mismatch");
|
||||
if (!verify)
|
||||
throw new Exception("verify was not enabled");
|
||||
if (ar.Position != ar.FinalSampleCount)
|
||||
throw new Exception("ar.Position != ar.FinalSampleCount");
|
||||
|
||||
@@ -290,6 +314,7 @@ namespace CUETools.AccurateRip
|
||||
int* _errpos = stackalloc int[npar];
|
||||
int* syn = stackalloc int[npar];
|
||||
bool foundOffset = false;
|
||||
var arSyndrome = ar.Syndrome;
|
||||
|
||||
for (int allowed_errors = 0; allowed_errors < npar / 2 && !foundOffset; allowed_errors++)
|
||||
{
|
||||
@@ -307,7 +332,7 @@ namespace CUETools.AccurateRip
|
||||
|
||||
for (int i = 0; i < npar; i++)
|
||||
{
|
||||
int synI = ar.syndrome[part, i];
|
||||
int synI = arSyndrome[part, i];
|
||||
|
||||
// offset < 0
|
||||
if (part < -offset * 2)
|
||||
@@ -365,6 +390,7 @@ namespace CUETools.AccurateRip
|
||||
{
|
||||
int* syn = stackalloc int[npar];
|
||||
int offset = fix.actualOffset;
|
||||
var arSyndrome = ar.Syndrome;
|
||||
|
||||
for (int part = 0; part < stride; part++)
|
||||
{
|
||||
@@ -374,7 +400,7 @@ namespace CUETools.AccurateRip
|
||||
|
||||
for (int i = 0; i < npar; i++)
|
||||
{
|
||||
syn[i] = ar.syndrome[part, i];
|
||||
syn[i] = arSyndrome[part, i];
|
||||
|
||||
// offset < 0
|
||||
if (part < -offset * 2)
|
||||
@@ -442,7 +468,7 @@ namespace CUETools.AccurateRip
|
||||
{
|
||||
get
|
||||
{
|
||||
return ar.syndrome;
|
||||
return ar.Syndrome;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user