Goals:
- use functions to modify your patterns
- change when/how often functions/filters are applied
- use continuous functions and oscillators to create constantly changing values
Reference:
- https://estuary.mcmaster.ca
- https://tidalcycles.org/docs/
- https://tidalcycles.org/docs/patternlib/tour/concatenation/
- https://tidalcycles.org/docs/reference/oscillators
- https://tidalcycles.org/docs/reference/alteration#scaling
!presetview twocolumns
Choose MiniTidal from the language dropdown for both cells
A function can very generally be thought of as a small program that takes something as input (in our case it's usually a pattern), occasionally some other things (numbers or other directives), processes it according to it's programming and gives us back a duly modifed output (in our case, usually a different pattern)!
We can apply functions to modify or change our patterns in a huge variety of ways by prepending them to our patterns, and separating with a $
symbol, similarly to
function $ pattern
The least confusing technical description of $
in haskell is
"You usually see $ where standard function application wouldn’t have the necessary associativity and precedence for the context. And what that means is you usually see it used instead of parentheses to associate things that otherwise wouldn’t. typeclasses.com
In short, it's easier (and quicker) to write
function $ pattern
than it is to write
function (pattern)
In Tidalcycles, it's not uncommon to have a large number of functions applied to your patterns so being able to associate these functions to your pattern without parentheses ( )
is a massive timesaver!
A great sample set to help us with this worksheet is alphabet
- here's our base pattern:
n "0 1 2 3" # sound "alphabet"
There are a huge number of functions builtin to tidal, but let's start with an oldie but a goodie...
rev
takes a pattern as input, and reverses the elements
rev $ n "0 1 2 3" # sound "alphabet"
palindrome
is similar to rev
- it takes a pattern as input, but alternates playing each cycle of the pattern forward then in reverse
palindrome $ n "0 1 2 3" # sound "alphabet"
Some functions take another function as input - these are called higher order functions
Higher order functions usually require their input arguments to be specified in ( )
brackets rather than with $
, otherwise minitidal will associate it with the whole pattern, instead of associating it to just our higher order function.
jux
is another old favourite that also happens to be a higher order function - let's try passing it our rev
function as input
jux (rev) $ n "0 1 2 3" # sound "alphabet"
Take a guess at what jux (rev)
is doing to our pattern based on what you're hearing (hint: try listening to one stereo channel at a time!)
That is pretty intense sounding though, in most cases we don't actually want our functions to be applied all the time. In most cases, we only want them applied sometimes
There are a multitude of ways to control when you apply a function to your pattern, this worksheet will only cover some of the more common ones (and introduce some new functions along the way!)
sometimesBy
will apply the function to an event randomly based on the number you provide to increase/decrease the likelihood - 0.9
is very likely (9 in 10 chance), 0.1
is unlikely (1 in 10 chance)
sometimesBy 0.4 (fast 2) $ n "0 1 2 3" # sound "alphabet"
sometimesBy
also has a host of shortcuts - almostNever
, rarely
, sometimes
, often
, almostAlways
sometimes (# speed "-1") $ n "0 1 2 3" # sound "alphabet"
someCyclesBy
is very similar to sometimesBy
, except that it will apply the function to a whole cycle instead of individual events
someCyclesBy 0.4 (hurry 2) $ n "0 1 2 3" # sound "alphabet"
There are times when you need to be more specific about when you want to apply a function to a pattern - for this you need:
every
will apply the function to every "Nth" cycle
every 4 (linger 0.333) $ n "0 1 2 3" # sound "alphabet"
There are times when every "Nth" cycle needs an offset by a cycle or two
every'
("every prime") allows you to specify an offset in number of cycles - that is, not changing the frequency that it applies, but shifting the frequency by a number of cycles
every' 4 2 (jux (rev)) $ n "0 1 2 3" # sound "alphabet"
Lastly, there are times when you will want to apply the function to more than one cycle in a row
whenmod
allows you to specify a range of cycles over which the function will apply
-- apply every 7th and 8th cycles
whenmod 8 6 (slow 2) $ n "0 1 2 3" # sound "alphabet"
Note: the second number N
must be lower than the first number M
, it will apply the function on the (M - N)th
cycles
By now, we have all the basic mechanics of sound generation in Minitidal! We can choose different sounds, different rhythms, modify pitch and timbre of those sounds, and even modify the patterns themselves!
Now, it's time to introduce continuous functions so we don't have to manually type out all those changes!
You can use these functions in place of fixed numbers to have values changing over time
run N
creates a sequence of integers from 0
to N
note (run 12) # s "ukulele"
note (scale "major" (run 8)) # s "ukulele"
rand
is a random floating point number generator for values between 0
and 1
sound "bd*8" # speed (rand)
sound "bd*8" # speed (rand * 2)
sound "bd*8" # speed (1 + rand)
irand N
is a random integer generator for values between 0
and N
sound "ukulele*4" # note (irand 8)
sound "ukulele*4" # note (scale "major" (irand 8))
Minitidal implements several oscillators, or continuous functions:
sine
(cosine
)square
tri
saw
(isaw
)
You can use these oscillators in place of fixed numbers to have values changing over time
Here's a simple example where we change speed
over time using a sine
wave
sound "bd*12" # speed (sine)
By default the sine wave amplitude (or vertical height) range is 0-1
, and it's period (or horizontal width) is 1 cycle
range
adjusts the amplitude - having our speed
go to 0
isn't much fun, let's set a lower value of 0.5
, and an upper value of 2
instead
sound "bd*12" # speed (range 0.5 2 (sine))
slow
and fast
can be use to adjust the period of the sine wave, let's extend our period to 3 cycles instead of 1
sound "bd*12" # speed (range 0.5 2 (slow 3 sine))
You can even pattern these values
sound "bd*12" # speed (range "<0.5 2>" "2 4" (slow "<3 5 7>" sine))
Try out some more oscillators, mixing up/patterning your amplitudes and periods!
- There are a huge number of functions available in Tidalcycles, pick some at random from the "Small Reference" sub menu and try them out!