diff --git a/CUETools.AccurateRip/AccurateRip.cs b/CUETools.AccurateRip/AccurateRip.cs index 01b8dca..1cc9bc9 100644 --- a/CUETools.AccurateRip/AccurateRip.cs +++ b/CUETools.AccurateRip/AccurateRip.cs @@ -835,7 +835,7 @@ namespace CUETools.AccurateRip { currentOffset = tempLocation + i - 20 * 588 + 445 * 588; } - if (currentOffset <= trStart) + if (currentOffset < trStart) continue; _CRCAR[iTrack, i] = crcar + part._CRCAR[iTrack, i]; @@ -872,6 +872,8 @@ namespace CUETools.AccurateRip int leadout_len = Math.Max(4096 * 4, (calcSyn || calcParity) ? stride + laststride : 0); leadin = new ushort[leadin_len]; leadout = new ushort[leadout_len]; + leadinCrc = null; + leadoutCrc = null; _currentTrack = 0; Position = 0; // NOT _toc[_toc.FirstAudio][0].Start * 588; } diff --git a/CUETools.Codecs/Codecs.cs b/CUETools.Codecs/Codecs.cs index cf0621a..460d38a 100644 --- a/CUETools.Codecs/Codecs.cs +++ b/CUETools.Codecs/Codecs.cs @@ -997,96 +997,6 @@ namespace CUETools.Codecs public string Path { get { return null; } } } - public class NoiseGenerator : IAudioSource - { - private long _sampleOffset, _sampleCount; - private AudioPCMConfig pcm; - private Random rnd; - private byte[] temp; - private int tempOffs; - - public NoiseGenerator(AudioPCMConfig pcm, long sampleCount, int seed, int offset) - { - if (offset < 0) - throw new ArgumentOutOfRangeException("offset", "offset cannot be negative"); - - this._sampleOffset = 0; - this._sampleCount = sampleCount; - this.pcm = pcm; - this.rnd = new Random(seed); - this.temp = new byte[8192 * pcm.BlockAlign]; - this.tempOffs = temp.Length; - int byteOff = offset * pcm.BlockAlign; - for (int k = 0; k < byteOff / temp.Length; k++) - rnd.NextBytes(temp); - if (byteOff % temp.Length > 0) - rnd.NextBytes(new byte[byteOff % temp.Length]); - } - - public NoiseGenerator(long sampleCount) - : this(AudioPCMConfig.RedBook, sampleCount, 0, 0) - { - } - - public long Length - { - get - { - return _sampleCount; - } - } - - public long Remaining - { - get - { - return _sampleCount - _sampleOffset; - } - } - - public long Position - { - get - { - return _sampleOffset; - } - set - { - _sampleOffset = value; - } - } - - public AudioPCMConfig PCM { get { return pcm; } } - - public int Read(AudioBuffer buff, int maxLength) - { - buff.Prepare(this, maxLength); - - int buffOffs = 0; - while (buffOffs < buff.ByteLength) - { - if (tempOffs == temp.Length) - { - rnd.NextBytes(temp); - tempOffs = 0; - } - int chunk = Math.Min(buff.ByteLength - buffOffs, temp.Length - tempOffs); - Array.Copy(temp, tempOffs, buff.Bytes, buffOffs, chunk); - buffOffs += chunk; - tempOffs += chunk; - } - - _sampleOffset += buff.Length; - return buff.Length; - } - - public void Close() - { - } - - public string Path { get { return null; } } - } - [AudioDecoderClass("builtin wav", "wav")] public class WAVReader : IAudioSource { diff --git a/CUETools.TestHelpers/CUETools.TestHelpers.csproj b/CUETools.TestHelpers/CUETools.TestHelpers.csproj new file mode 100644 index 0000000..4132c08 --- /dev/null +++ b/CUETools.TestHelpers/CUETools.TestHelpers.csproj @@ -0,0 +1,70 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {84EBB7CB-02C9-40A9-9D32-C641B822DAA2} + Library + Properties + CUETools.TestHelpers + CUETools.TestHelpers + v2.0 + 512 + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + {5802C7E9-157E-4124-946D-70B5AE48A5A1} + CUETools.AccurateRip + + + {1DD41038-D885-46C5-8DDE-E0B82F066584} + CUETools.CDImage + + + {6458A13A-30EF-45A9-9D58-E5031B17BEE2} + CUETools.Codecs + + + + + + + + \ No newline at end of file diff --git a/CUETools.TestHelpers/NoiseAndErrorsGenerator.cs b/CUETools.TestHelpers/NoiseAndErrorsGenerator.cs new file mode 100644 index 0000000..b5156d1 --- /dev/null +++ b/CUETools.TestHelpers/NoiseAndErrorsGenerator.cs @@ -0,0 +1,115 @@ +using System; +using System.Collections.Generic; +using System.Text; +using CUETools.Codecs; + +namespace CUETools.TestHelpers +{ + public class NoiseAndErrorsGenerator : IAudioSource + { + private long _sampleOffset, _sampleCount; + private AudioPCMConfig pcm; + private Random rnd, rnd2; + private byte[] temp; + private int[] errors; + private int tempOffs; + private int nextError; + + public NoiseAndErrorsGenerator(AudioPCMConfig pcm, long sampleCount, int seed, int offset, int errors) + { + if (offset < 0) + throw new ArgumentOutOfRangeException("offset", "offset cannot be negative"); + if (errors < 0) + throw new ArgumentOutOfRangeException("offset", "errors cannot be negative"); + + this._sampleOffset = 0; + this._sampleCount = sampleCount; + this.pcm = pcm; + this.rnd = new Random(seed); + this.temp = new byte[8192 * pcm.BlockAlign]; + this.tempOffs = temp.Length; + int byteOff = offset * pcm.BlockAlign; + for (int k = 0; k < byteOff / temp.Length; k++) + rnd.NextBytes(temp); + if (byteOff % temp.Length > 0) + rnd.NextBytes(new byte[byteOff % temp.Length]); + this.errors = new int[errors]; + this.rnd2 = new Random(seed); + for (int i = 0; i < errors; i++) + this.errors[i] = this.rnd2.Next(0, (int)sampleCount); + this.rnd2 = new Random(seed); + Array.Sort(this.errors); + this.nextError = 0; + } + + public NoiseAndErrorsGenerator(long sampleCount) + : this(AudioPCMConfig.RedBook, sampleCount, 0, 0, 0) + { + } + + public long Length + { + get + { + return _sampleCount; + } + } + + public long Remaining + { + get + { + return _sampleCount - _sampleOffset; + } + } + + public long Position + { + get + { + return _sampleOffset; + } + set + { + _sampleOffset = value; + } + } + + public AudioPCMConfig PCM { get { return pcm; } } + + public int Read(AudioBuffer buff, int maxLength) + { + buff.Prepare(this, maxLength); + + int buffOffs = 0; + while (buffOffs < buff.ByteLength) + { + if (tempOffs == temp.Length) + { + rnd.NextBytes(temp); + tempOffs = 0; + } + int chunk = Math.Min(buff.ByteLength - buffOffs, temp.Length - tempOffs); + Array.Copy(temp, tempOffs, buff.Bytes, buffOffs, chunk); + buffOffs += chunk; + tempOffs += chunk; + } + + while (this.nextError < this.errors.Length && this.errors[this.nextError] < _sampleOffset + buff.Length) + { + for (int i = 0; i < PCM.BlockAlign; i++) + buff.Bytes[(this.errors[this.nextError] - _sampleOffset) * PCM.BlockAlign + i] ^= (byte)this.rnd2.Next(1, 255); + this.nextError++; + } + + _sampleOffset += buff.Length; + return buff.Length; + } + + public void Close() + { + } + + public string Path { get { return null; } } + } +} diff --git a/CUETools.TestHelpers/Properties/AssemblyInfo.cs b/CUETools.TestHelpers/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..4748e1b --- /dev/null +++ b/CUETools.TestHelpers/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +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("CUETools.TestHelpers")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft")] +[assembly: AssemblyProduct("CUETools.TestHelpers")] +[assembly: AssemblyCopyright("Copyright © Microsoft 2011")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. 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("b71494d6-b658-4924-a009-d924e192550f")] + +// 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 Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/CUETools.TestHelpers/TestImageGenerator.cs b/CUETools.TestHelpers/TestImageGenerator.cs new file mode 100644 index 0000000..a7579d7 --- /dev/null +++ b/CUETools.TestHelpers/TestImageGenerator.cs @@ -0,0 +1,95 @@ +using System; +using System.Collections.Generic; +using System.Text; +using CUETools.AccurateRip; +using CUETools.Codecs; +using CUETools.CDImage; + +namespace CUETools.TestHelpers +{ + public class TestImageGenerator + { + public CDImageLayout toc; + public int seed, offset, start, end, errors; + + public TestImageGenerator(CDImageLayout toc, int seed, int offset, int errors, int start, int end) + { + this.toc = toc; + this.seed = seed; + this.offset = offset; + this.start = start; + this.end = end; + this.errors = errors; + } + + public TestImageGenerator(string trackoffsets, int seed, int offset, int errors, int start, int end) + : this (new CDImageLayout(trackoffsets), seed, offset, errors, start, end) + { + } + + public TestImageGenerator(CDImageLayout toc, int seed, int offset, int errors) + : this(toc, seed, offset, errors, 0, (int)toc.AudioLength * 588) + { + } + + public TestImageGenerator(string trackoffsets, int seed, int offset, int errors) + : this(new CDImageLayout(trackoffsets), seed, offset, errors) + { + } + + public TestImageGenerator(TestImageGenerator copy) + { + this.toc = copy.toc; + this.seed = copy.seed; + this.offset = copy.offset; + this.start = copy.start; + this.end = copy.end; + this.errors = copy.errors; + } + + public void Write(IAudioDest dest) + { + if (start < 0 || start > end || end > toc.AudioLength * 588) + throw new ArgumentOutOfRangeException(); + var src = new NoiseAndErrorsGenerator(AudioPCMConfig.RedBook, end - start, seed, offset + start, errors); + var buff = new AudioBuffer(src, 588 * 10); + var rnd = new Random(seed); + //dest.Position = start; + while (src.Remaining > 0) + { + src.Read(buff, rnd.Next(1, buff.Size)); + dest.Write(buff); + } + } + + public AccurateRipVerify CreateAccurateRipVerify() + { + var ar = new AccurateRipVerify(toc, null); + ar.Position = start; + Write(ar); + return ar; + } + + public CDRepairEncode CreateCDRepairEncode(int stride, int npar, bool do_verify, bool do_encode) + { + var ar = new AccurateRipVerify(toc, null); + var encode = new CDRepairEncode(ar, stride, npar, do_verify, do_encode); + ar.Position = start; + Write(ar); + ar.Close(); + return encode; + } + + public static AccurateRipVerify CreateAccurateRipVerify(string trackoffsets, int seed, int offset, int start, int end) + { + var generator = new TestImageGenerator(trackoffsets, seed, offset, 0, start, end); + return generator.CreateAccurateRipVerify(); + } + + public static AccurateRipVerify CreateAccurateRipVerify(string trackoffsets, int seed, int offset) + { + var generator = new TestImageGenerator(trackoffsets, seed, offset, 0); + return generator.CreateAccurateRipVerify(); + } + } +} diff --git a/CUETools.TestHelpers/app.config b/CUETools.TestHelpers/app.config new file mode 100644 index 0000000..b7db281 --- /dev/null +++ b/CUETools.TestHelpers/app.config @@ -0,0 +1,3 @@ + + + diff --git a/CUETools/CUETools.TestCodecs/AccurateRipVerifyTest.cs b/CUETools/CUETools.TestCodecs/AccurateRipVerifyTest.cs index e85b282..61469b9 100644 --- a/CUETools/CUETools.TestCodecs/AccurateRipVerifyTest.cs +++ b/CUETools/CUETools.TestCodecs/AccurateRipVerifyTest.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using CUETools.CDImage; using CUETools.AccurateRip; using CUETools.Codecs; +using CUETools.TestHelpers; namespace CUETools.TestCodecs { /// @@ -38,25 +39,6 @@ namespace CUETools.TestCodecs } } - private static AccurateRipVerify VerifyNoise(string trackoffsets, int seed, int offset) - { - return VerifyNoise(new CDImageLayout(trackoffsets), seed, offset); - } - - private static AccurateRipVerify VerifyNoise(CDImageLayout toc, int seed, int offset) - { - var src = new NoiseGenerator(AudioPCMConfig.RedBook, toc.AudioLength * 588, seed, offset); - var buff = new AudioBuffer(src, 588 * 10); - var ar = new AccurateRipVerify(toc, null); - var rnd = new Random(seed); - while (src.Remaining > 0) - { - src.Read(buff, rnd.Next(1, buff.Size)); - ar.Write(buff); - } - return ar; - } - #region Additional test attributes // //You can use the following additional attributes as you write your tests: @@ -80,8 +62,8 @@ namespace CUETools.TestCodecs [TestInitialize()] public void MyTestInitialize() { - ar = VerifyNoise("13 68 99 136", 2314, 0); - ar2 = VerifyNoise("0 136 886", 2314, 0); + ar = TestImageGenerator.CreateAccurateRipVerify("13 68 99 136", 2314, 0); + ar2 = TestImageGenerator.CreateAccurateRipVerify("0 136 886", 2314, 0); } //Use TestCleanup to run code after each test has run @@ -168,10 +150,11 @@ namespace CUETools.TestCodecs [TestMethod()] public void CRCTestOffset() { - var ar0 = VerifyNoise("13 68 99 136", 723722, 0); - for (int offs = 1; offs < 588 * 5; offs += 17) + var ar0 = TestImageGenerator.CreateAccurateRipVerify("13 68 99 136", 723722, 0); + var offsets = new int[] { 1, 2, 3, 4, 11, 256, 588, 588 * 5 - 1 }; + foreach (int offs in offsets) { - var ar1 = VerifyNoise("13 68 99 136", 723722, offs); + var ar1 = TestImageGenerator.CreateAccurateRipVerify("13 68 99 136", 723722, offs); for (int track = 0; track < 3; track++) { Assert.AreEqual(ar0.CRC(track, offs), ar1.CRC(track), "CRC with offset " + offs + " was not set correctly."); @@ -183,6 +166,39 @@ namespace CUETools.TestCodecs if (track != 0) Assert.AreEqual(ar0.CRC32(track + 1), ar1.CRC32(track + 1, -offs), "CRC32 with offset " + (-offs) + " was not set correctly."); } + Assert.AreEqual(ar0.CTDBCRC(2 * 588 * 5, 2 * 588 * 5), ar1.CTDBCRC(2 * 588 * 5 - offs * 2, 2 * 588 * 5 + offs * 2), "CTDBCRC with offset " + offs + " was not set correctly."); + Assert.AreEqual(ar1.CTDBCRC(2 * 588 * 5, 2 * 588 * 5), ar0.CTDBCRC(2 * 588 * 5 + offs * 2, 2 * 588 * 5 - offs * 2), "CTDBCRC with offset " + (-offs) + " was not set correctly."); + } + } + + /// + ///A test for CRC parralelism + /// + [TestMethod()] + public void CRCTestSplit() + { + var ar0 = TestImageGenerator.CreateAccurateRipVerify("13 68 99 136", 723722, 0); + var splits = new int[] { 1, 13 * 588 - 1, 13 * 588, 13 * 588 + 1, 30 * 588, 68 * 588 - 1, 68 * 588, 68 * 588 + 1 }; + foreach (int split in splits) + { + var ar1 = TestImageGenerator.CreateAccurateRipVerify("13 68 99 136", 723722, 0, 0, split); + var ar2 = TestImageGenerator.CreateAccurateRipVerify("13 68 99 136", 723722, 0, split, (int)ar0.FinalSampleCount); + ar1.Combine(ar2, split, (int)ar0.FinalSampleCount); + var offsets = new int[] { 0, -1, 1, -2, 2, -3, 3, -4, 4, -11, 11, -256, 256, -588, 588, 1 - 588 * 5, 588 * 5 - 1 }; + foreach (int offs in offsets) + { + for (int track = 0; track < 3; track++) + { + string message = "split = " + CDImageLayout.TimeToString((uint)split/588) + "." + (split%588).ToString() + ", offset = " + offs.ToString() + ", track = " + (track + 1).ToString(); + Assert.AreEqual(ar0.CRC(track, offs), ar1.CRC(track, offs), "CRC was not set correctly, " + message); + Assert.AreEqual(ar0.CRC450(track, offs), ar1.CRC450(track, offs), "CRC450 was not set correctly, " + message); + if ((track != 2 || offs <= 0) && (track != 0 || offs >= 0)) + { + Assert.AreEqual(ar0.CRC32(track + 1, offs), ar1.CRC32(track + 1, offs), "CRC32 was not set correctly, " + message); + Assert.AreEqual(ar0.CRCWONULL(track + 1, offs), ar1.CRCWONULL(track + 1, offs), "CRCWONULL was not set correctly, " + message); + } + } + } } } @@ -228,7 +244,7 @@ namespace CUETools.TestCodecs public void OffsetSafeCRCRecordTest() { //OffsetSafeCRCRecord[] records = new OffsetSafeCRCRecord[5000]; - var record0 = VerifyNoise("13 68 99 136", 2314, 0).OffsetSafeCRC; + var record0 = TestImageGenerator.CreateAccurateRipVerify("13 68 99 136", 2314, 0).OffsetSafeCRC; Assert.AreEqual( "8+lTDqEZidfayuC0LoxnL9Oluf4ywo1muFBu115XBgf254fKIdfVWZOcsQraS4eI\r\n" + @@ -242,11 +258,12 @@ namespace CUETools.TestCodecs "96ZJS2aBroYAw2We5RC2oekmi+N75L6+eQB/4iZOxB9aGP1sALd/UZaJqZP8FcmW\r\n" + "FJOXlBi/KW68TJvujz+2w/P7EaZ0L7llQAtoHwoJniuNN5WYXBlescGc+vyYr5df\r\n" + "jrul+QMmQ4xMi10mglq7CMLVfZZFFgBdvGBrn1tL9bg=\r\n", - VerifyNoise("13 68 99 136", 2314, 13).OffsetSafeCRC.Base64); + TestImageGenerator.CreateAccurateRipVerify("13 68 99 136", 2314, 13).OffsetSafeCRC.Base64); - for (int offset = 0; offset < 5000; offset += (offset < 256 ? 1 : 37)) + var offsets = new int[] { 1, 2, 3, 4, 8, 11, 15, 16, 31, 32, 255, 256, 597, 588, 588 * 5 - 1, 588 * 5, 4095, 4096, 4097, 5000 }; + foreach (int offset in offsets) { - var record = VerifyNoise("13 68 99 136", 2314, offset).OffsetSafeCRC; + var record = TestImageGenerator.CreateAccurateRipVerify("13 68 99 136", 2314, offset).OffsetSafeCRC; int real_off = -offset; int off; diff --git a/CUETools/CUETools.TestCodecs/CUETools.TestCodecs.csproj b/CUETools/CUETools.TestCodecs/CUETools.TestCodecs.csproj index 39cb438..ea42635 100644 --- a/CUETools/CUETools.TestCodecs/CUETools.TestCodecs.csproj +++ b/CUETools/CUETools.TestCodecs/CUETools.TestCodecs.csproj @@ -97,6 +97,10 @@ {D2700165-3E77-4B28-928D-551F5FC11954} CUETools.Ripper + + {84EBB7CB-02C9-40A9-9D32-C641B822DAA2} + CUETools.TestHelpers + {5ADCFD6D-BFEA-4B10-BB45-9083BBB56AF4} Freedb diff --git a/CUETools/CUETools.TestParity/CDRepairDecodeTest.cs b/CUETools/CUETools.TestParity/CDRepairDecodeTest.cs index c6ddeac..4213c9b 100644 --- a/CUETools/CUETools.TestParity/CDRepairDecodeTest.cs +++ b/CUETools/CUETools.TestParity/CDRepairDecodeTest.cs @@ -3,11 +3,10 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using CUETools.Codecs; using CUETools.CDImage; using CUETools.AccurateRip; +using CUETools.TestHelpers; namespace CUETools.TestParity { - - /// ///This is a test class for CDRepairDecodeTest and is intended ///to contain all CDRepairDecodeTest Unit Tests @@ -15,23 +14,27 @@ namespace CUETools.TestParity [TestClass()] public class CDRepairDecodeTest { - - const int finalSampleCount = 44100 * 60 * 10; // 10 minutes long - //const int stride = finalSampleCount * 2 / 32768; + // CD has maximum of 360.000 sectors; + // If stride equals 10 sectors (10 sectors * 588 samples * 2 words), + // then maximum sequence length is 36.000 sectors. + // 36.000 is less than (65535 - npar), so we're ok here. + // npar == 8 provides error correction for 4 samples out of every 36k, + // i.e. at best one sample per 9k can be repaired. + // Parity data per one CD requires 10 * 588 * 4 * npar bytes, + // which equals 188.160b == 184kb + // We might consider shorter strides to reduce parity data size, + // but it probably should still be a multiple of 588 * 2; + // (or the size of CD CIRC buffer?) const int stride = 10 * 588 * 2; const int npar = 8; - static byte[] wav = new byte[finalSampleCount * 4]; - static byte[] wav2 = new byte[finalSampleCount * 4]; - static byte[] wav3 = new byte[finalSampleCount * 4]; - static byte[] parity; - static uint crc; + const int errors = stride / 4; const int offset = 48; - static AccurateRipVerify ar; - static CDImageLayout toc; - static CDImageLayout toc2; + const int seed = 2423; //const int offset = 5 * 588 - 5; //const int offset = 2000; + private static TestImageGenerator generator; + private static CDRepairEncode encode; private TestContext testContextInstance; /// @@ -58,24 +61,8 @@ namespace CUETools.TestParity [ClassInitialize()] public static void MyClassInitialize(TestContext testContext) { - toc = new CDImageLayout(1, 1, 1, string.Format("0 {0}", (finalSampleCount / 588).ToString())); - toc2 = new CDImageLayout(1, 1, 1, string.Format("32 {0}", (32 + finalSampleCount / 588).ToString())); - ar = new AccurateRipVerify(toc, null); - - new Random(2423).NextBytes(wav); - new Random(2423).NextBytes(wav2); - Random rnd = new Random(987); - for (int i = 0; i < stride / 4; i++) - wav2[(int)(rnd.NextDouble() * (wav2.Length - 1))] = (byte)(rnd.NextDouble() * 255); - - AudioBuffer buff = new AudioBuffer(AudioPCMConfig.RedBook, 0); - CDRepairEncode encode = new CDRepairEncode(ar, stride, npar, false, true); - buff.Prepare(wav, finalSampleCount); - ar.Init(toc); - ar.Write(buff); - ar.Close(); - parity = encode.Parity; - crc = encode.CRC; + generator = new TestImageGenerator("0 9801", seed, 32 * 588, 0); + encode = generator.CreateCDRepairEncode(stride, npar, false, true); } // //Use ClassCleanup to run code after all tests in a class have run @@ -98,6 +85,15 @@ namespace CUETools.TestParity // #endregion + /// + ///A test for Write + /// + [TestMethod()] + public void CDRepairEncodeWriteTest() + { + Assert.AreEqual("jvR9QJ1cSWo=", Convert.ToBase64String(encode.Parity, 0, 8)); + Assert.AreEqual(377539636, encode.CRC); + } /// ///Verifying rip that is accurate @@ -105,15 +101,10 @@ namespace CUETools.TestParity [TestMethod()] public void CDRepairDecodeOriginalTest() { - AudioBuffer buff = new AudioBuffer(AudioPCMConfig.RedBook, 0); - CDRepairEncode decode = new CDRepairEncode(ar, stride, npar, true, false); - buff.Prepare(wav, finalSampleCount); - ar.Init(toc); - ar.Write(buff); - ar.Close(); + var decode = generator.CreateCDRepairEncode(stride, npar, true, false); int actualOffset; bool hasErrors; - Assert.IsTrue(decode.FindOffset(npar, parity, 0, crc, out actualOffset, out hasErrors)); + Assert.IsTrue(decode.FindOffset(encode.NPAR, encode.Parity, 0, encode.CRC, out actualOffset, out hasErrors)); Assert.IsFalse(hasErrors, "has errors"); Assert.AreEqual(0, actualOffset, "wrong offset"); } @@ -124,20 +115,14 @@ namespace CUETools.TestParity [TestMethod()] public void CDRepairDecodeOriginalWithPregapTest() { - AudioBuffer buff = new AudioBuffer(AudioPCMConfig.RedBook, 0); - ar.Init(toc2); - CDRepairEncode decode = new CDRepairEncode(ar, stride, npar, true, false); - buff.Prepare(wav, (int)toc2.Pregap * 588); - ar.Write(buff); - buff.Prepare(wav, finalSampleCount); - ar.Write(buff); - ar.Close(); + var generator2 = new TestImageGenerator("32 9833", seed, 0, 0); + var decode = generator2.CreateCDRepairEncode(stride, npar, true, false); int actualOffset; bool hasErrors; - Assert.IsTrue(decode.FindOffset(npar, parity, 0, crc, out actualOffset, out hasErrors)); + Assert.IsTrue(decode.FindOffset(encode.NPAR, encode.Parity, 0, encode.CRC, out actualOffset, out hasErrors)); Assert.IsTrue(hasErrors, "doesn't have errors"); Assert.AreEqual(-1176, actualOffset, "wrong offset"); - CDRepairFix fix = decode.VerifyParity(parity, actualOffset); + CDRepairFix fix = decode.VerifyParity(encode.Parity, actualOffset); Assert.IsTrue(fix.HasErrors, "doesn't have errors"); Assert.IsTrue(fix.CanRecover, "cannot recover"); } @@ -148,20 +133,18 @@ namespace CUETools.TestParity [TestMethod()] public void CDRepairDecodeModifiedTest() { - AudioBuffer buff = new AudioBuffer(AudioPCMConfig.RedBook, 0); - CDRepairEncode decode = new CDRepairEncode(ar, stride, npar, true, false); - buff.Prepare(wav2, finalSampleCount); - ar.Init(toc); - ar.Write(buff); - ar.Close(); + var generator2 = new TestImageGenerator("0 9801", seed, 32 * 588, errors); + var decode = generator2.CreateCDRepairEncode(stride, npar, true, false); int actualOffset; bool hasErrors; - Assert.IsTrue(decode.FindOffset(npar, parity, 0, crc, out actualOffset, out hasErrors)); + Assert.IsTrue(decode.FindOffset(encode.NPAR, encode.Parity, 0, encode.CRC, out actualOffset, out hasErrors)); Assert.IsTrue(hasErrors, "doesn't have errors"); Assert.AreEqual(0, actualOffset, "wrong offset"); - CDRepairFix fix = decode.VerifyParity(parity, actualOffset); + CDRepairFix fix = decode.VerifyParity(encode.Parity, actualOffset); Assert.IsTrue(fix.HasErrors, "doesn't have errors"); Assert.IsTrue(fix.CanRecover, "cannot recover"); + generator2.Write(fix); + Assert.AreEqual(encode.CRC, fix.CRC); } /// @@ -170,16 +153,11 @@ namespace CUETools.TestParity [TestMethod()] public void CDRepairDecodePositiveOffsetTest() { - AudioBuffer buff = new AudioBuffer(AudioPCMConfig.RedBook, 0); - CDRepairEncode decode = new CDRepairEncode(ar, stride, npar, true, false); - Array.Copy(wav, offset * 4, wav3, 0, (finalSampleCount - offset) * 4); - buff.Prepare(wav3, finalSampleCount); - ar.Init(toc); - ar.Write(buff); - ar.Close(); + var generator2 = new TestImageGenerator("0 9801", seed, 32 * 588 + offset, 0); + var decode = generator2.CreateCDRepairEncode(stride, npar, true, false); int actualOffset; bool hasErrors; - Assert.IsTrue(decode.FindOffset(npar, parity, 0, crc, out actualOffset, out hasErrors)); + Assert.IsTrue(decode.FindOffset(encode.NPAR, encode.Parity, 0, encode.CRC, out actualOffset, out hasErrors)); Assert.IsFalse(hasErrors, "has errors"); Assert.AreEqual(offset, actualOffset, "wrong offset"); } @@ -190,17 +168,11 @@ namespace CUETools.TestParity [TestMethod()] public void CDRepairDecodeNegativeOffsetTest() { - AudioBuffer buff = new AudioBuffer(AudioPCMConfig.RedBook, 0); - CDRepairEncode decode = new CDRepairEncode(ar, stride, npar, true, false); - ar.Init(toc); - buff.Prepare(new byte[offset * 4], offset); - ar.Write(buff); - buff.Prepare(wav, finalSampleCount - offset); - ar.Write(buff); - ar.Close(); + var generator2 = new TestImageGenerator("0 9801", seed, 32 * 588 - offset, 0); + var decode = generator2.CreateCDRepairEncode(stride, npar, true, false); int actualOffset; bool hasErrors; - Assert.IsTrue(decode.FindOffset(npar, parity, 0, crc, out actualOffset, out hasErrors)); + Assert.IsTrue(decode.FindOffset(encode.NPAR, encode.Parity, 0, encode.CRC, out actualOffset, out hasErrors)); Assert.IsFalse(hasErrors, "has errors"); Assert.AreEqual(-offset, actualOffset, "wrong offset"); } @@ -211,21 +183,18 @@ namespace CUETools.TestParity [TestMethod()] public void CDRepairDecodePositiveOffsetErrorsTest() { - AudioBuffer buff = new AudioBuffer(AudioPCMConfig.RedBook, 0); - CDRepairEncode decode = new CDRepairEncode(ar, stride, npar, true, false); - Array.Copy(wav2, offset * 4, wav3, 0, (finalSampleCount - offset) * 4); - buff.Prepare(wav3, finalSampleCount); - ar.Init(toc); - ar.Write(buff); - ar.Close(); + var generator2 = new TestImageGenerator("0 9801", seed, 32 * 588 + offset, errors); + var decode = generator2.CreateCDRepairEncode(stride, npar, true, false); int actualOffset; bool hasErrors; - Assert.IsTrue(decode.FindOffset(npar, parity, 0, crc, out actualOffset, out hasErrors)); + Assert.IsTrue(decode.FindOffset(encode.NPAR, encode.Parity, 0, encode.CRC, out actualOffset, out hasErrors)); Assert.IsTrue(hasErrors, "doesn't have errors"); Assert.AreEqual(offset, actualOffset, "wrong offset"); - CDRepairFix fix = decode.VerifyParity(parity, actualOffset); + CDRepairFix fix = decode.VerifyParity(encode.Parity, actualOffset); Assert.IsTrue(fix.HasErrors, "doesn't have errors"); Assert.IsTrue(fix.CanRecover, "cannot recover"); + generator2.Write(fix); + Assert.AreEqual(encode.CRC, fix.CRC); } /// @@ -234,22 +203,18 @@ namespace CUETools.TestParity [TestMethod()] public void CDRepairDecodeNegativeOffsetErrorsTest() { - AudioBuffer buff = new AudioBuffer(AudioPCMConfig.RedBook, 0); - CDRepairEncode decode = new CDRepairEncode(ar, stride, npar, true, false); - ar.Init(toc); - buff.Prepare(new byte[offset * 4], offset); - ar.Write(buff); - buff.Prepare(wav2, finalSampleCount - offset); - ar.Write(buff); - ar.Close(); + var generator2 = new TestImageGenerator("0 9801", seed, 32 * 588 - offset, errors); + var decode = generator2.CreateCDRepairEncode(stride, npar, true, false); int actualOffset; bool hasErrors; - Assert.IsTrue(decode.FindOffset(npar, parity, 0, crc, out actualOffset, out hasErrors)); + Assert.IsTrue(decode.FindOffset(encode.NPAR, encode.Parity, 0, encode.CRC, out actualOffset, out hasErrors)); Assert.IsTrue(hasErrors, "doesn't have errors"); Assert.AreEqual(-offset, actualOffset, "wrong offset"); - CDRepairFix fix = decode.VerifyParity(parity, actualOffset); + CDRepairFix fix = decode.VerifyParity(encode.Parity, actualOffset); Assert.IsTrue(fix.HasErrors, "doesn't have errors"); Assert.IsTrue(fix.CanRecover, "cannot recover"); + generator2.Write(fix); + Assert.AreEqual(encode.CRC, fix.CRC); } } } diff --git a/CUETools/CUETools.TestParity/CDRepairEncodeTest.cs b/CUETools/CUETools.TestParity/CDRepairEncodeTest.cs index a817279..9f219a2 100644 --- a/CUETools/CUETools.TestParity/CDRepairEncodeTest.cs +++ b/CUETools/CUETools.TestParity/CDRepairEncodeTest.cs @@ -32,9 +32,6 @@ namespace CUETools.TestParity // (or the size of CD CIRC buffer?) const int npar = 8; - static byte[] wav = new byte[finalSampleCount * 4]; - static AccurateRipVerify ar; - static CDImageLayout toc; private TestContext testContextInstance; @@ -54,6 +51,31 @@ namespace CUETools.TestParity } } + public static CDRepairEncode VerifyNoise(CDImageLayout toc, int seed, int offset, int start, int end, int errors, bool do_verify, bool do_encode) + { + if (start < 0 || start > end || end > toc.AudioLength * 588) + throw new ArgumentOutOfRangeException(); + var src = new NoiseAndErrorsGenerator(AudioPCMConfig.RedBook, end - start, seed, offset + start, errors); + var buff = new AudioBuffer(src, 588 * 100); + var ar = new AccurateRipVerify(toc, null); + var encode = new CDRepairEncode(ar, stride, npar, do_verify, do_encode); + var rnd = new Random(seed); + ar.Position = start; + while (src.Remaining > 0) + { + src.Read(buff, rnd.Next(1, buff.Size)); + ar.Write(buff); + } + ar.Close(); + return encode; + } + + public static CDRepairEncode VerifyNoise(string trackoffsets, int seed, int offset, int errors, bool do_verify, bool do_encode) + { + var toc = new CDImageLayout(trackoffsets); + return VerifyNoise(toc, seed, offset, 0, (int)toc.AudioLength * 588, errors, do_verify, do_encode); + } + #region Additional test attributes // //You can use the following additional attributes as you write your tests: @@ -62,9 +84,6 @@ namespace CUETools.TestParity [ClassInitialize()] public static void MyClassInitialize(TestContext testContext) { - toc = new CDImageLayout(1, 1, 1, string.Format("0 {0}", (finalSampleCount / 588).ToString())); - ar = new AccurateRipVerify(toc, null); - new Random(2423).NextBytes(wav); } //Use ClassCleanup to run code after all tests in a class have run @@ -94,13 +113,8 @@ namespace CUETools.TestParity [TestMethod()] public void CDRepairEncodeWriteTest() { - AudioBuffer buff = new AudioBuffer(AudioPCMConfig.RedBook, 0); - CDRepairEncode encode = new CDRepairEncode(ar, stride, npar, false, true); - buff.Prepare(wav, finalSampleCount); - ar.Init(toc); - ar.Write(buff); - ar.Close(); - Assert.AreEqual(8, encode.Parity[0]); + var encode = VerifyNoise("0 45000", 2423, 0, 0, false, true); + Assert.AreEqual("CAz3OBAHPAw=", Convert.ToBase64String(encode.Parity, 0, 8)); Assert.AreEqual(2278257733, encode.CRC); } } diff --git a/CUETools/CUETools.TestParity/CUETools.TestParity.csproj b/CUETools/CUETools.TestParity/CUETools.TestParity.csproj index 97d4ccd..b56409e 100644 --- a/CUETools/CUETools.TestParity/CUETools.TestParity.csproj +++ b/CUETools/CUETools.TestParity/CUETools.TestParity.csproj @@ -9,9 +9,11 @@ Properties CUETools.TestParity CUETools.TestParity - v3.5 + v2.0 512 {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + + true @@ -24,25 +26,20 @@ pdbonly - true + false bin\Release\ - TRACE + DEBUG;TRACE prompt 4 - - 3.5 - - - @@ -66,6 +63,13 @@ {ECEB839C-171B-4535-958F-9899310A0342} CUETools.Parity + + {84EBB7CB-02C9-40A9-9D32-C641B822DAA2} + CUETools.TestHelpers + + + +