Here's an example for managing sounds that will be played many times
(like gunshots, explosions, clicks, etc) using a pool and then sounds
that are just one-offs, like an announcer or an intro sound.

public class MediaPlayerPool {
        private static final String TAG = "MediaPlayerPool";

        private Context context;
        private int streamType;

        private HashMap<Integer, ArrayList<MediaPlayer>> pools;

        public MediaPlayerPool(Context context, int streamType) {
                this.context = context;
                this.streamType = streamType;
                pools = new HashMap<Integer, ArrayList<MediaPlayer>>();
        }

        public boolean hasMedia(int resourceId) {
                return pools.keySet().contains(resourceId);
        }

        public void addMedia(int resourceId, int poolSize) {
                ArrayList<MediaPlayer> pool = pools.get(resourceId);
                if (pool == null) {
                        pool = new ArrayList<MediaPlayer>();
                }
                for (int i = 0; i < poolSize; i++) {
                        pool.add(createMediaPlayer(resourceId));
                }
                pools.put(resourceId, pool);
        }

        public void playMedia(int resourceId) {
                ArrayList<MediaPlayer> pool = pools.get(resourceId);
                MediaPlayer player = null;
                if (pool.size() > 0) {
                        player = pool.remove(0);
                }
                if (player == null) {
                        Log.e(TAG, "Pool is empty for resource " + resourceId);
                } else {
                        player.start();
                }
        }

        public void release() {
                for (Integer key : pools.keySet()) {
                        ArrayList<MediaPlayer> pool = pools.get(key);
                        for (MediaPlayer player : pool) {
                                if (player.isPlaying()) {
                                        player.stop();
                                }
                                player.release();
                        }
                        pool.clear();
                }
                pools.clear();
        }

        private MediaPlayer createMediaPlayer(final int resourceId) {
                MediaPlayer mp = MediaPlayer.create(context, resourceId);
                mp.setOnCompletionListener(new 
MediaPlayer.OnCompletionListener() {
                        public void onCompletion(MediaPlayer player) {
                                player.seekTo(0);
                                returnToPool(resourceId, player);
                        }
                });
                mp.setAudioStreamType(streamType);
                return mp;
        }

        private void returnToPool(int resourceId, MediaPlayer player) {
                ArrayList<MediaPlayer> pool = pools.get(new 
Integer(resourceId));
                pool.add(player);
        }
}

public class MediaPlayerSoundManager {
        private static final String TAG = "MediaPlayerSoundManager";

        private Context context;
        private MediaPlayerPool pool;
        private HashMap<Integer, Integer> soundResourceMap;

        public MediaPlayerSoundManager(Context context) {
                this.context = context;
                this.pool = new MediaPlayerPool(context, 
AudioManager.STREAM_MUSIC);
                this.soundResourceMap = new HashMap<Integer, Integer>();
        }

        public void init() {
                release();
                pool.addMedia(R.raw.sound_1, 2);
                soundResourceMap.put(SOUND_1, R.raw.sound_1);
        }

        public void playSound(int soundId) {
                int resourceId = getResourceId(soundId);
                if (pool.hasMedia(resourceId)) {
                        pool.playMedia(resourceId);
                } else {
                        playOneShotSound(resourceId);
                }
        }

        private int getResourceId(int soundId) {
                Integer resourceId = soundResourceMap.get(soundId);
                if (resourceId == null) {
                        Log.e(TAG, "No resource found for soundId " + soundId);
                }
                return resourceId;
        }

        private void playOneShotSound(int resourceId) {
                MediaPlayer mp = MediaPlayer.create(context, resourceId);
                mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
                mp.start();
                mp.setOnCompletionListener(new 
MediaPlayer.OnCompletionListener() {
                        public void onCompletion(MediaPlayer arg0) {
                                arg0.release();
                        }
                });
        }

        public void release() {
                pool.release();
                soundResourceMap.clear();
        }
}

On Nov 10, 10:04 pm, plusminus <[EMAIL PROTECTED]> wrote:
> Hi all,
>
> any ideas on how to implement a kind of OnCompletionListener ?
> As I want to queue 2 sounds after each other :/
>
> Any help appreciated.
>
> Best Regards,
> plusminus
>
> On 15 Okt., 08:47, Robert Green <[EMAIL PROTECTED]> wrote:
>
> > I just read the whole discussion.  All I can say is... What were they
> > thinking??  How is a developer supposed to be able to generate or
> > synthesize audio real time?  These are important apps.  Just look at
> > the guitar or harmonica app for the iPhone.  Those are very popular
> > and do exactly that.
>
> > I'm just dumbfounded that the API developers don't provide such basic
> > functionality as setting a byte stream datasource for a media player.
> > Media players also are not adequate at all for games other than
> > providing the background music.  Games often times have small samples
> > that are played very often and need to be layered on each other.
> > Maintaining a media player pool seems very heavy and cumbersome just
> > to achieve this, not to mention you may end up with a 100 media
> > players if you have 30 different samples and estimate that it would be
> > possible to play 3 at a time of each.
>
> > Another problem is that for racing, flying and other games which have
> > an "engine" sound, it's not possible to get the pitch of the engine to
> > match the speed shown on the game without being able to change the
> > sampling rate of the sound.  I used SoundPool for that because it
> > supported changing the sampling rate while playing and it does work
> > correctly for me right now.  Whoever designed SoundPool definitely
> > knew what they were doing for games because it's the right kind of API
> > for that but we still have the problem of not being able to produce
> > our own stream of audio on the fly and play it which limits what kind
> > of apps we can write and the general quality of the audio in games and
> > other applications.
>
> > Originally I was thinking that I'd go the old school route on the
> > sound in my game and just mix the audio in an update routine and
> > constantly feed the sound buffer but there is no option for this.
>
> > Unbelievable.  I find this really discouraging.  It's also very
> > frustrating that there is a SoundPool API which DOES WORK given a few
> > bugs and workarounds in the SDK 1.0 and is very suitable for 90% of
> > gaming applications as well as soundboard style apps and I'm sure
> > other things.  Why would they get rid of this?!
>
> > blindfold - Where did you find that it's not supported under 1.0 r1?
> > I can't find any documentation on whether it's supported, intended for
> > future or recently added and already deprecated.
>
> > On Oct 15, 3:01 am, blindfold <[EMAIL PROTECTED]> wrote:
>
> > > > it works on both the emulator and a real G1.
>
> > > So you have access to a real G1. Lucky you!!
>
> > > > I'm really surprised that there is no access to the audio buffer.
> > > > How are we supposed to write dynamic audio generation apps?
>
> > > Unfortunately not supported by Android SDK 1.0 r1. See
>
> > >http://code.google.com/p/android/issues/detail?id=739
>
> > > and search this group for discussions on "ByteArrayInputStream".
>
> > > Regards
>
> > > On Oct 15, 12:43 am, Robert Green <[EMAIL PROTECTED]> wrote:
>
> > > > I used it for my game and it works on both the emulator and a real
> > > > G1.  Just follow my example.
>
>
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[EMAIL PROTECTED]
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to