最近我在Audacity有一个音频项目,里面有多个曲目。它将人声分开,乐器分开。
我已将每个曲目导出为WAV(16位)文件。我有5个曲目的5个文件。所有文件都超过300MB,长度为25分钟。
我试图使用媒体播放器同时播放它们:
我为每个文件创建了Mediaplayer实例mp1,mp2,mp3,mp4和mp5
我尝试通过以下方式同时播放:
默认启动所有媒体播放器的方式:
mp1.start()
mp2.start()
mp3.start()
mp4.start()
mp5.start()
我观察到的是两者之间存在一些差距。
我可以将它们混合在一起,并作为单个文件播放。我希望它们单独播放的原因是我想控制android中每个音轨的音量。
我在网上对此进行了很多研究:
我认为问题出在.start()命令不能同时启动。
方法1:Asyntask同时启动所有mp的方法:
所以我尝试过使用Asyntask并创建了5个单独的线程,如下所示:
class PlayThread extends AsyncTask<MediaPlayer, Void, Void>
{
@Override
protected Void doInBackground(MediaPlayer... player) {
player[0].start();
return null;
}
}
然后做了
PlayThread[] playThreads = new PlayThread[5];
for (int i = 0; i < 5; i++)
playThreads[i] = new PlayThread();
playThreads[0].executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, mp1);
playThreads[1].executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, mp2);
playThreads[2].executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, mp3);
playThreads[3].executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, mp4);
playThreads[4].executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, mp5);
方法2:使用CyclicBarrier
public void syncedCommand(
MediaPlayer player1,
MediaPlayer player2,
MediaPlayer player3,
MediaPlayer player4,
MediaPlayer player5
) {
final CyclicBarrier commandBarrier = new CyclicBarrier(5, new Runnable() {
@Override
public void run() {
L.m("ALL threads done");
}
});
new Thread(new SyncedCommandService(commandBarrier, player1)).start();
new Thread(new SyncedCommandService(commandBarrier, player2)).start();
new Thread(new SyncedCommandService(commandBarrier, player3)).start();
new Thread(new SyncedCommandService(commandBarrier, player4)).start();
new Thread(new SyncedCommandService(commandBarrier, player5)).start();
}
private class SyncedCommandService implements Runnable {
private final CyclicBarrier mCommandBarrier;
private MediaPlayer mMediaPlayer;
private int lengthseek;
public SyncedCommandService(CyclicBarrier barrier, MediaPlayer player) {
mCommandBarrier = barrier;
mMediaPlayer = player;
}
@Override public void run() {
try {
L.m("Waiting for thread");
mCommandBarrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
mMediaPlayer.start();
}
}
然后使用
播放它们syncedCommand(mp1,mp2,mp3,mp4,mp5);
在上述两种方法中,轨道之间存在一些延迟,两者之间存在一些差距。
后来我在另一篇文章中读到它不可能:
syncing multiple audio tracks on android
问题是每个MediaPlayer代表一个单独的流, 这可能会在不同的时间开始。即使你打电话给所有人开始 他们在同一时间(这是不可能的),没有办法 保证操作系统将加载并实际启动每个操作系统 同一时间。
据我所知,Android无法同步多个 流。即使有提供此功能的操作系统, 它非常麻烦,通常不是100%准确。
正确的解决方案是打开单个流,例如使用音频 跟踪界面,并自己做MP3解码和混音 将数据发送到流。
它提到的解决方案是解码,混合和编码。我是新手使用Audio Track执行此方法。我仍然可以弄明白该怎么做。 BUt会允许我
1。改变播放音乐的音量,就像媒体播放器改变每首音轨的音量一样。或者我必须首先修复参数然后混合,播放并检查它是否适合我的需要
2。我可以寻求特定的时间并开始游戏。