Click here to Skip to main content
Click here to Skip to main content
 
Add your own
alternative version

Sound Experiments in Managed DirectX

, 16 Feb 2007
Using static and streaming sound buffers in Managed DirectX.
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//  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.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

DrGary83
Software Developer (Senior)
United States United States
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.

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.1411028.1 | Last Updated 16 Feb 2007
Article Copyright 2006 by DrGary83
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid