0

Essentially I have a sound effect which is played when two items collide in my game. Some of the items are quite close to each other so the sound effect may have to be played it quick succession.

Using SoundEffect.Play() this works. However to save on Garbage collection I want to use an instance. Unfortunately this means that an instance won't play until the last one has finished playing. This isnt the effect I was after. Is there any way to over-write this functionality or will I have to go back to plain old SoundEffect?

Andrew Russell
  • 26,924
  • 7
  • 58
  • 104
dannybrown
  • 1,083
  • 3
  • 13
  • 26
  • possible duplicate of [Repeating sound from one Instance](http://stackoverflow.com/questions/8994292/repeating-sound-from-one-instance) – Dour High Arch May 08 '14 at 01:59

2 Answers2

1

Is there any reason why you want to "save on Garbage collection?" Unless you start running into actual performance problems, there's most likely no need to be worrying about it. From personal experience, you can play at least a dozen sounds in quick succession (using SoundEffect.Play()) without any issues. However, if you feel your game has lots of collisions, there are two things you can do:

First, consider creating a simple SoundPlayer class that handles all the sounds you play, and whenever you detect more than about 10 playing simultaneously, prevent the next one from being played. It's not like a player would notice missing sounds if there are lots of collisions taking place.

Second, take a look here (http://forums.create.msdn.com/forums/t/91165.aspx) on how to use DynamicSoundEffectInstance to premix sounds. This is a fair bit more complicated, but by looking ahead and mixing all the sounds that are about to play into a single buffer, you'll pretty much guarantee zero lag, because there is only one sound (or one audio stream buffer) effectively playing.

Stephane Beniak
  • 181
  • 1
  • 1
  • 7
  • Ah, if there is no simple way to do it its probably fine. Its impossible to have 10 or more collisions at once in my game, So I shall leave it how it is with a normal SoundEffect.Play(); Thanks for the thoughts. – dannybrown Mar 11 '12 at 16:34
0
List<SoundEffectInstance> explosionSoundInstanceList; 


        explosionSound = Content.Load<SoundEffect>("sound/explosion");

        explosionSoundInstanceList = new List<SoundEffectInstance>(MAX_EXPLOSIONS);

        for (int i = 0; i < MAX_EXPLOSIONS; i++)
        {
            explosionSoundInstanceList.Add(explosionSound.CreateInstance());
        }



 private void PlayExplosionSound(float volume, float pitch, float pan)
    {

        ClampSoundValues(ref volume, ref pitch, ref pan);

        for (int i = 0; i < explosionSoundInstanceList.Count; i++)
        {
            if (explosionSoundInstanceList[i].State == SoundState.Stopped)
            {
                explosionSoundInstanceList[i].Volume = volume / (i+1);
                explosionSoundInstanceList[i].Pitch = pitch;
                explosionSoundInstanceList[i].Pan = pan;
                explosionSoundInstanceList[i].Play();
                return;
            }

        }

        return;
    }

Works okay. Zero garbage on the 360 after instantiation. Will just elegantly fail after you hit the limit.

That's what I use.

I clamp the values thusly

    private static void ClampSoundValues(ref float volume, ref float pitch, ref float pan)
    {
        volume = MathHelper.Clamp(volume, -1f, 1f);
        pitch = MathHelper.Clamp(pitch, -1f, 1f);
        pan = MathHelper.Clamp(pan, -1f, 1f);
    }

As setting a foolish value will drop an exception.

twobob
  • 354
  • 8
  • 22