blob: 5dfd1ab129df432b04105147f05448886e376c24 [file] [log] [blame]
Guido van Rossum4acc25b2000-02-02 15:10:15 +00001"""Classes for manipulating audio devices (currently only for Sun and SGI)"""
2
Fred Drake227b1202000-08-17 05:06:49 +00003class error(Exception):
Tim Peters146965a2001-01-14 18:09:23 +00004 pass
Sjoerd Mullenderaa148371993-12-17 15:18:37 +00005
6class Play_Audio_sgi:
Tim Peters146965a2001-01-14 18:09:23 +00007 # 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
Sjoerd Mullenderaa148371993-12-17 15:18:37 +000011
Tim Peters146965a2001-01-14 18:09:23 +000012 classinited = 0
13 frameratelist = nchannelslist = sampwidthlist = None
Guido van Rossumb6775db1994-08-01 11:34:53 +000014
Tim Peters146965a2001-01-14 18:09:23 +000015 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),
25 ]
26 self.nchannelslist = [
27 (1, AL.MONO),
28 (2, AL.STEREO),
29 (4, AL.QUADRO),
30 ]
31 self.sampwidthlist = [
32 (1, AL.SAMPLE_8),
33 (2, AL.SAMPLE_16),
34 (3, AL.SAMPLE_24),
35 ]
36 self.classinited = 1
Sjoerd Mullenderaa148371993-12-17 15:18:37 +000037
Tim Peters146965a2001-01-14 18:09:23 +000038 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
Sjoerd Mullenderaa148371993-12-17 15:18:37 +000051
Tim Peters146965a2001-01-14 18:09:23 +000052 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 = []
Sjoerd Mullenderaa148371993-12-17 15:18:37 +000059
Tim Peters146965a2001-01-14 18:09:23 +000060 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()
Sjoerd Mullenderaa148371993-12-17 15:18:37 +000067
Tim Peters146965a2001-01-14 18:09:23 +000068 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 = []
Sjoerd Mullenderaa148371993-12-17 15:18:37 +000076
Tim Peters146965a2001-01-14 18:09:23 +000077 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'
Sjoerd Mullenderaa148371993-12-17 15:18:37 +000085
Tim Peters146965a2001-01-14 18:09:23 +000086 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'
Sjoerd Mullenderaa148371993-12-17 15:18:37 +0000100
Tim Peters146965a2001-01-14 18:09:23 +0000101 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'
Sjoerd Mullenderaa148371993-12-17 15:18:37 +0000109
Tim Peters146965a2001-01-14 18:09:23 +0000110 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)
Sjoerd Mullenderaa148371993-12-17 15:18:37 +0000122
Tim Peters146965a2001-01-14 18:09:23 +0000123 def getfilled(self):
124 if self.port:
125 return self.port.getfilled()
126 else:
127 return 0
Sjoerd Mullenderaa148371993-12-17 15:18:37 +0000128
Tim Peters146965a2001-01-14 18:09:23 +0000129 def getfillable(self):
130 if self.port:
131 return self.port.getfillable()
132 else:
133 return self.config.getqueuesize()
Sjoerd Mullenderaa148371993-12-17 15:18:37 +0000134
Tim Peters146965a2001-01-14 18:09:23 +0000135 # private methods
136## if 0: access *: private
Sjoerd Mullenderaa148371993-12-17 15:18:37 +0000137
Tim Peters146965a2001-01-14 18:09:23 +0000138 def ulaw2lin(self, data):
139 import audioop
140 return audioop.ulaw2lin(data, 2)
Sjoerd Mullenderaa148371993-12-17 15:18:37 +0000141
142class Play_Audio_sun:
Tim Peters146965a2001-01-14 18:09:23 +0000143## if 0: access outrate, sampwidth, nchannels, inited_outrate, inited_width, \
144## inited_nchannels, converter: private
Sjoerd Mullenderaa148371993-12-17 15:18:37 +0000145
Tim Peters146965a2001-01-14 18:09:23 +0000146 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
Sjoerd Mullenderaa148371993-12-17 15:18:37 +0000156
Tim Peters146965a2001-01-14 18:09:23 +0000157 def __del__(self):
158 self.stop()
Sjoerd Mullenderaa148371993-12-17 15:18:37 +0000159
Tim Peters146965a2001-01-14 18:09:23 +0000160 def setoutrate(self, rate):
161 self.outrate = rate
162 self.inited_outrate = 1
Sjoerd Mullenderaa148371993-12-17 15:18:37 +0000163
Tim Peters146965a2001-01-14 18:09:23 +0000164 def setsampwidth(self, width):
165 self.sampwidth = width
166 self.inited_width = 1
Sjoerd Mullenderaa148371993-12-17 15:18:37 +0000167
Tim Peters146965a2001-01-14 18:09:23 +0000168 def setnchannels(self, nchannels):
169 self.nchannels = nchannels
170 self.inited_nchannels = 1
Sjoerd Mullenderaa148371993-12-17 15:18:37 +0000171
Tim Peters146965a2001-01-14 18:09:23 +0000172 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)
Sjoerd Mullenderaa148371993-12-17 15:18:37 +0000192
Tim Peters146965a2001-01-14 18:09:23 +0000193 def wait(self):
194 if not self.port:
195 return
196 self.port.drain()
197 self.stop()
Sjoerd Mullenderaa148371993-12-17 15:18:37 +0000198
Tim Peters146965a2001-01-14 18:09:23 +0000199 def stop(self):
200 if self.port:
201 self.port.flush()
202 self.port.close()
203 self.port = None
Sjoerd Mullenderaa148371993-12-17 15:18:37 +0000204
Tim Peters146965a2001-01-14 18:09:23 +0000205 def getfilled(self):
206 if self.port:
207 return self.port.obufcount()
208 else:
209 return 0
Sjoerd Mullenderaa148371993-12-17 15:18:37 +0000210
Tim Peters146965a2001-01-14 18:09:23 +0000211 def getfillable(self):
212 return BUFFERSIZE - self.getfilled()
Sjoerd Mullenderaa148371993-12-17 15:18:37 +0000213
214def AudioDev():
Tim Peters146965a2001-01-14 18:09:23 +0000215 # 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()
Guido van Rossume174c151994-09-16 10:55:53 +0000231
Guido van Rossum27eb14d1996-12-13 00:19:56 +0000232def test(fn = None):
Tim Peters146965a2001-01-14 18:09:23 +0000233 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()
Guido van Rossume174c151994-09-16 10:55:53 +0000252
253if __name__ == '__main__':
Tim Peters146965a2001-01-14 18:09:23 +0000254 test()