I am working on a music tracker for Godot and have managed to get a working sequence. It's just a tiny 4-note thing until I can get the engine doing what it needs to do. However, I am having an issue. I have a changeable BPM in the editor but the program will not change it in the sequence. At 120 BPM default, it sounds great but it doesn't want to change in the editor - my guess is the timer cannot go under a half second. But... yeah. I need to be able to change time. That's a wall I have get past. (I will worry about optimization later, please ignore the repeating code as this is a rough draft).

I have published this program on GitHub but will also post code here.
Explanation:
The bpm is divided by 60000 to get the time in ms.
Those MS (realtime) are divided by 16 to get 16th note times. Those are plugged into the timer and the timer progresses the sequencer.
Driving me nuts and I need a fresh set of eyes. Note: the buttons are separate objects and have code for handling their own graphics, but that code is not affecting this whatsoever.

GitHub Repository:
Noisysaurus

And the code:

extends Control


export var _bpm : int = 120
var _clock = _bpm
var _realTime = _clock/60000
var _note = _realTime/16

var _isPlaying = false
var _sequenceState = 0 
var _track1steps = []


func _ready():
	_clockUpdate()
	_track1steps = [$Step0,$Step1,$Step2,$Step3]



func _clockUpdate():
	_clock = _bpm
	_realTime = _clock/60000
	_note = _realTime/16


func _sequencer():
	_clockUpdate()
	$MasterClock.start(_note)


	match _sequenceState:
		0:
			_sequenceState+=1
			if $Step0._isTrig:
				$Step0._play()
		1:
			_sequenceState+=1
			if $Step1._isTrig:
				$Step1._play()
		2:
			_sequenceState+=1
			if $Step2._isTrig:
				$Step2._play()
		3:
			_sequenceState+=1
			if $Step3._isTrig:
				$Step3._play()


func _process(_delta):
	if _sequenceState > 3:
		_sequenceState = 0
		for _s in _track1steps:
			_s._hasTriggered = false


	_realTime = (_bpm/60000)*_delta
	_note = (_realTime/16)*_delta


func _on_MasterClock_timeout():
	if _isPlaying:
		_sequencer()
	else:
		$MasterClock.stop()


func _on_PlayButton_pressed():
	if !_isPlaying:
		_sequencer()
		$MasterClock.start(_note)
	
	
	_isPlaying = !_isPlaying
	
	if _isPlaying:
		$PlayButton.icon = load("res://graphics/stop_icon.png")
	else:
		$PlayButton.icon = load("res://graphics/play_icon.png")

    xyz yeah i missed that. fixed it but it wasn't the only issue - turns out my math was WAYYYYY wrong. But your note led me to a solution. I also locked my frame rate to 30 for a bit more consistency though I am not sure if this matters. Here is the working code:

    extends Control
    
    ## make sure bpm is float so errors
    export var _bpm : float = 120.0
    ## clock reference bpm
    var _clock = _bpm
    ## math for clock time
    var _realTime = (30/_clock)
    var _note = (_realTime*2)
    
    ## sequencing logic
    var _isPlaying = false
    var _sequenceState = 0 
    var _track1steps = []
    
    
    func _ready(): ## fill array with steps of track
    	_track1steps = [$Step0,$Step1,$Step2,$Step3]
    
    
    func _clocking(): ## function to update clocking in real time
    	_clock = _bpm
    	_realTime = (30/_clock)
    	_note = (_realTime*2)
    
    
    func _sequencer(): ## state machine for sequencer (needs polish)
    	$MasterClock.start(_note)
    
    	match _sequenceState:
    		0:
    			_sequenceState+=1
    			if $Step0._isTrig:
    				$Step0._play()
    		1:
    			_sequenceState+=1
    			if $Step1._isTrig:
    				$Step1._play()
    		2:
    			_sequenceState+=1
    			if $Step2._isTrig:
    				$Step2._play()
    		3:
    			_sequenceState+=1
    			if $Step3._isTrig:
    				$Step3._play()
    
    
    func _process(_delta): ## listen for clock and reset every frame
    	_clocking()
    	
    	if _sequenceState > 3:
    		_sequenceState = 0
    		for _s in _track1steps:
    			_s._hasTriggered = false
    
    
    func _on_MasterClock_timeout(): ## continue sequencer if running on step end
    	if _isPlaying:
    		_sequencer()
    	else:
    		$MasterClock.stop()
    
    
    func _on_PlayButton_pressed(): ## control playing logic (main loop)
    	if !_isPlaying:
    		_sequencer()
    		$MasterClock.start(_note)
    	
    	
    	_isPlaying = !_isPlaying
    
    
    	if _isPlaying: ## graphics update
    		$PlayButton.icon = load("res://graphics/stop_icon.png")
    	else:
    		$PlayButton.icon = load("res://graphics/play_icon.png")