In my recent Silverlight game, there are a variety of sound effects that occur from bullet fires to explosions. Most of the audio files are brief, lasting only for a second or less on average.
I had a few options — put a MediaElement directly on the UI (in XAML) and reuse each as needed, or create new MediaElements on demand. Rather than live with the artificial restrictions that would be inherent in a design which potentially limited the total number of simultaneous audio streams playing at one time, I decided on the second option — create them on demand.
Playing a supported audio file in Silverlight is easy as:
MediaElement me = new MediaElement(); me.Source = new Uri(fileName, UriKind.Relative); me.Volume = volume; me.AutoPlay = true;
Game.Sky.Children.Add(me);
Boom. Explode. The audio plays (thanks to AutoPlay–which I’ve explicitly set here though the default is true). The part that annoys me though is that once these audio files are completed, there’s no way to have them be automatically removed from the control tree. A MediaElement is a UIElement — so it’s not zero impact to leave them around. So, they build up, and build up.
My simple technique is to attach to the individual file’s CurrentStateChanged event.
public static void PlayAudio(string fileName, double volume) { MediaElement me = new MediaElement(); me.Source = new Uri(fileName, UriKind.Relative); me.Volume = volume; me.AutoPlay = true; me.CurrentStateChanged += new RoutedEventHandler(Audio_CurrentStateChanged); Game.Sky.Children.Add(me); } public static void Audio_CurrentStateChanged(object sender, RoutedEventArgs e) { if (sender is MediaElement) { MediaElement me = sender as MediaElement; if (me.CurrentState == MediaElementState.Paused) { me.CurrentStateChanged -= new RoutedEventHandler(Audio_CurrentStateChanged); Game.Sky.Children.Remove(me); } } }
In the CurrentStateChanged event handler, the code verifies that the Media is a Paused state (which happens when the media has finished playing) and then removes the UIElement from the control tree. (By the way, the Game.Sky object is a technique that I’ve used to expose globally the base UI element used throughout the game).
It’s cool that Silverlight can play WAV, MP3, and WMA files (my game uses all three types!)