music livecoding with STRUDEL + live midi controls

music livecoding experiments with STRUDEL / REPL


// Load external samples from bubo:waveforms
samples('bubo:waveforms');

// Define a simple chord progression to support the bassline
let chords = chord("<dm7 em9 cm7 dm9>")

// --- Melodic Layer with MIDI Controls ---
// The note pattern is now set to play along with the chord progression using set(chords).
// It is also controlled by MIDI, which is defined by the cc variable.
 
let cc = await midin('LPD8')
// The notes are no longer hardcoded. The numbers here correspond to the notes within the current chord.
// For example, 0 is the root, 1 is the next note in the chord, and so on.
let d1 = note("<0 1 2 3>")
.set(chords.rootNotes(4))
  
// Corrected MIDI control access from cc(number) 
.sound("sawtooth")
.n("<1 2 3 4 5 6 7 8 9 10>/2").size(1.9)
.velocity(0.55).often(n => n.ply(4))
.attack(cc(1).range(0,0.4))
.sustain(cc(2).range(0.1,0.94))
.release(cc(3).range(0.1,0.94))
  .delay(cc(7).range(0, 9.0))
  .room(cc(8).range(0, 19.0))
.cutoff(cc(5).range(10, 15000))
  .resonance(cc(6).range(0, 55))
  .gain(0.4)
  .fast(4)

._scope()

// --- Bassline Layer ---
// This pattern plays the root notes of the chords progression.
// It uses a sequence of different synth sounds for a varied texture.
// The slow(2/3) function makes the pattern play as triplets.
let d4 = chords.rootNotes(1)
.slow(1/3)
.s("{z_sawtooth}%3").lpf(200).gain(2)  
.sustain(cc(2).range(0.1,1.94))
.decay(.5).scope()

// Stack the two patterns together to play them simultaneously.
stack(d1, d4)

overlapping chord progression with different anchors

let chords = "<Dsus Dm Cm7 Gm>"
let ac1 = "<g3 c4 e4 d4>"
let ac2 = "<g5 a5 d6 e5>"
let ac3 = "<g1 a1 d2>"
let d1,d2,d3,d4,d5

chords = "<Gsus Em Am7 Bm>"

d1 = anchor(ac1).
chord(chords).voicing().room(.75).delay(0.5).sound("gm_string_ensemble_1")
.gain(0.6)

d2 =  chord(chords).anchor(ac2).voicing().sound("gm_piano").room(.75)
.slow(1/4).gain(0.4)

d3 = chord(chords).anchor(ac2).voicing().sound("gm_pizzicato_strings").room(1.75).delay(4)
.slow(1).gain(0.4)


d4 = note(ac3).sound("sine*2").gain(5).sustain(0.3).slow(1/4).size(2)._scope()
d5 = s("bd*4").bank("<RolandTR808>").gain(2)


stack(d2,d1,d3,d4,d5)