module Sound.Tidal.Pattern where
import Control.Applicative
import Data.Monoid
import Data.Fixed
import Data.List
import Data.Maybe
import Data.Ord
import Data.Ratio
import Data.Typeable
import Data.Function
import System.Random.Mersenne.Pure64
import qualified Data.Text as T
import Sound.Tidal.Time
import Sound.Tidal.Utils
import Sound.Tidal.Bjorklund
import Text.Show.Functions ()
import qualified Control.Exception as E
data Pattern a = Pattern {arc :: Arc -> [Event a]}
deriving Typeable
noOv :: String -> a
noOv meth = error $ meth ++ ": No overloading"
instance Eq (Pattern a) where
(==) = noOv "(==)"
instance Ord a => Ord (Pattern a) where
min = liftA2 min
max = liftA2 max
instance Num a => Num (Pattern a) where
negate = fmap negate
(+) = liftA2 (+)
(*) = liftA2 (*)
fromInteger = pure . fromInteger
abs = fmap abs
signum = fmap signum
instance Enum a => Enum (Pattern a) where
succ = fmap succ
pred = fmap pred
toEnum = pure . toEnum
fromEnum = noOv "fromEnum"
enumFrom = noOv "enumFrom"
enumFromThen = noOv "enumFromThen"
enumFromTo = noOv "enumFromTo"
enumFromThenTo = noOv "enumFromThenTo"
instance (Num a, Ord a) => Real (Pattern a) where
toRational = noOv "toRational"
instance (Integral a) => Integral (Pattern a) where
quot = liftA2 quot
rem = liftA2 rem
div = liftA2 div
mod = liftA2 mod
toInteger = noOv "toInteger"
x `quotRem` y = (x `quot` y, x `rem` y)
x `divMod` y = (x `div` y, x `mod` y)
instance (Fractional a) => Fractional (Pattern a) where
recip = fmap recip
fromRational = pure . fromRational
instance (Floating a) => Floating (Pattern a) where
pi = pure pi
sqrt = fmap sqrt
exp = fmap exp
log = fmap log
sin = fmap sin
cos = fmap cos
asin = fmap asin
atan = fmap atan
acos = fmap acos
sinh = fmap sinh
cosh = fmap cosh
asinh = fmap asinh
atanh = fmap atanh
acosh = fmap acosh
instance (RealFrac a) => RealFrac (Pattern a) where
properFraction = noOv "properFraction"
truncate = noOv "truncate"
round = noOv "round"
ceiling = noOv "ceiling"
floor = noOv "floor"
instance (RealFloat a) => RealFloat (Pattern a) where
floatRadix = noOv "floatRadix"
floatDigits = noOv "floatDigits"
floatRange = noOv "floatRange"
decodeFloat = noOv "decodeFloat"
encodeFloat = ((.).(.)) pure encodeFloat
exponent = noOv "exponent"
significand = noOv "significand"
scaleFloat n = fmap (scaleFloat n)
isNaN = noOv "isNaN"
isInfinite = noOv "isInfinite"
isDenormalized = noOv "isDenormalized"
isNegativeZero = noOv "isNegativeZero"
isIEEE = noOv "isIEEE"
atan2 = liftA2 atan2
instance (Show a) => Show (Pattern a) where
show p@(Pattern _) = intercalate " " $ map showEvent $ arc p (0, 1)
showTime :: (Show a, Integral a) => Ratio a -> String
showTime t | denominator t == 1 = show (numerator t)
| otherwise = show (numerator t) ++ ('/':show (denominator t))
showArc :: Arc -> String
showArc a = concat[showTime $ fst a, (' ':showTime (snd a))]
showEvent :: (Show a) => Event a -> String
showEvent e@(_, b, v) = concat[on, show v, off,
(' ':showArc b),
"\n"
]
where on | hasOnset e = ""
| otherwise = ".."
off | hasOffset e = ""
| otherwise = ".."
instance Functor Pattern where
fmap f (Pattern a) = Pattern $ fmap (fmap (mapThd' f)) a
instance Applicative Pattern where
pure x = Pattern $ \(s, e) -> map
(\t -> ((t%1, (t+1)%1),
(t%1, (t+1)%1),
x
)
)
[floor s .. ((ceiling e) 1)]
(Pattern fs) <*> (Pattern xs) =
Pattern $ \a -> concatMap applyX (fs a)
where applyX ((s,e), (s', e'), f) =
map (\(_, _, x) -> ((s,e), (s', e'), f x))
(filter
(\(_, a', _) -> isIn a' s)
(xs (s',e'))
)
instance Monoid (Pattern a) where
mempty = silence
mappend = overlay
instance Monad Pattern where
return = pure
p >>= f = unwrap (f <$> p)
unwrap :: Pattern (Pattern a) -> Pattern a
unwrap p = Pattern $ \a -> concatMap (\(_, outerPart, p') -> catMaybes $ map (munge outerPart) $ arc p' a) (arc p a)
where munge a (whole,part,v) = do part' <- subArc a part
return (whole, part',v)
atom :: a -> Pattern a
atom = pure
silence :: Pattern a
silence = Pattern $ const []
withQueryArc :: (Arc -> Arc) -> Pattern a -> Pattern a
withQueryArc f p = Pattern $ \a -> arc p (f a)
withQueryTime :: (Time -> Time) -> Pattern a -> Pattern a
withQueryTime = withQueryArc . mapArc
withResultArc :: (Arc -> Arc) -> Pattern a -> Pattern a
withResultArc f p = Pattern $ \a -> mapArcs f $ arc p a
withResultTime :: (Time -> Time) -> Pattern a -> Pattern a
withResultTime = withResultArc . mapArc
withEvent :: (Event a -> Event b) -> Pattern a -> Pattern b
withEvent f p = Pattern $ \a -> map f $ arc p a
timedValues :: Pattern a -> Pattern (Arc, a)
timedValues = withEvent (\(a,a',v) -> (a,a',(a,v)))
overlay :: Pattern a -> Pattern a -> Pattern a
overlay p p' = Pattern $ \a -> (arc p a) ++ (arc p' a)
stack :: [Pattern a] -> Pattern a
stack ps = foldr overlay silence ps
append :: Pattern a -> Pattern a -> Pattern a
append a b = fastcat [a,b]
append' :: Pattern a -> Pattern a -> Pattern a
append' a b = slowcat [a,b]
fastcat :: [Pattern a] -> Pattern a
fastcat ps = _density (fromIntegral $ length ps) $ slowcat ps
splitAtSam :: Pattern a -> Pattern a
splitAtSam p =
splitQueries $ Pattern $ \(s,e) -> mapSnds' (trimArc (sam s)) $ arc p (s,e)
where trimArc s' (s,e) = (max (s') s, min (s'+1) e)
slowcat :: [Pattern a] -> Pattern a
slowcat [] = silence
slowcat ps = splitQueries $ Pattern f
where ps' = map splitAtSam ps
l = length ps'
f (s,e) = arc (withResultTime (+offset) p) (s',e')
where p = ps' !! n
r = (floor s) :: Int
n = (r `mod` l) :: Int
offset = (fromIntegral $ r ((r n) `div` l)) :: Time
(s', e') = (soffset, eoffset)
cat :: [Pattern a] -> Pattern a
cat = slowcat
listToPat :: [a] -> Pattern a
listToPat = fastcat . map atom
patToList :: Pattern a -> [a]
patToList p = map (thd') $ sortBy (\a b -> compare (snd' a) (snd' b)) $ filter ((\x -> x >= 0 && x < 1) . fst . snd' ) (arc p (0,1))
maybeListToPat :: [Maybe a] -> Pattern a
maybeListToPat = fastcat . map f
where f Nothing = silence
f (Just x) = atom x
run :: (Enum a, Num a) => Pattern a -> Pattern a
run tp = tp >>= _run
_run :: (Enum a, Num a) => a -> Pattern a
_run n = listToPat [0 .. n1]
scan :: (Enum a, Num a) => Pattern a -> Pattern a
scan tp = tp >>= _scan
_scan :: (Enum a, Num a) => a -> Pattern a
_scan n = slowcat $ map _run [1 .. n]
temporalParam :: (a -> Pattern b -> Pattern c) -> (Pattern a -> Pattern b -> Pattern c)
temporalParam f tv p = unwrap $ (\v -> f v p) <$> tv
temporalParam2 :: (a -> b -> Pattern c -> Pattern d) -> (Pattern a -> Pattern b -> Pattern c -> Pattern d)
temporalParam2 f a b p = unwrap $ (\x y -> f x y p) <$> a <*> b
temporalParam3 :: (a -> b -> c -> Pattern d -> Pattern e) -> (Pattern a -> Pattern b -> Pattern c -> Pattern d -> Pattern e)
temporalParam3 f a b c p = unwrap $ (\x y z -> f x y z p) <$> a <*> b <*> c
temporalParam' :: (a -> Pattern b -> Pattern c) -> (Pattern a -> Pattern b -> Pattern c)
temporalParam' f tv p = unwrap' $ (\v -> f v p) <$> tv
temporalParam2' :: (a -> b -> Pattern c -> Pattern d) -> (Pattern a -> Pattern b -> Pattern c -> Pattern d)
temporalParam2' f a b p = unwrap' $ (\x y -> f x y p) <$> a <*> b
temporalParam3' :: (a -> b -> c -> Pattern d -> Pattern e) -> (Pattern a -> Pattern b -> Pattern c -> Pattern d -> Pattern e)
temporalParam3' f a b c p = unwrap' $ (\x y z -> f x y z p) <$> a <*> b <*> c
fast :: Pattern Time -> Pattern a -> Pattern a
fast = temporalParam _density
_fast :: Time -> Pattern a -> Pattern a
_fast = _density
fast' :: Pattern Time -> Pattern a -> Pattern a
fast' = temporalParam' _density
density :: Pattern Time -> Pattern a -> Pattern a
density = fast
_density :: Time -> Pattern a -> Pattern a
_density r p | r == 0 = silence
| r < 0 = rev $ _density (0r) p
| otherwise = withResultTime (/ r) $ withQueryTime (* r) p
fastGap :: Time -> Pattern a -> Pattern a
fastGap 0 _ = silence
fastGap r p = splitQueries $ withResultArc (\(s,e) -> (sam s + ((s sam s)/r), (sam s + ((e sam s)/r)))) $ Pattern (\a -> arc p $ mapArc (\t -> sam t + (min 1 (r * cyclePos t))) a)
densityGap :: Time -> Pattern a -> Pattern a
densityGap = fastGap
slow :: Pattern Time -> Pattern a -> Pattern a
slow = temporalParam _slow
sparsity :: Pattern Time -> Pattern a -> Pattern a
sparsity = slow
slow' :: Pattern Time -> Pattern a -> Pattern a
slow' = temporalParam' _slow
_slow :: Time -> Pattern a -> Pattern a
_slow t p = _density (1/t) p
rotL :: Time -> Pattern a -> Pattern a
rotL t p = withResultTime (subtract t) $ withQueryTime (+ t) p
(<~) :: Pattern Time -> Pattern a -> Pattern a
(<~) = temporalParam rotL
rotR :: Time -> Pattern a -> Pattern a
rotR = (rotL) . (0)
(~>) :: Pattern Time -> Pattern a -> Pattern a
(~>) = temporalParam rotR
brak :: Pattern a -> Pattern a
brak = when ((== 1) . (`mod` 2)) (((1%4) `rotR`) . (\x -> fastcat [x, silence]))
iter :: Pattern Int -> Pattern c -> Pattern c
iter = temporalParam _iter
_iter :: Int -> Pattern a -> Pattern a
_iter n p = slowcat $ map (\i -> ((fromIntegral i)%(fromIntegral n)) `rotL` p) [0 .. (n1)]
iter' :: Pattern Int -> Pattern c -> Pattern c
iter' = temporalParam _iter'
_iter' :: Int -> Pattern a -> Pattern a
_iter' n p = slowcat $ map (\i -> ((fromIntegral i)%(fromIntegral n)) `rotR` p) [0 .. (n1)]
rev :: Pattern a -> Pattern a
rev p = splitQueries $ Pattern $ \a -> map makeWholeAbsolute $ mapSnds' (mirrorArc (mid a)) $ map makeWholeRelative (arc p (mirrorArc (mid a) a))
where makeWholeRelative ((s,e), part@(s',e'), v) = ((s's, ee'), part, v)
makeWholeAbsolute ((s,e), part@(s',e'), v) = ((s'e,e'+s), part, v)
mid (s,e) = (sam s) + 0.5
palindrome :: Pattern a -> Pattern a
palindrome p = append' p (rev p)
when :: (Int -> Bool) -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
when test f p = splitQueries $ Pattern apply
where apply a | test (floor $ fst a) = (arc $ f p) a
| otherwise = (arc p) a
whenT :: (Time -> Bool) -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
whenT test f p = splitQueries $ Pattern apply
where apply a | test (fst a) = (arc $ f p) a
| otherwise = (arc p) a
playWhen :: (Time -> Bool) -> Pattern a -> Pattern a
playWhen test (Pattern f) = Pattern $ (filter (\e -> test (eventOnset e))) . f
playFor :: Time -> Time -> Pattern a -> Pattern a
playFor s e = playWhen (\t -> and [t >= s, t < e])
seqP :: [(Time, Time, Pattern a)] -> Pattern a
seqP ps = stack $ map (\(s, e, p) -> playFor s e ((sam s) `rotR` p)) ps
every :: Pattern Int -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
every tp f p = tp >>= \t -> _every t f p
_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 f = when ((== o) . (`mod` n)) f
foldEvery :: [Int] -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
foldEvery ns f p = foldr ($) p (map (\x -> _every x f) ns)
sig :: (Time -> a) -> Pattern a
sig f = Pattern f'
where f' (s,e) | s > e = []
| otherwise = [((s,e), (s,e), f s)]
sinewave :: Pattern Double
sinewave = sig $ \t -> ((sin $ pi * 2 * (fromRational t)) + 1) / 2
sine :: Pattern Double
sine = sinewave
cosine :: Pattern Double
cosine = 0.25 ~> sine
sinerat :: Pattern Rational
sinerat = fmap toRational sine
ratsine :: Pattern Rational
ratsine = sinerat
sineAmp :: Double -> Pattern Double
sineAmp offset = (+ offset) <$> sinewave1
sawwave :: Pattern Double
sawwave = sig $ \t -> mod' (fromRational t) 1
saw :: Pattern Double
saw = sawwave
sawrat :: Pattern Rational
sawrat = fmap toRational saw
triwave :: Pattern Double
triwave = append sawwave1 (rev sawwave1)
tri :: Pattern Double
tri = triwave
trirat :: Pattern Rational
trirat = fmap toRational tri
squarewave :: Pattern Double
squarewave = sig $
\t -> fromIntegral $ ((floor $ (mod' (fromRational t :: Double) 1) * 2) :: Integer)
square :: Pattern Double
square = squarewave
sinewave1 :: Pattern Double
sinewave1 = sinewave
sine1 :: Pattern Double
sine1 = sinewave
sinerat1 :: Pattern Rational
sinerat1 = sinerat
sineAmp1 :: Double -> Pattern Double
sineAmp1 = sineAmp
sawwave1 :: Pattern Double
sawwave1 = sawwave
saw1 :: Pattern Double
saw1 = sawwave
sawrat1 :: Pattern Rational
sawrat1 = sawrat
triwave1 :: Pattern Double
triwave1 = triwave
tri1 :: Pattern Double
tri1 = triwave
trirat1 :: Pattern Rational
trirat1 = trirat
squarewave1 :: Pattern Double
squarewave1 = squarewave
square1 :: Pattern Double
square1 = square
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 (1t)) 1)))
envEqR :: Pattern Double
envEqR = sig $ \t -> sqrt (cos (pi/2 * (max 0 $ min (fromRational (1t)) 1)))
fadeOut :: Time -> Pattern a -> Pattern a
fadeOut n = spread' (_degradeBy) (_slow n $ envL)
fadeOut' :: Time -> Time -> Pattern a -> Pattern a
fadeOut' from dur p = spread' (_degradeBy) (from `rotR` _slow dur envL) p
fadeIn' :: Time -> Time -> Pattern a -> Pattern a
fadeIn' from dur p = spread' (\n p -> 1 `rotL` _degradeBy n p) (from `rotR` _slow dur ((1) <$> envL)) p
fadeIn :: Time -> Pattern a -> Pattern a
fadeIn n = spread' (_degradeBy) (_slow n $ (1) <$> envL)
spread :: (a -> t -> Pattern b) -> [a] -> t -> Pattern b
spread f xs p = slowcat $ map (\x -> f x p) xs
slowspread :: (a -> t -> Pattern b) -> [a] -> t -> Pattern b
slowspread = spread
fastspread :: (a -> t -> Pattern b) -> [a] -> t -> Pattern b
fastspread f xs p = fastcat $ map (\x -> f x p) xs
spread' :: Monad m => (a -> b -> m c) -> m a -> b -> m c
spread' f vpat pat = vpat >>= \v -> f v pat
spreadChoose :: (t -> t1 -> Pattern b) -> [t] -> t1 -> Pattern b
spreadChoose f vs p = do v <- discretise 1 (choose vs)
f v p
spreadr :: (t -> t1 -> Pattern b) -> [t] -> t1 -> Pattern b
spreadr = spreadChoose
filterValues :: (a -> Bool) -> Pattern a -> Pattern a
filterValues f (Pattern x) = Pattern $ (filter (f . thd')) . x
filterJust :: Pattern (Maybe a) -> Pattern a
filterJust p = fromJust <$> (filterValues (isJust) p)
filterOnsets :: Pattern a -> Pattern a
filterOnsets (Pattern f) =
Pattern $ (filter (\e -> eventOnset e >= eventStart e)) . f
filterStartInRange :: Pattern a -> Pattern a
filterStartInRange (Pattern f) =
Pattern $ \(s,e) -> filter ((isIn (s,e)) . eventOnset) $ f (s,e)
filterOnsetsInRange :: Pattern a -> Pattern a
filterOnsetsInRange = filterOnsets . filterStartInRange
seqToRelOnsetDeltas :: Arc -> Pattern a -> [(Double, Double, a)]
seqToRelOnsetDeltas (s, e) p = map (\((s', e'), _, x) -> (fromRational $ (s's) / (es), fromRational $ (e's) / (es), x)) $ arc (filterOnsetsInRange p) (s, e)
segment :: Pattern a -> Pattern [a]
segment p = Pattern $ \(s,e) -> filter (\(_,(s',e'),_) -> s' < e && e' > s) $ groupByTime (segment' (arc p (s,e)))
segment' :: [Event a] -> [Event a]
segment' es = foldr split es pts
where pts = nub $ points es
split :: Time -> [Event a] -> [Event a]
split _ [] = []
split t ((ev@(a,(s,e), v)):es) | t > s && t < e = (a,(s,t),v):(a,(t,e),v):(split t es)
| otherwise = ev:split t es
points :: [Event a] -> [Time]
points [] = []
points ((_,(s,e), _):es) = s:e:(points es)
groupByTime :: [Event a] -> [Event [a]]
groupByTime es = map mrg $ groupBy ((==) `on` snd') $ sortBy (compare `on` snd') es
where mrg es@((a, a', _):_) = (a, a', map thd' es)
mrg _ = error "groupByTime"
ifp :: (Int -> Bool) -> (Pattern a -> Pattern a) -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
ifp test f1 f2 p = splitQueries $ Pattern apply
where apply a | test (floor $ fst a) = (arc $ f1 p) a
| otherwise = (arc $ f2 p) a
rand :: Pattern Double
rand = Pattern $ \a -> [(a, a, timeToRand $ (midPoint a))]
timeToRand :: RealFrac r => r -> Double
timeToRand t = fst $ randomDouble $ pureMT $ floor $ (*1000000) t
irand :: Num a => Int -> Pattern a
irand i = (fromIntegral . (floor :: Double -> Int) . (* (fromIntegral i))) <$> rand
choose :: [a] -> Pattern a
choose [] = E.throw (E.ErrorCall "Empty list. Nothing to choose from.")
choose xs = (xs !!) <$> (irand $ length xs)
degradeBy :: Pattern Double -> Pattern a -> Pattern a
degradeBy = temporalParam _degradeBy
_degradeBy :: Double -> Pattern a -> Pattern a
_degradeBy x p = fmap fst $ filterValues ((> x) . snd) $ (,) <$> p <*> rand
unDegradeBy :: Pattern Double -> Pattern a -> Pattern a
unDegradeBy = temporalParam _unDegradeBy
_unDegradeBy :: Double -> Pattern a -> Pattern a
_unDegradeBy x p = fmap fst $ filterValues ((<= x) . snd) $ (,) <$> p <*> rand
degradeOverBy :: Int -> Pattern Double -> Pattern a -> Pattern a
degradeOverBy i tx p = unwrap $ (\x -> (fmap fst $ filterValues ((> x) . snd) $ (,) <$> p <*> repeatCycles i rand)) <$> (slow (fromIntegral i) tx)
sometimesBy :: Double -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
sometimesBy x f p = overlay (_degradeBy x p) (f $ _unDegradeBy x p)
sometimes :: (Pattern a -> Pattern a) -> Pattern a -> Pattern a
sometimes = sometimesBy 0.5
often :: (Pattern a -> Pattern a) -> Pattern a -> Pattern a
often = sometimesBy 0.75
rarely :: (Pattern a -> Pattern a) -> Pattern a -> Pattern a
rarely = sometimesBy 0.25
almostNever :: (Pattern a -> Pattern a) -> Pattern a -> Pattern a
almostNever = sometimesBy 0.1
almostAlways :: (Pattern a -> Pattern a) -> Pattern a -> Pattern a
almostAlways = sometimesBy 0.9
never :: (Pattern a -> Pattern a) -> Pattern a -> Pattern a
never = flip const
always :: (Pattern a -> Pattern a) -> Pattern a -> Pattern a
always = id
someCyclesBy :: Double -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
someCyclesBy x = when (test x)
where test x c = (timeToRand (fromIntegral c :: Double)) < x
somecyclesBy :: Double -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
somecyclesBy = someCyclesBy
someCycles :: (Pattern a -> Pattern a) -> Pattern a -> Pattern a
someCycles = someCyclesBy 0.5
degrade :: Pattern a -> Pattern a
degrade = _degradeBy 0.5
wedge :: Time -> Pattern a -> Pattern a -> Pattern a
wedge t p p' = overlay (densityGap (1/t) p) (t `rotR` densityGap (1/(1t)) p')
timeCat :: [(Time, Pattern a)] -> Pattern a
timeCat tps = stack $ map (\(s,e,p) -> compress (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)
whenmod :: Int -> Int -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
whenmod a b = Sound.Tidal.Pattern.when ((\t -> (t `mod` a) >= b ))
superimpose :: (Pattern a -> Pattern a) -> Pattern a -> Pattern a
superimpose f p = stack [p, f p]
splitQueries :: Pattern a -> Pattern a
splitQueries p = Pattern $ \a -> concatMap (arc p) $ arcCycles a
trunc :: Pattern Time -> Pattern a -> Pattern a
trunc = temporalParam _trunc
_trunc :: Time -> Pattern a -> Pattern a
_trunc t = compress (0,t) . zoom (0,t)
linger :: Pattern Time -> Pattern a -> Pattern a
linger = temporalParam _linger
_linger :: Time -> Pattern a -> Pattern a
_linger n p = _density (1/n) $ zoom (0,n) p
zoom :: Arc -> Pattern a -> Pattern a
zoom (s,e) p = splitQueries $ withResultArc (mapCycle ((/d) . (subtract s))) $ withQueryArc (mapCycle ((+s) . (*d))) p
where d = es
compress :: Arc -> Pattern a -> Pattern a
compress (s,e) p | s >= e = silence
| otherwise = s `rotR` densityGap (1/(es)) p
sliceArc :: Arc -> Pattern a -> Pattern a
sliceArc a@(s,e) p | s >= e = silence
| otherwise = compress a $ zoom a p
within :: Arc -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
within (s,e) f p = stack [playWhen (\t -> cyclePos t >= s && cyclePos t < e) $ f p,
playWhen (\t -> not $ cyclePos t >= s && cyclePos t < e) $ p
]
revArc :: Arc -> Pattern a -> Pattern a
revArc a = within a rev
e :: Int -> Int -> Pattern a -> Pattern a
e n k p = (flip const) <$> (filterValues (== True) $ listToPat $ bjorklund (n,k)) <*> p
e' :: Int -> Int -> Pattern a -> Pattern a
e' n k p = fastcat $ map (\x -> if x then p else silence) (bjorklund (n,k))
index :: Real b => b -> Pattern b -> Pattern c -> Pattern c
index sz indexpat pat = spread' (zoom' $ toRational sz) (toRational . (*(1sz)) <$> indexpat) pat
where zoom' sz start = zoom (start, start+sz)
prrw :: (a -> b -> c) -> Int -> (Time, Time) -> Pattern a -> Pattern b -> Pattern c
prrw f rot (blen, vlen) beatPattern valuePattern =
let
ecompare (_,e1,_) (_,e2,_) = compare (fst e1) (fst e2)
beats = sortBy ecompare $ arc beatPattern (0, blen)
values = fmap thd' . sortBy ecompare $ arc valuePattern (0, vlen)
cycles = blen * (fromIntegral $ lcm (length beats) (length values) `div` (length beats))
in
_slow cycles $ stack $ zipWith
(\( _, (start, end), v') v -> (start `rotR`) $ densityGap (1 / (end start)) $ pure (f v' v))
(sortBy ecompare $ arc (_density cycles $ beatPattern) (0, blen))
(drop (rot `mod` length values) $ cycle values)
prr :: Int -> (Time, Time) -> Pattern String -> Pattern b -> Pattern b
prr = prrw $ flip const
preplace :: (Time, Time) -> Pattern String -> Pattern b -> Pattern b
preplace = preplaceWith $ flip const
prep :: (Time, Time) -> Pattern String -> Pattern b -> Pattern b
prep = preplace
preplace1 :: Pattern String -> Pattern b -> Pattern b
preplace1 = preplace (1, 1)
preplaceWith :: (a -> b -> c) -> (Time, Time) -> Pattern a -> Pattern b -> Pattern c
preplaceWith f (blen, plen) = prrw f 0 (blen, plen)
prw :: (a -> b -> c) -> (Time, Time) -> Pattern a -> Pattern b -> Pattern c
prw = preplaceWith
preplaceWith1 :: (a -> b -> c) -> Pattern a -> Pattern b -> Pattern c
preplaceWith1 f = prrw f 0 (1, 1)
prw1 :: (a -> b -> c) -> Pattern a -> Pattern b -> Pattern c
prw1 = preplaceWith1
(<~>) :: Pattern String -> Pattern b -> Pattern b
(<~>) = preplace (1, 1)
protate :: Time -> Int -> Pattern a -> Pattern a
protate len rot p = prrw (flip const) rot (len, len) p p
prot :: Time -> Int -> Pattern a -> Pattern a
prot = protate
prot1 :: Int -> Pattern a -> Pattern a
prot1 = protate 1
(<<~) :: Int -> Pattern a -> Pattern a
(<<~) = protate 1
(~>>) :: Int -> Pattern a -> Pattern a
(~>>) = (<<~) . (0)
pequal :: Ord a => Time -> Pattern a -> Pattern a -> Bool
pequal cycles p1 p2 = (sort $ arc p1 (0, cycles)) == (sort $ arc p2 (0, cycles))
discretise :: Time -> Pattern a -> Pattern a
discretise n p = (_density n $ atom (id)) <*> p
discretise' = discretise
_discretise = discretise
randcat :: [Pattern a] -> Pattern a
randcat ps = spread' (rotL) (discretise 1 $ ((%1) . fromIntegral) <$> (irand (length ps) :: Pattern Int)) (slowcat ps)
fit :: Int -> [a] -> Pattern Int -> Pattern a
fit perCycle xs p = (xs !!!) <$> (Pattern $ \a -> map ((\e -> (mapThd' (+ (cyclePos perCycle e)) e))) (arc p a))
where cyclePos perCycle e = perCycle * (floor $ eventStart e)
permstep :: RealFrac b => Int -> [a] -> Pattern b -> Pattern a
permstep steps things p = unwrap $ (\n -> listToPat $ concatMap (\x -> replicate (fst x) (snd x)) $ zip (ps !! (floor (n * (fromIntegral $ (length ps 1))))) things) <$> (discretise 1 p)
where ps = permsort (length things) steps
deviance avg xs = sum $ map (abs . (avg) . fromIntegral) xs
permsort n total = map fst $ sortBy (comparing snd) $ map (\x -> (x,deviance (fromIntegral total / (fromIntegral n :: Double)) x)) $ perms n total
perms 0 _ = []
perms 1 n = [[n]]
perms n total = concatMap (\x -> map (x:) $ perms (n1) (totalx)) [1 .. (total(n1))]
struct :: Pattern String -> Pattern a -> Pattern a
struct ps pv = (flip const) <$> ps <*> pv
substruct :: Pattern String -> Pattern b -> Pattern b
substruct s p = Pattern $ f
where f a = concatMap (\a' -> arc (compressTo a' p) a') $ (map fst' $ arc s a)
compressTo :: Arc -> Pattern a -> Pattern a
compressTo (s,e) p = compress (cyclePos s, e(sam s)) p
randArcs :: Int -> Pattern [Arc]
randArcs n =
do rs <- mapM (\x -> (pure $ (toRational x)/(toRational n)) <~ choose [1,2,3]) [0 .. (n1)]
let rats = map toRational rs
total = sum rats
pairs = pairUp $ accumulate $ map ((/total)) rats
return $ pairs
where pairUp [] = []
pairUp xs = (0,head xs):(pairUp' xs)
pairUp' [] = []
pairUp' (a:[]) = []
pairUp' (a:b:[]) = [(a,1)]
pairUp' (a:b:xs) = (a,b):(pairUp' (b:xs))
randStruct n = splitQueries $ Pattern f
where f (s,e) = mapSnds' fromJust $ filter (\(_,x,_) -> isJust x) $ as
where as = map (\(n, (s',e')) -> ((s' + sam s, e' + sam s),
subArc (s,e) (s' + sam s, e' + sam s),
n
)
) $ enumerate $ thd' $ head $ arc (randArcs n) (sam s, nextSam s)
substruct' :: Pattern Int -> Pattern a -> Pattern a
substruct' s p = Pattern $ \a -> concatMap (\(a', _, i) -> arc (compressTo a' (inside (pure $ 1/toRational(length (arc s (sam (fst a), nextSam (fst a))))) (rotR (toRational i)) p)) a') (arc s a)
stripe :: Pattern Int -> Pattern a -> Pattern a
stripe = temporalParam _stripe
_stripe :: Int -> Pattern a -> Pattern a
_stripe = substruct' . randStruct
slowstripe :: Pattern Int -> Pattern a -> Pattern a
slowstripe n = slow (toRational <$> n) . stripe n
parseLMRule :: String -> [(String,String)]
parseLMRule s = map (splitOn ':') (commaSplit s)
where splitOn sep str = splitAt (fromJust $ elemIndex sep str)
$ filter (/= sep) str
commaSplit s = map T.unpack $ T.splitOn (T.pack ",") $ T.pack s
parseLMRule' :: String -> [(Char, String)]
parseLMRule' str = map fixer $ parseLMRule str
where fixer (c,r) = (head c, r)
lindenmayer :: Int -> String -> String -> String
lindenmayer _ _ [] = []
lindenmayer 1 r (c:cs) = (fromMaybe [c] $ lookup c $ parseLMRule' r)
++ (lindenmayer 1 r cs)
lindenmayer n r s = iterate (lindenmayer 1 r) s !! n
unwrap' :: Pattern (Pattern a) -> Pattern a
unwrap' pp = Pattern $ \a -> arc (stack $ map scalep (arc pp a)) a
where scalep ev = compress (fst' ev) $ thd' ev
mask :: Pattern a -> Pattern b -> Pattern b
mask pa pb = Pattern $ \a -> concat [filterOns (subArc a $ eventArc i) (arc pb a) | i <- arc pa a]
where filterOns Nothing _ = []
filterOns (Just arc) es = filter (onsetIn arc) es
enclosingArc :: [Arc] -> Arc
enclosingArc [] = (0,1)
enclosingArc as = (minimum (map fst as), maximum (map snd as))
stretch :: Pattern a -> Pattern a
stretch p = splitQueries $ Pattern $ \a@(s,_e) -> arc
(zoom (enclosingArc $ map eventArc $ arc p (sam s,nextSam s)) p)
a
fit' :: Pattern Time -> Int -> Pattern Int -> Pattern Int -> Pattern a -> Pattern a
fit' cyc n from to p = unwrap' $ fit n (mapMasks n from' p') to
where mapMasks n from p = [stretch $ mask (filterValues (== i) from) p
| i <- [0..n1]]
p' = density cyc $ p
from' = density cyc $ from
chunk :: Integer -> (Pattern b -> Pattern b) -> Pattern b -> Pattern b
chunk n f p = cat [within (i%(fromIntegral n),(i+1)%(fromIntegral n)) f p | i <- [0..n1]]
runWith :: Integer -> (Pattern b -> Pattern b) -> Pattern b -> Pattern b
runWith = chunk
chunk' :: Integral a => a -> (Pattern b -> Pattern b) -> Pattern b -> Pattern b
chunk' n f p = do i <- _slow (toRational n) $ rev $ run (fromIntegral n)
within (i%(fromIntegral n),(i+)1%(fromIntegral n)) f p
runWith' :: Integral a => a -> (Pattern b -> Pattern b) -> Pattern b -> Pattern b
runWith' = chunk'
inside :: Pattern Time -> (Pattern a1 -> Pattern a) -> Pattern a1 -> Pattern a
inside n f p = density n $ f (slow n p)
outside :: Pattern Time -> (Pattern a1 -> Pattern a) -> Pattern a1 -> Pattern a
outside n = inside (1/n)
loopFirst :: Pattern a -> Pattern a
loopFirst p = splitQueries $ Pattern f
where f a@(s,_) = mapSnds' plus $ mapFsts' plus $ arc p (minus a)
where minus = mapArc (subtract (sam s))
plus = mapArc (+ (sam s))
timeLoop :: Pattern Time -> Pattern a -> Pattern a
timeLoop n = outside n loopFirst
seqPLoop :: [(Time, Time, Pattern a)] -> Pattern a
seqPLoop ps = timeLoop (pure $ maxT minT) $ minT `rotL` seqP ps
where minT = minimum $ map fst' ps
maxT = maximum $ map snd' ps
toScale' :: Int -> [Int] -> Pattern Int -> Pattern Int
toScale' o s = fmap noteInScale
where octave x = x `div` length s
noteInScale x = (s !!! x) + o * octave x
toScale :: [Int] -> Pattern Int -> Pattern Int
toScale = toScale' 12
swingBy :: Pattern Time -> Pattern Time -> Pattern a -> Pattern a
swingBy x n = inside n (within (0.5,1) (x ~>))
swing :: Pattern Time -> Pattern a -> Pattern a
swing = swingBy (pure $ 1%3)
cycleChoose::[a] -> Pattern a
cycleChoose xs = Pattern $ \(s,e) -> [((s,e),(s,e), xs!!(floor $ (dlen xs)*(ctrand s) ))]
where dlen xs = fromIntegral $ length xs
ctrand s = (timeToRand :: Time -> Double) $ fromIntegral $ (floor :: Time -> Int) $ sam s
shuffle::Int -> Pattern a -> Pattern a
shuffle n = fit' 1 n (_run n) (randpat n)
where randpat n = Pattern $ \(s,e) -> arc (p n $ sam s) (s,e)
p n c = listToPat $ map snd $ sort $ zip
[timeToRand (c+i/n') | i <- [0..n'1]] [0..n1]
n' :: Time
n' = fromIntegral n
scramble::Int -> Pattern a -> Pattern a
scramble n = fit' 1 n (_run n) (_density (fromIntegral n) $
liftA2 (+) (pure 0) $ irand n)
ur :: Time -> Pattern String -> [Pattern a] -> Pattern a
ur t outer_p ps = _slow t $ unwrap $ adjust <$> (timedValues $ (getPat . split) <$> outer_p)
where split s = wordsBy (==':') s
getPat (n:xs) = (ps' !!! read n, transform xs)
ps' = map (_density t) ps
adjust (a, (p, f)) = f a p
transform (x:_) a = transform' x a
transform _ _ = id
transform' "in" (s,e) p = twiddle (fadeIn) (s,e) p
transform' "out" (s,e) p = twiddle (fadeOut) (s,e) p
transform' _ _ p = p
twiddle f (s,e) p = s `rotR` (f (es) p)
ur' :: Time -> Pattern String -> [(String, Pattern a)] -> [(String, Pattern a -> Pattern a)] -> Pattern a
ur' t outer_p ps fs = _slow t $ unwrap $ adjust <$> (timedValues $ (getPat . split) <$> outer_p)
where split s = wordsBy (==':') s
getPat (s:xs) = (match s, transform xs)
match s = fromMaybe silence $ lookup s ps'
ps' = map (fmap (_density t)) ps
adjust (a, (p, f)) = f a p
transform (x:_) a = transform' x a
transform _ _ = id
transform' str (s,e) p = s `rotR` (inside (pure $ 1/(es)) (matchF str) p)
matchF str = fromMaybe id $ lookup str fs
inhabit :: [(String, Pattern a)] -> Pattern String -> Pattern a
inhabit ps p = unwrap' $ (\s -> fromMaybe silence $ lookup s ps) <$> p
repeatCycles :: Int -> Pattern a -> Pattern a
repeatCycles n p = fastcat (replicate n p)
spaceOut :: [Time] -> Pattern a -> Pattern a
spaceOut xs p = _slow (toRational $ sum xs) $ stack $ map (\a -> compress a p) $ spaceArcs xs
where markOut :: Time -> [Time] -> [(Time, Time)]
markOut _ [] = []
markOut offset (x:xs) = (offset,offset+x):(markOut (offset+x) xs)
spaceArcs xs = map (\(a,b) -> (a/s,b/s)) $ markOut 0 xs
s = sum xs
flatpat :: Pattern [a] -> Pattern a
flatpat p = Pattern $ \a -> (concatMap (\(b,b',xs) -> map (\x -> (b,b',x)) xs) $ arc p a)
layer :: [a -> Pattern b] -> a -> Pattern b
layer fs p = stack $ map ($ p) fs
breakUp :: Pattern a -> Pattern a
breakUp p = Pattern $ \a -> munge $ arc p a
where munge es = concatMap spreadOut (groupBy (\a b -> fst' a == fst' b) es)
spreadOut xs = catMaybes $ map (\(n, x) -> shiftIt n (length xs) x) $ enumerate xs
shiftIt n d ((s,e), a', v) = do a'' <- subArc (newS, newE) a'
return ((newS, newE), a'', v)
where newS = s + (dur*(fromIntegral n))
newE = newS + dur
dur = (e s) / (fromIntegral d)
fill :: Pattern a -> Pattern a -> Pattern a
fill p' p = struct (splitQueries $ Pattern (f p)) p'
where
f p (s,e) = removeTolerance (s,e) $ invert (stolerance, e+tolerance) $ arc p (stolerance, e+tolerance)
invert (s,e) es = map arcToEvent $ foldr remove [(s,e)] (map snd' es)
remove (s,e) xs = concatMap (remove' (s, e)) xs
remove' (s,e) (s',e') | s > s' && e < e' = [(s',s),(e,e')]
| s > s' && s < e' = [(s',s)]
| e > s' && e < e' = [(e,e')]
| s <= s' && e >= e' = []
| otherwise = [(s',e')]
arcToEvent a = (a,a,"x")
removeTolerance (s,e) es = concatMap (expand) $ mapSnds' f es
where f (a) = concatMap (remove' (e,e+tolerance)) $ remove' (stolerance,s) a
expand (a,xs,c) = map (\x -> (a,x,c)) xs
tolerance = 0.01