{-# LANGUAGE BangPatterns #-}

module Sound.Tidal.Transition where

import Control.Concurrent.MVar (readMVar, swapMVar)
import qualified Data.Map.Strict as Map
-- import Data.Maybe (fromJust)

import qualified Sound.Tidal.Clock as Clock
import Sound.Tidal.Config (toClockConfig)
import Sound.Tidal.Control (_stut)
import Sound.Tidal.Core
import Sound.Tidal.ID (ID (fromID))
import Sound.Tidal.Params (gain, pan)
import Sound.Tidal.Pattern
import Sound.Tidal.Stream.Types
  ( PlayState (PlayState, psHistory, psMute, psPattern, psSolo),
    Stream (sClockRef, sConfig, sPMapMV),
  )
-- import Sound.Tidal.Tempo as T
import Sound.Tidal.UI (fadeInFrom, fadeOutFrom)
import Sound.Tidal.Utils (enumerate)
import Prelude hiding ((*>), (<*))

{-
    Transition.hs - A library for handling transitions between patterns
    Copyright (C) 2020, Alex McLean and contributors

    This library is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this library.  If not, see <http://www.gnu.org/licenses/>.
-}

type TransitionMapper = Time -> [ControlPattern] -> ControlPattern

-- Evaluation of pat is forced so exceptions are picked up here, before replacing the existing pattern.
-- the "historyFlag" determines if the new pattern should be placed on the history stack or not
transition :: Stream -> Bool -> TransitionMapper -> ID -> ControlPattern -> IO ()
transition :: Stream -> Bool -> TransitionMapper -> ID -> ControlPattern -> IO ()
transition Stream
stream Bool
historyFlag TransitionMapper
mapper ID
patId !ControlPattern
pat = do
  let appendPat :: Bool -> [ControlPattern] -> [ControlPattern]
appendPat Bool
flag = if Bool
flag then (ControlPattern
pat ControlPattern -> [ControlPattern] -> [ControlPattern]
forall a. a -> [a] -> [a]
:) else [ControlPattern] -> [ControlPattern]
forall a. a -> a
id
      updatePS :: Maybe PlayState -> PlayState
updatePS (Just PlayState
playState) = PlayState
playState {psHistory = appendPat historyFlag (psHistory playState)}
      updatePS Maybe PlayState
Nothing =
        PlayState
          { psPattern :: ControlPattern
psPattern = ControlPattern
forall a. Pattern a
silence,
            psMute :: Bool
psMute = Bool
False,
            psSolo :: Bool
psSolo = Bool
False,
            psHistory :: [ControlPattern]
psHistory = Bool -> [ControlPattern] -> [ControlPattern]
appendPat Bool
historyFlag [ControlPattern
forall a. Pattern a
silence]
          }
      transition' :: [ControlPattern] -> IO ControlPattern
transition' [ControlPattern]
pat' = do
        Time
t <- ClockConfig -> ClockRef -> IO Time
Clock.getCycleTime (Config -> ClockConfig
toClockConfig (Config -> ClockConfig) -> Config -> ClockConfig
forall a b. (a -> b) -> a -> b
$ Stream -> Config
sConfig Stream
stream) (Stream -> ClockRef
sClockRef Stream
stream)
        ControlPattern -> IO ControlPattern
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (ControlPattern -> IO ControlPattern)
-> ControlPattern -> IO ControlPattern
forall a b. (a -> b) -> a -> b
$! TransitionMapper
mapper Time
t [ControlPattern]
pat'
  PlayMap
pMap <- MVar PlayMap -> IO PlayMap
forall a. MVar a -> IO a
readMVar (Stream -> MVar PlayMap
sPMapMV Stream
stream)
  let playState :: PlayState
playState = Maybe PlayState -> PlayState
updatePS (Maybe PlayState -> PlayState) -> Maybe PlayState -> PlayState
forall a b. (a -> b) -> a -> b
$ String -> PlayMap -> Maybe PlayState
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup (ID -> String
fromID ID
patId) PlayMap
pMap
  ControlPattern
pat' <- [ControlPattern] -> IO ControlPattern
transition' ([ControlPattern] -> IO ControlPattern)
-> [ControlPattern] -> IO ControlPattern
forall a b. (a -> b) -> a -> b
$ Bool -> [ControlPattern] -> [ControlPattern]
appendPat (Bool -> Bool
not Bool
historyFlag) (PlayState -> [ControlPattern]
psHistory PlayState
playState)
  let pMap' :: PlayMap
pMap' = String -> PlayState -> PlayMap -> PlayMap
forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert (ID -> String
fromID ID
patId) (PlayState
playState {psPattern = pat'}) PlayMap
pMap
  PlayMap
_ <- MVar PlayMap -> PlayMap -> IO PlayMap
forall a. MVar a -> a -> IO a
swapMVar (Stream -> MVar PlayMap
sPMapMV Stream
stream) PlayMap
pMap'
  () -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()

_mortalOverlay :: Time -> Time -> [Pattern a] -> Pattern a
_mortalOverlay :: forall a. Time -> Time -> [Pattern a] -> Pattern a
_mortalOverlay Time
_ Time
_ [] = Pattern a
forall a. Pattern a
silence
_mortalOverlay Time
t Time
now (Pattern a
pat : [Pattern a]
ps) = Pattern a -> Pattern a -> Pattern a
forall a. Pattern a -> Pattern a -> Pattern a
overlay ([Pattern a] -> Pattern a
forall {a}. [Pattern a] -> Pattern a
pop [Pattern a]
ps) (Time -> Time -> Pattern a -> Pattern a
forall a. Time -> Time -> Pattern a -> Pattern a
playFor Time
s (Time
s Time -> Time -> Time
forall a. Num a => a -> a -> a
+ Time
t) Pattern a
pat)
  where
    pop :: [Pattern a] -> Pattern a
pop [] = Pattern a
forall a. Pattern a
silence
    pop (Pattern a
x : [Pattern a]
_) = Pattern a
x
    s :: Time
s = Time -> Time
sam (Time
now Time -> Time -> Time
forall a. Num a => a -> a -> a
- Int -> Time
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Time -> Int
forall b. Integral b => Time -> b
forall a b. (RealFrac a, Integral b) => a -> b
floor Time
now Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Time -> Int
forall b. Integral b => Time -> b
forall a b. (RealFrac a, Integral b) => a -> b
floor Time
t :: Int)) Time -> Time -> Time
forall a. Num a => a -> a -> a
+ Time -> Time
sam Time
t

-- | Washes away the current pattern after a certain delay by applying a
--    function to it over time, then switching over to the next pattern to
--    which another function is applied.
_wash :: (Pattern a -> Pattern a) -> (Pattern a -> Pattern a) -> Time -> Time -> Time -> Time -> [Pattern a] -> Pattern a
_wash :: forall a.
(Pattern a -> Pattern a)
-> (Pattern a -> Pattern a)
-> Time
-> Time
-> Time
-> Time
-> [Pattern a]
-> Pattern a
_wash Pattern a -> Pattern a
_ Pattern a -> Pattern a
_ Time
_ Time
_ Time
_ Time
_ [] = Pattern a
forall a. Pattern a
silence
_wash Pattern a -> Pattern a
_ Pattern a -> Pattern a
_ Time
_ Time
_ Time
_ Time
_ [Pattern a
pat] = Pattern a
pat
_wash Pattern a -> Pattern a
fout Pattern a -> Pattern a
fin Time
delay Time
durin Time
durout Time
now (Pattern a
pat : Pattern a
pat' : [Pattern a]
_) =
  [Pattern a] -> Pattern a
forall {a}. [Pattern a] -> Pattern a
stack
    [ (Time -> Bool) -> Pattern a -> Pattern a
forall a. (Time -> Bool) -> Pattern a -> Pattern a
filterWhen (Time -> Time -> Bool
forall a. Ord a => a -> a -> Bool
< (Time
now Time -> Time -> Time
forall a. Num a => a -> a -> a
+ Time
delay)) Pattern a
pat',
      (Time -> Bool) -> Pattern a -> Pattern a
forall a. (Time -> Bool) -> Pattern a -> Pattern a
filterWhen (Time -> Time -> Time -> Bool
forall {a}. Ord a => a -> a -> a -> Bool
between (Time
now Time -> Time -> Time
forall a. Num a => a -> a -> a
+ Time
delay) (Time
now Time -> Time -> Time
forall a. Num a => a -> a -> a
+ Time
delay Time -> Time -> Time
forall a. Num a => a -> a -> a
+ Time
durin)) (Pattern a -> Pattern a) -> Pattern a -> Pattern a
forall a b. (a -> b) -> a -> b
$ Pattern a -> Pattern a
fout Pattern a
pat',
      (Time -> Bool) -> Pattern a -> Pattern a
forall a. (Time -> Bool) -> Pattern a -> Pattern a
filterWhen (Time -> Time -> Time -> Bool
forall {a}. Ord a => a -> a -> a -> Bool
between (Time
now Time -> Time -> Time
forall a. Num a => a -> a -> a
+ Time
delay Time -> Time -> Time
forall a. Num a => a -> a -> a
+ Time
durin) (Time
now Time -> Time -> Time
forall a. Num a => a -> a -> a
+ Time
delay Time -> Time -> Time
forall a. Num a => a -> a -> a
+ Time
durin Time -> Time -> Time
forall a. Num a => a -> a -> a
+ Time
durout)) (Pattern a -> Pattern a) -> Pattern a -> Pattern a
forall a b. (a -> b) -> a -> b
$ Pattern a -> Pattern a
fin Pattern a
pat,
      (Time -> Bool) -> Pattern a -> Pattern a
forall a. (Time -> Bool) -> Pattern a -> Pattern a
filterWhen (Time -> Time -> Bool
forall a. Ord a => a -> a -> Bool
>= (Time
now Time -> Time -> Time
forall a. Num a => a -> a -> a
+ Time
delay Time -> Time -> Time
forall a. Num a => a -> a -> a
+ Time
durin Time -> Time -> Time
forall a. Num a => a -> a -> a
+ Time
durout)) Pattern a
pat
    ]
  where
    between :: a -> a -> a -> Bool
between a
lo a
hi a
x = (a
x a -> a -> Bool
forall a. Ord a => a -> a -> Bool
>= a
lo) Bool -> Bool -> Bool
&& (a
x a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
hi)

_washIn :: (Pattern a -> Pattern a) -> Time -> Time -> [Pattern a] -> Pattern a
_washIn :: forall a.
(Pattern a -> Pattern a)
-> Time -> Time -> [Pattern a] -> Pattern a
_washIn Pattern a -> Pattern a
f Time
durin Time
now [Pattern a]
pats = (Pattern a -> Pattern a)
-> (Pattern a -> Pattern a)
-> Time
-> Time
-> Time
-> Time
-> [Pattern a]
-> Pattern a
forall a.
(Pattern a -> Pattern a)
-> (Pattern a -> Pattern a)
-> Time
-> Time
-> Time
-> Time
-> [Pattern a]
-> Pattern a
_wash Pattern a -> Pattern a
f Pattern a -> Pattern a
forall a. a -> a
id Time
0 Time
durin Time
0 Time
now [Pattern a]
pats

_xfadeIn :: Time -> Time -> [ControlPattern] -> ControlPattern
_xfadeIn :: Time -> TransitionMapper
_xfadeIn Time
_ Time
_ [] = ControlPattern
forall a. Pattern a
silence
_xfadeIn Time
_ Time
_ [ControlPattern
pat] = ControlPattern
pat
_xfadeIn Time
t Time
now (ControlPattern
pat : ControlPattern
pat' : [ControlPattern]
_) = ControlPattern -> ControlPattern -> ControlPattern
forall a. Pattern a -> Pattern a -> Pattern a
overlay (ControlPattern
pat ControlPattern -> ControlPattern -> ControlPattern
forall a. Num a => Pattern a -> Pattern a -> Pattern a
|* Pattern Double -> ControlPattern
gain (Time
now Time -> Pattern Double -> Pattern Double
forall a. Time -> Pattern a -> Pattern a
`rotR` Time -> Pattern Double -> Pattern Double
forall a. Time -> Pattern a -> Pattern a
_slow Time
t Pattern Double
envEqR)) (ControlPattern
pat' ControlPattern -> ControlPattern -> ControlPattern
forall a. Num a => Pattern a -> Pattern a -> Pattern a
|* Pattern Double -> ControlPattern
gain (Time
now Time -> Pattern Double -> Pattern Double
forall a. Time -> Pattern a -> Pattern a
`rotR` Time -> Pattern Double -> Pattern Double
forall a. Time -> Pattern a -> Pattern a
_slow Time
t Pattern Double
envEq))

-- | Pans the last n versions of the pattern across the field
_histpan :: Int -> Time -> [ControlPattern] -> ControlPattern
_histpan :: Int -> TransitionMapper
_histpan Int
_ Time
_ [] = ControlPattern
forall a. Pattern a
silence
_histpan Int
0 Time
_ [ControlPattern]
_ = ControlPattern
forall a. Pattern a
silence
_histpan Int
n Time
_ [ControlPattern]
ps = [ControlPattern] -> ControlPattern
forall {a}. [Pattern a] -> Pattern a
stack ([ControlPattern] -> ControlPattern)
-> [ControlPattern] -> ControlPattern
forall a b. (a -> b) -> a -> b
$ ((Int, ControlPattern) -> ControlPattern)
-> [(Int, ControlPattern)] -> [ControlPattern]
forall a b. (a -> b) -> [a] -> [b]
map (\(Int
i, ControlPattern
pat) -> ControlPattern
pat ControlPattern -> ControlPattern -> ControlPattern
forall b. Unionable b => Pattern b -> Pattern b -> Pattern b
# Pattern Double -> ControlPattern
pan (Double -> Pattern Double
forall a. a -> Pattern a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Double -> Pattern Double) -> Double -> Pattern Double
forall a b. (a -> b) -> a -> b
$ Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
i Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
n')) ([ControlPattern] -> [(Int, ControlPattern)]
forall a. [a] -> [(Int, a)]
enumerate [ControlPattern]
ps')
  where
    ps' :: [ControlPattern]
ps' = Int -> [ControlPattern] -> [ControlPattern]
forall a. Int -> [a] -> [a]
take Int
n [ControlPattern]
ps
    n' :: Int
n' = [ControlPattern] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [ControlPattern]
ps' -- in case there's fewer patterns than requested

-- | Just stop for a bit before playing new pattern
_wait :: Time -> Time -> [ControlPattern] -> ControlPattern
_wait :: Time -> TransitionMapper
_wait Time
_ Time
_ [] = ControlPattern
forall a. Pattern a
silence
_wait Time
t Time
now (ControlPattern
pat : [ControlPattern]
_) = (Time -> Bool) -> ControlPattern -> ControlPattern
forall a. (Time -> Bool) -> Pattern a -> Pattern a
filterWhen (Time -> Time -> Bool
forall a. Ord a => a -> a -> Bool
>= Time -> Time
nextSam (Time
now Time -> Time -> Time
forall a. Num a => a -> a -> a
+ Time
t Time -> Time -> Time
forall a. Num a => a -> a -> a
- Time
1)) ControlPattern
pat

-- | Just as `wait`, `waitT` stops for a bit and then applies the given transition to the playing pattern
--
-- @
-- d1 $ sound "bd"
--
-- t1 (waitT (xfadeIn 8) 4) $ sound "hh*8"
-- @
_waitT :: (Time -> [ControlPattern] -> ControlPattern) -> Time -> Time -> [ControlPattern] -> ControlPattern
_waitT :: TransitionMapper -> Time -> TransitionMapper
_waitT TransitionMapper
_ Time
_ Time
_ [] = ControlPattern
forall a. Pattern a
silence
_waitT TransitionMapper
f Time
t Time
now [ControlPattern]
pats = (Time -> Bool) -> ControlPattern -> ControlPattern
forall a. (Time -> Bool) -> Pattern a -> Pattern a
filterWhen (Time -> Time -> Bool
forall a. Ord a => a -> a -> Bool
>= Time -> Time
nextSam (Time
now Time -> Time -> Time
forall a. Num a => a -> a -> a
+ Time
t Time -> Time -> Time
forall a. Num a => a -> a -> a
- Time
1)) (TransitionMapper
f (Time
now Time -> Time -> Time
forall a. Num a => a -> a -> a
+ Time
t) [ControlPattern]
pats)

-- |
-- Jumps directly into the given pattern, this is essentially the _no transition_-transition.
--
-- Variants of @jump@ provide more useful capabilities, see @jumpIn@ and @jumpMod@
_jump :: Time -> [ControlPattern] -> ControlPattern
_jump :: TransitionMapper
_jump = Int -> TransitionMapper
_jumpIn Int
0

-- | Sharp `jump` transition after the specified number of cycles have passed.
--
-- @
-- t1 (jumpIn 2) $ sound "kick(3,8)"
-- @
_jumpIn :: Int -> Time -> [ControlPattern] -> ControlPattern
_jumpIn :: Int -> TransitionMapper
_jumpIn Int
n = (ControlPattern -> ControlPattern)
-> (ControlPattern -> ControlPattern)
-> Time
-> Time
-> Time
-> TransitionMapper
forall a.
(Pattern a -> Pattern a)
-> (Pattern a -> Pattern a)
-> Time
-> Time
-> Time
-> Time
-> [Pattern a]
-> Pattern a
_wash ControlPattern -> ControlPattern
forall a. a -> a
id ControlPattern -> ControlPattern
forall a. a -> a
id (Int -> Time
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
n) Time
0 Time
0

-- | Unlike `jumpIn` the variant `jumpIn'` will only transition at cycle boundary (e.g. when the cycle count is an integer).
_jumpIn' :: Int -> Time -> [ControlPattern] -> ControlPattern
_jumpIn' :: Int -> TransitionMapper
_jumpIn' Int
n Time
now = (ControlPattern -> ControlPattern)
-> (ControlPattern -> ControlPattern)
-> Time
-> Time
-> Time
-> TransitionMapper
forall a.
(Pattern a -> Pattern a)
-> (Pattern a -> Pattern a)
-> Time
-> Time
-> Time
-> Time
-> [Pattern a]
-> Pattern a
_wash ControlPattern -> ControlPattern
forall a. a -> a
id ControlPattern -> ControlPattern
forall a. a -> a
id (Time -> Time
nextSam Time
now Time -> Time -> Time
forall a. Num a => a -> a -> a
- Time
now Time -> Time -> Time
forall a. Num a => a -> a -> a
+ Int -> Time
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
n) Time
0 Time
0 Time
now

-- | Sharp `jump` transition at next cycle boundary where cycle mod n == 0
_jumpMod :: Int -> Time -> [ControlPattern] -> ControlPattern
_jumpMod :: Int -> TransitionMapper
_jumpMod Int
n Time
now = Int -> TransitionMapper
_jumpIn' ((Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) Int -> Int -> Int
forall a. Num a => a -> a -> a
- (Time -> Int
forall b. Integral b => Time -> b
forall a b. (RealFrac a, Integral b) => a -> b
floor Time
now Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int
n)) Time
now

-- | Sharp `jump` transition at next cycle boundary where cycle mod n == p
_jumpMod' :: Int -> Int -> Time -> [ControlPattern] -> ControlPattern
_jumpMod' :: Int -> Int -> TransitionMapper
_jumpMod' Int
n Int
p Time
now = Int -> TransitionMapper
_jumpIn' ((Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) Int -> Int -> Int
forall a. Num a => a -> a -> a
- (Time -> Int
forall b. Integral b => Time -> b
forall a b. (RealFrac a, Integral b) => a -> b
floor Time
now Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int
n) Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
p) Time
now

-- | Degrade the new pattern over time until it ends in silence
_mortal :: Time -> Time -> Time -> [ControlPattern] -> ControlPattern
_mortal :: Time -> Time -> TransitionMapper
_mortal Time
_ Time
_ Time
_ [] = ControlPattern
forall a. Pattern a
silence
_mortal Time
lifespan Time
release Time
now (ControlPattern
p : [ControlPattern]
_) = ControlPattern -> ControlPattern -> ControlPattern
forall a. Pattern a -> Pattern a -> Pattern a
overlay ((Time -> Bool) -> ControlPattern -> ControlPattern
forall a. (Time -> Bool) -> Pattern a -> Pattern a
filterWhen (Time -> Time -> Bool
forall a. Ord a => a -> a -> Bool
< (Time
now Time -> Time -> Time
forall a. Num a => a -> a -> a
+ Time
lifespan)) ControlPattern
p) ((Time -> Bool) -> ControlPattern -> ControlPattern
forall a. (Time -> Bool) -> Pattern a -> Pattern a
filterWhen (Time -> Time -> Bool
forall a. Ord a => a -> a -> Bool
>= (Time
now Time -> Time -> Time
forall a. Num a => a -> a -> a
+ Time
lifespan)) (Time -> Time -> ControlPattern -> ControlPattern
forall a. Time -> Time -> Pattern a -> Pattern a
fadeOutFrom (Time
now Time -> Time -> Time
forall a. Num a => a -> a -> a
+ Time
lifespan) Time
release ControlPattern
p))

_interpolate :: Time -> [ControlPattern] -> ControlPattern
_interpolate :: TransitionMapper
_interpolate = Time -> TransitionMapper
_interpolateIn Time
4

_interpolateIn :: Time -> Time -> [ControlPattern] -> ControlPattern
_interpolateIn :: Time -> TransitionMapper
_interpolateIn Time
_ Time
_ [] = ControlPattern
forall a. Pattern a
silence
_interpolateIn Time
_ Time
_ [ControlPattern
p] = ControlPattern
p
_interpolateIn Time
t Time
now (ControlPattern
pat : ControlPattern
pat' : [ControlPattern]
_) = ValueMap -> ValueMap -> Double -> ValueMap
forall {k}.
Ord k =>
Map k Value -> Map k Value -> Double -> Map k Value
f (ValueMap -> ValueMap -> Double -> ValueMap)
-> ControlPattern -> Pattern (ValueMap -> Double -> ValueMap)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ControlPattern
pat' Pattern (ValueMap -> Double -> ValueMap)
-> ControlPattern -> Pattern (Double -> ValueMap)
forall a b. Pattern (a -> b) -> Pattern a -> Pattern b
*> ControlPattern
pat Pattern (Double -> ValueMap) -> Pattern Double -> ControlPattern
forall a b. Pattern (a -> b) -> Pattern a -> Pattern b
<* Pattern Double
automation
  where
    automation :: Pattern Double
automation = Time
now Time -> Pattern Double -> Pattern Double
forall a. Time -> Pattern a -> Pattern a
`rotR` Time -> Pattern Double -> Pattern Double
forall a. Time -> Pattern a -> Pattern a
_slow Time
t Pattern Double
envL
    f :: Map k Value -> Map k Value -> Double -> Map k Value
f Map k Value
a Map k Value
b Double
x =
      (Value -> Value -> Value)
-> Map k Value -> Map k Value -> Map k Value
forall k a. Ord k => (a -> a -> a) -> Map k a -> Map k a -> Map k a
Map.unionWith
        ( (Int -> Int -> Int)
-> (Double -> Double -> Double) -> Value -> Value -> Value
fNum2
            (\Int
a' Int
b' -> Double -> Int
forall b. Integral b => Double -> b
forall a b. (RealFrac a, Integral b) => a -> b
floor (Double -> Int) -> Double -> Int
forall a b. (a -> b) -> a -> b
$ Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
a' Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
x Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
b' Double -> Double -> Double
forall a. Num a => a -> a -> a
* (Double
1 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
x))
            (\Double
a' Double
b' -> Double
a' Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
x Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
b' Double -> Double -> Double
forall a. Num a => a -> a -> a
* (Double
1 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
x))
        )
        Map k Value
b
        Map k Value
a

-- |
-- Degrades the current pattern while undegrading the next.
--
-- This is like @xfade@ but not by gain of samples but by randomly removing events from the current pattern and slowly adding back in missing events from the next one.
--
-- @
-- d1 $ sound "bd(3,8)"
--
-- t1 clutch $ sound "[hh*4, odx(3,8)]"
-- @
--
-- @clutch@ takes two cycles for the transition, essentially this is @clutchIn 2@.
_clutch :: Time -> [Pattern a] -> Pattern a
_clutch :: forall a. Time -> [Pattern a] -> Pattern a
_clutch = Time -> Time -> [Pattern a] -> Pattern a
forall a. Time -> Time -> [Pattern a] -> Pattern a
_clutchIn Time
2

-- |
-- Also degrades the current pattern and undegrades the next.
-- To change the number of cycles the transition takes, you can use @clutchIn@ like so:
--
-- @
-- d1 $ sound "bd(5,8)"
--
-- t1 (clutchIn 8) $ sound "[hh*4, odx(3,8)]"
-- @
--
-- will take 8 cycles for the transition.
_clutchIn :: Time -> Time -> [Pattern a] -> Pattern a
_clutchIn :: forall a. Time -> Time -> [Pattern a] -> Pattern a
_clutchIn Time
_ Time
_ [] = Pattern a
forall a. Pattern a
silence
_clutchIn Time
_ Time
_ [Pattern a
p] = Pattern a
p
_clutchIn Time
t Time
now (Pattern a
p : Pattern a
p' : [Pattern a]
_) = Pattern a -> Pattern a -> Pattern a
forall a. Pattern a -> Pattern a -> Pattern a
overlay (Time -> Time -> Pattern a -> Pattern a
forall a. Time -> Time -> Pattern a -> Pattern a
fadeOutFrom Time
now Time
t Pattern a
p') (Time -> Time -> Pattern a -> Pattern a
forall a. Time -> Time -> Pattern a -> Pattern a
fadeInFrom Time
now Time
t Pattern a
p)

-- | same as `anticipate` though it allows you to specify the number of cycles until dropping to the new pattern, e.g.:
--
-- @
-- d1 $ sound "jvbass(3,8)"
--
-- t1 (anticipateIn 4) $ sound "jvbass(5,8)"
-- @
_anticipateIn :: Time -> Time -> [ControlPattern] -> ControlPattern
_anticipateIn :: Time -> TransitionMapper
_anticipateIn Time
t Time
now [ControlPattern]
pats = (ControlPattern -> ControlPattern) -> Time -> TransitionMapper
forall a.
(Pattern a -> Pattern a)
-> Time -> Time -> [Pattern a] -> Pattern a
_washIn (Pattern ControlPattern -> ControlPattern
forall b. Pattern (Pattern b) -> Pattern b
innerJoin (Pattern ControlPattern -> ControlPattern)
-> (ControlPattern -> Pattern ControlPattern)
-> ControlPattern
-> ControlPattern
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (\ControlPattern
pat -> (\Time
v -> Integer -> Double -> Time -> ControlPattern -> ControlPattern
_stut Integer
8 Double
0.2 Time
v ControlPattern
pat) (Time -> ControlPattern) -> Pattern Time -> Pattern ControlPattern
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Time
now Time -> Pattern Time -> Pattern Time
forall a. Time -> Pattern a -> Pattern a
`rotR` Time -> Pattern Time -> Pattern Time
forall a. Time -> Pattern a -> Pattern a
_slow Time
t (Double -> Time
forall a. Real a => a -> Time
toRational (Double -> Time) -> Pattern Double -> Pattern Time
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Pattern Double
envLR)))) Time
t Time
now [ControlPattern]
pats

