packages feed

tidal 1.0.5 → 1.0.6

raw patch · 15 files changed

+689/−318 lines, 15 filesdep −hashabledep −monad-loopsdep −mtldep ~basedep ~bifunctorsdep ~colourPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies removed: hashable, monad-loops, mtl, random, safe, time

Dependency ranges changed: base, bifunctors, colour, containers, hosc, mwc-random, network, parsec, text, vector

API changes (from Hackage documentation)

- 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.Stream: [sTarget] :: Stream -> OSCTarget
- Sound.Tidal.Stream: [sUDP] :: Stream -> UDP
+ Sound.Tidal.MiniTidal: instance Sound.Tidal.MiniTidal.MiniTidal GHC.Base.String
+ Sound.Tidal.MiniTidal: instance Sound.Tidal.MiniTidal.MiniTidal GHC.Integer.Type.Integer
+ Sound.Tidal.MiniTidal: instance Sound.Tidal.MiniTidal.MiniTidal GHC.Types.Double
+ Sound.Tidal.MiniTidal: instance Sound.Tidal.MiniTidal.MiniTidal GHC.Types.Int
+ Sound.Tidal.MiniTidal: instance Sound.Tidal.MiniTidal.MiniTidal Sound.Tidal.Pattern.Arc
+ Sound.Tidal.MiniTidal: instance Sound.Tidal.MiniTidal.MiniTidal Sound.Tidal.Pattern.ControlMap
+ Sound.Tidal.MiniTidal: instance Sound.Tidal.MiniTidal.MiniTidal Sound.Tidal.Pattern.Time
+ Sound.Tidal.Params: distort :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: fshift :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: fshiftnote :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: fshiftphase :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: kcutoff :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: krush :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: octer :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: octersub :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: octersubsub :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: ring :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: ringdf :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: ringf :: Pattern Double -> ControlPattern
+ Sound.Tidal.Params: triode :: Pattern Double -> ControlPattern
+ Sound.Tidal.Pattern: instance GHC.Show.Show Sound.Tidal.Pattern.Nature
+ Sound.Tidal.Stream: Cx :: OSCTarget -> UDP -> Cx
+ Sound.Tidal.Stream: [cxTarget] :: Cx -> OSCTarget
+ Sound.Tidal.Stream: [cxUDP] :: Cx -> UDP
+ Sound.Tidal.Stream: [oName] :: OSCTarget -> String
+ Sound.Tidal.Stream: [sCxs] :: Stream -> [Cx]
+ Sound.Tidal.Stream: data Cx
+ Sound.Tidal.Stream: dirtTarget :: OSCTarget
+ Sound.Tidal.Stream: instance GHC.Show.Show Sound.Tidal.Stream.OSCTarget
+ Sound.Tidal.Stream: instance GHC.Show.Show Sound.Tidal.Stream.TimeStamp
+ Sound.Tidal.Stream: startMulti :: [OSCTarget] -> Config -> IO Stream
+ Sound.Tidal.UI: _arp :: String -> Pattern a -> Pattern a
+ Sound.Tidal.UI: arp :: Pattern String -> Pattern a -> Pattern a
+ Sound.Tidal.UI: arpWith :: ([EventF (ArcF Time) a] -> [EventF (ArcF Time) b]) -> Pattern a -> Pattern b
- Sound.Tidal.ParseBP: parseChord :: Num a => Parser [a]
+ Sound.Tidal.ParseBP: parseChord :: (Enum a, Num a) => Parser [a]
- Sound.Tidal.Stream: OSCTarget :: String -> Int -> String -> Maybe [(String, Maybe Value)] -> Double -> [Datum] -> TimeStamp -> OSCTarget
+ Sound.Tidal.Stream: OSCTarget :: String -> String -> Int -> String -> Maybe [(String, Maybe Value)] -> Double -> [Datum] -> TimeStamp -> OSCTarget
- Sound.Tidal.Stream: Stream :: Config -> MVar ControlMap -> MVar ControlPattern -> Maybe ThreadId -> MVar PlayMap -> MVar Tempo -> MVar (ControlPattern -> ControlPattern) -> OSCTarget -> UDP -> Stream
+ Sound.Tidal.Stream: Stream :: Config -> MVar ControlMap -> MVar ControlPattern -> Maybe ThreadId -> MVar PlayMap -> MVar Tempo -> MVar (ControlPattern -> ControlPattern) -> [Cx] -> Stream
- Sound.Tidal.Stream: onTick :: Config -> MVar ControlMap -> MVar ControlPattern -> OSCTarget -> UDP -> MVar Tempo -> State -> IO ()
+ Sound.Tidal.Stream: onTick :: Config -> MVar ControlMap -> MVar ControlPattern -> [Cx] -> MVar Tempo -> State -> IO ()
- Sound.Tidal.Stream: send :: Transport t => Double -> t -> (Double, Message) -> IO ()
+ Sound.Tidal.Stream: send :: Transport t => OSCTarget -> Double -> t -> (Double, Message) -> IO ()
- Sound.Tidal.Stream: startStream :: Config -> MVar ControlMap -> OSCTarget -> IO (MVar ControlPattern, MVar Tempo, UDP)
+ Sound.Tidal.Stream: startStream :: Config -> MVar ControlMap -> [OSCTarget] -> IO (MVar ControlPattern, MVar Tempo, [Cx])
- Sound.Tidal.Stream: toData :: Event ControlMap -> [Datum]
+ Sound.Tidal.Stream: toData :: OSCTarget -> Event ControlMap -> Maybe [Datum]
- Sound.Tidal.Stream: toMessage :: OSCTarget -> Tempo -> Event (Map String Value) -> Message
+ Sound.Tidal.Stream: toMessage :: Double -> OSCTarget -> Tempo -> Event (Map String Value) -> Maybe Message

Files

