Skip to content

Instantly share code, notes, and snippets.

@mieki256
Last active July 30, 2016 22:49
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 mieki256/a69b06899f51df7c9cc8d2c1edfa06f2 to your computer and use it in GitHub Desktop.
Save mieki256/a69b06899f51df7c9cc8d2c1edfa06f2 to your computer and use it in GitHub Desktop.
MMLを周波数と時間のリストに変換するPythonスクリプト
#!/usr/bin/env python
# -*- mode: python; Encoding: utf-8; coding: utf-8 -*-
# Last updated: <2016/07/30 00:53:00 +0900>
"""
beep from MML
System requirements : Windows 10 x64 + Python 2.7.11
"""
import mmlparser
import time
import winsound
score = "T140 O4 l4 fa<ce l8 >dfa<c rc>af o5 l4 cegb l8 >a<ceg"
# score = "T160 L8 o6 c>c"
m = mmlparser.MMLParser()
lst = m.get_freq_list(score)
for freq, t in lst:
if freq != 0:
winsound.Beep(freq, int(t * 1000))
else:
time.sleep(t)
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# buzzer control - pigpio PWM
# Raspberry Pi3 + buzzer
import mmlparser
import pigpio
import time
import re
BUZZER_PIN = 12
score = "T140 O4 l4 fa<ce l8 >dfa<c rc>af o5 l4 cegb l8 >a<ceg"
# http://d.hatena.ne.jp/mohayonao/20110122/1295655031
score2 = """
T195 L8 O5
eerercergrr4>grr4<
crr>grrerrarbrb-arg6<c6g6arfgrercd>br4<
crr>grrerrarbrb-arg6<c6g6arfgrercd>br4<
r4gf+fd+rer>g+a<c>ra<cd
r4gf+fd+rer<crccrr4
>r4gf+fd+rer>g+a<c>ra<cd
r4e-rrdrrcrr4r2
r4gf+fd+rer>g+a<c>ra<cd
r4gf+fd+rer<crccrr4
>r4gf+fd+rer>g+a<c>ra<cd
r4e-rrdrrcrr4r2
ccrcrcdrecr>agrr4
<ccrcrcder1
ccrcrcdrecr>agrr4<
eerercergrr4>grr4<
crr>grrerrarbrb-arg6<c6g6arfgrercd>br4<
crr>grrerrarbrb-arg6<c6g6arfgrercd>br4<
ecr>gr4g+ra<frf>arr4
b6<a6a6a6g6f6ecr>agrr4<
ecr>gr4g+ra<frf>arr4
b6<f6f6f6e6d6crr2.
ecr>gr4g+ra<frf>arr4
b6<a6a6a6g6f6ecr>agrr4<
ecr>gr4g+ra<frf>arr4
b6<f6f6f6e6d6crr2.
ccrcrcdrecr>agrr4
<ccrcrcder1
ccrcrcdrecr>agrr4<
eerercergrr4>grr4<
ecr>gr4g+ra<frf>arr4
b6<a6a6a6g6f6ecr>agrr4<
ecr>gr4g+ra<frf>arr4
b6<f6f6f6e6d6crr2.
T180 c4.>g4.e4 T160 a6b6a6 T150 a-6b-6a-6g1
"""
mml_list = [score, score2]
pi1 = pigpio.pi()
pi1.set_mode(BUZZER_PIN, pigpio.OUTPUT)
pi1.hardware_PWM(BUZZER_PIN, 0, 0)
try:
m = mmlparser.MMLParser()
for mml in mml_list:
for freq, t in m.get_freq_list(mml):
duty = 500000 if freq != 0 else 0
pi1.hardware_PWM(BUZZER_PIN, freq, duty)
time.sleep(t)
pi1.hardware_PWM(BUZZER_PIN, 0, 0)
time.sleep(1.0)
except KeyboardInterrupt:
print "done."
pi1.hardware_PWM(BUZZER_PIN, 0, 0)
pi1.set_mode(BUZZER_PIN, pigpio.INPUT)
pi1.stop()
#!/usr/bin/python
# -*- mode: python; Encoding: utf-8; coding: utf-8 -*-
# Last updated: <2016/07/30 02:39:12 +0900>
"""
MML Parser
To convert the MML to the list of frequency.
by mieki256
requirements : Python 2.7.x
License : Public DOmain / CC0
"""
import re
class MMLParser:
def __init__(self, def_bpm = 120, def_l = 4, def_otb = 4, def_freq = 440.0):
self.bpm = def_bpm
self.otb = def_otb
self.base_freq = def_freq
self.set_tm(self.bpm)
self.note = 1.0 / float(def_l)
self.NOTE_DICT = {"C":-9, "D":-7, "E":-5, "F":-4, "G":-2, "A":0, "B":2}
self.NOTE_UPDOWN = {"+":+1, "-":-1, "#":+1}
def set_tm(self, bpm):
self.tm = 60.0 / bpm * 4
def get_note(self, n, dot):
if n == "":
return float(self.note)
d = 1.0 / float(n)
if dot != "":
d = d + (d / 2)
return float(d)
def get_freq_list(self, score):
cmd_lst = []
buf = ""
for c in score.upper():
if c in (" ", "\n"):
continue
if c in ("C", "D", "E", "F", "G", "A", "B",
"R", "T", "L", "O", ">", "<"):
if buf:
cmd_lst.append(buf)
buf = ""
buf += c
if buf:
cmd_lst.append(buf)
list = []
for s in cmd_lst:
m = re.match(r"^([A-GLORT<>]{1})([\#+-]{0,1})(\d*)(\.{0,1})", s)
if m:
c, sharp, n, dot = m.groups()
if c == "T": # tempo
self.bpm = int(n)
self.set_tm(self.bpm)
elif c == "O": # octave
self.otb = int(n)
elif c == "<": # up octave
self.otb += 1
elif c == ">": # down octave
self.otb -= 1
elif c == "L": # note
self.note = self.get_note(n, dot)
else:
if n == "":
d = self.note
else:
d = self.get_note(n, dot)
tt = self.tm * float(d)
if c == "R": # rest
list.append((0, tt))
elif self.NOTE_DICT.has_key(c): # pitch
v = (self.otb - 4) * 12 + self.NOTE_DICT[c]
if sharp != "":
v += self.NOTE_UPDOWN[sharp]
freq = int(self.base_freq * pow(2, (v / 12.0)))
list.append((freq, tt))
else:
print "unknown MML : %s" % (score)
break
return list
def dump_test(self, score):
print score
list = self.get_freq_list(score)
for freq, t in list:
print "freq %f , %f sec (%f ms)" % (freq, t, int(t * 1000))
if __name__ == '__main__':
score = "t160 o4 l4 faa#>ce. l8 <dfa>c r2 o6 l4 cegb o3 l8 a>ceg "
# score = "t160 o4 f4a>ce <d8fa>c r2 o6c4egb o3a8>ceg "
m = MMLParser()
m.dump_test(score)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment