diff --git a/CUETools.AccurateRip/AccurateRip.cs b/CUETools.AccurateRip/AccurateRip.cs index af151dc..c7b1a9f 100644 --- a/CUETools.AccurateRip/AccurateRip.cs +++ b/CUETools.AccurateRip/AccurateRip.cs @@ -5,154 +5,17 @@ using System.IO; using System.Net; using System.Text; using System.Threading; -using System.Xml.Serialization; using CUETools.Parity; using CUETools.CDImage; using CUETools.Codecs; namespace CUETools.AccurateRip { - [Serializable] - public class OffsetSafeCRCRecord - { - private uint[] val; - - public OffsetSafeCRCRecord() - { - this.val = new uint[1]; - } - - public OffsetSafeCRCRecord(AccurateRipVerify ar) - : this(new uint[64 + 64]) - { - int offset = 64 * 64; - for (int i = 0; i < 64; i++) - this.val[i] = ar.CTDBCRC(0, (i + 1) * 64, offset, 2 * offset); - for (int i = 0; i < 64; i++) - this.val[i + 64] = ar.CTDBCRC(0, 63 - i, offset, 2 * offset); - } - - public OffsetSafeCRCRecord(uint[] val) - { - this.val = val; - } - - [XmlIgnore] - public uint[] Value - { - get - { - return val; - } - } - - public unsafe string Base64 - { - get - { - byte[] res = new byte[val.Length * 4]; - fixed (byte* pres = &res[0]) - fixed (uint* psrc = &val[0]) - AudioSamples.MemCpy(pres, (byte*)psrc, res.Length); - var b64 = new char[res.Length * 2 + 4]; - int b64len = Convert.ToBase64CharArray(res, 0, res.Length, b64, 0); - StringBuilder sb = new StringBuilder(b64len + b64len / 4 + 1); - for (int i = 0; i < b64len; i += 64) - { - sb.Append(b64, i, Math.Min(64, b64len - i)); - sb.AppendLine(); - } - return sb.ToString(); - } - - set - { - if (value == null) - throw new ArgumentNullException(); - byte[] bytes = Convert.FromBase64String(value); - if (bytes.Length % 4 != 0) - throw new InvalidDataException(); - val = new uint[bytes.Length / 4]; - fixed (byte* pb = &bytes[0]) - fixed (uint* pv = &val[0]) - AudioSamples.MemCpy((byte*)pv, pb, bytes.Length); - } - } - - public override bool Equals(object obj) - { - return obj is OffsetSafeCRCRecord && this == (OffsetSafeCRCRecord)obj; - } - - public override int GetHashCode() - { - return (int)val[0]; - } - - public static bool operator ==(OffsetSafeCRCRecord x, OffsetSafeCRCRecord y) - { - if (x as object == null || y as object == null) return x as object == null && y as object == null; - if (x.Value.Length != y.Value.Length) return false; - for (int i = 0; i < x.Value.Length; i++) - if (x.Value[i] != y.Value[i]) - return false; - return true; - } - - public static bool operator !=(OffsetSafeCRCRecord x, OffsetSafeCRCRecord y) - { - return !(x == y); - } - - public bool DifferByOffset(OffsetSafeCRCRecord rec) - { - int offset; - return FindOffset(rec, out offset); - } - - public bool FindOffset(OffsetSafeCRCRecord rec, out int offset) - { - if (this.Value.Length != 128 || rec.Value.Length != 128) - { - offset = 0; - return false; - //throw new InvalidDataException("Unsupported OffsetSafeCRCRecord"); - } - - for (int i = 0; i < 64; i++) - { - if (rec.Value[0] == Value[i]) - { - offset = i * 64; - return true; - } - if (Value[0] == rec.Value[i]) - { - offset = -i * 64; - return true; - } - for (int j = 0; j < 64; j++) - { - if (rec.Value[i] == Value[64 + j]) - { - offset = i * 64 + j + 1; - return true; - } - if (Value[i] == rec.Value[64 + j]) - { - offset = -i * 64 - j - 1; - return true; - } - } - } - offset = 0; - return false; - } - } - public class AccurateRipVerify : IAudioDest { - public AccurateRipVerify(CDImageLayout toc, IWebProxy proxy) + const int maxNpar = 8; + + public AccurateRipVerify(CDImageLayout toc, IWebProxy proxy) { this.proxy = proxy; _accDisks = new List(); @@ -451,62 +314,37 @@ namespace CUETools.AccurateRip _CRCLOG[iTrack] = value; } - public unsafe ushort[,] GetSyndrome() + public unsafe byte[] GetParity(int npar = maxNpar) + { + if (npar == maxNpar) + return this.parity; + + var synShort = this.GetSyndrome(npar); + return ParityToSyndrome.Syndrome2Parity(synShort); + } + + public unsafe ushort[,] GetSyndrome(int npar = maxNpar) { - if (!calcParity) - throw new InvalidOperationException(); - var syndrome = new ushort[stride, npar]; - fixed (byte* pbpar = parity) - fixed (ushort* psyn0 = syndrome, plog = Galois16.instance.LogTbl, pexp = Galois16.instance.ExpTbl) - { - ushort* ppar = (ushort*)pbpar; - for (int y = 0; y < stride; y++) - { - ushort* syn = psyn0 + y * npar; - for (int x1 = 0; x1 < npar; x1++) - { - ushort lo = ppar[y * npar + x1]; - if (lo != 0) - { - var llo = plog[lo] + 0xffff; - for (int x = 0; x < npar; x++) - syn[x] ^= pexp[llo - (1 + x1) * x]; - } - } - } - } - return syndrome; + if (!calcParity) + throw new InvalidOperationException(); + return ParityToSyndrome.Parity2Syndrome(stride, npar, maxNpar, parity); } - public unsafe ushort[,] Syndrome - { - get - { - if (syndrome == null) - syndrome = GetSyndrome(); - return syndrome; - } - } - - private ushort[,] syndrome; - internal byte[] parity; + private byte[] parity; internal ushort[, ,] encodeTable; private int maxOffset; internal ushort[] leadin; internal ushort[] leadout; - private int stride = 1, laststride = 1, stridecount = 1, npar = 1; + private int stride = 1, laststride = 1, stridecount = 1; private bool calcParity = false; - internal void InitCDRepair(int stride, int laststride, int stridecount, int npar, bool calcParity) + internal void InitCDRepair(int stride, int laststride, int stridecount, bool calcParity) { - if (npar != 8) - throw new ArgumentOutOfRangeException("npar"); if (stride % 2 != 0 || laststride % 2 != 0) throw new ArgumentOutOfRangeException("stride"); this.stride = stride; this.laststride = laststride; this.stridecount = stridecount; - this.npar = npar; this.calcParity = calcParity; Init(_toc); } @@ -572,20 +410,37 @@ namespace CUETools.AccurateRip // ((ulong*)wr)[1] = (((ulong*)(wr))[1] >> 16) ^ ((ulong*)ptiblo0)[1] ^ ((ulong*)ptiblo1)[1]; //} - private unsafe static void CalcPar8(ushort* pt, ushort* wr, uint lo, uint hi) + 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[8] ^ hi; - ushort* ptiblo0 = pt + (wrlo & 255) * 16; - ushort* ptiblo1 = pt + (wrlo >> 8) * 16 + 8; - ushort* ptibhi0 = pt + (wrhi & 255) * 16; - ushort* ptibhi1 = pt + (wrhi >> 8) * 16 + 8; - wr[8] = 0; - ((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]; + uint wrhi = wr[maxNpar] ^ hi; + 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; @@ -665,7 +520,7 @@ namespace CUETools.AccurateRip } uint hi = sample >> 16; - if (doPar) CalcPar8(pte, wr + i * 16, lo, hi); + if (doPar) CalcPar(pte, wr + i * maxNpar * 2, lo, hi); //if (doPar) CalcPar8(pte, wr + i * 16, lo); //uint hi = sample >> 16; @@ -738,7 +593,7 @@ namespace CUETools.AccurateRip uint* samples = ((uint*)pSampleBuff) + pos; int currentPart = ((int)_sampleCount * 2) % stride; //ushort* synptr = synptr1 + npar * currentPart; - ushort* wr = ((ushort*)bpar) + npar * currentPart; + ushort* wr = ((ushort*)bpar) + maxNpar * currentPart; int currentStride = ((int)_sampleCount * 2) / stride; for (int i = 0; i < Math.Min(leadin.Length - (int)_sampleCount * 2, copyCount * 2); i++) @@ -887,18 +742,13 @@ namespace CUETools.AccurateRip var imax = Math.Max(i1s, i2s); var diff1 = diff + (imin < i2s ? 1 : 0) - (imin < i1s ? 1 : 0); for (int i = 0; i < stride; i++) - for (int j = 0; j < npar; j++) + for (int j = 0; j < maxNpar; j++) { var d1 = j * (i >= imin && i < imax ? diff1 : diff); newSyndrome1[i, j] = (ushort)(newSyndrome2[i, j] ^ Galois16.instance.mulExp(newSyndrome1[i, j], (d1 & 0xffff) + (d1 >> 16))); } - fixed (byte* p = this.parity) - fixed (ushort* syn = newSyndrome1) - { - ushort* p1 = (ushort*)p; - for (int i = 0; i < stride; i++) - Galois16.instance.Syndrome2Parity(syn + i * npar, p1 + i * npar, npar); - } + + ParityToSyndrome.Syndrome2Parity(newSyndrome1, this.parity); } } @@ -924,10 +774,12 @@ namespace CUETools.AccurateRip _CRCV2 = new uint[_toc.AudioTracks + 1, 3 * maxOffset]; _Peak = new int[_toc.AudioTracks + 1]; - syndrome = null; - parity = calcParity ? new byte[stride * npar * 2] : null; - if (calcParity && npar == 8) - encodeTable = Galois16.instance.makeEncodeTable(npar); + parity = null; + if (calcParity) + { + parity = new byte[stride * maxNpar * 2]; + encodeTable = Galois16.instance.makeEncodeTable(maxNpar); + } int leadin_len = Math.Max(4096 * 4, calcParity ? stride * 2 : 0); int leadout_len = Math.Max(4096 * 4, calcParity ? stride + laststride : 0); diff --git a/CUETools.AccurateRip/CDRepair.cs b/CUETools.AccurateRip/CDRepair.cs index 4af6344..e8fca95 100644 --- a/CUETools.AccurateRip/CDRepair.cs +++ b/CUETools.AccurateRip/CDRepair.cs @@ -94,7 +94,7 @@ namespace CUETools.AccurateRip : base ((int)ar.FinalSampleCount, stride, npar) { this.ar = ar; - ar.InitCDRepair(stride, laststride, stridecount, npar, true); + ar.InitCDRepair(stride, laststride, stridecount, true); } //private unsafe void ProcessStride(int currentStride, int currentPart, int count, ushort* data) @@ -315,7 +315,7 @@ namespace CUETools.AccurateRip int* _errpos = stackalloc int[npar]; int* syn = stackalloc int[npar]; bool foundOffset = false; - var arSyndrome = ar.Syndrome; + var arSyndrome = ar.GetSyndrome(npar); for (int allowed_errors = 0; allowed_errors < npar / 2 && !foundOffset; allowed_errors++) { @@ -392,7 +392,7 @@ namespace CUETools.AccurateRip { int* syn = stackalloc int[npar]; int offset = fix.actualOffset; - var arSyndrome = ar.Syndrome; + var arSyndrome = ar.GetSyndrome(npar); for (int part = 0; part < stride; part++) { @@ -473,7 +473,7 @@ namespace CUETools.AccurateRip { get { - return ar.Syndrome; + return this.ar.GetSyndrome(this.npar); } } @@ -481,7 +481,7 @@ namespace CUETools.AccurateRip { get { - return ar.parity; + return this.ar.GetParity(this.npar); } } } diff --git a/CUETools.AccurateRip/CUETools.AccurateRip.csproj b/CUETools.AccurateRip/CUETools.AccurateRip.csproj index df0d383..51065c7 100644 --- a/CUETools.AccurateRip/CUETools.AccurateRip.csproj +++ b/CUETools.AccurateRip/CUETools.AccurateRip.csproj @@ -64,6 +64,7 @@ + diff --git a/CUETools.AccurateRip/OffsetSafeCRCRecord.cs b/CUETools.AccurateRip/OffsetSafeCRCRecord.cs new file mode 100644 index 0000000..66dc1c0 --- /dev/null +++ b/CUETools.AccurateRip/OffsetSafeCRCRecord.cs @@ -0,0 +1,147 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Xml.Serialization; +using CUETools.Codecs; + +namespace CUETools.AccurateRip +{ + [Serializable] + public class OffsetSafeCRCRecord + { + private uint[] val; + + public OffsetSafeCRCRecord() + { + this.val = new uint[1]; + } + + public OffsetSafeCRCRecord(AccurateRipVerify ar) + : this(new uint[64 + 64]) + { + int offset = 64 * 64; + for (int i = 0; i < 64; i++) + this.val[i] = ar.CTDBCRC(0, (i + 1) * 64, offset, 2 * offset); + for (int i = 0; i < 64; i++) + this.val[i + 64] = ar.CTDBCRC(0, 63 - i, offset, 2 * offset); + } + + public OffsetSafeCRCRecord(uint[] val) + { + this.val = val; + } + + [XmlIgnore] + public uint[] Value + { + get + { + return val; + } + } + + public unsafe string Base64 + { + get + { + byte[] res = new byte[val.Length * 4]; + fixed (byte* pres = &res[0]) + fixed (uint* psrc = &val[0]) + AudioSamples.MemCpy(pres, (byte*)psrc, res.Length); + var b64 = new char[res.Length * 2 + 4]; + int b64len = Convert.ToBase64CharArray(res, 0, res.Length, b64, 0); + StringBuilder sb = new StringBuilder(b64len + b64len / 4 + 1); + for (int i = 0; i < b64len; i += 64) + { + sb.Append(b64, i, Math.Min(64, b64len - i)); + sb.AppendLine(); + } + return sb.ToString(); + } + + set + { + if (value == null) + throw new ArgumentNullException(); + byte[] bytes = Convert.FromBase64String(value); + if (bytes.Length % 4 != 0) + throw new InvalidDataException(); + val = new uint[bytes.Length / 4]; + fixed (byte* pb = &bytes[0]) + fixed (uint* pv = &val[0]) + AudioSamples.MemCpy((byte*)pv, pb, bytes.Length); + } + } + + public override bool Equals(object obj) + { + return obj is OffsetSafeCRCRecord && this == (OffsetSafeCRCRecord)obj; + } + + public override int GetHashCode() + { + return (int)val[0]; + } + + public static bool operator ==(OffsetSafeCRCRecord x, OffsetSafeCRCRecord y) + { + if (x as object == null || y as object == null) return x as object == null && y as object == null; + if (x.Value.Length != y.Value.Length) return false; + for (int i = 0; i < x.Value.Length; i++) + if (x.Value[i] != y.Value[i]) + return false; + return true; + } + + public static bool operator !=(OffsetSafeCRCRecord x, OffsetSafeCRCRecord y) + { + return !(x == y); + } + + public bool DifferByOffset(OffsetSafeCRCRecord rec) + { + int offset; + return FindOffset(rec, out offset); + } + + public bool FindOffset(OffsetSafeCRCRecord rec, out int offset) + { + if (this.Value.Length != 128 || rec.Value.Length != 128) + { + offset = 0; + return false; + //throw new InvalidDataException("Unsupported OffsetSafeCRCRecord"); + } + + for (int i = 0; i < 64; i++) + { + if (rec.Value[0] == Value[i]) + { + offset = i * 64; + return true; + } + if (Value[0] == rec.Value[i]) + { + offset = -i * 64; + return true; + } + for (int j = 0; j < 64; j++) + { + if (rec.Value[i] == Value[64 + j]) + { + offset = i * 64 + j + 1; + return true; + } + if (Value[i] == rec.Value[64 + j]) + { + offset = -i * 64 - j - 1; + return true; + } + } + } + offset = 0; + return false; + } + } +} diff --git a/CUETools.Codecs.LAME/LameWriter.cs b/CUETools.Codecs.LAME/LameWriter.cs index d090a66..17e67a6 100644 --- a/CUETools.Codecs.LAME/LameWriter.cs +++ b/CUETools.Codecs.LAME/LameWriter.cs @@ -1,7 +1,7 @@ using System; -using System.IO; using System.Runtime.InteropServices; using CUETools.Codecs; +using System.IO; namespace CUETools.Codecs.LAME { diff --git a/CUETools.Parity/CUETools.Parity.csproj b/CUETools.Parity/CUETools.Parity.csproj index f3bb055..a8c614e 100644 --- a/CUETools.Parity/CUETools.Parity.csproj +++ b/CUETools.Parity/CUETools.Parity.csproj @@ -60,6 +60,7 @@ + diff --git a/CUETools.Parity/Galois.cs b/CUETools.Parity/Galois.cs index 0f5b6f6..2ce3981 100644 Binary files a/CUETools.Parity/Galois.cs and b/CUETools.Parity/Galois.cs differ diff --git a/CUETools.Parity/Parity2Syndrome.cs b/CUETools.Parity/Parity2Syndrome.cs new file mode 100644 index 0000000..cd205d1 --- /dev/null +++ b/CUETools.Parity/Parity2Syndrome.cs @@ -0,0 +1,159 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace CUETools.Parity +{ + public class ParityToSyndrome + { + private int[] erasures_pos; + private int[] erasure_loc_pol; + private int[] erasure_diff; + private int npar; + const int w = 16; + const int max = (1 << w) - 1; + + public ParityToSyndrome(int npar) + { + this.npar = npar; + this.InitTables(); + } + + private void InitTables() + { + var num_erasures = this.npar; + + // Compute the erasure locator polynomial: + erasures_pos = new int[num_erasures]; + for (int x = 0; x < num_erasures; x++) + erasures_pos[x] = x; + + //%Compute the erasure-locator polynomial + // Optimized version + var erasure_loc_pol_exp = new int[num_erasures + 1]; + erasure_loc_pol_exp[0] = 1; + for (int i = 0; i < num_erasures; i++) + for (int x = num_erasures; x > 0; x--) + erasure_loc_pol_exp[x] ^= Galois16.instance.mulExp(erasure_loc_pol_exp[x - 1], erasures_pos[i]); + erasure_loc_pol = Galois16.instance.toLog(erasure_loc_pol_exp); + erasure_diff = Galois16.instance.gfdiff(erasure_loc_pol); + } + + public static unsafe byte[] Syndrome2Parity(ushort[,] syndrome, byte[] parity = null) + { + var stride = syndrome.GetLength(0); + var npar = syndrome.GetLength(1); + var converter = new ParityToSyndrome(npar); + if (parity == null) + parity = new byte[npar * stride * 2]; + fixed (byte* bpar = parity) + fixed (ushort* syn = syndrome) + { + ushort* par = (ushort*)bpar; + for (int i = 0; i < stride; i++) + converter.Syndrome2Parity(syn + i * npar, par + i * npar); + } + return parity; + } + + public static unsafe ushort[,] Parity2Syndrome(int stride, int npar, int npar2, byte[] parity) + { + if (npar > npar2) + throw new InvalidOperationException(); + var syndrome = new ushort[stride, npar]; + fixed (byte* pbpar = parity) + fixed (ushort* psyn = syndrome, plog = Galois16.instance.LogTbl, pexp = Galois16.instance.ExpTbl) + { + ushort* ppar = (ushort*)pbpar; + for (int y = 0; y < stride; y++) + { + ushort* syn = psyn + y * npar; + ushort* par = ppar + y * npar2; + for (int x1 = 0; x1 < npar2; x1++) + { + ushort lo = par[x1]; + if (lo != 0) + { + var llo = plog[lo] + 0xffff; + for (int x = 0; x < npar; x++) + syn[x] ^= pexp[llo - (1 + x1) * x]; + } + } + } + } + return syndrome; + } + + public unsafe void Syndrome2Parity(ushort* syndrome, ushort* parity) + { + // Advance syndrome by npar zeroes (for npar 'erased' parity symbols) + var S_pol = new int[npar + 1]; + S_pol[0] = -1; + for (int i = 0; i < npar; i++) + { + if (syndrome[i] == 0) + S_pol[i + 1] = -1; + else + { + var exp = Galois16.instance.LogTbl[syndrome[i]] + npar * i; + S_pol[i + 1] = (exp & max) + (exp >> w); + } + } + var mod_syn = Galois16.instance.gfconv(erasure_loc_pol, S_pol, npar + 1); + + //%Calculate remaining errors (non-erasures) + // + //S_M = []; + //for i = 1:h - num_erasures + // S_M(i) = mod_syn(i + num_erasures + 1); + //end + //flag = 0; + //if isempty(S_M) == 1 + // flag = 0; + //else + // for i = 1:length(S_M) + // if (S_M(i) ~= -Inf) + // flag = 1; %Other errors occured in conjunction with erasures + // end + // end + //end + //%Find error-location polynomial sigma (Berlekamp's iterative algorithm - + //if (flag == 1) + //{ + // ... + //} + //else + //{ + // sigma = 0; + // comp_error_locs = []; + //} + +#if kjsljdf + var sigma = new int[1] { 0 }; + var omega = gfconv(sigma, gfadd(mod_syn, 0), npar + 1); + var tsi = gfconv(sigma, erasure_loc_pol); + var tsi_diff = gfdiff(tsi); + //var e_e_places = [erasures_pos comp_error_locs]; +#else + var omega = mod_syn; + var tsi_diff = erasure_diff; + var e_e_places = erasures_pos; +#endif + + //%Calculate the error magnitudes + //%Substitute the inverse into sigma_diff + //var ERR = new int[e_e_places.Length]; + for (int ii = 0; ii < e_e_places.Length; ii++) + { + var point = max - e_e_places[ii]; + var ERR_DEN = Galois16.instance.gfsubstitute(tsi_diff, point, tsi_diff.Length); + var ERR_NUM = Galois16.instance.gfsubstitute(omega, point, omega.Length); + // Additional +ii because we use slightly different syndrome + var pow = ERR_NUM + e_e_places[ii] + ii + max - ERR_DEN; + + //ERR[ii] = ERR_NUM == -1 ? 0 : expTbl[(pow & max) + (pow >> w)]; + parity[npar - 1 - ii] = ERR_NUM == -1 ? (ushort)0 : Galois16.instance.ExpTbl[(pow & max) + (pow >> w)]; + } + } + } +} diff --git a/CUETools/CUETools.TestCodecs/ALACWriterTest.cs b/CUETools/CUETools.TestCodecs/ALACWriterTest.cs index d5c0e43..4797c2b 100644 --- a/CUETools/CUETools.TestCodecs/ALACWriterTest.cs +++ b/CUETools/CUETools.TestCodecs/ALACWriterTest.cs @@ -97,7 +97,30 @@ namespace CUETools.TestCodecs CollectionAssert.AreEqual(File.ReadAllBytes("alac.m4a"), File.ReadAllBytes("alacwriter0.m4a"), "alacwriter0.m4a doesn't match."); } - } + [TestMethod()] + public void SeekTest() + { + var r = new ALACReader("alac.m4a", null); + var buff1 = new AudioBuffer(r, 16536); + var buff2 = new AudioBuffer(r, 16536); + Assert.AreEqual(0, r.Position); + r.Read(buff1, 7); + Assert.AreEqual(7, r.Position); + r.Position = 0; + Assert.AreEqual(0, r.Position); + r.Read(buff2, 7); + Assert.AreEqual(7, r.Position); + AudioBufferTest.AreEqual(buff1, buff2); + r.Read(buff1, 7); + Assert.AreEqual(7 + 7, r.Position); + r.Position = 7; + Assert.AreEqual(7, r.Position); + r.Read(buff2, 7); + Assert.AreEqual(7 + 7, r.Position); + AudioBufferTest.AreEqual(buff1, buff2); + r.Close(); + } + } } diff --git a/CUETools/CUETools.TestParity/CDRepairDecodeTest.cs b/CUETools/CUETools.TestParity/CDRepairDecodeTest.cs index 7932c4d..7fa9345 100644 --- a/CUETools/CUETools.TestParity/CDRepairDecodeTest.cs +++ b/CUETools/CUETools.TestParity/CDRepairDecodeTest.cs @@ -92,12 +92,14 @@ namespace CUETools.TestParity [TestMethod()] public void CDRepairEncodeWriteTest() { - Assert.AreEqual("jvR9QJ1cSWpqbyP0I0tBrBkQRjCDTDDQkttZGj14ROvsXyg+AnnxVKxL7gwLZbrQmTw5ZPps1Q3744g94qaOOQ==", - Convert.ToBase64String(encode.Parity, 0, 64)); - Assert.AreEqual(377539636, encode.CRC); + Assert.AreEqual("jvR9QJ1cSWpqbyP0I0tBrBkQRjCDTDDQkttZGj14ROvsXyg+AnnxVKxL7gwLZbrQmTw5ZPps1Q3744g94qaOOQ==", + Convert.ToBase64String(encode.AR.GetParity(8), 0, 64)); + //Assert.AreEqual("gwln1GxlYWH/Jn74PreMLv4aFF2glkScSWVFlxMBx94v5D3/3wPx+2guRLquED0s9tOFikPLiSnAv0Xq8aIQ6Q==", + // Convert.ToBase64String(encode.AR.GetParity(16), 0, 64)); + Assert.AreEqual(377539636, encode.CRC); } - /// + /// ///Verifying rip that is accurate /// [TestMethod()] @@ -262,6 +264,7 @@ namespace CUETools.TestParity ///A test for CRC parralelism /// [TestMethod()] + //[Ignore] public void CDRepairSplitTest() { var seed = 723722; @@ -272,10 +275,9 @@ namespace CUETools.TestParity 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); ar1.AR.Combine(ar2.AR, split, (int)ar0.FinalSampleCount); - var offsets = new int[] { 0, -1, 1, -2, 2, -3, 3, -4, 4, -11, 11, -256, 256, -588, 588, 1 - 588 * 5, 588 * 5 - 1 }; - 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); - CollectionAssert.AreEqual(ar0.Parity, ar1.Parity, "Parity was not set correctly, " + message); + CollectionAssert.AreEqual(ar0.Parity, ar1.Parity, "Parity was not set correctly, " + message); } } @@ -300,32 +302,18 @@ namespace CUETools.TestParity public unsafe void CDRepairSyndrome2ParitySpeedTest() { byte[] parityCopy = new byte[encode.Parity.Length]; + var syndrome = encode.Syndrome; for (int t = 0; t < 100; t++) - { - fixed (byte* p = encode.Parity, p1 = parityCopy) - fixed (ushort* syn = encode.Syndrome) - { - ushort* p2 = (ushort*)p1; - for (int i = 0; i < stride; i++) - Galois16.instance.Syndrome2Parity(syn + i * npar, p2 + i * npar, npar); - } - } + ParityToSyndrome.Syndrome2Parity(syndrome, parityCopy); CollectionAssert.AreEqual(encode.Parity, parityCopy); } [TestMethod] public unsafe void CDRepairEncodeSynParTest() { - byte[] parityCopy = new byte[encode.Parity.Length]; - fixed(byte * p = encode.Parity, p1 = parityCopy) - fixed (ushort *syn = encode.Syndrome) - { - ushort* p2 = (ushort*)p1; - for (int i = 0; i < stride; i++) - Galois16.instance.Syndrome2Parity(syn + i * npar, p2 + i * npar, npar); - } - CollectionAssert.AreEqual(encode.Parity, parityCopy); - } + var parityCopy = ParityToSyndrome.Syndrome2Parity(encode.Syndrome); + CollectionAssert.AreEqual(encode.Parity, parityCopy); + } [TestMethod] public void CDRepairEncodeSpeedTest() @@ -350,7 +338,7 @@ namespace CUETools.TestParity ///Verifying rip that has errors /// [TestMethod()] - //[Ignore] + [Ignore] public void CDRepairVerifyParitySpeedTest() { var generator1 = new TestImageGenerator("0 98011", seed, 32 * 588, 0);