在android中降低或淡化声音

时间:2011-03-08 21:28:00

标签: android audio

我正在制作一个简单的琐事游戏,并在用户到达主菜单时运行循环~1分钟的mp3文件。当用户点击菜单上的任何按钮(即游戏)时,声音将停止。

我的问题是,当声音停止时,会发出一种刺耳的声音。而不是.pause()或.stop(),有没有办法让按下按钮后声音慢慢消失?

由于

3 个答案:

答案 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);   
}

您可能还想录制他们有媒体设置的原始音量,并在您淡出静音并停止播放音乐后将其重置为该音量。

该代码可能不准确,我目前无法以任何方式测试它,但我希望它能引导您朝着正确的方向前进....