+ pattern effects chapter

+ recap page
+ only load mini repls when visible
This commit is contained in:
Felix Roos 2023-05-30 06:16:02 +02:00
parent 0edd7e14b7
commit c4a38d9008
7 changed files with 362 additions and 34 deletions

View File

@ -47,7 +47,8 @@ export const SIDEBAR: Sidebar = {
{ text: 'First Sounds', link: 'workshop/first-sounds' },
{ text: 'First Notes', link: 'workshop/first-notes' },
{ text: 'First Effects', link: 'workshop/first-effects' },
{ text: 'Mini Notation', link: 'workshop/mini-notation' },
{ text: 'Pattern Effects', link: 'workshop/pattern-effects' },
{ text: 'Recap', link: 'workshop/recap' },
],
Tutorial: [
{ text: 'Getting Started', link: 'learn/getting-started' },

View File

@ -18,7 +18,7 @@ We have sounds, we have notes, now let's look at effects!
<MiniRepl
hideHeader
client:load
client:visible
tune={`note("<[c2 c3]*4 [bb1 bb2]*4 [f2 f3]*4 [eb2 eb3]*4>/2")
.sound("sawtooth").lpf(800)`}
/>
@ -36,7 +36,7 @@ lpf = **l**ow **p**ass **f**ilter
<MiniRepl
hideHeader
client:load
client:visible
tune={`note("<[c2 c3]*4 [bb1 bb2]*4 [f2 f3]*4 [eb2 eb3]*4>/2")
.sound("sawtooth").lpf("200 1000")`}
/>
@ -54,7 +54,7 @@ We will learn how to automate with waves later...
<MiniRepl
hideHeader
client:load
client:visible
tune={`note("<[c3,g3,e4] [bb2,f3,d4] [a2,f3,c4] [bb2,g3,eb4]>/2")
.sound("sawtooth").vowel("<a e i o>/2")`}
/>
@ -63,7 +63,7 @@ We will learn how to automate with waves later...
<MiniRepl
hideHeader
client:load
client:visible
tune={`stack(
sound("hh*8").gain("[.25 1]*2"),
sound("bd*2,~ sd:1")
@ -86,7 +86,7 @@ Let's combine all of the above into a little tune:
<MiniRepl
hideHeader
client:load
client:visible
tune={`stack(
stack(
sound("hh*8").gain("[.25 1]*2"),
@ -106,11 +106,11 @@ The 3 parts (drums, bassline, chords) are exactly as earlier, just stacked toget
</Box>
**adsr envelope**
**shape the sound with an adsr envelope**
<MiniRepl
hideHeader
client:load
client:visible
tune={`note("<c3 bb2 f3 eb3>")
.sound("sawtooth").lpf(600)
.attack(.1)
@ -147,7 +147,7 @@ Can you guess what they do?
<MiniRepl
hideHeader
client:load
client:visible
tune={`note("<c3 bb2 f3 eb3>")
.sound("sawtooth").lpf(600)
.adsr(".1:.1:.5:.2")
@ -158,7 +158,7 @@ Can you guess what they do?
<MiniRepl
hideHeader
client:load
client:visible
tune={`stack(
note("~ [<[d3,a3,f4]!2 [d3,bb3,g4]!2> ~]")
.sound("gm_electric_guitar_muted"),
@ -180,7 +180,7 @@ What happens if you use `.delay(".8:.06:.8")` ? Can you guess what the third num
<MiniRepl
hideHeader
client:load
client:visible
tune={`n("<4 [3@3 4] [<2 0> ~@16] ~>/2")
.scale("D4:minor").sound("gm_accordion:2")
.room(2)`}
@ -198,7 +198,7 @@ Add a delay too!
<MiniRepl
hideHeader
client:load
client:visible
tune={`stack(
note("~ [<[d3,a3,f4]!2 [d3,bb3,g4]!2> ~]")
.sound("gm_electric_guitar_muted").delay(.5),
@ -213,7 +213,7 @@ Let's add a bass to make this complete:
<MiniRepl
hideHeader
client:load
client:visible
tune={`stack(
note("~ [<[d3,a3,f4]!2 [d3,bb3,g4]!2> ~]")
.sound("gm_electric_guitar_muted").delay(.5),
@ -237,7 +237,7 @@ Try adding `.hush()` at the end of one of the patterns in the stack...
<MiniRepl
hideHeader
client:load
client:visible
tune={`sound("numbers:1 numbers:2 numbers:3 numbers:4")
.pan("0 0.3 .6 1")
.slow(2)`}
@ -245,13 +245,13 @@ Try adding `.hush()` at the end of one of the patterns in the stack...
**speed**
<MiniRepl hideHeader client:load tune={`sound("bd rim").speed("<1 2 -1 -2>").room(.2)`} />
<MiniRepl hideHeader client:visible tune={`sound("bd rim").speed("<1 2 -1 -2>").room(.2)`} />
**fast and slow**
We can use `fast` and `slow` to change the tempo of a pattern outside of Mini-Notation:
<MiniRepl hideHeader client:load tune={`sound("bd*2,~ rim").slow(2)`} />
<MiniRepl hideHeader client:visible tune={`sound("bd*2,~ rim").slow(2)`} />
<Box>
@ -263,13 +263,13 @@ What happens if you use a pattern like `.fast("<1 [2 4]>")`?
By the way, inside Mini-Notation, `fast` is `*` and slow is `/`.
<MiniRepl hideHeader client:load tune={`sound("[bd*2,~ rim]*<1 [2 4]>")`} />
<MiniRepl hideHeader client:visible tune={`sound("[bd*2,~ rim]*<1 [2 4]>")`} />
## automation with signals
Instead of changing values stepwise, we can also control them with signals:
<MiniRepl hideHeader client:load tune={`sound("hh*16").gain(sine)`} punchcard />
<MiniRepl hideHeader client:visible tune={`sound("hh*16").gain(sine)`} punchcard />
<Box>
@ -283,7 +283,9 @@ The gain is visualized as transparency in the pianoroll.
**setting a range**
<MiniRepl hideHeader client:load tune={`sound("hh*8").lpf(saw.range(500, 2000))`} />
By default, waves oscillate between 0 to 1. We can change that with `range`:
<MiniRepl hideHeader client:visible tune={`sound("hh*8").lpf(saw.range(500, 2000))`} />
<Box>
@ -291,13 +293,11 @@ What happens if you flip the range values?
</Box>
**setting a range**
By default, waves oscillate between 0 to 1. We can change that with `range`:
We can change the automation speed with slow / fast:
<MiniRepl
hideHeader
client:load
client:visible
tune={`note("<[c2 c3]*4 [bb1 bb2]*4 [f2 f3]*4 [eb2 eb3]*4>/2")
.sound("sawtooth")
.lpf(sine.range(100, 2000).slow(8))`}
@ -305,19 +305,19 @@ By default, waves oscillate between 0 to 1. We can change that with `range`:
<Box>
Notice how the wave is slowed down. The whole automation will take 8 cycles to repeat.
The whole automation will now take 8 cycles to repeat.
</Box>
## Recap
| name | example |
| ----- | ----------------------------------------------------------------------------------------------- |
| lpf | <MiniRepl hideHeader client:load tune={`note("c2 c3").s("sawtooth").lpf("<400 2000>")`} /> |
| vowel | <MiniRepl hideHeader client:load tune={`note("c3 eb3 g3").s("sawtooth").vowel("<a e i o>")`} /> |
| gain | <MiniRepl hideHeader client:load tune={`s("hh*8").gain("[.25 1]*2")`} /> |
| delay | <MiniRepl hideHeader client:load tune={`s("bd rim").delay(.5)`} /> |
| room | <MiniRepl hideHeader client:load tune={`s("bd rim").room(.5)`} /> |
| pan | <MiniRepl hideHeader client:load tune={`s("bd rim").pan("0 1")`} /> |
| speed | <MiniRepl hideHeader client:load tune={`s("bd rim").speed("<1 2 -1 -2>")`} /> |
| range | <MiniRepl hideHeader client:load tune={`s("hh*16").lpf(saw.range(200,4000))`} /> |
| name | example |
| ----- | -------------------------------------------------------------------------------------------------- |
| lpf | <MiniRepl hideHeader client:visible tune={`note("c2 c3").s("sawtooth").lpf("<400 2000>")`} /> |
| vowel | <MiniRepl hideHeader client:visible tune={`note("c3 eb3 g3").s("sawtooth").vowel("<a e i o>")`} /> |
| gain | <MiniRepl hideHeader client:visible tune={`s("hh*8").gain("[.25 1]*2")`} /> |
| delay | <MiniRepl hideHeader client:visible tune={`s("bd rim").delay(.5)`} /> |
| room | <MiniRepl hideHeader client:visible tune={`s("bd rim").room(.5)`} /> |
| pan | <MiniRepl hideHeader client:visible tune={`s("bd rim").pan("0 1")`} /> |
| speed | <MiniRepl hideHeader client:visible tune={`s("bd rim").speed("<1 2 -1 -2>")`} /> |
| range | <MiniRepl hideHeader client:visible tune={`s("hh*16").lpf(saw.range(200,4000))`} /> |

View File

@ -318,6 +318,14 @@ Let's recap what we've learned in this chapter:
| Elongate | @ | <MiniRepl hideHeader client:visible tune={`note("c@3 e")`} /> |
| Replicate | ! | <MiniRepl hideHeader client:visible tune={`note("c!3 e")`} /> |
New functions:
| Name | Description | Example |
| ----- | ----------------------------------- | -------------------------------------------------------------------------------------------- |
| note | set pitch as number or letter | <MiniRepl hideHeader client:visible tune={`note("b g e c").sound("piano")`} /> |
| scale | interpret `n` as scale degree | <MiniRepl hideHeader client:visible tune={`n("6 4 2 0").scale("C:minor").sound("piano")`} /> |
| stack | play patterns in parallel (read on) | <MiniRepl hideHeader client:visible tune={`stack(s("bd sd"),note("c eb g"))`} /> |
## Examples
**Classy Bassline**

View File

@ -197,6 +197,16 @@ It is quite common that there are many ways to express the same idea.
punchcard
/>
**selecting sample numbers separately**
Instead of using ":", we can also use the `n` function to select sample numbers:
<MiniRepl hideHeader client:visible tune={`n("0 1 [4 2] 3*2").sound("jazz")`} punchcard />
This is shorter and more readable than:
<MiniRepl hideHeader client:visible tune={`sound("jazz:0 jazz:1 [jazz:4 jazz:2] jazz:3*2")`} punchcard />
## Recap
Now we've learned the basics of the so called Mini-Notation, the rhythm language of Tidal.
@ -219,6 +229,7 @@ The Mini-Notation is usually used inside some function. These are the functions
| sound | plays the sound of the given name | <MiniRepl hideHeader client:visible tune={`sound("bd sd")`} /> |
| bank | selects the sound bank | <MiniRepl hideHeader client:visible tune={`sound("bd sd").bank("RolandTR909")`} /> |
| cpm | sets the tempo in cycles per minute | <MiniRepl hideHeader client:visible tune={`sound("bd sd").cpm(90)`} /> |
| n | select sample number | <MiniRepl hideHeader client:visible tune={`n("0 1 4 2").sound("jazz")`} /> |
## Examples

View File

@ -4,3 +4,19 @@ layout: ../../layouts/MainLayout.astro
---
# Introduction
## goals
- be beginner friendly
- teach a representative subset of strudel / tidal
- introduce one new thing at a time
- give practical / musical examples
- encourage self-experimentation
- hands on learning > walls of text
- maintain flow state
- no setup required
## inspired by
- https://github.com/tidalcycles/tidal-workshop/blob/master/workshop.tidal
- https://learningmusic.ableton.com

View File

@ -0,0 +1,194 @@
---
title: Pattern Effects
layout: ../../layouts/MainLayout.astro
---
import { MiniRepl } from '@src/docs/MiniRepl';
import Box from '@components/Box.astro';
import QA from '@components/QA';
# Pattern Effects
Up until now, most of the functions we've seen are what other music programs are typically capable of: sequencing sounds, playing notes, controlling effects.
In this chapter, we are going to look at functions that are more unique to tidal.
**reverse patterns with rev**
<MiniRepl hideHeader client:visible tune={`n("0 1 [4 3] 2").sound("jazz").rev()`} />
**play pattern left and modify it right with jux**
<MiniRepl hideHeader client:visible tune={`n("0 1 [4 3] 2").sound("jazz").jux(rev)`} />
This is the same as:
<MiniRepl
hideHeader
client:visible
tune={`stack(
n("0 1 [4 3] 2").sound("jazz").pan(0),
n("0 1 [4 3] 2").sound("jazz").pan(1).rev()
)`}
/>
Let's visualize what happens here:
<MiniRepl
hideHeader
client:visible
tune={`stack(
n("0 1 [4 3] 2").sound("jazz").pan(0).color("cyan"),
n("0 1 [4 3] 2").sound("jazz").pan(1).color("magenta").rev()
)`}
punchcard
/>
<Box>
Try commenting out one of the two by adding `//` before a line
</Box>
**multiple tempos**
<MiniRepl hideHeader client:visible tune={`note("c2, eb3 g3 [bb3 c4]").sound("piano").slow("1,2,3")`} />
This is like doing
<MiniRepl
hideHeader
client:visible
tune={`stack(
note("c2, eb3 g3 [bb3 c4]").s("piano").slow(1).color('cyan'),
note("c2, eb3 g3 [bb3 c4]").s("piano").slow(2).color('magenta'),
note("c2, eb3 g3 [bb3 c4]").s("piano").slow(3).color('yellow')
)`}
punchcard
/>
<Box>
Try commenting out one or more by adding `//` before a line
</Box>
**add**
<MiniRepl
hideHeader
client:visible
tune={`note("c2 [eb3,g3]".add("<0 <1 -1>>"))
.color("<cyan <magenta yellow>>").adsr("[.1 0]:.2:[1 0]")
.sound("gm_acoustic_bass").room(.5)`}
punchcard
/>
<Box>
If you add a number to a note, the note will be treated as if it was a number
</Box>
We can add as often as we like:
<MiniRepl
hideHeader
client:visible
tune={`note("c2 [eb3,g3]".add("<0 <1 -1>>").add("0,7"))
.color("<cyan <magenta yellow>>").adsr("[.1 0]:.2:[1 0]")
.sound("gm_acoustic_bass").room(.5)`}
punchcard
/>
**add with scale**
<MiniRepl
hideHeader
client:visible
tune={`n("<0 [2 4] <3 5> [~ <4 1>]>*2".add("<0 [0,2,4]>/4"))
.scale("C5:minor").release(.5)
.sound("gm_xylophone").room(.5)`}
punchcard
/>
**time to stack**
<MiniRepl
hideHeader
client:visible
tune={`stack(
n("<0 [2 4] <3 5> [~ <4 1>]>*2".add("<0 [0,2,4]>/4"))
.scale("C5:minor")
.sound("gm_xylophone")
.room(.4).delay(.125),
note("c2 [eb3,g3]".add("<0 <1 -1>>"))
.adsr("[.1 0]:.2:[1 0]")
.sound("gm_acoustic_bass")
.room(.5),
n("0 1 [2 3] 2").sound("jazz").jux(rev).slow(2)
)`}
/>
**ply**
<MiniRepl hideHeader client:visible tune={`sound("hh, bd rim").bank("RolandTR707").ply(2)`} punchcard />
this is like writing:
<MiniRepl hideHeader client:visible tune={`sound("hh*2, bd*2 rim*2").bank("RolandTR707")`} punchcard />
<Box>
Try patterning the `ply` function, for example using `"<1 2 1 3>"`
</Box>
**off**
<MiniRepl
hideHeader
client:visible
tune={`n("<0 [4 <3 2>] <2 3> [~ 1]>"
.off(1/8, x=>x.add(4))
//.off(1/4, x=>x.add(7))
).scale("<C5:minor Db5:mixolydian>/4")
.s("triangle").room(.5).ds(".1:0").delay(.5)`}
punchcard
/>
<Box>
In the notation `x=>x.`, the `x` is the shifted pattern, which where modifying.
</Box>
The above is like writing:
<MiniRepl
hideHeader
client:visible
tune={`stack(
n("<0 [4 <3 2>] <2 3> [~ 1]>*2").color("cyan"),
n("<0 [4 <3 2>] <2 3> [~ 1]>*2".add(7).late(1/8)).color("magenta")
).scale("<C4:minor Db4:mixolydian>/2")
.s("triangle").adsr(".01:.1:0").room(.5)`}
punchcard
/>
off is also useful for sounds:
<MiniRepl
hideHeader
client:visible
tune={`s("bd sd,[~ hh]*2").bank("CasioRZ1")
.off(1/8, x=>x.speed(1.5).gain(.25))`}
/>
| name | description | example |
| ---- | ------------------------------ | ---------------------------------------------------------------------------------------------- |
| rev | reverse | <MiniRepl hideHeader client:visible tune={`n("0 2 4 6").scale("C:minor").rev()`} /> |
| jux | split left/right, modify right | <MiniRepl hideHeader client:visible tune={`n("0 2 4 6").scale("C:minor").jux(rev)`} /> |
| add | add numbers / notes | <MiniRepl hideHeader client:visible tune={`n("0 2 4 6".add("<0 1 2 1>")).scale("C:minor")`} /> |
| ply | speed up each event n times | <MiniRepl hideHeader client:visible tune={`s("bd sd").ply("<1 2 3>")`} /> |
| off | copy, shift time & modify | <MiniRepl hideHeader client:visible tune={`s("bd sd, hh*4").off(1/8, x=>x.speed(2))`} /> |

View File

@ -0,0 +1,98 @@
---
title: Recap
layout: ../../layouts/MainLayout.astro
---
import { MiniRepl } from '../../docs/MiniRepl';
# Workshop Recap
This page is just a listing of all functions covered in the workshop!
## Mini Notation
| Concept | Syntax | Example |
| ----------------- | -------- | -------------------------------------------------------------------------------- |
| Sequence | space | <MiniRepl hideHeader client:visible tune={`sound("bd bd sn hh")`} /> |
| Sample Number | :x | <MiniRepl hideHeader client:visible tune={`sound("hh:0 hh:1 hh:2 hh:3")`} /> |
| Rests | ~ | <MiniRepl hideHeader client:visible tune={`sound("metal ~ jazz jazz:1")`} /> |
| Sub-Sequences | \[\] | <MiniRepl hideHeader client:visible tune={`sound("bd wind [metal jazz] hh")`} /> |
| Sub-Sub-Sequences | \[\[\]\] | <MiniRepl hideHeader client:visible tune={`sound("bd [metal [jazz sn]]")`} /> |
| Speed up | \* | <MiniRepl hideHeader client:visible tune={`sound("bd sn*2 cp*3")`} /> |
| Parallel | , | <MiniRepl hideHeader client:visible tune={`sound("bd*2, hh*2 [hh oh]")`} /> |
| Slow down | \/ | <MiniRepl hideHeader client:visible tune={`note("[c a f e]/2")`} /> |
| Alternate | \<\> | <MiniRepl hideHeader client:visible tune={`note("c <e g>")`} /> |
| Elongate | @ | <MiniRepl hideHeader client:visible tune={`note("c@3 e")`} /> |
| Replicate | ! | <MiniRepl hideHeader client:visible tune={`note("c!3 e")`} /> |
## Sounds
| Name | Description | Example |
| ----- | --------------------------------- | ---------------------------------------------------------------------------------- |
| sound | plays the sound of the given name | <MiniRepl hideHeader client:visible tune={`sound("bd sd")`} /> |
| bank | selects the sound bank | <MiniRepl hideHeader client:visible tune={`sound("bd sd").bank("RolandTR909")`} /> |
| n | select sample number | <MiniRepl hideHeader client:visible tune={`n("0 1 4 2").sound("jazz")`} /> |
## Notes
| Name | Description | Example |
| --------- | ----------------------------------- | -------------------------------------------------------------------------------------------- |
| note | set pitch as number or letter | <MiniRepl hideHeader client:visible tune={`note("b g e c").sound("piano")`} /> |
| n + scale | set note in scale | <MiniRepl hideHeader client:visible tune={`n("6 4 2 0").scale("C:minor").sound("piano")`} /> |
| stack | play patterns in parallel (read on) | <MiniRepl hideHeader client:visible tune={`stack(s("bd sd"),note("c eb g"))`} /> |
## Audio Effects
| name | example |
| ----- | -------------------------------------------------------------------------------------------------- |
| lpf | <MiniRepl hideHeader client:visible tune={`note("c2 c3").s("sawtooth").lpf("<400 2000>")`} /> |
| vowel | <MiniRepl hideHeader client:visible tune={`note("c3 eb3 g3").s("sawtooth").vowel("<a e i o>")`} /> |
| gain | <MiniRepl hideHeader client:visible tune={`s("hh*8").gain("[.25 1]*2")`} /> |
| delay | <MiniRepl hideHeader client:visible tune={`s("bd rim").delay(.5)`} /> |
| room | <MiniRepl hideHeader client:visible tune={`s("bd rim").room(.5)`} /> |
| pan | <MiniRepl hideHeader client:visible tune={`s("bd rim").pan("0 1")`} /> |
| speed | <MiniRepl hideHeader client:visible tune={`s("bd rim").speed("<1 2 -1 -2>")`} /> |
| range | <MiniRepl hideHeader client:visible tune={`s("hh*16").lpf(saw.range(200,4000))`} /> |
## Pattern Effects
| name | description | example |
| ---- | ----------------------------------- | ---------------------------------------------------------------------------------------------- |
| cpm | sets the tempo in cycles per minute | <MiniRepl hideHeader client:visible tune={`sound("bd sd").cpm(90)`} /> |
| fast | speed up | <MiniRepl hideHeader client:visible tune={`sound("bd sd").fast(2)`} /> |
| slow | slow down | <MiniRepl hideHeader client:visible tune={`sound("bd sd").slow(2)`} /> |
| rev | reverse | <MiniRepl hideHeader client:visible tune={`n("0 2 4 6").scale("C:minor").rev()`} /> |
| jux | split left/right, modify right | <MiniRepl hideHeader client:visible tune={`n("0 2 4 6").scale("C:minor").jux(rev)`} /> |
| add | add numbers / notes | <MiniRepl hideHeader client:visible tune={`n("0 2 4 6".add("<0 1 2 1>")).scale("C:minor")`} /> |
| ply | speed up each event n times | <MiniRepl hideHeader client:visible tune={`s("bd sd").ply("<1 2 3>")`} /> |
| off | copy, shift time & modify | <MiniRepl hideHeader client:visible tune={`s("bd sd, hh*4").off(1/8, x=>x.speed(2))`} /> |
## Samples
```
casio control crow techno house jazz
metal east jvbass juno insect space wind
bd sd sn cp hh
piano
```
## Synths
```
gm_electric_guitar_muted gm_acoustic_bass
gm_voice_oohs gm_blown_bottle sawtooth square triangle
gm_xylophone gm_synth_bass_1 gm_synth_strings_1
```
## Banks
```
RolandTR909
```
## Scales
```
major minor dorian mixolydian
minor:pentatonic major:pentatonic
```