Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

encloseEvent & query windowing functions #1093

Draft
wants to merge 3 commits into
base: dev
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions src/Sound/Tidal/Pattern.hs
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,16 @@
withPart :: (Arc -> Arc) -> Pattern a -> Pattern a
withPart f = withEvent (\(Event c w p v) -> Event c w (f p) v)

-- | @withEventsOnArc ef af p@ returns a new @Pattern@ with ef applied to the events list queried from the query arc modified by af, then enclosed into the original arc
-- function @f@
withEventsOnArc :: ([Event a] -> [Event a]) -> (Arc -> Arc) -> Pattern a -> Pattern a
withEventsOnArc ef af p = splitQueries $ p {query = \st -> mapMaybe (encloseEvent $ arc st) $ ef $ query p st { arc = af $ arc st}}

-- | @withEventOnArc ef af p@ returns a new @Pattern@ with ef applied to the each event queried from the query arc modified by af, then enclosed into the original arc
-- function @f@
withEventOnArc :: (Event a -> Event a) -> (Arc -> Arc) -> Pattern a -> Pattern a
withEventOnArc ef af p = withEventsOnArc (ef <$>) af p

_extract :: (Value -> Maybe a) -> String -> ControlPattern -> Pattern a
_extract f name pat = filterJust $ withValue (Map.lookup name >=> f) pat

Expand Down Expand Up @@ -902,6 +912,19 @@
eventHasOnset e | isAnalog e = False
| otherwise = start (fromJust $ whole e) == start (part e)

-- | Given any event, return it as if it was queried between the given arc
encloseEvent :: Arc -> Event a -> Maybe (Event a)
encloseEvent _ (Event _ Nothing _ _) = Nothing -- TODO how to handle analogs
encloseEvent a@(Arc as ae) ev@(Event ctx (Just w@(Arc ws we)) part val)

Check warning on line 918 in src/Sound/Tidal/Pattern.hs

View workflow job for this annotation

GitHub Actions / build (9.0.1, 3.4.0.0)

Defined but not used: ‘ctx’

Check warning on line 918 in src/Sound/Tidal/Pattern.hs

View workflow job for this annotation

GitHub Actions / build (9.0.1, 3.4.0.0)

This binding for ‘part’ shadows the existing binding

Check warning on line 918 in src/Sound/Tidal/Pattern.hs

View workflow job for this annotation

GitHub Actions / build (9.0.1, 3.4.0.0)

Defined but not used: ‘part’

Check warning on line 918 in src/Sound/Tidal/Pattern.hs

View workflow job for this annotation

GitHub Actions / build (9.0.1, 3.4.0.0)

Defined but not used: ‘val’

Check warning on line 918 in src/Sound/Tidal/Pattern.hs

View workflow job for this annotation

GitHub Actions / cabal latest - ghc latest

Defined but not used: ‘ctx’

Check warning on line 918 in src/Sound/Tidal/Pattern.hs

View workflow job for this annotation

GitHub Actions / cabal latest - ghc latest

This binding for ‘part’ shadows the existing binding

Check warning on line 918 in src/Sound/Tidal/Pattern.hs

View workflow job for this annotation

GitHub Actions / cabal latest - ghc latest

Defined but not used: ‘part’

Check warning on line 918 in src/Sound/Tidal/Pattern.hs

View workflow job for this annotation

GitHub Actions / cabal latest - ghc latest

Defined but not used: ‘val’

Check warning on line 918 in src/Sound/Tidal/Pattern.hs

View workflow job for this annotation

GitHub Actions / cabal 3.4.0.0 - ghc 8.10.1

Defined but not used: ‘ctx’

Check warning on line 918 in src/Sound/Tidal/Pattern.hs

View workflow job for this annotation

GitHub Actions / cabal 3.4.0.0 - ghc 8.10.1

This binding for ‘part’ shadows the existing binding

Check warning on line 918 in src/Sound/Tidal/Pattern.hs

View workflow job for this annotation

GitHub Actions / cabal 3.4.0.0 - ghc 8.10.1

Defined but not used: ‘part’

Check warning on line 918 in src/Sound/Tidal/Pattern.hs

View workflow job for this annotation

GitHub Actions / cabal 3.4.0.0 - ghc 8.10.1

Defined but not used: ‘val’

Check warning on line 918 in src/Sound/Tidal/Pattern.hs

View workflow job for this annotation

GitHub Actions / cabal 3.4.0.0 - ghc 8.8.3