src/Sound/Tidal/Control.hs view
@@ -335,7 +335,7 @@ 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)]))+_stut count feedback steptime p = stack (p:(map (\x -> (((x%1)*steptime) `rotR` (p |* P.gain (pure $ scalegain (fromIntegral x))))) [1..(count-1)]))   where scalegain x           = ((+feedback) . (*(1-feedback)) . (/(fromIntegral count)) . ((fromIntegral count)-)) x @@ -348,11 +348,11 @@ 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 n t f p = innerJoin $ (\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+_stutWith count steptime f p | count <= 1 = 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
src/Sound/Tidal/Core.hs view
@@ -361,7 +361,7 @@ -- | @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 tp f p = innerJoin $ (\t -> _every t f p) <$> tp  _every :: Int -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a _every 0 _ p = p@@ -405,8 +405,3 @@ 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/MiniTidal.hs view
@@ -4,10 +4,11 @@  import           Data.Functor.Identity (Identity) import           Text.Parsec.Language (haskellDef)-import           Text.Parsec.Prim (ParsecT)+import           Text.Parsec.Prim (ParsecT,parserZero) import           Text.ParserCombinators.Parsec import qualified Text.ParserCombinators.Parsec.Token as P import           Control.Monad (forever)+import Control.Applicative (liftA2) -- import Data.List (intercalate) -- import Data.Bool (bool) -- import Data.Ratio@@ -28,94 +29,78 @@     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+class MiniTidal a where+  literal :: Parser a -- parse an individual pure value of this type+  simplePattern :: Parser (Pattern a) -- any way of making this pattern that wouldn't require parentheses if it was an argument+  complexPattern :: Parser (Pattern a) -- producing this pattern by way of unary functions with an argument of a different type+  transformationWithArguments:: Parser (Pattern a -> Pattern a) -- producing this pattern by with unary functions that take same type+  transformationWithoutArguments :: Parser (Pattern a -> Pattern a) -- also producing this pattern by unary functions of same type+  mergeOperator :: Parser (Pattern a -> Pattern a -> Pattern a) -- operators for combining this type of pattern, eg. # or |>+  binaryFunctions :: Parser (a -> a -> a) -- binary functions on pure values of this type, eg. (+) for Int or other Num instances -pattern :: Pattern' a => Parser (Pattern a)+literalArg :: MiniTidal a => Parser a+literalArg = choice [+  literal,+  nestedParens literal,+  try $ applied $ parensOrNot literal+  ]++listLiteralArg :: MiniTidal a => Parser [a]+listLiteralArg = brackets (commaSep $ parensOrNot literal)++pattern :: MiniTidal a => Parser (Pattern a) pattern = chainl1 pattern' mergeOperator -pattern' :: Pattern' a => Parser (Pattern a)+pattern' :: MiniTidal a => Parser (Pattern a) pattern' = choice [   nestedParens $ chainl1 pattern mergeOperator,-  parensOrNot complexPattern,-  parensOrNot genericComplexPatterns,-  parensOrNot transformedPattern,-  parensOrNot simplePattern,+  transformation <*> patternArg,+  genericComplexPattern,+  complexPattern,+  simplePattern,   silence   ] -patternArg :: Pattern' a => Parser (Pattern a)+patternArg :: MiniTidal a => Parser (Pattern a) patternArg = choice [   try $ parensOrApplied $ chainl1 pattern mergeOperator,-  try $ parensOrApplied transformedPattern,+  try $ parensOrApplied $ transformation <*> patternArg,+  try $ parensOrApplied genericComplexPattern,   try $ parensOrApplied complexPattern,-  try $ parensOrApplied genericComplexPatterns,-  appliedOrNot simplePattern,+  try $ 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+transformation :: MiniTidal a => Parser (Pattern a -> Pattern a)+transformation = transformationWithArguments <|> transformationWithoutArguments -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+transformationArg :: MiniTidal a => Parser (Pattern a -> Pattern a)+transformationArg = choice [+  try $ appliedOrNot $ transformationWithoutArguments,+  parensOrApplied $ transformationWithArguments   ] -enumComplexPatterns :: (Enum a, Num a, Pattern' a) => Parser (Pattern a)-enumComplexPatterns = choice [-  (function "run" >> return T.run) <*> patternArg,-  (function "scan" >> return T.scan) <*> patternArg-  ]+listPatternArg :: MiniTidal a => Parser [Pattern a]+listPatternArg = try $ parensOrNot $ brackets (commaSep pattern) -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-  ]+listTransformationArg :: MiniTidal a => Parser [Pattern a -> Pattern a]+listTransformationArg = try $ parensOrNot $ brackets (commaSep transformation) -intComplexPatterns :: Parser (Pattern Int)-intComplexPatterns = choice [-  (function "randStruct" >> return T.randStruct) <*> literalArg-  ]+--  d1 $ spread ($) [density 2, rev, slow 2, striate 3, (# speed "0.8")] $ sound "[bd*2 [~ bd]] [sn future]*2 cp jvbass*4"+--  spread  ((a -> b) -> a -> b) -> [ControlPattern -> ControlPattern] -> ControlPattern -> ControlPattern -transformedPattern :: Pattern' a => Parser (Pattern a)-transformedPattern = (transformationWithArgs <|> transformationWithoutArgs) <*> patternArg -instance Pattern' ControlMap where-  simplePattern = choice []+silence :: Parser (Pattern a)+silence = function "silence" >> return T.silence++instance MiniTidal ControlMap where+  literal = parserZero+  simplePattern = parserZero+  transformationWithArguments = p_p <|> pControl_pControl+  transformationWithoutArguments = p_p_noArgs   complexPattern = specificControlPatterns   mergeOperator = controlPatternMergeOperator-  transformationWithArgs = controlPatternTransformation <|> patternTransformationWithArgs-  transformationWithoutArgs = patternTransformationWithoutArgs-  literal = choice []+  binaryFunctions = parserZero  controlPatternMergeOperator :: Parser (ControlPattern -> ControlPattern -> ControlPattern) controlPatternMergeOperator = choice [@@ -132,6 +117,7 @@  specificControlPatterns :: Parser ControlPattern specificControlPatterns = choice [+  try $ parens specificControlPatterns,   (function "coarse" >> return T.coarse) <*> patternArg,   (function "cut" >> return T.cut) <*> patternArg,   (function "n" >> return T.n) <*> patternArg,@@ -162,108 +148,273 @@   (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+genericComplexPattern :: MiniTidal a => Parser (Pattern a)+genericComplexPattern = choice [+  try $ parens genericComplexPattern,+  lp_p <*> listPatternArg,+  l_p <*> listLiteralArg   ] -patternTransformationArg :: Pattern' a => Parser (Pattern a -> Pattern a)-patternTransformationArg = appliedOrNot transformationWithoutArgs <|> parensOrApplied transformationWithArgs--patternTransformationWithoutArgs :: Parser (Pattern a -> Pattern a)-patternTransformationWithoutArgs = choice [+p_p_noArgs :: Parser (Pattern a -> Pattern a)+p_p_noArgs  = 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+p_p :: (MiniTidal a, MiniTidal a) => Parser (Pattern a -> Pattern a)+p_p = choice [+  try $ parens p_p,+  p_p_p <*> patternArg,+  t_p_p <*> transformationArg,+  lp_p_p <*> listPatternArg,+  lt_p_p <*> listTransformationArg,+  lpInt_p_p <*> listPatternArg,+  pTime_p_p <*> patternArg,+  pInt_p_p <*> patternArg,+  pString_p_p <*> patternArg,+  pDouble_p_p <*> patternArg,+  vTime_p_p <*> literalArg,+  vInt_p_p <*> literalArg,+  vTimeTime_p_p <*> literalArg,+  pDouble_p_p <*> patternArg,+  lTime_p_p <*> listLiteralArg   ] +lt_p_p = choice [+  try $ parens lt_p_p,+  spreads <*> (nestedParens $ reservedOp "$" >> return ($))+  ]++l_p :: MiniTidal a => Parser ([a] -> Pattern a)+l_p = choice [+  function "listToPat" >> return T.listToPat,+  function "choose" >> return T.choose,+  function "cycleChoose" >> return T.cycleChoose+  ]++lp_p :: MiniTidal a => Parser ([Pattern a] -> Pattern a)+lp_p = choice [+  function "stack" >> return T.stack,+  function "fastcat" >> return T.fastcat,+  function "slowcat" >> return T.slowcat,+  function "cat" >> return T.cat,+  function "randcat" >> return T.randcat+  ]++pInt_p :: MiniTidal a => Parser (Pattern Int -> Pattern a)+pInt_p = choice [+  try $ parens pInt_p,+  l_pInt_p <*> listLiteralArg+  ]++p_p_p :: MiniTidal a => Parser (Pattern a -> Pattern a -> Pattern a)+p_p_p = choice [+  try $ parens p_p_p,+  liftA2 <$> binaryFunctions,+  function "overlay" >> return T.overlay,+  function "append" >> return T.append,+  vTime_p_p_p <*> literalArg,+  pInt_p_p_p <*> patternArg+  ]++pTime_p_p = choice [+  try $ parens pTime_p_p,+  function "fast" >> return T.fast,+  function "fastGap" >> return T.fastGap,+  function "density" >> return T.density,+  function "slow" >> return T.slow,+  function "trunc" >> return T.trunc,+  function "fastGap" >> return T.fastGap,+  function "densityGap" >> return T.densityGap,+  function "sparsity" >> return T.sparsity,+  function "trunc" >> return T.trunc,+  function "linger" >> return T.linger,+  function "segment" >> return T.segment,+  function "discretise" >> return T.discretise,+  function "timeLoop" >> return T.timeLoop,+  function "swing" >> return T.swing,+  pTime_pTime_p_p <*> patternArg+  ]++lTime_p_p = choice [+  try $ parens lTime_p_p,+  spreads <*> parens vTime_p_p -- re: spread+  ]++spreads = choice [+  function "spread" >> return T.spread,+  function "slowspread" >> return T.slowspread,+  function "fastspread" >> return T.fastspread+  ]++pInt_p_p = choice [+  try $ parens pInt_p_p,+  function "iter" >> return T.iter,+  function "iter'" >> return T.iter',+  function "ply" >> return T.ply,+  function "substruct'" >> return T.substruct',+  function "slowstripe" >> return T.slowstripe,+  pInt_pInt_p_p <*> patternArg+  ]++pString_p_p = function "substruct" >> return T.substruct++pDouble_p_p = choice [+  try $ parens pDouble_p_p,+  function "degradeBy" >> return T.degradeBy,+  function "unDegradeBy" >> return T.unDegradeBy,+  vInt_pDouble_p_p <*> literalArg+  ]++vTime_p_p = choice [+  try $ parens vTime_p_p,+  function "rotL" >> return T.rotL,+  function "rotR" >> return T.rotR,+  vTime_vTime_p_p <*> literalArg+  ]++vInt_p_p = choice [+  function "shuffle" >> return T.shuffle,+  function "scramble" >> return T.scramble,+  function "repeatCycles" >> return T.repeatCycles+  ]++vTimeTime_p_p = choice [+  function "compress" >> return T.compressArc,+  function "zoom" >> return T.zoomArc,+  function "compressTo" >> return T.compressArcTo+  ]++t_p_p = choice [+  try $ parens t_p_p,+  function "sometimes" >> return T.sometimes,+  function "often" >> return T.often,+  function "rarely" >> return T.rarely,+  function "almostNever" >> return T.almostNever,+  function "almostAlways" >> return T.almostAlways,+  function "never" >> return T.never,+  function "always" >> return T.always,+  function "superimpose" >> return T.superimpose,+  function "someCycles" >> return T.someCycles,+  function "somecycles" >> return T.somecycles,+  pInt_t_p_p <*> patternArg,+  pDouble_t_p_p <*> patternArg,+  lvInt_t_p_p <*> listLiteralArg,+  vInt_t_p_p <*> literalArg,+  vDouble_t_p_p <*> literalArg+  ]++lvTime_p_p = function "spaceOut" >> return T.spaceOut++lpInt_p_p = function "distrib" >> return T.distrib++lp_p_p :: MiniTidal a => Parser ([Pattern a] -> Pattern a -> Pattern a)+lp_p_p = choice [+  try $ parens lp_p_p,+  try $ spreads <*> parens p_p_p+  ]++l_pInt_p = choice [+  try $ parens l_pInt_p,+  vInt_l_pInt_p <*> literalArg+  ]++vInt_l_pInt_p = function "fit" >> return T.fit++vTime_p_p_p = function "wedge" >> return T.wedge++vInt_pDouble_p_p = function "degradeOverBy" >> return T.degradeOverBy++pInt_t_p_p = choice [+  try $ parens pInt_t_p_p,+  function "every" >> return T.every,+  pInt_pInt_t_p_p <*> patternArg+  ]++pDouble_t_p_p = function "sometimesBy" >> return T.sometimesBy++lvInt_t_p_p = function "foldEvery" >> return T.foldEvery++vTime_vTime_p_p = function "playFor" >> return T.playFor++vTimeTime_t_p_p = function "within" >> return T.withinArc++vInt_t_p_p = choice [+  try $ parens vInt_t_p_p,+  function "chunk" >> return T.chunk,+  vInt_vInt_t_p_p <*> literalArg+  ]++vDouble_t_p_p = choice [+  function "someCyclesBy" >> return T.someCyclesBy,+  function "somecyclesBy" >> return T.somecyclesBy+  ]++pInt_pInt_p_p = choice [+  try $ parens pInt_pInt_p_p,+  function "euclid" >> return T.euclid,+  function "euclidInv" >> return T.euclidInv,+  vInt_pInt_pInt_p_p <*> literalArg+  ]++pTime_pTime_p_p = function "swingBy" >> return T.swingBy++pInt_pInt_t_p_p = function "every'" >> return T.every'++vInt_vInt_t_p_p = function "whenmod" >> return T.whenmod++pInt_p_p_p = choice [+  try $ parens pInt_p_p_p,+  pInt_pInt_p_p_p <*> patternArg+  ]++pInt_pInt_p_p_p = function "euclidFull" >> return T.euclidFull++vInt_pInt_pInt_p_p = choice [+  try $ parens vInt_pInt_pInt_p_p,+  pTime_vInt_pInt_pInt_p_p <*> patternArg+  ]++pTime_vInt_pInt_pInt_p_p = function "fit'" >> return T.fit'++pControl_pControl = choice [+  try $ parens pControl_pControl,+  pInt_pControl_pControl <*> patternArg,+  pDouble_pControl_pControl <*> patternArg,+  pTime_pControl_pControl <*> patternArg,+  tControl_pControl_pControl <*> transformationArg+  ]++tControl_pControl_pControl = function "jux" >> return T.jux++pInt_pControl_pControl = choice [+  function "chop" >> return T.chop,+  function "striate" >> return T.striate+  ]++pDouble_pControl_pControl = choice [+  try $ parens pDouble_pControl_pControl,+  pInt_pDouble_pControl_pControl <*> patternArg+  ]++pInt_pDouble_pControl_pControl = function "striate'" >> return T.striate'++pTime_pControl_pControl = choice [+  try $ parens pTime_pControl_pControl,+  pDouble_pTime_pControl_pControl <*> patternArg+  ]++pDouble_pTime_pControl_pControl = choice [+  try $ parens pDouble_pTime_pControl_pControl,+  pInteger_pDouble_pTime_pControl_pControl <*> patternArg+  ]++pInteger_pDouble_pTime_pControl_pControl = function "stut" >> return T.stut+ simpleDoublePatterns :: Parser (Pattern Double) simpleDoublePatterns = choice [   function "rand" >> return T.rand,@@ -275,71 +426,69 @@   function "cosine" >> return T.cosine   ] -instance Pattern' Int where-  simplePattern = choice [-    parseBP',-    pure <$> int-    ]+binaryNumFunctions :: Num a => Parser (a -> a -> a)+binaryNumFunctions = choice [+  try $ parens binaryNumFunctions,+  reservedOp "+" >> return (+),+  reservedOp "-" >> return (-),+  reservedOp "*" >> return (*)+  ]++instance MiniTidal Int where+  literal = int+  simplePattern = parseBP' <|> (pure <$> int)+  transformationWithArguments = p_p_noArgs+  transformationWithoutArguments = p_p   complexPattern = (atom <*> int) <|> enumComplexPatterns <|> numComplexPatterns <|> intComplexPatterns   mergeOperator = numMergeOperator-  transformationWithoutArgs = patternTransformationWithoutArgs-  transformationWithArgs = patternTransformationWithArgs-  literal = int+  binaryFunctions = binaryNumFunctions -instance Pattern' Integer where-  simplePattern = choice [-    parseBP',-    pure <$> integer-    ]+instance MiniTidal Integer where+  literal = integer+  simplePattern = parseBP' <|> (pure <$> integer)+  transformationWithArguments = p_p_noArgs+  transformationWithoutArguments = p_p   complexPattern = (atom <*> integer) <|> enumComplexPatterns <|> numComplexPatterns   mergeOperator = numMergeOperator-  transformationWithoutArgs = patternTransformationWithoutArgs-  transformationWithArgs = patternTransformationWithArgs-  literal = integer+  binaryFunctions = binaryNumFunctions -instance Pattern' Double where-  simplePattern = choice [-    parseBP',-    try $ pure <$> double,-    simpleDoublePatterns-    ]+instance MiniTidal Double where+  literal = double+  simplePattern = parseBP' <|> (try $ pure <$> double) <|> simpleDoublePatterns+  transformationWithArguments = p_p_noArgs+  transformationWithoutArguments = p_p   complexPattern = (atom <*> double) <|> enumComplexPatterns <|> numComplexPatterns   mergeOperator = numMergeOperator <|> fractionalMergeOperator-  transformationWithoutArgs = patternTransformationWithoutArgs-  transformationWithArgs = patternTransformationWithArgs-  literal = double+  binaryFunctions = binaryNumFunctions -instance Pattern' Time where-  simplePattern = choice [-    parseBP',-    pure <$> literal-    ]+instance MiniTidal Time where+  literal = (toRational <$> double) <|> (fromIntegral <$> integer)+  simplePattern = parseBP' <|> (pure <$> literal)+  transformationWithArguments = p_p_noArgs+  transformationWithoutArguments = p_p   complexPattern = atom <*> literal <|> numComplexPatterns   mergeOperator = numMergeOperator <|> fractionalMergeOperator-  transformationWithoutArgs = patternTransformationWithoutArgs-  transformationWithArgs = patternTransformationWithArgs-  literal = choice [-    toRational <$> double,-    fromIntegral <$> integer-    ]+  binaryFunctions = binaryNumFunctions -instance Pattern' Arc where-  simplePattern = pure <$> literal-  complexPattern = atom <*> literal-  mergeOperator = choice []-  transformationWithoutArgs = patternTransformationWithoutArgs-  transformationWithArgs = patternTransformationWithArgs+instance MiniTidal Arc where   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"+  simplePattern = pure <$> literal+  transformationWithArguments = p_p_noArgs+  transformationWithoutArguments = p_p+  complexPattern = atom <*> literal+  mergeOperator = parserZero+  binaryFunctions = parserZero -instance Pattern' String where+instance MiniTidal String where+  literal = stringLiteral   simplePattern = parseBP'+  transformationWithArguments = p_p_noArgs+  transformationWithoutArguments = p_p   complexPattern = atom <*> stringLiteral-  mergeOperator = choice [] -- ??-  transformationWithoutArgs = patternTransformationWithoutArgs-  transformationWithArgs = patternTransformationWithArgs-  literal = stringLiteral+  mergeOperator = parserZero+  binaryFunctions = parserZero  fractionalMergeOperator :: Fractional a => Parser (Pattern a -> Pattern a -> Pattern a) fractionalMergeOperator = op "/" >> return (/)@@ -351,6 +500,24 @@   op "*" >> return (*)   ] +enumComplexPatterns :: (Enum a, Num a, MiniTidal a) => Parser (Pattern a)+enumComplexPatterns = choice [+  (function "run" >> return T.run) <*> patternArg,+  (function "scan" >> return T.scan) <*> patternArg+  ]++numComplexPatterns :: (Num a, MiniTidal 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+  ]+ atom :: Applicative m => Parser (a -> m a) atom = (function "pure" <|> function "atom" <|> function "return") >> return (pure) @@ -393,8 +560,7 @@     "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",+    "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'",@@ -406,7 +572,7 @@     "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"],+    "cps","xfadeIn","note","spread","slowspread","fastspread"],   P.reservedOpNames = ["+","-","*","/","<~","~>","#","|+|","|-|","|*|","|/|","$","\"","|>","<|","|>|","|<|"]   } @@ -545,3 +711,18 @@   forever $ do     cmd <- miniTidalIO tidal <$> getLine     either (\x -> putStrLn $ "error: " ++ show x) id cmd++-- things whose status in new tidal we are unsure of+--(function "within'" >> return T.within') <*> literalArg <*> transformationArg,+-- (function "revArc" >> return T.revArc) <*> literalArg,+--  (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 "fill" >> return T.fill) <*> patternArg,+--function "struct" >> return T.struct,+--  (function "sliceArc" >> return T.sliceArc) <*> literalArg+--  function "breakUp" >> return T.breakUp, -- removed from new Tidal?
src/Sound/Tidal/Params.hs view
@@ -358,6 +358,33 @@ phaserrate = pF "phaserrate" phaserdepth = pF "phaserdepth" +-- More SuperDirt effects+-- frequency shifter+fshift, fshiftphase, fshiftnote :: Pattern Double -> ControlPattern+fshift = pF "fshift"+fshiftphase = pF "fshiftphase"+fshiftnote = pF "fshiftnote"+-- triode (tube distortion)+triode :: Pattern Double -> ControlPattern+triode = pF "triode"+-- krush (like Sonic Pi's shape/bass enhancer)+krush, kcutoff :: Pattern Double -> ControlPattern+krush = pF "krush"+kcutoff = pF "kcutoff"+-- octer (like Sonic Pi's octaver effect)+octer, octersub, octersubsub :: Pattern Double -> ControlPattern+octer = pF "octer"+octersub = pF "octersub"+octersubsub = pF "octersubsub"+-- ring modulation+ring, ringf, ringdf :: Pattern Double -> ControlPattern+ring = pF "ring"+ringf = pF "ringf"+ringdf = pF "ringdf"+-- noisy fuzzy distortion+distort :: Pattern Double -> ControlPattern+distort = pF "distort"+ -- 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
src/Sound/Tidal/ParseBP.hs view
@@ -359,10 +359,15 @@                do c <- parseChord                   return $ TPat_Stack $ map TPat_Atom c -parseChord :: Num a => Parser [a]+parseChord :: (Enum a, Num a) => Parser [a] parseChord = do char '\''                 name <- many1 $ letter <|> digit-                return $ fromMaybe [0] $ lookup name chordTable+                let chord = fromMaybe [0] $ lookup name chordTable+                do char '\''+                   i <- integer <?> "chord range"+                   let chord' = take (fromIntegral i) $ concatMap (\x -> map (+ x) chord) [0,12..]+                   return $ chord'+                  <|> return chord  parseNote :: Num a => Parser a parseNote = do n <- notenum
src/Sound/Tidal/Pattern.hs view
@@ -212,7 +212,7 @@  -- | Also known as Continuous vs Discrete/Amorphous vs Pulsating etc. data Nature = Analog | Digital-            deriving Eq+            deriving (Eq, Show)  -- | A datatype that's basically a query, plus a hint about whether its events -- are Analogue or Digital by nature
src/Sound/Tidal/Stream.hs view
@@ -3,10 +3,11 @@  module Sound.Tidal.Stream where +import           Control.Applicative ((<|>)) import           Control.Concurrent.MVar import           Control.Concurrent import qualified Data.Map.Strict as Map-import           Data.Maybe (fromJust, fromMaybe)+import           Data.Maybe (fromJust, fromMaybe, isJust, catMaybes) import qualified Control.Exception as E -- import Control.Monad.Reader -- import Control.Monad.Except@@ -23,7 +24,7 @@ -- import qualified Sound.OSC.Datum as O  data TimeStamp = BundleStamp | MessageStamp | NoStamp- deriving Eq+ deriving (Eq, Show)  data Stream = Stream {sConfig :: Config,                       sInput :: MVar ControlMap,@@ -32,13 +33,17 @@                       sPMapMV :: MVar PlayMap,                       sTempoMV :: MVar T.Tempo,                       sGlobalFMV :: MVar (ControlPattern -> ControlPattern),-                      sTarget :: OSCTarget,-                      sUDP :: O.UDP+                      sCxs :: [Cx]                      }  type PatId = String -data OSCTarget = OSCTarget {oAddress :: String,+data Cx = Cx {cxTarget :: OSCTarget,+              cxUDP :: O.UDP+             }++data OSCTarget = OSCTarget {oName :: String,+                            oAddress :: String,                             oPort :: Int,                             oPath :: String,                             oShape :: Maybe [(String, Maybe Value)],@@ -46,9 +51,11 @@                             oPreamble :: [O.Datum],                             oTimestamp :: TimeStamp                            }+                 deriving Show  superdirtTarget :: OSCTarget-superdirtTarget = OSCTarget {oAddress = "127.0.0.1",+superdirtTarget = OSCTarget {oName = "SuperDirt",+                             oAddress = "127.0.0.1",                              oPort = 57120,                              oPath = "/play2",                              oShape = Nothing,@@ -57,12 +64,61 @@                              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)+dirtTarget :: OSCTarget+dirtTarget = OSCTarget {oName = "Dirt",+                        oAddress = "127.0.0.1",+                        oPort = 7771,+                        oPath = "/play",+                        oShape = Just [("sec", Just $ VI 0),+                                       ("usec", Just $ VI 0),+                                       ("cps", Just $ VF 0),+                                       ("s", Nothing),+                                       ("offset", Just $ VF 0),+                                       ("begin", Just $ VF 0),+                                       ("end", Just $ VF 1),+                                       ("speed", Just $ VF 1),+                                       ("pan", Just $ VF 0.5),+                                       ("velocity", Just $ VF 0.5),+                                       ("vowel", Just $ VS ""),+                                       ("cutoff", Just $ VF 0),+                                       ("resonance", Just $ VF 0),+                                       ("accelerate", Just $ VF 0),+                                       ("shape", Just $ VF 0),+                                       ("kriole", Just $ VI 0),+                                       ("gain", Just $ VF 1),+                                       ("cut", Just $ VI 0),+                                       ("delay", Just $ VF 0),+                                       ("delaytime", Just $ VF (-1)),+                                       ("delayfeedback", Just $ VF (-1)),+                                       ("crush", Just $ VF 0),+                                       ("coarse", Just $ VI 0),+                                       ("hcutoff", Just $ VF 0),+                                       ("hresonance", Just $ VF 0),+                                       ("bandf", Just $ VF 0),+                                       ("bandq", Just $ VF 0),+                                       ("unit", Just $ VS "rate"),+                                       ("loop", Just $ VF 0),+                                       ("n", Just $ VF 0),+                                       ("attack", Just $ VF (-1)),+                                       ("hold", Just $ VF 0),+                                       ("release", Just $ VF (-1)),+                                       ("orbit", Just $ VI 0)+                                      ],+                         oLatency = 0.02,+                         oPreamble = [],+                         oTimestamp = MessageStamp+                       }++startStream :: Config -> MVar ControlMap -> [OSCTarget] -> IO (MVar ControlPattern, MVar T.Tempo, [Cx])+startStream config cMapMV targets+  = do cxs <- mapM (\target -> do u <- O.openUDP (oAddress target) (oPort target)+                                  return $ Cx {cxUDP = u,+                                               cxTarget = target+                                              }+                   ) targets        pMV <- newMVar empty-       (tempoMV, _) <- T.clocked config $ onTick config cMapMV pMV target u-       return $ (pMV, tempoMV, u)+       (tempoMV, _) <- T.clocked config $ onTick config cMapMV pMV cxs+       return $ (pMV, tempoMV, cxs)   data PlayState = PlayState {pattern :: ControlPattern,@@ -74,25 +130,37 @@  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+toData :: OSCTarget -> Event ControlMap -> Maybe [O.Datum]+toData target e+  | isJust (oShape target) = fmap (fmap toDatum) $ sequence $ map (\(n,v) -> Map.lookup n (value e) <|> v) (fromJust $ oShape target)+  | otherwise = Just $ 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+toMessage :: Double -> OSCTarget -> T.Tempo -> Event (Map.Map String Value) -> Maybe O.Message+toMessage t target tempo e = do vs <- toData target addExtra+                                return $ O.Message (oPath target) $ oPreamble target ++ vs   where on = sched tempo $ start $ whole e         off = sched tempo $ stop $ whole e         delta = off - on+        messageStamp = oTimestamp target == MessageStamp         -- 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+        addExtra = (\v -> (Map.union v $ Map.fromList (extra messageStamp)+                          )) <$> e+        extra False = [("cps", (VF $ T.cps tempo)),+                       ("delta", VF delta),+                       ("cycle", VF (fromRational $ start $ whole e))+                      ]+        extra True = timestamp ++ (extra False)+        timestamp = [("sec", VI sec),+                     ("usec", VI usec)+                    ]+        ut = O.ntpr_to_ut t+        sec = floor ut+        usec = floor $ 1000000 * (ut - (fromIntegral sec))  doCps :: MVar T.Tempo -> (Double, Maybe Value) -> IO () doCps tempoMV (d, Just (VF cps)) = do _ <- forkIO $ do threadDelay $ floor $ d * 1000000@@ -102,8 +170,8 @@                                       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 =+onTick :: Config -> MVar ControlMap -> MVar ControlPattern -> [Cx] -> MVar T.Tempo -> T.State -> IO ()+onTick config cMapMV pMV cxs tempoMV st =   do p <- readMVar pMV      cMap <- readMVar cMapMV      tempo <- readMVar tempoMV@@ -111,18 +179,27 @@      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+         messages target = catMaybes $ map (\e -> do m <- toMessage (on e + latency target) target tempo e+                                                     return $ (on e, m)+                                           ) 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))+         latency target = oLatency target + cFrameTimespan config + T.nudged tempo+     mapM_ (\(Cx target udp) -> E.catch (mapM_ (send target (latency target) udp) (messages target))+                       (\(_ ::E.SomeException)+                        -> putStrLn $ "Failed to send. Is the '" ++ oName target ++ "' target running?"+                       )+           ) cxs      mapM_ (doCps tempoMV) cpsChanges      return () -send :: O.Transport t => Double -> t -> (Double, O.Message) -> IO ()-send latency u (time, m) = O.sendBundle u $ O.Bundle (time + latency) [m]+send :: O.Transport t => OSCTarget -> Double -> t -> (Double, O.Message) -> IO ()+send target latency u (time, m)+  | oTimestamp target == BundleStamp = O.sendBundle u $ O.Bundle (time + latency) [m]+  | oTimestamp target == MessageStamp = O.sendMessage u m+  | otherwise = do _ <- forkIO $ do now <- O.time+                                    threadDelay $ floor $ ((time+latency) - now) * 1000000+                                    O.sendMessage u m+                   return ()  sched :: T.Tempo -> Rational -> Double sched tempo c = ((fromRational $ c - (T.atCycle tempo)) / T.cps tempo) + (T.atTime tempo)@@ -185,9 +262,8 @@   = do cMap <- readMVar (sInput st)        tempo <- readMVar (sTempoMV st)        now <- O.time-       let target = if asap-                    then (sTarget st) {oLatency = 0}-                    else sTarget st+       let latency target | asap = 0+                          | otherwise = oLatency target            fakeTempo = T.Tempo {T.cps = T.cps tempo,                                 T.atCycle = 0,                                 T.atTime = now,@@ -201,10 +277,16 @@            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))+           messages target =+             catMaybes $ map (\e -> do m <- toMessage (at e + (latency target)) target fakeTempo e+                                       return $ (at e, m)+                             ) es+       mapM_ (\(Cx target udp) ->+                 E.catch (mapM_ (send target (oLatency target) udp) (messages target))+                 (\(_ ::E.SomeException)+                   -> putStrLn $ "Failed to send. Is the '" ++ oName target ++ "' target running?"+                 )+             ) (sCxs st)        mapM_ (doCps $ sTempoMV st) cpsChanges        return () @@ -249,10 +331,13 @@                                        ) (Map.elems pMap)  startTidal :: OSCTarget -> Config -> IO Stream-startTidal target config =+startTidal target config = startMulti [target] config++startMulti :: [OSCTarget] -> Config -> IO Stream+startMulti targets config =   do cMapMV <- newMVar (Map.empty :: ControlMap)      listenTid <- ctrlListen cMapMV config-     (pMV, tempoMV, u) <- startStream config cMapMV target+     (pMV, tempoMV, cxs) <- startStream config cMapMV targets      pMapMV <- newMVar Map.empty      globalFMV <- newMVar id      return $ Stream {sConfig = config,@@ -262,8 +347,7 @@                       sPMapMV = pMapMV,                       sTempoMV = tempoMV,                       sGlobalFMV = globalFMV,-                      sTarget = target,-                      sUDP = u+                      sCxs = cxs                      }  ctrlListen :: MVar ControlMap -> Config -> IO (Maybe ThreadId)
src/Sound/Tidal/Transition.hs view
@@ -16,7 +16,7 @@ import Sound.Tidal.Pattern import Sound.Tidal.Stream import Sound.Tidal.Tempo (timeToCycles)-import Sound.Tidal.UI (fadeOutFrom, fadeInFrom, spread')+import Sound.Tidal.UI (fadeOutFrom, fadeInFrom) import Sound.Tidal.Utils (enumerate)  -- Evaluation of pat is forced so exceptions are picked up here, before replacing the existing pattern.@@ -177,7 +177,7 @@ 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+anticipateIn t now pats = washIn (innerJoin . (\pat -> (\v -> _stut 8 0.2 v pat) <$> (now `rotR` (_slow t $ toRational <$> envLR)))) t now pats  -- wash :: (Pattern a -> Pattern a) -> (Pattern a -> Pattern a) -> Time -> Time -> Time -> Time -> [Pattern a] -> Pattern a 
src/Sound/Tidal/UI.hs view
@@ -78,7 +78,7 @@ samples from a folder:  @-d1 $ n (irand 5) # sound "drum"+d1 $ segment 4 $ n (irand 5) # sound "drum" @ -} irand :: Num a => Int -> Pattern a@@ -364,26 +364,20 @@  -- | Degrades a pattern over the given time. fadeOut :: Time -> Pattern a -> Pattern a-fadeOut dur p = do slope <- _slow dur envL-                   _degradeBy slope p+fadeOut dur p = innerJoin $ (\slope -> _degradeBy slope p) <$> (_slow dur envL)  -- | 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-+fadeOutFrom from dur p = innerJoin $ (\slope -> _degradeBy slope p) <$> (from `rotR` _slow dur envL)  -- | '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+fadeIn dur p = innerJoin $ (\slope -> _degradeBy slope p) <$> (_slow dur envLR)  -- | 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-+fadeInFrom from dur p = innerJoin $ (\slope -> _degradeBy slope p) <$> (from `rotR` _slow dur envLR)  {- | The 'spread' function allows you to take a pattern transformation which takes a parameter, such as `slow`, and provide several@@ -1288,6 +1282,50 @@ -- | Shorthand alias for arpeggiate arpg :: Pattern a -> Pattern a arpg = arpeggiate+++arpWith :: ([EventF (ArcF Time) a] -> [EventF (ArcF Time) b]) -> Pattern a -> Pattern b+arpWith f p = withEvents munge p+  where munge es = concatMap (spreadOut . f) (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)++arp :: Pattern String -> Pattern a -> Pattern a+arp = tParam _arp++_arp :: String -> Pattern a -> Pattern a+_arp name p = arpWith f p+  where f = fromMaybe id $ lookup name arps+        arps :: [(String, [a] -> [a])]+        arps = [("up", id),+                ("down", reverse),+                ("updown", \x -> init x ++ init (reverse x)),+                ("downup", \x -> init (reverse x) ++ init x),+                ("up&down", \x -> x ++ reverse x),+                ("down&up", \x -> reverse x ++ x),+                ("converge", converge),+                ("diverge", reverse . converge),+                ("disconverge", \x -> converge x ++ (tail $ reverse $ converge x)),+                ("pinkyup", pinkyup),+                ("pinkyupdown", \x -> init (pinkyup x) ++ init (reverse $ pinkyup x)),+                ("thumbup", thumbup),+                ("thumbupdown", \x -> init (thumbup x) ++ init (reverse $ thumbup x))+               ]+        converge [] = []+        converge (x:xs) = x:(converge' xs)+        converge' [] = []+        converge' xs = (last xs):(converge $ init xs)+        pinkyup xs = concatMap (:[pinky]) $ init xs+          where pinky = last xs+        thumbup xs = concatMap (\x -> [thumb,x]) $ tail xs+          where thumb = head xs+  {- TODO ! 
+ test/Sound/Tidal/ControlTest.hs view
@@ -0,0 +1,27 @@+{-# LANGUAGE OverloadedStrings #-}++module Sound.Tidal.ControlTest 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.Control" $ do+    describe "stutWith" $ do+      it "can mimic stut" $ do+        comparePD (Arc 0 1)+          (stutWith 4 0.25 (# gain 1) $ sound "bd")+          (stut 4 1 0.25 $ sound "bd")+        
test/Sound/Tidal/CoreTest.hs view
@@ -134,3 +134,8 @@         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")+    describe "every" $ do+      it "`every n id` doesn't change the pattern's structure" $ do+        comparePD (Arc 0 4)+          (every 2 id $ "x/2" :: Pattern String)+          ("x/2")
test/Sound/Tidal/MiniTidalTest.hs view
@@ -133,3 +133,15 @@     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>"))++    it "parses a binary Num function spread over a simple Num pattern" $+      "n (spread (+) [2,3,4] \"1 2 3\")" `parsesTo`+        (n (spread (+) [2,3,4] "1 2 3"))++    it "parses an $ application spread over partially applied transformations of a non-Control Pattern" $+      "n (spread ($) [density 2, rev, slow 2] $ \"1 2 3 4\")" `parsesTo`+        (n (spread ($) [density 2, rev, slow 2] $ "1 2 3 4"))++    it "parses an $ application spread over partially applied transformations of a Control Pattern" $+      "spread ($) [density 2, rev, slow 2, striate 3] $ sound \"[bd*2 [~ bd]] [sn future]*2 cp jvbass*4\"" `parsesTo`+        (spread ($) [density 2, rev, slow 2, striate 3] $ sound "[bd*2 [~ bd]] [sn future]*2 cp jvbass*4")
test/Test.hs view
@@ -6,6 +6,7 @@ import Sound.Tidal.MiniTidalTest import Sound.Tidal.ParseTest import Sound.Tidal.PatternTest+import Sound.Tidal.ControlTest import Sound.Tidal.UITest import Sound.Tidal.UtilsTest @@ -15,5 +16,6 @@   Sound.Tidal.MiniTidalTest.run   Sound.Tidal.ParseTest.run   Sound.Tidal.PatternTest.run+  Sound.Tidal.ControlTest.run   Sound.Tidal.UITest.run   Sound.Tidal.UtilsTest.run
tidal.cabal view
@@ -1,5 +1,5 @@ name:                tidal-version:             1.0.5+version:             1.0.6 synopsis:            Pattern language for improvised music -- description: homepage:            http://tidalcycles.org/@@ -49,21 +49,15 @@    Build-depends:       base < 5-    , containers-    , hashable-    , colour-    , hosc == 0.17-    , text-    , random-    , time-    , parsec-    , safe-    , mtl >= 2.1-    , monad-loops-    , network-    , mwc-random-    , vector-    , bifunctors+    , containers < 0.7+    , colour < 2.4+    , hosc < 0.18+    , text < 1.3+    , parsec < 3.2+    , network < 2.9+    , mwc-random < 0.15+    , vector < 0.13+    , bifunctors < 5.6    if !impl(ghc >= 8.4.1)     build-depends: semigroups == 0.18.*@@ -74,7 +68,8 @@   hs-source-dirs:       test   ghc-options: -Wall-  other-modules: Sound.Tidal.CoreTest+  other-modules: Sound.Tidal.ControlTest+                 Sound.Tidal.CoreTest                  Sound.Tidal.MiniTidalTest                  Sound.Tidal.ParseTest                  Sound.Tidal.PatternTest
tidal.el view
@@ -54,8 +54,7 @@   "*The version of tidal interpreter as a string.")  (defvar tidal-interpreter-arguments-  (list "-XOverloadedStrings"-        )+  ()   "*Arguments to the haskell interpreter (default=none).")  (defvar tidal-literate-p@@ -92,8 +91,9 @@   (if (string< tidal-interpreter-version "8.2.0")       (tidal-send-string ":set prompt2 \"\"")     (tidal-send-string ":set prompt-cont \"\""))-  (tidal-send-string "import Sound.Tidal.Context-tidal <- startTidal (superdirtTarget {oLatency = 0.1, oAddress = \"127.0.0.1\", oPort = 57120}) (defaultConfig {cFrameTimespan = 1/20})+  (tidal-send-string ":set -XOverloadedStrings+import Sound.Tidal.Context+tidal <- startMulti [superdirtTarget {oLatency = 0.1, oAddress = \"127.0.0.1\", oPort = 57120}] (defaultConfig {cFrameTimespan = 1/20, cCtrlListen = True}) let p = streamReplace tidal     hush = streamHush tidal     list = streamList tidal@@ -107,31 +107,31 @@     all = streamAll tidal     resetCycles = streamResetCycles 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)+    xfade i = transition tidal (Sound.Tidal.Transition.xfadeIn 4) i+    xfadeIn i t = transition tidal (Sound.Tidal.Transition.xfadeIn t) i+    histpan i t = transition tidal (Sound.Tidal.Transition.histpan t) i+    wait i t = transition tidal (Sound.Tidal.Transition.wait t) i+    waitT i f t = transition tidal (Sound.Tidal.Transition.waitT f t) i+    jump i = transition tidal (Sound.Tidal.Transition.jump) i+    jumpIn i t = transition tidal (Sound.Tidal.Transition.jumpIn t) i+    jumpIn' i t = transition tidal (Sound.Tidal.Transition.jumpIn' t) i+    jumpMod i t = transition tidal (Sound.Tidal.Transition.jumpMod t) i+    mortal i lifespan release = transition tidal (Sound.Tidal.Transition.mortal lifespan release) i+    interpolate i = transition tidal (Sound.Tidal.Transition.interpolate) i+    interpolateIn i t = transition tidal (Sound.Tidal.Transition.interpolateIn t) i+    clutch i = transition tidal (Sound.Tidal.Transition.clutch) i+    clutchIn i t = transition tidal (Sound.Tidal.Transition.clutchIn t) i+    anticipate i = transition tidal (Sound.Tidal.Transition.anticipate) i+    anticipateIn i t = transition tidal (Sound.Tidal.Transition.anticipateIn t) i     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+    d2 = p 2 -- . (|< orbit 1)+    d3 = p 3 -- . (|< orbit 2)+    d4 = p 4 -- . (|< orbit 3)+    d5 = p 5 -- . (|< orbit 4)+    d6 = p 6 -- . (|< orbit 5)+    d7 = p 7 -- . (|< orbit 6)+    d8 = p 8 -- . (|< orbit 7)+    d9 = p 9 -- . (|< orbit 8)     d10 = p 10     d11 = p 11     d12 = p 12