diff --git a/Sound/Tidal/Dirt.hs b/Sound/Tidal/Dirt.hs
--- a/Sound/Tidal/Dirt.hs
+++ b/Sound/Tidal/Dirt.hs
@@ -2,7 +2,7 @@
   
 module Sound.Tidal.Dirt where
 
-import Sound.OSC.FD
+import Sound.OSC.FD (Datum)
 import qualified Data.Map as Map
 import Control.Applicative
 import Control.Concurrent.MVar
@@ -18,6 +18,7 @@
 import Sound.Tidal.Stream
 import Sound.Tidal.Pattern
 import Sound.Tidal.Parse
+import Sound.Tidal.Time
 
 dirt :: OscShape
 dirt = OscShape {path = "/play",
@@ -69,6 +70,7 @@
 
 dirtstart name = start "127.0.0.1" 7771 dirt
 dirtStream = stream "127.0.0.1" 7771 dirt
+dirtState = Sound.Tidal.Stream.state "127.0.0.1" 7771 dirt
 
 -- disused parameter..
 dirtstream _ = dirtStream
@@ -149,7 +151,7 @@
 
 
 pick :: String -> Int -> String
-pick name n = name ++ "/" ++ (show n)
+pick name n = name ++ ":" ++ (show n)
 
 striate :: Int -> OscPattern -> OscPattern
 striate n p = cat $ map (\x -> off (fromIntegral x) p) [0 .. n-1]
@@ -171,3 +173,24 @@
 striateL' n f l p = striate' n f p |+| loop (atom $ fromIntegral l)
 
 metronome = slow 2 $ sound (p "[odx, [hh]*8]")
+
+dirtSetters :: IO Time -> IO (OscPattern -> IO (), (Time -> [OscPattern] -> OscPattern) -> OscPattern -> IO ())
+dirtSetters getNow = do ds <- dirtState
+                        return (setter ds, transition getNow ds)
+
+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)
+
+clutch :: Time -> [Pattern a] -> Pattern a
+clutch = clutchIn 2
+
+xfadeIn :: Time -> Time -> [OscPattern] -> OscPattern
+xfadeIn _ _ [] = silence
+xfadeIn _ _ (p:[]) = p
+xfadeIn t now (p:p':_) = overlay (p |+| gain (now ~> (slow t envEqR))) (p' |+| gain (now ~> (slow t (envEq))))
+
+xfade :: Time -> [OscPattern] -> OscPattern
+xfade = xfadeIn 2
+
diff --git a/Sound/Tidal/Pattern.hs b/Sound/Tidal/Pattern.hs
--- a/Sound/Tidal/Pattern.hs
+++ b/Sound/Tidal/Pattern.hs
@@ -362,9 +362,27 @@
 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 -> sin (pi/2 * (max 0 $ min (fromRational (1-t)) 1))
+-- Equal power reversed
+envEqR = sig $ \t -> 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 ~> 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 <~ degradeBy n p) (from ~> slow dur ((1-) <$> envL)) p
+
 fadeIn :: Time -> Pattern a -> Pattern a
 fadeIn n = spread' (degradeBy) (slow n $ (1-) <$> envL)
 
@@ -423,8 +441,9 @@
                 | otherwise = (arc $ f2 p) a
 
 rand :: Pattern Double
-rand = Pattern $ \a -> [(a, a, fst $ randomDouble $ pureMT $ floor $ (*1000000) $ (midPoint a))]
+rand = Pattern $ \a -> [(a, a, timeToRand $ (midPoint a))]
 
+timeToRand t = fst $ randomDouble $ pureMT $ floor $ (*1000000) t
 
 irand :: Double -> Pattern Int
 irand i = (floor . (*i)) <$> rand
@@ -601,3 +620,14 @@
 -- | @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 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' (<~) (discretise 1 $ ((%1) . fromIntegral) <$> irand (fromIntegral $ length ps)) (slowcat ps)
