from machine import Pin, PWM, Timer
from time import sleep
INTER_TONES_GAP = 80
class Stimme:
noteNo = {'c':40, 'd':42, 'e':44, 'f':45, 'g':47, 'a':49, 'h':51, 'b':51,
'C':52, 'D':54, 'E':56, 'F':57, 'G':59, 'A':61, 'H':63, 'B':63, 'p':-22}
def __init__(self, pin, sound):
self.snd = sound
self.__stringPos = 0
self.oktave = 4
self.playing = True
self.noteNoDelta = 0
self.lp = PWM(Pin(pin))
self.lp.duty_u16(8000)
def tonOff(self, event):
self.lp.deinit()
def setStimme(self, notenstring):
self.notenstring = notenstring
def frequency(self, n):
n += 12*(self.oktave-4)
n += self.noteNoDelta
self.noteNoDelta = 0
return round(440*2**((n-49)/12))
def halt(self):
self.playing = False
def replay(self):
self.playing = True
def play(self, event=0):
if self.__stringPos < len(self.notenstring):
z = self.notenstring[self.__stringPos]
while not z in Stimme.noteNo:
if z in 'vV':
self.oktave -= 1
elif z == '^':
self.oktave += 1
elif z in '#+':
self.noteNoDelta = 1
elif z == '-':
self.noteNoDelta = -1
elif z == '@':
self.oktave = 4
elif z == ')':
self.oktave = 2
else:
print('Illegal character in notestring.')
return
self.__stringPos += 1
z = self.notenstring[self.__stringPos]
self.dur = self.snd.defaultLen
if self.__stringPos+1 < len(self.notenstring):
if self.notenstring[self.__stringPos+1] in '12468':
self.__stringPos += 1
self.dur = int(self.notenstring[self.__stringPos])
if self.dur == 6: self.dur = 16
if self.__stringPos+1 < len(self.notenstring):
if self.notenstring[self.__stringPos+1] =='.':
self.dur *= 1.5
self.__stringPos += 1
elif self.notenstring[self.__stringPos+1] == '.':
self.dur *= 1.5
self.__stringPos += 1
self.playLen = round(self.snd.lenx / self.dur)
f = self.frequency(Stimme.noteNo[z])
if f<8:
self.lp.deinit()
else:
self.lp.freq(f)
Timer(period=self.playLen-INTER_TONES_GAP, mode=Timer.ONE_SHOT, callback=self.tonOff)
if self.playing:
Timer(period=self.playLen, mode=Timer.ONE_SHOT, callback=self.play)
self.__stringPos += 1
else:
if self.snd.endless:
self.__stringPos = 0
Timer(period=2000, mode=Timer.ONE_SHOT, callback=self.play)
class Takt:
def __init__(self, pin, sound):
self.snd = sound
self.playing = True
self.tkt = Pin(pin, Pin.OUT)
self.play()
def play(self, event=0):
self.tktOn()
Timer(period=10, mode=Timer.ONE_SHOT, callback=self.tktOff)
if self.playing:
Timer(period=self.snd.lenx//self.snd.taktZähler, mode=Timer.ONE_SHOT, callback=self.play)
def tktOn(self):
self.tkt.on()
def tktOff(self, event=0):
self.tkt.off()
class Sound:
btonarten = ['f-dur', 'd-moll', 'b-dur', 'g-moll', 'es-dur', 'c-moll', 'as-dur', 'f-moll',
'des-dur', 'b-moll', 'ges-dur', 'es-moll']
tonarten = ['c-dur', 'a-moll', 'g-dur', 'e-moll', 'd-dur', 'h-moll', 'a-dur', 'fis-moll', 'e-dur',
'cis-moll', 'h-dur', 'gis-moll', 'fis-dur', 'dis-moll', 'cis-dur', 'ais-moll']
def __init__(self, tonart, speedPerTakt, defaultLen=4, taktZähler=4, taktNenner=4):
tonart = tonart.lower()
if not tonart in Sound.tonarten + Sound.btonarten:
print('Tonart unbekannt.')
return
self.tonart = tonart
self.speedPerTakt = speedPerTakt
self.defaultLen = defaultLen
self.taktZähler = taktZähler
self.taktNenner = taktNenner
self.lenx = speedPerTakt // taktNenner
self.endless = False
self.stimmen = []
def addStimme(self, pin, notenstring):
stimme = Stimme(pin, self)
notenstring = self.clsBlank(notenstring)
notenstring = self.rep(notenstring)
notenstring = self.verschiebeNoten(notenstring)
stimme.setStimme(notenstring)
self.stimmen += [stimme]
def addTakt(self, pin):
self.takt = Takt(pin, self)
@staticmethod
def clsBlank(s):
while ' ' in s:
i = s.index(' ')
s = s[:i] + s[i+1:]
return s
@staticmethod
def quote(s, z, vz='#'):
pos = 0
while z in s[pos:].lower():
i = pos + s[pos:].lower().index(z)
s = s[:i] + vz + s[i:]
pos = i+2
return s
@staticmethod
def rep(s):
while '|:' in s and ':|' in s:
beg = s.index('|:')
end = s.index(':|')
if beg < end:
s = s[:beg] + s[beg+2:end]*2 + s[end+2:]
while ':|' in s:
end = s.index(':|')
s = s[:end]*2 + s[end+2:]
return s
def verschiebeNoten(self, notenstring):
if self.tonart in Sound.tonarten:
no = Sound.tonarten.index(self.tonart) // 2
if no >= 1:
notenstring = self.quote(notenstring, 'f')
if no >= 2:
notenstring = self.quote(notenstring, 'c')
if no >= 3:
notenstring = self.quote(notenstring, 'g')
if no >= 4:
notenstring = self.quote(notenstring, 'd')
if no >= 5:
notenstring = self.quote(notenstring, 'a')
if no >= 6: #sinnvoll?
notenstring = self.quote(notenstring, 'e')
if no >= 7: #sinnvoll?
notenstring = self.quote(notenstring, 'h')
else:
no = Sound.btonarten.index(self.tonart) // 2
notenstring = self.quote(notenstring, 'h', '-')
if no >= 1:
notenstring = self.quote(notenstring, 'e', '-')
if no >= 2:
notenstring = self.quote(notenstring, 'a', '-')
if no >= 3:
notenstring = self.quote(notenstring, 'd', '-')
if no >= 4:
notenstring = self.quote(notenstring, 'g', '-')
if no >= 5: #sinnvoll?
notenstring = self.quote(notenstring, 'c', '-')
return notenstring
def replay(self):
for stimme in self.stimmen:
stimme.replay()
stimme.play()
def halt(self):
for stimme in self.stimmen:
stimme.halt()
def setEndless(self, endless=True):
self.endless = endless
def play(self):
if 'self.takt' in locals():
self.takt.play()
for stimme in self.stimmen:
stimme.play()
####### Main
lied = Sound('C-Dur', 4000)
lied.addStimme(0, 'cdef g2g2 aaaa g1 aaaa g1 ffff e2e2 gggg c1')
lied.addStimme(2, 'cvh^cd e2e2 ffff e1 ffff e1 dddd c2c2 vh1^ c1')
#lied.addStimme(2, 'c1 g1 a1 g1 a1 g1 f1 e1 g1 c1')
#lied.addStimme(4, 'e1 h1 C1 h1 C1 h1 a1 g1 h1 e1')
lied.addTakt(13)
lied.play()
"""
s1 = '@ E#D E#DEhDC a4pcea h4pe#gh C4peE#D E#DEhDC a4pcea h4peCh a4p4E#D E#DEhDC a4pcea'
s2 = ') p4 p1 aEApp4 E#GHpp4 aEApp4 p1 aEApp4 E#GHpp4 aEApp4 p1 aEApp4'
s1 += 'h4pe#gh C4peE#D E#DEhDC a4pcea h4peCh a4phCD E4pgFE D4pfED C4peDC h4eeEp pE^Evpp#D E#DEDED'
s2 += 'E#GHpp4 aEApp4 p1 aEApp4 E#GHpp4 aEApp4 CG^Cvpp4 gDGpp4 aEApp4 eEp4@pg Gpp#FGp )p1'
s1 += 'E#DEhDC a4pcea h4pe#gh CpeE#D E#DhDC a4pcea h4peCh a4phCD EpgFE D4pfED C4peDC h4eeEp'
s2 += 'p1 aEApp4 E#GHpp4 aEApp4 p1 aEApp4 E#GHpp4 aEApp4 CG^Cvpp4 gDGpp4 aEApp4 eEp4@pe'
s1 += 'pE^Evpp#D E#DEDED E#DEhDC a4pcea h4pe#gh C4peE#D E#DEhDC a4pcea h4peCh a2'
s2 += 'Epp#DEp )p1 p1 aEApp4 E#GHpp4 aEApp4 p1 aEApp4 E#GHpp4 a2'
s3 = ') p4' + 'p1'*35 + 'va2'
lied = Sound('A-Moll', 6000, defaultLen=8, taktZähler=3)
lied.addStimme(0, s1)
lied.addStimme(2, s2)
lied.addStimme(4, s3)
lied.addTakt(13)
lied.play()
#lied.setEndless()"""
#birth = Sound('d-dur', 10000, taktZähler=3)
#birth.addStimme(0, 'a8a8 haD C2a8a8 haE D2a8a8 AFD8D8 ChG8G8 FDE D2')
#birth.addStimme(2, 'p fff g2p ggg f2p FDh agh8h8 afg f2')
#birth.addTakt(13)
#birth.play()
i = 0
while True:
#print('===>', i)
i += 1
sleep(1)