Last active
July 30, 2016 22:49
-
-
Save mieki256/a69b06899f51df7c9cc8d2c1edfa06f2 to your computer and use it in GitHub Desktop.
MMLを周波数と時間のリストに変換するPythonスクリプト
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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) | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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() | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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