我是新来的,希望我的问题就在这里。 我正在尝试编程GUI,我可以从麦克风录制一些声音并实时绘制,以查看声音的左右声道。
我使用PyQt 5作为我的GUI和Matplotlib-FigureCanvas用于绘图。 流式传输工作正常,但是Plot仅在录制停止后显示,并且在录制期间不会更新,就像它应该的那样。 在调试模式中,我可以在每次更新时看到这些图,但是当我运行代码时,GUI会冻结,直到录制完成。 是这样,因为绘图太慢了? 我尝试了使用动画或线程的不同方法,但到目前为止没有任何工作。
我想最后有一个实时更新的情节,我该如何实现?还有更长的录音?
我希望有人可以帮助我,提前谢谢!
这是我的代码的一部分,我记录和绘图:
import sys
from PyQt5 import QtGui, QtWidgets, QtCore
import numpy as np
import time
import pyaudio
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
from matplotlib.figure import Figure
import matplotlib.gridspec as gridspec
import matplotlib.animation as animation
class Window(QtWidgets.QMainWindow):
def __init__(self): # sort of template for rest of GUI, is always there, menubar/ mainmenu eg.
super(Window, self).__init__()
self.setGeometry(50, 50, 1500, 900)
self.setWindowTitle("PyQt Tutorial!")
self.centralwidget = QtWidgets.QWidget(self)
self.centralwidget.setObjectName("centralwidget")
self.channels = 2
self.fs = 44100 # samplerate
self.Chunks = 1024
self.tapeLength = 2 # seconds
self.tape = np.empty(self.fs * self.tapeLength) * np.nan # tapes where recorded audio is stored
self.taper = np.empty(self.fs * self.tapeLength) * np.nan
self.tapel = np.empty(self.fs * self.tapeLength) * np.nan
self.home()
def home(self):
btn = QtWidgets.QPushButton("Stream and Plot", self) # Button to start streaming
btn.clicked.connect(self.plot)
btn.resize(btn.sizeHint())
btn.move(100, 100)
self.scrollArea = QtWidgets.QScrollArea(self)
self.scrollArea.move(75, 400)
self.scrollArea.resize(600, 300)
self.scrollArea.setWidgetResizable(False)
self.scrollArea2 = QtWidgets.QScrollArea(self)
self.scrollArea2.move(775, 400)
self.scrollArea2.resize(600, 300)
self.scrollArea2.setWidgetResizable(False)
self.scrollArea.horizontalScrollBar().valueChanged.connect(self.scrollArea2.horizontalScrollBar().setValue)
self.scrollArea2.horizontalScrollBar().valueChanged.connect(self.scrollArea.horizontalScrollBar().setValue)
self.figure = Figure((15, 2.8), dpi=100) # figure instance (to plot on) F(width, height, ...)
self.canvas = FigureCanvas(self.figure)
self.scrollArea.setWidget(self.canvas)
self.toolbar = NavigationToolbar(self.canvas, self.scrollArea)
self.canvas2 = FigureCanvas(self.figure)
self.scrollArea2.setWidget(self.canvas2)
self.toolbar2 = NavigationToolbar(self.canvas2, self.scrollArea2)
self.gs = gridspec.GridSpec(1, 1)
self.ax = self.figure.add_subplot(self.gs[0])
self.ax2 = self.figure.add_subplot(self.gs[0])
self.figure.subplots_adjust(left=0.05)
self.ax.clear()
def start_streamsignal(self, start=True):
# open and start the stream
if start is True:
print("start Signals")
self.p = pyaudio.PyAudio()
self.stream = self.p.open(format=pyaudio.paFloat32, channels=self.channels, rate=self.fs, input_device_index=1,
output_device_index=5, input=True, frames_per_buffer=self.Chunks)
print("recording...")
def start_streamread(self):
"""return values for Chunks of stream"""
data = self.stream.read(self.Chunks)
npframes2 = np.array(data).flatten()
npframes2 = np.fromstring(npframes2, dtype=np.float32)
norm_audio2 = (npframes2 / np.max(np.abs(npframes2))) # normalize
left2 = norm_audio2[::2]
right2 = norm_audio2[1::2]
print(norm_audio2)
return left2, right2
def tape_add(self):
"""add chunks to tape"""
self.tape[:-self.Chunks] = self.tape[self.Chunks:]
self.taper = self.tape
self.tapel = self.tape
self.taper[-self.Chunks:], self.tapel[-self.Chunks:] = self.start_streamread()
def plot(self, use_blit=True):
# Plot the Tape and update chunks
print('Plotting')
self.start_streamsignal(start=True)
start = True
for duration in range(0, 15, 1):
plotsec = 1
time.sleep(2)
self.timeArray = np.arange(self.taper.size)
self.timeArray = (self.timeArray / self.fs) * 1000 # scale to milliseconds
self.tape_add()
# self.canvas.draw()
while start is True and plotsec < 3:
# self.ani = animation.FuncAnimation(self.figure, self.animate, interval=25, blit=True)
self.ax2.plot(self.taper, '-b')
self.canvas.draw()
self.ax2.clear()
self.ax2.plot(self.tapel, 'g-')
self.canvas2.draw()
plotsec += 1
def animate(self):
self.line.set_xdata(self.taper)
return self.line,
def main():
app = QtWidgets.QApplication(sys.argv)
GUI = Window()
GUI.show()
sys.exit(app.exec_())
main()
答案 0 :(得分:1)
我确实在理解完整代码方面存在严重问题,因为那里的所有内容应该实际执行。所以我现在可以告诉你的是,你可能想要摆脱循环并使用FuncAnimation
来显示动画。
def plot(self, use_blit=True):
# Plot the Tape and update chunks
print('Plotting')
self.start_streamsignal(start=True)
start = True
self.line, = self.ax2.plot([],[], '-b')
self.ax.set_xlim(0, len(self.tape))
self.ax2.set_xlim(0, len(self.tape))
self.ax.set_ylim(-3, 3)
self.ax2.set_ylim(-3, 3)
self.ani = animation.FuncAnimation(self.figure, self.animate, frames=100,
interval=25, blit=use_blit)
def animate(self,i):
self.timeArray = np.arange(self.taper.size)
self.timeArray = (self.timeArray / self.fs) * 1000 # scale to milliseconds
self.tape_add()
self.line.set_data(range(len(self.taper)),self.taper)
return self.line,
答案 1 :(得分:0)
感谢所有帮助,如果有人感兴趣,这是现在正在运行的代码:
import sys
from PyQt5 import QtGui, QtWidgets, QtCore
import numpy as np
import time
import pyaudio
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
from matplotlib.figure import Figure
import matplotlib.gridspec as gridspec
import matplotlib.animation as animation
class Window(QtWidgets.QMainWindow):
def __init__(self): # sort of template for rest of GUI, is always there, menubar/ mainmenu eg.
super(Window, self).__init__()
self.setGeometry(50, 50, 1500, 900)
self.setWindowTitle("PyQt Tutorial!")
self.centralwidget = QtWidgets.QWidget(self)
self.centralwidget.setObjectName("centralwidget")
self.channels = 2
self.fs = 44100 # samplerate
self.Chunks = 1024
self.tapeLength = 2 # seconds
self.tape = np.empty(self.fs * self.tapeLength) * np.nan # tapes where recorded audio is stored
self.home()
def home(self):
btn = QtWidgets.QPushButton("Stream and Plot", self) # Button to start streaming
btn.clicked.connect(self.plot)
btn.resize(btn.sizeHint())
btn.move(100, 100)
self.scrollArea = QtWidgets.QScrollArea(self)
self.scrollArea.move(75, 400)
self.scrollArea.resize(600, 300)
self.scrollArea.setWidgetResizable(False)
self.scrollArea2 = QtWidgets.QScrollArea(self)
self.scrollArea2.move(775, 400)
self.scrollArea2.resize(600, 300)
self.scrollArea2.setWidgetResizable(False)
self.scrollArea.horizontalScrollBar().valueChanged.connect(self.scrollArea2.horizontalScrollBar().setValue)
self.scrollArea2.horizontalScrollBar().valueChanged.connect(self.scrollArea.horizontalScrollBar().setValue)
self.figure = Figure((15, 2.8), dpi=100) # figure instance (to plot on) F(width, height, ...)
self.canvas = FigureCanvas(self.figure)
self.scrollArea.setWidget(self.canvas)
self.toolbar = NavigationToolbar(self.canvas, self.scrollArea)
self.canvas2 = FigureCanvas(self.figure)
self.scrollArea2.setWidget(self.canvas2)
self.toolbar2 = NavigationToolbar(self.canvas2, self.scrollArea2)
self.gs = gridspec.GridSpec(1, 1)
self.ax = self.figure.add_subplot(self.gs[0])
self.ax2 = self.figure.add_subplot(self.gs[0])
self.figure.subplots_adjust(left=0.05)
self.ax.clear()
def start_streamsignal(self, start=True):
# open and start the stream
if start is True:
print("start Signals")
self.p = pyaudio.PyAudio()
self.stream = self.p.open(format=pyaudio.paFloat32, channels=self.channels, rate=self.fs, input_device_index=1,
output_device_index=5, input=True, frames_per_buffer=self.Chunks)
print("recording...")
def start_streamread(self):
"""return values for Chunks of stream"""
data = self.stream.read(self.Chunks)
npframes2 = np.array(data).flatten()
npframes2 = np.fromstring(npframes2, dtype=np.float32)
norm_audio2 = (npframes2 / np.max(np.abs(npframes2))) # normalize
left2 = norm_audio2[::2]
right2 = norm_audio2[1::2]
print(norm_audio2)
return left2, right2
def tape_add(self):
"""add chunks to tape"""
self.tape[:-self.Chunks] = self.tape[self.Chunks:]
self.taper = self.tape
self.tapel = self.tape
self.taper[-self.Chunks:], self.tapel[-self.Chunks:] = self.start_streamread()
def plot(self, use_blit=True):
# Plot the Tape and update chunks
print('Plotting')
self.start_streamsignal(start=True)
start = True
for duration in range(0, 15, 1):
QtWidgets.QApplication.processEvents()
plotsec = 1
time.sleep(2)
self.timeArray = np.arange(self.taper.size)
self.timeArray = (self.timeArray / self.fs) * 1000 # scale to milliseconds
self.tape_add()
while start is True and plotsec < 3:
self.ax.plot(self.taper, '-b')
self.canvas.draw()
self.ax2.clear()
self.ax2.plot(self.tapel, 'g-')
self.canvas2.draw()
plotsec += 1
def main():
app = QtWidgets.QApplication(sys.argv)
GUI = Window()
GUI.show()
sys.exit(app.exec_())
main()