I am developing a musical application that plays several sounds all together, like a sort of multitrack program. A timer triggers when it’s the moment for all the sounds to play. Sounds have to be played exactly on the beat and perfectly synchronized and mixed.
The easiest solution i found is to have one MediaPlayer for each sound, initialize all of them at the very beginning, with MediaPlayer.create() inside my app’s OnCreate().
To make it more reliable and quick I made TWO mediaplayers for each sound.
Then I have a timer that calls simple loop, similar to this:
for (int w=0; w<SOUNDS; w++)
if (must_play(w)) {
if (mp[w].isPlaying()) {
if (mp2[w].isPlaying())
mp[w].seekTo(0);
else mp2[w].start();
} else mp[w].start();
}
I used .seekTo(0) because I found it slightly faster than making .stop() and .start().
But the sounds are not always perfectly synchronized. A 1/10 of second of delay between the .start() of two mediaplayers is very annoying if those two sounds are two drums that are supposed to play perfectly in line.
Is there a way to force all mediaplayers that are instructed to .start() to effectly play all at once?
Please note that the sounds may be very short, like drum sounds: the problem is not to keep the multiple media players synchronized over time, but to make them start exactly all together, without delay.
The question is rather tricky because in my opinion involves two problems:
- Prioritization, above other processes that may slow down the timer or the app itself.
- How to create a single command/object/method (or whatever) that runs all the sounds atomically.
Thank you.
I made it, just used the SoundPool class instead of MediaPlayer. It’s much more responsive, and handles very well multitracks, even cutting the oldest sound played if the streams are not enough. Although the questions weren’t answered, the problem is fixed.