用Python制作一边播放音频文件一边同时显示FFT波形pyqt5带按键的多线程程序
时间: 2024-05-13 20:13:49 浏览: 171
以下是一个用Python和PyQt5制作的一边播放音频文件一边同时显示FFT波形的多线程程序。程序包括一个带有开始、暂停和停止按钮的界面,可以通过界面控制音频文件的播放和波形的显示。
需要安装的库:PyQt5, numpy, scipy, matplotlib, pyaudio
```python
import sys
import threading
import time
import numpy as np
import scipy.signal as signal
import matplotlib.pyplot as plt
import pyaudio
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QVBoxLayout
from PyQt5.QtCore import QThread, pyqtSignal
class AudioThread(QThread):
"""用于读取音频文件并播放的线程"""
def __init__(self, filename):
super().__init__()
self.filename = filename
self.p = pyaudio.PyAudio()
self.chunk = 1024
self.stream = None
self.stop_flag = False
def run(self):
wf = wave.open(self.filename, 'rb')
self.stream = self.p.open(format=self.p.get_format_from_width(wf.getsampwidth()),
channels=wf.getnchannels(),
rate=wf.getframerate(),
output=True)
while True:
if self.stop_flag:
break
data = wf.readframes(self.chunk)
if len(data) == 0:
break
self.stream.write(data)
self.stream.stop_stream()
self.stream.close()
self.p.terminate()
wf.close()
def stop(self):
"""停止播放"""
self.stop_flag = True
class PlotThread(QThread):
"""用于绘制FFT波形的线程"""
plot_signal = pyqtSignal(np.ndarray)
def __init__(self):
super().__init__()
self.chunk = 1024
self.fs = 44100
self.freqs = None
self.stop_flag = False
def run(self):
while True:
if self.stop_flag:
break
signal = np.random.rand(self.chunk)
freqs, psd = signal.welch(signal, fs=self.fs)
self.plot_signal.emit(psd)
def stop(self):
"""停止绘制"""
self.stop_flag = True
class MainWindow(QWidget):
"""主窗口"""
def __init__(self):
super().__init__()
self.audio_thread = None
self.plot_thread = None
self.play_button = QPushButton('开始')
self.pause_button = QPushButton('暂停')
self.stop_button = QPushButton('停止')
self.plot_canvas = plt.figure().canvas
self.layout = QVBoxLayout()
self.layout.addWidget(self.play_button)
self.layout.addWidget(self.pause_button)
self.layout.addWidget(self.stop_button)
self.layout.addWidget(self.plot_canvas)
self.setLayout(self.layout)
self.play_button.clicked.connect(self.start_audio)
self.pause_button.clicked.connect(self.pause_audio)
self.stop_button.clicked.connect(self.stop_audio)
def start_audio(self):
"""开始播放音频文件并绘制FFT波形"""
self.audio_thread = AudioThread('test.wav')
self.plot_thread = PlotThread()
self.plot_thread.plot_signal.connect(self.plot_fft)
self.audio_thread.start()
self.plot_thread.start()
def pause_audio(self):
"""暂停播放"""
if self.audio_thread and self.audio_thread.isRunning():
self.audio_thread.stop()
def stop_audio(self):
"""停止播放和绘制"""
if self.audio_thread and self.audio_thread.isRunning():
self.audio_thread.stop()
if self.plot_thread and self.plot_thread.isRunning():
self.plot_thread.stop()
def plot_fft(self, psd):
"""绘制FFT波形"""
self.plot_canvas.figure.clear()
plt.plot(psd)
self.plot_canvas.draw()
if __name__ == '__main__':
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
```
阅读全文