Syncing of music tracks

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Northburns

I’ve tried to read the manual, I think now’s the time to ask. Imagine the rhythm game Crypt of the Necrodancer. In short, as I recall it:

There’s an upbeat music playing during gameplay. Once you encounter the shopkeeper, they start to sing along the background music. The shopkeeper’s singing may become quieter once you go further away from them.

How’d one implement something like this in Godot?

:bust_in_silhouette: Reply From: pospathos

General idea: You need to render all your layers of music that you want to play dynamically as separate tracks. Then you need to store bars (or some unit of musical content - melody that loops) of your music track in array in seconds, so you can determine when second layer can be played to be in sync with backround track. You need to track position of your background music with get_playback_position of AudioStreamPlayer node, and you can play second track if position is equal to to some of values in array of background music. If it is equal then you play your second layer. If second layer is not simple small loop but it’s same length and as background music that changes its form (ABA or other) then you need to play second layer at same position with seek function of AudioStreamPlayer node. Each music track should be played in separate audio bus with bus function of AudioStreamPlayer node so yuo can mix them as you wish, and you can monitor distance of some object and make volume of second layer of music dependent of that disnace - volume_db function of AudioStramPlayer node. Hope it helps.

:bust_in_silhouette: Reply From: guilhermow

Here’s what I did: Both tracks have the same tempo. When the player enters into the area, track2 starts playing, but not from the beggining. It starts playing at the position track1 currently at.

onready var track1 = $Music/MusicTrack1
onready var track2 = $Music/MusicTrack2

func _ready():
	track1.play()

func _on_CueMusic_body_entered(body):
	var track1Position = track1.get_playback_position()
	track2.play(track1Position)