问题
I am trying to make a program in python which will take in sound frequencies with pyaudio and show ranges of frequencies as bars going up and down using turtle. I want it to look something like this:
I followed this tutorial for getting and graphing the sound data in an fft format: https://www.youtube.com/watch?v=aQKX3mrDFoY
My code is formatted to have 32 eq bands. To split the frequencies into 32 groups, I loop through the frequency list created by pyaudio and add all of the values of the list in groups of 32, then I make each value in the list a percentage of the largest value (so that the input volume hopefully doesn't matter). There are 1024 different frequencies in the list before it is split. Here is the function I use to split these values:
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]
I multiply each value by 400 at the end so that turtle will draw over a large part of the screen.
When I run the code one line is usually much higher than all of the other lines (which is to be expected because each one is a percent of the largest one). The problem is that it doesn't change at all when I play music or even certain frequencies. It always looks somewhat like this (with the bars moving at random):
Does anyone have any idea what the problem is? Here is my full code:
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)
来源:https://stackoverflow.com/questions/59240015/pyaudio-how-do-i-find-the-volume-of-a-certain-range-of-sound-frequencies