Skip to main content

Sampling

This page will present you all the functions that can be used to slice, cut, reverse or explode your audio samples, incoming signals or oscillators. Each function will be presented following the same model:

  • Type signature: how the function is declared on the Haskell side.
  • Description: verbal description of the function.
  • Examples: a small list of examples that you can copy/paste in your editor.

Audio sampling

chop

Type: chop :: Pattern Int -> ControlPattern -> ControlPattern

chop cuts each sample into the given number of parts, allowing you to explore a technique known as 'granular synthesis'. It turns a pattern of samples into a pattern of parts of samples. For example:

d1 $ chop 16 $ sound "arpy ~ feel*2 newnotes"

In the above, each sample is chopped into 16 bits, resulting in 64 (16*4) events. You can pattern that first parameter:

d1 $ chop "<16 128 32>" $ sound "arpy ~ feel*2 newnotes"

You end up with a pattern of the chopped up bits of samples. You'll already be able to hear this more clearly if you for example reverse the pattern, as you'll reverse the order of the sample parts:

d1 $ slow 2 $ rev $ chop 16 $ sound "breaks125"

Lets try that reverse in just one speaker:

d1 $ slow 2 $ jux rev $ chop 16 $ sound "breaks125"

Different values of chop can yield very different results, depending on the samples used:

d1 $ chop 16 $ sound (samples "arpy*8" (run 16))
d1 $ chop 32 $ sound (samples "arpy*8" (run 16))
d1 $ chop 256 $ sound "bd*4 [sn cp] [hh future]*2 [cp feel]"

You can also use chop (or striate) with very long samples, to cut it into short chunks and pattern those chunks. The following cuts a sample into 32 parts, and plays it over 8 cycles:

d1 $ loopAt 8 $ chop 32 $ sound "bev"

The loopAt takes care of changing the speed of sample playback so that the sample fits in the given number of cycles perfectly. As a result, in the above the granules line up perfectly, so you can’t really hear that the sample has been cut into bits. Again, this becomes more apparent when you do further manipulations of the pattern, for example rev to reverse the order of the cut up bits:

d1 $ loopAt 8 $ rev $ chop 32 $ sound "bev"

striate

Type: striate :: Pattern Int -> ControlPattern -> ControlPattern

striate is a kind of granulator, cutting samples into bits in a similar to chop, but the resulting bits are organised differently. For example:

d1 $ slow 4 $ striate 3 $ sound "numbers:0 numbers:1 numbers:2 numbers:3"

This plays the loop the given number of times, but triggering progressive portions of each sample. So in this case it plays the loop three times, the first time playing the first third of each sample, then the second time playing the second third of each sample, and then finally the last third of each sample.. Compare this with chop:

d1 $ slow 4 $ chop 3 $ sound "numbers:0 numbers:1 numbers:2 numbers:3"

You can hear that the striate version 'interlaces' the cut up bits of samples together, whereas the chop version plays the bits from each chopped up sample in turn. It might be worth listening to the samples without granulation, in case that helps understand what’s happening in the above:

d1 $ slow 4 $ sound "numbers:0 numbers:1 numbers:2 numbers:3"

striateBy

Type: striateBy :: Pattern Int -> Pattern Double -> ControlPattern -> ControlPattern

