My code generated Metronome gets out of sync with the audio source metronome.
Hello, this problem drives me crazy, so i have to post my first ever question.
Im am prototyping a rythm game, and i am trying to keep my code in sync with the music. In my simple test case, the music is a looping audio clip consisting of 4 clicks, at 125 BPM. So with a beat every 0.48 seconds, the Clip is 1.920 seconds long. Now i want anotcher click to be played in the same pace, at exactly the same times, but by code. So i ceate a AudioSource, and .play() it everytime my code determines a beat is completed. This seems to work fine for the first few loops, but after a while it loses sync. I made a short video to demonstrate the difference (20 seconds in it cuts to out of sync) Youtube Video
I've read through several tutorials for unity rythm games, and made use of dspTime and playSheduled. Can you guys see other problems with my approach? Here is my code:
// Start is called before the first frame update
void Start()
{
//Calculate the number of seconds in each beat
secPerBeat = 60f / songBpm; //125 bpm
songStartDelay = secPerBeat * 4;
//Record the time when the music starts
dspSongTime = AudioSettings.dspTime + songStartDelay;
//Start the music
audioSource.PlayScheduled(AudioSettings.dspTime + songStartDelay);
}
void Update()
{
//determine song position, with delta if we dont get a new position
if(AudioSettings.dspTime != lastDSPTime)
{
lastDSPTime = AudioSettings.dspTime;
songPosition = AudioSettings.dspTime - dspSongTime;
}
else
{
songPosition += Time.unscaledDeltaTime;
}
//determine how many beats since the song started
songPositionInBeats = songPosition / secPerBeat;
//calculate the loop position
if (songPositionInBeats >= (completedLoops + 1) * beatsPerLoop)
completedLoops++;
loopPositionInBeats = songPositionInBeats - completedLoops * beatsPerLoop;
loopPositionInAnalog = loopPositionInBeats / beatsPerLoop;
//detect new beat
beatPositionInAnalog = songPositionInBeats - completedBeats;
if (beatPositionInAnalog >= 1)
{
MusicDelayText.text = beatPositionInAnalog.ToString();
debugClap.PlayScheduled(AudioSettings.dspTime);
completedBeats++;
}
}
Maybe the Problem is that i try to detect a new beat by checking if "beatPositionInAnalog" is >= 1? as you can see in the video, it never equals 1, so maybe the delay adds up over time? But i dont know how to prevent this, IF this causes the problem.
Any feedback would be highly appriciated.
Your answer

Follow this Question
Related Questions
Breaking out of the right loop 1 Answer
Loop in coroutine stops after going halfway 2 Answers
Round Loop Problem?... 1 Answer
Can't figure out how to make this work without it looping? 0 Answers
Loop just executes once 0 Answers