def initAUD(self): # info = QAudioDeviceInfo.defaultInputDevice() if (~info.isFormatSupported(self.audio.format)): # print("警告,设置的默认音频格式并不支持,将尝试采用最相近的支持格式") # 不知道这里面有什么神改动? self.audio.format = info.nearestFormat(self.audio.format) # update_interval = 160 self.audioRecorder = QAudioInput(self.audio.format) self.audioRecorder.setNotifyInterval(update_interval) #按毫秒ms 类似于QTimer的作用 self.audioRecorder.notify.connect(self.processAudioData) self.audioRecorder_TD = QThread() self.audioRecorder.moveToThread(self.audioRecorder_TD) self.audioRecorder_TD.started.connect(self.startRecord) self.audioRecorder.stateChanged.connect(self.recordStopped) # 总结来说线程只是一个容器,里面执行的循环要是没法结束,强制退出也不好操作 # 所以还是好好写好任务流然后发送信号比较合理 self.audioPlayer = QAudioOutput(self.audio.format) self.audioPlayer.setNotifyInterval(update_interval) self.audioPlayer.notify.connect(self.processAudioData) self.audioPlayer_TD = QThread() self.audioPlayer.moveToThread(self.audioPlayer_TD) self.audioPlayer_TD.started.connect(self.startPlay) self.audioPlayer.stateChanged.connect(self.playStopped)
def in_dev_change(self, new_index): # Disconnect and stop the devices if they are connected. self.disconnect_devices() self.input_device = None # device object goes out of scope # Get the QAudioDeviceInfo corresponding to this index of the combox. audio_info = self.input_info_list[new_index] # Create a new QAudioInput based on that. preferred_format = audio_info.preferredFormat() self.input_device = QAudioInput(audio_info, preferred_format) # the input device volume is always 1.0, wide open. self.input_device.setVolume(1.0) # The choice of buffer size has a major impact on the lag. It needs # to be small or there is severe echo; but if it is too small, there # is a sputtering or "motor-boating" effect. self.input_device.setBufferSize(384) # hook up possible debug status display self.input_device.stateChanged.connect(self.in_dev_state_change) # reconnect the devices if possible. self.reconnect_devices()
def __init__(self, output_path: str, mw: aqt.AnkiQt, parent: QWidget) -> None: super().__init__(output_path) self.mw = mw self._parent = parent from PyQt5.QtMultimedia import QAudioDeviceInfo, QAudioFormat, QAudioInput format = QAudioFormat() format.setChannelCount(1) format.setSampleRate(44100) format.setSampleSize(16) format.setCodec("audio/pcm") format.setByteOrder(QAudioFormat.LittleEndian) format.setSampleType(QAudioFormat.SignedInt) device = QAudioDeviceInfo.defaultInputDevice() if not device.isFormatSupported(format): format = device.nearestFormat(format) print("format changed") print("channels", format.channelCount()) print("rate", format.sampleRate()) print("size", format.sampleSize()) self._format = format self._audio_input = QAudioInput(device, format, parent)
def changeinput(self, val): audio = QAudioFormat() audio.setSampleRate(44100) audio.setSampleType(QAudioFormat.UnSignedInt) audio.setSampleSize(8) audio.setCodec('audio/pcm') audio.setChannelCount(1) self.input = QAudioInput(self.inputdevices[val], audio)
def setup(self): self.output.setFileName("record.pcm") self.output.open(QIODevice.WriteOnly | QIODevice.Truncate) settings = QAudioFormat() settings.setCodec("audio/pcm") settings.setSampleRate(16000) settings.setSampleSize(16) settings.setChannelCount(1) settings.setByteOrder(QAudioFormat.LittleEndian) settings.setSampleType(QAudioFormat.SignedInt) self.audio = QAudioInput(settings)
class AudioRecPlot(QWidget): def __init__(self): super().__init__() self.m_chart = QChart() chart_view = QChartView(self.m_chart) chart_view.setMinimumSize(800, 600) self.m_series = QLineSeries() self.m_chart.addSeries(self.m_series) axis_x = QValueAxis() axis_x.setRange(0, 2000) axis_x.setLabelFormat("%g") axis_x.setTitleText("Samples") axis_y = QValueAxis() axis_y.setRange(-1, 1) axis_y.setTitleText("Audio level") self.m_chart.setAxisX(axis_x, self.m_series) self.m_chart.setAxisY(axis_y, self.m_series) self.m_chart.setTitle("Data from the microphone") main_layout = QVBoxLayout() main_layout.addWidget(chart_view) self.setLayout(main_layout) format_audio = QAudioFormat() format_audio.setSampleRate(48000) format_audio.setChannelCount(1) format_audio.setSampleSize(8) format_audio.setCodec("audio/pcm") format_audio.setByteOrder(QAudioFormat.LittleEndian) format_audio.setSampleType(QAudioFormat.UnSignedInt) input_devices = QAudioDeviceInfo.defaultInputDevice() self.m_audio_input = QAudioInput(input_devices, format_audio) self.m_device = XYSeriesIODevice(self.m_series) self.m_device.open(QIODevice.WriteOnly) self.m_audio_input.start(self.m_device) self.init_ui() def init_ui(self): self.show() def __exit__(self, exc_type, exc_val, exc_tb): self.m_audio_input.stop() self.m_device.close()
def __init__(self): super(Recorder, self).__init__() self.setupUi(self) self.output = QFile() self.audio = QAudioInput() self.NEED_ASR = False self.Open = True self.th1 = threading.Thread(target=self.ASR) self.th1.start() self.Pause_Button.clicked.connect(self.toggle_pause) self.Record_Button.clicked.connect(self.toggle_record)
class QDeckAudioItemWidget(QAudioInput): audio_input = None outputFile = None def __init__(self): super().__init__() def initAudioInput(self, filepath): self.outputFile = QFile() self.outputFile.setFileName(filepath) self.outputFile.open(QIODevice.WriteOnly | QIODevice.Truncate) format = QAudioFormat() format.setSampleType(QAudioFormat.Float) format.setSampleRate(44100) format.setChannelCount(1) format.setSampleSize(32) format.setCodec("audio/pcm") format.setByteOrder(QAudioFormat.LittleEndian) print(format.codec()) #self.audio_input = QAudioInput(QAudioDeviceInfo.defaultInputDevice(), format); self.audio_input = QAudioInput(format) print(self.audio_input.error()) print(self.audio_input.state()) #QTimer.singleShot(3000, self, def start(self): self.audio_input.start(self.outputFile) def stop(self): self.audio_input.stop() self.outputFile.close() def suspend(self): self.audio_input.suspend() def resume(self): self.audio_input.resume()
def in_dev_change(self, new_index): if self.input_device: if self.otput_device: self.otput_device.stop() self.input_device.stop() self.input_device = None # goodby object # Get the QAudioDeviceInfo corresponding to this index of the combox. audio_info = self.input_info_list[new_index] # Create a new QAudioInput based on that. preferred_format = audio_info.preferredFormat() self.input_device = QAudioInput(audio_info, preferred_format) self.input_device.setVolume(1.0) self.input_device.setBufferSize(384) # If we have an output device, redirect it to this input. This is # done by asking the input device for its QIODevice, and passing that # to the output device's start() method. if self.otput_device: self.input_device.start(self.otput_device.start())
def initializeAudio(self, deviceInfo): """ Make a QAudioInput from the given device """ # make buffers of 40ms of samples self.refRate = 0.04 # mono, 32-bit float audio fmt = QAudioFormat() fmt.setSampleRate(self.getSampleRate()) fmt.setChannelCount(1) fmt.setSampleSize(32) fmt.setSampleType(QAudioFormat.Float) fmt.setByteOrder(QAudioFormat.LittleEndian) fmt.setCodec("audio/pcm") if not deviceInfo.isFormatSupported(fmt): fmt = deviceInfo.nearestFormat(fmt) self.audioInput = QAudioInput(deviceInfo, fmt) self.audioInput.setBufferSize(4*self.buflen) # set size in bytes
def initAudioInput(self, filepath): self.outputFile = QFile() self.outputFile.setFileName(filepath) self.outputFile.open(QIODevice.WriteOnly | QIODevice.Truncate) format = QAudioFormat() format.setSampleType(QAudioFormat.Float) format.setSampleRate(44100) format.setChannelCount(1) format.setSampleSize(32) format.setCodec("audio/pcm") format.setByteOrder(QAudioFormat.LittleEndian) print(format.codec()) #self.audio_input = QAudioInput(QAudioDeviceInfo.defaultInputDevice(), format); self.audio_input = QAudioInput(format) print(self.audio_input.error()) print(self.audio_input.state())
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)
class SideToneWidget(QWidget): def __init__(self, parent): super().__init__(parent) # Save link to main window self.main_window = parent # Get the status bar self.status_bar = parent.statusBar() # Slot that will point to a QAudioInput some day self.input_device = None # Slot that will point to a QAudioOutput in time self.otput_device = None # set up layout, creating: # self.input_info_list, list of QAudioInfo for inputs # self.cb_inputs, combox of input names in same order # self.otput_info_list, list of QAudioInfo for outputs # self.cb_otputs, combox of output names in same order # self.volume, volume slider # self.mute, mute checkbox self._uic() # Connect up signals to slots. # Changes in the comboxes go to in_device and ot_device self.cb_inputs.currentIndexChanged.connect(self.in_dev_change) self.cb_otputs.currentIndexChanged.connect(self.ot_dev_change) # Mute button goes to mute_change self.mute.stateChanged.connect(self.mute_change) # Change in volume goes to volume_change self.volume.valueChanged.connect(self.volume_change) # Start with the mute switch on. This triggers the above two signals. self.mute.setChecked(True) # Slot for any change in volume (or mute). If we have an output device # then convert level to a real and pass to the output device. If the new # level is 0, tell the device to stop; if nonzero, tell it to start. # Note we don't do anything about the input device level, it is always 1.0 def volume_change(self, new_level): if self.otput_device: # we have an output device self.otput_device.setVolume(self.volume.value() / 100) if new_level == 0: # looks like a mute # tell the output device to stop just in case it # doesn't know about volume control. self.otput_device.stop() else: # non-zero level, if the output is stopped, start it if self.otput_device.state() == QAudio.StoppedState: self.otput_device.start() # Slot for mute switch. Note that any change to the volume slider # generates a signal to the volume_change slot. def mute_change(self, onoff): if onoff: # Mute has been clicked ON. Remember the current volume. # Turn the volume to zero. self.volume_level = self.volume.value() self.volume.setValue(0) else: # Mute has been clicked OFF. If we do not yet have input and # output devices, get them. Then reset the old volume level. if self.otput_device is None: # We are starting up and have no devices. Fake a call to # the checkbox-change entries thus creating devices. self.in_dev_change(self.cb_inputs.currentIndex()) self.ot_dev_change(self.cb_inputs.currentIndex()) self.volume.setValue(self.volume_level) # Slots for changes in the selection of the input- and output-device # combo boxes. On startup we have neither an input nor an output device. # We do not know which combox the user will fiddle with first. So either # has to assume that the other device may not yet exist. # # On a change of input choice: if we have an input device, get rid of it. # Create a new input device. Set its level to 1.0. If we # have an output, connect the two. def in_dev_change(self, new_index): if self.input_device: if self.otput_device: self.otput_device.stop() self.input_device.stop() self.input_device = None # goodby object # Get the QAudioDeviceInfo corresponding to this index of the combox. audio_info = self.input_info_list[new_index] # Create a new QAudioInput based on that. preferred_format = audio_info.preferredFormat() self.input_device = QAudioInput(audio_info, preferred_format) self.input_device.setVolume(1.0) self.input_device.setBufferSize(384) # If we have an output device, redirect it to this input. This is # done by asking the input device for its QIODevice, and passing that # to the output device's start() method. if self.otput_device: self.input_device.start(self.otput_device.start()) # self.otput_device.start( self.input_device.start() ) # On a change in the selection of output choice: If we have an output # device, get rid of it. Create a new output device. If we have an input # device, connect the two. Set the output level from the volume slider. def ot_dev_change(self, new_index): if self.otput_device: if self.input_device: self.input_device.stop() self.otput_device.stop() self.otput_device = None audio_info = self.otput_info_list[new_index] preferred_format = audio_info.preferredFormat() self.otput_device = QAudioOutput(audio_info, preferred_format) self.otput_device.setVolume(self.volume.value() / 100) # self.otput_device.setBufferSize( 384 ) if self.input_device: self.input_device.start(self.otput_device.start()) # self.otput_device.start( self.input_device.start() ) def _uic(self): """ set up our layout which consists of: Big Honkin' Label [input combobox] [output combobox] [volume slider] [x] Mute hooking put the signals to useful slots is the job of __init__. Here just make the layout. """ self.setMinimumWidth(400) # Create the big honkin' label and logo icon_pixmap = QPixmap(":/icon.png").scaledToWidth(64) icon_label = QLabel() icon_label.setPixmap(icon_pixmap) text_label = QLabel("Sidetone!") hb_label = QHBoxLayout() hb_label.addStretch(1) hb_label.addWidget(icon_label, 0) hb_label.addWidget(text_label, 0) hb_label.addStretch(1) # Create a list of QAudioInfo objects for inputs self.input_info_list = QAudioDeviceInfo.availableDevices(QAudio.AudioInput) if 0 == len(self.input_info_list): self.input_info_list = [QAudioDeviceInfo.defaultInputDevice()] # Create a combo box and populate it with names of inputs self.cb_inputs = QComboBox() self.cb_inputs.addItems([audio_info.deviceName() for audio_info in self.input_info_list]) # Create a list of QAudioInfo objects for outputs self.otput_info_list = QAudioDeviceInfo.availableDevices(QAudio.AudioOutput) if 0 == len(self.otput_info_list): self.otput_info_list = [QAudioDeviceInfo.defaultOutputDevice()] self.status_bar.showMessage( "{} inputs {} otputs".format(len(self.input_info_list), len(self.otput_info_list)), 2000 ) # Create a combo box and populate it with names of outputs self.cb_otputs = QComboBox() self.cb_otputs.addItems([audio_info.deviceName() for audio_info in self.otput_info_list]) # Lay those two out aligned to the outside hb_combos = QHBoxLayout() hb_combos.addWidget(self.cb_inputs, 1) hb_combos.addStretch(0) hb_combos.addWidget(self.cb_otputs, 1) # Create a volume slider from 0 to 100. self.volume = QSlider(Qt.Horizontal, self) self.volume.setMinimum(0) self.volume.setMaximum(100) self.volume.setTickInterval(10) self.volume.setTickPosition(QSlider.TicksBothSides) # Create a checkbox "Mute" self.mute = QCheckBox("Mute") # Put those together in a row squeezed in the center hb_volume = QHBoxLayout() hb_volume.addStretch(1) hb_volume.addWidget(self.volume, 1) hb_volume.addWidget(self.mute, 0) hb_volume.addStretch(1) # Stack all those up as this widget's layout vlayout = QVBoxLayout() vlayout.addLayout(hb_label) vlayout.addLayout(hb_combos) vlayout.addLayout(hb_volume) self.setLayout(vlayout)
class TabSound(Tab): def __init__(self, obj): super().__init__(obj) self.mode = None self.colors = None self.count = 0 # noinspection PyArgumentList self.inputdevices = QAudioDeviceInfo.availableDevices( QAudio.AudioInput) self.input = None if self.inputdevices: self.changeinput(0) self.stream = None self.timer = QTimer() # connections # noinspection PyUnresolvedReferences self.timer.timeout.connect(self.setcolorinterrupt) self.main.ui.plainTextEdit_bitdetector.textChanged.connect( self.checkinput) self.main.ui.comboBox_input.currentIndexChanged.connect( self.changeinput) self.main.ui.comboBox_effect_music.currentIndexChanged.connect( self.changetextedit) self.main.ui.pushButton_color_low.clicked.connect(self.colorselector) self.main.ui.pushButton_color_mid.clicked.connect(self.colorselector) self.main.ui.pushButton_color_high.clicked.connect(self.colorselector) self.main.ui.verticalSlider_lower_low.valueChanged.connect( self.changeslider) self.main.ui.verticalSlider_lower_mid.valueChanged.connect( self.changeslider) self.main.ui.verticalSlider_lower_high.valueChanged.connect( self.changeslider) self.main.ui.verticalSlider_higher_low.valueChanged.connect( self.changeslider) self.main.ui.verticalSlider_higher_mid.valueChanged.connect( self.changeslider) self.main.ui.verticalSlider_higher_high.valueChanged.connect( self.changeslider) self.main.ui.pushButton_sound_onoff.toggled.connect( self.soundbuttononoff) # update styles effects = ['Smooth', 'Change', 'Flash', 'Strob'] self.main.ui.comboBox_effect_music.addItems(effects) inputs = [i.deviceName() for i in self.inputdevices] self.main.ui.comboBox_input.addItems(inputs) self.updatebuttons() def enabletab(self, flag): self.main.ui.comboBox_input.setEnabled(flag) self.main.ui.comboBox_effect_music.setEnabled(flag) self.main.ui.groupBox_freq.setEnabled(flag) self.main.ui.groupBox_bit_detect.setEnabled(flag) self.main.ui.pushButton_sound_onoff.setEnabled(flag) def updatebuttons(self): color = self.main.ui.pushButton_color_low.text() self.main.ui.pushButton_color_low.setStyleSheet( Color.plainbuttonstyle(color)) color = self.main.ui.pushButton_color_mid.text() self.main.ui.pushButton_color_mid.setStyleSheet( Color.plainbuttonstyle(color)) color = self.main.ui.pushButton_color_high.text() self.main.ui.pushButton_color_high.setStyleSheet( Color.plainbuttonstyle(color)) def checkinput(self): text = self.main.ui.plainTextEdit_bitdetector.toPlainText() style = 'background-color: #ff0000' if not self.main.checktext( text) else '' self.main.ui.plainTextEdit_bitdetector.setStyleSheet(style) def changeinput(self, val): audio = QAudioFormat() audio.setSampleRate(44100) audio.setSampleType(QAudioFormat.UnSignedInt) audio.setSampleSize(8) audio.setCodec('audio/pcm') audio.setChannelCount(1) self.input = QAudioInput(self.inputdevices[val], audio) def changetextedit(self, val): self.main.ui.plainTextEdit_bitdetector.setEnabled(bool(val)) def changeslider(self, val): # 1 <= 2 <= 3 <= 4 <= 5 <= 6 (sliders) if self.main.sender() == self.main.ui.verticalSlider_lower_low: if val + 10 > self.main.ui.verticalSlider_higher_low.value(): self.main.ui.verticalSlider_higher_low.setValue(val + 10) elif self.main.sender() == self.main.ui.verticalSlider_higher_low: if val > self.main.ui.verticalSlider_lower_mid.value(): self.main.ui.verticalSlider_lower_mid.setValue(val) if val - 10 < self.main.ui.verticalSlider_lower_low.value(): self.main.ui.verticalSlider_lower_low.setValue(val - 10) elif self.main.sender() == self.main.ui.verticalSlider_lower_mid: if val + 10 > self.main.ui.verticalSlider_higher_mid.value(): self.main.ui.verticalSlider_higher_mid.setValue(val + 10) if val < self.main.ui.verticalSlider_higher_low.value(): self.main.ui.verticalSlider_higher_low.setValue(val) elif self.main.sender() == self.main.ui.verticalSlider_higher_mid: if val > self.main.ui.verticalSlider_lower_high.value(): self.main.ui.verticalSlider_lower_high.setValue(val) if val - 10 < self.main.ui.verticalSlider_lower_mid.value(): self.main.ui.verticalSlider_lower_mid.setValue(val - 10) elif self.main.sender() == self.main.ui.verticalSlider_lower_high: if val + 10 > self.main.ui.verticalSlider_higher_high.value(): self.main.ui.verticalSlider_higher_high.setValue(val + 10) if val < self.main.ui.verticalSlider_higher_mid.value(): self.main.ui.verticalSlider_higher_mid.setValue(val) elif self.main.sender() == self.main.ui.verticalSlider_higher_high: if val - 10 < self.main.ui.verticalSlider_lower_high.value(): self.main.ui.verticalSlider_lower_high.setValue(val - 10) def colorselector(self): # noinspection PyArgumentList dialog = QColorDialog().getColor() temp = '{:x}'.format(dialog.rgb()) color = '#{}'.format(temp[2:]) self.main.sender().setText(color) self.main.sender().setStyleSheet(Color.plainbuttonstyle(color)) def soundbuttononoff(self, flag): self.main.settabsenable(not flag) if flag: self.mode = self.main.ui.comboBox_effect_music.currentText() text = self.main.ui.plainTextEdit_bitdetector.toPlainText() if self.main.checktext(text): self.colors = text.split() self.count = 0 self.stream = self.input.start() timeout = 50 if self.mode == 'Smooth' else 200 self.timer.start(timeout) else: self.main.ui.pushButton_sound_onoff.setChecked(False) else: self.input.stop() self.timer.stop() self.stream = None def setcolorinterrupt(self): val = self.stream.readAll().data()[-5000:] self.timer.stop() if val: from numpy import fft from numpy.ma import absolute val = [i - 128 for i in val] fur = absolute(fft.fft(val)) freq = fft.fftfreq(len(val), d=1 / 44100) fur = fur[1:int(len(fur) / 2)] freq = freq[1:int(len(freq) / 2)] switch = { 'Smooth': self.smooth, 'Change': self.change, 'Flash': self.flash, 'Strob': self.strob } switch[self.mode](fur, freq) timeout = 50 if self.mode == 'Smooth' else 200 self.timer.start(timeout) def smooth(self, val, freq): lowcolor = Color.hex2rgb(self.main.ui.pushButton_color_low.text()) midcolor = Color.hex2rgb(self.main.ui.pushButton_color_mid.text()) highcolor = Color.hex2rgb(self.main.ui.pushButton_color_high.text()) lowlimits = [ self.main.ui.verticalSlider_lower_low.value(), self.main.ui.verticalSlider_higher_low.value() ] midlimits = [ self.main.ui.verticalSlider_lower_mid.value(), self.main.ui.verticalSlider_higher_mid.value() ] highlimits = [ self.main.ui.verticalSlider_lower_high.value(), self.main.ui.verticalSlider_higher_high.value() ] lowval, midval, highval = [], [], [] for i in range(len(freq)): if lowlimits[0] < freq[i] < lowlimits[1]: lowval.append(val[i]) for i in range(len(freq)): if midlimits[0] < freq[i] < midlimits[1]: midval.append(val[i]) for i in range(len(freq)): if highlimits[0] < freq[i] < highlimits[1]: highval.append(val[i]) lowval = max(lowval) if lowval else 0 midval = max(midval) if midval else 0 highval = max(highval) if highval else 0 mult = [ self.main.ui.doubleSpinBox_mult_low.value(), self.main.ui.doubleSpinBox_mult_mid.value(), self.main.ui.doubleSpinBox_mult_high.value() ] noise = self.main.ui.horizontalSlider_noise.value() limiter = max(val) if max(val) > 4000 else 4000 if limiter > noise: multval = [ (lowval - noise) / (limiter - noise) if lowval > noise else 0, (midval - noise) / (limiter - noise) if midval > noise else 0, (highval - noise) / (limiter - noise) if highval > noise else 0 ] r = (lowcolor[0] + midcolor[0] + highcolor[0]) * mult[0] * multval[0] g = (lowcolor[1] + midcolor[1] + highcolor[1]) * mult[1] * multval[1] b = (lowcolor[2] + midcolor[2] + highcolor[2]) * mult[2] * multval[2] for i in range(6): self.main.setcolor(int(r), int(g), int(b), i) else: for i in range(6): self.main.setcolor(0, 0, 0, i) def change(self, val, freq): freqlow = self.main.ui.verticalSlider_lower_low.value() freqhigh = self.main.ui.verticalSlider_higher_low.value() limit = self.main.ui.horizontalSlider_noise.value() lvl = [] for i in range(len(freq)): if freqlow < freq[i] < freqhigh: lvl.append(val[i]) lvl = sum(lvl) / len(lvl) if lvl > limit: for i in range(6): self.main.setcolor(*Color.hex2rgb(self.colors[self.count]), i) self.count = self.count + 1 if self.count < len( self.colors) - 1 else 0 def flash(self, val, freq): freqlow = self.main.ui.verticalSlider_lower_low.value() freqhigh = self.main.ui.verticalSlider_higher_low.value() limit = self.main.ui.horizontalSlider_noise.value() lvl = [] for i in range(len(freq)): if freqlow < freq[i] < freqhigh: lvl.append(val[i]) lvl = sum(lvl) / len(lvl) if lvl > limit: for i in range(6): self.main.setcolor(*Color.hex2rgb(self.colors[self.count]), i) for i in range(6): self.main.setcolor(0, 0, 0, i) self.count = self.count + 1 if self.count < len( self.colors) - 1 else 0 def strob(self, val, freq): freqlow = self.main.ui.verticalSlider_lower_low.value() freqhigh = self.main.ui.verticalSlider_higher_low.value() limit = self.main.ui.horizontalSlider_noise.value() lvl = [] for i in range(len(freq)): if freqlow < freq[i] < freqhigh: lvl.append(val[i]) lvl = sum(lvl) / len(lvl) if lvl > limit: for _ in range(2): for i in range(6): self.main.setcolor(*Color.hex2rgb(self.colors[self.count]), i) for __ in range(3): for i in range(6): self.main.setcolor(0, 0, 0, i) self.count = self.count + 1 if self.count < len( self.colors) - 1 else 0
class Visualizer(QMainWindow): def __init__(self): super().__init__() self.initUI() self._buflen = 1440 # 4096 def initUI(self): # main window/layout window = QWidget() layout = QVBoxLayout() # layout for audio device and sample rate selection deviceLayout = QHBoxLayout() # make audio device selection box and list of available devices self.deviceBox = QComboBox() defaultDeviceInfo = QAudioDeviceInfo.defaultInputDevice() self.availableDevices = [defaultDeviceInfo] self.availableDevices += QAudioDeviceInfo.availableDevices( QAudio.AudioInput) for device in self.availableDevices: self.deviceBox.addItem(device.deviceName()) # make sample rate label and combobox sRateLabel = QLabel("Sample rate:") sRateLabel.setAlignment(Qt.AlignRight) # user can choose between 44.1 and 48kHz (valid DetectorBank rates) self.sRateBox = QComboBox() self.sRateBox.addItem("44100") self.sRateBox.addItem("48000") self.sRateBox.setCurrentIndex(1) # add device and sr widgets to device layout deviceLayout.addWidget(self.deviceBox) deviceLayout.addWidget(sRateLabel) deviceLayout.addWidget(self.sRateBox) # add device layout to main layout layout.addLayout(deviceLayout) # DetectorBank parameters layout # two rows of three parameters # each param needs label and edit, # and a 'Start' button will be added at the bottom # so grid should be 3x6 detBankParamLayout = QGridLayout() # label and lineedit for each bandwidthLabel = QLabel("Bandwidth (cents):") dampingLabel = QLabel("Damping:") gainLabel = QLabel("Gain:") edoLabel = QLabel("EDO:") lwrLabel = QLabel("Lower note:") uprLabel = QLabel("Upper note:") self.bandwidthEdit = QLineEdit("0") self.dampingEdit = QLineEdit("0.0001") self.gainEdit = QLineEdit("25") self.edoEdit = QLineEdit("12") self.lwrEdit = QLineEdit("A1") self.uprEdit = QLineEdit("A7") # store all in lists detBankParamLabels = [bandwidthLabel, dampingLabel, gainLabel, edoLabel, lwrLabel, uprLabel] detBankParamEdits = [self.bandwidthEdit, self.dampingEdit, self.gainEdit, self.edoEdit, self.lwrEdit, self.uprEdit] # fill first two rows of grid with labels and edits row = 0 for row in range(2): widgetNum = 0 for i in range((row*3), (row*3)+3): detBankParamLayout.addWidget(detBankParamLabels[i], row, widgetNum) widgetNum += 1 detBankParamLayout.addWidget(detBankParamEdits[i], row, widgetNum) widgetNum += 1 # align labels to the right (next to the edit) for i in range(len(detBankParamLabels)): detBankParamLabels[i].setAlignment(Qt.AlignRight) # button to make DetectorBank and start visualisation row += 1 startButton = QPushButton("&Start!") detBankParamLayout.addWidget(startButton, row, 5) startButton.clicked.connect(self.start) # add grid of detbank params (and start button) to main layout layout.addLayout(detBankParamLayout) window.setLayout(layout) self.setCentralWidget(window) self.show() def initializeAudio(self, deviceInfo): """ Make a QAudioInput from the given device """ # make buffers of 40ms of samples self.refRate = 0.04 # mono, 32-bit float audio fmt = QAudioFormat() fmt.setSampleRate(self.getSampleRate()) fmt.setChannelCount(1) fmt.setSampleSize(32) fmt.setSampleType(QAudioFormat.Float) fmt.setByteOrder(QAudioFormat.LittleEndian) fmt.setCodec("audio/pcm") if not deviceInfo.isFormatSupported(fmt): fmt = deviceInfo.nearestFormat(fmt) self.audioInput = QAudioInput(deviceInfo, fmt) self.audioInput.setBufferSize(4*self.buflen) # set size in bytes def startAudio(self): self.audioDevice = self.audioInput.start() self.audioDevice.readyRead.connect(self.updatePlot) def start(self): """ Initialise audio, make DetectorBank, open PlotData window and start audio """ print('Initializing audio...') deviceIdx = self.deviceBox.currentIndex() device = self.availableDevices[deviceIdx] self.initializeAudio(device) print('Making DetectorBank...') pitchOffset = self.makeDetectorBank() print('Making PlotData object...') self.pd = PlotData(self.db.getChans(), pitchOffset) # self.pd.show() print('Starting audio...') self.startAudio() def updatePlot(self): # get data as float32 # 4*buflen is number of bytes data = self.audioDevice.read(4*self.buflen) data = np.frombuffer(data, dtype=np.int16) data = np.array(data/2**15, dtype=np.dtype('float32')) # set DetectorBank input self.db.setInputBuffer(data) # fill z with detector output self.db.getZ(self.z) # self.db.absZ(self.r, self.z) self.pd.update(self.z) # self.close() def makeDetectorBank(self): """ Make DetectorBank from given parameters """ sr = self.getSampleRate() bandwidth_cents = float(self.bandwidthEdit.text()) dmp = float(self.dampingEdit.text()) gain = float(self.gainEdit.text()) edo = float(self.edoEdit.text()) lwr = self.lwrEdit.text() upr = self.uprEdit.text() lwr, pitchOffset = getNoteNum(lwr, edo) upr, _ = getNoteNum(upr, edo) upr += 1 # include upr note in DetectorBank # make and fill frequency and bandwidth arrays freq = np.zeros(int(upr-lwr)) bw = np.zeros(len(freq)) for i in range(len(freq)): k = lwr+i freq[i] = 440*2**(k/edo) # if non-minimum bandwidth detectors requested, find B in Hz if bandwidth_cents != 0: bw[i] = centsToHz(freq[i], bandwidth_cents, edo) # combine into stacked array det_char = np.stack((freq,bw), axis=1) # (almost) empty input buffer buffer = np.zeros(1, dtype=np.float32) # DetectorBank features method = DetectorBank.runge_kutta f_norm = DetectorBank.freq_unnormalized a_norm = DetectorBank.amp_unnormalized self.db = DetectorBank(sr, buffer, 4, det_char, method|f_norm|a_norm, dmp, gain) # create empty output array self.z = np.zeros((int(self.db.getChans()),self.buflen), dtype=np.complex128) self.r = np.zeros(self.z.shape) print("Made DetectorBank with {} channels, with a sample rate of {}Hz" .format(self.db.getChans(), self.db.getSR())) return pitchOffset ## get and/or set various values def getSampleRate(self, returnType=int): return returnType(self.sRateBox.currentText()) @property def refreshRate(self): return self._refRate @refreshRate.setter def refreshRate(self, value): self._refRate = value self.buflen = self._refRate * self.getSampleRate() @property def buflen(self): return self._buflen @buflen.setter def buflen(self, value): self._buflen = int(value)
class QtAudioInputRecorder(Recorder): def __init__(self, output_path: str, mw: aqt.AnkiQt, parent: QWidget) -> None: super().__init__(output_path) self.mw = mw self._parent = parent from PyQt5.QtMultimedia import QAudioDeviceInfo, QAudioFormat, QAudioInput format = QAudioFormat() format.setChannelCount(1) format.setSampleRate(44100) format.setSampleSize(16) format.setCodec("audio/pcm") format.setByteOrder(QAudioFormat.LittleEndian) format.setSampleType(QAudioFormat.SignedInt) device = QAudioDeviceInfo.defaultInputDevice() if not device.isFormatSupported(format): format = device.nearestFormat(format) print("format changed") print("channels", format.channelCount()) print("rate", format.sampleRate()) print("size", format.sampleSize()) self._format = format self._audio_input = QAudioInput(device, format, parent) def start(self, on_done: Callable[[], None]) -> None: self._iodevice = self._audio_input.start() self._buffer = b"" self._iodevice.readyRead.connect(self._on_read_ready) # type: ignore super().start(on_done) def _on_read_ready(self) -> None: self._buffer += cast(bytes, self._iodevice.readAll()) def stop(self, on_done: Callable[[str], None]) -> None: def on_stop_timer() -> None: # read anything remaining in buffer & stop self._on_read_ready() self._audio_input.stop() if err := self._audio_input.error(): showWarning(f"recording failed: {err}") return def write_file() -> None: # swallow the first 300ms to allow audio device to quiesce wait = int(44100 * self.STARTUP_DELAY) if len(self._buffer) <= wait: return self._buffer = self._buffer[wait:] # write out the wave file wf = wave.open(self.output_path, "wb") wf.setnchannels(self._format.channelCount()) wf.setsampwidth(self._format.sampleSize() // 8) wf.setframerate(self._format.sampleRate()) wf.writeframes(self._buffer) wf.close() def and_then(fut: Future) -> None: fut.result() Recorder.stop(self, on_done) self.mw.taskman.run_in_background(write_file, and_then) # schedule the stop for half a second in the future, # to avoid truncating the end of the recording self._stop_timer = t = QTimer(self._parent) t.timeout.connect(on_stop_timer) # type: ignore t.setSingleShot(True) t.start(500)
class AudioAnalysis(QDialog): def __init__(self, mainwin, dir): super().__init__() self.main_Win = mainwin self.snd_record_ctr = 0 self.snd_play_ctr = 0 self.snd_reset_ctr = 0 self.is_snd_recording = None # self.audio = Audio(save_dir=dir) self.initAUD() self.initIF() self.initWaveList() def initIF(self): self.layout = QGridLayout(self) self.setLayout(self.layout) icon = QIcon() icon.addPixmap(QPixmap("./style/logo3.png")) self.setWindowIcon(icon) self.setWindowTitle("语音录制与分析") self.list_LW = QListWidget(self) self.list_LW.setMaximumWidth(160) class WaveSpectrum(QWidget): def __init__(self, parent=None, maindlg=None): super(WaveSpectrum, self).__init__(parent) self.main_Dlg = maindlg #self.pg_PL = pg.PlotWidget(enableMenu=False) self.audio = self.main_Dlg.audio self.layout = QGridLayout(self) self.setLayout(self.layout) self.pg_PL = pg.PlotWidget() #pg.plot(title="Three plot curves") self.pg_PL.hideButtons() self.layout.addWidget(self.pg_PL) self.item = self.pg_PL.getPlotItem() self.item.hideButtons() self.item.setMouseEnabled(y=False) self.item.setYRange(0,20000) range = self.audio.rate/2 self.item.setXRange(-range,range, padding=0) self.axis = self.item.getAxis("bottom") self.axis.setLabel("频率(赫兹)") def updatePlot(self): try: data = np.fromstring(self.audio.block, 'int16') #print(data) T = 1.0/self.audio.rate N = data.shape[0] Fx = (1./N) * np.fft.fft(data) # 万一N==0 except Exception as e: print("??",e) else: f = np.fft.fftfreq(N, T) Fx = np.fft.fftshift(Fx) f = np.fft.fftshift(f) self.item.plot(x=f.tolist(), y=(np.absolute(Fx)).tolist(), clear=True) self.wave_spectrum_PG = WaveSpectrum(maindlg=self) self.result_LB = QLabel(self) self.result_LB.setText("欢迎使用") self.running_SL = QSlider(Qt.Horizontal) self.running_SL.setMinimum(0) self.running_SL.setMaximum(100) self.running_SL.setStyleSheet("QSlider::handle:horizontal {background-color: #d91900;}") self.save_BT = QPushButton(self) self.save_BT.setText("保存与分析") self.save_BT.setMinimumSize(128,32) self.record_BT = QPushButton(self) self.record_BT.setText("开始录音") self.record_BT.setMinimumSize(144,32) self.play_BT = QPushButton(self) self.play_BT.setText("开始播放") self.play_BT.setMinimumSize(144,32) self.reset_BT = QPushButton(self) self.reset_BT.setText("停止") self.reset_BT.setMinimumSize(128,32) self.layout.addWidget(self.list_LW, 0,0,1,1) self.layout.addWidget(self.wave_spectrum_PG, 0,1, 1,3) self.layout.addWidget(self.result_LB, 1,0, 1,4) self.layout.addWidget(self.running_SL, 2,0, 1,4) self.layout.addWidget(self.save_BT, 3,0, 2,1) self.layout.addWidget(self.record_BT, 3,1, 2,1) self.layout.addWidget(self.play_BT, 3,2, 2,1) self.layout.addWidget(self.reset_BT, 3,3, 2,1) self.list_LW.itemClicked.connect(self.sel2Play) self.record_BT.clicked.connect(self.click2Record) self.running_SL.sliderReleased.connect(self.dragPosPlay) # 注意这里得是用户主动的动作哟 另外如果需要点击位置定位的话还必须要重写mousePressEvent,这里就不弄了 self.play_BT.clicked.connect(self.click2Play) self.reset_BT.clicked.connect(self.click2Reset) self.save_BT.clicked.connect(self.click2Save) def initWaveList(self): self.wave_dict = {"小黄":["catH1.wav",0],"小黄骚":["catH2.wav",0], "小黄又骚":["catH3.wav",0], "小黄又又骚":["catH4.wav",0] ,"煤球":["catM1.wav",0],"煤球骚":["catM2.wav",0], "煤球又骚":["catM3.wav",0] ,"老公":["laog.wav",0], "老婆":["laop.wav",0]} for k in self.wave_dict: item = QListWidgetItem() item.setText(k) item.setData(Qt.UserRole, self.wave_dict[k]) self.list_LW.addItem(item) def initAUD(self): # info = QAudioDeviceInfo.defaultInputDevice() if (~info.isFormatSupported(self.audio.format)): # print("警告,设置的默认音频格式并不支持,将尝试采用最相近的支持格式") # 不知道这里面有什么神改动? self.audio.format = info.nearestFormat(self.audio.format) # update_interval = 160 self.audioRecorder = QAudioInput(self.audio.format) self.audioRecorder.setNotifyInterval(update_interval) #按毫秒ms 类似于QTimer的作用 self.audioRecorder.notify.connect(self.processAudioData) self.audioRecorder_TD = QThread() self.audioRecorder.moveToThread(self.audioRecorder_TD) self.audioRecorder_TD.started.connect(self.startRecord) self.audioRecorder.stateChanged.connect(self.recordStopped) # 总结来说线程只是一个容器,里面执行的循环要是没法结束,强制退出也不好操作 # 所以还是好好写好任务流然后发送信号比较合理 self.audioPlayer = QAudioOutput(self.audio.format) self.audioPlayer.setNotifyInterval(update_interval) self.audioPlayer.notify.connect(self.processAudioData) self.audioPlayer_TD = QThread() self.audioPlayer.moveToThread(self.audioPlayer_TD) self.audioPlayer_TD.started.connect(self.startPlay) self.audioPlayer.stateChanged.connect(self.playStopped) # def startRecord(self): self.audioRecorder.start(self.audio.record_buffer) # 独立出来主要就是为了传个参数进去 def click2Record(self): if self.snd_play_ctr != 0: self.audioPlayer.suspend() self.audioPlayer.stop() self.audio.play_buffer.close() self.running_SL.setValue(0) self.audioPlayer_TD.quit() self.snd_play_ctr = 0 self.play_BT.setText("开始播放") # self.is_snd_recording = True self.running_SL.setStyleSheet("QSlider::handle:horizontal {background-color: #d91900;}") self.running_SL.setValue(0) if self.snd_record_ctr == 0: self.audio.record_buffer.open(QIODevice.WriteOnly) self.audioRecorder_TD.start() #注意这里是分线程进行 self.record_BT.setText("暂停录音") self.reset_BT.setText("停止录音") elif self.snd_record_ctr % 2 == 1: self.audioRecorder.suspend() self.result_LB.setText("录音暂停") self.record_BT.setText("继续录音") else: # self.snd_record_ctr % 2 == 0: self.audioRecorder.resume() self.record_BT.setText("暂停录音") self.snd_record_ctr += 1 def recordStopped(self): if self.audioRecorder.state() == QAudio.StoppedState: #==2 #QAudio.IdleState: #==3; self.audioRecorder_TD.quit() def startPlay(self): self.audioPlayer.start(self.audio.play_buffer) def click2Play(self): if self.is_snd_recording == None: self.result_LB.setText("还没录音呢!!!") else: if self.snd_record_ctr % 2 == 1: self.audioRecorder.suspend() self.record_BT.setText("继续录音") self.snd_record_ctr += 1 # self.is_snd_recording = False self.running_SL.setStyleSheet("QSlider::handle:horizontal {background-color: #007ad9;}") if self.snd_play_ctr == 0: data = self.audio.record_buffer.data() self.audio.play_buffer.setData(data) self.audio.play_buffer.open(QIODevice.ReadOnly) # 要在关闭的情况下设置数据然后在以某种模式打开 self.audioPlayer_TD.start() self.running_SL.setValue(0) self.start_time = 0 # self.start_time = self.running_SL.value() / 100 * self.audio.duration # self.audioPlayer.setVolume(0.8) self.play_BT.setText("暂停播放") self.reset_BT.setText("停止播放") elif self.snd_play_ctr % 2 == 1: self.audioPlayer.suspend() self.result_LB.setText("播放暂停") self.play_BT.setText("继续播放") else: self.audioPlayer.resume() self.play_BT.setText("暂停播放") self.snd_play_ctr += 1 def playStopped(self): if self.audioPlayer.state() == QAudio.IdleState: #==3; #QAudio.StoppedState: #==2 self.audioPlayer.stop() self.running_SL.setValue(0) self.audio.play_buffer.close() self.audioPlayer_TD.quit() self.snd_play_ctr = 0 self.play_BT.setText("开始播放") def dragPosPlay(self): if self.is_snd_recording == None: self.running_SL.setValue(0) else: if self.is_snd_recording & (self.snd_record_ctr % 2 == 1): self.audioRecorder.suspend() self.record_BT.setText("继续录音") self.snd_record_ctr += 1 if (not self.is_snd_recording) & (self.snd_play_ctr % 2 == 1): self.audioPlayer.suspend() self.play_BT.setText("继续播放") self.snd_play_ctr += 1 self.is_snd_recording = False self.running_SL.setStyleSheet("QSlider::handle:horizontal {background-color: #007ad9;}") self.audioPlayer.stop() self.audio.play_buffer.close() self.audioPlayer_TD.quit() # data = self.audio.record_buffer.data() self.audio.play_buffer.setData(data) self.audio.play_buffer.open(QIODevice.ReadOnly) # 要在关闭的情况下设置数据然后在以某种模式打开 self.audioPlayer_TD.start() data_size = self.audio.record_buffer.data().size() sel_pcent = self.running_SL.value() / 100 sel_size = int(sel_pcent * data_size) self.audio.pos = int(sel_pcent * (data_size / self.audio.chunksize)) # 重设第几个chunk开始播放 self.start_time = int(sel_pcent * self.audio.duration) # 重设开始播放时间 self.audio.play_buffer.seek(sel_size) self.snd_play_ctr = 1 self.play_BT.setText("暂停播放") def sel2Play(self, item): c0 = (self.is_snd_recording == None) c1 = ((self.is_snd_recording == False) & (self.snd_play_ctr % 2 == 0)) c2 = ((self.is_snd_recording == True) & (self.snd_record_ctr % 2 == 0)) if (c0 | c1 | c2): self.cur_item = item sound_dir = "./sound/" #self.cur_wave = os.path.abspath(item.data(Qt.UserRole)[0]) self.cur_wave = item.data(Qt.UserRole)[0] sound_path = os.path.join(sound_dir, self.cur_wave) with wave.open(sound_path, 'rb') as wf: data = wf.readframes(wf.getnframes()) self.audio.play_buffer.setData(data) self.audio.play_buffer.open(QIODevice.ReadOnly) self.start_time = 0 self.audio.duration = 10 # 随便给了个值,避免产生除0的问题其他没啥用 self.audioPlayer_TD.start() def click2Reset(self): if self.is_snd_recording == None: self.result_LB.setText("还没录音呢!!!") elif self.is_snd_recording: self.audioRecorder.stop() self.audio.record_buffer = QBuffer() self.snd_record_ctr = 0 self.result_LB.setText("录音停止") self.record_BT.setText("开始录音") else: #not self.is_snd_recording: self.audioPlayer.stop() self.audio.pos = 0 self.snd_play_ctr = 0 self.result_LB.setText("播放停止") self.play_BT.setText("开始播放") self.running_SL.setValue(0) def click2Save(self): if self.is_snd_recording == None: self.result_LB.setText("还没录音呢!!!") elif self.is_snd_recording: self.audioRecorder.suspend() else: self.audioPlayer.suspend() #self.audio.save_path = QFileDialog().getSaveFileName(self.main_Dlg, "选个保存的地方吧", new_path)[0] # 注意末尾那个[0]别丢了,不然返回的是tuple类型 self.audio.saveWave() self.snd_record_ctr = 0 self.result_LB.setText("录音存于:{};刚刚应该是{}叫了:)".format(os.path.abspath(self.audio.save_path), self.getMinDist())) self.record_BT.setText("开始录音") def processAudioData(self): if self.is_snd_recording: #self.audioRecorder.state() == QAudio.ActiveState: self.audio.block = self.audio.record_buffer.data().right(self.audio.chunksize) self.audio.duration = self.audioRecorder.processedUSecs() # 注意这里是微秒!!! interval = 10 self.running_SL.setValue((self.audio.duration / 1000000) % interval * (100 / interval)) show_info = "已录制{:.1f}秒".format(self.audio.duration/1000000.0) self.result_LB.setText(show_info) else: # self.audioPlayer.state() == QAudio.ActiveState: # 试过chop 不过好像没有必要 self.audio.block = self.audio.play_buffer.data().mid(self.audio.pos*self.audio.chunksize, self.audio.chunksize) self.audio.pos += 1 self.running_SL.setValue((self.start_time + self.audioPlayer.processedUSecs())/self.audio.duration*100) show_info = "正在播放{:.1f}/{:.1f}秒".format((self.start_time + self.audioPlayer.processedUSecs())/1000000.0 ,self.audio.duration/1000000.0) self.result_LB.setText(show_info) self.wave_spectrum_PG.updatePlot() def getMFCC(self,path): (rate, sig) = scwav.read(path) mfcc_feature = mfcc(sig, rate) nmfcc = np.array(mfcc_feature) y, sr = librosa.load(path) return librosa.feature.mfcc(y, sr) def compareMFCC(self, demo_path): mfcc1 = self.getMFCC(self.audio.save_path) print(demo_path) mfcc2 = self.getMFCC(demo_path) norm = lambda x, y: nlnorm(x-y, ord=1) d, cost_matrix, acc_cost_matrix, path = dtw(mfcc1.T, mfcc2.T, dist=norm) return d def getMinDist(self): i = 1000000 sound_dir = "./sound/" for k in self.wave_dict: self.wave_dict[k][1] = self.compareMFCC(os.path.join(sound_dir, self.wave_dict[k][0])) print("{}:{:.1f}".format(k, self.wave_dict[k][1])) i = min(i, self.wave_dict[k][1]) if i == self.wave_dict[k][1]: min_k = k return min_k
class SideToneWidget(QWidget): def __init__(self, parent, the_settings): super().__init__(parent) # Save link to main window self.main_window = parent # Save link to settings object self.settings = the_settings # Get the status bar self.status_bar = parent.statusBar() # just the time self.time = QTime() self.time.start() # Slot that will point to a QAudioInput some day self.input_device = None # Slot that will point to a QAudioOutput in time self.otput_device = None # set up layout, creating: # self.input_info_list, list of QAudioInfo for inputs # self.cb_inputs, combox of input names in same order # self.otput_info_list, list of QAudioInfo for outputs # self.cb_otputs, combox of output names in same order # self.volume, volume slider # self.mute, mute checkbox self._uic() # Connect up signals to slots. Up to this point, the changes that # _uic() made in e.g. the volume or mute, or the combobox selections, # raised signals that were not connected. Now connect the signals # so that user-changes go to our slots for handling. # Mute button goes to mute_change self.mute.stateChanged.connect(self.mute_change) # Change in volume goes to volume_change self.volume.valueChanged.connect(self.volume_change) # Changes in the combox selections go to in_device and ot_device self.cb_inputs.currentIndexChanged.connect(self.in_dev_change) self.cb_otputs.currentIndexChanged.connect(self.ot_dev_change) # Now pretend the user has made a selection of the in and out devices. # That should result in activating everythings. self.in_dev_change(self.cb_inputs.currentIndex()) self.ot_dev_change(self.cb_otputs.currentIndex()) # Method to disconnect the input and output devices, if they exist. # This is called prior to any change in device selection. # Note that the QWidget class has an existing method disconnect(), # and we do not want to override that, so that name is not used. def disconnect_devices(self): # If an output device exists, make it stop. That prevents it # trying to pull any data from the input device if any. if self.otput_device is not None: self.otput_device.stop() # If an input device exists, make it stop also. That means it # loses track of the output device it was formerly connected to. if self.input_device is not None: self.input_device.stop() # Method to connect the input and output devices, if both exist. This is # called after making any change in device selection. def reconnect_devices(self): if (self.input_device is not None) \ and (self.otput_device is not None ) : # Connect the devices by asking the OUTput device for its # QIODevice, and passing that to the INput device's start() # method. This could equally well be done the other way, # by passing the input dev's IODevice to the output device. self.input_device.start(self.otput_device.start()) #self.otput_device.start( self.input_device.start() ) # In case the output device was just created, set its volume. self.set_volume() # Method to set the volume on the output device. (The input device volume # is always 1.0.) This is called on any change of the volume slider or # of the Mute button or of the output device choice. def set_volume(self): if self.mute.isChecked(): # Mute is ON, set volume to 0 regardless of volume slider volume = 0.0 else: # Mute is OFF, set volume to float version of volume slider volume = self.volume.value() / 100 if self.otput_device: # an output device exists (almost always true), set it self.otput_device.setVolume(volume) # Slot entered upon any change in the volume slider widget. def volume_change(self, new_level): if self.mute.isChecked(): # The Mute button is ON; assume the user wants it OFF, else why # move the slider? Note this causes a call to set_volume(). self.mute.setChecked(False) else: # The Mute button is OFF, just change the volume. self.set_volume() # Slot entered upon toggling of the mute switch, by the user or by the # code calling mute.setChecked(). Make sure the volume is set appropriately. def mute_change(self, onoff): self.set_volume() # Slots for selection of the input and output devices. On startup we have # neither an input nor an output device. We do not know which combox the # user will fiddle with first. # Slot entered upon any change in the selection of the input device # combo box. The argument is the new index of the list of values. def in_dev_change(self, new_index): # Disconnect and stop the devices if they are connected. self.disconnect_devices() self.input_device = None # device object goes out of scope # Get the QAudioDeviceInfo corresponding to this index of the combox. audio_info = self.input_info_list[new_index] # Create a new QAudioInput based on that. preferred_format = audio_info.preferredFormat() self.input_device = QAudioInput(audio_info, preferred_format) # the input device volume is always 1.0, wide open. self.input_device.setVolume(1.0) # The choice of buffer size has a major impact on the lag. It needs # to be small or there is severe echo; but if it is too small, there # is a sputtering or "motor-boating" effect. self.input_device.setBufferSize(384) # hook up possible debug status display self.input_device.stateChanged.connect(self.in_dev_state_change) # reconnect the devices if possible. self.reconnect_devices() # Slot entered upon any change in the selection of output. The argument # is the index to the list of output devices in the combobox. def ot_dev_change(self, new_index): print('index', new_index) # Disconnect and stop the devices if they are connected. self.disconnect_devices() self.otput_device = None # device object goes out of scope # Get the QAudioDeviceInfo corresponding to this index of the combox. audio_info = self.otput_info_list[new_index] # Create a new QAudioOutput based on that. preferred_format = audio_info.preferredFormat() self.otput_device = QAudioOutput(audio_info, preferred_format) self.otput_device.setVolume(0) # reconnect will set correct volume # hook up possible debug status display self.otput_device.stateChanged.connect(self.ot_dev_state_change) # reconnect the devices if possible. Which also sets the volume. self.reconnect_devices() # Show some text in the main-window status bar for 1 second, more or less. def show_status(self, text, duration=1000): self.status_bar.showMessage(text, duration) # Slots called on any "state" change of an audio device. Optionally # show the state in the main window status bar. def in_dev_state_change(self, new_state): #self.show_status( #'{} in dev state {}'.format(self.time.elapsed(),int(new_state)) #) pass def ot_dev_state_change(self, new_state): #self.show_status( #'{} ot dev state {}'.format(self.time.elapsed(),int(new_state)) #) pass # Close events are only received by a top-level widget. When our top-level # widget gets one, indicating the app is done, it calls this method. def closeEvent(self, event): # if we have devices, make them stop. self.disconnect_devices() # if the devices exist, reset them and then trash them. if self.otput_device is not None: self.otput_device.reset() self.otput_device = None if self.input_device is not None: self.input_device.reset() self.input_device = None # Save the current selection of the input and output combo boxes, # in the settings file. in_dev_name = self.cb_inputs.currentText() self.settings.setValue('in_dev_name', in_dev_name) ot_dev_name = self.cb_otputs.currentText() self.settings.setValue('ot_dev_name', ot_dev_name) # Save the volume setting and mute status in the settings. self.settings.setValue('volume', self.volume.value()) self.settings.setValue('mute_status', int(self.mute.isChecked())) def _uic(self): ''' set up our layout which consists of: Big Honkin' Label [input combobox] [output combobox] [volume slider] [x] Mute Hooking the signals to useful slots is the job of __init__. Here just make the layout. ''' self.setMinimumWidth(400) # Create the big honkin' label and logo icon_pixmap = QPixmap(':/icon.png').scaledToWidth(64) icon_label = QLabel() icon_label.setPixmap(icon_pixmap) text_label = QLabel("Sidetone!") hb_label = QHBoxLayout() hb_label.addStretch(1) hb_label.addWidget(icon_label, 0) hb_label.addWidget(text_label, 0) hb_label.addStretch(1) # Create a list of QAudioInfo objects for inputs self.input_info_list = QAudioDeviceInfo.availableDevices( QAudio.AudioInput) if 0 == len(self.input_info_list): self.input_info_list = [QAudioDeviceInfo.defaultInputDevice()] # Make a list of the name-strings for those items. in_dev_names = [ audio_info.deviceName() for audio_info in self.input_info_list ] # Create a combo box and populate it with those names self.cb_inputs = QComboBox() self.cb_inputs.addItems(in_dev_names) # If the in_dev_name from the previous run is in the current list, # make it current, otherwise pick the first item. in_dev_name = self.settings.value('in_dev_name', 'unknown') if in_dev_name in in_dev_names: self.cb_inputs.setCurrentIndex(in_dev_names.index(in_dev_name)) else: self.cb_inputs.setCurrentIndex(0) # Create a list of QAudioInfo objects for outputs self.otput_info_list = QAudioDeviceInfo.availableDevices( QAudio.AudioOutput) if 0 == len(self.otput_info_list): self.otput_info_list = [QAudioDeviceInfo.defaultOutputDevice()] # Make a list of the name-strings of those things ot_dev_names = [ audio_info.deviceName() for audio_info in self.otput_info_list ] # Create a combo box and populate it with those names self.cb_otputs = QComboBox() self.cb_otputs.addItems(ot_dev_names) # If the ot_dev_name from the previous run is in the current list, # make it the current choice in the box. ot_dev_name = self.settings.value('ot_dev_name', 'unknown') if ot_dev_name in ot_dev_names: self.cb_otputs.setCurrentIndex(ot_dev_names.index(ot_dev_name)) else: self.cb_otputs.setCurrentIndex(0) #self.show_status( #'{} inputs {} otputs'.format(len(self.input_info_list),len(self.otput_info_list)) #) # Create a combo box and populate it with names of outputs # Lay those two out aligned to the outside hb_combos = QHBoxLayout() hb_combos.addWidget(self.cb_inputs, 1) hb_combos.addStretch(0) hb_combos.addWidget(self.cb_otputs, 1) # Create a volume slider from 0 to 100. self.volume = QSlider(Qt.Horizontal, self) self.volume.setMinimum(0) self.volume.setMaximum(100) self.volume.setTickInterval(10) self.volume.setTickPosition(QSlider.TicksBothSides) # set the volume slider to the value from the previous run, or zero. self.volume.setValue(self.settings.value('volume', 0)) # Create a checkbox "Mute" self.mute = QCheckBox('Mute') # Set it to the value at the end of the last run, or to True self.mute.setChecked(bool(self.settings.value('mute_status', 1))) # Put those together in a row squeezed in the center hb_volume = QHBoxLayout() hb_volume.addStretch(1) hb_volume.addWidget(self.volume, 1) hb_volume.addWidget(self.mute, 0) hb_volume.addStretch(1) # Stack all those up as this widget's layout vlayout = QVBoxLayout() vlayout.addLayout(hb_label) vlayout.addLayout(hb_combos) vlayout.addLayout(hb_volume) self.setLayout(vlayout)
class Recorder(QMainWindow, Ui_MainWindow): def __init__(self): super(Recorder, self).__init__() self.setupUi(self) self.output = QFile() self.audio = QAudioInput() self.NEED_ASR = False self.Open = True self.th1 = threading.Thread(target=self.ASR) self.th1.start() self.Pause_Button.clicked.connect(self.toggle_pause) self.Record_Button.clicked.connect(self.toggle_record) def closeEvent(self, event): self.Open = False def toggle_record(self): if self.Record_Button.text() == "开始录音": self.statusbar.showMessage("开始录音") self.setup() self.audio.start(self.output) self.Record_Button.setText("停止") self.Pause_Button.setText("暂停") self.Pause_Button.setEnabled(True) else: self.audio.stop() self.output.close() self.Pause_Button.setText("暂停") self.Record_Button.setText("开始录音") self.statusbar.showMessage("正在使用百度智能云识别,请稍等") self.NEED_ASR = True def toggle_pause(self): if self.Pause_Button.text() == "暂停": self.Pause_Button.setText("继续") self.audio.suspend() else: self.Pause_Button.setText("暂停") self.audio.resume() def ASR(self): while self.Open: print(1) if self.NEED_ASR: try: text = ASR().Baidu_ASR("record.pcm") print(text) if text['err_msg'] == 'success.': self.Text_plainTextEdit.setPlainText(text['result'][0]) self.statusbar.showMessage("识别成功") else: self.statusbar.showMessage("识别失败,请再说一遍") except: self.statusbar.showMessage("网络故障,请检查网络设置以及百度智能云账号") self.NEED_ASR = False else: pass def setup(self): self.output.setFileName("record.pcm") self.output.open(QIODevice.WriteOnly | QIODevice.Truncate) settings = QAudioFormat() settings.setCodec("audio/pcm") settings.setSampleRate(16000) settings.setSampleSize(16) settings.setChannelCount(1) settings.setByteOrder(QAudioFormat.LittleEndian) settings.setSampleType(QAudioFormat.SignedInt) self.audio = QAudioInput(settings)
class SideToneWidget(QWidget): def __init__(self, parent): super().__init__(parent) # Save link to main window self.main_window = parent # Get the status bar self.status_bar = parent.statusBar() # Slot that will point to a QAudioInput some day self.input_device = None # Slot that will point to a QAudioOutput in time self.otput_device = None # set up layout, creating: # self.input_info_list, list of QAudioInfo for inputs # self.cb_inputs, combox of input names in same order # self.otput_info_list, list of QAudioInfo for outputs # self.cb_otputs, combox of output names in same order # self.volume, volume slider # self.mute, mute checkbox self._uic() # Connect up signals to slots. # Changes in the comboxes go to in_device and ot_device self.cb_inputs.currentIndexChanged.connect(self.in_dev_change) self.cb_otputs.currentIndexChanged.connect(self.ot_dev_change) # Mute button goes to mute_change self.mute.stateChanged.connect(self.mute_change) # Change in volume goes to volume_change self.volume.valueChanged.connect(self.volume_change) # Start with the mute switch on. This triggers the above two signals. self.mute.setChecked(True) # Slot for any change in volume (or mute). If we have an output device # then convert level to a real and pass to the output device. If the new # level is 0, tell the device to stop; if nonzero, tell it to start. # Note we don't do anything about the input device level, it is always 1.0 def volume_change(self, new_level): if self.otput_device: # we have an output device self.otput_device.setVolume(self.volume.value() / 100) if new_level == 0: # looks like a mute # tell the output device to stop just in case it # doesn't know about volume control. self.otput_device.stop() else: # non-zero level, if the output is stopped, start it if self.otput_device.state() == QAudio.StoppedState: self.otput_device.start() # Slot for mute switch. Note that any change to the volume slider # generates a signal to the volume_change slot. def mute_change(self, onoff): if onoff: # Mute has been clicked ON. Remember the current volume. # Turn the volume to zero. self.volume_level = self.volume.value() self.volume.setValue(0) else: # Mute has been clicked OFF. If we do not yet have input and # output devices, get them. Then reset the old volume level. if self.otput_device is None: # We are starting up and have no devices. Fake a call to # the checkbox-change entries thus creating devices. self.in_dev_change(self.cb_inputs.currentIndex()) self.ot_dev_change(self.cb_inputs.currentIndex()) self.volume.setValue(self.volume_level) # Slots for changes in the selection of the input- and output-device # combo boxes. On startup we have neither an input nor an output device. # We do not know which combox the user will fiddle with first. So either # has to assume that the other device may not yet exist. # # On a change of input choice: if we have an input device, get rid of it. # Create a new input device. Set its level to 1.0. If we # have an output, connect the two. def in_dev_change(self, new_index): if self.input_device: if self.otput_device: self.otput_device.stop() self.input_device.stop() self.input_device = None # goodby object # Get the QAudioDeviceInfo corresponding to this index of the combox. audio_info = self.input_info_list[new_index] # Create a new QAudioInput based on that. preferred_format = audio_info.preferredFormat() self.input_device = QAudioInput(audio_info, preferred_format) self.input_device.setVolume(1.0) self.input_device.setBufferSize(384) # If we have an output device, redirect it to this input. This is # done by asking the input device for its QIODevice, and passing that # to the output device's start() method. if self.otput_device: self.input_device.start(self.otput_device.start()) #self.otput_device.start( self.input_device.start() ) # On a change in the selection of output choice: If we have an output # device, get rid of it. Create a new output device. If we have an input # device, connect the two. Set the output level from the volume slider. def ot_dev_change(self, new_index): if self.otput_device: if self.input_device: self.input_device.stop() self.otput_device.stop() self.otput_device = None audio_info = self.otput_info_list[new_index] preferred_format = audio_info.preferredFormat() self.otput_device = QAudioOutput(audio_info, preferred_format) self.otput_device.setVolume(self.volume.value() / 100) #self.otput_device.setBufferSize( 384 ) if self.input_device: self.input_device.start(self.otput_device.start()) #self.otput_device.start( self.input_device.start() ) def _uic(self): ''' set up our layout which consists of: Big Honkin' Label [input combobox] [output combobox] [volume slider] [x] Mute hooking put the signals to useful slots is the job of __init__. Here just make the layout. ''' self.setMinimumWidth(400) # Create the big honkin' label and logo icon_pixmap = QPixmap(':/icon.png').scaledToWidth(64) icon_label = QLabel() icon_label.setPixmap(icon_pixmap) text_label = QLabel("Sidetone!") hb_label = QHBoxLayout() hb_label.addStretch(1) hb_label.addWidget(icon_label, 0) hb_label.addWidget(text_label, 0) hb_label.addStretch(1) # Create a list of QAudioInfo objects for inputs self.input_info_list = QAudioDeviceInfo.availableDevices( QAudio.AudioInput) if 0 == len(self.input_info_list): self.input_info_list = [QAudioDeviceInfo.defaultInputDevice()] # Create a combo box and populate it with names of inputs self.cb_inputs = QComboBox() self.cb_inputs.addItems( [audio_info.deviceName() for audio_info in self.input_info_list]) # Create a list of QAudioInfo objects for outputs self.otput_info_list = QAudioDeviceInfo.availableDevices( QAudio.AudioOutput) if 0 == len(self.otput_info_list): self.otput_info_list = [QAudioDeviceInfo.defaultOutputDevice()] self.status_bar.showMessage( '{} inputs {} otputs'.format(len(self.input_info_list), len(self.otput_info_list)), 2000) # Create a combo box and populate it with names of outputs self.cb_otputs = QComboBox() self.cb_otputs.addItems( [audio_info.deviceName() for audio_info in self.otput_info_list]) # Lay those two out aligned to the outside hb_combos = QHBoxLayout() hb_combos.addWidget(self.cb_inputs, 1) hb_combos.addStretch(0) hb_combos.addWidget(self.cb_otputs, 1) # Create a volume slider from 0 to 100. self.volume = QSlider(Qt.Horizontal, self) self.volume.setMinimum(0) self.volume.setMaximum(100) self.volume.setTickInterval(10) self.volume.setTickPosition(QSlider.TicksBothSides) # Create a checkbox "Mute" self.mute = QCheckBox('Mute') # Put those together in a row squeezed in the center hb_volume = QHBoxLayout() hb_volume.addStretch(1) hb_volume.addWidget(self.volume, 1) hb_volume.addWidget(self.mute, 0) hb_volume.addStretch(1) # Stack all those up as this widget's layout vlayout = QVBoxLayout() vlayout.addLayout(hb_label) vlayout.addLayout(hb_combos) vlayout.addLayout(hb_volume) self.setLayout(vlayout)
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")