tidalcycles / Tidal

Pattern language
http://tidalcycles.org/
GNU General Public License v3.0
2.26k stars 256 forks source link

Reconsidering sig #336

Closed yaxu closed 6 years ago

yaxu commented 6 years ago

I'm thinking that sig and therefore sine etc should always return an event with a 'whole' that starts at something like -1, i.e signals should have no onsets on the timeline. Then saw + "1 2" (or "1 2" + saw) would be the same as "1 2.5". However, then I'm not sure what the 'end' of the whole should be..

yaxu commented 6 years ago

In the currently released tidal the whole and the part timespans are always the same as the query timespan. This is usually fine as you don't normally take structure from continuous patterns. Now the default might be to take structure from both sides, this will become more of a problem.

yaxu commented 6 years ago

One option could be to wrap the 'whole' into a Maybe, to represent continuous events which don't have a start or end:

data Pattern = Pattern {query :: (Span -> [((Maybe Span, Span), a)])}

yaxu commented 6 years ago

Looks OK so far, haven't actually tried anything with continuous patterns yet though!

yaxu commented 6 years ago

Hm I think this solution isn't working out. You really need to know whether a pattern is discrete or continuous not before you query it, so you know whether you're looking to match a range or a point.. So probably back to having different type constructors..

yaxu commented 6 years ago

Instead I'm trying putting a flag on Pattern to indicate whether it should be treated as continuous or discrete. I'm using Analog and Digital because they're shorter..

type Time = Rational
type Arc = (Time, Time)
type Part = (Arc, Arc)
type Event a = (Part, a)
type Query a = (Arc -> [Event a])
type Nature = Analog | Digital
data Pattern a = Pattern {nature :: Nature, query :: Query a}

<*> then looks something like this (untested):

  pf <*> px | isDigital pf && isDigital px = Pattern Digital q
                where q arc = catMaybes $ concat $ map match $ query pf arc
                        where
                          match ((fWhole, fPart), f) =
                            map
                            (\((xWhole, xPart),x) ->
                              do part' <- subArc fPart xPart
                                 whole' <- subArc xWhole' fWhole
                                 return ((whole', part'), f x)
                            )
                      (query px fPart)
            | isDigital pf && isAnalog px = Pattern Digital q
                where q arc = concatMap match $ query pf arc
                        where
                          match ((fWhole, fPart), f) =
                            map
                              (\(_ ,x) -> ((fWhole, fPart), f x))
                              (query px (fst fPart, fst fPart)
            | isAnalog pf && isDigital px = Pattern Digital q
                where q arc = concatMap match $ query px arc
                        where
                          match ((xWhole, xPart), x) =
                            map
                              (\(_ ,f) -> ((xWhole, xPart), f x))
                              (query pf (fst xPart, fst xPart)
            | otherwise = Pattern Analog q
                where q arc = concatMap match $ query pf arc
                        where
                          match (_, f) =
                            map
                              (\(_ ,x) -> (arc, f x))
                              (query px arc)
yaxu commented 6 years ago

I've got this approach passing tests now..