Defined but not used: ‘ctx’

Check warning on line 918 in src/Sound/Tidal/Pattern.hs

View workflow job for this annotation

GitHub Actions / cabal 3.4.0.0 - ghc 8.8.3

This binding for ‘part’ shadows the existing binding

Check warning on line 918 in src/Sound/Tidal/Pattern.hs

View workflow job for this annotation

GitHub Actions / cabal 3.4.0.0 - ghc 8.8.3

Defined but not used: ‘part’

Check warning on line 918 in src/Sound/Tidal/Pattern.hs

View workflow job for this annotation

GitHub Actions / cabal 3.4.0.0 - ghc 8.8.3

Defined but not used: ‘val’

Check warning on line 918 in src/Sound/Tidal/Pattern.hs

View workflow job for this annotation

GitHub Actions / cabal 3.4.0.0 - ghc 9.0.1

Defined but not used: ‘ctx’

Check warning on line 918 in src/Sound/Tidal/Pattern.hs

View workflow job for this annotation

GitHub Actions / cabal 3.4.0.0 - ghc 9.0.1

This binding for ‘part’ shadows the existing binding

Check warning on line 918 in src/Sound/Tidal/Pattern.hs

View workflow job for this annotation

GitHub Actions / cabal 3.4.0.0 - ghc 9.0.1

Defined but not used: ‘part’

Check warning on line 918 in src/Sound/Tidal/Pattern.hs

View workflow job for this annotation

GitHub Actions / cabal 3.4.0.0 - ghc 9.0.1

Defined but not used: ‘val’

Check warning on line 918 in src/Sound/Tidal/Pattern.hs

View workflow job for this annotation

GitHub Actions / cabal 3.4.0.0 - ghc 8.6.5

Defined but not used: ‘ctx’

Check warning on line 918 in src/Sound/Tidal/Pattern.hs

View workflow job for this annotation

GitHub Actions / cabal 3.4.0.0 - ghc 8.6.5

This binding for ‘part’ shadows the existing binding

Check warning on line 918 in src/Sound/Tidal/Pattern.hs

View workflow job for this annotation

GitHub Actions / cabal 3.4.0.0 - ghc 8.6.5

Defined but not used: ‘part’

Check warning on line 918 in src/Sound/Tidal/Pattern.hs

View workflow job for this annotation

GitHub Actions / cabal 3.4.0.0 - ghc 8.6.5

Defined but not used: ‘val’

Check warning on line 918 in src/Sound/Tidal/Pattern.hs

View workflow job for this annotation

GitHub Actions / cabal 3.8.1.0 - ghc 9.4.1

Defined but not used: ‘ctx’

Check warning on line 918 in src/Sound/Tidal/Pattern.hs

View workflow job for this annotation

GitHub Actions / cabal 3.8.1.0 - ghc 9.4.1

Defined but not used: ‘part’

Check warning on line 918 in src/Sound/Tidal/Pattern.hs

View workflow job for this annotation

GitHub Actions / cabal 3.8.1.0 - ghc 9.4.1

This binding for ‘part’ shadows the existing binding

Check warning on line 918 in src/Sound/Tidal/Pattern.hs

View workflow job for this annotation

GitHub Actions / cabal 3.8.1.0 - ghc 9.4.1

Defined but not used: ‘val’

Check warning on line 918 in src/Sound/Tidal/Pattern.hs

View workflow job for this annotation

GitHub Actions / build (9.0.1, 3.4.0.0)

Defined but not used: ‘ctx’

Check warning on line 918 in src/Sound/Tidal/Pattern.hs

View workflow job for this annotation

GitHub Actions / build (9.0.1, 3.4.0.0)

This binding for ‘part’ shadows the existing binding

Check warning on line 918 in src/Sound/Tidal/Pattern.hs

View workflow job for this annotation

GitHub Actions / build (9.0.1, 3.4.0.0)

Defined but not used: ‘part’

Check warning on line 918 in src/Sound/Tidal/Pattern.hs

View workflow job for this annotation

GitHub Actions / build (9.0.1, 3.4.0.0)

Defined but not used: ‘val’
| we <= as || ws >= ae = Nothing -- outside
| ws >= as && we <= ae = Just ev -- fully within
| otherwise = Just ev { part = sect w a } -- intersects