diff --git a/Sound/Tidal/Strategies.hs b/Sound/Tidal/Strategies.hs
--- a/Sound/Tidal/Strategies.hs
+++ b/Sound/Tidal/Strategies.hs
@@ -91,7 +91,7 @@
 cross f p p' = Pattern $ \t -> concat [filter flt $ arc p t,
                                        filter (not . flt) $ arc p' t
                                       ]
-  where flt = f . cyclePos . fst . fst
+]  where flt = f . cyclePos . fst . fst
 -}
 
 inside n f p = density n $ f (slow n p)
@@ -146,12 +146,23 @@
 en ns p = stack $ map (\(i, (k, n)) -> e k n (samples p (pure i))) $ enumerate ns
 
 weave :: Rational -> OscPattern -> [OscPattern] -> OscPattern
-weave t p ps = weave' t p (map const ps)
+weave t p ps = weave' t p (map (\x -> (x |+|)) ps)
 
-weave' :: Rational -> OscPattern -> [OscPattern -> OscPattern] -> OscPattern
+weave' :: Rational -> Pattern a -> [Pattern a -> Pattern a] -> Pattern a
 weave' t p fs | l == 0 = silence
-             | otherwise = slow t $ stack $ map (\(i, f) -> ((density t (f p)) |+| (((fromIntegral i) % l) <~ p))) (zip [0 ..] fs)
+              | otherwise = slow t $ stack $ map (\(i, f) -> (fromIntegral i % l) <~ (density t $ f (slow t p))) (zip [0 ..] fs)
   where l = fromIntegral $ length fs
 
-interlace :: OscPattern -> OscPattern -> OscPattern
-interlace a b = weave 16 (shape $ ((* 0.9) <$> sinewave1)) [a, b]
+
+--interlace :: OscPattern -> OscPattern -> OscPattern
+--interlace a b = weave 16 (shape $ ((* 0.9) <$> sinewave1)) [a, b]
+
+-- Step sequencing
+step :: String -> String -> Pattern String
+step s steps = cat $ map f steps
+    where f c | c == 'x' = atom s
+              | c >= '0' && c <= '9' = atom $ s ++ ":" ++ [c]
+              | otherwise = silence
+
+steps :: [(String, String)] -> Pattern String
+steps = stack . map (\(a,b) -> step a b)
diff --git a/Sound/Tidal/Stream.hs b/Sound/Tidal/Stream.hs
--- a/Sound/Tidal/Stream.hs
+++ b/Sound/Tidal/Stream.hs
@@ -17,6 +17,7 @@
 import qualified Sound.Tidal.Parse as P
 import Sound.Tidal.Tempo (Tempo, logicalTime, clocked,clockedTick,cps)
 import Sound.Tidal.Utils
+import qualified Sound.Tidal.Time as T
 
 import qualified Data.Map as Map
 
@@ -121,6 +122,15 @@
        forkIO $ clockedTick ticksPerCycle ot
        return patternM
 
