Guest User

Untitled

a guest
Jul 20th, 2018
80
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.13 KB | None | 0 0
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3.  
  4. import re
  5. import sys
  6. import math
  7. import array
  8. import random
  9. import itertools
  10. import collections
  11.  
  12. import pyaudio
  13.  
  14.  
  15. class MMLStatus:
  16. """テンポとか音符の長さとかの情報を持つ"""
  17. def __init__(self, T=120, L=4, O=4, Q=5, V=12):
  18. self.T = T
  19. self.L = L
  20. self.O = O
  21. self.Q = Q
  22. self.V = V
  23.  
  24. def __str__(self):
  25. return 'T=%d, L=%d, O=%d, Q=%d, V=%d' % (self.T, self.L, self.O, self.Q, self.V)
  26.  
  27. def change(self, cmd):
  28. if cmd.cmd == '<':
  29. if self.O < 7: self.O += 1
  30. elif cmd.cmd == '>':
  31. if self.O > 0: self.O -= 1
  32. elif cmd.cmd == 'L':
  33. if 1 <= cmd.arg <= 64: self.L = cmd.arg
  34. elif cmd.cmd == 'V':
  35. if 0 <= cmd.arg <= 16: self.V = cmd.arg
  36. elif cmd.cmd == 'T':
  37. if 30 <= cmd.arg <= 240: self.T = cmd.arg
  38. elif cmd.cmd == 'O':
  39. if 0 <= cmd.arg <= 7: self.O = cmd.arg
  40. elif cmd.cmd == 'Q':
  41. if 1 <= self.Q <= 8: self.Q = cmd.arg - 1
  42.  
  43.  
  44.  
  45. MMLCommand = collections.namedtuple('MMLCommand', 'cmd acci arg dot')
  46. ADSR = collections.namedtuple('ADSR', 'A D S R')
  47. class MMLPlayer:
  48. """MMLプレイヤー"""
  49. ACCI = ( 1.0, 1.0/1.06, 1.06, 1.06 )
  50. DOT = ( 1.0, 1.5, 1.75, 1.875 )
  51.  
  52. def __init__(self, tone, adsr=None):
  53. self.tone = tone
  54. self.adsr = adsr
  55. self.stat = MMLStatus()
  56.  
  57.  
  58. def fetch_token(self, command):
  59. buf = []
  60. for c in command.upper():
  61. if c in (' ', '¥n'):
  62. continue
  63. if c in ('A', 'B', 'C', 'D', 'E', 'F', 'G',
  64. 'R', 'T', 'L', 'O', 'V', 'Q', '>', '<'):
  65. if buf:
  66. yield ''.join(buf)
  67. buf = []
  68. buf.append(c)
  69. else:
  70. if buf: yield ''.join(buf)
  71.  
  72.  
  73. def conv_token(self, token):
  74. m = re.search(r'([A-Z<>])([-=+#]?)(¥d*)(¥.*)', token)
  75. if not m: return
  76. cmd = m.group(1).upper()
  77. acci = '=-+#'.index(m.group(2))
  78. arg = int(m.group(3) or 0)
  79. dot = len(m.group(4))
  80. return MMLCommand(cmd=cmd, acci=acci, arg=arg, dot=dot)
  81.  
  82.  
  83. def conv_freq(self, cmd):
  84. freq = 0
  85. if cmd.cmd == 'C':
  86. freq = 261.63
  87. elif cmd.cmd == 'D':
  88. freq = 293.66
  89. elif cmd.cmd == 'E':
  90. freq = 329.63
  91. elif cmd.cmd == 'F':
  92. freq = 349.23
  93. elif cmd.cmd == 'G':
  94. freq = 392.00
  95. elif cmd.cmd == 'A':
  96. freq = 440.00
  97. elif cmd.cmd == 'B':
  98. freq = 493.88
  99. elif cmd.cmd == 'R':
  100. freq = 0
  101. freq *= 2 ** (self.stat.O - 4) * self.ACCI[cmd.acci]
  102. return freq
  103.  
  104.  
  105. def conv_length(self, cmd):
  106. if 1 <= cmd.arg <= 64:
  107. return cmd.arg
  108. else:
  109. return self.stat.L
  110.  
  111.  
  112. def calc_tim(self, cmd):
  113. return (60.0 / self.stat.T) * (4.0 / self.conv_length(cmd)) * self.DOT[cmd.dot]
  114.  
  115.  
  116. def play(self, command):
  117. p = pyaudio.PyAudio()
  118. stream = p.open(rate=44100, channels=1, format=pyaudio.paFloat32, output=True)
  119.  
  120. buf = (0, 0, 0, 0)
  121. for i, token in enumerate(self.fetch_token(command)):
  122. cmd = self.conv_token(token)
  123.  
  124. if i % 20 == 0:
  125. sys.stdout.write('¥033[2J¥033[0;0H')
  126. print cmd, self.stat
  127.  
  128. if cmd.cmd not in ('A', 'B', 'C', 'D', 'E', 'F', 'G', 'R'):
  129. self.stat.change(cmd)
  130. continue
  131.  
  132. freq = self.conv_freq(cmd)
  133. tim = self.calc_tim(cmd)
  134. tim2 = tim * ((self.stat.Q + 1) / 8.0)
  135. velocity = self.stat.V / 16.0 * 0.1
  136.  
  137. if cmd.cmd != 'R':
  138. stream.write(self.tone(buf[0], sec=(buf[1], buf[2]), velocity=velocity, adsr=self.adsr))
  139. buf = (freq, tim, tim2, velocity)
  140. else:
  141. buf = (buf[0], buf[1] + tim, buf[2], velocity)
  142. else:
  143. stream.write(self.tone(buf[0], sec=(buf[1], buf[2]), velocity=velocity, adsr=self.adsr))
  144.  
  145. stream.close()
  146. p.terminate()
  147.  
  148.  
  149. def malkov_play(self, command, length=3):
  150. p = pyaudio.PyAudio()
  151. stream = p.open(rate=44100, channels=1, format=pyaudio.paFloat32, output=True)
  152.  
  153. ent = collections.namedtuple('ent', 'freq tim tim2')
  154.  
  155. entities = [ ]
  156. for token in self.fetch_token(command):
  157. cmd = self.conv_token(token)
  158. if cmd.cmd not in ('A', 'B', 'C', 'D', 'E', 'F', 'G', 'R'):
  159. self.stat.change(cmd)
  160. else:
  161. freq = self.conv_freq(cmd)
  162. tim = self.calc_tim(cmd)
  163. tim2 = tim * ((self.stat.Q + 1) / 8.0)
  164. entities.append(ent(freq, tim, tim2))
  165.  
  166. velocity = 0.1
  167. malkov = dict()
  168. for i in xrange(length, len(entities)):
  169. key = tuple(entities[i-length:i])
  170. val = entities[i]
  171. malkov.setdefault(key, []).append(val)
  172.  
  173. total_tim = 0
  174. key = entities[:length]
  175. key_insurances = set( tuple(key) )
  176. while total_tim < 120:
  177. cands = malkov.get(tuple(key))
  178. if not cands:
  179. key = list(random.choice(list(key_insurances)))
  180. continue
  181. key_insurances.add(tuple(key))
  182. e = random.choice(cands)
  183. key = key[1:] + [ e ]
  184. stream.write(self.tone(e.freq, sec=(e.tim, e.tim2), velocity=velocity, adsr=self.adsr))
  185. total_tim += e.tim
  186. print e, total_tim
  187.  
  188. stream.close()
  189. p.terminate()
  190.  
  191.  
  192.  
  193.  
  194. def sine_wave(w, n):
  195. """サイン派"""
  196. for i in xrange():
  197. yield math.sin(float(i % w) / w * PI2)
  198.  
  199. def sawtooth_wave(w, n):
  200. """ノコギリ波"""
  201. for i in xrange(n):
  202. yield (i % w) / float(w)
  203.  
  204. def square_wave(w, n):
  205. """矩形波"""
  206. hw = w / 2
  207. for i in xrange(n):
  208. yield 1.0 if i % w <= hw else 0.0
  209.  
  210.  
  211. def tone(freq, sec=1, velocity=.2, rate=44100, adsr=None):
  212. PI2 = math.pi * 2
  213.  
  214. if isinstance(sec, (int, float)):
  215. tim = sec
  216. else:
  217. sec, tim = sec
  218.  
  219. w = rate / freq if freq else 0
  220.  
  221. def envelope_generator():
  222. if adsr:
  223. length = rate * sec
  224.  
  225. i = 0
  226. attack = rate * adsr.A
  227. for i in xrange(int(min(attack, length))):
  228. yield i / float(attack)
  229.  
  230. decay = rate * adsr.D
  231. sustain = adsr.S
  232. for i in xrange(i, int(min(decay, length))):
  233. j = i - attack
  234. yield 1.0 - ((1.0 - sustain) * j / float(decay))
  235.  
  236. release_start = rate * tim
  237. for i in xrange(i, int(min(release_start, length))):
  238. yield sustain
  239.  
  240. release = rate * adsr.R
  241. for i in xrange(i, int(min(release, length))):
  242. j = i - release_start
  243. yield sustain * (1.0 - (j / float(release)))
  244.  
  245. for i in xrange(i, int(length)):
  246. yield 0.0
  247.  
  248. else:
  249. for i in xrange(int(rate * sec)):
  250. yield 1.0
  251.  
  252. wgen = square_wave
  253. def gen():
  254. if w:
  255. for i, j in itertools.izip(wgen(w, int(rate * sec)), envelope_generator()):
  256. yield i * j * velocity
  257. else:
  258. for i in xrange(int(rate * sec)):
  259. yield 0
  260.  
  261. return array.array('f', gen()).tostring()
  262.  
  263.  
  264.  
  265. mario = """
  266. T195 L8 O5
  267. eerercergrr4>grr4<
  268.  
  269. crr>grrerrarbrb-arg6<c6g6arfgrercd>br4<
  270. crr>grrerrarbrb-arg6<c6g6arfgrercd>br4<
  271.  
  272. r4gf+fd+rer>g+a<c>ra<cd
  273. r4gf+fd+rer<crccrr4
  274. >r4gf+fd+rer>g+a<c>ra<cd
  275. r4e-rrdrrcrr4r2
  276.  
  277. r4gf+fd+rer>g+a<c>ra<cd
  278. r4gf+fd+rer<crccrr4
  279. >r4gf+fd+rer>g+a<c>ra<cd
  280. r4e-rrdrrcrr4r2
  281.  
  282. ccrcrcdrecr>agrr4
  283. <ccrcrcder1
  284. ccrcrcdrecr>agrr4<
  285.  
  286. eerercergrr4>grr4<
  287. crr>grrerrarbrb-arg6<c6g6arfgrercd>br4<
  288. crr>grrerrarbrb-arg6<c6g6arfgrercd>br4<
  289.  
  290. ecr>gr4g+ra<frf>arr4
  291. b6<a6a6a6g6f6ecr>agrr4<
  292. ecr>gr4g+ra<frf>arr4
  293. b6<f6f6f6e6d6crr2.
  294.  
  295. ecr>gr4g+ra<frf>arr4
  296. b6<a6a6a6g6f6ecr>agrr4<
  297. ecr>gr4g+ra<frf>arr4
  298. b6<f6f6f6e6d6crr2.
  299.  
  300. ccrcrcdrecr>agrr4
  301. <ccrcrcder1
  302. ccrcrcdrecr>agrr4<
  303.  
  304. eerercergrr4>grr4<
  305.  
  306. ecr>gr4g+ra<frf>arr4
  307. b6<a6a6a6g6f6ecr>agrr4<
  308. ecr>gr4g+ra<frf>arr4
  309. b6<f6f6f6e6d6crr2.
  310. """
  311.  
  312.  
  313. invention04 = """
  314. T80
  315. O4
  316. L16
  317. DEFGAB- C#B-AGFE
  318. L8
  319. F A <D >G <C# E
  320. L16
  321. DEFGAB- C#B-AGFE
  322. FDEFGA >b-<agfed
  323. ecdefg >a<gfedc
  324. defdef >grrrrr
  325. <cdecde
  326. L8
  327. >f r b-&
  328. b- a g
  329. L16
  330. <c>b-agfe fg a32g32a32g32&g f
  331. L8
  332. f <c c
  333. L32
  334. cdcdcdcdcdcd
  335. cdcdcdcdcdcd
  336. cdcdcdcdcdcd
  337. L16
  338. c>b-agfe <c>def#ga b-agfed b-cdefg
  339.  
  340. ab<cdef >g#<fedc>b <c>b<dc>ba g#ag#f#ed cdef#g#a
  341. d<c>bag#f# ef#g#ab<c >f#<edc>ba g#ab<cde >a<fedc>b
  342. <ag#f#ea8& ad L32c>b<c>b&b16a16 a8&a16 L16 ab-<c >d8f#8a8 b-gab-<cd
  343. >e<dc>b-ag a8<fef8 >g8 <e8 r8 defgdb- c#b-agfe f8 d8 >g8&
  344. L16 g<dc#e>a<c# d>b L32<dc#dc#&c#16d16 L16 dc>b-agf b-c#defg a<d >f8ed d4&d8
  345. """
  346.  
  347.  
  348. # MMLPlayer(tone, adsr=ADSR(0., .4, 0., 0.2)).malkov_play(invention04, length=2)
  349. MMLPlayer(tone, adsr=ADSR(0., .4, 0., 0.2)).play(mario)
Add Comment
Please, Sign In to add comment