CUERipper: More precise measurement of track quality. Quality will now be less

than 100% if retries were made, even if retries were successful.
This commit is contained in:
Grigory Chudov
2013-05-07 00:13:50 -04:00
parent d54c133024
commit 110f6b19f4
7 changed files with 60 additions and 39 deletions

View File

@@ -408,20 +408,20 @@ namespace CUERipper
cueSheet.CTDB.Submit( cueSheet.CTDB.Submit(
(int)cueSheet.ArVerify.WorstConfidence() + 1, (int)cueSheet.ArVerify.WorstConfidence() + 1,
audioSource.CorrectionQuality == 0 ? 0 : 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.Artist,
cueSheet.Metadata.Title, cueSheet.Metadata.Title,
cueSheet.TOC.Barcode); cueSheet.TOC.Barcode);
bool canFix = false; 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) foreach (DBEntry entry in cueSheet.CTDB.Entries)
if (entry.hasErrors && entry.canRecover) if (entry.hasErrors && entry.canRecover)
canFix = true; canFix = true;
} }
this.Invoke((MethodInvoker)delegate() 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() + (canFix ? "\n" + Properties.Resources.DoneRippingRepair : "") + ".", Properties.Resources.DoneRippingErrors, MessageBoxButtons.OK, MessageBoxIcon.Error) :
MessageBox.Show(this, cueSheet.GenerateAccurateRipStatus() + ".", Properties.Resources.DoneRipping, MessageBoxButtons.OK, MessageBoxIcon.Information); MessageBox.Show(this, cueSheet.GenerateAccurateRipStatus() + ".", Properties.Resources.DoneRipping, MessageBoxButtons.OK, MessageBoxIcon.Information);
}); });

View File

@@ -816,7 +816,7 @@
AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj0yLjAuMC4w AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj0yLjAuMC4w
LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0
ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAABy ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAABy
CQAAAk1TRnQBSQFMAgEBBAEAAcQBAgHEAQIBEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo CQAAAk1TRnQBSQFMAgEBBAEAAcwBAgHMAQIBEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo
AwABQAMAASADAAEBAQABCAYAAQgYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA AwABQAMAASADAAEBAQABCAYAAQgYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA
AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5 AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5
AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA
@@ -966,7 +966,7 @@
AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj0yLjAuMC4w AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj0yLjAuMC4w
LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0
ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAAAY ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAAAY
EgAAAk1TRnQBSQFMAgEBCwEAAcQBAgHEAQIBEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo EgAAAk1TRnQBSQFMAgEBCwEAAcwBAgHMAQIBEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo
AwABQAMAATADAAEBAQABCAYAAQwYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA AwABQAMAATADAAEBAQABCAYAAQwYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA
AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5 AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5
AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA

View File

