From acb92171a15007b8f2313c4ac83873bec57f958d Mon Sep 17 00:00:00 2001 From: Kenneth Reitz Date: Sun, 22 Mar 2026 20:30:04 -0400 Subject: [PATCH] =?UTF-8?q?Speed=20up=20songs=20(BPM=20120=E2=86=92180)=20?= =?UTF-8?q?and=20catch=20KeyboardInterrupt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.6 (1M context) --- examples/song.py | 71 +++++++++++++++++++++++++++--------------------- 1 file changed, 40 insertions(+), 31 deletions(-) diff --git a/examples/song.py b/examples/song.py index 1089803..75ce11c 100644 --- a/examples/song.py +++ b/examples/song.py @@ -7,28 +7,34 @@ from pytheory import Tone, Chord, Key, TonedScale, play, Synth # ── Helpers ───────────────────────────────────────────────────────────── -BPM = 120 +BPM = 180 BEAT = 60_000 // BPM # ms per beat def play_melody(notes, synth=Synth.SINE): """Play a sequence of (note_string, beats) tuples.""" - for note, beats in notes: - if note == "REST": - import time - time.sleep(beats * BEAT / 1000) - else: - tone = Tone.from_string(note, system="western") - play(tone, synth=synth, t=int(beats * BEAT)) + try: + for note, beats in notes: + if note == "REST": + import time + time.sleep(beats * BEAT / 1000) + else: + tone = Tone.from_string(note, system="western") + play(tone, synth=synth, t=int(beats * BEAT)) + except KeyboardInterrupt: + print("\n Stopped.") def play_progression(chords, beats_each=2, synth=Synth.TRIANGLE): """Play a list of Chord objects.""" - for chord in chords: - name = chord.identify() or "?" - tones = " ".join(t.full_name for t in chord.tones) - print(f" {name:20s} {tones}") - play(chord, synth=synth, t=int(beats_each * BEAT)) + try: + for chord in chords: + name = chord.identify() or "?" + tones = " ".join(t.full_name for t in chord.tones) + print(f" {name:20s} {tones}") + play(chord, synth=synth, t=int(beats_each * BEAT)) + except KeyboardInterrupt: + print("\n Stopped.") # ── Songs ─────────────────────────────────────────────────────────────── @@ -184,24 +190,27 @@ SONGS = { } if __name__ == "__main__": - print("PyTheory Song Player") - print("=" * 40) - print() + try: + print("PyTheory Song Player") + print("=" * 40) + print() - for key, (name, _) in SONGS.items(): - print(f" {key}. {name}") + for key, (name, _) in SONGS.items(): + print(f" {key}. {name}") - print() - choice = input("Pick a song (1-7, or 'all'): ").strip() + print() + choice = input("Pick a song (1-7, or 'all'): ").strip() - if choice == "all": - for _, (_, fn) in SONGS.items(): - fn() - print() - elif choice in SONGS: - SONGS[choice][1]() - else: - print("Playing all melodies...") - for _, (_, fn) in SONGS.items(): - fn() - print() + if choice == "all": + for _, (_, fn) in SONGS.items(): + fn() + print() + elif choice in SONGS: + SONGS[choice][1]() + else: + print("Playing all melodies...") + for _, (_, fn) in SONGS.items(): + fn() + print() + except KeyboardInterrupt: + print("\n\nBye!")