-- | If an event ends before it starts, switch starts with ends
unflipEvent :: Event a -> Event a
unflipEvent ev@(Event _ (Just (Arc ws we)) (Arc ps pe) _) = if we >= ws then ev else ev { whole = (Just (Arc we ws)), part = (Arc pe ps) }
unflipEvent ev@(Event _ Nothing (Arc ps pe) _) = if pe >= ps then ev else ev { part = (Arc pe ps) }

-- TODO - Is this used anywhere? Just tests, it seems
-- TODO - support 'context' field
toEvent :: (((Time, Time), (Time, Time)), a) -> Event a
Expand Down
51 changes: 50 additions & 1 deletion src/Sound/Tidal/UI.hs
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,16 @@

import Prelude hiding ((*>), (<*))

import Control.Applicative (liftA2)

import Data.Bits (Bits, shiftL, shiftR, testBit, xor)
import Data.Char (digitToInt, isDigit, ord)

import Data.Bool (bool)
import Data.Fixed (mod')
import Data.List (elemIndex, findIndex, findIndices,
groupBy, intercalate, sort, sortOn,
transpose)
sortBy, transpose)
import qualified Data.Map.Strict as Map
import Data.Maybe (catMaybes, fromJust, fromMaybe, isJust,
mapMaybe)
Expand Down Expand Up @@ -2057,6 +2059,53 @@
tolerance = 0.01
-}

