public static string BuildCueSheet(TonieAudio file) { ulong[] positions = file.ParsePositions(); string[] titles = null; string title = null; StringBuilder cue = new StringBuilder(); var found = TonieInfos.Where(t => t.AudioIds.Contains(file.Header.AudioId)); if (found.Count() > 0) { var info = found.First(); title = info.Title; titles = info.Tracks; } if (title != null) { cue.Append("TITLE \"").Append(title).AppendLine("\""); } cue.Append("FILE ").Append(file.FilenameShort).Append(".ogg").AppendLine(" MP3"); for (int chapter = 0; chapter < file.Header.AudioChapters.Length; chapter++) { /* seems the chapter is the page, but off by one */ uint offset = file.Header.AudioChapters[chapter]; ulong granule = file.GetGranuleByPage((offset > 0) ? (offset - 1) : 0); cue.Append(" TRACK ").Append(chapter + 1).AppendLine(" AUDIO"); if (titles != null) { cue.Append(" TITLE \"").Append(titles[chapter]).AppendLine("\""); } string time = FormatGranuleCue(granule); cue.Append(" INDEX 1 ").AppendLine(time); } return(cue.ToString()); }
static void Main(string[] args) { bool showLicense = false; bool showHelp = false; eDumpFormat dumpFormat = eDumpFormat.FormatText; bool useVbr = false; string mode = ""; string outputLocation = ""; string prefixLocation = null; string audioId = ""; string jsonFile = "tonies.json"; int bitRate = 96; var p = new OptionSet { { "m|mode=", "Operating mode: info, decode, encode", (string n) => mode = n }, { "o|output=", "Location where to write the file(s) to", (string r) => outputLocation = r }, { "p|prefix=", "Location where to find prefix files", (string r) => prefixLocation = r }, { "i|id=", "Set AudioID for encoding (default: current time)", (string r) => audioId = r }, { "b|bitrate=", "Set opus bit rate (default: " + bitRate + " kbps)", (int r) => bitRate = r }, { "vbr", "Use VBR encoding", r => useVbr = true }, { "j|json=", "Set JSON file/URL with details about tonies", (string r) => jsonFile = r }, { "f|format=", "Output details as: csv, json or text", v => { switch (v) { case "csv": dumpFormat = eDumpFormat.FormatCSV; break; case "json": dumpFormat = eDumpFormat.FormatJSON; break; case "text": dumpFormat = eDumpFormat.FormatText; break; } } }, { "v", "increase debug message verbosity", v => { if (v != null) { ++Verbosity; } } }, { "h|help", "show this message and exit", h => showHelp = true }, { "license", "show licenses and disclaimer", h => showLicense = true }, }; List <string> extra; try { extra = p.Parse(args); } catch (OptionException e) { Console.Write("Teddy.exe: "); Console.WriteLine(e.Message); Console.WriteLine("Try `Teddy.exe --help' for more information."); return; } if (showLicense) { ShowLicense(p); return; } if (showHelp) { ShowHelp(p); return; } LoadJson(jsonFile); switch (mode) { default: ShowHelp(p); return; case "info": { if (extra.Count < 1 || (!Directory.Exists(extra[0]) && !File.Exists(extra[0]))) { Console.WriteLine("Error: You must specify a file"); return; } switch (dumpFormat) { case eDumpFormat.FormatCSV: if (extra.Count > 1 || Directory.Exists(extra[0])) { Console.WriteLine("UID;AudioID;AudioDate;HeaderLength;HeaderOK;Padding;AudioLength;AudioLengthCheck;AudioHash;AudioHashCheck;Chapters;Segments;MinSegmentsPerPage;MaxSegmentsPerPage;SegLengthSum;HighestGranule;Time;MinGranules;MaxGranules;MinTime;MaxTime;"); } break; case eDumpFormat.FormatJSON: Console.WriteLine("["); break; case eDumpFormat.FormatText: Console.WriteLine("[Mode: dump information]"); break; } List <string> files = new List <string>(); foreach (string file in extra) { if (Directory.Exists(file)) { FindTonieFiles(files, file); } else { if (!File.Exists(file)) { Console.WriteLine("Error: file '" + file + "' does not exist"); return; } files.Add(file); } } bool first = true; foreach (string file in files.ToArray()) { try { TonieAudio dumpFile = TonieAudio.FromFile(file); dumpFile.CalculateStatistics(out long segCount, out long segLength, out int minSegs, out int maxSegs, out ulong minGranule, out ulong maxGranule, out ulong highestGranule); string uidrev = new FileInfo(file).Directory.Name + new FileInfo(file).Name; List <string> groups = (from Match m in Regex.Matches(uidrev, @"[A-F0-9]{2}") select m.Value).ToList(); groups.Reverse(); string uid = string.Join("", groups.ToArray()); var date = DateTimeOffset.FromUnixTimeSeconds(dumpFile.Header.AudioId); switch (dumpFormat) { case eDumpFormat.FormatCSV: { Console.Write(uid + ";"); Console.Write(dumpFile.Header.AudioId.ToString("X8") + ";"); Console.Write(date.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss") + ";"); Console.Write(dumpFile.HeaderLength + ";"); Console.Write(((dumpFile.HeaderLength != 0xFFC) ? "[WARNING: EXTRA DATA]" : "[OK]") + ";"); Console.Write(dumpFile.Header.Padding.Length + ";"); Console.Write(dumpFile.Header.AudioLength + ";"); Console.Write((dumpFile.Header.AudioLength == dumpFile.Audio.Length ? "[OK]" : "[INCORRECT]") + ";"); Console.Write(BitConverter.ToString(dumpFile.Header.Hash).Replace("-", "") + ";"); Console.Write((dumpFile.HashCorrect ? "[OK]" : "[INCORRECT]") + ";"); foreach (var offset in dumpFile.Header.AudioChapters) { Console.Write(offset + " "); } Console.Write(";"); Console.Write(segCount + ";"); Console.Write(minSegs + ";"); Console.Write(maxSegs + ";"); Console.Write(segLength + ";"); Console.Write(highestGranule + ";"); Console.Write(TonieAudio.FormatGranule(highestGranule) + ";"); Console.Write(minGranule + ";"); Console.Write(maxGranule + ";"); Console.Write((1000 * minGranule / 48000.0f) + ";"); Console.Write((1000 * maxGranule / 48000.0f) + ";"); Console.WriteLine(); break; } case eDumpFormat.FormatText: { Console.WriteLine("Dump of " + dumpFile.Filename + " (UID " + uid + "):"); Console.WriteLine(" Header: AudioID 0x" + dumpFile.Header.AudioId.ToString("X8") + " (" + date.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss") + ")"); string[] titles = null; var found = TonieInfos.Where(t => t.AudioIds.Contains(dumpFile.Header.AudioId)); if (found.Count() > 0) { var info = found.First(); titles = info.Tracks; Console.WriteLine(" Header: JSON Name '" + info.Title + "'"); } Console.WriteLine(" Header: Length 0x" + dumpFile.HeaderLength.ToString("X8") + " " + ((dumpFile.HeaderLength != 0xFFC) ? " [WARNING: EXTRA DATA]" : "[OK]")); Console.WriteLine(" Header: Padding 0x" + dumpFile.Header.Padding.Length.ToString("X8")); Console.WriteLine(" Header: AudioLen 0x" + dumpFile.Header.AudioLength.ToString("X8") + " " + (dumpFile.Header.AudioLength == dumpFile.Audio.Length ? "[OK]" : "[INCORRECT]")); Console.WriteLine(" Header: Checksum " + BitConverter.ToString(dumpFile.Header.Hash).Replace("-", "") + " " + (dumpFile.HashCorrect ? "[OK]" : "[INCORRECT]")); Console.WriteLine(" Header: Chapters "); TimeSpan prevTime = new TimeSpan(); for (int track = 1; track <= dumpFile.Header.AudioChapters.Length; track++) { uint off = dumpFile.GetHighestPage(); if (track < dumpFile.Header.AudioChapters.Length) { off = dumpFile.Header.AudioChapters[track]; } ulong granule = dumpFile.GetGranuleByPage(off); string lengthString = "@" + off; if (granule != ulong.MaxValue) { TimeSpan trackOffset = TimeSpan.FromSeconds(granule / 48000.0f); lengthString = (trackOffset - prevTime).ToString(@"mm\:ss\.ff"); prevTime = trackOffset; } string title = ""; if (titles != null && track - 1 < titles.Length) { title = titles[track - 1]; } Console.WriteLine(" Track #" + track.ToString("00") + " " + lengthString + " " + title); } Console.WriteLine(" Ogg: Segments " + segCount + " (min: " + minSegs + " max: " + maxSegs + " per OggPage)"); Console.WriteLine(" Ogg: net payload " + segLength + " byte"); Console.WriteLine(" Ogg: granules total: " + highestGranule + " (" + TonieAudio.FormatGranule(highestGranule) + " hh:mm:ss.ff)"); Console.WriteLine(" Ogg: granules/page min: " + minGranule + " max: " + maxGranule + " (" + (1000 * minGranule / 48000.0f) + "ms - " + (1000 * maxGranule / 48000.0f) + "ms)"); Console.WriteLine(); break; } case eDumpFormat.FormatJSON: { if (!first) { Console.WriteLine(","); } Console.WriteLine(" {"); Console.WriteLine(" \"uid\": \"" + uid + "\","); Console.WriteLine(" \"audio_id\": \"" + dumpFile.Header.AudioId.ToString("X8") + "\","); Console.WriteLine(" \"audio_date\": \"" + date.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss") + "\","); Console.WriteLine(" \"header_length\": " + dumpFile.HeaderLength + ","); Console.WriteLine(" \"header_ok\": \"" + ((dumpFile.HeaderLength != 0xFFC) ? "FALSE" : "TRUE") + "\","); Console.WriteLine(" \"padding\": " + dumpFile.Header.Padding.Length + ","); Console.WriteLine(" \"audio_length\": " + dumpFile.Header.AudioLength + ","); Console.WriteLine(" \"audio_length_check\": \"" + (dumpFile.Header.AudioLength == dumpFile.Audio.Length ? "TRUE" : "FALSE") + "\","); Console.WriteLine(" \"audio_hash\": \"" + BitConverter.ToString(dumpFile.Header.Hash).Replace("-", "") + "\","); Console.WriteLine(" \"audio_hash_check\": \"" + (dumpFile.HashCorrect ? "TRUE" : "FALSE") + "\","); Console.Write(" \"chapters\": [ 0"); foreach (var offset in dumpFile.Header.AudioChapters) { Console.Write(", " + offset); } Console.WriteLine(" ],"); Console.WriteLine(" \"segments\": " + segCount + ","); Console.WriteLine(" \"min_segments_per_page\": " + minSegs + ","); Console.WriteLine(" \"max_segments_per_page\": " + maxSegs + ","); Console.WriteLine(" \"segment_length_sum\": " + segLength + ","); Console.WriteLine(" \"highest_granule\": " + highestGranule + ","); Console.WriteLine(" \"time\": \"" + TonieAudio.FormatGranule(highestGranule) + "\","); Console.WriteLine(" \"min_granules\": " + minGranule + ","); Console.WriteLine(" \"max_granules\": " + maxGranule + ","); Console.WriteLine(" \"min_time\": " + (1000 * minGranule / 48000.0f) + ","); Console.WriteLine(" \"max_time\": " + (1000 * maxGranule / 48000.0f) + ""); Console.WriteLine(" }"); break; } } } catch (FileNotFoundException ex) { Console.WriteLine("File not found: " + file); } catch (InvalidDataException ex) { Console.WriteLine("File corrupt: " + file); } catch (Exception e) { Console.WriteLine(); Console.WriteLine("[ERROR] Failed to process '" + file + "'"); Console.WriteLine(" Exception: " + e.GetType()); Console.WriteLine(" Message: " + e.Message); Console.WriteLine(" Stacktrace: " + e.StackTrace); } if (first) { first = false; } } switch (dumpFormat) { case eDumpFormat.FormatCSV: break; case eDumpFormat.FormatJSON: Console.WriteLine("]"); break; case eDumpFormat.FormatText: break; } break; } case "decode": { if (extra.Count < 1 || (!Directory.Exists(extra[0]) && !File.Exists(extra[0]))) { Console.WriteLine("Error: You must specify a file"); return; } List <string> files = new List <string>(); foreach (string file in extra) { if (Directory.Exists(file)) { FindTonieFiles(files, file); } else { if (!File.Exists(file)) { Console.WriteLine("Error: file '" + file + "' does not exist"); return; } files.Add(file); } } Console.WriteLine("[Mode: decode file]"); foreach (string file in files.ToArray()) { try { Console.WriteLine("Dumping '" + file + "'"); TonieAudio dump2 = TonieAudio.FromFile(file); string inFile = new FileInfo(file).Name; string inDir = new FileInfo(file).DirectoryName; string outDirectory = !string.IsNullOrEmpty(outputLocation) ? outputLocation : inDir; if (!Directory.Exists(outDirectory)) { Console.WriteLine("Error: Output directory '" + outDirectory + "' does not exist"); return; } string outFile = outDirectory + Path.DirectorySeparatorChar + inFile; try { File.WriteAllBytes(outFile + ".ogg", dump2.Audio); File.WriteAllText(outFile + ".cue", BuildCueSheet(dump2), Encoding.UTF8); } catch (Exception ex) { Console.WriteLine("[ERROR] Failed to write file '" + outFile + ".occ/.cue'"); Console.WriteLine(" Message: " + ex.Message); } Console.WriteLine("Written content to " + outFile + ".ogg/.cue"); } catch (FileNotFoundException ex) { Console.WriteLine("File not found: " + file); } catch (InvalidDataException ex) { Console.WriteLine("File corrupt: " + file); } catch (Exception e) { Console.WriteLine(); Console.WriteLine("[ERROR] Failed to process '" + file + "'"); Console.WriteLine(" Exception: " + e.GetType()); Console.WriteLine(" Message: " + e.Message); Console.WriteLine(" Stacktrace: " + e.StackTrace); } } break; } case "encode": Console.WriteLine("[Mode: encode, " + bitRate + " kbps, " + (useVbr ? "VBR" : "CBR") + "]"); if (extra.Count < 1) { Console.WriteLine("Error: You must specify a directory or files to encode"); return; } /* * if ((bitRate % 24) != 0) * { * Console.WriteLine("Error: You must specify a multiple of 24 kbps, else block alignment in output file would produce incompatible files"); * return; * }*/ uint id = (uint)DateTimeOffset.Now.ToUnixTimeSeconds(); if (audioId != "") { if (audioId.Trim().StartsWith("0x")) { if (!uint.TryParse(audioId.Replace("0x", ""), System.Globalization.NumberStyles.HexNumber, null, out id)) { Console.WriteLine("Error: You must specify the AudioID as hex value like 0x5E034216 or as decimal number like 1577271830"); return; } } else { if (!uint.TryParse(audioId, System.Globalization.NumberStyles.Integer, null, out id)) { Console.WriteLine("Error: You must specify the AudioID as hex value like 0x5E034216 or as decimal number like 1577271830"); return; } } } try { string outLocationEncode = ((!string.IsNullOrEmpty(outputLocation)) ? outputLocation : "."); string outFile; if (!Directory.Exists(outLocationEncode)) { string baseDirOutFile = new FileInfo(outLocationEncode).DirectoryName; if (!Directory.Exists(baseDirOutFile)) { Console.WriteLine("Error: Specified output directory '" + outLocationEncode + "' does not exist and file '" + baseDirOutFile + "' not reachable."); return; } outFile = outLocationEncode; } else { outFile = outLocationEncode + Path.DirectorySeparatorChar + "500304E0"; } TonieAudio generated = new TonieAudio(extra.ToArray(), id, bitRate * 1000, useVbr, prefixLocation); try { File.WriteAllBytes(outFile, generated.FileContent); } catch (Exception ex) { Console.WriteLine("[ERROR] Failed to write file '" + outFile + "'"); Console.WriteLine(" Message: " + ex.Message); } Console.WriteLine(""); Console.WriteLine("Written content to " + outFile); } catch (FileNotFoundException ex) { Console.WriteLine("[ERROR] Failed to process due to a missing file"); Console.WriteLine(" Message: " + ex.Message); } catch (InvalidDataException ex) { Console.WriteLine("[ERROR] Failed to process due to an invalid file"); Console.WriteLine(" Message: " + ex.Message); } catch (TonieAudio.EncodingException ex) { Console.WriteLine("[ERROR] Failed to encode audio"); Console.WriteLine(" Message: " + ex.Message); } catch (Exception e) { Console.WriteLine(); Console.WriteLine("[ERROR] Failed to process"); Console.WriteLine(" Exception: " + e.GetType()); Console.WriteLine(" Message: " + e.Message); Console.WriteLine(" Stacktrace: " + e.StackTrace); } break; } }
static void Main(string[] args) { bool showLicense = false; bool showHelp = false; TonieTools.eDumpFormat dumpFormat = TonieTools.eDumpFormat.FormatText; bool useVbr = false; bool reallyRename = false; bool deleteDuplicates = false; bool singleOgg = false; string mode = ""; string outputLocation = ""; string prefixLocation = null; string audioId = ""; string writeJson = null; string jsonFile = "http://gt-blog.de/JSON/tonies.json?source=Teddy&version=" + ThisAssembly.Git.BaseTag; int bitRate = 96; var p = new OptionSet { { "m|mode=", "Operating mode: info, decode, encode, rename", (string n) => mode = n }, { "o|output=", "Location where to write the file(s) to", (string r) => outputLocation = r }, { "p|prefix=", "encode: Location where to find prefix files", (string r) => prefixLocation = r }, { "i|id=", "encode: Set AudioID for encoding (default: current time)", (string r) => audioId = r }, { "b|bitrate=", "encode: Set opus bit rate (default: " + bitRate + " kbps)", (int r) => bitRate = r }, { "vbr", "encode: Use VBR encoding", r => useVbr = true }, { "s", "decode: Export as single .ogg file", r => singleOgg = true }, { "y", "rename: really rename files, else its a dry run", v => { reallyRename = true; } }, { "d", "rename: delete duplicates", v => { deleteDuplicates = true; } }, { "w|write=", "info: write updated json to local file", (string v) => { writeJson = v; } }, { "j|json=", "Set JSON file/URL with details about tonies", (string r) => jsonFile = r }, { "f|format=", "Output details as: csv, json or text", v => { switch (v) { case "csv": dumpFormat = TonieTools.eDumpFormat.FormatCSV; break; case "json": dumpFormat = TonieTools.eDumpFormat.FormatJSON; break; case "text": dumpFormat = TonieTools.eDumpFormat.FormatText; break; } } }, { "v", "increase debug message verbosity", v => { if (v != null) { ++Verbosity; } } }, { "h|help", "show this message and exit", h => showHelp = true }, { "license", "show licenses and disclaimer", h => showLicense = true }, }; List <string> extra; try { extra = p.Parse(args); } catch (OptionException e) { Console.Write("Teddy.exe: "); Console.WriteLine(e.Message); Console.WriteLine("Try `Teddy.exe --help' for more information."); return; } if (showLicense) { ShowLicense(p); return; } if (showHelp) { ShowHelp(p); return; } LoadJson(jsonFile); switch (mode) { default: ShowHelp(p); return; case "rename": { Dictionary <string, string> renameList = new Dictionary <string, string>(); List <string> files = new List <string>(); if (extra.Count < 2 || (!Directory.Exists(extra[0]) && !Directory.Exists(extra[1]))) { Console.WriteLine("Error: You must specify a source and a destination directory"); return; } FindTonieFiles(files, extra[0]); Console.WriteLine(" Scan files..."); foreach (string file in files.ToArray()) { try { TonieAudio dumpFile = TonieAudio.FromFile(file); /* skip creative tonies for now */ if (dumpFile.Header.AudioId == 1) { Console.WriteLine(" '" + file + "' -> '(creative)'"); continue; } var found = TonieInfos.Where(t => t.AudioIds.Contains(dumpFile.Header.AudioId)); string destFileName = "(unknown)"; if (found.Count() > 0) { var info = found.First(); destFileName = info.Title; if (!string.IsNullOrEmpty(info.Model)) { string destName = Path.Combine(extra[1], info.Model + " - " + dumpFile.Header.AudioId.ToString("X8") + " - " + RemoveInvalidChars(destFileName).Trim()); if (file != destName) { renameList.Add(file, destName); } } } Console.WriteLine(" '" + file + "' -> '" + destFileName + "'"); } catch (FileNotFoundException ex) { Console.WriteLine("File not found: " + file); } catch (InvalidDataException ex) { Console.WriteLine(" '" + file + "' -> (corrupt)"); } catch (Exception e) { Console.WriteLine(); Console.WriteLine("[ERROR] Failed to process '" + file + "'"); Console.WriteLine(" Exception: " + e.GetType()); Console.WriteLine(" Message: " + e.Message); Console.WriteLine(" Stacktrace: " + e.StackTrace); } } Console.WriteLine(""); Console.WriteLine(" Rename files..."); int renamed = 0; foreach (var key in renameList.Keys) { string dest = renameList[key]; Console.WriteLine(" Rename '" + key + "' -> '" + dest + "'"); if (File.Exists(dest)) { if (FileChecksum(dest) == FileChecksum(key)) { if (deleteDuplicates) { if (reallyRename) { var di = new FileInfo(key).Directory; File.Delete(key); renamed++; if (di.GetFiles().Length == 0) { di.Delete(); } } } else { Console.WriteLine(" Skipped, destination file content matches"); } } else { Console.WriteLine(" Skipped, destination file already exists but has different content"); } continue; } if (reallyRename) { var di = new FileInfo(key).Directory; try { File.Move(key, dest); renamed++; if (di.GetFiles().Length == 0) { di.Delete(); } } catch (Exception e) { Console.WriteLine("[ERROR] Failed to rename '" + key + "'"); } } } Console.WriteLine(""); Console.WriteLine(" Renamed " + renamed + " files"); break; } case "info": { if (extra.Count < 1 || (!Directory.Exists(extra[0]) && !File.Exists(extra[0]))) { Console.WriteLine("Error: You must specify a file"); return; } switch (dumpFormat) { case TonieTools.eDumpFormat.FormatCSV: if (extra.Count > 1 || Directory.Exists(extra[0])) { Console.WriteLine("UID;AudioID;AudioDate;HeaderLength;HeaderOK;Padding;AudioLength;AudioLengthCheck;AudioHash;AudioHashCheck;Chapters;Segments;MinSegmentsPerPage;MaxSegmentsPerPage;SegLengthSum;HighestGranule;Time;MinGranules;MaxGranules;MinTime;MaxTime;"); } break; case TonieTools.eDumpFormat.FormatJSON: Console.WriteLine("["); break; case TonieTools.eDumpFormat.FormatText: Console.WriteLine("[Mode: dump information]"); break; } List <string> files = new List <string>(); foreach (string file in extra) { if (Directory.Exists(file)) { FindTonieFiles(files, file); } else { if (!File.Exists(file)) { Console.WriteLine("Error: file '" + file + "' does not exist"); return; } files.Add(file); } } bool first = true; foreach (string file in files.ToArray()) { try { StringBuilder message = new StringBuilder(); TonieTools.DumpInfo(message, dumpFormat, file, TonieInfos); Console.Write(message.ToString()); } catch (FileNotFoundException ex) { Console.WriteLine("File not found: " + file); } catch (InvalidDataException ex) { Console.WriteLine("File corrupt: " + file); } catch (Exception e) { Console.WriteLine(); Console.WriteLine("[ERROR] Failed to process '" + file + "'"); Console.WriteLine(" Exception: " + e.GetType()); Console.WriteLine(" Message: " + e.Message); Console.WriteLine(" Stacktrace: " + e.StackTrace); } if (first) { first = false; } } switch (dumpFormat) { case TonieTools.eDumpFormat.FormatCSV: break; case TonieTools.eDumpFormat.FormatJSON: Console.WriteLine("]"); break; case TonieTools.eDumpFormat.FormatText: break; } if (writeJson != null) { SaveJson(writeJson); } break; } case "decode": { if (extra.Count < 1 || (!Directory.Exists(extra[0]) && !File.Exists(extra[0]))) { Console.WriteLine("Error: You must specify a file"); return; } List <string> files = new List <string>(); foreach (string file in extra) { if (Directory.Exists(file)) { FindTonieFiles(files, file); } else { if (!File.Exists(file)) { Console.WriteLine("Error: file '" + file + "' does not exist"); return; } files.Add(file); } } Console.WriteLine("[Mode: decode file]"); foreach (string file in files.ToArray()) { try { TonieAudio dump2 = TonieAudio.FromFile(file); string[] titles = null; List <string> tags = new List <string>(); tags.Add("TeddyVersion=" + GetVersion()); tags.Add("TeddyFile=" + file); string hashString = BitConverter.ToString(dump2.Header.Hash).Replace("-", ""); var found = TonieInfos.Where(t => t.Hash.Contains(hashString)); TonieTools.TonieData info = null; if (found.Count() > 0) { info = found.First(); titles = info.Tracks; tags.Add("ALBUM=" + info.Title); tags.Add("ARTIST=" + info.Series); tags.Add("LANGUAGE=" + info.Language); } tags.Add("HASH=" + hashString); string inFile = new FileInfo(file).Name; string inDir = new FileInfo(file).DirectoryName; string outDirectory = !string.IsNullOrEmpty(outputLocation) ? outputLocation : inDir; if (!Directory.Exists(outDirectory)) { Console.WriteLine("Error: Output directory '" + outDirectory + "' does not exist"); return; } try { dump2.DumpAudioFiles(outDirectory, inFile + "-" + dump2.Header.AudioId.ToString("X8"), singleOgg, tags.ToArray(), titles); } catch (Exception ex) { Console.WriteLine("[ERROR] Failed to write .ogg/.cue'"); Console.WriteLine(" Message: " + ex.Message); } } catch (FileNotFoundException ex) { Console.WriteLine("File not found: " + file); } catch (InvalidDataException ex) { Console.WriteLine("File corrupt: " + file); } catch (Exception e) { Console.WriteLine(); Console.WriteLine("[ERROR] Failed to process '" + file + "'"); Console.WriteLine(" Exception: " + e.GetType()); Console.WriteLine(" Message: " + e.Message); Console.WriteLine(" Stacktrace: " + e.StackTrace); } } break; } case "encode": Console.WriteLine("[Mode: encode, " + bitRate + " kbps, " + (useVbr ? "VBR" : "CBR") + "]"); if (extra.Count < 1) { Console.WriteLine("Error: You must specify a directory or files to encode"); return; } /* * if ((bitRate % 24) != 0) * { * Console.WriteLine("Error: You must specify a multiple of 24 kbps, else block alignment in output file would produce incompatible files"); * return; * }*/ uint id = (uint)DateTimeOffset.Now.ToUnixTimeSeconds() - 0x50000000; if (audioId != "") { if (audioId.Trim().StartsWith("0x")) { if (!uint.TryParse(audioId.Replace("0x", ""), System.Globalization.NumberStyles.HexNumber, null, out id)) { Console.WriteLine("Error: You must specify the AudioID as hex value like 0x5E034216 or as decimal number like 1577271830"); return; } } else { if (!uint.TryParse(audioId, System.Globalization.NumberStyles.Integer, null, out id)) { Console.WriteLine("Error: You must specify the AudioID as hex value like 0x5E034216 or as decimal number like 1577271830"); return; } } } try { string outLocationEncode = ((!string.IsNullOrEmpty(outputLocation)) ? outputLocation : "."); string outFile; if (!Directory.Exists(outLocationEncode)) { string baseDirOutFile = new FileInfo(outLocationEncode).DirectoryName; if (!Directory.Exists(baseDirOutFile)) { Console.WriteLine("Error: Specified output directory '" + outLocationEncode + "' does not exist and file '" + baseDirOutFile + "' not reachable."); return; } outFile = outLocationEncode; } else { outFile = Path.Combine(outLocationEncode, "500304E0"); } TonieAudio generated = new TonieAudio(extra.ToArray(), id, bitRate * 1000, useVbr, prefixLocation); try { File.WriteAllBytes(outFile, generated.FileContent); } catch (Exception ex) { Console.WriteLine("[ERROR] Failed to write file '" + outFile + "'"); Console.WriteLine(" Message: " + ex.Message); } Console.WriteLine(""); Console.WriteLine("Written content to " + outFile); } catch (FileNotFoundException ex) { Console.WriteLine("[ERROR] Failed to process due to a missing file"); Console.WriteLine(" Message: " + ex.Message); } catch (InvalidDataException ex) { Console.WriteLine("[ERROR] Failed to process due to an invalid file"); Console.WriteLine(" Message: " + ex.Message); } catch (TonieAudio.EncodingException ex) { Console.WriteLine("[ERROR] Failed to encode audio"); Console.WriteLine(" Message: " + ex.Message); } catch (Exception e) { Console.WriteLine(); Console.WriteLine("[ERROR] Failed to process"); Console.WriteLine(" Exception: " + e.GetType()); Console.WriteLine(" Message: " + e.Message); Console.WriteLine(" Stacktrace: " + e.StackTrace); } break; } }