Not able to achieve Gapless audio looping so far on Android

后端 未结 9 1861
走了就别回头了
走了就别回头了 2020-11-28 06:05

I have tried almost every method but I\'ve failed to achieve gapless audio playback between looping a single track with a duration of 10-15 seconds.

Steps I\'ve trie

相关标签:
9条回答
  • 2020-11-28 06:54

    I have tried everything suggested here and elsewhere and the only thing that worked is ExoPlayer instead of the Music class. You can access your libgdx files with:

    Uri.parse("file:///android_asset/" + path)
    

    You'll also need platform specific code.

    0 讨论(0)
  • 2020-11-28 06:56

    Something like this should work. Keep two copies of the same file in the res.raw directory. Please note that this is just a POC and not an optimized code. I just tested this out and it is working as intended. Let me know what you think.

    public class MainActivity extends Activity {
    MediaPlayer mp1;
    MediaPlayer mp2;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mp1 = MediaPlayer.create(MainActivity.this, R.raw.demo);
        mp2 = MediaPlayer.create(MainActivity.this, R.raw.demo2);
    
        mp1.start();
    
        Thread thread = new Thread(new Runnable() {
    
            @Override
            public void run() {
                int duration = mp1.getDuration();
                while (mp1.isPlaying() || mp2.isPlaying()) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    duration = duration - 100;
                    if (duration < 1000) {
                        if (mp1.isPlaying()) {
                            mp2.start();
                            mp1.reset();
                            mp1 = MediaPlayer.create(MainActivity.this,
                                    R.raw.demo);
                            duration = mp2.getDuration();
    
                        } else {
                            mp1.start();
                            mp2.reset();
                            mp2 = MediaPlayer.create(MainActivity.this,
                                    R.raw.demo2);
                            duration = mp1.getDuration();
                        }
                    }
                }
            }
    
        });
    
        thread.start();
    }
    }
    
    0 讨论(0)
  • 2020-11-28 06:58

    For some reason, I found that my "OnCompletion" Event was always firing a fraction of second late when attempting to loop an 8-second OGG file. For anyone experiencing this type of delay, try the following.

    It is possible to forcibly queue a "nextMediaPlayer" as recommend in previous solutions, by simply posting a delayed Runnable to a Handler for your MediaPlayers and avoiding looping in onCompletion Event altogether.

    This performs flawlessly for me with my 160kbps 8-second OGG, min API 16.

    Somewhere in your Activity/Service, create a HandlerThread & Handler...

    private HandlerThread SongLooperThread = new HandlerThread("SongLooperThread");
    private Handler SongLooperHandler;
    
    public void startSongLooperThread(){
        SongLooperThread.start();
        Looper looper = SongLooperThread.getLooper();
        SongLooperHandler = new Handler(looper){
            @Override
            public void handleMessage(Message msg){
                //do whatever...
            }
        }
    }
    
    public void stopSongLooperThread(){
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2){
            SongLooperThread.quit();
        } else {
            SongLooperThread.quitSafely();
        }
    }`
    

    ...start the Thread, declare and set up your MediaPlayers...

    @Override
    public void onCreate() {
        // TODO Auto-generated method stub
        super.onCreate();
    
        startSongLooperThread();
    
        activeSongResID = R.raw.some_loop;
        activeMP = MediaPlayer.create(getApplicationContext(), activeSongResID);
        activeSongMilliseconds = activeMP.getDuration();
    
        queuedMP = MediaPlayer.create(getApplicationContext(),activeSongResID);
    }
    
    @Override
    public void onDestroy() {
        // TODO Auto-generated method stub
        super.onDestroy();
        stopSongLooperThread();
    
        activeMP.release();
        queuedMP.release();
        activeMP = null;
        queuedMP = null;
    }
    

    ...create a Method for swapping your MediaPlayers...

    private void swapActivePlayers(){
        Log.v("SongLooperService","MediaPlayer swap started....");
        queuedMP.start();
    
        //Immediately get the Duration of the current track, then queue the next swap.
        activeSongMilliseconds = queuedMP.getDuration();
        SongLooperHandler.postDelayed(timedQueue,activeSongMilliseconds);
        Log.v("SongLooperService","Next call queued...");
    
        activeMP.release();
    
        //Swap your active and queued MPs...
        Log.v("SongLooperService","MediaPlayers swapping....");
        MediaPlayer temp = activeMP;
        activeMP = queuedMP;
        queuedMP = temp;
    
        //Prepare your now invalid queuedMP...
        queuedMP = MediaPlayer.create(getApplicationContext(),activeSongResID);
        Log.v("SongLooperService","MediaPlayer swapped.");
    }
    

    ...create Runnables to post to your thread...

    private Runnable startMP = new Runnable(){
        public void run(){
            activeMP.start();
            SongLooperHandler.postDelayed(timedQueue,activeSongMilliseconds);
        }
    };
    
    private Runnable timedQueue = new Runnable(){
        public void run(){
            swapActivePlayers();
        }
    };
    

    In your Service's onStartCommand() or somewhere in your Activity, start the MediaPlayer...

    ...
    SongLooperHandler.post(startMP);
    ...
    
    0 讨论(0)
提交回复
热议问题