bone.recipes



Strudel cheat sheet

Getting started

Visit https://strudel.cc/ and edit the code in the REPL.

Play the script with Ctrl + Enter. Also, after making changes to the code, use this shortcut to update the generated audio.

Stop the script with Ctrl + ..

Read their docs here.

Basics

Playing simple sounds

Make a chiptunes-y "beep" sound once per unit of time:

sound("casio")

Try replacing "casio" with these other sound names:

Making simple patterns

To make a simple pattern of sounds, simply separate sound names by spaces. For example:

sound("casio crow")

You may notice that these sounds are played twice as fast as those played by sound("casio"). That's because, by default, Strudel subdivides the duration of the time unit by the number of sounds it needs to play. So if it only has to play 1 sound, then that sound will be allowed to take up the full duration of the time unit. Or if it must play 2 sounds, then those sounds will each be allowed to take up half a unit's worth of time. As you can probably guess, then, the following code will cause sounds to be played 4 times as fast as sound("casio"):

sound("casio crow metal east")

Rests can be added with - or ~:

sound("casio ~ crow ~")

Selecting specific samples

Some sounds contain multiple samples. Using sound("casio"), for example, is the same as using the 0th sample in the set and is identical to sound("casio:0"). Replace 0 with other numbers to access other samples. For example:

sound("casio:3")

Playing drum samples

Strudel uses the following acronyms to represent drum sounds:

So, for example:

sound("bd hh sd oh")

Changing sound banks

We can change which sound bank is used to play samples like this:

sound("bd hh sd oh").bank("RolandTR909")

Working with time

As mentioned above, the default behavior of Strudel is to subdivide each time unit by the number of sounds it needs to play. However, this behavior can be overridden by using angle brackets (< and >).

First, let's start with this pattern:

sound("bd bd hh bd rim bd hh bd")

We'll wrap it in angle brackets:

sound("<bd bd hh bd rim bd hh bd>")

Instead of playing 8 sounds in a single time unit, the above pattern causes each individual sound to receive a full time unit (which is awfully slow)! We can speed it back up, though, by "multiplying" the pattern by some number:

sound("<bd bd hh bd rim bd hh bd> * 8")

Now, even though the above pattern — which has 8 sounds, wrapped in angle brackets, and then made 8 times as fast — ends up sounding exactly the same as the original version (with no angle brackets), there's one significant difference: When using angle brackets, time units are no longer subdivided equally among the given sounds. In the above pattern, each sound is allowed to last for 1/8 of a time unit. If we added another sound to the pattern without angle brackets, then each sound would be allowed to last for 1/9 of a time unit. But if we add another sound to the pattern with angle brackets, each sound still only lasts for 1/8 of a time unit — even though 9 sounds would be present in the pattern!

NOTE: At least, that's my naive understanding as I write these notes. But I've just started with Strudel, and there may be more nuance or better understanding yet to come.

Finally, we can set the tempo (in cycles per minute) using setcpm:

setcpm(90 / 4)
sound("<bd bd hh bd rim bd hh bd> * 8")

Creating sub-sequences

A sequence, as we've seen above, is (so far) just a list of sounds separated by spaces:

sound("bd hh sd oh")

We can create sub-sequences (i.e., nested sequences) using brackets:

sound("bd [hh hh] sd oh")

In the same way that sequences without angle brackets stretch to fill a unit of time, so sequences within (regular) brackets also stretch to fill a unit of time. In the above example, the sub-sequence [hh hh] is given the same amount of time as bd, sd, and oh.

Playing sequences simultaneously

Sequences separated by commas will be played simultaneously. For example:

sound(`
  bd [[rim rim] hh] bd cp,
  casio crow [east east east] [metal metal]
`)

NOTE: Notice the use of the multi-line string made with back-ticks (```).

Playing only by sample number

If we know we'll only be using one sound for a sequence, we can make things a bit more readable by replacing all of the sound names —

sound("jazz:0 jazz:1 [jazz:4 jazz:2] jazz:3*2")

— with the n function (followed by .sound):

n("0 1 [4 2] 3*2").sound("jazz")

Playing by pitch

To play by pitch, we use the note function:

// mary had a little lamb
note(`<
  e5 d5 c5 d5
  e5 e5 e5 ~
  d5 d5 d5 ~
  e5 g5 g5 ~
  e5 d5 c5 d5
  e5 e5 e5 e5
  d5 d5 e5 d5
  c5 ~  ~  ~
> * 4`)