Simple python spectrograph with shoebot
Posted by stu at May 17th, 2010
Seeing”Realtime FFT Graph of Audio WAV File or Microphone Input with Python…” on python.reddit.com reminded me of one I’d built in python with shoebot.
While it works OK, I feel like I’m missing a higher level audio library (especially having seen Minim, for C++ and Java).
To run it in shoebot:
sbot -w audiobot.bot
audiobot.bot
# Major library imports
import atexit
import pyaudio
from numpy import zeros, short, fromstring, array
from numpy.fft import fft
NUM_SAMPLES = 512
SAMPLING_RATE = 11025
def setup():
size(350, 260)
speed(SAMPLING_RATE / NUM_SAMPLES)
_stream = None
def read_fft():
global _stream
pa = None
def cleanup_audio():
if _stream:
_stream.stop_stream()
_stream.close()
pa.terminate()
if _stream is None:
pa = pyaudio.PyAudio()
_stream = pa.open(format=pyaudio.paInt16, channels=1,
rate=SAMPLING_RATE,
input=True, frames_per_buffer=NUM_SAMPLES)
atexit.register(cleanup_audio)
audio_data = fromstring(_stream.read(NUM_SAMPLES), dtype=short)
normalized_data = audio_data / 32768.0
return fft(normalized_data)[1:1+NUM_SAMPLES/2]
def flatten_fft(scale = 1.0):
"""
Produces a nicer graph, I'm not sure if this is correct
"""
for i, v in enumerate(read_fft()):
yield scale * (i * v) / NUM_SAMPLES
def triple(audio):
'''return bass/mid/treble'''
c = audio.copy()
c.resize(3, 255 / 3)
return c
def draw():
'''Draw 3 different colour graphs'''
global NUM_SAMPLES
audio = array(list(flatten_fft(scale = 80)))
freqs = len(audio)
bass, mid, treble = triple(audio)
colours = (0.5, 1.0, 0.5), (1, 1, 0), (1, 0.2, 0.5)
fill(0, 0, 1)
rect(0, 0, WIDTH, 400)
translate(50, 200)
for spectrum, col in zip((bass, mid, treble), colours):
fill(col)
for i, s in enumerate(spectrum):
rect(i, 0, 1, -abs(s))
else:
translate(i, 0)
audio = array(list(flatten_fft(scale = 80)))







