blob: d64bf4dc6bf30dd60208257b6ab277d1a16d615a [file] [log] [blame]
Guido van Rossum17448e21995-01-30 11:53:55 +00001QSIZE = 100000
2
3class Play_Audio_mac:
4
5 def __init__(self):
6 self._chan = None
7 self._qsize = QSIZE
8 self._outrate = 22254
9 self._sampwidth = 1
10 self._nchannels = 1
11 self._gc = []
Jack Jansen195e33e1996-01-09 17:15:57 +000012 self._usercallback = None
Guido van Rossum17448e21995-01-30 11:53:55 +000013
14 def __del__(self):
15 self.stop()
Jack Jansen195e33e1996-01-09 17:15:57 +000016 self._usercallback = None
Guido van Rossum17448e21995-01-30 11:53:55 +000017
18 def wait(self):
19 import time
20 while self.getfilled():
21 time.sleep(0.1)
22 self._chan = None
23 self._gc = []
24
25 def stop(self, quietNow = 1):
26 ##chan = self._chan
27 self._chan = None
28 ##chan.SndDisposeChannel(1)
29 self._gc = []
30
31 def setoutrate(self, outrate):
32 self._outrate = outrate
33
34 def setsampwidth(self, sampwidth):
35 self._sampwidth = sampwidth
36
37 def setnchannels(self, nchannels):
38 self._nchannels = nchannels
39
40 def writeframes(self, data):
41 import time
42 from Sound import *
43 import struct
44 if not self._chan:
45 import Snd
46 self._chan = Snd.SndNewChannel(5, 0, self._callback)
47 nframes = len(data) / self._nchannels / self._sampwidth
48 if len(data) != nframes * self._nchannels * self._sampwidth:
49 raise ValueError, 'data is not a whole number of frames'
50 while self._gc and \
51 self.getfilled() + nframes > \
52 self._qsize / self._nchannels / self._sampwidth:
53 time.sleep(0.1)
54 if self._sampwidth == 1:
55 import audioop
56 data = audioop.add(data, '\x80'*len(data), 1)
57 h1 = struct.pack('llhhllbbl',
58 id(data)+12,
59 self._nchannels,
60 self._outrate, 0,
61 0,
62 0,
63 extSH,
64 60,
65 nframes)
66 h2 = 22*'\0'
67 h3 = struct.pack('hhlll',
68 self._sampwidth*8,
69 0,
70 0,
71 0,
72 0)
73 header = h1+h2+h3
74 self._gc.append((header, data))
75 self._chan.SndDoCommand((bufferCmd, 0, header), 0)
76 self._chan.SndDoCommand((callBackCmd, 0, 0), 0)
77
78 def _callback(self, *args):
79 del self._gc[0]
Jack Jansen195e33e1996-01-09 17:15:57 +000080 if self._usercallback:
81 self._usercallback()
82
83 def setcallback(self, callback):
84 self._usercallback = callback
Guido van Rossum17448e21995-01-30 11:53:55 +000085
86 def getfilled(self):
87 filled = 0
88 for header, data in self._gc:
89 filled = filled + len(data)
90 return filled / self._nchannels / self._sampwidth
91
92 def getfillable(self):
Jack Jansen195e33e1996-01-09 17:15:57 +000093 return (self._qsize / self._nchannels / self._sampwidth) - self.getfilled()
Guido van Rossum17448e21995-01-30 11:53:55 +000094
95 def ulaw2lin(self, data):
96 import audioop
97 return audioop.ulaw2lin(data, 2)
98
Jack Jansen66019641996-01-02 12:09:30 +000099def test():
Guido van Rossum17448e21995-01-30 11:53:55 +0000100 import aifc
Jack Jansen66019641996-01-02 12:09:30 +0000101 import macfs
102 fss, ok = macfs.PromptGetFile("Select an AIFF soundfile", "AIFF")
103 if not ok: return
104 fn = fss.as_pathname()
Guido van Rossum17448e21995-01-30 11:53:55 +0000105 af = aifc.open(fn, 'r')
106 print af.getparams()
107 p = Play_Audio_mac()
108 p.setoutrate(af.getframerate())
109 p.setsampwidth(af.getsampwidth())
110 p.setnchannels(af.getnchannels())
111 BUFSIZ = 10000
112 while 1:
113 data = af.readframes(BUFSIZ)
114 if not data: break
115 p.writeframes(data)
Jack Jansen66019641996-01-02 12:09:30 +0000116 print 'wrote', len(data), 'space', p.getfillable()
Guido van Rossum17448e21995-01-30 11:53:55 +0000117 p.wait()
118
119if __name__ == '__main__':
120 test()