+-- variant of start where history of patterns is available
+state :: String -> Int -> OscShape -> IO (MVar (OscPattern, [OscPattern]))
+state address port shape
+  = do patternsM <- newMVar (silence, [])
+       s <- openUDP address port
+       let ot = (onTick' s shape patternsM) :: Tempo -> Int -> IO ()
+       forkIO $ clockedTick ticksPerCycle ot
+       return patternsM
+
 stream :: String -> Int -> OscShape -> IO (OscPattern -> IO ())
 stream address port shape 
   = do patternM <- start address port shape
@@ -146,6 +156,19 @@
        E.catch (sequence_ messages) (\msg -> putStrLn $ "oops " ++ show (msg :: E.SomeException))
        return ()
 
+-- Variant where mutable variable contains list as history of the patterns
+onTick' :: UDP -> OscShape -> MVar (OscPattern, [OscPattern]) -> Tempo -> Int -> IO ()
+onTick' s shape patternsM change ticks
+  = do ps <- readMVar patternsM
+       let ticks' = (fromIntegral ticks) :: Integer
+           a = ticks' % ticksPerCycle
+           b = (ticks' + 1) % ticksPerCycle
+           messages = mapMaybe 
+                      (toMessage s shape change ticks) 
+                      (seqToRelOnsets (a, b) $ fst ps)
+       E.catch (sequence_ messages) (\msg -> putStrLn $ "oops " ++ show (msg :: E.SomeException))
+       return ()
+
 make :: (a -> Datum) -> OscShape -> String -> Pattern a -> OscPattern
 make toOsc s nm p = fmap (\x -> Map.singleton nParam (defaultV x)) p
   where nParam = param s nm
@@ -165,7 +188,7 @@
 
 param :: OscShape -> String -> Param
 param shape n = head $ filter (\x -> name x == n) (params shape)
-                
+
 merge :: OscPattern -> OscPattern -> OscPattern
 merge x y = (flip Map.union) <$> x <*> y
 
@@ -173,7 +196,18 @@
 (|+|) :: OscPattern -> OscPattern -> OscPattern
 (|+|) = merge
 
-
-
-
+transition :: (IO T.Time) -> MVar (OscPattern, [OscPattern]) -> (T.Time -> [OscPattern] -> OscPattern) -> OscPattern -> 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 ()
 
+setter :: MVar (a, [a]) -> a -> IO ()
+setter ds p = do ps <- takeMVar ds
+                 putMVar ds $ (p, p:snd ps)
+                 return ()
diff --git a/tidal.cabal b/tidal.cabal
--- a/tidal.cabal
+++ b/tidal.cabal
@@ -1,5 +1,5 @@
 name:                tidal
-version:         0.4.33
+version:         0.4.34
 synopsis:            Pattern language for improvised music
 -- description:         
 homepage:            http://tidal.lurk.org/
diff --git a/tidal.el b/tidal.el
--- a/tidal.el
+++ b/tidal.el
@@ -56,21 +56,17 @@
     (tidal-see-output))
   (tidal-send-string ":set prompt \"\"")
   (tidal-send-string ":module Sound.Tidal.Context")
-;  (tidal-send-string "import Volca.Beat")
-;  (tidal-send-string "import Volca.Key")
-;  (tidal-send-string "(note, [portamento, expression, voice, octave, detune, vcoegint, kcutoff, vcfegint, lforate, lfopitchint, lfocutoffint, attack, decay, sustain, dtime , dfeedback], keystop) <- keystart")
-;  (tidal-send-string "(drum, [clapSpeed, clavesSpeed, agogoSpeed, crashSpeed, stutterTime, stutterDepth, tomDecay, clhatDecay, ophatDecay, hatGrain], beatstop) <- startbeat")
-  (tidal-send-string "d1 <- dirtStream")
-  (tidal-send-string "d2 <- dirtStream")
-  (tidal-send-string "d3 <- dirtStream")
-  (tidal-send-string "d4 <- dirtStream")
-  (tidal-send-string "d5 <- dirtStream")
-  (tidal-send-string "d6 <- dirtStream")
-  (tidal-send-string "d7 <- dirtStream")
-  (tidal-send-string "d8 <- dirtStream")
-  (tidal-send-string "d9 <- dirtStream")
-  (tidal-send-string "d10 <- dirtStream")
   (tidal-send-string "(cps, getNow) <- bpsUtils")
+  (tidal-send-string "(d1,t1) <- dirtSetters getNow")
+  (tidal-send-string "(d2,t2) <- dirtSetters getNow")
+  (tidal-send-string "(d3,t3) <- dirtSetters getNow")
+  (tidal-send-string "(d4,t4) <- dirtSetters getNow")
+  (tidal-send-string "(d5,t5) <- dirtSetters getNow")
+  (tidal-send-string "(d6,t6) <- dirtSetters getNow")
+  (tidal-send-string "(d7,t7) <- dirtSetters getNow")
+  (tidal-send-string "(d8,t8) <- dirtSetters getNow")
+  (tidal-send-string "(d9,t9) <- dirtSetters getNow")
+  (tidal-send-string "(d10,t10) <- dirtSetters getNow")
   (tidal-send-string "let bps x = cps (x/2)")
   (tidal-send-string "let hush = mapM_ ($ silence) [d1,d2,d3,d4,d5,d6,d7,d8,d9,d10]")
   (tidal-send-string "let solo = (>>) hush")
