static void Main(string[] args) { Options options = null; try { options = CommandLine.Parse<Options>(); } catch (CommandLineException exception) { Console.WriteLine(exception.ArgumentHelp.Message); Console.WriteLine(); Console.WriteLine(exception.ArgumentHelp.GetHelpText(Console.BufferWidth)); #if DEBUG Console.ReadLine(); #endif return; } using (Stream stream = File.OpenRead(options.Source)) { string bnkName = (options.Output != null) ? options.Output : Path.ChangeExtension(Path.GetFileName(options.Source), "bnk_pc"); string mbnkName = Path.ChangeExtension(bnkName, "mbnk_pc"); Console.WriteLine("Building {0} from {1}.", bnkName, options.Source); using (XmlReader reader = XmlReader.Create(stream)) { reader.ReadToFollowing("soundbank"); uint wwiseId = uint.Parse(reader.GetAttribute("wwiseId")); string gameName = reader.GetAttribute("game"); IGameInstance instance = GameInstance.GetFromString(gameName); StreamingSoundbank bank = new StreamingSoundbank(); bank.Header.WwiseBankId = wwiseId; string xmlFolder = Path.GetDirectoryName(options.Source); while (reader.ReadToFollowing("file")) { uint fileId = uint.Parse(reader.GetAttribute("id")); string audio = reader.GetAttribute("audio"); MemoryStream metadataStream = null; if (reader.ReadToDescendant("metadata")) { AudioMetadata metadata = new AudioMetadata(instance); using (XmlReader metadataReader = reader.ReadSubtree()) { metadataReader.Read(); uint metadataVersion = uint.Parse(metadataReader.GetAttribute("version")); uint personaId = uint.Parse(metadataReader.GetAttribute("personaid")); uint voicelineId = uint.Parse(metadataReader.GetAttribute("voicelineid")); uint wavLengthMs = uint.Parse(metadataReader.GetAttribute("wavlengthms")); metadata.Header.Version = metadataVersion; metadata.Header.PersonaID = personaId; metadata.Header.VoicelineID = voicelineId; metadata.Header.WavLengthMs = wavLengthMs; if (metadataReader.ReadToFollowing("subtitles")) { while (metadataReader.ReadToFollowing("subtitle")) { string languageString = metadataReader.GetAttribute("language"); metadataReader.Read(); string text = metadataReader.ReadContentAsString(); Language language = LanguageUtility.GetLanguageFromCode(languageString); metadata.Subtitles.Add(language, text); } } if (metadataReader.ReadToFollowing("lipsync")) { string lipsyncBase64 = metadataReader.ReadContentAsString(); metadata.LipsyncData = Convert.FromBase64String(lipsyncBase64); } } metadataStream = new MemoryStream(); metadata.Save(metadataStream); } Stream audioStream = File.OpenRead(Path.Combine(xmlFolder, audio)); bank.AddFile(fileId, audioStream, metadataStream); } using (Stream outStream = File.Create(bnkName)) { using (Stream mbnkOutStream = File.Create(mbnkName)) { bank.Save(outStream, mbnkOutStream); } } } } }
public SoundbankEntry(StreamingSoundbank bank) { }
static void Main(string[] args) { Options options = null; try { options = CommandLine.Parse<Options>(); } catch (CommandLineException exception) { Console.WriteLine(exception.ArgumentHelp.Message); Console.WriteLine(); Console.WriteLine(exception.ArgumentHelp.GetHelpText(Console.BufferWidth)); #if DEBUG Console.ReadLine(); #endif return; } IGameInstance instance = GameInstance.GetFromString(options.Game); string ww2ogg = Path.Combine(ExeLocation, "external", "ww2ogg.exe"); string codebooks = null; string codebooksPath = options.Codebooks; if (codebooks == null) { switch (instance.Game) { case GameSteamID.SaintsRowTheThird: codebooks = "packed_codebooks.bin"; break; case GameSteamID.SaintsRowIV: case GameSteamID.SaintsRowGatOutOfHell: codebooks = "packed_codebooks_aoTuV_603.bin"; break; default: throw new NotImplementedException(); } codebooksPath = Path.Combine(ExeLocation, "external", codebooks); } string revorb = Path.Combine(ExeLocation, "external", "revorb.exe"); bool failedToFindConversionRequirements = false; if (options.ConvertAudio) { if (!File.Exists(ww2ogg)) { Console.WriteLine("Could not find ww2ogg.exe at:\n{0}", ww2ogg); failedToFindConversionRequirements = true; } if (!File.Exists(codebooksPath)) { if (codebooks != null) Console.WriteLine("Could not find {0} at:\n{1}", codebooks, codebooksPath); else Console.WriteLine("Could not find your specified codebooks at:\n{1}", codebooks, codebooksPath); failedToFindConversionRequirements = true; } if (!File.Exists(revorb)) { Console.WriteLine("Could not find revorb.exe at:\n{0}", revorb); failedToFindConversionRequirements = true; } if (failedToFindConversionRequirements) { Console.WriteLine("Can't convert audio."); } } using (Stream stream = File.OpenRead(options.Source)) { var bnk = new StreamingSoundbank(stream); string bnkName = Path.GetFileName(options.Source); string folderName = (options.Output != null) ? options.Output : "extracted-" + bnkName; Console.WriteLine("Extracting {0} to {1}.", options.Source, folderName); Directory.CreateDirectory(folderName); if (File.Exists(Path.Combine(folderName, String.Format("{0}.xml", bnkName)))) File.Delete(Path.Combine(folderName, String.Format("{0}.xml", bnkName))); using (Stream xmlStream = File.Create(Path.Combine(folderName, Path.ChangeExtension(bnkName, "xml")))) { XmlWriterSettings settings = new XmlWriterSettings(); settings.Indent = true; settings.IndentChars = "\t"; settings.NewLineChars = "\r\n"; using (XmlWriter writer = XmlWriter.Create(xmlStream, settings)) { writer.WriteStartDocument(); writer.WriteStartElement("soundbank"); writer.WriteAttributeString("game", instance.Game.ToString()); writer.WriteAttributeString("wwiseId", bnk.Header.WwiseBankId.ToString()); //writer.WriteAttributeString() int currentFile = 0; foreach (SoundbankEntry entry in bnk.Files) { writer.WriteStartElement("file"); currentFile++; writer.WriteAttributeString("id", entry.Info.FileId.ToString()); Console.Write("[{0}/{1}] Extracting audio... ", currentFile, bnk.Files.Count); string audioFilename = String.Format("{0}_{1:D5}.wem", bnkName, currentFile); using (Stream outputStream = File.Create(Path.Combine(folderName, audioFilename))) { using (Stream inputStream = entry.GetAudioStream()) { inputStream.CopyTo(outputStream); } outputStream.Flush(); } Console.WriteLine("done."); writer.WriteAttributeString("audio", audioFilename); if (entry.Info.MetadataLength != 0) { Console.Write("[{0}/{1}] Extracting metadata... ", currentFile, bnk.Files.Count); using (Stream metadataStream = entry.GetMetadataStream()) { writer.WriteStartElement("metadata"); AudioMetadata metadata = new AudioMetadata(metadataStream, instance); writer.WriteAttributeString("version", metadata.Header.Version.ToString()); writer.WriteAttributeString("personaid", metadata.Header.PersonaID.ToString()); writer.WriteAttributeString("voicelineid", metadata.Header.VoicelineID.ToString()); writer.WriteAttributeString("wavlengthms", metadata.Header.WavLengthMs.ToString()); if (metadata.LipsyncData != null && metadata.LipsyncData.Length > 0) { writer.WriteStartElement("lipsync"); writer.WriteString(Convert.ToBase64String(metadata.LipsyncData)); writer.WriteEndElement(); // lipsync } if (metadata.Header.SubtitleSize > 0) { writer.WriteStartElement("subtitles"); writer.WriteAttributeString("version", metadata.SubtitleHeader.Version.ToString()); foreach (var subtitle in metadata.Subtitles) { Language language = subtitle.Key; string text = subtitle.Value; writer.WriteStartElement("subtitle"); writer.WriteAttributeString("language", language.ToString()); writer.WriteString(text); writer.WriteEndElement(); // subtitle } writer.WriteEndElement(); // subtitles } writer.WriteEndElement(); // metadata } Console.WriteLine("done."); } writer.WriteEndElement(); // file } writer.WriteEndElement(); // soundbank writer.WriteEndDocument(); } } if (options.ConvertAudio) { if (failedToFindConversionRequirements) { Console.WriteLine(); Console.WriteLine("Unable to convert extracted audio due to missing required files."); } else { Console.WriteLine(); Console.WriteLine("Converting extracted audio..."); for (int i = 1; i <= bnk.Files.Count; i++) { Console.Write("[{0}/{1}] Converting audio... ", i, bnk.Files.Count); string oggFilename = String.Format("{0}_{1:D5}.ogg", bnkName, i); string oggPath = Path.Combine(folderName, oggFilename); string audioFilename = String.Format("{0}_{1:D5}.wem", bnkName, i); string audioPath = Path.Combine(folderName, audioFilename); ProcessStartInfo ww2oggPsi = new ProcessStartInfo(ww2ogg, String.Format(@"--pcb ""{0}"" -o ""{1}"" ""{2}""", codebooksPath, oggPath, audioPath)); ww2oggPsi.WindowStyle = ProcessWindowStyle.Hidden; ww2oggPsi.CreateNoWindow = true; Process ww2oggP = Process.Start(ww2oggPsi); ww2oggP.WaitForExit(); Console.Write("revorb... "); ProcessStartInfo revorbPsi = new ProcessStartInfo(revorb, String.Format(@"""{0}""", oggPath)); revorbPsi.WindowStyle = ProcessWindowStyle.Hidden; revorbPsi.CreateNoWindow = true; Process revorbP = Process.Start(revorbPsi); revorbP.WaitForExit(); Console.WriteLine("done."); } } } Console.WriteLine(); Console.WriteLine("Done."); #if DEBUG Console.ReadLine(); #endif } }
public SoundbankEntry(StreamingSoundbank bank, SoundbankEntryInfo info) { Soundbank = bank; Info = info; }