From aeebac3f15971648a2ad3979f705db48e0a342f2 Mon Sep 17 00:00:00 2001 From: alex Date: Wed, 10 Apr 2024 12:04:14 +0100 Subject: [PATCH] rename step to steppify and steps to steppifies. Add new 'steps' that adjusts pattern to fit the given tactus --- src/Sound/Tidal/Core.hs | 8 ++++++++ src/Sound/Tidal/Pattern.hs | 17 ++++++++++++++--- src/Sound/Tidal/UI.hs | 22 +++++++++++----------- 3 files changed, 33 insertions(+), 14 deletions(-) diff --git a/src/Sound/Tidal/Core.hs b/src/Sound/Tidal/Core.hs index 420266b2..95195fe7 100644 --- a/src/Sound/Tidal/Core.hs +++ b/src/Sound/Tidal/Core.hs @@ -449,6 +449,14 @@ _stepsub r pat@(Pattern _ (Just t) _) | r >= t = nothing stepsub :: Pattern Rational -> Pattern a -> Pattern a stepsub = tParam _stepsub +_steplastof :: Int -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a +_steplastof i f pat | i <= 1 = pat + | otherwise = stepcat $ (take (i-1) $ repeat pat) ++ [f pat] + +steplastof :: Pattern Int -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a +steplastof (Pattern _ _ (Just i)) f pat = _steplastof i f pat +steplastof tp f p = innerJoin $ (\t -> _steplastof t f p) <$> tp + -- ** Manipulating time -- | Shifts a pattern back in time by the given amount, expressed in cycles diff --git a/src/Sound/Tidal/Pattern.hs b/src/Sound/Tidal/Pattern.hs index 81723c3a..96815106 100644 --- a/src/Sound/Tidal/Pattern.hs +++ b/src/Sound/Tidal/Pattern.hs @@ -68,9 +68,20 @@ setTactus r p = p {tactus = Just r} withTactus :: (Rational -> Rational) -> Pattern a -> Pattern a withTactus f p = p {tactus = f <$> tactus p} +_steps :: Rational -> Pattern a -> Pattern a +_steps target p@(Pattern _ (Just t) _) = setTactus target $ _fast (target / t) p +-- raise error? +_steps _ p = p + +steps :: Pattern Rational -> Pattern a -> Pattern a +steps = tParam _steps + keepMeta :: Pattern a -> Pattern a -> Pattern a keepMeta from to = to {tactus = tactus from, pureValue = pureValue from} +keepTactus :: Pattern a -> Pattern a -> Pattern a +keepTactus from to = to {tactus = tactus from} + -- type StateMap = Map.Map String (Pattern Value) type ControlPattern = Pattern ValueMap @@ -538,7 +549,7 @@ second half: > d1 $ fast "2 4" $ sound "bd sn kurt cp" -} fast :: Pattern Time -> Pattern a -> Pattern a -fast = tParam _fast +fast t pat = keepTactus pat $ tParam _fast t pat {-| @fastSqueeze@ speeds up a pattern by a time pattern given as input, squeezing the resulting pattern inside one cycle and playing the original @@ -582,7 +593,7 @@ density = fast _fast :: Time -> Pattern a -> Pattern a _fast rate pat | rate == 0 = silence | rate < 0 = rev $ _fast (negate rate) pat - | otherwise = withResultTime (/ rate) $ withQueryTime (* rate) pat + | otherwise = keepTactus pat $ withResultTime (/ rate) $ withQueryTime (* rate) pat {-| Slow down a pattern by the given time pattern. @@ -655,7 +666,7 @@ rotR t = rotL (negate t) -} rev :: Pattern a -> Pattern a rev p = - splitQueries $ p { + keepMeta p $ splitQueries $ p { query = \st -> map makeWholeAbsolute $ mapParts (mirrorArc (midCycle $ arc st)) $ map makeWholeRelative diff --git a/src/Sound/Tidal/UI.hs b/src/Sound/Tidal/UI.hs index 4ea4e08f..3661d83f 100644 --- a/src/Sound/Tidal/UI.hs +++ b/src/Sound/Tidal/UI.hs @@ -2414,29 +2414,29 @@ offadd :: Num a => Pattern Time -> Pattern a -> Pattern a -> Pattern a offadd tp pn p = off tp (+pn) p {- | - @step@ acts as a kind of simple step-sequencer using strings. For example, - @step "sn" "x x 12"@ is equivalent to the pattern of strings given by @"sn ~ - sn ~ sn:1 sn:2 ~"@. @step@ substitutes the given string for each @x@, for each number + @steppify@ acts as a kind of simple step-sequencer using strings. For example, + @steppify "sn" "x x 12"@ is equivalent to the pattern of strings given by @"sn ~ + sn ~ sn:1 sn:2 ~"@. @steppify@ substitutes the given string for each @x@, for each number it substitutes the string followed by a colon and the number, and for everything else it puts in a rest. - In other words, @step@ generates a pattern of strings in exactly the syntax you’d want for selecting samples and that can be fed directly into the 's' function. + In other words, @steppify@ generates a pattern of strings in exactly the syntax you’d want for selecting samples and that can be fed directly into the 's' function. - > d1 $ s (step "sn" "x x 12 ") + > d1 $ s (steppify "sn" "x x 12 ") -} -step :: String -> String -> Pattern String -step s cs = fastcat $ map f cs +steppify :: String -> String -> Pattern String +steppify s cs = fastcat $ map f cs where f c | c == 'x' = pure s | isDigit c = pure $ s ++ ":" ++ [c] | otherwise = silence -{- | @steps@ is like @step@ but it takes a list of pairs, like step would, and +{- | @stepifies@ is like @steppify@ but it takes a list of pairs, like steppify would, and it plays them all simultaneously. - > d1 $ s (steps [("cp","x x x x x x"),("bd", "xxxx")]) + > d1 $ s (stepifies [("cp","x x x x x x"),("bd", "xxxx")]) -} -steps :: [(String, String)] -> Pattern String -steps = stack . map (uncurry step) +stepifies :: [(String, String)] -> Pattern String +stepifies = stack . map (uncurry steppify) {- | like `step`, but allows you to specify an array of strings to use for @0,1,2...@ For example,