Introduction
This is a re-post of an item that I had on my old blog. As it seems to continue to get a lot of hits (when the site is up) I thought I would transfer it over here to the new site.
It is more of a "here's how" approach than a "why it works that way" one. Also I will be creating everything in code, not markup. There are several more approaches and advanced techniques available via XAML that I won't be covering here.
PART 1 : The SoundPlayer
1. Hard Coded File Path
Starting with possibly the least realistic scenario, you can use the SoundPlayer to play a .wav file by pointing directly to a file via a hard coded path.
Imports System.Media
Private Sub Button1_Click(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Button1.Click
Dim player As New SoundPlayer("C:Temp4WAY.WAV")
player.Play()
End Sub
Note the Imports statement at the top.
This wave file will play asynchronously (I do wish someone would come up with an easier to type word than that! - it's nearly as bad as 'concatenation' ) But I digress….
If it's a particularly large wav file, you can help things out by inserting a Load statement after the initialization and before the Play fires. This will tee the player up to play without any kind of pause while it cranks up the file. This is something well worth bearing in mind as we users have become more and more impatient of delays.
2. Use a Content File
One particularly useful approach which gets around all the potential problems of hard coding file paths is to add the file to your Solution Explorer items. You can do this with the standard "Add Existing Item" selection from the IDE menu, adding the wav file directly to the list of files for the Project.
This now brings me to Frustration #1. First, here's valid code to play the sound using a SoundPlayer object:
Private Sub Button6_Click(
ByVal sender
As System.Object,
ByVal e
As System.Windows.RoutedEventArgs)
Handles Button6.Click
Dim player As New SoundPlayer
player = New SoundPlayer("SND0103.WAV")
player.Play()
End Sub
Now, before we move on, let's check the Solution Explorer:

As you can see the file name is correctly entered and that file is sitting in the Solution Explorer's list of files that (you would think) it knows about.
The key to fixing this problem is the 'Copy to Output Directory' Property. By default, this is set to 'Do Not Copy'.

You need to change this to 'Copy Always' and you'll be back on track.
3. Audio File as Resource (Frustration #2)
I wasn't going to include this option because it has generally caused me more trouble than it's worth (especially bearing in mind that there are several relatively trouble-free alternatives). However, you can add a wav file as a Project Resource as normal and then play that Resource via a Stream.
The syntax is:
Private Sub btnResource_Click(
ByVal sender
As System.Object,
ByVal e
As System.Windows.RoutedEventArgs)
Handles btnResource.Click
Dim player
As New SoundPlayer(
My.Resources.canon)
player.Play()
End Sub
Even with small, well tested files I often found that using this approach I would get a lot of unacceptable sound distortion (actually additional unrelated sounds to that expected). I have tried it on several PCs, each with different sound card configurations and the problems occur on them all.
5. Other SoundPlayer Features
In addition to the standard Play method, the SoundPlayer has a PlaySync method – in case you should rather unusually want the system to be locked until the sound has finished playing.
And finally if you want a sound to be repeatedly played, you can use the PlayLooping method to drive people mad; sanity can be restored by inserting the Stop method!
PART 2: MediaPlayer and Media Element
As you've already seen, the SoundPlayer has some limitations. It only understands wav format files and you can generally only play one wav file at a time (unless you start to get quite fancy with multithreading). In many cases, the MediaPlayer or MediaElement will be a better option, but there is a good reason why I included the discussion of the SoundPlayer above. In some situations on particular systems you will have problems getting the two Media components to work properly. So it's always useful to know how to use the lighter weight SoundPlayer if you run into these problems in the future.
6. But I Want to Play MP3 Files!
- or WMA or MID, etc. for that matter. And this is a job for either the MediaPlayer or MediaElement. Keeping to my approach of doing all the work in code, I'm therefore going to home in on the MediaPlayer. (If you have a need to create a media object in XAML and have it play, pause, stop, trigger, etc, only in XAML then the MediaElement will be your tool of choice.)
Before abandoning the MediaElement approach altogether, I should point out that you can create the MediaElement in XAML and then access it's properties and methods in code. However, there is no advantage that I know of and in fact, the syntax is slightly more verbose and it also caused Frustration #4 – the fact that the audio file will only play once and then needs to be 'reset' by calling its Stop method; the Stop method apparently has the effect of returning the playhead to the beginning of the file.
So let's look at the MediaPlayer in WPF. It has an Open method which loads the file in the form of a URI. This was Frustration #5 for me, as it took me a while to get past the problem of the "Value of Type 'String' cannot be converted to 'System.URI.'" error. It took a lot more than a quick search to finally discover that I needed simply to add the URIKind argument to the Open method; so the considerable amount of time I spent trying to do casts was wasted. But maybe that's something I should have known.
It also has Play, Pause and Stop methods, plus the more sophisticated Balance and Volume properties.
There is another small Gotcha involved in using this control. Take a look at the following code snippet:
Code Copy
Dim mplayer As New MediaPlayer
mplayer.Open(New Uri("Godfather.mp3", UriKind.Relative))
mplayer.Play()
It's hard to see anything wrong with that code snippet, but if you do try it you'll find that the audio will play for a short period of time and then – for no apparent reason – stop. This is Frustration #6.
As I understand it, what happens here is that the new MediaPlayer object is created, passed a URI for its source and then instructed to play. Play begins but at that point seemingly the MediaPlayer closes itself, saying "I've set the audio away, so my work here is done". The end result is that at some unpredictable point in time the closed MediaPlayer is released from memory and will be disposed. And of course as soon as it no longer exists there is no means for the sound to continue to be played. So it stops in mid note!
Anyway, having dragged you laboriously through that explanation, you'll probably already have realised that the fix is simple. All you need do is instantiate the MediaPlayer outside the scope of the click event so that the MediaPlayer will continue to exist throughout the lifetime of that Window or Page. In other words, like this:
Class Window1
Dim mplayer
As MediaPlayer
Private Sub Button1_Click(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Button1.Click
mplayer = New MediaPlayer
mplayer.Open(New Uri("Godfather.mp3", UriKind.Relative))
mplayer.Play()
End Sub
End Class
As with the SoundPlayer sample, the mp3 file has been added to the project files in Solution Explorer, its Build property set to Content and its Copy To Output Director set to Copy Always.
If the file is extra large and you get a pause before it actually begins to play then you can of course move the mediaplayer instantiation and Open code to, for instance, the Window Loaded event or some other place where the delay won't be so obvious. It will then be teed up ready to go as soon as the Play method is invoked.
7. Summary
There isn't much else to add. I think you now have the tools you need to play sound and music files in WPF. By the way, that does also mean both sounds and music at the same time, because you can have multiple instances of MediaPlayers running concurrently (or MediaPlayer(s) and a SoundPlayer running together). Therefore you can have almost any combination of sound files running, subject to the limitations of your system, that is.
I hope you will find this information useful in your future projects if you need to include sound and want to avoid the frustration of the learning curve.
