/* Attempts to read the riff chunk from a given * stream of bytes, returns the ChunkSize if successful */ //TODO add custom exception public static uint ReadRiffChunk(List <byte> lData) { if (lData.Count() < RiffChunkSize) { throw new Exception("Not enough bytes available to read the Riff Chunk"); } var data = lData.Take(RiffChunkSize).ToArray(); // Chunk Id should contain the ascii string "RIFF" in Big Endian format if (EndianHelper.ToUInt32BE(data, 0) != 0x52494646) { throw new Exception("Unable to read WAVE file"); } // Read In Size of Chunk in Little Endian Format uint chunkSize = EndianHelper.ToUInt32LE(data, 4); // Format should contain the ascii string "WAVE" in Big Endian format if (EndianHelper.ToUInt32BE(data, 8) != 0x57415645) { throw new Exception("Unable to read WAVE file"); } return(chunkSize); }
public static List <short> ReadDataChunk(List <byte> lData) { var data = lData.ToArray(); // Could be a "List" Chunk prepending if (EndianHelper.ToUInt32BE(data, 0) == 0x4C495354) { data = data.Skip(78).ToArray(); lData.RemoveRange(0, 78); } // Chunk ID should contain the letters "data" in Big Endian format if (EndianHelper.ToUInt32BE(data, 0) != 0x64617461) { throw new Exception("Unable to read Data Chunk, incorrect ID"); } // Number of bytes containing pure sample data uint dataSize = EndianHelper.ToUInt32LE(data, 4); /* Check data size is a multiple of 2, as samples are 16bits each. Also * check there's enough bytes left in the buffer to extract the sample data */ if ((dataSize & 0x1) != 0x0 || dataSize > int.MaxValue || dataSize > lData.Count() - 8) { Debug.WriteLine((dataSize & 0x1) + " " + dataSize + " " + lData.Count()); throw new Exception("Unable to read Data Chunk"); } var sampleData = new List <short>(); lData.RemoveRange(0, 8); for (int i = 0; i < dataSize; i += 2) { sampleData.Add(BitConverter.IsLittleEndian ? (short)(lData[i] | lData[i + 1] << 8) : (short)(lData[i + 1] | lData[i] << 8)); } return(sampleData); }
public FormatChunk(List <byte> lData) { if (lData.Count() < FormatChunkSize) { throw new Exception("Not enough bytes for reading the Format Chunk"); } var data = lData.Take(FormatChunkSize).ToArray(); // SubChunk ID should contain the ascii string "fmt " in Big Endian format if (EndianHelper.ToUInt32BE(data, 0) != 0x666D7420) { throw new Exception("Unable to read Format Chunk"); } /* Check SubChunk Size is 16 for PCM. currently only supporting PCM at the moment, * so fail on any other sizes */ if (EndianHelper.ToUInt32LE(data, 4) != 0x10) { throw new Exception("Non PCM format non-supported"); } /* Check Audio Format is for PCM (value of 1). Current only supporting PCM at the moment, * so fail on any other values */ if (EndianHelper.ToUInt16LE(data, 8) != 0x1) { throw new Exception("Non PCM format non-supported"); } // Check if Mono(1) or Stereo(2) number of channels ushort nChannels = EndianHelper.ToUInt16LE(data, 10); if (nChannels != 1 && nChannels != 2) { throw new Exception("Unable to read Format Chunk"); } NChannels = nChannels == 1 ? NumChannels.Mono : NumChannels.Stereo; // Get Sample Rate SampleRate = EndianHelper.ToUInt32LE(data, 12); /* Get Byte Rate, in PCM this is redundant as it's equal to * SampleRate * NumChannels * BitsPerSample/8. */ ByteRate = EndianHelper.ToUInt32LE(data, 16); /* Get Block Align, again in PCM this is redundant as it's equal to * NumChannels * BitsPerSample/8 */ BlockAlign = EndianHelper.ToUInt16LE(data, 20); // Get Bits Per Sample, in PCM should be rounded up to the next 8 bits ushort bitsPerSample = EndianHelper.ToUInt16LE(data, 22); bitsPerSample += (ushort)(bitsPerSample % 8); BitsPerSample = bitsPerSample; /* For validity check ByteRate = SampleRate * nChannels * BitsPerSample/8*/ if (ByteRate != SampleRate * nChannels * (BitsPerSample / 8)) { throw new Exception("Unable to read Format Chunk"); } /* For validity check BlockAlign = nChannels * BitsPerSample/8*/ if (BlockAlign != nChannels * (BitsPerSample / 8)) { throw new Exception("Unable to read Format Chunk"); } }