Using SoundPool instead of MediaPlayer

All your problems with Audio, Video and Images.

Using SoundPool instead of MediaPlayer

Postby rbgrn » Sat Oct 11, 2008 6:08 pm

I'm adding sound into my game now and need the ability to have sound effects concurrent (like 2 of the same explosion playing at the same time, etc) so using the MediaPlayer is less than optimal for me. I was thinking of just adding a traditional sound update into the main loop which would probably work and isn't _that_ hard to write but I don't think I have access to the decoder and sound buffer.

I found a class called SoundPool that appears to be suited for exactly what I'm trying to do however the documentation is very weak - http://code.google.com/android/referenc ... dPool.html

Has anyone used this with success? If so, could I see a little code snippet?

I tried this:
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.  
  2.                 private void initSounds() {
  3.  
  4.                         // 4 streams
  5.  
  6.                         // stream type 3 is music
  7.  
  8.                         soundPool = new SoundPool(4, 3, 100);
  9.  
  10.                         int explosionSound = soundPool.load(getContext(), R.raw.explosion, 1);
  11.  
  12.                         soundPool.play(explosionSound, 100, 100, 1, 0, 1);
  13.  
  14.                 }
  15.  
  16.  
Parsed in 0.031 seconds, using GeSHi 1.0.8.4


but it didn't appear to do anything. I didn't get errors but I also heard no sound. Perhaps I need to configure something for the emulator to work like that?
Last edited by rbgrn on Sun Oct 12, 2008 5:57 am, edited 1 time in total.
rbgrn
Junior Developer
Junior Developer
 
Posts: 11
Joined: Sat Oct 11, 2008 6:03 pm

Top

Postby rbgrn » Sat Oct 11, 2008 11:27 pm

I figured it out. Here's how I'm doing my sound FX for my game:

This only loads one sound but you can load as many as you want. I have an mp3 in my res/raw directory called explosion.mp3.

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.  
  2.          public static final int SOUND_EXPLOSION = 1;
  3.  
  4.                 public static final int SOUND_YOU_WIN = 2;
  5.  
  6.                 public static final int SOUND_YOU_LOSE = 3;
  7.  
  8.  
  9.  
  10.          private SoundPool soundPool;
  11.  
  12.                 private HashMap<Integer, Integer> soundPoolMap;
  13.  
  14.                
  15.  
  16.                 private void initSounds() {
  17.  
  18.                         soundPool = new SoundPool(4, AudioManager.STREAM_MUSIC, 100);
  19.  
  20.                         soundPoolMap = new HashMap<Integer, Integer>();
  21.  
  22.                         soundPoolMap.put(SOUND_EXPLOSION, soundPool.load(getContext(), R.raw.explosion, 1));
  23.  
  24.                 }
  25.  
  26.                
  27.  
  28.                 public void playSound(int sound) {
  29.  
  30.                         AudioManager mgr = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
  31.  
  32.                         int streamVolume = mgr.getStreamVolume(AudioManager.STREAM_MUSIC);
  33.  
  34.                         soundPool.play(soundPoolMap.get(sound), streamVolume, streamVolume, 1, 0, 1f);
  35.  
  36.                 }
  37.  
  38.  
  39.  
  40.           public void update() {
  41.  
  42.                if (isExploding()) {
  43.  
  44.                      playSound(SOUND_EXPLOSION);
  45.  
  46.                }
  47.  
  48.           }
  49.  
  50.  
Parsed in 0.035 seconds, using GeSHi 1.0.8.4
rbgrn
Junior Developer
Junior Developer
 
Posts: 11
Joined: Sat Oct 11, 2008 6:03 pm

Postby ninor » Sun Oct 12, 2008 12:35 am

Thanks for sharing! :)
I'll post this as a snippet in its own section (with proper credit to you)
Image AndDev: Your Android Development Community / Tutorials | Here's my Basic ToolKit
User avatar
ninor
Moderator
Moderator
 
Posts: 180
Joined: Thu Aug 14, 2008 6:30 pm
Location: Barcelona, Spain

Postby rbgrn » Sun Oct 12, 2008 2:11 am

This is actually very frustrating. There seems to be a few bugs with SoundPool.

Bug #1) Looping an mp3 crashes around the 8th loop but looping waves seems to work fine.
Bug #2) SoundPool.stop(streamId) immediately crashes the app.

pause seems to work but I'm not sure how to workaround the stop() issue right now.
rbgrn
Junior Developer
Junior Developer
 
Posts: 11
Joined: Sat Oct 11, 2008 6:03 pm

Postby rbgrn » Sun Oct 12, 2008 6:00 am

More bugs and other weird workarounds I've discovered.

