Shawn beat me to the punch and did this great post on the changes to the SoundEffect API in XNA GS 3.1.  Here’re some tips if you’re trying to migrate your 3.0 code to the new release.

“Fire and Forget” Playback

  • SoundEffect.Play methods are now exclusively for “Fire and Forget” sounds. Instead of returning a SoundEffectInstance they’ll return a bool – “true” for successful playback and “false” instead of throwing the InstancePlayLimitException. XNA Framework will dispose these sounds as soon as they’re done playing. 
// this will play a 2D fire and forget sound effect with default
// volume, pitch and pan
SoundEffect effect = Content.Load<SoundEffect>(“GameSoundEffect”);
bool effectPlayed = effect.Play();
 
// This will play a 2D fire and forget sound effect with specified volume, pitch and pan
bool effectPlayed = effect.Play(0.8f, 1.0f, 0.0f);
  • You can only playback 2D, non-looping sounds using this “fire and forget” mechanism. For everything else – there’s “Create, Configure and Play”.

“Create, Configure and Play”

  • The SoundEffect.CreateInstance method returns a SoundEffectInstance object. The lifetime of this instance is completely controlled by the game. In other words you need to call Dispose on the instance returned by this method when you’re done with it. The usage pattern is -
    1. Create a SoundEffectInstance by calling SoundEffect.CreateInstance.
    2. Configure the SoundEffectInstance by setting all the properties. As you’ll notice, some of these properties are locked into place once you call Play.
    3. Call SoundEffectInstance.Play.
    4. When you’re done with the sound, call SoundEffectInstance.Dispose.

    // game controls the lifetime of the sound effect instance 
    SoundEffect effect = Content.Load< SoundEffect>(“GameSoundEffect”);
    SoundEffectInstance instance = effect.CreateInstance();
    instance.Play();
    instance.Dispose();

  • All SoundEffect.Play3D methods have been deprecated. Instead, game can now configure the SoundEffectInstance object returned by the SoundEffect.CreateInstance method for 2D/3D positioning and looping before playback. This configuration is locked into place on the first Play call made on the instance.
    • By default all instances are created as 2D non-looping sound effects.
// this will play a 2D non-looping sound effect
SoundEffect effect = Content.Load<SoundEffect>(“GameSoundEffect”);
SoundEffectInstance instance = effect.CreateInstance();
instance.Play(); 
    • Calling Apply3D on a SoundEffectInstance before calling Play configures it as a 3D positioned sound.
// this will play a 3D positioned non-looping sound effect
SoundEffect effect = Content.Load<SoundEffect>(“GameSoundEffect”);
SoundEffectInstance instance = effect.CreateInstance();
instance.Apply3D(listener, emitter);
instance.Play();
    • Setting the “IsLooped” property before calling Play configures the instance as a looping sound.
// this will play a 2D looping sound effect
SoundEffect effect = Content.Load<SoundEffect>(“GameSoundEffect”);
SoundEffectInstance instance = effect.CreateInstance();
instance.IsLooped = true;
instance.Play();
// this will play a 3D positioned looping sound effect
SoundEffect effect = Content.Load<SoundEffect>(“GameSoundEffect”);
SoundEffectInstance instance = effect.CreateInstance();
instance.IsLooped = true;
instance.Apply3D(listener, emitter);
instance.Play();
    • If you call both Pan and Apply3D (why would you do that?) the last call wins and determines if the sound is configured as a 2D or 3D positioned.
// this will play a 2D positioned looping sound effect.
// setting the Pan in this case overrides Apply3D.
SoundEffect effect = Content.Load<SoundEffect>(“GameSoundEffect”);
SoundEffectInstance instance = effect.CreateInstance();
instance.IsLooped = true;
instance.Apply3D(listener, emitter);
instance.Pan = 1.0f;
instance.Play();

Helper Extension Class

Here’s a helper class that may ease the pain of moving your code to the new world order.  Remember though, this is a helper for “Create and Configure” playback so you still need to explicitly dispose the instance when you’re done.

public static class SoundEffectExtensions
{
    public static SoundEffectInstance Play3D(this SoundEffect effect, AudioListener listener, AudioEmitter emitter)
    {
        return Play3D(effect, listener, emitter, 1f, 0f, false);
    }
 
    public static SoundEffectInstance Play3D(this SoundEffect effect, AudioListener listener, AudioEmitter emitter, float volume, float pitch, bool loop)
    {
        return Play3D(effect, new AudioListener[] { listener }, emitter, volume, pitch, loop);
    }
 
    public static SoundEffectInstance Play3D(this SoundEffect effect, AudioListener [] listeners, AudioEmitter emitter, float volume, float pitch, bool loop)
    {
        SoundEffectInstance instance = effect.CreateInstance();
        instance.Volume = volume;
        instance.Pitch = pitch;
        instance.IsLooped = loop;
        instance.Apply3D(listeners, emitter);
        instance.Play();
        return instance;
    }
 
    public static SoundEffectInstance Play2D(this SoundEffect effect)
    {
        return Play2D(effect, 1f, 0f, 0f, false);
    }
 
    public static SoundEffectInstance Play2D(this SoundEffect effect, float volume)
    {
        return Play2D(effect, volume, 0f, 0f, false);
    }
 
    public static SoundEffectInstance Play2D(this SoundEffect effect, float volume, float pitch, float pan, bool loop)
    {
        SoundEffectInstance instance = effect.CreateInstance();
        instance.Volume = volume;
        instance.Pitch = pitch;
        instance.Pan = pan;
        instance.IsLooped = loop;
        instance.Play();
        return instance;
    }
}