Preparing for next version of CTDB

This commit is contained in:
chudov
2011-10-27 20:50:11 +00:00
parent 2299e5f920
commit b84f1de118
9 changed files with 154 additions and 355 deletions

View File

@@ -330,13 +330,6 @@ namespace CUETools.AccurateRip
return ParityToSyndrome.Parity2Syndrome(stride, npar, maxNpar, parity);
}
public unsafe byte[] GetSyndromeBytes(int npar = maxNpar)
{
if (!calcParity)
throw new InvalidOperationException();
return ParityToSyndrome.Parity2SyndromeBytes(stride, npar, maxNpar, parity);
}
private byte[] parity;
internal ushort[, ,] encodeTable;
private int maxOffset;

View File

@@ -14,47 +14,27 @@ namespace CUETools.AccurateRip
protected int sampleCount;
protected int finalSampleCount;
internal Galois galois;
protected RsDecode rs;
//protected uint crc;
protected int[] encodeGx;
internal int stride;
internal int laststride;
internal int stridecount;
internal int npar;
public CDRepair(int finalSampleCount, int stride, int npar)
public CDRepair(int finalSampleCount, int stride)
{
this.npar = npar;
this.stride = stride;
this.finalSampleCount = finalSampleCount;
sampleCount = 0;
galois = Galois16.instance;
rs = new RsDecode16(npar, galois);
//crc32 = new Crc32();
//crc = 0xffffffff;
encodeGx = galois.makeEncodeGxLog(npar);
laststride = stride + (finalSampleCount * 2) % stride;
stridecount = (finalSampleCount * 2) / stride - 2; // minus one for leadin and one for leadout
if ((finalSampleCount * 2 + stride - 1) / stride + npar > galois.Max)
if ((finalSampleCount * 2 + stride - 1) / stride + AccurateRipVerify.maxNpar > galois.Max)
throw new Exception("invalid stride");
}
public CDRepair(CDRepair src)
: this(src.finalSampleCount, src.stride, src.npar)
: this(src.finalSampleCount, src.stride)
{
}
//public unsafe void Write(AudioBuffer sampleBuffer)
//{
// throw new Exception("unsupported");
//}
//public unsafe void Close()
//{
// if (sampleCount != finalSampleCount)
// throw new Exception("sampleCount != finalSampleCount");
//}
public long FinalSampleCount
{
get
@@ -69,14 +49,6 @@ namespace CUETools.AccurateRip
}
}
public int NPAR
{
get
{
return npar;
}
}
public int Stride
{
get
@@ -90,183 +62,13 @@ namespace CUETools.AccurateRip
{
protected AccurateRipVerify ar;
public CDRepairEncode(AccurateRipVerify ar, int stride, int npar)
: base ((int)ar.FinalSampleCount, stride, npar)
public CDRepairEncode(AccurateRipVerify ar, int stride)
: base ((int)ar.FinalSampleCount, stride)
{
this.ar = ar;
ar.InitCDRepair(stride, laststride, stridecount, true);
}
//private unsafe void ProcessStride(int currentStride, int currentPart, int count, ushort* data)
//{
// fixed (uint* crct = Crc32.table)
// fixed (byte* bpar = parity)
// fixed (ushort* exp = galois.ExpTbl, log = galois.LogTbl, synptr = syndrome)
// fixed (int* gx = encodeGx)
// for (int pos = 0; pos < count; pos++)
// {
// ushort* par = (ushort*)bpar;
// int part = currentPart + pos;
// ushort* wr = ((ushort*)par) + part * npar;
// ushort dd = data[pos];
// //crc = (crc >> 8) ^ crct[(byte)(crc ^ dd)];
// //crc = (crc >> 8) ^ crct[(byte)(crc ^ (dd >> 8))];
// if (verify)
// {
// ushort* syn = synptr + part * npar;
// syn[0] ^= dd; // wk += data
// for (int i = 1; i < npar; i++)
// syn[i] = (ushort)(dd ^ galois.mulExp(syn[i], i)); // wk = data + wk * α^i
// }
// int ib = wr[0] ^ dd;
// if (ib != 0)
// {
// ushort* myexp = exp + log[ib];
// for (int i = 0; i < npar - 1; i++)
// wr[i] = (ushort)(wr[i + 1] ^ myexp[gx[i]]);
// wr[npar - 1] = myexp[gx[npar - 1]];
// }
// else
// {
// for (int i = 0; i < npar - 1; i++)
// wr[i] = wr[i + 1];
// wr[npar - 1] = 0;
// }
// }
//}
//private unsafe void ProcessStride16(int currentStride, int currentPart, int count, ushort* data)
//{
// fixed (uint* crct = Crc32.table)
// fixed (byte* bpar = parity)
// fixed (ushort* exp = galois.ExpTbl, log = galois.LogTbl, synptr = syndrome)
// for (int pos = 0; pos < count; pos++)
// {
// ushort* par = (ushort*)bpar;
// int part = currentPart + pos;
// ushort* wr = par + part * 16;
// ushort dd = data[pos];
// //crc = (crc >> 8) ^ crct[(byte)(crc ^ dd)];
// //crc = (crc >> 8) ^ crct[(byte)(crc ^ (dd >> 8))];
// int ib = wr[0] ^ dd;
// if (ib != 0)
// {
// ushort* myexp = exp + log[ib];
// wr[0] = (ushort)(wr[1] ^ myexp[0x000059f1]);
// wr[1] = (ushort)(wr[2] ^ myexp[0x0000608f]);
// wr[2] = (ushort)(wr[3] ^ myexp[0x0000918b]);
// wr[3] = (ushort)(wr[4] ^ myexp[0x00004487]);
// wr[4] = (ushort)(wr[5] ^ myexp[0x0000a151]);
// wr[5] = (ushort)(wr[6] ^ myexp[0x0000c074]);
// wr[6] = (ushort)(wr[7] ^ myexp[0x00004178]);
// wr[7] = (ushort)(wr[8] ^ myexp[0x00004730]);
// wr[8] = (ushort)(wr[9] ^ myexp[0x00004187]);
// wr[9] = (ushort)(wr[10] ^ myexp[0x0000c092]);
// wr[10] = (ushort)(wr[11] ^ myexp[0x0000a17e]);
// wr[11] = (ushort)(wr[12] ^ myexp[0x000044c3]);
// wr[12] = (ushort)(wr[13] ^ myexp[0x000091d6]);
// wr[13] = (ushort)(wr[14] ^ myexp[0x000060e9]);
// wr[14] = (ushort)(wr[15] ^ myexp[0x00005a5a]);
// wr[15] = myexp[0x00000078];
// }
// else
// {
// wr[0] = wr[1];
// wr[1] = wr[2];
// wr[2] = wr[3];
// wr[3] = wr[4];
// wr[4] = wr[5];
// wr[5] = wr[6];
// wr[6] = wr[7];
// wr[7] = wr[8];
// wr[8] = wr[9];
// wr[9] = wr[10];
// wr[10] = wr[11];
// wr[11] = wr[12];
// wr[12] = wr[13];
// wr[13] = wr[14];
// wr[14] = wr[15];
// wr[15] = 0;
// }
// // syn[i] += data[pos] * α^(n*i)
// if (verify && dd != 0)
// {
// int n = stridecount - currentStride;
// ushort* syn = synptr + part * 16;
// syn[0] ^= dd;
// int idx = log[dd];
// idx += n; syn[1] ^= exp[(idx & 0xffff) + (idx >> 16)];
// idx += n; syn[2] ^= exp[(idx & 0xffff) + (idx >> 16)];
// idx += n; syn[3] ^= exp[(idx & 0xffff) + (idx >> 16)];
// idx += n; syn[4] ^= exp[(idx & 0xffff) + (idx >> 16)];
// idx += n; syn[5] ^= exp[(idx & 0xffff) + (idx >> 16)];
// idx += n; syn[6] ^= exp[(idx & 0xffff) + (idx >> 16)];
// idx += n; syn[7] ^= exp[(idx & 0xffff) + (idx >> 16)];
// idx += n; syn[8] ^= exp[(idx & 0xffff) + (idx >> 16)];
// idx += n; syn[9] ^= exp[(idx & 0xffff) + (idx >> 16)];
// idx += n; syn[10] ^= exp[(idx & 0xffff) + (idx >> 16)];
// idx += n; syn[11] ^= exp[(idx & 0xffff) + (idx >> 16)];
// idx += n; syn[12] ^= exp[(idx & 0xffff) + (idx >> 16)];
// idx += n; syn[13] ^= exp[(idx & 0xffff) + (idx >> 16)];
// idx += n; syn[14] ^= exp[(idx & 0xffff) + (idx >> 16)];
// idx += n; syn[15] ^= exp[(idx & 0xffff) + (idx >> 16)];
// }
// }
//}
//new public unsafe void Write(AudioBuffer sampleBuffer)
//{
// if (!verify && !encode)
// return;
// sampleBuffer.Prepare(this);
// if ((sampleBuffer.ByteLength & 1) != 0 || sampleCount + sampleBuffer.Length > finalSampleCount)
// throw new Exception("sampleCount > finalSampleCount");
// fixed (byte* bytes = sampleBuffer.Bytes)
// {
// int offs = 0;
// while (offs < sampleBuffer.Length)
// {
// int currentPart = (sampleCount * 2) % stride;
// int currentStride = (sampleCount * 2) / stride;
// // Process no more than there is in the buffer, and no more than up to a stride boundary.
// int copyCount = Math.Min((sampleBuffer.Length - offs) * 2, stride - currentPart);
// ushort* data = ((ushort*)bytes) + offs * 2;
// if (currentStride < 2)
// for (int pos = 0; pos < copyCount; pos++)
// leadin[sampleCount * 2 + pos] = data[pos];
// if (currentStride >= stridecount)
// for (int pos = 0; pos < copyCount; pos++)
// {
// int remaining = (finalSampleCount - sampleCount) * 2 - pos - 1;
// if (remaining < stride + laststride)
// leadout[remaining] = data[pos];
// }
// if (currentStride >= 1 && currentStride <= stridecount)
// {
// if (npar == 16)
// ProcessStride16(currentStride, currentPart, copyCount, data);
// else if (npar != 8)
// ProcessStride(currentStride, currentPart, copyCount, data);
// }
// sampleCount += copyCount >> 1;
// offs += copyCount >> 1;
// }
// }
//}
public AccurateRipVerify AR
{
get
@@ -294,21 +96,17 @@ namespace CUETools.AccurateRip
}
}
public unsafe bool FindOffset(int npar2, byte[] parity2, int pos, uint expectedCRC, out int actualOffset, out bool hasErrors)
{
var syn2 = ParityToSyndrome.Parity2Syndrome(1, npar2, npar2, parity2, pos);
return FindOffset(syn2, expectedCRC, out actualOffset, out hasErrors);
}
public unsafe bool FindOffset(ushort[,] syn2, uint expectedCRC, out int actualOffset, out bool hasErrors)
{
int npar2 = syn2.GetLength(1);
int npar = Math.Min(AccurateRipVerify.maxNpar, npar2);
if (npar2 != npar)
throw new Exception("npar mismatch");
if (ar.Position != ar.FinalSampleCount)
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])
@@ -366,19 +164,12 @@ namespace CUETools.AccurateRip
return false;
}
public unsafe CDRepairFix VerifyParity(int npar2, byte[] parity2, int pos, int len, int actualOffset)
{
if (len != stride * npar2 * 2)
throw new Exception("wrong size");
var syn2 = ParityToSyndrome.Parity2Syndrome(stride, npar2, npar2, parity2, pos);
return VerifyParity(syn2, actualOffset);
}
public unsafe CDRepairFix VerifyParity(ushort[,] syn2, int actualOffset)
{
int npar2 = syn2.GetLength(1);
int npar = Math.Min(AccurateRipVerify.maxNpar, npar2);
CDRepairFix fix = new CDRepairFix(this);
CDRepairFix fix = new CDRepairFix(this, npar);
fix.actualOffset = actualOffset;
fix.correctableErrors = 0;
fix.hasErrors = false;
@@ -391,11 +182,15 @@ namespace CUETools.AccurateRip
fix.errors = new int[stride];
var syn1 = ar.GetSyndrome(npar);
var rs = new RsDecode16(npar, this.galois);
//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)
{
int sfLen = fix.sigma.GetLength(1);
int ofLen = fix.omega.GetLength(1);
int efLen = fix.errpos.GetLength(1);
int* syn = stackalloc int[npar];
int offset = fix.actualOffset;
@@ -442,9 +237,9 @@ namespace CUETools.AccurateRip
if (err != 0)
{
int* s = sf + part * fix.sigma.GetLength(1);
int* o = of + part * fix.omega.GetLength(1);
int* e = ef + part * fix.errpos.GetLength(1);
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);
@@ -453,7 +248,7 @@ namespace CUETools.AccurateRip
if (fix.errors[part] <= 0 || !rs.chienSearch(e, stridecount + npar, fix.errors[part], s, chT))
fix.canRecover = false;
else
galois.mulPoly(o, s, syn, npar / 2 + 1, npar, npar);
galois.mulPoly(o, s, syn, ofLen, sfLen, npar);
}
}
else
@@ -471,22 +266,6 @@ namespace CUETools.AccurateRip
return ar.OffsetSafeCRC.Base64;
}
}
public ushort[,] Syndrome
{
get
{
return this.ar.GetSyndrome(this.npar);
}
}
public byte[] Parity
{
get
{
return this.ar.GetParity(this.npar);
}
}
}
public class CDRepairFix : CDRepair, IAudioDest
@@ -503,11 +282,13 @@ namespace CUETools.AccurateRip
internal int[] errors;
private BitArray affectedSectorArray;
private int nexterroff;
private int npar;
uint crc = 0;
internal CDRepairFix(CDRepairEncode decode)
internal CDRepairFix(CDRepairEncode decode, int npar)
: base(decode)
{
this.npar = npar;
}
public string AffectedSectors
@@ -569,7 +350,7 @@ namespace CUETools.AccurateRip
erroffsorted[erroffcount] = GetErrOff(part, i);
if (erroffsorted[erroffcount] >= 0 && erroffsorted[erroffcount] < finalSampleCount * 2)
{
forneysorted[erroffcount] = (ushort)rs.doForney(errors[part], errpos[part, i], s, o);
forneysorted[erroffcount] = (ushort)this.galois.doForney(errors[part], errpos[part, i], s, o);
erroffcount++;
}
}

