[B]
using System;
[/B][B]using System.IO;[/B]
[B]using System.Drawing;[/B]
[B]using System.Windows.Forms;[/B]
[B]using System.Diagnostics;[/B]
[B]namespace AudioUtils[/B]
[B]{[/B]
[B] /// <summary>[/B]
[B] /// Summary description for WaveFile.[/B]
[B] /// </summary>[/B]
[B] public class WaveFile[/B]
[B] {[/B]
[B] /// <summary>[/B]
[B] /// The Riff header is 12 bytes long[/B]
[B] /// </summary>[/B]
[B] class Riff[/B]
[B] {[/B]
[B] public Riff()[/B]
[B] {[/B]
[B] m_RiffID = new byte[ 4 ];[/B]
[B] m_RiffFormat = new byte[ 4 ];[/B]
[B] }[/B]
[B] public void ReadRiff( FileStream inFS )[/B]
[B] {[/B]
[B] inFS.Read( m_RiffID, 0, 4 );[/B]
[B] Debug.Assert( m_RiffID[0] == 82, "Riff ID Not Valid" );[/B]
[B] BinaryReader binRead = new BinaryReader( inFS );[/B]
[B] m_RiffSize = binRead.ReadUInt32( );[/B]
[B] inFS.Read( m_RiffFormat, 0, 4 );[/B]
[B] }[/B]
[B] public byte[] RiffID[/B]
[B] {[/B]
[B] get { return m_RiffID; }[/B]
[B] }[/B]
[B] public uint RiffSize[/B]
[B] {[/B]
[B] get { return ( m_RiffSize ); }[/B]
[B] }[/B]
[B] public byte[] RiffFormat[/B]
[B] {[/B]
[B] get { return m_RiffFormat; }[/B]
[B] }[/B]
[B] private byte[] m_RiffID;[/B]
[B] private uint m_RiffSize;[/B]
[B] private byte[] m_RiffFormat;[/B]
[B] }[/B]
[B] /// <summary>[/B]
[B] /// The Format header is 24 bytes long[/B]
[B] /// </summary>[/B]
[B] class Fmt[/B]
[B] {[/B]
[B] public Fmt()[/B]
[B] {[/B]
[B] m_FmtID = new byte[ 4 ];[/B]
[B] }[/B]
[B] public void ReadFmt( FileStream inFS )[/B]
[B] {[/B]
[B] inFS.Read( m_FmtID, 0, 4 );[/B]
[B] Debug.Assert( m_FmtID[0] == 102, "Format ID Not Valid" );[/B]
[B] BinaryReader binRead = new BinaryReader( inFS );[/B]
[B] m_FmtSize = binRead.ReadUInt32( );[/B]
[B] m_FmtTag = binRead.ReadUInt16( );[/B]
[B] m_Channels = binRead.ReadUInt16( );[/B]
[B] m_SamplesPerSec = binRead.ReadUInt32( );[/B]
[B] m_AverageBytesPerSec = binRead.ReadUInt32( );[/B]
[B] m_BlockAlign = binRead.ReadUInt16( );[/B]
[B] m_BitsPerSample = binRead.ReadUInt16( );[/B]
[B] // This accounts for the variable format header size [/B]
[B] // 12 bytes of Riff Header, 4 bytes for FormatId, 4 bytes for FormatSize & the Actual size of the Format Header [/B]
[B] inFS.Seek( m_FmtSize + 20, System.IO.SeekOrigin.Begin );[/B]
[B] }[/B]
[B] public byte[] FmtID[/B]
[B] {[/B]
[B] get { return m_FmtID; }[/B]
[B] }[/B]
[B] public uint FmtSize[/B]
[B] {[/B]
[B] get { return m_FmtSize; }[/B]
[B] }[/B]
[B] public ushort FmtTag[/B]
[B] {[/B]
[B] get { return m_FmtTag; }[/B]
[B] }[/B]
[B] public ushort Channels[/B]
[B] {[/B]
[B] get { return m_Channels; }[/B]
[B] }[/B]
[B] public uint SamplesPerSec[/B]
[B] {[/B]
[B] get { return m_SamplesPerSec; }[/B]
[B] }[/B]
[B] public uint AverageBytesPerSec[/B]
[B] {[/B]
[B] get { return m_AverageBytesPerSec; }[/B]
[B] }[/B]
[B] public ushort BlockAlign[/B]
[B] {[/B]
[B] get { return m_BlockAlign; }[/B]
[B] }[/B]
[B] public ushort BitsPerSample[/B]
[B] {[/B]
[B] get { return m_BitsPerSample; }[/B]
[B] }[/B]
[B] private byte[] m_FmtID;[/B]
[B] private uint m_FmtSize;[/B]
[B] private ushort m_FmtTag;[/B]
[B] private ushort m_Channels;[/B]
[B] private uint m_SamplesPerSec;[/B]
[B] private uint m_AverageBytesPerSec;[/B]
[B] private ushort m_BlockAlign;[/B]
[B] private ushort m_BitsPerSample;[/B]
[B] }[/B]
[B] /// <summary>[/B]
[B] /// The Data block is 8 bytes + ???? long[/B]
[B] /// </summary>[/B]
[B] class Data[/B]
[B] {[/B]
[B] public Data()[/B]
[B] {[/B]
[B] m_DataID = new byte[ 4 ];[/B]
[B] }[/B]
[B] public void ReadData( FileStream inFS )[/B]
[B] {[/B]
[B] //inFS.Seek( 36, System.IO.SeekOrigin.Begin );[/B]
[B] inFS.Read( m_DataID, 0, 4 );[/B]
[B] Debug.Assert( m_DataID[0] == 100, "Data ID Not Valid" );[/B]
[B] BinaryReader binRead = new BinaryReader( inFS );[/B]
[B] m_DataSize = binRead.ReadUInt32( );[/B]
[B] m_Data = new Int16[ m_DataSize ];[/B]
[B] inFS.Seek( 40, System.IO.SeekOrigin.Begin );[/B]
[B] m_NumSamples = (int) ( m_DataSize / 2 );[/B]
[B] for ( int i = 0; i < m_NumSamples; i++)[/B]
[B] {[/B]
[B] m_Data[ i ] = binRead.ReadInt16( );[/B]
[B] }[/B]
[B] } [/B]
[B] public byte[] DataID[/B]
[B] {[/B]
[B] get { return m_DataID; }[/B]
[B] }[/B]
[B] public uint DataSize[/B]
[B] {[/B]
[B] get { return m_DataSize; }[/B]
[B] }[/B]
[B] public Int16 this[ int pos ][/B]
[B] {[/B]
[B] get { return m_Data[ pos ]; }[/B]
[B] }[/B]
[B] public int NumSamples[/B]
[B] {[/B]
[B] get { return m_NumSamples; }[/B]
[B] }[/B]
[B] private byte[] m_DataID;[/B]
[B] private uint m_DataSize;[/B]
[B] private Int16[] m_Data;[/B]
[B] private int m_NumSamples;[/B]
[B] }[/B]
[B] public WaveFile( String inFilepath )[/B]
[B] {[/B]
[B] m_Filepath = inFilepath;[/B]
[B] m_FileInfo = new FileInfo( inFilepath );[/B]
[B] m_FileStream = m_FileInfo.OpenRead( );[/B]
[B] m_Riff = new Riff( );[/B]
[B] m_Fmt = new Fmt( );[/B]
[B] m_Data = new Data( );[/B]
[B] }[/B]
[B] public void Read( )[/B]
[B] {[/B]
[B] m_Riff.ReadRiff( m_FileStream );[/B]
[B] m_Fmt.ReadFmt( m_FileStream );[/B]
[B] m_Data.ReadData( m_FileStream );[/B]
[B] }[/B]
[B] public void Draw( PaintEventArgs pea, Pen pen )[/B]
[B] {[/B]
[B] Graphics grfx = pea.Graphics;[/B]
[B] if ( m_PageScale == 0.0f )[/B]
[B] m_PageScale = grfx.VisibleClipBounds.Width / m_Data.NumSamples;[/B]
[B] grfx.PageScale = m_PageScale;[/B]
[B] RectangleF visBounds = grfx.VisibleClipBounds;[/B]
[B] grfx.DrawLine( pen, 0, visBounds.Height / 2, visBounds.Width, visBounds.Height / 2 );[/B]
[B] grfx.TranslateTransform( 0, visBounds.Height );[/B]
[B] grfx.ScaleTransform( 1, -1 );[/B]
[B] Draw16Bit( grfx, pen, visBounds );[/B]
[B] }[/B]
[B] void Draw16Bit( Graphics grfx, Pen pen, RectangleF visBounds )[/B]
[B] {[/B]
[B] short val = m_Data[ 0 ];[/B]
[B] int prevX = 0;[/B]
[B] int prevY = (int) (( (val + 32768) * visBounds.Height ) / 65536 );[/B]
[B] for ( int i = 0; i < m_Data.NumSamples; i++ )[/B]
[B] {[/B]
[B] val = m_Data[ i ];[/B]
[B] int scaledVal = (int) (( (val + 32768) * visBounds.Height ) / 65536 );[/B]
[B] grfx.DrawLine( pen, prevX, prevY, i, scaledVal );[/B]
[B] prevX = i;[/B]
[B] prevY = scaledVal;[/B]
[B] if ( m_Fmt.Channels == 2 )[/B]
[B] i++;[/B]
[B] }[/B]
[B] }[/B]
[B] public void ZoomIn( )[/B]
[B] {[/B]
[B] m_PageScale /= 2;[/B]
[B] }[/B]
[B] public void ZoomOut( )[/B]
[B] {[/B]
[B] m_PageScale *= 2;[/B]
[B] }[/B]
[B] private string m_Filepath;[/B]
[B] private FileInfo m_FileInfo;[/B]
[B] private FileStream m_FileStream;[/B]
[B] private Riff m_Riff;[/B]
[B] private Fmt m_Fmt;[/B]
[B] private Data m_Data;[/B]
[B] private float m_PageScale = 0.0f;[/B]
[B] }[/B]
[B]}[/B]