-- wash :: (Pattern a -> Pattern a) -> (Pattern a -> Pattern a) -> Time -> Time -> Time -> Time -> [Pattern a] -> Pattern a

-- | `anticipate` is an increasing comb filter.
--
-- Build up some tension, culminating in a _drop_ to the new pattern after 8 cycles.
_anticipate :: Time -> [ControlPattern] -> ControlPattern
_anticipate :: TransitionMapper
_anticipate = Time -> TransitionMapper
_anticipateIn Time
8

-- Deprecated aliases
mortalOverlay :: Time -> Time -> [Pattern a] -> Pattern a
mortalOverlay :: forall a. Time -> Time -> [Pattern a] -> Pattern a
mortalOverlay = Time -> Time -> [Pattern a] -> Pattern a
forall a. Time -> Time -> [Pattern a] -> Pattern a
_mortalOverlay

wash ::
  (Pattern a -> Pattern a) ->
  (Pattern a -> Pattern a) ->
  Time ->
  Time ->
  Time ->
  Time ->
  [Pattern a] ->
  Pattern a
wash :: forall a.
(Pattern a -> Pattern a)
-> (Pattern a -> Pattern a)
-> Time
-> Time
-> Time
-> Time
-> [Pattern a]
-> Pattern a
wash = (Pattern a -> Pattern a)
-> (Pattern a -> Pattern a)
-> Time
-> Time
-> Time
-> Time
-> [Pattern a]
-> Pattern a
forall a.
(Pattern a -> Pattern a)
-> (Pattern a -> Pattern a)
-> Time
-> Time
-> Time
-> Time
-> [Pattern a]
-> Pattern a
_wash

