Playing sound FX for a game

3 votes · 7 comments

Playing sound FX for a game with android.media.SoundPool.

This code loads only one sound, but you can use as many as you want. Put them as mp3 in the directory /res/raw.

raw ·
copy
· download
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); }
Add a comment

7 Comments

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.

Reply · April 20, 2009, 11:21 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?

Reply · April 21, 2009, 1:22 a.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 .

Reply · April 22, 2009, 2:06 a.m.

perfect blog to visit...http://www.bulksupplementsdirect.co.uk/khxc/Mega-white-and-green-tea-extract.html

Reply · Aug. 14, 2011, 3:25 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.

Reply · Aug. 2, 2009, 3:38 p.m.

Works as a charm! thanks :)

Reply · April 28, 2011, 8:16 p.m.

I use this method to store 100 sounds, but this increases the app's load time substantially, even though the soundpool loads on a seperate thread. Is there a quicker way / better way to decode and load them?

public void initSounds()

{ soundPool = new SoundPool(2, AudioManager.STREAM_MUSIC, 0); soundPoolMap = new HashMap(); Log.i("Initialising Sounds ------ > ",""+soundPool.toString() );

Class raw = R.raw.class;
Field[] fields = raw.getFields();

Context con  = GlobalVars.ACTIVITY_1.getApplicationContext();

for (int i = 1; i < 101; i++)
{
    try
    {
        int id = fields[i].getInt(null);
        soundPoolMap.put(i, soundPool.load(con, id, 1));
    }
    catch (IllegalAccessException e)
    {
        Log.e("REFLECTION", String.format("%s threw IllegalAccessException.", fields[i].getName()));
    }
}

}

Reply · May 18, 2011, 10:01 p.m.

Thanks!

Reply · Nov. 22, 2014, 11:43 p.m.