1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
-- region Lesson 1 - continuous patterns
-- 'Continuous functions' provide different kinds of waveforms.
-- There's a nice graphic showing sine, square, triangle and sawtooth
-- waves here: https://en.wikipedia.org/wiki/Waveform
-- Here's what the sine waveform sounds like applied to sample playback
-- speed:
d1 $ sound "bd*32" # speed sine
-- and to panning:
d1 $ sound "bd*32" # pan sine
-- and to waveshape distortion (gets loud):
d1 $ sound "bd*32" # shape sine
-- You can manipulate continuous patterns just like other kinds of
-- patterns, for example slowing down:
d1 $ sound "bd*32" # shape (slow 2 sine)
-- The waveforms all move between 0 and 1. So at its lowest point, sine
-- will be 0, and at its highest point it will be 1. Having a value
-- near 0 can be problematic with 'speed', as you can end up with
-- sounds played very slowly that take a long time to complete.
-- To get around this you can add to the sine:
d1 $ sound "bd*32" # speed (sine + 0.5)
-- Or use the 'range' function:
d1 $ sound "bd*32" # speed (range 0.5 1.5 sine)
-- Lets listen to triangle, sawtooth and square waves:
d1 $ sound "bd*32" # speed (range 0.5 1.5 tri)
d1 $ sound "bd*32" # speed (range 0.5 1.5 saw)
d1 $ sound "bd*32" # speed (range 0.5 1.5 square)
-- What happens if you put the continuous pattern on the left?
-- Remember that with '#', the rhythmic structure comes from the
-- left. Try this:
d1 $ speed (range 0.5 1.5 sine) # sound "bd"
-- Silence! Why's that?
-- It's because continuous functions don't actually contain any
-- events. They have values which continually change, without
-- triggering anything.
-- If we want to trigger events in a continuous pattern, we have
-- to explicitly sample values from it. One way to do that is with
-- the 'segment' function:
d1 $ speed (segment 32 $ range 0.5 2.5 sine) # sound "bd"
-- The above samples 32 values per cycle, generating discrete
-- events from them.
-- Another way to do this is with 'binary' or 'boolean' patterns,
-- using the 'struct' function:
d1 $ speed (struct "t(3,8)" $ slow 2 $ range 0.5 2.5 sine)
# sound "bd"
-- 't' stands for 'true'. So that euclidean rhythm is used to sample
-- events from the continuous sine function. We'll return to
-- binary patterns in another video.
-- You can also add or multiply continous patterns together:
d1 $ sound "bd*32" # speed (range 0.5 2.5 (sine + (slow 2 saw)))
d1 $ sound "bd*32" # speed (range 0.5 2.5 (sine * (slow 2 saw)))
-- I slowed the 'saw' down in the above patterns, so you end
-- up with a sine wave that rises in pitch over two cycles.
-- In Tidal, random functions are also often continous.
-- For example, rand works like sine, saw etc, but returns random
-- values:
d1 $ sound "bd(5,8)" # speed (range 1 3 rand)
-- Perlin is similar, but returns 'perlin noise'. In Tidal, this
-- means that the pattern smoothly transitions between random values,
-- every cycle:
d1 $ sound "bd(5,8)" # speed (range 1 3 perlin)
-- Lets try that with some reverb:
d1 $ sound "bd(7,16)"
# room 0.7
# sz (range 0.4 1 $ slow 4 perlin)
-- endregion
-- region Lesson 2 - rand, irand, scramble, shuffle, choose + more
-- Let's start with a look at the 'rand' waveform that we
-- met in the last lesson:
d1 $ n "1*8" # sound "drum"
# speed (range 1 8 rand)
-- The 'resetCycles' resets the cycle count to '0', as
-- though you'd just started Tidal:
resetCycles
-- If you run resetCycles while the above pattern is running,
-- you'll notice that you also reset the random stream. You
-- will always get the same 'random' numbers every time you
-- start or reset Tidal.
-- You can apply rand to any numerical effect, but might have
-- to adjust the range. For example with the low pass filter
-- that cuts out frequencies higher than the given amount:
d1 $ sound "drum:5(5,8,<0 4>)"
# lpf (range 200 8000 rand)
# lpq 0.2
-- 'irand' is similar to 'rand', but creates integers, or
-- whole numbers, from 0 up to (and not including) the given
-- number. This is particularly useful for the 'n' and
-- 'note' controls:
d1 $ sound "rash(5,8)" # n (irand 32)
# room 0.3 # sz 0.5
-- There are a couple of ways of doing random things in the
-- mininotation too. To randomly choose between subsequences,
-- put a | (vertical bar) between them
-- The second step in this sequence is a randomly pick from
-- four subsequences:
d1 $ n "0 [0|1*3|2*8|3 4 5] 2 3" # sound "cpu"
# speed 1.5
-- Also, ? randomly 'drops' an event. In the following the
-- second step has a 50-50 chance of being played.
d1 $ sound "kick clap? kick snare"
# delay 0.3 # delaytime (1/3) # delayfb 0.8 # speed 1.5
-- (I've added some echo delay to make it sound cool. Delay is the
-- amount of sound to be delayed, delaytime is the length of the
-- echo, delayfb is the feedback of the delay into itself)
-- You can adjust the probability of ? working with a decimal
-- (floating point) number. For example, to have an 80% chance
-- of dropping that clap (and therefore 20% chance of playing
-- it)
d1 $ sound "kick clap?0.8 kick snare"
# speed 1.5
-- If you apply ? to a subsequence, it'll work individually
-- on each value in the subsequence
d1 $ sound "kick [clap:4 off clap:5]? kick snare"
# speed 1.5
d1 $ sound "bd*8? clap:4"
-- Ok, onward to functions, starting with scramble. scramble
-- takes a number, which is the number of parts to equally
-- divide a pattern into. It'll then play those parts at
-- random.
d1 $ scramble 4 $ n "0 1 2 3 4 5 6 7" # sound "arpy"
# room 0.3 # sz 0.8
-- The above is divided into four parts, and there are
-- eight events in them, so they are played in pairs. This
-- means that 0 is always followed by 1, 2 is always followed
-- by 3, and so on.
-- shuffle takes the same parameters as scramble, and sounds
-- very similar. Can you hear the difference?
d1 $ shuffle 4 $ n "0 1 2 3 4 5 6 7" # sound "arpy"
# room 0.3 # sz 0.8
-- Whereas scramble picks part at random, shuffle plays the
-- parts in random order. The difference is that with shuffle,
-- every cycle, you'll hear each part exactly once. With
-- scramble, there's a (small) chance that you'll hear only
-- one part, played four times.
-- You can maybe hear this better if you play a clap at the
-- same time, to mark the start of the cycle. Then you can
-- hear that parts aren't repeating within the cycle.
d1 $ shuffle 4 $ n "0 1 2 3 4 5 6 7" # sound "arpy"
# room 0.3 # sz 0.8
d2 $ sound "clap"
-- The "choose" function is for when you want to pick between
-- single values. It produces a continuous stream, with no
-- structure, so the following won't produce any events:
d1 $ sound (choose ["bd", "arpy", "snare"])
-- You'll need to provide some structure, with a function like
-- 'segment', which in this case picks 8 values per cycle:
d1 $ sound (segment 8 $ choose ["bd", "arpy", "snare"])
-- Or 'struct', which picks values according to a binary pattern:
d1 $ sound (struct "t t ~ t" $ choose ["bd", "arpy", "kick"])
d1 $ sound (struct "t(5,8)" $ choose ["bd", "arpy", "kick"])
-- Or by combining it with a pattern that *does* have structure:
d1 $ squiz "0*2 4 2 5 0 6*2 4 7"
# sound (choose ["bd", "arpy", "kick"])
-- Another 'gotcha' - the parameters to choose are a list of values,
-- *not*, patterns, so you can't normally use mininotation there.
-- This *won't* work.
d1 $ squiz "0*2 4 2 5 0 6*2 4 7"
# sound (choose ["bd*5", "arpy*2", "kick clap"])
-- I'll try to fix this in a future version of tidal! There is a
-- workaround, which is to use the 'innerJoin' function. Then you
-- can choose between patterns:
d1 $ squiz "0*2 4 2 5 0 6*2 4 7"
# sound (innerJoin $ choose ["bd*5", "arpy*2", "kick clap"])
-- You can use choose with any parameter.
-- For example:
d1 $ sound "clap:4(3,8)"
# speed (choose [2,5,0.5])
-- The following example is a bit different to the above, because
-- a new value is chosen only once per cycle:
d1 $ sound "clap:4(3,8)"
# speed "[2|5|0.5]"
-- You could get the same behaviour from choose with 'segment'ing it
-- by a cycle:
d1 $ sound "clap:4(3,8)"
# speed (segment 1 $ choose [2,5,0.5])
-- The 'wchoose' function is like 'choose', but you can give
-- a 'weighting' for each possibility. So something with a weighting
-- of '4' would be twice as likely to be chosen as one with a weighting
-- of '2', for example:
d1 $ sound "clap*4" # speed (wchoose [(2, 4), (-2, 2)])
-- The above claps will play either with a speed of '2' , or '-2'.
-- You can hear that negative speeds cause sounds to play backwards!
-- '2' has a weighting of '4', and '-2' has a weighting of
-- '2', so is half as likely to play.
-- Here I've weighted things so you get a lot of kicks, occasional
-- claps, and rarer snares:
d1 $ squiz "1 4*8 8*2 0*3"
# sound (wchoose [("bd", 8), ("snare", 0.5), ("clap", 1)])
-- Ok one more thing! In Tidal, randomness is "deterministic". At
-- a certain cycle time, you will always get the same number. We
-- saw this at the start of the lesson, with resetCycles. That
-- resets the cycle count, as if you just started Tidal up. You
-- can then hear that the 'random' numbers are the same.
-- This can result in unexpected results.
-- Listen to this:
d1 $ sound "clap*2" # speed (range 0.1 2 rand) # pan rand
-- You can hear that on the left speaker, the 'speed' of the
-- sound is always low, and when it pans to the right, it's
-- always high. Strange! This is because the same 'random'
-- number stream is used for both the speed and the pan, so
-- they get the same numbers, and seem to interact.
-- This can be nice! But if you don't want this effect, you can
-- avoid it by manipulating the timeline of one of the random
-- patterns. For example:
d1 $ sound "clap*2" # speed (range 0.1 2 rand)
# pan (slow 1.001 rand)
-- I only slowed that 'rand' down by a tiny amount, but that's
-- enough to end up with totally different numbers.. So now
-- you're as likely to get lower speeds on the left as on the right.
-- endregion
-- region Lesson 3 - randcat, stripe, degrade, someX, randslice + more
-- randcat
-- randcat is a variant of cat, which we haven't actually looked at
-- yet, so lets start with that..
d1 $ sound (cat ["kick snare:4 [~ kick] snare:5", "kick snare:4 . hc(5,8)"])
-- So you can hear that cat 'concatenates' patterns - it plays them
-- one after the other, in order.
-- randcat on the other hand, plays them in random order:
d1 $ sound (randcat ["kick snare:4 [~ kick] snare:5", "kick snare:4 . hc(5,8)"])
-- You can give it as many patterns to choose from as you like:
d1 $ sound (randcat ["kick snare:4 [~ kick] snare:5",
"kick snare:4 . hc(5,8)",
"snare:3(9,16)"
]
)
-- You can use it to randomise control patterns other than sound,
-- e.g. the vowel effect:
d1 $ vowel (randcat ["a e*2 i o", "e o u", "o*8"])
# sound ("kick snare:4 clap:4")
-- wrandcat is to randcat, what wchoose is to choose. That is,
-- You can give the choices relative probabilities:
d1 $ sound (wrandcat [("bd sn:4(3,8)", 1),
("arpy clap", 0.5),
("cpu(5,8)", 0.25)
]
)
-- stripe is a weird one. Lets start with a rhythm with the
-- cpu2 samples:
d1 $ n "0 4*2 ~ 4 2 4 5 ~" # sound "cpu2"
# squiz 2
-- 'fast 2' would squeeze that into two cycles:
d1 $ fast 2 $ n "0 4*2 ~ 4 2 4 5 ~" # sound "cpu2"
# squiz 2
-- stripe is similar, but the cycles are random durations,
-- although still fit the cycle:
d1 $ stripe 2 $ n "0 4*2 ~ 4 2 4 5 ~" # sound "cpu2"
# squiz 2
-- It sounds random, but against a straight clap, you can hear
-- every other repetition still perfectly aligns with the cycle:
d2 $ sound "clap:4"
-- degrade - remember the ? mininotation modifier in the previous
-- video? It drops events at random:
d1 $ sound "bd*8?"
-- Degrade is a function that does the same:
d1 $ degrade $ sound "bd*8"
-- Just like this:
d1 $ sound "bd*8?0.6"
-- You can specify a probability, by using 'degradeBy'. E.g.,
-- to give each event a 60% chance of being 'lost':
d1 $ degradeBy 0.6 $ sound "bd*8"
-- 'sometimes' applies a function to a pattern, but only sometimes.
-- lets hurry this rhythm, but only sometimes:
d1 $ sometimes (hurry 2) $ n "0 ~ 3 1 5 2 ~ 5" # sound "cpu"
-- Here's the original, which sounds pretty boring in comparison:
d1 $ n "0 ~ 3 1 5 2 ~ 5" # sound "cpu"
-- You can use it to apply effects as well.
d1 $ sometimes (# crush 4) $ n "0 ~ 3 1 5 2 ~ 5" # sound "cpu"
-- There's also a 'sometimesBy' variant, for specifying a
-- probability:
d1 $ sometimesBy 0.3 (# crush 4) $ n "0 ~ 3 1 5 2 ~ 5" # sound "cpu"
-- There's some aliases for different probabilities:
{-
sometimes = sometimesBy 0.5
often = sometimesBy 0.75
rarely = sometimesBy 0.25
almostNever = sometimesBy 0.1
almostAlways = sometimesBy 0.9
-}
-- So you can do this:
d1 $ rarely (# crush 4) $ n "0 ~ 3 1 5 2 ~ 5" # sound "cpu"
-- somecycles is similar to sometimes, but works on whole
-- cycles at a time, rather than individual events:
d1 $ somecycles (hurry 2) $ n "0 ~ 3 1 5 2 ~ 5" # sound "cpu"
# speed 1.5
-- Again, there's a 'somecyclesBy' variant for being specific
-- about that probability. To apply the squiz, 90% of the time:
d1 $ somecyclesBy 0.9 (# squiz 4) $ n "0 ~ 3 1 5 2 ~ 5" # sound "cpu"
# speed 1.5
-- randslice is a bit like 'slice' that we met a couple of lessons
-- ago:
d1 $ slice 4 "0 1 2 3" $ sound "break:8"
-- Instead of taking a pattern of slices though, it picks slices at
-- random. So to play a random quarter of this break:
d1 $ randslice 4 $ sound "break:8"
-- We can use 'loopAt' to fit them to a cycle, just like we saw before
-- with 'chop' and 'striate':
d1 $ loopAt 1 $ randslice 4 $ sound "break:8*4"
-- We could also do the same sort of thing by giving 'slice' or 'splice'
-- a random pattern:
d1 $ splice 4 (segment 4 $ irand 4) $ sound "break:8"
-- endregion
-- region Exercises:
-- TODO Play with delay
# delay 0.3 # delaytime (1/3) # delayfb 0.8 # speed 1.5
-- TODO Play with negative speed, e.g. backward clap
once $ s "glitch:7" # gain 1.1
-- d5
d1 $ sound "[bd(5,8), [~ cp]]"
# speed (range 0.5 4 perlin)
# gain 0.8
-- Study: "Oh boy! So much fun applying the lessons learned so far."
setcps (75/60/4)
xfadeIn 1 8 $ jux (iter 2) $ loopAt 6 $ chop 1 $ striate 64 $ speed (struct "t(2,7)" $ range 0.7 1 sine) # sound "bev" # gain 0.7 # delay 1 # delaytime 0.675 # delayfb 0.8 # room 0.2
d2 $ juxBy 0 (iter 4) $ rev $ struct "t(5,8)" $ sound "tabla" # n "<21 24> <16 6> <4 12>" # gain 0.8
-- endregion