summaryrefslogtreecommitdiff
path: root/src/main.clj
diff options
context:
space:
mode:
authorJake Zerrer <him@jakezerrer.com>2025-10-16 19:43:42 -0400
committerJake Zerrer <him@jakezerrer.com>2025-10-17 19:24:11 -0400
commit4ff62448f9adbb75e79f528ca4528e0faf4399a3 (patch)
treeafcb1bcc5961197b8e4775a215bb445867fdece4 /src/main.clj
parenta36b60a8ee2a293d0c9783cbe59da2a8d9c1b195 (diff)
Improve poly; pass clock as argument
Diffstat (limited to 'src/main.clj')
-rw-r--r--src/main.clj38
1 files changed, 23 insertions, 15 deletions
diff --git a/src/main.clj b/src/main.clj
index 74982ed..57eedad 100644
--- a/src/main.clj
+++ b/src/main.clj
@@ -2,7 +2,8 @@
(:require [missionary.core :as m]
[clojure.set :refer [difference union]]
[portal :refer [>portal-main rec show-portal hide-portal +cap -cap cap]]
- [notation :refer [melody]]))
+ [notation :as notation]
+ [example-song :refer [melody]]))
;; How many times per second are output continuous values sampled and turned
;; into events?
@@ -56,9 +57,10 @@
:tick
(recur)))))
-(def output
+(defn output
"Convert the continuous time >notes-on flow to a series of discrete midi note
on and off events."
+ [composition]
(m/eduction
(comp (remove #(= (select-keys % [:note-on :note-off]) {:note-on #{} :note-off #{}}))
(dedupe))
@@ -74,19 +76,20 @@
;; but not at all if nothing has changed
(m/sample
vector
- melody
+ composition
clock))))
-(def process-midi-toggle-events
+(defn process-midi-toggle-events
"Listen for changes on midi-enabled?
When playback is disabled, send a note-off event for each active note
and then zero out notes-on."
+ [composition]
(m/ap
(let [local-midi-enabled? (atom nil)
local-active (atom #{})
[tag value] (m/amb=
[:midi-enabled? (m/?< >midi-enabled?)]
- [:note-event (m/?< output)])]
+ [:note-event (m/?< (output composition))])]
(case tag
:midi-enabled?
(let [midi-enabled? value
@@ -110,10 +113,11 @@
(defonce engine (atom nil))
-(def set->midi-events
+(defn set->midi-events
"Convert set representation of notes to midi events"
+ [composition]
(m/ap
- (let [{:keys [note-on note-off]} (m/?< process-midi-toggle-events)]
+ (let [{:keys [note-on note-off]} (m/?< (process-midi-toggle-events composition))]
(m/amb=
(loop [notes note-on]
(if (first notes)
@@ -126,17 +130,18 @@
(recur (rest notes)))
(m/amb)))))))
-(def main
- (m/ap (m/amb= (m/?< (rec :root set->midi-events))
+(defn main
+ [composition]
+ (m/ap (m/amb= (m/?< (rec :root (set->midi-events composition)))
(m/?< >portal-main))))
(defn start-engine
"Start playback engine."
- []
+ [composition]
(when (not @engine)
(reset! engine
(do (enable-midi)
- ((m/reduce {} {} main) {} {})))))
+ ((m/reduce {} {} (main composition)) {} {})))))
(defn stop-engine
"Stop playback engine."
@@ -147,14 +152,17 @@
(reset! engine nil)))
(comment
- (start-engine)
-
- (cap)
-
+ (let [[>clock set-clock] (notation/clock)]
+ (def >clock >clock)
+ (def set-clock set-clock))
(+cap :root :notes-set)
+ (start-engine (melody >clock))
+ (set-clock 0)
(show-portal)
+ (cap)
+
(play-notes 1 2 3 4 5)
(stop-notes 4 5)