def __init__(self, device): super(MainWindow, self).__init__() self.series = QtCharts.QLineSeries() self.chart = QtCharts.QChart() self.chart.addSeries(self.series) self.axisX = QtCharts.QValueAxis() self.axisX.setRange(0, sampleCount) self.axisX.setLabelFormat("%g") self.axisX.setTitleText("Samples") self.axisY = QtCharts.QValueAxis() self.axisY.setRange(-1, 1) self.axisY.setTitleText("Audio level") self.chart.setAxisX(self.axisX, self.series) self.chart.setAxisY(self.axisY, self.series) self.chart.legend().hide() self.chart.setTitle("Data from the microphone ({})".format(device.deviceName())) formatAudio = QAudioFormat() formatAudio.setSampleRate(8000) formatAudio.setChannelCount(1) formatAudio.setSampleSize(8) formatAudio.setCodec("audio/pcm") formatAudio.setByteOrder(QAudioFormat.LittleEndian) formatAudio.setSampleType(QAudioFormat.UnSignedInt) self.audioInput = QAudioInput(device, formatAudio, self) self.ioDevice = self.audioInput.start() self.ioDevice.readyRead.connect(self._readyRead) self.chartView = QtCharts.QChartView(self.chart) self.setCentralWidget(self.chartView) self.buffer = [QPointF(x, 0) for x in range(sampleCount)] self.series.append(self.buffer)
def __init__(self, inference_thread): super(Dialog, self).__init__() self._btn = QPushButton('Record', self) self._label = QLabel('', self) layout = QVBoxLayout() layout.addWidget(self._btn) layout.addWidget(self._label) self.setLayout(layout) self._btn.clicked.connect(self._btn_clicked) self._is_recording = False self._inference_thread = inference_thread self._inference_thread.finished.connect( self._on_transcription_finished) audio_format = QAudioFormat() audio_format.setCodec('audio/pcm') audio_format.setChannelCount(1) audio_format.setSampleSize(16) audio_format.setSampleRate(16000) audio_format.setByteOrder(QAudioFormat.LittleEndian) audio_format.setSampleType(QAudioFormat.SignedInt) input_device_info = QAudioDeviceInfo.defaultInputDevice() if not input_device_info.isFormatSupported(audio_format): print('Can\'t record audio in 16kHz 16-bit signed PCM format.') exit(1) self._audio_input = QAudioInput(audio_format)
class AudioRecorder(QObject): def __init__(self, dialog, inference_thread): super(AudioRecorder, self).__init__() self.dialog = dialog self.inference_thread = inference_thread self.inference_thread.finished.connect(self.on_transcription_finished) self.format = QAudioFormat() self.format.setSampleRate(16000) self.format.setChannelCount(1) self.format.setSampleSize(16) self.format.setCodec("audio/pcm") self.format.setByteOrder(QAudioFormat.LittleEndian) self.format.setSampleType(QAudioFormat.SignedInt) self.recorder = QAudioInput(self.format, self) self.is_recording = False @Slot() def toggle_record(self): if self.is_recording == False: logging.info("Capturing sound") self.is_recording = True self.inference_thread.send_cmd(("start",)) self.recorded_message = self.recorder.start() self.recorded_message.readyRead.connect(self.read_from_IO_devide) else: logging.info("Finished sound capturing") self.is_recording = False self.recorder.stop() self.inference_thread.send_cmd(("finish",)) @Slot() def read_from_IO_devide(self): ''' Forward available audio data to the inference thread. ''' # self.sender() is the IO device returned by QAudioInput.start() self.inference_thread.send_cmd(("data", self.sender().readAll())) @Slot(str) def on_transcription_finished(self, result): logging.info("Transcription: {result}") self.dialog.set_user_message(result) self.dialog.process_user_message() self.dialog.process_machine_message()
def __init__(self, inputDevice, title, xlim, ylim): super(ZeStreamWidget, self).__init__() self.inputDevice = inputDevice # Creating QChart self.series = QtCharts.QLineSeries() self.chart = QtCharts.QChart() self.chart.addSeries(self.series) self.axisX = QtCharts.QValueAxis() self.axisX.setRange(0, sampleCount) self.axisX.setLabelFormat("%g") self.axisX.setTitleText("Samples") self.chart.setAxisX(self.axisX, self.series) self.axisY = QtCharts.QValueAxis() self.axisY.setRange(-1, 1) self.chart.setAxisY(self.axisY, self.series) self.chart.legend().hide() self.chart.setTitle(title) formatAudio = QAudioFormat() formatAudio.setSampleRate(8000) formatAudio.setChannelCount(1) formatAudio.setSampleSize(8) formatAudio.setCodec("audio/pcm") formatAudio.setByteOrder(QAudioFormat.LittleEndian) formatAudio.setSampleType(QAudioFormat.UnSignedInt) self.audioInput = QAudioInput(self.inputDevice, formatAudio, self) self.ioDevice = self.audioInput.start() self.ioDevice.readyRead.connect(self._readyRead) self.buffer = [QPointF(x, 0) for x in range(sampleCount)] self.series.append(self.buffer)
class AudioTest(QMainWindow): PUSH_MODE_LABEL = "Enable push mode" PULL_MODE_LABEL = "Enable pull mode" SUSPEND_LABEL = "Suspend playback" RESUME_LABEL = "Resume playback" DurationSeconds = 1 ToneSampleRateHz = 600 DataSampleRateHz = 44100 def __init__(self): super(AudioTest, self).__init__() self.m_device = QAudioDeviceInfo.defaultOutputDevice() self.m_output = None self.initializeWindow() self.initializeAudio() def initializeWindow(self): layout = QVBoxLayout() self.m_deviceBox = QComboBox() self.m_deviceBox.activated[int].connect(self.deviceChanged) for deviceInfo in QAudioDeviceInfo.availableDevices( QAudio.AudioOutput): self.m_deviceBox.addItem(deviceInfo.deviceName(), deviceInfo) layout.addWidget(self.m_deviceBox) self.m_modeButton = QPushButton() self.m_modeButton.clicked.connect(self.toggleMode) self.m_modeButton.setText(self.PUSH_MODE_LABEL) layout.addWidget(self.m_modeButton) self.m_suspendResumeButton = QPushButton( clicked=self.toggleSuspendResume) self.m_suspendResumeButton.setText(self.SUSPEND_LABEL) layout.addWidget(self.m_suspendResumeButton) volumeBox = QHBoxLayout() volumeLabel = QLabel("Volume:") self.m_volumeSlider = QSlider(Qt.Horizontal, minimum=0, maximum=100, singleStep=10) self.m_volumeSlider.valueChanged.connect(self.volumeChanged) volumeBox.addWidget(volumeLabel) volumeBox.addWidget(self.m_volumeSlider) layout.addLayout(volumeBox) window = QWidget() window.setLayout(layout) self.setCentralWidget(window) def initializeAudio(self): self.m_pullTimer = QTimer(self) self.m_pullTimer.timeout.connect(self.pullTimerExpired) self.m_pullMode = True self.m_format = QAudioFormat() self.m_format.setSampleRate(self.DataSampleRateHz) self.m_format.setChannelCount(1) self.m_format.setSampleSize(16) self.m_format.setCodec('audio/pcm') self.m_format.setByteOrder(QAudioFormat.LittleEndian) self.m_format.setSampleType(QAudioFormat.SignedInt) info = QAudioDeviceInfo(QAudioDeviceInfo.defaultOutputDevice()) if not info.isFormatSupported(self.m_format): qWarning("Default format not supported - trying to use nearest") self.m_format = info.nearestFormat(self.m_format) self.m_generator = Generator(self.m_format, self.DurationSeconds * 1000000, self.ToneSampleRateHz, self) self.createAudioOutput() def createAudioOutput(self): self.m_audioOutput = QAudioOutput(self.m_device, self.m_format) self.m_audioOutput.notify.connect(self.notified) self.m_audioOutput.stateChanged.connect(self.handleStateChanged) self.m_generator.start() self.m_audioOutput.start(self.m_generator) self.m_volumeSlider.setValue(self.m_audioOutput.volume() * 100) def deviceChanged(self, index): self.m_pullTimer.stop() self.m_generator.stop() self.m_audioOutput.stop() self.m_device = self.m_deviceBox.itemData(index) self.createAudioOutput() def volumeChanged(self, value): if self.m_audioOutput is not None: self.m_audioOutput.setVolume(value / 100.0) def notified(self): qWarning( "bytesFree = %d, elapsedUSecs = %d, processedUSecs = %d" % (self.m_audioOutput.bytesFree(), self.m_audioOutput.elapsedUSecs(), self.m_audioOutput.processedUSecs())) def pullTimerExpired(self): if self.m_audioOutput is not None and self.m_audioOutput.state( ) != QAudio.StoppedState: chunks = self.m_audioOutput.bytesFree( ) // self.m_audioOutput.periodSize() for _ in range(chunks): data = self.m_generator.read(self.m_audioOutput.periodSize()) if data is None or len( data) != self.m_audioOutput.periodSize(): break self.m_output.write(data) def toggleMode(self): self.m_pullTimer.stop() self.m_audioOutput.stop() if self.m_pullMode: self.m_modeButton.setText(self.PULL_MODE_LABEL) self.m_output = self.m_audioOutput.start() self.m_pullMode = False self.m_pullTimer.start(20) else: self.m_modeButton.setText(self.PUSH_MODE_LABEL) self.m_pullMode = True self.m_audioOutput.start(self.m_generator) self.m_suspendResumeButton.setText(self.SUSPEND_LABEL) def toggleSuspendResume(self): if self.m_audioOutput.state() == QAudio.SuspendedState: qWarning("status: Suspended, resume()") self.m_audioOutput.resume() self.m_suspendResumeButton.setText(self.SUSPEND_LABEL) elif self.m_audioOutput.state() == QAudio.ActiveState: qWarning("status: Active, suspend()") self.m_audioOutput.suspend() self.m_suspendResumeButton.setText(self.RESUME_LABEL) elif self.m_audioOutput.state() == QAudio.StoppedState: qWarning("status: Stopped, resume()") self.m_audioOutput.resume() self.m_suspendResumeButton.setText(self.SUSPEND_LABEL) elif self.m_audioOutput.state() == QAudio.IdleState: qWarning("status: IdleState") stateMap = { QAudio.ActiveState: "ActiveState", QAudio.SuspendedState: "SuspendedState", QAudio.StoppedState: "StoppedState", QAudio.IdleState: "IdleState" } def handleStateChanged(self, state): qWarning("state = " + self.stateMap.get(state, "Unknown"))
class AudioDevice(QObject): """Class for storing computer's audio system information.""" data_ready = Signal(np.ndarray) audio_inputs = Signal(object) def __init__(self, default_device_name): super().__init__() self.default_device_name = default_device_name self._pull_timer = QTimer() self._pull_timer.setInterval(3000) self._pull_timer.timeout.connect(self.write_to_buffer) self._audio_input = None self._input = None self._audio_data_handler = None devices = QAudioDeviceInfo.availableDevices(QAudio.AudioInput) self._device = None self.monitors = [] for item in devices: dev_name = item.deviceName() if dev_name.endswith(".monitor"): self.monitors.append(item) if self.default_device_name and self.default_device_name == item.deviceName( ): self._device = item if not self._device: try: self._device = self.monitors[0] except IndexError: self._device = QAudioDeviceInfo.defaultInputDevice() self.initialize_audio() self.start_audio() def initialize_audio(self): """Set up parameters for audio recording.""" self._format = QAudioFormat() self._format.setSampleRate(44100) self._format.setChannelCount(1) self._format.setSampleSize(8) self._format.setSampleType(QAudioFormat.UnSignedInt) self._format.setByteOrder(QAudioFormat.LittleEndian) self._format.setCodec("audio/pcm") device_info = QAudioDeviceInfo(self._device) if not device_info.isFormatSupported(self._format): print("Default format not supported - trying to use nearest.") self._format = device_info.nearestFormat(self._format) self._audio_data_handler = AudioDataHandler(self._format) self._audio_input = QAudioInput(self._device, self._format) self._audio_data_handler.data_ready.connect(self.data_ready) def start_audio(self): """Start running all audio objects.""" self._audio_data_handler.start() self._audio_input.start(self._audio_data_handler) self._input = self._audio_input.start() self._pull_timer.start() def get_input_devices(self): devices = [] if self._device: devices.append(self._device) for item in self.monitors: if item.deviceName() not in [x.deviceName() for x in devices]: devices.append(item) system_default = QAudioDeviceInfo.defaultInputDevice() if system_default not in [x.deviceName() for x in devices]: devices.append(system_default) return devices def get_input_device_names(self): devices = self.get_input_devices() names = [x.deviceName() for x in devices] return names @Slot(str) def change_audio_input(self, input_name): input_devices = self.monitors input_devices.append(QAudioDeviceInfo.defaultInputDevice()) for i in range(len(input_devices)): if input_devices[i].deviceName() == input_name: self._device = input_devices[i] self.initialize_audio() self.start_audio() break @Slot() def write_to_buffer(self): """Write data to buffer for later analysis.""" len_ = self._audio_input.bytesReady() if len_ > 0: self._audio_data_handler.writeData(self._input.readAll(), len_)
class AudioTest(QMainWindow): PUSH_MODE_LABEL = "Enable push mode" PULL_MODE_LABEL = "Enable pull mode" SUSPEND_LABEL = "Suspend playback" RESUME_LABEL = "Resume playback" DurationSeconds = 1 ToneSampleRateHz = 600 DataSampleRateHz = 44100 def __init__(self): super(AudioTest, self).__init__() self.m_device = QAudioDeviceInfo.defaultOutputDevice() self.m_output = None self.initializeWindow() self.initializeAudio() def initializeWindow(self): layout = QVBoxLayout() self.m_deviceBox = QComboBox() self.m_deviceBox.activated[int].connect(self.deviceChanged) for deviceInfo in QAudioDeviceInfo.availableDevices(QAudio.AudioOutput): self.m_deviceBox.addItem(deviceInfo.deviceName(), deviceInfo) layout.addWidget(self.m_deviceBox) self.m_modeButton = QPushButton() self.m_modeButton.clicked.connect(self.toggleMode) self.m_modeButton.setText(self.PUSH_MODE_LABEL) layout.addWidget(self.m_modeButton) self.m_suspendResumeButton = QPushButton( clicked=self.toggleSuspendResume) self.m_suspendResumeButton.setText(self.SUSPEND_LABEL) layout.addWidget(self.m_suspendResumeButton) volumeBox = QHBoxLayout() volumeLabel = QLabel("Volume:") self.m_volumeSlider = QSlider(Qt.Horizontal, minimum=0, maximum=100, singleStep=10) self.m_volumeSlider.valueChanged.connect(self.volumeChanged) volumeBox.addWidget(volumeLabel) volumeBox.addWidget(self.m_volumeSlider) layout.addLayout(volumeBox) window = QWidget() window.setLayout(layout) self.setCentralWidget(window) def initializeAudio(self): self.m_pullTimer = QTimer(self) self.m_pullTimer.timeout.connect(self.pullTimerExpired) self.m_pullMode = True self.m_format = QAudioFormat() self.m_format.setSampleRate(self.DataSampleRateHz) self.m_format.setChannelCount(1) self.m_format.setSampleSize(16) self.m_format.setCodec('audio/pcm') self.m_format.setByteOrder(QAudioFormat.LittleEndian) self.m_format.setSampleType(QAudioFormat.SignedInt) info = QAudioDeviceInfo(QAudioDeviceInfo.defaultOutputDevice()) if not info.isFormatSupported(self.m_format): qWarning("Default format not supported - trying to use nearest") self.m_format = info.nearestFormat(self.m_format) self.m_generator = Generator(self.m_format, self.DurationSeconds * 1000000, self.ToneSampleRateHz, self) self.createAudioOutput() def createAudioOutput(self): self.m_audioOutput = QAudioOutput(self.m_device, self.m_format) self.m_audioOutput.notify.connect(self.notified) self.m_audioOutput.stateChanged.connect(self.handleStateChanged) self.m_generator.start() self.m_audioOutput.start(self.m_generator) self.m_volumeSlider.setValue(self.m_audioOutput.volume() * 100) def deviceChanged(self, index): self.m_pullTimer.stop() self.m_generator.stop() self.m_audioOutput.stop() self.m_device = self.m_deviceBox.itemData(index) self.createAudioOutput() def volumeChanged(self, value): if self.m_audioOutput is not None: self.m_audioOutput.setVolume(value / 100.0) def notified(self): qWarning("bytesFree = %d, elapsedUSecs = %d, processedUSecs = %d" % ( self.m_audioOutput.bytesFree(), self.m_audioOutput.elapsedUSecs(), self.m_audioOutput.processedUSecs())) def pullTimerExpired(self): if self.m_audioOutput is not None and self.m_audioOutput.state() != QAudio.StoppedState: chunks = self.m_audioOutput.bytesFree() // self.m_audioOutput.periodSize() for _ in range(chunks): data = self.m_generator.read(self.m_audioOutput.periodSize()) if data is None or len(data) != self.m_audioOutput.periodSize(): break self.m_output.write(data) def toggleMode(self): self.m_pullTimer.stop() self.m_audioOutput.stop() if self.m_pullMode: self.m_modeButton.setText(self.PULL_MODE_LABEL) self.m_output = self.m_audioOutput.start() self.m_pullMode = False self.m_pullTimer.start(20) else: self.m_modeButton.setText(self.PUSH_MODE_LABEL) self.m_pullMode = True self.m_audioOutput.start(self.m_generator) self.m_suspendResumeButton.setText(self.SUSPEND_LABEL) def toggleSuspendResume(self): if self.m_audioOutput.state() == QAudio.SuspendedState: qWarning("status: Suspended, resume()") self.m_audioOutput.resume() self.m_suspendResumeButton.setText(self.SUSPEND_LABEL) elif self.m_audioOutput.state() == QAudio.ActiveState: qWarning("status: Active, suspend()") self.m_audioOutput.suspend() self.m_suspendResumeButton.setText(self.RESUME_LABEL) elif self.m_audioOutput.state() == QAudio.StoppedState: qWarning("status: Stopped, resume()") self.m_audioOutput.resume() self.m_suspendResumeButton.setText(self.SUSPEND_LABEL) elif self.m_audioOutput.state() == QAudio.IdleState: qWarning("status: IdleState") stateMap = { QAudio.ActiveState: "ActiveState", QAudio.SuspendedState: "SuspendedState", QAudio.StoppedState: "StoppedState", QAudio.IdleState: "IdleState"} def handleStateChanged(self, state): qWarning("state = " + self.stateMap.get(state, "Unknown"))