diff --git a/CUERipper/frmCUERipper.cs b/CUERipper/frmCUERipper.cs index 7cf5837..cffb544 100644 --- a/CUERipper/frmCUERipper.cs +++ b/CUERipper/frmCUERipper.cs @@ -408,20 +408,20 @@ namespace CUERipper cueSheet.CTDB.Submit( (int)cueSheet.ArVerify.WorstConfidence() + 1, audioSource.CorrectionQuality == 0 ? 0 : - (int)(100 * (1.0 - Math.Log(audioSource.ErrorsCount + 1) / Math.Log(audioSource.TOC.AudioLength + 1))), + (int)(100 * (1.0 - Math.Log(audioSource.FailedSectors.PopulationCount() + 1) / Math.Log(audioSource.TOC.AudioLength + 1))), cueSheet.Metadata.Artist, cueSheet.Metadata.Title, cueSheet.TOC.Barcode); bool canFix = false; - if (cueSheet.CTDB.QueryExceptionStatus == WebExceptionStatus.Success && audioSource.ErrorsCount != 0) + if (cueSheet.CTDB.QueryExceptionStatus == WebExceptionStatus.Success && audioSource.FailedSectors.PopulationCount() != 0) { foreach (DBEntry entry in cueSheet.CTDB.Entries) if (entry.hasErrors && entry.canRecover) canFix = true; } this.Invoke((MethodInvoker)delegate() - { - DialogResult dlgRes = audioSource.ErrorsCount != 0 ? + { + DialogResult dlgRes = audioSource.FailedSectors.PopulationCount() != 0 ? MessageBox.Show(this, cueSheet.GenerateAccurateRipStatus() + (canFix ? "\n" + Properties.Resources.DoneRippingRepair : "") + ".", Properties.Resources.DoneRippingErrors, MessageBoxButtons.OK, MessageBoxIcon.Error) : MessageBox.Show(this, cueSheet.GenerateAccurateRipStatus() + ".", Properties.Resources.DoneRipping, MessageBoxButtons.OK, MessageBoxIcon.Information); }); diff --git a/CUERipper/frmCUERipper.resx b/CUERipper/frmCUERipper.resx index fb45f6f..ffb9725 100644 --- a/CUERipper/frmCUERipper.resx +++ b/CUERipper/frmCUERipper.resx @@ -816,7 +816,7 @@ AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj0yLjAuMC4w LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAABy - CQAAAk1TRnQBSQFMAgEBBAEAAcQBAgHEAQIBEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo + CQAAAk1TRnQBSQFMAgEBBAEAAcwBAgHMAQIBEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo AwABQAMAASADAAEBAQABCAYAAQgYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5 AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA @@ -966,7 +966,7 @@ AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj0yLjAuMC4w LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAAAY - EgAAAk1TRnQBSQFMAgEBCwEAAcQBAgHEAQIBEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo + EgAAAk1TRnQBSQFMAgEBCwEAAcwBAgHMAQIBEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo AwABQAMAATADAAEBAQABCAYAAQwYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5 AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA diff --git a/CUETools.Processor/CUESheet.cs b/CUETools.Processor/CUESheet.cs index 4e7ea2b..634c56d 100644 --- a/CUETools.Processor/CUESheet.cs +++ b/CUETools.Processor/CUESheet.cs @@ -2239,7 +2239,7 @@ namespace CUETools.Processor uint sec_end = Math.Min(sec_start + 74, tr_start + len - 1); bool fError = false; for (uint iSector = sec_start; iSector <= sec_end; iSector++) - if (_ripper.Errors[(int)iSector - (int)_toc[_toc.FirstAudio][0].Start]) + if (_ripper.FailedSectors[(int)iSector - (int)_toc[_toc.FirstAudio][0].Start]) fError = true; if (fError) { @@ -2250,7 +2250,7 @@ namespace CUETools.Processor uint jsec_end = Math.Min(jsec_start + 74, tr_start + len - 1); bool jfError = false; for (uint jSector = jsec_start; jSector <= jsec_end; jSector++) - if (_ripper.Errors[(int)jSector - (int)_toc[_toc.FirstAudio][0].Start]) + if (_ripper.FailedSectors[(int)jSector - (int)_toc[_toc.FirstAudio][0].Start]) jfError = true; if (!jfError) { @@ -2429,10 +2429,10 @@ namespace CUETools.Processor if (prefix != "") prefix += ", "; prefix += "CTDB: " + CTDB.Status; } - if (_isCD && _ripper.ErrorsCount > 0) + if (_isCD && _ripper.FailedSectors.PopulationCount() > 0) { if (prefix != "") prefix += ", "; - prefix += "ripper found " + _ripper.ErrorsCount + " suspicious sectors"; + prefix += "ripper found " + _ripper.FailedSectors.PopulationCount() + " suspicious sectors"; } if (prefix == "") prefix += "done"; diff --git a/CUETools.Processor/CUESheetLogWriter.cs b/CUETools.Processor/CUESheetLogWriter.cs index 4f49de2..eaadfe0 100644 --- a/CUETools.Processor/CUESheetLogWriter.cs +++ b/CUETools.Processor/CUESheetLogWriter.cs @@ -2,6 +2,7 @@ using System.IO; using CUETools.AccurateRip; using CUETools.CDImage; +using CUETools.Ripper; using System.Globalization; namespace CUETools.Processor @@ -85,11 +86,9 @@ namespace CUETools.Processor private static double GetRangeQuality(CUESheet sheet, uint start, uint length) { - int errCount = 0; - for (uint iSector = start; iSector < start + length; iSector++) - if (sheet.CDRipper.Errors[(int)iSector - (int)sheet.TOC[sheet.TOC.FirstAudio][0].Start]) - errCount++; - return 100 * (1.0 - Math.Log(errCount / 5.0 + 1) / Math.Log(length / 5.0 + 1)); + int failedSectorsCount = sheet.CDRipper.FailedSectors.PopulationCount((int)start - (int)sheet.TOC[sheet.TOC.FirstAudio][0].Start, (int)length); + int retrySectorsCount = sheet.CDRipper.RetrySectors.PopulationCount((int)start - (int)sheet.TOC[sheet.TOC.FirstAudio][0].Start, (int)length); + return 100 * (1.0 - Math.Log(failedSectorsCount / 5.0 + retrySectorsCount / 100.0 + 1) / Math.Log(length / 5.0 + length / 100.0 + 1)); } public static string GetExactAudioCopyLog(CUESheet sheet) diff --git a/CUETools.Ripper.Console/Program.cs b/CUETools.Ripper.Console/Program.cs index 89c74e5..051b18c 100644 --- a/CUETools.Ripper.Console/Program.cs +++ b/CUETools.Ripper.Console/Program.cs @@ -254,7 +254,7 @@ namespace CUETools.ConsoleRipper Console.Write("\r \r"); Console.WriteLine("Results : {0:0.00}x; {1:d5} errors; {2:d2}:{3:d2}:{4:d2}", audioSource.Length / totalElapsed.TotalSeconds / audioSource.PCM.SampleRate, - audioSource.ErrorsCount, + audioSource.FailedSectors.PopulationCount(), totalElapsed.Hours, totalElapsed.Minutes, totalElapsed.Seconds ); audioDest.Close(); @@ -267,7 +267,7 @@ namespace CUETools.ConsoleRipper bool wereErrors = false; for (int iTrack = 1; iTrack <= audioSource.TOC.AudioTracks; iTrack++) for (uint iSector = audioSource.TOC[iTrack].Start; iSector <= audioSource.TOC[iTrack].End; iSector ++) - if (audioSource.Errors[(int)iSector]) + if (audioSource.FailedSectors[(int)iSector]) { if (!wereErrors) { diff --git a/CUETools.Ripper.SCSI/SCSIDrive.cs b/CUETools.Ripper.SCSI/SCSIDrive.cs index 305a9d8..507ab96 100644 --- a/CUETools.Ripper.SCSI/SCSIDrive.cs +++ b/CUETools.Ripper.SCSI/SCSIDrive.cs @@ -60,8 +60,7 @@ namespace CUETools.Ripper.SCSI public long[,,] UserData; public byte[,] C2Count; public long[] byte2long; - BitArray _errors; - int _errorsCount; + BitArray m_failedSectors, m_retrySctors; int _crcErrorsCount = 0; AudioBuffer currentData = new AudioBuffer(AudioPCMConfig.RedBook, MSECTORS * 588); short[] _valueScore = new short[256]; @@ -86,21 +85,21 @@ namespace CUETools.Ripper.SCSI } } - public BitArray Errors + public BitArray FailedSectors { get { - return _errors; + return m_failedSectors; } } - public int ErrorsCount - { - get - { - return _errorsCount; - } - } + public BitArray RetrySectors + { + get + { + return m_retrySctors; + } + } public int Timeout { @@ -967,7 +966,7 @@ namespace CUETools.Ripper.SCSI throw ex; } - private unsafe void CorrectSectors(int pass, int sector, int Sectors2Read, bool markErrors) + private unsafe void CorrectSectors(int pass, int sector, int Sectors2Read, BitArray markErrors) { for (int iSector = 0; iSector < Sectors2Read; iSector++) { @@ -1005,11 +1004,8 @@ namespace CUETools.Ripper.SCSI //_currentErrorsCount += newerr; _currentErrorsCount += newerr - errtmp[pos]; errtmp[pos] = newerr; - if (markErrors) - { - _errors[sector + iSector] |= fError; - _errorsCount += fError ? 1 : 0; - } + if (markErrors != null) + markErrors[sector + iSector] |= fError; } } @@ -1075,7 +1071,7 @@ namespace CUETools.Ripper.SCSI //TimeSpan delay1 = DateTime.Now - LastFetch; //DateTime LastFetched = DateTime.Now; if (pass >= _correctionQuality) - CorrectSectors(pass, sector, Sectors2Read, pass == max_scans - 1); + CorrectSectors(pass, sector, Sectors2Read, pass == max_scans - 1 ? m_failedSectors : pass == _correctionQuality ? m_retrySctors : null); //TimeSpan delay2 = DateTime.Now - LastFetched; //if (sector == _currentStart) //System.Console.WriteLine("\n{0},{1}", delay1.TotalMilliseconds, delay2.TotalMilliseconds); @@ -1194,10 +1190,10 @@ namespace CUETools.Ripper.SCSI if (_toc == null || _toc.AudioLength <= 0) throw new ReadCDException(Resource1.NoAudio); _crcErrorsCount = 0; - _errorsCount = 0; _currentStart = -1; _currentEnd = -1; - _errors = new BitArray((int)_toc.AudioLength); // !!! + m_failedSectors = new BitArray((int)_toc.AudioLength); // !!! + m_retrySctors = new BitArray((int)_toc.AudioLength); _sampleOffset = (int)value + _driveOffset; } } diff --git a/CUETools.Ripper/Ripper.cs b/CUETools.Ripper/Ripper.cs index 96a09ac..0fcccae 100644 --- a/CUETools.Ripper/Ripper.cs +++ b/CUETools.Ripper/Ripper.cs @@ -21,8 +21,8 @@ namespace CUETools.Ripper string RipperVersion { get; } string CurrentReadCommand { get; } int CorrectionQuality { get; set; } - int ErrorsCount { get; } - BitArray Errors { get; } + BitArray FailedSectors { get; } + BitArray RetrySectors { get; } event EventHandler ReadProgress; } @@ -62,4 +62,30 @@ namespace CUETools.Ripper PassTime = passTime; } } + + public static class BitArrayUtils + { + public static int PopulationCount(this BitArray bits, int start, int len) + { + int cnt = 0; + for (int i = start; i < start + len; i++) + if (bits[i]) + cnt++; + return cnt; + } + + public static int PopulationCount(this BitArray bits) + { + return bits.PopulationCount(0, bits.Count); + } + } +} + +namespace System.Runtime.CompilerServices +{ + [AttributeUsageAttribute(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Method)] + internal sealed class ExtensionAttribute : Attribute + { + public ExtensionAttribute() { } + } }