Skip to content
BoWen Chai's Notes
Go back

Heat Waves Inspired Arrangement in Strudel

Edit page

Take the shape of Lewis’s Blue Monday Strudel template: two kicks, two hat patterns, a layered snare, two bass parts, and a final stack of arrange calls. Move it toward Heat Waves by Glass Animals with a slower pulse, soft chord plucks, spaces between the bass notes, and a hook that opens up in the chorus. This is an instrumental adaptation with its own melody and a shortened song form.

In Dave Bayley’s breakdown of Heat Waves, he describes leaving space for the voice between pitched guitar layers and keeping the verse intimate before enlarging the chorus. That change in density is the idea to borrow here.

Press Play for the whole arrangement. Drum samples load from GitHub on first play; the chords, bass, and lead are synthesized.

/*
  @title Heat Waves inspired instrumental
  @by BoWen Chai
  Arrangement structure adapted from Lewis's Blue Monday cover / remix.
*/

await samples('https://raw.githubusercontent.com/felixroos/dough-samples/main/tidal-drum-machines.json')
setcpm(91/4)

const kick1 = sound("bd ~ [~ bd] ~").bank("LinnDrum").decay(.15).gain(.55)
const kick2 = sound("bd [~ bd] [~ bd] [bd ~]").bank("LinnDrum").decay(.18).gain(.6)

const hats1 = sound("hh*8").bank("OberheimDMX").decay(.045).gain("[.09 .05]*4")
const hats2 = stack(
  hats1,
  sound("~ oh ~ [~ oh]").bank("OberheimDMX").decay(.12).gain(.07)
)

const snare = stack(
  sound("~ sd ~ sd").bank("LinnDrum").decay(.12).gain(.28),
  sound("~ cp ~ cp").bank("LinnDrum").decay(.1).gain(.09)
)

const drums1 = stack(kick1, hats1, snare)
const drums2 = stack(kick2, hats2, snare)
const drums3 = stack(kick1, hats1.gain(.04))
const fill = stack(
  kick1, hats2,
  sound("~ sd ~ [sd sd*2]").bank("LinnDrum").decay(.1).gain(.2)
)

// Emaj7 -> D#7 -> G#m7 -> F#add9, one chord per bar.
const harmony = note("<[e3,g#3,b3,d#4] [d#3,g3,a#3,c#4] [g#3,b3,d#4,f#4] [f#3,a#3,c#4,g#4]>")
const chords1 = harmony.struct("x ~ x [~ x]").sound("triangle")
  .attack(.005).decay(.22).sustain(0).release(.12).lpf(1500).gain(.12)
const chords2 = stack(
  chords1.lpf(2800),
  harmony.sound("sawtooth").attack(.12).sustain(.35).release(.3).lpf(900).gain(.035)
)

const roots = note("<e2 d#2 g#1 f#1>")
const bass1 = roots.struct("x ~ [~ x] ~").sound("sine")
  .attack(.01).decay(.2).sustain(.3).release(.08).gain(.32)
const bass2 = roots.struct("x [~ x] [~ x] x").sound("sine, triangle")
  .attack(.01).decay(.25).sustain(.45).release(.1).lpf(450).gain(.2)

const synth = note("<[b4 ~ g#4 [~ f#4]] [a#4 ~ g4 [~ d#4]] [b4 d#5 ~ [b4 g#4]] [a#4 ~ g#4 f#4]>")
  .sound("triangle").attack(.02).decay(.2).sustain(.15).release(.18)
  .lpf(2400).gain(.13)

// Each row: intro, verse, lift, chorus, verse, breakdown, chorus, outro, rest.
stack(
  arrange(
    [4,silence], [8,drums1], [3,drums1], [1,fill], [8,drums2],
    [8,drums1], [4,drums3], [7,drums2], [1,fill], [4,silence], [1,silence]
  ).room(.08).orbit(0),
  arrange(
    [4,chords1.lpf(700)], [8,chords1], [4,chords1.lpf(2200)], [8,chords2],
    [8,chords1], [4,chords1.lpf(700)], [8,chords2], [4,chords1.lpf(700)], [1,silence]
  ).room(.22).orbit(1),
  arrange(
    [4,silence], [8,bass1], [4,bass1], [8,bass2],
    [8,bass1], [4,silence], [8,bass2], [4,silence], [1,silence]
  ).orbit(2),
  arrange(
    [4,silence], [8,silence], [4,synth.gain(.06)], [8,synth],
    [8,silence], [4,silence], [8,synth], [4,silence], [1,silence]
  ).delay(.18).delaytime(60/91/2).room(.18).orbit(3)
)

Follow the arrangement

One cycle is one four-beat bar: setcpm(91/4) sets this arrangement to 91 BPM. Each arrange entry gives a duration in bars and the pattern to play during it.

BarsSectionWhat changes
1–4IntroFiltered chord plucks establish the harmony.
5–12VerseSparse kick, closed hats, snare, and short bass enter.
13–16LiftThe plucks brighten, a quiet hook enters, and a fill leads into the chorus.
17–24ChorusExtra kick notes, open hats, sustained chords, and thicker bass support the hook.
25–32VerseThe hook and sustained chords drop away.
33–36BreakdownBass and snare disappear; dark plucks sit over a quiet beat.
37–44Final chorusThe full stack returns, with a fill in its last bar.
45–48OutroOnly filtered chord plucks remain.
49RestNo new notes; effect tails decay before the arrangement repeats.

The full pass lasts about 2 minutes 9 seconds, including the rest. Press Stop to end playback; the final silence is a pause inside the loop.

Change the feel

Keep the snare on beats two and four and let the kick move around it. The slower tempo and gaps in kick1 and bass1 create the relaxed pocket. bass2 adds a triangle layer for a more audible chorus bass, while chords2 fills the space behind the short plucks.

Try setcpm(86/4) for a heavier sway or setcpm(96/4) for more forward motion; match the 91 in delaytime(60/91/2) to the new tempo to keep the echo on eighth notes. Lower the chorus pad’s .gain(.035) if it masks the plucks. To hear only the chorus while editing, replace the final stack with stack(drums2, chords2, bass2, synth).

The explicit sample load and full bank names make the Linn and DMX drums work in this page’s player. See Strudel’s sample and bank reference. Keep the sample URL in single quotes: double quotes and backticks are parsed as musical mini-notation, while single quotes pass a plain string. The template’s ._pianoroll() is an editor visualization; this page uses its own Play and Stop controls, so the runnable block ends with the pattern itself.


Edit page
Share this post:

Next Post
2026 Aug Film Records