|
setcpm(72) |
|
|
|
// Generative Blues |
|
// Parser-safe version with weighted motif walking and light runtime evolution. |
|
// Four square-based voices in four registers. |
|
|
|
let conductor = "<1 0.92 0.96 0.9>".slow(32) |
|
let sopSpeak = "<1 0.18 0.08 0.72 1 0.15 0.08 0.62>".slow(24) |
|
let altoSpeak = "<0.08 1 0.22 0.12 0.08 0.9 0.2 0.1>".slow(24) |
|
let tenorSpeak = "<0.12 0.16 1 0.2 0.1 0.18 0.92 0.16>".slow(24) |
|
let bassSpeak = "<0.72 0.68 0.74 0.7 0.78 0.72 0.76 0.7>".slow(24) |
|
|
|
let swing = sine.range(-0.03, 0.035).slow(2) |
|
let leadS = "<1 0.22 0.08 0.65 1 0.18 0.08 0.55>".slow(48) |
|
let leadA = "<0.08 1 0.18 0.1 0.08 0.92 0.16 0.1>".slow(48) |
|
let leadT = "<0.12 0.18 1 0.2 0.1 0.16 0.94 0.18>".slow(48) |
|
let leadB = "<0.62 0.62 0.66 0.66 0.7 0.7 0.74 0.74>".slow(48) |
|
let push = "<0 0.008 -0.004 0.01>".slow(12) |
|
|
|
// density / maturation control |
|
// Lower values = reaches full density faster. |
|
// Higher values = much longer bloom. |
|
// Good starting points: |
|
// densitySpan 48-72 -> roughly 7-10 minute recorded track |
|
// densitySpan 256-512 -> long-form installation / hour-scale bloom |
|
// walkerSpan can be slower than densitySpan if you want the ensemble to fill in |
|
// without the motif changes accelerating as quickly. |
|
let densitySpan = 56 |
|
let walkerSpan = 84 |
|
|
|
// macro energy arc: starts sparse, opens up, then stays more conversational |
|
let energy = sine.range(0.35, 1.0).slow(densitySpan) |
|
let openS = sine.range(0.6, 1.0).slow(densitySpan) |
|
let openA = sine.range(0.55, 0.95).slow(densitySpan) |
|
let openT = sine.range(0.5, 0.9).slow(densitySpan) |
|
let openB = sine.range(0.75, 1.0).slow(densitySpan) |
|
|
|
// blues landing / assertiveness helpers |
|
let resolveS = "<e5 d5 g5 e5 d5 e5 g5 e5>" |
|
let resolveT = "<e4 d4 g4 e4 d4 e4 g4 e4>" |
|
let assertS = sine.range(0.85, 1.18).slow(densitySpan) |
|
let assertA = sine.range(0.82, 1.12).slow(densitySpan) |
|
let assertT = sine.range(0.8, 1.1).slow(densitySpan) |
|
let assertB = sine.range(0.9, 1.12).slow(densitySpan) |
|
|
|
let sopI = ` |
|
< |
|
[e5@2 ~ ~ ~] |
|
[g5@2 ~ ~ ~] |
|
[d5@2 ~ e5@2 ~ ~] |
|
[~ ~ g5@2 ~] |
|
> |
|
< |
|
[e5@2 ~ g5@2 ~] |
|
[~ ~ ~ bb5@2] |
|
[d5@2 ~ ~ e5@2] |
|
[~ e5@2 ~ ~] |
|
> |
|
` |
|
|
|
let altoI = ` |
|
< |
|
[~ g4@2 ~ ~] |
|
[d5@2 ~ ~ ~] |
|
[~ e5@2 ~ ~] |
|
[~ d5@2 ~ ~] |
|
> |
|
< |
|
[b4@2 ~ ~ d5@2] |
|
[~ ~ g4@2 ~] |
|
[~ e5@2 ~ ~] |
|
[~ g4@2 ~ ~] |
|
> |
|
` |
|
|
|
let tenorI = ` |
|
< |
|
[e4@2 ~ ~ ~] |
|
[~ d4@2 ~ ~] |
|
[g4@2 ~ ~ ~] |
|
[~ ~ d4@2 ~] |
|
> |
|
< |
|
[e4@2 ~ ~ g4@2] |
|
[~ d4@2 ~ ~] |
|
[g4@2 ~ e4@2 ~] |
|
[d4@2 ~ ~ ~] |
|
> |
|
` |
|
|
|
let bassI = ` |
|
< |
|
[e2@2 ~ ~ ~] |
|
[d2@2 ~ ~ ~] |
|
[e2@2 ~ ~ ~] |
|
[b1@2 ~ d2@2 ~] |
|
> |
|
< |
|
[e2@2 ~ ~ ~] |
|
[d2@2 ~ e2@2 ~] |
|
[g2@2 ~ e2@2 ~] |
|
[~ b1@2 ~ ~] |
|
> |
|
` |
|
|
|
let sopIV = ` |
|
< |
|
[a5@2 ~ ~ ~] |
|
[g5@2 a5@2 ~ ~] |
|
> |
|
< |
|
[a5@2 ~ c6@2 ~] |
|
[~ g5@2 ~ ~] |
|
> |
|
` |
|
|
|
let altoIV = ` |
|
< |
|
[~ a4@2 ~ ~] |
|
[e5@2 ~ ~ ~] |
|
> |
|
< |
|
[c5@2 ~ e5@2 ~] |
|
[~ a4@2 ~ ~] |
|
> |
|
` |
|
|
|
let tenorIV = ` |
|
< |
|
[a4@2 ~ ~ ~] |
|
[~ g4@2 ~ ~] |
|
> |
|
< |
|
[c5@2 ~ a4@2 ~] |
|
[~ ~ g4@2 ~] |
|
> |
|
` |
|
|
|
let bassIV = ` |
|
< |
|
[a2@2 ~ ~ ~] |
|
[g2@2 ~ a2@2 ~] |
|
> |
|
< |
|
[a2@2 ~ ~ e2@2] |
|
[c3@2 ~ a2@2 ~] |
|
> |
|
` |
|
|
|
let sopV = ` |
|
< |
|
[b5@2 ~ ~ ~] |
|
> |
|
< |
|
[d6@2 ~ b5@2 ~] |
|
> |
|
` |
|
|
|
let altoV = ` |
|
< |
|
[~ b4@2 ~ ~] |
|
> |
|
< |
|
[fs5@2 ~ d5@2 ~] |
|
> |
|
` |
|
|
|
let tenorV = ` |
|
< |
|
[b4@2 ~ ~ ~] |
|
> |
|
< |
|
[d5@2 ~ b4@2 ~] |
|
> |
|
` |
|
|
|
let bassV = ` |
|
< |
|
[b1@2 ~ ~ ~] |
|
> |
|
< |
|
[fs2@2 ~ b1@2 ~] |
|
> |
|
` |
|
|
|
let sopTurn = ` |
|
< |
|
[d6@2 ~ bb5@2 ~] |
|
[b5@2 ~ a5@2 ~] |
|
[~ g5@2 ~ ~] |
|
> |
|
< |
|
[d6@2 ~ ~ bb5@2] |
|
[a5@2 ~ g5@2 ~] |
|
[~ ~ g5@2 ~] |
|
> |
|
` |
|
|
|
let altoTurn = ` |
|
< |
|
[~ d5@2 ~ ~] |
|
[bb4@2 ~ a4@2 ~] |
|
[~ b4@2 ~ ~] |
|
> |
|
< |
|
[d5@2 ~ g5@2 ~] |
|
[a4@2 ~ bb4@2 ~] |
|
[~ d5@2 ~ ~] |
|
> |
|
` |
|
|
|
let tenorTurn = ` |
|
< |
|
[d5@2 ~ b4@2 ~] |
|
[a4@2 ~ g4@2 ~] |
|
[e4@2 ~ ~ ~] |
|
> |
|
< |
|
[b4@2 ~ d5@2 ~] |
|
[g4@2 ~ a4@2 ~] |
|
[~ e4@2 ~ ~] |
|
> |
|
` |
|
|
|
let bassTurn = ` |
|
< |
|
[a1@2 ~ e2@2 ~] |
|
[b1@2 ~ a1@2 ~] |
|
[e2@2 ~ ~ ~] |
|
> |
|
< |
|
[a1@2 ~ ~ e2@2] |
|
[b1@2 ~ d2@2 ~] |
|
[e2@2 ~ ~ ~] |
|
> |
|
` |
|
|
|
// weighted walker banks |
|
// explicit selector patterns are more reliable here than choose(...).inhabit(...) |
|
let walkS = "<a a a a b a c a a d>".slow(sine.range(7, 4).slow(walkerSpan)) |
|
let walkA = "<a a a b a c a d>".slow(sine.range(7, 4.5).slow(walkerSpan)) |
|
let walkT = "<a a a b a c a d>".slow(sine.range(8, 5).slow(walkerSpan)) |
|
let walkB = "<a a a a b a c a a d>".slow(sine.range(7, 4).slow(walkerSpan)) |
|
|
|
let soprano = walkS.inhabit({ a: sopI, b: sopIV, c: sopTurn, d: sopV }) |
|
let alto = walkA.inhabit({ a: altoI, b: altoIV, c: altoTurn, d: altoV }) |
|
let tenor = walkT.inhabit({ a: tenorI, b: tenorIV, c: tenorTurn, d: tenorV }) |
|
let bass = walkB.inhabit({ a: bassI, b: bassIV, c: bassTurn, d: bassV }) |
|
|
|
$: note(soprano).slow(8) |
|
.late(swing) |
|
.late(push) |
|
.sometimesBy(0.12, x => x.rev()) |
|
.sometimesBy(0.04, x => x.slow(1.15)) |
|
.sometimesBy(0.18, x => x.degradeBy(0.22)) |
|
.sometimesBy(0.14, x => x.early(0.01)) |
|
// phrase landing bias: kept rare and slow to avoid exposed beep-like events |
|
.sometimesBy(0.08, x => x.add(resolveS.sub(x)).slow(1.5)) |
|
.s("square") |
|
.gain(sine.range(0.055, 0.07).slow(9).mul(conductor).mul(sopSpeak.add(openS)).mul(leadS.add(energy)).mul(assertS)) |
|
.release(sine.range(1.5, 3.5).slow(18)) |
|
.lpf(sine.range(700, 1000).slow(10)) |
|
.hpf(260) |
|
.delay(0.18) |
|
.delayfeedback(0.03) |
|
.room(0.14) |
|
.size(2.6) |
|
.pan(sine.range(0.18, 0.34).slow(17)) |
|
|
|
$: note(alto).slow(9) |
|
.late(swing.mul(0.8)) |
|
.sometimesBy(0.1, x => x.rev()) |
|
.sometimesBy(0.03, x => x.slow(1.12)) |
|
.sometimesBy(0.2, x => x.degradeBy(0.24)) |
|
.sometimesBy(0.12, x => x.early(0.008)) |
|
.sometimesBy(0.03, x => x.slow(1.25)) |
|
.s("square") |
|
.gain(sine.range(0.06, 0.08).slow(12).mul(conductor).mul(altoSpeak.add(openA)).mul(leadA.add(energy)).mul(assertA)) |
|
.release(sine.range(2.0, 4.0).slow(20)) |
|
.lpf(sine.range(550, 800).slow(13)) |
|
.hpf(220) |
|
.delay(0.18) |
|
.delayfeedback(0.04) |
|
.room(0.14) |
|
.size(2.6) |
|
.pan(sine.range(0.78, 0.62).slow(19)) |
|
|
|
$: note(tenor).slow(10) |
|
.late(swing.mul(0.6)) |
|
.sometimesBy(0.08, x => x.rev()) |
|
.sometimesBy(0.22, x => x.degradeBy(0.26)) |
|
// phrase landing bias in the mid register, kept slow and rare |
|
.sometimesBy(0.08, x => x.add(resolveT.sub(x)).slow(1.5)) |
|
.s("square") |
|
.gain(sine.range(0.075, 0.1).slow(10).mul(conductor).mul(tenorSpeak.add(openT)).mul(leadT.add(energy)).mul(assertT)) |
|
.release(sine.range(2.5, 5.0).slow(22)) |
|
.lpf(sine.range(260, 420).slow(11)) |
|
.hpf(110) |
|
.delay(0.08) |
|
.delayfeedback(0.01) |
|
.room(0.1) |
|
.size(2.1) |
|
.pan(sine.range(0.42, 0.58).slow(21)) |
|
|
|
$: note(bass).slow(8) |
|
.late(swing.mul(0.3)) |
|
.sometimesBy(0.05, x => x.rev()) |
|
.sometimesBy(0.14, x => x.degradeBy(0.18)) |
|
.s("square") |
|
.gain(sine.range(0.09, 0.12).slow(18).mul(conductor).mul(bassSpeak.add(openB)).mul(leadB.add(energy.mul(0.5))).mul(assertB)) |
|
.release(sine.range(3.0, 6.0).slow(24)) |
|
.lpf(sine.range(90, 170).slow(15)) |
|
.hpf(35) |
|
.delay(0.14) |
|
.delayfeedback(0) |
|
.room(0.08) |
|
.size(1.8) |
|
.pan(0.5) |