0

So I'm trying to make a music visualizer, I'm very new to python ( let alone coding in general ) for a project I need to make a music visualiser however I'm struggling, I've managed to get an open audio stream.

Things i need help on :

Is this below code the correct way of getting the fft data and fftfreq data ( assuming thats amplitude and frequency data )? And do i need to do this calculation somewhere else? Or is doing it within that function the correct way?

How come when I try and print the fft_data at the end of the code, I get the error of ( fft_data is not defined ) even though I believe the function is called previously in the code and should have calculated something?

Am I correct that to get the resulting variables to be returned from the function i need to put return ( audio_data, fft_data, fft_freq) etc, and if so how come its still not printing fft_data at the bottom?

I will probably be following up with a later post when i am past these issues.

any help is honestly seriously appreciated <3

p.s since im new to python and coding in general please try not to explain in a complicated way, or if i ask, elaborate in simpler terms if possible ( doesnt have to be rediculously simple )

this is the method i want to go for, i dont want to use librosa or other modules i would like to stick with numpy struct and pyaudio as i know its possible

import pyaudio
import numpy as np
import time
import matplotlib.animation as animation
import matplotlib.pyplot as plt
from matplotlib import style

pa = pyaudio.PyAudio()

def callback(in_data, frame_count, time_info, flag):
audio_data = np.fromstring(in_data, dtype=np.float32)
print(audio_data)
fft_data = np.fft.fft(audio_data)
fft_freq = np.fft.fftfreq(len(fft_data))
return (audio_data, fft_data, fft_freq, pyaudio.paContinue)



stream = pa.open(format=pyaudio.paFloat32,
             channels=1,
             rate=44100,
             output=False,
             input=True,
             stream_callback=callback)

stream.start_stream()

stream.close()
pa.terminate()

print(fft_data)

If I do print(audio_data) inside the callback function, it prints the audio data but I'm not sure if its already plottable so I presume I have to use fft on it. However when I try and print fft_data at the bottom of the code it says "fft_data is not defined".

cronburg
  • 892
  • 1
  • 8
  • 24
m e m e
  • 105
  • 2
  • 11
  • `fft_data` isn't defined at the end of the file because it is created as a local variable in the callback which goes out of scope whenever the `callback()` function finishes executing. You could use `fft_data` [as a global variable](https://stackoverflow.com/a/423596/1542000), which may or may not partially achieve what you want. – cronburg May 16 '19 at 22:30

1 Answers1

1

from the docs, stream_callback "must return a tuple: (out_data, flag)" and returns control back to the PortAudio rather than your code.

for debugging, you might want to do something like:

callback_output = []

def callback(in_data, frame_count, time_info, flag):
    audio_data = np.fromstring(in_data, dtype=np.float32)
    callback_output.append(
        audio_data
    )
    return None, pyaudio.paContinue

and then do the FFTs afterwards on the data that has been stored in callback_output

Sam Mason
  • 15,216
  • 1
  • 41
  • 60
  • scratch that previous comment if you saw it, i am now stuck on how i would update a matplotlib graph real time, any help would be appreciated seen as you know your stuff :) – m e m e May 16 '19 at 23:57
  • Which matplotlib command are you stuck on exactly? A quick search online reveals [easy real time graphs like this one.](https://stackoverflow.com/a/4098938/1542000) – cronburg May 17 '19 at 02:38