This "Beat Indicator" is Inaccurate whenever beat steps change

Grand rising. I’m making this because I’ve run into a problem with indicating where the next beat should be. What I’m trying to accomplish is sort of like a marker of when the timing the of the “metronome” should change. (Right now, it’s either in Beats or in HalfBeats (two steps))

Here’s a video of my problem, since I can’t really explain as well as videos can (and ik, the recording is probably terrible, and I can’t even review it):

The green is the marker indicating where the next tick should occur, the red is just the marker of the Music.TimePosition.

Currently, it’s tapping in half-beats. (or two steps) If you know how rhythm games work, what should have happened is it switching from one tempo into another in a timed and smooth matter. In this instance, instead of doing that, it does a huge skip and positions at the next 4 bars, it seems (which is not what it should be doing).

I have a script here that controls this. It does look quite jumbled up, so I’m only going to include parts that (I feel like) is of importance to the problem.

-- some information that you may need to know so you don't think some of these values are useless:

-- excused is just if the player doesn't need to tap at this current time
-- tapped is if the player had tapped to the beat at this current time
-- delta is used for the function that allows the player to tap, calculating by how timed the tap was
-- beats is supposed to be how many beats the metronome tapped

-- beatEqu() (maybe should change the name) is the equation of calculating the placement of when the next beat should occur.

MusicReceiver.OnClientEvent:Connect(function(bpm, id, ...: { BeatMarker: number, StepType: string })
local beats = 0
	local delta = 0
	local beatDelta = 60/bpm
	local beatIncrement = 1
	local markers = {...}

	-- some parts of the code that was removed here

	local function beatEqu()
		return beats * beatDelta

	-- some parts of the code that was removed here

	RunService:BindToRenderStep("MusicSync", Enum.RenderPriority.Camera.Value, function(dt)
		delta += dt -- was used in this script, just not important here

		if (Music.TimePosition >= beatEqu() or excused) and Music.Playing and canTap then
			delta = 0 
			print(beatEqu(), Music.TimePosition, beatEqu() <= Music.TimePosition) -- figuring out why it was behaving how it was, this didn't help...
			canTap = false
				beats += 1
			until Music.TimePosition < beatEqu()
			VisualBop(beatDelta) -- the FOV change you saw in the video

			-- some block of code that was removed here

			for _, markerInfo in markers do
				if markerInfo.BeatMarker == beats * beatIncrement + 1 then
					local stepType = markerInfo.StepType
					local steps = stepType == "Beat" and 1 or stepType == "HalfBeat" and 2
					local miniDelta = 0
					beatDelta = NewBeatDelta(bpm, markerInfo.StepType) -- This function supposedly changes the timing of the tempo	
					for i = 1, steps do
						while miniDelta < beatDelta * i do
							miniDelta += RunService.RenderStepped:Wait()
			-- some block of code that was removed here

			canTap = true
		elseif not Music.IsPlaying or not Music then
			beats = 0

If there’s more information you need to know, please let me know. And those who do try to help me, I greatly appreciate your efforts, whether they helped or not.