Skip to content

Instantly share code, notes, and snippets.

@marcoonroad
Last active January 26, 2026 12:17
Show Gist options
  • Select an option

  • Save marcoonroad/87605752c9b67c4b09f367774317a3f5 to your computer and use it in GitHub Desktop.

Select an option

Save marcoonroad/87605752c9b67c4b09f367774317a3f5 to your computer and use it in GitHub Desktop.
Angelcore EDM sample of stretched leads made with Strudel REPL
// angelcore sample(s)
const leads = (isUpper) =>
n(
!isUpper ?
`< 61 61 63*2 - 63 65 61*2 - 61*2 - 63 64 - - - 72*2 - >` :
`< - - - 64*2 - - - - - - - - 67 69 71*2 - 73 >`
)
.cpm(135/4)
.fast(6)
const SuperSaw = (beat, option) => {
// NOTE: default built-in supersaw from Strudel has a lot of muddy
// whenever used in pitch bend / legato riffs contexts, so we made
// other custom options for better fine-tuning and control of sound
if (option < 0)
return beat.s("supersaw")
const DEFAULT_OCTAVE = 3
if (option === 0)
return beat.s("saw").layer(
x => x,
x => x.sub(.2),
x => x.add(.2)
).gain(.15).octave(DEFAULT_OCTAVE)
if (option === 1)
return stack(
beat.s("saw").sub(0.0).velocity(0.5),
beat.s("saw").sub(.03).velocity(0.4), beat.s("saw").add(.03).velocity(0.4),
beat.s("saw").sub(.08).velocity(0.3), beat.s("saw").add(.08).velocity(0.3),
beat.s("saw").sub(.14).velocity(0.2), beat.s("saw").add(.14).velocity(0.2),
beat.s("saw").sub(.21).velocity(0.1), beat.s("saw").add(.21).velocity(0.1)
)
.pan(
stack(
sine.range(-0.8, -0.2),
sine.range(0.2, 0.8)
)
)
.gain(.15).octave(DEFAULT_OCTAVE)
const drift = sine.slow(1).range(-2, 2)
if (option === 2)
return beat.s("saw").layer(
x => x.add(0).velocity(0.6),
x => x.sub(drift.add(7).div(100)).velocity(.4),
x => x.add(drift.add(7).div(100)).velocity(.4),
x => x.sub(.12).velocity(.2),
x => x.add(.12).velocity(.2)
)
.gain(0.2).octave(DEFAULT_OCTAVE)
if (option === 3)
return beat.s("saw").layer(
x => x.add(0.0).pan(0.5).velocity(0.5),
x => x.add(.04).pan(0.4).velocity(0.35), x => x.sub(.04).pan(0.6).velocity(0.35),
x => x.add(.16).pan(0.7).velocity(0.25), x => x.sub(.16).pan(0.3).velocity(0.25),
x => x.add(.32).pan(0.2).velocity(0.20), x => x.sub(.32).pan(0.8).velocity(0.20),
x => x.add(.64).pan(0.9).velocity(0.10), x => x.sub(.64).pan(0.1).velocity(0.10)
).gain(0.3).octave(DEFAULT_OCTAVE)
// NOTE: more dense supersaw with sub-square waves
if (option === 4)
return beat.layer(
x => x.s("square").sub(1.00).velocity(.40),
x => x.s("square").sub(3.00).velocity(.30),
x => x.s("square").sub(6.00).velocity(.20),
x => x.s("square").sub(12.0).velocity(.10),
x => x.s("square").sub(18.0).velocity(.05),
x => x.s("saw").add(0.75).velocity(.10),
x => x.s("saw").add(0.50).velocity(.35),
x => x.s("saw").add(0.25).velocity(.60),
x => x.s("saw").add(0.00).velocity(.70),
x => x.s("saw").sub(0.25).velocity(.60),
x => x.s("saw").sub(0.50).velocity(.35),
x => x.s("saw").sub(0.75).velocity(.10),
).gain(.35).octave(DEFAULT_OCTAVE - 1)
const sawCenter = beat.s("saw").add(0.0).velocity(0.50)
const sawPlusLight = beat.s("saw").add(.08).velocity(0.35)
const sawMinusLight = beat.s("saw").sub(.08).velocity(0.35)
const sawPlusWide = beat.s("saw").add(.18).velocity(0.25)
const sawMinusWide = beat.s("saw").sub(.18).velocity(0.25)
if (option === 5)
return stack(
sawCenter,
sawPlusLight, sawMinusLight,
sawPlusWide, sawMinusWide
).gain(0.3).octave(DEFAULT_OCTAVE)
}
const upperLeads = () =>
SuperSaw(leads(1), 4)
.legato(.666)
.penv(1)
.vib(.333)
.room(.333)
.delay(.333)
.chorus(.333)
.lpf(2500)
.hpf(500)
.color("purple")
const lowerLeads = () =>
leads(0)
.s("square")
.legato(.777)
.add(3) // NOTE: detuning 3 whole semitones to above
.penv(-1)
.chorus(.111)
.room(.111)
.delay(.111)
.vib(.111)
.gain(.666)
.lpf(1200)
.hpf(200)
.color("green")
// NOTE: different orbits due differents reverbs/delays
$: upperLeads().orbit(1)._punchcard()
$: lowerLeads().orbit(2)._punchcard()
// creating angelcore-like lead from synth brass instrument
// - unison detuning (with stereo knob/spread) and chorus
// - higher pitches/octaves
// - low brightness (low-pass / cutoff)
// - bitcrushing and soft distortion
// - small cents/semitones pitch bend down
// - dynamic compression
// - delay/echo and reverberation
$: note("<- d3 - <c3 e3*2> - d3 - c3@2 b2 d3@2>".fast(12))
.sound("gm_synth_brass_2")
.layer(
x => x.add(0.21).velocity(0.25).pan(0.8),
x => x.add(0.09).velocity(0.30).pan(0.2),
x => x.add(0.03).velocity(0.35).pan(0.8),
x => x.add(0.00).velocity(0.40).pan(0.5),
x => x.sub(0.03).velocity(0.35).pan(0.2),
x => x.sub(0.09).velocity(0.30).pan(0.8),
x => x.sub(0.21).velocity(0.25).pan(0.2)
)
.crush(8)
.soft("3:0.125")
.transpose(18)
.legato(0.5)
.penv(-0.25)
.gain(0.1)
.cutoff(1000)
.resonance(5)
.chorus(0.5)
.every(3, rev)
.delay(0.2)
.room(0.1)
.compressor("-15:20:5:0.001:0.125")
.orbit(3)
.postgain(0.75)
.cps(90/60/4)
._pianoroll()
@marcoonroad
Copy link
Author

NOTE: only works on recent engines of Strudel where both .add() and .sub() (and even .transpose()) support microtonal (cents) semitones, e.g 20 cents being 0.2 semitones. Older versions, and some VSCode plugins included, doesn't handle that well and instead round to closest/nearest integer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment