public static TonieAudio FromFile(string file) { TonieAudio audio = new TonieAudio(); audio.ReadFile(file); return(audio); }
public static bool DumpInfo(StringBuilder message, eDumpFormat dumpFormat, string file, TonieData[] tonieInfos, string customName = null) { 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()); string dateExtra = ""; int id = dumpFile.Header.AudioId; if (id < 0x50000000) { dateExtra = "custom file, real date "; id += 0x50000000; } var date = DateTimeOffset.FromUnixTimeSeconds(id); bool first = false; switch (dumpFormat) { case eDumpFormat.FormatCSV: { message.Append(uid + ";"); message.Append(dumpFile.Header.AudioId.ToString("X8") + ";"); message.Append(date.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss") + ";"); message.Append(dumpFile.HeaderLength + ";"); message.Append(((dumpFile.HeaderLength != 0xFFC) ? "[WARNING: EXTRA DATA]" : "[OK]") + ";"); message.Append(dumpFile.Header.Padding.Length + ";"); message.Append(dumpFile.Header.AudioLength + ";"); message.Append((dumpFile.Header.AudioLength == dumpFile.Audio.Length ? "[OK]" : "[INCORRECT]") + ";"); message.Append(BitConverter.ToString(dumpFile.Header.Hash).Replace("-", "") + ";"); message.Append((dumpFile.HashCorrect ? "[OK]" : "[INCORRECT]") + ";"); foreach (var offset in dumpFile.Header.AudioChapters) { message.Append(offset + " "); } message.Append(";"); message.Append(segCount + ";"); message.Append(minSegs + ";"); message.Append(maxSegs + ";"); message.Append(segLength + ";"); message.Append(highestGranule + ";"); message.Append(TonieAudio.FormatGranule(highestGranule) + ";"); message.Append(minGranule + ";"); message.Append(maxGranule + ";"); message.Append((1000 * minGranule / 48000.0f) + ";"); message.Append((1000 * maxGranule / 48000.0f) + ";"); message.AppendLine(); break; } case eDumpFormat.FormatText: { message.AppendLine("Dump of " + dumpFile.Filename + " (UID " + uid + "):"); message.AppendLine(" Header: AudioID 0x" + dumpFile.Header.AudioId.ToString("X8") + " (" + dateExtra + date.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss") + ")"); string[] titles = null; string hashString = BitConverter.ToString(dumpFile.Header.Hash).Replace("-", ""); var found = tonieInfos.Where(t => t.Hash.Contains(hashString)); TonieData info = null; string infoHashString = null; int infoIndex = 0; if (found.Count() > 0) { info = found.First(); titles = info.Tracks; infoIndex = Array.IndexOf(info.AudioIds, dumpFile.Header.AudioId); Array.Resize(ref info.Hash, info.AudioIds.Length); infoHashString = info.Hash[infoIndex]; message.AppendLine(" Header: JSON Name '" + info.Title + "'"); } if (!string.IsNullOrEmpty(customName)) { message.AppendLine(" Header: Custom Name '" + customName + "'"); } message.AppendLine(" Header: Length 0x" + dumpFile.HeaderLength.ToString("X8") + " " + ((dumpFile.HeaderLength != 0xFFC) ? " [WARNING: EXTRA DATA]" : "[OK]")); message.AppendLine(" Header: Padding 0x" + dumpFile.Header.Padding.Length.ToString("X8")); message.AppendLine(" Header: AudioLen 0x" + dumpFile.Header.AudioLength.ToString("X8") + " " + (dumpFile.Header.AudioLength == dumpFile.Audio.Length ? "[OK]" : "[INCORRECT]")); message.AppendLine(" Header: Checksum " + hashString + " " + (dumpFile.HashCorrect ? "[OK]" : "[INCORRECT]") + " " + (infoHashString != null ? (infoHashString == hashString ? "[JSON MATCH]" : "[JSON MISMATCH]") : "[NO JSON INFO]")); message.AppendLine(" Header: Chapters "); if (info != null && infoHashString == null) { info.Hash[infoIndex] = hashString; } 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]; } message.AppendLine(" Track #" + track.ToString("00") + " " + lengthString + " " + title); } message.AppendLine(" Ogg: Segments " + segCount + " (min: " + minSegs + " max: " + maxSegs + " per OggPage)"); message.AppendLine(" Ogg: net payload " + segLength + " byte"); message.AppendLine(" Ogg: granules total: " + highestGranule + " (" + TonieAudio.FormatGranule(highestGranule) + " hh:mm:ss.ff)"); message.AppendLine(" Ogg: granules/page min: " + minGranule + " max: " + maxGranule + " (" + (1000 * minGranule / 48000.0f) + "ms - " + (1000 * maxGranule / 48000.0f) + "ms)"); message.AppendLine(); break; } case eDumpFormat.FormatJSON: { if (!first) { message.AppendLine(","); } message.AppendLine(" {"); message.AppendLine(" \"uid\": \"" + uid + "\","); message.AppendLine(" \"audio_id\": \"" + dumpFile.Header.AudioId.ToString("X8") + "\","); message.AppendLine(" \"audio_date\": \"" + date.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss") + "\","); message.AppendLine(" \"header_length\": " + dumpFile.HeaderLength + ","); message.AppendLine(" \"header_ok\": \"" + ((dumpFile.HeaderLength != 0xFFC) ? "FALSE" : "TRUE") + "\","); message.AppendLine(" \"padding\": " + dumpFile.Header.Padding.Length + ","); message.AppendLine(" \"audio_length\": " + dumpFile.Header.AudioLength + ","); message.AppendLine(" \"audio_length_check\": \"" + (dumpFile.Header.AudioLength == dumpFile.Audio.Length ? "TRUE" : "FALSE") + "\","); message.AppendLine(" \"audio_hash\": \"" + BitConverter.ToString(dumpFile.Header.Hash).Replace("-", "") + "\","); message.AppendLine(" \"audio_hash_check\": \"" + (dumpFile.HashCorrect ? "TRUE" : "FALSE") + "\","); message.Append(" \"chapters\": [ 0"); foreach (var offset in dumpFile.Header.AudioChapters) { message.Append(", " + offset); } message.AppendLine(" ],"); message.AppendLine(" \"segments\": " + segCount + ","); message.AppendLine(" \"min_segments_per_page\": " + minSegs + ","); message.AppendLine(" \"max_segments_per_page\": " + maxSegs + ","); message.AppendLine(" \"segment_length_sum\": " + segLength + ","); message.AppendLine(" \"highest_granule\": " + highestGranule + ","); message.AppendLine(" \"time\": \"" + TonieAudio.FormatGranule(highestGranule) + "\","); message.AppendLine(" \"min_granules\": " + minGranule + ","); message.AppendLine(" \"max_granules\": " + maxGranule + ","); message.AppendLine(" \"min_time\": " + (1000 * minGranule / 48000.0f) + ","); message.AppendLine(" \"max_time\": " + (1000 * maxGranule / 48000.0f) + ""); message.AppendLine(" }"); break; } } return(true); }