【问题标题】:Android MediaPlayer loop has gaps even with OGG format即使使用 OGG 格式,Android MediaPlayer 循环也有差距
【发布时间】:2014-01-21 01:50:23
【问题描述】:

在 Android 4.x 中,我的音频循环应用在声音循环中有 0.2 到 0.5 秒的间隔。

我正在使用 MediaPlayer,因为我的声音可能非常大(在某些情况下每个 2-3mb)并且它可以同时运行多个实例。

我对此进行了相当多的研究,发现 Android 4.x 存在一个错误......但是,我尝试了很多解决方法,但似乎都无法让它们工作。

  • 使用 Audacity 将所有 wav 转换为 OGG(质量级别 2 到 10,没关系)
  • 试过 setNextMediaPlayer()
  • 尝试在停止和重复时使用 seekTo(0)
  • 试过有自己的 bug 的 soundPool

这是我正在使用的代码示例:

public class SoundPlayer implements OnCompletionListener {
    private MediaPlayer mp = null;

    public void initPlayer() {
        if(mp == null) {
            mp = new MediaPlayer();
        }
    }

    public void prepare(Context context, int resource) {
    initPlayer();
    try{
        mp.reset();
        Uri uri = Uri.parse("android.resource://com.myapp.app/"+resource);
        mp.setDataSource(context,uri);
        mp.prepare();
        isPrepared = true;
        mp.setOnCompletionListener(this);
    } catch(Exception e) {
        e.printStackTrace();
    }
    }


.......... etc (Uses typical MediaPlayer methods such as stop(), start(), setLooping(true)


}

我没有使用任何特殊的东西,所以我只是想知道是否有人知道解决 Android 上循环错误的方法。

【问题讨论】:

  • 你的差距不是由加载和重新创建 MediaPlayer 对象的简单延迟引起的吗?
  • 你在使用模拟器吗,我在模拟器上遇到了类似的问题,但是当我用实际设备尝试时 - 延迟消失了。
  • 使用 GS3 设备而不是模拟器。确实感觉像滞后,但我该如何防止呢?
  • 找到解决办法了吗

标签: android audio


【解决方案1】:

好的旧帖子,但这个解决方案有效。这是一种黑客行为。如果有人来回答这个问题,它会有所帮助。

我只使用三个媒体播放器。 mp1、mp2、mp3。 mp1 开始播放,我将 mp2 设置为它的 setNextMediaPlayer。当mp1 结束时,我将mp3 设置为mp2's setNextMediaPlayer。当mp2 结束时,我将mp1 设置为mp3's setNextMediaPlayer。以下是播放暂停、停止、设置音量的完整代码。只需创建一个对象BZMediaPlayer,通过提供uri 或资源ID 来启动它。

import android.content.Context;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.net.Uri;
import android.util.Log;

public class BZMediaPlayer {


    private Context context;
    private Uri uri;
    private int resourceId;

    // which file is getting played
    public static final int URI_PLAYING = 1;
    public static final int RESOURCE_PLAYING = 2;
    private int filePlaying;

    // states of the media player
    public static final int STATE_PLAYING = 1;
    public static final int STATE_PAUSED = 2;
    public static final int STATE_STOP = 3;

    // current state
    private int state = STATE_STOP;

    // current mediaPlayer which is playing
    private int mediaPlayerIndex = -1;

    // 3 media players
    private MediaPlayer mp[] = new MediaPlayer[3];

    // current volume
    private float vol;


    public BZMediaPlayer(Context context) {
        this.context = context;
    }

    /**
     * plays the provided uri
     * @param uri
     */
    public void play(Uri uri) {
        this.uri = uri;
        // current playing file
        filePlaying = URI_PLAYING;
        // stop any playing session
        stop();

        // initialize and set listener to three mediaplayers
        for (int i = 0; i < mp.length; i++) {
            mp[i] = MediaPlayer.create(context, uri);
            mp[i].setOnCompletionListener(completionListener);
        }

        // set nextMediaPlayers
        mp[0].setNextMediaPlayer(mp[1]);
        mp[1].setNextMediaPlayer(mp[2]);

        // start the first MediaPlayer
        mp[0].start();
        // set mediaplayer inex
        mediaPlayerIndex = 0;
        // set state
        state = STATE_PLAYING;
    }