@@ -2239,7 +2239,7 @@ namespace CUETools.Processor
uint sec_end = Math.Min(sec_start + 74, tr_start + len - 1); uint sec_end = Math.Min(sec_start + 74, tr_start + len - 1);
bool fError = false; bool fError = false;
for (uint iSector = sec_start; iSector <= sec_end; iSector++) 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; fError = true;
if (fError) if (fError)
{ {
@@ -2250,7 +2250,7 @@ namespace CUETools.Processor
uint jsec_end = Math.Min(jsec_start + 74, tr_start + len - 1); uint jsec_end = Math.Min(jsec_start + 74, tr_start + len - 1);
bool jfError = false; bool jfError = false;
for (uint jSector = jsec_start; jSector <= jsec_end; jSector++) 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; jfError = true;
if (!jfError) if (!jfError)
{ {
@@ -2429,10 +2429,10 @@ namespace CUETools.Processor
if (prefix != "") prefix += ", "; if (prefix != "") prefix += ", ";
prefix += "CTDB: " + CTDB.Status; prefix += "CTDB: " + CTDB.Status;
} }
if (_isCD && _ripper.ErrorsCount > 0) if (_isCD && _ripper.FailedSectors.PopulationCount() > 0)
{ {
if (prefix != "") prefix += ", "; if (prefix != "") prefix += ", ";
prefix += "ripper found " + _ripper.ErrorsCount + " suspicious sectors"; prefix += "ripper found " + _ripper.FailedSectors.PopulationCount() + " suspicious sectors";
} }
if (prefix == "") if (prefix == "")
prefix += "done"; prefix += "done";

View File

@@ -2,6 +2,7 @@
using System.IO; using System.IO;
using CUETools.AccurateRip; using CUETools.AccurateRip;
using CUETools.CDImage; using CUETools.CDImage;
using CUETools.Ripper;
using System.Globalization; using System.Globalization;
namespace CUETools.Processor namespace CUETools.Processor
@@ -85,11 +86,9 @@ namespace CUETools.Processor
private static double GetRangeQuality(CUESheet sheet, uint start, uint length) private static double GetRangeQuality(CUESheet sheet, uint start, uint length)
{ {
int errCount = 0; int failedSectorsCount = sheet.CDRipper.FailedSectors.PopulationCount((int)start - (int)sheet.TOC[sheet.TOC.FirstAudio][0].Start, (int)length);
for (uint iSector = start; iSector < start + length; iSector++) int retrySectorsCount = sheet.CDRipper.RetrySectors.PopulationCount((int)start - (int)sheet.TOC[sheet.TOC.FirstAudio][0].Start, (int)length);
if (sheet.CDRipper.Errors[(int)iSector - (int)sheet.TOC[sheet.TOC.FirstAudio][0].Start]) return 100 * (1.0 - Math.Log(failedSectorsCount / 5.0 + retrySectorsCount / 100.0 + 1) / Math.Log(length / 5.0 + length / 100.0 + 1));
errCount++;
return 100 * (1.0 - Math.Log(errCount / 5.0 + 1) / Math.Log(length / 5.0 + 1));
} }
public static string GetExactAudioCopyLog(CUESheet sheet) public static string GetExactAudioCopyLog(CUESheet sheet)

View File

@@ -254,7 +254,7 @@ namespace CUETools.ConsoleRipper
Console.Write("\r \r"); Console.Write("\r \r");
Console.WriteLine("Results : {0:0.00}x; {1:d5} errors; {2:d2}:{3:d2}:{4:d2}", Console.WriteLine("Results : {0:0.00}x; {1:d5} errors; {2:d2}:{3:d2}:{4:d2}",
audioSource.Length / totalElapsed.TotalSeconds / audioSource.PCM.SampleRate, audioSource.Length / totalElapsed.TotalSeconds / audioSource.PCM.SampleRate,
audioSource.ErrorsCount, audioSource.FailedSectors.PopulationCount(),
totalElapsed.Hours, totalElapsed.Minutes, totalElapsed.Seconds totalElapsed.Hours, totalElapsed.Minutes, totalElapsed.Seconds
); );
audioDest.Close(); audioDest.Close();
@@ -267,7 +267,7 @@ namespace CUETools.ConsoleRipper
bool wereErrors = false; bool wereErrors = false;
for (int iTrack = 1; iTrack <= audioSource.TOC.AudioTracks; iTrack++) for (int iTrack = 1; iTrack <= audioSource.TOC.AudioTracks; iTrack++)
for (uint iSector = audioSource.TOC[iTrack].Start; iSector <= audioSource.TOC[iTrack].End; iSector ++) 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) if (!wereErrors)
{ {

View File

@@ -60,8 +60,7 @@ namespace CUETools.Ripper.SCSI
public long[,,] UserData; public long[,,] UserData;
public byte[,] C2Count; public byte[,] C2Count;
public long[] byte2long; public long[] byte2long;
BitArray _errors; BitArray m_failedSectors, m_retrySctors;
int _errorsCount;
int _crcErrorsCount = 0; int _crcErrorsCount = 0;
AudioBuffer currentData = new AudioBuffer(AudioPCMConfig.RedBook, MSECTORS * 588); AudioBuffer currentData = new AudioBuffer(AudioPCMConfig.RedBook, MSECTORS * 588);
short[] _valueScore = new short[256]; short[] _valueScore = new short[256];
@@ -86,21 +85,21 @@ namespace CUETools.Ripper.SCSI
} }
} }
public BitArray Errors public BitArray FailedSectors
{ {
get get
{ {
return _errors; return m_failedSectors;
} }
} }
public int ErrorsCount public BitArray RetrySectors
{ {
get get
{ {
return _errorsCount; return m_retrySctors;
} }
} }
public int Timeout public int Timeout
{ {
@@ -967,7 +966,7 @@ namespace CUETools.Ripper.SCSI
throw ex; 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++) for (int iSector = 0; iSector < Sectors2Read; iSector++)
{ {
@@ -1005,11 +1004,8 @@ namespace CUETools.Ripper.SCSI
//_currentErrorsCount += newerr; //_currentErrorsCount += newerr;
_currentErrorsCount += newerr - errtmp[pos]; _currentErrorsCount += newerr - errtmp[pos];
errtmp[pos] = newerr; errtmp[pos] = newerr;
if (markErrors) if (markErrors != null)
{ markErrors[sector + iSector] |= fError;
_errors[sector + iSector] |= fError;
_errorsCount += fError ? 1 : 0;
}
} }
} }
@@ -1075,7 +1071,7 @@ namespace CUETools.Ripper.SCSI
//TimeSpan delay1 = DateTime.Now - LastFetch; //TimeSpan delay1 = DateTime.Now - LastFetch;
//DateTime LastFetched = DateTime.Now; //DateTime LastFetched = DateTime.Now;
if (pass >= _correctionQuality) 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; //TimeSpan delay2 = DateTime.Now - LastFetched;
//if (sector == _currentStart) //if (sector == _currentStart)
//System.Console.WriteLine("\n{0},{1}", delay1.TotalMilliseconds, delay2.TotalMilliseconds); //System.Console.WriteLine("\n{0},{1}", delay1.TotalMilliseconds, delay2.TotalMilliseconds);
@@ -1194,10 +1190,10 @@ namespace CUETools.Ripper.SCSI
if (_toc == null || _toc.AudioLength <= 0) if (_toc == null || _toc.AudioLength <= 0)
throw new ReadCDException(Resource1.NoAudio); throw new ReadCDException(Resource1.NoAudio);
_crcErrorsCount = 0; _crcErrorsCount = 0;
_errorsCount = 0;
_currentStart = -1; _currentStart = -1;
_currentEnd = -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; _sampleOffset = (int)value + _driveOffset;
} }
} }

View File

@@ -21,8 +21,8 @@ namespace CUETools.Ripper
string RipperVersion { get; } string RipperVersion { get; }
string CurrentReadCommand { get; } string CurrentReadCommand { get; }
int CorrectionQuality { get; set; } int CorrectionQuality { get; set; }
int ErrorsCount { get; } BitArray FailedSectors { get; }
BitArray Errors { get; } BitArray RetrySectors { get; }
event EventHandler<ReadProgressArgs> ReadProgress; event EventHandler<ReadProgressArgs> ReadProgress;
} }
@@ -62,4 +62,30 @@ namespace CUETools.Ripper
PassTime = passTime; 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() { }
}
} }