While matplotlib works well for displaying static graphs and charts, sometimes we may need to display a continuous (live) waveform on a graph. This requires repeatedly retrieving and displaying samples of incoming data (an audio stream, for example). An interesting way to display such a continuously varying waveform is to use the ‘Animation’ classes built into matplotlib.
In this example, we utilize matplotlib’s FuncAnimation class that can take a user defined function (‘animate’) which, in turn, provides samples of data to display on the output trace. We utilize the audio stream from the PC’s default audio input device to retrieve audio data samples in ‘animate’. This results in a continuous trace of the audio stream.
import numpy as np import pyaudio from matplotlib import pyplot as plt from matplotlib.animation import FuncAnimation plt.style.use('bmh') SAMPLESIZE = 4096 # number of data points to read at a time SAMPLERATE = 44100 # time resolution of the recording device (Hz) p = pyaudio.PyAudio() # instantiate PyAudio stream=p.open(format=pyaudio.paInt16,channels=1,rate=SAMPLERATE,input=True, frames_per_buffer=SAMPLESIZE) # use default input device to open audio stream # set up plotting fig = plt.figure() ax = plt.axes(xlim=(0, SAMPLESIZE-1), ylim=(-9999, 9999)) line, = ax.plot([], [], lw=1) # x axis data points x = np.linspace(0, SAMPLESIZE-1, SAMPLESIZE) # methods for animation def init(): line.set_data([], []) return line, def animate(i): y = np.frombuffer(stream.read(SAMPLESIZE), dtype=np.int16) line.set_data(x, y) return line, FuncAnimation(fig, animate, init_func=init, frames=200, interval=20, blit=True) plt.show() # stop and close the audio stream stream.stop_stream() stream.close() p.terminate()