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.
Make a chiptunes-y "beep" sound once per unit of time:
sound("casio")
Try replacing "casio" with these other sound names:
"insect""wind""jazz""metal""east""crow""space""numbers"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 ~")
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")
Strudel uses the following acronyms to represent drum sounds:
"bd" = bass drum"sd" = snare drum"rim" = rimshot"hh" = hihat"oh" = open hihat"lt" = low tom"mt" = middle tom"ht" = high tom"rd" = ride cymbal"cr" = crash cymbalSo, for example:
sound("bd hh sd oh")
We can change which sound bank is used to play samples like this:
sound("bd hh sd oh").bank("RolandTR909")
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")
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.
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 (```).
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")
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`)