diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -6,7 +6,7 @@
 For documentation, mailing list and more info see here:
   http://tidal.lurk.org/
 
-(c) Alex McLean and contributors, 2014
+(c) Alex McLean and contributors, 2015
 
 Distributed under the terms of the GNU Public license version 3 (or
 later).
diff --git a/Sound/Tidal/Context.hs b/Sound/Tidal/Context.hs
--- a/Sound/Tidal/Context.hs
+++ b/Sound/Tidal/Context.hs
@@ -4,6 +4,7 @@
 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.Stream as C
@@ -12,3 +13,6 @@
 import Sound.Tidal.Tempo as C
 import Sound.Tidal.Time as C
 import Sound.Tidal.SuperCollider as C
+import Sound.Tidal.Params as C
+import Sound.Tidal.Transition as C
+
diff --git a/Sound/Tidal/Dirt.hs b/Sound/Tidal/Dirt.hs
--- a/Sound/Tidal/Dirt.hs
+++ b/Sound/Tidal/Dirt.hs
@@ -19,37 +19,38 @@
 import Sound.Tidal.Stream
 import Sound.Tidal.Pattern
 import Sound.Tidal.Parse
+import Sound.Tidal.Params
 import Sound.Tidal.Time
 import Sound.Tidal.Utils (enumerate)
 
 dirt :: OscShape
 dirt = OscShape {path = "/play",
-                 params = [ S "sound" Nothing,
-                            F "offset" (Just 0),
-                            F "begin" (Just 0),
-                            F "end" (Just 1),
-                            F "speed" (Just 1),
-                            F "pan" (Just 0.5),
-                            F "velocity" (Just 0),
-                            S "vowel" (Just ""),
-                            F "cutoff" (Just 0),
-                            F "resonance" (Just 0),
-                            F "accelerate" (Just 0),
-                            F "shape" (Just 0),
-                            I "kriole" (Just 0),
-                            F "gain" (Just 1),
-                            I "cut" (Just (0)),
-                            F "delay" (Just (0)),
-                            F "delaytime" (Just (-1)),
-                            F "delayfeedback" (Just (-1)),
-                            F "crush" (Just 0),
-                            I "coarse" (Just 0),
-                            F "hcutoff" (Just 0),
-                            F "hresonance" (Just 0),
-                            F "bandf" (Just 0),
-                            F "bandq" (Just 0),
-                            S "unit" (Just "rate"),
-                            I "loop" (Just 1)
+                 params = [ sound_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
                           ],
                  cpsStamp = True,
                  timestamp = MessageStamp,
@@ -58,18 +59,6 @@
                  preamble = []
                 }
 
-kriole :: OscShape
-kriole = OscShape {path = "/trigger",
-                 params = [ I "ksymbol" Nothing,
-                            F "kpitch" (Just 1)
-                          ],
-                 cpsStamp = False,
-                 timestamp = MessageStamp,
-                 latency = 0.04,
-                 namedParams = False,
-                 preamble = []
-                }
-
 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
@@ -77,8 +66,6 @@
 -- disused parameter..
 dirtstream _ = dirtStream
 
-kstream name = stream "127.0.0.1" 6040 kriole
-
 doubledirt = do remote <- stream "178.77.72.138" 7777 dirt
                 local <- stream "192.168.0.102" 7771 dirt
                 return $ \p -> do remote p
@@ -118,68 +105,30 @@
 --                            streamcallback cb "127.0.0.1" "127.0.0.1" name "127.0.0.1" 7771 dirt
                             
 
-sound        = makeS dirt "sound"
-offset       = makeF dirt "offset"
-begin        = makeF dirt "begin"
-end          = makeF dirt "end"
-speed        = makeF dirt "speed"
-pan          = makeF dirt "pan"
-velocity     = makeF dirt "velocity"
-vowel        = makeS dirt "vowel"
-cutoff       = makeF dirt "cutoff"
-resonance    = makeF dirt "resonance"
-accelerate   = makeF dirt "accelerate"
-shape        = makeF dirt "shape"
-gain         = makeF dirt "gain"
-delay        = makeF dirt "delay"
-delaytime    = makeF dirt "delaytime"
-delayfeedback = makeF dirt "delayfeedback"
-crush        = makeF dirt "crush"
-
-coarse :: Pattern Int -> OscPattern
-coarse       = makeI dirt "coarse"
-hcutoff      = makeF dirt "hcutoff"
-hresonance   = makeF dirt "hresonance"
-bandf        = makeF dirt "bandf"
-bandq        = makeF dirt "bandq"
-unit         = makeS dirt "unit"
-loop         = makeI dirt "loop"
-
-cut :: Pattern Int -> OscPattern
-cut = makeI dirt "cut"
-
-ksymbol      = makeF kriole "ksymbol"
-kpitch       = makeF kriole "kpitch"
-
-
 pick :: String -> Int -> String
 pick name n = name ++ ":" ++ (show n)
 
 striate :: Int -> OscPattern -> OscPattern
 striate n p = cat $ 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))
