Play Embedded WAV Resources in .NET
By Peter A. Bromberg, Ph.D.
Printer - Friendly Version
Peter Bromberg

The .NET platform does not provide intrinsic classes to play sounds- these are handled natively in the Windows APIs resident in the Winmm.dll library. However, once you've isolated the API calls, it's no more difficult to play WAV files, and even WAV files stored in your assembly as embedded resources - than in any other language.

I wanted to embed a couple of handy WAV files in an assembly to be able to play them on demand for various events raised in one of my creations, and so I put together this handy class, which can simply be added to any project, to provide static access to the PlaySound export for embedded resources. There are several overloads, the one we want accepts a byte array containing the resource, an IntPtr and UInt32 flags parameter which as with many API calls is the result of performing an OR method against defined constants. The beauty of my little creation is that it can normally be added to any project as is, and uses Reflection to get the namespace of the assembly dynamically.

To add WAV files as embedded resources, simply ADD them to your project and set the property attribute of each to "Embedded Resource", and .NET takes care of the rest.

First, here's the class - you can see I've given it a namespace and class name that reflect where the call is being made to:



 

using System;
using System.Runtime.InteropServices;
using System.Resources;
using System.IO;
namespace Win32
{
public class Winmm
{
public const UInt32 SND_ASYNC = 1;
public const UInt32 SND_MEMORY = 4;
// these 2 overloads we dont need ...
// [DllImport("Winmm.dll")]
// public static extern bool PlaySound(IntPtr rsc, IntPtr hMod, UInt32 dwFlags);

// [DllImport("Winmm.dll")]
// public static extern bool PlaySound(string Sound, IntPtr hMod, UInt32 dwFlags);

// this is the overload we want to play embedded resource...
[DllImport("Winmm.dll")]
public static extern bool PlaySound(byte[] data, IntPtr hMod, UInt32 dwFlags);
public Winmm()
{
}
public static void PlayWavResource(string wav)
{
// get the namespace
string strNameSpace=
System.Reflection.Assembly.GetExecutingAssembly().GetName().Name.ToString();

// get the resource into a stream
Stream str =
System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream( strNameSpace +"."+ wav );
if ( str == null )
return;
// bring stream into a byte array
byte[] bStr = new Byte[str.Length];
str.Read(bStr, 0, (int)str.Length);
// play the resource
PlaySound(bStr, IntPtr.Zero, SND_ASYNC | SND_MEMORY);
}
}
}

 

To use the class, we would make the call as follows:


private void button2_Click(object sender, System.EventArgs e)
{
Win32.Winmm.PlayWavResource("chimes.wav");
}

N.B.   Reader Jim McLendon converted the class to VB.NET for those who are interested, and has posted his code on our forums. You can view it here.

That's all there is to it! The download has a complete solution, including the famous "chimes.wav" and "chord.wav" that everyone has, I am sure, heard many times.

Download the code that accompanies this article

 


Peter Bromberg is a C# MVP, MCP, and .NET consultant who has worked in the banking and financial industry for 20 years. He has architected and developed web - based corporate distributed application solutions since 1995, and focuses exclusively on the .NET Platform.