tutorial updates

This commit is contained in:
Jack Armitage 2022-12-25 16:21:18 +00:00
parent 823115c4ec
commit 858f4f74b3
14 changed files with 744 additions and 390 deletions

View file

@ -6,10 +6,13 @@ layout: ../../layouts/MainLayout.astro
import { MiniRepl } from '../../docs/MiniRepl';
import { JsDoc } from '../../docs/JsDoc';
# Mini Notation
# Mini-notation
Similar to Tidal Cycles, Strudel has an embedded mini language that is designed to write rhythmic patterns in a short manner.
Before diving deeper into the details, here is a flavor of how the mini language looks like:
Similar to [Haskell Tidal Cycles](https://tidalcycles.org/docs/), Strudel has an "embedded mini-notation" (also called a [domain-specific language, or DSL](https://en.wikipedia.org/wiki/Domain-specific_language)) that is designed for writing rhythmic patterns using little amounts of text.
If you've seen any Tidal code before, you may have noticed the mini-notation and wondered what it's all about.
It's one of the main features of Tidal, and although it might look like a strange way to notate music and other patterns, you will soon see how powerful it can be.
Before diving deeper into the details, here is a flavour of how the mini-notation looks like:
<MiniRepl
client:idle
@ -36,92 +39,197 @@ Before diving deeper into the details, here is a flavor of how the mini language
]/16\`)`}
/>
The snippet above is enclosed in backticks (`), which allows you to write multi-line strings.
You can also use double quotes (") for single line mini notation.
Note that the snippet above is enclosed in backticks (`), which allows you to write multi-line strings.
## Sequences
You can also use regular double quotes (`"`) for single line mini-notation, as we have done already.
# Sequences of events in a cycle
We can play more notes by separating them with spaces:
<MiniRepl client:only="react" tune={`note("e5 b4 d5 c5")`} />
<MiniRepl client:idle tune={`note("e5 b4 d5 c5")`} />
Here, those four notes are squashed into one cycle, so each note is a quarter second long.
Try adding or removing notes and notice how the tempo changes!
## Division
<MiniRepl client:idle tune={`note("e5 b4 d5 c5 e5 b4 d5 c5")`} />
We can slow the sequence down by enclosing it in brackets and dividing it by a number:
Note that the overall duration of time does not change, and instead each note length descreases.
This is a key idea, as it illustrates the 'Cycle' in TidalCycles!
<MiniRepl client:only="react" tune={`note("[e5 b4 d5 c5]/2")`} />
Each space-separated note in this sequence is an _event_.
The time duration of each event is based on the speed or tempo of the cycle, and how many events are present.
Taking the two examples above, we have four and eight events respectively, and since they have the same cycle duration, they each have to fit their events inside the same amount of time.
This is perhaps counter-intuitive if you are used to adding notes in a sequencer or piano roll and the overall length increasing.
But, it will begin to make sense as we go through more elements of mini-notation.
# Division
We can slow the sequence down by enclosing it in brackets and dividing it by a number (`/2`):
<MiniRepl client:idle tune={`note("[e5 b4 d5 c5]/2")`} />
The division by two means that the sequence will be played over the course of two cycles.
You can also use decimal numbers for any tempo you like.
You can also use decimal numbers for any tempo you like (`/2.75`).
## Angle Brackets
<MiniRepl client:idle tune={`note("[e5 b4 d5 c5]/2.75")`} />
Using angle brackets, we can define the sequence length based on the number of children:
# Angle Brackets
<MiniRepl client:only="react" tune={`note("<e5 b4 d5 c5>")`} />
Using angle brackets `<>`, we can define the sequence length based on the number of events:
<MiniRepl client:idle tune={`note("<e5 b4 d5 c5>")`} />
The above snippet is the same as:
<MiniRepl client:only="react" tune={`note("[e5 b4 d5 c5]/4")`} />
<MiniRepl client:idle tune={`note("[e5 b4 d5 c5]/4")`} />
The advantage of the angle brackets, is that we can add more children without needing to change the number at the end.
The advantage of the angle brackets, is that we can add more events without needing to change the number at the end.
## Multiplication
<MiniRepl client:idle tune={`note("<e5 b4 d5 c5 e5>")`} />
Contrary to division, a sequence can be sped up by multiplying it by a number:
<MiniRepl client:idle tune={`note("<e5 b4 d5 c5 e5 b4>")`} />
<MiniRepl client:only="react" tune={`note("[e5 b4 d5 c5]*2")`} />
This is more similar to traditional music sequencers and piano rolls, where adding a note increases the perceived overall duration.
The multiplication by 2 here means that the sequence will play twice a cycle.
# Multiplication
## Bracket Nesting
Contrary to division, a sequence can be sped up by multiplying it by a number using the asterisk symbol (`*`):
To create more interesting rhythms, you can nest sequences with brackets, like this:
<MiniRepl client:idle tune={`note("[e5 b4 d5 c5]*2")`} />
<MiniRepl client:only="react" tune={`note("e5 [b4 c5] d5 [c5 b4]")`} />
The multiplication by two here means that the sequence will play twice a cycle.
## Rests
As with divisions, multiplications can be decimal (`*2.75`):
The "~" represents a rest:
<MiniRepl client:idle tune={`note("[e5 b4 d5 c5]*2.75")`} />
<MiniRepl client:only="react" tune={`note("[b4 [~ c5] d5 e5]")`} />
Actually, this is not true, but this will be [fixed](https://github.com/tidalcycles/strudel/issues/314) :)
## Parallel
# Subdividing time with bracket nesting
Using commas, we can play chords:
To create more interesting rhythms, you can _nest_ or _enclose_ sequences (put sequences inside sequences) with brackets `[]`, like this:
<MiniRepl client:only="react" tune={`note("g3,b3,e4")`} />
Compare the difference between the following:
To play multiple chords in a sequence, we have to wrap them in brackets:
<MiniRepl client:idle tune={`note("e5 b4 c5 d5 c5 b4")`} />
<MiniRepl client:idle tune={`note("e5 [b4 c5] d5 c5 b4")`} />
<MiniRepl client:idle tune={`note("e5 [b4 c5] d5 [c5 b4]")`} />
<MiniRepl client:idle tune={`note("e5 [b4 c5] d5 [c5 b4 d5 e5]")`} />
<MiniRepl client:idle tune={`note("e5 [b4 c5] d5 [c5 b4 [d5 e5]]")`} />
<MiniRepl client:only="react" tune={`note("<[g3,b3,e4] [a3,c3,e4] [b3,d3,f#4] [b3,e4,g4]>")`} />
What's going on here? When we nest/enclose multiple events inside brackets (`[]`), their duration becomes the length of one event in the outer sequence.
## Elongation
This is a very simple change to make, but it has profound consequences.
Remember what we said earlier about how the cycles in tidal stay the same length, and the individual event lengths are divided up in this cycle?
Well, what this means is that in TidalCycles, not only can you divide time any way you want, and you can also subdivide time any way you want!
# Rests
The "~" represents a rest, and will create silence between other events:
<MiniRepl client:idle tune={`note("[b4 [~ c5] d5 e5]")`} />
# Parallel / polyphony
Using commas, we can play chords.
The following are the same:
<MiniRepl client:idle tune={`note("[g3,b3,e4]")`} />
<MiniRepl client:idle tune={`note("g3,b3,e4")`} />
But to play multiple chords in a sequence, we have to wrap them in brackets:
<MiniRepl client:idle tune={`note("<[g3,b3,e4] [a3,c3,e4] [b3,d3,f#4] [b3,e4,g4]>")`} />
# Elongation
With the "@" symbol, we can specify temporal "weight" of a sequence child:
<MiniRepl client:only="react" tune={`note("<[g3,b3,e4]@2 [a3,c3,e4] [b3,d3,f#4]>")`} />
<MiniRepl client:idle tune={`note("<[g3,b3,e4]@2 [a3,c3,e4] [b3,d3,f#4]>")`} />
Here, the first chord has a weight of 2, making it twice the length of the other chords. The default weight is 1.
## Replication
# Replication
Using "!" we can repeat without speeding up:
<MiniRepl client:only="react" tune={`note("<[g3,b3,e4]!2 [a3,c3,e4] [b3,d3,f#4]>")`} />
<MiniRepl client:idle tune={`note("<[g3,b3,e4]!2 [a3,c3,e4] [b3,d3,f#4]>")`} />
In essence, the `x!n` is like a shortcut for `[x*n]@n`.
## Euclidian
# Mini-notation review
Using round brackets, we can create rhythmical sub-divisions based on three parameters: beats, segments and offset.
The first parameter controls how may beats will be played.
The second parameter controls the total amount of segments the beats will be distributed over.
The third (optional) parameter controls the starting position for distributing the beats.
One popular Euclidian rhythm (going by various names, such as "Pop Clave") is "(3,8,0)" or simply "(3,8)",
resulting in a rhythmical structure of "x ~ ~ x ~ ~ x ~" (3 beats over 8 segments, starting on position 1).
To recap what we've learned so far, compare the following patterns:
<MiniRepl client:only="react" tune={`note("e5(2,8) b4(3,8) d5(2,8) c5(3,8)").slow(4)`} />
<MiniRepl client:idle tune={`note("<g3 b3 e4 [a3,c3,e4] [b3,d3,f#4]>")`} />
<MiniRepl client:idle tune={`note("<[g3,b3,e4] [a3,c3,e4] [b3,d3,f#4]>")`} />
<MiniRepl client:idle tune={`note("<[g3,b3,e4]/2 [a3,c3,e4] [b3,d3,f#4]>")`} />
<MiniRepl client:idle tune={`note("<[g3,b3,e4]*2 [a3,c3,e4] [b3,d3,f#4]>")`} />
<MiniRepl client:idle tune={`note("<[g3,b3,e4] _ [a3,c3,e4] [b3,d3,f#4]>")`} />
<MiniRepl client:idle tune={`note("<[g3,b3,e4]@2 [a3,c3,e4] [b3,d3,f#4]>")`} />
<MiniRepl client:idle tune={`note("<[g3,b3,e4]!2 [a3,c3,e4] [b3,d3,f#4]>")`} />
# Euclidian rhythms
Using round brackets after an event, we can create rhythmical sub-divisions based on three parameters: `beats`, `segments` and `offset`.
This algorithm can be found in many different types of music software, and is often referred to as a [Euclidean rhythm](https://en.wikipedia.org/wiki/Euclidean_rhythm) sequencer, after computer scientist Godfriend Toussaint.
Why is it interesting? Well, consider the following simple example:
<MiniRepl client:idle tune={`s("bd(3,8,0)")`} />
Sound familiar?
This is a popular Euclidian rhythm going by various names, such as "Pop Clave".
These rhythms can be found in all musical cultures, and the Euclidian rhythm algorithm allows us to express them extremely easily.
Writing this rhythm out in full require describing:
<MiniRepl client:idle tune={`s("bd ~ ~ bd ~ ~ bd ~")`} />
But using the Euclidian rhythm notation, we only need to express "3 beats over 8 segments, starting on position 1".
This makes it easy to write patterns with interesting rhythmic structures and variations that still sound familiar:
<MiniRepl client:idle tune={`note("e5(2,8) b4(3,8) d5(2,8) c5(3,8)").slow(4)`} />
Note that since the example above does not use the third `offset` parameter, it can be written simply as `"(3,8)"`.
<MiniRepl client:idle tune={`s("bd(3,8)")`} />
Let's look at those three parameters in detail.
## Beats
`beats`: the first parameter controls how may beats will be played.
Compare these:
<MiniRepl client:idle tune={`s("bd(2,8)")`} />
<MiniRepl client:idle tune={`s("bd(5,8)")`} />
<MiniRepl client:idle tune={`s("bd(7,8)")`} />
## Segments
`segments`: the second parameter controls the total amount of segments the beats will be distributed over:
<MiniRepl client:idle tune={`s("bd(3,4)")`} />
<MiniRepl client:idle tune={`s("bd(3,8)")`} />
<MiniRepl client:idle tune={`s("bd(3,13)")`} />
## Offsets
`offset`: the third (optional) parameter controls the starting position for distributing the beats.
We need a secondary rhythm to hear the difference:
<MiniRepl client:idle tune={`s("bd(3,8,0), hh cp")`} />
<MiniRepl client:idle tune={`s("bd(3,8,3), hh cp")`} />
<MiniRepl client:idle tune={`s("bd(3,8,5), hh cp")`} />
# Mini-notation exercise
The most fun thing about the mini-notation, is that everything you have just learned can be combined in various ways!
Starting with this one `n`, can you make a _pattern string_ that uses every single mini-notation element above?
<MiniRepl client:idle tune={`n("60")`} />
<br/>