Click here to Skip to main content
15,881,172 members
Articles / Programming Languages / C#
Article

Playing .wav files using C#

Rate me:
Please Sign up or sign in to vote.
4.79/5 (34 votes)
10 Aug 2003CPOL1 min read 322.1K   7.1K   79   24
An article demonstrating how to play chosen and user-defined sounds in the .NET framework

Sample Image - player.jpg

Introduction

To achieve some things in the .NET Framework, one must make platform invocation calls to the underlying OS, or use one of the thinly-wrapped COM objects exposed as a class library. This example shows how to play .WAV sounds from a file picker, or play a user-defined sound by enumerating the Windows registry. Since Microsoft did not include a method for playing sounds in the Framework, we must make a PInvoke call to the PlaySound() function located in the Winmm.dll library. The PlaySound function is extremely simple to use as you'll see below.

The PlaySound function

bool PlaySound(
    LPCSTR pszSound,    // filename
    HMODULE hmod,    // handle to resource file
    DWORD fdwSound)    // sound flags
For this example, we play a sound directly from a filename, therefore we need only specify values for pszSound and fdwSound; The hmod parameter must be set to NULL unless playing a sound from a resource.

Partial Source

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Runtime.InteropServices;    // for PInvoke
using Microsoft.Win32;    // RegistryKey

namespace PlaySound
{
    public class Form1 : System.Windows.Forms.Form
    {
        ...
        private RegistryKey key1;
        private RegistryKey key2;




        // collection of user-defined sound events
        private PropertyCollection events;    

        // PlaySound()
        [DllImport("winmm.dll", SetLastError=true, 
                                CallingConvention=CallingConvention.Winapi)]
            static extern bool PlaySound(
                string pszSound,
                IntPtr hMod,
                SoundFlags sf );

        // Flags for playing sounds.  For this example, we are reading 
        // the sound from a filename, so we need only specify 
        // SND_FILENAME | SND_ASYNC
        [Flags]
        public enum SoundFlags : int 
        {
            SND_SYNC = 0x0000,  // play synchronously (default) 
            SND_ASYNC = 0x0001,  // play asynchronously 
            SND_NODEFAULT = 0x0002,  // silence (!default) if sound not found 
            SND_MEMORY = 0x0004,  // pszSound points to a memory file
            SND_LOOP = 0x0008,  // loop the sound until next sndPlaySound 
            SND_NOSTOP = 0x0010,  // don't stop any currently playing sound 
            SND_NOWAIT = 0x00002000, // don't wait if the driver is busy 
            SND_ALIAS = 0x00010000, // name is a registry alias 
            SND_ALIAS_ID = 0x00110000, // alias is a predefined ID
            SND_FILENAME = 0x00020000, // name is file name 
            SND_RESOURCE = 0x00040004  // name is resource name or atom 
        }
        
        ...

        private void buttonPlay_Click(object sender, System.EventArgs e)
        {
            int err = 0;    // last error

            try
            {
                // play the sound from the selected filename
                if (!PlaySound( tbFileName.Text, IntPtr.Zero,
                    SoundFlags.SND_FILENAME | SoundFlags.SND_ASYNC ))
                    MessageBox.Show(this,
                           "Unable to find specified sound file or " +
                           "default Windows sound");
            }
            catch
            {
                // grab the underlying Win32 error code
                err = Marshal.GetLastWin32Error();
                if (err != 0)
                    MessageBox.Show( this,
                        "Error " + err.ToString(),
                        "PlaySound() failed",
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Error );
            }
        }

        // browse button handler
        private void buttonBrowse_Click(object sender, System.EventArgs e)
        {
            string sysRoot = System.Environment.SystemDirectory;
            OpenFileDialog dlg = new OpenFileDialog();
            dlg.AddExtension = true;
            dlg.Filter = "Wave files (*.wav)|*.wav|All files (*.*)|*.*" ;
            // start in media folder
            dlg.InitialDirectory = sysRoot + @"\..\Media";    
            // open dialog
            if(dlg.ShowDialog(this) == DialogResult.OK)
            {
                tbFileName.Text = dlg.FileName;
            }
        }

        ...
        
        // fill combobox with user-defined sounds
        private void PopulateDropDown()
        {
            // fill our PropertyCollection object
            events = GetUserDefinedSounds();

            // disable if no sound events
            if (events.Keys.Count == 0)
                cbUserSound.Enabled = false;
            else
            {
                foreach (string key in events.Keys)
                {
                    cbUserSound.Items.Add(key);
                }
            }
        }

