strudel is a browser port of tidalcycles
here are some notes from playing with it:
the foundational unit of time is a cycle. CPM = cycles per minute.
the default CPM is 120, which means that a cycle lasts 0.5 seconds.
any pattern written in quotes will play in one cycle
if you surround that pattern with angle brackets, each note will play in one cycle's length
The order you chain methods to set a pattern matters
// Creates a pattern with 3 events per cycle
note("1 2 3")
// preserves this 3-event structure
// uses the "piano" sound for each event
.sound("piano");open in strudel ↗// Creates a pattern with 1 event per cycle
sound("piano")
// only the "1" from "1 2 3" is used
.note("1 2 3");open in strudel ↗calling setcpm() is a one-off thing. it
doesn't reset if you delete the line and re-execute
there are lots of ways to do similar things with different methods, which causes concepts to blur quite a bit. mininotation is another thing.
using the "numbers" sample set is quite a useful way to understand how notes and rhythms are structured.
$: s("numbers").n("<0 1 2 3 4 5 6 7 8>");open in strudel ↗.begin() to start a sample later (i.e. to
remove dead air)
.early() to offset a pattern for cool
phases
you can use
ribbon
to create a buildup
all((x) => x.ribbon(1 / 2));open in strudel ↗all((x) => x.ribbon(1 / 4));open in strudel ↗all((x) => x.ribbon(1 / 8));open in strudel ↗Single quotes and double-quotes do different things
"1,2,3" (evaluated as a pattern) is different
from '1,2,3' (evaluated as a string)random snippets, techniques & scratches
cool beat
samples('github:switchangel/breaks');
samples('github:switchangel/pad');
samples('github:tidalcycles/Dirt-Samples');
setcpm(160 / 4);
$: s("breaks:3/2")
.fit()
.scrub(irand(16).div(16).seg(8).ribbon(2, 8))
.o(4);
$: s("swpad:7")
.scrub(irand(4).div(4).seg(2).ribbon(0, 2))
.gain(0.5)
.bpf(2000);
$: note("<C3 [E3 G3] A3 B3 D4>*[2, 2.01]")
.scale("C:minor")
.sound("piano")
.gain(1)
.room(1);
$: n(run(8).add(1))
.sound("birds")
.slow(10)
.speed(0.7)
.room(2)
.gain(2)
.delay(0.5)
.delayspeed(0.1);
$: sound("bd*2")
.bank("tr808")
.gain(2)
.duck(1)
.o(2)
.duckatt(0.5);
$: sound("<rd rd rd - - - >*12").gain(0.5).o(3);
$: sound("xylophone_soft_ff")
.note("C3 D3 [B3 | A3 | G3]")
.euclid(3, 5)
.gain(2)
.scale("C:major");
$: sound("xylophone_soft_ff")
.note("<G1 [G2 | G4]>")
.euclid(2, 7)
.gain(2)
.scale("C:major");
$: n("<4! 11 24 18>*3").sound("alphabet").hpf(2000).o(3);
$: sound("- [rim:1 | rim:2] rim:5 -")
.o(4)
.sometimes((x) => x.ply(3))
.dist("2:.2")
.hpf(1000)
.room(0.5);
$: sound("hh*16")
.gain(4)
.lpf(sine.range(4000, 10000))
.gain(0.5);
$: sound("sine")
.note("<C2, E3, G2> | <F3, A3, C3>")
.gain(4);
all((x) => x.hpf(1000));open in strudel ↗Arrange / stack
const pattern1 = sound("bd - - - bd bd - -");
const pattern2 = sound("bd - bd bd bd - - -");
const pattern3 = note("<C2 C3>*8");
stack(
arrange([4, pattern1], [2, pattern2]),
arrange([4, silence], [2, pattern3]),
);open in strudel ↗quick sample chopping
sound("numbers").fit().scrub(irand(8).div(8).seg(16));open in strudel ↗snare rush
sound("rim:2*16")
.mask(irand(2).segment(8).rib(1, 1))
.penv(irand(16).sub(8).seg(8).rib(0, 1))
.patt(1)
.decay(0.2)
.dist("2:.2");
// or for full random
// .degradeBy(0.5)open in strudel ↗jai paul
$: note(
irand(16)
.scale("C:dorian")
// or
// .scale("<A:pentatonic, E:pentatonic>")
.segment(8)
.rib(6, 3)
.sub(24),
)
.sound("gm_celesta")
.lpf(200)
.mask(rand.segment(8).gt(0.3).rib(0, 2))
.dist("4:.2")
.ply("2")
.delay(0.2);open in strudel ↗cool hats
setcpm(160 / 4);
samples('github:yaxu/clean-breaks');
$: sound("swat/2").fit().delay(1);open in strudel ↗footwork
setcpm(160 / 4);
samples('github:switchangel/pad');
$: s("[hh hh oh oh]*4").gain(0.8).dec(0.1);
$: s("bd, swpad:1")
.begin(stack("0", rand.range(0, 0.5).seg(16).rib(2, 1)))
.speed("<1!3 [.6 .7 .8 .9]>/4")
.beat("0,6,12", 16)
.fast(2)
.dec(1)
.rel(0.5)
.dist("4:.3");
$: s("rim")
.beat("16 | [16,22,[28,30]?]", 32)
.gain("5")
.speed(1.3)
.dec(0.05)
.hpf(400);
$: s("tr808_rim:2*16").mask(irand(2).seg(16).ribbon(0, 1));open in strudel ↗pads
$: s("gm_recorder")
.note("<E3 G2 D3 G2>")
.scale("G:pentatonic")
.dist(2)
.att(1 / 2)
.rel(3 / 2)
.room(1);
$: s("sine")
.note("<E3 G2 D3 G2>".trans(-12))
.scale("G:pentatonic")
.gain(1)
.att(1 / 2);
// $: note("<[B4 A4 D5]>")
$: note("<[B4 A4 D5], [D6 B5 A5]>")
.slow(6)
.s("harp")
.scale("G:pentatonic")
.dist(2)
.rel(2)
.dec(2)
.penv("<4 -4>/2")
.patt(1 / 4);open in strudel ↗busy looping melodies
const bSeed = "<0 0 0 3>".add("<2 1>/4");
const notes = note(
perlin.range(0, 7).seg(16).rib(bSeed, 1).sub(6),
)
// .mask(irand(2).seg(8).rib(2,1))
.scale("C:major");
$: notes
.sound("xylo")
.decay(1 / 8)
.transpose("12");
$: notes.sound("mallets").late(0).dec(0.1).release(0.1);
$: sound("hh*8").fit().gain(0.2).hpf(3000);
$: sound("bd*4").lpf(400);open in strudel ↗weird granular synth
$: sound("bd bd bd bd - bd - -")
.ply(8)
.freq(perlin.range(0, 1000));open in strudel ↗next part helicopter (drum over this?)
$: note("<C2!4 A0!4>*4".add(28))
.sound("sine")
.gain(2)
.decay(1)
.o(2);
$: note("<C2!4 A0!4>*4")
.sound("sine")
.gain(2)
.decay(1)
.o(2);
$: sound("bd*15")
.lpf(slider(1000, 200, 1000))
.duck(2)
.duckatt(0.001);
$: sound("hh*8").hpf(2000);
$: sound("- - - sd").hpf(2000);open in strudel ↗dazed and confused and beading
$: note("<0 1 2 3 4 5 6 7>*2".add(30))
.sound("sine")
.revv()
.release(2);
$: sound("rd - rd rd").bank("vintage").gain(0.2).swing(2);
$: sound("bd*2").bank("vintage");open in strudel ↗deacon
setcpm(70);
$: stack(
sound("bd:3 -").lpf(180).dist("2:.3"),
).bank("vintage")
$: sound("hh*4").bank("vintage").gain("<.1 .2>*2").dec(.4)
$: sound("bd").slow(2).bank("vintage").duck(2).duckatt(.2)
$: sound("<vintage_rd:3 vintage_rd:2!2>*6").gain("<.2 .1@2>*6".add(slider(0,-0.3,4,.1)))
$: sound("triangles:2*6").mask(irand(2).seg(6).rib(1,4)).pan(rand.range(0,1)).delay(.3).dt(1).gain(4)
let notes = irand(8).seg(8).rib(20,200)
$: note(notes)
.struct("<x x@2 x@3>*3")
.sound("sax_vib")
.dec(3)
.scale("F#:pentatonic, C#:major")
.o(2)
$: note(notes.sub(10)).struct("<x@2>").sound("sine").scale("F#:pentatonic")open in strudel ↗eyelash
samples('github:switchangel/breaks');
samples('http://localhost:5432');
setcpm(160 / 4);
const beat = "<1 0 0 1 0 1 0 0>*16";
// $: sound("breaks/2").fit().scrub(irand(16).div(16).seg(16).rib(2,1)).o(2).hpf(2000).gain(slider(1,0,2,.1))
$: sound("bd").dist(2).o(2);
$: sound("bd").struct(beat).lpf(200).dist(2).o(2);
$: sound("- sd").gain(2).speed(2.2).o(2);
// $: sound("- [sd [[sd sd sd] | ~ ] ]").gain(1.5).speed(2.2)
// $: sound("sd*16").bank("vintage").mask(irand(2).seg(16).rib(0,4)).gain(.3)
// $: sound("hh*16").gain("<.3 .5>*16").dec(.04).hpf(perlin.range(1000,4000))
// $: sound("<- hh hh hh>*16").dec(.1).gain("<.3 .7 .3>*16")
// $: sound("ocean:8")
// .freq("<65 76>/2")
// .struct(beat)
// .begin(rand.segment(1).slow(2))
// // .begin(rand.seg(8).rib(4,2))
// .dec(3/8)
// .room(.5)
// $: sound("saw").note("<[C4, D5] [C3, F5, A5]>/2").att(1).vib(4).vibmod(.2).release(2).gain(.5)
// $: sound("tri").duck(2).duckatt(10).duckdepth(1).gain(0).duckons(0).sus(10)open in strudel ↗i've been
setcpm(160 / 4);
$: sound("<ocean:3*2 [ocean:4 | ocean:3]>")
.fit()
.late(0.5)
.room(1)
.chop(8)
.dec(0.2)
.phaser(2)
.gain(2)
.o(2);
$: note("<[C,E,G] [A,C,E]>/4")
.sound("tri")
.tremdepth(2)
.tremolosync("<8 12 16>")
.trem(3)
.tremshape("sine")
.gain(3)
.o(2);
$: stack(
sound("bd*4").duck(2).duckatt(0.2),
sound("hh*16").gain("<.3 .2 .3>*16"),
sound("sd")
.late(1 / 2)
.sometimes((x) => x.delay(1.4))
.dist("4:.3")
.clip(1 / 16),
).bank("vintage");open in strudel ↗control keys
$: sound("hh*8").whenKey("Control:j", (x) => x.gain(2));open in strudel ↗fills
$: sound("hh*8").when("<0@3 1>", (x) => x.fast(2));
// or
$: note("E3*4")
.sound("sine")
.rel(0.1)
.dec(0.5)
.every(2, (x) =>
x
.euclid(7, 16)
.note("A2 C3 D3 E3")
.off(1 / 16, (x) => x.add(note(7))),
);
// or override struct
$: note("E3*4")
.struct("x - - x - - x - - x - - x - - x")
.every(2, (_) => note("A2 C3 D3 E3").struct("<x ->*16"))
.sound("sine")
.rel(0.1)
.dec(0.5);open in strudel ↗jungle gym
$: stack(
sound("xylo*3")
.note(irand(4))
.scale("C4:minor:pentatonic"),
sound("xylo*4")
.note(irand(8))
.scale("C4:minor:pentatonic"),
sound("mallets")
.note(irand(5))
.scale("C2:minor:pentatonic")
.lpf(600),
)
.rib("<1 2 3 4>/2".add(4), "[0.5 | 0.75 | 1 | .25]/2")
.gain(0.25);open in strudel ↗random chords
$: irand(12)
.seg(8)
.rib(0, 2)
.add("[3,5,7] | [0,2,9]")
.fast(4)
.scale("C3:minor")
.note()
.struct("<x - - x - - - ->*16")
.sound("triangle")
.release(1);
$: sound("r8_rd*6").gain(0.2);
$: sound("<- hh hh>*12");
$: sound("<- sine!2>*12").note("[C2]").gain(4);
$: sound("bd").lpf(200).gain(2);
$: sound("akaixr10_tb*16")
.mask(irand(2))
.ply(2)
.gain(rand.range(0.2, 0.4));
$: sound("gm_bird_tweet:3").delay(2).delayt(0.1).delayfb(2);open in strudel ↗