Getting started

This is how we write a basic pattern in Strudel.

  • You play the sound by pressing the play button or hitting ctrl and enter
  • You can stop the sound by hitting ctrl and .
sound("bd hh sd oh")

What happens if we put more sounds in the pattern?

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

Even more?

sound("bd hh sd oh hh bd oh sd hh sn oh bd")

The pattern becomes much faster and denser - this is because Strudel has a consistent ‘cycle’ running in the background. Any sounds in the pattern will run within that cycle, and Strudel will try to space them evenly in time. (unless we give explicit instructions for them not to - we’ll learn how to do that later).

This means that the pulse of the pattern is dictated by the number of elements

sound("hh bd sd")

vs.

sound("hh bd hh cp")

Later on when we learn how to play multiple patterns at once this gives us some fun opportunities to play with rhythm.

Why don’t you try writing a pattern with some of these other sounds:

insect wind jazz metal east crow casio space numbers

Mininotation

The green writing inside the speech marks has its own set of rules. We call this the ‘mininotation’ and it’s the core of how Strudel generates patterns.

We can speed things up with *

sound("hh")
sound("hh*4")
sound("hh*32")

Or slow them down with / - the snare only sounds every other cycle:

sound("bd sd/2") 

We can choose different sounds from a set using :. The computer starts counting at 0, so casio:0 is the same as casio.

sound("casio casio casio casio")
sound("casio casio:1 casio casio:5")

We can add a rest using ~

sound("casio casio:1 ~ casio:5")

We can create more variation with sub-sequences. We do this by breaking our steps down into mini patterns using []

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

Let’s have a look at how that looks visually:

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

You can nest sequences within sequences for dense patterns

sound("[[bd [bd bd bd bd]] bd sd] [bd cp]")

We can also schedule events across multiple cycles using <>

sound("casio <[hh cp] casio:1> ~ casio:5")

Let’s add some easy randomness using ?. Putting ? after a sound means there is a 50% probability that the sound will play.

sound("hh*8")
sound("hh*8?")

Chaining functions (and making it sound more interesting)

Let’s learn about chaining functions together. This is how we start to make more complex patterns.

There’s another way of selecting samples, using a function called n - this gives us a bit more flexibility in writing patterns.

sound("casio casio:1 casio casio:5")

We connect the functions together using .. The n function also uses the mininotation to create a pattern of numbers

n("0 1 0 5").sound("casio casio casio casio")

So far this isn’t saving us much time… but we can do better!

(This next part is a bit confusing, don’t worry too much if it doesn’t make sense right now)

We can reduce the amount of typing by specifying a pattern of n, and just specifying the sound once:

n("0 1 0 5").sound("casio")

However, because Strudel always takes the rhythm from the first pattern, this doesn’t work quite as we’d like, because Strudel thinks there’s only one event in the pattern:

sound("casio").n("0 1 0 5")

So far we’ve been looking at choosing different sounds from the folder with n. We can also choose different pitches with note.

This works in the same way as n:

note("0 1 0 5").sound("casio")

Or we can combine the two:

note("0 1 0 5").sound("casio").n("<0 2>")

And we can make use of all the mininotation we learned above in the note or n pattern

n("0 1*3 <0 [~ 7]> 5").sound("casio <space jazz>")

Strudel does its best to map the two patterns together, based on when each event in the pattern starts.

Effects

Ok, let’s try adding some effects.

sound("casio <[hh cp] casio:1> ~ casio:5")

The vowel effect is a kind of filter.

Notice again that we chain functions together using .

sound("casio <[hh cp] casio:1> ~ casio:5").vowel("a")

We can use mini-notation to create a pattern in the effect:

sound("casio <[hh cp] casio:1> ~ casio:5").vowel("<a e>")
sound("casio <[hh cp] casio:1> ~ casio:5").vowel("a e i")

Most effects take a pattern of numbers. pan moves the signal left and right:

sound("casio <[hh cp] casio:1> ~ casio:5").pan("0 1")

room adds reverb:

sound("casio <[hh cp] casio:1> ~ casio:5").room("<0 0 1 2>")

We can chain effects together:

sound("casio <[hh cp] casio:1> ~ casio:5").room("<0 0 1 2>").pan("0 1").vowel("<a o p>")

