Remove a ?? in the description of Mac OS support.
[python/dscho.git] / Lib / audiodev.py
blob9d4ddc26e55357c1c980da614030d448cb2a6d9b
1 """Classes for manipulating audio devices (currently only for Sun and SGI)"""
3 class error(Exception):
4 pass
6 class Play_Audio_sgi:
7 # Private instance variables
8 ## if 0: access frameratelist, nchannelslist, sampwidthlist, oldparams, \
9 ## params, config, inited_outrate, inited_width, \
10 ## inited_nchannels, port, converter, classinited: private
12 classinited = 0
13 frameratelist = nchannelslist = sampwidthlist = None
15 def initclass(self):
16 import AL
17 self.frameratelist = [
18 (48000, AL.RATE_48000),
19 (44100, AL.RATE_44100),
20 (32000, AL.RATE_32000),
21 (22050, AL.RATE_22050),
22 (16000, AL.RATE_16000),
23 (11025, AL.RATE_11025),
24 ( 8000, AL.RATE_8000),
26 self.nchannelslist = [
27 (1, AL.MONO),
28 (2, AL.STEREO),
29 (4, AL.QUADRO),
31 self.sampwidthlist = [
32 (1, AL.SAMPLE_8),
33 (2, AL.SAMPLE_16),
34 (3, AL.SAMPLE_24),
36 self.classinited = 1
38 def __init__(self):
39 import al, AL
40 if not self.classinited:
41 self.initclass()
42 self.oldparams = []
43 self.params = [AL.OUTPUT_RATE, 0]
44 self.config = al.newconfig()
45 self.inited_outrate = 0
46 self.inited_width = 0
47 self.inited_nchannels = 0
48 self.converter = None
49 self.port = None
50 return
52 def __del__(self):
53 if self.port:
54 self.stop()
55 if self.oldparams:
56 import al, AL
57 al.setparams(AL.DEFAULT_DEVICE, self.oldparams)
58 self.oldparams = []
60 def wait(self):
61 if not self.port:
62 return
63 import time
64 while self.port.getfilled() > 0:
65 time.sleep(0.1)
66 self.stop()
68 def stop(self):
69 if self.port:
70 self.port.closeport()
71 self.port = None
72 if self.oldparams:
73 import al, AL
74 al.setparams(AL.DEFAULT_DEVICE, self.oldparams)
75 self.oldparams = []
77 def setoutrate(self, rate):
78 for (raw, cooked) in self.frameratelist:
79 if rate == raw:
80 self.params[1] = cooked
81 self.inited_outrate = 1
82 break
83 else:
84 raise error, 'bad output rate'
86 def setsampwidth(self, width):
87 for (raw, cooked) in self.sampwidthlist:
88 if width == raw:
89 self.config.setwidth(cooked)
90 self.inited_width = 1
91 break
92 else:
93 if width == 0:
94 import AL
95 self.inited_width = 0
96 self.config.setwidth(AL.SAMPLE_16)
97 self.converter = self.ulaw2lin
98 else:
99 raise error, 'bad sample width'
101 def setnchannels(self, nchannels):
102 for (raw, cooked) in self.nchannelslist:
103 if nchannels == raw:
104 self.config.setchannels(cooked)
105 self.inited_nchannels = 1
106 break
107 else:
108 raise error, 'bad # of channels'
110 def writeframes(self, data):
111 if not (self.inited_outrate and self.inited_nchannels):
112 raise error, 'params not specified'
113 if not self.port:
114 import al, AL
115 self.port = al.openport('Python', 'w', self.config)
116 self.oldparams = self.params[:]
117 al.getparams(AL.DEFAULT_DEVICE, self.oldparams)
118 al.setparams(AL.DEFAULT_DEVICE, self.params)
119 if self.converter:
120 data = self.converter(data)
121 self.port.writesamps(data)
123 def getfilled(self):
124 if self.port:
125 return self.port.getfilled()
126 else:
127 return 0
129 def getfillable(self):
130 if self.port:
131 return self.port.getfillable()
132 else:
133 return self.config.getqueuesize()
135 # private methods
136 ## if 0: access *: private
138 def ulaw2lin(self, data):
139 import audioop
140 return audioop.ulaw2lin(data, 2)
142 class Play_Audio_sun:
143 ## if 0: access outrate, sampwidth, nchannels, inited_outrate, inited_width, \
144 ## inited_nchannels, converter: private
146 def __init__(self):
147 self.outrate = 0
148 self.sampwidth = 0
149 self.nchannels = 0
150 self.inited_outrate = 0
151 self.inited_width = 0
152 self.inited_nchannels = 0
153 self.converter = None
154 self.port = None
155 return
157 def __del__(self):
158 self.stop()
160 def setoutrate(self, rate):
161 self.outrate = rate
162 self.inited_outrate = 1
164 def setsampwidth(self, width):
165 self.sampwidth = width
166 self.inited_width = 1
168 def setnchannels(self, nchannels):
169 self.nchannels = nchannels
170 self.inited_nchannels = 1
172 def writeframes(self, data):
173 if not (self.inited_outrate and self.inited_width and self.inited_nchannels):
174 raise error, 'params not specified'
175 if not self.port:
176 import sunaudiodev, SUNAUDIODEV
177 self.port = sunaudiodev.open('w')
178 info = self.port.getinfo()
179 info.o_sample_rate = self.outrate
180 info.o_channels = self.nchannels
181 if self.sampwidth == 0:
182 info.o_precision = 8
183 self.o_encoding = SUNAUDIODEV.ENCODING_ULAW
184 # XXX Hack, hack -- leave defaults
185 else:
186 info.o_precision = 8 * self.sampwidth
187 info.o_encoding = SUNAUDIODEV.ENCODING_LINEAR
188 self.port.setinfo(info)
189 if self.converter:
190 data = self.converter(data)
191 self.port.write(data)
193 def wait(self):
194 if not self.port:
195 return
196 self.port.drain()
197 self.stop()
199 def stop(self):
200 if self.port:
201 self.port.flush()
202 self.port.close()
203 self.port = None
205 def getfilled(self):
206 if self.port:
207 return self.port.obufcount()
208 else:
209 return 0
211 def getfillable(self):
212 return BUFFERSIZE - self.getfilled()
214 def AudioDev():
215 # Dynamically try to import and use a platform specific module.
216 try:
217 import al
218 except ImportError:
219 try:
220 import sunaudiodev
221 return Play_Audio_sun()
222 except ImportError:
223 try:
224 import Audio_mac
225 except ImportError:
226 raise error, 'no audio device'
227 else:
228 return Audio_mac.Play_Audio_mac()
229 else:
230 return Play_Audio_sgi()
232 def test(fn = None):
233 import sys
234 if sys.argv[1:]:
235 fn = sys.argv[1]
236 else:
237 fn = 'f:just samples:just.aif'
238 import aifc
239 af = aifc.open(fn, 'r')
240 print fn, af.getparams()
241 p = AudioDev()
242 p.setoutrate(af.getframerate())
243 p.setsampwidth(af.getsampwidth())
244 p.setnchannels(af.getnchannels())
245 BUFSIZ = af.getframerate()/af.getsampwidth()/af.getnchannels()
246 while 1:
247 data = af.readframes(BUFSIZ)
248 if not data: break
249 print len(data)
250 p.writeframes(data)
251 p.wait()
253 if __name__ == '__main__':
254 test()