Microsoft & .NET Visual C# Audio Feedback the Easy Way

Audio Feedback the Easy Way

Adding audio feedback to a .NET 1.1 application was a bit of a nuisance
— you had to use interop to call the Windows Multimedia or DirectSound
APIs. You can find plenty of code for this if you search around; however,
.NET 2.0 has an easier solution: the System.Media namespace. This new
namespace provides you with several ways to play sound in your .NET
applications with very little code, and without the need for any interop.

Playing System Sounds

The easiest entry point into System.Media is the SystemSounds class,
which provides you with direct access to five of the sounds from the
current Windows sound scheme:

  • Asterisk
  • Beep
  • Exclamation
  • Hand
  • Question

To play one of these sounds, you use a static method of the
SystemSounds class to retrieve the appropriate SystemSound object, and
then call its Play method. For example, to play the current default beep
sound from your C# application you can use this line of code:


SystemSounds.Beep.Play();

System sounds are specified by the end user through the Sounds tab of
the Sounds and Audio Device Properties control panel applet, as shown in
Figure 1.

Selecting system sounds

Playing Any .wav File

The main potential drawback to using the system sounds is that you can
never be quite sure what sound you’re going to get (or indeed, if you’re
going to get any sound at all). Because it’s up to the user to select,
say, the default Question sound, you have no guarantee what that sound
will be or whether it will be appropriate when your application wants to
ask a question. That’s why the System.Media namespace also contains the
SoundPlayer class, which provides a way to play any .wav file.

By default, the SoundPlayer class works asynchronously, using a
background thread to do its work. The easiest way to use this class is to
tell it where to find the sound that you want to play, and then to call
its Play method, which plays the sound asynchronously. For example, you
could use this code to play a sound:


SoundPlayer sp = new SoundPlayer();
sp.SoundLocation = "c:windowsmediading.wav";
sp.Play();

In addition to the Play method, the SoundPlayer class offers two other
methods to play a sound after its location has been specified. You can
call the PlaySync method to play the sound on the user interface thread
(beware, though, that this will suspend updates to your application’s user
interface while the sound is playing), or the PlayLooping method to play
the sound continuously in a loop until the Stop method is called.

Pre-loading Sounds

The SoundLocation property isn’t limited to specifying disk files to
play. You can also load sounds from a URL by specifying the URL as the
SoundLocation. Alternatively, you can leave the SoundLocation empty and
specify a Stream containing a .wav file in the SoundPlayer’s Stream
property.

If you experiment with these alternative locations, particularly if
you’re working with large .wav files, you’ll discover a small drawback to the
Play method: it has to load the full sound file before playback begins. To work
around this problem, you can use the LoadAsync method and an event callback to
load the sound file before you try to play it.

To use this method, you need to first create your SoundPlayer method
and hook up an appropriate event delegate. You might, for example, do this
when you load a form:


private SoundPlayer spAsync = new SoundPlayer();
private void Form1_Load(object sender, EventArgs e)
{
    // set up event handler for async loading
    spAsync.LoadCompleted += 
        new AsyncCompletedEventHandler(spAsync_LoadCompleted);
}

Before you actually need to play the sound, call the SoundPlayer’s
LoadAsync to load the file that you want to play:


spAsync.SoundLocation = "c:windowsmediading.wav";
spAsync.LoadAsync();

When the SoundPlayer finishes loading the sound, it will call the
LoadCompleted delegate. Depending on your application flow, you might use
this handler to play the sound, or to enable some piece of your user
interface. You can use the IsLoadCompleted property to check whether any
errors happened during the load:

// enable the play button when loading is finished
void spAsync_LoadCompleted(object sender, AsyncCompletedEventArgs e)
{
    if (spAsync.IsLoadCompleted)
        btnPlay.Enabled = true;
}

Using this method, you can be sure that a sound is ready to play when
you want it, without an annoying delay.

A Note of Caution

Just because .NET 2.0 makes it easy to play sounds in your applications
doesn’t mean you should go overboard. Remember, there are potential
accessibility issues to depending solely on audio feedback in an
application. Some users do not hear well; others may be working in a noisy
environment, or running your application on a computer with no sound card
or speakers. Still others find audio feedback just plain annoying. Take
these factors into account when planning your sound use. At a minimum, you
should use sound as one means of feedback, but not the exclusive means,
especially for critical issues. If you do use sounds, it’s a good idea to
provide an option to turn them off. Finally, it adds a bit of polish to
your application to let the user choose their own sounds, rather than
depending on the files that you choose to ship. .NET 2.0 makes the audio
plumbing easy, but it’s up to you to design a system that makes good use
of this new capability.


About the Author

Mike Gunderloy is the author of over 20 books and numerous articles on
development topics, and the Senior Technology Partner for Adaptive Strategy, a
Washington State consulting firm. When
he’s not writing code, Mike putters in the garden on his farm in eastern
Washington state.

Latest Posts

Related Stories