public AccurateRipVerify CreateAccurateRipVerify() { var ar = new AccurateRipVerify(toc, null); ar.Position = start; Write(ar); return ar; }
public CDRepairEncode CreateCDRepairEncode(int stride) { var ar = new AccurateRipVerify(toc, null); var encode = new CDRepairEncode(ar, stride); ar.Position = start; Write(ar); //ar.Close(); return encode; }
public OffsetSafeCRCRecord(AccurateRipVerify ar) : this(new uint[64 + 64]) { int offset = 64 * 64; for (int i = 0; i < 64; i++) this.val[i] = ar.CTDBCRC(0, (i + 1) * 64, offset, 2 * offset); for (int i = 0; i < 64; i++) this.val[i + 64] = ar.CTDBCRC(0, 63 - i, offset, 2 * offset); }
public CUEToolsVerifyTask(CUESheet cueSheet, int start, int end, AccurateRipVerify ar) : this(cueSheet, start, end, ar, null) { if (cueSheet.Config.detectHDCD && CUEProcessorPlugins.hdcd != null) { try { this.hdcd = Activator.CreateInstance(CUEProcessorPlugins.hdcd, 2, 44100, 20, false) as IAudioDest; } catch { this.hdcd = null; } } }
private CUEToolsVerifyTask(CUESheet cueSheet, int start, int end, AccurateRipVerify ar, IAudioDest hdcd) { this.cueSheet = cueSheet; this.start = start; this.end = end; this.source = new CUESheetAudio(cueSheet); if (cueSheet.IsCD || cueSheet.Config.separateDecodingThread) this.source = new AudioPipe(this.source, 0x10000); this.source.Position = start; this.ar = cueSheet.IsUsingAccurateRip ? ar : null; this.hdcd = hdcd; if (this.ar != null) this.ar.Position = start; }
public static CDRepairEncode VerifyNoise(CDImageLayout toc, int seed, int offset, int start, int end, int errors, bool do_verify, bool do_encode) { if (start < 0 || start > end || end > toc.AudioLength * 588) throw new ArgumentOutOfRangeException(); var src = new NoiseAndErrorsGenerator(AudioPCMConfig.RedBook, end - start, seed, offset + start, errors); var buff = new AudioBuffer(src, 588 * 100); var ar = new AccurateRipVerify(toc, null); var encode = new CDRepairEncode(ar, stride, npar, do_verify, do_encode); var rnd = new Random(seed); ar.Position = start; while (src.Remaining > 0) { src.Read(buff, rnd.Next(1, buff.Size)); ar.Write(buff); } ar.Close(); return encode; }
public static void MyClassInitialize(TestContext testContext) { toc = new CDImageLayout(1, 1, 1, string.Format("0 {0}", (finalSampleCount / 588).ToString())); ar = new AccurateRipVerify(toc, null); ar2 = new AccurateRipVerify(toc, null); ar3 = new AccurateRipVerify(toc, null); new Random(2423).NextBytes(wav); new Random(2423).NextBytes(wav2); Random rnd = new Random(987); for (int i = 0; i < stride / 4; i++ ) wav2[(int)(rnd.NextDouble() * (wav2.Length - 1))] = (byte)(rnd.NextDouble() * 255); AudioBuffer buff = new AudioBuffer(AudioPCMConfig.RedBook, 0); CDRepairEncode encode = new CDRepairEncode(ar, stride, npar, false, true); buff.Prepare(wav, finalSampleCount); ar.Init(toc); ar.Write(buff); ar.Close(); parity = encode.Parity; crc = encode.CRC; decode = new CDRepairEncode(ar2, stride, npar, true, false); buff.Prepare(wav2, finalSampleCount); ar2.Init(toc); ar2.Write(buff); ar2.Close(); int actualOffset; bool hasErrors; decode.FindOffset(npar, parity, 0, crc, out actualOffset, out hasErrors); fix = decode.VerifyParity(parity, actualOffset); decode2 = new CDRepairEncode(ar3, stride, npar, true, false); ar3.Init(toc); buff.Prepare(new byte[offset * 4], offset); ar3.Write(buff); buff.Prepare(wav2, finalSampleCount - offset); ar3.Write(buff); ar3.Close(); decode2.FindOffset(npar, parity, 0, crc, out actualOffset, out hasErrors); fix2 = decode2.VerifyParity(parity, actualOffset); }
public void OpenCUE(TextReader sr) { string pathAudio = null; string lineStr, command, fileType; bool fileIsBinary = false; int timeRelativeToFileStart, absoluteFileStartTime = 0; int fileTimeLengthSamples = 0, fileTimeLengthFrames = 0, i; TagLib.File _trackFileInfo = null; bool seenFirstFileIndex = false; bool isAudioTrack = true; List<IndexInfo> indexes = new List<IndexInfo>(); IndexInfo indexInfo; SourceInfo sourceInfo; TrackInfo trackInfo = null; int trackNumber = 0; using (sr) { while ((lineStr = sr.ReadLine()) != null) { CUELine line = new CUELine(lineStr); if (line.Params.Count > 0) { command = line.Params[0].ToUpper(); if (command == "FILE") { fileType = line.Params[2].ToUpper(); fileIsBinary = (fileType == "BINARY") || (fileType == "MOTOROLA"); if (fileIsBinary) { if (!_hasEmbeddedCUESheet && _sourcePaths.Count == 0) { try { if (_isArchive) pathAudio = FileLocator.LocateFile(_archiveCUEpath, line.Params[1], _archiveContents); else pathAudio = FileLocator.LocateFile(_inputDir, line.Params[1], null); fileIsBinary = (pathAudio == null); } catch { } } } if (!fileIsBinary) { if (_sourcePaths.Count != 0 && !seenFirstFileIndex) throw new Exception("Double FILE in CUE sheet: \"" + line.Params[1] + "\"."); if (!_hasEmbeddedCUESheet) { if (_isArchive) pathAudio = FileLocator.LocateFile(_archiveCUEpath, line.Params[1], _archiveContents); else pathAudio = FileLocator.LocateFile(_inputDir, line.Params[1], null); } else { pathAudio = _inputPath; if (_sourcePaths.Count > 0) throw new Exception("Extra file in embedded CUE sheet: \"" + line.Params[1] + "\"."); } if (pathAudio == null) { throw new Exception("Unable to locate file \"" + line.Params[1] + "\"."); //fileTimeLengthFrames = 75 * 60 * 70;; //fileTimeLengthSamples = fileTimeLengthFrames * 588; //if (_hasEmbeddedCUESheet) // _fileInfo = null; //else // _trackFileInfo = null; } else { // Wierd case: audio file after data track with only index 00 specified. if (!isAudioTrack && _sourcePaths.Count == 0 && indexes.Count > 0 && indexes[indexes.Count - 1].Index == 0) { indexInfo.Track = indexes[indexes.Count - 1].Track; indexInfo.Index = 1; indexInfo.Time = indexes[indexes.Count - 1].Time + 150; indexes.Add(indexInfo); absoluteFileStartTime += 150; } TagLib.File fileInfo; _sourcePaths.Add(pathAudio); absoluteFileStartTime += fileTimeLengthFrames; fileTimeLengthSamples = GetSampleLength(pathAudio, out fileInfo); if ((fileTimeLengthSamples % 588) == 492 && _config.truncate4608ExtraSamples) { _truncated4608 = true; fileTimeLengthSamples -= 4608; } fileTimeLengthFrames = (int)((fileTimeLengthSamples + 587) / 588); if (_hasEmbeddedCUESheet) _fileInfo = fileInfo; else _trackFileInfo = fileInfo; } seenFirstFileIndex = false; } } else if (command == "TRACK") { isAudioTrack = line.Params[2].ToUpper() == "AUDIO"; trackNumber = int.Parse(line.Params[1]); if (trackNumber != _toc.TrackCount + 1) throw new Exception("Invalid track number"); // Disabled this check: fails on Headcandy test image //if (isAudioTrack && _sourcePaths.Count == 0) // throw new Exception("No FILE seen before TRACK"); _toc.AddTrack(new CDTrack((uint)trackNumber, 0, 0, isAudioTrack, false)); if (isAudioTrack) { trackInfo = new TrackInfo(); _tracks.Add(trackInfo); } } else if (command == "INDEX") { timeRelativeToFileStart = CDImageLayout.TimeFromString(line.Params[2]); if (!seenFirstFileIndex) { if (timeRelativeToFileStart != 0) throw new Exception("First index must start at file beginning."); seenFirstFileIndex = true; if (isAudioTrack) { if (_tracks.Count > 0 && _trackFileInfo != null) _tracks[_tracks.Count - 1]._fileInfo = _trackFileInfo; _trackFileInfo = null; sourceInfo.Path = pathAudio; sourceInfo.Offset = 0; sourceInfo.Length = (uint)fileTimeLengthSamples; _sources.Add(sourceInfo); if ((fileTimeLengthSamples % 588) != 0) { sourceInfo.Path = null; sourceInfo.Offset = 0; sourceInfo.Length = (uint)((fileTimeLengthFrames * 588) - fileTimeLengthSamples); _sources.Add(sourceInfo); _paddedToFrame = true; } } } else { if (fileIsBinary) { fileTimeLengthFrames = timeRelativeToFileStart + 150; sourceInfo.Path = null; sourceInfo.Offset = 0; sourceInfo.Length = 150 * 588; _sources.Add(sourceInfo); //throw new Exception("unexpected BINARY directive"); } else { if (timeRelativeToFileStart > fileTimeLengthFrames) throw new Exception(string.Format("TRACK {0} INDEX {1} is at {2}, which is past {3} - the end of source file {4}", trackNumber, line.Params[1], CDImageLayout.TimeToString((uint)timeRelativeToFileStart), CDImageLayout.TimeToString((uint)fileTimeLengthFrames), pathAudio)); } } indexInfo.Track = trackNumber; indexInfo.Index = Int32.Parse(line.Params[1]); indexInfo.Time = absoluteFileStartTime + timeRelativeToFileStart; indexes.Add(indexInfo); } else if (!isAudioTrack) { // Ignore lines belonging to data tracks } else if (command == "PREGAP") { if (seenFirstFileIndex) throw new Exception("Pregap must occur at the beginning of a file."); int pregapLength = CDImageLayout.TimeFromString(line.Params[1]); indexInfo.Track = trackNumber; indexInfo.Index = 0; indexInfo.Time = absoluteFileStartTime; indexes.Add(indexInfo); sourceInfo.Path = null; sourceInfo.Offset = 0; sourceInfo.Length = (uint)pregapLength * 588; _sources.Add(sourceInfo); absoluteFileStartTime += pregapLength; } else if (command == "POSTGAP") { throw new Exception("POSTGAP command isn't supported."); } //else if ((command == "REM") && // (line.Params.Count >= 3) && // (line.Params[1].Length >= 10) && // (line.Params[1].Substring(0, 10).ToUpper() == "REPLAYGAIN")) //{ // // Remove ReplayGain lines //} else if ((command == "REM") && (line.Params.Count == 3) && (line.Params[1].ToUpper() == "ACCURATERIPID")) { _accurateRipId = line.Params[2]; } //else if ((command == "REM") && // (line.Params.Count == 3) && // (line.Params[1].ToUpper() == "SHORTEN")) //{ // fileTimeLengthFrames -= General.TimeFromString(line.Params[2]); //} //else if ((command == "REM") && // (line.Params.Count == 3) && // (line.Params[1].ToUpper() == "LENGTHEN")) //{ // fileTimeLengthFrames += General.TimeFromString(line.Params[2]); //} else { if (trackInfo != null) { trackInfo.Attributes.Add(line); } else { if (line.Params.Count > 2 && !line.IsQuoted[1] && (line.Params[0].ToUpper() == "TITLE" || line.Params[0].ToUpper() == "ARTIST" || (line.Params[0].ToUpper() == "REM" && (line.Params[1].ToUpper() == "GENRE" || line.Params[1].ToUpper() == "COMMENT") && line.Params.Count > 3 && !line.IsQuoted[2]))) { CUELine modline = new CUELine(); int nParams = line.Params[0].ToUpper() == "REM" ? 2 : 1; for (int iParam = 0; iParam < nParams; iParam++) { modline.Params.Add(line.Params[iParam]); modline.IsQuoted.Add(false); } string s = line.Params[nParams]; for (int iParam = nParams + 1; iParam < line.Params.Count; iParam++) s += " " + line.Params[iParam]; modline.Params.Add(s); modline.IsQuoted.Add(true); line = modline; } _attributes.Add(line); } } } } sr.Close(); } if (_tracks.Count == 0) throw new Exception("File must contain at least one audio track."); // Add dummy index 01 for data track if (!_toc[_toc.TrackCount].IsAudio && indexes[indexes.Count - 1].Index == 0) { fileTimeLengthFrames += 152 * 75; indexInfo.Track = trackNumber; indexInfo.Index = 1; indexInfo.Time = absoluteFileStartTime + fileTimeLengthFrames; indexes.Add(indexInfo); } // Add dummy track for calculation purposes indexInfo.Track = trackNumber + 1; indexInfo.Index = 1; indexInfo.Time = absoluteFileStartTime + fileTimeLengthFrames; indexes.Add(indexInfo); // Calculate the length of each index for (i = 0; i < indexes.Count - 1; i++) { if (indexes[i + 1].Time - indexes[i].Time < 0) throw new Exception("Indexes must be in chronological order."); if ((indexes[i + 1].Track != indexes[i].Track || indexes[i + 1].Index != indexes[i].Index + 1) && (indexes[i + 1].Track != indexes[i].Track + 1 || indexes[i].Index < 1 || indexes[i + 1].Index > 1)) throw new Exception("Indexes must be in chronological order."); if (indexes[i].Index == 1 && (i == 0 || indexes[i - 1].Index != 0)) _toc[indexes[i].Track].AddIndex(new CDTrackIndex(0U, (uint)indexes[i].Time)); _toc[indexes[i].Track].AddIndex(new CDTrackIndex((uint)indexes[i].Index, (uint)indexes[i].Time)); } // Calculate the length of each track for (int iTrack = 1; iTrack <= _toc.TrackCount; iTrack++) { _toc[iTrack].Start = _toc[iTrack][1].Start; _toc[iTrack].Length = iTrack == _toc.TrackCount ? (uint)indexes[indexes.Count - 1].Time - _toc[iTrack].Start : _toc[iTrack + 1].IsAudio ? _toc[iTrack + 1][1].Start - _toc[iTrack].Start : _toc[iTrack + 1][0].Start - _toc[iTrack].Start; } // Store the audio filenames, generating generic names if necessary _hasSingleFilename = _sourcePaths.Count == 1; _singleFilename = _hasSingleFilename ? Path.GetFileName(_sourcePaths[0]) : "Range.wav"; _hasHTOAFilename = (_sourcePaths.Count == (TrackCount + 1)); _htoaFilename = _hasHTOAFilename ? Path.GetFileName(_sourcePaths[0]) : "00.wav"; _hasTrackFilenames = !_hasEmbeddedCUESheet && !_hasSingleFilename && (_sourcePaths.Count == TrackCount || _hasHTOAFilename); for (i = 0; i < TrackCount; i++) { _trackFilenames.Add(_hasTrackFilenames ? Path.GetFileName( _sourcePaths[i + (_hasHTOAFilename ? 1 : 0)]) : String.Format("{0:00}.wav", i + 1)); } if (!_hasEmbeddedCUESheet && _hasSingleFilename) { _fileInfo = _tracks[0]._fileInfo; _tracks[0]._fileInfo = null; } taglibMetadata = new CUEMetadata(TOC.TOCID, (int)TOC.AudioTracks); taglibMetadata.Artist = GetCommonTag(file => file.Tag.JoinedAlbumArtists) ?? GetCommonTag(file => file.Tag.JoinedPerformers) ?? ""; taglibMetadata.Title = GetCommonTag(file => file.Tag.Album) ?? ""; taglibMetadata.Year = GetCommonTag(file => file.Tag.Year != 0 ? file.Tag.Year.ToString() : null) ?? ""; taglibMetadata.Genre = GetCommonTag(file => file.Tag.JoinedGenres) ?? ""; taglibMetadata.Comment = GetCommonTag(file => file.Tag.Comment) ?? ""; taglibMetadata.TotalDiscs = GetCommonTag(file => file.Tag.DiscCount != 0 ? file.Tag.DiscCount.ToString() : null) ?? ""; taglibMetadata.DiscNumber = GetCommonTag(file => file.Tag.Disc != 0 ? file.Tag.Disc.ToString() : null) ?? ""; taglibMetadata.ReleaseDate = GetCommonTag(file => file.Tag.ReleaseDate) ?? ""; taglibMetadata.Country = GetCommonTag(file => file.Tag.MusicBrainzReleaseCountry) ?? ""; taglibMetadata.Label = GetCommonTag(file => file.Tag.Publisher) ?? ""; taglibMetadata.LabelNo = GetCommonTag(file => file.Tag.CatalogNo) ?? ""; taglibMetadata.DiscName = GetCommonTag(file => file.Tag.DiscSubtitle) ?? ""; for (i = 0; i < TrackCount; i++) { TrackInfo track = _tracks[i]; taglibMetadata.Tracks[i].Artist = (_hasTrackFilenames && track._fileInfo != null ? track._fileInfo.Tag.JoinedPerformers : _hasEmbeddedCUESheet && _fileInfo != null ? Tagging.TagListToSingleValue(Tagging.GetMiscTag(_fileInfo, String.Format("cue_track{0:00}_ARTIST", i + 1))) : null) ?? ""; taglibMetadata.Tracks[i].Title = (_hasTrackFilenames && track._fileInfo != null ? track._fileInfo.Tag.Title : _hasEmbeddedCUESheet && _fileInfo != null ? Tagging.TagListToSingleValue(Tagging.GetMiscTag(_fileInfo, String.Format("cue_track{0:00}_TITLE", i + 1))) : null) ?? ""; taglibMetadata.Tracks[i].Comment = (_hasTrackFilenames && track._fileInfo != null ? track._fileInfo.Tag.Title : _hasEmbeddedCUESheet && _fileInfo != null ? Tagging.TagListToSingleValue(Tagging.GetMiscTag(_fileInfo, String.Format("cue_track{0:00}_COMMENT", i + 1))) : null) ?? ""; } cueMetadata = new CUEMetadata(TOC.TOCID, (int)TOC.AudioTracks); cueMetadata.Artist = General.GetCUELine(_attributes, "PERFORMER"); cueMetadata.Title = General.GetCUELine(_attributes, "TITLE"); cueMetadata.Barcode = General.GetCUELine(_attributes, "CATALOG"); cueMetadata.Year = General.GetCUELine(_attributes, "REM", "DATE"); cueMetadata.DiscNumber = General.GetCUELine(_attributes, "REM", "DISCNUMBER"); cueMetadata.TotalDiscs = General.GetCUELine(_attributes, "REM", "TOTALDISCS"); cueMetadata.Genre = General.GetCUELine(_attributes, "REM", "GENRE"); cueMetadata.Comment = General.GetCUELine(_attributes, "REM", "COMMENT"); cueMetadata.ReleaseDate = General.GetCUELine(_attributes, "REM", "RELEASEDATE"); cueMetadata.Country = General.GetCUELine(_attributes, "REM", "COUNTRY"); cueMetadata.Label = General.GetCUELine(_attributes, "REM", "LABEL"); cueMetadata.LabelNo = General.GetCUELine(_attributes, "REM", "CATALOGNUMBER"); cueMetadata.DiscName = General.GetCUELine(_attributes, "REM", "DISCSUBTITLE"); for (i = 0; i < Tracks.Count; i++) { cueMetadata.Tracks[i].Artist = General.GetCUELine(Tracks[i].Attributes, "PERFORMER"); cueMetadata.Tracks[i].Title = General.GetCUELine(Tracks[i].Attributes, "TITLE"); cueMetadata.Tracks[i].ISRC = General.GetCUELine(Tracks[i].Attributes, "ISRC"); } // Now, TOC.TOCID might change!!! if (_config.fillUpCUE) { cueMetadata.Merge(taglibMetadata, _config.overwriteCUEData); for (i = 0; i < TrackCount; i++) { if (cueMetadata.Tracks[i].Title == "" && _hasTrackFilenames) cueMetadata.Tracks[i].Title = Path.GetFileNameWithoutExtension(_trackFilenames[i]).TrimStart(" .-_0123456789".ToCharArray()); } } CUELine cddbDiscIdLine = General.FindCUELine(_attributes, "REM", "DISCID"); _cddbDiscIdTag = cddbDiscIdLine != null && cddbDiscIdLine.Params.Count == 3 ? cddbDiscIdLine.Params[2] : null; if (_cddbDiscIdTag == null) _cddbDiscIdTag = GetCommonMiscTag("DISCID"); if (_accurateRipId == null) _accurateRipId = GetCommonMiscTag("ACCURATERIPID"); if (_eacLog == null && _logFiles != null && _logFiles.Count > 0) { foreach (CUEToolsSourceFile sf in _logFiles) { CDImageLayout tocFromLog1 = LogToTocParser.LogToToc(this._toc, sf.contents); if (tocFromLog1 != null && tocFromLog1.TOCID == _toc.TOCID) { if (_eacLog == null) _eacLog = sf.contents; else { _eacLog = null; break; } } } } if (_eacLog == null && _logFiles != null && _logFiles.Count > 0) { CUEToolsSourceFile selectedLogFile = ChooseFile(_logFiles, _defaultLog, false); _eacLog = selectedLogFile != null ? selectedLogFile.contents : null; } CDImageLayout tocFromLog = _eacLog == null ? null : LogToTocParser.LogToToc(this._toc, _eacLog); if (tocFromLog == null) { string tocPath = Path.ChangeExtension(InputPath, ".toc"); if (File.Exists(tocPath)) { tocFromLog = LogToTocParser.LogToToc(this._toc, new StreamReader(tocPath, CUESheet.Encoding).ReadToEnd()); } } // use pregaps from log if (tocFromLog != null) { //int srcNo = (int) _toc[_toc.FirstAudio].LastIndex - (PreGapLength == 0 ? 1 : 0); if (PreGapLength < tocFromLog.Pregap) { PreGapLength = tocFromLog.Pregap; //srcNo ++; } int trNo; for (trNo = 1; trNo < tocFromLog.AudioTracks && trNo < _toc.AudioTracks; trNo++) { if (_toc[_toc.FirstAudio + trNo].Pregap < tocFromLog[tocFromLog.FirstAudio + trNo].Pregap) _toc[_toc.FirstAudio + trNo].Pregap = tocFromLog[tocFromLog.FirstAudio + trNo].Pregap; } //if (_toc[_toc.FirstAudio].Length > tocFromLog[tocFromLog.FirstAudio].Length) //{ // uint offs = _toc[_toc.FirstAudio].Length - tocFromLog[tocFromLog.FirstAudio].Length; // _toc[_toc.FirstAudio].Length -= offs; // sourceInfo = _sources[srcNo]; // sourceInfo.Length -= offs * 588; // _sources[srcNo] = sourceInfo; // for (i = _toc.FirstAudio + 1; i <= _toc.TrackCount; i++) // { // _toc[i].Start -= offs; // for (int j = 0; j <= _toc[i].LastIndex; j++) // if (i != _toc.FirstAudio + 1 || j != 0 || _toc[i][0].Start == _toc[i][1].Start) // _toc[i][j].Start -= offs; // } //} //for (trNo = 1; trNo < tocFromLog.AudioTracks && trNo < _toc.AudioTracks; trNo++) //{ // srcNo ++; // if (_toc[_toc.FirstAudio + trNo].Length > tocFromLog[tocFromLog.FirstAudio + trNo].Length) // { // uint offs = _toc[_toc.FirstAudio + trNo].Length - tocFromLog[tocFromLog.FirstAudio + trNo].Length; // _toc[_toc.FirstAudio + trNo].Length -= offs; // sourceInfo = _sources[srcNo]; // sourceInfo.Length -= offs * 588; // _sources[srcNo] = sourceInfo; // for (i = _toc.FirstAudio + trNo + 1; i <= _toc.TrackCount; i++) // { // _toc[i].Start -= offs; // for (int j = 0; j <= _toc[i].LastIndex; j++) // if (i != _toc.FirstAudio + trNo + 1 || j != 0 || _toc[i][0].Start == _toc[i][1].Start) // _toc[i][j].Start -= offs; // } // } //} } // use data track length from log if (tocFromLog != null) { if (tocFromLog.AudioTracks == _toc.AudioTracks && tocFromLog.TrackCount == tocFromLog.AudioTracks + 1 && !tocFromLog[tocFromLog.TrackCount].IsAudio) { DataTrackLength = tocFromLog[tocFromLog.TrackCount].Length; _toc[_toc.TrackCount].Start = tocFromLog[_toc.TrackCount].Start; _toc[_toc.TrackCount][0].Start = tocFromLog[_toc.TrackCount].Start; _toc[_toc.TrackCount][1].Start = tocFromLog[_toc.TrackCount].Start; } if (_toc.TrackCount == _toc.AudioTracks && tocFromLog.TrackCount == tocFromLog.AudioTracks && tocFromLog.TrackCount > _toc.TrackCount) { int dtracks = tocFromLog.TrackCount - _toc.TrackCount; bool matches = true; for (int iTrack = 1; iTrack <= _toc.TrackCount; iTrack++) if (tocFromLog[iTrack + dtracks].Length != _toc[iTrack].Length) matches = false; if (matches) { for (int iTrack = 1; iTrack <= dtracks; iTrack++) { _toc.InsertTrack(new CDTrack((uint)iTrack, 0, 0, false, false)); tocFromLog[iTrack].IsAudio = false; } tocFromLog.FirstAudio += dtracks; tocFromLog.AudioTracks -= (uint)dtracks; } } if (tocFromLog.AudioTracks == _toc.AudioTracks && tocFromLog.TrackCount == _toc.TrackCount && tocFromLog.FirstAudio == _toc.FirstAudio && tocFromLog.TrackCount == tocFromLog.FirstAudio + tocFromLog.AudioTracks - 1) { //DataTrackLength = tocFromLog[1].Length; uint delta = tocFromLog[_toc.FirstAudio].Start - _toc[_toc.FirstAudio].Start; for (int itr = 1; itr < _toc.FirstAudio; itr++) { _toc[itr].Start = tocFromLog[itr].Start; _toc[itr].Length = tocFromLog[itr].Length; } for (int itr = _toc.FirstAudio; itr <= _toc.TrackCount; itr++) { _toc[itr].Start += delta; for (int j = 0; j <= _toc[itr].LastIndex; j++) _toc[itr][j].Start += delta; } } } // use data track length range from cddbId if (DataTrackLength == 0 && _cddbDiscIdTag != null) { uint cddbDiscIdNum; if (uint.TryParse(_cddbDiscIdTag, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out cddbDiscIdNum) && (cddbDiscIdNum & 0xff) == _toc.AudioTracks + 1) { if (_toc.TrackCount == _toc.AudioTracks) _toc.AddTrack(new CDTrack((uint)_toc.TrackCount + 1, _toc.Length + 152 * 75, 0, false, false)); uint lengthFromTag = ((cddbDiscIdNum >> 8) & 0xffff); _minDataTrackLength = (lengthFromTag + _toc[1].Start / 75) * 75 - _toc.Length; } } _arVerify = new AccurateRipVerify(_toc, proxy); if (_eacLog != null) { sr = new StringReader(_eacLog); bool isEACLog = false; int trNo = 1; while ((lineStr = sr.ReadLine()) != null) { if (isEACLog && trNo <= TrackCount) { string[] s = { "Copy CRC ", "CRC копии" }; string[] s1 = { "CRC" }; string[] n = lineStr.Split(s, StringSplitOptions.None); uint crc; if (n.Length == 2 && uint.TryParse(n[1], NumberStyles.HexNumber, CultureInfo.InvariantCulture, out crc)) _arVerify.CRCLOG(trNo++, crc); else if (n.Length == 1) { n = lineStr.Split(s1, StringSplitOptions.None); if (n.Length == 2 && n[0].Trim() == "" && uint.TryParse(n[1], NumberStyles.HexNumber, CultureInfo.InvariantCulture, out crc)) _arVerify.CRCLOG(trNo++, crc); } } else if (lineStr.StartsWith("Exact Audio Copy") || lineStr.StartsWith("EAC extraction logfile")) isEACLog = true; } if (trNo == 2) { _arVerify.CRCLOG(0, _arVerify.CRCLOG(1)); if (TrackCount > 1) _arVerify.CRCLOG(1, 0); } } LoadAlbumArt(_tracks[0]._fileInfo ?? _fileInfo); ResizeAlbumArt(); if (_config.embedAlbumArt || _config.CopyAlbumArt) _albumArt.ForEach(t => _padding += _albumArt[0].Data.Count); if (_config.embedLog && _eacLog != null) _padding += _eacLog.Length; cueMetadata.Id = TOC.TOCID; taglibMetadata.Id = TOC.TOCID; // TODO: It should also be set when assigning a DataTrack!!! }
public CDRepairEncode(int finalSampleCount, int stride, int npar, bool verify, bool encode, AccurateRipVerify ar) : base (finalSampleCount, stride, npar) { this.ar = ar; this.verify = verify; this.encode = encode; parity = new byte[stride * npar * 2]; if (verify) syndrome = new ushort[stride, npar]; else syndrome = new ushort[1, npar]; ar.CalcSyndrome(galois.ExpTbl, galois.LogTbl, syndrome, parity, stride, stridecount, npar, encode, verify); leadin = new ushort[stride * 2]; leadout = new ushort[stride + laststride]; }
public void Init(AccurateRipVerify ar) { verify = new CDRepairEncode(ar, 10 * 588 * 2); }
public CDRepairEncode(AccurateRipVerify ar, int stride) : base ((int)ar.TOC.Pregap * 588, (int)ar.FinalSampleCount, stride) { this.ar = ar; ar.InitCDRepair(stride, laststride, stridecount, true); }
public void MyTestInitialize() { ar = TestImageGenerator.CreateAccurateRipVerify("13 68 99 136", 2314, 0); ar2 = TestImageGenerator.CreateAccurateRipVerify("0 136 886", 2314, 0); }
static void Main(string[] args) { Console.SetOut(Console.Error); Console.WriteLine("CUERipper v2.1.4 Copyright (C) 2008-10 Grigory Chudov"); Console.WriteLine("This is free software under the GNU GPLv3+ license; There is NO WARRANTY, to"); Console.WriteLine("the extent permitted by law. <http://www.gnu.org/licenses/> for details."); int correctionQuality = 1; string driveLetter = null; int driveOffset = 0; bool test = false; bool forceD8 = false, forceBE = false, quiet = false; for (int arg = 0; arg < args.Length; arg++) { bool ok = true; if (args[arg] == "-P" || args[arg] == "--paranoid") correctionQuality = 2; 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] == "--d8") forceD8 = true; else if (args[arg] == "--be") forceBE = true; else if (args[arg] == "-Q" || args[arg] == "--quiet") quiet = 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) ok = int.TryParse(args[arg], out driveOffset); else ok = false; if (!ok) { Usage(); return; } } char[] drives; if (driveLetter == null || driveLetter.Length < 1) { drives = CDDrivesList.DrivesAvailable(); if (drives.Length < 1) { Console.WriteLine("No CD drives found."); return; } } else { drives = new char[1]; drives[0] = driveLetter[0]; } #if !DEBUG try #endif { CDDriveReader audioSource = new CDDriveReader(); audioSource.Open(drives[0]); if (audioSource.TOC.AudioTracks < 1) { Console.WriteLine("{0}: CD does not contain any audio tracks.", audioSource.Path); audioSource.Close(); return; } if (driveOffset == 0) 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); audioSource.DriveOffset = driveOffset; audioSource.CorrectionQuality = correctionQuality; audioSource.DebugMessages = !quiet; 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, WebRequest.GetSystemWebProxy()); AudioBuffer buff = new AudioBuffer(audioSource, 0x10000); string CDDBId = AccurateRipVerify.CalculateCDDBId(audioSource.TOC); string ArId = AccurateRipVerify.CalculateAccurateRipId(audioSource.TOC); var ctdb = new CUEToolsDB(audioSource.TOC, null); ctdb.Init(arVerify); ctdb.ContactDB(null, "CUETools.ConsoleRipper 2.1.4", audioSource.ARName, true, false, CTDBMetadataSearch.Fast); arVerify.ContactAccurateRip(ArId); CTDBResponseMeta meta = null; foreach (var imeta in ctdb.Metadata) { meta = imeta; break; } //string destFile = (release == null) ? "cdimage.flac" : release.GetArtist() + " - " + release.GetTitle() + ".flac"; string destFile = (meta == null) ? "cdimage.wav" : meta.artist + " - " + meta.album + ".wav"; Console.WriteLine("Drive : {0}", audioSource.Path); Console.WriteLine("Read offset : {0}", audioSource.DriveOffset); 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)); Console.WriteLine("AccurateRip : {0}", arVerify.ARStatus == null ? "ok" : arVerify.ARStatus); Console.WriteLine("MusicBrainz : {0}", meta == null ? "not found" : meta.artist + " - " + meta.album); ProgressMeter meter = new ProgressMeter(); audioSource.ReadProgress += new EventHandler<ReadProgressArgs>(meter.ReadProgress); audioSource.DetectGaps(); StringWriter cueWriter = new StringWriter(); cueWriter.WriteLine("REM DISCID {0}", CDDBId); cueWriter.WriteLine("REM ACCURATERIPID {0}", ArId); cueWriter.WriteLine("REM COMMENT \"{0}\"", audioSource.RipperVersion); if (meta != null && meta.year != "") cueWriter.WriteLine("REM DATE {0}", meta.year); if (audioSource.TOC.Barcode != null) cueWriter.WriteLine("CATALOG {0}", audioSource.TOC.Barcode); if (meta != null) { cueWriter.WriteLine("PERFORMER \"{0}\"", meta.artist); cueWriter.WriteLine("TITLE \"{0}\"", meta.album); } cueWriter.WriteLine("FILE \"{0}\" WAVE", destFile); for (int track = 1; track <= audioSource.TOC.TrackCount; track++) if (audioSource.TOC[track].IsAudio) { cueWriter.WriteLine(" TRACK {0:00} AUDIO", audioSource.TOC[track].Number); if (meta != null && meta.track.Length >= audioSource.TOC[track].Number) { cueWriter.WriteLine(" TITLE \"{0}\"", meta.track[(int)audioSource.TOC[track].Number - 1].name); cueWriter.WriteLine(" PERFORMER \"{0}\"", meta.track[(int)audioSource.TOC[track].Number - 1].artist); } if (audioSource.TOC[track].ISRC != null) cueWriter.WriteLine(" ISRC {0}", audioSource.TOC[track].ISRC); 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); } cueWriter.Close(); StreamWriter cueFile = new StreamWriter(Path.ChangeExtension(destFile, ".cue")); cueFile.Write(cueWriter.ToString()); cueFile.Close(); //IAudioDest audioDest = new FLACWriter(destFile, audioSource.BitsPerSample, audioSource.ChannelCount, audioSource.SampleRate); IAudioDest audioDest = new WAVWriter(destFile, null, audioSource.PCM); audioDest.FinalSampleCount = audioSource.Length; while (audioSource.Read(buff, -1) != 0) { arVerify.Write(buff); audioDest.Write(buff); } TimeSpan totalElapsed = DateTime.Now - meter.realStart; 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, totalElapsed.Hours, totalElapsed.Minutes, totalElapsed.Seconds ); audioDest.Close(); StringWriter logWriter = new StringWriter(); logWriter.WriteLine("{0}", audioSource.RipperVersion); logWriter.WriteLine("Extraction logfile from {0}", DateTime.Now); logWriter.WriteLine("Used drive : {0}", audioSource.Path); logWriter.WriteLine("Read offset correction : {0}", audioSource.DriveOffset); 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 (!wereErrors) { logWriter.WriteLine(); logWriter.WriteLine("Errors detected"); logWriter.WriteLine(); } wereErrors = true; logWriter.WriteLine("Track {0} contains errors", iTrack); break; } logWriter.WriteLine(); logWriter.WriteLine("TOC of the extracted CD"); logWriter.WriteLine(); logWriter.WriteLine(" Track | Start | Length | Start sector | End sector"); logWriter.WriteLine(" ---------------------------------------------------------"); for (int track = 1; track <= audioSource.TOC.TrackCount; track++) logWriter.WriteLine("{0,9} | {1,8} | {2,8} | {3,9} | {4,9}", audioSource.TOC[track].Number, audioSource.TOC[track].StartMSF, audioSource.TOC[track].LengthMSF, audioSource.TOC[track].Start, audioSource.TOC[track].End); logWriter.WriteLine(); logWriter.WriteLine("AccurateRip summary"); logWriter.WriteLine(); arVerify.GenerateFullLog(logWriter, true, ArId); logWriter.WriteLine(); logWriter.WriteLine("End of status report"); logWriter.Close(); StreamWriter logFile = new StreamWriter(Path.ChangeExtension(destFile, ".log")); logFile.Write(logWriter.ToString()); logFile.Close(); audioSource.Close(); //FLACReader tagger = new FLACReader(destFile, null); //tagger.Tags.Add("CUESHEET", cueWriter.ToString()); //tagger.Tags.Add("LOG", logWriter.ToString()); //tagger.UpdateTags(false); } #if !DEBUG catch (Exception ex) { Console.WriteLine(); Console.WriteLine("Error: {0}", ex.Message); Console.WriteLine("{0}", ex.StackTrace); } #endif }
public void TestBeforeCopy() { if (!_isCD) throw new Exception("Not a cd"); _ripper.DetectGaps(); _arTestVerify = new AccurateRipVerify(_toc, proxy); var buff = new AudioBuffer(AudioPCMConfig.RedBook, 0x10000); while (_ripper.Read(buff, -1) != 0) { _arTestVerify.Write(buff); } _ripper.Position = 0; }
public unsafe void Combine(AccurateRipVerify part, int start, int end) { for (int i = 0; i < leadin.Length; i++) { int currentOffset = i / 2 + 588 * (int)this.TOC.Pregap; if (currentOffset >= start && currentOffset < end) this.leadin[i] = part.leadin[i]; } for (int i = 0; i < leadout.Length; i++) { int currentOffset = (int)_finalSampleCount - i / 2 - 1; if (currentOffset >= start && currentOffset < end) this.leadout[i] = part.leadout[i]; } int iSplitTrack = -1; for (int iTrack = 0; iTrack <= _toc.AudioTracks; iTrack++) { int tempLocation = (int)(iTrack == 0 ? 0 : _toc[_toc.FirstAudio + iTrack - 1].Start - _toc[_toc.FirstAudio][0].Start) * 588; int tempLen = (int)(iTrack == 0 ? _toc[_toc.FirstAudio].Pregap : _toc[_toc.FirstAudio + iTrack - 1].Length) * 588; if (start > tempLocation && start <= tempLocation + tempLen) { iSplitTrack = iTrack; break; } } uint crc32 = _CRC32[iSplitTrack, 2 * maxOffset]; uint crcwn = _CRCWN[iSplitTrack, 2 * maxOffset]; int crcnl = _CRCNL[iSplitTrack, 2 * maxOffset]; for (int iTrack = 0; iTrack <= _toc.AudioTracks; iTrack++) { // ??? int tempLocation = (int) (iTrack == 0 ? _toc[_toc.FirstAudio][0].Start : _toc[_toc.FirstAudio + iTrack - 1].Start) * 588; int tempLocation = (int)(iTrack == 0 ? 0 : _toc[_toc.FirstAudio + iTrack - 1].Start - _toc[_toc.FirstAudio][0].Start) * 588; int tempLen = (int)(iTrack == 0 ? _toc[_toc.FirstAudio].Pregap : _toc[_toc.FirstAudio + iTrack - 1].Length) * 588; int trStart = Math.Max(tempLocation, start); int trEnd = Math.Min(tempLocation + tempLen, end); if (trStart >= trEnd) continue; uint crcar = _CRCAR[iTrack, 0]; uint crcv2 = _CRCV2[iTrack, 0]; uint crcsm = _CRCSM[iTrack, 0]; _CRCAR[iTrack, 0] = crcar + part._CRCAR[iTrack, 0]; _CRCSM[iTrack, 0] = crcsm + part._CRCSM[iTrack, 0]; _CRCV2[iTrack, 0] = crcv2 + part._CRCV2[iTrack, 0]; for (int i = 0; i < 3 * maxOffset; i++) { int currentOffset; if (i < maxOffset) currentOffset = tempLocation + i; else if (i < 2 * maxOffset) currentOffset = tempLocation + tempLen + i - 2 * maxOffset; else if (i == 2 * maxOffset) currentOffset = trEnd; else //if (i > 2 * maxOffset) currentOffset = tempLocation + i - 1 - 2 * maxOffset + 445 * 588; if (currentOffset < trStart || currentOffset > trEnd) continue; _CRC32[iTrack, i] = Crc32.Combine(crc32, part._CRC32[iTrack, i], 4 * (currentOffset - start)); _CRCWN[iTrack, i] = Crc32.Combine(crcwn, part._CRCWN[iTrack, i], part._CRCNL[iTrack, i] * 2); _CRCNL[iTrack, i] = crcnl + part._CRCNL[iTrack, i]; if (i == 0 || i == 2 * maxOffset) continue; _CRCAR[iTrack, i] = crcar + part._CRCAR[iTrack, i]; _CRCV2[iTrack, i] = crcv2 + part._CRCV2[iTrack, i]; _CRCSM[iTrack, i] = crcsm + part._CRCSM[iTrack, i]; } _Peak[iTrack] = Math.Max(_Peak[iTrack], part._Peak[iTrack]); } if (calcParity) { var newSyndrome1 = this.GetSyndrome(); var newSyndrome2 = part.GetSyndrome(); int firstSample = 588 * (int)TOC.Pregap; var i1 = Math.Max(0, (start - firstSample) * 2 - stride); var i2 = Math.Min(2 * ((int)_finalSampleCount - firstSample) - laststride - stride, (end - firstSample) * 2 - stride); var diff = i2 / stride - i1 / stride; var i1s = i1 % stride; var i2s = i2 % stride; var imin = Math.Min(i1s, i2s); var imax = Math.Max(i1s, i2s); var diff1 = diff + (imin < i2s ? 1 : 0) - (imin < i1s ? 1 : 0); for (int i = 0; i < stride; i++) for (int j = 0; j < maxNpar; j++) { var d1 = j * (i >= imin && i < imax ? diff1 : diff); newSyndrome1[i, j] = (ushort)(newSyndrome2[i, j] ^ Galois16.instance.mulExp(newSyndrome1[i, j], (d1 & 0xffff) + (d1 >> 16))); } ParityToSyndrome.Syndrome2Parity(newSyndrome1, this.parity); } }
public void OpenCD(ICDRipper ripper) { _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()); } cueMetadata = new CUEMetadata(TOC.TOCID, (int)TOC.AudioTracks); _arVerify = new AccurateRipVerify(_toc, proxy); _isCD = true; SourceInfo cdInfo; cdInfo.Path = _ripper.ARName; cdInfo.Offset = 0; cdInfo.Length = _toc.AudioLength * 588; _sources.Add(cdInfo); // Causes memory leak, so had to disable! //_ripper.ReadProgress += new EventHandler<ReadProgressArgs>(CDReadProgress); _padding += TrackCount * 200; _padding += _config.embedLog ? 500 + TrackCount * 200 : 0; }
// Now to the audio transfer functions, the sequence how // the functions are called is: // StartNewSession // StartNewTransfer // TransferAudio // ... // TransferAudio // TransferFinshed // Then perhaps repeating StartNewTransfer to TransferFinished // (e.g. when extracting several tracks), and finally // EndOfSession // This is called just before the log window will be // shown. You can return a log output in that stage (or // even display a window of your own - even though it should // not annoy the user) // StartNewSession is called once at the very beginning of an // extraction session. It receives the CD metadata, the // name of the used drive, the used read offset and whether // the offset was setted by AccurateRip (so having a comparable // offset value) public void StartNewSession(IMetadataLookup data, string drivename, int offset, bool aroffset, int mode) { // Copy the CD metadata to the object m_data = data; #if DEBUG m_trace = new StringWriter(); #endif var parts = drivename.Split(' '); m_drivename = parts[0].PadRight(8, ' ') + " -"; for (int i = 1; i < parts.Length; i++) m_drivename += " " + parts[i]; TOC = new CDImageLayout(); for (int i = 0; i < m_data.NumberOfTracks; i++) { uint start = m_data.GetTrackStartPosition(i); uint next = m_data.GetTrackEndPosition(i); TOC.AddTrack(new CDTrack( (uint)i + 1, start, next - start, !m_data.GetTrackDataTrack(i), m_data.GetTrackPreemphasis(i))); } TOC[1][0].Start = 0U; ar = new AccurateRipVerify(TOC, null); arTest = new AccurateRipVerify(TOC, null); ctdb = new CUEToolsDB(TOC, null); #if USEAR ArId = AccurateRipVerify.CalculateAccurateRipId(TOC); ar.ContactAccurateRip(ArId); #endif ctdb.Init(ar); this.sequence_ok = true; this.m_start_pos = 0; this.m_length = 0; this.m_test_mode = false; this.is_offset_set = aroffset; this.is_secure_mode = mode >= 2; }