+                  # begin (atom (fromIntegral i / fromIntegral n)) 
+                  # end (atom (fromIntegral (i+1) / fromIntegral n))
 
 striate' :: Int -> Double -> OscPattern -> OscPattern
 striate' n f p = cat $ 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)
+  where off i p = p # begin (atom (slot * i) :: Pattern Double) # end (atom ((slot * i) + f) :: Pattern Double)
         slot = (1 - f) / (fromIntegral n)
 
 striateO :: OscPattern -> Int -> Double -> OscPattern
 striateO p n o = cat $ map (\x -> off (fromIntegral x) p) [0 .. n-1]
-  where off i p = p |+| begin ((atom $ (fromIntegral i / fromIntegral n) + o) :: Pattern Double) |+| end ((atom $ (fromIntegral (i+1) / fromIntegral n) + o) :: Pattern Double)
+  where off i p = p # begin ((atom $ (fromIntegral i / fromIntegral n) + o) :: Pattern Double) # end ((atom $ (fromIntegral (i+1) / fromIntegral n) + o) :: Pattern Double)
 
 striateL :: Int -> Int -> OscPattern -> OscPattern
-striateL n l p = striate n p |+| loop (atom $ fromIntegral l)
-striateL' n f l p = striate' n f p |+| loop (atom $ fromIntegral l)
+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]")
 
-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
@@ -191,27 +140,16 @@
 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))))
+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
 
 stut :: Integer -> Double -> Rational -> OscPattern -> OscPattern
-stut steps feedback time p = stack (p:(map (\x -> (((x%steps)*time) ~> (p |+| gain (pure $ scale (fromIntegral x))))) [1..(steps-1)])) 
+stut steps feedback time p = stack (p:(map (\x -> (((x%steps)*time) ~> (p |*| gain (pure $ scale (fromIntegral x))))) [1..(steps-1)])) 
   where scale x 
           = ((+feedback) . (*(1-feedback)) . (/(fromIntegral steps)) . ((fromIntegral steps)-)) x
 
