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.