4

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.

Community
  • 1
  • 1
Volodymyr Kulyk
  • 6,455
  • 3
  • 36
  • 63

1 Answers1

5

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.

Volodymyr Kulyk
  • 6,455
  • 3
  • 36
  • 63
  • Have you tried with [SoundPool in accordance to google's developer](http://developer.android.com/reference/android/media/SoundPool.html) documentation it should be used for playing various tracks simulatenously but I'm having problems setting it. – CommonSenseCode Jun 11 '15 at 21:10
  • @cooervo yes, but SoundPool is not a good option. It can play only small audio files (http://stackoverflow.com/questions/13377604/soundpool-plays-only-first-5-secs-of-file-why) – Volodymyr Kulyk Jun 12 '15 at 09:01
  • 1
    @cooervo in my case, I used NDK to mix buffers of 8 decoded mp3 files. – Volodymyr Kulyk Jun 12 '15 at 09:02