我正在尝试用python制作一个程序,该程序将使用pyaudio接收声音频率,并使用乌龟将频率范围显示为横线向上和向下。我希望它看起来像这样:
我遵循了本教程,以fft格式获取和绘制声音数据: https://www.youtube.com/watch?v=aQKX3mrDFoY
我的代码被格式化为具有32个eq带。要将频率分为32组,我遍历pyaudio创建的频率列表,并以32组为单位添加列表的所有值,然后使列表中的每个值占最大值的百分比(这样输入音量无所谓)。在拆分之前,列表中有1024个不同的频率。这是我用来拆分这些值的函数:
def split_freq(freq): # splits given sound frequencies into groups of frequencies to feed into turtle
freq_ranges = []
for i in range(len(freq)-1): # split the frequencies into 32 groups
if i % abs((len(freq)//32)) == 0:
if len(freq_ranges) > 0:
freq_ranges[len(freq_ranges)-2] = freq_ranges[len(freq_ranges)-2]
freq_ranges.append(0)
freq_ranges[len(freq_ranges)-1] = freq_ranges[len(freq_ranges)-1] + freq[i]
for i in range(len(freq_ranges)):
freq_ranges[i] = (freq_ranges[i] / np.array(freq_ranges).max())
return [i * 400 for i in freq_ranges]
我将每个值最后都乘以400,这样乌龟就会在屏幕的很大一部分上绘制。
当我运行代码时,一行通常比其他所有行都高得多(这是可以预料的,因为每一行都是最大行的百分比)。问题是当我播放音乐甚至某些频率时,它根本不会改变。看起来总是这样(条形图随机移动):
有人知道这个问题是什么吗?这是我的完整代码:
import pyaudio
import struct
import numpy as np
from scipy.fftpack import fft
import turtle
import time
def update_graph(frequencies):
for i in range(len(eq_bars)):
eq_bars[i].penup()
eq_bars[i].sety(-200)
eq_bars[i].setx(-230+(i*15))
eq_bars[i].setheading(90)
eq_bars[i].pendown()
eq_bars[i].fd(frequencies[i]) # go up by the amount of the current frequency
eq_bars[i].penup()
eq_bars[i].setx(1+(i*20))
for eq_bar in eq_bars:
eq_bar.clear()
def split_freq(freq): # splits given sound frequencies into groups of frequencies to feed into turtle
freq_ranges = []
for i in range(len(freq)-1): # split the frequencies into 32 groups
if i % abs((len(freq)//32)) == 0:
if len(freq_ranges) > 0:
freq_ranges[len(freq_ranges)-2] = freq_ranges[len(freq_ranges)-2]
freq_ranges.append(0)
freq_ranges[len(freq_ranges)-1] = freq_ranges[len(freq_ranges)-1] + freq[i]
for i in range(len(freq_ranges)):
freq_ranges[i] = (freq_ranges[i] / np.array(freq_ranges).max())
return [i * 400 for i in freq_ranges]
CHUNK = 2**10
FORMAT = pyaudio.paInt16
CHANNELS = 1
RATE = 44100
p = pyaudio.PyAudio()
stream=p.open(format=FORMAT,channels=CHANNELS,rate=RATE,input=True,
output=True, frames_per_buffer=CHUNK)
wn = turtle.Screen()
wn.bgcolor("black")
wn.setup(width = 600, height = 600)
wn.title("Audio Visualizer")
wn.delay(0)
eq_bars = []
for i in range(32):
eq_bars.append(turtle.Turtle())
eq_bars[i].hideturtle()
eq_bars[i].speed(0)
eq_bars[i].pensize(5)
eq_bars[i].color("white")
eq_bars[i].penup()
eq_bars[i].sety(-200)
eq_bars[i].setx(-230+(i*15))
eq_bars[i].setheading(90)
eq_bars[i].pendown()
eq_bars[i].fd(100)
eq_bars[i].penup()
eq_bars[i].setx(1+(i*20))
x = np.arange(0, 2*CHUNK, 2)
x_fft = np.linspace(0, RATE, CHUNK)
while True:
data = struct.unpack(str(CHUNK*CHANNELS) + 'h', stream.read(CHUNK))
data = stream.read(CHUNK)
data = np.array(struct.unpack(str(2*CHUNK) + 'B', data), dtype='b')[::2] + 127
y_fft = fft(data)
y_fft = np.abs(y_fft[:CHUNK]) * 2 / (256 * CHUNK)
print(len(y_fft))
turtle_data = split_freq(y_fft)
update_graph(turtle_data)