└── README.md /README.md: -------------------------------------------------------------------------------- 1 | ## My own Tidal Cycles Tutorial 2 | 3 | ##### maybe this can be useful for someone someday. Atm, it is only to have organized what I have been learning in Tidal. 4 | 5 | ### Cheat Sheet 6 | 7 | #### Pattern Transformers > Event Scale < 8 | 9 | ##### change order 10 | ```c2hs 11 | d1 $ palindrome $ --- is the same as 12 | d1 $ every 2 (rev) $ n 13 | ``` 14 | ```c2hs 15 | d1 $ iter 4 $ sound 16 | d1 $ sound $ scramble 3 "xxx*3" 17 | d1 $ every 4 (0.25 <~) $ sound 18 | d1 $ "<0 0.5 0.125>" <~ sound 19 | d1 $ "[0 0.25]/4" <~ (sound " ") 20 | ``` 21 | 22 | ##### play a fraction of a pattern 23 | ```c2hs 24 | d1 $ linger 0.25 $ sound 25 | d1 $ linger "<0.25 0.5 1>" $ sound 26 | d1 $ every 2 (linger 0.25) $ 27 | d1 $ trunc "<0.75 0.25 1>" $ sound 28 | d1 $ zoom (0.25, 0.75) $ sound 29 | d1 $ every 4 (zoom (0.25, 0.75)) $ sound 30 | ``` 31 | ##### apply a func sometimes in a cycle 32 | ```c2hs 33 | d1 $ sometimesBy 0.25 (somefunc) $ sound 34 | ``` 35 | 36 | ##### filter events 37 | ```c2hs 38 | d1 $ degradeBy 0.9 $ sound 39 | ``` 40 | 41 | ##### More groove 42 | ```c2hs 43 | d1 $ brak $ sound 44 | d1 $ swingBy (1/3) 4 $ sound 45 | # somefunc (sine*2) 46 | ``` 47 | 48 | ##### Euclidean 49 | ```c2hs 50 | d1 $ sound "bd(3,8) sn(5,8)" 51 | ``` 52 | ##### rotate 53 | ```c2hs 54 | d1 $ sound "bd(5,8,2)" 55 | d1 $ e 3 8 $ sound "bd*2 [sn cp]" 56 | d1 $ sound "bd([5 3]/2,8)" 57 | ``` 58 | 59 | #### Pattern Transformers > Pattern Scale < 60 | 61 | ##### apply a func. in some cycles 62 | ```c2hs 63 | d1 $ someCyclesBy 0.25 (fast 2) $ sound 64 | ``` 65 | 66 | ##### like multiples 'every' 67 | ```c2hs 68 | d1 $ foldEvery [3, 4, 5] (fast 2) $ sound 69 | ``` 70 | ##### starts at cycle 0 71 | ```c2hs 72 | d1 $ every' 4 0 (somefunc) $ sound 73 | ``` 74 | ##### starts at cycle 2 75 | ```c2hs 76 | d1 $ every' 4 2 (somefunc) $ sound 77 | ``` 78 | 79 | ##### Fit is cool! Use it in seqPLoop 80 | ```c2hs 81 | d1 $ fit' 1 4 (run 4) "[0 3*2 2 1 0 3*2 2 [1*8 ~]]/2" $ s "" 82 | ``` 83 | 84 | ##### Spread! 85 | ```c2hs 86 | d1 $ spread slow [2,4/3] $ sound --- is the same as 87 | d1 $ slow "<2 4/3>" $ sound 88 | ``` 89 | ```c2hs 90 | d1 $ spread ($) [fast 2, rev, slow 2, striate 3, (# speed "0.8")] $ sound 91 | ``` 92 | ```c2hs 93 | d1 $ fastspread slow [2,4/3] $ sound --- inside one cycle(?) 94 | ``` 95 | 96 | ##### Within! 97 | ```c2hs 98 | d1 $ within (0, 0.5) (fast 2) $ sound 99 | d1 $ within (0.75, 1) (# speed "0.5") $ sound 100 | ``` 101 | ```c2hs 102 | d1 $ chunk 4 (somefunc) $ s 103 | ``` 104 | 105 | #### > Compositions < 106 | 107 | ##### One after the other 108 | ```c2hs 109 | d1 $ seqPLoop [ 110 | (0, 16, s "" ), 111 | (16, 32, s "" ) 112 | ] # n (irand 16) 113 | ``` 114 | ```c2hs 115 | d1 $ randcat[ 116 | s " ", 117 | s " " 118 | ] # n ( irand 16 ) 119 | ``` 120 | 121 | ##### All together now 122 | ```c2hs 123 | d2 $ stack [ 124 | s " ", 125 | s " " 126 | ] # n (run 16) 127 | ``` 128 | 129 | ##### Both ways!!! 130 | ```c2hs 131 | d2 $ seqPLoop [ 132 | (0, 32, stack [ 133 | slow 2 $ s " " # gain 1.5, 134 | s " " # gain 0.8 135 | ] ), 136 | (32, 64, stack[ 137 | s " ", 138 | s " " 139 | ] ) 140 | ] 141 | ``` 142 | 143 | #### > Utility < 144 | 145 | ```c2hs 146 | d1 $ sound "xxx*4" # speed (rand + 0.5) 147 | d1 $ n (run "<4 8 4 6>") # sound 148 | (scale 0.25 0.75 $ rand) 149 | # somefunc (slow 4 $ sine * 0.5 + 1) 150 | # somefunc (scale (-2) 3 $ tri) 151 | # somefunc (slow 8 $ saw) 152 | d1 $ s " xxxx*4 " # n (choose [0,2,5]) 153 | ``` 154 | ##### constrain continuous pattern's speed 155 | ```c2hs 156 | d1 $ s (discretise 1 $ choose["kif", "kip"]) 157 | d1 $ s (struct "x ~ x ~ ~ x ~ ~" $ choose["kif", "kip"]) 158 | solo $ d1 $ 159 | ``` 160 | 161 | #### > Transitions < 162 | 163 | ```c2hs 164 | t1 (clutchIn 8) $ sound 165 | t2 (jumpIn' 1) $ 166 | ``` 167 | ---------------------------------------------------------------------------------------------- 168 | 169 | ### Slack Excerpts 170 | ##### The Slack Tidal channel is great to learn, but the information is ephemeral. So I put here conversations about something that I might want to use, or experiment with, or learn about. 171 | 172 | ###### averageaht 5:43 PM 173 | > I know this information can be put together from the tutorial, but I can't figure it out: 174 | How can I play a chord progression that lasts more than a single cycle (say, 6 quarter notes) every N cycles? 175 | > assume 4/4 time. every 4 measures I want to play some notes, say ``` "c1 e1 g1 b1 d1" ``` , all quarter notes 176 | let me know if that's clear or not 177 | I know I can pitch notes with up or use midinotes to create the notes 178 | I can get something to happen every 4 measures using every 4, but this seems like a hack: 179 | ```c2hs 180 | d1 $ every 4 (const $ sound "bd") $ sound "~" 181 | ``` 182 | > guess I use slowcat to create a pattern longer than a single cycle 183 | 184 | ###### efairbanks 9:11 PM 185 | > You can use slow and fast to change the speed of a Pattern, not just ParamPatterns. 186 | 187 | ###### yaxu 9:12 PM 188 | > is this what you want? 189 | ```c2hs 190 | "<[c1 e1 g1 b1] [d1 ~ ~ ~] ~ ~>" 191 | ``` 192 | ###### efairbanks 9:13 PM 193 | ```c2hs 194 | d1 $ s "pluck*2" # up (slow 8 "0 3 5 7") 195 | ``` 196 | > Or even 197 | ```c2hs 198 | d1 $ s "pluck*2" |*| up "[0,3,7]" |*| up (slow 8 "0 3 5 7") 199 | ``` 200 | > If you want to get more advanced, you can apply a slow progression to multiple elements: 201 | ```c2hs 202 | do 203 | cps 1 204 | let progression p = p |*| up (slow 8 $ "0 5 10 7") 205 | let melody = progression $ stut 4 0.3 1.033 $ fast 2 $ up "0 3 7 10" |*| up "12" # s "pluck" 206 | let bass = progression $ s "pluck" |*| speed "0.5" |*| gain "1.0" # shape 0.6 # cut "-1" 207 | d1 $ stack [melody, bass] 208 | ``` 209 | 210 | ###### averageaht 9:16 PM 211 | > \@yaxu yes, that is what I want, can I slow that down so that it happens in 2 cycles I guess? 212 | 213 | > \@efairbanks I dont get why the plucks are playing twice in your example, even if I remove *2 214 | 215 | > oh, I guess 8/4=2 216 | ```c2hs 217 | d1 $ s "pluck" # up (slow 6 "0 3 5 7 9 11") 218 | ``` 219 | works 220 | 221 | ###### efairbanks 9:19 PM 222 | > Yeah, and there slow is essentially changing the length of a cycle. 223 | So you could alternate between two melodies per cycle like so: 224 | ```c2hs 225 | d1 $ s "pluck" # up (slow 6 "<[0 3 5 7 9 11] [2 4 8 11 13 15]>") 226 | ``` 227 | 228 | ###### averageaht 9:20 PM 229 | > hmm I don't want to change the length of the cycle 230 | 231 | ###### efairbanks 9:21 PM 232 | > It's only changing it local to the Pattern, not globally. 233 | 234 | ###### averageaht 9:21 PM 235 | > how do I get something that's "in time" with my other patterns? 236 | 237 | ###### efairbanks 9:21 PM 238 | > Another way to think of slow is that it slows down the time that the pattern is receiving, so to speak. 239 | > The pattern: 240 | ```c2hs 241 | "<[0 3 5 7 9 11] [2 4 8 11 13 15]>" 242 | ``` 243 | > is operating on a different time scale than the "pluck" pattern because you've slowed it. 244 | > But you could then do. 245 | ```c2hs 246 | d1 $ (s "pluck" # up (slow 6 "<[0 3 5 7 9 11] [2 4 8 11 13 15]>")) |*| up "0 7 12" 247 | ``` 248 | > And the cycle ``` "0 7 12" ``` is being evaluated after all that, so it is operating at the normal time scale and will occupy one normal cycle. 249 | 250 | > I mean, not strictly. There are a lot of ways to achieve what you want to do. 251 | The ``` <> ``` mean "every cycle play the next element within <>" 252 | Where each element occupies one cycle. 253 | And then the whole thing is being slowed by a factor of 6. 254 | 255 | ###### averageaht 9:26 PM 256 | > okay, so there are six notes in those two cycles 257 | 258 | ###### efairbanks 259 | > 6 notes in one cycle, 6 notes in the next. 260 | And because the whole thing is slowed by a factor of 6 after that, each cycle is 6 times as long as it normally would be. 261 | So each note ends up being the length of "one cycle" from a global reference point. 262 | 263 | ###### averageaht 9:27 PM 264 | > so I guess the alternative to ``` <> ``` is ``` slowcat ```? 265 | 266 | ###### yaxu 9:28 PM 267 | > an important point is that tidal has no fixed idea of what a beat is 268 | the reference point is (almost) always the cycle 269 | 270 | ###### averageaht 9:30 PM 271 | > hmm I got the impression a cycle was a measure 272 | 273 | ###### efairbanks 9:32 PM 274 | > Yeah, cycles are more like units of time, and time is malleable in Tidal. 275 | Tempo is defined in cycles per second rather than BPM. 276 | 277 | ###### anny 9:32 PM 278 | > cps 1 == bpm 60 279 | 280 | ###### yaxu 9:33 PM 281 | > only if you put four events per cycle 282 | 283 | ###### efairbanks 9:33 PM 284 | > ^ depending on if you want to think of a cycle as a beat. 285 | 286 | ###### yaxu 9:34 PM 287 | > cps 1 feels like 120 bpm to me 288 | 289 | ###### averageaht 9:35 PM 290 | > why doesn't this work? 291 | ```c2hs 292 | d1 $ slowcat [s "pluck*4" # up "[0 3 5 7]", s "pluck*2 ~ ~" # up "9 11 0 0 "] 293 | ``` 294 | 295 | ###### yaxu 9:35 PM 296 | > but if you put three events in a cycle it'll feel like a different bpm 297 | 298 | ###### efairbanks 9:36 PM 299 | > /@averageaht works for me 300 | 301 | > But! 302 | 303 | > This ``` "pluck*2 ~ ~" ``` 304 | 305 | > Does not mean 306 | 307 | ``` "pluck pluck ~ ~" ``` 308 | 309 | > It means 310 | 311 | ``` "[pluck pluck] ~ ~" ``` 312 | 313 | > That's why it's playing the 9 twice. 314 | 315 | > The up pattern hasn't switched to 0 yet. 316 | 317 | ###### averageaht 9:36 PM 318 | > hmm for me it's playing the 9 twice 319 | 320 | ###### yaxu 9:37 PM 321 | > yes the second pluck will start 1/6th of the way into each cycle 322 | 323 | ###### efairbanks 9:37 PM 324 | ```c2hs 325 | d1 $ slowcat [s "pluck*4" # up "[0 3 5 7]", s "pluck pluck ~ ~" # up "9 11 0 0 "] 326 | ``` 327 | > works the way you'd expect. 328 | 329 | ###### yaxu 9:38 PM 330 | > you can do ``` "pluck!2 ~ ~" ``` for that 331 | 332 | ###### efairbanks 9:39 PM 333 | > btw \@averageaht if you want to apply the same progression to multiple patterns, you can do stuff like this: 334 | ```c2hs 335 | d1 $ slow 2 $ 336 | stack [s "bass:3(3,8)", s "pluck(5,8,2)" # up "24"] |*| up (slow 4 "0 5 7 0") 337 | ``` 338 | 339 | ###### averageaht 9:39 PM 340 | > I can see how angle brackets are useful if cycle=beat. unfortunately they seem to just "not work" for me. I get: 341 | no synth or sample named 'nil' could be found. 342 | instrument not found: nil 343 | 344 | ###### yaxu 9:39 PM 345 | > well if you just want to repeat once you can do ``` "pluck ! ~ ~" ``` 346 | 347 | ###### anny 9:39 PM 348 | > ``` pluck ! ``` has the same effect - number is optional: ``` pluck !!! ``` 349 | 350 | ###### efairbanks 9:40 PM 351 | > That's cool as heck. 352 | Is there way to tell Tidal to continue the last note instead of cutting it off in the case of using cut 353 | or synthdefs as well? I heard something about _ but last time I tried it, it didn't work for me. 354 | 355 | > oh actually there is @ 356 | 357 | 358 | 359 | ##### 2017-07-02 ---------------------------------------------------------------------------------------------------- 360 | 361 | ###### mauro 2:46 PM 362 | 363 | (n.a. this is cool! Promising!) 364 | 365 | > added this Smalltalk snippet 366 | ```Smalltalk 367 | Tidal { 368 | classvar ghci, ghciOutput; 369 | 370 | *new { 371 | ^this.start(); 372 | } 373 | 374 | *start { 375 | if ( currentEnvironment.at(\tidal).isNil ){ 376 | ~tidal = this; 377 | ghci = Pipe.new("ghci -XOverloadedStrings", "w"); 378 | ghciOutput = Routine { 379 | var line = ghci.getLine; 380 | while( 381 | { line.notNil }, 382 | { 383 | line.postln; 384 | line = ghci.getLine; 385 | } 386 | ); 387 | ghci.close; 388 | }; 389 | }; 390 | } 391 | 392 | *send { 393 | |message| 394 | 395 | ghci.write("%\n".format(message)); 396 | ghci.flush; 397 | } 398 | 399 | *stop { 400 | ghci.close; 401 | ~tidal = nil; 402 | } 403 | 404 | } 405 | ``` 406 | 407 | ###### mauro 2:47 PM 408 | 409 | > with a little help of @munshkr, it's possible to talk to tidal from supercollider 410 | ```c2hs 411 | Tidal.start; 412 | Tidal.send(":module Sound.Tidal.Context"); 413 | Tidal.send("(cps, getNow) <- bpsUtils"); 414 | Tidal.send("(d1,t1) <- superDirtSetters getNow"); 415 | Tidal.send(":set prompt ".format("tidal> ".quote)); 416 | Tidal.send("d1 $ sound % # release 0.25".format("kick".quote)); 417 | Tidal.send("d1 silence"); 418 | Tidal.stop; 419 | ``` 420 | 421 | ###### datamads 11:55 PM 422 | 423 | > A dope little trick that it deserves the spotlight: https://medium.com/potac/reusable-code-in-tidalcycles-59b7a4dba30a 424 | 425 | ##### 2017-07-07 ------------------------------------------------------------------------------------------------------------ 426 | 427 | ###### bgold 8:38 PM 428 | 429 | > Ooh, hadn't realized that there's no reason custom effects can't also use parameters like n (or freq). Note-following filter: 430 | 431 | ```scd 432 | ~dirt.addModule( \lpf2, {|dirtEvent| dirtEvent.sendSynth("dirt_lpf2" ++ ~dirt.numChannels, 433 | [cutoff2: ~cutoff2, freq:~freq, resonance:~resonance, out: ~out])}, {~cutoff2.notNil}); 434 | 435 | SynthDef("dirt_lpf2"++~dirt.numChannels, {|out, cutoff2=0, resonance, freq| 436 | var sig; 437 | sig = In.ar(out, ~dirt.numChannels); 438 | sig = RLPF.ar(sig, freq*(1+cutoff2), resonance.linexp(0, 1, 1, 0.001)); 439 | ReplaceOut.ar(out, sig); 440 | }).add; 441 | ``` 442 | 443 | 444 | ##### 2017-07-17------------------------------------------------------------------------------------------------------------ 445 | 446 | ##### this is pure gold: 447 | 448 | ###### danielmkarlsson 5:51 PM 449 | > Hey gang. 450 | I'd like to choose a new value for a sine envelope each time that particular envelope has completed its full duration. 451 | This example chooses a new value for the sine envelope each cycle which is not what I want: 452 | ```c2hs 453 | d1 $ s "bass1:4*8" # cut 1 # gain (slow (choose [1..16]) $ scale 0 1 $ sine) 454 | ``` 455 | > That said, you can fake it for a finite amount of time with seqP 456 | 457 | ```c2hs 458 | let randomList sn len = map (ceiling . (* sn) . timeToRand) [1..len] 459 | let cycleSines sn len = seqP $ map (\(a,b,c) -> (fromIntegral a, fromIntegral b, slow (fromIntegral c) sine)) $ zip3 x0 x1 r 460 | where x0 = take (length r - 1) $ scanl (+) 0 r 461 | x1 = scanl1 (+) r 462 | r = randomList sn len 463 | ``` 464 | 465 | > so `cycleSines 16 100` will give you a series of sines with a `slow` in the range 1..16, and repeat for 100 sine cycles, 466 | which in this case is about to cycle count 850 (because of the random lengths). 467 | 468 | > Note that due to the way "random" numbers work, this will give the same exact sequence each time you 469 | use the same `sn` and `len`. If you want to mix things up you can change up the `[1..len]` in randomList 470 | ```c2hs 471 | let randomList' sn len k = map (ceiling . (* sn) . timeToRand . (+ k)) [1..len]` would give a different result for different `k 472 | ``` 473 | * [further footnote, `sine` starts its cycle at its midpoint, 0.5, if you want the waves to "reset" their cycle at 0.0 I think you can just rotate it, replacing `sine` with `0.25 ~> sine`] 474 | 475 | ###### bgold 3:48 AM 476 | > I realized mine doesn't work right - the phases aren't necessarily going to line up to be continuous. 477 | 478 | ###### yaxu 10:57 479 | > ok try this 480 | > eval these 481 | ```c2hs 482 | import Sound.Tidal.Time 483 | import Sound.Tidal.Utils 484 | import Data.Maybe 485 | ``` 486 | ###### yaxu 10:57 487 | > then this 488 | ```c2hs 489 | let randArcs :: Int -> Pattern [Arc] 490 | randArcs n = do rs <- mapM (\x -> (pure $ (toRational x)/(toRational n)) <~ rand) [0 .. (n-1)] 491 | let rats = map toRational rs 492 | total = sum rats 493 | pairs = pairUp $ accum 0 $ map ((/total)) rats 494 | return $ pairs -- seqP $ map (\(a,b) -> (a,b,"x")) pairs 495 | where pairUp [] = [] 496 | pairUp xs = (0,head xs):(pairUp' xs) 497 | -- 498 | pairUp' [] = [] 499 | pairUp' (a:[]) = [] 500 | pairUp' (a:b:[]) = [(a,1)] 501 | pairUp' (a:b:xs) = (a,b):(pairUp' (b:xs)) 502 | -- 503 | accum _ [] = [] 504 | accum n (a:xs) = (n+a):(accum (n+a) xs) 505 | randStruct n = splitQueries $ Pattern f 506 | where f (s,e) = mapSnds' fromJust $ filter (\(_,x,_) -> isJust x) $ as 507 | where as = map (\(n, (s',e')) -> ((s' + sam s, e' + sam s), 508 | subArc (s,e) (s' + sam s, e' + sam s), 509 | n) 510 | ) $ enumerate $ thd' $ head $ arc (randArcs n) (sam s, nextSam s) 511 | compressTo (s,e) p = compress (cyclePos s, e-(sam s)) p 512 | substruct' :: Pattern Int -> Pattern a -> Pattern a 513 | substruct' s p = Pattern $ \a -> concatMap (\(a', _, i) -> arc (compressTo a' (inside (1/toRational(length (arc s (sam (fst a), nextSam (fst a))))) (rotR (toRational i)) p)) a') (arc s a) 514 | ``` 515 | > then this 516 | ```c2hs 517 | d1 $ slow 16 $ substruct' (randStruct 16) $ sound "arpy*16" # gain (scale 0.5 1 sine) # speed (discretise 1 $ scale 1 2 rand) 518 | ``` 519 | ###### yaxu 12:05 AM 520 | > a bit better: 521 | ```c2hs 522 | d1 $ substruct (slow 8 $ randStruct 4) $ sound "arpy*8" # gain (scale 0.5 1 sine) # up (discretise 1 $ choose [0,7,12]) 523 | 524 | d1 $ substruct (randStruct 2) $ sound "arpy*8" # gain (scale 0.5 1 sine) # up (discretise 1 $ choose [0,7,12,2]) 525 | ``` 526 | ###### yaxu 1:12 PM 527 | > The first pattern sounds like it has no metronomic pulse when you play it on its own but 528 | when you add the second pattern you can hear that the cp always aligns perfectly with 529 | the start of every fourth repetition of the first pattern 530 | ```c2hs 531 | d1 $ slow 4 $ substruct' (randStruct 4) $ stack [n (off 0.125 (+7) $ "e2 d4 e3 [~ g3]") # sound "superzow" # pan saw # lpf (scale 500 1000 sine) # lpq 0.3] 532 | 533 | d2 $ slow 4 $ sound "cp" # shape 0.6 534 | ``` 535 | ###### danielmkarlsson 1:19 PM 536 | > I was messing around with this and it feels like it might be slightly off at times choosing values while not at zero. 537 | >Try this: 538 | ```c2hs 539 | d1 540 | $ slow 16 541 | $ substruct' (randStruct 4) 542 | $ s "bass1*64" 543 | # gain (scale 0 1 $ sine) 544 | # up (discretise 1 $ choose [0,2,3,5,7,8,11] + choose [0,12,24,36]) 545 | # n (discretise 1 $ choose [5,7,9,13,19]) 546 | # pan (discretise 1 $ scale 0 1 $ rand) 547 | ``` 548 | > Ah! bgolds solution with `0.25 ~> sine` sorted it! 549 | 550 | 551 | 552 | --------------------------------------------------------------------------------