strudel-samples.txt

A presentation on loading and manipulating samples with strudel.

Table of Contents

Samples Redux

strudel has lots of awesome ways to modulate, loop, chop, and process samples; kind of like having a Digitakt in your browser.

Playing samples

Playing a sample is the same as playing a sound; in fact, most sounds we have already played with are samples:

$: sound("xylophone_hard_ff")

Speed

speed controls the rate of playback, altering the pitch:

groove: "bd!2 [~ bd]!2".swing(2).speed("1 0.75").s()

Negative speeds reverse sample playback:

groove: "sd!2 [~ sd]!2".speed("1 -1").swing(2).s()

Cut

cut creates cut groups; only 1 sample can play at a time in any cut group.

melody: "piano*4".s().cut(1)
drums: "bd*4".s().late(1/16).cut("1 0")

Sample Banks

All the percussion we have used thus far are samples.

We can choose different sample banks to pull samples from:

groove: stack("bd!2 [~ bd]!2".swing(2), "hh*8", "~ ~ cp ~").s()
  .bank("RolandTR808")

Try changing the sample bank:

bankdescription
"RolandTR808"Iconic drum machine of 80s hip-hop sounds
"RolandTR909"Popular in techno and house
"BossDR220"Simplified Roland TR707
"OberheimDMX"Influential 1980s drum machine
"LinnDrum"1980s drum machine targeting realistic sound

The bank function works by putting the name of the sample bank with an _ at the front of sample names.

bank: s("bd*2").bank("RolandTR808")

explicit: s("RolandTR808_bd*2").late(1/4)


Find sample banks in the drum machine tab of the sounds window.


Not all sample banks support the same percussion sounds!

Velocity

Changing the velocity of a sample changes its loudness.

d1: "bd*4".s().bank("RolandTR909")
  .velocity(range(0.6, 1, sine))

Begin & End

Strudel can start and end samples in different spots:

$: n("0*2").s("numbers").late(1/16).begin("0 0.2").cut(0)

$: "<bd sd>*8".s().end("0.1 0.5 0.75 1").slow(2)

Filter

Strudel also supports filters:

$: "sd*8".s().bank("RolandTR909")
  .hpf(range(0, 2000, sine).slow(8))
  .hpq("<0 0 10>") // Resonance
  .hpattack("<0 0.1 1 4 -4>".slow(2)) // Envelope attack

Filter TypeDescription
hpfhigh-pass filter
lpflow-pass filter
bpfband-pass filter
djfdj-filter (try different values from 0 to 1.0)

Loading Samples

Strudel can load samples with a custom name from a URL:

samples({ conga: [ 'https://glfmn.io/samples/menegass-conga-7.wav' ]});

$: "conga*2".s()

Variations

Samples can have variations; 2 ways to select the variations:

  • Pass a pattern of sample indices into the n function
  • Append the index to the sample name with :
samples({
  conga: [
    'https://glfmn.io/samples/menegass-conga-7.wav',
    // CC-BY 4.0: https://freesound.org/people/MrRentAPercussionist/sounds/455509/ 
    'https://glfmn.io/samples/mrrentapercussionist-congas-muted-slap.wav'
  ]
});

$: cat("conga:<0 1>*2".s(), "conga*2".s().n("0 1"))

Sample Packs

One can make sample packs in strudel using a special strudel.json file.

{
  "_base": "https://glfmn.io/samples/",
  "conga": [ "menegass-conga-7.wav", "mrrentapercussionist-congas-muted-slap.wav" ],
  "tumbao": [ "stomachache-bongopattern145bpm" ],
  "train": [ "nnus_train_whistle1.wav" ]
}
_base
A URL that gets added to the beginning of every other URL in the file.

Github

Strudel has a special shorthand from loading samples from github repositories.

samples('github:path/to/repo');

Longer samples

By default, samples play at normal speed until the end. For long samples, this causes chaos.

Overlap

Try playing this sample:

samples({
  tumbao: ['https://glfmn.io/samples/stomachache-bongopattern145bpm.wav']
});

$: "tumbao".s()

cut groups can mitigate the chaos. Try adding .cut(1).

Slow

We can give more space for the sample to play out with slow:

samples({
  tumbao: ['https://glfmn.io/samples/stomachache-bongopattern145bpm.wav']
});

$: "tumbao".s().cut(1).slow(2)

Speed

We can speed up the sample to hear more of it:

samples({
  tumbao: ['https://glfmn.io/samples/stomachache-bongopattern145bpm.wav']
});

$: "tumbao".s().cut(1).slow(2).speed(1.25)

setcps

We can even try changing strudels tempo:

samples({
  tumbao: ['https://glfmn.io/samples/stomachache-bongopattern145bpm.wav']
});

setcps(1/2);

$: "tumbao".s().cut(1).slow(2).speed(1.25)

setcps sets cycles-per-second. A lower cps results in a faster tempo.


We can use a formula to convert bpm to cps:

const bpm = 120;
setcps(bpm/60/4);

LoopAt

loopAt speeds up the sample so that it loops perfectly in n cycles.

samples({
  tumbao: ['https://glfmn.io/samples/stomachache-bongopattern145bpm.wav']
});

setcps(125/60/4)

$: "tumbao".s().loopAt(5)

Combining knowledge of sample length and strudel's tempo is key!

# fit

fit makes the pattern perfectly fit its event duration:

$: n("<0 [0 1]>").s("numbers").end("<1!2 0.5>/2").fit()

Chopping samples

Strudel has lots of fun and gnarly ways of chopping up samples and making them feel new again.

Breakbeats!

But first, let's get some break beats :)

samples('github:yaxu/clean-breaks');

setcps(120/60/4)

$: s("amen").loopAt(4)

Chop

chop seamlessly splits the sample into multiple parts.

samples('github:yaxu/clean-breaks');

setcps(144/60/4)

$: s("amen").chop(8).color("<blue red>").loopAt(4)
  ._punchcard({ labels: 1 })

chop + more

Once the sample is chopped, we can start to transform it with patterns:

samples('github:yaxu/clean-breaks');

setcps(120/60/4);

$: s("groove").chop(32).loopAt(2)
  .velocity(sine.range(0.5, 1).fast(2))
  .mul(speed("0.75 1.5 0.9 1"))
  ._punchcard({ labels: 1 })

striate

Instead of chopping, we can striate:

$: s("numbers:0 numbers:1 numbers:2 numbers:3").cut(1)
  .color("red white purple brown")
  .every(2, striate(4))
  ._punchcard({ labels: 1 })

Repeats the pattern n times, but only playing the 1st nth of the sample the first time, the 2nd nth the next time, and so on.

Jam time

samples('github:yaxu/clean-breaks');

// Downtempo
setcps(80/60/4);

$: s("amen").loopAt(4).chop(32).gain(0.8)

Fin.