diff options
| author | Jake Zerrer <him@jakezerrer.com> | 2025-10-16 13:36:16 -0400 |
|---|---|---|
| committer | Jake Zerrer <him@jakezerrer.com> | 2025-10-16 13:54:03 -0400 |
| commit | a36b60a8ee2a293d0c9783cbe59da2a8d9c1b195 (patch) | |
| tree | d3d85aa044a3952aed9ab56c24f0c55935d4cc40 | |
| parent | 9b1b81e5097f05fe879bb67605fa839e2d00bfd1 (diff) | |
Simplify note; create group
| -rw-r--r-- | .nrepl-port | 2 | ||||
| -rw-r--r-- | src/.notation.clj.swp | bin | 0 -> 16384 bytes | |||
| -rw-r--r-- | src/main.clj | 5 | ||||
| -rw-r--r-- | src/notation.clj | 77 |
4 files changed, 41 insertions, 43 deletions
diff --git a/.nrepl-port b/.nrepl-port index 67de041..4e321f3 100644 --- a/.nrepl-port +++ b/.nrepl-port @@ -1 +1 @@ -57858
\ No newline at end of file +65174
\ No newline at end of file diff --git a/src/.notation.clj.swp b/src/.notation.clj.swp Binary files differnew file mode 100644 index 0000000..6bfd6d0 --- /dev/null +++ b/src/.notation.clj.swp diff --git a/src/main.clj b/src/main.clj index d3f7ce0..74982ed 100644 --- a/src/main.clj +++ b/src/main.clj @@ -1,7 +1,8 @@ (ns main (:require [missionary.core :as m] [clojure.set :refer [difference union]] - [portal :refer [>portal-main rec show-portal hide-portal +cap -cap cap]])) + [portal :refer [>portal-main rec show-portal hide-portal +cap -cap cap]] + [notation :refer [melody]])) ;; How many times per second are output continuous values sampled and turned ;; into events? @@ -73,7 +74,7 @@ ;; but not at all if nothing has changed (m/sample vector - >notes-on + melody clock)))) (def process-midi-toggle-events diff --git a/src/notation.clj b/src/notation.clj index a4b9488..7cf4e86 100644 --- a/src/notation.clj +++ b/src/notation.clj @@ -73,50 +73,47 @@ ;; - Loops ) -(def ctr (atom nil)) -(def pulse (m/signal (m/watch ctr))) - -(defn note [value duration] - (m/eduction (take-while #(not= ::done %)) - (m/ap - (m/amb #{value} - (let [c (atom 0)] - (m/?< pulse) - (swap! c inc) - (if (> @c duration) - (m/amb - #{} - ::done) - (m/amb))))))) - -(defmacro chord +(def clock (atom 0)) +(def >clock (m/signal (m/watch clock))) + +(defn note [clock start duration value] + (m/cp + (if (m/?< (m/latest #(<= start % (dec (+ start duration))) clock)) + #{value} + #{}))) + +(defmacro poly [& notes] (let [atoms (repeatedly (count notes) gensym) let-bindings (vec (mapcat (fn [atom] [atom `(atom #{})]) atoms)) reset-forms (map (fn [atom note] `(m/amb (reset! ~atom (m/?< ~note)))) atoms notes) union-form (cons `union (map (fn [atom] `(deref ~atom)) atoms))] - `(m/ap - (m/amb - (let ~let-bindings - (m/amb= ~@reset-forms) - ~union-form))))) - -(defmacro line - [& notes] - `(m/ap (m/amb ~@(map (fn [note] `(m/?< ~note)) notes)))) + `(m/relieve {} + (m/ap + (let ~let-bindings + (m/amb= ~@reset-forms) + ~union-form))))) + +;; TODO: Group could actually wrap note, rather than using explicitly +;; WIll introduce a lot of GC churn, though +(defn group + [clock start end content] + (m/cp + (let [content (m/signal content)] + (if (m/?< (m/latest #(<= start % end) clock)) + (m/?< content) + (m/amb #{}))))) (def melody - (line - (chord (note 1 2) - (note 3 2) - (note 5 2)) - (chord (note 2 2) - (note 4 2) - (note 6 2)))) - -(def cancel - ((m/reduce prn #{} melody) {} {})) - -(cancel) - -(reset! ctr nil) + (m/signal + (poly (note >clock 0 4 1) + (note >clock 0 5 3) + (note >clock 0 3 5)))) + +#_(def cancel + ((m/reduce prn #{} melody) {} {})) + +#_(cancel) +#_(reset! clock 0) +#_(swap! clock inc) +#_(swap! clock dec) |
