diff --git a/src/Sound/Tidal/Control.hs b/src/Sound/Tidal/Control.hs
--- a/src/Sound/Tidal/Control.hs
+++ b/src/Sound/Tidal/Control.hs
@@ -358,6 +358,15 @@
 stut' :: Pattern Int -> Pattern Time -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
 stut' = stutWith
 
+-- | Turns a pattern of seconds into a pattern of (rational) cycle durations
+sec :: Fractional a => Pattern a -> Pattern a
+sec p = (realToFrac <$> cF 1 "_cps") *| p
+
+-- | Turns a pattern of milliseconds into a pattern of (rational)
+-- cycle durations, according to the current cps.
+msec :: Fractional a => Pattern a -> Pattern a
+msec p = ((realToFrac . (/1000)) <$> cF 1 "_cps") *| p
+
 cI :: String -> Pattern Int
 cI s = Pattern Analog $ \(State a m) -> maybe [] (f a) $ Map.lookup s m
   where f a (VI v) = [Event a a v]
diff --git a/src/Sound/Tidal/Params.hs b/src/Sound/Tidal/Params.hs
--- a/src/Sound/Tidal/Params.hs
+++ b/src/Sound/Tidal/Params.hs
@@ -147,6 +147,11 @@
 delaytime = pF "delaytime"
 detune :: Pattern Double -> ControlPattern
 detune = pF "detune"
+
+-- DJ filter
+djf :: Pattern Double -> ControlPattern
+djf = pF "djf"
+
 -- | when set to `1` will disable all reverb for this pattern. See `room` and `size` for more information about reverb.
 dry :: Pattern Double -> ControlPattern
 dry = pF "dry"
diff --git a/src/Sound/Tidal/Scales.hs b/src/Sound/Tidal/Scales.hs
--- a/src/Sound/Tidal/Scales.hs
+++ b/src/Sound/Tidal/Scales.hs
@@ -170,7 +170,10 @@
 chromatic = [0,1,2,3,4,5,6,7,8,9,10,11]
 
 scale :: Num a => Pattern String -> Pattern Int -> Pattern a
-scale sp p = (\n scaleName -> noteInScale (fromMaybe [0] $ lookup scaleName scaleTable) n) <$> p <*> sp
+scale = getScale scaleTable
+
+getScale :: Num a => [(String, [a])] -> Pattern String -> Pattern Int -> Pattern a
+getScale table sp p = (\n scaleName -> noteInScale (fromMaybe [0] $ lookup scaleName table) n) <$> p <*> sp
   where octave s x = x `div` length s
         noteInScale s x = (s !!! x) + fromIntegral (12 * octave s x)
 
diff --git a/src/Sound/Tidal/Stream.hs b/src/Sound/Tidal/Stream.hs
--- a/src/Sound/Tidal/Stream.hs
+++ b/src/Sound/Tidal/Stream.hs
@@ -176,7 +176,8 @@
      cMap <- readMVar cMapMV
      tempo <- readMVar tempoMV
      now <- O.time
-     let es = filter eventHasOnset $ query p (State {arc = T.nowArc st, controls = cMap})
+     let cMap' = Map.insert "_cps" (VF $ T.cps tempo) cMap
+         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 target = catMaybes $ map (\e -> do m <- toMessage (on e + latency target) target tempo e
@@ -270,8 +271,9 @@
                                 T.paused = False,
                                 T.nudged = 0
                                }
+           cMap' = Map.insert "_cps" (VF $ T.cps tempo) cMap
            es = filter eventHasOnset $ query p (State {arc = (Arc 0 1),
-                                                       controls = cMap
+                                                       controls = cMap'
                                                       }
                                                )
            at e = sched fakeTempo $ start $ whole e
diff --git a/src/Sound/Tidal/Tempo.hs b/src/Sound/Tidal/Tempo.hs
--- a/src/Sound/Tidal/Tempo.hs
+++ b/src/Sound/Tidal/Tempo.hs
@@ -96,7 +96,9 @@
   where loop tempoMV st =
           do -- putStrLn $ show $ nowArc ts
              tempo <- readMVar tempoMV               
