I have an incoming audio stream via my microphone which pyaudio is reading, im performing FFT calculations to that data and what i would like is to plot the FFT amplitude data on the Y axis, and the FFT frequency Data on the X axis and have it update at (lets say 20fps for example), basically to look like this ( https://www.youtube.com/watch?v=Tu8p2pywJAs&t=93s ) but with the low frequencies on the left and the higher frequencies on the right. The code i have is as far as i have got
i am new to python, let alone to coding of any way shape or form so any help is appreciated but please try and keep it to understandable terms, if i ask to elaborate please do so with respect, thankyou very much to anyone who gives me their time!
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()
callback_output = []
def callback(in_data, frame_count, time_info, flag):
audio_data = np.fromstring(in_data, dtype=np.int16)
callback_output.append(audio_data)
return None,pyaudio.paContinue
stream = pa.open(format=pyaudio.paInt16,
channels=1,
rate=44100,
output=False,
input=True,
stream_callback=callback)
stream.start_stream()
fig = plt.gcf()
fig.show()
fig.canvas.draw()
while stream.is_active():
fft_data = np.fft.fft(callback_output)
fft_freq = np.fft.fftfreq(len(fft_data))
plt.plot(fft_freq,fft_data)
plt.xlim(min(fft_freq),max(fft_freq))
fig.canvas.draw()
plt.pause(0.05)
fig.canvas.flush_events()
fig.clear()
stream.close()
pa.terminate()
I can't generate data for you but I wrote an example which updates a matplotlib graph in a loop:
import matplotlib.pyplot as plt
import numpy as np
import time
plt.ion() # Stop matplotlib windows from blocking
# Setup figure, axis and initiate plot
fig, ax = plt.subplots()
xdata, ydata = [], []
ln, = ax.plot([], [], 'ro-')
while True:
time.sleep(0.5)
# Get the new data
xdata = np.arange(10)
ydata = np.random.random(10)
# Reset the data in the plot
ln.set_xdata(xdata)
ln.set_ydata(ydata)
# Rescale the axis so that the data can be seen in the plot
# if you know the bounds of your data you could just set this once
# so that the axis don't keep changing
ax.relim()
ax.autoscale_view()
# Update the window
fig.canvas.draw()
fig.canvas.flush_events()
You should just be able to change the lines where xdata and ydata are assigned in the loop to get it working for your data.
If you want to get the low frequencies on the left you might want to look at using np.fft.fftshift on fftfreq and fftdata: https://docs.scipy.org/doc/numpy/reference/generated/numpy.fft.fftshift.html
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With