Skip to content

Instantly share code, notes, and snippets.

@jaza-syed
Last active June 17, 2024 20:53
Show Gist options
  • Save jaza-syed/84104c18034352cc89c47ef64ad8860f to your computer and use it in GitHub Desktop.
Save jaza-syed/84104c18034352cc89c47ef64ad8860f to your computer and use it in GitHub Desktop.
ITP Camp 2024 Tidal Worksheet

Starting out in MiniTidal

To stop anything playing, comment out or delete your code and run silence.

Tidal's basic unit of time is cycles.

  • s "bd" - s is a function with one argument. here the argument is the string "bd". The string specifies a single cycle, where the sample bd is played at the start of the cycles

  • s ”bd sn” - 2 beat cycle

  • s ”bd sn oh” - 3 beat cycle

  • s ”bd sn oh cp” - 3 beat cycle

  • s ”bd sn ~ cp” - 4 beat cycle with no sound on the third beat

  • s “bd [sn sn] [cp cp cp]” - You can create nested patterns with square brackets. The first third of the cycle is just bd . The second third of the cycle is sn sn and the last third is cp cp cp

  • s “<bd sn> <hh oh>” - You can alternate between different choices of sample in each cycle with angle brackets. This is one way of creating longer form structure in Tidal. In this pattern, the first cycle is bd hh then the second cycle is hh oh.

IMPORTANT: There are no commas in these lists!

The sample name actually refers to a folder of sound files, not a single file. You can play different sounds from the same folder like so:

s “bd:0 bd:1 bd:2 bd:3” . The number refers to the position of the file in the folder in alphabetical order, starting at 0 for the first file. If you look at the relevant folder here https://github.com/tidalcycles/Dirt-Samples, you can see how many samples there are to work with in each folder. To hear a single sound in a loop, just evaluate s "<sample name>:<number>".

Here is a list of samples to get started with:

flick sid can metal future gabba sn mouth co gretsch mt arp h cp cr 
newnotes bass hc tabla bass0 hh bass1 bass2 oc bass3 ho odx diphone2
house off ht tink perc bd industrial pluck trump printshort jazz 
voodoo birds3 procshort blip drum jvbass psr wobble drumtraks koy 
rave bottle kurt latibro rm sax lighter lt arpy feel less stab ul

rave is one of my favorites!

Task 1: Find a few samples you like working with and make a pattern with them including rests, nested patterns and alternating choices of samples.

More Rhythm

There's some special syntax for layering multiple patterns rhythmically. You can use square brackets and curly brackets with commas, like so:

[a b, c d e] -- polyrhythm
{a b, c d e} -- polymeter

IMPORTANT: There are commas in these lists!

These have very differentIn tidal proper, there's a function drawLine for visualising patterns which can help to understand what's happening.

Square brackets force the sequences to fit the same length, so you simultaneously get a two-beat and three-beat cycles:

> drawLine "[a b, c d e]"
|a--b--|a--b--|a--b--|a--b--|a--b--|
|c-d-e-|c-d-e-|c-d-e-|c-d-e-|c-d-e-|

Curly brackets align the samples in the second sequence to the first, across cycle boundaries, so you get longer form structure:

> drawline "{a b, c d e}"
|ab|ab|ab|ab|ab|
|cd|ec|de|cd|ec|

There's a special syntax for euclidean rhythms. These are a special class of rhythm that can be specified by two numbers. The wikipedia page is pretty good if you want to learn more https://en.wikipedia.org/wiki/Euclidean_rhythm. For a euclidean sequence "(x, y)" the cycle is divided into y equal parts, then x events are as evenly distributed as possible in the cycle.

> drawline $ "a(4,8)"
|a.a.a.a.|a.a.a.a.|a.a.a.a.|a.a.a.a.|
> drawline $ "a(3,8)"
|a..a..a.|a..a..a.|a..a..a.|a..a..a.|
> drawline $ "a(5,8)"
|a.aa.aa.|a.aa.aa.|a.aa.aa.|a.aa.aa.|

All these approaches can be combined. Here's a random example:

s "[bd(3,8), {cp(5,16}, hh oh hh oh hh hh hh}]"

