即使使用OGG格式,Android MediaPlayer循环也存在差距

时间:2014-01-21 01:50:23

标签: android audio

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

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

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

  • 使用Audacity将所有wav转换为OGG(质量等级2到10,无所谓)
  • 尝试过setNextMediaPlayer()
  • 试图在停止时使用seekTo(0)并重复
  • 尝试过具有自己错误的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上的循环错误。

1 个答案:

答案 0 :(得分:1)

好的老邮政,但这个解决方案有效。这是一种黑客行为。如果有人回答这个问题,它会对某人有所帮助。

我只是使用三个媒体播放器。 mp1mp2mp3mp1开始播放,我将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