misc/python/spectrum.py
2018-08-05 18:53:07 +02:00

78 lines
1.8 KiB
Python
Executable File

#!/usr/bin/env nix-script
#!>python
#! python | matplotlib numpy scipy pyaudio
## Real-time sound spectrum analysis.
import pyaudio
import scipy.fftpack
import scipy.interpolate
import numpy
import pylab
#pyAudio settings
settings = {
"format": pyaudio.paInt16,
"channels": 2,
"rate": 96000,
"input": True,
"frames_per_buffer": 1024
}
audio = pyaudio.PyAudio()
stream = audio.open(**settings)
#pyLab configurations
pylab.ion()
figura, (spectrum_log, spectrum, wave) = pylab.subplots(nrows=3, ncols=1)
pylab.subplots_adjust(hspace=0.5, left=0.1)
#Plot settings
spectrum_log.set_ylabel("a (dB)")
spectrum_log.set_xlabel("ƒ (Hz)")
spectrum_log.ticklabel_format(style="sci", scilimits=(0, 0), axis="x")
spectrum_log.grid(True)
curve1, = spectrum_log.plot([0, 8 * 10 ** 3], [0, 10 ** 2], "b-")
spectrum.yaxis.set_visible(False)
spectrum.set_xlabel("ƒ (Hz)")
spectrum.ticklabel_format(style="sci", scilimits=(0, 0), axis="x")
spectrum.grid(True)
curve2, = spectrum.plot([0, 8 * 10 ** 3], [0, 10 ** 5])
wave.xaxis.set_visible(False)
wave.yaxis.set_visible(False)
curve3, = wave.plot([0, 8 * 10 ** 3], [-2 * 10 ** 3, 2 * 10 ** 3], "g-")
#Main loop
while True:
#Acquire data from microphone
try:
block = numpy.array(numpy.fromstring(
stream.read(settings["frames_per_buffer"]), dtype="int16"))
except IOError:
continue
#FFT of registred block
fftx = scipy.fftpack.rfftfreq(
settings["frames_per_buffer"],
1 / settings["rate"])
#Calculate log version
ffty = abs(scipy.fftpack.fft(block)[0:len(fftx)])
ffty_log = 10 * scipy.log10(ffty)
#Data interpolation
wave = scipy.interpolate.interp1d(fftx, block[0:len(fftx)])(fftx)
#Update plot data
curve1.set_xdata(fftx)
curve2.set_xdata(fftx)
curve3.set_xdata(fftx)
curve1.set_ydata(ffty_log)
curve2.set_ydata(ffty)
curve3.set_ydata(wave)
#Redraw
pylab.draw()