Click here to Skip to main content
Email Password   helpLost your password?

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.

You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
Generalwhy dont just add windows media player?
vishal1082
20:56 2 May '09  
why dont just add windows media player dll in your project... and play the audio through media palyer.....make media player visible = false if you dont want anyone to see it...simplest and easiest way.. Big Grin
GeneralStop Playing
MartinLarsson
2:38 18 Feb '09  
Is there a way to stop playing a sound. Or can I just call another PlaySound() with no file name and no default sound?
Great Function!
GeneralRe: Stop Playing
Marc Merritt
3:03 18 Feb '09  
Pass NULL to pszSound and any currently playing sound will stop. Smile
GeneralCode to play audio/video file
reogeo2008
3:01 28 Aug '08  
hi all,


i have a web application where the user can upload video/audio files.

For example in Songs category one can upload video /audio files of songs(Admin).But irrespective of the file format i have to play the file when another user cliks on play button(End User Part).how can i acheive this


Thanks in advance
Questionhow todefine visibility of a control in a datalist by clicking on a button which is also in datalist
rahul2526
0:14 14 Jun '08  
Hi to all..........
I am facing a problem......
all of u are aware great site ORKUT....
my proj is similar to that......

i need to make a textbox visible in datalist by clicking a reply button in datalist.....

bt i am not getting it.....

i want only textbox to be visible which is in same row with reply button in datalist.....
others must be not visible........

plz help me out......
Questionusing this dll in vista
gurumosch
22:21 19 Nov '07  
Hi,
i'm using that code in a program that must also run under windows vista. the problem is, that it only works, if i switch the "Run as administrator" in settings->compatibility on. Otherwise i get an exception. Is there a work around for taht problem?

Regards
AnswerRe: using this dll in vista
Marc Merritt
4:23 20 Nov '07  
Larry Osterman blogged about this very problem and posted the solution here: http://blogs.msdn.com/larryosterman/archive/2007/07/24/playsound-is-failing-on-vista-what-s-wrong.aspx

I have not personally tried it, but let me know if that doesn't fix the issue. I will get around to posting and update to this rather old article to address the Vista issue. Smile Thanks!
QuestionWhat about mp3???
Ibrahim Dwaikat
10:01 7 Nov '07  
1-How can we play mp3 files??

2- how can we select which sound card to play on???

Visit Me

www.engibrahim.tk

GeneralRe: What about mp3???
David ITA
18:42 31 Mar '08  
The PlaySound function is very limited. Basically it can only play certain formats of wave sounds. MP3 is not supported.