_quant :: Time -> Pattern a -> Pattern a
_quant 0 pat = pat
_quant k pat =
withEventOnArc (quantEvent k) (surround) pat
where
surround qa@(Arc qs qe) = Arc (qs - lookahead) (qe + lookahead)
lookahead = 1/k
quantEvent k ev = ev { whole = (fmap rounding <$> whole ev) }
rounding n = (roundNumerator n) % k'
roundNumerator n = (nn * k' + (nd `div` 2)) `div` nd
where nn = numerator n

Check failure on line 2072 in src/Sound/Tidal/UI.hs

View workflow job for this annotation

GitHub Actions / build (9.0.1, 3.4.0.0)

• Variable not in scope: numerator :: p -> t

Check failure on line 2072 in src/Sound/Tidal/UI.hs

View workflow job for this annotation

GitHub Actions / cabal latest - ghc latest

• Variable not in scope: numerator :: p -> t

Check failure on line 2072 in src/Sound/Tidal/UI.hs

View workflow job for this annotation

GitHub Actions / cabal 3.4.0.0 - ghc 8.10.1

• Variable not in scope: numerator :: p -> t

Check failure on line 2072 in src/Sound/Tidal/UI.hs

View workflow job for this annotation

GitHub Actions / cabal 3.4.0.0 - ghc 8.8.3

• Variable not in scope: numerator :: p -> t

Check failure on line 2072 in src/Sound/Tidal/UI.hs

View workflow job for this annotation

GitHub Actions / cabal 3.4.0.0 - ghc 9.0.1

• Variable not in scope: numerator :: p -> t

Check failure on line 2072 in src/Sound/Tidal/UI.hs

View workflow job for this annotation

GitHub Actions / cabal 3.4.0.0 - ghc 8.6.5

• Variable not in scope: numerator :: p -> t

Check failure on line 2072 in src/Sound/Tidal/UI.hs

View workflow job for this annotation

GitHub Actions / cabal 3.8.1.0 - ghc 9.4.1

Variable not in scope: numerator :: p -> t

Check failure on line 2072 in src/Sound/Tidal/UI.hs

View workflow job for this annotation

GitHub Actions / build (9.0.1, 3.4.0.0)

• Variable not in scope: numerator :: p -> t
nd = denominator n

Check failure on line 2073 in src/Sound/Tidal/UI.hs

View workflow job for this annotation

GitHub Actions / build (9.0.1, 3.4.0.0)

• Variable not in scope: denominator :: p -> t

Check failure on line 2073 in src/Sound/Tidal/UI.hs

View workflow job for this annotation

GitHub Actions / cabal latest - ghc latest

• Variable not in scope: denominator :: p -> t

Check failure on line 2073 in src/Sound/Tidal/UI.hs

View workflow job for this annotation

GitHub Actions / cabal 3.4.0.0 - ghc 8.10.1

• Variable not in scope: denominator :: p -> t

Check failure on line 2073 in src/Sound/Tidal/UI.hs

View workflow job for this annotation

GitHub Actions / cabal 3.4.0.0 - ghc 8.8.3

• Variable not in scope: denominator :: p -> t

Check failure on line 2073 in src/Sound/Tidal/UI.hs

View workflow job for this annotation

GitHub Actions / cabal 3.4.0.0 - ghc 9.0.1

• Variable not in scope: denominator :: p -> t

Check failure on line 2073 in src/Sound/Tidal/UI.hs

View workflow job for this annotation

GitHub Actions / cabal 3.4.0.0 - ghc 8.6.5

• Variable not in scope: denominator :: p -> t

Check failure on line 2073 in src/Sound/Tidal/UI.hs

View workflow job for this annotation

GitHub Actions / cabal 3.8.1.0 - ghc 9.4.1

Variable not in scope: denominator :: p -> t

Check failure on line 2073 in src/Sound/Tidal/UI.hs

View workflow job for this annotation

GitHub Actions / build (9.0.1, 3.4.0.0)

• Variable not in scope: denominator :: p -> t
k' = numerator k

Check failure on line 2074 in src/Sound/Tidal/UI.hs

View workflow job for this annotation

GitHub Actions / build (9.0.1, 3.4.0.0)

• Variable not in scope: numerator :: Time -> t

Check failure on line 2074 in src/Sound/Tidal/UI.hs

View workflow job for this annotation

GitHub Actions / cabal latest - ghc latest

• Variable not in scope: numerator :: Time -> t

Check failure on line 2074 in src/Sound/Tidal/UI.hs

View workflow job for this annotation

GitHub Actions / cabal 3.4.0.0 - ghc 8.10.1

• Variable not in scope: numerator :: Time -> t

Check failure on line 2074 in src/Sound/Tidal/UI.hs

View workflow job for this annotation

GitHub Actions / cabal 3.4.0.0 - ghc 8.8.3

• Variable not in scope: numerator :: Time -> t

Check failure on line 2074 in src/Sound/Tidal/UI.hs

View workflow job for this annotation

GitHub Actions / cabal 3.4.0.0 - ghc 9.0.1

• Variable not in scope: numerator :: Time -> t

Check failure on line 2074 in src/Sound/Tidal/UI.hs

View workflow job for this annotation

GitHub Actions / cabal 3.4.0.0 - ghc 8.6.5

• Variable not in scope: numerator :: Time -> t

Check failure on line 2074 in src/Sound/Tidal/UI.hs

View workflow job for this annotation

GitHub Actions / cabal 3.8.1.0 - ghc 9.4.1

Variable not in scope: numerator :: Time -> t

Check failure on line 2074 in src/Sound/Tidal/UI.hs

View workflow job for this annotation

GitHub Actions / build (9.0.1, 3.4.0.0)

• Variable not in scope: numerator :: Time -> t

quant :: Pattern Time -> Pattern a -> Pattern a
quant = patternify _quant

_fill :: Time -> Time -> Pattern a -> Pattern a
_fill l m pat =
withEventsOnArc (map multiplyEvent . updateEvents . sortEvents) (lookahead) pat
where lookahead a = a { start = (`subtract` l) $ start a, stop = (+l) $ stop a }
sortEvents = sortBy (\e0 e1 -> compare (start $ part e0) (start $ part e1))
updateEvents es = (zipWith updatePair es (drop 1 es)) ++ safeLast es
safeLast [] = []
safeLast es = [last es]
updatePair ev ev2 = ev { whole = (liftA2 updateArc (whole ev) (whole ev2)) }
updateArc (Arc s0 _) (Arc s1 _) = Arc s0 s1
multiplyEvent ev = ev { whole = multiplyDuration <$> whole ev }
multiplyDuration (Arc s e) = Arc s (s + ((e-s)*m))

fill :: Pattern Time -> Pattern a -> Pattern a
fill = patternify (_fill 1)

fill' :: Pattern Time -> Pattern Time -> Pattern a -> Pattern a
fill' = patternify2 _fill

alterT :: (Time -> Time) -> Pattern a -> Pattern a
alterT f pat =
withEventOnArc (unflipEvent . alterEvent) (timeToCycleArc . start) pat
where alterEvent ev = ev { whole = (fmap (mapCycle f) $ whole ev) }

alterF :: (Double -> Double) -> Pattern a -> Pattern a
alterF f pat =
withEventOnArc (unflipEvent . alterEvent) (timeToCycleArc . start) pat
where alterEvent ev = ev { whole = (fmap (mapCycle f') $ whole ev) }
f' = toRational . f . fromRational

{- | @ply n@ repeats each event @n@ times within its arc.

For example, the following are equivalent:
Expand Down
Loading