1 | QSIZE = 100000
|
---|
2 | error='Audio_mac.error'
|
---|
3 |
|
---|
4 | from warnings import warnpy3k
|
---|
5 | warnpy3k("In 3.x, the Play_Audio_mac module is removed.", stacklevel=2)
|
---|
6 |
|
---|
7 | class Play_Audio_mac:
|
---|
8 |
|
---|
9 | def __init__(self, qsize=QSIZE):
|
---|
10 | self._chan = None
|
---|
11 | self._qsize = qsize
|
---|
12 | self._outrate = 22254
|
---|
13 | self._sampwidth = 1
|
---|
14 | self._nchannels = 1
|
---|
15 | self._gc = []
|
---|
16 | self._usercallback = None
|
---|
17 |
|
---|
18 | def __del__(self):
|
---|
19 | self.stop()
|
---|
20 | self._usercallback = None
|
---|
21 |
|
---|
22 | def wait(self):
|
---|
23 | import time
|
---|
24 | while self.getfilled():
|
---|
25 | time.sleep(0.1)
|
---|
26 | self._chan = None
|
---|
27 | self._gc = []
|
---|
28 |
|
---|
29 | def stop(self, quietNow = 1):
|
---|
30 | ##chan = self._chan
|
---|
31 | self._chan = None
|
---|
32 | ##chan.SndDisposeChannel(1)
|
---|
33 | self._gc = []
|
---|
34 |
|
---|
35 | def setoutrate(self, outrate):
|
---|
36 | self._outrate = outrate
|
---|
37 |
|
---|
38 | def setsampwidth(self, sampwidth):
|
---|
39 | self._sampwidth = sampwidth
|
---|
40 |
|
---|
41 | def setnchannels(self, nchannels):
|
---|
42 | self._nchannels = nchannels
|
---|
43 |
|
---|
44 | def writeframes(self, data):
|
---|
45 | import time
|
---|
46 | from Carbon.Sound import bufferCmd, callBackCmd, extSH
|
---|
47 | import struct
|
---|
48 | import MacOS
|
---|
49 | if not self._chan:
|
---|
50 | from Carbon import Snd
|
---|
51 | self._chan = Snd.SndNewChannel(5, 0, self._callback)
|
---|
52 | nframes = len(data) / self._nchannels / self._sampwidth
|
---|
53 | if len(data) != nframes * self._nchannels * self._sampwidth:
|
---|
54 | raise error, 'data is not a whole number of frames'
|
---|
55 | while self._gc and \
|
---|
56 | self.getfilled() + nframes > \
|
---|
57 | self._qsize / self._nchannels / self._sampwidth:
|
---|
58 | time.sleep(0.1)
|
---|
59 | if self._sampwidth == 1:
|
---|
60 | import audioop
|
---|
61 | data = audioop.add(data, '\x80'*len(data), 1)
|
---|
62 | h1 = struct.pack('llHhllbbl',
|
---|
63 | id(data)+MacOS.string_id_to_buffer,
|
---|
64 | self._nchannels,
|
---|
65 | self._outrate, 0,
|
---|
66 | 0,
|
---|
67 | 0,
|
---|
68 | extSH,
|
---|
69 | 60,
|
---|
70 | nframes)
|
---|
71 | h2 = 22*'\0'
|
---|
72 | h3 = struct.pack('hhlll',
|
---|
73 | self._sampwidth*8,
|
---|
74 | 0,
|
---|
75 | 0,
|
---|
76 | 0,
|
---|
77 | 0)
|
---|
78 | header = h1+h2+h3
|
---|
79 | self._gc.append((header, data))
|
---|
80 | self._chan.SndDoCommand((bufferCmd, 0, header), 0)
|
---|
81 | self._chan.SndDoCommand((callBackCmd, 0, 0), 0)
|
---|
82 |
|
---|
83 | def _callback(self, *args):
|
---|
84 | del self._gc[0]
|
---|
85 | if self._usercallback:
|
---|
86 | self._usercallback()
|
---|
87 |
|
---|
88 | def setcallback(self, callback):
|
---|
89 | self._usercallback = callback
|
---|
90 |
|
---|
91 | def getfilled(self):
|
---|
92 | filled = 0
|
---|
93 | for header, data in self._gc:
|
---|
94 | filled = filled + len(data)
|
---|
95 | return filled / self._nchannels / self._sampwidth
|
---|
96 |
|
---|
97 | def getfillable(self):
|
---|
98 | return (self._qsize / self._nchannels / self._sampwidth) - self.getfilled()
|
---|
99 |
|
---|
100 | def ulaw2lin(self, data):
|
---|
101 | import audioop
|
---|
102 | return audioop.ulaw2lin(data, 2)
|
---|
103 |
|
---|
104 | def test():
|
---|
105 | import aifc
|
---|
106 | import EasyDialogs
|
---|
107 | fn = EasyDialogs.AskFileForOpen(message="Select an AIFF soundfile", typeList=("AIFF",))
|
---|
108 | if not fn: return
|
---|
109 | af = aifc.open(fn, 'r')
|
---|
110 | print af.getparams()
|
---|
111 | p = Play_Audio_mac()
|
---|
112 | p.setoutrate(af.getframerate())
|
---|
113 | p.setsampwidth(af.getsampwidth())
|
---|
114 | p.setnchannels(af.getnchannels())
|
---|
115 | BUFSIZ = 10000
|
---|
116 | while 1:
|
---|
117 | data = af.readframes(BUFSIZ)
|
---|
118 | if not data: break
|
---|
119 | p.writeframes(data)
|
---|
120 | print 'wrote', len(data), 'space', p.getfillable()
|
---|
121 | p.wait()
|
---|
122 |
|
---|
123 | if __name__ == '__main__':
|
---|
124 | test()
|
---|