If you want more complex operations you can use Windows Media SDK (it's what windows media player uses so if it works there it will work in your application).
GeneralAlternative - using sound recorder to play wave file programmatically
daluu
15:44 19 Jul '07  
Just an FYI to those interested. I just found this out from a web search.

Launch a process in .NET to run the following command:

sndrec32 /play /close pathToWaveFile

"A good scientist is a person with original ideas. A good engineer is a person who makes a design that works with as few original ideas as possible." - Freeman Dyson

Generalwinmm.dll's PlaySound fails to work after compiling my application
daluu
15:31 19 Jul '07  
Has anybody encountered this? I'll probably have to try compiling on other computers to see what happens.

I followed the code guidelines in the article when building my console application. After compilation, it fails to play wave file. It hangs trying to play the wave file.

I built the console application with SharpDevelop 2.0. That shouldn't matter I think since I built another app that used kernel32.dll with SharpDevelop as well and that app worked fine.

Frustrated that this isn't working, I tried using a simplified solution to this article at http://www.codeproject.com/cs/media/tonysound.asp. I tried with Visual Studio 2003 and GUI apps instead still to no luck.

Funny thing though is that the demo & re-compile of the source of that article, and the demo of this article work fine.

My system is running Windows XP SP2, with .NET v1.1, v2.0, Visual Studio 2003, SharpDevelop 2.0. I verified I have winmm.dll on my system as well.

I followed the code in this article accordingly, so I have no idea what the heck's going on. I wish the compile would fail with an message or that the running the app would give a runtime error. Too bad all it does is hang. Guess I'll try analyzing with a debugger when I have some time.

btw, be nice if someone could compile a console app that takes an argument for the path to a wave file to play. That's what I was originally trying to do.

"A good scientist is a person with original ideas. A good engineer is a person who makes a design that works with as few original ideas as possible." - Freeman Dyson

GeneralThanks!!!
Helbrax
6:01 23 Mar '07  
Using this I was able to piece together a simple class to play my wav files from a file or a resource. Thanks a bunch!

Media.Sound.PlayFile("c:\blah.wav");
Media.Sound.PlayResource("blah.wav");



using System;
using System.Runtime.InteropServices;
using System.IO;
using System.Windows.Forms;
using System.Reflection;

namespace Media
{
public class Sound
{
[DllImport("winmm.dll", SetLastError=true,
CallingConvention=CallingConvention.Winapi)]
static extern bool PlaySound(
string pszSound,
IntPtr hMod,
SoundFlags sf );

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

// Flags for playing sounds.
[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
}
public static void PlayFile(string wav)
{
PlaySound(wav, IntPtr.Zero, SoundFlags.SND_FILENAME | SoundFlags.SND_ASYNC);
}
public static void PlayResource(string wav)
{
Assembly asm = Assembly.GetExecutingAssembly();
System.IO.Stream stream = asm.GetManifestResourceStream(wav);
byte[] bStr = new Byte[stream.Length];
stream.Read(bStr, 0, (int)stream.Length);
IntPtr buff=Marshal.UnsafeAddrOfPinnedArrayElement(bStr, 0);
PlaySound(buff, SoundFlags.SND_MEMORY | SoundFlags.SND_ASYNC);
}
}
}
GeneralBookmark a given point in the wav files.
ywchen
14:38 7 Apr '06  

Hi,

I am wondering how to bookmark a given wav file so that we can play it from the bookmark instead of playing it from the beginning of it. Thanks.

Regards,
YW
GeneralPlaying a resource
Dave Midgley
5:02 24 Jan '06  
I'd like to see an example of playing a sound from a resource, as I'm not sure exactly what should go into hmod. Apparently it is the "handle to the executable file that contains the resource to be loaded", but I'm not sure how to acquire that in a C#.NET program. Can anyone help?

Dave
GeneralThanks!
Joe Pardue
12:12 21 Nov '05  
I needed to add a low battery audible alarm to a device that will be used in hospitals, so I wanted to allow selection of a wav file that would alert the Nurse without scaring the patients. I was able to use your code and in about half an hour my code can issue an alarm.

Smile Thanks for the effort.

Joe Pardue

More stuff at www.smileymicros.com
GeneralRecording .wav files
Ricardo Mendes
5:57 2 Feb '05  
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
Dave Midgley
4:57 24 Jan '06  
You're probably sorted by now, but if not I can recommend Audacity as a simple and free sound editing program.

Dave
GeneralVery simple
eVeryOne
0:51 28 Apr '04  
Very simple
General[Message Deleted]
Marc Merritt
15:42 28 Apr '04  

GeneralRe: Very simple
wenger2k
8:24 25 Oct '04  
It may be simple but is exactly what I needed - thanks!
GeneralRe: Very simple
Hui Shen
0:43 6 Jan '05  
Nice work!
Simple, effective and easy to copy Big Grin

What you don't know hurts you.
GeneralRe: Very simple
Muammar©
22:32 8 Jan '07  
Simplicity is what everyone is looking for!!
so thanx a bunchSmile Rose


All generalizations are wrong, including this one! (\ /)
(O.o)
(><)

GeneralSound File From Memory
Tboner
19:44 20 Aug '03  
Do you know how to play a sound file from memory?

ie.

Assembly asm = Assembly.GetExecutingAssembly();
System.IO.Stream stream = asm.GetManifestResourceStream("sound.wav");
PlaySound(stream); // <--??? how do you make a function like this?

Basically I would like the sound file to be embedded in a satellite assembly.

-Trevor
GeneralRe: Sound File From Memory
musketeer_aramis
11:51 9 Jun '05  
I think you can use this function :

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


IntPtr buff=Marshal.UnsafeAddrOfPinnedArrayElement(arrayToPlay, 0);

// play the sound from the selected filename
if (!PlaySound( buff, SoundFlags.SND_MEMORY | SoundFlags.SND_ASYNC ))
throw new Exception("Unable to find specified sound file or default Windows sound");



La vita e bella


Last Updated 11 Aug 2003 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2010