45

I am creating an application that will have multiple images on the screen, these images will be buttons and when tapped will play a short sound. I researched this and could only find the current method I am using to play sounds, which does not seem responsive at all. I want that the sound plays quickly and is responsive to many rapid taps. I was unsure if this was even possible in Android.

The code I am using to play my sound is this:

    Button sound1;
MediaPlayer  firstSound;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    firstSound = MediaPlayer.create(SoundActivity.this, R.raw.click);


    sound1 = (Button) findViewById(R.id.Sound1);


    beaver.setOnClickListener(new View.OnClickListener() {

        public void onClick(View v) {

            firstSound.start();

            }

    });



    }

My lag issue could also be perhaps down to the way I am using the media player object? I do feel that this should be smoother on my phone, any suggestions on how to play sounds in Android is appreciated.

Thanks.

Since discovering Sound Pool, I have edited my code to use this and it works perfectly, the new code looks like this:

SoundPool soundPool;
HashMap<Integer, Integer> soundPoolMap;
int soundID = 1;


Button sound1;
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);


    soundPool = new SoundPool(4, AudioManager.STREAM_MUSIC, 100);
    soundPoolMap = new HashMap<Integer, Integer>();
    soundPoolMap.put(soundID, soundPool.load(this, R.raw.click, 1));

    sound1 = (Button) findViewById(R.id.bBeaver);


    sound1.setOnClickListener(new View.OnClickListener() {

                public void onClick(View v) {

                    AudioManager audioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
              float curVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
              float maxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
              float leftVolume = curVolume/maxVolume;
              float rightVolume = curVolume/maxVolume;
              int priority = 1;
              int no_loop = 0;
              float normal_playback_rate = 1f;
              soundPool.play(soundID, leftVolume, rightVolume, priority, no_loop, normal_playback_rate);

            }

    });


    }

Thanks

deucalion0
  • 2,422
  • 9
  • 55
  • 99
  • 3
    It doesn't look like you are using your soundPoolMap? – Moberg Aug 05 '13 at 11:27
  • 2
    love the way you implemented, worked nicely at once – desgraci Apr 28 '14 at 15:22
  • 1
    after several hours spent with MediaPlayer issues, I got SoundPool work in five minutes, thanks! – Martina Mar 12 '15 at 21:52
  • `SoundPool` is the right choice, although it's somewhat more complicated than `MediaPlayer`. But this gets you efficient and fast playback. You should use a library, however, or create one yourself, as you have to make use of a separate worker thread: https://github.com/delight-im/Android-Audio – caw Apr 01 '15 at 22:37
  • 2
    @Moberg was right, instead of: "soundPool.play(soundID..." it shoud be: "soundPool.play(soundPoolMap.get(soundID)..." – Kresimir Aug 23 '15 at 09:43

3 Answers3

31

You can use SoundPool. It fits what you want to do perfectly.

You'll just need a way to store the sound effect IDs corresponding to each image (or button).

Perhaps extend Button to store associated sound effect ID. And use a common SoundPool to play the sound effect associated to the id when the button is touched.

You can read more about SoundPool here.

Rikonator
  • 1,830
  • 16
  • 27
  • 1
    Thanks for your advice, and link. I looked further into this and found a tutorial, this helped me do what I wanted, it certainly is much better than the media player! Many thanks! – deucalion0 Mar 11 '12 at 17:12
  • Would you post a link to the tutorial please? – Moberg Aug 05 '13 at 11:23
  • @Moberg here you have one http://stackoverflow.com/questions/17069955/play-sound-using-soundpool-example – JoséMi Jul 18 '16 at 07:04
5

@Rikonator is on the right track there with Soundpool. It's much more suited to the kind of functionality you are after.

If you decide to go with the mediaplayer anyway, though, don't forget the prepareAsync () method to prevent it from hanging the UI thread. You can read more about playing media here.

Qw4z1
  • 3,041
  • 1
  • 24
  • 36
  • 1
    It might be preferable to block on the UI thread as the sounds are being used for buttons. It may be bad to hang the UI, but sounds firing late is a little weirder. – Tonithy Sep 18 '13 at 01:22
3
MediaPlayer mp = MediaPlayer.create(getApplicationContext(), R.raw.sound);

try {
    if (mp.isPlaying()) {
        mp.stop();
        mp.release();

        mp = MediaPlayer.create(getApplicationContext(), R.raw.sound);
    }

    mp.start();
} catch (Exception e) {
    e.printStackTrace();
}
Philip Herbert
  • 4,599
  • 2
  • 37
  • 40