英文:
How to Play 'Tick Tick' Sound with Android Animation (possibly with `Android MediaPlayer / SoundPool`)?
问题
我有一个自定义视图(PieView
),它有一个旋转动画。现在我想要与旋转速度同步地播放“滴答滴答滴答滴答……”的声音(也就是说,当旋转速度快时,“滴答滴答”声音应该快,当旋转慢时,“滴答滴答”声音也应该慢)。
为了实现这一点,首先我创建了一个名为magicbox_tick.mp3
的 mp3 文件,其中只包含一个滴答声。接下来,我尝试使用Animation.setUpdateListener()
来播放声音。
起初我尝试使用MediaPlayer
播放音乐,但在大约 10 或 15 个滴答声后,它就停止了。因此现在我尝试使用SoundPool
来播放音乐。
相关的代码段如下所示:
public PieView extends View {
// ... 构造函数,其他方法等
private SoundPool soundPool;
private int soundId;
void init(){ // 在这些构造函数内调用
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(); // <----------------------- 这是播放声音的代码
})
.start();
}
void myPlaySound(){
soundPool.play(soundId, 1, 1, 0, 0, 1); // 这不会播放“滴答”声音
// 以前我使用 MediaPlayer 来这样做:
/*
MediaPlayer mp = new MediaPlayer.create(getContext(), R.raw.magicbox_tick);
mp.play();
// 这两行,在大约 10 个滴答后,就停止工作了。
*/
}
}
我以前从未做过类似的事情,也不知道如何修复这个问题。有人能帮助我吗?
请注意,只要能够正常工作,我对所有答案都持开放态度。您不必使用SoundPool
。因此,假设您可以通过 Android 的MediaPlayer
使其工作,我也可以接受这种方法。
英文:
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.
答案1
得分: 0
感谢Mike M先生的宝贵评论。我能够使用MediaPlayer
修复它。应该调用MediaPlayer.release()
方法。为了使声音与角动量同步,我保留了一个if块,检查旋转的dTheta
是否大于tolerance
角度。因此,如果有人需要,完整的代码如下:
public PieView extends View{
private float omega0; // 保存先前的旋转角度
/**
* @brief: 使用mediaPlayer播放音乐
* @input:
* @output: void,播放音乐
* */
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; // 更新先前的旋转角度
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: 释放mediaPlayer资源,以便其他mediaPlayer可以使用声音硬件资源
* @input: MediaPlayer对象
* @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();
}
// ... 其余的代码,如构造函数等
}
英文:
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
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论