Merge pull request #1053 from tidalcycles/workshop-edits

improve tutorial + custom samples doc
This commit is contained in:
Felix Roos 2024-04-12 12:34:27 +02:00 committed by GitHub
commit e0c4997f1e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 265 additions and 205 deletions

View File

@ -1,6 +1,6 @@
{
"name": "@strudel/sampler",
"version": "0.0.8",
"version": "0.0.9",
"description": "",
"keywords": [
"tidalcycles",

Binary file not shown.

After

Width:  |  Height:  |  Size: 338 KiB

View File

@ -146,15 +146,13 @@ Wir schauen uns später noch mehr Möglichkeiten an wie man patterns kombiniert.
**Sequenzen verlangsamen mit `/`**
{/* [c2 bb1 f2 eb2] */}
<MiniRepl client:visible tune={`note("[36 34 41 39]/4").sound("gm_acoustic_bass")`} punchcard />
<Box>
Das `/4` spielt die Sequenz 4 mal so langsam, also insgesamt 4 cycles = 4s.
Das `/4` spielt die Sequenz 4 mal so langsam, also insgesamt 4 cycles = 8s.
Jede Note ist nun also 1s lang.
Jede Note ist nun also 2s lang.
Schreib noch mehr Töne in die Klammern und achte darauf dass es schneller wird.
@ -164,6 +162,9 @@ Wenn eine Sequenz unabhängig von ihrem Inhalt immer gleich schnell bleiben soll
**Eins pro Cycle per \< \>**
Im letzten Kapitel haben wir schon gelernt dass `< ... >` (angle brackets) nur ein Element pro Cycle spielt.
Das ist für Melodien auch sehr nützlich:
<MiniRepl client:visible tune={`note("<36 34 41 39>").sound("gm_acoustic_bass")`} punchcard />
<Box>

View File

@ -78,13 +78,24 @@ Strudel kommt von Haus aus mit einer breiten Auswahl an Drum Sounds:
<Box>
Diese 2-Buchstaben Kombinationen stehen für verschiedene Teile eines Schlagzeugs:
Diese Kombinationen von Buchstaben stehen für verschiedene Teile eines Schlagzeugs:
<img src="/img/drumset.png" />
<a class="text-right text-xs" href="https://de.wikipedia.org/wiki/Schlagzeug#/media/Datei:Drum_set.svg" target="_blank">
original von Pbroks13
</a>
- `bd` = **b**ass **d**rum - Basstrommel
- `sd` = **s**nare **d**rum - Schnarrtrommel
- `rim` = **rim**shot - Rahmenschlag
- `hh` = **h**i**h**at - Hallo Hut
- `oh` = **o**pen **h**ihat - Offener Hallo Hut
- `lt` = **l**ow tom
- `mt` = **m**iddle tom
- `ht` = **h**igh tom
- `rd` = **r**i**d**e cymbal
- `rd` = **cr**ash cymbal
Probier verschiedene Sounds aus!
@ -131,34 +142,58 @@ Versuch noch mehr Sounds hinzuzfügen!
<MiniRepl client:visible tune={`sound("bd bd hh bd rim bd hh bd")`} punchcard />
Der Inhalt einer Sequence wird in einen sogenannten Cycle (=Zyklus) zusammengequetscht.
Der Inhalt einer Sequence wird in einen sogenannten Cycle (=Zyklus) zusammengequetscht. Ein Cycle ist standardmäßig 2 Sekunden lang.
**Eins pro Cycle mit `< .. >`**
Hier ist die gleiche Sequence, aber dieses mal umgeben von `< .. >` (angle brackets):
<MiniRepl client:visible tune={`sound("<bd bd hh bd rim bd hh bd>")`} punchcard />
Jetzt spielt nur ein Sound pro Cycle. Mit diesen Klammern bleibt das Tempo immer gleich, ganz egal wieviele Elemente enhalten sind!
Das ist jetzt aber etwas langsam, machen wir es schneller mit `*`:
<MiniRepl client:visible tune={`sound("<bd bd hh bd rim bd hh bd>*8")`} punchcard />
Die `*8` macht die ganze Sequenz 8 mal so schnell.
<Box>
Warte mal, ist das jetzt nicht das gleiche Ergebnis wie ohne `< ... >*8`? Wofür ist das dann gut?
Korrekt, der echte Vorteil dieser Schreibweise zeigt sich wenn du Elemente entfernst oder hinzufügst. Versuch es mal!
Ändere auch mal die Zahl am Ende um das Tempo zu verändern.
</Box>
**Tempo ändern mit `cpm`**
<MiniRepl client:visible tune={`sound("bd bd hh bd rim bd hh bd").cpm(40)`} punchcard />
<MiniRepl client:visible tune={`sound("<bd hh rim hh>*8").cpm(90/4)`} punchcard />
<Box>
cpm = **c**ycles per **m**inute = Cycles pro Minute
Das Tempo ist standardmäßig auf 60cpm eingestellt, also 1 Cycle pro Sekunde.
Das Tempo is standardmäßig is 30 Cycles pro Minute = 120/4 = 1 Cycle alle 2 Sekunden
`cpm` ist angelehnt an `bpm` (=beats per minute).
In taditioneller Musik-Terminologie könnte man sagen, das Pattern oben besteht aus 8tel Noten auf 90bpm im 4/4 Takt.
Kein Sorge wenn dir diese Begriffe nichts sagen, das ist nicht notwendig um mit Strudel Musik zu machen.
</Box>
Wir werden später noch mehr Möglichkeiten kennen lernen das Tempo zu verändern.
**Pausen mit '~'**
**Pausen mit '-' oder '~'**
<MiniRepl client:visible tune={`sound("bd hh ~ rim")`} punchcard />
<MiniRepl client:visible tune={`sound("bd hh - rim")`} punchcard />
<Box>
Tilde tippen:
- Windows / Linux: `Alt Gr` + `~`
- Mac: `option` + `N`
Du siehst wahrscheinlich auch Patterns von anderen Leuten mit '~' als Pausensymbol.
Besonders für deutsche Tastaturen ist `-` eine Alternative zum schwer tippbaren `~`.
</Box>
@ -219,7 +254,7 @@ Du kannst so tief verschachteln wie du willst!
Du kannst so viele Kommas benutzen wie du möchtest:
<MiniRepl client:visible tune={`sound("hh hh hh, bd bd, ~ casio")`} punchcard />
<MiniRepl client:visible tune={`sound("hh hh hh, bd bd, - casio")`} punchcard />
Kommas können auch in Unter-Sequenzen verwendet werden:
@ -237,9 +272,9 @@ Es kommt öfter vor, dass man die gleiche Idee auf verschiedene Arten ausdrücke
<MiniRepl
client:visible
tune={`sound(\`bd*2, ~ cp,
~ ~ ~ oh, hh*4,
[~ casio]*2\`)`}
tune={`sound(\`bd*2, - cp,
- - - oh, hh*4,
[- casio]*2\`)`}
punchcard
/>
@ -269,7 +304,7 @@ Das haben wir bisher gelernt:
| --------------------- | ----------- | --------------------------------------------------------------------- |
| Sequenz | Leerzeichen | <MiniRepl client:visible tune={`sound("bd bd sd hh")`} /> |
| Sound Nummer | :x | <MiniRepl client:visible tune={`sound("hh:0 hh:1 hh:2 hh:3")`} /> |
| Pausen | ~ | <MiniRepl client:visible tune={`sound("metal ~ jazz jazz:1")`} /> |
| Pausen | - | <MiniRepl client:visible tune={`sound("metal - jazz jazz:1")`} /> |
| Unter-Sequenzen | \[\] | <MiniRepl client:visible tune={`sound("bd wind [metal jazz] hh")`} /> |
| Unter-Unter-Sequenzen | \[\[\]\] | <MiniRepl client:visible tune={`sound("bd [metal [jazz sd]]")`} /> |
| Schneller | \* | <MiniRepl client:visible tune={`sound("bd sd*2 cp*3")`} /> |
@ -293,7 +328,7 @@ Die folgenden Funktionen haben wir bereits gesehen:
**Klassischer House**
<MiniRepl client:visible tune={`sound("bd*2, ~ cp, [~ hh]*2").bank("RolandTR909")`} punchcard />
<MiniRepl client:visible tune={`sound("bd*2, - cp, [- hh]*2").bank("RolandTR909")`} punchcard />
<Box>
@ -310,7 +345,7 @@ We Will Rock you
<MiniRepl
client:visible
tune={`sound("bd sd, ~ ~ ~ hh ~ hh ~ ~, ~ perc ~ perc:1*2")
tune={`sound("bd sd, - - - hh - hh - -, - perc - perc:1*2")
.bank("RolandCompurhythm1000")`}
punchcard
/>
@ -320,10 +355,10 @@ We Will Rock you
<MiniRepl
client:visible
tune={`sound(\`
[~ ~ oh ~ ] [~ ~ ~ ~ ] [~ ~ ~ ~ ] [~ ~ ~ ~ ],
[hh hh ~ ~ ] [hh ~ hh ~ ] [hh ~ hh ~ ] [hh ~ hh ~ ],
[~ ~ ~ ~ ] [cp ~ ~ ~ ] [~ ~ ~ ~ ] [cp ~ ~ ~ ],
[bd ~ ~ ~ ] [~ ~ ~ bd] [~ ~ bd ~ ] [~ ~ ~ bd]
[- - oh - ] [- - - - ] [- - - - ] [- - - - ],
[hh hh - - ] [hh - hh - ] [hh - hh - ] [hh - hh - ],
[- - - - ] [cp - - - ] [- - - - ] [cp - - - ],
[bd - - - ] [- - - bd] [- - bd - ] [- - - bd]
\`).cpm(90/4)`}
punchcard
/>
@ -333,10 +368,10 @@ We Will Rock you
<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 ] [~ ~ ~ ~ ]
[- - - - ] [- - - - ] [- - - - ] [- - 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
/>
@ -346,9 +381,9 @@ We Will Rock you
<MiniRepl
client:visible
tune={`s(\`jazz*2,
insect [crow metal] ~ ~,
~ space:4 ~ space:1,
~ wind\`)
insect [crow metal] - -,
- space:4 - space:1,
- wind\`)
.cpm(100/2)`}
punchcard
/>

View File

@ -24,20 +24,31 @@ Here, we are using the `s` function to play back different default samples (`bd`
For drum sounds, strudel uses the comprehensive [tidal-drum-machines](https://github.com/ritchse/tidal-drum-machines) library, with the following naming convention:
| Drum | Abbreviation |
| Drum | Abbreviation |
| -------------------- | ------------ |
| Bass drum, Kick drum | bd |
| Snare drum | sd |
| Rimshot | rim |
| Clap | cp |
| Closed hi-hat | hh |
| Open hi-hat | oh |
| Crash | cr |
| Ride | rd |
| High tom | ht |
| Medium tom | mt |
| Low tom | lt |
<img src="/img/drumset.png" />
<a class="text-right text-xs" href="https://de.wikipedia.org/wiki/Schlagzeug#/media/Datei:Drum_set.svg" target="_blank">
original von Pbroks13
</a>
More percussive sounds:
| Source | Abbreviation |
| ----------------------------------- | ------------ |
| Bass drum, Kick drum | bd |
| Snare drum | sd |
| Rimshot | rim |
| Clap | cp |
| Closed hi-hat | hh |
| Open hi-hat | oh |
| Crash | cr |
| Ride | rd |
| Shakers (and maracas, cabasas, etc) | sh |
| High tom | ht |
| Medium tom | mt |
| Low tom | lt |
| Cowbell | cb |
| Tambourine | tb |
| Other percussions | perc |
@ -63,11 +74,11 @@ We _could_ use them like this:
... but thats obviously a bit much to write. Using the `bank` function, we can shorten this to:
<MiniRepl client:idle tune={`s("bd sd bd sd,hh*16").bank("RolandTR808")`} />
<MiniRepl client:idle tune={`s("bd sd,hh*16").bank("RolandTR808")`} />
You could even pattern the bank to switch between different drum machines:
<MiniRepl client:idle tune={`s("bd sd bd sd,hh*16").bank("RolandTR808 RolandTR909")`} />
<MiniRepl client:idle tune={`s("bd sd,hh*16").bank("<RolandTR808 RolandTR909>")`} />
Behind the scenes, `bank` will just prepend the drum machine name to the sample name with `_` to get the full name.
This of course only works because the name after `_` (`bd`, `sd` etc..) is standardized.
@ -97,159 +108,128 @@ Selecting sounds also works inside the mini notation, using "`:`" like this:
# Loading Custom Samples
You can load your own sample map using the `samples` function.
In this example we create a map using sounds from the default sample map:
You can load a non-standard sample map using the `samples` function.
<MiniRepl
client:idle
tune={`samples({
bd: 'bd/BT0AADA.wav',
sd: 'sd/rytm-01-classic.wav',
hh: 'hh27/000_hh27closedhh.wav',
}, 'https://raw.githubusercontent.com/tidalcycles/Dirt-Samples/master/');
s("bd sd bd sd,hh*16")`}
/>
## Loading samples from file URLs
When you load your own samples, you can choose the names that you will then refer to in your pattern string inside the `s` function.
Compare with this example which uses the same samples, but with different names.
In this example we assign names `bassdrum`, `hihat` and `snaredrum` to specific audio files on a server:
<MiniRepl
client:idle
tune={`samples({
bassdrum: 'bd/BT0AADA.wav',
snaredrum: 'sd/rytm-01-classic.wav',
hihat: 'hh27/000_hh27closedhh.wav',
snaredrum: ['sd/rytm-01-classic.wav', 'sd/rytm-00-hard.wav'],
}, 'https://raw.githubusercontent.com/tidalcycles/Dirt-Samples/master/');
s("bassdrum snaredrum bassdrum snaredrum, hihat*16")`}
s("bassdrum snaredrum:0 bassdrum snaredrum:1, hihat*16")`}
/>
Here we have changed the "map" to include longer sample names.
You can freely choose any combination of letters for each sample name. It is even possible to override the default sounds.
The names you pick will be made available in the `s` function.
Make sure that the URL and each sample path form a correct URL!
## The `samples` function
In the above example, `bassdrum` will load:
The `samples` function has two arguments:
```
https://raw.githubusercontent.com/tidalcycles/Dirt-Samples/master/bd/BT0AADA.wav
|----------------------base path --------------------------------|--sample path-|
```
- A [JavaScript object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object) that maps sound names to audio file paths.
- A base URL that comes before each path describing where the sample folder can be found online.
- Make sure your base URL ends with a slash, while your sample paths do **not** begin with one!
Note that we can either load a single file, like for `bassdrum` and `hihat`, or a list of files like for `snaredrum`!
As soon as you run the code, your chosen sample names will be listed in `sounds` -> `user`.
To see how this looks in practice, compare the [DirtSamples GitHub repo](https://github.com/tidalcycles/Dirt-Samples) with the previous sample map example.
## Loading Samples from a strudel.json file
Because GitHub is a popular place for uploading open source samples, it has its own shortcut:
The above way to load samples might be tedious to write out / copy paste each time you write a new pattern.
To avoid that, you can simply pass a URL to a `strudel.json` file somewhere on the internet:
<MiniRepl
client:idle
tune={`samples({
bd: 'bd/BT0AADA.wav',
sd: 'sd/rytm-01-classic.wav',
hh: 'hh27/000_hh27closedhh.wav',
}, 'github:tidalcycles/dirt-samples');
tune={`samples('https://raw.githubusercontent.com/tidalcycles/Dirt-Samples/master/strudel.json')
s("bd sd bd sd,hh*16")`}
/>
The format is `github:user/repo/branch/`.
The file is expected to define a sample map using JSON, in the same format as described above.
Additionally, the base path can be defined with the `_base` key.
The last section could be written as:
Let's see another example, this time based on the following GitHub repo: https://github.com/jarmitage/jarmitage.github.io.
We can see there are some guitar samples inside the `/samples` folder, so let's try to load them:
```json
{
"_base": "https://raw.githubusercontent.com/tidalcycles/Dirt-Samples/master/",
"bassdrum": "bd/BT0AADA.wav",
"snaredrum": "sd/rytm-01-classic.wav",
"hihat": "hh27/000_hh27closedhh.wav"
}
```
## Github Shortcut
Because loading samples from github is common, there is a shortcut:
<MiniRepl
client:idle
tune={`samples({
g0: 'samples/guitar/guitar_0.wav',
g1: 'samples/guitar/guitar_1.wav',
g2: 'samples/guitar/guitar_2.wav',
g3: 'samples/guitar/guitar_3.wav',
g4: 'samples/guitar/guitar_4.wav'
}, 'github:jarmitage/jarmitage.github.io/master/');
s("<g0 g1 g2 g3 g4>/2")`}
tune={`samples('github:tidalcycles/dirt-samples')
s("bd sd bd sd,hh*16")`}
/>
## Multiple Samples per Sound
The format is `samples('github:<user>/<repo>/<branch>')`. If you omit `branch` (like above), the `main` branch will be used.
It assumes a `strudel.json` file to be present at the root of the repository:
It is also possible, to declare multiple files for one sound, using the array notation:
```
https://raw.githubusercontent.com/<user>/<repo>/<branch>/strudel.json
```
## From Disk via "Import Sounds"
If you don't want to upload your samples to the internet, you can also load them from your local disk.
Go to the `sounds` tab in the REPL and press "import sounds".
Then you can select a folder that contains audio files. The folder you select can also contain subfolders with audio files.
Example:
```
└─ samples
├─ swoop
│ ├─ swoopshort.wav
│ ├─ swooplong.wav
│ └─ swooptight.wav
└─ smash
├─ smashhigh.wav
├─ smashlow.wav
└─ smashmiddle.wav
```
In the above example the folder `samples` contains 2 subfolders `swoop` and `smash`, which contain audio files.
If you select that `samples` folder, the `user` tab (next to the import sounds button) will then contain 2 new sounds: `swoop(3) smash(3)`
The individual samples can the be played normally like `s("swoop:0 swoop:1 smash:2")`.
## From Disk via @strudel/sampler
Instead of loading your samples into your browser with the "import sounds" button, you can also serve the samples from a local file server.
The easiest way to do this is using [@strudel/sampler](https://www.npmjs.com/package/@strudel/sampler):
```sh
cd samples
npx @strudel/sampler
```
Then you can load it via:
<MiniRepl
client:idle
tune={`samples({
bd: ['bd/BT0AADA.wav','bd/BT0AAD0.wav'],
sd: ['sd/rytm-01-classic.wav','sd/rytm-00-hard.wav'],
hh: ['hh27/000_hh27closedhh.wav','hh/000_hh3closedhh.wav'],
}, 'github:tidalcycles/dirt-samples');
s("bd:0 bd:1,~ <sd:0 sd:1> ~ sd:0,[hh:0 hh:1]*4")`}
tune={`samples('http://localhost:5432/');
n("<0 1 2>").s("swoop smash")`}
/>
The `:0` `:1` etc. are the indices of the array.
The sample number can also be set using `n`:
The handy thing about `@strudel/sampler` is that it auto-generates the `strudel.json` file based on your folder structure.
You can see what it generated by going to `http://localhost:5432` with your browser.
<MiniRepl
client:idle
tune={`samples({
bd: ['bd/BT0AADA.wav','bd/BT0AAD0.wav'],
sd: ['sd/rytm-01-classic.wav','sd/rytm-00-hard.wav'],
hh: ['hh27/000_hh27closedhh.wav','hh/000_hh3closedhh.wav'],
}, 'github:tidalcycles/dirt-samples');
s("bd bd,~ sd ~ sd,hh*8").n("<0 1>")`}
/>
Note: You need [NodeJS](https://nodejs.org/) installed on your system for this to work.
In that case, we might load our guitar sample map a different way:
## Specifying Pitch
<MiniRepl
client:idle
tune={`samples({
guitar: [
'samples/guitar/guitar_0.wav',
'samples/guitar/guitar_1.wav',
'samples/guitar/guitar_2.wav',
'samples/guitar/guitar_3.wav',
'samples/guitar/guitar_4.wav'
]
}, 'github:jarmitage/jarmitage.github.io/master/');
s("<guitar:0 guitar:1 guitar:2 guitar:3 guitar:4>*2")`}
/>
And as above, we can choose the sample number using `n` for even more flexibility:
<MiniRepl
client:idle
tune={`samples({
guitar: [
'samples/guitar/guitar_0.wav',
'samples/guitar/guitar_1.wav',
'samples/guitar/guitar_2.wav',
'samples/guitar/guitar_3.wav',
'samples/guitar/guitar_4.wav'
]
}, 'github:jarmitage/jarmitage.github.io/master/');
n("<0 1 2 3 4>*2").s("guitar")`}
/>
## Pitched Sounds
For pitched sounds, you can use `note`, just like with synths:
<MiniRepl
client:idle
tune={`samples({
'gtr': 'gtr/0001_cleanC.wav',
}, 'github:tidalcycles/dirt-samples');
note("g3 [bb3 c4] <g4 f4 eb4 f3>@2").s('gtr').gain(.5)`}
/>
Here, the guitar samples will overlap, because they always play till the end.
If we want them to behave more like a synth, we can add `clip(1)`:
<MiniRepl
client:idle
tune={`samples({
'gtr': 'gtr/0001_cleanC.wav',
}, 'github:tidalcycles/dirt-samples');
note("g3 [bb3 c4] <g4 f4 eb4 f3>@2").s('gtr').clip(1)
.gain(.5)`}
/>
## Base Pitch
If we have 2 samples with different base pitches, we can make them in tune by specifying the pitch like this:
To make sure your samples are in tune when playing them with `note`, you can specify a base pitch like this:
<MiniRepl
client:idle
@ -261,8 +241,6 @@ note("g3 [bb3 c4] <g4 f4 eb4 f3>@2").s("gtr,moog").clip(1)
.gain(.5)`}
/>
If a sample has no pitch set, `c3` is the default.
We can also declare different samples for different regions of the keyboard:
<MiniRepl
@ -280,6 +258,8 @@ note("g2!2 <bb2 c3>!2, <c4@3 [<eb4 bb3> g4 f4]>")
The sampler will always pick the closest matching sample for the current note!
Note that this notation for pitched sounds also works inside a `strudel.json` file.
## Shabda
If you don't want to select samples by hand, there is also the wonderful tool called [shabda](https://shabda.ndre.gr/).

View File

@ -147,35 +147,43 @@ We will see more ways to combine patterns later..
**Divide sequences with `/` to slow them down**
{/* [c2 bb1 f2 eb2] */}
<MiniRepl 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).
The `/4` plays the sequence in brackets over 4 cycles (=8s).
So each of the 4 notes is 1s long.
So each of the 4 notes is 2s 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 `< ... >`**
**Play one per cycle with \< \>**
In the last section, we learned that `< ... >` (angle brackets) can be used to play only one thing per cycle,
which is useful for longer melodies too:
<MiniRepl 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.
Try adding more notes inside the brackets and notice how the tempo stays the same.
The angle brackets are actually just a shortcut:
`<a b c>` = `[a b c]/3`
`<a b c d>` = `[a b c d]/4`
...
</Box>
**Play one sequence per cycle**
{/* <[c2 c3]*4 [bb1 bb2]*4 [f2 f3]*4 [eb2 eb3]*4> */}
We can combine the 2 types of brackets in all sorts of different ways.
Here is an example of a repetitive bassline:
<MiniRepl
client:visible

View File

@ -78,11 +78,22 @@ By default, Strudel comes with a wide selection of drum sounds:
These letter combinations stand for different parts of a drum set:
<img src="/img/drumset.png" />
<a class="text-right text-xs" href="https://de.wikipedia.org/wiki/Schlagzeug#/media/Datei:Drum_set.svg" target="_blank">
original image by Pbroks13
</a>
- `bd` = **b**ass **d**rum
- `sd` = **s**nare **d**rum
- `rim` = **rim**shot
- `hh` = **h**i**h**at
- `oh` = **o**pen **h**ihat
- `lt` = **l**ow tom
- `mt` = **m**iddle tom
- `ht` = **h**igh tom
- `rd` = **r**i**d**e cymbal
- `rd` = **cr**ash cymbal
Try out different drum sounds!
@ -129,29 +140,54 @@ Try adding more sounds to the sequence!
<MiniRepl client:visible tune={`sound("bd bd hh bd rim bd hh bd")`} punchcard />
The content of a sequence will be squished into what's called a cycle.
The content of a sequence will be squished into what's called a cycle. A cycle is 2s long by default.
**One way to change the tempo is using `cpm`**
**One per cycle with `< .. >`**
<MiniRepl client:visible tune={`sound("bd bd hh bd rim bd hh bd").cpm(40)`} punchcard />
Here is the same sequence, but this time sourrounded with `< .. >` (angle brackets):
<MiniRepl client:visible tune={`sound("<bd bd hh bd rim bd hh bd>")`} punchcard />
This will play only one sound per cycle. With these brackets, the tempo doesn't change when we add or remove elements!
Because this is now very slow, we can speed it up again like this:
<MiniRepl client:visible tune={`sound("<bd bd hh bd rim bd hh bd>*8")`} punchcard />
Here, the `*8` means we make the whole thing 8 times faster.
<Box>
Wait a minute, isn't this the same as without `< ... >*8`? Why do we need it then?
That's true, the special thing about this notation is that the tempo won't change when you add or remove elements, try it!
Try also changing the number at the end to change the tempo!
</Box>
**changing the tempo with cpm**
<MiniRepl client:visible tune={`sound("<bd hh rim hh>*8").cpm(90/4)`} punchcard />
<Box>
cpm = cycles per minute
By default, the tempo is 30 cycles per minute = 1 half cycle per second.
By default, the tempo is 30 cycles per minute = 120/4 = 1 cycle every 2 seconds
In western music terms, you could say the above are 8ths notes at 90bpm in 4/4 time.
But don't worry if you don't know these terms, as they are not required to make music with Strudel.
</Box>
We will look at other ways to change the tempo later!
**Add a rests in a sequence with '-' or '~'**
**Add a rests in a sequence with '~'**
<MiniRepl client:visible tune={`sound("bd hh ~ rim ~ bd hh rim")`} punchcard />
<MiniRepl client:visible tune={`sound("bd hh - rim - bd hh rim")`} punchcard />
**Sub-Sequences with [brackets]**
<MiniRepl client:visible tune={`sound("bd [hh hh] sd [hh bd] bd ~ [hh sd] cp")`} punchcard />
<MiniRepl client:visible tune={`sound("bd [hh hh] sd [hh bd] bd - [hh sd] cp")`} punchcard />
<Box>
@ -163,7 +199,7 @@ Similar to the whole sequence, the content of a sub-sequence will be squished to
**Multiplication: Speed things up**
<MiniRepl client:visible tune={`sound("bd hh*2 rim hh*3 bd [~ hh*2] rim hh*2")`} punchcard />
<MiniRepl client:visible tune={`sound("bd hh*2 rim hh*3 bd [- hh*2] rim hh*2")`} punchcard />
**Multiplication: Speed up subsequences**
@ -195,7 +231,7 @@ You can go as deep as you want!
You can use as many commas as you want:
<MiniRepl client:visible tune={`sound("hh hh hh, bd bd, ~ casio")`} punchcard />
<MiniRepl client:visible tune={`sound("hh hh hh, bd bd, - casio")`} punchcard />
Commas can also be used inside sub-sequences:
@ -213,9 +249,9 @@ It is quite common that there are many ways to express the same idea.
<MiniRepl
client:visible
tune={`sound(\`bd*2, ~ cp,
~ ~ ~ oh, hh*4,
[~ casio]*2\`)`}
tune={`sound(\`bd*2, - cp,
- - - oh, hh*4,
[- casio]*2\`)`}
punchcard
/>
@ -238,7 +274,7 @@ This is what we've leared so far:
| ----------------- | -------- | ----------------------------------------------------------------------- |
| Sequence | space | <MiniRepl client:visible tune={`sound("bd bd sd hh")`} /> |
| Sample Number | :x | <MiniRepl client:visible tune={`sound("hh:0 hh:1 hh:2 hh:3")`} /> |
| Rests | ~ | <MiniRepl client:visible tune={`sound("metal ~ jazz jazz:1")`} /> |
| Rests | - or ~ | <MiniRepl client:visible tune={`sound("metal - jazz jazz:1")`} /> |
| Sub-Sequences | \[\] | <MiniRepl client:visible tune={`sound("bd wind [metal jazz] hh")`} /> |
| Sub-Sub-Sequences | \[\[\]\] | <MiniRepl client:visible tune={`sound("bd [metal [jazz [sd cp]]]")`} /> |
| Speed up | \* | <MiniRepl client:visible tune={`sound("bd sd*2 cp*3")`} /> |
@ -248,9 +284,9 @@ The Mini-Notation is usually used inside some function. These are the functions
| Name | Description | Example |
| ----- | ----------------------------------- | --------------------------------------------------------------------------------- |
| sound | plays the sound of the given name | <MiniRepl client:visible tune={`sound("bd sd [~ bd] sd")`} /> |
| bank | selects the sound bank | <MiniRepl client:visible tune={`sound("bd sd [~ bd] sd").bank("RolandTR909")`} /> |
| cpm | sets the tempo in cycles per minute | <MiniRepl client:visible tune={`sound("bd sd [~ bd] sd").cpm(45)`} /> |
| sound | plays the sound of the given name | <MiniRepl client:visible tune={`sound("bd sd [- bd] sd")`} /> |
| bank | selects the sound bank | <MiniRepl client:visible tune={`sound("bd sd [- bd] sd").bank("RolandTR909")`} /> |
| cpm | sets the tempo in cycles per minute | <MiniRepl client:visible tune={`sound("bd sd [- bd] sd").cpm(45)`} /> |
| n | select sample number | <MiniRepl client:visible tune={`n("0 1 4 2 0 6 3 2").sound("jazz")`} /> |
## Examples
@ -266,7 +302,7 @@ The Mini-Notation is usually used inside some function. These are the functions
**Classic house**
<MiniRepl client:visible tune={`sound("bd*4, [~ cp]*2, [~ hh]*4").bank("RolandTR909")`} punchcard />
<MiniRepl client:visible tune={`sound("bd*4, [- cp]*2, [- hh]*4").bank("RolandTR909")`} punchcard />
<Box>
@ -283,7 +319,7 @@ We Will Rock you
<MiniRepl
client:visible
tune={`sound("bd sd, ~ ~ ~ hh ~ hh ~ ~, ~ perc ~ perc:1*2")
tune={`sound("bd sd, - - - hh - hh - -, - perc - perc:1*2")
.bank("RolandCompurhythm1000").cpm(120/2)`}
punchcard
/>
@ -293,10 +329,10 @@ We Will Rock you
<MiniRepl
client:visible
tune={`sound(\`
[~ ~ oh ~ ] [~ ~ ~ ~ ] [~ ~ ~ ~ ] [~ ~ ~ ~ ],
[hh hh ~ ~ ] [hh ~ hh ~ ] [hh ~ hh ~ ] [hh ~ hh ~ ],
[~ ~ ~ ~ ] [cp ~ ~ ~ ] [~ ~ ~ ~ ] [cp ~ ~ ~ ],
[bd ~ ~ ~ ] [~ ~ ~ bd] [~ ~ bd ~ ] [~ ~ ~ bd]
[- - oh - ] [- - - - ] [- - - - ] [- - - - ],
[hh hh - - ] [hh - hh - ] [hh - hh - ] [hh - hh - ],
[- - - - ] [cp - - - ] [- - - - ] [cp - - - ],
[bd - - - ] [- - - bd] [- - bd - ] [- - - bd]
\`).cpm(90/4)`}
punchcard
/>
@ -306,10 +342,10 @@ We Will Rock you
<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 ] [~ ~ ~ ~ ]
[- - - - ] [- - - - ] [- - - - ] [- - 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
/>
@ -319,9 +355,9 @@ We Will Rock you
<MiniRepl
client:visible
tune={`s(\`jazz*2,
insect [crow metal] ~ ~,
~ space:4 ~ space:1,
~ wind\`)
insect [crow metal] - -,
- space:4 - space:1,
- wind\`)
.cpm(100/2)`}
punchcard
/>