using System; using System.Collections.Generic; using System.IO; //using System.Runtime.Remoting.Metadata.W3cXsd2001; namespace Oni.Sound { internal class WavFile { #region Private data private const int fcc_RIFF = 0x46464952; private const int fcc_WAVE = 0x45564157; private const int fcc_fmt = 0x20746d66; private const int fcc_fact = 0x74636166; private const int fcc_data = 0x61746164; private WavFormat format; private int channelCount; private int sampleRate; private int averageBytesPerSecond; private int blockAlign; private int bitsPerSample; private int sampleCount; private byte[] extraData; private byte[] soundData; #endregion public static WavFile FromFile(string filePath) { using (var reader = new BinaryReader(filePath)) { if (reader.ReadInt32() != fcc_RIFF) throw new InvalidDataException("Not a WAV file"); int size = reader.ReadInt32(); if (reader.ReadInt32() != fcc_WAVE) throw new InvalidDataException("Not a WAV file"); var header = new WavFile() { sampleCount = 0 }; for (int chunkType, chunkSize, chunkStart; reader.Position < size; reader.Position = chunkStart + chunkSize) { chunkType = reader.ReadInt32(); chunkSize = reader.ReadInt32(); chunkStart = reader.Position; if (chunkType == fcc_fmt) header.ReadFormatChunk(reader, chunkSize); if (chunkType == fcc_fact) header.ReadFactChunk(reader, chunkSize); if (chunkType == fcc_data) header.ReadDataChunk(reader, chunkSize); } header.ValidateSampleCount(); return header; } } private void ReadFormatChunk(BinaryReader reader, int chunkSize) { format = (WavFormat)reader.ReadInt16(); channelCount = reader.ReadInt16(); sampleRate = reader.ReadInt32(); averageBytesPerSecond = reader.ReadInt32(); blockAlign = reader.ReadInt16(); bitsPerSample = reader.ReadInt16(); if (chunkSize > 16) extraData = reader.ReadBytes(reader.ReadInt16()); else extraData = new byte[0]; } private void ReadFactChunk(BinaryReader reader, int chunkSize) { sampleCount = reader.ReadInt32(); } private void ReadDataChunk(BinaryReader reader, int chunkSize) { soundData = reader.ReadBytes(chunkSize); } private void ValidateSampleCount() // TODO: ACTUAL VALIDATION/CORRECTION { int sampleCountFromData = 0; int wholeBlocks = soundData.Length / blockAlign; if(sampleCount == 0) // not explicitly set (no fact chunk present) { Console.WriteLine("The imported WAV file has no FACT chunk."); } else // TODO: calculate sampleCountFromData, compare with sampleCount { } } public WavFormat Format => format; public int ChannelCount => channelCount; public int SampleRate => sampleRate; public int AverageBytesPerSecond => averageBytesPerSecond; public int BlockAlign => blockAlign; public int BitsPerSample => bitsPerSample; public byte[] ExtraData => extraData; public byte[] SoundData => soundData; } }