Skip to content

Instantly share code, notes, and snippets.

@interstar
Last active July 5, 2022 01:46
Show Gist options
  • Save interstar/8ced226984e1184a8b6a4d36c25e7685 to your computer and use it in GitHub Desktop.
Save interstar/8ced226984e1184a8b6a4d36c25e7685 to your computer and use it in GitHub Desktop.
3 Sound Modes for the BBC Microbit
import speech
import random
import music
import time
import math
from microbit import pin1, pin2, display, button_a, button_b, sleep
# See https://www.youtube.com/watch?v=DOlMiNbmLWg
def scale(x, lo1, hi1, lo2, hi2) :
if lo1 == hi1 : return lo2
if x == 0 : return 0
return ((float(math.log(x)-math.log(lo1)) / (math.log(hi1)-math.log(lo1))) * (hi2-lo2))+lo2
class CalibratedParameter :
def __init__(self,min=10000,max=-100000) :
self.min = min
self.max = max
self.val = 0
self.changed = False
self.threshold = 2
def set(self,x) :
if abs(x - self.val) > self.threshold :
self.changed = True
self.val = x
if x > self.max :
self.max = x
if x < self.min :
self.min = x
def projectTo(self,targetLo,targetHi) :
return scale(self.val, self.min, self.max, targetLo, targetHi)
def safeProjectTo(self,targetLo,targetHi) :
x = int(self.projectTo(targetLo,targetHi))
if x == targetHi :
x = x - 1
return x
def getVal(self) :
return self.val
def isChanged(self) :
c = self.changed
self.changed = False
return c
def report(self) :
return "%s in %s -- %s" % (self.val,self.min,self.max)
V1 = CalibratedParameter()
V2 = CalibratedParameter()
solfa = [
"#115DOWWWWWW", # Doh
"#103REYYYYYY", # Re
"#94MIYYYYYY", # Mi
"#88FAOAOAOAOR", # Fa
"#78SOHWWWWW", # Soh
"#70LAOAOAOAOR", # La
"#62TIYYYYYY", # Ti
"#58DOWWWWWW", # Doh
]
phones = ["uy", "ui", "nt", "ui"]
pot1 = pin1
pot2 = pin2
mode = 0
wait = 50
def make_phasor(n) :
x=0
yield x
while True :
x = (x + 1) % n
yield x
phas1 = make_phasor(len(phones))
while (True) :
# Input Handlers
if button_a.is_pressed():
wait=((wait+100) % 600)+50
display.set_pixel(0,0,5)
if button_b.is_pressed():
mode = (mode + 1) % 4
display.set_pixel(4,0,5)
V1.set(pot1.read_analog())
V2.set(pot2.read_analog())
print("%s, %s" % (V1.report(),V2.report()))
# Output
display.clear()
# Mode Handlers
if mode == 0 :
display.set_pixel(V1.safeProjectTo(0,5),mode,4)
display.set_pixel(V1.safeProjectTo(0,5),V2.safeProjectTo(0,5),3)
sleep(wait)
if mode == 1 :
display.set_pixel(V1.safeProjectTo(0,5),mode,5)
if (V1.safeProjectTo(0,1200) > 1000) :
freq = random.randint(200,1000)
else:
freq = int(V1.projectTo(0,1000))
wait = V2.safeProjectTo(30,1000)
music.pitch(freq, duration=wait)
sleep(wait)
if mode == 2 :
display.set_pixel(V1.safeProjectTo(0,5),mode,5)
index = V1.safeProjectTo(0,8)
wait = V2.safeProjectTo(30,300)
speech.sing(solfa[index], speed=wait)
sleep(wait)
if mode == 3 :
display.set_pixel(V1.safeProjectTo(0,5),mode,5)
s = V1.safeProjectTo(0,255)
p = V2.safeProjectTo(0,255)
t = random.randint(1,255)
m = random.randint(1,255)
speech.say(phones[next(phas1)], speed=s, pitch=p, throat=t, mouth=m)
sleep(wait)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment