// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY // KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR // PURPOSE. // // This material may not be duplicated in whole or in part, except for // personal use, without the express written consent of the author. // // Email: ianier@hotmail.com // // Copyright (C) 1999-2003 Ianier Munoz. All Rights Reserved. using System; using System.IO; namespace WaveLib { public class WaveStream : Stream, IDisposable { private Stream m_Stream; private long m_DataPos; private long m_Length; private WaveFormat m_Format; public WaveFormat Format { get { return m_Format; } } private string ReadChunk(BinaryReader reader) { byte[] ch = new byte[4]; reader.Read(ch, 0, ch.Length); return System.Text.Encoding.ASCII.GetString(ch); } private void ReadHeader() { BinaryReader Reader = new BinaryReader(m_Stream); if (ReadChunk(Reader) != "RIFF") throw new Exception("Invalid file format"); Reader.ReadInt32(); // File length minus first 8 bytes of RIFF description, we don't use it if (ReadChunk(Reader) != "WAVE") throw new Exception("Invalid file format"); if (ReadChunk(Reader) != "fmt ") throw new Exception("Invalid file format"); int FormatLength = Reader.ReadInt32(); if ( FormatLength < 16) // bad format chunk length throw new Exception("Invalid file format"); m_Format = new WaveFormat(22050, 16, 2); // initialize to any format m_Format.wFormatTag = Reader.ReadInt16(); m_Format.nChannels = Reader.ReadInt16(); m_Format.nSamplesPerSec = Reader.ReadInt32(); m_Format.nAvgBytesPerSec = Reader.ReadInt32(); m_Format.nBlockAlign = Reader.ReadInt16(); m_Format.wBitsPerSample = Reader.ReadInt16(); if ( FormatLength > 16) { m_Stream.Position += (FormatLength-16); } // assume the data chunk is aligned while(m_Stream.Position < m_Stream.Length && ReadChunk(Reader) != "data") ; if (m_Stream.Position >= m_Stream.Length) throw new Exception("Invalid file format"); m_Length = Reader.ReadInt32(); m_DataPos = m_Stream.Position; Position = 0; } public WaveStream(string fileName) : this(new FileStream(fileName, FileMode.Open)) { } public WaveStream(Stream S) { m_Stream = S; ReadHeader(); } public override bool CanRead { get { return true; } } public override bool CanSeek { get { return true; } } public override bool CanWrite { get { return false; } } public override long Length { get { return m_Length; } } public override long Position { get { return m_Stream.Position - m_DataPos; } set { Seek(value, SeekOrigin.Begin); } } public override void Flush() { } /*protected override void Dispose(bool disposing) { if (disposing) m_Stream.Dispose(); base.Dispose(disposing); }*/ public override void SetLength(long len) { throw new InvalidOperationException(); } public override long Seek(long pos, SeekOrigin o) { switch(o) { case SeekOrigin.Begin: m_Stream.Position = pos + m_DataPos; break; case SeekOrigin.Current: m_Stream.Seek(pos, SeekOrigin.Current); break; case SeekOrigin.End: m_Stream.Position = m_DataPos + m_Length - pos; break; } return this.Position; } public override int Read(byte[] buf, int ofs, int count) { int toread = (int)Math.Min(count, m_Length - Position); return m_Stream.Read(buf, ofs, toread); } public override void Write(byte[] buf, int ofs, int count) { throw new InvalidOperationException(); } } }