    /**
     * play file from resource
     * @param resourceId
     */
    public void play(int resourceId) {
        this.resourceId = resourceId;
        filePlaying = RESOURCE_PLAYING;
        stop();
        for (int i = 0; i < mp.length; i++) {
            mp[i] = MediaPlayer.create(context, resourceId);
            mp[i].setOnCompletionListener(completionListener);
        }

        mp[0].setNextMediaPlayer(mp[1]);
        mp[1].setNextMediaPlayer(mp[2]);

        mp[0].start();
        mediaPlayerIndex = 0;
        state = STATE_PLAYING;
    }

    /**
     * play if the mediaplayer is pause
     */
    public void play() {
        if (state == STATE_PAUSED) {
            mp[mediaPlayerIndex].start();
            Log.d("BZMediaPlayer", "playing");
            state = STATE_PLAYING;
        }
    }

    /**
     * pause current playing session
     */
    public void pause() {
        if (state == STATE_PLAYING) {
            mp[mediaPlayerIndex].pause();
            Log.d("BZMediaPlayer", "pausing");
            state = STATE_PAUSED;
        }
    }

    /**
     * get current state
     * @return
     */
    public int getState() {
        return state;
    }

    /**
     * stop every mediaplayer
     */
    public void stop() {
        for(int i = 0 ; i < mp.length ; i++) {
            if (mp[i] != null) { 
                mp[i].stop();

                if(mp[i].isPlaying()) {
                    mp[i].release();
                }
            }   
        }
        state = STATE_STOP;
    }

    /**
     * set vol for every mediaplayer
     * @param vol
     */
    public void setVol(float vol) {
        this.vol = vol;
        for(int i = 0 ; i < mp.length ; i++) {
            if (mp[i] != null && mp[i].isPlaying()) {
                mp[i].setVolume(vol, vol);
            }   
        }
    }

    /**
     * internal listener which handles looping thing
     */
    private MediaPlayer.OnCompletionListener completionListener = new OnCompletionListener() {

        @Override
        public void onCompletion(MediaPlayer curmp) {
            int mpEnds = 0;
            int mpPlaying = 0;
            int mpNext = 0;
            if(curmp == mp[0]) {
                mpEnds = 0;
                mpPlaying = 1;
                mpNext = 2;
            }
            else if(curmp == mp[1]) {
                mpEnds = 1;
                mpPlaying = 2;
                mpNext = 0;  // corrected, else index out of range
            }
            else if(curmp == mp[2]) {
                mpEnds = 2;
                mpPlaying = 0; // corrected, else index out of range
                mpNext = 1; // corrected, else index out of range
            }

            // as we have set mp2 mp1's next, so index will be 1
            mediaPlayerIndex = mpPlaying;
            Log.d("BZMediaPlayer", "Media Player " + mpEnds);
            try {
                // mp3 is already playing release it
                if (mp[mpNext] != null) {
                    mp[mpNext].release();
                }
                // if we are playing uri
                if (filePlaying == URI_PLAYING) {
                    mp[mpNext] = MediaPlayer.create(context, uri);
                } else {
                    mp[mpNext] = MediaPlayer.create(context, resourceId);
                }
                // at listener to mp3
                mp[mpNext].setOnCompletionListener(this);
                // set vol
                mp[mpNext].setVolume(vol, vol);
                // set nextMediaPlayer
                mp[mpPlaying].setNextMediaPlayer(mp[mpNext]);
                // set nextMediaPlayer vol
                mp[mpPlaying].setVolume(vol, vol);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    };

}

希望对大家有所帮助

Edit: clean code

【讨论】:

  • 感谢您提供此解决方案!但是有 2 个错误,我相应地编辑了源代码。现在效果很好!再次感谢您!
  • 我已经在我的游戏中实现了这个(使用 libGDX),它很有效。我不得不从源代码中复制很多类并屠宰一些东西,但这里的主体有效。好东西@moonzai
  • @RussWheeler 我的快乐伙伴 :-)
  • @moonzai 在我的情况下循环不起作用。音频只播放一次并停止。你能帮帮我吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-07-27
  • 2020-08-19
  • 2014-03-30
  • 1970-01-01
  • 2011-01-08
  • 1970-01-01
  • 2019-08-29
相关资源
最近更新 更多