diff --git a/CUEControls/CUEControls.csproj b/CUEControls/CUEControls.csproj index 6381bcc..d7ac7bd 100644 --- a/CUEControls/CUEControls.csproj +++ b/CUEControls/CUEControls.csproj @@ -2,7 +2,7 @@ Debug AnyCPU - 8.0.50727 + 9.0.30729 2.0 {CA4D64E6-6544-4A29-8BA5-7DB08D50D072} Library @@ -19,7 +19,7 @@ true full false - bin\Debug\ + ..\bin\Debug\ DEBUG;TRACE prompt 4 diff --git a/CUETools.AccurateRip/AccurateRip.cs b/CUETools.AccurateRip/AccurateRip.cs index 1ddb76b..f254a4a 100644 --- a/CUETools.AccurateRip/AccurateRip.cs +++ b/CUETools.AccurateRip/AccurateRip.cs @@ -11,8 +11,9 @@ namespace CUETools.AccurateRip { public class AccurateRipVerify : IAudioDest { - public AccurateRipVerify(CDImageLayout toc) + public AccurateRipVerify(CDImageLayout toc, IWebProxy proxy) { + this.proxy = proxy; _toc = toc; _accDisks = new List(); _crc32 = new Crc32(); @@ -302,7 +303,7 @@ namespace CUETools.AccurateRip /// /// /// - public unsafe void CalculateCRCs(int* pSampleBuff, int count, int currentOffset, int offs) + public unsafe void CalculateCRCs(uint* pSampleBuff, int count, int currentOffset, int offs) { uint crcar = _CRCAR[_currentTrack, 0]; uint crcsm = _CRCSM[_currentTrack, 0]; @@ -322,7 +323,11 @@ namespace CUETools.AccurateRip _CRCNL[_currentTrack, offs + i] = crcnl; } - uint lo = (uint)*(pSampleBuff++); + uint sample = *(pSampleBuff++); + crcsm += sample; + crcar += sample * (uint)(currentOffset + i + 1); + + uint lo = sample & 0xffff; crc32 = (crc32 >> 8) ^ t[(byte)(crc32 ^ lo)]; crc32 = (crc32 >> 8) ^ t[(byte)(crc32 ^ (lo >> 8))]; if (lo != 0) @@ -332,7 +337,7 @@ namespace CUETools.AccurateRip } else crcnl++; - uint hi = (uint)*(pSampleBuff++); + uint hi = sample >> 16; crc32 = (crc32 >> 8) ^ t[(byte)(crc32 ^ hi)]; crc32 = (crc32 >> 8) ^ t[(byte)(crc32 ^ (hi >> 8))]; if (hi != 0) @@ -341,10 +346,6 @@ namespace CUETools.AccurateRip crcwn = (crcwn >> 8) ^ t[(byte)(crcwn ^ (hi >> 8))]; } else crcnl++; - - uint sampleValue = (lo & 0xffff) + (hi << 16); - crcsm += sampleValue; - crcar += sampleValue * (uint)(currentOffset + i + 1); } } @@ -371,17 +372,17 @@ namespace CUETools.AccurateRip unsafe { - fixed (int* pSampleBuff = &sampleBuffer.Samples[pos, 0]) - //fixed (byte* pByteBuff = &sampleBuffer.Bytes[pos * sampleBuffer.BlockAlign]) + fixed (byte* pSampleBuff = &sampleBuffer.Bytes[pos * 4]) { + uint* samples = (uint*)pSampleBuff; if (currentSector < 10) - CalculateCRCs(pSampleBuff, copyCount, currentOffset, currentOffset); + CalculateCRCs(samples, copyCount, currentOffset, currentOffset); else if (remaingSectors < 10) - CalculateCRCs(pSampleBuff, copyCount, currentOffset, 20 * 588 - (int)_samplesRemTrack); + CalculateCRCs(samples, copyCount, currentOffset, 20 * 588 - (int)_samplesRemTrack); else if (currentSector >= 445 && currentSector <= 455) - CalculateCRCs(pSampleBuff, copyCount, currentOffset, 20 * 588 + currentOffset - 445 * 588); + CalculateCRCs(samples, copyCount, currentOffset, 20 * 588 + currentOffset - 445 * 588); else - CalculateCRCs(pSampleBuff, copyCount, currentOffset, -1); + CalculateCRCs(samples, copyCount, currentOffset, -1); } } pos += copyCount; @@ -442,6 +443,7 @@ namespace CUETools.AccurateRip HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url); req.Method = "GET"; + req.Proxy = proxy; try { @@ -896,6 +898,7 @@ namespace CUETools.AccurateRip private uint[,] _CacheCRCWN; private uint[,] _CacheCRC32; private uint[] _CRCLOG; + private IWebProxy proxy; Crc32 _crc32; diff --git a/CUETools.AccurateRip/CUETools.AccurateRip.csproj b/CUETools.AccurateRip/CUETools.AccurateRip.csproj index 136f158..2dac3ef 100644 --- a/CUETools.AccurateRip/CUETools.AccurateRip.csproj +++ b/CUETools.AccurateRip/CUETools.AccurateRip.csproj @@ -2,7 +2,7 @@ Debug AnyCPU - 8.0.50727 + 9.0.30729 2.0 {5802C7E9-157E-4124-946D-70B5AE48A5A1} Library @@ -19,7 +19,7 @@ true full false - bin\Debug\ + ..\bin\Debug\ DEBUG;TRACE prompt 4 diff --git a/CUETools.CDImage/CUETools.CDImage.csproj b/CUETools.CDImage/CUETools.CDImage.csproj index 8f264c2..684d025 100644 --- a/CUETools.CDImage/CUETools.CDImage.csproj +++ b/CUETools.CDImage/CUETools.CDImage.csproj @@ -2,7 +2,7 @@ Debug AnyCPU - 8.0.50727 + 9.0.30729 2.0 {1DD41038-D885-46C5-8DDE-E0B82F066584} Library @@ -19,7 +19,7 @@ true full false - bin\Debug\ + ..\bin\Debug\ DEBUG;TRACE prompt 4 diff --git a/CUETools.CDRepair/CDRepair.cs b/CUETools.CDRepair/CDRepair.cs index 7fb88b7..cefe1a3 100644 --- a/CUETools.CDRepair/CDRepair.cs +++ b/CUETools.CDRepair/CDRepair.cs @@ -29,7 +29,7 @@ namespace CUETools.CDRepair galois = Galois16.instance; rs = new RsDecode16(npar, galois); crc32 = new Crc32(); - crc = 0xffffffff; + //crc = 0xffffffff; encodeGx = galois.makeEncodeGxLog(npar); laststride = stride + (finalSampleCount * 2) % stride; stridecount = (finalSampleCount * 2) / stride - 2; // minus one for leadin and one for leadout @@ -97,11 +97,19 @@ namespace CUETools.CDRepair get { throw new Exception("unsupported"); } } + public int NPAR + { + get + { + return npar; + } + } + public uint CRC { get { - return crc ^ 0xffffffff; + return crc32.Combine(0xffffffff, crc, stride * 2 * stridecount) ^ 0xffffffff; } } } @@ -113,19 +121,14 @@ namespace CUETools.CDRepair protected ushort[] leadin; protected ushort[] leadout; protected bool verify; - protected bool hasErrors = false, canRecover = true; - protected int actualOffset = 0; + protected bool encode; + protected uint crcA, crcB; - internal int[,] sigma; - internal int[,] omega; - internal int[,] errpos; - internal int[,] erroff; - internal int[] errors; - - public CDRepairEncode(int finalSampleCount, int stride, int npar, bool verify) + public CDRepairEncode(int finalSampleCount, int stride, int npar, bool verify, bool encode) : base (finalSampleCount, stride, npar) { this.verify = verify; + this.encode = encode; parity = new byte[stride * npar * 2]; if (verify) { @@ -136,45 +139,64 @@ namespace CUETools.CDRepair syndrome = new ushort[1, npar]; } - new public unsafe void Write(AudioBuffer sampleBuffer) + private unsafe void ProcessStride(int currentStride, int currentPart, int count, ushort* data) { - sampleBuffer.Prepare(this); - - if ((sampleBuffer.ByteLength & 1) != 0) - throw new Exception("never happens"); - - int firstPos = Math.Max(0, stride - sampleCount * 2); - int lastPos = Math.Min(sampleBuffer.ByteLength >> 1, (finalSampleCount - sampleCount) * 2 - laststride); - - fixed (byte* bytes = sampleBuffer.Bytes, par = parity) - fixed (int* gx = encodeGx) - fixed (uint* t = crc32.table) + fixed (uint* crct = crc32.table) + fixed (byte* bpar = parity) fixed (ushort* exp = galois.ExpTbl, log = galois.LogTbl, synptr = syndrome) - { - ushort* data = (ushort*)bytes; + 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]; - if (verify) - for (int pos = 0; pos < (sampleBuffer.ByteLength >> 1); pos++) + crc = (crc >> 8) ^ crct[(byte)(crc ^ dd)]; + crc = (crc >> 8) ^ crct[(byte)(crc ^ (dd >> 8))]; + + if (verify) { - ushort dd = data[pos]; - if (sampleCount * 2 + pos < 2 * stride) - leadin[sampleCount * 2 + pos] = dd; - int remaining = (finalSampleCount - sampleCount) * 2 - pos - 1; - if (remaining < stride + laststride) - leadout[remaining] = dd; + 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 } - if (npar == 8) - { - for (int pos = firstPos; pos < lastPos; pos++) + int ib = wr[0] ^ dd; + if (ib != 0) { - int part = (sampleCount * 2 + pos) % stride; - ushort* wr = ((ushort*)par) + part * 8; - ushort dd = data[pos]; + 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; + } + } + } - crc = (crc >> 8) ^ t[(byte)(crc ^ dd)]; - crc = (crc >> 8) ^ t[(byte)(crc ^ (dd >> 8))]; + private unsafe void ProcessStride8(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 * 8; + ushort dd = data[pos]; + crc = (crc >> 8) ^ crct[(byte)(crc ^ dd)]; + crc = (crc >> 8) ^ crct[(byte)(crc ^ (dd >> 8))]; + + if (encode) + { int ib = wr[0] ^ dd; if (ib != 0) { @@ -199,161 +221,299 @@ namespace CUETools.CDRepair wr[6] = wr[7]; wr[7] = 0; } + } - // syn[i] += data[pos] * α^(pos*i) - if (verify && dd != 0) - { - ushort* syn = synptr + part * 8; - ushort* myexp = exp + log[dd]; - int offs = stridecount - (sampleCount * 2 + pos) / stride; - syn[0] ^= dd; - syn[1] ^= myexp[offs]; - syn[2] ^= myexp[(offs * 2) % 65535]; - syn[3] ^= myexp[(offs * 3) % 65535]; - syn[4] ^= myexp[(offs * 4) % 65535]; - syn[5] ^= myexp[(offs * 5) % 65535]; - syn[6] ^= myexp[(offs * 6) % 65535]; - syn[7] ^= myexp[(offs * 7) % 65535]; - //ushort logdd = log[dd]; - //syn[1] ^= exp[(logdd + offs) % 65535]; - //syn[2] ^= exp[(logdd + offs * 2) % 65535]; - //syn[3] ^= exp[(logdd + offs * 3) % 65535]; - //syn[4] ^= exp[(logdd + offs * 4) % 65535]; - //syn[5] ^= exp[(logdd + offs * 5) % 65535]; - //syn[6] ^= exp[(logdd + offs * 6) % 65535]; - //syn[7] ^= exp[(logdd + offs * 7) % 65535]; - } + // syn[i] += data[pos] * α^(n*i) + if (verify && dd != 0) + { + int n = stridecount - currentStride; + ushort* syn = synptr + part * 8; + 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)]; } } - else + } + + 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++) { - for (int pos = firstPos; pos < lastPos; 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) { - int part = (sampleCount * 2 + pos) % stride; - ushort* wr = ((ushort*)par) + part * npar; - ushort dd = data[pos]; - - crc = (crc >> 8) ^ t[(byte)(crc ^ dd)]; - crc = (crc >> 8) ^ t[(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; - } + 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) + { + sampleBuffer.Prepare(this); + + if ((sampleBuffer.ByteLength & 1) != 0) + throw new Exception("never happens"); + + 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 (verify) + { + // remember CRC after leadin + if (sampleCount * 2 == stride * 2) + crcA = crc; + + // remember CRC before leadout + if ((finalSampleCount - sampleCount) * 2 == stride + laststride) + crcB = crc; + + 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 == 8) + ProcessStride8(currentStride, currentPart, copyCount, data); + else if (npar == 16) + ProcessStride16(currentStride, currentPart, copyCount, data); + else + ProcessStride(currentStride, currentPart, copyCount, data); + } + + sampleCount += copyCount >> 1; + offs += copyCount >> 1; } } - sampleCount += sampleBuffer.Length; } - public unsafe bool VerifyParity(byte[] parity2) + public unsafe CDRepairFix VerifyParity(byte[] parity2, int actualOffset) { - return VerifyParity(parity2, 0, parity2.Length); + return VerifyParity(npar, parity2, 0, parity2.Length, actualOffset); } - public unsafe bool VerifyParity(byte[] parity2, int pos, int len) + private unsafe uint OffsettedCRC(int actualOffset) { + fixed (uint* crct = crc32.table) + { + // calculate leadin CRC + uint crc0 = 0; + for (int off = stride - 2 * actualOffset; off < 2 * stride; off++) + { + ushort dd = leadin[off]; + crc0 = (crc0 >> 8) ^ crct[(byte)(crc0 ^ dd)]; + crc0 = (crc0 >> 8) ^ crct[(byte)(crc0 ^ (dd >> 8))]; + } + // calculate leadout CRC + uint crc2 = 0; + for (int off = laststride + stride - 1; off >= laststride + 2 * actualOffset; off--) + { + ushort dd = leadout[off]; + crc2 = (crc2 >> 8) ^ crct[(byte)(crc2 ^ dd)]; + crc2 = (crc2 >> 8) ^ crct[(byte)(crc2 ^ (dd >> 8))]; + } + + // calculate middle CRC + uint crc1 = crc32.Combine(crcA, crcB, (stridecount - 2) * stride * 2); + // calculate offsettedCRC as sum of 0xffffffff, crc0, crc1, crc2; + return crc32.Combine( + 0xffffffff, + crc32.Combine( + crc32.Combine( + crc0, + crc1, + (stridecount - 2) * stride * 2), + crc2, + (stride - 2 * actualOffset) * 2), + stridecount * stride * 2) ^ 0xffffffff; + } + } + + public unsafe bool FindOffset(int npar2, byte[] parity2, int pos, uint expectedCRC, out int actualOffset, out bool hasErrors) + { + if (npar2 != npar) + throw new Exception("npar mismatch"); if (!verify) throw new Exception("verify was not enabled"); if (sampleCount != finalSampleCount) throw new Exception("sampleCount != finalSampleCount"); - if (len != stride * npar * 2) - throw new Exception("wrong size"); - - sigma = new int[stride, npar / 2 + 2]; - omega = new int[stride, npar / 2 + 1]; - errpos = new int[stride, npar / 2]; - erroff = new int[stride, npar / 2]; - errors = new int[stride]; - - actualOffset = 0; // find offset fixed (byte* par2ptr = &parity2[pos]) { ushort* par2 = (ushort*)par2ptr; - int* syn = stackalloc int[npar]; int* _sigma = stackalloc int[npar]; - int* _omega = stackalloc int[npar]; int* _errpos = stackalloc int[npar]; - int bestErrors = npar; + bool foundOffset = false; - // We can only use offset if Abs(offset * 2) < stride, - // else we might need to add/remove more than one sample - // from syndrome calculations, and that would be too difficult - // and will probably require longer leadin/leadout. - for (int offset = 1 - stride / 2; offset < stride / 2; offset++) + for (int allowed_errors = 0; allowed_errors < npar / 2 && !foundOffset; allowed_errors++) { - int err = 0; + int part2 = 0; + ushort* wr = par2 + part2 * npar; - for (int i = 0; i < npar; i++) + // We can only use offset if Abs(offset * 2) < stride, + // else we might need to add/remove more than one sample + // from syndrome calculations, and that would be too difficult + // and will probably require longer leadin/leadout. + for (int offset = 1 - stride / 2; offset < stride / 2; offset++) { - int part = (stride - 1) % stride; - int part2 = (part + offset * 2 + stride) % stride; - ushort* wr = par2 + part2 * npar; + int err = 0; + int part = (part2 + stride - offset * 2) % stride; + int* syn = stackalloc int[npar]; - syn[i] = syndrome[part, i]; - - // offset < 0 - if (part < -offset * 2) + for (int i = 0; i < npar; i++) { - syn[i] ^= galois.mulExp(leadin[stride + part], (i * (stridecount - 1)) % galois.Max); - syn[i] = leadout[laststride - part - 1] ^ galois.mulExp(syn[i], i); - } - // offset > 0 - if (part >= stride - offset * 2) - { - syn[i] = galois.divExp(syn[i] ^ leadout[laststride + stride - part - 1], i); - syn[i] ^= galois.mulExp(leadin[part], (i * (stridecount - 1)) % galois.Max); - } + int synI = syndrome[part, i]; - for (int j = 0; j < npar; j++) - syn[i] = wr[j] ^ galois.mulExp(syn[i], i); + // offset < 0 + if (part < -offset * 2) + { + synI ^= galois.mulExp(leadin[stride + part], (i * (stridecount - 1)) % galois.Max); + synI = leadout[laststride - part - 1] ^ galois.mulExp(synI, i); + } + // offset > 0 + if (part >= stride - offset * 2) + { + synI = galois.divExp(synI ^ leadout[laststride + stride - part - 1], i); + synI ^= galois.mulExp(leadin[part], (i * (stridecount - 1)) % galois.Max); + } - err |= syn[i]; - } - if (err == 0) - { - actualOffset = offset; - bestErrors = 0; - break; - } - int err_count = rs.calcSigmaMBM(_sigma, _omega, syn); - if (err_count > 0 && rs.chienSearch(_errpos, stridecount + npar, err_count, _sigma)) - { - if (err_count < bestErrors) + for (int j = 0; j < npar; j++) + synI = wr[j] ^ galois.mulExp(synI, i); + + syn[i] = synI; + err |= synI; + } + int err_count = err == 0 ? 0 : rs.calcSigmaMBM(_sigma, syn); + if (err_count == allowed_errors && (err_count == 0 || rs.chienSearch(_errpos, stridecount + npar, err_count, _sigma))) { actualOffset = offset; - bestErrors = err_count; + hasErrors = err_count != 0 || OffsettedCRC(offset) != expectedCRC; + return true; } } } } + actualOffset = 0; + hasErrors = true; + return false; + } + + public unsafe CDRepairFix VerifyParity(int npar2, byte[] parity2, int pos, int len, int actualOffset) + { + if (len != stride * npar * 2) + throw new Exception("wrong size"); + + CDRepairFix fix = new CDRepairFix(this); + fix.actualOffset = actualOffset; + fix.correctableErrors = 0; + fix.hasErrors = false; + fix.canRecover = true; + + fix.sigma = new int[stride, npar / 2 + 2]; + fix.omega = new int[stride, npar / 2 + 1]; + fix.errpos = new int[stride, npar / 2]; + fix.erroff = new int[stride, npar / 2]; + fix.errors = new int[stride]; - hasErrors = false; fixed (byte* par = &parity2[pos]) fixed (ushort* exp = galois.ExpTbl, log = galois.LogTbl) { int* syn = stackalloc int[npar]; - int offset = actualOffset; + int offset = fix.actualOffset; for (int part = 0; part < stride; part++) { @@ -400,25 +560,27 @@ namespace CUETools.CDRepair if (err != 0) { - hasErrors = true; - fixed (int* s = &sigma[part, 0], o = &omega[part, 0], e = &errpos[part, 0], f = &erroff[part, 0]) + fixed (int* s = &fix.sigma[part, 0], o = &fix.omega[part, 0], e = &fix.errpos[part, 0], f = &fix.erroff[part, 0]) { - errors[part] = rs.calcSigmaMBM(s, o, syn); - if (errors[part] <= 0 || !rs.chienSearch(e, stridecount + npar, errors[part], s)) - canRecover = false; + fix.errors[part] = rs.calcSigmaMBM(s, syn); + fix.hasErrors = true; + fix.correctableErrors += fix.errors[part]; + if (fix.errors[part] <= 0 || !rs.chienSearch(e, stridecount + npar, fix.errors[part], s)) + fix.canRecover = false; else { - for (int i = 0; i < errors[part]; i++) + galois.mulPoly(o, s, syn, npar / 2 + 1, npar, npar); + for (int i = 0; i < fix.errors[part]; i++) f[i] = galois.toPos(stridecount + npar, e[i]); } } } else - errors[part] = 0; + fix.errors[part] = 0; } } - return !hasErrors; + return fix; } public byte[] Parity @@ -428,6 +590,55 @@ namespace CUETools.CDRepair return parity; } } + } + + public class CDRepairFix : CDRepair + { + internal bool hasErrors = false, canRecover = true; + internal int actualOffset = 0; + internal int correctableErrors = 0; + internal int[,] sigma; + internal int[,] omega; + internal int[,] errpos; + internal int[,] erroff; + internal int[] errors; + + public CDRepairFix(CDRepairEncode decode) + : base(decode) + { + } + + new public unsafe void Write(AudioBuffer sampleBuffer) + { + sampleBuffer.Prepare(this); + + if ((sampleBuffer.ByteLength & 1) != 0) + throw new Exception("never happens"); + + int firstPos = Math.Max(0, stride - sampleCount * 2 - ActualOffset * 2); + int lastPos = Math.Min(sampleBuffer.ByteLength >> 1, (finalSampleCount - sampleCount) * 2 - laststride - ActualOffset * 2); + + fixed (byte* bytes = sampleBuffer.Bytes) + fixed (uint* t = crc32.table) + { + ushort* data = (ushort*)bytes; + for (int pos = firstPos; pos < lastPos; pos++) + { + int part = (sampleCount * 2 + pos) % stride; + int nerrors = errors[part]; + fixed (int* s = &sigma[part, 0], o = &omega[part, 0], f = &erroff[part, 0]) + for (int i = 0; i < nerrors; i++) + if (f[i] == (sampleCount * 2 + ActualOffset * 2 + pos) / stride - 1) + data[pos] ^= (ushort)rs.doForney(nerrors, errpos[part, i], s, o); + + ushort dd = data[pos]; + + crc = (crc >> 8) ^ t[(byte)(crc ^ dd)]; + crc = (crc >> 8) ^ t[(byte)(crc ^ (dd >> 8))]; + } + } + sampleCount += sampleBuffer.Length; + } public bool HasErrors { @@ -445,6 +656,14 @@ namespace CUETools.CDRepair } } + public int CorrectableErrors + { + get + { + return correctableErrors; + } + } + public int ActualOffset { get @@ -453,47 +672,4 @@ namespace CUETools.CDRepair } } } - - public class CDRepairFix : CDRepair - { - CDRepairEncode decode; - - public CDRepairFix(CDRepairEncode decode) - : base(decode) - { - this.decode = decode; - } - - new public unsafe void Write(AudioBuffer sampleBuffer) - { - sampleBuffer.Prepare(this); - - if ((sampleBuffer.ByteLength & 1) != 0) - throw new Exception("never happens"); - - int firstPos = Math.Max(0, stride - sampleCount * 2 - decode.ActualOffset * 2); - int lastPos = Math.Min(sampleBuffer.ByteLength >> 1, (finalSampleCount - sampleCount) * 2 - laststride - decode.ActualOffset * 2); - - fixed (byte* bytes = sampleBuffer.Bytes) - fixed (uint* t = crc32.table) - { - ushort* data = (ushort*)bytes; - for (int pos = firstPos; pos < lastPos; pos++) - { - int part = (sampleCount * 2 + pos) % stride; - int errors = decode.errors[part]; - fixed (int* s = &decode.sigma[part, 0], o = &decode.omega[part, 0], f = &decode.erroff[part, 0]) - for (int i = 0; i < errors; i++) - if (f[i] == (sampleCount * 2 + decode.ActualOffset * 2 + pos) / stride - 1) - data[pos] ^= (ushort)rs.doForney(errors, decode.errpos[part, i], s, o); - - ushort dd = data[pos]; - - crc = (crc >> 8) ^ t[(byte)(crc ^ dd)]; - crc = (crc >> 8) ^ t[(byte)(crc ^ (dd >> 8))]; - } - } - sampleCount += sampleBuffer.Length; - } - } } diff --git a/CUETools.CTDB/CUETools.CTDB.csproj b/CUETools.CTDB/CUETools.CTDB.csproj index 36e0677..adcce97 100644 --- a/CUETools.CTDB/CUETools.CTDB.csproj +++ b/CUETools.CTDB/CUETools.CTDB.csproj @@ -34,6 +34,7 @@ + diff --git a/CUETools.CTDB/CUEToolsDB.cs b/CUETools.CTDB/CUEToolsDB.cs index 0fadd90..50ea9ba 100644 --- a/CUETools.CTDB/CUEToolsDB.cs +++ b/CUETools.CTDB/CUEToolsDB.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Collections.Specialized; using System.Globalization; using System.IO; +using System.Management; using System.Net; using System.Text; using CUETools.CDImage; @@ -17,17 +18,22 @@ namespace CUETools.CTDB private CDImageLayout toc; private HttpStatusCode accResult; private string id; + private string subResult; private byte[] contents; private int pos; private int length; - private int confidence; private int total; List entries = new List(); + DBEntry selectedEntry; + IWebProxy proxy; + HttpUploadHelper uploadHelper; - public CUEToolsDB(CDImageLayout toc) + public CUEToolsDB(CDImageLayout toc, IWebProxy proxy) { this.toc = toc; this.length = (int)toc.AudioLength * 588; + this.proxy = proxy; + this.uploadHelper = new HttpUploadHelper(); } public void ContactDB(string id) @@ -51,7 +57,7 @@ namespace CUETools.CTDB HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url); req.Method = "GET"; - req.Proxy = WebRequest.GetSystemWebProxy(); + req.Proxy = proxy; try { @@ -76,6 +82,8 @@ namespace CUETools.CTDB } } Parse(); + if (entries.Count == 0) + accResult = HttpStatusCode.NoContent; } catch (WebException ex) { @@ -86,22 +94,23 @@ namespace CUETools.CTDB } } - /// - /// Database entry format: - /// 'CTDB' version(0x00000100) size - /// 'HEAD' version(0x00000100) size disc-count total-submissions - /// 'DISC' version(0x00000100) size - /// 'TOC ' version(0x00000100) size track-count preGap - /// 'TRAK' ersion(0x00000100) size flags(1==isAudio) length(frames) - /// .... track-count - /// 'ARDB' version(0x00000100) size pressings-count - /// 'ARCD' version(0x00000100) size CRC1 ... CRCN - /// .... pressings-count - /// 'PAR8' version(0x00000100) size parity-data - /// 'CONF' version(0x00000100) size confidence - /// 'CRC ' version(0x00000100) size CRC32 min-offset max-offset ... - /// .... disc-count - /// + static string cpuInfo = null; + + public static string GetCPUID() + { + if (cpuInfo == null) + { + ManagementClass mc = new ManagementClass("win32_processor"); + foreach (ManagementObject mo in mc.GetInstances()) + { + //Get only the first CPU's ID + cpuInfo = mo.Properties["processorID"].Value.ToString(); + break; + } + } + return cpuInfo ?? "unknown"; + } + public string Submit(int confidence, int total) { if (id == null) @@ -120,75 +129,72 @@ namespace CUETools.CTDB UploadFile[] files = new UploadFile[1]; MemoryStream newcontents = new MemoryStream(); - using (DBHDR CTDB = new DBHDR(newcontents, "CTDB", 0x100)) + using (DBHDR FTYP = new DBHDR(newcontents, "ftyp")) + FTYP.Write("CTDB"); + using (DBHDR CTDB = new DBHDR(newcontents, "CTDB")) { - using (DBHDR HEAD = new DBHDR(newcontents, "HEAD", 0x100)) + using (DBHDR HEAD = CTDB.HDR("HEAD")) { - DBHDR.WriteInt(newcontents, 1); // disc count - DBHDR.WriteInt(newcontents, total); + HEAD.Write(0x100); // version + HEAD.Write(1); // disc count + HEAD.Write(total); // total submissions + HEAD.Write(DateTime.Now); // date } - using (DBHDR DISC = new DBHDR(newcontents, "DISC", 0x100)) + using (DBHDR DISC = CTDB.HDR("DISC")) { - using (DBHDR TOC = new DBHDR(newcontents, "TOC ", 0x100)) + using (DBHDR TOC = DISC.HDR("TOC ")) { - DBHDR.WriteInt(newcontents, toc.TrackCount); - DBHDR.WriteInt(newcontents, toc.Pregap); + using (DBHDR INFO = TOC.HDR("INFO")) + { + INFO.Write(toc.TrackCount); + INFO.Write(toc.Pregap); + } for (int i = 1; i <= toc.TrackCount; i++) - using (DBHDR TRAK = new DBHDR(newcontents, "TRAK", 0x100)) + using (DBHDR TRAK = TOC.HDR("TRAK")) { - DBHDR.WriteInt(newcontents, toc[i].IsAudio ? 1 : 0); - DBHDR.WriteInt(newcontents, toc[i].Length); + TRAK.Write(toc[i].IsAudio ? 1 : 0); + TRAK.Write(toc[i].Length); } } - using (DBHDR PAR8 = new DBHDR(newcontents, "CONF", 0x100)) - { - DBHDR.WriteInt(newcontents, confidence); - } - using (DBHDR PAR8 = new DBHDR(newcontents, "CRC ", 0x100)) - { - DBHDR.WriteInt(newcontents, verify.CRC); - } - using (DBHDR PAR8 = new DBHDR(newcontents, "PAR8", 0x100)) - { - newcontents.Write(verify.Parity, 0, verify.Parity.Length); - } + using (DBHDR USER = DISC.HDR("USER")) USER.Write(GetCPUID()); + using (DBHDR TOOL = DISC.HDR("TOOL")) TOOL.Write("CUETools 205"); + using (DBHDR DATE = DISC.HDR("DATE")) DATE.Write(DateTime.Now); + using (DBHDR CONF = DISC.HDR("CONF")) CONF.Write(confidence); + using (DBHDR NPAR = DISC.HDR("NPAR")) NPAR.Write(verify.NPAR); + using (DBHDR CRC_ = DISC.HDR("CRC ")) CRC_.Write(verify.CRC); + using (DBHDR PAR_ = DISC.HDR("PAR ")) PAR_.Write(verify.Parity); } } newcontents.Position = 0; files[0] = new UploadFile(newcontents, "uploadedfile", "data.bin", "image/binary"); HttpWebRequest req = (HttpWebRequest)WebRequest.Create("http://db.cuetools.net/uploader.php"); - req.Proxy = WebRequest.GetSystemWebProxy(); + req.Proxy = proxy; + req.UserAgent = "CUETools 205"; NameValueCollection form = new NameValueCollection(); form.Add("id", String.Format("{0:d3}-{1:x8}-{2:x8}-{3:x8}", toc.AudioTracks, discId1, discId2, cddbDiscId)); - HttpWebResponse resp = HttpUploadHelper.Upload(req, files, form); - string errtext; + HttpWebResponse resp = uploadHelper.Upload(req, files, form); using (Stream s = resp.GetResponseStream()) using (StreamReader sr = new StreamReader(s)) - { - errtext = sr.ReadToEnd(); - } - return errtext; + subResult = sr.ReadToEnd(); + return subResult; } private string ReadHDR(out int end) { + int size = ReadInt(); string res = Encoding.ASCII.GetString(contents, pos, 4); pos += 4; - int version = ReadInt(); - if (version >= 0x200) - throw new Exception("unsupported CTDB version"); - int size = ReadInt(); - end = pos + size; + end = pos + size - 8; return res; } private int ReadInt() { int value = - (contents[pos] + - (contents[pos + 1] << 8) + - (contents[pos + 2] << 16) + - (contents[pos + 3] << 24)); + (contents[pos + 3] + + (contents[pos + 2] << 8) + + (contents[pos + 1] << 16) + + (contents[pos + 0] << 24)); pos += 4; return value; } @@ -196,10 +202,10 @@ namespace CUETools.CTDB private uint ReadUInt() { uint value = - ((uint)contents[pos] + - ((uint)contents[pos + 1] << 8) + - ((uint)contents[pos + 2] << 16) + - ((uint)contents[pos + 3] << 24)); + ((uint)contents[pos + 3] + + ((uint)contents[pos + 2] << 8) + + ((uint)contents[pos + 1] << 16) + + ((uint)contents[pos + 0] << 24)); pos += 4; return value; } @@ -212,12 +218,21 @@ namespace CUETools.CTDB pos = 0; int end; string hdr = ReadHDR(out end); - if (hdr != "CTDB") throw new Exception("invalid CTDB file"); - if (end != contents.Length) throw new Exception("incomplete CTDB file"); + uint magic = ReadUInt(); + if (hdr != "ftyp" || magic != 0x43544442 || end != pos) + throw new Exception("invalid CTDB file"); hdr = ReadHDR(out end); - if (hdr != "HEAD") throw new Exception("invalid CTDB file"); + if (hdr != "CTDB" || end != contents.Length) + throw new Exception("invalid CTDB file"); + hdr = ReadHDR(out end); + if (hdr != "HEAD") + throw new Exception("invalid CTDB file"); + uint version = ReadUInt(); int discCount = ReadInt(); total = ReadInt(); + if (discCount <= 0 || version >= 0x200) + throw new Exception("invalid CTDB file"); + // date pos = end; while (pos < contents.Length) { @@ -229,11 +244,11 @@ namespace CUETools.CTDB } int endDisc = end; uint crc = 0; - int parPos = 0, parLen = 0, conf = 0; + int parPos = 0, parLen = 0, conf = 0, npar = 0; while (pos < endDisc) { hdr = ReadHDR(out end); - if (hdr == "PAR8") + if (hdr == "PAR ") { parPos = pos; parLen = end - pos; @@ -242,10 +257,13 @@ namespace CUETools.CTDB crc = ReadUInt(); else if (hdr == "CONF") conf = ReadInt(); + else if (hdr == "NPAR") + npar = ReadInt(); pos = end; } - if (parPos != 0) - entries.Add(new DBEntry(parPos, parLen, conf, crc)); + if (parPos != 0 && npar >= 2 && npar <= 16 && conf >= 0) + //if (parPos != 0 && npar >= 2 && npar <= 16 && conf != 0) + entries.Add(new DBEntry(parPos, parLen, conf, npar, crc)); } } @@ -253,16 +271,22 @@ namespace CUETools.CTDB { foreach (DBEntry entry in entries) { - verify.VerifyParity(contents, entry.pos, entry.len); - if (!verify.HasErrors || verify.CanRecover) - confidence = entry.conf; - break; + if (!verify.FindOffset(entry.npar, contents, entry.pos, entry.crc, out entry.offset, out entry.hasErrors)) + entry.canRecover = false; + else if (entry.hasErrors) + { + entry.repair = verify.VerifyParity(entry.npar, contents, entry.pos, entry.len, entry.offset); + entry.canRecover = entry.repair.CanRecover; + } } } - public void Init() + public void Init(bool encode) { - verify = new CDRepairEncode(length, 10 * 588 * 2, 8, accResult == HttpStatusCode.OK); + int npar = 8; + foreach (DBEntry entry in entries) + npar = Math.Max(npar, entry.npar); + verify = new CDRepairEncode(length, 10 * 588 * 2, npar, entries.Count > 0, encode); } public int Total @@ -299,35 +323,95 @@ namespace CUETools.CTDB } } + public DBEntry SelectedEntry + { + set + { + selectedEntry = value; + } + get + { + return selectedEntry; + } + } + public string Status { get { //sw.WriteLine("CUETools DB CRC: {0:x8}", Verify.CRC); + string res = null; if (DBStatus != null) - return DBStatus; - if (!verify.HasErrors) - return string.Format("verified OK, confidence {0}/{1}", confidence, total); - if (verify.CanRecover) - return string.Format("contains correctable errors, confidence {0}/{1}", confidence, total); - return "could not be verified"; + res = DBStatus; + else + { + DBEntry popular = null; + foreach (DBEntry entry in entries) + if (!entry.hasErrors || entry.canRecover) + if (popular == null || entry.conf > popular.conf) + popular = entry; + if (popular != null) + res = popular.Status; + foreach (DBEntry entry in entries) + if (entry != popular && (!entry.hasErrors || entry.canRecover)) + res += ", or " + entry.Status; + if (res == null) + res = "could not be verified"; + } + if (subResult != null) + res += ", " + subResult; + return res; + } + } + + public IEnumerable Entries + { + get + { + return entries; + } + } + + public HttpUploadHelper UploadHelper + { + get + { + return uploadHelper; } } } - internal class DBEntry + public class DBEntry { public int pos; public int len; public int conf; + public int npar; + public int offset; public uint crc; + public bool hasErrors; + public bool canRecover; + public CDRepairFix repair; - public DBEntry(int pos, int len, int conf, uint crc) + public DBEntry(int pos, int len, int conf, int npar, uint crc) { this.pos = pos; this.len = len; this.conf = conf; this.crc = crc; + this.npar = npar; + } + + public string Status + { + get + { + if (!hasErrors) + return string.Format("verified OK, confidence {0}", conf); + if (canRecover) + return string.Format("contains {1} correctable errors, confidence {0}", conf, repair.CorrectableErrors); + return "could not be verified"; + } } } @@ -336,41 +420,74 @@ namespace CUETools.CTDB private long lenOffs; private MemoryStream stream; - public DBHDR(MemoryStream stream, string name, int version) + public DBHDR(MemoryStream stream, string name) { this.stream = stream; - stream.Write(Encoding.ASCII.GetBytes(name), 0, 4); - WriteInt(stream, version); lenOffs = stream.Position; - WriteInt(stream, 0); + Write(0); + Write(name); } public void Dispose() { long fin = stream.Position; stream.Position = lenOffs; - WriteInt(stream, (int)(fin - lenOffs - 4)); + Write((int)(fin - lenOffs)); stream.Position = fin; } - public static void WriteInt(MemoryStream stream, int value) + public void Write(int value) { byte[] temp = new byte[4]; - temp[0] = (byte)(value & 0xff); - temp[1] = (byte)((value >> 8) & 0xff); - temp[2] = (byte)((value >> 16) & 0xff); - temp[3] = (byte)((value >> 24) & 0xff); - stream.Write(temp, 0, 4); + temp[3] = (byte)(value & 0xff); + temp[2] = (byte)((value >> 8) & 0xff); + temp[1] = (byte)((value >> 16) & 0xff); + temp[0] = (byte)((value >> 24) & 0xff); + Write(temp); } - public static void WriteInt(MemoryStream stream, uint value) + public void Write(uint value) { byte[] temp = new byte[4]; - temp[0] = (byte)(value & 0xff); - temp[1] = (byte)((value >> 8) & 0xff); - temp[2] = (byte)((value >> 16) & 0xff); - temp[3] = (byte)((value >> 24) & 0xff); - stream.Write(temp, 0, 4); + temp[3] = (byte)(value & 0xff); + temp[2] = (byte)((value >> 8) & 0xff); + temp[1] = (byte)((value >> 16) & 0xff); + temp[0] = (byte)((value >> 24) & 0xff); + Write(temp); + } + + public void Write(long value) + { + byte[] temp = new byte[8]; + temp[7] = (byte)((value) & 0xff); + temp[6] = (byte)((value >> 8) & 0xff); + temp[5] = (byte)((value >> 16) & 0xff); + temp[4] = (byte)((value >> 24) & 0xff); + temp[3] = (byte)((value >> 32) & 0xff); + temp[2] = (byte)((value >> 40) & 0xff); + temp[1] = (byte)((value >> 48) & 0xff); + temp[0] = (byte)((value >> 56) & 0xff); + Write(temp); + } + + public void Write(string value) + { + Write(Encoding.UTF8.GetBytes(value)); + } + + public void Write(DateTime value) + { + Write(value.ToFileTimeUtc()); + } + + public void Write(byte[] value) + { + stream.Write(value, 0, value.Length); + } + + public DBHDR HDR(string name) + { + return new DBHDR(stream, name); } } } diff --git a/CUETools.CTDB/UploadHelper/HttpUploadHelper.cs b/CUETools.CTDB/UploadHelper/HttpUploadHelper.cs index aa950e7..49e85cf 100644 --- a/CUETools.CTDB/UploadHelper/HttpUploadHelper.cs +++ b/CUETools.CTDB/UploadHelper/HttpUploadHelper.cs @@ -15,10 +15,12 @@ namespace Krystalware.UploadHelper { public class HttpUploadHelper { - private HttpUploadHelper() + public EventHandler onProgress; + + public HttpUploadHelper() { } - public static string Upload(string url, UploadFile[] files, NameValueCollection form) + public string Upload(string url, UploadFile[] files, NameValueCollection form) { HttpWebResponse resp = Upload((HttpWebRequest)WebRequest.Create(url), files, form); @@ -29,7 +31,7 @@ namespace Krystalware.UploadHelper } } - public static HttpWebResponse Upload(HttpWebRequest req, UploadFile[] files, NameValueCollection form) + public HttpWebResponse Upload(HttpWebRequest req, UploadFile[] files, NameValueCollection form) { List mimeParts = new List(); @@ -84,16 +86,25 @@ namespace Krystalware.UploadHelper using (Stream s = req.GetRequestStream()) { + long pos = 0; foreach (MimePart part in mimeParts) { s.Write(part.Header, 0, part.Header.Length); + pos += part.Header.Length; - while ((read = part.Data.Read(buffer, 0, buffer.Length)) > 0) - s.Write(buffer, 0, read); + while ((read = part.Data.Read(buffer, 0, buffer.Length)) > 0) + { + if (onProgress != null) + onProgress(part, + new UploadProgressEventArgs(req.RequestUri.AbsoluteUri, ((double)pos)/contentLength)); + s.Write(buffer, 0, read); + pos += read; + } part.Data.Dispose(); s.Write(afterFile, 0, afterFile.Length); + pos += afterFile.Length; } s.Write(_footer, 0, _footer.Length); @@ -111,4 +122,16 @@ namespace Krystalware.UploadHelper } } } + + public class UploadProgressEventArgs: EventArgs + { + public string uri; + public double percent; + + public UploadProgressEventArgs(string uri, double percent) + { + this.uri = uri; + this.percent = percent; + } + } } \ No newline at end of file diff --git a/CUETools.CTDB/UploadHelper/uploader.php b/CUETools.CTDB/UploadHelper/uploader.php index d480d00..57122fb 100644 --- a/CUETools.CTDB/UploadHelper/uploader.php +++ b/CUETools.CTDB/UploadHelper/uploader.php @@ -43,6 +43,61 @@ function filesize_h($size, $dec = 1) return round($size, $dec) . ' ' . $sizes[$i]; } +function BigEndian2Int($byte_word, $signed = false) { + + $int_value = 0; + $byte_wordlen = strlen($byte_word); + + for ($i = 0; $i < $byte_wordlen; $i++) { + $int_value += ord($byte_word{$i}) * pow(256, ($byte_wordlen - 1 - $i)); + } + + if ($signed) { + $sign_mask_bit = 0x80 << (8 * ($byte_wordlen - 1)); + if ($int_value & $sign_mask_bit) { + $int_value = 0 - ($int_value & ($sign_mask_bit - 1)); + } + } + + return $int_value; +} + +function get_chunk_offset($fp, $offset, $filelen, $names, $namepos) +{ +// echo $offset, ":", $filelen, ":", $names, ":", $namepos, ":", count($names), "
"; + if ($namepos >= count($names)) + return $offset; + while ($offset < $filelen) { + fseek($fp, $offset, SEEK_SET); + $atom_header = fread($fp, 8); + $atom_size = BigEndian2Int(substr($atom_header, 0, 4)); + $atom_name = substr($atom_header, 4, 4); +// echo $atom_size, ":", $atom_name, ":", $names[$namepos], '
'; + if ($names[$namepos] == $atom_name) + return get_chunk_offset($fp, $offset + 8, $filelen, $names, $namepos + 1); + $offset += $atom_size; + } + return -1; +} + +function chunk_offset($fp, $offset, $filelen, $path) +{ + $names = explode(".", $path); + return get_chunk_offset($fp, $offset, $filelen, $names, 0); +} + +function read_chunk($fp, $offset, $filelen, $path, $len) +{ + $offset = chunk_offset($fp, $offset, $filelen, $path); + if ($offset < 0) return; + fseek($fp, $offset, SEEK_SET); + return fread($fp, $len); +} + +function read_int($fp, $offset, $filelen, $path) +{ + return BigEndian2Int(read_chunk($fp, $offset, $filelen, $path, 4)); +} $file = $_FILES['uploadedfile']; @@ -61,17 +116,43 @@ $file = $_FILES['uploadedfile']; echo "Error ", $file['error']; } +//if ($_SERVER['HTTP_USER_AGENT'] != "CUETools 205") { +// echo "user agent ", $_SERVER['HTTP_USER_AGENT'], " is not allowed"; +// return; +//} + +$tmpname = $file['tmp_name']; +$size = (@file_exists($tmpname)) ? filesize($tmpname) : 0; +if ($size == 0) { + echo "no file uploaded"; + return; +} + +$fp = fopen($tmpname, 'rb'); +$head = read_chunk($fp, 0, $size, 'CTDB.HEAD', 20); +$npar = read_int($fp, 0, $size, 'CTDB.DISC.NPAR'); +$version = BigEndian2Int(substr($head,0,4)); +$disccount = BigEndian2Int(substr($head,4,4)); +$total = BigEndian2Int(substr($head,8,4)); +printf("npar=%d, disccount=%d, total=%d,", $npar, $disccount, $total); +fclose($fp); + $id = $_POST['id']; -$err = sscanf($id, "%d-%x-%x-%x", $tracks, $id1, $id2, $cddbid); -$target_path = sprintf("parity/%x/%x/%x", $id1 & 15, ($id1 >> 4) & 15, ($id1 >> 8) & 15); -$target_file = sprintf("%s/dBCT-%03d-%08x-%08x-%08x.bin", $target_path, $tracks, $id1, $id2, $cddbid); +$err = sscanf($id, "%03d-%04x%04x-%04x%04x-%04x%04x", $tracks, $id1a, $id1b, $id2a, $id2b, $cddbida, $cddbidb); +$parsedid = sprintf("%03d-%04x%04x-%04x%04x-%04x%04x", $tracks, $id1a, $id1b, $id2a, $id2b, $cddbida, $cddbidb); +if ($id != $parsedid) { + echo "bad id ", $id; + return; +} +$target_path = sprintf("parity/%x/%x/%x", $id1b & 15, ($id1b >> 4) & 15, ($id1b >> 8) & 15); +$target_file = sprintf("%s/dBCT-%s.bin", $target_path, $parsedid); @mkdir($target_path, 0777, true); if(move_uploaded_file($file['tmp_name'], $target_file)) { - echo "The file ". $target_file. " has been uploaded"; + printf("%s has been uploaded", $parsedid); } else{ - echo "There was an error uploading the file, please try again!"; + echo "there was an error uploading the file, please try again!"; } ?> diff --git a/CUETools.Codecs.FLAC/CUETools.Codecs.FLAC.cpp b/CUETools.Codecs.FLAC/CUETools.Codecs.FLAC.cpp index 1dc7c83..729fe67 100644 --- a/CUETools.Codecs.FLAC/CUETools.Codecs.FLAC.cpp +++ b/CUETools.Codecs.FLAC/CUETools.Codecs.FLAC.cpp @@ -268,7 +268,7 @@ namespace CUETools { namespace Codecs { namespace FLAC { _sampleOffset += _bufferLength; } Int32 copyCount = Math::Min(samplesNeeded, SamplesInBuffer); - Array::Copy(_sampleBuffer, _bufferOffset * pcm->ChannelCount, buff->Samples, buffOffset * pcm->ChannelCount, copyCount * pcm->ChannelCount); + Array::Copy(_sampleBuffer->Bytes, _bufferOffset * pcm->BlockAlign, buff->Bytes, buffOffset * pcm->BlockAlign, copyCount * pcm->BlockAlign); samplesNeeded -= copyCount; buffOffset += copyCount; _bufferOffset += copyCount; @@ -288,7 +288,7 @@ namespace CUETools { namespace Codecs { namespace FLAC { FLAC__StreamDecoder *_decoder; Int64 _sampleCount, _sampleOffset; AudioPCMConfig^ pcm; - array^ _sampleBuffer; + AudioBuffer^ _sampleBuffer; array^ _readBuffer; String^ _path; bool _decoderActive; @@ -318,23 +318,31 @@ namespace CUETools { namespace Codecs { namespace FLAC { throw gcnew Exception("Format changes within a file are not allowed."); } - if ((_sampleBuffer == nullptr) || (_sampleBuffer->GetLength(0) < sampleCount)) { - _sampleBuffer = gcnew array(sampleCount, pcm->ChannelCount); + if (_bufferOffset != 0) + throw gcnew Exception("Internal buffer error."); + + if (_sampleBuffer == nullptr || _sampleBuffer->Size < sampleCount) + _sampleBuffer = gcnew AudioBuffer(pcm, sampleCount); + _sampleBuffer->Length = sampleCount; + + if (pcm->ChannelCount == 2) + _sampleBuffer->Interlace(0, (int*)buffer[0], (int*)buffer[1], sampleCount); + else + { + int _channelCount = pcm->ChannelCount; + for (Int32 iChan = 0; iChan < _channelCount; iChan++) + { + interior_ptr pMyBuffer = &_sampleBuffer->Samples[0, iChan]; + const FLAC__int32 *pFLACBuffer = buffer[iChan]; + const FLAC__int32 *pFLACBufferEnd = pFLACBuffer + sampleCount; + + while (pFLACBuffer < pFLACBufferEnd) { + *pMyBuffer = *pFLACBuffer; + pMyBuffer += _channelCount; + pFLACBuffer++; + } + } } - - int _channelCount = pcm->ChannelCount; - for (Int32 iChan = 0; iChan < _channelCount; iChan++) { - interior_ptr pMyBuffer = &_sampleBuffer[0, iChan]; - const FLAC__int32 *pFLACBuffer = buffer[iChan]; - const FLAC__int32 *pFLACBufferEnd = pFLACBuffer + sampleCount; - - while (pFLACBuffer < pFLACBufferEnd) { - *pMyBuffer = *pFLACBuffer; - pMyBuffer += _channelCount; - pFLACBuffer++; - } - } - _bufferLength = sampleCount; return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; } diff --git a/CUETools.Codecs.FLAKE/FlakeReader.cs b/CUETools.Codecs.FLAKE/FlakeReader.cs index da7fef0..01f5774 100644 --- a/CUETools.Codecs.FLAKE/FlakeReader.cs +++ b/CUETools.Codecs.FLAKE/FlakeReader.cs @@ -211,17 +211,17 @@ namespace CUETools.Codecs.FLAKE } } - unsafe void interlace(int [,] buff, int offset, int count) + unsafe void interlace(AudioBuffer buff, int offset, int count) { if (PCM.ChannelCount == 2) { - fixed (int* res = &buff[offset, 0], src = &samplesBuffer[_samplesBufferOffset]) - AudioSamples.Interlace(res, src, src + Flake.MAX_BLOCKSIZE, count); + fixed (int* src = &samplesBuffer[_samplesBufferOffset]) + buff.Interlace(offset, src, src + Flake.MAX_BLOCKSIZE, count); } else { for (int ch = 0; ch < PCM.ChannelCount; ch++) - fixed (int* res = &buff[offset, ch], src = &samplesBuffer[_samplesBufferOffset + ch * Flake.MAX_BLOCKSIZE]) + fixed (int* res = &buff.Samples[offset, ch], src = &samplesBuffer[_samplesBufferOffset + ch * Flake.MAX_BLOCKSIZE]) { int* psrc = src; for (int i = 0; i < count; i++) @@ -241,7 +241,7 @@ namespace CUETools.Codecs.FLAKE { if (_samplesInBuffer > 0) { - interlace(buff.Samples, offset, _samplesInBuffer); + interlace(buff, offset, _samplesInBuffer); sampleCount -= _samplesInBuffer; offset += _samplesInBuffer; _samplesInBuffer = 0; @@ -261,7 +261,7 @@ namespace CUETools.Codecs.FLAKE _sampleOffset += _samplesInBuffer; } - interlace(buff.Samples, offset, sampleCount); + interlace(buff, offset, sampleCount); _samplesInBuffer -= sampleCount; _samplesBufferOffset += sampleCount; if (_samplesInBuffer == 0) diff --git a/CUETools.Codecs/CUETools.Codecs.csproj b/CUETools.Codecs/CUETools.Codecs.csproj index 4858045..8fa1e6f 100644 --- a/CUETools.Codecs/CUETools.Codecs.csproj +++ b/CUETools.Codecs/CUETools.Codecs.csproj @@ -2,7 +2,7 @@ Debug AnyCPU - 8.0.50727 + 9.0.30729 2.0 {6458A13A-30EF-45A9-9D58-E5031B17BEE2} Library @@ -19,7 +19,7 @@ true full false - bin\Debug\ + ..\bin\Debug\ DEBUG;TRACE prompt 4 diff --git a/CUETools.Codecs/Codecs.cs b/CUETools.Codecs/Codecs.cs index a56a19f..f696a77 100644 --- a/CUETools.Codecs/Codecs.cs +++ b/CUETools.Codecs/Codecs.cs @@ -300,6 +300,8 @@ namespace CUETools.Codecs samples = _samples; dataInSamples = true; dataInBytes = false; + if (length > size) + throw new Exception("Invalid length"); } public void Prepare(byte[] _bytes, int _length) @@ -309,6 +311,8 @@ namespace CUETools.Codecs bytes = _bytes; dataInSamples = false; dataInBytes = true; + if (length > size) + throw new Exception("Invalid length"); } public unsafe void Prepare(AudioBuffer _src, int _offset, int _length) @@ -344,6 +348,18 @@ namespace CUETools.Codecs buffer.dataInBytes = false; } + unsafe public void Interlace(int pos, int* src1, int* src2, int n) + { + if (PCM.ChannelCount != 2 || PCM.BitsPerSample != 16) + throw new Exception(""); + fixed (byte* bs = Bytes) + { + int* res = ((int*)bs) + pos; + for (int i = n; i > 0; i--) + *(res++) = (*(src1++) & 0xffff) ^ (*(src2++) << 16); + } + } + //public void Clear() //{ // length = 0; @@ -1517,7 +1533,6 @@ namespace CUETools.Codecs public class UserDefinedReader : IAudioSource { string _path, _decoder, _decoderParams; - private AudioPCMConfig pcm; Process _decoderProcess; WAVReader rdr; @@ -1603,7 +1618,7 @@ namespace CUETools.Codecs get { Initialize(); - return pcm; + return rdr.PCM; } } @@ -1651,7 +1666,7 @@ namespace CUETools.Codecs while (_haveData && !_close) Monitor.Wait(this); if (_close) - throw new Exception("Decompression aborted"); + break; AudioBuffer temp = _writeBuffer; _writeBuffer = _readBuffer; _readBuffer = temp; @@ -1659,6 +1674,7 @@ namespace CUETools.Codecs Monitor.Pulse(this); } } while (!done); + _source.Close(); } catch (Exception ex) { diff --git a/CUETools.Compression/CUETools.Compression.csproj b/CUETools.Compression/CUETools.Compression.csproj index 5590460..1800ff7 100644 --- a/CUETools.Compression/CUETools.Compression.csproj +++ b/CUETools.Compression/CUETools.Compression.csproj @@ -2,7 +2,7 @@ Debug AnyCPU - 8.0.50727 + 9.0.30729 2.0 {14EE067E-C218-4625-9540-2361AB27C4A6} Library @@ -19,7 +19,7 @@ true full false - bin\Debug\ + ..\bin\Debug\ DEBUG;TRACE prompt 4 diff --git a/CUETools.Parity/RsDecode.cs b/CUETools.Parity/RsDecode.cs index bcae922..43bf63e 100644 Binary files a/CUETools.Parity/RsDecode.cs and b/CUETools.Parity/RsDecode.cs differ diff --git a/CUETools.Processor/AudioReadWrite.cs b/CUETools.Processor/AudioReadWrite.cs index 683f4f4..c70cf99 100644 --- a/CUETools.Processor/AudioReadWrite.cs +++ b/CUETools.Processor/AudioReadWrite.cs @@ -61,7 +61,7 @@ namespace CUETools.Processor return new LossyWAVReader(lossySource, lwcdfSource); } - public static IAudioDest GetAudioDest(AudioEncoderType audioEncoderType, string path, AudioPCMConfig pcm, long finalSampleCount, int padding, string extension, CUEConfig config) + public static IAudioDest GetAudioDest(AudioEncoderType audioEncoderType, string path, AudioPCMConfig pcm, long finalSampleCount, int padding, string extension, CUEConfig config) { IAudioDest dest; if (audioEncoderType == AudioEncoderType.NoAudio || extension == ".dummy") @@ -73,7 +73,7 @@ namespace CUETools.Processor CUEToolsFormat fmt; if (!extension.StartsWith(".") || !config.formats.TryGetValue(extension.Substring(1), out fmt)) throw new Exception("Unsupported audio type: " + path); - CUEToolsUDC encoder = audioEncoderType == AudioEncoderType.Lossless ? fmt.encoderLossless : + CUEToolsUDC encoder = audioEncoderType == AudioEncoderType.Lossless ? fmt.encoderLossless : audioEncoderType == AudioEncoderType.Lossy ? fmt.encoderLossy : null; if (encoder == null) @@ -86,37 +86,39 @@ namespace CUETools.Processor if (o == null || !(o is IAudioDest)) throw new Exception("Unsupported audio type: " + path + ": " + encoder.type.FullName); dest = o as IAudioDest; - } else + } + else throw new Exception("Unsupported audio type: " + path); dest.CompressionLevel = encoder.DefaultModeIndex; dest.FinalSampleCount = finalSampleCount; - switch (encoder.type.FullName) - { - case "CUETools.Codecs.ALAC.ALACWriter": - dest.Options = string.Format("--padding-length {0}", padding); - break; - case "CUETools.Codecs.FLAKE.FlakeWriter": - dest.Options = string.Format("--padding-length {0}", padding); - break; - case "CUETools.Codecs.FlaCuda.FlaCudaWriter": - dest.Options = string.Format("{0}{1}--padding-length {2} --cpu-threads {3}", - config.flaCudaVerify ? "--verify " : "", - config.flaCudaGPUOnly ? "--gpu-only " : "", - padding, - config.FlaCudaThreads ? 1 : 0); - break; - case "CUETools.Codecs.FLAC.FLACWriter": - dest.Options = string.Format("{0}{1}--padding-length {2}", - config.disableAsm ? "--disable-asm " : "", - config.flacVerify ? "--verify " : "", - padding); - break; - case "CUETools.Codecs.WavPack.WavPackWriter": - dest.Options = string.Format("{0}--extra-mode {1}", - config.wvStoreMD5 ? "--md5 " : "", - config.wvExtraMode); - break; - } + if (encoder.type != null) + switch (encoder.type.FullName) + { + case "CUETools.Codecs.ALAC.ALACWriter": + dest.Options = string.Format("--padding-length {0}", padding); + break; + case "CUETools.Codecs.FLAKE.FlakeWriter": + dest.Options = string.Format("--padding-length {0}", padding); + break; + case "CUETools.Codecs.FlaCuda.FlaCudaWriter": + dest.Options = string.Format("{0}{1}--padding-length {2} --cpu-threads {3}", + config.flaCudaVerify ? "--verify " : "", + config.flaCudaGPUOnly ? "--gpu-only " : "", + padding, + config.FlaCudaThreads ? 1 : 0); + break; + case "CUETools.Codecs.FLAC.FLACWriter": + dest.Options = string.Format("{0}{1}--padding-length {2}", + config.disableAsm ? "--disable-asm " : "", + config.flacVerify ? "--verify " : "", + padding); + break; + case "CUETools.Codecs.WavPack.WavPackWriter": + dest.Options = string.Format("{0}--extra-mode {1}", + config.wvStoreMD5 ? "--md5 " : "", + config.wvExtraMode); + break; + } return dest; } diff --git a/CUETools.Processor/CUETools.Processor.csproj b/CUETools.Processor/CUETools.Processor.csproj index 47f9b53..2982abc 100644 --- a/CUETools.Processor/CUETools.Processor.csproj +++ b/CUETools.Processor/CUETools.Processor.csproj @@ -34,7 +34,7 @@ true full false - ..\bin\win32\Debug\ + ..\bin\Debug\ DEBUG;TRACE prompt 4 @@ -74,6 +74,10 @@
+ + {C4869B37-EBB1-47BB-9406-B1209BEAB84B} + CUETools.CDRepair + {6458A13A-30EF-45A9-9D58-E5031B17BEE2} CUETools.Codecs @@ -90,6 +94,10 @@ {14EE067E-C218-4625-9540-2361AB27C4A6} CUETools.Compression + + {AA2A9A7E-45FB-4632-AD85-85B0E556F818} + CUETools.CTDB + {D2700165-3E77-4B28-928D-551F5FC11954} CUETools.Ripper diff --git a/CUETools.Processor/Processor.cs b/CUETools.Processor/Processor.cs index bedc2f7..ff5ae02 100644 --- a/CUETools.Processor/Processor.cs +++ b/CUETools.Processor/Processor.cs @@ -41,6 +41,8 @@ using System.Runtime.InteropServices; using CUETools.Codecs; using CUETools.CDImage; using CUETools.AccurateRip; +//using CUETools.CDRepair; +using CUETools.CTDB; using CUETools.Ripper; using CUETools.Compression; using MusicBrainz; @@ -928,6 +930,8 @@ namespace CUETools.Processor public int maxAlbumArtSize; public string arLogFilenameFormat, alArtFilenameFormat; public CUEStyle gapsHandling; + public bool separateDecodingThread; + public bool useSystemProxySettings; public bool CopyAlbumArt { get { return copyAlbumArt; } set { copyAlbumArt = value; } } public bool FlaCudaThreads { get { return flaCudaThreads; } set { flaCudaThreads = value; } } @@ -1004,6 +1008,9 @@ namespace CUETools.Processor arLogFilenameFormat = "%filename%.accurip"; alArtFilenameFormat = "folder.jpg"; + separateDecodingThread = true; + useSystemProxySettings = true; + gapsHandling = CUEStyle.GapsAppended; language = Thread.CurrentThread.CurrentUICulture.Name; @@ -1090,6 +1097,29 @@ if (tracksMatch * 100 < processor.Config.encodeWhenPercent * processor.TrackCoun processor.Action = CUEAction.Encode; return processor.Go(); ")); + scripts.Add("repair", new CUEToolsScript("repair", true, + new CUEAction[] { CUEAction.Encode }, +@" +processor.UseCUEToolsDB(); +processor.Action = CUEAction.Verify; +if (processor.CTDB.DBStatus != null) + return CTDB.DBStatus; +processor.Go(); +processor.CTDB.DoVerify(); +if (!processor.CTDB.Verify.HasErrors) + return ""nothing to fix""; +if (!processor.CTDB.Verify.CanRecover) + return ""cannot fix""; +processor._useCUEToolsDBFix = true; +processor.Action = CUEAction.Encode; +return processor.Go(); +")); + scripts.Add("submit", new CUEToolsScript("submit", true, + new CUEAction[] { CUEAction.Verify }, +@" +string status = processor.Go(); +")); + defaultVerifyScript = "default"; defaultEncodeScript = "default"; } @@ -1145,6 +1175,9 @@ return processor.Go(); sw.Save("CheckForUpdates", checkForUpdates); sw.Save("Language", language); + sw.Save("SeparateDecodingThread", separateDecodingThread); + sw.Save("UseSystemProxySettings", useSystemProxySettings); + sw.Save("WriteBasicTagsFromCUEData", writeBasicTagsFromCUEData); sw.Save("CopyBasicTags", copyBasicTags); sw.Save("CopyUnknownTags", copyUnknownTags); @@ -1289,6 +1322,9 @@ return processor.Go(); arLogFilenameFormat = sr.Load("ArLogFilenameFormat") ?? arLogFilenameFormat; alArtFilenameFormat = sr.Load("AlArtFilenameFormat") ?? alArtFilenameFormat; + separateDecodingThread = sr.LoadBoolean("SeparateDecodingThread") ?? separateDecodingThread; + useSystemProxySettings = sr.LoadBoolean("UseSystemProxySettings") ?? useSystemProxySettings; + int totalEncoders = sr.LoadInt32("ExternalEncoders", 0, null) ?? 0; for (int nEncoders = 0; nEncoders < totalEncoders; nEncoders++) { @@ -1477,6 +1513,7 @@ return processor.Go(); _useFreeDb = sr.LoadBoolean("FreedbLookup") ?? _useFreeDb; _useMusicBrainz = sr.LoadBoolean("MusicBrainzLookup") ?? _useMusicBrainz; _useAccurateRip = sr.LoadBoolean("AccurateRipLookup") ?? _useAccurateRip; + _useCUEToolsDB = sr.LoadBoolean("CUEToolsDBLookup") ?? _useCUEToolsDB; _outputAudioType = (AudioEncoderType?)sr.LoadInt32("OutputAudioType", null, null) ?? _outputAudioType; _outputAudioFormat = sr.Load("OutputAudioFmt") ?? _outputAudioFormat; _action = (CUEAction?)sr.LoadInt32("AccurateRipMode", (int)CUEAction.Encode, (int)CUEAction.CorrectFilenames) ?? _action; @@ -1493,6 +1530,7 @@ return processor.Go(); sw.Save("FreedbLookup", _useFreeDb); sw.Save("MusicBrainzLookup", _useMusicBrainz); sw.Save("AccurateRipLookup", _useAccurateRip); + sw.Save("CUEToolsDBLookup", _useCUEToolsDB); sw.Save("OutputAudioType", (int)_outputAudioType); sw.Save("OutputAudioFmt", _outputAudioFormat); sw.Save("AccurateRipMode", (int)_action); @@ -1508,7 +1546,7 @@ return processor.Go(); public CUEAction _action = CUEAction.Encode; public CUEStyle _CUEStyle = CUEStyle.SingleFileWithCUE; public int _writeOffset = 0; - public bool _useFreeDb = true, _useMusicBrainz = true, _useAccurateRip = true; + public bool _useFreeDb = true, _useMusicBrainz = true, _useAccurateRip = true, _useCUEToolsDB = true; public string _name; } @@ -1533,9 +1571,9 @@ return processor.Go(); { public string path; public string contents; - public bool isEAC; + public object data; - public CUEToolsSourceFile(string _path, StreamReader reader) + public CUEToolsSourceFile(string _path, TextReader reader) { path = _path; contents = reader.ReadToEnd(); @@ -1556,6 +1594,10 @@ return processor.Go(); private int _writeOffset; private CUEAction _action; private bool _useAccurateRip = false; + private bool _useCUEToolsDB = false; + private bool _useCUEToolsDBFix = false; + private bool _useCUEToolsDBSibmit = false; + private bool _processed = false; private uint? _minDataTrackLength; private string _accurateRipId; private string _eacLog; @@ -1581,10 +1623,12 @@ return processor.Go(); private string _archivePassword; private CUEToolsProgressEventArgs _progress; private AccurateRipVerify _arVerify; + private CUEToolsDB _CUEToolsDB; private CDImageLayout _toc; private string _arLogFileName, _alArtFileName; private TagLib.IPicture[] _albumArt; private int _padding = 8192; + private IWebProxy proxy; public event EventHandler PasswordRequired; public event EventHandler CUEToolsProgress; @@ -1614,6 +1658,7 @@ return processor.Go(); _isArchive = false; _isCD = false; _albumArt = null; + proxy = _config.useSystemProxySettings ? WebRequest.GetSystemWebProxy() : null; } public void OpenCD(ICDRipper ripper) @@ -1625,7 +1670,9 @@ return processor.Go(); _trackFilenames.Add(string.Format("{0:00}.wav", iTrack + 1)); _tracks.Add(new TrackInfo()); } - _arVerify = new AccurateRipVerify(_toc); + _arVerify = new AccurateRipVerify(_toc, proxy); + _CUEToolsDB = new CUEToolsDB(_toc, proxy); + _CUEToolsDB.UploadHelper.onProgress += new EventHandler(UploadProgress); _isCD = true; SourceInfo cdInfo; cdInfo.Path = _ripper.ARName; @@ -1653,6 +1700,14 @@ return processor.Go(); } } + public CUEToolsDB CTDB + { + get + { + return _CUEToolsDB; + } + } + public ICDRipper CDRipper { get @@ -2533,7 +2588,9 @@ return processor.Go(); } } - _arVerify = new AccurateRipVerify(_toc); + _arVerify = new AccurateRipVerify(_toc, proxy); + _CUEToolsDB = new CUEToolsDB(_toc, proxy); + _CUEToolsDB.UploadHelper.onProgress += new EventHandler(UploadProgress); if (_eacLog != null) { @@ -2578,6 +2635,16 @@ return processor.Go(); _padding += _eacLog.Length; } + public void UseCUEToolsDB() + { + ShowProgress((string)"Contacting CUETools database...", 0, 0, null, null); + + _CUEToolsDB.ContactDB(_accurateRipId ?? AccurateRipVerify.CalculateAccurateRipId(_toc)); + + ShowProgress("", 0.0, 0.0, null, null); + _useCUEToolsDB = true; + } + public void UseAccurateRip() { ShowProgress((string)"Contacting AccurateRip database...", 0, 0, null, null); @@ -2685,6 +2752,18 @@ return processor.Go(); this.CUEToolsProgress(this, _progress); } + private void UploadProgress(object sender, Krystalware.UploadHelper.UploadProgressEventArgs e) + { + CheckStop(); + if (this.CUEToolsProgress == null) + return; + _progress.percentDisk = 1.0; + _progress.percentTrck = e.percent; + _progress.offset = 0; + _progress.status = e.uri; + this.CUEToolsProgress(this, _progress); + } + private void CDReadProgress(object sender, ReadProgressArgs e) { CheckStop(); @@ -3016,7 +3095,8 @@ return processor.Go(); if (Path.GetExtension(path) == ".dummy" || Path.GetExtension(path) == ".bin") { fileInfo = null; - } else + } + else { TagLib.UserDefined.AdditionalFileTypes.Config = _config; TagLib.File.IFileAbstraction file = _isArchive @@ -3026,15 +3106,18 @@ return processor.Go(); } IAudioSource audioSource = AudioReadWrite.GetAudioSource(path, _isArchive ? OpenArchive(path, true) : null, _config); - if (!audioSource.PCM.IsRedBook || - audioSource.Length <= 0 || - audioSource.Length >= Int32.MaxValue) + try + { + if (!audioSource.PCM.IsRedBook || + audioSource.Length <= 0 || + audioSource.Length >= Int32.MaxValue) + throw new Exception("Audio format is invalid."); + return (int)audioSource.Length; + } + finally { audioSource.Close(); - throw new Exception("Audio format is invalid."); } - audioSource.Close(); - return (int)audioSource.Length; } public static void WriteText(string path, string text, Encoding encoding) @@ -3122,6 +3205,48 @@ return processor.Go(); logWriter.WriteLine(); logWriter.WriteLine(" Pre-gap length 0:{0}.{1:00}", CDImageLayout.TimeToString("{0:00}:{1:00}", _toc[track + _toc.FirstAudio].Pregap + (track + _toc.FirstAudio == 1 ? 150U : 0U)), (_toc[track + _toc.FirstAudio].Pregap % 75) * 100 / 75); } + + int errCount = 0; + uint tr_start = _toc[track + _toc.FirstAudio].Start; + uint tr_end = (_toc[track + _toc.FirstAudio].Length + 74) / 75; + for (uint iSecond = 0; iSecond < tr_end; iSecond ++) + { + uint sec_start = tr_start + iSecond * 75; + uint sec_end = Math.Min(sec_start + 74, _toc[track + _toc.FirstAudio].End); + bool fError = false; + for (uint iSector = sec_start; iSector <= sec_end; iSector++) + if (_ripper.Errors[(int)iSector]) + fError = true; + if (fError) + { + uint end = iSecond; + for (uint jSecond = iSecond + 1; jSecond < tr_end; jSecond++) + { + uint jsec_start = tr_start + jSecond * 75; + uint jsec_end = Math.Min(jsec_start + 74, _toc[track + _toc.FirstAudio].End); + bool jfError = false; + for (uint jSector = jsec_start; jSector <= jsec_end; jSector++) + if (_ripper.Errors[(int)jSector]) + jfError = true; + if (jfError) + end = jSecond; + } + if (errCount == 0) + logWriter.WriteLine(); + if (errCount++ > 20) + break; + //"Suspicious position 0:02:20" + //" Suspicious position 0:02:23 - 0:02:24" + string s1 = CDImageLayout.TimeToString("0:{0:00}:{1:00}", iSecond * 75); + string s2 = CDImageLayout.TimeToString("0:{0:00}:{1:00}", end * 75); + if (iSecond == end) + logWriter.WriteLine(" Suspicious position {0}", s1); + else + logWriter.WriteLine(" Suspicious position {0} - {1}", s1, s2); + iSecond = end; + } + } + logWriter.WriteLine(); logWriter.WriteLine(" Peak level {0:F1} %", (Tracks[track].PeakLevel * 1000 / 32768) * 0.1); logWriter.WriteLine(" Track quality 100.0 %"); @@ -3391,6 +3516,8 @@ return processor.Go(); public void GenerateAccurateRipLog(TextWriter sw) { + if (!_processed) + throw new Exception("not processed"); sw.WriteLine("[Verification date: {0}]", DateTime.Now); sw.WriteLine("[Disc ID: {0}]", _accurateRipId ?? AccurateRipVerify.CalculateAccurateRipId(_toc)); if (PreGapLength != 0) @@ -3414,6 +3541,10 @@ return processor.Go(); sw.WriteLine("HDCD: {0:f}", hdcdDecoder); if (0 != _writeOffset) sw.WriteLine("Offset applied: {0}", _writeOffset); + if (_useCUEToolsDBFix)// && _CUEToolsDB.SelectedEntry != null) + sw.WriteLine("CUETools DB: corrected {0} errors.", _CUEToolsDB.SelectedEntry.repair.CorrectableErrors); + else if (_useCUEToolsDB) + sw.WriteLine("CUETools DB: {0}.", _CUEToolsDB.Status); _arVerify.GenerateFullLog(sw, _config.arLogVerbose); } @@ -3550,6 +3681,14 @@ return processor.Go(); if (_audioEncoderType != AudioEncoderType.NoAudio || _action == CUEAction.Verify) WriteAudioFilesPass(OutputDir, OutputStyle, destLengths, htoaToFile, _action == CUEAction.Verify); + if (_useCUEToolsDB && CTDB.AccResult == HttpStatusCode.OK) + { + if (!_useCUEToolsDBFix) + CTDB.DoVerify(); + } + + _processed = true; + CreateRipperLOG(); if (_action == CUEAction.Encode) @@ -4097,6 +4236,8 @@ return processor.Go(); if (_useAccurateRip) _arVerify.Init(); + if (_useCUEToolsDB && !_useCUEToolsDBFix) + _CUEToolsDB.Init(_useCUEToolsDBSibmit); ShowProgress(String.Format("{2} track {0:00} ({1:00}%)...", 0, 0, noOutput ? "Verifying" : "Writing"), 0, 0.0, null, null); @@ -4179,6 +4320,13 @@ return processor.Go(); } copyCount = audioSource.Read(sampleBuffer, copyCount); + if (_useCUEToolsDB) + { + if (_useCUEToolsDBFix) + _CUEToolsDB.SelectedEntry.repair.Write(sampleBuffer); + else + _CUEToolsDB.Verify.Write(sampleBuffer); + } if (!discardOutput) { if (!_config.detectHDCD || !_config.decodeHDCD) @@ -4208,7 +4356,7 @@ return processor.Go(); { _arVerify.Write(sampleBuffer); if (iTrack > 0 || iIndex > 0) - Tracks[iTrack + (iIndex == 0 ? -1 : 0)].MeasurePeakLevel(sampleBuffer.Samples, copyCount); + Tracks[iTrack + (iIndex == 0 ? -1 : 0)].MeasurePeakLevel(sampleBuffer, copyCount); } currentOffset += copyCount; @@ -4550,7 +4698,9 @@ return processor.Go(); if (sourceInfo.Offset != 0) audioSource.Position = sourceInfo.Offset; - //audioSource = new AudioPipe(audioSource, 0x10000); + //if (!(audioSource is AudioPipe) && !(audioSource is UserDefinedReader) && _config.separateDecodingThread) + if (!(audioSource is AudioPipe) && _config.separateDecodingThread) + audioSource = new AudioPipe(audioSource, 0x10000); return audioSource; } @@ -4902,6 +5052,14 @@ return processor.Go(); } } + public bool Processed + { + get + { + return _processed; + } + } + public bool IsCD { get @@ -5039,6 +5197,56 @@ return processor.Go(); return Go(); case "only if found": return ArVerify.AccResult != HttpStatusCode.OK ? WriteReport() : Go(); + case "submit": + { + if (!_useCUEToolsDB) + return "CUETools DB not enabled"; + if (ArVerify.ARStatus != null) + return "AccurateRip: " + ArVerify.ARStatus; + if (ArVerify.WorstTotal() < 3) + return "AccurateRip: confidence too low"; + //if (CTDB.AccResult == HttpStatusCode.OK) + //return "CUEToolsDB: disc already present in database"; + if (CTDB.AccResult != HttpStatusCode.NotFound && CTDB.AccResult != HttpStatusCode.OK) + return "CUEToolsDB: " + CTDB.DBStatus; + _useCUEToolsDBSibmit = true; + string status = Go(); + if (CTDB.AccResult == HttpStatusCode.OK) + foreach (DBEntry entry in CTDB.Entries) + if (!entry.hasErrors) + return "CUEToolsDB: " + CTDB.Status; + if (ArVerify.WorstConfidence() < 3) + return status + ": confidence too low"; + return CTDB.Submit((int)ArVerify.WorstConfidence(), (int)ArVerify.WorstTotal()); + } + case "repair": + { + UseCUEToolsDB(); + Action = CUEAction.Verify; + if (CTDB.DBStatus != null) + return CTDB.DBStatus; + bool useAR = _useAccurateRip; + _useAccurateRip = false; + Go(); + _useAccurateRip = useAR; + List choices = new List(); + foreach (DBEntry entry in CTDB.Entries) + if (!entry.hasErrors || entry.canRecover) + { + CUEToolsSourceFile choice = new CUEToolsSourceFile(entry.Status, new StringReader("")); + choice.data = entry; + choices.Add(choice); + } + CUEToolsSourceFile selectedEntry = ChooseFile(choices, null, true); + if (selectedEntry == null) + return CTDB.Status; + CTDB.SelectedEntry = (DBEntry)selectedEntry.data; + if (!CTDB.SelectedEntry.hasErrors) + return CTDB.Status; + _useCUEToolsDBFix = true; + Action = CUEAction.Encode; + return Go(); + } case "fix offset": { if (ArVerify.AccResult != HttpStatusCode.OK) @@ -5276,12 +5484,15 @@ return processor.Go(); _peakLevel = 0; } - public unsafe void MeasurePeakLevel(int[,] samplesBuffer, int sampleCount) + public unsafe void MeasurePeakLevel(AudioBuffer buff, int sampleCount) { - fixed (int* s = samplesBuffer) + if (!buff.PCM.IsRedBook) + throw new Exception(); + fixed (byte* bb = buff.Bytes) { + short* ss = (short*)bb; for (int i = 0; i < sampleCount * 2; i++) - _peakLevel = Math.Max(_peakLevel, Math.Abs(s[i])); + _peakLevel = Math.Max(_peakLevel, Math.Abs((int)ss[i])); } //for (uint i = 0; i < sampleCount; i++) // for (uint j = 0; j < 2; j++) diff --git a/CUETools.Ripper.Console/Program.cs b/CUETools.Ripper.Console/Program.cs index f7cea8e..0194300 100644 --- a/CUETools.Ripper.Console/Program.cs +++ b/CUETools.Ripper.Console/Program.cs @@ -21,6 +21,7 @@ using System; using System.IO; +using System.Net; using System.Text; using System.Collections.Generic; using CUETools.Ripper; @@ -172,8 +173,8 @@ namespace CUETools.ConsoleRipper Console.Write(readCmd); return; } - - AccurateRipVerify arVerify = new AccurateRipVerify(audioSource.TOC); + + AccurateRipVerify arVerify = new AccurateRipVerify(audioSource.TOC, WebRequest.GetSystemWebProxy()); AudioBuffer buff = new AudioBuffer(audioSource, 0x10000); string CDDBId = AccurateRipVerify.CalculateCDDBId(audioSource.TOC); string ArId = AccurateRipVerify.CalculateAccurateRipId(audioSource.TOC); diff --git a/CUETools.Ripper.SCSI/CUETools.Ripper.SCSI.csproj b/CUETools.Ripper.SCSI/CUETools.Ripper.SCSI.csproj index 29a6398..e7aa6fb 100644 --- a/CUETools.Ripper.SCSI/CUETools.Ripper.SCSI.csproj +++ b/CUETools.Ripper.SCSI/CUETools.Ripper.SCSI.csproj @@ -2,7 +2,7 @@ Debug AnyCPU - 8.0.50727 + 9.0.30729 2.0 {8CF07381-BEA2-4AFC-B3DD-9B2F21C65A3A} Library @@ -39,9 +39,6 @@ - - - diff --git a/CUETools.Ripper.SCSI/SCSIDrive.cs b/CUETools.Ripper.SCSI/SCSIDrive.cs index 843e8eb..75e979f 100644 --- a/CUETools.Ripper.SCSI/SCSIDrive.cs +++ b/CUETools.Ripper.SCSI/SCSIDrive.cs @@ -46,7 +46,6 @@ namespace CUETools.Ripper.SCSI int _correctionQuality = 1; int _currentStart = -1, _currentEnd = -1, _currentErrorsCount = 0; const int CB_AUDIO = 4 * 588 + 2 + 294 + 16; - const int MAXSCANS = 20; const int NSECTORS = 16; //const int MSECTORS = 5*1024*1024 / (4 * 588); const int MSECTORS = 2400; @@ -58,11 +57,10 @@ namespace CUETools.Ripper.SCSI int m_max_sectors; int _timeout = 10; Crc16Ccitt _crc; - int _currentScan; - public byte[,,] UserData; - public byte[,,] C2Data; - public byte[,,] QData; - public long[] Quality; + public long[,] UserData; + public long[,] C2Data; + public byte[,] QData; + public long[] byte2long; BitArray _errors; int _errorsCount; int _crcErrorsCount = 0; @@ -185,10 +183,17 @@ namespace CUETools.Ripper.SCSI { m_logger = new Logger(); _crc = new Crc16Ccitt(InitialCrcValue.Zeros); - UserData = new byte[MAXSCANS, MSECTORS, 4 * 588]; - C2Data = new byte[MAXSCANS, MSECTORS, 294]; - QData = new byte[MAXSCANS, MSECTORS, 16]; - Quality = new long[MAXSCANS]; + UserData = new long[MSECTORS, 4 * 588]; + C2Data = new long[MSECTORS, 588 / 2]; + QData = new byte[MSECTORS, 16]; + byte2long = new long[256]; + for (long i = 0; i < 256; i++) + { + long bl = 0; + for (int b = 0; b < 8; b++) + bl += ((i >> b) & 1) << (b << 3); + byte2long[i] = bl; + } } public bool Open(char Drive) @@ -303,13 +308,13 @@ namespace CUETools.Ripper.SCSI for (int iSector = 0; iSector < Sectors2Read; iSector++) { int q_pos = (sector - _currentStart + iSector); - int ctl = QData[_currentScan, q_pos, 0] >> 4; - int adr = QData[_currentScan, q_pos, 0] & 7; + int ctl = QData[q_pos, 0] >> 4; + int adr = QData[q_pos, 0] & 7; bool preemph = (ctl & 1) == 1; bool dcp = (ctl & 2) == 2; for (int i = 0; i < 10; i++) - _subchannelBuffer[i] = QData[_currentScan, q_pos, i]; + _subchannelBuffer[i] = QData[ q_pos, i]; if (!_qChannelInBCD && adr == 1) { _subchannelBuffer[3] = toBCD(_subchannelBuffer[3]); @@ -321,8 +326,8 @@ namespace CUETools.Ripper.SCSI } ushort crc = _crc.ComputeChecksum(_subchannelBuffer, 0, 10); crc ^= 0xffff; - if ((QData[_currentScan, q_pos, 10] != 0 || QData[_currentScan, q_pos, 11] != 0) && - ((byte)(crc & 0xff) != QData[_currentScan, q_pos, 11] || (byte)(crc >> 8) != QData[_currentScan, q_pos, 10]) + if ((QData[q_pos, 10] != 0 || QData[q_pos, 11] != 0) && + ((byte)(crc & 0xff) != QData[q_pos, 11] || (byte)(crc >> 8) != QData[q_pos, 10]) ) { if (!updateMap) @@ -332,7 +337,7 @@ namespace CUETools.Ripper.SCSI { StringBuilder st = new StringBuilder(); for (int i = 0; i < 12; i++) - st.AppendFormat(",0x{0:X2}", QData[_currentScan, q_pos, i]); + st.AppendFormat(",0x{0:X2}", QData[q_pos, i]); System.Console.WriteLine("\rCRC error@{0}{1};", CDImageLayout.TimeToString((uint)(sector + iSector)), st.ToString()); } continue; @@ -341,11 +346,11 @@ namespace CUETools.Ripper.SCSI { case 1: // current position { - int iTrack = fromBCD(QData[_currentScan, q_pos, 1]); - int iIndex = fromBCD(QData[_currentScan, q_pos, 2]); - int mm = _qChannelInBCD ? fromBCD(QData[_currentScan, q_pos, 7]) : QData[_currentScan, q_pos, 7]; - int ss = _qChannelInBCD ? fromBCD(QData[_currentScan, q_pos, 8]) : QData[_currentScan, q_pos, 8]; - int ff = _qChannelInBCD ? fromBCD(QData[_currentScan, q_pos, 9]) : QData[_currentScan, q_pos, 9]; + int iTrack = fromBCD(QData[q_pos, 1]); + int iIndex = fromBCD(QData[q_pos, 2]); + int mm = _qChannelInBCD ? fromBCD(QData[q_pos, 7]) : QData[q_pos, 7]; + int ss = _qChannelInBCD ? fromBCD(QData[q_pos, 8]) : QData[q_pos, 8]; + int ff = _qChannelInBCD ? fromBCD(QData[q_pos, 9]) : QData[q_pos, 9]; //if (sec != sector + iSector) // System.Console.WriteLine("\rLost sync: {0} vs {1} ({2:X} vs {3:X})", CDImageLayout.TimeToString((uint)(sector + iSector)), CDImageLayout.TimeToString((uint)sec), sector + iSector, sec); if (iTrack == 110) @@ -413,7 +418,7 @@ namespace CUETools.Ripper.SCSI { StringBuilder catalog = new StringBuilder(); for (int i = 1; i < 8; i++) - catalog.AppendFormat("{0:x2}", QData[_currentScan, q_pos, i]); + catalog.AppendFormat("{0:x2}", QData[q_pos, i]); _toc.Catalog = catalog.ToString(0, 13); } break; @@ -421,16 +426,16 @@ namespace CUETools.Ripper.SCSI if (updateMap && _toc[_currentTrack].ISRC == null) { StringBuilder isrc = new StringBuilder(); - isrc.Append(from6bit(QData[_currentScan, q_pos, 1] >> 2)); - isrc.Append(from6bit(((QData[_currentScan, q_pos, 1] & 0x3) << 4) + (0x0f & (QData[_currentScan, q_pos, 2] >> 4)))); - isrc.Append(from6bit(((QData[_currentScan, q_pos, 2] & 0xf) << 2) + (0x03 & (QData[_currentScan, q_pos, 3] >> 6)))); - isrc.Append(from6bit((QData[_currentScan, q_pos, 3] & 0x3f))); - isrc.Append(from6bit(QData[_currentScan, q_pos, 4] >> 2)); - isrc.Append(from6bit(((QData[_currentScan, q_pos, 4] & 0x3) << 4) + (0x0f & (QData[_currentScan, q_pos, 5] >> 4)))); - isrc.AppendFormat("{0:x}", QData[_currentScan, q_pos, 5] & 0xf); - isrc.AppendFormat("{0:x2}", QData[_currentScan, q_pos, 6]); - isrc.AppendFormat("{0:x2}", QData[_currentScan, q_pos, 7]); - isrc.AppendFormat("{0:x}", QData[_currentScan, q_pos, 8] >> 4); + isrc.Append(from6bit(QData[q_pos, 1] >> 2)); + isrc.Append(from6bit(((QData[q_pos, 1] & 0x3) << 4) + (0x0f & (QData[q_pos, 2] >> 4)))); + isrc.Append(from6bit(((QData[q_pos, 2] & 0xf) << 2) + (0x03 & (QData[q_pos, 3] >> 6)))); + isrc.Append(from6bit((QData[q_pos, 3] & 0x3f))); + isrc.Append(from6bit(QData[q_pos, 4] >> 2)); + isrc.Append(from6bit(((QData[q_pos, 4] & 0x3) << 4) + (0x0f & (QData[q_pos, 5] >> 4)))); + isrc.AppendFormat("{0:x}", QData[q_pos, 5] & 0xf); + isrc.AppendFormat("{0:x2}", QData[q_pos, 6]); + isrc.AppendFormat("{0:x2}", QData[q_pos, 7]); + isrc.AppendFormat("{0:x}", QData[q_pos, 8] >> 4); if (!isrc.ToString().Contains("#") && isrc.ToString() != "0000000000") _toc[_currentTrack].ISRC = isrc.ToString(); } @@ -449,7 +454,6 @@ namespace CUETools.Ripper.SCSI Device.MainChannelSelection[] mainmode = { Device.MainChannelSelection.UserData, Device.MainChannelSelection.F8h }; bool found = false; _currentStart = 0; - _currentScan = 0; _currentTrack = -1; _currentIndex = -1; m_max_sectors = Math.Min(NSECTORS, m_device.MaximumTransferLength / CB_AUDIO - 1); @@ -507,27 +511,34 @@ namespace CUETools.Ripper.SCSI return found; } - private unsafe void ReorganiseSectors(int sector, int Sectors2Read) + private unsafe void ReorganiseSectors(int sector, int Sectors2Read) { int c2Size = _c2ErrorMode == Device.C2ErrorMode.None ? 0 : _c2ErrorMode == Device.C2ErrorMode.Mode294 ? 294 : 296; - int oldSize = 4 * 588 + c2Size + (_subChannelMode == Device.SubChannelMode.None ? 0 : 16); - fixed (byte* readBuf = _readBuffer, qBuf = _subchannelBuffer, userData = UserData, c2Data = C2Data, qData = QData) + int oldSize = 4 * 588 + c2Size + (_subChannelMode == Device.SubChannelMode.None ? 0 : 16); + fixed (byte* readBuf = _readBuffer, qBuf = _subchannelBuffer, qData = QData) + fixed (long* userData = UserData, c2Data = C2Data) { for (int iSector = 0; iSector < Sectors2Read; iSector++) { byte* sectorPtr = readBuf + iSector * oldSize; - byte* userDataPtr = userData + (_currentScan * MSECTORS + sector - _currentStart + iSector) * 4 * 588; - byte* c2DataPtr = c2Data + (_currentScan * MSECTORS + sector - _currentStart + iSector) * 294; - byte* qDataPtr = qData + (_currentScan * MSECTORS + sector - _currentStart + iSector) * 16; + long* userDataPtr = userData + (sector - _currentStart + iSector) * 4 * 588; + long* c2DataPtr = c2Data + (sector - _currentStart + iSector) * 294; + byte* qDataPtr = qData + (sector - _currentStart + iSector) * 16; for (int sample = 0; sample < 4 * 588; sample++) - userDataPtr[sample] = sectorPtr[sample]; + userDataPtr[sample] += byte2long[sectorPtr[sample]] * 3; if (_c2ErrorMode != Device.C2ErrorMode.None) + { for (int c2 = 0; c2 < 294; c2++) - c2DataPtr[c2] = sectorPtr[4 * 588 + c2Size - 294 + c2]; - else - for (int c2 = 0; c2 < 294; c2++) - c2DataPtr[c2] = 0; // 0xff?? + { + byte c2val = sectorPtr[4 * 588 + c2Size - 294 + c2]; + c2DataPtr[c2] += byte2long[c2val]; + if (c2val != 0) + for (int b = 0; b < 8; b++) + if (((c2val >> b) & 1) != 0) + userDataPtr[c2 * 8 + b] += 0x0101010101010101 - byte2long[sectorPtr[c2 * 8 + b]] * 2; + } + } if (_subChannelMode != Device.SubChannelMode.None) for (int qi = 0; qi < 16; qi++) qDataPtr[qi] = sectorPtr[4 * 588 + c2Size + qi]; @@ -538,6 +549,15 @@ namespace CUETools.Ripper.SCSI } } + private unsafe void ClearSectors(int sector, int Sectors2Read) + { + fixed (long* userData = &UserData[sector - _currentStart, 0], c2Data = &C2Data[sector - _currentStart, 0]) + { + ZeroMemory((byte*)userData, 8 * 4 * 588 * Sectors2Read); + ZeroMemory((byte*)c2Data, 4 * 588 * Sectors2Read); + } + } + private unsafe Device.CommandStatus FetchSectors(int sector, int Sectors2Read, bool abort, bool subchannel) { Device.CommandStatus st; @@ -579,11 +599,11 @@ namespace CUETools.Ripper.SCSI { iErrors ++; for (int i = 0; i < 4 * 588; i++) - UserData[_currentScan, sector + iSector - _currentStart, i] = 0; + UserData[sector + iSector - _currentStart, i] += 0x0101010101010101; for (int i = 0; i < 294; i++) - C2Data[_currentScan, sector + iSector - _currentStart, i] = 0xff; + C2Data[sector + iSector - _currentStart, i] += 0x0101010101010101; for (int i = 0; i < 16; i++) - QData[_currentScan, sector + iSector - _currentStart, i] = 0; + QData[ sector + iSector - _currentStart, i] = 0; if (_debugMessages) System.Console.WriteLine("\nSector lost"); } @@ -666,23 +686,24 @@ namespace CUETools.Ripper.SCSI private void PrintErrors(int pass, int sector, int Sectors2Read, byte[] realData) { - for (int iSector = 0; iSector < Sectors2Read; iSector++) - { - int pos = sector - _currentStart + iSector; - if (_debugMessages) - { - StringBuilder st = new StringBuilder(); - for (int i = 0; i < 294; i++) - if (C2Data[_currentScan, pos, i] != 0) - { - for (int j = i; j < i + 23; j++) - if (j < 294) - st.AppendFormat("{0:X2}", C2Data[_currentScan, pos, j]); - else - st.Append(" "); - System.Console.WriteLine("\rC2 error @{0}[{1:000}]{2};", CDImageLayout.TimeToString((uint)(sector + iSector)), i, st.ToString()); - return; - } + //for (int iSector = 0; iSector < Sectors2Read; iSector++) + //{ + // int pos = sector - _currentStart + iSector; + // if (_debugMessages) + // { + // StringBuilder st = new StringBuilder(); + // for (int i = 0; i < 294; i++) + // if (C2Data[pos, i] != 0) + // { + // for (int j = i; j < i + 23; j++) + // if (j < 294) + // st.AppendFormat("{0:X2}", C2Data[_currentScan, pos, j]); + // else + // st.Append(" "); + // System.Console.WriteLine("\rC2 error @{0}[{1:000}]{2};", CDImageLayout.TimeToString((uint)(sector + iSector)), i, st.ToString()); + // return; + // } + //for (int i = 0; i < 4 * 588; i++) // if (_currentData[pos * 4 * 588 + i] != realData[pos * 4 * 588 + i]) // { @@ -714,100 +735,50 @@ namespace CUETools.Ripper.SCSI // // st.Append(' '); // //System.Console.WriteLine("\rReal error @{0}[{1:000}]{2};", CDImageLayout.TimeToString((uint)(sector + iSector)), i, st.ToString()); // } - } - } + + // } + //} } - private unsafe void CorrectSectors0(int sector, int Sectors2Read) + private unsafe void CorrectSectors(int pass, int sector, int Sectors2Read, bool markErrors) { for (int iSector = 0; iSector < Sectors2Read; iSector++) { int pos = sector - _currentStart + iSector; + int avg = (pass + 1) * 3 / 2; + int er_limit = 2 + pass / 2; // allow 25% minority + // avg - pass + 1 + // p a l o + // 0 1 1 2 + // 2 4 3 3 + // 4 7 2 4 + // 6 10 5 + //16 25 10 + bool fError = false; for (int iPar = 0; iPar < 4 * 588; iPar++) { - byte bestValue = UserData[0, pos, iPar]; - _currentErrorsCount += (C2Data[0, pos, iPar >> 3] >> (iPar & 7)) & 1; - _currentData[pos * 4 * 588 + iPar] = bestValue; - } - } - } - - private unsafe void CorrectSectors1(int sector, int Sectors2Read) - { - for (int iSector = 0; iSector < Sectors2Read; iSector++) - { - int pos = sector - _currentStart + iSector; - for (int iPar = 0; iPar < 4 * 588; iPar++) - { - byte val1 = UserData[0, pos, iPar]; - byte val2 = UserData[1, pos, iPar]; - int err1 = (C2Data[0, pos, iPar >> 3] >> (iPar & 7)) & 1; - int err2 = (C2Data[1, pos, iPar >> 3] >> (iPar & 7)) & 1; - _currentErrorsCount += err1 | err2 | (val1 != val2 ? 1 : 0); - _currentData[pos * 4 * 588 + iPar] = err1 != 0 ? val2 : val1; - //if (_debugMessages && ((C2Data[_currentScan, pos, iPar >> 3] >> (iPar & 7)) & 1) != 0 && _currentErrorsCount < 10) - // System.Console.WriteLine("\rC2 error @{0}, byte {1:0000} ", CDImageLayout.TimeToString((uint)(sector + iSector)), iPar); - } - } - } - - private unsafe void CorrectSectors(int pass, int sector, int Sectors2Read, bool findWorst, bool markErrors) - { - if (pass == 0) - { - CorrectSectors0(sector, Sectors2Read); - return; - } - if (pass == 1) - { - CorrectSectors1(sector, Sectors2Read); - return; - } - short c2Score = 10; - fixed (short* valueScore = _valueScore) - { - fixed (byte* userData = UserData, c2Data = C2Data, qData = QData) - { - for (int iSector = 0; iSector < Sectors2Read; iSector++) + long val = UserData[pos, iPar]; + byte c2 = (byte)(C2Data[pos, iPar >> 3] >> ((iPar & 7) * 8)); + int bestValue = 0; + for (int i = 0; i < 8; i++) { - int pos = sector - _currentStart + iSector; - for (int iPar = 0; iPar < 4 * 588; iPar++) - { - int c2Bit = 0x80 >> (iPar % 8); - - ZeroMemory(valueScore, 256); - byte bestValue = 0; - short totalScore = 0; - for (int result = 0; result <= pass; result++) - { - int offs = (result * MSECTORS + pos) * 4 * 588 + iPar; - byte value = userData[offs]; - short score = (short)(1 + (((c2Data[offs >> 3] & c2Bit) == 0) ? c2Score : (short)0)); - valueScore[value] += score; - totalScore += score; - if (valueScore[value] > valueScore[bestValue]) - bestValue = value; - } -// if (_debugMessages && ((C2Data[_currentScan, pos, iPar >> 3] >> (iPar & 7)) & 1) != 0 && _currentErrorsCount < 10) -// System.Console.WriteLine("\rC2 error @{0}, byte {1:0000} ", CDImageLayout.TimeToString((uint)(sector + iSector)), iPar); - bool fError = valueScore[bestValue] <= _correctionQuality + c2Score + totalScore / 2; - if (fError) - _currentErrorsCount++; - _currentData[(sector - _currentStart + iSector) * 4 * 588 + iPar] = bestValue; - if (findWorst) - { - for (int result = 0; result <= pass; result++) - Quality[result] += Math.Min(0, valueScore[userData[(result * MSECTORS + pos) * 4 * 588 + iPar]] - c2Score - 2); - } - if (markErrors) - { - _errors[sector + iSector] |= fError; - _errorsCount += fError ? 1 : 0; - } - } + int sum = avg - ((int)(val & 0xff)); + int sig = sum >> 31; // bit value + fError |= (sum ^ sig) < er_limit; + bestValue += sig & (1 << i); + val >>= 8; } + _currentData[pos * 4 * 588 + iPar] = (byte)bestValue; + } + if (fError) + _currentErrorsCount++; + if (markErrors) + { + _errors[sector + iSector] |= fError; + _errorsCount += fError ? 1 : 0; } } + } //private unsafe int CorrectSectorsTest(int start, int end, int c2Score, byte[] realData, int worstScan) @@ -866,8 +837,6 @@ namespace CUETools.Ripper.SCSI public unsafe void PrefetchSector(int iSector) { - int nExtraPasses = MAXSCANS / 2 + _correctionQuality; - if (_currentStart == MSECTORS * (iSector / MSECTORS)) return; @@ -884,80 +853,44 @@ namespace CUETools.Ripper.SCSI // throw new Exception("read"); //correctFile.Close(); - fixed (byte* userData = UserData, c2Data = C2Data, qData = QData) + int max_scans = 64; + for (int pass = 0; pass <= max_scans; pass++) { - for (int pass = 0; pass < MAXSCANS + nExtraPasses; pass++) + DateTime PassTime = DateTime.Now, LastFetch = DateTime.Now; + _currentErrorsCount = 0; + + for (int sector = _currentStart; sector < _currentEnd; sector += m_max_sectors) { - DateTime PassTime = DateTime.Now, LastFetch = DateTime.Now; - if (pass < MAXSCANS) - _currentScan = pass; - else - { - _currentScan = 0; - for (int result = 1; result < MAXSCANS; result++) - if (Quality[result] < Quality[_currentScan]) - _currentScan = result; - //if (worstPass < 0) - // System.Console.WriteLine("bad scan"); - //else - // System.Console.WriteLine("{0}->{1}, {2}->{3}", _scanResults[worstPass].Quality, _currentScan.Quality, CorrectSectorsTest(_currentStart, _currentEnd, 10, realData, -1), CorrectSectorsTest(_currentStart, _currentEnd, 10, realData, worstPass)); - } - for (int result = 0; result < MAXSCANS; result++) - Quality[result] = 0; - _currentErrorsCount = 0; + int Sectors2Read = Math.Min(m_max_sectors, _currentEnd - sector); + int speed = pass == 5 ? 300 : pass == 6 ? 150 : pass == 7 ? 75 : 32500; // sectors per second + int msToSleep = 1000 * Sectors2Read / speed - (int)((DateTime.Now - LastFetch).TotalMilliseconds); - for (int sector = _currentStart; sector < _currentEnd; sector += m_max_sectors) - { - int Sectors2Read = Math.Min(m_max_sectors, _currentEnd - sector); - int speed = pass == 5 ? 300 : pass == 6 ? 150 : pass == 7 ? 75 : 32500; // sectors per second - int msToSleep = 1000 * Sectors2Read / speed - (int)((DateTime.Now - LastFetch).TotalMilliseconds); + //if (msToSleep > 0) Thread.Sleep(msToSleep); - //if (msToSleep > 0) Thread.Sleep(msToSleep); - LastFetch = DateTime.Now; - FetchSectors(sector, Sectors2Read, true, pass == 0); - //TimeSpan delay1 = DateTime.Now - LastFetch; - if (pass == 0) - ProcessSubchannel(sector, Sectors2Read, true); - //DateTime LastFetched = DateTime.Now; - CorrectSectors(Math.Min(pass, MAXSCANS - 1), sector, Sectors2Read, pass >= MAXSCANS - 1, pass == MAXSCANS - 1 + nExtraPasses); - PrintErrors(Math.Min(pass, MAXSCANS - 1), sector, Sectors2Read, /*realData*/null); - //TimeSpan delay2 = DateTime.Now - LastFetched; - //if (sector == _currentStart) - //System.Console.WriteLine("\n{0},{1}", delay1.TotalMilliseconds, delay2.TotalMilliseconds); - if (ReadProgress != null) - ReadProgress(this, new ReadProgressArgs(sector + Sectors2Read, pass, _currentStart, _currentEnd, _currentErrorsCount, PassTime)); + LastFetch = DateTime.Now; + if (pass == 0) + ClearSectors(sector, Sectors2Read); + FetchSectors(sector, Sectors2Read, true, pass == 0); + //TimeSpan delay1 = DateTime.Now - LastFetch; + if (pass == 0) + ProcessSubchannel(sector, Sectors2Read, true); + //DateTime LastFetched = DateTime.Now; + if ((pass & 1) == 0) + { + CorrectSectors(pass, sector, Sectors2Read, pass >= max_scans); + PrintErrors(pass, sector, Sectors2Read, /*realData*/null); } - //System.Console.WriteLine(); - //if (CorrectSectorsTest(start, _currentEnd, 10, realData) == 0) - // break; - //if (pass == MAXSCANS - 1 + nExtraPasses) - // break; - if (_currentErrorsCount == 0 && pass >= _correctionQuality) - break; - //if (_currentErrorsCount == 0 && pass >= _correctionQuality) - //{ - // bool syncOk = true; - // //if (pass == 0) - // //{ - // // ScanResults saved = _currentScan; - // // _currentScan = new ScanResults(_currentEnd - _currentStart, CB_AUDIO); - // // for (int sector = _currentStart; sector < _currentEnd && syncOk; sector += 7) - // // { - // // FetchSectors(sector, 2); - // // for (int i = 0; i < 2 * CB_AUDIO; i++) - // // if (_currentScan.Data[(sector - _currentStart) * CB_AUDIO + i] != saved.Data[(sector - _currentStart) * CB_AUDIO + i]) - // // { - // // System.Console.WriteLine("Lost Sync"); - // // syncOk = false; - // // break; - // // } - // // } - // // _currentScan = saved; - // //} - // if (syncOk) - // break; - //} + //TimeSpan delay2 = DateTime.Now - LastFetched; + //if (sector == _currentStart) + //System.Console.WriteLine("\n{0},{1}", delay1.TotalMilliseconds, delay2.TotalMilliseconds); + if (ReadProgress != null) + ReadProgress(this, new ReadProgressArgs(sector + Sectors2Read, pass, _currentStart, _currentEnd, _currentErrorsCount, PassTime)); } + //System.Console.WriteLine(); + //if (CorrectSectorsTest(start, _currentEnd, 10, realData) == 0) + // break; + if ((pass & 1) == 0 && pass >= _correctionQuality && _currentErrorsCount == 0) + break; } } diff --git a/CUETools.Ripper/CUETools.Ripper.csproj b/CUETools.Ripper/CUETools.Ripper.csproj index d154f3b..3cc381a 100644 --- a/CUETools.Ripper/CUETools.Ripper.csproj +++ b/CUETools.Ripper/CUETools.Ripper.csproj @@ -2,7 +2,7 @@ Debug AnyCPU - 8.0.50727 + 9.0.30729 2.0 {D2700165-3E77-4B28-928D-551F5FC11954} Library @@ -19,7 +19,7 @@ true full false - bin\Debug\ + ..\bin\Debug\ DEBUG;TRACE prompt 4 diff --git a/CUETools/CUETools.TestCodecs/AccurateRipVerifyTest.cs b/CUETools/CUETools.TestCodecs/AccurateRipVerifyTest.cs index a61afb9..07a3815 100644 --- a/CUETools/CUETools.TestCodecs/AccurateRipVerifyTest.cs +++ b/CUETools/CUETools.TestCodecs/AccurateRipVerifyTest.cs @@ -67,12 +67,12 @@ namespace CUETools.TestCodecs toc.AddTrack(new CDTrack(2, 68, 31, true, false)); toc.AddTrack(new CDTrack(3, 99, 37, true, false)); toc[1][0].Start = 0; - ar = new AccurateRipVerify(toc); + ar = new AccurateRipVerify(toc, null); toc2 = new CDImageLayout(); toc2.AddTrack(new CDTrack(1, 0, toc.AudioLength, true, false)); toc2.AddTrack(new CDTrack(2, toc.AudioLength, 750, true, false)); - ar2 = new AccurateRipVerify(toc2); + ar2 = new AccurateRipVerify(toc2, null); Random rnd = new Random(2314); for (int sector = 0; sector < toc2.AudioLength; sector++) diff --git a/CUETools/CUETools.TestParity/CDRepairDecodeTest.cs b/CUETools/CUETools.TestParity/CDRepairDecodeTest.cs index fd4e82d..38b758f 100644 --- a/CUETools/CUETools.TestParity/CDRepairDecodeTest.cs +++ b/CUETools/CUETools.TestParity/CDRepairDecodeTest.cs @@ -23,6 +23,7 @@ namespace CUETools.TestParity static byte[] wav2 = new byte[finalSampleCount * 4]; static byte[] wav3 = new byte[finalSampleCount * 4]; static byte[] parity; + static uint crc; const int offset = 48; //const int offset = 5 * 588 - 5; //const int offset = 2000; @@ -60,11 +61,12 @@ namespace CUETools.TestParity wav2[(int)(rnd.NextDouble() * (wav2.Length - 1))] = (byte)(rnd.NextDouble() * 255); AudioBuffer buff = new AudioBuffer(AudioPCMConfig.RedBook, 0); - CDRepairEncode encode = new CDRepairEncode(finalSampleCount, stride, npar, false); + CDRepairEncode encode = new CDRepairEncode(finalSampleCount, stride, npar, false, true); buff.Prepare(wav, finalSampleCount); encode.Write(buff); encode.Close(); parity = encode.Parity; + crc = encode.CRC; } // //Use ClassCleanup to run code after all tests in a class have run @@ -95,13 +97,15 @@ namespace CUETools.TestParity public void CDRepairDecodeOriginalTest() { AudioBuffer buff = new AudioBuffer(AudioPCMConfig.RedBook, 0); - CDRepairEncode decode = new CDRepairEncode(finalSampleCount, stride, npar, true); + CDRepairEncode decode = new CDRepairEncode(finalSampleCount, stride, npar, true, false); buff.Prepare(wav, finalSampleCount); decode.Write(buff); decode.Close(); - decode.VerifyParity(parity); - Assert.IsFalse(decode.HasErrors); - Assert.AreEqual(0, decode.ActualOffset, "wrong offset"); + int actualOffset; + bool hasErrors; + Assert.IsTrue(decode.FindOffset(npar, parity, 0, crc, out actualOffset, out hasErrors)); + Assert.IsFalse(hasErrors, "has errors"); + Assert.AreEqual(0, actualOffset, "wrong offset"); } /// @@ -111,14 +115,18 @@ namespace CUETools.TestParity public void CDRepairDecodeModifiedTest() { AudioBuffer buff = new AudioBuffer(AudioPCMConfig.RedBook, 0); - CDRepairEncode decode = new CDRepairEncode(finalSampleCount, stride, npar, true); + CDRepairEncode decode = new CDRepairEncode(finalSampleCount, stride, npar, true, false); buff.Prepare(wav2, finalSampleCount); decode.Write(buff); decode.Close(); - decode.VerifyParity(parity); - Assert.IsTrue(decode.HasErrors, "doesn't have errors"); - Assert.IsTrue(decode.CanRecover, "cannot recover"); - Assert.AreEqual(0, decode.ActualOffset, "wrong offset"); + int actualOffset; + bool hasErrors; + Assert.IsTrue(decode.FindOffset(npar, parity, 0, crc, out actualOffset, out hasErrors)); + Assert.IsTrue(hasErrors, "doesn't have errors"); + Assert.AreEqual(0, actualOffset, "wrong offset"); + CDRepairFix fix = decode.VerifyParity(parity, actualOffset); + Assert.IsTrue(fix.HasErrors, "doesn't have errors"); + Assert.IsTrue(fix.CanRecover, "cannot recover"); } /// @@ -128,14 +136,16 @@ namespace CUETools.TestParity public void CDRepairDecodePositiveOffsetTest() { AudioBuffer buff = new AudioBuffer(AudioPCMConfig.RedBook, 0); - CDRepairEncode decode = new CDRepairEncode(finalSampleCount, stride, npar, true); + CDRepairEncode decode = new CDRepairEncode(finalSampleCount, stride, npar, true, false); Array.Copy(wav, offset * 4, wav3, 0, (finalSampleCount - offset) * 4); buff.Prepare(wav3, finalSampleCount); decode.Write(buff); decode.Close(); - decode.VerifyParity(parity); - Assert.IsFalse(decode.HasErrors, "has errors"); - Assert.AreEqual(offset, decode.ActualOffset, "wrong offset"); + int actualOffset; + bool hasErrors; + Assert.IsTrue(decode.FindOffset(npar, parity, 0, crc, out actualOffset, out hasErrors)); + Assert.IsFalse(hasErrors, "has errors"); + Assert.AreEqual(offset, actualOffset, "wrong offset"); } /// @@ -145,15 +155,17 @@ namespace CUETools.TestParity public void CDRepairDecodeNegativeOffsetTest() { AudioBuffer buff = new AudioBuffer(AudioPCMConfig.RedBook, 0); - CDRepairEncode decode = new CDRepairEncode(finalSampleCount, stride, npar, true); + CDRepairEncode decode = new CDRepairEncode(finalSampleCount, stride, npar, true, false); buff.Prepare(new byte[offset * 4], offset); decode.Write(buff); buff.Prepare(wav, finalSampleCount - offset); decode.Write(buff); decode.Close(); - decode.VerifyParity(parity); - Assert.IsFalse(decode.HasErrors, "has errors"); - Assert.AreEqual(-offset, decode.ActualOffset, "wrong offset"); + int actualOffset; + bool hasErrors; + Assert.IsTrue(decode.FindOffset(npar, parity, 0, crc, out actualOffset, out hasErrors)); + Assert.IsFalse(hasErrors, "has errors"); + Assert.AreEqual(-offset, actualOffset, "wrong offset"); } /// @@ -163,15 +175,19 @@ namespace CUETools.TestParity public void CDRepairDecodePositiveOffsetErrorsTest() { AudioBuffer buff = new AudioBuffer(AudioPCMConfig.RedBook, 0); - CDRepairEncode decode = new CDRepairEncode(finalSampleCount, stride, npar, true); + CDRepairEncode decode = new CDRepairEncode(finalSampleCount, stride, npar, true, false); Array.Copy(wav2, offset * 4, wav3, 0, (finalSampleCount - offset) * 4); buff.Prepare(wav3, finalSampleCount); decode.Write(buff); decode.Close(); - decode.VerifyParity(parity); - Assert.IsTrue(decode.HasErrors, "doesn't have errors"); - Assert.IsTrue(decode.CanRecover, "cannot recover"); - Assert.AreEqual(offset, decode.ActualOffset, "wrong offset"); + int actualOffset; + bool hasErrors; + Assert.IsTrue(decode.FindOffset(npar, parity, 0, crc, out actualOffset, out hasErrors)); + Assert.IsTrue(hasErrors, "doesn't have errors"); + Assert.AreEqual(offset, actualOffset, "wrong offset"); + CDRepairFix fix = decode.VerifyParity(parity, actualOffset); + Assert.IsTrue(fix.HasErrors, "doesn't have errors"); + Assert.IsTrue(fix.CanRecover, "cannot recover"); } /// @@ -181,16 +197,20 @@ namespace CUETools.TestParity public void CDRepairDecodeNegativeOffsetErrorsTest() { AudioBuffer buff = new AudioBuffer(AudioPCMConfig.RedBook, 0); - CDRepairEncode decode = new CDRepairEncode(finalSampleCount, stride, npar, true); + CDRepairEncode decode = new CDRepairEncode(finalSampleCount, stride, npar, true, false); buff.Prepare(new byte[offset * 4], offset); decode.Write(buff); buff.Prepare(wav2, finalSampleCount - offset); decode.Write(buff); decode.Close(); - decode.VerifyParity(parity); - Assert.IsTrue(decode.HasErrors, "doesn't have errors"); - Assert.IsTrue(decode.CanRecover, "cannot recover"); - Assert.AreEqual(-offset, decode.ActualOffset, "wrong offset"); + int actualOffset; + bool hasErrors; + Assert.IsTrue(decode.FindOffset(npar, parity, 0, crc, out actualOffset, out hasErrors)); + Assert.IsTrue(hasErrors, "doesn't have errors"); + Assert.AreEqual(-offset, actualOffset, "wrong offset"); + CDRepairFix fix = decode.VerifyParity(parity, actualOffset); + Assert.IsTrue(fix.HasErrors, "doesn't have errors"); + Assert.IsTrue(fix.CanRecover, "cannot recover"); } } } diff --git a/CUETools/CUETools.TestParity/CDRepairEncodeTest.cs b/CUETools/CUETools.TestParity/CDRepairEncodeTest.cs index a23ef27..51139a3 100644 --- a/CUETools/CUETools.TestParity/CDRepairEncodeTest.cs +++ b/CUETools/CUETools.TestParity/CDRepairEncodeTest.cs @@ -90,7 +90,7 @@ namespace CUETools.TestParity public void CDRepairEncodeWriteTest() { AudioBuffer buff = new AudioBuffer(AudioPCMConfig.RedBook, 0); - CDRepairEncode encode = new CDRepairEncode(finalSampleCount, stride, npar, false); + CDRepairEncode encode = new CDRepairEncode(finalSampleCount, stride, npar, false, true); buff.Prepare(wav, finalSampleCount); encode.Write(buff); encode.Close(); diff --git a/CUETools/CUETools.TestParity/CDRepairTest.cs b/CUETools/CUETools.TestParity/CDRepairTest.cs index 1818694..dd81ef0 100644 --- a/CUETools/CUETools.TestParity/CDRepairTest.cs +++ b/CUETools/CUETools.TestParity/CDRepairTest.cs @@ -27,6 +27,8 @@ namespace CUETools.TestParity static uint crc; static CDRepairEncode decode; static CDRepairEncode decode2; + static CDRepairFix fix; + static CDRepairFix fix2; const int offset = 48; /// @@ -60,26 +62,31 @@ namespace CUETools.TestParity wav2[(int)(rnd.NextDouble() * (wav2.Length - 1))] = (byte)(rnd.NextDouble() * 255); AudioBuffer buff = new AudioBuffer(AudioPCMConfig.RedBook, 0); - CDRepairEncode encode = new CDRepairEncode(finalSampleCount, stride, npar, false); + CDRepairEncode encode = new CDRepairEncode(finalSampleCount, stride, npar, false, true); buff.Prepare(wav, finalSampleCount); encode.Write(buff); encode.Close(); parity = encode.Parity; crc = encode.CRC; - decode = new CDRepairEncode(finalSampleCount, stride, npar, true); + decode = new CDRepairEncode(finalSampleCount, stride, npar, true, false); buff.Prepare(wav2, finalSampleCount); decode.Write(buff); decode.Close(); - decode.VerifyParity(parity); - decode2 = new CDRepairEncode(finalSampleCount, stride, npar, true); + int actualOffset; + bool hasErrors; + decode.FindOffset(npar, parity, 0, crc, out actualOffset, out hasErrors); + fix = decode.VerifyParity(parity, actualOffset); + + decode2 = new CDRepairEncode(finalSampleCount, stride, npar, true, false); buff.Prepare(new byte[offset * 4], offset); decode2.Write(buff); buff.Prepare(wav2, finalSampleCount - offset); decode2.Write(buff); decode2.Close(); - decode2.VerifyParity(parity); + decode2.FindOffset(npar, parity, 0, crc, out actualOffset, out hasErrors); + fix2 = decode2.VerifyParity(parity, actualOffset); } //Use ClassCleanup to run code after all tests in a class have run @@ -108,12 +115,11 @@ namespace CUETools.TestParity [TestMethod()] public void CDRepairFixTest() { - Assert.IsTrue(decode.HasErrors); - Assert.IsTrue(decode.CanRecover); - Assert.AreEqual(0, decode.ActualOffset, "wrong offset"); + Assert.IsTrue(fix.HasErrors); + Assert.IsTrue(fix.CanRecover); + Assert.AreEqual(0, fix.ActualOffset, "wrong offset"); AudioBuffer buff = new AudioBuffer(AudioPCMConfig.RedBook, 0); - CDRepairFix fix = new CDRepairFix(decode); buff.Prepare(wav2, finalSampleCount); fix.Write(buff); fix.Close(); @@ -127,19 +133,18 @@ namespace CUETools.TestParity [TestMethod()] public void CDRepairFixWithOffsetTest() { - Assert.IsTrue(decode2.HasErrors); - Assert.IsTrue(decode2.CanRecover); - Assert.AreEqual(-offset, decode2.ActualOffset, "wrong offset"); + Assert.IsTrue(fix2.HasErrors); + Assert.IsTrue(fix2.CanRecover); + Assert.AreEqual(-offset, fix2.ActualOffset, "wrong offset"); AudioBuffer buff = new AudioBuffer(AudioPCMConfig.RedBook, 0); - CDRepairFix fix = new CDRepairFix(decode2); buff.Prepare(new byte[offset * 4], offset); - fix.Write(buff); + fix2.Write(buff); buff.Prepare(wav2, finalSampleCount - offset); - fix.Write(buff); - fix.Close(); + fix2.Write(buff); + fix2.Close(); - Assert.AreEqual(crc, fix.CRC); + Assert.AreEqual(crc, fix2.CRC); } } } diff --git a/CUETools/CUETools.csproj b/CUETools/CUETools.csproj index 3dc5776..c8e10fc 100644 --- a/CUETools/CUETools.csproj +++ b/CUETools/CUETools.csproj @@ -2,7 +2,7 @@ Debug AnyCPU - 8.0.50727 + 9.0.30729 2.0 {EF351583-A9CD-4530-92C3-20AC02136BC2} WinExe @@ -15,6 +15,12 @@ false true true + LocalIntranet + + + 2.0 + + ftp://cuetools.net/cuetools.net/install/cuetools/ true Web @@ -31,21 +37,16 @@ CUETools true publish.htm - 2.0.3.%2a - true - LocalIntranet - - - 2.0 7 - - + 2.0.3.%2a + false + true true full false - bin\Debug\ + ..\bin\Debug\ DEBUG;TRACE prompt 4 @@ -227,6 +228,10 @@ {14EE067E-C218-4625-9540-2361AB27C4A6} CUETools.Compression + + {AA2A9A7E-45FB-4632-AD85-85B0E556F818} + CUETools.CTDB + {4911BD82-49EF-4858-8B51-5394F86739A4} CUETools.Processor @@ -264,6 +269,8 @@ + + @@ -301,11 +308,31 @@ + + False + .NET Framework Client Profile + false + False - .NET Framework 2.0 + .NET Framework 2.0 %28x86%29 true + + False + .NET Framework 3.0 %28x86%29 + false + + + False + .NET Framework 3.5 + false + + + False + .NET Framework 3.5 SP1 + false + False Visual C++ Runtime Libraries %28x86%29 @@ -320,6 +347,7 @@ Include + True Satellite @@ -329,6 +357,7 @@ Include + True Satellite diff --git a/CUETools/CUETools.sln b/CUETools/CUETools.sln index c3e17fa..eb1e14b 100644 --- a/CUETools/CUETools.sln +++ b/CUETools/CUETools.sln @@ -143,6 +143,16 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CUETools.Compression.Zip", EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CUETools.Ripper", "..\CUETools.Ripper\CUETools.Ripper.csproj", "{D2700165-3E77-4B28-928D-551F5FC11954}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestRipper", "TestRipper\TestRipper.csproj", "{5C8B61C0-BC3D-4316-B8A7-419D55BB5796}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CUETools.Parity", "..\CUETools.Parity\CUETools.Parity.csproj", "{ECEB839C-171B-4535-958F-9899310A0342}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CUETools.TestParity", "CUETools.TestParity\CUETools.TestParity.csproj", "{6C74652F-1EF4-459E-84F4-99D93D3D17DA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CUETools.CDRepair", "..\CUETools.CDRepair\CUETools.CDRepair.csproj", "{C4869B37-EBB1-47BB-9406-B1209BEAB84B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CUETools.CTDB", "..\CUETools.CTDB\CUETools.CTDB.csproj", "{AA2A9A7E-45FB-4632-AD85-85B0E556F818}" +EndProject Global GlobalSection(TestCaseManagementSettings) = postSolution CategoryFile = CUETools1.vsmdi @@ -510,6 +520,46 @@ Global {D2700165-3E77-4B28-928D-551F5FC11954}.Release|Any CPU.Build.0 = Release|Any CPU {D2700165-3E77-4B28-928D-551F5FC11954}.Release|Win32.ActiveCfg = Release|Any CPU {D2700165-3E77-4B28-928D-551F5FC11954}.Release|x64.ActiveCfg = Release|Any CPU + {5C8B61C0-BC3D-4316-B8A7-419D55BB5796}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5C8B61C0-BC3D-4316-B8A7-419D55BB5796}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5C8B61C0-BC3D-4316-B8A7-419D55BB5796}.Debug|Win32.ActiveCfg = Debug|Any CPU + {5C8B61C0-BC3D-4316-B8A7-419D55BB5796}.Debug|x64.ActiveCfg = Debug|Any CPU + {5C8B61C0-BC3D-4316-B8A7-419D55BB5796}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5C8B61C0-BC3D-4316-B8A7-419D55BB5796}.Release|Any CPU.Build.0 = Release|Any CPU + {5C8B61C0-BC3D-4316-B8A7-419D55BB5796}.Release|Win32.ActiveCfg = Release|Any CPU + {5C8B61C0-BC3D-4316-B8A7-419D55BB5796}.Release|x64.ActiveCfg = Release|Any CPU + {ECEB839C-171B-4535-958F-9899310A0342}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {ECEB839C-171B-4535-958F-9899310A0342}.Debug|Any CPU.Build.0 = Debug|Any CPU + {ECEB839C-171B-4535-958F-9899310A0342}.Debug|Win32.ActiveCfg = Debug|Any CPU + {ECEB839C-171B-4535-958F-9899310A0342}.Debug|x64.ActiveCfg = Debug|Any CPU + {ECEB839C-171B-4535-958F-9899310A0342}.Release|Any CPU.ActiveCfg = Release|Any CPU + {ECEB839C-171B-4535-958F-9899310A0342}.Release|Any CPU.Build.0 = Release|Any CPU + {ECEB839C-171B-4535-958F-9899310A0342}.Release|Win32.ActiveCfg = Release|Any CPU + {ECEB839C-171B-4535-958F-9899310A0342}.Release|x64.ActiveCfg = Release|Any CPU + {6C74652F-1EF4-459E-84F4-99D93D3D17DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6C74652F-1EF4-459E-84F4-99D93D3D17DA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6C74652F-1EF4-459E-84F4-99D93D3D17DA}.Debug|Win32.ActiveCfg = Debug|Any CPU + {6C74652F-1EF4-459E-84F4-99D93D3D17DA}.Debug|x64.ActiveCfg = Debug|Any CPU + {6C74652F-1EF4-459E-84F4-99D93D3D17DA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6C74652F-1EF4-459E-84F4-99D93D3D17DA}.Release|Any CPU.Build.0 = Release|Any CPU + {6C74652F-1EF4-459E-84F4-99D93D3D17DA}.Release|Win32.ActiveCfg = Release|Any CPU + {6C74652F-1EF4-459E-84F4-99D93D3D17DA}.Release|x64.ActiveCfg = Release|Any CPU + {C4869B37-EBB1-47BB-9406-B1209BEAB84B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C4869B37-EBB1-47BB-9406-B1209BEAB84B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C4869B37-EBB1-47BB-9406-B1209BEAB84B}.Debug|Win32.ActiveCfg = Debug|Any CPU + {C4869B37-EBB1-47BB-9406-B1209BEAB84B}.Debug|x64.ActiveCfg = Debug|Any CPU + {C4869B37-EBB1-47BB-9406-B1209BEAB84B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C4869B37-EBB1-47BB-9406-B1209BEAB84B}.Release|Any CPU.Build.0 = Release|Any CPU + {C4869B37-EBB1-47BB-9406-B1209BEAB84B}.Release|Win32.ActiveCfg = Release|Any CPU + {C4869B37-EBB1-47BB-9406-B1209BEAB84B}.Release|x64.ActiveCfg = Release|Any CPU + {AA2A9A7E-45FB-4632-AD85-85B0E556F818}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AA2A9A7E-45FB-4632-AD85-85B0E556F818}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AA2A9A7E-45FB-4632-AD85-85B0E556F818}.Debug|Win32.ActiveCfg = Debug|Any CPU + {AA2A9A7E-45FB-4632-AD85-85B0E556F818}.Debug|x64.ActiveCfg = Debug|Any CPU + {AA2A9A7E-45FB-4632-AD85-85B0E556F818}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AA2A9A7E-45FB-4632-AD85-85B0E556F818}.Release|Any CPU.Build.0 = Release|Any CPU + {AA2A9A7E-45FB-4632-AD85-85B0E556F818}.Release|Win32.ActiveCfg = Release|Any CPU + {AA2A9A7E-45FB-4632-AD85-85B0E556F818}.Release|x64.ActiveCfg = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -546,6 +596,8 @@ Global {DDE1EA77-637C-4D5F-96F3-1328BC45CE80} = {93B7AE1D-DEF6-4A04-A222-5CDE09DF262D} {04945FB2-8410-4F14-8262-2ED18DCDACD6} = {D9D97BB6-002F-4858-8EF2-49B4C4C4DDB4} {A430AD28-B76A-4ED0-AF7D-D13B8969297F} = {D9D97BB6-002F-4858-8EF2-49B4C4C4DDB4} + {5C8B61C0-BC3D-4316-B8A7-419D55BB5796} = {D9D97BB6-002F-4858-8EF2-49B4C4C4DDB4} + {6C74652F-1EF4-459E-84F4-99D93D3D17DA} = {D9D97BB6-002F-4858-8EF2-49B4C4C4DDB4} {B75FA7AD-968E-4990-B342-1B4B17C850DF} = {B36BE134-D85A-437E-AB61-2DA1CCDE06C1} {F2DFEB00-BB35-4665-85EA-CB8C7729A6B7} = {B36BE134-D85A-437E-AB61-2DA1CCDE06C1} {A05B6AA6-0EC3-495D-BCC4-ECE1210071A8} = {B36BE134-D85A-437E-AB61-2DA1CCDE06C1} diff --git a/CUETools/Properties/Resources.Designer.cs b/CUETools/Properties/Resources.Designer.cs index af7204a..fda7f38 100644 --- a/CUETools/Properties/Resources.Designer.cs +++ b/CUETools/Properties/Resources.Designer.cs @@ -88,6 +88,20 @@ namespace JDP.Properties { } } + internal static System.Drawing.Icon cdrepair { + get { + object obj = ResourceManager.GetObject("cdrepair", resourceCulture); + return ((System.Drawing.Icon)(obj)); + } + } + + internal static System.Drawing.Bitmap cdrepair1 { + get { + object obj = ResourceManager.GetObject("cdrepair1", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + internal static System.Drawing.Bitmap cog { get { object obj = ResourceManager.GetObject("cog", resourceCulture); diff --git a/CUETools/Properties/Resources.resx b/CUETools/Properties/Resources.resx index 1343c04..576e230 100644 --- a/CUETools/Properties/Resources.resx +++ b/CUETools/Properties/Resources.resx @@ -238,4 +238,10 @@ ..\Resources\delete.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Resources\cdrepair.ico;System.Drawing.Icon, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\cdrepair.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + \ No newline at end of file diff --git a/CUETools/Resources/cdrepair.ico b/CUETools/Resources/cdrepair.ico new file mode 100644 index 0000000..6d8bdc2 Binary files /dev/null and b/CUETools/Resources/cdrepair.ico differ diff --git a/CUETools/Resources/cdrepair.png b/CUETools/Resources/cdrepair.png new file mode 100644 index 0000000..2f199b4 Binary files /dev/null and b/CUETools/Resources/cdrepair.png differ diff --git a/CUETools/TestRipper/CDDriveReaderTest.cs b/CUETools/TestRipper/CDDriveReaderTest.cs new file mode 100644 index 0000000..584fc6c --- /dev/null +++ b/CUETools/TestRipper/CDDriveReaderTest.cs @@ -0,0 +1,152 @@ +using System; +using System.Text; +using System.Collections.Generic; +using CUETools.Codecs; +using CUETools.Ripper; +using CUETools.Ripper.SCSI; +using Microsoft.VisualStudio.TestTools.UnitTesting; +namespace TestRipper +{ + + + /// + ///This is a test class for CDDriveReaderTest and is intended + ///to contain all CDDriveReaderTest Unit Tests + /// + [TestClass()] + public class CDDriveReaderTest + { + + + private TestContext testContextInstance; + + /// + ///Gets or sets the test context which provides + ///information about and functionality for the current test run. + /// + public TestContext TestContext + { + get + { + return testContextInstance; + } + set + { + testContextInstance = value; + } + } + + const int pass = 16; + const int Sectors2Read = 10000; + const int bit_weight = 3; + const int c2_weight = 1; + + bool markErrors = true; + int _currentStart = 0, _realErrors = 0; + byte[] _currentData = new byte[Sectors2Read * 4 * 588]; + + static long[,] UserData = new long[Sectors2Read, 4 * 588]; + static long[,] C2Data = new long[Sectors2Read, 4 * 588 / 8]; + static byte[] _realData = new byte[Sectors2Read * 4 * 588]; + static long[] byte2long = new long[256]; + + #region Additional test attributes + // + //You can use the following additional attributes as you write your tests: + // + //Use ClassInitialize to run code before running the first test in the class + [ClassInitialize()] + public static void MyClassInitialize(TestContext testContext) + { + for (long i = 0; i < 256; i++) + { + long bl = 0; + for (int b = 0; b < 8; b++) + bl += ((i >> b) & 1) << (b << 3); + byte2long[i] = bl; + } + + Random rnd = new Random(2314); + rnd.NextBytes(_realData); + + for (int p = 0; p <= pass; p++) + for (int iSector = 0; iSector < Sectors2Read; iSector++) + for (int iPar = 0; iPar < 4 * 588; iPar++) + { + bool error = rnd.NextDouble() < 0.2; + byte val = error ? (byte)rnd.Next(255) : _realData[iSector * 4 * 588 + iPar]; + UserData[iSector, iPar] += byte2long[val] * bit_weight; + if (error && rnd.NextDouble() < 0.5) + { + C2Data[iSector, iPar >> 3] += (iPar & 7) * 8; + UserData[iSector, iPar] += 0x0101010101010101 * (bit_weight / 2) + byte2long[val] * (c2_weight - bit_weight); + } + } + } + // + //Use ClassCleanup to run code after all tests in a class have run + //[ClassCleanup()] + //public static void MyClassCleanup() + //{ + //} + // + //Use TestInitialize to run code before running each test + [TestInitialize()] + public void MyTestInitialize() + { + } + // + //Use TestCleanup to run code after each test has run + //[TestCleanup()] + //public void MyTestCleanup() + //{ + //} + // + #endregion + + + /// + ///A test for CorrectSectors + /// + [TestMethod()] + [DeploymentItem("CUETools.Ripper.SCSI.dll")] + public void CorrectSectorsTest() + { + int _currentErrorsCount = 0; + int sector = 0; + + for (int iSector = 0; iSector < Sectors2Read; iSector++) + { + int pos = sector - _currentStart + iSector; + int avg = (pass + 1) * bit_weight / 2; + int c2_limit = pass / 3; // + int er_limit = avg - pass; // allow 33% minority + for (int iPar = 0; iPar < 4 * 588; iPar++) + { + long val = UserData[pos, iPar]; + byte c2 = (byte)(C2Data[pos, iPar >> 3] >> ((iPar & 7) * 8)); + int bestValue = 0; + for (int i = 0; i < 8; i++) + { + int sum = avg - ((int)(val & 0xff)); + int sig = sum >> 31; // bit value + if ((sum ^ sig) < er_limit) _currentErrorsCount++; + bestValue += sig & (1 << i); + val >>= 8; + } + //if (c2 > c2_limit) + //_currentErrorsCount++; + _currentData[pos * 4 * 588 + iPar] = (byte)bestValue; + } + } + for (int p = 0; p <= pass; p++) + for (int iSector = 0; iSector < Sectors2Read; iSector++) + for (int iPar = 0; iPar < 4 * 588; iPar++) + if (_realData[iSector * 4 * 588 + iPar] != _currentData[iSector * 4 * 588 + iPar]) + _realErrors++; + Assert.AreEqual(0, _realErrors, "0 != _realErrors; _currentErrorsCount == " + _currentErrorsCount.ToString()); + //CollectionAssert.AreEqual(_realData, _currentData, "_realData != _currentData"); + Assert.AreEqual(0, _currentErrorsCount, "_currentErrorsCount != 0"); + } + } +} diff --git a/CUETools/TestRipper/Properties/AssemblyInfo.cs b/CUETools/TestRipper/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..ce13457 --- /dev/null +++ b/CUETools/TestRipper/Properties/AssemblyInfo.cs @@ -0,0 +1,35 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("TestRipper")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft")] +[assembly: AssemblyProduct("TestRipper")] +[assembly: AssemblyCopyright("Copyright © Microsoft 2010")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM componenets. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("18afe9af-ef9e-48f4-87cf-76b1ba9f295d")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/CUETools/TestRipper/TestRipper.csproj b/CUETools/TestRipper/TestRipper.csproj new file mode 100644 index 0000000..a479ff8 --- /dev/null +++ b/CUETools/TestRipper/TestRipper.csproj @@ -0,0 +1,85 @@ + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {5C8B61C0-BC3D-4316-B8A7-419D55BB5796} + Library + Properties + TestRipper + TestRipper + v2.0 + 512 + {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + ..\bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + {F2DFEB00-BB35-4665-85EA-CB8C7729A6B7} + Bwg.Logging + + + {A05B6AA6-0EC3-495D-BCC4-ECE1210071A8} + Bwg.Scsi + + + {1DD41038-D885-46C5-8DDE-E0B82F066584} + CUETools.CDImage + + + {6458A13A-30EF-45A9-9D58-E5031B17BEE2} + CUETools.Codecs + + + {8CF07381-BEA2-4AFC-B3DD-9B2F21C65A3A} + CUETools.Ripper.SCSI + + + {D2700165-3E77-4B28-928D-551F5FC11954} + CUETools.Ripper + + + + + + + + + + + \ No newline at end of file diff --git a/CUETools/TestRipper/app.config b/CUETools/TestRipper/app.config new file mode 100644 index 0000000..b7db281 --- /dev/null +++ b/CUETools/TestRipper/app.config @@ -0,0 +1,3 @@ + + + diff --git a/CUETools/frmCUETools.Designer.cs b/CUETools/frmCUETools.Designer.cs index 5ad111d..aca7f0d 100644 --- a/CUETools/frmCUETools.Designer.cs +++ b/CUETools/frmCUETools.Designer.cs @@ -28,8 +28,9 @@ namespace JDP { this.toolStripContainer1 = new System.Windows.Forms.ToolStripContainer(); this.statusStrip1 = new System.Windows.Forms.StatusStrip(); this.toolStripStatusLabel1 = new System.Windows.Forms.ToolStripStatusLabel(); - this.toolStripStatusLabelAR = new System.Windows.Forms.ToolStripStatusLabel(); this.toolStripStatusLabelProcessed = new System.Windows.Forms.ToolStripStatusLabel(); + this.toolStripStatusLabelCTDB = new System.Windows.Forms.ToolStripStatusLabel(); + this.toolStripStatusLabelAR = new System.Windows.Forms.ToolStripStatusLabel(); this.toolStripProgressBar1 = new System.Windows.Forms.ToolStripProgressBar(); this.toolStripProgressBar2 = new System.Windows.Forms.ToolStripProgressBar(); this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); @@ -51,6 +52,8 @@ namespace JDP { this.toolStripMenuItemCorrectorModeLocateFiles = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripMenuItemCorrectorModeChangeExtension = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripDropDownButtonCorrectorFormat = new System.Windows.Forms.ToolStripDropDownButton(); + this.tableLayoutPanelVerifyMode = new System.Windows.Forms.TableLayoutPanel(); + this.checkBoxVerifyUseCDRepair = new System.Windows.Forms.CheckBox(); this.grpAudioOutput = new System.Windows.Forms.GroupBox(); this.labelEncoderMaxMode = new System.Windows.Forms.Label(); this.labelEncoderMinMode = new System.Windows.Forms.Label(); @@ -130,6 +133,7 @@ namespace JDP { this.groupBoxMode.SuspendLayout(); this.tableLayoutPanelCUEStyle.SuspendLayout(); this.toolStripCorrectorFormat.SuspendLayout(); + this.tableLayoutPanelVerifyMode.SuspendLayout(); this.grpAudioOutput.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.trackBarEncoderMode)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.pictureBoxMotd)).BeginInit(); @@ -177,8 +181,9 @@ namespace JDP { resources.ApplyResources(this.statusStrip1, "statusStrip1"); this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.toolStripStatusLabel1, - this.toolStripStatusLabelAR, this.toolStripStatusLabelProcessed, + this.toolStripStatusLabelCTDB, + this.toolStripStatusLabelAR, this.toolStripProgressBar1, this.toolStripProgressBar2}); this.statusStrip1.Name = "statusStrip1"; @@ -190,13 +195,6 @@ namespace JDP { resources.ApplyResources(this.toolStripStatusLabel1, "toolStripStatusLabel1"); this.toolStripStatusLabel1.Spring = true; // - // toolStripStatusLabelAR - // - resources.ApplyResources(this.toolStripStatusLabelAR, "toolStripStatusLabelAR"); - this.toolStripStatusLabelAR.Image = global::JDP.Properties.Resources.AR; - this.toolStripStatusLabelAR.Name = "toolStripStatusLabelAR"; - this.toolStripStatusLabelAR.Padding = new System.Windows.Forms.Padding(0, 0, 5, 0); - // // toolStripStatusLabelProcessed // this.toolStripStatusLabelProcessed.BorderSides = ((System.Windows.Forms.ToolStripStatusLabelBorderSides)((((System.Windows.Forms.ToolStripStatusLabelBorderSides.Left | System.Windows.Forms.ToolStripStatusLabelBorderSides.Top) @@ -206,6 +204,27 @@ namespace JDP { this.toolStripStatusLabelProcessed.Name = "toolStripStatusLabelProcessed"; resources.ApplyResources(this.toolStripStatusLabelProcessed, "toolStripStatusLabelProcessed"); // + // toolStripStatusLabelCTDB + // + this.toolStripStatusLabelCTDB.BorderSides = ((System.Windows.Forms.ToolStripStatusLabelBorderSides)((((System.Windows.Forms.ToolStripStatusLabelBorderSides.Left | System.Windows.Forms.ToolStripStatusLabelBorderSides.Top) + | System.Windows.Forms.ToolStripStatusLabelBorderSides.Right) + | System.Windows.Forms.ToolStripStatusLabelBorderSides.Bottom))); + this.toolStripStatusLabelCTDB.BorderStyle = System.Windows.Forms.Border3DStyle.SunkenOuter; + resources.ApplyResources(this.toolStripStatusLabelCTDB, "toolStripStatusLabelCTDB"); + this.toolStripStatusLabelCTDB.Image = global::JDP.Properties.Resources.cdrepair1; + this.toolStripStatusLabelCTDB.Name = "toolStripStatusLabelCTDB"; + // + // toolStripStatusLabelAR + // + this.toolStripStatusLabelAR.BorderSides = ((System.Windows.Forms.ToolStripStatusLabelBorderSides)((((System.Windows.Forms.ToolStripStatusLabelBorderSides.Left | System.Windows.Forms.ToolStripStatusLabelBorderSides.Top) + | System.Windows.Forms.ToolStripStatusLabelBorderSides.Right) + | System.Windows.Forms.ToolStripStatusLabelBorderSides.Bottom))); + this.toolStripStatusLabelAR.BorderStyle = System.Windows.Forms.Border3DStyle.SunkenOuter; + resources.ApplyResources(this.toolStripStatusLabelAR, "toolStripStatusLabelAR"); + this.toolStripStatusLabelAR.Image = global::JDP.Properties.Resources.AR; + this.toolStripStatusLabelAR.Name = "toolStripStatusLabelAR"; + this.toolStripStatusLabelAR.Padding = new System.Windows.Forms.Padding(0, 0, 5, 0); + // // toolStripProgressBar1 // this.toolStripProgressBar1.AutoToolTip = true; @@ -287,6 +306,7 @@ namespace JDP { // this.groupBoxMode.Controls.Add(this.tableLayoutPanelCUEStyle); this.groupBoxMode.Controls.Add(this.toolStripCorrectorFormat); + this.groupBoxMode.Controls.Add(this.tableLayoutPanelVerifyMode); resources.ApplyResources(this.groupBoxMode, "groupBoxMode"); this.groupBoxMode.Name = "groupBoxMode"; this.groupBoxMode.TabStop = false; @@ -409,6 +429,20 @@ namespace JDP { this.toolStripDropDownButtonCorrectorFormat.Name = "toolStripDropDownButtonCorrectorFormat"; this.toolStripDropDownButtonCorrectorFormat.DropDownItemClicked += new System.Windows.Forms.ToolStripItemClickedEventHandler(this.toolStripDropDownButtonCorrectorFormat_DropDownItemClicked); // + // tableLayoutPanelVerifyMode + // + resources.ApplyResources(this.tableLayoutPanelVerifyMode, "tableLayoutPanelVerifyMode"); + this.tableLayoutPanelVerifyMode.Controls.Add(this.checkBoxVerifyUseCDRepair, 0, 0); + this.tableLayoutPanelVerifyMode.Name = "tableLayoutPanelVerifyMode"; + this.toolTip1.SetToolTip(this.tableLayoutPanelVerifyMode, resources.GetString("tableLayoutPanelVerifyMode.ToolTip")); + // + // checkBoxVerifyUseCDRepair + // + resources.ApplyResources(this.checkBoxVerifyUseCDRepair, "checkBoxVerifyUseCDRepair"); + this.checkBoxVerifyUseCDRepair.Image = global::JDP.Properties.Resources.cdrepair1; + this.checkBoxVerifyUseCDRepair.Name = "checkBoxVerifyUseCDRepair"; + this.checkBoxVerifyUseCDRepair.UseVisualStyleBackColor = true; + // // grpAudioOutput // this.grpAudioOutput.Controls.Add(this.labelEncoderMaxMode); @@ -997,6 +1031,8 @@ namespace JDP { this.tableLayoutPanelCUEStyle.PerformLayout(); this.toolStripCorrectorFormat.ResumeLayout(false); this.toolStripCorrectorFormat.PerformLayout(); + this.tableLayoutPanelVerifyMode.ResumeLayout(false); + this.tableLayoutPanelVerifyMode.PerformLayout(); this.grpAudioOutput.ResumeLayout(false); this.grpAudioOutput.PerformLayout(); ((System.ComponentModel.ISupportInitialize)(this.trackBarEncoderMode)).EndInit(); @@ -1118,6 +1154,9 @@ namespace JDP { private System.Windows.Forms.CheckBox checkBoxUseMusicBrainz; private System.Windows.Forms.CheckBox checkBoxUseAccurateRip; private System.Windows.Forms.CheckBox checkBoxUseFreeDb; + private System.Windows.Forms.TableLayoutPanel tableLayoutPanelVerifyMode; + private System.Windows.Forms.CheckBox checkBoxVerifyUseCDRepair; + private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabelCTDB; } } diff --git a/CUETools/frmCUETools.cs b/CUETools/frmCUETools.cs index 9068ae9..aa69769 100644 --- a/CUETools/frmCUETools.cs +++ b/CUETools/frmCUETools.cs @@ -479,6 +479,7 @@ namespace JDP { string status = null; bool outputAudio = action == CUEAction.Encode && audioEncoderType != AudioEncoderType.NoAudio; bool useAR = action == CUEAction.Verify || (outputAudio && checkBoxUseAccurateRip.Checked); + bool useCUEToolsDB = action == CUEAction.Verify && checkBoxVerifyUseCDRepair.Checked; try { @@ -704,7 +705,7 @@ namespace JDP { } else { - if (Directory.Exists(pathIn)) + if (Directory.Exists(pathIn) && !IsCDROM(pathIn)) { if (_batchPaths.Count == 0) throw new Exception("is a directory"); @@ -742,6 +743,10 @@ namespace JDP { cueSheet.DataTrackLengthMSF = txtDataTrackLength.Text; cueSheet.UseAccurateRip(); } + if (useCUEToolsDB) + { + cueSheet.UseCUEToolsDB(); + } if (_batchPaths.Count == 0 && action == CUEAction.Encode) { @@ -751,9 +756,16 @@ namespace JDP { this.Invoke((MethodInvoker)delegate() { - toolStripStatusLabelAR.Visible = useAR;// && cueSheet.ArVerify.ARStatus == null; - toolStripStatusLabelAR.Text = cueSheet.ArVerify.ARStatus == null ? cueSheet.ArVerify.WorstTotal().ToString() : "?"; + toolStripStatusLabelAR.Enabled = cueSheet.ArVerify.ARStatus == null; + toolStripStatusLabelAR.Visible = useAR; + toolStripStatusLabelAR.Text = cueSheet.ArVerify.ARStatus == null ? cueSheet.ArVerify.WorstTotal().ToString() : ""; toolStripStatusLabelAR.ToolTipText = "AccurateRip: " + (cueSheet.ArVerify.ARStatus ?? "found") + "."; + + toolStripStatusLabelCTDB.Enabled = cueSheet.CTDB.DBStatus == null; + toolStripStatusLabelCTDB.Visible = useCUEToolsDB; + toolStripStatusLabelCTDB.Text = cueSheet.CTDB.DBStatus == null ? cueSheet.CTDB.Total.ToString() : ""; + toolStripStatusLabelCTDB.ToolTipText = "CUETools DB: " + (cueSheet.CTDB.DBStatus ?? "found") + "."; + if (releases != null) { frmChoice dlg = new frmChoice(); @@ -808,7 +820,34 @@ namespace JDP { else status = cueSheet.ExecuteScript(script); - //if (_batchPaths.Count > 0) + //if (useCUEToolsDB) + //{ + // if (cueSheet.CTDB.AccResult == HttpStatusCode.NotFound && + // cueSheet.ArVerify.ARStatus == null && + // cueSheet.ArVerify.WorstConfidence() > 2 + // ) + // { + // this.Invoke((MethodInvoker)delegate() + // { + // dlgRes = MessageBox.Show(this, "Disc is not present in CUETools Database, " + + // "do you want to submit it?", "Overwrite?", (_batchPaths.Count == 0) ? + // MessageBoxButtons.YesNo : MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question); + // if (dlgRes == DialogResult.Cancel) + // SetupControls(false); + // }); + // if (dlgRes == DialogResult.Cancel) + // { + // cueSheet.Close(); + // return; + // } + // if (dlgRes == DialogResult.Yes) + // { + // cueSheet.CTDB.Submit((int)cueSheet.ArVerify.WorstConfidence(), (int)cueSheet.ArVerify.WorstTotal()); + // } + // } + //} + + if (_batchPaths.Count > 0) { _batchProcessed++; BatchLog("{0}.", pathIn, status); @@ -836,7 +875,7 @@ namespace JDP { //reportForm.Message = _batchReport.ToString(); //reportForm.ShowDialog(this); } - else if (useAR) + else if (useAR && cueSheet.Processed) { using (StringWriter sw = new StringWriter()) { @@ -856,7 +895,7 @@ namespace JDP { //reportForm.ShowDialog(this); } else - ShowFinishedMessage(cueSheet.PaddedToFrame); + ShowFinishedMessage(cueSheet.PaddedToFrame, status); SetupControls(false); } }); @@ -963,6 +1002,7 @@ namespace JDP { groupBoxMode.Enabled = !running; toolStripCorrectorFormat.Visible = SelectedAction == CUEAction.CorrectFilenames; tableLayoutPanelCUEStyle.Visible = converting; + tableLayoutPanelVerifyMode.Visible = SelectedAction == CUEAction.Verify; grpOutputPathGeneration.Enabled = !running; grpAudioOutput.Enabled = !running && converting; grpAction.Enabled = !running; @@ -980,6 +1020,7 @@ namespace JDP { toolStripProgressBar1.Value = 0; toolStripProgressBar2.Value = 0; toolStripStatusLabelAR.Visible = false; + toolStripStatusLabelCTDB.Visible = false; if (ReportState) { if (_batchReport != null) @@ -1018,7 +1059,7 @@ namespace JDP { return (dlgRes == DialogResult.OK); } - private void ShowFinishedMessage(bool warnAboutPadding) { + private void ShowFinishedMessage(bool warnAboutPadding, string status) { if (_batchPaths.Count != 0) { return; } @@ -1028,7 +1069,7 @@ namespace JDP { "files are from a CD source, this may indicate a problem with your files.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning); } - MessageBox.Show(this, "Conversion was successful!", "Done", MessageBoxButtons.OK, + MessageBox.Show(this, status, "Done", MessageBoxButtons.OK, MessageBoxIcon.Information); } @@ -1063,6 +1104,7 @@ namespace JDP { checkBoxUseFreeDb.Checked = _profile._useFreeDb; checkBoxUseMusicBrainz.Checked = _profile._useMusicBrainz; checkBoxUseAccurateRip.Checked = _profile._useAccurateRip; + checkBoxVerifyUseCDRepair.Checked = _profile._useCUEToolsDB; } private void ActivateProfile(string profileName) @@ -1106,6 +1148,7 @@ namespace JDP { _profile._useFreeDb = checkBoxUseFreeDb.Checked; _profile._useMusicBrainz = checkBoxUseMusicBrainz.Checked; _profile._useAccurateRip = checkBoxUseAccurateRip.Checked; + _profile._useCUEToolsDB = checkBoxVerifyUseCDRepair.Checked; if (_profile != _defaultProfile) { diff --git a/CUETools/frmCUETools.resx b/CUETools/frmCUETools.resx index 8f13761..5924055 100644 --- a/CUETools/frmCUETools.resx +++ b/CUETools/frmCUETools.resx @@ -126,26 +126,11 @@ - 404, 21 + 381, 21 MiddleLeft - - Segoe UI, 8.25pt - - - White - - - 21, 21 - - - Overlay - - - Album found in AccurateRip database. - 32, 21 @@ -156,6 +141,33 @@ False + + Segoe UI, 9pt + + + 39, 21 + + + 77 + + + False + + + Segoe UI, 9pt + + + White + + + 44, 21 + + + 55 + + + Album found in AccurateRip database. + 120, 20 @@ -265,7 +277,7 @@ fileSystemTreeView1 - CUEControls.FileSystemTreeView, CUEControls, Version=1.0.3510.22143, Culture=neutral, PublicKeyToken=null + CUEControls.FileSystemTreeView, CUEControls, Version=2.0.5.0, Culture=neutral, PublicKeyToken=null grpInput @@ -319,13 +331,13 @@ NoControl - 95, 80 + 95, 84 0, 0, 0, 0 - 49, 30 + 49, 26 5 @@ -358,13 +370,13 @@ NoControl - 47, 80 + 47, 84 0, 0, 0, 0 - 48, 30 + 48, 26 4 @@ -394,13 +406,13 @@ NoControl - 3, 36 + 3, 40 3, 0, 3, 0 - 138, 18 + 138, 20 2 @@ -439,7 +451,7 @@ 3, 0, 3, 0 - 138, 18 + 138, 20 0 @@ -472,13 +484,13 @@ NoControl - 3, 18 + 3, 20 3, 0, 3, 0 - 138, 18 + 138, 20 1 @@ -507,14 +519,17 @@ Fill + + NoControl + - 0, 80 + 0, 84 0, 0, 0, 0 - 47, 30 + 47, 26 3 @@ -565,7 +580,7 @@ 0 - <?xml version="1.0" encoding="utf-16"?><TableLayoutSettings><Controls><Control Name="checkBoxUseAccurateRip" Row="4" RowSpan="1" Column="2" ColumnSpan="1" /><Control Name="checkBoxUseFreeDb" Row="4" RowSpan="1" Column="1" ColumnSpan="1" /><Control Name="rbTracks" Row="2" RowSpan="1" Column="0" ColumnSpan="3" /><Control Name="rbEmbedCUE" Row="0" RowSpan="1" Column="0" ColumnSpan="3" /><Control Name="rbSingleFile" Row="1" RowSpan="1" Column="0" ColumnSpan="3" /><Control Name="checkBoxUseMusicBrainz" Row="4" RowSpan="1" Column="0" ColumnSpan="1" /></Controls><Columns Styles="Percent,33,33333,Percent,33,33334,Percent,33,33334" /><Rows Styles="Percent,16,41941,Percent,16,41942,Percent,16,42196,Percent,24,54545,Percent,26,36364" /></TableLayoutSettings> + <?xml version="1.0" encoding="utf-16"?><TableLayoutSettings><Controls><Control Name="checkBoxUseAccurateRip" Row="4" RowSpan="1" Column="2" ColumnSpan="1" /><Control Name="checkBoxUseFreeDb" Row="4" RowSpan="1" Column="1" ColumnSpan="1" /><Control Name="rbTracks" Row="2" RowSpan="1" Column="0" ColumnSpan="3" /><Control Name="rbEmbedCUE" Row="0" RowSpan="1" Column="0" ColumnSpan="3" /><Control Name="rbSingleFile" Row="1" RowSpan="1" Column="0" ColumnSpan="3" /><Control Name="checkBoxUseMusicBrainz" Row="4" RowSpan="1" Column="0" ColumnSpan="1" /></Controls><Columns Styles="Percent,33,33332,Percent,33,33334,Percent,33,33334" /><Rows Styles="Percent,18,18229,Percent,18,18229,Percent,18,18229,Percent,22,72658,Percent,22,72658" /></TableLayoutSettings> 3, 17 @@ -645,6 +660,69 @@ 1 + + 2 + + + True + + + Fill + + + 3, 3 + + + 45, 29 + + + 0 + + + checkBoxVerifyUseCDRepair + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tableLayoutPanelVerifyMode + + + 0 + + + Fill + + + 3, 17 + + + 2 + + + 144, 110 + + + 2 + + + Use CUETools database + + + tableLayoutPanelVerifyMode + + + System.Windows.Forms.TableLayoutPanel, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxMode + + + 2 + + + <?xml version="1.0" encoding="utf-16"?><TableLayoutSettings><Controls><Control Name="checkBoxVerifyUseCDRepair" Row="0" RowSpan="1" Column="0" ColumnSpan="1" /></Controls><Columns Styles="Percent,36,11111,Percent,63,88889" /><Rows Styles="Percent,32,72727,Percent,67,27273" /></TableLayoutSettings> + Fill @@ -2729,7 +2807,7 @@ 700, 538 - CUETools 2.0.4a + CUETools 2.0.5 toolStripStatusLabel1 @@ -2737,18 +2815,24 @@ System.Windows.Forms.ToolStripStatusLabel, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - toolStripStatusLabelAR - - - System.Windows.Forms.ToolStripStatusLabel, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - toolStripStatusLabelProcessed System.Windows.Forms.ToolStripStatusLabel, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + toolStripStatusLabelCTDB + + + System.Windows.Forms.ToolStripStatusLabel, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + toolStripStatusLabelAR + + + System.Windows.Forms.ToolStripStatusLabel, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + toolStripProgressBar1 diff --git a/CUETools/frmSettings.Designer.cs b/CUETools/frmSettings.Designer.cs index 5459460..bc7434a 100644 --- a/CUETools/frmSettings.Designer.cs +++ b/CUETools/frmSettings.Designer.cs @@ -27,6 +27,7 @@ namespace JDP { System.Windows.Forms.Button btnCancel; System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(frmSettings)); this.grpGeneral = new System.Windows.Forms.GroupBox(); + this.checkBoxSeparateDecodingThread = new System.Windows.Forms.CheckBox(); this.checkBoxCheckForUpdates = new System.Windows.Forms.CheckBox(); this.chkAllowMultipleInstances = new System.Windows.Forms.CheckBox(); this.chkReducePriority = new System.Windows.Forms.CheckBox(); @@ -127,6 +128,7 @@ namespace JDP { this.columnHeader1 = new System.Windows.Forms.ColumnHeader(); this.tabPage10 = new System.Windows.Forms.TabPage(); this.groupBoxFlaCudaOptions = new System.Windows.Forms.GroupBox(); + this.checkBoxFlaCudaMultithread = new System.Windows.Forms.CheckBox(); this.checkBoxFlaCudaGPUOnly = new System.Windows.Forms.CheckBox(); this.checkBoxFlaCudaVerify = new System.Windows.Forms.CheckBox(); this.groupBoxExternalEncoder = new System.Windows.Forms.GroupBox(); @@ -174,7 +176,7 @@ namespace JDP { this.labelFormatEncoder = new System.Windows.Forms.Label(); this.columnHeader2 = new System.Windows.Forms.ColumnHeader(); this.checkBox1 = new System.Windows.Forms.CheckBox(); - this.checkBoxFlaCudaMultithread = new System.Windows.Forms.CheckBox(); + this.checkBoxUseSystemProxy = new System.Windows.Forms.CheckBox(); btnCancel = new System.Windows.Forms.Button(); this.grpGeneral.SuspendLayout(); this.groupBox1.SuspendLayout(); @@ -227,6 +229,8 @@ namespace JDP { // // grpGeneral // + this.grpGeneral.Controls.Add(this.checkBoxUseSystemProxy); + this.grpGeneral.Controls.Add(this.checkBoxSeparateDecodingThread); this.grpGeneral.Controls.Add(this.checkBoxCheckForUpdates); this.grpGeneral.Controls.Add(this.chkAllowMultipleInstances); this.grpGeneral.Controls.Add(this.chkReducePriority); @@ -238,6 +242,13 @@ namespace JDP { this.grpGeneral.Name = "grpGeneral"; this.grpGeneral.TabStop = false; // + // checkBoxSeparateDecodingThread + // + resources.ApplyResources(this.checkBoxSeparateDecodingThread, "checkBoxSeparateDecodingThread"); + this.checkBoxSeparateDecodingThread.Name = "checkBoxSeparateDecodingThread"; + this.toolTip1.SetToolTip(this.checkBoxSeparateDecodingThread, resources.GetString("checkBoxSeparateDecodingThread.ToolTip")); + this.checkBoxSeparateDecodingThread.UseVisualStyleBackColor = true; + // // checkBoxCheckForUpdates // resources.ApplyResources(this.checkBoxCheckForUpdates, "checkBoxCheckForUpdates"); @@ -1078,6 +1089,13 @@ namespace JDP { this.groupBoxFlaCudaOptions.Name = "groupBoxFlaCudaOptions"; this.groupBoxFlaCudaOptions.TabStop = false; // + // checkBoxFlaCudaMultithread + // + resources.ApplyResources(this.checkBoxFlaCudaMultithread, "checkBoxFlaCudaMultithread"); + this.checkBoxFlaCudaMultithread.DataBindings.Add(new System.Windows.Forms.Binding("Checked", this.cUEConfigBindingSource, "FlaCudaThreads", true)); + this.checkBoxFlaCudaMultithread.Name = "checkBoxFlaCudaMultithread"; + this.checkBoxFlaCudaMultithread.UseVisualStyleBackColor = true; + // // checkBoxFlaCudaGPUOnly // resources.ApplyResources(this.checkBoxFlaCudaGPUOnly, "checkBoxFlaCudaGPUOnly"); @@ -1455,12 +1473,11 @@ namespace JDP { this.checkBox1.Name = "checkBox1"; this.checkBox1.UseVisualStyleBackColor = true; // - // checkBoxFlaCudaMultithread + // checkBoxUseSystemProxy // - resources.ApplyResources(this.checkBoxFlaCudaMultithread, "checkBoxFlaCudaMultithread"); - this.checkBoxFlaCudaMultithread.DataBindings.Add(new System.Windows.Forms.Binding("Checked", this.cUEConfigBindingSource, "FlaCudaThreads", true)); - this.checkBoxFlaCudaMultithread.Name = "checkBoxFlaCudaMultithread"; - this.checkBoxFlaCudaMultithread.UseVisualStyleBackColor = true; + resources.ApplyResources(this.checkBoxUseSystemProxy, "checkBoxUseSystemProxy"); + this.checkBoxUseSystemProxy.Name = "checkBoxUseSystemProxy"; + this.checkBoxUseSystemProxy.UseVisualStyleBackColor = true; // // frmSettings // @@ -1695,6 +1712,8 @@ namespace JDP { private System.Windows.Forms.CheckBox checkBoxFlaCudaVerify; private System.Windows.Forms.CheckBox checkBox1; private System.Windows.Forms.CheckBox checkBoxFlaCudaMultithread; + private System.Windows.Forms.CheckBox checkBoxSeparateDecodingThread; + private System.Windows.Forms.CheckBox checkBoxUseSystemProxy; } } \ No newline at end of file diff --git a/CUETools/frmSettings.cs b/CUETools/frmSettings.cs index bcca793..72ce3fb 100644 --- a/CUETools/frmSettings.cs +++ b/CUETools/frmSettings.cs @@ -84,6 +84,8 @@ namespace JDP { checkBoxFixToNearest.Checked = _config.fixOffsetToNearest; //textBoxARLogExtension.Text = _config.arLogFilenameFormat; numericUpDownMaxResolution.Value = _config.maxAlbumArtSize; + checkBoxSeparateDecodingThread.Checked = _config.separateDecodingThread; + checkBoxUseSystemProxy.Checked = _config.useSystemProxySettings; switch (_config.gapsHandling) { @@ -246,6 +248,8 @@ namespace JDP { _config.fixOffsetToNearest = checkBoxFixToNearest.Checked; //_config.arLogFilenameFormat = textBoxARLogExtension.Text; _config.maxAlbumArtSize = (int) numericUpDownMaxResolution.Value; + _config.separateDecodingThread = checkBoxSeparateDecodingThread.Checked; + _config.useSystemProxySettings = checkBoxUseSystemProxy.Checked; _config.language = ((CultureInfo)comboLanguage.SelectedItem).Name; } diff --git a/CUETools/frmSettings.resx b/CUETools/frmSettings.resx index 1437aa0..867f0d9 100644 --- a/CUETools/frmSettings.resx +++ b/CUETools/frmSettings.resx @@ -126,7 +126,7 @@ - 273, 290 + 268, 320 73, 23 @@ -150,6 +150,66 @@ 1 + + True + + + 12, 157 + + + 153, 17 + + + 10 + + + Use system proxy settings + + + checkBoxUseSystemProxy + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + grpGeneral + + + 0 + + + True + + + 12, 140 + + + 168, 17 + + + 9 + + + Separate thread for decoding + + + 17, 17 + + + Improves speed on multicore processors + + + checkBoxSeparateDecodingThread + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + grpGeneral + + + 1 + True @@ -168,9 +228,6 @@ Check for updates - - 17, 17 - Check for updates @@ -184,7 +241,7 @@ grpGeneral - 0 + 2 True @@ -217,7 +274,7 @@ grpGeneral - 1 + 3 True @@ -250,7 +307,7 @@ grpGeneral - 2 + 4 True @@ -283,7 +340,7 @@ grpGeneral - 3 + 5 True @@ -316,7 +373,7 @@ grpGeneral - 4 + 6 True @@ -349,7 +406,7 @@ grpGeneral - 5 + 7 True @@ -382,13 +439,13 @@ grpGeneral - 6 + 8 6, 6 - 252, 144 + 252, 182 0 @@ -466,7 +523,7 @@ NoControl - 194, 290 + 189, 320 73, 23 @@ -1612,10 +1669,10 @@ Top, Left, Right - 8, 156 + 6, 193 - 250, 99 + 250, 98 16 @@ -1642,7 +1699,7 @@ 3, 3, 3, 3 - 535, 261 + 535, 291 0 @@ -1891,7 +1948,7 @@ 242, 3 - 284, 255 + 284, 275 1 @@ -2095,7 +2152,7 @@ 8, 3 - 226, 255 + 226, 275 0 @@ -2116,7 +2173,7 @@ 4, 22 - 535, 261 + 535, 291 9 @@ -2506,7 +2563,7 @@ 3, 3, 3, 3 - 535, 261 + 535, 291 1 @@ -2854,7 +2911,7 @@ 136, 6 - 390, 249 + 390, 269 17 @@ -2881,7 +2938,7 @@ 6, 6 - 124, 249 + 124, 269 0 @@ -2905,7 +2962,7 @@ 3, 3, 3, 3 - 535, 261 + 535, 291 2 @@ -3213,7 +3270,7 @@ NoControl - 37, 232 + 37, 262 25, 23 @@ -3251,7 +3308,7 @@ - 6, 232 + 6, 262 25, 23 @@ -3275,7 +3332,7 @@ 6, 7 - 124, 221 + 124, 247 27 @@ -3554,7 +3611,7 @@ 3, 3, 3, 3 - 535, 261 + 535, 291 6 @@ -3734,7 +3791,7 @@ 3, 6 - 124, 249 + 124, 279 26 @@ -3794,7 +3851,7 @@ 3, 3, 3, 3 - 535, 261 + 535, 291 7 @@ -3953,7 +4010,7 @@ 3, 3, 3, 3 - 535, 261 + 535, 291 3 @@ -3980,7 +4037,7 @@ 144, 110 - 382, 145 + 382, 167 28 @@ -4094,7 +4151,7 @@ 6, 6 - 124, 249 + 124, 271 1 @@ -4115,7 +4172,7 @@ 4, 22 - 535, 261 + 535, 291 8 @@ -4142,7 +4199,7 @@ 0, 0, 0, 0 - 543, 287 + 543, 317 0 @@ -4241,7 +4298,7 @@ 6, 13 - 542, 325 + 542, 355 Tahoma, 8.25pt diff --git a/Freedb/Freedb.csproj b/Freedb/Freedb.csproj index 987427b..e44a1a4 100644 --- a/Freedb/Freedb.csproj +++ b/Freedb/Freedb.csproj @@ -1,7 +1,7 @@  Local - 8.0.50727 + 9.0.30729 2.0 {5ADCFD6D-BFEA-4B10-BB45-9083BBB56AF4} Debug @@ -29,7 +29,7 @@ 2.0 - ..\bin\win32\Debug\ + ..\bin\Debug\ false 285212672 false diff --git a/MAC_SDK/Source/MACLib/Assembly/Assembly.obj b/MAC_SDK/Source/MACLib/Assembly/Assembly.obj index 2917adc..fa72420 100644 Binary files a/MAC_SDK/Source/MACLib/Assembly/Assembly.obj and b/MAC_SDK/Source/MACLib/Assembly/Assembly.obj differ diff --git a/MusicBrainz/MusicBrainz.csproj b/MusicBrainz/MusicBrainz.csproj index 5baf144..ce557b3 100644 --- a/MusicBrainz/MusicBrainz.csproj +++ b/MusicBrainz/MusicBrainz.csproj @@ -3,7 +3,7 @@ Debug AnyCPU - 8.0.50727 + 9.0.30729 {74C2036B-2C9B-4FC8-B7BD-AE81A8DCE533} Library MusicBrainz @@ -18,7 +18,7 @@ true full false - . + ..\bin\Debug\ prompt 4 .