I need help with playing multiple audio tracks at the same time in Android
.
I am supposed to play three audio tracks at the exact same time using Android.Media.MediaPlayer
.
Yesterday I managed to make it work doing so :
MediaPlayer track1 = MediaPlayer.create(this, R.raw.track1);
MediaPlayer track2 = MediaPlayer.create(this, R.raw.track2);
MediaPlayer track3 = MediaPlayer.create(this, R.raw.track3);
As you can see, I have three distincts instances of MediaPlaye
r here.
Because I am asked to, I need to have these MediaPlayer
being played in a background thread.
Here is the part where I start the MediaPlayers
:
//let's suppose this code snippet is in a run() method inside a Thread (which is the case)
track1.start();
track2.start();
track3.start();
If I say yesterday, it's because the next day, it did not work as supposed to.
Indeed, starting a MediaPlayer seems to stop any previous playing MediaPlayer.
I tested in debugger mode : clearly, track2.start()
stops track1's MediaPlayer and following the same pattern, track3.start()
stops tack2's MediaPlayer.
So at the end, only track3 is being played, I cannot hear any of the previous tracks, whatever the volume settings are whereas I could cleary hear all of them before : it is supposed to create some sort an ambiance.
Of course, changing the order in which the tracks are started does not change anything : only the last track will be heard.
If I say "heard" it is because in debugger mode, checking the property MediaPlayer.isPlaying
is returning true
: all three players are saying they are playing but only one can be heard... !
Why the change ? Why did it work once to stop working afterwards ?
NOTE:
.mp3
files compressed into .acc
files (from 320kbps
to 144kbps
)Xamarin Studio
in C#
but for clarety purpouse I will stick to small Java
code snippets.EDIT 1
According to this Play two mp3 song at the same time my solution should be working, right ?
I achieved what you're looking for using a CyclicBarrier instance and an inner class implementation.
Example:
public enum MP_COMMAND {
START,
STOP,
PAUSE
}
/**
* Uses threads to execute synced commands for the current video media player and
* background music player in tandem.
*/
public void syncedCommand(MediaPlayer player1, MediaPlayer player2, MP_COMMAND command) {
final CyclicBarrier commandBarrier = new CyclicBarrier(2);
new Thread(new SyncedCommandService(commandBarrier, player1, command)).start();
new Thread(new SyncedCommandService(commandBarrier, player2, command)).start();
}
/**
* Inner class that starts a given media player synchronously
* with other threads utilizing SyncedStartService
*/
private class SyncedCommandService implements Runnable {
private final CyclicBarrier mCommandBarrier;
private MediaPlayerTest.MP_COMMAND mCommand;
private MediaPlayer mMediaPlayer;
public SyncedCommandService(CyclicBarrier barrier, MediaPlayer player, MediaPlayerTest.MP_COMMAND command) {
mCommandBarrier = barrier;
mMediaPlayer = player;
mCommand = command;
}
@Override public void run() {
try {
mCommandBarrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
switch (mCommand) {
case START:
mMediaPlayer.start();
break;
case STOP:
mMediaPlayer.stop();
break;
case PAUSE:
mMediaPlayer.pause();
break;
default:
break;
}
}
}
You'd utilize it like so:
syncedCommand(mCurrentVideoPlayer, mBackgroundMusic, MP_COMMAND.START);
If you had the requirement that it be usable for any number of media players, you could easily implement it - my requirements just call for two.
I realize this question is old, but this page is where I found myself while searching for a solution, so I hope this helps anyone stuck on this issue in the future.