问题描述
audio_chart.py
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'audio_chart.ui'
#
# Created by: PyQt5 UI code generator 5.15.4
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you kNow what you are doing.
from PyQt5 import QtCore,QtGui,QtWidgets
class Ui_MainWindow(object):
def setupUi(self,MainWindow):
MainWindow.setobjectName("MainWindow")
MainWindow.resize(800,200)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding,QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(MainWindow.sizePolicy().hasHeightForWidth())
MainWindow.setSizePolicy(sizePolicy)
MainWindow.setMinimumSize(QtCore.QSize(0,200))
MainWindow.setMaximumSize(QtCore.QSize(16777215,200))
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setobjectName("centralwidget")
self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
self.verticalLayout.setContentsMargins(0,0)
self.verticalLayout.setSpacing(0)
self.verticalLayout.setobjectName("verticalLayout")
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self,MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setwindowTitle(_translate("MainWindow","Audio chart"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.showMaximized()
sys.exit(app.exec_())
audio_chart_code.py
from PyQt5 import QtCore,QtWidgets
from PyQt5.QtCore import pyqtSlot
from audio_chart import *
import sys
import pyaudio
from pydub import AudioSegment
import numpy as np
import queue
import matplotlib.pyplot as plt
from matplotlib.backends.backend_qt5agg import figureCanvasQTAgg as figureCanvas
from matplotlib import dates as mpl_dates
from matplotlib.animation import FuncAnimation
import datetime
class AudioChart:
def __init__(self):
self.app = QtWidgets.QApplication(sys.argv)
self.MainWindow = QtWidgets.QMainWindow()
self.ui = Ui_MainWindow()
self.ui.setupUi(self.MainWindow)
self.MainWindow.showMaximized()
#QoS settings
self.bit_rate = 128*1024 #128 kb/sec
self.packet_time = 125 #125 msec
self.packet_size = int(16384/4)
self.format = pyaudio.paInt16
self.channels = 2
self.test_sound = AudioSegment.from_file("pokemon.mp3",format="mp3")
slice = self.test_sound[0:1000]
self.test_sound_1_second_size = len(slice.raw_data)
self.test_sound_sample_rate = self.test_sound.frame_rate
self.new_sample_rate = int(self.test_sound_sample_rate*self.bit_rate/self.test_sound_1_second_size)
self.audio_timedelta = self.packet_time/(2*self.packet_size) #msec
self.test_sound = self.test_sound.set_frame_rate(self.new_sample_rate)
self.p = pyaudio.PyAudio()
#self.q = queue.Queue(maxsize=20)
self.q = queue.Queue()
self.chunk_number = 0
self.animate_window = 3000 #3 seconds
self.chart = Canvas(self)
self.chart.ax.set_facecolor((1,1,1))
#self.chart.ax.spines['top'].set_color('white')
self.chart.ax.tick_params(labelcolor='white')
self.x_vals = []
self.y_vals = []
self.x_1_vals = []
self.y_1_vals = []
self.x_2_vals = []
self.y_2_vals = []
self.stream = self.p.open(format=self.format,channels=self.channels,rate=self.new_sample_rate,output=True,stream_callback=self.play_pokemon,frames_per_buffer=self.packet_size)
self.stream.start_stream()
self.animate_chunks = self.animate_window/self.packet_time
self.ani = FuncAnimation(plt.gcf(),self.animate,interval=self.packet_time)
'''
self.threadpool = QtCore.QThreadPool()
worker = Worker(self.start_stream,)
self.threadpool.start(worker)
'''
def start_stream(self):
self.stream.start_stream()
self.animate_chunks = self.animate_window/self.packet_time
self.ani = FuncAnimation(plt.gcf(),interval=self.packet_time/2)
def play_pokemon(self,in_data,frame_count,time_info,status):
slice = self.test_sound[self.chunk_number*(self.packet_time):(self.chunk_number+1)*(self.packet_time)]
self.Now = datetime.datetime.Now()
frame = np.frombuffer(slice.raw_data,dtype=np.int16)
#normalized_signal = frame/200000
normalized_signal = frame
'''
frame = []
counter = 0
for audio_number in normalized_signal:
audio_time = self.Now+datetime.timedelta(milliseconds=counter*self.audio_timedelta)
counter +=1
frame.append([audio_time,audio_number])
'''
average_every = len(normalized_signal)/256
frame = []
self.counter = 0
total = 0
for audio_number in normalized_signal:
#audio_time = self.Now+datetime.timedelta(milliseconds=counter*self.audio_timedelta)
#frame.append([audio_time,audio_number])
self.counter +=1
total = total+audio_number
if(average_every==self.counter):
audio_average_number = total/self.counter
if(len(frame)==0):
audio_average_time = datetime.datetime(2021,0)+datetime.timedelta(milliseconds=self.chunk_number*(self.packet_time))
else:
audio_average_time = frame[-1][0]+datetime.timedelta(milliseconds=self.counter*self.audio_timedelta)
frame.append([audio_average_time,audio_average_number])
self.counter = 0
total = 0
self.q.put(frame)
self.chunk_number = self.chunk_number+1
return (slice.raw_data,pyaudio.paContinue)
def animate(self,i):
try:
while True:
try:
data = self.q.get_Nowait()
dates_1 = [i[0] for i in data]
audio_numbers_1 = [i[1] for i in data]
audio_numbers_2 = [i[1]+1 for i in data]
audio_numbers_3 = [i[1]-1 for i in data]
self.x_vals = self.x_vals+dates_1
self.y_vals = self.y_vals+audio_numbers_1
self.x_1_vals = self.x_1_vals+dates_1
self.y_1_vals = self.y_1_vals+audio_numbers_2
self.x_2_vals = self.x_2_vals+dates_1
self.y_2_vals = self.y_2_vals+audio_numbers_3
if(self.chunk_number>self.animate_chunks):
self.x_vals = self.x_vals[len(dates_1)::]
self.y_vals = self.y_vals[len(audio_numbers_1)::]
self.x_1_vals = self.x_1_vals[len(dates_1)::]
self.y_1_vals = self.y_1_vals[len(audio_numbers_1)::]
self.x_2_vals = self.x_2_vals[len(dates_1)::]
self.y_2_vals = self.y_2_vals[len(audio_numbers_1)::]
'''
date_1 = data[0]
average_number = data[1]
self.x_vals.append(date_1)
self.y_vals.append(average_number)
if(self.chunk_number>self.animate_chunks):
self.x_vals = self.x_vals[1::]
self.y_vals = self.y_vals[1::]
'''
plt.cla()
self.chart.ax.plot_date(self.x_1_vals,self.y_1_vals,color=(153/255,153/255,0),linestyle='solid',marker=",")
self.chart.ax.plot_date(self.x_2_vals,self.y_2_vals,")
self.chart.ax.plot_date(self.x_vals,self.y_vals,color=(0,0.29),")
date_format = mpl_dates.DateFormatter("%H:%M:%s")
plt.gca().xaxis.set_major_formatter(date_format)
plt.xticks(fontsize=5)
#self.chart.ax.grid(True,linestyle='--')
self.chart.ax.grid(False)
self.chart.ax.set_xlim([self.x_vals[0],self.x_vals[-1]])
ticks = []
for timedelta_time in range(0,self.animate_window+1,1000):
tick = self.x_vals[0]+datetime.timedelta(milliseconds=timedelta_time)
ticks.append(tick)
plt.xticks(ticks)
except queue.Empty:
break
except:
pass
return self.chart.ax,class Canvas(figureCanvas):
def __init__(self,parent):
fig,self.ax = plt.subplots(figsize=(5,4),dpi=200)
fig.patch.set_facecolor((6/255,21/255,154/255))
self.ax.set_position([0.,1.,0.8])
self.ax.xaxis.tick_top()
self.ax.tick_params(color=(1,1))
#self.ax.xaxis.set_color((1,1))
super().__init__(fig)
parent.ui.verticalLayout.addWidget(self)
#t = np.arange(0.0,2.0,0.01)
#s = 1 +np.sin(2*np.pi*t)
plt.xticks(fontsize=6)
self.ax.grid(True,linestyle='--')
self.Now = datetime.datetime.Now()
self.chart_stop = self.Now+datetime.timedelta(milliseconds=3000)
plt.cla()
#self.chart.ax.plot_date(self.x_vals,linestyle='solid')
date_format = mpl_dates.DateFormatter("%H:%M:%s")
plt.gca().xaxis.set_major_formatter(date_format)
plt.xticks(fontsize=5)
self.ax.grid(True,linestyle='--')
self.ax.set_xlim([self.Now,self.chart_stop])
plt.xticks([self.Now,self.Now+datetime.timedelta(milliseconds=1000),self.Now+datetime.timedelta(milliseconds=2000)])
self.show()
class Worker(QtCore.QRunnable):
def __init__(self,function,*args,**kwargs):
super(Worker,self).__init__()
self.function = function
self.args = args
self.kwargs = kwargs
@pyqtSlot()
def run(self):
self.function(*self.args,**self.kwargs)
audio_chart = AudioChart()
sys.exit(audio_chart.app.exec_())
使用以下命令运行程序:python audio_chart_code.py
在运行之前,下载 pokemon theme song 并将其放置在同一目录中。
正如您所听到的 - 请注意情节和声音之间存在不匹配延迟。 另请注意,在使用 pyinstaller 命令生成可执行文件后,我尝试从平板电脑运行该程序,但没有成功(应用程序几乎崩溃)。
任何建议都是有用的, 克里斯·帕帕斯
- 我用 pyqtgraph 做了一个类似的程序,但它有同样的延迟问题...... :/
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)