PyAudio How do I find the volume of a certain range of sound frequencies

时间秒杀一切 提交于 2020-06-27 12:18:26

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!