/Lib/plat-mac/Audio_mac.py

http://unladen-swallow.googlecode.com/ · Python · 124 lines · 105 code · 17 blank · 2 comment · 12 complexity · 7caf9a3245f567ed2fba2660a282524f MD5 · raw file

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