washIn ::
  (Pattern a -> Pattern a) ->
  Time ->
  Time ->
  [Pattern a] ->
  Pattern a
washIn :: forall a.
(Pattern a -> Pattern a)
-> Time -> Time -> [Pattern a] -> Pattern a
washIn = (Pattern a -> Pattern a)
-> Time -> Time -> [Pattern a] -> Pattern a
forall a.
(Pattern a -> Pattern a)
-> Time -> Time -> [Pattern a] -> Pattern a
_washIn

xfadeIn :: Time -> Time -> [ControlPattern] -> ControlPattern
xfadeIn :: Time -> TransitionMapper
xfadeIn = Time -> TransitionMapper
_xfadeIn

histpan :: Int -> Time -> [ControlPattern] -> ControlPattern
histpan :: Int -> TransitionMapper
histpan = Int -> TransitionMapper
_histpan

wait :: Time -> Time -> [ControlPattern] -> ControlPattern
wait :: Time -> TransitionMapper
wait = Time -> TransitionMapper
_wait

waitT ::
  (Time -> [ControlPattern] -> ControlPattern) ->
  Time ->
  Time ->
  [ControlPattern] ->
  ControlPattern
waitT :: TransitionMapper -> Time -> TransitionMapper
waitT = TransitionMapper -> Time -> TransitionMapper
_waitT

