用python制作一边录音一边播音一边显示FFT波形pyqt5一个开始按键的多线程程序
时间: 2023-10-05 13:05:42 浏览: 264
FFT.zip_fft_fft python_python FFT程序_python fft
以下是一个简单的基于PyQt5和PyAudio库的多线程程序,可以实现一边录音一边播音一边显示FFT波形,包含一个开始按键,点击开始后程序会启动一个新的线程进行录音、播音和FFT波形显示。
```python
import sys
import numpy as np
import pyaudio
import wave
from PyQt5.QtCore import QThread, pyqtSignal
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton
from matplotlib.backends.qt_compat import QtWidgets
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
class RecorderThread(QThread):
signal_data = pyqtSignal(np.ndarray)
def __init__(self):
super().__init__()
self.chunk = 1024
self.format = pyaudio.paInt16
self.channels = 1
self.rate = 44100
self.frames = []
self.stop_flag = False
def run(self):
p = pyaudio.PyAudio()
stream = p.open(format=self.format,
channels=self.channels,
rate=self.rate,
input=True,
frames_per_buffer=self.chunk)
while not self.stop_flag:
data = stream.read(self.chunk)
self.frames.append(data)
samples = np.frombuffer(data, dtype=np.int16)
self.signal_data.emit(samples)
stream.stop_stream()
stream.close()
p.terminate()
def stop(self):
self.stop_flag = True
class PlayerThread(QThread):
def __init__(self, frames):
super().__init__()
self.frames = frames
self.chunk = 1024
self.format = pyaudio.paInt16
self.channels = 1
self.rate = 44100
def run(self):
p = pyaudio.PyAudio()
stream = p.open(format=self.format,
channels=self.channels,
rate=self.rate,
output=True)
for data in self.frames:
stream.write(data)
stream.stop_stream()
stream.close()
p.terminate()
class FFTThread(QThread):
signal_fft = pyqtSignal(np.ndarray)
def __init__(self):
super().__init__()
self.chunk = 1024
self.rate = 44100
self.stop_flag = False
def run(self):
while not self.stop_flag:
samples = yield self.chunk
fft = np.fft.fft(samples) / self.chunk
fft = np.abs(fft[0:int(self.chunk / 2)])
self.signal_fft.emit(fft)
def stop(self):
self.stop_flag = True
class App(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
btn_start = QPushButton('Start', self)
btn_start.setGeometry(10, 10, 100, 30)
btn_start.clicked.connect(self.start)
self.fig = Figure()
self.canvas = FigureCanvas(self.fig)
layout = QtWidgets.QVBoxLayout(self)
layout.addWidget(self.canvas)
self.setGeometry(100, 100, 600, 400)
self.setWindowTitle('Recorder')
self.show()
def start(self):
self.recorder_thread = RecorderThread()
self.fft_thread = FFTThread()
self.recorder_thread.signal_data.connect(self.fft_thread.run)
self.fft_thread.signal_fft.connect(self.update_fft)
self.recorder_thread.start()
self.fft_thread.start()
def update_fft(self, fft):
self.fig.clear()
ax = self.fig.add_subplot(111)
ax.plot(fft)
self.canvas.draw()
def closeEvent(self, event):
if hasattr(self, 'recorder_thread'):
self.recorder_thread.stop()
if hasattr(self, 'fft_thread'):
self.fft_thread.stop()
event.accept()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
sys.exit(app.exec_())
```
在程序中,RecorderThread类用于录制音频,PlayerThread类用于播放音频,FFTThread类用于计算FFT波形。App类是主窗口类,包含一个开始按键和一个用于显示FFT波形的matplotlib FigureCanvas。点击开始按键后,程序会启动一个新的RecorderThread和FFTThread线程,RecorderThread线程不断从麦克风中读取音频数据,并将数据传递给FFTThread线程进行FFT计算,FFTThread线程计算完成后将FFT波形数据传递给主线程,在主线程中更新matplotlib FigureCanvas显示FFT波形。程序运行时可以通过关闭窗口或按下Ctrl+C停止线程。
阅读全文