blob: e7cff6c1bde934cade53474e14368be55c174764 [file] [log] [blame]
Guido van Rossum4acc25b2000-02-02 15:10:15 +00001"""Classes for manipulating audio devices (currently only for Sun and SGI)"""
2
Sjoerd Mullenderaa148371993-12-17 15:18:37 +00003error = 'audiodev.error'
4
5class Play_Audio_sgi:
6 # Private instance variables
Guido van Rossumd7abed31996-08-20 20:40:07 +00007## if 0: access frameratelist, nchannelslist, sampwidthlist, oldparams, \
8## params, config, inited_outrate, inited_width, \
9## inited_nchannels, port, converter, classinited: private
Sjoerd Mullenderaa148371993-12-17 15:18:37 +000010
Guido van Rossumb6775db1994-08-01 11:34:53 +000011 classinited = 0
12 frameratelist = nchannelslist = sampwidthlist = None
13
14 def initclass(self):
15 import AL
Guido van Rossum9d8fe641995-08-09 02:33:38 +000016 self.frameratelist = [
Guido van Rossumb6775db1994-08-01 11:34:53 +000017 (48000, AL.RATE_48000),
18 (44100, AL.RATE_44100),
19 (32000, AL.RATE_32000),
20 (22050, AL.RATE_22050),
21 (16000, AL.RATE_16000),
22 (11025, AL.RATE_11025),
23 ( 8000, AL.RATE_8000),
24 ]
Guido van Rossum9d8fe641995-08-09 02:33:38 +000025 self.nchannelslist = [
Guido van Rossumb6775db1994-08-01 11:34:53 +000026 (1, AL.MONO),
27 (2, AL.STEREO),
Guido van Rossum27eb14d1996-12-13 00:19:56 +000028 (4, AL.QUADRO),
Guido van Rossumb6775db1994-08-01 11:34:53 +000029 ]
Guido van Rossum9d8fe641995-08-09 02:33:38 +000030 self.sampwidthlist = [
Guido van Rossumb6775db1994-08-01 11:34:53 +000031 (1, AL.SAMPLE_8),
32 (2, AL.SAMPLE_16),
33 (3, AL.SAMPLE_24),
34 ]
Guido van Rossum9d8fe641995-08-09 02:33:38 +000035 self.classinited = 1
Sjoerd Mullenderaa148371993-12-17 15:18:37 +000036
37 def __init__(self):
Guido van Rossumb6775db1994-08-01 11:34:53 +000038 import al, AL
39 if not self.classinited:
40 self.initclass()
Sjoerd Mullenderaa148371993-12-17 15:18:37 +000041 self.oldparams = []
42 self.params = [AL.OUTPUT_RATE, 0]
43 self.config = al.newconfig()
44 self.inited_outrate = 0
45 self.inited_width = 0
46 self.inited_nchannels = 0
47 self.converter = None
48 self.port = None
49 return
50
51 def __del__(self):
52 if self.port:
53 self.stop()
54 if self.oldparams:
Guido van Rossumb6775db1994-08-01 11:34:53 +000055 import al, AL
Sjoerd Mullenderaa148371993-12-17 15:18:37 +000056 al.setparams(AL.DEFAULT_DEVICE, self.oldparams)
57 self.oldparams = []
58
59 def wait(self):
60 if not self.port:
61 return
62 import time
63 while self.port.getfilled() > 0:
64 time.sleep(0.1)
65 self.stop()
66
67 def stop(self):
68 if self.port:
69 self.port.closeport()
70 self.port = None
71 if self.oldparams:
Guido van Rossumb6775db1994-08-01 11:34:53 +000072 import al, AL
Sjoerd Mullenderaa148371993-12-17 15:18:37 +000073 al.setparams(AL.DEFAULT_DEVICE, self.oldparams)
74 self.oldparams = []
75
76 def setoutrate(self, rate):
77 for (raw, cooked) in self.frameratelist:
78 if rate == raw:
79 self.params[1] = cooked
80 self.inited_outrate = 1
81 break
82 else:
83 raise error, 'bad output rate'
84
85 def setsampwidth(self, width):
86 for (raw, cooked) in self.sampwidthlist:
87 if width == raw:
88 self.config.setwidth(cooked)
89 self.inited_width = 1
90 break
91 else:
92 if width == 0:
Guido van Rossumb6775db1994-08-01 11:34:53 +000093 import AL
Sjoerd Mullenderaa148371993-12-17 15:18:37 +000094 self.inited_width = 0
95 self.config.setwidth(AL.SAMPLE_16)
96 self.converter = self.ulaw2lin
97 else:
98 raise error, 'bad sample width'
99
100 def setnchannels(self, nchannels):
101 for (raw, cooked) in self.nchannelslist:
102 if nchannels == raw:
103 self.config.setchannels(cooked)
104 self.inited_nchannels = 1
105 break
106 else:
107 raise error, 'bad # of channels'
108
109 def writeframes(self, data):
110 if not (self.inited_outrate and self.inited_nchannels):
111 raise error, 'params not specified'
112 if not self.port:
Guido van Rossumb6775db1994-08-01 11:34:53 +0000113 import al, AL
Sjoerd Mullenderaa148371993-12-17 15:18:37 +0000114 self.port = al.openport('Python', 'w', self.config)
115 self.oldparams = self.params[:]
116 al.getparams(AL.DEFAULT_DEVICE, self.oldparams)
117 al.setparams(AL.DEFAULT_DEVICE, self.params)
118 if self.converter:
119 data = self.converter(data)
120 self.port.writesamps(data)
121
122 def getfilled(self):
123 if self.port:
124 return self.port.getfilled()
125 else:
126 return 0
127
128 def getfillable(self):
129 if self.port:
130 return self.port.getfillable()
131 else:
132 return self.config.getqueuesize()
133
134 # private methods
Guido van Rossumd7abed31996-08-20 20:40:07 +0000135## if 0: access *: private
Sjoerd Mullenderaa148371993-12-17 15:18:37 +0000136
137 def ulaw2lin(self, data):
138 import audioop
139 return audioop.ulaw2lin(data, 2)
140
141class Play_Audio_sun:
Guido van Rossumd7abed31996-08-20 20:40:07 +0000142## if 0: access outrate, sampwidth, nchannels, inited_outrate, inited_width, \
143## inited_nchannels, converter: private
Sjoerd Mullenderaa148371993-12-17 15:18:37 +0000144
145 def __init__(self):
146 self.outrate = 0
147 self.sampwidth = 0
148 self.nchannels = 0
149 self.inited_outrate = 0
150 self.inited_width = 0
151 self.inited_nchannels = 0
152 self.converter = None
153 self.port = None
154 return
155
156 def __del__(self):
157 self.stop()
158
159 def setoutrate(self, rate):
160 self.outrate = rate
161 self.inited_outrate = 1
162
163 def setsampwidth(self, width):
164 self.sampwidth = width
165 self.inited_width = 1
166
167 def setnchannels(self, nchannels):
168 self.nchannels = nchannels
169 self.inited_nchannels = 1
170
171 def writeframes(self, data):
172 if not (self.inited_outrate and self.inited_width and self.inited_nchannels):
173 raise error, 'params not specified'
174 if not self.port:
Guido van Rossumb6775db1994-08-01 11:34:53 +0000175 import sunaudiodev, SUNAUDIODEV
Sjoerd Mullenderaa148371993-12-17 15:18:37 +0000176 self.port = sunaudiodev.open('w')
177 info = self.port.getinfo()
178 info.o_sample_rate = self.outrate
179 info.o_channels = self.nchannels
180 if self.sampwidth == 0:
181 info.o_precision = 8
Guido van Rossum9d8fe641995-08-09 02:33:38 +0000182 self.o_encoding = SUNAUDIODEV.ENCODING_ULAW
183 # XXX Hack, hack -- leave defaults
Sjoerd Mullenderaa148371993-12-17 15:18:37 +0000184 else:
185 info.o_precision = 8 * self.sampwidth
186 info.o_encoding = SUNAUDIODEV.ENCODING_LINEAR
Guido van Rossum9d8fe641995-08-09 02:33:38 +0000187 self.port.setinfo(info)
Sjoerd Mullenderaa148371993-12-17 15:18:37 +0000188 if self.converter:
189 data = self.converter(data)
190 self.port.write(data)
191
192 def wait(self):
193 if not self.port:
194 return
195 self.port.drain()
196 self.stop()
197
198 def stop(self):
199 if self.port:
200 self.port.flush()
201 self.port.close()
202 self.port = None
203
204 def getfilled(self):
205 if self.port:
206 return self.port.obufcount()
207 else:
208 return 0
209
210 def getfillable(self):
211 return BUFFERSIZE - self.getfilled()
212
213def AudioDev():
Guido van Rossum92b44511999-05-03 18:04:07 +0000214 # Dynamically try to import and use a platform specific module.
Sjoerd Mullenderaa148371993-12-17 15:18:37 +0000215 try:
216 import al
Sjoerd Mullenderaa148371993-12-17 15:18:37 +0000217 except ImportError:
218 try:
219 import sunaudiodev
220 return Play_Audio_sun()
221 except ImportError:
Guido van Rossume174c151994-09-16 10:55:53 +0000222 try:
223 import Audio_mac
Guido van Rossume174c151994-09-16 10:55:53 +0000224 except ImportError:
225 raise error, 'no audio device'
Guido van Rossum9d8fe641995-08-09 02:33:38 +0000226 else:
227 return Audio_mac.Play_Audio_mac()
228 else:
229 return Play_Audio_sgi()
Guido van Rossume174c151994-09-16 10:55:53 +0000230
Guido van Rossum27eb14d1996-12-13 00:19:56 +0000231def test(fn = None):
232 import sys
233 if sys.argv[1:]:
234 fn = sys.argv[1]
235 else:
236 fn = 'f:just samples:just.aif'
Guido van Rossume174c151994-09-16 10:55:53 +0000237 import aifc
238 af = aifc.open(fn, 'r')
239 print fn, af.getparams()
240 p = AudioDev()
241 p.setoutrate(af.getframerate())
242 p.setsampwidth(af.getsampwidth())
243 p.setnchannels(af.getnchannels())
244 BUFSIZ = af.getframerate()/af.getsampwidth()/af.getnchannels()
245 while 1:
246 data = af.readframes(BUFSIZ)
247 if not data: break
248 print len(data)
249 p.writeframes(data)
250 p.wait()
251
252if __name__ == '__main__':
253 test()