Stacking patterns

There’s an important function in Strudel called stack - it allows us to play multiple patterns at the same time

Let’s start with our drum pattern:

sound("bd hh*2 bd <~ sd>")

And our synth line from above:

sound("casio <[hh cp] casio:1> ~ casio:5").room("<0 0 1 2>").pan("0 1").vowel("<a o p>")

And play them both at the same time:

stack(
  //drums:
  sound("bd hh*2 bd <~ sd>"),
  //synth:
  sound("casio <[hh cp] casio:1> ~ casio:5").room("<0 0 1 2>").pan("0 1").vowel("<a o p>")
  )

Note that each line of code in the stack should be separated with a comma. If we separate out the lines we can add comments in, this can help us keep track of what’s going on. If our code is getting a bit messy we can break it out onto separate lines within the stack.

stack(
  //drums:
  sound("bd hh*2 bd <~ sd>"),
  //synth:
  sound("casio <[hh cp] casio:1> ~ casio:5")
  .room("<0 0 1 2>")
  .pan("0 1")
  .vowel("<a o p>")
  )

Pattern transformation

Ok, so things are starting to sound a bit better. Let’s explore some ways of creating more complex patterns.

Let’s start with a simple drum beat:

sound("bd hh*2 bd [~ sd]")

We can slow that down with slow():

sound("bd hh*2 bd [~ sd]").slow(2)

Or speed it up with fast():

sound("bd hh*2 bd [~ sd]").fast(2)

You can change the number in brackets after fast or slow to change how much we speed up or slow down by. You can even pattern that number using the mininotation!

sound("bd hh*2 bd [~ sd]").slow("1 2")

It might seem like something a bit weird is happening here - basically Strudel is switching between two versions of the pattern, the normal version and the slow version. It can be a bit hard to get your head round exactly what’s happening sometimes, but as long as you’re happy with the sound I don’t think it matters too much.

Let’s think about some other kinds of patterns - rev() lets us play a pattern backwards:

sound("casio <[hh cp] casio:1> ~ casio:5")
sound("casio <[hh cp] casio:1> ~ casio:5").rev()

Or we can use every() to apply a transformation every so many cycles:

sound("casio <[hh cp] casio:1> ~ casio:5").every(4, rev())

We can put other transformations inside the every() function:

sound("casio <[hh cp] casio:1> ~ casio:5").every(4, slow(2))

Or we can do something similar with sometimes which will apply a transformation with 50% likelihood:

sound("bd hh*2 bd <~ sd>").sometimes(rev)

Iter starts the pattern at a different point each cycle, giving us a rotational pattern:

n("1 2 3 4").sound("numbers").iter(4).slow(2)

This can lead to some nice variation across time:

stack(
  //drums:
  sound("bd hh*2 bd <~ sd>"),
  //synth:
  sound("casio <[hh cp] casio:1> ~ casio:5").room("<0 0 1 2>").pan("0 1").vowel("<a o p>").iter(4)
  )

Finally, we can apply a transformation in one speaker only using jux:

stack(
  //drums:
  sound("bd hh*2 bd <~ sd>").jux(rev()),
  //synth:
  sound("casio <[hh cp] casio:1> ~ casio:5").room("<0 0 1 2>").pan("0 1").vowel("<a o p>").iter(4)
  )

Bonus content:

Polyrhythm/polymeter

Health warning: I may have got these mixed up…

We can use stack or [,] to create polyrhythmic structures - in this case patterns of three over four

stack(
  sound("bd sd bd hh"),
  note("0 2 4").sound("casio")
  )
sound("[bd bd bd, cp cp]")

We can use {,} to create polymetrical structures - the elements of the pattern after the comma will follow the same pulse as those before the comma This can give us a sense of rotation over time.

sound("{hh cp hh cp, bd sd ~ ~ bd}")

Euclidian rhythm

We can use brackets after the name of a sound to define a Euclidian rhythm - Strudel will try to space the first number of events over the second number of steps:

sound("cp(3,8)")

We can rotate the pattern so it starts on a different step by using a third argument:

sound("cp(3,8,<0 2>)")

Try experimenting with different values.

Long samples

Here are a few functions to help you work with longer sounds.

If we play a long sample it will be triggered every cycle and so we will end up with an overlapping effect