blob: d8b327bd12cb828bc56467bedc25e1de068ebe52 [file] [log] [blame]
Guido van Rossum17448e21995-01-30 11:53:55 +00001QSIZE = 100000
Jack Jansen52a40ac1996-03-18 13:33:48 +00002error='Audio_mac.error'
Guido van Rossum17448e21995-01-30 11:53:55 +00003
4class Play_Audio_mac:
5
Jack Jansen52a40ac1996-03-18 13:33:48 +00006 def __init__(self, qsize=QSIZE):
Guido van Rossum17448e21995-01-30 11:53:55 +00007 self._chan = None
Jack Jansen52a40ac1996-03-18 13:33:48 +00008 self._qsize = qsize
Guido van Rossum17448e21995-01-30 11:53:55 +00009 self._outrate = 22254
10 self._sampwidth = 1
11 self._nchannels = 1
12 self._gc = []
Jack Jansen195e33e1996-01-09 17:15:57 +000013 self._usercallback = None
Guido van Rossum17448e21995-01-30 11:53:55 +000014
15 def __del__(self):
16 self.stop()
Jack Jansen195e33e1996-01-09 17:15:57 +000017 self._usercallback = None
Guido van Rossum17448e21995-01-30 11:53:55 +000018
19 def wait(self):
20 import time
21 while self.getfilled():
22 time.sleep(0.1)
23 self._chan = None
24 self._gc = []
25
26 def stop(self, quietNow = 1):
27 ##chan = self._chan
28 self._chan = None
29 ##chan.SndDisposeChannel(1)
30 self._gc = []
31
32 def setoutrate(self, outrate):
33 self._outrate = outrate
34
35 def setsampwidth(self, sampwidth):
36 self._sampwidth = sampwidth
37
38 def setnchannels(self, nchannels):
39 self._nchannels = nchannels
40
41 def writeframes(self, data):
42 import time
Jack Jansen5a6fdcd2001-08-25 12:15:04 +000043 from Carbon.Sound import bufferCmd, callBackCmd, extSH
Guido van Rossum17448e21995-01-30 11:53:55 +000044 import struct
Jack Jansen1801aad1997-04-03 14:44:41 +000045 import MacOS
Guido van Rossum17448e21995-01-30 11:53:55 +000046 if not self._chan:
Jack Jansen5a6fdcd2001-08-25 12:15:04 +000047 from Carbon import Snd
Guido van Rossum17448e21995-01-30 11:53:55 +000048 self._chan = Snd.SndNewChannel(5, 0, self._callback)
49 nframes = len(data) / self._nchannels / self._sampwidth
50 if len(data) != nframes * self._nchannels * self._sampwidth:
Jack Jansen52a40ac1996-03-18 13:33:48 +000051 raise error, 'data is not a whole number of frames'
Guido van Rossum17448e21995-01-30 11:53:55 +000052 while self._gc and \
53 self.getfilled() + nframes > \
54 self._qsize / self._nchannels / self._sampwidth:
55 time.sleep(0.1)
56 if self._sampwidth == 1:
57 import audioop
58 data = audioop.add(data, '\x80'*len(data), 1)
Jack Jansene396c042001-01-03 11:14:12 +000059 h1 = struct.pack('llHhllbbl',
Jack Jansenf7d8f451998-02-25 15:42:03 +000060 id(data)+MacOS.string_id_to_buffer,
Guido van Rossum17448e21995-01-30 11:53:55 +000061 self._nchannels,
62 self._outrate, 0,
63 0,
64 0,
65 extSH,
66 60,
67 nframes)
68 h2 = 22*'\0'
69 h3 = struct.pack('hhlll',
70 self._sampwidth*8,
71 0,
72 0,
73 0,
74 0)
75 header = h1+h2+h3
76 self._gc.append((header, data))
77 self._chan.SndDoCommand((bufferCmd, 0, header), 0)
78 self._chan.SndDoCommand((callBackCmd, 0, 0), 0)
79
80 def _callback(self, *args):
81 del self._gc[0]
Jack Jansen195e33e1996-01-09 17:15:57 +000082 if self._usercallback:
83 self._usercallback()
84
85 def setcallback(self, callback):
86 self._usercallback = callback
Guido van Rossum17448e21995-01-30 11:53:55 +000087
88 def getfilled(self):
89 filled = 0
90 for header, data in self._gc:
91 filled = filled + len(data)
92 return filled / self._nchannels / self._sampwidth
93
94 def getfillable(self):
Jack Jansen195e33e1996-01-09 17:15:57 +000095 return (self._qsize / self._nchannels / self._sampwidth) - self.getfilled()
Guido van Rossum17448e21995-01-30 11:53:55 +000096
97 def ulaw2lin(self, data):
98 import audioop
99 return audioop.ulaw2lin(data, 2)
100
Jack Jansen66019641996-01-02 12:09:30 +0000101def test():
Guido van Rossum17448e21995-01-30 11:53:55 +0000102 import aifc
Jack Jansen66019641996-01-02 12:09:30 +0000103 import macfs
104 fss, ok = macfs.PromptGetFile("Select an AIFF soundfile", "AIFF")
105 if not ok: return
106 fn = fss.as_pathname()
Guido van Rossum17448e21995-01-30 11:53:55 +0000107 af = aifc.open(fn, 'r')
108 print af.getparams()
109 p = Play_Audio_mac()
110 p.setoutrate(af.getframerate())
111 p.setsampwidth(af.getsampwidth())
112 p.setnchannels(af.getnchannels())
113 BUFSIZ = 10000
114 while 1:
115 data = af.readframes(BUFSIZ)
116 if not data: break
117 p.writeframes(data)
Jack Jansen66019641996-01-02 12:09:30 +0000118 print 'wrote', len(data), 'space', p.getfillable()
Guido van Rossum17448e21995-01-30 11:53:55 +0000119 p.wait()
120
121if __name__ == '__main__':
122 test()