|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
// KIND, EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, WARRANTIES
// OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// � 2006 Gary W. Schwede Stream Computers, Inc. All rights reserved.
// Contact: gary at streamcomputers dot com. Permission to incorporate
// all or part of this code in your application is given on the condition
// that this notice accompanies it in your code and documentation.
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
using System;
using System.Diagnostics;
using System.IO;
using System.Text;
using Microsoft.DirectX.DirectSound;
namespace StreamComputers.Riff
{
/// <summary>
/// RIFFWaveManager is a base class for classes that operate on RIFF WAVE files,
/// including but not limited to Managed DirectX compatible PCM files.
/// </summary>
public abstract class RiffWaveManager : IDisposable
{
#region fields and properties
protected Stream m_Stream;
protected WaveFormatTag m_FormatTag; //aka compression code
protected short m_Channels;
protected int m_SamplesPerSecond; //sampling (frame) rate
protected int m_AverageBytesPerSecond;
protected short m_BlockAlign; // [bytes / frame]
protected short m_BitsPerSample; //significant bits per sample
protected long m_StreamLength; //file length [bytes]
protected long m_DataStart; //start of data field [bytes]
protected long m_DataLength; //number of data bytes (not frames!)
private bool m_Disposed;
public long Length
{
get { return m_Stream.Length; }
}
public bool CanRead
{
get { return m_Stream.CanRead; }
}
public bool CanWrite
{
get { return m_Stream.CanWrite; }
}
#endregion
protected RiffWaveManager()
{}
#region Utility functions for development and debugging.
/// <summary>
/// Returns a string representation of RIFF Wave file properties.
/// </summary>
/// <returns>7-line string representation of properties</returns>
public string WaveFormatAsString()
{
StringBuilder whs = new StringBuilder("MDX WaveFormat Properties:\n");
whs.AppendFormat("AverageBytesPerSecond: {0}\n", m_AverageBytesPerSecond);
whs.AppendFormat("BitsPerSample: {0}\n", m_BitsPerSample );
whs.AppendFormat("BlockAlign: {0}\n", m_BlockAlign );
whs.AppendFormat("Channels: {0}\n", m_Channels );
whs.AppendFormat("FormatTag: {0}\n", m_FormatTag );
whs.AppendFormat("SamplesPerSecond: {0}\n", m_SamplesPerSecond );
return whs.ToString();
}
/// <summary>
/// Returns a string representation of RIFF wave file properties and data length.
/// </summary>
/// <returns>11-line string representation of properties and data length</returns>
public string WaveFileInfoAsString()
{
string fmtString = WaveFormatAsString();
StringBuilder wfi = new StringBuilder(fmtString);
wfi.AppendFormat("\n");
wfi.AppendFormat("Stream length is {0}", m_StreamLength);
wfi.AppendFormat("Data field starts at byte position {0}", m_DataStart);
wfi.AppendFormat("Data field length is {0}", m_DataLength);
return wfi.ToString();
}
/// <summary>
/// Returns a Microsoft.DirectX.DirectSound WaveFormat structure consonant with
/// the RIFFWaveManager object. Throws BadFormatException if not compatible:
/// MDX waveFormat can represent only a subset of valid RIFFWaveManager objects.
/// </summary>
/// <returns>WaveFormat structure describing the RIFFWaveManager object, if compatible.
/// </returns>
public WaveFormat GetMDXWaveFormat()
{
if(m_FormatTag != WaveFormatTag.Pcm)
{
throw new BadFormatException("RIFFWaveManager object represents a non-pcm 16 file.");
}
WaveFormat w = new WaveFormat();
w.FormatTag = (Microsoft.DirectX.DirectSound.WaveFormatTag) WaveFormatTag.Pcm ;
w.AverageBytesPerSecond = m_AverageBytesPerSecond;
w.BitsPerSample = m_BitsPerSample;
w.BlockAlign = m_BlockAlign;
w.Channels = m_Channels;
w.SamplesPerSecond = m_SamplesPerSecond;
return w;
}
/// <summary>
/// Utility function to convert hex byte address of an interesting data pattern
/// seen in a WAVE file to the index of the frame where it appears.
/// </summary>
/// <param name="byteAddressInFile">hex address from start of file</param>
/// <returns>number of frames from start of data chunk</returns>
public long ByteAddressToFrameIndex(long byteAddressInFile)
{
Debug.Assert(byteAddressInFile <= m_StreamLength);
return (byteAddressInFile - m_DataStart)/m_BlockAlign;
}
#endregion
#region Finalization
// Closes the file and releases resources.
public virtual void Close()
{
Dispose();
}
// � 2005 IDesign Inc. Used by permission.
protected bool Disposed
{
get
{
lock(this)
{
return m_Disposed;
}
}
}
// � 2005 IDesign Inc. Used by permission.
public void Dispose()
{
lock(this)
{
if(m_Disposed == false)
{
Cleanup();
m_Disposed = true;
GC.SuppressFinalize(this);
}
}
}
protected virtual void Cleanup()
{
if(m_Stream != null)
{
m_Stream.Close();
m_Stream = null;
}
}
~RiffWaveManager()
{
Cleanup();
}
#endregion
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
My life and career have been a bit unusual (mostly in good ways). So, I'm grateful every day for the opportunities God's given me to do different things and see different aspects of life.
Education: B.S. Physics '73 (atmospheric physics, sounding rockets), M.S. Computer Science '76 (radio astronomy, fuzzy controllers, music pattern recognition and visualization) New Mexico Tech; Ph.D. Engineering '83 (parallel computer architecture, digital signal processing, economics) U.C. Berkeley.
I'm married to Susan, a wonderful woman whom I met in a Computer Architecture class at U.C. Berkeley.
Professional activities: Digital systems engineer, digital audio pioneer, founder or key in several tech startups, consulting engineer, expert witness. I'm currently developing a multithreading framework in C# .NET, that makes it almost easy to write correct programs for multicore processors. I'm also implementing a new transform for recognizing, editing, and processing signals, especially sound.
I'm an occasional essayist, public speaker, and podcaster, and free-market space advocate. I enjoy good wine, good music, good friends, and cats.
If you think your project could use a different point of view, I'm available for consulting work in the San Francisco Bay area, or (preferrably) via the net.