Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lower or fade sound in android

Tags:

android

audio

I'm making a simple trivia game, and running a looping ~1 min mp3 file when the user arrives at the main menu. The sound is set to stop when user clicks any of the buttons on the menu (i.e. Play Game).

My problem is that when the sound stops, its kind of a jarring cut off. Rather than do .pause() or .stop(), is there a way to make the sound slowly fade out after a button is pressed?

Thanks

like image 596
Sam Avatar asked Mar 08 '11 21:03

Sam


People also ask

What is fade in volume?

Fades are commonly used audio transitions. Audio fade-ins begin with silence and increase to full volume, and fade-outs begin at full volume and decrease to silence.

How do I fade in and out in audacity?

Fade In/Fade Out After highlighting and selecting a piece of audio, choose Fade in or Fade out from the Effects menu and Audacity will taper off the sound for Fade Out or bring up the volume for Fade Out.


2 Answers

EDIT (3/13/13): Updated with new QA'd code

This is my entire handler class for Android MediaPlayer. Look at the play() and pause() functions. Both contain the ability to either fade or not. The updateVolume() function was the key to let the sound increase/decrease linearly.

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);
}
}
like image 145
sngreco Avatar answered Oct 19 '22 14:10

sngreco


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;
}
like image 37
Thram Avatar answered Oct 19 '22 13:10

Thram