Как воспроизвести несколько треков одновременно, используя 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 ответ:
После долгих исследований проблема была решена. Для одновременного воспроизведения нескольких треков необходимо использовать 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 для воспроизведения.