Adding Sound Effects to a Windows Phone 7 Silverlight Application

Certain Windows Phone 7 applications benefit from using sound effects, even if the application itself is written in Silverlight. You most likely have noticed that you can play media inside a Silverlight application by making use of the MediaPlayerLauncher inside your application to pass control to the integrated media player on the phone or by making use of the MediaElement class. Both these options are great if you want to play audio content under control of some form of media player (with MediaElement allowing to integrate player functionality inside your own application).

However, if you want short sound effects that play under control of your application, you can make use of functionality that is available in the XNA Framework, even if you are developing a Silverlight based Windows Phone 7 application. The XNA Framework contains a SoundEffect class. This class holds a sound resource in memory that can be played from inside your application by calling its Play method. You can even alter properties like the pitch and volume of a SoundEffect. Since there is interoperability possible between Silverlight and the XNA Framework (at least to a certain extend), it is possible to make use of SoundEffect inside a Silverlight application. However, given the different application models for Silverlight and XNA Framework applications, you have to be aware of what you are doing when added SoundEffect to your Silverlight application. A first attempt to add sound might look like this:

  1. using System.ComponentModel;
  2. using System.IO;
  3. using Microsoft.Xna.Framework;
  4. using Microsoft.Xna.Framework.Audio;
  5.  
  6. namespace Clicker.Model
  7. {
  8.     public class SoundPlayer
  9.     {
  10.         public enum Sounds
  11.         {
  12.             Switch = 0,
  13.             Penalty,
  14.             StartGame,
  15.             HighScore,
  16.             EndGame
  17.         };
  18.  
  19.         static SoundEffect[] soundEffects;
  20.  
  21.         public static void Play(Sounds soundEffect)
  22.         {
  23.             if (soundEffects != null)
  24.             {
  25.                 soundEffects[(int)soundEffect].Play();
  26.             }
  27.         }
  28.     }
  29. }

This code snippet, taken from a real application, shows how to play a sound that was previously loaded into memory. To focus on playing sounds, loading the sounds into an array of type SoundEffect is omitted. When the static Play method of the SoundPlayer class is called, an exception is thrown.

Exception

The exception being displayed clearly indicates the cause of the problem. You can read more about solving this particular exception on MSDN, which contains information about enabling XNA Framework Events inside Windows Phone Applications. The information is very relevant, however, it explains how you should regularly call FrameworkDispatcher.Update(). Calling this method dispatches messages that are in the XNA Framework message queue for processing. The documentation gives the advice to call FrameworkDispatcher.Update() regularly, for instance on a timer. For playing single sound effects, this seems to be an overkill. After all, using a timer means that some code will executed repeatedly (in our case even if no sound is currently played). On a battery powered device like a Windows Phone 7 this means that we are draining more battery power then necessary. Instead, I simply modified my code by adding a call to FrameworkDispatcher.Update() immediately before calling the Play method on the SoundEffect object. This works fine in the following scenario:

  • The only XNA Framework functionality used inside a Silverlight application is one or more instances of type SoundEffect.
  • Only one single SoundEffect is played at any given time.

The following code snippet shows the modified Play method of my own SoundPlayer class (which is playing sounds as expected):

  1. public static void Play(Sounds soundEffect)
  2. {
  3.     if (soundEffects != null)
  4.     {
  5.         FrameworkDispatcher.Update();
  6.         soundEffects[(int)soundEffect].Play();
  7.     }
  8. }

In an upcoming blog entry I will show you how to load a number of SoundEffects into memory using a BackgroundWorker.

About these ads
Both comments and trackbacks are currently closed.
Follow

Get every new post delivered to your Inbox.

%d bloggers like this: