diff --git a/BootTidal.hs b/BootTidal.hs
--- a/BootTidal.hs
+++ b/BootTidal.hs
@@ -19,6 +19,7 @@
     mute = streamMute tidal
     unmute = streamUnmute tidal
     unmuteAll = streamUnmuteAll tidal
+    unsoloAll = streamUnsoloAll tidal
     solo = streamSolo tidal
     unsolo = streamUnsolo tidal
     once = streamOnce tidal
diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,10 @@
 # TidalCycles log of changes
 
+## 1.7.4 - Symonds Yat b
+   * Fixes for bipolar waveforms (sine2, etc) @mindofmatthew
+   * More playback controls for OSC API @mindofmatthew
+   * Disable bus variants for MIDI controls @mindofmatthew
+
 ## 1.7.3 - Symonds Yat
    * Signed ratio shorthands now supported @ndr_brt
    * OSC API - mute/unmute stream @mindofmatthew
diff --git a/src/Sound/Tidal/Core.hs b/src/Sound/Tidal/Core.hs
--- a/src/Sound/Tidal/Core.hs
+++ b/src/Sound/Tidal/Core.hs
@@ -62,7 +62,7 @@
 -- following a cosine with frequency of one cycle, and amplitude from
 -- -1 to 1. Equivalent to `0.25 ~> sine2`.
 cosine2 :: Fractional a => Pattern a
-cosine2 = 0.25 `rotR` sine
+cosine2 = 0.25 `rotR` sine2
 
 -- | @saw@ - unipolar ascending sawtooth wave. A pattern of continuous values
 -- following a sawtooth with frequency of one cycle, and amplitude from
@@ -82,7 +82,7 @@
 
 -- | @isaw2@ like @saw2@, but a descending (inverse) sawtooth.
 isaw2 :: (Fractional a, Real a) => Pattern a
-isaw2 = (1-) <$> saw
+isaw2 = (*(-1)) <$> saw2
 
 -- | @tri@ - unipolar triangle wave. A pattern of continuous values
 -- following a triangle wave with frequency of one cycle, and amplitude from
@@ -94,7 +94,7 @@
 -- following a triangle wave with frequency of one cycle, and amplitude from
 -- -1 to 1.
 tri2 :: (Fractional a, Real a) => Pattern a
-tri2 = fastAppend saw isaw
+tri2 = fastAppend saw2 isaw2
 
 -- | @square@ - unipolar square wave. A pattern of continuous values
 -- following a square wave with frequency of one cycle, and amplitude from
@@ -343,9 +343,9 @@
 density = fast
 
 _fast :: Time -> Pattern a -> Pattern a
-_fast r p | r == 0 = silence
-          | r < 0 = rev $ _fast (negate r) p
-          | otherwise = withResultTime (/ r) $ withQueryTime (* r) p
+_fast rate pat | rate == 0 = silence
+               | rate < 0 = rev $ _fast (negate rate) pat
+               | otherwise = withResultTime (/ rate) $ withQueryTime (* rate) pat
 
 -- | Slow down a pattern by the given time pattern
 slow :: Pattern Time -> Pattern a -> Pattern a
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
@@ -91,13 +91,16 @@
 pStateListF :: String -> String -> [Double] -> ControlPattern
 pStateListF name sName = pStateList name sName . map VF
 
+pStateListS :: String -> String -> [String] -> ControlPattern
+pStateListS name sName = pStateList name sName . map VS
+
 -- | Grouped params
 
 sound :: Pattern String -> ControlPattern
 sound = grp [mS "s", mF "n"]
 
-sTake :: String -> [Double] -> ControlPattern
-sTake name xs = pStateListF "s" name xs
+sTake :: String -> [String] -> ControlPattern
+sTake name xs = pStateListS "s" name xs
 
 cc :: Pattern String -> ControlPattern
 cc = grp [mF "ccn", mF "ccv"]
diff --git a/src/Sound/Tidal/Pattern.hs b/src/Sound/Tidal/Pattern.hs
--- a/src/Sound/Tidal/Pattern.hs
+++ b/src/Sound/Tidal/Pattern.hs
@@ -330,11 +330,11 @@
 
 -- | Apply a function to the timespan of the query
 withQueryArc :: (Arc -> Arc) -> Pattern a -> Pattern a
-withQueryArc f p = p {query = query p . (\(State a m) -> State (f a) m)}
+withQueryArc f pat = pat {query = query pat . (\(State a m) -> State (f a) m)}
 
 -- | Apply a function to the time (both start and end) of the query
 withQueryTime :: (Time -> Time) -> Pattern a -> Pattern a
-withQueryTime f = withQueryArc (\(Arc s e) -> Arc (f s) (f e))
+withQueryTime f pat = withQueryArc (\(Arc s e) -> Arc (f s) (f e)) pat
 
 -- | @withEvent f p@ returns a new @Pattern@ with each event mapped over
 -- function @f@.
@@ -482,7 +482,6 @@
         f (Context xs) = Context $ map (\((bx,by), (ex,ey)) -> ((bx+column,by+line), (ex+column,ey+line))) xs
 
 -- ** Events
-
 
 -- | Some context for an event, currently just position within sourcecode
 data Context = Context {contextPosition :: [((Int, Int), (Int, Int))]}
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
@@ -587,6 +587,9 @@
 streamUnmuteAll :: Stream -> IO ()
 streamUnmuteAll s = modifyMVar_ (sPMapMV s) $ return . fmap (\x -> x {mute = False})
 
