57 lines
No EOL
1.7 KiB
Julia
57 lines
No EOL
1.7 KiB
Julia
using Makie, GeometryTypes
|
|
using PortAudio
|
|
using FFTW
|
|
using CairoMakie
|
|
|
|
function waterfall_lines(seconds;
|
|
N = 1024, # size of audio read
|
|
D = 200, # number of bins to display
|
|
M = 100, # number of lines to draw
|
|
S = 0.5, # motion speed of lines
|
|
)
|
|
PortAudioStream(1, 2) do src
|
|
N2 = N ÷ 2 + 1 # size of rfft output
|
|
buf = Array{Float32}(undef, N)
|
|
fftbuf = Array{Complex{Float32}}(undef, N2)
|
|
magbuf = Array{Float32}(undef, N2)
|
|
fftplan = plan_rfft(buf; flags = FFTW.EXHAUSTIVE)
|
|
|
|
scene = Scene(resolution = (500, 500))
|
|
ax = axis(0:0.1:1, 0:0.1:1, 0:0.1:0.5)
|
|
center!(scene)
|
|
|
|
ls = map(1:M) do _
|
|
yoffset = to_node(to_value(scene[:time]))
|
|
offset = lift_node(scene[:time], yoffset) do t, yoff
|
|
Point3f0(0.0f0, (t - yoff) * S, 0.0f0)
|
|
end
|
|
l = lines(
|
|
linspace(0, 1, D),
|
|
0.0f0,
|
|
zeros(Float32, D),
|
|
offset = offset,
|
|
color = (:black, 0.1),
|
|
)
|
|
(yoffset, l)
|
|
end
|
|
done = false
|
|
@sync begin
|
|
@async begin
|
|
while !done
|
|
for (yoffset, line) in ls
|
|
isopen(scene[:screen]) || break
|
|
read!(src, buf)
|
|
A_mul_B!(fftbuf, fftplan, buf)
|
|
@. magbuf = log(clamp(abs(fftbuf), 0.0001, Inf)) / 10 + 0.5
|
|
line[:z] = magbuf[1:D]
|
|
push!(yoffset, to_value(scene[:time]))
|
|
end
|
|
end
|
|
end
|
|
sleep(seconds)
|
|
done = true
|
|
end
|
|
end
|
|
end
|
|
|
|
waterfall_lines(5) |