我正在製作一個簡單的瑣事遊戲,並在用戶到達主菜單時運行循環〜1分鐘的mp3文件。當用戶點擊菜單上的任何按鈕(即玩遊戲)時,聲音設置爲停止。在Android中降低或淡入聲音
我的問題是,當聲音停止時,它的一種震顫切斷。而不是做.pause()或.stop(),有沒有辦法使按鈕按下後聲音慢慢淡出?
感謝
我正在製作一個簡單的瑣事遊戲,並在用戶到達主菜單時運行循環〜1分鐘的mp3文件。當用戶點擊菜單上的任何按鈕(即玩遊戲)時,聲音設置爲停止。在Android中降低或淡入聲音
我的問題是,當聲音停止時,它的一種震顫切斷。而不是做.pause()或.stop(),有沒有辦法使按鈕按下後聲音慢慢淡出?
感謝
您可以使用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);
}
你可能也想記錄的原始卷他們的媒體設置爲,並將其重置爲您淡出靜音,停止後您的音樂。
這些代碼可能不準確,我目前還沒有獲得測試它的任何方式,但我希望它會導致你在正確的方向....
EDIT(3/13/13):用新QA代碼更新
這是我整個Android Media Player的處理程序類。看看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);
}
}
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;
}