1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
#!/usr/bin/python
"""
play a rtttl file by sending the tone lengths to the arduino
protocol information taken from http://merwin.bespin.org/t4a/specs/nokia_rtttl.txt
"""
from __future__ import division
import re
import serial
import struct
import sys
import time
BAUDRATE = 9600
PAUSE = .001
_rtttl_re = re.compile('^\s*([0-9]+)?([a-hp]#?)(\.?)([0-9]?)\s*$')
freqs = {
'c': 261.626,
'c#': 277.183,
'd': 293.665,
'd#': 311.127,
'e': 329.628,
'f': 349.228,
'f#': 369.994,
'g': 391.995,
'g#': 415.305,
'a': 440.000,
'a#': 466.164,
'b': 493.883,
'h': 493.883,
'p': 0,
}
def parse_defaults(s):
defaults = {
'd': 4, # duration
'o': 6, # octave
'b': 63, # beats per minute
}
if s == '':
return defaults
for option in s.split(','):
k,v = option.split('=')
defaults[k] = v
return defaults
def parse(s):
name, defs, music = s.split(':')
defaults = parse_defaults(defs)
defaultlength = int(defaults['d'])
defaultoctave = int(defaults['o'])
timefactor = 60/int(defaults['b'])
# for m in _rtttl_re.finditer(music):
for tone in music.split(","):
m = _rtttl_re.match(tone)
if not m:
print("Didn't match:", tone)
continue
l, t, ld, o = m.groups()
if l:
length = 1/int(l)
else:
length = 1/defaultlength
if ld:
length = length * 1.5
length = length*timefactor
tone = freqs[t.lower()]
if o:
octave = o
else:
octave = defaultoctave
tone = tone * 2**(int(octave) - 4)
yield (length, tone)
def send(sounds, device):
ser = serial.Serial(device, BAUDRATE)
try:
for length, freq in sounds:
sys.stderr.write('len: %.3f, ton: %9.3f, send: %d' % (length, freq, freq2t(freq)))
ser.write(struct.pack('>H', freq2t(freq)))
time.sleep(length)
sys.stderr.write('\n')
ser.write('\0\0')
time.sleep(PAUSE)
finally:
ser.write('\0\0')
ser.close()
def freq2t(freq):
if freq == 0:
return 0
return 2000000/freq
if __name__ == '__main__':
if len(sys.argv) > 1:
if sys.argv[1] == '-d':
for length, freq in parse(sys.stdin.read()):
print 'len: %.3f, ton: %9.3f' % (length, freq)
else:
send(parse(sys.stdin.read()), sys.argv[1])
else:
print >>sys.stderr, "Usage: %s -d|/dev/ttyUSBx" % sys.argv[0]
|