Poor performance when playing songs starts in WP7
I have an XNA arcade game that is working on a Silverlight framework. The game has several sound clips that play randomly as background music.
As stated at http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.media.songcollection.aspx , the developer cannot have full control over the Media Player. In particular, developers cannot create their own collection of songs or add songs to the play queue. There is a recommendation to play songs one at a time by calling MediaPlayer.Play ().
This is exactly what I do, but every time another song starts playing I am lacking in performance. The game freezes for a moment when I call MediaPlayer.Play (), even though all sound clips are loaded during game initialization and not at runtime. This only happens on some devices (eg HTC Mozart). In contrast, if I mute the game sounds and play the same clips in the phones music player while playing the game, there are no performance issues during song change. I also have no performance issues if we play clips using the SoundEffect class. However, I really want to use MediaPlayer for background audio for two reasons: - SoundEffect does not give a notification when playback ends - SoundEffect does not seem to work with .mp3 files.and using .wav files is very expensive
I also run profiling tests that confirm that the bad runtime starts a few milliseconds after MediaPlayer.Play () and lasts for about 0.4 seconds. During this time, my game does not perform any heavy operations, just a regular game update function ().
Here are my code snippets:
public void PlayBackgroundMusic(Song song)
{
if ((!(App.Current as App).AppModel.SoundDisabled) && (song != null))
{
if (MediaPlayer.State != MediaState.Stopped)
{
StopBackgroundMusic();
}
MediaPlayer.Play(song);
}
}
public void StopBackgroundMusic()
{
MediaPlayer.Stop();
}
and the handler:
private void OnMediaStateChanged(object sender, EventArgs e)
{
if (MediaPlayer.State != MediaState.Playing)
{
if (!AppModel.SoundDisabled)
{
int index = soundRandomizer.Next(0, sounds.Length - 1);
PlayBackgroundMusic(sounds[index]);
}
}
}
Are there any suggestions?
source to share
In the end, I found a solution that I am happy with. It completely eliminates bias. Its idea is to use each MediaPlayer API on a separate thread obtained from the thread pool. I don't know how it fixes the problem, but this actually works for me:
public void PlayBackgroundMusic(Song song)
{
if ((!(App.Current as App).AppModel.SoundDisabled) && (song != null))
{
if (MediaPlayer.State != MediaState.Stopped)
{
StopBackgroundMusic();
}
ThreadPool.QueueUserWorkItem((o) =>
{
MediaPlayer.Play(song);
}
}
}
public void StopBackgroundMusic()
{
ThreadPool.QueueUserWorkItem((o) =>
{
MediaPlayer.Stop();
}
}
source to share