-anticipateIn :: Time -> Time -> [OscPattern] -> OscPattern
-anticipateIn _ _ [] = silence
-anticipateIn _ _ (p:[]) = p
-anticipateIn t now (p:p':_) = overlay (playWhen (< (now + t)) $ spread' (stut 8 0.2) (now ~> (slow t $ toRational <$> envL)) p') (playWhen (>= (now + t)) p)
-
-anticipate :: Time -> [OscPattern] -> OscPattern
-anticipate = anticipateIn 4
-
-histpan :: Int -> Time -> [OscPattern] -> OscPattern
-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
+stut' :: Integer -> Time -> (OscPattern -> OscPattern) -> OscPattern -> OscPattern
+stut' steps steptime f p | steps <= 0 = p
+                         | otherwise = overlay (f (steptime ~> stut' (steps-1) steptime f p)) p
diff --git a/Sound/Tidal/Params.hs b/Sound/Tidal/Params.hs
new file mode 100644
--- /dev/null
+++ b/Sound/Tidal/Params.hs
@@ -0,0 +1,116 @@
+module Sound.Tidal.Params where
+
+import Sound.Tidal.Stream
+import Sound.Tidal.Pattern
+import Sound.OSC.FD
+import Sound.OSC.Datum
+import Data.Map as Map
+
+make' :: (a -> Datum) -> Param -> Pattern a -> OscPattern
+make' toOsc par p = fmap (\x -> Map.singleton par (defaultV x)) p
+  where defaultV a = Just $ toOsc a
+
+sound :: Pattern String -> OscPattern
+sound = make' string sound_p
+sound_p = S "sound" Nothing
+
+offset :: Pattern Double -> OscPattern
+offset = make' float offset_p
+offset_p = F "offset" (Just 0)
+
+begin :: Pattern Double -> OscPattern
+begin = make' float begin_p
+begin_p = F "begin" (Just 0)
+
+end :: Pattern Double -> OscPattern
+end = make' float end_p
+end_p = F "end" (Just 1)
+
+speed :: Pattern Double -> OscPattern
+speed = make' float speed_p
+speed_p = F "speed" (Just 1)
+
+pan :: Pattern Double -> OscPattern
+pan = make' float pan_p
+pan_p = F "pan" (Just 0.5)
+
+velocity :: Pattern Double -> OscPattern
+velocity = make' float velocity_p
+velocity_p = F "velocity" (Just 0)
+
+vowel :: Pattern String -> OscPattern
+vowel = make' string vowel_p
+vowel_p = S "vowel" (Just "")
+
+cutoff :: Pattern Double -> OscPattern
+cutoff = make' float cutoff_p
+cutoff_p = F "cutoff" (Just 0)
+
+resonance :: Pattern Double -> OscPattern
+resonance = make' float resonance_p
+resonance_p = F "resonance" (Just 0)
+
+accelerate :: Pattern Double -> OscPattern
+accelerate = make' float accelerate_p
+accelerate_p = F "accelerate" (Just 0)
+
+shape :: Pattern Double -> OscPattern
+shape = make' float shape_p
+shape_p = F "shape" (Just 0)
+
+kriole :: Pattern Int -> OscPattern
+kriole = make' int32 kriole_p
+kriole_p = I "kriole" (Just 0)
+
+gain :: Pattern Double -> OscPattern
+gain = make' float gain_p
+gain_p = F "gain" (Just 1)
+
+cut :: Pattern Int -> OscPattern
+cut = make' int32 cut_p
+cut_p = I "cut" (Just (0))
+
+delay :: Pattern Double -> OscPattern
+delay = make' float delay_p
+delay_p = F "delay" (Just (0))
+
+delaytime :: Pattern Double -> OscPattern
+delaytime = make' float delaytime_p
+delaytime_p = F "delaytime" (Just (-1))
+
+delayfeedback :: Pattern Double -> OscPattern
+delayfeedback = make' float delayfeedback_p
+delayfeedback_p = F "delayfeedback" (Just (-1))
+
+crush :: Pattern Double -> OscPattern
+crush = make' float crush_p
+crush_p = F "crush" (Just 0)
+
+coarse :: Pattern Int -> OscPattern
+coarse = make' int32 coarse_p
+coarse_p = I "coarse" (Just 0)
+
+hcutoff :: Pattern Double -> OscPattern
+hcutoff = make' float hcutoff_p
+hcutoff_p = F "hcutoff" (Just 0)
+
+hresonance :: Pattern Double -> OscPattern
+hresonance = make' float hresonance_p
+hresonance_p = F "hresonance" (Just 0)
+
+bandf :: Pattern Double -> OscPattern
+bandf = make' float bandf_p
+bandf_p = F "bandf" (Just 0)
+
+bandq :: Pattern Double -> OscPattern
+bandq = make' float bandq_p
+bandq_p = F "bandq" (Just 0)
+
+unit :: Pattern String -> OscPattern
+unit = make' string unit_p
+unit_p = S "unit" (Just "rate")
+
+loop :: Pattern Int -> OscPattern
+loop = make' int32 loop_p
+loop_p = I "loop" (Just 1)
+
diff --git a/Sound/Tidal/Parse.hs b/Sound/Tidal/Parse.hs
--- a/Sound/Tidal/Parse.hs
+++ b/Sound/Tidal/Parse.hs
@@ -182,15 +182,20 @@
               <|> return thing
 
 pE :: Pattern a -> Parser (Pattern a)
-pE thing = do (n,k) <- parens (pair)
-              return $ e n k thing
+pE thing = do (n,k,s) <- parens (pair)
+              return $ unwrap $ eoff <$> n <*> k <*> s <*> atom thing
             <|> return thing
-   where pair = do a <- integer
+   where pair = do a <- pSequence pInt
                    spaces
                    symbol ","
                    spaces
-                   b <- integer
-                   return (fromIntegral a, fromIntegral b)
+                   b <- pSequence pInt
+                   c <- do symbol ","
+                           spaces
+                           pSequence pInt
+                        <|> return (atom 0)
+                   return (fromIntegral <$> a, fromIntegral <$> b, fromIntegral <$> c)
+         eoff n k s p = ((s%(fromIntegral k)) <~) (e n k p)
                    
 
 pReplicate :: Pattern a -> Parser ([Pattern a])
diff --git a/Sound/Tidal/Pattern.hs b/Sound/Tidal/Pattern.hs
--- a/Sound/Tidal/Pattern.hs
+++ b/Sound/Tidal/Pattern.hs
@@ -127,10 +127,10 @@
 withResultTime = withResultArc . mapArc
 
 -- | @overlay@ combines two @Pattern@s into a new pattern, so that
--- their events are combined over time.
+-- 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)
-(>+<) = overlay
 
 -- | @stack@ combines a list of @Pattern@s into a new pattern, so that
 -- their events are combined over time.
@@ -368,9 +368,9 @@
 
 -- 'Equal power' for gain-based transitions
 envEq :: Pattern Double
-envEq = sig $ \t -> sin (pi/2 * (max 0 $ min (fromRational (1-t)) 1))
+envEq = sig $ \t -> sqrt (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))
+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)
@@ -476,7 +476,7 @@
 -- @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 <~ densityGap (1/(1-t)) p')
