用Python制作一边播放音频文件一边同时显示FFT波形pyqt5带按键的多线程正确运行的程序
时间: 2024-04-30 13:23:54 浏览: 162
以下是使用Python制作一边播放音频文件一边同时显示FFT波形pyqt5带按键的多线程正确运行的程序:
```python
import sys
import numpy as np
import pyqtgraph as pg
from PyQt5.QtCore import QThread, pyqtSignal
from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, QFileDialog
from scipy.io.wavfile import read
class AudioThread(QThread):
update_signal = pyqtSignal(np.ndarray)
def __init__(self, parent=None):
QThread.__init__(self, parent)
self.filename = None
self.fs = None
def set_filename(self, filename):
self.filename = filename
def run(self):
if self.filename is not None:
self.fs, audio = read(self.filename)
audio = audio / 32768.0
n = len(audio)
window = np.hanning(n)
audio = audio * window
freqs = np.fft.fftfreq(n, 1/self.fs)
while True:
for i in range(0, n, 1024):
chunk = audio[i:i+1024]
if len(chunk) < 1024:
break
fft = np.fft.fft(chunk)
fft = np.abs(fft[:len(fft)//2])
self.update_signal.emit(fft)
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.audio_thread = AudioThread()
self.audio_thread.update_signal.connect(self.update_plot)
self.audio_thread.start()
self.button = QPushButton('Select File', self)
self.button.move(10, 10)
self.button.clicked.connect(self.select_file)
self.plot_widget = pg.PlotWidget(self)
self.plot_widget.move(10, 50)
self.plot_widget.setRange(yRange=[0, 10000])
def select_file(self):
filename, _ = QFileDialog.getOpenFileName(self, 'Open file', '', 'WAV files (*.wav)')
if filename:
self.audio_thread.set_filename(filename)
def update_plot(self, data):
self.plot_widget.clear()
self.plot_widget.plot(data, pen='r')
if __name__ == '__main__':
app = QApplication(sys.argv)
window = MainWindow()
window.setGeometry(100, 100, 640, 480)
window.show()
sys.exit(app.exec_())
```
在这个程序中,我们使用了`AudioThread`类来处理音频文件的读取和FFT计算。`update_signal`信号被发出以更新FFT波形图。`MainWindow`类包括一个按钮用于选择音频文件,一个用于显示FFT波形的绘图小部件,并将`update_signal`信号连接到`update_plot`函数以更新绘图小部件。
注意,我们在`run`函数中使用了一个无限循环,以便能够一边读取音频文件,一边计算FFT。在循环中,我们使用1024个音频样本作为一个块进行FFT计算,并将FFT的前一半的幅度值发出`update_signal`信号以更新绘图小部件。我们使用汉宁窗口对每个块进行加窗,以减少频谱泄漏。
阅读全文