Here is a more concise version of trancegate, based directly on the original implementation by @Yaxu:
let trancegate i r = trigZeroJoin . fmap (\b -> ampbus i $ if b then slow r (when (<1) (const $ segment 8 isaw) $ pure 1) else 0.7)
in do
d1 $ note "-14" # sound "supersaw" # trancegate 1 0.05 ("1011010110011101") # gain 0.8
d2 $ s "kick:6*4"
Is it possible to create a helper function, for example randBits, that takes a number n and outputs a Boolean pattern of length n which can be directly used as the third argument of trancegate? The idea is to randomly determine which slices the gate closes on, so that I can write something like:
let trancegate i r = trigZeroJoin . fmap (\b -> ampbus i $ if b then slow r (when (<1) (const $ segment 8 isaw) $ pure 1) else 0.7)
in do
d1 $ note "-14" # sound "supersaw" # trancegate 1 0.05 (randBits 16) # gain 0.8
d2 $ s "kick:6*4"
Any suggestions or examples for implementing randBits in TidalCycles would be greatly appreciated.
Thanks so much for this, @yaxu! That’s incredibly concise and elegant. I love how randBits gives a perpetually unpredictable gating pattern. Perfect for what I wanted. Really appreciate the quick solution:
let trancegate i r = trigZeroJoin . fmap (\b -> ampbus i $ if b then slow r (when (<1) (const $ segment 8 isaw) $ pure 1) else 0.7)
randBits n = segment n ((/= 0) <$> irand 2)
in do
d1 $ note "-14" # sound "supersaw" # trancegate 1 0.05 (randBits 16) # gain 0.8
d2 $ s "kick:6*4"
I found that I sometimes need a random pattern to be generated once and have it repeat every cycle. I made a binary convertor such that:
let trancegate i r = trigZeroJoin . fmap (\b -> ampbus i $ if b then slow r (when (<1) (const $ segment 8 isaw) $ pure 1) else 0.7)
in do
d1 $ note "-14" # sound "supersaw" # trancegate 1 0.05 ("1011010110011101") # gain 0.8
d2 $ s "kick:6*4"
is the same as:
let trancegate i r = trigZeroJoin . fmap (\b -> ampbus i $ if b then slow r (when (<1) (const $ segment 8 isaw) $ pure 1) else 0.7)
bin n=fastcat$map pure$reverse$let f x|x==0=[]|1>0=(x`mod`2==1):f(x`div`2)in if n==0 then[False]else f n
in do
d1 $ note "-14" # sound "supersaw" # trancegate 1 0.05 (bin 46493) # gain 0.8
d2 $ s "kick:6*4"
Of course, for 8-bit numbers we can usebinary:
let trancegate i r = trigZeroJoin . fmap (\b -> ampbus i $ if b then slow r (when (<1) (const $ segment 8 isaw) $ pure 1) else 0.7)
in do
d1 $ note "-14" # sound "supersaw" # trancegate 1 0.05 (binary $ pure 241) # gain 0.8
d2 $ s "kick:6*4"
After playing with the code all day and trying bit scrambling, I ended up using seed-based hashing to generate fixed-length deterministic pseudo-random bits:
let trancegate i r = trigZeroJoin . fmap (\b -> ampbus i $ if b then slow r (when (<1) (const $ segment 8 isaw) $ pure 1) else 0.7)
rngBin s l = fastcat $ map pure $ take l $ f ((1103515245*s+12345) `mod` 2^64)
where f 0 = repeat False; f x = (x `mod` 2==1):f(x`div`2)
in do
d1 $ note "-14" # sound "supersaw" # trancegate 1 0.06 (rngBin 14 16) # gain 0.8
d2 $ s "kick:6*4"
I’m just starting out with TidalCycles, and this makes experimenting with patterns so much more approachable. Thank you!
hey @yaxu, I was curious what I would need to do to alter this so that it could be passed into the second argument of binaryN: ex d1 $ struct (binaryN 16 (randBits 16)) $ "s “bd”. it worked fine for the trancegate example but not for the binaryN experiment.