class AudioTest(QMainWindow): def __init__(self, filename=None): QMainWindow.__init__(self) self.pullTimer = QTimer(self) # Owned by layout self.modeButton = None self.suspendResumeButton = None self.deviceBox = None self.device = QAudioDeviceInfo.defaultOutputDevice() self.generator = None self.audioOutput = None self.output = None self.fmt = QAudioFormat() self.pullMode = False self.buf = QByteArray(BUFFER_SIZE, 0) self.dump = filename self.initializeWindow() self.initializeAudio() def initializeWindow(self): window = QWidget() layout = QVBoxLayout() self.deviceBox = QComboBox(self) for info in QAudioDeviceInfo.availableDevices(QAudio.AudioOutput): self.deviceBox.addItem(info.deviceName(), info) self.deviceBox.activated[int].connect(self.deviceChanged) layout.addWidget(self.deviceBox) self.modeButton = QPushButton(self) self.modeButton.setText(PUSH_MODE_LABEL) self.modeButton.clicked.connect(self.toggleMode) layout.addWidget(self.modeButton) self.suspendResumeButton = QPushButton(self) self.suspendResumeButton.setText(SUSPEND_LABEL) self.suspendResumeButton.clicked.connect(self.toggleSuspendResume) layout.addWidget(self.suspendResumeButton) window.setLayout(layout) self.setCentralWidget(window) window.show() def initializeAudio(self): self.pullTimer.timeout.connect(self.pullTimerExpired) self.pullMode = True self.fmt.setFrequency(DATA_FREQUENCY_HZ) self.fmt.setChannels(1) self.fmt.setSampleSize(16) self.fmt.setCodec('audio/pcm') self.fmt.setByteOrder(QAudioFormat.LittleEndian) self.fmt.setSampleType(QAudioFormat.SignedInt) info = QAudioDeviceInfo(QAudioDeviceInfo.defaultOutputDevice()) if not info.isFormatSupported(self.fmt): print 'Default format not supported - trying to use nearest' self.fmt = info.nearestFormat(self.fmt) self.generator = Generator(self.fmt, DURATION_SECONDS * 1000000, TONE_FREQUENCY_HZ, self, self.dump) self.createAudioOutput() def createAudioOutput(self): self.audioOutput = QAudioOutput(self.device, self.fmt, self) self.audioOutput.notify.connect(self.notified) self.audioOutput.stateChanged.connect(self.stateChanged) self.generator.start() self.audioOutput.start(self.generator) # Slots def notified(self): print 'Bytes free %d, elapsed usecs %d, processed usecs %d' % ( self.audioOutput.bytesFree(), self.audioOutput.elapsedUSecs(), self.audioOutput.processedUSecs()) def pullTimerExpired(self): if self.audioOutput.state() != QAudio.StoppedState: chunks = self.audioOutput.bytesFree() / self.audioOutput.periodSize() while chunks: data = self.generator.read(self.audioOutput.periodSize()) self.output.write(data) if len(data) != self.audioOutput.periodSize(): break chunks -= 1 def toggleMode(self): self.pullTimer.stop() self.audioOutput.stop() if self.pullMode: self.modeButton.setText(PULL_MODE_LABEL) self.output = self.audioOutput.start() self.pullMode = False self.pullTimer.start(5) else: self.modeButton.setText(PUSH_MODE_LABEL) self.pullMode = True self.audioOutput.start(self.generator) self.suspendResumeButton.setText(SUSPEND_LABEL) def toggleSuspendResume(self): if self.audioOutput.state() == QAudio.SuspendedState: print 'Status: Suspended, resuming' self.audioOutput.resume() self.suspendResumeButton.setText(SUSPEND_LABEL) elif self.audioOutput.state() == QAudio.ActiveState: print 'Status: Active, suspending' self.audioOutput.suspend() self.suspendResumeButton.setText(RESUME_LABEL) elif self.audioOutput.state() == QAudio.StoppedState: print 'Status: Stopped, resuming' self.audioOutput.resume() self.suspendResumeButton.setText(SUSPEND_LABEL) elif self.audioOutput.state() == QAudio.IdleState: print 'Status: Idle' def stateChanged(self, state): print 'State changed: ', state def deviceChanged(self, index): self.pullTimer.stop() self.generator.stop() self.audioOutput.stop() self.audioOutput.disconnect(self) self.device = self.deviceBox.itemData(index) self.createAudioOutput()
class TonePlayer(QObject): changed = Signal() def getStateLabel(self): print "Getting" return self._label def setStateLabel(self, value): print "Setting", value self._label = value self.changed.emit() stateLabel = Property(str, getStateLabel, setStateLabel, notify=changed) def __init__(self, devices=None, filename=None, parent=None): QObject.__init__(self, parent) self.pullTimer = QTimer(self) self.buf = QByteArray() self.devices = devices self.device = QAudioDeviceInfo.defaultOutputDevice() self.generator = None self.audioOutput = None self.output = None self.fmt = QAudioFormat() self.pullMode = False self.dump = filename self._label = SUSPEND_LABEL self.initializeAudio() def initializeAudio(self): self.pullTimer.timeout.connect(self.pullTimerExpired) self.pullMode = True self.fmt.setFrequency(DATA_FREQUENCY_HZ) self.fmt.setChannels(1) self.fmt.setSampleSize(16) self.fmt.setCodec('audio/pcm') self.fmt.setByteOrder(QAudioFormat.LittleEndian) self.fmt.setSampleType(QAudioFormat.SignedInt) info = QAudioDeviceInfo(QAudioDeviceInfo.defaultOutputDevice()) if not info.isFormatSupported(self.fmt): print 'Default format not supported - trying to use nearest' self.fmt = info.nearestFormat(self.fmt) self.generator = Generator(self.fmt, DURATION_SECONDS * 1000000, TONE_FREQUENCY_HZ, self, self.dump) self.createAudioOutput() def createAudioOutput(self): self.audioOutput = QAudioOutput(self.device, self.fmt, self) self.audioOutput.notify.connect(self.notified) self.audioOutput.stateChanged.connect(self.stateChanged) self.generator.start() self.audioOutput.start(self.generator) @Slot() def toggleSuspendResume(self): if self.audioOutput.state() == QAudio.SuspendedState: print 'Status: Suspended, resuming' self.audioOutput.resume() self.stateLabel = SUSPEND_LABEL elif self.audioOutput.state() == QAudio.ActiveState: print 'Status: Active, suspending' self.audioOutput.suspend() self.stateLabel = RESUME_LABEL elif self.audioOutput.state() == QAudio.StoppedState: print 'Status: Stopped, resuming' self.audioOutput.resume() self.stateLabel = SUSPEND_LABEL elif self.audioOutput.state() == QAudio.IdleState: print 'Status: Idle' playbackResumed = Signal() @Slot() def toggleMode(self): self.pullTimer.stop() self.audioOutput.stop() if self.pullMode: print "Enabling push mode" self.output = self.audioOutput.start() self.pullMode = False self.pullTimer.start(5) else: print "Enabling pull mode" self.pullMode = True self.audioOutput.start(self.generator) self.playbackResumed.emit() @Slot(int) def deviceChanged(self, index): print "Device changed: index:", index print "Selected device name: ", self.devices[index].deviceName() self.pullTimer.stop() self.generator.stop() self.audioOutput.stop() self.audioOutput.disconnect(self) self.device = self.devices[index] self.createAudioOutput() def stateChanged(self, state): print 'State changed: ', state def notified(self): print 'Bytes free %d, elapsed usecs %d, processed usecs %d' % ( self.audioOutput.bytesFree(), self.audioOutput.elapsedUSecs(), self.audioOutput.processedUSecs()) def pullTimerExpired(self): if self.audioOutput.state() != QAudio.StoppedState: chunks = self.audioOutput.bytesFree( ) / self.audioOutput.periodSize() while chunks: data = self.generator.read(self.audioOutput.periodSize()) self.output.write(data) if len(data) != self.audioOutput.periodSize(): break chunks -= 1
class TonePlayer(QObject): changed = Signal() def getStateLabel(self): print "Getting" return self._label def setStateLabel(self, value): print "Setting", value self._label = value self.changed.emit() stateLabel = Property(str, getStateLabel, setStateLabel, notify=changed) def __init__(self, devices=None, filename=None, parent=None): QObject.__init__(self, parent) self.pullTimer = QTimer(self) self.buf = QByteArray() self.devices = devices self.device = QAudioDeviceInfo.defaultOutputDevice() self.generator = None self.audioOutput = None self.output = None self.fmt = QAudioFormat() self.pullMode = False self.dump = filename self._label = SUSPEND_LABEL self.initializeAudio() def initializeAudio(self): self.pullTimer.timeout.connect(self.pullTimerExpired) self.pullMode = True self.fmt.setFrequency(DATA_FREQUENCY_HZ) self.fmt.setChannels(1) self.fmt.setSampleSize(16) self.fmt.setCodec("audio/pcm") self.fmt.setByteOrder(QAudioFormat.LittleEndian) self.fmt.setSampleType(QAudioFormat.SignedInt) info = QAudioDeviceInfo(QAudioDeviceInfo.defaultOutputDevice()) if not info.isFormatSupported(self.fmt): print "Default format not supported - trying to use nearest" self.fmt = info.nearestFormat(self.fmt) self.generator = Generator(self.fmt, DURATION_SECONDS * 1000000, TONE_FREQUENCY_HZ, self, self.dump) self.createAudioOutput() def createAudioOutput(self): self.audioOutput = QAudioOutput(self.device, self.fmt, self) self.audioOutput.notify.connect(self.notified) self.audioOutput.stateChanged.connect(self.stateChanged) self.generator.start() self.audioOutput.start(self.generator) @Slot() def toggleSuspendResume(self): if self.audioOutput.state() == QAudio.SuspendedState: print "Status: Suspended, resuming" self.audioOutput.resume() self.stateLabel = SUSPEND_LABEL elif self.audioOutput.state() == QAudio.ActiveState: print "Status: Active, suspending" self.audioOutput.suspend() self.stateLabel = RESUME_LABEL elif self.audioOutput.state() == QAudio.StoppedState: print "Status: Stopped, resuming" self.audioOutput.resume() self.stateLabel = SUSPEND_LABEL elif self.audioOutput.state() == QAudio.IdleState: print "Status: Idle" playbackResumed = Signal() @Slot() def toggleMode(self): self.pullTimer.stop() self.audioOutput.stop() if self.pullMode: print "Enabling push mode" self.output = self.audioOutput.start() self.pullMode = False self.pullTimer.start(5) else: print "Enabling pull mode" self.pullMode = True self.audioOutput.start(self.generator) self.playbackResumed.emit() @Slot(int) def deviceChanged(self, index): print "Device changed: index:", index print "Selected device name: ", self.devices[index].deviceName() self.pullTimer.stop() self.generator.stop() self.audioOutput.stop() self.audioOutput.disconnect(self) self.device = self.devices[index] self.createAudioOutput() def stateChanged(self, state): print "State changed: ", state def notified(self): print "Bytes free %d, elapsed usecs %d, processed usecs %d" % ( self.audioOutput.bytesFree(), self.audioOutput.elapsedUSecs(), self.audioOutput.processedUSecs(), ) def pullTimerExpired(self): if self.audioOutput.state() != QAudio.StoppedState: chunks = self.audioOutput.bytesFree() / self.audioOutput.periodSize() while chunks: data = self.generator.read(self.audioOutput.periodSize()) self.output.write(data) if len(data) != self.audioOutput.periodSize(): break chunks -= 1