packages feed

tidal 0.9.10 → 1.0.0

raw patch · 54 files changed

+7554/−5472 lines, 54 filesdep +bifunctorsdep +microspecdep +mwc-randomdep −mersenne-random-pure64dep −tastydep −tasty-hunitPVP ok

version bump matches the API change (PVP)

Dependencies added: bifunctors, microspec, mwc-random, network, random, vector

Dependencies removed: mersenne-random-pure64, tasty, tasty-hunit, websockets

API changes (from Hackage documentation)

- Sound.Tidal.Chords: arpg :: Num a => Pattern String -> Pattern a
- Sound.Tidal.Chords: chord :: Num a => Pattern String -> Pattern a
- Sound.Tidal.Chords: chordate :: Num b => [[b]] -> b -> Int -> [b]
- Sound.Tidal.Chords: enchord :: Num a => [[a]] -> Pattern a -> Pattern Int -> Pattern a
- Sound.Tidal.Chords: evelenSharp :: Num a => [a]
- Sound.Tidal.Context: (!!) :: () => [a] -> Int -> a
- Sound.Tidal.Context: (###) :: Foldable t => ParamPattern -> t ParamPattern -> ParamPattern
- Sound.Tidal.Context: (#&&#) :: Applicative f => f Bool -> f Bool -> f Bool
- Sound.Tidal.Context: (#) :: ParamPattern -> ParamPattern -> ParamPattern
- Sound.Tidal.Context: (#^^#) :: Applicative f => f Bool -> f Bool -> f Bool
- Sound.Tidal.Context: (#||#) :: Applicative f => f Bool -> f Bool -> f Bool
- Sound.Tidal.Context: (%) :: Integral a => a -> a -> Ratio a
- Sound.Tidal.Context: (***) :: Foldable t => ParamPattern -> t ParamPattern -> ParamPattern
- Sound.Tidal.Context: (*>) :: Applicative f => f a -> f b -> f b
- Sound.Tidal.Context: (++) :: () => [a] -> [a] -> [a]
- Sound.Tidal.Context: (+++) :: Foldable t => ParamPattern -> t ParamPattern -> ParamPattern
- Sound.Tidal.Context: (///) :: Foldable t => ParamPattern -> t ParamPattern -> ParamPattern
- Sound.Tidal.Context: (<$) :: Functor f => a -> f b -> f a
- Sound.Tidal.Context: (<$>) :: Functor f => a -> b -> f a -> f b
- Sound.Tidal.Context: (<*) :: Applicative f => f a -> f b -> f a
- Sound.Tidal.Context: (<**>) :: Applicative f => f a -> f a -> b -> f b
- Sound.Tidal.Context: (<*>) :: Applicative f => f a -> b -> f a -> f b
- Sound.Tidal.Context: (<<~) :: Int -> Pattern a -> Pattern a
- Sound.Tidal.Context: (<>) :: Semigroup a => a -> a -> a
- Sound.Tidal.Context: (<|>) :: Alternative f => f a -> f a -> f a
- Sound.Tidal.Context: (<~) :: Pattern Time -> Pattern a -> Pattern a
- Sound.Tidal.Context: (<~>) :: Pattern String -> Pattern b -> Pattern b
- Sound.Tidal.Context: (@@) :: Int -> Int -> Sieve Bool
- Sound.Tidal.Context: (\\) :: Eq a => [a] -> [a] -> [a]
- Sound.Tidal.Context: (|*|) :: ParamPattern -> ParamPattern -> ParamPattern
- Sound.Tidal.Context: (|+|) :: ParamPattern -> ParamPattern -> ParamPattern
- Sound.Tidal.Context: (|-|) :: ParamPattern -> ParamPattern -> ParamPattern
- Sound.Tidal.Context: (|/|) :: ParamPattern -> ParamPattern -> ParamPattern
- Sound.Tidal.Context: (|=|) :: ParamPattern -> ParamPattern -> ParamPattern
- Sound.Tidal.Context: (~>) :: Pattern Time -> Pattern a -> Pattern a
- Sound.Tidal.Context: (~>>) :: Int -> Pattern a -> Pattern a
- Sound.Tidal.Context: All :: Bool -> All
- Sound.Tidal.Context: Alt :: f a -> Alt
- Sound.Tidal.Context: Any :: Bool -> Any
- Sound.Tidal.Context: Backend :: ToMessageFunc -> Shape -> Tempo -> Int -> IO () -> Backend a
- Sound.Tidal.Context: Const :: a -> Const a
- Sound.Tidal.Context: Dirt :: StreamType
- Sound.Tidal.Context: Dual :: a -> Dual a
- Sound.Tidal.Context: Endo :: a -> a -> Endo a
- Sound.Tidal.Context: Esp :: SyncType
- Sound.Tidal.Context: F :: String -> Maybe Double -> Param
- Sound.Tidal.Context: First :: Maybe a -> First a
- Sound.Tidal.Context: I :: String -> Maybe Int -> Param
- Sound.Tidal.Context: Last :: Maybe a -> Last a
- Sound.Tidal.Context: Master :: ServerMode
- Sound.Tidal.Context: Negative :: Sign
- Sound.Tidal.Context: NoSync :: SyncType
- Sound.Tidal.Context: Pattern :: Arc -> [Event a] -> Pattern a
- Sound.Tidal.Context: Positive :: Sign
- Sound.Tidal.Context: Product :: a -> Product a
- Sound.Tidal.Context: S :: String -> Maybe String -> Param
- Sound.Tidal.Context: Shape :: [Param] -> Double -> Bool -> Shape
- Sound.Tidal.Context: Sieve :: Int -> a -> Sieve a
- Sound.Tidal.Context: Slave :: UDP -> ServerMode
- Sound.Tidal.Context: Sum :: a -> Sum a
- Sound.Tidal.Context: SuperDirt :: StreamType
- Sound.Tidal.Context: TConnection :: Unique -> Connection -> TConnection
- Sound.Tidal.Context: TPat_Atom :: a -> TPat a
- Sound.Tidal.Context: TPat_Cat :: [TPat a] -> TPat a
- Sound.Tidal.Context: TPat_DegradeBy :: Double -> (TPat a) -> TPat a
- Sound.Tidal.Context: TPat_Density :: (TPat Time) -> (TPat a) -> TPat a
- Sound.Tidal.Context: TPat_Elongate :: Int -> TPat a
- Sound.Tidal.Context: TPat_EnumFromTo :: (TPat a) -> (TPat a) -> TPat a
- Sound.Tidal.Context: TPat_Foot :: TPat a
- Sound.Tidal.Context: TPat_Overlay :: (TPat a) -> (TPat a) -> TPat a
- Sound.Tidal.Context: TPat_ShiftL :: Time -> (TPat a) -> TPat a
- Sound.Tidal.Context: TPat_Silence :: TPat a
- Sound.Tidal.Context: TPat_Slow :: (TPat Time) -> (TPat a) -> TPat a
- Sound.Tidal.Context: TPat_TimeCat :: [TPat a] -> TPat a
- Sound.Tidal.Context: TPat_Zoom :: Arc -> (TPat a) -> TPat a
- Sound.Tidal.Context: TPat_pE :: (TPat Int) -> (TPat Int) -> (TPat Integer) -> (TPat a) -> TPat a
- Sound.Tidal.Context: Tempo :: UTCTime -> Double -> Double -> Bool -> Double -> Tempo
- Sound.Tidal.Context: VF :: Double -> Value
- Sound.Tidal.Context: VI :: Int -> Value
- Sound.Tidal.Context: VS :: String -> Value
- Sound.Tidal.Context: WrapArrow :: a b c -> WrappedArrow b c
- Sound.Tidal.Context: WrapMonad :: m a -> WrappedMonad a
- Sound.Tidal.Context: ZipList :: [a] -> ZipList a
- Sound.Tidal.Context: [appEndo] :: Endo a -> a -> a
- Sound.Tidal.Context: [arc] :: Pattern a -> Arc -> [Event a]
- Sound.Tidal.Context: [at] :: Tempo -> UTCTime
- Sound.Tidal.Context: [beat] :: Tempo -> Double
- Sound.Tidal.Context: [clockLatency] :: Tempo -> Double
- Sound.Tidal.Context: [cpsStamp] :: Shape -> Bool
- Sound.Tidal.Context: [cps] :: Tempo -> Double
- Sound.Tidal.Context: [fDefault] :: Param -> Maybe Double
- Sound.Tidal.Context: [flush] :: Backend a -> Shape -> Tempo -> Int -> IO ()
- Sound.Tidal.Context: [fvalue] :: Value -> Double
- Sound.Tidal.Context: [getAll] :: All -> Bool
- Sound.Tidal.Context: [getAlt] :: Alt -> f a
- Sound.Tidal.Context: [getAny] :: Any -> Bool
- Sound.Tidal.Context: [getConst] :: Const a -> a
- Sound.Tidal.Context: [getDual] :: Dual a -> a
- Sound.Tidal.Context: [getFirst] :: First a -> Maybe a
- Sound.Tidal.Context: [getLast] :: Last a -> Maybe a
- Sound.Tidal.Context: [getProduct] :: Product a -> a
- Sound.Tidal.Context: [getSum] :: Sum a -> a
- Sound.Tidal.Context: [getZipList] :: ZipList a -> [a]
- Sound.Tidal.Context: [iDefault] :: Param -> Maybe Int
- Sound.Tidal.Context: [ivalue] :: Value -> Int
- Sound.Tidal.Context: [latency] :: Shape -> Double
- Sound.Tidal.Context: [name] :: Param -> String
- Sound.Tidal.Context: [params] :: Shape -> [Param]
- Sound.Tidal.Context: [paused] :: Tempo -> Bool
- Sound.Tidal.Context: [sDefault] :: Param -> Maybe String
- Sound.Tidal.Context: [sieveAt] :: Sieve a -> Int -> a
- Sound.Tidal.Context: [svalue] :: Value -> String
- Sound.Tidal.Context: [toMessage] :: Backend a -> ToMessageFunc
- Sound.Tidal.Context: [unwrapArrow] :: WrappedArrow b c -> a b c
- Sound.Tidal.Context: [unwrapMonad] :: WrappedMonad a -> m a
- Sound.Tidal.Context: _chop :: Int -> ParamPattern -> ParamPattern
- Sound.Tidal.Context: _degradeBy :: Double -> Pattern a -> Pattern a
- Sound.Tidal.Context: _density :: Time -> Pattern a -> Pattern a
- Sound.Tidal.Context: _discretise :: Time -> Pattern a -> Pattern a
- Sound.Tidal.Context: _distrib :: [Int] -> Pattern a -> Pattern a
- Sound.Tidal.Context: _e :: Int -> Int -> Pattern a -> Pattern a
- Sound.Tidal.Context: _e' :: Int -> Int -> Pattern a -> Pattern a
- Sound.Tidal.Context: _einv :: Int -> Int -> Pattern a -> Pattern a
- Sound.Tidal.Context: _eoff :: Int -> Int -> Integer -> Pattern a -> Pattern a
- Sound.Tidal.Context: _every :: Int -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
- Sound.Tidal.Context: _every' :: Int -> Int -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
- Sound.Tidal.Context: _fast :: Time -> Pattern a -> Pattern a
- Sound.Tidal.Context: _gap :: Int -> ParamPattern -> ParamPattern
- Sound.Tidal.Context: _iter :: Int -> Pattern a -> Pattern a
- Sound.Tidal.Context: _iter' :: Int -> Pattern a -> Pattern a
- Sound.Tidal.Context: _linger :: Time -> Pattern a -> Pattern a
- Sound.Tidal.Context: _off :: Time -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
- Sound.Tidal.Context: _ply :: Int -> Pattern a -> Pattern a
- Sound.Tidal.Context: _run :: (Enum a, Num a) => a -> Pattern a
- Sound.Tidal.Context: _scan :: (Enum a, Num a) => a -> Pattern a
- Sound.Tidal.Context: _slice :: Int -> Int -> ParamPattern -> ParamPattern
- Sound.Tidal.Context: _slow :: Time -> Pattern a -> Pattern a
- Sound.Tidal.Context: _spin :: Int -> ParamPattern -> ParamPattern
- Sound.Tidal.Context: _striate :: Int -> ParamPattern -> ParamPattern
- Sound.Tidal.Context: _striate' :: Int -> Double -> ParamPattern -> ParamPattern
- Sound.Tidal.Context: _striateL :: Int -> Int -> ParamPattern -> ParamPattern
- Sound.Tidal.Context: _striateL' :: Integral a => Int -> Double -> a -> ParamPattern -> ParamPattern
- Sound.Tidal.Context: _striateO :: Int -> Double -> ParamPattern -> ParamPattern
- Sound.Tidal.Context: _stripe :: Int -> Pattern a -> Pattern a
- Sound.Tidal.Context: _stut :: Integer -> Double -> Rational -> ParamPattern -> ParamPattern
- Sound.Tidal.Context: _stut' :: (Num n, Ord n) => n -> Time -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
- Sound.Tidal.Context: _trunc :: Time -> Pattern a -> Pattern a
- Sound.Tidal.Context: _unDegradeBy :: Double -> Pattern a -> Pattern a
- Sound.Tidal.Context: accelerate :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: accelerate_p :: Param
- Sound.Tidal.Context: addMVarFinalizer :: () => MVar a -> IO () -> IO ()
- Sound.Tidal.Context: all :: Foldable t => a -> Bool -> t a -> Bool
- Sound.Tidal.Context: almostAlways :: (Pattern a -> Pattern a) -> Pattern a -> Pattern a
- Sound.Tidal.Context: almostNever :: (Pattern a -> Pattern a) -> Pattern a -> Pattern a
- Sound.Tidal.Context: always :: (Pattern a -> Pattern a) -> Pattern a -> Pattern a
- Sound.Tidal.Context: and :: Foldable t => t Bool -> Bool
- Sound.Tidal.Context: angles :: Parser a -> Parser a
- Sound.Tidal.Context: anticipate :: Time -> [ParamPattern] -> ParamPattern
- Sound.Tidal.Context: anticipateIn :: Time -> Time -> [ParamPattern] -> ParamPattern
- Sound.Tidal.Context: any :: Foldable t => a -> Bool -> t a -> Bool
- Sound.Tidal.Context: append :: Pattern a -> Pattern a -> Pattern a
- Sound.Tidal.Context: append' :: Pattern a -> Pattern a -> Pattern a
- Sound.Tidal.Context: applyShape' :: Shape -> ParamMap -> Maybe ParamMap
- Sound.Tidal.Context: applySign :: Num a => Sign -> a -> a
- Sound.Tidal.Context: approxRational :: RealFrac a => a -> a -> Rational
- Sound.Tidal.Context: arcCycles :: Arc -> [Arc]
- Sound.Tidal.Context: arcCycles' :: Arc -> [Arc]
- Sound.Tidal.Context: array :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: array_p :: Param
- Sound.Tidal.Context: atom :: a -> Pattern a
- Sound.Tidal.Context: att :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: attack :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: attack_p :: Param
- Sound.Tidal.Context: bandf :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: bandf_p :: Param
- Sound.Tidal.Context: bandq :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: bandq_p :: Param
- Sound.Tidal.Context: beatNow :: Tempo -> IO (Double)
- Sound.Tidal.Context: begin :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: begin_p :: Param
- Sound.Tidal.Context: bpf :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: bpf_p :: Param
- Sound.Tidal.Context: bpq :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: bpq_p :: Param
- Sound.Tidal.Context: bpsUtils :: IO ((Double -> IO (), IO (Rational)))
- Sound.Tidal.Context: braces :: Parser a -> Parser a
- Sound.Tidal.Context: brackets :: Parser a -> Parser a
- Sound.Tidal.Context: brak :: Pattern a -> Pattern a
- Sound.Tidal.Context: break :: () => a -> Bool -> [a] -> ([a], [a])
- Sound.Tidal.Context: breakUp :: Pattern a -> Pattern a
- Sound.Tidal.Context: broadcast :: Text -> ClientState -> IO ()
- Sound.Tidal.Context: cat :: [Pattern a] -> Pattern a
- Sound.Tidal.Context: cc :: Pattern String -> ParamPattern
- Sound.Tidal.Context: ccn :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: ccn_p :: Param
- Sound.Tidal.Context: ccv :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: ccv_p :: Param
- Sound.Tidal.Context: changeStreamType :: MVar StreamType -> StreamType -> IO (IO StreamType)
- Sound.Tidal.Context: changeSyncType :: MVar SyncType -> SyncType -> IO (IO SyncType)
- Sound.Tidal.Context: changeTempo :: MVar Tempo -> Packet -> IO ()
- Sound.Tidal.Context: channel :: Pattern Int -> ParamPattern
- Sound.Tidal.Context: channel_p :: Param
- Sound.Tidal.Context: chdecay :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: choose :: [a] -> Pattern a
- Sound.Tidal.Context: chop :: Pattern Int -> ParamPattern -> ParamPattern
- Sound.Tidal.Context: chopArc :: Arc -> Int -> [Arc]
- Sound.Tidal.Context: chord :: Num a => Pattern String -> Pattern a
- Sound.Tidal.Context: chunk :: Integer -> (Pattern b -> Pattern b) -> Pattern b -> Pattern b
- Sound.Tidal.Context: chunk' :: Integral a => a -> (Pattern b -> Pattern b) -> Pattern b -> Pattern b
- Sound.Tidal.Context: class Applicative f => Alternative (f :: * -> *)
- Sound.Tidal.Context: class Functor f => Applicative (f :: * -> *)
- Sound.Tidal.Context: class Enumerable a
- Sound.Tidal.Context: class Semigroup a => Monoid a
- Sound.Tidal.Context: class ParamType a
- Sound.Tidal.Context: class Parseable a
- Sound.Tidal.Context: clhatdecay :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: clhatdecay_p :: Param
- Sound.Tidal.Context: clientApp :: MVar Tempo -> MVar Double -> MVar Double -> ClientApp ()
- Sound.Tidal.Context: clocked :: (Tempo -> Int -> IO ()) -> IO ()
- Sound.Tidal.Context: clockedTick :: Int -> (Tempo -> Int -> IO ()) -> IO ()
- Sound.Tidal.Context: clockedTickEsp :: Int -> (Tempo -> Int -> IO ()) -> IO ()
- Sound.Tidal.Context: clockedTickLoopEsp :: Int -> (Tempo -> Int -> IO ()) -> MVar Tempo -> Int -> IO Int
- Sound.Tidal.Context: clutch :: Time -> [Pattern a] -> Pattern a
- Sound.Tidal.Context: clutchIn :: Time -> Time -> [Pattern a] -> Pattern a
- Sound.Tidal.Context: coarse :: Pattern Int -> ParamPattern
- Sound.Tidal.Context: coarse_p :: Param
- Sound.Tidal.Context: coerce :: Param -> ParamPattern -> ParamPattern
- Sound.Tidal.Context: combineV :: (Value -> Value -> Value) -> ParamMap -> ParamMap -> ParamMap
- Sound.Tidal.Context: command :: Pattern String -> ParamPattern
- Sound.Tidal.Context: compress :: Arc -> Pattern a -> Pattern a
- Sound.Tidal.Context: compressTo :: Arc -> Pattern a -> Pattern a
- Sound.Tidal.Context: concat :: Foldable t => t [a] -> [a]
- Sound.Tidal.Context: concatMap :: Foldable t => a -> [b] -> t a -> [b]
- Sound.Tidal.Context: connectClient :: Bool -> String -> MVar Tempo -> MVar Double -> MVar Double -> IO ()
- Sound.Tidal.Context: control :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: control_p :: Param
- Sound.Tidal.Context: copyParam :: Param -> Param -> ParamPattern -> ParamPattern
- Sound.Tidal.Context: cosine :: Fractional a => Pattern a
- Sound.Tidal.Context: cpsSetter :: IO (Double -> IO ())
- Sound.Tidal.Context: cpsUtils :: IO (Double -> IO (), IO Rational)
- Sound.Tidal.Context: cpsUtils' :: IO ((Double -> IO (), (Double -> IO ()), IO Rational))
- Sound.Tidal.Context: cpsUtilsEsp :: IO (Double -> IO (), IO Rational, IO Tempo)
- Sound.Tidal.Context: crush :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: crush_p :: Param
- Sound.Tidal.Context: ctf :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: ctfg :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: ctlNum :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: ctlNum_p :: Param
- Sound.Tidal.Context: ctranspose :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: ctranspose_p :: Param
- Sound.Tidal.Context: cut :: Pattern Int -> ParamPattern
- Sound.Tidal.Context: cut_p :: Param
- Sound.Tidal.Context: cutoff :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: cutoff_p :: Param
- Sound.Tidal.Context: cutoffegint :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: cutoffegint_p :: Param
- Sound.Tidal.Context: cycle :: () => [a] -> [a]
- Sound.Tidal.Context: cycleChoose :: [a] -> Pattern a
- Sound.Tidal.Context: cyclePos :: Time -> Time
- Sound.Tidal.Context: data Backend a
- Sound.Tidal.Context: data Chan a
- Sound.Tidal.Context: data MVar a
- Sound.Tidal.Context: data Param
- Sound.Tidal.Context: data QSem
- Sound.Tidal.Context: data QSemN
- Sound.Tidal.Context: data Ratio a
- Sound.Tidal.Context: data ServerMode
- Sound.Tidal.Context: data Shape
- Sound.Tidal.Context: data Sieve a
- Sound.Tidal.Context: data Sign
- Sound.Tidal.Context: data StreamType
- Sound.Tidal.Context: data SyncType
- Sound.Tidal.Context: data TConnection
- Sound.Tidal.Context: data TPat a
- Sound.Tidal.Context: data Tempo
- Sound.Tidal.Context: data ThreadId
- Sound.Tidal.Context: data Value
- Sound.Tidal.Context: datumToColour :: Value -> ColourD
- Sound.Tidal.Context: decay :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: decay_p :: Param
- Sound.Tidal.Context: defaultMap :: Shape -> ParamMap
- Sound.Tidal.Context: defaultValue :: Param -> Value
- Sound.Tidal.Context: defaulted :: Shape -> [Param]
- Sound.Tidal.Context: degrade :: Pattern a -> Pattern a
- Sound.Tidal.Context: degradeBy :: Pattern Double -> Pattern a -> Pattern a
- Sound.Tidal.Context: degradeOverBy :: Int -> Pattern Double -> Pattern a -> Pattern a
- Sound.Tidal.Context: degree :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: degree_p :: Param
- Sound.Tidal.Context: delay :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: delay_p :: Param
- Sound.Tidal.Context: delayfb :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: delayfeedback :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: delayfeedback_p :: Param
- Sound.Tidal.Context: delayt :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: delaytime :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: delaytime_p :: Param
- Sound.Tidal.Context: delete :: Eq a => a -> [a] -> [a]
- Sound.Tidal.Context: deleteBy :: () => a -> a -> Bool -> a -> [a] -> [a]
- Sound.Tidal.Context: deleteFirstsBy :: () => a -> a -> Bool -> [a] -> [a] -> [a]
- Sound.Tidal.Context: denominator :: () => Ratio a -> a
- Sound.Tidal.Context: density :: Pattern Time -> Pattern a -> Pattern a
- Sound.Tidal.Context: densityGap :: Time -> Pattern a -> Pattern a
- Sound.Tidal.Context: det :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: detune :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: detune_p :: Param
- Sound.Tidal.Context: dirt :: Shape
- Sound.Tidal.Context: dirtBackend :: () => IO Backend a
- Sound.Tidal.Context: dirtSetters :: IO Time -> IO (ParamPattern -> IO (), (Time -> [ParamPattern] -> ParamPattern) -> ParamPattern -> IO ())
- Sound.Tidal.Context: dirtSettersEsp :: IO Time -> IO (ParamPattern -> IO (), (Time -> [ParamPattern] -> ParamPattern) -> ParamPattern -> IO ())
- Sound.Tidal.Context: dirtSlang :: OscSlang
- Sound.Tidal.Context: dirtState :: IO MVar (ParamPattern, [ParamPattern])
- Sound.Tidal.Context: dirtStream :: IO ParamPattern -> IO ()
- Sound.Tidal.Context: dirtStreamEsp :: IO (ParamPattern -> IO ())
- Sound.Tidal.Context: dirtToColour :: ParamPattern -> Pattern ColourD
- Sound.Tidal.Context: dirtstream :: () => p -> IO ParamPattern -> IO ()
- Sound.Tidal.Context: discretise :: Time -> Pattern a -> Pattern a
- Sound.Tidal.Context: discretise' :: Pattern Time -> Pattern a -> Pattern a
- Sound.Tidal.Context: distrib :: [Pattern Int] -> Pattern a -> Pattern a
- Sound.Tidal.Context: doAt :: RealFrac a => a -> IO () -> IO ()
- Sound.Tidal.Context: double :: Time -> Pattern a -> Pattern a
- Sound.Tidal.Context: drop :: () => Int -> [a] -> [a]
- Sound.Tidal.Context: dropWhile :: () => a -> Bool -> [a] -> [a]
- Sound.Tidal.Context: dropWhileEnd :: () => a -> Bool -> [a] -> [a]
- Sound.Tidal.Context: drum :: Pattern String -> ParamPattern
- Sound.Tidal.Context: drumN :: Num a => String -> a
- Sound.Tidal.Context: dry :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: dry_p :: Param
- Sound.Tidal.Context: dupChan :: () => Chan a -> IO Chan a
- Sound.Tidal.Context: dur :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: durPattern :: Pattern a -> Pattern Time
- Sound.Tidal.Context: durPattern' :: Pattern a -> Pattern Time
- Sound.Tidal.Context: dur_p :: Param
- Sound.Tidal.Context: durations :: [TPat a] -> [(Int, TPat a)]
- Sound.Tidal.Context: e :: Pattern Int -> Pattern Int -> Pattern a -> Pattern a
- Sound.Tidal.Context: e' :: Pattern Int -> Pattern Int -> Pattern a -> Pattern a
- Sound.Tidal.Context: echo :: Time -> Pattern a -> Pattern a
- Sound.Tidal.Context: efull :: Pattern Int -> Pattern Int -> Pattern a -> Pattern a -> Pattern a
- Sound.Tidal.Context: einv :: Pattern Int -> Pattern Int -> Pattern a -> Pattern a
- Sound.Tidal.Context: elem :: (Foldable t, Eq a) => a -> t a -> Bool
- Sound.Tidal.Context: elemIndex :: Eq a => a -> [a] -> Maybe Int
- Sound.Tidal.Context: elemIndices :: Eq a => a -> [a] -> [Int]
- Sound.Tidal.Context: elongate :: () => [TPat a] -> TPat a
- Sound.Tidal.Context: empty :: Alternative f => f a
- Sound.Tidal.Context: en :: [(Int, Int)] -> Pattern String -> Pattern String
- Sound.Tidal.Context: enclosingArc :: [Arc] -> Arc
- Sound.Tidal.Context: end :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: end_p :: Param
- Sound.Tidal.Context: enumFromThenTo' :: (Ord a, Enum a, Num a) => a -> a -> a -> Pattern a
- Sound.Tidal.Context: enumFromTo' :: (Ord a, Enum a) => a -> a -> Pattern a
- Sound.Tidal.Context: envEq :: Pattern Double
- Sound.Tidal.Context: envEqR :: Pattern Double
- Sound.Tidal.Context: envL :: Pattern Double
- Sound.Tidal.Context: envLR :: Pattern Double
- Sound.Tidal.Context: eoff :: Pattern Int -> Pattern Int -> Pattern Integer -> Pattern a -> Pattern a
- Sound.Tidal.Context: eventArc :: Event a -> Arc
- Sound.Tidal.Context: eventOffset :: Event a -> Time
- Sound.Tidal.Context: eventOnset :: Event a -> Time
- Sound.Tidal.Context: eventStart :: Event a -> Time
- Sound.Tidal.Context: every :: Pattern Int -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
- Sound.Tidal.Context: every' :: Pattern Int -> Pattern Int -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
- Sound.Tidal.Context: expression :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: expression_p :: Param
- Sound.Tidal.Context: fadeIn :: Time -> Pattern a -> Pattern a
- Sound.Tidal.Context: fadeIn' :: Time -> Time -> Pattern a -> Pattern a
- Sound.Tidal.Context: fadeOut :: Time -> Pattern a -> Pattern a
- Sound.Tidal.Context: fadeOut' :: Time -> Time -> Pattern a -> Pattern a
- Sound.Tidal.Context: fast :: Pattern Time -> Pattern a -> Pattern a
- Sound.Tidal.Context: fast' :: Pattern Time -> Pattern a -> Pattern a
- Sound.Tidal.Context: fastGap :: Time -> Pattern a -> Pattern a
- Sound.Tidal.Context: fastcat :: [Pattern a] -> Pattern a
- Sound.Tidal.Context: fastspread :: (a -> t -> Pattern b) -> [a] -> t -> Pattern b
- Sound.Tidal.Context: fill :: Pattern a -> Pattern a -> Pattern a
- Sound.Tidal.Context: filter :: () => a -> Bool -> [a] -> [a]
- Sound.Tidal.Context: filterJust :: Pattern (Maybe a) -> Pattern a
- Sound.Tidal.Context: filterOnsets :: Pattern a -> Pattern a
- Sound.Tidal.Context: filterOnsetsInRange :: Pattern a -> Pattern a
- Sound.Tidal.Context: filterStartInRange :: Pattern a -> Pattern a
- Sound.Tidal.Context: filterValues :: (a -> Bool) -> Pattern a -> Pattern a
- Sound.Tidal.Context: find :: Foldable t => a -> Bool -> t a -> Maybe a
- Sound.Tidal.Context: findIndex :: () => a -> Bool -> [a] -> Maybe Int
- Sound.Tidal.Context: findIndices :: () => a -> Bool -> [a] -> [Int]
- Sound.Tidal.Context: fit :: Int -> [a] -> Pattern Int -> Pattern a
- Sound.Tidal.Context: fit' :: Pattern Time -> Int -> Pattern Int -> Pattern Int -> Pattern a -> Pattern a
- Sound.Tidal.Context: flatpat :: Pattern [a] -> Pattern a
- Sound.Tidal.Context: float :: Parser Double
- Sound.Tidal.Context: foldEvery :: [Int] -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
- Sound.Tidal.Context: foldl :: Foldable t => b -> a -> b -> b -> t a -> b
- Sound.Tidal.Context: foldl' :: Foldable t => b -> a -> b -> b -> t a -> b
- Sound.Tidal.Context: foldl1 :: Foldable t => a -> a -> a -> t a -> a
- Sound.Tidal.Context: foldl1' :: () => a -> a -> a -> [a] -> a
- Sound.Tidal.Context: foldr :: Foldable t => a -> b -> b -> b -> t a -> b
- Sound.Tidal.Context: foldr1 :: Foldable t => a -> a -> a -> t a -> a
- Sound.Tidal.Context: follow :: (ParamType a, ParamType b) => Param -> Param -> (Pattern a -> Pattern b) -> ParamPattern -> ParamPattern
- Sound.Tidal.Context: follow' :: ParamType a => Param -> Param -> (Pattern a -> Pattern a) -> ParamPattern -> ParamPattern
- Sound.Tidal.Context: followF :: Param -> Param -> (Pattern Double -> Pattern Double) -> ParamPattern -> ParamPattern
- Sound.Tidal.Context: followI :: Param -> Param -> (Pattern Int -> Pattern Int) -> ParamPattern -> ParamPattern
- Sound.Tidal.Context: followS :: Param -> Param -> (Pattern String -> Pattern String) -> ParamPattern -> ParamPattern
- Sound.Tidal.Context: forkFinally :: () => IO a -> Either SomeException a -> IO () -> IO ThreadId
- Sound.Tidal.Context: forkIO :: IO () -> IO ThreadId
- Sound.Tidal.Context: forkIOWithUnmask :: forall a. () => IO a -> IO a -> IO () -> IO ThreadId
- Sound.Tidal.Context: forkOS :: IO () -> IO ThreadId
- Sound.Tidal.Context: forkOSWithUnmask :: forall a. () => IO a -> IO a -> IO () -> IO ThreadId
- Sound.Tidal.Context: forkOn :: Int -> IO () -> IO ThreadId
- Sound.Tidal.Context: forkOnWithUnmask :: Int -> forall a. () => IO a -> IO a -> IO () -> IO ThreadId
- Sound.Tidal.Context: frameRate :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: frameRate_p :: Param
- Sound.Tidal.Context: frames :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: frames_p :: Param
- Sound.Tidal.Context: fromNote :: Num a => Pattern String -> Pattern a
- Sound.Tidal.Context: fromThenTo :: Enumerable a => a -> a -> a -> Pattern a
- Sound.Tidal.Context: fromTo :: Enumerable a => a -> a -> Pattern a
- Sound.Tidal.Context: fromV :: ParamType a => Value -> Maybe a
- Sound.Tidal.Context: gain :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: gain_p :: Param
- Sound.Tidal.Context: gap :: Pattern Int -> ParamPattern -> ParamPattern
- Sound.Tidal.Context: gat :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: gate :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: gate_p :: Param
- Sound.Tidal.Context: genericDrop :: Integral i => i -> [a] -> [a]
- Sound.Tidal.Context: genericIndex :: Integral i => [a] -> i -> a
- Sound.Tidal.Context: genericLength :: Num i => [a] -> i
- Sound.Tidal.Context: genericReplicate :: Integral i => i -> a -> [a]
- Sound.Tidal.Context: genericSplitAt :: Integral i => i -> [a] -> ([a], [a])
- Sound.Tidal.Context: genericTake :: Integral i => i -> [a] -> [a]
- Sound.Tidal.Context: get :: ParamType a => Param -> ParamPattern -> Pattern a
- Sound.Tidal.Context: getChanContents :: () => Chan a -> IO [a]
- Sound.Tidal.Context: getClockIp :: IO String
- Sound.Tidal.Context: getCurrentBeat :: MVar Tempo -> IO Rational
- Sound.Tidal.Context: getF :: Param -> ParamPattern -> Pattern Double
- Sound.Tidal.Context: getI :: Param -> ParamPattern -> Pattern Int
- Sound.Tidal.Context: getLatency :: IO Double
- Sound.Tidal.Context: getMasterPort :: IO Int
- Sound.Tidal.Context: getNumCapabilities :: IO Int
- Sound.Tidal.Context: getS :: Param -> ParamPattern -> Pattern String
- Sound.Tidal.Context: getServerPort :: IO Int
- Sound.Tidal.Context: getSlavePort :: IO Int
- Sound.Tidal.Context: getTempo :: MVar Tempo -> IO Tempo
- Sound.Tidal.Context: ghost :: Pattern ParamMap -> Pattern ParamMap
- Sound.Tidal.Context: ghost' :: () => p -> Pattern ParamMap -> Pattern ParamMap
- Sound.Tidal.Context: ghost'' :: () => Time -> Pattern a -> Pattern a -> Pattern a -> Pattern a
- Sound.Tidal.Context: group :: Eq a => [a] -> [[a]]
- Sound.Tidal.Context: groupBy :: () => a -> a -> Bool -> [a] -> [[a]]
- Sound.Tidal.Context: groupByTime :: [Event a] -> [Event [a]]
- Sound.Tidal.Context: grp :: [Param] -> Pattern String -> ParamPattern
- Sound.Tidal.Context: harmonic :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: harmonic_p :: Param
- Sound.Tidal.Context: hasDefault :: Param -> Bool
- Sound.Tidal.Context: hasOffset :: Event a -> Bool
- Sound.Tidal.Context: hasOnset :: Event a -> Bool
- Sound.Tidal.Context: hasRequired :: Shape -> ParamMap -> Bool
- Sound.Tidal.Context: hatgrain :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: hatgrain_p :: Param
- Sound.Tidal.Context: hcutoff :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: hcutoff_p :: Param
- Sound.Tidal.Context: head :: () => [a] -> a
- Sound.Tidal.Context: hg :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: histpan :: Int -> Time -> [ParamPattern] -> ParamPattern
- Sound.Tidal.Context: hold :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: hold_p :: Param
- Sound.Tidal.Context: hours :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: hours_p :: Param
- Sound.Tidal.Context: hpf :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: hpf_p :: Param
- Sound.Tidal.Context: hpq :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: hpq_p :: Param
- Sound.Tidal.Context: hresonance :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: hresonance_p :: Param
- Sound.Tidal.Context: hurry :: Pattern Rational -> ParamPattern -> ParamPattern
- Sound.Tidal.Context: ifp :: (Int -> Bool) -> (Pattern a -> Pattern a) -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
- Sound.Tidal.Context: index :: Real b => b -> Pattern b -> Pattern c -> Pattern c
- Sound.Tidal.Context: infix 4 `notElem`
- Sound.Tidal.Context: infix 5 \\
- Sound.Tidal.Context: infixl 1 |/|
- Sound.Tidal.Context: infixl 2 #^^#
- Sound.Tidal.Context: infixl 3 #&&#
- Sound.Tidal.Context: infixl 4 <**>
- Sound.Tidal.Context: infixl 7 %
- Sound.Tidal.Context: infixl 9 @@
- Sound.Tidal.Context: infixr 5 ++
- Sound.Tidal.Context: infixr 6 <>
- Sound.Tidal.Context: inhabit :: [(String, Pattern a)] -> Pattern String -> Pattern a
- Sound.Tidal.Context: init :: () => [a] -> [a]
- Sound.Tidal.Context: initializeStreamType :: IO (MVar StreamType)
- Sound.Tidal.Context: initializeSyncType :: IO (MVar SyncType)
- Sound.Tidal.Context: inits :: () => [a] -> [[a]]
- Sound.Tidal.Context: insert :: Ord a => a -> [a] -> [a]
- Sound.Tidal.Context: insertBy :: () => a -> a -> Ordering -> a -> [a] -> [a]
- Sound.Tidal.Context: inside :: Pattern Time -> (Pattern a1 -> Pattern a) -> Pattern a1 -> Pattern a
- Sound.Tidal.Context: intOrFloat :: Parser Double
- Sound.Tidal.Context: integer :: Parser Integer
- Sound.Tidal.Context: intercalate :: () => [a] -> [[a]] -> [a]
- Sound.Tidal.Context: interlace :: ParamPattern -> ParamPattern -> ParamPattern
- Sound.Tidal.Context: interpolateIn :: Time -> Time -> [ParamPattern] -> ParamPattern
- Sound.Tidal.Context: intersect :: Eq a => [a] -> [a] -> [a]
- Sound.Tidal.Context: intersectBy :: () => a -> a -> Bool -> [a] -> [a] -> [a]
- Sound.Tidal.Context: intersperse :: () => a -> [a] -> [a]
- Sound.Tidal.Context: irand :: Num a => Int -> Pattern a
- Sound.Tidal.Context: isCurrentThreadBound :: IO Bool
- Sound.Tidal.Context: isEmptyMVar :: () => MVar a -> IO Bool
- Sound.Tidal.Context: isIn :: Arc -> Time -> Bool
- Sound.Tidal.Context: isInfixOf :: Eq a => [a] -> [a] -> Bool
- Sound.Tidal.Context: isPrefixOf :: Eq a => [a] -> [a] -> Bool
- Sound.Tidal.Context: isSubsequenceOf :: Eq a => [a] -> [a] -> Bool
- Sound.Tidal.Context: isSubset :: (Eq a) => [a] -> [a] -> Bool
- Sound.Tidal.Context: isSuffixOf :: Eq a => [a] -> [a] -> Bool
- Sound.Tidal.Context: iter :: Pattern Int -> Pattern c -> Pattern c
- Sound.Tidal.Context: iter' :: Pattern Int -> Pattern c -> Pattern c
- Sound.Tidal.Context: iterate :: () => a -> a -> a -> [a]
- Sound.Tidal.Context: iterate' :: () => a -> a -> a -> [a]
- Sound.Tidal.Context: jump :: Time -> [ParamPattern] -> ParamPattern
- Sound.Tidal.Context: jumpIn :: Int -> Time -> [ParamPattern] -> ParamPattern
- Sound.Tidal.Context: jumpIn' :: Int -> Time -> [ParamPattern] -> ParamPattern
- Sound.Tidal.Context: jumpMod :: Int -> Time -> [ParamPattern] -> ParamPattern
- Sound.Tidal.Context: jux :: ParamPattern -> Pattern ParamMap -> ParamPattern -> Pattern ParamMap
- Sound.Tidal.Context: jux' :: () => [t -> ParamPattern] -> t -> Pattern ParamMap
- Sound.Tidal.Context: jux4 :: ParamPattern -> Pattern ParamMap -> ParamPattern -> Pattern ParamMap
- Sound.Tidal.Context: juxBy :: Pattern Double -> ParamPattern -> Pattern ParamMap -> ParamPattern -> Pattern ParamMap
- Sound.Tidal.Context: juxcut :: ParamPattern -> Pattern ParamMap -> ParamPattern -> Pattern ParamMap
- Sound.Tidal.Context: juxcut' :: () => [t -> ParamPattern] -> t -> Pattern ParamMap
- Sound.Tidal.Context: killThread :: ThreadId -> IO ()
- Sound.Tidal.Context: kriole :: Pattern Int -> ParamPattern
- Sound.Tidal.Context: kriole_p :: Param
- Sound.Tidal.Context: lag :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: lagogo :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: lagogo_p :: Param
- Sound.Tidal.Context: last :: () => [a] -> a
- Sound.Tidal.Context: layer :: [a -> Pattern b] -> a -> Pattern b
- Sound.Tidal.Context: lbd :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: lch :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: lcl :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: lclap :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: lclap_p :: Param
- Sound.Tidal.Context: lclaves :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: lclaves_p :: Param
- Sound.Tidal.Context: lclhat :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: lclhat_p :: Param
- Sound.Tidal.Context: lcp :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: lcr :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: lcrash :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: lcrash_p :: Param
- Sound.Tidal.Context: legato :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: legato_p :: Param
- Sound.Tidal.Context: length :: Foldable t => t a -> Int
- Sound.Tidal.Context: leslie :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: leslie_p :: Param
- Sound.Tidal.Context: lexer :: () => GenTokenParser String u Identity
- Sound.Tidal.Context: lfo :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: lfo_p :: Param
- Sound.Tidal.Context: lfoc :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: lfocutoffint :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: lfocutoffint_p :: Param
- Sound.Tidal.Context: lfodelay :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: lfodelay_p :: Param
- Sound.Tidal.Context: lfoi :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: lfoint :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: lfoint_p :: Param
- Sound.Tidal.Context: lfop :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: lfopitchint :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: lfopitchint_p :: Param
- Sound.Tidal.Context: lfoshape :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: lfoshape_p :: Param
- Sound.Tidal.Context: lfosync :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: lfosync_p :: Param
- Sound.Tidal.Context: lhitom :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: lhitom_p :: Param
- Sound.Tidal.Context: lht :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: liftA :: Applicative f => a -> b -> f a -> f b
- Sound.Tidal.Context: liftA2 :: Applicative f => a -> b -> c -> f a -> f b -> f c
- Sound.Tidal.Context: liftA3 :: Applicative f => a -> b -> c -> d -> f a -> f b -> f c -> f d
- Sound.Tidal.Context: lindenmayer :: Int -> String -> String -> String
- Sound.Tidal.Context: lindenmayerI :: Num b => Int -> String -> String -> [b]
- Sound.Tidal.Context: lines :: String -> [String]
- Sound.Tidal.Context: linger :: Pattern Time -> Pattern a -> Pattern a
- Sound.Tidal.Context: listToPat :: [a] -> Pattern a
- Sound.Tidal.Context: lkick :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: lkick_p :: Param
- Sound.Tidal.Context: llotom :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: llotom_p :: Param
- Sound.Tidal.Context: llt :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: lock :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: lock_p :: Param
- Sound.Tidal.Context: logicalOnset' :: Integral a => Tempo -> a -> Double -> Double -> Double
- Sound.Tidal.Context: logicalTime :: Tempo -> Double -> Double
- Sound.Tidal.Context: loh :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: lookup :: Eq a => a -> [(a, b)] -> Maybe b
- Sound.Tidal.Context: loop :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: loopAt :: Pattern Time -> ParamPattern -> ParamPattern
- Sound.Tidal.Context: loopFirst :: Pattern a -> Pattern a
- Sound.Tidal.Context: loop_p :: Param
- Sound.Tidal.Context: lophat :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: lophat_p :: Param
- Sound.Tidal.Context: lpf :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: lpf_p :: Param
- Sound.Tidal.Context: lpq :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: lpq_p :: Param
- Sound.Tidal.Context: lrate :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: lrate_p :: Param
- Sound.Tidal.Context: lsize :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: lsize_p :: Param
- Sound.Tidal.Context: lsn :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: lsnare :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: lsnare_p :: Param
- Sound.Tidal.Context: make :: (a -> Value) -> Shape -> String -> Pattern a -> ParamPattern
- Sound.Tidal.Context: make' :: ParamType a => (a -> Value) -> Param -> Pattern a -> ParamPattern
- Sound.Tidal.Context: makeF :: Shape -> String -> Pattern Double -> ParamPattern
- Sound.Tidal.Context: makeI :: Shape -> String -> Pattern Int -> ParamPattern
- Sound.Tidal.Context: makeP :: ParamType a => Param -> Pattern a -> ParamPattern
- Sound.Tidal.Context: makeS :: Shape -> String -> Pattern String -> ParamPattern
- Sound.Tidal.Context: many :: Alternative f => f a -> f [a]
- Sound.Tidal.Context: map :: () => a -> b -> [a] -> [b]
- Sound.Tidal.Context: mapAccumL :: Traversable t => a -> b -> (a, c) -> a -> t b -> (a, t c)
- Sound.Tidal.Context: mapAccumR :: Traversable t => a -> b -> (a, c) -> a -> t b -> (a, t c)
- Sound.Tidal.Context: mapArc :: (Time -> Time) -> Arc -> Arc
- Sound.Tidal.Context: mapCycle :: (Time -> Time) -> Arc -> Arc
- Sound.Tidal.Context: mappend :: Monoid a => a -> a -> a
- Sound.Tidal.Context: mask :: Pattern a -> Pattern b -> Pattern b
- Sound.Tidal.Context: maximum :: (Foldable t, Ord a) => t a -> a
- Sound.Tidal.Context: maximumBy :: Foldable t => a -> a -> Ordering -> t a -> a
- Sound.Tidal.Context: maybeListToPat :: [Maybe a] -> Pattern a
- Sound.Tidal.Context: mconcat :: Monoid a => [a] -> a
- Sound.Tidal.Context: mempty :: Monoid a => a
- Sound.Tidal.Context: merge :: ParamPattern -> ParamPattern -> ParamPattern
- Sound.Tidal.Context: mergeNumWith :: Applicative f => Int -> Int -> Int -> Double -> Double -> Double -> f Map Param Value -> f Map Param Value -> f Map Param Value
- Sound.Tidal.Context: mergePlus :: Applicative f => f Map Param Value -> f Map Param Value -> f Map Param Value
- Sound.Tidal.Context: mergeWith :: (Ord k, Applicative f) => (k -> a -> a -> a) -> f (Map k a) -> f (Map k a) -> f (Map k a)
- Sound.Tidal.Context: metronome :: Pattern ParamMap
- Sound.Tidal.Context: midPoint :: Arc -> Time
- Sound.Tidal.Context: midichan :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: midichan_p :: Param
- Sound.Tidal.Context: midicmd :: Pattern String -> ParamPattern
- Sound.Tidal.Context: midicmd_p :: Param
- Sound.Tidal.Context: midinote :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: minimum :: (Foldable t, Ord a) => t a -> a
- Sound.Tidal.Context: minimumBy :: Foldable t => a -> a -> Ordering -> t a -> a
- Sound.Tidal.Context: minutes :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: minutes_p :: Param
- Sound.Tidal.Context: mirrorArc :: Time -> Arc -> Arc
- Sound.Tidal.Context: mixNums :: Double -> Value -> Value -> Value
- Sound.Tidal.Context: mkWeakMVar :: () => MVar a -> IO () -> IO Weak MVar a
- Sound.Tidal.Context: mkWeakThreadId :: ThreadId -> IO Weak ThreadId
- Sound.Tidal.Context: modifyMVar :: () => MVar a -> a -> IO (a, b) -> IO b
- Sound.Tidal.Context: modifyMVarMasked :: () => MVar a -> a -> IO (a, b) -> IO b
- Sound.Tidal.Context: modifyMVarMasked_ :: () => MVar a -> a -> IO a -> IO ()
- Sound.Tidal.Context: modifyMVar_ :: () => MVar a -> a -> IO a -> IO ()
- Sound.Tidal.Context: modwheel :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: modwheel_p :: Param
- Sound.Tidal.Context: mortal :: Time -> Time -> Time -> [ParamPattern] -> ParamPattern
- Sound.Tidal.Context: mtranspose :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: mtranspose_p :: Param
- Sound.Tidal.Context: multiModeCpsUtils :: CpsUtils -> CpsUtils -> MVar SyncType -> IO CpsUtils
- Sound.Tidal.Context: multiModeSetters :: IO Rational -> IO Rational -> MVar SyncType -> MVar StreamType -> IO (ParamPattern -> IO ())
- Sound.Tidal.Context: myThreadId :: IO ThreadId
- Sound.Tidal.Context: n :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: nToOrbit :: ParamPattern -> ParamPattern
- Sound.Tidal.Context: n_p :: Param
- Sound.Tidal.Context: natural :: Parser Integer
- Sound.Tidal.Context: naturalOrFloat :: Parser (Either Integer Double)
- Sound.Tidal.Context: never :: (Pattern a -> Pattern a) -> Pattern a -> Pattern a
- Sound.Tidal.Context: newChan :: () => IO Chan a
- Sound.Tidal.Context: newEmptyMVar :: () => IO MVar a
- Sound.Tidal.Context: newMVar :: () => a -> IO MVar a
- Sound.Tidal.Context: newQSem :: Int -> IO QSem
- Sound.Tidal.Context: newQSemN :: Int -> IO QSemN
- Sound.Tidal.Context: newtype Const a (b :: k) :: forall k. () => * -> k -> *
- Sound.Tidal.Context: newtype All
- Sound.Tidal.Context: newtype Any
- Sound.Tidal.Context: newtype Dual a
- Sound.Tidal.Context: newtype Endo a
- Sound.Tidal.Context: newtype First a
- Sound.Tidal.Context: newtype Last a
- Sound.Tidal.Context: newtype Pattern a
- Sound.Tidal.Context: newtype Product a
- Sound.Tidal.Context: newtype Sum a
- Sound.Tidal.Context: newtype WrappedArrow (a :: * -> * -> *) b c
- Sound.Tidal.Context: newtype WrappedMonad (m :: * -> *) a
- Sound.Tidal.Context: newtype ZipList a
- Sound.Tidal.Context: newtype Alt (f :: k -> *) (a :: k) :: forall k. () => k -> * -> k -> *
- Sound.Tidal.Context: nextSam :: Time -> Time
- Sound.Tidal.Context: noOv :: String -> a
- Sound.Tidal.Context: not' :: Applicative f => f Bool -> f Bool
- Sound.Tidal.Context: notElem :: (Foldable t, Eq a) => a -> t a -> Bool
- Sound.Tidal.Context: note :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: note_p :: Param
- Sound.Tidal.Context: nub :: Eq a => [a] -> [a]
- Sound.Tidal.Context: nubBy :: () => a -> a -> Bool -> [a] -> [a]
- Sound.Tidal.Context: nudge :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: nudgeTempo :: Tempo -> Double -> Tempo
- Sound.Tidal.Context: nudge_p :: Param
- Sound.Tidal.Context: null :: Foldable t => t a -> Bool
- Sound.Tidal.Context: numerator :: () => Ratio a -> a
- Sound.Tidal.Context: octave :: Pattern Int -> ParamPattern
- Sound.Tidal.Context: octaveRatio :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: octaveRatio_p :: Param
- Sound.Tidal.Context: octave_p :: Param
- Sound.Tidal.Context: off :: Pattern Time -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
- Sound.Tidal.Context: offadd :: Num a => Pattern Time -> Pattern a -> Pattern a -> Pattern a
- Sound.Tidal.Context: offset :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: offsetIn :: Arc -> Event a -> Bool
- Sound.Tidal.Context: offset_p :: Param
- Sound.Tidal.Context: often :: (Pattern a -> Pattern a) -> Pattern a -> Pattern a
- Sound.Tidal.Context: ohdecay :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: onTick :: Backend a -> Shape -> MVar (ParamPattern) -> Tempo -> Int -> IO ()
- Sound.Tidal.Context: onTick' :: Backend a -> Shape -> MVar (ParamPattern, [ParamPattern]) -> Tempo -> Int -> IO ()
- Sound.Tidal.Context: onsetIn :: Arc -> Event a -> Bool
- Sound.Tidal.Context: ophatdecay :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: ophatdecay_p :: Param
- Sound.Tidal.Context: optional :: Alternative f => f a -> f Maybe a
- Sound.Tidal.Context: or :: Foldable t => t Bool -> Bool
- Sound.Tidal.Context: orbit :: Pattern Int -> ParamPattern
- Sound.Tidal.Context: orbit_p :: Param
- Sound.Tidal.Context: outside :: Pattern Time -> (Pattern a1 -> Pattern a) -> Pattern a1 -> Pattern a
- Sound.Tidal.Context: overlay :: Pattern a -> Pattern a -> Pattern a
- Sound.Tidal.Context: p :: (Enumerable a, Parseable a) => String -> Pattern a
- Sound.Tidal.Context: pBool :: Parser (TPat Bool)
- Sound.Tidal.Context: pColour :: Parser (TPat ColourD)
- Sound.Tidal.Context: pDouble :: Parser (TPat Double)
- Sound.Tidal.Context: pE :: Parseable a => TPat a -> Parser (TPat a)
- Sound.Tidal.Context: pF :: String -> Maybe Double -> (Pattern Double -> ParamPattern, Param)
- Sound.Tidal.Context: pI :: String -> Maybe Int -> (Pattern Int -> ParamPattern, Param)
- Sound.Tidal.Context: pIntegral :: Parseable a => Integral a => Parser (TPat a)
- Sound.Tidal.Context: pMult :: Parseable a => TPat a -> Parser (TPat a)
- Sound.Tidal.Context: pPart :: Parseable a => Parser (TPat a) -> Parser [TPat a]
- Sound.Tidal.Context: pPolyIn :: Parseable a => Parser (TPat a) -> Parser (TPat a)
- Sound.Tidal.Context: pPolyOut :: Parseable a => Parser (TPat a) -> Parser (TPat a)
- Sound.Tidal.Context: pRand :: Parseable a => TPat a -> Parser (TPat a)
- Sound.Tidal.Context: pRatio :: Parser (Rational)
- Sound.Tidal.Context: pRational :: Parser (TPat Rational)
- Sound.Tidal.Context: pReplicate :: Parseable a => TPat a -> Parser [TPat a]
- Sound.Tidal.Context: pS :: String -> Maybe String -> (Pattern String -> ParamPattern, Param)
- Sound.Tidal.Context: pSequence :: Parseable a => Parser (TPat a) -> GenParser Char () (TPat a)
- Sound.Tidal.Context: pSequenceN :: Parseable a => Parser (TPat a) -> GenParser Char () (Int, TPat a)
- Sound.Tidal.Context: pSingle :: Parseable a => Parser (TPat a) -> Parser (TPat a)
- Sound.Tidal.Context: pStretch :: Parseable a => TPat a -> Parser [TPat a]
- Sound.Tidal.Context: pString :: Parser (String)
- Sound.Tidal.Context: pVocable :: Parser (TPat String)
- Sound.Tidal.Context: palindrome :: Pattern a -> Pattern a
- Sound.Tidal.Context: pan :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: pan_p :: Param
- Sound.Tidal.Context: panorient :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: panorient_p :: Param
- Sound.Tidal.Context: panspan :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: panspan_p :: Param
- Sound.Tidal.Context: pansplay :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: pansplay_p :: Param
- Sound.Tidal.Context: panwidth :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: panwidth_p :: Param
- Sound.Tidal.Context: param :: Shape -> String -> Param
- Sound.Tidal.Context: parens :: Parser a -> Parser a
- Sound.Tidal.Context: parseEspTempo :: [Datum] -> Maybe Tempo
- Sound.Tidal.Context: parseInt :: Parser Int
- Sound.Tidal.Context: parseIntNote :: Integral i => Parser i
- Sound.Tidal.Context: parseLMRule :: String -> [(String, String)]
- Sound.Tidal.Context: parseLMRule' :: String -> [(Char, String)]
- Sound.Tidal.Context: parseNote :: Num a => Parser a
- Sound.Tidal.Context: parseRhythm :: Parseable a => Parser (TPat a) -> String -> TPat a
- Sound.Tidal.Context: parseTPat :: Parseable a => String -> TPat a
- Sound.Tidal.Context: partition :: () => a -> Bool -> [a] -> ([a], [a])
- Sound.Tidal.Context: patToList :: Pattern a -> [a]
- Sound.Tidal.Context: pequal :: Ord a => Time -> Pattern a -> Pattern a -> Bool
- Sound.Tidal.Context: permstep :: RealFrac b => Int -> [a] -> Pattern b -> Pattern a
- Sound.Tidal.Context: permutations :: () => [a] -> [[a]]
- Sound.Tidal.Context: phasdp :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: phaserdepth :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: phaserdepth_p :: Param
- Sound.Tidal.Context: phaserrate :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: phaserrate_p :: Param
- Sound.Tidal.Context: phasr :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: pick :: String -> Int -> String
- Sound.Tidal.Context: pit1 :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: pit2 :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: pit3 :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: pitch1 :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: pitch1_p :: Param
- Sound.Tidal.Context: pitch2 :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: pitch2_p :: Param
- Sound.Tidal.Context: pitch3 :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: pitch3_p :: Param
- Sound.Tidal.Context: playFor :: Time -> Time -> Pattern a -> Pattern a
- Sound.Tidal.Context: playWhen :: (Time -> Bool) -> Pattern a -> Pattern a
- Sound.Tidal.Context: ply :: Pattern Int -> Pattern a -> Pattern a
- Sound.Tidal.Context: points :: [Event a] -> [Time]
- Sound.Tidal.Context: por :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: portamento :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: portamento_p :: Param
- Sound.Tidal.Context: prep :: (Time, Time) -> Pattern String -> Pattern b -> Pattern b
- Sound.Tidal.Context: preplace :: (Time, Time) -> Pattern String -> Pattern b -> Pattern b
- Sound.Tidal.Context: preplace1 :: Pattern String -> Pattern b -> Pattern b
- Sound.Tidal.Context: preplaceWith :: (a -> b -> c) -> (Time, Time) -> Pattern a -> Pattern b -> Pattern c
- Sound.Tidal.Context: preplaceWith1 :: (a -> b -> c) -> Pattern a -> Pattern b -> Pattern c
- Sound.Tidal.Context: product :: (Foldable t, Num a) => t a -> a
- Sound.Tidal.Context: progNum :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: progNum_p :: Param
- Sound.Tidal.Context: prot :: Time -> Int -> Pattern a -> Pattern a
- Sound.Tidal.Context: prot1 :: Int -> Pattern a -> Pattern a
- Sound.Tidal.Context: protate :: Time -> Int -> Pattern a -> Pattern a
- Sound.Tidal.Context: prr :: Int -> (Time, Time) -> Pattern String -> Pattern b -> Pattern b
- Sound.Tidal.Context: prrw :: (a -> b -> c) -> Int -> (Time, Time) -> Pattern a -> Pattern b -> Pattern c
- Sound.Tidal.Context: prw :: (a -> b -> c) -> (Time, Time) -> Pattern a -> Pattern b -> Pattern c
- Sound.Tidal.Context: prw1 :: (a -> b -> c) -> Pattern a -> Pattern b -> Pattern c
- Sound.Tidal.Context: pure :: Applicative f => a -> f a
- Sound.Tidal.Context: putMVar :: () => MVar a -> a -> IO ()
- Sound.Tidal.Context: quad :: Time -> Pattern a -> Pattern a
- Sound.Tidal.Context: r :: (Enumerable a, Parseable a) => String -> Pattern a -> IO (Pattern a)
- Sound.Tidal.Context: rand :: Pattern Double
- Sound.Tidal.Context: rand4 :: Pattern Double
- Sound.Tidal.Context: randArcs :: Int -> Pattern [Arc]
- Sound.Tidal.Context: randStruct :: Int -> Pattern Int
- Sound.Tidal.Context: randcat :: [Pattern a] -> Pattern a
- Sound.Tidal.Context: randslice :: Int -> ParamPattern -> ParamPattern
- Sound.Tidal.Context: rarely :: (Pattern a -> Pattern a) -> Pattern a -> Pattern a
- Sound.Tidal.Context: ratsine :: Pattern Double
- Sound.Tidal.Context: readChan :: () => Chan a -> IO a
- Sound.Tidal.Context: readMVar :: () => MVar a -> IO a
- Sound.Tidal.Context: readTempo :: String -> Tempo
- Sound.Tidal.Context: rel :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: release :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: release_p :: Param
- Sound.Tidal.Context: removeClient :: TConnection -> ClientState -> ClientState
- Sound.Tidal.Context: repeat :: () => a -> [a]
- Sound.Tidal.Context: repeatCycles :: Int -> Pattern a -> Pattern a
- Sound.Tidal.Context: replicate :: () => Int -> a -> [a]
- Sound.Tidal.Context: required :: Shape -> [Param]
- Sound.Tidal.Context: resonance :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: resonance_p :: Param
- Sound.Tidal.Context: rev :: Pattern a -> Pattern a
- Sound.Tidal.Context: revArc :: Arc -> Pattern a -> Pattern a
- Sound.Tidal.Context: reverse :: () => [a] -> [a]
- Sound.Tidal.Context: room :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: room_p :: Param
- Sound.Tidal.Context: rotL :: Time -> Pattern a -> Pattern a
- Sound.Tidal.Context: rotR :: Time -> Pattern a -> Pattern a
- Sound.Tidal.Context: rtsSupportsBoundThreads :: Bool
- Sound.Tidal.Context: run :: (Enum a, Num a) => Pattern a -> Pattern a
- Sound.Tidal.Context: runClient :: IO ((MVar Tempo, MVar Double, MVar Double))
- Sound.Tidal.Context: runClientEsp :: IO (MVar Tempo, MVar Double)
- Sound.Tidal.Context: runInBoundThread :: () => IO a -> IO a
- Sound.Tidal.Context: runInUnboundThread :: () => IO a -> IO a
- Sound.Tidal.Context: runWith :: Integer -> (Pattern b -> Pattern b) -> Pattern b -> Pattern b
- Sound.Tidal.Context: runWith' :: Integral a => a -> (Pattern b -> Pattern b) -> Pattern b -> Pattern b
- Sound.Tidal.Context: s :: Pattern String -> ParamPattern
- Sound.Tidal.Context: s' :: Pattern String -> ParamPattern
- Sound.Tidal.Context: s_p :: Param
- Sound.Tidal.Context: sag :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: sagogo :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: sagogo_p :: Param
- Sound.Tidal.Context: sam :: Time -> Time
- Sound.Tidal.Context: samples :: Applicative f => f String -> f Int -> f String
- Sound.Tidal.Context: samples' :: Applicative f => f String -> f Int -> f String
- Sound.Tidal.Context: saw :: (Fractional a, Real a) => Pattern a
- Sound.Tidal.Context: saw1 :: (Fractional a, Real a) => Pattern a
- Sound.Tidal.Context: sawrat :: Pattern Double
- Sound.Tidal.Context: sawrat1 :: Pattern Double
- Sound.Tidal.Context: sawwave :: (Fractional a, Real a) => Pattern a
- Sound.Tidal.Context: sawwave1 :: (Fractional a, Real a) => Pattern a
- Sound.Tidal.Context: sawwave4 :: Pattern Double
- Sound.Tidal.Context: scBackend :: String -> IO (Backend a)
- Sound.Tidal.Context: scSlang :: String -> OscSlang
- Sound.Tidal.Context: scStream :: String -> [Param] -> Double -> IO (ParamPattern -> IO (), Shape)
- Sound.Tidal.Context: scale :: (Functor f, Num b) => b -> b -> f b -> f b
- Sound.Tidal.Context: scaleP :: Num a => Pattern String -> Pattern Int -> Pattern a
- Sound.Tidal.Context: scaleSieve :: Int -> Sieve Bool -> Pattern Int -> Pattern Int
- Sound.Tidal.Context: scalex :: (Functor f, Floating b) => b -> b -> f b -> f b
- Sound.Tidal.Context: scan :: (Enum a, Num a) => Pattern a -> Pattern a
- Sound.Tidal.Context: scanl :: () => b -> a -> b -> b -> [a] -> [b]
- Sound.Tidal.Context: scanl' :: () => b -> a -> b -> b -> [a] -> [b]
- Sound.Tidal.Context: scanl1 :: () => a -> a -> a -> [a] -> [a]
- Sound.Tidal.Context: scanr :: () => a -> b -> b -> b -> [a] -> [b]
- Sound.Tidal.Context: scanr1 :: () => a -> a -> a -> [a] -> [a]
- Sound.Tidal.Context: scl :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: sclap :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: sclap_p :: Param
- Sound.Tidal.Context: sclaves :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: sclaves_p :: Param
- Sound.Tidal.Context: scp :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: scr :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: scramble :: Int -> Pattern a -> Pattern a
- Sound.Tidal.Context: scrash :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: scrash_p :: Param
- Sound.Tidal.Context: seconds :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: seconds_p :: Param
- Sound.Tidal.Context: segment :: Pattern a -> Pattern [a]
- Sound.Tidal.Context: segment' :: [Event a] -> [Event a]
- Sound.Tidal.Context: semitone :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: semitone_p :: Param
- Sound.Tidal.Context: sendCps :: Connection -> MVar Double -> IO ()
- Sound.Tidal.Context: sendEspTempo :: Real t => t -> IO ()
- Sound.Tidal.Context: sendNudge :: Connection -> MVar Double -> IO ()
- Sound.Tidal.Context: sendTempo :: [Connection] -> Tempo -> IO ()
- Sound.Tidal.Context: seqP :: [(Time, Time, Pattern a)] -> Pattern a
- Sound.Tidal.Context: seqPLoop :: [(Time, Time, Pattern a)] -> Pattern a
- Sound.Tidal.Context: seqToRelOnsetDeltas :: Arc -> Pattern a -> [(Double, Double, a)]
- Sound.Tidal.Context: serverAct :: String -> ServerMode -> MVar Tempo -> MVar ClientState -> IO ()
- Sound.Tidal.Context: serverApp :: MVar Tempo -> MVar ServerMode -> MVar ClientState -> ServerApp
- Sound.Tidal.Context: serverLoop :: TConnection -> MVar Tempo -> MVar ServerMode -> MVar ClientState -> IO ()
- Sound.Tidal.Context: setCps :: Double -> ServerMode -> MVar Tempo -> MVar ClientState -> IO ()
- Sound.Tidal.Context: setNudge :: Double -> ServerMode -> MVar Tempo -> MVar ClientState -> IO ()
- Sound.Tidal.Context: setNumCapabilities :: Int -> IO ()
- Sound.Tidal.Context: setSlave :: MVar ServerMode -> IO ()
- Sound.Tidal.Context: setter :: MVar (a, [a]) -> a -> IO ()
- Sound.Tidal.Context: sew :: Pattern Bool -> Pattern a -> Pattern a -> Pattern a
- Sound.Tidal.Context: shape :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: shape_p :: Param
- Sound.Tidal.Context: showArc :: Arc -> String
- Sound.Tidal.Context: showEvent :: (Show a) => Event a -> String
- Sound.Tidal.Context: showTime :: (Show a, Integral a) => Ratio a -> String
- Sound.Tidal.Context: showToColour :: Show a => a -> ColourD
- Sound.Tidal.Context: shuffle :: Int -> Pattern a -> Pattern a
- Sound.Tidal.Context: sieveToInts :: Int -> Sieve Bool -> [Int]
- Sound.Tidal.Context: sieveToList :: Int -> Sieve a -> [a]
- Sound.Tidal.Context: sieveToPat :: Int -> Sieve Bool -> Pattern String
- Sound.Tidal.Context: sieveToString :: Int -> Sieve Bool -> [Char]
- Sound.Tidal.Context: sig :: (Time -> a) -> Pattern a
- Sound.Tidal.Context: sign :: Parser Sign
- Sound.Tidal.Context: signalQSem :: QSem -> IO ()
- Sound.Tidal.Context: signalQSemN :: QSemN -> Int -> IO ()
- Sound.Tidal.Context: silence :: Pattern a
- Sound.Tidal.Context: sine :: Fractional a => Pattern a
- Sound.Tidal.Context: sine1 :: Fractional a => Pattern a
- Sound.Tidal.Context: sineAmp :: Fractional a => a -> Pattern a
- Sound.Tidal.Context: sineAmp1 :: Fractional a => a -> Pattern a
- Sound.Tidal.Context: sinerat :: Pattern Double
- Sound.Tidal.Context: sinerat1 :: Pattern Double
- Sound.Tidal.Context: sinewave :: Fractional a => Pattern a
- Sound.Tidal.Context: sinewave1 :: Fractional a => Pattern a
- Sound.Tidal.Context: sinewave4 :: Pattern Double
- Sound.Tidal.Context: size :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: size_p :: Param
- Sound.Tidal.Context: slave :: MVar ServerMode -> MVar ClientState -> IO ()
- Sound.Tidal.Context: slaveAct :: String -> MVar ServerMode -> MVar ClientState -> Message -> IO ()
- Sound.Tidal.Context: sld :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: slice :: Pattern Int -> Pattern Int -> ParamPattern -> ParamPattern
- Sound.Tidal.Context: sliceArc :: Arc -> Pattern a -> Pattern a
- Sound.Tidal.Context: slide :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: slide_p :: Param
- Sound.Tidal.Context: slow :: Pattern Time -> Pattern a -> Pattern a
- Sound.Tidal.Context: slow' :: Pattern Time -> Pattern a -> Pattern a
- Sound.Tidal.Context: slowcat :: [Pattern a] -> Pattern a
- Sound.Tidal.Context: slowspread :: (a -> t -> Pattern b) -> [a] -> t -> Pattern b
- Sound.Tidal.Context: slowstepSieve :: Pattern Time -> Int -> String -> Sieve Bool -> Pattern String
- Sound.Tidal.Context: slowstripe :: Pattern Int -> Pattern a -> Pattern a
- Sound.Tidal.Context: smash :: Pattern Int -> [Pattern Time] -> ParamPattern -> Pattern ParamMap
- Sound.Tidal.Context: smash' :: Int -> [Pattern Time] -> ParamPattern -> Pattern ParamMap
- Sound.Tidal.Context: some :: Alternative f => f a -> f [a]
- Sound.Tidal.Context: someCycles :: (Pattern a -> Pattern a) -> Pattern a -> Pattern a
- Sound.Tidal.Context: someCyclesBy :: Double -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
- Sound.Tidal.Context: somecycles :: (Pattern a -> Pattern a) -> Pattern a -> Pattern a
- Sound.Tidal.Context: somecyclesBy :: Double -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
- Sound.Tidal.Context: sometimes :: (Pattern a -> Pattern a) -> Pattern a -> Pattern a
- Sound.Tidal.Context: sometimesBy :: Double -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
- Sound.Tidal.Context: songPtr :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: songPtr_p :: Param
- Sound.Tidal.Context: sort :: Ord a => [a] -> [a]
- Sound.Tidal.Context: sortBy :: () => a -> a -> Ordering -> [a] -> [a]
- Sound.Tidal.Context: sortOn :: Ord b => a -> b -> [a] -> [a]
- Sound.Tidal.Context: sound :: Pattern String -> ParamPattern
- Sound.Tidal.Context: soundToOrbit :: [String] -> ParamPattern -> ParamPattern
- Sound.Tidal.Context: spaceOut :: [Time] -> Pattern a -> Pattern a
- Sound.Tidal.Context: span :: () => a -> Bool -> [a] -> ([a], [a])
- Sound.Tidal.Context: sparsity :: Pattern Time -> Pattern a -> Pattern a
- Sound.Tidal.Context: speed :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: speed_p :: Param
- Sound.Tidal.Context: spin :: Pattern Int -> ParamPattern -> ParamPattern
- Sound.Tidal.Context: split :: Time -> [Event a] -> [Event a]
- Sound.Tidal.Context: splitAt :: () => Int -> [a] -> ([a], [a])
- Sound.Tidal.Context: splitAtSam :: Pattern a -> Pattern a
- Sound.Tidal.Context: splitFeet :: [TPat t] -> [[TPat t]]
- Sound.Tidal.Context: splitQueries :: Pattern a -> Pattern a
- Sound.Tidal.Context: spread :: (a -> t -> Pattern b) -> [a] -> t -> Pattern b
- Sound.Tidal.Context: spread' :: Monad m => (a -> b -> m c) -> m a -> b -> m c
- Sound.Tidal.Context: spreadChoose :: (t -> t1 -> Pattern b) -> [t] -> t1 -> Pattern b
- Sound.Tidal.Context: spreadf :: () => p1 -> p2 -> [a -> Pattern b] -> a -> Pattern b
- Sound.Tidal.Context: spreadr :: (t -> t1 -> Pattern b) -> [t] -> t1 -> Pattern b
- Sound.Tidal.Context: square :: (Fractional a, Real a) => Pattern a
- Sound.Tidal.Context: square1 :: (Fractional a, Real a) => Pattern a
- Sound.Tidal.Context: squarewave :: (Fractional a, Real a) => Pattern a
- Sound.Tidal.Context: squarewave1 :: (Fractional a, Real a) => Pattern a
- Sound.Tidal.Context: stack :: [Pattern a] -> Pattern a
- Sound.Tidal.Context: stackwith :: Pattern ParamMap -> [ParamPattern] -> Pattern ParamMap
- Sound.Tidal.Context: start :: Backend a -> Shape -> IO (MVar (ParamPattern))
- Sound.Tidal.Context: startServer :: IO (ThreadId)
- Sound.Tidal.Context: state :: Backend a -> Shape -> IO (MVar (ParamPattern, [ParamPattern]))
- Sound.Tidal.Context: stateEsp :: Backend a -> Shape -> IO (MVar (ParamPattern, [ParamPattern]))
- Sound.Tidal.Context: std :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: step :: String -> String -> Pattern String
- Sound.Tidal.Context: step' :: [String] -> String -> Pattern String
- Sound.Tidal.Context: stepSieve :: Int -> String -> Sieve Bool -> Pattern String
- Sound.Tidal.Context: steps :: [(String, String)] -> Pattern String
- Sound.Tidal.Context: stepsPerOctave :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: stepsPerOctave_p :: Param
- Sound.Tidal.Context: stream :: Backend a -> Shape -> IO (ParamPattern -> IO ())
- Sound.Tidal.Context: streamEsp :: Backend a -> Shape -> IO (ParamPattern -> IO ())
- Sound.Tidal.Context: streamcallback :: (ParamPattern -> IO ()) -> Backend a -> Shape -> IO (ParamPattern -> IO ())
- Sound.Tidal.Context: stretch :: Pattern a -> Pattern a
- Sound.Tidal.Context: striate :: Pattern Int -> ParamPattern -> ParamPattern
- Sound.Tidal.Context: striate' :: Pattern Int -> Pattern Double -> ParamPattern -> ParamPattern
- Sound.Tidal.Context: striateL :: Pattern Int -> Pattern Int -> ParamPattern -> ParamPattern
- Sound.Tidal.Context: striateL' :: Pattern Int -> Pattern Double -> Pattern Int -> ParamPattern -> ParamPattern
- Sound.Tidal.Context: striateO :: Pattern Int -> Pattern Double -> ParamPattern -> ParamPattern
- Sound.Tidal.Context: stringToColour :: String -> ColourD
- Sound.Tidal.Context: stripPrefix :: Eq a => [a] -> [a] -> Maybe [a]
- Sound.Tidal.Context: stripe :: Pattern Int -> Pattern a -> Pattern a
- Sound.Tidal.Context: struct :: Pattern String -> Pattern a -> Pattern a
- Sound.Tidal.Context: stt :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: stut :: Pattern Integer -> Pattern Double -> Pattern Rational -> ParamPattern -> ParamPattern
- Sound.Tidal.Context: stut' :: Pattern Int -> Pattern Time -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
- Sound.Tidal.Context: stutter :: Integral i => i -> Time -> Pattern a -> Pattern a
- Sound.Tidal.Context: stutterdepth :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: stutterdepth_p :: Param
- Sound.Tidal.Context: stuttertime :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: stuttertime_p :: Param
- Sound.Tidal.Context: stutx :: Pattern Int -> Pattern Time -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
- Sound.Tidal.Context: subArc :: Arc -> Arc -> Maybe Arc
- Sound.Tidal.Context: subsequences :: () => [a] -> [[a]]
- Sound.Tidal.Context: substruct :: Pattern String -> Pattern b -> Pattern b
- Sound.Tidal.Context: substruct' :: Pattern Int -> Pattern a -> Pattern a
- Sound.Tidal.Context: sum :: (Foldable t, Num a) => t a -> a
- Sound.Tidal.Context: superDirtBackend :: () => Int -> IO Backend a
- Sound.Tidal.Context: superDirtSetters :: IO Time -> IO (ParamPattern -> IO (), (Time -> [ParamPattern] -> ParamPattern) -> ParamPattern -> IO ())
- Sound.Tidal.Context: superDirtSettersEsp :: IO Time -> IO (ParamPattern -> IO (), (Time -> [ParamPattern] -> ParamPattern) -> ParamPattern -> IO ())
- Sound.Tidal.Context: superDirtSlang :: OscSlang
- Sound.Tidal.Context: superDirtState :: Int -> IO MVar (ParamPattern, [ParamPattern])
- Sound.Tidal.Context: superDirts :: [Int] -> IO [(ParamPattern -> IO (), (Time -> [ParamPattern] -> ParamPattern) -> ParamPattern -> IO ())]
- Sound.Tidal.Context: supercollider :: [Param] -> Double -> Shape
- Sound.Tidal.Context: superimpose :: (Pattern a -> Pattern a) -> Pattern a -> Pattern a
- Sound.Tidal.Context: superwash :: (Pattern a -> Pattern a) -> (Pattern a -> Pattern a) -> Time -> Time -> Time -> Time -> [Pattern a] -> Pattern a
- Sound.Tidal.Context: sus :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: sustain :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: sustain_p :: Param
- Sound.Tidal.Context: sustainpedal :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: sustainpedal_p :: Param
- Sound.Tidal.Context: swapMVar :: () => MVar a -> a -> IO a
- Sound.Tidal.Context: swing :: Pattern Time -> Pattern a -> Pattern a
- Sound.Tidal.Context: swingBy :: Pattern Time -> Pattern Time -> Pattern a -> Pattern a
- Sound.Tidal.Context: symbol :: String -> Parser String
- Sound.Tidal.Context: sz :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: tabby :: () => Integer -> Pattern a -> Pattern a -> Pattern a
- Sound.Tidal.Context: tail :: () => [a] -> [a]
- Sound.Tidal.Context: tails :: () => [a] -> [[a]]
- Sound.Tidal.Context: take :: () => Int -> [a] -> [a]
- Sound.Tidal.Context: takeMVar :: () => MVar a -> IO a
- Sound.Tidal.Context: takeWhile :: () => a -> Bool -> [a] -> [a]
- Sound.Tidal.Context: tdecay :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: temporalParam :: (a -> Pattern b -> Pattern c) -> (Pattern a -> Pattern b -> Pattern c)
- Sound.Tidal.Context: temporalParam' :: (a -> Pattern b -> Pattern c) -> (Pattern a -> Pattern b -> Pattern c)
- Sound.Tidal.Context: temporalParam2 :: (a -> b -> Pattern c -> Pattern d) -> (Pattern a -> Pattern b -> Pattern c -> Pattern d)
- Sound.Tidal.Context: temporalParam2' :: (a -> b -> Pattern c -> Pattern d) -> (Pattern a -> Pattern b -> Pattern c -> Pattern d)
- Sound.Tidal.Context: temporalParam3 :: (a -> b -> c -> Pattern d -> Pattern e) -> (Pattern a -> Pattern b -> Pattern c -> Pattern d -> Pattern e)
- Sound.Tidal.Context: temporalParam3' :: (a -> b -> c -> Pattern d -> Pattern e) -> (Pattern a -> Pattern b -> Pattern c -> Pattern d -> Pattern e)
- Sound.Tidal.Context: threadCapability :: ThreadId -> IO (Int, Bool)
- Sound.Tidal.Context: threadDelay :: Int -> IO ()
- Sound.Tidal.Context: threadWaitRead :: Fd -> IO ()
- Sound.Tidal.Context: threadWaitReadSTM :: Fd -> IO (STM (), IO ())
- Sound.Tidal.Context: threadWaitWrite :: Fd -> IO ()
- Sound.Tidal.Context: threadWaitWriteSTM :: Fd -> IO (STM (), IO ())
- Sound.Tidal.Context: throwTo :: Exception e => ThreadId -> e -> IO ()
- Sound.Tidal.Context: ticksPerCycle :: Num p => p
- Sound.Tidal.Context: tidal_version :: [Char]
- Sound.Tidal.Context: timeCat :: [(Time, Pattern a)] -> Pattern a
- Sound.Tidal.Context: timeLoop :: Pattern Time -> Pattern a -> Pattern a
- Sound.Tidal.Context: timeToRand :: RealFrac r => r -> Double
- Sound.Tidal.Context: timedValues :: Pattern a -> Pattern (Arc, a)
- Sound.Tidal.Context: toPat :: Enumerable a => TPat a -> Pattern a
- Sound.Tidal.Context: toScale :: Num a => [a] -> Pattern Int -> Pattern a
- Sound.Tidal.Context: toScale' :: Num a => Int -> [a] -> Pattern Int -> Pattern a
- Sound.Tidal.Context: toV :: ParamType a => a -> Value
- Sound.Tidal.Context: tomdecay :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: tomdecay_p :: Param
- Sound.Tidal.Context: transition :: (IO Time) -> MVar (ParamPattern, [ParamPattern]) -> (Time -> [ParamPattern] -> ParamPattern) -> ParamPattern -> IO ()
- Sound.Tidal.Context: transpose :: () => [[a]] -> [[a]]
- Sound.Tidal.Context: tremdp :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: tremolodepth :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: tremolodepth_p :: Param
- Sound.Tidal.Context: tremolorate :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: tremolorate_p :: Param
- Sound.Tidal.Context: tremr :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: tri :: (Fractional a, Real a) => Pattern a
- Sound.Tidal.Context: tri1 :: (Fractional a, Real a) => Pattern a
- Sound.Tidal.Context: triple :: Time -> Pattern a -> Pattern a
- Sound.Tidal.Context: trirat :: Pattern Double
- Sound.Tidal.Context: trirat1 :: Pattern Double
- Sound.Tidal.Context: triwave :: (Fractional a, Real a) => Pattern a
- Sound.Tidal.Context: triwave1 :: (Fractional a, Real a) => Pattern a
- Sound.Tidal.Context: trunc :: Pattern Time -> Pattern a -> Pattern a
- Sound.Tidal.Context: tryPutMVar :: () => MVar a -> a -> IO Bool
- Sound.Tidal.Context: tryReadMVar :: () => MVar a -> IO Maybe a
- Sound.Tidal.Context: tryTakeMVar :: () => MVar a -> IO Maybe a
- Sound.Tidal.Context: type Arc = (Time, Time)
- Sound.Tidal.Context: type ClientState = [TConnection]
- Sound.Tidal.Context: type ColourD = Colour Double
- Sound.Tidal.Context: type CpsUtils = (Double -> IO (), IO Rational)
- Sound.Tidal.Context: type Event a = (Arc, Arc, a)
- Sound.Tidal.Context: type ParamMap = Map Param Value
- Sound.Tidal.Context: type ParamPattern = Pattern ParamMap
- Sound.Tidal.Context: type Rational = Ratio Integer
- Sound.Tidal.Context: type Time = Rational
- Sound.Tidal.Context: type ToMessageFunc = Shape -> Tempo -> Int -> (Double, Double, ParamMap) -> Maybe (IO ())
- Sound.Tidal.Context: uid :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: uid_p :: Param
- Sound.Tidal.Context: unDegradeBy :: Pattern Double -> Pattern a -> Pattern a
- Sound.Tidal.Context: uncons :: () => [a] -> Maybe (a, [a])
- Sound.Tidal.Context: unfoldr :: () => b -> Maybe (a, b) -> b -> [a]
- Sound.Tidal.Context: union :: Eq a => [a] -> [a] -> [a]
- Sound.Tidal.Context: unionBy :: () => a -> a -> Bool -> [a] -> [a] -> [a]
- Sound.Tidal.Context: unit :: Pattern String -> ParamPattern
- Sound.Tidal.Context: unit_p :: Param
- Sound.Tidal.Context: unlines :: [String] -> String
- Sound.Tidal.Context: unwords :: [String] -> String
- Sound.Tidal.Context: unwrap :: Pattern (Pattern a) -> Pattern a
- Sound.Tidal.Context: unwrap' :: Pattern (Pattern a) -> Pattern a
- Sound.Tidal.Context: unzip :: () => [(a, b)] -> ([a], [b])
- Sound.Tidal.Context: unzip3 :: () => [(a, b, c)] -> ([a], [b], [c])
- Sound.Tidal.Context: unzip4 :: () => [(a, b, c, d)] -> ([a], [b], [c], [d])
- Sound.Tidal.Context: unzip5 :: () => [(a, b, c, d, e)] -> ([a], [b], [c], [d], [e])
- Sound.Tidal.Context: unzip6 :: () => [(a, b, c, d, e, f)] -> ([a], [b], [c], [d], [e], [f])
- Sound.Tidal.Context: unzip7 :: () => [(a, b, c, d, e, f, g)] -> ([a], [b], [c], [d], [e], [f], [g])
- Sound.Tidal.Context: up :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: updateTempo :: Tempo -> Double -> IO (Tempo)
- Sound.Tidal.Context: ur :: Time -> Pattern String -> [(String, Pattern a)] -> [(String, Pattern a -> Pattern a)] -> Pattern a
- Sound.Tidal.Context: val :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: val_p :: Param
- Sound.Tidal.Context: vcf :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: vcfegint :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: vcfegint_p :: Param
- Sound.Tidal.Context: vco :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: vcoegint :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: vcoegint_p :: Param
- Sound.Tidal.Context: velocity :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: velocity_p :: Param
- Sound.Tidal.Context: voi :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: voice :: Pattern Double -> ParamPattern
- Sound.Tidal.Context: voice_p :: Param
- Sound.Tidal.Context: vowel :: Pattern String -> ParamPattern
- Sound.Tidal.Context: vowel_p :: Param
- Sound.Tidal.Context: wait :: Time -> Time -> [ParamPattern] -> ParamPattern
- Sound.Tidal.Context: wait' :: (Time -> [ParamPattern] -> ParamPattern) -> Time -> Time -> [ParamPattern] -> ParamPattern
- Sound.Tidal.Context: waitQSem :: QSem -> IO ()
- Sound.Tidal.Context: waitQSemN :: QSemN -> Int -> IO ()
- Sound.Tidal.Context: wash :: (Pattern a -> Pattern a) -> Time -> Time -> [Pattern a] -> Pattern a
- Sound.Tidal.Context: weave :: Rational -> ParamPattern -> [ParamPattern] -> ParamPattern
- Sound.Tidal.Context: weave' :: Rational -> Pattern a -> [Pattern a -> Pattern a] -> Pattern a
- Sound.Tidal.Context: wedge :: Time -> Pattern a -> Pattern a -> Pattern a
- Sound.Tidal.Context: when :: (Int -> Bool) -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
- Sound.Tidal.Context: whenT :: (Time -> Bool) -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
- Sound.Tidal.Context: whenmod :: Int -> Int -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
- Sound.Tidal.Context: with :: (ParamType a) => Param -> (Pattern a -> Pattern a) -> ParamPattern -> ParamPattern
- Sound.Tidal.Context: withEvent :: (Event a -> Event b) -> Pattern a -> Pattern b
- Sound.Tidal.Context: withF :: Param -> (Pattern Double -> Pattern Double) -> ParamPattern -> ParamPattern
- Sound.Tidal.Context: withI :: Param -> (Pattern Int -> Pattern Int) -> ParamPattern -> ParamPattern
- Sound.Tidal.Context: withMVar :: () => MVar a -> a -> IO b -> IO b
- Sound.Tidal.Context: withMVarMasked :: () => MVar a -> a -> IO b -> IO b
- Sound.Tidal.Context: withQueryArc :: (Arc -> Arc) -> Pattern a -> Pattern a
- Sound.Tidal.Context: withQueryTime :: (Time -> Time) -> Pattern a -> Pattern a
- Sound.Tidal.Context: withResultArc :: (Arc -> Arc) -> Pattern a -> Pattern a
- Sound.Tidal.Context: withResultTime :: (Time -> Time) -> Pattern a -> Pattern a
- Sound.Tidal.Context: withS :: Param -> (Pattern String -> Pattern String) -> ParamPattern -> ParamPattern
- Sound.Tidal.Context: within :: Arc -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
- Sound.Tidal.Context: within' :: Arc -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
- Sound.Tidal.Context: words :: String -> [String]
- Sound.Tidal.Context: writeChan :: () => Chan a -> a -> IO ()
- Sound.Tidal.Context: writeList2Chan :: () => Chan a -> [a] -> IO ()
- Sound.Tidal.Context: wsConn :: TConnection -> Connection
- Sound.Tidal.Context: xfade :: Time -> [ParamPattern] -> ParamPattern
- Sound.Tidal.Context: xfadeIn :: Time -> Time -> [ParamPattern] -> ParamPattern
- Sound.Tidal.Context: yield :: IO ()
- Sound.Tidal.Context: zip :: () => [a] -> [b] -> [(a, b)]
- Sound.Tidal.Context: zip3 :: () => [a] -> [b] -> [c] -> [(a, b, c)]
- Sound.Tidal.Context: zip4 :: () => [a] -> [b] -> [c] -> [d] -> [(a, b, c, d)]
- Sound.Tidal.Context: zip5 :: () => [a] -> [b] -> [c] -> [d] -> [e] -> [(a, b, c, d, e)]
- Sound.Tidal.Context: zip6 :: () => [a] -> [b] -> [c] -> [d] -> [e] -> [f] -> [(a, b, c, d, e, f)]
- Sound.Tidal.Context: zip7 :: () => [a] -> [b] -> [c] -> [d] -> [e] -> [f] -> [g] -> [(a, b, c, d, e, f, g)]
- Sound.Tidal.Context: zipWith :: () => a -> b -> c -> [a] -> [b] -> [c]
- Sound.Tidal.Context: zipWith3 :: () => a -> b -> c -> d -> [a] -> [b] -> [c] -> [d]
- Sound.Tidal.Context: zipWith4 :: () => a -> b -> c -> d -> e -> [a] -> [b] -> [c] -> [d] -> [e]
- Sound.Tidal.Context: zipWith5 :: () => a -> b -> c -> d -> e -> f -> [a] -> [b] -> [c] -> [d] -> [e] -> [f]
- Sound.Tidal.Context: zipWith6 :: () => a -> b -> c -> d -> e -> f -> g -> [a] -> [b] -> [c] -> [d] -> [e] -> [f] -> [g]
- Sound.Tidal.Context: zipWith7 :: () => a -> b -> c -> d -> e -> f -> g -> h -> [a] -> [b] -> [c] -> [d] -> [e] -> [f] -> [g] -> [h]
- Sound.Tidal.Context: zoom :: Arc -> Pattern a -> Pattern a
- Sound.Tidal.Dirt: _striate :: Int -> ParamPattern -> ParamPattern
- Sound.Tidal.Dirt: _striate' :: Int -> Double -> ParamPattern -> ParamPattern
- Sound.Tidal.Dirt: _striateL :: Int -> Int -> ParamPattern -> ParamPattern
- Sound.Tidal.Dirt: _striateL' :: Integral a => Int -> Double -> a -> ParamPattern -> ParamPattern
- Sound.Tidal.Dirt: _striateO :: Int -> Double -> ParamPattern -> ParamPattern
- Sound.Tidal.Dirt: _stut :: Integer -> Double -> Rational -> ParamPattern -> ParamPattern
- Sound.Tidal.Dirt: _stut' :: (Num n, Ord n) => n -> Time -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
- Sound.Tidal.Dirt: anticipate :: Time -> [ParamPattern] -> ParamPattern
- Sound.Tidal.Dirt: anticipateIn :: Time -> Time -> [ParamPattern] -> ParamPattern
- Sound.Tidal.Dirt: clutch :: Time -> [Pattern a] -> Pattern a
- Sound.Tidal.Dirt: clutchIn :: Time -> Time -> [Pattern a] -> Pattern a
- Sound.Tidal.Dirt: datumToColour :: Value -> ColourD
- Sound.Tidal.Dirt: dirt :: Shape
- Sound.Tidal.Dirt: dirtBackend :: () => IO Backend a
- Sound.Tidal.Dirt: dirtSetters :: IO Time -> IO (ParamPattern -> IO (), (Time -> [ParamPattern] -> ParamPattern) -> ParamPattern -> IO ())
- Sound.Tidal.Dirt: dirtSlang :: OscSlang
- Sound.Tidal.Dirt: dirtState :: IO MVar (ParamPattern, [ParamPattern])
- Sound.Tidal.Dirt: dirtStream :: IO ParamPattern -> IO ()
- Sound.Tidal.Dirt: dirtToColour :: ParamPattern -> Pattern ColourD
- Sound.Tidal.Dirt: dirtstream :: () => p -> IO ParamPattern -> IO ()
- Sound.Tidal.Dirt: durPattern :: Pattern a -> Pattern Time
- Sound.Tidal.Dirt: durPattern' :: Pattern a -> Pattern Time
- Sound.Tidal.Dirt: metronome :: Pattern ParamMap
- Sound.Tidal.Dirt: nToOrbit :: ParamPattern -> ParamPattern
- Sound.Tidal.Dirt: pick :: String -> Int -> String
- Sound.Tidal.Dirt: showToColour :: Show a => a -> ColourD
- Sound.Tidal.Dirt: soundToOrbit :: [String] -> ParamPattern -> ParamPattern
- Sound.Tidal.Dirt: striate :: Pattern Int -> ParamPattern -> ParamPattern
- Sound.Tidal.Dirt: striate' :: Pattern Int -> Pattern Double -> ParamPattern -> ParamPattern
- Sound.Tidal.Dirt: striateL :: Pattern Int -> Pattern Int -> ParamPattern -> ParamPattern
- Sound.Tidal.Dirt: striateL' :: Pattern Int -> Pattern Double -> Pattern Int -> ParamPattern -> ParamPattern
- Sound.Tidal.Dirt: striateO :: Pattern Int -> Pattern Double -> ParamPattern -> ParamPattern
- Sound.Tidal.Dirt: stringToColour :: String -> ColourD
- Sound.Tidal.Dirt: stut :: Pattern Integer -> Pattern Double -> Pattern Rational -> ParamPattern -> ParamPattern
- Sound.Tidal.Dirt: stut' :: Pattern Int -> Pattern Time -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
- Sound.Tidal.Dirt: stutx :: Pattern Int -> Pattern Time -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
- Sound.Tidal.Dirt: superDirtBackend :: () => Int -> IO Backend a
- Sound.Tidal.Dirt: superDirtSetters :: IO Time -> IO (ParamPattern -> IO (), (Time -> [ParamPattern] -> ParamPattern) -> ParamPattern -> IO ())
- Sound.Tidal.Dirt: superDirtSlang :: OscSlang
- Sound.Tidal.Dirt: superDirtState :: Int -> IO MVar (ParamPattern, [ParamPattern])
- Sound.Tidal.Dirt: superDirts :: [Int] -> IO [(ParamPattern -> IO (), (Time -> [ParamPattern] -> ParamPattern) -> ParamPattern -> IO ())]
- Sound.Tidal.Dirt: xfade :: Time -> [ParamPattern] -> ParamPattern
- Sound.Tidal.Dirt: xfadeIn :: Time -> Time -> [ParamPattern] -> ParamPattern
- Sound.Tidal.EspGrid: changeTempo :: MVar Tempo -> Packet -> IO ()
- Sound.Tidal.EspGrid: clockedTickEsp :: Int -> (Tempo -> Int -> IO ()) -> IO ()
- Sound.Tidal.EspGrid: clockedTickLoopEsp :: Int -> (Tempo -> Int -> IO ()) -> MVar Tempo -> Int -> IO Int
- Sound.Tidal.EspGrid: cpsUtilsEsp :: IO (Double -> IO (), IO Rational, IO Tempo)
- Sound.Tidal.EspGrid: dirtSettersEsp :: IO Time -> IO (ParamPattern -> IO (), (Time -> [ParamPattern] -> ParamPattern) -> ParamPattern -> IO ())
- Sound.Tidal.EspGrid: dirtStreamEsp :: IO (ParamPattern -> IO ())
- Sound.Tidal.EspGrid: getTempo :: MVar Tempo -> IO Tempo
- Sound.Tidal.EspGrid: parseEspTempo :: [Datum] -> Maybe Tempo
- Sound.Tidal.EspGrid: runClientEsp :: IO (MVar Tempo, MVar Double)
- Sound.Tidal.EspGrid: sendEspTempo :: Real t => t -> IO ()
- Sound.Tidal.EspGrid: stateEsp :: Backend a -> Shape -> IO (MVar (ParamPattern, [ParamPattern]))
- Sound.Tidal.EspGrid: streamEsp :: Backend a -> Shape -> IO (ParamPattern -> IO ())
- Sound.Tidal.EspGrid: superDirtSettersEsp :: IO Time -> IO (ParamPattern -> IO (), (Time -> [ParamPattern] -> ParamPattern) -> ParamPattern -> IO ())
- Sound.Tidal.MultiMode: Dirt :: StreamType
- Sound.Tidal.MultiMode: Esp :: SyncType
- Sound.Tidal.MultiMode: NoSync :: SyncType
- Sound.Tidal.MultiMode: SuperDirt :: StreamType
- Sound.Tidal.MultiMode: changeStreamType :: MVar StreamType -> StreamType -> IO (IO StreamType)
- Sound.Tidal.MultiMode: changeSyncType :: MVar SyncType -> SyncType -> IO (IO SyncType)
- Sound.Tidal.MultiMode: data StreamType
- Sound.Tidal.MultiMode: data SyncType
- Sound.Tidal.MultiMode: initializeStreamType :: IO (MVar StreamType)
- Sound.Tidal.MultiMode: initializeSyncType :: IO (MVar SyncType)
- Sound.Tidal.MultiMode: multiModeCpsUtils :: CpsUtils -> CpsUtils -> MVar SyncType -> IO CpsUtils
- Sound.Tidal.MultiMode: multiModeSetters :: IO Rational -> IO Rational -> MVar SyncType -> MVar StreamType -> IO (ParamPattern -> IO ())
- Sound.Tidal.MultiMode: type CpsUtils = (Double -> IO (), IO Rational)
- Sound.Tidal.OscStream: BundleStamp :: TimeStamp
- Sound.Tidal.OscStream: MessageStamp :: TimeStamp
- Sound.Tidal.OscStream: NoStamp :: TimeStamp
- Sound.Tidal.OscStream: OscSlang :: String -> TimeStamp -> Bool -> [Datum] -> OscSlang
- Sound.Tidal.OscStream: [namedParams] :: OscSlang -> Bool
- Sound.Tidal.OscStream: [path] :: OscSlang -> String
- Sound.Tidal.OscStream: [preamble] :: OscSlang -> [Datum]
- Sound.Tidal.OscStream: [timestamp] :: OscSlang -> TimeStamp
- Sound.Tidal.OscStream: data OscSlang
- Sound.Tidal.OscStream: data TimeStamp
- Sound.Tidal.OscStream: instance GHC.Classes.Eq Sound.Tidal.OscStream.TimeStamp
- Sound.Tidal.OscStream: makeConnection :: String -> Int -> OscSlang -> IO (ToMessageFunc)
- Sound.Tidal.OscStream: send :: (Integral a) => UDP -> OscSlang -> Shape -> Tempo -> a -> (Double, Double, OscMap) -> IO ()
- Sound.Tidal.OscStream: toOscDatum :: Value -> Datum
- Sound.Tidal.OscStream: toOscMap :: ParamMap -> OscMap
- Sound.Tidal.OscStream: type OscMap = Map Param Datum
- Sound.Tidal.Params: begin_p :: Param
- Sound.Tidal.Params: bpf_p :: Param
- Sound.Tidal.Params: bpq_p :: Param
- Sound.Tidal.Params: channel_p :: Param
- Sound.Tidal.Params: clhatdecay_p :: Param
- Sound.Tidal.Params: coarse_p :: Param
- Sound.Tidal.Params: crush_p :: Param
- Sound.Tidal.Params: ctranspose_p :: Param
- Sound.Tidal.Params: degree_p :: Param
- Sound.Tidal.Params: harmonic_p :: Param
- Sound.Tidal.Params: hpf_p :: Param
- Sound.Tidal.Params: hpq_p :: Param
- Sound.Tidal.Params: legato_p :: Param
- Sound.Tidal.Params: lpf_p :: Param
- Sound.Tidal.Params: lpq_p :: Param
- Sound.Tidal.Params: mtranspose_p :: Param
- Sound.Tidal.Params: octaveRatio_p :: Param
- Sound.Tidal.Params: phaserdepth_p :: Param
- Sound.Tidal.Params: phaserrate_p :: Param
- Sound.Tidal.Params: stepsPerOctave_p :: Param
- Sound.Tidal.Params: tremolodepth_p :: Param
- Sound.Tidal.Params: tremolorate_p :: Param
- Sound.Tidal.Parse: Negative :: Sign
- Sound.Tidal.Parse: Positive :: Sign
- Sound.Tidal.Parse: TPat_Atom :: a -> TPat a
- Sound.Tidal.Parse: TPat_Cat :: [TPat a] -> TPat a
- Sound.Tidal.Parse: TPat_DegradeBy :: Double -> (TPat a) -> TPat a
- Sound.Tidal.Parse: TPat_Density :: (TPat Time) -> (TPat a) -> TPat a
- Sound.Tidal.Parse: TPat_Elongate :: Int -> TPat a
- Sound.Tidal.Parse: TPat_EnumFromTo :: (TPat a) -> (TPat a) -> TPat a
- Sound.Tidal.Parse: TPat_Foot :: TPat a
- Sound.Tidal.Parse: TPat_Overlay :: (TPat a) -> (TPat a) -> TPat a
- Sound.Tidal.Parse: TPat_ShiftL :: Time -> (TPat a) -> TPat a
- Sound.Tidal.Parse: TPat_Silence :: TPat a
- Sound.Tidal.Parse: TPat_Slow :: (TPat Time) -> (TPat a) -> TPat a
- Sound.Tidal.Parse: TPat_TimeCat :: [TPat a] -> TPat a
- Sound.Tidal.Parse: TPat_Zoom :: Arc -> (TPat a) -> TPat a
- Sound.Tidal.Parse: TPat_pE :: (TPat Int) -> (TPat Int) -> (TPat Integer) -> (TPat a) -> TPat a
- Sound.Tidal.Parse: _eoff :: Int -> Int -> Integer -> Pattern a -> Pattern a
- Sound.Tidal.Parse: angles :: Parser a -> Parser a
- Sound.Tidal.Parse: applySign :: Num a => Sign -> a -> a
- Sound.Tidal.Parse: braces :: Parser a -> Parser a
- Sound.Tidal.Parse: brackets :: Parser a -> Parser a
- Sound.Tidal.Parse: class Enumerable a
- Sound.Tidal.Parse: class Parseable a
- Sound.Tidal.Parse: data Sign
- Sound.Tidal.Parse: data TPat a
- Sound.Tidal.Parse: durations :: [TPat a] -> [(Int, TPat a)]
- Sound.Tidal.Parse: elongate :: () => [TPat a] -> TPat a
- Sound.Tidal.Parse: enumFromThenTo' :: (Ord a, Enum a, Num a) => a -> a -> a -> Pattern a
- Sound.Tidal.Parse: enumFromTo' :: (Ord a, Enum a) => a -> a -> Pattern a
- Sound.Tidal.Parse: eoff :: Pattern Int -> Pattern Int -> Pattern Integer -> Pattern a -> Pattern a
- Sound.Tidal.Parse: float :: Parser Double
- Sound.Tidal.Parse: fromNote :: Num a => Pattern String -> Pattern a
- Sound.Tidal.Parse: fromThenTo :: Enumerable a => a -> a -> a -> Pattern a
- Sound.Tidal.Parse: fromTo :: Enumerable a => a -> a -> Pattern a
- Sound.Tidal.Parse: instance (Sound.Tidal.Parse.Enumerable a, Sound.Tidal.Parse.Parseable a) => Data.String.IsString (Sound.Tidal.Pattern.Pattern a)
- Sound.Tidal.Parse: instance GHC.Show.Show a => GHC.Show.Show (Sound.Tidal.Parse.TPat a)
- Sound.Tidal.Parse: instance Sound.Tidal.Parse.Enumerable GHC.Base.String
- Sound.Tidal.Parse: instance Sound.Tidal.Parse.Enumerable GHC.Integer.Type.Integer
- Sound.Tidal.Parse: instance Sound.Tidal.Parse.Enumerable GHC.Real.Rational
- Sound.Tidal.Parse: instance Sound.Tidal.Parse.Enumerable GHC.Types.Bool
- Sound.Tidal.Parse: instance Sound.Tidal.Parse.Enumerable GHC.Types.Double
- Sound.Tidal.Parse: instance Sound.Tidal.Parse.Enumerable GHC.Types.Int
- Sound.Tidal.Parse: instance Sound.Tidal.Parse.Enumerable Sound.Tidal.Parse.ColourD
- Sound.Tidal.Parse: instance Sound.Tidal.Parse.Parseable GHC.Base.String
- Sound.Tidal.Parse: instance Sound.Tidal.Parse.Parseable GHC.Integer.Type.Integer
- Sound.Tidal.Parse: instance Sound.Tidal.Parse.Parseable GHC.Real.Rational
- Sound.Tidal.Parse: instance Sound.Tidal.Parse.Parseable GHC.Types.Bool
- Sound.Tidal.Parse: instance Sound.Tidal.Parse.Parseable GHC.Types.Double
- Sound.Tidal.Parse: instance Sound.Tidal.Parse.Parseable GHC.Types.Int
- Sound.Tidal.Parse: instance Sound.Tidal.Parse.Parseable Sound.Tidal.Parse.ColourD
- Sound.Tidal.Parse: intOrFloat :: Parser Double
- Sound.Tidal.Parse: integer :: Parser Integer
- Sound.Tidal.Parse: lexer :: () => GenTokenParser String u Identity
- Sound.Tidal.Parse: natural :: Parser Integer
- Sound.Tidal.Parse: naturalOrFloat :: Parser (Either Integer Double)
- Sound.Tidal.Parse: p :: (Enumerable a, Parseable a) => String -> Pattern a
- Sound.Tidal.Parse: pBool :: Parser (TPat Bool)
- Sound.Tidal.Parse: pColour :: Parser (TPat ColourD)
- Sound.Tidal.Parse: pDouble :: Parser (TPat Double)
- Sound.Tidal.Parse: pE :: Parseable a => TPat a -> Parser (TPat a)
- Sound.Tidal.Parse: pIntegral :: Parseable a => Integral a => Parser (TPat a)
- Sound.Tidal.Parse: pMult :: Parseable a => TPat a -> Parser (TPat a)
- Sound.Tidal.Parse: pPart :: Parseable a => Parser (TPat a) -> Parser [TPat a]
- Sound.Tidal.Parse: pPolyIn :: Parseable a => Parser (TPat a) -> Parser (TPat a)
- Sound.Tidal.Parse: pPolyOut :: Parseable a => Parser (TPat a) -> Parser (TPat a)
- Sound.Tidal.Parse: pRand :: Parseable a => TPat a -> Parser (TPat a)
- Sound.Tidal.Parse: pRatio :: Parser (Rational)
- Sound.Tidal.Parse: pRational :: Parser (TPat Rational)
- Sound.Tidal.Parse: pReplicate :: Parseable a => TPat a -> Parser [TPat a]
- Sound.Tidal.Parse: pSequence :: Parseable a => Parser (TPat a) -> GenParser Char () (TPat a)
- Sound.Tidal.Parse: pSequenceN :: Parseable a => Parser (TPat a) -> GenParser Char () (Int, TPat a)
- Sound.Tidal.Parse: pSingle :: Parseable a => Parser (TPat a) -> Parser (TPat a)
- Sound.Tidal.Parse: pStretch :: Parseable a => TPat a -> Parser [TPat a]
- Sound.Tidal.Parse: pString :: Parser (String)
- Sound.Tidal.Parse: pVocable :: Parser (TPat String)
- Sound.Tidal.Parse: parens :: Parser a -> Parser a
- Sound.Tidal.Parse: parseInt :: Parser Int
- Sound.Tidal.Parse: parseIntNote :: Integral i => Parser i
- Sound.Tidal.Parse: parseNote :: Num a => Parser a
- Sound.Tidal.Parse: parseRhythm :: Parseable a => Parser (TPat a) -> String -> TPat a
- Sound.Tidal.Parse: parseTPat :: Parseable a => String -> TPat a
- Sound.Tidal.Parse: r :: (Enumerable a, Parseable a) => String -> Pattern a -> IO (Pattern a)
- Sound.Tidal.Parse: sign :: Parser Sign
- Sound.Tidal.Parse: splitFeet :: [TPat t] -> [[TPat t]]
- Sound.Tidal.Parse: symbol :: String -> Parser String
- Sound.Tidal.Parse: toPat :: Enumerable a => TPat a -> Pattern a
- Sound.Tidal.Parse: type ColourD = Colour Double
- Sound.Tidal.Pattern: (<<~) :: Int -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: (<~) :: Pattern Time -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: (<~>) :: Pattern String -> Pattern b -> Pattern b
- Sound.Tidal.Pattern: (~>) :: Pattern Time -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: (~>>) :: Int -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: _degradeBy :: Double -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: _density :: Time -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: _discretise :: Time -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: _distrib :: [Int] -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: _e :: Int -> Int -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: _e' :: Int -> Int -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: _einv :: Int -> Int -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: _every :: Int -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: _every' :: Int -> Int -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: _fast :: Time -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: _iter :: Int -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: _iter' :: Int -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: _linger :: Time -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: _ply :: Int -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: _run :: (Enum a, Num a) => a -> Pattern a
- Sound.Tidal.Pattern: _scan :: (Enum a, Num a) => a -> Pattern a
- Sound.Tidal.Pattern: _slow :: Time -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: _stripe :: Int -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: _trunc :: Time -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: _unDegradeBy :: Double -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: almostAlways :: (Pattern a -> Pattern a) -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: almostNever :: (Pattern a -> Pattern a) -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: always :: (Pattern a -> Pattern a) -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: append :: Pattern a -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: append' :: Pattern a -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: atom :: a -> Pattern a
- Sound.Tidal.Pattern: brak :: Pattern a -> Pattern a
- Sound.Tidal.Pattern: breakUp :: Pattern a -> Pattern a
- Sound.Tidal.Pattern: cat :: [Pattern a] -> Pattern a
- Sound.Tidal.Pattern: choose :: [a] -> Pattern a
- Sound.Tidal.Pattern: chunk :: Integer -> (Pattern b -> Pattern b) -> Pattern b -> Pattern b
- Sound.Tidal.Pattern: chunk' :: Integral a => a -> (Pattern b -> Pattern b) -> Pattern b -> Pattern b
- Sound.Tidal.Pattern: compress :: Arc -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: compressTo :: Arc -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: cosine :: Fractional a => Pattern a
- Sound.Tidal.Pattern: cycleChoose :: [a] -> Pattern a
- Sound.Tidal.Pattern: degrade :: Pattern a -> Pattern a
- Sound.Tidal.Pattern: degradeBy :: Pattern Double -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: degradeOverBy :: Int -> Pattern Double -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: density :: Pattern Time -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: densityGap :: Time -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: discretise :: Time -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: discretise' :: Pattern Time -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: distrib :: [Pattern Int] -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: e :: Pattern Int -> Pattern Int -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: e' :: Pattern Int -> Pattern Int -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: efull :: Pattern Int -> Pattern Int -> Pattern a -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: einv :: Pattern Int -> Pattern Int -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: enclosingArc :: [Arc] -> Arc
- Sound.Tidal.Pattern: envEq :: Pattern Double
- Sound.Tidal.Pattern: envEqR :: Pattern Double
- Sound.Tidal.Pattern: envL :: Pattern Double
- Sound.Tidal.Pattern: envLR :: Pattern Double
- Sound.Tidal.Pattern: every :: Pattern Int -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: every' :: Pattern Int -> Pattern Int -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: fadeIn :: Time -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: fadeIn' :: Time -> Time -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: fadeOut :: Time -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: fadeOut' :: Time -> Time -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: fast :: Pattern Time -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: fast' :: Pattern Time -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: fastGap :: Time -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: fastcat :: [Pattern a] -> Pattern a
- Sound.Tidal.Pattern: fastspread :: (a -> t -> Pattern b) -> [a] -> t -> Pattern b
- Sound.Tidal.Pattern: fill :: Pattern a -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: filterOnsets :: Pattern a -> Pattern a
- Sound.Tidal.Pattern: filterOnsetsInRange :: Pattern a -> Pattern a
- Sound.Tidal.Pattern: filterStartInRange :: Pattern a -> Pattern a
- Sound.Tidal.Pattern: fit :: Int -> [a] -> Pattern Int -> Pattern a
- Sound.Tidal.Pattern: fit' :: Pattern Time -> Int -> Pattern Int -> Pattern Int -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: flatpat :: Pattern [a] -> Pattern a
- Sound.Tidal.Pattern: foldEvery :: [Int] -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: groupByTime :: [Event a] -> [Event [a]]
- Sound.Tidal.Pattern: ifp :: (Int -> Bool) -> (Pattern a -> Pattern a) -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: index :: Real b => b -> Pattern b -> Pattern c -> Pattern c
- Sound.Tidal.Pattern: inhabit :: [(String, Pattern a)] -> Pattern String -> Pattern a
- Sound.Tidal.Pattern: inside :: Pattern Time -> (Pattern a1 -> Pattern a) -> Pattern a1 -> Pattern a
- Sound.Tidal.Pattern: irand :: Num a => Int -> Pattern a
- Sound.Tidal.Pattern: iter :: Pattern Int -> Pattern c -> Pattern c
- Sound.Tidal.Pattern: iter' :: Pattern Int -> Pattern c -> Pattern c
- Sound.Tidal.Pattern: layer :: [a -> Pattern b] -> a -> Pattern b
- Sound.Tidal.Pattern: lindenmayer :: Int -> String -> String -> String
- Sound.Tidal.Pattern: lindenmayerI :: Num b => Int -> String -> String -> [b]
- Sound.Tidal.Pattern: linger :: Pattern Time -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: listToPat :: [a] -> Pattern a
- Sound.Tidal.Pattern: loopFirst :: Pattern a -> Pattern a
- Sound.Tidal.Pattern: mask :: Pattern a -> Pattern b -> Pattern b
- Sound.Tidal.Pattern: maybeListToPat :: [Maybe a] -> Pattern a
- Sound.Tidal.Pattern: never :: (Pattern a -> Pattern a) -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: newtype Pattern a
- Sound.Tidal.Pattern: often :: (Pattern a -> Pattern a) -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: outside :: Pattern Time -> (Pattern a1 -> Pattern a) -> Pattern a1 -> Pattern a
- Sound.Tidal.Pattern: overlay :: Pattern a -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: palindrome :: Pattern a -> Pattern a
- Sound.Tidal.Pattern: parseLMRule :: String -> [(String, String)]
- Sound.Tidal.Pattern: parseLMRule' :: String -> [(Char, String)]
- Sound.Tidal.Pattern: patToList :: Pattern a -> [a]
- Sound.Tidal.Pattern: pequal :: Ord a => Time -> Pattern a -> Pattern a -> Bool
- Sound.Tidal.Pattern: permstep :: RealFrac b => Int -> [a] -> Pattern b -> Pattern a
- Sound.Tidal.Pattern: playWhen :: (Time -> Bool) -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: ply :: Pattern Int -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: points :: [Event a] -> [Time]
- Sound.Tidal.Pattern: prep :: (Time, Time) -> Pattern String -> Pattern b -> Pattern b
- Sound.Tidal.Pattern: preplace :: (Time, Time) -> Pattern String -> Pattern b -> Pattern b
- Sound.Tidal.Pattern: preplace1 :: Pattern String -> Pattern b -> Pattern b
- Sound.Tidal.Pattern: preplaceWith :: (a -> b -> c) -> (Time, Time) -> Pattern a -> Pattern b -> Pattern c
- Sound.Tidal.Pattern: preplaceWith1 :: (a -> b -> c) -> Pattern a -> Pattern b -> Pattern c
- Sound.Tidal.Pattern: prot :: Time -> Int -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: prot1 :: Int -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: protate :: Time -> Int -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: prr :: Int -> (Time, Time) -> Pattern String -> Pattern b -> Pattern b
- Sound.Tidal.Pattern: prrw :: (a -> b -> c) -> Int -> (Time, Time) -> Pattern a -> Pattern b -> Pattern c
- Sound.Tidal.Pattern: prw :: (a -> b -> c) -> (Time, Time) -> Pattern a -> Pattern b -> Pattern c
- Sound.Tidal.Pattern: prw1 :: (a -> b -> c) -> Pattern a -> Pattern b -> Pattern c
- Sound.Tidal.Pattern: rand :: Pattern Double
- Sound.Tidal.Pattern: randArcs :: Int -> Pattern [Arc]
- Sound.Tidal.Pattern: randStruct :: Int -> Pattern Int
- Sound.Tidal.Pattern: randcat :: [Pattern a] -> Pattern a
- Sound.Tidal.Pattern: rarely :: (Pattern a -> Pattern a) -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: ratsine :: Pattern Double
- Sound.Tidal.Pattern: repeatCycles :: Int -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: rev :: Pattern a -> Pattern a
- Sound.Tidal.Pattern: revArc :: Arc -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: run :: (Enum a, Num a) => Pattern a -> Pattern a
- Sound.Tidal.Pattern: runWith :: Integer -> (Pattern b -> Pattern b) -> Pattern b -> Pattern b
- Sound.Tidal.Pattern: runWith' :: Integral a => a -> (Pattern b -> Pattern b) -> Pattern b -> Pattern b
- Sound.Tidal.Pattern: saw :: (Fractional a, Real a) => Pattern a
- Sound.Tidal.Pattern: saw1 :: (Fractional a, Real a) => Pattern a
- Sound.Tidal.Pattern: sawrat :: Pattern Double
- Sound.Tidal.Pattern: sawrat1 :: Pattern Double
- Sound.Tidal.Pattern: sawwave :: (Fractional a, Real a) => Pattern a
- Sound.Tidal.Pattern: sawwave1 :: (Fractional a, Real a) => Pattern a
- Sound.Tidal.Pattern: scan :: (Enum a, Num a) => Pattern a -> Pattern a
- Sound.Tidal.Pattern: scramble :: Int -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: segment :: Pattern a -> Pattern [a]
- Sound.Tidal.Pattern: segment' :: [Event a] -> [Event a]
- Sound.Tidal.Pattern: seqP :: [(Time, Time, Pattern a)] -> Pattern a
- Sound.Tidal.Pattern: seqPLoop :: [(Time, Time, Pattern a)] -> Pattern a
- Sound.Tidal.Pattern: seqToRelOnsetDeltas :: Arc -> Pattern a -> [(Double, Double, a)]
- Sound.Tidal.Pattern: sew :: Pattern Bool -> Pattern a -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: showArc :: Arc -> String
- Sound.Tidal.Pattern: showEvent :: (Show a) => Event a -> String
- Sound.Tidal.Pattern: showTime :: (Show a, Integral a) => Ratio a -> String
- Sound.Tidal.Pattern: shuffle :: Int -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: sig :: (Time -> a) -> Pattern a
- Sound.Tidal.Pattern: silence :: Pattern a
- Sound.Tidal.Pattern: sine :: Fractional a => Pattern a
- Sound.Tidal.Pattern: sine1 :: Fractional a => Pattern a
- Sound.Tidal.Pattern: sineAmp :: Fractional a => a -> Pattern a
- Sound.Tidal.Pattern: sineAmp1 :: Fractional a => a -> Pattern a
- Sound.Tidal.Pattern: sinerat :: Pattern Double
- Sound.Tidal.Pattern: sinerat1 :: Pattern Double
- Sound.Tidal.Pattern: sinewave :: Fractional a => Pattern a
- Sound.Tidal.Pattern: sinewave1 :: Fractional a => Pattern a
- Sound.Tidal.Pattern: sliceArc :: Arc -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: slow :: Pattern Time -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: slow' :: Pattern Time -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: slowcat :: [Pattern a] -> Pattern a
- Sound.Tidal.Pattern: slowspread :: (a -> t -> Pattern b) -> [a] -> t -> Pattern b
- Sound.Tidal.Pattern: slowstripe :: Pattern Int -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: someCycles :: (Pattern a -> Pattern a) -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: someCyclesBy :: Double -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: somecycles :: (Pattern a -> Pattern a) -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: somecyclesBy :: Double -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: sometimes :: (Pattern a -> Pattern a) -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: sometimesBy :: Double -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: spaceOut :: [Time] -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: sparsity :: Pattern Time -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: split :: Time -> [Event a] -> [Event a]
- Sound.Tidal.Pattern: splitAtSam :: Pattern a -> Pattern a
- Sound.Tidal.Pattern: spread :: (a -> t -> Pattern b) -> [a] -> t -> Pattern b
- Sound.Tidal.Pattern: spread' :: Monad m => (a -> b -> m c) -> m a -> b -> m c
- Sound.Tidal.Pattern: spreadChoose :: (t -> t1 -> Pattern b) -> [t] -> t1 -> Pattern b
- Sound.Tidal.Pattern: spreadr :: (t -> t1 -> Pattern b) -> [t] -> t1 -> Pattern b
- Sound.Tidal.Pattern: square :: (Fractional a, Real a) => Pattern a
- Sound.Tidal.Pattern: square1 :: (Fractional a, Real a) => Pattern a
- Sound.Tidal.Pattern: squarewave :: (Fractional a, Real a) => Pattern a
- Sound.Tidal.Pattern: squarewave1 :: (Fractional a, Real a) => Pattern a
- Sound.Tidal.Pattern: stack :: [Pattern a] -> Pattern a
- Sound.Tidal.Pattern: stretch :: Pattern a -> Pattern a
- Sound.Tidal.Pattern: stripe :: Pattern Int -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: struct :: Pattern String -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: substruct :: Pattern String -> Pattern b -> Pattern b
- Sound.Tidal.Pattern: substruct' :: Pattern Int -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: superimpose :: (Pattern a -> Pattern a) -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: swing :: Pattern Time -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: swingBy :: Pattern Time -> Pattern Time -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: temporalParam :: (a -> Pattern b -> Pattern c) -> (Pattern a -> Pattern b -> Pattern c)
- Sound.Tidal.Pattern: temporalParam' :: (a -> Pattern b -> Pattern c) -> (Pattern a -> Pattern b -> Pattern c)
- Sound.Tidal.Pattern: temporalParam2 :: (a -> b -> Pattern c -> Pattern d) -> (Pattern a -> Pattern b -> Pattern c -> Pattern d)
- Sound.Tidal.Pattern: temporalParam2' :: (a -> b -> Pattern c -> Pattern d) -> (Pattern a -> Pattern b -> Pattern c -> Pattern d)
- Sound.Tidal.Pattern: temporalParam3 :: (a -> b -> c -> Pattern d -> Pattern e) -> (Pattern a -> Pattern b -> Pattern c -> Pattern d -> Pattern e)
- Sound.Tidal.Pattern: temporalParam3' :: (a -> b -> c -> Pattern d -> Pattern e) -> (Pattern a -> Pattern b -> Pattern c -> Pattern d -> Pattern e)
- Sound.Tidal.Pattern: timeCat :: [(Time, Pattern a)] -> Pattern a
- Sound.Tidal.Pattern: timeLoop :: Pattern Time -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: timeToRand :: RealFrac r => r -> Double
- Sound.Tidal.Pattern: timedValues :: Pattern a -> Pattern (Arc, a)
- Sound.Tidal.Pattern: toScale :: Num a => [a] -> Pattern Int -> Pattern a
- Sound.Tidal.Pattern: toScale' :: Num a => Int -> [a] -> Pattern Int -> Pattern a
- Sound.Tidal.Pattern: tri :: (Fractional a, Real a) => Pattern a
- Sound.Tidal.Pattern: tri1 :: (Fractional a, Real a) => Pattern a
- Sound.Tidal.Pattern: trirat :: Pattern Double
- Sound.Tidal.Pattern: trirat1 :: Pattern Double
- Sound.Tidal.Pattern: triwave :: (Fractional a, Real a) => Pattern a
- Sound.Tidal.Pattern: triwave1 :: (Fractional a, Real a) => Pattern a
- Sound.Tidal.Pattern: trunc :: Pattern Time -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: unDegradeBy :: Pattern Double -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: unwrap' :: Pattern (Pattern a) -> Pattern a
- Sound.Tidal.Pattern: ur :: Time -> Pattern String -> [(String, Pattern a)] -> [(String, Pattern a -> Pattern a)] -> Pattern a
- Sound.Tidal.Pattern: wedge :: Time -> Pattern a -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: when :: (Int -> Bool) -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: whenT :: (Time -> Bool) -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: whenmod :: Int -> Int -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: within :: Arc -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: within' :: Arc -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
- Sound.Tidal.Pattern: zoom :: Arc -> Pattern a -> Pattern a
- Sound.Tidal.Scales: aeolian :: Num a => [a]
- Sound.Tidal.Scales: ahirbhairav :: Num a => [a]
- Sound.Tidal.Scales: augmented :: Num a => [a]
- Sound.Tidal.Scales: augmented2 :: Num a => [a]
- Sound.Tidal.Scales: bartok :: Num a => [a]
- Sound.Tidal.Scales: bhairav :: Num a => [a]
- Sound.Tidal.Scales: chinese :: Num a => [a]
- Sound.Tidal.Scales: chromatic :: Num a => [a]
- Sound.Tidal.Scales: diminished :: Num a => [a]
- Sound.Tidal.Scales: diminished2 :: Num a => [a]
- Sound.Tidal.Scales: dorian :: Num a => [a]
- Sound.Tidal.Scales: egyptian :: Num a => [a]
- Sound.Tidal.Scales: enigmatic :: Num a => [a]
- Sound.Tidal.Scales: gong :: Num a => [a]
- Sound.Tidal.Scales: harmonicMajor :: Num a => [a]
- Sound.Tidal.Scales: harmonicMinor :: Num a => [a]
- Sound.Tidal.Scales: hexAeolian :: Num a => [a]
- Sound.Tidal.Scales: hexDorian :: Num a => [a]
- Sound.Tidal.Scales: hexMajor6 :: Num a => [a]
- Sound.Tidal.Scales: hexMajor7 :: Num a => [a]
- Sound.Tidal.Scales: hexPhrygian :: Num a => [a]
- Sound.Tidal.Scales: hexSus :: Num a => [a]
- Sound.Tidal.Scales: hindu :: Num a => [a]
- Sound.Tidal.Scales: hirajoshi :: Num a => [a]
- Sound.Tidal.Scales: hungarianMinor :: Num a => [a]
- Sound.Tidal.Scales: indian :: Num a => [a]
- Sound.Tidal.Scales: ionian :: Num a => [a]
- Sound.Tidal.Scales: iwato :: Num a => [a]
- Sound.Tidal.Scales: jiao :: Num a => [a]
- Sound.Tidal.Scales: kumai :: Num a => [a]
- Sound.Tidal.Scales: leadingWhole :: Num a => [a]
- Sound.Tidal.Scales: locrian :: Num a => [a]
- Sound.Tidal.Scales: locrianMajor :: Num a => [a]
- Sound.Tidal.Scales: lydian :: Num a => [a]
- Sound.Tidal.Scales: lydianMinor :: Num a => [a]
- Sound.Tidal.Scales: majPent :: Num a => [a]
- Sound.Tidal.Scales: major :: Num a => [a]
- Sound.Tidal.Scales: marva :: Num a => [a]
- Sound.Tidal.Scales: melodicMajor :: Num a => [a]
- Sound.Tidal.Scales: melodicMinor :: Num a => [a]
- Sound.Tidal.Scales: melodicMinorDesc :: Num a => [a]
- Sound.Tidal.Scales: minPent :: Num a => [a]
- Sound.Tidal.Scales: minor :: Num a => [a]
- Sound.Tidal.Scales: mixolydian :: Num a => [a]
- Sound.Tidal.Scales: neapolitanMajor :: Num a => [a]
- Sound.Tidal.Scales: neapolitanMinor :: Num a => [a]
- Sound.Tidal.Scales: pelog :: Num a => [a]
- Sound.Tidal.Scales: phrygian :: Num a => [a]
- Sound.Tidal.Scales: prometheus :: Num a => [a]
- Sound.Tidal.Scales: purvi :: Num a => [a]
- Sound.Tidal.Scales: ritusen :: Num a => [a]
- Sound.Tidal.Scales: romanianMinor :: Num a => [a]
- Sound.Tidal.Scales: scaleP :: Num a => Pattern String -> Pattern Int -> Pattern a
- Sound.Tidal.Scales: scaleTable :: Num a => [(String, [a])]
- Sound.Tidal.Scales: scriabin :: Num a => [a]
- Sound.Tidal.Scales: shang :: Num a => [a]
- Sound.Tidal.Scales: spanish :: Num a => [a]
- Sound.Tidal.Scales: superLocrian :: Num a => [a]
- Sound.Tidal.Scales: todi :: Num a => [a]
- Sound.Tidal.Scales: whole :: Num a => [a]
- Sound.Tidal.Scales: yu :: Num a => [a]
- Sound.Tidal.Scales: zhi :: Num a => [a]
- Sound.Tidal.Sieve: (#&&#) :: Applicative f => f Bool -> f Bool -> f Bool
- Sound.Tidal.Sieve: (#^^#) :: Applicative f => f Bool -> f Bool -> f Bool
- Sound.Tidal.Sieve: (#||#) :: Applicative f => f Bool -> f Bool -> f Bool
- Sound.Tidal.Sieve: (@@) :: Int -> Int -> Sieve Bool
- Sound.Tidal.Sieve: Sieve :: Int -> a -> Sieve a
- Sound.Tidal.Sieve: [sieveAt] :: Sieve a -> Int -> a
- Sound.Tidal.Sieve: data Sieve a
- Sound.Tidal.Sieve: infixl 2 #^^#
- Sound.Tidal.Sieve: infixl 3 #&&#
- Sound.Tidal.Sieve: infixl 9 @@
- Sound.Tidal.Sieve: instance GHC.Base.Applicative Sound.Tidal.Sieve.Sieve
- Sound.Tidal.Sieve: instance GHC.Base.Functor Sound.Tidal.Sieve.Sieve
- Sound.Tidal.Sieve: instance GHC.Show.Show (Sound.Tidal.Sieve.Sieve GHC.Types.Bool)
- Sound.Tidal.Sieve: not' :: Applicative f => f Bool -> f Bool
- Sound.Tidal.Sieve: scaleSieve :: Int -> Sieve Bool -> Pattern Int -> Pattern Int
- Sound.Tidal.Sieve: sieveToInts :: Int -> Sieve Bool -> [Int]
- Sound.Tidal.Sieve: sieveToList :: Int -> Sieve a -> [a]
- Sound.Tidal.Sieve: sieveToPat :: Int -> Sieve Bool -> Pattern String
- Sound.Tidal.Sieve: sieveToString :: Int -> Sieve Bool -> [Char]
- Sound.Tidal.Sieve: slowstepSieve :: Pattern Time -> Int -> String -> Sieve Bool -> Pattern String
- Sound.Tidal.Sieve: stepSieve :: Int -> String -> Sieve Bool -> Pattern String
- Sound.Tidal.Simple: jump :: ParamPattern -> ParamPattern
- Sound.Tidal.Simple: mute :: ParamPattern -> ParamPattern
- Sound.Tidal.Strategies: _chop :: Int -> ParamPattern -> ParamPattern
- Sound.Tidal.Strategies: _gap :: Int -> ParamPattern -> ParamPattern
- Sound.Tidal.Strategies: _off :: Time -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
- Sound.Tidal.Strategies: _slice :: Int -> Int -> ParamPattern -> ParamPattern
- Sound.Tidal.Strategies: _spin :: Int -> ParamPattern -> ParamPattern
- Sound.Tidal.Strategies: chop :: Pattern Int -> ParamPattern -> ParamPattern
- Sound.Tidal.Strategies: chopArc :: Arc -> Int -> [Arc]
- Sound.Tidal.Strategies: double :: Time -> Pattern a -> Pattern a
- Sound.Tidal.Strategies: echo :: Time -> Pattern a -> Pattern a
- Sound.Tidal.Strategies: en :: [(Int, Int)] -> Pattern String -> Pattern String
- Sound.Tidal.Strategies: gap :: Pattern Int -> ParamPattern -> ParamPattern
- Sound.Tidal.Strategies: ghost :: Pattern ParamMap -> Pattern ParamMap
- Sound.Tidal.Strategies: ghost' :: () => p -> Pattern ParamMap -> Pattern ParamMap
- Sound.Tidal.Strategies: ghost'' :: () => Time -> Pattern a -> Pattern a -> Pattern a -> Pattern a
- Sound.Tidal.Strategies: hurry :: Pattern Rational -> ParamPattern -> ParamPattern
- Sound.Tidal.Strategies: interlace :: ParamPattern -> ParamPattern -> ParamPattern
- Sound.Tidal.Strategies: jux :: ParamPattern -> Pattern ParamMap -> ParamPattern -> Pattern ParamMap
- Sound.Tidal.Strategies: jux' :: () => [t -> ParamPattern] -> t -> Pattern ParamMap
- Sound.Tidal.Strategies: jux4 :: ParamPattern -> Pattern ParamMap -> ParamPattern -> Pattern ParamMap
- Sound.Tidal.Strategies: juxBy :: Pattern Double -> ParamPattern -> Pattern ParamMap -> ParamPattern -> Pattern ParamMap
- Sound.Tidal.Strategies: juxcut :: ParamPattern -> Pattern ParamMap -> ParamPattern -> Pattern ParamMap
- Sound.Tidal.Strategies: juxcut' :: () => [t -> ParamPattern] -> t -> Pattern ParamMap
- Sound.Tidal.Strategies: loopAt :: Pattern Time -> ParamPattern -> ParamPattern
- Sound.Tidal.Strategies: off :: Pattern Time -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
- Sound.Tidal.Strategies: offadd :: Num a => Pattern Time -> Pattern a -> Pattern a -> Pattern a
- Sound.Tidal.Strategies: quad :: Time -> Pattern a -> Pattern a
- Sound.Tidal.Strategies: rand4 :: Pattern Double
- Sound.Tidal.Strategies: randslice :: Int -> ParamPattern -> ParamPattern
- Sound.Tidal.Strategies: samples :: Applicative f => f String -> f Int -> f String
- Sound.Tidal.Strategies: samples' :: Applicative f => f String -> f Int -> f String
- Sound.Tidal.Strategies: sawwave4 :: Pattern Double
- Sound.Tidal.Strategies: scale :: (Functor f, Num b) => b -> b -> f b -> f b
- Sound.Tidal.Strategies: scalex :: (Functor f, Floating b) => b -> b -> f b -> f b
- Sound.Tidal.Strategies: sinewave4 :: Pattern Double
- Sound.Tidal.Strategies: slice :: Pattern Int -> Pattern Int -> ParamPattern -> ParamPattern
- Sound.Tidal.Strategies: smash :: Pattern Int -> [Pattern Time] -> ParamPattern -> Pattern ParamMap
- Sound.Tidal.Strategies: smash' :: Int -> [Pattern Time] -> ParamPattern -> Pattern ParamMap
- Sound.Tidal.Strategies: spin :: Pattern Int -> ParamPattern -> ParamPattern
- Sound.Tidal.Strategies: spreadf :: () => p1 -> p2 -> [a -> Pattern b] -> a -> Pattern b
- Sound.Tidal.Strategies: stackwith :: Pattern ParamMap -> [ParamPattern] -> Pattern ParamMap
- Sound.Tidal.Strategies: step :: String -> String -> Pattern String
- Sound.Tidal.Strategies: step' :: [String] -> String -> Pattern String
- Sound.Tidal.Strategies: steps :: [(String, String)] -> Pattern String
- Sound.Tidal.Strategies: stutter :: Integral i => i -> Time -> Pattern a -> Pattern a
- Sound.Tidal.Strategies: tabby :: () => Integer -> Pattern a -> Pattern a -> Pattern a
- Sound.Tidal.Strategies: triple :: Time -> Pattern a -> Pattern a
- Sound.Tidal.Strategies: up :: Pattern Double -> ParamPattern
- Sound.Tidal.Strategies: weave :: Rational -> ParamPattern -> [ParamPattern] -> ParamPattern
- Sound.Tidal.Strategies: weave' :: Rational -> Pattern a -> [Pattern a -> Pattern a] -> Pattern a
- Sound.Tidal.Stream: (###) :: Foldable t => ParamPattern -> t ParamPattern -> ParamPattern
- Sound.Tidal.Stream: (#) :: ParamPattern -> ParamPattern -> ParamPattern
- Sound.Tidal.Stream: (***) :: Foldable t => ParamPattern -> t ParamPattern -> ParamPattern
- Sound.Tidal.Stream: (+++) :: Foldable t => ParamPattern -> t ParamPattern -> ParamPattern
- Sound.Tidal.Stream: (///) :: Foldable t => ParamPattern -> t ParamPattern -> ParamPattern
- Sound.Tidal.Stream: (|*|) :: ParamPattern -> ParamPattern -> ParamPattern
- Sound.Tidal.Stream: (|+|) :: ParamPattern -> ParamPattern -> ParamPattern
- Sound.Tidal.Stream: (|-|) :: ParamPattern -> ParamPattern -> ParamPattern
- Sound.Tidal.Stream: (|/|) :: ParamPattern -> ParamPattern -> ParamPattern
- Sound.Tidal.Stream: (|=|) :: ParamPattern -> ParamPattern -> ParamPattern
- Sound.Tidal.Stream: Backend :: ToMessageFunc -> Shape -> Tempo -> Int -> IO () -> Backend a
- Sound.Tidal.Stream: F :: String -> Maybe Double -> Param
- Sound.Tidal.Stream: I :: String -> Maybe Int -> Param
- Sound.Tidal.Stream: S :: String -> Maybe String -> Param
- Sound.Tidal.Stream: Shape :: [Param] -> Double -> Bool -> Shape
- Sound.Tidal.Stream: VF :: Double -> Value
- Sound.Tidal.Stream: VI :: Int -> Value
- Sound.Tidal.Stream: VS :: String -> Value
- Sound.Tidal.Stream: [cpsStamp] :: Shape -> Bool
- Sound.Tidal.Stream: [fDefault] :: Param -> Maybe Double
- Sound.Tidal.Stream: [flush] :: Backend a -> Shape -> Tempo -> Int -> IO ()
- Sound.Tidal.Stream: [fvalue] :: Value -> Double
- Sound.Tidal.Stream: [iDefault] :: Param -> Maybe Int
- Sound.Tidal.Stream: [ivalue] :: Value -> Int
- Sound.Tidal.Stream: [latency] :: Shape -> Double
- Sound.Tidal.Stream: [name] :: Param -> String
- Sound.Tidal.Stream: [params] :: Shape -> [Param]
- Sound.Tidal.Stream: [sDefault] :: Param -> Maybe String
- Sound.Tidal.Stream: [svalue] :: Value -> String
- Sound.Tidal.Stream: [toMessage] :: Backend a -> ToMessageFunc
- Sound.Tidal.Stream: applyShape' :: Shape -> ParamMap -> Maybe ParamMap
- Sound.Tidal.Stream: class ParamType a
- Sound.Tidal.Stream: coerce :: Param -> ParamPattern -> ParamPattern
- Sound.Tidal.Stream: copyParam :: Param -> Param -> ParamPattern -> ParamPattern
- Sound.Tidal.Stream: data Backend a
- Sound.Tidal.Stream: data Param
- Sound.Tidal.Stream: data Shape
- Sound.Tidal.Stream: data Value
- Sound.Tidal.Stream: defaultMap :: Shape -> ParamMap
- Sound.Tidal.Stream: defaultValue :: Param -> Value
- Sound.Tidal.Stream: defaulted :: Shape -> [Param]
- Sound.Tidal.Stream: doAt :: RealFrac a => a -> IO () -> IO ()
- Sound.Tidal.Stream: follow :: (ParamType a, ParamType b) => Param -> Param -> (Pattern a -> Pattern b) -> ParamPattern -> ParamPattern
- Sound.Tidal.Stream: follow' :: ParamType a => Param -> Param -> (Pattern a -> Pattern a) -> ParamPattern -> ParamPattern
- Sound.Tidal.Stream: followF :: Param -> Param -> (Pattern Double -> Pattern Double) -> ParamPattern -> ParamPattern
- Sound.Tidal.Stream: followI :: Param -> Param -> (Pattern Int -> Pattern Int) -> ParamPattern -> ParamPattern
- Sound.Tidal.Stream: followS :: Param -> Param -> (Pattern String -> Pattern String) -> ParamPattern -> ParamPattern
- Sound.Tidal.Stream: fromV :: ParamType a => Value -> Maybe a
- Sound.Tidal.Stream: get :: ParamType a => Param -> ParamPattern -> Pattern a
- Sound.Tidal.Stream: getF :: Param -> ParamPattern -> Pattern Double
- Sound.Tidal.Stream: getI :: Param -> ParamPattern -> Pattern Int
- Sound.Tidal.Stream: getS :: Param -> ParamPattern -> Pattern String
- Sound.Tidal.Stream: hasDefault :: Param -> Bool
- Sound.Tidal.Stream: hasRequired :: Shape -> ParamMap -> Bool
- Sound.Tidal.Stream: infixl 1 |/|
- Sound.Tidal.Stream: instance GHC.Classes.Eq Sound.Tidal.Stream.Param
- Sound.Tidal.Stream: instance GHC.Classes.Eq Sound.Tidal.Stream.Value
- Sound.Tidal.Stream: instance GHC.Classes.Ord Sound.Tidal.Stream.Param
- Sound.Tidal.Stream: instance GHC.Classes.Ord Sound.Tidal.Stream.Value
- Sound.Tidal.Stream: instance GHC.Show.Show Sound.Tidal.Stream.Param
- Sound.Tidal.Stream: instance GHC.Show.Show Sound.Tidal.Stream.Value
- Sound.Tidal.Stream: instance Sound.Tidal.Stream.ParamType GHC.Base.String
- Sound.Tidal.Stream: instance Sound.Tidal.Stream.ParamType GHC.Types.Double
- Sound.Tidal.Stream: instance Sound.Tidal.Stream.ParamType GHC.Types.Int
- Sound.Tidal.Stream: isSubset :: (Eq a) => [a] -> [a] -> Bool
- Sound.Tidal.Stream: logicalOnset' :: Integral a => Tempo -> a -> Double -> Double -> Double
- Sound.Tidal.Stream: make :: (a -> Value) -> Shape -> String -> Pattern a -> ParamPattern
- Sound.Tidal.Stream: make' :: ParamType a => (a -> Value) -> Param -> Pattern a -> ParamPattern
- Sound.Tidal.Stream: makeF :: Shape -> String -> Pattern Double -> ParamPattern
- Sound.Tidal.Stream: makeI :: Shape -> String -> Pattern Int -> ParamPattern
- Sound.Tidal.Stream: makeP :: ParamType a => Param -> Pattern a -> ParamPattern
- Sound.Tidal.Stream: makeS :: Shape -> String -> Pattern String -> ParamPattern
- Sound.Tidal.Stream: merge :: ParamPattern -> ParamPattern -> ParamPattern
- Sound.Tidal.Stream: mergeNumWith :: Applicative f => Int -> Int -> Int -> Double -> Double -> Double -> f Map Param Value -> f Map Param Value -> f Map Param Value
- Sound.Tidal.Stream: mergePlus :: Applicative f => f Map Param Value -> f Map Param Value -> f Map Param Value
- Sound.Tidal.Stream: mergeWith :: (Ord k, Applicative f) => (k -> a -> a -> a) -> f (Map k a) -> f (Map k a) -> f (Map k a)
- Sound.Tidal.Stream: onTick' :: Backend a -> Shape -> MVar (ParamPattern, [ParamPattern]) -> Tempo -> Int -> IO ()
- Sound.Tidal.Stream: param :: Shape -> String -> Param
- Sound.Tidal.Stream: required :: Shape -> [Param]
- Sound.Tidal.Stream: setter :: MVar (a, [a]) -> a -> IO ()
- Sound.Tidal.Stream: start :: Backend a -> Shape -> IO (MVar (ParamPattern))
- Sound.Tidal.Stream: state :: Backend a -> Shape -> IO (MVar (ParamPattern, [ParamPattern]))
- Sound.Tidal.Stream: stream :: Backend a -> Shape -> IO (ParamPattern -> IO ())
- Sound.Tidal.Stream: streamcallback :: (ParamPattern -> IO ()) -> Backend a -> Shape -> IO (ParamPattern -> IO ())
- Sound.Tidal.Stream: ticksPerCycle :: Num p => p
- Sound.Tidal.Stream: toV :: ParamType a => a -> Value
- Sound.Tidal.Stream: type ParamMap = Map Param Value
- Sound.Tidal.Stream: type ParamPattern = Pattern ParamMap
- Sound.Tidal.Stream: type ToMessageFunc = Shape -> Tempo -> Int -> (Double, Double, ParamMap) -> Maybe (IO ())
- Sound.Tidal.Stream: with :: (ParamType a) => Param -> (Pattern a -> Pattern a) -> ParamPattern -> ParamPattern
- Sound.Tidal.Stream: withF :: Param -> (Pattern Double -> Pattern Double) -> ParamPattern -> ParamPattern
- Sound.Tidal.Stream: withI :: Param -> (Pattern Int -> Pattern Int) -> ParamPattern -> ParamPattern
- Sound.Tidal.Stream: withS :: Param -> (Pattern String -> Pattern String) -> ParamPattern -> ParamPattern
- Sound.Tidal.SuperCollider: scBackend :: String -> IO (Backend a)
- Sound.Tidal.SuperCollider: scSlang :: String -> OscSlang
- Sound.Tidal.SuperCollider: scStream :: String -> [Param] -> Double -> IO (ParamPattern -> IO (), Shape)
- Sound.Tidal.SuperCollider: supercollider :: [Param] -> Double -> Shape
- Sound.Tidal.Tempo: Master :: ServerMode
- Sound.Tidal.Tempo: Slave :: UDP -> ServerMode
- Sound.Tidal.Tempo: TConnection :: Unique -> Connection -> TConnection
- Sound.Tidal.Tempo: [at] :: Tempo -> UTCTime
- Sound.Tidal.Tempo: [beat] :: Tempo -> Double
- Sound.Tidal.Tempo: [clockLatency] :: Tempo -> Double
- Sound.Tidal.Tempo: beatNow :: Tempo -> IO (Double)
- Sound.Tidal.Tempo: bpsUtils :: IO ((Double -> IO (), IO (Rational)))
- Sound.Tidal.Tempo: broadcast :: Text -> ClientState -> IO ()
- Sound.Tidal.Tempo: clientApp :: MVar Tempo -> MVar Double -> MVar Double -> ClientApp ()
- Sound.Tidal.Tempo: clockedTick :: Int -> (Tempo -> Int -> IO ()) -> IO ()
- Sound.Tidal.Tempo: connectClient :: Bool -> String -> MVar Tempo -> MVar Double -> MVar Double -> IO ()
- Sound.Tidal.Tempo: cpsSetter :: IO (Double -> IO ())
- Sound.Tidal.Tempo: cpsUtils :: IO (Double -> IO (), IO Rational)
- Sound.Tidal.Tempo: cpsUtils' :: IO ((Double -> IO (), (Double -> IO ()), IO Rational))
- Sound.Tidal.Tempo: data ServerMode
- Sound.Tidal.Tempo: data TConnection
- Sound.Tidal.Tempo: getClockIp :: IO String
- Sound.Tidal.Tempo: getCurrentBeat :: MVar Tempo -> IO Rational
- Sound.Tidal.Tempo: getLatency :: IO Double
- Sound.Tidal.Tempo: getMasterPort :: IO Int
- Sound.Tidal.Tempo: getServerPort :: IO Int
- Sound.Tidal.Tempo: getSlavePort :: IO Int
- Sound.Tidal.Tempo: instance GHC.Classes.Eq Sound.Tidal.Tempo.TConnection
- Sound.Tidal.Tempo: instance GHC.Show.Show Sound.Tidal.Tempo.ServerMode
- Sound.Tidal.Tempo: instance GHC.Show.Show Sound.Tidal.Tempo.Tempo
- Sound.Tidal.Tempo: logicalTime :: Tempo -> Double -> Double
- Sound.Tidal.Tempo: nudgeTempo :: Tempo -> Double -> Tempo
- Sound.Tidal.Tempo: readTempo :: String -> Tempo
- Sound.Tidal.Tempo: removeClient :: TConnection -> ClientState -> ClientState
- Sound.Tidal.Tempo: runClient :: IO ((MVar Tempo, MVar Double, MVar Double))
- Sound.Tidal.Tempo: sendCps :: Connection -> MVar Double -> IO ()
- Sound.Tidal.Tempo: sendNudge :: Connection -> MVar Double -> IO ()
- Sound.Tidal.Tempo: serverAct :: String -> ServerMode -> MVar Tempo -> MVar ClientState -> IO ()
- Sound.Tidal.Tempo: serverApp :: MVar Tempo -> MVar ServerMode -> MVar ClientState -> ServerApp
- Sound.Tidal.Tempo: serverLoop :: TConnection -> MVar Tempo -> MVar ServerMode -> MVar ClientState -> IO ()
- Sound.Tidal.Tempo: setNudge :: Double -> ServerMode -> MVar Tempo -> MVar ClientState -> IO ()
- Sound.Tidal.Tempo: setSlave :: MVar ServerMode -> IO ()
- Sound.Tidal.Tempo: slave :: MVar ServerMode -> MVar ClientState -> IO ()
- Sound.Tidal.Tempo: slaveAct :: String -> MVar ServerMode -> MVar ClientState -> Message -> IO ()
- Sound.Tidal.Tempo: startServer :: IO (ThreadId)
- Sound.Tidal.Tempo: type ClientState = [TConnection]
- Sound.Tidal.Tempo: updateTempo :: Tempo -> Double -> IO (Tempo)
- Sound.Tidal.Tempo: wsConn :: TConnection -> Connection
- Sound.Tidal.Time: arcCycles :: Arc -> [Arc]
- Sound.Tidal.Time: arcCycles' :: Arc -> [Arc]
- Sound.Tidal.Time: cyclePos :: Time -> Time
- Sound.Tidal.Time: eventArc :: Event a -> Arc
- Sound.Tidal.Time: eventOffset :: Event a -> Time
- Sound.Tidal.Time: eventOnset :: Event a -> Time
- Sound.Tidal.Time: eventStart :: Event a -> Time
- Sound.Tidal.Time: hasOffset :: Event a -> Bool
- Sound.Tidal.Time: hasOnset :: Event a -> Bool
- Sound.Tidal.Time: isIn :: Arc -> Time -> Bool
- Sound.Tidal.Time: mapArc :: (Time -> Time) -> Arc -> Arc
- Sound.Tidal.Time: mapCycle :: (Time -> Time) -> Arc -> Arc
- Sound.Tidal.Time: midPoint :: Arc -> Time
- Sound.Tidal.Time: mirrorArc :: Time -> Arc -> Arc
- Sound.Tidal.Time: nextSam :: Time -> Time
- Sound.Tidal.Time: offsetIn :: Arc -> Event a -> Bool
- Sound.Tidal.Time: onsetIn :: Arc -> Event a -> Bool
- Sound.Tidal.Time: sam :: Time -> Time
- Sound.Tidal.Time: subArc :: Arc -> Arc -> Maybe Arc
- Sound.Tidal.Time: type Arc = (Time, Time)
- Sound.Tidal.Time: type Event a = (Arc, Arc, a)
- Sound.Tidal.Time: type Time = Rational
- Sound.Tidal.Transition: combineV :: (Value -> Value -> Value) -> ParamMap -> ParamMap -> ParamMap
- Sound.Tidal.Transition: mixNums :: Double -> Value -> Value -> Value
- Sound.Tidal.Transition: superwash :: (Pattern a -> Pattern a) -> (Pattern a -> Pattern a) -> Time -> Time -> Time -> Time -> [Pattern a] -> Pattern a
- Sound.Tidal.Transition: wait' :: (Time -> [ParamPattern] -> ParamPattern) -> Time -> Time -> [ParamPattern] -> ParamPattern
- Sound.Tidal.Utils: fst' :: () => (a, b, c) -> a
- Sound.Tidal.Utils: mapArcs :: (a -> a) -> [(a, a, x)] -> [(a, a, x)]
- Sound.Tidal.Utils: mapFst' :: (a -> x) -> (a, b, c) -> (x, b, c)
- Sound.Tidal.Utils: mapFsts :: (a -> b) -> [(a, c)] -> [(b, c)]
- Sound.Tidal.Utils: mapFsts' :: (a -> x) -> [(a, b, c)] -> [(x, b, c)]
- Sound.Tidal.Utils: mapSnd' :: (b -> x) -> (a, b, c) -> (a, x, c)
- Sound.Tidal.Utils: mapSnds :: (a -> b) -> [(c, a)] -> [(c, b)]
- Sound.Tidal.Utils: mapSnds' :: (b -> x) -> [(a, b, c)] -> [(a, x, c)]
- Sound.Tidal.Utils: mapThd' :: (c -> x) -> (a, b, c) -> (a, b, x)
- Sound.Tidal.Utils: mapThds' :: (c -> x) -> [(a, b, c)] -> [(a, b, x)]
- Sound.Tidal.Utils: maybeRead :: String -> Maybe Double
- Sound.Tidal.Utils: mergelists :: [a] -> [a] -> [a]
- Sound.Tidal.Utils: snd' :: () => (a, b, c) -> b
- Sound.Tidal.Utils: thd' :: () => (a, b, c) -> c
- Sound.Tidal.Version: tidal_version :: [Char]
+ Sound.Tidal.Chords: elevenSharp :: Num a => [a]
+ Sound.Tidal.Config: Config :: Bool -> String -> Int -> Double -> String -> Int -> Config
+ Sound.Tidal.Config: [cCtrlAddr] :: Config -> String
+ Sound.Tidal.Config: [cCtrlListen] :: Config -> Bool
+ Sound.Tidal.Config: [cCtrlPort] :: Config -> Int
+ Sound.Tidal.Config: [cFrameTimespan] :: Config -> Double
+ Sound.Tidal.Config: [cTempoAddr] :: Config -> String
+ Sound.Tidal.Config: [cTempoPort] :: Config -> Int
+ Sound.Tidal.Config: data Config
+ Sound.Tidal.Config: defaultConfig :: Config
+ Sound.Tidal.Control: _cF :: [Double] -> String -> Pattern Double
+ Sound.Tidal.Control: _cP :: (Enumerable a, Parseable a) => [Pattern a] -> String -> Pattern a
+ Sound.Tidal.Control: _cS :: [String] -> String -> Pattern String
+ Sound.Tidal.Control: _cX :: (Arc -> Value -> [Event a]) -> [a] -> String -> Pattern a
+ Sound.Tidal.Control: _chop :: Int -> ControlPattern -> ControlPattern
+ Sound.Tidal.Control: _gap :: Int -> ControlPattern -> ControlPattern
+ Sound.Tidal.Control: _slice :: Int -> Int -> ControlPattern -> ControlPattern
+ Sound.Tidal.Control: _spin :: Int -> ControlPattern -> ControlPattern
+ Sound.Tidal.Control: _striate :: Int -> ControlPattern -> ControlPattern
+ Sound.Tidal.Control: _striateBy :: Int -> Double -> ControlPattern -> ControlPattern
+ Sound.Tidal.Control: _stut :: Integer -> Double -> Rational -> ControlPattern -> ControlPattern
+ Sound.Tidal.Control: _stutWith :: (Num n, Ord n) => n -> Time -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
+ Sound.Tidal.Control: cF :: Double -> String -> Pattern Double
+ Sound.Tidal.Control: cF0 :: String -> Pattern Double
+ Sound.Tidal.Control: cF_ :: String -> Pattern Double
+ Sound.Tidal.Control: cI :: String -> Pattern Int
+ Sound.Tidal.Control: cP :: (Enumerable a, Parseable a) => Pattern a -> String -> Pattern a
+ Sound.Tidal.Control: cP_ :: (Enumerable a, Parseable a) => String -> Pattern a
+ Sound.Tidal.Control: cR :: Time -> String -> Pattern Rational
+ Sound.Tidal.Control: cR0 :: String -> Pattern Time
+ Sound.Tidal.Control: cR_ :: String -> Pattern Time
+ Sound.Tidal.Control: cS :: String -> String -> Pattern String
+ Sound.Tidal.Control: cS_ :: String -> Pattern String
+ Sound.Tidal.Control: cT :: Time -> String -> Pattern Time
+ Sound.Tidal.Control: cT0 :: String -> Pattern Time
+ Sound.Tidal.Control: cT_ :: String -> Pattern Time
+ Sound.Tidal.Control: chop :: Pattern Int -> ControlPattern -> ControlPattern
+ Sound.Tidal.Control: chopArc :: Arc -> Int -> [Arc]
+ Sound.Tidal.Control: gap :: Pattern Int -> ControlPattern -> ControlPattern
+ Sound.Tidal.Control: hurry :: Pattern Rational -> ControlPattern -> ControlPattern
+ Sound.Tidal.Control: in0 :: Pattern Double
+ Sound.Tidal.Control: in1 :: Pattern Double
+ Sound.Tidal.Control: in10 :: Pattern Double
+ Sound.Tidal.Control: in100 :: Pattern Double
+ Sound.Tidal.Control: in101 :: Pattern Double
+ Sound.Tidal.Control: in102 :: Pattern Double
+ Sound.Tidal.Control: in103 :: Pattern Double
+ Sound.Tidal.Control: in104 :: Pattern Double
+ Sound.Tidal.Control: in105 :: Pattern Double
+ Sound.Tidal.Control: in106 :: Pattern Double
+ Sound.Tidal.Control: in107 :: Pattern Double
+ Sound.Tidal.Control: in108 :: Pattern Double
+ Sound.Tidal.Control: in109 :: Pattern Double
+ Sound.Tidal.Control: in11 :: Pattern Double
+ Sound.Tidal.Control: in110 :: Pattern Double
+ Sound.Tidal.Control: in111 :: Pattern Double
+ Sound.Tidal.Control: in112 :: Pattern Double
+ Sound.Tidal.Control: in113 :: Pattern Double
+ Sound.Tidal.Control: in114 :: Pattern Double
+ Sound.Tidal.Control: in115 :: Pattern Double
+ Sound.Tidal.Control: in116 :: Pattern Double
+ Sound.Tidal.Control: in117 :: Pattern Double
+ Sound.Tidal.Control: in118 :: Pattern Double
+ Sound.Tidal.Control: in119 :: Pattern Double
+ Sound.Tidal.Control: in12 :: Pattern Double
+ Sound.Tidal.Control: in120 :: Pattern Double
+ Sound.Tidal.Control: in121 :: Pattern Double
+ Sound.Tidal.Control: in122 :: Pattern Double
+ Sound.Tidal.Control: in123 :: Pattern Double
+ Sound.Tidal.Control: in124 :: Pattern Double
+ Sound.Tidal.Control: in125 :: Pattern Double
+ Sound.Tidal.Control: in126 :: Pattern Double
+ Sound.Tidal.Control: in127 :: Pattern Double
+ Sound.Tidal.Control: in13 :: Pattern Double
+ Sound.Tidal.Control: in14 :: Pattern Double
+ Sound.Tidal.Control: in15 :: Pattern Double
+ Sound.Tidal.Control: in16 :: Pattern Double
+ Sound.Tidal.Control: in17 :: Pattern Double
+ Sound.Tidal.Control: in18 :: Pattern Double
+ Sound.Tidal.Control: in19 :: Pattern Double
+ Sound.Tidal.Control: in2 :: Pattern Double
+ Sound.Tidal.Control: in20 :: Pattern Double
+ Sound.Tidal.Control: in21 :: Pattern Double
+ Sound.Tidal.Control: in22 :: Pattern Double
+ Sound.Tidal.Control: in23 :: Pattern Double
+ Sound.Tidal.Control: in24 :: Pattern Double
+ Sound.Tidal.Control: in25 :: Pattern Double
+ Sound.Tidal.Control: in26 :: Pattern Double
+ Sound.Tidal.Control: in27 :: Pattern Double
+ Sound.Tidal.Control: in28 :: Pattern Double
+ Sound.Tidal.Control: in29 :: Pattern Double
+ Sound.Tidal.Control: in3 :: Pattern Double
+ Sound.Tidal.Control: in30 :: Pattern Double
+ Sound.Tidal.Control: in31 :: Pattern Double
+ Sound.Tidal.Control: in32 :: Pattern Double
+ Sound.Tidal.Control: in33 :: Pattern Double
+ Sound.Tidal.Control: in34 :: Pattern Double
+ Sound.Tidal.Control: in35 :: Pattern Double
+ Sound.Tidal.Control: in36 :: Pattern Double
+ Sound.Tidal.Control: in37 :: Pattern Double
+ Sound.Tidal.Control: in38 :: Pattern Double
+ Sound.Tidal.Control: in39 :: Pattern Double
+ Sound.Tidal.Control: in4 :: Pattern Double
+ Sound.Tidal.Control: in40 :: Pattern Double
+ Sound.Tidal.Control: in41 :: Pattern Double
+ Sound.Tidal.Control: in42 :: Pattern Double
+ Sound.Tidal.Control: in43 :: Pattern Double
+ Sound.Tidal.Control: in44 :: Pattern Double
+ Sound.Tidal.Control: in45 :: Pattern Double
+ Sound.Tidal.Control: in46 :: Pattern Double
+ Sound.Tidal.Control: in47 :: Pattern Double
+ Sound.Tidal.Control: in48 :: Pattern Double
+ Sound.Tidal.Control: in49 :: Pattern Double
+ Sound.Tidal.Control: in5 :: Pattern Double
+ Sound.Tidal.Control: in50 :: Pattern Double
+ Sound.Tidal.Control: in51 :: Pattern Double
+ Sound.Tidal.Control: in52 :: Pattern Double
+ Sound.Tidal.Control: in53 :: Pattern Double
+ Sound.Tidal.Control: in54 :: Pattern Double
+ Sound.Tidal.Control: in55 :: Pattern Double
+ Sound.Tidal.Control: in56 :: Pattern Double
+ Sound.Tidal.Control: in57 :: Pattern Double
+ Sound.Tidal.Control: in58 :: Pattern Double
+ Sound.Tidal.Control: in59 :: Pattern Double
+ Sound.Tidal.Control: in6 :: Pattern Double
+ Sound.Tidal.Control: in60 :: Pattern Double
+ Sound.Tidal.Control: in61 :: Pattern Double
+ Sound.Tidal.Control: in62 :: Pattern Double
+ Sound.Tidal.Control: in63 :: Pattern Double
+ Sound.Tidal.Control: in64 :: Pattern Double
+ Sound.Tidal.Control: in65 :: Pattern Double
+ Sound.Tidal.Control: in66 :: Pattern Double
+ Sound.Tidal.Control: in67 :: Pattern Double
+ Sound.Tidal.Control: in68 :: Pattern Double
+ Sound.Tidal.Control: in69 :: Pattern Double
+ Sound.Tidal.Control: in7 :: Pattern Double
+ Sound.Tidal.Control: in70 :: Pattern Double
+ Sound.Tidal.Control: in71 :: Pattern Double
+ Sound.Tidal.Control: in72 :: Pattern Double
+ Sound.Tidal.Control: in73 :: Pattern Double
+ Sound.Tidal.Control: in74 :: Pattern Double
+ Sound.Tidal.Control: in75 :: Pattern Double
+ Sound.Tidal.Control: in76 :: Pattern Double
+ Sound.Tidal.Control: in77 :: Pattern Double
+ Sound.Tidal.Control: in78 :: Pattern Double
+ Sound.Tidal.Control: in79 :: Pattern Double
+ Sound.Tidal.Control: in8 :: Pattern Double
+ Sound.Tidal.Control: in80 :: Pattern Double
+ Sound.Tidal.Control: in81 :: Pattern Double
+ Sound.Tidal.Control: in82 :: Pattern Double
+ Sound.Tidal.Control: in83 :: Pattern Double
+ Sound.Tidal.Control: in84 :: Pattern Double
+ Sound.Tidal.Control: in85 :: Pattern Double
+ Sound.Tidal.Control: in86 :: Pattern Double
+ Sound.Tidal.Control: in87 :: Pattern Double
+ Sound.Tidal.Control: in88 :: Pattern Double
+ Sound.Tidal.Control: in89 :: Pattern Double
+ Sound.Tidal.Control: in9 :: Pattern Double
+ Sound.Tidal.Control: in90 :: Pattern Double
+ Sound.Tidal.Control: in91 :: Pattern Double
+ Sound.Tidal.Control: in92 :: Pattern Double
+ Sound.Tidal.Control: in93 :: Pattern Double
+ Sound.Tidal.Control: in94 :: Pattern Double
+ Sound.Tidal.Control: in95 :: Pattern Double
+ Sound.Tidal.Control: in96 :: Pattern Double
+ Sound.Tidal.Control: in97 :: Pattern Double
+ Sound.Tidal.Control: in98 :: Pattern Double
+ Sound.Tidal.Control: in99 :: Pattern Double
+ Sound.Tidal.Control: interlace :: ControlPattern -> ControlPattern -> ControlPattern
+ Sound.Tidal.Control: loopAt :: Pattern Time -> ControlPattern -> ControlPattern
+ Sound.Tidal.Control: mergePlayRange :: (Double, Double) -> ControlMap -> ControlMap
+ Sound.Tidal.Control: randslice :: Pattern Int -> ControlPattern -> ControlPattern
+ Sound.Tidal.Control: slice :: Pattern Int -> Pattern Int -> ControlPattern -> ControlPattern
+ Sound.Tidal.Control: smash :: Pattern Int -> [Pattern Time] -> ControlPattern -> Pattern ControlMap
+ Sound.Tidal.Control: smash' :: Int -> [Pattern Time] -> ControlPattern -> Pattern ControlMap
+ Sound.Tidal.Control: spin :: Pattern Int -> ControlPattern -> ControlPattern
+ Sound.Tidal.Control: striate :: Pattern Int -> ControlPattern -> ControlPattern
+ Sound.Tidal.Control: striate' :: Pattern Int -> Pattern Double -> ControlPattern -> ControlPattern
+ Sound.Tidal.Control: striateBy :: Pattern Int -> Pattern Double -> ControlPattern -> ControlPattern
+ Sound.Tidal.Control: stut :: Pattern Integer -> Pattern Double -> Pattern Rational -> ControlPattern -> ControlPattern
+ Sound.Tidal.Control: stut' :: Pattern Int -> Pattern Time -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
+ Sound.Tidal.Control: stutWith :: Pattern Int -> Pattern Time -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
+ Sound.Tidal.Control: weave :: Time -> ControlPattern -> [ControlPattern] -> ControlPattern
+ Sound.Tidal.Control: weave' :: Time -> Pattern a -> [Pattern a -> Pattern a] -> Pattern a
+ Sound.Tidal.Control: weaveWith :: Time -> Pattern a -> [Pattern a -> Pattern a] -> Pattern a
+ Sound.Tidal.Core: (#) :: Unionable b => Pattern b -> Pattern b -> Pattern b
+ Sound.Tidal.Core: (%|) :: Real a => Pattern a -> Pattern a -> Pattern a
+ Sound.Tidal.Core: (*|) :: Num a => Pattern a -> Pattern a -> Pattern a
+ Sound.Tidal.Core: (+|) :: Num a => Pattern a -> Pattern a -> Pattern a
+ Sound.Tidal.Core: (-|) :: Num a => Pattern a -> Pattern a -> Pattern a
+ Sound.Tidal.Core: (/|) :: Fractional a => Pattern a -> Pattern a -> Pattern a
+ Sound.Tidal.Core: (<|) :: Unionable a => Pattern a -> Pattern a -> Pattern a
+ Sound.Tidal.Core: (<~) :: Pattern Time -> Pattern a -> Pattern a
+ Sound.Tidal.Core: (>|) :: Unionable a => Pattern a -> Pattern a -> Pattern a
+ Sound.Tidal.Core: (|%) :: Real a => Pattern a -> Pattern a -> Pattern a
+ Sound.Tidal.Core: (|%|) :: (Applicative a, Real b) => a b -> a b -> a b
+ Sound.Tidal.Core: (|*) :: Num a => Pattern a -> Pattern a -> Pattern a
+ Sound.Tidal.Core: (|*|) :: (Applicative a, Num b) => a b -> a b -> a b
+ Sound.Tidal.Core: (|+) :: Num a => Pattern a -> Pattern a -> Pattern a
+ Sound.Tidal.Core: (|+|) :: (Applicative a, Num b) => a b -> a b -> a b
+ Sound.Tidal.Core: (|-) :: Num a => Pattern a -> Pattern a -> Pattern a
+ Sound.Tidal.Core: (|-|) :: (Applicative a, Num b) => a b -> a b -> a b
+ Sound.Tidal.Core: (|/) :: Fractional a => Pattern a -> Pattern a -> Pattern a
+ Sound.Tidal.Core: (|/|) :: (Applicative a, Fractional b) => a b -> a b -> a b
+ Sound.Tidal.Core: (|<) :: Unionable a => Pattern a -> Pattern a -> Pattern a
+ Sound.Tidal.Core: (|<|) :: (Applicative a, Unionable b) => a b -> a b -> a b
+ Sound.Tidal.Core: (|>) :: Unionable a => Pattern a -> Pattern a -> Pattern a
+ Sound.Tidal.Core: (|>|) :: (Applicative a, Unionable b) => a b -> a b -> a b
+ Sound.Tidal.Core: (~>) :: Pattern Time -> Pattern a -> Pattern a
+ Sound.Tidal.Core: _every :: Int -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
+ Sound.Tidal.Core: _every' :: Int -> Int -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
+ Sound.Tidal.Core: _fast :: Time -> Pattern a -> Pattern a
+ Sound.Tidal.Core: _run :: (Enum a, Num a) => a -> Pattern a
+ Sound.Tidal.Core: _scan :: (Enum a, Num a) => a -> Pattern a
+ Sound.Tidal.Core: _slow :: Time -> Pattern a -> Pattern a
+ Sound.Tidal.Core: append :: Pattern a -> Pattern a -> Pattern a
+ Sound.Tidal.Core: cat :: [Pattern a] -> Pattern a
+ Sound.Tidal.Core: class Unionable a
+ Sound.Tidal.Core: compress :: (Time, Time) -> Pattern a -> Pattern a
+ Sound.Tidal.Core: compressTo :: (Time, Time) -> Pattern a -> Pattern a
+ Sound.Tidal.Core: cosine :: Fractional a => Pattern a
+ Sound.Tidal.Core: density :: Pattern Time -> Pattern a -> Pattern a
+ Sound.Tidal.Core: densityGap :: Pattern Time -> Pattern a -> Pattern a
+ Sound.Tidal.Core: envEq :: Pattern Double
+ Sound.Tidal.Core: envEqR :: Pattern Double
+ Sound.Tidal.Core: envL :: Pattern Double
+ Sound.Tidal.Core: envLR :: Pattern Double
+ Sound.Tidal.Core: every :: Pattern Int -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
+ Sound.Tidal.Core: every' :: Pattern Int -> Pattern Int -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
+ Sound.Tidal.Core: fast :: Pattern Time -> Pattern a -> Pattern a
+ Sound.Tidal.Core: fastAppend :: Pattern a -> Pattern a -> Pattern a
+ Sound.Tidal.Core: fastCat :: [Pattern a] -> Pattern a
+ Sound.Tidal.Core: fastFromList :: [a] -> Pattern a
+ Sound.Tidal.Core: fastGap :: Pattern Time -> Pattern a -> Pattern a
+ Sound.Tidal.Core: fastRepeatCycles :: Int -> Pattern a -> Pattern a
+ Sound.Tidal.Core: fastSqueeze :: Pattern Time -> Pattern a -> Pattern a
+ Sound.Tidal.Core: fastcat :: [Pattern a] -> Pattern a
+ Sound.Tidal.Core: foldEvery :: [Int] -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
+ Sound.Tidal.Core: fromList :: [a] -> Pattern a
+ Sound.Tidal.Core: fromMaybes :: [Maybe a] -> Pattern a
+ Sound.Tidal.Core: instance Sound.Tidal.Core.Unionable Sound.Tidal.Pattern.ControlMap
+ Sound.Tidal.Core: instance Sound.Tidal.Core.Unionable a
+ Sound.Tidal.Core: isaw :: (Fractional a, Real a) => Pattern a
+ Sound.Tidal.Core: listToPat :: [a] -> Pattern a
+ Sound.Tidal.Core: overlay :: Pattern a -> Pattern a -> Pattern a
+ Sound.Tidal.Core: repeatCycles :: Int -> Pattern a -> Pattern a
+ Sound.Tidal.Core: rev :: Pattern a -> Pattern a
+ Sound.Tidal.Core: run :: (Enum a, Num a) => Pattern a -> Pattern a
+ Sound.Tidal.Core: saw :: (Fractional a, Real a) => Pattern a
+ Sound.Tidal.Core: scan :: (Enum a, Num a) => Pattern a -> Pattern a
+ Sound.Tidal.Core: sig :: (Time -> a) -> Pattern a
+ Sound.Tidal.Core: silence :: Pattern a
+ Sound.Tidal.Core: sine :: Fractional a => Pattern a
+ Sound.Tidal.Core: slow :: Pattern Time -> Pattern a -> Pattern a
+ Sound.Tidal.Core: slowAppend :: Pattern a -> Pattern a -> Pattern a
+ Sound.Tidal.Core: slowCat :: [Pattern a] -> Pattern a
+ Sound.Tidal.Core: slowSqueeze :: Pattern Time -> Pattern a -> Pattern a
+ Sound.Tidal.Core: slowcat :: [Pattern a] -> Pattern a
+ Sound.Tidal.Core: sparsity :: Pattern Time -> Pattern a -> Pattern a
+ Sound.Tidal.Core: square :: Fractional a => Pattern a
+ Sound.Tidal.Core: stack :: [Pattern a] -> Pattern a
+ Sound.Tidal.Core: timeCat :: [(Time, Pattern a)] -> Pattern a
+ Sound.Tidal.Core: tri :: (Fractional a, Real a) => Pattern a
+ Sound.Tidal.Core: union :: Unionable a => a -> a -> a
+ Sound.Tidal.Core: when :: (Int -> Bool) -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
+ Sound.Tidal.Core: whenT :: (Time -> Bool) -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
+ Sound.Tidal.Core: zoom :: (Time, Time) -> Pattern a -> Pattern a
+ Sound.Tidal.Core: zoomArc :: Arc -> Pattern a -> Pattern a
+ Sound.Tidal.EspGrid: cpsEsp :: Real t => t -> IO ()
+ Sound.Tidal.EspGrid: tidalEspGridLink :: MVar Tempo -> IO ()
+ Sound.Tidal.MiniTidal: instance Sound.Tidal.MiniTidal.Pattern' GHC.Base.String
+ Sound.Tidal.MiniTidal: instance Sound.Tidal.MiniTidal.Pattern' GHC.Integer.Type.Integer
+ Sound.Tidal.MiniTidal: instance Sound.Tidal.MiniTidal.Pattern' GHC.Types.Double
+ Sound.Tidal.MiniTidal: instance Sound.Tidal.MiniTidal.Pattern' GHC.Types.Int
+ Sound.Tidal.MiniTidal: instance Sound.Tidal.MiniTidal.Pattern' Sound.Tidal.Pattern.Arc
+ Sound.Tidal.MiniTidal: instance Sound.Tidal.MiniTidal.Pattern' Sound.Tidal.Pattern.ControlMap
+ Sound.Tidal.MiniTidal: instance Sound.Tidal.MiniTidal.Pattern' Sound.Tidal.Pattern.Time
+ Sound.Tidal.MiniTidal: main :: IO ()
+ Sound.Tidal.MiniTidal: miniTidal :: String -> Either ParseError (Pattern ControlMap)
+ Sound.Tidal.MiniTidal: miniTidalIO :: Stream -> String -> Either ParseError (IO ())
+ Sound.Tidal.Params: button0 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: button1 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: button10 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: button11 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: button12 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: button13 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: button14 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: button15 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: button16 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: button17 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: button18 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: button19 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: button2 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: button20 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: button21 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: button22 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: button23 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: button24 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: button25 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: button26 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: button27 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: button28 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: button29 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: button3 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: button30 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: button31 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: button4 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: button5 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: button6 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: button7 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: button8 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: button9 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: cps :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: mF :: String -> String -> ControlMap
+ Sound.Tidal.Params: mI :: String -> String -> ControlMap
+ Sound.Tidal.Params: mS :: String -> String -> ControlMap
+ Sound.Tidal.Params: slider0 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: slider1 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: slider10 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: slider11 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: slider12 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: slider13 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: slider14 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: slider15 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: slider16 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: slider17 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: slider18 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: slider19 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: slider2 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: slider20 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: slider21 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: slider22 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: slider23 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: slider24 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: slider25 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: slider26 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: slider27 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: slider28 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: slider29 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: slider3 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: slider30 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: slider31 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: slider4 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: slider5 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: slider6 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: slider7 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: slider8 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: slider9 :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: squiz :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: up :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: waveloss :: Pattern Double -> ControlPattern
+ Sound.Tidal.ParseBP: Negative :: Sign
+ Sound.Tidal.ParseBP: Positive :: Sign
+ Sound.Tidal.ParseBP: TPat_Atom :: a -> TPat a
+ Sound.Tidal.ParseBP: TPat_Cat :: [TPat a] -> TPat a
+ Sound.Tidal.ParseBP: TPat_DegradeBy :: Double -> TPat a -> TPat a
+ Sound.Tidal.ParseBP: TPat_Density :: TPat Time -> TPat a -> TPat a
+ Sound.Tidal.ParseBP: TPat_Elongate :: Int -> TPat a
+ Sound.Tidal.ParseBP: TPat_EnumFromTo :: TPat a -> TPat a -> TPat a
+ Sound.Tidal.ParseBP: TPat_Foot :: TPat a
+ Sound.Tidal.ParseBP: TPat_Overlay :: TPat a -> TPat a -> TPat a
+ Sound.Tidal.ParseBP: TPat_ShiftL :: Time -> TPat a -> TPat a
+ Sound.Tidal.ParseBP: TPat_Silence :: TPat a
+ Sound.Tidal.ParseBP: TPat_Slow :: TPat Time -> TPat a -> TPat a
+ Sound.Tidal.ParseBP: TPat_Stack :: [TPat a] -> TPat a
+ Sound.Tidal.ParseBP: TPat_TimeCat :: [TPat a] -> TPat a
+ Sound.Tidal.ParseBP: TPat_Zoom :: Arc -> TPat a -> TPat a
+ Sound.Tidal.ParseBP: TPat_pE :: TPat Int -> TPat Int -> TPat Int -> TPat a -> TPat a
+ Sound.Tidal.ParseBP: TidalParseError :: ParseError -> String -> TidalParseError
+ Sound.Tidal.ParseBP: [code] :: TidalParseError -> String
+ Sound.Tidal.ParseBP: [parsecError] :: TidalParseError -> ParseError
+ Sound.Tidal.ParseBP: angles :: Parser a -> Parser a
+ Sound.Tidal.ParseBP: applySign :: Num a => Sign -> a -> a
+ Sound.Tidal.ParseBP: braces :: Parser a -> Parser a
+ Sound.Tidal.ParseBP: brackets :: Parser a -> Parser a
+ Sound.Tidal.ParseBP: class Enumerable a
+ Sound.Tidal.ParseBP: class Parseable a
+ Sound.Tidal.ParseBP: data Sign
+ Sound.Tidal.ParseBP: data TPat a
+ Sound.Tidal.ParseBP: data TidalParseError
+ Sound.Tidal.ParseBP: doEuclid :: Parseable a => Pattern Int -> Pattern Int -> Pattern Int -> Pattern a -> Pattern a
+ Sound.Tidal.ParseBP: durations :: [TPat a] -> [(Int, TPat a)]
+ Sound.Tidal.ParseBP: elongate :: [TPat a] -> TPat a
+ Sound.Tidal.ParseBP: enumFromThenTo' :: (Ord a, Enum a, Num a) => a -> a -> a -> Pattern a
+ Sound.Tidal.ParseBP: enumFromTo' :: (Ord a, Enum a) => a -> a -> Pattern a
+ Sound.Tidal.ParseBP: float :: Parser Double
+ Sound.Tidal.ParseBP: fromNote :: Num a => Pattern String -> Pattern a
+ Sound.Tidal.ParseBP: fromThenTo :: Enumerable a => a -> a -> a -> Pattern a
+ Sound.Tidal.ParseBP: fromTo :: Enumerable a => a -> a -> Pattern a
+ Sound.Tidal.ParseBP: instance (Sound.Tidal.ParseBP.Enumerable a, Sound.Tidal.ParseBP.Parseable a) => Data.String.IsString (Sound.Tidal.Pattern.Pattern a)
+ Sound.Tidal.ParseBP: instance GHC.Classes.Eq Sound.Tidal.ParseBP.TidalParseError
+ Sound.Tidal.ParseBP: instance GHC.Exception.Type.Exception Sound.Tidal.ParseBP.TidalParseError
+ Sound.Tidal.ParseBP: instance GHC.Show.Show Sound.Tidal.ParseBP.TidalParseError
+ Sound.Tidal.ParseBP: instance GHC.Show.Show a => GHC.Show.Show (Sound.Tidal.ParseBP.TPat a)
+ Sound.Tidal.ParseBP: instance Sound.Tidal.ParseBP.Enumerable GHC.Base.String
+ Sound.Tidal.ParseBP: instance Sound.Tidal.ParseBP.Enumerable GHC.Integer.Type.Integer
+ Sound.Tidal.ParseBP: instance Sound.Tidal.ParseBP.Enumerable GHC.Real.Rational
+ Sound.Tidal.ParseBP: instance Sound.Tidal.ParseBP.Enumerable GHC.Types.Bool
+ Sound.Tidal.ParseBP: instance Sound.Tidal.ParseBP.Enumerable GHC.Types.Double
+ Sound.Tidal.ParseBP: instance Sound.Tidal.ParseBP.Enumerable GHC.Types.Int
+ Sound.Tidal.ParseBP: instance Sound.Tidal.ParseBP.Enumerable Sound.Tidal.ParseBP.ColourD
+ Sound.Tidal.ParseBP: instance Sound.Tidal.ParseBP.Parseable GHC.Base.String
+ Sound.Tidal.ParseBP: instance Sound.Tidal.ParseBP.Parseable GHC.Integer.Type.Integer
+ Sound.Tidal.ParseBP: instance Sound.Tidal.ParseBP.Parseable GHC.Real.Rational
+ Sound.Tidal.ParseBP: instance Sound.Tidal.ParseBP.Parseable GHC.Types.Bool
+ Sound.Tidal.ParseBP: instance Sound.Tidal.ParseBP.Parseable GHC.Types.Double
+ Sound.Tidal.ParseBP: instance Sound.Tidal.ParseBP.Parseable GHC.Types.Int
+ Sound.Tidal.ParseBP: instance Sound.Tidal.ParseBP.Parseable Sound.Tidal.ParseBP.ColourD
+ Sound.Tidal.ParseBP: intOrFloat :: Parser Double
+ Sound.Tidal.ParseBP: integer :: Parser Integer
+ Sound.Tidal.ParseBP: lexer :: GenTokenParser String u Identity
+ Sound.Tidal.ParseBP: natural :: Parser Integer
+ Sound.Tidal.ParseBP: naturalOrFloat :: Parser (Either Integer Double)
+ Sound.Tidal.ParseBP: pBool :: Parser (TPat Bool)
+ Sound.Tidal.ParseBP: pColour :: Parser (TPat ColourD)
+ Sound.Tidal.ParseBP: pDouble :: Parser (TPat Double)
+ Sound.Tidal.ParseBP: pE :: TPat a -> Parser (TPat a)
+ Sound.Tidal.ParseBP: pIntegral :: Integral a => Parser (TPat a)
+ Sound.Tidal.ParseBP: pMult :: TPat a -> Parser (TPat a)
+ Sound.Tidal.ParseBP: pPart :: Parseable a => Parser (TPat a) -> Parser [TPat a]
+ Sound.Tidal.ParseBP: pPolyIn :: Parseable a => Parser (TPat a) -> Parser (TPat a)
+ Sound.Tidal.ParseBP: pPolyOut :: Parseable a => Parser (TPat a) -> Parser (TPat a)
+ Sound.Tidal.ParseBP: pRand :: TPat a -> Parser (TPat a)
+ Sound.Tidal.ParseBP: pRatio :: Parser Rational
+ Sound.Tidal.ParseBP: pRational :: Parser (TPat Rational)
+ Sound.Tidal.ParseBP: pReplicate :: TPat a -> Parser [TPat a]
+ Sound.Tidal.ParseBP: pSequence :: Parseable a => Parser (TPat a) -> GenParser Char () (TPat a)
+ Sound.Tidal.ParseBP: pSequenceN :: Parseable a => Parser (TPat a) -> GenParser Char () (Int, TPat a)
+ Sound.Tidal.ParseBP: pSingle :: Parser (TPat a) -> Parser (TPat a)
+ Sound.Tidal.ParseBP: pStretch :: TPat a -> Parser [TPat a]
+ Sound.Tidal.ParseBP: pString :: Parser String
+ Sound.Tidal.ParseBP: pVocable :: Parser (TPat String)
+ Sound.Tidal.ParseBP: parens :: Parser a -> Parser a
+ Sound.Tidal.ParseBP: parseBP :: (Enumerable a, Parseable a) => String -> Either ParseError (Pattern a)
+ Sound.Tidal.ParseBP: parseBP_E :: (Enumerable a, Parseable a) => String -> Pattern a
+ Sound.Tidal.ParseBP: parseChord :: Num a => Parser [a]
+ Sound.Tidal.ParseBP: parseInt :: Parser Int
+ Sound.Tidal.ParseBP: parseIntNote :: Integral i => Parser i
+ Sound.Tidal.ParseBP: parseNote :: Num a => Parser a
+ Sound.Tidal.ParseBP: parseRhythm :: Parseable a => Parser (TPat a) -> String -> Either ParseError (TPat a)
+ Sound.Tidal.ParseBP: parseTPat :: Parseable a => String -> Either ParseError (TPat a)
+ Sound.Tidal.ParseBP: sign :: Parser Sign
+ Sound.Tidal.ParseBP: splitFeet :: [TPat t] -> [[TPat t]]
+ Sound.Tidal.ParseBP: symbol :: String -> Parser String
+ Sound.Tidal.ParseBP: tPatParser :: Parseable a => Parser (TPat a)
+ Sound.Tidal.ParseBP: toPat :: (Enumerable a, Parseable a) => TPat a -> Pattern a
+ Sound.Tidal.ParseBP: type ColourD = Colour Double
+ Sound.Tidal.Pattern: (*>) :: Pattern (a -> b) -> Pattern a -> Pattern b
+ Sound.Tidal.Pattern: (<*) :: Pattern (a -> b) -> Pattern a -> Pattern b
+ Sound.Tidal.Pattern: (~==) :: TolerantEq a => a -> a -> Bool
+ Sound.Tidal.Pattern: Analog :: Nature
+ Sound.Tidal.Pattern: Arc :: a -> a -> ArcF a
+ Sound.Tidal.Pattern: Digital :: Nature
+ Sound.Tidal.Pattern: Event :: a -> a -> b -> EventF a b
+ Sound.Tidal.Pattern: State :: Arc -> ControlMap -> State
+ Sound.Tidal.Pattern: VF :: Double -> Value
+ Sound.Tidal.Pattern: VI :: Int -> Value
+ Sound.Tidal.Pattern: VS :: String -> Value
+ Sound.Tidal.Pattern: [controls] :: State -> ControlMap
+ Sound.Tidal.Pattern: [fvalue] :: Value -> Double
+ Sound.Tidal.Pattern: [ivalue] :: Value -> Int
+ Sound.Tidal.Pattern: [nature] :: Pattern a -> Nature
+ Sound.Tidal.Pattern: [part] :: EventF a b -> a
+ Sound.Tidal.Pattern: [query] :: Pattern a -> Query a
+ Sound.Tidal.Pattern: [start] :: ArcF a -> a
+ Sound.Tidal.Pattern: [stop] :: ArcF a -> a
+ Sound.Tidal.Pattern: [svalue] :: Value -> String
+ Sound.Tidal.Pattern: [value] :: EventF a b -> b
+ Sound.Tidal.Pattern: [whole] :: EventF a b -> a
+ Sound.Tidal.Pattern: _fastGap :: Time -> Pattern a -> Pattern a
+ Sound.Tidal.Pattern: applyFIS :: (Double -> Double) -> (Int -> Int) -> (String -> String) -> Value -> Value
+ Sound.Tidal.Pattern: arcCycles :: Arc -> [Arc]
+ Sound.Tidal.Pattern: arcCyclesZW :: Arc -> [Arc]
+ Sound.Tidal.Pattern: class TolerantEq a
+ Sound.Tidal.Pattern: compareDefrag :: Ord a => [Event a] -> [Event a] -> Bool
+ Sound.Tidal.Pattern: compressArc :: Arc -> Pattern a -> Pattern a
+ Sound.Tidal.Pattern: compressArcTo :: Arc -> Pattern a -> Pattern a
+ Sound.Tidal.Pattern: cycleArcsInArc :: Arc -> [Arc]
+ Sound.Tidal.Pattern: cyclePos :: Time -> Time
+ Sound.Tidal.Pattern: cyclesInArc :: Integral a => Arc -> [a]
+ Sound.Tidal.Pattern: data ArcF a
+ Sound.Tidal.Pattern: data EventF a b
+ Sound.Tidal.Pattern: data Nature
+ Sound.Tidal.Pattern: data Pattern a
+ Sound.Tidal.Pattern: data State
+ Sound.Tidal.Pattern: data Value
+ Sound.Tidal.Pattern: defragParts :: Eq a => [Event a] -> [Event a]
+ Sound.Tidal.Pattern: empty :: Pattern a
+ Sound.Tidal.Pattern: eventHasOnset :: Event a -> Bool
+ Sound.Tidal.Pattern: eventPart :: Event a -> Arc
+ Sound.Tidal.Pattern: eventPartStart :: Event a -> Time
+ Sound.Tidal.Pattern: eventPartStop :: Event a -> Time
+ Sound.Tidal.Pattern: eventValue :: Event a -> a
+ Sound.Tidal.Pattern: fNum2 :: (Int -> Int -> Int) -> (Double -> Double -> Double) -> Value -> Value -> Value
+ Sound.Tidal.Pattern: filterWhen :: (Time -> Bool) -> Pattern a -> Pattern a
+ Sound.Tidal.Pattern: getF :: Value -> Maybe Double
+ Sound.Tidal.Pattern: getI :: Value -> Maybe Int
+ Sound.Tidal.Pattern: getS :: Value -> Maybe String
+ Sound.Tidal.Pattern: hull :: Arc -> Arc -> Arc
+ Sound.Tidal.Pattern: infixl 4 *>
+ Sound.Tidal.Pattern: innerJoin :: Pattern (Pattern a) -> Pattern a
+ Sound.Tidal.Pattern: instance (GHC.Classes.Eq a, GHC.Classes.Eq b) => GHC.Classes.Eq (Sound.Tidal.Pattern.EventF a b)
+ Sound.Tidal.Pattern: instance (GHC.Classes.Ord a, GHC.Classes.Ord b) => GHC.Classes.Ord (Sound.Tidal.Pattern.EventF a b)
+ Sound.Tidal.Pattern: instance Data.Bifunctor.Bifunctor Sound.Tidal.Pattern.EventF
+ Sound.Tidal.Pattern: instance Data.Data.Data Sound.Tidal.Pattern.Value
+ Sound.Tidal.Pattern: instance GHC.Base.Applicative Sound.Tidal.Pattern.ArcF
+ Sound.Tidal.Pattern: instance GHC.Base.Functor (Sound.Tidal.Pattern.EventF a)
+ Sound.Tidal.Pattern: instance GHC.Base.Functor Sound.Tidal.Pattern.ArcF
+ Sound.Tidal.Pattern: instance GHC.Classes.Eq Sound.Tidal.Pattern.Nature
+ Sound.Tidal.Pattern: instance GHC.Classes.Eq Sound.Tidal.Pattern.Value
+ Sound.Tidal.Pattern: instance GHC.Classes.Eq a => GHC.Classes.Eq (Sound.Tidal.Pattern.ArcF a)
+ Sound.Tidal.Pattern: instance GHC.Classes.Ord Sound.Tidal.Pattern.Value
+ Sound.Tidal.Pattern: instance GHC.Classes.Ord a => GHC.Classes.Ord (Sound.Tidal.Pattern.ArcF a)
+ Sound.Tidal.Pattern: instance GHC.Num.Num Sound.Tidal.Pattern.ControlMap
+ Sound.Tidal.Pattern: instance GHC.Num.Num a => GHC.Num.Num (Sound.Tidal.Pattern.ArcF a)
+ Sound.Tidal.Pattern: instance GHC.Real.Fractional Sound.Tidal.Pattern.ControlMap
+ Sound.Tidal.Pattern: instance GHC.Real.Fractional a => GHC.Real.Fractional (Sound.Tidal.Pattern.ArcF a)
+ Sound.Tidal.Pattern: instance GHC.Show.Show Sound.Tidal.Pattern.Arc
+ Sound.Tidal.Pattern: instance GHC.Show.Show Sound.Tidal.Pattern.ControlMap
+ Sound.Tidal.Pattern: instance GHC.Show.Show Sound.Tidal.Pattern.Value
+ Sound.Tidal.Pattern: instance GHC.Show.Show a => GHC.Show.Show (Sound.Tidal.Pattern.Event a)
+ Sound.Tidal.Pattern: instance Sound.Tidal.Pattern.TolerantEq (Sound.Tidal.Pattern.Event Sound.Tidal.Pattern.ControlMap)
+ Sound.Tidal.Pattern: instance Sound.Tidal.Pattern.TolerantEq Sound.Tidal.Pattern.ControlMap
+ Sound.Tidal.Pattern: instance Sound.Tidal.Pattern.TolerantEq Sound.Tidal.Pattern.Value
+ Sound.Tidal.Pattern: instance Sound.Tidal.Pattern.TolerantEq a => Sound.Tidal.Pattern.TolerantEq [a]
+ Sound.Tidal.Pattern: isAdjacent :: Eq a => Event a -> Event a -> Bool
+ Sound.Tidal.Pattern: isAnalog :: Pattern a -> Bool
+ Sound.Tidal.Pattern: isDigital :: Pattern a -> Bool
+ Sound.Tidal.Pattern: isIn :: Arc -> Time -> Bool
+ Sound.Tidal.Pattern: mapCycle :: (Time -> Time) -> Arc -> Arc
+ Sound.Tidal.Pattern: matchManyToOne :: (b -> a -> Bool) -> Pattern a -> Pattern b -> Pattern (Bool, b)
+ Sound.Tidal.Pattern: nextSam :: Time -> Time
+ Sound.Tidal.Pattern: onsetIn :: Arc -> Event a -> Bool
+ Sound.Tidal.Pattern: outerJoin :: Pattern (Pattern a) -> Pattern a
+ Sound.Tidal.Pattern: prettyRat :: Rational -> String
+ Sound.Tidal.Pattern: queryArc :: Pattern a -> Arc -> [Event a]
+ Sound.Tidal.Pattern: sam :: Time -> Time
+ Sound.Tidal.Pattern: sect :: Arc -> Arc -> Arc
+ Sound.Tidal.Pattern: showFrac :: Integer -> Integer -> String
+ Sound.Tidal.Pattern: showPattern :: Show a => Arc -> Pattern a -> String
+ Sound.Tidal.Pattern: subArc :: Arc -> Arc -> Maybe Arc
+ Sound.Tidal.Pattern: tParam :: (t1 -> t2 -> Pattern a) -> Pattern t1 -> t2 -> Pattern a
+ Sound.Tidal.Pattern: tParam2 :: (a -> b -> c -> Pattern d) -> Pattern a -> Pattern b -> c -> Pattern d
+ Sound.Tidal.Pattern: tParam3 :: (a -> b -> c -> Pattern d -> Pattern e) -> Pattern a -> Pattern b -> Pattern c -> Pattern d -> Pattern e
+ Sound.Tidal.Pattern: tParamSqueeze :: (a -> Pattern b -> Pattern c) -> Pattern a -> Pattern b -> Pattern c
+ Sound.Tidal.Pattern: timeToCycleArc :: Time -> Arc
+ Sound.Tidal.Pattern: toEvent :: (((Time, Time), (Time, Time)), a) -> Event a
+ Sound.Tidal.Pattern: toTime :: Real a => a -> Rational
+ Sound.Tidal.Pattern: type Arc = ArcF Time
+ Sound.Tidal.Pattern: type ControlMap = Map String Value
+ Sound.Tidal.Pattern: type ControlPattern = Pattern ControlMap
+ Sound.Tidal.Pattern: type Event a = EventF (ArcF Time) a
+ Sound.Tidal.Pattern: type Query a = (State -> [Event a])
+ Sound.Tidal.Pattern: type Time = Rational
+ Sound.Tidal.Pattern: unwrapSqueeze :: Pattern (Pattern a) -> Pattern a
+ Sound.Tidal.Pattern: wholeStart :: Event a -> Time
+ Sound.Tidal.Pattern: wholeStop :: Event a -> Time
+ Sound.Tidal.Pattern: withEvents :: ([Event a] -> [Event b]) -> Pattern a -> Pattern b
+ Sound.Tidal.Pattern: withPart :: (Arc -> Arc) -> Pattern a -> Pattern a
+ Sound.Tidal.Scales: scale :: Num a => Pattern String -> Pattern Int -> Pattern a
+ Sound.Tidal.Scales: scaleList :: String
+ Sound.Tidal.Simple: silent :: ControlPattern -> ControlPattern
+ Sound.Tidal.Simple: skip :: ControlPattern -> ControlPattern
+ Sound.Tidal.Stream: BundleStamp :: TimeStamp
+ Sound.Tidal.Stream: MessageStamp :: TimeStamp
+ Sound.Tidal.Stream: NoStamp :: TimeStamp
+ Sound.Tidal.Stream: OSCTarget :: String -> Int -> String -> Maybe [(String, Maybe Value)] -> Double -> [Datum] -> TimeStamp -> OSCTarget
+ Sound.Tidal.Stream: PlayState :: ControlPattern -> Bool -> Bool -> [ControlPattern] -> PlayState
+ Sound.Tidal.Stream: Stream :: Config -> MVar ControlMap -> MVar ControlPattern -> Maybe ThreadId -> MVar PlayMap -> MVar Tempo -> OSCTarget -> UDP -> Stream
+ Sound.Tidal.Stream: [history] :: PlayState -> [ControlPattern]
+ Sound.Tidal.Stream: [mute] :: PlayState -> Bool
+ Sound.Tidal.Stream: [oAddress] :: OSCTarget -> String
+ Sound.Tidal.Stream: [oLatency] :: OSCTarget -> Double
+ Sound.Tidal.Stream: [oPath] :: OSCTarget -> String
+ Sound.Tidal.Stream: [oPort] :: OSCTarget -> Int
+ Sound.Tidal.Stream: [oPreamble] :: OSCTarget -> [Datum]
+ Sound.Tidal.Stream: [oShape] :: OSCTarget -> Maybe [(String, Maybe Value)]
+ Sound.Tidal.Stream: [oTimestamp] :: OSCTarget -> TimeStamp
+ Sound.Tidal.Stream: [pattern] :: PlayState -> ControlPattern
+ Sound.Tidal.Stream: [sConfig] :: Stream -> Config
+ Sound.Tidal.Stream: [sInput] :: Stream -> MVar ControlMap
+ Sound.Tidal.Stream: [sListenTid] :: Stream -> Maybe ThreadId
+ Sound.Tidal.Stream: [sOutput] :: Stream -> MVar ControlPattern
+ Sound.Tidal.Stream: [sPMapMV] :: Stream -> MVar PlayMap
+ Sound.Tidal.Stream: [sTarget] :: Stream -> OSCTarget
+ Sound.Tidal.Stream: [sTempoMV] :: Stream -> MVar Tempo
+ Sound.Tidal.Stream: [sUDP] :: Stream -> UDP
+ Sound.Tidal.Stream: [solo] :: PlayState -> Bool
+ Sound.Tidal.Stream: calcOutput :: Stream -> IO ()
+ Sound.Tidal.Stream: ctrlListen :: MVar ControlMap -> Config -> IO (Maybe ThreadId)
+ Sound.Tidal.Stream: data OSCTarget
+ Sound.Tidal.Stream: data PlayState
+ Sound.Tidal.Stream: data Stream
+ Sound.Tidal.Stream: data TimeStamp
+ Sound.Tidal.Stream: doCps :: MVar Tempo -> (Double, Maybe Value) -> IO ()
+ Sound.Tidal.Stream: hasSolo :: Map k PlayState -> Bool
+ Sound.Tidal.Stream: instance GHC.Classes.Eq Sound.Tidal.Stream.TimeStamp
+ Sound.Tidal.Stream: instance GHC.Show.Show Sound.Tidal.Stream.PlayState
+ Sound.Tidal.Stream: sched :: Tempo -> Rational -> Double
+ Sound.Tidal.Stream: send :: Transport t => Double -> t -> (Double, Message) -> IO ()
+ Sound.Tidal.Stream: startStream :: Config -> MVar ControlMap -> OSCTarget -> IO (MVar ControlPattern, MVar Tempo, UDP)
+ Sound.Tidal.Stream: startTidal :: OSCTarget -> Config -> IO Stream
+ Sound.Tidal.Stream: streamHush :: Stream -> IO ()
+ Sound.Tidal.Stream: streamList :: Stream -> IO ()
+ Sound.Tidal.Stream: streamMute :: Show a => Stream -> a -> IO ()
+ Sound.Tidal.Stream: streamMuteAll :: Stream -> IO ()
+ Sound.Tidal.Stream: streamMutes :: Show a => Stream -> [a] -> IO ()
+ Sound.Tidal.Stream: streamNudgeAll :: Stream -> Double -> IO ()
+ Sound.Tidal.Stream: streamOnce :: Stream -> Bool -> ControlPattern -> IO ()
+ Sound.Tidal.Stream: streamReplace :: Show a => Stream -> a -> ControlPattern -> IO ()
+ Sound.Tidal.Stream: streamResetCycles :: Stream -> IO ()
+ Sound.Tidal.Stream: streamSolo :: Show a => Stream -> a -> IO ()
+ Sound.Tidal.Stream: streamUnmute :: Show a => Stream -> a -> IO ()
+ Sound.Tidal.Stream: streamUnmuteAll :: Stream -> IO ()
+ Sound.Tidal.Stream: streamUnsolo :: Show a => Stream -> a -> IO ()
+ Sound.Tidal.Stream: superdirtTarget :: OSCTarget
+ Sound.Tidal.Stream: toData :: Event ControlMap -> [Datum]
+ Sound.Tidal.Stream: toDatum :: Value -> Datum
+ Sound.Tidal.Stream: toMessage :: OSCTarget -> Tempo -> Event (Map String Value) -> Message
+ Sound.Tidal.Stream: type PatId = String
+ Sound.Tidal.Stream: type PlayMap = Map PatId PlayState
+ Sound.Tidal.Stream: withPatId :: Stream -> PatId -> (PlayState -> PlayState) -> IO ()
+ Sound.Tidal.Stream: withPatIds :: Stream -> [PatId] -> (PlayState -> PlayState) -> IO ()
+ Sound.Tidal.Tempo: State :: Int -> Time -> Time -> Arc -> State
+ Sound.Tidal.Tempo: [atCycle] :: Tempo -> Rational
+ Sound.Tidal.Tempo: [atTime] :: Tempo -> Time
+ Sound.Tidal.Tempo: [localUDP] :: Tempo -> UDP
+ Sound.Tidal.Tempo: [nowArc] :: State -> Arc
+ Sound.Tidal.Tempo: [nowTime] :: State -> Time
+ Sound.Tidal.Tempo: [nudged] :: Tempo -> Double
+ Sound.Tidal.Tempo: [remoteAddr] :: Tempo -> SockAddr
+ Sound.Tidal.Tempo: [start] :: State -> Time
+ Sound.Tidal.Tempo: [ticks] :: State -> Int
+ Sound.Tidal.Tempo: clientListen :: Config -> Time -> IO (MVar Tempo, ThreadId)
+ Sound.Tidal.Tempo: data State
+ Sound.Tidal.Tempo: defaultTempo :: Time -> UDP -> SockAddr -> Tempo
+ Sound.Tidal.Tempo: listenTempo :: UDP -> MVar Tempo -> IO ()
+ Sound.Tidal.Tempo: resetCycles :: MVar Tempo -> IO Tempo
+ Sound.Tidal.Tempo: serverListen :: Config -> IO (Maybe ThreadId)
+ Sound.Tidal.Tempo: timeToCycles :: Tempo -> Time -> Rational
+ Sound.Tidal.Transition: anticipate :: Time -> [ControlPattern] -> ControlPattern
+ Sound.Tidal.Transition: anticipateIn :: Time -> Time -> [ControlPattern] -> ControlPattern
+ Sound.Tidal.Transition: clutch :: Time -> [Pattern a] -> Pattern a
+ Sound.Tidal.Transition: clutchIn :: Time -> Time -> [Pattern a] -> Pattern a
+ Sound.Tidal.Transition: interpolate :: Time -> [ControlPattern] -> ControlPattern
+ Sound.Tidal.Transition: waitT :: (Time -> [ControlPattern] -> ControlPattern) -> Time -> Time -> [ControlPattern] -> ControlPattern
+ Sound.Tidal.Transition: washIn :: (Pattern a -> Pattern a) -> Time -> Time -> [Pattern a] -> Pattern a
+ Sound.Tidal.Transition: xfadeIn :: Time -> Time -> [ControlPattern] -> ControlPattern
+ Sound.Tidal.UI: _degradeBy :: Double -> Pattern a -> Pattern a
+ Sound.Tidal.UI: _distrib :: [Int] -> Pattern a -> Pattern a
+ Sound.Tidal.UI: _euclid :: Int -> Int -> Pattern a -> Pattern a
+ Sound.Tidal.UI: _euclid' :: Int -> Int -> Pattern a -> Pattern a
+ Sound.Tidal.UI: _euclidBool :: Int -> Int -> Pattern Bool
+ Sound.Tidal.UI: _euclidFull :: Int -> Int -> Pattern a -> Pattern a -> Pattern a
+ Sound.Tidal.UI: _euclidInv :: Int -> Int -> Pattern a -> Pattern a
+ Sound.Tidal.UI: _euclidOff :: Int -> Int -> Int -> Pattern a -> Pattern a
+ Sound.Tidal.UI: _euclidOffBool :: Int -> Int -> Int -> Pattern Bool -> Pattern Bool
+ Sound.Tidal.UI: _iter :: Int -> Pattern a -> Pattern a
+ Sound.Tidal.UI: _iter' :: Int -> Pattern a -> Pattern a
+ Sound.Tidal.UI: _linger :: Time -> Pattern a -> Pattern a
+ Sound.Tidal.UI: _off :: Time -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
+ Sound.Tidal.UI: _ply :: Int -> Pattern a -> Pattern a
+ Sound.Tidal.UI: _range :: (Functor f, Num b) => b -> b -> f b -> f b
+ Sound.Tidal.UI: _rot :: Ord a => Int -> Pattern a -> Pattern a
+ Sound.Tidal.UI: _segment :: Time -> Pattern a -> Pattern a
+ Sound.Tidal.UI: _select :: Double -> [Pattern a] -> Pattern a
+ Sound.Tidal.UI: _stripe :: Int -> Pattern a -> Pattern a
+ Sound.Tidal.UI: _trunc :: Time -> Pattern a -> Pattern a
+ Sound.Tidal.UI: _unDegradeBy :: Double -> Pattern a -> Pattern a
+ Sound.Tidal.UI: almostAlways :: (Pattern a -> Pattern a) -> Pattern a -> Pattern a
+ Sound.Tidal.UI: almostNever :: (Pattern a -> Pattern a) -> Pattern a -> Pattern a
+ Sound.Tidal.UI: always :: (Pattern a -> Pattern a) -> Pattern a -> Pattern a
+ Sound.Tidal.UI: arpeggiate :: Pattern a -> Pattern a
+ Sound.Tidal.UI: arpg :: Pattern a -> Pattern a
+ Sound.Tidal.UI: brak :: Pattern a -> Pattern a
+ Sound.Tidal.UI: choose :: [a] -> Pattern a
+ Sound.Tidal.UI: chooseBy :: Pattern Double -> [a] -> Pattern a
+ Sound.Tidal.UI: chunk :: Int -> (Pattern b -> Pattern b) -> Pattern b -> Pattern b
+ Sound.Tidal.UI: chunk' :: Integral a => a -> (Pattern b -> Pattern b) -> Pattern b -> Pattern b
+ Sound.Tidal.UI: contrast :: (ControlPattern -> ControlPattern) -> (ControlPattern -> ControlPattern) -> ControlPattern -> ControlPattern -> ControlPattern
+ Sound.Tidal.UI: contrastBy :: (a -> Value -> Bool) -> (ControlPattern -> Pattern b) -> (ControlPattern -> Pattern b) -> Pattern (Map String a) -> Pattern (Map String Value) -> Pattern b
+ Sound.Tidal.UI: contrastRange :: (ControlPattern -> Pattern a) -> (ControlPattern -> Pattern a) -> Pattern (Map String (Value, Value)) -> ControlPattern -> Pattern a
+ Sound.Tidal.UI: cycleChoose :: [a] -> Pattern a
+ Sound.Tidal.UI: degrade :: Pattern a -> Pattern a
+ Sound.Tidal.UI: degradeBy :: Pattern Double -> Pattern a -> Pattern a
+ Sound.Tidal.UI: degradeOverBy :: Int -> Pattern Double -> Pattern a -> Pattern a
+ Sound.Tidal.UI: discretise :: Pattern Time -> Pattern a -> Pattern a
+ Sound.Tidal.UI: distrib :: [Pattern Int] -> Pattern a -> Pattern a
+ Sound.Tidal.UI: double :: Time -> Pattern a -> Pattern a
+ Sound.Tidal.UI: echo :: Time -> Pattern a -> Pattern a
+ Sound.Tidal.UI: enclosingArc :: [Arc] -> Arc
+ Sound.Tidal.UI: eoff :: Pattern Int -> Pattern Int -> Pattern Int -> Pattern a -> Pattern a
+ Sound.Tidal.UI: euclid :: Pattern Int -> Pattern Int -> Pattern a -> Pattern a
+ Sound.Tidal.UI: euclidFull :: Pattern Int -> Pattern Int -> Pattern a -> Pattern a -> Pattern a
+ Sound.Tidal.UI: euclidInv :: Pattern Int -> Pattern Int -> Pattern a -> Pattern a
+ Sound.Tidal.UI: euclidOff :: Pattern Int -> Pattern Int -> Pattern Int -> Pattern a -> Pattern a
+ Sound.Tidal.UI: euclidOffBool :: Pattern Int -> Pattern Int -> Pattern Int -> Pattern Bool -> Pattern Bool
+ Sound.Tidal.UI: fadeIn :: Time -> Pattern a -> Pattern a
+ Sound.Tidal.UI: fadeInFrom :: Time -> Time -> Pattern a -> Pattern a
+ Sound.Tidal.UI: fadeOut :: Time -> Pattern a -> Pattern a
+ Sound.Tidal.UI: fadeOutFrom :: Time -> Time -> Pattern a -> Pattern a
+ Sound.Tidal.UI: fastspread :: (a -> t -> Pattern b) -> [a] -> t -> Pattern b
+ Sound.Tidal.UI: fit :: Int -> [a] -> Pattern Int -> Pattern a
+ Sound.Tidal.UI: fit' :: Pattern Time -> Int -> Pattern Int -> Pattern Int -> Pattern a -> Pattern a
+ Sound.Tidal.UI: fix :: (ControlPattern -> ControlPattern) -> ControlPattern -> ControlPattern -> ControlPattern
+ Sound.Tidal.UI: fixRange :: (ControlPattern -> Pattern ControlMap) -> Pattern (Map String (Value, Value)) -> ControlPattern -> Pattern ControlMap
+ Sound.Tidal.UI: flatpat :: Pattern [a] -> Pattern a
+ Sound.Tidal.UI: ghost :: Pattern ControlMap -> Pattern ControlMap
+ Sound.Tidal.UI: ghost' :: Time -> Pattern ControlMap -> Pattern ControlMap
+ Sound.Tidal.UI: ghost'' :: Time -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
+ Sound.Tidal.UI: ifp :: (Int -> Bool) -> (Pattern a -> Pattern a) -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
+ Sound.Tidal.UI: index :: Real b => b -> Pattern b -> Pattern c -> Pattern c
+ Sound.Tidal.UI: inhabit :: [(String, Pattern a)] -> Pattern String -> Pattern a
+ Sound.Tidal.UI: inside :: Pattern Time -> (Pattern a1 -> Pattern a) -> Pattern a1 -> Pattern a
+ Sound.Tidal.UI: inv :: Functor f => f Bool -> f Bool
+ Sound.Tidal.UI: irand :: Num a => Int -> Pattern a
+ Sound.Tidal.UI: iter :: Pattern Int -> Pattern c -> Pattern c
+ Sound.Tidal.UI: iter' :: Pattern Int -> Pattern c -> Pattern c
+ Sound.Tidal.UI: jux :: (Pattern ControlMap -> Pattern ControlMap) -> Pattern ControlMap -> Pattern ControlMap
+ Sound.Tidal.UI: jux' :: [t -> Pattern ControlMap] -> t -> Pattern ControlMap
+ Sound.Tidal.UI: jux4 :: (Pattern ControlMap -> Pattern ControlMap) -> Pattern ControlMap -> Pattern ControlMap
+ Sound.Tidal.UI: juxBy :: Pattern Double -> (Pattern ControlMap -> Pattern ControlMap) -> Pattern ControlMap -> Pattern ControlMap
+ Sound.Tidal.UI: juxcut :: (Pattern ControlMap -> Pattern ControlMap) -> Pattern ControlMap -> Pattern ControlMap
+ Sound.Tidal.UI: juxcut' :: [t -> Pattern ControlMap] -> t -> Pattern ControlMap
+ Sound.Tidal.UI: layer :: [a -> Pattern b] -> a -> Pattern b
+ Sound.Tidal.UI: lindenmayer :: Int -> String -> String -> String
+ Sound.Tidal.UI: lindenmayerI :: Num b => Int -> String -> String -> [b]
+ Sound.Tidal.UI: linger :: Pattern Time -> Pattern a -> Pattern a
+ Sound.Tidal.UI: loopFirst :: Pattern a -> Pattern a
+ Sound.Tidal.UI: mask :: Pattern Bool -> Pattern a -> Pattern a
+ Sound.Tidal.UI: mono :: Pattern a -> Pattern a
+ Sound.Tidal.UI: never :: (Pattern a -> Pattern a) -> Pattern a -> Pattern a
+ Sound.Tidal.UI: off :: Pattern Time -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
+ Sound.Tidal.UI: offadd :: Num a => Pattern Time -> Pattern a -> Pattern a -> Pattern a
+ Sound.Tidal.UI: often :: (Pattern a -> Pattern a) -> Pattern a -> Pattern a
+ Sound.Tidal.UI: outside :: Pattern Time -> (Pattern a1 -> Pattern a) -> Pattern a1 -> Pattern a
+ Sound.Tidal.UI: palindrome :: Pattern a -> Pattern a
+ Sound.Tidal.UI: parseLMRule :: String -> [(String, String)]
+ Sound.Tidal.UI: parseLMRule' :: String -> [(Char, String)]
+ Sound.Tidal.UI: perlin :: Pattern Double
+ Sound.Tidal.UI: perlin2 :: Pattern Double -> Pattern Double
+ Sound.Tidal.UI: perlin2With :: Pattern Double -> Pattern Double -> Pattern Double
+ Sound.Tidal.UI: perlinWith :: Pattern Double -> Pattern Double
+ Sound.Tidal.UI: permstep :: RealFrac b => Int -> [a] -> Pattern b -> Pattern a
+ Sound.Tidal.UI: pick :: String -> Int -> String
+ Sound.Tidal.UI: ply :: Pattern Int -> Pattern a -> Pattern a
+ Sound.Tidal.UI: quad :: Time -> Pattern a -> Pattern a
+ Sound.Tidal.UI: quantise :: (Functor f, RealFrac b) => b -> f b -> f b
+ Sound.Tidal.UI: rand :: Fractional a => Pattern a
+ Sound.Tidal.UI: randArcs :: Int -> Pattern [Arc]
+ Sound.Tidal.UI: randStruct :: Int -> Pattern Int
+ Sound.Tidal.UI: randcat :: [Pattern a] -> Pattern a
+ Sound.Tidal.UI: range :: Num a => Pattern a -> Pattern a -> Pattern a -> Pattern a
+ Sound.Tidal.UI: rangex :: (Functor f, Floating b) => b -> b -> f b -> f b
+ Sound.Tidal.UI: rarely :: (Pattern a -> Pattern a) -> Pattern a -> Pattern a
+ Sound.Tidal.UI: revArc :: (Time, Time) -> Pattern a -> Pattern a
+ Sound.Tidal.UI: rot :: Ord a => Pattern Int -> Pattern a -> Pattern a
+ Sound.Tidal.UI: runWith :: Int -> (Pattern b -> Pattern b) -> Pattern b -> Pattern b
+ Sound.Tidal.UI: runWith' :: Integral a => a -> (Pattern b -> Pattern b) -> Pattern b -> Pattern b
+ Sound.Tidal.UI: samples :: Applicative f => f String -> f Int -> f String
+ Sound.Tidal.UI: samples' :: Applicative f => f String -> f Int -> f String
+ Sound.Tidal.UI: scramble :: Int -> Pattern a -> Pattern a
+ Sound.Tidal.UI: segment :: Pattern Time -> Pattern a -> Pattern a
+ Sound.Tidal.UI: select :: Pattern Double -> [Pattern a] -> Pattern a
+ Sound.Tidal.UI: seqP :: [(Time, Time, Pattern a)] -> Pattern a
+ Sound.Tidal.UI: seqPLoop :: [(Time, Time, Pattern a)] -> Pattern a
+ Sound.Tidal.UI: sew :: Pattern Bool -> Pattern a -> Pattern a -> Pattern a
+ Sound.Tidal.UI: shuffle :: Int -> Pattern a -> Pattern a
+ Sound.Tidal.UI: slowspread :: (a -> t -> Pattern b) -> [a] -> t -> Pattern b
+ Sound.Tidal.UI: slowstripe :: Pattern Int -> Pattern a -> Pattern a
+ Sound.Tidal.UI: smooth :: Fractional a => Pattern a -> Pattern a
+ Sound.Tidal.UI: someCycles :: (Pattern a -> Pattern a) -> Pattern a -> Pattern a
+ Sound.Tidal.UI: someCyclesBy :: Double -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
+ Sound.Tidal.UI: somecycles :: (Pattern a -> Pattern a) -> Pattern a -> Pattern a
+ Sound.Tidal.UI: somecyclesBy :: Double -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
+ Sound.Tidal.UI: sometimes :: (Pattern a -> Pattern a) -> Pattern a -> Pattern a
+ Sound.Tidal.UI: sometimesBy :: Pattern Double -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
+ Sound.Tidal.UI: spaceOut :: [Time] -> Pattern a -> Pattern a
+ Sound.Tidal.UI: spread :: (a -> t -> Pattern b) -> [a] -> t -> Pattern b
+ Sound.Tidal.UI: spread' :: Monad m => (a -> b -> m c) -> m a -> b -> m c
+ Sound.Tidal.UI: spreadChoose :: (t -> t1 -> Pattern b) -> [t] -> t1 -> Pattern b
+ Sound.Tidal.UI: spreadf :: [a -> Pattern b] -> a -> Pattern b
+ Sound.Tidal.UI: spreadr :: (t -> t1 -> Pattern b) -> [t] -> t1 -> Pattern b
+ Sound.Tidal.UI: stackwith :: Unionable a => Pattern a -> [Pattern a] -> Pattern a
+ Sound.Tidal.UI: step :: String -> String -> Pattern String
+ Sound.Tidal.UI: step' :: [String] -> String -> Pattern String
+ Sound.Tidal.UI: steps :: [(String, String)] -> Pattern String
+ Sound.Tidal.UI: stretch :: Pattern a -> Pattern a
+ Sound.Tidal.UI: stripe :: Pattern Int -> Pattern a -> Pattern a
+ Sound.Tidal.UI: struct :: Pattern Bool -> Pattern a -> Pattern a
+ Sound.Tidal.UI: stutter :: Integral i => i -> Time -> Pattern a -> Pattern a
+ Sound.Tidal.UI: substruct :: Pattern String -> Pattern b -> Pattern b
+ Sound.Tidal.UI: substruct' :: Pattern Int -> Pattern a -> Pattern a
+ Sound.Tidal.UI: superimpose :: (Pattern a -> Pattern a) -> Pattern a -> Pattern a
+ Sound.Tidal.UI: swing :: Pattern Time -> Pattern a -> Pattern a
+ Sound.Tidal.UI: swingBy :: Pattern Time -> Pattern Time -> Pattern a -> Pattern a
+ Sound.Tidal.UI: tabby :: Int -> Pattern a -> Pattern a -> Pattern a
+ Sound.Tidal.UI: timeLoop :: Pattern Time -> Pattern a -> Pattern a
+ Sound.Tidal.UI: timeToRand :: RealFrac a => a -> Double
+ Sound.Tidal.UI: toScale :: Num a => [a] -> Pattern Int -> Pattern a
+ Sound.Tidal.UI: toScale' :: Num a => Int -> [a] -> Pattern Int -> Pattern a
+ Sound.Tidal.UI: triple :: Time -> Pattern a -> Pattern a
+ Sound.Tidal.UI: trunc :: Pattern Time -> Pattern a -> Pattern a
+ Sound.Tidal.UI: unDegradeBy :: Pattern Double -> Pattern a -> Pattern a
+ Sound.Tidal.UI: unfix :: (ControlPattern -> ControlPattern) -> ControlPattern -> ControlPattern -> ControlPattern
+ Sound.Tidal.UI: unfixRange :: (ControlPattern -> Pattern ControlMap) -> Pattern (Map String (Value, Value)) -> ControlPattern -> Pattern ControlMap
+ Sound.Tidal.UI: unwrap' :: Pattern (Pattern a) -> Pattern a
+ Sound.Tidal.UI: ur :: Time -> Pattern String -> [(String, Pattern a)] -> [(String, Pattern a -> Pattern a)] -> Pattern a
+ Sound.Tidal.UI: wchoose :: [(a, Double)] -> Pattern a
+ Sound.Tidal.UI: wchooseBy :: Pattern Double -> [(a, Double)] -> Pattern a
+ Sound.Tidal.UI: wedge :: Time -> Pattern a -> Pattern a -> Pattern a
+ Sound.Tidal.UI: whenmod :: Int -> Int -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
+ Sound.Tidal.UI: within :: (Time, Time) -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
+ Sound.Tidal.UI: within' :: (Time, Time) -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
+ Sound.Tidal.UI: withinArc :: Arc -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
+ Sound.Tidal.Utils: delta :: Num a => (a, a) -> a
+ Sound.Tidal.Utils: mapBoth :: (a -> a) -> (a, a) -> (a, a)
+ Sound.Tidal.Utils: mapPartTimes :: (a -> a) -> ((a, a), (a, a)) -> ((a, a), (a, a))
+ Sound.Tidal.Utils: mid :: Fractional a => (a, a) -> a
+ Sound.Tidal.Utils: nth :: Int -> [a] -> Maybe a
+ Sound.Tidal.Utils: readMaybe :: Read a => String -> Maybe a
+ Sound.Tidal.Utils: removeCommon :: Eq a => [a] -> [a] -> ([a], [a])
- Sound.Tidal.Params: accelerate :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: accelerate :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: array :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: array :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: att :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: att :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: attack :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: attack :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: bandf :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: bandf :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: bandq :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: bandq :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: begin :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: begin :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: bpf :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: bpf :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: bpq :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: bpq :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: cc :: Pattern String -> ParamPattern
+ Sound.Tidal.Params: cc :: Pattern String -> ControlPattern
- Sound.Tidal.Params: ccn :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: ccn :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: ccv :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: ccv :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: channel :: Pattern Int -> ParamPattern
+ Sound.Tidal.Params: channel :: Pattern Int -> ControlPattern
- Sound.Tidal.Params: chdecay :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: chdecay :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: clhatdecay :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: clhatdecay :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: coarse :: Pattern Int -> ParamPattern
+ Sound.Tidal.Params: coarse :: Pattern Int -> ControlPattern
- Sound.Tidal.Params: command :: Pattern String -> ParamPattern
+ Sound.Tidal.Params: command :: Pattern String -> ControlPattern
- Sound.Tidal.Params: control :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: control :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: crush :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: crush :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: ctf :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: ctf :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: ctfg :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: ctfg :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: ctlNum :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: ctlNum :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: ctranspose :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: ctranspose :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: cut :: Pattern Int -> ParamPattern
+ Sound.Tidal.Params: cut :: Pattern Int -> ControlPattern
- Sound.Tidal.Params: cutoff :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: cutoff :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: cutoffegint :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: cutoffegint :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: decay :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: decay :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: degree :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: degree :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: delay :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: delay :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: delayfb :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: delayfb :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: delayfeedback :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: delayfeedback :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: delayt :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: delayt :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: delaytime :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: delaytime :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: det :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: det :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: detune :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: detune :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: drum :: Pattern String -> ParamPattern
+ Sound.Tidal.Params: drum :: Pattern String -> ControlPattern
- Sound.Tidal.Params: dry :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: dry :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: dur :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: dur :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: end :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: end :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: expression :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: expression :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: frameRate :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: frameRate :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: frames :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: frames :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: gain :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: gain :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: gat :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: gat :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: gate :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: gate :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: grp :: [Param] -> Pattern String -> ParamPattern
+ Sound.Tidal.Params: grp :: [String -> ControlMap] -> Pattern String -> ControlPattern
- Sound.Tidal.Params: harmonic :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: harmonic :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: hatgrain :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: hatgrain :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: hcutoff :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: hcutoff :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: hg :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: hg :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: hold :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: hold :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: hours :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: hours :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: hpf :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: hpf :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: hpq :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: hpq :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: hresonance :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: hresonance :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: kriole :: Pattern Int -> ParamPattern
+ Sound.Tidal.Params: kriole :: Pattern Int -> ControlPattern
- Sound.Tidal.Params: lag :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: lag :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: lagogo :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: lagogo :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: lbd :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: lbd :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: lch :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: lch :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: lcl :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: lcl :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: lclap :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: lclap :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: lclaves :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: lclaves :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: lclhat :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: lclhat :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: lcp :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: lcp :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: lcr :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: lcr :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: lcrash :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: lcrash :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: legato :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: legato :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: leslie :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: leslie :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: lfo :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: lfo :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: lfoc :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: lfoc :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: lfocutoffint :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: lfocutoffint :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: lfodelay :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: lfodelay :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: lfoi :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: lfoi :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: lfoint :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: lfoint :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: lfop :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: lfop :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: lfopitchint :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: lfopitchint :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: lfoshape :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: lfoshape :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: lfosync :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: lfosync :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: lhitom :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: lhitom :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: lht :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: lht :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: lkick :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: lkick :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: llotom :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: llotom :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: llt :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: llt :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: lock :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: lock :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: loh :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: loh :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: loop :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: loop :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: lophat :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: lophat :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: lpf :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: lpf :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: lpq :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: lpq :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: lrate :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: lrate :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: lsize :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: lsize :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: lsn :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: lsn :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: lsnare :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: lsnare :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: midichan :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: midichan :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: midicmd :: Pattern String -> ParamPattern
+ Sound.Tidal.Params: midicmd :: Pattern String -> ControlPattern
- Sound.Tidal.Params: midinote :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: midinote :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: minutes :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: minutes :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: modwheel :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: modwheel :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: mtranspose :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: mtranspose :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: n :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: n :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: note :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: note :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: nudge :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: nudge :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: octave :: Pattern Int -> ParamPattern
+ Sound.Tidal.Params: octave :: Pattern Int -> ControlPattern
- Sound.Tidal.Params: octaveRatio :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: octaveRatio :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: offset :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: offset :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: ohdecay :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: ohdecay :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: ophatdecay :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: ophatdecay :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: orbit :: Pattern Int -> ParamPattern
+ Sound.Tidal.Params: orbit :: Pattern Int -> ControlPattern
- Sound.Tidal.Params: pF :: String -> Maybe Double -> (Pattern Double -> ParamPattern, Param)
+ Sound.Tidal.Params: pF :: String -> Pattern Double -> ControlPattern
- Sound.Tidal.Params: pI :: String -> Maybe Int -> (Pattern Int -> ParamPattern, Param)
+ Sound.Tidal.Params: pI :: String -> Pattern Int -> ControlPattern
- Sound.Tidal.Params: pS :: String -> Maybe String -> (Pattern String -> ParamPattern, Param)
+ Sound.Tidal.Params: pS :: String -> Pattern String -> ControlPattern
- Sound.Tidal.Params: pan :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: pan :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: panorient :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: panorient :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: panspan :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: panspan :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: pansplay :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: pansplay :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: panwidth :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: panwidth :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: phasdp :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: phasdp :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: phaserdepth :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: phaserdepth :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: phaserrate :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: phaserrate :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: phasr :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: phasr :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: pit1 :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: pit1 :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: pit2 :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: pit2 :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: pit3 :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: pit3 :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: pitch1 :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: pitch1 :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: pitch2 :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: pitch2 :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: pitch3 :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: pitch3 :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: por :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: por :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: portamento :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: portamento :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: progNum :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: progNum :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: rel :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: rel :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: release :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: release :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: resonance :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: resonance :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: room :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: room :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: s :: Pattern String -> ParamPattern
+ Sound.Tidal.Params: s :: Pattern String -> ControlPattern
- Sound.Tidal.Params: s' :: Pattern String -> ParamPattern
+ Sound.Tidal.Params: s' :: Pattern String -> ControlPattern
- Sound.Tidal.Params: sag :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: sag :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: sagogo :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: sagogo :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: scl :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: scl :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: sclap :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: sclap :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: sclaves :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: sclaves :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: scp :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: scp :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: scr :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: scr :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: scrash :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: scrash :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: seconds :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: seconds :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: semitone :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: semitone :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: shape :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: shape :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: size :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: size :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: sld :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: sld :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: slide :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: slide :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: songPtr :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: songPtr :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: sound :: Pattern String -> ParamPattern
+ Sound.Tidal.Params: sound :: Pattern String -> ControlPattern
- Sound.Tidal.Params: speed :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: speed :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: std :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: std :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: stepsPerOctave :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: stepsPerOctave :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: stt :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: stt :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: stutterdepth :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: stutterdepth :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: stuttertime :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: stuttertime :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: sus :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: sus :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: sustain :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: sustain :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: sustainpedal :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: sustainpedal :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: sz :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: sz :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: tdecay :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: tdecay :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: tomdecay :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: tomdecay :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: tremdp :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: tremdp :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: tremolodepth :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: tremolodepth :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: tremolorate :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: tremolorate :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: tremr :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: tremr :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: uid :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: uid :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: unit :: Pattern String -> ParamPattern
+ Sound.Tidal.Params: unit :: Pattern String -> ControlPattern
- Sound.Tidal.Params: val :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: val :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: vcf :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: vcf :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: vcfegint :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: vcfegint :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: vco :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: vco :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: vcoegint :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: vcoegint :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: velocity :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: velocity :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: voi :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: voi :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: voice :: Pattern Double -> ParamPattern
+ Sound.Tidal.Params: voice :: Pattern Double -> ControlPattern
- Sound.Tidal.Params: vowel :: Pattern String -> ParamPattern
+ Sound.Tidal.Params: vowel :: Pattern String -> ControlPattern
- Sound.Tidal.Pattern: Pattern :: Arc -> [Event a] -> Pattern a
+ Sound.Tidal.Pattern: Pattern :: Nature -> Query a -> Pattern a
- Sound.Tidal.Pattern: [arc] :: Pattern a -> Arc -> [Event a]
+ Sound.Tidal.Pattern: [arc] :: State -> Arc
- Sound.Tidal.Simple: crunch :: ParamPattern -> ParamPattern
+ Sound.Tidal.Simple: crunch :: ControlPattern -> ControlPattern
- Sound.Tidal.Simple: faster :: ParamPattern -> ParamPattern
+ Sound.Tidal.Simple: faster :: ControlPattern -> ControlPattern
- Sound.Tidal.Simple: higher :: ParamPattern -> ParamPattern
+ Sound.Tidal.Simple: higher :: ControlPattern -> ControlPattern
- Sound.Tidal.Simple: left :: ParamPattern -> ParamPattern
+ Sound.Tidal.Simple: left :: ControlPattern -> ControlPattern
- Sound.Tidal.Simple: louder :: ParamPattern -> ParamPattern
+ Sound.Tidal.Simple: louder :: ControlPattern -> ControlPattern
- Sound.Tidal.Simple: lower :: ParamPattern -> ParamPattern
+ Sound.Tidal.Simple: lower :: ControlPattern -> ControlPattern
- Sound.Tidal.Simple: quieter :: ParamPattern -> ParamPattern
+ Sound.Tidal.Simple: quieter :: ControlPattern -> ControlPattern
- Sound.Tidal.Simple: right :: ParamPattern -> ParamPattern
+ Sound.Tidal.Simple: right :: ControlPattern -> ControlPattern
- Sound.Tidal.Simple: scratch :: ParamPattern -> ParamPattern
+ Sound.Tidal.Simple: scratch :: ControlPattern -> ControlPattern
- Sound.Tidal.Simple: slower :: ParamPattern -> ParamPattern
+ Sound.Tidal.Simple: slower :: ControlPattern -> ControlPattern
- Sound.Tidal.Stream: onTick :: Backend a -> Shape -> MVar (ParamPattern) -> Tempo -> Int -> IO ()
+ Sound.Tidal.Stream: onTick :: Config -> MVar ControlMap -> MVar ControlPattern -> OSCTarget -> UDP -> MVar Tempo -> State -> IO ()
- Sound.Tidal.Tempo: Tempo :: UTCTime -> Double -> Double -> Bool -> Double -> Tempo
+ Sound.Tidal.Tempo: Tempo :: Time -> Rational -> Time -> Bool -> Double -> UDP -> SockAddr -> Tempo
- Sound.Tidal.Tempo: [cps] :: Tempo -> Double
+ Sound.Tidal.Tempo: [cps] :: Tempo -> Time
- Sound.Tidal.Tempo: clocked :: (Tempo -> Int -> IO ()) -> IO ()
+ Sound.Tidal.Tempo: clocked :: Config -> (MVar Tempo -> State -> IO ()) -> IO (MVar Tempo, [ThreadId])
- Sound.Tidal.Tempo: sendTempo :: [Connection] -> Tempo -> IO ()
+ Sound.Tidal.Tempo: sendTempo :: Tempo -> IO ()
- Sound.Tidal.Tempo: setCps :: Double -> ServerMode -> MVar Tempo -> MVar ClientState -> IO ()
+ Sound.Tidal.Tempo: setCps :: MVar Tempo -> Time -> IO Tempo
- Sound.Tidal.Transition: histpan :: Int -> Time -> [ParamPattern] -> ParamPattern
+ Sound.Tidal.Transition: histpan :: Int -> Time -> [ControlPattern] -> ControlPattern
- Sound.Tidal.Transition: interpolateIn :: Time -> Time -> [ParamPattern] -> ParamPattern
+ Sound.Tidal.Transition: interpolateIn :: Time -> Time -> [ControlPattern] -> ControlPattern
- Sound.Tidal.Transition: jump :: Time -> [ParamPattern] -> ParamPattern
+ Sound.Tidal.Transition: jump :: Time -> [ControlPattern] -> ControlPattern
- Sound.Tidal.Transition: jumpIn :: Int -> Time -> [ParamPattern] -> ParamPattern
+ Sound.Tidal.Transition: jumpIn :: Int -> Time -> [ControlPattern] -> ControlPattern
- Sound.Tidal.Transition: jumpIn' :: Int -> Time -> [ParamPattern] -> ParamPattern
+ Sound.Tidal.Transition: jumpIn' :: Int -> Time -> [ControlPattern] -> ControlPattern
- Sound.Tidal.Transition: jumpMod :: Int -> Time -> [ParamPattern] -> ParamPattern
+ Sound.Tidal.Transition: jumpMod :: Int -> Time -> [ControlPattern] -> ControlPattern
- Sound.Tidal.Transition: mortal :: Time -> Time -> Time -> [ParamPattern] -> ParamPattern
+ Sound.Tidal.Transition: mortal :: Time -> Time -> Time -> [ControlPattern] -> ControlPattern
- Sound.Tidal.Transition: transition :: (IO Time) -> MVar (ParamPattern, [ParamPattern]) -> (Time -> [ParamPattern] -> ParamPattern) -> ParamPattern -> IO ()
+ Sound.Tidal.Transition: transition :: Show a => Stream -> (Time -> [ControlPattern] -> ControlPattern) -> a -> ControlPattern -> IO ()
- Sound.Tidal.Transition: wait :: Time -> Time -> [ParamPattern] -> ParamPattern
+ Sound.Tidal.Transition: wait :: Time -> Time -> [ControlPattern] -> ControlPattern
- Sound.Tidal.Transition: wash :: (Pattern a -> Pattern a) -> Time -> Time -> [Pattern a] -> Pattern a
+ Sound.Tidal.Transition: wash :: (Pattern a -> Pattern a) -> (Pattern a -> Pattern a) -> Time -> Time -> Time -> Time -> [Pattern a] -> Pattern a

Files

CHANGELOG.md view
@@ -1,5 +1,20 @@ # TidalCycles log of changes +## 0.9.10 (and earlier missing versions from this log)++* arpg, a function to arpeggiate+* within', an alternate within with a different approach to time, following discussion here https://github.com/tidalcycles/Tidal/issues/313+* sine et al are now generalised so can be used as double or rational patterns+* New Sound.Tidal.Simple module with a range of simple transformations (faster, slower, higher, lower, mute, etc)+* slice upgraded to take a pattern of slice indexes+* espgrid support+* lindenmayerI+* sew function, for binary switching between two patterns+* somecycles alias for someCycles+* ply function, for repeating each event in a pattern a given number+  of times within their original timespan+* patternify juxBy, e, e', einv, efull, eoff+ ## 0.9.7  ### Enhancements
LICENSE view
@@ -76,7 +76,7 @@    "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks.- +   "The Program" refers to any copyrightable work licensed under this License.  Each licensee is addressed as "you".  "Licensees" and "recipients" may be individuals or organizations.@@ -509,7 +509,7 @@ covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid.-  +   If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties@@ -672,4 +672,3 @@ the library.  If this is what you want to do, use the GNU Lesser General Public License instead of this License.  But first, please read <http://www.gnu.org/philosophy/why-not-lgpl.html>.-
README.md view
@@ -1,5 +1,5 @@ -Tidal [![Build Status](https://travis-ci.org/tidalcycles/Tidal.svg?branch=1.0-dev)](https://travis-ci.org/tidalcycles/Tidal)+Tidal [![Build Status](https://travis-ci.org/tidalcycles/Tidal.svg)](https://travis-ci.org/tidalcycles/Tidal) =====  Language for live coding of pattern@@ -7,7 +7,7 @@ For documentation, mailing list and more info see here:   https://tidalcycles.org/ -(c) Alex McLean and contributors, 2016+(c) Alex McLean and contributors, 2018  Distributed under the terms of the GNU Public license version 3 (or later).
− Sound/Tidal/Bjorklund.hs
@@ -1,34 +0,0 @@-module Sound.Tidal.Bjorklund (bjorklund) where---- The below is (c) Rohan Drape, taken from the hmt library and--- distributed here under the terms of the GNU Public Licence.  Tidal--- used to just include the library but removed for now due to--- dependency problems.. We could however likely benefit from other--- parts of the library..--type STEP a = ((Int,Int),([[a]],[[a]]))--left :: STEP a -> STEP a-left ((i,j),(xs,ys)) =-    let (xs',xs'') = splitAt j xs-    in ((j,i-j),(zipWith (++) xs' ys,xs''))--right :: STEP a -> STEP a-right ((i,j),(xs,ys)) =-    let (ys',ys'') = splitAt i ys-    in ((i,j-i),(zipWith (++) xs ys',ys''))--bjorklund' :: STEP a -> STEP a-bjorklund' (n,x) =-    let (i,j) = n-    in if min i j <= 1-       then (n,x)-       else bjorklund' (if i > j then left (n,x) else right (n,x))--bjorklund :: (Int,Int) -> [Bool]-bjorklund (i,j') =-    let j = j' - i-        x = replicate i [True]-        y = replicate j [False]-        (_,(x',y')) = bjorklund' ((i,j),(x,y))-    in concat x' ++ concat y'
− Sound/Tidal/Chords.hs
@@ -1,166 +0,0 @@-module Sound.Tidal.Chords where--import Sound.Tidal.Pattern-import Data.Maybe-import Control.Applicative--major :: Num a => [a]-major = [0,4,7]-minor :: Num a => [a]-minor = [0,3,7]-major7 :: Num a => [a]-major7 = [0,4,7,11]-dom7 :: Num a => [a]-dom7 = [0,4,7,10]-minor7 :: Num a => [a]-minor7 = [0,3,7,10]-aug :: Num a => [a]-aug = [0,4,8]-dim :: Num a => [a]-dim = [0,3,6]-dim7 :: Num a => [a]-dim7 = [0,3,6,9]-one :: Num a => [a]-one = [0]-five :: Num a => [a]-five = [0,7]-plus :: Num a => [a]-plus = [0,4,8]-sharp5 :: Num a => [a]-sharp5 = [0,4,8]-msharp5 :: Num a => [a]-msharp5 = [0,3,8]-sus2 :: Num a => [a]-sus2 = [0,2,7]-sus4 :: Num a => [a]-sus4 = [0,5,7]-six :: Num a => [a]-six = [0,4,7,9]-m6 :: Num a => [a]-m6 = [0,3,7,9]-sevenSus2 :: Num a => [a]-sevenSus2 = [0,2,7,10]-sevenSus4 :: Num a => [a]-sevenSus4 = [0,5,7,10]-sevenFlat5 :: Num a => [a]-sevenFlat5 = [0,4,6,10]-m7flat5 :: Num a => [a]-m7flat5 = [0,3,6,10]-sevenSharp5 :: Num a => [a]-sevenSharp5 = [0,4,8,10]-m7sharp5 :: Num a => [a]-m7sharp5 = [0,3,8,10]-nine :: Num a => [a]-nine = [0,4,7,10,14]-m9 :: Num a => [a]-m9 = [0,3,7,10,14]-m7sharp9 :: Num a => [a]-m7sharp9 = [0,3,7,10,14]-maj9 :: Num a => [a]-maj9 = [0,4,7,11,14]-nineSus4 :: Num a => [a]-nineSus4 = [0,5,7,10,14]-sixby9 :: Num a => [a]-sixby9 = [0,4,7,9,14]-m6by9 :: Num a => [a]-m6by9 = [0,3,9,7,14]-sevenFlat9 :: Num a => [a]-sevenFlat9 = [0,4,7,10,13]-m7flat9 :: Num a => [a]-m7flat9 = [0,3,7,10,13]-sevenFlat10 :: Num a => [a]-sevenFlat10 = [0,4,7,10,15]-nineSharp5 :: Num a => [a]-nineSharp5 = [0,1,13]-m9sharp5 :: Num a => [a]-m9sharp5 = [0,1,14]-sevenSharp5flat9 :: Num a => [a]-sevenSharp5flat9 = [0,4,8,10,13]-m7sharp5flat9 :: Num a => [a]-m7sharp5flat9 = [0,3,8,10,13]-eleven :: Num a => [a]-eleven = [0,4,7,10,14,17]-m11 :: Num a => [a]-m11 = [0,3,7,10,14,17]-maj11 :: Num a => [a]-maj11 = [0,4,7,11,14,17]-evelenSharp :: Num a => [a]-evelenSharp = [0,4,7,10,14,18]-m11sharp :: Num a => [a]-m11sharp = [0,3,7,10,14,18]-thirteen :: Num a => [a]-thirteen = [0,4,7,10,14,17,21]-m13 :: Num a => [a]-m13 = [0,3,7,10,14,17,21]---- | @chordate cs m n@ selects the @n@th "chord" (a chord is a list of Ints)--- from a list of chords @cs@ and transposes it by @m@-chordate :: Num b => [[b]] -> b -> Int -> [b]-chordate cs m n = map (+m) $ cs!!n---- | @enchord chords pn pc@ turns every note in the note pattern @pn@ into--- a chord, selecting from the chord lists @chords@ using the index pattern--- @pc@.  For example, @Chords.enchord [Chords.major Chords.minor] "c g" "0 1"@--- will create a pattern of a C-major chord followed by a G-minor chord.-enchord :: Num a => [[a]] -> Pattern a -> Pattern Int -> Pattern a-enchord chords pn pc = flatpat $ (chordate chords) <$> pn <*> pc--chordTable :: Num a => [(String, [a])]-chordTable = [("major", major),-              ("minor", minor),-              ("major7", major7),-              ("dom7", dom7),-              ("minor7", minor7),-              ("aug", aug),-              ("dim", dim),-              ("dim7", dim7),-              ("one", one),-              ("five", five),-              ("plus", plus),-              ("sharp5", sharp5),-              ("msharp5", msharp5),-              ("sus2", sus2),-              ("sus4", sus4),-              ("six", six),-              ("m6", m6),-              ("sevenSus2", sevenSus2),-              ("sevenSus4", sevenSus4),-              ("sevenFlat5", sevenFlat5),-              ("m7flat5", m7flat5),-              ("sevenSharp5", sevenSharp5),-              ("m7sharp5", m7sharp5),-              ("nine", nine),-              ("m9", m9),-              ("m7sharp9", m7sharp9),-              ("maj9", maj9),-              ("nineSus4", nineSus4),-              ("sixby9", sixby9),-              ("m6by9", m6by9),-              ("sevenFlat9", sevenFlat9),-              ("m7flat9", m7flat9),-              ("sevenFlat10", sevenFlat10),-              ("nineSharp5", nineSharp5),-              ("m9sharp5", m9sharp5),-              ("sevenSharp5flat9", sevenSharp5flat9),-              ("m7sharp5flat9", m7sharp5flat9),-              ("eleven", eleven),-              ("m11", m11),-              ("maj11", maj11),-              ("evelenSharp", evelenSharp),-              ("m11sharp", m11sharp),-              ("thirteen", thirteen),-              ("m13", m13)-             ]--chordL :: Num a => Pattern String -> Pattern [a]-chordL p = (\name -> fromMaybe [] $ lookup name chordTable) <$> p---- | @chord p@ turns a pattern of chord names into a pattern of--- numbers, representing note value offsets for the chords-chord :: Num a => Pattern String -> Pattern a-chord p = flatpat $ chordL p---- | @arpg p@ turns a pattern of chord names into a pattern of arpeggios--- of the those chords respectively-arpg :: Num a => Pattern String -> Pattern a-arpg p = breakUp $ chord p
− Sound/Tidal/Context.hs
@@ -1,27 +0,0 @@-module Sound.Tidal.Context (module C) where--import Control.Concurrent as C-import Data.List as C-import Control.Applicative as C-import Data.Ratio as C-import Data.Monoid as C-import Sound.Tidal.Parse as C-import Sound.Tidal.Pattern as C--- import Sound.Tidal.PatternList as C-import Sound.Tidal.Stream as C-import Sound.Tidal.Dirt as C-import Sound.Tidal.Strategies as C-import Sound.Tidal.Tempo as C-import Sound.Tidal.Time as C-import Sound.Tidal.Sieve as C-import Sound.Tidal.SuperCollider as C-import Sound.Tidal.Params as C-import Sound.Tidal.Transition as C-import Sound.Tidal.EspGrid as C-import Sound.Tidal.MultiMode as C-import Sound.Tidal.Version as C-import Sound.Tidal.Chords as C (chord)-import Sound.Tidal.Scales as C (scaleP)--import qualified Sound.Tidal.Scales as C.Scales-import qualified Sound.Tidal.Chords as C.Chords
− Sound/Tidal/Dirt.hs
@@ -1,390 +0,0 @@-{-# LANGUAGE NoMonomorphismRestriction #-}-module Sound.Tidal.Dirt where--import Sound.OSC.Datum (Datum)-import qualified Data.Map as Map-import Control.Applicative-import Control.Concurrent.MVar---import Visual-import Data.Colour.SRGB-import Data.Colour.Names-import Data.Hashable-import Data.Bits-import Data.Maybe-import Data.Fixed-import Data.Ratio-import Data.List (elemIndex, sort)--import Sound.Tidal.Stream-import Sound.Tidal.OscStream-import Sound.Tidal.Pattern-import Sound.Tidal.Parse-import Sound.Tidal.Params-import Sound.Tidal.Time-import Sound.Tidal.Tempo-import Sound.Tidal.Transition (transition, wash)-import Sound.Tidal.Utils (enumerate, fst')--dirt :: Shape-dirt = Shape {   params = [ s_p,-                            offset_p,-                            begin_p,-                            end_p,-                            speed_p,-                            pan_p,-                            velocity_p,-                            vowel_p,-                            cutoff_p,-                            resonance_p,-                            accelerate_p,-                            shape_p,-                            kriole_p,-                            gain_p,-                            cut_p,-                            delay_p,-                            delaytime_p,-                            delayfeedback_p,-                            crush_p,-                            coarse_p,-                            hcutoff_p,-                            hresonance_p,-                            bandf_p,-                            bandq_p,-                            unit_p,-                            loop_p,-                            n_p,-                            attack_p,-                            hold_p,-                            release_p,-                            orbit_p-                          ],-                 cpsStamp = True,-                 latency = 0.3-                }--dirtSlang = OscSlang {-  path = "/play",-  timestamp = MessageStamp,-  namedParams = False,-  preamble = []-  }--superDirtSlang = dirtSlang { timestamp = BundleStamp, path = "/play2", namedParams = True }--superDirtBackend port = do-  s <- makeConnection "127.0.0.1" port superDirtSlang-  return $ Backend s (\_ _ _ -> return ())--superDirtState port = do-  backend <- superDirtBackend port-  Sound.Tidal.Stream.state backend dirt--dirtBackend = do-  s <- makeConnection "127.0.0.1" 7771 dirtSlang-  return $ Backend s (\_ _ _ -> return ())---- dirtstart name = start "127.0.0.1" 7771 dirt--dirtStream = do-  backend <- dirtBackend-  stream backend dirt--dirtState = do-  backend <- dirtBackend-  Sound.Tidal.Stream.state backend dirt--dirtSetters :: IO Time -> IO (ParamPattern -> IO (), (Time -> [ParamPattern] -> ParamPattern) -> ParamPattern -> IO ())-dirtSetters getNow = do ds <- dirtState-                        return (setter ds, transition getNow ds)--superDirtSetters :: IO Time -> IO (ParamPattern -> IO (), (Time -> [ParamPattern] -> ParamPattern) -> ParamPattern -> IO ())-superDirtSetters getNow = do ds <- superDirtState 57120-                             return (setter ds, transition getNow ds)---superDirts :: [Int]  -> IO [(ParamPattern -> IO (), (Time -> [ParamPattern] -> ParamPattern) -> ParamPattern -> IO ())]-superDirts ports = do (_, getNow) <- cpsUtils-                      states <- mapM (superDirtState) ports-                      return $ map (\state -> (setter state, transition getNow state)) states---- -- disused parameter..-dirtstream _ = dirtStream---- doubledirt = do remote <- stream "178.77.72.138" 7777 dirt---                 local <- stream "192.168.0.102" 7771 dirt---                 return $ \p -> do remote p---                                   local p---                                   return ()---dirtToColour :: ParamPattern -> Pattern ColourD---dirtToColour p = s---  where s = fmap (\x -> maybe black (datumToColour) (Map.lookup (param dirt "s") x)) p-dirtToColour = fmap (stringToColour . show)--showToColour :: Show a => a -> ColourD-showToColour = stringToColour . show--datumToColour :: Value -> ColourD-datumToColour = showToColour--stringToColour :: String -> ColourD-stringToColour s = sRGB (r/256) (g/256) (b/256)-  where i = (hash s) `mod` 16777216-        r = fromIntegral $ (i .&. 0xFF0000) `shiftR` 16;-        g = fromIntegral $ (i .&. 0x00FF00) `shiftR` 8;-        b = fromIntegral $ (i .&. 0x0000FF);--{--visualcallback :: IO (ParamPattern -> IO ())-visualcallback = do t <- ticker-                    mv <- startVis t-                    let f p = do let p' = dirtToColour p-                                 swapMVar mv p'-                                 return ()-                    return f--}----dirtyvisualstream name = do cb <- visualcallback---                            streamcallback cb "127.0.0.1" "127.0.0.1" name "127.0.0.1" 7771 dirt--pick :: String -> Int -> String-pick name n = name ++ ":" ++ (show n)--{- | Striate is a kind of granulator, for example:--@-d1 $ striate 3 $ sound "ho ho:2 ho:3 hc"-@--This plays the loop the given number of times, but triggering-progressive portions of each sample. So in this case it plays the loop-three times, the first time playing the first third of each sample,-then the second time playing the second third of each sample, etc..-With the highhat samples in the above example it sounds a bit like-reverb, but it isn't really.--You can also use striate with very long samples, to cut it into short-chunks and pattern those chunks. This is where things get towards-granular synthesis. The following cuts a sample into 128 parts, plays-it over 8 cycles and manipulates those parts by reversing and rotating-the loops.--@-d1 $  slow 8 $ striate 128 $ sound "bev"-@--}--striate :: Pattern Int -> ParamPattern -> ParamPattern-striate = temporalParam _striate--_striate :: Int -> ParamPattern -> ParamPattern-_striate n p = fastcat $ map (\x -> off (fromIntegral x) p) [0 .. n-1]-  where off i p = p-                  # begin (atom (fromIntegral i / fromIntegral n))-                  # end (atom (fromIntegral (i+1) / fromIntegral n))--{-|-The `striate'` function is a variant of `striate` with an extra-parameter, which specifies the length of each part. The `striate'`-function still scans across the sample over a single cycle, but if-each bit is longer, it creates a sort of stuttering effect. For-example the following will cut the bev sample into 32 parts, but each-will be 1/16th of a sample long:--@-d1 $ slow 32 $ striate' 32 (1/16) $ sound "bev"-@--Note that `striate` uses the `begin` and `end` parameters-internally. This means that if you're using `striate` (or `striate'`)-you probably shouldn't also specify `begin` or `end`. -}-striate' :: Pattern Int -> Pattern Double -> ParamPattern -> ParamPattern-striate' = temporalParam2 _striate'--_striate' :: Int -> Double -> ParamPattern -> ParamPattern-_striate' n f p = fastcat $ map (\x -> off (fromIntegral x) p) [0 .. n-1]-  where off i p = p # begin (atom (slot * i) :: Pattern Double) # end (atom ((slot * i) + f) :: Pattern Double)-        slot = (1 - f) / (fromIntegral n)--{- | like `striate`, but with an offset to the begin and end values -}-striateO :: Pattern Int -> Pattern Double -> ParamPattern -> ParamPattern-striateO = temporalParam2 _striateO--_striateO :: Int -> Double -> ParamPattern -> ParamPattern-_striateO n o p = _striate n p |+| begin (atom o :: Pattern Double) |+| end (atom o :: Pattern Double)--{- | Just like `striate`, but also loops each sample chunk a number of times specified in the second argument.-The primed version is just like `striate'`, where the loop count is the third argument. For example:--@-d1 $ striateL' 3 0.125 4 $ sound "feel sn:2"-@--Like `striate`, these use the `begin` and `end` parameters internally, as well as the `loop` parameter for these versions.--}-striateL :: Pattern Int -> Pattern Int -> ParamPattern -> ParamPattern-striateL = temporalParam2 _striateL--striateL' :: Pattern Int -> Pattern Double -> Pattern Int -> ParamPattern -> ParamPattern-striateL' = temporalParam3 _striateL'--_striateL :: Int -> Int -> ParamPattern -> ParamPattern-_striateL n l p = _striate n p # loop (atom $ fromIntegral l)-_striateL' n f l p = _striate' n f p # loop (atom $ fromIntegral l)--metronome = _slow 2 $ sound (p "[odx, [hh]*8]")--{-|-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 _ _ [] = silence-clutchIn _ _ (p:[]) = p-clutchIn t now (p:p':_) = overlay (fadeOut' now t p') (fadeIn' now t p)--{-|-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 = clutchIn 2--{- | crossfades between old and new pattern over given number of cycles, e.g.:--@-d1 $ sound "bd sn"--t1 (xfadeIn 16) $ sound "jvbass*3"-@--Will fade over 16 cycles from "bd sn" to "jvbass*3"--}-xfadeIn :: Time -> Time -> [ParamPattern] -> ParamPattern-xfadeIn _ _ [] = silence-xfadeIn _ _ (p:[]) = p-xfadeIn t now (p:p':_) = overlay (p |*| gain (now `rotR` (_slow t envEqR))) (p' |*| gain (now `rotR` (_slow t (envEq))))--{- |-Crossfade between old and new pattern over the next two cycles.--@-d1 $ sound "bd sn"--t1 xfade $ sound "can*3"-@--`xfade` is built with `xfadeIn` in this case taking two cycles for the fade.--}-xfade :: Time -> [ParamPattern] -> ParamPattern-xfade = xfadeIn 2--{- | Stut applies a type of delay to a pattern. It has three parameters,-which could be called depth, feedback and time. Depth is an integer-and the others floating point. This adds a bit of echo:--@-d1 $ stut 4 0.5 0.2 $ sound "bd sn"-@--The above results in 4 echos, each one 50% quieter than the last,-with 1/5th of a cycle between them. It is possible to reverse the echo:--@-d1 $ stut 4 0.5 (-0.2) $ sound "bd sn"-@--}--stut :: Pattern Integer -> Pattern Double -> Pattern Rational -> ParamPattern -> ParamPattern-stut = temporalParam3 _stut--_stut :: Integer -> Double -> Rational -> ParamPattern -> ParamPattern-_stut steps feedback time p = stack (p:(map (\x -> (((x%steps)*time) `rotR` (p |*| gain (pure $ scale (fromIntegral x))))) [1..(steps-1)]))-  where scale x-          = ((+feedback) . (*(1-feedback)) . (/(fromIntegral steps)) . ((fromIntegral steps)-)) x--{- | Instead of just decreasing volume to produce echoes, @stut'@ allows to apply a function for each step and overlays the result delayed by the given time.--@-d1 $ stut' 2 (1%3) (# vowel "{a e i o u}%2") $ sound "bd sn"-@--In this case there are two _overlays_ delayed by 1/3 of a cycle, where each has the @vowel@ filter applied.--}-stut' :: Pattern Int -> Pattern Time -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a-stut' n t f p = unwrap $ (\a b -> _stut' a b f p) <$> n <*> t--_stut' :: (Num n, Ord n) => n -> Time -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a-_stut' steps steptime f p | steps <= 0 = p-                         | otherwise = overlay (f (steptime `rotR` _stut' (steps-1) steptime f p)) p--{- | @durPattern@ takes a pattern and returns the length of events in that-pattern as a new pattern.  For example the result of `durPattern "[a ~] b"`-would be `"[0.25 ~] 0.5"`.--}--durPattern :: Pattern a -> Pattern Time-durPattern p = Pattern $ \a -> map eventLengthEvent $ arc p a-  where eventLengthEvent (a1@(s1,e1), a2, x) = (a1, a2, e1-s1)--{- | @durPattern'@ is similar to @durPattern@, but does some lookahead to try-to find the length of time to the *next* event. For example, the result of-`durPattern' "[a ~] b"` would be `"[0.5 ~] 0.5"`.--}--durPattern' :: Pattern a -> Pattern Time-durPattern' p = Pattern $ \a@(s,e) -> map (eventDurToNext (arc p (s,e+1))) (arc p a)-      where eventDurToNext evs ev@(a1,a2,x) = (a1, a2, (nextNum (t ev) (mt evs)) - (t ev))-            t = fst . fst'-            mt = (map fst) . (map fst')-            nextNum a = head . sort . filter (\x -> x >a)--{- | @stutx@ is like @stut'@ but will limit the number of repeats using the -duration of the original sound.  This usually prevents overlapping "stutters"-from subsequent sounds.--}--stutx :: Pattern Int -> Pattern Time -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a-stutx n t f p = stut' (liftA2 min n (fmap floor $ durPattern' p / (t+0.001))) t f 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 -> [ParamPattern] -> ParamPattern-anticipateIn t now = wash (spread' (_stut 8 0.2) (now `rotR` (_slow t $ (toRational . (1-)) <$> envL))) t now--{- | `anticipate` is an increasing comb filter.--Build up some tension, culminating in a _drop_ to the new pattern after 8 cycles.--}-anticipate :: Time -> [ParamPattern] -> ParamPattern-anticipate = anticipateIn 8--{- | Copies the @n@ parameter to the @orbit@ parameter, so different sound variants or notes go to different orbits in SuperDirt. -}-nToOrbit = copyParam n_p orbit_p--{- | Maps the sample or synth names to different @orbit@s, using indexes from the given list. E.g. @soundToOrbit ["bd", "sn", "cp"] $ sound "bd [cp sn]"@ would cause the bd, sn and cp smamples to be sent to orbit 0, 1, 2 respectively.-}-soundToOrbit :: [String] -> ParamPattern -> ParamPattern-soundToOrbit sounds p = follow s_p orbit_p ((\s -> fromMaybe 0 $ elemIndex s sounds) <$>) p
− Sound/Tidal/EspGrid.hs
@@ -1,114 +0,0 @@-module Sound.Tidal.EspGrid where
-
-import Control.Concurrent.MVar
-import Control.Concurrent
-import Control.Monad (forever)
-import Control.Monad.Loops (iterateM_)
-import Sound.OSC.FD
-import Data.Time.Clock
-import Data.Time.Clock.POSIX
-import Data.Time.Calendar (fromGregorian)
-
-import Sound.Tidal.Tempo
-import Sound.Tidal.Time as T
-import Sound.Tidal.Stream
-import Sound.Tidal.Dirt
-import Sound.Tidal.Transition (transition)
-import Sound.Tidal.Pattern (silence)
-
-parseEspTempo :: [Datum] -> Maybe Tempo
-parseEspTempo d = do
-  on <- datum_integral (d!!0)
-  bpm <- datum_floating (d!!1)
-  t1 <- datum_integral (d!!2)
-  t2 <- datum_integral (d!!3)
-  n <- datum_integral (d!!4)
-  let nanos = (t1*1000000000) + t2
-  let utc = posixSecondsToUTCTime ((realToFrac nanos)/1000000000)
-  return (Tempo utc (fromIntegral n) (bpm/60) (on==0) 0.04)
-
-changeTempo :: MVar Tempo -> Packet -> IO ()
-changeTempo mvar (Packet_Message msg) = do
-    case parseEspTempo (messageDatum msg) of
-      Just t -> tryTakeMVar mvar >> putMVar mvar t
-      Nothing -> putStrLn "Unable to parse message as Tempo"
-changeTempo _ _ = putStrLn "Can only process Packet_Message"
-
-getTempo :: MVar Tempo -> IO Tempo
-getTempo = readMVar
-
-runClientEsp :: IO (MVar Tempo,MVar Double)
-runClientEsp = do
-  mTempo <- newEmptyMVar
-  mCps <- newEmptyMVar
-  socket <- openUDP "127.0.0.1" 5510
-  forkIO $ forever $ do
-    sendOSC socket $ Message "/esp/tempo/q" []
-    response <- waitAddress socket "/esp/tempo/r"
-    changeTempo mTempo response
-    threadDelay 100000
-  return (mTempo, mCps)
-
-sendEspTempo :: Real t => t -> IO ()
-sendEspTempo t = do
-  socket <- openUDP "127.0.0.1" 5510
-  sendOSC socket $ Message "/esp/beat/tempo" [float (t*60)]
-
-cpsUtilsEsp :: IO (Double -> IO (), IO Rational, IO Tempo)
-cpsUtilsEsp = do
-  (mTempo,mCps) <- runClientEsp
-  return (sendEspTempo,getCurrentBeat mTempo,getTempo mTempo)
-
-clockedTickEsp :: Int -> (Tempo -> Int -> IO ()) -> IO ()
-clockedTickEsp tpb callback = do
-  (mTempo, _) <- runClientEsp
-  nowBeat <- getCurrentBeat mTempo
-  let nextTick = ceiling (nowBeat * (fromIntegral tpb))
-  iterateM_ (clockedTickLoopEsp tpb callback mTempo) nextTick
-
-clockedTickLoopEsp :: Int -> (Tempo -> Int -> IO ()) -> MVar Tempo -> Int -> IO Int
-clockedTickLoopEsp tpb callback mTempo tick = do
-  tempo <- readMVar mTempo
-  if (paused tempo)
-    then do  -- TODO - do this via blocking read on the mvar somehow rather than polling
-      let pause = 0.01
-      threadDelay $ floor (pause * 1000000)
-      return $ if cps tempo < 0 then 0 else tick  -- reset tick to 0 if cps is negative
-    else do
-      now <- getCurrentTime
-      let beatsFromAtToTick = fromIntegral tick / fromIntegral tpb - beat tempo
-          delayUntilTick = beatsFromAtToTick / cps tempo - realToFrac (diffUTCTime now (at tempo))
-      threadDelay $ floor (delayUntilTick * 1000000)
-      callback tempo tick
-      return $ tick + 1
-
-streamEsp :: Backend a -> Shape -> IO (ParamPattern -> IO ())
-streamEsp backend shape = do
-  patternM <- newMVar silence
-  forkIO $ clockedTickEsp ticksPerCycle (onTick backend shape patternM)
-  return $ \p -> do swapMVar patternM p
-                    return ()
-
-dirtStreamEsp :: IO (ParamPattern -> IO ())
-dirtStreamEsp = do
-  backend <- dirtBackend
-  streamEsp backend dirt
-
-stateEsp :: Backend a -> Shape -> IO (MVar (ParamPattern, [ParamPattern]))
-stateEsp backend shape = do
-  patternsM <- newMVar (silence, [])
-  let ot = (onTick' backend shape patternsM) :: Tempo -> Int -> IO ()
-  forkIO $ clockedTickEsp ticksPerCycle ot
-  return patternsM
-
-dirtSettersEsp :: IO T.Time -> IO (ParamPattern -> IO (), (T.Time -> [ParamPattern] -> ParamPattern) -> ParamPattern -> IO ())
-dirtSettersEsp getNow = do
-  backend <- dirtBackend
-  ds <- stateEsp backend dirt
-  return (setter ds, transition getNow ds)
-
-superDirtSettersEsp :: IO T.Time -> IO (ParamPattern -> IO (), (T.Time -> [ParamPattern] -> ParamPattern) -> ParamPattern -> IO ())
-superDirtSettersEsp getNow = do
-  backend <- superDirtBackend 57120
-  ds <- stateEsp backend dirt
-  return (setter ds, transition getNow ds)
− Sound/Tidal/MultiMode.hs
@@ -1,106 +0,0 @@-module Sound.Tidal.MultiMode where
-
-import Control.Concurrent.MVar
-import Control.Concurrent
-import Control.Monad (forever)
-import Control.Monad.Loops (iterateM_)
-import Sound.OSC.FD
-import Data.Time.Clock
-import Data.Time.Clock.POSIX
-import Data.Time.Calendar (fromGregorian)
-
-import Sound.Tidal.Tempo
-import Sound.Tidal.Time as T
-import Sound.Tidal.Stream
-import Sound.Tidal.Dirt
-import Sound.Tidal.EspGrid
-import Sound.Tidal.Transition (transition)
-import Sound.Tidal.Pattern (silence)
-
-data StreamType = Dirt | SuperDirt
-
-data SyncType = NoSync | Esp
-
-initializeStreamType :: IO (MVar StreamType)
-initializeStreamType = newMVar SuperDirt
-
-changeStreamType :: MVar StreamType -> StreamType -> IO (IO StreamType)
-changeStreamType mvar t = return (swapMVar mvar t)
-
-initializeSyncType :: IO (MVar SyncType)
-initializeSyncType = newMVar NoSync
-
-changeSyncType :: MVar SyncType -> SyncType -> IO (IO SyncType)
-changeSyncType mvar t = return (swapMVar mvar t)
-
-type CpsUtils = (Double -> IO(), IO Rational)
-
-multiModeCpsUtils :: CpsUtils -> CpsUtils -> MVar SyncType -> IO CpsUtils
-multiModeCpsUtils (cpsNone,getNowNone) (cpsEsp,getNowEsp) mSync = return (cps,getNow)
-  where cps x = do s <- readMVar mSync
-                   case s of NoSync -> cpsNone x
-                             Esp -> cpsEsp x
-        getNow = do s <- readMVar mSync
-                    case s of NoSync -> getNowNone
-                              Esp -> getNowEsp
-
-multiModeSetters :: IO Rational -> IO Rational -> MVar SyncType -> MVar StreamType -> IO (ParamPattern -> IO ())
-multiModeSetters getNowNone getNowEsp mSync mStream = do
-  (classicDirt,tClassic) <- dirtSetters getNowNone
-  (espDirt,tEsp) <- dirtSettersEsp getNowEsp
-  (superDirt,tSuper) <- superDirtSetters getNowNone
-  (espSuperDirt,tEspSuper) <- superDirtSettersEsp getNowEsp
-  let f NoSync Dirt p = do classicDirt p
-                           espDirt silence
-                           superDirt silence
-                           espSuperDirt silence
-      f Esp Dirt p = do espDirt p
-                        classicDirt silence
-                        superDirt silence
-                        espSuperDirt silence
-      f NoSync SuperDirt p = do superDirt p
-                                classicDirt silence
-                                espDirt silence
-                                espSuperDirt silence
-      f Esp SuperDirt p = do espSuperDirt p
-                             classicDirt silence
-                             espDirt silence
-                             superDirt silence
-  return $ \p -> readMVar mSync >>= \s -> readMVar mStream >>= \t -> f s t p
-
-{-
-
-Example of using the above definitions:
-(note: if using Atom, evaluate each of the lines below one by one using shift-Enter)
-
-syncType <- initializeSyncType
-nosync <- changeSyncType syncType NoSync
-esp <- changeSyncType syncType Esp
-(cpsNone,getNowNone) <- cpsUtils
-(cpsEsp,getNowEsp,getTempoEsp) <- cpsUtilsEsp
-(cps,getNow) <- multiModeCpsUtils (cpsNone,getNowNone) (cpsEsp,getNowEsp) syncType
-
-streamType <- initializeStreamType
-classicDirt <- changeStreamType streamType Dirt
-superDirt <- changeStreamType streamType SuperDirt
-d1 <- multiModeSetters getNowNone getNowEsp syncType streamType
-d2 <- multiModeSetters getNowNone getNowEsp syncType streamType
-d3 <- multiModeSetters getNowNone getNowEsp syncType streamType
-d4 <- multiModeSetters getNowNone getNowEsp syncType streamType
-d5 <- multiModeSetters getNowNone getNowEsp syncType streamType
-d6 <- multiModeSetters getNowNone getNowEsp syncType streamType
-d7 <- multiModeSetters getNowNone getNowEsp syncType streamType
-d8 <- multiModeSetters getNowNone getNowEsp syncType streamType
-d9 <- multiModeSetters getNowNone getNowEsp syncType streamType
-d10 <- multiModeSetters getNowNone getNowEsp syncType streamType
-
-let bps x = cps (x/2)
-let hush = mapM_ ($ silence) [d1,d2,d3,d4,d5,d6,d7,d8,d9,d10]
-let solo = (>>) hush
-
-then you can evaluate "classicDirt" to switch to classic Dirt
-and "superDirt" to switch back to SuperDirt (the default)
-and "esp" to turn on EspGrid-aware synchronization
-and "nosync" to switch off EspGrid-aware synchronization (the default)
-(switching between sync types is only noticeable after the next time a pattern is redefined right now)
--}
− Sound/Tidal/OscStream.hs
@@ -1,91 +0,0 @@-module Sound.Tidal.OscStream where--import qualified Data.Map as Map-import Data.Maybe-import Sound.Tidal.Tempo (Tempo, cps)-import Sound.Tidal.Stream-import Sound.Tidal.Utils-import GHC.Float (float2Double, double2Float)-import Sound.OSC.FD-import Sound.OSC.Datum-import Sound.Tidal.Params--data TimeStamp = BundleStamp | MessageStamp | NoStamp- deriving Eq--data OscSlang = OscSlang {path :: String,-                          timestamp :: TimeStamp,-                          namedParams :: Bool,-                          preamble :: [Datum]-                         }--type OscMap = Map.Map Param Datum--toOscDatum :: Value -> Datum-toOscDatum (VF x) = float x-toOscDatum (VI x) = int32 x-toOscDatum (VS x) = string x--toOscMap :: ParamMap -> OscMap-toOscMap m = Map.map (toOscDatum) m---- constructs and sends an Osc Message according to the given slang--- and other params - this is essentially the same as the former--- toMessage in Stream.hs--send-  :: (Integral a) =>-     UDP-     -> OscSlang-     -> Shape-     -> Tempo-     -> a-     -> (Double,-         Double,-         OscMap)-     -> IO ()-send s slang shape change tick (on, off, m) = osc-    where-      osc | timestamp slang == BundleStamp =-            sendOSC s $ Bundle (ut_to_ntpr logicalOnset) [Message (path slang) oscdata]-          | timestamp slang == MessageStamp =-            sendOSC s $ Message (path slang) ((int32 sec):(int32 usec):oscdata)-          | otherwise =-            doAt logicalOnset $ sendOSC s $ Message (path slang) oscdata-      oscPreamble = cpsPrefix ++ preamble slang-      oscdata | namedParams slang = oscPreamble ++ (concatMap (\(k, v) -> [string (name k), v] )-                                                    $ Map.assocs m)-              | otherwise = oscPreamble ++ (catMaybes $ map (\x -> Map.lookup x m) (params shape))-      cpsPrefix | cpsStamp shape && namedParams slang = [string "cps",-                                                         float (cps change),-                                                         string "delta",-                                                         float (logicalOffset-                                                                - logicalOnset),-                                                         string "cycle", float cycle-                                                        ]-                | cpsStamp shape = [float (cps change)]-                | otherwise = []-      cycle = (on + fromIntegral tick) / (fromIntegral ticksPerCycle)-      _parameterise ds = mergelists (map (string . name) (params shape)) ds-      usec = floor $ 1000000 * (logicalOnset - (fromIntegral sec))-      sec = floor logicalOnset-      logicalOnset = logicalOnset' change tick on ((latency shape) + nudge)-      logicalOffset = logicalOnset' change tick off ((latency shape) + nudge)-      nudge = maybe 0 (toF) (Map.lookup nudge_p (m :: OscMap))-      toF (Float f) = float2Double f-      toF _ = 0---- type OscMap = Map.Map Param (Maybe Datum)-              --- Returns a function that will convert a generic ParamMap into a specific Osc message and send it over UDP to the supplied server--- messages will be built according to the given OscSlang-makeConnection :: String -> Int -> OscSlang -> IO (ToMessageFunc)-makeConnection address port slang = do-  s <- openUDP address port-  return (\ shape change tick (on,off,m) -> do-             let m' = if (namedParams slang) then (Just m) else (applyShape' shape m)-             -- this might result in Nothing, make sure we do this first-             m'' <- fmap (toOscMap) m'-             -- to allow us to simplify `send` (no `do`)-             return $ send s slang shape change tick (on,off,m'')-         )
− Sound/Tidal/Params.hs
@@ -1,391 +0,0 @@-module Sound.Tidal.Params where--import Sound.Tidal.Stream-import Sound.Tidal.Pattern-import qualified Data.Map as Map-import Sound.Tidal.Utils-import Control.Applicative---- | group multiple params into one-grp :: [Param] -> Pattern String -> ParamPattern-grp [] _ = silence-grp params p = (fmap lookupPattern p)-  where lookupPattern :: String -> ParamMap-        lookupPattern s = Map.fromList $ map (\(param,s') -> toPV param s') $ zip params $ (split s)-        split s = wordsBy (==':') s-        toPV :: Param -> String -> (Param, Value)-        toPV param@(S _ _) s = (param, (VS s))-        toPV param@(F _ _) s = (param, (VF $ read s))-        toPV param@(I _ _) s = (param, (VI $ read s))-{- |--A pattern of strings representing sounds or synth notes.--Internally, `sound` or its shorter alias `s` is a combination of the samplebank name and number when used with samples, or synth name and note number when used with a synthesiser. For example `bd:2` specifies the third sample (not the second as you might expect, because we start counting at zero) in the `bd` sample folder.--*Internally, `sound`/`s` is a combination of two parameters, the-hidden parameter `s'` which specifies the samplebank or synth, and the-`n` parameter which specifies the sample or note number. For example:--@-d1 $ sound "bd:2 sn:0"-@--is essentially the same as:--@-d1 $ s' "bd sn" # n "2 0"-@--`n` is therefore useful when you want to pattern the sample or note-number separately from the samplebank or synth. For example:--@-d1 $ n "0 5 ~ 2" # sound "drum"-@--is equivalent to:--@-d1 $ sound "drum:0 drum:5 ~ drum:2"-@--}-sound :: Pattern String -> ParamPattern-sound = grp [s_p, n_p]-s = sound--pF name defaultV = (make' VF param, param)-  where param = F name defaultV-pI name defaultV = (make' VI param, param)-  where param = I name defaultV-pS name defaultV = (make' VS param, param)-  where param = S name defaultV--- | a pattern of numbers that speed up (or slow down) samples while they play.-(accelerate, accelerate_p)       = pF "accelerate" (Just 0)--- | a pattern of numbers to specify the attack time (in seconds) of an envelope applied to each sample. Only takes effect if `release` is also specified.-(attack, attack_p)               = pF "attack" (Just (-1))--- | a pattern of numbers from 0 to 1. Sets the center frequency of the band-pass filter.-(bandf, bandf_p)                 = pF "bandf" (Just 0)--- | a pattern of numbers from 0 to 1. Sets the q-factor of the band-pass filter.y-(bandq, bandq_p)                 = pF "bandq" (Just 0)-{- | a pattern of numbers from 0 to 1. Skips the beginning of each sample, e.g. `0.25` to cut off the first quarter from each sample.--Using `begin "-1"` combined with `cut "-1"` means that when the sample cuts itself it will begin playback from where the previous one left off, so it will sound like one seamless sample. This allows you to apply a synth param across a long sample in a way similar to `chop`:--@-cps 0.5--d1 $ sound "breaks125*8" # unit "c" # begin "-1" # cut "-1" # coarse "1 2 4 8 16 32 64 128"-@--This will play the `breaks125` sample and apply the changing `coarse` parameter over the sample. Compare to:--@-d1 $ (chop 8 $ sounds "breaks125") # unit "c" # coarse "1 2 4 8 16 32 64 128"-@--which performs a similar effect, but due to differences in implementation sounds different.--}-begin_p, channel_p, legato_p, clhatdecay_p, coarse_p, crush_p :: Param-begin, legato, clhatdecay, crush :: Pattern Double -> ParamPattern-channel, coarse :: Pattern Int -> ParamPattern-(begin, begin_p)                 = pF "begin" (Just 0)--- | choose the physical channel the pattern is sent to, this is super dirt specific-(channel, channel_p)             = pI "channel" Nothing----legato controls the amount of overlap between two adjacent synth sounds-(legato, legato_p)             = pF "legato" (Just 1)--(clhatdecay, clhatdecay_p)       = pF "clhatdecay" (Just 0)--- | fake-resampling, a pattern of numbers for lowering the sample rate, i.e. 1 for original 2 for half, 3 for a third and so on.-(coarse, coarse_p)               = pI "coarse" (Just 0)--- | bit crushing, a pattern of numbers from 1 (for drastic reduction in bit-depth) to 16 (for barely no reduction).-(crush, crush_p)                 = pF "crush" (Just 0)-{- |-In the style of classic drum-machines, `cut` will stop a playing sample as soon as another samples with in same cutgroup is to be played.--An example would be an open hi-hat followed by a closed one, essentially muting the open.--@-d1 $ stack [-  sound "bd",-  sound "~ [~ [ho:2 hc/2]]" # cut "1"-  ]-@--This will mute the open hi-hat every second cycle when the closed one is played.--Using `cut` with negative values will only cut the same sample. This is useful to cut very long samples--@-d1 $ sound "[bev, [ho:3](3,8)]" # cut "-1"-@--Using `cut "0"` is effectively _no_ cutgroup.--}-(cut, cut_p)                     = pI "cut" (Just 0)--- | a pattern of numbers from 0 to 1. Applies the cutoff frequency of the low-pass filter.-(cutoff, cutoff_p)               = pF "cutoff" (Just 0)-(cutoffegint, cutoffegint_p)     = pF "cutoffegint" (Just 0)-(decay, decay_p)                 = pF "decay" (Just 0)--- | a pattern of numbers from 0 to 1. Sets the level of the delay signal.-(delay, delay_p)                 = pF "delay" (Just 0)--- | a pattern of numbers from 0 to 1. Sets the amount of delay feedback.-(delayfeedback, delayfeedback_p) = pF "delayfeedback" (Just (-1))--- | a pattern of numbers from 0 to 1. Sets the length of the delay.-(delaytime, delaytime_p)         = pF "delaytime" (Just (-1))-(detune, detune_p)               = pF "detune" (Just 0)--- | when set to `1` will disable all reverb for this pattern. See `room` and `size` for more information about reverb.-(dry, dry_p)                     = pF "dry" (Just 0)-{- the same as `begin`, but cuts the end off samples, shortening them;-  e.g. `0.75` to cut off the last quarter of each sample.--}-(end, end_p)                     = pF "end" (Just 1)--- | a pattern of numbers that specify volume. Values less than 1 make the sound quieter. Values greater than 1 make the sound louder.-(gain, gain_p)                   = pF "gain" (Just 1)-(gate, gate_p)                   = pF "gate" (Just 0)-(hatgrain, hatgrain_p)           = pF "hatgrain" (Just 0)--- | a pattern of numbers from 0 to 1. Applies the cutoff frequency of the high-pass filter.-(hcutoff, hcutoff_p)             = pF "hcutoff" (Just 0)--- | a pattern of numbers to specify the hold time (in seconds) of an envelope applied to each sample. Only takes effect if `attack` and `release` are also specified.-(hold, hold_p)                   = pF "hold" (Just 0)--- | a pattern of numbers from 0 to 1. Applies the resonance of the high-pass filter.-(hresonance, hresonance_p)       = pF "hresonance" (Just 0)-(kriole, kriole_p)               = pI "kriole" (Just 0)-(lagogo, lagogo_p)               = pF "lagogo" (Just 0)-(lclap, lclap_p)                 = pF "lclap" (Just 0)-(lclaves, lclaves_p)             = pF "lclaves" (Just 0)-(lclhat, lclhat_p)               = pF "lclhat" (Just 0)-(lcrash, lcrash_p)               = pF "lcrash" (Just 0)-(leslie, leslie_p)               = pF "leslie" (Just 0)-(lrate, lrate_p)                 = pF "lrate" (Just 0)-(lsize, lsize_p)                 = pF "lsize" (Just 0) -(lfo, lfo_p)                     = pF "lfo" (Just 0)-(lfocutoffint, lfocutoffint_p)   = pF "lfocutoffint" (Just 0)-(lfodelay, lfodelay_p)           = pF "lfodelay" (Just 0)-(lfoint, lfoint_p)               = pF "lfoint" (Just 0)-(lfopitchint, lfopitchint_p)     = pF "lfopitchint" (Just 0)-(lfoshape, lfoshape_p)           = pF "lfoshape" (Just 0)-(lfosync, lfosync_p)             = pF "lfosync" (Just 0)-(lhitom, lhitom_p)               = pF "lhitom" (Just 0)-(lkick, lkick_p)                 = pF "lkick" (Just 0)-(llotom, llotom_p)               = pF "llotom" (Just 0)-{- |  A pattern of numbers. Specifies whether delaytime is calculated relative to cps. When set to 1, delaytime is a direct multiple of a cycle.--}-(lock, lock_p)                 = pF "lock" (Just 0)--- | loops the sample (from `begin` to `end`) the specified number of times.-(loop, loop_p)                   = pF "loop" (Just 1)-(lophat, lophat_p)               = pF "lophat" (Just 0)-(lsnare, lsnare_p)               = pF "lsnare" (Just 0)--- | specifies the sample or note number to be used-(n, n_p)                         = pF "n" (Just 0)-(note, note_p)                   = pF "note" (Just 0)-{- |-Pushes things forward (or backwards within built-in latency) in time. Allows for nice things like _swing_ feeling:--@-d1 $ stack [-  sound "bd bd/4",-  sound "hh(5,8)"-  ] # nudge "[0 0.04]*4"-@----pitch model -}--degree, mtranspose, ctranspose, harmonic, stepsPerOctave, octaveRatio :: Pattern Double -> ParamPattern-degree_p, mtranspose_p, ctranspose_p, harmonic_p, stepsPerOctave_p, octaveRatio_p :: Param-(degree, degree_p)               = pF "degree" Nothing-(mtranspose, mtranspose_p)       = pF "mtranspose" Nothing-(ctranspose, ctranspose_p)       = pF "ctranspose" Nothing-(harmonic, harmonic_p)           = pF "ctranspose" Nothing-(stepsPerOctave, stepsPerOctave_p)           = pF "stepsPerOctave" Nothing-(octaveRatio, octaveRatio_p)           = pF "octaveRatio" Nothing-----Low values will give a more _human_ feeling, high values might result in quite the contrary.--(nudge, nudge_p)                 = pF "nudge" (Just 0)-(octave, octave_p)               = pI "octave" (Just 3)-(offset, offset_p)               = pF "offset" (Just 0)-(ophatdecay, ophatdecay_p)       = pF "ophatdecay" (Just 0)-{- |  a pattern of numbers. An `orbit` is a global parameter context for patterns. Patterns with the same orbit will share hardware output bus offset and global effects, e.g. reverb and delay. The maximum number of orbits is specified in the superdirt startup, numbers higher than maximum will wrap around.--}-(orbit, orbit_p)                 = pI "orbit" (Just 0)--- | a pattern of numbers between 0 and 1, from left to right (assuming stereo), once round a circle (assuming multichannel)-(pan, pan_p)                     = pF "pan" (Just 0.5)--- | a pattern of numbers between -inf and inf, which controls how much multichannel output is fanned out (negative is backwards ordering)-(panspan, panspan_p)                     = pF "span" (Just 1.0)--- | a pattern of numbers between 0.0 and 1.0, which controls the multichannel spread range (multichannel only)-(pansplay, pansplay_p)                     = pF "splay" (Just 1.0)--- | a pattern of numbers between 0.0 and inf, which controls how much each channel is distributed over neighbours (multichannel only)-(panwidth, panwidth_p)                     = pF "panwidth" (Just 2.0)--- | a pattern of numbers between -1.0 and 1.0, which controls the relative position of the centre pan in a pair of adjacent speakers (multichannel only)-(panorient, panorient_p)                     = pF "orientation" (Just 0.5)--(pitch1, pitch1_p)               = pF "pitch1" (Just 0)-(pitch2, pitch2_p)               = pF "pitch2" (Just 0)-(pitch3, pitch3_p)               = pF "pitch3" (Just 0)-(portamento, portamento_p)       = pF "portamento" (Just 0)--- | a pattern of numbers to specify the release time (in seconds) of an envelope applied to each sample. Only takes effect if `attack` is also specified.-(release, release_p)             = pF "release" (Just (-1))--- | a pattern of numbers from 0 to 1. Specifies the resonance of the low-pass filter.-(resonance, resonance_p)         = pF "resonance" (Just 0)--- | a pattern of numbers from 0 to 1. Sets the level of reverb.-(room, room_p)                   = pF "room" Nothing-(sagogo, sagogo_p)               = pF "sagogo" (Just 0)-(sclap, sclap_p)                 = pF "sclap" (Just 0)-(sclaves, sclaves_p)             = pF "sclaves" (Just 0)-(scrash, scrash_p)               = pF "scrash" (Just 0)-(semitone, semitone_p)           = pF "semitone" (Just 0)--- | wave shaping distortion, a pattern of numbers from 0 for no distortion up to 1 for loads of distortion.-(shape, shape_p)                 = pF "shape" (Just 0)--- | a pattern of numbers from 0 to 1. Sets the perceptual size (reverb time) of the `room` to be used in reverb.-(size, size_p)                   = pF "size" Nothing-(slide, slide_p)                 = pF "slide" (Just 0)--- | a pattern of numbers which changes the speed of sample playback, i.e. a cheap way of changing pitch. Negative values will play the sample backwards!-(speed, speed_p)                 = pF "speed" (Just 1)--- | a pattern of strings. Selects the sample to be played.-(s', s_p)                         = pS "s" Nothing-(stutterdepth, stutterdepth_p)   = pF "stutterdepth" (Just 0)-(stuttertime, stuttertime_p)     = pF "stuttertime" (Just 0)-(sustain, sustain_p)             = pF "sustain" (Just 0)-(tomdecay, tomdecay_p)           = pF "tomdecay" (Just 0)-{- | used in conjunction with `speed`, accepts values of "r" (rate, default behavior), "c" (cycles), or "s" (seconds).-Using `unit "c"` means `speed` will be interpreted in units of cycles, e.g. `speed "1"` means samples will be stretched to fill a cycle.-Using `unit "s"` means the playback speed will be adjusted so that the duration is the number of seconds specified by `speed`.--}-(unit, unit_p)                   = pS "unit" (Just "rate")-(velocity, velocity_p)           = pF "velocity" (Just 0.5)-(vcfegint, vcfegint_p)           = pF "vcfegint" (Just 0)-(vcoegint, vcoegint_p)           = pF "vcoegint" (Just 0)-(voice, voice_p)                 = pF "voice" (Just 0)--- | formant filter to make things sound like vowels, a pattern of either `a`, `e`, `i`, `o` or `u`. Use a rest (`~`) for no effect.-(vowel, vowel_p)                 = pS "vowel" (Just "")---- MIDI-specific params--(dur,dur_p)                      = pF "dur" (Just 0.05)-(modwheel,modwheel_p)            = pF "modwheel" (Just 0)-(expression,expression_p)        = pF "expression" (Just 1)-(sustainpedal,sustainpedal_p)    = pF "sustainpedal" (Just 0)---- Tremolo Audio DSP effect | params are "tremolorate" and "tremolodepth"-tremolorate, tremolodepth :: Pattern Double -> ParamPattern-tremolorate_p, tremolodepth_p :: Param-(tremolorate,tremolorate_p)      = pF "tremolorate" (Just 1)-(tremolodepth,tremolodepth_p)    = pF "tremolodepth" (Just 0.5)---- Phaser Audio DSP effect | params are "phaserrate" and "phaserdepth"-phaserrate, phaserdepth :: Pattern Double -> ParamPattern-phaserrate_p, phaserdepth_p :: Param-(phaserrate,phaserrate_p)      = pF "phaserrate" (Just 1)-(phaserdepth,phaserdepth_p)    = pF "phaserdepth" (Just 0.5)---- aliases-att, chdecay, ctf, ctfg, delayfb, delayt, lbd, lch, lcl, lcp, lcr, lfoc, lfoi-   , lfop, lht, llt, loh, lsn, ohdecay, phasdp, phasr, pit1, pit2, pit3, por, sag, scl, scp-   , scr, sld, std, stt, sus, tdecay, tremdp, tremr, vcf, vco, voi-      :: Pattern Double -> ParamPattern-att = attack-bpf = bandf-bpf_p = bandf_p-bpq = bandq-bpq_p = bandq_p-chdecay = clhatdecay-ctf  = cutoff-ctfg = cutoffegint-delayfb = delayfeedback-delayt  = delaytime-det  = detune-gat = gate-hg = hatgrain-hpf = hcutoff-hpf_p = hcutoff_p-hpq = hresonance-hpq_p = hresonance_p-lag = lagogo-lbd = lkick-lch = lclhat-lcl = lclaves-lcp = lclap-lcr = lcrash-lfoc = lfocutoffint-lfoi = lfoint-lfop = lfopitchint-lht = lhitom-llt = llotom-loh = lophat-lpf = cutoff-lpf_p = cutoff_p-lpq = resonance-lpq_p = resonance_p-lsn = lsnare-ohdecay = ophatdecay-phasdp = phaserdepth-phasr = phaserrate-pit1 = pitch1-pit2 = pitch2-pit3 = pitch3-por = portamento-rel = release-sag = sagogo-scl = sclaves-scp = sclap-scr = scrash-sz  = size-sld = slide-std = stutterdepth-stt = stuttertime-sus  = sustain-tdecay = tomdecay-tremdp = tremolodepth-tremr = tremolorate-vcf  = vcfegint-vco  = vcoegint-voi  = voice--midinote :: Pattern Double -> ParamPattern-midinote = note . ((subtract 60) <$>)--drum :: Pattern String -> ParamPattern-drum = n . ((subtract 60) . drumN <$>)--drumN :: Num a => String -> a-drumN "bd"  = 36-drumN "sn"  = 38-drumN "lt"  = 43-drumN "ht"  = 50-drumN "ch"  = 42-drumN "oh"  = 46-drumN "cp"  = 39-drumN "cl"  = 75-drumN "ag"  = 67-drumN "cr"  = 49-drumN _ = 0----- SuperDirt MIDI Params--(array, array_p) = pF "array" Nothing-(midichan, midichan_p) = pF "midichan" Nothing-(control, control_p) = pF "control" Nothing--(ccn, ccn_p) = pF "ccn" Nothing-(ccv, ccv_p) = pF "ccv" Nothing-cc = grp [ccn_p, ccv_p]--(ctlNum, ctlNum_p) = pF "ctlNum" Nothing--(frameRate, frameRate_p) = pF "frameRate" Nothing-(frames, frames_p) = pF "frames" Nothing-(hours, hours_p) = pF "hours" Nothing--(midicmd, midicmd_p) = pS "midicmd" Nothing-command = midicmd--(minutes, minutes_p) = pF "minutes" Nothing-(progNum, progNum_p) = pF "progNum" Nothing-(seconds, seconds_p) = pF "seconds" Nothing-(songPtr, songPtr_p) = pF "songPtr" Nothing-(uid, uid_p) = pF "uid" Nothing-(val, val_p) = pF "val" Nothing
− Sound/Tidal/Parse.hs
@@ -1,436 +0,0 @@-{-# LANGUAGE OverloadedStrings, TypeSynonymInstances, FlexibleInstances, CPP #-}-{-# LANGUAGE LambdaCase #-}--module Sound.Tidal.Parse where--import Text.ParserCombinators.Parsec-import qualified Text.ParserCombinators.Parsec.Token as P-import Text.ParserCombinators.Parsec.Language ( haskellDef )-import Data.Ratio-import Data.Colour-import Data.Colour.Names-import Data.Colour.SRGB-import GHC.Exts( IsString(..) )--- import Data.Monoid--- import qualified Data.Semigroup as Sem-import Control.Exception as E-import Control.Applicative ((<$>), (<*>), pure)-import Data.Maybe-import Data.List--import Sound.Tidal.Pattern-import Sound.Tidal.Time (Arc, Time)--{--#ifdef TIDAL_SEMIGROUP-import qualified Data.Semigroup as Sem-#endif--}---- | AST representation of patterns--data TPat a = TPat_Atom a-            | TPat_Density (TPat Time) (TPat a)-            | TPat_Slow (TPat Time) (TPat a)-            | TPat_Zoom Arc (TPat a)-            | TPat_DegradeBy Double (TPat a)-            | TPat_Silence-            | TPat_Foot-            | TPat_Elongate Int-            | TPat_EnumFromTo (TPat a) (TPat a)-            | TPat_Cat [TPat a]-            | TPat_TimeCat [TPat a]-            | TPat_Overlay (TPat a) (TPat a)-            | TPat_ShiftL Time (TPat a)-              -- TPat_E Int Int (TPat a)-            | TPat_pE (TPat Int) (TPat Int) (TPat Integer) (TPat a)-            deriving (Show)--{--#ifdef TIDAL_SEMIGROUP-instance Sem.Semigroup (TPat a) where-  (<>) = TPat_Overlay--instance Parseable a => Monoid (TPat a) where-   mempty = TPat_Silence-   mappend = (<>)-#else-instance Parseable a => Monoid (TPat a) where-   mempty = TPat_Silence-   mappend = TPat_Overlay-#endif--}--toPat :: Enumerable a => TPat a -> Pattern a-toPat = \case-   TPat_Atom x -> atom x-   TPat_Density t x -> density (toPat t) $ toPat x-   TPat_Slow t x -> slow (toPat t) $ toPat x-   TPat_Zoom arc x -> zoom arc $ toPat x-   TPat_DegradeBy amt x -> _degradeBy amt $ toPat x-   TPat_Silence -> silence-   TPat_Cat xs -> fastcat $ map toPat xs-   TPat_TimeCat xs -> timeCat $ map (\(n, p) -> (toRational n, toPat p)) $ durations xs-   TPat_Overlay x0 x1 -> overlay (toPat x0) (toPat x1)-   TPat_ShiftL t x -> t `rotL` toPat x-   TPat_pE n k s thing ->-      unwrap $ _eoff <$> toPat n <*> toPat k <*> toPat s <*> pure (toPat thing)-   TPat_Foot -> error "Can't happen, feet (.'s) only used internally.."-   TPat_EnumFromTo a b -> unwrap $ fromTo <$> (toPat a) <*> (toPat b)-   -- TPat_EnumFromThenTo a b c -> unwrap $ fromThenTo <$> (toPat a) <*> (toPat b) <*> (toPat c)--durations :: [TPat a] -> [(Int, TPat a)]-durations [] = []-durations ((TPat_Elongate n):xs) = (n, TPat_Silence):(durations xs)-durations (a:(TPat_Elongate n):xs) = (n+1,a):(durations xs)-durations (a:xs) = (1,a):(durations xs)--p :: (Enumerable a, Parseable a) => String -> Pattern a-p = toPat . parseTPat--class Parseable a where-  parseTPat :: String -> TPat a--class Enumerable a where-  fromTo :: a -> a -> Pattern a-  fromThenTo :: a -> a -> a -> Pattern a--instance Parseable Double where-  parseTPat = parseRhythm pDouble-instance Enumerable Double where-  fromTo a b = enumFromTo' a b-  fromThenTo a b c = enumFromThenTo' a b c--instance Parseable String where-  parseTPat = parseRhythm pVocable-instance Enumerable String where-  fromTo a b = listToPat [a,b]-  fromThenTo a b c = listToPat [a,b,c]--instance Parseable Bool where-  parseTPat = parseRhythm pBool-instance Enumerable Bool where-  fromTo a b = listToPat [a,b]-  fromThenTo a b c = listToPat [a,b,c]--instance Parseable Int where-  parseTPat = parseRhythm pIntegral-instance Enumerable Int where-  fromTo a b = enumFromTo' a b-  fromThenTo a b c = enumFromThenTo' a b c--instance Parseable Integer where-  parseTPat s = parseRhythm pIntegral s-instance Enumerable Integer where-  fromTo a b = enumFromTo' a b-  fromThenTo a b c = enumFromThenTo' a b c--instance Parseable Rational where-  parseTPat = parseRhythm pRational-instance Enumerable Rational where-  fromTo a b = enumFromTo' a b-  fromThenTo a b c = enumFromThenTo' a b c--enumFromTo' a b | a > b = listToPat $ reverse $ enumFromTo b a-                | otherwise = listToPat $ enumFromTo a b--enumFromThenTo' a b c | a > c = listToPat $ reverse $ enumFromThenTo c (c + (a-b)) a-                      | otherwise = listToPat $ enumFromThenTo a b c--type ColourD = Colour Double --instance Parseable ColourD where-  parseTPat = parseRhythm pColour-instance Enumerable ColourD where-  fromTo a b = listToPat [a,b]-  fromThenTo a b c = listToPat [a,b,c]--instance (Enumerable a, Parseable a) => IsString (Pattern a) where-  fromString = toPat . parseTPat----instance (Parseable a, Pattern p) => IsString (p a) where---  fromString = p :: String -> p a--lexer   = P.makeTokenParser haskellDef--braces, brackets, parens, angles:: Parser a -> Parser a-braces  = P.braces lexer-brackets = P.brackets lexer-parens = P.parens lexer-angles = P.angles lexer--symbol :: String -> Parser String-symbol  = P.symbol lexer--natural, integer :: Parser Integer-natural = P.natural lexer-integer = P.integer lexer--float :: Parser Double-float = P.float lexer--naturalOrFloat :: Parser (Either Integer Double)-naturalOrFloat = P.naturalOrFloat lexer--data Sign      = Positive | Negative--applySign          :: Num a => Sign -> a -> a-applySign Positive =  id-applySign Negative =  negate--sign  :: Parser Sign-sign  =  do char '-'-            return Negative-         <|> do char '+'-                return Positive-         <|> return Positive--intOrFloat :: Parser Double-intOrFloat =  do s   <- sign-                 num <- naturalOrFloat-                 return (case num of-                            Right x -> applySign s x-                            Left  x -> fromIntegral $ applySign s x-                        )--r :: (Enumerable a, Parseable a) => String -> Pattern a -> IO (Pattern a)-r s orig = do E.handle -                (\err -> do putStrLn (show (err :: E.SomeException))-                            return orig -                )-                (return $ p s)--parseRhythm :: Parseable a => Parser (TPat a) -> String -> TPat a-parseRhythm f input = either (const TPat_Silence) id $ parse (pSequence f') "" input-  where f' = f-             <|> do symbol "~" <?> "rest"-                    return TPat_Silence--pSequenceN :: Parseable a => Parser (TPat a) -> GenParser Char () (Int, TPat a)-pSequenceN f = do spaces-                  -- d <- pDensity-                  ps <- many $ do a <- pPart f-                                  do Text.ParserCombinators.Parsec.try $ symbol ".."-                                     b <- pPart f-                                     return [TPat_EnumFromTo (TPat_Cat a) (TPat_Cat b)]-                                    <|> return a-                               <|> do symbol "."-                                      return [TPat_Foot]-                               <|> do es <- many1 (symbol "_")-                                      return [TPat_Elongate (length es)]-                  let ps' = TPat_Cat $ map elongate $ splitFeet $ concat ps-                  return (length ps, ps')--elongate xs | any (isElongate) xs = TPat_TimeCat xs-            | otherwise = TPat_Cat xs-  where isElongate (TPat_Elongate _) = True-        isElongate _ = False-{--expandEnum :: Parseable t => Maybe (TPat t) -> [TPat t] -> [TPat t]-expandEnum a [] = [a]-expandEnum (Just a) (TPat_Enum:b:ps) = (TPat_EnumFromTo a b) : (expandEnum Nothing ps)--- ignore ..s in other places-expandEnum a (TPat_Enum:ps) = expandEnum a ps-expandEnum (Just a) (b:ps) = a:(expandEnum b (Just c) ps)-expandEnum Nothing (c:ps) = expandEnum (Just c) ps--}---- could use splitOn here but `TPat a` isn't a member of `EQ`..-splitFeet :: [TPat t] -> [[TPat t]]-splitFeet [] = []-splitFeet ps = foot:(splitFeet ps')-  where (foot, ps') = takeFoot ps-        takeFoot [] = ([], [])-        takeFoot (TPat_Foot:ps) = ([], ps)-        takeFoot (p:ps) = (\(a,b) -> (p:a,b)) $ takeFoot ps--pSequence :: Parseable a => Parser (TPat a) -> GenParser Char () (TPat a)-pSequence f = do (_, p) <- pSequenceN f-                 return p--pSingle :: Parseable a => Parser (TPat a) -> Parser (TPat a)-pSingle f = f >>= pRand >>= pMult--pPart :: Parseable a => Parser (TPat a) -> Parser [TPat a]-pPart f = do part <- pSingle f <|> pPolyIn f <|> pPolyOut f-             part <- pE part-             part <- pRand part-             spaces-             parts <- pStretch part-                      <|> pReplicate part-             spaces-             return $ parts--pPolyIn :: Parseable a => Parser (TPat a) -> Parser (TPat a)-pPolyIn f = do ps <- brackets (pSequence f `sepBy` symbol ",")-               spaces-               pMult $ foldr TPat_Overlay TPat_Silence ps--pPolyOut :: Parseable a => Parser (TPat a) -> Parser (TPat a)-pPolyOut f = do ps <- braces (pSequenceN f `sepBy` symbol ",")-                spaces-                base <- do char '%'-                           spaces-                           i <- integer <?> "integer"-                           return $ Just (fromIntegral i)-                        <|> return Nothing-                pMult $ foldr TPat_Overlay TPat_Silence $ scale base ps-             <|>-             do ps <- angles (pSequenceN f `sepBy` symbol ",")-                spaces-                pMult $ foldr TPat_Overlay TPat_Silence $ scale (Just 1) ps-  where scale _ [] = []-        scale base (ps@((n,_):_)) = map (\(n',p) -> TPat_Density (TPat_Atom $ fromIntegral (fromMaybe n base)/ fromIntegral n') p) ps--pString :: Parser (String)-pString = do c <- (letter <|> oneOf "0123456789") <?> "charnum"-             cs <- many (letter <|> oneOf "0123456789:.-_") <?> "string"-             return (c:cs)--pVocable :: Parser (TPat String)-pVocable = do v <- pString-              return $ TPat_Atom v--pDouble :: Parser (TPat Double)-pDouble = do f <- choice [intOrFloat, parseNote] <?> "float"-             return $ TPat_Atom f--pBool :: Parser (TPat Bool)-pBool = do oneOf "t1"-           return $ TPat_Atom True-        <|>-        do oneOf "f0"-           return $ TPat_Atom False--parseIntNote  :: Integral i => Parser i-parseIntNote = do s <- sign-                  i <- choice [integer, parseNote]-                  return $ applySign s $ fromIntegral i--parseInt :: Parser Int-parseInt = do s <- sign-              i <- integer-              return $ applySign s $ fromIntegral i--pIntegral :: Parseable a => Integral a => Parser (TPat a)-pIntegral = TPat_Atom <$> parseIntNote--parseNote :: Num a => Parser a-parseNote = do n <- notenum-               modifiers <- many noteModifier-               octave <- option 5 natural-               let n' = foldr (+) n modifiers-               return $ fromIntegral $ n' + ((octave-5)*12)-  where-        notenum :: Parser Integer-        notenum = choice [char 'c' >> return 0,-                          char 'd' >> return 2,-                          char 'e' >> return 4,-                          char 'f' >> return 5,-                          char 'g' >> return 7,-                          char 'a' >> return 9,-                          char 'b' >> return 11-                         ]-        noteModifier :: Parser Integer-        noteModifier = choice [char 's' >> return 1,-                               char 'f' >> return (-1),-                               char 'n' >> return 0-                              ]--fromNote :: Num a => Pattern String -> Pattern a-fromNote p = (\s -> either (const 0) id $ parse parseNote "" s) <$> p--pColour :: Parser (TPat ColourD)-pColour = do name <- many1 letter <?> "colour name"-             colour <- readColourName name <?> "known colour"-             return $ TPat_Atom colour--pMult :: Parseable a => TPat a -> Parser (TPat a)-pMult thing = do char '*'-                 spaces-                 r <- (pRational <|> pPolyIn pRational  <|> pPolyOut pRational)-                 return $ TPat_Density r thing-              <|>-              do char '/'-                 spaces-                 r <- (pRational <|> pPolyIn pRational  <|> pPolyOut pRational)-                 return $ TPat_Slow r thing-              <|>-              return thing----pRand :: Parseable a => TPat a -> Parser (TPat a)-pRand thing = do char '?'-                 spaces-                 return $ TPat_DegradeBy 0.5 thing-              <|> return thing--pE :: Parseable a => TPat a -> Parser (TPat a)-pE thing = do (n,k,s) <- parens (pair)-              pure $ TPat_pE n k s thing-            <|> return thing-   where pair :: Parser (TPat Int, TPat Int, TPat Integer)-         pair = do a <- pSequence pIntegral-                   spaces-                   symbol ","-                   spaces-                   b <- pSequence pIntegral-                   c <- do symbol ","-                           spaces-                           pSequence pIntegral-                        <|> return (TPat_Atom 0)-                   return (a, b, c)--eoff :: Pattern Int -> Pattern Int -> Pattern Integer -> Pattern a -> Pattern a-eoff = temporalParam3 _eoff--_eoff :: Int -> Int -> Integer -> Pattern a -> Pattern a-_eoff n k s p = ((s%(fromIntegral k)) `rotL`) (_e n k p)-   -- TPat_ShiftL (s%(fromIntegral k)) (TPat_E n k p)--pReplicate :: Parseable a => TPat a -> Parser [TPat a]-pReplicate thing =-  do extras <- many $ do char '!'-                         -- if a number is given (without a space)slow 2 $ fast-                         -- replicate that number of times-                         n <- ((read <$> many1 digit) <|> return 2)-                         spaces-                         thing' <- pRand thing-                         -- -1 because we already have parsed the original one-                         return $ replicate (fromIntegral (n-1)) thing'-     return (thing:concat extras)---pStretch :: Parseable a => TPat a -> Parser [TPat a]-pStretch thing =-  do char '@'-     n <- ((read <$> many1 digit) <|> return 1)-     return $ map (\x -> TPat_Zoom (x%n,(x+1)%n) thing) [0 .. (n-1)]--pRatio :: Parser (Rational)-pRatio = do s <- sign-            n <- natural-            result <- do char '%'-                         d <- natural-                         return (n%d)-                      <|>-                      do char '.'-                         s <- many1 digit-                         -- A hack, but not sure if doing this-                         -- numerically would be any faster..-                         return (toRational $ ((read $ show n ++ "." ++ s)  :: Double))-                      <|>-                      return (n%1)-            return $ applySign s result--pRational :: Parser (TPat Rational)-pRational = do r <- pRatio-               return $ TPat_Atom r--{--pDensity :: Parser (Rational)-pDensity = angles (pRatio <?> "ratio")-           <|>-           return (1 % 1)--}
− Sound/Tidal/Pattern.hs
@@ -1,1752 +0,0 @@-{-# LANGUAGE DeriveDataTypeable, CPP #-}-{-# OPTIONS_GHC -Wall -fno-warn-orphans -fno-warn-name-shadowing #-}--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 Debug.Trace-import Data.Typeable-import Data.Function-import System.Random.Mersenne.Pure64-import Data.Char (digitToInt)-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--{--#ifdef TIDAL_SEMIGROUP-import qualified Data.Semigroup as Sem-#endif--}---- | The pattern datatype, a function from a time @Arc@ to @Event@--- values. For discrete patterns, this returns the events which are--- active during that time. For continuous patterns, events with--- values for the midpoint of the given @Arc@ is returned.-newtype 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---- | @show (p :: Pattern)@ returns a text string representing the--- event values active during the first cycle of the given pattern.-instance (Show a) => Show (Pattern a) where-  show p@(Pattern _) = unwords $ map showEvent $ arc p (0, 1)---- | converts a ratio into human readable string, e.g. @1/3@-showTime :: (Show a, Integral a) => Ratio a -> String-showTime t | denominator t == 1 = show (numerator t)-           | otherwise = show (numerator t) ++ ('/':show (denominator t))---- | converts a time arc into human readable string, e.g. @1/3 3/4@-showArc :: Arc -> String-showArc a = (showTime $ fst a) ++ (' ':showTime (snd a))---- | converts an event into human readable string, e.g. @("bd" 1/4 2/3)@-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---- | @pure a@ returns a pattern with an event with value @a@, which--- has a duration of one cycle, and repeats every cycle.-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'))-                )--{--#ifdef TIDAL_SEMIGROUP--- | @mappend@ a.k.a. @<>@ is a synonym for @overlay@.-instance Sem.Semigroup (Pattern a) where-  (<>) = overlay--instance Monoid (Pattern a) where-  mempty = silence-  mappend = (<>)--#else--- | @mempty@ is a synonym for @silence@.-instance Monoid (Pattern a) where-  mempty = silence-  mappend = overlay-#endif--}--instance Monad Pattern where-  return = pure--  p >>= f = unwrap (f <$> p)--unwrap :: Pattern (Pattern a) -> Pattern a-unwrap p = Pattern $ \a -> concatMap (\(_, outerPart, p') -> mapMaybe (munge outerPart) $ arc p' a) (arc p a)-  where munge a (whole,part,v) = do part' <- subArc a part-                                    return (whole, part',v)----- | @atom@ is a synonym for @pure@.-atom :: a -> Pattern a-atom = pure---- | @silence@ returns a pattern with no events.-silence :: Pattern a-silence = Pattern $ const []---- | @withQueryArc f p@ returns a new @Pattern@ with function @f@--- applied to the @Arc@ values passed to the original @Pattern@ @p@.-withQueryArc :: (Arc -> Arc) -> Pattern a -> Pattern a-withQueryArc f p = Pattern $ \a -> arc p (f a)---- | @withQueryTime f p@ returns a new @Pattern@ with function @f@--- applied to the both the start and end @Time@ of the @Arc@ passed to--- @Pattern@ @p@.-withQueryTime :: (Time -> Time) -> Pattern a -> Pattern a-withQueryTime = withQueryArc . mapArc---- | @withResultArc f p@ returns a new @Pattern@ with function @f@--- applied to the @Arc@ values in the events returned from the--- original @Pattern@ @p@.-withResultArc :: (Arc -> Arc) -> Pattern a -> Pattern a-withResultArc f p = Pattern $ \a -> mapArcs f $ arc p a---- | @withResultTime f p@ returns a new @Pattern@ with function @f@--- applied to the both the start and end @Time@ of the @Arc@ values in--- the events returned from the original @Pattern@ @p@.-withResultTime :: (Time -> Time) -> Pattern a -> Pattern a-withResultTime = withResultArc . mapArc---- | @withEvent f p@ returns a new @Pattern@ with events mapped over--- function @f@.-withEvent :: (Event a -> Event b) -> Pattern a -> Pattern b-withEvent f p = Pattern $ \a -> map f $ arc p a---- | @timedValues p@ returns a new @Pattern@ where values are turned--- into tuples of @Arc@ and value.-timedValues :: Pattern a -> Pattern (Arc, a)-timedValues = withEvent (\(a,a',v) -> (a,a',(a,v)))---- | @overlay@ combines two @Pattern@s into a new pattern, so that--- their events are combined over time. This is the same as the infix--- operator `<>`.-overlay :: Pattern a -> Pattern a -> Pattern a-overlay p p' = Pattern $ \a -> (arc p a) ++ (arc p' a)---- | @stack@ combines a list of @Pattern@s into a new pattern, so that--- their events are combined over time.-stack :: [Pattern a] -> Pattern a-stack = foldr overlay silence---- | @append@ combines two patterns @Pattern@s into a new pattern, so--- that the events of the second pattern are appended to those of the--- first pattern, within a single cycle--append :: Pattern a -> Pattern a -> Pattern a-append a b = fastcat [a,b]---- | @append'@ does the same as @append@, but over two cycles, so that--- the cycles alternate between the two patterns.-append' :: Pattern a -> Pattern a -> Pattern a-append' a b  = slowcat [a,b]---- | @fastcat@ returns a new pattern which interlaces the cycles of the--- given patterns, within a single cycle. It's the equivalent of--- @append@, but with a list of patterns.-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@ does the same as @fastcat@, but maintaining the duration of--- the original patterns. It is the equivalent of @append'@, but with--- a list of patterns.--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') = (s-offset, e-offset)---- | @cat@ is an alias of @slowcat@-cat :: [Pattern a] -> Pattern a-cat = slowcat---- | @listToPat@ turns the given list of values to a Pattern, which--- cycles through the list.-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@ is similar to @listToPat@, but allows values to--- be optional using the @Maybe@ type, so that @Nothing@ results in--- gaps in the pattern.-maybeListToPat :: [Maybe a] -> Pattern a-maybeListToPat = fastcat . map f-  where f Nothing = silence-        f (Just x) = atom x---- | @run@ @n@ returns a pattern representing a cycle of numbers from @0@ to @n-1@.-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 .. n-1]--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 $ (`f` 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' $ (`f` 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@ (also known as @density@) returns the given pattern with speed--- (or density) increased by the given @Time@ factor. Therefore @fast 2 p@--- will return a pattern that is twice as fast, and @fast (1/3) p@--- will return one three times as slow.-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@ is an alias of @fast@. @fast@ is quicker to type, but--- @density@ is its old name so is used in a lot of examples.-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 (negate r) p-             | otherwise = withResultTime (/ r) $ withQueryTime (* r) p---- | @fastGap@ (also known as @densityGap@ is similar to @fast@ but maintains its cyclic--- alignment. For example, @fastGap 2 p@ would squash the events in--- pattern @p@ into the first half of each cycle (and the second--- halves would be empty).-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@ does the opposite of @fast@, i.e. @slow 2 p@ will return a--- pattern that is half the speed.-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---- | The @<~@ operator shifts (or rotates) a pattern to the left (or--- counter-clockwise) by the given @Time@ value. For example--- @(1%16) <~ p@ will return a pattern with all the events moved--- one 16th of a cycle to the left.-rotL :: Time -> Pattern a -> Pattern a-rotL t p = withResultTime (subtract t) $ withQueryTime (+ t) p--(<~) :: Pattern Time -> Pattern a -> Pattern a-(<~) = temporalParam rotL---- | The @~>@ operator does the same as @<~@ but shifts events to the--- right (or clockwise) rather than to the left.-rotR :: Time -> Pattern a -> Pattern a-rotR = rotL . (0-)--(~>) :: Pattern Time -> Pattern a -> Pattern a-(~>) = temporalParam rotR--{- | (The above means that `brak` is a function from patterns of any type,-to a pattern of the same type.)--Make a pattern sound a bit like a breakbeat--Example:--@-d1 $ sound (brak "bd sn kurt")-@--}-brak :: Pattern a -> Pattern a-brak = when ((== 1) . (`mod` 2)) (((1%4) `rotR`) . (\x -> fastcat [x, silence]))--{- | Divides a pattern into a given number of subdivisions, plays the subdivisions-in order, but increments the starting subdivision each cycle. The pattern-wraps to the first subdivision after the last subdivision is played.--Example:--@-d1 $ iter 4 $ sound "bd hh sn cp"-@--This will produce the following over four cycles:--@-bd hh sn cp-hh sn cp bd-sn cp bd hh-cp bd hh sn-@--There is also `iter'`, which shifts the pattern in the opposite direction.---}-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 .. (n-1)]---- | @iter'@ is the same as @iter@, but decrements the starting--- subdivision instead of incrementing it.-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 .. (n-1)]---- | @rev p@ returns @p@ with the event positions in each cycle--- reversed (or mirrored).-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, e-e'), part, v)-        makeWholeAbsolute ((s,e), part@(s',e'), v) = ((s'-e,e'+s), part, v)-        mid (s,_) = (sam s) + 0.5---- | @palindrome p@ applies @rev@ to @p@ every other cycle, so that--- the pattern alternates between forwards and backwards.-palindrome :: Pattern a -> Pattern a-palindrome p = append' p (rev p)--{-|-Only `when` the given test function returns `True` the given pattern transformation is applied. The test function will be called with the current cycle as a number.--@-d1 $ when ((elem '4').show)-  (striate 4)-  $ sound "hh hc"-@--The above will only apply `striate 4` to the pattern if the current cycle number contains the number 4. So the fourth cycle will be striated and the fourteenth and so on. Expect lots of striates after cycle number 399.--}-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])--{- | The function @seqP@ allows you to define when-a sound within a list starts and ends. The code below contains three-separate patterns in a `stack`, but each has different start times-(zero cycles, eight cycles, and sixteen cycles, respectively). All-patterns stop after 128 cycles:--@-d1 $ seqP [-  (0, 128, sound "bd bd*2"),-  (8, 128, sound "hh*2 [sn cp] cp future*4"),-  (16, 128, sound (samples "arpy*8" (run 16)))-]-@--}-seqP :: [(Time, Time, Pattern a)] -> Pattern a-seqP ps = stack $ map (\(s, e, p) -> playFor s e ((sam s) `rotR` p)) ps---- | @every n f p@ applies the function @f@ to @p@, but only affects--- every @n@ cycles.-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 n o f'@ is like @every n f@ with an offset of @o@ cycles-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 ns f p@ applies the function @f@ to @p@, and is applied for--- each cycle in @ns@.-foldEvery :: [Int] -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a-foldEvery ns f p = foldr ($) p (map (\x -> _every x f) ns)---- | @sig f@ takes a function from time to values, and turns it into a--- @Pattern@.-sig :: (Time -> a) -> Pattern a-sig f = Pattern f'-  where f' (s,e) | s > e = []-                 | otherwise = [((s,e), (s,e), f s)]---- | @sinewave@ returns a @Pattern@ of continuous @Fractional@ values following a--- sinewave with frequency of one cycle, and amplitude from 0 to 1.-sinewave :: Fractional a => Pattern a-sinewave = sig $ \t -> ((sin_rat $ pi * 2 * (fromRational t)) + 1) / 2-  where sin_rat = fromRational . toRational . sin---- | @sine@ is a synonym for @sinewave@.-sine :: Fractional a => Pattern a-sine = sinewave---- | @sine@ is a synonym for @0.25 ~> sine@.-cosine :: Fractional a => Pattern a-cosine = 0.25 ~> sine---- | @sineAmp d@ returns @sinewave@ with its amplitude offset by @d@.--- Deprecated, as these days you can simply do e.g. (sine + 0.5)-sineAmp :: Fractional a => a -> Pattern a-sineAmp offset = (+ offset) <$> sinewave1---- | @sawwave@ is the equivalent of @sinewave@ for (ascending) sawtooth waves.-sawwave :: (Fractional a, Real a) => Pattern a-sawwave = sig $ \t -> mod' (fromRational t) 1---- | @saw@ is a synonym for @sawwave@.-saw :: (Fractional a, Real a) => Pattern a-saw = sawwave---- | @triwave@ is the equivalent of @sinewave@ for triangular waves.-triwave :: (Fractional a, Real a) => Pattern a-triwave = append sawwave1 (rev sawwave1)---- | @tri@ is a synonym for @triwave@.-tri :: (Fractional a, Real a) => Pattern a-tri = triwave---- | @squarewave1@ is the equivalent of @sinewave@ for square waves.-squarewave :: (Fractional a, Real a) => Pattern a-squarewave = sig $-             \t -> fromIntegral $ ((floor $ (mod' (fromRational t :: Double) 1) * 2) :: Integer)---- | @square@ is a synonym for @squarewave@.-square :: (Fractional a, Real a) => Pattern a-square = squarewave---- deprecated..-sinewave1 :: Fractional a => Pattern a-sinewave1 = sinewave-sine1 :: Fractional a => Pattern a-sine1 = sinewave-sinerat = sine-ratsine = sine-sinerat1 = sine-sineAmp1 :: Fractional a => a -> Pattern a-sineAmp1 = sineAmp-sawwave1 :: (Fractional a, Real a) => Pattern a-sawwave1 = sawwave-saw1 :: (Fractional a, Real a) => Pattern a-saw1 = sawwave-sawrat = saw-sawrat1 = saw-triwave1 :: (Fractional a, Real a) => Pattern a-triwave1 = triwave-tri1 :: (Fractional a, Real a) => Pattern a-tri1 = triwave-trirat = tri-trirat1 = tri-squarewave1 :: (Fractional a, Real a) => Pattern a-squarewave1 = squarewave-square1 :: (Fractional a, Real a) => Pattern a-square1 = square---- | @envL@ is a @Pattern@ of continuous @Double@ values, representing--- a linear interpolation between 0 and 1 during the first cycle, then--- staying constant at 1 for all following cycles. Possibly only--- useful if you're using something like the retrig function defined--- in tidal.el.-envL :: Pattern Double-envL = sig $ \t -> max 0 $ min (fromRational t) 1---- like envL but reversed.-envLR :: Pattern Double-envLR = (1-) <$> envL---- 'Equal power' for gain-based transitions-envEq :: Pattern Double-envEq = sig $ \t -> sqrt (sin (pi/2 * (max 0 $ min (fromRational (1-t)) 1)))---- Equal power reversed-envEqR :: Pattern Double-envEqR = sig $ \t -> sqrt (cos (pi/2 * (max 0 $ min (fromRational (1-t)) 1)))--fadeOut :: Time -> Pattern a -> Pattern a-fadeOut n = spread' (_degradeBy) (_slow n $ envL)---- Alternate versions where you can provide the time from which the fade starts-fadeOut' :: Time -> Time -> Pattern a -> Pattern a-fadeOut' from dur p = spread' (_degradeBy) (from `rotR` _slow dur envL) p---- The 1 <~ is so fade ins and outs have different degredations-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)--{- | (The above is difficult to describe, if you don't understand Haskell,-just ignore it and read the below..)--The `spread` function allows you to take a pattern transformation-which takes a parameter, such as `slow`, and provide several-parameters which are switched between. In other words it 'spreads' a-function across several values.--Taking a simple high hat loop as an example:--@-d1 $ sound "ho ho:2 ho:3 hc"-@--We can slow it down by different amounts, such as by a half:--@-d1 $ slow 2 $ sound "ho ho:2 ho:3 hc"-@--Or by four thirds (i.e. speeding it up by a third; `4%3` means four over-three):--@-d1 $ slow (4%3) $ sound "ho ho:2 ho:3 hc"-@--But if we use `spread`, we can make a pattern which alternates between-the two speeds:--@-d1 $ spread slow [2,4%3] $ sound "ho ho:2 ho:3 hc"-@--Note that if you pass ($) as the function to spread values over, you-can put functions as the list of values. For example:--@-d1 $ spread ($) [density 2, rev, slow 2, striate 3, (# speed "0.8")]-    $ sound "[bd*2 [~ bd]] [sn future]*2 cp jvbass*4"-@--Above, the pattern will have these transforms applied to it, one at a time, per cycle:--* cycle 1: `density 2` - pattern will increase in speed-* cycle 2: `rev` - pattern will be reversed-* cycle 3: `slow 2` - pattern will decrease in speed-* cycle 4: `striate 3` - pattern will be granualized-* cycle 5: `(# speed "0.8")` - pattern samples will be played back more slowly--After `(# speed "0.8")`, the transforms will repeat and start at `density 2` again.--}-spread :: (a -> t -> Pattern b) -> [a] -> t -> Pattern b-spread f xs p = slowcat $ map (`f` p) xs--slowspread :: (a -> t -> Pattern b) -> [a] -> t -> Pattern b-slowspread = spread--{- | @fastspread@ works the same as @spread@, but the result is squashed into a single cycle. If you gave four values to @spread@, then the result would seem to speed up by a factor of four. Compare these two:--d1 $ spread chop [4,64,32,16] $ sound "ho ho:2 ho:3 hc"--d1 $ fastspread chop [4,64,32,16] $ sound "ho ho:2 ho:3 hc"--There is also @slowspread@, which is an alias of @spread@.--}-fastspread :: (a -> t -> Pattern b) -> [a] -> t -> Pattern b-fastspread f xs p = fastcat $ map (\x -> f x p) xs--{- | There's a version of this function, `spread'` (pronounced "spread prime"), which takes a *pattern* of parameters, instead of a list:--@-d1 $ spread' slow "2 4%3" $ sound "ho ho:2 ho:3 hc"-@--This is quite a messy area of Tidal - due to a slight difference of-implementation this sounds completely different! One advantage of-using `spread'` though is that you can provide polyphonic parameters, e.g.:--@-d1 $ spread' slow "[2 4%3, 3]" $ sound "ho ho:2 ho:3 hc"-@--}-spread' :: Monad m => (a -> b -> m c) -> m a -> b -> m c-spread' f vpat pat = vpat >>= \v -> f v pat--{- | `spreadChoose f xs p` is similar to `slowspread` but picks values from-`xs` at random, rather than cycling through them in order. It has a-shorter alias `spreadr`.--}-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)---- Filter out events that have had their onsets cut off-filterOnsets :: Pattern a -> Pattern a-filterOnsets (Pattern f) =-  Pattern $ (filter (\e -> eventOnset e >= eventStart e)) . f---- Filter events which have onsets, which are within the given range--- TODO - what about < e ??-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---- Samples some events from a pattern, returning a list of onsets--- (relative to the given arc), deltas (durations) and values.-seqToRelOnsetDeltas :: Arc -> Pattern a -> [(Double, Double, a)]-seqToRelOnsetDeltas (s, e) p = map (\((s', e'), _, x) -> (fromRational $ (s'-s) / (e-s), fromRational $ (e'-s) / (e-s), 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"---{-| Decide whether to apply one or another function depending on the result of a test function that is passed the current cycle as a number.--@-d1 $ ifp ((== 0).(flip mod 2))-  (striate 4)-  (# coarse "24 48") $-  sound "hh hc"-@--This will apply `striate 4` for every _even_ cycle and aply `# coarse "24 48"` for every _odd_.--Detail: As you can see the test function is arbitrary and does not rely on anything tidal specific. In fact it uses only plain haskell functionality, that is: it calculates the modulo of 2 of the current cycle which is either 0 (for even cycles) or 1. It then compares this value against 0 and returns the result, which is either `True` or `False`. This is what the `ifp` signature's first part signifies `(Int -> Bool)`, a function that takes a whole number and returns either `True` or `False`.--}-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` generates a continuous pattern of (pseudo-)random, floating point numbers between `0` and `1`.--@-d1 $ sound "bd*8" # pan rand-@--pans bass drums randomly--@-d1 $ sound "sn sn ~ sn" # gain rand-@--makes the snares' randomly loud and quiet.--Numbers coming from this pattern are random, but dependent on time. So if you reset time via `cps (-1)` the random pattern will emit the exact same _random_ numbers again.--In cases where you need two different random patterns, you can shift one of them around to change the time from which the _random_ pattern is read, note the difference:--@-d1 $ jux (|+| gain rand) $ sound "sn sn ~ sn" # gain rand-@--and with the juxed version shifted backwards for 1024 cycles:--@-d1 $ jux (|+| ((1024 <~) $ gain rand)) $ sound "sn sn ~ sn" # gain rand-@--}-rand :: Pattern Double-rand = Pattern $ \a -> [(a, a, timeToRand $ (midPoint a))]--timeToRand :: RealFrac r => r -> Double-timeToRand t = fst $ randomDouble $ pureMT $ floor $ (*1000000) t--{- | Just like `rand` but for whole numbers, `irand n` generates a pattern of (pseudo-) random whole numbers between `0` to `n-1` inclusive. Notably used to pick a random-samples from a folder:--@-d1 $ n (irand 5) # sound "drum"-@--}-irand :: Num a => Int -> Pattern a-irand i = (fromIntegral . (floor :: Double -> Int) . (* (fromIntegral i))) <$> rand--{- | Randomly picks an element from the given list--@-d1 $ sound (samples "xx(3,8)" (tom $ choose ["a", "e", "g", "c"]))-@--plays a melody randomly choosing one of the four notes \"a\", \"e\", \"g\", \"c\".--}-choose :: [a] -> Pattern a-choose [] =  E.throw (E.ErrorCall "Empty list. Nothing to choose from.")-choose xs = (xs !!) <$> (irand $ length xs)--{- |-Similar to `degrade` `degradeBy` allows you to control the percentage of events that-are removed. For example, to remove events 90% of the time:--@-d1 $ slow 2 $ degradeBy 0.9 $ sound "[[[feel:5*8,feel*3] feel:3*8], feel*4]"-   # accelerate "-6"-   # speed "2"-@---}--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)---{- | Use @sometimesBy@ to apply a given function "sometimes". For example, the-following code results in `density 2` being applied about 25% of the time:--@-d1 $ sometimesBy 0.25 (density 2) $ sound "bd*8"-@--There are some aliases as well:--@-sometimes = sometimesBy 0.5-often = sometimesBy 0.75-rarely = sometimesBy 0.25-almostNever = sometimesBy 0.1-almostAlways = sometimesBy 0.9-@--}-sometimesBy :: Double -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a-sometimesBy x f p = overlay (_degradeBy x p) (f $ _unDegradeBy x p)---- | @sometimes@ is an alias for sometimesBy 0.5.-sometimes :: (Pattern a -> Pattern a) -> Pattern a -> Pattern a-sometimes = sometimesBy 0.5---- | @often@ is an alias for sometimesBy 0.75.-often :: (Pattern a -> Pattern a) -> Pattern a -> Pattern a-often = sometimesBy 0.75---- | @rarely@ is an alias for sometimesBy 0.25.-rarely :: (Pattern a -> Pattern a) -> Pattern a -> Pattern a-rarely = sometimesBy 0.25---- | @almostNever@ is an alias for sometimesBy 0.1-almostNever :: (Pattern a -> Pattern a) -> Pattern a -> Pattern a-almostNever = sometimesBy 0.1---- | @almostAlways@ is an alias for sometimesBy 0.9-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@ is a cycle-by-cycle version of @sometimesBy@. It has a-`someCycles = someCyclesBy 0.5` alias -}-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--somecycles :: (Pattern a -> Pattern a) -> Pattern a -> Pattern a-somecycles = someCycles--{- | `degrade` randomly removes events from a pattern 50% of the time:--@-d1 $ slow 2 $ degrade $ sound "[[[feel:5*8,feel*3] feel:3*8], feel*4]"-   # accelerate "-6"-   # speed "2"-@--The shorthand syntax for `degrade` is a question mark: `?`. Using `?`-will allow you to randomly remove events from a portion of a pattern:--@-d1 $ slow 2 $ sound "bd ~ sn bd ~ bd? [sn bd?] ~"-@--You can also use `?` to randomly remove events from entire sub-patterns:--@-d1 $ slow 2 $ sound "[[[feel:5*8,feel*3] feel:3*8]?, feel*4]"-@--}-degrade :: Pattern a -> Pattern a-degrade = _degradeBy 0.5---- | @wedge t p p'@ combines patterns @p@ and @p'@ by squashing the--- @p@ into the portion of each cycle given by @t@, and @p'@ into the--- remainer of each cycle.-wedge :: Time -> Pattern a -> Pattern a -> Pattern a-wedge t p p' = overlay (densityGap (1/t) p) (t `rotR` densityGap (1/(1-t)) 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@ has a similar form and behavior to `every`, but requires an-additional number. Applies the function to the pattern, when the-remainder of the current loop number divided by the first parameter,-is greater or equal than the second parameter.--For example the following makes every other block of four loops twice-as dense:--@-d1 $ whenmod 8 4 (density 2) (sound "bd sn kurt")-@--}-whenmod :: Int -> Int -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a-whenmod a b = Sound.Tidal.Pattern.when ((\t -> (t `mod` a) >= b ))--{- |-@-superimpose f p = stack [p, f p]-@--`superimpose` plays a modified version of a pattern at the same time as the original pattern,-resulting in two patterns being played at the same time.--@-d1 $ superimpose (density 2) $ sound "bd sn [cp ht] hh"-d1 $ superimpose ((# speed "2") . (0.125 <~)) $ sound "bd sn cp hh"-@---}-superimpose :: (Pattern a -> Pattern a) -> Pattern a -> Pattern a-superimpose f p = stack [p, f p]---- | @splitQueries p@ wraps `p` to ensure that it does not get--- queries that span arcs. For example `arc p (0.5, 1.5)` would be--- turned into two queries, `(0.5,1)` and `(1,1.5)`, and the results--- combined. Being able to assume queries don't span cycles often--- makes transformations easier to specify.-splitQueries :: Pattern a -> Pattern a-splitQueries p = Pattern $ \a -> concatMap (arc p) $ arcCycles a--{- | @trunc@ truncates a pattern so that only a fraction of the pattern is played.-The following example plays only the first quarter of the pattern:--@-d1 $ trunc 0.25 $ sound "bd sn*2 cp hh*4 arpy bd*2 cp bd*2"-@--}-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@ is similar to `trunc` but the truncated part of the pattern loops until the end of the cycle--@-d1 $ linger 0.25 $ sound "bd sn*2 cp hh*4 arpy bd*2 cp bd*2"-@--}-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--{- | Plays a portion of a pattern, specified by a beginning and end arc of time.-The new resulting pattern is played over the time period of the original pattern:--@-d1 $ zoom (0.25, 0.75) $ sound "bd*2 hh*3 [sn bd]*2 drum"-@--In the pattern above, `zoom` is used with an arc from 25% to 75%. It is equivalent to this pattern:--@-d1 $ sound "hh*3 [sn bd]*2"-@--}-zoom :: Arc -> Pattern a -> Pattern a-zoom (s,e) p = splitQueries $ withResultArc (mapCycle ((/d) . (subtract s))) $ withQueryArc (mapCycle ((+s) . (*d))) p-     where d = e-s--compress :: Arc -> Pattern a -> Pattern a-compress (s,e) p | s >= e = silence-                 | otherwise = s `rotR` densityGap (1/(e-s)) p--sliceArc :: Arc -> Pattern a -> Pattern a-sliceArc a@(s,e) p | s >= e = silence-                   | otherwise = compress a $ zoom a p--{- |-Use `within` to apply a function to only a part of a pattern. For example, to-apply `density 2` to only the first half of a pattern:--@-d1 $ within (0, 0.5) (density 2) $ sound "bd*2 sn lt mt hh hh hh hh"-@--Or, to apply `(# speed "0.5") to only the last quarter of a pattern:--@-d1 $ within (0.75, 1) (# speed "0.5") $ sound "bd*2 sn lt mt hh hh hh hh"-@--}-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-                         ]--{- |-For many cases, @within'@ will function exactly as within.  -The difference between the two occurs when applying functions that change the timing of notes such as 'fast' or '<~'. -within first applies the function to all notes in the cycle, then keeps the results in the specified interval, and then combines it with the old cycle (an "apply split combine" paradigm). -within' first keeps notes in the specified interval, then applies the function to these notes, and then combines it with the old cycle (a "split apply combine" paradigm).---For example, whereas using the standard version of within--@-d1 $ within (0, 0.25) (fast 2) $ sound "bd hh cp sd"-@--sounds like:--@-d1 $ sound "[bd hh] hh cp sd"-@--using this alternative version, within'--@-d1 $ within' (0, 0.25) (fast 2) $ sound "bd hh cp sd"-@--sounds like: --@-d1 $ sound "[bd bd] hh cp sd"-@---}--within' :: Arc -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a-within' (s,e) f p = stack [playWhen (\t -> cyclePos t >= s && cyclePos t < e) $ compress (s,e) $ f $ zoom (s,e) $ p, -                           playWhen (\t -> not $ cyclePos t >= s && cyclePos t < e) $ p -                          ]---revArc :: Arc -> Pattern a -> Pattern a-revArc a = within a rev--{- | You can use the @e@ function to apply a Euclidean algorithm over a-complex pattern, although the structure of that pattern will be lost:--@-d1 $ e 3 8 $ sound "bd*2 [sn cp]"-@--In the above, three sounds are picked from the pattern on the right according-to the structure given by the `e 3 8`. It ends up picking two `bd` sounds, a-`cp` and missing the `sn` entirely.--These types of sequences use "Bjorklund's algorithm", which wasn't made for-music but for an application in nuclear physics, which is exciting. More-exciting still is that it is very similar in structure to the one of the first-known algorithms written in Euclid's book of elements in 300 BC. You can read-more about this in the paper-[The Euclidean Algorithm Generates Traditional Musical Rhythms](http://cgm.cs.mcgill.ca/~godfried/publications/banff.pdf)-by Toussaint. Some examples from this paper are included below,-including rotation in some cases.--@-- (2,5) : A thirteenth century Persian rhythm called Khafif-e-ramal.-- (3,4) : The archetypal pattern of the Cumbia from Colombia, as well as a Calypso rhythm from Trinidad.-- (3,5,2) : Another thirteenth century Persian rhythm by the name of Khafif-e-ramal, as well as a Rumanian folk-dance rhythm.-- (3,7) : A Ruchenitza rhythm used in a Bulgarian folk-dance.-- (3,8) : The Cuban tresillo pattern.-- (4,7) : Another Ruchenitza Bulgarian folk-dance rhythm.-- (4,9) : The Aksak rhythm of Turkey.-- (4,11) : The metric pattern used by Frank Zappa in his piece titled Outside Now.-- (5,6) : Yields the York-Samai pattern, a popular Arab rhythm.-- (5,7) : The Nawakhat pattern, another popular Arab rhythm.-- (5,8) : The Cuban cinquillo pattern.-- (5,9) : A popular Arab rhythm called Agsag-Samai.-- (5,11) : The metric pattern used by Moussorgsky in Pictures at an Exhibition.-- (5,12) : The Venda clapping pattern of a South African children’s song.-- (5,16) : The Bossa-Nova rhythm necklace of Brazil.-- (7,8) : A typical rhythm played on the Bendir (frame drum).-- (7,12) : A common West African bell pattern.-- (7,16,14) : A Samba rhythm necklace from Brazil.-- (9,16) : A rhythm necklace used in the Central African Republic.-- (11,24,14) : A rhythm necklace of the Aka Pygmies of Central Africa.-- (13,24,5) : Another rhythm necklace of the Aka Pygmies of the upper Sangha.-@--}-e :: Pattern Int -> Pattern Int -> Pattern a -> Pattern a-e = temporalParam2 _e--_e :: Int -> Int -> Pattern a -> Pattern a-_e n k p = (flip const) <$> (filterValues (== True) $ listToPat $ bjorklund (n,k)) <*> p--e' :: Pattern Int -> Pattern Int -> Pattern a -> Pattern a-e' = temporalParam2 _e'--_e' :: Int -> Int -> Pattern a -> Pattern a-_e' n k p = fastcat $ map (\x -> if x then p else silence) (bjorklund (n,k))---distrib :: [Pattern Int] -> Pattern a -> Pattern a-distrib steps p = do steps' <- sequence steps-                     _distrib steps' p--_distrib :: [Int] -> Pattern a -> Pattern a-_distrib xs p = boolsToPat (foldr (distrib') (replicate (last xs) True) (reverse $ layers xs)) p-  where-    distrib' :: [Bool] -> [Bool] -> [Bool]-    distrib' [] _ = []-    distrib' (_:a) [] = False:(distrib' a [])-    distrib' (True:a) (x:b) = x:(distrib' a b)-    distrib' (False:a) (b) = False:(distrib' a b)-    layers = map bjorklund . (zip<*>tail)-    boolsToPat p p' = (flip const) <$> (filterValues (== True) $ listToPat $ p) <*> p'--{- | `einv` fills in the blanks left by `e`- -- @e 3 8 "x"@ -> @"x ~ ~ x ~ ~ x ~"@-- @einv 3 8 "x"@ -> @"~ x x ~ x x ~ x"@--}-einv :: Pattern Int -> Pattern Int -> Pattern a -> Pattern a-einv = temporalParam2 _einv--_einv :: Int -> Int -> Pattern a -> Pattern a-_einv n k p = (flip const) <$> (filterValues (== False) $ listToPat $ bjorklund (n,k)) <*> p--{- | `efull n k pa pb` stacks @e n k pa@ with @einv n k pb@ -}-efull :: Pattern Int -> Pattern Int -> Pattern a -> Pattern a -> Pattern a-efull n k pa pb = stack [ e n k pa, einv n k pb ]--index :: Real b => b -> Pattern b -> Pattern c -> Pattern c-index sz indexpat pat = spread' (zoom' $ toRational sz) (toRational . (*(1-sz)) <$> indexpat) pat-  where zoom' sz start = zoom (start, start+sz)---- | @prrw f rot (blen, vlen) beatPattern valuePattern@: pattern rotate/replace.-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 rot (blen, vlen) beatPattern valuePattern@: pattern rotate/replace.-prr :: Int -> (Time, Time) -> Pattern String -> Pattern b -> Pattern b-prr = prrw $ flip const--{-|-@preplace (blen, plen) beats values@ combines the timing of @beats@ with the values-of @values@. Other ways of saying this are:-* sequential convolution-* @values@ quantized to @beats@.--Examples:--@-d1 $ sound $ preplace (1,1) "x [~ x] x x" "bd sn"-d1 $ sound $ preplace (1,1) "x(3,8)" "bd sn"-d1 $ sound $ "x(3,8)" <~> "bd sn"-d1 $ sound "[jvbass jvbass:5]*3" |+| (shape $ "1 1 1 1 1" <~> "0.2 0.9")-@--It is assumed the pattern fits into a single cycle. This works well with-pattern literals, but not always with patterns defined elsewhere. In those cases-use @preplace@ and provide desired pattern lengths:-@-let p = slow 2 $ "x x x"--d1 $ sound $ preplace (2,1) p "bd sn"-@--}-preplace :: (Time, Time) -> Pattern String -> Pattern b -> Pattern b-preplace = preplaceWith $ flip const---- | @prep@ is an alias for preplace.-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 len rot p@ rotates pattern @p@ by @rot@ beats to the left.--- @len@: length of the pattern, in cycles.--- Example: @d1 $ every 4 (protate 2 (-1)) $ slow 2 $ sound "bd hh hh hh"@-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--{-| The @<<~@ operator rotates a unit pattern to the left, similar to @<~@,-but by events rather than linear time. The timing of the pattern remains constant:--@-d1 $ (1 <<~) $ sound "bd ~ sn hh"--- will become-d1 $ sound "sn ~ hh bd"-@ -}--(<<~) :: Int -> Pattern a -> Pattern a-(<<~) = protate 1---- | @~>>@ is like @<<~@ but for shifting to the right.-(~>>) :: Int -> Pattern a -> Pattern a-(~>>) = (<<~) . (0-)---- | @pequal cycles p1 p2@: quickly test if @p1@ and @p2@ are the same.-pequal :: Ord a => Time -> Pattern a -> Pattern a -> Bool-pequal cycles p1 p2 = (sort $ arc p1 (0, cycles)) == (sort $ arc p2 (0, cycles))---- | @discretise n p@: 'samples' the pattern @p@ at a rate of @n@--- events per cycle. Useful for turning a continuous pattern into a--- discrete one.-discretise :: Time -> Pattern a -> Pattern a-discretise = _discretise--discretise' :: Pattern Time -> Pattern a -> Pattern a-discretise' n p = (density n $ atom (id)) <*> p--_discretise :: Time -> Pattern a -> Pattern a-_discretise n p = (_density n $ atom (id)) <*> p---- | @randcat ps@: does a @slowcat@ on the list of patterns @ps@ but--- randomises the order in which they are played.-randcat :: [Pattern a] -> Pattern a-randcat ps = spread' (rotL) (_discretise 1 $ ((%1) . fromIntegral) <$> (irand (length ps) :: Pattern Int)) (slowcat ps)---- @fromNote p@: converts a pattern of human-readable pitch names--- into pitch numbers. For example, @"cs2"@ will be parsed as C Sharp--- in the 2nd octave with the result of @11@, and @"b-3"@ as--- @-25@. Pitches can be decorated using:------    * s = Sharp, a half-step above (@"gs-1"@)---    * f = Flat, a half-step below (@"gf-1"@)---    * n = Natural, no decoration (@"g-1" and "gn-1"@ are equivalent)---    * ss = Double sharp, a whole step above (@"gss-1"@)---    * ff = Double flat, a whole step below (@"gff-1"@)------ Note that TidalCycles now assumes that middle C is represented by--- the value 0, rather than the previous value of 60. This function--- is similar to previously available functions @tom@ and @toMIDI@,--- but the default octave is now 0 rather than 5.-{---definition moved to Parse.hs ..--toMIDI :: Pattern String -> Pattern Int-toMIDI p = fromJust <$> (filterValues (isJust) (noteLookup <$> p))-  where-    noteLookup :: String -> Maybe Int-    noteLookup [] = Nothing-    noteLookup s | not (last s `elem` ['0' .. '9']) = noteLookup (s ++ "0")-                 | not (isLetter (s !! 1)) = noteLookup((head s):'n':(tail s))-                 | otherwise = parse s-    parse x = (\a b c -> a+b+c) <$> pc x <*> sym x <*> Just(12*digitToInt (last x))-    pc x = lookup (head x) [('c',0),('d',2),('e',4),('f',5),('g',7),('a',9),('b',11)]-    sym x = lookup (init (tail x)) [("s",1),("f",-1),("n",0),("ss",2),("ff",-2)]--}---- @tom p@: Alias for @toMIDI@.--- tom = toMIDI---{- | The `fit` function takes a pattern of integer numbers, which are used to select values from the given list. What makes this a bit strange is that only a given number of values are selected each cycle. For example:--@-d1 $ sound (fit 3 ["bd", "sn", "arpy", "arpy:1", "casio"] "0 [~ 1] 2 1")-@--The above fits three samples into the pattern, i.e. for the first cycle this will be `"bd"`, `"sn"` and `"arpy"`, giving the result `"bd [~ sn] arpy sn"` (note that we start counting at zero, so that `0` picks the first value). The following cycle the *next* three values in the list will be picked, i.e. `"arpy:1"`, `"casio"` and `"bd"`, giving the pattern `"arpy:1 [~ casio] bd casio"` (note that the list wraps round here).---}-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 (n-1) (total-x)) [1 .. (total-(n-1))]---- | @struct a b@: structures pattern @b@ in terms of @a@.-struct :: Pattern String -> Pattern a -> Pattern a-struct ps pv = (flip const) <$> ps <*> pv----- | @substruct a b@: similar to @struct@, but each event in pattern @a@ gets replaced with pattern @b@, compressed to fit the timespan of the event.-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 .. (n-1)]-     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' (_:[]) = []-             pairUp' (a:_:[]) = [(a,1)]-             pairUp' (a:b:xs) = (a,b):(pairUp' (b:xs))--randStruct :: Int -> Pattern Int-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 n p@: repeats pattern @p@, @n@ times per cycle. So--- similar to @fast@, but with random durations. The repetitions will--- be continguous (touching, but not overlapping) and the durations--- will add up to a single cycle. @n@ can be supplied as a pattern of--- integers.-stripe :: Pattern Int -> Pattern a -> Pattern a-stripe = temporalParam _stripe--_stripe :: Int -> Pattern a -> Pattern a-_stripe = substruct' . randStruct---- | @slowstripe n p@: The same as @stripe@, but the result is also--- @n@ times slower, so that the mean average duration of the stripes--- is exactly one cycle, and every @n@th stripe starts on a cycle--- boundary (in indian classical terms, the @sam@).-slowstripe :: Pattern Int -> Pattern a -> Pattern a-slowstripe n = slow (toRational <$> n) . stripe n---- Lindenmayer patterns, these go well with the step sequencer--- general rule parser (strings map to strings)-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---- specific parser for step sequencer (chars map to string)--- ruleset in form "a:b,b:ab"-parseLMRule' :: String -> [(Char, String)]-parseLMRule' str = map fixer $ parseLMRule str-  where fixer (c,r) = (head c, r)--{- | returns the `n`th iteration of a [Lindenmayer System](https://en.wikipedia.org/wiki/L-system) with given start sequence.--for example:--@-lindenmayer 1 "a:b,b:ab" "ab" -> "bab"-@--}-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--{- | @lindenmayerI@ converts the resulting string into a a list of integers-with @fromIntegral@ applied (so they can be used seamlessly where floats or-rationals are required) -}-lindenmayerI n r s = fmap fromIntegral $ fmap digitToInt $ lindenmayer n r s---- support for fit'-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--{-|-Removes events from second pattern that don't start during an event from first.--Consider this, kind of messy rhythm without any rests.--@-d1 $ sound (slowcat ["sn*8", "[cp*4 bd*4, hc*5]"]) # n (run 8)-@--If we apply a mask to it--@-d1 $ s (mask ("1 1 1 ~ 1 1 ~ 1" :: Pattern Bool)-  (slowcat ["sn*8", "[cp*4 bd*4, bass*5]"] ))-  # n (run 8)-@--Due to the use of `slowcat` here, the same mask is first applied to `"sn*8"` and in the next cycle to `"[cp*4 bd*4, hc*5]".--You could achieve the same effect by adding rests within the `slowcat` patterns, but mask allows you to do this more easily. It kind of keeps the rhythmic structure and you can change the used samples independently, e.g.--@-d1 $ s (mask ("1 ~ 1 ~ 1 1 ~ 1" :: Pattern Bool)-  (slowcat ["can*8", "[cp*4 sn*4, jvbass*16]"] ))-  # n (run 8)-@--Detail: It is currently needed to explicitly _tell_ Tidal that the mask itself is a `Pattern Bool` as it cannot infer this by itself, otherwise it will complain as it does not know how to interpret your input.--}-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'` is a generalization of `fit`, where the list is instead constructed by using another integer pattern to slice up a given pattern.  The first argument is the number of cycles of that latter pattern to use when slicing.  It's easier to understand this with a few examples:--@-d1 $ sound (fit' 1 2 "0 1" "1 0" "bd sn")-@--So what does this do?  The first `1` just tells it to slice up a single cycle of `"bd sn"`. The `2` tells it to select two values each cycle, just like the first argument to `fit`.  The next pattern `"0 1"` is the "from" pattern which tells it how to slice, which in this case means `"0"` maps to `"bd"`, and `"1"` maps to `"sn"`.  The next pattern `"1 0"` is the "to" pattern, which tells it how to rearrange those slices.  So the final result is the pattern `"sn bd"`.--A more useful example might be something like--@-d1 $ fit' 1 4 (run 4) "[0 3*2 2 1 0 3*2 2 [1*8 ~]]/2" $ chop 4 $ (sound "breaks152" # unit "c")-@--which uses `chop` to break a single sample into individual pieces, which `fit'` then puts into a list (using the `run 4` pattern) and reassembles according to the complicated integer pattern.---}-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..n-1]]-        p' = density cyc $ p-        from' = density cyc $ from--{-| @chunk n f p@ treats the given pattern @p@ as having @n@ chunks, and applies the function @f@ to one of those sections per cycle, running from left to right.--@-d1 $ chunk 4 (density 4) $ sound "cp sn arpy [mt lt]"-@--}-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..n-1]]--{--chunk n f p = do i <- _slow (toRational n) $ run (fromIntegral n)-                 within (i%(fromIntegral n),(i+)1%(fromIntegral n)) f p--}---- deprecated (renamed to chunk)-runWith :: Integer -> (Pattern b -> Pattern b) -> Pattern b -> Pattern b-runWith = chunk--{-| @chunk'@ works much the same as `chunk`, but runs from right to left.--}-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---- deprecated (renamed to chunk')-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@ lets you turn a pattern of notes within a scale (expressed as a-list) to note numbers.  For example `toScale [0, 4, 7] "0 1 2 3"` will turn-into the pattern `"0 4 7 12"`.  It assumes your scale fits within an octave;-to change this use `toScale' size`.  Example:-`toScale' 24 [0,4,7,10,14,17] (run 8)` turns into `"0 4 7 10 14 17 24 28"`--}-toScale' :: Num a => Int -> [a] -> Pattern Int -> Pattern a-toScale' o s = fmap noteInScale-  where octave x = x `div` length s-        noteInScale x = (s !!! x) + (fromIntegral $ o * octave x)--toScale :: Num a => [a] -> Pattern Int -> Pattern a-toScale = toScale' 12--{- | `swingBy x n` divides a cycle into `n` slices and delays the notes in-the second half of each slice by `x` fraction of a slice . @swing@ is an alias-for `swingBy (1%3)`--}-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` is like `choose` but only picks a new item from the list-once each cycle -}-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 n p` evenly divides one cycle of the pattern `p` into `n` parts,-and returns a random permutation of the parts each cycle.  For example,-`shuffle 3 "a b c"` could return `"a b c"`, `"a c b"`, `"b a c"`, `"b c a"`,-`"c a b"`, or `"c b a"`.  But it will **never** return `"a a a"`, because that-is not a permutation of the parts.--}-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..n-1]-        n' :: Time-        n' = fromIntegral n--{- | `scramble n p` is like `shuffle` but randomly selects from the parts-of `p` instead of making permutations.-For example, `scramble 3 "a b c"` will randomly select 3 parts from-`"a"` `"b"` and `"c"`, possibly repeating a single part.--}-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 -> [(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/(e-s)) (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 xs p@ repeats a pattern @p@ at different durations given by the list of time values in @xs@ -}-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@ takes a Pattern of lists and pulls the list elements as--- separate Events-flatpat :: Pattern [a] -> Pattern a-flatpat p = Pattern $ \a -> (concatMap (\(b,b',xs) -> map (\x -> (b,b',x)) xs) $ arc p a)---- | @layer@ takes a Pattern of lists and pulls the list elements as--- separate Events-layer :: [a -> Pattern b] -> a -> Pattern b-layer fs p = stack $ map ($ p) fs---- | @breakUp@ finds events that share the same timespan, and spreads them out during that timespan, so for example @breakUp "[bd,sn]"@ gets turned into @"bd sn"@-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 = mapMaybe (\(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@ 'fills in' gaps in one pattern with events from another. For example @fill "bd" "cp ~ cp"@ would result in the equivalent of `"~ bd ~"`. This only finds gaps in a resulting pattern, in other words @"[bd ~, sn]"@ doesn't contain any gaps (because @sn@ covers it all), and @"bd ~ ~ sn"@ only contains a single gap that bridges two steps.-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 (s-tolerance, e+tolerance) $ arc p (s-tolerance, 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')] -- inside-                          | s > s' && s < e' = [(s',s)] -- cut off right-                          | e > s' && e < e' = [(e,e')] -- cut off left-                          | s <= s' && e >= e' = [] -- swallow-                          | otherwise = [(s',e')] -- miss-    arcToEvent a = (a,a,"x")-    removeTolerance (s,e) es = concatMap (expand) $ mapSnds' f es-      where f a = concatMap (remove' (e,e+tolerance)) $ remove' (s-tolerance,s) a-            expand (a,xs,c) = map (\x -> (a,x,c)) xs-    tolerance = 0.01---- Repeats each event @n@ times within its arc-ply :: Pattern Int -> Pattern a -> Pattern a-ply = temporalParam _ply--_ply :: Int -> Pattern a -> Pattern a-_ply n p = breakUp $ stack (replicate n p)---- Uses the first (binary) pattern to switch between the following two--- patterns. -sew :: Pattern Bool -> Pattern a -> Pattern a -> Pattern a-sew stitch p1 p2 = overlay (const <$> p1 <*> a) (const <$> p2 <*> b)-  where a = filterValues (id) stitch-        b = filterValues (not . id) stitch
− Sound/Tidal/Scales.hs
@@ -1,224 +0,0 @@-module Sound.Tidal.Scales where--import Data.Maybe--import Sound.Tidal.Pattern-import Sound.Tidal.Utils-import Control.Applicative---- five notes scales-minPent :: Num a => [a]-minPent = [0,3,5,7,10]-majPent :: Num a => [a]-majPent = [0,2,4,7,9]----  another mode of major pentatonic-ritusen :: Num a => [a]-ritusen = [0,2,5,7,9]---- another mode of major pentatonic-egyptian :: Num a => [a]-egyptian = [0,2,5,7,10]-----kumai :: Num a => [a]-kumai = [0,2,3,7,9]-hirajoshi :: Num a => [a]-hirajoshi = [0,2,3,7,8]-iwato :: Num a => [a]-iwato = [0,1,5,6,10]-chinese :: Num a => [a]-chinese = [0,4,6,7,11]-indian :: Num a => [a]-indian = [0,4,5,7,10]-pelog :: Num a => [a]-pelog = [0,1,3,7,8]-----prometheus :: Num a => [a]-prometheus = [0,2,4,6,11]-scriabin :: Num a => [a]-scriabin = [0,1,4,7,9]---- han chinese pentatonic scales-gong :: Num a => [a]-gong = [0,2,4,7,9]-shang :: Num a => [a]-shang = [0,2,5,7,10]-jiao :: Num a => [a]-jiao = [0,3,5,8,10]-zhi :: Num a => [a]-zhi = [0,2,5,7,9]-yu :: Num a => [a]-yu = [0,3,5,7,10]---- 6 note scales-whole :: Num a => [a]-whole = [0,2,4,6,8,10]-augmented :: Num a => [a]-augmented = [0,3,4,7,8,11]-augmented2 :: Num a => [a]-augmented2 = [0,1,4,5,8,9]---- hexatonic modes with no tritone-hexMajor7 :: Num a => [a]-hexMajor7 = [0,2,4,7,9,11]-hexDorian :: Num a => [a]-hexDorian = [0,2,3,5,7,10]-hexPhrygian :: Num a => [a]-hexPhrygian = [0,1,3,5,8,10]-hexSus :: Num a => [a]-hexSus = [0,2,5,7,9,10]-hexMajor6 :: Num a => [a]-hexMajor6 = [0,2,4,5,7,9]-hexAeolian :: Num a => [a]-hexAeolian = [0,3,5,7,8,10]---- 7 note scales-major :: Num a => [a]-major = [0,2,4,5,7,9,11]-ionian :: Num a => [a]-ionian = [0,2,4,5,7,9,11]-dorian :: Num a => [a]-dorian = [0,2,3,5,7,9,10]-phrygian :: Num a => [a]-phrygian = [0,1,3,5,7,8,10]-lydian :: Num a => [a]-lydian = [0,2,4,6,7,9,11]-mixolydian :: Num a => [a]-mixolydian = [0,2,4,5,7,9,10]-aeolian :: Num a => [a]-aeolian = [0,2,3,5,7,8,10]-minor :: Num a => [a]-minor = [0,2,3,5,7,8,10]-locrian :: Num a => [a]-locrian = [0,1,3,5,6,8,10]-harmonicMinor :: Num a => [a]-harmonicMinor = [0,2,3,5,7,8,11]-harmonicMajor :: Num a => [a]-harmonicMajor = [0,2,4,5,7,8,11]-melodicMinor :: Num a => [a]-melodicMinor = [0,2,3,5,7,9,11]-melodicMinorDesc :: Num a => [a]-melodicMinorDesc = [0,2,3,5,7,8,10]-melodicMajor :: Num a => [a]-melodicMajor = [0,2,4,5,7,8,10]-bartok :: Num a => [a]-bartok = [0,2,4,5,7,8,10]-hindu :: Num a => [a]-hindu = [0,2,4,5,7,8,10]---- raga modes-todi :: Num a => [a]-todi = [0,1,3,6,7,8,11]-purvi :: Num a => [a]-purvi = [0,1,4,6,7,8,11]-marva :: Num a => [a]-marva = [0,1,4,6,7,9,11]-bhairav :: Num a => [a]-bhairav = [0,1,4,5,7,8,11]-ahirbhairav :: Num a => [a]-ahirbhairav = [0,1,4,5,7,9,10]-----superLocrian :: Num a => [a]-superLocrian = [0,1,3,4,6,8,10]-romanianMinor :: Num a => [a]-romanianMinor = [0,2,3,6,7,9,10]-hungarianMinor :: Num a => [a]-hungarianMinor = [0,2,3,6,7,8,11]-neapolitanMinor :: Num a => [a]-neapolitanMinor = [0,1,3,5,7,8,11]-enigmatic :: Num a => [a]-enigmatic = [0,1,4,6,8,10,11]-spanish :: Num a => [a]-spanish = [0,1,4,5,7,8,10]---- modes of whole tones with added note ->-leadingWhole :: Num a => [a]-leadingWhole = [0,2,4,6,8,10,11]-lydianMinor :: Num a => [a]-lydianMinor = [0,2,4,6,7,8,10]-neapolitanMajor :: Num a => [a]-neapolitanMajor = [0,1,3,5,7,9,11]-locrianMajor :: Num a => [a]-locrianMajor = [0,2,4,5,6,8,10]---- 8 note scales-diminished :: Num a => [a]-diminished = [0,1,3,4,6,7,9,10]-diminished2 :: Num a => [a]-diminished2 = [0,2,3,5,6,8,9,11]---- 12 note scales-chromatic :: Num a => [a]-chromatic = [0,1,2,3,4,5,6,7,8,9,10,11]--scaleP :: Num a => Pattern String -> Pattern Int -> Pattern a-scaleP sp p = (\n scaleName -> noteInScale (fromMaybe [0] $ lookup scaleName scaleTable) n) <$> p <*> sp-  where octave s x = x `div` length s-        noteInScale s x = (s !!! x) + (fromIntegral $ 12 * octave s x)--scaleTable :: Num a => [(String, [a])]-scaleTable = [("minPent", minPent),-              ("majPent", majPent),-              ("ritusen", ritusen),-              ("egyptian", egyptian),-              ("kumai", kumai),-              ("hirajoshi", hirajoshi),-              ("iwato", iwato),-              ("chinese", chinese),-              ("indian", indian),-              ("pelog", pelog),-              ("prometheus", prometheus),-              ("scriabin", scriabin),-              ("gong", gong),-              ("shang", shang),-              ("jiao", jiao),-              ("zhi", zhi),-              ("yu", yu),-              ("whole", whole),-              ("augmented", augmented),-              ("augmented2", augmented2),-              ("hexMajor7", hexMajor7),-              ("hexDorian", hexDorian),-              ("hexPhrygian", hexPhrygian),-              ("hexSus", hexSus),-              ("hexMajor6", hexMajor6),-              ("hexAeolian", hexAeolian),-              ("major", major),-              ("ionian", ionian),-              ("dorian", dorian),-              ("phrygian", phrygian),-              ("lydian", lydian),-              ("mixolydian", mixolydian),-              ("aeolian", aeolian),-              ("minor", minor),-              ("locrian", locrian),-              ("harmonicMinor", harmonicMinor),-              ("harmonicMajor", harmonicMajor),-              ("melodicMinor", melodicMinor),-              ("melodicMinorDesc", melodicMinorDesc),-              ("melodicMajor", melodicMajor),-              ("bartok", bartok),-              ("hindu", hindu),-              ("todi", todi),-              ("purvi", purvi),-              ("marva", marva),-              ("bhairav", bhairav),-              ("ahirbhairav", ahirbhairav),-              ("superLocrian", superLocrian),-              ("romanianMinor", romanianMinor),-              ("hungarianMinor", hungarianMinor),-              ("neapolitanMinor", neapolitanMinor),-              ("enigmatic", enigmatic),-              ("spanish", spanish),-              ("leadingWhole", leadingWhole),-              ("lydianMinor", lydianMinor),-              ("neapolitanMajor", neapolitanMajor),-              ("locrianMajor", locrianMajor),-              ("diminished", diminished),-              ("diminished2", diminished2),-              ("chromatic", chromatic)-             ]-
− Sound/Tidal/Sieve.hs
@@ -1,100 +0,0 @@-{-# LANGUAGE FlexibleInstances #-}-{-# OPTIONS_GHC -Wall -fno-warn-orphans -fno-warn-name-shadowing #-}--module Sound.Tidal.Sieve where--import Control.Applicative-import Data.Monoid--import Sound.Tidal.Parse-import Sound.Tidal.Pattern-import Sound.Tidal.Strategies-import Sound.Tidal.Time---- The 'Sieve' datatype, which represents a Xenakis sieve.--- (for an overview, see www.mitpressjournals.org/doi/pdf/10.1162/0148926054094396)--data Sieve a = Sieve {sieveAt :: Int -> a}--instance Functor Sieve where-    fmap f s = Sieve $ \i -> f (sieveAt s i)--instance Applicative Sieve where-    pure b = Sieve $ \i -> b-    a <*> b = Sieve $ \i -> (sieveAt a i) (sieveAt b i)---- | The basic notation for and constructor of a boolean 'Sieve' is @m\@\@n@,--- which represents all integers whose modulo with @m@ is equal to @n@-infixl 9 @@ -(@@) :: Int -> Int -> Sieve Bool -m @@ i = Sieve $ \j -> (j `mod` m) == i---- If Haskell's logic operators had been defined on a type class, we could--- declare Sieve to be an instance, but they haven't so here we are---- | @not'@ gives the complement of a sieve-not' :: Applicative f => f Bool -> f Bool-not' = fmap not---- | @#||#@ gives the union (logical OR) of two sieves-infixl 2 #||#-(#||#) :: Applicative f => f Bool -> f Bool -> f Bool-(#||#) = liftA2 (||)---- | @#&&#@ gives the intersection (logical AND) of two sieves-infixl 3 #&&#-(#&&#) :: Applicative f => f Bool -> f Bool -> f Bool-(#&&#) = liftA2 (&&)---- | `#^^#` gives the exclusive disjunction (logical XOR) of two sieves-infixl 2 #^^#-(#^^#) :: Applicative f => f Bool -> f Bool -> f Bool-(#^^#) x y = (x #&&# not' y) #||# (y #&&# not' x)---- | @sieveToList n@ returns a list of the values of the sieve for each--- nonnegative integer less than @n@ --- For example: @sieveToList 10 $ 3\@\@1@ returns --- `[False, True, False, False, True, False, False, True, False, False]`-sieveToList :: Int -> Sieve a -> [a]-sieveToList n s = map (sieveAt s) [0..n-1]---- | @sieveToString n@ represents the sieve as a character string, where--- @-@ represents False and @x@ represents True-sieveToString :: Int -> Sieve Bool -> [Char]-sieveToString n s = map b2c $ sieveToList n s-    where b2c b | b == True = 'x' | otherwise = '-'---- | @sieveToInts n@ returns a list of nonnegative integers less than @n@--- where the sieve is True-sieveToInts :: Int -> Sieve Bool -> [Int]-sieveToInts n s = map snd $ filter fst $ zip (sieveToList n s) [0..n-1]---- | @sieveToPat n@ returns a pattern where the cycle is divided into @n@--- beats, and there is an event whenever the matching beat number is in the--- sieve--- For example: @sieveToPat 8 $ 3\@\@1@ returns @"~ x ~ ~ x ~ ~ x"@-sieveToPat :: Int -> Sieve Bool -> Pattern String-sieveToPat n s = p $ concatMap b2s $ sieveToList n s where-  b2s b | b == True = "x " | otherwise = "~ "---- | @stepSieve n str@ works like 'sieveToPat' but uses @str@ in the pattern--- instead of @x@-stepSieve :: Int -> String -> Sieve Bool -> Pattern String-stepSieve n str sieve = step str (sieveToString n sieve)---- | @slowstepSieve t@ is shorthand for applying @slow t@ to the result of--- `stepSieve`-slowstepSieve :: Pattern Time -> Int -> String -> Sieve Bool -> Pattern String-slowstepSieve t n str sieve = slow t $ stepSieve n str sieve---- | @scaleSieve n@ uses 'sieveToInts' to turn a sieve into a list of--- integers, and then uses that with the @toScale@ function to--- turn a pattern of numbers into a pattern of notes in the scale.--- For example: @scaleSieve 8 (3\@\@1) "0 1 2 1"@ first converts the sieve--- to the scale @[1, 4, 7]@ and then uses that with @toScale@ to return the--- pattern @"1 4 7 4"@-scaleSieve :: Int -> Sieve Bool -> Pattern Int -> Pattern Int-scaleSieve n sieve = toScale (sieveToInts n sieve)--instance Show (Sieve Bool) where -    show = sieveToString 32
− Sound/Tidal/Simple.hs
@@ -1,39 +0,0 @@-module Sound.Tidal.Simple where--import Sound.Tidal.Context--crunch :: ParamPattern -> ParamPattern-crunch = (# crush 3)--scratch :: ParamPattern -> ParamPattern-scratch = rev . chop 32--louder :: ParamPattern -> ParamPattern-louder = (|*| gain 1.2)--quieter :: ParamPattern -> ParamPattern-quieter = (|*| gain 0.8)--mute :: ParamPattern -> ParamPattern-mute = const silence--jump :: ParamPattern -> ParamPattern-jump = (0.25 <~)--left :: ParamPattern -> ParamPattern-left = (# pan 0)--right :: ParamPattern -> ParamPattern-right = (# pan 1)--higher :: ParamPattern -> ParamPattern-higher = (|*| speed 1.5)--lower :: ParamPattern -> ParamPattern-lower = (|*| speed 0.75)--faster :: ParamPattern -> ParamPattern-faster = hurry 2--slower :: ParamPattern -> ParamPattern-slower = hurry 0.5
− Sound/Tidal/Strategies.hs
@@ -1,421 +0,0 @@-{-# OPTIONS_GHC -XNoMonomorphismRestriction -XOverloadedStrings #-}--module Sound.Tidal.Strategies where--import Data.Ratio-import Control.Applicative-import qualified Data.Map as Map-import qualified Data.Char as Char-import Data.Fixed-import Data.Maybe--import Sound.Tidal.Dirt-import Sound.Tidal.Pattern-import Sound.Tidal.Stream-import Sound.Tidal.Time-import Sound.Tidal.Utils-import Sound.Tidal.Params-import Sound.Tidal.Parse-import Data.List (transpose)--stutter :: Integral i => i -> Time -> Pattern a -> Pattern a-stutter n t p = stack $ map (\i -> (t * (fromIntegral i)) `rotR` p) [0 .. (n-1)]--echo, triple, quad, double :: Time -> Pattern a -> Pattern a-echo   = stutter 2-triple = stutter 3-quad   = stutter 4-double = echo--{- | The `jux` function creates strange stereo effects, by applying a-function to a pattern, but only in the right-hand channel. For-example, the following reverses the pattern on the righthand side:--@-d1 $ slow 32 $ jux (rev) $ striate' 32 (1/16) $ sound "bev"-@--When passing pattern transforms to functions like [jux](#jux) and [every](#every),-it's possible to chain multiple transforms together with `.`, for-example this both reverses and halves the playback speed of the-pattern in the righthand channel:--@-d1 $ slow 32 $ jux ((# speed "0.5") . rev) $ striate' 32 (1/16) $ sound "bev"-@--}-jux = juxBy 1-juxcut f p = stack [p     # pan (pure 0) # cut (pure (-1)),-                    f $ p # pan (pure 1) # cut (pure (-2))-                   ]--juxcut' fs p = stack $ map (\n -> ((fs !! n) p |+| cut (pure $ 1-n)) # pan (pure $ fromIntegral n / fromIntegral l)) [0 .. l-1]-  where l = length fs--{- | In addition to `jux`, `jux'` allows using a list of pattern transform. resulting patterns from each transformation will be spread via pan from left to right.--For example:--@-d1 $ jux' [iter 4, chop 16, id, rev, palindrome] $ sound "bd sn"-@--will put `iter 4` of the pattern to the far left and `palindrome` to the far right. In the center the original pattern will play and mid left mid right the chopped and the reversed version will appear.--One could also write:--@-d1 $ stack [-    iter 4 $ sound "bd sn" # pan "0",-    chop 16 $ sound "bd sn" # pan "0.25",-    sound "bd sn" # pan "0.5",-    rev $ sound "bd sn" # pan "0.75",-    palindrome $ sound "bd sn" # pan "1",-    ]-@---}-jux' fs p = stack $ map (\n -> ((fs !! n) p) |+| pan (pure $ fromIntegral n / fromIntegral l)) [0 .. l-1]-  where l = length fs---- | Multichannel variant of `jux`, _not sure what it does_-jux4 f p = stack [p # pan (pure (5/8)), f $ p # pan (pure (1/8))]--{- |-With `jux`, the original and effected versions of the pattern are-panned hard left and right (i.e., panned at 0 and 1). This can be a-bit much, especially when listening on headphones. The variant `juxBy`-has an additional parameter, which brings the channel closer to the-centre. For example:--@-d1 $ juxBy 0.5 (density 2) $ sound "bd sn:1"-@--In the above, the two versions of the pattern would be panned at 0.25-and 0.75, rather than 0 and 1.--}-juxBy n f p = stack [p |+| pan 0.5 |-| pan (n/2), f $ p |+| pan 0.5 |+| pan (n/2)]--{- | Smash is a combination of `spread` and `striate` - it cuts the samples-into the given number of bits, and then cuts between playing the loop-at different speeds according to the values in the list.--So this:--@-d1 $ smash 3 [2,3,4] $ sound "ho ho:2 ho:3 hc"-@--Is a bit like this:--@-d1 $ spread (slow) [2,3,4] $ striate 3 $ sound "ho ho:2 ho:3 hc"-@--This is quite dancehall:--@-d1 $ (spread' slow "1%4 2 1 3" $ spread (striate) [2,3,4,1] $ sound-"sn:2 sid:3 cp sid:4")-  # speed "[1 2 1 1]/2"-@--}-smash n xs p = slowcat $ map (\n -> slow n p') xs-  where p' = striate n p--{- | an altenative form to `smash` is `smash'` which will use `chop` instead of `striate`.--}-smash' n xs p = slowcat $ map (\n -> slow n p') xs-  where p' = _chop n p---- samples "jvbass [~ latibro] [jvbass [latibro jvbass]]" ((1%2) `rotL` slow 6 "[1 6 8 7 3]")--samples :: Applicative f => f String -> f Int -> f String-samples p p' = pick <$> p <*> p'--samples' :: Applicative f => f String -> f Int -> f String-samples' p p' = (flip pick) <$> p' <*> p--{--scrumple :: Time -> Pattern a -> Pattern a -> Pattern a-scrumple o p p' = p'' -- overlay p (o `rotR` p'')-  where p'' = Pattern $ \a -> concatMap-                              (\((s,d), vs) -> map (\x -> ((s,d),-                                                           snd x-                                                          )-                                                   )-                                                   (arc p' (s,s))-                              ) (arc p a)--}----rev :: Pattern a -> Pattern a---rev p = Pattern $ \a -> concatMap---                        (\a' -> mapFsts mirrorArc $---                                (arc p (mirrorArc a')))---                        (arcCycles a)----spreadf :: [Pattern a -> Pattern b] -> Pattern a -> Pattern b-spreadf ts p = spread ($)--{- | `spin` will "spin" a layer up a pattern the given number of times, with each successive layer offset in time by an additional `1/n` of a cycle, and panned by an additional `1/n`. The result is a pattern that seems to spin around. This function works best on multichannel systems.--@-d1 $ slow 3 $ spin 4 $ sound "drum*3 tabla:4 [arpy:2 ~ arpy] [can:2 can:3]"-@--}-spin :: Pattern Int -> ParamPattern -> ParamPattern-spin = temporalParam _spin--_spin :: Int -> ParamPattern -> ParamPattern-_spin copies p =-  stack $ map (\n -> let offset = toInteger n % toInteger copies in-                     offset `rotL` p-                     # pan (pure $ fromRational offset)-              )-          [0 .. (copies - 1)]--{-stripe :: Arc -> Pattern a -> Pattern a-stripe (stripeS, stripeE) p = slow t $ Pattern $ \a -> concatMap f $ arcCycles a-  where f a = mapFsts (stretch . stripe') $ arc p (stripe' a)-        trunc' (s,e) = (min s ((sam s) + t), min e ((sam s) + t))-        stretch (s,e) = (sam s + ((s - sam s) / t), sam s + ((e - sam s) / t))--}--sawwave4, sinewave4, rand4 :: Pattern Double-sawwave4 = ((*4) <$> sawwave1)-sinewave4 = ((*4) <$> sinewave1)-rand4 = ((*4) <$> rand)--stackwith p ps | null ps = silence-               | otherwise = stack $ map (\(i, p') -> p' # (((fromIntegral i) % l) `rotL` p)) (zip [0 ..] ps)-  where l = fromIntegral $ length ps--{--cross f p p' = Pattern $ \t -> concat [filter flt $ arc p t,-                                       filter (not . flt) $ arc p' t-                                      ]-]  where flt = f . cyclePos . fst . fst--}--{- | `scale` will take a pattern which goes from 0 to 1 (like `sine1`), and scale it to a different range - between the first and second arguments. In the below example, `scale 1 1.5` shifts the range of `sine1` from 0 - 1 to 1 - 1.5.--@-d1 $ jux (iter 4) $ sound "arpy arpy:2*2"-  |+| speed (slow 4 $ scale 1 1.5 sine1)-@--}-scale :: (Functor f, Num b) => b -> b -> f b -> f b-scale from to p = ((+ from) . (* (to-from))) <$> p--{- | `scalex` is an exponential version of `scale`, good for using with-frequencies.  Do *not* use negative numbers or zero as arguments! -}-scalex :: (Functor f, Floating b) => b -> b -> f b -> f b-scalex from to p = exp <$> scale (log from) (log to) p--{- | `chop` granualizes every sample in place as it is played, turning a pattern of samples into a pattern of sample parts. Use an integer value to specify how many granules each sample is chopped into:--@-d1 $ chop 16 $ sound "arpy arp feel*4 arpy*4"-@--Different values of `chop` can yield very different results, depending-on the samples used:---@-d1 $ chop 16 $ sound (samples "arpy*8" (run 16))-d1 $ chop 32 $ sound (samples "arpy*8" (run 16))-d1 $ chop 256 $ sound "bd*4 [sn cp] [hh future]*2 [cp feel]"-@--}--chop :: Pattern Int -> ParamPattern -> ParamPattern-chop = temporalParam _chop--_chop :: Int -> ParamPattern -> ParamPattern-_chop n p = Pattern $ \queryA -> concatMap (f queryA) $ arcCycles queryA-  where f queryA a = concatMap (chopEvent queryA) (arc p a)-        chopEvent (queryS, queryE) (a,_a',v) = map (newEvent v) $ filter (\(_, (s,e)) -> not $ or [e < queryS, s >= queryE]) (enumerate $ chopArc a n)-        newEvent :: ParamMap -> (Int, Arc) -> Event ParamMap-        newEvent v (i, a) = (a,a,Map.insert (param dirt "end") (VF ((fromIntegral $ i+1)/(fromIntegral n))) $ Map.insert (param dirt "begin") (VF ((fromIntegral i)/(fromIntegral n))) v)---{- | `gap` is similar to `chop` in that it granualizes every sample in place as it is played,-but every other grain is silent. Use an integer value to specify how many granules-each sample is chopped into:--@-d1 $ gap 8 $ sound "jvbass"-d1 $ gap 16 $ sound "[jvbass drum:4]"-@-}--gap :: Pattern Int -> ParamPattern -> ParamPattern-gap = temporalParam _gap--_gap :: Int -> ParamPattern -> ParamPattern-_gap n p = Pattern $ \queryA -> concatMap (f queryA) $ arcCycles queryA-     where f queryA a = concatMap (chopEvent queryA) (arc p a)-           chopEvent (queryS, queryE) (a,_a',v) = map (newEvent v) $ filter (\(_, (s,e)) -> not $ or [e < queryS, s >= queryE]) (enumerate $ everyOther $ chopArc a n)-           newEvent :: ParamMap -> (Int, Arc) -> Event ParamMap-           newEvent v (i, a) = (a,a,Map.insert (param dirt "end") (VF ((fromIntegral $ i+1)/(fromIntegral n))) $ Map.insert (param dirt "begin") (VF ((fromIntegral i)/(fromIntegral n))) v)-           everyOther (x:_:xs) = x:everyOther xs-           everyOther xs = xs--chopArc :: Arc -> Int -> [Arc]-chopArc (s, e) n = map (\i -> ((s + (e-s)*(fromIntegral i/fromIntegral n)), s + (e-s)*((fromIntegral $ i+1)/fromIntegral n))) [0 .. n-1]-{--normEv :: Event a -> Event a -> Event a-normEv ev@(_, (s,e), _) ev'@(_, (s',e'), _)-       | not on && not off = [] -- shouldn't happen-       | on && off = splitEv ev'-       | not on && s' > sam s = []-       | not off && e' < nextSam s = [(fst' ev, mapSnd' (mapSnd (min $ nextSam s)) ev, thd' ev)]-  where on = onsetIn (sam s, nextSam s) ev-        off = offsetIn (sam s, nextSam s) ev-        eplitEv--}---mapCycleEvents :: Pattern a -> ([Event a] -> [Event a]) -> Pattern a---mapCycleEvents p f = splitQueries $ Pattern $ \(s,e) -> filter (\ev -> isJust $ subArc (s,e) (eventArc ev)) $ f $ arc p (sam s, nextSam s)----off :: Time -> Pattern a -> Pattern a---off t p = mapCycleEvents p (mapArcs (mapSnd wrappedPlus . mapFst wrappedPlus))---               where wrapAtCycle f t' = sam t' + cyclePos (f t')---                     wrappedPlus = wrapAtCycle (+t)---en :: [(Int, Int)] -> Pattern String -> Pattern String-en ns p = stack $ map (\(i, (k, n)) -> _e k n (samples p (pure i))) $ enumerate ns--{- |-`weave` applies a function smoothly over an array of different patterns. It uses an `OscPattern` to-apply the function at different levels to each pattern, creating a weaving effect.--@-d1 $ weave 3 (shape $ sine1) [sound "bd [sn drum:2*2] bd*2 [sn drum:1]", sound "arpy*8 ~"]-@--}-weave :: Rational -> ParamPattern -> [ParamPattern] -> ParamPattern-weave t p ps = weave' t p (map (\x -> (x #)) ps)---{- | `weave'` is similar in that it blends functions at the same time at different amounts over a pattern:--@-d1 $ weave' 3 (sound "bd [sn drum:2*2] bd*2 [sn drum:1]") [density 2, (# speed "0.5"), chop 16]-@--}-weave' :: Rational -> Pattern a -> [Pattern a -> Pattern a] -> Pattern a-weave' t p fs | l == 0 = silence-              | otherwise = _slow t $ stack $ map (\(i, f) -> (fromIntegral i % l) `rotL` (_density t $ f (_slow t p))) (zip [0 ..] fs)-  where l = fromIntegral $ length fs--{- |-(A function that takes two OscPatterns, and blends them together into-a new OscPattern. An OscPattern is basically a pattern of messages to-a synthesiser.)--Shifts between the two given patterns, using distortion.--Example:--@-d1 $ interlace (sound  "bd sn kurt") (every 3 rev $ sound  "bd sn:2")-@--}-interlace :: ParamPattern -> ParamPattern -> ParamPattern-interlace a b = weave 16 (shape $ ((* 0.9) <$> sinewave1)) [a, b]---- | Step sequencing-step :: String -> String -> Pattern String-step s steps = fastcat $ map f steps-    where f c | c == 'x' = atom s-              | Char.isDigit c = atom $ s ++ ":" ++ [c]-              | otherwise = silence--steps :: [(String, String)] -> Pattern String-steps = stack . map (\(a,b) -> step a b)---- | like `step`, but allows you to specify an array of strings to use for 0,1,2...-step' :: [String] -> String -> Pattern String-step' ss steps = fastcat $ map f steps-    where f c | c == 'x' = atom $ head ss-              | Char.isDigit c = atom $ ss!!(Char.digitToInt c)-              | otherwise = silence--off :: Pattern Time -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a-off tp f p = unwrap $ (\tv -> _off tv f p) <$> tp--_off :: Time -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a-_off t f p = superimpose (f . (t `rotR`)) p--offadd :: Num a => Pattern Time -> Pattern a -> Pattern a -> Pattern a-offadd tp pn p = off tp (+pn) p--{- | `up` does a poor man's pitchshift by semitones via `speed`.--You can easily produce melodies from a single sample with up:--@-d1 # up "0 5 4 12" # sound "arpy"-@--This will play the _arpy_ sample four times a cycle in the original pitch, pitched by 5 semitones, by 4 and then by an octave.--}-up :: Pattern Double -> ParamPattern-up = speed . ((1.059466**) <$>)--ghost'' a f p = superimpose (((a*2.5) `rotR`) . f) $ superimpose (((a*1.5) `rotR`) . f) $ p-ghost' a p = ghost'' 0.125 ((|*| gain (pure 0.7)) . (|=| end (pure 0.2)) . (|*| speed (pure 1.25))) p-ghost p = ghost' 0.125 p---slice :: Pattern Int -> Pattern Int -> ParamPattern -> ParamPattern-slice pi pn p = begin b # end e # p-  where b = (\i n -> (div' i n)) <$> pi <*> pn-        e = (\i n -> (div' i n) + (div' 1 n)) <$> pi <*> pn-        div' a b = fromIntegral (a `mod` b) / fromIntegral b--_slice :: Int -> Int -> ParamPattern -> ParamPattern-_slice i n p =-      p-      # begin (pure $ fromIntegral i / fromIntegral n)-      # end (pure $ fromIntegral (i+1) / fromIntegral n)--randslice :: Int -> ParamPattern -> ParamPattern-randslice n p = unwrap $ (\i -> _slice i n p) <$> irand n--{- |-`loopAt` makes a sample fit the given number of cycles. Internally, it-works by setting the `unit` parameter to "c", changing the playback-speed of the sample with the `speed` parameter, and setting setting-the `density` of the pattern to match.--@-d1 $ loopAt 4 $ sound "breaks125"-d1 $ juxBy 0.6 (|*| speed "2") $ slowspread (loopAt) [4,6,2,3] $ chop 12 $ sound "fm:14"-@--}-loopAt :: Pattern Time -> ParamPattern -> ParamPattern-loopAt n p = slow n p |*| speed (fromRational <$> (1/n)) # unit (pure "c")---{- |-   tabby - A more literal weaving than the `weave` function, give number-   of 'threads' per cycle and two patterns, and this function will weave them-   together using a plain (aka 'tabby') weave, with a simple over/under structure- -}-tabby n p p' = stack [maskedWarp n p,-                      maskedWeft n p'-                     ]-  where-    weft n = concatMap (\x -> [[0..n-1],(reverse [0..n-1])]) [0 .. (n `div` 2) - 1]-    warp = transpose . weft-    thread xs n p = _slow (n%1) $ fastcat $ map (\i -> zoom (i%n,(i+1)%n) p) (concat xs)-    weftP n p = thread (weft n) n p-    warpP n p = thread (warp n) n p-    maskedWeft n p = Sound.Tidal.Pattern.mask (every 2 rev $ _density ((n)%2) "~ 1" :: Pattern Int) $ weftP n p-    maskedWarp n p = mask (every 2 rev $ _density ((n)%2) "1 ~" :: Pattern Int) $ warpP n p--hurry :: Pattern Rational -> ParamPattern -> ParamPattern-hurry x = (|*| speed (fromRational <$> x)) . fast x
− Sound/Tidal/Stream.hs
@@ -1,329 +0,0 @@-{-# LANGUAGE OverloadedStrings, FlexibleInstances, RankNTypes, NoMonomorphismRestriction, DeriveDataTypeable #-}--module Sound.Tidal.Stream where--import Data.Maybe-import Control.Applicative-import Control.Concurrent-import Control.Concurrent.MVar-import Control.Exception as E-import Data.Time (getCurrentTime)-import Data.Time.Clock.POSIX (utcTimeToPOSIXSeconds)-import Data.Ratio-import Data.Typeable-import Sound.Tidal.Pattern-import qualified Sound.Tidal.Parse as P-import Sound.Tidal.Tempo (Tempo, logicalTime, clockedTick,cps)-import Sound.Tidal.Utils-import qualified Sound.Tidal.Time as T-import System.IO (stderr, hPutStrLn)--import qualified Data.Map.Strict as Map--type ToMessageFunc = Shape -> Tempo -> Int -> (Double, Double, ParamMap) -> Maybe (IO ())--data Backend a = Backend {-  toMessage :: ToMessageFunc,-  flush :: Shape -> Tempo -> Int -> IO ()-  }--data Param = S {name :: String, sDefault :: Maybe String}-           | F {name :: String, fDefault :: Maybe Double}-           | I {name :: String, iDefault :: Maybe Int}-  deriving Typeable--instance Eq Param where-  a == b = name a == name b--instance Ord Param where-  compare a b = compare (name a) (name b)-instance Show Param where-  show p = name p---data Shape = Shape {params :: [Param],-                    latency :: Double,-                    cpsStamp :: Bool}---data Value = VS { svalue :: String } | VF { fvalue :: Double } | VI { ivalue :: Int }-           deriving (Eq,Ord,Typeable)--instance Show Value where-  show (VS s) = s-  show (VF f) = show f-  show (VI i) = show i--class ParamType a where-  fromV :: Value -> Maybe a-  toV :: a -> Value--instance ParamType String where-  fromV (VS s) = Just s-  fromV _ = Nothing-  toV s = VS s--instance ParamType Double where-  fromV (VF f) = Just f-  fromV _ = Nothing-  toV f = VF f--instance ParamType Int where-  fromV (VI i) = Just i-  fromV _ = Nothing-  toV i = VI i--type ParamMap = Map.Map Param Value--type ParamPattern = Pattern ParamMap--ticksPerCycle = 8--defaultValue :: Param -> Value-defaultValue (S _ (Just x)) = VS x-defaultValue (I _ (Just x)) = VI x-defaultValue (F _ (Just x)) = VF x--hasDefault :: Param -> Bool-hasDefault (S _ Nothing) = False-hasDefault (I _ Nothing) = False-hasDefault (F _ Nothing) = False-hasDefault _ = True--defaulted :: Shape -> [Param]-defaulted = filter hasDefault . params--defaultMap :: Shape -> ParamMap-defaultMap s-  = Map.fromList $ map (\x -> (x, defaultValue x)) (defaulted s)--required :: Shape -> [Param]-required = filter (not . hasDefault) . params--hasRequired :: Shape -> ParamMap -> Bool-hasRequired s m = isSubset (required s) (Map.keys m)--isSubset :: (Eq a) => [a] -> [a] -> Bool-isSubset xs ys = all (\x -> elem x ys) xs---doAt t action = do _ <- forkIO $ do-                               now <- getCurrentTime-                               let nowf = realToFrac $ utcTimeToPOSIXSeconds now-                               threadDelay $ floor $ (t - nowf) * 1000000-                               action-                   return ()--logicalOnset' change tick o offset = logicalNow + (logicalPeriod * o) + offset-  where-    tpc = fromIntegral ticksPerCycle-    cycleD = ((fromIntegral tick) / tpc) :: Double-    logicalNow = logicalTime change cycleD-    logicalPeriod = (logicalTime change (cycleD + (1/tpc))) - logicalNow---applyShape' :: Shape -> ParamMap -> Maybe ParamMap-applyShape' s m | hasRequired s m = Just $ Map.union m (defaultMap s)-                | otherwise = Nothing--start :: Backend a -> Shape -> IO (MVar (ParamPattern))-start backend shape-  = do patternM <- newMVar silence-       let ot = (onTick backend shape patternM) :: Tempo -> Int -> IO ()-       forkIO $ clockedTick ticksPerCycle ot-       return patternM---- variant of start where history of patterns is available-state :: Backend a -> Shape -> IO (MVar (ParamPattern, [ParamPattern]))-state backend shape-  = do patternsM <- newMVar (silence, [])-       let ot = (onTick' backend shape patternsM) :: Tempo -> Int -> IO ()-       forkIO $ clockedTick ticksPerCycle ot-       return patternsM--stream :: Backend a -> Shape -> IO (ParamPattern -> IO ())-stream backend shape-  = do patternM <- start backend shape-       return $ \p -> do swapMVar patternM p-                         return ()--streamcallback :: (ParamPattern -> IO ()) -> Backend a -> Shape -> IO (ParamPattern -> IO ())-streamcallback callback backend shape-  = do f <- stream backend shape-       let f' p = do callback p-                     f p-       return f'--onTick :: Backend a -> Shape -> MVar (ParamPattern) -> Tempo -> Int -> IO ()-onTick backend shape patternM change ticks-  = do p <- readMVar patternM-       let ticks' = (fromIntegral ticks) :: Integer-           a = ticks' % ticksPerCycle-           b = (ticks' + 1) % ticksPerCycle-           messages = mapMaybe-                      (toMessage backend shape change ticks)-                      (seqToRelOnsetDeltas (a, b) p)-       E.catch (sequence_ messages) (\msg -> hPutStrLn stderr $ "failed " ++ show (msg :: E.SomeException))-       flush backend shape change ticks-       return ()---- Variant where mutable variable contains list as history of the patterns-onTick' :: Backend a -> Shape -> MVar (ParamPattern, [ParamPattern]) -> Tempo -> Int -> IO ()-onTick' backend shape patternsM change ticks-  = do ps <- readMVar patternsM-       let ticks' = (fromIntegral ticks) :: Integer-           toM = (toMessage backend)-           a = ticks' % ticksPerCycle-           b = (ticks' + 1) % ticksPerCycle-           messages = mapMaybe-                      (toM shape change ticks)-                      (seqToRelOnsetDeltas (a, b) $ fst ps)-       E.catch (sequence_ messages) (\msg -> putStrLn $ "oops " ++ show (msg :: E.SomeException))-       flush backend shape change ticks-       return ()--make :: (a -> Value) -> Shape -> String -> Pattern a -> ParamPattern-make toValue s nm p = fmap (\x -> Map.singleton nParam (defaultV x)) p-  where nParam = param s nm-        defaultV a = toValue a-        --defaultV Nothing = defaultValue nParam--make' :: ParamType a => (a -> Value) -> Param -> Pattern a -> ParamPattern-make' toValue par p = fmap (\x -> Map.singleton par (toValue x)) p--makeP :: ParamType a => Param -> Pattern a -> ParamPattern-makeP par p = coerce par $ fmap (\x -> Map.singleton par (toV x)) p--makeS = make VS--makeF :: Shape -> String -> Pattern Double -> ParamPattern-makeF = make VF--makeI :: Shape -> String -> Pattern Int -> ParamPattern-makeI = make VI--param :: Shape -> String -> Param-param shape n = head $ filter (\x -> name x == n) (params shape)--merge :: ParamPattern -> ParamPattern -> ParamPattern-merge x y = (flip Map.union) <$> x <*> y--infixl 1 |=|-(|=|) :: ParamPattern -> ParamPattern -> ParamPattern-(|=|) = merge--infixl 1 #-(#) = (|=|)--mergeWith op x y = (Map.unionWithKey op) <$> x <*> y--mergeWith-  :: (Ord k, Applicative f) =>-     (k -> a -> a -> a)-     -> f (Map.Map k a) -> f (Map.Map k a) -> f (Map.Map k a)--mergeNumWith intOp floatOp = mergeWith f-  where f (F _ _) (VF a) (VF b) = VF $ floatOp a b-        f (I _ _) (VI a) (VI b) = VI $ intOp a b-        f _ _ b = b--mergePlus = mergeWith f-  where f (F _ _) (VF a) (VF b) = VF $ a + b-        f (I _ _) (VI a) (VI b) = VI $ a + b-        f (S _ _) (VS a) (VS b) = VS $ a ++ b-        f _ _ b = b--infixl 1 |*|-(|*|) :: ParamPattern -> ParamPattern -> ParamPattern-(|*|) = mergeNumWith (*) (*)--infixl 1 |+|-(|+|) :: ParamPattern -> ParamPattern -> ParamPattern-(|+|) = mergePlus--infixl 1 |-|-(|-|) :: ParamPattern -> ParamPattern -> ParamPattern-(|-|) = mergeNumWith (-) (-)--infixl 1 |/|-(|/|) :: ParamPattern -> ParamPattern -> ParamPattern-(|/|) = mergeNumWith (div) (/)--{- | These are shorthand for merging lists of patterns with @#@, @|*|@, @|+|@,-or @|/|@.  Sometimes this saves a little typing and can improve readability-when passing things into other functions.  As an example, instead of writing-@-d1 $ sometimes ((|*| speed "2") . (|*| cutoff "2") . (|*| shape "1.5")) $ sound "arpy*4" # cutoff "350" # shape "0.3"-@-you can write-@-d1 $ sometimes (*** [speed "2", cutoff "2", shape "1.5"]) $ sound "arpy*4" ### [cutoff "350", shape "0.3"]-@--}-(###) = foldl (#)-(***) = foldl (|*|)-(+++) = foldl (|+|)-(///) = foldl (|/|)--setter :: MVar (a, [a]) -> a -> IO ()-setter ds p = do ps <- takeMVar ds-                 putMVar ds $ (p, p:snd ps)-                 return ()--{- | Copies values from one parameter to another. Used by @nToOrbit@ in @Sound.Tidal.Dirt@. -}--copyParam:: Param -> Param -> ParamPattern -> ParamPattern-copyParam fromParam toParam pat = f <$> pat-  where f m = maybe m (updateValue m) (Map.lookup fromParam m)-        updateValue m v = Map.union m (Map.fromList [(toParam,v)])--get :: ParamType a => Param -> ParamPattern -> Pattern a-get param p = filterJust $ fromV <$> (filterJust $ Map.lookup param <$> p)--getI :: Param -> ParamPattern -> Pattern Int-getI = get-getF :: Param -> ParamPattern -> Pattern Double-getF = get-getS :: Param -> ParamPattern -> Pattern String-getS = get--with :: (ParamType a) => Param -> (Pattern a -> Pattern a) -> ParamPattern -> ParamPattern-with param f p = p # (makeP param) ((\x -> f (get param x)) p)-withI :: Param -> (Pattern Int -> Pattern Int) -> ParamPattern -> ParamPattern-withI = with-withF :: Param -> (Pattern Double -> Pattern Double) -> ParamPattern -> ParamPattern-withF = with-withS :: Param -> (Pattern String -> Pattern String) -> ParamPattern -> ParamPattern-withS = with--follow :: (ParamType a, ParamType b) => Param -> Param -> (Pattern a -> Pattern b) -> ParamPattern -> ParamPattern-follow source dest f p = p # (makeP dest $ f (get source p))---- follow :: ParamType a => Param -> (Pattern a -> ParamPattern) -> ParamPattern -> ParamPattern--- follow source dest p = p # (dest $ get source p)--follow' :: ParamType a => Param -> Param -> (Pattern a -> Pattern a) -> ParamPattern -> ParamPattern-follow' source dest f p = p # (makeP dest $ f (get source p))--followI :: Param -> Param -> (Pattern Int -> Pattern Int) -> ParamPattern -> ParamPattern-followI = follow'-followF :: Param -> Param -> (Pattern Double -> Pattern Double) -> ParamPattern -> ParamPattern-followF = follow'-followS :: Param -> Param -> (Pattern String -> Pattern String) -> ParamPattern -> ParamPattern-followS = follow'---- with :: ParamType a => Param -> (Pattern a -> Pattern a) -> ParamPattern -> ParamPattern--- with source f p = p # (makeP source $ f (get source p))-coerce :: Param -> ParamPattern -> ParamPattern-coerce par@(S _ _) p = (Map.update f par) <$> p-  where f (VS s) = Just (VS s)-        f (VI i) = Just (VS $ show i)-        f (VF f) = Just (VS $ show f)-coerce par@(I _ _) p = (Map.update f par) <$> p-  where f (VS s) = Just (VI $ read s)-        f (VI i) = Just (VI i)-        f (VF f) = Just (VI $ floor f)-coerce par@(F _ _) p = (Map.update f par) <$> p-  where f (VS s) = Just (VF $ read s)-        f (VI i) = Just (VF $ fromIntegral i)-        f (VF f) = Just (VF f)
− Sound/Tidal/SuperCollider.hs
@@ -1,36 +0,0 @@-{-# LANGUAGE NoMonomorphismRestriction #-}--module Sound.Tidal.SuperCollider where--import Sound.Tidal.Stream-import Sound.Tidal.Pattern-import Sound.Tidal.Parse-import Sound.OSC.Datum-import Sound.Tidal.OscStream--supercollider :: [Param] -> Double -> Shape-supercollider ps l = Shape {-  params = ps,-  cpsStamp = False,-  latency = l-  }--scSlang :: String -> OscSlang-scSlang n = OscSlang {-  -- The OSC path-  path = "/s_new",-  preamble = [string n, int32 (-1), int32 1, int32 1],-  namedParams = True,-  timestamp = BundleStamp-  }--scBackend :: String -> IO (Backend a)-scBackend n = do-  s <- makeConnection "127.0.0.1" 57110 (scSlang n)-  return $ Backend s (\_ _ _ -> return ())--scStream :: String -> [Param] -> Double -> IO (ParamPattern -> IO (), Shape)-scStream n ps l = do let shape = (supercollider ps l)-                     backend <- scBackend n-                     sc <- stream backend shape-                     return (sc, shape)
− Sound/Tidal/Tempo.hs
@@ -1,341 +0,0 @@-{-# LANGUAGE ScopedTypeVariables #-}-module Sound.Tidal.Tempo where--import Data.Time (getCurrentTime, UTCTime, NominalDiffTime, diffUTCTime, addUTCTime)-import Data.Time.Clock.POSIX-import Control.Applicative ((<$>), (<*>))-import Control.Monad (forM_, forever, void)---import Control.Monad.IO.Class (liftIO)-import Control.Concurrent (forkIO, threadDelay)-import Control.Concurrent.MVar-import Control.Monad.Trans (liftIO)-import Data.Maybe (fromMaybe, maybe, isJust, fromJust)-import Data.Text (Text)-import qualified Data.Text as T-import qualified Data.Text.IO as T-import Data.Unique-import qualified Network.WebSockets as WS-import qualified Control.Exception as E-import Safe (readNote)-import System.Environment (lookupEnv)-import qualified System.IO.Error as Error-import GHC.Conc.Sync (ThreadId)-import Sound.OSC.Datum.Datem-import Sound.OSC.FD--import Sound.Tidal.Utils--data Tempo = Tempo {at :: UTCTime, beat :: Double, cps :: Double, paused :: Bool, clockLatency :: Double}--type ClientState = [TConnection]--data ServerMode = Master-                | Slave UDP--instance Show ServerMode where-  show Master = "Master"-  show _ = "Slave"--data TConnection = TConnection Unique WS.Connection--wsConn :: TConnection -> WS.Connection-wsConn (TConnection _ c) = c--instance Eq TConnection where-   TConnection a _ == TConnection b _ = a == b--instance Show Tempo where-  show x = show (at x) ++ "," ++ show (beat x) ++ "," ++ show (cps x) ++ "," ++ show (paused x) ++ "," ++ (show $ clockLatency x)--getLatency :: IO Double-getLatency =-   maybe 0.04 (readNote "latency parse") <$> lookupEnv "TIDAL_CLOCK_LATENCY"--getClockIp :: IO String-getClockIp = fromMaybe "127.0.0.1" <$> lookupEnv "TIDAL_TEMPO_IP"--getServerPort :: IO Int-getServerPort =-   maybe 9160 (readNote "port parse") <$> lookupEnv "TIDAL_TEMPO_PORT"--getMasterPort :: IO Int-getMasterPort =-   maybe 6042 (readNote "port parse") <$> lookupEnv "TIDAL_MASTER_PORT"--getSlavePort :: IO Int-getSlavePort =-   maybe 6043 (readNote "port parse") <$> lookupEnv "TIDAL_SLAVE_PORT"--readTempo :: String -> Tempo-readTempo x = Tempo (read a) (read b) (read c) (read d) (read e)-  where (a:b:c:d:e:_) = wordsBy (== ',') x---- given a Tempo and a cycle position (aka "a beat")--- returns the POSIX time of that cycle position (aka beat)-logicalTime :: Tempo -> Double -> Double-logicalTime t b = changeT + timeDelta-  where beatDelta = b - (beat t)-        timeDelta = beatDelta / (cps t)-        changeT = realToFrac $ utcTimeToPOSIXSeconds $ at t----- beatNow: accesses a clock and returns the time now in terms of--- beats relative to metrical grid of a given Tempo-beatNow :: Tempo -> IO (Double)-beatNow t = do now <- getCurrentTime-               let delta = realToFrac $ diffUTCTime now (at t)-               let beatDelta = cps t * delta-               return $ beat t + beatDelta---- getCurrentBeat: given current Tempo grid, gets the current beat-getCurrentBeat :: MVar Tempo -> IO Rational-getCurrentBeat t = (readMVar t) >>= (beatNow) >>= (return . toRational)--clientApp :: MVar Tempo -> MVar Double -> MVar Double -> WS.ClientApp ()-clientApp mTempo mCps mNudge conn = do-    liftIO $ forkIO $ sendCps conn mCps-    liftIO $ forkIO $ sendNudge conn mNudge-    forever loop-  where-    loop = do-        msg <- WS.receiveData conn-        let s = T.unpack msg-        let tempo = readTempo $ s-        old <- liftIO $ tryTakeMVar mTempo-        -- putStrLn $ "from: " ++ show old-        -- putStrLn $ "to: " ++ show tempo-        liftIO $ putMVar mTempo tempo--sendTempo :: [WS.Connection] -> Tempo -> IO ()-sendTempo conns t = mapM_ (\conn -> WS.sendTextData conn (T.pack $ show t)) conns--sendCps :: WS.Connection -> MVar Double -> IO ()-sendCps conn mCps = forever $ do cps <- takeMVar mCps-                                 let m = "cps " ++ (show cps)-                                 WS.sendTextData conn (T.pack m)--sendNudge :: WS.Connection -> MVar Double -> IO ()-sendNudge conn mNudge = forever $ do nudge <- takeMVar mNudge-                                     let m = "nudge " ++ (show nudge)-                                     WS.sendTextData conn (T.pack m)--connectClient :: Bool -> String -> MVar Tempo -> MVar Double -> MVar Double -> IO ()-connectClient secondTry ip mTempo mCps mNudge = do-  let errMsg = "Failed to connect to tidal server. Try specifying a " ++-               "different port (default is 9160) setting the " ++-               "environment variable TIDAL_TEMPO_PORT"-  serverPort <- getServerPort-  WS.runClient ip serverPort "/tempo" (clientApp mTempo mCps mNudge) `E.catch`-    \(_ :: E.SomeException) -> do-      case secondTry of-        True -> error errMsg-        _ -> do-          res <- E.try (void startServer)-          case res of-            Left (_ :: E.SomeException) -> error errMsg-            Right _ -> do-              threadDelay 500000-              connectClient True ip mTempo mCps mNudge--runClient :: IO ((MVar Tempo, MVar Double, MVar Double))-runClient =-  do clockip <- getClockIp-     mTempo <- newEmptyMVar-     mCps <- newEmptyMVar-     mNudge <- newEmptyMVar-     forkIO $ connectClient False clockip mTempo mCps mNudge-     return (mTempo, mCps, mNudge)--cpsUtils' :: IO ((Double -> IO (), (Double -> IO ()), IO Rational))-cpsUtils' = do (mTempo, mCps, mNudge) <- runClient-               let cpsSetter = putMVar mCps-                   nudger = putMVar mNudge-                   currentTime = do tempo <- readMVar mTempo-                                    now <- beatNow tempo-                                    return $ toRational now-               return (cpsSetter, nudger, currentTime)---- backward compatibility-cpsUtils = do (cpsSetter, _, currentTime) <- cpsUtils'-              return (cpsSetter, currentTime)---- Backwards compatibility-bpsUtils :: IO ((Double -> IO (), IO (Rational)))-bpsUtils = cpsUtils--cpsSetter :: IO (Double -> IO ())-cpsSetter = do (f, _) <- cpsUtils-               return f--clocked :: (Tempo -> Int -> IO ()) -> IO ()-clocked = clockedTick 1-                         -clockedTick :: Int -> (Tempo -> Int -> IO ()) -> IO ()-clockedTick tpb callback =-  do (mTempo, _, mCps) <- runClient-     t <- readMVar mTempo-     now <- getCurrentTime-     let delta = realToFrac $ diffUTCTime now (at t)-         beatDelta = cps t * delta-         nowBeat = beat t + beatDelta-         nextTick = ceiling (nowBeat * (fromIntegral tpb))-         -- next4 = nextBeat + (4 - (nextBeat `mod` 4))-     loop mTempo nextTick-  where loop mTempo tick =-          do tempo <- readMVar mTempo-             tick' <- doTick tempo tick-             loop mTempo tick'-        doTick tempo tick | paused tempo =-          do let pause = 0.01-             -- TODO - do this via blocking read on the mvar somehow-             -- rather than polling-             threadDelay $ floor (pause * 1000000)-             -- reset tick to 0 if cps is negative-             return $ if cps tempo < 0 then 0 else tick-                          | otherwise =-          do now <- getCurrentTime-             let tps = (fromIntegral tpb) * cps tempo-                 delta = realToFrac $ diffUTCTime now (at tempo)-                 actualTick = ((fromIntegral tpb) * beat tempo) + (tps * delta)-                 -- only wait by up to two ticks-                 tickDelta = min 2 $ (fromIntegral tick) - actualTick-                 delay = tickDelta / tps-             -- putStrLn $ "tick delta: " ++ show tickDelta-             --putStrLn ("Delay: " ++ show delay ++ "s Beat: " ++ show (beat tempo))-             threadDelay $ floor (delay * 1000000)-             callback tempo tick-             -- putStrLn $ "hmm diff: " ++ show (abs $ (floor actualTick) - tick)-             let newTick | (abs $ (floor actualTick) - tick) > 4 = floor actualTick-                         | otherwise = tick + 1-             return $ newTick--updateTempo :: Tempo -> Double -> IO (Tempo)-updateTempo t cps'-  | paused t == True && cps' > 0 =-    -- unpause-    do now <- getCurrentTime-       return $ t {at = addUTCTime (realToFrac $ clockLatency t) now, cps = cps', paused = False}-  | otherwise =-    do now <- getCurrentTime-       let delta = realToFrac $ diffUTCTime now (at t)-           beat' = (beat t) + ((cps t) * delta)-           beat'' = if cps' < 0 then 0 else beat'-       return $ t {at = now, beat = beat'', cps = cps', paused = (cps' <= 0)}--nudgeTempo :: Tempo -> Double -> Tempo-nudgeTempo t secs = t {at = addUTCTime (realToFrac secs) (at t)}--removeClient :: TConnection -> ClientState -> ClientState-removeClient client = filter (/= client)--broadcast :: Text -> ClientState -> IO ()-broadcast message clients = do-  -- T.putStrLn message-  forM_ clients $ \conn -> WS.sendTextData (wsConn conn) $ message--startServer :: IO (ThreadId)-startServer = do-  serverPort <- getServerPort-  start <- getCurrentTime-  l <- getLatency-  tempoState <- newMVar (Tempo start 0 1 False l)-  clientState <- newMVar []-  serverState <- newMVar Master-  --liftIO $ oscBridge clientState-  liftIO $ slave serverState clientState-  forkIO $ WS.runServer "0.0.0.0" serverPort $ serverApp tempoState serverState clientState--serverApp :: MVar Tempo -> MVar ServerMode -> MVar ClientState -> WS.ServerApp-serverApp tempoState serverState clientState pending = do-    conn <- TConnection <$> newUnique <*> WS.acceptRequest pending-    tempo <- liftIO $ readMVar tempoState-    liftIO $ WS.sendTextData (wsConn conn) $ T.pack $ show tempo-    clients <- liftIO $ readMVar clientState-    liftIO $ modifyMVar_ clientState $ return . (conn:)-    serverLoop conn tempoState serverState clientState--slave :: MVar ServerMode -> MVar ClientState -> IO ()-slave serverState clientState =-  do slavePort <- getSlavePort-     slaveSock <- udpServer "127.0.0.1" (fromIntegral slavePort)-     _ <- forkIO $ loop slaveSock-     return ()-  where loop slaveSock =-          do ms <- recvMessages slaveSock-             mapM_ (\m -> slaveAct (messageAddress m) serverState clientState m) ms-             loop slaveSock--slaveAct :: String -> MVar ServerMode -> MVar ClientState -> Message -> IO ()-slaveAct "/tempo" serverState clientState m-  | isJust t = do clients <- readMVar clientState-                  setSlave serverState-                  sendTempo (map wsConn clients) (fromJust t)-  | otherwise = return ()-  where t = do beat' <- datum_floating $ (messageDatum m) !! 2-               cps' <- datum_floating $ (messageDatum m) !! 3-               return $ Tempo {at = ut,-                               beat = beat',-                               cps = cps',-                               paused = False,-                               clockLatency = 0-                              }-        ut = addUTCTime (realToFrac $ dsec) ut_epoch-        sec = fromJust $ datum_int32 $ (messageDatum m) !! 0-        usec = fromJust $ datum_int32 $ (messageDatum m) !! 1-        dsec = ((fromIntegral sec) + ((fromIntegral usec) / 1000000)) :: Double--setSlave :: MVar ServerMode -> IO ()-setSlave serverState = do s <- takeMVar serverState-                          s' <- updateState s-                          putMVar serverState s'-                          return ()-     where updateState Master = do putStrLn "Slaving tempo.."-                                   masterPort <- getMasterPort-                                   sock <- openUDP "127.0.0.1" (fromIntegral masterPort)-                                   return (Slave sock)-           -- already slaving..-           updateState s = return s-                          -serverLoop :: TConnection -> MVar Tempo -> MVar ServerMode -> MVar ClientState -> IO ()-serverLoop conn tempoState serverState clientState = E.handle catchDisconnect $-  forever $ do-    msg <- WS.receiveData $ wsConn conn-    --liftIO $ updateTempo tempoState $ maybeRead $ T.unpack msg-    mode <- readMVar serverState-    serverAct (T.unpack msg) mode tempoState clientState-    -- -    --tempo <- liftIO $ readMVar tempoState-    -- liftIO $ readMVar clientState >>= broadcast (T.pack $ show tempo)-  where-    catchDisconnect e = case E.fromException e of-        Just WS.ConnectionClosed -> liftIO $ modifyMVar_ clientState $ \s -> do-            let s' = removeClient conn s-            return s'-        _ -> return ()--serverAct :: String -> ServerMode -> MVar Tempo -> MVar ClientState -> IO ()-serverAct ('c':'p':'s':' ':n) mode tempoState clientState = setCps (read n) mode tempoState clientState-serverAct ('n':'u':'d':'g':'e':' ':n) mode tempoState clientState = setNudge (read n) mode tempoState clientState-serverAct s _ _ _ = do putStrLn $ "tempo server received unknown message " ++ s-                       return ()--setCps :: Double -> ServerMode -> MVar Tempo -> MVar ClientState -> IO ()-setCps n Master tempoState clientState = do tempo <- takeMVar tempoState-                                            tempo' <- updateTempo tempo (n :: Double)-                                            clients <- readMVar clientState-                                            sendTempo (map wsConn clients) (tempo')-                                            putMVar tempoState tempo'-                                            return ()-                                            -setCps n (Slave sock) tempoState clientState = sendOSC sock $ Message "/cps" [Float (realToFrac n)]---setNudge :: Double -> ServerMode -> MVar Tempo -> MVar ClientState -> IO ()-setNudge n Master tempoState clientState = do tempo <- takeMVar tempoState-                                              let tempo' = nudgeTempo tempo n-                                              clients <- readMVar clientState-                                              sendTempo (map wsConn clients) (tempo')-                                              putMVar tempoState tempo'-                                              return ()-                                              -setNudge n (Slave sock) tempoState clientState = sendOSC sock $ Message "/nudge" [Float (realToFrac n)]
− Sound/Tidal/Time.hs
@@ -1,117 +0,0 @@-{-|-Module: Time-Description: Defines core data types and functions for handling tidal's concept of time in `Arc`s & `Event`s--}-module Sound.Tidal.Time where--import Sound.Tidal.Utils-import Data.Ratio---- | Time is represented by a rational number. Each natural number--- represents both the start of the next rhythmic cycle, and the end--- of the previous one. Rational numbers are used so that subdivisions--- of each cycle can be accurately represented.-type Time = Rational---- | @(s,e) :: Arc@ represents a time interval with a start and end value.--- @ { t : s <= t && t < e } @-type Arc = (Time, Time)---- | An Event is a value that occurs during the period given by the--- first @Arc@. The second one indicates the event's "domain of--- influence". These will often be the same, but many temporal--- transformations, such as rotation and scaling time, may result in--- arcs being split or truncated. In such cases, the first arc is--- preserved, but the second arc reflects the portion of the event--- which is relevant.-type Event a = (Arc, Arc, a)---- | The starting point of the current cycle. A cycle occurs from each--- natural number to the next, so this is equivalent to @floor@.-sam :: Time -> Time-sam = fromIntegral . floor---- | The end point of the current cycle (and starting point of the next cycle)-nextSam :: Time -> Time-nextSam = (1+) . sam----- | The position of a time value relative to the start of its cycle.-cyclePos :: Time -> Time-cyclePos t = t - sam t---- | @isIn a t@ is @True@ if @t@ is inside--- the arc represented by @a@.-isIn :: Arc -> Time -> Bool-isIn (s,e) t = t >= s && t < e---- | Splits the given @Arc@ into a list of @Arc@s, at cycle boundaries.-arcCycles :: Arc -> [Arc]-arcCycles (s,e) | s >= e = []-                | sam s == sam e = [(s,e)]-                | otherwise = (s, nextSam s) : (arcCycles (nextSam s, e))---- | Splits the given @Arc@ into a list of @Arc@s, at cycle boundaries, but wrapping the arcs within the same cycle.-arcCycles' :: Arc -> [Arc]-arcCycles' (s,e) | s >= e = []-                 | sam s == sam e = [(s,e)]-                 | otherwise = (s, nextSam s) : (arcCycles' ((nextSam s) - 1, e - 1))----- | @subArc i j@ is the arc that is the intersection of @i@ and @j@.-subArc :: Arc -> Arc -> Maybe Arc-subArc (s, e) (s',e') | s'' < e'' = Just (s'', e'')-                      | otherwise = Nothing-  where s'' = max s s'-        e'' = min e e'---- | Map the given function over both the start and end @Time@ values--- of the given @Arc@.-mapArc :: (Time -> Time) -> Arc -> Arc-mapArc f (s,e) = (f s, f e)---- | Similar to @mapArc@ but time is relative to the cycle (i.e. the--- sam of the start of the arc)-mapCycle :: (Time -> Time) -> Arc -> Arc-mapCycle f (s,e) = (sam' + (f $ s - sam'), sam' + (f $ e - sam'))-         where sam' = sam s---- | Returns the `mirror image' of an @Arc@ around the given point intime, used by @Sound.Tidal.Pattern.rev@.-mirrorArc :: Time -> Arc -> Arc-mirrorArc mid (s, e) = (mid - (e-mid), mid+(mid-s))---- | The start time of the given @Event@-eventStart :: Event a -> Time-eventStart = fst . snd'---- | The original onset of the given @Event@-eventOnset :: Event a -> Time-eventOnset = fst . fst'---- | The original offset of the given @Event@-eventOffset :: Event a -> Time-eventOffset = snd . fst'---- | The arc of the given @Event@-eventArc :: Event a -> Arc-eventArc = snd'---- | The midpoint of an @Arc@-midPoint :: Arc -> Time-midPoint (s,e) = s + ((e - s) / 2)---- | `True` if an `Event`'s first and second `Arc`'s start times match-hasOnset :: Event a -> Bool-hasOnset ((s,_), (s',_), _) = s == s'---- | `True` if an `Event`'s first and second `Arc`'s end times match-hasOffset :: Event a -> Bool-hasOffset ((_,e), (_,e'), _) = e == e'---- | `True` if an `Event`'s starts is within given `Arc`-onsetIn :: Arc -> Event a -> Bool-onsetIn a e = isIn a (eventOnset e)---- | `True` if an `Event`'s ends is within given `Arc`-offsetIn :: Arc -> Event a -> Bool-offsetIn a e = isIn a (eventOffset e)
− Sound/Tidal/Transition.hs
@@ -1,129 +0,0 @@-module Sound.Tidal.Transition where--import Sound.Tidal.Stream-import Sound.Tidal.Pattern-import Sound.Tidal.Time-import Sound.Tidal.Params-import Sound.Tidal.Utils--import Control.Concurrent.MVar-import Control.Applicative-import Data.Maybe--import qualified Data.Map.Strict as Map-import Data.Monoid--transition :: (IO Time) -> MVar (ParamPattern, [ParamPattern]) -> (Time -> [ParamPattern] -> ParamPattern) -> ParamPattern -> IO ()-transition getNow mv f p =-  do now <- getNow-     ps <- takeMVar mv-     let p' = f now (p:snd ps)-     -- don't put the transition in history, only-     -- the target pattern, or things get overcomplex-     -- (transitions of transitions)-     putMVar mv (p', (p:snd ps))-     return ()---- | Pans the last n versions of the pattern across the field-histpan :: Int -> Time -> [ParamPattern] -> ParamPattern-histpan _ _ [] = silence-histpan 0 _ _ = silence-histpan n _ ps = stack $ map (\(i,p) -> p # pan (atom $ (fromIntegral i) / (fromIntegral n'))) (enumerate ps')-  where ps' = take n ps-        n' = length ps' -- in case there's fewer patterns than requested--{-|-A generalization of `wash`. 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.--}-superwash :: (Pattern a -> Pattern a) -> (Pattern a -> Pattern a) -> Time -> Time -> Time -> Time -> [Pattern a] -> Pattern a-superwash _ _ _ _ _ _ [] = silence-superwash _ _ _ _ _ _ (p:[]) = p-superwash fout fin delay durin durout now (p:p':_) =-   stack [(playWhen (< (now + delay)) p'),-          (playWhen (between (now + delay) (now + delay + durin)) $ fout p'),-          (playWhen (between (now + delay + durin) (now + delay + durin + durout)) $ fin p),-          (playWhen (>= (now + delay + durin + durout)) $ p)-         ]- where-   between lo hi x = (x >= lo) && (x < hi)--{-|-Wash away the current pattern by applying a function to it over time, then switching over to the next.--@-d1 $ sound "feel ! feel:1 feel:2"--t1 (wash (chop 8) 4) $ sound "feel*4 [feel:2 sn:2]"-@--Note that `chop 8` is applied to `sound "feel ! feel:1 feel:2"` for 4 cycles and then the whole pattern is replaced by `sound "feel*4 [feel:2 sn:2]`--}-wash :: (Pattern a -> Pattern a) -> Time -> Time -> [Pattern a] -> Pattern a-wash _ _ _ [] = silence-wash _ _ _ (p:[]) = p-wash f t now (p:p':_) = overlay (playWhen (< (now + t)) $ f p') (playWhen (>= (now + t)) p)----- | Just stop for a bit before playing new pattern-wait :: Time -> Time -> [ParamPattern] -> ParamPattern-wait _ _ [] = silence-wait t now (p:_) = playWhen (>= (nextSam (now+t-1))) p--{- | Just as `wait`, `wait'` stops for a bit and then applies the given transition to the playing pattern--@-d1 $ sound "bd"--t1 (wait' (xfadeIn 8) 4) $ sound "hh*8"-@--}-wait' :: (Time -> [ParamPattern] -> ParamPattern) -> Time -> Time -> [ParamPattern] -> ParamPattern-wait' _ t _ [] = silence-wait' f t now ps@(p:_) = playWhen (>= (nextSam (now+t-1))) (f (now + t) ps)---{- |-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 -> [ParamPattern] -> ParamPattern-jump = jumpIn 0--{- | Sharp `jump` transition after the specified number of cycles have passed.--@-t1 (jumpIn 2) $ sound "kick(3,8)"-@--}-jumpIn :: Int -> Time -> [ParamPattern] -> ParamPattern-jumpIn n = superwash id id (fromIntegral n) 0 0--{- | Unlike `jumpIn` the variant `jumpIn'` will only transition at cycle boundary (e.g. when the cycle count is an integer).--}-jumpIn' :: Int -> Time -> [ParamPattern] -> ParamPattern-jumpIn' n now = superwash id id ((nextSam now) - now + (fromIntegral n)) 0 0 now---- | Sharp `jump` transition at next cycle boundary where cycle mod n == 0-jumpMod :: Int -> Time -> [ParamPattern] -> ParamPattern-jumpMod n now = jumpIn ((n-1) - ((floor now) `mod` n)) now---- | Degrade the new pattern over time until it ends in silence-mortal :: Time -> Time -> Time -> [ParamPattern] -> ParamPattern-mortal _ _ _ [] = silence-mortal lifespan release now (p:_) = overlay (playWhen (<(now+lifespan)) p) (playWhen (>= (now+lifespan)) (fadeOut' (now + lifespan) release p))--combineV :: (Value -> Value -> Value) -> ParamMap -> ParamMap -> ParamMap-combineV f a b = Map.mapWithKey pairUp a-  where pairUp k v | Map.notMember k b = v-                   | otherwise = f v (fromJust $ Map.lookup k b)--mixNums v (VF a) (VF b) = VF $ (a * v) + (b * (1-v))-mixNums v (VI a) (VI b) = VI $ floor $ (fromIntegral a * v) + (fromIntegral b * (1-v))-mixNums v _ b = b--interpolateIn :: Time -> Time -> [ParamPattern] -> ParamPattern-interpolateIn _ _ [] = silence-interpolateIn _ _ (p:[]) = p-interpolateIn t now (p:p':_) = do n <- now `rotR` (_slow t envL)-                                  combineV (mixNums n) <$> p <*> p'
− Sound/Tidal/Utils.hs
@@ -1,104 +0,0 @@-{-|-Module: Utils-Description: Helper functions not directly specific to Tidal--}-module Sound.Tidal.Utils where--import Data.Maybe (listToMaybe)--{- | enumerate a list of things-->>> enumerate ["foo","bar","baz"]-[(1,"foo"), (2,"bar"), (3,"baz")]--}-enumerate :: [a] -> [(Int, a)]-enumerate = zip [0..]---- | apply @f@ to the first element of a tuple-mapFst :: (a -> b) -> (a, c) -> (b, c)-mapFst f (x,y) = (f x,y)---- | apply function to the first value of each tuple in given list-mapFsts :: (a -> b) -> [(a, c)] -> [(b, c)]-mapFsts = map . mapFst---- | apply @f@ to the second element of a tuple-mapSnd :: (a -> b) -> (c, a) -> (c, b)-mapSnd f (x,y) = (x,f y)---- | apply function to the second value of each tuple in given list-mapSnds :: (a -> b) -> [(c, a)] -> [(c, b)]-mapSnds = fmap . mapSnd---{- | split given list of @a@ by given single a, e.g.-->>> wordsBy (== ':') "bd:3"-["bd", "3"]--}-wordsBy :: (a -> Bool) -> [a] -> [[a]]-wordsBy p s = case dropWhile p s of-   []      -> []-   s':rest -> (s':w) : wordsBy p (drop 1 s'')-          where (w, s'') = break p rest--maybeRead :: String -> Maybe Double-maybeRead = fmap fst . listToMaybe . reads---- | shorthand for first element of triple-fst' (a, _, _) = a--- | shorthand for second element of triple-snd' (_, b, _) = b--- | shorthand for third element of triple-thd' (_, _, c) = c---- | apply @f@ to the first element of a triple-mapFst' :: (a -> x) -> (a, b, c) -> (x, b, c)-mapFst' f (x,y,z) = (f x,y,z)---- | apply @f@ to the second element of a triple-mapSnd' :: (b -> x) -> (a, b, c) -> (a, x, c)-mapSnd' f (x,y,z) = (x,f y,z)---- | apply @f@ to the third element of a triple-mapThd' :: (c -> x) -> (a, b, c) -> (a, b, x)-mapThd' f (x,y,z) = (x,y,f z)---- | apply function to the second value of each triple in given list-mapFsts' :: (a -> x) -> [(a, b, c)] -> [(x, b, c)]-mapFsts' = fmap . mapFst'---- | apply function to the second value of each triple in given list-mapSnds' :: (b -> x) -> [(a, b, c)] -> [(a, x, c)]-mapSnds' = fmap . mapSnd'---- | apply function to the third value of each triple in given list-mapThds' :: (c -> x) -> [(a, b, c)] -> [(a, b, x)]-mapThds' = fmap . mapThd'---- | map @f@ over a given list of arcs-mapArcs :: (a -> a) -> [(a, a, x)] -> [(a, a, x)]-mapArcs f = (mapFsts' f) . (mapSnds' f)--{- | combines two lists by interleaving them-->>> mergelists [1,2,3] [9,8,7]-[1,9,2,8,3,7]--}-mergelists :: [a] -> [a] -> [a]-mergelists xs     []     = xs-mergelists []     ys     = ys-mergelists (x:xs) (y:ys) = x : y : mergelists xs ys--{- | like `!!` selects @n@th element from xs, but wraps over at the end of @xs@-->>> map ((!!!) [1,3,5]) [0,1,2,3,4,5]-[1,3,5,1,3,5]--}-(!!!) :: [a] -> Int -> a-(!!!) xs n = xs !! (n `mod` length xs)--accumulate :: Num t => [t] -> [t]-accumulate = accumulate' 0-  where accumulate' _ [] = []-        accumulate' n (a:xs) = (n+a):(accumulate' (n+a) xs)
− Sound/Tidal/Version.hs
@@ -1,4 +0,0 @@--module Sound.Tidal.Version where--tidal_version = "0.9.10"
− doc/tidal.md
@@ -1,2 +0,0 @@-Documentation has now moved to the Tidal website:-  http://tidal.lurk.org/
+ src/Sound/Tidal/Bjorklund.hs view
@@ -0,0 +1,34 @@+module Sound.Tidal.Bjorklund (bjorklund) where++-- The below is (c) Rohan Drape, taken from the hmt library and+-- distributed here under the terms of the GNU Public Licence.  Tidal+-- used to just include the library but removed for now due to+-- dependency problems.. We could however likely benefit from other+-- parts of the library..++type STEP a = ((Int,Int),([[a]],[[a]]))++left :: STEP a -> STEP a+left ((i,j),(xs,ys)) =+    let (xs',xs'') = splitAt j xs+    in ((j,i-j),(zipWith (++) xs' ys,xs''))++right :: STEP a -> STEP a+right ((i,j),(xs,ys)) =+    let (ys',ys'') = splitAt i ys+    in ((i,j-i),(zipWith (++) xs ys',ys''))++bjorklund' :: STEP a -> STEP a+bjorklund' (n,x) =+    let (i,j) = n+    in if min i j <= 1+       then (n,x)+       else bjorklund' (if i > j then left (n,x) else right (n,x))++bjorklund :: (Int,Int) -> [Bool]+bjorklund (i,j') =+    let j = j' - i+        x = replicate i [True]+        y = replicate j [False]+        (_,(x',y')) = bjorklund' ((i,j),(x,y))+    in concat x' ++ concat y'
+ src/Sound/Tidal/Chords.hs view
@@ -0,0 +1,184 @@+module Sound.Tidal.Chords where++import Data.Maybe++import Sound.Tidal.Pattern++major :: Num a => [a]+major = [0,4,7]+minor :: Num a => [a]+minor = [0,3,7]+major7 :: Num a => [a]+major7 = [0,4,7,11]+dom7 :: Num a => [a]+dom7 = [0,4,7,10]+minor7 :: Num a => [a]+minor7 = [0,3,7,10]+aug :: Num a => [a]+aug = [0,4,8]+dim :: Num a => [a]+dim = [0,3,6]+dim7 :: Num a => [a]+dim7 = [0,3,6,9]+one :: Num a => [a]+one = [0]+five :: Num a => [a]+five = [0,7]+plus :: Num a => [a]+plus = [0,4,8]+sharp5 :: Num a => [a]+sharp5 = [0,4,8]+msharp5 :: Num a => [a]+msharp5 = [0,3,8]+sus2 :: Num a => [a]+sus2 = [0,2,7]+sus4 :: Num a => [a]+sus4 = [0,5,7]+six :: Num a => [a]+six = [0,4,7,9]+m6 :: Num a => [a]+m6 = [0,3,7,9]+sevenSus2 :: Num a => [a]+sevenSus2 = [0,2,7,10]+sevenSus4 :: Num a => [a]+sevenSus4 = [0,5,7,10]+sevenFlat5 :: Num a => [a]+sevenFlat5 = [0,4,6,10]+m7flat5 :: Num a => [a]+m7flat5 = [0,3,6,10]+sevenSharp5 :: Num a => [a]+sevenSharp5 = [0,4,8,10]+m7sharp5 :: Num a => [a]+m7sharp5 = [0,3,8,10]+nine :: Num a => [a]+nine = [0,4,7,10,14]+m9 :: Num a => [a]+m9 = [0,3,7,10,14]+m7sharp9 :: Num a => [a]+m7sharp9 = [0,3,7,10,14]+maj9 :: Num a => [a]+maj9 = [0,4,7,11,14]+nineSus4 :: Num a => [a]+nineSus4 = [0,5,7,10,14]+sixby9 :: Num a => [a]+sixby9 = [0,4,7,9,14]+m6by9 :: Num a => [a]+m6by9 = [0,3,9,7,14]+sevenFlat9 :: Num a => [a]+sevenFlat9 = [0,4,7,10,13]+m7flat9 :: Num a => [a]+m7flat9 = [0,3,7,10,13]+sevenFlat10 :: Num a => [a]+sevenFlat10 = [0,4,7,10,15]+nineSharp5 :: Num a => [a]+nineSharp5 = [0,1,13]+m9sharp5 :: Num a => [a]+m9sharp5 = [0,1,14]+sevenSharp5flat9 :: Num a => [a]+sevenSharp5flat9 = [0,4,8,10,13]+m7sharp5flat9 :: Num a => [a]+m7sharp5flat9 = [0,3,8,10,13]+eleven :: Num a => [a]+eleven = [0,4,7,10,14,17]+m11 :: Num a => [a]+m11 = [0,3,7,10,14,17]+maj11 :: Num a => [a]+maj11 = [0,4,7,11,14,17]+elevenSharp :: Num a => [a]+elevenSharp = [0,4,7,10,14,18]+m11sharp :: Num a => [a]+m11sharp = [0,3,7,10,14,18]+thirteen :: Num a => [a]+thirteen = [0,4,7,10,14,17,21]+m13 :: Num a => [a]+m13 = [0,3,7,10,14,17,21]++-- | @chordate cs m n@ selects the @n@th "chord" (a chord is a list of Ints)+-- from a list of chords @cs@ and transposes it by @m@+-- chordate :: Num b => [[b]] -> b -> Int -> [b]+-- chordate cs m n = map (+m) $ cs!!n++-- | @enchord chords pn pc@ turns every note in the note pattern @pn@ into+-- a chord, selecting from the chord lists @chords@ using the index pattern+-- @pc@.  For example, @Chords.enchord [Chords.major Chords.minor] "c g" "0 1"@+-- will create a pattern of a C-major chord followed by a G-minor chord.+-- enchord :: Num a => [[a]] -> Pattern a -> Pattern Int -> Pattern a+-- enchord chords pn pc = flatpat $ (chordate chords) <$> pn <*> pc++chordTable :: Num a => [(String, [a])]+chordTable = [("major", major),+              ("maj", major),+              ("minor", minor),+              ("min", minor),+              ("major7", major7),+              ("maj7", major7),+              ("dom7", dom7),+              ("minor7", minor7),+              ("min7", minor7),+              ("aug", aug),+              ("dim", dim),+              ("dim7", dim7),+              ("one", one),+              ("1", one),+              ("five", five),+              ("5", five),+              ("plus", plus),+              ("sharp5", sharp5),+              ("msharp5", msharp5),+              ("sus2", sus2),+              ("sus4", sus4),+              ("six", six),+              ("6", six),+              ("m6", m6),+              ("sevenSus2", sevenSus2),+              ("7sus2", sevenSus2),+              ("sevenSus4", sevenSus4),+              ("7sus4", sevenSus4),+              ("sevenFlat5", sevenFlat5),+              ("7f5", sevenFlat5),+              ("m7flat5", m7flat5),+              ("m7f5", m7flat5),+              ("sevenSharp5", sevenSharp5),+              ("7s5", sevenSharp5),+              ("m7sharp5", m7sharp5),+              ("m7s5", m7sharp5),+              ("nine", nine),+              ("m9", m9),+              ("m7sharp9", m7sharp9),+              ("m7s9", m7sharp9),+              ("maj9", maj9),+              ("nineSus4", nineSus4),+              ("ninesus4", nineSus4),+              ("9sus4", nineSus4),+              ("sixby9", sixby9),+              ("6by9", sixby9),+              ("m6by9", m6by9),+              ("sevenFlat9", sevenFlat9),+              ("7f9", sevenFlat9),+              ("m7flat9", m7flat9),+              ("m7f9", m7flat9),+              ("sevenFlat10", sevenFlat10),+              ("7f10", sevenFlat10),+              ("nineSharp5", nineSharp5),+              ("9s5", nineSharp5),+              ("m9sharp5", m9sharp5),+              ("m9s5", m9sharp5),+              ("sevenSharp5flat9", sevenSharp5flat9),+              ("7s5f9", sevenSharp5flat9),+              ("m7sharp5flat9", m7sharp5flat9),+              ("eleven", eleven),+              ("11", eleven),+              ("m11", m11),+              ("maj11", maj11),+              ("elevenSharp", elevenSharp),+              ("11s", elevenSharp),+              ("m11sharp", m11sharp),+              ("m11s", m11sharp),+              ("thirteen", thirteen),+              ("13", thirteen),+              ("m13", m13)+             ]++chordL :: Num a => Pattern String -> Pattern [a]+chordL p = (\name -> fromMaybe [] $ lookup name chordTable) <$> p+
+ src/Sound/Tidal/Config.hs view
@@ -0,0 +1,19 @@+module Sound.Tidal.Config where+++data Config = Config {cCtrlListen :: Bool,+                      cCtrlAddr :: String,+                      cCtrlPort :: Int,+                      cFrameTimespan :: Double,+                      cTempoAddr :: String,+                      cTempoPort :: Int+                     }++defaultConfig :: Config+defaultConfig = Config {cCtrlListen = True,+                        cCtrlAddr ="127.0.0.1",+                        cCtrlPort = 6010,+                        cFrameTimespan = 1/20,+                        cTempoAddr = "127.0.0.1",+                        cTempoPort = 9160+                       }
+ src/Sound/Tidal/Context.hs view
@@ -0,0 +1,18 @@+module Sound.Tidal.Context (module C) where++import Prelude hiding ((<*), (*>))++import Data.Ratio as C++import Sound.Tidal.Config as C+import Sound.Tidal.Control as C+import Sound.Tidal.Core as C+import Sound.Tidal.Params as C+import Sound.Tidal.ParseBP as C+import Sound.Tidal.Pattern as C+import Sound.Tidal.Scales as C+import Sound.Tidal.Simple as C+import Sound.Tidal.Stream as C+import Sound.Tidal.Transition as C+import Sound.Tidal.UI as C+import Sound.Tidal.EspGrid as C
+ src/Sound/Tidal/Control.hs view
@@ -0,0 +1,675 @@+{-# LANGUAGE TypeSynonymInstances, FlexibleInstances, OverloadedStrings #-}++module Sound.Tidal.Control where++import           Prelude hiding ((<*), (*>))++import qualified Data.Map.Strict as Map+import Data.Maybe (fromMaybe, isJust, fromJust)+import Data.Ratio++import Sound.Tidal.Pattern+import Sound.Tidal.Core+import Sound.Tidal.UI+import qualified Sound.Tidal.Params as P+import Sound.Tidal.Utils+import Sound.Tidal.ParseBP (Parseable, Enumerable, parseBP_E)++{- | `spin` will "spin" a layer up a pattern the given number of times,+with each successive layer offset in time by an additional `1/n` of a+cycle, and panned by an additional `1/n`. The result is a pattern that+seems to spin around. This function works best on multichannel+systems.++@+d1 $ slow 3 $ spin 4 $ sound "drum*3 tabla:4 [arpy:2 ~ arpy] [can:2 can:3]"+@+-}+spin :: Pattern Int -> ControlPattern -> ControlPattern+spin = tParam _spin++_spin :: Int -> ControlPattern -> ControlPattern+_spin copies p =+  stack $ map (\i -> let offset = toInteger i % toInteger copies in+                     offset `rotL` p+                     # P.pan (pure $ fromRational offset)+              )+          [0 .. (copies - 1)]++++{- | `chop` granualizes every sample in place as it is played, turning a pattern of samples into a pattern of sample parts. Use an integer value to specify how many granules each sample is chopped into:++@+d1 $ chop 16 $ sound "arpy arp feel*4 arpy*4"+@++Different values of `chop` can yield very different results, depending+on the samples used:+++@+d1 $ chop 16 $ sound (samples "arpy*8" (run 16))+d1 $ chop 32 $ sound (samples "arpy*8" (run 16))+d1 $ chop 256 $ sound "bd*4 [sn cp] [hh future]*2 [cp feel]"+@+-}++chop :: Pattern Int -> ControlPattern -> ControlPattern+chop = tParam _chop++chopArc :: Arc -> Int -> [Arc]+chopArc (Arc s e) n = map (\i -> (Arc (s + (e-s)*(fromIntegral i/fromIntegral n)) (s + (e-s)*((fromIntegral $ i+1)/fromIntegral n)))) [0 .. n-1]++_chop :: Int -> ControlPattern -> ControlPattern+_chop n p = withEvents (concatMap chopEvent) p+  where -- for each part,+        chopEvent :: Event ControlMap -> [Event ControlMap]+        chopEvent (Event w p' v) = map (\a -> chomp v (length $ chopArc w n) a) $ arcs w p'+        -- cut whole into n bits, and number them+        arcs w' p' = numberedArcs p' $ chopArc w' n+        -- each bit is a new whole, with part that's the intersection of old part and new whole+        -- (discard new parts that don't intersect with the old part)+        numberedArcs :: Arc -> [Arc] -> [(Int, (Arc, Arc))]+        numberedArcs p' as = map ((fromJust <$>) <$>) $ filter (isJust . snd . snd) $ enumerate $ map (\a -> (a, subArc p' a)) as+        -- begin set to i/n, end set to i+1/n+        -- if the old event had a begin and end, then multiply the new+        -- begin and end values by the old difference (end-begin), and+        -- add the old begin+        chomp :: ControlMap -> Int -> (Int, (Arc, Arc)) -> Event ControlMap+        chomp v n' (i, (w,p')) = Event w p' (Map.insert "begin" (VF b') $ Map.insert "end" (VF e') v)+          where b = fromMaybe 0 $ do v' <- Map.lookup "begin" v+                                     getF v'+                e = fromMaybe 1 $ do v' <- Map.lookup "end" v+                                     getF v'+                d = e-b+                b' = (((fromIntegral i)/(fromIntegral n')) * d) + b+                e' = (((fromIntegral $ i+1)/(fromIntegral n')) * d) + b++{-+-- A simpler definition than the above, but this version doesn't chop+-- with multiple chops, and only works with a single 'pure' event..+_chop' :: Int -> ControlPattern -> ControlPattern+_chop' n p = begin (fromList begins) # end (fromList ends) # p+  where step = 1/(fromIntegral n)+        begins = [0,step .. (1-step)]+        ends = (tail begins) ++ [1]+-}+++{- | Striate is a kind of granulator, for example:++@+d1 $ striate 3 $ sound "ho ho:2 ho:3 hc"+@++This plays the loop the given number of times, but triggering+progressive portions of each sample. So in this case it plays the loop+three times, the first time playing the first third of each sample,+then the second time playing the second third of each sample, etc..+With the highhat samples in the above example it sounds a bit like+reverb, but it isn't really.++You can also use striate with very long samples, to cut it into short+chunks and pattern those chunks. This is where things get towards+granular synthesis. The following cuts a sample into 128 parts, plays+it over 8 cycles and manipulates those parts by reversing and rotating+the loops.++@+d1 $  slow 8 $ striate 128 $ sound "bev"+@+-}++striate :: Pattern Int -> ControlPattern -> ControlPattern+striate = tParam _striate++_striate :: Int -> ControlPattern -> ControlPattern+_striate n p = fastcat $ map (\i -> offset i) [0 .. n-1]+  where offset i = (mergePlayRange ((fromIntegral i / fromIntegral n), (fromIntegral (i+1) / fromIntegral n))) <$> p++mergePlayRange :: (Double, Double) -> ControlMap -> ControlMap+mergePlayRange (b,e) cm = Map.insert "begin" (VF $ (b*d')+b') $ Map.insert "end" (VF $ (e*d')+b') $ cm+  where b' = fromMaybe 0 $ Map.lookup "begin" cm >>= getF+        e' = fromMaybe 1 $ Map.lookup "end" cm >>= getF+        d' = e' - b'+++{-|+The `striateBy` function is a variant of `striate` with an extra+parameter, which specifies the length of each part. The `striateBy`+function still scans across the sample over a single cycle, but if+each bit is longer, it creates a sort of stuttering effect. For+example the following will cut the bev sample into 32 parts, but each+will be 1/16th of a sample long:++@+d1 $ slow 32 $ striateBy 32 (1/16) $ sound "bev"+@++Note that `striate` uses the `begin` and `end` parameters+internally. This means that if you're using `striate` (or `striateBy`)+you probably shouldn't also specify `begin` or `end`. -}+striateBy :: Pattern Int -> Pattern Double -> ControlPattern -> ControlPattern+striateBy = tParam2 _striateBy++-- Old name for striateBy, here as a deprecated alias for now.+striate' :: Pattern Int -> Pattern Double -> ControlPattern -> ControlPattern+striate' = striateBy++_striateBy :: Int -> Double -> ControlPattern -> ControlPattern+_striateBy n f p = fastcat $ map (\i -> offset (fromIntegral i)) [0 .. n-1]+  where offset i = p # P.begin (pure (slot * i) :: Pattern Double) # P.end (pure ((slot * i) + f) :: Pattern Double)+        slot = (1 - f) / (fromIntegral n)++++{- | `gap` is similar to `chop` in that it granualizes every sample in place as it is played,+but every other grain is silent. Use an integer value to specify how many granules+each sample is chopped into:++@+d1 $ gap 8 $ sound "jvbass"+d1 $ gap 16 $ sound "[jvbass drum:4]"+@-}++gap :: Pattern Int -> ControlPattern -> ControlPattern+gap = tParam _gap++_gap :: Int -> ControlPattern -> ControlPattern +_gap n p = (_fast (toRational n) $ cat [pure 1, silence]) |>| ( _chop n p)++{- |+`weave` applies a function smoothly over an array of different patterns. It uses an `OscPattern` to+apply the function at different levels to each pattern, creating a weaving effect.++@+d1 $ weave 3 (shape $ sine1) [sound "bd [sn drum:2*2] bd*2 [sn drum:1]", sound "arpy*8 ~"]+@+-}+weave :: Time -> ControlPattern -> [ControlPattern] -> ControlPattern+weave t p ps = weave' t p (map (\x -> (x #)) ps)+++{- | `weaveWith` is similar in that it blends functions at the same time at different amounts over a pattern:++@+d1 $ weaveWith 3 (sound "bd [sn drum:2*2] bd*2 [sn drum:1]") [density 2, (# speed "0.5"), chop 16]+@+-}+weaveWith :: Time -> Pattern a -> [Pattern a -> Pattern a] -> Pattern a+weaveWith t p fs | l == 0 = silence+              | otherwise = _slow t $ stack $ map (\(i, f) -> (fromIntegral i % l) `rotL` (_fast t $ f (_slow t p))) (zip [0 :: Int ..] fs)+  where l = fromIntegral $ length fs++weave' :: Time -> Pattern a -> [Pattern a -> Pattern a] -> Pattern a+weave' = weaveWith++{- |+(A function that takes two ControlPatterns, and blends them together into+a new ControlPattern. An ControlPattern is basically a pattern of messages to+a synthesiser.)++Shifts between the two given patterns, using distortion.++Example:++@+d1 $ interlace (sound  "bd sn kurt") (every 3 rev $ sound  "bd sn:2")+@+-}+interlace :: ControlPattern -> ControlPattern -> ControlPattern+interlace a b = weave 16 (P.shape $ (sine * 0.9)) [a, b]++{-+{- | Just like `striate`, but also loops each sample chunk a number of times specified in the second argument.+The primed version is just like `striateBy`, where the loop count is the third argument. For example:++@+d1 $ striateL' 3 0.125 4 $ sound "feel sn:2"+@++Like `striate`, these use the `begin` and `end` parameters internally, as well as the `loop` parameter for these versions.+-}+striateL :: Pattern Int -> Pattern Int -> ControlPattern -> ControlPattern+striateL = tParam2 _striateL++striateL' :: Pattern Int -> Pattern Double -> Pattern Int -> ControlPattern -> ControlPattern+striateL' = tParam3 _striateL'++_striateL :: Int -> Int -> ControlPattern -> ControlPattern+_striateL n l p = _striate n p # loop (pure $ fromIntegral l)+_striateL' n f l p = _striateBy n f p # loop (pure $ fromIntegral l)+++en :: [(Int, Int)] -> Pattern String -> Pattern String+en ns p = stack $ map (\(i, (k, n)) -> _e k n (samples p (pure i))) $ enumerate ns++-}++slice :: Pattern Int -> Pattern Int -> ControlPattern -> ControlPattern+slice pN pI p = P.begin b # P.end e # p+  where b = (\i n -> (div' i n)) <$> pI <* pN+        e = (\i n -> (div' i n) + (div' 1 n)) <$> pI <* pN+        div' num den = fromIntegral (num `mod` den) / fromIntegral den++_slice :: Int -> Int -> ControlPattern -> ControlPattern+_slice n i p =+      p+      # P.begin (pure $ fromIntegral i / fromIntegral n)+      # P.end (pure $ fromIntegral (i+1) / fromIntegral n)++randslice :: Pattern Int -> ControlPattern -> ControlPattern+randslice = tParam $ \n p -> innerJoin $ (\i -> _slice n i p) <$> irand n++{- |+`loopAt` makes a sample fit the given number of cycles. Internally, it+works by setting the `unit` parameter to "c", changing the playback+speed of the sample with the `speed` parameter, and setting setting+the `density` of the pattern to match.++@+d1 $ loopAt 4 $ sound "breaks125"+d1 $ juxBy 0.6 (|* speed "2") $ slowspread (loopAt) [4,6,2,3] $ chop 12 $ sound "fm:14"+@+-}+loopAt :: Pattern Time -> ControlPattern -> ControlPattern+loopAt n p = slow n p |* P.speed (fromRational <$> (1/n)) # P.unit (pure "c")++hurry :: Pattern Rational -> ControlPattern -> ControlPattern+hurry x = (|* P.speed (fromRational <$> x)) . fast x++{- | Smash is a combination of `spread` and `striate` - it cuts the samples+into the given number of bits, and then cuts between playing the loop+at different speeds according to the values in the list.++So this:++@+d1 $ smash 3 [2,3,4] $ sound "ho ho:2 ho:3 hc"+@++Is a bit like this:++@+d1 $ spread (slow) [2,3,4] $ striate 3 $ sound "ho ho:2 ho:3 hc"+@++This is quite dancehall:++@+d1 $ (spread' slow "1%4 2 1 3" $ spread (striate) [2,3,4,1] $ sound+"sn:2 sid:3 cp sid:4")+  # speed "[1 2 1 1]/2"+@+-}++smash :: Pattern Int -> [Pattern Time] -> ControlPattern -> Pattern ControlMap+smash n xs p = slowcat $ map (\x -> slow x p') xs+  where p' = striate n p++{- | an altenative form to `smash` is `smash'` which will use `chop` instead of `striate`.+-}+smash' :: Int -> [Pattern Time] -> ControlPattern -> Pattern ControlMap+smash' n xs p = slowcat $ map (\x -> slow x p') xs+  where p' = _chop n p+++{- | Stut applies a type of delay to a pattern. It has three parameters,+which could be called depth, feedback and time. Depth is an integer+and the others floating point. This adds a bit of echo:++@+d1 $ stut 4 0.5 0.2 $ sound "bd sn"+@++The above results in 4 echos, each one 50% quieter than the last,+with 1/5th of a cycle between them. It is possible to reverse the echo:++@+d1 $ stut 4 0.5 (-0.2) $ sound "bd sn"+@+-}++stut :: Pattern Integer -> Pattern Double -> Pattern Rational -> ControlPattern -> ControlPattern+stut = tParam3 _stut++_stut :: Integer -> Double -> Rational -> ControlPattern -> ControlPattern+_stut count feedback time p = stack (p:(map (\x -> (((x%count)*time) `rotR` (p |* P.gain (pure $ scalegain (fromIntegral x))))) [1..(count-1)]))+  where scalegain x+          = ((+feedback) . (*(1-feedback)) . (/(fromIntegral count)) . ((fromIntegral count)-)) x++{- | Instead of just decreasing volume to produce echoes, @stut'@ allows to apply a function for each step and overlays the result delayed by the given time.++@+d1 $ stut' 2 (1%3) (# vowel "{a e i o u}%2") $ sound "bd sn"+@++In this case there are two _overlays_ delayed by 1/3 of a cycle, where each has the @vowel@ filter applied.+-}+stutWith :: Pattern Int -> Pattern Time -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a+stutWith n t f p = unwrap $ (\a b -> _stutWith a b f p) <$> n <*> t++_stutWith :: (Num n, Ord n) => n -> Time -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a+_stutWith count steptime f p | count <= 0 = p+                          | otherwise = overlay (f (steptime `rotR` _stutWith (count-1) steptime f p)) p++-- | The old name for stutWith+stut' :: Pattern Int -> Pattern Time -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a+stut' = stutWith++cI :: String -> Pattern Int+cI s = Pattern Analog $ \(State a m) -> maybe [] (f a) $ Map.lookup s m+  where f a (VI v) = [Event a a v]+        f a (VF v) = [Event a a (floor v)]+        f a (VS v) = maybe [] (\v' -> [Event a a v']) (readMaybe v)++_cX :: (Arc -> Value -> [Event a]) -> [a] -> String -> Pattern a+_cX f ds s = Pattern Analog $+               \(State a m) -> maybe (map (\d -> (Event a a d)) ds) (f a) $ Map.lookup s m++_cF :: [Double] -> String -> Pattern Double+_cF = _cX f+  where f a (VI v) = [Event a a (fromIntegral v)]+        f a (VF v) = [Event a a v]+        f a (VS v) = maybe [] (\v' -> [Event a a v']) (readMaybe v)++cF :: Double -> String -> Pattern Double+cF d = _cF [d]+cF0 :: String -> Pattern Double+cF0 = _cF [0]+cF_ :: String -> Pattern Double+cF_ = _cF []++cT :: Time -> String -> Pattern Time+cT d = (toRational <$>) . cF (fromRational d)+cT0 :: String -> Pattern Time+cT0 = (toRational <$>) . cF0+cT_ :: String -> Pattern Time+cT_ = (toRational <$>) . cF_+++cR :: Time -> String -> Pattern Rational+cR = cT+cR0 :: String -> Pattern Time+cR0 = cT0+cR_ :: String -> Pattern Time+cR_ = cT_++_cS :: [String] -> String -> Pattern String+_cS = _cX f+  where f a (VI v) = [Event a a (show v)]+        f a (VF v) = [Event a a (show v)]+        f a (VS v) = [Event a a v]+cS :: String -> String -> Pattern String+cS d = _cS [d]+cS_ :: String -> Pattern String+cS_ = _cS []++_cP :: (Enumerable a, Parseable a) => [Pattern a] -> String -> Pattern a+_cP ds s = innerJoin $ _cX f ds s+  where f a (VI v) = [Event a a (parseBP_E $ show v)]+        f a (VF v) = [Event a a (parseBP_E $ show v)]+        f a (VS v) = [Event a a (parseBP_E $ v)]+cP :: (Enumerable a, Parseable a) => Pattern a -> String -> Pattern a+cP d = _cP [d]+cP_ :: (Enumerable a, Parseable a) => String -> Pattern a+cP_ = _cP []++-- Default controller inputs (for MIDI)+in0 :: Pattern Double+in0 = cF 0 "0"+in1 :: Pattern Double+in1 = cF 0 "1"+in2 :: Pattern Double+in2 = cF 0 "2"+in3 :: Pattern Double+in3 = cF 0 "3"+in4 :: Pattern Double+in4 = cF 0 "4"+in5 :: Pattern Double+in5 = cF 0 "5"+in6 :: Pattern Double+in6 = cF 0 "6"+in7 :: Pattern Double+in7 = cF 0 "7"+in8 :: Pattern Double+in8 = cF 0 "8"+in9 :: Pattern Double+in9 = cF 0 "9"+in10 :: Pattern Double+in10 = cF 0 "10"+in11 :: Pattern Double+in11 = cF 0 "11"+in12 :: Pattern Double+in12 = cF 0 "12"+in13 :: Pattern Double+in13 = cF 0 "13"+in14 :: Pattern Double+in14 = cF 0 "14"+in15 :: Pattern Double+in15 = cF 0 "15"+in16 :: Pattern Double+in16 = cF 0 "16"+in17 :: Pattern Double+in17 = cF 0 "17"+in18 :: Pattern Double+in18 = cF 0 "18"+in19 :: Pattern Double+in19 = cF 0 "19"+in20 :: Pattern Double+in20 = cF 0 "20"+in21 :: Pattern Double+in21 = cF 0 "21"+in22 :: Pattern Double+in22 = cF 0 "22"+in23 :: Pattern Double+in23 = cF 0 "23"+in24 :: Pattern Double+in24 = cF 0 "24"+in25 :: Pattern Double+in25 = cF 0 "25"+in26 :: Pattern Double+in26 = cF 0 "26"+in27 :: Pattern Double+in27 = cF 0 "27"+in28 :: Pattern Double+in28 = cF 0 "28"+in29 :: Pattern Double+in29 = cF 0 "29"+in30 :: Pattern Double+in30 = cF 0 "30"+in31 :: Pattern Double+in31 = cF 0 "31"+in32 :: Pattern Double+in32 = cF 0 "32"+in33 :: Pattern Double+in33 = cF 0 "33"+in34 :: Pattern Double+in34 = cF 0 "34"+in35 :: Pattern Double+in35 = cF 0 "35"+in36 :: Pattern Double+in36 = cF 0 "36"+in37 :: Pattern Double+in37 = cF 0 "37"+in38 :: Pattern Double+in38 = cF 0 "38"+in39 :: Pattern Double+in39 = cF 0 "39"+in40 :: Pattern Double+in40 = cF 0 "40"+in41 :: Pattern Double+in41 = cF 0 "41"+in42 :: Pattern Double+in42 = cF 0 "42"+in43 :: Pattern Double+in43 = cF 0 "43"+in44 :: Pattern Double+in44 = cF 0 "44"+in45 :: Pattern Double+in45 = cF 0 "45"+in46 :: Pattern Double+in46 = cF 0 "46"+in47 :: Pattern Double+in47 = cF 0 "47"+in48 :: Pattern Double+in48 = cF 0 "48"+in49 :: Pattern Double+in49 = cF 0 "49"+in50 :: Pattern Double+in50 = cF 0 "50"+in51 :: Pattern Double+in51 = cF 0 "51"+in52 :: Pattern Double+in52 = cF 0 "52"+in53 :: Pattern Double+in53 = cF 0 "53"+in54 :: Pattern Double+in54 = cF 0 "54"+in55 :: Pattern Double+in55 = cF 0 "55"+in56 :: Pattern Double+in56 = cF 0 "56"+in57 :: Pattern Double+in57 = cF 0 "57"+in58 :: Pattern Double+in58 = cF 0 "58"+in59 :: Pattern Double+in59 = cF 0 "59"+in60 :: Pattern Double+in60 = cF 0 "60"+in61 :: Pattern Double+in61 = cF 0 "61"+in62 :: Pattern Double+in62 = cF 0 "62"+in63 :: Pattern Double+in63 = cF 0 "63"+in64 :: Pattern Double+in64 = cF 0 "64"+in65 :: Pattern Double+in65 = cF 0 "65"+in66 :: Pattern Double+in66 = cF 0 "66"+in67 :: Pattern Double+in67 = cF 0 "67"+in68 :: Pattern Double+in68 = cF 0 "68"+in69 :: Pattern Double+in69 = cF 0 "69"+in70 :: Pattern Double+in70 = cF 0 "70"+in71 :: Pattern Double+in71 = cF 0 "71"+in72 :: Pattern Double+in72 = cF 0 "72"+in73 :: Pattern Double+in73 = cF 0 "73"+in74 :: Pattern Double+in74 = cF 0 "74"+in75 :: Pattern Double+in75 = cF 0 "75"+in76 :: Pattern Double+in76 = cF 0 "76"+in77 :: Pattern Double+in77 = cF 0 "77"+in78 :: Pattern Double+in78 = cF 0 "78"+in79 :: Pattern Double+in79 = cF 0 "79"+in80 :: Pattern Double+in80 = cF 0 "80"+in81 :: Pattern Double+in81 = cF 0 "81"+in82 :: Pattern Double+in82 = cF 0 "82"+in83 :: Pattern Double+in83 = cF 0 "83"+in84 :: Pattern Double+in84 = cF 0 "84"+in85 :: Pattern Double+in85 = cF 0 "85"+in86 :: Pattern Double+in86 = cF 0 "86"+in87 :: Pattern Double+in87 = cF 0 "87"+in88 :: Pattern Double+in88 = cF 0 "88"+in89 :: Pattern Double+in89 = cF 0 "89"+in90 :: Pattern Double+in90 = cF 0 "90"+in91 :: Pattern Double+in91 = cF 0 "91"+in92 :: Pattern Double+in92 = cF 0 "92"+in93 :: Pattern Double+in93 = cF 0 "93"+in94 :: Pattern Double+in94 = cF 0 "94"+in95 :: Pattern Double+in95 = cF 0 "95"+in96 :: Pattern Double+in96 = cF 0 "96"+in97 :: Pattern Double+in97 = cF 0 "97"+in98 :: Pattern Double+in98 = cF 0 "98"+in99 :: Pattern Double+in99 = cF 0 "99"+in100 :: Pattern Double+in100 = cF 0 "100"+in101 :: Pattern Double+in101 = cF 0 "101"+in102 :: Pattern Double+in102 = cF 0 "102"+in103 :: Pattern Double+in103 = cF 0 "103"+in104 :: Pattern Double+in104 = cF 0 "104"+in105 :: Pattern Double+in105 = cF 0 "105"+in106 :: Pattern Double+in106 = cF 0 "106"+in107 :: Pattern Double+in107 = cF 0 "107"+in108 :: Pattern Double+in108 = cF 0 "108"+in109 :: Pattern Double+in109 = cF 0 "109"+in110 :: Pattern Double+in110 = cF 0 "110"+in111 :: Pattern Double+in111 = cF 0 "111"+in112 :: Pattern Double+in112 = cF 0 "112"+in113 :: Pattern Double+in113 = cF 0 "113"+in114 :: Pattern Double+in114 = cF 0 "114"+in115 :: Pattern Double+in115 = cF 0 "115"+in116 :: Pattern Double+in116 = cF 0 "116"+in117 :: Pattern Double+in117 = cF 0 "117"+in118 :: Pattern Double+in118 = cF 0 "118"+in119 :: Pattern Double+in119 = cF 0 "119"+in120 :: Pattern Double+in120 = cF 0 "120"+in121 :: Pattern Double+in121 = cF 0 "121"+in122 :: Pattern Double+in122 = cF 0 "122"+in123 :: Pattern Double+in123 = cF 0 "123"+in124 :: Pattern Double+in124 = cF 0 "124"+in125 :: Pattern Double+in125 = cF 0 "125"+in126 :: Pattern Double+in126 = cF 0 "126"+in127 :: Pattern Double+in127 = cF 0 "127"
+ src/Sound/Tidal/Core.hs view
@@ -0,0 +1,412 @@+{-# LANGUAGE TypeSynonymInstances, FlexibleInstances, OverloadedStrings #-}++module Sound.Tidal.Core where++import           Prelude hiding ((<*), (*>))++import           Data.Fixed (mod')+import qualified Data.Map.Strict as Map++import           Sound.Tidal.Pattern++-- ** Elemental patterns++-- | An empty pattern+silence :: Pattern a+silence = empty++-- | Takes a function from time to values, and turns it into a 'Pattern'.+sig :: (Time -> a) -> Pattern a+sig f = Pattern Analog q+  where q (State (Arc s e) _)+          | s > e = []+          | otherwise = [Event (Arc s e) (Arc s e) (f (s+((e-s)/2)))]++-- | @sine@ returns a 'Pattern' of continuous 'Fractional' values following a+-- sinewave with frequency of one cycle, and amplitude from 0 to 1.+sine :: Fractional a => Pattern a+sine = sig $ \t -> ((sin_rat $ (pi :: Double) * 2 * (fromRational t)) + 1) / 2+  where sin_rat = fromRational . toRational . sin++-- | @cosine@ is a synonym for @0.25 ~> sine@.+cosine :: Fractional a => Pattern a+cosine = 0.25 `rotR` sine++-- | @saw@ is the equivalent of 'sine' for (ascending) sawtooth waves.+saw :: (Fractional a, Real a) => Pattern a+saw = sig $ \t -> mod' (fromRational t) 1++-- | @isaw@ is the equivalent of 'sine' for inverse (descending) sawtooth waves.+isaw :: (Fractional a, Real a) => Pattern a+isaw = (1-) <$> saw++-- | @tri@ is the equivalent of 'sine' for triangular waves.+tri :: (Fractional a, Real a) => Pattern a+tri = fastAppend saw isaw++-- | @square@ is the equivalent of 'sine' for square waves.+square :: (Fractional a) => Pattern a+square = sig $+         \t -> fromIntegral $ ((floor $ (mod' (fromRational t :: Double) 1) * 2) :: Integer)++-- | @envL@ is a 'Pattern' of continuous 'Double' values, representing+-- a linear interpolation between 0 and 1 during the first cycle, then+-- staying constant at 1 for all following cycles. Possibly only+-- useful if you're using something like the retrig function defined+-- in tidal.el.+envL :: Pattern Double+envL = sig $ \t -> max 0 $ min (fromRational t) 1++-- | like 'envL' but reversed.+envLR :: Pattern Double+envLR = (1-) <$> envL++-- | 'Equal power' version of 'env', for gain-based transitions+envEq :: Pattern Double+envEq = sig $ \t -> sqrt (sin (pi/2 * (max 0 $ min (fromRational (1-t)) 1)))++-- | Equal power reversed+envEqR :: Pattern Double+envEqR = sig $ \t -> sqrt (cos (pi/2 * (max 0 $ min (fromRational (1-t)) 1)))++-- ** Pattern algebra++-- class for types that support a left-biased union+class Unionable a where+  union :: a -> a -> a++-- default union is just to take the left hand side..+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, 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, 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++-- Backward compatibility - structure from left, values from right.+(#) :: Unionable b => Pattern b -> Pattern b -> Pattern b+(#) = (|>)++++-- ** Constructing patterns++-- | Turns a list of values into a pattern, playing one of them per cycle.+fromList :: [a] -> Pattern a+fromList = cat . map pure++-- | Turns a list of values into a pattern, playing one of them per cycle.+fastFromList :: [a] -> Pattern a+fastFromList = fastcat . map pure++-- | A synonym for 'fastFromList'+listToPat :: [a] -> Pattern a+listToPat = fastFromList++-- | 'fromMaybes; is similar to 'fromList', but allows values to+-- be optional using the 'Maybe' type, so that 'Nothing' results in+-- gaps in the pattern.+fromMaybes :: [Maybe a] -> Pattern a+fromMaybes = fastcat . map f+  where f Nothing = silence+        f (Just x) = pure x++-- | A pattern of whole numbers from 0 to the given number, in a single cycle.+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]++-- | From @1@ for the first cycle, successively adds a number until it gets up to @n@+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]++-- ** Combining patterns++-- | Alternate between cycles of the two given patterns+append :: Pattern a -> Pattern a -> Pattern a+append a b = cat [a,b]++-- | Like 'append', but for a list of patterns. Interlaces them, playing the first cycle from each+-- in turn, then the second cycle from each, and so on.+cat :: [Pattern a] -> Pattern a+cat [] = silence+-- TODO I *guess* it would be digital..+cat ps = Pattern Digital 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++-- | Alias for 'cat'+slowCat :: [Pattern a] -> Pattern a+slowCat = cat+slowcat :: [Pattern a] -> Pattern a+slowcat = slowCat++-- | Alias for 'append'+slowAppend :: Pattern a -> Pattern a -> Pattern a+slowAppend = append++-- | Like 'append', but twice as fast+fastAppend :: Pattern a -> Pattern a -> Pattern a+fastAppend a b = _fast 2 $ append a b++-- | The same as 'cat', but speeds up the result by the number of+-- patterns there are, so the cycles from each are squashed to fit a+-- single cycle.+fastCat :: [Pattern a] -> Pattern a+fastCat ps = _fast (toTime $ length ps) $ cat ps++fastcat :: [Pattern a] -> Pattern a+fastcat = fastCat++-- | Similar to @fastCat@, but each pattern is given a relative duration+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' combines two 'Pattern's into a new pattern, so that+-- their events are combined over time. +overlay :: Pattern a -> Pattern a -> Pattern a+-- Analog if they're both analog+overlay p@(Pattern Analog _) p'@(Pattern Analog _) = Pattern Analog $ \st -> (query p st) ++ (query p' st)+-- Otherwise digital. Won't really work to have a mixture.. Hmm+overlay p p' = Pattern Digital $ \st -> (query p st) ++ (query p' st)++-- | 'stack' combines a list of 'Pattern's into a new pattern, so that+-- their events are combined over time.+stack :: [Pattern a] -> Pattern a+stack = foldr overlay silence++++-- ** Manipulating time++-- | Shifts a pattern back in time by the given amount, expressed in cycles+(<~) :: Pattern Time -> Pattern a -> Pattern a+(<~) = tParam rotL++-- | Shifts a pattern forward in time by the given amount, expressed in cycles+(~>) :: Pattern Time -> Pattern a -> Pattern a+(~>) = tParam rotR++-- | Speed up a pattern by the given time pattern+fast :: Pattern Time -> Pattern a -> Pattern a+fast = tParam _fast++-- | Slow down a pattern by the factors in the given time pattern, 'squeezing'+-- the pattern to fit the slot given in the time pattern+fastSqueeze :: Pattern Time -> Pattern a -> Pattern a+fastSqueeze = tParamSqueeze _fast++-- | An alias for @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 (0-r) p+          | otherwise = withResultTime (/ r) $ withQueryTime (* r) p++-- | Slow down a pattern by the given time pattern+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++-- | Slow down a pattern by the factors in the given time pattern, 'squeezing'+-- the pattern to fit the slot given in the time pattern+slowSqueeze :: Pattern Time -> Pattern a -> Pattern a+slowSqueeze = tParamSqueeze _slow++-- | An alias for @slow@+sparsity :: Pattern Time -> Pattern a -> Pattern a+sparsity = slow++-- | @rev p@ returns @p@ with the event positions in each cycle+-- reversed (or mirrored).+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 (Event (Arc s e) p'@(Arc s' e') v) =+          Event (Arc (s'-s) (e'-e)) p' v+        makeWholeAbsolute :: Event a -> Event a+        makeWholeAbsolute (Event (Arc s e) p'@(Arc s' e') v) =+          Event (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+        -- | Returns the `mirror image' of a 'Arc' around the given point in time+        mirrorArc :: Time -> Arc -> Arc+        mirrorArc mid' (Arc s e) = Arc (mid' - (e-mid')) (mid'+(mid'-s))++{- | Plays a portion of a pattern, specified by a time arc (start and end time).+The new resulting pattern is played over the time period of the original pattern:++@+d1 $ zoom (0.25, 0.75) $ sound "bd*2 hh*3 [sn bd]*2 drum"+@++In the pattern above, `zoom` is used with an arc from 25% to 75%. It is equivalent to this pattern:++@+d1 $ sound "hh*3 [sn bd]*2"+@+-}+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@ is similar to 'fast' but maintains its cyclic+-- alignment. For example, @fastGap 2 p@ would squash the events in+-- pattern @p@ into the first half of each cycle (and the second+-- halves would be empty). The factor should be at least 1+fastGap :: Pattern Time -> Pattern a -> Pattern a+fastGap = tParam _fastGap++-- | An alias for @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)++-- | * Higher order functions++-- | Functions which work on other functions (higher order functions)++-- | @every n f p@ applies the function @f@ to @p@, but only affects+-- every @n@ cycles.+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 n o f'@ is like @every n f@ with an offset of @o@ cycles+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 ns f p@ applies the function @f@ to @p@, and is applied for+-- each cycle in @ns@.+foldEvery :: [Int] -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a+foldEvery ns f p = foldr ($) p (map (\x -> _every x f) ns)++{-|+Only `when` the given test function returns `True` the given pattern+transformation is applied. The test function will be called with the+current cycle as a number.++@+d1 $ when ((elem '4').show)+  (striate 4)+  $ sound "hh hc"+@++The above will only apply `striate 4` to the pattern if the current+cycle number contains the number 4. So the fourth cycle will be+striated and the fourteenth and so on. Expect lots of striates after+cycle number 399.+-}+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++-- | Like 'when', but works on continuous time values rather than cycle numbers.+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+++--eoff :: Int -> Int -> Integer -> Pattern a -> Pattern a+--eoff n k s p = ((s%(fromIntegral k)) `rotL`) (_e n k p)+   -- TPat_ShiftL (s%(fromIntegral k)) (TPat_E n k p)
+ src/Sound/Tidal/EspGrid.hs view
@@ -0,0 +1,46 @@+{-# LANGUAGE ScopedTypeVariables #-}
+
+module Sound.Tidal.EspGrid (tidalEspGridLink,cpsEsp) where
+
+import Control.Concurrent.MVar
+import Control.Concurrent (forkIO,threadDelay)
+import Control.Monad (forever)
+import Sound.OSC.FD
+import Sound.Tidal.Tempo
+
+parseEspTempo :: [Datum] -> Maybe (Tempo -> Tempo)
+parseEspTempo d = do
+  on :: Integer <- datum_integral (d!!0)
+  bpm <- datum_floating (d!!1)
+  t1 :: Integer <- datum_integral (d!!2)
+  t2 <- datum_integral (d!!3)
+  n :: Integer <- datum_integral (d!!4)
+  let nanos = (t1*1000000000) + t2
+  return $ \t -> t {
+    atTime = ((realToFrac nanos)/1000000000),
+    atCycle = fromIntegral n,
+    cps = bpm/60,
+    paused = on == 0
+    }
+
+changeTempo :: MVar Tempo -> Packet -> IO ()
+changeTempo t (Packet_Message msg) = do
+    case parseEspTempo (messageDatum msg) of
+      Just f -> takeMVar t >>= (\x -> putMVar t (f x))
+      Nothing -> putStrLn "Warning: Unable to parse message (likely from EspGrid) as Tempo"
+changeTempo _ _ = putStrLn "Serious error: Can only process Packet_Message"
+
+tidalEspGridLink :: MVar Tempo -> IO ()
+tidalEspGridLink t = do
+  socket <- openUDP "127.0.0.1" 5510
+  _ <- forkIO $ forever $ do
+    _ <- sendOSC socket $ Message "/esp/tempo/q" []
+    response <- waitAddress socket "/esp/tempo/r"
+    changeTempo t response
+    threadDelay 200000
+  return ()
+
+cpsEsp :: Real t => t -> IO ()
+cpsEsp t = do
+  socket <- openUDP "127.0.0.1" 5510
+  sendOSC socket $ Message "/esp/beat/tempo" [float (t*60)]
+ src/Sound/Tidal/MiniTidal.hs view
@@ -0,0 +1,547 @@+{-# LANGUAGE FlexibleInstances #-}++module Sound.Tidal.MiniTidal (miniTidal,miniTidalIO,main) where++import           Data.Functor.Identity (Identity)+import           Text.Parsec.Language (haskellDef)+import           Text.Parsec.Prim (ParsecT)+import           Text.ParserCombinators.Parsec+import qualified Text.ParserCombinators.Parsec.Token as P+import           Control.Monad (forever)+-- import Data.List (intercalate)+-- import Data.Bool (bool)+-- import Data.Ratio++import           Sound.Tidal.Context (Pattern,ControlMap,ControlPattern,Enumerable,Parseable,Time,Arc,TPat,Stream)+import qualified Sound.Tidal.Context as T++-- This is depended upon by Estuary, and changes to its type will cause problems downstream for Estuary.+miniTidal :: String -> Either ParseError (Pattern ControlMap)+miniTidal = parse miniTidalParser "miniTidal"++miniTidalParser :: Parser ControlPattern+miniTidalParser = whiteSpace >> choice [+  eof >> return T.silence,+  do+    x <- pattern+    eof+    return x+  ]++class Pattern' a where+  simplePattern :: Parser (Pattern a)+  complexPattern :: Parser (Pattern a)+  mergeOperator :: Parser (Pattern a -> Pattern a -> Pattern a)+  transformationWithoutArgs :: Parser (Pattern a -> Pattern a)+  transformationWithArgs :: Parser (Pattern a -> Pattern a)+  literal :: Parser a++pattern :: Pattern' a => Parser (Pattern a)+pattern = chainl1 pattern' mergeOperator++pattern' :: Pattern' a => Parser (Pattern a)+pattern' = choice [+  nestedParens $ chainl1 pattern mergeOperator,+  parensOrNot complexPattern,+  parensOrNot genericComplexPatterns,+  parensOrNot transformedPattern,+  parensOrNot simplePattern,+  silence+  ]++patternArg :: Pattern' a => Parser (Pattern a)+patternArg = choice [+  try $ parensOrApplied $ chainl1 pattern mergeOperator,+  try $ parensOrApplied transformedPattern,+  try $ parensOrApplied complexPattern,+  try $ parensOrApplied genericComplexPatterns,+  appliedOrNot simplePattern,+  appliedOrNot silence+  ]++literalArg :: Pattern' a => Parser a+literalArg = choice [+  literal,+  nestedParens literal,+  try $ applied $ parensOrNot literal+  ]++listLiteralArg :: Pattern' a => Parser [a]+listLiteralArg = brackets (commaSep $ parensOrNot literal)++listPatternArg :: Pattern' a => Parser [Pattern a]+listPatternArg = parensOrNot $ brackets (commaSep pattern)++silence :: Parser (Pattern a)+silence = function "silence" >> return T.silence++genericComplexPatterns :: Pattern' a => Parser (Pattern a)+genericComplexPatterns = choice [+  (function "stack" >> return T.stack) <*> listPatternArg,+  (function "fastcat" >> return T.fastcat) <*> listPatternArg,+  (function "slowcat" >> return T.slowcat) <*> listPatternArg,+  (function "cat" >> return T.cat) <*> listPatternArg,+  (function "listToPat" >> return T.listToPat) <*> listLiteralArg,+  (function "fit" >> return T.fit) <*> literalArg <*> listLiteralArg <*> patternArg,+  (function "choose" >> return T.choose) <*> listLiteralArg,+  (function "randcat" >> return T.randcat) <*> listPatternArg,+  (function "cycleChoose" >> return T.cycleChoose) <*> listLiteralArg+  ]++enumComplexPatterns :: (Enum a, Num a, Pattern' a) => Parser (Pattern a)+enumComplexPatterns = choice [+  (function "run" >> return T.run) <*> patternArg,+  (function "scan" >> return T.scan) <*> patternArg+  ]++numComplexPatterns :: (Num a, Pattern' a) => Parser (Pattern a)+numComplexPatterns = choice [+  (function "irand" >> return T.irand) <*> literal,+  (function "toScale'" >> return T.toScale') <*> literalArg <*> listLiteralArg <*> patternArg,+  (function "toScale" >> return T.toScale) <*> listLiteralArg <*> patternArg+  ]++intComplexPatterns :: Parser (Pattern Int)+intComplexPatterns = choice [+  (function "randStruct" >> return T.randStruct) <*> literalArg+  ]++transformedPattern :: Pattern' a => Parser (Pattern a)+transformedPattern = (transformationWithArgs <|> transformationWithoutArgs) <*> patternArg++instance Pattern' ControlMap where+  simplePattern = choice []+  complexPattern = specificControlPatterns+  mergeOperator = controlPatternMergeOperator+  transformationWithArgs = controlPatternTransformation <|> patternTransformationWithArgs+  transformationWithoutArgs = patternTransformationWithoutArgs+  literal = choice []++controlPatternMergeOperator :: Parser (ControlPattern -> ControlPattern -> ControlPattern)+controlPatternMergeOperator = choice [+  op "#" >> return (T.#),+  op "|>" >> return (T.|>),+  op "<|" >> return (T.<|),+  op "|>|" >> return (T.|>|),+  op "|<|" >> return (T.|<),+  op "|+|" >> return (T.|+|),+  op "|-|" >> return (T.|-|),+  op "|*|" >> return (T.|*|),+  op "|/|" >> return (T.|/|)+  ]++specificControlPatterns :: Parser ControlPattern+specificControlPatterns = choice [+  (function "coarse" >> return T.coarse) <*> patternArg,+  (function "cut" >> return T.cut) <*> patternArg,+  (function "n" >> return T.n) <*> patternArg,+  (function "up" >> return T.up) <*> patternArg,+  (function "speed" >> return T.speed) <*> patternArg,+  (function "pan" >> return T.pan) <*> patternArg,+  (function "shape" >> return T.shape) <*> patternArg,+  (function "gain" >> return T.gain) <*> patternArg,+  (function "accelerate" >> return T.accelerate) <*> patternArg,+  (function "bandf" >> return T.bandf) <*> patternArg,+  (function "bandq" >> return T.bandq) <*> patternArg,+  (function "begin" >> return T.begin) <*> patternArg,+  (function "crush" >> return T.crush) <*> patternArg,+  (function "cutoff" >> return T.cutoff) <*> patternArg,+  (function "delayfeedback" >> return T.delayfeedback) <*> patternArg,+  (function "delaytime" >> return T.delaytime) <*> patternArg,+  (function "delay" >> return T.delay) <*> patternArg,+  (function "end" >> return T.end) <*> patternArg,+  (function "hcutoff" >> return T.hcutoff) <*> patternArg,+  (function "hresonance" >> return T.hresonance) <*> patternArg,+  (function "resonance" >> return T.resonance) <*> patternArg,+  (function "shape" >> return T.shape) <*> patternArg,+  (function "loop" >> return T.loop) <*> patternArg,+  (function "s" >> return T.s) <*> patternArg,+  (function "sound" >> return T.sound) <*> patternArg,+  (function "vowel" >> return T.vowel) <*> patternArg,+  (function "unit" >> return T.unit) <*> patternArg,+  (function "note" >> return T.note) <*> patternArg+  ]++controlPatternTransformation :: Parser (ControlPattern -> ControlPattern)+controlPatternTransformation = choice [+  function "chop" >> patternArg >>= return . T.chop,+  function "striate" >> patternArg >>= return . T.striate,+  (function "striate'" >> return T.striate') <*> patternArg <*> patternArg,+  (function "stut" >> return T.stut) <*> patternArg <*> patternArg <*> patternArg,+  function "jux" >> patternTransformationArg >>= return . T.jux+  ]++patternTransformationArg :: Pattern' a => Parser (Pattern a -> Pattern a)+patternTransformationArg = appliedOrNot transformationWithoutArgs <|> parensOrApplied transformationWithArgs++patternTransformationWithoutArgs :: Parser (Pattern a -> Pattern a)+patternTransformationWithoutArgs = choice [+  function "brak" >> return T.brak,+  function "rev" >> return T.rev,+  function "palindrome" >> return T.palindrome,+  function "stretch" >> return T.stretch,+  function "loopFirst" >> return T.loopFirst,+--  function "breakUp" >> return T.breakUp, -- removed from new Tidal?+  function "degrade" >> return T.degrade+  ]++patternTransformationWithArgs :: Pattern' a => Parser (Pattern a -> Pattern a)+patternTransformationWithArgs = parensOrNot $ choice [+  function "fast" >> patternArg >>= return . T.fast,+--  function "fast'" >> patternArg >>= return . T.fast', -- removed from Tidal 1.0?+  function "density" >> patternArg >>= return . T.density,+  function "slow" >> patternArg >>= return . T.slow,+  function "iter" >> patternArg >>= return . T.iter,+  function "iter'" >> patternArg >>= return . T.iter',+  function "trunc" >> patternArg >>= return . T.trunc,+  (function "swingBy" >> return T.swingBy) <*> patternArg <*> patternArg,+  (function "append" >> return T.append) <*> patternArg,+--  (function "append'" >> return T.append') <*> patternArg,+  (function "every" >> return T.every) <*> patternArg <*> patternTransformationArg,+  (function "every'" >> return T.every') <*> patternArg <*> patternArg <*> patternTransformationArg,+  (function "whenmod" >> return T.whenmod) <*> int <*> int <*> patternTransformationArg,+  (function "overlay" >> return T.overlay) <*> patternArg,+  (function "fastGap" >> return T.fastGap) <*> patternArg,+  (function "densityGap" >> return T.densityGap) <*> patternArg,+  (function "sparsity" >> return T.sparsity) <*> patternArg,+  (function "rotL" >> return T.rotL) <*> literalArg,+  (function "rotR" >> return T.rotR) <*> literalArg,+  (function "playFor" >> return T.playFor) <*> literalArg <*> literalArg,+  (function "foldEvery" >> return T.foldEvery) <*> listLiteralArg <*> patternTransformationArg,+  (function "superimpose" >> return T.superimpose) <*> patternTransformationArg,+  (function "trunc" >> return T.trunc) <*> patternArg,+  (function "linger" >> return T.linger) <*> patternArg,+  (function "zoom" >> return T.zoomArc) <*> literalArg,+  (function "compress" >> return T.compressArc) <*> literalArg,+--  (function "sliceArc" >> return T.sliceArc) <*> literalArg,+  (function "within" >> return T.withinArc) <*> literalArg <*> patternTransformationArg,+  --(function "within'" >> return T.within') <*> literalArg <*> patternTransformationArg,+  -- (function "revArc" >> return T.revArc) <*> literalArg,+  (function "euclid" >> return T.euclid) <*> patternArg <*> patternArg,+  (function "euclidFull" >> return T.euclidFull) <*> patternArg <*> patternArg <*> patternArg,+  (function "euclidInv" >> return T.euclidInv) <*> patternArg <*> patternArg,+  (function "distrib" >> return T.distrib) <*> listPatternArg,+  (function "wedge" >> return T.wedge) <*> literalArg <*> patternArg,+--  (function "prr" >> return T.prr) <*> literalArg <*> literalArg <*> patternArg,+--  (function "preplace" >> return T.preplace) <*> literalArg <*> patternArg,+--  (function "prep" >> return T.prep) <*> literalArg <*> patternArg,+--  (function "preplace1" >> return T.preplace1) <*> patternArg,+--  (function "protate" >> return T.protate) <*> literalArg <*> literalArg,+--  (function "prot" >> return T.prot) <*> literalArg <*> literalArg,+--  (function "prot1" >> return T.prot1) <*> literalArg,+  (function "discretise" >> return T.discretise) <*> patternArg,+  (function "segment" >> return T.segment) <*> patternArg,+  --(function "struct" >> return T.struct) <*> patternArg,+  (function "substruct" >> return T.substruct) <*> patternArg,+  (function "compressTo" >> return T.compressArcTo) <*> literalArg,+  (function "substruct'" >> return T.substruct') <*> patternArg,+  (function "slowstripe" >> return T.slowstripe) <*> patternArg,+  (function "fit'" >> return T.fit') <*> patternArg <*> literalArg <*> patternArg <*> patternArg,+  (function "chunk" >> return T.chunk) <*> literalArg <*> patternTransformationArg,+  (function "timeLoop" >> return T.timeLoop) <*> patternArg,+  (function "swing" >> return T.swing) <*> patternArg,+  (function "degradeBy" >> return T.degradeBy) <*> patternArg,+  (function "unDegradeBy" >> return T.unDegradeBy) <*> patternArg,+  (function "degradeOverBy" >> return T.degradeOverBy) <*> literalArg <*> patternArg,+  (function "sometimesBy" >> return T.sometimesBy) <*> patternArg <*> patternTransformationArg,+  (function "sometimes" >> return T.sometimes) <*> patternTransformationArg,+  (function "often" >> return T.often) <*> patternTransformationArg,+  (function "rarely" >> return T.rarely) <*> patternTransformationArg,+  (function "almostNever" >> return T.almostNever) <*> patternTransformationArg,+  (function "almostAlways" >> return T.almostAlways) <*> patternTransformationArg,+  (function "never" >> return T.never) <*> patternTransformationArg,+  (function "always" >> return T.always) <*> patternTransformationArg,+  (function "someCyclesBy" >> return T.someCyclesBy) <*> literalArg <*> patternTransformationArg,+  (function "somecyclesBy" >> return T.somecyclesBy) <*> literalArg <*> patternTransformationArg,+  (function "someCycles" >> return T.someCycles) <*> patternTransformationArg,+  (function "somecycles" >> return T.somecycles) <*> patternTransformationArg,+  (function "substruct'" >> return T.substruct') <*> patternArg,+  (function "repeatCycles" >> return T.repeatCycles) <*> literalArg,+  (function "spaceOut" >> return T.spaceOut) <*> listLiteralArg,+--  (function "fill" >> return T.fill) <*> patternArg, -- removed from tidal-1.0?+  (function "ply" >> return T.ply) <*> patternArg,+  (function "shuffle" >> return T.shuffle) <*> literalArg,+  (function "scramble" >> return T.scramble) <*> literalArg+  ]++simpleDoublePatterns :: Parser (Pattern Double)+simpleDoublePatterns = choice [+  function "rand" >> return T.rand,+  function "sine" >> return T.sine,+  function "saw" >> return T.saw,+  function "isaw" >> return T.isaw,+  function "tri" >> return T.tri,+  function "square" >> return T.square,+  function "cosine" >> return T.cosine+  ]++instance Pattern' Int where+  simplePattern = choice [+    parseBP',+    pure <$> int+    ]+  complexPattern = (atom <*> int) <|> enumComplexPatterns <|> numComplexPatterns <|> intComplexPatterns+  mergeOperator = numMergeOperator+  transformationWithoutArgs = patternTransformationWithoutArgs+  transformationWithArgs = patternTransformationWithArgs+  literal = int++instance Pattern' Integer where+  simplePattern = choice [+    parseBP',+    pure <$> integer+    ]+  complexPattern = (atom <*> integer) <|> enumComplexPatterns <|> numComplexPatterns+  mergeOperator = numMergeOperator+  transformationWithoutArgs = patternTransformationWithoutArgs+  transformationWithArgs = patternTransformationWithArgs+  literal = integer++instance Pattern' Double where+  simplePattern = choice [+    parseBP',+    try $ pure <$> double,+    simpleDoublePatterns+    ]+  complexPattern = (atom <*> double) <|> enumComplexPatterns <|> numComplexPatterns+  mergeOperator = numMergeOperator <|> fractionalMergeOperator+  transformationWithoutArgs = patternTransformationWithoutArgs+  transformationWithArgs = patternTransformationWithArgs+  literal = double++instance Pattern' Time where+  simplePattern = choice [+    parseBP',+    pure <$> literal+    ]+  complexPattern = atom <*> literal <|> numComplexPatterns+  mergeOperator = numMergeOperator <|> fractionalMergeOperator+  transformationWithoutArgs = patternTransformationWithoutArgs+  transformationWithArgs = patternTransformationWithArgs+  literal = choice [+    toRational <$> double,+    fromIntegral <$> integer+    ]++instance Pattern' Arc where+  simplePattern = pure <$> literal+  complexPattern = atom <*> literal+  mergeOperator = choice []+  transformationWithoutArgs = patternTransformationWithoutArgs+  transformationWithArgs = patternTransformationWithArgs+  literal = do+    xs <- parens (commaSep1 literal)+    if length xs == 2 then return (T.Arc (xs!!0) (xs!!1)) else unexpected "Arcs must contain exactly two values"++instance Pattern' String where+  simplePattern = parseBP'+  complexPattern = atom <*> stringLiteral+  mergeOperator = choice [] -- ??+  transformationWithoutArgs = patternTransformationWithoutArgs+  transformationWithArgs = patternTransformationWithArgs+  literal = stringLiteral++fractionalMergeOperator :: Fractional a => Parser (Pattern a -> Pattern a -> Pattern a)+fractionalMergeOperator = op "/" >> return (/)++numMergeOperator :: Num a => Parser (Pattern a -> Pattern a -> Pattern a)+numMergeOperator = choice [+  op "+" >> return (+),+  op "-" >> return (-),+  op "*" >> return (*)+  ]++atom :: Applicative m => Parser (a -> m a)+atom = (function "pure" <|> function "atom" <|> function "return") >> return (pure)++double :: Parser Double+double = choice [+  parens $ symbol "-" >> float >>= return . (* (-1)),+  parens double,+  try float,+  try $ fromIntegral <$> integer+  ]++int :: Parser Int+int = try $ parensOrNot $ fromIntegral <$> integer++function :: String -> Parser ()+function x = reserved x <|> try (parens (function x))++op :: String -> Parser ()+op x = reservedOp x <|> try (parens (op x))++parensOrNot :: Parser a -> Parser a+parensOrNot p = p <|> try (parens (parensOrNot p))++nestedParens :: Parser a -> Parser a+nestedParens p = try (parens p) <|> try (parens (nestedParens p))++applied :: Parser a -> Parser a+applied p = op "$" >> p++appliedOrNot :: Parser a -> Parser a+appliedOrNot p = applied p <|> p++parensOrApplied :: Parser a -> Parser a+parensOrApplied p = try (parens p) <|> try (applied p)++tokenParser :: P.TokenParser a+tokenParser = P.makeTokenParser $ haskellDef {+  P.reservedNames = ["chop","striate","striate'","stut","jux","brak","rev",+    "palindrome","fast","density","slow","iter","iter'","trunc","swingBy","every","whenmod",+    "append","append'","silence","s","sound","n","up","speed","vowel","pan","shape","gain",+    "accelerate","bandf","bandq","begin","coarse","crush","cut","cutoff","delayfeedback",+    "delaytime","delay","end","hcutoff","hresonance","loop","resonance","shape","unit",+    "sine","saw","isaw","fit","irand",+    "tri","square","rand",+    "pure","return","stack","fastcat","slowcat","cat","atom","overlay","run","scan","fast'",+    "fastGap","densityGap","sparsity","rotL","rotR","playFor","every'","foldEvery",+    "cosine","superimpose","trunc","linger","zoom","compress","sliceArc","within","within'",+    "revArc","euclid","euclidFull","euclidInv","distrib","wedge","prr","preplace","prep","preplace1",+    "protate","prot","prot1","discretise","segment","struct","substruct","compressTo",+    "substruct'","stripe","slowstripe","stretch","fit'","chunk","loopFirst","timeLoop","swing",+    "choose","degradeBy","unDegradeBy","degradeOverBy","sometimesBy","sometimes","often",+    "rarely","almostNever","almostAlways","never","always","someCyclesBy","somecyclesBy",+    "someCycles","somecycles","substruct'","repeatCycles","spaceOut","fill","ply","shuffle",+    "scramble","breakUp","degrade","randcat","randStruct","toScale'","toScale","cycleChoose",+    "d1","d2","d3","d4","d5","d6","d7","d8","d9","t1","t2","t3","t4","t5","t6","t7","t8","t9",+    "cps","xfadeIn","note"],+  P.reservedOpNames = ["+","-","*","/","<~","~>","#","|+|","|-|","|*|","|/|","$","\"","|>","<|","|>|","|<|"]+  }++{- Not currently in use+angles :: ParsecT String u Identity a -> ParsecT String u Identity a+angles = P.angles tokenParser+braces :: ParsecT String u Identity a -> ParsecT String u Identity a+braces = P.braces tokenParser+charLiteral :: ParsecT String u Identity Char+charLiteral = P.charLiteral tokenParser+colon :: ParsecT String u Identity String+colon = P.colon tokenParser+comma :: ParsecT String u Identity String+comma = P.comma tokenParser+decimal :: ParsecT String u Identity Integer+decimal = P.decimal tokenParser+dot :: ParsecT String u Identity String+dot = P.dot tokenParser+hexadecimal :: ParsecT String u Identity Integer+hexadecimal = P.hexadecimal tokenParser+identifier :: ParsecT String u Identity String+identifier = P.identifier tokenParser+lexeme :: ParsecT String u Identity a -> ParsecT String u Identity a+lexeme = P.lexeme tokenParser+naturalOrFloat :: ParsecT String u Identity (Either Integer Double)+naturalOrFloat = P.naturalOrFloat tokenParser+natural :: ParsecT String u Identity Integer+natural = P.natural tokenParser+octal :: ParsecT String u Identity Integer+octal = P.octal tokenParser+operator :: ParsecT String u Identity String+operator = P.operator tokenParser+semi :: ParsecT String u Identity String+semi = P.semi tokenParser+semiSep1 :: ParsecT String u Identity a -> ParsecT String u Identity [a]+semiSep1 = P.semiSep1 tokenParser+semiSep :: ParsecT String u Identity a -> ParsecT String u Identity [a]+semiSep = P.semiSep tokenParser+-}++brackets :: ParsecT String u Identity a -> ParsecT String u Identity a+brackets = P.brackets tokenParser+commaSep1 :: ParsecT String u Identity a -> ParsecT String u Identity [a]+commaSep1 = P.commaSep1 tokenParser+commaSep :: ParsecT String u Identity a -> ParsecT String u Identity [a]+commaSep = P.commaSep tokenParser+float :: ParsecT String u Identity Double+float = P.float tokenParser+integer :: ParsecT String u Identity Integer+integer = P.integer tokenParser+parens :: ParsecT String u Identity a -> ParsecT String u Identity a+parens = P.parens tokenParser+reservedOp :: String -> ParsecT String u Identity ()+reservedOp = P.reservedOp tokenParser+reserved :: String -> ParsecT String u Identity ()+reserved = P.reserved tokenParser+stringLiteral :: ParsecT String u Identity String+stringLiteral = P.stringLiteral tokenParser+symbol :: String -> ParsecT String u Identity String+symbol = P.symbol tokenParser+whiteSpace :: ParsecT String u Identity ()+whiteSpace = P.whiteSpace tokenParser++parseBP' :: (Enumerable a, Parseable a) => Parser (Pattern a)+parseBP' = parseTPat' >>= return . T.toPat++parseTPat' :: Parseable a => Parser (TPat a)+parseTPat' = parseRhythm' T.tPatParser++parseRhythm' :: Parseable a => Parser (TPat a) -> Parser (TPat a)+parseRhythm' f = do+  char '\"' >> whiteSpace+  x <- T.pSequence f'+  char '\"' >> whiteSpace+  return x+  where f' = f+             <|> do _ <- symbol "~" <?> "rest"+                    return T.TPat_Silence++miniTidalIO :: Stream -> String -> Either ParseError (IO ())+miniTidalIO tidal = parse (miniTidalIOParser tidal) "miniTidal"++miniTidalIOParser :: Stream -> Parser (IO ())+miniTidalIOParser tidal = whiteSpace >> choice [+  eof >> return (return ()),+  dParser tidal <*> patternArg+{-  tParser tidal <*> transitionArg tidal <*> patternArg, -}+--  (reserved "setcps" >> return (T.streamOnce tidal True . T.cps)) <*> literalArg+  ]++dParser :: Stream -> Parser (ControlPattern -> IO ())+dParser tidal = choice [+  reserved "d1" >> return (T.streamReplace tidal "1"),+  reserved "d2" >> return (T.streamReplace tidal "2"),+  reserved "d3" >> return (T.streamReplace tidal "3"),+  reserved "d4" >> return (T.streamReplace tidal "4"),+  reserved "d5" >> return (T.streamReplace tidal "5"),+  reserved "d6" >> return (T.streamReplace tidal "6"),+  reserved "d7" >> return (T.streamReplace tidal "7"),+  reserved "d8" >> return (T.streamReplace tidal "8"),+  reserved "d9" >> return (T.streamReplace tidal "9"),+  reserved "d10" >> return (T.streamReplace tidal "10"),+  reserved "d11" >> return (T.streamReplace tidal "11"),+  reserved "d12" >> return (T.streamReplace tidal "12"),+  reserved "d13" >> return (T.streamReplace tidal "13"),+  reserved "d14" >> return (T.streamReplace tidal "14"),+  reserved "d15" >> return (T.streamReplace tidal "15"),+  reserved "d16" >> return (T.streamReplace tidal "16")+  ]++{- tParser :: Stream -> Parser ((Time -> [ControlPattern] -> ControlPattern) -> ControlPattern -> IO ())+tParser tidal = choice [+  reserved "t1" >> return ((ts tidal)!!0),+  reserved "t2" >> return ((ts tidal)!!1),+  reserved "t3" >> return ((ts tidal)!!2),+  reserved "t4" >> return ((ts tidal)!!3),+  reserved "t5" >> return ((ts tidal)!!4),+  reserved "t6" >> return ((ts tidal)!!5),+  reserved "t7" >> return ((ts tidal)!!6),+  reserved "t8" >> return ((ts tidal)!!7),+  reserved "t9" >> return ((ts tidal)!!8)+  ] -}++{- transitionArg :: Stream -> Parser (Time -> [ControlPattern] -> ControlPattern)+transitionArg tidal = choice [+  parensOrApplied $ (reserved "xfadeIn" >> return (T.transition tidal . T.xfadeIn)) <*> literalArg+  ] -}++-- below is a stand-alone Tidal interpreter+-- can be compiled, for example, with: ghc --make Sound/Tidal/MiniTidal.hs -main-is Sound.Tidal.MiniTidal -o miniTidal++main :: IO ()+main = do+  putStrLn "miniTidal"+  tidal <- T.startTidal T.superdirtTarget T.defaultConfig+  forever $ do+    cmd <- miniTidalIO tidal <$> getLine+    either (\x -> putStrLn $ "error: " ++ show x) id cmd
+ src/Sound/Tidal/Params.hs view
@@ -0,0 +1,616 @@+module Sound.Tidal.Params where++import qualified Data.Map.Strict as Map++import Sound.Tidal.Pattern+import Sound.Tidal.Utils++-- | group multiple params into one+grp :: [String -> ControlMap] -> Pattern String -> ControlPattern+grp [] _ = empty+grp fs p = splitby <$> p+  where splitby name = Map.unions $ map (\(v, f) -> f v) $ zip (split name) fs+        split :: String -> [String]+        split = wordsBy (==':')++mF :: String -> String -> ControlMap+mF name v = Map.singleton name (VF $ read v)++mI :: String -> String -> ControlMap+mI name v = Map.singleton name (VI $ read v)++mS :: String -> String -> ControlMap+mS name v = Map.singleton name (VS v)++-- | Grouped params++sound :: Pattern String -> ControlPattern+sound = grp [mS "s", mF "n"]++s :: Pattern String -> ControlPattern+s = sound++cc :: Pattern String -> ControlPattern+cc = grp [mF "ccn", mF "ccv"]++-- | Singular params++pF :: String -> Pattern Double -> ControlPattern+pF name = fmap (Map.singleton name . VF)++pI :: String -> Pattern Int -> ControlPattern+pI name = fmap (Map.singleton name . VI)++pS :: String -> Pattern String -> ControlPattern+pS name = fmap (Map.singleton name . VS)++-- | a pattern of numbers that speed up (or slow down) samples while they play.+accelerate :: Pattern Double -> ControlPattern+accelerate       = pF "accelerate"++-- | a pattern of numbers to specify the attack time (in seconds) of an envelope applied to each sample. Only takes effect if `release` is also specified.+attack :: Pattern Double -> ControlPattern+attack = pF "attack"++-- | a pattern of numbers from 0 to 1. Sets the center frequency of the band-pass filter.+bandf :: Pattern Double -> ControlPattern+bandf = pF "bandf"++-- | a pattern of numbers from 0 to 1. Sets the q-factor of the band-pass filter.y+bandq :: Pattern Double -> ControlPattern+bandq = pF "bandq"++{- | a pattern of numbers from 0 to 1. Skips the beginning of each sample, e.g. `0.25` to cut off the first quarter from each sample.++Using `begin "-1"` combined with `cut "-1"` means that when the sample cuts itself it will begin playback from where the previous one left off, so it will sound like one seamless sample. This allows you to apply a synth param across a long sample in a way similar to `chop`:++@+cps 0.5++d1 $ sound "breaks125*8" # unit "c" # begin "-1" # cut "-1" # coarse "1 2 4 8 16 32 64 128"+@++This will play the `breaks125` sample and apply the changing `coarse` parameter over the sample. Compare to:++@+d1 $ (chop 8 $ sounds "breaks125") # unit "c" # coarse "1 2 4 8 16 32 64 128"+@++which performs a similar effect, but due to differences in implementation sounds different.+-}+begin, legato, clhatdecay, crush :: Pattern Double -> ControlPattern+channel, coarse :: Pattern Int -> ControlPattern+begin = pF "begin"+-- | choose the physical channel the pattern is sent to, this is super dirt specific+channel = pI "channel"++--legato controls the amount of overlap between two adjacent synth sounds+legato = pF "legato"++clhatdecay = pF "clhatdecay"+-- | fake-resampling, a pattern of numbers for lowering the sample rate, i.e. 1 for original 2 for half, 3 for a third and so on.+coarse = pI "coarse"+-- | bit crushing, a pattern of numbers from 1 (for drastic reduction in bit-depth) to 16 (for barely no reduction).+crush = pF "crush"+{- |+In the style of classic drum-machines, `cut` will stop a playing sample as soon as another samples with in same cutgroup is to be played.++An example would be an open hi-hat followed by a closed one, essentially muting the open.++@+d1 $ stack [+  sound "bd",+  sound "~ [~ [ho:2 hc/2]]" # cut "1"+  ]+@++This will mute the open hi-hat every second cycle when the closed one is played.++Using `cut` with negative values will only cut the same sample. This is useful to cut very long samples++@+d1 $ sound "[bev, [ho:3](3,8)]" # cut "-1"+@++Using `cut "0"` is effectively _no_ cutgroup.+-}+cut :: Pattern Int -> ControlPattern+cut = pI "cut"++-- | a pattern of numbers from 0 to 1. Applies the cutoff frequency of the low-pass filter.+cutoff :: Pattern Double -> ControlPattern+cutoff = pF "cutoff"++cutoffegint :: Pattern Double -> ControlPattern+cutoffegint = pF "cutoffegint"++decay :: Pattern Double -> ControlPattern+decay = pF "decay"+-- | a pattern of numbers from 0 to 1. Sets the level of the delay signal.+delay :: Pattern Double -> ControlPattern+delay = pF "delay"+-- | a pattern of numbers from 0 to 1. Sets the amount of delay feedback.+delayfeedback :: Pattern Double -> ControlPattern+delayfeedback = pF "delayfeedback"+-- | a pattern of numbers from 0 to 1. Sets the length of the delay.+delaytime :: Pattern Double -> ControlPattern+delaytime = pF "delaytime"+detune :: Pattern Double -> ControlPattern+detune = pF "detune"+-- | when set to `1` will disable all reverb for this pattern. See `room` and `size` for more information about reverb.+dry :: Pattern Double -> ControlPattern+dry = pF "dry"+{- the same as `begin`, but cuts the end off samples, shortening them;+ e.g. `0.75` to cut off the last quarter of each sample.+-}+end :: Pattern Double -> ControlPattern+end = pF "end"+-- | a pattern of numbers that specify volume. Values less than 1 make the sound quieter. Values greater than 1 make the sound louder.+gain :: Pattern Double -> ControlPattern+gain = pF "gain"+gate :: Pattern Double -> ControlPattern+gate = pF "gate"+hatgrain :: Pattern Double -> ControlPattern+hatgrain = pF "hatgrain"+-- | a pattern of numbers from 0 to 1. Applies the cutoff frequency of the high-pass filter.+hcutoff :: Pattern Double -> ControlPattern+hcutoff = pF "hcutoff"+-- | a pattern of numbers to specify the hold time (in seconds) of an envelope applied to each sample. Only takes effect if `attack` and `release` are also specified.+hold :: Pattern Double -> ControlPattern+hold = pF "hold"+-- | a pattern of numbers from 0 to 1. Applies the resonance of the high-pass filter.+hresonance :: Pattern Double -> ControlPattern+hresonance = pF "hresonance"+kriole :: Pattern Int -> ControlPattern+kriole = pI "kriole"+lagogo :: Pattern Double -> ControlPattern+lagogo = pF "lagogo"+lclap :: Pattern Double -> ControlPattern+lclap = pF "lclap"+lclaves :: Pattern Double -> ControlPattern+lclaves = pF "lclaves"+lclhat :: Pattern Double -> ControlPattern+lclhat = pF "lclhat"+lcrash :: Pattern Double -> ControlPattern+lcrash = pF "lcrash"+leslie :: Pattern Double -> ControlPattern+leslie = pF "leslie"+lrate :: Pattern Double -> ControlPattern+lrate = pF "lrate"+lsize :: Pattern Double -> ControlPattern+lsize = pF "lsize"+lfo :: Pattern Double -> ControlPattern+lfo = pF "lfo"+lfocutoffint :: Pattern Double -> ControlPattern+lfocutoffint = pF "lfocutoffint"+lfodelay :: Pattern Double -> ControlPattern+lfodelay = pF "lfodelay"+lfoint :: Pattern Double -> ControlPattern+lfoint = pF "lfoint"+lfopitchint :: Pattern Double -> ControlPattern+lfopitchint = pF "lfopitchint"+lfoshape :: Pattern Double -> ControlPattern+lfoshape = pF "lfoshape"+lfosync :: Pattern Double -> ControlPattern+lfosync = pF "lfosync"+lhitom :: Pattern Double -> ControlPattern+lhitom = pF "lhitom"+lkick :: Pattern Double -> ControlPattern+lkick = pF "lkick"+llotom :: Pattern Double -> ControlPattern+llotom = pF "llotom"+{- | A pattern of numbers. Specifies whether delaytime is calculated relative to cps. When set to 1, delaytime is a direct multiple of a cycle.+-}+lock :: Pattern Double -> ControlPattern+lock = pF "lock"+-- | loops the sample (from `begin` to `end`) the specified number of times.+loop :: Pattern Double -> ControlPattern+loop = pF "loop"+lophat :: Pattern Double -> ControlPattern+lophat = pF "lophat"+lsnare :: Pattern Double -> ControlPattern+lsnare = pF "lsnare"+-- | specifies the sample or note number to be used+n :: Pattern Double -> ControlPattern+n = pF "n"+note :: Pattern Double -> ControlPattern+note = pF "note"+{- |+Pushes things forward (or backwards within built-in latency) in time. Allows for nice things like _swing_ feeling:++@+d1 $ stack [+ sound "bd bd/4",+ sound "hh(5,8)"+ ] # nudge "[0 0.04]*4"+@++--pitch model -}++degree, mtranspose, ctranspose, harmonic, stepsPerOctave, octaveRatio :: Pattern Double -> ControlPattern+degree = pF "degree"+mtranspose = pF "mtranspose"+ctranspose = pF "ctranspose"+harmonic = pF "ctranspose"+stepsPerOctave = pF "stepsPerOctave"+octaveRatio = pF "octaveRatio"+++--Low values will give a more _human_ feeling, high values might result in quite the contrary.++nudge :: Pattern Double -> ControlPattern+nudge = pF "nudge"+octave :: Pattern Int -> ControlPattern+octave = pI "octave"+offset :: Pattern Double -> ControlPattern+offset = pF "offset"+ophatdecay :: Pattern Double -> ControlPattern+ophatdecay = pF "ophatdecay"+{- | a pattern of numbers. An `orbit` is a global parameter context for patterns. Patterns with the same orbit will share hardware output bus offset and global effects, e.g. reverb and delay. The maximum number of orbits is specified in the superdirt startup, numbers higher than maximum will wrap around.+-}+orbit :: Pattern Int -> ControlPattern+orbit = pI "orbit"+-- | a pattern of numbers between 0 and 1, from left to right (assuming stereo), once round a circle (assuming multichannel)+pan :: Pattern Double -> ControlPattern+pan = pF "pan"+-- | a pattern of numbers between -inf and inf, which controls how much multichannel output is fanned out (negative is backwards ordering)+panspan :: Pattern Double -> ControlPattern+panspan = pF "span"+-- | a pattern of numbers between 0.0 and 1.0, which controls the multichannel spread range (multichannel only)+pansplay :: Pattern Double -> ControlPattern+pansplay = pF "splay"+-- | a pattern of numbers between 0.0 and inf, which controls how much each channel is distributed over neighbours (multichannel only)+panwidth :: Pattern Double -> ControlPattern+panwidth = pF "panwidth"+-- | a pattern of numbers between -1.0 and 1.0, which controls the relative position of the centre pan in a pair of adjacent speakers (multichannel only)+panorient :: Pattern Double -> ControlPattern+panorient = pF "orientation"++pitch1 :: Pattern Double -> ControlPattern+pitch1 = pF "pitch1"+pitch2 :: Pattern Double -> ControlPattern+pitch2 = pF "pitch2"+pitch3 :: Pattern Double -> ControlPattern+pitch3 = pF "pitch3"+portamento :: Pattern Double -> ControlPattern+portamento = pF "portamento"+-- | a pattern of numbers to specify the release time (in seconds) of an envelope applied to each sample. Only takes effect if `attack` is also specified.+release :: Pattern Double -> ControlPattern+release = pF "release"+-- | a pattern of numbers from 0 to 1. Specifies the resonance of the low-pass filter.+resonance :: Pattern Double -> ControlPattern+resonance = pF "resonance"+-- | a pattern of numbers from 0 to 1. Sets the level of reverb.+room :: Pattern Double -> ControlPattern+room = pF "room"+sagogo :: Pattern Double -> ControlPattern+sagogo = pF "sagogo"+sclap :: Pattern Double -> ControlPattern+sclap = pF "sclap"+sclaves :: Pattern Double -> ControlPattern+sclaves = pF "sclaves"+scrash :: Pattern Double -> ControlPattern+scrash = pF "scrash"+semitone :: Pattern Double -> ControlPattern+semitone = pF "semitone"+-- | wave shaping distortion, a pattern of numbers from 0 for no distortion up to 1 for loads of distortion.+shape :: Pattern Double -> ControlPattern+shape = pF "shape"+-- | a pattern of numbers from 0 to 1. Sets the perceptual size (reverb time) of the `room` to be used in reverb.+size :: Pattern Double -> ControlPattern+size = pF "size"+slide :: Pattern Double -> ControlPattern+slide = pF "slide"+-- | a pattern of numbers which changes the speed of sample playback, i.e. a cheap way of changing pitch. Negative values will play the sample backwards!+speed :: Pattern Double -> ControlPattern+speed = pF "speed"+squiz :: Pattern Double -> ControlPattern+squiz = pF "squiz"+-- | a pattern of strings. Selects the sample to be played.+s' :: Pattern String -> ControlPattern+s' = pS "s"+stutterdepth :: Pattern Double -> ControlPattern+stutterdepth = pF "stutterdepth"+stuttertime :: Pattern Double -> ControlPattern+stuttertime = pF "stuttertime"+sustain :: Pattern Double -> ControlPattern+sustain = pF "sustain"+tomdecay :: Pattern Double -> ControlPattern+tomdecay = pF "tomdecay"+{- | used in conjunction with `speed`, accepts values of "r" (rate, default behavior), "c" (cycles), or "s" (seconds).+Using `unit "c"` means `speed` will be interpreted in units of cycles, e.g. `speed "1"` means samples will be stretched to fill a cycle.+Using `unit "s"` means the playback speed will be adjusted so that the duration is the number of seconds specified by `speed`.+-}+unit :: Pattern String -> ControlPattern+unit = pS "unit"+velocity :: Pattern Double -> ControlPattern+velocity = pF "velocity"+vcfegint :: Pattern Double -> ControlPattern+vcfegint = pF "vcfegint"+vcoegint :: Pattern Double -> ControlPattern+vcoegint = pF "vcoegint"+voice :: Pattern Double -> ControlPattern+voice = pF "voice"+-- | formant filter to make things sound like vowels, a pattern of either `a`, `e`, `i`, `o` or `u`. Use a rest (`~`) for no effect.+vowel :: Pattern String -> ControlPattern+vowel = pS "vowel"+waveloss :: Pattern Double -> ControlPattern+waveloss = pF "waveloss"++-- MIDI-specific params++dur :: Pattern Double -> ControlPattern+dur = pF "dur"+modwheel :: Pattern Double -> ControlPattern+modwheel = pF "modwheel"+expression :: Pattern Double -> ControlPattern+expression = pF "expression"+sustainpedal :: Pattern Double -> ControlPattern+sustainpedal = pF "sustainpedal"++-- Tremolo Audio DSP effect | params are "tremolorate" and "tremolodepth"+tremolorate, tremolodepth :: Pattern Double -> ControlPattern+tremolorate = pF "tremolorate"+tremolodepth = pF "tremolodepth"++-- Phaser Audio DSP effect | params are "phaserrate" and "phaserdepth"+phaserrate, phaserdepth :: Pattern Double -> ControlPattern+phaserrate = pF "phaserrate"+phaserdepth = pF "phaserdepth"++-- aliases+att, bpf, bpq, chdecay, ctf, ctfg, delayfb, delayt, det, gat, hg, hpf, hpq, lag, lbd, lch, lcl, lcp, lcr, lfoc, lfoi+   , lfop, lht, llt, loh, lpf, lpq, lsn, ohdecay, phasdp, phasr, pit1, pit2, pit3, por, rel, sz, sag, scl, scp+   , scr, sld, std, stt, sus, tdecay, tremdp, tremr, vcf, vco, voi+ :: Pattern Double -> ControlPattern+att = attack+bpf = bandf+bpq = bandq+chdecay = clhatdecay+ctf = cutoff+ctfg = cutoffegint+delayfb = delayfeedback+delayt = delaytime+det = detune+gat = gate+hg = hatgrain+hpf = hcutoff+hpq = hresonance+lag = lagogo+lbd = lkick+lch = lclhat+lcl = lclaves+lcp = lclap+lcr = lcrash+lfoc = lfocutoffint+lfoi = lfoint+lfop = lfopitchint+lht = lhitom+llt = llotom+loh = lophat+lpf = cutoff+lpq = resonance+lsn = lsnare+ohdecay = ophatdecay+phasdp = phaserdepth+phasr = phaserrate+pit1 = pitch1+pit2 = pitch2+pit3 = pitch3+por = portamento+rel = release+sag = sagogo+scl = sclaves+scp = sclap+scr = scrash+sz = size+sld = slide+std = stutterdepth+stt = stuttertime+sus = sustain+tdecay = tomdecay+tremdp = tremolodepth+tremr = tremolorate+vcf = vcfegint+vco = vcoegint+voi = voice++midinote :: Pattern Double -> ControlPattern+midinote = note . ((subtract 60) <$>)++drum :: Pattern String -> ControlPattern+drum = n . ((subtract 60) . drumN <$>)++drumN :: Num a => String -> a+drumN "bd" = 36+drumN "sn" = 38+drumN "lt" = 43+drumN "ht" = 50+drumN "ch" = 42+drumN "oh" = 46+drumN "cp" = 39+drumN "cl" = 75+drumN "ag" = 67+drumN "cr" = 49+drumN _ = 0+++-- SuperDirt MIDI Params++array :: Pattern Double -> ControlPattern+array = pF "array"+midichan :: Pattern Double -> ControlPattern+midichan = pF "midichan"+control :: Pattern Double -> ControlPattern+control = pF "control"++ccn :: Pattern Double -> ControlPattern+ccn = pF "ccn"+ccv :: Pattern Double -> ControlPattern+ccv = pF "ccv"++ctlNum :: Pattern Double -> ControlPattern+ctlNum = pF "ctlNum"++frameRate :: Pattern Double -> ControlPattern+frameRate = pF "frameRate"+frames :: Pattern Double -> ControlPattern+frames = pF "frames"+hours :: Pattern Double -> ControlPattern+hours = pF "hours"++midicmd :: Pattern String -> ControlPattern+midicmd = pS "midicmd"+command :: Pattern String -> ControlPattern+command = midicmd++minutes :: Pattern Double -> ControlPattern+minutes = pF "minutes"+progNum :: Pattern Double -> ControlPattern+progNum = pF "progNum"+seconds :: Pattern Double -> ControlPattern+seconds = pF "seconds"+songPtr :: Pattern Double -> ControlPattern+songPtr = pF "songPtr"+uid :: Pattern Double -> ControlPattern+uid = pF "uid"+val :: Pattern Double -> ControlPattern+val = pF "val"++{- | `up` is now an alias of `note`. -}+up :: Pattern Double -> ControlPattern+up = note++cps :: Pattern Double -> ControlPattern+cps = pF "cps"++-- generic names for mapping to e.g. midi controls+button0 :: Pattern Double -> ControlPattern+button0 = pF "button0"+button1 :: Pattern Double -> ControlPattern+button1 = pF "button1"+button2 :: Pattern Double -> ControlPattern+button2 = pF "button2"+button3 :: Pattern Double -> ControlPattern+button3 = pF "button3"+button4 :: Pattern Double -> ControlPattern+button4 = pF "button4"+button5 :: Pattern Double -> ControlPattern+button5 = pF "button5"+button6 :: Pattern Double -> ControlPattern+button6 = pF "button6"+button7 :: Pattern Double -> ControlPattern+button7 = pF "button7"+button8 :: Pattern Double -> ControlPattern+button8 = pF "button8"+button9 :: Pattern Double -> ControlPattern+button9 = pF "button9"+button10 :: Pattern Double -> ControlPattern+button10 = pF "button10"+button11 :: Pattern Double -> ControlPattern+button11 = pF "button11"+button12 :: Pattern Double -> ControlPattern+button12 = pF "button12"+button13 :: Pattern Double -> ControlPattern+button13 = pF "button13"+button14 :: Pattern Double -> ControlPattern+button14 = pF "button14"+button15 :: Pattern Double -> ControlPattern+button15 = pF "button15"+button16 :: Pattern Double -> ControlPattern+button16 = pF "button16"+button17 :: Pattern Double -> ControlPattern+button17 = pF "button17"+button18 :: Pattern Double -> ControlPattern+button18 = pF "button18"+button19 :: Pattern Double -> ControlPattern+button19 = pF "button19"+button20 :: Pattern Double -> ControlPattern+button20 = pF "button20"+button21 :: Pattern Double -> ControlPattern+button21 = pF "button21"+button22 :: Pattern Double -> ControlPattern+button22 = pF "button22"+button23 :: Pattern Double -> ControlPattern+button23 = pF "button23"+button24 :: Pattern Double -> ControlPattern+button24 = pF "button24"+button25 :: Pattern Double -> ControlPattern+button25 = pF "button25"+button26 :: Pattern Double -> ControlPattern+button26 = pF "button26"+button27 :: Pattern Double -> ControlPattern+button27 = pF "button27"+button28 :: Pattern Double -> ControlPattern+button28 = pF "button28"+button29 :: Pattern Double -> ControlPattern+button29 = pF "button29"+button30 :: Pattern Double -> ControlPattern+button30 = pF "button30"+button31 :: Pattern Double -> ControlPattern+button31 = pF "button31"++slider0 :: Pattern Double -> ControlPattern+slider0 = pF "slider0"+slider1 :: Pattern Double -> ControlPattern+slider1 = pF "slider1"+slider2 :: Pattern Double -> ControlPattern+slider2 = pF "slider2"+slider3 :: Pattern Double -> ControlPattern+slider3 = pF "slider3"+slider4 :: Pattern Double -> ControlPattern+slider4 = pF "slider4"+slider5 :: Pattern Double -> ControlPattern+slider5 = pF "slider5"+slider6 :: Pattern Double -> ControlPattern+slider6 = pF "slider6"+slider7 :: Pattern Double -> ControlPattern+slider7 = pF "slider7"+slider8 :: Pattern Double -> ControlPattern+slider8 = pF "slider8"+slider9 :: Pattern Double -> ControlPattern+slider9 = pF "slider9"+slider10 :: Pattern Double -> ControlPattern+slider10 = pF "slider10"+slider11 :: Pattern Double -> ControlPattern+slider11 = pF "slider11"+slider12 :: Pattern Double -> ControlPattern+slider12 = pF "slider12"+slider13 :: Pattern Double -> ControlPattern+slider13 = pF "slider13"+slider14 :: Pattern Double -> ControlPattern+slider14 = pF "slider14"+slider15 :: Pattern Double -> ControlPattern+slider15 = pF "slider15"+slider16 :: Pattern Double -> ControlPattern+slider16 = pF "slider16"+slider17 :: Pattern Double -> ControlPattern+slider17 = pF "slider17"+slider18 :: Pattern Double -> ControlPattern+slider18 = pF "slider18"+slider19 :: Pattern Double -> ControlPattern+slider19 = pF "slider19"+slider20 :: Pattern Double -> ControlPattern+slider20 = pF "slider20"+slider21 :: Pattern Double -> ControlPattern+slider21 = pF "slider21"+slider22 :: Pattern Double -> ControlPattern+slider22 = pF "slider22"+slider23 :: Pattern Double -> ControlPattern+slider23 = pF "slider23"+slider24 :: Pattern Double -> ControlPattern+slider24 = pF "slider24"+slider25 :: Pattern Double -> ControlPattern+slider25 = pF "slider25"+slider26 :: Pattern Double -> ControlPattern+slider26 = pF "slider26"+slider27 :: Pattern Double -> ControlPattern+slider27 = pF "slider27"+slider28 :: Pattern Double -> ControlPattern+slider28 = pF "slider28"+slider29 :: Pattern Double -> ControlPattern+slider29 = pF "slider29"+slider30 :: Pattern Double -> ControlPattern+slider30 = pF "slider30"+slider31 :: Pattern Double -> ControlPattern+slider31 = pF "slider31"
+ src/Sound/Tidal/ParseBP.hs view
@@ -0,0 +1,478 @@+{-# LANGUAGE OverloadedStrings, TypeSynonymInstances, FlexibleInstances, CPP #-}+{-# LANGUAGE LambdaCase #-}+{-# OPTIONS_GHC -Wall -fno-warn-orphans -fno-warn-unused-do-bind #-}++module Sound.Tidal.ParseBP where++import           Control.Applicative ((<$>), (<*>), pure)+import qualified Control.Exception as E+import           Data.Colour+import           Data.Colour.Names+import           Data.Functor.Identity (Identity)+import           Data.Maybe+import           Data.Ratio+import           Data.Typeable (Typeable)+import           GHC.Exts ( IsString(..) )+import           Text.Parsec.Error+import           Text.ParserCombinators.Parsec+import           Text.ParserCombinators.Parsec.Language ( haskellDef )+import qualified Text.ParserCombinators.Parsec.Token as P++import           Sound.Tidal.Pattern+import           Sound.Tidal.UI+import           Sound.Tidal.Core+import           Sound.Tidal.Chords (chordTable)++data TidalParseError = TidalParseError {parsecError :: ParseError,+                                        code :: String+                                       }+  deriving (Eq, Typeable)++instance E.Exception TidalParseError++instance Show TidalParseError where+  show err = "Syntax error in sequence:\n  \"" ++ code err ++ "\"\n  " ++ pointer ++ "  " ++ message+    where pointer = replicate (sourceColumn $ errorPos perr) ' ' ++ "^"+          message = showErrorMessages "or" "unknown parse error" "expecting" "unexpected" "end of input" $ errorMessages perr+          perr = parsecError err+++-- | AST representation of patterns++data TPat a = TPat_Atom a+            | TPat_Density (TPat Time) (TPat a)+            | TPat_Slow (TPat Time) (TPat a)+            | TPat_Zoom Arc (TPat a)+            | TPat_DegradeBy Double (TPat a)+            | TPat_Silence+            | TPat_Foot+            | TPat_Elongate Int+            | TPat_EnumFromTo (TPat a) (TPat a)+            | TPat_Cat [TPat a]+            | TPat_TimeCat [TPat a]+            | TPat_Overlay (TPat a) (TPat a)+            | TPat_Stack [TPat a]+            | TPat_ShiftL Time (TPat a)+              -- TPat_E Int Int (TPat a)+            | TPat_pE (TPat Int) (TPat Int) (TPat Int) (TPat a)+            deriving (Show)++toPat :: (Enumerable a, Parseable a) => TPat a -> Pattern a+toPat = \case+   TPat_Atom x -> pure x+   TPat_Density t x -> fast (toPat t) $ toPat x+   TPat_Slow t x -> slow (toPat t) $ toPat x+   TPat_Zoom a x -> zoomArc a $ toPat x+   TPat_DegradeBy amt x -> _degradeBy amt $ toPat x+   TPat_Silence -> silence+   TPat_Cat xs -> fastcat $ map toPat xs+   TPat_TimeCat xs -> timeCat $ map (\(n, pat) -> (toRational n, toPat pat)) $ durations xs+   TPat_Overlay x0 x1 -> overlay (toPat x0) (toPat x1)+   TPat_Stack xs -> stack $ map toPat xs+   TPat_ShiftL t x -> t `rotL` toPat x+   TPat_pE n k s thing ->+      doEuclid (toPat n) (toPat k) (toPat s) (toPat thing)+   TPat_Foot -> error "Can't happen, feet (.'s) only used internally.."+   TPat_EnumFromTo a b -> unwrap $ fromTo <$> (toPat a) <*> (toPat b)+   -- TPat_EnumFromThenTo a b c -> unwrap $ fromThenTo <$> (toPat a) <*> (toPat b) <*> (toPat c)+   _ -> silence++durations :: [TPat a] -> [(Int, TPat a)]+durations [] = []+durations ((TPat_Elongate n):xs) = (n, TPat_Silence):(durations xs)+durations (a:(TPat_Elongate n):xs) = (n+1,a):(durations xs)+durations (a:xs) = (1,a):(durations xs)++parseBP :: (Enumerable a, Parseable a) => String -> Either ParseError (Pattern a)+parseBP s = toPat <$> parseTPat s++parseBP_E :: (Enumerable a, Parseable a) => String -> Pattern a+parseBP_E s = toE parsed+  where+    parsed = parseTPat s+    -- TODO - custom error+    toE (Left e) = E.throw $ TidalParseError {parsecError = e, code = s}+    toE (Right tp) = toPat tp++parseTPat :: Parseable a => String -> Either ParseError (TPat a)+parseTPat = parseRhythm tPatParser++class Parseable a where+  tPatParser :: Parser (TPat a)+  doEuclid :: Pattern Int -> Pattern Int -> Pattern Int -> Pattern a -> Pattern a+  -- toEuclid :: a -> ++class Enumerable a where+  fromTo :: a -> a -> Pattern a+  fromThenTo :: a -> a -> a -> Pattern a++instance Parseable Double where+  tPatParser = pDouble+  doEuclid = euclidOff+  +instance Enumerable Double where+  fromTo a b = enumFromTo' a b+  fromThenTo a b c = enumFromThenTo' a b c++instance Parseable String where+  tPatParser = pVocable+  doEuclid = euclidOff++instance Enumerable String where+  fromTo a b = fastFromList [a,b]+  fromThenTo a b c = fastFromList [a,b,c]++instance Parseable Bool where+  tPatParser = pBool+  doEuclid = euclidOffBool++instance Enumerable Bool where+  fromTo a b = fastFromList [a,b]+  fromThenTo a b c = fastFromList [a,b,c]++instance Parseable Int where+  tPatParser = pIntegral+  doEuclid = euclidOff++instance Enumerable Int where+  fromTo a b = enumFromTo' a b+  fromThenTo a b c = enumFromThenTo' a b c++instance Parseable Integer where+  tPatParser = pIntegral+  doEuclid = euclidOff++instance Enumerable Integer where+  fromTo a b = enumFromTo' a b+  fromThenTo a b c = enumFromThenTo' a b c++instance Parseable Rational where+  tPatParser = pRational+  doEuclid = euclidOff++instance Enumerable Rational where+  fromTo a b = enumFromTo' a b+  fromThenTo a b c = enumFromThenTo' a b c++enumFromTo' :: (Ord a, Enum a) => a -> a -> Pattern a+enumFromTo' a b | a > b = fastFromList $ reverse $ enumFromTo b a+                | otherwise = fastFromList $ enumFromTo a b++enumFromThenTo'+  :: (Ord a, Enum a, Num a) => a -> a -> a -> Pattern a+enumFromThenTo' a b c | a > c = fastFromList $ reverse $ enumFromThenTo c (c + (a-b)) a+                      | otherwise = fastFromList $ enumFromThenTo a b c++type ColourD = Colour Double++instance Parseable ColourD where+  tPatParser = pColour+  doEuclid = euclidOff++instance Enumerable ColourD where+  fromTo a b = fastFromList [a,b]+  fromThenTo a b c = fastFromList [a,b,c]++instance (Enumerable a, Parseable a) => IsString (Pattern a) where+  fromString = parseBP_E++--instance (Parseable a, Pattern p) => IsString (p a) where+--  fromString = p :: String -> p a++lexer :: P.GenTokenParser String u Data.Functor.Identity.Identity+lexer   = P.makeTokenParser haskellDef++braces, brackets, parens, angles:: Parser a -> Parser a+braces  = P.braces lexer+brackets = P.brackets lexer+parens = P.parens lexer+angles = P.angles lexer++symbol :: String -> Parser String+symbol  = P.symbol lexer++natural, integer :: Parser Integer+natural = P.natural lexer+integer = P.integer lexer++float :: Parser Double+float = P.float lexer++naturalOrFloat :: Parser (Either Integer Double)+naturalOrFloat = P.naturalOrFloat lexer++data Sign      = Positive | Negative++applySign          :: Num a => Sign -> a -> a+applySign Positive =  id+applySign Negative =  negate++sign  :: Parser Sign+sign  =  do char '-'+            return Negative+         <|> do char '+'+                return Positive+         <|> return Positive++intOrFloat :: Parser Double+intOrFloat =  do s   <- sign+                 num <- naturalOrFloat+                 return (case num of+                            Right x -> applySign s x+                            Left  x -> fromIntegral $ applySign s x+                        )++{-+r :: (Enumerable a, Parseable a) => String -> Pattern a -> IO (Pattern a)+r s orig = do E.handle+                (\err -> do putStrLn (show (err :: E.SomeException))+                            return orig+                )+                (return $ p s)+-}++parseRhythm :: Parseable a => Parser (TPat a) -> String -> Either ParseError (TPat a)+parseRhythm f input = parse (pSequence f') "" input+  where f' = f+             <|> do symbol "~" <?> "rest"+                    return TPat_Silence++pSequenceN :: Parseable a => Parser (TPat a) -> GenParser Char () (Int, TPat a)+pSequenceN f = do spaces+                  -- d <- pDensity+                  ps <- many $ do a <- pPart f+                                  do Text.ParserCombinators.Parsec.try $ symbol ".."+                                     b <- pPart f+                                     return [TPat_EnumFromTo (TPat_Cat a) (TPat_Cat b)]+                                    <|> return a+                               <|> do symbol "."+                                      return [TPat_Foot]+                               <|> do es <- many1 (symbol "_")+                                      return [TPat_Elongate (length es)]+                  let ps' = TPat_Cat $ map elongate $ splitFeet $ concat ps+                  return (length ps, ps')++elongate :: [TPat a] -> TPat a+elongate xs | any (isElongate) xs = TPat_TimeCat xs+            | otherwise = TPat_Cat xs+  where isElongate (TPat_Elongate _) = True+        isElongate _ = False+{-+expandEnum :: Parseable t => Maybe (TPat t) -> [TPat t] -> [TPat t]+expandEnum a [] = [a]+expandEnum (Just a) (TPat_Enum:b:ps) = (TPat_EnumFromTo a b) : (expandEnum Nothing ps)+-- ignore ..s in other places+expandEnum a (TPat_Enum:ps) = expandEnum a ps+expandEnum (Just a) (b:ps) = a:(expandEnum b (Just c) ps)+expandEnum Nothing (c:ps) = expandEnum (Just c) ps+-}++-- could use splitOn here but `TPat a` isn't a member of `EQ`..+splitFeet :: [TPat t] -> [[TPat t]]+splitFeet [] = []+splitFeet pats = foot:(splitFeet pats')+  where (foot, pats') = takeFoot pats+        takeFoot [] = ([], [])+        takeFoot (TPat_Foot:pats'') = ([], pats'')+        takeFoot (pat:pats'') = (\(a,b) -> (pat:a,b)) $ takeFoot pats''++pSequence :: Parseable a => Parser (TPat a) -> GenParser Char () (TPat a)+pSequence f = do (_, pat) <- pSequenceN f+                 return pat++pSingle :: Parser (TPat a) -> Parser (TPat a)+pSingle f = f >>= pRand >>= pMult++pPart :: Parseable a => Parser (TPat a) -> Parser [TPat a]+pPart f = do pt <- pSingle f <|> pPolyIn f <|> pPolyOut f+             pt' <- pE pt+             pt'' <- pRand pt'+             spaces+             pts <- pStretch pt+                    <|> pReplicate pt''+             spaces+             return $ pts++pPolyIn :: Parseable a => Parser (TPat a) -> Parser (TPat a)+pPolyIn f = do ps <- brackets (pSequence f `sepBy` symbol ",")+               spaces+               pMult $ TPat_Stack ps++pPolyOut :: Parseable a => Parser (TPat a) -> Parser (TPat a)+pPolyOut f = do ps <- braces (pSequenceN f `sepBy` symbol ",")+                spaces+                base <- do char '%'+                           spaces+                           i <- integer <?> "integer"+                           return $ Just (fromIntegral i)+                        <|> return Nothing+                pMult $ TPat_Stack $ scale' base ps+             <|>+             do ps <- angles (pSequenceN f `sepBy` symbol ",")+                spaces+                pMult $ TPat_Stack $ scale' (Just 1) ps+  where scale' _ [] = []+        scale' base (pats@((n,_):_)) = map (\(n',pat) -> TPat_Density (TPat_Atom $ fromIntegral (fromMaybe n base)/ fromIntegral n') pat) pats++pString :: Parser (String)+pString = do c <- (letter <|> oneOf "0123456789") <?> "charnum"+             cs <- many (letter <|> oneOf "0123456789:.-_") <?> "string"+             return (c:cs)++pVocable :: Parser (TPat String)+pVocable = do v <- pString+              return $ TPat_Atom v++pDouble :: Parser (TPat Double)+pDouble = do f <- choice [intOrFloat, parseNote] <?> "float"+             do c <- parseChord+                return $ TPat_Stack $ map (TPat_Atom . (+f)) c+               <|> return (TPat_Atom f)+            <|>+               do c <- parseChord+                  return $ TPat_Stack $ map TPat_Atom c+++pBool :: Parser (TPat Bool)+pBool = do oneOf "t1"+           return $ TPat_Atom True+        <|>+        do oneOf "f0"+           return $ TPat_Atom False++parseIntNote  :: Integral i => Parser i+parseIntNote = do s <- sign+                  i <- choice [integer, parseNote]+                  return $ applySign s $ fromIntegral i++parseInt :: Parser Int+parseInt = do s <- sign+              i <- integer+              return $ applySign s $ fromIntegral i++pIntegral :: Integral a => Parser (TPat a)+pIntegral = do i <- parseIntNote+               do c <- parseChord+                  return $ TPat_Stack $ map (TPat_Atom . (+i)) c+                 <|> return (TPat_Atom i)+            <|>+               do c <- parseChord+                  return $ TPat_Stack $ map TPat_Atom c++parseChord :: Num a => Parser [a]+parseChord = do char '\''+                name <- many1 $ letter <|> digit+                return $ fromMaybe [0] $ lookup name chordTable++parseNote :: Num a => Parser a+parseNote = do n <- notenum+               modifiers <- many noteModifier+               octave <- option 5 natural+               let n' = foldr (+) n modifiers+               return $ fromIntegral $ n' + ((octave-5)*12)+  where+        notenum :: Parser Integer+        notenum = choice [char 'c' >> return 0,+                          char 'd' >> return 2,+                          char 'e' >> return 4,+                          char 'f' >> return 5,+                          char 'g' >> return 7,+                          char 'a' >> return 9,+                          char 'b' >> return 11+                         ]+        noteModifier :: Parser Integer+        noteModifier = choice [char 's' >> return 1,+                               char 'f' >> return (-1),+                               char 'n' >> return 0+                              ]++fromNote :: Num a => Pattern String -> Pattern a+fromNote pat = (\s -> either (const 0) id $ parse parseNote "" s) <$> pat++pColour :: Parser (TPat ColourD)+pColour = do name <- many1 letter <?> "colour name"+             colour <- readColourName name <?> "known colour"+             return $ TPat_Atom colour++pMult :: TPat a -> Parser (TPat a)+pMult thing = do char '*'+                 spaces+                 r <- (pRational <|> pPolyIn pRational  <|> pPolyOut pRational)+                 return $ TPat_Density r thing+              <|>+              do char '/'+                 spaces+                 r <- (pRational <|> pPolyIn pRational  <|> pPolyOut pRational)+                 return $ TPat_Slow r thing+              <|>+              return thing++++pRand :: TPat a -> Parser (TPat a)+pRand thing = do char '?'+                 spaces+                 return $ TPat_DegradeBy 0.5 thing+              <|> return thing++pE :: TPat a -> Parser (TPat a)+pE thing = do (n,k,s) <- parens (pair)+              pure $ TPat_pE n k s thing+            <|> return thing+   where pair :: Parser (TPat Int, TPat Int, TPat Int)+         pair = do a <- pSequence pIntegral+                   spaces+                   symbol ","+                   spaces+                   b <- pSequence pIntegral+                   c <- do symbol ","+                           spaces+                           pSequence pIntegral+                        <|> return (TPat_Atom 0)+                   return (a, b, c)++pReplicate :: TPat a -> Parser [TPat a]+pReplicate thing =+  do extras <- many $ do char '!'+                         -- if a number is given (without a space)slow 2 $ fast+                         -- replicate that number of times+                         n <- ((read <$> many1 digit) <|> return (2 :: Int))+                         spaces+                         thing' <- pRand thing+                         -- -1 because we already have parsed the original one+                         return $ replicate (fromIntegral (n-1)) thing'+     return (thing:concat extras)++pStretch :: TPat a -> Parser [TPat a]+pStretch thing =+  do char '@'+     n <- ((read <$> many1 digit) <|> return 1)+     return $ map (\x -> TPat_Zoom (Arc (x%n) ((x+1)%n)) thing) [0 .. (n-1)]++pRatio :: Parser (Rational)+pRatio = do s <- sign+            n <- natural+            result <- do char '%'+                         d <- natural+                         return (n%d)+                      <|>+                      do char '.'+                         frac <- many1 digit+                         -- A hack, but not sure if doing this+                         -- numerically would be any faster..+                         return (toRational $ ((read $ show n ++ "." ++ frac)  :: Double))+                      <|>+                      return (n%1)+            return $ applySign s result++pRational :: Parser (TPat Rational)+pRational = do r <- pRatio+               return $ TPat_Atom r++{-+pDensity :: Parser (Rational)+pDensity = angles (pRatio <?> "ratio")+           <|>+           return (1 % 1)+-}+
+ src/Sound/Tidal/Pattern.hs view
@@ -0,0 +1,727 @@+{-# LANGUAGE DeriveDataTypeable, TypeSynonymInstances, FlexibleInstances #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE DeriveFunctor #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}++module Sound.Tidal.Pattern where++import           Prelude hiding ((<*), (*>))++import           Control.Applicative (liftA2)+import           Data.Bifunctor (Bifunctor(..))+import           Data.Data (Data) -- toConstr+import           Data.List (delete, findIndex, sort, intercalate)+import qualified Data.Map.Strict as Map+import           Data.Maybe (isJust, fromJust, catMaybes, fromMaybe)+import           Data.Ratio (numerator, denominator)+import           Data.Typeable (Typeable)++------------------------------------------------------------------------+-- * Types++-- | Time is rational+type Time = Rational++-- | The 'sam' (start of cycle) for the given time value+sam :: Time -> Time+sam = fromIntegral . (floor :: Time -> Int)++-- | Turns a number into a (rational) time value. An alias for 'toRational'.+toTime :: Real a => a -> Rational+toTime = toRational++-- | The end point of the current cycle (and starting point of the next cycle)+nextSam :: Time -> Time+nextSam = (1+) . sam++-- | The position of a time value relative to the start of its cycle.+cyclePos :: Time -> Time+cyclePos t = t - sam t++-- | An arc of time, with a start time (or onset) and a stop time (or offset)+data ArcF a = Arc+  { start :: a+  , stop :: a+  } deriving (Eq, Ord, Functor)++type Arc = ArcF Time++instance {-# OVERLAPPING #-} Show Arc where+  show (Arc s e) = prettyRat s ++ ">" ++ prettyRat e++instance Num a => Num (ArcF a) where+  negate      = fmap negate+  (+)         = liftA2 (+)+  (*)         = liftA2 (*)+  fromInteger = pure . fromInteger+  abs         = fmap abs+  signum      = fmap signum++instance (Fractional a) => Fractional (ArcF a) where+  recip        = fmap recip+  fromRational = pure . fromRational++sect :: Arc -> Arc -> Arc+sect (Arc s e) (Arc s' e') = Arc (max s s') (min e e')++-- | convex hull union+hull :: Arc -> Arc -> Arc+hull (Arc s e) (Arc s' e') = Arc (min s s') (max e e')++-- | @subArc i j@ is the timespan that is the intersection of @i@ and @j@.+-- intersection+-- The definition is a bit fiddly as results might be zero-width, but+-- not at the end of an non-zero-width arc - e.g. (0,1) and (1,2) do+-- not intersect, but (1,1) (1,1) does.+subArc :: Arc -> Arc -> Maybe Arc+subArc a@(Arc s e) b@(Arc s' e')+  | and [s'' == e'', s'' == e, s < e] = Nothing+  | and [s'' == e'', s'' == e', s' < e'] = Nothing+  | s'' <= e'' = Just (Arc s'' e'')+  | otherwise = Nothing+  where (Arc s'' e'') = sect a b++instance Applicative ArcF where+  pure t = Arc t t+  (<*>) (Arc sf ef) (Arc sx ex) = Arc (sf sx) (ef ex)++-- | The arc of the whole cycle that the given time value falls within+timeToCycleArc :: Time -> Arc+timeToCycleArc t = (Arc (sam t) ((sam t) + 1))++-- | A list of cycle numbers which are included in the given arc+cyclesInArc :: Integral a => Arc -> [a]+cyclesInArc (Arc s e)+  | s > e = []+  | s == e = [floor s]+  | otherwise = [floor s .. (ceiling e)-1]++-- | A list of arcs of the whole cycles which are included in the given arc+cycleArcsInArc :: Arc -> [Arc]+cycleArcsInArc = map (timeToCycleArc . (toTime :: Int -> Time)) . cyclesInArc++-- | Splits the given 'Arc' into a list of 'Arc's, at cycle boundaries.+arcCycles :: Arc -> [Arc]+arcCycles (Arc s e) | s >= e = []+                | sam s == sam e = [Arc s e]+                | otherwise = (Arc s (nextSam s)) : (arcCycles (Arc (nextSam s) e))++-- | Like arcCycles, but returns zero-width arcs+arcCyclesZW :: Arc -> [Arc]+arcCyclesZW (Arc s e) | s == e = [Arc s e]+                  | otherwise = arcCycles (Arc s e)++-- | Similar to 'fmap' but time is relative to the cycle (i.e. the+-- sam of the start of the arc)+mapCycle :: (Time -> Time) -> Arc -> Arc+mapCycle f (Arc s e) = Arc (sam' + (f $ s - sam')) (sam' + (f $ e - sam'))+         where sam' = sam s++-- | @isIn a t@ is @True@ if @t@ is inside+-- the arc represented by @a@.+isIn :: Arc -> Time -> Bool+isIn (Arc s e) t = t >= s && t < e++-- | An event is a value that's active during a timespan+-- The part should be equal to or fit inside the+-- whole+data EventF a b = Event+  { whole :: a+  , part :: a+  , value :: b+  } deriving (Eq, Ord, Functor)++type Event a = EventF (ArcF Time) a++instance Bifunctor EventF where+  bimap f g (Event w p e) = (Event (f w) (f p) (g e))++instance {-# OVERLAPPING #-} Show a => Show (Event a) where+  show (Event (Arc ws we) a@(Arc ps pe) e) =+    h ++ "(" ++ show a ++ ")" ++ t ++ "|" ++ show e+    where h | ws == ps = ""+            | otherwise = prettyRat ws ++ "-"+          t | we == pe = ""+            | otherwise = "-" ++ prettyRat we++-- | `True` if an `Event`'s starts is within given `Arc`+onsetIn :: Arc -> Event a -> Bool+onsetIn a e = isIn a (wholeStart e)++-- | Compares two lists of events, attempting to combine fragmented events in the process+-- for a 'truer' compare+compareDefrag :: (Ord a) => [Event a] -> [Event a] -> Bool+compareDefrag as bs = (sort $ defragParts as) == (sort $ defragParts bs)++-- | Returns a list of events, with any adjacent parts of the same whole combined+defragParts :: Eq a => [Event a] -> [Event a]+defragParts [] = []+defragParts (e:[]) = (e:[])+defragParts (e:es) | isJust i = defraged:(defragParts (delete e' es))+                   | otherwise = e:(defragParts es)+  where i = findIndex (isAdjacent e) es+        e' = es !! (fromJust i)+        defraged = Event (whole e) u (value e)+        u = hull (part e) (part e')++-- | Returns 'True' if the two given events are adjacent parts of the same whole+isAdjacent :: Eq a => Event a -> Event a -> Bool+isAdjacent e e' = (whole e == whole e')+                  && (value e == value e')+                  && (((stop $ part e) == (start $ part e'))+                      ||+                      ((stop $ part e') == (start $ part e))+                     )++-- | Get the onset of an event's 'whole'+wholeStart :: Event a -> Time+wholeStart = start . whole++-- | Get the offset of an event's 'whole'+wholeStop :: Event a -> Time+wholeStop = stop . whole++-- | Get the onset of an event's 'whole'+eventPartStart :: Event a -> Time+eventPartStart = start . part++-- | Get the offset of an event's 'part'+eventPartStop :: Event a -> Time+eventPartStop = stop . part++-- | Get the timespan of an event's 'part'+eventPart :: Event a -> Arc+eventPart = part++eventValue :: Event a -> a+eventValue = value++eventHasOnset :: Event a -> Bool+eventHasOnset e = (start $ whole e) == (start $ part e)++toEvent :: (((Time, Time), (Time, Time)), a) -> Event a+toEvent (((ws, we), (ps, pe)), v) = Event (Arc ws we) (Arc ps pe) v++-- | an Arc and some named control values+data State = State {arc :: Arc,+                    controls :: ControlMap+                   }++-- | A function that represents events taking place over time+type Query a = (State -> [Event a])++-- | Also known as Continuous vs Discrete/Amorphous vs Pulsating etc.+data Nature = Analog | Digital+            deriving Eq++-- | A datatype that's basically a query, plus a hint about whether its events+-- are Analogue or Digital by nature+data Pattern a = Pattern {nature :: Nature, query :: Query a}++data Value = VS { svalue :: String }+           | VF { fvalue :: Double }+           | VI { ivalue :: Int }+           deriving (Eq,Ord,Typeable,Data)++type ControlMap = Map.Map String Value+type ControlPattern = Pattern ControlMap++------------------------------------------------------------------------+-- * Instances++instance Functor Pattern where+  -- | apply a function to all the values in a pattern+  fmap f p = p {query = (fmap (fmap f)) . query p}++instance Applicative Pattern where+  -- | Repeat the given value once per cycle, forever+  pure v = Pattern Digital $ \(State a _) ->+    map (\a' -> Event a' (sect a a') v) $ cycleArcsInArc a++  (<*>) pf@(Pattern Digital _) px@(Pattern Digital _) = Pattern Digital q+    where q st = catMaybes $ concat $ map match $ query pf st+            where+              match (Event fWhole fPart f) =+                map+                (\(Event xWhole xPart x) ->+                  do whole' <- subArc xWhole fWhole+                     part' <- subArc fPart xPart+                     return (Event whole' part' (f x))+                )+                (query px $ st {arc = fPart})+  (<*>) pf@(Pattern Digital _) px@(Pattern Analog _) = Pattern Digital q+    where q st = concatMap match $ query pf st+            where+              match (Event fWhole fPart f) =+                map+                (\e -> (Event fWhole fPart (f (value e))))+                (query px $ st {arc = pure (start fPart)})++  (<*>) pf@(Pattern Analog _) px@(Pattern Digital _) = Pattern Digital q+    where q st = concatMap match $ query px st+            where+              match (Event xWhole xPart x) =+                map+                (\e -> (Event xWhole xPart ((value e) x)))+                (query pf st {arc = (pure (start xPart))})++  (<*>) pf px = Pattern Analog q+    where q st = concatMap match $ query pf st+            where+              match ef =+                map+                (\ex -> (Event (arc st) (arc st) ((value ef) (value ex))))+                (query px st)++-- | Like <*>, but the structure only comes from the left+(<*) :: Pattern (a -> b) -> Pattern a -> Pattern b+(<*) pf@(Pattern Digital _) px = Pattern Digital q+  where q st = concatMap match $ query pf st+         where+            match (Event fWhole fPart f) =+              map+              (\e -> (Event fWhole fPart (f (value e)))) $+              query px $ st {arc = xQuery fWhole}+            xQuery (Arc s _) = pure s -- for discrete events, match with the onset++pf <* px = Pattern Analog q+  where q st = concatMap match $ query pf st+          where+            match (Event fWhole fPart f) =+              map+              (\e -> (Event fWhole fPart (f (value e)))) $+              query px st -- for continuous events, use the original query++-- | Like <*>, but the structure only comes from the right+(*>) :: Pattern (a -> b) -> Pattern a -> Pattern b+(*>) pf px@(Pattern Digital _) = Pattern Digital q+  where q st = concatMap match $ query px st+         where+            match (Event xWhole xPart x) =+              map+              (\e -> (Event xWhole xPart ((value e) x))) $+              query pf $ fQuery xWhole+            fQuery (Arc s _) = st {arc = pure s} -- for discrete events, match with the onset++pf *> px = Pattern Analog q+  where q st = concatMap match $ query px st+          where+            match (Event xWhole xPart x) =+              map+              (\e -> (Event xWhole xPart ((value e) x))) $+              query pf st -- for continuous events, use the original query++infixl 4 <*, *>++instance Monad Pattern where+  return = pure+  p >>= f = unwrap (f <$> p)++-- | Turns a pattern of patterns into a single pattern.+-- (this is actually 'join')+--+-- 1/ For query 'arc', get the events from the outer pattern @pp@+-- 2/ Query the inner pattern using the 'part' of the outer+-- 3/ For each inner event, set the whole and part to be the intersection+--    of the outer whole and part, respectively+-- 4/ Concatenate all the events together (discarding wholes/parts that didn't intersect)+--+-- TODO - what if a continuous pattern contains a discrete one, or vice-versa?+unwrap :: Pattern (Pattern a) -> Pattern a+unwrap pp = pp {query = q}+  where q st = concatMap+          (\(Event w p v) ->+             catMaybes $+             map (munge w p) $+             query v st {arc = p})+          (query pp st)+        munge ow op (Event iw ip v') =+          do+            w' <- subArc ow iw+            p' <- subArc op ip+            return (Event w' p' v')++-- | Turns a pattern of patterns into a single pattern. Like @unwrap@,+-- but structure only comes from the inner pattern.+innerJoin :: Pattern (Pattern a) -> Pattern a+innerJoin pp = pp {query = q}+  where q st = concatMap+          (\(Event _ p v) ->+              catMaybes $+              map munge $+              query v st {arc = p})+          (query pp st)+          where munge (Event iw ip v) =+                  do+                    p <- subArc (arc st) ip+                    p' <- subArc p (arc st)+                    return (Event iw p' v)++-- | Turns a pattern of patterns into a single pattern. Like @unwrap@,+-- but structure only comes from the outer pattern.+outerJoin :: Pattern (Pattern a) -> Pattern a+outerJoin pp = pp {query = q}+  where q st = concatMap+          (\(Event w p v) ->+             catMaybes $+             map (munge w p) $+             query v st {arc = (pure (start w))})+          (query pp st)+          where munge ow op (Event _ _ v') =+                  do+                    p' <- subArc (arc st) op+                    return (Event ow p' v')++-- | Like @unwrap@, but cycles of the inner patterns are compressed to fit the+-- timespan of the outer whole (or the original query if it's a continuous pattern?)+-- TODO - what if a continuous pattern contains a discrete one, or vice-versa?+unwrapSqueeze :: Pattern (Pattern a) -> Pattern a+unwrapSqueeze pp = pp {query = q}+  where q st = concatMap+          (\(Event w p v) ->+             catMaybes $+             map (munge w p) $+             query (compressArc w v) st {arc = p})+          (query pp st)+        munge oWhole oPart (Event iWhole iPart v) =+          do w' <- subArc oWhole iWhole+             p' <- subArc oPart iPart+             return (Event w' p' v)++noOv :: String -> a+noOv meth = error $ meth ++ ": not supported for patterns"++class TolerantEq a where+   (~==) :: a -> a -> Bool++instance TolerantEq Value where+         (VS a) ~== (VS b) = a == b+         (VI a) ~== (VI b) = a == b+         (VF a) ~== (VF b) = (abs (a - b)) < 0.000001+         _ ~== _ = False++instance TolerantEq ControlMap where+  a ~== b = (Map.differenceWith (\a' b' -> if a' ~== b' then Nothing else Just a') a b) == Map.empty++instance TolerantEq (Event ControlMap) where+  (Event w p x) ~== (Event w' p' x') = w == w' && p == p' && x ~== x'++instance TolerantEq a => TolerantEq ([a]) where+  as ~== bs = (length as == length bs) && (and $ map (\(a,b) -> a ~== b) $ zip as bs)++instance Eq (Pattern a) where+  (==) = noOv "(==)"++instance Ord a => Ord (Pattern a) where+  min = liftA2 min+  max = liftA2 max+  compare = noOv "compare"+  (<=) = noOv "(<=)"++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 Num (ControlMap) where+  negate      = ((applyFIS negate negate id) <$>)+  (+)         = Map.unionWith (fNum2 (+) (+))+  (*)         = Map.unionWith (fNum2 (*) (*))+  fromInteger i = Map.singleton "n" $ VI $ fromInteger i+  signum      = ((applyFIS signum signum id) <$>)+  abs         = ((applyFIS abs abs id) <$>)++instance Fractional ControlMap where+  recip        = fmap (applyFIS recip id id)+  fromRational = Map.singleton "speed" . VF . fromRational++showPattern :: Show a => Arc -> Pattern a -> String+showPattern a p = intercalate "\n" $ map show $ queryArc p a++instance (Show a) => Show (Pattern a) where+  show p = showPattern (Arc 0 1) p++instance Show Value where+  show (VS s) = ('"':s) ++ "\""+  show (VI i) = show i+  show (VF f) = show f ++ "f"++instance {-# OVERLAPPING #-} Show (ControlMap) where+  show m = intercalate ", " $ map (\(name, v) -> name ++ ": " ++ show v) $ Map.toList m++prettyRat :: Rational -> String+prettyRat r | unit == 0 && frac > 0 = showFrac (numerator frac) (denominator frac)+            | otherwise =  show unit ++ showFrac (numerator frac) (denominator frac)+  where unit = floor r :: Int+        frac = (r - (toRational unit))++showFrac :: Integer -> Integer -> String+showFrac 0 _ = ""+showFrac 1 2 = "½"+showFrac 1 3 = "⅓"+showFrac 2 3 = "⅔"+showFrac 1 4 = "¼"+showFrac 3 4 = "¾"+showFrac 1 5 = "⅕"+showFrac 2 5 = "⅖"+showFrac 3 5 = "⅗"+showFrac 4 5 = "⅘"+showFrac 1 6 = "⅙"+showFrac 5 6 = "⅚"+showFrac 1 7 = "⅐"+showFrac 1 8 = "⅛"+showFrac 3 8 = "⅜"+showFrac 5 8 = "⅝"+showFrac 7 8 = "⅞"+showFrac 1 9 = "⅑"+showFrac 1 10 = "⅒"++showFrac n d = fromMaybe plain $ do n' <- up n+                                    d' <- down d+                                    return $ n' ++ d'+  where plain = " " ++ show n ++ "/" ++ show d+        up 1 = Just "¹"+        up 2 = Just "²"+        up 3 = Just "³"+        up 4 = Just "⁴"+        up 5 = Just "⁵"+        up 6 = Just "⁶"+        up 7 = Just "⁷"+        up 8 = Just "⁸"+        up 9 = Just "⁹"+        up 0 = Just "⁰"+        up _ = Nothing+        down 1 = Just "₁"+        down 2 = Just "₂"+        down 3 = Just "₃"+        down 4 = Just "₄"+        down 5 = Just "₅"+        down 6 = Just "₆"+        down 7 = Just "₇"+        down 8 = Just "₈"+        down 9 = Just "₉"+        down 0 = Just "₀"+        down _ = Nothing++------------------------------------------------------------------------+-- * Internal functions++empty :: Pattern a+empty = Pattern {nature = Digital, query = const []}++queryArc :: Pattern a -> Arc -> [Event a]+queryArc p a = query p $ State a Map.empty ++isDigital :: Pattern a -> Bool+isDigital = (== Digital) . nature++isAnalog :: Pattern a -> Bool+isAnalog = not . isDigital++-- | Splits queries that span cycles. For example `query p (0.5, 1.5)` would be+-- turned into two queries, `(0.5,1)` and `(1,1.5)`, and the results+-- combined. Being able to assume queries don't span cycles often+-- makes transformations easier to specify.+splitQueries :: Pattern a -> Pattern a+splitQueries p = p {query = \st -> concatMap (\a -> query p st {arc = a}) $ arcCyclesZW (arc st)}++-- | Apply a function to the arcs/timespans (both whole and parts) of the result+withResultArc :: (Arc -> Arc) -> Pattern a -> Pattern a+withResultArc f pat = pat+  { query = map (\(Event w p e) -> Event (f w) (f p) e) . query pat}++-- | Apply a function to the time (both start and end of the timespans+-- of both whole and parts) of the result+withResultTime :: (Time -> Time) -> Pattern a -> Pattern a+withResultTime f = withResultArc (\(Arc s e) -> Arc (f s) (f e))++-- | Apply a function to the timespan of the query+withQueryArc :: (Arc -> Arc) -> Pattern a -> Pattern a+withQueryArc f p = p {query = query p . (\(State a m) -> State (f a) m)}++-- | Apply a function to the time (both start and end) of the query+withQueryTime :: (Time -> Time) -> Pattern a -> Pattern a+withQueryTime f = withQueryArc (\(Arc s e) -> Arc (f s) (f e))++-- | @withEvent f p@ returns a new @Pattern@ with each event mapped over+-- function @f@.+withEvent :: (Event a -> Event b) -> Pattern a -> Pattern b+withEvent f p = p {query = map f . query p}++-- | @withEvent f p@ returns a new @Pattern@ with f applied to the resulting list of events for each query+-- function @f@.+withEvents :: ([Event a] -> [Event b]) -> Pattern a -> Pattern b+withEvents f p = p {query = f . query p}++-- | @withPart f p@ returns a new @Pattern@ with function @f@ applied+-- to the part.+withPart :: (Arc -> Arc) -> Pattern a -> Pattern a+withPart f = withEvent (\(Event w p v) -> (Event w (f p) v))++-- | Apply one of three functions to a Value, depending on its type+applyFIS :: (Double -> Double) -> (Int -> Int) -> (String -> String) -> Value -> Value+applyFIS f _ _ (VF f') = VF $ f f'+applyFIS _ f _ (VI i ) = VI $ f i+applyFIS _ _ f (VS s ) = VS $ f s++-- | Apply one of two functions to a Value, depending on its type (int+-- or float; strings are ignored)+fNum2 :: (Int -> Int -> Int) -> (Double -> Double -> Double) -> Value -> Value -> Value+fNum2 fInt _      (VI a) (VI b) = VI $ fInt a b+fNum2 _    fFloat (VF a) (VF b) = VF $ fFloat a b+fNum2 _    fFloat (VI a) (VF b) = VF $ fFloat (fromIntegral a) b+fNum2 _    fFloat (VF a) (VI b) = VF $ fFloat a (fromIntegral b)+fNum2 _    _      x      _      = x++getI :: Value -> Maybe Int+getI (VI i) = Just i+getI _  = Nothing++getF :: Value -> Maybe Double+getF (VF f) = Just f+getF _  = Nothing++getS :: Value -> Maybe String+getS (VS s) = Just s+getS _  = Nothing++compressArc :: Arc -> Pattern a -> Pattern a+compressArc (Arc s e) p | s > e = empty+                        | s > 1 || e > 1 = empty+                        | s < 0 || e < 0 = empty+                        | otherwise = s `rotR` _fastGap (1/(e-s)) p++compressArcTo :: Arc -> Pattern a -> Pattern a+compressArcTo (Arc s e) p = compressArc (Arc (cyclePos s) (e-(sam s))) p++_fastGap :: Time -> Pattern a -> Pattern a+_fastGap 0 _ = empty+_fastGap r p = splitQueries $ +  withResultArc (\(Arc s e) -> Arc (sam s + ((s - sam s)/r'))+                             (sam s + ((e - sam s)/r'))+                 ) $ p {query = f}+  where r' = max r 1+        -- zero width queries of the next sam should return zero in this case..+        f st@(State a _) | start a' == nextSam (start a) = []+                         | otherwise = query p st {arc = a'}+          where mungeQuery t = sam t + (min 1 $ r' * cyclePos t)+                a' = (\(Arc s e) -> Arc (mungeQuery s) (mungeQuery e)) a++-- | Shifts a pattern back in time by the given amount, expressed in cycles+rotL :: Time -> Pattern a -> Pattern a+rotL t p = withResultTime (subtract t) $ withQueryTime (+ t) p++-- | Shifts a pattern forward in time by the given amount, expressed in cycles+rotR :: Time -> Pattern a -> Pattern a+rotR t = rotL (0-t)++-- ** Event filters++-- | Remove events from patterns that to not meet the given test+filterValues :: (a -> Bool) -> Pattern a -> Pattern a+filterValues f p = p {query = (filter (f . value)) . query p}++-- | Turns a pattern of 'Maybe' values in to a pattern of values,+-- dropping the events of 'Nothing'.+filterJust :: Pattern (Maybe a) -> Pattern a+filterJust p = fromJust <$> (filterValues (isJust) p)++-- formerly known as playWhen+filterWhen :: (Time -> Bool) -> Pattern a -> Pattern a+filterWhen test p = p {query = filter (test . wholeStart) . query p}++playFor :: Time -> Time -> Pattern a -> Pattern a+playFor s e = filterWhen (\t -> and [t >= s, t < e])++-- ** Temporal parameter helpers++tParam :: (t1 -> t2 -> Pattern a) -> Pattern t1 -> t2 -> Pattern a+tParam f tv p = innerJoin $ (`f` p) <$> tv++tParam2 :: (a -> b -> c -> Pattern d) -> Pattern a -> Pattern b -> c -> Pattern d+tParam2 f a b p = innerJoin $ (\x y -> f x y p) <$> a <*> b++tParam3 :: (a -> b -> c -> Pattern d -> Pattern e) -> (Pattern a -> Pattern b -> Pattern c -> Pattern d -> Pattern e)+tParam3 f a b c p = innerJoin $ (\x y z -> f x y z p) <$> a <*> b <*> c++tParamSqueeze :: (a -> Pattern b -> Pattern c) -> (Pattern a -> Pattern b -> Pattern c)+tParamSqueeze f tv p = unwrapSqueeze $ (`f` p) <$> tv++-- | Mark values in the first pattern which match with at least one+-- value in the second pattern.+matchManyToOne :: (b -> a -> Bool) -> Pattern a -> Pattern b -> Pattern (Bool, b)+matchManyToOne f pa pb = pa {query = q}+  where q st = map match $ query pb st+          where+            match (Event xWhole xPart x) =+              Event xWhole xPart (or $ (map (f x) (as $ start xWhole)), x)+            as s = map value $ query pa $ fQuery s+            fQuery s = st {arc = (Arc s s)}
+ src/Sound/Tidal/Scales.hs view
@@ -0,0 +1,227 @@+module Sound.Tidal.Scales (scale, scaleList) where++import Data.Maybe+import Data.List (intercalate)++import Sound.Tidal.Pattern+import Sound.Tidal.Utils++-- five notes scales+minPent :: Num a => [a]+minPent = [0,3,5,7,10]+majPent :: Num a => [a]+majPent = [0,2,4,7,9]++--  another mode of major pentatonic+ritusen :: Num a => [a]+ritusen = [0,2,5,7,9]++-- another mode of major pentatonic+egyptian :: Num a => [a]+egyptian = [0,2,5,7,10]++--+kumai :: Num a => [a]+kumai = [0,2,3,7,9]+hirajoshi :: Num a => [a]+hirajoshi = [0,2,3,7,8]+iwato :: Num a => [a]+iwato = [0,1,5,6,10]+chinese :: Num a => [a]+chinese = [0,4,6,7,11]+indian :: Num a => [a]+indian = [0,4,5,7,10]+pelog :: Num a => [a]+pelog = [0,1,3,7,8]++--+prometheus :: Num a => [a]+prometheus = [0,2,4,6,11]+scriabin :: Num a => [a]+scriabin = [0,1,4,7,9]++-- han chinese pentatonic scales+gong :: Num a => [a]+gong = [0,2,4,7,9]+shang :: Num a => [a]+shang = [0,2,5,7,10]+jiao :: Num a => [a]+jiao = [0,3,5,8,10]+zhi :: Num a => [a]+zhi = [0,2,5,7,9]+yu :: Num a => [a]+yu = [0,3,5,7,10]++-- 6 note scales+whole' :: Num a => [a]+whole' = [0,2,4,6,8,10]+augmented :: Num a => [a]+augmented = [0,3,4,7,8,11]+augmented2 :: Num a => [a]+augmented2 = [0,1,4,5,8,9]++-- hexatonic modes with no tritone+hexMajor7 :: Num a => [a]+hexMajor7 = [0,2,4,7,9,11]+hexDorian :: Num a => [a]+hexDorian = [0,2,3,5,7,10]+hexPhrygian :: Num a => [a]+hexPhrygian = [0,1,3,5,8,10]+hexSus :: Num a => [a]+hexSus = [0,2,5,7,9,10]+hexMajor6 :: Num a => [a]+hexMajor6 = [0,2,4,5,7,9]+hexAeolian :: Num a => [a]+hexAeolian = [0,3,5,7,8,10]++-- 7 note scales+major :: Num a => [a]+major = [0,2,4,5,7,9,11]+ionian :: Num a => [a]+ionian = [0,2,4,5,7,9,11]+dorian :: Num a => [a]+dorian = [0,2,3,5,7,9,10]+phrygian :: Num a => [a]+phrygian = [0,1,3,5,7,8,10]+lydian :: Num a => [a]+lydian = [0,2,4,6,7,9,11]+mixolydian :: Num a => [a]+mixolydian = [0,2,4,5,7,9,10]+aeolian :: Num a => [a]+aeolian = [0,2,3,5,7,8,10]+minor :: Num a => [a]+minor = [0,2,3,5,7,8,10]+locrian :: Num a => [a]+locrian = [0,1,3,5,6,8,10]+harmonicMinor :: Num a => [a]+harmonicMinor = [0,2,3,5,7,8,11]+harmonicMajor :: Num a => [a]+harmonicMajor = [0,2,4,5,7,8,11]+melodicMinor :: Num a => [a]+melodicMinor = [0,2,3,5,7,9,11]+melodicMinorDesc :: Num a => [a]+melodicMinorDesc = [0,2,3,5,7,8,10]+melodicMajor :: Num a => [a]+melodicMajor = [0,2,4,5,7,8,10]+bartok :: Num a => [a]+bartok = [0,2,4,5,7,8,10]+hindu :: Num a => [a]+hindu = [0,2,4,5,7,8,10]++-- raga modes+todi :: Num a => [a]+todi = [0,1,3,6,7,8,11]+purvi :: Num a => [a]+purvi = [0,1,4,6,7,8,11]+marva :: Num a => [a]+marva = [0,1,4,6,7,9,11]+bhairav :: Num a => [a]+bhairav = [0,1,4,5,7,8,11]+ahirbhairav :: Num a => [a]+ahirbhairav = [0,1,4,5,7,9,10]++--+superLocrian :: Num a => [a]+superLocrian = [0,1,3,4,6,8,10]+romanianMinor :: Num a => [a]+romanianMinor = [0,2,3,6,7,9,10]+hungarianMinor :: Num a => [a]+hungarianMinor = [0,2,3,6,7,8,11]+neapolitanMinor :: Num a => [a]+neapolitanMinor = [0,1,3,5,7,8,11]+enigmatic :: Num a => [a]+enigmatic = [0,1,4,6,8,10,11]+spanish :: Num a => [a]+spanish = [0,1,4,5,7,8,10]++-- modes of whole tones with added note ->+leadingWhole :: Num a => [a]+leadingWhole = [0,2,4,6,8,10,11]+lydianMinor :: Num a => [a]+lydianMinor = [0,2,4,6,7,8,10]+neapolitanMajor :: Num a => [a]+neapolitanMajor = [0,1,3,5,7,9,11]+locrianMajor :: Num a => [a]+locrianMajor = [0,2,4,5,6,8,10]++-- 8 note scales+diminished :: Num a => [a]+diminished = [0,1,3,4,6,7,9,10]+diminished2 :: Num a => [a]+diminished2 = [0,2,3,5,6,8,9,11]++-- 12 note scales+chromatic :: Num a => [a]+chromatic = [0,1,2,3,4,5,6,7,8,9,10,11]++scale :: Num a => Pattern String -> Pattern Int -> Pattern a+scale sp p = (\n scaleName -> noteInScale (fromMaybe [0] $ lookup scaleName scaleTable) n) <$> p <*> sp+  where octave s x = x `div` length s+        noteInScale s x = (s !!! x) + (fromIntegral $ 12 * octave s x)++scaleList :: String+scaleList = intercalate " " $ map fst (scaleTable :: [(String, [Int])])++scaleTable :: Num a => [(String, [a])]+scaleTable = [("minPent", minPent),+              ("majPent", majPent),+              ("ritusen", ritusen),+              ("egyptian", egyptian),+              ("kumai", kumai),+              ("hirajoshi", hirajoshi),+              ("iwato", iwato),+              ("chinese", chinese),+              ("indian", indian),+              ("pelog", pelog),+              ("prometheus", prometheus),+              ("scriabin", scriabin),+              ("gong", gong),+              ("shang", shang),+              ("jiao", jiao),+              ("zhi", zhi),+              ("yu", yu),+              ("whole", whole'),+              ("augmented", augmented),+              ("augmented2", augmented2),+              ("hexMajor7", hexMajor7),+              ("hexDorian", hexDorian),+              ("hexPhrygian", hexPhrygian),+              ("hexSus", hexSus),+              ("hexMajor6", hexMajor6),+              ("hexAeolian", hexAeolian),+              ("major", major),+              ("ionian", ionian),+              ("dorian", dorian),+              ("phrygian", phrygian),+              ("lydian", lydian),+              ("mixolydian", mixolydian),+              ("aeolian", aeolian),+              ("minor", minor),+              ("locrian", locrian),+              ("harmonicMinor", harmonicMinor),+              ("harmonicMajor", harmonicMajor),+              ("melodicMinor", melodicMinor),+              ("melodicMinorDesc", melodicMinorDesc),+              ("melodicMajor", melodicMajor),+              ("bartok", bartok),+              ("hindu", hindu),+              ("todi", todi),+              ("purvi", purvi),+              ("marva", marva),+              ("bhairav", bhairav),+              ("ahirbhairav", ahirbhairav),+              ("superLocrian", superLocrian),+              ("romanianMinor", romanianMinor),+              ("hungarianMinor", hungarianMinor),+              ("neapolitanMinor", neapolitanMinor),+              ("enigmatic", enigmatic),+              ("spanish", spanish),+              ("leadingWhole", leadingWhole),+              ("lydianMinor", lydianMinor),+              ("neapolitanMajor", neapolitanMajor),+              ("locrianMajor", locrianMajor),+              ("diminished", diminished),+              ("diminished2", diminished2),+              ("chromatic", chromatic)+             ]+
+ src/Sound/Tidal/Simple.hs view
@@ -0,0 +1,42 @@+module Sound.Tidal.Simple where++import Sound.Tidal.Control (chop, hurry)+import Sound.Tidal.Core ((#), (|*), (<~), silence, rev)+import Sound.Tidal.Params (crush, gain, pan, speed)+import Sound.Tidal.Pattern (ControlPattern)++crunch :: ControlPattern -> ControlPattern+crunch = (# crush 3)++scratch :: ControlPattern -> ControlPattern+scratch = rev . chop 32++louder :: ControlPattern -> ControlPattern+louder = (|* gain 1.2)++quieter :: ControlPattern -> ControlPattern+quieter = (|* gain 0.8)++silent :: ControlPattern -> ControlPattern+silent = const silence++skip :: ControlPattern -> ControlPattern+skip = (0.25 <~)++left :: ControlPattern -> ControlPattern+left = (# pan 0)++right :: ControlPattern -> ControlPattern+right = (# pan 1)++higher :: ControlPattern -> ControlPattern+higher = (|* speed 1.5)++lower :: ControlPattern -> ControlPattern+lower = (|* speed 0.75)++faster :: ControlPattern -> ControlPattern+faster = hurry 2++slower :: ControlPattern -> ControlPattern+slower = hurry 0.5
+ src/Sound/Tidal/Stream.hs view
@@ -0,0 +1,305 @@+{-# LANGUAGE ConstraintKinds, GeneralizedNewtypeDeriving, FlexibleContexts, ScopedTypeVariables, BangPatterns #-}+{-# OPTIONS_GHC -fno-warn-missing-fields #-}++module Sound.Tidal.Stream where++import           Control.Concurrent.MVar+import           Control.Concurrent+import qualified Data.Map.Strict as Map+import           Data.Maybe (fromJust, fromMaybe)+import qualified Control.Exception as E+-- import Control.Monad.Reader+-- import Control.Monad.Except+-- import qualified Data.Bifunctor as BF+-- import qualified Data.Bool as B+-- import qualified Data.Char as C++import qualified Sound.OSC.FD as O++import           Sound.Tidal.Config+import           Sound.Tidal.Core (stack, silence)+import           Sound.Tidal.Pattern+import qualified Sound.Tidal.Tempo as T+-- import qualified Sound.OSC.Datum as O++data TimeStamp = BundleStamp | MessageStamp | NoStamp+ deriving Eq++data Stream = Stream {sConfig :: Config,+                      sInput :: MVar ControlMap,+                      sOutput :: MVar ControlPattern,+                      sListenTid :: Maybe ThreadId,+                      sPMapMV :: MVar PlayMap,+                      sTempoMV :: MVar T.Tempo,+                      sTarget :: OSCTarget,+                      sUDP :: O.UDP+                     }++type PatId = String++data OSCTarget = OSCTarget {oAddress :: String,+                            oPort :: Int,+                            oPath :: String,+                            oShape :: Maybe [(String, Maybe Value)],+                            oLatency :: Double,+                            oPreamble :: [O.Datum],+                            oTimestamp :: TimeStamp+                           }++superdirtTarget :: OSCTarget+superdirtTarget = OSCTarget {oAddress = "127.0.0.1",+                             oPort = 57120,+                             oPath = "/play2",+                             oShape = Nothing,+                             oLatency = 0.02,+                             oPreamble = [],+                             oTimestamp = BundleStamp+                            }++startStream :: Config -> MVar ControlMap -> OSCTarget -> IO (MVar ControlPattern, MVar T.Tempo, O.UDP)+startStream config cMapMV target+  = do u <- O.openUDP (oAddress target) (oPort target)+       pMV <- newMVar empty+       (tempoMV, _) <- T.clocked config $ onTick config cMapMV pMV target u+       return $ (pMV, tempoMV, u)+++data PlayState = PlayState {pattern :: ControlPattern,+                            mute :: Bool,+                            solo :: Bool,+                            history :: [ControlPattern]+                           }+               deriving Show++type PlayMap = Map.Map PatId PlayState+++toDatum :: Value -> O.Datum+toDatum (VF x) = O.float x+toDatum (VI x) = O.int32 x+toDatum (VS x) = O.string x++toData :: Event ControlMap -> [O.Datum]+toData e = concatMap (\(n,v) -> [O.string n, toDatum v]) $ Map.toList $ value e++toMessage :: OSCTarget -> T.Tempo -> Event (Map.Map String Value) -> O.Message+toMessage target tempo e = O.Message (oPath target) $ oPreamble target ++ toData addCps+  where on = sched tempo $ start $ whole e+        off = sched tempo $ stop $ whole e+        delta = off - on+        -- If there is already cps in the event, the union will preserve that.+        addCps = (\v -> (Map.union v $ Map.fromList [("cps", (VF $ T.cps tempo)),+                                                     ("delta", VF delta),+                                                     ("cycle", VF (fromRational $ start $ whole e))+                                                    ])) <$> e++doCps :: MVar T.Tempo -> (Double, Maybe Value) -> IO ()+doCps tempoMV (d, Just (VF cps)) = do _ <- forkIO $ do threadDelay $ floor $ d * 1000000+                                                       -- hack to stop things from stopping !+                                                       _ <- T.setCps tempoMV (max 0.00001 cps)+                                                       return ()+                                      return ()+doCps _ _ = return ()++onTick :: Config -> MVar ControlMap -> MVar ControlPattern -> OSCTarget -> O.UDP -> MVar T.Tempo -> T.State -> IO ()+onTick config cMapMV pMV target u tempoMV st =+  do p <- readMVar pMV+     cMap <- readMVar cMapMV+     tempo <- readMVar tempoMV+     now <- O.time+     let es = filter eventHasOnset $ query p (State {arc = T.nowArc st, controls = cMap})+         on e = (sched tempo $ start $ whole e) + eventNudge e+         eventNudge e = fromJust $ getF $ fromMaybe (VF 0) $ Map.lookup "nudge" $ value e+         messages = map (\e -> (on e, toMessage target tempo e)) es+         cpsChanges = map (\e -> (on e - now, Map.lookup "cps" $ value e)) es+         latency = oLatency target + cFrameTimespan config + T.nudged tempo+     E.catch (mapM_ (send latency u) messages)+       (\(_ ::E.SomeException)+        -> putStrLn $ "Failed to send. Is the target (probably superdirt) running?")+                -- ++ show (msg :: E.SomeException))+     mapM_ (doCps tempoMV) cpsChanges+     return ()++send :: O.Transport t => Double -> t -> (Double, O.Message) -> IO ()+send latency u (time, m) = O.sendOSC u $ O.Bundle (time + latency) [m]++sched :: T.Tempo -> Rational -> Double+sched tempo c = ((fromRational $ c - (T.atCycle tempo)) / T.cps tempo) + (T.atTime tempo)++-- Interaction++streamNudgeAll :: Stream -> Double -> IO ()+streamNudgeAll s nudge = do tempo <- takeMVar $ sTempoMV s+                            putMVar (sTempoMV s) $ tempo {T.nudged = nudge}++streamResetCycles :: Stream -> IO ()+streamResetCycles s = do _ <- T.resetCycles (sTempoMV s)+                         return ()++hasSolo :: Map.Map k PlayState -> Bool+hasSolo = (>= 1) . length . filter solo . Map.elems++streamList :: Stream -> IO ()+streamList s = do pMap <- readMVar (sPMapMV s)+                  let hs = hasSolo pMap+                  putStrLn $ concatMap (showKV hs) $ Map.toList pMap+  where showKV :: Bool -> (PatId, PlayState) -> String+        showKV True  (k, (PlayState _  _ True _)) = k ++ " - solo\n"+        showKV True  (k, _) = "(" ++ k ++ ")\n"+        showKV False (k, (PlayState _ False _ _)) = k ++ "\n"+        showKV False (k, _) = "(" ++ k ++ ") - muted\n"++-- Evaluation of pat is forced so exceptions are picked up here, before replacing the existing pattern.+streamReplace :: Show a => Stream -> a -> ControlPattern -> IO ()+streamReplace s k !pat+  = E.catch (do pMap <- takeMVar $ sPMapMV s+                let playState = updatePS $ Map.lookup (show k) pMap+                putMVar (sPMapMV s) $ Map.insert (show k) playState pMap+                calcOutput s+                return ()+          )+    (\(e :: E.SomeException) -> putStrLn $ "Error in pattern: " ++ show e+    )+  where updatePS (Just playState) = do playState {pattern = pat, history = pat:(history playState)}+        updatePS Nothing = PlayState pat False False []++streamMute :: Show a => Stream -> a -> IO ()+streamMute s k = withPatId s (show k) (\x -> x {mute = True})++streamMutes :: Show a => Stream -> [a] -> IO ()+streamMutes s ks = withPatIds s (map show ks) (\x -> x {mute = True})++streamUnmute :: Show a => Stream -> a -> IO ()+streamUnmute s k = withPatId s (show k) (\x -> x {mute = False})++streamSolo :: Show a => Stream -> a -> IO ()+streamSolo s k = withPatId s (show k) (\x -> x {solo = True})++streamUnsolo :: Show a => Stream -> a -> IO ()+streamUnsolo s k = withPatId s (show k) (\x -> x {solo = False})++streamOnce :: Stream -> Bool -> ControlPattern -> IO ()+streamOnce st asap p+  = do cMap <- readMVar (sInput st)+       tempo <- readMVar (sTempoMV st)+       now <- O.time+       let target = if asap+                    then (sTarget st) {oLatency = 0}+                    else sTarget st+           fakeTempo = T.Tempo {T.cps = T.cps tempo,+                                T.atCycle = 0,+                                T.atTime = now,+                                T.paused = False,+                                T.nudged = 0+                               }+           es = filter eventHasOnset $ query p (State {arc = (Arc 0 1),+                                                       controls = cMap+                                                      }+                                               )+           at e = sched fakeTempo $ start $ whole e+           on e = sched tempo $ start $ whole e+           cpsChanges = map (\e -> (on e - now, Map.lookup "cps" $ value e)) es+           messages = map (\e -> (at e, toMessage target fakeTempo e)) es+       E.catch (mapM_ (send (oLatency target) (sUDP st)) messages)+         (\(msg ::E.SomeException)+          -> putStrLn $ "Failed to send. Is the target (probably superdirt) running? " ++ show (msg :: E.SomeException))+       mapM_ (doCps $ sTempoMV st) cpsChanges+       return ()++withPatId :: Stream -> PatId -> (PlayState -> PlayState) -> IO ()+withPatId s k f = withPatIds s [k] f++withPatIds :: Stream -> [PatId] -> (PlayState -> PlayState) -> IO ()+withPatIds s ks f+  = do playMap <- takeMVar $ sPMapMV s+       let pMap' = foldr (Map.update (\x -> Just $ f x)) playMap ks+       putMVar (sPMapMV s) pMap'+       calcOutput s+       return ()++-- TODO - is there a race condition here?+streamMuteAll :: Stream -> IO ()+streamMuteAll s = do modifyMVar_ (sOutput s) $ return . const silence+                     modifyMVar_ (sPMapMV s) $ return . fmap (\x -> x {mute = True})++streamHush :: Stream -> IO ()+streamHush s = do modifyMVar_ (sOutput s) $ return . const silence+                  modifyMVar_ (sPMapMV s) $ return . fmap (\x -> x {pattern = silence})++streamUnmuteAll :: Stream -> IO ()+streamUnmuteAll s = do modifyMVar_ (sPMapMV s) $ return . fmap (\x -> x {mute = False})+                       calcOutput s++calcOutput :: Stream -> IO ()+calcOutput s = do pMap <- readMVar $ sPMapMV s+                  _ <- swapMVar (sOutput s) $ toPat pMap+                  return ()+  where toPat pMap =+          stack $ map pattern $ filter (\pState -> if hasSolo pMap+                                                   then solo pState+                                                   else not (mute pState)+                                       ) (Map.elems pMap)++startTidal :: OSCTarget -> Config -> IO Stream+startTidal target config =+  do cMapMV <- newMVar (Map.empty :: ControlMap)+     listenTid <- ctrlListen cMapMV config+     (pMV, tempoMV, u) <- startStream config cMapMV target+     pMapMV <- newMVar Map.empty+     return $ Stream {sConfig = config,+                      sInput = cMapMV,+                      sListenTid = listenTid,+                      sOutput = pMV,+                      sPMapMV = pMapMV,+                      sTempoMV = tempoMV,+                      sTarget = target,+                      sUDP = u+                     }+ctrlListen :: MVar ControlMap -> Config -> IO (Maybe ThreadId)+ctrlListen cMapMV c+  | cCtrlListen c = do putStrLn $ "Listening for controls on " ++ cCtrlAddr c ++ ":" ++ show (cCtrlPort c)+                       catchAny run (\_ -> do putStrLn $ "Control listen failed. Perhaps there's already another tidal instance listening on that port?"+                                              return Nothing+                                    )+  | otherwise  = return Nothing+  where+        run = do sock <- O.udpServer (cCtrlAddr c) (cCtrlPort c)+                 tid <- forkIO $ loop sock+                 return $ Just tid+        loop sock = do ms <- O.recvMessages sock+                       mapM_ act ms+                       loop sock+        act (O.Message x (O.Int32 k:v:[]))+          = act (O.Message x [O.string $ show k,v])+        act (O.Message _ (O.ASCII_String k:v@(O.Float _):[]))+          = add (O.ascii_to_string k) (VF $ fromJust $ O.datum_floating v)+        act (O.Message _ (O.ASCII_String k:O.ASCII_String v:[]))+          = add (O.ascii_to_string k) (VS $ O.ascii_to_string v)+        act (O.Message _ (O.ASCII_String k:O.Int32 v:[]))+          = add (O.ascii_to_string k) (VI $ fromIntegral v)+        act m = putStrLn $ "Unhandled OSC: " ++ show m+        add :: String -> Value -> IO ()+        add k v = do cMap <- takeMVar cMapMV+                     putMVar cMapMV $ Map.insert k v cMap+                     return ()+        catchAny :: IO a -> (E.SomeException -> IO a) -> IO a+        catchAny = E.catch++{-+listenCMap :: MVar ControlMap -> IO ()+listenCMap cMapMV = do sock <- O.udpServer "127.0.0.1" (6011)+                       _ <- forkIO $ loop sock+                       return ()+  where loop sock =+          do ms <- O.recvMessages sock+             mapM_ readMessage ms+             loop sock+        readMessage (O.Message _ (O.ASCII_String k:v@(O.Float _):[])) = add (O.ascii_to_string k) (VF $ fromJust $ O.datum_floating v)+        readMessage (O.Message _ (O.ASCII_String k:O.ASCII_String v:[])) = add (O.ascii_to_string k) (VS $ O.ascii_to_string v)+        readMessage (O.Message _ (O.ASCII_String k:O.Int32 v:[]))  = add (O.ascii_to_string k) (VI $ fromIntegral v)+        readMessage _ = return ()+        add :: String -> Value -> IO ()+        add k v = do cMap <- takeMVar cMapMV+                     putMVar cMapMV $ Map.insert k v cMap+                     return ()+-}
+ src/Sound/Tidal/Tempo.hs view
@@ -0,0 +1,183 @@+{-# OPTIONS_GHC -fno-warn-incomplete-uni-patterns #-}++module Sound.Tidal.Tempo where++-- import Data.Time (getCurrentTime, UTCTime, NominalDiffTime, diffUTCTime, addUTCTime)+-- import Data.Time.Clock.POSIX (utcTimeToPOSIXSeconds)+import Control.Concurrent.MVar+import qualified Sound.Tidal.Pattern as P+import qualified Sound.OSC.FD as O+-- import qualified Sound.OSC.Transport.FD.UDP as O+import qualified Network.Socket as N+import Control.Concurrent (forkIO, ThreadId, threadDelay)+import Control.Monad (forever, when, foldM)+import Data.List (isPrefixOf, nub)+import qualified Control.Exception as E++import Sound.Tidal.Config++data Tempo = Tempo {atTime  :: O.Time,+                    atCycle :: Rational,+                    cps     :: O.Time,+                    paused  :: Bool,+                    nudged  :: Double,+                    localUDP   :: O.UDP,+                    remoteAddr :: N.SockAddr+                   }+           -- deriving Show++-- sendTempo udp tempo remote_sockaddr            +-- ++data State = State {ticks   :: Int,+                    start   :: O.Time,+                    nowTime :: O.Time,+                    nowArc  :: P.Arc+                   }++resetCycles :: MVar Tempo -> IO (Tempo)+resetCycles tempoMV = do t <- O.time+                         tempo <- takeMVar tempoMV+                         let tempo' = tempo {atTime = t,+                                             atCycle = (-0.5)+                                            }+                         sendTempo tempo'+                         putMVar tempoMV $ tempo'+                         return tempo'+++setCps :: MVar Tempo -> O.Time -> IO (Tempo)+setCps tempoMV newCps = do t <- O.time+                           tempo <- takeMVar tempoMV+                           let c = timeToCycles tempo t+                               tempo' = tempo {atTime = t,+                                               atCycle = c,+                                               cps = newCps+                                              }+                           sendTempo tempo'+                           -- TODO - should we set the tempo ASAP rather than waiting for (possibly failing) network round trip?+                           putMVar tempoMV $ tempo'+                           return tempo'++defaultTempo :: O.Time -> O.UDP -> N.SockAddr -> Tempo+defaultTempo t local remote = Tempo {atTime   = t,+                                     atCycle  = 0,+                                     cps      = 0.5625,+                                     paused   = False,+                                     nudged   = 0,+                                     localUDP   = local,+                                     remoteAddr = remote+                                    }++-- | Returns the given time in terms of+-- cycles relative to metrical grid of a given Tempo+timeToCycles :: Tempo -> O.Time -> Rational+timeToCycles tempo t = (atCycle tempo) + (toRational cycleDelta)+  where delta = t - (atTime tempo)+        cycleDelta = (realToFrac $ cps tempo) * delta++{-+getCurrentCycle :: MVar Tempo -> IO Rational+getCurrentCycle t = (readMVar t) >>= (cyclesNow) >>= (return . toRational)+-}+++clocked :: Config -> (MVar Tempo -> State -> IO ()) -> IO (MVar Tempo, [ThreadId])+clocked config callback+  = do s <- O.time+       -- TODO - do something with thread id+       _ <- serverListen config+       (tempoMV, listenTid) <- clientListen config s+       let st = State {ticks = 0,+                       start = s,+                       nowTime = s,+                       nowArc = (P.Arc 0 0)+                      }+       clockTid <- forkIO $ loop tempoMV st+       return (tempoMV, [listenTid, clockTid])+  where loop tempoMV st =+          do -- putStrLn $ show $ nowArc ts+             tempo <- readMVar tempoMV+             let frameTimespan = cFrameTimespan config+             let -- 'now' comes from clock ticks, nothing to do with cycles+                 logicalNow = start st + (fromIntegral $ (ticks st)+1) * frameTimespan+                 -- the tempo is just used to convert logical time to cycles+                 s = P.stop $ nowArc st+                 e = timeToCycles tempo logicalNow+                 st' = st {ticks = (ticks st) + 1, nowArc = P.Arc s e}+             t <- O.time+             when (t < logicalNow) $ threadDelay (floor $ (logicalNow - t) * 1000000)+             callback tempoMV st'+             loop tempoMV st'++clientListen :: Config -> O.Time -> IO (MVar Tempo, ThreadId)+clientListen config s =+  do -- Listen on random port+     local <- O.udpServer "127.0.0.1" 0+     let hostname = cTempoAddr config+         port = cTempoPort config+     (remote_addr:_) <- N.getAddrInfo Nothing (Just hostname) Nothing+     let (N.SockAddrInet _ a) = N.addrAddress remote_addr+         remote = N.SockAddrInet (fromIntegral port) (a)+         t = defaultTempo s local remote+     -- Send to clock port from same port that's listened to+     O.sendTo local (O.Message "/hello" []) remote+     -- Make tempo mvar+     tempoMV <- newMVar t+     -- Listen to tempo changes+     tempoChild <- (forkIO $ listenTempo local tempoMV)+     return (tempoMV, tempoChild)++sendTempo :: Tempo -> IO ()+sendTempo tempo = O.sendTo (localUDP tempo) b (remoteAddr tempo)+  where b = O.Bundle (atTime tempo) [O.Message "/transmit/cps/cycle" [O.Float $ fromRational $ atCycle tempo,+                                                                      O.Float $ realToFrac $ cps tempo,+                                                                      O.Int32 $ if (paused tempo) then 1 else 0+                                                                     ]+                                    ]++listenTempo :: O.UDP -> (MVar Tempo) -> IO ()+listenTempo udp tempoMV = forever $ do pkt <- O.recvPacket udp+                                       act Nothing pkt+                                       return ()+  where act _ (O.Packet_Bundle (O.Bundle ts ms)) = mapM_ (act (Just ts) . O.Packet_Message) ms+        act (Just ts) (O.Packet_Message (O.Message "/cps/cycle" [O.Float atCycle',+                                                                 O.Float cps',+                                                                 O.Int32 paused'+                                                                ]+                                        )+                      ) =+          do tempo <- takeMVar tempoMV+             putMVar tempoMV $ tempo {atTime = ts,+                                      atCycle = realToFrac atCycle',+                                      cps = realToFrac cps',+                                      paused = (paused' == 1)+                                     }+        act _ pkt = putStrLn $ "Unknown packet: " ++ show pkt++serverListen :: Config -> IO (Maybe ThreadId)+serverListen config = catchAny (run) (\_ -> do putStrLn $ "Tempo listener failed (is one already running?)"+                                               return Nothing+                                     )+  where run = do let port = cTempoPort config+                 -- iNADDR_ANY deprecated - what's the right way to do this?+                 udp <- O.udpServer "0.0.0.0" port+                 tid <- forkIO $ loop udp []+                 return $ Just tid+        loop udp cs = do (pkt,c) <- O.recvFrom udp+                         cs' <- act udp c Nothing cs pkt+                         loop udp cs'+        act :: O.UDP -> N.SockAddr -> Maybe O.Time -> [N.SockAddr] -> O.Packet -> IO [N.SockAddr]+        act udp c _ cs (O.Packet_Bundle (O.Bundle ts ms)) = foldM (act udp c (Just ts)) cs $ map (O.Packet_Message) ms+        act _ c _ cs (O.Packet_Message (O.Message "/hello" []))+          = return $ nub $ c:cs+        act udp _ (Just ts) cs (O.Packet_Message (O.Message path params))+          | isPrefixOf "/transmit" path =+              do let path' = drop 9 path+                     msg = O.Message path' params+                 mapM_ (O.sendTo udp $ O.Bundle ts [msg]) cs+                 return cs+        act _ _ _ cs pkt = do putStrLn $ "Unknown packet: " ++ show pkt+                              return cs+        catchAny :: IO a -> (E.SomeException -> IO a) -> IO a+        catchAny = E.catch
+ src/Sound/Tidal/Transition.hs view
@@ -0,0 +1,189 @@+{-# LANGUAGE BangPatterns #-}++module Sound.Tidal.Transition where++import Prelude hiding ((<*), (*>))++import Control.Concurrent.MVar (readMVar, takeMVar, putMVar)++import qualified Sound.OSC.FD as O+import qualified Data.Map.Strict as Map+-- import Data.Maybe (fromJust)++import Sound.Tidal.Control+import Sound.Tidal.Core+import Sound.Tidal.Params (gain, pan)+import Sound.Tidal.Pattern+import Sound.Tidal.Stream+import Sound.Tidal.Tempo (timeToCycles)+import Sound.Tidal.UI (fadeOutFrom, fadeInFrom, spread')+import Sound.Tidal.Utils (enumerate)++-- Evaluation of pat is forced so exceptions are picked up here, before replacing the existing pattern.+transition :: Show a => Stream -> (Time -> [ControlPattern] -> ControlPattern) -> a -> ControlPattern -> IO ()+transition stream f patId !pat = do pMap <- takeMVar (sPMapMV stream)+                                    let playState = updatePS $ Map.lookup (show patId) pMap+                                    pat' <- transition' $ history playState+                                    let pMap' =+                                          Map.insert (show patId) (playState {pattern = pat'}) pMap+                                    putMVar (sPMapMV stream) pMap'+                                    calcOutput stream+                                    return ()+  where+    updatePS (Just playState) = playState {history = pat:(history playState)}+    updatePS Nothing = PlayState {pattern = silence,+                                  mute = False,+                                  solo = False,+                                  history = pat:silence:[]+                                 }+    transition' context = do tempo <- readMVar $ sTempoMV stream+                             now <- O.time+                             let c = timeToCycles tempo now+                             return $ f c context++{-| 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 _ _ _ _ _ _ [] = silence+wash _ _ _ _ _ _ (pat:[]) = pat+wash fout fin delay durin durout now (pat:pat':_) =+   stack [(filterWhen (< (now + delay)) pat'),+          (filterWhen (between (now + delay) (now + delay + durin)) $ fout pat'),+          (filterWhen (between (now + delay + durin) (now + delay + durin + durout)) $ fin pat),+          (filterWhen (>= (now + delay + durin + durout)) $ pat)+         ]+ where+   between lo hi x = (x >= lo) && (x < hi)++washIn :: (Pattern a -> Pattern a) -> Time -> Time -> [Pattern a] -> Pattern a+washIn f durin now pats = wash f id 0 durin 0 now pats++xfadeIn :: Time -> Time -> [ControlPattern] -> ControlPattern+xfadeIn _ _ [] = silence+xfadeIn _ _ (pat:[]) = pat+xfadeIn t now (pat:pat':_) = overlay (pat |*| gain (now `rotR` (_slow t envEqR))) (pat' |*| gain (now `rotR` (_slow t (envEq))))++-- | Pans the last n versions of the pattern across the field+histpan :: Int -> Time -> [ControlPattern] -> ControlPattern+histpan _ _ [] = silence+histpan 0 _ _ = silence+histpan n _ ps = stack $ map (\(i,pat) -> pat # pan (pure $ (fromIntegral i) / (fromIntegral n'))) (enumerate ps')+  where ps' = take n ps+        n' = length ps' -- in case there's fewer patterns than requested++-- | Just stop for a bit before playing new pattern+wait :: Time -> Time -> [ControlPattern] -> ControlPattern+wait _ _ [] = silence+wait t now (pat:_) = filterWhen (>= (nextSam (now+t-1))) 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 _ _ _ [] = silence+waitT f t now pats = filterWhen (>= (nextSam (now+t-1))) (f (now + t) 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 = jumpIn 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 n = wash id id (fromIntegral n) 0 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' n now = wash id id ((nextSam now) - now + (fromIntegral n)) 0 0 now++-- | Sharp `jump` transition at next cycle boundary where cycle mod n == 0+jumpMod :: Int -> Time -> [ControlPattern] -> ControlPattern+jumpMod n now = jumpIn ((n-1) - ((floor now) `mod` n)) now++-- | Degrade the new pattern over time until it ends in silence+mortal :: Time -> Time -> Time -> [ControlPattern] -> ControlPattern+mortal _ _ _ [] = silence+mortal lifespan release now (p:_) = overlay (filterWhen (<(now+lifespan)) p) (filterWhen (>= (now+lifespan)) (fadeOutFrom (now + lifespan) release p))+++interpolate :: Time -> [ControlPattern] -> ControlPattern+interpolate = interpolateIn 4++interpolateIn :: Time -> Time -> [ControlPattern] -> ControlPattern+interpolateIn _ _ [] = silence+interpolateIn _ _ (p:[]) = p+interpolateIn t now (pat:pat':_) = f <$> pat' *> pat <* automation+  where automation = now `rotR` (_slow t envL)+        f = (\a b x -> Map.unionWith (fNum2 (\a' b' -> floor $ (fromIntegral a') * x + (fromIntegral b') * (1-x))+                                            (\a' b' -> a' * x + b' * (1-x))+                                     )+                       b 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 = clutchIn 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 _ _ [] = silence+clutchIn _ _ (p:[]) = p+clutchIn t now (p:p':_) = overlay (fadeOutFrom now t p') (fadeInFrom now t 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 t now pats = washIn (spread' (_stut 8 0.2) (now `rotR` (_slow t $ (toRational . (1-)) <$> envL))) t now 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 = anticipateIn 8
+ src/Sound/Tidal/UI.hs view
@@ -0,0 +1,1656 @@+{-# LANGUAGE TypeSynonymInstances, FlexibleInstances, OverloadedStrings #-}++module Sound.Tidal.UI where++import           Prelude hiding ((<*), (*>))++import           Data.Ord (comparing)+import           Data.Char (digitToInt, isDigit)+import           System.Random.MWC+import           Control.Monad.ST+import qualified Data.Vector as V+import           Data.Word (Word32)+import           Data.Ratio ((%),numerator,denominator)+import           Data.List (sort, sortBy, findIndices, elemIndex, groupBy, transpose)+import           Data.Maybe (isJust, fromJust, fromMaybe, mapMaybe, catMaybes)+import qualified Data.Text as T+import           Control.Applicative (liftA2)+import qualified Data.Map.Strict as Map++import           Sound.Tidal.Bjorklund (bjorklund)+import           Sound.Tidal.Core+import qualified Sound.Tidal.Params as P+import           Sound.Tidal.Pattern+import           Sound.Tidal.Utils+ +------------------------------------------------------------------------+-- * UI++-- | Randomisation++timeToRand :: RealFrac a => a -> Double+timeToRand x = runST $ do+  let x' = toRational (x*x) / 1000000+  let n' = fromIntegral $ numerator x'+  let d' = fromIntegral $ denominator x'+  seed <- initialize (V.fromList [n',d'] :: V.Vector Word32)+  uniform seed++{-|++`rand` generates a continuous pattern of (pseudo-)random numbers between `0` and `1`.++@+sound "bd*8" # pan rand+@++pans bass drums randomly++@+sound "sn sn ~ sn" # gain rand+@++makes the snares' randomly loud and quiet.++Numbers coming from this pattern are 'seeded' by time. So if you reset+time (via `cps (-1)`, then `cps 1.1` or whatever cps you want to+restart with) the random pattern will emit the exact same _random_+numbers again.++In cases where you need two different random patterns, you can shift+one of them around to change the time from which the _random_ pattern+is read, note the difference:++@+jux (# gain rand) $ sound "sn sn ~ sn" # gain rand+@++and with the juxed version shifted backwards for 1024 cycles:++@+jux (# ((1024 <~) $ gain rand)) $ sound "sn sn ~ sn" # gain rand+@+-}+rand :: Fractional a => Pattern a+rand = Pattern Analog (\(State a@(Arc s e) _) -> [Event a a (realToFrac $ timeToRand $ (e + s)/2)])++{- | Just like `rand` but for whole numbers, `irand n` generates a pattern of (pseudo-) random whole numbers between `0` to `n-1` inclusive. Notably used to pick a random+samples from a folder:++@+d1 $ n (irand 5) # sound "drum"+@+-}+irand :: Num a => Int -> Pattern a+irand i = (fromIntegral . (floor :: Double -> Int) . (* (fromIntegral i))) <$> rand++{- | 1D Perlin (smooth) noise, works like rand but smoothly moves between random+values each cycle. `perlinWith` takes a pattern as the RNG's "input" instead+of automatically using the cycle count.+@+d1 $ s "arpy*32" # cutoff (perlinWith (saw * 4) * 2000)+@+will generate a smooth random pattern for the cutoff frequency which will+repeat every cycle (because the saw does)+The `perlin` function uses the cycle count as input and can be used much like @rand@.+-}+perlinWith :: Pattern Double -> Pattern Double+perlinWith p = interp <$> (p-pa) <*> (timeToRand <$> pa) <*> (timeToRand <$> pb) where+  pa = ((fromIntegral :: Int -> Double) . floor) <$> p+  pb = ((fromIntegral :: Int -> Double) . (+1) . floor) <$> p+  interp x a b = a + smootherStep x * (b-a)+  smootherStep x = 6.0 * x**5 - 15.0 * x**4 + 10.0 * x**3++perlin :: Pattern Double+perlin = perlinWith (sig fromRational)++{- `perlin2With` is Perlin noise with a 2-dimensional input. This can be+useful for more control over how the randomness repeats (or doesn't).+@+d1 + $ s "[supersaw:-12*32]" + # lpf (rangex 60 5000 $ perlin2With (cosine*2) (sine*2)) + # lpq 0.3+@+will generate a smooth random cutoff pattern that repeats every cycle without+any reversals or discontinuities (because the 2D path is a circle).+`perlin2` only needs one input because it uses the cycle count as the+second input.+-}+perlin2With :: Pattern Double -> Pattern Double -> Pattern Double+perlin2With x y = (/2) . (+1) $ interp2 <$> xfrac <*> yfrac <*> dota <*> dotb <*> dotc <*> dotd where+  fl = fmap ((fromIntegral :: Int -> Double) . floor)+  ce = fmap ((fromIntegral :: Int -> Double) . (+1) . floor)+  xfrac = x - fl x+  yfrac = y - fl y+  randAngle a b = 2 * pi * timeToRand (a + 0.0001 * b)+  pcos x' y' = cos $ randAngle <$> x' <*> y'+  psin x' y' = sin $ randAngle <$> x' <*> y'+  dota = pcos (fl x) (fl y) * xfrac       + psin (fl x) (fl y) * yfrac+  dotb = pcos (ce x) (fl y) * (xfrac - 1) + psin (ce x) (fl y) * yfrac+  dotc = pcos (fl x) (ce y) * xfrac       + psin (fl x) (ce y) * (yfrac - 1)+  dotd = pcos (ce x) (ce y) * (xfrac - 1) + psin (ce x) (ce y) * (yfrac - 1)+  interp2 x' y' a b c d = (1.0 - s x') * (1.0 - s y') * a  +  s x' * (1.0 - s y') * b+                          + (1.0 - s x') * s y' * c  +  s x' * s y' * d+  s x' = 6.0 * x'**5 - 15.0 * x'**4 + 10.0 * x'**3++perlin2 :: Pattern Double -> Pattern Double+perlin2 = perlin2With (sig fromRational)++{- | Randomly picks an element from the given list++@+sound "superpiano(3,8)" # note (choose ["a", "e", "g", "c"])+@++plays a melody randomly choosing one of the four notes \"a\", \"e\", \"g\", \"c\".+-}+choose :: [a] -> Pattern a+choose = chooseBy rand++chooseBy :: Pattern Double -> [a] -> Pattern a+chooseBy _ [] = silence+chooseBy f xs = ((xs !!) . floor) <$> (range 0 (fromIntegral $ length xs) f)++{- | Like @choose@, but works on an a list of tuples of values and weights++@+sound "superpiano(3,8)" # note (choose [("a",1), ("e",0.5), ("g",2), ("c",1)])+@++In the above example, the "a" and "c" notes are twice as likely to+play as the "e" note, and half as likely to play as the "g" note.++-}+wchoose :: [(a,Double)] -> Pattern a+wchoose = wchooseBy rand++wchooseBy :: Pattern Double -> [(a,Double)] -> Pattern a+wchooseBy pat pairs = match <$> pat+  where+    match r = values !! (head (findIndices (> (r*total)) cweights))+    cweights = scanl1 (+) (map snd pairs)+    values = map fst pairs+    total = sum $ map snd pairs++{- |+Similar to `degrade` `degradeBy` allows you to control the percentage of events that+are removed. For example, to remove events 90% of the time:++@+d1 $ slow 2 $ degradeBy 0.9 $ sound "[[[feel:5*8,feel*3] feel:3*8], feel*4]"+   # accelerate "-6"+   # speed "2"+@++-}++degradeBy :: Pattern Double -> Pattern a -> Pattern a+degradeBy = tParam _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 = tParam _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 <*> fastRepeatCycles i rand)) <$> (slow (fromIntegral i) tx)+++{- | Use @sometimesBy@ to apply a given function "sometimes". For example, the+following code results in `density 2` being applied about 25% of the time:++@+d1 $ sometimesBy 0.25 (density 2) $ sound "bd*8"+@++There are some aliases as well:++@+sometimes = sometimesBy 0.5+often = sometimesBy 0.75+rarely = sometimesBy 0.25+almostNever = sometimesBy 0.1+almostAlways = sometimesBy 0.9+@+-}+sometimesBy :: Pattern Double -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a+sometimesBy x f p = overlay (degradeBy x p) (f $ unDegradeBy x p)++-- | @sometimes@ is an alias for sometimesBy 0.5.+sometimes :: (Pattern a -> Pattern a) -> Pattern a -> Pattern a+sometimes = sometimesBy 0.5++-- | @often@ is an alias for sometimesBy 0.75.+often :: (Pattern a -> Pattern a) -> Pattern a -> Pattern a+often = sometimesBy 0.75++-- | @rarely@ is an alias for sometimesBy 0.25.+rarely :: (Pattern a -> Pattern a) -> Pattern a -> Pattern a+rarely = sometimesBy 0.25++-- | @almostNever@ is an alias for sometimesBy 0.1+almostNever :: (Pattern a -> Pattern a) -> Pattern a -> Pattern a+almostNever = sometimesBy 0.1++-- | @almostAlways@ is an alias for sometimesBy 0.9+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@ is a cycle-by-cycle version of @sometimesBy@. It has a+`someCycles = someCyclesBy 0.5` alias -}+someCyclesBy :: Double -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a+someCyclesBy x = when test+  where test 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++somecycles :: (Pattern a -> Pattern a) -> Pattern a -> Pattern a+somecycles = someCycles++{- | `degrade` randomly removes events from a pattern 50% of the time:++@+d1 $ slow 2 $ degrade $ sound "[[[feel:5*8,feel*3] feel:3*8], feel*4]"+   # accelerate "-6"+   # speed "2"+@++The shorthand syntax for `degrade` is a question mark: `?`. Using `?`+will allow you to randomly remove events from a portion of a pattern:++@+d1 $ slow 2 $ sound "bd ~ sn bd ~ bd? [sn bd?] ~"+@++You can also use `?` to randomly remove events from entire sub-patterns:++@+d1 $ slow 2 $ sound "[[[feel:5*8,feel*3] feel:3*8]?, feel*4]"+@+-}+degrade :: Pattern a -> Pattern a+degrade = _degradeBy 0.5++++{- | (The above means that `brak` is a function from patterns of any type,+to a pattern of the same type.)++Make a pattern sound a bit like a breakbeat++Example:++@+d1 $ sound (brak "bd sn kurt")+@+-}+brak :: Pattern a -> Pattern a+brak = when ((== 1) . (`mod` 2)) (((1%4) `rotR`) . (\x -> fastcat [x, silence]))++{- | Divides a pattern into a given number of subdivisions, plays the subdivisions+in order, but increments the starting subdivision each cycle. The pattern+wraps to the first subdivision after the last subdivision is played.++Example:++@+d1 $ iter 4 $ sound "bd hh sn cp"+@++This will produce the following over four cycles:++@+bd hh sn cp+hh sn cp bd+sn cp bd hh+cp bd hh sn+@++There is also `iter'`, which shifts the pattern in the opposite direction.++-}+iter :: Pattern Int -> Pattern c -> Pattern c+iter = tParam _iter++_iter :: Int -> Pattern a -> Pattern a+_iter n p = slowcat $ map (\i -> ((fromIntegral i)%(fromIntegral n)) `rotL` p) [0 .. (n-1)]++-- | @iter'@ is the same as @iter@, but decrements the starting+-- subdivision instead of incrementing it.+iter' :: Pattern Int -> Pattern c -> Pattern c+iter' = tParam _iter'++_iter' :: Int -> Pattern a -> Pattern a+_iter' n p = slowcat $ map (\i -> ((fromIntegral i)%(fromIntegral n)) `rotR` p) [0 .. (n-1)]++-- | @palindrome p@ applies @rev@ to @p@ every other cycle, so that+-- the pattern alternates between forwards and backwards.+palindrome :: Pattern a -> Pattern a+palindrome p = slowAppend p (rev p)++-- | Composing patterns++{- | The function @seqP@ allows you to define when+a sound within a list starts and ends. The code below contains three+separate patterns in a `stack`, but each has different start times+(zero cycles, eight cycles, and sixteen cycles, respectively). All+patterns stop after 128 cycles:++@+d1 $ seqP [+  (0, 128, sound "bd bd*2"),+  (8, 128, sound "hh*2 [sn cp] cp future*4"),+  (16, 128, sound (samples "arpy*8" (run 16)))+]+@+-}+seqP :: [(Time, Time, Pattern a)] -> Pattern a+seqP ps = stack $ map (\(s, e, p) -> playFor s e ((sam s) `rotR` p)) ps++-- | Degrades a pattern over the given time.+fadeOut :: Time -> Pattern a -> Pattern a+fadeOut dur p = do slope <- _slow dur envL+                   _degradeBy slope p++-- | Alternate version to @fadeOut@ where you can provide the time from which the fade starts+fadeOutFrom :: Time -> Time -> Pattern a -> Pattern a+fadeOutFrom from dur p = do slope <- (from `rotR` _slow dur envL)+                            _degradeBy slope p+++-- | 'Undegrades' a pattern over the given time.+fadeIn :: Time -> Pattern a -> Pattern a+fadeIn dur p = do slope <- _slow dur ((1-) <$> envL)+                  _degradeBy slope p++-- | Alternate version to @fadeIn@ where you can provide the time from+-- which the fade in starts+fadeInFrom :: Time -> Time -> Pattern a -> Pattern a+fadeInFrom from dur p = do slope <- (from `rotR` _slow dur ((1-) <$> envL))+                           _degradeBy slope p+++{- | The 'spread' function allows you to take a pattern transformation+which takes a parameter, such as `slow`, and provide several+parameters which are switched between. In other words it 'spreads' a+function across several values.++Taking a simple high hat loop as an example:++@+d1 $ sound "ho ho:2 ho:3 hc"+@++We can slow it down by different amounts, such as by a half:++@+d1 $ slow 2 $ sound "ho ho:2 ho:3 hc"+@++Or by four thirds (i.e. speeding it up by a third; `4%3` means four over+three):++@+d1 $ slow (4%3) $ sound "ho ho:2 ho:3 hc"+@++But if we use `spread`, we can make a pattern which alternates between+the two speeds:++@+d1 $ spread slow [2,4%3] $ sound "ho ho:2 ho:3 hc"+@++Note that if you pass ($) as the function to spread values over, you+can put functions as the list of values. For example:++@+d1 $ spread ($) [density 2, rev, slow 2, striate 3, (# speed "0.8")]+    $ sound "[bd*2 [~ bd]] [sn future]*2 cp jvbass*4"+@++Above, the pattern will have these transforms applied to it, one at a time, per cycle:++* cycle 1: `density 2` - pattern will increase in speed+* cycle 2: `rev` - pattern will be reversed+* cycle 3: `slow 2` - pattern will decrease in speed+* cycle 4: `striate 3` - pattern will be granualized+* cycle 5: `(# speed "0.8")` - pattern samples will be played back more slowly++After `(# speed "0.8")`, the transforms will repeat and start at `density 2` again.+-}++spread :: (a -> t -> Pattern b) -> [a] -> t -> Pattern b+spread f xs p = slowcat $ map (`f` p) xs++slowspread :: (a -> t -> Pattern b) -> [a] -> t -> Pattern b+slowspread = spread++{- | @fastspread@ works the same as @spread@, but the result is squashed into a single cycle. If you gave four values to @spread@, then the result would seem to speed up by a factor of four. Compare these two:++d1 $ spread chop [4,64,32,16] $ sound "ho ho:2 ho:3 hc"++d1 $ fastspread chop [4,64,32,16] $ sound "ho ho:2 ho:3 hc"++There is also @slowspread@, which is an alias of @spread@.+-}+fastspread :: (a -> t -> Pattern b) -> [a] -> t -> Pattern b+fastspread f xs p = fastcat $ map (\x -> f x p) xs++{- | There's a version of this function, `spread'` (pronounced "spread prime"), which takes a *pattern* of parameters, instead of a list:++@+d1 $ spread' slow "2 4%3" $ sound "ho ho:2 ho:3 hc"+@++This is quite a messy area of Tidal - due to a slight difference of+implementation this sounds completely different! One advantage of+using `spread'` though is that you can provide polyphonic parameters, e.g.:++@+d1 $ spread' slow "[2 4%3, 3]" $ sound "ho ho:2 ho:3 hc"+@+-}+spread' :: Monad m => (a -> b -> m c) -> m a -> b -> m c+spread' f vpat pat = vpat >>= \v -> f v pat++{- | `spreadChoose f xs p` is similar to `slowspread` but picks values from+`xs` at random, rather than cycling through them in order. It has a+shorter alias `spreadr`.+-}+spreadChoose :: (t -> t1 -> Pattern b) -> [t] -> t1 -> Pattern b+spreadChoose f vs p = do v <- _segment 1 (choose vs)+                         f v p++spreadr :: (t -> t1 -> Pattern b) -> [t] -> t1 -> Pattern b+spreadr = spreadChoose++++{-| Decide whether to apply one or another function depending on the result of a test function that is passed the current cycle as a number.++@+d1 $ ifp ((== 0).(flip mod 2))+  (striate 4)+  (# coarse "24 48") $+  sound "hh hc"+@++This will apply `striate 4` for every _even_ cycle and aply `# coarse "24 48"` for every _odd_.++Detail: As you can see the test function is arbitrary and does not rely on anything tidal specific. In fact it uses only plain haskell functionality, that is: it calculates the modulo of 2 of the current cycle which is either 0 (for even cycles) or 1. It then compares this value against 0 and returns the result, which is either `True` or `False`. This is what the `ifp` signature's first part signifies `(Int -> Bool)`, a function that takes a whole number and returns either `True` or `False`.+-}+ifp :: (Int -> Bool) -> (Pattern a -> Pattern a) -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a+ifp test f1 f2 p = splitQueries $ p {query = q}+  where q a | test (floor $ start $ arc a) = query (f1 p) a+            | otherwise = query (f2 p) a++-- | @wedge t p p'@ combines patterns @p@ and @p'@ by squashing the+-- @p@ into the portion of each cycle given by @t@, and @p'@ into the+-- remainer of each cycle.+wedge :: Time -> Pattern a -> Pattern a -> Pattern a+wedge t p p' = overlay (_fastGap (1/t) p) (t `rotR` _fastGap (1/(1-t)) p')++{- | @whenmod@ has a similar form and behavior to `every`, but requires an+additional number. Applies the function to the pattern, when the+remainder of the current loop number divided by the first parameter,+is greater or equal than the second parameter.++For example the following makes every other block of four loops twice+as dense:++@+d1 $ whenmod 8 4 (density 2) (sound "bd sn kurt")+@+-}+whenmod :: Int -> Int -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a+whenmod a b = Sound.Tidal.Core.when ((\t -> (t `mod` a) >= b ))++{- |+@+superimpose f p = stack [p, f p]+@++`superimpose` plays a modified version of a pattern at the same time as the original pattern,+resulting in two patterns being played at the same time.++@+d1 $ superimpose (density 2) $ sound "bd sn [cp ht] hh"+d1 $ superimpose ((# speed "2") . (0.125 <~)) $ sound "bd sn cp hh"+@++-}+superimpose :: (Pattern a -> Pattern a) -> Pattern a -> Pattern a+superimpose f p = stack [p, f p]++{- | @trunc@ truncates a pattern so that only a fraction of the pattern is played.+The following example plays only the first quarter of the pattern:++@+d1 $ trunc 0.25 $ sound "bd sn*2 cp hh*4 arpy bd*2 cp bd*2"+@+-}+trunc :: Pattern Time -> Pattern a -> Pattern a+trunc = tParam _trunc++_trunc :: Time -> Pattern a -> Pattern a+_trunc t = compress (0, t) . zoomArc (Arc 0 t)++{- | @linger@ is similar to `trunc` but the truncated part of the pattern loops until the end of the cycle++@+d1 $ linger 0.25 $ sound "bd sn*2 cp hh*4 arpy bd*2 cp bd*2"+@+-}+linger :: Pattern Time -> Pattern a -> Pattern a+linger = tParam _linger++_linger :: Time -> Pattern a -> Pattern a+_linger n p = _fast (1/n) $ zoomArc (Arc 0 n) p++{- |+Use `within` to apply a function to only a part of a pattern. For example, to+apply `density 2` to only the first half of a pattern:++@+d1 $ within (0, 0.5) (density 2) $ sound "bd*2 sn lt mt hh hh hh hh"+@++Or, to apply `(# speed "0.5") to only the last quarter of a pattern:++@+d1 $ within (0.75, 1) (# speed "0.5") $ sound "bd*2 sn lt mt hh hh hh hh"+@+-}+within :: (Time, Time) -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a+within (s, e) f p = stack [filterWhen (\t -> cyclePos t >= s && cyclePos t < e) $ f p,+                           filterWhen (\t -> not $ cyclePos t >= s && cyclePos t < e) $ p+                          ]++withinArc :: Arc -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a+withinArc (Arc s e) = within (s, e)++{- |+For many cases, @within'@ will function exactly as within.+The difference between the two occurs when applying functions that change the timing of notes such as 'fast' or '<~'.+within first applies the function to all notes in the cycle, then keeps the results in the specified interval, and then combines it with the old cycle (an "apply split combine" paradigm).+within' first keeps notes in the specified interval, then applies the function to these notes, and then combines it with the old cycle (a "split apply combine" paradigm).+++For example, whereas using the standard version of within++@+d1 $ within (0, 0.25) (fast 2) $ sound "bd hh cp sd"+@++sounds like:++@+d1 $ sound "[bd hh] hh cp sd"+@++using this alternative version, within'++@+d1 $ within' (0, 0.25) (fast 2) $ sound "bd hh cp sd"+@++sounds like:++@+d1 $ sound "[bd bd] hh cp sd"+@++-}++within' :: (Time, Time) -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a+within' a@(s, e) f p =+  stack [ filterWhen (\t -> cyclePos t >= s && cyclePos t < e) $ compress a $ f $ zoom a $ p+        , filterWhen (\t -> not $ cyclePos t >= s && cyclePos t < e) $ p+        ]++revArc :: (Time, Time) -> Pattern a -> Pattern a+revArc a = within a rev++{- | You can use the @e@ function to apply a Euclidean algorithm over a+complex pattern, although the structure of that pattern will be lost:++@+d1 $ e 3 8 $ sound "bd*2 [sn cp]"+@++In the above, three sounds are picked from the pattern on the right according+to the structure given by the `e 3 8`. It ends up picking two `bd` sounds, a+`cp` and missing the `sn` entirely.++These types of sequences use "Bjorklund's algorithm", which wasn't made for+music but for an application in nuclear physics, which is exciting. More+exciting still is that it is very similar in structure to the one of the first+known algorithms written in Euclid's book of elements in 300 BC. You can read+more about this in the paper+[The Euclidean Algorithm Generates Traditional Musical Rhythms](http://cgm.cs.mcgill.ca/~godfried/publications/banff.pdf)+by Toussaint. Some examples from this paper are included below,+including rotation in some cases.++@+- (2,5) : A thirteenth century Persian rhythm called Khafif-e-ramal.+- (3,4) : The archetypal pattern of the Cumbia from Colombia, as well as a Calypso rhythm from Trinidad.+- (3,5,2) : Another thirteenth century Persian rhythm by the name of Khafif-e-ramal, as well as a Rumanian folk-dance rhythm.+- (3,7) : A Ruchenitza rhythm used in a Bulgarian folk-dance.+- (3,8) : The Cuban tresillo pattern.+- (4,7) : Another Ruchenitza Bulgarian folk-dance rhythm.+- (4,9) : The Aksak rhythm of Turkey.+- (4,11) : The metric pattern used by Frank Zappa in his piece titled Outside Now.+- (5,6) : Yields the York-Samai pattern, a popular Arab rhythm.+- (5,7) : The Nawakhat pattern, another popular Arab rhythm.+- (5,8) : The Cuban cinquillo pattern.+- (5,9) : A popular Arab rhythm called Agsag-Samai.+- (5,11) : The metric pattern used by Moussorgsky in Pictures at an Exhibition.+- (5,12) : The Venda clapping pattern of a South African children’s song.+- (5,16) : The Bossa-Nova rhythm necklace of Brazil.+- (7,8) : A typical rhythm played on the Bendir (frame drum).+- (7,12) : A common West African bell pattern.+- (7,16,14) : A Samba rhythm necklace from Brazil.+- (9,16) : A rhythm necklace used in the Central African Republic.+- (11,24,14) : A rhythm necklace of the Aka Pygmies of Central Africa.+- (13,24,5) : Another rhythm necklace of the Aka Pygmies of the upper Sangha.+@+-}+euclid :: Pattern Int -> Pattern Int -> Pattern a -> Pattern a+euclid = tParam2 _euclid++_euclid :: Int -> Int -> Pattern a -> Pattern a+_euclid n k p = (flip const) <$> (filterValues (== True) $ fastFromList $ bjorklund (n,k)) <*> p++{- | `euclidfull n k pa pb` stacks @e n k pa@ with @einv n k pb@ -}+euclidFull :: Pattern Int -> Pattern Int -> Pattern a -> Pattern a -> Pattern a+--euclidFull pn pk pa pb = innerJoin $ (\n k -> _euclidFull n k pa pb) <$> pn <*> pk+euclidFull n k pa pb = stack [ euclid n k pa, euclidInv n k pb ]++_euclidBool :: Int -> Int -> Pattern Bool+_euclidBool n k = fastFromList $ bjorklund (n,k)++_euclidFull :: Int -> Int -> Pattern a -> Pattern a -> Pattern a+_euclidFull n k p p' = pickbool <$> (_euclidBool n k) <*> p <*> p'+  where pickbool True a _ = a+        pickbool False _ b = b++-- euclid' :: Pattern Int -> Pattern Int -> Pattern a -> Pattern a+-- euclid' = tParam2 _euclidq'++_euclid' :: Int -> Int -> Pattern a -> Pattern a+_euclid' n k p = fastcat $ map (\x -> if x then p else silence) (bjorklund (n,k))++euclidOff :: Pattern Int -> Pattern Int -> Pattern Int -> Pattern a -> Pattern a+euclidOff = tParam3 _euclidOff++eoff :: Pattern Int -> Pattern Int -> Pattern Int -> Pattern a -> Pattern a+eoff = euclidOff++_euclidOff :: Int -> Int -> Int -> Pattern a -> Pattern a+_euclidOff _ 0 _ _ = silence+_euclidOff n k s p = (((fromIntegral s)%(fromIntegral k)) `rotL`) (_euclid n k p)++euclidOffBool :: Pattern Int -> Pattern Int -> Pattern Int -> Pattern Bool -> Pattern Bool+euclidOffBool = tParam3 _euclidOffBool++_euclidOffBool :: Int -> Int -> Int -> Pattern Bool -> Pattern Bool+_euclidOffBool _ 0 _ _ = silence+_euclidOffBool n k s p = (((fromIntegral s)%(fromIntegral k)) `rotL`) ((\a b -> if b then a else not a) <$> _euclidBool n k <*> p)++distrib :: [Pattern Int] -> Pattern a -> Pattern a+distrib ps p = do p' <- sequence ps+                  _distrib p' p++_distrib :: [Int] -> Pattern a -> Pattern a+_distrib xs p = boolsToPat (foldr (distrib') (replicate (last xs) True) (reverse $ layers xs)) p+  where+    distrib' :: [Bool] -> [Bool] -> [Bool]+    distrib' [] _ = []+    distrib' (_:a) [] = False:(distrib' a [])+    distrib' (True:a) (x:b) = x:(distrib' a b)+    distrib' (False:a) (b) = False:(distrib' a b)+    layers = map bjorklund . (zip<*>tail)+    boolsToPat a b' = (flip const) <$> (filterValues (== True) $ fastFromList $ a) <*> b'++{- | `euclidInv` fills in the blanks left by `e`+ -+ @e 3 8 "x"@ -> @"x ~ ~ x ~ ~ x ~"@++ @euclidInv 3 8 "x"@ -> @"~ x x ~ x x ~ x"@+-}+euclidInv :: Pattern Int -> Pattern Int -> Pattern a -> Pattern a+euclidInv = tParam2 _euclidInv++_euclidInv :: Int -> Int -> Pattern a -> Pattern a+_euclidInv n k p = (flip const) <$> (filterValues (== False) $ fastFromList $ bjorklund (n,k)) <*> p++index :: Real b => b -> Pattern b -> Pattern c -> Pattern c+index sz indexpat pat =+  spread' (zoom' $ toRational sz) (toRational . (*(1-sz)) <$> indexpat) pat+  where+    zoom' tSz s = zoomArc (Arc s (s+tSz))++{-+-- | @prrw f rot (blen, vlen) beatPattern valuePattern@: pattern rotate/replace.+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 (_fast cycles $ beatPattern) (0, blen))+    (drop (rot `mod` length values) $ cycle values)++-- | @prr rot (blen, vlen) beatPattern valuePattern@: pattern rotate/replace.+prr :: Int -> (Time, Time) -> Pattern String -> Pattern b -> Pattern b+prr = prrw $ flip const++{-|+@preplace (blen, plen) beats values@ combines the timing of @beats@ with the values+of @values@. Other ways of saying this are:+* sequential convolution+* @values@ quantized to @beats@.++Examples:++@+d1 $ sound $ preplace (1,1) "x [~ x] x x" "bd sn"+d1 $ sound $ preplace (1,1) "x(3,8)" "bd sn"+d1 $ sound $ "x(3,8)" <~> "bd sn"+d1 $ sound "[jvbass jvbass:5]*3" |+| (shape $ "1 1 1 1 1" <~> "0.2 0.9")+@++It is assumed the pattern fits into a single cycle. This works well with+pattern literals, but not always with patterns defined elsewhere. In those cases+use @preplace@ and provide desired pattern lengths:+@+let p = slow 2 $ "x x x"++d1 $ sound $ preplace (2,1) p "bd sn"+@+-}+preplace :: (Time, Time) -> Pattern String -> Pattern b -> Pattern b+preplace = preplaceWith $ flip const++-- | @prep@ is an alias for preplace.+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 len rot p@ rotates pattern @p@ by @rot@ beats to the left.+-- @len@: length of the pattern, in cycles.+-- Example: @d1 $ every 4 (protate 2 (-1)) $ slow 2 $ sound "bd hh hh hh"@+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++{-| The @<<~@ operator rotates a unit pattern to the left, similar to @<~@,+but by events rather than linear time. The timing of the pattern remains constant:++@+d1 $ (1 <<~) $ sound "bd ~ sn hh"+-- will become+d1 $ sound "sn ~ hh bd"+@ -}++(<<~) :: Int -> Pattern a -> Pattern a+(<<~) = protate 1++-- | @~>>@ is like @<<~@ but for shifting to the right.+(~>>) :: Int -> Pattern a -> Pattern a+(~>>) = (<<~) . (0-)++-- | @pequal cycles p1 p2@: quickly test if @p1@ and @p2@ are the same.+pequal :: Ord a => Time -> Pattern a -> Pattern a -> Bool+pequal cycles p1 p2 = (sort $ arc p1 (0, cycles)) == (sort $ arc p2 (0, cycles))+-}++-- | @rot n p@ rotates the values in a pattern @p@ by @n@ beats to the left.+-- Example: @d1 $ every 4 (rot 2) $ slow 2 $ sound "bd hh hh hh"@+rot :: Ord a => Pattern Int -> Pattern a -> Pattern a+rot = tParam _rot++-- Calculates a whole cycle, rotates it, then constrains events to the original query arc+_rot :: Ord a => Int -> Pattern a -> Pattern a+_rot i pat = splitQueries $ pat {query = \st -> f st (query pat (st {arc = wholeCycle (arc st)}))}+  where -- TODO maybe events with the same arc (part+whole) should be+        -- grouped together in the rotation?+        f st es = constrainEvents (arc st) $ shiftValues $ sort $ defragParts es+        shiftValues es | i >= 0 =+                         zipWith (\(Event w p _) s -> Event w p s) es+                         (drop i $ cycle $ map value es)+                       | otherwise =+                         zipWith (\(Event w p _) s -> Event w p s) es+                         (drop ((length es) - (abs i)) $ cycle $ map value es)+        wholeCycle (Arc s _) = Arc (sam s) (nextSam s)+        constrainEvents :: Arc -> [Event a] -> [Event a]+        constrainEvents a es = catMaybes $ map (constrainEvent a) es+        constrainEvent :: Arc -> Event a -> Maybe (Event a)+        constrainEvent a (Event w p v) =+          do+            p' <- subArc p a+            return (Event w p' v)++-- | @segment n p@: 'samples' the pattern @p@ at a rate of @n@+-- events per cycle. Useful for turning a continuous pattern into a+-- discrete one.+segment :: Pattern Time -> Pattern a -> Pattern a+segment = tParam _segment++_segment :: Time -> Pattern a -> Pattern a+_segment n p = (_fast n $ pure (id)) <* p++-- | @discretise@: the old (deprecated) name for 'segment'+discretise :: Pattern Time -> Pattern a -> Pattern a+discretise = segment++-- | @randcat ps@: does a @slowcat@ on the list of patterns @ps@ but+-- randomises the order in which they are played.+randcat :: [Pattern a] -> Pattern a+randcat ps = spread' (rotL) (_segment 1 $ ((%1) . fromIntegral) <$> (irand (length ps) :: Pattern Int)) (slowcat ps)++-- @fromNote p@: converts a pattern of human-readable pitch names+-- into pitch numbers. For example, @"cs2"@ will be parsed as C Sharp+-- in the 2nd octave with the result of @11@, and @"b-3"@ as+-- @-25@. Pitches can be decorated using:+--+--    * s = Sharp, a half-step above (@"gs-1"@)+--    * f = Flat, a half-step below (@"gf-1"@)+--    * n = Natural, no decoration (@"g-1" and "gn-1"@ are equivalent)+--    * ss = Double sharp, a whole step above (@"gss-1"@)+--    * ff = Double flat, a whole step below (@"gff-1"@)+--+-- Note that TidalCycles now assumes that middle C is represented by+-- the value 0, rather than the previous value of 60. This function+-- is similar to previously available functions @tom@ and @toMIDI@,+-- but the default octave is now 0 rather than 5.+{-++definition moved to Parse.hs ..++toMIDI :: Pattern String -> Pattern Int+toMIDI p = fromJust <$> (filterValues (isJust) (noteLookup <$> p))+  where+    noteLookup :: String -> Maybe Int+    noteLookup [] = Nothing+    noteLookup s | not (last s `elem` ['0' .. '9']) = noteLookup (s ++ "0")+                 | not (isLetter (s !! 1)) = noteLookup((head s):'n':(tail s))+                 | otherwise = parse s+    parse x = (\a b c -> a+b+c) <$> pc x <*> sym x <*> Just(12*digitToInt (last x))+    pc x = lookup (head x) [('c',0),('d',2),('e',4),('f',5),('g',7),('a',9),('b',11)]+    sym x = lookup (init (tail x)) [("s",1),("f",-1),("n",0),("ss",2),("ff",-2)]+-}++-- @tom p@: Alias for @toMIDI@.+-- tom = toMIDI+++{- | The `fit` function takes a pattern of integer numbers, which are used to select values from the given list. What makes this a bit strange is that only a given number of values are selected each cycle. For example:++@+d1 $ sound (fit 3 ["bd", "sn", "arpy", "arpy:1", "casio"] "0 [~ 1] 2 1")+@++The above fits three samples into the pattern, i.e. for the first cycle this will be `"bd"`, `"sn"` and `"arpy"`, giving the result `"bd [~ sn] arpy sn"` (note that we start counting at zero, so that `0` picks the first value). The following cycle the *next* three values in the list will be picked, i.e. `"arpy:1"`, `"casio"` and `"bd"`, giving the pattern `"arpy:1 [~ casio] bd casio"` (note that the list wraps round here).++-}+fit :: Int -> [a] -> Pattern Int -> Pattern a+fit perCycle xs p = (xs !!!) <$> (p {query = \st -> map ((\e -> (fmap (+ (pos e)) e))) (query p st)})+  where pos e = perCycle * (floor $ start $ part e)++permstep :: RealFrac b => Int -> [a] -> Pattern b -> Pattern a+permstep nSteps things p = unwrap $ (\n -> fastFromList $ concatMap (\x -> replicate (fst x) (snd x)) $ zip (ps !! (floor (n * (fromIntegral $ (length ps - 1))))) things) <$> (_segment 1 p)+      where ps = permsort (length things) nSteps+            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 (n-1) (total-x)) [1 .. (total-(n-1))]++-- | @struct a b@: structures pattern @b@ in terms of the pattern of+-- boolean values @a@. Only @True@ values in the boolean pattern are+-- used.+struct :: Pattern Bool -> Pattern a -> Pattern a+struct ps pv = filterJust $ (\a b -> if a then Just b else Nothing ) <$> ps <* pv++-- | @substruct a b@: similar to @struct@, but each event in pattern @a@ gets replaced with pattern @b@, compressed to fit the timespan of the event.+substruct :: Pattern String -> Pattern b -> Pattern b+substruct s p = p {query = f}+  where f st =+          concatMap (\a' -> queryArc (compressArcTo a' p) a') $ (map whole $ query s st)++randArcs :: Int -> Pattern [Arc]+randArcs n =+  do rs <- mapM (\x -> (pure $ (toRational x)/(toRational n)) <~ choose [1 :: Int,2,3]) [0 .. (n-1)]+     let rats = map toRational rs+         total = sum rats+         pairs = pairUp $ accumulate $ map ((/total)) rats+     return $ pairs+       where pairUp [] = []+             pairUp xs = (Arc 0 (head xs)):(pairUp' xs)+             pairUp' [] = []+             pairUp' (_:[]) = []+             pairUp' (a:_:[]) = [Arc a 1]+             pairUp' (a:b:xs) = (Arc a b):(pairUp' (b:xs))++-- TODO - what does this do? Something for @stripe@ ..+randStruct :: Int -> Pattern Int+randStruct n = splitQueries $ Pattern {nature = Digital, query = f}+  where f st = map (\(a,b,c) -> (Event a (fromJust b) c)) $ filter (\(_,x,_) -> isJust x) $ as+          where as = map (\(i, (Arc s' e')) ->+                    (((Arc (s' + sam s) (e' + sam s)),+                       subArc (Arc s e) (Arc (s' + sam s) (e' + sam s)), i))) $+                      enumerate $ value $ head $+                      queryArc (randArcs n) (Arc (sam s) (nextSam s))+                (Arc s e) = arc st++-- TODO - what does this do?+substruct' :: Pattern Int -> Pattern a -> Pattern a+substruct' s p = p {query = \st -> concatMap (\(Event a' _ i) -> queryArc (compressArcTo a' (inside (pure $ 1/toRational(length (queryArc s (Arc (sam (start $ arc st)) (nextSam (start $ arc st)))))) (rotR (toRational i)) p)) a') (query s st)}++-- | @stripe n p@: repeats pattern @p@, @n@ times per cycle. So+-- similar to @fast@, but with random durations. The repetitions will+-- be continguous (touching, but not overlapping) and the durations+-- will add up to a single cycle. @n@ can be supplied as a pattern of+-- integers.+stripe :: Pattern Int -> Pattern a -> Pattern a+stripe = tParam _stripe++_stripe :: Int -> Pattern a -> Pattern a+_stripe = substruct' . randStruct++-- | @slowstripe n p@: The same as @stripe@, but the result is also+-- @n@ times slower, so that the mean average duration of the stripes+-- is exactly one cycle, and every @n@th stripe starts on a cycle+-- boundary (in indian classical terms, the @sam@).+slowstripe :: Pattern Int -> Pattern a -> Pattern a+slowstripe n = slow (toRational <$> n) . stripe n++-- Lindenmayer patterns, these go well with the step sequencer+-- general rule parser (strings map to strings)+parseLMRule :: String -> [(String,String)]+parseLMRule s = map (splitOn ':') commaSplit+  where splitOn sep str = splitAt (fromJust $ elemIndex sep str)+                            $ filter (/= sep) str+        commaSplit = map T.unpack $ T.splitOn (T.pack ",") $ T.pack s++-- specific parser for step sequencer (chars map to string)+-- ruleset in form "a:b,b:ab"+parseLMRule' :: String -> [(Char, String)]+parseLMRule' str = map fixer $ parseLMRule str+  where fixer (c,r) = (head c, r)++{- | returns the `n`th iteration of a [Lindenmayer System](https://en.wikipedia.org/wiki/L-system) with given start sequence.++for example:++@+lindenmayer 1 "a:b,b:ab" "ab" -> "bab"+@+-}+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++{- | @lindenmayerI@ converts the resulting string into a a list of integers+with @fromIntegral@ applied (so they can be used seamlessly where floats or+rationals are required) -}+lindenmayerI :: Num b => Int -> String -> String -> [b]+lindenmayerI n r s = fmap fromIntegral $ fmap digitToInt $ lindenmayer n r s++-- support for fit'+unwrap' :: Pattern (Pattern a) -> Pattern a+unwrap' pp = pp {query = \st -> query (stack $ map scalep (query pp st)) st}+  where scalep ev = compressArc (whole ev) $ value ev++{-|+Removes events from second pattern that don't start during an event from first.++Consider this, kind of messy rhythm without any rests.++@+d1 $ sound (slowcat ["sn*8", "[cp*4 bd*4, hc*5]"]) # n (run 8)+@++If we apply a mask to it++@+d1 $ s (mask ("1 1 1 ~ 1 1 ~ 1" :: Pattern Bool)+  (slowcat ["sn*8", "[cp*4 bd*4, bass*5]"] ))+  # n (run 8)+@++Due to the use of `slowcat` here, the same mask is first applied to `"sn*8"` and in the next cycle to `"[cp*4 bd*4, hc*5]".++You could achieve the same effect by adding rests within the `slowcat` patterns, but mask allows you to do this more easily. It kind of keeps the rhythmic structure and you can change the used samples independently, e.g.++@+d1 $ s (mask ("1 ~ 1 ~ 1 1 ~ 1")+  (slowcat ["can*8", "[cp*4 sn*4, jvbass*16]"] ))+  # n (run 8)+@+-}++mask :: Pattern Bool -> Pattern a -> Pattern a+mask maskpat pat = filterJust $ toMaybe <$> pat'+  where pat' = matchManyToOne (flip const) maskpat pat+        toMaybe (True, a) = Just a+        toMaybe (False, _) = Nothing++{-+mask :: Pattern Bool -> Pattern b -> Pattern b+-- TODO - should that be part or whole?+mask pa pb = pb {query = \st -> concat [filterOns (subArc (arc st) $ part i) (query pb st) | i <- query pa st]}+     where filterOns Nothing _ = []+           filterOns (Just a) es = filter (onsetIn a) es+-}++-- | TODO: refactor towards union+enclosingArc :: [Arc] -> Arc+enclosingArc [] = (Arc 0 1)+enclosingArc as = Arc (minimum (map start as)) (maximum (map stop as))++stretch :: Pattern a -> Pattern a+-- TODO - should that be whole or part?+stretch p = splitQueries $ p {query = q}+  where q st = query (zoomArc (enclosingArc $ map whole $ query p (st {arc = (Arc (sam s) (nextSam s))})) p) st+          where s = start $ arc st++{- | `fit'` is a generalization of `fit`, where the list is instead constructed by using another integer pattern to slice up a given pattern.  The first argument is the number of cycles of that latter pattern to use when slicing.  It's easier to understand this with a few examples:++@+d1 $ sound (fit' 1 2 "0 1" "1 0" "bd sn")+@++So what does this do?  The first `1` just tells it to slice up a single cycle of `"bd sn"`. The `2` tells it to select two values each cycle, just like the first argument to `fit`.  The next pattern `"0 1"` is the "from" pattern which tells it how to slice, which in this case means `"0"` maps to `"bd"`, and `"1"` maps to `"sn"`.  The next pattern `"1 0"` is the "to" pattern, which tells it how to rearrange those slices.  So the final result is the pattern `"sn bd"`.++A more useful example might be something like++@+d1 $ fit' 1 4 (run 4) "[0 3*2 2 1 0 3*2 2 [1*8 ~]]/2" $ chop 4 $ (sound "breaks152" # unit "c")+@++which uses `chop` to break a single sample into individual pieces, which `fit'` then puts into a list (using the `run 4` pattern) and reassembles according to the complicated integer pattern.++-}+fit' :: Pattern Time -> Int -> Pattern Int -> Pattern Int -> Pattern a -> Pattern a+fit' cyc n from to p = unwrap' $ fit n mapMasks to+  where mapMasks = [stretch $ mask (const True <$> filterValues (== i) from') p'+                     | i <- [0..n-1]]+        p' = density cyc $ p+        from' = density cyc $ from++{-| @chunk n f p@ treats the given pattern @p@ as having @n@ chunks, and applies the function @f@ to one of those sections per cycle, running from left to right.++@+d1 $ chunk 4 (density 4) $ sound "cp sn arpy [mt lt]"+@+-}+chunk :: Int -> (Pattern b -> Pattern b) -> Pattern b -> Pattern b+chunk n f p = cat [withinArc (Arc (i%(fromIntegral n)) ((i+1)%(fromIntegral n))) f p | i <- [0..(fromIntegral n)-1]]++{-+chunk n f p = do i <- _slow (toRational n) $ run (fromIntegral n)+                 within (i%(fromIntegral n),(i+)1%(fromIntegral n)) f p+-}++-- deprecated (renamed to chunk)+runWith :: Int -> (Pattern b -> Pattern b) -> Pattern b -> Pattern b+runWith = chunk++{-| @chunk'@ works much the same as `chunk`, but runs from right to left.+-}+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)+                  withinArc (Arc (i%(fromIntegral n)) ((i+)1%(fromIntegral n))) f p++-- deprecated (renamed to chunk')+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 $ p {query = f}+  where f st = map+          (\(Event w p' v) ->+             (Event (plus w) (plus p') v)) $+          query p (st {arc = minus $ arc st})+          where minus = fmap (subtract (sam s))+                plus = fmap (+ (sam s))+                s = start $ arc st++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 (\(x,_,_) -> x) ps+        maxT = maximum $ map (\(_,x,_) -> x) ps++{- | @toScale@ lets you turn a pattern of notes within a scale (expressed as a+list) to note numbers.  For example `toScale [0, 4, 7] "0 1 2 3"` will turn+into the pattern `"0 4 7 12"`.  It assumes your scale fits within an octave;+to change this use `toScale' size`.  Example:+`toScale' 24 [0,4,7,10,14,17] (run 8)` turns into `"0 4 7 10 14 17 24 28"`+-}+toScale' :: Num a => Int -> [a] -> Pattern Int -> Pattern a+toScale' o s = fmap noteInScale+  where octave x = x `div` length s+        noteInScale x = (s !!! x) + (fromIntegral $ o * octave x)++toScale :: Num a => [a] -> Pattern Int -> Pattern a+toScale = toScale' 12++{- | `swingBy x n` divides a cycle into `n` slices and delays the notes in+the second half of each slice by `x` fraction of a slice . @swing@ is an alias+for `swingBy (1%3)`+-}+swingBy :: Pattern Time -> Pattern Time -> Pattern a -> Pattern a+swingBy x n = inside n (withinArc (Arc 0.5 1) (x ~>))++swing :: Pattern Time -> Pattern a -> Pattern a+swing = swingBy (pure $ 1%3)++{- | `cycleChoose` is like `choose` but only picks a new item from the list+once each cycle -}+cycleChoose::[a] -> Pattern a+cycleChoose xs = Pattern {nature = Digital, query = q}+  where q (State {arc = Arc s e}) = [Event (Arc s e) (Arc s e) (xs!!(floor $ dlen*(ctrand s)))]+        dlen = fromIntegral $ length xs+        ctrand s = (timeToRand :: Time -> Double) $ fromIntegral $ (floor :: Time -> Int) $ sam s++{- | `shuffle n p` evenly divides one cycle of the pattern `p` into `n` parts,+and returns a random permutation of the parts each cycle.  For example,+`shuffle 3 "a b c"` could return `"a b c"`, `"a c b"`, `"b a c"`, `"b c a"`,+`"c a b"`, or `"c b a"`.  But it will **never** return `"a a a"`, because that+is not a permutation of the parts.+-}+shuffle::Int -> Pattern a -> Pattern a+shuffle n = fit' 1 n (_run n) randpat+  where randpat = Pattern {nature = Digital,+                           query = \(State {arc = Arc s e}) -> queryArc (p $ sam s) (Arc s e)+                          }+        p c = fastFromList $ map snd $ sort $ zip+              [timeToRand (c+i/n') | i <- [0..n'-1]] [0..n-1]+        n' :: Time+        n' = fromIntegral n++{- | `scramble n p` is like `shuffle` but randomly selects from the parts+of `p` instead of making permutations.+For example, `scramble 3 "a b c"` will randomly select 3 parts from+`"a"` `"b"` and `"c"`, possibly repeating a single part.+-}+scramble::Int -> Pattern a -> Pattern a+scramble n = fit' 1 n (_run n) (_fast (fromIntegral n) $+  liftA2 (+) (pure 0) $ irand n)++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)+        -- TODO - check this really can't happen..+        getPat _ = error "can't happen?"+        match s = fromMaybe silence $ lookup s ps'+        ps' = map (fmap (_fast t)) ps+        adjust (a, (p, f)) = f a p+        transform (x:_) a = transform' x a+        transform _ _ = id+        transform' str (Arc s e) p = s `rotR` (inside (pure $ 1/(e-s)) (matchF str) p)+        matchF str = fromMaybe id $ lookup str fs+        timedValues = withEvent (\(Event a a' v) -> Event a a' (a,v))++inhabit :: [(String, Pattern a)] -> Pattern String -> Pattern a+inhabit ps p = unwrap' $ (\s -> fromMaybe silence $ lookup s ps) <$> p++{- | @spaceOut xs p@ repeats a pattern @p@ at different durations given by the list of time values in @xs@ -}+spaceOut :: [Time] -> Pattern a -> Pattern a+spaceOut xs p = _slow (toRational $ sum xs) $ stack $ map (\a -> compressArc a p) $ spaceArcs+  where markOut :: Time -> [Time] -> [Arc]+        markOut _ [] = []+        markOut offset (x:xs') = (Arc offset (offset+x)):(markOut (offset+x) xs')+        spaceArcs = map (\(Arc a b) -> (Arc (a/s) (b/s))) $ markOut 0 xs+        s = sum xs++-- | @flatpat@ takes a Pattern of lists and pulls the list elements as+-- separate Events+flatpat :: Pattern [a] -> Pattern a+flatpat p = p {query = \st -> (concatMap (\(Event b b' xs) -> map (\x -> (Event b b' x)) xs) $ query p st)}++-- | @layer@ takes a Pattern of lists and pulls the list elements as+-- separate Events+layer :: [a -> Pattern b] -> a -> Pattern b+layer fs p = stack $ map ($ p) fs++-- | @arpeggiate@ finds events that share the same timespan, and spreads+-- them out during that timespan, so for example @arpeggiate "[bd,sn]"@+-- gets turned into @"bd sn"@. Useful for creating arpeggios/broken chords.+arpeggiate :: Pattern a -> Pattern a+arpeggiate p = withEvents munge p+  where munge es = concatMap spreadOut (groupBy (\a b -> whole a == whole b) es)+        spreadOut xs = mapMaybe (\(n, x) -> shiftIt n (length xs) x) $ enumerate xs+        shiftIt n d (Event (Arc s e) a' v) =+          do+            a'' <- subArc (Arc newS newE) a'+            return (Event (Arc newS newE) a'' v)+          where newS = s + (dur*(fromIntegral n))+                newE = newS + dur+                dur = (e - s) / (fromIntegral d)++-- | Shorthand alias for arpeggiate+arpg :: Pattern a -> Pattern a+arpg = arpeggiate++{- TODO !++-- | @fill@ 'fills in' gaps in one pattern with events from another. For example @fill "bd" "cp ~ cp"@ would result in the equivalent of `"~ bd ~"`. This only finds gaps in a resulting pattern, in other words @"[bd ~, sn]"@ doesn't contain any gaps (because @sn@ covers it all), and @"bd ~ ~ sn"@ only contains a single gap that bridges two steps.+fill :: Pattern a -> Pattern a -> Pattern a+fill p' p = struct (splitQueries $ p {query = q}) p'+  where+    q st = removeTolerance (s,e) $ invert (s-tolerance, e+tolerance) $ query p (st {arc = (s-tolerance, e+tolerance)})+      where (s,e) = arc st+    invert (s,e) es = map arcToEvent $ foldr remove [(s,e)] (map part es)+    remove (s,e) xs = concatMap (remove' (s, e)) xs+    remove' (s,e) (s',e') | s > s' && e < e' = [(s',s),(e,e')] -- inside+                          | s > s' && s < e' = [(s',s)] -- cut off right+                          | e > s' && e < e' = [(e,e')] -- cut off left+                          | s <= s' && e >= e' = [] -- swallow+                          | otherwise = [(s',e')] -- miss+    arcToEvent a = ((a,a),"x")+    removeTolerance (s,e) es = concatMap (expand) $ map (withPart f) es+      where f a = concatMap (remove' (e,e+tolerance)) $ remove' (s-tolerance,s) a+            expand ((a,xs),c) = map (\x -> ((a,x),c)) xs+    tolerance = 0.01+-}++-- Repeats each event @n@ times within its arc+ply :: Pattern Int -> Pattern a -> Pattern a+ply = tParam _ply++_ply :: Int -> Pattern a -> Pattern a+_ply n p = arpeggiate $ stack (replicate n p)++-- Uses the first (binary) pattern to switch between the following two+-- patterns.+sew :: Pattern Bool -> Pattern a -> Pattern a -> Pattern a+sew stitch p1 p2 = overlay (const <$> p1 <* a) (const <$> p2 <* b)+  where a = filterValues (id) stitch+        b = filterValues (not . id) stitch+++stutter :: Integral i => i -> Time -> Pattern a -> Pattern a+stutter n t p = stack $ map (\i -> (t * (fromIntegral i)) `rotR` p) [0 .. (n-1)]++echo, triple, quad, double :: Time -> Pattern a -> Pattern a+echo   = stutter (2 :: Int)+triple = stutter (3 :: Int)+quad   = stutter (4 :: Int)+double = echo++{- | The `jux` function creates strange stereo effects, by applying a+function to a pattern, but only in the right-hand channel. For+example, the following reverses the pattern on the righthand side:++@+d1 $ slow 32 $ jux (rev) $ striateBy 32 (1/16) $ sound "bev"+@++When passing pattern transforms to functions like [jux](#jux) and [every](#every),+it's possible to chain multiple transforms together with `.`, for+example this both reverses and halves the playback speed of the+pattern in the righthand channel:++@+d1 $ slow 32 $ jux ((# speed "0.5") . rev) $ striateBy 32 (1/16) $ sound "bev"+@+-}+jux+  :: (Pattern ControlMap -> Pattern ControlMap)+     -> Pattern ControlMap -> Pattern ControlMap+jux = juxBy 1+juxcut+  :: (Pattern ControlMap -> Pattern ControlMap)+     -> Pattern ControlMap -> Pattern ControlMap+juxcut f p = stack [p     # P.pan (pure 0) # P.cut (pure (-1)),+                    f $ p # P.pan (pure 1) # P.cut (pure (-2))+                   ]++juxcut' :: [t -> Pattern ControlMap] -> t -> Pattern ControlMap+juxcut' fs p = stack $ map (\n -> ((fs !! n) p |+ P.cut (pure $ 1-n)) # P.pan (pure $ fromIntegral n / fromIntegral l)) [0 .. l-1]+  where l = length fs++{- | In addition to `jux`, `jux'` allows using a list of pattern transform. resulting patterns from each transformation will be spread via pan from left to right.++For example:++@+d1 $ jux' [iter 4, chop 16, id, rev, palindrome] $ sound "bd sn"+@++will put `iter 4` of the pattern to the far left and `palindrome` to the far right. In the center the original pattern will play and mid left mid right the chopped and the reversed version will appear.++One could also write:++@+d1 $ stack [+    iter 4 $ sound "bd sn" # pan "0",+    chop 16 $ sound "bd sn" # pan "0.25",+    sound "bd sn" # pan "0.5",+    rev $ sound "bd sn" # pan "0.75",+    palindrome $ sound "bd sn" # pan "1",+    ]+@++-}+jux' :: [t -> Pattern ControlMap] -> t -> Pattern ControlMap+jux' fs p = stack $ map (\n -> ((fs !! n) p) |+ P.pan (pure $ fromIntegral n / fromIntegral l)) [0 .. l-1]+  where l = length fs++-- | Multichannel variant of `jux`, _not sure what it does_+jux4+  :: (Pattern ControlMap -> Pattern ControlMap)+     -> Pattern ControlMap -> Pattern ControlMap+jux4 f p = stack [p # P.pan (pure (5/8)), f $ p # P.pan (pure (1/8))]++{- |+With `jux`, the original and effected versions of the pattern are+panned hard left and right (i.e., panned at 0 and 1). This can be a+bit much, especially when listening on headphones. The variant `juxBy`+has an additional parameter, which brings the channel closer to the+centre. For example:++@+d1 $ juxBy 0.5 (density 2) $ sound "bd sn:1"+@++In the above, the two versions of the pattern would be panned at 0.25+and 0.75, rather than 0 and 1.+-}+juxBy+  :: Pattern Double+     -> (Pattern ControlMap -> Pattern ControlMap)+     -> Pattern ControlMap+     -> Pattern ControlMap+juxBy n f p = stack [p |+ P.pan 0.5 |- P.pan (n/2), f $ p |+ P.pan 0.5 |+ P.pan (n/2)]++pick :: String -> Int -> String+pick name n = name ++ ":" ++ (show n)++-- samples "jvbass [~ latibro] [jvbass [latibro jvbass]]" ((1%2) `rotL` slow 6 "[1 6 8 7 3]")++samples :: Applicative f => f String -> f Int -> f String+samples p p' = pick <$> p <*> p'++samples' :: Applicative f => f String -> f Int -> f String+samples' p p' = (flip pick) <$> p' <*> p++{-+scrumple :: Time -> Pattern a -> Pattern a -> Pattern a+scrumple o p p' = p'' -- overlay p (o `rotR` p'')+  where p'' = Pattern $ \a -> concatMap+                              (\((s,d), vs) -> map (\x -> ((s,d),+                                                           snd x+                                                          )+                                                   )+                                                   (arc p' (s,s))+                              ) (arc p a)+-}++spreadf :: [a -> Pattern b] -> a -> Pattern b+spreadf = spread ($)++stackwith :: Unionable a => Pattern a -> [Pattern a] -> Pattern a+stackwith p ps | null ps = silence+               | otherwise = stack $ map (\(i, p') -> p' # (((fromIntegral i) % l) `rotL` p)) (zip [0::Int ..] ps)+  where l = fromIntegral $ length ps++{-+cross f p p' = Pattern $ \t -> concat [filter flt $ arc p t,+                                       filter (not . flt) $ arc p' t+                                      ]+]  where flt = f . cyclePos . fst . fst+-}++{- | `range` will take a pattern which goes from 0 to 1 (like `sine`), and range it to a different range - between the first and second arguments. In the below example, `range 1 1.5` shifts the range of `sine1` from 0 - 1 to 1 - 1.5.++@+d1 $ jux (iter 4) $ sound "arpy arpy:2*2"+  |+ speed (slow 4 $ range 1 1.5 sine1)+@+-}++range :: Num a => Pattern a -> Pattern a -> Pattern a -> Pattern a+range fromP toP p = do+  from <- fromP+  to <- toP+  _range from to p++_range :: (Functor f, Num b) => b -> b -> f b -> f b+_range from to p = ((+ from) . (* (to-from))) <$> p++{- | `rangex` is an exponential version of `range`, good for using with+frequencies.  Do *not* use negative numbers or zero as arguments! -}+rangex :: (Functor f, Floating b) => b -> b -> f b -> f b+rangex from to p = exp <$> _range (log from) (log to) p++off :: Pattern Time -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a+off tp f p = innerJoin $ (\tv -> _off tv f p) <$> tp++_off :: Time -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a+_off t f p = superimpose (f . (t `rotR`)) p++offadd :: Num a => Pattern Time -> Pattern a -> Pattern a -> Pattern a+offadd tp pn p = off tp (+pn) p++-- | Step sequencing+step :: String -> String -> Pattern String+step s cs = fastcat $ map f cs+    where f c | c == 'x' = pure s+              | isDigit c = pure $ s ++ ":" ++ [c]+              | otherwise = silence++steps :: [(String, String)] -> Pattern String+steps = stack . map (\(a,b) -> step a b)++-- | like `step`, but allows you to specify an array of strings to use for 0,1,2...+step' :: [String] -> String -> Pattern String+step' ss cs = fastcat $ map f cs+    where f c | c == 'x' = pure $ head ss+              | isDigit c = pure $ ss!!(digitToInt c)+              | otherwise = silence+++ghost'' :: Time -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a+ghost'' a f p = superimpose (((a*2.5) `rotR`) . f) $ superimpose (((a*1.5) `rotR`) . f) $ p++ghost' :: Time -> Pattern ControlMap -> Pattern ControlMap+ghost' a p = ghost'' a ((|*| P.gain (pure 0.7)) . (|> P.end (pure 0.2)) . (|*| P.speed (pure 1.25))) p++ghost :: Pattern ControlMap -> Pattern ControlMap+ghost p = ghost' 0.125 p++{- |+   tabby - A more literal weaving than the `weave` function, give number+   of 'threads' per cycle and two patterns, and this function will weave them+   together using a plain (aka 'tabby') weave, with a simple over/under structure+ -}+tabby :: Int -> Pattern a -> Pattern a -> Pattern a+tabby nInt p p' = stack [maskedWarp,+                      maskedWeft+                     ]+  where+    n = fromIntegral nInt+    weft = concatMap (\_ -> [[0..n-1],(reverse [0..n-1])]) [0 .. (n `div` 2) - 1]+    warp = transpose weft+    thread xs p'' = _slow (n%1) $ fastcat $ map (\i -> zoomArc (Arc (i%n) ((i+1)%n)) p'') (concat xs)+    weftP = thread weft p'+    warpP = thread warp p+    maskedWeft = mask (every 2 rev $ _fast ((n)%2) $ fastCat [silence, pure True]) weftP+    maskedWarp = mask (every 2 rev $ _fast ((n)%2) $ fastCat [pure True, silence]) warpP++_select :: Double -> [Pattern a] -> Pattern a+_select f ps =  ps !! (floor $ (max 0 $ min 1 f) * (fromIntegral $ length ps - 1))++-- | chooses between a list of patterns, using a pattern of floats (from 0-1)+select :: Pattern Double -> [Pattern a] -> Pattern a+select = tParam _select+++-- | @contrast p f f' p'@ splits controlpattern @p'@ in two, applying+-- the function @f@ to one and @f'@ to the other. This depends on+-- whether events in it contains values matching with those in @p@.+-- For example in @contrast (n "1") (# crush 3) (# vowel "a") $ n "0 1" # s "bd sn" # speed 3@,+-- the first event will have the vowel effect applied and the second+-- will have the crush applied.+++contrast :: (ControlPattern -> ControlPattern) -> (ControlPattern -> ControlPattern)+            -> ControlPattern -> ControlPattern -> ControlPattern+contrast = contrastBy (==)++contrastBy :: (a -> Value -> Bool)+              -> (ControlPattern -> Pattern b)+              -> (ControlPattern -> Pattern b)+              -> Pattern (Map.Map String a)+              -> Pattern (Map.Map String Value)+              -> Pattern b+contrastBy comp f f' p p' = overlay (f matched) (f' unmatched)+  where matches = matchManyToOne (flip $ Map.isSubmapOfBy comp) p p'+        matched :: ControlPattern+        matched = filterJust $ (\(t, a) -> if t then Just a else Nothing) <$> matches+        unmatched :: ControlPattern+        unmatched = filterJust $ (\(t, a) -> if not t then Just a else Nothing) <$> matches++contrastRange+  :: (ControlPattern -> Pattern a)+     -> (ControlPattern -> Pattern a)+     -> Pattern (Map.Map String (Value, Value))+     -> ControlPattern+     -> Pattern a+contrastRange = contrastBy f+      where f (VI s, VI e) (VI v) = v >= s && v <= e +            f (VF s, VF e) (VF v) = v >= s && v <= e +            f (VS s, VS e) (VS v) = v == s && v == e+            f _ _ = False++-- | Like @contrast@, but one function is given, and applied to events with matching controls.+fix :: (ControlPattern -> ControlPattern) -> ControlPattern -> ControlPattern -> ControlPattern+fix f = contrast f id++-- | Like @contrast@, but one function is given, and applied to events+-- with controls which don't match.+unfix :: (ControlPattern -> ControlPattern) -> ControlPattern -> ControlPattern -> ControlPattern+unfix f = contrast id f++fixRange :: (ControlPattern -> Pattern ControlMap)+            -> Pattern (Map.Map String (Value, Value))+            -> ControlPattern+            -> Pattern ControlMap+fixRange f = contrastRange f id++unfixRange :: (ControlPattern -> Pattern ControlMap)+              -> Pattern (Map.Map String (Value, Value))+              -> ControlPattern+              -> Pattern ControlMap+unfixRange f = contrastRange id f++-- | limit values in a Pattern (or other Functor) to n equally spaced+-- divisions of 1.+quantise :: (Functor f, RealFrac b) => b -> f b -> f b+quantise n = fmap ((/n) . (fromIntegral :: RealFrac b => Int -> b) . floor . (*n))++-- | Inverts all the values in a boolean pattern+inv :: Functor f => f Bool -> f Bool+inv = (not <$>)++-- | Serialises a pattern so there's only one event playing at any one+-- time, making it 'monophonic'. Events which start/end earlier are given priority.+mono :: Pattern a -> Pattern a+mono p = Pattern Digital $ \(State a cm) -> flatten $ (query p) (State a cm) where+  flatten :: [Event a] -> [Event a]+  flatten = catMaybes . map constrainPart . truncateOverlaps . sortBy (comparing whole)+  truncateOverlaps [] = []+  truncateOverlaps (e:es) = e:(truncateOverlaps $ catMaybes $ map (snip e) es)+  snip a b | (start $ whole b) >= (stop $ whole a) = Just b+           | (stop $ whole b) <= (stop $ whole a) = Nothing+           | otherwise = Just b {whole = Arc (stop $ whole a) (stop $ whole b)}+  constrainPart :: Event a -> Maybe (Event a)+  constrainPart e = do a <- subArc (whole e) (part e)+                       return $ e {part = a}++-- serialize the given pattern+-- find the middle of the query's arc and use that to query the serialized pattern. We should get either no events or a single event back+-- if we don't get any events, return nothing+-- if we get an event, get the stop of its arc, and use that to query the serialized pattern, to see if there's an adjoining event+-- if there isn't, return the event as-is.+-- if there is, check where we are in the 'whole' of the event, and use that to tween between the values of the event and the next event+-- smooth :: Pattern Double -> Pattern Double++smooth :: Fractional a => Pattern a -> Pattern a+smooth p = Pattern Analog $ \st@(State a cm) -> tween st a $ query monoP (State (midArc a) cm)+  where+    midArc a = Arc (mid (start a, stop a)) (mid (start a, stop a))+    tween _ _ [] = []+    tween st queryA (e:_) = maybe [e {whole = queryA, part = queryA}] (tween' queryA) (nextV st)+      where aStop = Arc (wholeStop e) (wholeStop e)+            nextEs st' = query monoP (st' {arc = aStop})+            nextV st' | null (nextEs st') = Nothing+                      | otherwise = Just $ value (head (nextEs st'))+            tween' queryA' v =+              [ Event+                { whole = queryA'+                , part = queryA'+                , value = value e + ((v - value e) * pc)}+              ]+            pc | (delta' $ whole e) == 0 = 0+               | otherwise = fromRational $ (eventPartStart e - wholeStart e) / (delta' $ whole e)+            delta' a = stop a - start a+    monoP = mono p
+ src/Sound/Tidal/Utils.hs view
@@ -0,0 +1,73 @@+module Sound.Tidal.Utils where++import Data.List (delete)++mapBoth :: (a -> a) -> (a,a) -> (a,a)+mapBoth f (a,b) = (f a, f b)++mapPartTimes :: (a -> a) -> ((a,a),(a,a)) -> ((a,a),(a,a))+mapPartTimes f part = mapBoth (mapBoth f) part++mapFst :: (a -> b) -> (a, c) -> (b, c)+mapFst f (x,y) = (f x,y)++mapSnd :: (a -> b) -> (c, a) -> (c, b)+mapSnd f (x,y) = (x,f y)++delta :: Num a => (a, a) -> a+delta (a,b) = b-a++-- | The midpoint of two values+mid :: Fractional a => (a,a) -> a+mid (a,b) = a + ((b - a) / 2)++removeCommon :: Eq a => [a] -> [a] -> ([a],[a])+removeCommon [] bs = ([],bs)+removeCommon as [] = (as,[])+removeCommon (a:as) bs | elem a bs = removeCommon as (delete a bs)+                       | otherwise = (a:as',bs')+                           where (as',bs') = removeCommon as bs++readMaybe        :: (Read a) => String -> Maybe a+readMaybe s      =  case [x | (x,t) <- reads s, ("","") <- lex t] of+                         [x] -> Just x+                         _   -> Nothing++{- | like `!!` selects @n@th element from xs, but wraps over at the end of @xs@++>>> map ((!!!) [1,3,5]) [0,1,2,3,4,5]+[1,3,5,1,3,5]+-}+(!!!) :: [a] -> Int -> a+(!!!) xs n = xs !! (n `mod` length xs)+++{- | Safer version of !! --}+nth :: Int -> [a] -> Maybe a+nth _ []       = Nothing+nth 0 (x : _)  = Just x+nth n (_ : xs) = nth (n - 1) xs++accumulate :: Num t => [t] -> [t]+accumulate = accumulate' 0+  where accumulate' _ [] = []+        accumulate' n (a:xs) = (n+a):(accumulate' (n+a) xs)++{- | enumerate a list of things++>>> enumerate ["foo","bar","baz"]+[(1,"foo"), (2,"bar"), (3,"baz")]+-}+enumerate :: [a] -> [(Int, a)]+enumerate = zip [0..]++{- | split given list of @a@ by given single a, e.g.++>>> wordsBy (== ':') "bd:3"+["bd", "3"]+-}+wordsBy :: (a -> Bool) -> [a] -> [[a]]+wordsBy p s = case dropWhile p s of+   []      -> []+   s':rest -> (s':w) : wordsBy p (drop 1 s'')+          where (w, s'') = break p rest
+ test/Sound/Tidal/CoreTest.hs view
@@ -0,0 +1,136 @@+{-# LANGUAGE OverloadedStrings #-}++module Sound.Tidal.CoreTest where++import TestUtils+import Test.Microspec++import Prelude hiding ((<*), (*>))++import Data.Ratio+import Data.List (sort)++import Sound.Tidal.Context++run :: Microspec ()+run =+  describe "Sound.Tidal.Core" $ do+    describe "append" $ do+      it "can switch between the cycles from two pures" $ do+        (queryArc (append (pure "a") (pure "b")) (Arc 0 5)) `shouldBe`+          fmap toEvent+          [(((0,1), (0,1)), "a" :: String),+            (((1,2), (1,2)), "b"),+            (((2,3), (2,3)), "a"),+            (((3,4), (3,4)), "b"),+            (((4,5), (4,5)), "a")+          ]+    describe "cat" $ do+      it "can switch between the cycles from three pures" $ do+        queryArc (cat [pure "a", pure "b", pure "c"]) (Arc 0 5) `shouldBe`+          fmap toEvent+          [(((0,1), (0,1)), "a" :: String),+            (((1,2), (1,2)), "b"),+            (((2,3), (2,3)), "c"),+            (((3,4), (3,4)), "a"),+            (((4,5), (4,5)), "b")+          ]++    describe "fastCat" $ do+      it "can switch between the cycles from three pures inside one cycle" $ do+        it "1" $ queryArc (fastCat [pure "a", pure "b", pure "c"]) (Arc 0 1)+          `shouldBe` fmap toEvent+          [(((0,1/3),   (0,1/3)),   "a" :: String),+            (((1/3,2/3), (1/3,2/3)), "b"),+            (((2/3,1),   (2/3,1)),   "c")+          ]+        it "5/3" $ queryArc (fastCat [pure "a", pure "b", pure "c"]) (Arc 0 (5/3))+          `shouldBe` fmap toEvent+          [(((0,1/3),   (0,1/3)),   "a" :: String),+            (((1/3,2/3), (1/3,2/3)), "b"),+            (((2/3,1),   (2/3,1)),   "c"),+            (((1,4/3),   (1,4/3)),   "a"),+            (((4/3,5/3), (4/3,5/3)), "b")+          ]+      it "works with zero-length queries" $ do+        it "0" $+          queryArc (fastCat [pure "a", pure "b"]) (Arc 0 0)+            `shouldBe` fmap toEvent [(((0,0.5), (0,0)), "a" :: String)]+        it "1/3" $+          queryArc (fastCat [pure "a", pure "b"]) (Arc (1%3) (1%3))+            `shouldBe` fmap toEvent [(((0,0.5), (1%3,1%3)), "a" :: String)]++    describe "rev" $ do+      it "mirrors events" $ do+        let forward = fastCat [fastCat [pure 7, pure 8], pure 9] :: Pattern Int+            backward = fastCat [pure 9, fastCat [pure 8, pure 7]]+        -- sort the events into time order to compare them+        (sort $ queryArc (rev forward) (Arc 0 1)) `shouldBe` (sort $ queryArc (backward) (Arc 0 1))++      it "returns the original if you reverse it twice" $ do+        let x = fastCat [fastCat [pure 7, pure 8], pure 9] :: Pattern Int+        (queryArc (rev $ rev x) (Arc 0 5)) `shouldBe` (queryArc x (Arc 0 5))++    describe "compress" $ do+      it "squashes cycles to the start of a cycle" $ do+        let p = compress (0, 0.5) $ fastCat [pure 7, pure 8] :: Pattern Int+        (queryArc p (Arc 0 1)) `shouldBe` fmap toEvent+          [ (((0,0.25),  (0,0.25)),   7),+            (((0.25,0.5),(0.25,0.5)), 8)+          ]+      it "squashes cycles to the end of a cycle" $ do+        let p = compress (0.5, 1) $ fastCat [pure 7, pure 8] :: Pattern Int+        (queryArc p (Arc 0 1)) `shouldBe` fmap toEvent+          [(((0.5,0.75),  (0.5,0.75)), 7 :: Int),+           (((0.75,1),    (0.75,1)),   8)+          ]+      it "squashes cycles to the middle of a cycle" $ do+        let p = compress (0.25, 0.75) $ fastCat [pure 7, pure 8]+        (queryArc p (Arc 0 1)) `shouldBe` fmap toEvent+          [(((0.25,0.5),  (0.25,0.5)), 7 :: Int),+            (((0.5,0.75),  (0.5,0.75)), 8)+          ]++    describe "saw" $ do+      it "goes from 0 up to 1 every cycle" $ do+        it "0" $+          (queryArc saw (Arc 0 0))    `shouldBe` fmap toEvent [(((0,0), (0,0)),    0 :: Float)]+        it "0.25" $+          (queryArc saw (Arc 0.25 0.25)) `shouldBe` fmap toEvent [(((0.25,0.25), (0.25,0.25)), 0.25 :: Float)]+        it "0.5" $+          (queryArc saw (Arc 0.5 0.5))  `shouldBe` fmap toEvent [(((0.5,0.5), (0.5,0.5) ), 0.5 :: Float)]+        it "0.75" $+          (queryArc saw (Arc 0.75 0.75)) `shouldBe` fmap toEvent [(((0.75,0.75), (0.75,0.75)), 0.75 :: Float)]+      it "can be added to" $ do+        (map value $ queryArc ((+1) <$> saw) (Arc 0.5 0.5)) `shouldBe` [1.5 :: Float]+      it "works on the left of <*>" $ do+        (queryArc ((+) <$> saw <*> pure 3) (Arc 0 1))+          `shouldBe` fmap toEvent [(((0,1), (0,1)), 3 :: Float)]+      it "works on the right of <*>" $ do+        (queryArc ((fast 4 $ pure (+3)) <*> saw) (Arc 0 1))+          `shouldBe` fmap toEvent+          [(((0,0.25), (0,0.25)), 3 :: Float),+            (((0.25,0.5), (0.25,0.5)), 3.25),+            (((0.5,0.75), (0.5,0.75)), 3.5),+            (((0.75,1), (0.75,1)), 3.75)+          ]+      it "can be reversed" $ do+        it "works with whole cycles" $+          (queryArc (rev saw) (Arc 0 1))+            `shouldBe` fmap toEvent [(((0,1), (0,1)), 0.5 :: Float)]+        it "works with half cycles" $+          (queryArc (rev saw) (Arc 0 0.5))+            `shouldBe` fmap toEvent [(((0,0.5), (0,0.5)), 0.75 :: Float)]+        it "works with inset points" $+          (queryArc (rev saw) (Arc 0.25 0.25))+            `shouldBe` fmap toEvent [(((0.25,0.25), (0.25,0.25)), 0.75 :: Float)]++    describe "tri" $ do+      it "goes from 0 up to 1 and back every cycle" $ do+        comparePD (Arc 0 1)+          (struct "t*8" (tri :: Pattern Double))+          ("0 0.25 0.5 0.75 1 0.75 0.5 0.25")+      it "can be added to" $ do+        comparePD (Arc 0 1)+          (struct "t*8" $ (tri :: Pattern Double) + 1)+          ("1 1.25 1.5 1.75 2 1.75 1.5 1.25")
+ test/Sound/Tidal/MiniTidalTest.hs view
@@ -0,0 +1,135 @@+{-# LANGUAGE OverloadedStrings #-}++module Sound.Tidal.MiniTidalTest where++import Test.Microspec+import Sound.Tidal.MiniTidal+import Sound.Tidal.Context as Tidal+import Data.Either+import Text.ParserCombinators.Parsec (ParseError)+import qualified Data.Map.Strict as Map++parsesTo :: String -> ControlPattern -> Property+parsesTo str p = x `shouldBe` y+  where x = query <$> miniTidal str <*> Right (State (Arc 0 16) Map.empty)+        y = Right $ query p $ State (Arc 0 16) Map.empty++causesParseError :: String -> Property+causesParseError str = isLeft (miniTidal str :: Either ParseError ControlPattern) `shouldBe` True++run :: Microspec ()+run =+  describe "miniTidal" $ do++    it "parses the empty string as silence" $+      "" `parsesTo` silence++    it "parses a string containing only spaces as silence" $+      "    " `parsesTo` silence++    it "parses a very simple single 's' pattern" $+      "s \"bd cp\"" `parsesTo` s "bd cp"++    it "parses a single 's' pattern that uses angle brackets" $+      "s \"<bd cp>\"" `parsesTo` s "<bd cp>"++    it "parses a single 's' pattern that uses square brackets" $+      "s \"[bd sn] cp\"" `parsesTo` s "[bd sn] cp"++    it "parses a single 's' pattern that uses square brackets and *" $+      "s \"[bd sn]*2 cp\"" `parsesTo` s "[bd sn]*2 cp"++    it "parses a single 's' pattern that uses Bjorklund rhythms" $+      "s \"sn(5,16)\"" `parsesTo` s "sn(5,16)"++    it "parses a literal int as a double pattern" $+      "pan 0" `parsesTo` (pan 0)++    it "parses a literal double as a double pattern" $+      "pan 1.0" `parsesTo` (pan 1.0)++    it "parses a negative literal double as a double pattern" $+      "pan (-1.0)" `parsesTo` (pan (-1.0))++    it "parses two merged patterns" $+      "s \"bd cp\" # pan \"0 1\"" `parsesTo` (s "bd cp" # pan "0 1")++    it "parses three merged patterns" $+      "s \"bd cp\" # pan \"0 1\" # gain \"0.5 0.7\"" `parsesTo`+        (s "bd cp" # pan "0 1" # gain "0.5 0.7")++    it "parses three merged patterns, everything in brackets" $+      "(s \"bd cp\" # pan \"0 1\" # gain \"0.5 0.7\")" `parsesTo`+        ((s "bd cp" # pan "0 1" # gain "0.5 0.7"))++    it "parses three merged patterns, everything in muliple layers of brackets" $+      "(((s \"bd cp\" # pan \"0 1\" # gain \"0.5 0.7\")))" `parsesTo`+        ((((s "bd cp" # pan "0 1" # gain "0.5 0.7"))))++    it "parses three merged patterns with right associative brackets" $+      "s \"bd cp\" # (pan \"0 1\" # gain \"0.5 0.7\")" `parsesTo`+        (s "bd cp" # (pan "0 1" # gain "0.5 0.7"))++    it "parses three merged patterns with left associative brackets" $+      "(s \"bd cp\" # pan \"0 1\") # gain \"0.5 0.7\"" `parsesTo`+        ((s "bd cp" # pan "0 1") # gain "0.5 0.7")++    it "parses simple patterns in brackets applied to ParamPattern functions" $+      "s (\"bd cp\")" `parsesTo` (s ("bd cp"))++    it "parses simple patterns applied to ParamPattern functions with $" $+      "s $ \"bd cp\"" `parsesTo` (s $ "bd cp")++    it "parses addition of simple patterns" $+      "n (\"0 1\" + \"2 3\")" `parsesTo` (n ("0 1" + "2 3"))++    it "parses multiplication of simple patterns as a merged parampattern" $+      "s \"arpy*8\" # up (\"3\" * \"2\")" `parsesTo` (s "arpy*8" # up ("3" * "2"))++    it "parses pan patterns" $+      "pan \"0 0.25 0.5 0.75 1\"" `parsesTo` (pan "0 0.25 0.5 0.75 1")++    it "parses note patterns" $+      "note \"0 0.25 0.5 0.75 1\"" `parsesTo` (note "0 0.25 0.5 0.75 1")++    it "parses sine oscillators" $+      "pan sine" `parsesTo` (pan sine)++    it "parses sine oscillators used in pan patterns" $+      "s \"arpy*8\" # pan sine" `parsesTo` (s "arpy*8" # pan sine)++    it "parses fast transformations of parampatterns" $+      "fast 2 $ s \"bd cp\"" `parsesTo` (fast 2 $ s "bd cp")++    it "parses fast transformations of parampatterns when in brackets" $+      "(fast 2) $ s \"bd cp\"" `parsesTo` ((fast 2) $ s "bd cp")++    it "parses rev transformations of parampatterns" $+      "rev $ s \"bd cp\"" `parsesTo` (rev $ s "bd cp")++    it "parses rev transformations of parampatterns when in brackets" $+      "(rev) $ s \"bd cp\"" `parsesTo` ((rev) $ s "bd cp")++    it "parses jux transformations with transformations in brackets" $+        "jux (rev) $ s \"arpy*8\" # up \"0 2 3 5 3 5 7 8\"" `parsesTo`+         (jux (rev) $ s "arpy*8" # up "0 2 3 5 3 5 7 8")++    it "parses jux transformations with transformations not in brackets" $+        "jux rev $ s \"arpy*8\" # up \"0 2 3 5 3 5 7 8\"" `parsesTo`+         (jux rev $ s "arpy*8" # up "0 2 3 5 3 5 7 8")++    it "doesn't parse when a transformation requiring an argument is provided without parens or $ to jux" $+      causesParseError "jux fast 2 $ s \"bd*4 cp\""++    it "parses multiple fast transformations of parampatterns" $+      "fast 2 $ fast 2 $ s \"bd cp\"" `parsesTo` (fast 2 $ fast 2 $ s "bd cp")++    it "parses an 'every' transformation applied to a simple s pattern" $+      "every 2 (fast 2) (s \"bd cp\")" `parsesTo` (every 2 (fast 2) (s "bd cp"))++    it "parses a transformed pattern merged with a pattern constructed from parampatterning an arithmetic expression on patterns" $+      "(every 2 (fast 2) $ s \"arpy*8\") # up (\"[0 4 7 2,16 12 12 16]\" - \"<0 3 5 7>\")" `parsesTo` ((every 2 (fast 2) $ s "arpy*8") # up ("[0 4 7 2,16 12 12 16]" - "<0 3 5 7>"))++    it "parses a fast transformation applied to a simple (ie. non-param) pattern" $+      "up (fast 2 \"<0 2 3 5>\")" `parsesTo`+        (up (fast 2 "<0 2 3 5>"))
+ test/Sound/Tidal/ParseTest.hs view
@@ -0,0 +1,69 @@+{-# LANGUAGE OverloadedStrings #-}++module Sound.Tidal.ParseTest where++import TestUtils+import Test.Microspec++import Prelude hiding ((<*), (*>))++import Sound.Tidal.Core+import Sound.Tidal.Pattern++run :: Microspec ()+run =+  describe "Sound.Tidal.Parse" $ do+    describe "parseBP_E" $ do+      it "can parse strings" $ do+        compareP (Arc 0 12)+          ("a b c" :: Pattern String)+          (fastCat ["a", "b", "c"])+      it "can parse ints" $ do+        compareP (Arc 0 2)+          ("0 1 2 3 4 5 6 7 8 0 10 20 30 40 50" :: Pattern Int)+          (fastCat $ map (pure . read) $ words "0 1 2 3 4 5 6 7 8 0 10 20 30 40 50")+      it "can alternate with <>" $ do+        compareP (Arc 0 2)+          ("a <b c>" :: Pattern String)+          (cat [fastCat ["a", "b"], fastCat ["a", "c"]])+      it "can slow with /" $ do+        compareP (Arc 0 2)+          ("a/2" :: Pattern String)+          (slow 2 $ "a")+      it "can speed up with *" $ do+        compareP (Arc 0 2)+          ("a*8" :: Pattern String)+          (fast 8 "a")+      it "can do polymeter with {}" $ do+        compareP (Arc 0 2)+          ("{a b, c d e}" :: Pattern String)+          (stack [fastcat [pure "a", pure "b"], slow 1.5 $ fastcat [pure "c", pure "d", pure "e"]])+      it "can parse a chord" $ do+        compareP (Arc 0 2)+          ("'major" :: Pattern Int)+          ("[0,4,7]")+      it "can parse two chords" $ do+        compareP (Arc 0 2)+          ("'major 'minor" :: Pattern Int)+          ("[0,4,7] [0,3,7]")+      it "can parse c chords" $ do+        compareP (Arc 0 2)+          ("'major 'minor 'dim7" :: Pattern Int)+          ("c'major c'minor c'dim7")+      it "can parse various chords" $ do+        compareP (Arc 0 2)+          ("c'major e'minor f'dim7" :: Pattern Int)+          ("c e f" + "'major 'minor 'dim7")+      it "doesn't crash on zeroes (1)" $ do+        compareP (Arc 0 2)+          ("cp/0" :: Pattern String)+          (silence)+      it "doesn't crash on zeroes (2)" $ do+        compareP (Arc 0 2)+          ("cp(5,0)" :: Pattern String)+          (silence)+      it "doesn't crash on zeroes (3)" $ do+        compareP (Arc 0 2)+          ("cp(5,c)" :: Pattern String)+          (silence)+
+ test/Sound/Tidal/PatternTest.hs view
@@ -0,0 +1,430 @@+{-# LANGUAGE OverloadedStrings #-}++module Sound.Tidal.PatternTest where++import           Test.Microspec+import           TestUtils++import           Prelude             hiding ((*>), (<*))++import           Data.Bifunctor (first, second)+import           Data.Ratio++import           Sound.Tidal.Control+import           Sound.Tidal.Core+import           Sound.Tidal.Pattern++import qualified Data.Map.Strict     as Map++run :: Microspec ()+run =+  describe "Sound.Tidal.Pattern" $ do+    describe "Arc" $ do+      it "Arc is a Functor: Apply a given function to the start and end values of an Arc" $ do+        let res = fmap (+1) (Arc 3 5)+        property $ ((Arc 4 6) :: Arc) === res++    describe "Event" $ do+      it "(Bifunctor) first: Apply a function to the Arc elements: whole and part" $ do+        let res = Event (Arc 1 2) (Arc 3 4) 5 :: Event Int+            f = (+1)+        property $+          first f res ===+          Event (Arc 2 3) (Arc 4 5) 5+      it "(Bifunctor) second: Apply a function to the event element" $ do+        let res = Event (Arc 1 2) (Arc 3 4) 5 :: Event Int+            f = (+1)+        property $+          second f res ===+          Event (Arc 1 2) (Arc 3 4) 6++    describe "whole" $ do+      it "returns the whole Arc in an Event" $ do+        property $ Arc 1 2 === whole (Event (Arc 1 2) (Arc 3 4) 5 :: Event Int)++    describe "part" $ do+      it "returns the part Arc in an Event" $ do+        property $ Arc 3 4 === part (Event (Arc 1 2) (Arc 3 4) 5 :: Event Int)++    describe "value" $ do+      it "returns the event value in an Event" $ do+        property $ 5 === value (Event (Arc 1 2 :: Arc) (Arc 3 4) ( 5 :: Int))++    describe "wholeStart" $ do +      it "retrieve the onset of an event: the start of the whole Arc" $ do +        property $ 1 === wholeStart (Event (Arc 1 2) (Arc 3 4) (5 :: Int))++    describe "eventHasOnset" $ do +      it "return True when the start values of the two arcs in an event are equal" $ do +        let ev = (Event (Arc 1 2) (Arc 1 3) (4 :: Int)) +        property $ True === eventHasOnset ev +      it "return False when the start values of the two arcs in an event are not equal" $ do +        let ev = (Event (Arc 1 2) (Arc 3 4) (5 :: Int)) +        property $ False === eventHasOnset ev++    describe "pure" $ do+      it "fills a whole cycle" $ do+        property $ queryArc (pure 0) (Arc 0 1) === [(Event (Arc 0 1) (Arc 0 1) (0 :: Int))]+      it "returns the part of an pure that you ask for, preserving the whole" $ do+        property $ queryArc (pure 0) (Arc 0.25 0.75) === [(Event (Arc 0 1) (Arc 0.25 0.75) (0 :: Int))]+      it "gives correct fragments when you go over cycle boundaries" $ do+        property $ queryArc (pure 0) (Arc 0.25 1.25) ===+          [ (Event (Arc 0 1) (Arc 0.25 1) (0 :: Int)),+            (Event (Arc 1 2) (Arc 1 1.25) 0)+          ]+      it "works with zero-length queries" $ do+        it "0" $+          queryArc (pure "a") (Arc 0 0)+            `shouldBe` fmap toEvent [(((0,1), (0,0)), "a" :: String)]+        it "1/3" $+          queryArc (pure "a") (Arc (1%3) (1%3))+            `shouldBe` fmap toEvent [(((0,1), (1%3,1%3)), "a" :: String)]++    describe "_fastGap" $ do+      it "copes with cross-cycle queries" $ do+        (queryArc(_fastGap 2 $ fastCat [pure "a", pure "b"]) (Arc 0.5 1.5))+          `shouldBe`+          [(Event (Arc (1 % 1) (5 % 4)) (Arc (1 % 1) (5 % 4)) ("a" :: String)),+           (Event (Arc (5 % 4) (3 % 2)) (Arc (5 % 4) (3 % 2)) "b")+          ]+      it "does not return events outside of the query" $ do+        (queryArc(_fastGap 2 $ fastCat [pure "a", pure ("b" :: String)]) (Arc 0.5 0.9))+          `shouldBe` []++    describe "<*>" $ do+      it "can apply a pattern of values to a pattern of values" $ do+        queryArc ((pure (+1)) <*> (pure 3)) (Arc 0 1) `shouldBe` fmap toEvent [(((0,1), (0,1)), 4  :: Int)]+      it "can take structure from the left" $ do+        queryArc ((fastCat [pure (+1), pure (+2)]) <*> (pure 3)) (Arc 0 1) `shouldBe` fmap toEvent+          [(((0,0.5), (0,0.5)), 4 :: Int),+            (((0.5,1), (0.5,1)), 5)+          ]+      it "can take structure from the right" $ do+        queryArc (pure (+1) <*> (fastCat [pure 7, pure 8])) (Arc 0 1) `shouldBe` fmap toEvent+          [(((0,0.5), (0,0.5)), 8 :: Int),+            (((0.5,1), (0.5,1)), 9)+          ]+      it "can take structure from the both sides" $ do+        it "one" $+          queryArc ((fastCat [pure (+1), pure (+2)]) <*> (fastCat [pure 7, pure 8])) (Arc 0 1)+          `shouldBe` fmap toEvent+          [(((0,0.5), (0,0.5)), 8 :: Int),+            (((0.5,1), (0.5,1)), 10)+          ]+        it "two" $+          queryArc ((fastCat [pure (+1), pure (+2), pure (+3)]) <*> (fastCat [pure 7, pure 8])) (Arc 0 1)+          `shouldBe` fmap toEvent+          [ (((0%1, 1%3), (0%1, 1%3)), 8 :: Int),+            (((1%3, 1%2), (1%3, 1%2)), 9),+            (((1%2, 2%3), (1%2, 2%3)), 10),+            (((2%3, 1%1), (2%3, 1%1)), 11)+          ]+      it "obeys pure id <*> v = v" $ do+        let v = (fastCat [fastCat [pure 7, pure 8], pure 9]) :: Pattern Int+        queryArc ((pure id <*> v)) (Arc 0 5) `shouldBe` queryArc v (Arc 0 5)++      it "obeys pure f <*> pure x = pure (f x)" $ do+        let f = (+3)+            x = 7 :: Int+        queryArc (pure f <*> pure x) (Arc 0 5) `shouldBe` queryArc (pure (f x)) (Arc 0 5)++      it "obeys u <*> pure y = pure ($ y) <*> u" $ do+        let u = fastCat [pure (+7), pure (+8)]+            y = 6 :: Int+        queryArc (u <*> pure y) (Arc 0 5) `shouldBe` queryArc (pure ($ y) <*> u) (Arc 0 5)++      it "obeys pure (.) <*> u <*> v <*> w = u <*> (v <*> w)" $ do+        let u = (fastCat [pure (+7), pure (+8)]) :: Pattern (Int -> Int)+            v = fastCat [pure (+3), pure (+4), pure (+5)]+            w = fastCat [pure 1, pure 2]+        queryArc (pure (.) <*> u <*> v <*> w) (Arc 0 5) `shouldBe` queryArc (u <*> (v <*> w)) (Arc 0 5)++    describe "<*" $ do+      it "can apply a pattern of values to a pattern of functions" $ do+        queryArc ((pure (+1)) <* (pure 3)) (Arc 0 1) `shouldBe` fmap toEvent+          [(((0,1), (0,1)), 4  :: Int)]+      it "doesn't take structure from the right" $ do+        queryArc (pure (+1) <* (fastCat [pure 7, pure 8])) (Arc 0 1)+          `shouldBe` fmap toEvent [(((0,1), (0,1)), 8 :: Int)]++    describe "*>" $ do+      it "can apply a pattern of values to a pattern of functions" $ do+        it "works within cycles" $ queryArc ((pure (+1)) *> (pure 3)) (Arc 0 1) `shouldBe` fmap toEvent [(((0,1), (0,1)), 4  :: Int)]+        it "works across cycles" $ queryArc ((pure (+1)) *> (slow 2 $ pure 3)) (Arc 0 1) `shouldBe` fmap toEvent [(((0,2), (0,1)), 4  :: Int)]+      it "doesn't take structure from the left" $ do+        queryArc (pure (+1) *> (fastCat [pure 7, pure 8])) (Arc 0 1)+          `shouldBe` fmap toEvent+          [(((0,0.5), (0,0.5)), 8 :: Int),+            (((0.5,1), (0.5,1)), 9 :: Int)+          ]++    describe "arcCycles" $ do+     it "leaves a unit cycle intact" $ do+       it "(0,1)" $ arcCycles (Arc 0 1) `shouldBe` [(Arc 0 1)]+       it "(3,4)" $ arcCycles (Arc 3 4) `shouldBe` [(Arc 3 4)]+     it "splits a cycle at cycle boundaries" $ do+       it "(0,1.1)" $ arcCycles (Arc 0 1.1) `shouldBe` [(Arc 0 1),(Arc 1 1.1)]+       it "(1,2,1)" $ arcCycles (Arc 1 2.1) `shouldBe` [(Arc 1 2),(Arc 2 2.1)]+       it "(3 + (1%3),5.1)" $+          arcCycles (Arc (3 + (1%3)) 5.1) `shouldBe` [(Arc (3+(1%3)) 4),(Arc 4 5),(Arc 5 5.1)]++    describe "unwrap" $ do+      it "preserves inner structure" $ do+        it "one" $+          (queryArc (unwrap $ pure (fastCat [pure "a", pure ("b" :: String)])) (Arc 0 1))+          `shouldBe` (queryArc (fastCat [pure "a", pure "b"]) (Arc 0 1))+        it "two" $+          (queryArc (unwrap $ pure (fastCat [pure "a", pure "b", fastCat [pure "c", pure ("d" :: String)]])) (Arc 0 1))+          `shouldBe` (queryArc (fastCat [pure "a", pure "b", fastCat [pure "c", pure "d"]]) (Arc 0 1))+      it "preserves outer structure" $ do+        it "one" $+          (queryArc (unwrap $ fastCat [pure $ pure "a", pure $ pure ("b" :: String)]) (Arc 0 1))+          `shouldBe` (queryArc (fastCat [pure "a", pure "b"]) (Arc 0 1))+        it "two" $+          (queryArc (unwrap $ fastCat [pure $ pure "a", pure $ pure "b", fastCat [pure $ pure "c", pure $ pure ("d" :: String)]]) (Arc 0 1))+          `shouldBe` (queryArc (fastCat [pure "a", pure "b", fastCat [pure "c", pure "d"]]) (Arc 0 1))+      it "gives events whole/part timespans that are an intersection of that of inner and outer events" $ do+        let a = fastCat [pure "a", pure "b"]+            b = fastCat [pure "c", pure "d", pure "e"]+            pp = fastCat [pure a, pure b]+        queryArc (unwrap pp) (Arc 0 1)+          `shouldBe` [(Event (Arc (0 % 1) (1 % 2)) (Arc (0 % 1) (1 % 2)) ("a" :: String)),+                      (Event (Arc (1 % 2) (2 % 3)) (Arc (1 % 2) (2 % 3)) "d"),+                      (Event (Arc (2 % 3) (1 % 1)) (Arc (2 % 3) (1 % 1)) "e")+                     ]++    describe "unwrapSqueeze" $ do+      it "compresses cycles to fit outer 'whole' timearc of event" $ do+        let a = fastCat [pure "a", pure "b"]+            b = fastCat [pure "c", pure "d", pure "e"]+            pp = fastCat [pure a, pure b]+        queryArc (unwrapSqueeze pp) (Arc 0 1)+          `shouldBe` [(Event (Arc (0 % 1) (1 % 4)) (Arc (0 % 1) (1 % 4)) ("a" :: String)),+                      (Event (Arc (1 % 4) (1 % 2)) (Arc (1 % 4) (1 % 2)) "b"),+                      (Event (Arc (1 % 2) (2 % 3)) (Arc (1 % 2) (2 % 3)) "c"),+                      (Event (Arc (2 % 3) (5 % 6)) (Arc (2 % 3) (5 % 6)) "d"),+                      (Event (Arc (5 % 6) (1 % 1)) (Arc (5 % 6) (1 % 1)) "e")+                     ]++    describe ">>=" $ do+      it "can apply functions to patterns" $ do+       let p = fastCat [pure 7, pure 8] :: Pattern Int+           p' = do x <- p+                   return $ x + 1+       (queryArc p' (Arc 0 1)) `shouldBe` (queryArc ((+1) <$> p) (Arc 0 1))++      it "can add two patterns together" $ do+       let p1 = fastCat [pure 7, pure 8, pure 9] :: Pattern Int+           p2 = fastCat [pure 4, fastCat [pure 5, pure 6]]+           p' = do x <- p1+                   y <- p2+                   return $ x + y+       compareP (Arc 0 1) p' ((+) <$> p1 <*> p2)++      it "conforms to (return v) >>= f = f v" $ do+       let f x = pure $ x + 10+           v = 5 :: Int+       compareP (Arc 0 5) ((return v) >>= f) (f v)+      it "conforms to m >>= return ≡ m" $ do+       let m = fastCat [pure "a", fastCat [pure "b", pure ("c" :: String)]]+       compareP (Arc 0 1) (m >>= return) m+     --    it "conforms to (m >>= f) >>= g ≡ m >>= ( \x -> (f x >>= g) )" $ do+     --      let m = fastCat [pure "a", fastCat [pure "b", pure "c"]]++    describe "rotR" $ do+      it "works over two cycles" $+       property $ comparePD (Arc 0 2) (0.25 ~> pure "a") (0.25 `rotR` pure ("a" :: String))+      it "works over one cycle" $+       property $ compareP (Arc 0 1) (0.25 ~> pure "a") (0.25 `rotR` pure ("a" :: String))+      it "works with zero width queries" $+       property $ compareP (Arc 0 0) (0.25 ~> pure "a") (0.25 `rotR` pure ("a" :: String))++    describe "comparePD" $ do+      it "allows split events to be compared" $+       property $ comparePD (Arc 0 2)+         (splitQueries $ _slow 2 $ pure ("a" :: String))+         (_slow 2 $ pure "a")++    describe "controlI" $ do+      it "can retrieve values from state" $+       (query (pure 3 + cF_ "hello") $ State (Arc 0 1) (Map.singleton "hello" (VF 0.5)))+       `shouldBe` [(Event (Arc (0 % 1) (1 % 1)) (Arc (0 % 1) (1 % 1)) 3.5)]++    describe "wholeStart" $ do +      it "retrieve first element of a tuple, inside first element of a tuple, inside the first of another" $ do +        property $ 1 === wholeStart (Event (Arc 1 2) (Arc 3 4) (5 :: Int))++    describe "eventValue" $ do+      it "retrieve the second value from a tuple" $ do +        property $ 5 === eventValue (Event (Arc 1 2) (Arc 3 4) (5 :: Int))++    describe "eventHasOnset" $ do +      it "return True when the start values of the two arcs in an event are equal" $ do +        let ev = (Event (Arc 1 2) (Arc 1 3) (4 :: Int)) +        property $ True === eventHasOnset ev +      it "return False when the start values of the two arcs in an event are not equal" $ do +        let ev = (Event (Arc 1 2) (Arc 3 4) (5 :: Int)) +        property $ False === eventHasOnset ev++    describe "sam" $ do+      it "start of a cycle, round down time value" $ do+        let res = sam (3.4 :: Time)+        property $ (3.0 :: Time) === res++    describe "nextSam" $ do+      it "the end point of the current cycle, and start of the next" $ do+        let res = nextSam (3.4 :: Time)+        property $ (4.0 :: Time) === res++    describe "arcCycles" $ do +      it "if start time is greater than end time return empty list" $ do +        let res = arcCycles (Arc 2.3 2.1)+        property $ [] === res +      it "if start time is equal to end time return empty list" $ do +        let res = arcCycles (Arc 3 3)+        property $ [] === res+      it "if start and end time round down to same value return list of (start, end)" $ do+        let res = arcCycles (Arc 2.1 2.3) +        property $ [(Arc 2.1 2.3)] === res+      it "if start time is less than end time and start time does not round down to same value as end time" $ do+        let res = arcCycles (Arc 2.1 3.3)+        property $ [(Arc 2.1 3.0), (Arc 3.0 3.3)] === res++    describe "arcCyclesZW" $ do+      it "if start and end time are equal return list of (start, end)" $ do+        let res = arcCyclesZW (Arc 2.5 2.5)+        property $ [(Arc 2.5 2.5)] === res+      it "if start and end time are not equal call arcCycles (start, end) with same rules as above" $ do+        let res = arcCyclesZW (Arc 2.3 2.1)+        property $ [] === res+      it "if start time is less than end time" $ do+        let res = arcCyclesZW (Arc 2.1 2.3)+        property $ [(Arc 2.1 2.3)] === res+      it "if start time is greater than end time" $ do+        let res = arcCyclesZW (Arc 2.1 3.3)+        property $ [(Arc 2.1 3.0), (Arc 3.0 3.3)] === res++    describe "mapCycle" $ do+      it "Apply a function to the Arc values minus the start value rounded down (sam'), adding both results to sam' to obtain the new Arc value" $ do+        let res = mapCycle (*2) (Arc 3.3 5)+        property $ ((Arc 3.6 7.0) :: Arc) === res++    describe "toTime" $ do+      it "Convert a number of type Real to a Time value of type Rational, Int test" $ do+        let res = toTime (3 :: Int)+        property $ (3 % 1 :: Time) === res+      it "Convert a number of type Double to a Time value of type Rational" $ do+        let res = toTime (3.2 :: Double)+        property $ (3602879701896397 % 1125899906842624 :: Time) === res++    describe "cyclePos" $ do+      it "Subtract a Time value from its value rounded down (the start of the cycle)" $ do+        let res = cyclePos 2.6+        property $ (0.6 :: Time) === res+      it "If no difference between a given Time and the start of the cycle" $ do+        let res = cyclePos 2+        property $ (0.0 :: Time) === res++    describe "isIn" $ do+      it "Check given Time is inside a given Arc value, Time is greater than start and less than end Arc values" $ do+        let res = isIn (Arc 2.0 2.8) 2.5+        property $ True === res+      it "Given Time is equal to the Arc start value" $ do+        let res = isIn (Arc 2.0 2.8) 2.0+        property $ True === res+      it "Given Time is less than the Arc start value" $ do+        let res = isIn (Arc 2.0 2.8) 1.4+        property $ False === res+      it "Given Time is greater than the Arc end value" $ do+        let res = isIn (Arc 2.0 2.8) 3.2+        property $ False === res++    describe "onsetIn" $ do+      it "If the beginning of an Event is within a given Arc, same rules as 'isIn'" $ do +         let res = onsetIn (Arc 2.0 2.8) (Event (Arc 2.2 2.7) (Arc 3.3 3.8) (5 :: Int))+         property $ True === res +      it "Beginning of Event is equal to beggining of given Arc" $ do +         let res = onsetIn (Arc 2.0 2.8) (Event (Arc 2.0 2.7) (Arc 3.3 3.8) (5 :: Int))+         property $ True === res +      it "Beginning of an Event is less than the start of the Arc" $ do +         let res = onsetIn (Arc 2.0 2.8) (Event (Arc 1.2 1.7) (Arc 3.3 3.8) (5 :: Int))+         property $ False === res+      it "Start of Event is greater than the start of the given Arc" $ do +         let res = onsetIn (Arc 2.0 2.8) (Event (Arc 3.1 3.5) (Arc 4.0 4.6) (5 :: Int))+         property $ False === res++    describe "subArc" $ do+      it "Checks if an Arc is within another, returns Just (max $ (fst a1) (fst a2), min $ (snd a1) (snd a2)) if so, otherwise Nothing" $ do       +        let res = subArc (Arc 2.1 2.4) (Arc 2.4 2.8)+        property $ Nothing === res+      it "if max (fst arc1) (fst arc2) <= min (snd arc1) (snd arc2) return Just (max (fst arc1) (fst arc2), min...)" $ do+        let res = subArc (Arc 2 2.8) (Arc 2.4 2.9)+        property $ Just (Arc 2.4 2.8) === res++    describe "timeToCycleArc" $ do+      it "given a Time value return the Arc in which it resides" $ do+        let res = timeToCycleArc 2.2 +        property $ (Arc 2.0 3.0) === res++    describe "cyclesInArc" $ do +      it "Return a list of cycles in a given arc, if start is greater than end return empty list" $ do +        let res = cyclesInArc (Arc 2.4 2.2)+        property $ ([] :: [Int]) === res+      it "If start value of Arc is equal to end value return list with start value rounded down" $ do+        let res = cyclesInArc (Arc 2.4 2.4)+        property $ ([2] :: [Int]) === res+      it "if start of Arc is less than end return list of start rounded down to end rounded up minus one" $ do+        let res = cyclesInArc (Arc 2.2 4.5)+        property $ ([2,3,4] :: [Int]) === res  ++    describe "cycleArcsInArc" $ do+      it "generates a list of Arcs based on the cycles found within a given a Arc" $ do+       let res = cycleArcsInArc (Arc 2.2 4.5) +       property $ [(Arc 2.0 3.0), (Arc 3.0 4.0), (Arc 4.0 5.0)] === res++    describe "isAdjacent" $ do+      it "if the given Events are adjacent parts of the same whole" $ do +        let res = isAdjacent (Event (Arc 1 2) (Arc 3 4) 5) (Event (Arc 1 2) (Arc 4 3) (5 :: Int))+        property $ True === res +      it "if first Arc of of first Event is not equal to first Arc of second Event" $ do+        let res = isAdjacent (Event (Arc 1 2) (Arc 3 4) 5) (Event (Arc 7 8) (Arc 4 3) (5 :: Int))+        property $ False === res  +      it "if the value of the first Event does not equal the value of the second Event" $ do +        let res = isAdjacent (Event (Arc 1 2) (Arc 3 4) 5) (Event (Arc 1 2) (Arc 4 3) (6 :: Int))+        property $ False === res +      it "second value of second Arc of first Event not equal to first value of second Arc in second Event..." $ do+        let res = isAdjacent (Event (Arc 1 2) (Arc 3 4) 5) (Event (Arc 1 2) (Arc 3 4) (5 :: Int))+        property $ False === res ++    describe "defragParts" $ do +      it "if empty list with no events return empty list" $ do +        let res = defragParts ([] :: [Event Int]) +        property $ [] === res+      it "if list consists of only one Event return it as is" $ do +        let res = defragParts [(Event (Arc 1 2) (Arc 3 4) (5 :: Int))]+        property $ [Event (Arc 1 2) (Arc 3 4) (5 :: Int)] === res +      it "if list contains adjacent Events return list with Parts combined" $ do +        let res = defragParts [(Event (Arc 1 2) (Arc 3 4) (5 :: Int)), (Event (Arc 1 2) (Arc 4 3) (5 :: Int))]+        property $ [(Event (Arc 1 2) (Arc 3 4) 5)] === res+      it "if list contains more than one Event none of which are adjacent, return List as is" $ do +        let res = defragParts [(Event (Arc 1 2) (Arc 3 4) 5), (Event (Arc 7 8) (Arc 4 3) (5 :: Int))]+        property $ [Event (Arc 1 2) (Arc 3 4) 5, Event (Arc 7 8) (Arc 4 3) (5 :: Int)] === res++    describe "compareDefrag" $ do +      it "compare list with Events with empty list of Events" $ do+        let res = compareDefrag [Event (Arc 1 2) (Arc 3 4) (5 :: Int), Event (Arc 1 2) (Arc 4 3) (5 :: Int)] []+        property $ False === res +      it "compare lists containing same Events but of different length" $ do +        let res = compareDefrag [Event (Arc 1 2) (Arc 3 4) (5 :: Int), Event (Arc 1 2) (Arc 4 3) 5] [Event (Arc 1 2) (Arc 3 4) (5 :: Int)]+        property $ True === res+      it "compare lists of same length with same Events" $ do +        let res = compareDefrag [Event (Arc 1 2) (Arc 3 4) (5 :: Int)] [Event (Arc 1 2) (Arc 3 4) (5 :: Int)]+        property $ True === res ++    -- pending "Sound.Tidal.Pattern.eventL" $ do+    --  it "succeeds if the first event 'whole' is shorter" $ do+    --    property $ eventL (Event (Arc 0,0),(Arc 0 1)),"x") (((0 0) (Arc 0 1.1)) "x")+    --  it "fails if the events are the same length" $ do+    --    property $ not $ eventL (Event (Arc 0,0),(Arc 0 1)),"x") (((0 0) (Arc 0 1)) "x")+    --  it "fails if the second event is shorter" $ do+    --    property $ not $ eventL (Event (Arc 0,0),(Arc 0 1)),"x") (((0 0) (Arc 0 0.5)) "x")
+ test/Sound/Tidal/UITest.hs view
@@ -0,0 +1,171 @@+{-# LANGUAGE OverloadedStrings #-}++module Sound.Tidal.UITest where++import TestUtils+import Test.Microspec++import Prelude hiding ((<*), (*>))++import qualified Data.Map.Strict as Map++-- import Sound.Tidal.Pattern+import Sound.Tidal.Control+import Sound.Tidal.Core+import Sound.Tidal.Params+import Sound.Tidal.Pattern+import Sound.Tidal.UI++run :: Microspec ()+run =+  describe "Sound.Tidal.UI" $ do+    describe "_chop" $ do+      it "can chop in two bits" $ do+        compareP (Arc 0 1)+          (_chop 2 $ s (pure "a"))+          (begin (fastcat [pure 0, pure 0.5]) # end (fastcat [pure 0.5, pure 1]) # (s (pure "a")))+      it "can be slowed" $ do+        compareP (Arc 0 1)+          (slow 2 $ _chop 2 $ s (pure "a"))+          (begin (pure 0) # end (pure 0.5) # (s (pure "a")))+      it "can chop a chop" $+        property $ compareTol (Arc 0 1) (_chop 6 $ s $ pure "a") (_chop 2 $ _chop 3 $ s $ pure "a")++    describe "segment" $ do+      it "can turn a single event into multiple events" $ do+        compareP (Arc 0 3)+          (segment 4 "x")+          ("x*4" :: Pattern String)+      it "can turn a continuous pattern into multiple discrete events" $ do+        compareP (Arc 0 3)+          (segment 4 saw)+          ("0 0.25 0.5 0.75" :: Pattern Double)+      it "can hold a value over multiple cycles" $ do+        comparePD (Arc 0 8)+          (segment 0.5 saw)+          (slow 2 "0" :: Pattern Double)+      it "holding values over multiple cycles works in combination" $ do+        comparePD (Arc 0 8)+          ("0*4" |+ (_segment (1/8) $ saw))+          ("0*4" :: Pattern Double)++    describe "sometimesBy" $ do+      it "does nothing when set at 0% probability" $ do+        let+          overTimeSpan = (Arc 0  1)+          testMe = sometimesBy 0 (rev) (ps "bd*2 hh sn")+          expectedResult = ps "bd*2 hh sn"+          in+            compareP overTimeSpan testMe expectedResult++      it "applies the 'rev' function when set at 100% probability" $ do+        let+          overTimeSpan = (Arc 0  1)+          testMe = sometimesBy 1 (rev) (ps "bd*2 hh cp")+          expectedResult = ps "cp hh bd*2"+          in+            compareP overTimeSpan testMe expectedResult++    describe "rand" $ do+      it "generates a (pseudo-)random number between zero & one" $ do+        it "at the start of a cycle" $+          (queryArc rand (Arc 0 0)) `shouldBe` fmap toEvent [(((0, 0), (0, 0)), 0.5000844 :: Float)]+        it "at 1/4 of a cycle" $+          (queryArc rand (Arc 0.25 0.25)) `shouldBe` fmap toEvent+            [(((0.25, 0.25), (0.25, 0.25)), 0.8587171 :: Float)]+        it "at 3/4 of a cycle" $+          (queryArc rand (Arc 0.75 0.75)) `shouldBe` fmap toEvent+            [(((0.75, 0.75), (0.75, 0.75)), 0.7277789 :: Float)]++    describe "range" $ do+      describe "scales a pattern to the supplied range" $ do+        describe "from 3 to 4" $ do+          it "at the start of a cycle" $+            (queryArc (Sound.Tidal.UI.range 3 4 saw) (Arc 0 0)) `shouldBe` fmap toEvent+              [(((0, 0), (0, 0)), 3 :: Float)]+          it "at 1/4 of a cycle" $+            (queryArc (Sound.Tidal.UI.range 3 4 saw) (Arc 0.25  0.25)) `shouldBe` fmap toEvent+              [(((0.25, 0.25), (0.25, 0.25)), 3.25 :: Float)]+          it "at 3/4 of a cycle" $+            (queryArc (Sound.Tidal.UI.range 3 4 saw) (Arc 0.75 0.75)) `shouldBe` fmap toEvent+              [(((0.75, 0.75), (0.75, 0.75)), 3.75 :: Float)]++        describe "from -1 to 1" $ do+          it "at 1/2 of a cycle" $+            (queryArc (Sound.Tidal.UI.range (-1) 1 saw) (Arc 0.5 0.5)) `shouldBe` fmap toEvent+              [(((0.5, 0.5), (0.5, 0.5)), 0 :: Float)]++        describe "from 4 to 2" $ do+          it "at the start of a cycle" $+            (queryArc (Sound.Tidal.UI.range 4 2 saw) (Arc 0 0)) `shouldBe` fmap toEvent+              [(((0, 0), (0, 0)), 4 :: Float)]+          it "at 1/4 of a cycle" $+            (queryArc (Sound.Tidal.UI.range 4 2 saw) (Arc 0.25 0.25)) `shouldBe` fmap toEvent+              [(((0.25, 0.25), (0.25, 0.25)), 3.5 :: Float)]+          it "at 3/4 of a cycle" $+            (queryArc (Sound.Tidal.UI.range 4 2 saw) (Arc 0.75 0.75)) `shouldBe` fmap toEvent+              [(((0.75, 0.75), (0.75, 0.75)), 2.5 :: Float)]++        describe "from 10 to 10" $ do+          it "at 1/2 of a cycle" $+            (queryArc (Sound.Tidal.UI.range 10 10 saw) (Arc 0.5 0.5)) `shouldBe` fmap toEvent+              [(((0.5, 0.5), (0.5, 0.5)), 10 :: Float)]+    describe "rot" $ do+      it "rotates values in a pattern irrespective of structure" $+        property $ comparePD (Arc 0 2)+          (rot 1 "a ~ b c" :: Pattern String)+          ( "b ~ c a" :: Pattern String)+      it "works with negative values" $+        property $ comparePD (Arc 0 2)+          (rot (-1) "a ~ b c" :: Pattern String)+          ( "c ~ a b" :: Pattern String)+      it "works with complex patterns" $+        property $ comparePD (Arc 0 2)+          (rot (1) "a ~ [b [c ~ d]] [e <f g>]" :: Pattern String)+          ( "b ~ [c [d ~ e]] [<f g> a]" :: Pattern String)++    describe "fix" $ do+      it "can apply functions conditionally" $ do+        compareP (Arc 0 1)+          (fix (|+ n 1) (s "sn") (s "bd sn cp" # n 1))+          (s "bd sn cp" # n "1 2 1")+      it "works with complex matches" $ do+        compareP (Arc 0 1)+          (fix (|+ n 2) (s "sn" # n 2) (s "bd sn*4 cp" # n "1 2"))+          (s "bd sn*4 cp" # n "1 [1 4] 2")+      it "leaves unmatched controls in place" $ do+        compareP (Arc 0 1)+          (fix (|+ n 2) (s "sn" # n 2) (s "bd sn*4 cp" # n "1 2" # speed (sine + 1)))+          (s "bd sn*4 cp" # n "1 [1 4] 2" # speed (sine + 1))+      it "ignores silence" $ do+        compareP (Arc 0 1)+          (fix (|+ n 2) (silence) $ s "bd sn*4 cp" # n "1 2" # speed (sine + 1))+          (s "bd sn*4 cp" # n "1 2" # speed (sine + 1))+      it "treats polyphony as 'or'" $ do+        compareP (Arc 0 1)+          (fix (# crush 2) (n "[1,2]") $ s "bd sn" # n "1 2")+          (s "bd sn" # n "1 2" # crush 2)++    describe "unfix" $ do+      it "does the opposite of fix" $ do+        compareP (Arc 0 1)+          (unfix (|+ n 2) (s "sn" # n 2) (s "bd sn*4 cp" # n "1 2" # speed (sine + 1)))+          (s "bd sn*4 cp" # n "3 [3 2] 4" # speed (sine + 1))++    describe "contrast" $ do+      it "does both fix and unfix" $ do+        compareP (Arc 0 1)+          (contrast (|+ n 2) (|+ n 10) (s "sn" # n 2) (s "bd sn*4 cp" # n "1 2" # speed (sine + 1)))+          (s "bd sn*4 cp" # n "11 [11 4] 12" # speed (sine + 1))++    describe "contrastRange" $ do+      it "matches using a pattern of ranges" $ do+        compareP (Arc 0 1)+          (contrastRange (# crush 3) (# crush 0) (pure $ Map.singleton "n" $ (VF 0, VF 3)) $ s "bd" >| n "1 4")+          (s "bd" >| n "1 4" >| crush "3 0")++    describe "euclidFull" $ do+      it "can match against silence" $ do+        compareP (Arc 0 1)+          (euclidFull 3 8 "bd" silence)+          ("bd(3,8)" :: Pattern String)
+ test/Sound/Tidal/UtilsTest.hs view
@@ -0,0 +1,16 @@+{-# LANGUAGE OverloadedStrings #-}++module Sound.Tidal.UtilsTest where++import Test.Microspec++import Prelude hiding ((<*), (*>))++import Sound.Tidal.Utils++run :: Microspec ()+run =+  describe "Sound.Tidal.Utils" $ do+    describe "delta" $ do+      it "subtracts the second element of a tuple from the first" $ do+        property $ delta (3,10) === (7 :: Int)
+ test/Test.hs view
@@ -0,0 +1,19 @@+{-# LANGUAGE OverloadedStrings #-}++import Test.Microspec++import Sound.Tidal.CoreTest+import Sound.Tidal.MiniTidalTest+import Sound.Tidal.ParseTest+import Sound.Tidal.PatternTest+import Sound.Tidal.UITest+import Sound.Tidal.UtilsTest++main :: IO ()+main = microspec $ do+  Sound.Tidal.CoreTest.run+  Sound.Tidal.MiniTidalTest.run+  Sound.Tidal.ParseTest.run+  Sound.Tidal.PatternTest.run+  Sound.Tidal.UITest.run+  Sound.Tidal.UtilsTest.run
+ test/TestUtils.hs view
@@ -0,0 +1,32 @@+{-# LANGUAGE OverloadedStrings #-}++module TestUtils where++import Test.Microspec++import Prelude hiding ((<*), (*>))++import Data.List (sort)++import Sound.Tidal.ParseBP (parseBP_E)+import Sound.Tidal.Pattern++import qualified Data.Map.Strict as Map++-- | Compare the events of two patterns using the given arc+compareP :: (Ord a, Show a) => Arc -> Pattern a -> Pattern a -> Property+compareP a p p' = (sort $ query p $ State a Map.empty) `shouldBe` (sort $ query p' $ State a Map.empty)++-- | Like @compareP@, but tries to 'defragment' the events+comparePD :: (Ord a) => Arc -> Pattern a -> Pattern a -> Bool+comparePD a p p' = compareDefrag es es'+  where es = query p (State a Map.empty)+        es' = query p' (State a Map.empty)++-- | Like @compareP@, but for control patterns, with some tolerance for floating point error+compareTol :: Arc -> ControlPattern -> ControlPattern -> Bool+compareTol a p p' = (sort $ queryArc p a) ~== (sort $ queryArc p' a)++-- | Utility to create a pattern from a String+ps :: String -> Pattern String+ps = parseBP_E
− tests/test.hs
@@ -1,47 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}--import Test.Tasty--- import Test.Tasty.SmallCheck as SC--- import Test.Tasty.QuickCheck as QC-import Test.Tasty.HUnit--import Data.List-import Data.Ord--import Sound.Tidal.Context--main = defaultMain tests--tests :: TestTree-tests = testGroup "Tests" [basic1,-                           parser1-                           -- patternsOfPatterns-                          ]--basic1 = testGroup "fast / slow"-         [-           testCase "silence" $ same16 (fast 1.1 silence) (silence :: Pattern Double),-           testCase "fast" $ same16  silence (silence :: Pattern Double),-           testCase "fast2" $ same16 "bd*128" (rep 128 "bd")-         ]--parser1 = testGroup "subpatterns"-         [-           testCase "square" $ same16 ("bd sn" :: Pattern String) ("[bd sn]" :: Pattern String)-         ]--patternsOfPatterns =-  testGroup "patterns of patterns"-  [-    testCase "decimal density" $ same16 (_discretise 0.25 saw) (discretise 0.25 saw)-  ]--rep :: Int -> String -> Pattern String-rep n v = p $ intercalate " " $ take n $ repeat v--sameN :: (Eq a, Show a) => String -> Time -> Pattern a -> Pattern a -> Assertion-sameN s n a b = assertEqual s (arc a (0,n)) (arc b (0,n))--same16 :: (Eq a, Show a) => Pattern a -> Pattern a -> Assertion-same16 = sameN "for 16 cycles," 16-
tidal.cabal view
@@ -1,5 +1,5 @@ name:                tidal-version:             0.9.10+version:             1.0.0 synopsis:            Pattern language for improvised music -- description: homepage:            http://tidalcycles.org/@@ -8,44 +8,44 @@ author:              Alex McLean maintainer:          Alex McLean <alex@slab.org>, Mike Hodnick <mike.hodnick@gmail.com> Stability:           Experimental-Copyright:           (c) Tidal contributors, 2017+Copyright:           (c) Tidal contributors, 2018 category:            Sound build-type:          Simple cabal-version:       >=1.10-tested-with:         GHC == 7.10.3, GHC == 8.0.1, GHC == 8.4.1+tested-with:         GHC == 7.10.3, GHC == 8.0.2, GHC == 8.2.2, GHC == 8.4.4, GHC == 8.6.3 -Extra-source-files: README.md CHANGELOG.md tidal.el doc/tidal.md+Extra-source-files: README.md CHANGELOG.md tidal.el  Description: Tidal is a domain specific language for live coding pattern.  library-  if impl(ghc == 8.4.1)+  if impl(ghc == 8.4.4)     cpp-options: -DTIDAL_SEMIGROUP +  ghc-options: -Wall+  hs-source-dirs:+                 src+   default-language:    Haskell2010    Exposed-modules:     Sound.Tidal.Bjorklund-                       Sound.Tidal.Strategies-                       Sound.Tidal.Dirt+                       Sound.Tidal.Chords+                       Sound.Tidal.Config+                       Sound.Tidal.Control+                       Sound.Tidal.Context+                       Sound.Tidal.Core+                       Sound.Tidal.MiniTidal+                       Sound.Tidal.Params+                       Sound.Tidal.ParseBP                        Sound.Tidal.Pattern+                       Sound.Tidal.Scales+                       Sound.Tidal.Simple                        Sound.Tidal.Stream-                       Sound.Tidal.OscStream-                       Sound.Tidal.Parse                        Sound.Tidal.Tempo-                       Sound.Tidal.Time-                       Sound.Tidal.Context-                       Sound.Tidal.Utils-                       Sound.Tidal.SuperCollider-                       Sound.Tidal.Params                        Sound.Tidal.Transition+                       Sound.Tidal.UI+                       Sound.Tidal.Utils                        Sound.Tidal.EspGrid-                       Sound.Tidal.MultiMode-                       Sound.Tidal.Scales-                       Sound.Tidal.Chords-                       Sound.Tidal.Sieve-                       Sound.Tidal.Version-                       Sound.Tidal.Simple-                       -- Sound.Tidal.PatternList    Build-depends:       base < 5@@ -54,32 +54,42 @@     , colour     , hosc >= 0.16     , text-    , mersenne-random-pure64+    , random     , time     , parsec     , safe-    , websockets > 0.8     , mtl >= 2.1     , monad-loops+    , network+    , mwc-random+    , vector+    , bifunctors    if !impl(ghc >= 8.4.1)     build-depends: semigroups == 0.18.* +test-suite tests+  type: exitcode-stdio-1.0+  main-is: Test.hs+  hs-source-dirs:+      test+  ghc-options: -Wall+  other-modules: Sound.Tidal.CoreTest+                 Sound.Tidal.MiniTidalTest+                 Sound.Tidal.ParseTest+                 Sound.Tidal.PatternTest+                 Sound.Tidal.UITest+                 Sound.Tidal.UtilsTest+                 TestUtils+  build-depends:+                base ==4.*+              , microspec >= 0.2.0.1+              , containers+              , parsec+              , tidal++  default-language: Haskell2010+ source-repository head   type:     git   location: https://github.com/tidalcycles/Tidal--test-suite test-  default-language:-    Haskell2010-  type:-    exitcode-stdio-1.0-  hs-source-dirs:-    tests-  main-is:-    test.hs-  build-depends:-      base >= 4 && < 5-              , tasty -              , tasty-hunit-    , tidal
tidal.el view
@@ -92,33 +92,52 @@   (if (string< tidal-interpreter-version "8.2.0")       (tidal-send-string ":set prompt2 \"\"")     (tidal-send-string ":set prompt-cont \"\""))-  (tidal-send-string ":module Sound.Tidal.Context")-  (tidal-send-string "import qualified Sound.Tidal.Scales as Scales")-  (tidal-send-string "import qualified Sound.Tidal.Chords as Chords")-  (tidal-send-string "(cps, nudger, getNow) <- cpsUtils'")-  (tidal-send-string "(d1,t1) <- superDirtSetters getNow")-  (tidal-send-string "(d2,t2) <- superDirtSetters getNow")-  (tidal-send-string "(d3,t3) <- superDirtSetters getNow")-  (tidal-send-string "(d4,t4) <- superDirtSetters getNow")-  (tidal-send-string "(d5,t5) <- superDirtSetters getNow")-  (tidal-send-string "(d6,t6) <- superDirtSetters getNow")-  (tidal-send-string "(d7,t7) <- superDirtSetters getNow")-  (tidal-send-string "(d8,t8) <- superDirtSetters getNow")-  (tidal-send-string "(d9,t9) <- superDirtSetters getNow")-  (tidal-send-string "(d10,t10) <- superDirtSetters getNow")-  (tidal-send-string "(c1,ct1) <- dirtSetters getNow")-  (tidal-send-string "(c2,ct2) <- dirtSetters getNow")-  (tidal-send-string "(c3,ct3) <- dirtSetters getNow")-  (tidal-send-string "(c4,ct4) <- dirtSetters getNow")-  (tidal-send-string "(c5,ct5) <- dirtSetters getNow")-  (tidal-send-string "(c6,ct6) <- dirtSetters getNow")-  (tidal-send-string "(c7,ct7) <- dirtSetters getNow")-  (tidal-send-string "(c8,ct8) <- dirtSetters getNow")-  (tidal-send-string "(c9,ct9) <- dirtSetters getNow")-  (tidal-send-string "(c10,ct10) <- dirtSetters getNow")-  (tidal-send-string "let bps x = cps (x/2)")-  (tidal-send-string "let hush = mapM_ ($ silence) [c1,c2,c3,c4,c5,c6,c7,c8,c9,c10,d1,d2,d3,d4,d5,d6,d7,d8,d9,d10]")-  (tidal-send-string "let solo = (>>) hush")+  (tidal-send-string "import Sound.Tidal.Context+tidal <- startTidal (superdirtTarget {oLatency = 0.1, oAddress = \"127.0.0.1\", oPort = 57120}) (defaultConfig {cFrameTimespan = 1/20})+let p = streamReplace tidal+    hush = streamHush tidal+    list = streamList tidal+    mute = streamMute tidal+    unmute = streamUnmute tidal+    solo = streamSolo tidal+    unsolo = streamUnsolo tidal+    once = streamOnce tidal False+    asap = streamOnce tidal True+    nudgeAll = streamNudgeAll tidal+    setcps = asap . cps+    xfade = transition tidal (Sound.Tidal.Transition.xfadeIn 4)+    xfadeIn t = transition tidal (Sound.Tidal.Transition.xfadeIn t)+    histpan t = transition tidal (Sound.Tidal.Transition.histpan t)+    wait t = transition tidal (Sound.Tidal.Transition.wait t)+    waitT f t = transition tidal (Sound.Tidal.Transition.waitT f t)+    jump = transition tidal (Sound.Tidal.Transition.jump)+    jumpIn t = transition tidal (Sound.Tidal.Transition.jumpIn t)+    jumpIn' t = transition tidal (Sound.Tidal.Transition.jumpIn' t)+    jumpMod t = transition tidal (Sound.Tidal.Transition.jumpMod t)+    mortal lifespan release = transition tidal (Sound.Tidal.Transition.mortal lifespan release)+    interpolate = transition tidal (Sound.Tidal.Transition.interpolate)+    interpolateIn t = transition tidal (Sound.Tidal.Transition.interpolateIn t)+    clutch = transition tidal (Sound.Tidal.Transition.clutch)+    clutchIn t = transition tidal (Sound.Tidal.Transition.clutchIn t)+    anticipate = transition tidal (Sound.Tidal.Transition.anticipate)+    anticipateIn t = transition tidal (Sound.Tidal.Transition.anticipateIn t)+    d1 = p 1+    d2 = p 2+    d3 = p 3+    d4 = p 4+    d5 = p 5+    d6 = p 6+    d7 = p 7+    d8 = p 8+    d9 = p 9+    d10 = p 10+    d11 = p 11+    d12 = p 12+    d13 = p 13+    d14 = p 14+    d15 = p 15+    d16 = p 16+  ")   (tidal-send-string ":set prompt \"tidal> \"") ) @@ -179,7 +198,7 @@ (defun tidal-run-line ()   "Send the current line to the interpreter."   (interactive)-  (tidal-get-now)+  ;(tidal-get-now)   (let* ((s (buffer-substring (line-beginning-position) 			      (line-end-position))) 	 (s* (if tidal-literate-p@@ -192,7 +211,7 @@  (defun tidal-eval-multiple-lines ()   "Eval the current region in the interpreter as a single line."-  (tidal-get-now)+  ;(tidal-get-now)   (mark-paragraph)   (let* ((s (buffer-substring-no-properties (region-beginning)                                             (region-end)))