diff --git a/packages/core/controls.mjs b/packages/core/controls.mjs index 901a2ba3..ad521112 100644 --- a/packages/core/controls.mjs +++ b/packages/core/controls.mjs @@ -798,6 +798,16 @@ const generic_params = [ ['f', 'uid', ''], ['f', 'val', ''], ['f', 'cps', ''], + /** + * If set to 1, samples will be cut to the duration of their event. + * In tidal, this would be done with legato, which [is about to land in strudel too](https://github.com/tidalcycles/strudel/issues/111) + * + * @name clip + * @param {number | Pattern} active 1 or 0 + * @example + * note("c a f e ~").s("piano").clip(1) + * + */ ['f', 'clip', ''], ]; diff --git a/test/__snapshots__/examples.test.mjs.snap b/test/__snapshots__/examples.test.mjs.snap index 148f12cc..e52a5932 100644 --- a/test/__snapshots__/examples.test.mjs.snap +++ b/test/__snapshots__/examples.test.mjs.snap @@ -1060,6 +1060,27 @@ exports[`runs examples > example "chunkBack" example index 0 1`] = ` ] `; +exports[`runs examples > example "clip" example index 0 1`] = ` +[ + "[ 0/1 → 1/5 | note:c s:piano clip:1 ]", + "[ 1/5 → 2/5 | note:a s:piano clip:1 ]", + "[ 2/5 → 3/5 | note:f s:piano clip:1 ]", + "[ 3/5 → 4/5 | note:e s:piano clip:1 ]", + "[ 1/1 → 6/5 | note:c s:piano clip:1 ]", + "[ 6/5 → 7/5 | note:a s:piano clip:1 ]", + "[ 7/5 → 8/5 | note:f s:piano clip:1 ]", + "[ 8/5 → 9/5 | note:e s:piano clip:1 ]", + "[ 2/1 → 11/5 | note:c s:piano clip:1 ]", + "[ 11/5 → 12/5 | note:a s:piano clip:1 ]", + "[ 12/5 → 13/5 | note:f s:piano clip:1 ]", + "[ 13/5 → 14/5 | note:e s:piano clip:1 ]", + "[ 3/1 → 16/5 | note:c s:piano clip:1 ]", + "[ 16/5 → 17/5 | note:a s:piano clip:1 ]", + "[ 17/5 → 18/5 | note:f s:piano clip:1 ]", + "[ 18/5 → 19/5 | note:e s:piano clip:1 ]", +] +`; + exports[`runs examples > example "coarse" example index 0 1`] = ` [ "[ 0/1 → 1/2 | s:bd coarse:1 ]", diff --git a/website/src/pages/learn/samples.mdx b/website/src/pages/learn/samples.mdx index 510b43c5..5ad0c0e0 100644 --- a/website/src/pages/learn/samples.mdx +++ b/website/src/pages/learn/samples.mdx @@ -9,16 +9,90 @@ import { JsDoc } from '../../docs/JsDoc'; # Samples -# Default Sample Map +Samples are the most common way to make sound with tidal and strudel. +A sample is a (commonly short) piece of audio that is used as a basis for sound generation, undergoing various transformations. +Music that is based on samples can be thought of as a collage of sound. [Read more about Sampling]() -As we have seen, `s` can play back audio samples: +Strudel allows loading samples in the form of audio files of various formats (wav, mp3, ogg) from any publicly available URL. - +# Default Samples -These sounds come from Strudel's in-built default "sample map". -To know which sounds are available, open the [default sample map](https://strudel.tidalcycles.org/EmuSP12.json). +By default, strudel comes with a built-in "sample map", providing a solid base to play with. -# Custom Sample Maps + + +Here, we are using the `s` function to play back different default samples (`bd`, `sd`, `hh` and `misc`) to get a drum beat. + +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 | +| ----------------------------------- | ------------ | +| 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 | +| Miscellaneous samples | misc | +| Effects | fx | + +Furthermore, strudel also loads instrument samples from [VCSL](https://github.com/sgossner/VCSL) by default. + +To see which sample names are available, open the `samples` tab in the [REPL](https://strudel.tidalcycles.org/). + +Note that only the sample maps (mapping names to URLs) are loaded initially, while the audio samples itself are not loaded until they are actually played. +This behaviour of loading things only when they are needed is also called `lazy loading`. +While it saves resources, it can also lead to sounds not being audible the first time they are triggered, because the sound is still loading. +[This might be fixed in the future](https://github.com/tidalcycles/strudel/issues/187) + +# Sound Banks + +If we look at the `samples` tab, we can see that the drum samples are all prefixed with drum machine names: `RolandTR808_bd`, `RolandTR808_sd`, `RolandTR808_hh` etc.. + +We _could_ use them like this: + + + +... but thats obviously a bit much to write. Using the `bank` function, we can shorten this to: + + + +You could even pattern the bank to switch between different drum machines: + +")`} /> + +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. +Also note that some banks won't have samples for all sounds! + +# Selecting Sounds + +If we look again at the `samples` tab, there is also a number behind each name, indicating how many individual samples are available. +For example `RolandTR909_hh(4)` means there are 4 samples of a TR909 hihat available. +By default, `s` will play the first sample, but we can selecting the other ones using `n`, starting from 0: + +")`} /> + +Numbers that are too high will just wrap around to the beginning + +")`} /> + +Here, 0-3 will play the same sounds as 4-7, because `RolandTR909_hh` only has 4 sounds. + +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: @@ -48,7 +122,7 @@ s("bassdrum snaredrum, hihat*8")`} Here we have changed the "map" to include longer sample names. -# Loading Custom Samples +## The `samples` function The `samples` function has two arguments: @@ -87,7 +161,7 @@ We can see there are some guitar samples inside the `/samples` folder, so let's s("[g0 g1 g2 g3 g4]/5")`} /> -# Loading Multiple Samples per Sound +## Multiple Samples per Sound It is also possible, to declare multiple files for one sound, using the array notation: @@ -146,7 +220,7 @@ And as above, we can choose the sample number using `n` for even more flexibilit n("<0 1 2 3 4>").s("guitar")`} /> -# Pitched Sounds +## Pitched Sounds For pitched sounds, you can use `note`, just like with synths: @@ -170,7 +244,7 @@ note("g3 [bb3 c4] @2").s('gtr').clip(1) .gain(.5)`} /> -# Base Pitch +## Base Pitch If we have 2 samples with different base pitches, we can make them in tune by specifying the pitch like this: @@ -203,7 +277,7 @@ note("g2!2 !2, g4 f4]>") The sampler will always pick the closest matching sample for the current note! -# Shabda +## Shabda If you don't want to select samples by hand, there is also the wonderful tool called [shabda](https://shabda.ndre.gr/). With it, you can enter any sample name(s) to query from [freesound.org](https://freesound.org/). Example: @@ -220,30 +294,32 @@ stack( # Sampler Effects -Below are four different examples of sampler "effects" which are functions that can be used to change the behaviour of sample playback. -Note that most of what you've learned already about Tidal mini-notation can be used with these functions too. -Almost everything in Tidal can be patterned using strings! +Sampler effects are functions that can be used to change the behaviour of sample playback. -### `begin` +### begin -### `end` +### end -### `cut` +### cut -### `loopAt` +### clip + + + +### loopAt -### `chop` +### chop -### `speed` +### speed