Reputation: 3573
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 ?
Upvotes: 11
Views: 17370
Reputation: 1
hi try below code it will work it the song wont stop you just need to select the song from spinner and click on start button, then select next song from spinner and click start it will work.
public class MainActivity extends AppCompatActivity {
Spinner sp;
Button bstart;
MediaPlayer mp;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
sp=(Spinner)findViewById(R.id.sp);
String [] mys={"demo","democheap","demorehana"};
ArrayAdapter<String> data=new ArrayAdapter<String>(this,R.layout.support_simple_spinner_dropdown_item,mys);
sp.setAdapter(data);
}
public void code(View v)
{
if(sp.getSelectedItem().toString().equals("demo"))
{
mp=MediaPlayer.create(this,R.raw.demo);
}
else if(sp.getSelectedItem().toString().equals("democheap"))
{
mp=MediaPlayer.create(this,R.raw.democheap);
}
else if(sp.getSelectedItem().toString().equals("demorehana"))
{
mp=MediaPlayer.create(this,R.raw.demorehana);
}
if(v.getId()==R.id.bstart)
{
mp.start();
}
}
}
Upvotes: 0
Reputation: 1328
I converted my mp3 in ogg file audio (using Audacity) and I am been able to use 2 Mediaplayer istances and listen the audio mixed.
I didn't try is it is possible for more than 3.
Upvotes: 0
Reputation: 151
As Andrey Nikishaev already wrote in a comment, it seems like some devices have problems using multiple MediaPlayers at the same time. While only one was playing on my Nexus 5, it worked on my Moto G4 (but still having short breaks during playback). Both running with Android 6.0.1.
I suggest to use the ExoPlayer for this use-case instead. It worked fine for me, at least on my two devices.
Upvotes: 1
Reputation: 3573
Well, I believe I found what I could name "a temporary solution".
MediaPlayer track1 = MediaPlayer.create(this, R.raw.track1);
track1.start();
MediaPlayer track2 = MediaPlayer.create(this, R.raw.track2);
track2.start();
MediaPlayer track3 = MediaPlayer.create(this, R.raw.track3);
track3.start();
The problem with this is that the create()
method creates a noticeable gap when the songs are being played.
So this is not it.
After a while, I tried the following :
MediaPlayer track1 = MediaPlayer.create(this, R.raw.track1);
track1.start();
track1.pause();
MediaPlayer track2 = MediaPlayer.create(this, R.raw.track2);
track2.start();
track2.pause();
MediaPlayer track3 = MediaPlayer.create(this, R.raw.track3);
track3.start();
track3.pause();
// resuming...
track1.start();
track2.start();
track3.start();
That whay, the songs are more synchronous. I can still hear a very small gap but it is way better. I found this solution quite strange as well as ugly.
Unless someone has another idea, I will stick with that solution.
Upvotes: 2
Reputation: 1263
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.
Upvotes: 8