1+ ; ; # Nowway Clojure Meetup Dec 2025: Modeling a Violin Tremolo
2+
13(ns clojure-norway.meetup-2025-12.violin
24 (:require [scicloj.kindly.v4.kind :as kind]
35 [clojure.java.io :as io]
1113 [tech.v3.datatype :as dtype]
1214 [clojure.math :as math]))
1315
14- ; ; ## Exploring a violin Tremolo
16+
17+ ^:kindly/hide-code
18+ (kind/hiccup
19+ [:style
20+ " .clay-dataset {
21+ max-height:400px;
22+ overflow-y: auto;
23+ }
24+ .clay-table {
25+ max-height:400px;
26+ overflow-y: auto;
27+ }
28+ " ])
1529
1630; ; ## Relevant community projects
1731
2135
2236; ; [Clojure Jam 2026](https://scicloj.github.io/clojure-jam-2026/)
2337
24- ; ; ## Data source
38+ ; ; ## Libraries
39+
40+ ; ; - [Noj](https://scicloj.github.io/noj/) - data science toolkig
41+ ; ; - [Underlying libraries](https://scicloj.github.io/noj/noj_book.underlying_libraries.html)
42+ ; ; - [JDSP](https://jdsp.dev/) - signal processing in the JVM
43+
44+ ; ; ## Our data: a violin tremolo
2545; ;
2646; ; [violin tremolo G#2.aif](https://freesound.org/people/ldk1609/sounds/56085/)
2747; ; by [ldk1609](https://freesound.org/people/ldk1609/)
@@ -117,7 +137,9 @@ wav-format
117137 (double sample-rate))
118138 :sample wav-samples}))
119139
120- wav-ds
140+ (tc/head wav-ds)
141+
142+ ; ; ## Visualizing the vibrations along time
121143
122144(-> wav-ds
123145 (tc/select-rows #(<= 0 (:time %) 1 ))
@@ -135,6 +157,8 @@ wav-ds
135157{:samples wav-samples
136158 :sample-rate sample-rate}
137159
160+ ; ; ## Oversimplifying by repeatition
161+
138162^kind/audio
139163{:samples (->> (-> wav-ds
140164 (tc/select-rows #(<= 1 (:time %) 1.06 ))
@@ -143,7 +167,23 @@ wav-ds
143167 (apply concat))
144168 :sample-rate sample-rate}
145169
146- ; ; ## Computing the Discrete Fouriee Transform the data
170+ ; ; ## Modelling a simple wave
171+
172+ (def cosine-wave
173+ (-> {:time (-> (range 0
174+ 0.1
175+ (/ 1.0 sample-rate)))}
176+ tc/dataset
177+ (tc/add-column :value #(-> %
178+ :time
179+ (dfn/* (* 2 math/PI 50 ))
180+ (dfn/+ (* 0.25 math/PI))
181+ dfn/cos))))
182+
183+ (-> cosine-wave
184+ (plotly/layer-line {:=x :time
185+ :=y :value }))
186+
147187
148188(import 'com.github.psambit9791.jdsp.transform.DiscreteFourier)
149189
@@ -170,23 +210,6 @@ wav-ds
170210 :phase phase})
171211 (tc/add-column :power #(tcc/sq (:amplitude %)))))))
172212
173-
174-
175- (def cosine-wave
176- (-> {:time (-> (range 0
177- 0.1
178- (/ 1.0 sample-rate)))}
179- tc/dataset
180- (tc/add-column :value #(-> %
181- :time
182- (dfn/* (* 2 math/PI 50 ))
183- (dfn/+ (* 0.25 math/PI))
184- dfn/cos))))
185-
186- (-> cosine-wave
187- (plotly/layer-line {:=x :time
188- :=y :value }))
189-
190213(def cosine-wave-dft-ds
191214 (-> cosine-wave
192215 :value
@@ -314,28 +337,19 @@ wav-ds
314337(-> (some-part 1 1.05 )
315338 audio)
316339
317- (-> some-dft-ds
318- (dft-ds->peaks-ds {:n-peaks 10 })
319- (peaks-ds->components-ds {:duration 1 })
320- components-ds->combined-ds
321- :combined
322- audio)
323-
324- (-> (some-part 1 2 )
325- values->dft-ds
326- (dft-ds->peaks-ds {:n-peaks 30 })
327- (peaks-ds->components-ds {:duration 1 })
328- components-ds->combined-ds
329- :combined
330- audio)
331-
340+ (for [n-peaks (range 1 7 )]
341+ (-> some-dft-ds
342+ (dft-ds->peaks-ds {:n-peaks n-peaks})
343+ (peaks-ds->components-ds {:duration 0.2 })
344+ components-ds->combined-ds
345+ :combined
346+ audio))
332347
333348; ; ## Short Time Fourier Transform
334349
335350(import 'com.github.psambit9791.jdsp.windows.Hanning)
336351
337352
338-
339353(def stft
340354 (let [window-size 0.05 ; seconds
341355 window-samples (* sample-rate window-size)
@@ -394,6 +408,13 @@ wav-ds
394408 (tc/add-column :power #(tcc/sq (:amplitude %))))))))))))
395409
396410
411+ (kind/hiccup
412+ [:div {:style {:max-height " 400px"
413+ :overflow-y " auto" }}
414+ stft])
415+
416+ ; ; ### Spectrogram
417+
397418(require '[tech.v3.dataset.tensor :as ds-tensor])
398419
399420(def spectrogram
@@ -429,8 +450,7 @@ wav-ds
429450 bufimg/tensor->image)
430451
431452
432- ; ; ## Playing the spectrogram
433-
453+ ; ; ## Playing the STFT
434454
435455(-> stft
436456 (->> (map (fn [dft]
0 commit comments