public void ExtractXMA(string directory) { if (BlamSoundGestalt == null) { using (var stream = Cache.OpenCacheRead()) BlamSoundGestalt = PortingContextFactory.LoadSoundGestalt(Cache, stream); } var resourceDefinition = Cache.ResourceCache.GetSoundResourceDefinition(Sound.Resource); var xmaFileSize = BlamSoundGestalt.GetFileSize(Sound.SoundReference.PitchRangeIndex, Sound.SoundReference.PitchRangeCount); if (xmaFileSize < 0) { return; } var xmaData = resourceDefinition.Data.Data; if (xmaData == null) { Console.WriteLine($"ERROR: Failed to find sound data!"); return; } var parts = Tag.Name.Split('\\'); string baseName = parts[parts.Length - 1]; for (int pitchRangeIndex = Sound.SoundReference.PitchRangeIndex; pitchRangeIndex < Sound.SoundReference.PitchRangeIndex + Sound.SoundReference.PitchRangeCount; pitchRangeIndex++) { var relativePitchRangeIndex = pitchRangeIndex - Sound.SoundReference.PitchRangeIndex; var permutationCount = BlamSoundGestalt.GetPermutationCount(pitchRangeIndex); for (int i = 0; i < permutationCount; i++) { BlamSound blamSound = SoundConverter.GetXMA(Cache, BlamSoundGestalt, Sound, relativePitchRangeIndex, i, xmaData); string permutationName = $"{baseName}_{relativePitchRangeIndex}_{i}"; var fileName = $"{directory}\\{permutationName}.xma"; using (EndianWriter output = new EndianWriter(new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None), EndianFormat.BigEndian)) { XMAFile XMAfile = new XMAFile(blamSound); XMAfile.Write(output); } } } }
public override object Execute(List <string> args) { string outDirectory = ""; if (args.Count == 1) { outDirectory = args[0]; } else if (args.Count == 0) { outDirectory = "Sounds"; } else { return(false); } if (!Directory.Exists(outDirectory)) { Console.Write("Destination directory does not exist. Create it? [y/n] "); var answer = Console.ReadLine().ToLower(); if (answer.Length == 0 || !(answer.StartsWith("y") || answer.StartsWith("n"))) { return(false); } if (answer.StartsWith("y")) { Directory.CreateDirectory(outDirectory); } else { return(false); } } var resourceReference = Definition.Resource; var resourceDefinition = Cache.ResourceCache.GetSoundResourceDefinition(resourceReference); if (resourceDefinition.Data == null) { Console.WriteLine("Invalid sound definition"); return(false); } var dataReference = resourceDefinition.Data; byte[] soundData = dataReference.Data; if (Cache is GameCacheHaloOnlineBase) { for (int i = 0; i < Definition.PitchRanges.Count; i++) { var pitchRange = Definition.PitchRanges[i]; for (int j = 0; j < pitchRange.Permutations.Count; j++) { var permutation = pitchRange.Permutations[j]; var filename = Tag.Index.ToString("X8") + "_" + i.ToString() + "_" + j.ToString(); byte[] permutationData = new byte[permutation.PermutationChunks[0].EncodedSize & 0x3FFFFFF]; Array.Copy(soundData, permutation.PermutationChunks[0].Offset, permutationData, 0, permutationData.Length); switch (Definition.PlatformCodec.Compression) { case Compression.PCM: filename += ".wav"; break; case Compression.MP3: filename += ".mp3"; break; case Compression.FSB4: filename += ".fsb"; break; } var outPath = Path.Combine(outDirectory, filename); using (EndianWriter writer = new EndianWriter(new FileStream(outPath, FileMode.Create, FileAccess.Write, FileShare.None), EndianFormat.BigEndian)) { var channelCount = Encoding.GetChannelCount(Definition.PlatformCodec.Encoding); var sampleRate = Definition.SampleRate.GetSampleRateHz(); switch (Definition.PlatformCodec.Compression) { case Compression.PCM: WAVFile WAVfile = new WAVFile(permutationData, channelCount, sampleRate); WAVfile.Write(writer); break; case Compression.MP3: case Compression.FSB4: writer.Write(permutationData); break; } } } } } else if (Cache.GetType() == typeof(GameCacheGen3)) { if (BlamSoundGestalt == null) { using (var stream = Cache.OpenCacheRead()) BlamSoundGestalt = PortingContextFactory.LoadSoundGestalt(Cache, stream); } for (int pitchRangeIndex = Definition.SoundReference.PitchRangeIndex; pitchRangeIndex < Definition.SoundReference.PitchRangeIndex + Definition.SoundReference.PitchRangeCount; pitchRangeIndex++) { var relativePitchRangeIndex = pitchRangeIndex - Definition.SoundReference.PitchRangeIndex; var permutationCount = BlamSoundGestalt.GetPermutationCount(pitchRangeIndex); for (int i = 0; i < permutationCount; i++) { string permutationName = $"{Tag.Name.Replace('\\', '_')}_{relativePitchRangeIndex}_{i}.mp3"; var outPath = Path.Combine(outDirectory, permutationName); BlamSound blamSound = SoundConverter.ConvertGen3Sound(Cache, BlamSoundGestalt, Definition, relativePitchRangeIndex, i, soundData); using (EndianWriter output = new EndianWriter(new FileStream(outPath, FileMode.Create, FileAccess.Write, FileShare.None), EndianFormat.BigEndian)) { output.WriteBlock(blamSound.Data); } } } } Console.WriteLine("Done!"); return(true); }