        // Retrieves the user-defined sounds from the registry
        private PropertyCollection GetUserDefinedSounds()
        {
            string rootKey = "AppEvents\\Schemes\\Apps\\.Default";
            PropertyCollection coll = new PropertyCollection();

            try
            {                
                // open root key
                key1 = Registry.CurrentUser.OpenSubKey(rootKey, false);

                // go through each subkey
                foreach (string subKey in key1.GetSubKeyNames())
                {
                    // open subkey
                    key2 = key1.OpenSubKey(subKey + "\\.Current", false);
                    
                    // get filename, if any
                    if (key2 != null)
                        if (key2.GetValue(null).ToString().Length > 0)
                            coll.Add(subKey, key2.GetValue(null).ToString());
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(this, ex.Message, "Yikes!", 
                                  MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            finally
            {
                // close keys
                key1.Close();
                key2.Close();
            }
            
            return coll;
        }
        
        ...        
    }
}

You probably noticed the SetLastError=true parameter in the DllImport call. This simply states that the runtime marshaler calls GetLastError for us in the event something went wrong with our PInvoke call.

Points of Interest

This code has only been tested on Windows 2000 and XP SP1 using Framework version 1.1, however it should also work as far back as Windows 98. Oh yes, the project file is VS.NET 2003 - sorry.

History

Version 1.0 - 07.25.03 - First version.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Zambia Zambia
Living abroad and loving life.

Comments and Discussions

 
Questionwhy dont just add windows media player? Pin
vishal10822-May-09 19:56
vishal10822-May-09 19:56 
GeneralStop Playing Pin
MartinLarsson18-Feb-09 1:38
MartinLarsson18-Feb-09 1:38 
GeneralRe: Stop Playing Pin
Christian Merritt18-Feb-09 2:03
Christian Merritt18-Feb-09 2:03 
GeneralCode to play audio/video file Pin
reogeo200828-Aug-08 2:01
reogeo200828-Aug-08 2:01 
Questionhow todefine visibility of a control in a datalist by clicking on a button which is also in datalist Pin
rahul252613-Jun-08 23:14
rahul252613-Jun-08 23:14 
Questionusing this dll in vista Pin
gurumosch19-Nov-07 21:21
gurumosch19-Nov-07 21:21 
AnswerRe: using this dll in vista Pin
Christian Merritt20-Nov-07 3:23
Christian Merritt20-Nov-07 3:23 
QuestionWhat about mp3??? Pin
Ibrahim Dwaikat7-Nov-07 9:01
Ibrahim Dwaikat7-Nov-07 9:01 
GeneralRe: What about mp3??? Pin
David ITA31-Mar-08 17:42
David ITA31-Mar-08 17:42 
GeneralAlternative - using sound recorder to play wave file programmatically Pin
daluu19-Jul-07 14:44
daluu19-Jul-07 14:44 
Generalwinmm.dll's PlaySound fails to work after compiling my application Pin
daluu19-Jul-07 14:31
daluu19-Jul-07 14:31 
GeneralThanks!!! Pin
Helbrax23-Mar-07 5:01
Helbrax23-Mar-07 5:01 
GeneralBookmark a given point in the wav files. Pin
ywchen7-Apr-06 13:38
ywchen7-Apr-06 13:38 
GeneralPlaying a resource Pin
Dave Midgley24-Jan-06 4:02
Dave Midgley24-Jan-06 4:02 
GeneralThanks! Pin
Joe Pardue21-Nov-05 11:12
Joe Pardue21-Nov-05 11:12 
GeneralRecording .wav files Pin
Ricardo Mendes2-Feb-05 4:57
Ricardo Mendes2-Feb-05 4:57 
I've seen your article and used the information. But I need a way to record audio too. Do you have anything about this?

Thanks
GeneralRe: Recording .wav files Pin
Dave Midgley24-Jan-06 3:57
Dave Midgley24-Jan-06 3:57 
GeneralVery simple Pin
everyone27-Apr-04 23:51
everyone27-Apr-04 23:51 
General[Message Deleted] Pin
Christian Merritt28-Apr-04 14:42
Christian Merritt28-Apr-04 14:42 
GeneralRe: Very simple Pin
wenger2k25-Oct-04 7:24
wenger2k25-Oct-04 7:24 
GeneralRe: Very simple Pin
Hui Shen5-Jan-05 23:43
Hui Shen5-Jan-05 23:43 
GeneralRe: Very simple Pin
Muammar©8-Jan-07 21:32
Muammar©8-Jan-07 21:32 
GeneralSound File From Memory Pin
Tboner20-Aug-03 18:44
Tboner20-Aug-03 18:44 
GeneralRe: Sound File From Memory Pin
musketeer_aramis9-Jun-05 10:51
musketeer_aramis9-Jun-05 10:51 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.