Playing sound FX for a game

public static final int SOUND_EXPLOSION = 1;

private SoundPool soundPool;
private HashMap<Integer, Integer> soundPoolMap;

private void initSounds() {
     soundPool = new SoundPool(4, AudioManager.STREAM_MUSIC, 100);
     soundPoolMap = new HashMap<Integer, Integer>();
     soundPoolMap.put(SOUND_EXPLOSION, soundPool.load(getContext(), R.raw.explosion, 1));
}
          
public void playSound(int sound) {
    /* Updated: The next 4 lines calculate the current volume in a scale of 0.0 to 1.0 */
    AudioManager mgr = (AudioManager)getContext().getSystemService(Context.AUDIO_SERVICE);
    float streamVolumeCurrent = mgr.getStreamVolume(AudioManager.STREAM_MUSIC);
    float streamVolumeMax = mgr.getStreamMaxVolume(AudioManager.STREAM_MUSIC);    
    float volume = streamVolumeCurrent / streamVolumeMax;
    
    /* Play the sound with the correct volume */
    soundPool.play(soundPoolMap.get(sound), volume, volume, 1, 0, 1f);     
}

public void explode() {
    playSound(SOUND_EXPLOSION);
} 

7 Comments

#
Yoni Samlan - April 20, 2009 at 6:21 p.m.

There's a lot of code like this I keep seeing that involves setting the soundpool volume incorrectly. The R/L channel volumes should be numbers between 0.0 and 1.0, *NOT* the integer scaled audio stream volume (typically an integer between 1-25, depending on the number of steps set up). (See http://www.mail-archive.com/android-developers@googlegroups.com/msg12286.html ).

Besides potential bad things happening, the volume coming out of your soundpool will pretty much always be too loud if you don't scale 0.0 - 1.0 for your values. Plus, if they ever start actually checking value ranges in a future supported SDK release, this will give an error.

#
sissi - April 20, 2009 at 8:22 p.m.

Re: Yoni Samlan. Thanks for the info about not setting the volume correctly! I've updated the code and think the current revision should work. What do you think?

#
Yoni Samlan - April 21, 2009 at 9:06 p.m.

Looks good :)
A performance-tweaker's note, btw: If you want to use a mapping to track samples to SoundPool identifiers, I'd either just use a normal int[] whose indexes correspond to your samples' IDs, or a SparseArray: http://developer.android.com/reference/android/util/SparseArray.html .
Doesn't matter much in this exact example, but could make a difference if you're writing a game with lots of audio events (requiring lookups) and where samples get pushed in and out of the pool frequently (requiring Object creation). HashMaps in Dalvik are slooow, and you need to create Integers all over the place when you could just be working with ints. There's more at http://developer.android.com/guide/practices/design/performance.html#object_creation .

#
Lim Thye Chean - August 2, 2009 at 10:38 a.m.

I am currently using MediaPlayer for all the sound effects in my game Space War, and except for sound delay in Android 1.1, this works fine for 1.5. What's the advantage of switching over to SoundPool?

Thanks.

#
mbt shoes sale - January 28, 2010 at 12:02 a.m.

Code looks great to me. Thanks for sharing.

#
Ariat Boots - February 19, 2010 at 4:10 p.m.

Works great. Thanks

#
mbt shoes - March 2, 2010 at 4:38 p.m.

have a good day,

Add a Comment