Skip to content

Commit

Permalink
MidiPerformance fixes (#181)
Browse files Browse the repository at this point in the history
* Fixes playing multiple notes when  skipping forward and getting stuck when skipping backward

* added delay to account for device lag
  • Loading branch information
TREX2M authored Feb 17, 2025
1 parent 27d04e7 commit 0a484b1
Showing 1 changed file with 13 additions and 6 deletions.
19 changes: 13 additions & 6 deletions backend/src/midi_performance.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ def __init__(self, midi_file_path: str, tempo: float, instrument_index: int = 0,
self.instrument_index = instrument_index
self.score_position = 0.0 # in beats
self._next_note_index = 0
self.last_beat = 0

# Initialize FluidSynth.
self.fs = fluidsynth.Synth(samplerate=44100)
Expand Down Expand Up @@ -161,6 +162,7 @@ def update_score_position(self, position: float):
Current position in beats (quarter-note units).
"""
self.score_position = position
self._next_note_index = 0

def _note_worker(self, midi_note: int, duration_sec: float):
"""
Expand Down Expand Up @@ -215,11 +217,13 @@ def _performance_loop(self):
while (self._next_note_index < len(self.notes) and
self.score_position >= self.notes[self._next_note_index][2]):
frequency, quarter_duration, quarter_offset = self.notes[self._next_note_index]
print(
f"Playing note at beat {quarter_offset}: {frequency:.2f} Hz, "
f"duration {quarter_duration} beats"
)
self._play_note(frequency, quarter_duration)
if (self.score_position - quarter_offset < .1 and self.last_beat is not quarter_offset):
print(
f"Playing note at beat {quarter_offset}: {frequency:.2f} Hz, "
f"duration {quarter_duration} beats"
)
self._play_note(frequency, quarter_duration)
self.last_beat = quarter_offset
self._next_note_index += 1
sleep(0.005)
print("Performance loop ended.")
Expand Down Expand Up @@ -267,10 +271,11 @@ def stop(self):

# Create a MidiPerformance instance with a MIDI file and an initial tempo (BPM).
performance = MidiPerformance(
midi_file_path=r"data/midi/house_of_the_rising_sun.mid", tempo=100, instrument_index=1, program_number=25
midi_file_path=r"data/midi/twinkle_twinkle.mid", tempo=180, instrument_index=0, program_number=25
)

# Start the performance.
sleep(2)
performance.start()

# Simulate score follower updates.
Expand All @@ -283,6 +288,8 @@ def simulate_score_follower():
elapsed_time = current_time - prev_time
position += elapsed_time * performance.current_tempo / 60 # in beats
prev_time = current_time
if position > 5 and position < 6:
position += 10
sleep(0.01)
performance.update_score_position(position)

Expand Down

0 comments on commit 0a484b1

Please sign in to comment.