/// <summary> /// Converts a RIFF WAVE bitstream with header to raw samples. /// </summary> public RIFFWaveDecoder(BinaryReader reader) { // RIFF header if (reader.ReadInt32() != RIFFWave.syncWord1) { throw new SyncException(); } stream = reader.BaseStream; stream.Position += 4; // File length // Format header if (reader.ReadInt64() != RIFFWave.syncWord2) { throw new SyncException(); } stream.Position += 4; // Format header length short sampleFormat = reader.ReadInt16(); // 1 = int, 3 = float, -2 = WAVE EX channelCount = reader.ReadInt16(); sampleRate = reader.ReadInt32(); stream.Position += 4; // Bytes/sec stream.Position += 2; // Block size in bytes short bitDepth = reader.ReadInt16(); if (sampleFormat == -2) { // Extension size (22) - 2 bytes, valid bits per sample - 2 bytes, channel mask - 4 bytes stream.Position += 8; sampleFormat = reader.ReadInt16(); stream.Position += 15; // Skip the rest of the sub format GUID } if (sampleFormat == 1) { Bits = bitDepth switch { 8 => BitDepth.Int8, 16 => BitDepth.Int16, 24 => BitDepth.Int24, _ => throw new IOException($"Unsupported bit depth for signed little endian integer: {bitDepth}.") }; } else if (sampleFormat == 3 && bitDepth == 32) { Bits = BitDepth.Float32; } else { throw new IOException($"Unsupported bit depth ({bitDepth}) for sample format {sampleFormat}."); } // Data header int header = 0; do { header = (header << 8) | reader.ReadByte(); }while (header != RIFFWave.syncWord3BE && stream.Position < stream.Length); length = reader.ReadUInt32() * 8L / (long)Bits / ChannelCount; dataStart = stream.Position; this.reader = BlockBuffer <byte> .Create(reader, FormatConsts.blockSize); }