summaryrefslogtreecommitdiff
path: root/src/unheard/theory.clj
blob: 6ceff3eff78fcc24701def92fd4b8a5c31f0ed0b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
(ns unheard.theory
  (:require [missionary.core :as m]
            [unheard.time-object :refer [time-object]]
            [clojure.set :refer [union]]))

(defn note
  [>clock start duration >value]
  (time-object start
               duration
               [(gensym)
                (m/cp (let [[c v] (m/?< (m/latest vector >clock >value))]
                        (if (<= start c (dec (+ start duration))) #{v} #{})))]))

;; Reducing function that returns diffs :add v :remove v
;; Reducing function that unfolds to values

(comment
  (require '[unheard.time-object :refer [lift phrase timeline point-query]])
  (def c (atom 0))
  (def >c (m/signal (m/watch c)))
  (def v (atom 0))
  (def >v (m/watch v))
  (def n (note >c 4 8 >v))
  (def song (phrase (lift n)))
  (def t (timeline (song 0)))
  (def r (point-query t >c))
  (def r
    (m/ap (try (m/?<
                 ;; TODO: Simplify
                 (apply m/latest
                   vector
                   (point-query t >c)
                   (vals (m/?< (m/eduction (map #(into {} %))
                                           (point-query t >c))))))
               (catch missionary.Cancelled _ (m/amb)))))
  (def cancel ((m/reduce prn nil r) prn prn))
  (cancel)
  (swap! c dec)
  (swap! c inc)
  (swap! v inc)
  (swap! v dec))

(defn poly
  [& notes]
  (m/signal (m/cp (apply union (m/?< (apply m/latest vector notes))))))

;; 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 #{})))))

;; TODO:
;; - Note literals turn into numbers
;; - Represent keyboard as byte array of shorts
;; - play a note increments, stop a note decrements
;; - Multiple instruments
;; - Mapping inputs to vars
;; - Inputs get declared at the top of a track
;; - Devices get mapped to declared inputs
;; - Notion of scenes that change mapping of inputs to vars
;; - Loops