diff options
| -rw-r--r-- | DEVLOG.md | 378 |
1 files changed, 378 insertions, 0 deletions
@@ -1194,3 +1194,381 @@ A few more observations: 1. parallel composition is closely related to instruments. (Instruments are trees playing in parallel.) 2. It might make sense to pass instrument specifiers down as arguments + +## December 10th, 2025 + +What about tags? + +Consider: + + +```clojure +;; tetris +(p + (tag :melody + (f (l _ (l _ _) _ (l _ _)) + (l _ (l _ _) _ (l _ _)) + (l _ (l r _) _ _) + (l _ _ _ r) + (l (l r _) (l r _) _ (l _ _)) + (l _ (l r _) _ (l _ _)) + (l _ (l _ _) _ _) + (l _ _ _ r))) + (tag :bass + (f (rate 4 (l _ _)) + (rate 4 (l _ _)) + (l (rate 2 (l _ _)) (rate 2 (l _ _))) + (l _ _ _ _ _ _ _ _) + (rate 4 (l _ _)) + (rate 4 (l _ _)) + (l (rate 2 (l _ _)) (rate 2 (l _ _))) + (rate 4 (l _ _))))) +``` + +When compiled, each interval of the above (except the outer p) would be tagged with either :melody or :bass. + + +```clojure +(tag :theme + (p + (tag :melody + (f (l _ (l _ _) _ (l _ _)) + (l _ (l _ _) _ (l _ _)) + (l _ (l r _) _ _) + (l _ _ _ r) + (l (l r _) (l r _) _ (l _ _)) + (l _ (l r _) _ (l _ _)) + (l _ (l _ _) _ _) + (l _ _ _ r))) + (tag :bass + (f (rate 4 (l _ _)) + (rate 4 (l _ _)) + (l (rate 2 (l _ _)) (rate 2 (l _ _))) + (l _ _ _ _ _ _ _ _) + (rate 4 (l _ _)) + (rate 4 (l _ _)) + (l (rate 2 (l _ _)) (rate 2 (l _ _))) + (rate 4 (l _ _)))))) +``` + +Here, every interval would also be tagged with :theme. + +What might we do with tags? +We could turn the output into tuples like this: + + +``` +[0 1 #{:theme :melody} :c4] +[0 1 #{:theme :bass} :d4] +``` + +That information could aid in interpretation at playback time? + + +Note that every slot (that is, every `_`) is a place where a tag +set can be placed. + +Without a tagging context, the tag is just the empty set. + +That is: + +```clojure +(f (l _ (l _ _) _ (l _ _)) + (l _ (l _ _) _ (l _ _)) + (l _ (l r _) _ _) + (l _ _ _ r) + (l (l r _) (l r _) _ (l _ _)) + (l _ (l r _) _ (l _ _)) + (l _ (l _ _) _ _) + (l _ _ _ r)) +``` + +Would result in each slot (that is, each interval) having a +tag set of `#{}`. + +Let's see how tagging would accomplish a few goals. + +1. Play midi notes, alternating between two instrument types. +2. Play two voices, swapping positions. +3. Write a phrase, and then output it both in OSC and MIDI +4. Write a phrase based on intervals, and then map those intervals + to a scale. +5. Same as 4, but move the scale based on a knob. During t1, the + knob swaps between ionian and mixolydian. During t2, the knob + swaps between dorian and locrian. +6. Two different instruments playing the same phrase, one shifted up + an octave + +### No. 1: + +```clojure + +(import [midi-notes :as m]) + +(def melody + (tag + :m/notes + (l :m/c1 :m/c2 :m/c3 :m/c2))) + +(def inst-changes + (tag + :inst + (l :synth-1 :synth-2))) + +(def song + (tag + :song + (p melody inst-changes))) + +[0 1 #{:song :m/notes} :m/c1] +[0 2 #{:song :inst} :synth-1] +[1 2 #{:song :m/notes} :m/c2] +[2 3 #{:song :m/notes} :m/c3] +[2 4 #{:song :inst} :synth-2] +[3 4 #{:song :m/notes} :m/c2] +``` + +### No. 2: + +```clojure +(import [midi-notes :as m]) + +(def voice-1 + (tag + :m/notes + (l :m/a1 :m/a2))) + +(def voice-2 + (tag + :m/notes + (l :m/a2 :m/a1))) + +(def song + (p + (tag :v1 voice-1) + (tag :v2 voice-2))) + +[0 1 #{:v1 :m/notes} :m/a1] +[0 1 #{:v2 :m/notes} :m/a2] +[1 2 #{:v1 :m/notes} :m/a2] +[1 2 #{:v2 :m/notes} :m/a1] + +``` + +### No. 3 + +```clojure +(def melody + (tag + :an/notes + (l :an/a1 :an/a2 :an/a3))) + +[0 1 #{:an/notes} :an/a1] +[1 2 #{:an/notes} :an/a2] +[2 3 #{:an/notes} :an/a3] +``` + +One thing interesting about the above: +:an/a1 could include its own tag. that is, +it could be replaced with: + +```clojure +(def a1 + (tag + :an/notes + (l :an/a1))) +``` + +Then the whole thing could be rewritten: + +```clojure +(def a1 + (tag + :an/notes + (l :an/a1))) + +(def a2 + (tag + :an/notes + (l :an/a2))) + +(def a3 + (tag + :an/notes + (l :an/a3))) + +(def melody + (l a1 a2 a3)) + +[0 1 #{:an/notes} :an/a1] +[1 2 #{:an/notes} :an/a2] +[2 3 #{:an/notes} :an/a3] +``` + +Note that the result is the same. + +### No. 4 + +```clojure +(def d1 + (tag + :scale/degree + (l :sd/d1))) + +(def d2 + (tag + :scale/degree + (l :sd/d2))) + +(def d3 + (tag + :scale/degree + (l :sd/d3))) + +(def ionian + (tag + :mode + (l :ionian))) + +(def mixolydian + (tag + :mode + (l :mixolydian))) + +(def melody + (tag :tune + (p + (l d1 d2 d3) + (l ionian mixolydian)))) + +[0 1 #{:tune :scale/degree} :sd/d1] +[0 1.5 #{:tune :mode} :ionian] +[1 2 #{:tune :scale/degree} :sd/d2] +[1.5 3 #{:tune :mode} :mixolydian] +[2 3 #{:tune :scale/degree} :sd/d3] +``` + +I think this one makes sense. + +### No. 5 + +```clojure +(def d1 + (tag + :scale/degree + (l :sd/d1))) + +(def d2 + (tag + :scale/degree + (l :sd/d2))) + +(def d3 + (tag + :scale/degree + (l :sd/d3))) + +(def ionian + (tag + :mode + (l :ionian))) + +(def mixolydian + (tag + :mode + (l :mixolydian))) + +(def dorian ...) +(def locrian ...) + +(def melody + (tag :tune + (p + (l d1 d2 d3) + (l + ;; x: flow combinator + (x + (m/ap + (if (< 0 (rescale 0 1 (m/?< (cv :k1-knob-1))) 0.5) + ionian + mixolydian))) + (x + (m/ap + (if (< 0 (rescale 0 1 (m/?< (cv :k1-knob-1))) 0.5) + dorian + locrian))))))) + +[0 1 #{:tune :scale/degree} :sd/d1] +[0 1.5 #{:tune :mode} first-flow] +[1 2 #{:tune :scale/degree} :sd/d2] +[1.5 3 #{:tune :mode} second-flow] +[2 3 #{:tune :scale/degree} :sd/d3] +``` + +Hm, we're back to flows in the value position. +This makes me think that we should _always have a flow in value position_. + +```clojure +(def d1 + (tag + :scale/degree + (l (m/ap :sd/d1)))) + +(def ionian + (tag + :mode + (l (m/ap :ionian)))) +``` + + +## No. 6 + +This is a dumb way to accomplish no.6: + +```clojue +(def c3 + (tag + :an/notes + (l :an/c3))) + +(def d3 + (tag + :an/notes + (l :an/d3))) + +(def e3 + (tag + :an/notes + (l :an/e3))) + +(def f3 + (tag + :an/notes + (l :an/f3))) + +(def riff + (l c3 d3 e3 f3)) + +(def song + (p + (tag :inst-1 + riff) + (tag :inst-3 + (paste riff c4 d4 e4 f4)))) +``` + +I don't love this one. + +### No. 7 + +--- + +Next, need to think about interpretation. + +Should tags be a set? That loses hierarchical information. +Is that bad? + +Oh, what about temporally relative structures, such as +1 tone? + +And counterpoint-like relations, like in no. 6? + |
