class QmyMainWindow(QMainWindow): def __init__(self, parent=None): super().__init__(parent) #调用父类构造函数,创建窗体 self.ui=Ui_MainWindow() #创建UI对象 self.ui.setupUi(self) #构造UI界面 self.ui.progBar_Max.setMaximum(256) self.ui.progBar_Min.setMaximum(256) self.ui.progBar_Diff.setMaximum(256) self.ui.sliderVolumn.setMaximum(100) self.ui.sliderVolumn.setValue(100) self.ui.comboDevices.clear() self.__deviceList=QAudioDeviceInfo.availableDevices(QAudio.AudioInput) #音频输入设备列表 for i in range(len(self.__deviceList)): device=self.__deviceList[i] #QAudioDeviceInfo类 self.ui.comboDevices.addItem(device.deviceName()) ## self.__deviceInfo =None #当前设备信息,QAudioDeviceInfo self.audioDevice=None #音频输入设备,QAudioInput self.BUFFER_SIZE=4000 self.ioDevice=None #第1种读取方法,内建的IODevice ## self.externalReader=None #第2种读取方法,外建的IODevice self.recordFile=QFile() #第3种读取方法,使用QFile直接写入文件 if len(self.__deviceList)>0: self.ui.comboDevices.setCurrentIndex(0) #触发comboDevices的信号currentIndexChanged() ## self.__deviceInfo =deviceList[0] else: self.ui.actStart.setEnabled(False) self.ui.actDeviceTest.setEnabled(False) self.ui.groupBoxDevice.setTitle("支持的音频输入设置(无设备)") ## ==============自定义功能函数======================== def __getSampleTypeStr(self,sampleType): result="Unknown" if sampleType==QAudioFormat.SignedInt: result = "SignedInt" elif sampleType==QAudioFormat.UnSignedInt: result = "UnSignedInt" elif sampleType==QAudioFormat.Float: result = "Float" elif sampleType==QAudioFormat.Unknown: result = "Unknown" return result def __getByteOrderStr(self,endian): if (endian==QAudioFormat.LittleEndian): return "LittleEndian" else: return "BigEndian" ## ==============event处理函数========================== ## ==========由connectSlotsByName()自动连接的槽函数============ @pyqtSlot(int) ##选择音频输入设备 def on_comboDevices_currentIndexChanged(self,index): deviceInfo =self.__deviceList[index] #当前音频设备,QAudioDeviceInfo类型 self.ui.comboCodec.clear() codecs = deviceInfo.supportedCodecs() #支持的音频编码,字符串列表 for strLine in codecs: self.ui.comboCodec.addItem(strLine) self.ui.comboSampleRate.clear() #支持的采样率 sampleRates = deviceInfo.supportedSampleRates() #QList<int> for i in sampleRates: self.ui.comboSampleRate.addItem("%d"% i) self.ui.comboChannels.clear() #支持的通道数 Channels = deviceInfo.supportedChannelCounts() #QList<int> for i in Channels: self.ui.comboChannels.addItem("%d"%i ) self.ui.comboSampleTypes.clear() #支持的采样点类型 sampleTypes = deviceInfo.supportedSampleTypes() #QList<QAudioFormat::SampleType> for i in sampleTypes: sampTypeStr=self.__getSampleTypeStr(i) self.ui.comboSampleTypes.addItem(sampTypeStr,i) self.ui.comboSampleSizes.clear() #采样点大小 sampleSizes = deviceInfo.supportedSampleSizes() #QList<int> for i in sampleSizes: self.ui.comboSampleSizes.addItem("%d"%i) self.ui.comboByteOrder.clear() #字节序 endians = deviceInfo.supportedByteOrders() #QList<QAudioFormat::Endian> for i in endians: self.ui.comboByteOrder.addItem(self.__getByteOrderStr(i)) @pyqtSlot() ##使用内建IODevice def on_radioSaveMode_Inner_clicked(self): self.ui.groupBox_disp.setVisible(True) @pyqtSlot() ##使用QFile对象(test.raw) def on_radioSaveMode_QFile_clicked(self): self.ui.groupBox_disp.setVisible(False) @pyqtSlot(int) ##调节录音音量 def on_sliderVolumn_valueChanged(self,value): self.ui.LabVol.setText("录音音量(%d%%)"%value) @pyqtSlot() ##测试音频输入设备是否支持选择的设置 def on_actDeviceTest_triggered(self): settings=QAudioFormat() settings.setCodec(self.ui.comboCodec.currentText()) settings.setSampleRate(int(self.ui.comboSampleRate.currentText())) settings.setChannelCount(int(self.ui.comboChannels.currentText())) k=self.ui.comboSampleTypes.currentData() settings.setSampleType(k) #QAudioFormat.SampleType settings.setSampleSize(int(self.ui.comboSampleSizes.currentText())) if (self.ui.comboByteOrder.currentText()=="LittleEndian"): settings.setByteOrder(QAudioFormat.LittleEndian) else: settings.setByteOrder(QAudioFormat.BigEndian) index=self.ui.comboDevices.currentIndex() deviceInfo =self.__deviceList[index] #当前音频设备 if deviceInfo.isFormatSupported(settings): QMessageBox.information(self,"消息","测试成功,设备支持此设置") else: QMessageBox.critical(self,"错误","测试失败,设备不支持此设置") @pyqtSlot() ##开始音频输入 def on_actStart_triggered(self): audioFormat=QAudioFormat() #使用固定格式 audioFormat.setSampleRate(8000) audioFormat.setChannelCount(1) audioFormat.setSampleSize(8) audioFormat.setCodec("audio/pcm") audioFormat.setByteOrder(QAudioFormat.LittleEndian) audioFormat.setSampleType(QAudioFormat.UnSignedInt) index=self.ui.comboDevices.currentIndex() deviceInfo =self.__deviceList[index] #当前音频设备 if (False== deviceInfo.isFormatSupported(audioFormat)): QMessageBox.critical(self,"错误","测试失败,输入设备不支持此设置") return self.audioDevice = QAudioInput(deviceInfo,audioFormat) #音频输入设备 self.audioDevice.setBufferSize(self.BUFFER_SIZE) #设置的缓冲区大小,字节数,并不一定等于实际数据块大小 self.audioDevice.stateChanged.connect(self.do_stateChanged) #状态变化 ##1. 使用 start()->QIODevice 启动,返回的内置的IODevice, pull mode,利用readyRead()信号读出数据 if self.ui.radioSaveMode_Inner.isChecked(): self.ioDevice=self.audioDevice.start() #返回内建的IODevice self.ioDevice.readyRead.connect(self.do_IO_readyRead) ## 2. 自定义流设备QWAudioBlockReader,push mode, start(QIODevice),不行 ## if self.ui.radioSaveMode_External.isChecked(): ## self.externalReader = QmyAudioReader() ## self.externalReader.open(QIODevice.WriteOnly) ## self.externalReader.updateBlockInfo.connect(self.do_updateBlockInfo) ## self.audioDevice.start(self.externalReader) #使用外建的IODevice ##3. 写入文件,用 start(QIODevice)启动 if self.ui.radioSaveMode_QFile.isChecked(): self.recordFile.setFileName("test.raw") self.recordFile.open(QIODevice.WriteOnly) self.audioDevice.start(self.recordFile) @pyqtSlot() ##停止音频输入 def on_actStop_triggered(self): self.audioDevice.stop() self.audioDevice.deleteLater() ##1. 使用 QIODevice =start()返回的内置的IODevice, pull mode,利用readyRead()信号读出数据 #无需处理,停止后self.ioDevice自动变为无效 ##2. 外部IODevice接收音频输入数据的流设备 ## if self.ui.radioSaveMode_External.isChecked(): ## self.externalReader.close() ## self.externalReader.updateBlockSize.disconnect(self.do_updateBlockInfo) ## del self.externalReader #删除外建设备 ##3. 写入文件,start(QIODevice) 启动 if self.ui.radioSaveMode_QFile.isChecked(): self.recordFile.close() #关闭文件 ## =============自定义槽函数=============================== ##1. 使用QIODevice* start()返回的内置的IODevice, pull mode,利用readyRead()信号读出数据 def do_IO_readyRead(self): ##内建IODevice,读取缓冲区数据 self.ui.LabBufferSize.setText("bufferSize()=%d" %self.audioDevice.bufferSize()) byteCount = self.audioDevice.bytesReady() #可以读取的字节数 self.ui.LabBytesReady.setText("bytesReady()=%d"%byteCount) if byteCount>self.BUFFER_SIZE: byteCount=self.BUFFER_SIZE buffer=self.ioDevice.read(byteCount) #返回的是bytes类型,便于处理 ## buffer=self.ioDevice.readAll() #不能用readAll()读取,返回的是QByteArray,需要再转换为bytes ## print(type(buffer)) ## print(buffer) maxSize=len(buffer) ## print(maxSize) self.ui.LabBlockSize.setText("IODevice数据字节数=%d"%maxSize) maxV=0 minV=255 for k in range(maxSize): V=buffer[k] #取一个字节,整数 if V>maxV: maxV=V #求最大值 if V<minV: minV=V #求最小值 self.ui.progBar_Max.setValue(maxV) self.ui.progBar_Min.setValue(minV) self.ui.progBar_Diff.setValue(maxV-minV) def do_stateChanged(self,state): ##设备状态变化 isStoped=(state== QAudio.StoppedState) #停止状态 self.ui.groupBox_saveMode.setEnabled(isStoped) self.ui.sliderVolumn.setEnabled(isStoped) self.ui.actStart.setEnabled(isStoped) self.ui.actStop.setEnabled(not isStoped) self.ui.actDeviceTest.setEnabled(isStoped) self.ui.sliderVolumn.setEnabled(isStoped) if state== QAudio.ActiveState: self.ui.statusBar.showMessage("state: ActiveState") elif state== QAudio.SuspendedState: self.ui.statusBar.showMessage("state: SuspendedState") elif state== QAudio.StoppedState: self.ui.statusBar.showMessage("state: StoppedState") elif state== QAudio.IdleState: self.ui.statusBar.showMessage("state: IdleState") elif state== QAudio.InterruptedState: self.ui.statusBar.showMessage("state: InterruptedState")