started german translation of workshop

This commit is contained in:
Felix Roos 2023-06-05 23:48:04 +02:00
parent f0faf5b42e
commit 61a9b01062
11 changed files with 1574 additions and 2 deletions

View File

@ -1,5 +1,5 @@
---
// import { getLanguageFromURL } from '../../languages';
import { getLanguageFromURL } from '../../languages';
import { SIDEBAR } from '../../config';
type Props = {
@ -10,7 +10,7 @@ const { currentPage } = Astro.props as Props;
const { BASE_URL } = import.meta.env;
let currentPageMatch = currentPage.slice(BASE_URL.length, currentPage.endsWith('/') ? -1 : undefined);
const langCode = 'en'; // getLanguageFromURL(currentPage);
const langCode = getLanguageFromURL(currentPage) || 'en';
const sidebar = SIDEBAR[langCode];
---

View File

@ -24,6 +24,7 @@ export type Frontmatter = {
export const KNOWN_LANGUAGES = {
English: 'en',
German: 'de',
} as const;
export const KNOWN_LANGUAGE_CODES = Object.values(KNOWN_LANGUAGES);
@ -41,6 +42,16 @@ export const ALGOLIA = {
export type SidebarLang = Record<string, { text: string; link: string }[]>;
export type Sidebar = Record<(typeof KNOWN_LANGUAGE_CODES)[number], SidebarLang>;
export const SIDEBAR: Sidebar = {
de: {
Workshop: [
{ text: 'Intro', link: 'de/workshop/intro' },
{ text: 'Erste Sounds', link: 'de/workshop/first-sounds' },
{ text: 'Erste Töne', link: 'de/workshop/first-notes' },
{ text: 'Erste Effekte', link: 'de/workshop/first-effects' },
{ text: 'Pattern Effekte', link: 'de/workshop/pattern-effects' },
{ text: 'Rückblick', link: 'de/workshop/recap' },
],
},
en: {
Workshop: [
{ text: 'Intro', link: 'workshop/intro' },

View File

@ -0,0 +1,323 @@
---
title: First Effects
layout: ../../../layouts/MainLayout.astro
---
import { MiniRepl } from '../../../docs/MiniRepl';
import QA from '@components/QA';
# First Effects
import Box from '@components/Box.astro';
We have sounds, we have notes, now let's look at effects!
## Some basic effects
**low-pass filter**
<MiniRepl
hideHeader
client:visible
tune={`note("<[c2 c3]*4 [bb1 bb2]*4 [f2 f3]*4 [eb2 eb3]*4>/2")
.sound("sawtooth").lpf(800)`}
/>
<Box>
lpf = **l**ow **p**ass **f**ilter
- Change lpf to 200. Notice how it gets muffled. Think of it as standing in front of the club with the door closed 🚪.
- Now let's open the door... change it to 5000. Notice how it gets brighter ✨🪩
</Box>
**pattern the filter**
<MiniRepl
hideHeader
client:visible
tune={`note("<[c2 c3]*4 [bb1 bb2]*4 [f2 f3]*4 [eb2 eb3]*4>/2")
.sound("sawtooth").lpf("200 1000")`}
/>
<Box>
- Try adding more values
- Notice how the pattern in lpf does not change the overall rhythm
We will learn how to automate with waves later...
</Box>
**vowel**
<MiniRepl
hideHeader
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")`}
/>
**gain**
<MiniRepl
hideHeader
client:visible
tune={`stack(
sound("hh*8").gain("[.25 1]*2"),
sound("bd*2,~ sd:1")
) `}
punchcard
/>
<Box>
Rhythm is all about dynamics!
- Remove `.gain(...)` and notice how flat it sounds.
- Bring it back by undoing (ctrl+z)
</Box>
**stacks within stacks**
Let's combine all of the above into a little tune:
<MiniRepl
hideHeader
client:visible
tune={`stack(
stack(
sound("hh*8").gain("[.25 1]*2"),
sound("bd*2,~ sd:1")
),
note("<[c2 c3]*4 [bb1 bb2]*4 [f2 f3]*4 [eb2 eb3]*4>/2")
.sound("sawtooth").lpf("200 1000"),
note("<[c3,g3,e4] [bb2,f3,d4] [a2,f3,c4] [bb2,g3,eb4]>/2")
.sound("sawtooth").vowel("<a e i o>/2")
) `}
/>
<Box>
Try to identify the individual parts of the stacks, pay attention to where the commas are.
The 3 parts (drums, bassline, chords) are exactly as earlier, just stacked together, separated by comma.
</Box>
**shape the sound with an adsr envelope**
<MiniRepl
hideHeader
client:visible
tune={`note("<c3 bb2 f3 eb3>")
.sound("sawtooth").lpf(600)
.attack(.1)
.decay(.1)
.sustain(.25)
.release(.2)`}
/>
<Box>
Try to find out what the numbers do.. Compare the following
- attack: `.5` vs `0`
- decay: `.5` vs `0`
- sustain: `1` vs `.25` vs `0`
- release: `0` vs `.5` vs `1`
Can you guess what they do?
</Box>
<QA q="Click to see solution" client:visible>
- attack: time it takes to fade in
- decay: time it takes to fade to sustain
- sustain: level after decay
- release: time it takes to fade out after note is finished
![ADSR](https://upload.wikimedia.org/wikipedia/commons/thumb/e/ea/ADSR_parameter.svg/1920px-ADSR_parameter.svg.png)
</QA>
**adsr short notation**
<MiniRepl
hideHeader
client:visible
tune={`note("<c3 bb2 f3 eb3>")
.sound("sawtooth").lpf(600)
.adsr(".1:.1:.5:.2")
`}
/>
**delay**
<MiniRepl
hideHeader
client:visible
tune={`stack(
note("~ [<[d3,a3,f4]!2 [d3,bb3,g4]!2> ~]")
.sound("gm_electric_guitar_muted"),
sound("<bd rim>").bank("RolandTR707")
).delay(".5")`}
/>
<Box>
Try some `delay` values between 0 and 1. Btw, `.5` is short for `0.5`
What happens if you use `.delay(".8:.125")` ? Can you guess what the second number does?
What happens if you use `.delay(".8:.06:.8")` ? Can you guess what the third number does?
</Box>
**room aka reverb**
<MiniRepl
hideHeader
client:visible
tune={`n("<4 [3@3 4] [<2 0> ~@16] ~>/2")
.scale("D4:minor").sound("gm_accordion:2")
.room(2)`}
/>
<Box>
Try different values!
Add a delay too!
</Box>
**little dub tune**
<MiniRepl
hideHeader
client:visible
tune={`stack(
note("~ [<[d3,a3,f4]!2 [d3,bb3,g4]!2> ~]")
.sound("gm_electric_guitar_muted").delay(.5),
sound("<bd rim>").bank("RolandTR707").delay(.5),
n("<4 [3@3 4] [<2 0> ~@16] ~>/2")
.scale("D4:minor").sound("gm_accordion:2")
.room(2).gain(.5)
)`}
/>
Let's add a bass to make this complete:
<MiniRepl
hideHeader
client:visible
tune={`stack(
note("~ [<[d3,a3,f4]!2 [d3,bb3,g4]!2> ~]")
.sound("gm_electric_guitar_muted").delay(.5),
sound("<bd rim>").bank("RolandTR707").delay(.5),
n("<4 [3@3 4] [<2 0> ~@16] ~>/2")
.scale("D4:minor").sound("gm_accordion:2")
.room(2).gain(.4),
n("<0 [~ 0] 4 [3 2] [0 ~] [0 ~] <0 2> ~>*2")
.scale("D2:minor")
.sound("sawtooth,triangle").lpf(800)
)`}
/>
<Box>
Try adding `.hush()` at the end of one of the patterns in the stack...
</Box>
**pan**
<MiniRepl
hideHeader
client:visible
tune={`sound("numbers:1 numbers:2 numbers:3 numbers:4")
.pan("0 0.3 .6 1")
.slow(2)`}
/>
**speed**
<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:visible tune={`sound("bd*2,~ rim").slow(2)`} />
<Box>
Change the `slow` value. Try replacing it with `fast`.
What happens if you use a pattern like `.fast("<1 [2 4]>")`?
</Box>
By the way, inside Mini-Notation, `fast` is `*` and slow is `/`.
<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:visible tune={`sound("hh*16").gain(sine)`} punchcard />
<Box>
The basic waveforms for signals are `sine`, `saw`, `square`, `tri` 🌊
Try also random signals `rand` and `perlin`!
The gain is visualized as transparency in the pianoroll.
</Box>
**setting a range**
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>
What happens if you flip the range values?
</Box>
We can change the automation speed with slow / fast:
<MiniRepl
hideHeader
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))`}
/>
<Box>
The whole automation will now take 8 cycles to repeat.
</Box>
## Recap
| 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

@ -0,0 +1,388 @@
---
title: First Notes
layout: ../../../layouts/MainLayout.astro
---
import { MiniRepl } from '@src/docs/MiniRepl';
import { midi2note } from '@strudel.cycles/core/';
import Box from '@components/Box.astro';
import QA from '@components/QA';
# Erste Töne
Jetzt schauen wir uns an wie man mit Tönen mit der `note` Funktion spielt.
## Zahlen und Noten
**Töne mit Zahlen**
<MiniRepl
hideHeader
client:visible
tune={`note("48 52 55 59").sound("piano")`}
claviature
claviatureLabels={Object.fromEntries(
Array(49)
.fill()
.map((_, i) => [midi2note(i + 36), i + 36]),
)}
/>
<Box>
Probiere verschiedene Zahlen aus!
Versuch auch mal Kommazahlen, z.B. 55.5 (beachte die englische Schreibweise von Kommazahlen mit "." anstatt ",")
</Box>
**Töne mit Buchstaben**
<MiniRepl
hideHeader
client:visible
tune={`note("c e g b").sound("piano")`}
claviature
claviatureLabels={Object.fromEntries(['c3', 'd3', 'e3', 'f3', 'g3', 'a3', 'b3'].map((n) => [n, n.split('')[0]]))}
/>
<Box>
Versuch verschiedene Buchstaben aus (a - g).
Findest du Melodien die auch gleichzeitig ein Wort sind? Tipp: ☕ 🙈 🧚
</Box>
**Vorzeichen**
<MiniRepl
hideHeader
client:visible
tune={`note("db eb gb ab bb").sound("piano")`}
claviature
claviatureLabels={Object.fromEntries(
['db3', 'eb3', 'gb3', 'ab3', 'bb3'].map((n) => [n, n.split('').slice(0, 2).join('')]),
)}
/>
<MiniRepl
hideHeader
client:visible
tune={`note("c# d# f# g# a#").sound("piano")`}
claviature
claviatureLabels={Object.fromEntries(
['c#3', 'd#3', 'f#3', 'g#3', 'a#3'].map((n) => [n, n.split('').slice(0, 2).join('')]),
)}
/>
**Andere Oktaven**
<MiniRepl
hideHeader
client:visible
tune={`note("c2 e3 g4 b5").sound("piano")`}
claviature
claviatureLabels={Object.fromEntries(['c1', 'c2', 'c3', 'c4', 'c5'].map((n) => [n, n]))}
claviatureLabels={Object.fromEntries(
Array(49)
.fill()
.map((_, i) => [midi2note(i + 36), midi2note(i + 36)]),
)}
/>
<Box>
Probiere verschiedene Oktaven aus (1-8)
</Box>
Normalerweise kommen Leute die keine Noten besser mit Zahlen anstatt mit Buchstaben zurecht.
Daher benutzen die folgenden Beispiele meistens Zahlen.
Später sehen wir auch noch ein paar Tricks die es uns erleichtern Töne zu spielen die zueinander passen.
## Den Sound verändern
Genau wie bei geräuschhaften Sounds können wir den Klang unserer Töne mit `sound` verändern:
<MiniRepl hideHeader client:visible tune={`note("36 43, 52 59 62 64").sound("piano")`} />
<Box>
Probier ein paar sounds aus:
- gm_electric_guitar_muted - E-Gitarre
- gm_acoustic_bass - Kontrabass
- gm_voice_oohs - Chords
- gm_blown_bottle - Flasche
- sawtooth - Sägezahn-Welle
- square - Rechteck-Welle
- triangle - Dreieck-Welle
- Was ist mit bd, sd oder hh?
- Entferne `.sound('...')` komplett
</Box>
**Zwischen Sounds hin und her wechseln**
<MiniRepl
hideHeader
client:visible
tune={`note("48 67 63 [62, 58]")
.sound("piano gm_electric_guitar_muted")`}
/>
**Gleichzeitige Sounds**
<MiniRepl
hideHeader
client:visible
tune={`note("48 67 63 [62, 58]")
.sound("piano, gm_electric_guitar_muted")`}
/>
<Box>
Die patterns in `note` und `sound` werden kombiniert!
Wir schauen uns später noch mehr Möglichkeiten an wie man patterns kombiniert.
</Box>
## Längere Sequenzen
**Divide sequences with `/` to slow them down**
{/* [c2 bb1 f2 eb2] */}
<MiniRepl hideHeader client:visible tune={`note("[36 34 41 39]/4").sound("gm_acoustic_bass")`} punchcard />
<Box>
The `/4` plays the sequence in brackets over 4 cycles (=4s).
So each of the 4 notes is 1s long.
Try adding more notes inside the brackets and notice how it gets faster.
</Box>
Because it is so common to just play one thing per cycle, you can..
**Play one per cycle with \< \>**
<MiniRepl hideHeader client:visible tune={`note("<36 34 41 39>").sound("gm_acoustic_bass")`} punchcard />
<Box>
Try adding more notes inside the brackets and notice how it does **not** get faster.
</Box>
**Play one sequence per cycle**
{/* <[c2 c3]*4 [bb1 bb2]*4 [f2 f3]*4 [eb2 eb3]*4>/2 */}
<MiniRepl
hideHeader
client:visible
tune={`note("<[36 48]*4 [34 46]*4 [41 53]*4 [39 51]*4>/2")
.sound("gm_acoustic_bass")`}
punchcard
/>
**Alternate between multiple things**
<MiniRepl
hideHeader
client:visible
tune={`note("60 <63 62 65 63>")
.sound("gm_xylophone")`}
punchcard
/>
This is also useful for unpitched sounds:
<MiniRepl
hideHeader
client:visible
tune={`sound("bd*2, ~ <sd cp>, [~ hh]*2")
.bank("RolandTR909")`}
punchcard
/>
## Scales
Finding the right notes can be difficult.. Scales are here to help:
<MiniRepl
hideHeader
client:visible
tune={`n("0 2 4 <[6,8] [7,9]>")
.scale("C:minor").sound("piano")`}
punchcard
/>
<Box>
Try out different numbers. Any number should sound good!
Try out different scales:
- C:major
- A2:minor
- D:dorian
- G:mixolydian
- A2:minor:pentatonic
- F:major:pentatonic
</Box>
**automate scales**
Just like anything, we can automate the scale with a pattern:
<MiniRepl
hideHeader
client:visible
tune={`n("<0 -3>, 2 4 <[6,8] [7,9]>")
.scale("<C:major D:mixolydian>/4")
.sound("piano")`}
punchcard
/>
<Box>
If you have no idea what these scale mean, don't worry.
These are just labels for different sets of notes that go well together.
Take your time and you'll find scales you like!
</Box>
## Repeat & Elongate
**Elongate with @**
<MiniRepl hideHeader client:visible tune={`note("c@3 eb").sound("gm_acoustic_bass")`} punchcard />
<Box>
Not using `@` is like using `@1`. In the above example, c is 3 units long and eb is 1 unit long.
Try changing that number!
</Box>
**Elongate within sub-sequences**
<MiniRepl
hideHeader
client:visible
tune={`n("<[4@2 4] [5@2 5] [6@2 6] [5@2 5]>*2")
.scale("<C2:mixolydian F2:mixolydian>/4")
.sound("gm_acoustic_bass")`}
punchcard
/>
<Box>
This groove is called a `shuffle`.
Each beat has two notes, where the first is twice as long as the second.
This is also sometimes called triplet swing. You'll often find it in blues and jazz.
</Box>
**Replicate**
<MiniRepl hideHeader client:visible tune={`note("c!2 [eb,<g a bb a>]").sound("piano")`} punchcard />
<Box>
Try switching between `!`, `*` and `@`
What's the difference?
</Box>
## Recap
Let's recap what we've learned in this chapter:
| Concept | Syntax | Example |
| --------- | ------ | ------------------------------------------------------------------- |
| 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")`} /> |
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**
<MiniRepl
hideHeader
client:visible
tune={`note("<[c2 c3]*4 [bb1 bb2]*4 [f2 f3]*4 [eb2 eb3]*4>/2")
.sound("gm_synth_bass_1")
.lpf(800) // <-- we'll learn about this soon`}
/>
**Classy Melody**
<MiniRepl
hideHeader
client:visible
tune={`n(\`<
[~ 0] 2 [0 2] [~ 2]
[~ 0] 1 [0 1] [~ 1]
[~ 0] 3 [0 3] [~ 3]
[~ 0] 2 [0 2] [~ 2]
>*2\`).scale("C4:minor")
.sound("gm_synth_strings_1")`}
/>
**Classy Drums**
<MiniRepl
hideHeader
client:visible
tune={`sound("bd*2, ~ <sd cp>, [~ hh]*2")
.bank("RolandTR909")`}
/>
**If there just was a way to play all the above at the same time.......**
<Box>
It's called `stack` 😙
</Box>
<MiniRepl
hideHeader
client:visible
tune={`stack(
note("<[c2 c3]*4 [bb1 bb2]*4 [f2 f3]*4 [eb2 eb3]*4>/2")
.sound("gm_synth_bass_1").lpf(800),
n(\`<
[~ 0] 2 [0 2] [~ 2]
[~ 0] 1 [0 1] [~ 1]
[~ 0] 3 [0 3] [~ 3]
[~ 0] 2 [0 2] [~ 2]
>*2\`).scale("C4:minor")
.sound("gm_synth_strings_1"),
sound("bd*2, ~ <sd cp>, [~ hh]*2")
.bank("RolandTR909")
)`}
/>
This is starting to sound like actual music! We have sounds, we have notes, now the last piece of the puzzle is missing: [effects](/workshop/first-effects)

View File

@ -0,0 +1,310 @@
---
title: Erste Sounds
layout: ../../../layouts/MainLayout.astro
---
import { MiniRepl } from '@src/docs/MiniRepl';
import Box from '@components/Box.astro';
import QA from '@components/QA';
## Erste Sounds
{/* Let's start by making some noise: */}
Los geht's mit ein paar Sounds:
<MiniRepl hideHeader client:visible tune={`sound("house")`} />
<Box>
1. ⬆️ Klicke in das obige Textfeld ⬆️
2. Drücke `Strg`+`Enter` zum Abspielen
3. Ändere `house` in `casio`
4. Drücke `Strg`+`Enter` zum Aktualisieren
5. Drücke `Strg`+`.` zum Stoppen
</Box>
Glückwunsch, du bist nun am live coden!
**Probiere mehr Sounds aus**
Mit ":" kannst du einen anderen Sound aus dem Set wählen:
<MiniRepl hideHeader client:visible tune={`sound("east:1")`} hideHeader />
<Box>
Ändere `east:1` in `east:2` um einen anderen Sound aus dem Set `east` zu hören.
Du kannst auch andere Zahlen ausprobieren! Es kann sein dass du kurz nichts hörst während ein neuer Sound lädt.
</Box>
Hier sind ein paar mehr Sounds zum ausprobieren:
```
casio control crow techno house jazz
metal east jvbass juno insect space wind
```
Jetzt weißt du wie man verschiedene Sounds benutzt.
Vorerst bleiben wir bei den voreingestellten Sounds, später erfahren wir noch wie man eigene benutzt.
## Drum Sounds
Strudel kommt von Haus aus mit einer breiten Auswahl an Drum Sounds:
<MiniRepl hideHeader client:visible tune={`sound("bd hh sd oh")`} hideHeader />
Diese 2-Buchstaben Kombinationen stehen für verschiedene Teile eines Drumsets:
- `bd` = **b**ass **d**rum - Basstrommel
- `sd` = **s**nare **d**rum - Schnarrtrommel
- `sn` = **sn**are
- `rim` = **rim**shot - Rahmenschlag
- `hh` = **h**i**h**at
- `oh` = **o**pen **h**ihat - Offenes Hi-Hat
Wir können den Charakter des Drum Sounds verändern, indem wir mit `bank` die Drum Machine auswählen:
{/* To change the sound character of our drums, we can use `bank` to change the drum machine: */}
<MiniRepl hideHeader client:visible tune={`sound("bd hh sd oh").bank("RolandTR909")`} hideHeader />
In diesem Beispiel ist `RolandTR909` der Name der Drum Machine, welche eine prägende Rolle für House und Techno Musik spielte.
<Box>
Ändere `RolandTR909` in
- `AkaiLinn`
- `RhythmAce`
- `RolandTR808`
- `RolandTR707`
- `ViscoSpaceDrum`
Es gibt noch viel mehr, aber das sollte fürs Erste reichen..
</Box>
## Sequenzen / Sequences
Im letzten Beispiel haben wir schon gesehen dass man mehrere Sounds hintereinander abspielen kann wenn man sie durch Leerzeichen trennt:
<MiniRepl hideHeader client:visible tune={`sound("bd hh sd hh")`} punchcard />
Beachte wie der aktuell gespielte Sound im Code markiert und auch darunter visualisiert wird.
<Box>
Versuch noch mehr Sounds hinzuzfügen!
</Box>
**Je länger die Sequence, desto schneller**
<MiniRepl hideHeader client:visible tune={`sound("bd bd hh bd sn bd hh bd")`} punchcard />
Der Inhalt einer Sequence wird in einen sogenannten Cycle (=Zyklus) zusammengequetscht.
**Tempo ändern mit `cpm`**
<MiniRepl hideHeader client:visible tune={`sound("bd bd hh bd sn bd hh bd").cpm(40)`} punchcard />
<Box>
cpm = **c**ycles per **m**inute = Cycles pro Minute
Das Tempo ist standardmäßig auf 60cpm eingestellt, also 1 Cycle pro Sekunde.
</Box>
Wir werden später noch mehr Möglichkeiten kennen lernen wie man das Tempo verändert.
**Pausen mit '~'**
<MiniRepl hideHeader client:visible tune={`sound("bd hh ~ rim")`} punchcard />
**Unter-Sequenzen mit [Klammern]**
<MiniRepl hideHeader client:visible tune={`sound("bd [hh hh] sn [hh bd]")`} punchcard />
<Box>
Füge noch mehr Sounds in die Klammern ein!
</Box>
Genau wie bei der ganzen Sequence wird der eine Unter-Sequence schneller je mehr drin ist.
**Multiplikation: Dinge schneller machen**
<MiniRepl hideHeader client:visible tune={`sound("bd hh*2 sn hh*3")`} punchcard />
**Multiplikation: Unter-Sequences schneller machen**
<MiniRepl hideHeader client:visible tune={`sound("bd [hh sn]*2")`} punchcard />
**Multiplikation: Vieeeeeeel schneller**
<MiniRepl hideHeader client:visible tune={`sound("bd hh*16 sn hh*8")`} punchcard />
<Box>
Tonhöhe = sehr schneller Rhythmus
</Box>
**Unter-Unter-Sequenzen mit [[Klammern]]**
<MiniRepl hideHeader client:visible tune={`sound("bd [[sn sn] hh]")`} punchcard />
<Box>
Du kannst so tief verschachteln wie du willst!
</Box>
**Parallele Sequenzen mit Komma**
<MiniRepl hideHeader client:visible tune={`sound("hh hh hh, bd casio")`} punchcard />
Du kannst soviele Kommas benutzen wie du magst:
<MiniRepl hideHeader client:visible tune={`sound("hh hh hh, bd bd, ~ casio")`} punchcard />
Kommas können auch in Unter-Sequenzen verwendet werden:
<MiniRepl hideHeader client:visible tune={`sound("hh hh hh, bd [bd,casio]")`} punchcard />
<Box>
Ist dir aufgefallen dass sich die letzten beiden Beispiele gleich anhören?
Es kommt öfter vor dass man die gleiche Idee auf verschiedene Arten ausdrücken kann.
</Box>
**Mehrere Zeilen mit \`**
<MiniRepl
hideHeader
client:visible
tune={`sound(\`bd*2, ~ cp,
~ ~ ~ oh, hh*4,
[~ perc:1*2]*2,
[~ jvbass]*2\`)`}
punchcard
/>
**Sound Nummer separat auswählen**
Anstatt mit ":" kann man die Sound Nummer auch separat mir der `n` Funktion steuern:
<MiniRepl hideHeader client:visible tune={`n("0 1 [4 2] 3*2").sound("jazz")`} punchcard />
Das ist kürzer und lesbarer als:
<MiniRepl hideHeader client:visible tune={`sound("jazz:0 jazz:1 [jazz:4 jazz:2] jazz:3*2")`} punchcard />
## Rückblick
Wir haben jetzt die Grundlagen der sogenannten Mini-Notation gelernt, der Rhythmus-Sprache von Tidal.
Das haben wir bisher gelernt:
| Concept | Syntax | Example |
| --------------------- | ----------- | -------------------------------------------------------------------------------- |
| Sequenz | Leerzeichen | <MiniRepl hideHeader client:visible tune={`sound("bd bd sn hh")`} /> |
| Sound Nummer | :x | <MiniRepl hideHeader client:visible tune={`sound("hh:0 hh:1 hh:2 hh:3")`} /> |
| Pausen | ~ | <MiniRepl hideHeader client:visible tune={`sound("metal ~ jazz jazz:1")`} /> |
| Unter-Sequenzen | \[\] | <MiniRepl hideHeader client:visible tune={`sound("bd wind [metal jazz] hh")`} /> |
| Unter-Unter-Sequenzen | \[\[\]\] | <MiniRepl hideHeader client:visible tune={`sound("bd [metal [jazz sn]]")`} /> |
| Schneller | \* | <MiniRepl hideHeader client:visible tune={`sound("bd sn*2 cp*3")`} /> |
| Parallel | , | <MiniRepl hideHeader client:visible tune={`sound("bd*2, hh*2 [hh oh]")`} /> |
Die mit Apostrophen umgebene Mini-Notation benutzt man normalerweise in eine sogenannten Funktion.
Die folgenden Funktionen haben wir bereits gesehen:
| Name | Description | Example |
| ----- | -------------------------------------- | ---------------------------------------------------------------------------------- |
| sound | Spielt den Sound mit dem Namen | <MiniRepl hideHeader client:visible tune={`sound("bd sd")`} /> |
| bank | Wählt die Soundbank / Drum Machine | <MiniRepl hideHeader client:visible tune={`sound("bd sd").bank("RolandTR909")`} /> |
| cpm | Tempo in **C**ycles **p**ro **M**inute | <MiniRepl hideHeader client:visible tune={`sound("bd sd").cpm(90)`} /> |
| n | Sample Nummer | <MiniRepl hideHeader client:visible tune={`n("0 1 4 2").sound("jazz")`} /> |
## Beispiele
**Einfacher Rock Beat**
<MiniRepl hideHeader client:visible tune={`sound("bd sd, hh*4").bank("RolandTR505").cpm(100/2)`} punchcard />
**Klassischer House**
<MiniRepl hideHeader client:visible tune={`sound("bd*2, ~ cp, [~ hh]*2").bank("RolandTR909")`} punchcard />
<Box>
Ist die aufgefallen dass die letzten 2 Patterns extrem ähnlich sind?
Bestimmte Drum Patterns werden oft genreübergreifend wiederverwendet.
</Box>
We Will Rock you
<MiniRepl hideHeader client:visible tune={`sound("bd*2 cp").bank("RolandTR707").cpm(81/2)`} punchcard />
**Yellow Magic Orchestra - Firecracker**
<MiniRepl
hideHeader
client:visible
tune={`sound("bd sd, ~ ~ ~ hh ~ hh ~ ~, ~ perc ~ perc:1*2")
.bank("RolandCompurhythm1000")`}
punchcard
/>
**Nachahmung eines 16 step sequencers**
<MiniRepl
hideHeader
client:visible
tune={`sound(\`
[~ ~ oh ~ ] [~ ~ ~ ~ ] [~ ~ ~ ~ ] [~ ~ ~ ~ ],
[hh hh ~ ~ ] [hh ~ hh ~ ] [hh ~ hh ~ ] [hh ~ hh ~ ],
[~ ~ ~ ~ ] [cp ~ ~ ~ ] [~ ~ ~ ~ ] [cp ~ ~ ~ ],
[bd ~ ~ ~ ] [~ ~ ~ bd] [~ ~ bd ~ ] [~ ~ ~ bd]
\`).cpm(90/4)`}
punchcard
/>
**Noch eins**
<MiniRepl
hideHeader
client:visible
tune={`sound(\`
[~ ~ ~ ~ ] [~ ~ ~ ~ ] [~ ~ ~ ~ ] [~ ~ oh:1 ~ ],
[hh hh hh hh] [hh hh hh hh] [hh hh hh hh] [hh hh ~ ~ ],
[~ ~ ~ ~ ] [cp ~ ~ ~ ] [~ ~ ~ ~ ] [~ cp ~ ~ ],
[bd bd ~ ~ ] [~ ~ bd ~ ] [bd bd ~ bd ] [~ ~ ~ ~ ]
\`).bank("RolandTR808").cpm(88/4)`}
punchcard
/>
**Nicht so typische Drums**
<MiniRepl
hideHeader
client:visible
tune={`s(\`jazz*2,
insect [crow metal] ~ ~,
~ space:4 ~ space:1,
~ wind\`)
.cpm(100/2)`}
punchcard
/>
Jetzt haben wir eine grundlegende Ahnung davon wie man mit Strudel Beats baut!
Im nächsten Kapitel werden wir ein paar [Töne spielen](/workshop/first-notes).

View File

@ -0,0 +1,3 @@
<script is:inline>
window.location.pathname = `/workshop/intro`;
</script>

View File

@ -0,0 +1,22 @@
---
title: Introduction
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,154 @@
<Box>
1. press play button to start
2. change `house` to `casio`
3. press refresh button to update
4. press stop button to stop
</Box>
**Change tempo**
<MiniRepl
client:load
tune={`setcps(.5)
sound("bd bd hh bd sn bd hh bd")`}
punchcard
/>
adding your own samples
<MiniRepl
client:visible
tune={`sound(\`
[~ ~ oh ~ ] [~ ~ ~ ~ ] [~ ~ ~ ~ ] [~ ~ ~ ~ ],
[hh hh ~ ~ ] [hh ~ hh ~ ] [hh ~ hh ~ ] [hh ~ hh ~ ],
[~ ~ ~ ~ ] [cp ~ ~ ~ ] [~ ~ ~ ~ ] [cp ~ ~ ~ ],
[bd ~ ~ ~ ] [~ ~ ~ bd] [~ ~ bd ~ ] [~ ~ ~ bd ]
\`).slow(3)`}
punchcard
/>
<MiniRepl
client:visible
tune={`sound(\`
[~ ~ ~ ~ ] [~ ~ ~ ~ ] [~ ~ ~ ~ ] [~ ~ oh:1 ~ ],
[hh hh hh hh] [hh hh hh hh] [hh hh hh hh] [hh hh ~ ~ ],
[~ ~ ~ ~ ] [cp ~ ~ ~ ] [~ ~ ~ ~ ] [~ cp ~ ~ ],
[bd bd ~ ~ ] [~ ~ bd ~ ] [bd bd ~ bd ] [~ ~ ~ ~ ]
\`).bank("<RolandTR808 AkaiMPC60>").slow(3)`}
punchcard
/>
n(run(8)).sound("east")
Shorter variant:
<MiniRepl
hideHeader
client:visible
tune={`sound(\`
[~ ~ oh ~ ] ~ ~ ~,
[hh*2 ~] hh*2 hh*2 hh*2,
[~ cp]*2,
bd [~ ~ ~ bd] [~ bd] [~ ~ ~ bd]
\`).cpm(90/4)`}
/>
polyrythms & polymeters
-- This can make for flexible time signatures:
d1 $ sound "[bd bd sn:5] [bd sn:3]"
-- You can put subsequences inside subsequences:
d1 $ sound "[[bd bd] bd sn:5] [bd sn:3]"
-- Keep going..
d1 $ sound "[[bd [bd bd bd bd]] bd sn:5] [bd sn:3]"
-- \* Polymetric / polyrhythmic sequences
-- Play two subsequences at once by separating with a comma:
d1 $ sound "[voodoo voodoo:3, arpy arpy:4 arpy:2]"
-- compare how [,] and {,} work:
d1 $ sound "[voodoo voodoo:3, arpy arpy:4 arpy:2]"
d1 $ sound "{voodoo voodoo:3, arpy arpy:4 arpy:2}"
d1 $ sound "[drum bd hh bd, can can:2 can:3 can:4 can:2]"
d1 $ sound "{drum bd hh bd, can can:2 can:3 can:4 can:2}"
d1 $ sound "[bd sn, can:2 can:3 can:1, arpy arpy:1 arpy:2 arpy:3 arpy:5]"
d1 $ sound "{bd sn, can:2 can:3 can:1, arpy arpy:1 arpy:2 arpy:3 arpy:5}"
**Play X per cycle with \{ \}**
<MiniRepl
hideHeader
client:visible
tune={`note(\`{
[~ 60] 63 [60 63] [~ 63]
[~ 60] 62 [60 62] [~ 62]
[~ 60] 65 [60 65] [~ 65]
[~ 60] 63 [60 63] [~ 63]
}%2\`).sound("gm_xylophone")`}
punchcard
/>
<Box>
Try different numbers after `%`
`{ ... }%1` is the same as `< ... >`
</Box>
## Bracket Recap
- `[]` squeezes contents to 1 cycle
- `<>` plays one item per cycle
- `{}%x` plays x items per cycle
<MiniRepl
hideHeader
client:visible
tune={`note("[0 12]*2".add("<36 34 41 39>/2"))
.sound("gm_synth_bass_1")`}
/>
vertical
<MiniRepl
hideHeader
client:visible
tune={`n(\`<
<[0,7] [-1,6] [-1,6] [-1,6]>
< 4 4 4 3>
<[2,7] [2,6] [1,6] [1,6]>
< 4 4 4 3>
>*2\`)
.scale("<E:minor>/4")
.sound("piano")`}
/>
horizontal
<MiniRepl
hideHeader
client:visible
tune={`
n(\`<
[0,7] 4 [2,7] 4
[-1,6] 4 [2,6] 4
[-1,6] 4 [1,6] 4
[-1,6] 3 [1,6] 3
>*2\`)
.scale("<E:minor>/4")
.sound("piano")`}
/>

View File

@ -0,0 +1,69 @@
---
title: First Sounds
layout: ../../../layouts/MainLayout.astro
---
import { MiniRepl } from '../../docs/MiniRepl';
# Mini Notation
Mini Notation is everything between the quotes. It the short rhythm language of Tidal.
## Cycles
**The longer the sequence, the faster it runs**
<MiniRepl client:load tune={`sound("bd bd hh bd sn bd hh bd")`} punchcard />
**Play less sounds per cycle with \{curly braces\}**
<MiniRepl client:load tune={`sound("{bd bd hh bd sn bd hh bd}%4")`} punchcard />
**Use \`backticks\` for multiple lines**
<MiniRepl
client:load
tune={`sound(\`{
bd bd hh bd
sn bd hh bd
sn bd hh bd
sn bd hh hh:4
}%4\`)`}
punchcard
/>
**Play one sounds per cycle with \<angle brackets\>**
<MiniRepl client:load tune={`sound("<bd bd hh bd sn bd hh bd>")`} punchcard />
This is the same as `{...}%1`
## Operators
**Multiplication: Speed things up**
<MiniRepl client:load tune={`sound("bd hh*2 sn hh*2")`} punchcard />
**Division: Slow things down**
<MiniRepl client:load tune={`sound("bd/2 sd, hh*4")`} punchcard />
`bd` will play only every second time
## Combining it all
**Speed up Sub-Sequences**
<MiniRepl client:load tune={`sound("bd [sn hh]*2 sd hh")`} punchcard />
**Slow down Sequences**
<MiniRepl client:load tune={`sound("[bd [sn hh] sd hh]/2")`} punchcard />
**Parallel Sub-Sequences**
<MiniRepl client:load tune={`sound("bd [sn,hh] sd [hh:2,sn]")`} punchcard />
**Sample Numbers on groups**
<MiniRepl client:load tune={`sound("bd [sn,hh] sd [hh,sn]:2")`} punchcard />

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
```