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
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.
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?
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 .
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.
Code looks great to me. Thanks for sharing.
Works great. Thanks
have a good day,
Add a Comment