Here's an introduction to the 'ur' function, which lets you make patterns out of patterns, to make a track. I also talk about issues with 'orbits' and global effects (e.g. reverb, delay) you might have when using ur, seqPLoop and stack. This is still an area of Tidal that could be developed, so I'd be happy to have your ideas about possible features/improvements.
thank you alex! that ur seems even more...neat than seqP
alright...i'm german so i'll do a bit of germaning:
you're quite right, "ur-" means something that's higher than something else,
but in value-'cause-it's-older-so-to-say- A N C I E N T, not in height
so...there's plenty o' fish in the sea, but there's only one UR F I S H left, see: Quastenflosser
the austrians have a quite charming way to express the feeling of being well and cosy when all things align in space/time: leiwand
the superlative of leiwand, like when all that cosy space/time warps into a perfectly traversable wormhole of well-being is: UR L E I W A N D
which is how i feel here, and hopefully soon in tidalcycles as well, cheers
ps: oh dear, i only now realized:
this is just a form of appreciation of conservatism baked into and dragged along in language
This is super useful even for live performance!
The fact that you're not able to hear what you're working immediately is a blessing I thin.
Sometimes it requires a lot of agility to turn every second channels off when you want to introduce a rapid change, sequencing it out in a pattern of patterns definitely helps.
Two things I'm curious about:
Is it possible to layer two effects on top of another inside of the metapattern?
I've tried
ur "pat1:fx1:fx2"
in this case only fx1 seems to work, guess you can always define effects as composite functions separately.
I'm not sure if I correctly understand the syntax of the metapattern.
When it comes to division of the number of cycles we give to the ur function, if we have a pattern ur 4 "pat1 pat2" it seems to divide it evenly between them (each gets two cycles out).
For ur 8 "[pat1, ~ pat2] pat2 will only play on cycles 5-8.
Not sure what happens if we slow the pattern down or speed it up though.
You have no idea how much I've been waiting for that lesson, thank you so much !
I have one related issue (user error I bet ;)) : ur works perfectly, as expected... except for the fact that I can't find a way to have several cycle long patterns, say a 4 bar long bassline, to start at their respective beginning. I've tried using resetCycles, reset and trigger, but I can't get constant results. Any tip ? Cheers !
No not currently. I could think about adding that.. Right now you'd have to make an fx3 that does both fx1 and fx2.
Yes pat1 and ~ pat2 are layered up as subpatterns. So pat2 is only active for the second half. There's lots on the mininotation in week 1: Week 1 - mini-notation - Tidal Club
Hm, here's a version of ur called ur' that plays each pattern from cycle 0, is that better?
import Data.Maybe (fromMaybe)
import Sound.Tidal.Utils (wordsBy)
ur' :: Time -> Pattern String -> [(String, Pattern a)] -> [(String, Pattern a -> Pattern a)] -> Pattern a
ur' t outer_p ps fs = _slow t $ unwrap $ adjust <$> timedValues (getPat . split <$> outer_p)
where split = wordsBy (==':')
getPat (s:xs) = (match s, transform xs)
-- TODO - check this really can't happen..
getPat _ = error "can't happen?"
match s = fromMaybe silence $ lookup s ps'
ps' = map (fmap (_fast t)) ps
adjust (a, (pat, f)) = rotR (start a) $ f a pat
transform (x:xs) a pat = transform xs a $ transform' x a pat
transform _ _ pat = pat
transform' str (Arc s e) p = inside (pure $ 1/(e-s)) (matchF str) p
matchF str = fromMaybe id $ lookup str fs
timedValues = withEvent (\(Event c (Just a) a' v) -> Event c (Just a) a' (a,v)) . filterDigital
Unfortunately it doesn't seem to work either. I get a bit more of predictability / consistency if throwing a reset 1 in the mix, but then it seems like the bassline starts at its second cycle, rather than at its begining.
The incriminated melodic sequence is something like :
I have a question related to patterning chords but did't know if this lesson is the right place post it (I can change it if not).
The point is I am trying to use ur to create a melody (here a simplified example):
let parts =
[
("a", n "c'maj" # s "superpiano"),
("b", n "a'maj" # s "superpiano"),
("c", n "f'maj" # s "superpiano")
]
in
d1 $ ur 3 "a b c" parts
but I'd like that Tidal started playing at the beginning. I tried with "trigger" and "qtrigger" functions but doesn't seem to work. (d1 $ trigger $ ur 3 "a b c" parts ). Is there an alternative?
Additionally, is there a way to play it just once? (if you use once instead of d1 it plays just "a".
let parts = [
("a", n "c'maj" # s "superpiano"),
("b", n "a'maj" # s "superpiano"),
("c", n "f'maj" # s "superpiano")
]
playFor c pat = seqP [(0, c, pat)]
urOnce c pat parts fs = playFor c $ ur c pat parts fs
in
d1 $ qtrigger 1 $ urOnce 3 "a b c" parts []
You have to say which 'channel' you're triggering with qtrigger. I had to define a new function urOnce to only play the pattern through once. One problem is that if you've just missed the start of a cycle, qtrigger will miss off the start of the pattern.. Hmm.
You can also use trigger instead of qtrigger but that won't align with anything else that's playing.
Please bare the sheer absence of musicality of that example, hopefully it'll successfully illustrate what I aim for : I'd love to find a way to have the whole block starting with superpiano's lowest C note, with the slowest / simplest rhythm (that is, mel1). Can't make it work each and every time.
do
let
pat1 = "t*4"
pat2 = "t([5 6],16,<0!! [0 2]>)"
mel = "<[<-7 0!3> ~] [1 3 5 7]>"
mel1 = struct pat1 $ n (toScale [0,1,3,5,7,8,10] mel) # s "superpiano" # amp 0.333
mel2 = struct pat2 $ n (toScale [0,1,3,5,7,8,10] mel) # s "superpiano" # amp 0.333
poomtchack = stack [struct "t(3,8)" $ s "808bd" , struct "[ft]*2" $ s "808sd"] #amp 0.75
techno = stack [struct "t*4" $ s "808bd" , struct "[ft]!4" $ s "808hh"] #amp 0.75
d1 $
ur' 8 "a b"
[ ("a", poomtchack),
("b", techno)]
[]
d2 $
ur' 8 "1 2"
[ ("1", mel1),
("2", mel2)]
[]
Interesting function, but it's a bit hard to sequence multiple patterns at once isn't it?
I know you can do it using a comma, but things gets complicated, at least in my head. On first glance seqPLoop seems more easy for this.
I'm pretty new at digital music, but I assume people wants to build up tunes by layering patterns and turn them off/solo. So for making tracks it's an important function, which I'll explore further.
When I run the code from this lesson I get the following error. I had a look around the forum and it looks like either a Tidal package error or a Cabal error? In Atom everything seems up to date so I'm guessing it's the later?
Thanks in advance!
t>
β’ Variable not in scope: dt :: Double -> Pattern ControlMap
β’ Perhaps you meant one of these:
βd1β (line 43), βqtβ (imported from Sound.Tidal.Context),
βdetβ (imported from Sound.Tidal.Context)
Variable not in scope: dfb :: Double -> Pattern ControlMap
Ah, yes if I recall he mentioned that it was a shortcut being added to newer versions of tidal (you may be running an older ver). You can also use delayt and delayfb I believe