Android的媒体播放器:为什么音频循环不能与在同一个BPM上播放的节拍器同步?

时间:2017-01-03 17:36:21

标签: android audio android-mediaplayer

我正在使用Android的MediaPlayer来循环播放音频文件。我用

设置媒体播放器循环
mMediaPlayer.setLooping(true);

经过几次重复之后,循环开始的时间早于它应该做的事情,即如果我在计算机上播放相同的循环,节拍器在与循环相同的BPM上独立运行,Android的媒体播放器和节拍器保持同步几个小节,但经过几次循环后,使用应用程序播放的循环开始得太早。

我读到其他人抱怨这个问题。

我在Android 4.4和Android 6上都重现了这个问题

这是一个用于重现问题的最小Android项目: https://drive.google.com/open?id=0B9FRLIzBQgR1WWdMU29ZcHdsMXc

2 个答案:

答案 0 :(得分:1)

在我的项目中,我遇到了同样的问题,我发现他在某处解决了问题,我不记得究竟在哪里。但这就是我所做的:

您可以尝试使用处理程序将搜索设置为文件结尾前的x毫秒

loopTimer = new Timer();
loopTask = new TimerTask() {               
    @Override public void run() {
        mMediaPlayer.seekTo(0);
    }
};
long waitingTime = mMediaPlayer.getDuration()-mLoopingPreview;
loopTimer.schedule(loopTask, waitingTime, waitingTime);

现在只需将mLoopingPreview设置为合理的时间值即可。我使用80ms。

答案 1 :(得分:0)

我在Mediaplayer

中也遇到了这个问题

有几种解决方案:

1.使用ogg格式声音文件(https://en.wikipedia.org/wiki/.ogg

2.可以使用soundpool它有一个用于媒体播放的循环和缓存工具(https://developer.android.com/reference/android/media/SoundPool.html

3.你也可以使用下面的类:它会在第一个完成后立即初始化一个新的媒体播放器。所以延迟不那么明显了

    public class LoopMediaPlayer {

    public static final String TAG = LoopMediaPlayer.class.getSimpleName();

    private Context mContext = null;
    private int mResId = 0;
    private int mCounter = 1;

    private MediaPlayer mCurrentPlayer = null;
    private MediaPlayer mNextPlayer = null;

    public static LoopMediaPlayer create(Context context, int resId) {
        return new LoopMediaPlayer(context, resId);
    }

    private LoopMediaPlayer(Context context, int resId) {
        mContext = context;
        mResId = resId;

        mCurrentPlayer = MediaPlayer.create(mContext, mResId);
        mCurrentPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
            @Override
            public void onPrepared(MediaPlayer mediaPlayer) {
                mCurrentPlayer.start();
            }
        });

        createNextMediaPlayer();
    }

    private void createNextMediaPlayer() {
        mNextPlayer = MediaPlayer.create(mContext, mResId);
        mCurrentPlayer.setNextMediaPlayer(mNextPlayer);
        mCurrentPlayer.setOnCompletionListener(onCompletionListener);
    }

    private MediaPlayer.OnCompletionListener onCompletionListener = new MediaPlayer.OnCompletionListener() {
        @Override
        public void onCompletion(MediaPlayer mediaPlayer) {
            mediaPlayer.release();
            mCurrentPlayer = mNextPlayer;

            createNextMediaPlayer();

            Log.d(TAG, String.format("Loop #%d", ++mCounter));
        }
    };
}

使用它只需调用

LoopMediaPlayer.create(context, R.raw.sound_file_name);

而不是mp.setLooping(true);