diff options
| author | Jake Zerrer <him@jakezerrer.com> | 2025-10-15 13:35:07 -0400 |
|---|---|---|
| committer | Jake Zerrer <him@jakezerrer.com> | 2025-10-16 08:54:11 -0400 |
| commit | 3454235122b8208af7a30e6fdd374ebe15e9b777 (patch) | |
| tree | f5e9b4f04e4fde1d303bd554fd81484079fbcaae | |
| parent | aedd0df6c2c61b6ef42d610017f066e3d10233dd (diff) | |
Improve portal window opening / closing
| -rw-r--r-- | src/notation.clj | 66 |
1 files changed, 61 insertions, 5 deletions
diff --git a/src/notation.clj b/src/notation.clj index aff26e3..6ec09f8 100644 --- a/src/notation.clj +++ b/src/notation.clj @@ -1,5 +1,7 @@ (ns notation - "Experimental notation") + "Experimental notation" + (:require [missionary.core :as m] + [clojure.set :refer [union]])) (comment ;; Parallel groups @@ -7,6 +9,7 @@ ;; = should remind you of amb= ;; implicit duration of 1 [= 1 2 3] + ;; Compiles to? ;; Same as above, but with duration 3 ([= 1 2 3] 3) @@ -41,8 +44,7 @@ [= 1 2 3] [= 1 2 3]] - - ;; Note 1, followed by a rest, followed by note 3 +;; Note 1, followed by a rest, followed by note 3 [1 (r) 3] ;; Unlike notes, rests are at most 2-tuples @@ -59,8 +61,7 @@ ;; Middle arguments are variable names (=loop2 dur ([1 2 3] dur)) - - ;; TODO: +;; TODO: ;; - Note literals turn into numbers ;; - Represent keyboard as byte array of shorts ;; - play a note increments, stop a note decrements @@ -71,3 +72,58 @@ ;; - Notion of scenes that change mapping of inputs to vars ;; - 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) + dxfn (case (m/?< pulse) :inc inc :dec dec)] + (println "AT" (swap! c dxfn)) + (if (< 0 @c duration) + (m/amb #{value}) + (m/amb #{}) + ))))) + +(defmacro chord + [& 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))))) + +;; We have something pretty cool going. I think chord is actually correct. +;; Line isn't working quite corectly, though. +;; The idea of note storing its internal state is clever, but isn't behaving +;; quite corectly when you try to sequence two chords back to back. Think through +;; how this will work with pulses. You are close! +;; +(defmacro line + [& notes] + `(m/ap (m/amb ~@(map (fn [note] `(m/?< ~note)) notes)))) + +(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 :dec) +(reset! ctr :inc) |
