private void WriteLine(StreamWriter sw, int level, CUELine line) { WriteLine(sw, level, line.ToString()); }
public CUESheet(string path, bool autoCorrectFilenames) { string cueDir, lineStr, command, pathAudio, fileType; CUELine line; TrackInfo trackInfo; int tempTimeLength, timeRelativeToFileStart, absoluteFileStartTime; int fileTimeLengthSamples, fileTimeLengthFrames, i, trackNumber; bool seenFirstFileIndex, seenDataTrack; List <IndexInfo> indexes; IndexInfo indexInfo; SourceInfo sourceInfo; _stop = false; _attributes = new List <CUELine>(); _tracks = new List <TrackInfo>(); _sources = new List <SourceInfo>(); _sourcePaths = new List <string>(); _paddedToFrame = false; _usePregapForFirstTrackInSingleFile = false; _preserveHTOA = false; _flacCompressionLevel = 5; _flacVerify = false; _wvCompressionMode = 1; _wvExtraMode = 0; _appliedWriteOffset = false; cueDir = Path.GetDirectoryName(path); pathAudio = null; indexes = new List <IndexInfo>(); trackInfo = null; absoluteFileStartTime = 0; fileTimeLengthSamples = 0; fileTimeLengthFrames = 0; trackNumber = 0; seenFirstFileIndex = false; seenDataTrack = false; if (autoCorrectFilenames) { CorrectAudioFilenames(path, false); } using (StreamReader sr = new StreamReader(path, CUESheet.Encoding)) { while ((lineStr = sr.ReadLine()) != null) { line = new CUELine(lineStr); if (line.Params.Count > 0) { command = line.Params[0].ToUpper(); if (command == "FILE") { fileType = line.Params[2].ToUpper(); if ((fileType == "BINARY") || (fileType == "MOTOROLA")) { seenDataTrack = true; } else if (seenDataTrack) { throw new Exception("Audio tracks cannot appear after data tracks."); } else { pathAudio = LocateFile(cueDir, line.Params[1]); if (pathAudio == null) { throw new Exception("Unable to locate file \"" + line.Params[1] + "\"."); } _sourcePaths.Add(pathAudio); absoluteFileStartTime += fileTimeLengthFrames; fileTimeLengthSamples = GetSampleLength(pathAudio); fileTimeLengthFrames = (int)((fileTimeLengthSamples + 587) / 588); seenFirstFileIndex = false; } } else if (command == "TRACK") { if (line.Params[2].ToUpper() != "AUDIO") { seenDataTrack = true; } else if (seenDataTrack) { throw new Exception("Audio tracks cannot appear after data tracks."); } else { trackNumber = Int32.Parse(line.Params[1]); if (trackNumber != _tracks.Count + 1) { throw new Exception("Invalid track number."); } trackInfo = new TrackInfo(); _tracks.Add(trackInfo); } } else if (seenDataTrack) { // Ignore lines belonging to data tracks } else if (command == "INDEX") { timeRelativeToFileStart = General.TimeFromString(line.Params[2]); if (!seenFirstFileIndex) { if (timeRelativeToFileStart != 0) { throw new Exception("First index must start at file beginning."); } seenFirstFileIndex = true; sourceInfo.Path = pathAudio; sourceInfo.Offset = 0; sourceInfo.Length = fileTimeLengthSamples; _sources.Add(sourceInfo); if ((fileTimeLengthSamples % 588) != 0) { sourceInfo.Path = null; sourceInfo.Offset = 0; sourceInfo.Length = (fileTimeLengthFrames * 588) - fileTimeLengthSamples; _sources.Add(sourceInfo); _paddedToFrame = true; } } indexInfo.Track = trackNumber; indexInfo.Index = Int32.Parse(line.Params[1]); indexInfo.Time = absoluteFileStartTime + timeRelativeToFileStart; indexes.Add(indexInfo); } else if (command == "PREGAP") { if (seenFirstFileIndex) { throw new Exception("Pregap must occur at the beginning of a file."); } tempTimeLength = General.TimeFromString(line.Params[1]); indexInfo.Track = trackNumber; indexInfo.Index = 0; indexInfo.Time = absoluteFileStartTime; indexes.Add(indexInfo); sourceInfo.Path = null; sourceInfo.Offset = 0; sourceInfo.Length = tempTimeLength * 588; _sources.Add(sourceInfo); absoluteFileStartTime += tempTimeLength; } 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 (trackInfo != null) { trackInfo.Attributes.Add(line); } else { _attributes.Add(line); } } } } } if (trackNumber == 0) { throw new Exception("File must contain at least one audio track."); } // 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++) { indexInfo = indexes[i]; tempTimeLength = indexes[i + 1].Time - indexInfo.Time; if (tempTimeLength > 0) { _tracks[indexInfo.Track - 1].AddIndex((indexInfo.Index == 0), tempTimeLength); } else if (tempTimeLength < 0) { throw new Exception("Indexes must be in chronological order."); } } for (i = 0; i < TrackCount; i++) { if (_tracks[i].LastIndex < 1) { throw new Exception("Track must have an INDEX 01."); } } // 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]) : "01.00.wav"; _hasTrackFilenames = (_sourcePaths.Count == TrackCount) || _hasHTOAFilename; _trackFilenames = new List <string>(); for (i = 0; i < TrackCount; i++) { _trackFilenames.Add(_hasTrackFilenames ? Path.GetFileName( _sourcePaths[i + (_hasHTOAFilename ? 1 : 0)]) : String.Format("{0:00}.wav", i + 1)); } }
public static void CorrectAudioFilenames(string path, bool always) { string[] audioExts = new string[] { "*.wav", "*.flac", "*.wv" }; List <string> lines = new List <string>(); List <int> filePos = new List <int>(); bool foundAll = true; string[] audioFiles = null; string lineStr; CUELine line; string dir; int i; dir = Path.GetDirectoryName(path); using (StreamReader sr = new StreamReader(path, CUESheet.Encoding)) { while ((lineStr = sr.ReadLine()) != null) { lines.Add(lineStr); line = new CUELine(lineStr); if ((line.Params.Count == 3) && (line.Params[0].ToUpper() == "FILE")) { string fileType = line.Params[2].ToUpper(); if ((fileType != "BINARY") && (fileType != "MOTOROLA")) { filePos.Add(lines.Count - 1); foundAll &= (LocateFile(dir, line.Params[1]) != null); } } } } if (foundAll && !always) { return; } for (i = 0; i < audioExts.Length; i++) { audioFiles = Directory.GetFiles(dir, audioExts[i]); if (audioFiles.Length == filePos.Count) { break; } } if (i == audioExts.Length) { throw new Exception("Unable to locate the audio files."); } Array.Sort(audioFiles); for (i = 0; i < filePos.Count; i++) { lines[filePos[i]] = "FILE \"" + Path.GetFileName(audioFiles[i]) + "\" WAVE"; } using (StreamWriter sw = new StreamWriter(path, false, CUESheet.Encoding)) { for (i = 0; i < lines.Count; i++) { sw.WriteLine(lines[i]); } } }