Skip to content

Commit 3254d17

Browse files
committed
Enable live parameter updates for step sequencer
- Add _reschedule_on_change() to apply parameter changes immediately - Reschedule events when BPM, scale, root note, or octave changes - Reschedule when steps are toggled on/off during playback - Clear and rebuild event queue while preserving sample-accurate timing
1 parent 34bf78d commit 3254d17

1 file changed

Lines changed: 26 additions & 3 deletions

File tree

qwerty_synth/step_sequencer.py

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -487,9 +487,8 @@ def update_sequencer_bpm(self, bpm):
487487
# Calculate step duration - use a slightly shorter duration to prevent overlap
488488
self.step_duration = (step_interval / 1000) * 0.98 # 98% of step interval
489489

490-
if self.sequencer_running:
491-
# Update timer if running
492-
self.sequencer_timer.setInterval(step_interval)
490+
# Reschedule if running to apply new BPM immediately
491+
self._reschedule_on_change()
493492

494493
def update_root_note(self, root_name):
495494
"""Update the root note and regenerate notes."""
@@ -503,6 +502,9 @@ def update_root_note(self, root_name):
503502
# Update note labels to show correct names
504503
self.update_note_labels()
505504

505+
# Reschedule if running to apply new notes immediately
506+
self._reschedule_on_change()
507+
506508
def update_scale(self, scale_name):
507509
"""Update the current scale and regenerate notes."""
508510
self.current_scale = scale_name
@@ -514,6 +516,9 @@ def update_scale(self, scale_name):
514516
# Update note labels to show correct names
515517
self.update_note_labels()
516518

519+
# Reschedule if running to apply new scale immediately
520+
self._reschedule_on_change()
521+
517522
def update_note_labels(self):
518523
"""Update all note labels based on current scale and root."""
519524
for i, label in enumerate(self.note_labels):
@@ -695,6 +700,18 @@ def _schedule_next_bar(self):
695700
source='sequencer'
696701
)
697702

703+
def _reschedule_on_change(self):
704+
"""Reschedule sequencer events after parameter changes during playback."""
705+
if not self.sequencer_running:
706+
return
707+
708+
# Clear all scheduled sequencer events
709+
global_scheduler.clear_events_by_source('sequencer')
710+
711+
# Reschedule from the beginning
712+
# The scheduler will handle proper timing based on current sample position
713+
self._schedule_first_bar()
714+
698715
def _update_ui_step(self, step: int):
699716
"""Update UI for a specific step (called from audio thread via scheduler).
700717
@@ -863,6 +880,9 @@ def update_octave(self, value):
863880
# Update note labels
864881
self.update_note_labels()
865882

883+
# Reschedule if running to apply new octave immediately
884+
self._reschedule_on_change()
885+
866886
def toggle_step(self):
867887
"""Handle toggling a step button in the sequencer grid."""
868888
button = self.sender()
@@ -905,6 +925,9 @@ def toggle_step(self):
905925
else:
906926
button.setStyleSheet(f"QPushButton {{ background-color: {self.COLORS['grid_secondary_alt']}; }}")
907927

928+
# Reschedule if running to apply step changes immediately
929+
self._reschedule_on_change()
930+
908931
def _update_octave_display(self, value):
909932
"""Update the display format of the octave spinbox."""
910933
if value > 0:

0 commit comments

Comments
 (0)