private static void WriteWAVFile(BlamSound blamSound) { using (EndianWriter output = new EndianWriter(new FileStream(WAVFile, FileMode.Create, FileAccess.Write, FileShare.None), EndianFormat.BigEndian)) { WAVFile WAVfile = new WAVFile(blamSound); WAVfile.Write(output); } }
public static string ConvertXMAPermutation(byte[] buffer, int channelCount, int sampleRate, bool loopingSound, bool useCache, string permutationName) { if (!File.Exists(@"Tools\ffmpeg.exe")) { Console.WriteLine("Missing tools, please install all the required tools before porting sounds."); return(null); } var gui = Guid.NewGuid(); var audioFile = permutationName; var tempXMA = $"{audioFile}.xma"; var tempWAV = $"{audioFile}_temp.wav"; var fixedWAV = $"{audioFile}_truncated.wav"; var tempMP3 = $"{audioFile}_temp.mp3"; var resultWAV = $"{audioFile}.wav"; var resultMP3 = $"{audioFile}.mp3"; CLEAN_FILES: try { if (File.Exists(tempXMA)) { File.Delete(tempXMA); } if (File.Exists(tempWAV)) { File.Delete(tempWAV); } if (File.Exists(fixedWAV)) { File.Delete(fixedWAV); } if (File.Exists(resultWAV)) { File.Delete(resultWAV); } if (File.Exists(resultMP3)) { File.Delete(resultMP3); } if (File.Exists(tempMP3)) { File.Delete(tempMP3); } } catch (Exception e) { Console.WriteLine(e.Message); goto CLEAN_FILES; } using (EndianWriter output = new EndianWriter(new FileStream(tempXMA, FileMode.Create, FileAccess.Write, FileShare.None), EndianFormat.BigEndian)) { XMAFile XMAfile = new XMAFile(buffer, channelCount, sampleRate); XMAfile.Write(output); } if (!ConvertXMAToWAV(tempXMA, tempWAV)) { return(null); } // Convert to MP3 and remove header if (loopingSound && channelCount <= 2) { if (!ConvertWAVToMP3Looping(tempWAV, tempMP3)) { return(null); } } else { // truncate file byte[] originalWAVdata = File.ReadAllBytes(tempWAV); byte[] truncatedWAVdata = TruncateWAVFile(originalWAVdata, sampleRate, channelCount, 0x2C); using (EndianWriter writer = new EndianWriter(new FileStream(fixedWAV, FileMode.Create, FileAccess.Write, FileShare.None), EndianFormat.BigEndian)) { WAVFile WAVfile = new WAVFile(truncatedWAVdata, channelCount, sampleRate); WAVfile.Write(writer); } // add code to handle looping sounds with more than 2 channels here. Mp3Loop does not handle that kind of file. if (!ConvertWAVToMP3(fixedWAV, tempMP3)) { return(null); } } int size = (int)(new FileInfo(tempMP3).Length - 0x2D); byte[] MP3stream = File.ReadAllBytes(tempMP3); using (var output = new FileStream(resultMP3, FileMode.Create, FileAccess.Write, FileShare.None)) output.Write(MP3stream, 0x2D, size); CLEAN_FILES2: try { if (File.Exists(tempXMA)) { File.Delete(tempXMA); } if (File.Exists(tempWAV)) { File.Delete(tempWAV); } if (File.Exists(fixedWAV)) { File.Delete(fixedWAV); } if (File.Exists(resultWAV)) { File.Delete(resultWAV); } if (File.Exists(tempMP3)) { File.Delete(tempMP3); } } catch (Exception e) { Console.WriteLine(e.Message); goto CLEAN_FILES2; } return(resultMP3); }
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); }
public override object Execute(List <string> args) { if (args.Count != 1) { return(false); } var outDirectory = args[0]; 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 resource = Definition.Resource; var resourceContext = new ResourceSerializationContext(CacheContext, resource); var resourceDefinition = CacheContext.Deserializer.Deserialize <SoundResourceDefinition>(resourceContext); if (resourceDefinition.Data == null) { Console.WriteLine("Invalid sound definition"); return(false); } var dataReference = resourceDefinition.Data; byte[] soundData = new byte[dataReference.Size]; var resourceDataStream = new MemoryStream(soundData); CacheContext.ExtractResource(resource, resourceDataStream); 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; } } } } Console.WriteLine("Done!"); return(true); }