/// <summary> /// Reads the header part of a WAV file from a stream /// </summary> /// <param name="stream">The stream, positioned at the start of audio data</param> /// <param name="format">The format found</param> /// <param name="dataChunkPosition">The position of the data chunk</param> /// <param name="dataChunkLength">The length of the data chunk</param> /// <param name="chunks">Additional chunks found</param> public static void ReadWaveHeader(Stream stream, out WaveFormat format, out long dataChunkPosition, out int dataChunkLength, List <RiffChunk> chunks) { dataChunkPosition = -1; format = null; var br = new BinaryReader(stream); if (br.ReadInt32() != WaveInterop.mmioStringToFOURCC("RIFF", 0)) { throw new FormatException("Not a WAVE file - no RIFF header"); } uint fileSize = br.ReadUInt32(); // read the file size (minus 8 bytes) if (br.ReadInt32() != WaveInterop.mmioStringToFOURCC("WAVE", 0)) { throw new FormatException("Not a WAVE file - no WAVE header"); } int dataChunkID = WaveInterop.mmioStringToFOURCC("data", 0); int formatChunkId = WaveInterop.mmioStringToFOURCC("fmt ", 0); dataChunkLength = 0; // sometimes a file has more data than is specified after the RIFF header long stopPosition = Math.Min(fileSize + 8, stream.Length); // this -8 is so we can be sure that there are at least 8 bytes for a chunk id and length while (stream.Position <= stopPosition - 8) { int chunkIdentifier = br.ReadInt32(); int chunkLength = br.ReadInt32(); if (chunkIdentifier == dataChunkID) { dataChunkPosition = stream.Position; dataChunkLength = chunkLength; stream.Position += chunkLength; } else if (chunkIdentifier == formatChunkId) { format = WaveFormat.FromFormatChunk(br, chunkLength); } else { if (chunks != null) { chunks.Add(new RiffChunk(chunkIdentifier, chunkLength, stream.Position)); } stream.Position += chunkLength; } } if (format == null) { throw new FormatException("Invalid WAV file - No fmt chunk found"); } if (dataChunkPosition == -1) { throw new FormatException("Invalid WAV file - No data chunk found"); } }
public WaveFormat ReadWaveHeader(Stream stream) { this.dataChunkPosition = -1; this.riffChunks = new List <RiffChunk>(); this.dataChunkLength = 0; var br = new BinaryReader(stream); ReadRiffHeader(br); this.riffSize = br.ReadUInt32(); // read the file size (minus 8 bytes) if (br.ReadInt32() != ChunkIdentifier.ChunkIdentifierToInt32("WAVE")) { throw new FormatException("Not a WAVE file - no WAVE header"); } if (isRf64) { ReadDs64Chunk(br); } long length = stream.Length; int dataChunkId = ChunkIdentifier.ChunkIdentifierToInt32("data"); int formatChunkId = ChunkIdentifier.ChunkIdentifierToInt32("fmt "); // sometimes a file has more data than is specified after the RIFF header long stopPosition = Math.Min(riffSize + 8, length); // this -8 is so we can be sure that there are at least 8 bytes for a chunk id and length while (stream.Position <= stopPosition - 8) { Int32 chunkIdentifier = br.ReadInt32(); var chunkLength = br.ReadUInt32(); if (chunkIdentifier == dataChunkId) { dataChunkPosition = stream.Position; if (!isRf64) // we already know the dataChunkLength if this is an RF64 file { dataChunkLength = chunkLength; } stream.Position += chunkLength; } else if (chunkIdentifier == formatChunkId) { if (chunkLength > Int32.MaxValue) { throw new InvalidDataException(string.Format("Format chunk length must be between 0 and {0}.", Int32.MaxValue)); } return(WaveFormat.FromFormatChunk(br, (int)chunkLength)); } else { // check for invalid chunk length if (chunkLength > length - stream.Position) { if (strictMode) { Debug.Assert(false, String.Format("Invalid chunk length {0}, pos: {1}. length: {2}", chunkLength, stream.Position, length)); } // an exception will be thrown further down if we haven't got a format and data chunk yet, // otherwise we will tolerate this file despite it having corrupt data at the end break; } /*if (storeAllChunks) * { * if (chunkLength > Int32.MaxValue) * throw new InvalidDataException(string.Format("RiffChunk chunk length must be between 0 and {0}.", Int32.MaxValue)); * riffChunks.Add(GetRiffChunk(stream, chunkIdentifier, (int)chunkLength)); * }*/ stream.Position += chunkLength; } } throw new FormatException("Invalid WAV file - No fmt chunk found"); }
private WaveFormat ReadMicrosoftAdPcmWaveFormat(SscfWaveHeader waveHeader) { BinaryReader br = new BinaryReader(_input); return(WaveFormat.FromFormatChunk(br, waveHeader.FormatHeaderLength)); }
public void ReadWaveHeader(Stream stream) { this.dataChunkPosition = -1; this.waveFormat = null; this.riffChunks = new List <RiffChunk>(); this.dataChunkLength = 0; var br = new BinaryReader(stream); ReadRiffHeader(br); this.riffSize = br.ReadUInt32(); // read the file size (minus 8 bytes) if (br.ReadInt32() != ChunkIdentifier.ChunkIdentifierToInt32("WAVE")) { throw new FormatException("Not a WAVE file - no WAVE header"); } if (isRf64) { ReadDs64Chunk(br); } int dataChunkId = ChunkIdentifier.ChunkIdentifierToInt32("data"); int formatChunkId = ChunkIdentifier.ChunkIdentifierToInt32("fmt "); // sometimes a file has more data than is specified after the RIFF header long stopPosition = Math.Min(riffSize + 8, stream.Length); // this -8 is so we can be sure that there are at least 8 bytes for a chunk id and length while (stream.Position <= stopPosition - 8) { Int32 chunkIdentifier = br.ReadInt32(); var chunkLength = br.ReadUInt32(); if (chunkIdentifier == dataChunkId) { dataChunkPosition = stream.Position; if (!isRf64) // we already know the dataChunkLength if this is an RF64 file { dataChunkLength = chunkLength; } stream.Position += chunkLength; } else if (chunkIdentifier == formatChunkId) { if (chunkLength > Int32.MaxValue) { throw new InvalidDataException(string.Format("Format chunk length must be between 0 and {0}.", Int32.MaxValue)); } waveFormat = WaveFormat.FromFormatChunk(br, (int)chunkLength); } else { // check for invalid chunk length if (chunkLength > stream.Length - stream.Position) { if (strictMode) { Debug.Assert(false, String.Format("Invalid chunk length {0}, pos: {1}. length: {2}", chunkLength, stream.Position, stream.Length)); } // an exception will be thrown further down if we haven't got a format and data chunk yet, // otherwise we will tolerate this file despite it having corrupt data at the end break; } if (storeAllChunks) { if (chunkLength > Int32.MaxValue) { throw new InvalidDataException(string.Format("RiffChunk chunk length must be between 0 and {0}.", Int32.MaxValue)); } riffChunks.Add(GetRiffChunk(stream, chunkIdentifier, (int)chunkLength)); } stream.Position += chunkLength; } // All Chunks have to be word aligned. // https://www.tactilemedia.com/info/MCI_Control_Info.html // "If the chunk size is an odd number of bytes, a pad byte with value zero is // written after ckData. Word aligning improves access speed (for chunks resident in memory) // and maintains compatibility with EA IFF. The ckSize value does not include the pad byte." if (((chunkLength % 2) != 0) && (br.PeekChar() == 0)) { stream.Position++; } } if (waveFormat == null) { throw new FormatException("Invalid WAV file - No fmt chunk found"); } if (dataChunkPosition == -1) { throw new FormatException("Invalid WAV file - No data chunk found"); } }
public void ReadWaveHeader(Stream stream) { this.dataChunkPosition = -1; this.waveFormat = null; this.riffChunks = new List <RiffChunk>(); this.dataChunkLength = 0; BinaryReader br = new BinaryReader(stream); ReadRiffHeader(br); this.riffSize = br.ReadUInt32(); // read the file size (minus 8 bytes) if (br.ReadInt32() != WaveInterop.mmioStringToFOURCC("WAVE", 0)) { throw new FormatException("Not a WAVE file - no WAVE header"); } if (isRf64) { ReadDs64Chunk(br); } int dataChunkID = WaveInterop.mmioStringToFOURCC("data", 0); int formatChunkId = WaveInterop.mmioStringToFOURCC("fmt ", 0); // sometimes a file has more data than is specified after the RIFF header long stopPosition = Math.Min(riffSize + 8, stream.Length); // this -8 is so we can be sure that there are at least 8 bytes for a chunk id and length while (stream.Position <= stopPosition - 8) { Int32 chunkIdentifier = br.ReadInt32(); Int32 chunkLength = br.ReadInt32(); if (chunkIdentifier == dataChunkID) { dataChunkPosition = stream.Position; if (!isRf64) // we already know the dataChunkLength if this is an RF64 file { dataChunkLength = chunkLength; } stream.Position += chunkLength; } else if (chunkIdentifier == formatChunkId) { waveFormat = WaveFormat.FromFormatChunk(br, chunkLength); } else { // check for invalid chunk length if (chunkLength < 0 || chunkLength > stream.Length - stream.Position) { if (strictMode) { Debug.Assert(false, String.Format("Invalid chunk length {0}, pos: {1}. length: {2}", chunkLength, stream.Position, stream.Length)); } // an exception will be thrown further down if we haven't got a format and data chunk yet, // otherwise we will tolerate this file despite it having corrupt data at the end break; } if (storeAllChunks) { riffChunks.Add(GetRiffChunk(stream, chunkIdentifier, chunkLength)); } stream.Position += chunkLength; } } if (waveFormat == null) { throw new FormatException("Invalid WAV file - No fmt chunk found"); } if (dataChunkPosition == -1) { throw new FormatException("Invalid WAV file - No data chunk found"); } }
public void ReadWaveHeader(Stream stream) { this.dataChunkPosition = -1L; this.waveFormat = null; this.riffChunks = new List <RiffChunk>(); this.dataChunkLength = 0L; BinaryReader binaryReader = new BinaryReader(stream); this.ReadRiffHeader(binaryReader); this.riffSize = (long)((ulong)binaryReader.ReadUInt32()); if (binaryReader.ReadInt32() != ChunkIdentifier.ChunkIdentifierToInt32("WAVE")) { throw new FormatException("Not a WAVE file - no WAVE header"); } if (this.isRf64) { this.ReadDs64Chunk(binaryReader); } int num = ChunkIdentifier.ChunkIdentifierToInt32("data"); int num2 = ChunkIdentifier.ChunkIdentifierToInt32("fmt "); long num3 = Math.Min(this.riffSize + 8L, stream.Length); while (stream.Position <= num3 - 8L) { int num4 = binaryReader.ReadInt32(); uint num5 = binaryReader.ReadUInt32(); if (num4 == num) { this.dataChunkPosition = stream.Position; if (!this.isRf64) { this.dataChunkLength = (long)((ulong)num5); } stream.Position += (long)((ulong)num5); } else if (num4 == num2) { if (num5 > 2147483647u) { throw new InvalidDataException(string.Format("Format chunk length must be between 0 and {0}.", int.MaxValue)); } this.waveFormat = WaveFormat.FromFormatChunk(binaryReader, (int)num5); } else if ((ulong)num5 > (ulong)(stream.Length - stream.Position)) { if (this.strictMode) { break; } break; } else { if (this.storeAllChunks) { if (num5 > 2147483647u) { throw new InvalidDataException(string.Format("RiffChunk chunk length must be between 0 and {0}.", int.MaxValue)); } this.riffChunks.Add(WaveFileChunkReader.GetRiffChunk(stream, num4, (int)num5)); } stream.Position += (long)((ulong)num5); } } if (this.waveFormat == null) { throw new FormatException("Invalid WAV file - No fmt chunk found"); } if (this.dataChunkPosition == -1L) { throw new FormatException("Invalid WAV file - No data chunk found"); } }
public void ReadWaveHeader(Stream stream) { this.dataChunkPosition = -1; this.waveFormat = null; this.riffChunks = new List <RiffChunk>(); this.dataChunkLength = 0; var br = new BinaryReader(stream); ReadRiffHeader(br); this.riffSize = br.ReadUInt32(); // read the file size (minus 8 bytes) if (br.ReadInt32() != ChunkIdentifier.ChunkIdentifierToInt32("WAVE")) { throw new FormatException("Not a WAVE file - no WAVE header"); } if (isRf64) { ReadDs64Chunk(br); } HashSet <int> knownChunkIds = new HashSet <int>(ChunkIdentifier.KnownChunkIdentifiers()); int dataChunkId = ChunkIdentifier.ChunkIdentifierToInt32("data"); int formatChunkId = ChunkIdentifier.ChunkIdentifierToInt32("fmt "); // sometimes a file has more data than is specified after the RIFF header long stopPosition = Math.Min(riffSize + 8, stream.Length); // this -8 is so we can be sure that there are at least 8 bytes for a chunk id and length while (stream.Position <= stopPosition - 8) { Int32 chunkIdentifier = br.ReadInt32(); if (knownChunkIds.Contains(chunkIdentifier) == false) { //this chunk id isn't known, perhaps the previous chunk length was incorrect, lets look in nearby offsets chunkIdentifier = LocalSeekForChunkIdentifier(stream, br, knownChunkIds); } var chunkLength = br.ReadUInt32(); if (chunkIdentifier == dataChunkId) { dataChunkPosition = stream.Position; if (!isRf64) // we already know the dataChunkLength if this is an RF64 file { dataChunkLength = chunkLength; } stream.Position += chunkLength; } else if (chunkIdentifier == formatChunkId) { if (chunkLength > Int32.MaxValue) { throw new InvalidDataException(string.Format("Format chunk length must be between 0 and {0}.", Int32.MaxValue)); } waveFormat = WaveFormat.FromFormatChunk(br, (int)chunkLength); } else { // check for invalid chunk length if (chunkLength > stream.Length - stream.Position) { if (strictMode) { Debug.Assert(false, String.Format("Invalid chunk length {0}, pos: {1}. length: {2}", chunkLength, stream.Position, stream.Length)); } // an exception will be thrown further down if we haven't got a format and data chunk yet, // otherwise we will tolerate this file despite it having corrupt data at the end break; } if (storeAllChunks) { if (chunkLength > Int32.MaxValue) { throw new InvalidDataException(string.Format("RiffChunk chunk length must be between 0 and {0}.", Int32.MaxValue)); } riffChunks.Add(GetRiffChunk(stream, chunkIdentifier, (int)chunkLength)); } stream.Position += chunkLength; } } if (waveFormat == null) { throw new FormatException("Invalid WAV file - No fmt chunk found"); } if (dataChunkPosition == -1) { throw new FormatException("Invalid WAV file - No data chunk found"); } }