SoundPool works fairly well if you need high performance sound streams but it really is sensitive and riddled with bugs.

The newest bug I've found:

setRate() with a rate over 1.5 either doesn't work or also crashes the VM with no exception.

My new workaround for lack of stop():

to stop a stream, call setLoop(streamId, 0) then setVolume(streamId, 0f, 0f). This will stop a loop after it's done but drop the volume so it seems to the user to have quit right then. After that, you don't need to call stop() because the stream will clean itself up from the loop stopping. This worked for me.
rbgrn
Junior Developer
Junior Developer
 
Posts: 11
Joined: Sat Oct 11, 2008 6:03 pm

Postby MrSnowflake » Sun Oct 12, 2008 12:32 pm

Thanks for these reports, but definately don't for get to report them to the googlecode android site!

[edit]I just looked over the docs of SoundPool and sinds non of the methods have comments, it's not supposed to work. I hope you realised it before you began diggin in to it :). But still good, you could get it to work.
User avatar
MrSnowflake
Moderator
Moderator
 
Posts: 1439
Joined: Sat Feb 16, 2008 3:11 pm
Location: Flanders, Belgium

Top

Postby rbgrn » Sun Oct 12, 2008 5:27 pm

Even if they haven't readied it for public use, it's the only suitable API for sound in games. I looked into using MediaPlayers but if you have more than a couple of sounds and you need to be able to play the same sound a few times concurrently, it's just not a feasible solution.

I'm really surprised that there is no access to the audio buffer. How are we supposed to write dynamic audio generation apps?

Android really needs 2 things to be competitive with the audio side:

1) Public access to the media decoders (so a dev can decode an mp3 into raw)
2) Public access to a sound stream output buffer (so a dev can pipe in raw sound data)
rbgrn
Junior Developer
Junior Developer
 
Posts: 11
Joined: Sat Oct 11, 2008 6:03 pm

Postby rbgrn » Sun Oct 12, 2008 6:43 pm

MrSnowflake wrote:Thanks for these reports, but definately don't for get to report them to the googlecode android site!

[edit]I just looked over the docs of SoundPool and sinds non of the methods have comments, it's not supposed to work. I hope you realised it before you began diggin in to it :). But still good, you could get it to work.


I think it'd be strange to leave a class in the API but not document it and claim that it's not supported because it's not documented. IMO if it's in a public package (like java.lang or android.media) it's a public API regardless of how poor the documentation is. It's certainly listed as added in the .9-m5 changelist.

I posted everything I found on the android google code site. I really hope they don't remove it in the next release because MediaPlayers really don't do the same job!
rbgrn
Junior Developer
Junior Developer
 
Posts: 11
Joined: Sat Oct 11, 2008 6:03 pm

Postby ninor » Sun Oct 12, 2008 7:25 pm

Thanks for sharing all your findings.
This thread is now linked from the snippet.

Snippet

·
Image AndDev: Your Android Development Community / Tutorials | Here's my Basic ToolKit
User avatar
ninor
Moderator
Moderator
 
Posts: 180
Joined: Thu Aug 14, 2008 6:30 pm
Location: Barcelona, Spain

Postby MrSnowflake » Mon Oct 13, 2008 12:05 am

rbgrn wrote:I think it'd be strange to leave a class in the API but not document it and claim that it's not supported because it's not documented. IMO if it's in a public package (like java.lang or android.media) it's a public API regardless of how poor the documentation is. It's certainly listed as added in the .9-m5 changelist.
i think you're right but Google don't think so :).

I don't think SoundPool will be removed as it should be now te final api.
User avatar
MrSnowflake
Moderator
Moderator
 
Posts: 1439
Joined: Sat Feb 16, 2008 3:11 pm
Location: Flanders, Belgium

Postby ninor » Mon Oct 13, 2008 1:42 am

Let's hope that as soon as the first device goes to the streets they release 1.0r2 or 1.1r1, with a lot of fixed and properly documented code..
Image AndDev: Your Android Development Community / Tutorials | Here's my Basic ToolKit
User avatar
ninor
Moderator
Moderator
 
Posts: 180
Joined: Thu Aug 14, 2008 6:30 pm
Location: Barcelona, Spain

Postby rbgrn » Mon Oct 13, 2008 2:52 am

I have a friend that's a google employee and so I tried my game on a real G1 today and it's safe to say that this technique does certainly work. I did have a weird crash happen sometime into the game but it seemed to work well up until that point.
rbgrn
Junior Developer
Junior Developer
 
Posts: 11
Joined: Sat Oct 11, 2008 6:03 pm

Postby ninor » Mon Oct 13, 2008 2:50 pm

