我正在制作一个简单的琐事游戏,并在用户到达主菜单时运行循环~1分钟的mp3文件。当用户点击菜单上的任何按钮(即游戏)时,声音将停止。
我的问题是,当声音停止时,会发出一种刺耳的声音。而不是.pause()或.stop(),有没有办法让按下按钮后声音慢慢消失?
由于
答案 0 :(得分:16)
编辑(2013年3月13日):更新了新的质量保证代码
这是Android MediaPlayer的整个处理程序类。查看play()和pause()函数。两者都包含褪色或不褪色的能力。 updateVolume()函数是让声音线性增加/减少的关键。
public class MusicHandler
{
private MediaPlayer mediaPlayer;
private Context context;
private int iVolume;
private final static int INT_VOLUME_MAX = 100;
private final static int INT_VOLUME_MIN = 0;
private final static float FLOAT_VOLUME_MAX = 1;
private final static float FLOAT_VOLUME_MIN = 0;
public MusicHandler(Context context)
{
this.context = context;
}
public void load(String path, boolean looping)
{
mediaPlayer = MediaPlayer.create(context, Uri.fromFile(new File(path)));
mediaPlayer.setLooping(looping);
}
public void load(int address, boolean looping)
{
mediaPlayer = MediaPlayer.create(context, address);
mediaPlayer.setLooping(looping);
}
public void play(int fadeDuration)
{
//Set current volume, depending on fade or not
if (fadeDuration > 0)
iVolume = INT_VOLUME_MIN;
else
iVolume = INT_VOLUME_MAX;
updateVolume(0);
//Play music
if(!mediaPlayer.isPlaying()) mediaPlayer.start();
//Start increasing volume in increments
if(fadeDuration > 0)
{
final Timer timer = new Timer(true);
TimerTask timerTask = new TimerTask()
{
@Override
public void run()
{
updateVolume(1);
if (iVolume == INT_VOLUME_MAX)
{
timer.cancel();
timer.purge();
}
}
};
// calculate delay, cannot be zero, set to 1 if zero
int delay = fadeDuration/INT_VOLUME_MAX;
if (delay == 0) delay = 1;
timer.schedule(timerTask, delay, delay);
}
}
public void pause(int fadeDuration)
{
//Set current volume, depending on fade or not
if (fadeDuration > 0)
iVolume = INT_VOLUME_MAX;
else
iVolume = INT_VOLUME_MIN;
updateVolume(0);
//Start increasing volume in increments
if(fadeDuration > 0)
{
final Timer timer = new Timer(true);
TimerTask timerTask = new TimerTask()
{
@Override
public void run()
{
updateVolume(-1);
if (iVolume == INT_VOLUME_MIN)
{
//Pause music
if (mediaPlayer.isPlaying()) mediaPlayer.pause();
timer.cancel();
timer.purge();
}
}
};
// calculate delay, cannot be zero, set to 1 if zero
int delay = fadeDuration/INT_VOLUME_MAX;
if (delay == 0) delay = 1;
timer.schedule(timerTask, delay, delay);
}
}
private void updateVolume(int change)
{
//increment or decrement depending on type of fade
iVolume = iVolume + change;
//ensure iVolume within boundaries
if (iVolume < INT_VOLUME_MIN)
iVolume = INT_VOLUME_MIN;
else if (iVolume > INT_VOLUME_MAX)
iVolume = INT_VOLUME_MAX;
//convert to float value
float fVolume = 1 - ((float) Math.log(INT_VOLUME_MAX - iVolume) / (float) Math.log(INT_VOLUME_MAX));
//ensure fVolume within boundaries
if (fVolume < FLOAT_VOLUME_MIN)
fVolume = FLOAT_VOLUME_MIN;
else if (fVolume > FLOAT_VOLUME_MAX)
fVolume = FLOAT_VOLUME_MAX;
mediaPlayer.setVolume(fVolume, fVolume);
}
}
答案 1 :(得分:2)
https://stackoverflow.com/a/29246026/922514
private static void crossFade() {
MediaPlayerManager.fadeOut(currentPlayer, 2000);
MediaPlayerManager.fadeIn(auxPlayer, 2000);
currentPlayer = auxPlayer;
auxPlayer = null;
}
public static void fadeOut(final MediaPlayer _player, final int duration) {
final float deviceVolume = getDeviceVolume();
final Handler h = new Handler();
h.postDelayed(new Runnable() {
private float time = duration;
private float volume = 0.0f;
@Override
public void run() {
if (!_player.isPlaying())
_player.start();
// can call h again after work!
time -= 100;
volume = (deviceVolume * time) / duration;
_player.setVolume(volume, volume);
if (time > 0)
h.postDelayed(this, 100);
else {
_player.stop();
_player.release();
}
}
}, 100); // 1 second delay (takes millis)
}
public static void fadeIn(final MediaPlayer _player, final int duration) {
final float deviceVolume = getDeviceVolume();
final Handler h = new Handler();
h.postDelayed(new Runnable() {
private float time = 0.0f;
private float volume = 0.0f;
@Override
public void run() {
if (!_player.isPlaying())
_player.start();
// can call h again after work!
time += 100;
volume = (deviceVolume * time) / duration;
_player.setVolume(volume, volume);
if (time < duration)
h.postDelayed(this, 100);
}
}, 100); // 1 second delay (takes millis)
}
public static float getDeviceVolume() {
int volumeLevel = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
int maxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
return (float) volumeLevel / maxVolume;
}
答案 2 :(得分:0)
您可以使用AudioManager
:
public static final int STEP_DOWN = 5; // how far each step goes down
// later on, and in a backgroud thread like an AsyncTask
AudioManager am = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
int targetVol = 0; // or whatever you wanted.
int currentVol = am.getStreamVolume(AudioManager.STREAM_MUSIC);
while(currentVol > targetVol)
{
am.setStreamVolume(AudioManager.STREAM_MUSIC, currentVol - STEP_DOWN, 0);
currentVol = am.getStreamVolume(AudioManager.STREAM_MUSIC);
thread.sleep(100);
}
您可能还想录制他们有媒体设置的原始音量,并在您淡出静音并停止播放音乐后将其重置为该音量。
该代码可能不准确,我目前无法以任何方式测试它,但我希望它能引导您朝着正确的方向前进....