+wedge t p p' = overlay (densityGap (1/t) p) (t ~> densityGap (1/(1-t)) p')
 
 whenmod :: Int -> Int -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
 whenmod a b = Sound.Tidal.Pattern.when ((\t -> (t `mod` a) >= b ))
@@ -631,3 +631,23 @@
 -- 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)
+
+toMIDI :: Pattern String -> Pattern Int
+toMIDI p = fromJust <$> (filterValues (isJust) (noteLookup <$> p))
+  where
+    noteLookup [] = Nothing
+    noteLookup s | last s `elem` ['0' .. '9'] = elemIndex s names
+                 | otherwise = noteLookup (s ++ "5")
+    names = take 128 [(n ++ show o)
+                     | o <- octaves,
+                       n <- notes
+                     ]
+    notes = ["c","cs","d","ds","e","f","fs","g","gs","a","as","b"]
+    octaves = [0 .. 10]
+
+tom = toMIDI
+
+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)
+
diff --git a/Sound/Tidal/Strategies.hs b/Sound/Tidal/Strategies.hs
--- a/Sound/Tidal/Strategies.hs
+++ b/Sound/Tidal/Strategies.hs
@@ -12,6 +12,7 @@
 import Sound.Tidal.Stream
 import Sound.Tidal.Time
 import Sound.Tidal.Utils
+import Sound.Tidal.Params
 import qualified Sound.OSC.FD as OSC.FD
 
 stutter n t p = stack $ map (\i -> (t * (fromIntegral i)) ~> p) [0 .. (n-1)]
@@ -21,14 +22,19 @@
 quad   = stutter 4
 double = echo
 
