同步播放多个音轨

时间:2018-04-13 09:42:10

标签: android audio

最近我在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。我可以寻求特定的时间并开始游戏。

0 个答案:

没有答案