在Android / Eclipse上使用3个MediaPlayer对象同步播放音乐

时间:2015-05-04 13:27:16

标签: android eclipse synchronization android-mediaplayer

我有什么: 我在我的应用程序中实现了三个MediaPlayer.Objects。 所有三个都是使用线程创建的:

protected void onResume() {
    // Threads
    mTT1 = new TrackThread(this, R.raw.audiofile1, 1, mHandler);
    mTT2 = new TrackThread(this, R.raw.audiofile2, 2, mHandler);
    mTT3 = new TrackThread(this, R.raw.audiofile3, 3, mHandler);
    // start thread
    mTT1.start();
    mTT2.start();
    mTT3.start();
    super.onResume();
}

"简化"线程中的代码用于创建:

public class TrackThread extends Thread implements OnPreparedListener {
...
...
...
 public void run() {
    super.run();
            try {
                mMp.setDataSource(afd.getFileDescriptor(),
                        afd.getStartOffset(), afd.getDeclaredLength());
                mMp.prepare();
            } catch (IllegalArgumentException | IllegalStateException
                    | IOException e) {
                Log.e(TAG, "Unable to play audio queue do to exception: "
                        + e.getMessage(), e);
            }
      }

当我在几个教程中读到" prepare()" methode需要一点时间才能完成。因此,我实施了一个等待循环"等待所有国会议员准备和创建。

当"准备并创建"完成后我启用了“开始”按钮,我想同时启动所有3个媒体播放器。

我再次使用Thread for dooing:

public void onClick(View v) {
    // Button 1
    if (mBtn.getId() == v.getId()) {
                mTT1.startMusic();
                mTT2.startMusic();
                mTT3.startMusic();
    }

线程中的代码:

public class TrackThread extends Thread implements OnPreparedListener {
...
...
...

// start
public void startMusic() {
    if (mMp == null)
        return;
    mMp.start();
}

请注意,上面的代码不是完整的代码,但应该足以定义我的问题。

我想要什么,我的问题:

所有国会议员应该同步播放他们的音乐,不幸的是,有时当我开始播放音乐时,他们之间会有时间延迟。

MP必须在同时播放3Audio文件的同时开始(并且完全同步)

我已尝试过的内容:

+)使用SoundPool:对于SoundPool,我的音频文件要大(5兆字节以上)

+)seekTo(msec):我想寻找每个MP到特定的时间:例如:0,但这并没有解决问题。

+)为了吸引更多程序员我也问过这个问题:coderanch.com

我希望有人可以帮助我!

提前致谢

2 个答案:

答案 0 :(得分:1)

这里的瓶颈肯定会让媒体播放器做好准备。 Android框架提供了一种异步方法来执行此加载,因此使用一些同步代码,您应该能够在大致相同的时间播放这些音频源。为了避免声音伪影,您需要不到10毫秒的延迟。

将原子计数器C初始化为要加载的事物数量。

使用MediaPlayer中的prepareAsync()函数来准备这三个函数。在调用prepareAsync之后,立即使用setOnPreparedListener(listener)提供一个监听器。

在此侦听器中,递减C并检查值。如果该值大于0,则使用java对象.wait()函数等待对象。如果该值等于0,则调用该对象上的notifyAll()以唤醒所有其他mediaplayer prepared-listener回调线程。

public void startMediaPlayers(List<MediaPlayer> mediaPlayers) {
     private AtomicInteger counter = new AtomicInteger(mediaPlayers.size());
     Object barrier = new Object();
     /* start off all media players */
     for (MediaPlayer player : mediaPlayers) {
          player.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                                @Override
                                public void onPrepared(final MediaPlayer mediaPlayer) {
                                    int value = counter.decrementAndGet();
                                    if (value == 0) {
                                        // all media players are done loading.
                                        // wake up all the ones that are asleep
                                        barrier.notifyAll();
                                    } else {
                                       while (value > 0) {
                                            try {
                                              // wait for everyone else to load
                                              barrier.wait();
                                            } catch (InterruptedException e) {
                                              // ignore
                                            } 
                                       }
                                    }
                                    mediaPlayer.start();
                                    callback.success(true);
                                }
          player.prepareAsync();
     }
}

答案 1 :(得分:0)

由于没有人能帮助我,我自己找到了解决方案。 MediaPlayer未满足我的要求,Android JETPlayerJETCreator结合使用。

注意:安装Python以使用JETCreator非常棘手 关注this tutorial。并且要小心python和wxpython的版本,并非所有版本都支持JETCreator。

我用过:

  • Python Version 2.5.4(python-2.5.4.msi)
  • wxPython 2.8(wxPython2.8-win32-unicode-2.8.7.1-py25.exe)

对于那些不知道如何实施Jetplayer观看的人this video (在第5分钟,他开始编程Jetplayer)。 不幸的是,我不会说法语,所以我只是遵循了对我有用的代码。

使用Android JETCreator,您可以创建自己的JET文件并将其用作资源。

有用的链接: