예제 #1
0
 public static void Copy(EndianReader input, EndianWriter output)
 {
     // http://stackoverflow.com/questions/230128/best-way-to-copy-between-two-stream-instances-c-sharp
     const int BufferSize = 0x1000;
     byte[] buffer = new byte[BufferSize];
     int read;
     while ((read = input.ReadBlock(buffer, 0, BufferSize)) > 0)
         output.WriteBlock(buffer, 0, read);
 }
예제 #2
0
 public static void Copy(EndianReader input, EndianWriter output, int size)
 {
     const int BufferSize = 0x1000;
     byte[] buffer = new byte[BufferSize];
     while (size > 0)
     {
         int read = input.ReadBlock(buffer, 0, Math.Min(BufferSize, size));
         output.WriteBlock(buffer, 0, read);
         size -= BufferSize;
     }
 }
        /// <summary>
        /// Extracts an xWMA sound and converts it to WAV.
        /// </summary>
        /// <param name="reader">The stream to read from.</param>
        /// <param name="offset">The offset of the data to extract.</param>
        /// <param name="rifx">The RIFX data for the sound.</param>
        /// <param name="outPath">The path of the file to save to.</param>
        public static void ExtractXWMAToWAV(EndianReader reader, int offset, RIFX rifx, string outPath)
        {
            // Create a temporary file to write an XWMA to
            string tempFile = Path.GetTempFileName();

            try
            {
                using (EndianWriter output = new EndianWriter(File.OpenWrite(tempFile), EndianFormat.BigEndian))
                {
                    // Generate a little-endian XWMA header
                    // TODO: move this into a class?
                    output.Write(0x52494646); // 'RIFF'

                    // Recompute the file size because the one Wwise gives us is trash
                    // fileSize = header size (always 0x2C) + dpds data size + data header size (always 0x8) + data size
                    int fileSize = 0x2C + rifx.SeekOffsets.Length * 0x4 + 0x8 + rifx.DataSize;
                    output.EndianType = EndianFormat.LittleEndian;
                    output.Write(fileSize);

                    output.EndianType = EndianFormat.BigEndian;
                    output.Write(RIFFFormat.XWMA);

                    // Generate the 'fmt ' chunk
                    output.Write(0x666D7420); // 'fmt '
                    output.EndianType = EndianFormat.LittleEndian;
                    output.Write(0x18); // Chunk size
                    output.Write(rifx.Codec);
                    output.Write(rifx.ChannelCount);
                    output.Write(rifx.SampleRate);
                    output.Write(rifx.BytesPerSecond);
                    output.Write(rifx.BlockAlign);
                    output.Write(rifx.BitsPerSample);

                    // Write the extradata
                    // Bytes 4 and 5 have to be flipped because they make up an int16
                    // TODO: add error checking to make sure the extradata is the correct size (0x6)
                    output.Write((short)0x6);
                    output.WriteBlock(rifx.ExtraData, 0, 4);
                    output.Write(rifx.ExtraData[5]);
                    output.Write(rifx.ExtraData[4]);

                    // Generate the 'dpds' chunk
                    // It's really just the 'seek' chunk from the original data but renamed
                    output.EndianType = EndianFormat.BigEndian;
                    output.Write(0x64706473); // 'dpds'

                    output.EndianType = EndianFormat.LittleEndian;
                    output.Write(rifx.SeekOffsets.Length * 4); // One uint32 per offset
                    foreach (int seek in rifx.SeekOffsets)
                        output.Write(seek);

                    // 'data' chunk
                    output.EndianType = EndianFormat.BigEndian;
                    output.Write(0x64617461); // 'data'
                    output.EndianType = EndianFormat.LittleEndian;
                    output.Write(rifx.DataSize);

                    // Copy the data chunk contents from the original RIFX
                    reader.SeekTo(offset + rifx.DataOffset);
                    StreamUtil.Copy(reader, output, rifx.DataSize);
                }

                // Convert it with xWMAEncode
                RunProgramSilently("Helpers/xWMAEncode.exe", "\"" + tempFile + "\" \"" + outPath + "\"", Directory.GetCurrentDirectory());
            }
            finally
            {
                // Delete the temporary XWMA file
                if (File.Exists(tempFile))
                    File.Delete(tempFile);
            }
        }