-jux f p = stack [p |+| pan (pure 0), f $ p |+| pan (pure 1)]
-juxcut f p = stack [p     |+| pan (pure 0) |+| cut (pure (-1)), 
-                    f $ p |+| pan (pure 1) |+| cut (pure (-2))
+jux f p = stack [p # pan (pure 0), f $ p # pan (pure 1)]
+juxcut f p = stack [p     # pan (pure 0) # cut (pure (-1)), 
+                    f $ p # pan (pure 1) # cut (pure (-2))
                    ]
-jux4 f p = stack [p |+| pan (pure 0), f $ p |+| pan (pure 2)]
 
-juxBy n f p = stack [p |+| pan (pure $ 0.5 - (n/2)), f $ p |+| pan (pure $ 0.5 + (n/2))]
+jux' fs p = stack $ map (\n -> ((fs !! n) p) # pan (pure $ fromIntegral n / fromIntegral l)) [0 .. l-1]
+  where l = length fs
 
+-- For multichannel
+jux4 f p = stack [p # pan (pure (5/8)), f $ p # pan (pure (1/8))]
+
+juxBy n f p = stack [p # pan (pure $ 0.5 - (n/2)), f $ p # pan (pure $ 0.5 + (n/2))]
+
 -- every 4 (smash 4 [1, 2, 3]) $ sound "[odx sn/2 [~ odx] sn/3, [~ hh]*4]"
 
 smash n xs p = slowcat $ map (\n -> slow n p') xs
@@ -42,6 +48,8 @@
 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
@@ -68,7 +76,7 @@
 spin copies p =
   stack $ map (\n -> let offset = toInteger n % toInteger copies in
                      offset <~ p
-                     |+| pan (pure $ fromRational offset)
+                     # pan (pure $ fromRational offset)
               )
           [0 .. (copies - 1)]
 
@@ -84,7 +92,7 @@
 rand4 = ((*4) <$> rand)
 
 stackwith p ps | null ps = silence
-               | otherwise = stack $ map (\(i, p') -> p' |+| (((fromIntegral i) % l) <~ p)) (zip [0 ..] ps)
+               | otherwise = stack $ map (\(i, p') -> p' # (((fromIntegral i) % l) <~ p)) (zip [0 ..] ps)
   where l = fromIntegral $ length ps
 
 {-
@@ -141,7 +149,7 @@
 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 (\x -> (x |+|)) ps)
+weave t p ps = weave' t p (map (\x -> (x #)) ps)
 
 weave' :: Rational -> Pattern a -> [Pattern a -> Pattern a] -> Pattern a
 weave' t p fs | l == 0 = silence
@@ -160,3 +168,12 @@
 
 steps :: [(String, String)] -> Pattern String
 steps = stack . map (\(a,b) -> step a b)
+
+off :: Time -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
+off t f p = superimpose (f . (t ~>)) p
+
+offadd :: Num a => Time -> a -> Pattern a -> Pattern a
+offadd t n p = off t ((+n) <$>) p
+
+up :: Pattern Double -> OscPattern
+up = speed . ((1.059466**) <$>)
diff --git a/Sound/Tidal/Stream.hs b/Sound/Tidal/Stream.hs
--- a/Sound/Tidal/Stream.hs
+++ b/Sound/Tidal/Stream.hs
@@ -192,20 +192,33 @@
 merge :: OscPattern -> OscPattern -> OscPattern
 merge x y = (flip Map.union) <$> x <*> y
 
+infixl 1 |=|
+(|=|) :: OscPattern -> OscPattern -> OscPattern
+(|=|) = merge
+
+(#) = (|=|)
+
+mergeWith op x y = (Map.unionWithKey f) <$> x <*> y
+  where f (F _ _) (Just a) (Just b) = do a' <- datum_float a
+                                         b' <- datum_float b
+                                         return $ float (op a' b')
+        f _ a b = b
+
+infixl 1 |*|
+(|*|) :: OscPattern -> OscPattern -> OscPattern
+(|*|) = mergeWith (*)
+
 infixl 1 |+|
 (|+|) :: OscPattern -> OscPattern -> OscPattern
-(|+|) = merge
+(|+|) = mergeWith (+)
 
-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 ()
+infixl 1 |-|
+(|-|) :: OscPattern -> OscPattern -> OscPattern
+(|-|) = mergeWith (-)
+
+infixl 1 |/|
+(|/|) :: OscPattern -> OscPattern -> OscPattern
+(|/|) = mergeWith (/)
 
 setter :: MVar (a, [a]) -> a -> IO ()
 setter ds p = do ps <- takeMVar ds
diff --git a/Sound/Tidal/Transition.hs b/Sound/Tidal/Transition.hs
new file mode 100644
--- /dev/null
+++ b/Sound/Tidal/Transition.hs
@@ -0,0 +1,85 @@
+module Sound.Tidal.Transition where
+
+import Sound.Tidal.Dirt
+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.Monoid
+
+transition :: (IO Time) -> MVar (OscPattern, [OscPattern]) -> (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 ()
+
+-- Pans the last n versions of the pattern across the field
+histpan :: Int -> Time -> [OscPattern] -> OscPattern
+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
+
+-- generalizing wash to use pattern transformers on fadeout, fadein, and delay
+-- to start of transition
+superwash :: (Pattern a -> Pattern a) -> (Pattern a -> Pattern a) -> Time -> Time -> Time -> [Pattern a] -> Pattern a
+superwash _ _ _ _ _ [] = silence
+superwash _ _ _ _ _ (p:[]) = p
+superwash fout fin delay dur now (p:p':_) = 
+   (playWhen (< (now + delay)) p') <>
+   (playWhen (between (now + delay) (now + delay + dur)) $ fout p') <>
+   (playWhen (>= (now + delay + dur)) $ fin p)
+ where
+   between lo hi x = (x >= lo) && (x < hi)
+
+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)
+
+-- Increase comb filter to anticipate 'drop' to next pattern
+anticipateIn :: Time -> Time -> [OscPattern] -> OscPattern
+anticipateIn t now = wash (spread' (stut 8 0.2) (now ~> (slow t $ (toRational . (1-)) <$> envL))) t now
+
+anticipate :: Time -> [OscPattern] -> OscPattern
+anticipate = anticipateIn 8
+
+-- Just stop for a bit before playing new pattern
+wait :: Time -> Time -> [OscPattern] -> OscPattern
+wait t _ [] = silence
+wait t now (p:_) = playWhen (>= (nextSam (now+t-1))) p
+
+-- transition at cycle boundary after n cycles
+jumpIn' :: Int -> Time -> [OscPattern] -> OscPattern
+jumpIn' n now = superwash id id ((nextSam now) - now + (fromIntegral n)) 0 now
+
+-- sharp transition a certain number of cycles in the future
+jumpIn :: Int -> Time -> [OscPattern] -> OscPattern
+jumpIn n = superwash id id (fromIntegral n) 0
+
+jump :: Time -> [OscPattern] -> OscPattern
+jump = jumpIn 0
+
+-- transition at next cycle boundary where cycle mod n == 0
+jumpMod :: Int -> Time -> [OscPattern] -> OscPattern
+jumpMod n now = jumpIn ((n-1) - ((floor now) `mod` n)) now
+
+-- Degrade the new pattern over time until it goes to nothing
+mortal :: Time -> Time -> Time -> [OscPattern] -> OscPattern
+mortal _ _ _ [] = silence
+mortal lifespan release now (p:_) = overlay (playWhen (<(now+lifespan)) p) (playWhen (>= (now+lifespan)) (fadeOut' (now + lifespan) release p))
+
+dirtSetters :: IO Time -> IO (OscPattern -> IO (), (Time -> [OscPattern] -> OscPattern) -> OscPattern -> IO ())
+dirtSetters getNow = do ds <- dirtState
+                        return (setter ds, transition getNow ds)
diff --git a/Sound/Tidal/Utils.hs b/Sound/Tidal/Utils.hs
--- a/Sound/Tidal/Utils.hs
+++ b/Sound/Tidal/Utils.hs
@@ -63,3 +63,6 @@
 mergelists xs     []     = xs
 mergelists []     ys     = ys
 mergelists (x:xs) (y:ys) = x : y : mergelists xs ys
+
+(!!!) :: [a] -> Int -> a
+(!!!) xs n = xs !! (n `mod` length xs)
diff --git a/tidal.cabal b/tidal.cabal
--- a/tidal.cabal
+++ b/tidal.cabal
@@ -1,5 +1,5 @@
 name:                tidal
-version:         0.5.3
+version:             0.6
 synopsis:            Pattern language for improvised music
 -- description:         
 homepage:            http://tidal.lurk.org/
@@ -28,5 +28,7 @@
                        Sound.Tidal.Context
                        Sound.Tidal.Utils
                        Sound.Tidal.SuperCollider
+                       Sound.Tidal.Params
+                       Sound.Tidal.Transition
 
   Build-depends: base < 5, process, parsec, hosc > 0.13, hashable, colour, containers, time, websockets > 0.8, text, mtl >=2.1, transformers, mersenne-random-pure64,binary, bytestring, hmt
