Click here to Skip to main content
15,884,388 members
Articles / Multimedia / DirectX

Sound Experiments in Managed DirectX

Rate me:
Please Sign up or sign in to vote.
4.85/5 (46 votes)
16 Feb 200726 min read 267.5K   4K   118  
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.


Written By
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.

Comments and Discussions