用python生成一边录音一边播放一边显示FFT画布PyQt5的多线程程序
时间: 2023-09-04 10:15:36 浏览: 120
pyqt5多线程示例程序
以下是用Python生成一边录音一边播放一边显示FFT画布的PyQt5多线程程序示例:
```python
import sys
import pyaudio
import numpy as np
import queue
import time
from PyQt5.QtGui import QPainter, QColor, QPen
from PyQt5.QtCore import Qt, QThread, pyqtSignal
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QVBoxLayout
CHUNK = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 1
RATE = 44100
RECORD_SECONDS = 5
class AudioThread(QThread):
data_signal = pyqtSignal(np.ndarray)
def __init__(self, audio_queue):
super().__init__()
self.audio_queue = audio_queue
self.keep_running = True
def run(self):
audio = pyaudio.PyAudio()
stream = audio.open(format=FORMAT,
channels=CHANNELS,
rate=RATE,
input=True,
output=True,
frames_per_buffer=CHUNK)
while self.keep_running:
data = stream.read(CHUNK)
self.audio_queue.put(data)
data = np.frombuffer(data, dtype=np.int16)
self.data_signal.emit(data)
stream.stop_stream()
stream.close()
audio.terminate()
def stop(self):
self.keep_running = False
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.audio_queue = queue.Queue()
self.audio_thread = AudioThread(self.audio_queue)
self.audio_thread.data_signal.connect(self.update_plot)
self.audio_thread.start()
central_widget = QWidget()
layout = QVBoxLayout(central_widget)
self.plot_widget = PlotWidget()
layout.addWidget(self.plot_widget)
self.setCentralWidget(central_widget)
self.setGeometry(200, 200, 800, 600)
self.show()
def update_plot(self, data):
self.plot_widget.update_plot(data)
def closeEvent(self, event):
self.audio_thread.stop()
self.audio_thread.wait()
class PlotWidget(QWidget):
def __init__(self):
super().__init__()
self.setMinimumSize(400, 300)
self.x_axis = np.arange(0, CHUNK, 1)
self.y_axis = np.zeros(CHUNK)
def update_plot(self, data):
self.y_axis = np.abs(np.fft.fft(data))[:CHUNK//2]
self.update()
def paintEvent(self, event):
qp = QPainter()
qp.begin(self)
self.draw_spectrum(qp)
qp.end()
def draw_spectrum(self, qp):
qp.setPen(QPen(QColor(255, 0, 0), 2))
for i in range(len(self.y_axis)):
x = self.x_axis[i] * 2
y = self.y_axis[i] / 10
qp.drawLine(x, self.height(), x, self.height() - y)
if __name__ == '__main__':
app = QApplication(sys.argv)
window = MainWindow()
sys.exit(app.exec_())
```
该程序使用PyQt5创建了一个主窗口,其中包含一个绘制FFT图形的自定义QWidget。另外,该程序还使用了一个AudioThread类,用于在后台录制音频,并将数据传递给主窗口和自定义QWidget以进行绘制。
在主窗口中,我们创建了一个AudioThread实例并启动它。然后,我们创建了一个自定义QWidget实例,并将其添加到主窗口的布局中。最后,我们调用show()方法显示主窗口。
在自定义QWidget中,我们使用paintEvent方法来绘制FFT图形。该方法首先使用QPainter对象设置颜色和线宽,然后使用drawLine方法绘制FFT图形。
在AudioThread类中,我们使用PyAudio录制音频,并将数据存储在一个队列中。我们还使用一个data_signal信号来将数据传递给主窗口和自定义QWidget以进行绘制。在run方法中,我们不断读取音频数据并将其存储在队列中,直到keep_running变量被设置为False。最后,我们停止并关闭PyAudio流,并终止线程。
在主窗口中,我们使用update_plot方法来更新自定义QWidget的绘图。该方法接收音频数据并计算FFT,然后调用QWidget的update方法来重新绘制FFT图形。
在closeEvent方法中,我们停止并等待AudioThread线程完成。这是为了确保在关闭应用程序之前停止录音并释放资源。
阅读全文