用python生成一边录音一边播放一边显示FFT画布PyQt5的多线程程序
时间: 2023-09-04 08:15:57 浏览: 97
以下是一个基本的多线程程序,它可以一边录音一边播放声音,同时显示FFT图像。这个程序使用PyQt5和PyAudio库。
```python
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
import pyaudio
import numpy as np
import time
class AudioThread(QThread):
def __init__(self):
super().__init__()
self.chunk = 1024
self.format = pyaudio.paInt16
self.channels = 1
self.rate = 44100
self.p = pyaudio.PyAudio()
self.stream = self.p.open(format=self.format,
channels=self.channels,
rate=self.rate,
input=True,
output=True,
frames_per_buffer=self.chunk)
self.running = True
def run(self):
while self.running:
data = self.stream.read(self.chunk)
self.stream.write(data)
data = np.frombuffer(data, dtype=np.int16)
fft_data = np.abs(np.fft.fft(data))[:len(data)//2]
fft_data = fft_data / np.max(fft_data)
self.sig_data.emit(fft_data)
def stop(self):
self.running = False
self.stream.stop_stream()
self.stream.close()
self.p.terminate()
sig_data = pyqtSignal(np.ndarray)
class AudioWidget(QWidget):
def __init__(self):
super().__init__()
self.audio_thread = AudioThread()
self.audio_thread.sig_data.connect(self.update_data)
self.audio_thread.start()
self.data = np.zeros(1024)
self.setMinimumSize(400, 200)
self.setWindowTitle("Audio FFT")
def paintEvent(self, event):
qp = QPainter()
qp.begin(self)
qp.setPen(QColor(0, 0, 0))
qp.fillRect(event.rect(), QColor(255, 255, 255))
qp.setPen(QColor(0, 0, 255))
for i in range(len(self.data)):
x = self.width() * i / len(self.data)
y = self.height() * (1 - self.data[i])
qp.drawLine(x, self.height(), x, y)
qp.end()
def update_data(self, data):
self.data = data
self.update()
def closeEvent(self, event):
self.audio_thread.stop()
self.audio_thread.wait()
if __name__ == '__main__':
app = QApplication(sys.argv)
widget = AudioWidget()
widget.show()
sys.exit(app.exec_())
```
在这个程序中,我们创建了一个名为AudioThread的新类。这个类继承自QThread,它是一个基本的多线程类。在这个类的构造函数中,我们初始化了PyAudio库,打开了一个音频流,并设置了音频的参数。在run()函数中,我们使用PyAudio库的read()方法读取音频数据,使用write()方法播放音频数据,并将其转换为numpy数组。然后我们使用numpy.fft.fft()方法计算FFT,将其归一化,并将其发送到sig_data信号中。
在AudioWidget类中,我们创建了一个AudioThread对象,并连接sig_data信号到update_data()函数。在update_data()函数中,我们将新的FFT数据保存到self.data变量中,并使用update()方法刷新窗口。
在paintEvent()函数中,我们使用QPainter对象绘制FFT图像。我们首先使用fillRect()方法填充窗口,然后使用drawLine()方法绘制FFT图像。
最后,在main函数中,我们创建了一个QApplication对象和一个AudioWidget对象,并运行了应用程序。当用户关闭窗口时,我们停止了AudioThread对象并等待它完成。
阅读全文