summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJake Zerrer <him@jakezerrer.com>2025-11-06 11:17:12 -0500
committerJake Zerrer <him@jakezerrer.com>2025-11-06 12:32:15 -0500
commit576bfd688fc8a65de176d4f1fbf9bf71505953a9 (patch)
tree437c1528646774253f12f640fb4203ff4dbd9548
parentbefc0162943944b88108cce208ef443822def7d2 (diff)
Create first clock-based composition
-rw-r--r--dev/scratch.clj36
-rw-r--r--src/unheard/theory.clj9
2 files changed, 34 insertions, 11 deletions
diff --git a/dev/scratch.clj b/dev/scratch.clj
index 9459c81..ef7241a 100644
--- a/dev/scratch.clj
+++ b/dev/scratch.clj
@@ -1,6 +1,6 @@
(ns scratch
(:require [unheard.midi :as midi]
- [unheard.midi.percussion :refer [kick snare]]
+ [unheard.midi.percussion :refer [kick snare hat]]
[unheard.clock :refer [clock]]
[unheard.theory :refer [note poly]]
[missionary.core :as m]))
@@ -9,19 +9,41 @@
(def midi-keyboard "CoreMIDI4J - Minilab3 MIDI")
-
(def run
(midi/<bus midi-keyboard
(fn [v]
(m/ap
;; 2 is the number of message types, e.g. :key
- (let [[t f] (m/?> 2 (midi/keyboard v))]
- [t (rest (m/?< f))])))))
+ (let [[>c c] (clock)
+ p (poly
+ (note >c 0 1 kick)
+ (note >c 8 1 kick)
+ (note >c 16 1 kick)
+ (note >c 24 1 kick)
+
+ (note >c 0 1 hat)
+ (note >c 4 1 hat)
+ (note >c 8 1 hat)
+ (note >c 12 1 hat)
+ (note >c 16 1 hat)
+ (note >c 20 1 hat)
+ (note >c 24 1 hat)
+ (note >c 28 1 hat)
+
+ (note >c 4 1 snare)
+ (note >c 12 1 snare)
+ (note >c 20 1 snare)
+ (note >c 28 1 snare))]
+ (m/amb=
+ (let [[t f] (m/?> 2 (midi/keyboard v))
+ [ch k v] (rest (m/?< f))]
+ (if (and (= t :control) (= ch 0) (= k 74))
+ (do (reset! c v) (m/amb))
+ (m/amb)))
+ [:n (m/?< (m/eduction (dedupe) p))]
+ [:c (m/?< (m/eduction (dedupe) >c))]))))))
-#_
(def cancel
(run prn prn))
-#_
(cancel)
-
diff --git a/src/unheard/theory.clj b/src/unheard/theory.clj
index 5d5805b..0fbc6d5 100644
--- a/src/unheard/theory.clj
+++ b/src/unheard/theory.clj
@@ -4,12 +4,13 @@
(defn note [clock start duration value]
(m/cp
- (if (m/?< (m/latest #(<= start % (dec (+ start duration))) clock))
- #{value}
- #{})))
+ (let [v (m/?< clock)]
+ (if (<= start v (dec (+ start duration)))
+ #{value}
+ #{}))))
(defn poly [& notes]
- (m/ap
+ (m/cp
(apply union (m/?< (apply m/latest vector notes)))))
;; TODO: Group could actually wrap note, rather than using explicitly