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); 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; private byte[] parity;
internal ushort[, ,] encodeTable; internal ushort[, ,] encodeTable;
private int maxOffset; private int maxOffset;

View File

@@ -14,47 +14,27 @@ namespace CUETools.AccurateRip
protected int sampleCount; protected int sampleCount;
protected int finalSampleCount; protected int finalSampleCount;
internal Galois galois; internal Galois galois;
protected RsDecode rs;
//protected uint crc;
protected int[] encodeGx;
internal int stride; internal int stride;
internal int laststride; internal int laststride;
internal int stridecount; 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.stride = stride;
this.finalSampleCount = finalSampleCount; this.finalSampleCount = finalSampleCount;
sampleCount = 0; sampleCount = 0;
galois = Galois16.instance; galois = Galois16.instance;
rs = new RsDecode16(npar, galois);
//crc32 = new Crc32();
//crc = 0xffffffff;
encodeGx = galois.makeEncodeGxLog(npar);
laststride = stride + (finalSampleCount * 2) % stride; laststride = stride + (finalSampleCount * 2) % stride;
stridecount = (finalSampleCount * 2) / stride - 2; // minus one for leadin and one for leadout 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"); throw new Exception("invalid stride");
} }
public CDRepair(CDRepair src) 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 public long FinalSampleCount
{ {
get get
@@ -69,14 +49,6 @@ namespace CUETools.AccurateRip
} }
} }
public int NPAR
{
get
{
return npar;
}
}
public int Stride public int Stride
{ {
get get
@@ -90,183 +62,13 @@ namespace CUETools.AccurateRip
{ {
protected AccurateRipVerify ar; protected AccurateRipVerify ar;
public CDRepairEncode(AccurateRipVerify ar, int stride, int npar) public CDRepairEncode(AccurateRipVerify ar, int stride)
: base ((int)ar.FinalSampleCount, stride, npar) : base ((int)ar.FinalSampleCount, stride)
{ {
this.ar = ar; this.ar = ar;
ar.InitCDRepair(stride, laststride, stridecount, true); 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 public AccurateRipVerify AR
{ {
get 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) public unsafe bool FindOffset(ushort[,] syn2, uint expectedCRC, out int actualOffset, out bool hasErrors)
{ {
int npar2 = syn2.GetLength(1); int npar2 = syn2.GetLength(1);
int npar = Math.Min(AccurateRipVerify.maxNpar, npar2);
if (npar2 != npar) if (npar2 != npar)
throw new Exception("npar mismatch"); throw new Exception("npar mismatch");
if (ar.Position != ar.FinalSampleCount) if (ar.Position != ar.FinalSampleCount)
throw new Exception("ar.Position != ar.FinalSampleCount"); throw new Exception("ar.Position != ar.FinalSampleCount");
var rs = new RsDecode16(npar, this.galois);
int part2 = 0; int part2 = 0;
// find offset // find offset
fixed (ushort* chT = rs.chienTable, syn2part = &syn2[part2, 0]) fixed (ushort* chT = rs.chienTable, syn2part = &syn2[part2, 0])
@@ -366,19 +164,12 @@ namespace CUETools.AccurateRip
return false; 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) public unsafe CDRepairFix VerifyParity(ushort[,] syn2, int actualOffset)
{ {
int npar2 = syn2.GetLength(1); 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.actualOffset = actualOffset;
fix.correctableErrors = 0; fix.correctableErrors = 0;
fix.hasErrors = false; fix.hasErrors = false;
@@ -391,12 +182,16 @@ namespace CUETools.AccurateRip
fix.errors = new int[stride]; fix.errors = new int[stride];
var syn1 = ar.GetSyndrome(npar); var syn1 = ar.GetSyndrome(npar);
var rs = new RsDecode16(npar, this.galois);
//fixed (byte* par = &parity2[pos]) //fixed (byte* par = &parity2[pos])
fixed (ushort* exp = galois.ExpTbl, log = galois.LogTbl, chT = rs.chienTable, psyn2 = syn2, psyn1 = syn1) 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) fixed (int* sf = fix.sigma, of = fix.omega, ef = fix.errpos)
{ {
int* syn = stackalloc int[npar]; 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; int offset = fix.actualOffset;
for (int part = 0; part < stride; part++) for (int part = 0; part < stride; part++)
@@ -442,9 +237,9 @@ namespace CUETools.AccurateRip
if (err != 0) if (err != 0)
{ {
int* s = sf + part * fix.sigma.GetLength(1); int* s = sf + part * sfLen;
int* o = of + part * fix.omega.GetLength(1); int* o = of + part * ofLen;
int* e = ef + part * fix.errpos.GetLength(1); int* e = ef + part * efLen;
//fixed (int* s = &fix.sigma[part, 0], o = &fix.omega[part, 0], e = &fix.errpos[part, 0]) //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.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)) if (fix.errors[part] <= 0 || !rs.chienSearch(e, stridecount + npar, fix.errors[part], s, chT))
fix.canRecover = false; fix.canRecover = false;
else else
galois.mulPoly(o, s, syn, npar / 2 + 1, npar, npar); galois.mulPoly(o, s, syn, ofLen, sfLen, npar);
} }
} }
else else
@@ -471,22 +266,6 @@ namespace CUETools.AccurateRip
return ar.OffsetSafeCRC.Base64; 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 public class CDRepairFix : CDRepair, IAudioDest
@@ -503,11 +282,13 @@ namespace CUETools.AccurateRip
internal int[] errors; internal int[] errors;
private BitArray affectedSectorArray; private BitArray affectedSectorArray;
private int nexterroff; private int nexterroff;
private int npar;
uint crc = 0; uint crc = 0;
internal CDRepairFix(CDRepairEncode decode) internal CDRepairFix(CDRepairEncode decode, int npar)
: base(decode) : base(decode)
{ {
this.npar = npar;
} }
public string AffectedSectors public string AffectedSectors
@@ -561,7 +342,7 @@ namespace CUETools.AccurateRip
erroffcount = 0; erroffcount = 0;
erroffsorted = new int[errpos.GetLength(0) * errpos.GetLength(1)]; erroffsorted = new int[errpos.GetLength(0) * errpos.GetLength(1)];
forneysorted = new ushort[errpos.GetLength(0) * errpos.GetLength(1)]; forneysorted = new ushort[errpos.GetLength(0) * errpos.GetLength(1)];
for (int part = 0; part < stride; part++) for (int part = 0; part < stride; part++)
{ {
fixed (int* s = &sigma[part, 0], o = &omega[part, 0]) fixed (int* s = &sigma[part, 0], o = &omega[part, 0])
for (int i = 0; i < errors[part]; i++) for (int i = 0; i < errors[part]; i++)
@@ -569,7 +350,7 @@ namespace CUETools.AccurateRip
erroffsorted[erroffcount] = GetErrOff(part, i); erroffsorted[erroffcount] = GetErrOff(part, i);
if (erroffsorted[erroffcount] >= 0 && erroffsorted[erroffcount] < finalSampleCount * 2) 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++; erroffcount++;
} }
} }

View File

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

View File

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

View File

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

Binary file not shown.

View File

@@ -39,6 +39,16 @@ namespace CUETools.Parity
erasure_diff = Galois16.instance.gfdiff(erasure_loc_pol); 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) public static unsafe byte[] Syndrome2Parity(ushort[,] syndrome, byte[] parity = null)
{ {
var stride = syndrome.GetLength(0); var stride = syndrome.GetLength(0);
@@ -65,14 +75,6 @@ namespace CUETools.Parity
return syndrome; 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) public static unsafe void Parity2Syndrome(ushort *ppar, ushort *psyn, int stride, int npar, int npar2)
{ {
if (npar > npar2) if (npar > npar2)

View File

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

View File

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