mirror of
https://github.com/claunia/cuetools.net.git
synced 2025-12-16 18:14:25 +00:00
CTDB 2.0
This commit is contained in:
@@ -13,7 +13,7 @@ namespace CUETools.AccurateRip
|
||||
{
|
||||
public class AccurateRipVerify : IAudioDest
|
||||
{
|
||||
public const int maxNpar = 8;
|
||||
public const int maxNpar = 16;
|
||||
|
||||
public AccurateRipVerify(CDImageLayout toc, IWebProxy proxy)
|
||||
{
|
||||
@@ -314,21 +314,68 @@ namespace CUETools.AccurateRip
|
||||
_CRCLOG[iTrack] = value;
|
||||
}
|
||||
|
||||
public unsafe byte[] GetParity(int npar = maxNpar)
|
||||
public unsafe ushort[,] GetSyndrome(int npar = maxNpar, int strides = -1, int offset = 0)
|
||||
{
|
||||
if (npar == maxNpar)
|
||||
return this.parity;
|
||||
|
||||
var synShort = this.GetSyndrome(npar);
|
||||
return ParityToSyndrome.Syndrome2Parity(synShort);
|
||||
}
|
||||
|
||||
public unsafe ushort[,] GetSyndrome(int npar = maxNpar)
|
||||
{
|
||||
// We can only use offset if Abs(offset * 2) < stride,
|
||||
// else we might need to add/remove more than one sample
|
||||
// from syndrome calculations, and that would be too difficult
|
||||
// and will probably require longer leadin/leadout.
|
||||
if (!calcParity)
|
||||
throw new InvalidOperationException();
|
||||
return ParityToSyndrome.Parity2Syndrome(stride, npar, maxNpar, parity);
|
||||
}
|
||||
if (strides == -1)
|
||||
strides = stride;
|
||||
var syn = ParityToSyndrome.Parity2Syndrome(strides, stride, npar, maxNpar, parity, 0, -offset * 2);
|
||||
var galois = Galois16.instance;
|
||||
for (int part2 = 0; part2 < strides; part2++)
|
||||
{
|
||||
int part = (part2 + offset * 2 + stride) % stride;
|
||||
if (part < offset * 2)
|
||||
{
|
||||
for (int i = 0; i < npar; i++)
|
||||
{
|
||||
int synI = syn[part2, i];
|
||||
synI = galois.mulExp(synI, i);
|
||||
synI ^= leadout[laststride - part - 1] ^ galois.mulExp(leadin[stride + part], (i * stridecount) % galois.Max);
|
||||
syn[part2, i] = (ushort)synI;
|
||||
}
|
||||
}
|
||||
if (part >= stride + offset * 2)
|
||||
{
|
||||
for (int i = 0; i < npar; i++)
|
||||
{
|
||||
int synI = syn[part2, i];
|
||||
synI ^= leadout[laststride + stride - part - 1] ^ galois.mulExp(leadin[part], (i * stridecount) % galois.Max);
|
||||
synI = galois.divExp(synI, i);
|
||||
syn[part2, i] = (ushort)synI;
|
||||
}
|
||||
}
|
||||
}
|
||||
//for (int part = 0; part < offset * 2; part++)
|
||||
//{
|
||||
// int part2 = (part - offset * 2 + stride) % stride;
|
||||
// if (part2 < strides)
|
||||
// for (int i = 0; i < npar; i++)
|
||||
// {
|
||||
// int synI = syn[part2, i];
|
||||
// synI = galois.mulExp(synI, i);
|
||||
// synI ^= leadout[laststride - part - 1] ^ galois.mulExp(leadin[stride + part], (i * stridecount) % galois.Max);
|
||||
// syn[part2, i] = (ushort)synI;
|
||||
// }
|
||||
//}
|
||||
//for (int part = stride + offset * 2; part < stride; part++)
|
||||
//{
|
||||
// int part2 = (part - offset * 2 + stride) % stride;
|
||||
// if (part2 < strides)
|
||||
// for (int i = 0; i < npar; i++)
|
||||
// {
|
||||
// int synI = syn[part2, i];
|
||||
// synI ^= leadout[laststride + stride - part - 1] ^ galois.mulExp(leadin[part], (i * stridecount) % galois.Max);
|
||||
// synI = galois.divExp(synI, i);
|
||||
// syn[part2, i] = (ushort)synI;
|
||||
// }
|
||||
//}
|
||||
return syn;
|
||||
}
|
||||
|
||||
private byte[] parity;
|
||||
internal ushort[, ,] encodeTable;
|
||||
@@ -401,69 +448,37 @@ namespace CUETools.AccurateRip
|
||||
return CTDBCRC(0, offset, stride / 2, laststride / 2);
|
||||
}
|
||||
|
||||
//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];
|
||||
//}
|
||||
// pt = &encodeTable
|
||||
private unsafe delegate void SyndromeCalc(ushort* pt, ushort* wr, ushort lo);
|
||||
|
||||
private unsafe static void CalcPar(ushort* pt, ushort* wr, uint lo, uint hi)
|
||||
{
|
||||
// pt = &encodeTable
|
||||
#if !sdfs
|
||||
uint wrlo = wr[0] ^ lo;
|
||||
uint wrhi = wr[maxNpar] ^ hi;
|
||||
ushort* ptiblo0 = pt + (wrlo & 255) * maxNpar * 2;
|
||||
private unsafe static void SyndromeCalcDummy(ushort* pt, ushort* wr, ushort lo)
|
||||
{
|
||||
}
|
||||
|
||||
private unsafe static void SyndromeCalc8(ushort* pt, ushort* wr, ushort lo)
|
||||
{
|
||||
ushort wrlo = (ushort)(wr[0] ^ lo);
|
||||
ushort* ptiblo0 = pt + (wrlo & 255) * maxNpar * 2;
|
||||
ushort* ptiblo1 = pt + (wrlo >> 8) * maxNpar * 2 + maxNpar;
|
||||
ushort* ptibhi0 = pt + (wrhi & 255) * maxNpar * 2;
|
||||
ushort* ptibhi1 = pt + (wrhi >> 8) * maxNpar * 2 + maxNpar;
|
||||
wr[maxNpar] = 0;
|
||||
if (maxNpar == 16)
|
||||
{
|
||||
((ulong*)wr)[0] = ((ulong*)(wr + 1))[0] ^ ((ulong*)ptiblo0)[0] ^ ((ulong*)ptiblo1)[0];
|
||||
((ulong*)wr)[1] = ((ulong*)(wr + 1))[1] ^ ((ulong*)ptiblo0)[1] ^ ((ulong*)ptiblo1)[1];
|
||||
((ulong*)wr)[2] = ((ulong*)(wr + 1))[2] ^ ((ulong*)ptiblo0)[2] ^ ((ulong*)ptiblo1)[2];
|
||||
((ulong*)wr)[3] = ((ulong*)(wr + 1))[3] ^ ((ulong*)ptiblo0)[3] ^ ((ulong*)ptiblo1)[3];
|
||||
((ulong*)wr)[4] = ((ulong*)(wr + 1))[4] ^ ((ulong*)ptibhi0)[0] ^ ((ulong*)ptibhi1)[0];
|
||||
((ulong*)wr)[5] = ((ulong*)(wr + 1))[5] ^ ((ulong*)ptibhi0)[1] ^ ((ulong*)ptibhi1)[1];
|
||||
((ulong*)wr)[6] = ((ulong*)(wr + 1))[6] ^ ((ulong*)ptibhi0)[2] ^ ((ulong*)ptibhi1)[2];
|
||||
((ulong*)wr)[7] = (((ulong*)(wr))[7] >> 16) ^ ((ulong*)ptibhi0)[3] ^ ((ulong*)ptibhi1)[3];
|
||||
}
|
||||
else if (maxNpar == 8)
|
||||
{
|
||||
((ulong*)wr)[0] = ((ulong*)(wr + 1))[0] ^ ((ulong*)ptiblo0)[0] ^ ((ulong*)ptiblo1)[0];
|
||||
((ulong*)wr)[1] = ((ulong*)(wr + 1))[1] ^ ((ulong*)ptiblo0)[1] ^ ((ulong*)ptiblo1)[1];
|
||||
((ulong*)wr)[2] = ((ulong*)(wr + 1))[2] ^ ((ulong*)ptibhi0)[0] ^ ((ulong*)ptibhi1)[0];
|
||||
((ulong*)wr)[3] = (((ulong*)(wr))[3] >> 16) ^ ((ulong*)ptibhi0)[1] ^ ((ulong*)ptibhi1)[1];
|
||||
}
|
||||
else
|
||||
throw new InvalidOperationException();
|
||||
#else
|
||||
const int npar = 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];
|
||||
}
|
||||
|
||||
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] ^ ptib0[i] ^ ptib1[i]);
|
||||
wr[npar - 1] = (ushort)(ptib0[npar - 1] ^ ptib1[npar - 1]);
|
||||
//[System.Runtime.InteropServices.DllImport("CUETools.AVX.dll", CallingConvention = System.Runtime.InteropServices.CallingConvention.StdCall)]
|
||||
//private unsafe static extern void SyndromeCalc16AVX(ushort* table, ushort* parity, ushort* samples, int n);
|
||||
|
||||
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
|
||||
}
|
||||
private unsafe static void SyndromeCalc16(ushort* pt, ushort* wr, ushort lo)
|
||||
{
|
||||
ushort wrlo = (ushort)(wr[0] ^ lo);
|
||||
ushort* ptiblo0 = pt + (wrlo & 255) * maxNpar * 2;
|
||||
ushort* ptiblo1 = pt + (wrlo >> 8) * maxNpar * 2 + maxNpar;
|
||||
((ulong*)wr)[0] = ((ulong*)(wr + 1))[0] ^ ((ulong*)ptiblo0)[0] ^ ((ulong*)ptiblo1)[0];
|
||||
((ulong*)wr)[1] = ((ulong*)(wr + 1))[1] ^ ((ulong*)ptiblo0)[1] ^ ((ulong*)ptiblo1)[1];
|
||||
((ulong*)wr)[2] = ((ulong*)(wr + 1))[2] ^ ((ulong*)ptiblo0)[2] ^ ((ulong*)ptiblo1)[2];
|
||||
((ulong*)wr)[3] = (((ulong*)(wr))[3] >> 16) ^ ((ulong*)ptiblo0)[3] ^ ((ulong*)ptiblo1)[3];
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// <summary>
|
||||
/// This function calculates three different CRCs and also
|
||||
/// collects some additional information for the purposes of
|
||||
/// offset detection.
|
||||
@@ -481,6 +496,7 @@ namespace CUETools.AccurateRip
|
||||
{
|
||||
int currentStride = ((int)_sampleCount * 2) / stride;
|
||||
bool doPar = currentStride >= 1 && currentStride <= stridecount && calcParity;
|
||||
SyndromeCalc syndromeCalc = doPar ? maxNpar == 8 ? (SyndromeCalc)SyndromeCalc8 : (SyndromeCalc)SyndromeCalc16 : (SyndromeCalc)SyndromeCalcDummy;
|
||||
|
||||
int crcTrack = _currentTrack + (_samplesDoneTrack == 0 && _currentTrack > 0 ? -1 : 0);
|
||||
uint crcar = _CRCAR[_currentTrack, 0];
|
||||
@@ -491,6 +507,8 @@ namespace CUETools.AccurateRip
|
||||
uint crcv2 = _CRCV2[_currentTrack, 0];
|
||||
int peak = _Peak[_currentTrack];
|
||||
|
||||
//if (doPar) SyndromeCalc16AVX(pte, wr, (ushort*)pSampleBuff, count * 2);
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
if (offs >= 0)
|
||||
@@ -518,12 +536,9 @@ namespace CUETools.AccurateRip
|
||||
crcwn = (crcwn >> 8) ^ t[(byte)(crcwn ^ (lo >> 8))];
|
||||
crcnl++;
|
||||
}
|
||||
syndromeCalc(pte, wr + i * maxNpar * 2, (ushort)lo);
|
||||
|
||||
uint hi = sample >> 16;
|
||||
if (doPar) CalcPar(pte, wr + i * maxNpar * 2, 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))];
|
||||
if (hi != 0)
|
||||
@@ -532,7 +547,7 @@ namespace CUETools.AccurateRip
|
||||
crcwn = (crcwn >> 8) ^ t[(byte)(crcwn ^ (hi >> 8))];
|
||||
crcnl++;
|
||||
}
|
||||
//if (doPar) CalcPar8(pte, wr + i * 16 + 8, hi);
|
||||
syndromeCalc(pte, wr + i * maxNpar * 2 + maxNpar, (ushort)hi);
|
||||
|
||||
int pk = ((int)(lo << 16)) >> 16;
|
||||
peak = Math.Max(peak, (pk << 1) ^ (pk >> 31));
|
||||
|
||||
@@ -56,7 +56,15 @@ namespace CUETools.AccurateRip
|
||||
return stride;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int LastStride
|
||||
{
|
||||
get
|
||||
{
|
||||
return laststride;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class CDRepairEncode : CDRepair
|
||||
{
|
||||
@@ -85,16 +93,18 @@ 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 string GetTrackCRCs(int oi)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
for (int i = 1; i <= ar.TOC.AudioTracks; i++)
|
||||
sb.AppendFormat(" {0:x8}", this.TrackCRC(i, oi));
|
||||
return sb.ToString().Substring(1);
|
||||
}
|
||||
|
||||
public uint TrackCRC(int iTrack, int oi)
|
||||
{
|
||||
return this.ar.CTDBCRC(iTrack, oi, this.stride / 2, this.laststride / 2);
|
||||
}
|
||||
|
||||
public unsafe bool FindOffset(ushort[,] syn2, uint expectedCRC, out int actualOffset, out bool hasErrors)
|
||||
{
|
||||
@@ -107,56 +117,44 @@ namespace CUETools.AccurateRip
|
||||
throw new Exception("ar.Position != ar.FinalSampleCount");
|
||||
|
||||
var rs = new RsDecode16(npar, this.galois);
|
||||
int part2 = 0;
|
||||
// find offset
|
||||
fixed (ushort* chT = rs.chienTable, syn2part = &syn2[part2, 0])
|
||||
fixed (ushort* syn2part = syn2)
|
||||
{
|
||||
int* _sigma = stackalloc int[npar];
|
||||
int* _errpos = stackalloc int[npar];
|
||||
int* syn = stackalloc int[npar];
|
||||
bool foundOffset = false;
|
||||
var arSyndrome = ar.GetSyndrome(npar);
|
||||
int bestOffset = 0;
|
||||
int bestOffsetErrors = npar / 2;
|
||||
|
||||
for (int allowed_errors = 0; allowed_errors < npar / 2 && !foundOffset; allowed_errors++)
|
||||
// fast search
|
||||
for (int offset = 1 - stride / 2; offset < stride / 2; offset++)
|
||||
{
|
||||
// We can only use offset if Abs(offset * 2) < stride,
|
||||
// else we might need to add/remove more than one sample
|
||||
// from syndrome calculations, and that would be too difficult
|
||||
// and will probably require longer leadin/leadout.
|
||||
for (int offset = 1 - stride / 2; offset < stride / 2; offset++)
|
||||
var syn1 = ar.GetSyndrome(npar, 1, -offset);
|
||||
int err = 0;
|
||||
for (int i = 0; i < npar; i++)
|
||||
{
|
||||
int err = 0;
|
||||
int part = (part2 + stride - offset * 2) % stride;
|
||||
|
||||
for (int i = 0; i < npar; i++)
|
||||
{
|
||||
int synI = arSyndrome[part, i];
|
||||
|
||||
// offset < 0
|
||||
if (part < -offset * 2)
|
||||
{
|
||||
synI ^= galois.mulExp(ar.leadin[stride + part], (i * (stridecount - 1)) % galois.Max);
|
||||
synI = ar.leadout[laststride - part - 1] ^ galois.mulExp(synI, i);
|
||||
}
|
||||
// offset > 0
|
||||
if (part >= stride - offset * 2)
|
||||
{
|
||||
synI = galois.divExp(synI ^ ar.leadout[laststride + stride - part - 1], i);
|
||||
synI ^= galois.mulExp(ar.leadin[part], (i * (stridecount - 1)) % galois.Max);
|
||||
}
|
||||
|
||||
synI = galois.mulExp(synI ^ syn2part[i], i * npar);
|
||||
syn[i] = synI;
|
||||
err |= synI;
|
||||
}
|
||||
int err_count = err == 0 ? 0 : rs.calcSigmaMBM(_sigma, syn);
|
||||
if (err_count == allowed_errors && (err_count == 0 || rs.chienSearch(_errpos, stridecount + npar, err_count, _sigma, chT)))
|
||||
{
|
||||
actualOffset = offset;
|
||||
hasErrors = err_count != 0 || ar.CTDBCRC(-offset) != expectedCRC;
|
||||
return true;
|
||||
}
|
||||
int synI = syn1[0, i] ^ syn2part[i];
|
||||
syn[i] = synI;
|
||||
err |= synI;
|
||||
}
|
||||
if (err == 0)
|
||||
{
|
||||
actualOffset = offset;
|
||||
hasErrors = ar.CTDBCRC(-offset) != expectedCRC;
|
||||
return true;
|
||||
}
|
||||
int err_count = rs.calcSigmaMBM(_sigma, syn);
|
||||
if (err_count > 0 && err_count < bestOffsetErrors && rs.chienSearch(_errpos, stridecount, err_count, _sigma))
|
||||
{
|
||||
bestOffset = offset;
|
||||
bestOffsetErrors = err_count;
|
||||
}
|
||||
}
|
||||
|
||||
if (bestOffsetErrors < npar / 2)
|
||||
{
|
||||
actualOffset = bestOffset;
|
||||
hasErrors = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
actualOffset = 0;
|
||||
@@ -164,99 +162,92 @@ namespace CUETools.AccurateRip
|
||||
return false;
|
||||
}
|
||||
|
||||
public unsafe CDRepairFix VerifyParity(ushort[,] syn2, int actualOffset)
|
||||
public unsafe CDRepairFix VerifyParity(ushort[,] syn2, uint crc, int actualOffset)
|
||||
{
|
||||
int npar2 = syn2.GetLength(1);
|
||||
int npar = Math.Min(AccurateRipVerify.maxNpar, npar2);
|
||||
|
||||
CDRepairFix fix = new CDRepairFix(this, npar);
|
||||
fix.actualOffset = actualOffset;
|
||||
fix.correctableErrors = 0;
|
||||
fix.hasErrors = false;
|
||||
fix.canRecover = true;
|
||||
|
||||
fix.sigma = new int[stride, npar / 2 + 2];
|
||||
fix.omega = new int[stride, npar / 2 + 1];
|
||||
fix.errpos = new int[stride, npar / 2];
|
||||
//fix.erroff = new int[stride, npar / 2];
|
||||
fix.errors = new int[stride];
|
||||
|
||||
var syn1 = ar.GetSyndrome(npar);
|
||||
var erroff = new int[stride * npar / 2];
|
||||
var forney = new ushort[stride * npar / 2];
|
||||
var syn1 = ar.GetSyndrome(npar, -1, -actualOffset);
|
||||
var rs = new RsDecode16(npar, this.galois);
|
||||
CDRepairFix fix = new CDRepairFix(this, npar);
|
||||
|
||||
//fixed (byte* par = &parity2[pos])
|
||||
fixed (ushort* exp = galois.ExpTbl, log = galois.LogTbl, chT = rs.chienTable, psyn2 = syn2, psyn1 = syn1)
|
||||
fixed (int* sf = fix.sigma, of = fix.omega, ef = fix.errpos)
|
||||
fix.actualOffset = actualOffset;
|
||||
fix.correctableErrors = 0;
|
||||
fix.hasErrors = false;
|
||||
fix.canRecover = true;
|
||||
|
||||
fixed (ushort *psyn2 = syn2, psyn1 = syn1)
|
||||
{
|
||||
int sfLen = fix.sigma.GetLength(1);
|
||||
int ofLen = fix.omega.GetLength(1);
|
||||
int efLen = fix.errpos.GetLength(1);
|
||||
int sfLen = npar / 2 + 2;
|
||||
int ofLen = npar / 2 + 1;
|
||||
int efLen = npar / 2;
|
||||
int* _sigma = stackalloc int[npar / 2 + 2];
|
||||
int* _omega = stackalloc int[npar / 2 + 1];
|
||||
int* _errpos = stackalloc int[npar / 2];
|
||||
int* syn = stackalloc int[npar];
|
||||
int offset = fix.actualOffset;
|
||||
|
||||
for (int part = 0; part < stride; part++)
|
||||
for (int part2 = 0; part2 < stride; part2++)
|
||||
{
|
||||
int part2 = (part + offset * 2 + stride) % stride;
|
||||
ushort* syn1part = psyn1 + part * npar;
|
||||
ushort* syn1part = psyn1 + part2 * npar;
|
||||
ushort* syn2part = psyn2 + part2 * npar;
|
||||
int err = 0;
|
||||
|
||||
for (int i = 0; i < npar; i++)
|
||||
{
|
||||
int synI = syn1part[i];
|
||||
|
||||
// offset < 0
|
||||
if (part < -offset * 2)
|
||||
{
|
||||
synI ^= galois.mulExp(ar.leadin[stride + part], (i * (stridecount - 1)) % galois.Max);
|
||||
synI = ar.leadout[laststride - part - 1] ^ galois.mulExp(synI, i);
|
||||
}
|
||||
// offset > 0
|
||||
if (part >= stride - offset * 2)
|
||||
{
|
||||
synI = galois.divExp(synI ^ ar.leadout[laststride + stride - part - 1], i);
|
||||
synI ^= galois.mulExp(ar.leadin[part], (i * (stridecount - 1)) % galois.Max);
|
||||
}
|
||||
|
||||
synI = galois.mulExp(synI ^ syn2part[i], i * npar);
|
||||
var synI = syn1part[i] ^ syn2part[i];
|
||||
syn[i] = synI;
|
||||
err |= synI;
|
||||
}
|
||||
|
||||
//for (int j = 0; j < npar; j++)
|
||||
// if (wr[j] != 0)
|
||||
// {
|
||||
// ushort* myexp = exp + log[wr[j]];
|
||||
// syn[0] ^= wr[j];
|
||||
// for (int i = 1; i < npar; i++)
|
||||
// syn[i] ^= myexp[(npar - j - 1) * i];
|
||||
// }
|
||||
if (err != 0)
|
||||
{
|
||||
int errcount = rs.calcSigmaMBM(_sigma, syn);
|
||||
fix.hasErrors = true;
|
||||
if (errcount <= 0 || errcount > efLen || !rs.chienSearch(_errpos, stridecount, errcount, _sigma))
|
||||
{
|
||||
fix.canRecover = false;
|
||||
return fix;
|
||||
}
|
||||
|
||||
//for (int i = 0; i < npar; i++)
|
||||
// err |= syn[i];
|
||||
galois.mulPoly(_omega, _sigma, syn, ofLen, sfLen, npar);
|
||||
|
||||
if (err != 0)
|
||||
{
|
||||
int* s = sf + part * sfLen;
|
||||
int* o = of + part * ofLen;
|
||||
int* e = ef + part * efLen;
|
||||
//fixed (int* s = &fix.sigma[part, 0], o = &fix.omega[part, 0], e = &fix.errpos[part, 0])
|
||||
{
|
||||
fix.errors[part] = rs.calcSigmaMBM(s, syn);
|
||||
fix.hasErrors = true;
|
||||
fix.correctableErrors += fix.errors[part];
|
||||
if (fix.errors[part] <= 0 || !rs.chienSearch(e, stridecount + npar, fix.errors[part], s, chT))
|
||||
fix.canRecover = false;
|
||||
else
|
||||
galois.mulPoly(o, s, syn, ofLen, sfLen, npar);
|
||||
}
|
||||
}
|
||||
else
|
||||
fix.errors[part] = 0;
|
||||
for (int i = 0; i < errcount; i++)
|
||||
{
|
||||
int pos = galois.toPos(stridecount, _errpos[i]) * stride + part2;
|
||||
int erroffi = stride + pos - actualOffset * 2;
|
||||
ushort diff = (ushort)this.galois.doForney(errcount, _errpos[i], _sigma, _omega);
|
||||
if (erroffi < 0 || erroffi >= finalSampleCount * 2)
|
||||
{
|
||||
fix.canRecover = false;
|
||||
return fix;
|
||||
}
|
||||
crc ^= Crc32.Combine(Crc32.ComputeChecksum(Crc32.ComputeChecksum(0, (byte)diff), (byte)(diff >> 8)), 0, (stridecount * stride - pos - 1) * 2);
|
||||
erroff[fix.correctableErrors] = erroffi;
|
||||
forney[fix.correctableErrors] = diff;
|
||||
fix.correctableErrors++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
crc ^= ar.CTDBCRC(-actualOffset);
|
||||
if (crc != 0)
|
||||
{
|
||||
fix.canRecover = false;
|
||||
return fix;
|
||||
}
|
||||
}
|
||||
|
||||
return fix;
|
||||
fix.erroffsorted = new int[fix.correctableErrors];
|
||||
fix.forneysorted = new ushort[fix.correctableErrors];
|
||||
for (int i = 0; i < fix.correctableErrors; i++)
|
||||
{
|
||||
fix.erroffsorted[i] = erroff[i];
|
||||
fix.forneysorted[i] = forney[i];
|
||||
}
|
||||
Array.Sort<int, ushort>(fix.erroffsorted, fix.forneysorted, 0, fix.correctableErrors);
|
||||
return fix;
|
||||
}
|
||||
|
||||
public string OffsetSafeCRC
|
||||
@@ -273,15 +264,10 @@ namespace CUETools.AccurateRip
|
||||
internal bool hasErrors = false, canRecover = true;
|
||||
internal int actualOffset = 0;
|
||||
internal int correctableErrors = 0;
|
||||
internal int[,] sigma;
|
||||
internal int[,] omega;
|
||||
internal int[,] errpos;
|
||||
internal int[] erroffsorted;
|
||||
internal int[] erroffsorted;
|
||||
internal ushort[] forneysorted;
|
||||
internal int erroffcount;
|
||||
internal int[] errors;
|
||||
private BitArray affectedSectorArray;
|
||||
private int nexterroff;
|
||||
private int nexterroff = 0;
|
||||
private int npar;
|
||||
uint crc = 0;
|
||||
|
||||
@@ -289,29 +275,13 @@ namespace CUETools.AccurateRip
|
||||
: base(decode)
|
||||
{
|
||||
this.npar = npar;
|
||||
}
|
||||
}
|
||||
|
||||
public string AffectedSectors
|
||||
{
|
||||
get
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
SortErrors();
|
||||
for (int i = 0; i < erroffcount; i++)
|
||||
{
|
||||
int j;
|
||||
for (j = i + 1; j < erroffcount; j++)
|
||||
if (erroffsorted[j] - erroffsorted[j - 1] > 2 * 588 * 5)
|
||||
break;
|
||||
uint sec1 = (uint)erroffsorted[i] / 2 / 588;
|
||||
uint sec2 = (uint)erroffsorted[j - 1] / 2 / 588;
|
||||
if (sb.Length != 0) sb.Append(",");
|
||||
sb.Append(CDImageLayout.TimeToString(sec1));
|
||||
if (sec1 != sec2) sb.Append("-");
|
||||
if (sec1 != sec2) sb.Append(CDImageLayout.TimeToString(sec2));
|
||||
i = j - 1;
|
||||
}
|
||||
return sb.ToString();
|
||||
return this.GetAffectedSectors(0, finalSampleCount);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -322,43 +292,46 @@ namespace CUETools.AccurateRip
|
||||
if (affectedSectorArray == null)
|
||||
{
|
||||
affectedSectorArray = new BitArray(finalSampleCount / 588 + 1);
|
||||
SortErrors();
|
||||
for (int i = 0; i < erroffcount; i++)
|
||||
for (int i = 0; i < correctableErrors; i++)
|
||||
affectedSectorArray[erroffsorted[i] / 2 / 588] = true;
|
||||
}
|
||||
return affectedSectorArray;
|
||||
}
|
||||
}
|
||||
|
||||
private int GetErrOff(int part, int i)
|
||||
{
|
||||
return (2 + galois.toPos(stridecount + npar, errpos[part, i]) - (stride + part + ActualOffset * 2) / stride) * stride + part;
|
||||
}
|
||||
public int GetAffectedSectorsCount(int min, int max)
|
||||
{
|
||||
min = Math.Max(2 * min, stride - 2 * ActualOffset);
|
||||
max = Math.Min(2 * max, 2 * finalSampleCount - laststride - 2 * ActualOffset);
|
||||
int count = 0;
|
||||
for (int i = 0; i < correctableErrors; i++)
|
||||
if (erroffsorted[i] >= min && erroffsorted[i] < max)
|
||||
count++;
|
||||
return count;
|
||||
}
|
||||
|
||||
private unsafe void SortErrors()
|
||||
{
|
||||
if (erroffsorted != null)
|
||||
return;
|
||||
erroffcount = 0;
|
||||
erroffsorted = new int[errpos.GetLength(0) * errpos.GetLength(1)];
|
||||
forneysorted = new ushort[errpos.GetLength(0) * errpos.GetLength(1)];
|
||||
for (int part = 0; part < stride; part++)
|
||||
{
|
||||
fixed (int* s = &sigma[part, 0], o = &omega[part, 0])
|
||||
for (int i = 0; i < errors[part]; i++)
|
||||
{
|
||||
erroffsorted[erroffcount] = GetErrOff(part, i);
|
||||
if (erroffsorted[erroffcount] >= 0 && erroffsorted[erroffcount] < finalSampleCount * 2)
|
||||
{
|
||||
forneysorted[erroffcount] = (ushort)this.galois.doForney(errors[part], errpos[part, i], s, o);
|
||||
erroffcount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
Array.Sort<int, ushort>(erroffsorted, forneysorted, 0, erroffcount);
|
||||
// assert erroffcount == CorrectableErrors
|
||||
nexterroff = 0;
|
||||
}
|
||||
public string GetAffectedSectors(int min, int max)
|
||||
{
|
||||
min = Math.Max(2 * min, stride - 2 * ActualOffset);
|
||||
max = Math.Min(2 * max, 2 * finalSampleCount - laststride - 2 * ActualOffset);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < correctableErrors; i++)
|
||||
if (erroffsorted[i] >= min && erroffsorted[i] < max)
|
||||
{
|
||||
int j;
|
||||
for (j = i + 1; j < correctableErrors; j++)
|
||||
if (erroffsorted[j] - erroffsorted[j - 1] > 2 * 588 * 5)
|
||||
break;
|
||||
uint sec1 = (uint)(erroffsorted[i] - min) / 2 / 588;
|
||||
uint sec2 = (uint)(erroffsorted[j - 1] - min) / 2 / 588;
|
||||
if (sb.Length != 0) sb.Append(",");
|
||||
sb.Append(CDImageLayout.TimeToString(sec1));
|
||||
if (sec1 != sec2) sb.Append("-");
|
||||
if (sec1 != sec2) sb.Append(CDImageLayout.TimeToString(sec2));
|
||||
i = j - 1;
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public unsafe void Write(AudioBuffer sampleBuffer)
|
||||
{
|
||||
@@ -370,15 +343,13 @@ namespace CUETools.AccurateRip
|
||||
int firstPos = Math.Max(0, stride - sampleCount * 2 - ActualOffset * 2);
|
||||
int lastPos = Math.Min(sampleBuffer.ByteLength >> 1, (finalSampleCount - sampleCount) * 2 - laststride - ActualOffset * 2);
|
||||
|
||||
SortErrors();
|
||||
|
||||
fixed (byte* bytes = sampleBuffer.Bytes)
|
||||
fixed (uint* t = Crc32.table)
|
||||
{
|
||||
ushort* data = (ushort*)bytes;
|
||||
for (int pos = firstPos; pos < lastPos; pos++)
|
||||
{
|
||||
if (sampleCount * 2 + pos == erroffsorted[nexterroff] && nexterroff < erroffsorted.Length)
|
||||
if (nexterroff < erroffsorted.Length && sampleCount * 2 + pos == erroffsorted[nexterroff])
|
||||
data[pos] ^= forneysorted[nexterroff++];
|
||||
|
||||
ushort dd = data[pos];
|
||||
|
||||
Reference in New Issue
Block a user