diff options
Diffstat (limited to 'src/notation.clj')
| -rw-r--r-- | src/notation.clj | 77 |
1 files changed, 37 insertions, 40 deletions
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) |