jump :: Time -> [ControlPattern] -> ControlPattern
jump :: TransitionMapper
jump = TransitionMapper
_jump

jumpIn :: Int -> Time -> [ControlPattern] -> ControlPattern
jumpIn :: Int -> TransitionMapper
jumpIn = Int -> TransitionMapper
_jumpIn

jumpIn' :: Int -> Time -> [ControlPattern] -> ControlPattern
jumpIn' :: Int -> TransitionMapper
jumpIn' = Int -> TransitionMapper
_jumpIn'

jumpMod :: Int -> Time -> [ControlPattern] -> ControlPattern
jumpMod :: Int -> TransitionMapper
jumpMod = Int -> TransitionMapper
_jumpMod

jumpMod' :: Int -> Int -> Time -> [ControlPattern] -> ControlPattern
jumpMod' :: Int -> Int -> TransitionMapper
jumpMod' = Int -> Int -> TransitionMapper
_jumpMod'

mortal ::
  Time -> Time -> Time -> [ControlPattern] -> ControlPattern
mortal :: Time -> Time -> TransitionMapper
mortal = Time -> Time -> TransitionMapper
_mortal

interpolate :: Time -> [ControlPattern] -> ControlPattern
interpolate :: TransitionMapper
interpolate = TransitionMapper
_interpolate

interpolateIn ::
  Time -> Time -> [ControlPattern] -> ControlPattern
interpolateIn :: Time -> TransitionMapper
interpolateIn = Time -> TransitionMapper
_interpolateIn

clutch :: Time -> [Pattern a] -> Pattern a
clutch :: forall a. Time -> [Pattern a] -> Pattern a
clutch = Time -> [Pattern a] -> Pattern a
forall a. Time -> [Pattern a] -> Pattern a
_clutch

clutchIn :: Time -> Time -> [Pattern a] -> Pattern a
clutchIn :: forall a. Time -> Time -> [Pattern a] -> Pattern a
clutchIn = Time -> Time -> [Pattern a] -> Pattern a
forall a. Time -> Time -> [Pattern a] -> Pattern a
_clutchIn

anticipateIn :: Time -> Time -> [ControlPattern] -> ControlPattern
anticipateIn :: Time -> TransitionMapper
anticipateIn = Time -> TransitionMapper
_anticipateIn

anticipate :: Time -> [ControlPattern] -> ControlPattern
anticipate :: TransitionMapper
anticipate = TransitionMapper
_anticipate