diff --git a/Help/Server/b_alloc.help.lhs b/Help/Server/b_alloc.help.lhs
--- a/Help/Server/b_alloc.help.lhs
+++ b/Help/Server/b_alloc.help.lhs
@@ -1,4 +1,4 @@
-    Sound.SC3.Server.Help.viewServerHelp "/b_alloc"
+    Sound.SC3.Lang.Help.viewServerHelp "/b_alloc"
 
 Buffer indices are not restricted by the number of available buffers
 at the server.  Below allocates a buffer at index 2 ^ 15.  Note the
diff --git a/Help/Server/b_allocRead.help.lhs b/Help/Server/b_allocRead.help.lhs
--- a/Help/Server/b_allocRead.help.lhs
+++ b/Help/Server/b_allocRead.help.lhs
@@ -1,13 +1,14 @@
-    Sound.SC3.Server.Help.viewServerHelp "/b_allocRead"
+    Sound.SC3.Lang.Help.viewServerHelp "/b_allocRead"
 
 > import Sound.OSC {- hosc -}
 > import Sound.SC3 {- hsc3 -}
 
 Read a large audio file into a buffer.
 
-> fn = "/home/rohan/data/audio/xenakis/jonchaies.wav"
+> f_00 = "/home/rohan/data/audio/xenakis/jonchaies.wav"
+> m_00 = b_allocRead 0 f_00 0 0
 
-    withSC3 (async (b_allocRead 0 fn 0 0))
+    withSC3 (async m_00)
 
 Audio data is loaded in IEEE 32-bit form, so in-memory storage can be
 greater than on-disk storage.
@@ -25,20 +26,20 @@
 
 Query buffer.
 
-> q0 :: Connection UDP ()
-> q0 = do
->      sendMessage (b_query [0])
->      r <- waitReply "/b_info"
->      liftIO (print r)
+> q_00 :: Connection UDP ()
+> q_00 = do
+>   sendMessage (b_query [0])
+>   r <- waitReply "/b_info"
+>   liftIO (print r)
 
-    withSC3 q0
+    withSC3 q_00
 
 Play buffer.
 
-> g0 =
->     let n = 257
->         s = bufRateScale KR n
->     in playBuf 1 AR n s 1 0 NoLoop RemoveSynth
+> g_00 =
+>   let bufnum = 257
+>       s = bufRateScale KR bufnum
+>   in playBuf 1 AR bufnum s 1 0 NoLoop RemoveSynth
 
 Re-read file into buffer with the same identifier.  The existing
 buffer is freed but not before further memory is allocated,
diff --git a/Help/Server/b_allocReadChannel.help.lhs b/Help/Server/b_allocReadChannel.help.lhs
--- a/Help/Server/b_allocReadChannel.help.lhs
+++ b/Help/Server/b_allocReadChannel.help.lhs
@@ -1,29 +1,33 @@
-> Sound.SC3.Server.Help.viewServerHelp "/b_allocReadChannel"
+    Sound.SC3.Lang.Help.viewServerHelp "/b_allocReadChannel"
 
-> import Sound.SC3
+> import Data.List {- base -}
+> import Data.List.Split {- split -}
+> import Sound.SC3 {- hsc3 -}
 
-Read an audio file with many channels (here 2000)
+Read an audio file with many channels (here 1024)
 
-> let fn = "/home/rohan/sw/hsc3-sf/au/mc-12-2000.au"
+> fn_00 = "/home/rohan/sw/hsc3-sf/data/au/mc-10-1024.au"
 
-> withSC3 (async (b_allocRead 0 fn 0 0))
+> m_00 = b_allocRead 0 fn_00 0 0
 
+    > withSC3 (async_ m_00)
+
 Query buffer
 
-> withSC3 (b_query1_unpack 0)
+    > withSC3 (b_query1_unpack 0)
 
 Read only specified channels
 
-> withSC3 (async (b_allocReadChannel 0 fn 0 0 [0..1023]))
+> m_01 = b_allocReadChannel 0 fn_00 0 0 [0 .. 7]
 
+    > withSC3 (async_ m_01)
+
 Query buffer
 
-> withSC3 (b_query1_unpack 0)
+    > withSC3 (b_query1_unpack 0)
 
 Examine buffer
 
-> import Data.List {- base -}
-> import Data.List.Split {- split -}
-> let (nf,nc) = (12,1024)
-> d <- withSC3 (b_getn1_data_segment 128 0 (0,nf * nc))
-> (putStrLn . unlines . transpose . chunksOf nc . map (\n -> if n > 0 then '1' else '0')) d
+    > let (nf,nc) = (10,8)
+    > d <- withSC3 (b_getn1_data_segment 128 0 (0,nf * nc))
+    > (putStrLn . unlines . transpose . chunksOf nc . map (\n -> if n > 0 then '1' else '0')) d
diff --git a/Help/Server/b_close.help.lhs b/Help/Server/b_close.help.lhs
--- a/Help/Server/b_close.help.lhs
+++ b/Help/Server/b_close.help.lhs
@@ -1,1 +1,1 @@
-> Sound.SC3.Server.Help.viewServerHelp "/b_close"
+    Sound.SC3.Lang.Help.viewServerHelp "/b_close"
diff --git a/Help/Server/b_fill.help.lhs b/Help/Server/b_fill.help.lhs
--- a/Help/Server/b_fill.help.lhs
+++ b/Help/Server/b_fill.help.lhs
@@ -1,1 +1,1 @@
-> Sound.SC3.Server.Help.viewServerHelp "/b_fill"
+     Sound.SC3.Lang.Help.viewServerHelp "/b_fill"
diff --git a/Help/Server/b_free.help.lhs b/Help/Server/b_free.help.lhs
--- a/Help/Server/b_free.help.lhs
+++ b/Help/Server/b_free.help.lhs
@@ -1,4 +1,4 @@
-    Sound.SC3.Server.Help.viewServerHelp "/b_free"
+    Sound.SC3.Lang.Help.viewServerHelp "/b_free"
 
 > import Sound.SC3 {- hsc3 -}
 
diff --git a/Help/Server/b_gen.help.lhs b/Help/Server/b_gen.help.lhs
--- a/Help/Server/b_gen.help.lhs
+++ b/Help/Server/b_gen.help.lhs
@@ -1,1 +1,1 @@
-> Sound.SC3.Server.Help.viewServerHelp "/b_gen"
+    Sound.SC3.Lang.Help.viewServerHelp "/b_gen"
diff --git a/Help/Server/b_get.help.lhs b/Help/Server/b_get.help.lhs
--- a/Help/Server/b_get.help.lhs
+++ b/Help/Server/b_get.help.lhs
@@ -1,1 +1,1 @@
-> Sound.SC3.Server.Help.viewServerHelp "/b_get"
+    Sound.SC3.Lang.Help.viewServerHelp "/b_get"
diff --git a/Help/Server/b_getn.help.lhs b/Help/Server/b_getn.help.lhs
--- a/Help/Server/b_getn.help.lhs
+++ b/Help/Server/b_getn.help.lhs
@@ -1,4 +1,4 @@
-> Sound.SC3.Server.Help.viewServerHelp "/b_getn"
+    Sound.SC3.Lang.Help.viewServerHelp "/b_getn"
 
 > import Sound.OSC {- hosc -}
 > import Sound.SC3 {- hsc3 -}
@@ -6,27 +6,40 @@
 
 Allocate and generate wavetable buffer (256 frames)
 
-> withSC3 (do {_ <- async (b_alloc 0 256 1)
->             ;let f = [Normalise,Clear]
->              in send (b_gen_sine1 0 f [1,1/2,1/3,1/4,1/5])})
+> x_00 :: DuplexOSC m => m ()
+> x_00 = do
+>   async_ (b_alloc 0 256 1)
+>   let f = [Normalise,Clear]
+>   sendMessage (b_gen_sine1 0 f [1,1/2,1/3,1/4,1/5])
 
+    > withSC3 x_00
+
 Run simple read...
 
-> d0 <- withSC3 (b_getn1_data 0 (0,255))
+    > d0 <- withSC3 (b_getn1_data 0 (0,255))
 
 and draw buffer
 
-> plotTable [d0]
+    > plotTable [d0]
 
 Load sound file
 
-> let fn = "/home/rohan/data/audio/pf-c5.aif"
-> in withSC3 (async (b_allocRead 1 fn 0 0))
+> fn_00 = "/tmp/dx7.wav"
 
-Run segmented read (2^15 frames in 1024 frame segments)...
+> m_00 = b_allocRead 1 fn_00 0 0
 
-> d1 <- withSC3 (b_getn1_data_segment 1024 1 (0,2^15))
+    > withSC3 (async_ m_00)
 
+Run segmented read (n-frames of data in m-frame segments)...
+
+> x_01 :: DuplexOSC m => m [Double]
+> x_01 = do
+>   let m = 155
+>       n = m * 3
+>   b_getn1_data_segment m 1 (0,n)
+
+    > d1 <- withSC3 x_01
+
 and draw buffer
 
-> plotTable [d1]
+    > plotImpulses [d1]
diff --git a/Help/Server/b_query.help.lhs b/Help/Server/b_query.help.lhs
--- a/Help/Server/b_query.help.lhs
+++ b/Help/Server/b_query.help.lhs
@@ -1,4 +1,4 @@
-    Sound.SC3.Server.Help.viewServerHelp "/b_query"
+    Sound.SC3.Lang.Help.viewServerHelp "/b_query"
 
 > import Sound.OSC {- hosc -}
 > import Sound.SC3 {- hsc3 -}
diff --git a/Help/Server/b_read.help.lhs b/Help/Server/b_read.help.lhs
--- a/Help/Server/b_read.help.lhs
+++ b/Help/Server/b_read.help.lhs
@@ -1,1 +1,1 @@
-> Sound.SC3.Server.Help.viewServerHelp "/b_read"
+    Sound.SC3.Lang.Help.viewServerHelp "/b_read"
diff --git a/Help/Server/b_readChannel.help.lhs b/Help/Server/b_readChannel.help.lhs
--- a/Help/Server/b_readChannel.help.lhs
+++ b/Help/Server/b_readChannel.help.lhs
@@ -1,1 +1,1 @@
-> Sound.SC3.Server.Help.viewServerHelp "/b_readChannel"
+    Sound.SC3.Lang.Help.viewServerHelp "/b_readChannel"
diff --git a/Help/Server/b_set.help.lhs b/Help/Server/b_set.help.lhs
--- a/Help/Server/b_set.help.lhs
+++ b/Help/Server/b_set.help.lhs
@@ -1,1 +1,1 @@
-> Sound.SC3.Server.Help.viewServerHelp "/b_set"
+    Sound.SC3.Lang.Help.viewServerHelp "/b_set"
diff --git a/Help/Server/b_setn.help.lhs b/Help/Server/b_setn.help.lhs
--- a/Help/Server/b_setn.help.lhs
+++ b/Help/Server/b_setn.help.lhs
@@ -1,1 +1,1 @@
-> Sound.SC3.Server.Help.viewServerHelp "/b_setn"
+    Sound.SC3.Lang.Help.viewServerHelp "/b_setn"
diff --git a/Help/Server/b_write.help.lhs b/Help/Server/b_write.help.lhs
--- a/Help/Server/b_write.help.lhs
+++ b/Help/Server/b_write.help.lhs
@@ -1,1 +1,1 @@
-> Sound.SC3.Server.Help.viewServerHelp "/b_write"
+    Sound.SC3.Lang.Help.viewServerHelp "/b_write"
diff --git a/Help/Server/b_zero.help.lhs b/Help/Server/b_zero.help.lhs
--- a/Help/Server/b_zero.help.lhs
+++ b/Help/Server/b_zero.help.lhs
@@ -1,1 +1,1 @@
-> Sound.SC3.Server.Help.viewServerHelp "/b_zero"
+    Sound.SC3.Lang.Help.viewServerHelp "/b_zero"
diff --git a/Help/Server/c_fill.help.lhs b/Help/Server/c_fill.help.lhs
--- a/Help/Server/c_fill.help.lhs
+++ b/Help/Server/c_fill.help.lhs
@@ -1,1 +1,1 @@
-> Sound.SC3.Server.Help.viewServerHelp "/c_fill"
+    Sound.SC3.Lang.Help.viewServerHelp "/c_fill"
diff --git a/Help/Server/c_get.help.lhs b/Help/Server/c_get.help.lhs
--- a/Help/Server/c_get.help.lhs
+++ b/Help/Server/c_get.help.lhs
@@ -1,10 +1,14 @@
-> Sound.SC3.Server.Help.viewServerHelp "/c_get"
+     Sound.SC3.Lang.Help.viewServerHelp "/c_get"
 
 > import Sound.OSC {- hosc -}
 > import Sound.SC3 {- hsc3 -}
 
-> audition (out 0 (tRand 'α' 220 2200 (dust 'β' KR 1)))
+> g_01 = out 0 (tRand 'α' 220 2200 (dust 'β' KR 1))
 
-> withSC3 (do {send (c_get [0])
->             ;r <- waitReply "/c_set"
->             ;liftIO (print r)})
+> x_01 :: Transport m => m ()
+> x_01 = do
+>   sendMessage (c_get [0])
+>   r <- waitReply "/c_set"
+>   liftIO (print r)
+
+    > withSC3 x_01
diff --git a/Help/Server/c_getn.help.lhs b/Help/Server/c_getn.help.lhs
--- a/Help/Server/c_getn.help.lhs
+++ b/Help/Server/c_getn.help.lhs
@@ -1,4 +1,4 @@
-    Sound.SC3.Server.Help.viewServerHelp "/c_getn"
+    Sound.SC3.Lang.Help.viewServerHelp "/c_getn"
 
 > import Sound.OSC {- hosc -}
 > import Sound.SC3 {- hsc3 -}
diff --git a/Help/Server/c_set.help.lhs b/Help/Server/c_set.help.lhs
--- a/Help/Server/c_set.help.lhs
+++ b/Help/Server/c_set.help.lhs
@@ -1,1 +1,1 @@
-> Sound.SC3.Server.Help.viewServerHelp "/c_set"
+    Sound.SC3.Lang.Help.viewServerHelp "/c_set"
diff --git a/Help/Server/c_setn.help.lhs b/Help/Server/c_setn.help.lhs
--- a/Help/Server/c_setn.help.lhs
+++ b/Help/Server/c_setn.help.lhs
@@ -1,1 +1,1 @@
-> Sound.SC3.Server.Help.viewServerHelp "/c_setn"
+    Sound.SC3.Lang.Help.viewServerHelp "/c_setn"
diff --git a/Help/Server/clearSched.help.lhs b/Help/Server/clearSched.help.lhs
--- a/Help/Server/clearSched.help.lhs
+++ b/Help/Server/clearSched.help.lhs
@@ -1,1 +1,1 @@
-> Sound.SC3.Server.Help.viewServerHelp "/clearSched"
+    Sound.SC3.Lang.Help.viewServerHelp "/clearSched"
diff --git a/Help/Server/d_free.help.lhs b/Help/Server/d_free.help.lhs
--- a/Help/Server/d_free.help.lhs
+++ b/Help/Server/d_free.help.lhs
@@ -1,1 +1,1 @@
-> Sound.SC3.Server.Help.viewServerHelp "/d_free"
+    Sound.SC3.Lang.Help.viewServerHelp "/d_free"
diff --git a/Help/Server/d_load.help.lhs b/Help/Server/d_load.help.lhs
--- a/Help/Server/d_load.help.lhs
+++ b/Help/Server/d_load.help.lhs
@@ -1,1 +1,1 @@
-> Sound.SC3.Server.Help.viewServerHelp "/d_load"
+    Sound.SC3.Lang.Help.viewServerHelp "/d_load"
diff --git a/Help/Server/d_loadDir.help.lhs b/Help/Server/d_loadDir.help.lhs
--- a/Help/Server/d_loadDir.help.lhs
+++ b/Help/Server/d_loadDir.help.lhs
@@ -1,1 +1,1 @@
-> Sound.SC3.Server.Help.viewServerHelp "/d_loadDir"
+    Sound.SC3.Lang.Help.viewServerHelp "/d_loadDir"
diff --git a/Help/Server/d_recv.help.lhs b/Help/Server/d_recv.help.lhs
--- a/Help/Server/d_recv.help.lhs
+++ b/Help/Server/d_recv.help.lhs
@@ -1,1 +1,1 @@
-> Sound.SC3.Server.Help.viewServerHelp "/d_recv"
+    Sound.SC3.Lang.Help.viewServerHelp "/d_recv"
diff --git a/Help/Server/dumpOSC.help.lhs b/Help/Server/dumpOSC.help.lhs
--- a/Help/Server/dumpOSC.help.lhs
+++ b/Help/Server/dumpOSC.help.lhs
@@ -1,4 +1,4 @@
-    Sound.SC3.Server.Help.viewServerHelp "/dumpOSC"
+    Sound.SC3.Lang.Help.viewServerHelp "/dumpOSC"
 
 > import Sound.OSC {- hosc -}
 > import Sound.SC3 {- hsc3 -}
diff --git a/Help/Server/g_deepFree.help.lhs b/Help/Server/g_deepFree.help.lhs
--- a/Help/Server/g_deepFree.help.lhs
+++ b/Help/Server/g_deepFree.help.lhs
@@ -1,1 +1,1 @@
-> Sound.SC3.Server.Help.viewServerHelp "/g_deepFree"
+    Sound.SC3.Lang.Help.viewServerHelp "/g_deepFree"
diff --git a/Help/Server/g_freeAll.help.lhs b/Help/Server/g_freeAll.help.lhs
--- a/Help/Server/g_freeAll.help.lhs
+++ b/Help/Server/g_freeAll.help.lhs
@@ -1,4 +1,4 @@
-    > Sound.SC3.Server.Help.viewServerHelp "/g_freeAll"
+    Sound.SC3.Lang.Help.viewServerHelp "/g_freeAll"
 
 > import Sound.OSC
 > import Sound.SC3
diff --git a/Help/Server/g_head.help.lhs b/Help/Server/g_head.help.lhs
--- a/Help/Server/g_head.help.lhs
+++ b/Help/Server/g_head.help.lhs
@@ -1,1 +1,1 @@
-> Sound.SC3.Server.Help.viewServerHelp "/g_head"
+    Sound.SC3.Lang.Help.viewServerHelp "/g_head"
diff --git a/Help/Server/g_new.help.lhs b/Help/Server/g_new.help.lhs
--- a/Help/Server/g_new.help.lhs
+++ b/Help/Server/g_new.help.lhs
@@ -1,10 +1,12 @@
-> Sound.SC3.Server.Help.viewServerHelp "/g_new"
+    Sound.SC3.Lang.Help.viewServerHelp "/g_new"
 
 The root node of the synthesiser tree is a group with ID zero.
 
 By convention there is a group with ID one at the root group, but
 this is only a convention.  We need to make the group.
 
-> import Sound.SC3
+> import Sound.SC3 {- hsc3 -}
 
-> withSC3 (send (g_new [(1,AddToTail,0)]))
+> m_01 = g_new [(1,AddToTail,0)]
+
+    > withSC3 (send m_00)
diff --git a/Help/Server/g_queryTree.help.lhs b/Help/Server/g_queryTree.help.lhs
--- a/Help/Server/g_queryTree.help.lhs
+++ b/Help/Server/g_queryTree.help.lhs
@@ -1,4 +1,4 @@
-    Sound.SC3.Server.Help.viewServerHelp "/g_queryTree"
+    Sound.SC3.Lang.Help.viewServerHelp "/g_queryTree"
 
 > import Sound.OSC {- hosc -}
 > import Sound.SC3 {- hsc3 -}
diff --git a/Help/Server/g_tail.help.lhs b/Help/Server/g_tail.help.lhs
--- a/Help/Server/g_tail.help.lhs
+++ b/Help/Server/g_tail.help.lhs
@@ -1,1 +1,1 @@
-> Sound.SC3.Server.Help.viewServerHelp "/g_tail"
+    Sound.SC3.Lang.Help.viewServerHelp "/g_tail"
diff --git a/Help/Server/n_after.help.lhs b/Help/Server/n_after.help.lhs
--- a/Help/Server/n_after.help.lhs
+++ b/Help/Server/n_after.help.lhs
@@ -1,1 +1,1 @@
-> Sound.SC3.Server.Help.viewServerHelp "/n_after"
+    Sound.SC3.Lang.Help.viewServerHelp "/n_after"
diff --git a/Help/Server/n_before.help.lhs b/Help/Server/n_before.help.lhs
--- a/Help/Server/n_before.help.lhs
+++ b/Help/Server/n_before.help.lhs
@@ -1,1 +1,1 @@
-> Sound.SC3.Server.Help.viewServerHelp "/n_before"
+    Sound.SC3.Lang.Help.viewServerHelp "/n_before"
diff --git a/Help/Server/n_fill.help.lhs b/Help/Server/n_fill.help.lhs
--- a/Help/Server/n_fill.help.lhs
+++ b/Help/Server/n_fill.help.lhs
@@ -1,1 +1,1 @@
-> Sound.SC3.Server.Help.viewServerHelp "/n_fill"
+    Sound.SC3.Lang.Help.viewServerHelp "/n_fill"
diff --git a/Help/Server/n_free.help.lhs b/Help/Server/n_free.help.lhs
--- a/Help/Server/n_free.help.lhs
+++ b/Help/Server/n_free.help.lhs
@@ -1,1 +1,1 @@
-> Sound.SC3.Server.Help.viewServerHelp "/n_free"
+    Sound.SC3.Lang.Help.viewServerHelp "/n_free"
diff --git a/Help/Server/n_map.help.lhs b/Help/Server/n_map.help.lhs
--- a/Help/Server/n_map.help.lhs
+++ b/Help/Server/n_map.help.lhs
@@ -1,1 +1,1 @@
-> Sound.SC3.Server.Help.viewServerHelp "/n_map"
+    Sound.SC3.Lang.Help.viewServerHelp "/n_map"
diff --git a/Help/Server/n_mapn.help.lhs b/Help/Server/n_mapn.help.lhs
--- a/Help/Server/n_mapn.help.lhs
+++ b/Help/Server/n_mapn.help.lhs
@@ -1,4 +1,4 @@
-    Sound.SC3.Server.Help.viewServerHelp "/n_mapn"
+    Sound.SC3.Lang.Help.viewServerHelp "/n_mapn"
 
 > import Sound.OSC {- hosc -}
 > import Sound.SC3 {- hsc3 -}
diff --git a/Help/Server/n_query.help.lhs b/Help/Server/n_query.help.lhs
--- a/Help/Server/n_query.help.lhs
+++ b/Help/Server/n_query.help.lhs
@@ -1,14 +1,21 @@
-> Sound.SC3.Server.Help.viewServerHelp "/n_query"
+    Sound.SC3.Lang.Help.viewServerHelp "/n_query"
 
 > import Sound.OSC {- hosc -}
 > import Sound.SC3 {- hsc3 -}
 
-> let d = let {f = control KR "freq" 440
->             ;o = saw AR f * 0.1}
->         in synthdef "saw" (out 0 o)
+> d_00 =
+>   let f = control KR "freq" 440
+>       o = saw AR f * 0.1
+>   in synthdef "saw" (out 0 o)
 
-> withSC3 (async (d_recv d) >> send (s_new0 "saw" 1000 AddToTail 1))
+> m_00 = s_new0 "saw" 1000 AddToTail 1
 
-> r <- withSC3 (withNotifications (send (n_query [1000]) >> waitReply "/n_info"))
+   > withSC3 (async_ (d_recv d_00) >> sendMessage m_00)
 
-> print r
+> x_01 :: Transport m => m Message
+> x_01 = withNotifications $ do
+>   sendMessage (n_query [1000])
+>   waitReply "/n_info"
+
+    > r <- withSC3 x_01
+    > print r
diff --git a/Help/Server/n_run.help.lhs b/Help/Server/n_run.help.lhs
--- a/Help/Server/n_run.help.lhs
+++ b/Help/Server/n_run.help.lhs
@@ -1,1 +1,1 @@
-> Sound.SC3.Server.Help.viewServerHelp "/n_run"
+    Sound.SC3.Lang.Help.viewServerHelp "/n_run"
diff --git a/Help/Server/n_set.help.lhs b/Help/Server/n_set.help.lhs
--- a/Help/Server/n_set.help.lhs
+++ b/Help/Server/n_set.help.lhs
@@ -1,1 +1,1 @@
-> Sound.SC3.Server.Help.viewServerHelp "/n_set"
+    Sound.SC3.Lang.Help.viewServerHelp "/n_set"
diff --git a/Help/Server/n_setn.help.lhs b/Help/Server/n_setn.help.lhs
--- a/Help/Server/n_setn.help.lhs
+++ b/Help/Server/n_setn.help.lhs
@@ -1,1 +1,5 @@
-    Sound.SC3.Server.Help.viewServerHelp "/n_setn"
+    Sound.SC3.Lang.Help.viewServerHelp "/n_setn"
+
+At some point /n_setn was broken at scsynth, it no longer behaves as specified.
+
+/n_setn only works correctly with <int> indices, and not when the index is given as a <string>.
diff --git a/Help/Server/n_trace.help.lhs b/Help/Server/n_trace.help.lhs
--- a/Help/Server/n_trace.help.lhs
+++ b/Help/Server/n_trace.help.lhs
@@ -1,4 +1,4 @@
-     > Sound.SC3.Server.Help.viewServerHelp "/n_trace"
+     Sound.SC3.Lang.Help.viewServerHelp "/n_trace"
 
 > import Sound.OSC {- hosc -}
 > import Sound.SC3 {- hsc3 -}
diff --git a/Help/Server/notify.help.lhs b/Help/Server/notify.help.lhs
--- a/Help/Server/notify.help.lhs
+++ b/Help/Server/notify.help.lhs
@@ -1,4 +1,4 @@
-     Sound.SC3.Server.Help.viewServerHelp "/notify"
+     Sound.SC3.Lang.Help.viewServerHelp "/notify"
 
 > import Sound.OSC {- hosc -}
 > import Sound.SC3 {- hsc3 -}
diff --git a/Help/Server/quit.help.lhs b/Help/Server/quit.help.lhs
--- a/Help/Server/quit.help.lhs
+++ b/Help/Server/quit.help.lhs
@@ -1,1 +1,1 @@
-> Sound.SC3.Server.Help.viewServerHelp "/quit"
+    Sound.SC3.Lang.Help.viewServerHelp "/quit"
diff --git a/Help/Server/s_get.help.lhs b/Help/Server/s_get.help.lhs
--- a/Help/Server/s_get.help.lhs
+++ b/Help/Server/s_get.help.lhs
@@ -1,1 +1,1 @@
-> Sound.SC3.Server.Help.viewServerHelp "/s_get"
+    Sound.SC3.Lang.Help.viewServerHelp "/s_get"
diff --git a/Help/Server/s_getn.help.lhs b/Help/Server/s_getn.help.lhs
--- a/Help/Server/s_getn.help.lhs
+++ b/Help/Server/s_getn.help.lhs
@@ -1,1 +1,1 @@
-> Sound.SC3.Server.Help.viewServerHelp "/s_getn"
+    Sound.SC3.Lang.Help.viewServerHelp "/s_getn"
diff --git a/Help/Server/s_new.help.lhs b/Help/Server/s_new.help.lhs
--- a/Help/Server/s_new.help.lhs
+++ b/Help/Server/s_new.help.lhs
@@ -1,1 +1,1 @@
-> Sound.SC3.Server.Help.viewServerHelp "/s_new"
+    Sound.SC3.Lang.Help.viewServerHelp "/s_new"
diff --git a/Help/Server/s_noid.help.lhs b/Help/Server/s_noid.help.lhs
--- a/Help/Server/s_noid.help.lhs
+++ b/Help/Server/s_noid.help.lhs
@@ -1,1 +1,1 @@
-> Sound.SC3.Server.Help.viewServerHelp "/s_noid"
+    Sound.SC3.Lang.Help.viewServerHelp "/s_noid"
diff --git a/Help/Server/status.help.lhs b/Help/Server/status.help.lhs
--- a/Help/Server/status.help.lhs
+++ b/Help/Server/status.help.lhs
@@ -1,4 +1,4 @@
-    Sound.SC3.Server.Help.viewServerHelp "/status"
+    Sound.SC3.Lang.Help.viewServerHelp "/status"
 
 > import Sound.SC3 {- hsc3 -}
 
diff --git a/Help/Server/sync.help.lhs b/Help/Server/sync.help.lhs
--- a/Help/Server/sync.help.lhs
+++ b/Help/Server/sync.help.lhs
@@ -1,1 +1,1 @@
-> Sound.SC3.Server.Help.viewServerHelp "/sync"
+    Sound.SC3.Lang.Help.viewServerHelp "/sync"
diff --git a/Help/Server/tr.help.lhs b/Help/Server/tr.help.lhs
--- a/Help/Server/tr.help.lhs
+++ b/Help/Server/tr.help.lhs
@@ -1,1 +1,1 @@
-> Sound.SC3.Server.Help.viewServerHelp "/tr"
+    Sound.SC3.Lang.Help.viewServerHelp "/tr"
diff --git a/Help/Server/u_cmd.help.lhs b/Help/Server/u_cmd.help.lhs
--- a/Help/Server/u_cmd.help.lhs
+++ b/Help/Server/u_cmd.help.lhs
@@ -1,1 +1,1 @@
-> Sound.SC3.Server.Help.viewServerHelp "/u_cmd"
+    Sound.SC3.Lang.Help.viewServerHelp "/u_cmd"
diff --git a/Help/UGen/abs.help.lhs b/Help/UGen/abs.help.lhs
--- a/Help/UGen/abs.help.lhs
+++ b/Help/UGen/abs.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Operator.abs"
-    > :t abs
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 = abs (syncSaw AR 100 440 * 0.1)
diff --git a/Help/UGen/absDif.help.lhs b/Help/UGen/absDif.help.lhs
--- a/Help/UGen/absDif.help.lhs
+++ b/Help/UGen/absDif.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Operator.absdif"
-    > :t absDif
-
 > import Sound.SC3 {- hsc3 -}
 
 Finding the magnitude of the difference of two values is a common operation.
diff --git a/Help/UGen/add.help.lhs b/Help/UGen/add.help.lhs
--- a/Help/UGen/add.help.lhs
+++ b/Help/UGen/add.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Operator.+"
-    > :t (+)
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 =
@@ -11,3 +8,9 @@
 DC offset.
 
 > g_02 = fSinOsc AR 440 0 * 0.1 + 0.5
+
+Optimises identity
+
+> g_03 = (sinOsc AR 440 0 + 0) * 0.1
+
+> g_04 = (0 + sinOsc AR 440 0) * 0.1
diff --git a/Help/UGen/allpassN.help.lhs b/Help/UGen/allpassN.help.lhs
--- a/Help/UGen/allpassN.help.lhs
+++ b/Help/UGen/allpassN.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "AllpassN"
-    > Sound.SC3.UGen.DB.ugenSummary "AllpassN"
-
 > import Sound.SC3 {- hsc3 -}
 
 Since the allpass delay has no audible effect as a resonator on steady
@@ -42,3 +39,12 @@
 >         d = dust 'ζ' AR 1
 >         src = decay (d * 0.5) 0.2 * n
 >     in allpassN src 0.2 0.2 3
+
+Phasing
+
+> g_06 =
+>   let i = soundIn (mce2 0 1) -- two channels of input signal
+>       f = mouseX KR 0.1 1.0 Linear 0.2 -- phaser freq
+>       e = allpassN i 0.02 (sinOsc KR f 0 * 0.01 + 0.01) 1 -- max delay of 20msec
+>   in i + e -- sum phase-shifted signal to original signal
+
diff --git a/Help/UGen/amClip.help.lhs b/Help/UGen/amClip.help.lhs
--- a/Help/UGen/amClip.help.lhs
+++ b/Help/UGen/amClip.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Operator.amclip"
-    > :t amClip
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 = amClip (whiteNoise 'α' AR) (fSinOsc KR 1 0 * 0.2)
diff --git a/Help/UGen/ampComp.help.lhs b/Help/UGen/ampComp.help.lhs
--- a/Help/UGen/ampComp.help.lhs
+++ b/Help/UGen/ampComp.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "AmpComp"
-    > Sound.SC3.UGen.DB.ugenSummary "AmpComp"
-
 > import Sound.SC3 {- hsc3 -}
 
 mouse X axis frequency control
diff --git a/Help/UGen/ampDb.help.lhs b/Help/UGen/ampDb.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/ampDb.help.lhs
@@ -0,0 +1,10 @@
+> import Sound.SC3 {- hsc3 -}
+
+    > let amp = map (2 **) [0 .. 15]
+    > let db = [0,-6 .. -90]
+    > map (round . ampDb . (/) 1) amp == db
+    > map (round . amp_to_db . (/) 1) amp == db
+    > zip amp db
+
+    > db_to_amp (-3) == 0.7079457843841379
+    > amp_to_db 0.7079457843841379 == -3
diff --git a/Help/UGen/amplitude.help.lhs b/Help/UGen/amplitude.help.lhs
--- a/Help/UGen/amplitude.help.lhs
+++ b/Help/UGen/amplitude.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Amplitude"
-    > Sound.SC3.UGen.DB.ugenSummary "Amplitude"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 =
diff --git a/Help/UGen/atan2.help.lhs b/Help/UGen/atan2.help.lhs
--- a/Help/UGen/atan2.help.lhs
+++ b/Help/UGen/atan2.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Operator.atan2"
-    > :t atan2
-
 > import Sound.SC3 {- hsc3 -}
 
 Add a pan to the hypot doppler examples by using atan2 to find the
diff --git a/Help/UGen/atari2600.help.lhs b/Help/UGen/atari2600.help.lhs
--- a/Help/UGen/atari2600.help.lhs
+++ b/Help/UGen/atari2600.help.lhs
@@ -1,35 +1,33 @@
-    Sound.SC3.UGen.Help.viewSC3Help "Atari2600"
-    Sound.SC3.UGen.DB.ugenSummary "Atari2600"
-
 > import Sound.SC3 {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.HW.External.F0 as X {- hsc3 -}
+
 > import Sound.SC3.Lang.Pattern {- hsc3-lang -}
-> import Sound.SC3.UGen.Bindings.HW.External.F0 {- hsc3 -}
 
-> gr_00 = atari2600 1 2 3 4 5 5 1
+> gr_00 = X.atari2600 1 2 3 4 5 5 1
 
-> gr_01 = atari2600 2 3 10 10 5 5 1
+> gr_01 = X.atari2600 2 3 10 10 5 5 1
 
 > gr_02 =
 >     let x = mouseX KR 0 15 Linear 0.1
 >         y = mouseY KR 0 15 Linear 0.1
->     in atari2600 x y 10 10 5 5 1
+>     in X.atari2600 x y 10 10 5 5 1
 
 > gr_03 =
 >     let x = mouseX KR 0 31 Linear 0.1
 >         y = mouseY KR 0 31 Linear 0.1
->     in atari2600 2 3 x y 5 5 1
+>     in X.atari2600 2 3 x y 5 5 1
 
 > gr_04 =
 >     let x = mouseX KR 0 15 Linear 0.1
 >         y = mouseY KR 0 15 Linear 0.1
->     in atari2600 2 3 10 10 x y 1
+>     in X.atari2600 2 3 10 10 x y 1
 
 > gr_05 =
 >     let x = mouseX KR 0 15 Linear 0.1
 >         o1 = sinOsc KR 0.35 0 * 7.5 + 7.5
 >         y = mouseY KR 0 31 Linear 0.1
 >         o2 = sinOsc KR 0.3 0 * 5.5 + 5.5
->     in atari2600 x o1 10 y o2 5 1
+>     in X.atari2600 x o1 10 y o2 5 1
 
 > ati_syn =
 >     let gate' = control KR "gate" 1
@@ -42,7 +40,7 @@
 >         pan = control KR "pan" 0
 >         e = envASR 0.01 amp 0.05 (EnvNum (-4))
 >         eg = envGen KR gate' 1 0 1 RemoveSynth e
->         z = atari2600 tone0 tone1 freq0 freq1 15 15 rate
+>         z = X.atari2600 tone0 tone1 freq0 freq1 15 15 rate
 >         o = out 0 (pan2 (z * eg) pan 1)
 >     in synthdef "atari2600" o
 
diff --git a/Help/UGen/atsNoiSynth.help.lhs b/Help/UGen/atsNoiSynth.help.lhs
--- a/Help/UGen/atsNoiSynth.help.lhs
+++ b/Help/UGen/atsNoiSynth.help.lhs
@@ -1,37 +1,43 @@
-    Sound.SC3.UGen.Help.viewSC3Help "AtsNoiSynth"
-    Sound.SC3.UGen.DB.ugenSummary "AtsNoiSynth"
-
 > import System.IO.Unsafe {- base -}
 > import Sound.SC3 {- hsc3 -}
-> import Sound.SC3.UGen.Bindings.DB.External {- hsc3 -}
-> import Sound.SC3.Data.ATS {- hsc3-data -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
 
-> ats_fn_0 = "/home/rohan/data/audio/pf-c5.4.ats"
-> ats_fn_1 = "/home/rohan/cvs/tn/tn-56/ats/metal.ats"
+> import qualified Sound.SC3.Data.ATS as ATS {- hsc3-data -}
 
+> ats_fn_0 = "/home/rohan/sw/hsc3-data/data/ats/pf-c5.4.ats"
+> ats_fn_1 = "/home/rohan/sw/hsc3-data/data/ats/metal.ats"
+
 load ATS file at scsynth
 
-    > ats_load_sc3 0 ats_fn_0
+    > ATS.ats_load_sc3 0 ats_fn_0 -- ats_fn_1
     > withSC3 (b_query1_unpack 0)
 
 read ATS header
 
-> ats_hdr_0 = unsafePerformIO (fmap ats_header (ats_read ats_fn_0))
-> ats_hdr_1 = unsafePerformIO (fmap ats_header (ats_read ats_fn_1))
+> ats_hdr_0 = unsafePerformIO (fmap ATS.ats_header (ATS.ats_read ats_fn_0))
+> ats_hdr_1 = unsafePerformIO (fmap ATS.ats_header (ATS.ats_read ats_fn_1))
 
-    > putStrLn $ ats_header_pp ats_hdr_0
-    > putStrLn $ ats_header_pp ats_hdr_1
+    > putStrLn $ ATS.ats_header_pp ats_hdr_0
+    > putStrLn $ ATS.ats_header_pp ats_hdr_1
 
-run re-synthesis
+run re-synthesis, sine & noise levels are at X and Y mouse controls
 
 > g_01 =
->     let np = constant (ats_n_partials ats_hdr_0)
->         ptr = lfSaw KR (constant (1 / ats_analysis_duration ats_hdr_0)) 1 * 0.5 + 0.5
->     in atsNoiSynth AR 0 np 0 1 ptr 1 0.1 1 0 25 0 1
+>     let numPartials = constant (ATS.ats_n_partials ats_hdr_0)
+>         dur = constant (ATS.ats_analysis_duration ats_hdr_0)
+>         filePointer = lfSaw KR (1 / dur) 1 * 0.5 + 0.5
+>         sinePct = mouseX KR 0 1 Linear 0.2
+>         noisePct = mouseY KR 0 1 Linear 0.2
+>     in X.atsNoiSynth AR 0 numPartials 0 1 filePointer sinePct noisePct 1 0 25 0 1
 
-> g_02 =
->     let x = mouseX KR 0.0 1.0 Linear 0.2
->         y = mouseY KR 0.0 1.0 Linear 0.2
->         np = constant (ats_n_partials ats_hdr_0)
->     in atsNoiSynth AR 0 np 0 1 x (1 - y) y 1 0 25 0 1
+run re-synthesis, filePointer is at X-axis, sine & noise levels are both at Y
 
+> f_02 numBands bandStart bandSkip =
+>     let numPartials = constant (ATS.ats_n_partials ats_hdr_0)
+>         filePointer = mouseX KR 0.0 1.0 Linear 0.2
+>         noisePct = mouseY KR 0.0 1.0 Linear 0.2
+>     in X.atsNoiSynth AR 0 numPartials 0 1 filePointer (1 - noisePct) noisePct 1 0 25 0 1
+
+> g_02 = f_02 25 0 1
+> g_03 = f_02 25 1 2
+> g_04 = f_02 12 12 1
diff --git a/Help/UGen/atsSynth.help.lhs b/Help/UGen/atsSynth.help.lhs
--- a/Help/UGen/atsSynth.help.lhs
+++ b/Help/UGen/atsSynth.help.lhs
@@ -1,30 +1,46 @@
-    Sound.SC3.UGen.Help.viewSC3Help "AtsSynth"
-    Sound.SC3.UGen.DB.ugenSummary "AtsSynth"
-
 > import System.IO.Unsafe {- base -}
 > import Sound.SC3 {- hsc3 -}
-> import Sound.SC3.UGen.Bindings.DB.External {- hsc3 -}
-> import Sound.SC3.Data.ATS {- hsc3-data -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
+> import qualified Sound.SC3.Data.ATS as ATS {- hsc3-data -}
 
-> ats_fn_0 = "/home/rohan/data/audio/pf-c5.4.ats"
-> ats_fn_1 = "/home/rohan/cvs/tn/tn-56/ats/metal.ats"
+> ats_fn_0 = "/home/rohan/sw/hsc3-data/data/ats/pf-c5.4.ats"
+> ats_fn_1 = "/home/rohan/sw/hsc3-data/data/ats/metal.ats"
 
-    > ats_load_sc3 0 ats_fn
+load ATS file at scsynth
+
+    > ATS.ats_load_sc3 0 ats_fn_0
     > withSC3 (b_query1_unpack 0)
 
-read file
+read ATS header
 
-> ats_hdr_0 = unsafePerformIO (fmap ats_header (ats_read ats_fn_0))
-> ats_hdr_1 = unsafePerformIO (fmap ats_header (ats_read ats_fn_1))
+> ats_hdr_0 = unsafePerformIO (fmap ATS.ats_header (ATS.ats_read ats_fn_0))
+> ats_hdr_1 = unsafePerformIO (fmap ATS.ats_header (ATS.ats_read ats_fn_1))
 
-show header
+    > putStrLn $ ATS.ats_header_pp ats_hdr_0
+    > putStrLn $ ATS.ats_header_pp ats_hdr_1
 
-    > putStrLn $ ats_header_pp ats_hdr_0
+simple re-synthesiser, ATS data is at buffer 0, X is file pointer, Y is freq multiplier
 
-simple re-synthesiser, ATS data is at buffer 0
+> g_00 =
+>   let numPartials = constant (ATS.ats_n_partials ats_hdr_0)
+>       filePointer = mouseX KR 0.0 1.0 Linear 0.2
+>       freqMul = mouseY KR 0.75 1.25 Linear 0.2
+>   in X.atsSynth AR 0 numPartials 0 1 filePointer freqMul 0
 
+> f_01 numPartials partialStart partialSkip freqMul freqAdd =
+>     let dur = constant (ATS.ats_analysis_duration ats_hdr_0)
+>         filePointer = lfSaw KR (1 / dur) 1 * 0.5 + 0.5
+>     in X.atsSynth AR 0 numPartials partialStart partialSkip filePointer freqMul freqAdd
+
+resynthesize only the top half of the partials
+
 > g_01 =
->     let x = mouseX KR 0.0 1.0 Linear 0.2
->         y = mouseY KR 0.75 1.25 Linear 0.2
->         np = constant (ats_n_partials ats_hdr_0)
->     in atsSynth AR 0 np 0 1 x y 0
+>   let np = constant (ATS.ats_n_partials ats_hdr_0)
+>   in f_01 (np / 2) (np / 2) 3 1 0
+
+> f_02 = f_01 (constant (ATS.ats_n_partials ats_hdr_0))
+
+> g_02 = f_02 0 1 1 0 -- default
+> g_03 = f_02 0 1 1.5 0 -- multiply frequencies by 1.5
+> g_04 = f_02 0 1 1 100 -- add 100 to all frequencies
+> g_05 = f_02 0 3 1 0 -- resynthesize every third partial only (partial skip)
diff --git a/Help/UGen/audioMSG.help.lhs b/Help/UGen/audioMSG.help.lhs
--- a/Help/UGen/audioMSG.help.lhs
+++ b/Help/UGen/audioMSG.help.lhs
@@ -1,10 +1,7 @@
-    Sound.SC3.UGen.Help.viewSC3Help "AudioMSG"
-    Sound.SC3.UGen.DB.ugenSummary "AudioMSG"
-
 > import Sound.SC3 {- hsc3 -}
-> import Sound.SC3.UGen.Bindings.DB.External {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
 
-> g_01 = audioMSG AR (sinOsc AR 220 0 * 0.1) (mouseX KR 0 (2 * pi) Linear 0.2)
+> g_01 = X.audioMSG AR (sinOsc AR 220 0 * 0.1) (mouseX KR 0 (2 * pi) Linear 0.2)
 
-> g_02 = audioMSG AR (soundIn 0) (mouseX KR 0 (2 * pi) Linear 0.2)
+> g_02 = X.audioMSG AR (soundIn 0) (mouseX KR 0 (2 * pi) Linear 0.2)
 
diff --git a/Help/UGen/ay.help.lhs b/Help/UGen/ay.help.lhs
--- a/Help/UGen/ay.help.lhs
+++ b/Help/UGen/ay.help.lhs
@@ -1,11 +1,10 @@
-    Sound.SC3.UGen.Help.viewSC3Help "AY"
-    Sound.SC3.UGen.DB.ugenSummary "AY"
-
 > import Sound.SC3 {- hsc3 -}
-> import Sound.SC3.UGen.Bindings.DB.External {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
 
-> g_01 = ay 1777 1666 1555 1 7 15 15 15 4 1 0
+default parameters
 
+> g_01 = X.ay 1777 1666 1555 1 7 15 15 15 4 1 0
+
 > g_02 =
 >     let tonea = mouseY KR 10 3900 Exponential 0.2
 >         toneb = mouseX KR 10 3900 Exponential 0.2
@@ -13,7 +12,7 @@
 >         vola = 14
 >         volb = 14
 >         volc = 0
->         s = ay tonea toneb 1555 1 ctl vola volb volc 4 1 0
+>         s = X.ay tonea toneb 1555 1 ctl vola volb volc 4 1 0
 >     in pan2 s 0 0.25
 
 > g_03 =
@@ -31,5 +30,5 @@
 >         volc = mk_ctl 'θ' 0 15
 >         efreq = mk_ctl 'ι' 0 4095
 >         estyle = mk_ctl 'κ' 0 15
->         s = ay tonea toneb tonec n ctl vola volb volc efreq estyle 0
+>         s = X.ay tonea toneb tonec n ctl vola volb volc efreq estyle 0
 >     in pan2 s 0 0.5
diff --git a/Help/UGen/bAllpass.help.lhs b/Help/UGen/bAllpass.help.lhs
--- a/Help/UGen/bAllpass.help.lhs
+++ b/Help/UGen/bAllpass.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "BAllPass"
-    > Sound.SC3.UGen.DB.ugenSummary "BAllPass"
-
 > import Sound.SC3 {- hsc3 -}
 > import Sound.SC3.Common.Math.Filter.BEQ {- hsc3 -}
 
diff --git a/Help/UGen/bBandPass.help.lhs b/Help/UGen/bBandPass.help.lhs
--- a/Help/UGen/bBandPass.help.lhs
+++ b/Help/UGen/bBandPass.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "BBandPass"
-    Sound.SC3.UGen.DB.ugenSummary "BBandPass"
-
 > import Sound.SC3 {- hsc3 -}
 > import Sound.SC3.Common.Math.Filter.BEQ {- hsc3 -}
 
diff --git a/Help/UGen/bBandStop.help.lhs b/Help/UGen/bBandStop.help.lhs
--- a/Help/UGen/bBandStop.help.lhs
+++ b/Help/UGen/bBandStop.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "BBandStop"
-    Sound.SC3.UGen.DB.ugenSummary "BBandStop"
-
 > import Sound.SC3 {- hsc3 -}
 > import Sound.SC3.Common.Math.Filter.BEQ {- hsc3 -}
 
diff --git a/Help/UGen/bHiPass.help.lhs b/Help/UGen/bHiPass.help.lhs
--- a/Help/UGen/bHiPass.help.lhs
+++ b/Help/UGen/bHiPass.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "BHiPass"
-    Sound.SC3.UGen.DB.ugenSummary "BHiPass"
-
 > import Sound.SC3 {- hsc3 -}
 > import Sound.SC3.Common.Math.Filter.BEQ {- hsc3 -}
 
diff --git a/Help/UGen/bHiPass4.help.lhs b/Help/UGen/bHiPass4.help.lhs
--- a/Help/UGen/bHiPass4.help.lhs
+++ b/Help/UGen/bHiPass4.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "BHiPass4"
-    > :t bHiPass4
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 =
diff --git a/Help/UGen/bHiShelf.help.lhs b/Help/UGen/bHiShelf.help.lhs
--- a/Help/UGen/bHiShelf.help.lhs
+++ b/Help/UGen/bHiShelf.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "BHiShelf"
-    Sound.SC3.UGen.DB.ugenSummary "BHiShelf"
-
 > import Sound.SC3 {- hsc3 -}
 > import Sound.SC3.Common.Math.Filter.BEQ {- hsc3 -}
 
diff --git a/Help/UGen/bLowPass.help.lhs b/Help/UGen/bLowPass.help.lhs
--- a/Help/UGen/bLowPass.help.lhs
+++ b/Help/UGen/bLowPass.help.lhs
@@ -1,7 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "BLowPass"
-    > Sound.SC3.UGen.DB.ugenSummary "BLowPass"
-    > :t bLowPassCoef
-
 > import Sound.SC3 {- hsc3 -}
 > import Sound.SC3.Common.Math.Filter.BEQ {- hsc3 -}
 
@@ -25,3 +21,6 @@
 >         rq = mouseY KR 0.1 1 Linear 0.2
 >         (a0, a1, a2, b1, b2) = bLowPassCoef sampleRate f rq
 >     in sos i a0 a1 a2 b1 b2
+
+> g_04 = bLowPass (whiteNoise 'α' AR) (xLine KR 24000 20 10 DoNothing) 1
+> g_05 = bLowPass (whiteNoise 'α' AR) 1200 (xLine KR 0.5 100 10 DoNothing)
diff --git a/Help/UGen/bLowPass4.help.lhs b/Help/UGen/bLowPass4.help.lhs
--- a/Help/UGen/bLowPass4.help.lhs
+++ b/Help/UGen/bLowPass4.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "BLowPass4"
-    > :t bLowPass4
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 =
diff --git a/Help/UGen/bLowShelf.help.lhs b/Help/UGen/bLowShelf.help.lhs
--- a/Help/UGen/bLowShelf.help.lhs
+++ b/Help/UGen/bLowShelf.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "BLowShelf"
-    Sound.SC3.UGen.DB.ugenSummary "BLowShelf"
-
 > import Sound.SC3 {- hsc3 -}
 > import Sound.SC3.Common.Math.Filter.BEQ {- hsc3 -}
 
diff --git a/Help/UGen/bMoog.help.lhs b/Help/UGen/bMoog.help.lhs
--- a/Help/UGen/bMoog.help.lhs
+++ b/Help/UGen/bMoog.help.lhs
@@ -1,8 +1,5 @@
-    Sound.SC3.UGen.Help.viewSC3Help "BMoog"
-    Sound.SC3.UGen.DB.ugenSummary "BMoog"
-
 > import Sound.SC3 {- hsc3 -}
-> import Sound.SC3.UGen.Bindings.DB.External {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
 
 > f_01 md =
 >   let dup x = mce2 x x
@@ -10,15 +7,12 @@
 >       o = dup (lfSaw AR (mce2 (x * 0.99) (x * 1.01)) 0 * 0.1)
 >       cf = sinOsc KR (sinOsc KR 0.1 0) (1.5 * pi) * 1550 + 1800
 >       y = mouseY KR 1 0 Linear 0.2
->       sig = bMoog o cf y md 0.95
+>       sig = X.bMoog o cf y md 0.95
 >   in (combN sig 0.5 (mce2 0.4 0.35) 2 * 0.4) + (sig * 0.5)
 
 modes are: 0 = lowpass, 1 = highpass, 2 = bandpass
 
 > g_01 = f_01 0
-
 > g_02 = f_01 1
-
 > g_03 = f_01 2
-
 > g_04 = f_01 (lfSaw KR 1 0 * 3)
diff --git a/Help/UGen/bPeakEQ.help.lhs b/Help/UGen/bPeakEQ.help.lhs
--- a/Help/UGen/bPeakEQ.help.lhs
+++ b/Help/UGen/bPeakEQ.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "BPeakEQ"
-    Sound.SC3.UGen.DB.ugenSummary "BPeakEQ"
-
 > import Sound.SC3 {- hsc3 -}
 > import Sound.SC3.Common.Math.Filter.BEQ {- hsc3 -}
 
diff --git a/Help/UGen/balance2.help.lhs b/Help/UGen/balance2.help.lhs
--- a/Help/UGen/balance2.help.lhs
+++ b/Help/UGen/balance2.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "Balance2"
-    Sound.SC3.UGen.DB.ugenSummary "Balance2"
-
 > import Sound.SC3 {- hsc3 -}
 
 {Balance2.ar(LFSaw.ar(44),Pulse.ar(33),FSinOsc.kr(0.5),0.1)}.play
diff --git a/Help/UGen/beatTrack.help.lhs b/Help/UGen/beatTrack.help.lhs
--- a/Help/UGen/beatTrack.help.lhs
+++ b/Help/UGen/beatTrack.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "BeatTrack"
-    Sound.SC3.UGen.DB.ugenSummary "BeatTrack"
-
 > import Sound.SC3 {- hsc3 -}
 
     > withSC3 (async (b_alloc 10 1024 1))
diff --git a/Help/UGen/blip.help.lhs b/Help/UGen/blip.help.lhs
--- a/Help/UGen/blip.help.lhs
+++ b/Help/UGen/blip.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "Blip"
-    Sound.SC3.UGen.DB.ugenSummary "Blip"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 = blip AR 440 200 * 0.1
diff --git a/Help/UGen/blitB3.help.lhs b/Help/UGen/blitB3.help.lhs
--- a/Help/UGen/blitB3.help.lhs
+++ b/Help/UGen/blitB3.help.lhs
@@ -1,10 +1,7 @@
-    Sound.SC3.UGen.Help.viewSC3Help "BlitB3Square"
-    Sound.SC3.UGen.DB.ugenSummary "BlitB3Square"
-
 > import Sound.SC3 {- hsc3 -}
-> import Sound.SC3.UGen.Bindings.DB.External {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
 
-> g_01 = blitB3 AR (xLine KR 10000 20 10 DoNothing) * 0.2
+> g_01 = X.blitB3 AR (xLine KR 10000 20 10 DoNothing) * 0.2
 
 spot the aliasing
 
@@ -14,11 +11,11 @@
 
 > g_03 =
 >   let x = mouseX KR 20 1000 Exponential 0.2
->   in leakDC (integrator (blitB3 AR x * 0.2) 0.99) 0.995
+>   in leakDC (integrator (X.blitB3 AR x * 0.2) 0.99) 0.995
 
 sawtooth; super-saw, can integrate mix
 leaks dealt with one by one so don't accumulate
 
 > g_04 =
 >   let x = mouseX KR 1 4 Linear 0.2
->   in mix (leakDC (integrator (blitB3 AR (x * mce [220,221,223,224]) * 0.125) 0.99) 0.995)
+>   in mix (leakDC (integrator (X.blitB3 AR (x * mce [220,221,223,224]) * 0.125) 0.99) 0.995)
diff --git a/Help/UGen/blitB3Saw.help.lhs b/Help/UGen/blitB3Saw.help.lhs
--- a/Help/UGen/blitB3Saw.help.lhs
+++ b/Help/UGen/blitB3Saw.help.lhs
@@ -1,20 +1,17 @@
-    Sound.SC3.UGen.Help.viewSC3Help "BlitB3Saw"
-    Sound.SC3.UGen.DB.ugenSummary "BlitB3Saw"
-
 > import Sound.SC3 {- hsc3 -}
-> import Sound.SC3.UGen.Bindings.DB.External {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
 
 > g_01 =
 >     let f = xLine KR 1000 20 10 DoNothing
->     in blitB3Saw AR f 0.99 * 0.1
+>     in X.blitB3Saw AR f 0.99 * 0.1
 
 aliasing suddenly appears for very high frequencies
 
 > g_02 =
 >     let f = mouseX KR 10 10000 Exponential 0.2
 >         c = mouseY KR 0.01 0.99 Linear 0.2
->     in blitB3Saw AR f c * 0.1
+>     in X.blitB3Saw AR f c * 0.1
 
 comparison
 
-> g_03 = mce2 (saw AR 20) (blitB3Saw AR 20 0.99) * 0.1
+> g_03 = mce2 (saw AR 20) (X.blitB3Saw AR 20 0.99) * 0.1
diff --git a/Help/UGen/blitB3Square.help.lhs b/Help/UGen/blitB3Square.help.lhs
--- a/Help/UGen/blitB3Square.help.lhs
+++ b/Help/UGen/blitB3Square.help.lhs
@@ -1,23 +1,20 @@
-    Sound.SC3.UGen.Help.viewSC3Help "BlitB3Square"
-    Sound.SC3.UGen.DB.ugenSummary "BlitB3Square"
-
 > import Sound.SC3 {- hsc3 -}
-> import Sound.SC3.UGen.Bindings.DB.External {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
 
 > g_00 =
 >   let x = mouseX KR 20 400 Exponential 0.2
->   in blitB3Square AR x 0.99 * 0.1
+>   in X.blitB3Square AR x 0.99 * 0.1
 
 > g_01 =
 >     let f = xLine KR 1000 20 10 DoNothing
->     in blitB3Square AR f 0.99 * 0.1
+>     in X.blitB3Square AR f 0.99 * 0.1
 
 aliasing suddenly appears for very high frequencies
 
 > g_02 =
 >     let f = mouseX KR 20 10000 Exponential 0.2
 >         c = mouseY KR 0.001 0.999 Linear 0.2
->     in blitB3Square AR f c * 0.1
+>     in X.blitB3Square AR f c * 0.1
 
 difference in CPU usage (excessive wire use,-w 1024)
 
@@ -27,5 +24,5 @@
 >         o z = pan2 (sqr_osc AR (f z) * 0.1) (l z) 0.1
 >     in sum (map o [0::Int .. 99])
 
-> g_03 = f_03 (\rt f -> blitB3Square rt f 0.99)
+> g_03 = f_03 (\rt f -> X.blitB3Square rt f 0.99)
 > g_04 = f_03 (\rt f -> pulse rt f 0.5)
diff --git a/Help/UGen/blitB3Tri.help.lhs b/Help/UGen/blitB3Tri.help.lhs
--- a/Help/UGen/blitB3Tri.help.lhs
+++ b/Help/UGen/blitB3Tri.help.lhs
@@ -1,10 +1,7 @@
-    Sound.SC3.UGen.Help.viewSC3Help "BlitB3Tri"
-    Sound.SC3.UGen.DB.ugenSummary "BlitB3Tri"
-
 > import Sound.SC3 {- hsc3 -}
-> import qualified Sound.SC3.UGen.Bindings.DB.External as E {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
 
-> g_01 = E.blitB3Tri AR (xLine KR 1000 20 10 DoNothing) 0.99 0.99 * 0.1
+> g_01 = X.blitB3Tri AR (xLine KR 1000 20 10 DoNothing) 0.99 0.99 * 0.1
 
 unfortunately, aliasing returns at higher frequencies
 (over 5000Hz or so) with a vengence (very beautiful in point scope)
@@ -12,7 +9,7 @@
 > g_02 =
 >   let x = mouseX KR 20 8000 Exponential 0.2
 >       y = mouseY KR 0.001 0.99 Linear 0.2
->   in E.blitB3Tri AR x 0.99 y * 0.1
+>   in X.blitB3Tri AR x 0.99 y * 0.1
 
 more efficient, some aliasing from 3000, but not so scary over 5000
 Duller sound (less high harmonics included for lower fundamentals)
diff --git a/Help/UGen/blockSize.help.lhs b/Help/UGen/blockSize.help.lhs
--- a/Help/UGen/blockSize.help.lhs
+++ b/Help/UGen/blockSize.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "BlockSize"
-    > Sound.SC3.UGen.DB.ugenSummary "BlockSize"
-
 > import Sound.SC3 {- hsc3 -}
 
 default block size is 64 samples
diff --git a/Help/UGen/bpf.help.lhs b/Help/UGen/bpf.help.lhs
--- a/Help/UGen/bpf.help.lhs
+++ b/Help/UGen/bpf.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "BPF"
-    Sound.SC3.UGen.DB.ugenSummary "BPF"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 =
diff --git a/Help/UGen/brf.help.lhs b/Help/UGen/brf.help.lhs
--- a/Help/UGen/brf.help.lhs
+++ b/Help/UGen/brf.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "BRF"
-    Sound.SC3.UGen.DB.ugenSummary "BRF"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 =
diff --git a/Help/UGen/brownNoise.help.lhs b/Help/UGen/brownNoise.help.lhs
--- a/Help/UGen/brownNoise.help.lhs
+++ b/Help/UGen/brownNoise.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "BrownNoise"
-    Sound.SC3.UGen.DB.ugenSummary "BrownNoise"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 = brownNoise 'α' AR * 0.1
diff --git a/Help/UGen/bufAllpassC.help.lhs b/Help/UGen/bufAllpassC.help.lhs
--- a/Help/UGen/bufAllpassC.help.lhs
+++ b/Help/UGen/bufAllpassC.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "BufAllpassC"
-    > Sound.SC3.UGen.DB.ugenSummary "BufAllpassC"
-
 > import Sound.SC3 {- hsc3 -}
 
 Allocate buffer
diff --git a/Help/UGen/bufChannels.help.lhs b/Help/UGen/bufChannels.help.lhs
--- a/Help/UGen/bufChannels.help.lhs
+++ b/Help/UGen/bufChannels.help.lhs
@@ -1,2 +0,0 @@
-    Sound.SC3.UGen.Help.viewSC3Help "BufChannels"
-    Sound.SC3.UGen.DB.ugenSummary "BufChannels"
diff --git a/Help/UGen/bufCombC.help.lhs b/Help/UGen/bufCombC.help.lhs
--- a/Help/UGen/bufCombC.help.lhs
+++ b/Help/UGen/bufCombC.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "BufCombC"
-    > Sound.SC3.UGen.DB.ugenSummary "BufCombC"
-
 > import Sound.SC3 {- hsc3 -}
 
 Allocate buffer zero (required for examples below)
diff --git a/Help/UGen/bufDelayC.help.lhs b/Help/UGen/bufDelayC.help.lhs
--- a/Help/UGen/bufDelayC.help.lhs
+++ b/Help/UGen/bufDelayC.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "BufDelayC"
-    > Sound.SC3.UGen.DB.ugenSummary "BufDelayC"
-
 > import Sound.SC3 {- hsc3 -}
 
 Allocate buffer zero (required for examples below)
diff --git a/Help/UGen/bufDur.help.lhs b/Help/UGen/bufDur.help.lhs
--- a/Help/UGen/bufDur.help.lhs
+++ b/Help/UGen/bufDur.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "BufDur"
-    Sound.SC3.UGen.DB.ugenSummary "BufDur"
-
 > import Sound.SC3 {- hsc3 -}
 
 Load sound file to buffer zero (required for examples)
@@ -16,4 +13,4 @@
 > g_01 =
 >     let t = impulse AR (recip (bufDur KR 0)) 0
 >         p = sweep t (bufSampleRate KR 0)
->     in bufRdL 1 AR 0 p NoLoop
+>     in bufRd 1 AR 0 p NoLoop LinearInterpolation
diff --git a/Help/UGen/bufFrames.help.lhs b/Help/UGen/bufFrames.help.lhs
--- a/Help/UGen/bufFrames.help.lhs
+++ b/Help/UGen/bufFrames.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "BufFrames"
-    > Sound.SC3.UGen.DB.ugenSummary "BufFrames"
-
 > import Sound.SC3
 
 Load sound file to buffer zero (required for examples)
diff --git a/Help/UGen/bufRateScale.help.lhs b/Help/UGen/bufRateScale.help.lhs
--- a/Help/UGen/bufRateScale.help.lhs
+++ b/Help/UGen/bufRateScale.help.lhs
@@ -1,19 +1,24 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "BufRateScale"
-    > Sound.SC3.UGen.DB.ugenSummary "BufRateScale"
-
 > import Sound.SC3 {- hsc 3 -}
 
 Load sound file to buffer zero (required for examples)
 
-> fn_01 = "/home/rohan/data/audio/pf-c5.aif"
+> fn_01 = "/home/rohan/rd/j/2019-04-21/FAIRLIGHT/IIX/REEDS/clarmdhi.snd"
 
 > m_01 = b_allocRead 0 fn_01 0 0
 
     > withSC3 (async m_01)
 
-Read buffer at 3/4 reported sample rate.
-
-> g_01 =
->     let r = 0.75 * bufRateScale KR 0
+> f_01 m =
+>     let r = m * bufRateScale KR 0
 >         p = phasor AR 0 r 0 (bufFrames KR 0) 0
 >     in bufRdL 1 AR 0 p NoLoop
+
+> g_01 = f_01 1.0 * 0.5
+
+    > audition (sinOsc AR (midiCPS 69) 0 * 0.2)
+
+Read buffer at ~ 3/4 reported sample rate.
+
+> g_02 = f_01 (midiRatio (-5)) * 0.5
+
+    > audition (sinOsc AR (midiCPS 64) 0 * 0.2)
diff --git a/Help/UGen/bufRd.help.lhs b/Help/UGen/bufRd.help.lhs
--- a/Help/UGen/bufRd.help.lhs
+++ b/Help/UGen/bufRd.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "BufRd"
-    > Sound.SC3.UGen.DB.ugenSummary "BufRd"
-
 > import Sound.SC3 {- hsc3 -}
 
 Load sound file to buffer zero (required for examples)
diff --git a/Help/UGen/bufSampleRate.help.lhs b/Help/UGen/bufSampleRate.help.lhs
--- a/Help/UGen/bufSampleRate.help.lhs
+++ b/Help/UGen/bufSampleRate.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "BufSampleRate"
-    > Sound.SC3.UGen.DB.ugenSummary "BufSampleRate"
-
 > import Sound.SC3 {- hsc3 -}
 
 Load sound file to buffer zero (required for examples)
diff --git a/Help/UGen/bufWr.help.lhs b/Help/UGen/bufWr.help.lhs
--- a/Help/UGen/bufWr.help.lhs
+++ b/Help/UGen/bufWr.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "BufWr"
-    > Sound.SC3.UGen.DB.ugenSummary "BufWr"
-
 > import Sound.SC3 {- hsc3 -}
 
 allocate a buffer (id = 0) for writing into
diff --git a/Help/UGen/cOsc.help.lhs b/Help/UGen/cOsc.help.lhs
--- a/Help/UGen/cOsc.help.lhs
+++ b/Help/UGen/cOsc.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "COsc"
-    > Sound.SC3.UGen.DB.ugenSummary "COsc"
-
 > import Sound.SC3 {- hsc3 -}
 
 Allocate and fill buffer.
diff --git a/Help/UGen/changed.help.lhs b/Help/UGen/changed.help.lhs
--- a/Help/UGen/changed.help.lhs
+++ b/Help/UGen/changed.help.lhs
@@ -1,9 +1,6 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Changed"
-    > Sound.SC3.UGen.DB.ugenSummary "Changed"
-
 > import Sound.SC3 {- hsc3 -}
 
-simple composition of hpz1 and >*
+simple composition of hpz1 and greater_than
 
 > g_01 =
 >     let s = lfNoise0 'α' KR 2
diff --git a/Help/UGen/choose.help.lhs b/Help/UGen/choose.help.lhs
--- a/Help/UGen/choose.help.lhs
+++ b/Help/UGen/choose.help.lhs
@@ -3,7 +3,7 @@
 choose is a composite of iRand and select.
 
 > import Sound.SC3 {- hsc3 -}
->
+
 > g_01 =
 >     let f = uclone 'α' 2 (choose 'β' (mce [440,460 .. 880]))
 >     in sinOsc AR f  0 * 0.1
diff --git a/Help/UGen/clip.help.lhs b/Help/UGen/clip.help.lhs
--- a/Help/UGen/clip.help.lhs
+++ b/Help/UGen/clip.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Clip"
-    > Sound.SC3.UGen.DB.ugenSummary "Clip"
-
 > import Sound.SC3 {- hsc3 -}
->
+
 > g_01 = clip (sinOsc AR 440 0 * 0.4) (-0.25) 0.25
diff --git a/Help/UGen/clip2.help.lhs b/Help/UGen/clip2.help.lhs
--- a/Help/UGen/clip2.help.lhs
+++ b/Help/UGen/clip2.help.lhs
@@ -1,10 +1,7 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Operator.clip2"
-    > :t clip2
-
 > import Sound.SC3 {- hsc3 -}
 
 clipping distortion
 
 > g_01 = clip2 (fSinOsc AR 400 0) 0.2
->
+
 > g_02 = clip2 (fSinOsc AR 400 0) (line KR 0 1 8 RemoveSynth)
diff --git a/Help/UGen/clipNoise.help.lhs b/Help/UGen/clipNoise.help.lhs
--- a/Help/UGen/clipNoise.help.lhs
+++ b/Help/UGen/clipNoise.help.lhs
@@ -1,8 +1,5 @@
-    Sound.SC3.UGen.Help.viewSC3Help "ClipNoise"
-    Sound.SC3.UGen.DB.ugenSummary "ClipNoise"
-
 > import Sound.SC3
->
+
 > g_01 = clipNoise 'α' AR * 0.1 {- hsc3 -}
 
 Drawings
diff --git a/Help/UGen/coinGate.help.lhs b/Help/UGen/coinGate.help.lhs
--- a/Help/UGen/coinGate.help.lhs
+++ b/Help/UGen/coinGate.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "CoinGate"
-    Sound.SC3.UGen.DB.ugenSummary "CoinGate"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 =
diff --git a/Help/UGen/compander.help.lhs b/Help/UGen/compander.help.lhs
--- a/Help/UGen/compander.help.lhs
+++ b/Help/UGen/compander.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "Compander"
-    Sound.SC3.UGen.DB.ugenSummary "Compander"
-
 > import Sound.SC3 {- hsc3 -}
 
 Example signal to process.
diff --git a/Help/UGen/complexRes.help.lhs b/Help/UGen/complexRes.help.lhs
--- a/Help/UGen/complexRes.help.lhs
+++ b/Help/UGen/complexRes.help.lhs
@@ -1,11 +1,8 @@
-    Sound.SC3.UGen.Help.viewSC3Help "ComplexRes"
-    Sound.SC3.UGen.DB.ugenSummary "ComplexRes"
-
 > import Sound.SC3 {- hsc3 -}
-> import qualified Sound.SC3.UGen.Bindings.DB.External as External {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
 
 > g_01 =
 >   let s = pulse AR 0.1 0.001 * 0.1
 >       fr = 50 + 5000 * sinOsc AR 50 0
 >       dt = 0.5
->   in External.complexRes s fr dt
+>   in X.complexRes s fr dt
diff --git a/Help/UGen/concat.help.lhs b/Help/UGen/concat.help.lhs
--- a/Help/UGen/concat.help.lhs
+++ b/Help/UGen/concat.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "Concat"
-    Sound.SC3.UGen.DB.ugenSummary "Concat"
-
 > import Sound.SC3 {- hsc3 -}
 
 > fn_01 = "/home/rohan/data/audio/pf-c5.snd"
diff --git a/Help/UGen/controlDur.help.lhs b/Help/UGen/controlDur.help.lhs
--- a/Help/UGen/controlDur.help.lhs
+++ b/Help/UGen/controlDur.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "ControlDur"
-    > Sound.SC3.UGen.DB.ugenSummary "ControlDur"
-
 > import Sound.SC3 {- hsc3 -}
 
 default block size = 64, default sample rate = 48000
diff --git a/Help/UGen/controlRate.help.lhs b/Help/UGen/controlRate.help.lhs
--- a/Help/UGen/controlRate.help.lhs
+++ b/Help/UGen/controlRate.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "ControlRate"
-    > Sound.SC3.UGen.DB.ugenSummary "ControlRate"
-
 > import Sound.SC3 {- hsc3 -}
 
 play a sine tone at control rate, the reciprocal of controlDur
diff --git a/Help/UGen/convolution.help.lhs b/Help/UGen/convolution.help.lhs
--- a/Help/UGen/convolution.help.lhs
+++ b/Help/UGen/convolution.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Convolution"
-    > Sound.SC3.UGen.DB.ugenSummary "Convolution"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 =
diff --git a/Help/UGen/coyote.help.lhs b/Help/UGen/coyote.help.lhs
--- a/Help/UGen/coyote.help.lhs
+++ b/Help/UGen/coyote.help.lhs
@@ -1,11 +1,8 @@
-    Sound.SC3.UGen.Help.viewSC3Help "Coyote"
-    Sound.SC3.UGen.DB.ugenSummary "Coyote"
-
 > import Sound.SC3 {- hsc3 -}
-> import Sound.SC3.UGen.Bindings.DB.External {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
 
 > g_01 =
 >   let i = soundIn 0
->       c = coyote KR i 0.2 0.2 0.01 0.5 0.05 0.1
+>       c = X.coyote KR i 0.2 0.2 0.01 0.5 0.05 0.1
 >       o = pinkNoise 'α' AR * decay c 1
 >   in mce2 i o
diff --git a/Help/UGen/crackle.help.lhs b/Help/UGen/crackle.help.lhs
--- a/Help/UGen/crackle.help.lhs
+++ b/Help/UGen/crackle.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "Crackle"
-    Sound.SC3.UGen.DB.ugenSummary "Crackle"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 = crackle AR 1.95 * 0.2
diff --git a/Help/UGen/crossoverDistortion.help.lhs b/Help/UGen/crossoverDistortion.help.lhs
--- a/Help/UGen/crossoverDistortion.help.lhs
+++ b/Help/UGen/crossoverDistortion.help.lhs
@@ -1,19 +1,16 @@
-    Sound.SC3.UGen.Help.viewSC3Help "CrossoverDistortion"
-    Sound.SC3.UGen.DB.ugenSummary "CrossoverDistortion"
-
 > import Sound.SC3 {- hsc3 -}
-> import Sound.SC3.UGen.Bindings.DB.External {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
 
 {CrossoverDistortion.ar(SinOsc.ar([400, 404], 0, 0.2), MouseX.kr(0, 1), MouseY.kr(0, 1))}.play
 
 > g_01 =
 >   let x = mouseX KR 0 1 Linear 0.2
 >       y = mouseY KR 0 1 Linear 0.2
->   in crossoverDistortion (sinOsc AR (mce2 400 404) 0 * 0.2) x y
+>   in X.crossoverDistortion (sinOsc AR (mce2 400 404) 0 * 0.2) x y
 
 {CrossoverDistortion.ar(SoundIn.ar, MouseX.kr(0, 1), MouseY.kr(0, 1))}.play
 
 > g_02 =
 >   let x = mouseX KR 0 1 Linear 0.2
 >       y = mouseY KR 0 1 Linear 0.2
->   in crossoverDistortion (soundIn 0) x y
+>   in X.crossoverDistortion (soundIn 0) x y
diff --git a/Help/UGen/cuspL.help.lhs b/Help/UGen/cuspL.help.lhs
--- a/Help/UGen/cuspL.help.lhs
+++ b/Help/UGen/cuspL.help.lhs
@@ -1,12 +1,14 @@
-    Sound.SC3.UGen.Help.viewSC3Help "CuspL"
-    Sound.SC3.UGen.DB.ugenSummary "CuspL"
-
 > import Sound.SC3 {- hsc3 -}
+> import Sound.SC3.Common.Math.Noise {- hsc3 -}
 
+Default values
+
+> g_00 = cuspL AR 22050 1.0 1.9 0.0 * 0.1
+
 Vary frequency
 
 > g_01 =
->     let x = mouseX KR 20 sampleRate Linear 0.1
+>     let x = mouseX KR 20 (sampleRate / 2) Linear 0.1
 >     in cuspL AR x 1.0 1.99 0 * 0.3
 
 Mouse-controlled parameters.
@@ -26,8 +28,8 @@
 
 Haskell implementation of equation.
 
-> cuspl_hs a b = iterate (\x -> a - (b * sqrt (abs x))) 0
+> cusp_hs a b = iterate (cusp_f a b) 0
 
     import Sound.SC3.Plot {- hsc3-plot -}
-    plotTable1 (take 600 (cuspl_hs 1.0 1.9))
+    plotTable1 (take 600 (cusp_hs 1.0 1.9))
     plot_ugen_nrt (600,1) 1.0 (cuspL AR 600 1.0 1.9 0)
diff --git a/Help/UGen/dNoiseRing.help.lhs b/Help/UGen/dNoiseRing.help.lhs
--- a/Help/UGen/dNoiseRing.help.lhs
+++ b/Help/UGen/dNoiseRing.help.lhs
@@ -1,13 +1,10 @@
-    Sound.SC3.UGen.Help.viewSC3Help "DNoiseRing"
-    Sound.SC3.UGen.DB.ugenSummary "DNoiseRing"
-
 > import Sound.SC3 {- hsc3 -}
-> import qualified Sound.SC3.UGen.Bindings.DB.External as External {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
 
 > g_01 =
 >   let tr = impulse AR 10 0
 >       x = mouseX KR 0 1 Linear 0.2
 >       y = mouseY KR 0 1 Linear 0.2
->       nr = demand tr 0 (External.dNoiseRing x y 1.0 32.0 0.0)
+>       nr = demand tr 0 (X.dNoiseRing x y 1.0 32.0 0.0)
 >       freq = midiCPS (linLin nr 0 (2**32) 40 (40 + 48))
 >   in sinOsc AR freq 0 * 0.1
diff --git a/Help/UGen/dWGBowed.help.lhs b/Help/UGen/dWGBowed.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/dWGBowed.help.lhs
@@ -0,0 +1,25 @@
+> import Sound.SC3 {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
+
+> g_01 =
+>   let k = control KR
+>       out_ = k "out" 0
+>       freq = k "freq" 440
+>       amp = k "amp" 0.5
+>       force = k "force" 1
+>       gate_ = k "gate" 1
+>       pos = k "pos" 0.07
+>       c1 = k "c1" 0.25
+>       c3 = k "c3" 31
+>       pan = k "pan" 0
+>       vib = gendy1 'α' KR 1 1 1 1 0.1 4 0.5 0.5 12 0 * 0.003 + 1
+>       s1 = X.dWGBowed AR (freq  *vib) amp force gate_ pos 0.1 c1 c3 0.55 2
+>       s2 = X.dWGSoundBoard AR s1 20 20 0.8 199 211 223 227 229 233 239 241
+>       s3 = bpf s2 118 1 + s2
+>       s4 = bpf s3 430 1 + s3
+>       s5 = bpf s4 490 1 + s4
+>       s6 = lpf s5 6000
+>   in out out_ (pan2 (s6 * 0.1) pan 1)
+
+    > import Sound.OSC {- hosc -}
+    > withSC3 (sendMessage (n_set1 (-1) "gate" 0))
diff --git a/Help/UGen/dWGBowedTor.help.lhs b/Help/UGen/dWGBowedTor.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/dWGBowedTor.help.lhs
@@ -0,0 +1,25 @@
+> import Sound.SC3 {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
+
+> g_01 =
+>   let k = control KR
+>       out_ = k "out" 0
+>       freq = k "freq" 440
+>       amp = k "amp" 0.5
+>       force = k "force" 1
+>       gate_ = k "gate" 1
+>       pos = k "pos" 0.07
+>       c1 = k "c1" 0.25
+>       c3 = k "c3" 31
+>       pan = k "pan" 0
+>       vib = gendy1 'α' KR 1 1 1 1 0.1 4 0.5 0.5 12 0 * 0.003 + 1
+>       s1 = X.dWGBowedTor AR (freq  *vib) amp force gate_ pos 0.1 c1 c3 0.55 2 5.2 1 3000 1.8
+>       s2 = X.dWGSoundBoard AR s1 20 20 0.8 199 211 223 227 229 233 239 241
+>       s3 = bpf s2 118 1 + s2
+>       s4 = bpf s3 430 1 + s3
+>       s5 = bpf s4 490 1 + s4
+>       s6 = lpf s5 6000
+>   in out out_ (pan2 (s6 * 0.1) pan 1)
+
+    > import Sound.OSC {- hosc -}
+    > withSC3 (sendMessage (n_set1 (-1) "gate" 0))
diff --git a/Help/UGen/dWGPlucked2.help.lhs b/Help/UGen/dWGPlucked2.help.lhs
--- a/Help/UGen/dWGPlucked2.help.lhs
+++ b/Help/UGen/dWGPlucked2.help.lhs
@@ -1,8 +1,5 @@
-    Sound.SC3.UGen.Help.viewSC3Help "DWGPlucked2"
-    Sound.SC3.UGen.DB.ugenSummary "DWGPlucked2"
-
-> import Sound.SC3
-> import qualified Sound.SC3.UGen.Bindings.DB.External as E {- hsc3 -}
+> import Sound.SC3 {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
 
 self deleting
 
@@ -13,7 +10,7 @@
 >       c3 = 20
 >       inp = let e = envelope [0,1,1,0] [0.001,0.006,0.0005] (map EnvNum [5,-5,-8])
 >             in amp * lfClipNoise 'α' AR 2000 * envGen AR gate_ 1 0 1 DoNothing e
->       ps = E.dWGPlucked2 AR freq amp gate_ 0.1 1 c3 inp 0.1 1.008 0.55 0.01
+>       ps = X.dWGPlucked2 AR freq amp gate_ 0.1 1 c3 inp 0.1 1.008 0.55 0.01
 >       pan = 0
 >       z = detectSilence ps 0.001 0.1 RemoveSynth
 >   in mrg2 (pan2 ps pan 0.1) z
@@ -37,9 +34,9 @@
 >             in amp * lfClipNoise 'κ' AR 2000 * env -- pluck signal
 >       release = tRand 'λ' 0.05 0.15 t -- release time (seconds, def = 0.1)
 >       mistune = tRand 'μ' 0.992 1.008 t -- factor for detuning second string (def = 1.008)
->       mp = tRand 'ν' 0.35 0.65 t -- exitation mixer (def = 0.55)
+>       mp = tRand 'ν' 0.35 0.65 t -- excitation mixer (def = 0.55)
 >       gc = tRand 'ξ' 0.001 0.020 t -- coupling string factor (def = 0.01)
->       ps = E.dWGPlucked2 AR freq amp gate_ pos c1 c3 inp release mistune mp gc
+>       ps = X.dWGPlucked2 AR freq amp gate_ pos c1 c3 inp release mistune mp gc
 >       pan = tRand 'ο' (-1) 1 t
 >   in pan2 ps pan 0.1
 
diff --git a/Help/UGen/dWGPluckedStiff.help.lhs b/Help/UGen/dWGPluckedStiff.help.lhs
--- a/Help/UGen/dWGPluckedStiff.help.lhs
+++ b/Help/UGen/dWGPluckedStiff.help.lhs
@@ -1,8 +1,5 @@
-    Sound.SC3.UGen.Help.viewSC3Help "DWGPluckedStiff"
-    Sound.SC3.UGen.DB.ugenSummary "DWGPluckedStiff"
-
-> import Sound.SC3
-> import qualified Sound.SC3.UGen.Bindings.DB.External as E {- hsc3 -}
+> import Sound.SC3 {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
 
 self deleting
 
@@ -17,7 +14,7 @@
 >             in amp * lfClipNoise 'α' AR 2000 * envGen AR gate_ 1 0 1 DoNothing e
 >       release = 0.1
 >       fB = 2.0
->       ps = E.dWGPluckedStiff AR freq amp gate_ pos c1 c3 inp release fB
+>       ps = X.dWGPluckedStiff AR freq amp gate_ pos c1 c3 inp release fB
 >       pan = 0
 >       z = detectSilence ps 0.001 0.1 RemoveSynth
 >   in mrg2 (pan2 ps pan 0.1) z
@@ -41,6 +38,6 @@
 >             in amp * lfClipNoise 'κ' AR 2000 * env -- pluck signal
 >       release = tRand 'λ' 0.05 0.15 t -- release time (seconds, def = 0.1)
 >       fB = tRand 'μ' 1.0 4.0 t -- inharmonicity factor (def = 2.0)
->       ps = E.dWGPluckedStiff AR freq amp gate_ pos c1 c3 inp release fB
+>       ps = X.dWGPluckedStiff AR freq amp gate_ pos c1 c3 inp release fB
 >       pan = tRand 'ο' (-1) 1 t
 >   in pan2 ps pan 0.1
diff --git a/Help/UGen/dbAmp.help.lhs b/Help/UGen/dbAmp.help.lhs
--- a/Help/UGen/dbAmp.help.lhs
+++ b/Help/UGen/dbAmp.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Operator.dbamp"
-    > :t dbAmp
-
 > import Sound.SC3 {- hsc3 -}
 
 Linear db motion is exponential amplitude decay
diff --git a/Help/UGen/dbrown.help.lhs b/Help/UGen/dbrown.help.lhs
--- a/Help/UGen/dbrown.help.lhs
+++ b/Help/UGen/dbrown.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "Dbrown"
-    Sound.SC3.UGen.DB.ugenSummary "Dbrown"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 =
diff --git a/Help/UGen/dbufrd.help.lhs b/Help/UGen/dbufrd.help.lhs
--- a/Help/UGen/dbufrd.help.lhs
+++ b/Help/UGen/dbufrd.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Dbufrd"
-    > Sound.SC3.UGen.DB.ugenSummary "Dbufrd"
-
 > import Sound.SC3 {- hsc3 -}
 > import System.Random {- random -}
 
diff --git a/Help/UGen/dbufwr.help.lhs b/Help/UGen/dbufwr.help.lhs
--- a/Help/UGen/dbufwr.help.lhs
+++ b/Help/UGen/dbufwr.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Dbufwr"
-    > Sound.SC3.UGen.DB.ugenSummary "Dbufwr"
-
 > import Sound.SC3 {- hsc3 -}
 
 allocate buffer
diff --git a/Help/UGen/dc.help.lhs b/Help/UGen/dc.help.lhs
--- a/Help/UGen/dc.help.lhs
+++ b/Help/UGen/dc.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "DC"
-    > Sound.SC3.UGen.DB.ugenSummary "DC"
-
 > import Sound.SC3 {- hsc3 -}
 
 error...
diff --git a/Help/UGen/dconst.help.lhs b/Help/UGen/dconst.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/dconst.help.lhs
@@ -0,0 +1,12 @@
+> import Sound.SC3 {- hsc3 -}
+
+fast notes of random duration for 0.5 seconds, then a single note for 0.5 seconds
+
+there is no Dexprand
+
+> dexprand z rp l r = lin_exp (dwhite z rp 0 1) 0 1 l r
+
+> g_01 =
+>   let t = dconst 'α' 0.5 (dwhite 'β' dinf 0.05 0.08) 0.001
+>       f = duty KR (dseq 'γ' dinf (mce2 t 0.5)) 0 DoNothing (dexprand 'δ' dinf 200 600)
+>   in varSaw AR (lag f 0.02) 0 0.3 * 0.1
diff --git a/Help/UGen/decay.help.lhs b/Help/UGen/decay.help.lhs
--- a/Help/UGen/decay.help.lhs
+++ b/Help/UGen/decay.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "Decay"
-    Sound.SC3.UGen.DB.ugenSummary "Decay"
-
 > import Sound.SC3 {- hsc3 -}
 
 Used as an envelope.
diff --git a/Help/UGen/decay2.help.lhs b/Help/UGen/decay2.help.lhs
--- a/Help/UGen/decay2.help.lhs
+++ b/Help/UGen/decay2.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "Decay2"
-    Sound.SC3.UGen.DB.ugenSummary "Decay2"
-
 > import Sound.SC3 {- hsc3 -}
 
 Used as an envelope
diff --git a/Help/UGen/degreeToKey.help.lhs b/Help/UGen/degreeToKey.help.lhs
--- a/Help/UGen/degreeToKey.help.lhs
+++ b/Help/UGen/degreeToKey.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "DegreeToKey"
-    > Sound.SC3.UGen.DB.ugenSummary "DegreeToKey"
-
 > import Sound.SC3 {- hsc3 -}
 
 allocate & initialise buffer zero
@@ -11,11 +8,11 @@
 
 modal space, mouse x controls discrete pitch in dorian mode
 
-> f_01 b =
->     let n = lfNoise1 'α' KR (mce [3,3.05])
->         x = mouseX KR 0 15 Linear 0.1
->         k = degreeToKey b x 12
->         f b = let o = sinOsc AR (midiCPS (b + k + n * 0.04)) 0 * 0.1
+> f_01 buf =
+>     let x = mouseX KR 0 15 Linear 0.1
+>         k = degreeToKey buf x 12
+>         f b = let n = lfNoise1 'α' KR (mce [3,3.05])
+>                   o = sinOsc AR (midiCPS (b + k + n * 0.04)) 0 * 0.1
 >                   t = lfPulse AR (midiCPS (mce [48,55])) 0.15 0.5
 >                   d = rlpf t (midiCPS (sinOsc KR 0.1 0 * 10 + b)) 0.1 * 0.1
 >                   m = o + d
diff --git a/Help/UGen/delay1.help.lhs b/Help/UGen/delay1.help.lhs
--- a/Help/UGen/delay1.help.lhs
+++ b/Help/UGen/delay1.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "Delay1"
-    Sound.SC3.UGen.DB.ugenSummary "Delay1"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 = let s = impulse AR 1 0 in s + (delay1 s)
diff --git a/Help/UGen/delay2.help.lhs b/Help/UGen/delay2.help.lhs
--- a/Help/UGen/delay2.help.lhs
+++ b/Help/UGen/delay2.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Delay2"
-    > Sound.SC3.UGen.DB.ugenSummary "Delay2"
-
 > import Sound.SC3 {- hsc3 -}
->
+
 > g_01 = let s = impulse AR 1 0 in s + (delay2 s)
diff --git a/Help/UGen/delayL.help.lhs b/Help/UGen/delayL.help.lhs
--- a/Help/UGen/delayL.help.lhs
+++ b/Help/UGen/delayL.help.lhs
@@ -1,1 +1,10 @@
 See delayN
+
+> import Sound.SC3 {- hsc3 -}
+
+> g_01 =
+>   let t = mouseX KR 0.001 0.2 Exponential 0.2
+>       s = impulse AR 1 0
+>       d = delayL s 0.6 t
+>   in mce2 d s
+
diff --git a/Help/UGen/delayN.help.lhs b/Help/UGen/delayN.help.lhs
--- a/Help/UGen/delayN.help.lhs
+++ b/Help/UGen/delayN.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "DelayN"
-    Sound.SC3.UGen.DB.ugenSummary "DelayN"
-
 > import Sound.SC3 {- hsc3 -}
 
 Dust randomly triggers Decay to create an exponential decay envelope
@@ -18,3 +15,17 @@
 >         maxdelaytime = 0.005
 >         delaytime = mouseX KR 0.0 maxdelaytime Linear 0.15
 >     in i + delayN i maxdelaytime delaytime
+
+Flanging
+
+> f_03 lp_f =
+>   let f = 0.1 -- flanger freq
+>       g = 0.1 -- feedback
+>       i = soundIn (mce2 0 1) -- two channels of input signal
+>       fb = i + localIn 2 AR 0 -- add feedback
+>       e = delayN fb 0.02 (sinOsc KR f 0 * 0.005 + 0.005) -- max delay of 20msec
+>       o = localOut (lp_f e * g)
+>   in mrg2 (i + e) o
+
+> g_03 = f_03 id
+> g_04 = f_03 (\x -> bpf x (mouseX KR 1000 10000 Linear 0.2) 0.1) -- filter in the feedback loop
diff --git a/Help/UGen/demand.help.lhs b/Help/UGen/demand.help.lhs
--- a/Help/UGen/demand.help.lhs
+++ b/Help/UGen/demand.help.lhs
@@ -1,8 +1,5 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Demand"
-    > Sound.SC3.UGen.DB.ugenSummary "Demand"
-
 > import Sound.SC3 {- hsc3 -}
->
+
 > g_01 :: UId m => m UGen
 > g_01 = do
 >   r <- dustM KR 1
@@ -11,7 +8,7 @@
 >       f = demand t r s
 >       o = sinOsc AR (mce [f,f + 0.7]) 0
 >   return (max (cubed o) 0 * 0.1)
->
+
 > g_02 =
 >     let n = diwhite 'α' dinf 60 72
 >         t = impulse KR 10 0
@@ -30,6 +27,19 @@
 >         x1 = demand t 0 d
 >         x2 = latch i t
 >         s = mce2 x1 x2
->         p = poll t s (mce2 (label "x1") (label "x2")) 0
+>         p = poll t s 0 (mce2 (label "x1") (label "x2"))
 >         o = sinOsc AR (s * 300 + 400) 0 * 0.1
 >     in mrg2 o p
+
+> g_04 =
+>   let t = impulse AR 5 0
+>       d1 = dseq 'α' dinf (mce [1,0,1,1,0,1,0,0,1,0,1])
+>       d2 = dseq 'β' dinf (mce [0,1,0,0,1,0,1,1,0,1,0])
+>       x = demand t 0 (mce2 d1 d2) * t
+>   in decay x 1 * brownNoise 'γ' AR * 0.1
+
+> g_05 =
+>   let t = impulse AR 5 0
+>       d = drand 'α' dinf (mce [dseq 'β' 1 (mce [1,1,1,1]),dseq 'γ' 1 (mce [1,0,0,0])])
+>       x = demand t 0 d * t
+>   in decay x 1 * brownNoise 'δ' AR * 0.1
diff --git a/Help/UGen/demandEnvGen.help.lhs b/Help/UGen/demandEnvGen.help.lhs
--- a/Help/UGen/demandEnvGen.help.lhs
+++ b/Help/UGen/demandEnvGen.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "DemandEnvGen"
-    Sound.SC3.UGen.DB.ugenSummary "DemandEnvGen"
-
 > import Sound.SC3 {- hsc3 -}
 
 Frequency ramp, exponential curve.
@@ -45,7 +42,7 @@
 > g_05 =
 >     let n = roundTo (dwhite 'α' dinf 300 1000) 100
 >         x = mouseX KR 0 1 Linear 0.2
->         g = x >* 0.5
+>         g = x >** 0.5
 >         f = demandEnvGen AR n 0.1 5 0.3 g 1 1 0 1 DoNothing
 >     in sinOsc AR (f * mce2 1 1.21) 0 * 0.1
 
@@ -56,9 +53,9 @@
 > g_06 =
 >     let l = dseq 'α' 2 (mce [dseries 'β' 5 400 200,500,800,530,4000,900])
 >         x = mouseX KR 0 1 Linear 0.2
->         g = (x >* 0.5) - 0.1
+>         g = (x >** 0.5) - 0.1
 >         b = mouseButton KR 0 1 0.2
->         r = (b >* 0.5) * 2
+>         r = (b >** 0.5) * 2
 >         s = env_curve_shape EnvSin
 >         f = demandEnvGen KR l 0.1 s 0 g r 1 0 1 DoNothing
 >     in sinOsc AR (f * mce2 1 1.001) 0 * 0.1
@@ -81,7 +78,8 @@
 
 change envelope by setting values or indeed reallocating buffer
 
-    > withSC3 (send (b_set1 0 1 0.1))
+    > import Sound.OSC {- hosc -}
+    > withSC3 (sendMessage (b_set1 0 1 0.1))
     > withSC3 (async (b_alloc_setn1 0 0 [0.5,0.9,0.1,0.1,1,0.01]))
 
 read envelope break-points from buffer, here simply duration/level pairs.
diff --git a/Help/UGen/detectIndex.help.lhs b/Help/UGen/detectIndex.help.lhs
--- a/Help/UGen/detectIndex.help.lhs
+++ b/Help/UGen/detectIndex.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "DetectIndex"
-    > Sound.SC3.UGen.DB.ugenSummary "DetectIndex"
-
 > import Sound.SC3 {- hsc3 -}
 
 Find indexes and map to an audible frequency range.
diff --git a/Help/UGen/detectSilence.help.lhs b/Help/UGen/detectSilence.help.lhs
--- a/Help/UGen/detectSilence.help.lhs
+++ b/Help/UGen/detectSilence.help.lhs
@@ -1,9 +1,6 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "DetectSilence"
-    > Sound.SC3.UGen.DB.ugenSummary "DetectSilence"
-
 > import Sound.SC3 {- hsc3 -}
->
+
 > g_01 =
 >     let s = sinOsc AR 440 0 * mouseY KR 0 0.2 Linear 0.1
->         d = detectSilence s 0.1 0.1 RemoveSynth
+>         d = detectSilence s 0.01 0.1 RemoveSynth
 >     in mrg [s,d]
diff --git a/Help/UGen/dfm1.help.lhs b/Help/UGen/dfm1.help.lhs
--- a/Help/UGen/dfm1.help.lhs
+++ b/Help/UGen/dfm1.help.lhs
@@ -1,20 +1,17 @@
-    Sound.SC3.UGen.Help.viewSC3Help "DFM1"
-    Sound.SC3.UGen.DB.ugenSummary "DFM1"
-
 > import Sound.SC3 {- hsc3 -}
-> import Sound.SC3.UGen.Bindings.DB.External {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
 
 Play it with the mouse
 
-> gr_01 =
+> g_01 =
 >     let n = pinkNoise 'α' AR * 0.5
 >         x = mouseX KR 80 5000 Exponential 0.1
 >         y = mouseY KR 0.1 1.2 Linear 0.1
->     in dfm1 n x y 1 0 3e-4
+>     in X.dfm1 n x y 1 0 3e-4
 
 Bass...
 
-> gr_02 =
+> g_02 =
 >     let i = mix (pulse AR (mce2 100 100.1) 0.5) * 0.4
 >         f = range 80 2000 (sinOsc KR (range 0.2 5 (sinOsc KR 0.3 0)) 0)
->     in dfm1 i f 1.1 2 0 0.0003 * 0.1
+>     in X.dfm1 i f 1.1 2 0 0.0003 * 0.1
diff --git a/Help/UGen/dgeom.help.lhs b/Help/UGen/dgeom.help.lhs
--- a/Help/UGen/dgeom.help.lhs
+++ b/Help/UGen/dgeom.help.lhs
@@ -1,8 +1,5 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Dgeom"
-    > Sound.SC3.UGen.DB.ugenSummary "Dgeom"
-
 > import Sound.SC3 {- hsc3 -}
->
+
 > g_01 =
 >     let n = dgeom 'α' 15 1 1.2
 >         x = mouseX KR 1 40 Exponential 0.1
diff --git a/Help/UGen/difSqr.help.lhs b/Help/UGen/difSqr.help.lhs
--- a/Help/UGen/difSqr.help.lhs
+++ b/Help/UGen/difSqr.help.lhs
@@ -1,8 +1,5 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Operator.difsqr"
-    > :t difSqr
-
 > import Sound.SC3 {- hsc3 -}
->
+
 > g_01 =
 >     let a = fSinOsc AR 800 0
 >         b = fSinOsc AR (xLine KR 200 500 5 DoNothing) 0
diff --git a/Help/UGen/diodeRingMod.help.lhs b/Help/UGen/diodeRingMod.help.lhs
--- a/Help/UGen/diodeRingMod.help.lhs
+++ b/Help/UGen/diodeRingMod.help.lhs
@@ -1,26 +1,23 @@
-    Sound.SC3.UGen.Help.viewSC3Help "DiodeRingMod"
-    Sound.SC3.UGen.DB.ugenSummary "DiodeRingMod"
-
 > import Sound.SC3 {- hsc3 -}
-> import qualified Sound.SC3.UGen.Bindings.DB.External as External {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
 
 > o_01 = sinOsc AR 440 0
 > o_02 = sinOsc AR (xLine KR 1 100 10 DoNothing) 0
 > o_03 = sinOsc AR (xLine KR 200 500 5 DoNothing) 0
-> g_01 = External.diodeRingMod o_01 o_02 * 0.125
+> g_01 = X.diodeRingMod o_01 o_02 * 0.125
 > g_02 = (o_01 * o_02) * 0.125
-> g_03 = External.diodeRingMod o_01 o_03 * 0.125
+> g_03 = X.diodeRingMod o_01 o_03 * 0.125
 > g_04 = (o_01 * o_03) * 0.125
 
 > g_05 =
 >   let s1 = sinOsc AR (3700 * mce [1, 1.1, 1.2] * range 1 2 (sinOsc AR 200 0)) 0
 >       s2 = sinOsc AR (100 * mce [0.75, 1, 0.5]) 0
->       s3 = External.diodeRingMod s1 s2
+>       s3 = X.diodeRingMod s1 s2
 >   in mix s3 * lfPulse AR (10.3 * 0.5) 0 0.04 * 0.1
 
 > mf_sin = sinOsc AR
 
-> mf_square f _ = External.blitB3Square AR f 0.99
+> mf_square f _ = X.blitB3Square AR f 0.99
 
 c_freq = carrier frequency (mf = six-octave range, 2-130 and 60-4000 hz)
 
@@ -39,7 +36,7 @@
 >       lfo = range_2oct (lfo_type lfo_freq lfo_ph * lfo_amp)
 >       car_sig = sinOsc AR (car_freq * lfo) car_ph
 >       mod_sig_post = mod_sig * drive
->   in xFade2 mod_sig_post (External.diodeRingMod car_sig mod_sig_post) x_mix 1
+>   in xFade2 mod_sig_post (X.diodeRingMod car_sig mod_sig_post) x_mix 1
 
 > g_07 =
 >   let c_freq = 6.25
diff --git a/Help/UGen/disintegrator.help.lhs b/Help/UGen/disintegrator.help.lhs
--- a/Help/UGen/disintegrator.help.lhs
+++ b/Help/UGen/disintegrator.help.lhs
@@ -1,11 +1,8 @@
-    Sound.SC3.UGen.Help.viewSC3Help "Disintegrator"
-    Sound.SC3.UGen.DB.ugenSummary "Disintegrator"
-
 > import Sound.SC3 {- hsc3 -}
-> import Sound.SC3.UGen.Bindings.DB.External {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
 
 > gr_01 =
 >     let x = mouseX KR 0 1 Linear 0.2
 >         y = mouseY KR 0 1 Linear 0.2
 >         s = sinOsc AR (mce2 400 404) 0 * 0.2
->     in disintegrator 'α' s x y
+>     in X.disintegrator 'α' s x y
diff --git a/Help/UGen/diskIn.help.lhs b/Help/UGen/diskIn.help.lhs
--- a/Help/UGen/diskIn.help.lhs
+++ b/Help/UGen/diskIn.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "DiskIn"
-    Sound.SC3.UGen.DB.ugenSummary "DiskIn"
-
 > import Sound.SC3 {- hsc3 -}
 
 > fn_01 = "/home/rohan/data/audio/pf-c5.snd"
diff --git a/Help/UGen/diskOut.help.lhs b/Help/UGen/diskOut.help.lhs
--- a/Help/UGen/diskOut.help.lhs
+++ b/Help/UGen/diskOut.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "DiskOut"
-    Sound.SC3.UGen.DB.ugenSummary "DiskOut"
-
 > import Sound.OSC {- hosc -}
 > import Sound.SC3 {- hsc3 -}
 
diff --git a/Help/UGen/distort.help.lhs b/Help/UGen/distort.help.lhs
--- a/Help/UGen/distort.help.lhs
+++ b/Help/UGen/distort.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Operator.distort"
-    > :t distort
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 =
diff --git a/Help/UGen/div.help.lhs b/Help/UGen/div.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/div.help.lhs
@@ -0,0 +1,14 @@
+    Sound.SC3.UGen.Help.viewSC3Help "Operator./"
+    :t (/)
+
+> import Sound.SC3 {- hsc3 -}
+
+> g_01 = sinOsc AR 440 0 / 6
+
+Creates a beating effect (subaudio rate).
+
+> g_02 = (pinkNoise 'α' AR / fSinOsc KR 5 0) * 0.1
+
+Optimises identity
+
+> g_04 = sinOsc AR 440 0 / 1 * 0.1
diff --git a/Help/UGen/diwhite.help.lhs b/Help/UGen/diwhite.help.lhs
--- a/Help/UGen/diwhite.help.lhs
+++ b/Help/UGen/diwhite.help.lhs
@@ -1,4 +1,1 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Diwhite"
-    > Sound.SC3.UGen.DB.ugenSummary "Diwhite"
-
 See dwhite
diff --git a/Help/UGen/done.help.lhs b/Help/UGen/done.help.lhs
--- a/Help/UGen/done.help.lhs
+++ b/Help/UGen/done.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Done"
-    > Sound.SC3.UGen.DB.ugenSummary "Done"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 =
diff --git a/Help/UGen/doubleWell3.help.lhs b/Help/UGen/doubleWell3.help.lhs
--- a/Help/UGen/doubleWell3.help.lhs
+++ b/Help/UGen/doubleWell3.help.lhs
@@ -1,8 +1,5 @@
-    Sound.SC3.UGen.Help.viewSC3Help "DoubleWell3"
-    Sound.SC3.UGen.DB.ugenSummary "DoubleWell3"
-
 > import Sound.SC3 {- hsc3 -}
-> import Sound.SC3.UGen.Bindings.DB.External {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
 
 bass synth
 
@@ -10,11 +7,11 @@
 >   let x = mouseX KR 0 200 Linear 0.2
 >       y = mouseY KR 0.5 4.0 Linear 0.2
 >       f = sinOsc AR x 0 * y
->   in doubleWell3 AR 0 0.01 f 0.25 0 0
+>   in X.doubleWell3 AR 0 0.01 f 0.25 0 0
 
 gradually changing
 
 > g_02 =
 >   let f = lfSaw AR (line KR 10 1000 10 DoNothing) 0
 >       delta = line KR 0.0 0.3 20 DoNothing
->   in doubleWell3 AR 0 0.05 f delta 0 0
+>   in X.doubleWell3 AR 0 0.05 f delta 0 0
diff --git a/Help/UGen/dpw3Tri.help.lhs b/Help/UGen/dpw3Tri.help.lhs
--- a/Help/UGen/dpw3Tri.help.lhs
+++ b/Help/UGen/dpw3Tri.help.lhs
@@ -1,18 +1,15 @@
-    Sound.SC3.UGen.Help.viewSC3Help "DPW3Tri"
-    Sound.SC3.UGen.DB.ugenSummary "DPW3Tri"
-
 > import Sound.SC3 {- hsc3 -}
-> import qualified Sound.SC3.UGen.Bindings.DB.External as E {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
 
 > import qualified Sound.SC3.UGen.Bindings.DB.RDU as RDU {- sc3-rdu -}
 
 distortion creeps in under 200Hz
 
-> g_01 = E.dpw3Tri AR (xLine KR 2000 20 10 DoNothing) * 0.1
+> g_01 = X.dpw3Tri AR (xLine KR 2000 20 10 DoNothing) * 0.1
 
 very fast sweeps can have transient distortion effects
 
-> g_02 = E.dpw3Tri AR (mouseX KR 200 12000 Exponential 0.2) * 0.2
+> g_02 = X.dpw3Tri AR (mouseX KR 200 12000 Exponential 0.2) * 0.2
 
 compare
 
@@ -21,7 +18,7 @@
 less efficient than LFTri
 
 > g_04 = let f = RDU.randN 50 'α' 50 5000
->        in splay (E.dpw3Tri AR f) 1 0.1 0 True
+>        in splay (X.dpw3Tri AR f) 1 0.1 0 True
 
 > g_05 = let f = RDU.randN 50 'α' 50 5000
 >        in splay (lfTri AR f 0) 1 0.1 0 True
@@ -35,7 +32,7 @@
 differentiation of triangle is square
 
 > g_07 = let f = mouseX KR 440 8800 Exponential 0.2
->            o = E.dpw3Tri AR f
+>            o = X.dpw3Tri AR f
 >        in hpz1 (o * 2) * 0.25
 
 compare
diff --git a/Help/UGen/dpw4Saw.help.lhs b/Help/UGen/dpw4Saw.help.lhs
--- a/Help/UGen/dpw4Saw.help.lhs
+++ b/Help/UGen/dpw4Saw.help.lhs
@@ -1,13 +1,10 @@
-    Sound.SC3.UGen.Help.viewSC3Help "DPW4Saw"
-    Sound.SC3.UGen.DB.ugenSummary "DPW4Saw"
-
 > import Sound.SC3 {- hsc3 -}
-> import qualified Sound.SC3.UGen.Bindings.DB.External as E {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
 
 > import qualified Sound.SC3.UGen.Bindings.DB.RDU as RDU {- sc3-rdu -}
 
-> g_01 = E.dpw4Saw AR (xLine KR 2000 20 10 DoNothing) * 0.1
+> g_01 = X.dpw4Saw AR (xLine KR 2000 20 10 DoNothing) * 0.1
 
-> g_02 = E.dpw4Saw AR (mouseX KR 200 12000 Exponential 0.2) * 0.2
+> g_02 = X.dpw4Saw AR (mouseX KR 200 12000 Exponential 0.2) * 0.2
 
 > g_03 = saw AR (mouseX KR 200 12000 Exponential 0.2) * 0.1
diff --git a/Help/UGen/drand.help.lhs b/Help/UGen/drand.help.lhs
--- a/Help/UGen/drand.help.lhs
+++ b/Help/UGen/drand.help.lhs
@@ -1,11 +1,23 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Drand"
-    > Sound.SC3.UGen.DB.ugenSummary "Drand"
-
 > import Sound.SC3 {- hsc3 -}
->
+
 > g_01 =
 >     let n = drand 'α' dinf (mce [1, 3, 2, 7, 8])
 >         x = mouseX KR 1 400 Exponential 0.1
 >         t = impulse KR x 0
 >         f = demand t 0 n * 30 + 340
 >     in sinOsc AR f 0 * 0.1
+
+> g_02 =
+>   let d = drand 'α' dinf
+>           (mce [dseq 'β' 1 (mce [2, 0, 2, 0, 1, 0, 1, 1])
+>		 ,dseq 'γ' 1 (mce [2, 0, 1, 0, 1, 0, 1, 0])
+>		 ,dseq 'δ' 1 (mce [2, 0, 1, 1, 1, 1, 1, 0])
+>		 ,dseq 'ε' 1 (mce [2, 0.3, 0.3, 1, 0.3, 0.3, 1, 0.3])
+>		 ,dseq 'ζ' 1 (mce [2, 0, 0.3, 0, 0.3, 0, 0.3, 0])
+>		 ,dseq 'η' 1 (mce [2, 0, 0, 1, 0, 0, 0, 0])
+>		 ,dseq 'θ' 1 (mce [2, 0, 0, 0, 0, 0, 0, 0])
+>		 ,dseq 'ι' 1 (mce [0, 1, 0, 1, 0, 1, 0, 1])
+>		 ,dseq 'κ' 1 (mce [1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0])])
+>       t = impulse AR 10 0
+>       x = demand t 0 d * t
+>   in decay x 1 * pinkNoise 'λ' AR * 0.1
diff --git a/Help/UGen/dseq.help.lhs b/Help/UGen/dseq.help.lhs
--- a/Help/UGen/dseq.help.lhs
+++ b/Help/UGen/dseq.help.lhs
@@ -1,11 +1,8 @@
-    Sound.SC3.UGen.Help.viewSC3Help "Dseq"
-    Sound.SC3.UGen.DB.ugenSummary "Dseq"
-
 > import Sound.SC3 {- hsc3 -}
 
 At control rate.
 
-> gr_01 =
+> g_01 =
 >     let n = dseq 'α' 3 (mce [1,3,2,7,8])
 >         x = mouseX KR 1 40 Exponential 0.1
 >         t = impulse KR x 0
@@ -14,7 +11,7 @@
 
 At audio rate.
 
-> gr_02 =
+> g_02 =
 >     let n = dseq 'α' dinf (mce [1,3,2,7,8,32,16,18,12,24])
 >         x = mouseX KR 1 10000 Exponential 0.1
 >         t = impulse AR x 0
@@ -23,7 +20,7 @@
 
 The SC2 Sequencer UGen is somewhat like the sequ function below
 
-> gr_03 =
+> g_03 =
 >     let sequ e s tr = demand tr 0 (dseq e dinf (mce s))
 >         t = impulse AR 6 0
 >         n0 = sequ 'α' [60,62,63,58,48,55] t
diff --git a/Help/UGen/dser.help.lhs b/Help/UGen/dser.help.lhs
--- a/Help/UGen/dser.help.lhs
+++ b/Help/UGen/dser.help.lhs
@@ -1,8 +1,5 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Dser"
-    > Sound.SC3.UGen.DB.ugenSummary "Dser"
-
 > import Sound.SC3 {- hsc3 -}
->
+
 > g_01 =
 >     let a = dser 'α' 7 (mce [1, 3, 2, 7, 8])
 >         x = mouseX KR 1 40 Exponential 0.1
diff --git a/Help/UGen/dseries.help.lhs b/Help/UGen/dseries.help.lhs
--- a/Help/UGen/dseries.help.lhs
+++ b/Help/UGen/dseries.help.lhs
@@ -1,8 +1,5 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Dseries"
-    > Sound.SC3.UGen.DB.ugenSummary "Dseries"
-
 > import Sound.SC3 {- hsc3 -}
->
+
 > g_01 =
 >     let n = dseries 'α' 15 0 1
 >         x = mouseX KR 1 40 Exponential 0.1
diff --git a/Help/UGen/dshuf.help.lhs b/Help/UGen/dshuf.help.lhs
--- a/Help/UGen/dshuf.help.lhs
+++ b/Help/UGen/dshuf.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Dshuf"
-    > Sound.SC3.UGen.DB.ugenSummary "Dshuf"
-
 > import Sound.SC3 {- hsc3 -}
 > import qualified Sound.SC3.UGen.Bindings.DB.RDU as RDU {- sc3-rdu -}
 
diff --git a/Help/UGen/dstutter.help.lhs b/Help/UGen/dstutter.help.lhs
--- a/Help/UGen/dstutter.help.lhs
+++ b/Help/UGen/dstutter.help.lhs
@@ -1,8 +1,5 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Dstutter"
-    > Sound.SC3.UGen.DB.ugenSummary "Dstutter"
-
 > import Sound.SC3 {- hsc3-}
->
+
 > g_01 =
 >     let inp = dseq 'α' dinf (mce [1,2,3])
 >         nse = diwhite 'β' dinf 2 8
@@ -17,10 +14,10 @@
 >     let a z = let xr = dxrand z dinf (mce [0.1,0.2,0.3,0.4,0.5])
 >                   lf = dstutter z 2 xr
 >                   du = duty AR lf 0 DoNothing lf
->                   tr = abs (hpz1 du) >* 0
+>                   tr = abs (hpz1 du) >** 0
 >                   ph = sweep tr (1/du)
 >               in linExp ph 0 1 (rand z 50 100) (rand z 500 2000)
->         f = mce (map a ['a'..'h'])
+>         f = mce (map a (id_seq 8 'α'))
 >         [s0,s1] = mceChannels (splay (sinOsc AR f 0) 1 1 0 True)
 >         o = limiter (rotate2 s0 s1 (lfSaw KR 0.1 0)) 1 1e-2
 >     in o * 0.25
diff --git a/Help/UGen/dswitch.help.lhs b/Help/UGen/dswitch.help.lhs
--- a/Help/UGen/dswitch.help.lhs
+++ b/Help/UGen/dswitch.help.lhs
@@ -1,8 +1,5 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Dswitch"
-    > Sound.SC3.UGen.DB.ugenSummary "Dswitch"
-
 > import Sound.SC3 {- hsc3 -}
->
+
 > mk_g :: UId m => (UGen -> UGen -> m UGen) -> m UGen
 > mk_g sw = do
 >   a0 <- dwhiteM 2 3 4
diff --git a/Help/UGen/dswitch1.help.lhs b/Help/UGen/dswitch1.help.lhs
--- a/Help/UGen/dswitch1.help.lhs
+++ b/Help/UGen/dswitch1.help.lhs
@@ -1,8 +1,5 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Dswitch1"
-    > Sound.SC3.UGen.DB.ugenSummary "Dswitch1"
-
 > import Sound.SC3 {- hsc3 -}
->
+
 > g_01 =
 >     let x = mouseX KR 0 4 Linear 0.1
 >         y = mouseY KR 1 15 Linear 0.1
diff --git a/Help/UGen/dust.help.lhs b/Help/UGen/dust.help.lhs
--- a/Help/UGen/dust.help.lhs
+++ b/Help/UGen/dust.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "Dust"
-    Sound.SC3.UGen.DB.ugenSummary "Dust"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 = dust 'α' AR 2 * 0.25
diff --git a/Help/UGen/dust2.help.lhs b/Help/UGen/dust2.help.lhs
--- a/Help/UGen/dust2.help.lhs
+++ b/Help/UGen/dust2.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "Dust2"
-    Sound.SC3.UGen.DB.ugenSummary "Dust2"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 = dust2 'α' AR 200 * 0.5
diff --git a/Help/UGen/duty.help.lhs b/Help/UGen/duty.help.lhs
--- a/Help/UGen/duty.help.lhs
+++ b/Help/UGen/duty.help.lhs
@@ -1,8 +1,5 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Duty"
-    > Sound.SC3.UGen.DB.ugenSummary "Duty"
-
 > import Sound.SC3 {- hsc3 -}
->
+
 > g_01 :: UId m => m UGen
 > g_01 = do
 >   n0 <- drandM dinf (mce [0.01,0.2,0.4])
diff --git a/Help/UGen/dwhite.help.lhs b/Help/UGen/dwhite.help.lhs
--- a/Help/UGen/dwhite.help.lhs
+++ b/Help/UGen/dwhite.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Dwhite"
-    > Sound.SC3.UGen.DB.ugenSummary "Dwhite"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 =
diff --git a/Help/UGen/dwrand.help.lhs b/Help/UGen/dwrand.help.lhs
--- a/Help/UGen/dwrand.help.lhs
+++ b/Help/UGen/dwrand.help.lhs
@@ -1,8 +1,5 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Dwrand"
-    > Sound.SC3.UGen.DB.ugenSummary "Dwrand"
-
 > import Sound.SC3 {- hsc3 -}
->
+
 > g_01 =
 >     let n = dwrand 'α' dinf (mce [0.3,0.2,0.1,0.2,0.2]) (mce [1,3,2,7,8])
 >         x = mouseX KR 1 400 Exponential 0.1
diff --git a/Help/UGen/dxrand.help.lhs b/Help/UGen/dxrand.help.lhs
--- a/Help/UGen/dxrand.help.lhs
+++ b/Help/UGen/dxrand.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Dxrand"
-    > Sound.SC3.UGen.DB.ugenSummary "Dxrand"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 =
diff --git a/Help/UGen/dynKlang.help.lhs b/Help/UGen/dynKlang.help.lhs
--- a/Help/UGen/dynKlang.help.lhs
+++ b/Help/UGen/dynKlang.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "DynKlang"
-    > Sound.SC3.UGen.DB.ugenSummary "DynKlang"
-
 > import Sound.SC3 {- hsc3 -}
 
 fixed
@@ -23,3 +20,14 @@
 >         a = mce3 0.3 0.3 0.3
 >         p = mce3 pi pi pi
 >     in dynKlang AR 1 0 (klangSpec_mce f a p) * 0.1
+
+-- <https://www.listarc.bham.ac.uk/lists/sc-users/msg66911.html>
+
+> f_04 k =
+>   let f i = (((fromIntegral i ** range_hs (0.3,0.7) (lag (lfNoise0 i KR 1) 0.1)) + 1) * 99
+>             ,max 0 (lfNoise1 i KR (linRand i 0 10 0)))
+>       (frq,amp) = unzip (map f [0::Int .. k - 1])
+>  	s = dynKlang AR 1 0 (klangSpec frq amp (replicate k 0)) * 0.01
+>   in pan2 s 0 1
+
+> g_04 = f_04 16
diff --git a/Help/UGen/dynKlank.help.lhs b/Help/UGen/dynKlank.help.lhs
--- a/Help/UGen/dynKlank.help.lhs
+++ b/Help/UGen/dynKlank.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "DynKlank"
-    > Sound.SC3.UGen.DB.ugenSummary "DynKlank"
-
 > import Sound.SC3 {- hsc3 -}
 
     {s=`[[800,1071,1153,1723],nil,[1,1,1,1]]
diff --git a/Help/UGen/envADSR.help.lhs b/Help/UGen/envADSR.help.lhs
--- a/Help/UGen/envADSR.help.lhs
+++ b/Help/UGen/envADSR.help.lhs
@@ -1,7 +1,4 @@
     Sound.SC3.UGen.Help.viewSC3Help "Env.*adsr"
-    :i Sound.SC3.ADSR
-    :t Sound.SC3.envADSR_r
-    :t Sound.SC3.envADSR
 
 > import Sound.SC3 {- hsc3 -}
 
diff --git a/Help/UGen/envCoord.help.lhs b/Help/UGen/envCoord.help.lhs
--- a/Help/UGen/envCoord.help.lhs
+++ b/Help/UGen/envCoord.help.lhs
@@ -1,5 +1,3 @@
-    :t envCoord
-
 > import Sound.SC3 {- hsc3 -}
 
 co-ordinate (break-point) envelope
diff --git a/Help/UGen/envDetect.help.lhs b/Help/UGen/envDetect.help.lhs
--- a/Help/UGen/envDetect.help.lhs
+++ b/Help/UGen/envDetect.help.lhs
@@ -1,12 +1,9 @@
-    Sound.SC3.UGen.Help.viewSC3Help "EnvDetect"
-    Sound.SC3.UGen.DB.ugenSummary "EnvDetect"
-
 > import Sound.SC3 {- hsc3 -}
-> import Sound.SC3.UGen.Bindings.DB.External {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
 
 > g_01 =
 >     let i = soundIn 0
->         c = envDetect AR i 0.01 0.1
+>         c = X.envDetect AR i 0.01 0.1
 >         p = pitch i 440 60 4000 100 16 1 0.01 0.5 1 0
 >         f = mceChannel 0 p * 3
 >         e = lagUD (mceChannel 1 p) 0 0.1
diff --git a/Help/UGen/envFollow.help.lhs b/Help/UGen/envFollow.help.lhs
--- a/Help/UGen/envFollow.help.lhs
+++ b/Help/UGen/envFollow.help.lhs
@@ -1,12 +1,9 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "EnvFollow"
-    > Sound.SC3.UGen.DB.ugenSummary "EnvFollow"
-
 > import Sound.SC3 {- hsc3 -}
-> import Sound.SC3.UGen.Bindings.DB.External {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
 
 > g_01 =
 >     let z = soundIn 0
 >         d = mouseX KR 0.990 0.999 Linear 0.2
->         c = envFollow KR z d
+>         c = X.envFollow KR z d
 >         o = pinkNoise 'α' AR * c
 >     in mce2 z o
diff --git a/Help/UGen/envGate.help.lhs b/Help/UGen/envGate.help.lhs
--- a/Help/UGen/envGate.help.lhs
+++ b/Help/UGen/envGate.help.lhs
@@ -1,5 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "EnvGate"
-
 > import Sound.SC3 {- hsc3 -}
 
 Make envGate, giving the /default/ arguments, as used by envGate_def.
diff --git a/Help/UGen/envGen.help.lhs b/Help/UGen/envGen.help.lhs
--- a/Help/UGen/envGen.help.lhs
+++ b/Help/UGen/envGen.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "EnvGen"
-    > Sound.SC3.UGen.DB.ugenSummary "EnvGen"
-
 See also help files for the following envelope constructors:
 
 - envADSR
@@ -21,31 +18,31 @@
 env_circle joins the end of the envelope to the start
 
 > e_01 :: Fractional n => Envelope n
-> e_01 = Envelope [6000,700,100] [1,1] [EnvExp,EnvLin] Nothing Nothing 0
+> e_01 = envelope [6000,700,100] [1,1] [EnvExp,EnvLin]
+> a_01 = envelope_sc3_array e_01
 
-    import Sound.SC3.Plot {- hsc3-plot -}
-    plotEnvelope [e_01]
+    > a_01 == Just [6000,2,-99,-99,700,1,2,0,100,1,1,0]
+    > import Sound.SC3.Plot {- hsc3-plot -}
+    > plotEnvelope [e_01]
 
-> e_01_c :: Fractional n => Envelope n
-> e_01_c = env_circle_0 e_01
+{var e = Env([6000,700,100],[1,1],['exp','lin'])
+;var e_c = Env([6000,700,100],[1,1],['exp','lin']).circle(1,\lin)
+;e.asArray.postln
+;e_c.asArray.postln
+;SinOsc.ar(e_c.kr,0) * 0.1}.draw
 
-    plotEnvelope [e_01_c]
+> e_01_c :: Fractional t => Envelope t
+> e_01_c = env_circle_z 0 1 EnvLin e_01
+> a_01_c = envelope_sc3_array e_01_c
 
+    > a_01_c == Just [0,4,3,0,6000,0,1,0,700,1,2,0,100,1,1,0,0,1,1,0]
+    > plotEnvelope [e_01_c]
+
 > g_01 =
 >     let f = envGen KR 1 1 0 1 DoNothing e_01_c
 >     in sinOsc AR f 0 * 0.1 + impulse AR 1 0
 
-Env([6000,700,100],[1,1],['exp','lin']).circle.asArray == [6000,2,-99,-99,700,1,2,0,100,1,1,0]
-
-    > r = [0,4,3,0,6000,0,1,0,700,1,2,0,100,1,1,0,0,9e8,1,0]
-    > envelope_sc3_array (env_circle e_01 0 EnvLin) == Just r
-
-Env([0,1],[0.1]).asArray == [0,1,-99,-99,1,0.1,1,0]
-
-    > e = Envelope [0,1] [0.1] [EnvLin] Nothing Nothing 0
-    > envelope_sc3_array e == Just [0,1,-99,-99,1,0.1,1,0]
-
-https://www.listarc.bham.ac.uk/lists/sc-users/msg14815.html
+<https://www.listarc.bham.ac.uk/lists/sc-users/msg14815.html>
 
 > e_02 =
 >   let n = range 0.01 0.15 (lfNoise1 'α' KR 2)
@@ -67,7 +64,13 @@
     plotEnvelope [e_03]
 
 > f_03 rt ts = sinOsc rt 0 (envGen rt 1 1 0 ts DoNothing e_03_c)
-
 > g_03 = soundIn 0 * range 0.25 1 (f_03 KR 2)
 
    plot_ugen 0.1 (f_03 AR 0.1)
+
+Env([0,1],[0.1]).asArray == [0,1,-99,-99,1,0.1,1,0]
+
+> e_04 = envelope [0,1] [0.1] [EnvLin]
+> a_04 = envelope_sc3_array e_04
+
+    a_04 == Just [0,1,-99,-99,1,0.1,1,0]
diff --git a/Help/UGen/envLinen.help.lhs b/Help/UGen/envLinen.help.lhs
--- a/Help/UGen/envLinen.help.lhs
+++ b/Help/UGen/envLinen.help.lhs
@@ -1,6 +1,5 @@
     Sound.SC3.UGen.Help.viewSC3Help "Env.*linen"
     :i Sound.SC3.LINEN
-    :t envLinen
 
 > import Sound.SC3 {- hsc3 -}
 
diff --git a/Help/UGen/envPairs.help.lhs b/Help/UGen/envPairs.help.lhs
--- a/Help/UGen/envPairs.help.lhs
+++ b/Help/UGen/envPairs.help.lhs
@@ -1,5 +1,4 @@
-    Sound.SC3.UGen.Help.viewSC3Help "Env.*pairs"
-    :t envPairs
+    Sound.SC3.Lang.Help.viewSC3Help "Env.*pairs"
 
 > import Sound.SC3 {- hsc3 -}
 
diff --git a/Help/UGen/envPerc.help.lhs b/Help/UGen/envPerc.help.lhs
--- a/Help/UGen/envPerc.help.lhs
+++ b/Help/UGen/envPerc.help.lhs
@@ -1,5 +1,4 @@
     Sound.SC3.UGen.Help.viewSC3Help "Env.*perc"
-    :t envPerc'
 
 > import Sound.SC3 {- hsc3 -}
 
diff --git a/Help/UGen/envSine.help.lhs b/Help/UGen/envSine.help.lhs
--- a/Help/UGen/envSine.help.lhs
+++ b/Help/UGen/envSine.help.lhs
@@ -1,5 +1,4 @@
     Sound.SC3.UGen.Help.viewSC3Help "Env.*sine"
-    :t Sound.SC3.envSine
 
 > import Sound.SC3 {- hsc3 -}
 
diff --git a/Help/UGen/envStep.help.lhs b/Help/UGen/envStep.help.lhs
--- a/Help/UGen/envStep.help.lhs
+++ b/Help/UGen/envStep.help.lhs
@@ -1,5 +1,4 @@
     Sound.SC3.UGen.Help.viewSC3Help "Env.*step"
-    :i Sound.SC3.envStep
 
 > import Sound.SC3 {- hsc3 -}
 
diff --git a/Help/UGen/envTrapezoid.help.lhs b/Help/UGen/envTrapezoid.help.lhs
--- a/Help/UGen/envTrapezoid.help.lhs
+++ b/Help/UGen/envTrapezoid.help.lhs
@@ -1,5 +1,3 @@
-    :t Sound.SC3.envTrapezoid
-
 > import Sound.SC3
 
 > g_01 =
diff --git a/Help/UGen/envTriangle.help.lhs b/Help/UGen/envTriangle.help.lhs
--- a/Help/UGen/envTriangle.help.lhs
+++ b/Help/UGen/envTriangle.help.lhs
@@ -1,5 +1,4 @@
     Sound.SC3.UGen.Help.viewSC3Help "Env.*triangle"
-    :t envTriangle
 
 > import Sound.SC3 {- hsc3 -}
 
diff --git a/Help/UGen/envXYC.help.lhs b/Help/UGen/envXYC.help.lhs
--- a/Help/UGen/envXYC.help.lhs
+++ b/Help/UGen/envXYC.help.lhs
@@ -1,5 +1,4 @@
     Sound.SC3.UGen.Help.viewSC3Help "Env.*xyc"
-    :t Sound.SC3.envXYC
 
 > import Sound.SC3 {- hsc3 -}
 
diff --git a/Help/UGen/equal_to.help.lhs b/Help/UGen/equal_to.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/equal_to.help.lhs
@@ -0,0 +1,18 @@
+The star suffixes (==**,/=**,<**,<=**,>**,>=**) are because the result of the
+operators is not of type Bool, as is required by the signature for the
+classes Eq and Ord.
+
+> import Sound.SC3 {- hsc3 -}
+
+> g_01 =
+>     let o = sinOsc KR 1 0
+>         t = [o >** 0
+>             ,o >=** 0
+>             ,o <** 0
+>             ,o <=** 0
+>             ,o ==** 0
+>             ,(o <** 0.001) * (o >** (-0.001))]
+>         f = [220, 330, 440, 550, 660, 770]
+>         p = envPerc 0.01 1
+>         e = envGen KR (mce t) 0.1 0 1 DoNothing p
+>     in mix (sinOsc AR (mce f) 0 * e)
diff --git a/Help/UGen/excess.help.lhs b/Help/UGen/excess.help.lhs
--- a/Help/UGen/excess.help.lhs
+++ b/Help/UGen/excess.help.lhs
@@ -1,8 +1,5 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Operator.excess"
-    > :t excess
-
 > import Sound.SC3 {- hsc3 -}
->
+
 > g_01 =
 >     let o = fSinOsc AR 1000 0
 >         l = line KR 0 1 8 DoNothing
diff --git a/Help/UGen/expRand.help.lhs b/Help/UGen/expRand.help.lhs
--- a/Help/UGen/expRand.help.lhs
+++ b/Help/UGen/expRand.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "ExpRand"
-    > Sound.SC3.UGen.DB.ugenSummary "ExpRand"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 =
diff --git a/Help/UGen/fSinOsc.help.lhs b/Help/UGen/fSinOsc.help.lhs
--- a/Help/UGen/fSinOsc.help.lhs
+++ b/Help/UGen/fSinOsc.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "FSinOsc"
-    > Sound.SC3.UGen.DB.ugenSummary "FSinOsc"
-
 Note: SC2 did not have the initial phase argument.
 
 > import Sound.SC3 {- hsc3 -}
diff --git a/Help/UGen/fbSineC.help.lhs b/Help/UGen/fbSineC.help.lhs
--- a/Help/UGen/fbSineC.help.lhs
+++ b/Help/UGen/fbSineC.help.lhs
@@ -1,12 +1,14 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "FBSineC"
-    > Sound.SC3.UGen.DB.ugenSummary "FBSineC"
-
 > import Sound.SC3 {- hsc3 -}
+> import Sound.SC3.Common.Math.Noise {- hsc3 -}
 
 SC3 default values.
 
-> g_01 = fbSineC AR (sampleRate / 4) 1 0.1 1.1 0.5 0.1 0.1 * 0.2
+> g_00 = fbSineC AR (sampleRate / 2) 1 0.1 1.1 0.5 0.1 0.1 * 0.2
 
+FB generating noise
+
+> g_01 = fbSineC AR (sampleRate / 2) 1 4 1.1 0.5 0.1 0.1 * 0.2
+
 Increase feedback
 
 > g_02 =
@@ -22,12 +24,19 @@
 Randomly modulate parameters
 
 > g_04 =
->     let madd a m = (+ a) . (* m)
->         x = mouseX KR 1 12 Linear 0.1
+>     let x = mouseX KR 1 12 Linear 0.1
 >         n e = lfNoise2 e KR x
->         n0 = madd 1e4 1e4 (n 'α')
->         n1 = madd 33 32 (n 'β')
->         n2 = madd 0 0.5 (n 'γ')
->         n3 = madd 1.05 0.05 (n 'δ')
->         n4 = madd 0.3 0.3 (n 'ε')
+>         n0 = n 'α' * 1e4 + 1e4
+>         n1 = n 'β' * 32 + 33
+>         n2 = n 'γ' * 0.5
+>         n3 = n 'δ' * 0.05 + 1.05
+>         n4 = n 'ε' * 0.3 + 0.3
 >     in fbSineC AR n0 n1 n2 n3 n4 0.1 0.1 * 0.2
+
+Haskell implementation of equation.
+
+> fbSineC_hs im fb a c = map fst (iterate (fbSine_f im fb a c) (0.1,0.1))
+
+    import Sound.SC3.Plot {- hsc3-plot -}
+    plotTable1 (take 600 (fbSineC_hs 1.0 4.0 1.1 0.5))
+    plot_ugen_nrt (600,1) 1.0 (fbSineC AR 600 1.0 4.0 1.1 0.5 0.1 0.1)
diff --git a/Help/UGen/fdiv.help.lhs b/Help/UGen/fdiv.help.lhs
--- a/Help/UGen/fdiv.help.lhs
+++ b/Help/UGen/fdiv.help.lhs
@@ -1,8 +1,5 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Operator./"
-    > :t (/)
-
 > import Sound.SC3 {- hsc3 -}
->
+
 > g_01 =
 >     let o = fSinOsc KR 10 0.5
 >         n = pinkNoise 'α' AR
diff --git a/Help/UGen/fft.help.lhs b/Help/UGen/fft.help.lhs
--- a/Help/UGen/fft.help.lhs
+++ b/Help/UGen/fft.help.lhs
@@ -1,5 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "FFT"
-    Sound.SC3.UGen.DB.ugenSummary "FFT"
     :t fft'
 
 > import Sound.SC3 {- hsc3 -}
diff --git a/Help/UGen/fftTrigger.help.lhs b/Help/UGen/fftTrigger.help.lhs
--- a/Help/UGen/fftTrigger.help.lhs
+++ b/Help/UGen/fftTrigger.help.lhs
@@ -1,2 +1,1 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "FFTTrigger"
-    > Sound.SC3.UGen.DB.ugenSummary "FFTTrigger"
+See example at packFFT
diff --git a/Help/UGen/fm7.help.lhs b/Help/UGen/fm7.help.lhs
--- a/Help/UGen/fm7.help.lhs
+++ b/Help/UGen/fm7.help.lhs
@@ -1,8 +1,5 @@
-    Sound.SC3.UGen.Help.viewSC3Help "FM7"
-    Sound.SC3.UGen.DB.ugenSummary "FM7"
-
 > import Sound.SC3 {- hsc3 -}
-> import qualified Sound.SC3.UGen.Bindings.DB.External as E {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.Composite.External as X {- hsc3 -}
 
 two of six...
 
@@ -19,7 +16,7 @@
 >             ,[0,0,0,0,0,0]
 >             ,[0,0,0,0,0,0]
 >             ,[0,0,0,0,0,0] ]
->         [l,r,_,_,_,_] = mceChannels (fm7_mx c m)
+>         [l,r,_,_,_,_] = mceChannels (X.fm7_mx c m)
 >     in mce2 l r * 0.1
 
 An algorithmically generated graph courtesy f0.
@@ -81,7 +78,7 @@
 >              ,[1.0,0.5,-1/6,0.5]]]
 >         cs = map (map (\[f,p,m,a] -> sinOsc AR f p * m + a)) x
 >         ms = map (map (\[f,w,m,a] -> pulse AR f w * m + a)) y
->         [c1,c2,c3,c4,c5,c6] = mceChannels (fm7_mx cs ms)
+>         [c1,c2,c3,c4,c5,c6] = mceChannels (X.fm7_mx cs ms)
 >         g3 = linLin (lfSaw KR 0.1 0) (-1) 1 0 (dbAmp (-12))
 >         g6 = dbAmp (-3)
 >     in mce [c1 + c3 * g3 + c5,c2 + c4 + c6 * g6]
diff --git a/Help/UGen/fmGrain.help.lhs b/Help/UGen/fmGrain.help.lhs
--- a/Help/UGen/fmGrain.help.lhs
+++ b/Help/UGen/fmGrain.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "FMGrain"
-    > Sound.SC3.UGen.DB.ugenSummary "FMGrain"
-
 > import Sound.SC3 {- hsc3 -}
 > import Sound.SC3.UGen.Bindings.DB.External {- hsc3 -}
 
diff --git a/Help/UGen/fmGrainB.help.lhs b/Help/UGen/fmGrainB.help.lhs
--- a/Help/UGen/fmGrainB.help.lhs
+++ b/Help/UGen/fmGrainB.help.lhs
@@ -1,8 +1,5 @@
-    Sound.SC3.UGen.Help.viewSC3Help "FMGrainB"
-    Sound.SC3.UGen.DB.ugenSummary "FMGrainB"
-
 > import Sound.SC3 {- hsc3 -}
-> import Sound.SC3.UGen.Bindings.DB.External {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
 
 > m_01 =
 >   [b_alloc 10 512 1
@@ -15,4 +12,4 @@
 >       n = linLin (lfNoise1 'α' KR 1) (-1) 1 1 10
 >       s = envSine 9 0.1
 >       e = envGen KR 1 1 0 1 RemoveSynth s
->   in fmGrainB t 0.2 440 220 n 10 * e
+>   in X.fmGrainB t 0.2 440 220 n 10 * e
diff --git a/Help/UGen/fold2.help.lhs b/Help/UGen/fold2.help.lhs
--- a/Help/UGen/fold2.help.lhs
+++ b/Help/UGen/fold2.help.lhs
@@ -1,8 +1,5 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Operator.fold2"
-    > :t fold2
-
 > import Sound.SC3 {- hsc3 -}
->
+
 > g_01 =
 >     let o = fSinOsc AR 1000 0
 >         l = line KR 0 1 8 DoNothing
diff --git a/Help/UGen/formant.help.lhs b/Help/UGen/formant.help.lhs
--- a/Help/UGen/formant.help.lhs
+++ b/Help/UGen/formant.help.lhs
@@ -1,7 +1,4 @@
-    Sound.SC3.UGen.Help.viewSC3Help "Formant"
-    Sound.SC3.UGen.DB.ugenSummary "Formant"
-
-> import Sound.SC3
+> import Sound.SC3 {- hsc3 -}
 
 Default values
 
diff --git a/Help/UGen/formlet.help.lhs b/Help/UGen/formlet.help.lhs
--- a/Help/UGen/formlet.help.lhs
+++ b/Help/UGen/formlet.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Formlet"
-    > Sound.SC3.UGen.DB.ugenSummary "Formlet"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 = formlet (impulse AR 20 0.5) 1000 0.01 0.1
diff --git a/Help/UGen/free.help.lhs b/Help/UGen/free.help.lhs
--- a/Help/UGen/free.help.lhs
+++ b/Help/UGen/free.help.lhs
@@ -1,10 +1,7 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Free"
-    > Sound.SC3.UGen.DB.ugenSummary "Free"
-
 > import Sound.SC3 {- hsc3 -}
->
+
 > g_01 = out 0 (sinOsc AR 880 0 * 0.1)
->
+
 > g_02 =
 >     let n0 = pinkNoise 'α' AR
 >         n1 = dust 'β' KR 20
diff --git a/Help/UGen/freeSelf.help.lhs b/Help/UGen/freeSelf.help.lhs
--- a/Help/UGen/freeSelf.help.lhs
+++ b/Help/UGen/freeSelf.help.lhs
@@ -1,8 +1,5 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "FreeSelf"
-    > Sound.SC3.UGen.DB.ugenSummary "FreeSelf"
-
 > import Sound.SC3 {- hsc3 -}
->
+
 > g_01 =
 >     let n = dust 'α' KR 0.5
 >     in mrg [sinOsc AR 440 0 * 0.1,freeSelf n]
diff --git a/Help/UGen/freeSelfWhenDone.help.lhs b/Help/UGen/freeSelfWhenDone.help.lhs
--- a/Help/UGen/freeSelfWhenDone.help.lhs
+++ b/Help/UGen/freeSelfWhenDone.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "FreeSelfWhenDone"
-    > Sound.SC3.UGen.DB.ugenSummary "FreeSelfWhenDone"
-
 > import Sound.SC3 {- hsc3 -}
 
 using RemoveSynth doneAction
diff --git a/Help/UGen/freeVerb.help.lhs b/Help/UGen/freeVerb.help.lhs
--- a/Help/UGen/freeVerb.help.lhs
+++ b/Help/UGen/freeVerb.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "FreeVerb"
-    > Sound.SC3.UGen.DB.ugenSummary "FreeVerb"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 =
diff --git a/Help/UGen/freqShift.help.lhs b/Help/UGen/freqShift.help.lhs
--- a/Help/UGen/freqShift.help.lhs
+++ b/Help/UGen/freqShift.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "FreqShift"
-    Sound.SC3.UGen.DB.ugenSummary "FreqShift"
-
 > import Sound.SC3 {- hcs3 -}
 
 Shifting a 100Hz tone by 1 Hz rising to 500Hz
diff --git a/Help/UGen/gVerb.help.lhs b/Help/UGen/gVerb.help.lhs
--- a/Help/UGen/gVerb.help.lhs
+++ b/Help/UGen/gVerb.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "GVerb"
-    > Sound.SC3.UGen.DB.ugenSummary "GVerb"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 =
diff --git a/Help/UGen/gate.help.lhs b/Help/UGen/gate.help.lhs
--- a/Help/UGen/gate.help.lhs
+++ b/Help/UGen/gate.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "Gate"
-    Sound.SC3.UGen.DB.ugenSummary "Gate"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 =
diff --git a/Help/UGen/gaussTrig.help.lhs b/Help/UGen/gaussTrig.help.lhs
--- a/Help/UGen/gaussTrig.help.lhs
+++ b/Help/UGen/gaussTrig.help.lhs
@@ -1,12 +1,9 @@
-    Sound.SC3.UGen.Help.viewSC3Help "GaussTrig"
-    Sound.SC3.UGen.DB.ugenSummary "GaussTrig"
-
 > import Sound.SC3 {- hsc3 -}
-> import Sound.SC3.UGen.Bindings.DB.External {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
 
 > g_01 =
 >   let x = mouseX KR 0 0.9 Linear 0.2
->       t1 = gaussTrig KR 10 x * abs (whiteNoise 'α' KR) * 0.5
+>       t1 = X.gaussTrig KR 10 x * abs (whiteNoise 'α' KR) * 0.5
 >       t2 = dust 'β' KR 10 * 0.5
 >       n = pinkNoise 'γ' AR * decay (mce2 t1 t2) 0.02 * 0.5
 >   in fold2 (ringz n 2000 0.02) 0.5
diff --git a/Help/UGen/gbmanN.help.lhs b/Help/UGen/gbmanN.help.lhs
--- a/Help/UGen/gbmanN.help.lhs
+++ b/Help/UGen/gbmanN.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "GbmanN"
-    Sound.SC3.UGen.DB.ugenSummary "GbmanN"
-
 > import Sound.SC3 {- hsc3 -}
 
 default initial params
diff --git a/Help/UGen/gendy1.help.lhs b/Help/UGen/gendy1.help.lhs
--- a/Help/UGen/gendy1.help.lhs
+++ b/Help/UGen/gendy1.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Gendy1"
-    > Sound.SC3.UGen.DB.ugenSummary "Gendy1"
-
 > import Data.Char {- base -}
 > import Sound.SC3 {- base -}
 
@@ -93,17 +90,17 @@
 
 > g_14 =
 >     let node e = let f = rand e 130 160.3
->                      r0 = rand e 0 6
->                      r1 = rand (toUpper e) 0 6
+>                      r0 = rand ('α',e) 0 6
+>                      r1 = rand ('β',e) 0 6
 >                      l = rand e (-1) 1
 >                      ad = sinOsc KR 0.10 0 * 0.49 + 0.51
 >                      dd = sinOsc KR 0.13 0 * 0.49 + 0.51
 >                      as = sinOsc KR 0.17 0 * 0.49 + 0.51
 >                      ds = sinOsc KR 0.19 0 * 0.49 + 0.51
->                      g = gendy1 'α' AR r0 r1 ad dd f f as ds 12 12
+>                      g = gendy1 'γ' AR r0 r1 ad dd f f as ds 12 12
 >                      o = sinOsc AR (g * 200 + 400) 0
 >                  in pan2 o l 0.1
->     in mix (mce (map node (take 10 (enumFrom 'β'))))
+>     in mix (mce (map node (id_seq 10 'δ')))
 
 Try durscale 10.0 and 0.0 too.
 
diff --git a/Help/UGen/grainBuf.help.lhs b/Help/UGen/grainBuf.help.lhs
--- a/Help/UGen/grainBuf.help.lhs
+++ b/Help/UGen/grainBuf.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "GrainBuf"
-    Sound.SC3.UGen.DB.ugenSummary "GrainBuf"
-
 > import Sound.SC3 {- hsc3 -}
 
 > fn_01 = "/home/rohan/data/audio/pf-c5.snd"
diff --git a/Help/UGen/grainFM.help.lhs b/Help/UGen/grainFM.help.lhs
--- a/Help/UGen/grainFM.help.lhs
+++ b/Help/UGen/grainFM.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "GrainFM"
-    Sound.SC3.UGen.DB.ugenSummary "GrainFM"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 =
diff --git a/Help/UGen/grainIn.help.lhs b/Help/UGen/grainIn.help.lhs
--- a/Help/UGen/grainIn.help.lhs
+++ b/Help/UGen/grainIn.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "GrainIn"
-    Sound.SC3.UGen.DB.ugenSummary "GrainIn"
-
 > import Sound.SC3 {- hsc3 -}
 
 > f_01 s =
diff --git a/Help/UGen/grainSin.help.lhs b/Help/UGen/grainSin.help.lhs
--- a/Help/UGen/grainSin.help.lhs
+++ b/Help/UGen/grainSin.help.lhs
@@ -1,8 +1,5 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "GrainSin"
-    > Sound.SC3.UGen.DB.ugenSummary "GrainSin"
-
 > import Sound.SC3 {- hsc3 -}
->
+
 > g_01 =
 >     let n = whiteNoise 'α' KR
 >         x = mouseX KR (-0.5) 0.5 Linear 0.1
@@ -10,3 +7,18 @@
 >         f = n * y + 440
 >         t = impulse KR 10 0
 >     in grainSin 2 t 0.1 f x (-1) 512 * 0.1
+
+-- <https://www.listarc.bham.ac.uk/lists/sc-users/msg66911.html>
+
+> f_02 k =
+>   let t = impulse AR (mouseY KR 1 999 Linear 0.2) 0
+>	f i = ((fromIntegral i ** range_hs (0.3,0.7) (lfNoise0 i KR 1)) + 1) * 99
+>       l = mce (map f [0::Int .. k - 1])
+>   in grainSin 2 t (mouseX KR 0.001 0.5 Exponential 0.2) (tChoose 'α' t l) 0 (-1) 512 * 0.01
+
+> g_02 = f_02 16
+
+> g_03 =
+>   let (s1,s2) = unmce2 g_02
+>   in freeVerb2 s1 s2 0.9 0.1 0.5
+
diff --git a/Help/UGen/grayNoise.help.lhs b/Help/UGen/grayNoise.help.lhs
--- a/Help/UGen/grayNoise.help.lhs
+++ b/Help/UGen/grayNoise.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "GrayNoise"
-    > Sound.SC3.UGen.DB.ugenSummary "GrayNoise"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 = grayNoise 'α' AR * 0.1
diff --git a/Help/UGen/greater_than.help.lhs b/Help/UGen/greater_than.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/greater_than.help.lhs
@@ -0,0 +1,2 @@
+See equal_to
+
diff --git a/Help/UGen/greyholeRaw.help.lhs b/Help/UGen/greyholeRaw.help.lhs
--- a/Help/UGen/greyholeRaw.help.lhs
+++ b/Help/UGen/greyholeRaw.help.lhs
@@ -1,11 +1,8 @@
-    Sound.SC3.UGen.Help.viewSC3Help "GreyholeRaw"
-    Sound.SC3.UGen.DB.ugenSummary "GreyholeRaw"
-
 > import Sound.SC3 {- hsc3 -}
-> import qualified Sound.SC3.UGen.Bindings.DB.External as External {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
 
 default values
 
 > g_01 =
 >   let (i1,i2) = (soundIn 0,soundIn 1)
->   in External.greyholeRaw i1 i2 0.0 2.0 0.5 0.9 0.1 2.0 1.0
+>   in X.greyholeRaw i1 i2 0.0 2.0 0.5 0.9 0.1 2.0 1.0
diff --git a/Help/UGen/gt.help.lhs b/Help/UGen/gt.help.lhs
deleted file mode 100644
--- a/Help/UGen/gt.help.lhs
+++ /dev/null
@@ -1,22 +0,0 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Operator.=="
-    > :t (==*)
-
-The star suffixes (<*,<=*,>*,>=*) are because the result of the
-operators is not of type Bool, as is required by the signature for the
-class Ord.  At some point `<*` was written into the standard prelude...
-
-> import Prelude hiding ((<*)) {- base -}
-> import Sound.SC3 {- hsc3 -}
->
-> g_01 =
->     let o = sinOsc KR 1 0
->         t = [o >* 0
->             ,o >=* 0
->             ,o <* 0
->             ,o <=* 0
->             ,o ==* 0
->             ,(o <* 0.001) * (o >* (-0.001))]
->         f = [220, 330, 440, 550, 660, 770]
->         p = envPerc 0.01 1
->         e = envGen KR (mce t) 0.1 0 1 DoNothing p
->     in mix (sinOsc AR (mce f) 0 * e)
diff --git a/Help/UGen/hasher.help.lhs b/Help/UGen/hasher.help.lhs
--- a/Help/UGen/hasher.help.lhs
+++ b/Help/UGen/hasher.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "Hasher"
-    Sound.SC3.UGen.DB.ugenSummary "Hasher"
-
 > import Sound.SC3 {- hsc3 -}
 
 noise
diff --git a/Help/UGen/henonN.help.lhs b/Help/UGen/henonN.help.lhs
--- a/Help/UGen/henonN.help.lhs
+++ b/Help/UGen/henonN.help.lhs
@@ -1,7 +1,5 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "HenonN"
-    > Sound.SC3.UGen.DB.ugenSummary "HenonN"
-
 > import Sound.SC3 {- hsc3 -}
+> import Sound.SC3.Common.Math.Noise {- hsc3 -}
 
 With SC3 default initial parameters.
 
@@ -38,3 +36,11 @@
     > plot_ugen1 0.1 (henonN AR 2500 1.4 0.3 0 0 * 0.1)
 
 ![](sw/hsc3/Help/SVG/henonN.0.svg)
+
+In haskell:
+
+> henon_hs a b = map snd (iterate (henon_f a b) (0.0,0.0))
+
+    import Sound.SC3.Plot {- hsc3-plot -}
+    plotTable1 (take 600 (henon_hs 1.4 0.3))
+    plot_ugen_nrt (600,1) 1.0 (henonN AR 600 1.4 0.3 0 0)
diff --git a/Help/UGen/hilbertFIR.help.lhs b/Help/UGen/hilbertFIR.help.lhs
--- a/Help/UGen/hilbertFIR.help.lhs
+++ b/Help/UGen/hilbertFIR.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "HilbertFIR"
-    Sound.SC3.UGen.DB.ugenSummary "HilbertFIR"
-
 > import Sound.SC3 {- hsc3 -}
 
 composite UGen
diff --git a/Help/UGen/hpf.help.lhs b/Help/UGen/hpf.help.lhs
--- a/Help/UGen/hpf.help.lhs
+++ b/Help/UGen/hpf.help.lhs
@@ -1,8 +1,5 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "HPF"
-    > Sound.SC3.UGen.DB.ugenSummary "HPF"
-
 > import Sound.SC3 {- hsc3 -}
->
+
 > g_01 =
 >     let f = fSinOsc KR (xLine KR 0.7 300 20 RemoveSynth) 0 * 3600 + 4000
 >     in hpf (saw AR 200 * 0.2) f
diff --git a/Help/UGen/hpz1.help.lhs b/Help/UGen/hpz1.help.lhs
--- a/Help/UGen/hpz1.help.lhs
+++ b/Help/UGen/hpz1.help.lhs
@@ -1,19 +1,16 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "HPZ1"
-    > Sound.SC3.UGen.DB.ugenSummary "HPZ1"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 = let n = whiteNoise 'α' AR in hpz1 (n * 0.25)
 
-    import Sound.SC3.Plot.FFT {- hsc3-plot -}
-    plot_ugen_fft1 0.05 (hpz1 (whiteNoise 'α' AR))
+    > import Sound.SC3.Plot.FFT {- hsc3-plot -}
+    > plot_ugen_fft1 0.05 (hpz1 (whiteNoise 'α' AR))
 
 detect changes in a signal (see also hpz2)
 
 > g_02 =
->   let n = lfNoise0 'a' AR 1000
+>   let n = lfNoise0 'α' AR 1000
 >       h = hpz1 n
->   in mce [h,h >* 0,abs h >* 0]
+>   in mce [h,h >** 0,abs h >** 0]
 
-    import Sound.SC3.Plot {- hsc3-plot -}
-    plot_ugen 0.01 g_02
+    > import Sound.SC3.Plot {- hsc3-plot -}
+    > plot_ugen 0.01 g_02
diff --git a/Help/UGen/hpz2.help.lhs b/Help/UGen/hpz2.help.lhs
--- a/Help/UGen/hpz2.help.lhs
+++ b/Help/UGen/hpz2.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "HPZ2"
-    Sound.SC3.UGen.DB.ugenSummary "HPZ2"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 =
diff --git a/Help/UGen/hypot.help.lhs b/Help/UGen/hypot.help.lhs
--- a/Help/UGen/hypot.help.lhs
+++ b/Help/UGen/hypot.help.lhs
@@ -1,8 +1,5 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Operator.hypot"
-    > :t hypot
-
 > import Sound.SC3 {- hsc3 -}
->
+
 > g_01 =
 >     let x = mouseX KR 0 0.1 Linear 0.1
 >         y = mouseY KR 0 0.1 Linear 0.1
@@ -15,11 +12,11 @@
 >     let x = 10
 >         y = lfSaw KR (1 / 6) 0 * 100
 >         d = hypot x y
+>         a = 10 / (squared d)
 >         v = slope d
 >         r = (344 - v) / 344
->         a = 10 / (squared d)
 >     in fSinOsc AR (1000 * r) 0 * a
->
+
 > g_03 =
 >     let x = 10
 >         y = lfSaw KR (1 / 6) 0 * 100
diff --git a/Help/UGen/iEnvGen.help.lhs b/Help/UGen/iEnvGen.help.lhs
--- a/Help/UGen/iEnvGen.help.lhs
+++ b/Help/UGen/iEnvGen.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "IEnvGen"
-    Sound.SC3.UGen.DB.ugenSummary "IEnvGen"
-
 > import Sound.SC3 {- hsc3 -}
 
 > e_01 :: (Fractional n,Ord n) => Envelope n
diff --git a/Help/UGen/iRand.help.lhs b/Help/UGen/iRand.help.lhs
--- a/Help/UGen/iRand.help.lhs
+++ b/Help/UGen/iRand.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "IRand"
-    Sound.SC3.UGen.DB.ugenSummary "IRand"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 =
diff --git a/Help/UGen/ifft.help.lhs b/Help/UGen/ifft.help.lhs
--- a/Help/UGen/ifft.help.lhs
+++ b/Help/UGen/ifft.help.lhs
@@ -1,5 +1,1 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "IFFT"
-    > Sound.SC3.UGen.DB.ugenSummary "IFFT"
-    > :t ifft'
-
 # ifft' is a variant with the default window type and size
diff --git a/Help/UGen/iirFilter.help.lhs b/Help/UGen/iirFilter.help.lhs
--- a/Help/UGen/iirFilter.help.lhs
+++ b/Help/UGen/iirFilter.help.lhs
@@ -1,13 +1,10 @@
-    Sound.SC3.UGen.Help.viewSC3Help "IIRFilter"
-    Sound.SC3.UGen.DB.ugenSummary "IIRFilter"
-
 > import Sound.SC3 {- hsc3 -}
-> import Sound.SC3.UGen.Bindings.DB.External {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
 
 > g_01 =
 >   let x = mouseX KR 20 12000 Exponential 0.2
 >       y = mouseY KR 0.01 1 Linear 0.2
 >       o = lfSaw AR (mce [x * 0.99,x * 1.01]) 0 * 0.1
 >       freq = sinOsc KR (sinOsc KR 0.1 0) (1.5 * pi) * 1550 + 1800
->       s = iirFilter o freq y
+>       s = X.iirFilter o freq y
 >   in combN s 0.5 (mce2 0.4 0.35) 2 * 0.4 + s * 0.5
diff --git a/Help/UGen/impulse.help.lhs b/Help/UGen/impulse.help.lhs
--- a/Help/UGen/impulse.help.lhs
+++ b/Help/UGen/impulse.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Impulse"
-    > Sound.SC3.UGen.DB.ugenSummary "Impulse"
-
 Note: SC2 had no phase input.
 
 > import Sound.SC3 {- hsc3 -}
diff --git a/Help/UGen/in.help.lhs b/Help/UGen/in.help.lhs
--- a/Help/UGen/in.help.lhs
+++ b/Help/UGen/in.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "In"
-    > Sound.SC3.UGen.DB.ugenSummary "In"
-
 Note: `hsc3` renames UGen to `in'` since `in` is a reserved keyword
 
 > import Sound.OSC {- hosc -}
@@ -55,3 +52,7 @@
 Audio rate graph reading control buses 0 & 1.
 
 > g_07 = sinOsc AR (in' 1 KR 0) 0 * decay (in' 1 KR 1) 0.2 * 0.1
+
+Patch mono input to stereo output
+
+> g_08 = pan2 (in' 1 AR numOutputBuses) 0 1
diff --git a/Help/UGen/inFeedback.help.lhs b/Help/UGen/inFeedback.help.lhs
--- a/Help/UGen/inFeedback.help.lhs
+++ b/Help/UGen/inFeedback.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "InFeedback"
-    Sound.SC3.UGen.DB.ugenSummary "InFeedback"
-
 > import Sound.SC3 {- hsc3 -}
 
 Audio feedback modulation
diff --git a/Help/UGen/inRange.help.lhs b/Help/UGen/inRange.help.lhs
--- a/Help/UGen/inRange.help.lhs
+++ b/Help/UGen/inRange.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "InRange"
-    > Sound.SC3.UGen.DB.ugenSummary "InRange"
-
 > import Sound.SC3 {- hsc3 -}
 
 trigger noise burst
@@ -10,3 +7,7 @@
 >         x = mouseX KR 1 2 Linear 0.1
 >         o = sinOsc KR x 0 * 0.2
 >     in inRange o (-0.15) 0.15 * n
+
+i-rate...
+
+> g_02 = sinOsc AR 440 0 * inRange (rand 'α' 0 1) 0.5 1.0 * 0.1
diff --git a/Help/UGen/inTrig.help.lhs b/Help/UGen/inTrig.help.lhs
--- a/Help/UGen/inTrig.help.lhs
+++ b/Help/UGen/inTrig.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "InTrig"
-    > Sound.SC3.UGen.DB.ugenSummary "InTrig"
-
 > import Sound.SC3 {- hsc3 -}
 
 Run an oscillator with the trigger at bus 10.
diff --git a/Help/UGen/index.help.lhs b/Help/UGen/index.help.lhs
--- a/Help/UGen/index.help.lhs
+++ b/Help/UGen/index.help.lhs
@@ -1,13 +1,10 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Index"
-    > Sound.SC3.UGen.DB.ugenSummary "Index"
-
 > import Sound.SC3 {- hsc3 -}
 
 Index buffer for frequency values
 
 > g_01 =
 >   let b = asLocalBuf 'α' [50,100,200,400,800,1600]
->       f = index b (lfSaw KR 2 3 * 4)
+>       f = index b (range 0 6 (lfSaw KR 2 0))
 >   in sinOsc AR (mce [f,f * 9]) 0 * 0.1
 
 > g_02 =
diff --git a/Help/UGen/indexInBetween.help.lhs b/Help/UGen/indexInBetween.help.lhs
--- a/Help/UGen/indexInBetween.help.lhs
+++ b/Help/UGen/indexInBetween.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "IndexInBetween"
-    > Sound.SC3.UGen.DB.ugenSummary "IndexInBetween"
-
 > import Sound.SC3 {- hsc3 -}
 
 Index into buffer for frequency values
@@ -18,5 +15,5 @@
 >     let from = asLocalBuf 'α' [1, 2, 4, 8, 16]
 >         to = asLocalBuf 'β' [0, 1, 0, -1, 0]
 >         x = mouseX KR 1 16 Linear 0.1
->         i = indexL KR to (indexInBetween from x)
+>         i = indexL to (indexInBetween from x)
 >     in sinOsc AR (linLin i (-1) 1 440 880) 0 * 0.1
diff --git a/Help/UGen/indexL.help.lhs b/Help/UGen/indexL.help.lhs
--- a/Help/UGen/indexL.help.lhs
+++ b/Help/UGen/indexL.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "IndexL"
-    > Sound.SC3.UGen.DB.ugenSummary "IndexL"
-
 > import Sound.SC3 {- hsc3 -}
 
 Index buffer for frequency values
diff --git a/Help/UGen/integrator.help.lhs b/Help/UGen/integrator.help.lhs
--- a/Help/UGen/integrator.help.lhs
+++ b/Help/UGen/integrator.help.lhs
@@ -1,8 +1,5 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Integrator"
-    > Sound.SC3.UGen.DB.ugenSummary "Integrator"
-
 > import Sound.SC3 {- hsc3 -}
->
+
 > g_01 =
 >     let x = mouseX KR 0.001 0.999 Exponential 0.2
 >         o = lfPulse AR 300 0.2 0.1 * 0.1
@@ -12,7 +9,7 @@
 
 > g_02 =
 >     let i = lfPulse AR 3 0.2 0.0004
->         o = sinOsc AR 700 0
+>         o = sinOsc AR 700 0 * 0.1
 >     in integrator i 0.999 * o
 
 
diff --git a/Help/UGen/ix.md b/Help/UGen/ix.md
--- a/Help/UGen/ix.md
+++ b/Help/UGen/ix.md
@@ -8,7 +8,7 @@
 
 [beatTrack](?t=hsc3&e=Help/UGen/beatTrack.help.lhs),
 [beatTrack2](?t=hsc3&e=Help/UGen/beatTrack2.help.lhs),
-[mFCC](?t=hsc3&e=Help/UGen/mFCC.help.lhs),
+[mfcc](?t=hsc3&e=Help/UGen/mfcc.help.lhs),
 [onsets](?t=hsc3&e=Help/UGen/onsets.help.lhs),
 [runningSum](?t=hsc3&e=Help/UGen/runningSum.help.lhs),
 [slope](?t=hsc3&e=Help/UGen/slope.help.lhs)
@@ -73,11 +73,11 @@
 
 ## Conversion
 
-[a2K](?t=hsc3&e=Help/UGen/a2K.help.lhs),
+[a2k](?t=hsc3&e=Help/UGen/a2k.help.lhs),
 [degreeToKey](?t=hsc3&e=Help/UGen/degreeToKey.help.lhs),
-[k2A](?t=hsc3&e=Help/UGen/k2A.help.lhs),
-[t2A](?t=hsc3&e=Help/UGen/t2A.help.lhs),
-[t2K](?t=hsc3&e=Help/UGen/t2K.help.lhs)
+[k2a](?t=hsc3&e=Help/UGen/k2a.help.lhs),
+[t2a](?t=hsc3&e=Help/UGen/t2a.help.lhs),
+[t2k](?t=hsc3&e=Help/UGen/t2k.help.lhs)
 
 
 ## Convolution
@@ -180,7 +180,7 @@
 [convolution2](?t=hsc3&e=Help/UGen/convolution2.help.lhs),
 [convolution2L](?t=hsc3&e=Help/UGen/convolution2L.help.lhs),
 [fft](?t=hsc3&e=Help/UGen/fft.help.lhs),
-[fFTTrigger](?t=hsc3&e=Help/UGen/fFTTrigger.help.lhs),
+[fftTrigger](?t=hsc3&e=Help/UGen/fftTrigger.help.lhs),
 [ifft](?t=hsc3&e=Help/UGen/ifft.help.lhs),
 [pv_Add](?t=hsc3&e=Help/UGen/pv_Add.help.lhs),
 [pv_BinScramble](?t=hsc3&e=Help/UGen/pv_BinScramble.help.lhs),
@@ -240,7 +240,7 @@
 [bAllPass](?t=hsc3&e=Help/UGen/bAllPass.help.lhs),
 [bBandPass](?t=hsc3&e=Help/UGen/bBandPass.help.lhs),
 [bBandStop](?t=hsc3&e=Help/UGen/bBandStop.help.lhs),
-[bEQSuite](?t=hsc3&e=Help/UGen/bEQSuite.help.lhs),
+[beqSuite](?t=hsc3&e=Help/UGen/beqSuite.help.lhs),
 [bHiPass](?t=hsc3&e=Help/UGen/bHiPass.help.lhs),
 [bHiShelf](?t=hsc3&e=Help/UGen/bHiShelf.help.lhs),
 [bLowPass](?t=hsc3&e=Help/UGen/bLowPass.help.lhs),
@@ -314,9 +314,9 @@
 [chaosGen](?t=hsc3&e=Help/UGen/chaosGen.help.lhs),
 [cuspL](?t=hsc3&e=Help/UGen/cuspL.help.lhs),
 [cuspN](?t=hsc3&e=Help/UGen/cuspN.help.lhs),
-[fBSineC](?t=hsc3&e=Help/UGen/fBSineC.help.lhs),
-[fBSineL](?t=hsc3&e=Help/UGen/fBSineL.help.lhs),
-[fBSineN](?t=hsc3&e=Help/UGen/fBSineN.help.lhs),
+[fbSineC](?t=hsc3&e=Help/UGen/fbSineC.help.lhs),
+[fbSineL](?t=hsc3&e=Help/UGen/fbSineL.help.lhs),
+[fbSineN](?t=hsc3&e=Help/UGen/fbSineN.help.lhs),
 [gbmanL](?t=hsc3&e=Help/UGen/gbmanL.help.lhs),
 [gbmanN](?t=hsc3&e=Help/UGen/gbmanN.help.lhs),
 [henonC](?t=hsc3&e=Help/UGen/henonC.help.lhs),
@@ -516,7 +516,7 @@
 [randID](?t=hsc3&e=Help/UGen/randID.help.lhs),
 [randSeed](?t=hsc3&e=Help/UGen/randSeed.help.lhs),
 [tExpRand](?t=hsc3&e=Help/UGen/tExpRand.help.lhs),
-[tIRand](?t=hsc3&e=Help/UGen/tIRand.help.lhs),
+[tiRand](?t=hsc3&e=Help/UGen/tiRand.help.lhs),
 [tRand](?t=hsc3&e=Help/UGen/tRand.help.lhs),
 [tWindex](?t=hsc3&e=Help/UGen/tWindex.help.lhs)
 
@@ -558,11 +558,11 @@
 [setResetFF](?t=hsc3&e=Help/UGen/setResetFF.help.lhs),
 [stepper](?t=hsc3&e=Help/UGen/stepper.help.lhs),
 [sweep](?t=hsc3&e=Help/UGen/sweep.help.lhs),
-[t2A](?t=hsc3&e=Help/UGen/t2A.help.lhs),
-[t2K](?t=hsc3&e=Help/UGen/t2K.help.lhs),
+[t2a](?t=hsc3&e=Help/UGen/t2a.help.lhs),
+[t2k](?t=hsc3&e=Help/UGen/t2k.help.lhs),
 [tDelay](?t=hsc3&e=Help/UGen/tDelay.help.lhs),
 [tExpRand](?t=hsc3&e=Help/UGen/tExpRand.help.lhs),
-[tIRand](?t=hsc3&e=Help/UGen/tIRand.help.lhs),
+[tiRand](?t=hsc3&e=Help/UGen/tiRand.help.lhs),
 [tRand](?t=hsc3&e=Help/UGen/tRand.help.lhs),
 [tWindex](?t=hsc3&e=Help/UGen/tWindex.help.lhs),
 [timer](?t=hsc3&e=Help/UGen/timer.help.lhs),
@@ -576,21 +576,8 @@
 [apf](?t=hsc3&e=Help/UGen/apf.help.lhs),
 [audioControl](?t=hsc3&e=Help/UGen/audioControl.help.lhs),
 [blockSize](?t=hsc3&e=Help/UGen/blockSize.help.lhs),
-[dustR](?t=hsc3&e=Help/UGen/dustR.help.lhs),
 [nodeID](?t=hsc3&e=Help/UGen/nodeID.help.lhs),
 [pauseSelfWhenDone](?t=hsc3&e=Help/UGen/pauseSelfWhenDone.help.lhs),
-[rDelayMap](?t=hsc3&e=Help/UGen/rDelayMap.help.lhs),
-[rDelaySet](?t=hsc3&e=Help/UGen/rDelaySet.help.lhs),
-[rDelaySetB](?t=hsc3&e=Help/UGen/rDelaySetB.help.lhs),
-[rFreezer](?t=hsc3&e=Help/UGen/rFreezer.help.lhs),
-[rLoopSet](?t=hsc3&e=Help/UGen/rLoopSet.help.lhs),
-[rPlayTrace](?t=hsc3&e=Help/UGen/rPlayTrace.help.lhs),
-[rShufflerB](?t=hsc3&e=Help/UGen/rShufflerB.help.lhs),
-[rShufflerL](?t=hsc3&e=Help/UGen/rShufflerL.help.lhs),
-[rTraceRd](?t=hsc3&e=Help/UGen/rTraceRd.help.lhs),
-[rTraceRdX](?t=hsc3&e=Help/UGen/rTraceRdX.help.lhs),
-[rTraceRdY](?t=hsc3&e=Help/UGen/rTraceRdY.help.lhs),
-[rTraceRdZ](?t=hsc3&e=Help/UGen/rTraceRdZ.help.lhs),
 [scopeOut](?t=hsc3&e=Help/UGen/scopeOut.help.lhs),
 [scopeOut2](?t=hsc3&e=Help/UGen/scopeOut2.help.lhs),
 [trigControl](?t=hsc3&e=Help/UGen/trigControl.help.lhs)
@@ -646,7 +633,7 @@
 [sqrDif](?t=hsc3&e=Help/UGen/sqrDif.help.lhs),
 [absDif](?t=hsc3&e=Help/UGen/absDif.help.lhs),
 [thresh](?t=hsc3&e=Help/UGen/thresh.help.lhs),
-[aMClip](?t=hsc3&e=Help/UGen/aMClip.help.lhs),
+[amClip](?t=hsc3&e=Help/UGen/amClip.help.lhs),
 [scaleNeg](?t=hsc3&e=Help/UGen/scaleNeg.help.lhs),
 [clip2](?t=hsc3&e=Help/UGen/clip2.help.lhs),
 [excess](?t=hsc3&e=Help/UGen/excess.help.lhs),
@@ -676,14 +663,14 @@
 [sqrt](?t=hsc3&e=Help/UGen/sqrt.help.lhs),
 [exp](?t=hsc3&e=Help/UGen/exp.help.lhs),
 [recip](?t=hsc3&e=Help/UGen/recip.help.lhs),
-[mIDICPS](?t=hsc3&e=Help/UGen/mIDICPS.help.lhs),
-[cPSMIDI](?t=hsc3&e=Help/UGen/cPSMIDI.help.lhs),
-[mIDIRatio](?t=hsc3&e=Help/UGen/mIDIRatio.help.lhs),
+[midicps](?t=hsc3&e=Help/UGen/midicps.help.lhs),
+[cpsmidi](?t=hsc3&e=Help/UGen/cpsmidi.help.lhs),
+[midiRatio](?t=hsc3&e=Help/UGen/midiRatio.help.lhs),
 [ratioMIDI](?t=hsc3&e=Help/UGen/ratioMIDI.help.lhs),
 [dbAmp](?t=hsc3&e=Help/UGen/dbAmp.help.lhs),
 [ampDb](?t=hsc3&e=Help/UGen/ampDb.help.lhs),
 [octCPS](?t=hsc3&e=Help/UGen/octCPS.help.lhs),
-[cPSOct](?t=hsc3&e=Help/UGen/cPSOct.help.lhs),
+[cpsOct](?t=hsc3&e=Help/UGen/cpsOct.help.lhs),
 [log](?t=hsc3&e=Help/UGen/log.help.lhs),
 [log2](?t=hsc3&e=Help/UGen/log2.help.lhs),
 [log10](?t=hsc3&e=Help/UGen/log10.help.lhs),
diff --git a/Help/UGen/jPverbRaw.help.lhs b/Help/UGen/jPverbRaw.help.lhs
--- a/Help/UGen/jPverbRaw.help.lhs
+++ b/Help/UGen/jPverbRaw.help.lhs
@@ -1,10 +1,9 @@
-    Sound.SC3.UGen.Help.viewSC3Help "JPverbRaw"
-    Sound.SC3.UGen.DB.ugenSummary "JPverbRaw"
-
 > import Sound.SC3 {- hsc3 -}
-> import qualified Sound.SC3.UGen.Bindings.DB.External as External {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
 
+default values
+
 > g_01 =
 >   let (i1,i2) = (soundIn 0,soundIn 1)
->   in External.jPverbRaw i1 i2 0 0.707 2000 1 500 1 0.1 2 1 1 1
+>   in X.jPverbRaw i1 i2 0 0.707 2000 1 500 1 0.1 2 1 1 1
 
diff --git a/Help/UGen/k2a.help.lhs b/Help/UGen/k2a.help.lhs
--- a/Help/UGen/k2a.help.lhs
+++ b/Help/UGen/k2a.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "K2A"
-    > Sound.SC3.UGen.DB.ugenSummary "K2A"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 = k2a (whiteNoise 'α' KR * 0.3)
diff --git a/Help/UGen/keyState.help.lhs b/Help/UGen/keyState.help.lhs
--- a/Help/UGen/keyState.help.lhs
+++ b/Help/UGen/keyState.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "KeyState"
-    Sound.SC3.UGen.DB.ugenSummary "KeyState"
-
 > import Sound.SC3 {- hsc3 -}
 
 The keycode 38 is the A key on my keyboard.  Under X the xev(1)
diff --git a/Help/UGen/keyTrack.help.lhs b/Help/UGen/keyTrack.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/keyTrack.help.lhs
@@ -0,0 +1,9 @@
+> import Sound.SC3 {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
+
+> g_01 =
+>   let s = soundIn (mce2 0 1)
+>       t = fft' (localBuf 'α' 1 4096) (mix s)
+>       k = keyTrack KR t 2.0 0.5
+>       p = poll (impulse KR 1 0) k 0 (label "key")
+>   in mrg2 s p
diff --git a/Help/UGen/klang.help.lhs b/Help/UGen/klang.help.lhs
--- a/Help/UGen/klang.help.lhs
+++ b/Help/UGen/klang.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Klang"
-    > Sound.SC3.UGen.DB.ugenSummary "Klang"
-
 Note: SC2 had mul/add inputs.
 
 > import Sound.SC3 {- hsc3 -}
diff --git a/Help/UGen/klank.help.lhs b/Help/UGen/klank.help.lhs
--- a/Help/UGen/klank.help.lhs
+++ b/Help/UGen/klank.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Klank"
-    > Sound.SC3.UGen.DB.ugenSummary "Klank"
-
 > import Sound.SC3 {- hsc3 -}
 
 The klankSpec family of functions can help create the 'spec' entry.
diff --git a/Help/UGen/ladspa.help.lhs b/Help/UGen/ladspa.help.lhs
--- a/Help/UGen/ladspa.help.lhs
+++ b/Help/UGen/ladspa.help.lhs
@@ -1,15 +1,12 @@
-    Sound.SC3.UGen.Help.viewSC3Help "LADSPA"
-    Sound.SC3.UGen.DB.ugenSummary "LADSPA"
-
 > import Sound.SC3 {- hsc3 -}
-> import Sound.SC3.UGen.Bindings.DB.External {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.HW.External as X {- hsc3 -}
 
 Note: debian sc3-plugins doesn't build ladspalist, to build type:
 
     cd opt/src/sc3-plugins/source/LadspaUGen
     gcc -ldl search.c ladspalist.c -o ladspalist
 
-CAPS = http://quitte.de/dsp/caps.html, http://packages.debian.org/stretch/caps
+CAPS = http://quitte.de/dsp/caps.html, http://packages.debian.org/stable/caps
 
     # 1767 C* ChorusI - Mono chorus/flanger
     > k: t (ms) (2.5 to 40)
@@ -27,7 +24,7 @@
 >       y = mouseY KR 0 1 Linear 0.2
 >       n1 = range 2.5 40 (lfNoise2 'α' KR 0.2)
 >       n2 = range 0.5 10 (lfNoise2 'β' KR 0.2)
->   in ladspa 1 AR 1767 [n1,n2,0.5,0.5,x,y,s]
+>   in X.ladspa 1 AR 1767 [n1,n2,0.5,0.5,x,y,s]
 
     # 1769 C* Click - Metronome
     > k: model (0 to 3)
@@ -39,7 +36,7 @@
 > caps_1769_01 =
 >   let x = roundE (mouseX KR 0 3 Linear 0.2)
 >       y = mouseY KR 4 240 Linear 0.2
->   in ladspa 1 AR 1769 [x,y,0.5,0.5]
+>   in X.ladspa 1 AR 1769 [x,y,0.5,0.5]
 
     # 1773 C* Eq10 - 10-band equaliser
     > k: 31 Hz (-48 to 24)
@@ -60,7 +57,7 @@
 > caps_1773_01 =
 >   let s = soundIn 0
 >       n = map (\z -> range (-24) 48 (lfNoise2 z KR 0.2)) (enumN 10 'α')
->   in ladspa 1 AR 1773 (n ++ [s]) * 0.5
+>   in X.ladspa 1 AR 1773 (n ++ [s]) * 0.5
 
     # 1771 C* Saturate - Various static nonlinearities, 8x oversampled
     > k: mode (0 to 11)
@@ -71,13 +68,13 @@
 
 > caps_1771_01 =
 >   let s = soundIn 0
->   in ladspa 1 AR 1771 [1,0,0,s]
+>   in X.ladspa 1 AR 1771 [1,0,0,s]
 
 > caps_1771_02 =
 >   let s = soundIn 0
 >       x = roundE (mouseX KR 0 11 Linear 0.2)
 >       y = mouseY KR (-24) 72 Linear 0.2
->   in ladspa 1 AR 1771 [x,y,0.0,s]
+>   in X.ladspa 1 AR 1771 [x,y,0.0,s]
 
     # 1772 C* Compress - Compressor and saturating limiter
     > k: measure (0 to 1)
@@ -95,7 +92,7 @@
 >   let s = soundIn 0
 >       x = roundE (mouseX KR 0 2 Linear 0.2)
 >       y = mouseY KR 0 1 Linear 0.2
->   in ladspa 1 AR 1772 [0.5,x,y,0.5,0.5,0.1,0,s]
+>   in X.ladspa 1 AR 1772 [0.5,x,y,0.5,0.5,0.1,0,s]
 
     # 1779 C* Plate - Versatile plate reverb
     > k: bandwidth (0 to 1)
@@ -110,7 +107,7 @@
 >   let s = soundIn 0
 >       x = mouseX KR 0 1 Linear 0.2
 >       y = mouseY KR 0 1 Linear 0.2
->   in ladspa 2 AR 1779 [x,y,0.5,0.5,s]
+>   in X.ladspa 2 AR 1779 [x,y,0.5,0.5,s]
 
     # 1788 C* Wider - Stereo image synthesis
     > k: pan (-1 to 1)
@@ -123,7 +120,7 @@
 >   let s = soundIn 0
 >       x = mouseX KR (-1) 1 Linear 0.2
 >       y = mouseY KR 0 1 Linear 0.2
->   in ladspa 2 AR 1788 [x,y,s]
+>   in X.ladspa 2 AR 1788 [x,y,s]
 
     # 2586 C* PhaserII - Mono phaser
     > k: rate (0 to 1)
@@ -138,7 +135,7 @@
 >   let s = soundIn 0
 >       x = mouseX KR 0 1 Linear 0.2
 >       y = mouseY KR 0 1 Linear 0.2
->   in ladspa 1 AR 2586 [0.3,x,0.5,y,0.8,s]
+>   in X.ladspa 1 AR 2586 [0.3,x,0.5,y,0.8,s]
 
     # 2588 C* Scape - Stereo delay with chromatic resonances
     > k: bpm (30 to 164)
@@ -157,7 +154,7 @@
 >       y = roundE (mouseY KR 2 4 Linear 0.2)
 >       n1 = lfNoise2 'α' KR 0.2
 >       n2 = lfNoise2 'β' KR 0.2
->   in ladspa 2 AR 2588 [x,y,n1,n2,0.5,440,s]
+>   in X.ladspa 2 AR 2588 [x,y,n1,n2,0.5,440,s]
 
     # 2592 C* AmpVTS - Idealised guitar amplification
     > k: over (0 to 2)
@@ -176,14 +173,14 @@
 
 > caps_2592_def s = [1,0.25,0.75,0.5,1,0.25,1,0.75,0.75,0.25,0.5,s]
 
-> caps_2592_01 = ladspa 1 AR 2592 (caps_2592_def (soundIn 0))
+> caps_2592_01 = X.ladspa 1 AR 2592 (caps_2592_def (soundIn 0))
 
 > caps_2592_02 =
 >   let s = soundIn 0
 >       x = roundE (mouseX KR 0 8 Linear 0.2)
 >       y = mouseY KR 0 1 Linear 0.2
 >       [n1,n2,n3,n4,n5,n6,n7,n8] = map (\z -> lfNoise2 z KR 0.2) (enumN 8 'α')
->   in ladspa 1 AR 2592 [1,y,n1,n2,x,n3,n4,n5,n6,n7,n8,s]
+>   in X.ladspa 1 AR 2592 [1,y,n1,n2,x,n3,n4,n5,n6,n7,n8,s]
 
     # 2603 C* Spice - Not an exciter
     > k: lo.f (Hz) (50 to 400)
@@ -198,7 +195,7 @@
 >   let s = soundIn 0
 >       x = mouseX KR 50 400 Exponential 0.2
 >       y = mouseY KR 400 5000 Exponential 0.2
->   in ladspa 1 AR 2603 [x,0.5,0.5,y,0.5,s]
+>   in X.ladspa 1 AR 2603 [x,0.5,0.5,y,0.5,s]
 
     # 2609 C* EqFA4p - 4-band parametric eq
     > k: a.act (0 to 1)
@@ -243,4 +240,4 @@
 >           ,f 'π' linLin (-24) 24
 >           ,0
 >           ,s]
->   in ladspa 1 AR 2609 p * 0.5
+>   in X.ladspa 1 AR 2609 p * 0.5
diff --git a/Help/UGen/lag.help.lhs b/Help/UGen/lag.help.lhs
--- a/Help/UGen/lag.help.lhs
+++ b/Help/UGen/lag.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "Lag"
-    Sound.SC3.UGen.DB.ugenSummary "Lag"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 =
diff --git a/Help/UGen/lag2.help.lhs b/Help/UGen/lag2.help.lhs
--- a/Help/UGen/lag2.help.lhs
+++ b/Help/UGen/lag2.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "Lag2"
-    Sound.SC3.UGen.DB.ugenSummary "Lag2"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 =
diff --git a/Help/UGen/lag3.help.lhs b/Help/UGen/lag3.help.lhs
--- a/Help/UGen/lag3.help.lhs
+++ b/Help/UGen/lag3.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "Lag3"
-    Sound.SC3.UGen.DB.ugenSummary "Lag3"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 =
diff --git a/Help/UGen/lagIn.help.lhs b/Help/UGen/lagIn.help.lhs
--- a/Help/UGen/lagIn.help.lhs
+++ b/Help/UGen/lagIn.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "LagIn"
-    Sound.SC3.UGen.DB.ugenSummary "LagIn"
-
 > import Sound.SC3 {- hsc3 -}
 
 Set frequency at control bus
diff --git a/Help/UGen/lagUD.help.lhs b/Help/UGen/lagUD.help.lhs
--- a/Help/UGen/lagUD.help.lhs
+++ b/Help/UGen/lagUD.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "LagUD"
-    Sound.SC3.UGen.DB.ugenSummary "LagUD"
-
 > import Sound.SC3 {- hsc3 -}
 
 lag pitch, slower down (5 seconds) than up (1 second)
diff --git a/Help/UGen/latch.help.lhs b/Help/UGen/latch.help.lhs
--- a/Help/UGen/latch.help.lhs
+++ b/Help/UGen/latch.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "Latch"
-    Sound.SC3.UGen.DB.ugenSummary "Latch"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 =
diff --git a/Help/UGen/latoocarfianC.help.lhs b/Help/UGen/latoocarfianC.help.lhs
--- a/Help/UGen/latoocarfianC.help.lhs
+++ b/Help/UGen/latoocarfianC.help.lhs
@@ -1,7 +1,5 @@
-    Sound.SC3.UGen.Help.viewSC3Help "LatoocarfianC"
-    Sound.SC3.UGen.DB.ugenSummary "LatoocarfianC"
-
-> import Sound.SC3
+> import Sound.SC3 {- hsc3 -}
+> import Sound.SC3.Common.Math.Noise {- hsc3 -}
 
 SC3 default initial parameters.
 
@@ -19,3 +17,11 @@
 >       c = n2 * 0.5 + 1.5
 >       d = n3 * 0.5 + 1.5
 >   in latoocarfianC AR f a b c d 0.5 0.5 * 0.2
+
+Haskell implementation of equation.
+
+> latoocarfian_hs a b c d = map fst (iterate (latoocarfian_f a b c d) (0.5,0.5))
+
+    import Sound.SC3.Plot {- hsc3-plot -}
+    plotTable1 (take 600 (latoocarfian_hs 1.0 3.0 0.5 0.5))
+    plot_ugen_nrt (600,1) 1.0 (latoocarfianC AR 600 1.0 3.0 0.5 0.5 0.5 0.5)
diff --git a/Help/UGen/leakDC.help.lhs b/Help/UGen/leakDC.help.lhs
--- a/Help/UGen/leakDC.help.lhs
+++ b/Help/UGen/leakDC.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "LeakDC"
-    > Sound.SC3.UGen.DB.ugenSummary "LeakDC"
-
 > import Sound.SC3
 
 > g_01 =
diff --git a/Help/UGen/lfBrownNoise0.help.lhs b/Help/UGen/lfBrownNoise0.help.lhs
--- a/Help/UGen/lfBrownNoise0.help.lhs
+++ b/Help/UGen/lfBrownNoise0.help.lhs
@@ -1,9 +1,7 @@
-    Sound.SC3.UGen.Help.viewSC3Help "LFBrownNoise2"
-
 > import Sound.SC3 {- hsc3 -}
-> import Sound.SC3.UGen.Bindings.DB.External {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
 
 > g_01 =
->   let n = lfBrownNoise0 'α' AR 10 0.05 0
+>   let n = X.lfBrownNoise0 'α' AR 10 0.05 0
 >       f = linExp n (-1) 1 64 9600
 >   in sinOsc AR f 0 * 0.1
diff --git a/Help/UGen/lfBrownNoise2.help.lhs b/Help/UGen/lfBrownNoise2.help.lhs
--- a/Help/UGen/lfBrownNoise2.help.lhs
+++ b/Help/UGen/lfBrownNoise2.help.lhs
@@ -1,13 +1,11 @@
-    Sound.SC3.UGen.Help.viewSC3Help "LFBrownNoise2"
-
 > import Sound.SC3 {- hsc3 -}
-> import Sound.SC3.UGen.Bindings.DB.External {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
 
 > g_01 =
 >   let freq = 1000
 >       dev = mouseX KR 0 1 Linear 0.2
 >       dist = mouseY KR 0 5 Linear 0.2
->   in lfBrownNoise2 'α' AR freq dev dist * 0.25
+>   in X.lfBrownNoise2 'α' AR freq dev dist * 0.25
 
 Use as frequency control.
 
@@ -15,17 +13,17 @@
 >   let freq = 8
 >       dev = mouseX KR 0 1 Linear 0.2
 >       dist = mouseY KR 0 5 Linear 0.2
->       n1:n2:n3:_ = map (\z -> lfBrownNoise2 z KR freq dev dist) ['α'..]
+>       n1:n2:n3:_ = map (\z -> X.lfBrownNoise2 z KR freq dev dist) ['α'..]
 >       o = impulse AR (range 6 24 n1) 0
 >   in lagUD o (range 0.0001 0.001 n2) (range 0.0001 0.001 n3) * 0.5
 
 Use as pan & volume controls (external sound input)
 
 > f_01 s =
->   let freq = range 0.5 2 (lfBrownNoise2 'α' KR 2 0.1 5)
+>   let freq = range 0.5 2 (X.lfBrownNoise2 'α' KR 2 0.1 5)
 >       dev = mouseX KR 0.01 0.35 Linear 0.2
 >       dist = mouseY KR 0 5 Linear 0.2
->       n1:n2:_ = map (\z -> lfBrownNoise2 z KR freq dev dist) ['β'..]
+>       n1:n2:_ = map (\z -> X.lfBrownNoise2 z KR freq dev dist) ['β'..]
 >   in pan2 s (range (-0.75) 0.75 n1) 1 * range 0.01 0.5 n2
 
 > g_03 = f_01 (soundIn 0)
diff --git a/Help/UGen/lfClipNoise.help.lhs b/Help/UGen/lfClipNoise.help.lhs
--- a/Help/UGen/lfClipNoise.help.lhs
+++ b/Help/UGen/lfClipNoise.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "LFClipNoise"
-    Sound.SC3.UGen.DB.ugenSummary "LFClipNoise"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 = lfClipNoise 'α' AR 1000 * 0.05
diff --git a/Help/UGen/lfCub.help.lhs b/Help/UGen/lfCub.help.lhs
--- a/Help/UGen/lfCub.help.lhs
+++ b/Help/UGen/lfCub.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "LFCub"
-    > Sound.SC3.UGen.DB.ugenSummary "LFCub"
-
 > import Sound.SC3
 
 > g_01 = lfCub AR (lfCub KR (lfCub KR 0.2 0 * 8 + 10) 0 * 400 + 800) 0 * 0.1
diff --git a/Help/UGen/lfGauss.help.lhs b/Help/UGen/lfGauss.help.lhs
--- a/Help/UGen/lfGauss.help.lhs
+++ b/Help/UGen/lfGauss.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "LFGauss"
-    Sound.SC3.UGen.DB.ugenSummary "LFGauss"
-
 > import Sound.SC3 {- hsc3 -}
 
 modulating duration
diff --git a/Help/UGen/lfNoise0.help.lhs b/Help/UGen/lfNoise0.help.lhs
--- a/Help/UGen/lfNoise0.help.lhs
+++ b/Help/UGen/lfNoise0.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "LFNoise0"
-    Sound.SC3.UGen.DB.ugenSummary "LFNoise0"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 = lfNoise0 'α' AR 1000 * 0.05
diff --git a/Help/UGen/lfNoise1.help.lhs b/Help/UGen/lfNoise1.help.lhs
--- a/Help/UGen/lfNoise1.help.lhs
+++ b/Help/UGen/lfNoise1.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "LFNoise1"
-    Sound.SC3.UGen.DB.ugenSummary "LFNoise1"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 = lfNoise1 'α' AR 1000 * 0.05
diff --git a/Help/UGen/lfNoise2.help.lhs b/Help/UGen/lfNoise2.help.lhs
--- a/Help/UGen/lfNoise2.help.lhs
+++ b/Help/UGen/lfNoise2.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "LFNoise2"
-    Sound.SC3.UGen.DB.ugenSummary "LFNoise2"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 = lfNoise2 'α' AR 1000 * 0.05
diff --git a/Help/UGen/lfPar.help.lhs b/Help/UGen/lfPar.help.lhs
--- a/Help/UGen/lfPar.help.lhs
+++ b/Help/UGen/lfPar.help.lhs
@@ -1,4 +1,1 @@
-    Sound.SC3.UGen.Help.viewSC3Help "LFPar"
-    Sound.SC3.UGen.DB.ugenSummary "LFPar"
-
 See lfCub
diff --git a/Help/UGen/lfPulse.help.lhs b/Help/UGen/lfPulse.help.lhs
--- a/Help/UGen/lfPulse.help.lhs
+++ b/Help/UGen/lfPulse.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "LFPulse"
-    Sound.SC3.UGen.DB.ugenSummary "LFPulse"
-
 Note: SC2 had no initial phase argument.
 
 > import Sound.SC3
diff --git a/Help/UGen/lfSaw.help.lhs b/Help/UGen/lfSaw.help.lhs
--- a/Help/UGen/lfSaw.help.lhs
+++ b/Help/UGen/lfSaw.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "LFSaw"
-    Sound.SC3.UGen.DB.ugenSummary "LFSaw"
-
 Note: SC2 did not have the initial phase argument.
 
 > import Sound.SC3
diff --git a/Help/UGen/lfTri.help.lhs b/Help/UGen/lfTri.help.lhs
--- a/Help/UGen/lfTri.help.lhs
+++ b/Help/UGen/lfTri.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "LFTri"
-    Sound.SC3.UGen.DB.ugenSummary "LFTri"
-
 see <http://thread.gmane.org/gmane.comp.audio.supercollider.user/84719>
 
 > import Sound.SC3 {- hsc3 -}
@@ -15,7 +12,7 @@
 
 > g_03 = let f = lfTri KR 0.4 (mce [0..3]) * 200 + 400
 >        in mix (lfTri AR f 0 * 0.1)
->
+
 > g_04 = let x = midiCPS (mouseX KR 20 72 Linear 0.2)
 >            e = xLine KR 0.01 1 20 DoNothing
 >            o1 = triAS 25 x * (1 - e)
diff --git a/Help/UGen/lfdClipNoise.help.lhs b/Help/UGen/lfdClipNoise.help.lhs
--- a/Help/UGen/lfdClipNoise.help.lhs
+++ b/Help/UGen/lfdClipNoise.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "LFDClipNoise"
-    Sound.SC3.UGen.DB.ugenSummary "LFDClipNoise"
-
 > import Sound.SC3 {- hsc3 -}
 
 for fast x lfClipNoise frequently seems stuck, lfdClipNoise changes smoothly
diff --git a/Help/UGen/lfdNoise0.help.lhs b/Help/UGen/lfdNoise0.help.lhs
--- a/Help/UGen/lfdNoise0.help.lhs
+++ b/Help/UGen/lfdNoise0.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "LFDNoise0"
-    Sound.SC3.UGen.DB.ugenSummary "LFDNoise0"
-
 > import Sound.SC3 {- hsc3 -}
 
 for fast x LFNoise frequently seems stuck, LFDNoise changes smoothly
diff --git a/Help/UGen/lfdNoise3.help.lhs b/Help/UGen/lfdNoise3.help.lhs
--- a/Help/UGen/lfdNoise3.help.lhs
+++ b/Help/UGen/lfdNoise3.help.lhs
@@ -1,13 +1,12 @@
-    Sound.SC3.UGen.Help.viewSC3Help "LFDNoise3"
-    Sound.SC3.UGen.DB.ugenSummary "LFDNoise3"
-
 See lfdNoise0
 
 Drawings
 
-    > import Sound.SC3 {- hsc3 -}
-    > import Sound.SC3.Plot {- hsc3-plot -}
-    > plot_ugen1 0.1 (lfdNoise3 'α' AR (xLine AR 1000 100 0.1 DoNothing))
+> import Sound.SC3 {- hsc3 -}
+
+> g_01 = lfdNoise3 'α' AR (xLine AR 1000 100 0.1 DoNothing)
+
+    > Sound.SC3.Plot.plot_ugen1 0.1 g_01
 
 ![](sw/hsc3/Help/SVG/lfdNoise3.0.svg)
 
diff --git a/Help/UGen/linCongC.help.lhs b/Help/UGen/linCongC.help.lhs
--- a/Help/UGen/linCongC.help.lhs
+++ b/Help/UGen/linCongC.help.lhs
@@ -1,7 +1,5 @@
-    Sound.SC3.UGen.Help.viewSC3Help "LinCongC"
-    Sound.SC3.UGen.DB.ugenSummary "LinCongC"
-
 > import Sound.SC3 {- hsc3 -}
+> import Sound.SC3.Common.Math.Noise {- hsc3 -}
 
 Default SC3 initial parameters.
 
@@ -20,3 +18,11 @@
 >       a = n1 * 0.5 + 1.4
 >       c = n2 * 0.1 + 0.1
 >   in linCongC AR f a c m 0 * 0.2
+
+Haskell implementation of equation.
+
+> linCong_hs a c m = iterate (linCong_f a c m) 0
+
+    import Sound.SC3.Plot {- hsc3-plot -}
+    plotTable1 (take 600 (linCong_hs 1.1 0.13 1.0))
+    plot_ugen_nrt (600,1) 1.0 (linCongC AR 600 1.1 0.13 1.0 0.0)
diff --git a/Help/UGen/linExp.help.lhs b/Help/UGen/linExp.help.lhs
--- a/Help/UGen/linExp.help.lhs
+++ b/Help/UGen/linExp.help.lhs
@@ -1,16 +1,29 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "LinExp"
-    > Sound.SC3.UGen.DB.ugenSummary "LinExp"
-
 > import Sound.SC3 {- hsc3 -}
 
+{var mod = SinOsc.kr(Line.kr(1, 10, 10)); SinOsc.ar(mod * 400 + 500) * 0.1}.play
+
 > g_01 =
+>   let mod = sinOsc KR (line KR 1 10 10 DoNothing) 0
+>   in sinOsc AR (mod * 400 + 500) 0 * 0.1
+
+{var mod = SinOsc.kr(Line.kr(1, 10, 10)); SinOsc.ar(LinExp.kr(mod, -1,1, 100, 900)) * 0.1}.play
+
+> g_02 =
+>   let mod = sinOsc KR (line KR 1 10 10 DoNothing) 0
+>   in sinOsc AR (linExp mod (-1) 1 100 900) 0 * 0.1
+
+> g_03 =
 >     let f = linExp (mouseX KR 0 1 Linear 0.2) 0 1 440 660
 >     in sinOsc AR f 0 * 0.1
 
 The destination range may be k-rate.
 
-> g_02 =
+> g_04 =
 >     let x = mouseX KR 0 1 Linear 0.2
 >         y = mouseY KR 220 440 Linear 0.2
 >         f = linExp x 0 1 y 660
 >     in sinOsc AR f 0 * 0.1
+
+i-rate...
+
+> g_05 = sinOsc AR (linExp (rand 'α' 0 1) 0 1 220 440) 0 * 0.1
diff --git a/Help/UGen/linLin.help.lhs b/Help/UGen/linLin.help.lhs
--- a/Help/UGen/linLin.help.lhs
+++ b/Help/UGen/linLin.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "LinLin"
-    Sound.SC3.UGen.DB.ugenSummary "LinLin"
-
 > import Sound.SC3 {- hsc3 -}
 
 linLin is a function for writing a MulAdd UGen.
diff --git a/Help/UGen/linPan2.help.lhs b/Help/UGen/linPan2.help.lhs
--- a/Help/UGen/linPan2.help.lhs
+++ b/Help/UGen/linPan2.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "LinPan2"
-    > Sound.SC3.UGen.DB.ugenSummary "LinPan2"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 =
diff --git a/Help/UGen/linRand.help.lhs b/Help/UGen/linRand.help.lhs
--- a/Help/UGen/linRand.help.lhs
+++ b/Help/UGen/linRand.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "LinRand"
-    Sound.SC3.UGen.DB.ugenSummary "LinRand"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 =
diff --git a/Help/UGen/linXFade2.help.lhs b/Help/UGen/linXFade2.help.lhs
--- a/Help/UGen/linXFade2.help.lhs
+++ b/Help/UGen/linXFade2.help.lhs
@@ -1,15 +1,13 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "LinXFade2"
-    > Sound.SC3.UGen.DB.ugenSummary "LinXFade2"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 = linXFade2 (saw AR 440) (sinOsc AR 440 0) (lfTri KR 0.1 0) 0.1
->
-> gen_cmp ty = ty (fSinOsc AR 800 0 * 0.2)
->                 (pinkNoise 'α' AR * 0.2)
->                 (fSinOsc KR 0.5 0)
->                 1.0
->
-> g_03 = gen_cmp linXFade2
->
-> g_04 = gen_cmp xFade2
+
+> f_01 ty = ty
+>           (fSinOsc AR 800 0 * 0.2)
+>           (pinkNoise 'α' AR * 0.2)
+>           (fSinOsc KR 0.5 0)
+>           1.0
+
+> g_02 = f_01 linXFade2
+
+> g_03 = f_01 xFade2
diff --git a/Help/UGen/line.help.lhs b/Help/UGen/line.help.lhs
--- a/Help/UGen/line.help.lhs
+++ b/Help/UGen/line.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "Line"
-    Sound.SC3.UGen.DB.ugenSummary "Line"
-
 Note: SC3 reorders the mul and add inputs to precede the doneAction input.
 
 > import Sound.SC3 {- hsc3 -}
diff --git a/Help/UGen/linen.help.lhs b/Help/UGen/linen.help.lhs
--- a/Help/UGen/linen.help.lhs
+++ b/Help/UGen/linen.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "Linen"
-    Sound.SC3.UGen.DB.ugenSummary "Linen"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 =
@@ -9,6 +6,6 @@
 
 > g_02 =
 >     let x = mouseX KR (-1) 1 Linear 0.1
->         y = mouseY KR 0.1 0.5 Linear 0.1
+>         y = mouseY KR 0.01 0.25 Linear 0.1
 >         e = linen x 1 y 1.0 DoNothing
 >     in sinOsc AR 440 0 * e
diff --git a/Help/UGen/localBuf.help.lhs b/Help/UGen/localBuf.help.lhs
--- a/Help/UGen/localBuf.help.lhs
+++ b/Help/UGen/localBuf.help.lhs
@@ -1,22 +1,21 @@
-    Sound.SC3.UGen.Help.viewSC3Help "LocalBuf"
-    Sound.SC3.UGen.DB.ugenSummary "LocalBuf"
-
-> import Sound.SC3
+> import Sound.SC3 {- hsc3 -}
 
-Allocate a buffer local to the synthesis graph.
+Allocate a buffer local to the synthesis graph, 1-channel, 2048
 
 > g_01 =
->     let n = whiteNoise 'α' AR
->         b = localBuf 'β' 2048 1
->         f = fft' b n
+>     let nc = 1
+>         nf = 2048
+>         buf = localBuf 'α' nc nf
+>         f = fft' buf (whiteNoise 'β' AR)
 >         c = pv_BrickWall f (sinOsc KR 0.1 0 * 0.75)
 >     in ifft' c * 0.1
 
 Variant with two local buffers
 
 > g_02 =
->     let n = uclone 'α' 2 (whiteNoise 'β' AR)
->         b = uclone 'γ' 2 (localBuf 'δ' 2048 1)
+>     let dup (p,q) f = mce2 (f p) (f q)
+>         n = dup ('α','β') (\z -> whiteNoise z AR)
+>         b = dup ('γ','δ') (\z -> localBuf z 1 2048)
 >         f = fft' b n
 >         c = pv_BrickWall f (sinOsc KR (mce2 0.1 0.11) 0 * 0.75)
 >     in ifft' c * 0.1
@@ -24,24 +23,26 @@
 Not clearing the buffer accesses old data, slowly overwrite data with noise
 
 > g_03 =
->     let b = localBuf 'α' 2048 2
+>     let dup (p,q) f = mce2 (f p) (f q)
+>         b = localBuf 'α' 2 2048
 >         nf = bufFrames KR b
 >         x = mouseX KR 1 2 Linear 0.2
 >         r = playBuf 2 AR b x 1 0 Loop DoNothing * 0.1
 >         wr p i = bufWr b (linLin p (-1) 1 0 nf) Loop i
->         n = uclone 'β' 2 (whiteNoise 'γ' AR)
+>         n = dup ('β','γ') (\z -> whiteNoise z AR)
 >         ph = lfNoise0 'δ' AR 530
 >     in mrg2 r (wr ph n)
 
 bufCombC needs no clearing, because the delay line is filled by the ugen
 
 > g_04 =
->     let d = uclone 'α' 2 (dust 'β' AR 1)
+>     let dup (p,q) f = mce2 (f p) (f q)
+>         d = dup ('α','β') (\z -> dust z AR 1)
 >         n = whiteNoise 'γ' AR
 >         z = decay d 0.3 * n
 >         l = xLine KR 0.0001 0.01 20 DoNothing
 >         sr = sampleRate
->         b = uclone 'δ' 2 (localBuf 'ε' sr 2)
+>         b = dup ('δ','ε') (\z -> localBuf z 2 sr)
 >     in bufCombC b z l 0.2
 
 asLocalBuf combines localBuf and setBuf
diff --git a/Help/UGen/localIn.help.lhs b/Help/UGen/localIn.help.lhs
--- a/Help/UGen/localIn.help.lhs
+++ b/Help/UGen/localIn.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "LocalIn"
-    Sound.SC3.UGen.DB.ugenSummary "LocalIn"
-
 > import Sound.SC3 {- hsc3 -}
 
 > noise_signal =
@@ -25,7 +22,7 @@
 
 > tape_delay dt fb z =
 >     let a = amplitude KR (mix z) 0.01 0.01
->         z' = z * (a >* 0.02)
+>         z' = z * (a >** 0.02)
 >         l0 = localIn 2 AR 0
 >         l1 = onePole l0 0.4
 >         l2 = onePole l1 (-0.08)
diff --git a/Help/UGen/localOut.help.lhs b/Help/UGen/localOut.help.lhs
--- a/Help/UGen/localOut.help.lhs
+++ b/Help/UGen/localOut.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "LocalOut"
-    Sound.SC3.UGen.DB.ugenSummary "LocalOut"
-
 > import Sound.SC3 {- hsc3 -}
 
 Resonator, must subtract blockSize for correct tuning
diff --git a/Help/UGen/logistic.help.lhs b/Help/UGen/logistic.help.lhs
--- a/Help/UGen/logistic.help.lhs
+++ b/Help/UGen/logistic.help.lhs
@@ -1,11 +1,10 @@
-    Sound.SC3.UGen.Help.viewSC3Help "Logistic"
-    Sound.SC3.UGen.DB.ugenSummary "Logistic"
-
 > import Sound.SC3 {- hsc3 -}
 
 SC3 default parameters
 
-> g_01 = logistic AR 3 1000 0.5
+> g_00 = logistic AR 3 1000 0.5
+
+> g_01 = logistic AR 3.95 sampleRate 0.5
 
 Onset of chaos
 
diff --git a/Help/UGen/loopBuf.help.lhs b/Help/UGen/loopBuf.help.lhs
--- a/Help/UGen/loopBuf.help.lhs
+++ b/Help/UGen/loopBuf.help.lhs
@@ -1,15 +1,14 @@
-    Sound.SC3.UGen.Help.viewSC3Help "LoopBuf"
-    Sound.SC3.UGen.DB.ugenSummary "LoopBuf"
+    mapM_ Sound.SC3.UGen.DB.ugenSummary ["LoopBuf","PlayBuf"]
 
 > import Sound.SC3 {- hsc3 -}
-> import qualified Sound.SC3.UGen.Bindings.DB.External as E {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
 
 Read audio file into memory
 
-> ld b = do
->   let fn = "/home/rohan/opt/src/supercollider/sounds/a11wlk01.wav"
->   withSC3 (async (b_allocRead b fn 0 0))
+> fn_01 = "/home/rohan/rd/j/2019-04-21/FAIRLIGHT/IIX/REEDS/clarmdhi.snd"
 
+> ld fn b = withSC3 (async (b_allocRead b fn 0 0))
+
 Simple sampler instrument
 
 > lb0 =
@@ -20,27 +19,30 @@
 >         gt = control KR "gate" 1
 >         lr = control KR "loopRel" 0
 >         sp = control KR "startPos" 0
->         sl = control KR "startLoop" 0
->         el = control KR "endLoop" 0
+>         sl = control KR "startLoop" 0 -- FRAME
+>         el = control KR "endLoop" 0 -- FRAME
 >         ip = control KR "ipol" 2
+>         am = control KR "amp" 1
 >         rt' = lag rt gl * bufRateScale KR bf
 >         e = let d = envADSR 0.1 0.2 1 2 1 (EnvNum (-4)) 0
 >             in envGen AR gt 1 0 1 RemoveSynth d
->         s = E.loopBuf 1 AR bf rt' (gt + lr) sp sl el ip
->     in out ou (s * e)
+>         s = X.loopBuf 1 AR bf rt' (gt + lr) sp sl el ip
+>     in out ou (s * e * am)
 
 > lb0s :: Synthdef
 > lb0s = synthdef "lb0" lb0
 
-    ld 0
+    ld fn_01 0
     withSC3 (async (d_recv lb0s))
 
     import Sound.OSC {- hosc -}
     let send = sendMessage
     let run = withSC3 . send
 
-    run (s_new "lb0" 3000 AddToTail 1 [("bufnum",0),("startLoop",5000),("endLoop",15000)])
+    audition (sinOsc AR (midiCPS 69) 0 * 0.2)
+    run (s_new "lb0" 3000 AddToTail 1 [("bufnum",0),("amp",0.1),("startLoop",5376),("endLoop",5504)])
 
+    run (n_set1 3000 "amp" 0.25) -- louder
     run (n_set1 3000 "rate" (-1)) -- backwards
     run (n_set1 3000 "rate" 1) -- forwards
     run (n_set 3000 [("startLoop",11000),("endLoop",13000)]) -- change loop points
diff --git a/Help/UGen/lorenzL.help.lhs b/Help/UGen/lorenzL.help.lhs
--- a/Help/UGen/lorenzL.help.lhs
+++ b/Help/UGen/lorenzL.help.lhs
@@ -1,7 +1,8 @@
-    Sound.SC3.UGen.Help.viewSC3Help "LorenzL"
-    Sound.SC3.UGen.DB.ugenSummary "LorenzL"
-
 > import Sound.SC3 {- hsc3 -}
+
+Default parameters
+
+> g_00 = lorenzL AR (sampleRate / 2) 10 28 2.667 0.05 0.1 0 0 * 0.2
 
 Vary frequency
 
diff --git a/Help/UGen/lorenzTrig.help.lhs b/Help/UGen/lorenzTrig.help.lhs
--- a/Help/UGen/lorenzTrig.help.lhs
+++ b/Help/UGen/lorenzTrig.help.lhs
@@ -1,8 +1,5 @@
-    Sound.SC3.UGen.Help.viewSC3Help "LorenzTrig"
-    Sound.SC3.UGen.DB.ugenSummary "LorenzTrig"
-
 > import Sound.SC3 {- hsc3 -}
-> import Sound.SC3.UGen.Bindings.DB.External {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
 
 > f_01 minfreq maxfreq s b =
 >   let r = 28
@@ -10,7 +7,7 @@
 >       x0 = 0.090879182417163
 >       y0 = 2.97077458055
 >       z0 = 24.282041054363
->   in lorenzTrig AR minfreq maxfreq s r b h x0 y0 z0
+>   in X.lorenzTrig AR minfreq maxfreq s r b h x0 y0 z0
 
 > f_02 = f_01 11025 44100
 
diff --git a/Help/UGen/loudness.help.lhs b/Help/UGen/loudness.help.lhs
--- a/Help/UGen/loudness.help.lhs
+++ b/Help/UGen/loudness.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "Loudness"
-    Sound.SC3.UGen.DB.ugenSummary "Loudness"
-
 > import Sound.SC3 {- hsc3 -}
 
 Assume hop of half fftsize
diff --git a/Help/UGen/lpcAnalyzer.help.lhs b/Help/UGen/lpcAnalyzer.help.lhs
--- a/Help/UGen/lpcAnalyzer.help.lhs
+++ b/Help/UGen/lpcAnalyzer.help.lhs
@@ -1,21 +1,18 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "LPCAnalyzer"
-    > Sound.SC3.UGen.DB.ugenSummary "LPCAnalyzer"
-
 > import Sound.SC3 {- hsc3 -}
-> import Sound.SC3.UGen.Bindings.DB.External {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
 
-> g_01 = lpcAnalyzer (soundIn 0) (impulse AR 440 0 * 0.2) 256 50 0 0.999 0
+> g_01 = X.lpcAnalyzer (soundIn 0) (impulse AR 440 0 * 0.2) 256 50 0 0.999 0
 
-> g_02 = lpcAnalyzer (soundIn 0) (impulse AR 440 0 * 0.2) 256 50 0 0.999 1
+> g_02 = X.lpcAnalyzer (soundIn 0) (impulse AR 440 0 * 0.2) 256 50 0 0.999 1
 
 > g_03 =
 >   let x = mouseX KR 1 128 Linear 0.2
->   in lpcAnalyzer (soundIn 0) (impulse AR 440 0 * 0.2) 128 x 0 0.999 0
+>   in X.lpcAnalyzer (soundIn 0) (impulse AR 440 0 * 0.2) 128 x 0 0.999 0
 
 > g_04 =
 >   let x = mouseX KR 1 128 Linear 0.2
->   in lpcAnalyzer (soundIn 0) (impulse AR 440 0 * 0.2) 1024 x 0 0.999 1
+>   in X.lpcAnalyzer (soundIn 0) (impulse AR 440 0 * 0.2) 1024 x 0 0.999 1
 
 > g_05 =
 >   let x = mouseX KR 1 256 Linear 0.2
->   in lpcAnalyzer (soundIn 0) (whiteNoise 'α' AR * 0.1) 256 x 0 0.999 0
+>   in X.lpcAnalyzer (soundIn 0) (whiteNoise 'α' AR * 0.1) 256 x 0 0.999 0
diff --git a/Help/UGen/lpcSynth.help.lhs b/Help/UGen/lpcSynth.help.lhs
--- a/Help/UGen/lpcSynth.help.lhs
+++ b/Help/UGen/lpcSynth.help.lhs
@@ -1,31 +1,29 @@
-    Sound.SC3.UGen.Help.viewSC3Help "LPCSynth"
-    Sound.SC3.UGen.DB.ugenSummary "LPCSynth"
-
 > import Sound.OSC {- hosc -}
 > import Sound.SC3 {- hsc3 -}
-> import Sound.SC3.UGen.Bindings.DB.External {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
 
 > import qualified Sound.SC3.Data.LPC as LPC {- hsc3-data -}
 
-> lpc_instr b n lpc =
->     let x = mouseX KR 0.05 1.5 Linear 0.2
->         y = mouseY KR 0.25 2.0 Linear 0.2
->         f = x / constant (LPC.lpcAnalysisDuration (LPC.lpcHeader lpc))
->         ptr = lfSaw AR f 1 * 0.5 + 0.5
->         [cps, rms, err] = mceChannels (lpcVals AR b ptr)
->         nh = floorE (22000 / cps)
->         voc = blip AR (cps * y) nh * (1 - err)
->         s = lpcSynth b (voc + (n * err * 20)) ptr
->     in s * 1e-5 * rms
+> lpc_instr buf noise lpc =
+>   let x = mouseX KR 0.01 1.5 Linear 0.2
+>       y = mouseY KR 0.25 2.0 Linear 0.2
+>       f = x / constant (LPC.lpcAnalysisDuration (LPC.lpcHeader lpc))
+>       ptr = lfSaw AR f 1 * 0.5 + 0.5
+>       [cps, rms, err] = mceChannels (X.lpcVals AR buf ptr)
+>       nh = floorE (22000 / cps)
+>       voc = blip AR (cps * y) nh * (1 - err)
+>   in X.lpcSynth buf (voc + (noise * err)) ptr * rms
 
 > fn_01 = "/home/rohan/sw/hsc3-data/data/lpc/fate.lpc"
+> fn_02 = "/home/rohan/uc/invisible/clarity/lpc/z.01.lpc"
 
-> au_01 lpc = do
+> au_01 lpc noise = do
 >   let d = map realToFrac (LPC.lpcSC3 lpc)
 >   _ <- async (b_alloc 10 (length d) 1)
 >   mapM_ sendMessage (b_setn1_segmented 512 10 0 d)
->   let s = lpc_instr 10 (pinkNoise 'α' AR) lpc
+>   let s = lpc_instr 10 noise lpc
 >   play (out 0 s)
 
-    lpc <- LPC.lpcRead fn_01
-    withSC3 (au_01 lpc)
+    lpc <- LPC.lpc_read_binary LPC.BigEndian fn_01
+    lpc <- LPC.lpc_read_text fn_02
+    withSC3 (au_01 lpc (whiteNoise 'α' AR * 10))
diff --git a/Help/UGen/lpf.help.lhs b/Help/UGen/lpf.help.lhs
--- a/Help/UGen/lpf.help.lhs
+++ b/Help/UGen/lpf.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "LPF"
-    > Sound.SC3.UGen.DB.ugenSummary "LPF"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 =
diff --git a/Help/UGen/lpz2.help.lhs b/Help/UGen/lpz2.help.lhs
--- a/Help/UGen/lpz2.help.lhs
+++ b/Help/UGen/lpz2.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "LPZ2"
-    Sound.SC3.UGen.DB.ugenSummary "LPZ2"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 =
diff --git a/Help/UGen/lti.help.lhs b/Help/UGen/lti.help.lhs
--- a/Help/UGen/lti.help.lhs
+++ b/Help/UGen/lti.help.lhs
@@ -1,11 +1,8 @@
-    Sound.SC3.UGen.Help.viewSC3Help "LTI"
-    Sound.SC3.UGen.DB.ugenSummary "LTI"
-
 > import Sound.SC3 {- hsc3 -}
-> import Sound.SC3.UGen.Bindings.DB.External {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
 
-> gr_01 =
+> g_01 =
 >     let a = [0.02,-0.01]
 >         b = [1,0.7,0,0,0,0,-0.8,0,0,0,0,0.9,0,0,0,-0.5,0,0,0,0,0,0,0.25,0.1,0.25]
 >         z = pinkNoise 'α' AR * 0.1
->     in lti AR z (asLocalBuf 'β' a) (asLocalBuf 'γ' b)
+>     in X.lti AR z (asLocalBuf 'β' a) (asLocalBuf 'γ' b)
diff --git a/Help/UGen/max.help.lhs b/Help/UGen/max.help.lhs
--- a/Help/UGen/max.help.lhs
+++ b/Help/UGen/max.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Operator.max"
-    > :t max
-
 > import Sound.SC3 {- hsc3 -}
 
 q modulates and envelopes p
diff --git a/Help/UGen/membraneCircle.help.lhs b/Help/UGen/membraneCircle.help.lhs
--- a/Help/UGen/membraneCircle.help.lhs
+++ b/Help/UGen/membraneCircle.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "MembraneCircle"
-    Sound.SC3.UGen.DB.ugenSummary "MembraneCircle"
-
 > import Sound.SC3 {- hsc3 -}
 > import Sound.SC3.UGen.Bindings.DB.External {- hsc3 -}
 
diff --git a/Help/UGen/metro.help.lhs b/Help/UGen/metro.help.lhs
--- a/Help/UGen/metro.help.lhs
+++ b/Help/UGen/metro.help.lhs
@@ -1,18 +1,15 @@
-    Sound.SC3.UGen.Help.viewSC3Help "Metro"
-    Sound.SC3.UGen.DB.ugenSummary "Metro"
-
 > import Sound.SC3 {- hsc3 -}
-> import Sound.SC3.UGen.Bindings.DB.External {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
 
-> g_01 = metro AR 60 1
+> g_01 = X.metro AR 60 1
 
 > g_02 =
 >   let b = xLine KR 60 120 5 DoNothing
->       m = metro KR b 1
+>       m = X.metro KR b 1
 >       o = sinOsc AR 440 0 * 0.1
 >   in decay m 0.2 * o
 
 > g_03 =
 >   let b = range 30 240 (lfNoise2 'α' KR 0.2)
 >       n = dseq 'β' dinf (mce [1,0.25,0.5,0.25])
->   in decay (metro KR b n) 0.2 * sinOsc AR 440 0 * 0.1
+>   in decay (X.metro KR b n) 0.2 * sinOsc AR 440 0 * 0.1
diff --git a/Help/UGen/midEQ.help.lhs b/Help/UGen/midEQ.help.lhs
--- a/Help/UGen/midEQ.help.lhs
+++ b/Help/UGen/midEQ.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "MidEQ"
-    Sound.SC3.UGen.DB.ugenSummary "MidEQ"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 =
diff --git a/Help/UGen/mix.help.lhs b/Help/UGen/mix.help.lhs
--- a/Help/UGen/mix.help.lhs
+++ b/Help/UGen/mix.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "Mix"
-    Sound.SC3.UGen.DB.ugenSummary "Mix"
-
 > import Sound.SC3 {- hsc3 -}
 
 optimized summation (see sum_opt), ie. Sum3
diff --git a/Help/UGen/mod.help.lhs b/Help/UGen/mod.help.lhs
--- a/Help/UGen/mod.help.lhs
+++ b/Help/UGen/mod.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Operator.%"
-    > :t modE
-
 > import Sound.SC3 {- hsc3 -}
->
+
 > g_01 = fSinOsc AR 100 4 `modE` 1 * 0.1
diff --git a/Help/UGen/moogFF.help.lhs b/Help/UGen/moogFF.help.lhs
--- a/Help/UGen/moogFF.help.lhs
+++ b/Help/UGen/moogFF.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "MoogFF"
-    Sound.SC3.UGen.DB.ugenSummary "MoogFF"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 =
diff --git a/Help/UGen/moogLadder.help.lhs b/Help/UGen/moogLadder.help.lhs
--- a/Help/UGen/moogLadder.help.lhs
+++ b/Help/UGen/moogLadder.help.lhs
@@ -1,15 +1,12 @@
-    Sound.SC3.UGen.Help.viewSC3Help "MoogLadder"
-    Sound.SC3.UGen.DB.ugenSummary "MoogLadder"
-
 > import Sound.SC3 {- hsc3 -}
-> import Sound.SC3.UGen.Bindings.DB.External {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
 
 > g_01 =
 >   let o = mix (lfSaw AR (mce2 120 180) 0 * 0.33)
 >       cf = linExp (lfCub KR 0.1 (0.5 * pi)) (-1) 1 180 8500
->   in moogLadder o cf 0.75
+>   in X.moogLadder o cf 0.75
 
 > g_02 =
 >   let n = dust 'α' AR 3
->   in moogLadder n 2000 (mouseY KR 0 1 Linear 0.2)
+>   in X.moogLadder n 2000 (mouseY KR 0 1 Linear 0.2)
 
diff --git a/Help/UGen/moogVCF.help.lhs b/Help/UGen/moogVCF.help.lhs
--- a/Help/UGen/moogVCF.help.lhs
+++ b/Help/UGen/moogVCF.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "MoogVCF"
-    Sound.SC3.UGen.DB.ugenSummary "MoogVCF"
-
 > import Sound.SC3 {- hsc3 -}
 > import Sound.SC3.UGen.Bindings.DB.External {- hsc3 -}
 
diff --git a/Help/UGen/mostChange.help.lhs b/Help/UGen/mostChange.help.lhs
--- a/Help/UGen/mostChange.help.lhs
+++ b/Help/UGen/mostChange.help.lhs
@@ -1,8 +1,5 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "MostChange"
-    > Sound.SC3.UGen.DB.ugenSummary "MostChange"
-
 > import Sound.SC3 {- hsc3 -}
->
+
 > g_01 =
 >     let n = lfNoise0 'α' KR 1
 >         x = mouseX KR 200 300 Linear 0.1
diff --git a/Help/UGen/mouseButton.help.lhs b/Help/UGen/mouseButton.help.lhs
--- a/Help/UGen/mouseButton.help.lhs
+++ b/Help/UGen/mouseButton.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "MouseButton"
-    Sound.SC3.UGen.DB.ugenSummary "MouseButton"
-
 > import Sound.SC3 {- hsc3 -}
 
 As amplitude envelope
diff --git a/Help/UGen/mouseX.help.lhs b/Help/UGen/mouseX.help.lhs
--- a/Help/UGen/mouseX.help.lhs
+++ b/Help/UGen/mouseX.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "MouseX"
-    Sound.SC3.UGen.DB.ugenSummary "MouseX"
-
 > import Sound.SC3
 
 > e_01 = map from_warp [Linear,Exponential]
diff --git a/Help/UGen/mouseY.help.lhs b/Help/UGen/mouseY.help.lhs
--- a/Help/UGen/mouseY.help.lhs
+++ b/Help/UGen/mouseY.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "MouseY"
-    > Sound.SC3.UGen.DB.ugenSummary "MouseY"
-
 > import Sound.SC3 {- hsc3 -}
 
 Frequency at X axis and amplitude at Y axis.
diff --git a/Help/UGen/mrg2.help.lhs b/Help/UGen/mrg2.help.lhs
--- a/Help/UGen/mrg2.help.lhs
+++ b/Help/UGen/mrg2.help.lhs
@@ -1,24 +1,30 @@
-> :t mrg2
-
-> import Sound.SC3
+> import Sound.SC3 {- hsc3 -}
 
 mrg2 defines a node indicating a multiple root graph.
-> let {l = out 0 (sinOsc AR 300 0 * 0.1)
->     ;r = out 1 (sinOsc AR 900 0 * 0.1)}
-> in audition (mrg2 l r)
 
+> g_01 =
+>   let l = out 0 (sinOsc AR 300 0 * 0.1)
+>       r = out 1 (sinOsc AR 900 0 * 0.1)
+>   in mrg2 l r
+
 there is a leftmost rule, so that mrg nodes need not
 be terminal.
-> let {l = sinOsc AR 300 0 * 0.1
->     ;r = out 1 (sinOsc AR 900 0 * 0.1)}
-> in audition (out 0 (mrg2 l r))
 
+> g_02 =
+>   let l = sinOsc AR 300 0 * 0.1
+>       r = out 1 (sinOsc AR 900 0 * 0.1)
+>   in mrg2 l r
+
 the leftmost node may be an mce node
-> let {l = sinOsc AR (mce2 300 400) 0 * 0.1
->     ;r = out 1 (sinOsc AR 900 0 * 0.1)}
-> in audition (out 0 (mrg2 l r))
 
+> g_03 =
+>   let l = sinOsc AR (mce2 300 400) 0 * 0.1
+>       r = out 1 (sinOsc AR 900 0 * 0.1)
+>   in mrg2 l r
+
 the implementation is not thorough
-> let {l = sinOsc AR (mce2 300 400) 0 * 0.1
->     ;r = out 1 (sinOsc AR 900 0 * 0.1)}
-> in audition (out 0 (mrg2 l r + mrg2 l r))
+
+> g_04 =
+>   let l = sinOsc AR (mce2 300 400) 0 * 0.1
+>       r = out 1 (sinOsc AR 900 0 * 0.1)
+>   in out 0 (mrg2 l r + mrg2 l r)
diff --git a/Help/UGen/mul.help.lhs b/Help/UGen/mul.help.lhs
--- a/Help/UGen/mul.help.lhs
+++ b/Help/UGen/mul.help.lhs
@@ -15,3 +15,9 @@
 >     let p = sinOsc AR (xLine KR 100 1001 10 DoNothing) 0
 >         q = syncSaw AR 100 200
 >     in p * q * 0.25
+
+Optimises identity
+
+> g_04 = sinOsc AR 440 0 * 1 / 10
+
+> g_05 = 1 * sinOsc AR 440 0 / 10
diff --git a/Help/UGen/mulAdd.help.lhs b/Help/UGen/mulAdd.help.lhs
--- a/Help/UGen/mulAdd.help.lhs
+++ b/Help/UGen/mulAdd.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "MulAdd"
-    Sound.SC3.UGen.DB.ugenSummary "MulAdd"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 = mulAdd (sinOsc AR 440 0) 0.1 0.05
@@ -10,3 +7,27 @@
 > g_02 = sinOsc AR 440 0 * 0.1 + 0.05
 
 > g_03 = 0.05 + sinOsc AR 440 0 * 0.1
+
+    > putStrLn $ unlines (map synthstat [g_01,g_02,g_03])
+
+The order of the multiplier inputs is significant regards multi-rate inputs?
+sclang re-orders these if required.
+g_04 CRASHES scsynth.
+
+> g_04 = mulAdd 0.1 (sinOsc AR 440 0) 0.05
+
+    {MulAdd(0.1,SinOsc.ar(440,0),0.05)}.draw
+
+> g_05 = 0.05 + 0.1 * sinOsc AR 440 0
+
+    {0.05 + (0.1 * SinOsc.ar(440,0))}.draw
+
+NOTE: mulAdd with I-RATE at input 0 and K-RATE thereafter CRASHES
+
+> g_06 = sinOsc AR (mulAdd (control IR "x" 110) (control KR "y" 2) (control IR "z" 110)) 0 * 0.1
+
+all AR inputs optimise ordinarily
+
+> g_07 = (sinOsc AR 440 0 * sinOsc AR 441 0 + sinOsc AR 442 0) * 0.1
+
+> g_08 = (sinOsc AR 440 0 + sinOsc AR 441 0 * sinOsc AR 442 0) * 0.1
diff --git a/Help/UGen/mzPokey.help.lhs b/Help/UGen/mzPokey.help.lhs
--- a/Help/UGen/mzPokey.help.lhs
+++ b/Help/UGen/mzPokey.help.lhs
@@ -1,8 +1,5 @@
-    Sound.SC3.UGen.Help.viewSC3Help "MZPokey"
-    Sound.SC3.UGen.DB.ugenSummary "MZPokey"
-
 > import Sound.SC3 {- hsc3 -}
-> import Sound.SC3.UGen.Bindings.HW.External.F0 {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.HW.External.F0 as F0 {- hsc3 -}
 > import qualified Sound.SC3.Lang.Math as M
 
 > bits_to_int :: String -> Int
@@ -13,8 +10,8 @@
 
 > b = bits_to_ugen
 > bln = line KR 0 255 5 RemoveSynth
-> mz1 i j = mzPokey i j 0 0 0 0 0 0 0
-> mz1c i j c = mzPokey i j 0 0 0 0 0 0 c
+> mz1 i j = F0.mzPokey i j 0 0 0 0 0 0 0
+> mz1c i j c = F0.mzPokey i j 0 0 0 0 0 0 c
 
 > g_01 = mz1 bln (b "00001111")
 > g_02 = mz1 bln (b "00101111")
@@ -22,13 +19,13 @@
 > g_04 = mz1c bln (b "10101111") (b "00000001")
 > g_05 = mz1c bln (b "10101111") (b "01000001")
 
-> mz2c i j p q c = mzPokey i j p q 0 0 0 0 c
+> mz2c i j p q c = F0.mzPokey i j p q 0 0 0 0 c
 > bX = mouseX KR 0 255 Linear 0.1
 > bY = mouseY KR 0 255 Linear 0.1
 
 > g_06 = mz2c bX (b "10101010") bY (b "10101010") (b "00000001")
 
-> mz4pc (f1,c1) (f2,c2) (f3,c3) (f4,c4) c = mzPokey f1 c1 f2 c2 f3 c3 f4 c4 c
+> mz4pc (f1,c1) (f2,c2) (f3,c3) (f4,c4) c = F0.mzPokey f1 c1 f2 c2 f3 c3 f4 c4 c
 
 > g_07 =
 >   let v1 = (bX,b "11000111")
diff --git a/Help/UGen/nRand.help.lhs b/Help/UGen/nRand.help.lhs
--- a/Help/UGen/nRand.help.lhs
+++ b/Help/UGen/nRand.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "NRand"
-    Sound.SC3.UGen.DB.ugenSummary "NRand"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 =
diff --git a/Help/UGen/nestedAllpassC.help.lhs b/Help/UGen/nestedAllpassC.help.lhs
--- a/Help/UGen/nestedAllpassC.help.lhs
+++ b/Help/UGen/nestedAllpassC.help.lhs
@@ -1,19 +1,16 @@
-    Sound.SC3.UGen.Help.viewSC3Help "NestedAllpassL"
-    Sound.SC3.UGen.DB.ugenSummary "NestedAllpassL"
-
 > import Sound.SC3 {- hsc3 -}
-> import Sound.SC3.UGen.Bindings.DB.External {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
 
 > nestedAllpassL_def s =
 >   let d1 = 0.036
 >       d2 = 0.030
->   in nestedAllpassL s d1 d1 0.08 d2 d2 0.3
+>   in X.nestedAllpassL s d1 d1 0.08 d2 d2 0.3
 
 > doubleNestedAllpassL_def s =
 >   let d1 = 0.0047
 >       d2 = 0.022
 >       d3 = 0.0084
->   in doubleNestedAllpassL s d1 d1 0.15 d2 d2 0.25 d3 d3 0.3
+>   in X.doubleNestedAllpassL s d1 d1 0.15 d2 d2 0.25 d3 d3 0.3
 
 > f_01 nc s =
 >   let fb = localIn nc AR 0
@@ -28,9 +25,9 @@
 > f_02 nc s =
 >   let fb = localIn nc AR 0
 >       lp = lpf s 6000
->       ap1 = doubleNestedAllpassL (lp + (0.5 * fb)) 0.0047 0.0047 0.25 0.0083 0.0083 0.35 0.022 0.022 0.45
->       ap2 = delayL (nestedAllpassL (delayL ap1 0.05 0.05) 0.03 0.03 0.25952 0.03 0.03 0.3) 0.067 0.067
->       ap3 = nestedAllpassL (lp + (delayL ap2 0.015 0.015 * 0.4)) 0.0292 0.0292 0.25 0.0098 0.0098 0.35
+>       ap1 = X.doubleNestedAllpassL (lp + (0.5 * fb)) 0.0047 0.0047 0.25 0.0083 0.0083 0.35 0.022 0.022 0.45
+>       ap2 = delayL (X.nestedAllpassL (delayL ap1 0.05 0.05) 0.03 0.03 0.25952 0.03 0.03 0.3) 0.067 0.067
+>       ap3 = X.nestedAllpassL (lp + (delayL ap2 0.015 0.015 * 0.4)) 0.0292 0.0292 0.25 0.0098 0.0098 0.35
 >       revout = sum_opt [ap1,ap2,ap3] * 0.5
 >       locout = localOut (bpf (revout * 0.4) 1000 0.5)
 >   in mrg2 revout locout
@@ -40,8 +37,8 @@
 >       lp = lpf s 4000
 >       ap1 = allpassL (lp + (0.5 * fb)) 0.008 0.008 0.0459
 >       ap2 = delayL (allpassL ap1 0.012 0.012 0.06885) 0.004 0.004
->       ap3 = delayL (nestedAllpassL (delayL ap2 0.017 0.017) 0.025 0.025 0.5 0.062 0.062 0.25) 0.031 0.031
->       ap4 = doubleNestedAllpassL (delayL ap3 0.003 0.003) 0.120 0.120 0.5 0.076 0.076 0.25 0.030 0.030 0.25
+>       ap3 = delayL (X.nestedAllpassL (delayL ap2 0.017 0.017) 0.025 0.025 0.5 0.062 0.062 0.25) 0.031 0.031
+>       ap4 = X.doubleNestedAllpassL (delayL ap3 0.003 0.003) 0.120 0.120 0.5 0.076 0.076 0.25 0.030 0.030 0.25
 >       revout = sum_opt [ap4 * 0.8,ap3 * 0.8,ap2 * 1.5]
 >       locout = localOut (bpf (revout * 0.4) 1000 0.5)
 >   in mrg2 revout locout
diff --git a/Help/UGen/nhHall.help.lhs b/Help/UGen/nhHall.help.lhs
--- a/Help/UGen/nhHall.help.lhs
+++ b/Help/UGen/nhHall.help.lhs
@@ -1,11 +1,8 @@
-    Sound.SC3.UGen.Help.viewSC3Help "NHHall"
-    Sound.SC3.UGen.DB.ugenSummary "NHHall"
-
 > import Sound.SC3 {- hsc3 -}
-> import Sound.SC3.UGen.Bindings.DB.External {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
 
 > g_01 =
 >   let in1 = soundIn 0
 >       in2 = soundIn 1
 >       rt60 = mouseX KR 0.1 10.0 Linear 0.1
->   in nhHall in1 in2 rt60 0.5 200 0.5 4000 0.5 0.5 0.5 0.2 0.3
+>   in X.nhHall in1 in2 rt60 0.5 200 0.5 4000 0.5 0.5 0.5 0.2 0.3
diff --git a/Help/UGen/nodeId.help.lhs b/Help/UGen/nodeId.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/nodeId.help.lhs
@@ -0,0 +1,8 @@
+> import Sound.SC3 {- hsc3 -}
+
+NodeId, except that negative nodeId are not reported.
+
+> g_01 = sinOsc AR (mce2 (-100) (nodeID IR * 100)) 0 * 0.1
+
+    audition_at (-1,AddToHead,1,[]) g_01
+    audition_at (8,AddToHead,1,[]) g_01
diff --git a/Help/UGen/numAudioBuses.help.lhs b/Help/UGen/numAudioBuses.help.lhs
--- a/Help/UGen/numAudioBuses.help.lhs
+++ b/Help/UGen/numAudioBuses.help.lhs
@@ -1,3 +0,0 @@
-    Sound.SC3.UGen.Help.viewSC3Help "NumAudioBuses"
-    Sound.SC3.UGen.DB.ugenSummary "NumAudioBuses"
-
diff --git a/Help/UGen/numBuffers.help.lhs b/Help/UGen/numBuffers.help.lhs
--- a/Help/UGen/numBuffers.help.lhs
+++ b/Help/UGen/numBuffers.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "NumBuffers"
-    Sound.SC3.UGen.DB.ugenSummary "NumBuffers"
-
 > import Sound.SC3 {- hsc3 -}
 
 the number of audio buffers available at the server (by default 1024)
diff --git a/Help/UGen/numControlBuses.help.lhs b/Help/UGen/numControlBuses.help.lhs
--- a/Help/UGen/numControlBuses.help.lhs
+++ b/Help/UGen/numControlBuses.help.lhs
@@ -1,2 +0,0 @@
-    Sound.SC3.UGen.Help.viewSC3Help "NumControlBuses"
-    Sound.SC3.UGen.DB.ugenSummary "NumControlBuses"
diff --git a/Help/UGen/numInputBuses.help.lhs b/Help/UGen/numInputBuses.help.lhs
--- a/Help/UGen/numInputBuses.help.lhs
+++ b/Help/UGen/numInputBuses.help.lhs
@@ -1,2 +0,0 @@
-    Sound.SC3.UGen.Help.viewSC3Help "NumInputBuses"
-    Sound.SC3.UGen.DB.ugenSummary "NumInputBuses"
diff --git a/Help/UGen/numOutputBuses.help.lhs b/Help/UGen/numOutputBuses.help.lhs
--- a/Help/UGen/numOutputBuses.help.lhs
+++ b/Help/UGen/numOutputBuses.help.lhs
@@ -1,2 +0,0 @@
-    Sound.SC3.UGen.Help.viewSC3Help "NumOutputBuses"
-    Sound.SC3.UGen.DB.ugenSummary "NumOutputBuses"
diff --git a/Help/UGen/numRunningSynths.help.lhs b/Help/UGen/numRunningSynths.help.lhs
--- a/Help/UGen/numRunningSynths.help.lhs
+++ b/Help/UGen/numRunningSynths.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "NumRunningSynths"
-    Sound.SC3.UGen.DB.ugenSummary "NumRunningSynths"
-
 > import Sound.SC3 {- hsc3 -}
 
 each concurrent audition increases oscillator frequency
diff --git a/Help/UGen/offsetOut.help.lhs b/Help/UGen/offsetOut.help.lhs
--- a/Help/UGen/offsetOut.help.lhs
+++ b/Help/UGen/offsetOut.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "OffsetOut"
-    Sound.SC3.UGen.DB.ugenSummary "OffsetOut"
-
 > import Sound.OSC {- hosc -}
 > import Sound.SC3 {- hsc3 -}
 
diff --git a/Help/UGen/onsets.help.lhs b/Help/UGen/onsets.help.lhs
--- a/Help/UGen/onsets.help.lhs
+++ b/Help/UGen/onsets.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Onsets"
-    > Sound.SC3.UGen.DB.ugenSummary "Onsets"
-
 > import Sound.SC3 {- hsc3 -}
 
     > withSC3 (async (b_alloc 10 512 1))
diff --git a/Help/UGen/osc.help.lhs b/Help/UGen/osc.help.lhs
--- a/Help/UGen/osc.help.lhs
+++ b/Help/UGen/osc.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Osc"
-    > Sound.SC3.UGen.DB.ugenSummary "Osc"
-
 > import Sound.SC3 {- hsc3 -}
 
 Allocate and generate wavetable buffer
diff --git a/Help/UGen/osc1.help.lhs b/Help/UGen/osc1.help.lhs
--- a/Help/UGen/osc1.help.lhs
+++ b/Help/UGen/osc1.help.lhs
@@ -1,9 +1,18 @@
-> import Sound.SC3
+> import Sound.OSC {- hosc -}
+> import Sound.SC3 {- hsc3 -}
 
-> withSC3 (let {z = [Normalise,Wavetable,Clear]
->              ;a = [[13,8,55,34,5,21,3,1,2],[55,34,1,3,2,13,5,8,21]]
->              ;f (b,l) = do {_ <- async (b_alloc b 512 1)
->                            ;send (b_gen_sine1 b z (map recip l))}}
->          in mapM_ f (zip [10,11] a))
+> f_01 (b,l) = do
+>  let z = [Normalise,Wavetable,Clear]
+>  _ <- async (b_alloc b 512 1)
+>  sendMessage (b_gen_sine1 b z (map recip l))
 
-> audition (out 0 (lfSaw AR (mce2 110 164) 0 * 0.1 * osc1 AR (mce2 10 11) 4 RemoveSynth))
+> t_01 :: Transport m => m ()
+> t_01 = do
+>   let a = [[13,8,55,34,5,21,3,1,2],[55,34,1,3,2,13,5,8,21]]
+>   mapM_ f_01 (zip [10,11] a)
+
+    withSC3 t_01
+
+> g_01 = lfSaw AR (mce2 110 164) 0 * 0.1 * osc1 AR (mce2 10 11) 4 RemoveSynth
+
+    audition g_01
diff --git a/Help/UGen/oteyPianoStrings.help.lhs b/Help/UGen/oteyPianoStrings.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/oteyPianoStrings.help.lhs
@@ -0,0 +1,13 @@
+> import Sound.SC3 {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
+
+> g_01 =
+>   let k = control KR
+>       freq = k "freq" 440
+>       gate_ = k "gate" 1
+>       amp = k "amp" 0.5
+>       rho = k "rho" 1
+>       env = envGen AR gate_ 1 0 1 RemoveSynth (envASR 0 1 0.1 EnvLin)
+>       loc = linLin freq (midiCPS 36) (midiCPS 90) (-0.75) 0.75
+>       s = X.oteyPianoStrings AR freq amp 0 0.35 2 4 8 1 7e-2 1.4 (-4) 4 rho 1 1 0 1 0.2 1 1 0.142 1 3e-4 1
+>   in X.oteySoundBoard AR (pan2 (s * env) loc 0.1) 20 20 0.8
diff --git a/Help/UGen/oteySoundBoard.help.lhs b/Help/UGen/oteySoundBoard.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/oteySoundBoard.help.lhs
@@ -0,0 +1,13 @@
+> import Sound.SC3 {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
+
+> g_01 =
+>   let loc = mouseX KR (-1) 1 Linear 0.2
+>   in X.oteySoundBoard AR (pan2 (soundIn 0) loc 0.1) 20 20 0.8
+
+> g_02 =
+>   let d = dust 'α' AR 1
+>       n = whiteNoise 'β' AR
+>       i = decay (d * 0.5) 0.2 * n
+>       loc = mouseX KR (-1) 1 Linear 0.2
+>   in X.oteySoundBoard AR (pan2 i loc 0.1) 20 20 0.8
diff --git a/Help/UGen/out.help.lhs b/Help/UGen/out.help.lhs
--- a/Help/UGen/out.help.lhs
+++ b/Help/UGen/out.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "Out"
-    Sound.SC3.UGen.DB.ugenSummary "Out"
-
 > import Sound.SC3 {- hsc3 -}
 
 Oscillators at outputs zero (330) and one (331)
diff --git a/Help/UGen/packFFT.help.lhs b/Help/UGen/packFFT.help.lhs
--- a/Help/UGen/packFFT.help.lhs
+++ b/Help/UGen/packFFT.help.lhs
@@ -1,22 +1,19 @@
-> Sound.SC3.UGen.Help.viewSC3Help "PackFFT"
-> Sound.SC3.UGen.DB.ugenSummary "PackFFT"
-
-> import Sound.SC3
+> import Sound.SC3 {- hsc3 -}
 
-> withSC3 (async (b_alloc 10 512 1))
+> g_01 =
+>   let b = localBuf 'α' 512 1
+>       n = 100
+>       square a = a * a
+>       r1 z = range 0 1 (fSinOsc KR (expRand (z,'β') 0.1 1) 0)
+>       m1 = map r1 (id_seq n 'γ')
+>       m2 = zipWith (*) m1 (map square [1.0, 0.99 ..])
+>       r2 z = lfPulse KR (2 ** iRand (z,'δ') (-3) 5) 0 0.3
+>       i = map r2 (id_seq n 'ε')
+>       m3 = zipWith (*) m2 i
+>       p = replicate n 0.0
+>       c1 = fft' b (fSinOsc AR 440 0)
+>       c2 = packFFT c1 512 0 (constant n - 1) 1 (packFFTSpec m3 p)
+>       s = ifft' c2
+>   in mce2 s s
 
-> let {n = 100
->     ;square a = a * a
->     ;r1 = let f = expRand 'α' 0.1 1
->           in linLin (fSinOsc KR f 0) (-1) 1 0 1
->     ;m1 = uclone' 'β' n r1
->     ;m2 = zipWith (*) m1 (map square [1.0, 0.99 ..])
->     ;r2 = let r = iRand 'γ' (-3) 5
->           in lfPulse KR (2 ** r) 0 0.3
->     ;i = uclone' 'δ' n r2
->     ;m3 = zipWith (*) m2 i
->     ;p = replicate n 0.0
->     ;c1 = fft' 10 (fSinOsc AR 440 0)
->     ;c2 = packFFT c1 512 0 (constant n - 1) 1 (packFFTSpec m3 p)
->     ;s = ifft' c2}
-> in audition (out 0 (mce [s,s]))
+    > putStrLn $ synthstat_concise g_01
diff --git a/Help/UGen/pan2.help.lhs b/Help/UGen/pan2.help.lhs
--- a/Help/UGen/pan2.help.lhs
+++ b/Help/UGen/pan2.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Pan2"
-    > Sound.SC3.UGen.DB.ugenSummary "Pan2"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 =
diff --git a/Help/UGen/panAz.help.lhs b/Help/UGen/panAz.help.lhs
--- a/Help/UGen/panAz.help.lhs
+++ b/Help/UGen/panAz.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "PanAz"
-    > Sound.SC3.UGen.DB.ugenSummary "PanAz"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 =
diff --git a/Help/UGen/partConv.help.lhs b/Help/UGen/partConv.help.lhs
--- a/Help/UGen/partConv.help.lhs
+++ b/Help/UGen/partConv.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "PartConv"
-    Sound.SC3.UGen.DB.ugenSummary "PartConv"
-
 > import Sound.OSC {- hosc -}
 > import Sound.SC3 {- hsc3 -}
 
diff --git a/Help/UGen/pause.help.lhs b/Help/UGen/pause.help.lhs
--- a/Help/UGen/pause.help.lhs
+++ b/Help/UGen/pause.help.lhs
@@ -1,8 +1,5 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Pause"
-    > Sound.SC3.UGen.DB.ugenSummary "Pause"
-
 > import Sound.SC3 {- hsc3 -}
->
+
 > g_01 =
 >     let f = control KR "f" 440
 >         g = control KR "g" 1
diff --git a/Help/UGen/pauseSelf.help.lhs b/Help/UGen/pauseSelf.help.lhs
--- a/Help/UGen/pauseSelf.help.lhs
+++ b/Help/UGen/pauseSelf.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "PauseSelf"
-    > Sound.SC3.UGen.DB.ugenSummary "PauseSelf"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 =
diff --git a/Help/UGen/pauseSelfWhenDone.help.lhs b/Help/UGen/pauseSelfWhenDone.help.lhs
--- a/Help/UGen/pauseSelfWhenDone.help.lhs
+++ b/Help/UGen/pauseSelfWhenDone.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "PauseSelfWhenDone"
-    > Sound.SC3.UGen.DB.ugenSummary "PauseSelfWhenDone"
-
 > import Sound.SC3 {- hsc3 -}
 
 using PauseSynth done action
@@ -12,12 +9,14 @@
 
 Run paused node (assuming no intermediate node is created).
 
-    > withSC3 (send (n_run [(-1, True)]))
+    > withSC3 (Sound.OSC.sendMessage (n_run [(-1, True)]))
 
+using pauseSelfWhenDone UGen
+
 > g_02 =
 >     let x = mouseX KR (-1) 1 Linear 0.1
 >         e = linen x 1 0.1 1 DoNothing
 >         o = sinOsc AR 440 0 * e
 >     in mrg [o,pauseSelfWhenDone e]
 
-    > withSC3 (send (n_run [(-1, True)]))
+    > withSC3 (Sound.OSC.sendMessage (n_run [(-1, True)]))
diff --git a/Help/UGen/peak.help.lhs b/Help/UGen/peak.help.lhs
--- a/Help/UGen/peak.help.lhs
+++ b/Help/UGen/peak.help.lhs
@@ -1,8 +1,5 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Peak"
-    > Sound.SC3.UGen.DB.ugenSummary "Peak"
-
 > import Sound.SC3 {- hsc3 -}
->
+
 > g_01 =
 >     let t = dust 'α' AR 20
 >         r = impulse AR 0.4 0
diff --git a/Help/UGen/perlin3.help.lhs b/Help/UGen/perlin3.help.lhs
--- a/Help/UGen/perlin3.help.lhs
+++ b/Help/UGen/perlin3.help.lhs
@@ -1,10 +1,7 @@
-    Sound.SC3.UGen.Help.viewSC3Help "Perlin3"
-    Sound.SC3.UGen.DB.ugenSummary "Perlin3"
-
 > import Sound.SC3 {- hsc3 -}
-> import Sound.SC3.UGen.Bindings.DB.External {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
 
 > g_01 =
 >     let x = integrator (k2a (mouseX KR 0 0.1 Linear 0.2)) 1.0
 >         y = integrator (k2a (mouseY KR 0 0.1 Linear 0.2)) 1.0
->     in perlin3 AR x y 0
+>     in X.perlin3 AR x y 0
diff --git a/Help/UGen/phasor.help.lhs b/Help/UGen/phasor.help.lhs
--- a/Help/UGen/phasor.help.lhs
+++ b/Help/UGen/phasor.help.lhs
@@ -1,7 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "Phasor"
-    Sound.SC3.UGen.DB.ugenSummary "Phasor"
-
-> import Prelude hiding ((<*))
 > import Sound.SC3
 
 phasor controls sine frequency, end frequency matches second sine.
@@ -25,8 +21,8 @@
 
 Load sound file to buffer zero
 
-    let fn = "/home/rohan/data/audio/pf-c5.aif"
-    withSC3 (async (b_allocRead 0 fn 0 0))
+    > let fn = "/home/rohan/data/audio/pf-c5.aif"
+    > withSC3 (async (b_allocRead 0 fn 0 0))
 
 Phasor as phase input to bufRd
 
@@ -37,7 +33,7 @@
 Allocate and generate (non-wavetable) buffer at index one
 (see osc for wavetable oscillator)
 
-    withSC3 (mapM_ maybe_async [b_alloc 1 256 1,b_gen_sine1 1 [Normalise,Clear] [1]])
+    > withSC3 (mapM_ maybe_async [b_alloc 1 256 1,b_gen_sine1 1 [Normalise,Clear] [1]])
 
 Audio rate phasor oscillator as phase input to bufRd
 
@@ -54,8 +50,8 @@
 > g_04 =
 >     let impulse_reset freq reset =
 >             let ph = phasor AR reset (freq / sampleRate) 0 1 0
->             in hpz1 ph <* 0
->         x = mouseX KR 0 1 Linear 0.2 >* 0.5
+>             in hpz1 ph <** 0
+>         x = mouseX KR 0 1 Linear 0.2 >** 0.5
 >         ck = impulse AR 3 0
 >         im = impulse_reset 3 x
 >         x' = sinOsc AR 440 0 * x * 0.05
diff --git a/Help/UGen/pinkNoise.help.lhs b/Help/UGen/pinkNoise.help.lhs
--- a/Help/UGen/pinkNoise.help.lhs
+++ b/Help/UGen/pinkNoise.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "PinkNoise"
-    > Sound.SC3.UGen.DB.ugenSummary "PinkNoise"
-
 > import Sound.SC3 {- hsc3 -}
 
     audition . (out 0) . (* 0.05) =<< pinkNoiseM AR
diff --git a/Help/UGen/pitch.help.lhs b/Help/UGen/pitch.help.lhs
--- a/Help/UGen/pitch.help.lhs
+++ b/Help/UGen/pitch.help.lhs
@@ -1,5 +1,5 @@
-     Sound.SC3.UGen.Help.viewSC3Help "Pitch"
-     Sound.SC3.UGen.DB.ugenSummary "Pitch"
+ 
+ 
 
 > import Sound.SC3 {- hsc3 -}
 
@@ -11,11 +11,14 @@
 >         f = pitch s 440 60 4000 100 16 7 0.02 0.5 1 0
 >     in mce [s, sinOsc AR (mceChannel 0 f / 2) 0 * a]
 
+Live input tracking, carelessly
+
 > g_02 =
->     let s = soundIn 0
->         a = amplitude KR s 0.1 0.1
->         f = pitch s 440 60 4000 100 16 7 0.02 0.5 1 0
->     in mce [s * 0.1, sinOsc AR (mceChannel 0 f) 0 * a]
+>     let s = hpf (soundIn 0) 90
+>         a = lag (amplitude KR s 0.01 0.01) 0.2
+>         [f,_] = mceChannels (pitch s 440 60 4000 100 16 1 0.02 0.5 1 0)
+>         fq = midiCPS (roundE (lag (cpsMIDI f) 0.1))
+>     in mce [s * 0.1, lfTri AR f 0 * lag a 0.2 * lag (f >** 90 * f <** 500) 0.2]
 
 Comparison of input frequency (x) and tracked oscillator frequency (f).
 Output is printed to the console by scsynth.
diff --git a/Help/UGen/pitchShift.help.lhs b/Help/UGen/pitchShift.help.lhs
--- a/Help/UGen/pitchShift.help.lhs
+++ b/Help/UGen/pitchShift.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "PitchShift"
-    > Sound.SC3.UGen.DB.ugenSummary "PitchShift"
-
 > import Sound.SC3 {- hsc3 -}
 
 > gr_01 =
diff --git a/Help/UGen/playBuf.help.lhs b/Help/UGen/playBuf.help.lhs
--- a/Help/UGen/playBuf.help.lhs
+++ b/Help/UGen/playBuf.help.lhs
@@ -1,34 +1,33 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "PlayBuf"
-    > Sound.SC3.UGen.DB.ugenSummary "PlayBuf"
-
 > import Sound.SC3 {- hsc3 -}
 
 Load sound file to buffer zero (single channel file required for examples)
 
-> f_01 = "/home/rohan/data/audio/pf-c5.aif"
+> fn_01 = "/home/rohan/data/audio/pf-c5.aif"
 
-> m_01 = (b_allocRead 0 f_01 0 0)
+> m_01 = (b_allocRead 0 fn_01 0 0)
 
     withSC3 (async m_01)
 
 Play once only.
 
-> gr_01 = playBuf 1 AR 0 (bufRateScale KR 0) 1 0 NoLoop RemoveSynth
+> f_01 b = playBuf 1 AR b (bufRateScale KR b) 1 0 NoLoop RemoveSynth
 
+> g_01 = f_01 28 -- 0 28
+
 Play in infinite loop.
 
-> gr_02 = playBuf 1 AR 0 (bufRateScale KR 0) 1 0 Loop DoNothing
+> g_02 = playBuf 1 AR 0 (bufRateScale KR 0) 1 0 Loop DoNothing
 
 Trigger playback at each pulse.
 
-> gr_03 =
+> g_03 =
 >     let t = impulse KR 2 0
 >         s = bufRateScale KR 0
 >     in playBuf 1 AR 0 s t 0 NoLoop DoNothing
 
 Trigger playback at each pulse (diminishing intervals).
 
-> gr_04 =
+> g_04 =
 >     let f = xLine KR 0.1 100 10 RemoveSynth
 >         t = impulse KR f 0
 >         s = bufRateScale KR 0
@@ -36,13 +35,13 @@
 
 Loop playback, accelerating pitch.
 
-> gr_05 =
+> g_05 =
 >     let r = xLine KR 0.1 100 60 RemoveSynth
 >     in playBuf 1 AR 0 r 1 0 Loop DoNothing
 
 Sine wave control of playback rate, negative rate plays backwards.
 
-> gr_06 =
+> g_06 =
 >     let f = xLine KR 0.2 8 30 RemoveSynth
 >         r = fSinOsc KR f 0 * 3 + 0.6
 >         s = bufRateScale KR 0 * r
@@ -51,7 +50,7 @@
 Channel mismatch, single channel buffer, two channel playBuf, result
 is single channel playback and channel mismatch message in server log.
 
-> gr_07 = playBuf 2 AR 0 (bufRateScale KR 0) 1 0 Loop DoNothing
+> g_07 = playBuf 2 AR 0 (bufRateScale KR 0) 1 0 Loop DoNothing
 
 Graph will play both channels after loading a two channel signal to
 buffer.
@@ -68,11 +67,13 @@
 
 Scan sequence of buffers:
 
-> gr_08 =
->     let n = 29 * 6
+> f_08 n =
+>     let t = impulse KR 2 0
 >         b = mouseX KR 0 n Linear 0.2
 >         r = bufRateScale KR b
->     in playBuf 1 AR b r 1 0 Loop DoNothing
+>     in playBuf 1 AR b r t 0 Loop DoNothing
+
+> g_08 = f_08 52 -- (29 * 6)
 
 In sclanguage:
 
diff --git a/Help/UGen/playBufCF.help.lhs b/Help/UGen/playBufCF.help.lhs
--- a/Help/UGen/playBufCF.help.lhs
+++ b/Help/UGen/playBufCF.help.lhs
@@ -1,5 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "PlayBufCF"
-
 wslib: external/composite
 
 > import Sound.SC3 {- hsc3 -}
diff --git a/Help/UGen/pluck.help.lhs b/Help/UGen/pluck.help.lhs
--- a/Help/UGen/pluck.help.lhs
+++ b/Help/UGen/pluck.help.lhs
@@ -1,7 +1,5 @@
-    Sound.SC3.UGen.Help.viewSC3Help "Pluck"
-    Sound.SC3.UGen.DB.ugenSummary "Pluck"
-
 > import Sound.SC3 {- hsc3 -}
+> import Sound.SC3.UGen.Protect {- hsc3-rw -}
 
 Excitation signal is white noise, triggered twice a second with varying OnePole coef.
 
@@ -15,7 +13,7 @@
 
 > g_02 =
 >     let n = 50
->         udup = uclone 'α'
+>         udup = uclone (const False) 'α'
 >         f = udup n (rand 'β' 0.05 0.2)
 >         p = udup n (rand 'γ' 0 1)
 >         w = udup n (whiteNoise 'δ' AR)
diff --git a/Help/UGen/pmOsc.help.lhs b/Help/UGen/pmOsc.help.lhs
--- a/Help/UGen/pmOsc.help.lhs
+++ b/Help/UGen/pmOsc.help.lhs
@@ -1,9 +1,8 @@
-    Sound.SC3.UGen.Help.viewSC3Help "PMOsc"
     :t pmOsc
 
 pmOsc is a composite of sinOsc, ie. sinOsc r cf (sinOsc r mf mp * pm)
 
-> import Sound.SC3
+> import Sound.SC3 {- hsc3 -}
 
 Random parameters, linear modulation index motion over n seconds
 
diff --git a/Help/UGen/poll.help.lhs b/Help/UGen/poll.help.lhs
--- a/Help/UGen/poll.help.lhs
+++ b/Help/UGen/poll.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Poll"
-    > Sound.SC3.UGen.DB.ugenSummary "Poll"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 =
@@ -35,3 +32,11 @@
 
     import Sound.OSC {- hosc -}
     withSC3 (sendMessage (n_set1 (-1) "t" 1))
+
+print oscillator frequency
+
+> g_05 =
+>     let x = mouseX KR 200 260 Exponential 0.2
+>         o = sinOsc AR x 0 * 0.25
+>         t = impulse KR 2 0
+>     in mrg2 o (poll t x 0 (label "polling..."))
diff --git a/Help/UGen/pow.help.lhs b/Help/UGen/pow.help.lhs
--- a/Help/UGen/pow.help.lhs
+++ b/Help/UGen/pow.help.lhs
@@ -1,8 +1,5 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Operator.**"
-    > :t (**)
-
 > import Sound.SC3 {- hsc3 -}
->
+
 > g_01 =
 >     let a = fSinOsc AR 100 0 * 0.1
 >     in mce2 a (a ** 10)
@@ -18,3 +15,7 @@
 >         d = latch s (impulse AR x 0)
 >         b = roundUp d (0.5 ** y)
 >     in mce2 d b
+
+optimises identity
+
+> g_03 = (sinOsc AR 440 0 ** 1) * 0.1
diff --git a/Help/UGen/pulse.help.lhs b/Help/UGen/pulse.help.lhs
--- a/Help/UGen/pulse.help.lhs
+++ b/Help/UGen/pulse.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Pulse"
-    > Sound.SC3.UGen.DB.ugenSummary "Pulse"
-
 > import Sound.SC3 {- hsc3 -}
 
 Modulate frequency
diff --git a/Help/UGen/pulseDPW.help.lhs b/Help/UGen/pulseDPW.help.lhs
--- a/Help/UGen/pulseDPW.help.lhs
+++ b/Help/UGen/pulseDPW.help.lhs
@@ -1,8 +1,6 @@
-    Sound.SC3.UGen.Help.viewSC3Help "PulseDPW"
-    Sound.SC3.UGen.DB.ugenSummary "PulseDPW"
-
 > import Sound.SC3 {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.Composite.External as X {- hsc3 -}
 
-> g_01 = pulseDPW AR (xLine KR 2000 20 10 DoNothing) 0.5 * 0.1
+> g_01 = X.pulseDPW AR (xLine KR 2000 20 10 DoNothing) 0.5 * 0.1
 
-> g_02 = pulseDPW AR (mouseX KR 200 12000 Exponential 0.2) 0.5 * 0.2
+> g_02 = X.pulseDPW AR (mouseX KR 200 12000 Exponential 0.2) 0.5 * 0.2
diff --git a/Help/UGen/pulseDivider.help.lhs b/Help/UGen/pulseDivider.help.lhs
--- a/Help/UGen/pulseDivider.help.lhs
+++ b/Help/UGen/pulseDivider.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "PulseDivider"
-    > Sound.SC3.UGen.DB.ugenSummary "PulseDivider"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 =
diff --git a/Help/UGen/pv_BinDelay.help.lhs b/Help/UGen/pv_BinDelay.help.lhs
--- a/Help/UGen/pv_BinDelay.help.lhs
+++ b/Help/UGen/pv_BinDelay.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "PV_BinDelay"
-    > Sound.SC3.UGen.DB.ugenSummary "PV_BinDelay"
-
 > import Sound.OSC {- hsc3 -}
 > import Sound.SC3 {- hsc3 -}
 > import Sound.SC3.UGen.Bindings.DB.External {- hsc3 -}
diff --git a/Help/UGen/pv_Compander.help.lhs b/Help/UGen/pv_Compander.help.lhs
--- a/Help/UGen/pv_Compander.help.lhs
+++ b/Help/UGen/pv_Compander.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "Compander"
-    Sound.SC3.UGen.DB.ugenSummary "Compander"
-
 > import Sound.SC3 {- hsc3 -}
 > import Sound.SC3.UGen.Bindings.DB.External {- hsc3 -}
 
diff --git a/Help/UGen/pv_Copy.help.lhs b/Help/UGen/pv_Copy.help.lhs
--- a/Help/UGen/pv_Copy.help.lhs
+++ b/Help/UGen/pv_Copy.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "PV_Copy"
-    > Sound.SC3.UGen.DB.ugenSummary "PV_Copy"
-
 > import Sound.SC3 {- hsc3 -}
 
 Proof of concept, silence.  This graph is disallowed.  pv_Copy is
diff --git a/Help/UGen/pv_Diffuser.help.lhs b/Help/UGen/pv_Diffuser.help.lhs
--- a/Help/UGen/pv_Diffuser.help.lhs
+++ b/Help/UGen/pv_Diffuser.help.lhs
@@ -3,14 +3,14 @@
 
 > import Sound.SC3 {- hsc3 -}
 
-> n_01 = "/home/rohan/data/audio/pf-c5.snd"
+> n_01 = "/usr/share/SuperCollider/sounds/a11wlk01.wav"
+> n_02 = "/home/rohan/data/audio/instr/bosendorfer/064/C5.aif"
 
-> m_01 = b_allocRead 12 n_01 0 0
+> m_01 = b_allocRead 12 n_02 0 0
 
     withSC3 (async m_01)
 
 > g_01 = playBuf 1 AR 12 (bufRateScale KR 12) 0 0 Loop DoNothing
-
 > g_02 = soundIn 0
 
 Trigger revised phase shifts with MouseX crossing center of screen
@@ -18,7 +18,8 @@
 > f_01 z =
 >   let f = fft' (localBuf 'α' 2048 1) z
 >       x = mouseX KR 0 1 Linear 0.1
->       h = pv_Diffuser f (x >* 0.5)
+>       h = pv_Diffuser f (x >** 0.5)
 >   in ifft' h * 0.5
 
-> g_03 = f_01 g_02
+> g_03 = f_01 g_01
+> g_04 = f_01 g_02
diff --git a/Help/UGen/pv_Freeze.help.lhs b/Help/UGen/pv_Freeze.help.lhs
--- a/Help/UGen/pv_Freeze.help.lhs
+++ b/Help/UGen/pv_Freeze.help.lhs
@@ -2,10 +2,10 @@
     Sound.SC3.UGen.DB.ugenSummary "PV_Freeze"
 
 > import Sound.SC3 {- hsc3 -}
-> import Sound.SC3.UGen.Bindings.DB.External {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
 
 > g_01 =
 >   let f = fft' (localBuf 'α' 2048 1) (soundIn 0)
 >       x = mouseX KR 0 1 Linear 0.1
->       h = pv_Freeze f (x >* 0.5)
+>       h = X.pv_Freeze f (x >** 0.5)
 >   in ifft' h * 0.5
diff --git a/Help/UGen/pv_MagFreeze.help.lhs b/Help/UGen/pv_MagFreeze.help.lhs
--- a/Help/UGen/pv_MagFreeze.help.lhs
+++ b/Help/UGen/pv_MagFreeze.help.lhs
@@ -31,7 +31,7 @@
 > f_01 z =
 >   let f = fft' (localBuf 'α' 2048 1) z
 >       x = mouseX KR 0 1 Linear 0.1
->       h = pv_MagFreeze f (x >* 0.5)
+>       h = pv_MagFreeze f (x >** 0.5)
 >   in ifft' h * 0.5
 
 > g_04 = f_01 g_03
diff --git a/Help/UGen/pv_RandWipe.help.lhs b/Help/UGen/pv_RandWipe.help.lhs
--- a/Help/UGen/pv_RandWipe.help.lhs
+++ b/Help/UGen/pv_RandWipe.help.lhs
@@ -21,5 +21,5 @@
 >       f2 = fft' (localBuf 'β' 2048 1) g_02
 >       x = mouseX KR 0 1 Linear 0.1
 >       y = mouseY KR 0 1 Linear 0.1
->       h = pv_RandWipe 'γ' f1 f2 x (y >* 0.5)
+>       h = pv_RandWipe 'γ' f1 f2 x (y >** 0.5)
 >   in pan2 (ifft' h) 0 0.5
diff --git a/Help/UGen/pv_SpectralMap.help.lhs b/Help/UGen/pv_SpectralMap.help.lhs
--- a/Help/UGen/pv_SpectralMap.help.lhs
+++ b/Help/UGen/pv_SpectralMap.help.lhs
@@ -2,9 +2,10 @@
     Sound.SC3.UGen.DB.ugenSummary "PV_SpectralMap"
 
 > import Sound.SC3 {- hsc3 -}
-> import Sound.SC3.UGen.Bindings.DB.External {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
 
-> n_01 = "/home/rohan/opt/src/supercollider/sounds/a11wlk01.wav"
+> n_01 = "/usr/share/SuperCollider/sounds/a11wlk01.wav"
+> n_02 = "/home/rohan/data/audio/instr/bosendorfer/064/C5.aif"
 
 > m_01 = b_allocRead 10 n_01 0 0
 
@@ -16,5 +17,5 @@
 >       b = localBuf 'β' 2048 1
 >       c1 = fft' a (soundIn 0)
 >       c2 = fft' b (playBuf 1 AR 10 1 1 0 Loop DoNothing)
->       c3 = pv_SpectralMap c1 c2 0.0 freeze (mouseX KR (-1) 1 Linear 0.2) 1 0
+>       c3 = X.pv_SpectralMap c1 c2 0.0 freeze (mouseX KR (-1) 1 Linear 0.2) 1 0
 >   in ifft' c3
diff --git a/Help/UGen/pvcollect.help.lhs b/Help/UGen/pvcollect.help.lhs
--- a/Help/UGen/pvcollect.help.lhs
+++ b/Help/UGen/pvcollect.help.lhs
@@ -1,53 +1,55 @@
-> Sound.SC3.UGen.Help.viewSC3Help "PV_ChainUGen.pvcollect"
-> :t pvcollect
-
-> import Prelude hiding ((<*))
 > import Data.List {- base -}
+> import Sound.OSC {- hosc -}
 > import Sound.SC3 {- hsc3 -}
 
-> let fileName = "/home/rohan/data/audio/pf-c5.snd"
-> in withSC3 (do {_ <- async (b_alloc 10 1024 1)
->                ;async (b_allocRead 11 fileName 0 0)})
+> file_name = "/home/rohan/data/audio/instr/bosendorfer/064/C5.aif"
 
-> let spectral_delay m p _ =
->     let {l = lfPar KR 0.5 0
->         ;v = linLin l (-1) 1 0.1 1}
->     in (m + delayN m 1 v,p)
+> alloc_buf :: DuplexOSC m => m Message
+> alloc_buf = do
+>   _ <- async (b_alloc 10 1024 1)
+>   async (b_allocRead 11 file_name 0 0)
 
-> let bpf_sweep nf m p i =
->     let {l = lfPar KR 0.1 0
->         ;e = abs (i - (linLin l (-1) 1 2 (nf / 20)))}
->     in ((e <* 10) * m,p)
+    > withSC3 alloc_buf
 
-> let pv_g nf cf =
->   let {no_op m p _ = (m,p)
->       ;combf m p i = ((modE i 7.0 ==* 0) * m,p)
->       ;sf = playBuf 1 AR 11 (bufRateScale KR 11) 1 0 Loop DoNothing
->       ;c1 = fft' 10 sf
->       ;c2 = pvcollect c1 nf cf 0 250 0}
->   in out 0 (0.1 * ifft' c2)
+> spectral_delay m p _ =
+>   let l = lfPar KR 0.5 0
+>       v = linLin l (-1) 1 0.1 1
+>   in (m + delayN m 1 v,p)
 
-> let pv_au nf cf =
->   let {no_op m p _ = (m,p)
->       ;combf m p i = ((modE i 7.0 ==* 0) * m,p)
->       ;c1 = fft' 10 (soundIn 0)
->       ;c2 = pvcollect c1 nf cf 0 250 0}
->   in out 0 (0.1 * ifft' c2)
+> bpf_sweep nf m p i =
+>   let l = lfPar KR 0.1 0
+>       e = abs (constant i - (linLin l (-1) 1 2 (constant nf / 20)))
+>   in ((e <** 10) * m,p)
 
-> let r = unlines ["number of constants       : 257"
->                 ,"number of controls        : 0"
->                 ,"control rates             : []"
->                 ,"number of unit generators : 1013"
->                 ,"unit generator rates      : [(KR,5),(AR,4),(DR,1004)]"]
-> in r `isPrefixOf` synthstat (pv_g 1024 spectral_delay)
+> pv_g nf cf =
+>   let no_op m p _ = (m,p)
+>       combf m p i = ((modE i 7.0 ==** 0) * m,p)
+>       sf = playBuf 1 AR 11 (bufRateScale KR 11) 1 0 Loop DoNothing
+>       c1 = fft' 10 sf
+>       c2 = pvcollect c1 nf cf 0 250 0
+>   in 0.1 * ifft' c2
 
-> synthstat (pv_g 1024 (bpf_sweep 1024))
-> audition (pv_g 1024 spectral_delay)
-> audition (pv_g 1024 (bpf_sweep 1024))
+> pv_au nf cf =
+>   let no_op m p _ = (m,p)
+>       combf m p i = ((modE i 7.0 ==** 0) * m,p)
+>       c1 = fft' 10 (soundIn 0)
+>       c2 = pvcollect c1 nf cf 0 250 0
+>   in 0.1 * ifft' c2
 
-> audition (pv_au 1024 spectral_delay)
-> audition (pv_au 1024 (bpf_sweep 1024))
+    > putStrLn $ synthstat_concise (pv_g 1024 spectral_delay)
 
-> import Sound.SC3.UGen.Dot {- hsc3-dot -}
+    > number of constants       : 257
+    > number of controls        : 0
+    > control rates             : []
+    > number of unit generators : 1013
+    > unit generator rates      : [(KR,5),(AR,4),(DR,1004)]
 
-> draw_svg (pv_g 1024 (bpf_sweep 1024))
+   > putStrLn $ synthstat_concise (pv_g 1024 (bpf_sweep 1024))
+
+> g_01 = pv_g 1024 spectral_delay
+> g_02 = pv_g 1024 (bpf_sweep 1024)
+> g_03 = pv_au 1024 spectral_delay
+> g_04 = pv_au 1024 (bpf_sweep 1024)
+
+    > import Sound.SC3.UGen.Dot {- hsc3-dot -}
+    > draw_svg (pv_g 1024 (bpf_sweep 1024))
diff --git a/Help/UGen/qitch.help.lhs b/Help/UGen/qitch.help.lhs
--- a/Help/UGen/qitch.help.lhs
+++ b/Help/UGen/qitch.help.lhs
@@ -1,23 +1,30 @@
-> Sound.SC3.UGen.Help.viewSC3Help "Qitch"
-> Sound.SC3.UGen.DB.ugenSummary "Qitch"
-
-> import Sound.SC3
-> import System.FilePath
+> import Sound.SC3 {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
 
 Load required data file (edit path as required)
 
-> let {d = "/home/rohan/opt/share/SuperCollider/Extensions/SC3plugins"
->     ;qf = d </> "PitchDetection/extraqitchfiles/QspeckernN2048SR48000.wav"}
-> in withSC3 (async (b_allocRead 10 qf 0 0))
+    > import System.FilePath {- filepath -}
+    > d = "/home/rohan/opt/share/SuperCollider/Extensions/SC3plugins"
+    > d = "/usr/share/SuperCollider/Extensions/SC3plugins"
+    > qf = d </> "PitchDetection/extraqitchfiles/QspeckernN2048SR48000.wav"
+    > withSC3 (async (b_allocRead 10 qf 0 0))
 
 Comparison of input frequency (x) and tracked oscillator frequency (f).
 Output is printed to the console by scsynth.
 
-> let {x = mouseX KR 440 880 Exponential 0.1
->     ;o = sinOsc AR x 0 * 0.1
->     ;[f,e] = mceChannels (qitch KR o 10 1e-2 1 0 0 2500)
->     ;r = sinOsc AR f 0 * 0.1
->     ;t = impulse KR 4 0
->     ;pf = poll t f (label "f") 0
->     ;px = poll t x (label "x") 0}
-> in audition (mrg [out 0 (mce2 o r),pf,px])
+> g_01 =
+>   let x = mouseX KR 440 880 Exponential 0.1
+>       o = sinOsc AR x 0 * 0.1
+>       [f,_e] = mceChannels (X.qitch KR o 10 1e-2 1 0 0 2500)
+>       r = sinOsc AR f 0 * 0.1
+>       t = impulse KR 4 0
+>       pf = poll t f 0 (label "f")
+>       px = poll t x 0 (label "x")
+>   in mrg [out 0 (mce2 o r),pf,px]
+
+> g_02 =
+>   let s = hpf (soundIn 0) 110
+>       [f,e] = mceChannels (X.qitch KR s 10 0.01 1 0 0 2500)
+>       a = amplitude KR s 0.15 0.25
+>       r = sinOsc AR f 0 * a * e
+>   in out 0 (mce2 (s * 0.1) r)
diff --git a/Help/UGen/quadN.help.lhs b/Help/UGen/quadN.help.lhs
--- a/Help/UGen/quadN.help.lhs
+++ b/Help/UGen/quadN.help.lhs
@@ -1,9 +1,6 @@
-    Sound.SC3.UGen.Help.viewSC3Help "QuadN"
-    Sound.SC3.UGen.DB.ugenSummary "QuadN"
-
 > import Sound.SC3 {- hsc3 -}
 
-> g_01 = quadC AR (sampleRate / 4) 1 (-1) (-0.75) 0 * 0.2
+> g_01 = quadC AR (sampleRate / 2) 1 (-1) (-0.75) 0 * 0.2
 
 > g_02 =
 >   let x = mouseX KR 3.5441 4 Linear 0.1
diff --git a/Help/UGen/rMEQ.help.lhs b/Help/UGen/rMEQ.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/rMEQ.help.lhs
@@ -0,0 +1,17 @@
+> import Sound.SC3 {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
+
+rm = regalia-mitra
+freq = cut-off frequency (hz)
+rq = reciprocal-of-Q
+k = gain (db)
+
+default parameters
+
+> g_01 = X.rMEQ AR (pinkNoise 'α' AR * 0.1) 440 1 0
+
+> g_02 =
+>   let freq = mouseX KR 55 3520 Exponential 0.2
+>       rq = mouseY KR 0.01 2.0 Linear 0.2
+>       k = 3
+>   in X.rMEQ AR (pinkNoise 'α' AR * 0.1) freq rq k
diff --git a/Help/UGen/rMShelf.help.lhs b/Help/UGen/rMShelf.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/rMShelf.help.lhs
@@ -0,0 +1,23 @@
+> import Sound.SC3 {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
+
+rm = regalia-mitra
+freq = cut-off frequency (hz)
+k = gain (db)
+
+default parameters
+
+> g_01 = X.rMShelf2 AR (whiteNoise 'α' AR * 0.1) 440 0
+
+freq = mouse-x
+
+> g_02 =
+>   let freq = mouseX KR 55 3520 Exponential 0.2
+>   in X.rMShelf2 AR (whiteNoise 'α' AR * 0.1) freq 0
+
+k = mouse-y
+
+> g_03 =
+>   let freq = mouseX KR 55 3520 Exponential 0.2
+>       k = mouseY KR (-12) 12 Linear 0.2
+>   in X.rMShelf2 AR (whiteNoise 'α' AR * 0.1) freq k
diff --git a/Help/UGen/radiansPerSample.help.lhs b/Help/UGen/radiansPerSample.help.lhs
--- a/Help/UGen/radiansPerSample.help.lhs
+++ b/Help/UGen/radiansPerSample.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "RadiansPerSample"
-    > Sound.SC3.UGen.DB.ugenSummary "RadiansPerSample"
-
 > import Sound.SC3 {- hsc3 -}
 
 two pi divided by the nominal sample rate (ie. a very small number)
diff --git a/Help/UGen/ramp.help.lhs b/Help/UGen/ramp.help.lhs
--- a/Help/UGen/ramp.help.lhs
+++ b/Help/UGen/ramp.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "Ramp"
-    Sound.SC3.UGen.DB.ugenSummary "Ramp"
-
 > import Sound.SC3 {- hsc3 -}
 
 Used to lag pitch
diff --git a/Help/UGen/rand.help.lhs b/Help/UGen/rand.help.lhs
--- a/Help/UGen/rand.help.lhs
+++ b/Help/UGen/rand.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "Rand"
-    Sound.SC3.UGen.DB.ugenSummary "Rand"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 =
diff --git a/Help/UGen/randID.help.lhs b/Help/UGen/randID.help.lhs
--- a/Help/UGen/randID.help.lhs
+++ b/Help/UGen/randID.help.lhs
@@ -1,2 +0,0 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "RandID"
-    > Sound.SC3.UGen.DB.ugenSummary "RandID"
diff --git a/Help/UGen/randSeed.help.lhs b/Help/UGen/randSeed.help.lhs
--- a/Help/UGen/randSeed.help.lhs
+++ b/Help/UGen/randSeed.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "RandSeed"
-    Sound.SC3.UGen.DB.ugenSummary "RandSeed"
-
 > import Sound.SC3
 
 start a noise patch
diff --git a/Help/UGen/recordBuf.help.lhs b/Help/UGen/recordBuf.help.lhs
--- a/Help/UGen/recordBuf.help.lhs
+++ b/Help/UGen/recordBuf.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "RecordBuf"
-    Sound.SC3.UGen.DB.ugenSummary "RecordBuf"
-
 > import Sound.SC3 {- hsc3 -}
 
 > b_01 :: Num n => n
diff --git a/Help/UGen/redPhasor.help.lhs b/Help/UGen/redPhasor.help.lhs
--- a/Help/UGen/redPhasor.help.lhs
+++ b/Help/UGen/redPhasor.help.lhs
@@ -1,25 +1,22 @@
-    Sound.SC3.UGen.Help.viewSC3Help "RedPhasor"
-    Sound.SC3.UGen.DB.ugenSummary "RedPhasor"
-
 > import Sound.SC3 {- hsc3 -}
-> import Sound.SC3.UGen.Bindings.HW.External.F0 {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.HW.External.F0 as F0 {- hsc3 -}
 
 no looping & it will play through once. Mouse x acts as trigger
 
 > g_01 =
->   let tr = mouseX KR 0 1 Linear 0.2 >* 0.5
->   in sinOsc AR (redPhasor KR tr 0.3 400 800 0 500 600) 0 * 0.2
+>   let tr = mouseX KR 0 1 Linear 0.2 >** 0.5
+>   in sinOsc AR (F0.redPhasor KR tr 0.3 400 800 0 500 600) 0 * 0.2
 
 mouse y controls looping on/off, mouse x trigger
 
 > g_02 =
->   let tr = mouseX KR 0 1 Linear 0.2 >* 0.5
->       lp = mouseY KR 0 1 Linear 0.2 >* 0.5
->   in sinOsc AR (redPhasor KR tr 0.3 400 800 lp 500 600) 0 * 0.2
+>   let tr = mouseX KR 0 1 Linear 0.2 >** 0.5
+>       lp = mouseY KR 0 1 Linear 0.2 >** 0.5
+>   in sinOsc AR (F0.redPhasor KR tr 0.3 400 800 lp 500 600) 0 * 0.2
 
 mouse x controls loop rate, mouse y scales the start looppoint
 
 > g_03 =
 >   let x = mouseX KR 0 5 Linear 0.2
 >       y = mouseY KR 200 500 Linear 0.2
->   in sinOsc AR (redPhasor KR 0 x 400 800 1 y 600) 0 * 0.2
+>   in sinOsc AR (F0.redPhasor KR 0 x 400 800 1 y 600) 0 * 0.2
diff --git a/Help/UGen/replaceOut.help.lhs b/Help/UGen/replaceOut.help.lhs
--- a/Help/UGen/replaceOut.help.lhs
+++ b/Help/UGen/replaceOut.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "ReplaceOut"
-    Sound.SC3.UGen.DB.ugenSummary "ReplaceOut"
-
 > import Sound.OSC {- hosc -}
 > import Sound.SC3 {- hsc3 -}
 
@@ -8,21 +5,21 @@
 
 Send signal to a bus, overwrite existing signal.
 
-> g_02 =
->     let a = out 0 (sinOsc AR (mce [330, 331]) 0 * 0.1)
->         b = replaceOut 0 (sinOsc AR (mce [880, 881]) 0 * 0.1)
->         c = out 0 (sinOsc AR (mce [120, 121]) 0 * 0.1)
+> f_02 a_out b_out c_out =
+>     let a = a_out 0 (sinOsc AR (mce [330, 331]) 0 * 0.1)
+>         b = b_out 0 (sinOsc AR (mce [880, 881]) 0 * 0.1)
+>         c = c_out 0 (sinOsc AR (mce [120, 121]) 0 * 0.1)
 >     in mrg [a, b, c]
 
-Compare to
+The MRG nodes are ordered right to left, so below b replaces c and a is summed
 
-> g_03 =
->     let a = out 0 (sinOsc AR (mce [330, 331]) 0 * 0.1)
->         b = out 0 (sinOsc AR (mce [880, 881]) 0 * 0.1)
->         c = out 0 (sinOsc AR (mce [120, 121]) 0 * 0.1)
->     in mrg [a,b,c]
+> g_02 = f_02 out replaceOut out
 
-- a writes noise to 24
+Compare to, where c is also heard
+
+> g_03 = f_02 out out out
+
+- a writes noise to bus 24
 - b reads 24 and replaces with filtered variant
 - c reads 24 and writes to 0
 
diff --git a/Help/UGen/resonz.help.lhs b/Help/UGen/resonz.help.lhs
--- a/Help/UGen/resonz.help.lhs
+++ b/Help/UGen/resonz.help.lhs
@@ -1,7 +1,26 @@
-    Sound.SC3.UGen.Help.viewSC3Help "Resonz"
-    Sound.SC3.UGen.DB.ugenSummary "Resonz"
-
 > import Sound.SC3 {- hsc3 -}
+
+The Q factor of a resonator is defined as the center-frequency (cf) divided by the bandwidth (bw).
+
+    > let q cf bw = cf / bw
+
+The higher the Q the narrower the filter.
+
+    > let bw_set = [1,4,10,100,200,400]
+    > map (q 400) bw_set == [400,100,40,4,2,1]
+
+Q multipled by the band-width gives the center-frequency.
+
+    > map (\bw -> q 400 bw * bw) bw_set == replicate (length bw_set) 400
+
+The third argument to resonz is the reciprocal of Q (rq).
+
+    > let rq cf = recip . q cf
+    > map (rq 400) [1,4,10,100,200,400] == [1/400,1/100,1/40,1/4,1/2,1]
+
+1/Q multiplied by the center-frequency gives the bandwidth.
+
+    > map (\bw -> rq 400 bw * 400) bw_set == bw_set
 
 > g_01 =
 >   let n = whiteNoise 'α' AR
diff --git a/Help/UGen/rhpf.help.lhs b/Help/UGen/rhpf.help.lhs
--- a/Help/UGen/rhpf.help.lhs
+++ b/Help/UGen/rhpf.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "RHPF"
-    Sound.SC3.UGen.DB.ugenSummary "RHPF"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 =
diff --git a/Help/UGen/ringz.help.lhs b/Help/UGen/ringz.help.lhs
--- a/Help/UGen/ringz.help.lhs
+++ b/Help/UGen/ringz.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "Ringz"
-    Sound.SC3.UGen.DB.ugenSummary "Ringz"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 =
diff --git a/Help/UGen/rlpf.help.lhs b/Help/UGen/rlpf.help.lhs
--- a/Help/UGen/rlpf.help.lhs
+++ b/Help/UGen/rlpf.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "RLPF"
-    Sound.SC3.UGen.DB.ugenSummary "RLPF"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 =
diff --git a/Help/UGen/rlpfD.help.lhs b/Help/UGen/rlpfD.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/rlpfD.help.lhs
@@ -0,0 +1,7 @@
+> import Sound.SC3 {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
+
+> g_01 =
+>   let s = mix (lfSaw AR (mce2 120 180) 0 * 0.33)
+>       f = linExp (lfCub KR 0.1 (0.5 * pi)) (-1) 1 280 1500
+>   in X.rlpfd s f 0.6 0.5 * 3
diff --git a/Help/UGen/rlpfd.help.lhs b/Help/UGen/rlpfd.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/rlpfd.help.lhs
@@ -0,0 +1,7 @@
+> import Sound.SC3 {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
+
+> g_01 =
+>   let s = mix (lfSaw AR (mce2 120 180) 0 * 0.33)
+>       f = linExp (lfCub KR 0.1 (0.5 * pi)) (-1) 1 280 1500
+>   in X.rlpfd s f 0.6 0.5 * 3
diff --git a/Help/UGen/rotate2.help.lhs b/Help/UGen/rotate2.help.lhs
--- a/Help/UGen/rotate2.help.lhs
+++ b/Help/UGen/rotate2.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Rotate2"
-    > Sound.SC3.UGen.DB.ugenSummary "Rotate2"
-
 > import Sound.SC3 {- hsc3 -}
 
 Rotation of stereo sound, via LFO.
diff --git a/Help/UGen/roundUp.help.lhs b/Help/UGen/roundUp.help.lhs
--- a/Help/UGen/roundUp.help.lhs
+++ b/Help/UGen/roundUp.help.lhs
@@ -1,13 +1,10 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Operator.round"
-    > :t roundUp
-
 > import Sound.SC3 {- hsc3 -}
->
+
 > g_01 =
 >     let x = mouseX KR 60 4000 Linear 0.1
 >         f = roundUp x 100
 >     in sinOsc AR f 0 * 0.1
->
+
 > g_02 =
 >     let n = line KR 24 108 6 RemoveSynth
 >     in saw AR (midiCPS (roundUp n 1)) * 0.2
diff --git a/Help/UGen/runningMax.help.lhs b/Help/UGen/runningMax.help.lhs
--- a/Help/UGen/runningMax.help.lhs
+++ b/Help/UGen/runningMax.help.lhs
@@ -1,8 +1,5 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "RunningMax"
-    > Sound.SC3.UGen.DB.ugenSummary "RunningMax"
-
 > import Sound.SC3 {- hsc3 -}
->
+
 > g_01 =
 >     let n = dust 'α' AR 20
 >         t = impulse AR 0.4 0
diff --git a/Help/UGen/runningMin.help.lhs b/Help/UGen/runningMin.help.lhs
--- a/Help/UGen/runningMin.help.lhs
+++ b/Help/UGen/runningMin.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "RunningMin"
-    > Sound.SC3.UGen.DB.ugenSummary "RunningMin"
-
 > import Sound.SC3 {- hsc3 -}
 
 Follow a sine lfo, reset rate controlled by mouseX
@@ -11,7 +8,7 @@
 >         t = impulse AR x 0
 >         f = runningMin o t * 500 + 200
 >     in t + sinOsc AR f 0 * 0.1
->
+
 > g_02 =
 >     let n = dust 'α' AR 20
 >         t = impulse AR 0.4 0
diff --git a/Help/UGen/runningSum.help.lhs b/Help/UGen/runningSum.help.lhs
--- a/Help/UGen/runningSum.help.lhs
+++ b/Help/UGen/runningSum.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "RunningSum"
-    > Sound.SC3.UGen.DB.ugenSummary "RunningSum"
-
 > import Sound.SC3 {- hsc3 -}
 
 distorts of course - would need scaling
diff --git a/Help/UGen/sampleDur.help.lhs b/Help/UGen/sampleDur.help.lhs
--- a/Help/UGen/sampleDur.help.lhs
+++ b/Help/UGen/sampleDur.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "SampleDur"
-    > Sound.SC3.UGen.DB.ugenSummary "SampleDur"
-
 > import Sound.SC3 {- hsc3 -}
 
 `sampleDur` is the reciprocal of the nominal sample rate of the server
diff --git a/Help/UGen/sampleRate.help.lhs b/Help/UGen/sampleRate.help.lhs
--- a/Help/UGen/sampleRate.help.lhs
+++ b/Help/UGen/sampleRate.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "SampleRate"
-    > Sound.SC3.UGen.DB.ugenSummary "SampleRate"
-
 > import Sound.SC3 {- hsc3 -}
 
 the current nominal sample rate of the server
diff --git a/Help/UGen/saw.help.lhs b/Help/UGen/saw.help.lhs
--- a/Help/UGen/saw.help.lhs
+++ b/Help/UGen/saw.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "Saw"
-    Sound.SC3.UGen.DB.ugenSummary "Saw"
-
 > import Sound.SC3 {- hsc3 -}
 
 SC3 saw is descending
diff --git a/Help/UGen/sawDPW.help.lhs b/Help/UGen/sawDPW.help.lhs
--- a/Help/UGen/sawDPW.help.lhs
+++ b/Help/UGen/sawDPW.help.lhs
@@ -1,9 +1,6 @@
-    Sound.SC3.UGen.Help.viewSC3Help "SawDPW"
-    Sound.SC3.UGen.DB.ugenSummary "SawDPW"
-
 > import Sound.SC3 {- hsc3 -}
-> import Sound.SC3.UGen.Bindings.DB.External {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
 
-> g_01 = sawDPW AR (xLine KR 2000 20 10 DoNothing) 0 * 0.1
+> g_01 = X.sawDPW AR (xLine KR 2000 20 10 DoNothing) 0 * 0.1
 
-> g_02 = sawDPW AR (mouseX KR 200 12000 Exponential 0.2) 0 * 0.2
+> g_02 = X.sawDPW AR (mouseX KR 200 12000 Exponential 0.2) 0 * 0.2
diff --git a/Help/UGen/scaleNeg.help.lhs b/Help/UGen/scaleNeg.help.lhs
--- a/Help/UGen/scaleNeg.help.lhs
+++ b/Help/UGen/scaleNeg.help.lhs
@@ -1,9 +1,6 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Operator.scaleneg"
-    > :t scaleNeg
-
 > import Prelude hiding ((<*)) {- base -}
 > import Sound.SC3 {- hsc3 -}
->
+
 > g_01 =
 >     let o = fSinOsc AR 1000 0
 >         l = line AR 1 (-1) 4 RemoveSynth
diff --git a/Help/UGen/schmidt.help.lhs b/Help/UGen/schmidt.help.lhs
--- a/Help/UGen/schmidt.help.lhs
+++ b/Help/UGen/schmidt.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Schmidt"
-    > Sound.SC3.UGen.DB.ugenSummary "Schmidt"
-
 > import Sound.SC3 {- hsc3 -}
 
 threshold octave jumps
diff --git a/Help/UGen/select.help.lhs b/Help/UGen/select.help.lhs
--- a/Help/UGen/select.help.lhs
+++ b/Help/UGen/select.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Select"
-    > Sound.SC3.UGen.DB.ugenSummary "Select"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 =
@@ -17,3 +14,8 @@
 >         f = select (lfSaw KR 0.5 0 * c + c) a
 >     in saw AR f * 0.2
 
+i-rate...
+
+> g_03 =
+>     let a = mce [rand 'α' 110 220,rand 'β' 220 440,rand 'γ' 440 880]
+>     in sinOsc AR (select (rand 'δ' 0 3) a) 0 * 0.1
diff --git a/Help/UGen/selectX.help.lhs b/Help/UGen/selectX.help.lhs
--- a/Help/UGen/selectX.help.lhs
+++ b/Help/UGen/selectX.help.lhs
@@ -1,15 +1,14 @@
-    Sound.SC3.UGen.Help.viewSC3Help "SelectX"
     :t selectX
 
 selectX is a composite ugen graph
 
-> import Sound.SC3
+> import Sound.SC3 {- hsc3 -}
 
 > g_01 =
 >   let n = 3/2
 >       f = mce2 440 441
 >       a = mce [sinOsc AR f 0, saw AR f, pulse AR f 0.1]
->   in mceSum (selectX (lfSaw KR 1 0 * n + n) a * 0.2)
+>   in mix (selectX (lfSaw KR 1 0 * n + n) a * 0.2)
 
 Here used as a sequencer:
 
@@ -17,5 +16,5 @@
 >   let n = 10
 >       a = mce [517, 403, 89, 562, 816, 107, 241, 145, 90, 224]
 >       c = n / 2
->       f = mceSum (selectX (lfSaw KR 0.5 0 * c + c) a)
+>       f = mix (selectX (lfSaw KR 0.5 0 * c + c) a)
 >   in saw AR f * 0.2
diff --git a/Help/UGen/sendReply.help.lhs b/Help/UGen/sendReply.help.lhs
--- a/Help/UGen/sendReply.help.lhs
+++ b/Help/UGen/sendReply.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "SendReply"
-    > Sound.SC3.UGen.DB.ugenSummary "SendReply"
-
 > import Sound.OSC {- hosc3 -}
 > import Sound.SC3 {- hsc3 -}
 
diff --git a/Help/UGen/sendTrig.help.lhs b/Help/UGen/sendTrig.help.lhs
--- a/Help/UGen/sendTrig.help.lhs
+++ b/Help/UGen/sendTrig.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "SendTrig"
-    Sound.SC3.UGen.DB.ugenSummary "SendTrig"
-
 > import Control.Monad {- base -}
 > import Data.Maybe {- base -}
 
diff --git a/Help/UGen/shaper.help.lhs b/Help/UGen/shaper.help.lhs
--- a/Help/UGen/shaper.help.lhs
+++ b/Help/UGen/shaper.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Shaper"
-    > Sound.SC3.UGen.DB.ugenSummary "Shaper"
-
 > import Sound.SC3 {- hsc3 -}
 > import qualified Sound.SC3.Common.Buffer.Gen as Gen {- hsc3 -}
 
diff --git a/Help/UGen/silent.help.lhs b/Help/UGen/silent.help.lhs
--- a/Help/UGen/silent.help.lhs
+++ b/Help/UGen/silent.help.lhs
@@ -1,7 +1,3 @@
-> Sound.SC3.UGen.Help.viewSC3Help "Silent"
-> Sound.SC3.UGen.DB.ugenSummary "Silent"
-
-> import Sound.SC3
+> import Sound.SC3 {- hsc3 -}
 
-> let g = out 0 (silent 2)
-> in audition g
+> g_01 = silent 2
diff --git a/Help/UGen/sinOsc.help.lhs b/Help/UGen/sinOsc.help.lhs
--- a/Help/UGen/sinOsc.help.lhs
+++ b/Help/UGen/sinOsc.help.lhs
@@ -1,11 +1,8 @@
-    Sound.SC3.UGen.Help.viewSC3Help "SinOsc"
-    Sound.SC3.UGen.DB.ugenSummary "SinOsc"
-
 > import Sound.SC3 {- hsc3 -}
 
 Fixed frequency (hz) and initial-phase (radians)
 
-> g_00 = sinOsc AR 440 0 * 0.25
+> g_00 = sinOsc AR (midiCPS 69) 0 * 0.75 -- 415 440
 
 Control input for frequency
 
@@ -108,3 +105,15 @@
 >       direction = toggleFF (impulse AR sync_freq 0 + impulse AR freq 0) * (-2) + 1
 >       o = sinOsc AR 0 (wrap (sweep (k2a 0) (direction * freq)) 0 (2 * pi))
 >   in o * 0.5
+
+15.5 khz
+
+> f_13 x = pan2 (sinOsc AR x 0) 0
+
+> g_13 = f_13 15500 0.75
+
+12 khz - 15.5 khz sweep
+
+> f_14 x = pan2 (sinOsc AR (range_hs x (sinOsc KR (1/6) 0)) 0) 0
+
+> g_14 = f_14 (12000,15500) 0.75
diff --git a/Help/UGen/sinOscFB.help.lhs b/Help/UGen/sinOscFB.help.lhs
--- a/Help/UGen/sinOscFB.help.lhs
+++ b/Help/UGen/sinOscFB.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "SinOscFB"
-    Sound.SC3.UGen.DB.ugenSummary "SinOscFB"
-
 > import Sound.SC3 {- hsc3 -}
 
     {SinOscFB.ar([400,301],MouseX.kr(0,4))*0.1}.play
diff --git a/Help/UGen/sineShaper.help.lhs b/Help/UGen/sineShaper.help.lhs
--- a/Help/UGen/sineShaper.help.lhs
+++ b/Help/UGen/sineShaper.help.lhs
@@ -1,13 +1,10 @@
-    Sound.SC3.UGen.Help.viewSC3Help "SineShaper"
-    Sound.SC3.UGen.DB.ugenSummary "SineShaper"
-
 > import Sound.SC3 {- hsc3 -}
-> import Sound.SC3.UGen.Bindings.DB.External {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
 
 {SineShaper.ar(SinOsc.ar([400, 404], 0, 0.2), MouseX.kr(0, 1))}.play
 
-> g_01 = sineShaper (sinOsc AR (mce2 400 404) 0 * 0.2) (mouseX KR 0 1 Linear 0.2)
+> g_01 = X.sineShaper (sinOsc AR (mce2 400 404) 0 * 0.2) (mouseX KR 0 1 Linear 0.2)
 
 {SineShaper.ar(SoundIn.ar, MouseX.kr(0, 1))}.play
 
-> g_02 = sineShaper (soundIn 0) (mouseX KR 0 1 Linear 0.2)
+> g_02 = X.sineShaper (soundIn 0) (mouseX KR 0 1 Linear 0.2)
diff --git a/Help/UGen/slew.help.lhs b/Help/UGen/slew.help.lhs
--- a/Help/UGen/slew.help.lhs
+++ b/Help/UGen/slew.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Slew"
-    > Sound.SC3.UGen.DB.ugenSummary "Slew"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 = let z = lfPulse AR 800 0 0.5 * 0.1 in mce2 z (slew z 4000 4000)
diff --git a/Help/UGen/slope.help.lhs b/Help/UGen/slope.help.lhs
--- a/Help/UGen/slope.help.lhs
+++ b/Help/UGen/slope.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Slope"
-    > Sound.SC3.UGen.DB.ugenSummary "Slope"
-
 > import Sound.SC3 {- hsc3 -}
 
 > f_01 f0 =
diff --git a/Help/UGen/sms.help.lhs b/Help/UGen/sms.help.lhs
--- a/Help/UGen/sms.help.lhs
+++ b/Help/UGen/sms.help.lhs
@@ -1,8 +1,5 @@
-    Sound.SC3.UGen.Help.viewSC3Help "SMS"
-    Sound.SC3.UGen.DB.ugenSummary "SMS"
-
 > import Sound.SC3 {- hsc3 -}
-> import Sound.SC3.UGen.Bindings.DB.External {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
 
 sine reconstruction left channel, noises on right
 
@@ -10,10 +7,10 @@
 >   let z = soundIn 0
 >       y = mouseY KR 1 50 Linear 0.2
 >       x = mouseX KR 0.5 4 Linear 0.2
->   in sms AR z 50 y 8 0.3 x 0 0 0 1 (-1)
+>   in X.sms {- AR -} z 50 y 8 0.3 x 0 0 0 1 (-1)
 
 default param
 
 > g_02 =
 >   let z = soundIn 0
->   in sms AR z 80 80 4 0.2 1 0 0 0 1 (-1)
+>   in X.sms {- AR -} z 80 80 4 0.2 1 0 0 0 1 (-1)
diff --git a/Help/UGen/softClip.help.lhs b/Help/UGen/softClip.help.lhs
--- a/Help/UGen/softClip.help.lhs
+++ b/Help/UGen/softClip.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Operator.softclip"
-    > :t softClip
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 =
diff --git a/Help/UGen/softClipAmp.help.lhs b/Help/UGen/softClipAmp.help.lhs
--- a/Help/UGen/softClipAmp.help.lhs
+++ b/Help/UGen/softClipAmp.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "SoftClipAmp"
-    Sound.SC3.UGen.DB.ugenSummary "SoftClipAmp"
-
 > import Sound.SC3 {- hsc3 -}
 > import Sound.SC3.UGen.Bindings.DB.External {- hsc3 -}
 
diff --git a/Help/UGen/sos.help.lhs b/Help/UGen/sos.help.lhs
--- a/Help/UGen/sos.help.lhs
+++ b/Help/UGen/sos.help.lhs
@@ -1,13 +1,25 @@
-    Sound.SC3.UGen.Help.viewSC3Help "SOS"
-    Sound.SC3.UGen.DB.ugenSummary "SOS"
-
 > import Sound.SC3 {- hsc3 -}
 
 Same as TwoPole
 
 > g_01 =
->     let theta = line KR (0.2 * pi) pi 5 RemoveSynth
->     rho = line KR 0.6 0.99 5 RemoveSynth
->     b1 = 2 * rho * cos theta
->     b2 = - (rho * rho) }
-> in sos (lfSaw AR 200 0 * 0.1) 1 0 0 b1 b2)
+>   let theta = line KR (0.2 * pi) pi 5 RemoveSynth
+>       rho = line KR 0.6 0.99 5 RemoveSynth
+>       b1 = 2 * rho * cos theta
+>       b2 = - (rho * rho)
+>   in sos (lfSaw AR 200 0 * 0.1) 1 0 0 b1 b2
+
+<http://www.earlevel.com/main/2011/01/02/biquad-formulas/>
+
+> g_02 =
+>   let fc = 100
+>       sr = 48000
+>       k = tan (pi * fc / sr)
+>       q = 0.707
+>       norm = 1 / (1 + k / q + k * k)
+>       a0 = k * k * norm
+>       a1 = 2 * a0
+>       a2 = a0
+>       b1 = 2 * (k * k - 1) * norm
+>       b2 = (1 - k / q + k * k) * norm
+>   in sos (whiteNoise 'a' AR * 0.2) a0 a1 a2 (- b1) (- b2)
diff --git a/Help/UGen/soundIn.help.lhs b/Help/UGen/soundIn.help.lhs
--- a/Help/UGen/soundIn.help.lhs
+++ b/Help/UGen/soundIn.help.lhs
@@ -1,5 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "SoundIn"
-
 soundIn is a composite of the UGens in' and numOutputBuses
 
 > import Sound.SC3 {- hsc3 -}
diff --git a/Help/UGen/specCentroid.help.lhs b/Help/UGen/specCentroid.help.lhs
--- a/Help/UGen/specCentroid.help.lhs
+++ b/Help/UGen/specCentroid.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "SpecCentroid"
-    Sound.SC3.UGen.DB.ugenSummary "SpecCentroid"
-
 > import Sound.SC3 {- hsc3 -}
 
 as the number of harmonics increases, the centroid is pushed higher
diff --git a/Help/UGen/specFlatness.help.lhs b/Help/UGen/specFlatness.help.lhs
--- a/Help/UGen/specFlatness.help.lhs
+++ b/Help/UGen/specFlatness.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "SpecFlatness"
-    Sound.SC3.UGen.DB.ugenSummary "SpecFlatness"
-
 > import Sound.SC3 {- hsc3 -}
 > import Sound.SC3.UGen.Bindings.DB.External {- hsc3 -}
 
diff --git a/Help/UGen/splay.help.lhs b/Help/UGen/splay.help.lhs
--- a/Help/UGen/splay.help.lhs
+++ b/Help/UGen/splay.help.lhs
@@ -1,5 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Splay"
-
 splay is a composite UGen, arguments are:
 inArray spread=1 level=1 center=0 levelComp=true
 
@@ -33,23 +31,24 @@
 
 full stereo
 
-    > withSC3 (send (n_set (-1) [("spread",1),("center",0)]))
+    > import Sound.OSC {- hosc -}
+    > withSC3 (sendMessage (n_set (-1) [("spread",1),("center",0)]))
 
 less wide
 
-    > withSC3 (send (n_set (-1) [("spread",0.5),("center",0)]))
+    > withSC3 (sendMessage (n_set (-1) [("spread",0.5),("center",0)]))
 
 mono center
 
-    > withSC3 (send (n_set (-1) [("spread",0),("center",0)]))
+    > withSC3 (sendMessage (n_set (-1) [("spread",0),("center",0)]))
 
 from center to right
 
-    > withSC3 (send (n_set (-1) [("spread",0.5),("center",0.5)]))
+    > withSC3 (sendMessage (n_set (-1) [("spread",0.5),("center",0.5)]))
 
 all left
 
-    > withSC3 (send (n_set (-1) [("spread",0),("center",-1)]))
+    > withSC3 (sendMessage (n_set (-1) [("spread",0),("center",-1)]))
 
 single channel input
 
diff --git a/Help/UGen/spreader.help.lhs b/Help/UGen/spreader.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/spreader.help.lhs
@@ -0,0 +1,18 @@
+> import Sound.SC3 {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
+
+> g_01 =
+>   let theta = pi / 2
+>       filtsPerOctave = 8
+>   in X.spreader AR (pinkNoise 'α' AR * 0.1) theta filtsPerOctave
+
+> g_02 =
+>   let theta = mouseX KR 0 (pi / 2) Linear 0.2
+>       filtsPerOctave = 8
+>   in X.spreader AR (pinkNoise 'α' AR * 0.1) theta filtsPerOctave
+
+> g_03 =
+>   let in_ = sinOsc AR (mouseX KR 110 880 Exponential 0.2) 0 * 0.1
+>       theta = pi / 2
+>       filtsPerOctave = 8
+>   in X.spreader AR in_ theta filtsPerOctave
diff --git a/Help/UGen/squiz.help.lhs b/Help/UGen/squiz.help.lhs
--- a/Help/UGen/squiz.help.lhs
+++ b/Help/UGen/squiz.help.lhs
@@ -1,17 +1,15 @@
-    Sound.SC3.UGen.Help.viewSC3Help "Squiz"
-    Sound.SC3.UGen.DB.ugenSummary "Squiz"
-
 > import Sound.SC3 {- hsc3 -}
-> import Sound.SC3.UGen.Bindings.DB.External {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
 
 > f_01 zmax s =
 >   let x = mouseX KR 1 10 Exponential 0.2
 >       y = mouseY KR 1 zmax Linear 0.2
->   in squiz s x y 0.1 * 0.1
+>   in X.squiz s x y 0.1 * 0.1
 
 Squiz of sin oscillator
 
 > g_01 = f_01 10 (sinOsc AR 440 0)
+
 
 > g_02 = f_01 100 (soundIn 0)
 
diff --git a/Help/UGen/standard2DL.help.lhs b/Help/UGen/standard2DL.help.lhs
--- a/Help/UGen/standard2DL.help.lhs
+++ b/Help/UGen/standard2DL.help.lhs
@@ -1,5 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Standard2DL"
-
 > import Sound.SC3 {- hsc3 -}
 > import Sound.SC3.UGen.Bindings.DB.External {- hsc3 -}
 
diff --git a/Help/UGen/standardL.help.lhs b/Help/UGen/standardL.help.lhs
--- a/Help/UGen/standardL.help.lhs
+++ b/Help/UGen/standardL.help.lhs
@@ -1,6 +1,6 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "StandardL"
-
 > import Sound.SC3 {- hsc3 -}
+
+> g_00 = standardL AR (sampleRate / 2) 1.0 0.5 0 * 0.2
 
 vary frequency
 
diff --git a/Help/UGen/stepper.help.lhs b/Help/UGen/stepper.help.lhs
--- a/Help/UGen/stepper.help.lhs
+++ b/Help/UGen/stepper.help.lhs
@@ -1,42 +1,52 @@
-> Sound.SC3.UGen.Help.viewSC3Help "Stepper"
-> Sound.SC3.UGen.DB.ugenSummary "Stepper"
-
-> import Sound.SC3
+> import Sound.OSC {- hosc -}
+> import Sound.SC3 {- hsc3 -}
 
-> let {i = impulse KR 10 0
->     ;f = stepper i 0 4 16 (-3) 4 * 100}
-> in audition (out 0 (sinOsc AR f 0 * 0.1))
+> g_01 =
+>   let i = impulse KR 10 0
+>       f = stepper i 0 4 16 (-3) 4 * 100
+>   in sinOsc AR f 0 * 0.1
 
 Using Stepper and BufRd for sequencing
 
-> let {compose = foldl (flip (.)) id
->     ;rvb z s =
->         let f i = let dly = mce [rand (z `joinID` i `joinID` 'α') 0 0.5
->                                 ,rand (z `joinID` i `joinID` 'β') 0 0.5]
->                     in allpassN i 0.05 dly (rand i 1.5 2)
->         in compose (replicate 5 f) s
->     ;stpr = let {rate = mouseX KR 1.75 2.25 Exponential 0.1
->                 ;clock = impulse KR rate 0
->                 ;envl = decay2 clock 0.002 2.5
->                 ;indx = stepper clock 0 0 15 1 0
->                 ;freq = bufRdN 1 KR 10 indx Loop
->                 ;ffreq = lag2 freq 0.1 + mce [0,0.3]
->                 ;lfo = sinOsc KR 0.2 (mce [0,pi/2]) * 0.0024 + 0.0025
->                 ;top = mix (lfPulse AR (freq * mce [1,1.5,2]) 0 0.3)
->                 ;chn = [\s -> rlpf s ffreq 0.3 * envl
->                        ,\s -> rlpf s ffreq 0.3 * envl
->                        ,\s -> s * 0.5
->                        ,\s -> combL s 1 (0.66 / rate) 2 * 0.8 + s
->                        ,\s -> s + (rvb 'γ' s * 0.3)
->                        ,\s -> leakDC s 0.1
->                        ,\s -> delayL s 0.1 lfo + s
->                        ,\s -> onePole s 0.9]}
->             in compose chn top
->     ;stprInit =
->      let n = [97.999,195.998,523.251,466.164,195.998
->              ,233.082,87.307,391.995,87.307,261.626
->              ,195.998,77.782,233.082,195.998,97.999
->              ,155.563]
->      in do {_ <- async (b_alloc 10 128 1)
->            ;send (b_setn 10 [(0,n)])}}
-> in withSC3 (stprInit >> play (out 0 stpr))
+> compose :: [t -> t] -> t -> t
+> compose = foldl (flip (.)) id
+
+> rvb :: ID z => z -> UGen -> UGen
+> rvb z0 s =
+>   let f z1 i =
+>         let dly = mce [rand ((z0,z1),'α') 0 0.5
+>                       ,rand ((z0,z1),'β') 0 0.5]
+>         in allpassN i 0.05 dly (rand z1 1.5 2)
+>   in compose (map f (id_seq 5 'γ')) s
+
+> stpr :: UGen
+> stpr =
+>   let rate = mouseX KR 1.75 2.25 Exponential 0.1
+>       clock = impulse KR rate 0
+>       envl = decay2 clock 0.002 2.5
+>       indx = stepper clock 0 0 15 1 0
+>       freq = bufRdN 1 KR 10 indx Loop
+>       ffreq = lag2 freq 0.1 + mce [0,0.3]
+>       lfo = sinOsc KR 0.2 (mce [0,pi/2]) * 0.0024 + 0.0025
+>       top = mix (lfPulse AR (freq * mce [1,1.5,2]) 0 0.3)
+>       chn = [\s -> rlpf s ffreq 0.3 * envl
+>             ,\s -> rlpf s ffreq 0.3 * envl
+>             ,\s -> s * 0.5
+>             ,\s -> combL s 1 (0.66 / rate) 2 * 0.8 + s
+>             ,\s -> s + (rvb 'γ' s * 0.3)
+>             ,\s -> leakDC s 0.1
+>             ,\s -> delayL s 0.1 lfo + s
+>             ,\s -> onePole s 0.9]
+>   in compose chn top
+
+> stpr_init :: DuplexOSC m => m ()
+> stpr_init = do
+>   let n = [97.999,195.998,523.251,466.164,195.998
+>           ,233.082,87.307,391.995,87.307,261.626
+>           ,195.998,77.782,233.082,195.998,97.999
+>           ,155.563]
+>   _ <- async (b_alloc 10 128 1)
+>   sendMessage (b_setn 10 [(0,n)])
+
+    > withSC3 stpr_init
+    > audition stpr
diff --git a/Help/UGen/stkBandedWG.help.lhs b/Help/UGen/stkBandedWG.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/stkBandedWG.help.lhs
@@ -0,0 +1,32 @@
+> import Sound.SC3 {- hsc3 -}
+> import Sound.SC3.UGen.Record.Plain.StkBandedWG {- hsc3-rec -}
+
+> g_01 = mkStkBandedWG stkBandedWGR
+
+instr: Uniform Bar = 0, Tuned Bar = 1, Glass Harmonica = 2, Tibetan Bowl = 3
+
+> g_02 = mkStkBandedWG stkBandedWGR {instr = 3}
+
+> g_03 =
+>   let tr = impulse KR (mouseX KR 0.5 12 Linear 0.2) 0 - 0.5
+>       u = stkBandedWGR
+>           {freq = midiCPS (tExpRand 'α' 24 96 tr)
+>           ,modalresonance = tRand 'ζ' 0 127 tr
+>           ,instr = 3
+>           ,trig_ = tr}
+>   in mkStkBandedWG u
+
+setstriking: 0 = Plucked, 127 = Bowed
+
+> g_04 =
+>   let u = stkBandedWGR
+>           {freq = rand 'α' 110 440
+>           ,instr = iRand 'β' 1 3
+>           ,bowpressure = iRand 'γ' 32 96
+>           ,bowmotion = rand 'δ' 32 96
+>           ,integration = rand 'ε' 0 64
+>           ,modalresonance = rand 'ζ' 32 96
+>           ,bowvelocity = rand 'η' 64 96
+>           ,setstriking = 127
+>           ,trig_ = 1}
+>   in mkStkBandedWG u
diff --git a/Help/UGen/stkBowed.help.lhs b/Help/UGen/stkBowed.help.lhs
--- a/Help/UGen/stkBowed.help.lhs
+++ b/Help/UGen/stkBowed.help.lhs
@@ -1,22 +1,22 @@
-    Sound.SC3.UGen.Help.viewSC3Help "StkBowed"
-    Sound.SC3.UGen.DB.ugenSummary "StkBowed"
-
 > import Sound.SC3 {- hsc3 -}
-> import Sound.SC3.UGen.Bindings.DB.External {- hsc3 -}
+> import Sound.SC3.UGen.Record.Plain.StkBowed {- hsc3-rec -}
 
-...not working...
+> g_01 = mkStkBowed stkBowedR
 
-> g_01 =
->   let g = toggleFF (impulse KR 1 0)
->       freq = 220.0
->       bowpressure = 64.0
->       bowposition = 64.0
->       vibfreq = 64.0
->       vibgain = 64.0
->       loudness_ = 64.0
->       gate_ = 1.0
->       attackrate = 1
->       decayrate = 1
->   in stkBowed AR freq bowpressure bowposition vibfreq vibgain loudness_ gate_ attackrate decayrate
+...gate prints however...
+
+> g_02 =
+>   let g = lfPulse KR 0.25 0 0.5
+>       u = stkBowedR
+>         {freq = midiCPS (rand 'α' 24 96)
+>         ,bowpressure = rand 'β' 0 127
+>         ,bowposition = rand 'γ' 0 127
+>         ,vibfreq = rand 'δ' 32 96
+>         ,vibgain = rand 'ε' 32 96
+>         ,loudness_ = rand 'ζ' 32 96
+>         ,gate_ = g
+>         ,attackrate = rand 'η' 1 64
+>         ,decayrate = rand 'θ' 1 64}
+>   in mkStkBowed u
 
 <https://ccrma.stanford.edu/software/stk/classstk_1_1Bowed.html>
diff --git a/Help/UGen/stkFlute.help.lhs b/Help/UGen/stkFlute.help.lhs
--- a/Help/UGen/stkFlute.help.lhs
+++ b/Help/UGen/stkFlute.help.lhs
@@ -1,24 +1,24 @@
-    Sound.SC3.UGen.Help.viewSC3Help "StkFlute"
-    Sound.SC3.UGen.DB.ugenSummary "StkFlute"
-
 > import Sound.SC3 {- hsc3 -}
-> import qualified Sound.SC3.UGen.Bindings.DB.External as External {- hsc3 -}
-> import qualified Sound.SC3.UGen.Bindings.DB.RDU as RDU {- sc3-rdu -}
+> import Sound.SC3.UGen.Record.Plain.StkFlute {- hsc3-rec -}
 
 ...not working...
 
-> g_01 =
->   let freq = 440
->       jetDelay = 49
->       noisegain = 0.15
->       jetRatio = 0.32
->   in External.stkFlute AR freq jetDelay noisegain jetRatio
+> g_01 = mkStkFlute stkFluteR
 
 > g_02 =
->   let freq = 440
->       jetDelay = 49
->       noisegain = line KR 0.05 0.25 3 DoNothing -- def = 0.15
->       jetRatio = line KR 0.10 0.60 3 RemoveSynth -- def = 0.32
->   in External.stkFlute AR freq jetDelay noisegain jetRatio
+>   let u = stkFluteR
+>           {freq = 440
+>           ,jetDelay = 49
+>           ,noisegain = 0.15
+>           ,jetRatio = 0.32}
+>   in mkStkFlute u
+
+> g_03 =
+>   let u = stkFluteR
+>           {freq = 440
+>           ,jetDelay = 49
+>           ,noisegain = line KR 0.05 0.25 3 DoNothing
+>           ,jetRatio = line KR 0.10 0.60 3 RemoveSynth}
+>   in mkStkFlute u
 
 <https://ccrma.stanford.edu/software/stk/classstk_1_1Flute.html>
diff --git a/Help/UGen/stkMandolin.help.lhs b/Help/UGen/stkMandolin.help.lhs
--- a/Help/UGen/stkMandolin.help.lhs
+++ b/Help/UGen/stkMandolin.help.lhs
@@ -1,25 +1,29 @@
-    Sound.SC3.UGen.Help.viewSC3Help "StkMandolin"
-    Sound.SC3.UGen.DB.ugenSummary "StkMandolin"
-
 > import Sound.SC3 {- hsc3 -}
-> import qualified Sound.SC3.UGen.Bindings.DB.External as External {- hsc3 -}
-> import qualified Sound.SC3.UGen.Bindings.DB.RDU as RDU {- sc3-rdu -}
+> import Sound.SC3.UGen.Record.Plain.StkMandolin {- hsc3-rec -}
 
 > g_01 =
->   let x = mouseX KR 0.25 4 Linear 0.2
+>   let x = mouseX KR 0.25 16 Linear 0.2
 >       tr = impulse KR x 0 - 0.5
->       freq = midiCPS (tRand 'α' 54 66 tr)
->       [bs, pp, dm, dt, at] = mceChannels (RDU.tRandN 5 'β' 0 127 tr)
->   in External.stkMandolin AR freq bs pp dm dt at tr
+>       u = stkMandolinR
+>         {freq = midiCPS (tiRand 'α' 32 96 tr)
+>         ,bodysize = tRand 'β' 0 127 tr
+>         ,pickposition = tRand 'γ' 0 127 tr
+>         ,stringdamping = tRand 'δ' 0 127 tr
+>         ,stringdetune = tRand 'ε' 0 127 tr
+>         ,aftertouch = tRand 'ζ' 0 127 tr
+>         ,trig_ = tr}
+>   in mkStkMandolin u
 
 > g_02 =
 >   let x = mouseX KR 3 16 Linear 0.2
 >       tr = impulse KR x 0 - 0.5 -- trig
 >       tr3 = pulseDivider tr 3 0
->       freq = midiCPS (tiRand 'α' 54 66 tr)
->       bs = tRand 'β' 72 94 tr3 -- bodysize
->       pp = tRand 'γ' 32 42 tr3 -- pickposition
->       dm = tRand 'δ' 64 72 tr3 -- stringdamping
->       dt = tRand 'ε' 0 4 tr3 -- stringdetune
->       at = tRand 'ζ' 2 8 tr3 -- aftertouch
->   in External.stkMandolin AR freq bs pp dm dt at tr
+>       u = stkMandolinR
+>         {freq = midiCPS (tiRand 'α' 54 66 tr)
+>         ,bodysize = tRand 'β' 72 94 tr3
+>         ,pickposition = tRand 'γ' 32 42 tr3
+>         ,stringdamping = tRand 'δ' 64 72 tr3
+>         ,stringdetune = tRand 'ε' 0 4 tr3
+>         ,aftertouch = tRand 'ζ' 2 8 tr3
+>         ,trig_ = tr}
+>   in mkStkMandolin u
diff --git a/Help/UGen/stkModalBar.help.lhs b/Help/UGen/stkModalBar.help.lhs
--- a/Help/UGen/stkModalBar.help.lhs
+++ b/Help/UGen/stkModalBar.help.lhs
@@ -1,31 +1,37 @@
-    Sound.SC3.UGen.Help.viewSC3Help "StkModalBar"
-    Sound.SC3.UGen.DB.ugenSummary "StkModalBar"
-
 > import Sound.SC3 {- hsc3 -}
-> import qualified Sound.SC3.UGen.Bindings.DB.External as External {- hsc3 -}
-> import qualified Sound.SC3.UGen.Bindings.DB.RDU as RDU {- sc3-rdu -}
+> import Sound.SC3.UGen.Record.Plain.StkModalBar {- hsc3-rec -}
 
+instrument: Marimba=0, Vibraphone=1, Agogo=2, Wood1=3, Reso=4, Wood2=5, Beats=6, Two Fixed=7, Clump=8
+
 > g_01 =
 >   let x = mouseX KR 0.25 12 Linear 0.2
 >       tr = impulse KR x 0 - 0.5
->       tR = tRand 'α' 0 127 tr
->       i = tRand 'β' 0 9 tr
->       mn = tiRand 'γ' 25 96 tr
->       [sh,sp,vg,vf,mx,v] = mceChannels (RDU.tRandN 6 'δ' 0 127 tr)
->   in External.stkModalBar AR (midiCPS mn) i sh sp vg vf mx v tr
+>       u = stkModalBarR
+>         {freq = midiCPS (tiRand 'α' 25 96 tr)
+>         ,instrument = tiRand 'β' 0 9 tr
+>         ,stickhardness = tRand 'γ' 0 127 tr
+>         ,stickposition = tRand 'δ' 0 127 tr
+>         ,vibratogain = tRand 'ε' 0 127 tr
+>         ,vibratofreq = tRand 'ζ' 0 127 tr
+>         ,directstickmix = tRand 'η' 0 127 tr
+>         ,volume = tRand 'θ' 0 127 tr
+>         ,trig_ = tr}
+>   in mkStkModalBar u
 
 > g_02 =
 >   let x = mouseX KR 1 12 Linear 0.2
 >       tr = impulse KR x 0 - 0.5
 >       tr3 = pulseDivider tr 3 0
->       freq = midiCPS (tiRand 'α' 52 64 tr)
->       instr = 1 -- instrument (0 - 9)
->       sh = tRand 'β' 10 50 tr3 -- stickhardness
->       sp = tRand 'γ' 40 80 tr3 -- stickposition
->       vg = tRand 'δ' 66 98 tr3 -- vibratogain
->       vf = tRand 'ε' 4 12 tr3 -- vibratofreq
->       mx = tRand 'ζ' 0 1 tr3 -- directstickmix
->       v = tRand 'η' 16 48 tr3 -- volume
->   in External.stkModalBar AR freq instr sh sp vg vf mx v tr
+>       u = stkModalBarR
+>         {freq = midiCPS (tiRand 'α' 52 64 tr)
+>         ,instrument = 1
+>         ,stickhardness = tRand 'β' 10 50 tr3
+>         ,stickposition = tRand 'γ' 40 80 tr3
+>         ,vibratogain = tRand 'δ' 66 98 tr3
+>         ,vibratofreq = tRand 'ε' 4 12 tr3
+>         ,directstickmix = tRand 'ζ' 0 1 tr3
+>         ,volume = tRand 'η' 16 48 tr3
+>         ,trig_ = tr}
+>   in mkStkModalBar u
 
 <https://ccrma.stanford.edu/software/stk/classstk_1_1ModalBar.html>
diff --git a/Help/UGen/stkMoog.help.lhs b/Help/UGen/stkMoog.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/stkMoog.help.lhs
@@ -0,0 +1,40 @@
+> import Sound.SC3 {- hsc3 -}
+> import Sound.SC3.UGen.Record.Plain.StkMoog {- hsc3-rec -}
+
+> g_01 =
+>   let tr = mouseButton KR 0 1 0 - 0.5
+>       u = stkMoogR
+>         {freq = midiCPS (tiRand 'α' 12 96 tr)
+>         ,filterQ = tRand 'β' 0 127 tr
+>         ,sweeprate = tRand 'γ' 0 127 tr
+>         ,vibfreq = tRand 'δ' 0 127 tr
+>         ,vibgain = tRand 'ε' 0 127 tr
+>         ,gain = tRand 'ζ' 0 127 tr
+>         ,trig_ = tr}
+>   in mkStkMoog u
+
+> g_02 =
+>   let x = mouseX KR 0.25 16 Linear 0.2
+>       tr = impulse KR x 0 - 0.5
+>       u = stkMoogR
+>         {freq = midiCPS (tiRand 'α' 24 72 tr)
+>         ,filterQ = tRand 'β' 0 32 tr
+>         ,sweeprate = tRand 'γ' 0 32 tr
+>         ,vibfreq = tRand 'δ' 0 96 tr
+>         ,vibgain = tRand 'ε' 0 16 tr
+>         ,gain = tRand 'ζ' 32 127 tr
+>         ,trig_ = tr}
+>   in mkStkMoog u
+
+> g_03 =
+>   let nsig z l r f = range l r (lfNoise2 z KR f)
+>       scl = asLocalBuf 'α' [0,2,3.2,5,7,9,10]
+>       mnn = 48 + degreeToKey scl (nsig 'β' 0 15 0.35) 12
+>       u = stkMoogR
+>         {freq = midiCPS mnn
+>         ,filterQ = nsig 'γ' 0 64 0.5
+>         ,sweeprate = nsig 'δ' 0 64 0.5
+>         ,vibfreq = nsig 'ε' 0 64 0.5
+>         ,vibgain = nsig 'ζ' 0 16 0.5
+>         ,gain = nsig 'η' 16 96 0.5}
+>   in mkStkMoog u
diff --git a/Help/UGen/stkPluck.help.lhs b/Help/UGen/stkPluck.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/stkPluck.help.lhs
@@ -0,0 +1,11 @@
+> import Sound.SC3 {- hsc3 -}
+> import Sound.SC3.UGen.Record.Plain.StkPluck {- hsc3-rec -}
+
+> g_01 = mkStkPluck stkPluckR
+
+> g_02 =
+>   let u = stkPluckR
+>           {freq = midiCPS (iRand 'α' 32 96)
+>           ,decay_ = rand 'β' 0 127}
+>       s = leakDC (mkStkPluck u) 0.995
+>   in mrg2 s (detectSilence s 0.01 0.5 RemoveSynth)
diff --git a/Help/UGen/stkShakers.help.lhs b/Help/UGen/stkShakers.help.lhs
--- a/Help/UGen/stkShakers.help.lhs
+++ b/Help/UGen/stkShakers.help.lhs
@@ -1,17 +1,17 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "StkShakers"
-    > Sound.SC3.UGen.DB.ugenSummary "StkShakers"
-
 > import Sound.SC3 {- hsc3 -}
-> import qualified Sound.SC3.UGen.Bindings.DB.External as Ext {- hsc3 -}
-> import qualified Sound.SC3.UGen.Bindings.DB.RDU as RDU {- sc3-rdu -}
+> import Sound.SC3.UGen.Record.Plain.StkShakers {- hsc3-rec -}
 
-> gr_01 =
+> gr_01 = mkStkShakers stkShakersR
+
+> gr_02 =
 >     let x = mouseX KR 0.25 4 Linear 0.2
 >         tr = impulse KR x 0 - 0.5
->         instr = tRand 'α' 0 23 tr
->         [energy,decay,objects,resfreq] = mceChannels (RDU.tRandN 4 'β' 0 127 tr)
->     in Ext.stkShakers AR instr energy decay objects resfreq
-
-> gr_02 = Ext.stkShakers AR 4 64 64 64 64
+>         u = stkShakersR
+>           {instr = tRand 'α' 0 23 tr
+>           ,energy = tRand 'β' 0 127 tr
+>           ,decay_ = tRand 'γ' 0 127 tr
+>           ,objects = tRand 'δ' 0 127 tr
+>           ,resfreq = tRand 'ε' 0 127 tr}
+>     in mkStkShakers u
 
 <https://ccrma.stanford.edu/software/stk/classstk_1_1Shakers.html>
diff --git a/Help/UGen/streson.help.lhs b/Help/UGen/streson.help.lhs
--- a/Help/UGen/streson.help.lhs
+++ b/Help/UGen/streson.help.lhs
@@ -1,17 +1,14 @@
-    Sound.SC3.UGen.Help.viewSC3Help "Streson"
-    Sound.SC3.UGen.DB.ugenSummary "Streson"
-
-    <http://www.csounds.com/manual/html/streson.html>
+<http://www.csounds.com/manual/html/streson.html>
 
 > import Sound.SC3 {- hsc3 -}
-> import qualified Sound.SC3.UGen.Bindings.DB.External as External {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
 
 > k_01 = recip (linExp (lfCub KR 0.1 (0.5 * pi)) (-1) 1 280 377)
 
     import Sound.SC3.Plot {- hsc3-plot -}
     plot_ugen_nrt (20,1) 16.0 k_01
 
-> f_01 z = External.streson z k_01 0.9 * 0.3
+> f_01 z = X.streson z k_01 0.9 * 0.3
 
 > g_01 = f_01 (lfSaw AR (mce2 220 180) 0 * 0.2)
 
diff --git a/Help/UGen/sub.help.lhs b/Help/UGen/sub.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/sub.help.lhs
@@ -0,0 +1,14 @@
+> import Sound.SC3 {- hsc3 -}
+
+> g_01 =
+>     let o = fSinOsc AR 800 0
+>         n = pinkNoise 'α' AR
+>     in (o - n) * 0.1
+
+DC offset.
+
+> g_02 = fSinOsc AR 440 0 * 0.1 - 0.5
+
+Optimises identity
+
+> g_03 = (sinOsc AR 440 0 - 0) * 0.1
diff --git a/Help/UGen/subsampleOffset.help.lhs b/Help/UGen/subsampleOffset.help.lhs
--- a/Help/UGen/subsampleOffset.help.lhs
+++ b/Help/UGen/subsampleOffset.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "SubsampleOffset"
-    > Sound.SC3.UGen.DB.ugenSummary "SubsampleOffset"
-
 > import Sound.OSC {- hosc -}
 > import Sound.SC3 {- hsc3 -}
 
diff --git a/Help/UGen/sum3.help.lhs b/Help/UGen/sum3.help.lhs
--- a/Help/UGen/sum3.help.lhs
+++ b/Help/UGen/sum3.help.lhs
@@ -1,9 +1,8 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Sum3"
-    > Sound.SC3.UGen.DB.ugenSummary "Sum3"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 = sum3 (sinOsc AR 440 0) (sinOsc AR 441 0) (sinOsc AR 442 0) * 0.1
+
+there is an optimiser/re-writer, applicable at ADD
 
 > g_02 = (sinOsc AR 440 0 + sinOsc AR 441 0 + sinOsc AR 442 0) * 0.1
 
diff --git a/Help/UGen/sum4.help.lhs b/Help/UGen/sum4.help.lhs
--- a/Help/UGen/sum4.help.lhs
+++ b/Help/UGen/sum4.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Sum4"
-    > Sound.SC3.UGen.DB.ugenSummary "Sum4"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 = sum4 (sinOsc AR 440 0) (sinOsc AR 441 0) (sinOsc AR 442 0) (sinOsc AR 443 0) * 0.1
diff --git a/Help/UGen/sumSqr.help.lhs b/Help/UGen/sumSqr.help.lhs
--- a/Help/UGen/sumSqr.help.lhs
+++ b/Help/UGen/sumSqr.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "Operator.sumsqr"
-    :t sumSqr
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 =
diff --git a/Help/UGen/svf.help.lhs b/Help/UGen/svf.help.lhs
--- a/Help/UGen/svf.help.lhs
+++ b/Help/UGen/svf.help.lhs
@@ -1,21 +1,18 @@
-    Sound.SC3.UGen.Help.viewSC3Help "SVF"
-    Sound.SC3.UGen.DB.ugenSummary "SVF"
-
 > import Sound.OSC {- hosc -}
 > import Sound.SC3 {- hsc3 -}
-> import Sound.SC3.UGen.Bindings.DB.External {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
 
 > g_01 =
->   let o = lfSaw AR (range 110 35 (lfSaw KR 2 0)) 0
->       x = mouseX KR 20 20000 Exponential 0.2
->       y = mouseY KR 1 0 Linear 0.2
+>   let signal = lfSaw AR (range 110 35 (lfSaw KR 2 0)) 0
+>       cutoff = mouseX KR 20 20000 Exponential 0.2
+>       res = mouseY KR 1 0 Linear 0.2
 >       k = control KR
 >       low = k "low" 0.1
 >       band = k "band" 0.0
 >       high = k "high" 0.0
 >       notch = k "notch" 0.0
 >       peak_ = k "peak" 0.0
->   in svf o x y low band high notch peak_
+>   in X.svf signal cutoff res low band high notch peak_
 
 > f_01 k v = withSC3 (sendMessage (n_set1 (-1) k v))
 
diff --git a/Help/UGen/sweep.help.lhs b/Help/UGen/sweep.help.lhs
--- a/Help/UGen/sweep.help.lhs
+++ b/Help/UGen/sweep.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "Sweep"
-    Sound.SC3.UGen.DB.ugenSummary "Sweep"
-
 > import Sound.SC3 {- hsc3 -}
 
 Using sweep to modulate sine frequency
@@ -51,7 +48,7 @@
 > g_05 =
 >   let lf = range 0.01 1.25 (lfNoise2 'α' KR 1)
 >       du = duty AR lf 0 DoNothing lf
->       tr = abs (hpz1 du) >* 0
+>       tr = abs (hpz1 du) >** 0
 >       ph = sweep tr (1/du)
 >       fr = linExp ph 0 1 400 800
 >   in sinOsc AR fr 0 * 0.2
@@ -68,6 +65,6 @@
 >       sw = sweep tr rt + st
 >   in sinOsc AR sw 0 * 0.2
 
-    > import Sound.OSC
+    > import Sound.OSC {- hosc -}
     > withSC3 (sendMessage (n_set (-1) [("st",660),("en",550),("tm",4),("tr",1)]))
     > withSC3 (sendMessage (n_set (-1) [("st",110),("en",990),("tm",1),("tr",1)]))
diff --git a/Help/UGen/switchDelay.help.lhs b/Help/UGen/switchDelay.help.lhs
--- a/Help/UGen/switchDelay.help.lhs
+++ b/Help/UGen/switchDelay.help.lhs
@@ -1,18 +1,15 @@
-    Sound.SC3.UGen.Help.viewSC3Help "SwitchDelay"
-    Sound.SC3.UGen.DB.ugenSummary "SwitchDelay"
-
 > import Sound.SC3 {- hsc3 -}
-> import Sound.SC3.UGen.Bindings.DB.External {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
 
 simple feedback delay
 
-> g_01 = switchDelay (soundIn 0) 1 1 1 0.99 20
+> g_01 = X.switchDelay (soundIn 0) 1 1 1 0.99 20
 
-> g_02 = switchDelay (soundIn 0) 1 0.7 0.4 0.6 20
+> g_02 = X.switchDelay (soundIn 0) 1 0.7 0.4 0.6 20
 
 change the buffer read pointer periodically.
 
 > g_03 =
 >   let ix = stepper (impulse KR 0.5 0) 0 0 3 1 0
 >       dt = select ix (mce [0.02,0.1,0.725,0.25])
->   in switchDelay (soundIn 0) 1 0.6 dt 0.7 20
+>   in X.switchDelay (soundIn 0) 1 0.6 dt 0.7 20
diff --git a/Help/UGen/syncSaw.help.lhs b/Help/UGen/syncSaw.help.lhs
--- a/Help/UGen/syncSaw.help.lhs
+++ b/Help/UGen/syncSaw.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "SyncSaw"
-    Sound.SC3.UGen.DB.ugenSummary "SyncSaw"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 =
diff --git a/Help/UGen/t2a.help.lhs b/Help/UGen/t2a.help.lhs
--- a/Help/UGen/t2a.help.lhs
+++ b/Help/UGen/t2a.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "T2A"
-    Sound.SC3.UGen.DB.ugenSummary "T2A"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 =
diff --git a/Help/UGen/t2k.help.lhs b/Help/UGen/t2k.help.lhs
--- a/Help/UGen/t2k.help.lhs
+++ b/Help/UGen/t2k.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "T2K"
-    Sound.SC3.UGen.DB.ugenSummary "T2K"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 =
diff --git a/Help/UGen/tBetaRand.help.lhs b/Help/UGen/tBetaRand.help.lhs
--- a/Help/UGen/tBetaRand.help.lhs
+++ b/Help/UGen/tBetaRand.help.lhs
@@ -1,21 +1,18 @@
-    Sound.SC3.UGen.Help.viewSC3Help "TBetaRand"
-    Sound.SC3.UGen.DB.ugenSummary "TBetaRand"
-
 > import Sound.SC3 {- hsc3 -}
-> import Sound.SC3.UGen.Bindings.DB.External {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
 
 > g_01 =
 >     let t = dust 'α' KR 10
->         f = tBetaRand 'β' 300 3000 0.1 0.1 t
+>         f = X.tBetaRand 'β' 300 3000 0.1 0.1 t
 >     in sinOsc AR f 0 * 0.1
 
-mouse control of parameters
+mouse control of parameters (...scsynth -> 100% CPU)
 
 > g_02 =
 >     let t = dust 'α' AR 10
 >         p1 = mouseX KR 1 5 Linear 0.2
 >         p2 = mouseY KR 1 5 Linear 0.2
->         f = tBetaRand 'β' 300 3000 p1 p2 t
+>         f = X.tBetaRand 'β' 300 3000 p1 p2 t
 >     in sinOsc AR f 0 * 0.1
 
 ...audio rate crashes server...
@@ -24,4 +21,4 @@
 >     let t = dust 'α' AR 100
 >         p1 = mouseX KR 1 5 Linear 0.2
 >         p2 = mouseY KR 1 5 Linear 0.2
->     in lag (tBetaRand 'β' (-1) 1 p1 p2 t) (10 / 48000)
+>     in lag (X.tBetaRand 'β' (-1) 1 p1 p2 t) (10 / 48000)
diff --git a/Help/UGen/tBrownRand.help.lhs b/Help/UGen/tBrownRand.help.lhs
--- a/Help/UGen/tBrownRand.help.lhs
+++ b/Help/UGen/tBrownRand.help.lhs
@@ -1,21 +1,18 @@
-    Sound.SC3.UGen.Help.viewSC3Help "TBrownRand"
-    Sound.SC3.UGen.DB.ugenSummary "TBrownRand"
-
 > import Sound.SC3 {- hsc3 -}
-> import Sound.SC3.UGen.Bindings.DB.External {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
 
 > g_01 =
 >     let t = dust 'α' KR 10
 >         dist = mouseX KR 0 5 Linear 0.2
->         f = tBrownRand 'β' 300 3000 1 dist t
+>         f = X.tBrownRand 'β' 300 3000 1 dist t
 >     in sinOsc AR f 0 * 0.1
 
 > g_02 =
 >     let t = dust 'α' KR 10
->         n = tBrownRand 'β' 0 1 0.2 0 t
+>         n = X.tBrownRand 'β' 0 1 0.2 0 t
 >         f = linExp n 0 1 300 3000
 >         o = sinOsc AR f 0
->         l = tBrownRand 'γ' (-1) 1 1 4 t
+>         l = X.tBrownRand 'γ' (-1) 1 1 4 t
 >     in pan2 o l 0.1
 
 audio rate noise
@@ -24,4 +21,4 @@
 >   let x = mouseX KR 500 5000 Exponential 0.2
 >       y = mouseY KR 10 500 Exponential 0.2
 >       t = dust 'α' AR x
->   in lag (tBrownRand 'β' (-1) 1 0.2 0 t) (y / 48000)
+>   in lag (X.tBrownRand 'β' (-1) 1 0.2 0 t) (y / 48000)
diff --git a/Help/UGen/tChoose.help.lhs b/Help/UGen/tChoose.help.lhs
--- a/Help/UGen/tChoose.help.lhs
+++ b/Help/UGen/tChoose.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "TChoose"
-    :t tChoose
-
 tChoose is a composite of tIRand and select.
 
 > import Sound.SC3 {- hsc3 -}
diff --git a/Help/UGen/tDelay.help.lhs b/Help/UGen/tDelay.help.lhs
--- a/Help/UGen/tDelay.help.lhs
+++ b/Help/UGen/tDelay.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "TDelay"
-    Sound.SC3.UGen.DB.ugenSummary "TDelay"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 =
diff --git a/Help/UGen/tDuty.help.lhs b/Help/UGen/tDuty.help.lhs
--- a/Help/UGen/tDuty.help.lhs
+++ b/Help/UGen/tDuty.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "TDuty"
-    > Sound.SC3.UGen.DB.ugenSummary "TDuty"
-
 > import Data.List {- base -}
 > import Sound.SC3 {- hsc3 -}
 
diff --git a/Help/UGen/tExpRand.help.lhs b/Help/UGen/tExpRand.help.lhs
--- a/Help/UGen/tExpRand.help.lhs
+++ b/Help/UGen/tExpRand.help.lhs
@@ -1,7 +1,8 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "TExpRand"
-    > Sound.SC3.UGen.DB.ugenSummary "TExpRand"
-
 > import Sound.SC3 {- hsc3 -}
+
+> g_00 =
+>  let f = tExpRand 'α' 300.0 3000.0 (dust 'β' KR 10)
+>  in sinOsc AR f 0 * 0.1
 
 > g_01 :: UId m => m UGen
 > g_01 = do
diff --git a/Help/UGen/tGaussRand.help.lhs b/Help/UGen/tGaussRand.help.lhs
--- a/Help/UGen/tGaussRand.help.lhs
+++ b/Help/UGen/tGaussRand.help.lhs
@@ -1,8 +1,5 @@
-    Sound.SC3.UGen.Help.viewSC3Help "TGaussRand"
-    Sound.SC3.UGen.DB.ugenSummary "TGaussRand"
-
 > import Sound.SC3 {- hsc3 -}
-> import Sound.SC3.UGen.Bindings.DB.External {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
 
 > f_01 rand_f =
 >     let t = dust 'α' KR 10
@@ -11,7 +8,7 @@
 >         l = rand_f 'γ' (-1) 1 t
 >     in pan2 o l 0.1
 
-> g_01 = f_01 tGaussRand
+> g_01 = f_01 X.tGaussRand
 
 compare to tRand
 
diff --git a/Help/UGen/tGrains.help.lhs b/Help/UGen/tGrains.help.lhs
--- a/Help/UGen/tGrains.help.lhs
+++ b/Help/UGen/tGrains.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "TGrains"
-    > Sound.SC3.UGen.DB.ugenSummary "TGrains"
-
 > import Sound.SC3 {- hsc3 -}
 
 Load audio (#10) data
diff --git a/Help/UGen/tRand.help.lhs b/Help/UGen/tRand.help.lhs
--- a/Help/UGen/tRand.help.lhs
+++ b/Help/UGen/tRand.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "TRand"
-    > Sound.SC3.UGen.DB.ugenSummary "TRand"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 =
diff --git a/Help/UGen/tWindex.help.lhs b/Help/UGen/tWindex.help.lhs
--- a/Help/UGen/tWindex.help.lhs
+++ b/Help/UGen/tWindex.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "TWindex"
-    Sound.SC3.UGen.DB.ugenSummary "TWindex"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 =
diff --git a/Help/UGen/tanh.help.lhs b/Help/UGen/tanh.help.lhs
--- a/Help/UGen/tanh.help.lhs
+++ b/Help/UGen/tanh.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Operator.tanh"
-    > :t tanh
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 =
diff --git a/Help/UGen/tartini.help.lhs b/Help/UGen/tartini.help.lhs
--- a/Help/UGen/tartini.help.lhs
+++ b/Help/UGen/tartini.help.lhs
@@ -1,21 +1,33 @@
-> Sound.SC3.UGen.Help.viewSC3Help "Tartini"
-> Sound.SC3.UGen.DB.ugenSummary "Tartini"
-
-> import Sound.SC3
+> import Sound.SC3 {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
 
 Comparison of input frequency (x) and tracked oscillator frequency (f).
 
-> let {x = mouseX KR 440 880 Exponential 0.1
->     ;o = lfSaw AR x 0 * 0.05 {- sinOsc AR x 0 * 0.1 -}
->     ;[f,e] = mceChannels (tartini KR o 0.2 2048 0 1024 0.5)
->     ;r = sinOsc AR f 0 * 0.1
->     ;t = impulse KR 4 0
->     ;pf = poll t f (label "f") 0
->     ;px = poll t x (label "x") 0}
-> in audition (mrg [out 0 (mce2 o r),pf,px])
+> g_01 =
+>   let x = mouseX KR 440 880 Exponential 0.1
+>       o = lfSaw AR x 0 * 0.05 {- sinOsc AR x 0 * 0.1 -}
+>       [f,_e] = mceChannels (X.tartini KR o 0.2 2048 0 1024 0.5)
+>       r = sinOsc AR f 0 * 0.1
+>       t = impulse KR 4 0
+>       pf = poll t f 0 (label "f")
+>       px = poll t x 0 (label "x")
+>   in mrg [out 0 (mce2 o r),pf,px]
 
 Fast test of live pitch tracking, not careful with amplitude of input
 
-> let {z = soundIn 4
->     ;[f,e] = mceChannels (tartini KR z 0.2 2048 0 1024 0.5)}
-> in audition (out 0 (saw AR f * 0.05 * e))
+> g_02 =
+>   let z = hpf (soundIn 0) 90
+>       [f,e] = mceChannels (X.tartini KR z 0.2 2048 0 1024 0.5)
+>   in mce2 (z * 0.1) (lfTri AR f 0 * 0.2 * lag e 0.2 * lag (f >** 90 * f <** 500) 0.2)
+
+Printer for pitch tracker
+
+> g_03 =
+>   let i = soundIn 0
+>       [f,_e] = mceChannels (X.tartini KR i 0.2 2048 0 1024 0.5)
+>       r = sinOsc AR f 0 * 0.1
+>       t = impulse KR 4 0
+>       pf = poll t f 0 (label "f")
+>   in mrg [out 0 (mce2 i r),pf]
+
+ZELL = C4 - C5 = 247 259 277 295 309 331 345 369 387 415 441 462 493 (hz)
diff --git a/Help/UGen/thresh.help.lhs b/Help/UGen/thresh.help.lhs
--- a/Help/UGen/thresh.help.lhs
+++ b/Help/UGen/thresh.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "Operator.thresh"
-    > :t thresh
-
 > import Sound.SC3 {- hsc3 -}
 
 low-rent gate
diff --git a/Help/UGen/tiRand.help.lhs b/Help/UGen/tiRand.help.lhs
--- a/Help/UGen/tiRand.help.lhs
+++ b/Help/UGen/tiRand.help.lhs
@@ -1,7 +1,8 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "TIRand"
-    > Sound.SC3.UGen.DB.ugenSummary "TIRand"
-
 > import Sound.SC3 {- hsc3 -}
+
+> g_00 =
+>   let l = tiRand 'α' (-1) 1 (dust 'β' KR 10)
+>   in pan2 (pinkNoise 'γ' AR * 0.1) l 1
 
 > g_01 :: UId m => m UGen
 > g_01 = do
diff --git a/Help/UGen/timer.help.lhs b/Help/UGen/timer.help.lhs
--- a/Help/UGen/timer.help.lhs
+++ b/Help/UGen/timer.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "Timer"
-    Sound.SC3.UGen.DB.ugenSummary "Timer"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 =
diff --git a/Help/UGen/toggleFF.help.lhs b/Help/UGen/toggleFF.help.lhs
--- a/Help/UGen/toggleFF.help.lhs
+++ b/Help/UGen/toggleFF.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "ToggleFF"
-    > Sound.SC3.UGen.DB.ugenSummary "ToggleFF"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 =
diff --git a/Help/UGen/tpv.help.lhs b/Help/UGen/tpv.help.lhs
--- a/Help/UGen/tpv.help.lhs
+++ b/Help/UGen/tpv.help.lhs
@@ -1,14 +1,11 @@
-    Sound.SC3.UGen.Help.viewSC3Help "TPV"
-    Sound.SC3.UGen.DB.ugenSummary "TPV"
-
 > import Sound.SC3 {- hsc3 -}
-> import Sound.SC3.UGen.Bindings.DB.External {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
 
 > fft_sz = 2048::Int
 > hop_sz = fft_sz `div` 2
 > fn_0 = "/home/rohan/data/audio/pf-c5.snd"
 > fn_1 = "/home/rohan/data/audio/material/tyndall/var/talking-fragments/0001.WAV"
-> tpv' b i = tpv (fft b i 0.5 1 1 0) (constant fft_sz) (constant hop_sz)
+> tpv' b i = X.tpv (fft b i 0.5 1 1 0) (constant fft_sz) (constant hop_sz)
 > msg = [b_alloc 0 fft_sz 1,b_allocRead 1 fn_1 0 0]
 
     > withSC3 (mapM_ async msg)
diff --git a/Help/UGen/trig.help.lhs b/Help/UGen/trig.help.lhs
--- a/Help/UGen/trig.help.lhs
+++ b/Help/UGen/trig.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "Trig"
-    Sound.SC3.UGen.DB.ugenSummary "Trig"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 =
diff --git a/Help/UGen/trig1.help.lhs b/Help/UGen/trig1.help.lhs
--- a/Help/UGen/trig1.help.lhs
+++ b/Help/UGen/trig1.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "Trig1"
-    Sound.SC3.UGen.DB.ugenSummary "Trig1"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 =
diff --git a/Help/UGen/twChoose.help.lhs b/Help/UGen/twChoose.help.lhs
--- a/Help/UGen/twChoose.help.lhs
+++ b/Help/UGen/twChoose.help.lhs
@@ -1,5 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "TWChoose"
-
 tWChoose is a composite of tWindex and select
 
 > import Sound.SC3 {- hsc3 -}
diff --git a/Help/UGen/twoPole.help.lhs b/Help/UGen/twoPole.help.lhs
--- a/Help/UGen/twoPole.help.lhs
+++ b/Help/UGen/twoPole.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "TwoPole"
-    Sound.SC3.UGen.DB.ugenSummary "TwoPole"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 =
diff --git a/Help/UGen/twoTube.help.lhs b/Help/UGen/twoTube.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/twoTube.help.lhs
@@ -0,0 +1,11 @@
+> import Sound.SC3 {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
+
+> g_01 =
+>   let dly1 = 100
+>       dly2 = 40
+>       env = envelope [1,1,0] [(dly1 + dly2) / sampleRate,0.0] [EnvLin]
+>       x = mouseX KR (-1) 1 Linear 0.2
+>       y = mouseY KR 1 4 Linear 0.2
+>       src = whiteNoise 'α' AR * 0.5 * envGen AR (impulse KR y 0) 1 0 1 DoNothing env
+>   in X.twoTube AR src x 0.99 dly1 dly2
diff --git a/Help/UGen/twoZero.help.lhs b/Help/UGen/twoZero.help.lhs
--- a/Help/UGen/twoZero.help.lhs
+++ b/Help/UGen/twoZero.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "TwoZero"
-    Sound.SC3.UGen.DB.ugenSummary "TwoZero"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 =
diff --git a/Help/UGen/vDiskIn.help.lhs b/Help/UGen/vDiskIn.help.lhs
--- a/Help/UGen/vDiskIn.help.lhs
+++ b/Help/UGen/vDiskIn.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "VDiskIn"
-    Sound.SC3.UGen.DB.ugenSummary "VDiskIn"
-
 > import Sound.SC3 {- hsc3 -}
 
 > fn_01 = "/home/rohan/data/audio/pf-c5.snd"
diff --git a/Help/UGen/vOsc.help.lhs b/Help/UGen/vOsc.help.lhs
--- a/Help/UGen/vOsc.help.lhs
+++ b/Help/UGen/vOsc.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "VOsc"
-    Sound.SC3.UGen.DB.ugenSummary "VOsc"
-
 > import Sound.OSC {- hosc -}
 > import Sound.SC3 {- hsc3 -}
 
diff --git a/Help/UGen/vOsc3.help.lhs b/Help/UGen/vOsc3.help.lhs
--- a/Help/UGen/vOsc3.help.lhs
+++ b/Help/UGen/vOsc3.help.lhs
@@ -1,6 +1,3 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "VOsc3"
-    > Sound.SC3.UGen.DB.ugenSummary "VOsc3"
-
 > import Sound.SC3 {- hsc3 -}
 
 see vOsc help for code to allocate and fill tables 0 to 7...
diff --git a/Help/UGen/varLag.help.lhs b/Help/UGen/varLag.help.lhs
--- a/Help/UGen/varLag.help.lhs
+++ b/Help/UGen/varLag.help.lhs
@@ -1,13 +1,10 @@
-    Sound.SC3.UGen.Help.viewSC3Help "VarLag"
-    Sound.SC3.UGen.DB.ugenSummary "VarLag"
-
 > import Sound.SC3 {- hsc3 -}
 
-The implemented varLag UGen has three inputs: (input, lagTime, start)
+The implemented varLag UGen has five inputs: (input, lagTime, curvature, warp, start)
 
-> g_00 = varLag (lfPulse AR 50 0 0.5) (mouseX KR 0.0 (1/50) Linear 0.2) 0 * 0.2
+> g_00 = varLag (lfPulse AR 50 0 0.5) (mouseX KR 0.0 (1/50) Linear 0.2) 0 5 0 * 0.2
 
-> g_01 = varLag (impulse AR 50 0) (mouseX KR 0.0 (1/50) Linear 0.2) 0 * 0.2
+> g_01 = varLag (impulse AR 50 0) (mouseX KR 0.0 (1/50) Linear 0.2) 0 5 0 * 0.2
 
 The varLag_env composite UGen has various odd behaviours
 
@@ -35,7 +32,7 @@
 
 > f_03 s =
 >   let x = mouseX KR 0.0001 0.01 Exponential 0.2
->   in varLag s x s
+>   in varLag s x 0 5 s
 
 > g_07 = f_03 (0 - saw AR 440) * 0.15
 > g_08 = f_03 (impulse AR (range 6 24 (lfNoise2 'γ' KR 4)) 0) * 0.5
@@ -43,3 +40,10 @@
 > g_09 =
 >   let s = varSaw AR 220 0 (range 0 1 (sinOsc KR 0.25 0))
 >   in f_03 s * 0.1
+
+used to lag pitch
+
+> g_10 =
+>   let f1 = range 100 400 (lfPulse KR 1 0 0.5)
+>       f2 = varLag f1 0.2 (line KR (-8) 8 15 RemoveSynth) 5 0
+>   in sinOsc AR f2 0 * 0.3
diff --git a/Help/UGen/varSaw.help.lhs b/Help/UGen/varSaw.help.lhs
--- a/Help/UGen/varSaw.help.lhs
+++ b/Help/UGen/varSaw.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "VarSaw"
-    Sound.SC3.UGen.DB.ugenSummary "VarSaw"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_00 =
@@ -45,7 +42,7 @@
 
     > import Sound.OSC {- hosc -}
     > set_factor n = withSC3 (sendMessage (n_set1 (-1) "factor" n))
-    > set_factor 0.125 {- 0.5 1.5 23.0 0.125 1.3 -}
+    > set_factor 0.125 {- 0.125 0.5 1.3 1.5 23.0 -}
 
 slow indeterminate modulation of width, <http://sccode.org/1-5as>
 
diff --git a/Help/UGen/vibrato.help.lhs b/Help/UGen/vibrato.help.lhs
--- a/Help/UGen/vibrato.help.lhs
+++ b/Help/UGen/vibrato.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "Vibrato"
-    Sound.SC3.UGen.DB.ugenSummary "Vibrato"
-
 > import Sound.SC3 {- hsc3 -}
 
 vibrato at 1 Hz, note the use of DC.ar
@@ -8,7 +5,7 @@
     {SinOsc.ar(Vibrato.ar(DC.ar(400.0),1,0.02))*0.1}.play
 
 > g_01 =
->     let v = vibrato 'α' AR (dc AR 400) 1 0.02 0 0 0.04 0.1 0
+>     let v = vibrato 'α' AR (dc AR 400) 1 0.02 0 0 0.04 0.1 0 0
 >     in sinOsc AR v 0 * 0.1
 
 compare: k-rate freq input can be a constant
@@ -16,7 +13,7 @@
     {SinOsc.ar(Vibrato.kr(400.0,1,0.02))}.play
 
 > g_02 =
->     let v = vibrato 'α' KR 400 1 0.02 0 0 0.04 0.1 0
+>     let v = vibrato 'α' KR 400 1 0.02 0 0 0.04 0.1 0 0
 >     in sinOsc AR v 0 * 0.1
 
 control rate and rateVariation
@@ -29,7 +26,7 @@
 > g_03 =
 >     let x = mouseX KR 2 100 Linear 0.2
 >         y = mouseY KR 0 1 Linear 0.2
->         v = vibrato 'α' AR (dc AR 400) x 0.1 1 1 y 0.1 0
+>         v = vibrato 'α' AR (dc AR 400) x 0.1 1 1 y 0.1 0 0
 >     in sinOsc AR v 0 * 0.1
 
 control depth and depthVariation
@@ -44,5 +41,5 @@
 >     let n = lfNoise1 'α' KR 1 * 3 + 7
 >         x = mouseX KR 0 1 Linear 0.2
 >         y = mouseY KR 0 1 Linear 0.2
->         v = vibrato 'β' AR (dc AR 400) n x 1 1 y 0.1 0
+>         v = vibrato 'β' AR (dc AR 400) n x 1 1 y 0.1 0 0
 >     in sinOsc AR v 0 * 0.1
diff --git a/Help/UGen/vosim.help.lhs b/Help/UGen/vosim.help.lhs
--- a/Help/UGen/vosim.help.lhs
+++ b/Help/UGen/vosim.help.lhs
@@ -1,19 +1,16 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "VOSIM"
-    > Sound.SC3.UGen.DB.ugenSummary "VOSIM"
-
 > import Sound.SC3 {- hsc3 -}
-> import Sound.SC3.UGen.Bindings.DB.External {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
 
-> gr_00 =
+> g_00 =
 >     let trg = impulse AR 100 0
 >         frq = mouseX KR 440 880 Exponential 0.2
 >         n_cycles = 3
 >         dcy = 0.1
->     in vosim AR trg frq n_cycles dcy * 0.25
+>     in X.vosim AR trg frq n_cycles dcy * 0.25
 
-> gr_01 =
+> g_01 =
 >     let p = tRand 'α' 0 1 (impulse AR 6 0)
->         t = impulse AR (9 * ( 1 + ( p >* 0.95))) 0
+>         t = impulse AR (9 * ( 1 + ( p >** 0.95))) 0
 >         x = mouseX KR 0.25 2 Linear 0.2
 >         y = mouseY KR 0.25 0.75 Linear 0.2
 >         z = 9
@@ -27,5 +24,5 @@
 >         l = tR 'ζ' [-1] [1] t
 >         xn = mk_n 'η'
 >         yn = mk_n 'θ'
->         v = vosim AR t (f * x * xn) n (d * y * yn) * a
+>         v = X.vosim AR t (f * x * xn) n (d * y * yn) * a
 >     in pan2 (mix v) l 1
diff --git a/Help/UGen/warp1.help.lhs b/Help/UGen/warp1.help.lhs
--- a/Help/UGen/warp1.help.lhs
+++ b/Help/UGen/warp1.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "Warp1"
-    Sound.SC3.UGen.DB.ugenSummary "Warp1"
-
 > import Sound.SC3 {- hsc3 -}
 
 > fn_01 = "/home/rohan/data/audio/pf-c5.aif"
diff --git a/Help/UGen/waveTerrain.help.lhs b/Help/UGen/waveTerrain.help.lhs
--- a/Help/UGen/waveTerrain.help.lhs
+++ b/Help/UGen/waveTerrain.help.lhs
@@ -1,8 +1,5 @@
-    > Sound.SC3.UGen.Help.viewSC3Help "WaveTerrain"
-    > Sound.SC3.UGen.DB.ugenSummary "WaveTerrain"
-
 > import Sound.SC3 {- hsc3 -}
-> import Sound.SC3.UGen.Bindings.DB.External {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.DB.External as X {- hsc3 -}
 
 Terrain function, ie. (x,y) -> z
 
@@ -48,7 +45,7 @@
 >         x = abs (sinOsc AR x' 0) + lfNoise2 'α' AR 2
 >         y = abs (sinOsc AR y' (pi / 2))
 >         b = 0
->     in waveTerrain AR b x y 100 50
+>     in X.waveTerrain AR b x y 100 50
 
 Alternate terrain function.
 
diff --git a/Help/UGen/whiteNoise.help.lhs b/Help/UGen/whiteNoise.help.lhs
--- a/Help/UGen/whiteNoise.help.lhs
+++ b/Help/UGen/whiteNoise.help.lhs
@@ -1,10 +1,11 @@
-    Sound.SC3.UGen.Help.viewSC3Help "WhiteNoise"
-    Sound.SC3.UGen.DB.ugenSummary "WhiteNoise"
-
 > import Sound.SC3 {- hsc3 -}
 
-> g_01 = whiteNoise 'α' AR * 0.05
+> g_00 = let n = whiteNoise 'α' AR * 0.05 in mce2 n n
 
+> g_01_m = fmap (* 0.05) (whiteNoiseM AR)
+
+> g_01 = uid_st_eval g_01_m
+
 Random filtered noise bursts.
 
 > g_02 =
@@ -17,8 +18,7 @@
 
 Monadic form of above graph.
 
-> g_03 :: UId m => m UGen
-> g_03 = do
+> g_03_m = do
 >   n <- whiteNoiseM AR
 >   t <- dustM AR (mce [3, 7])
 >   f <- tExpRandM 20 1800 t
@@ -26,10 +26,11 @@
 >   let e = decay2 t 0.01 0.2
 >   return (resonz (n * e) f bw)
 
+> g_03 = uid_st_eval g_03_m
+
 The same graph again, without using do notation.
 
-> g_04 :: UId m => m UGen
-> g_04 =
+> g_04_m =
 >     whiteNoiseM AR >>= \n ->
 >     dustM AR (mce [3, 7]) >>= \t ->
 >     tExpRandM 20 1800 t >>= \f ->
@@ -37,6 +38,8 @@
 >     let e = decay2 t 0.01 0.2
 >     in return (resonz (n * e) f bw)
 
+> g_04 = uid_st_eval g_04_m
+
 Drawing
 
     import Sound.SC3.Plot {- hsc3-plot -}
@@ -61,4 +64,3 @@
 >     in pan2 n l 0.1
 
 > g_07 = hpz1 (whiteNoise 'α' AR * 0.01)
-
diff --git a/Help/UGen/wrapIndex.help.lhs b/Help/UGen/wrapIndex.help.lhs
--- a/Help/UGen/wrapIndex.help.lhs
+++ b/Help/UGen/wrapIndex.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "WrapIndex"
-    Sound.SC3.UGen.DB.ugenSummary "WrapIndex"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 =
diff --git a/Help/UGen/wt_FilterScale.help.lhs b/Help/UGen/wt_FilterScale.help.lhs
--- a/Help/UGen/wt_FilterScale.help.lhs
+++ b/Help/UGen/wt_FilterScale.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "WT_FilterScale"
-    Sound.SC3.UGen.DB.ugenSummary "WT_FilterScale"
-
 > import Sound.SC3 {- hsc3 -}
 > import Sound.SC3.UGen.Bindings.HW.External.Wavelets {- hsc3 -}
 
diff --git a/Help/UGen/wt_TimeWipe.help.lhs b/Help/UGen/wt_TimeWipe.help.lhs
--- a/Help/UGen/wt_TimeWipe.help.lhs
+++ b/Help/UGen/wt_TimeWipe.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "WT_TimeWipe"
-    Sound.SC3.UGen.DB.ugenSummary "WT_TimeWipe"
-
 > import Sound.SC3 {- hsc3 -}
 > import Sound.SC3.UGen.Bindings.HW.External.Wavelets {- hsc3 -}
 
diff --git a/Help/UGen/xFade2.help.lhs b/Help/UGen/xFade2.help.lhs
--- a/Help/UGen/xFade2.help.lhs
+++ b/Help/UGen/xFade2.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "XFade2"
-    Sound.SC3.UGen.DB.ugenSummary "XFade2"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 = xFade2 (saw AR 440) (sinOsc AR 440 0) (lfTri KR 0.1 0) 0.1
diff --git a/Help/UGen/xLine.help.lhs b/Help/UGen/xLine.help.lhs
--- a/Help/UGen/xLine.help.lhs
+++ b/Help/UGen/xLine.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "XLine"
-    Sound.SC3.UGen.DB.ugenSummary "XLine"
-
 Note: SC3 reorders mul and add inputs to precede the doneAction input.
 
 > import Sound.SC3 {- hsc3 -}
diff --git a/Help/UGen/xOut.help.lhs b/Help/UGen/xOut.help.lhs
--- a/Help/UGen/xOut.help.lhs
+++ b/Help/UGen/xOut.help.lhs
@@ -1,15 +1,14 @@
-    Sound.SC3.UGen.Help.viewSC3Help "XOut"
-    Sound.SC3.UGen.DB.ugenSummary "XOut"
-
 > import Sound.SC3 {- hsc3 -}
 
 Send signal to a bus, crossfading with existing contents.
 
 > g_01 =
->     let p a b = sinOsc AR (mce [a, b]) 0 * 0.1
+>     let p a b = sinOsc AR (mce2 a b) 0 * 0.1
 >         x = mouseX KR 0 1 Linear 0.1
 >         y = mouseY KR 0 1 Linear 0.1
 >     in mrg [out  0   (p 220 221)
 >            ,xOut 0 x (p 330 331)
 >            ,xOut 0 y (p 440 441)
 >            ,out  0   (p 120 121)]
+
+out is a summing output, see replaceOut for over-writing output.
diff --git a/Help/UGen/zeroCrossing.help.lhs b/Help/UGen/zeroCrossing.help.lhs
--- a/Help/UGen/zeroCrossing.help.lhs
+++ b/Help/UGen/zeroCrossing.help.lhs
@@ -1,6 +1,3 @@
-    Sound.SC3.UGen.Help.viewSC3Help "ZeroCrossing"
-    Sound.SC3.UGen.DB.ugenSummary "ZeroCrossing"
-
 > import Sound.SC3 {- hsc3 -}
 
 > g_01 =
diff --git a/Help/UGen/zitaRev.help.lhs b/Help/UGen/zitaRev.help.lhs
--- a/Help/UGen/zitaRev.help.lhs
+++ b/Help/UGen/zitaRev.help.lhs
@@ -1,9 +1,9 @@
-http://kokkinizita.linuxaudio.org/linuxaudio/zita-rev1-doc/quickguide.html
+<http://kokkinizita.linuxaudio.org/linuxaudio/zita-rev1-doc/quickguide.html>
 
 > import Sound.SC3 {- hsc3 -}
-> import qualified Sound.SC3.UGen.Bindings.HW.External.Zita as Zita {- hsc3 -}
+> import qualified Sound.SC3.UGen.Bindings.HW.External.X as X {- hsc3 -}
 
-    > Zita.zitaRev_param
+    > X.zitaRev_param
 
 mostly default settings
 
@@ -14,7 +14,7 @@
 >         eq2_freq = 1500
 >         dry_wet_mix = 0.5
 >         level = 0
->     in Zita.zitaRev i i in_delay 200 3 2 6000 eq1_freq 0 eq2_freq 0 dry_wet_mix level
+>     in X.zitaRev i i in_delay 200 3 2 6000 eq1_freq 0 eq2_freq 0 dry_wet_mix level
 
 longer
 
@@ -29,7 +29,7 @@
 >         eq2_level = 6
 >         dry_wet_mix = 0
 >         level = 0
->     in Zita.zitaRev i i in_delay 200 low_rt60 mid_rt60 6000 eq1_freq eq1_level eq2_freq eq2_level dry_wet_mix level
+>     in X.zitaRev i i in_delay 200 low_rt60 mid_rt60 6000 eq1_freq eq1_level eq2_freq eq2_level dry_wet_mix level
 
 longer still
 
@@ -44,6 +44,6 @@
 >         eq2_level = 6
 >         dry_wet_mix = 0.5
 >         level = 0.0
->     in Zita.zitaRev i i in_delay 200 low_rt60 mid_rt60 6000 eq1_freq eq1_level eq2_freq eq2_level dry_wet_mix level
+>     in X.zitaRev i i in_delay 200 low_rt60 mid_rt60 6000 eq1_freq eq1_level eq2_freq eq2_level dry_wet_mix level
 
 
diff --git a/README b/README
--- a/README
+++ b/README
@@ -1,12 +1,21 @@
 hsc3 - haskell supercollider
 ----------------------------
 
-[hsc3][hsc3] provides `Sound.SC3`, a module for using [Haskell][hs] as
-a client to the [SuperCollider][sc3] synthesis server.  hsc3 requires
-[hosc](?t=hosc).
+[hsc3](http://rohandrape.net/?t=hsc3)
+provides `Sound.SC3`, a module for using
+[Haskell](http://haskell.org/)
+as a client to the
+[SuperCollider](http://audiosynth.com/)
+synthesis server.
+hsc3 requires
+[hosc](http://rohandrape.net/?t=hosc).
 
-For installation and configuration information see the
-[tutorial][tutorial] at [hsc3-texts][hsc3-texts].
+There is an
+[introduction](http://rohandrape.net/?t=hsc3-texts&e=lhs/hsc3-introduction.lhs)
+and a
+[tutorial](http://rohandrape.net/?t=hsc3-texts&e=lhs/hsc3-tutorial.lhs)
+at
+[hsc3-texts](http://rohandrape.net/?t=hsc3-texts).
 
 There are a number of related projects:
 
@@ -17,7 +26,7 @@
 - [hsc3-unsafe](?t=hsc3-unsafe): Unsafe UGen variants (2006)
 - [hsc3-lang](?t=hsc3-lang): SC3 language (2007)
 - [hsc3-rec](?t=hsc3-rec): Record UGens (2008)
-- [hsc3-sf-hsndfile](?t=hsc3-sf): Sound file IO (libsndfile) (2010)
+- [hsc3-sf-hsndfile](?t=hsc3-sf-hsndfile): Sound file IO (libsndfile) (2010)
 - [hsc3-auditor](?t=hsc3-auditor): Simple-minded auditioner (2010)
 - [hsc3-cairo](?t=hsc3-cairo): Drawing (2012)
 - [hsc3-plot](?t=hsc3-plot): Plotting (2013)
@@ -25,18 +34,35 @@
 - [hsc3-rw](?t=hsc3-rw): UGen Graph Re-writing (2013)
 - [hsc3-forth](?t=hsc3-forth): FORTH SuperCollider (2014)
 - [hsc3-lisp](?t=hsc3-lisp): LISP SuperCollider (2014)
+- [hsc3-m](?t=hsc3-m): UGen variants (2018)
 
 The hsc3 interaction environment ([hsc3.el](?t=hsc3&e=emacs/hsc3.el))
-is written for [GNU][gnu] [Emacs][emacs].
+is written for
+[GNU](http://gnu.org/)
+[Emacs](http://gnu.org/software/emacs/).
 
+<!--
+There is also, more obliquely related:
+
+- [sc3-rdu](?t=sc3-rdu): SuperCollider UGens (1998)
+- [rsc3](?t=rsc3): Scheme SuperCollider (2004)
+- [smlsc3](?t=smlsc3): Standard ML SuperCollider (2008)
+-->
+
 ## cli
 
-[scsyndef-stat](?t=hsc3&e=md/scsyndef-stat.md),
-[scsyndef-to-hs](?t=hsc3&e=md/scsyndef-to-hs.md),
 [scsynth](?t=hsc3&e=md/scsynth.md),
 [setup](?t=hsc3&e=md/setup.md)
 
-© [rohan drape][rd] and others, 2005-2018, [gpl][gpl].
+## help
+
+[UGen Index](?t=hsc3&e=Help/UGen/ix.md)
+
+©
+[rohan drape](http://rohandrape.net/)
+and others, 2005-2020,
+[gpl](http://gnu.org/copyleft/)
+
 with contributions by:
 
 - henning thielemann
@@ -45,18 +71,11 @@
 - brent yorgey
 - shae erisson
 
-see the [git](https://git-scm.com/) [history](?t=hsc3&q=history) for details
+see the
+[git](https://git-scm.com/)
+[history](?t=hsc3&q=history)
+for details
 
 initial announcement:
 [[2005-11-29/haskell-cafe](?t=hsc3&e=md/announce.text),
  [haskell.org](http://www.haskell.org/pipermail/haskell-cafe/2005-November/012483.html)]
-
-[rd]: http://rohandrape.net/
-[hsc3]: http://rohandrape.net/?t=hsc3
-[hs]: http://haskell.org/
-[sc3]: http://audiosynth.com/
-[tutorial]: http://rohandrape.net/?t=hsc3-texts&e=lhs/hsc3-tutorial.lhs
-[hsc3-texts]: http://rohandrape.net/?t=hsc3-texts
-[gnu]: http://gnu.org/
-[emacs]: http://gnu.org/software/emacs/
-[gpl]: http://gnu.org/copyleft/
diff --git a/Sound/SC3/Common.hs b/Sound/SC3/Common.hs
--- a/Sound/SC3/Common.hs
+++ b/Sound/SC3/Common.hs
@@ -2,7 +2,10 @@
 module Sound.SC3.Common (module M) where
 
 import Sound.SC3.Common.Buffer as M
+import Sound.SC3.Common.Enum as M
 import Sound.SC3.Common.Envelope as M
 import Sound.SC3.Common.Math as M
+import Sound.SC3.Common.Math.Operator as M
 import Sound.SC3.Common.Monad as M
+import Sound.SC3.Common.Rate as M
 import Sound.SC3.Common.UId as M
diff --git a/Sound/SC3/Common/Base.hs b/Sound/SC3/Common/Base.hs
--- a/Sound/SC3/Common/Base.hs
+++ b/Sound/SC3/Common/Base.hs
@@ -1,8 +1,14 @@
 -- | Common core functions.
 module Sound.SC3.Common.Base where
 
+import Control.Exception {- base -}
+import Control.Monad {- base -}
 import Data.Char {- base -}
+import Data.Function {- base -}
 import Data.List {- base -}
+import Data.Maybe {- base -}
+import System.IO.Error {- base -}
+import System.Environment {- base -}
 
 -- * Function
 
@@ -65,13 +71,13 @@
 --
 -- > compose_l [(* 2),(+ 1)] 3 == 7
 compose_l :: [t -> t] -> t -> t
-compose_l = flip (foldl (\x f -> f x))
+compose_l = flip (foldl (&))
 
 -- | Right to left composition of a list of functions.
 --
 -- > compose_r [(* 2),(+ 1)] 3 == 8
 compose_r :: [t -> t] -> t -> t
-compose_r = flip (foldr (\f x -> f x))
+compose_r = flip (foldr ($))
 
 {- | SequenceableCollection.differentiate
 
@@ -112,9 +118,13 @@
 dx_d' = (0 :) . dx_d
 
 -- | 'lookup' with equality function.
-lookup_by :: (a -> a -> Bool) -> a -> [(a,b)] -> Maybe b
+lookup_by :: (a -> t -> Bool) -> a -> [(t,b)] -> Maybe b
 lookup_by f x = fmap snd . find (f x . fst)
 
+-- | Erroring variant.
+lookup_by_err :: (a -> t -> Bool) -> a -> [(t,b)] -> b
+lookup_by_err f x = fromMaybe (error "lookup_by") . lookup_by f x
+
 -- | Reverse 'lookup' with equality function.
 rlookup_by :: (b -> b -> Bool) -> b -> [(a,b)] -> Maybe a
 rlookup_by f x = fmap fst . find (f x . snd)
@@ -202,3 +212,19 @@
 -- | [x,y] -> (x,y)
 t2_from_list :: [t] -> T2 t
 t2_from_list l = case l of {[p,q] -> (p,q);_ -> error "t2_from_list"}
+
+-- * System
+
+-- | Guarded variant of 'getEnv' with default value.
+get_env_default :: String -> String -> IO String
+get_env_default e k = do
+  r <- tryJust (guard . isDoesNotExistError) (getEnv e)
+  case r of
+    Right v -> return v
+    _ -> return k
+
+-- | 'lookupEnv' with default value.
+--
+-- > lookup_env_default "PATH" "/usr/bin"
+lookup_env_default :: String -> String -> IO String
+lookup_env_default e k = fmap (fromMaybe k) (lookupEnv e)
diff --git a/Sound/SC3/Common/Buffer.hs b/Sound/SC3/Common/Buffer.hs
--- a/Sound/SC3/Common/Buffer.hs
+++ b/Sound/SC3/Common/Buffer.hs
@@ -18,11 +18,10 @@
 
 -- | Variant of '(!!)' but values for index greater than the size of
 -- the collection will be clipped to the last index.
+--
+-- > map (\x -> clipAt x "abc") [-1,0,1,2,3] == "aabcc"
 clipAt :: Int -> [a] -> a
-clipAt ix c =
-    if ix > length c - 1
-    then last c
-    else c !! ix
+clipAt ix c = if ix > length c - 1 then last c else if ix < 0 then c !! 0 else c !! ix
 
 -- | 'abs' of '(-)'.
 absdif :: Num a => a -> a -> a
@@ -76,9 +75,7 @@
 -- > > [1,2,3].normalizeSum == [1/6,1/3,0.5]
 -- > normalizeSum [1,2,3] == [1/6,2/6,3/6]
 normalizeSum :: (Fractional a) => [a] -> [a]
-normalizeSum l =
-    let n = sum l
-    in map (/ n) l
+normalizeSum l = let n = sum l in map (/ n) l
 
 -- | Variant that specifies range of input sequence separately.
 normalise_rng :: Fractional n => (n,n) -> (n,n) -> [n] -> [n]
diff --git a/Sound/SC3/Common/Buffer/Gen.hs b/Sound/SC3/Common/Buffer/Gen.hs
--- a/Sound/SC3/Common/Buffer/Gen.hs
+++ b/Sound/SC3/Common/Buffer/Gen.hs
@@ -32,7 +32,6 @@
 
 -- | 'sum_l' of 'sine1_l'.
 --
--- > import Sound.SC3.Plot {- hsc3-plot -}
 -- > plotTable1 (sine1 256 [1,0.95 .. 0.5])
 sine1 :: (Enum n,Floating n) => Int -> [n] -> [n]
 sine1 n = sum_l . sine1_l n
@@ -82,7 +81,6 @@
 
 {- | Generate Chebyshev waveshaping table, see b_gen_cheby.
 
-> import Sound.SC3.Plot
 > plotTable1 (gen_cheby 256 [1,0,1,1,0,1])
 
 -}
diff --git a/Sound/SC3/Common/Enum.hs b/Sound/SC3/Common/Enum.hs
new file mode 100644
--- /dev/null
+++ b/Sound/SC3/Common/Enum.hs
@@ -0,0 +1,122 @@
+-- | Data types for enumerated and non signal unit generator inputs.
+module Sound.SC3.Common.Enum where
+
+-- * Loop
+
+-- | Loop indicator input.
+data Loop t =
+    NoLoop -- ^ 0
+  | Loop -- ^ 1
+  | WithLoop t
+  deriving (Eq, Show)
+
+-- | Apply /f/ at 'WithLoop'.
+loop_coerce :: (t -> u) -> Loop t -> Loop u
+loop_coerce f lp =
+  case lp of
+    NoLoop -> NoLoop
+    Loop -> Loop
+    WithLoop t -> WithLoop (f t)
+
+-- | fmap is 'loop_coerce'
+instance Functor Loop where
+  fmap = loop_coerce
+
+-- | Resolve 'Loop'.
+from_loop :: Num t => Loop t -> t
+from_loop e =
+    case e of
+      NoLoop -> 0
+      Loop -> 1
+      WithLoop u -> u
+
+-- * Interpolation
+
+-- | Interpolation indicator input.
+data Interpolation t =
+    NoInterpolation
+  | LinearInterpolation
+  | CubicInterpolation
+  | WithInterpolation t
+  deriving (Eq, Show)
+
+-- | Resolve 'Interpolation'.
+from_interpolation :: Num t => Interpolation t -> t
+from_interpolation e =
+    case e of
+      NoInterpolation -> 1
+      LinearInterpolation -> 2
+      CubicInterpolation -> 4
+      WithInterpolation u -> u
+
+-- * DoneAction
+
+-- | Completion mode indicator input.
+data DoneAction t
+  = DoNothing
+  | PauseSynth
+  | RemoveSynth
+  | RemoveGroup
+  | WithDoneAction t
+  deriving (Eq, Show)
+
+-- | Apply /f/ at 'WithDoneAction'.
+done_action_coerce :: (t -> u) -> DoneAction t -> DoneAction u
+done_action_coerce f e =
+    case e of
+      DoNothing -> DoNothing
+      PauseSynth -> PauseSynth
+      RemoveSynth -> RemoveSynth
+      RemoveGroup -> RemoveGroup
+      WithDoneAction x -> WithDoneAction (f x)
+
+-- | fmap is 'done_action_coerce'
+instance Functor DoneAction where
+  fmap = done_action_coerce
+
+-- | Resolve 'DoneAction'.
+from_done_action :: Num t => DoneAction t -> t
+from_done_action e =
+    case e of
+      DoNothing -> 0
+      PauseSynth -> 1
+      RemoveSynth -> 2
+      RemoveGroup -> 14
+      WithDoneAction x -> x
+
+-- * Warp
+
+-- | Warp interpolation indicator input.
+data Warp t =
+    Linear
+  | Exponential
+  | WithWarp t
+  deriving (Eq, Show)
+
+-- | Resolve 'Warp'.
+from_warp :: Num t => Warp t -> t
+from_warp e =
+    case e of
+      Linear -> 0
+      Exponential -> 1
+      WithWarp u -> u
+
+-- | Apply /f/ at 'WithWarp'
+warp_coerce :: (t -> u) -> Warp t -> Warp u
+warp_coerce f e =
+    case e of
+      Linear -> Linear
+      Exponential -> Exponential
+      WithWarp u -> WithWarp (f u)
+
+-- | fmap = 'warp_coerce'
+instance Functor Warp where
+  fmap = warp_coerce
+
+-- * Buffer
+
+-- | Unification of integer and 'UGen' buffer identifiers.
+data Buffer t =
+    Buffer_Id Int
+  | Buffer t
+  deriving (Eq, Show)
diff --git a/Sound/SC3/Common/Envelope.hs b/Sound/SC3/Common/Envelope.hs
--- a/Sound/SC3/Common/Envelope.hs
+++ b/Sound/SC3/Common/Envelope.hs
@@ -102,6 +102,10 @@
     let Envelope l t c rn ln os = e
     in Envelope (map f l) (map f t) (map (env_curve_coerce f) c) rn ln (f os)
 
+-- | fmap = 'envelope_coerce'
+instance Functor Envelope where
+  fmap = envelope_coerce
+
 -- | Variant without release and loop node inputs (defaulting to nil).
 envelope :: Num a => [a] -> [a] -> [Envelope_Curve a] -> Envelope a
 envelope l t c = Envelope l t c Nothing Nothing 0
diff --git a/Sound/SC3/Common/Math.hs b/Sound/SC3/Common/Math.hs
--- a/Sound/SC3/Common/Math.hs
+++ b/Sound/SC3/Common/Math.hs
@@ -1,12 +1,14 @@
 -- | Common math functions.
 module Sound.SC3.Common.Math where
 
-import Data.Fixed {- base -}
+import qualified Data.Fixed {- base -}
 import Data.Maybe {- base -}
 import Data.Ratio {- base -}
-import Numeric {- base -}
-import Text.Read {- base -}
+import qualified Numeric {- base -}
+import qualified Text.Read {- base -}
 
+import qualified Safe {- safe -}
+
 -- | Half pi.
 --
 -- > half_pi == 1.5707963267948966
@@ -19,13 +21,29 @@
 two_pi :: Floating n => n
 two_pi = 2 * pi
 
--- | Multiply and add, ordinary haskell argument order.
--- See also 'mul_add' of the 'MulAdd' class.
+-- | SC3 MulAdd type signature, arguments in SC3 order of input, multiply, add.
+type SC3_MulAdd t = t -> t -> t -> t
+
+-- | Ordinary (un-optimised) multiply-add, see also mulAdd UGen.
 --
--- > map (mul_add_hs 2 3) [1,2] == [5,7] && map (mul_add_hs 3 4) [1,2] == [7,10]
-mul_add_hs :: Num a => a -> a -> a -> a
-mul_add_hs m a = (+ a) . (* m)
+-- > sc3_mul_add 2 3 4 == 2 * 3 + 4
+-- > map (\x -> sc3_mul_add x 2 3) [1,5] == [5,13] && map (\x -> sc3_mul_add x 3 2) [1,5] == [5,17]
+sc3_mul_add :: Num t => SC3_MulAdd t
+sc3_mul_add i m a = i * m + a
 
+-- | Ordinary Haskell order (un-optimised) multiply-add.
+--
+-- > mul_add 3 4 2 == 2 * 3 + 4
+-- > map (mul_add 2 3) [1,5] == [5,13] && map (mul_add 3 4) [1,5] == [7,19]
+mul_add :: Num t => t -> t -> t -> t
+mul_add m a = (+ a) . (* m)
+
+-- | 'uncurry' 'mul_add'
+--
+-- > mul_add_hs (3,4) 2 == 2 * 3 + 4
+mul_add_hs :: Num t => (t,t) -> t -> t
+mul_add_hs = uncurry mul_add
+
 -- | 'fromInteger' of 'truncate'.
 sc3_truncate :: RealFrac a => a -> a
 sc3_truncate = fromInteger . truncate
@@ -48,6 +66,7 @@
 --
 -- > let r = [0,0,0.25,0.25,0.5,0.5,0.5,0.75,0.75,1,1]
 -- > map (`sc3_round_to` 0.25) [0,0.1 .. 1] == r
+-- > map (`sc3_round_to` 5.0) [100.0 .. 110.0]
 sc3_round_to :: RealFrac n => n -> n -> n
 sc3_round_to a b = if b == 0 then a else sc3_floor ((a / b) + 0.5) * b
 
@@ -55,7 +74,7 @@
 sc3_idiv :: RealFrac n => n -> n -> n
 sc3_idiv a b = fromInteger (floor a `div` floor b)
 
-{- | The SC3 @%@ UGen operator is the 'Numeric.mod'' function.
+{- | The SC3 @%@ UGen operator is the 'Data.Fixed.mod'' function.
 
 > > 1.5 % 1.2 // ~= 0.3
 > > -1.5 % 1.2 // ~= 0.9
@@ -81,7 +100,7 @@
 > map (\n -> sc3_mod n 12.0) [-1.0,12.25,15.0] == [11.0,0.25,3.0]
 -}
 sc3_mod :: RealFrac n => n -> n -> n
-sc3_mod = mod'
+sc3_mod = Data.Fixed.mod'
 
 -- | Type specialised 'sc3_mod'.
 fmod_f32 :: Float -> Float -> Float
@@ -169,10 +188,11 @@
 bin_to_freq :: (Fractional n, Integral i) => n -> i -> i -> n
 bin_to_freq sr n i = fromIntegral i * sr / fromIntegral n
 
--- | Midi note number to cycles per second.
+-- | Fractional midi note number to cycles per second.
 --
 -- > map (floor . midi_to_cps) [0,24,69,120,127] == [8,32,440,8372,12543]
 -- > map (floor . midi_to_cps) [-36,138] == [1,23679]
+-- > map (floor . midi_to_cps) [69.0,69.25 .. 70.0] == [440,446,452,459,466]
 midi_to_cps :: Floating a => a -> a
 midi_to_cps i = 440.0 * (2.0 ** ((i - 69.0) * (1.0 / 12.0)))
 
@@ -191,6 +211,7 @@
 
 -- | Linear octave to cycles per second.
 --
+-- > > [4.0,4.25,4.75].octcps.cpsmidi == [60,63,69]
 -- > map (cps_to_midi . oct_to_cps) [4.0,4.25,4.75] == [60,63,69]
 oct_to_cps :: Floating a => a -> a
 oct_to_cps a = 440.0 * (2.0 ** (a - 4.75))
@@ -201,7 +222,7 @@
     let l = length s
         d' = round d
         a = (d - fromIntegral d') * 10.0 * (n / 12.0)
-    in (n * fromIntegral (d' `div` l)) + (s !! (d' `mod` l)) + a
+    in (n * fromIntegral (d' `div` l)) + (Safe.atNote "degree_to_key" s (d' `mod` l)) + a
 
 -- | Linear amplitude to decibels.
 --
@@ -217,7 +238,7 @@
 
 -- | Fractional midi note interval to frequency multiplier.
 --
--- > map midi_to_ratio [0,7,12] == [1,1.4983070768766815,2]
+-- > map midi_to_ratio [-12,0,7,12] == [0.5,1,1.4983070768766815,2]
 midi_to_ratio :: Floating a => a -> a
 midi_to_ratio a = 2.0 ** (a * (1.0 / 12.0))
 
@@ -374,31 +395,45 @@
 
 -- * LinLin
 
--- | Scale uni-polar (0,1) input to linear (l,r) range
+-- | Scale uni-polar (0,1) input to linear (l,r) range.
+urange_ma :: Fractional a => SC3_MulAdd a -> a -> a -> a -> a
+urange_ma mul_add_f l r i = mul_add_f i (r - l) l
+
+-- | Scale (0,1) input to linear (l,r) range. u = uni-polar.
 --
 -- > map (urange 3 4) [0,0.5,1] == [3,3.5,4]
 urange :: Fractional a => a -> a -> a -> a
-urange l r i = let m = r - l in i * m + l
+urange = urange_ma sc3_mul_add
 
--- | Calculate multiplier and add values for 'range' transform.
+-- | Calculate multiplier and add values for (-1,1) 'range' transform.
 --
 -- > range_muladd 3 4 == (0.5,3.5)
 range_muladd :: Fractional t => t -> t -> (t,t)
 range_muladd = linlin_muladd (-1) 1
 
 -- | Scale bi-polar (-1,1) input to linear (l,r) range.  Note that the
--- argument order is not the same as 'linlin'.
+-- argument order is not the same as 'linLin'.
+range_ma :: Fractional a => SC3_MulAdd a -> a -> a -> a -> a
+range_ma mul_add_f l r i =
+  let (m,a) = range_muladd l r
+  in mul_add_f i m a
+
+-- | Scale (-1,1) input to linear (l,r) range.  Note that the argument
+-- order is not the same as 'linlin'. Note also that the various range
+-- UGen methods at sclang select mul-add values given the output range
+-- of the UGen, ie LFPulse.range selects a (0,1) input range.
 --
 -- > map (range 3 4) [-1,0,1] == [3,3.5,4]
 -- > map (\x -> let (m,a) = linlin_muladd (-1) 1 3 4 in x * m + a) [-1,0,1] == [3,3.5,4]
 range :: Fractional a => a -> a -> a -> a
-range l r i = let (m,a) = range_muladd l r in i * m + a
+range = range_ma sc3_mul_add
 
--- | Tuple variant of 'range'.
+-- | 'uncurry' 'range'
 range_hs :: Fractional a => (a,a) -> a -> a
-range_hs (l,r) = range l r
+range_hs = uncurry range
 
 -- | Calculate multiplier and add values for 'linlin' transform.
+--   Inputs are: input-min input-max output-min output-max
 --
 -- > range_muladd 3 4 == (0.5,3.5)
 -- > linlin_muladd (-1) 1 3 4 == (0.5,3.5)
@@ -411,11 +446,19 @@
         a = dl - (m * sl)
     in (m,a)
 
--- | 'sc3_linlin' with a more typical haskell argument structure, ranges as pairs and input last.
+-- | Map from one linear range to another linear range.
 --
--- > map (linlin_hs (0,127) (-0.5,0.5)) [0,63.5,127]
+-- > linlin_ma hs_muladd 5 0 10 (-1) 1 == 0
+linlin_ma :: Fractional a => SC3_MulAdd a -> a -> a -> a -> a -> a -> a
+linlin_ma mul_add_f i sl sr dl dr =
+  let (m,a) = linlin_muladd sl sr dl dr
+  in mul_add_f i m a
+
+-- | 'linLin' with a more typical haskell argument structure, ranges as pairs and input last.
+--
+-- > map (linlin_hs (0,127) (-0.5,0.5)) [0,63.5,127] == [-0.5,0.0,0.5]
 linlin_hs :: Fractional a => (a, a) -> (a, a) -> a -> a
-linlin_hs (sl,sr) (dl,dr) i = let (m,a) = linlin_muladd sl sr dl dr in i * m + a
+linlin_hs (sl,sr) (dl,dr) = let (m,a) = linlin_muladd sl sr dl dr in (+ a) . (* m)
 
 {- | Map from one linear range to another linear range.
 
@@ -569,28 +612,44 @@
 
 -- * PP
 
--- | The default show is odd, 0.05 shows as 5.0e-2.
---
--- > unwords (map (double_pp 4) [0.0001,0.001,0.01,0.1,1.0]) == "0.0001 0.001 0.01 0.1 1.0"
-double_pp :: Int -> Double -> String
-double_pp k n =
+-- | Removes all but the last trailing zero from floating point string.
+double_pp_rm0 :: String -> String
+double_pp_rm0 =
     let rev_f f = reverse . f . reverse
         remv l = case l of
                    '0':'.':_ -> l
                    '0':l' -> remv l'
                    _ -> l
-    in rev_f remv (showFFloat (Just k) n "")
+    in rev_f remv
 
+-- | The default show is odd, 0.05 shows as 5.0e-2.
+--
+-- > unwords (map (double_pp 4) [0.0001,0.001,0.01,0.1,1.0]) == "0.0001 0.001 0.01 0.1 1.0"
+double_pp :: Int -> Double -> String
+double_pp k n = double_pp_rm0 (Numeric.showFFloat (Just k) n "")
+
 -- | Print as integer if integral, else as real.
 --
--- > unwords (map real_pp [0.0001,0.001,0.01,0.1,1.0]) == "0.0001 0.001 0.01 0.1 1"
-real_pp :: Double -> String
-real_pp n =
+-- > unwords (map (real_pp 5) [0.0001,0.001,0.01,0.1,1.0]) == "0.0001 0.001 0.01 0.1 1"
+real_pp :: Int -> Double -> String
+real_pp k n =
     let r = toRational n
-    in if denominator r == 1 then show (numerator r) else double_pp 5 n
+    in if denominator r == 1 then show (numerator r) else double_pp k n
 
 -- * Parser
 
--- | Type-specialised 'R.readMaybe'.
+-- | Type-specialised 'Text.Read.readMaybe'.
 parse_double :: String -> Maybe Double
-parse_double = readMaybe
+parse_double = Text.Read.readMaybe
+
+-- * Optimiser
+
+-- | Non-specialised optimised sum function (3 & 4 element adders).
+sum_opt_f :: Num t => (t -> t -> t -> t) -> (t -> t -> t -> t -> t) -> [t] -> t
+sum_opt_f f3 f4 =
+  let recur l =
+        case l of
+          p:q:r:s:l' -> recur (f4 p q r s : l')
+          p:q:r:l' -> recur (f3 p q r : l')
+          _ -> sum l
+  in recur
diff --git a/Sound/SC3/Common/Math/Noise.hs b/Sound/SC3/Common/Math/Noise.hs
new file mode 100644
--- /dev/null
+++ b/Sound/SC3/Common/Math/Noise.hs
@@ -0,0 +1,47 @@
+-- | Noise generating functions.
+module Sound.SC3.Common.Math.Noise where
+
+import Sound.SC3.Common.Math {- hsc3 -}
+
+-- | x(n+1) = a - b * sqrt(|x(n)|)
+cusp_f :: Floating t => t -> t -> t -> t
+cusp_f a b x = a - (b * sqrt (abs x))
+
+-- | x(n+1) = sin(im * y(n) + fb * x(n))
+--   y(n+1) = (a * y(n) + c) % 2pi
+fbSine_f :: (Floating t, RealFrac t) => t -> t -> t -> t -> (t, t) -> (t, t)
+fbSine_f im fb a c (x,y) = (sin ((im * y) + (fb * x)),((a * y) + c) `sc3_mod` (2 * pi))
+
+-- | x(n+2) = 1 - a * x(n+1)^2 + b * x(n)
+henon_f :: Floating t => t -> t -> (t, t) -> (t, t)
+henon_f a b (x1,x0) = (1 - (a * (x1 ** 2)) + (b * x0),x1)
+
+-- | x(n+1) = sin(b * y(n)) + c * sin(b * x(n))
+--   y(n+1) = sin(a * x(n)) + d * sin(a * y(n))
+latoocarfian_f :: Floating t => t -> t -> t -> t -> (t, t) -> (t, t)
+latoocarfian_f a b c d (x,y) = (sin(b * y) + (c * sin (b * x)),sin(a * x) + (d * sin (a * y)))
+
+-- | x(n+1) = (a * x(n) + c) % m
+linCong_f :: RealFrac t => t -> t -> t -> t -> t
+linCong_f a c m x = (a * x + c) `sc3_mod` m
+
+-- | x(n+1) = a * x * (1.0 - x)
+logistic_f :: Num t => t -> t -> t
+logistic_f a x = a * x * (1 - x)
+
+-- | x' = s * (y - x)
+--   y' = x * (r - z) - y
+--   z' = x * y - b * z
+lorenz_f :: Num t => t -> t -> t -> (t, t, t) -> (t, t, t)
+lorenz_f s r b (x,y,z) = (s * (y - x),x * (r - z) - y,x * y - b * z)
+
+-- | x(n+1) = a * x(n)^2 + b * x(n) + c
+quad_f :: Floating t => t -> t -> t -> t -> t
+quad_f a b c x = (a * (x ** 2)) + (b * x) + c
+
+-- | x(n+1) = (x(n) + y(n+1)) % 2pi
+--   y(n+1) = (y(n) + k * sin(x(n))) % 2pi
+standard_f :: (RealFrac t, Floating t) => t -> (t, t) -> (t, t)
+standard_f k (x,y) =
+  let y' = (y + (k * sin x)) `sc3_mod` two_pi
+  in ((x + y') `sc3_mod` two_pi,y')
diff --git a/Sound/SC3/Common/Math/Operator.hs b/Sound/SC3/Common/Math/Operator.hs
new file mode 100644
--- /dev/null
+++ b/Sound/SC3/Common/Math/Operator.hs
@@ -0,0 +1,490 @@
+{- | Non-standard mathematical enumerations, classes and base instances.
+
+Enumerations of the unary and binary math unit generators.
+Names that conflict with existing names have a @_@ suffix.
+
+The Eq and Ord classes in the Prelude require Bool, hence EqE and OrdE.
+True is 1.0, False is 0.0
+
+The RealFrac class requires Integral results, hence RealFracE.
+
+-}
+module Sound.SC3.Common.Math.Operator where
+
+import Control.Monad {- base -}
+import qualified Data.Fixed as F {- base -}
+import Data.Int {- base -}
+import Data.Maybe {- base -}
+
+import qualified Sound.SC3.Common.Base as Base {- hsc3 -}
+import qualified Sound.SC3.Common.Math as Math {- hsc3 -}
+
+-- * Unary
+
+-- | Enumeration of @SC3@ unary operator UGens.
+data SC3_Unary_Op
+            = Neg -- -
+            | Not -- !
+            | IsNil
+            | NotNil
+            | BitNot
+            | Abs
+            | AsFloat
+            | AsInt
+            | Ceil
+            | Floor
+            | Frac
+            | Sign
+            | Squared
+            | Cubed
+            | Sqrt
+            | Exp
+            | Recip
+            | MIDICPS
+            | CPSMIDI
+            | MIDIRatio
+            | RatioMIDI
+            | DbAmp
+            | AmpDb
+            | OctCPS
+            | CPSOct
+            | Log
+            | Log2
+            | Log10
+            | Sin
+            | Cos
+            | Tan
+            | ArcSin
+            | ArcCos
+            | ArcTan
+            | SinH
+            | CosH
+            | TanH
+            | Rand_ -- UGen
+            | Rand2
+            | LinRand_ -- UGen
+            | BiLinRand
+            | Sum3Rand
+            | Distort
+            | SoftClip
+            | Coin
+            | DigitValue
+            | Silence
+            | Thru
+            | RectWindow
+            | HanWindow
+            | WelchWindow
+            | TriWindow
+            | Ramp_ -- UGen
+            | SCurve
+              deriving (Eq,Show,Enum,Bounded,Read)
+
+-- | Type-specialised 'Base.parse_enum'.
+--
+-- > mapMaybe (parse_unary Base.CS) (words "Abs Rand_") == [Abs,Rand_]
+parse_unary :: Base.Case_Rule -> String -> Maybe SC3_Unary_Op
+parse_unary = Base.parse_enum
+
+-- | Table of operator names (non-symbolic) and indices.
+--
+-- > map fst sc3_unary_op_tbl
+sc3_unary_op_tbl :: [(String,Int)]
+sc3_unary_op_tbl = zip (map show [Neg .. SCurve]) [0..]
+
+-- | Table of symbolic names for standard unary operators.
+unary_sym_tbl :: [(SC3_Unary_Op,String)]
+unary_sym_tbl = [] -- (Neg,"-"),(Not,"!")
+
+-- | Lookup possibly symbolic name for standard unary operators.
+unaryName :: Int -> String
+unaryName n =
+    let e = toEnum n
+    in fromMaybe (show e) (lookup e unary_sym_tbl)
+
+-- | Given name of unary operator derive index.
+--
+-- > mapMaybe (unaryIndex CI) (words "NEG CUBED") == [0,13]
+-- > unaryIndex CS "SinOsc" == Nothing
+unaryIndex :: Base.Case_Rule -> String -> Maybe Int
+unaryIndex cr nm =
+    let ix = Base.rlookup_str cr nm unary_sym_tbl
+        ix' = parse_unary cr nm
+    in fmap fromEnum (mplus ix' ix)
+
+-- | 'isJust' of 'unaryIndex'.
+--
+-- > map (is_unary CI) (words "ABS MIDICPS NEG")
+-- > map (is_unary CI) (words "- RAND")
+is_unary :: Base.Case_Rule -> String -> Bool
+is_unary cr = isJust . unaryIndex cr
+
+-- * Binary
+
+-- | Enumeration of @SC3@ unary operator UGens.
+--
+-- > map show [minBound :: Binary .. maxBound]
+data SC3_Binary_Op
+            = Add -- 0
+            | Sub -- 1
+            | Mul -- 2
+            | IDiv
+            | FDiv -- 4
+            | Mod -- 5
+            | EQ_ -- 6
+            | NE -- 7
+            | LT_ -- 8
+            | GT_ -- 9
+            | LE -- 10
+            | GE -- 11
+            | Min -- 12
+            | Max
+            | BitAnd
+            | BitOr
+            | BitXor
+            | LCM
+            | GCD
+            | Round
+            | RoundUp
+            | Trunc
+            | Atan2
+            | Hypot
+            | Hypotx
+            | Pow -- 25
+            | ShiftLeft
+            | ShiftRight
+            | UnsignedShift
+            | Fill
+            | Ring1
+            | Ring2
+            | Ring3
+            | Ring4
+            | DifSqr
+            | SumSqr
+            | SqrSum
+            | SqrDif
+            | AbsDif
+            | Thresh
+            | AMClip
+            | ScaleNeg
+            | Clip2
+            | Excess
+            | Fold2
+            | Wrap2
+            | FirstArg
+            | RandRange
+            | ExpRandRange
+              deriving (Eq,Show,Enum,Bounded,Read)
+
+-- | Table of operator names (non-symbolic) and indices.
+sc3_binary_op_tbl :: [(String,Int)]
+sc3_binary_op_tbl = zip (map show [Add .. ExpRandRange]) [0..]
+
+-- | Type-specialised 'parse_enum'.
+parse_binary :: Base.Case_Rule -> String -> Maybe SC3_Binary_Op
+parse_binary = Base.parse_enum
+
+-- | Table of symbolic names for standard binary operators.
+binary_sym_tbl :: [(SC3_Binary_Op,String)]
+binary_sym_tbl =
+    [(Add,"+")
+    ,(Sub,"-")
+    ,(Mul,"*")
+    ,(FDiv,"/")
+    ,(Mod,"%")
+    ,(EQ_,"==")
+    ,(NE,"/=") -- !=
+    ,(LT_,"<")
+    ,(GT_,">")
+    ,(LE,"<=")
+    ,(GE,">=")
+    ,(BitAnd,".&.") -- &
+    ,(BitOr,".|.") -- |
+    ,(Pow,"**")]
+
+-- | Table of operator names (non-symbolic) and indices.
+--
+-- > map fst sc3_binary_op_sym_tbl
+sc3_binary_op_sym_tbl :: [(String,Int)]
+sc3_binary_op_sym_tbl =
+  let f x = maybe (show x) id (lookup x binary_sym_tbl)
+  in zip (map f [Add .. ExpRandRange]) [0..]
+
+-- | Lookup possibly symbolic name for standard binary operators.
+--
+-- > map binaryName [1,2,8,12] == ["-","*","<","Min"]
+binaryName :: Int -> String
+binaryName n =
+    let e = toEnum n
+    in fromMaybe (show e) (lookup e binary_sym_tbl)
+
+-- | Given name of binary operator derive index.
+--
+-- > mapMaybe (binaryIndex CI) (words "* MUL RING1") == [2,2,30]
+-- > binaryIndex CI "SINOSC" == Nothing
+binaryIndex :: Base.Case_Rule -> String -> Maybe Int
+binaryIndex cr nm =
+    let ix = Base.rlookup_str cr nm binary_sym_tbl
+        ix' = parse_binary cr nm
+    in fmap fromEnum (mplus ix' ix)
+
+-- | 'isJust' of 'binaryIndex'.
+--
+-- > map (is_binary CI) (words "== > % TRUNC MAX")
+is_binary :: Base.Case_Rule -> String -> Bool
+is_binary cr = isJust . binaryIndex cr
+
+-- * Operator
+
+-- | Order of lookup: binary then unary.
+--
+-- > map (resolve_operator Sound.SC3.Common.Base.CI) (words "+ - ADD SUB NEG")
+resolve_operator :: Base.Case_Rule -> String -> (String,Maybe Int)
+resolve_operator cr nm =
+    case binaryIndex cr nm of
+      Just sp -> ("SC3_Binary_OpOpUGen",Just sp)
+      Nothing -> case unaryIndex cr nm of
+                   Just sp -> ("UnaryOpUGen",Just sp)
+                   _ -> (nm,Nothing)
+
+-- * Classes
+
+-- | Variant on 'Eq' class, result is of the same type as the values compared.
+class (Eq a,Num a) => EqE a where
+  equal_to :: a -> a -> a
+  equal_to = Math.sc3_eq
+  not_equal_to :: a -> a -> a
+  not_equal_to = Math.sc3_neq
+
+instance EqE Int where
+instance EqE Integer where
+instance EqE Int32 where
+instance EqE Int64 where
+instance EqE Float where
+instance EqE Double where
+
+-- | Variant on Ord class, result is of the same type as the values compared.
+class (Ord a,Num a) => OrdE a where
+    less_than :: a -> a -> a
+    less_than = Math.sc3_lt
+    less_than_or_equal_to :: a -> a -> a
+    less_than_or_equal_to = Math.sc3_lte
+    greater_than :: a -> a -> a
+    greater_than = Math.sc3_gt
+    greater_than_or_equal_to :: a -> a -> a
+    greater_than_or_equal_to = Math.sc3_gte
+
+instance OrdE Int
+instance OrdE Integer
+instance OrdE Int32
+instance OrdE Int64
+instance OrdE Float
+instance OrdE Double
+
+-- | Variant of 'RealFrac' with non 'Integral' results.
+class RealFrac a => RealFracE a where
+  properFractionE :: a -> (a,a)
+  properFractionE = Math.sc3_properFraction
+  truncateE :: a -> a
+  truncateE = Math.sc3_truncate
+  roundE :: a -> a
+  roundE = Math.sc3_round
+  ceilingE :: a -> a
+  ceilingE = Math.sc3_ceiling
+  floorE :: a -> a
+  floorE = Math.sc3_floor
+
+instance RealFracE Float
+instance RealFracE Double
+
+-- | Unary operator class.
+--
+-- > map (floor . (* 1e4) . dbAmp) [-90,-60,-30,0] == [0,10,316,10000]
+class (Floating a, Ord a) => UnaryOp a where
+    ampDb :: a -> a
+    ampDb = Math.amp_to_db
+    asFloat :: a -> a
+    asFloat = error "asFloat"
+    asInt :: a -> a
+    asInt = error "asInt"
+    cpsMIDI :: a -> a
+    cpsMIDI = Math.cps_to_midi
+    cpsOct :: a -> a
+    cpsOct = Math.cps_to_oct
+    cubed :: a -> a
+    cubed n = n * n * n
+    dbAmp :: a -> a
+    dbAmp = Math.db_to_amp
+    distort :: a -> a
+    distort = Math.sc3_distort
+    frac :: a -> a
+    frac = error "frac"
+    isNil :: a -> a
+    isNil a = if a == 0.0 then 0.0 else 1.0
+    log10 :: a -> a
+    log10 = logBase 10
+    log2 :: a -> a
+    log2 = logBase 2
+    midiCPS :: a -> a
+    midiCPS = Math.midi_to_cps
+    midiRatio :: a -> a
+    midiRatio = Math.midi_to_ratio
+    notE :: a -> a
+    notE a = if a > 0.0 then 0.0 else 1.0
+    notNil :: a -> a
+    notNil a = if a /= 0.0 then 0.0 else 1.0
+    octCPS :: a -> a
+    octCPS = Math.oct_to_cps
+    ramp_ :: a -> a
+    ramp_ _ = error "ramp_"
+    ratioMIDI :: a -> a
+    ratioMIDI = Math.ratio_to_midi
+    softClip :: a -> a
+    softClip = Math.sc3_softclip
+    squared :: a -> a
+    squared = \z -> z * z
+
+instance UnaryOp Float where
+instance UnaryOp Double where
+
+-- | SC3_Binary_Op operator class.
+class (Floating a,RealFrac a, Ord a) => BinaryOp a where
+    absDif :: a -> a -> a
+    absDif a b = abs (a - b)
+    amClip :: a -> a -> a
+    amClip a b = if b <= 0 then 0 else a * b
+    atan2E :: a -> a -> a
+    atan2E a b = atan (b/a)
+    clip2 :: a -> a -> a
+    clip2 a b = Math.sc3_clip a (-b) b
+    difSqr :: a -> a -> a
+    difSqr = Math.sc3_dif_sqr
+    excess :: a -> a -> a
+    excess a b = a - Math.sc3_clip a (-b) b
+    exprandRange :: a -> a -> a
+    exprandRange = error "exprandRange"
+    fill :: a -> a -> a
+    fill = error "fill"
+    firstArg :: a -> a -> a
+    firstArg a _ = a
+    fold2 :: a -> a -> a
+    fold2 a b = Math.sc3_fold a (-b) b
+    gcdE :: a -> a -> a
+    gcdE = error "gcdE"
+    hypot :: a -> a -> a
+    hypot = Math.sc3_hypot
+    hypotx :: a -> a -> a
+    hypotx = Math.sc3_hypotx
+    iDiv :: a -> a -> a
+    iDiv = Math.sc3_idiv
+    lcmE :: a -> a -> a
+    lcmE = error "lcmE"
+    modE :: a -> a -> a
+    modE = error "modE"
+    randRange :: a -> a -> a
+    randRange = error "randRange"
+    ring1 :: a -> a -> a
+    ring1 a b = a * b + a
+    ring2 :: a -> a -> a
+    ring2 a b = a * b + a + b
+    ring3 :: a -> a -> a
+    ring3 a b = a * a * b
+    ring4 :: a -> a -> a
+    ring4 a b = a * a * b - a * b * b
+    roundUp :: a -> a -> a
+    roundUp = error "roundUp"
+    scaleNeg :: a -> a -> a
+    scaleNeg a b = (abs a - a) * b' + a where b' = 0.5 * b + 0.5
+    sqrDif :: a -> a -> a
+    sqrDif a b = (a-b) * (a-b)
+    sqrSum :: a -> a -> a
+    sqrSum a b = (a+b) * (a+b)
+    sumSqr :: a -> a -> a
+    sumSqr a b = (a*a) + (b*b)
+    thresh :: a -> a -> a
+    thresh a b = if a <  b then 0 else a
+    trunc :: a -> a -> a
+    trunc = error "trunc"
+    wrap2 :: a -> a -> a
+    wrap2 = error "wrap2"
+
+instance BinaryOp Float where
+    fold2 a b = Math.sc3_fold a (-b) b
+    modE = F.mod'
+    roundUp a b = if b == 0 then a else ceilingE (a/b + 0.5) * b
+    wrap2 a b = Math.sc3_wrap_ni a (-b) b
+
+instance BinaryOp Double where
+    fold2 a b = Math.sc3_fold a (-b) b
+    modE = F.mod'
+    roundUp a b = if b == 0 then a else ceilingE (a/b + 0.5) * b
+    wrap2 a b = Math.sc3_wrap_ni a (-b) b
+
+-- * Infix
+
+(==**) :: EqE a => a -> a -> a
+(==**) = equal_to
+
+(/=**) :: EqE a => a -> a -> a
+(/=**) = not_equal_to
+
+(<**) :: OrdE a => a -> a -> a
+(<**) = less_than
+
+(<=**) :: OrdE a => a -> a -> a
+(<=**) = less_than_or_equal_to
+
+(>**) :: OrdE a => a -> a -> a
+(>**) = greater_than
+
+(>=**) :: OrdE a => a -> a -> a
+(>=**) = greater_than_or_equal_to
+
+-- * Tables
+
+-- | Association table for 'SC3_Binary_Op' to haskell function implementing operator.
+binop_hs_tbl :: (Real n,Floating n,RealFrac n) => [(SC3_Binary_Op,n -> n -> n)]
+binop_hs_tbl =
+    [(Add,(+))
+    ,(Sub,(-))
+    ,(FDiv,(/))
+    ,(IDiv,Math.sc3_idiv)
+    ,(Mod,Math.sc3_mod)
+    ,(EQ_,Math.sc3_eq)
+    ,(NE,Math.sc3_neq)
+    ,(LT_,Math.sc3_lt)
+    ,(LE,Math.sc3_lte)
+    ,(GT_,Math.sc3_gt)
+    ,(GE,Math.sc3_gte)
+    ,(Min,min)
+    ,(Max,max)
+    ,(Mul,(*))
+    ,(Pow,(**))
+    ,(Min,min)
+    ,(Max,max)
+    ,(Round,Math.sc3_round_to)]
+
+-- | 'lookup' 'binop_hs_tbl' via 'toEnum'.
+binop_special_hs :: (RealFrac n,Floating n) => Int -> Maybe (n -> n -> n)
+binop_special_hs z = lookup (toEnum z) binop_hs_tbl
+
+-- | Association table for 'Unary' to haskell function implementing operator.
+uop_hs_tbl :: (RealFrac n,Floating n) => [(SC3_Unary_Op,n -> n)]
+uop_hs_tbl =
+    [(Neg,negate)
+    ,(Not,\z -> if z > 0 then 0 else 1)
+    ,(Abs,abs)
+    ,(Ceil,Math.sc3_ceiling)
+    ,(Floor,Math.sc3_floor)
+    ,(Squared,\z -> z * z)
+    ,(Cubed,\z -> z * z * z)
+    ,(Sqrt,sqrt)
+    ,(Recip,recip)
+    ,(MIDICPS,Math.midi_to_cps)
+    ,(CPSMIDI,Math.cps_to_midi)
+    ,(Sin,sin)
+    ,(Cos,cos)
+    ,(Tan,tan)]
+
+-- | 'lookup' 'uop_hs_tbl' via 'toEnum'.
+uop_special_hs :: (RealFrac n,Floating n) => Int -> Maybe (n -> n)
+uop_special_hs z = lookup (toEnum z) uop_hs_tbl
diff --git a/Sound/SC3/Common/Rate.hs b/Sound/SC3/Common/Rate.hs
new file mode 100644
--- /dev/null
+++ b/Sound/SC3/Common/Rate.hs
@@ -0,0 +1,60 @@
+-- | Operating rate definitions and utilities.
+module Sound.SC3.Common.Rate where
+
+import Data.Char {- base -}
+
+-- | Operating rate of unit generator.
+--   I = initialisation, K = control, A = audio, D = demand.
+--
+-- > Data.List.sort [DR,AR,KR,IR] == [IR,KR,AR,DR]
+data Rate = IR | KR | AR | DR
+            deriving (Eq,Ord,Enum,Bounded,Show,Read)
+
+-- | Integer rate identifier, as required for scsynth bytecode.
+rateId :: Rate -> Int
+rateId = fromEnum
+
+-- | Color identifiers for each 'Rate'.
+rate_color :: Rate -> String
+rate_color r =
+    case r of
+      AR -> "black"
+      KR -> "blue"
+      IR -> "yellow"
+      DR -> "red"
+
+-- | Set of all 'Rate' values.
+all_rates :: [Rate]
+all_rates = [minBound .. maxBound]
+
+-- | Case insensitive parser for rate.
+--
+-- > Data.Maybe.mapMaybe rate_parse (words "ar kR IR Dr") == [AR,KR,IR,DR]
+rate_parse :: String -> Maybe Rate
+rate_parse r =
+    case map toUpper r of
+      "AR" -> Just AR
+      "KR" -> Just KR
+      "IR" -> Just IR
+      "DR" -> Just DR
+      _ -> Nothing
+
+-- * Control rates
+
+-- | Enumeration of the four operating rates for controls.
+--   I = initialisation, K = control, T = trigger, A = audio.
+data K_Type = K_IR | K_KR | K_TR | K_AR
+             deriving (Eq,Show,Ord)
+
+-- | Determine class of control given 'Rate' and /trigger/ status.
+ktype :: Rate -> Bool -> K_Type
+ktype r tr =
+    if tr
+    then case r of
+           KR -> K_TR
+           _ -> error "ktype: non KR trigger control"
+    else case r of
+           IR -> K_IR
+           KR -> K_KR
+           AR -> K_AR
+           DR -> error "ktype: DR control"
diff --git a/Sound/SC3/Common/UId.hs b/Sound/SC3/Common/UId.hs
--- a/Sound/SC3/Common/UId.hs
+++ b/Sound/SC3/Common/UId.hs
@@ -9,6 +9,7 @@
 import Data.List {- base -}
 import qualified Data.Unique as Unique {- base -}
 
+--import qualified Control.Monad.Trans.Identity as Identity {- transformers -}
 import qualified Control.Monad.Trans.Reader as Reader {- transformers -}
 import qualified Control.Monad.Trans.State as State {- transformers -}
 import qualified Data.Digest.Murmur32 as Murmur32 {- hashable -}
@@ -40,6 +41,10 @@
 -- | 'State.State' UId.
 type UId_ST = State.State Int
 
+-- | Alias for 'runIdentity'.
+uid_id_eval :: Identity t -> t
+uid_id_eval = runIdentity
+
 -- | 'State.evalState' with initial state of zero.
 --
 -- > uid_st_eval (replicateM 3 generateUId) == [0,1,2]
@@ -103,6 +108,6 @@
 
 -- | /n/ identifiers from /x/.
 --
--- > id_seq 10 'α' == [945 .. 954]
+-- > id_seq 10 'α' == [1439603815 .. 1439603824]
 id_seq :: ID a => Int -> a -> [Id]
 id_seq n x = take n [resolveID x ..]
diff --git a/Sound/SC3/Server.hs b/Sound/SC3/Server.hs
--- a/Sound/SC3/Server.hs
+++ b/Sound/SC3/Server.hs
@@ -9,4 +9,5 @@
 import Sound.SC3.Server.Status as S
 import Sound.SC3.Server.NRT as S
 import Sound.SC3.Server.NRT.Edit as S
+import Sound.SC3.Server.Param as S
 import Sound.SC3.Server.Recorder as S
diff --git a/Sound/SC3/Server/Command/Generic.hs b/Sound/SC3/Server/Command/Generic.hs
--- a/Sound/SC3/Server/Command/Generic.hs
+++ b/Sound/SC3/Server/Command/Generic.hs
@@ -12,35 +12,54 @@
 import qualified Sound.SC3.Server.Graphdef as G
 import qualified Sound.SC3.Server.Synthdef as S
 
+cmd_check_arg :: String -> (t -> Bool) -> t -> t
+cmd_check_arg e f x = if not (f x) then error e else x
+
 -- * Buffer commands (b_)
 
+-- | BUF-NUM must be >= 0
+b_bufnum :: Integral t => t -> Datum
+b_bufnum = int32 . cmd_check_arg "buffer-number < 0?" (>= 0)
+
+-- | BUF-FRAME-IX must be >= 0
+b_ix :: Integral t => t -> Datum
+b_ix = int32 . cmd_check_arg "buffer-ix < 0?" (>= 0)
+
+-- | BUF-CHANNEL must be >= 0
+b_ch :: Integral t => t -> Datum
+b_ch = int32 . cmd_check_arg "buffer-channel < 0?" (>= 0)
+
+-- | BUF-FRAME-CNT must be >= 0
+b_size :: Integral t => t -> Datum
+b_size = int32 . cmd_check_arg "buffer-size < 0?" (>= 0)
+
 -- | Allocates zero filled buffer to number of channels and samples. (Asynchronous)
 b_alloc :: Integral i => i -> i -> i -> Message
-b_alloc nid frames channels = message "/b_alloc" [int32 nid,int32 frames,int32 channels]
+b_alloc b frames channels = message "/b_alloc" [b_bufnum b,b_size frames,int32 channels]
 
 -- | Allocate buffer space and read a sound file. (Asynchronous)
 b_allocRead :: Integral i => i -> String -> i -> i -> Message
-b_allocRead nid p f n = message "/b_allocRead" [int32 nid,string p,int32 f,int32 n]
+b_allocRead b p f n = message "/b_allocRead" [b_bufnum b,string p,b_ix f,b_ix n]
 
 -- | Allocate buffer space and read a sound file, picking specific channels. (Asynchronous)
 b_allocReadChannel :: Integral i => i -> String -> i -> i -> [i] -> Message
-b_allocReadChannel nid p f n cs = message "/b_allocReadChannel" ([int32 nid,string p,int32 f,int32 n] ++ map int32 cs)
+b_allocReadChannel b p f n cs = message "/b_allocReadChannel" ([b_bufnum b,string p,b_ix f,b_ix n] ++ map b_ch cs)
 
 -- | Close attached soundfile and write header information. (Asynchronous)
 b_close :: Integral i => i -> Message
-b_close nid = message "/b_close" [int32 nid]
+b_close b = message "/b_close" [b_bufnum b]
 
 -- | Fill ranges of sample values.
 b_fill :: (Integral i,Real n) => i -> [(i,i,n)] -> Message
-b_fill nid l = message "/b_fill" (int32 nid : B.mk_triples int32 int32 float l)
+b_fill b l = message "/b_fill" (b_bufnum b : B.mk_triples int32 int32 float l)
 
 -- | Free buffer data. (Asynchronous)
 b_free :: Integral i => i -> Message
-b_free nid = message "/b_free" [int32 nid]
+b_free b = message "/b_free" [b_bufnum b]
 
 -- | Call a command to fill a buffer.  (Asynchronous)
 b_gen :: Integral i => i -> String -> [Datum] -> Message
-b_gen bid name arg = message "/b_gen" (int32 bid : string name : arg)
+b_gen b name arg = message "/b_gen" (b_bufnum b : string name : arg)
 
 -- | Call @sine1@ 'b_gen' command.
 b_gen_sine1 :: (Integral i,Real n) => i -> [E.B_Gen] -> [n] -> Message
@@ -66,11 +85,11 @@
 
 -- | Get sample values.
 b_get :: Integral i => i -> [i] -> Message
-b_get nid i = message "/b_get" (int32 nid : map int32 i)
+b_get b i = message "/b_get" (b_bufnum b : map int32 i)
 
 -- | Get ranges of sample values.
 b_getn :: Integral i => i -> [(i,i)] -> Message
-b_getn nid l = message "/b_getn" (int32 nid : B.mk_duples int32 int32 l)
+b_getn b l = message "/b_getn" (b_bufnum b : B.mk_duples b_ix b_size l)
 
 -- | Request \/b_info messages.
 b_query :: Integral i => [i] -> Message
@@ -78,32 +97,32 @@
 
 -- | Read sound file data into an existing buffer. (Asynchronous)
 b_read :: Integral i => i -> String -> i -> i -> i -> Bool -> Message
-b_read nid p f n f' z = message "/b_read" [int32 nid,string p,int32 f,int32 n,int32 f',int32 (fromEnum z)]
+b_read b p f n f' z = message "/b_read" [b_bufnum b,string p,int32 f,int32 n,int32 f',int32 (fromEnum z)]
 
 -- | Read sound file data into an existing buffer, picking specific channels. (Asynchronous)
 b_readChannel :: Integral i => i -> String -> i -> i -> i -> Bool -> [i] -> Message
-b_readChannel nid p f n f' z cs = message "/b_readChannel" ([int32 nid,string p,int32 f,int32 n,int32 f',int32 (fromEnum z)] ++ map int32 cs)
+b_readChannel b p f n f' z cs = message "/b_readChannel" ([b_bufnum b,string p,int32 f,int32 n,int32 f',int32 (fromEnum z)] ++ map int32 cs)
 
 -- | Set sample values.
 b_set :: (Integral i,Real n) => i -> [(i,n)] -> Message
-b_set nid l = message "/b_set" (int32 nid : B.mk_duples int32 float l)
+b_set b l = message "/b_set" (b_bufnum b : B.mk_duples int32 float l)
 
 -- | Set ranges of sample values.
 b_setn :: (Integral i,Real n) => i -> [(i,[n])] -> Message
-b_setn nid l =
+b_setn b l =
     let f (i,d) = int32 i : int32 (length d) : map float d
-    in message "/b_setn" (int32 nid : concatMap f l)
+    in message "/b_setn" (b_bufnum b : concatMap f l)
 
 -- | Write sound file data. (Asynchronous)
 b_write :: Integral i => i -> String -> E.SoundFileFormat -> E.SampleFormat -> i -> i -> Bool -> Message
-b_write nid p h t f s z =
+b_write b p h t f s z =
     let h' = string (E.soundFileFormatString h)
         t' = string (E.sampleFormatString t)
-    in message "/b_write" [int32 nid,string p,h',t',int32 f,int32 s,int32 (fromEnum z)]
+    in message "/b_write" [b_bufnum b,string p,h',t',int32 f,int32 s,int32 (fromEnum z)]
 
 -- | Zero sample data. (Asynchronous)
 b_zero :: Integral i => i -> Message
-b_zero nid = message "/b_zero" [int32 nid]
+b_zero b = message "/b_zero" [b_bufnum b]
 
 -- * Control bus commands (c_)
 
@@ -132,12 +151,16 @@
 -- * Instrument definition commands (d_)
 
 -- | Install a bytecode instrument definition. (Asynchronous)
-d_recv' :: G.Graphdef -> Message
-d_recv' g = message "/d_recv" [Blob (G.encode_graphdef g)]
+d_recv_bytes :: BLOB -> Message
+d_recv_bytes b = message "/d_recv" [Blob b]
 
--- | Install a bytecode instrument definition. (Asynchronous)
+-- | 'G.Graphdef' encoding variant.
+d_recv_gr :: G.Graphdef -> Message
+d_recv_gr = d_recv_bytes . G.encode_graphdef
+
+-- | 'S.Synthdef' encoding variant.
 d_recv :: S.Synthdef -> Message
-d_recv d = message "/d_recv" [Blob (S.synthdefData d)]
+d_recv = d_recv_bytes . S.synthdefData
 
 -- | Load an instrument definition from a named file. (Asynchronous)
 d_load :: String -> Message
@@ -207,9 +230,13 @@
 
 -- * Node commands (n_)
 
+-- | NODE-ID must be >= -1
+n_id :: Integral t => t -> Datum
+n_id = int32 . cmd_check_arg "node-id < -1?" (>= (-1))
+
 -- | Place a node after another.
 n_after :: Integral i => [(i,i)] -> Message
-n_after = message "/n_after" . B.mk_duples int32 int32
+n_after = message "/n_after" . B.mk_duples n_id n_id
 
 -- | Place a node before another.
 n_before :: Integral i => [(i,i)] -> Message
@@ -217,46 +244,46 @@
 
 -- | Fill ranges of a node's control values.
 n_fill :: (Integral i,Real f) => i -> [(String,i,f)] -> Message
-n_fill nid l = message "/n_fill" (int32 nid : B.mk_triples string int32 float l)
+n_fill n l = message "/n_fill" (n_id n : B.mk_triples string int32 float l)
 
 -- | Delete a node.
 n_free :: Integral i => [i] -> Message
-n_free = message "/n_free" . map int32
+n_free = message "/n_free" . map n_id
 
 n_map :: Integral i => i -> [(String,i)] -> Message
-n_map nid l = message "/n_map" (int32 nid : B.mk_duples string int32 l)
+n_map n l = message "/n_map" (n_id n : B.mk_duples string int32 l)
 
 -- | Map a node's controls to read from buses.
 --   n_mapn only works if the control is given as an index and not as a name (3.8.0).
 n_mapn :: Integral i => i -> [(i,i,i)] -> Message
-n_mapn nid l = message "/n_mapn" (int32 nid : B.mk_triples int32 int32 int32 l)
+n_mapn n l = message "/n_mapn" (n_id n : B.mk_triples int32 int32 int32 l)
 
 -- | Map a node's controls to read from an audio bus.
 n_mapa :: Integral i => i -> [(String,i)] -> Message
-n_mapa nid l = message "/n_mapa" (int32 nid : B.mk_duples string int32 l)
+n_mapa n l = message "/n_mapa" (n_id n : B.mk_duples string int32 l)
 
 -- | Map a node's controls to read from audio buses.
 n_mapan :: Integral i => i -> [(String,i,i)] -> Message
-n_mapan nid l = message "/n_mapan" (int32 nid : B.mk_triples string int32 int32 l)
+n_mapan n l = message "/n_mapan" (n_id n : B.mk_triples string int32 int32 l)
 
 -- | Get info about a node.
 n_query :: Integral i => [i] -> Message
-n_query = message "/n_query" . map int32
+n_query = message "/n_query" . map n_id
 
 -- | Turn node on or off.
 n_run :: Integral i => [(i,Bool)] -> Message
-n_run = message "/n_run" . B.mk_duples int32 (int32 . fromEnum)
+n_run = message "/n_run" . B.mk_duples n_id (int32 . fromEnum)
 
 -- | Set a node's control values.
 n_set :: (Integral i,Real n) => i -> [(String,n)] -> Message
-n_set nid c = message "/n_set" (int32 nid : B.mk_duples string float c)
+n_set n c = message "/n_set" (n_id n : B.mk_duples string float c)
 
 -- | Set ranges of a node's control values.
 -- n_mapn and n_setn only work if the control is given as an index and not as a name.
 n_setn :: (Integral i,Real n) => i -> [(i,[n])] -> Message
-n_setn nid l =
+n_setn n l =
     let f (s,d) = int32 s : int32 (length d) : map float d
-    in message "/n_setn" (int32 nid : concatMap f l)
+    in message "/n_setn" (n_id n : concatMap f l)
 
 -- | Trace a node.
 n_trace :: Integral i => [i] -> Message
@@ -276,11 +303,11 @@
 
 -- | Get control values.
 s_get :: Integral i => i -> [String] -> Message
-s_get nid i = message "/s_get" (int32 nid : map string i)
+s_get n i = message "/s_get" (n_id n : map string i)
 
 -- | Get ranges of control values.
 s_getn :: Integral i => i -> [(String,i)] -> Message
-s_getn nid l = message "/s_getn" (int32 nid : B.mk_duples string int32 l)
+s_getn n l = message "/s_getn" (n_id n : B.mk_duples string int32 l)
 
 -- | Create a new synth.
 s_new :: (Integral i,Real n) => String -> i -> E.AddAction -> i -> [(String,n)] -> Message
@@ -294,7 +321,7 @@
 
 -- | Send a command to a unit generator.
 u_cmd :: Integral i => i -> i -> String -> [Datum] -> Message
-u_cmd nid uid name arg = message "/u_cmd" ([int32 nid,int32 uid,string name] ++ arg)
+u_cmd n uid name arg = message "/u_cmd" ([n_id n,int32 uid,string name] ++ arg)
 
 -- * Server operation commands
 
@@ -360,14 +387,14 @@
 
 -- | Pre-allocate for b_setn1, values preceding offset are zeroed.
 b_alloc_setn1 :: (Integral i,Real n) => i -> i -> [n] -> Message
-b_alloc_setn1 nid i xs =
+b_alloc_setn1 b i xs =
     let k = i + genericLength xs
         xs' = genericReplicate i 0 ++ xs
-    in withCM (b_alloc nid k 1) (b_setn1 nid 0 xs')
+    in withCM (b_alloc b k 1) (b_setn1 b 0 xs')
 
 -- | Get ranges of sample values.
 b_getn1 :: Integral i => i -> (i,i) -> Message
-b_getn1 nid = b_getn nid . return
+b_getn1 b = b_getn b . return
 
 -- | Variant on 'b_query'.
 b_query1 :: Integral i => i -> Message
@@ -375,11 +402,11 @@
 
 -- | Set single sample value.
 b_set1 :: (Integral i,Real n) => i -> i -> n -> Message
-b_set1 nid i x = b_set nid [(i,x)]
+b_set1 b i x = b_set b [(i,x)]
 
 -- | Set a range of sample values.
 b_setn1 :: (Integral i,Real n) => i -> i -> [n] -> Message
-b_setn1 nid i xs = b_setn nid [(i,xs)]
+b_setn1 b i xs = b_setn b [(i,xs)]
 
 -- | Segmented variant of 'b_setn1'.
 b_setn1_segmented :: (Integral i,Real n) => i -> i -> i -> [n] -> [Message]
@@ -402,11 +429,11 @@
 
 -- | Turn a single node on or off.
 n_run1 :: Integral i => i -> Bool -> Message
-n_run1 nid k = n_run [(nid,k)]
+n_run1 n k = n_run [(n,k)]
 
 -- | Set a single node control value.
 n_set1 :: (Integral i,Real n) => i -> String -> n -> Message
-n_set1 nid k n = n_set nid [(k,n)]
+n_set1 n k v = n_set n [(k,v)]
 
 -- | @s_new@ with no parameters.
 s_new0 :: Integral i => String -> i -> E.AddAction -> i -> Message
diff --git a/Sound/SC3/Server/Command/Plain.hs b/Sound/SC3/Server/Command/Plain.hs
--- a/Sound/SC3/Server/Command/Plain.hs
+++ b/Sound/SC3/Server/Command/Plain.hs
@@ -1,7 +1,7 @@
 -- | Functions from "Sound.SC3.Server.Command.Generic" specialised to 'Int' and 'Double'.
 module Sound.SC3.Server.Command.Plain where
 
-import Sound.OSC.Core (Datum,Message) {- hosc -}
+import Sound.OSC.Core (BLOB,Datum,Message) {- hosc -}
 
 import qualified Sound.SC3.Server.Command.Generic as G
 import qualified Sound.SC3.Server.Enum as E
@@ -122,10 +122,14 @@
 -- * Instrument definition commands (d_)
 
 -- | Install a bytecode instrument definition. (Asynchronous)
-d_recv' :: Graphdef -> Message
-d_recv' = G.d_recv'
+d_recv_bytes :: BLOB -> Message
+d_recv_bytes = G.d_recv_bytes
 
--- | Install a bytecode instrument definition. (Asynchronous)
+-- | 'Graphdef' encoding variant.
+d_recv_gr :: Graphdef -> Message
+d_recv_gr = G.d_recv_gr
+
+-- | 'Synthdef' encoding variant.
 d_recv :: Synthdef -> Message
 d_recv = G.d_recv
 
diff --git a/Sound/SC3/Server/Graphdef.hs b/Sound/SC3/Server/Graphdef.hs
--- a/Sound/SC3/Server/Graphdef.hs
+++ b/Sound/SC3/Server/Graphdef.hs
@@ -5,6 +5,8 @@
 import Control.Monad {- base -}
 import qualified Data.ByteString.Lazy as L {- bytestring -}
 import Data.List {- base -}
+import qualified Safe {- safe -}
+import System.FilePath {- filepath -}
 import System.IO {- base -}
 
 import qualified Sound.OSC.Coding.Byte as Byte {- hosc -}
@@ -75,11 +77,11 @@
 
 -- | Lookup UGen by index.
 graphdef_ugen :: Graphdef -> Int -> UGen
-graphdef_ugen g = (graphdef_ugens g !!)
+graphdef_ugen g = Safe.atNote "graphdef_ugen" (graphdef_ugens g)
 
 -- | Lookup Control and default value by index.
 graphdef_control :: Graphdef -> Int -> (Control,Sample)
-graphdef_control g = (graphdef_controls g !!)
+graphdef_control g = Safe.atNote "graphdef_controls" (graphdef_controls g)
 
 -- | nid of constant.
 graphdef_constant_nid :: Graphdef -> Int -> Int
@@ -136,7 +138,7 @@
 -- | Read a 'Graphdef'. Ignores variants.
 read_graphdef :: Handle -> IO Graphdef
 read_graphdef h = do
-  magic <- fmap Byte.decode_str (L.hGet h 4)
+  magic <- fmap Byte.decode_ascii (L.hGet h 4)
   version <- Byte.read_i32 h
   let read_i =
           case version of
@@ -162,7 +164,7 @@
                    (zip controls control_defaults)
                    ugens)
 
-{- | Read Graphdef from file.
+{- | Read Graphdef from .scsyndef file.
 
 > dir = "/home/rohan/sw/rsc3-disassembler/scsyndef/"
 > pp nm = read_graphdef_file (dir ++ nm) >>= putStrLn . graphdef_stat
@@ -179,6 +181,12 @@
   hClose h
   return g
 
+-- | Read scsyndef file and run 'graphdef_stat'.
+scsyndef_stat :: FilePath -> IO String
+scsyndef_stat fn = do
+  g <- read_graphdef_file fn
+  return (graphdef_stat g)
+
 -- * Encode (version zero)
 
 -- | Pascal (length prefixed) encoding of string.
@@ -212,7 +220,7 @@
 encode_graphdef :: Graphdef -> L.ByteString
 encode_graphdef (Graphdef nm cs ks us) =
     let (ks_ctl,ks_def) = unzip ks
-    in L.concat [Byte.encode_str (Datum.ascii "SCgf")
+    in L.concat [Byte.encode_ascii (Datum.ascii "SCgf")
                 ,Byte.encode_i32 0 -- version
                 ,Byte.encode_i16 1 -- number of graphs
                 ,encode_pstr nm
@@ -224,6 +232,19 @@
                 ,L.concat (map encode_control ks_ctl)
                 ,Byte.encode_i16 (length us)
                 ,L.concat (map encode_ugen us)]
+
+-- * IO
+
+-- | Write 'Graphdef' to indicated file.
+graphdefWrite :: FilePath -> Graphdef -> IO ()
+graphdefWrite fn = L.writeFile fn . encode_graphdef
+
+-- | Write 'Graphdef' to indicated directory.  The filename is the
+-- 'graphdef_name' with the appropriate extension (@scsyndef@).
+graphdefWrite_dir :: FilePath -> Graphdef -> IO ()
+graphdefWrite_dir dir s =
+    let fn = dir </> Datum.ascii_to_string (graphdef_name s) <.> "scsyndef"
+    in graphdefWrite fn s
 
 -- * Stat
 
diff --git a/Sound/SC3/Server/Graphdef/Graph.hs b/Sound/SC3/Server/Graphdef/Graph.hs
--- a/Sound/SC3/Server/Graphdef/Graph.hs
+++ b/Sound/SC3/Server/Graphdef/Graph.hs
@@ -6,8 +6,8 @@
 
 import qualified Sound.OSC.Datum as Datum {- hosc -}
 
+import qualified Sound.SC3.Common.Rate as Rate
 import qualified Sound.SC3.UGen.Graph as Graph
-import qualified Sound.SC3.UGen.Rate as Rate
 import qualified Sound.SC3.UGen.Type as Type
 import qualified Sound.SC3.Server.Graphdef as Graphdef
 
diff --git a/Sound/SC3/Server/Graphdef/Read.hs b/Sound/SC3/Server/Graphdef/Read.hs
--- a/Sound/SC3/Server/Graphdef/Read.hs
+++ b/Sound/SC3/Server/Graphdef/Read.hs
@@ -3,9 +3,9 @@
 
 import Sound.OSC.Datum {- hosc -}
 
-import Sound.SC3.Server.Graphdef
+import qualified Sound.SC3.Common.Rate as Rate
+import           Sound.SC3.Server.Graphdef as Graphdef
 import qualified Sound.SC3.UGen.Graph as Graph
-import qualified Sound.SC3.UGen.Rate as Rate
 import qualified Sound.SC3.UGen.Type as Type
 
 control_to_node :: Graphdef -> Type.UID_t -> (Control,Type.Sample) -> Graph.U_Node
@@ -47,3 +47,16 @@
         nm = ascii_to_string (graphdef_name g)
         gr = Graph.U_Graph (-1) constants_nd controls_nd ugens_nd
     in (nm,gr) -- S.Synthdef nm gr
+
+-- | Read graphdef file and translate to graph.
+read_graph :: FilePath -> IO Graph.U_Graph
+read_graph sy_nm = do
+  d <- Graphdef.read_graphdef_file sy_nm
+  let (_,g) = graphdef_to_graph d
+  return g
+
+-- | Read graphdef file, translate to graph, and run 'ug_stat_ln'.
+scsyndef_ug_stat :: FilePath -> IO String
+scsyndef_ug_stat sy_nm = do
+  g <- read_graph sy_nm
+  return (unlines (Graph.ug_stat_ln g))
diff --git a/Sound/SC3/Server/Help.hs b/Sound/SC3/Server/Help.hs
deleted file mode 100644
--- a/Sound/SC3/Server/Help.hs
+++ /dev/null
@@ -1,35 +0,0 @@
--- | Functions to provide mediated access to the SC3 help system.
-module Sound.SC3.Server.Help where
-
-import Control.Monad {- base -}
-import System.FilePath {- filepath -}
-import System.Process {- process -}
-
-import qualified Sound.SC3.UGen.Help as Help
-
-{- | Generate path to indicated SC3 instance method help.  Adds initial
-forward slash if not present.
-
-> let r = "./Reference/Server-Command-Reference.html#/b_alloc"
-> sc3_server_command_ref "." "b_alloc" == r
-
--}
-sc3_server_command_ref :: FilePath -> String -> FilePath
-sc3_server_command_ref d c =
-    let f = d </> "Reference/Server-Command-Reference.html"
-        c' = case c of
-               '/':_ -> c
-               _ -> '/':c
-    in f ++ '#':c'
-
-{- | Lookup @SC3@ help file for server command `c'.
-
-> Sound.SC3.Server.Help.viewServerHelp "/b_allocRead"
-> viewServerHelp "done"
--}
-viewServerHelp :: String -> IO ()
-viewServerHelp c = do
-  d <- Help.sc3HelpDirectory
-  let nm = sc3_server_command_ref d c
-  br <- Help.get_env_default "BROWSER" "x-www-browser"
-  void (rawSystem br ["file://" ++ nm])
diff --git a/Sound/SC3/Server/NRT.hs b/Sound/SC3/Server/NRT.hs
--- a/Sound/SC3/Server/NRT.hs
+++ b/Sound/SC3/Server/NRT.hs
@@ -1,11 +1,13 @@
 -- | Non-realtime score generation.
 module Sound.SC3.Server.NRT where
 
-import qualified Data.ByteString.Lazy as B {- bytestring -}
+import Data.Maybe {- base -}
 import System.FilePath {- filepath -}
 import System.IO {- base -}
 import System.Process {- process -}
 
+import qualified Data.ByteString.Lazy as B {- bytestring -}
+
 import Sound.OSC.Core {- hosc -}
 import qualified Sound.OSC.Coding.Byte as Byte {- hosc -}
 
@@ -145,6 +147,8 @@
   nrt_exec_plain opt
 
 -- | Variant for no input case.
+--
+-- (osc-file-name,audio-file-name,number-of-channels,sample-rate,sample-format,param)
 type NRT_Render_Plain = (FilePath,FilePath,Int,Int,SampleFormat,[String])
 
 {- | Add ("-",0) as input parameters and run 'nrt_proc_plain'.
@@ -156,3 +160,12 @@
 nrt_render_plain (osc_nm,sf_nm,nc,sr,sf,param) sc =
   let opt = (osc_nm,("_",0),(sf_nm,nc),sr,sf,param)
   in nrt_proc_plain opt sc
+
+-- * QUERY
+
+-- | Find any non-ascending sequences.
+nrt_non_ascending :: NRT -> [(Bundle, Bundle)]
+nrt_non_ascending (NRT b) =
+  let p = zip b (tail b)
+      f (i,j) = if bundleTime i > bundleTime j then Just (i,j) else Nothing
+  in mapMaybe f p
diff --git a/Sound/SC3/Server/NRT/UGen.hs b/Sound/SC3/Server/NRT/UGen.hs
new file mode 100644
--- /dev/null
+++ b/Sound/SC3/Server/NRT/UGen.hs
@@ -0,0 +1,33 @@
+-- | NRT / UGen
+module Sound.SC3.Server.NRT.UGen where
+
+import Sound.OSC {- hosc -}
+
+import Sound.SC3.Common.Rate
+import Sound.SC3.Server.Command.Plain
+import Sound.SC3.Server.Enum
+import Sound.SC3.Server.NRT
+import Sound.SC3.Server.Synthdef
+import Sound.SC3.UGen.Bindings.DB
+import Sound.SC3.UGen.Type
+
+-- | Make NRT score that runs /u/ for /dur/ seconds to output bus zero.
+--   If /u/ is at KR insert 'k2a' UGen.
+nrt_ugen_rec :: Time -> UGen -> NRT
+nrt_ugen_rec dur u =
+    let sg = case rateOf u of
+               AR -> u
+               KR -> k2a u
+               _ -> error "nrt_ugen_rec: rate?"
+        sy = synthdef "anonymous" (out 0 sg)
+        m0 = d_recv sy
+        m1 = s_new0 "anonymous" 1 AddToHead 0
+    in NRT [bundle 0 [m0,m1],bundle dur [nrt_end]]
+
+-- | 'nrt_render_plain' of 'ugen_rec_nrt'.
+--   The number of channels is equal to the degree of /u/.
+nrt_ugen_render :: (FilePath, FilePath, Int, SampleFormat, [String]) -> Time -> UGen -> IO ()
+nrt_ugen_render (osc_fn,sf_fn,sample_rate,fmt,opt) dur u = do
+  let sc = nrt_ugen_rec dur u
+      nc = length (mceChannels u)
+  nrt_render_plain (osc_fn,sf_fn,nc,sample_rate,fmt,opt) sc
diff --git a/Sound/SC3/Server/Options.hs b/Sound/SC3/Server/Options.hs
new file mode 100644
--- /dev/null
+++ b/Sound/SC3/Server/Options.hs
@@ -0,0 +1,94 @@
+-- | scsynth server command-line options.
+module Sound.SC3.Server.Options where
+
+import Data.List {- base -}
+
+-- | (SHORT-OPTION,LONG-OPTION,DEFAULT-VALUE)
+type SC3_OPT i = (Char,String,i)
+
+-- | Get value from option.
+sc3_opt_value :: SC3_OPT i -> i
+sc3_opt_value (_,_,v) = v
+
+-- | Default port number, either a 'u' or a 't' option is required.
+sc3_port_def :: Num i => i
+sc3_port_def = 57110
+
+-- | Protocol is either UDP or TCP.
+data SC3_PROTOCOL = SC3_UDP | SC3_TCP
+
+-- | Default port option.
+sc3_opt_port_def :: Num i => SC3_PROTOCOL -> SC3_OPT i
+sc3_opt_port_def p =
+  case p of
+    SC3_UDP -> ('u',"udp-port-number",sc3_port_def)
+    SC3_TCP -> ('t',"tcp-port-number",sc3_port_def)
+
+-- | SC3 default options.
+sc3_opt_def :: Num i => SC3_PROTOCOL -> [SC3_OPT i]
+sc3_opt_def p =
+  sc3_opt_port_def p :
+  [('a',"number-of-audio-bus-channels",1024)
+  ,('b',"number-of-sample-buffers",1024)
+  ,('c',"number-of-control-bus-channels",16384)
+  ,('D',"load-synthdefs?",1)
+  ,('d',"max-number-of-synth-defs",1024)
+  ,('i',"number-of-input-bus-channels",8)
+  ,('l',"max-logins",64)
+  ,('m',"real-time-memory-size",8192)
+  ,('n',"max-number-of-nodes",1024)
+  ,('o',"number-of-output-bus-channels",8)
+  ,('r',"number-of-random-seeds",64)
+  ,('R',"publish-to-rendezvous?",1)
+  ,('S',"hardware-sample-rate",0)
+  ,('V',"verbosity",0)
+  ,('w',"number-of-wire-buffers",64)
+  ,('z',"block-size",64)
+  ,('Z',"hardware-buffer-size",0)]
+
+-- | SC3 default options for UDP.
+sc3_opt_def_udp :: Num i => [SC3_OPT i]
+sc3_opt_def_udp = sc3_opt_def SC3_UDP
+
+-- | Is option boolean, ie. 0=FALSE and 1=TRUE.
+--
+-- > filter sc3_opt_bool sc3_opt_def_udp
+sc3_opt_bool :: SC3_OPT i -> Bool
+sc3_opt_bool (_,s,_) = last s == '?'
+
+-- | Lookup option given either short or long name.
+sc3_opt_get :: [SC3_OPT i] -> Either Char String -> Maybe i
+sc3_opt_get opt k =
+  case k of
+    Left c -> fmap sc3_opt_value (find (\(o,_,_) -> o == c) opt)
+    Right s -> fmap sc3_opt_value (find (\(_,o,_) -> o == s) opt)
+
+-- | Set option given either short or long name.
+--
+-- > sc3_opt_set sc3_opt_def_udp (Left 'w',256)
+sc3_opt_set :: [SC3_OPT i] -> (Either Char String,i) -> [SC3_OPT i]
+sc3_opt_set opt (k,v) =
+  case k of
+    Left x -> map (\(c,s,y) -> if c == x then (c,s,v) else (c,s,y)) opt
+    Right x -> map (\(c,s,y) -> if s == x then (c,s,v) else (c,s,y)) opt
+
+-- | Apply set of edits to options.
+--
+-- > sc3_opt_edit sc3_opt_def_udp [(Left 'w',256),(Left 'm',2 ^ 16)]
+sc3_opt_edit :: [SC3_OPT i] -> [(Either Char String,i)] -> [SC3_OPT i]
+sc3_opt_edit opt edt =
+  case edt of
+    [] -> opt
+    x:rst -> sc3_opt_edit (sc3_opt_set opt x) rst
+
+-- | Generate scsynth argument list.
+--
+-- > unwords (sc3_opt_arg sc3_opt_def_udp)
+sc3_opt_arg :: Show i => [SC3_OPT i] -> [String]
+sc3_opt_arg = concatMap (\(c,_,v) -> [['-',c],show v])
+
+-- | Generate arguments for 'System.Process.callProcess' or related functions.
+--
+-- > sc3_opt_cmd sc3_opt_def_udp
+sc3_opt_cmd :: Show i => [SC3_OPT i] -> (FilePath,[String])
+sc3_opt_cmd opt = ("scsynth",sc3_opt_arg opt)
diff --git a/Sound/SC3/Server/Param.hs b/Sound/SC3/Server/Param.hs
new file mode 100644
--- /dev/null
+++ b/Sound/SC3/Server/Param.hs
@@ -0,0 +1,67 @@
+-- * Synthesis parameters
+module Sound.SC3.Server.Param where
+
+import Data.Function {- base -}
+import Data.List {- base -}
+import Data.Maybe {- base -}
+
+import Data.List.Split {- split -}
+
+import Sound.SC3.Common.Math {- hsc3 -}
+
+-- | An SC3 synthesis parameters, ie. (control-name,control-value).
+type Param1 = (String,Double)
+
+-- | Set of SC3 synthesiser parameters.
+type Param = [Param1]
+
+-- | Add new, or overwrite existing, parameter.
+param_insert :: Param -> Param1 -> Param
+param_insert p z = z : deleteBy ((==) `on` fst) z p
+
+-- | Merge, require keys be unique.
+--
+-- > param_merge_uniq [("a",1),("b",2)] [("c",3),("d",4)] == [("a",1),("b",2),("c",3),("d",4)]
+-- > param_merge_uniq [("a",1)] [("a",2)] -- error
+param_merge_uniq :: Param -> Param -> Param
+param_merge_uniq p1 p2 =
+  case map fst p1 `intersect` map fst p2 of
+    [] -> p1 ++ p2
+    _ -> error "param_merge_uniq?"
+
+-- | Merge, right biased.
+--
+-- > param_merge_r [("a",1),("b",2)] [("c",3),("a",4)] == [("b",2),("c",3),("a",4)]
+param_merge_r :: Param -> Param -> Param
+param_merge_r p1 p2 =
+    let p3 = let k2 = map fst p2 in filter (\(x,_) -> x `notElem` k2) p1
+    in p3 ++ p2
+
+-- | Right-fold (right-biased) of 'param_merge'
+--
+-- > param_merge_r_seq [[("a",1),("b",2)],[("c",3),("a",4)],[("b",5)]] == [("c",3),("a",4),("b",5)]
+param_merge_r_seq :: [Param] -> Param
+param_merge_r_seq = foldr1 param_merge_r
+
+-- | Lookup parameter value, with default.
+param_get :: Param -> String -> Double -> Double
+param_get p k v = fromMaybe v (lookup k p)
+
+-- | Given (param-separator,key-value-separator) parse paramter string.
+--
+-- > param_parse (';','=') "a=1;b=2" == [("a",1),("b",2)]
+param_parse :: (Char,Char) -> String -> Param
+param_parse (c1,c2) str =
+    let f x = case splitOn [c2] x of
+                [lhs,rhs] -> (lhs,read rhs)
+                _ -> error ("param_parse: " ++ x)
+    in if null str then [] else map f (splitOn [c1] str)
+
+-- | Inverse of 'param_parse', /k/ is the precision to print values to.
+--
+-- > param_pp (';','=') 4 [("a",1),("b",2)] == "a=1.0;b=2.0"
+param_pp :: (Char,Char) -> Int -> Param -> String
+param_pp (c1,c2) k =
+    let f (lhs,rhs) = concat [lhs,[c2],double_pp k rhs]
+    in intercalate [c1] . map f
+
diff --git a/Sound/SC3/Server/Recorder.hs b/Sound/SC3/Server/Recorder.hs
--- a/Sound/SC3/Server/Recorder.hs
+++ b/Sound/SC3/Server/Recorder.hs
@@ -3,12 +3,13 @@
 
 import Sound.OSC {- hosc -}
 
+import Sound.SC3.Common.Rate
 import Sound.SC3.Server.Command
 import Sound.SC3.Server.Enum
 import Sound.SC3.Server.NRT
 import Sound.SC3.Server.Synthdef
-import Sound.SC3.UGen
 import Sound.SC3.UGen.Bindings
+import Sound.SC3.UGen.UGen
 
 -- | Parameters for recording @scsynth@.
 data SC3_Recorder =
diff --git a/Sound/SC3/Server/Status.hs b/Sound/SC3/Server/Status.hs
--- a/Sound/SC3/Server/Status.hs
+++ b/Sound/SC3/Server/Status.hs
@@ -7,10 +7,13 @@
 -}
 module Sound.SC3.Server.Status where
 
-import qualified Data.ByteString.Char8 as C {- bytestring -}
 import Data.List {- base -}
 import Data.Maybe {- base -}
+import Text.Printf {- base -}
+
+import qualified Data.ByteString.Char8 as C {- bytestring -}
 import qualified Data.Tree as T {- containers -}
+import qualified Safe {- safe -}
 
 import Sound.OSC.Datum {- hosc -}
 
@@ -18,21 +21,21 @@
 
 -- * Status
 
--- | Get /n/th field of status as 'Floating'.
+-- | Get /n/th field of /status.reply message as 'Floating'.
 extractStatusField :: Floating n => Int -> [Datum] -> n
 extractStatusField n =
     fromMaybe (error "extractStatusField")
     . datum_floating
-    . (!! n)
+    . flip (Safe.atNote "extractStatusField") n
 
--- | Names of status fields.
+-- | Names of /status.reply fields sent in reply to /status request.
 statusFields :: [String]
 statusFields =
     ["Unused                      "
     ,"# UGens                     "
     ,"# Synths                    "
     ,"# Groups                    "
-    ,"# Instruments               "
+    ,"# Synthdefs                 "
     ,"% CPU (Average)             "
     ,"% CPU (Peak)                "
     ,"Sample Rate (Nominal)       "
@@ -43,6 +46,16 @@
 statusFormat d =
     let s = "***** SuperCollider Server Status *****"
     in s : zipWith (++) (tail statusFields) (map (datum_pp_typed (Just 5)) (tail d))
+
+-- | Concise pretty printer, one line, omits PEAK-CPU and NOMINAL-SR.
+status_format_concise :: [Datum] -> String
+status_format_concise d =
+  case d of
+    [Int32 _,Int32 ugn,Int32 grp,Int32 syn,Int32 ins,Float cpu1,Float _cpu2,Double _sr1,Double sr2] ->
+      printf
+      "UGN=%-5d GRP=%-5d SYN=%-5d INS=%-5d CPU=%-5.1f SR=%-7.1f"
+      ugn grp syn ins cpu1 sr2
+    _ -> error "status_format_concise?"
 
 -- * Query Group
 
diff --git a/Sound/SC3/Server/Synthdef.hs b/Sound/SC3/Server/Synthdef.hs
--- a/Sound/SC3/Server/Synthdef.hs
+++ b/Sound/SC3/Server/Synthdef.hs
@@ -2,7 +2,6 @@
 module Sound.SC3.Server.Synthdef where
 
 import qualified Data.ByteString.Lazy as L {- bytestring -}
-import System.FilePath {- filepath -}
 
 import Sound.SC3.UGen.Graph
 import Sound.SC3.UGen.Help.Graph
@@ -10,6 +9,7 @@
 
 import qualified Sound.SC3.Server.Graphdef as Graphdef
 import qualified Sound.SC3.Server.Graphdef.Graph as Graph
+import qualified Sound.SC3.Server.Param as Param
 
 -- | A named unit generator graph.
 data Synthdef = Synthdef {synthdefName :: String
@@ -47,9 +47,9 @@
 
 -- | Parameter names at 'Synthdef'.
 --
--- > synthdefParam defaultSynthdef == ["amp","pan","gate","freq","out"]
-synthdefParam :: Synthdef -> [String]
-synthdefParam = map u_node_k_name . ug_controls . synthdefGraph
+-- > synthdefParam defaultSynthdef == [("amp",0.1),("pan",0),("gate",1),("freq",440),("out",0)]
+synthdefParam :: Synthdef -> Param.Param
+synthdefParam = map (\n -> (u_node_k_name n,u_node_k_default n)) . ug_controls . synthdefGraph
 
 -- | 'graph_to_graphdef' at 'Synthdef'.
 synthdef_to_graphdef :: Synthdef -> Graphdef.Graphdef
@@ -59,22 +59,28 @@
 synthdefData :: Synthdef -> L.ByteString
 synthdefData = Graphdef.encode_graphdef . synthdef_to_graphdef
 
+-- | Write 'Synthdef' to indicated file.
+synthdefWrite :: FilePath -> Synthdef -> IO ()
+synthdefWrite fn = Graphdef.graphdefWrite fn . synthdef_to_graphdef
+
 -- | Write 'Synthdef' to indicated directory.  The filename is the
 -- 'synthdefName' with the appropriate extension (@scsyndef@).
-synthdefWrite :: Synthdef -> FilePath -> IO ()
-synthdefWrite s dir =
-    let nm = dir </> synthdefName s <.> "scsyndef"
-    in L.writeFile nm (synthdefData s)
+synthdefWrite_dir :: FilePath -> Synthdef -> IO ()
+synthdefWrite_dir dir = Graphdef.graphdefWrite_dir dir . synthdef_to_graphdef
 
 -- | 'graph_stat_ln' of 'synth'.
 synthstat_ln :: UGen -> [String]
 synthstat_ln = ug_stat_ln . ugen_to_graph
 
 -- | 'unlines' of 'synthstat_ln'.
---
--- > putStrLn $ synthstat Sound.SC3.UGen.Help.Graph.default_ugen_graph
 synthstat :: UGen -> String
 synthstat = unlines . synthstat_ln
+
+-- | 'putStrLn' of 'synthstat'.
+--
+-- > synthstat_wr Sound.SC3.UGen.Help.Graph.default_ugen_graph
+synthstat_wr :: UGen -> IO ()
+synthstat_wr = putStrLn . synthstat
 
 -- | Variant without UGen sequence.
 --
diff --git a/Sound/SC3/Server/Transport/FD.hs b/Sound/SC3/Server/Transport/FD.hs
--- a/Sound/SC3/Server/Transport/FD.hs
+++ b/Sound/SC3/Server/Transport/FD.hs
@@ -5,8 +5,10 @@
 module Sound.SC3.Server.Transport.FD where
 
 import Control.Monad {- base -}
+import qualified Data.ByteString.Lazy as L {- bytestring -}
 import Data.List {- base -}
 import qualified Data.List.Split as Split {- split -}
+import System.FilePath {- filepath -}
 
 import Sound.OSC.FD {- hosc -}
 
@@ -14,6 +16,7 @@
 import Sound.SC3.Server.Enum
 import qualified Sound.SC3.Server.Graphdef as G
 import Sound.SC3.Server.NRT
+import Sound.SC3.Server.Options
 import Sound.SC3.Server.Status
 import Sound.SC3.Server.Synthdef
 import Sound.SC3.UGen.Type
@@ -37,7 +40,7 @@
 
 -- | Bracket @SC3@ communication.
 withSC3 :: (UDP -> IO a) -> IO a
-withSC3 = withTransport (openUDP "127.0.0.1" 57110)
+withSC3 = withTransport (openUDP "127.0.0.1" sc3_port_def)
 
 -- * Server control
 
@@ -54,8 +57,13 @@
 -- | Send 'd_recv' and 's_new' messages to scsynth.
 playGraphdef :: Transport t => Int -> t -> G.Graphdef -> IO ()
 playGraphdef k fd g = do
-  _ <- async fd (d_recv' g)
-  sendMessage fd (s_new0 (ascii_to_string (G.graphdef_name g)) k AddToTail 1)
+  let nm = ascii_to_string (G.graphdef_name g)
+      fn = "/tmp" </> nm <.> "scsyndef"
+      by = G.encode_graphdef g
+      sz = L.length by
+  if sz < 65507
+    then void (async fd (d_recv_bytes by))
+    else G.graphdefWrite fn g >> async fd (d_load fn) >> sendMessage fd (s_new0 nm k AddToTail 1)
 
 -- | 'playGraphdef' of 'synthdef_to_graphdef'.
 playSynthdef :: Transport t => Int -> t -> Synthdef -> IO ()
diff --git a/Sound/SC3/Server/Transport/Monad.hs b/Sound/SC3/Server/Transport/Monad.hs
--- a/Sound/SC3/Server/Transport/Monad.hs
+++ b/Sound/SC3/Server/Transport/Monad.hs
@@ -2,11 +2,14 @@
 module Sound.SC3.Server.Transport.Monad where
 
 import Control.Monad {- base -}
+import qualified Data.ByteString.Lazy as L {- bytestring -}
 import Data.List {- base -}
 import qualified Data.List.Split as Split {- split -}
 import Data.Maybe {- base -}
 import qualified Data.Tree as Tree {- containers -}
 import qualified Safe {- safe -}
+import System.Directory {- directory -}
+import System.FilePath {- filepath -}
 
 import Sound.OSC {- hosc -}
 
@@ -15,12 +18,19 @@
 import qualified Sound.SC3.Server.Enum as Enum
 import qualified Sound.SC3.Server.Graphdef as Graphdef
 import qualified Sound.SC3.Server.NRT as NRT
+import qualified Sound.SC3.Server.Options as Options
 import qualified Sound.SC3.Server.Status as Status
 import qualified Sound.SC3.Server.Synthdef as Synthdef
 
 import Sound.SC3.UGen.Bindings.Composite (wrapOut)
 import Sound.SC3.UGen.Type (UGen)
 
+{-
+import qualified Control.Monad.IO.Class as M {- transformers -}
+import qualified Control.Monad.Trans.Reader as R {- transformers -}
+import qualified Sound.SC3.Server.Transport.FD as FD
+-}
+
 -- * hosc variants
 
 -- | 'sendMessage' and 'waitReply' for a @\/done@ reply.
@@ -42,10 +52,14 @@
     then async_ m
     else sendBundle (bundle t [m])
 
--- | Local host (ie. @127.0.0.1@) at port @57110@.
+-- | Local host (ie. @127.0.0.1@) at port 'sc3_port_def'
 sc3_default_udp :: IO UDP
-sc3_default_udp = openUDP "127.0.0.1" 57110
+sc3_default_udp = openUDP "127.0.0.1" Options.sc3_port_def
 
+-- | Maximum packet size, in bytes, that can be sent over UDP.
+sc3_udp_limit :: Num n => n
+sc3_udp_limit = 65507
+
 -- | Bracket @SC3@ communication, ie. 'withTransport' 'sc3_default_udp'.
 --
 -- > import Sound.SC3.Server.Command
@@ -87,20 +101,30 @@
     let nm = ascii_to_string (Graphdef.graphdef_name g)
     in s_new nm nid act gid param
 
--- | Send 'd_recv' and 's_new' messages to scsynth.
-playGraphdef :: DuplexOSC m => Play_Opt -> Graphdef.Graphdef -> m ()
-playGraphdef opt g = async_ (d_recv' g) >> sendMessage (play_graphdef_msg opt g)
+-- | If the graph size is less than 'sc3_udp_limit' encode and send
+-- using 'd_recv_bytes', else write to temporary directory and read
+-- using 'd_load'.
+recv_or_load_graphdef :: Transport m => Graphdef.Graphdef -> m Message
+recv_or_load_graphdef g = do
+  tmp <- liftIO getTemporaryDirectory
+  let nm = ascii_to_string (Graphdef.graphdef_name g)
+      fn = tmp </> nm <.> "scsyndef"
+      by = Graphdef.encode_graphdef g
+      sz = L.length by
+  if sz < sc3_udp_limit
+    then async (d_recv_bytes by)
+    else liftIO (Graphdef.graphdefWrite fn g) >> async (d_load fn)
 
--- | Make 's_new' message to play 'Synthdef.Synthdef'.
-play_synthdef_msg :: Play_Opt -> Synthdef.Synthdef -> Message
-play_synthdef_msg (nid,act,gid,param) syn = s_new (Synthdef.synthdefName syn) nid act gid param
+-- | Send 'd_recv' and 's_new' messages to scsynth.
+playGraphdef :: Transport m => Play_Opt -> Graphdef.Graphdef -> m ()
+playGraphdef opt g = recv_or_load_graphdef g >> sendMessage (play_graphdef_msg opt g)
 
 -- | Send 'd_recv' and 's_new' messages to scsynth.
-playSynthdef :: DuplexOSC m => Play_Opt -> Synthdef.Synthdef -> m ()
-playSynthdef opt syn = async_ (d_recv syn) >> sendMessage (play_synthdef_msg opt syn)
+playSynthdef :: Transport m => Play_Opt -> Synthdef.Synthdef -> m ()
+playSynthdef opt = playGraphdef opt . Synthdef.synthdef_to_graphdef
 
 -- | Send an /anonymous/ instrument definition using 'playSynthdef'.
-playUGen :: DuplexOSC m => Play_Opt -> UGen -> m ()
+playUGen :: Transport m => Play_Opt -> UGen -> m ()
 playUGen loc =
     playSynthdef loc .
     Synthdef.synthdef "Anonymous" .
@@ -250,22 +274,22 @@
   liftM f (waitDatum "/c_setn")
 
 -- | Apply /f/ to result of 'n_query'.
-n_query1_unpack_f :: Transport m => (Message -> t) -> Node_Id -> m t
+n_query1_unpack_f :: DuplexOSC m => (Message -> t) -> Node_Id -> m t
 n_query1_unpack_f f n = do
   sendMessage (n_query [n])
   r <- waitReply "/n_info"
   return (f r)
 
 -- | Variant of 'n_query' that waits for and unpacks the reply.
-n_query1_unpack :: Transport m => Node_Id -> m (Maybe (Int,Int,Int,Int,Int,Maybe (Int,Int)))
+n_query1_unpack :: DuplexOSC m => Node_Id -> m (Maybe (Int,Int,Int,Int,Int,Maybe (Int,Int)))
 n_query1_unpack = n_query1_unpack_f unpack_n_info
 
 -- | Variant of 'n_query1_unpack' that returns plain (un-lifted) result.
-n_query1_unpack_plain :: Transport m => Node_Id -> m [Int]
+n_query1_unpack_plain :: DuplexOSC m => Node_Id -> m [Int]
 n_query1_unpack_plain = n_query1_unpack_f unpack_n_info_plain
 
 -- | Variant of 'g_queryTree' that waits for and unpacks the reply.
-g_queryTree1_unpack :: Transport m => Group_Id -> m Status.Query_Node
+g_queryTree1_unpack :: DuplexOSC m => Group_Id -> m Status.Query_Node
 g_queryTree1_unpack n = do
   sendMessage (g_queryTree [(n,True)])
   r <- waitReply "/g_queryTree.reply"
@@ -279,6 +303,12 @@
 serverStatus :: DuplexOSC m => m [String]
 serverStatus = liftM Status.statusFormat serverStatusData
 
+-- | Collect server status information.
+--
+-- > withSC3 server_status_concise >>= putStrLn
+server_status_concise :: DuplexOSC m => m String
+server_status_concise = liftM Status.status_format_concise serverStatusData
+
 -- | Read nominal sample rate of server.
 --
 -- > withSC3 serverSampleRateNominal
@@ -302,7 +332,7 @@
 -- | Collect server node tree information.
 --
 -- > withSC3 serverTree >>= mapM_ putStrLn
-serverTree :: Transport m => m [String]
+serverTree :: DuplexOSC m => m [String]
 serverTree = do
   qt <- g_queryTree1_unpack 0
   let tr = Status.queryTree_rt qt
diff --git a/Sound/SC3/UGen.hs b/Sound/SC3/UGen.hs
--- a/Sound/SC3/UGen.hs
+++ b/Sound/SC3/UGen.hs
@@ -4,12 +4,10 @@
 import Sound.SC3.UGen.Analysis as U
 import Sound.SC3.UGen.Envelope as U
 import Sound.SC3.UGen.Enum as U
-import Sound.SC3.UGen.Help as U
 import Sound.SC3.UGen.Help.Graph as U
 import Sound.SC3.UGen.Math as U
+import Sound.SC3.UGen.Math.Composite as U
 import Sound.SC3.UGen.Name as U
-import Sound.SC3.UGen.Operator as U
 import Sound.SC3.UGen.Optimise as U
-import Sound.SC3.UGen.Rate as U
 import Sound.SC3.UGen.Type as U
 import Sound.SC3.UGen.UGen as U
diff --git a/Sound/SC3/UGen/Bindings/Composite.hs b/Sound/SC3/UGen/Bindings/Composite.hs
--- a/Sound/SC3/UGen/Bindings/Composite.hs
+++ b/Sound/SC3/UGen/Bindings/Composite.hs
@@ -6,18 +6,17 @@
 import qualified Data.List.Split as Split {- split -}
 import Data.Maybe {- base -}
 
+import Sound.SC3.Common.Enum
 import Sound.SC3.Common.Envelope
 import Sound.SC3.Common.Math
 import Sound.SC3.Common.Math.Filter.BEQ
-
+import Sound.SC3.Common.Math.Operator
+import Sound.SC3.Common.Rate
 import Sound.SC3.Common.UId
+
 import Sound.SC3.UGen.Bindings.DB
-import qualified Sound.SC3.UGen.Bindings.DB.External as External
 import Sound.SC3.UGen.Bindings.HW
 import Sound.SC3.UGen.Bindings.Monad
-import Sound.SC3.UGen.Enum
-import Sound.SC3.UGen.Math
-import Sound.SC3.UGen.Rate
 import Sound.SC3.UGen.Type
 import Sound.SC3.UGen.UGen
 
@@ -43,20 +42,20 @@
   in flt (flt i)
 
 -- | Buffer reader (no interpolation).
-bufRdN :: Int -> Rate -> UGen -> UGen -> Loop -> UGen
+bufRdN :: Int -> Rate -> UGen -> UGen -> Loop UGen -> UGen
 bufRdN n r b p l = bufRd n r b p l NoInterpolation
 
 -- | Buffer reader (linear interpolation).
-bufRdL :: Int -> Rate -> UGen -> UGen -> Loop -> UGen
+bufRdL :: Int -> Rate -> UGen -> UGen -> Loop UGen -> UGen
 bufRdL n r b p l = bufRd n r b p l LinearInterpolation
 
 -- | Buffer reader (cubic interpolation).
-bufRdC :: Int -> Rate -> UGen -> UGen -> Loop -> UGen
+bufRdC :: Int -> Rate -> UGen -> UGen -> Loop UGen -> UGen
 bufRdC n r b p l = bufRd n r b p l CubicInterpolation
 
 -- | Triggers when a value changes
 changed :: UGen -> UGen -> UGen
-changed input threshold = abs (hpz1 input) >* threshold
+changed input threshold = abs (hpz1 input) `greater_than` threshold
 
 -- | 'mce' variant of 'lchoose'.
 choose :: ID m => m -> UGen -> UGen
@@ -200,7 +199,7 @@
 
 -- | Map from one linear range to another linear range.
 linLin :: UGen -> UGen -> UGen -> UGen -> UGen -> UGen
-linLin = linlin_ma
+linLin = linlin_ma mulAdd
 
 -- | 'linLin' where source is (0,1).
 linLin_u :: UGen -> UGen -> UGen -> UGen
@@ -223,10 +222,18 @@
 makeFadeEnv fadeTime =
     let dt = control KR "fadeTime" (realToFrac fadeTime)
         gate_ = control KR "gate" 1
-        startVal = dt <=* 0
+        startVal = dt `less_than_or_equal_to` 0
         env = Envelope [startVal,1,0] [1,1] [EnvLin,EnvLin] (Just 1) Nothing 0
     in envGen KR gate_ 1 0 dt RemoveSynth env
 
+-- | 'mce' of 'map' /f/ of 'id_seq' /n/.
+mce_gen :: ID z => (Id -> UGen) -> Int -> z -> UGen
+mce_gen f n = mce . map f . id_seq n
+
+-- | Monad/applicative variant of mce_gen.
+mce_genM :: Applicative f => f UGen -> Int -> f UGen
+mce_genM f n = fmap mce (replicateM n f)
+
 -- | Count 'mce' channels.
 mceN :: UGen -> UGen
 mceN = constant . length . mceChannels
@@ -239,7 +246,7 @@
 mixN :: Int -> UGen -> UGen
 mixN n u =
     let xs = transpose (Split.chunksOf n (mceChannels u))
-    in mce (map sum xs)
+    in mce (map sum_opt xs)
 
 -- | Construct and sum a set of UGens.
 mixFill :: Integral n => Int -> (n -> UGen) -> UGen
@@ -247,7 +254,7 @@
 
 -- | Monad variant on mixFill.
 mixFillM :: (Integral n,Monad m) => Int -> (n -> m UGen) -> m UGen
-mixFillM n f = liftM sum (mapM f [0 .. fromIntegral n - 1])
+mixFillM n f = liftM sum_opt (mapM f [0 .. fromIntegral n - 1])
 
 -- | Variant that is randomly pressed.
 mouseButton' :: Rate -> UGen -> UGen -> UGen -> UGen
@@ -256,7 +263,7 @@
     in lag (linLin o (-1) 1 l r) tm
 
 -- | Randomised mouse UGen (see also 'mouseX'' and 'mouseY'').
-mouseR :: ID a => a -> Rate -> UGen -> UGen -> Warp -> UGen -> UGen
+mouseR :: ID a => a -> Rate -> UGen -> UGen -> Warp UGen -> UGen -> UGen
 mouseR z rt l r ty tm =
   let f = case ty of
             Linear -> linLin
@@ -265,11 +272,11 @@
   in lag (f (lfNoise1 z rt 1) (-1) 1 l r) tm
 
 -- | Variant that randomly traverses the mouseX space.
-mouseX' :: Rate -> UGen -> UGen -> Warp -> UGen -> UGen
+mouseX' :: Rate -> UGen -> UGen -> Warp UGen -> UGen -> UGen
 mouseX' = mouseR 'x'
 
 -- | Variant that randomly traverses the mouseY space.
-mouseY' :: Rate -> UGen -> UGen -> Warp -> UGen -> UGen
+mouseY' :: Rate -> UGen -> UGen -> Warp UGen -> UGen -> UGen
 mouseY' = mouseR 'y'
 
 -- | Translate onset type string to constant UGen value.
@@ -296,6 +303,7 @@
     in fft_size * num_partitions
 
 -- | PM oscillator.
+-- cf = carrier frequency, mf = modulation frequency, pm = pm-index = 0.0, mp = mod-phase = 0.0
 pmOsc :: Rate -> UGen -> UGen -> UGen -> UGen -> UGen
 pmOsc r cf mf pm mp = sinOsc r cf (sinOsc r mf mp * pm)
 
@@ -317,7 +325,7 @@
 
 -- | Apply function /f/ to each bin of an @FFT@ chain, /f/ receives
 -- magnitude, phase and index and returns a (magnitude,phase).
-pvcollect :: UGen -> UGen -> (UGen -> UGen -> UGen -> (UGen, UGen)) -> UGen -> UGen -> UGen -> UGen
+pvcollect :: UGen -> Int -> (UGen -> UGen -> Int -> (UGen, UGen)) -> Int -> Int -> UGen -> UGen
 pvcollect c nf f from to z =
     let m = unpackFFT c nf from to 0
         p = unpackFFT c nf from to 1
@@ -400,13 +408,9 @@
         a = if lc then sqrt (1 / n) else 1
     in mix (pan2 i (mce p * s + c) 1) * l * a
 
--- | Optimised sum function.
+-- | Optimised UGen sum function.
 sum_opt :: [UGen] -> UGen
-sum_opt l =
-    case l of
-      p:q:r:s:l' -> sum_opt (sum4 p q r s : l')
-      p:q:r:l' -> sum_opt (sum3 p q r : l')
-      _ -> sum l
+sum_opt = sum_opt_f sum3 sum4
 
 -- | Single tap into a delayline
 tap :: Int -> UGen -> UGen -> UGen
@@ -416,12 +420,12 @@
 
 -- | Randomly select one of several inputs on trigger.
 tChoose :: ID m => m -> UGen -> UGen -> UGen
-tChoose z t a = select (tiRand z 0 (mceN a) t) a
+tChoose z t a = select (tiRand z 0 (mceN a - 1) t) a
 
 -- | Randomly select one of several inputs.
 tChooseM :: (UId m) => UGen -> UGen -> m UGen
 tChooseM t a = do
-  r <- tiRandM 0 (constant (length (mceChannels a))) t
+  r <- tiRandM 0 (constant (length (mceChannels a) - 1)) t
   return (select r a)
 
 -- | Triangle wave as sum of /n/ sines.
@@ -433,7 +437,7 @@
         mk_ph i = if i + 1 `mod` 4 == 0 then pi else 0
         m = [1,3 .. n]
         param = zip3 (map mk_freq m) (map mk_ph m) (map mk_amp m)
-    in sum (map (\(fr,ph,am) -> sinOsc AR fr ph * am) param)
+    in sum_opt (map (\(fr,ph,am) -> sinOsc AR fr ph * am) param)
 
 -- | Randomly select one of several inputs on trigger (weighted).
 tWChoose :: ID m => m -> UGen -> UGen -> UGen -> UGen -> UGen
@@ -448,8 +452,8 @@
   return (select i a)
 
 -- | Unpack an FFT chain into separate demand-rate FFT bin streams.
-unpackFFT :: UGen -> UGen -> UGen -> UGen -> UGen -> [UGen]
-unpackFFT c nf from to w = map (\i -> unpack1FFT c nf i w) [from .. to]
+unpackFFT :: UGen -> Int -> Int -> Int -> UGen -> [UGen]
+unpackFFT c nf from to w = map (\i -> unpack1FFT c (constant nf) (constant i) w) [from .. to]
 
 -- | VarLag in terms of envGen
 varLag_env :: UGen -> UGen -> Envelope_Curve UGen -> UGen -> UGen
@@ -460,12 +464,14 @@
       tr = changed in_ 0 + time_ch + impulse rt 0 0
   in envGen rt tr 1 0 1 DoNothing e
 
--- | If @z@ isn't a sink node route to an @out@ node writing to @bus@.
--- If @fadeTime@ is given multiply by 'makeFadeEnv'.
---
--- > import Sound.SC3
--- > audition (wrapOut (sinOsc AR 440 0 * 0.1) 1)
--- > withSC3 (send (n_set1 (-1) "gate" 0))
+{- | If @z@ isn't a sink node route to an @out@ node writing to @bus@.
+     If @fadeTime@ is given multiply by 'makeFadeEnv'.
+
+> import Sound.SC3 {- hsc3 -}
+> audition (wrapOut (Just 1) (sinOsc AR 440 0 * 0.1))
+> import Sound.OSC {- hosc -}
+> withSC3 (sendMessage (n_set1 (-1) "gate" 0))
+-}
 wrapOut :: Maybe Double -> UGen -> UGen
 wrapOut fadeTime z =
     let bus = control KR "out" 0
@@ -476,7 +482,7 @@
 -- * wslib
 
 -- | Cross-fading version of 'playBuf'.
-playBufCF :: Int -> UGen -> UGen -> UGen -> UGen -> Loop -> UGen -> Int -> UGen
+playBufCF :: Int -> UGen -> UGen -> UGen -> UGen -> Loop UGen -> UGen -> Int -> UGen
 playBufCF nc bufnum rate trigger startPos loop lag' n =
     let trigger' = if rateOf trigger == DR
                    then tDuty AR trigger 0 DoNothing 1 0
@@ -498,25 +504,12 @@
             (\(on',r) -> let p = playBuf nc AR bufnum r on' startPos' loop DoNothing
                          in p * sqrt (slew on' lag'' lag''))
             (zip on rate')
-    in sum s
+    in sum_opt s
 
 -- * adc
 
 -- | An oscillator that reads through a table once.
-osc1 :: Rate -> UGen -> UGen -> DoneAction -> UGen
+osc1 :: Rate -> UGen -> UGen -> DoneAction UGen -> UGen
 osc1 rt buf dur doneAction =
     let ph = line rt 0 (bufFrames IR buf - 1) dur doneAction
     in bufRd 1 rt buf ph NoLoop LinearInterpolation
-
--- * External
-
--- | FM7 variant where input matrices are not in MCE form.
-fm7_mx :: [[UGen]] -> [[UGen]] -> UGen
-fm7_mx ctlMatrix modMatrix = External.fm7 AR (mce (concat ctlMatrix)) (mce (concat modMatrix))
-
--- | pulse signal as difference of two 'sawDPW' signals.
-pulseDPW :: Rate -> UGen -> UGen -> UGen
-pulseDPW rt freq width =
-  let o1 = External.sawDPW rt freq 0
-      o2 = External.sawDPW rt freq (wrap_hs (-1,1) (width+width))
-  in o1 - o2
diff --git a/Sound/SC3/UGen/Bindings/Composite/External.hs b/Sound/SC3/UGen/Bindings/Composite/External.hs
new file mode 100644
--- /dev/null
+++ b/Sound/SC3/UGen/Bindings/Composite/External.hs
@@ -0,0 +1,19 @@
+-- | Common unit generator graphs.
+module Sound.SC3.UGen.Bindings.Composite.External where
+
+import Sound.SC3.Common.Math
+import Sound.SC3.Common.Rate
+import Sound.SC3.UGen.Type
+
+import qualified Sound.SC3.UGen.Bindings.DB.External as External
+
+-- | FM7 variant where input matrices are not in MCE form.
+fm7_mx :: [[UGen]] -> [[UGen]] -> UGen
+fm7_mx ctlMatrix modMatrix = External.fm7 AR (mce (concat ctlMatrix)) (mce (concat modMatrix))
+
+-- | pulse signal as difference of two 'sawDPW' signals.
+pulseDPW :: Rate -> UGen -> UGen -> UGen
+pulseDPW rt freq width =
+  let o1 = External.sawDPW rt freq 0
+      o2 = External.sawDPW rt freq (wrap_hs (-1,1) (width+width))
+  in o1 - o2
diff --git a/Sound/SC3/UGen/Bindings/DB.hs b/Sound/SC3/UGen/Bindings/DB.hs
--- a/Sound/SC3/UGen/Bindings/DB.hs
+++ b/Sound/SC3/UGen/Bindings/DB.hs
@@ -1,10 +1,10 @@
 -- | SC3 UGen bindings (auto-generated).
 module Sound.SC3.UGen.Bindings.DB where
 
+import Sound.SC3.Common.Enum
 import Sound.SC3.Common.Envelope
+import Sound.SC3.Common.Rate
 import Sound.SC3.Common.UId
-import Sound.SC3.UGen.Enum
-import Sound.SC3.UGen.Rate
 import Sound.SC3.UGen.Type
 import Sound.SC3.UGen.UGen
 
@@ -20,19 +20,19 @@
 apf :: UGen -> UGen -> UGen -> UGen
 apf in_ freq radius = mkUGen Nothing [KR,AR] (Right [0]) "APF" [in_,freq,radius] Nothing 1 (Special 0) NoId
 
--- | All pass delay line with cubic interpolation.
+-- | Schroeder allpass delay line with cubic interpolation.
 --
 --  AllpassC [KR,AR] in=0.0 maxdelaytime=0.2 delaytime=0.2 decaytime=1.0;    FILTER: TRUE
 allpassC :: UGen -> UGen -> UGen -> UGen -> UGen
 allpassC in_ maxdelaytime delaytime decaytime = mkUGen Nothing [KR,AR] (Right [0]) "AllpassC" [in_,maxdelaytime,delaytime,decaytime] Nothing 1 (Special 0) NoId
 
--- | All pass delay line with linear interpolation.
+-- | Schroeder allpass delay line with linear interpolation.
 --
 --  AllpassL [KR,AR] in=0.0 maxdelaytime=0.2 delaytime=0.2 decaytime=1.0;    FILTER: TRUE
 allpassL :: UGen -> UGen -> UGen -> UGen -> UGen
 allpassL in_ maxdelaytime delaytime decaytime = mkUGen Nothing [KR,AR] (Right [0]) "AllpassL" [in_,maxdelaytime,delaytime,decaytime] Nothing 1 (Special 0) NoId
 
--- | All pass delay line with no interpolation.
+-- | Schroeder allpass delay line with no interpolation.
 --
 --  AllpassN [KR,AR] in=0.0 maxdelaytime=0.2 delaytime=0.2 decaytime=1.0;    FILTER: TRUE
 allpassN :: UGen -> UGen -> UGen -> UGen -> UGen
@@ -56,12 +56,6 @@
 amplitude :: Rate -> UGen -> UGen -> UGen -> UGen
 amplitude rate in_ attackTime releaseTime = mkUGen Nothing [KR,AR] (Left rate) "Amplitude" [in_,attackTime,releaseTime] Nothing 1 (Special 0) NoId
 
--- | (Undocumented class)
---
---  AudioControl [AR] values=0.0
-audioControl :: Rate -> UGen -> UGen
-audioControl rate values = mkUGen Nothing [AR] (Left rate) "AudioControl" [values] Nothing 0 (Special 0) NoId
-
 -- | All Pass Filter
 --
 --  BAllPass [AR] in=0.0 freq=1200.0 rq=1.0;    FILTER: TRUE
@@ -144,7 +138,7 @@
 --
 --  Ball [KR,AR] in=0.0 g=1.0 damp=0.0 friction=1.0e-2
 ball :: Rate -> UGen -> UGen -> UGen -> UGen -> UGen
-ball rate in_ g damp friction = mkUGen Nothing [KR,AR] (Left rate) "Ball" [in_,g,damp,friction] Nothing 1 (Special 0) NoId
+ball rate in_ g damp friction_ = mkUGen Nothing [KR,AR] (Left rate) "Ball" [in_,g,damp,friction_] Nothing 1 (Special 0) NoId
 
 -- | Autocorrelation beat tracker
 --
@@ -269,7 +263,7 @@
 -- | Buffer reading oscillator.
 --
 --  BufRd [KR,AR] bufnum=0.0 phase=0.0 loop=1.0 interpolation=2.0;    NC INPUT: True, ENUMERATION INPUTS: 2=Loop, 3=Interpolation
-bufRd :: Int -> Rate -> UGen -> UGen -> Loop -> Interpolation -> UGen
+bufRd :: Int -> Rate -> UGen -> UGen -> Loop UGen -> Interpolation UGen -> UGen
 bufRd numChannels rate bufnum phase loop interpolation = mkUGen Nothing [KR,AR] (Left rate) "BufRd" [bufnum,phase,(from_loop loop),(from_interpolation interpolation)] Nothing numChannels (Special 0) NoId
 
 -- | Buffer sample rate.
@@ -286,8 +280,8 @@
 
 -- | Buffer writing oscillator.
 --
---  BufWr [KR,AR] bufnum=0.0 phase=0.0 loop=1.0 *inputArray=0.0;    MCE, FILTER: TRUE, REORDERS INPUTS: [3,0,1,2], ENUMERATION INPUTS: 2=Loop
-bufWr :: UGen -> UGen -> Loop -> UGen -> UGen
+--  BufWr [KR,AR] bufnum=0.0 phase=0.0 loop=1.0 *inputArray=0.0;    MCE=1, FILTER: TRUE, REORDERS INPUTS: [3,0,1,2], ENUMERATION INPUTS: 2=Loop
+bufWr :: UGen -> UGen -> Loop UGen -> UGen -> UGen
 bufWr bufnum phase loop inputArray = mkUGen Nothing [KR,AR] (Right [3]) "BufWr" [bufnum,phase,(from_loop loop)] (Just [inputArray]) 1 (Special 0) NoId
 
 -- | Chorusing wavetable oscillator.
@@ -419,15 +413,21 @@
 -- | Buffer read demand ugen
 --
 --  Dbufrd [DR] bufnum=0.0 phase=0.0 loop=1.0;    ENUMERATION INPUTS: 2=Loop, DEMAND/NONDET
-dbufrd :: ID a => a -> UGen -> UGen -> Loop -> UGen
+dbufrd :: ID a => a -> UGen -> UGen -> Loop UGen -> UGen
 dbufrd z bufnum phase loop = mkUGen Nothing [DR] (Left DR) "Dbufrd" [bufnum,phase,(from_loop loop)] Nothing 1 (Special 0) (toUId z)
 
 -- | Buffer write demand ugen
 --
 --  Dbufwr [DR] bufnum=0.0 phase=0.0 loop=1.0 input=0.0;    REORDERS INPUTS: [3,0,1,2], ENUMERATION INPUTS: 3=Loop, DEMAND/NONDET
-dbufwr :: ID a => a -> UGen -> UGen -> UGen -> Loop -> UGen
+dbufwr :: ID a => a -> UGen -> UGen -> UGen -> Loop UGen -> UGen
 dbufwr z bufnum phase loop input = mkUGen Nothing [DR] (Left DR) "Dbufwr" [bufnum,phase,loop,(from_loop input)] Nothing 1 (Special 0) (toUId z)
 
+-- | Constrain a demand-rate stream to a given sum
+--
+--  Dconst [DR] sum=0.0 in=0.0 tolerance=1.0e-3;    DEMAND/NONDET
+dconst :: ID a => a -> UGen -> UGen -> UGen -> UGen
+dconst z sum_ in_ tolerance = mkUGen Nothing [DR] (Left DR) "Dconst" [sum_,in_,tolerance] Nothing 1 (Special 0) (toUId z)
+
 -- | Exponential decay
 --
 --  Decay [KR,AR] in=0.0 decayTime=1.0;    FILTER: TRUE
@@ -496,14 +496,14 @@
 
 -- | Demand results from demand rate UGens.
 --
---  Demand [KR,AR] trig=0.0 reset=0.0 *demandUGens=0.0;    MCE, FILTER: TRUE
+--  Demand [KR,AR] trig=0.0 reset=0.0 *demandUGens=0.0;    MCE=1, FILTER: TRUE
 demand :: UGen -> UGen -> UGen -> UGen
 demand trig_ reset demandUGens = mkUGen Nothing [KR,AR] (Right [0]) "Demand" [trig_,reset] (Just [demandUGens]) (length (mceChannels demandUGens) + 0) (Special 0) NoId
 
 -- | Demand rate envelope generator
 --
 --  DemandEnvGen [KR,AR] level=0.0 dur=0.0 shape=1.0 curve=0.0 gate=1.0 reset=1.0 levelScale=1.0 levelBias=0.0 timeScale=1.0 doneAction=0.0;    ENUMERATION INPUTS: 9=DoneAction
-demandEnvGen :: Rate -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> DoneAction -> UGen
+demandEnvGen :: Rate -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> DoneAction UGen -> UGen
 demandEnvGen rate level dur shape curve gate_ reset levelScale levelBias timeScale doneAction = mkUGen Nothing [KR,AR] (Left rate) "DemandEnvGen" [level,dur,shape,curve,gate_,reset,levelScale,levelBias,timeScale,(from_done_action doneAction)] Nothing 1 (Special 0) NoId
 
 -- | Search a buffer for a value
@@ -512,10 +512,10 @@
 detectIndex :: UGen -> UGen -> UGen
 detectIndex bufnum in_ = mkUGen Nothing [KR,AR] (Right [1]) "DetectIndex" [bufnum,in_] Nothing 1 (Special 0) NoId
 
--- | When input falls below a threshhold, evaluate doneAction.
+-- | Detect when input falls below an amplitude threshold
 --
 --  DetectSilence [KR,AR] in=0.0 amp=1.0e-4 time=0.1 doneAction=0.0;    FILTER: TRUE, ENUMERATION INPUTS: 3=DoneAction
-detectSilence :: UGen -> UGen -> UGen -> DoneAction -> UGen
+detectSilence :: UGen -> UGen -> UGen -> DoneAction UGen -> UGen
 detectSilence in_ amp time doneAction = mkUGen Nothing [KR,AR] (Right [0]) "DetectSilence" [in_,amp,time,(from_done_action doneAction)] Nothing 1 (Special 0) NoId
 
 -- | Demand rate geometric series UGen.
@@ -533,12 +533,12 @@
 -- | Stream in audio from a file.
 --
 --  DiskIn [AR] bufnum=0.0 loop=0.0;    NC INPUT: True, ENUMERATION INPUTS: 1=Loop
-diskIn :: Int -> UGen -> Loop -> UGen
+diskIn :: Int -> UGen -> Loop UGen -> UGen
 diskIn numChannels bufnum loop = mkUGen Nothing [AR] (Left AR) "DiskIn" [bufnum,(from_loop loop)] Nothing numChannels (Special 0) NoId
 
 -- | Record to a soundfile to disk.
 --
---  DiskOut [AR] bufnum=0.0 *channelsArray=0.0;    MCE
+--  DiskOut [AR] bufnum=0.0 *channelsArray=0.0;    MCE=1
 diskOut :: UGen -> UGen -> UGen
 diskOut bufnum input = mkUGen Nothing [AR] (Left AR) "DiskOut" [bufnum] (Just [input]) 1 (Special 0) NoId
 
@@ -548,12 +548,6 @@
 diwhite :: ID a => a -> UGen -> UGen -> UGen -> UGen
 diwhite z length_ lo hi = mkUGen Nothing [DR] (Left DR) "Diwhite" [length_,lo,hi] Nothing 1 (Special 0) (toUId z)
 
--- | (Undocumented class)
---
---  Donce [DR] in=0.0;    DEMAND/NONDET
-donce :: ID a => a -> UGen -> UGen
-donce z in_ = mkUGen Nothing [DR] (Left DR) "Donce" [in_] Nothing 1 (Special 0) (toUId z)
-
 -- | Monitors another UGen to see when it is finished
 --
 --  Done [KR] src=0.0
@@ -568,7 +562,7 @@
 
 -- | Demand rate random sequence generator.
 --
---  Drand [DR] repeats=1.0 *list=0.0;    MCE, REORDERS INPUTS: [1,0], DEMAND/NONDET
+--  Drand [DR] repeats=1.0 *list=0.0;    MCE=1, REORDERS INPUTS: [1,0], DEMAND/NONDET
 drand :: ID a => a -> UGen -> UGen -> UGen
 drand z repeats list_ = mkUGen Nothing [DR] (Left DR) "Drand" [repeats] (Just [list_]) 1 (Special 0) (toUId z)
 
@@ -580,13 +574,13 @@
 
 -- | Demand rate sequence generator.
 --
---  Dseq [DR] repeats=1.0 *list=0.0;    MCE, REORDERS INPUTS: [1,0], DEMAND/NONDET
+--  Dseq [DR] repeats=1.0 *list=0.0;    MCE=1, REORDERS INPUTS: [1,0], DEMAND/NONDET
 dseq :: ID a => a -> UGen -> UGen -> UGen
 dseq z repeats list_ = mkUGen Nothing [DR] (Left DR) "Dseq" [repeats] (Just [list_]) 1 (Special 0) (toUId z)
 
 -- | Demand rate sequence generator.
 --
---  Dser [DR] repeats=1.0 *list=0.0;    MCE, REORDERS INPUTS: [1,0], DEMAND/NONDET
+--  Dser [DR] repeats=1.0 *list=0.0;    MCE=1, REORDERS INPUTS: [1,0], DEMAND/NONDET
 dser :: ID a => a -> UGen -> UGen -> UGen
 dser z repeats list_ = mkUGen Nothing [DR] (Left DR) "Dser" [repeats] (Just [list_]) 1 (Special 0) (toUId z)
 
@@ -598,7 +592,7 @@
 
 -- | Demand rate random sequence generator
 --
---  Dshuf [DR] repeats=1.0 *list=0.0;    MCE, REORDERS INPUTS: [1,0], DEMAND/NONDET
+--  Dshuf [DR] repeats=1.0 *list=0.0;    MCE=1, REORDERS INPUTS: [1,0], DEMAND/NONDET
 dshuf :: ID a => a -> UGen -> UGen -> UGen
 dshuf z repeats list_ = mkUGen Nothing [DR] (Left DR) "Dshuf" [repeats] (Just [list_]) 1 (Special 0) (toUId z)
 
@@ -610,13 +604,13 @@
 
 -- | Demand rate generator for embedding different inputs
 --
---  Dswitch [DR] index=0.0 *list=0.0;    MCE, REORDERS INPUTS: [1,0], DEMAND/NONDET
+--  Dswitch [DR] index=0.0 *list=0.0;    MCE=1, REORDERS INPUTS: [1,0], DEMAND/NONDET
 dswitch :: ID a => a -> UGen -> UGen -> UGen
 dswitch z index_ list_ = mkUGen Nothing [DR] (Left DR) "Dswitch" [index_] (Just [list_]) 1 (Special 0) (toUId z)
 
 -- | Demand rate generator for switching between inputs.
 --
---  Dswitch1 [DR] index=0.0 *list=0.0;    MCE, REORDERS INPUTS: [1,0], DEMAND/NONDET
+--  Dswitch1 [DR] index=0.0 *list=0.0;    MCE=1, REORDERS INPUTS: [1,0], DEMAND/NONDET
 dswitch1 :: ID a => a -> UGen -> UGen -> UGen
 dswitch1 z index_ list_ = mkUGen Nothing [DR] (Left DR) "Dswitch1" [index_] (Just [list_]) 1 (Special 0) (toUId z)
 
@@ -641,7 +635,7 @@
 -- | Demand results from demand rate UGens.
 --
 --  Duty [KR,AR] dur=1.0 reset=0.0 doneAction=0.0 level=1.0;    REORDERS INPUTS: [0,1,3,2], ENUMERATION INPUTS: 2=DoneAction
-duty :: Rate -> UGen -> UGen -> DoneAction -> UGen -> UGen
+duty :: Rate -> UGen -> UGen -> DoneAction UGen -> UGen -> UGen
 duty rate dur reset doneAction level = mkUGen Nothing [KR,AR] (Left rate) "Duty" [dur,reset,(from_done_action doneAction),level] Nothing 1 (Special 0) NoId
 
 -- | Demand rate white noise random generator.
@@ -653,22 +647,22 @@
 {-
 -- | Demand rate weighted random sequence generator
 --
---  Dwrand [DR] repeats=1.0 weights=0.0 *list=0.0;    MCE, REORDERS INPUTS: [2,1,0], DEMAND/NONDET
+--  Dwrand [DR] repeats=1.0 weights=0.0 *list=0.0;    MCE=1, REORDERS INPUTS: [2,1,0], DEMAND/NONDET
 dwrand :: ID a => a -> UGen -> UGen -> UGen -> UGen
 dwrand z repeats weights list_ = mkUGen Nothing [DR] (Left DR) "Dwrand" [repeats,weights] (Just [list_]) 1 (Special 0) (toUId z)
 -}
 
 -- | Demand rate random sequence generator.
 --
---  Dxrand [DR] repeats=1.0 *list=0.0;    MCE, REORDERS INPUTS: [1,0], DEMAND/NONDET
+--  Dxrand [DR] repeats=1.0 *list=0.0;    MCE=1, REORDERS INPUTS: [1,0], DEMAND/NONDET
 dxrand :: ID a => a -> UGen -> UGen -> UGen
 dxrand z repeats list_ = mkUGen Nothing [DR] (Left DR) "Dxrand" [repeats] (Just [list_]) 1 (Special 0) (toUId z)
 
 -- | Envelope generator
 --
---  EnvGen [KR,AR] gate=1.0 levelScale=1.0 levelBias=0.0 timeScale=1.0 doneAction=0.0 *envelope=0.0;    MCE, REORDERS INPUTS: [5,0,1,2,3,4,5], ENUMERATION INPUTS: 4=DoneAction, 5=Envelope UGen
-envGen :: Rate -> UGen -> UGen -> UGen -> UGen -> DoneAction -> Envelope UGen -> UGen
-envGen rate gate_ levelScale levelBias timeScale doneAction envelope_ = mkUGen Nothing [KR,AR] (Left rate) "EnvGen" [gate_,levelScale,levelBias,timeScale,(from_done_action doneAction)] (Just [envelope_to_ugen envelope_]) 1 (Special 0) NoId
+--  EnvGen [KR,AR] gate=1.0 levelScale=1.0 levelBias=0.0 timeScale=1.0 doneAction=0.0 *envelope=0.0;    MCE=1, REORDERS INPUTS: [5,0,1,2,3,4,5], ENUMERATION INPUTS: 4=DoneAction, 5=Envelope
+envGen :: Rate -> UGen -> UGen -> UGen -> UGen -> DoneAction UGen -> Envelope UGen -> UGen
+envGen rate gate_ levelScale levelBias timeScale doneAction envelope_ = mkUGen Nothing [KR,AR] (Left rate) "EnvGen" [gate_,levelScale,levelBias,timeScale,(from_done_action doneAction)] (Just [(envelope_to_ugen envelope_)]) 1 (Special 0) NoId
 
 -- | Exponential single random number generator.
 --
@@ -856,7 +850,7 @@
 hpz2 :: UGen -> UGen
 hpz2 in_ = mkUGen Nothing [KR,AR] (Right [0]) "HPZ2" [in_] Nothing 1 (Special 0) NoId
 
--- | Randomized value.
+-- | Scrambled value with a hash function.
 --
 --  Hasher [KR,AR] in=0.0;    FILTER: TRUE
 hasher :: UGen -> UGen
@@ -888,9 +882,9 @@
 
 -- | Envelope generator for polling values from an Env
 --
---  IEnvGen [KR,AR] index=0.0 *envelope=0.0;    MCE, REORDERS INPUTS: [1,0], ENUMERATION INPUTS: 1=Envelope UGen
+--  IEnvGen [KR,AR] index=0.0 *envelope=0.0;    MCE=1, REORDERS INPUTS: [1,0], ENUMERATION INPUTS: 1=Envelope
 iEnvGen :: Rate -> UGen -> Envelope UGen -> UGen
-iEnvGen rate index_ envelope_ = mkUGen Nothing [KR,AR] (Left rate) "IEnvGen" [index_] (Just [envelope_to_ienvgen_ugen envelope_]) 1 (Special 0) NoId
+iEnvGen rate index_ envelope_ = mkUGen Nothing [KR,AR] (Left rate) "IEnvGen" [index_] (Just [(envelope_to_ugen envelope_)]) 1 (Special 0) NoId
 
 -- | Inverse Fast Fourier Transform
 --
@@ -954,7 +948,7 @@
 
 -- | Index into a table with a signal, linear interpolated
 --
---  IndexL [KR,AR] bufnum=0.0 in=0.0
+--  IndexL [KR,AR] bufnum=0.0 in=0.0;    FILTER: TRUE
 indexL :: UGen -> UGen -> UGen
 indexL bufnum in_ = mkUGen Nothing [KR,AR] (Right [1]) "IndexL" [bufnum,in_] Nothing 1 (Special 0) NoId
 
@@ -990,13 +984,13 @@
 
 -- | Sine oscillator bank
 --
---  Klang [AR] freqscale=1.0 freqoffset=0.0 *specificationsArrayRef=0.0;    MCE, REORDERS INPUTS: [2,0,1]
+--  Klang [AR] freqscale=1.0 freqoffset=0.0 *specificationsArrayRef=0.0;    MCE=1, REORDERS INPUTS: [2,0,1]
 klang :: Rate -> UGen -> UGen -> UGen -> UGen
 klang rate freqscale freqoffset specificationsArrayRef = mkUGen Nothing [AR] (Left rate) "Klang" [freqscale,freqoffset] (Just [specificationsArrayRef]) 1 (Special 0) NoId
 
 -- | Bank of resonators
 --
---  Klank [AR] input=0.0 freqscale=1.0 freqoffset=0.0 decayscale=1.0 *specificationsArrayRef=0.0;    MCE, FILTER: TRUE, REORDERS INPUTS: [4,0,1,2,3]
+--  Klank [AR] input=0.0 freqscale=1.0 freqoffset=0.0 decayscale=1.0 *specificationsArrayRef=0.0;    MCE=1, FILTER: TRUE, REORDERS INPUTS: [4,0,1,2,3]
 klank :: UGen -> UGen -> UGen -> UGen -> UGen -> UGen
 klank input freqscale freqoffset decayscale specificationsArrayRef = mkUGen Nothing [AR] (Right [0]) "Klank" [input,freqscale,freqoffset,decayscale] (Just [specificationsArrayRef]) 1 (Special 0) NoId
 
@@ -1039,7 +1033,7 @@
 -- | Gaussian function oscillator
 --
 --  LFGauss [KR,AR] duration=1.0 width=0.1 iphase=0.0 loop=1.0 doneAction=0.0;    ENUMERATION INPUTS: 3=Loop, 4=DoneAction
-lfGauss :: Rate -> UGen -> UGen -> UGen -> Loop -> DoneAction -> UGen
+lfGauss :: Rate -> UGen -> UGen -> UGen -> Loop UGen -> DoneAction UGen -> UGen
 lfGauss rate duration width iphase loop doneAction = mkUGen Nothing [KR,AR] (Left rate) "LFGauss" [duration,width,iphase,(from_loop loop),(from_done_action doneAction)] Nothing 1 (Special 0) NoId
 
 -- | Step noise
@@ -1237,13 +1231,13 @@
 -- | Line generator.
 --
 --  Line [KR,AR] start=0.0 end=1.0 dur=1.0 doneAction=0.0;    ENUMERATION INPUTS: 3=DoneAction
-line :: Rate -> UGen -> UGen -> UGen -> DoneAction -> UGen
+line :: Rate -> UGen -> UGen -> UGen -> DoneAction UGen -> UGen
 line rate start end dur doneAction = mkUGen Nothing [KR,AR] (Left rate) "Line" [start,end,dur,(from_done_action doneAction)] Nothing 1 (Special 0) NoId
 
 -- | Simple linear envelope generator.
 --
 --  Linen [KR] gate=1.0 attackTime=1.0e-2 susLevel=1.0 releaseTime=1.0 doneAction=0.0;    ENUMERATION INPUTS: 4=DoneAction
-linen :: UGen -> UGen -> UGen -> UGen -> DoneAction -> UGen
+linen :: UGen -> UGen -> UGen -> UGen -> DoneAction UGen -> UGen
 linen gate_ attackTime susLevel releaseTime doneAction = mkUGen Nothing [KR] (Left KR) "Linen" [gate_,attackTime,susLevel,releaseTime,(from_done_action doneAction)] Nothing 1 (Special 0) NoId
 
 -- | Allocate a buffer local to the synth
@@ -1254,13 +1248,13 @@
 
 -- | Define and read from buses local to a synth.
 --
---  LocalIn [KR,AR] *default=0.0;    MCE, NC INPUT: True
+--  LocalIn [KR,AR] *default=0.0;    MCE=1, NC INPUT: True
 localIn :: Int -> Rate -> UGen -> UGen
 localIn numChannels rate default_ = mkUGen Nothing [KR,AR] (Left rate) "LocalIn" [] (Just [default_]) numChannels (Special 0) NoId
 
 -- | Write to buses local to a synth.
 --
---  LocalOut [KR,AR] *channelsArray=0.0;    MCE, FILTER: TRUE
+--  LocalOut [KR,AR] *channelsArray=0.0;    MCE=1, FILTER: TRUE
 localOut :: UGen -> UGen
 localOut input = mkUGen Nothing [KR,AR] (Right [0]) "LocalOut" [] (Just [input]) 0 (Special 0) NoId
 
@@ -1333,13 +1327,13 @@
 -- | Cursor tracking UGen.
 --
 --  MouseX [KR] minval=0.0 maxval=1.0 warp=0.0 lag=0.2;    ENUMERATION INPUTS: 2=Warp
-mouseX :: Rate -> UGen -> UGen -> Warp -> UGen -> UGen
+mouseX :: Rate -> UGen -> UGen -> Warp UGen -> UGen -> UGen
 mouseX rate minval maxval warp lag_ = mkUGen Nothing [KR] (Left rate) "MouseX" [minval,maxval,(from_warp warp),lag_] Nothing 1 (Special 0) NoId
 
 -- | Cursor tracking UGen.
 --
 --  MouseY [KR] minval=0.0 maxval=1.0 warp=0.0 lag=0.2;    ENUMERATION INPUTS: 2=Warp
-mouseY :: Rate -> UGen -> UGen -> Warp -> UGen -> UGen
+mouseY :: Rate -> UGen -> UGen -> Warp UGen -> UGen -> UGen
 mouseY rate minval maxval warp lag_ = mkUGen Nothing [KR] (Left rate) "MouseY" [minval,maxval,(from_warp warp),lag_] Nothing 1 (Special 0) NoId
 
 -- | Sum of uniform distributions.
@@ -1348,6 +1342,12 @@
 nRand :: ID a => a -> UGen -> UGen -> UGen -> UGen
 nRand z lo hi n = mkUGen Nothing [IR] (Left IR) "NRand" [lo,hi,n] Nothing 1 (Special 0) (toUId z)
 
+-- | (Undocumented class)
+--
+--  NodeID [IR]
+nodeID :: Rate -> UGen
+nodeID rate = mkUGen Nothing [IR] (Left rate) "NodeID" [] Nothing 1 (Special 0) NoId
+
 -- | Flattens dynamics.
 --
 --  Normalizer [AR] in=0.0 level=1.0 dur=1.0e-2;    FILTER: TRUE
@@ -1392,7 +1392,7 @@
 
 -- | Write a signal to a bus with sample accurate timing.
 --
---  OffsetOut [KR,AR] bus=0.0 *channelsArray=0.0;    MCE, FILTER: TRUE
+--  OffsetOut [KR,AR] bus=0.0 *channelsArray=0.0;    MCE=1, FILTER: TRUE
 offsetOut :: UGen -> UGen -> UGen
 offsetOut bus input = mkUGen Nothing [KR,AR] (Right [1]) "OffsetOut" [bus] (Just [input]) 0 (Special 0) NoId
 
@@ -1428,13 +1428,13 @@
 
 -- | Write a signal to a bus.
 --
---  Out [KR,AR] bus=0.0 *channelsArray=0.0;    MCE, FILTER: TRUE
+--  Out [KR,AR] bus=0.0 *channelsArray=0.0;    MCE=1, FILTER: TRUE
 out :: UGen -> UGen -> UGen
 out bus input = mkUGen Nothing [KR,AR] (Right [1]) "Out" [bus] (Just [input]) 0 (Special 0) NoId
 
 -- | Very fast sine grain with a parabolic envelope
 --
---  PSinGrain [AR] freq=440.0 dur=0.2 amp=1.0
+--  PSinGrain [AR] freq=440.0 dur=0.2 amp=0.1
 pSinGrain :: Rate -> UGen -> UGen -> UGen -> UGen
 pSinGrain rate freq dur amp = mkUGen Nothing [AR] (Left rate) "PSinGrain" [freq,dur,amp] Nothing 1 (Special 0) NoId
 
@@ -1468,12 +1468,6 @@
 pv_BrickWall :: UGen -> UGen -> UGen
 pv_BrickWall buffer wipe = mkUGen Nothing [KR] (Left KR) "PV_BrickWall" [buffer,wipe] Nothing 1 (Special 0) NoId
 
--- | Base class for UGens that alter FFT chains
---
---  PV_ChainUGen [KR] maxSize=0.0
-pv_ChainUGen :: UGen -> UGen
-pv_ChainUGen maxSize = mkUGen Nothing [KR] (Left KR) "PV_ChainUGen" [maxSize] Nothing 1 (Special 0) NoId
-
 -- | Complex plane attack.
 --
 --  PV_ConformalMap [KR] buffer=0.0 areal=0.0 aimag=0.0
@@ -1743,7 +1737,7 @@
 -- | Sample playback oscillator.
 --
 --  PlayBuf [KR,AR] bufnum=0.0 rate=1.0 trigger=1.0 startPos=0.0 loop=0.0 doneAction=0.0;    NC INPUT: True, ENUMERATION INPUTS: 4=Loop, 5=DoneAction
-playBuf :: Int -> Rate -> UGen -> UGen -> UGen -> UGen -> Loop -> DoneAction -> UGen
+playBuf :: Int -> Rate -> UGen -> UGen -> UGen -> UGen -> Loop UGen -> DoneAction UGen -> UGen
 playBuf numChannels rate bufnum rate_ trigger startPos loop doneAction = mkUGen Nothing [KR,AR] (Left rate) "PlayBuf" [bufnum,rate_,trigger,startPos,(from_loop loop),(from_done_action doneAction)] Nothing numChannels (Special 0) NoId
 
 -- | A Karplus-Strong UGen
@@ -1755,9 +1749,9 @@
 {-
 -- | Print the current output value of a UGen
 --
---  Poll [KR,AR] trig=0.0 in=0.0 label=0.0 trigid=-1.0;    FILTER: TRUE
+--  Poll [KR,AR] trig=0.0 in=0.0 trigid=-1.0 label=0.0;    FILTER: TRUE, REORDERS INPUTS: [0,1,3,2]
 poll :: UGen -> UGen -> UGen -> UGen -> UGen
-poll trig_ in_ label_ trigid = mkUGen Nothing [KR,AR] (Right [1]) "Poll" [trig_,in_,label_,trigid] Nothing 1 (Special 0) NoId
+poll trig_ in_ trigid label_ = mkUGen Nothing [KR,AR] (Right [1]) "Poll" [trig_,in_,trigid,label_] Nothing 1 (Special 0) NoId
 -}
 
 -- | Band limited pulse wave.
@@ -1840,13 +1834,13 @@
 
 -- | Record or overdub into a Buffer.
 --
---  RecordBuf [KR,AR] bufnum=0.0 offset=0.0 recLevel=1.0 preLevel=0.0 run=1.0 loop=1.0 trigger=1.0 doneAction=0.0 *inputArray=0.0;    MCE, REORDERS INPUTS: [8,0,1,2,3,4,5,6,7], ENUMERATION INPUTS: 5=Loop, 7=DoneAction
-recordBuf :: Rate -> UGen -> UGen -> UGen -> UGen -> UGen -> Loop -> UGen -> DoneAction -> UGen -> UGen
+--  RecordBuf [KR,AR] bufnum=0.0 offset=0.0 recLevel=1.0 preLevel=0.0 run=1.0 loop=1.0 trigger=1.0 doneAction=0.0 *inputArray=0.0;    MCE=1, REORDERS INPUTS: [8,0,1,2,3,4,5,6,7], ENUMERATION INPUTS: 5=Loop, 7=DoneAction
+recordBuf :: Rate -> UGen -> UGen -> UGen -> UGen -> UGen -> Loop UGen -> UGen -> DoneAction UGen -> UGen -> UGen
 recordBuf rate bufnum offset recLevel preLevel run loop trigger doneAction inputArray = mkUGen Nothing [KR,AR] (Left rate) "RecordBuf" [bufnum,offset,recLevel,preLevel,run,(from_loop loop),trigger,(from_done_action doneAction)] (Just [inputArray]) 1 (Special 0) NoId
 
 -- | Send signal to a bus, overwriting previous contents.
 --
---  ReplaceOut [KR,AR] bus=0.0 *channelsArray=0.0;    MCE, FILTER: TRUE
+--  ReplaceOut [KR,AR] bus=0.0 *channelsArray=0.0;    MCE=1, FILTER: TRUE
 replaceOut :: UGen -> UGen -> UGen
 replaceOut bus input = mkUGen Nothing [KR,AR] (Right [1]) "ReplaceOut" [bus] (Just [input]) 0 (Special 0) NoId
 
@@ -1904,6 +1898,12 @@
 sampleRate :: UGen
 sampleRate = mkUGen Nothing [IR] (Left IR) "SampleRate" [] Nothing 1 (Special 0) NoId
 
+-- | Remove infinity, NaN, and denormals
+--
+--  Sanitize [KR,AR] in=0.0 replace=0.0
+sanitize :: UGen -> UGen -> UGen
+sanitize in_ replace = mkUGen Nothing [KR,AR] (Right [0]) "Sanitize" [in_,replace] Nothing 1 (Special 0) NoId
+
 -- | Band limited sawtooth.
 --
 --  Saw [KR,AR] freq=440.0
@@ -1916,21 +1916,9 @@
 schmidt :: UGen -> UGen -> UGen -> UGen
 schmidt in_ lo hi = mkUGen Nothing [IR,KR,AR] (Right [0]) "Schmidt" [in_,lo,hi] Nothing 1 (Special 0) NoId
 
--- | FIXME: ScopeOut purpose.
---
---  ScopeOut [KR,AR] inputArray=0.0 bufnum=0.0
-scopeOut :: Rate -> UGen -> UGen -> UGen
-scopeOut rate inputArray bufnum = mkUGen Nothing [KR,AR] (Left rate) "ScopeOut" [inputArray,bufnum] Nothing 0 (Special 0) NoId
-
--- | (Undocumented class)
---
---  ScopeOut2 [KR,AR] inputArray=0.0 scopeNum=0.0 maxFrames=4096.0 scopeFrames=0.0
-scopeOut2 :: Rate -> UGen -> UGen -> UGen -> UGen -> UGen
-scopeOut2 rate inputArray scopeNum maxFrames scopeFrames = mkUGen Nothing [KR,AR] (Left rate) "ScopeOut2" [inputArray,scopeNum,maxFrames,scopeFrames] Nothing 0 (Special 0) NoId
-
 -- | Select output from an array of inputs.
 --
---  Select [IR,KR,AR] which=0.0 *array=0.0;    MCE, FILTER: TRUE
+--  Select [IR,KR,AR] which=0.0 *array=0.0;    MCE=1, FILTER: TRUE
 select :: UGen -> UGen -> UGen
 select which array = mkUGen Nothing [IR,KR,AR] (Right [0,1]) "Select" [which] (Just [array]) 1 (Special 0) NoId
 
@@ -2070,7 +2058,7 @@
 --
 --  TBall [KR,AR] in=0.0 g=10.0 damp=0.0 friction=1.0e-2
 tBall :: Rate -> UGen -> UGen -> UGen -> UGen -> UGen
-tBall rate in_ g damp friction = mkUGen Nothing [KR,AR] (Left rate) "TBall" [in_,g,damp,friction] Nothing 1 (Special 0) NoId
+tBall rate in_ g damp friction_ = mkUGen Nothing [KR,AR] (Left rate) "TBall" [in_,g,damp,friction_] Nothing 1 (Special 0) NoId
 
 -- | Trigger delay.
 --
@@ -2081,7 +2069,7 @@
 -- | Demand results as trigger from demand rate UGens.
 --
 --  TDuty [KR,AR] dur=1.0 reset=0.0 doneAction=0.0 level=1.0 gapFirst=0.0;    REORDERS INPUTS: [0,1,3,2,4], ENUMERATION INPUTS: 2=DoneAction
-tDuty :: Rate -> UGen -> UGen -> DoneAction -> UGen -> UGen -> UGen
+tDuty :: Rate -> UGen -> UGen -> DoneAction UGen -> UGen -> UGen -> UGen
 tDuty rate dur reset doneAction level gapFirst = mkUGen Nothing [KR,AR] (Left rate) "TDuty" [dur,reset,(from_done_action doneAction),level,gapFirst] Nothing 1 (Special 0) NoId
 
 -- | Triggered exponential random number generator.
@@ -2110,7 +2098,7 @@
 
 -- | Triggered windex.
 --
---  TWindex [KR,AR] in=0.0 normalize=0.0 *array=0.0;    MCE, FILTER: TRUE, REORDERS INPUTS: [0,2,1], NONDET
+--  TWindex [KR,AR] in=0.0 normalize=0.0 *array=0.0;    MCE=1, FILTER: TRUE, REORDERS INPUTS: [0,2,1], NONDET
 tWindex :: ID a => a -> UGen -> UGen -> UGen -> UGen
 tWindex z in_ normalize array = mkUGen Nothing [KR,AR] (Right [0]) "TWindex" [in_,normalize] (Just [array]) 1 (Special 0) (toUId z)
 
@@ -2138,12 +2126,6 @@
 trig1 :: UGen -> UGen -> UGen
 trig1 in_ dur = mkUGen Nothing [KR,AR] (Right [0]) "Trig1" [in_,dur] Nothing 1 (Special 0) NoId
 
--- | FIXME: TrigControl purpose.
---
---  TrigControl [IR,KR] values=0.0
-trigControl :: Rate -> UGen -> UGen
-trigControl rate values = mkUGen Nothing [IR,KR] (Left rate) "TrigControl" [values] Nothing 0 (Special 0) NoId
-
 -- | Two pole filter.
 --
 --  TwoPole [KR,AR] in=0.0 freq=440.0 radius=0.8;    FILTER: TRUE
@@ -2165,7 +2147,7 @@
 -- | Stream in audio from a file, with variable rate
 --
 --  VDiskIn [AR] bufnum=0.0 rate=1.0 loop=0.0 sendID=0.0;    NC INPUT: True, ENUMERATION INPUTS: 2=Loop
-vDiskIn :: Int -> UGen -> UGen -> Loop -> UGen -> UGen
+vDiskIn :: Int -> UGen -> UGen -> Loop UGen -> UGen -> UGen
 vDiskIn numChannels bufnum rate_ loop sendID = mkUGen Nothing [AR] (Left AR) "VDiskIn" [bufnum,rate_,(from_loop loop),sendID] Nothing numChannels (Special 0) NoId
 
 -- | Variable wavetable oscillator.
@@ -2182,9 +2164,9 @@
 
 -- | Variable shaped lag
 --
---  VarLag [KR,AR] in=0.0 time=0.1 level=0.0;    FILTER: TRUE
-varLag :: UGen -> UGen -> UGen -> UGen
-varLag in_ time level = mkUGen Nothing [KR,AR] (Right [0]) "VarLag" [in_,time,level] Nothing 1 (Special 0) NoId
+--  VarLag [KR,AR] in=0.0 time=0.1 curvature=0.0 warp=5.0 start=0.0;    FILTER: TRUE
+varLag :: UGen -> UGen -> UGen -> UGen -> UGen -> UGen
+varLag in_ time curvature warp start = mkUGen Nothing [KR,AR] (Right [0]) "VarLag" [in_,time,curvature,warp,start] Nothing 1 (Special 0) NoId
 
 -- | Variable duty saw
 --
@@ -2194,9 +2176,9 @@
 
 -- | The Vibrato oscillator models a slow frequency modulation.
 --
---  Vibrato [KR,AR] freq=440.0 rate=6.0 depth=2.0e-2 delay=0.0 onset=0.0 rateVariation=4.0e-2 depthVariation=0.1 iphase=0.0;    NONDET
-vibrato :: ID a => a -> Rate -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
-vibrato z rate freq rate_ depth delay onset rateVariation depthVariation iphase = mkUGen Nothing [KR,AR] (Left rate) "Vibrato" [freq,rate_,depth,delay,onset,rateVariation,depthVariation,iphase] Nothing 1 (Special 0) (toUId z)
+--  Vibrato [KR,AR] freq=440.0 rate=6.0 depth=2.0e-2 delay=0.0 onset=0.0 rateVariation=4.0e-2 depthVariation=0.1 iphase=0.0 trig=0.0;    NONDET
+vibrato :: ID a => a -> Rate -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
+vibrato z rate freq rate_ depth delay onset rateVariation depthVariation iphase trig_ = mkUGen Nothing [KR,AR] (Left rate) "Vibrato" [freq,rate_,depth,delay,onset,rateVariation,depthVariation,iphase,trig_] Nothing 1 (Special 0) (toUId z)
 
 -- | Warp a buffer with a time pointer
 --
@@ -2210,12 +2192,6 @@
 whiteNoise :: ID a => a -> Rate -> UGen
 whiteNoise z rate = mkUGen Nothing [KR,AR] (Left rate) "WhiteNoise" [] Nothing 1 (Special 0) (toUId z)
 
--- | (Undocumented class)
---
---  WidthFirstUGen [] maxSize=0.0
-widthFirstUGen :: Rate -> UGen -> UGen
-widthFirstUGen rate maxSize = mkUGen Nothing [IR,KR,AR,DR] (Left rate) "WidthFirstUGen" [maxSize] Nothing 1 (Special 0) NoId
-
 -- | Wrap a signal outside given thresholds.
 --
 --  Wrap [IR,KR,AR] in=0.0 lo=0.0 hi=1.0;    FILTER: TRUE
@@ -2237,12 +2213,12 @@
 -- | Exponential line generator.
 --
 --  XLine [KR,AR] start=1.0 end=2.0 dur=1.0 doneAction=0.0;    ENUMERATION INPUTS: 3=DoneAction
-xLine :: Rate -> UGen -> UGen -> UGen -> DoneAction -> UGen
+xLine :: Rate -> UGen -> UGen -> UGen -> DoneAction UGen -> UGen
 xLine rate start end dur doneAction = mkUGen Nothing [KR,AR] (Left rate) "XLine" [start,end,dur,(from_done_action doneAction)] Nothing 1 (Special 0) NoId
 
 -- | Send signal to a bus, crossfading with previous contents.
 --
---  XOut [KR,AR] bus=0.0 xfade=0.0 *channelsArray=0.0;    MCE, FILTER: TRUE
+--  XOut [KR,AR] bus=0.0 xfade=0.0 *channelsArray=0.0;    MCE=1, FILTER: TRUE
 xOut :: UGen -> UGen -> UGen -> UGen
 xOut bus xfade input = mkUGen Nothing [KR,AR] (Right [2]) "XOut" [bus,xfade] (Just [input]) 0 (Special 0) NoId
 
@@ -2254,18 +2230,18 @@
 
 -- | LocalBuf count
 --
---  MaxLocalBufs [IR] count=0.0
+--  MaxLocalBufs [IR,KR] count=0.0
 maxLocalBufs :: UGen -> UGen
-maxLocalBufs count = mkUGen Nothing [IR] (Left IR) "MaxLocalBufs" [count] Nothing 1 (Special 0) NoId
+maxLocalBufs count = mkUGen Nothing [IR,KR] (Left KR) "MaxLocalBufs" [count] Nothing 1 (Special 0) NoId
 
 -- | Multiply add
 --
 --  MulAdd [IR,KR,AR] in=0.0 mul=0.0 add=0.0;    FILTER: TRUE
 mulAdd :: UGen -> UGen -> UGen -> UGen
-mulAdd in_ mul add = mkUGen Nothing [IR,KR,AR] (Right [0]) "MulAdd" [in_,mul,add] Nothing 1 (Special 0) NoId
+mulAdd in_ mul add = mkUGen Nothing [IR,KR,AR] (Right [0,1,2]) "MulAdd" [in_,mul,add] Nothing 1 (Special 0) NoId
 
 -- | Set local buffer
 --
---  SetBuf [IR] buf=0.0 offset=0.0 length=0.0 *array=0.0;    MCE, REORDERS INPUTS: [0,1,2,3]
+--  SetBuf [IR] buf=0.0 offset=0.0 length=0.0 *array=0.0;    MCE=1, REORDERS INPUTS: [0,1,2,3]
 setBuf :: UGen -> UGen -> UGen -> UGen -> UGen
 setBuf buf offset length_ array = mkUGen Nothing [IR] (Left IR) "SetBuf" [buf,offset,length_] (Just [array]) 1 (Special 0) NoId
diff --git a/Sound/SC3/UGen/Bindings/DB/External.hs b/Sound/SC3/UGen/Bindings/DB/External.hs
--- a/Sound/SC3/UGen/Bindings/DB/External.hs
+++ b/Sound/SC3/UGen/Bindings/DB/External.hs
@@ -1,8 +1,8 @@
 -- | SC3 external (sce3-plugins) UGen bindings (auto-generated).
 module Sound.SC3.UGen.Bindings.DB.External where
 
+import Sound.SC3.Common.Rate
 import Sound.SC3.Common.UId
-import Sound.SC3.UGen.Rate
 import Sound.SC3.UGen.Type
 import Sound.SC3.UGen.UGen
 
@@ -42,6 +42,12 @@
 analyseEvents2 :: Rate -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
 analyseEvents2 rate in_ bufnum threshold triggerid circular pitch_ = mkUGen Nothing [AR] (Left rate) "AnalyseEvents2" [in_,bufnum,threshold,triggerid,circular,pitch_] Nothing 1 (Special 0) NoId
 
+-- | 2-species Predator-Prey model
+--
+--  ArneodoCoulletTresser [AR] freq=22050.0 alpha=1.5 h=5.0e-2 xi=0.5 yi=0.5 zi=0.5
+arneodoCoulletTresser :: Rate -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
+arneodoCoulletTresser rate freq alpha h xi yi zi = mkUGen Nothing [AR] (Left rate) "ArneodoCoulletTresser" [freq,alpha,h,xi,yi,zi] Nothing 3 (Special 0) NoId
+
 -- | detect the largest value (and its position) in an array of UGens
 --
 --  ArrayMax [KR,AR] array=0.0
@@ -1942,8 +1948,8 @@
 -- | TB303 Filter Emulation
 --
 --  RLPFD [KR,AR] in=0.0 ffreq=440.0 res=0.0 dist=0.0
-rLPFD :: Rate -> UGen -> UGen -> UGen -> UGen -> UGen
-rLPFD rate in_ ffreq res dist = mkUGen Nothing [KR,AR] (Left rate) "RLPFD" [in_,ffreq,res,dist] Nothing 1 (Special 0) NoId
+rlpfd :: UGen -> UGen -> UGen -> UGen -> UGen
+rlpfd in_ ffreq res dist = mkUGen Nothing [KR,AR] (Right [0]) "RLPFD" [in_,ffreq,res,dist] Nothing 1 (Special 0) NoId
 
 -- | (Undocumented class)
 --
diff --git a/Sound/SC3/UGen/Bindings/HW.hs b/Sound/SC3/UGen/Bindings/HW.hs
--- a/Sound/SC3/UGen/Bindings/HW.hs
+++ b/Sound/SC3/UGen/Bindings/HW.hs
@@ -1,9 +1,9 @@
 -- | Hand-written bindings.
 module Sound.SC3.UGen.Bindings.HW where
 
+import Sound.SC3.Common.Rate
 import qualified Sound.SC3.Common.UId as I
 import qualified Sound.SC3.UGen.Bindings.HW.Construct as C
-import Sound.SC3.UGen.Rate
 import Sound.SC3.UGen.Type
 import qualified Sound.SC3.UGen.UGen as U
 
@@ -21,19 +21,19 @@
         inp = repeats : constant n : weights'
     in mkUGen Nothing [DR] (Left DR) "Dwrand" inp (Just [list_]) 1 (Special 0) (U.toUId z)
 
+-- | Variant on 'envGen' without enumeration types.
+envGen_ll :: Rate -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
+envGen_ll rate gate_ levelScale levelBias timeScale doneAction envelope_ = mkUGen Nothing [KR,AR] (Left rate) "EnvGen" [gate_,levelScale,levelBias,timeScale,doneAction] (Just [envelope_]) 1 (Special 0) NoId
+
 -- | Outputs signal for @FFT@ chains, without performing FFT.
 fftTrigger :: UGen -> UGen -> UGen -> UGen
 fftTrigger b h p = C.mkOsc KR "FFTTrigger" [b,h,p] 1
 
--- | LADSPA plugins inside SuperCollider.
-ladspa :: Int -> Rate -> UGen -> [UGen] -> UGen
-ladspa nc rt k z = C.mkOsc rt "LADSPA" (constant nc : k : z) nc
-
 -- | Pack demand-rate FFT bin streams into an FFT chain.
-packFFT :: UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
+packFFT :: UGen -> Int -> Int -> Int -> UGen -> UGen -> UGen
 packFFT b sz from to z mp =
     let n = constant (mceDegree_err mp)
-    in C.mkOscMCE KR "PackFFT" [b, sz, from, to, z, n] mp 1
+    in C.mkOscMCE KR "PackFFT" [b, constant sz, constant from, constant to, z, n] mp 1
 
 -- | Poll value of input UGen when triggered.
 poll :: UGen -> UGen -> UGen -> UGen -> UGen
@@ -58,5 +58,5 @@
 
 -- | Unpack a single value (magnitude or phase) from an FFT chain
 unpack1FFT :: UGen -> UGen -> UGen -> UGen -> UGen
-unpack1FFT buf size index' which = C.mkOsc DR "Unpack1FFT" [buf, size, index', which] 1
+unpack1FFT buf size index_ which = C.mkOsc DR "Unpack1FFT" [buf, size, index_, which] 1
 
diff --git a/Sound/SC3/UGen/Bindings/HW/Construct.hs b/Sound/SC3/UGen/Bindings/HW/Construct.hs
--- a/Sound/SC3/UGen/Bindings/HW/Construct.hs
+++ b/Sound/SC3/UGen/Bindings/HW/Construct.hs
@@ -1,7 +1,7 @@
 -- | For hand-writing UGens.
 module Sound.SC3.UGen.Bindings.HW.Construct where
 
-import Sound.SC3.UGen.Rate
+import Sound.SC3.Common.Rate
 import Sound.SC3.UGen.Type
 
 -- | Oscillator constructor with constrained set of operating 'Rate's.
diff --git a/Sound/SC3/UGen/Bindings/HW/External/F0.hs b/Sound/SC3/UGen/Bindings/HW/External/F0.hs
--- a/Sound/SC3/UGen/Bindings/HW/External/F0.hs
+++ b/Sound/SC3/UGen/Bindings/HW/External/F0.hs
@@ -1,21 +1,21 @@
 -- | F0 UGens (f0plugins)
 module Sound.SC3.UGen.Bindings.HW.External.F0 where
 
-import Sound.SC3.UGen.Bindings.HW.Construct
-import Sound.SC3.UGen.Rate
+import Sound.SC3.Common.Rate
+import qualified Sound.SC3.UGen.Bindings.HW.Construct as C
 import Sound.SC3.UGen.Type
 
 -- | Emulation of the sound generation hardware of the Atari TIA chip.
 atari2600 :: UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
-atari2600 audc0 audc1 audf0 audf1 audv0 audv1 rate = mkOsc AR "Atari2600" [audc0,audc1,audf0,audf1,audv0,audv1,rate] 1
+atari2600 audc0 audc1 audf0 audf1 audv0 audv1 rate = C.mkOsc AR "Atari2600" [audc0,audc1,audf0,audf1,audv0,audv1,rate] 1
 
 -- | POKEY Chip Sound Simulator
 mzPokey :: UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
-mzPokey f1 c1 f2 c2 f3 c3 f4 c4 ctl = mkOsc AR "MZPokey" [f1,c1,f2,c2,f3,c3,f4,c4,ctl] 1
+mzPokey f1 c1 f2 c2 f3 c3 f4 c4 ctl = C.mkOsc AR "MZPokey" [f1,c1,f2,c2,f3,c3,f4,c4,ctl] 1
 
 -- | A phasor that can loop.
 redPhasor :: Rate -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
-redPhasor rate trig rate_ start end loop loopstart loopend = mkOsc rate "RedPhasor" [trig,rate_,start,end,loop,loopstart,loopend] 1
+redPhasor rate trig rate_ start end loop loopstart loopend = C.mkOsc rate "RedPhasor" [trig,rate_,start,end,loop,loopstart,loopend] 1
 
 -- Local Variables:
 -- truncate-lines:t
diff --git a/Sound/SC3/UGen/Bindings/HW/External/SC3_Plugins.hs b/Sound/SC3/UGen/Bindings/HW/External/SC3_Plugins.hs
--- a/Sound/SC3/UGen/Bindings/HW/External/SC3_Plugins.hs
+++ b/Sound/SC3/UGen/Bindings/HW/External/SC3_Plugins.hs
@@ -1,12 +1,14 @@
 -- | Bindings to unit generators in sc3-plugins.
 module Sound.SC3.UGen.Bindings.HW.External.SC3_Plugins where
 
--- * AY
+import Sound.SC3.Common.Rate
+import qualified Sound.SC3.UGen.Bindings.HW.Construct as C
+import Sound.SC3.UGen.Type
 
 -- | Convert frequency value to value appropriate for AY tone inputs.
 ayFreqToTone :: Fractional a => a -> a
 ayFreqToTone f = 110300 / (f - 0.5)
 
--- Local Variables:
--- truncate-lines:t
--- End:
+-- | LADSPA plugins inside SuperCollider.
+ladspa :: Int -> Rate -> UGen -> [UGen] -> UGen
+ladspa nc rt k z = C.mkOsc rt "LADSPA" (constant nc : k : z) nc
diff --git a/Sound/SC3/UGen/Bindings/HW/External/Wavelets.hs b/Sound/SC3/UGen/Bindings/HW/External/Wavelets.hs
--- a/Sound/SC3/UGen/Bindings/HW/External/Wavelets.hs
+++ b/Sound/SC3/UGen/Bindings/HW/External/Wavelets.hs
@@ -1,8 +1,8 @@
 -- | Wavelet unit generators (Nick Collins).
 module Sound.SC3.UGen.Bindings.HW.External.Wavelets where
 
+import Sound.SC3.Common.Rate
 import Sound.SC3.UGen.Bindings.HW.Construct
-import Sound.SC3.UGen.Rate
 import Sound.SC3.UGen.Type
 
 -- | Forward wavelet transform.
diff --git a/Sound/SC3/UGen/Bindings/HW/External/Zita.hs b/Sound/SC3/UGen/Bindings/HW/External/Zita.hs
--- a/Sound/SC3/UGen/Bindings/HW/External/Zita.hs
+++ b/Sound/SC3/UGen/Bindings/HW/External/Zita.hs
@@ -3,8 +3,8 @@
 -- See hsc3/ext/faust to build the SC3 plugin.
 module Sound.SC3.UGen.Bindings.HW.External.Zita where
 
+import Sound.SC3.Common.Rate
 import Sound.SC3.UGen.Bindings.HW.Construct
-import Sound.SC3.UGen.Rate
 import Sound.SC3.UGen.Type
 
 -- | Parameter (name,value) pairs.
diff --git a/Sound/SC3/UGen/Bindings/Monad.hs b/Sound/SC3/UGen/Bindings/Monad.hs
--- a/Sound/SC3/UGen/Bindings/Monad.hs
+++ b/Sound/SC3/UGen/Bindings/Monad.hs
@@ -3,199 +3,219 @@
 
 import Control.Monad {- base -}
 
+import Sound.SC3.Common.Enum
+import Sound.SC3.Common.Rate
 import Sound.SC3.Common.UId
 import Sound.SC3.UGen.Bindings.DB
 import Sound.SC3.UGen.Bindings.HW
-import Sound.SC3.UGen.Enum
-import Sound.SC3.UGen.Rate
 import Sound.SC3.UGen.Type
 
 -- | Clone a unit generator (mce . replicateM).
-clone :: (UId m) => Int -> m UGen -> m UGen
+clone :: UId m => Int -> m UGen -> m UGen
 clone n = liftM mce . replicateM n
 
 -- * Demand
 
--- | Buffer demand ugen.
-dbufrdM :: (UId m) => UGen -> UGen -> Loop -> m UGen
+-- | 'dbufrd'
+dbufrdM :: UId m => UGen -> UGen -> Loop UGen -> m UGen
 dbufrdM = liftUId3 dbufrd
 
--- | Buffer write on demand unit generator.
-dbufwrM :: (UId m) => UGen -> UGen -> UGen -> Loop -> m UGen
+-- | 'dbufwr'
+dbufwrM :: UId m => UGen -> UGen -> UGen -> Loop UGen -> m UGen
 dbufwrM = liftUId4 dbufwr
 
--- | Demand rate white noise.
-dwhiteM :: (UId m) => UGen -> UGen -> UGen -> m UGen
+-- | 'dconst'
+dconstM :: UId m => UGen -> UGen -> UGen -> m UGen
+dconstM = liftUId3 dconst
+
+-- | 'dwhite'
+dwhiteM :: UId m => UGen -> UGen -> UGen -> m UGen
 dwhiteM = liftUId3 dwhite
 
--- | Demand rate integer white noise.
-diwhiteM :: (UId m) => UGen -> UGen -> UGen -> m UGen
+-- | 'diwhite'
+diwhiteM :: UId m => UGen -> UGen -> UGen -> m UGen
 diwhiteM = liftUId3 diwhite
 
--- | Demand rate brown noise.
-dbrownM :: (UId m) => UGen -> UGen -> UGen -> UGen -> m UGen
+-- | 'dbrown'
+dbrownM :: UId m => UGen -> UGen -> UGen -> UGen -> m UGen
 dbrownM = liftUId4 dbrown
 
--- | Demand rate integer brown noise.
-dibrownM :: (UId m) => UGen -> UGen -> UGen -> UGen -> m UGen
+-- | 'dibrown'
+dibrownM :: UId m => UGen -> UGen -> UGen -> UGen -> m UGen
 dibrownM = liftUId4 dibrown
 
--- | Demand rate random selection.
-drandM :: (UId m) => UGen -> UGen -> m UGen
+-- | 'dpoll'
+dpollM :: UId m => UGen -> UGen -> UGen -> UGen -> m UGen
+dpollM = liftUId4 dpoll
+
+-- | 'drand'
+drandM :: UId m => UGen -> UGen -> m UGen
 drandM = liftUId2 drand
 
--- | Demand rate weighted random sequence generator.
-dwrandM :: (UId m) => UGen -> UGen -> UGen -> m UGen
+-- | 'dreset'
+dresetM :: UId m => UGen -> UGen -> m UGen
+dresetM = liftUId2 dreset
+
+-- | 'dunique'
+duniqueM :: UId m => UGen -> UGen -> UGen -> m UGen
+duniqueM = liftUId3 dunique
+
+-- | 'dwrand'
+dwrandM :: UId m => UGen -> UGen -> UGen -> m UGen
 dwrandM = liftUId3 dwrand
 
--- | Demand rate random selection with no immediate repetition.
-dxrandM :: (UId m) => UGen -> UGen -> m UGen
+-- | 'dxrand'
+dxrandM :: UId m => UGen -> UGen -> m UGen
 dxrandM = liftUId2 dxrand
 
 -- | Demand rate arithmetic series.
-dseriesM :: (UId m) => UGen -> UGen -> UGen -> m UGen
+dseriesM :: UId m => UGen -> UGen -> UGen -> m UGen
 dseriesM = liftUId3 dseries
 
 -- | Demand rate geometric series.
-dgeomM :: (UId m) => UGen -> UGen -> UGen -> m UGen
+dgeomM :: UId m => UGen -> UGen -> UGen -> m UGen
 dgeomM = liftUId3 dgeom
 
 -- | Demand rate sequence generator.
-dseqM :: (UId m) => UGen -> UGen -> m UGen
+dseqM :: UId m => UGen -> UGen -> m UGen
 dseqM = liftUId2 dseq
 
 -- | Demand rate series generator.
-dserM :: (UId m) => UGen -> UGen -> m UGen
+dserM :: UId m => UGen -> UGen -> m UGen
 dserM = liftUId2 dser
 
 -- | Demand rate sequence shuffler.
-dshufM :: (UId m) => UGen -> UGen -> m UGen
+dshufM :: UId m => UGen -> UGen -> m UGen
 dshufM = liftUId2 dshuf
 
 -- | Demand input replication
-dstutterM :: (UId m) => UGen -> UGen -> m UGen
+dstutterM :: UId m => UGen -> UGen -> m UGen
 dstutterM = liftUId2 dstutter
 
 -- | Demand rate input switching.
-dswitch1M :: (UId m) => UGen -> UGen -> m UGen
+dswitch1M :: UId m => UGen -> UGen -> m UGen
 dswitch1M = liftUId2 dswitch1
 
 -- | Demand rate input switching.
-dswitchM :: (UId m) => UGen -> UGen -> m UGen
+dswitchM :: UId m => UGen -> UGen -> m UGen
 dswitchM = liftUId2 dswitch
 
 -- * FFT
 
 -- | Randomize order of bins.
-pv_BinScrambleM :: (UId m) => UGen -> UGen -> UGen -> UGen -> m UGen
+pv_BinScrambleM :: UId m => UGen -> UGen -> UGen -> UGen -> m UGen
 pv_BinScrambleM = liftUId4 pv_BinScramble
 
 -- | Randomly clear bins.
-pv_RandCombM :: (UId m) => UGen -> UGen -> UGen -> m UGen
+pv_RandCombM :: UId m => UGen -> UGen -> UGen -> m UGen
 pv_RandCombM = liftUId3 pv_RandComb
 
 -- | Cross fade, copying bins in random order.
-pv_RandWipeM :: (UId m) => UGen -> UGen -> UGen -> UGen -> m UGen
+pv_RandWipeM :: UId m => UGen -> UGen -> UGen -> UGen -> m UGen
 pv_RandWipeM = liftUId4 pv_RandWipe
 
 -- * Noise
 
 -- | Brown noise.
-brownNoiseM :: (UId m) => Rate -> m UGen
+brownNoiseM :: UId m => Rate -> m UGen
 brownNoiseM = liftUId1 brownNoise
 
 -- | Clip noise.
-clipNoiseM :: (UId m) => Rate -> m UGen
+clipNoiseM :: UId m => Rate -> m UGen
 clipNoiseM = liftUId1 clipNoise
 
 -- | Randomly pass or block triggers.
-coinGateM :: (UId m) => UGen -> UGen -> m UGen
+coinGateM :: UId m => UGen -> UGen -> m UGen
 coinGateM = liftUId2 coinGate
 
 -- | Random impulses in (-1, 1).
-dust2M :: (UId m) => Rate -> UGen -> m UGen
+dust2M :: UId m => Rate -> UGen -> m UGen
 dust2M = liftUId2 dust2
 
 -- | Random impulse in (0,1).
-dustM :: (UId m) => Rate -> UGen -> m UGen
+dustM :: UId m => Rate -> UGen -> m UGen
 dustM = liftUId2 dust
 
 -- | Random value in exponential distribution.
-expRandM :: (UId m) => UGen -> UGen -> m UGen
+expRandM :: UId m => UGen -> UGen -> m UGen
 expRandM = liftUId2 expRand
 
 -- | Gray noise.
-grayNoiseM :: (UId m) => Rate -> m UGen
+grayNoiseM :: UId m => Rate -> m UGen
 grayNoiseM = liftUId1 grayNoise
 
 -- | Random integer in uniform distribution.
-iRandM :: (UId m) => UGen -> UGen -> m UGen
+iRandM :: UId m => UGen -> UGen -> m UGen
 iRandM = liftUId2 iRand
 
 -- | Clip noise.
-lfClipNoiseM :: (UId m) => Rate -> UGen -> m UGen
+lfClipNoiseM :: UId m => Rate -> UGen -> m UGen
 lfClipNoiseM = liftUId2 lfClipNoise
 
 -- | Dynamic clip noise.
-lfdClipNoiseM :: (UId m) => Rate -> UGen -> m UGen
+lfdClipNoiseM :: UId m => Rate -> UGen -> m UGen
 lfdClipNoiseM = liftUId2 lfdClipNoise
 
 -- | Dynamic step noise.
-lfdNoise0M :: (UId m) => Rate -> UGen -> m UGen
+lfdNoise0M :: UId m => Rate -> UGen -> m UGen
 lfdNoise0M = liftUId2 lfdNoise0
 
 -- | Dynamic ramp noise.
-lfdNoise1M :: (UId m) => Rate -> UGen -> m UGen
+lfdNoise1M :: UId m => Rate -> UGen -> m UGen
 lfdNoise1M = liftUId2 lfdNoise1
 
 -- | Dynamic cubic noise
-lfdNoise3M :: (UId m) => Rate -> UGen -> m UGen
+lfdNoise3M :: UId m => Rate -> UGen -> m UGen
 lfdNoise3M = liftUId2 lfdNoise3
 
 -- | Step noise.
-lfNoise0M :: (UId m) => Rate -> UGen -> m UGen
+lfNoise0M :: UId m => Rate -> UGen -> m UGen
 lfNoise0M = liftUId2 lfNoise0
 
 -- | Ramp noise.
-lfNoise1M :: (UId m) => Rate -> UGen -> m UGen
+lfNoise1M :: UId m => Rate -> UGen -> m UGen
 lfNoise1M = liftUId2 lfNoise1
 
 -- | Quadratic noise.
-lfNoise2M :: (UId m) => Rate -> UGen -> m UGen
+lfNoise2M :: UId m => Rate -> UGen -> m UGen
 lfNoise2M = liftUId2 lfNoise2
 
 -- | Random value in skewed linear distribution.
-linRandM :: (UId m) => UGen -> UGen -> UGen -> m UGen
+linRandM :: UId m => UGen -> UGen -> UGen -> m UGen
 linRandM = liftUId3 linRand
 
+-- | 'localBuf'
+localBufM :: UId m => UGen -> UGen -> m UGen
+localBufM = liftUId2 localBuf
+
 -- | Random value in sum of n linear distribution.
-nRandM :: (UId m) => UGen -> UGen -> UGen -> m UGen
+nRandM :: UId m => UGen -> UGen -> UGen -> m UGen
 nRandM = liftUId3 nRand
 
 -- | Pink noise.
-pinkNoiseM :: (UId m) => Rate -> m UGen
+pinkNoiseM :: UId m => Rate -> m UGen
 pinkNoiseM = liftUId1 pinkNoise
 
 -- | Random value in uniform distribution.
-randM :: (UId m) => UGen -> UGen -> m UGen
+randM :: UId m => UGen -> UGen -> m UGen
 randM = liftUId2 rand
 
 -- | Random value in exponential distribution on trigger.
-tExpRandM :: (UId m) => UGen -> UGen -> UGen -> m UGen
+tExpRandM :: UId m => UGen -> UGen -> UGen -> m UGen
 tExpRandM = liftUId3 tExpRand
 
 -- | Random integer in uniform distribution on trigger.
-tiRandM :: (UId m) => UGen -> UGen -> UGen -> m UGen
+tiRandM :: UId m => UGen -> UGen -> UGen -> m UGen
 tiRandM = liftUId3 tiRand
 
 -- | Random value in uniform distribution on trigger.
-tRandM :: (UId m) => UGen -> UGen -> UGen -> m UGen
+tRandM :: UId m => UGen -> UGen -> UGen -> m UGen
 tRandM = liftUId3 tRand
 
 -- | Triggered windex.
-tWindexM :: (UId m) => UGen -> UGen -> UGen -> m UGen
+tWindexM :: UId m => UGen -> UGen -> UGen -> m UGen
 tWindexM = liftUId3 tWindex
 
 -- | White noise.
-whiteNoiseM :: (UId m) => Rate -> m UGen
+whiteNoiseM :: UId m => Rate -> m UGen
 whiteNoiseM = liftUId1 whiteNoise
diff --git a/Sound/SC3/UGen/Enum.hs b/Sound/SC3/UGen/Enum.hs
--- a/Sound/SC3/UGen/Enum.hs
+++ b/Sound/SC3/UGen/Enum.hs
@@ -1,84 +1,15 @@
 -- | Data types for enumerated and non signal unit generator inputs.
 module Sound.SC3.UGen.Enum where
 
-import qualified Sound.SC3.Common.Envelope as E
+import Sound.SC3.Common.Envelope
+import Sound.SC3.Common.Enum
 import Sound.SC3.UGen.Type
 
--- | Loop indicator input.
-data Loop' t = Loop
-             | NoLoop
-             | WithLoop t
-               deriving (Eq, Show)
-
--- | Type-specialised 'Loop''.
-type Loop = Loop' UGen
-
--- | Resolve 'Loop''.
-from_loop :: Num t => Loop' t -> t
-from_loop e =
-    case e of
-      NoLoop -> 0
-      Loop -> 1
-      WithLoop u -> u
-
--- | Interpolation indicator input.
-data Interpolation = NoInterpolation
-                   | LinearInterpolation
-                   | CubicInterpolation
-                   | Interpolation UGen
-                     deriving (Eq, Show)
-
--- | Resolve 'Interpolation'.
-from_interpolation :: Interpolation -> UGen
-from_interpolation e =
-    case e of
-      NoInterpolation -> 1
-      LinearInterpolation -> 2
-      CubicInterpolation -> 4
-      Interpolation u -> u
-
--- | Completion mode indicator input.
-data DoneAction = DoNothing
-                | PauseSynth
-                | RemoveSynth
-                | RemoveGroup
-                | DoneAction UGen
-                  deriving (Eq, Show)
-
--- | Resolve 'DoneAction'.
-from_done_action :: DoneAction -> UGen
-from_done_action e =
-    case e of
-      DoNothing -> 0
-      PauseSynth -> 1
-      RemoveSynth -> 2
-      RemoveGroup -> 14
-      DoneAction u -> u
-
--- | Warp interpolation indicator input.
-data Warp = Linear
-          | Exponential
-          | Warp UGen
-            deriving (Eq, Show)
-
--- | Resolve 'Warp'.
-from_warp :: Warp -> UGen
-from_warp e =
-    case e of
-      Linear -> 0
-      Exponential -> 1
-      Warp u -> u
-
 -- | Type specialised ('UGen') envelope curve.
-type EnvCurve = E.Envelope_Curve UGen
-
--- | Unification of integer and 'UGen' buffer identifiers.
-data Buffer = Buffer_Id Int
-            | Buffer UGen
-              deriving (Eq, Show)
+type EnvCurve = Envelope_Curve UGen
 
 -- | Lift to 'UGen'.
-from_buffer :: Buffer -> UGen
+from_buffer :: Buffer UGen -> UGen
 from_buffer b =
     case b of
       Buffer_Id i -> constant i
diff --git a/Sound/SC3/UGen/Envelope.hs b/Sound/SC3/UGen/Envelope.hs
--- a/Sound/SC3/UGen/Envelope.hs
+++ b/Sound/SC3/UGen/Envelope.hs
@@ -1,12 +1,12 @@
 -- | Envelope / UGen.
 module Sound.SC3.UGen.Envelope where
 
+import Sound.SC3.Common.Enum
 import Sound.SC3.Common.Envelope
+import Sound.SC3.Common.Math.Operator
+import Sound.SC3.Common.Rate
 
 import Sound.SC3.UGen.Bindings
-import Sound.SC3.UGen.Math
-import Sound.SC3.UGen.Enum
-import Sound.SC3.UGen.Rate
 import Sound.SC3.UGen.Type
 import Sound.SC3.UGen.UGen
 
@@ -17,16 +17,20 @@
 
 -}
 envTrapezoid :: OrdE t => t -> t -> t -> t -> Envelope t
-envTrapezoid = envTrapezoid_f ((<=*),(>=*))
+envTrapezoid = envTrapezoid_f (less_than_or_equal_to,greater_than_or_equal_to)
 
--- | 'env_circle_z' of 'latch' of 'impulse'.
+-- | 'latch' 1 of 'impulse' 0.
+first_zero_then_one :: Rate -> UGen
+first_zero_then_one rt = latch 1 (impulse rt 0 0)
+
+-- | 'env_circle_z' of k-rate 'first_zero_thereafter_one'.
 env_circle_u :: UGen -> Envelope_Curve UGen -> Envelope UGen -> Envelope UGen
-env_circle_u = env_circle_z (latch 1 (impulse KR 0 0))
+env_circle_u = env_circle_z (first_zero_then_one KR)
 
 -- | Singleton fade envelope.
-envGate :: UGen -> UGen -> UGen -> DoneAction -> Envelope_Curve UGen -> UGen
+envGate :: UGen -> UGen -> UGen -> DoneAction UGen -> Envelope_Curve UGen -> UGen
 envGate level gate_ fadeTime doneAction curve =
-    let startVal = fadeTime <=* 0
+    let startVal = fadeTime `less_than_or_equal_to` 0
         e = Envelope [startVal,1,0] [1,1] [curve] (Just 1) Nothing 0
     in envGen KR gate_ level 0 fadeTime doneAction e
 
diff --git a/Sound/SC3/UGen/Graph.hs b/Sound/SC3/UGen/Graph.hs
--- a/Sound/SC3/UGen/Graph.hs
+++ b/Sound/SC3/UGen/Graph.hs
@@ -19,8 +19,8 @@
 import Data.List {- base -}
 import Data.Maybe {- base -}
 
+import Sound.SC3.Common.Rate
 import qualified Sound.SC3.UGen.Analysis as Analysis
-import Sound.SC3.UGen.Rate
 import Sound.SC3.UGen.Type
 import Sound.SC3.UGen.UGen
 
diff --git a/Sound/SC3/UGen/Graph/Reconstruct.hs b/Sound/SC3/UGen/Graph/Reconstruct.hs
--- a/Sound/SC3/UGen/Graph/Reconstruct.hs
+++ b/Sound/SC3/UGen/Graph/Reconstruct.hs
@@ -5,9 +5,9 @@
 import Data.List {- base -}
 import Text.Printf {- base -}
 
+import qualified Sound.SC3.Common.Math.Operator as Operator
+import Sound.SC3.Common.Rate
 import qualified Sound.SC3.UGen.Graph as Graph
-import qualified Sound.SC3.UGen.Operator as Operator
-import Sound.SC3.UGen.Rate
 import Sound.SC3.UGen.Type
 import Sound.SC3.UGen.UGen
 
@@ -42,7 +42,7 @@
 reconstruct_graph_module :: String -> Graph.U_Graph -> [String]
 reconstruct_graph_module nm gr =
   let imp = ["import Sound.SC3"
-            ,"import Sound.SC3.Common"
+            ,"import Sound.SC3.Common.Base"
             ,"import Sound.SC3.UGen.Plain"]
       (b0:bnd,res) = reconstruct_graph gr
       hs = ("  let " ++ b0) : map ("      " ++ ) bnd ++ ["  in " ++ res]
diff --git a/Sound/SC3/UGen/Graph/Transform.hs b/Sound/SC3/UGen/Graph/Transform.hs
--- a/Sound/SC3/UGen/Graph/Transform.hs
+++ b/Sound/SC3/UGen/Graph/Transform.hs
@@ -4,8 +4,8 @@
 import Data.Either {- base -}
 import Data.List {- base -}
 
+import Sound.SC3.Common.Rate
 import Sound.SC3.UGen.Graph
-import Sound.SC3.UGen.Rate
 import Sound.SC3.UGen.Type
 
 -- * Lift constants
diff --git a/Sound/SC3/UGen/Help.hs b/Sound/SC3/UGen/Help.hs
deleted file mode 100644
--- a/Sound/SC3/UGen/Help.hs
+++ /dev/null
@@ -1,109 +0,0 @@
--- | Functions to provide mediated access to the SC3 help system.
---
--- Requires the HTML files generated by SCDoc.renderAll (sclang).
-module Sound.SC3.UGen.Help where
-
-import Control.Exception
-import Control.Monad
-import Data.List.Split {- split -}
-import Data.Maybe
-import System.IO.Error
-import System.Process {- process -}
-import System.Directory {- directory -}
-import System.Environment
-import System.FilePath {- filepath -}
-
--- | Guarded variant of 'getEnv' with default value.
-get_env_default :: String -> String -> IO String
-get_env_default e k = do
-  r <- tryJust (guard . isDoesNotExistError) (getEnv e)
-  case r of
-    Right v -> return v
-    _ -> return k
-
--- | 'lookupEnv' with default value.
---
--- > lookup_env_default "PATH" "/usr/bin"
-lookup_env_default :: String -> String -> IO String
-lookup_env_default e k = fmap (fromMaybe k) (lookupEnv e)
-
--- | Read the environment variable @SC3_HELP@, the default value is
--- @~\/.local\/share\/SuperCollider/Help@.
-sc3HelpDirectory :: IO String
-sc3HelpDirectory = do
-  h <- getEnv "HOME"
-  let d = h </> ".local/share/SuperCollider/Help"
-  get_env_default "SC3_HELP" d
-
--- | Locate path to indicated SC3 class help file.
---
--- > import System.FilePath
--- >
--- > d <- sc3HelpDirectory
--- > h <- sc3HelpClassFile d "SinOsc"
--- > h == Just (d </> "Classes/SinOsc.html")
-sc3HelpClassFile :: FilePath -> String -> IO (Maybe FilePath)
-sc3HelpClassFile d c = do
-  let f = d </> "Classes" </> c <.> "html"
-  e <- doesFileExist f
-  return (if e then Just f else Nothing)
-
--- | Generate path to indicated SC3 operator help file.
---
--- > sc3HelpOperatorEntry "." "+" == "./Overviews/Operators.html#.+"
-sc3HelpOperatorEntry :: FilePath -> String -> FilePath
-sc3HelpOperatorEntry d o = d </> "Overviews/Operators.html#." ++ o
-
--- | Generate path to indicated SC3 method help.
---
--- > sc3HelpMethod "." '*' ("C","m") == "./Classes/C.html#*m"
-sc3HelpMethod :: FilePath -> Char -> (String,String) -> FilePath
-sc3HelpMethod d z (c,m) = d </> "Classes" </> c <.> "html#" ++ [z] ++ m
-
--- | Generate path to indicated SC3 class method help.
---
--- > sc3HelpClassMethod "." ("C","m") == "./Classes/C.html#*m"
-sc3HelpClassMethod :: FilePath -> (String,String) -> FilePath
-sc3HelpClassMethod d = sc3HelpMethod d '*'
-
--- | Generate path to indicated SC3 instance method help.
---
--- > sc3HelpInstanceMethod "." ("C","m") == "./Classes/C.html#-m"
-sc3HelpInstanceMethod :: FilePath -> (String,String) -> FilePath
-sc3HelpInstanceMethod d = sc3HelpMethod d '-'
-
--- | The name of the local SC3 Help file documenting `u'.  Deletes
--- @\@@ to allow use on haddock quoted comments.
---
--- > import Sound.SC3.UGen.Name
--- >
--- > ugenSC3HelpFile "Collection.*fill"
--- > ugenSC3HelpFile "Collection.inject"
--- > ugenSC3HelpFile (toSC3Name "sinOsc")
-ugenSC3HelpFile :: String -> IO FilePath
-ugenSC3HelpFile x = do
-  let s = filter (`notElem` "@") x
-  d <- sc3HelpDirectory
-  cf <- sc3HelpClassFile d s
-  case splitOn "." s of
-    ["Operator",m] -> return (sc3HelpOperatorEntry d m)
-    [c,'*':m] -> return (sc3HelpClassMethod d (c,m))
-    [c,m] -> return (sc3HelpInstanceMethod d (c,m))
-    _ -> case cf of
-           Just cf' -> return cf'
-           Nothing -> error (show ("ugenSC3HelpFile",d,cf,x,s))
-
--- | Use @BROWSER@ or @x-www-browser@ to view SC3 help file for `u'.
---
--- > get_env_default "BROWSER" "x-www-browser"
---
--- > import Sound.SC3.UGen.Name
--- >
--- > viewSC3Help (toSC3Name "Collection.*fill")
--- > viewSC3Help (toSC3Name "Collection.inject")
--- > viewSC3Help (toSC3Name "sinOsc")
-viewSC3Help :: String -> IO ()
-viewSC3Help u = do
-  nm <- ugenSC3HelpFile u
-  br <- get_env_default "BROWSER" "x-www-browser"
-  void (rawSystem br ["file://" ++ nm])
diff --git a/Sound/SC3/UGen/Help/Graph.hs b/Sound/SC3/UGen/Help/Graph.hs
--- a/Sound/SC3/UGen/Help/Graph.hs
+++ b/Sound/SC3/UGen/Help/Graph.hs
@@ -1,11 +1,11 @@
 -- | Standard SC3 graphs, referenced in documentation.
 module Sound.SC3.UGen.Help.Graph where
 
+import Sound.SC3.Common.Enum
 import Sound.SC3.Common.Envelope
+import Sound.SC3.Common.Rate
 
 import Sound.SC3.UGen.Bindings
-import Sound.SC3.UGen.Enum
-import Sound.SC3.UGen.Rate
 import Sound.SC3.UGen.Type
 import Sound.SC3.UGen.UGen
 
diff --git a/Sound/SC3/UGen/Math.hs b/Sound/SC3/UGen/Math.hs
--- a/Sound/SC3/UGen/Math.hs
+++ b/Sound/SC3/UGen/Math.hs
@@ -1,337 +1,13 @@
 -- | Non-standard mathematical classes and class instances.
 module Sound.SC3.UGen.Math where
 
-import qualified Data.Fixed as F {- base -}
-import Data.Int {- base -}
-
-import qualified Sound.SC3.Common.Math as Math
-import Sound.SC3.UGen.Bindings.DB (mulAdd)
-import Sound.SC3.UGen.Operator
-import Sound.SC3.UGen.Type
+import qualified Sound.SC3.Common.Math.Operator as Operator
+import qualified Sound.SC3.UGen.Type as Type
 
 -- | Pseudo-infinite constant UGen.
-dinf :: UGen
-dinf = constant (9e8::Float)
-
--- | Association table for 'Binary' to haskell function implementing operator.
-binop_hs_tbl :: (Real n,Floating n,RealFrac n) => [(Binary,n -> n -> n)]
-binop_hs_tbl =
-    [(Add,(+))
-    ,(Sub,(-))
-    ,(FDiv,(/))
-    ,(IDiv,Math.sc3_idiv)
-    ,(Mod,Math.sc3_mod)
-    ,(EQ_,Math.sc3_eq)
-    ,(NE,Math.sc3_neq)
-    ,(LT_,Math.sc3_lt)
-    ,(LE,Math.sc3_lte)
-    ,(GT_,Math.sc3_gt)
-    ,(GE,Math.sc3_gte)
-    ,(Min,min)
-    ,(Max,max)
-    ,(Mul,(*))
-    ,(Pow,(**))
-    ,(Min,min)
-    ,(Max,max)
-    ,(Round,Math.sc3_round_to)]
-
--- | 'lookup' 'binop_hs_tbl' via 'toEnum'.
-binop_special_hs :: (RealFrac n,Floating n) => Int -> Maybe (n -> n -> n)
-binop_special_hs z = lookup (toEnum z) binop_hs_tbl
-
--- | Association table for 'Unary' to haskell function implementing operator.
-uop_hs_tbl :: (RealFrac n,Floating n) => [(Unary,n -> n)]
-uop_hs_tbl =
-    [(Neg,negate)
-    ,(Not,\z -> if z > 0 then 0 else 1)
-    ,(Abs,abs)
-    ,(Ceil,Math.sc3_ceiling)
-    ,(Floor,Math.sc3_floor)
-    ,(Squared,\z -> z * z)
-    ,(Cubed,\z -> z * z * z)
-    ,(Sqrt,sqrt)
-    ,(Recip,recip)
-    ,(MIDICPS,Math.midi_to_cps)
-    ,(CPSMIDI,Math.cps_to_midi)
-    ,(Sin,sin)
-    ,(Cos,cos)
-    ,(Tan,tan)]
-
--- | 'lookup' 'uop_hs_tbl' via 'toEnum'.
-uop_special_hs :: (RealFrac n,Floating n) => Int -> Maybe (n -> n)
-uop_special_hs z = lookup (toEnum z) uop_hs_tbl
-
--- The Eq and Ord classes in the Prelude require Bool, hence the name
--- mangling.  True is 1.0, False is 0.0
-
--- | Variant on Eq class, result is of the same type as the values compared.
-class (Eq a,Num a) => EqE a where
-    (==*) :: a -> a -> a
-    (==*) = Math.sc3_eq
-    (/=*) :: a -> a -> a
-    (/=*) = Math.sc3_neq
-
-instance EqE Int where
-instance EqE Integer where
-instance EqE Int32 where
-instance EqE Int64 where
-instance EqE Float where
-instance EqE Double where
-
-instance EqE UGen where
-    (==*) = mkBinaryOperator EQ_ (==*)
-    (/=*) = mkBinaryOperator NE (/=*)
-
--- | Variant on Ord class, result is of the same type as the values compared.
-class (Ord a,Num a) => OrdE a where
-    (<*) :: a -> a -> a
-    (<*) = Math.sc3_lt
-    (<=*) :: a -> a -> a
-    (<=*) = Math.sc3_lte
-    (>*) :: a -> a -> a
-    (>*) = Math.sc3_gt
-    (>=*) :: a -> a -> a
-    (>=*) = Math.sc3_gte
-
-instance OrdE Int
-instance OrdE Integer
-instance OrdE Int32
-instance OrdE Int64
-instance OrdE Float
-instance OrdE Double
-
-instance OrdE UGen where
-    (<*) = mkBinaryOperator LT_ Math.sc3_lt
-    (<=*) = mkBinaryOperator LE Math.sc3_lte
-    (>*) = mkBinaryOperator GT_ Math.sc3_gt
-    (>=*) = mkBinaryOperator GE Math.sc3_gte
-
--- | Variant of 'RealFrac' with non 'Integral' results.
-class RealFrac a => RealFracE a where
-  properFractionE :: a -> (a,a)
-  properFractionE = Math.sc3_properFraction
-  truncateE :: a -> a
-  truncateE = Math.sc3_truncate
-  roundE :: a -> a
-  roundE = Math.sc3_round
-  ceilingE :: a -> a
-  ceilingE = Math.sc3_ceiling
-  floorE :: a -> a
-  floorE = Math.sc3_floor
-
-instance RealFracE Float
-instance RealFracE Double
-
--- | 'UGen' form or 'Math.sc3_round_to'.
-roundTo :: UGen -> UGen -> UGen
-roundTo = mkBinaryOperator Round Math.sc3_round_to
-
-instance RealFracE UGen where
-    properFractionE = error "UGen.properFractionE"
-    truncateE = error "UGen.truncateE"
-    roundE i = roundTo i 1
-    ceilingE = mkUnaryOperator Ceil ceilingE
-    floorE = mkUnaryOperator Floor floorE
+dinf :: Type.UGen
+dinf = Type.constant (9e8 :: Type.Sample)
 
 -- | 'UGen' form of 'ceilingE'.
-ceil :: UGen -> UGen
-ceil = ceilingE
-
--- | Unary operator class.
---
--- > map (floor . (* 1e4) . dbAmp) [-90,-60,-30,0] == [0,10,316,10000]
-class (Floating a, Ord a) => UnaryOp a where
-    ampDb :: a -> a
-    ampDb = Math.amp_to_db
-    asFloat :: a -> a
-    asFloat = error "asFloat"
-    asInt :: a -> a
-    asInt = error "asInt"
-    cpsMIDI :: a -> a
-    cpsMIDI = Math.cps_to_midi
-    cpsOct :: a -> a
-    cpsOct = Math.cps_to_oct
-    cubed :: a -> a
-    cubed n = n * n * n
-    dbAmp :: a -> a
-    dbAmp = Math.db_to_amp
-    distort :: a -> a
-    distort = Math.sc3_distort
-    frac :: a -> a
-    frac = error "frac"
-    isNil :: a -> a
-    isNil a = if a == 0.0 then 0.0 else 1.0
-    log10 :: a -> a
-    log10 = logBase 10
-    log2 :: a -> a
-    log2 = logBase 2
-    midiCPS :: a -> a
-    midiCPS = Math.midi_to_cps
-    midiRatio :: a -> a
-    midiRatio = Math.midi_to_ratio
-    notE :: a -> a
-    notE a = if a > 0.0 then 0.0 else 1.0
-    notNil :: a -> a
-    notNil a = if a /= 0.0 then 0.0 else 1.0
-    octCPS :: a -> a
-    octCPS = Math.oct_to_cps
-    ramp_ :: a -> a
-    ramp_ _ = error "ramp_"
-    ratioMIDI :: a -> a
-    ratioMIDI = Math.ratio_to_midi
-    softClip :: a -> a
-    softClip = Math.sc3_softclip
-    squared :: a -> a
-    squared = \z -> z * z
-
-instance UnaryOp Float where
-instance UnaryOp Double where
-
-instance UnaryOp UGen where
-    ampDb = mkUnaryOperator AmpDb ampDb
-    asFloat = mkUnaryOperator AsFloat asFloat
-    asInt = mkUnaryOperator AsInt asInt
-    cpsMIDI = mkUnaryOperator CPSMIDI cpsMIDI
-    cpsOct = mkUnaryOperator CPSOct cpsOct
-    cubed = mkUnaryOperator Cubed cubed
-    dbAmp = mkUnaryOperator DbAmp dbAmp
-    distort = mkUnaryOperator Distort distort
-    frac = mkUnaryOperator Frac frac
-    isNil = mkUnaryOperator IsNil isNil
-    log10 = mkUnaryOperator Log10 log10
-    log2 = mkUnaryOperator Log2 log2
-    midiCPS = mkUnaryOperator MIDICPS midiCPS
-    midiRatio = mkUnaryOperator MIDIRatio midiRatio
-    notE = mkUnaryOperator Not notE
-    notNil = mkUnaryOperator NotNil notNil
-    octCPS = mkUnaryOperator OctCPS octCPS
-    ramp_ = mkUnaryOperator Ramp_ ramp_
-    ratioMIDI = mkUnaryOperator RatioMIDI ratioMIDI
-    softClip = mkUnaryOperator SoftClip softClip
-    squared = mkUnaryOperator Squared squared
-
--- | Binary operator class.
-class (Floating a,RealFrac a, Ord a) => BinaryOp a where
-    absDif :: a -> a -> a
-    absDif a b = abs (a - b)
-    amClip :: a -> a -> a
-    amClip a b = if b <= 0 then 0 else a * b
-    atan2E :: a -> a -> a
-    atan2E a b = atan (b/a)
-    clip2 :: a -> a -> a
-    clip2 a b = Math.sc3_clip a (-b) b
-    difSqr :: a -> a -> a
-    difSqr = Math.sc3_dif_sqr
-    excess :: a -> a -> a
-    excess a b = a - Math.sc3_clip a (-b) b
-    exprandRange :: a -> a -> a
-    exprandRange = error "exprandRange"
-    fill :: a -> a -> a
-    fill = error "fill"
-    firstArg :: a -> a -> a
-    firstArg a _ = a
-    fold2 :: a -> a -> a
-    fold2 a b = Math.sc3_fold a (-b) b
-    gcdE :: a -> a -> a
-    gcdE = error "gcdE"
-    hypot :: a -> a -> a
-    hypot = Math.sc3_hypot
-    hypotx :: a -> a -> a
-    hypotx = Math.sc3_hypotx
-    iDiv :: a -> a -> a
-    iDiv = Math.sc3_idiv
-    lcmE :: a -> a -> a
-    lcmE = error "lcmE"
-    modE :: a -> a -> a
-    modE = error "modE"
-    randRange :: a -> a -> a
-    randRange = error "randRange"
-    ring1 :: a -> a -> a
-    ring1 a b = a * b + a
-    ring2 :: a -> a -> a
-    ring2 a b = a * b + a + b
-    ring3 :: a -> a -> a
-    ring3 a b = a * a * b
-    ring4 :: a -> a -> a
-    ring4 a b = a * a * b - a * b * b
-    roundUp :: a -> a -> a
-    roundUp = error "roundUp"
-    scaleNeg :: a -> a -> a
-    scaleNeg a b = (abs a - a) * b' + a where b' = 0.5 * b + 0.5
-    sqrDif :: a -> a -> a
-    sqrDif a b = (a-b) * (a-b)
-    sqrSum :: a -> a -> a
-    sqrSum a b = (a+b) * (a+b)
-    sumSqr :: a -> a -> a
-    sumSqr a b = (a*a) + (b*b)
-    thresh :: a -> a -> a
-    thresh a b = if a <  b then 0 else a
-    trunc :: a -> a -> a
-    trunc = error "trunc"
-    wrap2 :: a -> a -> a
-    wrap2 = error "wrap2"
-
-instance BinaryOp Float where
-    fold2 a b = Math.sc3_fold a (-b) b
-    modE = F.mod'
-    roundUp a b = if b == 0 then a else ceilingE (a/b + 0.5) * b
-    wrap2 a b = Math.sc3_wrap_ni a (-b) b
-
-instance BinaryOp Double where
-    fold2 a b = Math.sc3_fold a (-b) b
-    modE = F.mod'
-    roundUp a b = if b == 0 then a else ceilingE (a/b + 0.5) * b
-    wrap2 a b = Math.sc3_wrap_ni a (-b) b
-
-instance BinaryOp UGen where
-    iDiv = mkBinaryOperator IDiv iDiv
-    modE = mkBinaryOperator Mod F.mod'
-    lcmE = mkBinaryOperator LCM lcmE
-    gcdE = mkBinaryOperator GCD gcdE
-    roundUp = mkBinaryOperator RoundUp roundUp
-    trunc = mkBinaryOperator Trunc trunc
-    atan2E = mkBinaryOperator Atan2 atan2E
-    hypot = mkBinaryOperator Hypot hypot
-    hypotx = mkBinaryOperator Hypotx hypotx
-    fill = mkBinaryOperator Fill fill
-    ring1 = mkBinaryOperator Ring1 ring1
-    ring2 = mkBinaryOperator Ring2 ring2
-    ring3 = mkBinaryOperator Ring3 ring3
-    ring4 = mkBinaryOperator Ring4 ring4
-    difSqr = mkBinaryOperator DifSqr difSqr
-    sumSqr = mkBinaryOperator SumSqr sumSqr
-    sqrSum = mkBinaryOperator SqrSum sqrSum
-    sqrDif = mkBinaryOperator SqrDif sqrDif
-    absDif = mkBinaryOperator AbsDif absDif
-    thresh = mkBinaryOperator Thresh thresh
-    amClip = mkBinaryOperator AMClip amClip
-    scaleNeg = mkBinaryOperator ScaleNeg scaleNeg
-    clip2 = mkBinaryOperator Clip2 clip2
-    excess = mkBinaryOperator Excess excess
-    fold2 = mkBinaryOperator Fold2 fold2
-    wrap2 = mkBinaryOperator Wrap2 wrap2
-    firstArg = mkBinaryOperator FirstArg firstArg
-    randRange = mkBinaryOperator RandRange randRange
-    exprandRange = mkBinaryOperator ExpRandRange exprandRange
-
--- | MulAdd operator class.
-class Num a => MulAdd a where
-    mul_add :: a -> a -> a -> a
-    mul_add i m a = i * m + a
-
-instance MulAdd UGen where mul_add = mulAdd
-instance MulAdd Float where
-instance MulAdd Double where
-
--- | Map from one linear range to another linear range.
-linlin_ma :: (Fractional a,MulAdd a) => a -> a -> a -> a -> a -> a
-linlin_ma i sl sr dl dr = let (m,a) = Math.linlin_muladd sl sr dl dr in mul_add i m a
-
--- | Scale uni-polar (0,1) input to linear (l,r) range
-urange_ma :: (Fractional a,MulAdd a) => a -> a -> a -> a
-urange_ma l r i = let m = r - l in mul_add i m l
-
--- | Scale bi-polar (-1,1) input to linear (l,r) range.  Note that the
--- argument order is not the same as 'linLin'.
-range_ma :: (Fractional a,MulAdd a) => a -> a -> a -> a
-range_ma l r i = let (m,a) = Math.range_muladd l r in mul_add i m a
+ceil :: Type.UGen -> Type.UGen
+ceil = Operator.ceilingE
diff --git a/Sound/SC3/UGen/Math/Composite.hs b/Sound/SC3/UGen/Math/Composite.hs
--- a/Sound/SC3/UGen/Math/Composite.hs
+++ b/Sound/SC3/UGen/Math/Composite.hs
@@ -1,7 +1,7 @@
 -- | Non-primitve math UGens.
 module Sound.SC3.UGen.Math.Composite where
 
-import Sound.SC3.UGen.Math
+import Sound.SC3.Common.Math.Operator
 import Sound.SC3.UGen.Type
 import Sound.SC3.UGen.UGen
 
@@ -16,7 +16,7 @@
 ugen_integral_and_fractional_parts n =
     let gt_eq_0 = let n' = floorE n in mce2 n' (n - n')
         lt_0 = let n' = ceilingE n in mce2 n' (n - n')
-    in ugen_if (n >=* 0) gt_eq_0 lt_0
+    in ugen_if (n `greater_than_or_equal_to` 0) gt_eq_0 lt_0
 
 -- | Fractional midi into integral midi and cents detune.
 --
diff --git a/Sound/SC3/UGen/Name.hs b/Sound/SC3/UGen/Name.hs
--- a/Sound/SC3/UGen/Name.hs
+++ b/Sound/SC3/UGen/Name.hs
@@ -1,13 +1,16 @@
--- | Functions to normalise UGen names.  @SC3@ UGen names are
--- capitalised, @hsc3@ cannot use the same names for UGen constructor
--- functions.  The functions here are heuristics, and are likely only
--- partial.
+{- | Functions to normalise UGen names.
+
+@SC3@ UGen names are capitalised.
+@hsc3@ cannot use these names for UGen constructor functions.
+Haskell names are given by lower-casing until the first word edge.
+Lisp names are given by lower-casing everything and adding hyphens before edges.
+-}
 module Sound.SC3.UGen.Name where
 
 import Data.Char {- base -}
 import Data.List.Split {- split -}
 
-import Sound.SC3.UGen.Rate {- hsc3 -}
+import Sound.SC3.Common.Rate {- hsc3 -}
 
 {-
 import qualified Sound.SC3.Common.Base {- hsc3 -}
@@ -23,14 +26,15 @@
 sc3_name_edges_plain :: String -> [Bool]
 sc3_name_edges_plain = map (not . isLower)
 
--- | Find non-initial SC3 name edges.
---
--- > sc3_name_edges "SinOsc" == [False,False,False,True,False,False]
--- > sc3_name_edges "FFT" == [False,False,False]
--- > sc3_name_edges "DFM1" == [False,False,False,False]
--- > sc3_name_edges "PV_Add" == [False,False,False,True,False,False]
--- > sc3_name_edges "A2K" == [False,False,False]
--- > sc3_name_edges "Lag2UD" == [False,False,False,True,True,True]
+{- | Find non-initial SC3 name edges.
+
+> sc3_name_edges "SinOsc" == [False,False,False,True,False,False]
+> sc3_name_edges "FFT" == [False,False,False]
+> sc3_name_edges "DFM1" == [False,False,False,False]
+> sc3_name_edges "PV_Add" == [False,False,False,True,False,False]
+> sc3_name_edges "A2K" == [False,False,False]
+> sc3_name_edges "Lag2UD" == [False,False,False,True,True,True]
+-}
 sc3_name_edges :: String -> [Bool]
 sc3_name_edges s =
   let (p,q) = span (== True) (sc3_name_edges_plain s)
@@ -39,22 +43,24 @@
      then replicate n False ++ q
      else replicate (n - 1) False ++ [True] ++ q
 
--- | Convert from SC3 name to HS style name.
---
--- > s = words "SinOsc LFSaw FFT PV_Add AllpassN BHiPass BinaryOpUGen HPZ1 RLPF TGrains DFM1 FBSineC A2K Lag2UD IIRFilter FMGrainB"
--- > l = words "sinOsc lfSaw fft pv_Add allpassN bHiPass binaryOpUGen hpz1 rlpf tGrains dfm1 fbSineC a2k lag2UD iirFilter fmGrainB"
--- > map sc3_name_to_hs_name s == l
+{- | Convert from SC3 name to HS style name.
+
+> s = words "SinOsc LFSaw FFT PV_Add AllpassN BHiPass BinaryOpUGen HPZ1 RLPF TGrains DFM1 FBSineC A2K Lag2UD IIRFilter FMGrainB"
+> l = words "sinOsc lfSaw fft pv_Add allpassN bHiPass binaryOpUGen hpz1 rlpf tGrains dfm1 fbSineC a2k lag2UD iirFilter fmGrainB"
+> map sc3_name_to_hs_name s == l
+-}
 sc3_name_to_hs_name :: String -> String
 sc3_name_to_hs_name s =
     let f (c,e) = if e then toUpper c else c
         s_lc = map toLower s
     in map f (zip s_lc (sc3_name_edges s))
 
--- | Convert from SC3 name to Lisp style name.
---
--- > s = words "SinOsc LFSaw FFT PV_Add AllpassN BHiPass BinaryOpUGen HPZ1 RLPF TGrains DFM1"
--- > l = words "sin-osc lf-saw fft pv-add allpass-n b-hi-pass binary-op-u-gen hpz1 rlpf t-grains dfm1"
--- > map sc3_name_to_lisp_name s == l
+{- | Convert from SC3 name to Lisp style name.
+
+> s = words "SinOsc LFSaw FFT PV_Add AllpassN BHiPass BinaryOpUGen HPZ1 RLPF TGrains DFM1"
+> l = words "sin-osc lf-saw fft pv-add allpass-n b-hi-pass binary-op-u-gen hpz1 rlpf t-grains dfm1"
+> map sc3_name_to_lisp_name s == l
+-}
 sc3_name_to_lisp_name :: String -> String
 sc3_name_to_lisp_name s =
     let f (c,e) = if e then ['-',c] else if c == '_' then [] else [c]
diff --git a/Sound/SC3/UGen/Operator.hs b/Sound/SC3/UGen/Operator.hs
deleted file mode 100644
--- a/Sound/SC3/UGen/Operator.hs
+++ /dev/null
@@ -1,211 +0,0 @@
--- | Enumerations of the unary and binary math unit generators.  Names
--- that conflict with existing names have a @_@ suffix.
-module Sound.SC3.UGen.Operator where
-
-import Control.Monad {- base -}
-import Data.Maybe {- base -}
-
-import Sound.SC3.Common.Base {- hsc3 -}
-
--- * Unary
-
--- | Enumeration of @SC3@ unary operator UGens.
-data Unary  = Neg
-            | Not
-            | IsNil
-            | NotNil
-            | BitNot
-            | Abs
-            | AsFloat
-            | AsInt
-            | Ceil
-            | Floor
-            | Frac
-            | Sign
-            | Squared
-            | Cubed
-            | Sqrt
-            | Exp
-            | Recip
-            | MIDICPS
-            | CPSMIDI
-            | MIDIRatio
-            | RatioMIDI
-            | DbAmp
-            | AmpDb
-            | OctCPS
-            | CPSOct
-            | Log
-            | Log2
-            | Log10
-            | Sin
-            | Cos
-            | Tan
-            | ArcSin
-            | ArcCos
-            | ArcTan
-            | SinH
-            | CosH
-            | TanH
-            | Rand_ -- UGen
-            | Rand2
-            | LinRand_ -- UGen
-            | BiLinRand
-            | Sum3Rand
-            | Distort
-            | SoftClip
-            | Coin
-            | DigitValue
-            | Silence
-            | Thru
-            | RectWindow
-            | HanWindow
-            | WelchWindow
-            | TriWindow
-            | Ramp_ -- UGen
-            | SCurve
-              deriving (Eq,Show,Enum,Bounded,Read)
-
--- | Type-specialised 'parse_enum'.
-parse_unary :: Case_Rule -> String -> Maybe Unary
-parse_unary = parse_enum
-
--- | Table of symbolic names for standard unary operators.
-unaryTable :: [(Unary,String)]
-unaryTable = [] -- (Neg,"-")
-
--- | Lookup possibly symbolic name for standard unary operators.
-unaryName :: Int -> String
-unaryName n =
-    let e = toEnum n
-    in fromMaybe (show e) (lookup e unaryTable)
-
--- | Given name of unary operator derive index.
---
--- > mapMaybe (unaryIndex CI) (words "NEG CUBED") == [0,13]
--- > unaryIndex CS "SinOsc" == Nothing
-unaryIndex :: Case_Rule -> String -> Maybe Int
-unaryIndex cr nm =
-    let ix = rlookup_str cr nm unaryTable
-        ix' = parse_unary cr nm
-    in fmap fromEnum (mplus ix' ix)
-
--- | 'isJust' of 'unaryIndex'.
---
--- > map (is_unary CI) (words "ABS MIDICPS NEG")
--- > map (is_unary CI) (words "- RAND")
-is_unary :: Case_Rule -> String -> Bool
-is_unary cr = isJust . unaryIndex cr
-
--- * Binary
-
--- | Enumeration of @SC3@ unary operator UGens.
---
--- > map show [minBound :: Binary .. maxBound]
-data Binary = Add -- 0
-            | Sub -- 1
-            | Mul -- 2
-            | IDiv
-            | FDiv -- 4
-            | Mod -- 5
-            | EQ_ -- 6
-            | NE -- 7
-            | LT_ -- 8
-            | GT_ -- 9
-            | LE -- 10
-            | GE -- 11
-            | Min -- 12
-            | Max
-            | BitAnd
-            | BitOr
-            | BitXor
-            | LCM
-            | GCD
-            | Round
-            | RoundUp
-            | Trunc
-            | Atan2
-            | Hypot
-            | Hypotx
-            | Pow -- 25
-            | ShiftLeft
-            | ShiftRight
-            | UnsignedShift
-            | Fill
-            | Ring1
-            | Ring2
-            | Ring3
-            | Ring4
-            | DifSqr
-            | SumSqr
-            | SqrSum
-            | SqrDif
-            | AbsDif
-            | Thresh
-            | AMClip
-            | ScaleNeg
-            | Clip2
-            | Excess
-            | Fold2
-            | Wrap2
-            | FirstArg
-            | RandRange
-            | ExpRandRange
-              deriving (Eq,Show,Enum,Bounded,Read)
-
--- | Type-specialised 'parse_enum'.
-parse_binary :: Case_Rule -> String -> Maybe Binary
-parse_binary = parse_enum
-
--- | Table of symbolic names for standard binary operators.
-binaryTable :: [(Binary,String)]
-binaryTable =
-    [(Add,"+")
-    ,(Sub,"-")
-    ,(Mul,"*")
-    ,(FDiv,"/")
-    ,(Mod,"%")
-    ,(EQ_,"==")
-    ,(NE,"/=")
-    ,(LT_,"<")
-    ,(GT_,">")
-    ,(LE,"<=")
-    ,(GE,">=")
-    ,(Pow,"**")]
-
--- | Lookup possibly symbolic name for standard binary operators.
---
--- > map binaryName [1,2,8,12] == ["-","*","<","Min"]
-binaryName :: Int -> String
-binaryName n =
-    let e = toEnum n
-    in fromMaybe (show e) (lookup e binaryTable)
-
--- | Given name of binary operator derive index.
---
--- > mapMaybe (binaryIndex CI) (words "* MUL RING1") == [2,2,30]
--- > binaryIndex CI "SINOSC" == Nothing
-binaryIndex :: Case_Rule -> String -> Maybe Int
-binaryIndex cr nm =
-    let ix = rlookup_str cr nm binaryTable
-        ix' = parse_binary cr nm
-    in fmap fromEnum (mplus ix' ix)
-
--- | 'isJust' of 'binaryIndex'.
---
--- > map (is_binary CI) (words "== > % TRUNC MAX")
-is_binary :: Case_Rule -> String -> Bool
-is_binary cr = isJust . binaryIndex cr
-
--- * Operator
-
--- | Order of lookup: binary then unary.
---
--- > map (resolve_operator Sound.SC3.Common.Base.CI) (words "+ - ADD SUB NEG")
-resolve_operator :: Case_Rule -> String -> (String,Maybe Int)
-resolve_operator cr nm =
-    case binaryIndex cr nm of
-      Just sp -> ("BinaryOpUGen",Just sp)
-      Nothing -> case unaryIndex cr nm of
-                   Just sp -> ("UnaryOpUGen",Just sp)
-                   _ -> (nm,Nothing)
diff --git a/Sound/SC3/UGen/Optimise.hs b/Sound/SC3/UGen/Optimise.hs
--- a/Sound/SC3/UGen/Optimise.hs
+++ b/Sound/SC3/UGen/Optimise.hs
@@ -3,22 +3,11 @@
 
 import System.Random {- random -}
 
-import Sound.SC3.UGen.Math
-import Sound.SC3.UGen.Rate
+import Sound.SC3.Common.Math.Operator
+import Sound.SC3.Common.Rate
 import Sound.SC3.UGen.Type
 import Sound.SC3.UGen.UGen
 
--- | MulAdd optimiser, applicable at any UGen.
---
--- > import Sound.SC3
--- > g1 = mul_add_optimise (sinOsc AR 440 0 * 0.1 + 0.05)
--- > g2 = mul_add_optimise (0.05 + sinOsc AR 440 0 * 0.1)
-mul_add_optimise :: UGen -> UGen
-mul_add_optimise u =
-  case u of
-    Primitive_U (Primitive _ "BinaryOpUGen" _ [_] (Special 0) NoId) -> mul_add_optimise_direct u
-    _ -> u
-
 -- | Constant form of 'rand' UGen.
 c_rand :: Random a => Int -> a -> a -> a
 c_rand z l r = fst (randomR (l,r) (mkStdGen z))
@@ -49,7 +38,7 @@
                         Constant_U (Constant (c_irand z l r))
                     _ -> u
               _ -> u
-    in ugenTraverse f
+    in ugenTraverse (const False) f
 
 -- | Optimise 'UGen' graph by re-writing binary operators with
 -- 'Constant' inputs.  The standard graph constructors already do
@@ -85,7 +74,7 @@
                           _ -> u
                     _ -> u
               _ -> u
-    in ugenTraverse f
+    in ugenTraverse (const False) f
 
 -- | 'u_constant' of 'ugen_optimise_ir_rand'.
 constant_opt :: UGen -> Maybe Sample
diff --git a/Sound/SC3/UGen/PP.hs b/Sound/SC3/UGen/PP.hs
--- a/Sound/SC3/UGen/PP.hs
+++ b/Sound/SC3/UGen/PP.hs
@@ -18,9 +18,10 @@
 ugen_concise_pp :: UGen -> String
 ugen_concise_pp u =
     let prim_pp (Primitive _ nm _ _ sp _) = ugen_user_name nm sp
+        k = 5
     in case u of
-         Constant_U (Constant n) -> real_pp n
-         Control_U (Control _ _ nm def _ _) -> nm ++ "=" ++ real_pp def
+         Constant_U (Constant n) -> real_pp k n
+         Control_U (Control _ _ nm def _ _) -> nm ++ "=" ++ real_pp k def
          Label_U (Label s) -> bracketed ('"','"') s
          Primitive_U p -> prim_pp p
          Proxy_U (Proxy p n) -> prim_pp p ++ "@" ++ show n
diff --git a/Sound/SC3/UGen/Plain.hs b/Sound/SC3/UGen/Plain.hs
--- a/Sound/SC3/UGen/Plain.hs
+++ b/Sound/SC3/UGen/Plain.hs
@@ -9,8 +9,8 @@
 module Sound.SC3.UGen.Plain where
 
 import Sound.SC3.Common.Base
-import Sound.SC3.UGen.Operator
-import Sound.SC3.UGen.Rate
+import Sound.SC3.Common.Math.Operator
+import Sound.SC3.Common.Rate
 import Sound.SC3.UGen.Type
 
 -- | Variant of 'mkUGen'.
diff --git a/Sound/SC3/UGen/Protect.hs b/Sound/SC3/UGen/Protect.hs
deleted file mode 100644
--- a/Sound/SC3/UGen/Protect.hs
+++ /dev/null
@@ -1,58 +0,0 @@
--- | Functions to re-write assigned node identifiers at UGen graphs.
--- Used carefully it allows for composition of sub-graphs with psuedo-random nodes.
-module Sound.SC3.UGen.Protect where
-
-import Sound.SC3.Common.UId
-import Sound.SC3.UGen.Type
-import Sound.SC3.UGen.UGen
-
-{-
--- | Collect Ids at UGen graph
-ugenIds :: UGen -> [UGenId]
-ugenIds =
-    let f u = case u of
-                Primitive_U p -> [ugenId p]
-                _ -> []
-    in ugenFoldr ((++) . f) []
--}
-
--- | Replace UId /i/ at /z/ with /(e,i)/.
-edit_ugenid :: ID a => a -> UGenId -> UGenId
-edit_ugenid e z =
-    case z of
-      NoId -> NoId
-      UId i -> UId (resolveID (e,i))
-
--- | 'edit_ugenid' of /e/ at all 'Primitive_U' of /u/.
-uprotect :: ID a => a -> UGen -> UGen
-uprotect e =
-    let f u = case u of
-                Primitive_U p -> Primitive_U (p {ugenId = edit_ugenid e (ugenId p)})
-                _ -> u
-    in ugenTraverse f
-
--- | Variant of 'uprotect' with subsequent identifiers derived by
--- incrementing initial identifier.
-uprotect_seq :: ID a => a -> [UGen] -> [UGen]
-uprotect_seq e =
-    let n = map (+ resolveID e) [1..]
-    in zipWith uprotect n
-
--- | Make /n/ instances of 'UGen' with protected identifiers.
-uclone_seq :: ID a => a -> Int -> UGen -> [UGen]
-uclone_seq e n = uprotect_seq e . replicate n
-
--- | 'mce' of 'uclone_seq'.
-uclone :: ID a => a -> Int -> UGen -> UGen
-uclone e n = mce . uclone_seq e n
-
--- | Left to right UGen function composition with 'UGenId' protection.
-ucompose :: ID a => a -> [UGen -> UGen] -> UGen -> UGen
-ucompose e xs =
-    let go [] u = u
-        go ((f,k):f') u = go f' (uprotect k (f u))
-    in go (zip xs [resolveID e ..])
-
--- | Make /n/ sequential instances of `f' with protected Ids.
-useq :: ID a => a -> Int -> (UGen -> UGen) -> UGen -> UGen
-useq e n f = ucompose e (replicate n f)
diff --git a/Sound/SC3/UGen/Rate.hs b/Sound/SC3/UGen/Rate.hs
deleted file mode 100644
--- a/Sound/SC3/UGen/Rate.hs
+++ /dev/null
@@ -1,70 +0,0 @@
--- | Operating rate definitions and utilities.
-module Sound.SC3.UGen.Rate where
-
-import Data.Char {- base -}
-import Data.Function {- base -}
-
--- | Operating rate of unit generator.
-data Rate = IR | KR | AR | DR
-            deriving (Eq,Enum,Bounded,Show,Read)
-
-instance Ord Rate where
-    compare = compare `on` rate_ord
-
--- | Integer rate identifier, as required for scsynth bytecode.
-rateId :: Rate -> Int
-rateId = fromEnum
-
--- | Rates as ordered for filter rate selection.
-rate_ord :: Rate -> Int
-rate_ord r =
-    case r of
-      IR -> 0
-      KR -> 1
-      AR -> 2
-      DR -> 3 -- ?
-
--- | Color identifiers for each 'Rate'.
-rate_color :: Rate -> String
-rate_color r =
-    case r of
-      AR -> "black"
-      KR -> "blue"
-      IR -> "yellow"
-      DR -> "red"
-
--- | Set of all 'Rate' values.
-all_rates :: [Rate]
-all_rates = [minBound .. maxBound]
-
--- | Case insensitive parser for rate.
---
--- > Data.Maybe.mapMaybe rate_parse (words "ar kR IR Dr") == [AR,KR,IR,DR]
-rate_parse :: String -> Maybe Rate
-rate_parse r =
-    case map toUpper r of
-      "AR" -> Just AR
-      "KR" -> Just KR
-      "IR" -> Just IR
-      "DR" -> Just DR
-      _ -> Nothing
-
--- * Control rates
-
--- | Enumeration of the four operating rates for controls.
---   IR = initialisation rate, KR = control rate, TR = trigger rate, AR = audio rate.
-data K_Type = K_IR | K_KR | K_TR | K_AR
-             deriving (Eq,Show,Ord)
-
--- | Determine class of control given 'Rate' and /trigger/ status.
-ktype :: Rate -> Bool -> K_Type
-ktype r tr =
-    if tr
-    then case r of
-           KR -> K_TR
-           _ -> error "ktype: non KR trigger control"
-    else case r of
-           IR -> K_IR
-           KR -> K_KR
-           AR -> K_AR
-           DR -> error "ktype: DR control"
diff --git a/Sound/SC3/UGen/Type.hs b/Sound/SC3/UGen/Type.hs
--- a/Sound/SC3/UGen/Type.hs
+++ b/Sound/SC3/UGen/Type.hs
@@ -2,15 +2,17 @@
 module Sound.SC3.UGen.Type where
 
 import Data.Bits {- base -}
+import Data.Either {- base -}
+import qualified Data.Fixed as F {- base -}
 import Data.List {- base -}
 import Data.Maybe {- base -}
-import Safe {- safe -}
+import qualified Safe {- safe -}
 import System.Random {- random -}
 
-import Sound.SC3.Common.Math
+import qualified Sound.SC3.Common.Math as Math
+import Sound.SC3.Common.Math.Operator
+import Sound.SC3.Common.Rate
 import Sound.SC3.UGen.MCE
-import Sound.SC3.UGen.Operator
-import Sound.SC3.UGen.Rate
 
 -- * Basic types
 
@@ -105,11 +107,89 @@
           | MRG_U MRG
             deriving (Eq,Read,Show)
 
+instance EqE UGen where
+    equal_to = mkBinaryOperator EQ_ Math.sc3_eq
+    not_equal_to = mkBinaryOperator NE Math.sc3_neq
+
+instance OrdE UGen where
+    less_than = mkBinaryOperator LT_ Math.sc3_lt
+    less_than_or_equal_to = mkBinaryOperator LE Math.sc3_lte
+    greater_than = mkBinaryOperator GT_ Math.sc3_gt
+    greater_than_or_equal_to = mkBinaryOperator GE Math.sc3_gte
+
+-- | 'UGen' form or 'Math.sc3_round_to'.
+roundTo :: UGen -> UGen -> UGen
+roundTo = mkBinaryOperator Round Math.sc3_round_to
+
+instance RealFracE UGen where
+    properFractionE = error "UGen.properFractionE"
+    truncateE = error "UGen.truncateE"
+    roundE i = roundTo i 1
+    ceilingE = mkUnaryOperator Ceil ceilingE
+    floorE = mkUnaryOperator Floor floorE
+
+
+instance UnaryOp UGen where
+    ampDb = mkUnaryOperator AmpDb ampDb
+    asFloat = mkUnaryOperator AsFloat asFloat
+    asInt = mkUnaryOperator AsInt asInt
+    cpsMIDI = mkUnaryOperator CPSMIDI cpsMIDI
+    cpsOct = mkUnaryOperator CPSOct cpsOct
+    cubed = mkUnaryOperator Cubed cubed
+    dbAmp = mkUnaryOperator DbAmp dbAmp
+    distort = mkUnaryOperator Distort distort
+    frac = mkUnaryOperator Frac frac
+    isNil = mkUnaryOperator IsNil isNil
+    log10 = mkUnaryOperator Log10 log10
+    log2 = mkUnaryOperator Log2 log2
+    midiCPS = mkUnaryOperator MIDICPS midiCPS
+    midiRatio = mkUnaryOperator MIDIRatio midiRatio
+    notE = mkUnaryOperator Not notE
+    notNil = mkUnaryOperator NotNil notNil
+    octCPS = mkUnaryOperator OctCPS octCPS
+    ramp_ = mkUnaryOperator Ramp_ ramp_
+    ratioMIDI = mkUnaryOperator RatioMIDI ratioMIDI
+    softClip = mkUnaryOperator SoftClip softClip
+    squared = mkUnaryOperator Squared squared
+
+instance BinaryOp UGen where
+    iDiv = mkBinaryOperator IDiv iDiv
+    modE = mkBinaryOperator Mod F.mod'
+    lcmE = mkBinaryOperator LCM lcmE
+    gcdE = mkBinaryOperator GCD gcdE
+    roundUp = mkBinaryOperator RoundUp roundUp
+    trunc = mkBinaryOperator Trunc trunc
+    atan2E = mkBinaryOperator Atan2 atan2E
+    hypot = mkBinaryOperator Hypot hypot
+    hypotx = mkBinaryOperator Hypotx hypotx
+    fill = mkBinaryOperator Fill fill
+    ring1 = mkBinaryOperator Ring1 ring1
+    ring2 = mkBinaryOperator Ring2 ring2
+    ring3 = mkBinaryOperator Ring3 ring3
+    ring4 = mkBinaryOperator Ring4 ring4
+    difSqr = mkBinaryOperator DifSqr difSqr
+    sumSqr = mkBinaryOperator SumSqr sumSqr
+    sqrSum = mkBinaryOperator SqrSum sqrSum
+    sqrDif = mkBinaryOperator SqrDif sqrDif
+    absDif = mkBinaryOperator AbsDif absDif
+    thresh = mkBinaryOperator Thresh thresh
+    amClip = mkBinaryOperator AMClip amClip
+    scaleNeg = mkBinaryOperator ScaleNeg scaleNeg
+    clip2 = mkBinaryOperator Clip2 clip2
+    excess = mkBinaryOperator Excess excess
+    fold2 = mkBinaryOperator Fold2 fold2
+    wrap2 = mkBinaryOperator Wrap2 wrap2
+    firstArg = mkBinaryOperator FirstArg firstArg
+    randRange = mkBinaryOperator RandRange randRange
+    exprandRange = mkBinaryOperator ExpRandRange exprandRange
+
+--instance MulAdd UGen where mul_add = mulAdd
+
 -- * Parser
 
 -- | 'constant' of 'parse_double'.
 parse_constant :: String -> Maybe UGen
-parse_constant = fmap constant . parse_double
+parse_constant = fmap constant . Math.parse_double
 
 -- * Accessors
 
@@ -309,25 +389,34 @@
       Constant_U _ -> u
       _ -> error "proxify: illegal ugen"
 
+-- | Filters with DR inputs run at KR.  This is a little unfortunate,
+-- it'd be nicer if the rate in this circumstance could be given.
+mk_ugen_select_rate :: String -> [UGen] -> [Rate] -> Either Rate [Int] -> Rate
+mk_ugen_select_rate nm h rs r =
+  let r' = either id (maximum . map (rateOf . Safe.atNote ("mkUGen: " ++ nm) h)) r
+  in if isRight r && r' == DR && DR `notElem` rs
+     then if KR `elem` rs then KR else error "mkUGen: DR input to non-KR filter"
+     else if r' `elem` rs || r' == DR
+          then r'
+          else error ("mkUGen: rate restricted: " ++ show (r,r',rs,nm))
+
 -- | Construct proxied and multiple channel expanded UGen.
 --
 -- cf = constant function, rs = rate set, r = rate, nm = name, i =
--- inputs, o = outputs.
+-- inputs, i_mce = list of MCE inputs, o = outputs.
 mkUGen :: Maybe ([Sample] -> Sample) -> [Rate] -> Either Rate [Int] ->
           String -> [UGen] -> Maybe [UGen] -> Int -> Special -> UGenId -> UGen
 mkUGen cf rs r nm i i_mce o s z =
     let i' = maybe i ((i ++) . concatMap mceChannels) i_mce
-        f h = let r' = either id (maximum . map (rateOf . atNote ("mkUGen: " ++ nm) h)) r
+        f h = let r' = mk_ugen_select_rate nm h rs r
                   o' = replicate o r'
                   u = Primitive_U (Primitive r' nm h o' s z)
-              in if r' `elem` rs
-                 then case cf of
-                        Just cf' ->
-                            if all isConstant h
-                            then constant (cf' (mapMaybe u_constant h))
-                            else u
-                        Nothing -> u
-                 else error ("mkUGen: rate restricted: " ++ show (r,rs,nm))
+              in case cf of
+                   Just cf' ->
+                     if all isConstant h
+                     then constant (cf' (mapMaybe u_constant h))
+                     else u
+                   Nothing -> u
     in proxify (mceBuild f (map checkInput i'))
 
 -- * Operators
@@ -339,13 +428,13 @@
     in mkUGen (Just f) all_rates (Right ix) c i Nothing 1 (Special s) NoId
 
 -- | Unary math constructor.
-mkUnaryOperator :: Unary -> (Sample -> Sample) -> UGen -> UGen
+mkUnaryOperator :: SC3_Unary_Op -> (Sample -> Sample) -> UGen -> UGen
 mkUnaryOperator i f a =
     let g [x] = f x
         g _ = error "mkUnaryOperator: non unary input"
     in mkOperator g "UnaryOpUGen" [a] (fromEnum i)
 
--- | Binary math constructor with constant optimization.
+-- | Binary math constructor with constant optimisation.
 --
 -- > let o = sinOsc AR 440 0
 --
@@ -354,10 +443,10 @@
 -- > o - 0 == o && 0 - o /= o
 -- > o / 1 == o && 1 / o /= o
 -- > o ** 1 == o && o ** 2 /= o
-mkBinaryOperator_optimize_constants :: Binary -> (Sample -> Sample -> Sample) ->
+mkBinaryOperator_optimise_constants :: SC3_Binary_Op -> (Sample -> Sample -> Sample) ->
                                        (Either Sample Sample -> Bool) ->
                                        UGen -> UGen -> UGen
-mkBinaryOperator_optimize_constants i f o a b =
+mkBinaryOperator_optimise_constants i f o a b =
    let g [x,y] = f x y
        g _ = error "mkBinaryOperator: non binary input"
        r = case (a,b) of
@@ -369,7 +458,7 @@
    in fromMaybe (mkOperator g "BinaryOpUGen" [a, b] (fromEnum i)) r
 
 -- | Plain (non-optimised) binary math constructor.
-mkBinaryOperator :: Binary -> (Sample -> Sample -> Sample) -> UGen -> UGen -> UGen
+mkBinaryOperator :: SC3_Binary_Op -> (Sample -> Sample -> Sample) -> UGen -> UGen -> UGen
 mkBinaryOperator i f a b =
    let g [x,y] = f x y
        g _ = error "mkBinaryOperator: non binary input"
@@ -377,22 +466,62 @@
 
 -- * Numeric instances
 
+-- | Is /u/ a binary math operator with SPECIAL of /k/.
+is_math_binop :: Int -> UGen -> Bool
+is_math_binop k u =
+    case u of
+      Primitive_U (Primitive _ "BinaryOpUGen" [_,_] [_] (Special s) NoId) -> s == k
+      _ -> False
+
+-- | Is /u/ an ADD operator?
+is_add_operator :: UGen -> Bool
+is_add_operator = is_math_binop 0
+
+assert_is_add_operator :: String -> UGen -> UGen
+assert_is_add_operator msg u = if is_add_operator u then u else error ("assert_is_add_operator: " ++ msg)
+
+-- | Is /u/ an MUL operator?
+is_mul_operator :: UGen -> Bool
+is_mul_operator = is_math_binop 2
+
 -- | MulAdd re-writer, applicable only directly at add operator UGen.
+--   The MulAdd UGen is very sensitive to input rates.
+--   ADD=AR with IN|MUL=IR|CONST will CRASH scsynth.
 mul_add_optimise_direct :: UGen -> UGen
 mul_add_optimise_direct u =
-  case u of
-    Primitive_U
-      (Primitive r _ [Primitive_U (Primitive _ "BinaryOpUGen" [i,j] [_] (Special 2) NoId),k] [_] _ NoId) ->
-      Primitive_U (Primitive r "MulAdd" [i,j,k] [r] (Special 0) NoId)
-    Primitive_U
-      (Primitive r _ [k,Primitive_U (Primitive _ "BinaryOpUGen" [i,j] [_] (Special 2) NoId)] [_] _ NoId) ->
-      Primitive_U (Primitive r "MulAdd" [i,j,k] [r] (Special 0) NoId)
-    _ -> u
+  let reorder (i,j,k) =
+        let (ri,rj,rk) = (rateOf i,rateOf j,rateOf k)
+        in if rk > max ri rj
+           then Nothing
+           else Just (max (max ri rj) rk,if rj > ri then (j,i,k) else (i,j,k))
+  in case assert_is_add_operator "MUL-ADD" u of
+       Primitive_U
+         (Primitive _ _ [Primitive_U (Primitive _ "BinaryOpUGen" [i,j] [_] (Special 2) NoId),k] [_] _ NoId) ->
+         case reorder (i,j,k) of
+           Just (rt,(p,q,r)) -> Primitive_U (Primitive rt "MulAdd" [p,q,r] [rt] (Special 0) NoId)
+           Nothing -> u
+       Primitive_U
+         (Primitive _ _ [k,Primitive_U (Primitive _ "BinaryOpUGen" [i,j] [_] (Special 2) NoId)] [_] _ NoId) ->
+         case reorder (i,j,k) of
+           Just (rt,(p,q,r)) -> Primitive_U (Primitive rt "MulAdd" [p,q,r] [rt] (Special 0) NoId)
+           Nothing -> u
+       _ -> u
 
+{- | MulAdd optimiser, applicable at any UGen (ie. checks /u/ is an ADD ugen)
+
+> import Sound.SC3
+> g1 = sinOsc AR 440 0 * 0.1 + control IR "x" 0.05
+> g2 = sinOsc AR 440 0 * control IR "x" 0.1 + 0.05
+> g3 = control IR "x" 0.1 * sinOsc AR 440 0 + 0.05
+> g4 = 0.05 + sinOsc AR 440 0 * 0.1
+-}
+mul_add_optimise :: UGen -> UGen
+mul_add_optimise u = if is_add_operator u then mul_add_optimise_direct u else u
+
 -- | Sum3 re-writer, applicable only directly at add operator UGen.
 sum3_optimise_direct :: UGen -> UGen
 sum3_optimise_direct u =
-  case u of
+  case assert_is_add_operator "SUM3" u of
     Primitive_U
       (Primitive r _ [Primitive_U (Primitive _ "BinaryOpUGen" [i,j] [_] (Special 0) NoId),k] [_] _ NoId) ->
       Primitive_U (Primitive r "Sum3" [i,j,k] [r] (Special 0) NoId)
@@ -401,17 +530,21 @@
       Primitive_U (Primitive r "Sum3" [i,j,k] [r] (Special 0) NoId)
     _ -> u
 
--- | 'sum3_optimise_direct' of 'mul_add_optimise_direct'.
-add_optimise_direct :: UGen -> UGen
-add_optimise_direct = sum3_optimise_direct . mul_add_optimise_direct
+-- | /Sum3/ optimiser, applicable at any /u/ (ie. checks if /u/ is an ADD operator).
+sum3_optimise :: UGen -> UGen
+sum3_optimise u = if is_add_operator u then sum3_optimise_direct u else u
 
+-- | 'sum3_optimise' of 'mul_add_optimise'.
+add_optimise :: UGen -> UGen
+add_optimise = sum3_optimise . mul_add_optimise
+
 -- | Unit generators are numbers.
 instance Num UGen where
     negate = mkUnaryOperator Neg negate
-    (+) = fmap add_optimise_direct .
-          mkBinaryOperator_optimize_constants Add (+) (`elem` [Left 0,Right 0])
-    (-) = mkBinaryOperator_optimize_constants Sub (-) (Right 0 ==)
-    (*) = mkBinaryOperator_optimize_constants Mul (*) (`elem` [Left 1,Right 1])
+    (+) = fmap add_optimise .
+          mkBinaryOperator_optimise_constants Add (+) (`elem` [Left 0,Right 0])
+    (-) = mkBinaryOperator_optimise_constants Sub (-) (Right 0 ==)
+    (*) = mkBinaryOperator_optimise_constants Mul (*) (`elem` [Left 1,Right 1])
     abs = mkUnaryOperator Abs abs
     signum = mkUnaryOperator Sign signum
     fromInteger = Constant_U . Constant . fromInteger
@@ -419,7 +552,7 @@
 -- | Unit generators are fractional.
 instance Fractional UGen where
     recip = mkUnaryOperator Recip recip
-    (/) = mkBinaryOperator_optimize_constants FDiv (/) (Right 1 ==)
+    (/) = mkBinaryOperator_optimise_constants FDiv (/) (Right 1 ==)
     fromRational = Constant_U . Constant . fromRational
 
 -- | Unit generators are floating point.
@@ -428,7 +561,7 @@
     exp = mkUnaryOperator Exp exp
     log = mkUnaryOperator Log log
     sqrt = mkUnaryOperator Sqrt sqrt
-    (**) = mkBinaryOperator_optimize_constants Pow (**) (Right 1 ==)
+    (**) = mkBinaryOperator_optimise_constants Pow (**) (Right 1 ==)
     logBase a b = log b / log a
     sin = mkUnaryOperator Sin sin
     cos = mkUnaryOperator Cos cos
diff --git a/Sound/SC3/UGen/UGen.hs b/Sound/SC3/UGen/UGen.hs
--- a/Sound/SC3/UGen/UGen.hs
+++ b/Sound/SC3/UGen/UGen.hs
@@ -7,9 +7,9 @@
 
 import qualified Sound.SC3.Common.Envelope as E
 import qualified Sound.SC3.Common.Base as B
+import qualified Sound.SC3.Common.Math.Operator as O
+import qualified Sound.SC3.Common.Rate as R
 import qualified Sound.SC3.Common.UId as UId
-import qualified Sound.SC3.UGen.Operator as O
-import qualified Sound.SC3.UGen.Rate as R
 import Sound.SC3.UGen.Type
 
 -- | 'UId' of 'resolveID'.
@@ -26,22 +26,25 @@
 
 -- * UGen graph functions
 
--- | Depth first traversal of graph at `u' applying `f' to each node.
-ugenTraverse :: (UGen -> UGen) -> UGen -> UGen
-ugenTraverse f u =
-    let recur = ugenTraverse f
+-- | Depth first traversal of graph at `u', stopping at `halt_f', else applying `map_f' to each node.
+ugenTraverse :: (UGen -> Bool) -> (UGen -> UGen) -> UGen -> UGen
+ugenTraverse halt_f map_f u =
+  if halt_f u
+  then u
+  else
+    let recur = ugenTraverse halt_f map_f
     in case u of
          Primitive_U p ->
              let i = ugenInputs p
-             in f (Primitive_U (p {ugenInputs = map recur i}))
+             in map_f (Primitive_U (p {ugenInputs = map recur i}))
          Proxy_U p ->
              let s = Primitive_U (proxySource p)
              in case recur s of
-                  Primitive_U p' -> f (Proxy_U (p {proxySource = p'}))
+                  Primitive_U p' -> map_f (Proxy_U (p {proxySource = p'}))
                   _ -> error "ugenTraverse"
-         MCE_U m -> f (mce (map recur (mceProxies m)))
-         MRG_U (MRG l r) -> f (MRG_U (MRG (recur l) (recur r)))
-         _ -> f u
+         MCE_U m -> map_f (mce (map recur (mceProxies m)))
+         MRG_U (MRG l r) -> map_f (MRG_U (MRG (recur l) (recur r)))
+         _ -> map_f u
 
 -- | Right fold of UGen graph.
 ugenFoldr :: (UGen -> a -> a) -> a -> UGen -> a
@@ -153,10 +156,6 @@
 -- | Transpose rows and columns, ie. {{a,b},{c,d}} to {{a,c},{b,d}}.
 mceTranspose :: UGen -> UGen
 mceTranspose = mce . map mce . transpose . map mceChannels . mceChannels
-
--- | Collapse mce by summing (see also mix and mixN).
-mceSum :: UGen -> UGen
-mceSum = sum . mceChannels
 
 -- * Transform
 
diff --git a/emacs/hsc3.el b/emacs/hsc3.el
--- a/emacs/hsc3.el
+++ b/emacs/hsc3.el
@@ -13,6 +13,10 @@
   nil
   "*The directory containing the help files (default=nil).")
 
+(defvar sc3-help-directory
+  nil
+  "*The directory containing the SC3 RTF help files (default=nil).")
+
 (defvar hsc3-literate-p
   t
   "*Flag to indicate if we are in literate mode (default=t).")
@@ -49,30 +53,22 @@
   "Remove initial comment and Bird-literate markers if present."
    (replace-regexp-in-string "^[- ]*[> ]*" "" s))
 
-(defun hsc3-help ()
-  "Lookup up the name at point in the hsc3 help files."
-  (interactive)
+(defun hsc3-find-files (dir rgx)
   (mapc (lambda (filename)
-	  (find-file-other-window filename))
-	(find-lisp-find-files hsc3-help-directory
-			      (concat "^"
-				      (thing-at-point 'symbol)
-				      "\\.help\\.l?hs$"))))
+          (find-file-other-window filename))
+        (find-lisp-find-files dir rgx)))
 
-(defun hsc3-sc3-ugen-help ()
-  "Lookup up the UGen name at point in the SC3 help files."
+(defun hsc3-help ()
+  "Lookup up the name at point in the hsc3 help files."
   (interactive)
-  (hsc3-send-string
-   (format
-    "Sound.SC3.viewSC3Help (Sound.SC3.UGen.DB.ugenSC3Name \"%s\")"
-    (thing-at-point 'symbol))))
+  (let ((rgx (concat "^" (thing-at-point 'symbol) "\\.help\\.l?hs$")))
+    (hsc3-find-files hsc3-help-directory rgx)))
 
-(defun hsc3-sc3-server-help ()
-  "Lookup up the Server Command name at point in the SC3 help files."
+(defun hsc3-sc3-help ()
+  "Lookup up the name at point in the SC3 (RTF) help files."
   (interactive)
-  (hsc3-send-string
-   (format "Sound.SC3.Server.Help.viewServerHelp \"%s\""
-           (thing-at-point 'symbol))))
+  (let ((rgx (concat "^" (thing-at-point 'symbol) "\\\(.help\\\)?.rtf$")))
+    (hsc3-find-files sc3-help-directory rgx)))
 
 (defun hsc3-ugen-summary ()
   "Lookup up the UGen at point in hsc3-db"
@@ -237,8 +233,8 @@
   (define-key map (kbd "C-c C-g") 'hsc3-draw-graph)
   (define-key map (kbd "C-c C-S-g") 'hsc3-draw-graph-plain)
   (define-key map [?\C-c ?\M-g] 'hsc3-draw-graph-m)
-  (define-key map [?\C-c ?\C-j] 'hsc3-sc3-ugen-help)
-  (define-key map [?\C-c ?\C-/] 'hsc3-sc3-server-help)
+  (define-key map [?\C-c ?\C-j] 'hsc3-sc3-help)
+  ;(define-key map [?\C-c ?\C-/] 'hsc3-sc3-html-help)
   (define-key map [?\C-c ?i] 'hsc3-interrupt-haskell)
   (define-key map [?\C-c ?\C-k] 'hsc3-reset-scsynth)
   (define-key map [?\C-c ?\C-m] 'hsc3-run-main)
@@ -246,6 +242,7 @@
   (define-key map [?\C-c ?\C-q] 'hsc3-quit-haskell)
   (define-key map [?\C-c ?\C-0] 'hsc3-quit-scsynth)
   (define-key map [?\C-c ?\C-.] 'hsc3-stop)
+  (define-key map [?\C-c ?\C-s] 'hsc3-stop) ; ie. sclang-mode key
   (define-key map [?\C-c ?\C-u] 'hsc3-ugen-summary))
 
 (defun hsc3-mode-menu (map)
@@ -255,13 +252,13 @@
   (define-key map [menu-bar hsc3 help]
     (cons "Help" (make-sparse-keymap "Help")))
   (define-key map [menu-bar hsc3 help hsc3]
-    '("Haskell SuperCollider help" . hsc3-help))
+    '("HSC3 Help" . hsc3-help))
   (define-key map [menu-bar hsc3 help ugen]
-    '("UGen parameter summary" . hsc3-ugen-summary))
-  (define-key map [menu-bar hsc3 help sc3-server]
-    '("SuperCollider Server Command help" . hsc3-sc3-server-help))
+    '("UGen Summary" . hsc3-ugen-summary))
+  ;(define-key map [menu-bar hsc3 help sc3-server]
+  ;  '("SuperCollider Server Command help" . hsc3-sc3-server-help))
   (define-key map [menu-bar hsc3 help sc3-ugen]
-    '("SuperCollider UGen help" . hsc3-sc3-ugen-help))
+    '("SC3 Help" . hsc3-sc3-ugen-help))
   (define-key map [menu-bar hsc3 expression]
     (cons "Expression" (make-sparse-keymap "Expression")))
   (define-key map [menu-bar hsc3 expression stop]
@@ -320,125 +317,3 @@
 (add-to-list 'auto-mode-alist '("\\.hs$" . hsc3-mode))
 
 (provide 'hsc3)
-
-;; (require 'haskell-interactive-mode)
-;; (require 'haskell-process)
-
-;; (defun hsc3-send-string (s)
-;;   (haskell-process-send-string (haskell-interactive-process) s))
-
-;; (defun hsc3-send-string-and-print (s)
-;;   (haskell-process-show-repl-response s))
-
-;; (defun hsc3-interrupt-haskell ()
-;;   (haskell-process-interrupt))
-
-;; (defun hsc3-see-haskell ()
-;;   "Show haskell output."
-;;   (interactive)
-;;   (haskell-interactive-bring))
-
-;; (require 'sclang)
-
-;; (define-key map [?\C-c ?\C-e] 'hsc3-run-multiple-lines)
-;; (define-key map [?\C-c ?\M-e] 'hsc3-run-multiple-lines-sclang)
-;; (define-key map [?\C-c ?\C-r] 'hsc3-run-consecutive-lines)
-;; (define-key map [?\C-c ?\C-f] 'hsc3-run-layout-block)
-;; (define-key map [?\C-c ?\M-f] 'hsc3-sc3-forth-pp)
-;; (define-key map [?\C-c ?\M-m] 'hsc3-load-main)
-;; (define-key map [?\C-c ?\C-,] 'hsc3-ugen-default-param)
-
-;; (define-key map [menu-bar hsc3 expression gen-default-param]
-;;   '("Insert default parameters" . hsc3-ugen-default-param))
-;; (define-key map [menu-bar hsc3 expression run-layout-block]
-;;   '("Run layout block" . hsc3-run-layout-block))
-;; (define-key map [menu-bar hsc3 expression run-consecutive-lines]
-;;   '("Run consecutive lines" . hsc3-run-consecutive-lines))
-;; (define-key map [menu-bar hsc3 expression run-multiple-lines]
-;;   '("Run multiple lines" . hsc3-run-multiple-lines))
-
-;; (defun hsc3-wait ()
-;;   "Wait for prompt after sending command."
-;;   (interactive)
-;;   (inferior-haskell-wait-for-prompt (inferior-haskell-process)))
-
-;; (defun hsc3-request-type ()
-;;   "Ask ghci for the type of the name at point."
-;;   (interactive)
-;;   (hsc3-send-string (concat ":t " (thing-at-point 'symbol))))
-
-;; (defun hsc3-load-main ()
-;;   "Load current buffer and run main."
-;;   (interactive)
-;;   (hsc3-load-buffer)
-;;   (hsc3-run-main))
-
-;; (defun hsc3-ugen-default-param ()
-;;   "Insert the default UGen parameters for the UGen before <point>."
-;;   (interactive)
-;;   (let ((p (format "hsc3-default-param %s" (thing-at-point 'symbol))))
-;;     (insert " ")
-;;     (insert (hsc3-remove-trailing-newline (shell-command-to-string p)))))
-
-;; (defun hsc3-sc3-forth-pp () "Forth PP" (interactive)
-;;   (hsc3-send-string
-;;    (format "Sound.SC3.UGen.DB.PP.ugen_graph_forth_pp False %s" (thing-at-point 'symbol))))
-
-;; (defun hsc3-region-string ()
-;;   "Get region as string (no properties)"
-;;   (buffer-substring-no-properties
-;;    (region-beginning)
-;;    (region-end)))
-
-;; (defun hsc3-gen-param ()
-;;   "Rewrite an SC3 argument list as control definitions."
-;;   (interactive)
-;;   (hsc3-send-string
-;;    (concat "putStrLn $ Sound.SC3.RW.PSynth.rewrite_param_list \"" (hsc3-region-string) "\"")))
-
-;; (defun hsc3-local-dot ()
-;;   "Copy '/tmp/hsc3.dot' to 'buffer-name' .dot."
-;;   (interactive)
-;;   (let ((nm (concat (file-name-sans-extension (buffer-name)) ".dot")))
-;;     (copy-file "/tmp/hsc3.dot" nm t)))
-
-;; (defun hsc3-concat (l)
-;;   (apply #'concat l))
-
-;; (defun hsc3-remove-non-literates (s)
-;;   "Remove non-bird literate lines"
-;;   (replace-regexp-in-string "^[^>]*$" "" s))
-
-;; (defun hsc3-region-string-unlit ()
-;;   "The current region (unlit, uncomment)."
-;;   (let* ((s (hsc3-region-string)))
-;;     (if hsc3-literate-p
-;;         (hsc3-unlit (hsc3-remove-non-literates s))
-;;       (hsc3-concat (mapcar 'hsc3-uncomment (split-string s "\n"))))))
-
-;; (defun hsc3-region-string-one-line ()
-;;   "Replace newlines with spaces in `hsc3-region-string'."
-;;   (replace-regexp-in-string "\n" " " (hsc3-region-string-unlit)))
-
-;; (defun hsc3-run-multiple-lines ()
-;;   "Send the current region to the haskell interpreter as a single line."
-;;   (interactive)
-;;   (hsc3-send-string (hsc3-region-string-one-line)))
-
-;; (defun hsc3-run-multiple-lines-sclang ()
-;;   "Send the current region to the sclang interpreter as a single line."
-;;   (interactive)
-;;   (sclang-eval-string (hsc3-region-string-one-line) t))
-
-;; (defun hsc3-run-consecutive-lines ()
-;;   "Send the current region to the interpreter one line at a time."
-;;   (interactive)
-;;   (mapcar 'hsc3-send-string
-;;           (split-string (hsc3-region-string) "\n")))
-
-;; (defun hsc3-run-layout-block ()
-;;   "Variant of `hsc3-run-consecutive-lines' with ghci layout quoting."
-;;   (interactive)
-;;   (hsc3-send-string ":{")
-;;   (hsc3-send-string (hsc3-region-string))
-;;   (hsc3-send-string ":}"))
diff --git a/hsc3.cabal b/hsc3.cabal
--- a/hsc3.cabal
+++ b/hsc3.cabal
@@ -1,5 +1,5 @@
 Name:              hsc3
-Version:           0.17
+Version:           0.18
 Synopsis:          Haskell SuperCollider
 Description:       Haskell client for the SuperCollider synthesis server,
                    <http://audiosynth.com/>.
@@ -8,14 +8,14 @@
                    <http://rohandrape.net/t/hsc3-texts>.
 License:           GPL-3
 Category:          Sound
-Copyright:         (c) Rohan Drape and others, 2005-2018
+Copyright:         (c) Rohan Drape and others, 2005-2020
 Author:            Rohan Drape
 Maintainer:        rd@rohandrape.net
 Stability:         Experimental
 Homepage:          http://rohandrape.net/t/hsc3
-Tested-With:       GHC == 8.4.3
+Tested-With:       GHC == 8.6.5
 Build-Type:        Simple
-Cabal-Version:     >= 1.8
+Cabal-Version:     >= 1.10
 
 Data-files:        README
                    emacs/hsc3.el
@@ -32,7 +32,7 @@
                    data-ordlist,
                    directory,
                    filepath,
-                   hosc == 0.17.*,
+                   hosc == 0.18.*,
                    murmur-hash,
                    network,
                    process,
@@ -41,6 +41,7 @@
                    split >= 0.2,
                    transformers,
                    vector
+  Default-Language:Haskell2010
   GHC-Options:     -Wall -fwarn-tabs
   Exposed-modules: Sound.SC3
                    Sound.SC3.Common
@@ -49,14 +50,18 @@
                    Sound.SC3.Common.Buffer.Array
                    Sound.SC3.Common.Buffer.Gen
                    Sound.SC3.Common.Buffer.Vector
+                   Sound.SC3.Common.Enum
                    Sound.SC3.Common.Envelope
                    Sound.SC3.Common.Math
                    Sound.SC3.Common.Math.Filter
                    Sound.SC3.Common.Math.Filter.BEQ
                    Sound.SC3.Common.Math.Interpolate
+                   Sound.SC3.Common.Math.Noise
+                   Sound.SC3.Common.Math.Operator
                    Sound.SC3.Common.Math.Window
                    Sound.SC3.Common.Monad
                    Sound.SC3.Common.Monad.Operators
+                   Sound.SC3.Common.Rate
                    Sound.SC3.Common.UId
                    Sound.SC3.FD
                    Sound.SC3.Server
@@ -70,10 +75,12 @@
                    Sound.SC3.Server.Graphdef.Graph
                    Sound.SC3.Server.Graphdef.Read
                    Sound.SC3.Server.FD
-                   Sound.SC3.Server.Help
                    Sound.SC3.Server.Monad
                    Sound.SC3.Server.NRT
                    Sound.SC3.Server.NRT.Edit
+                   Sound.SC3.Server.NRT.UGen
+                   Sound.SC3.Server.Options
+                   Sound.SC3.Server.Param
                    Sound.SC3.Server.Recorder
                    Sound.SC3.Server.Status
                    Sound.SC3.Server.Synthdef
@@ -83,6 +90,7 @@
                    Sound.SC3.UGen.Analysis
                    Sound.SC3.UGen.Bindings
                    Sound.SC3.UGen.Bindings.Composite
+                   Sound.SC3.UGen.Bindings.Composite.External
                    Sound.SC3.UGen.Bindings.DB
                    Sound.SC3.UGen.Bindings.DB.External
                    Sound.SC3.UGen.Bindings.HW
@@ -98,19 +106,15 @@
                    Sound.SC3.UGen.Graph
                    Sound.SC3.UGen.Graph.Reconstruct
                    Sound.SC3.UGen.Graph.Transform
-                   Sound.SC3.UGen.Help
                    Sound.SC3.UGen.Help.Graph
                    Sound.SC3.UGen.HS
                    Sound.SC3.UGen.Math
                    Sound.SC3.UGen.Math.Composite
                    Sound.SC3.UGen.MCE
                    Sound.SC3.UGen.Name
-                   Sound.SC3.UGen.Operator
                    Sound.SC3.UGen.Optimise
                    Sound.SC3.UGen.Plain
                    Sound.SC3.UGen.PP
-                   Sound.SC3.UGen.Protect
-                   Sound.SC3.UGen.Rate
                    Sound.SC3.UGen.Type
                    Sound.SC3.UGen.UGen
 
