| 
									
										
										
										
											1995-01-30 11:53:55 +00:00
										 |  |  | QSIZE = 100000 | 
					
						
							| 
									
										
										
										
											1996-03-18 13:33:48 +00:00
										 |  |  | error='Audio_mac.error' | 
					
						
							| 
									
										
										
										
											1995-01-30 11:53:55 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | class Play_Audio_mac: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-03-18 13:33:48 +00:00
										 |  |  | 	def __init__(self, qsize=QSIZE): | 
					
						
							| 
									
										
										
										
											1995-01-30 11:53:55 +00:00
										 |  |  | 		self._chan = None | 
					
						
							| 
									
										
										
										
											1996-03-18 13:33:48 +00:00
										 |  |  | 		self._qsize = qsize | 
					
						
							| 
									
										
										
										
											1995-01-30 11:53:55 +00:00
										 |  |  | 		self._outrate = 22254 | 
					
						
							|  |  |  | 		self._sampwidth = 1 | 
					
						
							|  |  |  | 		self._nchannels = 1 | 
					
						
							|  |  |  | 		self._gc = [] | 
					
						
							| 
									
										
										
										
											1996-01-09 17:15:57 +00:00
										 |  |  | 		self._usercallback = None | 
					
						
							| 
									
										
										
										
											1995-01-30 11:53:55 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	def __del__(self): | 
					
						
							|  |  |  | 		self.stop() | 
					
						
							| 
									
										
										
										
											1996-01-09 17:15:57 +00:00
										 |  |  | 		self._usercallback = None | 
					
						
							| 
									
										
										
										
											1995-01-30 11:53:55 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	def wait(self): | 
					
						
							|  |  |  | 		import time | 
					
						
							|  |  |  | 		while self.getfilled(): | 
					
						
							|  |  |  | 			time.sleep(0.1) | 
					
						
							|  |  |  | 		self._chan = None | 
					
						
							|  |  |  | 		self._gc = [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	def stop(self, quietNow = 1): | 
					
						
							|  |  |  | 		##chan = self._chan | 
					
						
							|  |  |  | 		self._chan = None | 
					
						
							|  |  |  | 		##chan.SndDisposeChannel(1) | 
					
						
							|  |  |  | 		self._gc = [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	def setoutrate(self, outrate): | 
					
						
							|  |  |  | 		self._outrate = outrate | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	def setsampwidth(self, sampwidth): | 
					
						
							|  |  |  | 		self._sampwidth = sampwidth | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	def setnchannels(self, nchannels): | 
					
						
							|  |  |  | 		self._nchannels = nchannels | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	def writeframes(self, data): | 
					
						
							|  |  |  | 		import time | 
					
						
							| 
									
										
										
										
											2001-08-25 12:15:04 +00:00
										 |  |  | 		from Carbon.Sound import bufferCmd, callBackCmd, extSH | 
					
						
							| 
									
										
										
										
											1995-01-30 11:53:55 +00:00
										 |  |  | 		import struct | 
					
						
							| 
									
										
										
										
											1997-04-03 14:44:41 +00:00
										 |  |  | 		import MacOS | 
					
						
							| 
									
										
										
										
											1995-01-30 11:53:55 +00:00
										 |  |  | 		if not self._chan: | 
					
						
							| 
									
										
										
										
											2001-08-25 12:15:04 +00:00
										 |  |  | 			from Carbon import Snd | 
					
						
							| 
									
										
										
										
											1995-01-30 11:53:55 +00:00
										 |  |  | 			self._chan = Snd.SndNewChannel(5, 0, self._callback) | 
					
						
							|  |  |  | 		nframes = len(data) / self._nchannels / self._sampwidth | 
					
						
							|  |  |  | 		if len(data) != nframes * self._nchannels * self._sampwidth: | 
					
						
							| 
									
										
										
										
											1996-03-18 13:33:48 +00:00
										 |  |  | 			raise error, 'data is not a whole number of frames' | 
					
						
							| 
									
										
										
										
											1995-01-30 11:53:55 +00:00
										 |  |  | 		while self._gc and \ | 
					
						
							|  |  |  | 			  self.getfilled() + nframes > \ | 
					
						
							|  |  |  | 				self._qsize / self._nchannels / self._sampwidth: | 
					
						
							|  |  |  | 			time.sleep(0.1) | 
					
						
							|  |  |  | 		if self._sampwidth == 1: | 
					
						
							|  |  |  | 			import audioop | 
					
						
							|  |  |  | 			data = audioop.add(data, '\x80'*len(data), 1) | 
					
						
							| 
									
										
										
										
											2001-01-03 11:14:12 +00:00
										 |  |  | 		h1 = struct.pack('llHhllbbl', | 
					
						
							| 
									
										
										
										
											1998-02-25 15:42:03 +00:00
										 |  |  | 			id(data)+MacOS.string_id_to_buffer, | 
					
						
							| 
									
										
										
										
											1995-01-30 11:53:55 +00:00
										 |  |  | 			self._nchannels, | 
					
						
							|  |  |  | 			self._outrate, 0, | 
					
						
							|  |  |  | 			0, | 
					
						
							|  |  |  | 			0, | 
					
						
							|  |  |  | 			extSH, | 
					
						
							|  |  |  | 			60, | 
					
						
							|  |  |  | 			nframes) | 
					
						
							|  |  |  | 		h2 = 22*'\0' | 
					
						
							|  |  |  | 		h3 = struct.pack('hhlll', | 
					
						
							|  |  |  | 			self._sampwidth*8, | 
					
						
							|  |  |  | 			0, | 
					
						
							|  |  |  | 			0, | 
					
						
							|  |  |  | 			0, | 
					
						
							|  |  |  | 			0) | 
					
						
							|  |  |  | 		header = h1+h2+h3 | 
					
						
							|  |  |  | 		self._gc.append((header, data)) | 
					
						
							|  |  |  | 		self._chan.SndDoCommand((bufferCmd, 0, header), 0) | 
					
						
							|  |  |  | 		self._chan.SndDoCommand((callBackCmd, 0, 0), 0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	def _callback(self, *args): | 
					
						
							|  |  |  | 		del self._gc[0] | 
					
						
							| 
									
										
										
										
											1996-01-09 17:15:57 +00:00
										 |  |  | 		if self._usercallback: | 
					
						
							|  |  |  | 			self._usercallback() | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 	def setcallback(self, callback): | 
					
						
							|  |  |  | 		self._usercallback = callback | 
					
						
							| 
									
										
										
										
											1995-01-30 11:53:55 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	def getfilled(self): | 
					
						
							|  |  |  | 		filled = 0 | 
					
						
							|  |  |  | 		for header, data in self._gc: | 
					
						
							|  |  |  | 			filled = filled + len(data) | 
					
						
							|  |  |  | 		return filled / self._nchannels / self._sampwidth | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	def getfillable(self): | 
					
						
							| 
									
										
										
										
											1996-01-09 17:15:57 +00:00
										 |  |  | 		return (self._qsize / self._nchannels / self._sampwidth) - self.getfilled() | 
					
						
							| 
									
										
										
										
											1995-01-30 11:53:55 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	def ulaw2lin(self, data): | 
					
						
							|  |  |  | 		import audioop | 
					
						
							|  |  |  | 		return audioop.ulaw2lin(data, 2) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-01-02 12:09:30 +00:00
										 |  |  | def test(): | 
					
						
							| 
									
										
										
										
											1995-01-30 11:53:55 +00:00
										 |  |  | 	import aifc | 
					
						
							| 
									
										
										
										
											2003-02-06 23:12:23 +00:00
										 |  |  | 	import EasyDialogs | 
					
						
							|  |  |  | 	fn = EasyDialogs.AskFileForOpen(message="Select an AIFF soundfile", typeList=("AIFF",)) | 
					
						
							|  |  |  | 	if not fn: return | 
					
						
							| 
									
										
										
										
											1995-01-30 11:53:55 +00:00
										 |  |  | 	af = aifc.open(fn, 'r') | 
					
						
							|  |  |  | 	print af.getparams() | 
					
						
							|  |  |  | 	p = Play_Audio_mac() | 
					
						
							|  |  |  | 	p.setoutrate(af.getframerate()) | 
					
						
							|  |  |  | 	p.setsampwidth(af.getsampwidth()) | 
					
						
							|  |  |  | 	p.setnchannels(af.getnchannels()) | 
					
						
							|  |  |  | 	BUFSIZ = 10000 | 
					
						
							|  |  |  | 	while 1: | 
					
						
							|  |  |  | 		data = af.readframes(BUFSIZ) | 
					
						
							|  |  |  | 		if not data: break | 
					
						
							|  |  |  | 		p.writeframes(data) | 
					
						
							| 
									
										
										
										
											1996-01-02 12:09:30 +00:00
										 |  |  | 		print 'wrote', len(data), 'space', p.getfillable() | 
					
						
							| 
									
										
										
										
											1995-01-30 11:53:55 +00:00
										 |  |  | 	p.wait() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | if __name__ == '__main__': | 
					
						
							|  |  |  | 	test() |