Great!
Image AndDev: Your Android Development Community / Tutorials | Here's my Basic ToolKit
User avatar
ninor
Moderator
Moderator
 
Posts: 180
Joined: Thu Aug 14, 2008 6:30 pm
Location: Barcelona, Spain

Still can't get SoundPool to work

Postby g1bb » Sun Nov 09, 2008 3:32 am

Hello,

Java is not my fluent language, so please bear with me ;)

I've tried the following code after seeing the snippet here, and I can't seem to get this to work. Here's what I have:

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. public class OneShotAlarm extends BroadcastReceiver
  2.  
  3. {
  4.  
  5.         private SoundPool soundPool;
  6.  
  7.          private HashMap<Integer, Integer> soundPoolMap;
  8.  
  9.          
  10.  
  11.     @Override
  12.  
  13.     public void onReceive(Context context, Intent intent)
  14.  
  15.     {
  16.  
  17.          soundPool = new SoundPool(4, AudioManager.STREAM_MUSIC, 100);
  18.  
  19.          soundPoolMap = new HashMap<Integer, Integer>();
  20.  
  21.          soundPoolMap.put(1, soundPool.load(context, R.raw.sound1, 1));
  22.  
  23.        
  24.  
  25.         AudioManager mgr = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
  26.  
  27.         int streamVolume = mgr.getStreamVolume(AudioManager.STREAM_MUSIC);
  28.  
  29.         soundPool.play(soundPoolMap.get(1), streamVolume, streamVolume, 1, 0, 1f);
  30.  
  31.     }
  32.  
  33. }
Parsed in 0.037 seconds, using GeSHi 1.0.8.4


You'll notice I replaced instaces of 'getContext()' with 'Context', as 'getContext()' doesn't seem to be available from where I have this code.

Here is my LogCat that's being returned, and no sound is being played:
11-08 19:25:23.679: DEBUG/dalvikvm(1822): Trying to load lib /system/lib/libsoundpool.so 0x0
11-08 19:25:23.759: DEBUG/dalvikvm(1822): Added shared lib /system/lib/libsoundpool.so 0x0
11-08 19:25:23.819: WARN/SoundPool(1822): sample 1 not READY

Any ideas on this? I've been pulling my hair out all day messing with MediaPlayer, then I came across SoundPool and it looks great!

Thanks in advance.
g1bb
Freshman
Freshman
 
Posts: 2
Joined: Fri Nov 07, 2008 3:12 pm

Re: Still can't get SoundPool to work

Postby g1bb » Mon Nov 10, 2008 4:49 pm

g1bb wrote:Hello,

Java is not my fluent language, so please bear with me ;)

I've tried the following code after seeing the snippet here, and I can't seem to get this to work. Here's what I have:

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. public class OneShotAlarm extends BroadcastReceiver
  2. {
  3.         private SoundPool soundPool;
  4.          private HashMap<Integer, Integer> soundPoolMap;
  5.          
  6.     @Override
  7.     public void onReceive(Context context, Intent intent)
  8.     {
  9.          soundPool = new SoundPool(4, AudioManager.STREAM_MUSIC, 100);
  10.          soundPoolMap = new HashMap<Integer, Integer>();
  11.          soundPoolMap.put(1, soundPool.load(context, R.raw.sound1, 1));
  12.        
  13.         AudioManager mgr = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
  14.         int streamVolume = mgr.getStreamVolume(AudioManager.STREAM_MUSIC);
  15.         soundPool.play(soundPoolMap.get(1), streamVolume, streamVolume, 1, 0, 1f);
  16.     }
  17. }
Parsed in 0.037 seconds, using GeSHi 1.0.8.4


You'll notice I replaced instaces of 'getContext()' with 'Context', as 'getContext()' doesn't seem to be available from where I have this code.

Here is my LogCat that's being returned, and no sound is being played:
11-08 19:25:23.679: DEBUG/dalvikvm(1822): Trying to load lib /system/lib/libsoundpool.so 0x0
11-08 19:25:23.759: DEBUG/dalvikvm(1822): Added shared lib /system/lib/libsoundpool.so 0x0
11-08 19:25:23.819: WARN/SoundPool(1822): sample 1 not READY

Any ideas on this? I've been pulling my hair out all day messing with MediaPlayer, then I came across SoundPool and it looks great!

Thanks in advance.


Got help with this. See this link for reference: http://groups.google.com/group/android- ... 2d3bc57537
g1bb
Freshman
Freshman
 
Posts: 2
Joined: Fri Nov 07, 2008 3:12 pm

Top
Next

Return to Multimedia Problems

Who is online

Users browsing this forum: No registered users and 13 guests