+streamUnsoloAll :: Stream -> IO ()
+streamUnsoloAll s = modifyMVar_ (sPMapMV s) $ return . fmap (\x -> x {solo = False})
+
 streamAll :: Stream -> (ControlPattern -> ControlPattern) -> IO ()
 streamAll s f = do _ <- swapMVar (sGlobalFMV s) f
                    return ()
@@ -667,10 +670,22 @@
           = streamUnmute stream k
         act (O.Message "/unmute" (O.ASCII_String k:[]))
           = streamUnmute stream (O.ascii_to_string k)
+        act (O.Message "/solo" (O.Int32 k:[]))
+          = streamSolo stream k
+        act (O.Message "/solo" (O.ASCII_String k:[]))
+          = streamSolo stream (O.ascii_to_string k)
+        act (O.Message "/unsolo" (O.Int32 k:[]))
+          = streamUnsolo stream k
+        act (O.Message "/unsolo" (O.ASCII_String k:[]))
+          = streamUnsolo stream (O.ascii_to_string k)
         act (O.Message "/muteAll" [])
           = streamMuteAll stream
         act (O.Message "/unmuteAll" [])
           = streamUnmuteAll stream
+        act (O.Message "/unsoloAll" [])
+          = streamUnsoloAll stream
+        act (O.Message "/hush" [])
+          = streamHush stream
         act m = hPutStrLn stderr $ "Unhandled OSC: " ++ show m
         add :: String -> Value -> IO ()
         add k v = do sMap <- takeMVar (sStateMV stream)
diff --git a/src/Sound/Tidal/Version.hs b/src/Sound/Tidal/Version.hs
--- a/src/Sound/Tidal/Version.hs
+++ b/src/Sound/Tidal/Version.hs
@@ -21,7 +21,7 @@
 -}
 
 tidal_version :: String
-tidal_version = "1.7.3"
+tidal_version = "1.7.4"
 
 tidal_status :: IO ()
 tidal_status = tidal_status_string >>= putStrLn 
diff --git a/test/Sound/Tidal/CoreTest.hs b/test/Sound/Tidal/CoreTest.hs
--- a/test/Sound/Tidal/CoreTest.hs
+++ b/test/Sound/Tidal/CoreTest.hs
@@ -4,6 +4,7 @@
 
 import Data.List (sort)
 import Data.Ratio
+import qualified Data.Map as Map
 import Sound.Tidal.Context
 import Test.Microspec
 import TestUtils
@@ -12,6 +13,29 @@
 run :: Microspec ()
 run =
   describe "Sound.Tidal.Core" $ do
+    describe "Elemental patterns" $ do
+      let sampleOf :: Pattern Double -> Rational -> Double
+          sampleOf pat t = (value . head) $ query pat (State (Arc t t) Map.empty)
+      describe "are in range [0, 1]" $ do
+        let inNormalRange pat t = (y >= 0) && (y <= 1)
+              where y = sampleOf pat t
+        it "sine" $ inNormalRange sine
+        it "cosine" $ inNormalRange cosine
+        it "saw" $ inNormalRange saw
+        it "isaw" $ inNormalRange isaw
+        it "tri" $ inNormalRange tri
+        it "square" $ inNormalRange square
+      describe "have correctly-scaled bipolar variants" $ do
+        let areCorrectlyScaled pat pat2 t = (y * 2 - 1) ~== y2
+              where y = sampleOf pat t
+                    y2 = sampleOf pat2 t
+        it "sine" $ areCorrectlyScaled sine sine2
+        it "cosine" $ areCorrectlyScaled cosine cosine2
+        it "saw" $ areCorrectlyScaled saw saw2
+        it "isaw" $ areCorrectlyScaled isaw isaw2
+        it "tri" $ areCorrectlyScaled tri tri2
+        it "square" $ areCorrectlyScaled square square2
+    
     describe "append" $
       it "can switch between the cycles from two pures" $ do
         queryArc (append (pure "a") (pure "b")) (Arc 0 5)
@@ -23,6 +47,7 @@
               (((3, 4), (3, 4)), "b"),
               (((4, 5), (4, 5)), "a")
             ]
+
     describe "cat" $ do
       it "can switch between the cycles from three pures" $ do
         queryArc (cat [pure "a", pure "b", pure "c"]) (Arc 0 5)
@@ -42,6 +67,7 @@
               (Arc 0 10)
               (rev $ cat [a, b, c])
               (cat [rev a, rev b, rev c])
+
     describe "fastCat" $ do
       it "can switch between the cycles from three pures inside one cycle" $ do
         it "1" $
diff --git a/test/TestUtils.hs b/test/TestUtils.hs
--- a/test/TestUtils.hs
+++ b/test/TestUtils.hs
@@ -15,6 +15,9 @@
 class TolerantEq a where
    (~==) :: a -> a -> Bool
 
+instance TolerantEq Double where
+  a ~== b = abs (a - b) < 0.000001
+
 instance TolerantEq Value where
          (VS a) ~== (VS b) = a == b
          (VI a) ~== (VI b) = a == b
diff --git a/tidal.cabal b/tidal.cabal
--- a/tidal.cabal
+++ b/tidal.cabal
@@ -1,7 +1,7 @@
 name:                tidal
-version:             1.7.3
+version:             1.7.4
 synopsis:            Pattern language for improvised music
--- description:
+description:         Tidal is a domain specific language for live coding patterns.
 homepage:            http://tidalcycles.org/
 license:             GPL-3
 license-file:        LICENSE
@@ -16,8 +16,6 @@
 data-files:          BootTidal.hs
 
 Extra-source-files: README.md CHANGELOG.md tidal.el
-
-Description: Tidal is a domain specific language for live coding pattern.
 
 library
   ghc-options: -Wall
