{-# LANGUAGE TypeSynonymInstances, FlexibleInstances, BangPatterns #-}
module Sound.Tidal.Core where
import Prelude hiding ((<*), (*>))
import Data.Fixed (mod')
import qualified Data.Map.Strict as Map
import Sound.Tidal.Pattern
silence :: Pattern a
silence = empty
sig :: (Time -> a) -> Pattern a
sig f = Pattern q
where q (State (Arc s e) _)
| s > e = []
| otherwise = [Event Nothing (Arc s e) (f (s+((e-s)/2)))]
sine :: Fractional a => Pattern a
sine = sig $ \t -> (sin_rat ((pi :: Double) * 2 * fromRational t) + 1) / 2
where sin_rat = fromRational . toRational . sin
cosine :: Fractional a => Pattern a
cosine = 0.25 `rotR` sine
saw :: (Fractional a, Real a) => Pattern a
saw = sig $ \t -> mod' (fromRational t) 1
isaw :: (Fractional a, Real a) => Pattern a
isaw = (1-) <$> saw
tri :: (Fractional a, Real a) => Pattern a
tri = fastAppend saw isaw
square :: (Fractional a) => Pattern a
square = sig $
\t -> fromIntegral ((floor $ mod' (fromRational t :: Double) 1 * 2) :: Integer)
envL :: Pattern Double
envL = sig $ \t -> max 0 $ min (fromRational t) 1
envLR :: Pattern Double
envLR = (1-) <$> envL
envEq :: Pattern Double
envEq = sig $ \t -> sqrt (sin (pi/2 * max 0 (min (fromRational (1-t)) 1)))
envEqR :: Pattern Double
envEqR = sig $ \t -> sqrt (cos (pi/2 * max 0 (min (fromRational (1-t)) 1)))
class Unionable a where
union :: a -> a -> a
instance Unionable a where
union = const
instance {-# OVERLAPPING #-} Unionable ControlMap where
union = Map.union
(|+|) :: (Applicative a, Num b) => a b -> a b -> a b
a |+| b = (+) <$> a <*> b
(|+ ) :: Num a => Pattern a -> Pattern a -> Pattern a
a |+ b = (+) <$> a <* b
( +|) :: Num a => Pattern a -> Pattern a -> Pattern a
a +| b = (+) <$> a *> b
(|++|) :: Applicative a => a String -> a String -> a String
a |++| b = (++) <$> a <*> b
(|++ ) :: Pattern String -> Pattern String -> Pattern String
a |++ b = (++) <$> a <* b
( ++|) :: Pattern String -> Pattern String -> Pattern String
a ++| b = (++) <$> a *> b
(|/|) :: (Applicative a, Fractional b) => a b -> a b -> a b
a |/| b = (/) <$> a <*> b
(|/ ) :: Fractional a => Pattern a -> Pattern a -> Pattern a
a |/ b = (/) <$> a <* b
( /|) :: Fractional a => Pattern a -> Pattern a -> Pattern a
a /| b = (/) <$> a *> b
(|*|) :: (Applicative a, Num b) => a b -> a b -> a b
a |*| b = (*) <$> a <*> b
(|* ) :: Num a => Pattern a -> Pattern a -> Pattern a
a |* b = (*) <$> a <* b
( *|) :: Num a => Pattern a -> Pattern a -> Pattern a
a *| b = (*) <$> a *> b
(|-|) :: (Applicative a, Num b) => a b -> a b -> a b
a |-| b = (-) <$> a <*> b
(|- ) :: Num a => Pattern a -> Pattern a -> Pattern a
a |- b = (-) <$> a <* b
( -|) :: Num a => Pattern a -> Pattern a -> Pattern a
a -| b = (-) <$> a *> b
(|%|) :: (Applicative a, Real b) => a b -> a b -> a b
a |%| b = mod' <$> a <*> b
(|% ) :: Real a => Pattern a -> Pattern a -> Pattern a
a |% b = mod' <$> a <* b
( %|) :: Real a => Pattern a -> Pattern a -> Pattern a
a %| b = mod' <$> a *> b
(|**|) :: (Applicative a, Floating b) => a b -> a b -> a b
a |**| b = (**) <$> a <*> b
(|** ) :: Floating a => Pattern a -> Pattern a -> Pattern a
a |** b = (**) <$> a <* b
( **|) :: Floating a => Pattern a -> Pattern a -> Pattern a
a **| b = (**) <$> a *> b
(|>|) :: (Applicative a, Unionable b) => a b -> a b -> a b
a |>| b = flip union <$> a <*> b
(|> ) :: Unionable a => Pattern a -> Pattern a -> Pattern a
a |> b = flip union <$> a <* b
( >|) :: Unionable a => Pattern a -> Pattern a -> Pattern a
a >| b = flip union <$> a *> b
(|<|) :: (Applicative a, Unionable b) => a b -> a b -> a b
a |<| b = union <$> a <*> b
(|< ) :: Unionable a => Pattern a -> Pattern a -> Pattern a
a |< b = union <$> a <* b
( <|) :: Unionable a => Pattern a -> Pattern a -> Pattern a
a <| b = union <$> a *> b
(#) :: Unionable b => Pattern b -> Pattern b -> Pattern b
(#) = (|>)
fromList :: [a] -> Pattern a
fromList = cat . map pure
fastFromList :: [a] -> Pattern a
fastFromList = fastcat . map pure
listToPat :: [a] -> Pattern a
listToPat = fastFromList
fromMaybes :: [Maybe a] -> Pattern a
fromMaybes = fastcat . map f
where f Nothing = silence
f (Just x) = pure x
run :: (Enum a, Num a) => Pattern a -> Pattern a
run = (>>= _run)
_run :: (Enum a, Num a) => a -> Pattern a
_run n = fastFromList [0 .. n-1]
scan :: (Enum a, Num a) => Pattern a -> Pattern a
scan = (>>= _scan)
_scan :: (Enum a, Num a) => a -> Pattern a
_scan n = slowcat $ map _run [1 .. n]
append :: Pattern a -> Pattern a -> Pattern a
append a b = cat [a,b]
cat :: [Pattern a] -> Pattern a
cat [] = silence
cat ps = Pattern $ q
where n = length ps
q st = concatMap (f st) $ arcCyclesZW (arc st)
f st a = query (withResultTime (+offset) p) $ st {arc = Arc (subtract offset (start a)) (subtract offset (stop a))}
where p = ps !! i
cyc = (floor $ start a) :: Int
i = cyc `mod` n
offset = (fromIntegral $ cyc - ((cyc - i) `div` n)) :: Time
slowCat :: [Pattern a] -> Pattern a
slowCat = cat
slowcat :: [Pattern a] -> Pattern a
slowcat = slowCat
slowAppend :: Pattern a -> Pattern a -> Pattern a
slowAppend = append
slowappend :: Pattern a -> Pattern a -> Pattern a
slowappend = append
fastAppend :: Pattern a -> Pattern a -> Pattern a
fastAppend a b = _fast 2 $ append a b
fastappend :: Pattern a -> Pattern a -> Pattern a
fastappend = fastAppend
fastCat :: [Pattern a] -> Pattern a
fastCat ps = _fast (toTime $ length ps) $ cat ps
fastcat :: [Pattern a] -> Pattern a
fastcat = fastCat
timeCat :: [(Time, Pattern a)] -> Pattern a
timeCat tps = stack $ map (\(s,e,p) -> compressArc (Arc (s/total) (e/total)) p) $ arrange 0 tps
where total = sum $ map fst tps
arrange :: Time -> [(Time, Pattern a)] -> [(Time, Time, Pattern a)]
arrange _ [] = []
arrange t ((t',p):tps') = (t,t+t',p) : arrange (t+t') tps'
overlay :: Pattern a -> Pattern a -> Pattern a
overlay !p !p' = Pattern $ \st -> query p st ++ query p' st
(<>) :: Pattern a -> Pattern a -> Pattern a
(<>) = overlay
stack :: [Pattern a] -> Pattern a
stack = foldr overlay silence
(<~) :: Pattern Time -> Pattern a -> Pattern a
(<~) = tParam rotL
(~>) :: Pattern Time -> Pattern a -> Pattern a
(~>) = tParam rotR
fast :: Pattern Time -> Pattern a -> Pattern a
fast = tParam _fast
fastSqueeze :: Pattern Time -> Pattern a -> Pattern a
fastSqueeze = tParamSqueeze _fast
density :: Pattern Time -> Pattern a -> Pattern a
density = fast
_fast :: Time -> Pattern a -> Pattern a
_fast r p | r == 0 = silence
| r < 0 = rev $ _fast (negate r) p
| otherwise = withResultTime (/ r) $ withQueryTime (* r) p
slow :: Pattern Time -> Pattern a -> Pattern a
slow = tParam _slow
_slow :: Time -> Pattern a -> Pattern a
_slow 0 _ = silence
_slow r p = _fast (1/r) p
slowSqueeze :: Pattern Time -> Pattern a -> Pattern a
slowSqueeze = tParamSqueeze _slow
sparsity :: Pattern Time -> Pattern a -> Pattern a
sparsity = slow
rev :: Pattern a -> Pattern a
rev p =
splitQueries $ p {
query = \st -> map makeWholeAbsolute $
mapParts (mirrorArc (midCycle $ arc st)) $
map makeWholeRelative
(query p st
{arc = mirrorArc (midCycle $ arc st) (arc st)
})
}
where makeWholeRelative :: Event a -> Event a
makeWholeRelative (e@(Event Nothing _ _)) = e
makeWholeRelative (Event (Just (Arc s e)) p'@(Arc s' e') v) =
Event (Just $ Arc (s'-s) (e-e')) p' v
makeWholeAbsolute :: Event a -> Event a
makeWholeAbsolute (e@(Event Nothing _ _)) = e
makeWholeAbsolute (Event (Just (Arc s e)) p'@(Arc s' e') v) =
Event (Just $ Arc (s'-e) (e'+s)) p' v
midCycle :: Arc -> Time
midCycle (Arc s _) = sam s + 0.5
mapParts :: (Arc -> Arc) -> [Event a] -> [Event a]
mapParts f es = (\(Event w p' v) -> Event w (f p') v) <$> es
mirrorArc :: Time -> Arc -> Arc
mirrorArc mid' (Arc s e) = Arc (mid' - (e-mid')) (mid'+(mid'-s))
zoom :: (Time, Time) -> Pattern a -> Pattern a
zoom (s,e) = zoomArc (Arc s e)
zoomArc :: Arc -> Pattern a -> Pattern a
zoomArc (Arc s e) p = splitQueries $
withResultArc (mapCycle ((/d) . subtract s)) $ withQueryArc (mapCycle ((+s) . (*d))) p
where d = e-s
fastGap :: Pattern Time -> Pattern a -> Pattern a
fastGap = tParam _fastGap
densityGap :: Pattern Time -> Pattern a -> Pattern a
densityGap = fastGap
compress :: (Time,Time) -> Pattern a -> Pattern a
compress (s,e) = compressArc (Arc s e)
compressTo :: (Time,Time) -> Pattern a -> Pattern a
compressTo (s,e) = compressArcTo (Arc s e)
repeatCycles :: Int -> Pattern a -> Pattern a
repeatCycles n p = cat (replicate n p)
fastRepeatCycles :: Int -> Pattern a -> Pattern a
fastRepeatCycles n p = cat (replicate n p)
every :: Pattern Int -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
every tp f p = innerJoin $ (\t -> _every t f p) <$> tp
_every :: Int -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
_every 0 _ p = p
_every n f p = when ((== 0) . (`mod` n)) f p
every' :: Pattern Int -> Pattern Int -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
every' np op f p = do { n <- np; o <- op; _every' n o f p }
_every' :: Int -> Int -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
_every' n o = when ((== o) . (`mod` n))
foldEvery :: [Int] -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
foldEvery ns f p = foldr (`_every` f) p ns
when :: (Int -> Bool) -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
when test f p = splitQueries $ p {query = apply}
where apply st | test (floor $ start $ arc st) = query (f p) st
| otherwise = query p st
whenT :: (Time -> Bool) -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
whenT test f p = splitQueries $ p {query = apply}
where apply st | test (start $ arc st) = query (f p) st
| otherwise = query p st