Volodymyr Kulyk
Volodymyr Kulyk

Reputation: 6546

How to play several tracks simultaneously, using MediaPlayer?

I have 8 mp3 files. And I have to play it simultaneously (not nearly. will for sure).
I'm using 'AudaCity' for control accuracy. But my code did't give me the desired results...
(asynchrony = 30~90 ms)
So, it's my code:
(for first start to play)

public void start() {
//songInfo.getMediaPlayer() - it's array of MediaPlayers, source already setted
        for (MediaPlayer player : songInfo.getMediaPlayer()) {
            try {
                if (player != null) {
                    player.prepare();
                    player.seekTo(0);
                }
            } catch (Exception ex) {
                ex.printStackTrace();
            }       
        }
        songInfo.getMediaPlayer()[0]
                .setOnCompletionListener(new OnCompletionListener() {
                        @Override
                        public void onCompletion(MediaPlayer mp) {
                            //code for play next setlist
                        }
        });
        resume();
}

(for pause)

public void pause() {
        for (MediaPlayer player : songInfo.getMediaPlayer()) {
            if (player != null)
                player.pause();
        }
}

(for resume after pause, and for start play(used in first method))

public void resume() {  
        int pos = songInfo.getMediaPlayer()[0].getCurrentPosition();
        long iTime = System.currentTimeMillis();
        for (MediaPlayer player : songInfo.getMediaPlayer()) {
            if (player != null) {
                player.seekTo(pos + (int)(System.currentTimeMillis()-iTime));
                player.start();
            }
        }
}

If I start play in the first time it gives me asynchrony ~ 30ms+
Then after pause/resume it plays perfect.

Upvotes: 4

Views: 3055

Answers (1)

Volodymyr Kulyk
Volodymyr Kulyk

Reputation: 6546

After much research, problem was solved. To play several tracks simultaneously you should use AsyncTask and execute it on THREAD_POOL_EXECUTOR.
How to do this:
Thread class:

class PlayThread extends AsyncTask<MediaPlayer, Void, Void>
{
    @Override
    protected Void doInBackground(MediaPlayer... player) {

        player[0].start();          
        return null;
    }
}

Media Players:

MediaPlayer[] players = new MediaPlayer[5];
//Then set source to each player...
//...
//Create objects of Thread class
PlayThread[] playThreads = new PlayThread[5];
for (int i = 0; i < 5; i++)
    playThreads[i] = new PlayThread();
//Set Media Players there and start play
for (int i = 0; i < 5; i++)
    playThreads[i].executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, players[i]);

AsyncTask can execute only 5 Threads simultaneously, other are going to queue.


SoundPool buffer limit is 1Mb, so it is not a solution at all.


It is very important:
To play simultaneously more audio tracks you should mix them into 1 buffer.
The way to do this: decode mp3 to pcm (to small buffers in stream mode), mix it into one byte buffer and put it to AudioTrack for playing.

Upvotes: 5

Related Questions