Task 2: Using the same samples, make some more complex rhythms using these features.

Transformations

You aren't limited to writing out ever more complex strings. There are lots of functions for transforming patterns. You can do things like:

  • fast 2 $ s "bd sn hh oh" - speed up by factor of 2
  • slow 2 $ s "bd sn hh oh" - slow down by factor of 2

fast is a function that takes two arguments. The first is a numerical factor of how much to speed up the pattern, the second is the pattern to be sped up. The $ operator acts as brackets round the rest of the line, so that it is understood as the second argument.

The first argument doesn't actually have to be a number! You can replace it with a pattern instead. Things can get weird pretty quickly (embrace it!). drawLine can be helpful sometimes.

  • fast "<1 2>" $ s "bd sn hh oh" - first cycle normal speed, second sped up by factor of 2
  • slow "1 2" $ s "bd sn hh oh" - first half of cycle normal speed, second half half speed

iter n rotates the pattern by 1/n cycles each cycle:

> drawLine $ iter 4 $ "a b c d"
|abcd|bcda|cdab|dabc|

degradeBy p drops events with probability p

> drawLine $ degradeBy 0.5 $ "a b c d"
|.b..|abc.|ab.d|a..d|ab..|

Some other good functions to try out are rev, ghost and palindrome.

Check out the documentation for some things to try out if you're feeling adventurous: https://tidalcycles.org/docs/reference/alteration/

You can chain functions using $ e.g. fast 2 $ rev $ iter 4 $ s "bd sn hh oh"

Task 3: Start with a simple pattern and try making a complex one with some transformations. Try patterning the other parameters of the transform function!

Conditions and higher-order functions

Many functions take other functions as arguments. These are called higher-order functions in some contexts. jux takes a function as the first argument and the pattern it's applied to as the second argument. It plays the pattern with the function applied in one ear and the original pattern in the other. Using rev as the function gets you weird stereo effects:

jux rev $ s "bd sn hh oh"

A very important higher-order function is every. Every takes three arguments: every n function pattern.

every 3 rev $ s "bd sn hh oh" - every 3 cycles, play the pattern reversed.

You're not limited to using functions that only take a pattern as an argument. Haskell has in-built partial function application. This means that for the function fast n pattern if you say fast 2, you get a function that just takes a pattern as an argument

every 3 (fast 2) $ s "bd sn hh oh" - every three cycles, play the pattern at double speed

You can stack higher order function applications the same way as regular functions. Doing this with every and different integers is a great way of generating long-form structure quickly:

every 4 (rev) $ every 3 (fast 2) $ s "bd sn hh oh" - we have a 12-bar structure very quickly!

Functions that work with time tend to be higher-order functions that do something with another function and a pattern https://tidalcycles.org/docs/reference/time.

Some suggestions to work with, in addition to every and jux

  • sometimesBy p func pattern - apply func to pattern with probability p each cycle
  • off x fun pattern - play the pattern overlaid with the transformed patterned at an offst of x cycles

Task 4: Start with a simple pattern and try making a complex one with some transformations. Use higher order functions and conditions to make the pattern more complex!

Effects

We can apply effects with the # operator:

s "bd sn hh oh" # gain 0.5 - play the pattern at half volume

Effects can be patterned

s "bd sn hh oh" # gain "1 0.75 0.5 0.25" - play the pattern with descending volume

s "bd sn hh oh" # distort 0.5 - distorted pattern

s "bd sn hh oh" # vowel "a" - pattern with vowel effect applied. vowel effect values are a/e/i/o/u in a string.

You can stack these:

s "bd sn hh oh" # gain "1 0.75 0.5 0.25" # distort 0.5 # vowel "a" - all previous effects applied at once

You can convert effects to functions with this nice trick, so you can use them with higher order functions

every 3 (# vowel "a") $ s "bd sn hh oh" - apply the vowel effect every three cycles

https://userbase.tidalcycles.org/Combining_pattern_structure.html - This is a very useful link if you're intersted in how the effect and sound patterns are combined.

Task 5: Start with a simple pattern and try making a complex one with some transformations. Apply effects, pattern the effcts, combine the effects with higher order functions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment