|
19 | 19 |
|
20 | 20 | module Sound.Tidal.Stepwise where
|
21 | 21 |
|
22 |
| -import Data.List (transpose) |
23 |
| -import Data.Maybe (fromMaybe) |
| 22 | +import Data.Containers.ListUtils (nubOrd) |
| 23 | +import Data.List (sort, transpose) |
| 24 | +import Data.Maybe (catMaybes, fromMaybe, isJust) |
24 | 25 |
|
25 | 26 | import Sound.Tidal.Core
|
26 | 27 | import Sound.Tidal.Pattern
|
27 |
| -import Sound.Tidal.UI (while) |
28 |
| -import Sound.Tidal.Utils (applyWhen) |
| 28 | +import Sound.Tidal.UI (while) |
| 29 | +import Sound.Tidal.Utils (applyWhen, pairs) |
| 30 | + |
| 31 | +_lcmtactus :: [Pattern a] -> Maybe Time |
| 32 | +_lcmtactus pats = foldl1 lcmr <$> (sequence $ map tactus pats) |
29 | 33 |
|
30 | 34 | s_cat :: [Pattern a] -> Pattern a
|
31 | 35 | s_cat pats = timecat $ map (\pat -> (fromMaybe 1 $ tactus pat, pat)) pats
|
@@ -111,3 +115,24 @@ s_expand = patternify _s_expand
|
111 | 115 |
|
112 | 116 | s_contract :: Pattern Rational -> Pattern a -> Pattern a
|
113 | 117 | s_contract = patternify _s_contract
|
| 118 | + |
| 119 | +stepJoin :: Pattern (Pattern a) -> Pattern a |
| 120 | +stepJoin pp = Pattern q Nothing Nothing |
| 121 | + where q st@(State a c) = query (timecat $ retime $ slices $ query (rotL (sam $ start a) pp) (st {arc = Arc 0 1})) st |
| 122 | + retime :: [(Time, Pattern a)] -> [(Time, Pattern a)] |
| 123 | + retime xs = map (\(dur, pat) -> adjust dur pat) xs |
| 124 | + where occupied_perc = sum $ map fst $ filter (isJust . tactus . snd) xs |
| 125 | + occupied_tactus = sum $ catMaybes $ map (tactus . snd) xs |
| 126 | + total_tactus = occupied_tactus / occupied_perc |
| 127 | + adjust dur pat@(Pattern {tactus = Just t}) = (t, pat) |
| 128 | + adjust dur pat = (dur*total_tactus, pat) |
| 129 | + -- break up events at all start/end points, into groups, including empty ones. |
| 130 | + slices :: [Event (Pattern a)] -> [(Time, Pattern a)] |
| 131 | + slices evs = map (\s -> ((snd s - fst s), stack $ map value $ fit s evs)) $ pairs $ sort $ nubOrd $ 0:1:concatMap (\ev -> start (part ev):stop (part ev):[]) evs |
| 132 | + -- list of slices of events within the given range |
| 133 | + fit :: (Rational, Rational) -> [Event (Pattern a)] -> [Event (Pattern a)] |
| 134 | + fit (b,e) evs = catMaybes $ map (match (b,e)) evs |
| 135 | + -- slice of event within the given range |
| 136 | + match :: (Rational, Rational) -> Event (Pattern a) -> Maybe (Event (Pattern a)) |
| 137 | + match (b,e) ev = do a <- subArc (Arc b e) $ part ev |
| 138 | + return ev {part = a} |
0 commit comments