windows-phone-7xnasoundeffectsoundeffectinstance

Find base SoundEffect of a SoundEffectInstance in C# WP7


WP7 suffers pretty severe performance penalties when too many sounds are played. I have an AudioManager that keeps track of SoundEffectInstances and prevents too many from playing at once.

However, some things don't require an instance and simply call Play() on a SoundEffect itself. For example, a bullet plays an impact sound when it hits something but doesn't actually need an instance.

My current system only manages Instances. What I'd like to do is see if I have an existing instance of that SoundEffect on hand that's not used and simply play it. This would require finding the SoundEffect type of a SoundEffectInstance, checking if it's played and then playing it if not. Doing this will enable me to keep track of total playing sounds more accurately.

Hopefully that makes sense and someone can point me in the right direction.


Solution

  • The important thing to decide is how you are going to manage the number of playing SoundEffectInstances at once? The obvious way is to modify your gameplay code (or levels or whatever) such that the number of playing sounds simply never grows too large.

    But if this is not acceptable you will need to enforce a hard limit somehow. And the question is: how are you going to do it? Will each sound effect have a maximum number of instances of that effect? Or will you have "sound classes" (where the class has a maximum play count)? Or just a global maximum sound count? Will the cap be enforced by preventing additional sounds from playing? Or by cutting off sounds that are already playing?

    What I would suggest is creating a wrapper object around SoundEffect that implements pretty much the same thing that SoundEffect.Play does (it internally manages a pool of SoundEffectInstances, reusing them when they are finished playing). Then add your playback cap functionality on top of it.

    So your wrapper class might look something like this:

    class MySoundEffect
    {
        SoundEffect sound;
        List<SoundEffectInstance> instances;
        int maxInstances;
    }
    

    Or perhaps like this:

    class MySoundEffect
    {
        static int[] soundClassMaximums = { 2, 2, 5, 10 };
        static int[] soundClassInstanceCount;
    
        SoundEffect sound;
        List<SoundEffectInstance> instances;
        int class;
    }
    

    And then you would use MySoundEffect everywhere you'd normally be using SoundEffect.

    Take a look at ExEn. Because it implements the internals of SoundEffect, you can possibly borrow its pooling code, which is similar to what the real XNA SoundEffect does, and then use it as a starting point for your own instance pool with your added functionality.

    There are other ways to do it, and it will depend on your architecture. But basically it is up to you to track the association between sound effects and instances. There's no way to do it in the XNA API (short of doing some nasty reflection).