0

I've been trying to pin down an annoying performance bug in my C# 2d game engine.

It only occurs when I have sound enabled, and I am trying to figure out what I am doing wrong. I suspect multiple things, since the sound functionality was implemented quite a while ago to achieve basic functionality. At this stage in development it is now a higher priority. I need to resolve it.

When I implemented sound it was after much experimentation with sound APIs. I tried SoundPlayer, MediaPlayer, and WindowsMediaPlayer - with the latter the only one I could get working in an acceptable manner.

My implementation was based around setting up an array of players for each sound I wanted to play. They are all instantiated up-front. The method by which they are used is:

  1. Search through player array until you find one which isn't currently playing.

  2. Play the sound.

Now for some reason, which I can't figure out, this implementation is causing a wierd problem. I have a method which fires when you die, and from what I can tell this does NOTHING with sound whatsoever. It basically waits 5 seconds before restarting the game. But with sound on the screen flickers for a millisecond, something in sharpdevelop refreshes, and it's as if there is a sudden lag in the game. From a functionality point of view I don't have a problem - but the performance is unacceptable.

To give you an idea of what I'm doing, here is some code from my sound initialisation method:

                if(soundLibrary=="WindowsMediaPlayer")
            {    

                // Music player
                WMP_Music = new WMPLib.WindowsMediaPlayer();
                WMP_Music.settings.autoStart = false;
                WMP_Music.URL = "D:\\Programming\\SFX\\MUSIC\\IN_GAME_1.wav";

                // Array of players ----------------------------------------
                WMP_EATEN_GHOST_Array = new WMPLib.WindowsMediaPlayer[EATEN_GHOST_noOfPlayers];
                WMP_EATEN_PILL_Array = new WMPLib.WindowsMediaPlayer[EATEN_PILL_noOfPlayers];
                WMP_EATEN_POWERPILL_Array = new WMPLib.WindowsMediaPlayer[EATEN_POWERPILL_noOfPlayers];
                WMP_KILLED_BY_GHOST_Array = new WMPLib.WindowsMediaPlayer[KILLED_BY_GHOST_noOfPlayers];    

                for(int i=0;i<WMP_EATEN_GHOST_Array.Length;i++)
                {
                    WMP_EATEN_GHOST_Array[i] = new WMPLib.WindowsMediaPlayer();
                    WMP_EATEN_GHOST_Array[i].settings.autoStart = false;
                    WMP_EATEN_GHOST_Array[i].URL = "D:\\Programming\\SFX\\EATEN_GHOST\\Hit_55.wav";


                    WMP_EATEN_PILL_Array[i] = new WMPLib.WindowsMediaPlayer();
                    WMP_EATEN_PILL_Array[i].settings.autoStart = false;
                    WMP_EATEN_PILL_Array[i].URL = "D:\\Programming\\SFX\\EATEN_PILL\\Hit_43_s.wav";


                    WMP_EATEN_POWERPILL_Array[i] = new WMPLib.WindowsMediaPlayer();
                    WMP_EATEN_POWERPILL_Array[i].settings.autoStart = false;
                    WMP_EATEN_POWERPILL_Array[i].URL = "D:\\Programming\\SFX\\EATEN_POWERPILL\\Hit_49.wav";


                    WMP_KILLED_BY_GHOST_Array[i] = new WMPLib.WindowsMediaPlayer();
                    WMP_KILLED_BY_GHOST_Array[i].settings.autoStart = false;
                    WMP_KILLED_BY_GHOST_Array[i].URL = "D:\\Programming\\SFX\\KILLED_BY_GHOST\\Hit_55.wav";

                }

So with these set up, here's the code which plays the sound:

        public void PlayPCM_WindowsMediaPlayer_FX(string effectIn)
    {
        int i=-1;
        bool found = false;

        if(soundEnabled)
        {
            switch(effectIn)
            {
                case "KILLED_BY_GHOST":
                    // 1.   Choose a media player which is not playing.
                    i = 0;
                    do
                    {
                        if(WMP_KILLED_BY_GHOST_Array[i].playState == WMPLib.WMPPlayState.wmppsPlaying)
                        {
                            // Keep looking
                            i++;
                        }
                        else
                        {
                            found = true;
                        }
                    } while( (i<WMP_KILLED_BY_GHOST_Array.Length) && (!found));
                    // Now 'i' holds the index of the player which is not playing.

                    // 2.   Play effect                 
                    if(found)
                    {
                        Thread thread = new Thread(new ThreadStart( WMP_KILLED_BY_GHOST_Array[i].controls.play ));
                        thread.Start();

                    }
                    break;

                case "EATEN_PILL":
                    // 1.   Choose a media player which is not playing.
                    i = 0;
                    do
                    {
                        if(WMP_EATEN_PILL_Array[i].playState == WMPLib.WMPPlayState.wmppsPlaying)
                        {
                            // Keep looking
                            i++;
                        }
                        else
                        {
                            found = true;
                        }
                    } while( (i<WMP_EATEN_PILL_Array.Length) && (!found));
                    // Now 'i' holds the index of the player which is not playing.

                    // 2.   Play effect 
                    if(found)
                    {                   

                        Thread thread = new Thread(new ThreadStart( WMP_EATEN_PILL_Array[i].controls.play ));
                        thread.Start();

                    }

                    break;
                case "EATEN_GHOST":
                    // 1.   Choose a media player which is not playing.
                    i = 0;
                    do
                    {
                        if(WMP_EATEN_GHOST_Array[i].playState == WMPLib.WMPPlayState.wmppsPlaying)
                        {
                            // Keep looking
                            i++;
                        }
                        else
                        {
                            found = true;
                        }
                    } while( (i<WMP_EATEN_GHOST_Array.Length) && (!found));
                    // Now 'i' holds the index of the player which is not playing.

                    // 2.   Play effect                 
                    if(found)
                    {
                        Thread thread = new Thread(new ThreadStart( WMP_EATEN_GHOST_Array[i].controls.play ));
                        thread.Start();

                    }
                    break;
                case "EATEN_POWERPILL":
                    // 1.   Choose a media player which is not playing.
                    i = 0;
                    do
                    {
                        if(WMP_EATEN_POWERPILL_Array[i].playState == WMPLib.WMPPlayState.wmppsPlaying)
                        {
                            // Keep looking
                            i++;
                        }
                        else
                        {
                            found = true;
                        }
                    } while( (i<WMP_EATEN_POWERPILL_Array.Length) && (!found));
                    // Now 'i' holds the index of the player which is not playing.

                    // 2.   Play effect                 
                    if(found)
                    {
                        Thread thread = new Thread(new ThreadStart( WMP_EATEN_POWERPILL_Array[i].controls.play ));
                        thread.Start();

                    }
                    break;
            } // switch
        } // soundEnabled
    }       

It's pretty clunky I know, but it worked at the time - well enough anyway. Can anyone see anything which would explain why I get a screen flicker?

My threading expertise is really basic at the moment.

Thanks in advance

CdrTomalak
  • 479
  • 1
  • 4
  • 15
  • 1
    I would guess at a utility power grid brown-out from you creating this many WMP instances. It is *not* a cheap component. Doesn't like threading at all either. Get ahead with an audio library designed for game use, there are many to chose from. – Hans Passant Jan 26 '14 at 19:39
  • Thanks Hans. This was really a go at using something which worked. I had a go with NAudio, Xaudio2, and felt they were also too heavyweight. Can you recommend an API? Clearly I'm doing something silly here. – CdrTomalak Jan 26 '14 at 20:31

0 Answers0