Skip to content

Instantly share code, notes, and snippets.

@dlech
Created December 18, 2020 19:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dlech/066cc9593eecf88d044963a0a374f65e to your computer and use it in GitHub Desktop.
Save dlech/066cc9593eecf88d044963a0a374f65e to your computer and use it in GitHub Desktop.
background music
from pybricks.hubs import InventorHub
from pybricks.pupdevices import Motor, ColorSensor, UltrasonicSensor
from pybricks.parameters import Port, Stop, Color, Button
from pybricks.tools import wait, StopWatch
JINGLE_BELLS = (
["B3/4", "B3/4", "B3/2"] * 2 + ["B3/4", "D4/4", "G3/4.", "A3/8", "B3/2.", "R/4"] +
["C4/4", "C4/4", "C4/4.", "C4/8", "C4/4", "B3/4", "B3/4", "B3/8", "B3/8",
"D4/4", "D4/4", "C4/4", "A3/4", "G3/2.", "R/4"]
)
hub = InventorHub()
def play_note(note, duration):
# needs some padding so we don't get StopIteration when calling next(note)
note = iter(note + "\0")
# Note names can be A-G followed by optional # (sharp) or b (flat) or R for rest
c = next(note)
if c == 'C':
c = next(note)
if c == 'b':
raise ValueError("Cb is not allowed")
elif c == '#':
c = next(note)
freq = 17.32
else:
freq = 16.35
elif c == 'D':
c = next(note)
if c == 'b':
c = next(note)
freq = 17.32
elif c == '#':
c = next(note)
freq = 19.45
else:
freq = 18.35
elif c == 'E':
c = next(note)
if c == 'b':
c = next(note)
freq = 19.45
elif c == '#':
raise ValueError("E# is not allowed")
else:
freq = 20.60
elif c == 'F':
c = next(note)
if c == 'b':
raise ValueError("Fb is not allowed")
elif c == '#':
c = next(note)
freq = 23.12
else:
freq = 21.83
elif c == 'G':
c = next(note)
if c == 'b':
c = next(note)
freq = 23.12
elif c == '#':
c = next(note)
freq = 25.96
else:
freq = 24.50
elif c == 'A':
c = next(note)
if c == 'b':
c = next(note)
freq = 25.96
elif c == '#':
c = next(note)
freq = 29.14
else:
freq = 27.50
elif c == 'B':
c = next(note)
if c == 'b':
c = next(note)
freq = 29.14
elif c == '#':
raise ValueError("B# is not allowed")
else:
freq = 30.87
elif c == 'R':
c = next(note)
freq = 0.0
else:
raise ValueError("Missing note name A-G or R")
# Note name must be followed by the octave number
if freq:
octave = ord(c) - ord('0')
c = next(note)
if octave < 2 or octave > 8:
raise ValueError("Missing octave number 2-8")
freq *= 2 << (octave - 1)
# '/' delimiter is required between octave and fraction
if c != '/':
raise ValueError("Missing /")
c = next(note)
# The fractional size of the note, e.g. 4 = quarter note
fraction = ord(c) - ord('0')
c = next(note)
if fraction < 0 or fraction > 9:
raise ValueError("Missing fractional value 1, 2, 4, 8, etc.")
# optional second digit
fraction2 = ord(c) - ord('0')
if 0 <= fraction2 <= 9:
c = next(note)
fraction = fraction * 10 + fraction2
duration /= fraction
# optional decorations
if c == '.':
c = next(note)
duration = 3 * duration / 2
release = True
if c == '_':
c = next(note)
release = False
hub.speaker.beep(freq, -1)
if release:
full_duration = duration
duration = 7 * duration / 8
timer = StopWatch()
while timer.time() < duration:
yield
if release:
hub.speaker.beep(0, -1)
while timer.time() < full_duration:
yield
def play_notes(notes, tempo=120):
duration = 4 * 60 * 1000 / tempo
try:
for n in notes:
yield from play_note(n, duration)
finally:
hub.speaker.beep(0, -1)
music = play_notes(JINGLE_BELLS, tempo=140)
while True:
try:
next(music)
except StopIteration:
pass
wait(10)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment