Avoid signed overflow in some xrange calculations, and extend
[python.git] / Demo / scripts / morse.py
blob265fae9f941ff506c8f59bc9d8083686d695c462
1 #! /usr/bin/env python
3 # DAH should be three DOTs.
4 # Space between DOTs and DAHs should be one DOT.
5 # Space between two letters should be one DAH.
6 # Space between two words should be DOT DAH DAH.
8 import sys, math, audiodev
10 DOT = 30
11 DAH = 3 * DOT
12 OCTAVE = 2 # 1 == 441 Hz, 2 == 882 Hz, ...
14 morsetab = {
15 'A': '.-', 'a': '.-',
16 'B': '-...', 'b': '-...',
17 'C': '-.-.', 'c': '-.-.',
18 'D': '-..', 'd': '-..',
19 'E': '.', 'e': '.',
20 'F': '..-.', 'f': '..-.',
21 'G': '--.', 'g': '--.',
22 'H': '....', 'h': '....',
23 'I': '..', 'i': '..',
24 'J': '.---', 'j': '.---',
25 'K': '-.-', 'k': '-.-',
26 'L': '.-..', 'l': '.-..',
27 'M': '--', 'm': '--',
28 'N': '-.', 'n': '-.',
29 'O': '---', 'o': '---',
30 'P': '.--.', 'p': '.--.',
31 'Q': '--.-', 'q': '--.-',
32 'R': '.-.', 'r': '.-.',
33 'S': '...', 's': '...',
34 'T': '-', 't': '-',
35 'U': '..-', 'u': '..-',
36 'V': '...-', 'v': '...-',
37 'W': '.--', 'w': '.--',
38 'X': '-..-', 'x': '-..-',
39 'Y': '-.--', 'y': '-.--',
40 'Z': '--..', 'z': '--..',
41 '0': '-----', ',': '--..--',
42 '1': '.----', '.': '.-.-.-',
43 '2': '..---', '?': '..--..',
44 '3': '...--', ';': '-.-.-.',
45 '4': '....-', ':': '---...',
46 '5': '.....', "'": '.----.',
47 '6': '-....', '-': '-....-',
48 '7': '--...', '/': '-..-.',
49 '8': '---..', '(': '-.--.-',
50 '9': '----.', ')': '-.--.-',
51 ' ': ' ', '_': '..--.-',
54 nowave = '\0' * 200
56 # If we play at 44.1 kHz (which we do), then if we produce one sine
57 # wave in 100 samples, we get a tone of 441 Hz. If we produce two
58 # sine waves in these 100 samples, we get a tone of 882 Hz. 882 Hz
59 # appears to be a nice one for playing morse code.
60 def mkwave(octave):
61 sinewave = ''
62 for i in range(100):
63 val = int(math.sin(math.pi * i * octave / 50.0) * 30000)
64 sinewave += chr((val >> 8) & 255) + chr(val & 255)
65 return sinewave
67 defaultwave = mkwave(OCTAVE)
69 def main():
70 import getopt
71 try:
72 opts, args = getopt.getopt(sys.argv[1:], 'o:p:')
73 except getopt.error:
74 sys.stderr.write('Usage ' + sys.argv[0] +
75 ' [ -o outfile ] [ -p octave ] [ words ] ...\n')
76 sys.exit(1)
77 dev = None
78 wave = defaultwave
79 for o, a in opts:
80 if o == '-o':
81 import aifc
82 dev = aifc.open(a, 'w')
83 dev.setframerate(44100)
84 dev.setsampwidth(2)
85 dev.setnchannels(1)
86 if o == '-p':
87 wave = mkwave(int(a))
88 if not dev:
89 import audiodev
90 dev = audiodev.AudioDev()
91 dev.setoutrate(44100)
92 dev.setsampwidth(2)
93 dev.setnchannels(1)
94 dev.close = dev.stop
95 dev.writeframesraw = dev.writeframes
96 if args:
97 source = [' '.join(args)]
98 else:
99 source = iter(sys.stdin.readline, '')
100 for line in source:
101 mline = morse(line)
102 play(mline, dev, wave)
103 if hasattr(dev, 'wait'):
104 dev.wait()
105 dev.close()
107 # Convert a string to morse code with \001 between the characters in
108 # the string.
109 def morse(line):
110 res = ''
111 for c in line:
112 try:
113 res += morsetab[c] + '\001'
114 except KeyError:
115 pass
116 return res
118 # Play a line of morse code.
119 def play(line, dev, wave):
120 for c in line:
121 if c == '.':
122 sine(dev, DOT, wave)
123 elif c == '-':
124 sine(dev, DAH, wave)
125 else: # space
126 pause(dev, DAH + DOT)
127 pause(dev, DOT)
129 def sine(dev, length, wave):
130 for i in range(length):
131 dev.writeframesraw(wave)
133 def pause(dev, length):
134 for i in range(length):
135 dev.writeframesraw(nowave)
137 if __name__ == '__main__':
138 main()