| 1 | using System; | 
 
 
 
 
 | 2 | using System.Collections.Generic; | 
 
 
 
 
 | 3 | using System.IO; | 
 
 
 
 
 | 4 |  | 
 
 
 
 
 | 5 | namespace Oni.Sound | 
 
 
 
 
 | 6 | { | 
 
 
 
 
 | 7 | internal class WavFile | 
 
 
 
 
 | 8 | { | 
 
 
 
 
 | 9 | #region Private data | 
 
 
 
 
 | 10 | private const int fcc_RIFF = 0x46464952; | 
 
 
 
 
 | 11 | private const int fcc_WAVE = 0x45564157; | 
 
 
 
 
 | 12 | private const int fcc_fmt = 0x20746d66; | 
 
 
 
 
 | 13 | private const int fcc_data = 0x61746164; | 
 
 
 
 
 | 14 |  | 
 
 
 
 
 | 15 | private WavFormat format; | 
 
 
 
 
 | 16 | private int channelCount; | 
 
 
 
 
 | 17 | private int sampleRate; | 
 
 
 
 
 | 18 | private int averageBytesPerSecond; | 
 
 
 
 
 | 19 | private int blockAlign; | 
 
 
 
 
 | 20 | private int bitsPerSample; | 
 
 
 
 
 | 21 | private byte[] extraData; | 
 
 
 
 
 | 22 | private byte[] soundData; | 
 
 
 
 
 | 23 | #endregion | 
 
 
 
 
 | 24 |  | 
 
 
 
 
 | 25 | public static WavFile FromFile(string filePath) | 
 
 
 
 
 | 26 | { | 
 
 
 
 
 | 27 | using (var reader = new BinaryReader(filePath)) | 
 
 
 
 
 | 28 | { | 
 
 
 
 
 | 29 | if (reader.ReadInt32() != fcc_RIFF) | 
 
 
 
 
 | 30 | throw new InvalidDataException("Not a WAV file"); | 
 
 
 
 
 | 31 |  | 
 
 
 
 
 | 32 | int size = reader.ReadInt32(); | 
 
 
 
 
 | 33 |  | 
 
 
 
 
 | 34 | if (reader.ReadInt32() != fcc_WAVE) | 
 
 
 
 
 | 35 | throw new InvalidDataException("Not a WAV file"); | 
 
 
 
 
 | 36 |  | 
 
 
 
 
 | 37 | var header = new WavFile(); | 
 
 
 
 
 | 38 |  | 
 
 
 
 
 | 39 | for (int chunkType, chunkSize, chunkStart; reader.Position < size; reader.Position = chunkStart + chunkSize) | 
 
 
 
 
 | 40 | { | 
 
 
 
 
 | 41 | chunkType = reader.ReadInt32(); | 
 
 
 
 
 | 42 | chunkSize = reader.ReadInt32(); | 
 
 
 
 
 | 43 | chunkStart = reader.Position; | 
 
 
 
 
 | 44 |  | 
 
 
 
 
 | 45 | if (chunkType == fcc_fmt) | 
 
 
 
 
 | 46 | header.ReadFormatChunk(reader, chunkSize); | 
 
 
 
 
 | 47 | else if (chunkType == fcc_data) | 
 
 
 
 
 | 48 | header.ReadDataChunk(reader, chunkSize); | 
 
 
 
 
 | 49 | } | 
 
 
 
 
 | 50 |  | 
 
 
 
 
 | 51 | return header; | 
 
 
 
 
 | 52 | } | 
 
 
 
 
 | 53 | } | 
 
 
 
 
 | 54 |  | 
 
 
 
 
 | 55 | private void ReadFormatChunk(BinaryReader reader, int chunkSize) | 
 
 
 
 
 | 56 | { | 
 
 
 
 
 | 57 | format = (WavFormat)reader.ReadInt16(); | 
 
 
 
 
 | 58 | channelCount = reader.ReadInt16(); | 
 
 
 
 
 | 59 | sampleRate = reader.ReadInt32(); | 
 
 
 
 
 | 60 | averageBytesPerSecond = reader.ReadInt32(); | 
 
 
 
 
 | 61 | blockAlign = reader.ReadInt16(); | 
 
 
 
 
 | 62 | bitsPerSample = reader.ReadInt16(); | 
 
 
 
 
 | 63 |  | 
 
 
 
 
 | 64 | if (chunkSize > 16) | 
 
 
 
 
 | 65 | extraData = reader.ReadBytes(reader.ReadInt16()); | 
 
 
 
 
 | 66 | else | 
 
 
 
 
 | 67 | extraData = new byte[0]; | 
 
 
 
 
 | 68 | } | 
 
 
 
 
 | 69 |  | 
 
 
 
 
 | 70 | private void ReadDataChunk(BinaryReader reader, int chunkSize) | 
 
 
 
 
 | 71 | { | 
 
 
 
 
 | 72 | soundData = reader.ReadBytes(chunkSize); | 
 
 
 
 
 | 73 | } | 
 
 
 
 
 | 74 |  | 
 
 
 
 
 | 75 | public WavFormat Format => format; | 
 
 
 
 
 | 76 | public int ChannelCount => channelCount; | 
 
 
 
 
 | 77 | public int SampleRate => sampleRate; | 
 
 
 
 
 | 78 | public int AverageBytesPerSecond => averageBytesPerSecond; | 
 
 
 
 
 | 79 | public int BlockAlign => blockAlign; | 
 
 
 
 
 | 80 | public int BitsPerSample => bitsPerSample; | 
 
 
 
 
 | 81 | public byte[] ExtraData => extraData; | 
 
 
 
 
 | 82 | public byte[] SoundData => soundData; | 
 
 
 
 
 | 83 | } | 
 
 
 
 
 | 84 | } |