Commit 5910aacc by PLN (Algolia)

feat(surface): REMAP PHASE 2 — the button rows column-align, and the board is now one sentence

96 substitutions across all 13 OPAL tracks. "Column N is orbit N" is now true for
the WHOLE surface, not just the knobs:

    BT 41-44/57-60   d1..d8 gate
    BL 73-76/89-92   gMute1/2/3 | d4..d8 gate2
    A  13-20         d9..d12 level | d9..d12 fx
    B  29-36         d1..d8 fx
    C  49-56         gF1/2/3 | d4..d8 fx2
    D  77-84         d1..d8 level

    surface-columns:  23/84 aligned, 127 renumbers  ->  82/82 aligned, 0 renumbers

PLN drove the key decision. My first attempt left over-budget controls in place and
reached only 11/13 tracks, which he rejected outright: "we need finish the job. why
half moved? cant you move all-but then comment out with fixme?" He was right on both
counts, and leaving them was not the conservative choice — it was a bug generator.

THE CASCADE, AND WHY COMMENTING OUT DISSOLVES IT
The board has 8 BT + 5 BL = 13 per-orbit buttons for 8 orbits, because BL1-3 are the
family mutes. So d1..d3 get exactly ONE button each, and bombe_dj's kick — a 3-state
gesture on TWO buttons —

    $ midiOn  ("^41"-"^42") (<| "k(3,8) ~")
    $ midiOff ("^42"+"^41") (<| "k*<1!7 2> ~ ...")
    $ midiOn  "^42"         (<| "k k k*<1!8 2!8> ...")

