blob: f93cc3acbbc84c1c222ab2e783fef8f70a2642a6 (
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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
|
(ns scratch
(:require [unheard.midi :as midi]
[unheard.midi.percussion :refer [kick snare hat]]
[unheard.instrument.minilab3 :as minilab3]
[unheard.time-object :refer [phrase timeline]]
[unheard.theory :refer [note read]]
[missionary.core :as m]))
#_(print-all-midi-devices)
(defn triad
[>c >tonic]
(phrase
;; This is a major cord,
;; held 32 32nd notes.
;; The tonic can vary.
(note >c 0 32 >tonic)
(note >c 0 32 (m/latest #(+ % 4) >tonic))
(note >c 0 32 (m/latest #(+ % 7) >tonic))))
(defn drums
[>clock]
(phrase (note >clock 1 1 (m/ap kick))
(note >clock 9 1 (m/ap kick))
(note >clock 17 1 (m/ap kick))
(note >clock 25 1 (m/ap kick))
(note >clock 1 1 (m/ap hat))
(note >clock 5 1 (m/ap hat))
(note >clock 9 1 (m/ap hat))
(note >clock 13 1 (m/ap hat))
(note >clock 17 1 (m/ap hat))
(note >clock 21 1 (m/ap hat))
(note >clock 25 1 (m/ap hat))
(note >clock 29 1 (m/ap hat))
(note >clock 5 1 (m/ap snare))
(note >clock 13 1 (m/ap snare))
(note >clock 21 1 (m/ap snare))
(note >clock 29 1 (m/ap snare))))
(defn song'
[>clock >tonic]
(phrase ((triad >clock >tonic) 0)
((triad >clock (m/latest #(+ % 12) >tonic)) 0)
((drums >clock) 0)))
(defn song
[>clock >tonic]
(apply phrase
(apply concat
(for [i (range 0 50000)] [((song' >clock >tonic) (* 32 i))]))))
;; TODO: Move into /dev
;; Add logging
(defn debug-flow [f] ((m/reduce prn nil (m/ap (m/?< f))) prn prn))
(def run
(midi/<bus minilab3/device-name
(fn [v]
(m/ap (let [controls (midi/controller v minilab3/config)
>clock (get-in controls [:knob 1])
>tonic (get-in controls [:knob 2])
s (song >clock >tonic)
t (timeline s)]
(m/?<
;; BUG:
;; Remove dedupe as part of #2d7f861
(m/eduction
(dedupe)
(m/latest vector >clock (read >clock t)))))))))
#_(def cancel (run {} {}))
#_(cancel)
(comment
;; Manual test of read, without reliance on whole midi setup
(def c (atom 0))
(def >c (m/signal (m/watch c)))
(def t (atom 0))
(def >t (m/signal (m/watch t)))
(def s (song >c >t))
(def cancel ((m/reduce prn #{} (read >c (timeline s))) prn prn))
(cancel)
(reset! c -1)
(reset! c 1)
(reset! c 10000)
(reset! t 1)
(swap! c inc)
(swap! t inc))
|