Как воспроизвести несколько треков одновременно, используя MediaPlayer?


У меня есть 8 mp3 файлов. И я должен играть его одновременно (Не почти. будет наверняка) .
Я использую "дерзость " для точности управления. Но мой код не дал мне желаемых результатов...
(асинхронность = 30~90 МС)
Итак, это мой код.:
( для первого начала игры)

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();
}

(для паузы)

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

(для возобновления после паузы и для начала воспроизведения (используется в первом методе))

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();
            }
        }
}

Если я начну играть в первый раз это дает мне асинхронность ~ 30 мс+
Затем после паузы / возобновления он играет идеально.

1 3

1 ответ:

После долгих исследований проблема была решена. Для одновременного воспроизведения нескольких треков необходимо использовать AsyncTask и выполнить его на THREAD_POOL_EXECUTOR.
Как это сделать:
класс потока :

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

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

Медиаплееры :

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 может выполнять только 5 потоков одновременно, остальные собираются в очередь.


Предел буфера SoundPool составляет 1 мб, так что это вообще не решение.


Это очень важно. важно:
Для одновременного воспроизведения большего количества звуковых дорожек вы должны смешать их в 1 буфер.
Способ сделать это: декодировать mp3 в pcm (в небольшие буферы в потоковом режиме), смешать его в один байтовый буфер и поместить его в AudioTrack для воспроизведения.