striateBy (formerly called striate') is a variant of striate, with an extra parameter, which specifies the length of each part. striate still scans across the sample over a single cycle, but if each bit is longer, it creates a sort of stuttering effect. For example the following will cut the bev sample into 32 parts, but each will be 1/16th of a sample long:

d1 $ slow 32 $ striateBy 32 (1/16) $ sound "bev"

Note that striate uses the begin and end parameters internally. This means that if you’re using striate or striateBy you probably shouldn’t also specify begin or end.

slice

Type: Pattern Int -> Pattern Int -> ControlPattern -> ControlPattern

slice is similar to chop and striate, in that it's used to slice samples up into bits. The difference is that it allows you to rearrange those bits as a pattern.

d1 $ slice 8 "7 6 5 4 3 2 1 0" $ sound "breaks165"
# legato 1

The above slices the sample into eight bits, and then plays them backwards, equivalent of applying rev $ chop 8. Here's a more complex example:

d1 $ slice 8 "[<0*8 0*2> 3*4 2 4] [4 .. 7]" $ sound "breaks165"
# legato 1

Note that the order of the first two parameters changed since tidal version 1.0.0.

splice

Type: splice :: Pattern Int -> Pattern Int -> ControlPattern -> ControlPattern

splice is similar to slice, but the slices are automatically pitched up or down to fit their 'slot'.

d1 $ splice 8 "[<0*8 0*2> 3*4 2 4] [4 .. 7]" $ sound "breaks165"

randslice

Type: randslice :: Pattern Int -> ControlPattern -> ControlPattern

randslice chops the sample into the given number of pieces and then plays back a random one each cycle:

d1 $ randslice 32 $ sound "bev"

Use fast to get more than one per cycle;

d1 $ fast 4 $ randslice 32 $ sound "bev"

chew

Type: chew :: Int -> Pattern Int -> Pattern a -> Pattern a

chew works the same as bite, but speeds up/slows down playback of sounds as well as squeezing / contracting the slices of pattern.

Compare these:

d1 $ bite 4 "0 1*2 2*2 [~ 3]" $ n "0 .. 7" # sound "drum"

d1 $ chew 4 "0 1*2 2*2 [~ 3]" $ n "0 .. 7" # sound "drum"

loopAt

Type: loopAt :: Pattern Time -> ControlPattern -> ControlPattern

loopAt makes sample fit the given number of cycles. Internally, it works by setting the unit control to "c", changing the playback speed of the sample with the speed parameter, and setting the density of the pattern to match.

d1 $ loopAt 4 $ sound "breaks125"

It’s a good idea to use this in conjuction with chop, so the break is chopped into pieces and you don’t have to wait for the whole sample to start/stop.

d1 $ loopAt 4 $ chop 32 $ sound "breaks125"

Like all Tidal functions, you can mess about with this considerably. The below example shows how you can supply a pattern of cycle counts to loopAt:

d1 $ juxBy 0.6 (|* speed "2") $ loopAt "<4 6 2 3>" $ chop 12 $ sound "fm:14"

smash

Type: smash :: Pattern Int -> [Pattern Time] -> ControlPattern -> ControlPattern

smash is a combination of spread and striate - it cuts the samples into the given number of bits, and then cuts between playing the loop at different speeds according to the values in the list. So this:

d1 $ smash 3 [2,3,4] $ sound "ho ho:2 ho:3 hc"

Is a bit like this:

d1 $ slow "<2 3 4>" $ striate 3 $ sound "ho ho:2 ho:3 hc"

smash'

Type: smash' :: Int -> [Pattern Time] -> ControlPattern -> ControlPattern

smash' is smash but based on chop instead of striate.

Compare:

d1 $ smash 6 [2,3,4] $ sound "ho ho:2 ho:3 hc"

to

d1 $ smash' 6 [2,3,4] $ sound "ho ho:2 ho:3 hc"

or

d1 $ smash 12 [2,3,4] $ s "bev*4"

vs

d1 $ smash' 12 [2,3,4] $ s "bev*4"

for a dramatic difference.

Signal sampling

segment

Type: segment :: Pattern Time -> Pattern a -> Pattern a

segment 'samples' the pattern at a rate of n events per cycle. Useful for turning a continuous pattern into a discrete one. In this example, the pattern originates from the shape of a sine wave, a continuous pattern. Without segment the samples will get triggered at an undefined frequency which may be very high.

d1 $ n (slow 2 $ segment 16 $ range 0 32 $ sine) # sound "amencutup"

discretise

segment used to be known as discretise. The old name remains as an alias and will still work, but may be removed or repurposed in a future version of Tidal.

sig

Type: sig :: (Time -> a) -> Pattern a

sig takes a function of time and turns it into a pattern. It's very useful for creating continuous patterns such as sine or perlin. For example, saw is defined as

saw = sig $ \t -> mod' (fromRational t) 1