+             t <- O.time
              let frameTimespan = cFrameTimespan config
+                 delta = logicalNow - t
                  -- 'now' comes from clock ticks, nothing to do with cycles
                  logicalT ticks' = start st + fromIntegral ticks' * frameTimespan
                  logicalNow = logicalT $ ticks st + 1
@@ -108,8 +110,7 @@
                  st' = st {ticks = ticks st + 1, nowArc = P.Arc s e,
                            starting = not (synched tempo)
                           }
-             t <- O.time
-             when (t < logicalNow) $ threadDelay (floor $ (logicalNow - t) * 1000000)
+             when (t < logicalNow) $ threadDelay (floor $ delta * 1000000)
              callback tempoMV st'
              loop tempoMV st'
 
@@ -120,7 +121,7 @@
          hostname = cTempoAddr config
          port = cTempoPort config
      (remote_addr:_) <- N.getAddrInfo Nothing (Just hostname) Nothing
-     local <- O.udpServer "127.0.0.1" tempoClientPort
+     local <- O.udpServer "0.0.0.0" tempoClientPort
      let (N.SockAddrInet _ a) = N.addrAddress remote_addr
          remote = N.SockAddrInet (fromIntegral port) a
          t = defaultTempo s local remote
diff --git a/src/Sound/Tidal/UI.hs b/src/Sound/Tidal/UI.hs
--- a/src/Sound/Tidal/UI.hs
+++ b/src/Sound/Tidal/UI.hs
@@ -11,7 +11,7 @@
 import qualified Data.Vector as V
 import           Data.Word (Word32)
 import           Data.Ratio ((%),numerator,denominator)
-import           Data.List (sort, sortOn, findIndices, elemIndex, groupBy, transpose)
+import           Data.List (sort, sortOn, findIndices, elemIndex, groupBy, transpose, intercalate)
 import           Data.Maybe (isJust, fromJust, fromMaybe, mapMaybe)
 import qualified Data.Text as T
 import qualified Data.Map.Strict as Map
@@ -1187,6 +1187,7 @@
 `toScale' 24 [0,4,7,10,14,17] (run 8)` turns into `"0 4 7 10 14 17 24 28"`
 -}
 toScale' :: Num a => Int -> [a] -> Pattern Int -> Pattern a
+toScale' _ [] = const silence
 toScale' o s = fmap noteInScale
   where octave x = x `div` length s
         noteInScale x = (s !!! x) + fromIntegral (o * octave x)
@@ -1737,3 +1738,16 @@
 -}
 soak ::  Int -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
 soak depth f pattern = cat $ take depth $ iterate f pattern
+
+deconstruct :: Int -> Pattern String -> String
+deconstruct n p = intercalate " " $ map showStep $ toList n p
+  where 
+    showStep :: [String] -> String
+    showStep [] = "~"
+    showStep [x] = x
+    showStep xs = "[" ++ (intercalate ", " xs) ++ "]"
+    toList :: Int -> Pattern a -> [[a]]
+    toList n pat = map (\(s,e) -> map value $ queryArc (_segment n' pat) (Arc s e)) arcs
+      where breaks = [0, (1/n') ..]
+            arcs = zip (take n breaks) (drop 1 breaks)
+            n' = fromIntegral n
diff --git a/tidal.cabal b/tidal.cabal
--- a/tidal.cabal
+++ b/tidal.cabal
@@ -1,5 +1,5 @@
 name:                tidal
-version:             1.0.8
+version:             1.0.9
 synopsis:            Pattern language for improvised music
 -- description:
 homepage:            http://tidalcycles.org/
@@ -58,7 +58,7 @@
     , vector < 0.13
     , bifunctors < 5.6
     , transformers < 0.5.7
-    , template-haskell >= 2.10.0.0 && < 3
+    , template-haskell >= 2.10.0.0 && < 2.15
 
   if !impl(ghc >= 8.4.1)
     build-depends: semigroups == 0.18.*