is over budget by design. Left in place, d1's ^42 blocked d2, which blocked d3, then
d4, then d5: 4/8 aligned. Commented out, the control is free and the row aligns.
Nothing is lost — the original sits one line above under two dashes, restorable the
moment gSel (#54) can fold three states onto d1's own control.

THREE BUGS THE GATES CAUGHT BEFORE THIS SHIPPED — all in my own tool

1. LEAVING OVERFLOW IN PLACE IS A CROSS-ORBIT TRIGGER. Once ^42 becomes d2's button,
   any surviving d1 reference means pressing d2's gate also fires d1's kick variant.
   Measured, not theorised: perfect.tidal ended up with ^42 driving BOTH d1 and d2.
   A new gate now asserts no button drives two orbits — 0 across the setlist.

2. THE CLASH GUARD HAD A HOLE. A clashed control also stays put, so it too becomes an
   obstacle — but I computed clashes in the same sweep that consumed them. bombe_dj:
   d2 was left on ^43 by a clash while d3 was still planned to move ONTO ^43. Fixed by
   iterating pass 2 to a fixed point, growing the sticky set until a sweep finds
   nothing new, with a non-convergence bail-out.

3. COMMENTING A LINE ORPHANS ITS CLOSING PARENS. A chain step spans several lines, so
   commenting only the line carrying the CC left the body live and the `)` dangling —
   `perfect: parse error on input ')'`, and desire went from building to not building.
   The unit is a `$`-chain SEGMENT; it is expanded to one, then paren-balance-checked,
   and the tool refuses rather than emit broken Haskell.

4. MULTI-BLOCK ORBITS WERE SILENTLY DROPPED. perfect.tidal declares `d1` SIX times as
   section alternates. Keying the plan by orbit number meant each later block
   overwrote the earlier one's plan, so the first block's ^42 -> ^41 vanished — the
   real reason gate 1 kept failing after I "fixed" it. An orbit's control set is the
   UNION across its blocks. Recovered 3 more moves (perfect 7->8, electric_hammer 3->5).

VALIDATION
  no button drives 2+ orbits    0 tracks (was 1)
  silent-eval --seeded          OK, every declared orbit emits events
  build failures                4, identical to before — no new breakage (#93)
  surface-columns               82/82 aligned, 0 renumbers
  pvlint                        0 errors, 9 pre-existing warnings (#70, dup d5)
  pytest                        471 passed
  check-boot / -blocks          OK

9 overflow controls are now commented with a FIXME naming the orbit, its slots, and
the restore path. That is the honest total: the surface is fully aligned, and every
control that could not fit says so in the file rather than in someone's memory.
parent 1764d3e1
......@@ -2,8 +2,8 @@ do
-- resetCycles
setcps (127/60/4)
d1 $ gF1 $ gMute2 -- KICK: Sub thud, 4otf with flourish (NTO: deepens over time)
$ midiOn "^42" (<| "k k k <k k*2 k [~ k]>") -- ON: 4otf + flourish variations
$ midiOff "^42" (<| "k ~ ~ <~!3 k>") -- OFF: sparse intro
$ midiOn "^41" (<| "k k k <k k*2 k [~ k]>") -- ON: 4otf + flourish variations
$ midiOff "^41" (<| "k ~ ~ <~!3 k>") -- OFF: sparse intro
$ sometimesBy "^29" ( -- ^29: ghost doubles (pre-drop energy)
superimpose (("0.07" <~) . (|* gain 0.7))
)
......@@ -11,8 +11,8 @@ d1 $ gF1 $ gMute2 -- KICK: Sub thud, 4otf with flourish (NTO: deepens over time)
# gain 1.5
d2 $ gF1 $ gM1 -- CLAP: Dry quiet snap, contretemps (enters late)
-- NTO: peak=0.13 (QUIET!), att=10ms, dom=1292Hz, 0% sub, beats 1&3
$ midiOn "^43" (<| "cp ~ cp ~") -- ON: contretemps (NTO climax)
$ midiOff "^43" (<| "~ cp ~ <~ cp*<1 2>>") -- OFF: backbeat (our touch)
$ midiOn "^42" (<| "cp ~ cp ~") -- ON: contretemps (NTO climax)
$ midiOff "^42" (<| "~ cp ~ <~ cp*<1 2>>") -- OFF: backbeat (our touch)
$ sometimesBy "^30" ( -- ^30: flam probability
superimpose (("e" <~) . (|* gain 0.6))
)
......@@ -23,11 +23,12 @@ d2 $ gF1 $ gM1 -- CLAP: Dry quiet snap, contretemps (enters late)
# pan 0.55
d3 $ gF1 $ gM1 -- OH/CY: Subtle offbeat hats, ^44 morphs to cymbal shimmer
-- NTO: OH on upbeats, centroid brightens 4000→8400Hz. Breakdown = quiet cymbal.
$ midiOn "^76" (stut 3 0.6 "s") -- push: rolls
$ midiOn "^44" ( -- ON: cymbal shimmer (quiet, bright, breakdown character)
(|* gain 0.94) . (# legato 0.2) . (# "h2ogmcy:1") . (# hpf 5000)
)
-- $ midiOff "^44" (mask "t(3,8)") -- OFF: sparse euclidean (subtle)
$ midiOn "^43" (stut 3 0.6 "s") -- push: rolls
-- FIXME(#94) d3 drives more controls than the grid gives it (BT3 only — BL1-3 are the family mutes). ^44 now belongs to another orbit, so the line(s) below are COMMENTED OUT rather than left firing across columns. Nothing is lost — restore by removing the dashes once gSel folds this onto d3's own control.
-- $ midiOn "^44" ( -- ON: cymbal shimmer (quiet, bright, breakdown character)
-- (|* gain 0.94) . (# legato 0.2) . (# "h2ogmcy:1") . (# hpf 5000)
-- )
-- -- $ midiOff "^44" (mask "t(3,8)") -- OFF: sparse euclidean (subtle)
$ sometimesBy "^31" (ply "<2!3 [2 4]>") -- ^32: roll probability
$ "~ h ~ h ~ h ~ <h!3 h*2>" -- offbeat pattern with flourish
# "h2ogmhh"
......@@ -53,14 +54,14 @@ d4 $ gF2 $ gM3 -- BASS (the FIXME): D minor, grounded in measured key (corr=0.90
# lpf (range 300 1800 "^32") # resonance 0.2
# gain 1.15
d6 $ gF1 $ gM2 -- ACID ARP: D minor, 4/16 square rises, ^59-driven
$ midiOn "^59" (arp "<up updown pinkyup speedupdown>")
$ midiOn "^58" (arp "<up updown pinkyup speedupdown>")
$ off 0.125 ((|+ note 12) . (|* gain 0.6))
$ note (scale "aeolian" (run "<4 16>") + "<0 3 5 3>" + 2) -- +2 = D root
# s "superzow" # voice 0.05
# lpf (range 500 5000 "^59") # resonance 0.35
# lpf (range 500 5000 "^58") # resonance 0.35
# gain 0.8
d5 $ gF3 $ gM3 --
$ midiOn "^90" (ply "<2 4 [<4!3 16> <8 16>]>")
$ midiOn "^57" (ply "<2 4 [<4!3 16> <8 16>]>")
$ slice 4 "<0 1 2 3>"
$ "desire" # n "<1!4 2!4 3!7 4 3!6 2 2 3!7 4>"
# cut 5 # lpf 4000
......@@ -81,7 +82,7 @@ d9 $ gF2 $ gM3 -- Announcing SYNTH
# gain 1.9
# room 0.4 # sz 0.7 # dry 1.4
d7 $ gF3 $ gM3 -- Voices
$ midiOn "^91" (ply "2 <2!3 <4 8>>")
$ midiOn "^59" (ply "2 <2!3 <4 8>>")
$ fix ((6/8) ~>) (n 6)
$ fix ((1/8) ~>) (n 9)
$ fix ((5/8) <~) (n "[11,12]")
......@@ -91,23 +92,23 @@ d7 $ gF3 $ gM3 -- Voices
-- lost — if the linked swell was the point, gSel or a shared knob restores it.
$ midiOn "^35" (>| n "<11 12>") -- NANANA | B7 = d7's primary effect
$ midiOn "^55" (>| n "<10 ~>") -- FREE FROM DESIRE
$ midiOn ("^59" - "^55") ( -- Refrain
$ midiOn ("^91" - "^55") ( -- Refrain
(>| n "<10!4 11!4>")
) -- Refrain
$ midiOff "^59" ( -- Couplet
$ midiOff "^91" ( -- Couplet
(>| n "<6 ~ 6 ~ 7 ~ 7 ~ 8 ~ 8 8 9 9 9 9>"))
$ "desire"
# cut 7
d8 $ gF1 $ gM1
$ loopAt 2
$ midiOn "^92" ( -- Bouton Nassim <3
$ midiOn "^60" ( -- Bouton Nassim <3
loopAt 0.5 . (# "breaks165")
-- . (# octer 0.4) . ( octersubsub 4)
. (# lpf 2500)
. (# room 0)
. (|* gain 1.2)
)
$ midiOff "^60" (mask "f(8,16)" . chop 16)
$ midiOff "^92" (mask "f(8,16)" . chop 16)
$ midiOn "^36" (# "jungle_breaks:7")
$ midiOn "^56" (# "jungle_breaks:37")
$ chop 16 $ "jungle_breaks:101"
......
......@@ -7,26 +7,26 @@ setcps (160/60/4)
d1 $ gF1 $ gMute2
-- $ midiOff "^42" (<| "<k [~!7 k*<1 2>]>")
$ fix (# bandf 300) "clubkick"
$ midiOff "^42" (<| "k . ~ k*<1 2> ~ <~ k k <~ k*4>>")
$ midiOn "^42" (<| "k k . k <k [~ k] k k*2>")
$ midiOff "^41" (<| "k . ~ k*<1 2> ~ <~ k k <~ k*4>>")
$ midiOn "^41" (<| "k k . k <k [~ k] k k*2>")
$ "[jazz,clubkick]"
# cut 1
# gain 1.5
d2 $ gF1 $ gM1
$ midiOn "^43" (<| "~ s ~ [s*<1 2> <~!7 [~ s]>]")
$ midiOff "^43" (<| "~ s")
$ midiOn "^42" (<| "~ s ~ [s*<1 2> <~!7 [~ s]>]")
$ midiOff "^42" (<| "~ s")
$ "snare:45"
# "jazz:4" # gain 1.3
d3 $ gF1 $ gM1
$ midiOff "^44" (
$ midiOff "^43" (
(<| "h(3,8)") . (# "jbk_kick:43")
. (# room 0.2) . (# sz 0.4)
)
$ midiOn "^44" (<| "~ h ~ h ~ h*<1!3 2> ~ h*<1 [1|2]>")
$ midiOn "^43" (<| "~ h ~ h ~ h*<1!3 2> ~ h*<1 [1|2]>")
$ "h2ogmhh" # n "<0!4 1!3 2>"
# gain (0.9 * (range 0.9 1.2 perlin))
d4 $ gF2 $ gM3
$ midiOn "^89" (ply 4)
$ midiOn "^44" (ply 4)
$ slow 2 $ note ("<[e3@7 f3]!4 [b2@7 c2]!4>")
# "moog:2"
# cut 4
......@@ -34,13 +34,13 @@ d4 $ gF2 $ gM3
# octerbus 42 (range 0 2.5 "^52")
# gain 1.1
d5 $ gF2 $ gM3 --
$ midiOn "^90" ((# n ("<0>" + "<0 0 0 [0 0 1 0] 3 5 4 5>"))
$ midiOn "^57" ((# n ("<0>" + "<0 0 0 [0 0 1 0] 3 5 4 5>"))
. (ply 4) . (slice 4 2))
$ midiOn "^58" (
$ midiOn "^89" (
slice 4 "0 1 2 3"
. (>| n "<2 2 2 2 4 4 4 4>")
)
$ midiOff "^58" (slow 2)
$ midiOff "^89" (slow 2)
$ whenmod 16 12 (# n 8)
$ "oil"
# n (
......@@ -51,7 +51,7 @@ d5 $ gF2 $ gM3 --
# gain 1.4
# squizbus 51 (range 0 2.5 "^33")
d7 $ gF3 $ gM3 -- FIXME ACID WEIRD NOT GOOD
$ midiOn "^91" (ply 4)
$ midiOn "^59" (ply 4)
-- $ slow 2
$ note (
"<e3!4 b2!4>"
......@@ -63,7 +63,8 @@ d7 $ gF3 $ gM3 -- FIXME ACID WEIRD NOT GOOD
# octerbus 42 (range 0 2.5 "^55")
# gain 1.1
-- FIXME(#54) d7 3rd+ effect: the grid gives d7 B7 + C7. Fold ^19 in via gSel rather than borrowing a column.
# width (range 0 5 "^19")
-- FIXME(#54) d7 drives more controls than the grid gives it (B7 + C7). ^19 now belongs to another orbit, so the line(s) below are COMMENTED OUT rather than left firing across columns. Nothing is lost — restore by removing the dashes once gSel folds this onto d7's own control.
-- # width (range 0 5 "^19")
d8 $ gF1 $ gM1
$ midiOn ("^60" - "^92") (mask "f(4,8)")
$ midiOn ("^36" - "^92") ((loopAt 2) . (# hpf 1500) . (# "jungle_breaks:45")) -- ORL RPZ
......
......@@ -2,21 +2,21 @@ do
-- resetCycles
setcps (124/60/4)
d1 $ gF1 $ gM2
$ midiOn "^42" (<| "k k k <k [<~!3 k> k]>")
$ midiOff "^42" (<| "k . <[~ k] k(<3 5>,8)>")
$ midiOn "^41" (<| "k k k <k [<~!3 k> k]>")
$ midiOff "^41" (<| "k . <[~ k] k(<3 5>,8)>")
$ "[techno:0,808bd:2,909,kick:4]"
-- $ "kick:5"
# gain 1.7
# lpf 400
d2 $ gF1 $ gM1 -- Clap Technocratique
$ midiOn "^43" (mask "[t <f t!3>] [t <f t>]" . fast 2)
$ midiOn "^42" (mask "[t <f t!3>] [t <f t>]" . fast 2)
$ "~ s ~ [s*<1 2> <~ s*<2 [4 2]>>]"
# "vec1_claps" # n 10
# gain 1.3
# lpf 2000
d3 $ gF1 $ gM1
$ midiOn "^44" (<| "[~ h*<1!3 <1 2 [4 2] 1?>>]*4" )
$ midiOff "^44" (<| "h(3,8) h([3 1 3],8)")
$ midiOn "^43" (<| "[~ h*<1!3 <1 2 [4 2] 1?>>]*4" )
$ midiOff "^43" (<| "h(3,8) h([3 1 3],8)")
$ "h2ogmhh"
# gain 1.4
# room 0.3
......@@ -24,9 +24,9 @@ d3 $ gF1 $ gM1
# legato (range 0.05 2 "^31")
# sz 0.4
d4 $ gF2 $ gM3
$ midiOn "^89" (struct "t . t(<1 3 5>,8)")
$ midiOn "^57" (struct "t . t(<1 3 5>,8)")
$ midiOff "^57" (struct "<t!3 t*[<4 8> [8 <8 16>]]>")
$ midiOn "^44" (struct "t . t(<1 3 5>,8)")
$ midiOn "^76" (struct "t . t(<1 3 5>,8)")
$ midiOff "^76" (struct "<t!3 t*[<4 8> [8 <8 16>]]>")
$ note (
"<bf2 bf2 bf2 [bf2@7 cs3]>"
+ "[0,12]"
......@@ -40,8 +40,8 @@ d4 $ gF2 $ gM3
# room 0.2 # dry 1.2 # sz 0.7
# gain 1.4
d5 $ gF3 $ gM3 -- LE PIMENT BRESILIEN
$ midiOn "^90" (ply "<4!3 8>")
$ midiOn "^58" (striate "2" . chop 8)
$ midiOn "^57" (ply "<4!3 8>")
$ midiOn "^89" (striate "2" . chop 8)
$ slice 8 "<[0 1] [2 3] [4 5] <[6 7] 5*<2 4 4 8>>>"
-- $ slice 4 "<0 1 2 3>"
-- $ slice 4 "<0 1 2 3>"
......@@ -51,7 +51,7 @@ d5 $ gF3 $ gM3 -- LE PIMENT BRESILIEN
# octerbus 51 (range 0 1.4 "^33")
# octersubbus 52 (range 0 4 "^53")
d7 $ gF3 $ gM3
$ midiOn "^91" (ply 2)
$ midiOn "^59" (ply 2)
$ note ("[f3 cs3 c3 cs3 f3 cs3 <c3 f3> <cs3 fs3>]"
-- + "[0,12]"
+"<0!4 12!4 24!4 36!4>"
......@@ -72,8 +72,8 @@ d10 $ gF3 $ gM3 -- Menace
# octersub 1
# cut 9
d8 $ gF1 $ gM1 -- La Boite à breaks de ParVagues <3
$ midiOn "^92" (ply "1 <2!3 4>")
$ midiOff "^60" (mask "t(4,8,1)") -- Techno drum mask
$ midiOn "^60" (ply "1 <2!3 4>")
$ midiOff "^92" (mask "t(4,8,1)") -- Techno drum mask
$ midiOn ("^36" - "^56") ((# n "22")) -- Hmmm Break
$ midiOn "^56" ((# n "23")) -- Raise COMEON!
$ chop 16
......
......@@ -8,20 +8,22 @@ let rq = pF "rq"
let filterRange = pF "filterRange"
-- lagTime = 0.12, filterRange = 6, width = 0.51, rq = 0.3;
d1 $ gF1 $ gM2
$ midiOn ("^41"-"^42") ((<| "k(3,8) ~"))
$ midiOff ("^42"+"^41") (<| "k*<1!7 2> ~ . ~ <~!7 [k*2 k]>")
$ midiOn "^42" (fast 2 . (<| "k k k*<1!8 2!8> k*<1 <2!2 4>>"). (# "kick:4") . (|* gain 0.54))
-- FIXME(#94) d1 drives more controls than the grid gives it (BT1 only — BL1-3 are the family mutes). ^42 now belongs to another orbit, so the line(s) below are COMMENTED OUT rather than left firing across columns. Nothing is lost — restore by removing the dashes once gSel folds this onto d1's own control.
-- $ midiOn ("^41"-"^42") ((<| "k(3,8) ~"))
-- $ midiOff ("^42"+"^41") (<| "k*<1!7 2> ~ . ~ <~!7 [k*2 k]>")
-- $ midiOn "^42" (fast 2 . (<| "k k k*<1!8 2!8> k*<1 <2!2 4>>"). (# "kick:4") . (|* gain 0.54))
$ "[808bd:1,808bd:11]" -- 1 4 6 9 11
# octersubsub 1.2
# gain 2
d2 $ gF1 $ gM2
$ midiOn "^43" (fast 2 . (<| "~ c ~ c*<1!7 <2 [4 2]>>"))
$ midiOff "^43" (<| "~ . ~ c")
$ midiOn "^42" (fast 2 . (<| "~ c ~ c*<1!7 <2 [4 2]>>"))
$ midiOff "^42" (<| "~ . ~ c")
$ "vec1_claps:18"
# gain 1.4
d3 $ gF1 $ gM1
$ midiOn "^76" (fast "2 <2 2 4 8>")
$ midiOff "^44" (mask "f(4,32)" . chop 16)
$ midiOn "^43" (fast "2 <2 2 4 8>")
-- FIXME(#94) d3 drives more controls than the grid gives it (BT3 only — BL1-3 are the family mutes). ^44 now belongs to another orbit, so the line(s) below are COMMENTED OUT rather than left firing across columns. Nothing is lost — restore by removing the dashes once gSel folds this onto d3's own control.
-- $ midiOff "^44" (mask "f(4,32)" . chop 16)
$ (# pan "[0.25 0.75]*4")
$ ply (slow 16 "<2 [2 <4!3 [4 2]>] 4 [4 8 4] [8 4] 8 [8 16 8] 16>")
$ chop 16
......@@ -33,9 +35,9 @@ d3 $ gF1 $ gM1
# dry 0.4
# sz 0.3
d4 $ gF2 $ gM3
$ midiOn "^89" (struct "t*16")
$ midiOff "^89" (mask "[f [t f t] t t@2]") -- SILENCES
$ midiOn "^57" (stutWith 4 "q" ((|* gain 0.9) . (|+ pan 0.1). (|+ cut 1)))
$ midiOn "^44" (struct "t*16")
$ midiOff "^44" (mask "[f [t f t] t t@2]") -- SILENCES
$ midiOn "^76" (stutWith 4 "q" ((|* gain 0.9) . (|+ pan 0.1). (|+ cut 1)))
$ note "[cf4 [f4 cf4 f4] <[<cs4 fs4> cs4]!3 fs4> bf3@2]"
# "giorgio_syn:43" # n (slow 16 $ "<47 48 47 46>")
# cut 40
......@@ -47,7 +49,7 @@ d4 $ gF2 $ gM3
# sz 0.4
# dry 1.8
d5 $ gF3 $ gM3
$ midiOn "^90" (# rq (slow 8 $ range 0.1 0.01 saw))
$ midiOn "^57" (# rq (slow 8 $ range 0.1 0.01 saw))
$ fast 2 $ arp "up"
$ note (cat [
"[bf4,cs5,f5,bf4,cs5,f5,bf4,cs5]",
......@@ -76,9 +78,9 @@ d5 $ gF3 $ gM3
-- # pan "[0.4|0.6]*8"
d8 $ gF1 $ gM1
$ midiOn "^36" (# "jungle_breaks:75")
$ midiOn "^92" (ply 4)
$ midiOn "^60" (ply 4)
-- $ midiOff "^60" (mask "f(8,16)" . chop 8)
$ midiOff "^60" (slice 8 "<~!3 0> <1!3 ~> 2 <3!3 ~> 4 <5!3 ~> 6? 7*<1 2>" )
$ midiOff "^92" (slice 8 "<~!3 0> <1!3 ~> 2 <3!3 ~> 4 <5!3 ~> 6? 7*<1 2>" )
$ slice 8 "<~!3 0> <1!3 ~> 2 <3!3 ~> 4 <5!3 ~> 6? 7*<1 2>"
$ chop 16
$ loopAt 2
......
......@@ -9,19 +9,20 @@ setcps(166/60/4)
-- where an untouched/low knob sits. Bypass is djf 0.5, the CENTRE.
d1 $ gF1 $ gMute2
$ fix ((# lpf 150) . (|* gain 0.93)) "kick:5"
$ midiOn "^42" (<| "k k k <k <k*2 [k k k ~]>>")
$ midiOff "^42" (<| "k . ~ k ~ ~")
$ midiOn "^41" (<| "k k k <k <k*2 [k k k ~]>>")
$ midiOff "^41" (<| "k . ~ k ~ ~")
$ "[kick:5,tech:5,jazz]"
# gain 1.8
d2 $ gF1 $ gM1
$ midiOn "^43" (<| "~ c ~ c*<1!3 <2 [2 4]>>")
$ midiOff "^43" (<| "~ . c*<1!3 <2!3 4>> ~")
$ midiOn "^42" (<| "~ c ~ c*<1!3 <2 [2 4]>>")
$ midiOff "^42" (<| "~ . c*<1!3 <2!3 4>> ~")
$ "rampleS37:5"
# gain 1.8
-- # lpf 2650
d3 $ gF1 $ gM1 -- Highest hats
$ midiOn "^44" (ply 2)
$ midiOn "^76" (ply 2)
$ midiOn "^43" (ply 2)
-- FIXME(#94) d3 drives more controls than the grid gives it (BT3 only — BL1-3 are the family mutes). ^76 now belongs to another orbit, so the line(s) below are COMMENTED OUT rather than left firing across columns. Nothing is lost — restore by removing the dashes once gSel folds this onto d3's own control.
-- $ midiOn "^76" (ply 2)
$ sometimesBy "0!3 <0 0.5>" (# n 12)
$ sometimesBy "0!3 <0.1 0>" (# n 13)
$ "~ d ~ d d d d*<1 1 2 1> d"
......@@ -34,7 +35,7 @@ d3 $ gF1 $ gM1 -- Highest hats
-- Emphasize "and" of beats
d4 $ gF2 $ gM3
$ superimpose (const $ gF2 $ gM3 -- Second BASS!
$ midiOff "^57" (slow 2)
$ midiOff "^44" (slow 2)
$ note "~ [a3 c4] ~ [e3 g3] ~ [a3 e3] ~ g3"
# "bassWarsaw" |- note 12
# cut 41 # gain (range 0.5 2 "^32")
......@@ -52,19 +53,19 @@ d4 $ gF2 $ gM3
# crushbus 42 (range 16 2.5 "^52")
d5 -- The Voice of Love
-- $ gF3 $ gM3
$ midiOn "^58" ( -- I KNOW
$ midiOn "^57" ( -- I KNOW
(# n "<16 ~!3>")
. (# cut 5)) -- FIXME VOICE OFF
$ midiOff "^58" (>| n ("<~ ~ [~ 0] ~>"
$ midiOff "^57" (>| n ("<~ ~ [~ 0] ~>"
+ (slow 4 "<9 9 10 11 ~ 12 13 14 ~>")))
$ "no_sunshine"
# gain 1.5
# cut 5
# room 0.3 # sz 0.3
d7 $ gF3 $ gM3 -- Guitar Sunshine
$ midiOn "^91" (ply 2)
$ midiOn "^59" (ply 2)
$ juxBy 0.8 (rev . (#cut 71))
$ midiOn "^59" ( -- SLICE!
$ midiOn "^91" ( -- SLICE!
ply "1 2" . slow 4 . chop 8 . (# n 24)
)
$ "no_sunshine/2"
......@@ -84,7 +85,7 @@ d9 $ gF3 $ gM3
# room 0.3
d8 $ gF1 $ gM1 -- JazzyBelle JazzyBreak
$ juxBy 0.5 (# cut 81)
$ midiOn "^92" (slice 4 "0*2 [1 2] 2*2 3*<1 1 1 2>")
$ midiOn "^60" (slice 4 "0*2 [1 2] 2*2 3*<1 1 1 2>")
$ chop 16
$ midiOn "^36" (loopAt 1 . (# "org_jungle_breaks:24"))
$ midiOn "^56" (slice 4 "0 <1 1 1 3> <2 2 3 2> <3 3 2 <1 3>>" .
......
......@@ -2,26 +2,26 @@ do
setcps (133/60/4)
-- resetCycles
d1 $ gF1 $ gM2 -- Kick
$ midiOn "^42" (<| "k k k <k <[~ k] k*2>>")
$ midiOff "^42" (<| "k . ~ k ~ ~ ")
$ midiOn "^41" (<| "k k k <k <[~ k] k*2>>")
$ midiOff "^41" (<| "k . ~ k ~ ~ ")
$ "[kick:4]"
# gain 1.2
# lpf 400
d2 $ gF1 $ gM1
$ midiOff "^43" (slow 2 . (<| "~ ~ ~ s"))
$ midiOn "^43" (<| "~ s ~ s*<1 2 [2 1] [4 <2 8>]>" )
$ midiOff "^42" (slow 2 . (<| "~ ~ ~ s"))
$ midiOn "^42" (<| "~ s ~ s*<1 2 [2 1] [4 <2 8>]>" )
$ "cp" # hpf 1400 # gain 1.3
d3 $ gF1 $ gM1
$ midiOn "^44" (<| "h(4,8,1)")
$ midiOff "^44" (<| "hh(3,8) hh(<3 [3 5] 8>,8,1)")
$ midiOn "^43" (<| "h(4,8,1)")
$ midiOff "^43" (<| "hh(3,8) hh(<3 [3 5] 8>,8,1)")
$ "vec1_snare:11"
# legato (range 0.25 2 "^31")
d4 $ gF2 $ gM3 -- WAP BASS
$ midiOn "^89" (
$ midiOn "^44" (
slice 8 ("~ 0 ~ 5 ~ 3 <~!4 5!4> <3!4 [3 0]!4>")
-- . (superimpose (# cut 41))
)
$ midiOn "^57" (
$ midiOn "^76" (
slice 8 ("~ 0 <~ ~ 5 5> 3 <~ 0!3> <~!4 0!10 ~ 0*4> 5 <~ 5>")
-- $ (0.125 ~>) :
. (# gain 1.3 )
......@@ -41,11 +41,11 @@ d4 $ gF2 $ gM3 -- WAP BASS
-- # octerbus 41 (range 0 1.4 "^53")
d5 $ gF3 $ gMute3 -- WAP HOES v1 magic repeat
$ midiOn "^33" (# 7) -- FORCE INTRO
$ midiOff ("^33"+"^90") (slow 4)
$ midiOff ("^33"+"^57") (slow 4)
$ stut 4 1 1 -- Four repeats each
$ slow 4
$ midiOn "^58" (stut "4" 0.9 (fast 4 "e"))
$ midiOn "^90" (
$ midiOn "^89" (stut "4" 0.9 (fast 4 "e"))
$ midiOn "^57" (
ply "[1!3 4]*4" . chop 4 . -- Magic Repeat: next segment instead
stut "2" 0.9 (fast 2 "s") -- Magic Repeat: repeater
. (# att 0.08)
......@@ -57,12 +57,12 @@ d5 $ gF3 $ gMute3 -- WAP HOES v1 magic repeat
# sz 0
# gain 1.4
d5 $ gF3 $ gMute3 -- WAP HOES v1 science of repeat
$ midiOn "^90" ((slice 4 "0*4"))
$ midiOn "^57" ((slice 4 "0*4"))
$ midiOn "^33" (# 7) -- FORCE INTRO
$ midiOff ("^33" + "^90") (slow 4) -- 4 bars
$ midiOff ("^33" + "^57") (slow 4) -- 4 bars
$ stut 4 1 1 -- Four repeats each
$ slow 4 -- times Four bits
$ midiOn "^58" (stut "4" 0.9 (fast 4 "e"))
$ midiOn "^89" (stut "4" 0.9 (fast 4 "e"))
$ "wap:0" # n ("<8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31>") -- Rotation complete
# cut 5
# room 0
......
......@@ -3,16 +3,16 @@ do
setcps (114/60/4)
d1 $ gF1 $ gM2
$ sometimesBy "^29" (fast 2)
$ midiOn "^42" (<| "k k k k*2")
$ midiOff "^42" (<| "k . k(3,8)")
$ midiOn "^41" (<| "k k k k*2")
$ midiOff "^41" (<| "k . k(3,8)")
$ stack [
"kick:5" # gain 1.4 # lpf 200, -- character (KICK16, click+body)
"bd:5" # gain 1.0 # lpf 90 # hpf 25 -- sub thump (90% sub @ 43Hz)
]
-- alt punchier replacement: "hardkick:5" (sub + 9% mid click, distorted)
d2 $ gF1 $ gM1
$ midiOn "^43" (<| "~ <s!4 [~ s] s s s*2> ~ <s [s s*<1 2>]>")
$ midiOff "^43" (<| "~ s")
$ midiOn "^42" (<| "~ <s!4 [~ s] s s s*2> ~ <s [s s*<1 2>]>")
$ midiOff "^42" (<| "~ s")
$ stack [
"cp:1" # gain 1.05 # speed 0.95, -- 80s hand clap (HANDCLPA)
"snare:54" # gain 0.65 # hpf 280, -- existing snare, crack only
......@@ -34,10 +34,10 @@ d3 $ gF1 $ gM1
# s "h2ogmhh"
# gain 1.4
d4 $ gF2 $ gM3
$ midiOn "^57" (# n 3)
$ midiOff "^57" ( -- MONTEE
$ midiOn "^44" (# n 3)
$ midiOff "^44" ( -- MONTEE
whenmod 16 12 (# n "<[1 2] 2*2>"))
$ midiOff "^57" (slice 4 "<[0 1] [2 3]>")
$ midiOff "^44" (slice 4 "<[0 1] [2 3]>")
$ "like_sugar:0" # cut 4
# gain 1.4
-- # room 0.3 # sz 0.3
......@@ -46,7 +46,7 @@ d4 $ gF2 $ gM3
# bandf (range 50 1200 "^52")
d5 $ gF3 $ gM3
$ slow 2 -- Adjusted to Sugar rhytm <3
$ midiOn "^90" (ply "<4!3 8>" . (# begin "0 <0 0.25> 0.5 0.5"))
$ midiOn "^57" (ply "<4!3 8>" . (# begin "0 <0 0.25> 0.5 0.5"))
-- $ ply 4
-- $ slow 4
$ fix (# begin "<0 0 [0@3 0.7] 0.7>") (n 12) -- Sex appeal
......@@ -94,8 +94,8 @@ d7 $ gF2 $ gM3 -- LEAD: Rhodes arp in D Dorian (i7 → IV7 → bIII → v)
# modIndex (slow 16 $ range 0.4 2.5 perlin)
# legato 0.9
d8 $ gF1 $ gM1
$ midiOn "^92" (ply "<2 <4 [4 8]>>")
$ midiOff "^60" (mask "t(8,16,1)" . chop 16)
$ midiOn "^60" (ply "<2 <4 [4 8]>>")
$ midiOff "^92" (mask "t(8,16,1)" . chop 16)
$ chop 16
$ loopAt 2
$ midiOn "^36" (# n "102")
......
......@@ -5,21 +5,21 @@ setcps (124/60/4)
-- let gF2 = id
-- let gF3 = id
d1 $ gF1 $ gM2
$ midiOn "^42" (<| "k k k <k [<~!3 k> k]>")
$ midiOff "^42" (<| "k . <[~ k] k(<3 5>,8)>")
$ midiOn "^41" (<| "k k k <k [<~!3 k> k]>")
$ midiOff "^41" (<| "k . <[~ k] k(<3 5>,8)>")
$ "[techno:0,808bd:2,909,kick:4]"
-- $ "kick:5"
# gain 1.5
# lpf 400
d2 $ gF1 $ gM1
$ midiOn "^43" (<| "~ s ~ [s*<1 2> <~ s*<2 [4 2]>>]")
$ midiOff "^43" (<| "~ s")
$ midiOn "^42" (<| "~ s ~ [s*<1 2> <~ s*<2 [4 2]>>]")
$ midiOff "^42" (<| "~ s")
$ "vec1_claps:10"
# gain 1.3
# lpf 2000
d3 $ gF1 $ gM1
$ midiOn "^44" (ply 2 . (<| "h(4,8,1)"))
$ midiOff "^44" (<| "[~ h*<1!3 <1 2 [4 2] 1?>>]*4" )
$ midiOn "^43" (ply 2 . (<| "h(4,8,1)"))
$ midiOff "^43" (<| "[~ h*<1!3 <1 2 [4 2] 1?>>]*4" )
$ "h2ogmhh"
# gain 1.4
# room 0.5
......@@ -28,14 +28,14 @@ d3 $ gF1 $ gM1
# legato (range 0.3 2 "^31")
d5 $ gF3 $ gM3
$ midiOn "^33" (# n "15")
$ midiOn "^90" (ply "<2 2 1 2 2 4 [4 2 8 4] 8>")
$ midiOn "^57" (ply "<2 2 1 2 2 4 [4 2 8 4] 8>")
$ slice 4 "<0 1 2 3*<1!3 <2 4 [4 1]>>>"
$ midiOn "^53" (
mask "<t <f!4 t!4> <f t t t> <f!8 t!6 f t>>" .
(>| n (slow 8 $ "<18 19 20 21 22 23 24 26>"))
)
$ midiOn ("^58" - "^53") (>| n (slow 4 $ "<10 11 12 13 13 13 14 13 14 15 15 13 15 16 15 13>"))
$ midiOff ("^58" + "^53") (>| n (slow 4 $ "<9 9 10 9>"))
$ midiOn ("^89" - "^53") (>| n (slow 4 $ "<10 11 12 13 13 13 14 13 14 15 15 13 15 16 15 13>"))
$ midiOff ("^89" + "^53") (>| n (slow 4 $ "<9 9 10 9>"))
$ fix (|* gain 1.2) "take5:9"
$ "take5"
# cut 5
......@@ -46,7 +46,7 @@ d5 $ gF3 $ gM3
# pan 0.8
d4 -- BASSLINE GENERATIVE
$ gF2 $ gM3
$ midiOn "^57" (superimpose (
$ midiOn "^44" (superimpose (
degradeBy "0 <0!3 0.2>!6 <0.2!3 0.5>" .
(|+| note "[0 7 2 12]*4")
. (|+ note 12)
......@@ -99,8 +99,8 @@ d12
# gain 1.1
d8 $ gF1
-- $ gF1 $ gM1 -- La Boite à breaks de ParVagues <3
$ midiOn "^92" (ply "1 <2!3 4>")
$ midiOff "^60" (mask "t(4,8,1)") -- Techno drum mask
$ midiOn "^60" (ply "1 <2!3 4>")
$ midiOff "^92" (mask "t(4,8,1)") -- Techno drum mask
$ midiOn ("^36" - "^56") (loopAt 0.5 . (# "jungle_breaks:22")) -- Hmmm Break
$ midiOn "^56" (loopAt 0.5 . (# "jungle_breaks:23")) -- Raise COMEON!
$ chop 8
......
......@@ -7,32 +7,32 @@ setcps (128/60/4)
d1 $ gF1 $ gMute2
-- $ midiOff "^42" (<| "<k [~!7 k*<1 2>]>")
$ fix (# bandf 300) "clubkick"
$ midiOff "^42" (<| "k . ~ k*<1 2> ~ <~ k k <~ k*4>>")
$ midiOn "^42" (<| "k k . k <k [~ k] k k*2>")
$ midiOff "^41" (<| "k . ~ k*<1 2> ~ <~ k k <~ k*4>>")
$ midiOn "^41" (<| "k k . k <k [~ k] k k*2>")
$ "[jazz,clubkick]"
# cut 1
# gain 1.5
d2 $ gF1 $ gM1 -- Clap Technocratique
$ midiOn "^43" (mask "[t <f t!3>] [t <f t>]" . fast 2)
$ midiOn "^42" (mask "[t <f t!3>] [t <f t>]" . fast 2)
$ "~ s ~ [s*<1 2> <~ s*<2 [4 2]>>]"
# "vec1_claps" # n 10
# gain 1.7
# lpf 4000 # cut 2
d3 $ gF1 $ gM1
$ midiOn "^44" (ply "2 <2!3 [2|4|[4 8]]>")
$ midiOn "^43" (ply "2 <2!3 [2|4|[4 8]]>")
$ "~ h ~ h ~ h*<1!3 2> ~ h*<1 [1|2]>"
# "h2ogmhh" # n "<0!4 1!3 2>"
# gain (1.4 * (range 0.9 1.2 perlin))
d4 $ gF2 $ gM3
$ midiOn "^89" (ply 4) -- HIGHER
$ midiOn "^44" (ply 4) -- HIGHER
$ chop 8
$ loopAt 4
$ midiOn "^57" ( -- HIGHER
$ midiOn "^76" ( -- HIGHER
slow 2 . ply 2 .
(# n "<1 1 2 2 6 6 6 1 16 16 17 18>" )
. (|* gain 0.9)
)
$ midiOff "^57" ( -- LOWER
$ midiOff "^76" ( -- LOWER
(# n "<5 5 5 6>")
)
$ "perfect"
......@@ -42,7 +42,8 @@ d4 $ gF2 $ gM3
# crushbus 41 (range 16 4.5 "^32")
# octersubbus 42 (range 0 2.5 "^52")
-- FIXME(#54) d4 3rd+ effect: the grid gives d4 B4 + C4. Fold ^17 in via gSel rather than borrowing a column.
# octersubbus 43 (range 0 5 "^17")
-- FIXME(#54) d4 drives more controls than the grid gives it (B4 + C4). ^17 now belongs to another orbit, so the line(s) below are COMMENTED OUT rather than left firing across columns. Nothing is lost — restore by removing the dashes once gSel folds this onto d4's own control.
-- # octersubbus 43 (range 0 5 "^17")
# cut 4
# gain 1.5
d5
......@@ -52,26 +53,27 @@ d5
slice 16 "<<[0 1 2 3] [<0 10> <1 11> 10 11]> <[8 9 10 11] [<12!3 15> <13!3 15> <14 12> <15 13>]>>"
. (>| "perfect")
)
$ midiOn "^90" (ply "<2 4>")
$ midiOn "^57" (ply "<2 4>")
-- FIXME(#54) d5 3rd+ effect: the grid gives d5 B5 + C5. Fold ^18 in via gSel rather than borrowing a column.
$ midiOn ("^53" - "^18") ( -- THE HIPS THE FACE THE LIPS THE MICROPHONE
slice 4 "<0 1 0 1 2 2 [2 2] 3>"
. (# n 14) . (|* gain 0.8)
)
$ midiOn "^18" -- SUPERSTAR
(
-- mask "<t f!3>"
loopAt 4
. (0.5 ~>)
. (# n 8)
. mask "<t!4 t f t t>"
. (# end "<0.18!3 0.45 1!4>")
. (# begin "<0!4 0.5!4>")
. (|* gain 0.9)
)
$ midiOn ("^58") ( -- Slice 1 2 3 4!
-- FIXME(#54) d5 drives more controls than the grid gives it (B5 + C5). ^18 now belongs to another orbit, so the line(s) below are COMMENTED OUT rather than left firing across columns. Nothing is lost — restore by removing the dashes once gSel folds this onto d5's own control.
-- $ midiOn ("^53" - "^18") ( -- THE HIPS THE FACE THE LIPS THE MICROPHONE
-- slice 4 "<0 1 0 1 2 2 [2 2] 3>"
-- . (# n 14) . (|* gain 0.8)
-- )
-- $ midiOn "^18" -- SUPERSTAR
-- (
-- -- mask "<t f!3>"
-- loopAt 4
-- . (0.5 ~>)
-- . (# n 8)
-- . mask "<t!4 t f t t>"
-- . (# end "<0.18!3 0.45 1!4>")
-- . (# begin "<0!4 0.5!4>")
-- . (|* gain 0.9)
-- )
$ midiOn ("^89") ( -- Slice 1 2 3 4!
slice 8 "<[0 1] [0 1] [0 0 <0 1> <1 0>] [2 3]>" )
$ midiOff ("^58"+"^33" + "^53") ( -- WATCH ME WORK IT
$ midiOff ("^89"+"^33" + "^53") ( -- WATCH ME WORK IT
slice 8 "<[0 1] [2 3] [4 5] [6 <7 <6 6*2>>]>"
)
$ "perfect"
......@@ -82,7 +84,7 @@ d5
# octersub 0.8
d6 $ gF1 $ gM3
$ mask "f t"
$ midiOn "^89" (ply "<4 8>")
$ midiOn "^58" (ply "<4 8>")
$ chop 16
$ "meth_bass:3/8"
# room 0.4
......
......@@ -4,21 +4,22 @@ do
-- resetCycles
setcps (124/60/4)
d1 $ gF1 $ gM2
$ midiOn ("^41"-"^42") ((<| "k(3,8) ~"))
$ midiOff ("^42"+"^41") (<| "k*<1!7 2> ~ . ~ <~!7 [k*2 k]>")
$ midiOn "^42" ((<| "k k k*<1!8 2!8> k*<1 <2!2 4>>"). (# "kick:4") . (|* gain 0.94))
-- FIXME(#94) d1 drives more controls than the grid gives it (BT1 only — BL1-3 are the family mutes). ^42 now belongs to another orbit, so the line(s) below are COMMENTED OUT rather than left firing across columns. Nothing is lost — restore by removing the dashes once gSel folds this onto d1's own control.
-- $ midiOn ("^41"-"^42") ((<| "k(3,8) ~"))
-- $ midiOff ("^42"+"^41") (<| "k*<1!7 2> ~ . ~ <~!7 [k*2 k]>")
-- $ midiOn "^42" ((<| "k k k*<1!8 2!8> k*<1 <2!2 4>>"). (# "kick:4") . (|* gain 0.94))
$ "[808bd:1,808bd:11]" -- 1 4 6 9 11
# gain 1.52
d2 $ gF1 $ gM1 -- Clap Technocratiqu
$ midiOn "^43" (mask "[t <f t!3>] [t <f t>]" . fast 2)
$ midiOn "^42" (mask "[t <f t!3>] [t <f t>]" . fast 2)
$ "~ s ~ [s*<1 2> <~ s*<2 [4 2]>>]"
# "vec1_claps" # n 10
# gain 1.4
# sz 0.4 # room 0.3 # dry 0.8
# lpf 2000
d3 $ gF1 $ gM1
$ midiOn "^44" (<| "[~ h*<1!3 <1 2 [4 2] 1?>>]*4" )
$ midiOff "^44" (<| "h(3,8) h([3 1 3],8)")
$ midiOn "^43" (<| "[~ h*<1!3 <1 2 [4 2] 1?>>]*4" )
$ midiOff "^43" (<| "h(3,8) h([3 1 3],8)")
$ "h2ogmhh"
# gain 1.4
# room 0.3
......@@ -26,11 +27,11 @@ d3 $ gF1 $ gM1
# legato (range 0.05 2 "^31")
# sz 0.4
d4 $ gF2 $ gM3
$ midiOn "^89" (struct "t(8,16)")
$ midiOn "^44" (struct "t(8,16)")
$ juxBy 0.7 (|- note 12)
$ midiOff "^32" (slow 4)
$ midiOn "^57" (arp "pinkyup")
$ midiOff "^57" (arp "up")
$ midiOn "^76" (arp "pinkyup")
$ midiOff "^76" (arp "up")
$ ply 2 $ slow 2 $ note ("<[e3, gs3, b3, c4] [e3, d4, c4, b3] [e3, f4, ef4, e4] [e3, f4, ef4, e4]>" + "[0,-12]")
# "bassWarsaw"
# crushbus 41 (range 16 3.5 "^52")
......@@ -39,8 +40,8 @@ d4 $ gF2 $ gM3
# dry 1.5
# gain 1.5
d5 $ gF3 $ gM3 -- GUITARE DU DJ
$ midiOn "^58" (ply 4)
$ midiOn "^90" (ply "4 <2 4 4 8>")
$ midiOn "^57" (ply 4)
$ midiOn "^89" (ply "4 <2 4 4 8>")
-- $ slow 4 $ n "<9 9 9 11 12 12 13 14 15>"
$ slow "<1 2 ~ <2 ~>>" $ n "9"
# "diams_dj"
......@@ -52,14 +53,14 @@ d5 $ gF3 $ gM3 -- GUITARE DU DJ
# lpf 5000
# pan (slow 4 $ range 0.8 0.2 sine)
d7 $ gF3 $ gM3 -- Laisse moi kiffer la vibe.
$ midiOn ("^91" - "^59") (ply "<2 <2 4> 2 <4 [4 8] [4 16 4] [16 4]>>")
$ midiOn ("^59" - "^91") (ply "<2 <2 4> 2 <4 [4 8] [4 16 4] [16 4]>>")
$ midiOn "^35" (-- COPINE
ply 4 .
(>| n (slow 8 "<2 6 2 2>"))
. (# begin "<0!3 0.5>")
)
$ midiOn "^59" (-- KIFFANCE DE VIBZ
midiOn "^91" (ply "<1 1 1 2> <2 4>") .
$ midiOn "^91" (-- KIFFANCE DE VIBZ
midiOn "^59" (ply "<1 1 1 2> <2 4>") .
ply 4 .
(>| n (slow 4 $ "<4 5>"))
)
......
......@@ -5,8 +5,8 @@ resetCycles
do
setcps (130/60/4)
d1 $ gF1 $ gM1
$ midiOn "^42" (<| "k k k <k <k*2 [~ k]> k k*[2 <2 4>]>")
$ midiOff "^42" (<| "k . ~ k ~ ~" )
$ midiOn "^41" (<| "k k k <k <k*2 [~ k]> k k*[2 <2 4>]>")
$ midiOff "^41" (<| "k . ~ k ~ ~" )
$ "jazz"
# lpf 4000
# gain 1.3
......@@ -21,7 +21,7 @@ d3 $ gF1 $ gM1
# room 0.2
d4 $ gF2 $ gM3
$ slow 2
$ midiOn "^57" (juxBy 0.6 ((# cut 41) . (slice 4 "~ 3 4 <~ 4*4>")))
$ midiOn "^44" (juxBy 0.6 ((# cut 41) . (slice 4 "~ 3 4 <~ 4*4>")))
-- $ "hammer:1"
$ "superfreak:1"
# cut 4
......@@ -30,11 +30,11 @@ d4 $ gF2 $ gM3
# octerbus 42 (range 0 1.13 "^52")
# room 0.4
d5 $ gF3 $ gM3
$ midiOn "^90" (ply 8)
$ midiOn "^54" (
$ midiOn "^57" (ply 8)
$ midiOn "^33" (
(# n 3)
)
$ midiOn "^58" ((ply 4)
$ midiOn "^89" ((ply 4)
. (# begin "<0 0.25>")
. (# end "<1 0.45>")
)
......@@ -44,7 +44,7 @@ d5 $ gF3 $ gM3
# room 0.4 # sz 0.6 # dry 1.1
# octersub 1.4
d5 $ gF3 $ gM3
$ midiOn "^58" (>| n "<~ ~ 8 ~>")
$ midiOn "^89" (>| n "<~ ~ 8 ~>")
$ n "<<3 4 5 <6 7>> ~ <3 ~> ~>"
# "superfreak"
# cut 5
......
......@@ -5,16 +5,16 @@ d1 $ fast 2
$ gF1 $ gMute2
-- $ midiOff "^42" (<| "<k [~!7 k*<1 2>]>")#
$ midiOn "^29" (# "jazz:0")
$ midiOff "^42" (<| "k . ~ k ~ ~")
$ midiOn "^42" (<| "k k . k <k [~ k] k k*2>")
$ midiOff "^41" (<| "k . ~ k ~ ~")
$ midiOn "^41" (<| "k k . k <k [~ k] k k*2>")
$ "[popkick:2,kick:5]"
# lpf 300 -- TODO Sound design this kick <3
-- # cut 1
# gain 2
-- # midiG' "^78" 0 1.5
d2 $ fast 2 $ gF1 $ gM1
$ midiOn "^43" (<| "~ s ~ s*<1!3 <2 [4 2]>>")
$ midiOff "^43" (<| "~ . s*<1!3 2> ~")
$ midiOn "^42" (<| "~ s ~ s*<1!3 <2 [4 2]>>")
$ midiOff "^42" (<| "~ . s*<1!3 2> ~")
$ "[realclaps:0,snare:56]"
-- # "h2ogmcp"
-- # gain (1.0 * "<[1]!16 [1 <1 <1 [1 0.93] 1 [0.9]>>]!16>")
......@@ -27,7 +27,7 @@ d3 $ gM1 $ gF1
# room 0.3 # sz 0.5 # dry 0.9
# pan "0.8 0.8 0.8 <0.2 0.2 0.8 [0.8 0.2]>"
d4 $ gF2 $ gM3
$ midiOn "^89" (ply "1 <1 2 1 4>")
$ midiOn "^44" (ply "1 <1 2 1 4>")
$ note "[<as2 cs3 f3 cs3> <b2 ef3 fs3 b2>@7]" dr
# "bassWarsaw" # cut 4
# room 0.4 # sz 0.8 # dry 0.9
......@@ -35,7 +35,7 @@ d4 $ gF2 $ gM3
# crushbus 41 (range 16 4.5 "^52")
# gain 1.5
d5 $ gF3 $ gM3
$ midiOn "^90" ((# begin "0 0.5") . ply "<4!7 [8 16]>")
$ midiOn "^57" ((# begin "0 0.5") . ply "<4!7 [8 16]>")
$ slice 4 "<0 1 2 3 4 5 6 7>"
$ "daft" # n "<0!8 1!8>"
# cut 5
......@@ -47,7 +47,7 @@ d5 $ gF3 $ gM3
# crushbus 53 (range 16 5 "^53")
d7 $ gF3 $ gM3
$ midiOn "^35" (# n 3)
$ midiOn "^91" (ply "<4!3 [8 16]>")
$ midiOn "^59" (ply "<4!3 [8 16]>")
$ slice 4 "<0 1 2 3 4 5 6 7>"
$ "daft" # n "2"
# cut 7
......@@ -57,8 +57,8 @@ d7 $ gF3 $ gM3
# room 0.7 # sz 0.8
d8 $ gF1
$ gM1
$ midiOn "^92" (ply "<2 2 2 <4 8>>")
$ midiOff "^60" (mask "t(8,16,1)" . chop 16)
$ midiOn "^60" (ply "<2 2 2 <4 8>>")
$ midiOff "^92" (mask "t(8,16,1)" . chop 16)
$ chop 8
$ fix (loopAt 2) (n 155)
$ loopAt 1
......
......@@ -3,10 +3,11 @@ resetCycles
do
setcps (120/60/4)
d1 $ gMute2 $ gF1 -- Kick solide
$ midiOn "^58" (# cps (130/60/4))
$ midiOn "^41" (# cps (130/60/4))
$ fix ((# att 0.02) . (# rel 0.5) . (# lpf 5000)) "kick:4"
$ midiOn "^42" (struct "t t t t*<1!6 2 2>")
$ midiOff "^42" (<| "k . ~ <~!3 k> ~ ~")
-- FIXME(#94) d1 drives more controls than the grid gives it (BT1 only — BL1-3 are the family mutes). ^42 now belongs to another orbit, so the line(s) below are COMMENTED OUT rather than left firing across columns. Nothing is lost — restore by removing the dashes once gSel folds this onto d1's own control.
-- $ midiOn "^42" (struct "t t t t*<1!6 2 2>")
-- $ midiOff "^42" (<| "k . ~ <~!3 k> ~ ~")
$ "[kick:4,jazz]"
# gain 1
d2 $ gF1 $ gM1 $ "~ c . <[~ c ~ c] [<c ~ ~ c> <~ c ~ c> . ~]>"
......@@ -14,15 +15,15 @@ d2 $ gF1 $ gM1 $ "~ c . <[~ c ~ c] [<c ~ ~ c> <~ c ~ c> . ~]>"
# lpf 2000
# room 0.4 # sz 0.6 # dry 1.04 # octersub 0.8
d3 $ gF1 $ gM1
$ midiOn "^44" (>| "[~ hh]*4")
$ midiOff "^44" (chop 8 . loopAt 4 . (>| "crimewave:3") . ("e" ~>))
$ midiOn "^43" (>| "[~ hh]*4")
$ midiOff "^43" (chop 8 . loopAt 4 . (>| "crimewave:3") . ("e" ~>))
$ "drums"
# cut 3 # gain 1.6
# pan (range 0.4 0.8 perlin)
d4
$ gF2 $ gM3
$ chop 4 -- CRIMINAL BASSLINE
$ midiOn "^89" (ply "<[2 <2 [4 2]>]!3 [2 4]>")
$ midiOn "^44" (ply "<[2 <2 [4 2]>]!3 [2 4]>")
$ slice 4 "<0 1 2 3>"
-- $ chop 4
$ "crimewave"
......@@ -34,25 +35,25 @@ d4
# room 0.3 # sz 0.3 # dry 1.13
d5 $ gM3 $ gF3 -- THIS SYNTH IS A CRIME <3
$ slice 16 (slow 4 $ run 16)
$ midiOn "^58" (-- LZRTAG CRIMINAL TAKEOVER <3 <3
$ midiOn "^57" (-- LZRTAG CRIMINAL TAKEOVER <3 <3
("e" ~>) .
(>| n (slow 4 "<11!4 12!4 13!4 14!4>"))
)
-- $ midiOn "^90" (ply 4) . (# begin 0.25)
$ midiOff "^58" ( -- Standard Crimes
$ midiOff "^57" ( -- Standard Crimes
>| n (slow 4 $ "<0 0 0 1 0 1 1 2>")
)
$ "crimewave" # cut 5
# gain 1.4
# room 0.3 # sz 0.8 # pan 0.7
d7 $ gM3 $ gF3 -- DARK LIPS <3
$ midiOn "^91" (ply "4 <4!3 8>")
$ midiOn "^59" (ply "4 <4!3 8>")
$ midiOn "^35" ( -- GLITCH VOICE
(>| n (slow 4 "<16 17 18 19 20 21 22 23>"))
. (# room 0.3) . (# dry 0.9) . (# sz 0.4) )
$ midiOff "^35" (slice 4 ("<0 1 2 3>")) -- Structure par 4
$ midiOff ("^59"+"^35") (>| n (slow 8 "<9 10 7 8>" )) -- Loop Intro to Rough
$ midiOn "^59"
$ midiOff ("^91"+"^35") (>| n (slow 8 "<9 10 7 8>" )) -- Loop Intro to Rough
$ midiOn "^91"
-- REMIX VOCALS CRIME
(
(>| n (slow 4 "<16 17 16 17 18 19 18 19 20 21 20 21 22 22 22 23>"))
......
......@@ -96,37 +96,186 @@ def helper_ccs() -> set[int]:
return {int(m) for m in CC_REF.findall(text)}
def plan_track(path: Path, helpers: set[int]) -> dict:
"""Per-orbit {src cc -> dest cc}, plus the overflow that needs gSel."""
track = load(path)
per_orbit: dict[int, dict[int, int]] = {}
overflow: list[tuple[int, int, int]] = [] # (orbit, cc, line)
for orb in track.orbits():
if not 1 <= orb.number <= 8:
def label(cc: int) -> str:
"""'^35' -> 'B7'. The one place CC->physical-control naming lives here."""
for base, row in ((12, "A"), (28, "B"), (48, "C"),
(40, "BT"), (52, "BT"), (72, "BL"), (84, "BL")):
col = cc - base
if 1 <= col <= 8:
if row == "BT" and not (41 <= cc <= 44 or 57 <= cc <= 60):
continue
# First-appearance order matters: the first effect written is the one
# most likely to be the primary gesture, so it gets the easy B knob.
if row == "BL" and not (73 <= cc <= 76 or 89 <= cc <= 92):
continue
if row in ("A", "B", "C") and col > 8:
continue
return f"{row}{col}"
return f"cc{cc}"
def knob_slots(orbit: int) -> list[int]:
"""The knob destinations an orbit owns, in order of reachability.
B<col> first (row B is per-orbit for all 8 columns), then C<col> — but C1/C2/C3
are gF1/gF2/gF3, the per-FAMILY DJ filters, so d1..d3 own exactly one knob.
"""
slots = [28 + orbit]
if orbit >= 4:
slots.append(48 + orbit)
return slots
def button_slots(orbit: int) -> list[int]:
"""The button destinations an orbit owns, in order of reachability.
BT (top button row) is per-orbit across all 8 columns: 41-44 then 57-60.
BL (bottom row) columns 1-3 are gMute1/gMute2/gMute3, the per-family mutes,
so d1..d3 own exactly ONE button. That is the structural reason a two-button
gesture on d1 cannot survive column alignment — see the clash report.
"""
slots = [40 + orbit if orbit <= 4 else 52 + orbit] # 41..44, 57..60
if orbit >= 4:
slots.append(72 + orbit if orbit <= 4 else 84 + orbit) # 76, 89..92
return slots
def _seen_ccs(blocks: list, pool: set[int], helpers: set[int]) -> list[tuple[int, int]]:
"""CCs of one kind an orbit drives, in first-appearance order.
Takes ALL BLOCKS of that orbit, not one. A track routinely declares the same
orbit several times as section alternates — perfect.tidal has six `d1 $ …`
blocks. Planning per block and keying by orbit number silently dropped every
block but the last, which is why perfect.tidal kept ^42 on d1 while d2 also
owned ^42: d1's move was computed and then overwritten. An orbit's control
set is the UNION across its blocks.
First-appearance order matters: the first control written is the one most
likely to be the primary gesture, so it gets the most reachable slot.
"""
seen: list[tuple[int, int]] = []
for orb in blocks:
for off, raw in enumerate(orb.lines):
for m in CC_REF.finditer(strip_comment(raw)):
cc = int(m.group(1))
if cc in KNOBS and cc not in helpers and cc not in ARDOUR:
if cc in pool and cc not in helpers and cc not in ARDOUR:
if cc not in [c for c, _ in seen]:
seen.append((cc, orb.start + off))
return seen
def segment(lines: list[str], i: int, last: int) -> list[int]:
"""The whole `$`-chain segment starting at 1-indexed line i.
Commenting out a single LINE is wrong, and it produced a parse error the
first time: a Tidal chain step routinely spans several lines —
$ midiOn ("^53" - "^18") ( <- comment only this
slice 4 "<0 1 0 1 2 2 [2 2] 3>" and the body stays live
) and this ) is orphaned
In this codebase a chain step starts with `$` or `#` (or `d<N>` for a new
orbit), so the segment runs from i up to just before the next such line.
Verified afterwards by paren balance: if the segment does not close, we
refuse rather than write syntactically broken Haskell.
"""
out = [i]
j = i + 1
while j <= last:
s = lines[j - 1].strip()
if not s or re.match(r"(\$|#|d\d+\b|let\b|--\s*(FIXME|TODO))", s):
break
out.append(j)
j += 1
depth = 0
for k in out:
code = strip_comment(lines[k - 1])
code = re.sub(r'"[^"]*"', '""', code) # parens inside strings don't count
depth += code.count("(") - code.count(")")
depth += code.count("[") - code.count("]")
if depth != 0:
raise SystemExit(
f"migrate-columns: segment at line {i} does not close (depth {depth}); "
f"refusing to comment it out — this would produce broken Haskell.")
return out
def plan_track(path: Path, helpers: set[int]) -> dict:
"""Per-orbit {src cc -> dest cc}, plus overflow and cross-orbit clashes."""
track = load(path)
blocks: dict[int, list] = {}
for o in track.orbits():
if 1 <= o.number <= 8:
blocks.setdefault(o.number, []).append(o)
# Pass 1: what each orbit WANTS, planned over ALL of that orbit's blocks.
wants: dict[int, list[tuple[int, int, int]]] = {} # orbit -> [(cc,line,dest)]
overflow: list[tuple[int, int, int]] = [] # (orbit, cc, line)
for number, orbs in blocks.items():
pairs: list[tuple[int, int, int]] = []
for pool, slots in ((KNOBS, knob_slots(number)),
(BUTTONS, button_slots(number))):
for i, (cc, line) in enumerate(_seen_ccs(orbs, pool, helpers)):
if i < len(slots):
pairs.append((cc, line, slots[i]))
else:
overflow.append((number, cc, line))
wants[number] = pairs
# Pass 2: a destination is only free if NO overflow CC is squatting it. An
# overflow CC does not move, so moving another orbit onto it would put two
# orbits on one physical control — the failure this guard exists to prevent.
# OVERFLOW IS COMMENTED OUT, NOT LEFT IN PLACE — so it does NOT squat.
#
# The first version left an over-budget control where it was. That looks
# conservative and is actually a bug generator: once ^42 becomes d2's button,
# any d1 line still referencing ^42 means pressing d2's gate also fires d1's
# kick variant. Measured on the real setlist, that is exactly what happened:
# perfect.tidal ended up with ^42 driving BOTH d1 and d2.
#
# It was also a cascade: d1's stuck ^42 blocked d2, which blocked d3, which
# blocked d4, which blocked d5 — bombe_dj could only reach 4/8 aligned. PLN:
# "we need finish the job. why half moved? cant you move all-but then comment
# out with fixme?" Commenting the line out frees the control, so the rest of
# the row aligns, and nothing is lost: the original is one line above under
# two dashes, re-enableable the moment gSel (#54) can fold it onto one knob.
#
# A clashed control still stays put, so it IS sticky, and discovering a clash
# changes the answer for orbits already processed. Hence the fixed point.
base_sticky: set[int] = set()
sticky = set(base_sticky)
per_orbit: dict[int, dict[int, int]] = {}
clashes: list[tuple[int, int, int, int, str]] = []
for _round in range(len(wants) + 2):
per_orbit, clashes = {}, []
claimed: dict[int, int] = {} # dest -> orbit
for orbit, pairs in wants.items():
m: dict[int, int] = {}
for i, (cc, line) in enumerate(seen):
if i == 0:
m[cc] = 28 + orb.number # its B knob
elif i == 1 and orb.number >= 4:
m[cc] = 48 + orb.number # its C knob
for cc, line, dest in pairs:
if dest == cc:
claimed[dest] = orbit # already home
continue
if dest in sticky:
clashes.append((orbit, cc, line, dest,
f"^{dest} is held by a control that cannot move"))
elif dest in claimed and claimed[dest] != orbit:
clashes.append((orbit, cc, line, dest,
f"^{dest} already claimed by d{claimed[dest]}"))
else:
overflow.append((orb.number, cc, line)) # -> gSel
m[cc] = dest
claimed[dest] = orbit
# Guard: within one orbit two sources must never share a destination.
if len(set(m.values())) != len(m):
raise SystemExit(f"migrate-columns: internal collision in "
f"{path.name} d{orb.number}: {m}")
per_orbit[orb.number] = m
return dict(track=track, per_orbit=per_orbit, overflow=overflow)
f"{path.name} d{orbit}: {m}")
per_orbit[orbit] = m
grown = base_sticky | {cc for _o, cc, _l, _d, _w in clashes}
if grown == sticky:
break
sticky = grown
else:
raise SystemExit(f"migrate-columns: {path.name} did not converge — "
f"report this, do not --apply")
return dict(track=track, per_orbit=per_orbit,
overflow=overflow, clashes=clashes)
def rewrite(path: Path, res: dict) -> tuple[int, list[str]]:
......@@ -165,15 +314,58 @@ def rewrite(path: Path, res: dict) -> tuple[int, list[str]]:
lines[idx] = CC_REF.sub(sub, lines[idx])
notes = []
# FIXMEs for overflow, inserted bottom-up so earlier line numbers hold.
for orbit, cc, line in sorted(res["overflow"], reverse=True):
indent = re.match(r"\s*", lines[line - 1]).group(0)
lines.insert(line - 1,
f"{indent}-- FIXME(#54) d{orbit} 3rd+ effect: the grid gives d{orbit} "
f"B{orbit}"
+ (f" + C{orbit}" if orbit >= 4 else " only (C is a gF filter)")
+ f". Fold ^{cc} in via gSel rather than borrowing a column.\n")
notes.append(f"d{orbit} ^{cc} -> gSel FIXME at line {line}")
# Overflow: COMMENT OUT every live line of that orbit which references the
# over-budget control, and head the group with one FIXME. Every such line
# must go, not just the ones mentioning the control alone — the control now
# belongs to a DIFFERENT orbit, so any surviving reference is a cross-orbit
# trigger (the perfect.tidal ^42-drives-d1-and-d2 bug).
#
# Clashes: annotate only. A clashed control keeps its own CC, so it is still
# correct code; it is simply not where the grid wants it.
edits: list[tuple[int, str, list[int], str]] = [] # (anchor, fixme, lines, note)
# ALL blocks of each orbit, not just the last — see _seen_ccs.
ranges: dict[int, list[tuple[int, int]]] = {}
for o in res["track"].orbits():
ranges.setdefault(o.number, []).append((o.start, o.start + len(o.lines) - 1))
for orbit, cc, line in res["overflow"]:
hits: set[int] = set()
for start, end in ranges.get(orbit, [(line, line)]):
for i in range(start, min(end, len(lines)) + 1):
if (not lines[i - 1].lstrip().startswith("--")
and f'"^{cc}"' in strip_comment(lines[i - 1])):
# Expand to the whole chain segment, or the closing parens of
# a multi-line step are left dangling.
hits.update(segment(lines, i, end))
hits = sorted(hits) if hits else [line]
slots = (f"BT{orbit}" + (f" + BL{orbit}" if orbit >= 4
else " only — BL1-3 are the family mutes")
if cc in BUTTONS
else f"B{orbit}" + (f" + C{orbit}" if orbit >= 4
else " only (C1-3 are the family gF filters)"))
tag = "#94" if cc in BUTTONS else "#54"
fixme = (f"-- FIXME({tag}) d{orbit} drives more controls than the grid gives it "
f"({slots}). ^{cc} now belongs to another orbit, so the line(s) below "
f"are COMMENTED OUT rather than left firing across columns. Nothing is "
f"lost — restore by removing the dashes once gSel folds this onto "
f"d{orbit}'s own control.")
edits.append((hits[0], fixme, hits, f"d{orbit} ^{cc} commented out ({len(hits)} line(s))"))
for orbit, cc, line, dest, reason in res.get("clashes", []):
edits.append((line,
f"-- FIXME(#94) d{orbit}: ^{cc} should become ^{dest} ({label(dest)}) "
f"but {reason}. Left on ^{cc} — moving it would put two orbits on "
f"one physical control.",
[], f"d{orbit} ^{cc} CLASH -> ^{dest} at line {line}"))
# Bottom-up so earlier line numbers stay valid as we insert.
for anchor, fixme, hits, note in sorted(edits, key=lambda e: e[0], reverse=True):
for i in sorted(hits, reverse=True):
stripped = lines[i - 1].rstrip("\n")
indent = stripped[: len(stripped) - len(stripped.lstrip())]
nl = "\n" if lines[i - 1].endswith("\n") else ""
lines[i - 1] = f"{indent}-- {stripped.lstrip()}{nl}"
indent = re.match(r"\s*", lines[anchor - 1]).group(0)
lines.insert(anchor - 1, f"{indent}{fixme}\n")
notes.append(note)
path.write_text("".join(lines))
return n, notes
......@@ -202,10 +394,12 @@ def main() -> int:
g = ap.add_mutually_exclusive_group(required=True)
g.add_argument("--plan", action="store_true")
g.add_argument("--apply", action="store_true")
ap.add_argument("--force-partial", action="store_true",
help="apply even to a track with clashes (leaves it HALF aligned)")
a = ap.parse_args()
helpers = helper_ccs()
total_moves = total_over = 0
total_moves = total_over = total_clash = 0
for p in resolve(a.tracks):
res = plan_track(p, helpers)
moves = [(s, d, o) for o, m in res["per_orbit"].items()
......@@ -213,15 +407,26 @@ def main() -> int:
keeps = sum(1 for m in res["per_orbit"].values()
for s, d in m.items() if s == d)
print(f"== {p.name} {len(moves)} move {keeps} keep "
f"{len(res['overflow'])} overflow")
f"{len(res['overflow'])} overflow {len(res['clashes'])} clash")
for s, d, o in sorted(moves, key=lambda x: x[2]):
row = "A" if s in KNOB_A else "B" if s in KNOB_B else "C"
drow = "B" if d in KNOB_B else "C"
print(f" d{o:<2} ^{s:<3} {row}{(s-12) if s in KNOB_A else (s-28) if s in KNOB_B else s-48}"
f" -> ^{d:<3} {drow}{o}")
kind = "btn " if s in BUTTONS else "knob"
print(f" d{o:<2} {kind} ^{s:<3} {label(s):<4} -> ^{d:<3} {label(d)}")
for o, cc, line in res["overflow"]:
print(f" d{o:<2} ^{cc:<3} line {line} -> gSel FIXME (no slot)")
print(f" d{o:<2} ^{cc:<3} {label(cc):<4} line {line} -> FIXME (no slot)")
for o, cc, line, dest, reason in res["clashes"]:
print(f" d{o:<2} ^{cc:<3} {label(cc):<4} line {line} -> CLASH: {reason}")
total_moves += len(moves); total_over += len(res["overflow"])
total_clash += len(res["clashes"])
if a.apply and res["clashes"] and not a.force_partial:
# A track with clashes cannot be FULLY aligned, and applying only the
# movable half is the worst outcome for muscle memory: the player
# then has to remember which orbits moved and which did not. A
# consistently-old track beats an inconsistently-new one. Skip it,
# name it, and let the blocking decision be made deliberately.
print(f" SKIPPED — {len(res['clashes'])} clash(es); this track cannot be "
f"fully aligned. Resolve the blocking gesture first, or "
f"--force-partial to half-migrate it on purpose.")
continue
if a.apply:
n, notes = rewrite(p, res)
print(f" APPLIED: {n} substitution(s), {len(notes)} FIXME(s)")
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment