makie fail
This commit is contained in:
parent
f708835e5a
commit
5056541968
3 changed files with 95 additions and 69 deletions
2
.github/workflows/Tests.yml
vendored
2
.github/workflows/Tests.yml
vendored
|
@ -18,8 +18,6 @@ jobs:
|
||||||
matrix:
|
matrix:
|
||||||
version:
|
version:
|
||||||
- '1.3'
|
- '1.3'
|
||||||
- '1.4'
|
|
||||||
- '1.5'
|
|
||||||
- '1'
|
- '1'
|
||||||
- 'nightly'
|
- 'nightly'
|
||||||
os:
|
os:
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
using Makie
|
using Makie
|
||||||
using PortAudio
|
using PortAudio
|
||||||
using DSP
|
using DSP
|
||||||
|
using LinearAlgebra
|
||||||
|
using FFTW
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Slide the values in the given matrix to the right by 1.
|
Slide the values in the given matrix to the right by 1.
|
||||||
|
@ -16,52 +18,64 @@ end
|
||||||
"""
|
"""
|
||||||
takes a block of audio, FFT it, and write it to the beginning of the buffer
|
takes a block of audio, FFT it, and write it to the beginning of the buffer
|
||||||
"""
|
"""
|
||||||
function processbuf!(readbuf, win, dispbuf, fftbuf, fftplan)
|
function processbuf!(readbuf, win, dispbuf, fftbuf, fftplan; D = 200)
|
||||||
readbuf .*= win
|
readbuf .*= win
|
||||||
A_mul_B!(fftbuf, fftplan, readbuf)
|
mul!(fftbuf, fftplan, readbuf)
|
||||||
shift1!(dispbuf)
|
shift1!(dispbuf)
|
||||||
@. dispbuf[end:-1:1, 1] = log(clamp(abs(fftbuf[1:D]), 0.0001, Inf))
|
@. dispbuf[end:-1:1, 1] = log(clamp(abs(fftbuf[1:D]), 0.0001, Inf))
|
||||||
end
|
end
|
||||||
|
|
||||||
function processblock!(src, buf, win, dispbufs, fftbuf, fftplan)
|
function processblock!(src, buf, win, dispbufs, fftbuf, fftplan; D = 200)
|
||||||
read!(src, buf)
|
read!(src, buf)
|
||||||
for dispbuf in dispbufs
|
for dispbuf in dispbufs
|
||||||
processbuf!(buf, win, dispbuf, fftbuf, fftplan)
|
processbuf!(buf, win, dispbuf, fftbuf, fftplan; D = D)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
N = 1024 # size of audio read
|
function waterfall_heatmap(seconds;
|
||||||
N2 = N ÷ 2 + 1 # size of rfft output
|
N = 1024, # size of audio read
|
||||||
D = 200 # number of bins to display
|
D = 200, # number of bins to display
|
||||||
M = 200 # amount of history to keep
|
M = 200, # amount of history to keep
|
||||||
src = PortAudioStream(1, 2)
|
)
|
||||||
buf = Array{Float32}(N) # buffer for reading
|
N2 = N ÷ 2 + 1 # size of rfft output
|
||||||
fftplan = plan_rfft(buf; flags = FFTW.EXHAUSTIVE)
|
PortAudioStream(1, 2) do src
|
||||||
fftbuf = Array{Complex{Float32}}(N2) # destination buf for FFT
|
buf = Array{Float32}(undef, N) # buffer for reading
|
||||||
dispbufs = [zeros(Float32, D, M) for i in 1:5, j in 1:5] # STFT bufs
|
fftplan = plan_rfft(buf; flags = FFTW.EXHAUSTIVE)
|
||||||
win = gaussian(N, 0.125)
|
fftbuf = Array{Complex{Float32}}(undef, N2) # destination buf for FFT
|
||||||
|
dispbufs = [zeros(Float32, D, M) for i in 1:5, j in 1:5] # STFT bufs
|
||||||
|
win = gaussian(N, 0.125)
|
||||||
|
|
||||||
scene = Scene(resolution = (1000, 1000))
|
scene = Scene(resolution = (1000, 1000))
|
||||||
|
|
||||||
#pre-fill the display buffer so we can do a reasonable colormap
|
#pre-fill the display buffer so we can do a reasonable colormap
|
||||||
for _ in 1:M
|
for _ in 1:M
|
||||||
processblock!(src, buf, win, dispbufs, fftbuf, fftplan)
|
processblock!(src, buf, win, dispbufs, fftbuf, fftplan; D = D)
|
||||||
end
|
end
|
||||||
|
|
||||||
heatmaps = map(enumerate(IndexCartesian(), dispbufs)) do ibuf
|
heatmaps = map(zip(CartesianIndices(dispbufs), dispbufs)) do ibuf
|
||||||
i = ibuf[1]
|
i = ibuf[1]
|
||||||
buf = ibuf[2]
|
buf = ibuf[2]
|
||||||
|
|
||||||
# some function of the 2D index and the value
|
# some function of the 2D index and the value
|
||||||
heatmap(buf, offset = (i[2] * size(buf, 2), i[1] * size(buf, 1)))
|
heatmap(buf, offset = (i[2] * size(buf, 2), i[1] * size(buf, 1)))
|
||||||
end
|
end
|
||||||
|
|
||||||
center!(scene)
|
center!(scene)
|
||||||
|
|
||||||
while isopen(scene[:screen])
|
done = false
|
||||||
processblock!(src, buf, dispbufs, fftbuf, fftplan)
|
|
||||||
for (hm, db) in zip(heatmaps, dispbufs)
|
@sync begin
|
||||||
hm[:heatmap] = db
|
@async while !done
|
||||||
|
processblock!(src, buf, win, dispbufs, fftbuf, fftplan)
|
||||||
|
for (hm, db) in zip(heatmaps, dispbufs)
|
||||||
|
hm[:heatmap] = db
|
||||||
|
end
|
||||||
|
render_frame(scene)
|
||||||
|
end
|
||||||
|
sleep(seconds)
|
||||||
|
done = true
|
||||||
|
end
|
||||||
end
|
end
|
||||||
render_frame(scene)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
waterfall_heatmap(5)
|
|
@ -1,43 +1,57 @@
|
||||||
using Makie, GeometryTypes
|
using Makie, GeometryTypes
|
||||||
using PortAudio
|
using PortAudio
|
||||||
|
using FFTW
|
||||||
|
using CairoMakie
|
||||||
|
|
||||||
N = 1024 # size of audio read
|
function waterfall_lines(seconds;
|
||||||
N2 = N ÷ 2 + 1 # size of rfft output
|
N = 1024, # size of audio read
|
||||||
D = 200 # number of bins to display
|
D = 200, # number of bins to display
|
||||||
M = 100 # number of lines to draw
|
M = 100, # number of lines to draw
|
||||||
S = 0.5 # motion speed of lines
|
S = 0.5, # motion speed of lines
|
||||||
src = PortAudioStream(1, 2)
|
)
|
||||||
buf = Array{Float32}(N)
|
PortAudioStream(1, 2) do src
|
||||||
fftbuf = Array{Complex{Float32}}(N2)
|
N2 = N ÷ 2 + 1 # size of rfft output
|
||||||
magbuf = Array{Float32}(N2)
|
buf = Array{Float32}(undef, N)
|
||||||
fftplan = plan_rfft(buf; flags = FFTW.EXHAUSTIVE)
|
fftbuf = Array{Complex{Float32}}(undef, N2)
|
||||||
|
magbuf = Array{Float32}(undef, N2)
|
||||||
|
fftplan = plan_rfft(buf; flags = FFTW.EXHAUSTIVE)
|
||||||
|
|
||||||
scene = Scene(resolution = (500, 500))
|
scene = Scene(resolution = (500, 500))
|
||||||
ax = axis(0:0.1:1, 0:0.1:1, 0:0.1:0.5)
|
ax = axis(0:0.1:1, 0:0.1:1, 0:0.1:0.5)
|
||||||
center!(scene)
|
center!(scene)
|
||||||
|
|
||||||
ls = map(1:M) do _
|
ls = map(1:M) do _
|
||||||
yoffset = to_node(to_value(scene[:time]))
|
yoffset = to_node(to_value(scene[:time]))
|
||||||
offset = lift_node(scene[:time], yoffset) do t, yoff
|
offset = lift_node(scene[:time], yoffset) do t, yoff
|
||||||
Point3f0(0.0f0, (t - yoff) * S, 0.0f0)
|
Point3f0(0.0f0, (t - yoff) * S, 0.0f0)
|
||||||
end
|
end
|
||||||
l = lines(
|
l = lines(
|
||||||
linspace(0, 1, D),
|
linspace(0, 1, D),
|
||||||
0.0f0,
|
0.0f0,
|
||||||
zeros(Float32, D),
|
zeros(Float32, D),
|
||||||
offset = offset,
|
offset = offset,
|
||||||
color = (:black, 0.1),
|
color = (:black, 0.1),
|
||||||
)
|
)
|
||||||
(yoffset, l)
|
(yoffset, l)
|
||||||
end
|
end
|
||||||
|
done = false
|
||||||
while isopen(scene[:screen])
|
@sync begin
|
||||||
for (yoffset, line) in ls
|
@async begin
|
||||||
isopen(scene[:screen]) || break
|
while !done
|
||||||
read!(src, buf)
|
for (yoffset, line) in ls
|
||||||
A_mul_B!(fftbuf, fftplan, buf)
|
isopen(scene[:screen]) || break
|
||||||
@. magbuf = log(clamp(abs(fftbuf), 0.0001, Inf)) / 10 + 0.5
|
read!(src, buf)
|
||||||
line[:z] = magbuf[1:D]
|
A_mul_B!(fftbuf, fftplan, buf)
|
||||||
push!(yoffset, to_value(scene[:time]))
|
@. 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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
waterfall_lines(5)
|
Loading…
Add table
Reference in a new issue