I have a custom view (PieView
) that is has a rotating animation. Now I would like to play tick tick tick tick...
sound synchronously with the rotation speed (that is, when the rotation speed is fast, the tick tick should be fast, when rotation is slow, the tick tick should be slow).
To do this, first I created an mp3 file named magicbox_tick.mp3
that has only ONE (1) tick. Next I tried to play the sound with Animation.setUpdateListener()
.
First I tried to play music with MediaPlayer
but after some 10 or 15 ticks, it stoped. So now I am trying SoundPool
to play the music.
The relevant code segment looks like this:
public PieView extends View {
// ... constructors, other methods etc
private SoundPool soundPool;
private int soundId;
void init(){ // called inside those constructors
SoundPool soundPool = new SoundPool(5, AudioManager.STREAM_MUSIC, 0);
soundId = soundPool.load(getContext(), R.raw.magicbox_tick, 1);
}
public void rotateTo(){
animate()..setInterpolator(new DecelerateInterpolator())
.setDuration(mDuration)
.setListener(someListener)
.rotation(targetAngle)
.setUpdateListener(animation -> {
myPlaySound(); // <----------------------- This is the sound playing code
})
.start();
}
void myPlaySound(){
soundPool.play(soundId, 1, 1, 0, 0, 1); // this doesnot play the `tick` sound
// previously I used MediaPlayer like this:
/*
MediaPlayer mp = new MediaPlayer.create(getContext(), R.raw.magicbox_tick);
mp.play();
// these 2 line, after some 10 ticks, stopped working.
*/
}
}
I have never done anything like this, and I don't know how to fix this. Can anyone help me?
Please note that I am open to all answers as long as it works. You don't have to use SoundPool
. So suppose if you can make it work with android MediaPlayer
, I am ok with that.
Special thanks to Mr Mike M for his valuable comment. I was able to fix it using MediaPlayer
. MediaPlayer.release()
method should be called. And to make the sound synced with the angular motion, I kept an if block that checks if the rotation dTheta
is greater than tolerance
angle.
So, if anyone needs it, the complete code looks like this:
public PieView extends View{
private float omega0; // holds the previous rotation
/**
* @brief: plays a music using mediaPlayer
* @input:
* @output: void, plays a music
* */
private void myPlayTick() {
float omega1 = Math.abs(getRotation());
float dOmeda = 0;
if(omega1>omega0){
dOmeda = omega1 - omega0;
}else{
dOmeda = omega0-omega1;
}
if(dOmeda > threshold){
omega0 = omega1; // update previous rotation
final MediaPlayer mp = MediaPlayer.create(getContext(), R.raw.magicbox_tick);
mp.start();
mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
releaseMediaPlayer(mp);
}
});
}
}
/**
* @brief: releases mediaPlayer resource so that other mediaPlayers can use sound hardware resources
* @input: MediaPlayer object
* @output: void
* */
private void releaseMediaPlayer(MediaPlayer mediaPlayer) {
try {
if (mediaPlayer != null) {
if (mediaPlayer.isPlaying())
mediaPlayer.stop();
mediaPlayer.release();
mediaPlayer = null;
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void rotateTo(){
animate()..setInterpolator(new DecelerateInterpolator())
.setDuration(mDuration)
.setListener(someListener)
.rotation(targetAngle)
.setUpdateListener(animation -> {
myPlayTick();
})
.start();
}
// ... rest of the code, such as constructors, etc
}