mirror of
https://github.com/claunia/cuetools.net.git
synced 2025-12-16 18:14:25 +00:00
more work on ripper
This commit is contained in:
@@ -76,6 +76,7 @@ namespace Bwg.Scsi
|
||||
SetCdSpeed = 0xBB,
|
||||
MechanismStatus = 0xBD,
|
||||
ReadCd = 0xBE,
|
||||
SendDvdStructure = 0xBF
|
||||
SendDvdStructure = 0xBF,
|
||||
ReadCDDA = 0xD8
|
||||
} ;
|
||||
}
|
||||
|
||||
@@ -2161,7 +2161,7 @@ namespace Bwg.Scsi
|
||||
/// <param name="start"></param>
|
||||
/// <param name="length"></param>
|
||||
/// <param name="data">the memory area </param>
|
||||
/// <param name="size">the size of the memory area given by the data parameter</param>
|
||||
/// <param name="timeout">timeout (in seconds)</param>
|
||||
/// <returns></returns>
|
||||
public CommandStatus ReadCDAndSubChannel(MainChannelSelection mainmode, SubChannelMode submode, C2ErrorMode c2mode, byte exp, bool dap, uint start, uint length, IntPtr data, int timeout)
|
||||
{
|
||||
@@ -2204,6 +2204,41 @@ namespace Bwg.Scsi
|
||||
return CommandStatus.Success;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="submode">subchannel mode</param>
|
||||
/// <param name="start"></param>
|
||||
/// <param name="length"></param>
|
||||
/// <param name="data">the memory area </param>
|
||||
/// <param name="timeout">timeout (in seconds)</param>
|
||||
/// <returns></returns>
|
||||
public CommandStatus ReadCDDA(SubChannelMode submode, uint start, uint length, IntPtr data, int timeout)
|
||||
{
|
||||
if (m_logger != null)
|
||||
{
|
||||
string args = start.ToString() + ", " + length.ToString() + ", data";
|
||||
m_logger.LogMessage(new UserMessage(UserMessage.Category.Debug, 8, "Bwg.Scsi.Device.ReadCDDA(" + args + ")"));
|
||||
}
|
||||
|
||||
byte mode = (byte)(submode == SubChannelMode.QOnly ? 1 : submode == SubChannelMode.RWMode ? 2 : 0);
|
||||
int size = 4 * 588 + (submode == SubChannelMode.QOnly ? 16 : submode == SubChannelMode.RWMode ? 96 : 0);
|
||||
|
||||
using (Command cmd = new Command(ScsiCommandCode.ReadCDDA, 12, data, size, Command.CmdDirection.In, timeout))
|
||||
{
|
||||
cmd.SetCDB8(1, 0 << 5); // lun
|
||||
cmd.SetCDB32(2, start);
|
||||
cmd.SetCDB24(7, length);
|
||||
cmd.SetCDB8(10, mode); // Subchannel
|
||||
|
||||
CommandStatus st = SendCommand(cmd);
|
||||
if (st != CommandStatus.Success)
|
||||
return st;
|
||||
}
|
||||
|
||||
return CommandStatus.Success;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read CD header data from the disk
|
||||
/// </summary>
|
||||
|
||||
@@ -86,12 +86,22 @@
|
||||
<Compile Include="frmCUERipper.Designer.cs">
|
||||
<DependentUpon>frmCUERipper.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="frmRelease.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="frmRelease.Designer.cs">
|
||||
<DependentUpon>frmRelease.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<EmbeddedResource Include="frmCUERipper.resx">
|
||||
<SubType>Designer</SubType>
|
||||
<DependentUpon>frmCUERipper.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="frmRelease.resx">
|
||||
<SubType>Designer</SubType>
|
||||
<DependentUpon>frmRelease.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
|
||||
21
CUERipper/frmCUERipper.Designer.cs
generated
21
CUERipper/frmCUERipper.Designer.cs
generated
@@ -48,8 +48,11 @@ namespace CUERipper
|
||||
this.buttonPause = new System.Windows.Forms.Button();
|
||||
this.comboRelease = new System.Windows.Forms.ComboBox();
|
||||
this.releaseBindingSource = new System.Windows.Forms.BindingSource(this.components);
|
||||
this.contextMenuStripRelease = new System.Windows.Forms.ContextMenuStrip(this.components);
|
||||
this.editToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.statusStrip1.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.releaseBindingSource)).BeginInit();
|
||||
this.contextMenuStripRelease.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// comboDrives
|
||||
@@ -106,6 +109,7 @@ namespace CUERipper
|
||||
this.listTracks.Name = "listTracks";
|
||||
this.listTracks.UseCompatibleStateImageBehavior = false;
|
||||
this.listTracks.View = System.Windows.Forms.View.Details;
|
||||
this.listTracks.AfterLabelEdit += new System.Windows.Forms.LabelEditEventHandler(this.listTracks_AfterLabelEdit);
|
||||
this.listTracks.DoubleClick += new System.EventHandler(this.listTracks_DoubleClick);
|
||||
this.listTracks.PreviewKeyDown += new System.Windows.Forms.PreviewKeyDownEventHandler(this.listTracks_PreviewKeyDown);
|
||||
this.listTracks.KeyDown += new System.Windows.Forms.KeyEventHandler(this.listTracks_KeyDown);
|
||||
@@ -183,6 +187,7 @@ namespace CUERipper
|
||||
// comboRelease
|
||||
//
|
||||
resources.ApplyResources(this.comboRelease, "comboRelease");
|
||||
this.comboRelease.ContextMenuStrip = this.contextMenuStripRelease;
|
||||
this.comboRelease.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||
this.comboRelease.FormattingEnabled = true;
|
||||
this.comboRelease.Name = "comboRelease";
|
||||
@@ -193,6 +198,19 @@ namespace CUERipper
|
||||
//
|
||||
this.releaseBindingSource.DataSource = typeof(MusicBrainz.Release);
|
||||
//
|
||||
// contextMenuStripRelease
|
||||
//
|
||||
this.contextMenuStripRelease.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.editToolStripMenuItem});
|
||||
this.contextMenuStripRelease.Name = "contextMenuStripRelease";
|
||||
resources.ApplyResources(this.contextMenuStripRelease, "contextMenuStripRelease");
|
||||
//
|
||||
// editToolStripMenuItem
|
||||
//
|
||||
this.editToolStripMenuItem.Name = "editToolStripMenuItem";
|
||||
resources.ApplyResources(this.editToolStripMenuItem, "editToolStripMenuItem");
|
||||
this.editToolStripMenuItem.Click += new System.EventHandler(this.editToolStripMenuItem_Click);
|
||||
//
|
||||
// frmCUERipper
|
||||
//
|
||||
resources.ApplyResources(this, "$this");
|
||||
@@ -215,6 +233,7 @@ namespace CUERipper
|
||||
this.statusStrip1.ResumeLayout(false);
|
||||
this.statusStrip1.PerformLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.releaseBindingSource)).EndInit();
|
||||
this.contextMenuStripRelease.ResumeLayout(false);
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
@@ -240,6 +259,8 @@ namespace CUERipper
|
||||
private System.Windows.Forms.Button buttonPause;
|
||||
private System.Windows.Forms.ComboBox comboRelease;
|
||||
private System.Windows.Forms.BindingSource releaseBindingSource;
|
||||
private System.Windows.Forms.ContextMenuStrip contextMenuStripRelease;
|
||||
private System.Windows.Forms.ToolStripMenuItem editToolStripMenuItem;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
@@ -25,6 +26,7 @@ namespace CUERipper
|
||||
private OutputAudioFormat _format;
|
||||
private CUEStyle _style;
|
||||
private CUESheet _cueSheet;
|
||||
private string _pathOut;
|
||||
|
||||
public frmCUERipper()
|
||||
{
|
||||
@@ -39,7 +41,13 @@ namespace CUERipper
|
||||
{
|
||||
CDDriveReader reader = new CDDriveReader();
|
||||
if (reader.Open(drive))
|
||||
{
|
||||
int driveOffset;
|
||||
if (!AccurateRipVerify.FindDriveReadOffset(reader.ARName, out driveOffset))
|
||||
; //throw new Exception("Failed to find drive read offset for drive" + _ripper.ARName);
|
||||
reader.DriveOffset = driveOffset;
|
||||
comboDrives.Items.Add(reader);
|
||||
}
|
||||
}
|
||||
if (comboDrives.Items.Count == 0)
|
||||
comboDrives.Items.Add("No CD drives found");
|
||||
@@ -105,58 +113,18 @@ namespace CUERipper
|
||||
{
|
||||
CDDriveReader audioSource = (CDDriveReader)o;
|
||||
audioSource.ReadProgress += new EventHandler<ReadProgressArgs>(CDReadProgress);
|
||||
int[,] buff = new int[audioSource.BestBlockSize, audioSource.ChannelCount];
|
||||
AccurateRipVerify arVerify = new AccurateRipVerify(audioSource.TOC);
|
||||
string ArId = AccurateRipVerify.CalculateAccurateRipId(audioSource.TOC);
|
||||
|
||||
arVerify.ContactAccurateRip(ArId);
|
||||
|
||||
IAudioDest audioDest = null;
|
||||
|
||||
CUESheet.WriteText(_pathOut, _cueSheet.CUESheetContents(_style));
|
||||
CUESheet.WriteText(Path.ChangeExtension(_pathOut, ".log"), _cueSheet.LOGContents());
|
||||
try
|
||||
{
|
||||
audioSource.Position = 0;
|
||||
if (_style == CUEStyle.SingleFile || _style == CUEStyle.SingleFileWithCUE)
|
||||
audioDest = AudioReadWrite.GetAudioDest(_cueSheet.SingleFilename, (long)audioSource.Length, _config);
|
||||
|
||||
for (int iTrack = 0; iTrack <= audioSource.TOC.AudioTracks; iTrack++)
|
||||
{
|
||||
uint samplesRemTrack = (iTrack > 0 ? audioSource.TOC[iTrack].Length : audioSource.TOC.Pregap) * 588;
|
||||
if (_style == CUEStyle.GapsAppended)
|
||||
{
|
||||
if (audioDest != null)
|
||||
audioDest.Close();
|
||||
audioDest = AudioReadWrite.GetAudioDest(iTrack > 0 ? _cueSheet.TrackFilenames[iTrack - 1] : _cueSheet.HTOAFilename, (long)samplesRemTrack, _config);
|
||||
}
|
||||
while (samplesRemTrack > 0)
|
||||
{
|
||||
uint toRead = Math.Min((uint)buff.GetLength(0), (uint)samplesRemTrack);
|
||||
uint samplesRead = audioSource.Read(buff, toRead);
|
||||
if (samplesRead != toRead)
|
||||
throw new Exception("samples read != samples requested");
|
||||
arVerify.Write(buff, samplesRead);
|
||||
audioDest.Write(buff, samplesRead);
|
||||
samplesRemTrack -= samplesRead;
|
||||
}
|
||||
}
|
||||
|
||||
if (audioDest != null)
|
||||
audioDest.Close();
|
||||
audioDest = null;
|
||||
_cueSheet.WriteAudioFiles(".", _style);
|
||||
}
|
||||
catch (StopException)
|
||||
{
|
||||
if (audioDest != null)
|
||||
try { audioDest.Close(); }
|
||||
catch { };
|
||||
audioDest = null;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (audioDest != null)
|
||||
try { audioDest.Close(); }
|
||||
catch { };
|
||||
audioDest = null;
|
||||
this.Invoke((MethodInvoker)delegate()
|
||||
{
|
||||
string message = "Exception";
|
||||
@@ -165,6 +133,7 @@ namespace CUERipper
|
||||
DialogResult dlgRes = MessageBox.Show(this, message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
});
|
||||
}
|
||||
audioSource.ReadProgress -= new EventHandler<ReadProgressArgs>(CDReadProgress);
|
||||
_workThread = null;
|
||||
this.BeginInvoke((MethodInvoker)delegate()
|
||||
{
|
||||
@@ -176,17 +145,20 @@ namespace CUERipper
|
||||
{
|
||||
if (_reader == null)
|
||||
return;
|
||||
|
||||
|
||||
_style = comboImage.SelectedIndex == 0 ? CUEStyle.SingleFileWithCUE :
|
||||
CUEStyle.GapsAppended;
|
||||
_pathOut = _config.CleanseString(_cueSheet.Artist) + " - " +
|
||||
_config.CleanseString(_cueSheet.Title) + ".cue";
|
||||
_config.lossyWAVHybrid = comboLossless.SelectedIndex == 1; // _cueSheet.Config?
|
||||
_config.singleFilenameFormat = "%D - %C.cue";
|
||||
if (_style == CUEStyle.SingleFileWithCUE)
|
||||
_cueSheet.SingleFilename = Path.GetFileName(_pathOut);
|
||||
_format = (string)comboCodec.SelectedItem == "wav" ? OutputAudioFormat.WAV :
|
||||
(string)comboCodec.SelectedItem == "flac" ? OutputAudioFormat.FLAC :
|
||||
(string)comboCodec.SelectedItem == "wv" ? OutputAudioFormat.WavPack :
|
||||
(string)comboCodec.SelectedItem == "ape" ? OutputAudioFormat.APE :
|
||||
OutputAudioFormat.NoAudio;
|
||||
_style = comboImage.SelectedIndex == 0 ? CUEStyle.SingleFileWithCUE :
|
||||
CUEStyle.GapsAppended;
|
||||
_cueSheet.GenerateFilenames(_format, comboLossless.SelectedIndex != 0, ".");
|
||||
_cueSheet.GenerateFilenames(_format, comboLossless.SelectedIndex != 0, _pathOut);
|
||||
|
||||
_workThread = new Thread(Rip);
|
||||
_workThread.Priority = ThreadPriority.BelowNormal;
|
||||
@@ -197,31 +169,12 @@ namespace CUERipper
|
||||
|
||||
private void buttonAbort_Click(object sender, EventArgs e)
|
||||
{
|
||||
lock (_startStop)
|
||||
{
|
||||
if (_startStop._pause)
|
||||
{
|
||||
_startStop._pause = false;
|
||||
Monitor.Pulse(_startStop);
|
||||
}
|
||||
_startStop._stop = true;
|
||||
}
|
||||
_startStop.Stop();
|
||||
}
|
||||
|
||||
private void buttonPause_Click(object sender, EventArgs e)
|
||||
{
|
||||
lock (_startStop)
|
||||
{
|
||||
if (_startStop._pause)
|
||||
{
|
||||
_startStop._pause = false;
|
||||
Monitor.Pulse(_startStop);
|
||||
}
|
||||
else
|
||||
{
|
||||
_startStop._pause = true;
|
||||
}
|
||||
}
|
||||
_startStop.Pause();
|
||||
}
|
||||
|
||||
private void comboRelease_Format(object sender, ListControlConvertEventArgs e)
|
||||
@@ -283,27 +236,25 @@ namespace CUERipper
|
||||
p.DiscId = audioSource.TOC.MusicBrainzId;
|
||||
Query<Release> results = Release.Query(p);
|
||||
MusicBrainzService.XmlRequest += new EventHandler<XmlRequestEventArgs>(MusicBrainz_LookupProgress);
|
||||
foreach (Release release in results)
|
||||
try
|
||||
{
|
||||
release.GetEvents();
|
||||
release.GetTracks();
|
||||
|
||||
this.BeginInvoke((MethodInvoker)delegate()
|
||||
foreach (Release release in results)
|
||||
{
|
||||
release.GetEvents();
|
||||
release.GetTracks();
|
||||
CUESheet cueSheet = new CUESheet(_config);
|
||||
cueSheet.OpenTOC(audioSource.TOC);
|
||||
cueSheet.Artist = release.GetArtist();
|
||||
cueSheet.Title = release.GetTitle();
|
||||
if (release.GetEvents().Count > 0)
|
||||
General.SetCUELine(cueSheet.Attributes, "REM", "DATE", release.GetEvents()[0].Date.Substring(0, 4), false);
|
||||
for (int i = 1; i <= audioSource.TOC.AudioTracks; i++)
|
||||
cueSheet.OpenCD(audioSource);
|
||||
cueSheet.FillFromMusicBrainz(release);
|
||||
cueSheet.AccurateRip = AccurateRipMode.VerifyAndConvert;
|
||||
cueSheet.ArVerify.ContactAccurateRip(AccurateRipVerify.CalculateAccurateRipId(audioSource.TOC));
|
||||
this.BeginInvoke((MethodInvoker)delegate()
|
||||
{
|
||||
Track track = release.GetTracks()[(int)audioSource.TOC[i].Number - 1];
|
||||
cueSheet.Tracks[i - 1].Title = track.GetTitle();
|
||||
cueSheet.Tracks[i - 1].Artist = track.GetArtist();
|
||||
}
|
||||
comboRelease.Items.Add(cueSheet);
|
||||
});
|
||||
comboRelease.Items.Add(cueSheet);
|
||||
});
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
MusicBrainzService.XmlRequest -= new EventHandler<XmlRequestEventArgs>(MusicBrainz_LookupProgress);
|
||||
this.BeginInvoke((MethodInvoker)delegate()
|
||||
@@ -311,9 +262,16 @@ namespace CUERipper
|
||||
if (comboRelease.Items.Count == 0)
|
||||
{
|
||||
CUESheet cueSheet = new CUESheet(_config);
|
||||
cueSheet.OpenTOC(audioSource.TOC);
|
||||
cueSheet.OpenCD(audioSource);
|
||||
General.SetCUELine(cueSheet.Attributes, "REM", "DISCID", AccurateRipVerify.CalculateCDDBId(audioSource.TOC), false);
|
||||
General.SetCUELine(cueSheet.Attributes, "REM", "COMMENT", CDDriveReader.RipperVersion(), true);
|
||||
cueSheet.Artist = "Unknown Artist";
|
||||
cueSheet.Title = "Unknown Title";
|
||||
cueSheet.AccurateRip = AccurateRipMode.VerifyAndConvert;
|
||||
cueSheet.ArVerify.ContactAccurateRip(AccurateRipVerify.CalculateAccurateRipId(audioSource.TOC));
|
||||
for (int i = 0; i < audioSource.TOC.AudioTracks; i++)
|
||||
cueSheet.Tracks[i].Title = string.Format("Track {0:00}", i + 1);
|
||||
comboRelease.Items.Add(cueSheet);
|
||||
// cueSheet.Tracks[i - 1].Title = "Track " + _reader.TOC[i].Number.ToString();
|
||||
}
|
||||
});
|
||||
_workThread = null;
|
||||
@@ -370,13 +328,20 @@ namespace CUERipper
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class StopException : Exception
|
||||
{
|
||||
public StopException()
|
||||
: base()
|
||||
private void listTracks_AfterLabelEdit(object sender, LabelEditEventArgs e)
|
||||
{
|
||||
CUESheet cueSheet = (CUESheet)comboRelease.SelectedItem;
|
||||
cueSheet.Tracks[e.Item].Title = e.Label;
|
||||
}
|
||||
|
||||
private void editToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
CUESheet cueSheet = (CUESheet)comboRelease.SelectedItem;
|
||||
frmRelease frm = new frmRelease();
|
||||
frm.CUE = cueSheet;
|
||||
frm.ShowDialog();
|
||||
comboRelease.Items[comboRelease.SelectedIndex] = cueSheet;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -388,5 +353,34 @@ namespace CUERipper
|
||||
_stop = false;
|
||||
_pause = false;
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
if (_pause)
|
||||
{
|
||||
_pause = false;
|
||||
Monitor.Pulse(this);
|
||||
}
|
||||
_stop = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void Pause()
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
if (_pause)
|
||||
{
|
||||
_pause = false;
|
||||
Monitor.Pulse(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
_pause = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,29 +142,11 @@
|
||||
<value>$this</value>
|
||||
</data>
|
||||
<data name=">>comboDrives.ZOrder" xml:space="preserve">
|
||||
<value>9</value>
|
||||
<value>10</value>
|
||||
</data>
|
||||
<metadata name="statusStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>0, 371</value>
|
||||
</metadata>
|
||||
<data name="toolStripStatusLabel1.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>200, 17</value>
|
||||
</data>
|
||||
<data name="toolStripStatusLabel1.TextAlign" type="System.Drawing.ContentAlignment, System.Drawing">
|
||||
<value>MiddleLeft</value>
|
||||
</data>
|
||||
<data name="toolStripProgressBar1.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>140, 16</value>
|
||||
</data>
|
||||
<data name="toolStripProgressBar1.ToolTipText" xml:space="preserve">
|
||||
<value>Track progress</value>
|
||||
</data>
|
||||
<data name="toolStripProgressBar2.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>140, 16</value>
|
||||
</data>
|
||||
<data name="toolStripProgressBar2.ToolTipText" xml:space="preserve">
|
||||
<value>Disk progress</value>
|
||||
</data>
|
||||
<data name="statusStrip1.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>0, 371</value>
|
||||
</data>
|
||||
@@ -187,11 +169,50 @@
|
||||
<value>$this</value>
|
||||
</data>
|
||||
<data name=">>statusStrip1.ZOrder" xml:space="preserve">
|
||||
<value>8</value>
|
||||
<value>9</value>
|
||||
</data>
|
||||
<data name="toolStripStatusLabel1.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>200, 17</value>
|
||||
</data>
|
||||
<data name="toolStripStatusLabel1.TextAlign" type="System.Drawing.ContentAlignment, System.Drawing">
|
||||
<value>MiddleLeft</value>
|
||||
</data>
|
||||
<data name="toolStripProgressBar1.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>140, 16</value>
|
||||
</data>
|
||||
<data name="toolStripProgressBar1.ToolTipText" xml:space="preserve">
|
||||
<value>Track progress</value>
|
||||
</data>
|
||||
<data name="toolStripProgressBar2.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>140, 16</value>
|
||||
</data>
|
||||
<data name="toolStripProgressBar2.ToolTipText" xml:space="preserve">
|
||||
<value>Disk progress</value>
|
||||
</data>
|
||||
<data name="listTracks.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
|
||||
<value>Top, Left, Right</value>
|
||||
</data>
|
||||
<data name="listTracks.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>6, 60</value>
|
||||
</data>
|
||||
<data name="listTracks.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>481, 269</value>
|
||||
</data>
|
||||
<data name="listTracks.TabIndex" type="System.Int32, mscorlib">
|
||||
<value>0</value>
|
||||
</data>
|
||||
<data name=">>listTracks.Name" xml:space="preserve">
|
||||
<value>listTracks</value>
|
||||
</data>
|
||||
<data name=">>listTracks.Type" xml:space="preserve">
|
||||
<value>System.Windows.Forms.ListView, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name=">>listTracks.Parent" xml:space="preserve">
|
||||
<value>$this</value>
|
||||
</data>
|
||||
<data name=">>listTracks.ZOrder" xml:space="preserve">
|
||||
<value>8</value>
|
||||
</data>
|
||||
<data name="Title.DisplayIndex" type="System.Int32, mscorlib">
|
||||
<value>1</value>
|
||||
</data>
|
||||
@@ -222,27 +243,6 @@
|
||||
<data name="Length.Width" type="System.Int32, mscorlib">
|
||||
<value>70</value>
|
||||
</data>
|
||||
<data name="listTracks.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>6, 60</value>
|
||||
</data>
|
||||
<data name="listTracks.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>481, 269</value>
|
||||
</data>
|
||||
<data name="listTracks.TabIndex" type="System.Int32, mscorlib">
|
||||
<value>0</value>
|
||||
</data>
|
||||
<data name=">>listTracks.Name" xml:space="preserve">
|
||||
<value>listTracks</value>
|
||||
</data>
|
||||
<data name=">>listTracks.Type" xml:space="preserve">
|
||||
<value>System.Windows.Forms.ListView, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name=">>listTracks.Parent" xml:space="preserve">
|
||||
<value>$this</value>
|
||||
</data>
|
||||
<data name=">>listTracks.ZOrder" xml:space="preserve">
|
||||
<value>7</value>
|
||||
</data>
|
||||
<data name="buttonGo.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
|
||||
<value>Top, Left, Right</value>
|
||||
</data>
|
||||
@@ -268,7 +268,7 @@
|
||||
<value>$this</value>
|
||||
</data>
|
||||
<data name=">>buttonGo.ZOrder" xml:space="preserve">
|
||||
<value>6</value>
|
||||
<value>7</value>
|
||||
</data>
|
||||
<data name="comboLossless.Items" xml:space="preserve">
|
||||
<value>lossless</value>
|
||||
@@ -298,7 +298,7 @@
|
||||
<value>$this</value>
|
||||
</data>
|
||||
<data name=">>comboLossless.ZOrder" xml:space="preserve">
|
||||
<value>5</value>
|
||||
<value>6</value>
|
||||
</data>
|
||||
<data name="comboCodec.Items" xml:space="preserve">
|
||||
<value>flac</value>
|
||||
@@ -331,7 +331,7 @@
|
||||
<value>$this</value>
|
||||
</data>
|
||||
<data name=">>comboCodec.ZOrder" xml:space="preserve">
|
||||
<value>4</value>
|
||||
<value>5</value>
|
||||
</data>
|
||||
<data name="comboImage.Items" xml:space="preserve">
|
||||
<value>image</value>
|
||||
@@ -358,7 +358,7 @@
|
||||
<value>$this</value>
|
||||
</data>
|
||||
<data name=">>comboImage.ZOrder" xml:space="preserve">
|
||||
<value>3</value>
|
||||
<value>4</value>
|
||||
</data>
|
||||
<data name="buttonAbort.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
|
||||
<value>Top, Left, Right</value>
|
||||
@@ -391,7 +391,7 @@
|
||||
<value>$this</value>
|
||||
</data>
|
||||
<data name=">>buttonAbort.ZOrder" xml:space="preserve">
|
||||
<value>2</value>
|
||||
<value>3</value>
|
||||
</data>
|
||||
<data name="buttonPause.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
|
||||
<value>Top, Left, Right</value>
|
||||
@@ -424,11 +424,29 @@
|
||||
<value>$this</value>
|
||||
</data>
|
||||
<data name=">>buttonPause.ZOrder" xml:space="preserve">
|
||||
<value>1</value>
|
||||
<value>2</value>
|
||||
</data>
|
||||
<data name="comboRelease.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
|
||||
<value>Top, Left, Right</value>
|
||||
</data>
|
||||
<metadata name="contextMenuStripRelease.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>285, 58</value>
|
||||
</metadata>
|
||||
<data name="editToolStripMenuItem.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>152, 22</value>
|
||||
</data>
|
||||
<data name="editToolStripMenuItem.Text" xml:space="preserve">
|
||||
<value>Edit</value>
|
||||
</data>
|
||||
<data name="contextMenuStripRelease.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>95, 26</value>
|
||||
</data>
|
||||
<data name=">>contextMenuStripRelease.Name" xml:space="preserve">
|
||||
<value>contextMenuStripRelease</value>
|
||||
</data>
|
||||
<data name=">>contextMenuStripRelease.Type" xml:space="preserve">
|
||||
<value>System.Windows.Forms.ContextMenuStrip, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name="comboRelease.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>6, 33</value>
|
||||
</data>
|
||||
@@ -448,7 +466,7 @@
|
||||
<value>$this</value>
|
||||
</data>
|
||||
<data name=">>comboRelease.ZOrder" xml:space="preserve">
|
||||
<value>0</value>
|
||||
<value>1</value>
|
||||
</data>
|
||||
<metadata name="releaseBindingSource.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>116, 371</value>
|
||||
@@ -516,6 +534,12 @@
|
||||
<data name=">>releaseBindingSource.Type" xml:space="preserve">
|
||||
<value>System.Windows.Forms.BindingSource, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name=">>editToolStripMenuItem.Name" xml:space="preserve">
|
||||
<value>editToolStripMenuItem</value>
|
||||
</data>
|
||||
<data name=">>editToolStripMenuItem.Type" xml:space="preserve">
|
||||
<value>System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name=">>$this.Name" xml:space="preserve">
|
||||
<value>frmCUERipper</value>
|
||||
</data>
|
||||
|
||||
@@ -201,6 +201,18 @@ namespace CUETools.CDImage
|
||||
}
|
||||
}
|
||||
|
||||
public bool DCP
|
||||
{
|
||||
get
|
||||
{
|
||||
return _dcp;
|
||||
}
|
||||
set
|
||||
{
|
||||
_dcp = value;
|
||||
}
|
||||
}
|
||||
|
||||
public void AddIndex(CDTrackIndex index)
|
||||
{
|
||||
if (index.Index < 2)
|
||||
@@ -212,7 +224,7 @@ namespace CUETools.CDImage
|
||||
IList<CDTrackIndex> _indexes;
|
||||
string _isrc;
|
||||
bool _isAudio;
|
||||
bool _preEmphasis;
|
||||
bool _preEmphasis, _dcp;
|
||||
uint _start;
|
||||
uint _length;
|
||||
uint _number;
|
||||
|
||||
@@ -439,9 +439,7 @@ namespace CUETools.Processor
|
||||
private CUEConfig _config;
|
||||
private string _cddbDiscIdTag;
|
||||
private bool _isCD;
|
||||
private string _driveName;
|
||||
private int _driveOffset;
|
||||
private BitArray _cdErrors;
|
||||
private CDDriveReader _ripper;
|
||||
private bool _isArchive;
|
||||
private List<string> _archiveContents;
|
||||
private string _archiveCUEpath;
|
||||
@@ -481,17 +479,55 @@ namespace CUETools.Processor
|
||||
_isCD = false;
|
||||
}
|
||||
|
||||
public void OpenTOC(CDImageLayout toc)
|
||||
public void OpenCD(CDDriveReader ripper)
|
||||
{
|
||||
_toc = toc;
|
||||
_ripper = ripper;
|
||||
_toc = (CDImageLayout)_ripper.TOC.Clone();
|
||||
for (int iTrack = 0; iTrack < _toc.AudioTracks; iTrack++)
|
||||
{
|
||||
_trackFilenames.Add(string.Format("{0:00}.wav", iTrack + 1));
|
||||
_tracks.Add(new TrackInfo());
|
||||
}
|
||||
_hasTrackFilenames = false;
|
||||
_accurateRipId = _accurateRipIdActual = AccurateRipVerify.CalculateAccurateRipId(_toc);
|
||||
_arVerify = new AccurateRipVerify(_toc);
|
||||
_isCD = true;
|
||||
SourceInfo cdInfo;
|
||||
cdInfo.Path = _ripper.ARName;
|
||||
cdInfo.Offset = 0;
|
||||
cdInfo.Length = _toc.AudioLength * 588;
|
||||
_sources.Add(cdInfo);
|
||||
_ripper.ReadProgress += new EventHandler<ReadProgressArgs>(CDReadProgress);
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
if (_ripper != null)
|
||||
_ripper.Close();
|
||||
_ripper = null;
|
||||
}
|
||||
|
||||
public AccurateRipVerify ArVerify
|
||||
{
|
||||
get
|
||||
{
|
||||
return _arVerify;
|
||||
}
|
||||
}
|
||||
|
||||
public void FillFromMusicBrainz(Release release)
|
||||
{
|
||||
General.SetCUELine(_attributes, "REM", "DISCID", AccurateRipVerify.CalculateCDDBId(_toc), false);
|
||||
General.SetCUELine(_attributes, "REM", "COMMENT", CDDriveReader.RipperVersion(), true);
|
||||
if (release.GetEvents().Count > 0)
|
||||
General.SetCUELine(_attributes, "REM", "DATE", release.GetEvents()[0].Date.Substring(0, 4), false);
|
||||
Artist = release.GetArtist();
|
||||
Title = release.GetTitle();
|
||||
for (int i = 1; i <= _toc.AudioTracks; i++)
|
||||
{
|
||||
Track track = release.GetTracks()[(int)_toc[i].Number - 1];
|
||||
Tracks[i - 1].Title = track.GetTitle();
|
||||
Tracks[i - 1].Artist = track.GetArtist();
|
||||
}
|
||||
}
|
||||
|
||||
public void Open(string pathIn)
|
||||
@@ -502,27 +538,13 @@ namespace CUETools.Processor
|
||||
{
|
||||
CDDriveReader ripper = new CDDriveReader();
|
||||
ripper.Open(pathIn[0]);
|
||||
_toc = ripper.TOC;
|
||||
_driveName = ripper.ARName;
|
||||
ripper.Close();
|
||||
if (_toc.AudioTracks > 0)
|
||||
if (ripper.TOC.AudioTracks > 0)
|
||||
{
|
||||
if (!AccurateRipVerify.FindDriveReadOffset(_driveName, out _driveOffset))
|
||||
throw new Exception("Failed to find drive read offset for drive" + _driveName);
|
||||
_isCD = true;
|
||||
SourceInfo cdInfo;
|
||||
cdInfo.Path = pathIn;
|
||||
cdInfo.Offset = 0;
|
||||
cdInfo.Length = _toc.AudioLength * 588;
|
||||
_sources.Add(cdInfo);
|
||||
for (int iTrack = 0; iTrack < _toc.AudioTracks; iTrack++)
|
||||
{
|
||||
_trackFilenames.Add(string.Format("{0:00}.wav", iTrack + 1));
|
||||
_tracks.Add(new TrackInfo());
|
||||
}
|
||||
_hasTrackFilenames = false;
|
||||
_accurateRipId = _accurateRipIdActual = AccurateRipVerify.CalculateAccurateRipId(_toc);
|
||||
_arVerify = new AccurateRipVerify(_toc);
|
||||
OpenCD(ripper);
|
||||
int driveOffset;
|
||||
if (!AccurateRipVerify.FindDriveReadOffset(_ripper.ARName, out driveOffset))
|
||||
throw new Exception("Failed to find drive read offset for drive" + _ripper.ARName);
|
||||
_ripper.DriveOffset = driveOffset;
|
||||
|
||||
Release release;
|
||||
ReleaseQueryParameters p = new ReleaseQueryParameters();
|
||||
@@ -533,15 +555,11 @@ namespace CUETools.Processor
|
||||
try
|
||||
{
|
||||
release = results.First();
|
||||
General.SetCUELine(_attributes, "REM", "DISCID", AccurateRipVerify.CalculateCDDBId(_toc), false);
|
||||
General.SetCUELine(_attributes, "REM", "COMMENT", CDDriveReader.RipperVersion(), true);
|
||||
General.SetCUELine(_attributes, "REM", "DATE", release.GetEvents()[0].Date.Substring(0, 4), false);
|
||||
General.SetCUELine(_attributes, "PERFORMER", release.GetArtist(), true);
|
||||
General.SetCUELine(_attributes, "TITLE", release.GetTitle(), true);
|
||||
for (int iTrack = 0; iTrack < _toc.AudioTracks; iTrack++)
|
||||
if (release != null)
|
||||
{
|
||||
General.SetCUELine(_tracks[iTrack].Attributes, "TITLE", release.GetTracks()[iTrack].GetTitle(), true);
|
||||
General.SetCUELine(_tracks[iTrack].Attributes, "PERFORMER ", release.GetTracks()[iTrack].GetArtist(), true);
|
||||
release.GetEvents();
|
||||
release.GetTracks();
|
||||
FillFromMusicBrainz(release);
|
||||
}
|
||||
}
|
||||
catch
|
||||
@@ -1212,7 +1230,7 @@ namespace CUETools.Processor
|
||||
return (int)audioSource.Length;
|
||||
}
|
||||
|
||||
public void WriteText(string path, string text)
|
||||
public static void WriteText(string path, string text)
|
||||
{
|
||||
bool utf8Required = CUESheet.Encoding.GetString(CUESheet.Encoding.GetBytes(text)) != text;
|
||||
StreamWriter sw1 = new StreamWriter(path, false, utf8Required ? Encoding.UTF8 : CUESheet.Encoding);
|
||||
@@ -1222,16 +1240,18 @@ namespace CUETools.Processor
|
||||
|
||||
public string LOGContents()
|
||||
{
|
||||
if (!_isCD)
|
||||
if (!_isCD || _ripper == null)
|
||||
return null;
|
||||
#if !MONO
|
||||
StringWriter logWriter = new StringWriter();
|
||||
logWriter.WriteLine("{0}", CDDriveReader.RipperVersion());
|
||||
logWriter.WriteLine("Extraction logfile from : {0}", DateTime.Now);
|
||||
logWriter.WriteLine("Used drive : {0}", _driveName);
|
||||
logWriter.WriteLine("Read offset correction : {0}", _driveOffset);
|
||||
//logWriter.WriteLine("Read command : {0}", );
|
||||
//logWriter.WriteLine("Secure mode : {0}", );
|
||||
logWriter.WriteLine("Used drive : {0}", _ripper.ARName);
|
||||
logWriter.WriteLine("Read offset correction : {0}", _ripper.DriveOffset);
|
||||
logWriter.WriteLine("Read command : {0}", _ripper.CurrentReadCommand);
|
||||
logWriter.WriteLine("Secure mode : {0}", _ripper.CorrectionQuality);
|
||||
logWriter.WriteLine("Disk length : {0}", CDImageLayout.TimeToString(_toc.AudioLength));
|
||||
logWriter.WriteLine("AccurateRip : {0}", _arVerify.ARStatus == null ? "ok" : _arVerify.ARStatus);
|
||||
if (hdcdDecoder != null && hdcdDecoder.Detected)
|
||||
{
|
||||
hdcd_decoder_statistics stats;
|
||||
@@ -1264,7 +1284,7 @@ namespace CUETools.Processor
|
||||
bool crcMismatch = _accurateRipMode == AccurateRipMode.VerifyThenConvert &&
|
||||
_arVerify.BackupCRC(iTrack) != _arVerify.CRC(iTrack);
|
||||
for (uint iSector = _toc[iTrack + 1].Start; iSector <= _toc[iTrack + 1].End; iSector++)
|
||||
if (_cdErrors[(int)iSector])
|
||||
if (_ripper.Errors[(int)iSector])
|
||||
cdErrors++;
|
||||
if (crcMismatch || cdErrors != 0)
|
||||
{
|
||||
@@ -2040,10 +2060,9 @@ namespace CUETools.Processor
|
||||
if (_isCD && audioSource != null && audioSource is CDDriveReader)
|
||||
{
|
||||
updatedTOC = ((CDDriveReader)audioSource).TOC;
|
||||
_cdErrors = ((CDDriveReader)audioSource).Errors;
|
||||
}
|
||||
#endif
|
||||
if (audioSource != null) audioSource.Close();
|
||||
if (audioSource != null && !_isCD) audioSource.Close();
|
||||
audioSource = GetAudioSource(++iSource);
|
||||
samplesRemSource = (uint)_sources[iSource].Length;
|
||||
}
|
||||
@@ -2073,7 +2092,7 @@ namespace CUETools.Processor
|
||||
hdcdDecoder = null;
|
||||
if (_config.decodeHDCD)
|
||||
{
|
||||
audioSource.Close();
|
||||
if (!_isCD) audioSource.Close();
|
||||
audioDest.Delete();
|
||||
throw new Exception("HDCD not detected.");
|
||||
}
|
||||
@@ -2113,7 +2132,7 @@ namespace CUETools.Processor
|
||||
if (hdcdDecoder != null)
|
||||
hdcdDecoder.AudioDest = null;
|
||||
hdcdDecoder = null;
|
||||
try { if (audioSource != null) audioSource.Close(); }
|
||||
try { if (audioSource != null && !_isCD) audioSource.Close(); }
|
||||
catch { }
|
||||
audioSource = null;
|
||||
try { if (audioDest != null) audioDest.Close(); }
|
||||
@@ -2126,7 +2145,6 @@ namespace CUETools.Processor
|
||||
if (_isCD && audioSource != null && audioSource is CDDriveReader)
|
||||
{
|
||||
updatedTOC = ((CDDriveReader)audioSource).TOC;
|
||||
_cdErrors = ((CDDriveReader)audioSource).Errors;
|
||||
}
|
||||
if (updatedTOC != null)
|
||||
{
|
||||
@@ -2134,10 +2152,15 @@ namespace CUETools.Processor
|
||||
if (_toc.Catalog != null)
|
||||
General.SetCUELine(_attributes, "CATALOG", _toc.Catalog, false);
|
||||
for (iTrack = 1; iTrack <= _toc.TrackCount; iTrack++)
|
||||
if (_toc[iTrack].IsAudio)
|
||||
{
|
||||
if (_toc[iTrack].IsAudio && _toc[iTrack].ISRC != null)
|
||||
if (_toc[iTrack].ISRC != null)
|
||||
General.SetCUELine(_tracks[iTrack - 1].Attributes, "ISRC", _toc[iTrack].ISRC, false);
|
||||
if (_toc[iTrack].IsAudio && _toc[iTrack].PreEmphasis)
|
||||
//if (_toc[iTrack].DCP || _toc[iTrack].PreEmphasis)
|
||||
//cueWriter.WriteLine(" FLAGS{0}{1}", audioSource.TOC[track].PreEmphasis ? " PRE" : "", audioSource.TOC[track].DCP ? " DCP" : "");
|
||||
if (_toc[iTrack].DCP)
|
||||
General.SetCUELine(_tracks[iTrack - 1].Attributes, "FLAGS", "DCP", false);
|
||||
if (_toc[iTrack].PreEmphasis)
|
||||
General.SetCUELine(_tracks[iTrack - 1].Attributes, "FLAGS", "PRE", false);
|
||||
}
|
||||
}
|
||||
@@ -2145,7 +2168,7 @@ namespace CUETools.Processor
|
||||
|
||||
if (hdcdDecoder != null)
|
||||
hdcdDecoder.AudioDest = null;
|
||||
if (audioSource != null)
|
||||
if (audioSource != null && !_isCD)
|
||||
audioSource.Close();
|
||||
if (audioDest != null)
|
||||
audioDest.Close();
|
||||
@@ -2339,11 +2362,8 @@ namespace CUETools.Processor
|
||||
#if !MONO
|
||||
if (_isCD)
|
||||
{
|
||||
CDDriveReader ripper = new CDDriveReader();
|
||||
ripper.Open(sourceInfo.Path[0]);
|
||||
ripper.DriveOffset = _driveOffset;
|
||||
ripper.ReadProgress += new EventHandler<ReadProgressArgs>(CDReadProgress);
|
||||
audioSource = ripper;
|
||||
audioSource = _ripper;
|
||||
audioSource.Position = 0;
|
||||
} else
|
||||
if (_isArchive)
|
||||
{
|
||||
|
||||
@@ -75,11 +75,14 @@ namespace CUETools.ConsoleRipper
|
||||
drives += string.Format("{0}: ", drivesAvailable[i]);
|
||||
Console.WriteLine("Usage : CUERipper.exe <options>");
|
||||
Console.WriteLine();
|
||||
//Console.WriteLine("-S, --secure secure mode, read each block twice;");
|
||||
Console.WriteLine("-S, --secure secure mode, read each block twice (default);");
|
||||
Console.WriteLine("-B, --burst burst (1 pass) mode;");
|
||||
Console.WriteLine("-P, --paranoid maximum level of error correction;");
|
||||
Console.WriteLine("-D, --drive <letter> use a specific CD drive, e.g. {0};", drives);
|
||||
Console.WriteLine("-O, --offset <samples> use specific drive read offset;");
|
||||
Console.WriteLine("-T, --test detect read command;");
|
||||
Console.WriteLine("--d8 force D8h read command;");
|
||||
Console.WriteLine("--be force BEh read command;");
|
||||
}
|
||||
|
||||
static void Main(string[] args)
|
||||
@@ -94,15 +97,22 @@ namespace CUETools.ConsoleRipper
|
||||
string driveLetter = null;
|
||||
int driveOffset = 0;
|
||||
bool test = false;
|
||||
bool forceD8 = false, forceBE = false;
|
||||
for (int arg = 0; arg < args.Length; arg++)
|
||||
{
|
||||
bool ok = true;
|
||||
if (args[arg] == "-P" || args[arg] == "--paranoid")
|
||||
correctionQuality = 4;
|
||||
if (args[arg] == "-T" || args[arg] == "--test")
|
||||
else if (args[arg] == "-S" || args[arg] == "--secure")
|
||||
correctionQuality = 1;
|
||||
else if (args[arg] == "-B" || args[arg] == "--burst")
|
||||
correctionQuality = 0;
|
||||
else if (args[arg] == "-T" || args[arg] == "--test")
|
||||
test = true;
|
||||
//else if (args[arg] == "-B" || args[arg] == "--burst")
|
||||
// correctionQuality = 1;
|
||||
else if (args[arg] == "--d8")
|
||||
forceD8 = true;
|
||||
else if (args[arg] == "--be")
|
||||
forceBE = true;
|
||||
else if ((args[arg] == "-D" || args[arg] == "--drive") && ++arg < args.Length)
|
||||
driveLetter = args[arg];
|
||||
else if ((args[arg] == "-O" || args[arg] == "--offset") && ++arg < args.Length)
|
||||
@@ -149,14 +159,18 @@ namespace CUETools.ConsoleRipper
|
||||
if (!AccurateRipVerify.FindDriveReadOffset(audioSource.ARName, out driveOffset))
|
||||
Console.WriteLine("Unknown read offset for drive {0}!!!", audioSource.Path);
|
||||
//throw new Exception("Failed to find drive read offset for drive" + audioSource.ARName);
|
||||
if (test)
|
||||
{
|
||||
Console.Write(audioSource.AutoDetectReadCommand);
|
||||
return;
|
||||
}
|
||||
|
||||
audioSource.DriveOffset = driveOffset;
|
||||
audioSource.CorrectionQuality = correctionQuality;
|
||||
audioSource.DebugMessages = true;
|
||||
if (forceD8) audioSource.ForceD8 = true;
|
||||
if (forceBE) audioSource.ForceBE = true;
|
||||
string readCmd = audioSource.AutoDetectReadCommand;
|
||||
if (test)
|
||||
{
|
||||
Console.Write(readCmd);
|
||||
return;
|
||||
}
|
||||
|
||||
AccurateRipVerify arVerify = new AccurateRipVerify(audioSource.TOC);
|
||||
int[,] buff = new int[audioSource.BestBlockSize, audioSource.ChannelCount];
|
||||
@@ -183,7 +197,7 @@ namespace CUETools.ConsoleRipper
|
||||
|
||||
Console.WriteLine("Drive : {0}", audioSource.Path);
|
||||
Console.WriteLine("Read offset : {0}", audioSource.DriveOffset);
|
||||
Console.WriteLine("Read cmd : {0}", audioSource.ChosenReadCommand);
|
||||
Console.WriteLine("Read cmd : {0}", audioSource.CurrentReadCommand);
|
||||
Console.WriteLine("Secure mode : {0}", audioSource.CorrectionQuality);
|
||||
Console.WriteLine("Filename : {0}", destFile);
|
||||
Console.WriteLine("Disk length : {0}", CDImageLayout.TimeToString(audioSource.TOC.AudioLength));
|
||||
@@ -285,8 +299,8 @@ namespace CUETools.ConsoleRipper
|
||||
}
|
||||
if (audioSource.TOC[track].ISRC != null)
|
||||
cueWriter.WriteLine(" ISRC {0}", audioSource.TOC[track].ISRC);
|
||||
if (audioSource.TOC[track].PreEmphasis)
|
||||
cueWriter.WriteLine(" FLAGS PRE");
|
||||
if (audioSource.TOC[track].DCP || audioSource.TOC[track].PreEmphasis)
|
||||
cueWriter.WriteLine(" FLAGS{0}{1}", audioSource.TOC[track].PreEmphasis ? " PRE" : "", audioSource.TOC[track].DCP ? " DCP" : "");
|
||||
for (int index = audioSource.TOC[track].Pregap > 0 ? 0 : 1; index <= audioSource.TOC[track].LastIndex; index++)
|
||||
cueWriter.WriteLine(" INDEX {0:00} {1}", index, audioSource.TOC[track][index].MSF);
|
||||
}
|
||||
|
||||
@@ -46,8 +46,9 @@ 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 = 10000000 / (4 * 588);
|
||||
const int MSECTORS = 5*1024*1024 / (4 * 588);
|
||||
int _currentTrack = -1, _currentIndex = -1, _currentTrackActualStart = -1;
|
||||
Logger m_logger;
|
||||
CDImageLayout _toc;
|
||||
@@ -56,17 +57,23 @@ namespace CUETools.Ripper.SCSI
|
||||
int m_max_sectors;
|
||||
int _timeout = 10;
|
||||
Crc16Ccitt _crc;
|
||||
List<ScanResults> _scanResults;
|
||||
ScanResults _currentScan = null;
|
||||
int _currentScan;
|
||||
public byte[,,] UserData;
|
||||
public byte[,,] C2Data;
|
||||
public byte[,,] QData;
|
||||
public long[] Quality;
|
||||
BitArray _errors;
|
||||
int _errorsCount;
|
||||
int _crcErrorsCount = 0;
|
||||
byte[] _currentData = new byte[MSECTORS * 4 * 588];
|
||||
int[] valueScore = new int[256];
|
||||
short[] _valueScore = new short[256];
|
||||
bool _debugMessages = false;
|
||||
ReadCDCommand _readCDCommand = ReadCDCommand.Unknown;
|
||||
ReadCDCommand _forceReadCommand = ReadCDCommand.Unknown;
|
||||
Device.MainChannelSelection _mainChannelMode = Device.MainChannelSelection.UserData;
|
||||
Device.SubChannelMode _subChannelMode = Device.SubChannelMode.None;
|
||||
Device.SubChannelMode _subChannelMode = Device.SubChannelMode.QOnly;
|
||||
Device.C2ErrorMode _c2ErrorMode = Device.C2ErrorMode.Mode296;
|
||||
string m_test_result;
|
||||
string _autodetectResult;
|
||||
byte[] _readBuffer = new byte[NSECTORS * CB_AUDIO];
|
||||
byte[] _subchannelBuffer = new byte[NSECTORS * 16];
|
||||
|
||||
@@ -124,9 +131,36 @@ namespace CUETools.Ripper.SCSI
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_test_result == null)
|
||||
TestReadCommand();
|
||||
return m_test_result;
|
||||
if (_autodetectResult != null || TestReadCommand())
|
||||
return _autodetectResult;
|
||||
string ret = _autodetectResult;
|
||||
_autodetectResult = null;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
public bool ForceD8
|
||||
{
|
||||
get
|
||||
{
|
||||
return _forceReadCommand == ReadCDCommand.ReadCdD8h;
|
||||
}
|
||||
set
|
||||
{
|
||||
_forceReadCommand = value ? ReadCDCommand.ReadCdD8h : ReadCDCommand.Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public bool ForceBE
|
||||
{
|
||||
get
|
||||
{
|
||||
return _forceReadCommand == ReadCDCommand.ReadCdBEh;
|
||||
}
|
||||
set
|
||||
{
|
||||
_forceReadCommand = value ? ReadCDCommand.ReadCdBEh : ReadCDCommand.Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,25 +168,24 @@ namespace CUETools.Ripper.SCSI
|
||||
{
|
||||
get
|
||||
{
|
||||
return string.Format("BEh, {0}, {1}, {2}, {3} blocks at a time", (_mainChannelMode == Device.MainChannelSelection.UserData ? "10h" : "F8h"),
|
||||
return _readCDCommand == ReadCDCommand.Unknown ? "unknown" :
|
||||
string.Format("{0}, {1}, {2}, {3}, {4} blocks at a time",
|
||||
(_readCDCommand == ReadCDCommand.ReadCdBEh ? "BEh" : "D8h"),
|
||||
(_mainChannelMode == Device.MainChannelSelection.UserData ? "10h" : "F8h"),
|
||||
(_subChannelMode == Device.SubChannelMode.None ? "00h" : _subChannelMode == Device.SubChannelMode.QOnly ? "02h" : "04h"),
|
||||
(_c2ErrorMode == Device.C2ErrorMode.None ? "00h" : _c2ErrorMode == Device.C2ErrorMode.Mode294 ? "01h" : "04h"),
|
||||
m_max_sectors);
|
||||
}
|
||||
}
|
||||
|
||||
public string ChosenReadCommand
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_test_result == null && !TestReadCommand() ? "not detected" : CurrentReadCommand;
|
||||
}
|
||||
}
|
||||
|
||||
public CDDriveReader()
|
||||
{
|
||||
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];
|
||||
}
|
||||
|
||||
public bool Open(char Drive)
|
||||
@@ -197,6 +230,7 @@ namespace CUETools.Ripper.SCSI
|
||||
//if (st != Device.CommandStatus.Success)
|
||||
// throw new Exception("GetSpeed failed: SCSI error");
|
||||
|
||||
//m_device.SetCdSpeed(Device.RotationalControl.CLVandNonPureCav, (ushort)(0x7fff), (ushort)(0x7fff));
|
||||
//int bytesPerSec = 4 * 588 * 75 * (pass > 8 ? 4 : pass > 4 ? 8 : pass > 0 ? 16 : 32);
|
||||
//Device.CommandStatus st = m_device.SetStreaming(Device.RotationalControl.CLVandNonPureCav, start, end, bytesPerSec, 1, bytesPerSec, 1);
|
||||
//if (st != Device.CommandStatus.Success)
|
||||
@@ -253,34 +287,39 @@ namespace CUETools.Ripper.SCSI
|
||||
int posCount = 0;
|
||||
for (int iSector = 0; iSector < Sectors2Read; iSector++)
|
||||
{
|
||||
int q_pos = sector - _currentStart + iSector;
|
||||
int ctl = _currentScan.QData[q_pos, 0] >> 4;
|
||||
int adr = _currentScan.QData[q_pos, 0] & 7;
|
||||
int q_pos = (sector - _currentStart + iSector);
|
||||
int ctl = QData[_currentScan, q_pos, 0] >> 4;
|
||||
int adr = QData[_currentScan, q_pos, 0] & 7;
|
||||
bool preemph = (ctl & 1) == 1;
|
||||
bool dcp = (ctl & 2) == 2;
|
||||
switch (adr)
|
||||
{
|
||||
case 1: // current position
|
||||
{
|
||||
int iTrack = fromBCD(_currentScan.QData[q_pos, 1]);
|
||||
int iIndex = fromBCD(_currentScan.QData[q_pos, 2]);
|
||||
int mm = fromBCD(_currentScan.QData[q_pos, 7]);
|
||||
int ss = fromBCD(_currentScan.QData[q_pos, 8]);
|
||||
int ff = fromBCD(_currentScan.QData[q_pos, 9]);
|
||||
int iTrack = fromBCD(QData[_currentScan, q_pos, 1]);
|
||||
int iIndex = fromBCD(QData[_currentScan, q_pos, 2]);
|
||||
int mm = fromBCD(QData[_currentScan, q_pos, 7]);
|
||||
int ss = fromBCD(QData[_currentScan, q_pos, 8]);
|
||||
int ff = fromBCD(QData[_currentScan, q_pos, 9]);
|
||||
int sec = ff + 75 * (ss + 60 * mm) - 150; // sector + iSector;
|
||||
//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);
|
||||
byte[] tmp = new byte[16];
|
||||
for (int i = 0; i < 10; i++)
|
||||
_subchannelBuffer[i] = _currentScan.QData[q_pos, i];
|
||||
_subchannelBuffer[i] = QData[_currentScan, q_pos, i];
|
||||
ushort crc = _crc.ComputeChecksum(_subchannelBuffer, 0, 10);
|
||||
crc ^= 0xffff;
|
||||
if (_currentScan.QData[q_pos, 10] != 0 && _currentScan.QData[q_pos, 11] != 0 &&
|
||||
((crc & 0xff) != _currentScan.QData[q_pos, 11] ||
|
||||
(crc >> 8) != _currentScan.QData[q_pos, 10])
|
||||
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 (_debugMessages)
|
||||
System.Console.WriteLine("\nCRC error at {0}", CDImageLayout.TimeToString((uint)(sector + iSector)));
|
||||
_crcErrorsCount ++;
|
||||
if (_debugMessages && _crcErrorsCount < 4)
|
||||
{
|
||||
StringBuilder st = new StringBuilder();
|
||||
for (int i = 0; i < 12; i++)
|
||||
st.AppendFormat(" 0x{0:X2}", QData[_currentScan, q_pos, i]);
|
||||
System.Console.WriteLine("\nCRC error at {0}:{1}", CDImageLayout.TimeToString((uint)(sector + iSector)), st.ToString());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (iTrack == 110)
|
||||
@@ -299,16 +338,33 @@ namespace CUETools.Ripper.SCSI
|
||||
throw new Exception("strange track number encountred");
|
||||
if (iTrack != _currentTrack)
|
||||
{
|
||||
if (_currentTrack != -1 && iTrack != _currentTrack + 1)
|
||||
{
|
||||
if (_debugMessages)
|
||||
System.Console.WriteLine("\nNon-consequent track at {0}: {1} after {2}", CDImageLayout.TimeToString((uint)(sector + iSector)), iTrack, _currentTrack);
|
||||
//throw new Exception("invalid track");
|
||||
continue;
|
||||
}
|
||||
if (iIndex != 1 && iIndex != 0)
|
||||
{
|
||||
if (_debugMessages)
|
||||
System.Console.WriteLine("\nInvalid track start index at {0}: {1}.{2}", CDImageLayout.TimeToString((uint)(sector + iSector)), iTrack, iIndex);
|
||||
//throw new Exception("invalid index");
|
||||
continue;
|
||||
}
|
||||
_currentTrack = iTrack;
|
||||
_currentTrackActualStart = sec;
|
||||
_currentIndex = iIndex;
|
||||
if (_currentIndex != 1 && _currentIndex != 0)
|
||||
throw new Exception("invalid index");
|
||||
}
|
||||
else if (iIndex != _currentIndex)
|
||||
{
|
||||
if (iIndex != _currentIndex + 1)
|
||||
throw new Exception("invalid index");
|
||||
{
|
||||
if (_debugMessages)
|
||||
System.Console.WriteLine("\nNon-consequent index at {0}: {1} after {2}", CDImageLayout.TimeToString((uint)(sector + iSector)), iIndex, _currentIndex);
|
||||
//throw new Exception("invalid index");
|
||||
continue;
|
||||
}
|
||||
_currentIndex = iIndex;
|
||||
if (_currentIndex == 1)
|
||||
{
|
||||
@@ -321,32 +377,35 @@ namespace CUETools.Ripper.SCSI
|
||||
}
|
||||
if (preemph)
|
||||
_toc[iTrack].PreEmphasis = true;
|
||||
if (dcp)
|
||||
_toc[iTrack].DCP = true;
|
||||
break;
|
||||
}
|
||||
case 2: // catalog
|
||||
if (_toc.Catalog == null)
|
||||
if (updateMap && _toc.Catalog == null)
|
||||
{
|
||||
StringBuilder catalog = new StringBuilder();
|
||||
for (int i = 1; i < 8; i++)
|
||||
catalog.AppendFormat("{0:x2}", _currentScan.QData[q_pos, i]);
|
||||
catalog.AppendFormat("{0:x2}", QData[_currentScan, q_pos, i]);
|
||||
_toc.Catalog = catalog.ToString(0, 13);
|
||||
}
|
||||
break;
|
||||
case 3: //isrc
|
||||
if (_toc[_currentTrack].ISRC == null)
|
||||
if (updateMap && _toc[_currentTrack].ISRC == null)
|
||||
{
|
||||
StringBuilder isrc = new StringBuilder();
|
||||
isrc.Append(from6bit(_currentScan.QData[q_pos, 1] >> 2));
|
||||
isrc.Append(from6bit(((_currentScan.QData[q_pos, 1] & 0x3) << 4) + (0x0f & (_currentScan.QData[q_pos, 2] >> 4))));
|
||||
isrc.Append(from6bit(((_currentScan.QData[q_pos, 2] & 0xf) << 2) + (0x03 & (_currentScan.QData[q_pos, 3] >> 6))));
|
||||
isrc.Append(from6bit((_currentScan.QData[q_pos, 3] & 0x3f)));
|
||||
isrc.Append(from6bit(_currentScan.QData[q_pos, 4] >> 2));
|
||||
isrc.Append(from6bit(((_currentScan.QData[q_pos, 4] & 0x3) << 4) + (0x0f & (_currentScan.QData[q_pos, 5] >> 4))));
|
||||
isrc.AppendFormat("{0:x}", _currentScan.QData[q_pos, 5] & 0xf);
|
||||
isrc.AppendFormat("{0:x2}", _currentScan.QData[q_pos, 6]);
|
||||
isrc.AppendFormat("{0:x2}", _currentScan.QData[q_pos, 7]);
|
||||
isrc.AppendFormat("{0:x}", _currentScan.QData[q_pos, 8] >> 4);
|
||||
_toc[_currentTrack].ISRC = isrc.ToString();
|
||||
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);
|
||||
if (!isrc.ToString().Contains("#") && isrc.ToString() != "0000000000")
|
||||
_toc[_currentTrack].ISRC = isrc.ToString();
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -356,38 +415,60 @@ namespace CUETools.Ripper.SCSI
|
||||
|
||||
public unsafe bool TestReadCommand()
|
||||
{
|
||||
Device.MainChannelSelection[] mainmode = { Device.MainChannelSelection.UserData, Device.MainChannelSelection.F8h };
|
||||
Device.SubChannelMode[] submode = { Device.SubChannelMode.None, Device.SubChannelMode.QOnly, Device.SubChannelMode.RWMode };
|
||||
//ReadCDCommand[] readmode = { ReadCDCommand.ReadCdBEh, ReadCDCommand.ReadCdD8h };
|
||||
ReadCDCommand[] readmode = { ReadCDCommand.ReadCdD8h, ReadCDCommand.ReadCdBEh };
|
||||
Device.SubChannelMode[] submode = { Device.SubChannelMode.QOnly, Device.SubChannelMode.None, Device.SubChannelMode.RWMode };
|
||||
Device.C2ErrorMode[] c2mode = { Device.C2ErrorMode.Mode296, Device.C2ErrorMode.Mode294, Device.C2ErrorMode.None };
|
||||
Device.MainChannelSelection[] mainmode = { Device.MainChannelSelection.UserData, Device.MainChannelSelection.F8h };
|
||||
bool found = false;
|
||||
ScanResults saved = _currentScan;
|
||||
_currentScan = new ScanResults(MSECTORS);
|
||||
for (int m = 0; m <= 1 && !found; m++)
|
||||
for (int q = 0; q <= 2 && !found; q++)
|
||||
for (int c = 0; c <= 2 && !found; c++)
|
||||
{
|
||||
_mainChannelMode = mainmode[m];
|
||||
_subChannelMode = submode[q];
|
||||
_c2ErrorMode = c2mode[c];
|
||||
m_max_sectors = 1;
|
||||
Device.CommandStatus st = FetchSectors(0, 1, false);
|
||||
m_test_result += string.Format("{0}: {1}\n", CurrentReadCommand, (st == Device.CommandStatus.DeviceFailed ? Device.LookupSenseError(m_device.GetSenseAsc(), m_device.GetSenseAscq()) : st.ToString()));
|
||||
found = st == Device.CommandStatus.Success && _subChannelMode != Device.SubChannelMode.RWMode;
|
||||
}
|
||||
_currentStart = 0;
|
||||
_currentScan = 0;
|
||||
_currentTrack = -1;
|
||||
_currentIndex = -1;
|
||||
m_max_sectors = Math.Min(NSECTORS, m_device.MaximumTransferLength / CB_AUDIO - 1);
|
||||
int sector = 3;
|
||||
for (int q = 0; q <= 1 && !found; q++)
|
||||
for (int c = 0; c <= 2 && !found; c++)
|
||||
for (int r = 0; r <= 1 && !found; r++)
|
||||
for (int m = 0; m <= 1 && !found; m++)
|
||||
{
|
||||
_readCDCommand = readmode[r];
|
||||
_subChannelMode = submode[q];
|
||||
_c2ErrorMode = c2mode[c];
|
||||
_mainChannelMode = mainmode[m];
|
||||
if (_forceReadCommand != ReadCDCommand.Unknown && _readCDCommand != _forceReadCommand)
|
||||
continue;
|
||||
if (_readCDCommand == ReadCDCommand.ReadCdD8h && (_c2ErrorMode != Device.C2ErrorMode.None || _mainChannelMode != Device.MainChannelSelection.UserData))
|
||||
continue;
|
||||
Array.Clear(_readBuffer, 0, _readBuffer.Length); // fill with something nasty instead?
|
||||
DateTime tm = DateTime.Now;
|
||||
Device.CommandStatus st = FetchSectors(sector, m_max_sectors, false, false);
|
||||
TimeSpan delay = DateTime.Now - tm;
|
||||
if (st == Device.CommandStatus.Success && _subChannelMode == Device.SubChannelMode.QOnly && ProcessSubchannel(sector, m_max_sectors, false) == 0)
|
||||
{
|
||||
_autodetectResult += string.Format("{0}: {1}\n", CurrentReadCommand, "Got no subchannel information");
|
||||
continue;
|
||||
}
|
||||
_autodetectResult += string.Format("{0}: {1} ({2}ms)\n", CurrentReadCommand, (st == Device.CommandStatus.DeviceFailed ? Device.LookupSenseError(m_device.GetSenseAsc(), m_device.GetSenseAscq()) : st.ToString()), delay.TotalMilliseconds);
|
||||
found = st == Device.CommandStatus.Success && _subChannelMode != Device.SubChannelMode.RWMode;// && _subChannelMode != Device.SubChannelMode.QOnly;
|
||||
//sector += m_max_sectors;
|
||||
}
|
||||
//if (found)
|
||||
// for (int n = 1; n <= m_max_sectors; n++)
|
||||
// {
|
||||
// Device.CommandStatus st = FetchSectors(0, n, false, false);
|
||||
// if (st != Device.CommandStatus.Success)
|
||||
// {
|
||||
// _autodetectResult += string.Format("Maximum sectors: {0}, else {1}; max length {2}\n", n - 1, (st == Device.CommandStatus.DeviceFailed ? Device.LookupSenseError(m_device.GetSenseAsc(), m_device.GetSenseAscq()) : st.ToString()), m_device.MaximumTransferLength);
|
||||
// m_max_sectors = n - 1;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
if (found)
|
||||
for (int n = 1; n <= m_max_sectors; n++)
|
||||
{
|
||||
Device.CommandStatus st = FetchSectors(0, n, false);
|
||||
if (st != Device.CommandStatus.Success)
|
||||
{
|
||||
m_test_result += string.Format("Maximum sectors: {0}, else {1}; max length {2}\n", n - 1, (st == Device.CommandStatus.DeviceFailed ? Device.LookupSenseError(m_device.GetSenseAsc(), m_device.GetSenseAscq()) : st.ToString()), m_device.MaximumTransferLength);
|
||||
m_max_sectors = n - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_test_result += "Chosen " + CurrentReadCommand + "\n";
|
||||
_currentScan = saved;
|
||||
_autodetectResult += "Chosen " + CurrentReadCommand + "\n";
|
||||
else
|
||||
_readCDCommand = ReadCDCommand.Unknown;
|
||||
_currentStart = -1;
|
||||
return found;
|
||||
}
|
||||
|
||||
@@ -395,26 +476,26 @@ namespace CUETools.Ripper.SCSI
|
||||
{
|
||||
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 = _currentScan.UserData, c2Data = _currentScan.C2Data, qData = _currentScan.QData)
|
||||
fixed (byte* readBuf = _readBuffer, qBuf = _subchannelBuffer, userData = UserData, c2Data = C2Data, qData = QData)
|
||||
{
|
||||
for (int iSector = 0; iSector < Sectors2Read; iSector++)
|
||||
{
|
||||
byte* sectorPtr = readBuf + iSector * oldSize;
|
||||
byte* userDataPtr = userData + (sector - _currentStart + iSector) * 4 * 588;
|
||||
byte* c2DataPtr = c2Data + (sector - _currentStart + iSector) * 294;
|
||||
byte* qDataPtr = qData + (sector - _currentStart + iSector) * 16;
|
||||
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;
|
||||
|
||||
for (int sample = 0; sample < 4 * 588; sample++)
|
||||
userDataPtr[sample] = sectorPtr[sample];
|
||||
if (_c2ErrorMode != Device.C2ErrorMode.None)
|
||||
for (int c2 = 0; c2 < 294; c2++)
|
||||
c2DataPtr[c2] = sectorPtr[4 * 588 + c2Size - 294];
|
||||
c2DataPtr[c2] = sectorPtr[4 * 588 + c2Size - 294 + c2];
|
||||
else
|
||||
for (int c2 = 0; c2 < 294; c2++)
|
||||
c2DataPtr[c2] = 0xff;
|
||||
c2DataPtr[c2] = 0; // 0xff??
|
||||
if (_subChannelMode != Device.SubChannelMode.None)
|
||||
for (int qi = 0; qi < 16; qi++)
|
||||
qDataPtr[qi] = sectorPtr[4 * 588 + c2Size];
|
||||
qDataPtr[qi] = sectorPtr[4 * 588 + c2Size + qi];
|
||||
else
|
||||
for (int qi = 0; qi < 16; qi++)
|
||||
qDataPtr[qi] = qBuf[iSector * 16 + qi];
|
||||
@@ -422,47 +503,45 @@ namespace CUETools.Ripper.SCSI
|
||||
}
|
||||
}
|
||||
|
||||
private unsafe Device.CommandStatus FetchSectors(int sector, int Sectors2Read, bool abort)
|
||||
private unsafe Device.CommandStatus FetchSectors(int sector, int Sectors2Read, bool abort, bool subchannel)
|
||||
{
|
||||
Device.CommandStatus st;
|
||||
fixed (byte* data = _readBuffer)
|
||||
{
|
||||
st = m_device.ReadCDAndSubChannel(_mainChannelMode, _subChannelMode, _c2ErrorMode, 1, false, (uint)sector, (uint)Sectors2Read, (IntPtr)((void*)data), _timeout);
|
||||
if (_readCDCommand == ReadCDCommand.ReadCdBEh)
|
||||
st = m_device.ReadCDAndSubChannel(_mainChannelMode, _subChannelMode, _c2ErrorMode, 1, false, (uint)sector, (uint)Sectors2Read, (IntPtr)((void*)data), _timeout);
|
||||
else
|
||||
st = m_device.ReadCDDA(_subChannelMode, (uint)sector, (uint)Sectors2Read, (IntPtr)((void*)data), _timeout);
|
||||
}
|
||||
|
||||
if (st == Device.CommandStatus.Success && _subChannelMode == Device.SubChannelMode.None && subchannel)
|
||||
st = m_device.ReadSubChannel(2, (uint)sector, (uint)Sectors2Read, ref _subchannelBuffer, _timeout);
|
||||
|
||||
if (st == Device.CommandStatus.Success)
|
||||
{
|
||||
if (_subChannelMode == Device.SubChannelMode.None)
|
||||
{
|
||||
st = m_device.ReadSubChannel(2, (uint)sector, (uint)Sectors2Read, ref _subchannelBuffer, _timeout);
|
||||
if (st == Device.CommandStatus.Success)
|
||||
{
|
||||
ReorganiseSectors(sector, Sectors2Read);
|
||||
return st;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ReorganiseSectors(sector, Sectors2Read);
|
||||
return st;
|
||||
}
|
||||
ReorganiseSectors(sector, Sectors2Read);
|
||||
return st;
|
||||
}
|
||||
|
||||
if (!abort)
|
||||
return st;
|
||||
SCSIException ex = new SCSIException("ReadCD", m_device, st);
|
||||
if (sector != 0 && Sectors2Read > 1 && st == Device.CommandStatus.DeviceFailed && m_device.GetSenseAsc() == 0x64 && m_device.GetSenseAscq() == 0x00)
|
||||
{
|
||||
if (_debugMessages)
|
||||
System.Console.WriteLine("\n{0}: retrying one sector at a time", ex.Message);
|
||||
int iErrors = 0;
|
||||
for (int iSector = 0; iSector < Sectors2Read; iSector++)
|
||||
{
|
||||
if (FetchSectors(sector + iSector, 1, false) != Device.CommandStatus.Success)
|
||||
if (FetchSectors(sector + iSector, 1, false, subchannel) != Device.CommandStatus.Success)
|
||||
{
|
||||
iErrors ++;
|
||||
for (int i = 0; i < 4 * 588; i++)
|
||||
_currentScan.UserData[sector + iSector - _currentStart, i] = 0;
|
||||
UserData[_currentScan, sector + iSector - _currentStart, i] = 0;
|
||||
for (int i = 0; i < 294; i++)
|
||||
_currentScan.C2Data[sector + iSector - _currentStart, i] = 0xff;
|
||||
C2Data[_currentScan, sector + iSector - _currentStart, i] = 0xff;
|
||||
for (int i = 0; i < 16; i++)
|
||||
_currentScan.QData[sector + iSector - _currentStart, i] = 0;
|
||||
QData[_currentScan, sector + iSector - _currentStart, i] = 0;
|
||||
if (_debugMessages)
|
||||
System.Console.WriteLine("\nSector lost");
|
||||
}
|
||||
@@ -470,46 +549,136 @@ namespace CUETools.Ripper.SCSI
|
||||
if (iErrors < Sectors2Read)
|
||||
return Device.CommandStatus.Success;
|
||||
}
|
||||
throw new Exception(ex.Message + "; Autodetect: " + m_test_result);
|
||||
throw ex;
|
||||
}
|
||||
|
||||
private unsafe void CorrectSectors(int sector, int Sectors2Read, bool findWorst, bool markErrors)
|
||||
private unsafe void ZeroMemory(short *buf, int count)
|
||||
{
|
||||
if (IntPtr.Size == 4)
|
||||
{
|
||||
Int32* start = (Int32*)buf;
|
||||
Int32* end = (Int32*)(buf + count);
|
||||
while (start < end)
|
||||
*(start++) = 0;
|
||||
}
|
||||
else if (IntPtr.Size == 8)
|
||||
{
|
||||
Int64* start = (Int64*)buf;
|
||||
Int64* end = (Int64*)(buf + count);
|
||||
while (start < end)
|
||||
*(start++) = 0;
|
||||
}
|
||||
else
|
||||
throw new Exception("wierd IntPtr.Size");
|
||||
}
|
||||
|
||||
private unsafe void ZeroMemory(byte* buf, int count)
|
||||
{
|
||||
if (IntPtr.Size == 4)
|
||||
{
|
||||
Int32* start = (Int32*)buf;
|
||||
Int32* end = (Int32*)(buf + count);
|
||||
while (start < end)
|
||||
*(start++) = 0;
|
||||
for (int i = 0; i < (count & 3); i++)
|
||||
buf[count - i - 1] = 0;
|
||||
}
|
||||
else if (IntPtr.Size == 8)
|
||||
{
|
||||
Int64* start = (Int64*)buf;
|
||||
Int64* end = (Int64*)(buf + count);
|
||||
while (start < end)
|
||||
*(start++) = 0;
|
||||
for (int i = 0; i < (count & 7); i++)
|
||||
buf[count - i - 1] = 0;
|
||||
}
|
||||
else
|
||||
throw new Exception("wierd IntPtr.Size");
|
||||
}
|
||||
|
||||
private unsafe void CorrectSectors0(int sector, int Sectors2Read)
|
||||
{
|
||||
int c2Score = 10;
|
||||
for (int iSector = 0; iSector < Sectors2Read; iSector++)
|
||||
{
|
||||
int pos = sector - _currentStart + iSector;
|
||||
for (int iPar = 0; iPar < 4 * 588; iPar++)
|
||||
{
|
||||
int pos = sector - _currentStart + iSector;
|
||||
int c2Bit = 0x80 >> (iPar % 8);
|
||||
byte bestValue = UserData[0, pos, iPar];
|
||||
_currentErrorsCount += (C2Data[0, pos, iPar >> 3] >> (iPar & 7)) & 1;
|
||||
_currentData[pos * 4 * 588 + iPar] = bestValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Array.Clear(valueScore, 0, 256);
|
||||
byte bestValue = _currentScan.UserData[pos, iPar];
|
||||
valueScore[bestValue] += 1 + (((_currentScan.C2Data[pos, iPar/8] & c2Bit) == 0) ? c2Score : 0);
|
||||
int totalScore = valueScore[bestValue];
|
||||
for (int result = 0; result < _scanResults.Count; result++)
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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++)
|
||||
{
|
||||
byte value = _scanResults[result].UserData[pos, iPar];
|
||||
int score = 1 + (((_scanResults[result].C2Data[pos, iPar/8] & c2Bit) == 0) ? c2Score : 0);
|
||||
valueScore[value] += score;
|
||||
totalScore += score;
|
||||
if (valueScore[value] > valueScore[bestValue])
|
||||
bestValue = value;
|
||||
}
|
||||
bool fError = valueScore[bestValue] * 2 <= c2Score + totalScore;
|
||||
if (fError)
|
||||
_currentErrorsCount++;
|
||||
_currentData[(sector - _currentStart + iSector) * 4 * 588 + iPar] = bestValue;
|
||||
if (findWorst)
|
||||
{
|
||||
for (int result = 0; result < _scanResults.Count; result++)
|
||||
_scanResults[result].Quality += Math.Min(0, valueScore[_scanResults[result].UserData[pos, iPar]] - c2Score - 1);
|
||||
_currentScan.Quality += Math.Min(0, valueScore[_currentScan.UserData[pos, iPar]] - c2Score - 1);
|
||||
}
|
||||
if (markErrors)
|
||||
{
|
||||
_errors[sector + iSector] = fError;
|
||||
_errorsCount += fError ? 1 : 0;
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -569,20 +738,18 @@ namespace CUETools.Ripper.SCSI
|
||||
// return realErrors;
|
||||
//}
|
||||
|
||||
public void PrefetchSector(int iSector)
|
||||
public unsafe void PrefetchSector(int iSector)
|
||||
{
|
||||
int nPasses = 16 + _correctionQuality * 2;
|
||||
int nExtraPasses = 8 + _correctionQuality;
|
||||
int nExtraPasses = MAXSCANS / 2 + _correctionQuality;
|
||||
|
||||
if (_currentStart == MSECTORS * (iSector / MSECTORS))
|
||||
return;
|
||||
|
||||
if (m_test_result == null && !TestReadCommand())
|
||||
throw new Exception("failed to autodetect read command: " + m_test_result);
|
||||
if (_readCDCommand == ReadCDCommand.Unknown && !TestReadCommand())
|
||||
throw new Exception("failed to autodetect read command: " + _autodetectResult);
|
||||
|
||||
_currentStart = MSECTORS * (iSector / MSECTORS);
|
||||
_currentEnd = Math.Min(_currentStart + MSECTORS, (int)_toc.AudioLength);
|
||||
_scanResults = new List<ScanResults>();
|
||||
|
||||
//FileStream correctFile = new FileStream("correct.wav", FileMode.Open);
|
||||
//byte[] realData = new byte[MSECTORS * 4 * 588];
|
||||
@@ -591,82 +758,80 @@ namespace CUETools.Ripper.SCSI
|
||||
// throw new Exception("read");
|
||||
//correctFile.Close();
|
||||
|
||||
for (int pass = 0; pass <= nPasses + nExtraPasses; pass++)
|
||||
fixed (byte* userData = UserData, c2Data = C2Data, qData = QData)
|
||||
{
|
||||
DateTime PassTime = DateTime.Now, LastFetch = DateTime.Now;
|
||||
_currentScan = new ScanResults(MSECTORS);
|
||||
_currentErrorsCount = 0;
|
||||
for (int sector = _currentStart; sector < _currentEnd; sector += m_max_sectors)
|
||||
for (int pass = 0; pass < MAXSCANS + nExtraPasses; pass++)
|
||||
{
|
||||
int Sectors2Read = Math.Min(m_max_sectors, _currentEnd - sector);
|
||||
int speed = pass == 4 || pass == 5 ? 4 : pass == 8 || pass == 9 ? 2 : pass == 17 || pass == 18 ? 1 : 0;
|
||||
if (speed != 0)
|
||||
Thread.Sleep(Math.Max(1, 1000 * Sectors2Read / (75 * speed) - (int)((DateTime.Now - LastFetch).TotalMilliseconds)));
|
||||
LastFetch = DateTime.Now;
|
||||
FetchSectors(sector, Sectors2Read, true);
|
||||
|
||||
if (ProcessSubchannel(sector, Sectors2Read, pass == 0) == 0 && _subChannelMode != Device.SubChannelMode.None && sector == 0)
|
||||
{
|
||||
if (_debugMessages)
|
||||
System.Console.WriteLine("\nGot no subchannel using ReadCD. Switching to ReadSubchannel.");
|
||||
_subChannelMode = Device.SubChannelMode.None;
|
||||
// TODO: move to TestReadCommand
|
||||
FetchSectors(sector, Sectors2Read, true);
|
||||
}
|
||||
CorrectSectors(sector, Sectors2Read, pass > nPasses, pass == nPasses + nExtraPasses);
|
||||
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 == nPasses + nExtraPasses)
|
||||
break;
|
||||
if (pass > nPasses)
|
||||
{
|
||||
int worstPass = -1;
|
||||
for (int result = 0; result < _scanResults.Count; result++)
|
||||
if (_scanResults[result].Quality < (worstPass < 0 ? _currentScan.Quality : _scanResults[worstPass].Quality))
|
||||
worstPass = 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));
|
||||
if (worstPass < 0)
|
||||
_currentScan = null;
|
||||
DateTime PassTime = DateTime.Now, LastFetch = DateTime.Now;
|
||||
if (pass < MAXSCANS)
|
||||
_currentScan = pass;
|
||||
else
|
||||
_scanResults[worstPass] = _currentScan;
|
||||
for (int result = 0; result < _scanResults.Count; result++)
|
||||
_scanResults[result].Quality = 0;
|
||||
continue;
|
||||
}
|
||||
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)
|
||||
{
|
||||
_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;
|
||||
|
||||
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);
|
||||
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);
|
||||
//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 == MAXSCANS - 1 + nExtraPasses)
|
||||
// break;
|
||||
if (_currentErrorsCount == 0 && pass >= _correctionQuality)
|
||||
break;
|
||||
}
|
||||
_scanResults.Add(_currentScan);
|
||||
//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;
|
||||
//}
|
||||
}
|
||||
}
|
||||
_currentScan = null;
|
||||
_scanResults = null;
|
||||
}
|
||||
|
||||
public uint Read(int[,] buff, uint sampleCount)
|
||||
@@ -806,9 +971,14 @@ namespace CUETools.Ripper.SCSI
|
||||
}
|
||||
set
|
||||
{
|
||||
if (_toc.AudioLength <= 0)
|
||||
throw new Exception("no audio");
|
||||
_currentTrack = -1;
|
||||
_currentIndex = -1;
|
||||
_sampleOffset = (int) value + _driveOffset;
|
||||
_crcErrorsCount = 0;
|
||||
_errorsCount = 0;
|
||||
_errors = new BitArray((int)_toc.AudioLength);
|
||||
_sampleOffset = (int)value + _driveOffset;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -873,24 +1043,12 @@ namespace CUETools.Ripper.SCSI
|
||||
}
|
||||
}
|
||||
|
||||
internal class ScanResults
|
||||
enum ReadCDCommand
|
||||
{
|
||||
public byte[,] UserData;
|
||||
public byte[,] C2Data;
|
||||
public byte[,] QData;
|
||||
public long Quality;
|
||||
|
||||
public ScanResults(int msector)
|
||||
{
|
||||
//byte[] a1 = new byte[msector * 4 * 588];
|
||||
//byte[] a2 = new byte[msector * 294];
|
||||
//byte[] a3 = new byte[msector * 16];
|
||||
UserData = new byte[msector, 4 * 588];
|
||||
C2Data = new byte[msector, 294];
|
||||
QData = new byte[msector, 16];
|
||||
Quality = 0;
|
||||
}
|
||||
}
|
||||
ReadCdBEh,
|
||||
ReadCdD8h,
|
||||
Unknown
|
||||
};
|
||||
|
||||
public sealed class SCSIException : Exception
|
||||
{
|
||||
|
||||
@@ -348,6 +348,7 @@ namespace JDP {
|
||||
outputExists = false;
|
||||
else if (dlgRes == DialogResult.Cancel || _batchPaths.Count == 0)
|
||||
{
|
||||
cueSheet.Close();
|
||||
_batchPaths.Clear();
|
||||
SetupControls(false);
|
||||
return;
|
||||
@@ -413,6 +414,7 @@ namespace JDP {
|
||||
});
|
||||
}
|
||||
#endif
|
||||
cueSheet.Close();
|
||||
|
||||
if (_batchPaths.Count != 0) {
|
||||
_batchPaths.RemoveAt(0);
|
||||
|
||||
Reference in New Issue
Block a user