View File

@@ -89,6 +89,10 @@
<Project>{6458A13A-30EF-45A9-9D58-E5031B17BEE2}</Project>
<Name>CUETools.Codecs</Name>
</ProjectReference>
<ProjectReference Include="..\CUETools.Parity\CUETools.Parity.csproj">
<Project>{ECEB839C-171B-4535-958F-9899310A0342}</Project>
<Name>CUETools.Parity</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">

View File

@@ -10,6 +10,7 @@ using System.Text;
using System.Xml.Serialization;
using CUETools.AccurateRip;
using CUETools.CDImage;
using CUETools.Parity;
using Krystalware.UploadHelper;
namespace CUETools.CTDB
@@ -101,13 +102,16 @@ namespace CUETools.CTDB
var parity = Convert.FromBase64String(ctdbRespEntry.parity);
var entry_toc = CDImageLayout.FromString(ctdbRespEntry.toc);
this.total += ctdbRespEntry.confidence;
if (parity.Length != ctdbRespEntry.npar * 2)
throw new Exception("invalid parity length");
//if (verify.Stride != ctdbRespEntry.stride * 2)
// throw new Exception("invalid stride length");
var syndrome = ParityToSyndrome.Parity2Syndrome(1, ctdbRespEntry.npar, ctdbRespEntry.npar, parity);
var entry = new DBEntry(
parity,
0,
parity.Length,
syndrome,
ctdbRespEntry.confidence,
ctdbRespEntry.npar,
ctdbRespEntry.stride,
ctdbRespEntry.stride * 2,
uint.Parse(ctdbRespEntry.crc32, NumberStyles.HexNumber),
ctdbRespEntry.id,
entry_toc,
@@ -165,8 +169,8 @@ namespace CUETools.CTDB
if (entry.httpStatus == HttpStatusCode.OK)
{
if (resp.ContentLength < entry.npar * entry.stride * 4 ||
resp.ContentLength > entry.npar * entry.stride * 8)
if (resp.ContentLength < entry.Npar * entry.stride * 2 ||
resp.ContentLength > entry.Npar * entry.stride * 4)
{
entry.httpStatus = HttpStatusCode.PartialContent;
}
@@ -230,13 +234,15 @@ namespace CUETools.CTDB
return this.DBStatus;
DBEntry confirm = this.MatchingEntry;
if (confirm != null) confidence = 1;
DoSubmit(confidence, quality, artist, title, barcode, false, confirm);
int npar = AccurateRipVerify.maxNpar;
var parity = verify.AR.GetParity(npar);
DoSubmit(confidence, quality, artist, title, barcode, false, confirm, parity, npar);
if (subResult == "parity needed")
DoSubmit(confidence, quality, artist, title, barcode, true, confirm);
DoSubmit(confidence, quality, artist, title, barcode, true, confirm, parity, npar);
return subResult;
}
protected string DoSubmit(int confidence, int quality, string artist, string title, string barcode, bool upload, DBEntry confirm)
protected string DoSubmit(int confidence, int quality, string artist, string title, string barcode, bool upload, DBEntry confirm, byte[] parity, int npar)
{
UploadFile[] files;
if (upload)
@@ -253,9 +259,9 @@ namespace CUETools.CTDB
using (DBHDR DISC = CTDB.HDR("DISC"))
{
using (DBHDR CONF = DISC.HDR("CONF")) CONF.Write(confidence);
using (DBHDR NPAR = DISC.HDR("NPAR")) NPAR.Write(verify.NPAR);
using (DBHDR NPAR = DISC.HDR("NPAR")) NPAR.Write(npar);
using (DBHDR CRC_ = DISC.HDR("CRC ")) CRC_.Write(verify.CRC);
using (DBHDR PAR_ = DISC.HDR("PAR ")) PAR_.Write(verify.Parity);
using (DBHDR PAR_ = DISC.HDR("PAR ")) PAR_.Write(parity);
}
}
newcontents.Position = 0;
@@ -278,7 +284,7 @@ namespace CUETools.CTDB
form.Add("toc", toc.ToString());
form.Add("crc32", ((int)verify.CRC).ToString());
form.Add("trackcrcs", verify.TrackCRCs);
form.Add("parity", Convert.ToBase64String(verify.Parity, 0, 16));
form.Add("parity", Convert.ToBase64String(parity, 0, npar * 2));
form.Add("confidence", confidence.ToString());
form.Add("userid", GetUUID());
form.Add("quality", quality.ToString());
@@ -327,11 +333,9 @@ namespace CUETools.CTDB
private bool Parse(byte[] contents, DBEntry entry)
{
if (contents.Length == entry.npar * entry.stride * 4)
if (contents.Length == entry.Npar * entry.stride * 2)
{
entry.parity = contents;
entry.pos = 0;
entry.len = contents.Length;
entry.syndrome = ParityToSyndrome.Parity2Syndrome(entry.stride, entry.Npar, entry.Npar, contents);
return true;
}
@@ -377,9 +381,9 @@ namespace CUETools.CTDB
}
if (parPos != 0)
{
entry.parity = contents;
entry.pos = parPos;
entry.len = parLen;
if (parLen != entry.Npar * entry.stride * 2)
return false;
entry.syndrome = ParityToSyndrome.Parity2Syndrome(entry.stride, entry.Npar, entry.Npar, contents, parPos);
return true;
}
}
@@ -392,13 +396,13 @@ namespace CUETools.CTDB
return;
foreach (DBEntry entry in entries)
{
if (entry.toc.Pregap != toc.Pregap || entry.toc.AudioLength != toc.AudioLength || entry.stride != verify.Stride / 2)
if (entry.toc.Pregap != toc.Pregap || entry.toc.AudioLength != toc.AudioLength || entry.stride != verify.Stride)
{
entry.hasErrors = true;
entry.canRecover = false;
continue;
}
if (!verify.FindOffset(entry.npar, entry.parity, entry.pos, entry.crc, out entry.offset, out entry.hasErrors))
if (!verify.FindOffset(entry.syndrome, entry.crc, out entry.offset, out entry.hasErrors))
entry.canRecover = false;
else if (entry.hasErrors)
{
@@ -411,7 +415,7 @@ namespace CUETools.CTDB
entry.canRecover = false;
else
{
entry.repair = verify.VerifyParity(entry.npar, entry.parity, entry.pos, entry.len, entry.offset);
entry.repair = verify.VerifyParity(entry.syndrome, entry.offset);
entry.canRecover = entry.repair.CanRecover;
}
}
@@ -448,10 +452,7 @@ namespace CUETools.CTDB
public void Init(AccurateRipVerify ar)
{
int npar = 8;
foreach (DBEntry entry in entries)
npar = Math.Max(npar, entry.npar);
verify = new CDRepairEncode(ar, 10 * 588 * 2, npar);
verify = new CDRepairEncode(ar, 10 * 588 * 2);
}
public CDImageLayout TOC

View File

@@ -6,11 +6,8 @@ namespace CUETools.CTDB
{
public class DBEntry
{
public byte[] parity;
public int pos;
public int len;
public ushort[,] syndrome;
public int conf;
public int npar;
public int stride;
public int offset;
public uint crc;
@@ -22,20 +19,25 @@ namespace CUETools.CTDB
public CDImageLayout toc;
public string hasParity;
public DBEntry(byte[] parity, int pos, int len, int conf, int npar, int stride, uint crc, string id, CDImageLayout toc, string hasParity)
public DBEntry(ushort[,] syndrome, int conf, int stride, uint crc, string id, CDImageLayout toc, string hasParity)
{
this.parity = parity;
this.syndrome = syndrome;
this.id = id;
this.pos = pos;
this.len = len;
this.conf = conf;
this.crc = crc;
this.npar = npar;
this.stride = stride;
this.toc = toc;
this.hasParity = hasParity;
}
public int Npar
{
get
{
return syndrome.GetLength(1);
}
}
public string Status
{
get

Binary file not shown.

View File

@@ -39,6 +39,16 @@ namespace CUETools.Parity
erasure_diff = Galois16.instance.gfdiff(erasure_loc_pol);
}
public static unsafe string ToBase64String(ushort[,] inArray, int offset, int length)
{
var outBuf = new byte[inArray.GetLength(1) * length * 2];
fixed (ushort* inPtr = &inArray[offset, 0])
fixed (byte* outPtr = outBuf)
for (int i = 0; i < inArray.GetLength(1) * length; i++)
((ushort*)outPtr)[i] = inPtr[i];
return Convert.ToBase64String(outBuf);
}
public static unsafe byte[] Syndrome2Parity(ushort[,] syndrome, byte[] parity = null)
{
var stride = syndrome.GetLength(0);
@@ -65,14 +75,6 @@ namespace CUETools.Parity
return syndrome;
}
public static unsafe byte[] Parity2SyndromeBytes(int stride, int npar, int npar2, byte[] parity)
{
var syndrome = new byte[stride * npar * 2];
fixed (byte* pbpar = parity, psyn = syndrome)
Parity2Syndrome((ushort*)pbpar, (ushort*)psyn, stride, npar, npar2);
return syndrome;
}
public static unsafe void Parity2Syndrome(ushort *ppar, ushort *psyn, int stride, int npar, int npar2)
{
if (npar > npar2)

View File

@@ -70,10 +70,10 @@ namespace CUETools.TestHelpers
return ar;
}
public CDRepairEncode CreateCDRepairEncode(int stride, int npar)
public CDRepairEncode CreateCDRepairEncode(int stride)
{
var ar = new AccurateRipVerify(toc, null);
var encode = new CDRepairEncode(ar, stride, npar);
var encode = new CDRepairEncode(ar, stride);
ar.Position = start;
Write(ar);
//ar.Close();

View File

@@ -27,7 +27,6 @@ namespace CUETools.TestParity
// but it probably should still be a multiple of 588 * 2;
// (or the size of CD CIRC buffer?)
const int stride = 10 * 588 * 2;
const int npar = 8;
const int errors = stride / 4;
const int offset = 48;
const int seed = 2423;
@@ -36,6 +35,9 @@ namespace CUETools.TestParity
private static TestImageGenerator generator;
private static CDRepairEncode encode;
private static string[] encodeSyndrome = new string[33];
private static string[] encodeParity = new string[33];
private static string[] encodeParity1 = new string[33];
private TestContext testContextInstance;
/// <summary>
@@ -63,7 +65,14 @@ namespace CUETools.TestParity
public static void MyClassInitialize(TestContext testContext)
{
generator = new TestImageGenerator("0 9801", seed, 32 * 588, 0);
encode = generator.CreateCDRepairEncode(stride, npar);
encode = generator.CreateCDRepairEncode(stride);
encodeSyndrome[4] = "DP7tAM2tuWBe7kb/A3o5hcS+o59uoT1ckHh9Am+wZxA=";
encodeSyndrome[8] = "DP7tAM2tuWCBRjyLjt6a+l7uRv8DejmFzRtv3ofeEWzEvqOfbqE9XFOz/6WaYU+lkHh9Am+wZxCw3m1Y7zKctw==";
encodeSyndrome[16] = "DP7tAM2tuWCBRjyLjt6a+lr7hvwnJWrfZ0MGKOYwFmVe7kb/A3o5hc0bb96H3hFsIcjxCpERbjnJjVvLc5NDJcS+o59uoT1cU7P/pZphT6WaQ4f3L/ImdyD5psk3fWRvkHh9Am+wZxCw3m1Y7zKct8QUsJHnLA6wcmxT/LmmQdE=";
encodeParity[8] = "jvR9QJ1cSWpqbyP0I0tBrBkQRjCDTDDQkttZGj14ROvsXyg+AnnxVKxL7gwLZbrQmTw5ZPps1Q3744g94qaOOQ==";
encodeParity[16] = "gwln1GxlYWH/Jn74PreMLv4aFF2glkScSWVFlxMBx94v5D3/3wPx+2guRLquED0s9tOFikPLiSnAv0Xq8aIQ6Q==";
encodeParity1[8] = "CWgEDNLjSi22nIOyaeyp+12R3UCVWlzIb+nbv8XWXg9YEhkHxYr8xqrr1+hIbFwKNEXnj0esJrKbiW3XGbHsYw==";
encodeParity1[16] = "BdvaDZCGCVEggrcfscGQWdfSXnCSrOcpD6NfKZGYraK80J2a+v/zkDPWePOQ9k0u0WdWNJ9hQKvPJD0wf2MN+g==";
}
//
//Use ClassCleanup to run code after all tests in a class have run
@@ -86,20 +95,25 @@ namespace CUETools.TestParity
//
#endregion
[TestMethod()]
public void CDRepairEncodeSyndromeTest()
{
for (int n = 4; n <= AccurateRipVerify.maxNpar; n *= 2)
{
Assert.AreEqual<string>(encodeSyndrome[n], ParityToSyndrome.ToBase64String(encode.AR.GetSyndrome(n), 0, 4));
}
Assert.AreEqual<uint>(377539636, encode.CRC);
}
/// <summary>
///A test for Write
///</summary>
[TestMethod()]
public void CDRepairEncodeWriteTest()
public void CDRepairEncodeParityTest()
{
Assert.AreEqual<string>("jvR9QJ1cSWpqbyP0I0tBrBkQRjCDTDDQkttZGj14ROvsXyg+AnnxVKxL7gwLZbrQmTw5ZPps1Q3744g94qaOOQ==",
Convert.ToBase64String(encode.AR.GetParity(8), 0, 64));
Assert.AreEqual<string>("DP7tAM2tuWCBRjyLjt6a+l7uRv8DejmFzRtv3ofeEWzEvqOfbqE9XFOz/6WaYU+lkHh9Am+wZxCw3m1Y7zKctw==",
Convert.ToBase64String(encode.AR.GetSyndromeBytes(8), 0, 64));
if (AccurateRipVerify.maxNpar >= 16)
for (int n = 8; n <= AccurateRipVerify.maxNpar; n *= 2)
{
Assert.AreEqual<string>("gwln1GxlYWH/Jn74PreMLv4aFF2glkScSWVFlxMBx94v5D3/3wPx+2guRLquED0s9tOFikPLiSnAv0Xq8aIQ6Q==",
Convert.ToBase64String(encode.AR.GetParity(16), 0, 64));
Assert.AreEqual<string>(encodeParity[n], Convert.ToBase64String(encode.AR.GetParity(n), 0, 64));
}
Assert.AreEqual<uint>(377539636, encode.CRC);
}
@@ -110,10 +124,13 @@ namespace CUETools.TestParity
[TestMethod()]
public void CDRepairDecodeOriginalTest()
{
var decode = generator.CreateCDRepairEncode(stride, npar);
var decode = generator.CreateCDRepairEncode(stride);
int actualOffset;
bool hasErrors;
Assert.IsTrue(decode.FindOffset(encode.NPAR, encode.Parity, 0, encode.CRC, out actualOffset, out hasErrors));
Assert.IsTrue(decode.FindOffset(encode.AR.GetSyndrome(), encode.CRC, out actualOffset, out hasErrors));
Assert.IsFalse(hasErrors, "has errors");
Assert.AreEqual(0, actualOffset, "wrong offset");
Assert.IsTrue(decode.FindOffset(encode.AR.GetSyndrome(8), encode.CRC, out actualOffset, out hasErrors));
Assert.IsFalse(hasErrors, "has errors");
Assert.AreEqual(0, actualOffset, "wrong offset");
}
@@ -125,13 +142,13 @@ namespace CUETools.TestParity
public void CDRepairDecodeOriginalWithPregapTest()
{
var generator2 = new TestImageGenerator("32 9833", seed, 0, 0);
var decode = generator2.CreateCDRepairEncode(stride, npar);
var decode = generator2.CreateCDRepairEncode(stride);
int actualOffset;
bool hasErrors;
Assert.IsTrue(decode.FindOffset(encode.NPAR, encode.Parity, 0, encode.CRC, out actualOffset, out hasErrors));
Assert.IsTrue(decode.FindOffset(encode.AR.GetSyndrome(), encode.CRC, out actualOffset, out hasErrors));
Assert.IsTrue(hasErrors, "doesn't have errors");
Assert.AreEqual(-1176, actualOffset, "wrong offset");
CDRepairFix fix = decode.VerifyParity(encode.Syndrome, actualOffset);
CDRepairFix fix = decode.VerifyParity(encode.AR.GetSyndrome(), actualOffset);
Assert.IsTrue(fix.HasErrors, "doesn't have errors");
Assert.IsTrue(fix.CanRecover, "cannot recover");
}
@@ -143,13 +160,13 @@ namespace CUETools.TestParity
public void CDRepairDecodeModifiedTest()
{
var generator2 = new TestImageGenerator("0 9801", seed, 32 * 588, errors);
var decode = generator2.CreateCDRepairEncode(stride, npar);
var decode = generator2.CreateCDRepairEncode(stride);
int actualOffset;
bool hasErrors;
Assert.IsTrue(decode.FindOffset(encode.NPAR, encode.Parity, 0, encode.CRC, out actualOffset, out hasErrors));
Assert.IsTrue(decode.FindOffset(encode.AR.GetSyndrome(), encode.CRC, out actualOffset, out hasErrors));
Assert.IsTrue(hasErrors, "doesn't have errors");
Assert.AreEqual(0, actualOffset, "wrong offset");
CDRepairFix fix = decode.VerifyParity(encode.Syndrome, actualOffset);
CDRepairFix fix = decode.VerifyParity(encode.AR.GetSyndrome(), actualOffset);
Assert.IsTrue(fix.HasErrors, "doesn't have errors");
Assert.IsTrue(fix.CanRecover, "cannot recover");
generator2.Write(fix);
@@ -163,10 +180,10 @@ namespace CUETools.TestParity
public void CDRepairDecodePositiveOffsetTest()
{
var generator2 = new TestImageGenerator("0 9801", seed, 32 * 588 + offset, 0);
var decode = generator2.CreateCDRepairEncode(stride, npar);
var decode = generator2.CreateCDRepairEncode(stride);
int actualOffset;
bool hasErrors;
Assert.IsTrue(decode.FindOffset(encode.NPAR, encode.Parity, 0, encode.CRC, out actualOffset, out hasErrors));
Assert.IsTrue(decode.FindOffset(encode.AR.GetSyndrome(), encode.CRC, out actualOffset, out hasErrors));
Assert.IsFalse(hasErrors, "has errors");
Assert.AreEqual(offset, actualOffset, "wrong offset");
}
@@ -178,10 +195,10 @@ namespace CUETools.TestParity
public void CDRepairDecodeNegativeOffsetTest()
{
var generator2 = new TestImageGenerator("0 9801", seed, 32 * 588 - offset, 0);
var decode = generator2.CreateCDRepairEncode(stride, npar);
var decode = generator2.CreateCDRepairEncode(stride);
int actualOffset;
bool hasErrors;
Assert.IsTrue(decode.FindOffset(encode.NPAR, encode.Parity, 0, encode.CRC, out actualOffset, out hasErrors));
Assert.IsTrue(decode.FindOffset(encode.AR.GetSyndrome(), encode.CRC, out actualOffset, out hasErrors));
Assert.IsFalse(hasErrors, "has errors");
Assert.AreEqual(-offset, actualOffset, "wrong offset");
}
@@ -193,10 +210,10 @@ namespace CUETools.TestParity
public void CDRepairDecodePositiveOffsetErrorsTest()
{
var generator2 = new TestImageGenerator("0 9801", seed, 32 * 588 + offset, errors);
var decode = generator2.CreateCDRepairEncode(stride, npar);
var decode = generator2.CreateCDRepairEncode(stride);
int actualOffset;
bool hasErrors;
var syn = encode.AR.GetSyndrome(encode.NPAR);
var syn = encode.AR.GetSyndrome();
Assert.IsTrue(decode.FindOffset(syn, encode.CRC, out actualOffset, out hasErrors));
Assert.IsTrue(hasErrors, "doesn't have errors");
Assert.AreEqual(offset, actualOffset, "wrong offset");
@@ -214,17 +231,26 @@ namespace CUETools.TestParity
public void CDRepairDecodeNegativeOffsetErrorsTest()
{
var generator2 = new TestImageGenerator("0 999 9801", seed, 32 * 588 - offset, errors);
var decode = generator2.CreateCDRepairEncode(stride, npar);
var decode = generator2.CreateCDRepairEncode(stride);
int actualOffset;
bool hasErrors;
Assert.IsTrue(decode.FindOffset(encode.NPAR, encode.Parity, 0, encode.CRC, out actualOffset, out hasErrors), "couldn't find offset");
Assert.IsTrue(decode.FindOffset(encode.AR.GetSyndrome(), encode.CRC, out actualOffset, out hasErrors), "couldn't find offset");
Assert.IsTrue(hasErrors, "doesn't have errors");
Assert.AreEqual(-offset, actualOffset, "wrong offset");
CDRepairFix fix = decode.VerifyParity(encode.Syndrome, actualOffset);
var fix = decode.VerifyParity(encode.AR.GetSyndrome(), actualOffset);
Assert.IsTrue(fix.HasErrors, "doesn't have errors");
Assert.IsTrue(fix.CanRecover, "cannot recover");
generator2.Write(fix);
Assert.AreEqual<uint>(encode.CRC, fix.CRC);
if (AccurateRipVerify.maxNpar > 8)
{
fix = decode.VerifyParity(encode.AR.GetSyndrome(8), actualOffset);
Assert.IsTrue(fix.HasErrors, "doesn't have errors");
Assert.IsTrue(fix.CanRecover, "cannot recover");
generator2.Write(fix);
Assert.AreEqual<uint>(encode.CRC, fix.CRC);
}
}
[TestMethod]
@@ -274,16 +300,16 @@ namespace CUETools.TestParity
public void CDRepairSplitTest()
{
var seed = 723722;
var ar0 = new TestImageGenerator("13 68 99 136", seed, 0, 0).CreateCDRepairEncode(stride, npar);
var ar0 = new TestImageGenerator("13 68 99 136", seed, 0, 0).CreateCDRepairEncode(stride);
var splits = new int[] { 1, 13 * 588 - 1, 13 * 588, 13 * 588 + 1, 30 * 588 - 1, 30 * 588, 30 * 588 + 1, 68 * 588 - 1, 68 * 588, 68 * 588 + 1 };
foreach (int split in splits)
{
var ar1 = new TestImageGenerator("13 68 99 136", seed, 0, 0, 0, split).CreateCDRepairEncode(stride, npar);
var ar2 = new TestImageGenerator("13 68 99 136", seed, 0, 0, split, (int)ar0.FinalSampleCount).CreateCDRepairEncode(stride, npar);
var ar1 = new TestImageGenerator("13 68 99 136", seed, 0, 0, 0, split).CreateCDRepairEncode(stride);
var ar2 = new TestImageGenerator("13 68 99 136", seed, 0, 0, split, (int)ar0.FinalSampleCount).CreateCDRepairEncode(stride);
ar1.AR.Combine(ar2.AR, split, (int)ar0.FinalSampleCount);
string message = "split = " + CDImageLayout.TimeToString((uint)split / 588) + "." + (split % 588).ToString();
Assert.AreEqual(ar0.CRC, ar1.CRC, "CRC was not set correctly, " + message);
CollectionAssert.AreEqual(ar0.Parity, ar1.Parity, "Parity was not set correctly, " + message);
CollectionAssert.AreEqual(ar0.AR.GetParity(), ar1.AR.GetParity(), "Parity was not set correctly, " + message);
}
}
@@ -295,8 +321,8 @@ namespace CUETools.TestParity
{
var seed = 723722;
var split = 20 * 588;
var ar1 = new TestImageGenerator("13 68 99 136", seed, 0, 0, 0, split).CreateCDRepairEncode(stride, npar);
var ar2 = new TestImageGenerator("13 68 99 136", seed, 0, 0, split, (int)ar1.FinalSampleCount).CreateCDRepairEncode(stride, npar);
var ar1 = new TestImageGenerator("13 68 99 136", seed, 0, 0, 0, split).CreateCDRepairEncode(stride);
var ar2 = new TestImageGenerator("13 68 99 136", seed, 0, 0, split, (int)ar1.FinalSampleCount).CreateCDRepairEncode(stride);
for (int i = 0; i < 20; i++)
ar1.AR.Combine(ar2.AR, split, (int)ar1.FinalSampleCount);
}
@@ -307,37 +333,26 @@ namespace CUETools.TestParity
[TestMethod()]
public unsafe void CDRepairSyndrome2ParitySpeedTest()
{
byte[] parityCopy = new byte[encode.Parity.Length];
var syndrome = encode.Syndrome;
byte[] parityCopy = new byte[encode.AR.GetParity().Length];
var syndrome = encode.AR.GetSyndrome();
for (int t = 0; t < 100; t++)
ParityToSyndrome.Syndrome2Parity(syndrome, parityCopy);
CollectionAssert.AreEqual(encode.Parity, parityCopy);
CollectionAssert.AreEqual(encode.AR.GetParity(), parityCopy);
}
[TestMethod]
public unsafe void CDRepairEncodeSynParTest()
{
var parityCopy = ParityToSyndrome.Syndrome2Parity(encode.Syndrome);
CollectionAssert.AreEqual(encode.Parity, parityCopy);
var parityCopy = ParityToSyndrome.Syndrome2Parity(encode.AR.GetSyndrome());
CollectionAssert.AreEqual(encode.AR.GetParity(), parityCopy);
}
[TestMethod]
public void CDRepairEncodeSpeedTest()
{
var generator = new TestImageGenerator("0 75000", seed, 0, 0);
var encode = generator.CreateCDRepairEncode(stride, npar);
Assert.AreEqual<string>("CWgEDNLjSi22nIOyaeyp+12R3UCVWlzIb+nbv8XWXg9YEhkHxYr8xqrr1+hIbFwKNEXnj0esJrKbiW3XGbHsYw==",
Convert.ToBase64String(encode.Parity, 0, 64));
var syndrome = encode.Syndrome;
var bsyn = new byte[64];
for (int i = 0; i < 4; i++)
for (int j = 0; j < 8; j++)
{
bsyn[(i * 8 + j) * 2] = (byte)syndrome[i, j];
bsyn[(i * 8 + j) * 2 + 1] = (byte)(syndrome[i, j] >> 8);
}
Assert.AreEqual<string>("YJPyo4+KY35P+DpljMplMGbMWXmpvhkdDOCKeEo4NDoRPPW7D0cv8hmLb7yZujp0sVg/6AEWKY5QrDKkiYp0Zw==",
Convert.ToBase64String(bsyn));
var encode = generator.CreateCDRepairEncode(stride);
Assert.AreEqual<string>(encodeParity1[AccurateRipVerify.maxNpar], Convert.ToBase64String(encode.AR.GetParity(), 0, 64), "parity mismatch");
}
/// <summary>
@@ -348,17 +363,18 @@ namespace CUETools.TestParity
public void CDRepairVerifyParitySpeedTest()
{
var generator1 = new TestImageGenerator("0 98011", seed, 32 * 588, 0);
var encode1 = generator1.CreateCDRepairEncode(stride, npar);
var encode1 = generator1.CreateCDRepairEncode(stride);
var generator2 = new TestImageGenerator("0 98011", seed, 32 * 588, errors/2);
var decode = generator2.CreateCDRepairEncode(stride, npar);
var decode = generator2.CreateCDRepairEncode(stride);
int actualOffset;
bool hasErrors;
Assert.IsTrue(decode.FindOffset(encode1.NPAR, encode1.Parity, 0, encode1.CRC, out actualOffset, out hasErrors));
var syndrome = encode1.AR.GetSyndrome();
Assert.IsTrue(decode.FindOffset(syndrome, encode1.CRC, out actualOffset, out hasErrors));
Assert.IsTrue(hasErrors, "doesn't have errors");
Assert.AreEqual(0, actualOffset, "wrong offset");
for (int t = 0; t < 1000; t++)
decode.VerifyParity(encode1.Syndrome, actualOffset);
CDRepairFix fix = decode.VerifyParity(encode1.Syndrome, actualOffset);
decode.VerifyParity(syndrome, actualOffset);
CDRepairFix fix = decode.VerifyParity(syndrome, actualOffset);
Assert.IsTrue(fix.HasErrors, "doesn't have errors");
Assert.IsTrue(fix.CanRecover, "cannot recover");
generator2.Write(fix);