programextensions/audio/demos/spectrum.xtl
The music visualizer: an Ogg Vorbis (or MP3, WAV) file plays while X_eTaL turns what is playing into a spectrum and the spectrum into 16 spokes in a 3D window -- Rust decodes, plays and draws; the analysis and the picture's geometry are X_eTaL arrays. Run: just demo audio spectrum (Space: pause, j/k: back/on 5 s, q: quit) Another file: change the path below (Ogg Vorbis, MP3 or WAV).
The analysis: 1024 samples under the playhead, a Hann taper, and the
n : Int
loudness at 8 frequencies an octave apart, 60 Hz to 7680 Hz, for each channel: one inner product with cosine and sine tables (1024 by 8)
n ← 1024
hann : Float
hann ← 0.5 − 0.5 × c̲os 6.283185307179586 × (f̲loat r̲ange n) ÷ f̲loat n
ᵘl̲oudness : Float -> Float
ᵘl̲oudness ← { w → v ← w × taper re ← v '+ '× i̲nner c̲os x im ← v '+ '× i̲nner s̲in x m ← ((re × re) + im × im) ^ 0.5 1.3 × m ÷ m + 12.0 }
The picture: 16 spokes, the left channel's 8 on one half of the
k : Float
circle, the right's mirrored on the other; bass nearest the center; loudness lengthens a spoke outward and lifts its tip
k ← f̲loat r̲ange 8
ᵘs̲pokes : Float -> Float
ᵘs̲pokes ← { l → len ← r̲avel l r1 ← r0 + len cs ← c̲os ang sn ← s̲in ang flat ← (r0 × cs) c̲at (16 r̲eshape 0.0) c̲at (r0 × sn) c̲at (r1 × cs) c̲at (0.9 × len) c̲at r1 × sn i ← r̲avel (r̲ange 16) '+ t̲able 16 × (r̲ange 6) − 1 16 6 r̲eshape i s̲elect flat }
c : Int
c ← w ˢᶜc̲amera! 0.0 0.9 3.6 0.12
ᵘr̲ows : a -> a
n by 3 points from their x, y and z columns, laid end to end
ᵘr̲ows ← { flat → n ← f̲loor (t̲ally flat) ÷ 3 i ← r̲avel (r̲ange n) '+ t̲able n × (r̲ange 3) − 1 (n c̲at 3) r̲eshape i s̲elect flat }
g : Float
a faint ring where the spokes stand
g ← 6.283185307179586 × (f̲loat r̲ange 65) ÷ 64.0
ring : Int
ring ← ((f̲loat w c̲at 4) c̲at 0.25 0.27 0.33) ˢᶜp̲olyline! ᵘr̲ows (0.3 × c̲os g) c̲at (65 r̲eshape 0.0) c̲at 0.3 × s̲in g
ᵘd̲raw : Float -> Float
one colored object per band: bass blue, mid green, high orange
ᵘd̲raw ← { l → m ← ᵘs̲pokes l b ← ((f̲loat w c̲at 1) c̲at 0.25 0.55 1.0) ˢᶜs̲egments! 12 3 r̲eshape r̲avel (1 2 3 9 10 11) s̲elect₁ m d ← ((f̲loat w c̲at 2) c̲at 0.3 0.9 0.4) ˢᶜs̲egments! 12 3 r̲eshape r̲avel (4 5 6 12 13 14) s̲elect₁ m h ← ((f̲loat w c̲at 3) c̲at 1.0 0.6 0.2) ˢᶜs̲egments! 8 3 r̲eshape r̲avel (7 8 15 16) s̲elect₁ m l }
The loop: each frame read an event, then the window, then draw; the
ᵘq̲uit : Any a => a -> Float
ᵘq̲uit ← { l → x ← ˢᶜc̲lose! w y ← ᵃᵘc̲lose! a 2 8 r̲eshape -1.0 }
ᵘk̲ey : Char -> Int
ᵘk̲ey ← { e → s ← ᵃᵘs̲tate a (e m̲atch "key Space") × s = 1 ? ᵃᵘp̲ause! a e m̲atch "key Space" ? ᵃᵘp̲lay! a e m̲atch "key j" ? f̲loor a ᵃᵘs̲eek! 0.0 m̲ax (ᵃᵘp̲osition a) − 5.0 e m̲atch "key k" ? f̲loor a ᵃᵘs̲eek! (ᵃᵘp̲osition a) + 5.0 0 }