Crossfade Background Music

beginner

By: Henrique Campos

In the background music tutorial, we saw how to keep the music playing when transitioning between game levels or screens.

What if we want to transition between two soundtracks smoothly? In this tutorial, you’ll learn to crossfade two music tracks smoothly.

Setting up the scene

To achieve a crossfade effect in Godot, we need two AudioStreamPlayer nodes, one for each music track. Create a new scene with a node named BackgroundMusic. Add two AudioStreamPlayer and an AnimationPlayer node as its children. I’ve called the stream players Track1 and Track2. Leave them without a stream and set them to not autoplay as we will control them from BackgroundMusic‘s script.

Crossfade background music scene structure

Let’s start with the crossfade animations. We need two, respectively, to fade from track one to track two and vice-versa.

Animate the Volume dB property of the audio tracks. One Node should animate from 0.0 to -80.0 dB, and the other from -80.0 to 0.0. For the track that ends the animation at -80.0 dB, add a track and keyframe that sets its Playing property to false.

Here is my animation FadeToTrack1:

Animation fading from track two to track one

And FadeToTrack2:

Animation fading from track one to track two

Note that you need to change the easing on the animation keys at the start of the animation. Because audio volume follows a logarithmic scale, linear interpolation will cause the music to fade out in a split second. Instead, we want them to blend for a moment.

Using a non-linear audio easing

One curve should ease in, as on the image above, and the other ease out.

Coding the crossfade

We need some code to play music and automatically fade from one track to the other. Internally, our BackgroundMusic Node should toggle between the two audio stream players. From the user’s perspective, all we want is to call a function and let the fade happen magically.

Attach a script to BackgroundMusic and add the following code to it.

extends Node

# References to the nodes in our scene
onready var _anim_player := $AnimationPlayer
onready var _track_1 := $Track1
onready var _track_2 := $Track2


# crossfades to a new audio stream
func crossfade_to(audio_stream: AudioStream) -> void:
	# If both tracks are playing, we're calling the function in the middle of a fade.
	# We return early to avoid jumps in the sound.
	if _track_1.playing and _track_2.playing:
		return

	# The `playing` property of the stream players tells us which track is active. 
	# If it's track two, we fade to track one, and vice-versa.
	if _track_2.playing:
		_track_1.stream = audio_stream
		_track_1.play()
		_anim_player.play("FadeToTrack1")
	else:
		_track_2.stream = audio_stream
		_track_2.play()
		_anim_player.play("FadeToTrack2")

You can use the script above by adding BackgroundMusic as an autoload in your project and calling BackgroundMusic.crossfade_to(). Note that the function takes an AudioStream.

Become a better game developer

Join our weekly newsletter and get our latest game creation tutorials, tips, and open-source tools right in your inbox.

🔒 No spam. Unsubscribe anytime.

Made by

Our tutorials are the result of careful teamwork to ensure we produce high quality content. The following team members worked on this one:

Henrique Campos

Tutor

Nathan Lovato

Founder