|
26 | 26 | ;; A noon score is a set of event maps. That's it. |
27 | 27 | ;; Each event represents a MIDI note with properties like position, duration, velocity, and pitch: |
28 | 28 | ;; |
29 | | -;;```clj |
30 | | -;; noon.events/DEFAULT_EVENT |
31 | | -;; ;; => {:position 0, :duration 1, :channel 0, :track 0, |
32 | | -;; ;; :velocity 80, :pitch {...}, :voice 0, :patch [0 4]} |
33 | | -;;``` |
34 | | -;; |
| 29 | + |
| 30 | +(nclay/editor "noon.events/DEFAULT_EVENT") |
| 31 | + |
35 | 32 | ;; A fresh score contains a single event — middle C: |
36 | | -;; |
37 | | -;;```clj |
38 | | -;; (score) |
39 | | -;; ;; => #{{:position 0, :duration 1, ...}} |
40 | | -;;``` |
| 33 | + |
| 34 | +(nclay/editor "(score)") |
41 | 35 | ;; |
42 | 36 | ;; Everything in noon is a **transformation** — a function from score to score. |
43 | 37 | ;; You build music by composing transformations: |
44 | 38 | ;; |
45 | | -;;```clj |
46 | | -;; (play dur2 (tup s0 s1 s2 s3)) |
47 | | -;;``` |
48 | | -;; |
49 | 39 | ;; This plays an ascending arpeggio at double duration. |
50 | 40 | ;; `dur2` doubles the duration, `tup` splits it into equal parts, |
51 | 41 | ;; and `s0` through `s3` are structural intervals (more on those soon). |
52 | 42 |
|
| 43 | +(nclay/editor "(play dur2 (tup s0 s1 s2 s3))") |
| 44 | + |
53 | 45 | ;; ## Building Blocks |
54 | 46 | ;; |
55 | 47 | ;; Three core functions handle most of the composition: |
56 | 48 | ;; |
57 | 49 | ;; **`lin`** — concatenate transformations in sequence (a melody): |
58 | | -;; |
59 | | -;;```clj |
60 | | -;; (play (lin C0 E0 G0 B0)) |
61 | | -;;``` |
62 | | -;; |
| 50 | + |
| 51 | +(nclay/editor "(play (lin C0 E0 G0 B0))") |
| 52 | + |
63 | 53 | ;; **`par`** — stack transformations simultaneously (a chord): |
64 | | -;; |
65 | | -;;```clj |
66 | | -;; (play (par C0 Eb0 G0)) ; C minor chord |
67 | | -;;``` |
68 | | -;; |
| 54 | + |
| 55 | +(nclay/editor "(play (par C0 Eb0 G0))") |
| 56 | + |
69 | 57 | ;; **`tup`** — like `lin`, but fitted to the current duration (a tuplet): |
70 | | -;; |
71 | | -;;```clj |
72 | | -;; (play (tup c0 c3 c7 c10)) ; four notes in the space of one |
73 | | -;;``` |
74 | | -;; |
| 58 | + |
| 59 | +(nclay/editor "(play (tup c0 c3 c7 c10))") |
| 60 | + |
75 | 61 | ;; These compose freely. A chord progression with arpeggios: |
76 | | -;; |
77 | | -;;```clj |
78 | | -;; (play (lin I IV V I) |
79 | | -;; (each (tup s0 s1 s2))) |
80 | | -;;``` |
81 | | -;; |
| 62 | + |
| 63 | +(nclay/editor "(play (lin I IV V I) (each (tup s0 s1 s2)))") |
| 64 | + |
82 | 65 | ;; And transformations can be chained using vectors: |
83 | | -;; |
84 | | -;;```clj |
85 | | -;; (play [dur:2 (lin C0 E0 G0)]) |
86 | | -;;``` |
| 66 | + |
| 67 | +(nclay/editor "(play [dur:2 (lin C0 E0 G0)])") |
87 | 68 | ;; |
88 | 69 | ;; A few more useful combinators: |
89 | 70 | ;; |
|
92 | 73 | ;; - `each` — apply a transformation to every event individually |
93 | 74 | ;; - `chans` — like `par` but on separate MIDI channels (for different instruments) |
94 | 75 | ;; |
95 | | -;;```clj |
96 | | -;; (play |
97 | | -;; (chans |
98 | | -;; [(patch :ocarina) (tup s0 s1 s2 s3) (rep 4 s1)] |
99 | | -;; [(patch :vibraphone) vel3 (par s0 s1 s2)] |
100 | | -;; [(patch :acoustic-bass) o1-]) |
101 | | -;; (dup 4)) |
102 | | -;;``` |
| 76 | +(nclay/editor "(play |
| 77 | + (chans |
| 78 | + [(patch :ocarina) (tup s0 s1 s2 s3) (rep 4 s1)] |
| 79 | + [(patch :vibraphone) vel3 (par s0 s1 s2)] |
| 80 | + [(patch :acoustic-bass) o1-]) |
| 81 | + (dup 4))") |
103 | 82 |
|
104 | 83 | ;; ## How Musicians Think About Pitch |
105 | 84 | ;; |
|
142 | 121 | ;; |
143 | 122 | ;; Each event in a noon score carries this full context under its `:pitch` key: |
144 | 123 | ;; |
145 | | -;;```clj |
146 | | -;; (:pitch noon.events/DEFAULT_EVENT) |
147 | | -;; ;; => {:scale [0 2 4 5 7 9 11] ; C major |
148 | | -;; ;; :structure [0 2 4] ; triad |
149 | | -;; ;; :origin {:d 35, :c 60} ; middle C |
150 | | -;; ;; :position {:t 0, :s 0, :d 0, :c 0}} |
151 | | -;;``` |
| 124 | + |
| 125 | +(nclay/editor "(:pitch noon.events/DEFAULT_EVENT)") |
152 | 126 | ;; |
153 | 127 | ;; The `:position` map holds an offset at each layer. |
154 | 128 | ;; This is where the note actually *is* within the harmonic context. |
|
158 | 132 | ;; Each layer has a corresponding **step** operation. |
159 | 133 | ;; A step moves you to the next position *on that layer*: |
160 | 134 | ;; |
161 | | -;;```clj |
162 | | -;; (play (tup c0 c1 c2 c3 c4 c5 c6)) ; chromatic: semitone by semitone |
163 | | -;; (play (tup d0 d1 d2 d3 d4 d5 d6)) ; diatonic: scale degree by degree |
164 | | -;; (play (tup s0 s1 s2 s3)) ; structural: chord tone by chord tone |
165 | | -;; (play (tup t0 t1 t2)) ; tonic: octave by octave |
166 | | -;;``` |
| 135 | + |
167 | 136 |
|
168 | 137 | ;; *The four step types — chromatic, diatonic, structural, and tonic — each walking up from C4. |
169 | 138 | ;; Note how the same ascending pattern selects different notes depending on the layer. |
|
190 | 159 | ;; Here's the key insight: **steps are always relative to the current harmonic context**. |
191 | 160 | ;; When you change the scale or structure, the same step operations produce different notes: |
192 | 161 | ;; |
193 | | -;;```clj |
194 | | -;; ;; Major scale |
195 | | -;; (play dur:4 (lin d0 d1 d2 d3 d4 d5 d6 d7)) |
196 | | -;; |
197 | | -;; ;; Dorian scale — same code, different result |
198 | | -;; (play dur:4 (scale :dorian) (lin d0 d1 d2 d3 d4 d5 d6 d7)) |
199 | | -;; |
200 | | -;; ;; Hungarian scale |
201 | | -;; (play dur:4 (scale :hungarian) (lin d0 d1 d2 d3 d4 d5 d6 d7)) |
202 | | -;;``` |
| 162 | + |
203 | 163 |
|
204 | 164 | ;; *Same diatonic steps, three different scales. The code is identical — only the scale context changes. |
205 | 165 | ;; Notice how the intervals between notes shift while the structure remains.* |
|
215 | 175 |
|
216 | 176 | ;; The same goes for structural steps: |
217 | 177 | ;; |
218 | | -;;```clj |
219 | | -;; ;; Triad arpeggio |
220 | | -;; (play (tup s0 s1 s2 s3)) |
221 | | -;; |
222 | | -;; ;; Tetrad arpeggio — same code, richer chord |
223 | | -;; (play (structure :tetrad) (tup s0 s1 s2 s3)) |
224 | | -;;``` |
| 178 | + |
225 | 179 |
|
226 | 180 | ;; *Triad vs tetrad: the same structural steps produce C-E-G-C with a triad structure, |
227 | 181 | ;; but C-E-G-B when the structure is set to tetrad — the seventh appears automatically.* |
|
237 | 191 | ;; Several functions let you reshape the harmonic context: |
238 | 192 | ;; |
239 | 193 | ;; **`scale`** — change the scale: |
240 | | -;; |
241 | | -;;```clj |
242 | | -;; (play (scale :melodic-minor) (rup 8 d1)) |
243 | | -;;``` |
244 | | -;; |
| 194 | + |
| 195 | +(nclay/editor "(play (scale :melodic-minor) (rup 8 d1))") |
| 196 | + |
245 | 197 | ;; **`structure`** — change the chord structure: |
246 | | -;; |
247 | | -;;```clj |
248 | | -;; (play (structure :tetrad) (tup s0 s1 s2 s3)) |
249 | | -;;``` |
250 | | -;; |
| 198 | + |
| 199 | +(nclay/editor "(play (structure :tetrad) (tup s0 s1 s2 s3))") |
| 200 | + |
251 | 201 | ;; **`root`** — change the tonal center: |
252 | | -;; |
253 | | -;;```clj |
254 | | -;; (play (root :Eb) (tup s0 s1 s2)) |
255 | | -;;``` |
256 | | -;; |
| 202 | + |
| 203 | +(nclay/editor "(play (root :Eb) (tup s0 s1 s2))") |
| 204 | + |
257 | 205 | ;; **`degree`** — move to a scale degree (mode change): |
258 | | -;; |
259 | | -;;```clj |
260 | | -;; (play (lin I IV V I) (each (tup s0 s1 s2))) |
261 | | -;;``` |
| 206 | + |
| 207 | +(nclay/editor "(play (lin I IV V I) (each (tup s0 s1 s2)))") |
262 | 208 |
|
263 | 209 | ;; *A I-IV-V-I chord progression, each chord arpeggiated. |
264 | 210 | ;; The same arpeggio pattern adapts to each degree. |
|
275 | 221 | ;; The real power emerges when you mix layers. |
276 | 222 | ;; Since each event carries the full context, you can navigate between layers freely: |
277 | 223 | ;; |
278 | | -;;```clj |
279 | | -;; ;; Structural arpeggio with diatonic passing tones |
280 | | -;; (play dur:2 |
281 | | -;; (tup s0 s1 s2 s3) |
282 | | -;; (each (tup d1 d1- d0))) |
283 | | -;;``` |
| 224 | + |
284 | 225 |
|
285 | 226 | ;; *Mixing layers: structural chord tones decorated with diatonic neighbor notes. |
286 | 227 | ;; The structural steps define the skeleton; the diatonic steps fill in the passing tones.* |
|
295 | 236 | ;; |
296 | 237 | ;; An arpeggiated chord progression in harmonic minor: |
297 | 238 | ;; |
298 | | -;;```clj |
299 | | -;; (play (scale :harmonic-minor) |
300 | | -;; (lin I IV VII I) |
301 | | -;; (each (tup s0 s1 s2))) |
302 | | -;;``` |
| 239 | + |
303 | 240 |
|
304 | 241 | ;; *Harmonic minor progression: I-IV-VII-I with arpeggiated chords. |
305 | 242 | ;; Notice the characteristic G♯ (raised 7th degree) appearing in the VII chord.* |
|
0 commit comments