Search code examples
androidaudioandroid-mediaplayer

Play sound sequentially with no delay between the parts [Android]


In my Android application I want to play sequentially some sound that was divided to parts before. Each part is a .wave file with 2-3 seconds length.

I do perform that successfully, but I have a noticeable delay between those parts.

My code looks now like that -

localMediaPlayer = new MediaPlayer[3];
localMediaPlayer[0] = MediaPlayer.create(this, R.raw.sound_1);
localMediaPlayer[1] = MediaPlayer.create(this, R.raw.sound_2);
localMediaPlayer[2] = MediaPlayer.create(this, R.raw.sound_3);

public void onClick_localBtn(View v){
    Toast.makeText(this, "Play Local Sound", Toast.LENGTH_LONG).show();
    localMediaPlayer[0].start();
    localMediaPlayer[0].setOnCompletionListener(new MediaPlayer.OnCompletionListener(){
        public void onCompletion(MediaPlayer mp) {
        localMediaPlayer[1].start();
        }
        });
    localMediaPlayer[1].setOnCompletionListener(new MediaPlayer.OnCompletionListener(){
        public void onCompletion(MediaPlayer mp) {
            localMediaPlayer[2].start();
        }
    });
}

How can I improve my code that those parts will play smooth and with no delay, like if it were a 1 file sound?

Thanks.


Solution

  • When you start playing your (N)th media player, call prepareAsync() on your (N+1)th media player:

    localMediaPlayer[0].start();
    localMediaPlayer[1].prepareAsync();
        localMediaPlayer[0].setOnCompletionListener(new MediaPlayer.OnCompletionListener(){
            public void onCompletion(MediaPlayer mp) {
            localMediaPlayer[1].start();
            localMediaPlayer[2].prepareAsync();
            }
            });
        localMediaPlayer[1].setOnCompletionListener(new MediaPlayer.OnCompletionListener(){
            public void onCompletion(MediaPlayer mp) {
                localMediaPlayer[2].start();
            }
        });
    

    Edit

    Based on your update and your comment, perhaps a better way would to be time the playing of the next media player according to the duration of the previous player minus some delta:

    private static final int DURATION_DELTA = 1000;
    
    private Handler mHandler = new Handler();
    
    public void playMediaPlayer(final int index) {
       if (index >= localMediaPlayer.length || localMediaPlayer[index] == null)
           return;
    
    
       localMediaPlayer[index].start();
       final int duration = localMediaPlayer[index].getDuration();
    
       mHandler.postDelayed(new Runnable() {
    
           @Override
           public void run() {
               playMediaPlayer(index + 1);
           }
       }, duration - DURATION_DELTA);
    }
    

    This code will basically play a media player, then schedule playing the next media player approx 1 second before the next media player ends. It's a bit "hacky", but you can play around with it (the value for DURATION_DELTA) until you get the best results.