Skip to content

Instantly share code, notes, and snippets.

@ssfrr
Created January 12, 2018 19:32
Show Gist options
  • Save ssfrr/3b8f76fe57d3960354b0687d24099cbd to your computer and use it in GitHub Desktop.
Save ssfrr/3b8f76fe57d3960354b0687d24099cbd to your computer and use it in GitHub Desktop.
using Makie
using PortAudio
"""
Slide the values in the given matrix to the right by 1.
The rightmosts column is discarded and the leftmost column is
left alone.
"""
function shift1!(buf::AbstractMatrix)
for col in size(buf,2):-1:2
@. buf[:, col] = buf[:, col-1]
end
end
"""
takes a block of audio, FFT it, and write it to the beginning of the buffer
"""
function processbuf!(readbuf, dispbuf, fftbuf, fftplan)
A_mul_B!(fftbuf, fftplan, readbuf)
shift1!(dispbuf)
@. dispbuf[end:-1:1,1] = log(clamp(abs(fftbuf[1:D]), 0.0001, Inf))
end
function processblock!(src, buf, dispbufs, fftbuf, fftplan)
read!(src, buf)
for dispbuf in dispbufs
processbuf!(buf, dispbuf, fftbuf, fftplan)
end
end
N = 1024 # size of audio read
N2 = N÷2+1 # size of rfft output
D = 200 # number of bins to display
M = 200 # amount of history to keep
src = PortAudioStream(1, 2, blocksize=N)
buf = Array{Float32}(N) # buffer for reading
fftplan = plan_rfft(buf; flags=FFTW.EXHAUSTIVE)
fftbuf = Array{Complex{Float32}}(N2) # destination buf for FFT
dispbufs = [zeros(Float32, D, M) for i in 1:5, j in 1:5] # STFT bufs
scene = Scene(resolution=(1000,1000))
#pre-fill the display buffer so we can do a reasonable colormap
for _ in 1:M
processblock!(src, buf, dispbufs, fftbuf, fftplan)
end
heatmaps = map(enumerate(IndexCartesian(), dispbufs)) do ibuf
i = ibuf[1]
buf = ibuf[2]
# some function of the 2D index and the value
heatmap(buf, offset=(i[2]*size(buf, 2), i[1]*size(buf, 1)))
end
center!(scene)
while isopen(scene[:screen])
processblock!(src, buf, dispbufs, fftbuf, fftplan)
for (hm, db) in zip(heatmaps, dispbufs)
hm[:heatmap] = db
end
render_frame(scene)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment