jevstrudel.git / website / src / pages / learn / samples.mdx
samples.mdx390 lines · 12.9 KB · raw
1---
2title: Samples
3layout: ../../layouts/MainLayout.astro
4---
5
6import { MiniRepl } from '../../docs/MiniRepl';
7import { JsDoc } from '../../docs/JsDoc';
8
9# Samples
10
11Samples are the most common way to make sound with tidal and strudel.
12A sample is a (commonly short) piece of audio that is used as a basis for sound generation, undergoing various transformations.
13Music that is based on samples can be thought of as a collage of sound. [Read more about Sampling](<https://en.wikipedia.org/wiki/Sampling_(music)>)
14
15Strudel allows loading samples in the form of audio files of various formats (wav, mp3, ogg) from any publicly available URL.
16
17# Default Samples
18
19By default, strudel comes with a built-in "sample map", providing a solid base to play with.
20
21<MiniRepl client:idle tune={`s("bd sd [~ bd] sd,hh*16, misc")`} />
22
23Here, we are using the `s` function to play back different default samples (`bd`, `sd`, `hh` and `misc`) to get a drum beat.
24
25For drum sounds, strudel uses the comprehensive [tidal-drum-machines](https://github.com/ritchse/tidal-drum-machines) library, with the following naming convention:
26
27| Drum                 | Abbreviation |
28| -------------------- | ------------ |
29| Bass drum, Kick drum | bd           |
30| Snare drum           | sd           |
31| Rimshot              | rim          |
32| Clap                 | cp           |
33| Closed hi-hat        | hh           |
34| Open hi-hat          | oh           |
35| Crash                | cr           |
36| Ride                 | rd           |
37| High tom             | ht           |
38| Medium tom           | mt           |
39| Low tom              | lt           |
40
41<img src="/img/drumset.png" />
42
43<a class="text-right text-xs" href="https://de.wikipedia.org/wiki/Schlagzeug#/media/Datei:Drum_set.svg" target="_blank">
44  original von Pbroks13
45</a>
46
47More percussive sounds:
48
49| Source                              | Abbreviation |
50| ----------------------------------- | ------------ |
51| Shakers (and maracas, cabasas, etc) | sh           |
52| Cowbell                             | cb           |
53| Tambourine                          | tb           |
54| Other percussions                   | perc         |
55| Miscellaneous samples               | misc         |
56| Effects                             | fx           |
57
58Furthermore, strudel also loads instrument samples from [VCSL](https://github.com/sgossner/VCSL) by default.
59
60To see which sample names are available, open the `sounds` tab in the [REPL](https://strudel.cc/).
61
62You can also create custom aliases for existing sounds using the `soundAlias` function:
63
64<MiniRepl
65  client:idle
66  tune={`soundAlias('RolandTR808_bd', 'kick')
67s("kick")`}
68/>
69
70Note that only the sample maps (mapping names to URLs) are loaded initially, while the audio samples themselves are not loaded until they are actually played.
71This behaviour of loading things only when they are needed is also called `lazy loading`.
72While it saves resources, it can also lead to sounds not being audible the first time they are triggered, because the sound is still loading.
73[This might be fixed in the future](https://codeberg.org/uzu/strudel/issues/187)
74
75# Sound Banks
76
77If we open the `sounds` tab and then `drum-machines`, we can see that the drum samples are all prefixed with drum machine names: `RolandTR808_bd`, `RolandTR808_sd`, `RolandTR808_hh` etc..
78
79We _could_ use them like this:
80
81<MiniRepl client:idle tune={`s("RolandTR808_bd RolandTR808_sd,RolandTR808_hh*16")`} />
82
83... but thats obviously a bit much to write. Using the `bank` function, we can shorten this to:
84
85<MiniRepl client:idle tune={`s("bd sd,hh*16").bank("RolandTR808")`} />
86
87You could even pattern the bank to switch between different drum machines:
88
89<MiniRepl client:idle tune={`s("bd sd,hh*16").bank("<RolandTR808 RolandTR909>")`} />
90
91Behind the scenes, `bank` will just prepend the drum machine name to the sample name with `_` to get the full name.
92This of course only works because the name after `_` (`bd`, `sd` etc..) is standardized.
93Also note that some banks won't have samples for all sounds!
94
95# Selecting Sounds
96
97If we open the `sounds` tab again, followed by tab `drum machines`, there is also a number behind each name, indicating how many individual samples are available.
98For example `RolandTR909_hh(4)` means there are 4 samples of a TR909 hihat available.
99By default, `s` will play the first sample, but we can select the other ones using `n`, starting from 0:
100
101<MiniRepl client:idle tune={`s("hh*8").bank("RolandTR909").n("0 1 2 3")`} />
102
103Numbers that are too high will just wrap around to the beginning
104
105<MiniRepl client:idle tune={`s("hh*8").bank("RolandTR909").n("0 1 2 3 4 5 6 7")`} />
106
107Here, 0-3 will play the same sounds as 4-7, because `RolandTR909_hh` only has 4 sounds.
108
109Selecting sounds also works inside the mini notation, using "`:`" like this:
110
111<MiniRepl
112  client:idle
113  tune={`s("bd*4,hh:0 hh:1 hh:2 hh:3 hh:4 hh:5 hh:6 hh:7")
114.bank("RolandTR909")`}
115/>
116
117# Loading Custom Samples
118
119You can load a non-standard sample map using the `samples` function.
120
121## Loading samples from file URLs
122
123In this example we assign names `bassdrum`, `hihat` and `snaredrum` to specific audio files on a server:
124
125<MiniRepl
126  client:idle
127  tune={`samples({
128  bassdrum: 'bd/BT0AADA.wav',
129  hihat: 'hh27/000_hh27closedhh.wav',
130  snaredrum: ['sd/rytm-01-classic.wav', 'sd/rytm-00-hard.wav'],
131}, 'https://raw.githubusercontent.com/tidalcycles/Dirt-Samples/master/');
132 
133s("bassdrum snaredrum:0 bassdrum snaredrum:1, hihat*16")`}
134/>
135
136You can freely choose any combination of letters for each sample name. It is even possible to override the default sounds.
137The names you pick will be made available in the `s` function.
138Make sure that the URL and each sample path form a correct URL!
139
140In the above example, `bassdrum` will load:
141
142```
143https://raw.githubusercontent.com/tidalcycles/Dirt-Samples/master/bd/BT0AADA.wav
144|----------------------base path --------------------------------|--sample path-|
145```
146
147Note that we can either load a single file, like for `bassdrum` and `hihat`, or a list of files like for `snaredrum`!
148As soon as you run the code, your chosen sample names will be listed in `sounds` -> `user`.
149
150## Loading Samples from a strudel.json file
151
152The above way to load samples might be tedious to write out / copy paste each time you write a new pattern.
153To avoid that, you can simply pass a URL to a `strudel.json` file somewhere on the internet:
154
155<MiniRepl
156  client:idle
157  tune={`samples('https://raw.githubusercontent.com/tidalcycles/Dirt-Samples/master/strudel.json')
158s("bd sd bd sd,hh*16")`}
159/>
160
161The file is expected to define a sample map using JSON, in the same format as described above.
162Additionally, the base path can be defined with the `_base` key.
163The last section could be written as:
164
165```json
166{
167  "_base": "https://raw.githubusercontent.com/tidalcycles/Dirt-Samples/master/",
168  "bassdrum": "bd/BT0AADA.wav",
169  "snaredrum": "sd/rytm-01-classic.wav",
170  "hihat": "hh27/000_hh27closedhh.wav"
171}
172```
173
174Please note that browsers will often cache `strudel.json` on first load, and keep using the cached
175version even if the orginal has been updated. If this bites you (for example while developing a new
176sample pack), you can force the browser to download a new copy by i.e. changing capitalization of one
177character in the URL, or adding a URL attribute, such as:
178
179```javascript
180samples('https://raw.githubusercontent.com/tidalcycles/Dirt-Samples/master/strudel.json?version=2');
181```
182
183that gets ignored by GitHub (but changes the URL, forcing the browser to reload every time we increase
184the version number).
185
186It is also possible, of course, to just remove it from cache (deleting cache in browser Privacy settings,
187or from the dev console if you're technically minded, or by using a cache deleting extension).
188
189## Generating strudel.json
190
191You can use [@strudel/sampler](https://www.npmjs.com/package/@strudel/sampler) to generate a strudel.json file for you, by running:
192
193```sh
194npx --yes @strudel/sampler --json > strudel.json
195```
196
197See other uses of strudel/sampler further below, under "From Disk via @strudel/sampler".
198
199## Github Shortcut
200
201Because loading samples from github is common, there is a shortcut:
202
203<MiniRepl
204  client:idle
205  tune={`samples('github:tidalcycles/dirt-samples')
206s("bd sd bd sd,hh*16")`}
207/>
208
209The format is `samples('github:<user>/<repo>/<branch>')`. If you omit `branch` (like above), the `main` branch will be used.
210It assumes a `strudel.json` file to be present at the root of the repository:
211
212```
213https://raw.githubusercontent.com/<user>/<repo>/<branch>/strudel.json
214```
215
216## From Disk via "Import Sounds Folder"
217
218If you don't want to upload your samples to the internet, you can also load them from your local disk.
219Go to the `sounds` tab in the REPL and open the `import-sounds` tab below the search bar.
220Press the "import sounds folder" button and select a folder that contains audio files.
221The folder you select can also contain subfolders with audio files.
222Example:
223
224```
225└─ samples
226   ├─ swoop
227   │  ├─ swoopshort.wav
228   │  ├─ swooplong.wav
229   │  └─ swooptight.wav
230   └─ smash
231      ├─ smashhigh.wav
232      ├─ smashlow.wav
233      └─ smashmiddle.wav
234```
235
236In the above example the folder `samples` contains 2 subfolders `swoop` and `smash`, which contain audio files.
237If you select that `samples` folder, the `user` tab (next to the `import-sounds` tab) will then contain 2 new sounds: `swoop(3) smash(3)`
238The individual samples can the be played normally like `s("swoop:0 swoop:1 smash:2")`.
239The samples within each sound use zero-based indexing in alphabetical order.
240
241## From Disk via @strudel/sampler
242
243Instead of loading your samples into your browser with the "import sounds folder" button, you can also serve the samples from a local file server.
244The easiest way to do this is using [@strudel/sampler](https://www.npmjs.com/package/@strudel/sampler):
245
246```sh
247cd samples
248npx @strudel/sampler
249```
250
251Then you can load it via:
252
253<MiniRepl
254  client:idle
255  tune={`samples('http://localhost:5432/');
256 
257n("<0 1 2>").s("swoop smash")`}
258/>
259
260The handy thing about `@strudel/sampler` is that it auto-generates the `strudel.json` file based on your folder structure.
261You can see what it generated by going to `http://localhost:5432` with your browser.
262
263Note: You need [NodeJS](https://nodejs.org/) installed on your system for this to work.
264
265## Specifying Pitch
266
267To make sure your samples are in tune when playing them with `note`, you can specify a base pitch like this:
268
269<MiniRepl
270  client:idle
271  tune={`samples({
272  'gtr': 'gtr/0001_cleanC.wav',
273  'moog': { 'g3': 'moog/005_Mighty%20Moog%20G3.wav' },
274}, 'github:tidalcycles/dirt-samples');
275note("g3 [bb3 c4] <g4 f4 eb4 f3>@2").s("gtr,moog").clip(1)
276  .gain(.5)`}
277/>
278
279We can also declare different samples for different regions of the keyboard:
280
281<MiniRepl
282  client:idle
283  tune={`setcpm(60)
284samples({
285  'moog': {
286    'g2': 'moog/004_Mighty%20Moog%20G2.wav',
287    'g3': 'moog/005_Mighty%20Moog%20G3.wav',
288    'g4': 'moog/006_Mighty%20Moog%20G4.wav',
289  }}, 'github:tidalcycles/dirt-samples')
290
291note("g2!2 <bb2 c3>!2, <c4@3 [<eb4 bb3> g4 f4]>")
292.s('moog').clip(1)
293.gain(.5)`}
294/>
295
296The sampler will always pick the closest matching sample for the current note!
297
298Note that this notation for pitched sounds also works inside a `strudel.json` file.
299
300## Shabda
301
302If you don't want to select samples by hand, there is also the wonderful tool called [shabda](https://shabda.ndre.gr/).
303With it, you can enter any sample name(s) to query from [freesound.org](https://freesound.org/). Example:
304
305<MiniRepl
306  client:idle
307  tune={`samples('shabda:bass:4,hihat:4,rimshot:2')
308
309$: n("0 1 2 3 0 1 2 3").s('bass')
310$: n("0 1*2 2 3*2").s('hihat').clip(1)
311$: n("~ 0 ~ 1 ~ 0 0 1").s('rimshot')`}
312/>
313
314You can also generate artificial voice samples with any text, in multiple languages.
315Note that the language code and the gender parameters are optional and default to `en-GB` and `f`
316
317<MiniRepl
318  client:idle
319  tune={`samples('shabda/speech:the_drum,forever')
320samples('shabda/speech/fr-FR/m:magnifique')
321
322$: s("the_drum*2").chop(16).speed(rand.range(0.85,1.1))
323$: s("forever magnifique").slow(4).late(0.125)`}
324/>
325
326# Sampler Effects
327
328Sampler effects are functions that can be used to change the behaviour of sample playback.
329
330### begin
331
332<JsDoc client:idle name="Pattern.begin" h={0} />
333
334### end
335
336<JsDoc client:idle name="Pattern.end" h={0} />
337
338### loop
339
340<JsDoc client:idle name="loop" h={0} />
341
342### loopBegin
343
344<JsDoc client:idle name="loopBegin" h={0} />
345
346### loopEnd
347
348<JsDoc client:idle name="loopEnd" h={0} />
349
350### cut
351
352<JsDoc client:idle name="cut" h={0} />
353
354### clip
355
356<JsDoc client:idle name="clip" h={0} />
357
358### loopAt
359
360<JsDoc client:idle name="Pattern.loopAt" h={0} />
361
362### fit
363
364<JsDoc client:idle name="fit" h={0} />
365
366### chop
367
368<JsDoc client:idle name="Pattern.chop" h={0} />
369
370### striate
371
372<JsDoc client:idle name="Pattern.striate" h={0} />
373
374### slice
375
376<JsDoc client:idle name="Pattern.slice" h={0} />
377
378### splice
379
380<JsDoc client:idle name="splice" h={0} />
381
382### scrub
383
384<JsDoc client:idle name="Pattern.scrub" h={0} />
385
386### speed
387
388<JsDoc client:idle name="speed" h={0} />
389
390After samples, let's see what [Synths](/learn/synths) afford us.