Open jwaldmann opened 4 years ago
Have you looked at timecat
, seqPLoop
and ur
?
I did now.
timeCat
speeds up argument patterns individually, which I don't want. (I find it impossible to undo this later.)
ur
is hard to discover (the name tells nothing, implementation has no haddock).
The example in https://tidalcycles.org/index.php/ur uses ".. play four cycles each" so I assume the timing is uniform (too uniform for my use case).
seqPLoop
comes close but it's not what I want:
flip queryArc (Arc 0 4) $ seqPLoop [(0,1,s "<a1 a2>"),(1,3,s "b")]
[[((2,1),(4,1))](0>1)|s: "a1",
[((1,1),(2,1))](1>2)|s: "b",
[((1,1),(2,1))](2>3)|s: "b",
[((2,1),(4,1))](3>4)|s: "a1"] -- this should be "a2"
My implementation above wasn't doing this correctly, it should really be
tcat dps = Pattern q
where (total, segs) = make_segments dps
q st = concatMap (f st) $ arcCyclesZW (arc st) -- still don't know why exactly
f st a = query (withResultTime (+offset) p)
$ st {arc = Arc (start a - offset) (stop a - offset)}
where t = start a
(cyc,f) = properFraction $ t / total
:: (Int,Time)
local_t = f * total
(arc ,p) = find_segment segs local_t
dur = stop arc - start arc
offset = start arc
+ (total - dur) * fromIntegral cyc -- must substract duration of segment
Ah, I thought ur
would mean something like 'higher' in German, so thought it would make sense as a short name for a function that patterned patterns. It's always felt like a work-in-progress, but it's been around a long time now so does need properly documenting really!
So your implementation is like seqPLoop, but it doesn't play the patterns from cycle 0 each time?
Fractions cause trouble:
d1 $ tcat [(0.5, sound "bd sn"),
(0.25, sound "<arpy arpy:1 arpy:2>")
]
Here's a version built around compress
which seems to cope with that:
tcat :: [(Time, Pattern a)] -> Pattern a
tcat pats = _slow s $ stack $ zoomin 0 pats
where zoomin t [] = []
zoomin t (pat:pats) = (compress (t, t + (fst pat/s)) $ snd pat) : (zoomin (t + (fst pat/s)) pats)
s = sum $ map fst pats
Re: "like seqPLoop, but it doesn't play the patterns from cycle 0 each time?" - Yes.
Re: your implementation: that's much better, using compress
instead of manipulating queries explicitly. compress(Arc)
should be documented.
Re: ur
. I thought you meant this as an abbreviation that I couldn't figure out. As a word (prefix) in German, it means "primordial", e.g., "Ur-schrei" = "primal scream", "Ur-suppe" = "primordial soup" (in biology). Even "Ur-sache" (reaon) is literally "first thing". Yes, I would accept "Ur-combinator" (of patterns) as a name for a function that is, well, fundamental in the sense that you could implement all (or lots) others with it.
Examples for "ur-" in art and music: https://en.wikipedia.org/wiki/Kurt_Schwitters#Ursonate and
Ursatz (deep structure) in https://en.wikipedia.org/wiki/Schenkerian_analysis (also "Urlinie", fundamental line)
So, future haddock for ur
should start with In Schenkerian analysis, ...
- Not!
From discussion on club.tidalcycles.org, it seems with ur
too, sometimes people want inner patterns to restart from 0
for each outer event, and sometimes they don't.. just as with this tcat
vs timecat
.
What should these be called? They could be timecat
and timecat'
, but I don't really like doing that - I renamed a lot of 'primed' functions to be more descriptive in Tidal version 1.0.. There were a lot of them and it was hard to remember what they did.
Also it is feasible that someone would want one pattern-as-event to start at cycle 0, and another to align with the 'outer' cycle, in the same pattern. Is there a reasonable way of expressing this?
That's good to know on ur
, and I agree we should keep Schenker out of this!
One of the very first things I did was prototypical Tidal was model Kurt Schwitters Ursonate :) https://tidalcycles.org/index.php/History_of_Tidal The kurt
default samples might be familiar..
keep Schenker out ..
On the other hand, I am reading references given in https://en.wikipedia.org/wiki/Peter_Westergaard%27s_tonal_theory and it'd definitely be interesting to compare these operators (segmentation, anticipation, ...) with Tidal's.
Kurt
I had no idea! - I have very little knowledge of the superdirt samples. I'm looking forward to the results of https://github.com/tidalcycles/Dirt-Samples/issues/15#issuecomment-630147427 to get this organised.
Is your feature request related to a problem? Please describe.
I found it surprisingly hard to implement "play x cycles of pattern a, then y cycles of pattern b", in fact, impossible with abstract operators (that don't manipulate queries or arcs).
Describe the function/feature you'd like
I thought this variant of
(slow)cat
would help:proxy implementation below.
Describe alternatives you've considered
combinations of "surface" functions (fast, slow, sew) that don't manipulate queries
Additional context
I made this proof-of-concept implementation, starting from the code in
Sound.Tidal.Core.cat
. Note that we could thencat = tcat . zip (repeat 1)
.This seems to work for point-like events (play synth), probably doesn't work right for events with span (play sample).
It could be improved by more efficient lookup in
find_segment
(lookup table if timespans are nicely commensurable, balanced decision tree for the general case).There is no way to make timespans patternable in this approach.