如何让这个均衡器更有效率?
How to make this equalizer more efficient?
所以我一直在努力制作一个均衡器,我面临的问题是 pyaudio 流的传输速度比 eq 的速度快得多。正在查找音频文件的低音分量。我将简要概述实现:
我创建了两个额外的线程,并为 gui 使用了 tkinter。线程 1 以 50 毫秒数据块的形式计算声音的低音分量 (fn bass() )。
线程 2 通过在 tkinter 中实际创建一个具有不同左上角坐标的矩形来绘制。
flag2 保留主线程 运行,而 flag 同步 bass() 和 plot() 函数。代码的最后一部分是确保显示不会比歌曲本身快(但现在恰恰相反)。
我在这里附上代码:
import numpy as np
from scipy.io import wavfile
from numpy import fft as fft
import time
import tkinter as tk
import threading
import pyaudio
import wave
CHUNK = 1024
wf = wave.open("test3.wav", 'rb')
p = pyaudio.PyAudio()
###
def callback(in_data, frame_count, time_info, status):
data = wf.readframes(frame_count)
return (data, pyaudio.paContinue)
stream = p.open(format=p.get_format_from_width(wf.getsampwidth()),
channels=wf.getnchannels(),
rate=wf.getframerate(),
output=True,
stream_callback=callback)
####
rate,audData = wavfile.read("test3.wav")
print ("Rate "+str(rate))
print ("Length of wav file(in s) = " + str(audData.shape[0]/rate))
ch1=audData[:]
tim = 0.050
pt=int(tim*rate)
flag2 = True
flag = False
cnt = 0
value=0
def bass():
global pt
global cnt
global audData
global value
global flag2
global flag
cnt +=1
fourier=fft.fft(ch1[((cnt-1)*pt):((cnt)*pt)])
fourier = abs(fourier) / float(pt)
fourier = fourier[0:25]
fourier = fourier**2
if (cnt+1)*pt > len(audData[:]) :
flag2 = False
value = (np.sum(fourier))/pt
flag= True
return
def plot():
global value
global flag
root=tk.Tk()
canvas =tk.Canvas(root,width=200,height=500)
canvas.pack()
while True:
if flag:
canvas.delete("all")
flag=False
greenbox = canvas.create_rectangle(50,500-(value/80),150,500,fill="green")
print(value/80) # to check whether it excees 500
root.update_idletasks()
root.update()
return
def sound():
global data
global stream
global wf
global CHUNK
stream.start_stream()
while stream.is_active():
time.sleep(0.1)
stream.stop_stream()
stream.close()
wf.close()
p.terminate()
bass()
t1 = threading.Thread(target=plot, name='t_1')
t2 = threading.Thread(target=sound, name='t_2')
t1.start()
t2.start()
while flag2:
a = time.time()
bass()
b=time.time()
while (b-a) < tim :
time.sleep(0.015)
b=time.time()
为了克服这个处理速度问题,我尝试每 3 个块处理 1 个:
cnt +=1
fourier=fft.fft(ch1[((3*cnt-3)*pt):((3*cnt-2)*pt)])
fourier = abs(fourier) / float(pt)
fourier = fourier[0:25]
fourier = fourier**2
if (3*cnt+1)*pt > len(audData[:]) :
flag2 = False
#######
while (b-a) < 3*tim :
time.sleep(0.015)
b=time.time()
但是这连这都不合格。几秒钟后可以看到滞后。关于如何改进这一点有什么想法吗?
除了提高效率,更现实的解决方案可能是延迟匹配。如果您可以确定 FFT 和显示(等)过程的延迟,则可以延迟声音输出(使用一定数量的音频样本的 fifo),或者让可视化过程在播放文件中提前读取等效样本数。
所以我一直在努力制作一个均衡器,我面临的问题是 pyaudio 流的传输速度比 eq 的速度快得多。正在查找音频文件的低音分量。我将简要概述实现:
我创建了两个额外的线程,并为 gui 使用了 tkinter。线程 1 以 50 毫秒数据块的形式计算声音的低音分量 (fn bass() )。
线程 2 通过在 tkinter 中实际创建一个具有不同左上角坐标的矩形来绘制。
flag2 保留主线程 运行,而 flag 同步 bass() 和 plot() 函数。代码的最后一部分是确保显示不会比歌曲本身快(但现在恰恰相反)。
我在这里附上代码:
import numpy as np
from scipy.io import wavfile
from numpy import fft as fft
import time
import tkinter as tk
import threading
import pyaudio
import wave
CHUNK = 1024
wf = wave.open("test3.wav", 'rb')
p = pyaudio.PyAudio()
###
def callback(in_data, frame_count, time_info, status):
data = wf.readframes(frame_count)
return (data, pyaudio.paContinue)
stream = p.open(format=p.get_format_from_width(wf.getsampwidth()),
channels=wf.getnchannels(),
rate=wf.getframerate(),
output=True,
stream_callback=callback)
####
rate,audData = wavfile.read("test3.wav")
print ("Rate "+str(rate))
print ("Length of wav file(in s) = " + str(audData.shape[0]/rate))
ch1=audData[:]
tim = 0.050
pt=int(tim*rate)
flag2 = True
flag = False
cnt = 0
value=0
def bass():
global pt
global cnt
global audData
global value
global flag2
global flag
cnt +=1
fourier=fft.fft(ch1[((cnt-1)*pt):((cnt)*pt)])
fourier = abs(fourier) / float(pt)
fourier = fourier[0:25]
fourier = fourier**2
if (cnt+1)*pt > len(audData[:]) :
flag2 = False
value = (np.sum(fourier))/pt
flag= True
return
def plot():
global value
global flag
root=tk.Tk()
canvas =tk.Canvas(root,width=200,height=500)
canvas.pack()
while True:
if flag:
canvas.delete("all")
flag=False
greenbox = canvas.create_rectangle(50,500-(value/80),150,500,fill="green")
print(value/80) # to check whether it excees 500
root.update_idletasks()
root.update()
return
def sound():
global data
global stream
global wf
global CHUNK
stream.start_stream()
while stream.is_active():
time.sleep(0.1)
stream.stop_stream()
stream.close()
wf.close()
p.terminate()
bass()
t1 = threading.Thread(target=plot, name='t_1')
t2 = threading.Thread(target=sound, name='t_2')
t1.start()
t2.start()
while flag2:
a = time.time()
bass()
b=time.time()
while (b-a) < tim :
time.sleep(0.015)
b=time.time()
为了克服这个处理速度问题,我尝试每 3 个块处理 1 个:
cnt +=1
fourier=fft.fft(ch1[((3*cnt-3)*pt):((3*cnt-2)*pt)])
fourier = abs(fourier) / float(pt)
fourier = fourier[0:25]
fourier = fourier**2
if (3*cnt+1)*pt > len(audData[:]) :
flag2 = False
#######
while (b-a) < 3*tim :
time.sleep(0.015)
b=time.time()
但是这连这都不合格。几秒钟后可以看到滞后。关于如何改进这一点有什么想法吗?
除了提高效率,更现实的解决方案可能是延迟匹配。如果您可以确定 FFT 和显示(等)过程的延迟,则可以延迟声音输出(使用一定数量的音频样本的 fifo),或者让可视化过程在播放文件中提前读取等效样本数。