def init_state(self): self.player = QMediaPlayer() self.playlist = QMediaPlaylist() self.probe = QAudioProbe() self.probe.setSource(self.player) self.probe_connected = False self.timer = QTimer() self.timer.setInterval(100) self.timer.setSingleShot(True) self.recent_files_manager = RecentFilesManager() self.ui_manager.set_output(self.player) self.player.setPlaylist(self.playlist)
def __init__(self, parent=None): super(Tuner, self).__init__(parent) # 从文件中加载UI定义 # self.ui = loadUi('Tuner.ui') #pyqt5 self.ui = Ui_MainWindow() # 创建UI对象 self.ui.setupUi(self) # 构造UI界面 # # 播放标准音 self.mediaPlayer = QMediaPlayer(self) self.ui.c1.clicked.connect(self.playaudioc) self.ui.d1.clicked.connect(self.playaudiod) self.ui.e1.clicked.connect(self.playaudioe) self.ui.f1.clicked.connect(self.playaudiof) self.ui.g1.clicked.connect(self.playaudiog) self.ui.a1.clicked.connect(self.playaudioa) self.ui.b1.clicked.connect(self.playaudiob) # 录音 self.fileName = "" self.recorder = QAudioRecorder(self) self.recorder.stateChanged.connect(self.do_stateChanged) self.recorder.durationChanged.connect(self.do_durationChanged) self.probe = QAudioProbe(self) # 探测器 self.probe.setSource(self.recorder) # self.probe.audioBufferProbed.connect(self.do_processBuffer) if self.recorder.defaultAudioInput() == "": # str类型 return # 无音频录入设备 for device in self.recorder.audioInputs(): self.ui.comboDevices.addItem(device) # 音频录入设备列表 for codecName in self.recorder.supportedAudioCodecs(): self.ui.comboCodec.addItem(codecName) # 支持的音频编码 sampleList, isContinuous = self.recorder.supportedAudioSampleRates() # isContinuous 是否支持连续的采样率,与C++不一样 for i in range(len(sampleList)): self.ui.comboSampleRate.addItem("%d" % sampleList[i]) # 支持的采样率 ## channels self.ui.comboChannels.addItem("1") self.ui.comboChannels.addItem("2") self.ui.comboChannels.addItem("4")
def __init__(self, parent=None): super().__init__(parent) self.ui = Ui_Form() self.ui.setupUi(self) self.recorder = QAudioRecorder(self) self.recorder.stateChanged.connect(self.do_stateChanged) self.recorder.durationChanged.connect(self.do_durationChanged) self.probe = QAudioProbe(self) self.probe.setSource(self.recorder) self.probe.audioBufferProbed.connect(self.do_processBuffer) if self.recorder.defaultAudioInput() == "": # str类型 return # 无音频录入设备 for device in self.recorder.audioInputs(): self.ui.comboDevices.addItem(device) # 音频录入设备列表 for codecName in self.recorder.supportedAudioCodecs(): self.ui.comboCodec.addItem(codecName) # 支持的音频编码 sampleList, isContinuous = self.recorder.supportedAudioSampleRates() # isContinuous 是否支持连续的采样率,与C++不一样 for i in range(len(sampleList)): self.ui.comboSampleRate.addItem("%d" % sampleList[i]) # 支持的采样率 # channels self.ui.comboChannels.addItem("1") self.ui.comboChannels.addItem("2") self.ui.comboChannels.addItem("4") # quality self.ui.sliderQuality.setRange(0, QMultimedia.VeryHighQuality) self.ui.sliderQuality.setValue(QMultimedia.NormalQuality) # bitrates self.ui.comboBitrate.addItem("32000") self.ui.comboBitrate.addItem("64000") self.ui.comboBitrate.addItem("96000") self.ui.comboBitrate.addItem("128000") self.__addToolbar()
class Tuner(QMainWindow): def __init__(self, parent=None): super(Tuner, self).__init__(parent) # 从文件中加载UI定义 # self.ui = loadUi('Tuner.ui') #pyqt5 self.ui = Ui_MainWindow() # 创建UI对象 self.ui.setupUi(self) # 构造UI界面 # # 播放标准音 self.mediaPlayer = QMediaPlayer(self) self.ui.c1.clicked.connect(self.playaudioc) self.ui.d1.clicked.connect(self.playaudiod) self.ui.e1.clicked.connect(self.playaudioe) self.ui.f1.clicked.connect(self.playaudiof) self.ui.g1.clicked.connect(self.playaudiog) self.ui.a1.clicked.connect(self.playaudioa) self.ui.b1.clicked.connect(self.playaudiob) # 录音 self.fileName = "" self.recorder = QAudioRecorder(self) self.recorder.stateChanged.connect(self.do_stateChanged) self.recorder.durationChanged.connect(self.do_durationChanged) self.probe = QAudioProbe(self) # 探测器 self.probe.setSource(self.recorder) # self.probe.audioBufferProbed.connect(self.do_processBuffer) if self.recorder.defaultAudioInput() == "": # str类型 return # 无音频录入设备 for device in self.recorder.audioInputs(): self.ui.comboDevices.addItem(device) # 音频录入设备列表 for codecName in self.recorder.supportedAudioCodecs(): self.ui.comboCodec.addItem(codecName) # 支持的音频编码 sampleList, isContinuous = self.recorder.supportedAudioSampleRates() # isContinuous 是否支持连续的采样率,与C++不一样 for i in range(len(sampleList)): self.ui.comboSampleRate.addItem("%d" % sampleList[i]) # 支持的采样率 ## channels self.ui.comboChannels.addItem("1") self.ui.comboChannels.addItem("2") self.ui.comboChannels.addItem("4") ## ==============自定义功能函数============ def __setRecordParams(self): ##设置音频输入参数 selectedFile = self.ui.editOutputFile.text().strip() if (selectedFile == ""): QMessageBox.critical(self, "错误", "请先设置录音输出文件") return False if os.path.exists(selectedFile): os.remove(selectedFile) # 删除已有文件 ## QMessageBox.critical(self,"错误","录音输出文件被占用,无法删除") ## return False recordFile = QUrl.fromLocalFile(selectedFile) self.recorder.setOutputLocation(recordFile) # 设置输出文件 recordDevice = self.ui.comboDevices.currentText() self.recorder.setAudioInput(recordDevice) # 设置录入设备 settings = QAudioEncoderSettings() # 音频编码设置 settings.setCodec(self.ui.comboCodec.currentText()) # 编码 sampRate = int(self.ui.comboSampleRate.currentText()) settings.setSampleRate(sampRate) # 采样率 channelCount = int(self.ui.comboChannels.currentText()) settings.setChannelCount(channelCount) # 通道数 settings.setEncodingMode(QMultimedia.ConstantBitRateEncoding) # 固定比特率 self.recorder.setAudioSettings(settings) # 音频设置 return True def pitch_estimation(self, wavpath): if os.path.exists(wavpath): y, sr = librosa.load(wavpath) f0, voiced_flag, voiced_probs = librosa.pyin( y, fmin=librosa.note_to_hz('B3'), fmax=librosa.note_to_hz('C5')) f0 = f0[~np.isnan(f0)] times = librosa.times_like(f0) level = optimize.curve_fit(lambda x, b: b, times, np.nan_to_num(f0))[0] pitch = np.around(level[0], decimals=3).astype(float) return pitch ## ==========由connectSlotsByName() 自动连接的槽函数================== @pyqtSlot() def on_btnGetFile_clicked(self): ##"录音输出文件"按钮 curPath = os.getcwd() # 获取系统当前目录 dlgTitle = "选择输出文件" filt = "wav文件(*.wav)" self.fileName, flt, = QFileDialog.getSaveFileName( self, dlgTitle, curPath, filt) if (self.fileName != ""): self.ui.editOutputFile.setText(self.fileName) @pyqtSlot() ##开始录音 def on_actRecord_triggered(self): success = True if (self.recorder.state() == QMediaRecorder.StoppedState): # 已停止,重新设置 success = self.__setRecordParams() # 设置录音参数 if success: self.recorder.record() @pyqtSlot() ##退出 def on_actQuit_triggered(self): sys.exit(app.exec_()) # @pyqtSlot() ##暂停 # def on_actPause_triggered(self): # self.recorder.pause() @pyqtSlot() ##停止 def on_actStop_triggered(self): self.recorder.stop() # 录完立马分析并显示Hz name = self.fileName.split('/')[-1][:-4] # 存储的文件名 无.wav # func = lambda x, b: b if name == 'c1': # if os.path.exists(self.fileName): # y, sr = librosa.load(self.fileName) # f0, voiced_flag, voiced_probs = librosa.pyin(y, fmin=librosa.note_to_hz('C4'), # fmax=librosa.note_to_hz('C5')) # f0 = f0[~np.isnan(f0)] # times = librosa.times_like(f0) # level = optimize.curve_fit(lambda x, b: b, times, np.nan_to_num(f0))[0] # pitch = np.around(level[0], decimals=3).astype(float) pitch = self.pitch_estimation(self.fileName) self.ui.c1m.setStyleSheet("color:rgb(10,10,10,255);" "font-size:32px;" "font-weight:600;" "font-family:Times New Roman;") self.ui.c1m.setText(str(pitch)) F0 = 261.626 err = np.around(np.abs(pitch - F0) / F0, decimals=4) * 100 self.ui.c1e.setStyleSheet("color:rgb(10,10,10,255);" "font-size:32px;" "font-weight:600;" "font-family:Times New Roman;") self.ui.c1e.setText(str(err)) elif name == 'd1': pitch = self.pitch_estimation(self.fileName) self.ui.d1m.setStyleSheet("color:rgb(10,10,10,255);" "font-size:32px;" "font-weight:600;" "font-family:Times New Roman;") self.ui.d1m.setText(str(pitch)) F0 = 293.665 err = np.around(np.abs(pitch - F0) / F0, decimals=4) * 100 self.ui.d1e.setStyleSheet("color:rgb(10,10,10,255);" "font-size:32px;" "font-weight:600;" "font-family:Times New Roman;") self.ui.d1e.setText(str(err)) elif name == 'e1': pitch = self.pitch_estimation(self.fileName) self.ui.e1m.setStyleSheet("color:rgb(10,10,10,255);" "font-size:32px;" "font-weight:600;" "font-family:Times New Roman;") self.ui.e1m.setText(str(pitch)) F0 = 329.628 err = np.around(np.abs(pitch - F0) / F0, decimals=4) * 100 self.ui.e1e.setStyleSheet("color:rgb(10,10,10,255);" "font-size:32px;" "font-weight:600;" "font-family:Times New Roman;") self.ui.e1e.setText(str(err)) elif name == 'f1': pitch = self.pitch_estimation(self.fileName) self.ui.f1m.setStyleSheet("color:rgb(10,10,10,255);" "font-size:32px;" "font-weight:600;" "font-family:Times New Roman;") self.ui.f1m.setText(str(pitch)) F0 = 349.228 err = np.around(np.abs(pitch - F0) / F0, decimals=4) * 100 self.ui.f1e.setStyleSheet("color:rgb(10,10,10,255);" "font-size:32px;" "font-weight:600;" "font-family:Times New Roman;") self.ui.f1e.setText(str(err)) elif name == 'g1': pitch = self.pitch_estimation(self.fileName) self.ui.g1m.setStyleSheet("color:rgb(10,10,10,255);" "font-size:32px;" "font-weight:600;" "font-family:Times New Roman;") self.ui.g1m.setText(str(pitch)) F0 = 391.995 err = np.around(np.abs(pitch - F0) / F0, decimals=4) * 100 self.ui.g1e.setStyleSheet("color:rgb(10,10,10,255);" "font-size:32px;" "font-weight:600;" "font-family:Times New Roman;") self.ui.g1e.setText(str(err)) elif name == 'a1': pitch = self.pitch_estimation(self.fileName) self.ui.a1m.setStyleSheet("color:rgb(10,10,10,255);" "font-size:32px;" "font-weight:600;" "font-family:Times New Roman;") self.ui.a1m.setText(str(pitch)) F0 = 440.000 err = np.around(np.abs(pitch - F0) / F0, decimals=4) * 100 self.ui.a1e.setStyleSheet("color:rgb(10,10,10,255);" "font-size:32px;" "font-weight:600;" "font-family:Times New Roman;") self.ui.a1e.setText(str(err)) elif name == 'b1': pitch = self.pitch_estimation(self.fileName) self.ui.b1m.setStyleSheet("color:rgb(10,10,10,255);" "font-size:32px;" "font-weight:600;" "font-family:Times New Roman;") self.ui.b1m.setText(str(pitch)) F0 = 493.883 err = np.around(np.abs(pitch - F0) / F0, decimals=4) * 100 self.ui.b1e.setStyleSheet("color:rgb(10,10,10,255);" "font-size:32px;" "font-weight:600;" "font-family:Times New Roman;") self.ui.b1e.setText(str(err)) else: QMessageBox.critical(self, "文件名错误", "请输入c1-b1中的音名") ## =============自定义槽函数=============================== def do_stateChanged(self, state): ##状态变化 isRecording = (state == QMediaRecorder.RecordingState) # 正在录制 self.ui.actRecord.setEnabled(not isRecording) # self.ui.actPause.setEnabled(isRecording) self.ui.actStop.setEnabled(isRecording) isStoped = (state == QMediaRecorder.StoppedState) # 已停止 self.ui.btnGetFile.setEnabled(isStoped) self.ui.editOutputFile.setEnabled(isStoped) def do_durationChanged(self, duration): ##持续时间长度变化 self.ui.LabPassTime.setText("已录制 %d 秒" % (duration / 1000)) # ============================================================================ @pyqtSlot() def playaudioc(self): self.mediaPlayer.setMedia( QMediaContent(QUrl.fromLocalFile("data/standard/C4.wav"))) self.mediaPlayer.play() @pyqtSlot() def playaudiod(self): self.mediaPlayer.setMedia( QMediaContent(QUrl.fromLocalFile("data/standard/D4.wav"))) self.mediaPlayer.play() @pyqtSlot() def playaudioe(self): self.mediaPlayer.setMedia( QMediaContent(QUrl.fromLocalFile("data/standard/E4.wav"))) self.mediaPlayer.play() @pyqtSlot() def playaudiof(self): self.mediaPlayer.setMedia( QMediaContent(QUrl.fromLocalFile("data/standard/F4.wav"))) self.mediaPlayer.play() @pyqtSlot() def playaudiog(self): self.mediaPlayer.setMedia( QMediaContent(QUrl.fromLocalFile("data/standard/G4.wav"))) self.mediaPlayer.play() @pyqtSlot() def playaudioa(self): self.mediaPlayer.setMedia( QMediaContent(QUrl.fromLocalFile("data/standard/A4.wav"))) self.mediaPlayer.play() @pyqtSlot() def playaudiob(self): self.mediaPlayer.setMedia( QMediaContent(QUrl.fromLocalFile("data/standard/B4.wav"))) self.mediaPlayer.play()
class Recorder(QtWidgets.QWidget): def __init__(self, parent=None): super().__init__(parent) self.ui = Ui_Form() self.ui.setupUi(self) self.recorder = QAudioRecorder(self) self.recorder.stateChanged.connect(self.do_stateChanged) self.recorder.durationChanged.connect(self.do_durationChanged) self.probe = QAudioProbe(self) self.probe.setSource(self.recorder) self.probe.audioBufferProbed.connect(self.do_processBuffer) if self.recorder.defaultAudioInput() == "": # str类型 return # 无音频录入设备 for device in self.recorder.audioInputs(): self.ui.comboDevices.addItem(device) # 音频录入设备列表 for codecName in self.recorder.supportedAudioCodecs(): self.ui.comboCodec.addItem(codecName) # 支持的音频编码 sampleList, isContinuous = self.recorder.supportedAudioSampleRates() # isContinuous 是否支持连续的采样率,与C++不一样 for i in range(len(sampleList)): self.ui.comboSampleRate.addItem("%d" % sampleList[i]) # 支持的采样率 # channels self.ui.comboChannels.addItem("1") self.ui.comboChannels.addItem("2") self.ui.comboChannels.addItem("4") # quality self.ui.sliderQuality.setRange(0, QMultimedia.VeryHighQuality) self.ui.sliderQuality.setValue(QMultimedia.NormalQuality) # bitrates self.ui.comboBitrate.addItem("32000") self.ui.comboBitrate.addItem("64000") self.ui.comboBitrate.addItem("96000") self.ui.comboBitrate.addItem("128000") self.__addToolbar() def __addToolbar(self): layout = QtWidgets.QVBoxLayout() Astart = QtWidgets.QToolButton() Astart.setText("开始") Astart.setDefaultAction(self.ui.actRecordStart) Apause = QtWidgets.QToolButton() Apause.setText("暂停") Apause.setDefaultAction(self.ui.actRecordPause) Astop = QtWidgets.QToolButton() Astop.setText("停止") Astop.setDefaultAction(self.ui.actRecordStop) self.toolbar = QtWidgets.QToolBar() self.toolbar.addWidget(Astart) self.toolbar.addWidget(Apause) self.toolbar.addWidget(Astop) layout.addWidget(self.toolbar) layout.addWidget(self.ui.widget) self.setLayout(layout) def __setRecordParams(self): selectedFile=self.ui.editOutputFile.text().strip() if (selectedFile ==""): QMessageBox.critical(self,"错误","请先设置录音输出文件") return False if os.path.exists(selectedFile): os.remove(selectedFile)#删除已有文件 recordFile=QUrl.fromLocalFile(selectedFile) self.recorder.setOutputLocation(recordFile) #设置输出文件 recordDevice=self.ui.comboDevices.currentText() self.recorder.setAudioInput(recordDevice) #设置录入设备 settings=QAudioEncoderSettings() #音频编码设置 settings.setCodec(self.ui.comboCodec.currentText()) #编码 sampRate=int(self.ui.comboSampleRate.currentText()) settings.setSampleRate(sampRate) #采样率 bitRate=int(self.ui.comboBitrate.currentText()) settings.setBitRate(bitRate) #比特率 channelCount=int(self.ui.comboChannels.currentText()) settings.setChannelCount(channelCount) #通道数 quality=QMultimedia.EncodingQuality(self.ui.sliderQuality.value()) settings.setQuality(quality) #品质 if self.ui.radioQuality.isChecked(): #编码模式为固定品质,自动决定采样率,采样点大小 settings.setEncodingMode(QMultimedia.ConstantQualityEncoding) else: settings.setEncodingMode(QMultimedia.ConstantBitRateEncoding) #固定比特率 self.recorder.setAudioSettings(settings) #音频设置 return True ## ==========由connectSlotsByName() 自动连接的槽函数================== @pyqtSlot() def on_btnGetFile_clicked(self): ##"录音输出文件"按钮 curPath=os.getcwd() #获取系统当前目录 dlgTitle="选择输出文件" filt="wav文件(*.wav)" fileName,flt,=QFileDialog.getSaveFileName(self, dlgTitle, curPath, filt) if (fileName !=""): self.ui.editOutputFile.setText(fileName) @pyqtSlot() ##开始录音 def on_actRecordStart_triggered(self): success=True if (self.recorder.state() == QMediaRecorder.StoppedState): #已停止,重新设置 success=self.__setRecordParams() #设置录音参数 if success: self.recorder.record() @pyqtSlot() ##暂停 def on_actRecordPause_triggered(self): self.recorder.pause() @pyqtSlot() def on_actRecordStop_triggered(self): self.recorder.stop() ## =============自定义槽函数=============================== def do_stateChanged(self,state): ##状态变化 isRecording=(state==QMediaRecorder.RecordingState) #正在录制 self.ui.actRecordStart.setEnabled(not isRecording) self.ui.actRecordPause.setEnabled(isRecording) self.ui.actRecordStop.setEnabled(isRecording) isStoped=(state==QMediaRecorder.StoppedState) #已停止 self.ui.btnGetFile.setEnabled(isStoped) self.ui.editOutputFile.setEnabled(isStoped) def do_durationChanged(self,duration): ##持续时间长度变化 self.ui.LabPassTime.setText("已录制 %d 秒"%(duration/1000)) def do_processBuffer(self,buffer): ##解析缓冲区数据 self.ui.spin_byteCount.setValue(buffer.byteCount()) #缓冲区字节数 self.ui.spin_duration.setValue(buffer.duration()/1000) #缓冲区时长 self.ui.spin_frameCount.setValue(buffer.frameCount()) #缓冲区帧数 self.ui.spin_sampleCount.setValue(buffer.sampleCount()) #缓冲区采样数 audioFormat=buffer.format() #缓冲区格式,QAudioBuffer self.ui.spin_channelCount.setValue(audioFormat.channelCount()) #通道数 self.ui.spin_sampleSize.setValue(audioFormat.sampleSize()) #采样大小 self.ui.spin_sampleRate.setValue(audioFormat.sampleRate()) #采样率 self.ui.spin_bytesPerFrame.setValue(audioFormat.bytesPerFrame()) #每帧字节数 if (audioFormat.byteOrder()==QAudioFormat.LittleEndian): self.ui.edit_byteOrder.setText("LittleEndian") #字节序 else: self.ui.edit_byteOrder.setText("BigEndian") self.ui.edit_codec.setText(audioFormat.codec()) #编码格式 if (audioFormat.sampleType()==QAudioFormat.SignedInt): #采样点类型 self.ui.edit_sampleType.setText("SignedInt") elif(audioFormat.sampleType()==QAudioFormat.UnSignedInt): self.ui.edit_sampleType.setText("UnSignedInt") elif(audioFormat.sampleType()==QAudioFormat.Float): self.ui.edit_sampleType.setText("Float") else: self.ui.edit_sampleType.setText("Unknown")
class InputManager: __instance = None def __init__(self): if not InputManager.__instance: self.ui_manager = UIManager.get_instance() self.radio_stations_manager = RadioStationsManager() self.player = None self.playlist = None self.probe = None self.load_state() if not self.playlist: self.init_state() self.init_signals() def init_signals(self): self.player.durationChanged.connect(self.duration_changed_slot) self.player.positionChanged.connect(self.position_changed_slot) self.player.currentMediaChanged.connect( self.current_media_changed_slot) self.player.stateChanged.connect(self.state_changed_slot) def set_position(self, new_pos): self.ui_manager.set_position_slider_value(new_pos) self.player.setPosition(new_pos) def get_duration(self): return self.player.duration() def get_position(self): return self.player.position() def duration_changed_slot(self, duration): self.ui_manager.set_position_slider_max_value(duration) def position_changed_slot(self, position): self.ui_manager.set_position_slider_value(position) def get_volume(self): return self.player.volume() def set_volume(self, value): self.ui_manager.set_volume_slider_value(value) self.player.setVolume(value) def current_media_changed_slot(self): self.ui_manager.sync_row(self.get_media_position()) def state_changed_slot(self, new_state): if new_state == QMediaPlayer.StoppedState or new_state == QMediaPlayer.PausedState: self.ui_manager.change_play_btn_state(False) else: self.ui_manager.change_play_btn_state(True) def next_media(self): self.playlist.next() def previous_media(self): self.playlist.previous() @classmethod def get_instance(cls, *args, **kwargs): if not cls.__instance: cls.__instance = InputManager(*args, **kwargs) return cls.__instance def init_state(self): self.player = QMediaPlayer() self.playlist = QMediaPlaylist() self.probe = QAudioProbe() self.probe.setSource(self.player) self.probe_connected = False self.timer = QTimer() self.timer.setInterval(100) self.timer.setSingleShot(True) self.recent_files_manager = RecentFilesManager() self.ui_manager.set_output(self.player) self.player.setPlaylist(self.playlist) def load_state(self): file = QFile("file.dat") file.open(QIODevice.ReadOnly) in_stream = QDataStream(file) cur_playlist = QVariant() in_stream >> cur_playlist self.playlist = cur_playlist.value() def get_radio_stations(self, limit=None, category=None): stations = self.radio_stations_manager.get_all_stations( limit, category) return stations def get_radio_categories(self): categories = self.radio_stations_manager.get_all_categories() return categories def save_state(self): file = QFile("file.dat") file.open(QIODevice.WriteOnly) out = QDataStream(file) out << QVariant(self.current_playlist) def add_folder(self, path: str): files = get_dir_files(path) for file in files: self.add_media(path + "/" + file, get_format(file)) def add_file(self, filename: str): format = get_format(filename) if format != FILE_FORMAT.INVALID: return self.add_media(filename, format) raise RuntimeError("Invalid file format") def add_media(self, filename: str, format: FILE_FORMAT): url = QUrl.fromLocalFile( filename) if format != FILE_FORMAT.URL else QUrl(filename) content = QMediaContent(url) self.ui_manager.append_playlist(url.fileName(), format) self.recent_files_manager.write_recent_file(url.path()) self.ui_manager.init_recent_files() self.playlist.addMedia(content) def set_media_position(self, pos): self.playlist.setCurrentIndex(pos) def get_media_position(self): return self.playlist.currentIndex() def get_current_format(self): position = self.get_media_position() if position == -1: return None item = self.ui_manager.get_list_item(self.get_media_position()) return item.data(PlaylistItemDataRole.FORMAT) def play(self): format = self.get_current_format() if format is None: return self.ui_manager.change_play_btn_state(True) if format == FILE_FORMAT.AUDIO: self.probe.audioBufferProbed.connect(self.process_buffer) self.probe_connected = True else: self.probe_connected = False self.ui_manager.show_video() self.player.play() def pause(self): self.player.pause() def stop(self): self.player.stop() def is_muted(self): return self.player.isMuted() def is_paused(self): return self.player.state() in (QMediaPlayer.StoppedState, QMediaPlayer.PausedState) def mute(self, toggle): self.ui_manager.change_mute_state(toggle, self.get_volume()) self.player.setMuted(toggle) def get_playback_rate(self): return self.player.playbackRate() def set_playback_rate(self, value): self.player.setPlaybackRate(value) def process_buffer(self, buffer): if not self.probe_connected: return if not self.timer.isActive(): self.timer.start() else: if self.timer.remainingTime() == 0: data = buffer.data() chunked = chunk(list(data.asarray(buffer.byteCount())), 12) to_visualizer = [int(sum(e) // 12 // 75) for e in chunked] self.show_visualization(to_visualizer) def show_visualization(self, to_visualizer): self.ui_manager.update_equalizer(to_visualizer) def get_audio_devices(self): return QAudioDeviceInfo.availableDevices(QAudio.AudioOutput) def get_recent_files(self): return self.recent_files_manager.get_recent_files() def clear_recent_files(self): return self.recent_files_manager.clear_recent_files() def exit(self): self.ui_manager.exit()