diff --git a/Help/UGen/Buffer/bufRd.help.lhs b/Help/UGen/Buffer/bufRd.help.lhs
--- a/Help/UGen/Buffer/bufRd.help.lhs
+++ b/Help/UGen/Buffer/bufRd.help.lhs
@@ -8,7 +8,7 @@
 > in withSC3 (async (b_allocRead 0 fn 0 0))
 
 Audio rate sine oscillator as phase input
-> let phase = (sinOsc AR 0.1 0 * bufFrames KR 0)
+> let phase = sinOsc AR 0.1 0 * bufFrames KR 0
 > in audition (out 0 (bufRd 1 AR 0 phase Loop NoInterpolation))
 
 There are constructors, bufRd{N|L|C}, for the fixed cases.
diff --git a/Help/UGen/Envelope/detectSilence.help.lhs b/Help/UGen/Envelope/detectSilence.help.lhs
--- a/Help/UGen/Envelope/detectSilence.help.lhs
+++ b/Help/UGen/Envelope/detectSilence.help.lhs
@@ -3,6 +3,6 @@
 
 > import Sound.SC3
 
-> let {s = sinOsc AR 440 0 * mouseY KR 0 0.4 Linear 0.1
->     ;d = detectSilence s 0.1 0.2 RemoveSynth}
+> let {s = sinOsc AR 440 0 * mouseY KR 0 0.2 Linear 0.1
+>     ;d = detectSilence s 0.1 0.1 RemoveSynth}
 > in audition (mrg [out 0 s,d])
diff --git a/Help/UGen/Envelope/envADSR.help.lhs b/Help/UGen/Envelope/envADSR.help.lhs
--- a/Help/UGen/Envelope/envADSR.help.lhs
+++ b/Help/UGen/Envelope/envADSR.help.lhs
@@ -1,4 +1,4 @@
-> Sound.SC3.UGen.Help.viewSC3Help "Env.*adsr"
+
 > :i Sound.SC3.ADSR
 > :t Sound.SC3.envADSR_r
 > :t Sound.SC3.envADSR
@@ -15,6 +15,7 @@
 > withSC3 (send (n_free [-1]))
 
 > import Sound.SC3.Plot
+
 > plotEnvelope [envADSR 0.75 0.75 0.5 0.75 1 (EnvNum (-4)) 0
 >              ,envADSR 0.02 0.2 0.25 1 1 (EnvNum (-4)) 0
 >              ,envADSR 0.001 0.2 0.25 1 1 (EnvNum (-4)) 0
diff --git a/Help/UGen/Envelope/envASR.help.lhs b/Help/UGen/Envelope/envASR.help.lhs
--- a/Help/UGen/Envelope/envASR.help.lhs
+++ b/Help/UGen/Envelope/envASR.help.lhs
@@ -11,5 +11,6 @@
 > withSC3 (send (n_set1 (-1) "gate" 0))
 
 > import Sound.SC3.Plot
+
 > plotEnvelope [envASR 0.1 1 1 (EnvNum (-4))
 >              ,envASR 0.3 0.25 1 EnvSin]
diff --git a/Help/UGen/Envelope/envCoord.help.lhs b/Help/UGen/Envelope/envCoord.help.lhs
--- a/Help/UGen/Envelope/envCoord.help.lhs
+++ b/Help/UGen/Envelope/envCoord.help.lhs
@@ -20,10 +20,20 @@
 > withSC3 (send (n_set (-1) [("en",990),("tm",1),("tr",1)]))
 > withSC3 (send (n_set (-1) [("en",110),("tm",2),("tr",1)]))
 
+> import Sound.SC3.ID
+
+likewise, but internal graph triggers and line end points
+> let {tr = dust 'α' KR 2
+>     ;st = 440
+>     ;en = tRand 'β' 300 900 tr
+>     ;tm = tRand 'γ' 0.5 1.5 tr
+>     ;p = envCoord [(0,st),(tm,en)] 1 1 EnvLin
+>     ;e = envGen KR tr 1 0 1 DoNothing p}
+> in audition (out 0 (sinOsc AR e 0 * 0.2))
+
 plotting
 > import Sound.SC3.Plot
 
 > let {c0 = [(0,0),(0.35,0.1),(0.55,1),(1,0)]
 >     ;c1 = [(0,0),(0.15,0.6),(0.35,0.2),(1,0)]}
 > in plotEnvelope [envCoord c0 9 0.1 EnvLin,envCoord c1 6 0.1 EnvLin]
-
diff --git a/Help/UGen/Envelope/envGen.help.lhs b/Help/UGen/Envelope/envGen.help.lhs
--- a/Help/UGen/Envelope/envGen.help.lhs
+++ b/Help/UGen/Envelope/envGen.help.lhs
@@ -25,7 +25,7 @@
 > in 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
-> let {n = range 0.01 0.1 (lfNoise1 'a' KR 2)
+> let {n = range 0.01 0.1 (lfNoise1 'α' KR 2)
 >     ;e = Envelope [0,1] [n] [EnvLin] Nothing (Just 0)
 >     ;a = envGen AR 1 1 0 1 DoNothing (env_circle e 0 EnvLin)
 >     ;o = sinOsc AR (a * 400 + 500) 0 * 0.1}
diff --git a/Help/UGen/External/atari2600.help.lhs b/Help/UGen/External/atari2600.help.lhs
--- a/Help/UGen/External/atari2600.help.lhs
+++ b/Help/UGen/External/atari2600.help.lhs
@@ -38,28 +38,31 @@
 >               ;o = out 0 (pan2 (z * eg) pan 1)}
 >           in synthdef "atari2600" o
 
-> import Sound.SC3.Lang.Pattern.ID
+> import Sound.SC3.Lang.Pattern
 
-> let p = [("dur",0.125)
->         ,("amp",0.5)
->         ,("tone0",pseq [pn 3 64,pn 2 128,pn 10 8] inf)
->         ,("tone1",pseqn [32,12] [8,pwhite 'a' 0 15 inf] inf)
->         ,("freq0",pseqn [17,4,3] [10,prand 'a' [1,2,3] inf,10] inf)
->         ,("freq1",pseq1 [10,3,pwrand 'c' [20,1] [0.6,0.4] inf] inf)]
-> in audition (ati,pbind p)
+> let p = [(K_instr,psynth ati)
+>         ,(K_dur,0.125)
+>         ,(K_amp,0.5)
+>         ,(K_param "tone0",pseq [pn 3 64,pn 2 128,pn 10 8] inf)
+>         ,(K_param "tone1",pseqn [32,12] [8,pwhite 'α' 0 15 inf] inf)
+>         ,(K_param "freq0",pseqn [17,4,3] [10,prand 'β' [1,2,3] inf,10] inf)
+>         ,(K_param "freq1",pseq1 [10,3,pwrand 'γ' [20,1] [0.6,0.4] inf] inf)]
+> in audition (pbind p)
 
-> let p = [("dur",pseq [0.25,0.25,0.25,0.45] inf)
->         ,("amp",0.5)
->         ,("tone0",pseq [pseq [2,5] 32,pseq [3,5] 32] inf)
->         ,("tone1",14)
->         ,("freq0",pseq [pbrown 'a' 28 31 1 32,pbrown 'b' 23 26 3 32] inf)
->         ,("freq1",pseq [pn 10 16,pn 11 16] inf)]
-> in audition (ati,pbind p)
+> let p = [(K_instr,psynth ati)
+>         ,(K_dur,pseq [0.25,0.25,0.25,0.45] inf)
+>         ,(K_amp,0.5)
+>         ,(K_param "tone0",pseq [pseq [2,5] 32,pseq [3,5] 32] inf)
+>         ,(K_param "tone1",14)
+>         ,(K_param "freq0",pseq [pbrown 'α' 28 31 1 32,pbrown 'β' 23 26 3 32] inf)
+>         ,(K_param "freq1",pseq [pn 10 16,pn 11 16] inf)]
+> in audition (pbind p)
 
-> let p = [("dur",pbrown 'a' 0.1 0.15 0.1 inf)
->         ,("amp",0.5)
->         ,("tone0",1)
->         ,("tone1",2)
->         ,("freq0",pseqn [2,1] [24,pwrand 'b' [20,23] [0.6,0.4] inf] inf)
->         ,("freq1",pseqn [1,1,1] [1,3,pwrand 'c' [2,1] [0.6,0.4] inf] inf)]
-> in audition (ati,pbind p)
+> let p = [(K_instr,psynth ati)
+>         ,(K_dur,pbrown 'α' 0.1 0.15 0.1 inf)
+>         ,(K_amp,0.5)
+>         ,(K_param "tone0",1)
+>         ,(K_param "tone1",2)
+>         ,(K_param "freq0",pseqn [2,1] [24,pwrand 'β' [20,23] [0.6,0.4] inf] inf)
+>         ,(K_param "freq1",pseqn [1,1,1] [1,3,pwrand 'γ' [2,1] [0.6,0.4] inf] inf)]
+> in audition (pbind p)
diff --git a/Help/UGen/External/concat.help.lhs b/Help/UGen/External/concat.help.lhs
--- a/Help/UGen/External/concat.help.lhs
+++ b/Help/UGen/External/concat.help.lhs
@@ -9,7 +9,7 @@
 Granulator
 > let {y0 = mouseY KR 0.01 1 Linear 0.2
 >     ;y1 = mouseY KR 12 100 Linear 0.2
->     ;n = lfNoise0 'a' KR y0 * 3 + 4.5
+>     ;n = lfNoise0 'α' KR y0 * 3 + 4.5
 >     ;k = saw AR (sinOsc KR n 0 * 10 + y1)
 >     ;i = playBuf 1 AR 12 (bufRateScale KR 12) 0 0 Loop DoNothing
 >     ;x0 = mouseX KR 0.01 0.1 Linear 0.2
diff --git a/Help/UGen/External/dfm1.help.lhs b/Help/UGen/External/dfm1.help.lhs
--- a/Help/UGen/External/dfm1.help.lhs
+++ b/Help/UGen/External/dfm1.help.lhs
@@ -4,7 +4,7 @@
 > import Sound.SC3.ID
 
 Play it with the mouse
-> let { n = pinkNoise 'a' AR * 0.5
+> let { n = pinkNoise 'α' AR * 0.5
 >     ; x = mouseX KR 80 5000 Exponential 0.1
 >     ; y = mouseX KR 0.1 1.2 Linear 0.1 }
 > in audition (out 0 (dfm1 n x y 1 0 3e-4))
diff --git a/Help/UGen/External/disintegrator.help.lhs b/Help/UGen/External/disintegrator.help.lhs
--- a/Help/UGen/External/disintegrator.help.lhs
+++ b/Help/UGen/External/disintegrator.help.lhs
@@ -6,5 +6,5 @@
 > 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
->     ;o = disintegrator 'a' s x y}
+>     ;o = disintegrator 'α' s x y}
 > in audition (out 0 o)
diff --git a/Help/UGen/External/fm7.help.lhs b/Help/UGen/External/fm7.help.lhs
--- a/Help/UGen/External/fm7.help.lhs
+++ b/Help/UGen/External/fm7.help.lhs
@@ -3,19 +3,19 @@
 
 > import Sound.SC3
 
-> let { c = [[xLine KR 300 310 4 DoNothing,0,1]
->           ,[xLine KR 300 310 8 DoNothing,0,1]
->           ,[0,0,1]
->           ,[0,0,1]
->           ,[0,0,1]
->           ,[0,0,1] ]
->     ; m = [[line KR 0 0.001 2 DoNothing,line KR 0.1 0 4 DoNothing,0,0,0,0]
->           ,[line KR 0 6 1 DoNothing,0,0,0,0,0]
->           ,[0,0,0,0,0,0]
->           ,[0,0,0,0,0,0]
->           ,[0,0,0,0,0,0]
->           ,[0,0,0,0,0,0] ]
->     ; MCE [l,r,_,_,_,_] = fm7 c m }
+> let {c = [[xLine KR 300 310 4 DoNothing,0,1]
+>          ,[xLine KR 300 310 8 DoNothing,0,1]
+>          ,[0,0,1]
+>          ,[0,0,1]
+>          ,[0,0,1]
+>          ,[0,0,1] ]
+>     ;m = [[line KR 0 0.001 2 DoNothing,line KR 0.1 0 4 DoNothing,0,0,0,0]
+>          ,[line KR 0 6 1 DoNothing,0,0,0,0,0]
+>          ,[0,0,0,0,0,0]
+>          ,[0,0,0,0,0,0]
+>          ,[0,0,0,0,0,0]
+>          ,[0,0,0,0,0,0] ]
+>     ;[l,r,_,_,_,_] = mceChannels (fm7 c m)}
 > in audition (out 0 (mce2 l r * 0.1))
 
 An algorithmically generated graph courtesy f0.
@@ -75,7 +75,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
->     ; MCE [c1,c2,c3,_,c4,c5] = fm7 cs ms
+>     ; [c1,c2,c3,_,c4,c5] = mceChannels (fm7 cs ms)
 >     ; g3 = linLin (lfSaw KR 0.1 0) (-1) 1 0 (dbAmp (-12))
 >     ; g5 = dbAmp (-3) }
 > in audition (out 0 (mce [c1 + c3 * g3 + c5 * g5,c2 + c4 + c5 * g5]))
diff --git a/Help/UGen/External/fmGrain.help.lhs b/Help/UGen/External/fmGrain.help.lhs
--- a/Help/UGen/External/fmGrain.help.lhs
+++ b/Help/UGen/External/fmGrain.help.lhs
@@ -4,7 +4,7 @@
 > import Sound.SC3.ID
 
 > let {t = impulse AR 20 0
->     ;n = linLin (lfNoise1 'a' KR 1) (-1) 1 1 10
+>     ;n = linLin (lfNoise1 'α' KR 1) (-1) 1 1 10
 >     ;s = envSine 9 0.1
 >     ;e = envGen KR 1 1 0 1 RemoveSynth s
 >     ;o = fmGrain t 0.2 440 220 n * e}
diff --git a/Help/UGen/External/lfBrownNoise.help.lhs b/Help/UGen/External/lfBrownNoise.help.lhs
--- a/Help/UGen/External/lfBrownNoise.help.lhs
+++ b/Help/UGen/External/lfBrownNoise.help.lhs
@@ -5,9 +5,9 @@
 
 Modulate frequency.
 > let {x = mouseX KR 0 5 Linear 0.2
->     ;n = lfBrownNoise2 'a' AR 1000 1 x}
+>     ;n = lfBrownNoise2 'α' AR 1000 1 x}
 > in audition (out 0 (n * 0.25))
 
 Use as frequency control.
-> let f = lfBrownNoise2 'a' KR 8 0.2 0 * 400 + 450
+> let f = lfBrownNoise2 'α' KR 8 0.2 0 * 400 + 450
 > in audition (out 0 (sinOsc AR f 0 * 0.2))
diff --git a/Help/UGen/External/lpcSynth.help.lhs b/Help/UGen/External/lpcSynth.help.lhs
--- a/Help/UGen/External/lpcSynth.help.lhs
+++ b/Help/UGen/External/lpcSynth.help.lhs
@@ -3,25 +3,29 @@
 
 > import Sound.SC3.ID
 
-> let {load_data b i d =
->          if length d < 512
->          then send (b_setn1 b i d)
->          else do {send (b_setn1 b i (take 512 d))
->                  ;load_data b (i + 512) (drop 512 d)}
->     ;lpc_instr b n lpc =
+> let load_data b i d =
+>         if length d < 512
+>         then send (b_setn1 b i d)
+>         else do {send (b_setn1 b i (take 512 d))
+>                 ;load_data b (i + 512) (drop 512 d)}
+
+> :t load_data
+
+> let 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 (lpcAnalysisDuration (lpcHeader lpc))
 >             ;ptr = lfSaw AR f 1 * 0.5 + 0.5
->             ;MCE [cps, rms, err] = lpcVals AR b ptr
+>             ;[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}
-> in do {lpc <- lpcRead "/home/rohan/cvs/tn/tn-56/lpc/fate.lpc"
->       ;let {n = pinkNoise 'a' AR
->            ;d = lpcSC3 lpc
->            ; s = lpc_instr 10 n lpc}
->        in withSC3 (do {_ <- async (b_alloc 10 (length d) 1)
->                       ;load_data 10 0 d
->                       ;play (out 0 s)})}
+>         in s * 1e-5 * rms
+
+> do {lpc <- lpcRead "/home/rohan/cvs/tn/tn-56/lpc/fate.lpc"
+>    ;let {n = pinkNoise 'a' AR
+>         ;d = map realToFrac (lpcSC3 lpc)
+>         ;s = lpc_instr 10 n lpc}
+>     in withSC3 (do {_ <- async (b_alloc 10 (length d) 1)
+>                    ;load_data 10 0 d
+>                    ;play (out 0 s)})}
diff --git a/Help/UGen/External/membraneCircle.help.lhs b/Help/UGen/External/membraneCircle.help.lhs
--- a/Help/UGen/External/membraneCircle.help.lhs
+++ b/Help/UGen/External/membraneCircle.help.lhs
@@ -6,14 +6,14 @@
 Excite the mesh with some pink noise, triggered by an
 impulse generator.  mouseX is tension and impulse frequency,
 mouseY is duration of excitation, release-time and amplitude.
-> let { x = mouseX KR 0 1 Linear 0.2
->     ; y = mouseY KR 1e-9 1 Exponential 0.2
->     ; loss = linLin y 0 1 0.999999 0.999
->     ; wobble = sinOsc KR 2 0
->     ; tension = linLin x 0 1 0.01 0.1 + (wobble * 0.0001)
->     ; p = envPerc 0.0001 y
->     ; tr = impulse KR (linLin x 0 1 3 9) 0
->     ; e = envGen KR tr (linLin y 0 1 0.05 0.25) 0 0.1 DoNothing p
->     ; m = membraneCircle
->     ; n = pinkNoise 'a' AR }
+> let {x = mouseX KR 0 1 Linear 0.2
+>     ;y = mouseY KR 1e-9 1 Exponential 0.2
+>     ;loss = linLin y 0 1 0.999999 0.999
+>     ;wobble = sinOsc KR 2 0
+>     ;tension = linLin x 0 1 0.01 0.1 + (wobble * 0.0001)
+>     ;p = envPerc 0.0001 y
+>     ;tr = impulse KR (linLin x 0 1 3 9) 0
+>     ;e = envGen KR tr (linLin y 0 1 0.05 0.25) 0 0.1 DoNothing p
+>     ;m = membraneCircle
+>     ;n = pinkNoise 'α' AR}
 > in audition (out (mce2 0 1) (m (n * e) tension loss))
diff --git a/Help/UGen/External/metro.help.lhs b/Help/UGen/External/metro.help.lhs
--- a/Help/UGen/External/metro.help.lhs
+++ b/Help/UGen/External/metro.help.lhs
@@ -5,12 +5,12 @@
 
 > audition (out 0 (metro AR 60 1))
 
-> let { b = xLine KR 60 120 5 DoNothing
->     ; m = metro KR b 1
->     ; o = sinOsc AR 440 0 * 0.1 }
+> let {b = xLine KR 60 120 5 DoNothing
+>     ;m = metro KR b 1
+>     ;o = sinOsc AR 440 0 * 0.1}
 > in audition (out 0 (decay m 0.2 * o))
 
-> let { b = range 30 240 (lfNoise2 'a' KR 0.2)
->     ; n = dseq 'b' dinf (mce [1,0.25,0.5,0.25])
->     ; a = decay (metro KR b n) 0.2 * sinOsc AR 440 0 * 0.1 }
+> let {b = range 30 240 (lfNoise2 'α' KR 0.2)
+>     ;n = dseq 'β' dinf (mce [1,0.25,0.5,0.25])
+>     ;a = decay (metro KR b n) 0.2 * sinOsc AR 440 0 * 0.1}
 > in audition (out 0 a)
diff --git a/Help/UGen/External/pv_Invert.help.lhs b/Help/UGen/External/pv_Invert.help.lhs
--- a/Help/UGen/External/pv_Invert.help.lhs
+++ b/Help/UGen/External/pv_Invert.help.lhs
@@ -3,11 +3,11 @@
 
 > import Sound.SC3.ID
 
-> let { s = sinOsc AR 440 0 * 0.4
->     ; n = pinkNoise 'a' AR * 0.1
->     ; i = s + n
->     ; c0 = fft' 10 i
->     ; c1 = pv_Invert c0
->     ; run = do {_ <- async (b_alloc 10 2048 1)
->                ;play (out 0 (mce2 i (ifft' c1) * 0.5))}}
+> let {s = sinOsc AR 440 0 * 0.4
+>     ;n = pinkNoise 'α' AR * 0.1
+>     ;i = s + n
+>     ;c0 = fft' 10 i
+>     ;c1 = pv_Invert c0
+>     ;run = do {_ <- async (b_alloc 10 2048 1)
+>               ;play (out 0 (mce2 i (ifft' c1) * 0.5))}}
 > in withSC3 run
diff --git a/Help/UGen/External/qitch.help.lhs b/Help/UGen/External/qitch.help.lhs
--- a/Help/UGen/External/qitch.help.lhs
+++ b/Help/UGen/External/qitch.help.lhs
@@ -13,7 +13,7 @@
 Output is printed to the console by scsynth.
 > let {x = mouseX KR 440 880 Exponential 0.1
 >     ;o = sinOsc AR x 0 * 0.1
->     ;MCE [f,e] = qitch KR o 10 1e-2 1 0 0 2500
+>     ;[f,e] = mceChannels (qitch KR o 10 1e-2 1 0 0 2500)
 >     ;t = impulse KR 4 0
 >     ;pf = poll t f (label "f") 0
 >     ;px = poll t x (label "x") 0}
diff --git a/Help/UGen/External/stkBowed.help.lhs b/Help/UGen/External/stkBowed.help.lhs
--- a/Help/UGen/External/stkBowed.help.lhs
+++ b/Help/UGen/External/stkBowed.help.lhs
@@ -3,5 +3,6 @@
 
 > import Sound.SC3
 
+no longer working...
 > let g = toggleFF (impulse KR 1 0)
 > in audition (out 0 (stkBowed AR 220 64 64 64 64 64 g 1 1))
diff --git a/Help/UGen/External/stkMandolin.help.lhs b/Help/UGen/External/stkMandolin.help.lhs
--- a/Help/UGen/External/stkMandolin.help.lhs
+++ b/Help/UGen/External/stkMandolin.help.lhs
@@ -3,21 +3,22 @@
 
 > import Control.Monad
 > import Sound.SC3.ID
-> import qualified Sound.SC3.Monadic as M
+> import qualified Sound.SC3.Monad as M
 
-> let { x = mouseX KR 0.25 4 Linear 0.2
->     ; tr = impulse KR x 0 - 0.5 }
-> in do { mn <- M.tRand 54 66 tr
->       ; [bs, pp, dm, dt, at] <- replicateM 5 (M.tRand 0 127 tr)
->       ; audition (out 0 (stkMandolin AR (midiCPS mn) bs pp dm dt at tr)) }
+requires "../../rawwaves/mand1.raw"
+> let {x = mouseX KR 0.25 4 Linear 0.2
+>     ;tr = impulse KR x 0 - 0.5 }
+> in do {mn <- M.tRand 54 66 tr
+>       ;[bs, pp, dm, dt, at] <- replicateM 5 (M.tRand 0 127 tr)
+>       ;audition (out 0 (stkMandolin AR (midiCPS mn) bs pp dm dt at tr))}
 
-> let { x = mouseX KR 3 16 Linear 0.2
->     ; t = impulse KR x 0 - 0.5
->     ; tr = pulseDivider t 6 0 }
-> in do { mn <- M.tIRand 54 66 t
->       ; bs <- M.tRand 72 94 tr
->       ; pp <- M.tRand 32 42 tr
->       ; dm <- M.tRand 64 72 tr
->       ; dt <- M.tRand 0 4 tr
->       ; at <- M.tRand 2 8 tr
->       ; audition (out 0 (stkMandolin AR (midiCPS mn) bs pp dm dt at t)) }
+> let {x = mouseX KR 3 16 Linear 0.2
+>     ;t = impulse KR x 0 - 0.5
+>     ;tr = pulseDivider t 6 0 }
+> in do {mn <- M.tIRand 54 66 t
+>       ;bs <- M.tRand 72 94 tr
+>       ;pp <- M.tRand 32 42 tr
+>       ;dm <- M.tRand 64 72 tr
+>       ;dt <- M.tRand 0 4 tr
+>       ;at <- M.tRand 2 8 tr
+>       ;audition (out 0 (stkMandolin AR (midiCPS mn) bs pp dm dt at t))}
diff --git a/Help/UGen/External/stkModalBar.help.lhs b/Help/UGen/External/stkModalBar.help.lhs
--- a/Help/UGen/External/stkModalBar.help.lhs
+++ b/Help/UGen/External/stkModalBar.help.lhs
@@ -5,6 +5,7 @@
 > import Sound.SC3.ID
 > import qualified Sound.SC3.Monadic as M
 
+requires "../../rawwaves/marmstk1.raw"
 > let {x = mouseX KR 0.25 4 Linear 0.2
 >     ;tr = impulse KR x 0 - 0.5
 >     ;tR = M.tRand 0 127 tr}
diff --git a/Help/UGen/External/streson.help.lhs b/Help/UGen/External/streson.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/External/streson.help.lhs
@@ -0,0 +1,8 @@
+> Sound.SC3.UGen.Help.viewSC3Help "Streson"
+> Sound.SC3.UGen.DB.ugenSummary "Streson"
+
+> import Sound.SC3
+
+> let {dt = recip (linExp (lfCub KR 0.1 (0.5 * pi)) (-1) 1 280 377)
+>     ;s = streson (lfSaw AR (mce2 220 180) 0 * 0.2) dt 0.9 * 0.3}
+> in audition (out 0 s)
diff --git a/Help/UGen/External/tartini.help.lhs b/Help/UGen/External/tartini.help.lhs
--- a/Help/UGen/External/tartini.help.lhs
+++ b/Help/UGen/External/tartini.help.lhs
@@ -6,13 +6,12 @@
 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 -}
->     ;MCE [f,e] = tartini KR o 0.2 2048 0 1024 0.5
+>     ;[f,e] = mceChannels (tartini KR o 0.2 2048 0 1024 0.5)
 >     ;t = impulse KR 4 0
 >     ;pf = poll t f (label "f") 0
 >     ;px = poll t x (label "x") 0}
 > in audition (mrg [out 0 o,pf,px])
 
 Fast test of live pitch tracking, not careful with amplitude of input
-(see better example below)
-> let MCE [f,e] = tartini KR (soundIn 0) 0.2 2048 0 1024 0.5
+> let [f,e] = mceChannels (tartini KR (soundIn 0) 0.2 2048 0 1024 0.5)
 > in audition (out 0 (saw AR f * 0.05))
diff --git a/Help/UGen/External/vosim.help.lhs b/Help/UGen/External/vosim.help.lhs
--- a/Help/UGen/External/vosim.help.lhs
+++ b/Help/UGen/External/vosim.help.lhs
@@ -3,7 +3,7 @@
 
 > import Sound.SC3.ID
 
-> let {p = tRand 'a' 0 1 (impulse AR 6 0)
+> let {p = tRand 'α' 0 1 (impulse AR 6 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
@@ -11,12 +11,12 @@
 >     ;rng i = linLin i (-1) 1
 >     ;mk_n e = rng (lfNoise2 e KR z) 0.25 2
 >     ;tR e ll rl = tRand e (mce ll) (mce rl)
->     ;f = tR 'b' [40,120,220] [440,990,880] t
->     ;n = tR 'b' [4] [8,16,32] t
->     ;d = tR 'b' [0.2,0.4,0.6] [0.6,0.8,1] t
->     ;a = tR 'b' [0] [0.05,0.15,0.25] t
->     ;l = tR 'b' [-1] [1] t
->     ;xn = mk_n 'c'
->     ;yn = mk_n 'd'
+>     ;f = tR 'β' [40,120,220] [440,990,880] t
+>     ;n = tR 'γ' [4] [8,16,32] t
+>     ;d = tR 'δ' [0.2,0.4,0.6] [0.6,0.8,1] t
+>     ;a = tR 'ε' [0] [0.05,0.15,0.25] t
+>     ;l = tR 'ζ' [-1] [1] t
+>     ;xn = mk_n 'η'
+>     ;yn = mk_n 'θ'
 >     ;v = vosim t (f * x * xn) n (d * y * yn) * a}
 > in audition (out 0 (pan2 (mix v) l 1))
diff --git a/Help/UGen/FFT/packFFT.help.lhs b/Help/UGen/FFT/packFFT.help.lhs
--- a/Help/UGen/FFT/packFFT.help.lhs
+++ b/Help/UGen/FFT/packFFT.help.lhs
@@ -9,11 +9,11 @@
 >     ;square a = a * a
 >     ;r1 = let f = expRand 'a' 0.1 1
 >           in linLin (fSinOsc KR f 0) (-1) 1 0 1
->     ;m1 = udup' n r1
+>     ;m1 = uclone' 'a' n r1
 >     ;m2 = zipWith (*) m1 (map square [1.0, 0.99 ..])
 >     ;r2 = let r = iRand 'a' (-3) 5
 >           in lfPulse KR (2 ** r) 0 0.3
->     ;i = udup' n r2
+>     ;i = uclone' 'a' n r2
 >     ;m3 = zipWith (*) m2 i
 >     ;p = replicate n 0.0
 >     ;c1 = fft' 10 (fSinOsc AR 440 0)
diff --git a/Help/UGen/Filter/pluck.help.lhs b/Help/UGen/Filter/pluck.help.lhs
--- a/Help/UGen/Filter/pluck.help.lhs
+++ b/Help/UGen/Filter/pluck.help.lhs
@@ -12,7 +12,10 @@
 >     ;dl = 1 / 440}
 > in audition (out 0 (pluck (n * 0.25) t dl (dl * y) 10 x))
 
-> let {n = 25
+> import Sound.SC3.UGen.Protect
+
+> let {n = 50
+>     ;udup = uclone 'a'
 >     ;f = udup n (rand 'a' 0.05 0.2)
 >     ;p = udup n (rand 'a' 0 1)
 >     ;w = udup n (whiteNoise 'a' AR)
diff --git a/Help/UGen/IO/localBuf.help.lhs b/Help/UGen/IO/localBuf.help.lhs
--- a/Help/UGen/IO/localBuf.help.lhs
+++ b/Help/UGen/IO/localBuf.help.lhs
@@ -15,9 +15,9 @@
 > in audition (out 0 (ifft' c * 0.1))
 
 Variant with two local buffers
-> let {n = udup 2 (whiteNoise 'α' AR)
+> let {n = uclone 'α' 2 (whiteNoise 'α' AR)
 >     ;m = maxLocalBufs 2
->     ;b = mrg2 (udup 2 (localBuf 'α' 2048 1)) m
+>     ;b = mrg2 (uclone 'α' 2 (localBuf 'α' 2048 1)) m
 >     ;f = fft' b n
 >     ;c = pv_BrickWall f (sinOsc KR (mce2 0.1 0.11) 0 * 0.75)}
 > in audition (out 0 (ifft' c * 0.1))
@@ -29,18 +29,18 @@
 >     ;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 = udup 2 (whiteNoise 'α' AR)
+>     ;n = uclone 'α' 2 (whiteNoise 'α' AR)
 >     ;ph = lfNoise0 'α' AR 530}
 > in audition (mrg2 (out 0 r) (wr ph n))
 
 bufCombC needs no clearing, because the delay line is filled by the ugen
-> let {d = udup 2 (dust 'α' AR 1)
+> let {d = uclone 'α' 2 (dust 'α' AR 1)
 >     ;n = whiteNoise 'α' AR
 >     ;z = decay d 0.3 * n
 >     ;l = xLine KR 0.0001 0.01 20 DoNothing
 >     ;sr = sampleRate
 >     ;m = maxLocalBufs 2
->     ;b = mrg2 (udup 2 (localBuf 'α' sr 2)) m}
+>     ;b = mrg2 (uclone 'α' 2 (localBuf 'α' sr 2)) m}
 > in audition (out 0 (bufCombC b z l 0.2))
 
 asLocalBuf combines localBuf and setBuf
diff --git a/Help/UGen/IO/localIn.help.lhs b/Help/UGen/IO/localIn.help.lhs
--- a/Help/UGen/IO/localIn.help.lhs
+++ b/Help/UGen/IO/localIn.help.lhs
@@ -4,7 +4,7 @@
 > import Sound.SC3.ID
 
 Ping-pong delay
-> let {n = whiteNoise 'a' AR
+> let {n = whiteNoise 'α' AR
 >     ;a0 = decay (impulse AR 0.3 0) 0.1 * n * 0.2
 >     ;a1 = localIn 2 AR + mce [a0,0]
 >     ;a2 = delayN a1 0.2 0.2
diff --git a/Help/UGen/Noise/choose.help.lhs b/Help/UGen/Noise/choose.help.lhs
--- a/Help/UGen/Noise/choose.help.lhs
+++ b/Help/UGen/Noise/choose.help.lhs
@@ -5,5 +5,5 @@
 
 > import Sound.SC3.ID
 
-> let f = udup 2 (choose 'a' (mce [440,460 .. 880]))
+> let f = uclone 'a' 2 (choose 'a' (mce [440,460 .. 880]))
 > in audition (out 0 (sinOsc AR f  0 * 0.1))
diff --git a/Help/UGen/Noise/randSeed.help.lhs b/Help/UGen/Noise/randSeed.help.lhs
--- a/Help/UGen/Noise/randSeed.help.lhs
+++ b/Help/UGen/Noise/randSeed.help.lhs
@@ -4,7 +4,7 @@
 > import Sound.SC3.ID
 
 start a noise patch
-> let {n = udup 2 (whiteNoise 'a' AR * 0.05 + dust2 'a' AR 70)
+> let {n = uclone 'a' 2 (whiteNoise 'a' AR * 0.05 + dust2 'a' AR 70)
 >     ;f = lfNoise1 'a' KR 3 * 5500 + 6000
 >     ;r = resonz (n * 5) f 0.5 + n * 0.5}
 > in audition (out 0 r)
diff --git a/Help/UGen/Noise/tRand.help.lhs b/Help/UGen/Noise/tRand.help.lhs
--- a/Help/UGen/Noise/tRand.help.lhs
+++ b/Help/UGen/Noise/tRand.help.lhs
@@ -3,6 +3,6 @@
 
 > import Sound.SC3.ID
 
-> let {t = dust 'a' KR (mce2 5 12)
->     ;f = tRand 'b' (mce2 200 1600) (mce2 500 3000) t}
+> let {t = dust 'α' KR (mce2 5 12)
+>     ;f = tRand 'β' (mce2 200 1600) (mce2 500 3000) t}
 > in audition (out 0 (sinOsc AR f 0 * 0.2))
diff --git a/Help/UGen/Oscillator/blip.help.lhs b/Help/UGen/Oscillator/blip.help.lhs
--- a/Help/UGen/Oscillator/blip.help.lhs
+++ b/Help/UGen/Oscillator/blip.help.lhs
@@ -12,3 +12,8 @@
 Modulate number of harmonics.
 > let nh = line KR 1 100 20 RemoveSynth
 > in audition (out 0 (blip AR 200 nh * 0.2))
+
+Self-modulation at control rate.
+> let {fr = blip KR 0.25 3 * 300 + 500
+>     ;nh = blip KR 0.15 2 * 20 + 21}
+> in audition (out 0 (blip AR fr nh * 0.2))
diff --git a/Help/UGen/Oscillator/fSinOsc.help.lhs b/Help/UGen/Oscillator/fSinOsc.help.lhs
--- a/Help/UGen/Oscillator/fSinOsc.help.lhs
+++ b/Help/UGen/Oscillator/fSinOsc.help.lhs
@@ -15,26 +15,25 @@
 > let f = fSinOsc AR (xLine KR 4 401 8 RemoveSynth)
 > in audition (out 0 (fSinOsc AR (f 0 * 200 + 800) 0 * 0.1))
 
-sin grain with sin envelope
-> let {b = control IR "out" 0
->     ;f = control IR "freq" 440
->     ;d = control IR "dur" 0.2
->     ;a = control IR "amp" 0.1
->     ;p = control IR "pan" 0
->     ;o = fSinOsc AR f 0
->     ;s = envSine d a
->     ;e = envGen AR 1 1 0 1 RemoveSynth s
->     ;u = offsetOut b (pan2 o p e)
->     ;i = synthdef "grain" u}
-> in withSC3 (async (d_recv i))
+sin grain with sine envelope (see also 'sine_grain_ugen_graph')
+> let sine = let {b = control IR "out" 0
+>                ;f = control IR "freq" 440
+>                ;d = control IR "dur" 0.2
+>                ;a = control IR "amp" 0.1
+>                ;p = control IR "pan" 0
+>                ;o = fSinOsc AR f 0
+>                ;s = envSine d a
+>                ;e = envGen AR 1 1 0 1 RemoveSynth s
+>                ;u = offsetOut b (pan2 o p e)}
+>            in synthdef "sine" u
 
-> import Sound.SC3.Lang.Pattern.ID
+> import Sound.SC3.Lang.Pattern {- hsc3-lang -}
 
 granular synthesis
-> let p = pbind [("midinote",fmap fround (pbrown 'a' 72 84 1 inf))
->               ,("detune",pwhite 'a' 0 10 inf)
->               ,("dur",pbrown 'b' 0.005 0.15 0.05 inf)
->               ,("legato",pbrown 'c' 1 2 0.1 inf)
->               ,("amp",pbrown 'd' 0.05 0.25 0.05 inf)
->               ,("pan",pbrown 'e' (-1) 1 0.2 inf)]
-> in audition ("grain",p)
+> audition (pbind [(K_instr,psynth sine)
+>                 ,(K_midinote,fmap roundE (pbrown 'α' 72 84 1 inf))
+>                 ,(K_detune,pwhite 'β' 0 10 inf)
+>                 ,(K_dur,pbrown 'γ' 0.005 0.15 0.05 inf)
+>                 ,(K_legato,pbrown 'δ' 1 2 0.1 inf)
+>                 ,(K_amp,pbrown 'ε' 0.05 0.25 0.05 inf)
+>                 ,(K_param "pan",pbrown 'ζ' (-1) 1 0.2 inf)])
diff --git a/Help/UGen/Oscillator/lfGauss.help.lhs b/Help/UGen/Oscillator/lfGauss.help.lhs
--- a/Help/UGen/Oscillator/lfGauss.help.lhs
+++ b/Help/UGen/Oscillator/lfGauss.help.lhs
@@ -52,25 +52,31 @@
 
 > withSC3 (send (n_trace [-1]))
 
-gabor grain
-> let {b = control IR "out" 0
->     ;f = control IR "freq" 440
->     ;s = control IR "sustain" 1
->     ;p = control IR "pan" 1
->     ;a = control IR "amp" 0.1
->     ;w = control IR "width" 0.25
->     ;e = lfGauss AR s w 0 NoLoop RemoveSynth
->     ;o = fSinOsc AR f (pi / 2) * e
->     ;u = offsetOut b (pan2 o p a)
->     ;i = synthdef "gabor" u}
-> in withSC3 (async (d_recv i))
+gabor grain (see also 'gabor_grain_ugen_graph')
+> let gabor = let {b = control IR "out" 0
+>                 ;f = control IR "freq" 440
+>                 ;s = control IR "sustain" 1
+>                 ;p = control IR "pan" 1
+>                 ;a = control IR "amp" 0.1
+>                 ;w = control IR "width" 0.25
+>                 ;e = lfGauss AR s w 0 NoLoop RemoveSynth
+>                 ;o = fSinOsc AR f (pi / 2) * e
+>                 ;u = offsetOut b (pan2 o p a)}
+>             in synthdef "gabor" u
 
-> import Sound.SC3.Lang.Pattern.ID
+> import Sound.SC3.Lang.Pattern {- hsc3-lang -}
 
 granular synthesis, modulating duration, width and pan
-> let {p = pbind [("freq",1000)
->                ,("legato",2)
->                ,("dur",pbrown 'a' 0.005 0.025 0.001 inf)
->                ,("width",pbrown 'b' 0.05 0.25 0.005 inf)
->                ,("pan",pbrown 'c' (-1) 1 0.05 inf)]}
-> in audition ("gabor",p)
+> audition (pbind [(K_instr,psynth gabor)
+>                 ,(K_freq,1000)
+>                 ,(K_legato,2)
+>                 ,(K_dur,pbrown 'α' 0.005 0.025 0.001 inf)
+>                 ,(K_param "width",pbrown 'β' 0.05 0.25 0.005 inf)
+>                 ,(K_param "pan",pbrown 'γ' (-1) 1 0.05 inf)])
+
+granular synthesis, modulating width only
+> audition (pbind [(K_instr,psynth gabor)
+>                 ,(K_freq,1000)
+>                 ,(K_dur,0.01)
+>                 ,(K_param "width",pgeom 0.25 0.995 1250)
+>                 ,(K_legato,2)])
diff --git a/Help/UGen/Oscillator/pmOsc.help.lhs b/Help/UGen/Oscillator/pmOsc.help.lhs
--- a/Help/UGen/Oscillator/pmOsc.help.lhs
+++ b/Help/UGen/Oscillator/pmOsc.help.lhs
@@ -7,10 +7,10 @@
 > import Sound.SC3.ID
 
 Random parameters, linear modulation index motion over n seconds
-> let pmi n = let {cf = rand 'a' 0 2000
->                 ;mf = rand 'b' 0 800
->                 ;pme = rand 'c' 0 12
->                 ;l = rand 'd' (-1) 1
+> let pmi n = let {cf = rand 'α' 0 2000
+>                 ;mf = rand 'β' 0 800
+>                 ;pme = rand 'γ' 0 12
+>                 ;l = rand 'δ' (-1) 1
 >                 ;pm = line KR 0 pme n DoNothing}
 > in linPan2 (pmOsc AR cf mf pm 0) l 0.05
 
diff --git a/Help/UGen/Oscillator/tGrains.help.lhs b/Help/UGen/Oscillator/tGrains.help.lhs
--- a/Help/UGen/Oscillator/tGrains.help.lhs
+++ b/Help/UGen/Oscillator/tGrains.help.lhs
@@ -16,9 +16,9 @@
 > let {b = 10
 >     ;rt = mouseY KR 8 120 Exponential 0.1
 >     ;dur = 4 / rt
->     ;clk = dust 'a' AR rt
->     ;r = tRand 'a' 0 0.01 clk
->     ;pan = whiteNoise 'a' KR * 0.6
+>     ;clk = dust 'α' AR rt
+>     ;r = tRand 'β' 0 0.01 clk
+>     ;pan = whiteNoise 'γ' KR * 0.6
 >     ;x = mouseX KR 0 (bufDur KR b) Linear 0.1
 >     ;pos = x + r}
 > in audition (out 0 (tGrains 2 clk b 1 pos dur pan 0.1 2))
@@ -28,8 +28,8 @@
 >     ;dur = 1.2 / rt
 >     ;clk = impulse AR rt 0
 >     ;pos = mouseX KR 0 (bufDur KR b) Linear 0.1
->     ;n0 = whiteNoise 'a' KR
->     ;n1 = whiteNoise 'b' KR
+>     ;n0 = whiteNoise 'α' KR
+>     ;n1 = whiteNoise 'β' KR
 >     ;rate = shiftLeft 1.2 (roundTo (n0 * 3) 1)}
 > in audition (out 0 (tGrains 2 clk b rate pos dur (n1 * 0.6) 0.25 2))
 
@@ -41,9 +41,9 @@
 >                                ,dgeom e1 (diwhite e1 1 20 40) 1 (1 - d e1)])
 >     ;clk = impulse AR rt 0
 >     ;dsq e xs = dseq e dinf (mce xs)
->     ;rate = dsq 'a' [1,1,z 'a' 'b',0.5,0.5,0.2,0.1,0.1,0.1,0.1] * 2 + 1
->     ;pos = dsq 'b' (take 8 (zipWith z ['a'..] ['A'..]))
->     ;dur = dsq 'c' [1,d 'x',1,z 'x' 'X',0.5,0.5,0.1,z 'y' 'Y'] * 2 / rt
->     ;pan = dsq 'd' [1,1,1,0.5,0.2,0.1,0,0,0] * 2 - 1
->     ;amp = dsq 'e' [1,0,z 'z' 'Z',0,2,1,1,0.1,0.1]}
+>     ;rate = dsq 'α' [1,1,z 'β' 'γ',0.5,0.5,0.2,0.1,0.1,0.1,0.1] * 2 + 1
+>     ;pos = dsq 'δ' (take 8 (zipWith z ['ε'..] ['ζ'..]))
+>     ;dur = dsq 'η' [1,d 'θ',1,z 'ι' 'κ',0.5,0.5,0.1,z 'λ' 'μ'] * 2 / rt
+>     ;pan = dsq 'ν' [1,1,1,0.5,0.2,0.1,0,0,0] * 2 - 1
+>     ;amp = dsq 'ξ' [1,0,z 'ο' 'π',0,2,1,1,0.1,0.1]}
 > in audition (out 0 (tGrains 2 clk b rate pos dur pan amp 2))
diff --git a/README b/README
--- a/README
+++ b/README
@@ -16,11 +16,12 @@
 - [hsc3-cairo](?t=hsc3-cairo) & [hsc3-plot](?t=hsc3-plot): Drawing & Plotting
 - [hsc3-rec](?t=hsc3-rec) & [hsc3-unsafe](?t=hsc3-rec): UGen Variants
 - [hsc3-db](?t=hsc3-db): UGen Database
+- [hsc3-rw](?t=hsc3-rw): UGen Graph Re-writing
 
 The hsc3 interaction environment is written for [GNU][gnu]
 [Emacs][emacs].
 
-© [rohan drape][rd] and others, 2006-2012, [gpl][gpl].
+© [rohan drape][rd] and others, 2006-2013, [gpl][gpl].
 with contributions by:
 
 - henning thielemann
diff --git a/Sound/SC3/Monad.hs b/Sound/SC3/Monad.hs
--- a/Sound/SC3/Monad.hs
+++ b/Sound/SC3/Monad.hs
@@ -1,5 +1,6 @@
 -- | Composite of "Sound.SC3.UGen.Monad" and "Sound.SC3.Server.Monad"
 module Sound.SC3.Monad (module M) where
 
+import Sound.SC3.Monad.Syntax as M
 import Sound.SC3.UGen.Monad as M
 import Sound.SC3.Server.Monad as M
diff --git a/Sound/SC3/Monad/Syntax.hs b/Sound/SC3/Monad/Syntax.hs
new file mode 100644
--- /dev/null
+++ b/Sound/SC3/Monad/Syntax.hs
@@ -0,0 +1,58 @@
+-- | Functions to make writing 'Applicative' and 'Monad' UGen graphs
+-- less clumsy.
+module Sound.SC3.Monad.Syntax where
+
+import Control.Applicative {- base -}
+import Control.Monad {- base -}
+
+infixl 7  .*,*.,.*.
+infixl 6  .+,+.,.+.
+
+-- | '+' variant with 'Functor' at left.
+--
+-- > fmap (== 5) (return 3 .+ 2)
+(.+) :: (Functor f, Num a) => f a -> a -> f a
+m .+ n = fmap (+ n) m
+
+-- | '+' variant with 'Functor' at right.
+--
+-- > fmap (== 5) (3 +. return 2)
+(+.) :: (Functor f, Num a) => a -> f a -> f a
+m +. n = fmap (+ m) n
+
+-- | '+' variant with 'Applicative' at left and right.
+--
+-- > fmap (== 5) (return 3 .+. return 2)
+(.+.) :: (Applicative m, Num a) => m a -> m a -> m a
+(.+.) = liftA2 (+)
+
+-- | '*' variant with 'Functor' at left.
+--
+-- > fmap (== 6) (return 3 .* 2)
+(.*) :: (Functor f, Num a) => f a -> a -> f a
+m .* n = fmap (* n) m
+
+-- | '*' variant with 'Functor' at right.
+--
+-- > fmap (== 6) (3 *. return 2)
+(*.) :: (Functor f, Num a) => a -> f a -> f a
+m *. n = fmap (* m) n
+
+-- | '*' variant with 'Applicative' at left and right.
+--
+-- > fmap (== 6) (return 3 .*. return 2)
+(.*.) :: (Applicative m, Num a) => m a -> m a -> m a
+(.*.) = liftA2 (*)
+
+-- | Right to left compositon of 'Monad' functions.
+--
+-- > fmap (== 7) (composeM [return . (+ 1),return . (* 2)] 3)
+-- > fmap (== 8) (composeM [return . (* 2),return . (+ 1)] 3)
+composeM :: Monad m => [a -> m a] -> a -> m a
+composeM f = foldr (<=<) return f
+
+-- | Feed forward composition of /n/ applications of /f/.
+--
+-- > fmap (== 3) (chainM 3 (return . (+ 1)) 0)
+chainM :: Monad m => Int -> (b -> m b) -> b -> m b
+chainM n f = foldr (<=<) return (replicate n f)
diff --git a/Sound/SC3/Server.hs b/Sound/SC3/Server.hs
--- a/Sound/SC3/Server.hs
+++ b/Sound/SC3/Server.hs
@@ -3,7 +3,9 @@
 -- "Sound.SC3.Server.Monad".
 module Sound.SC3.Server (module S) where
 
-import Sound.SC3.Server.Command as S
+import Sound.SC3.Server.Command.Core as S
+import Sound.SC3.Server.Command.Int as S
+import Sound.SC3.Server.Command.Double as S
 import Sound.SC3.Server.Enum as S
 import Sound.SC3.Server.Synthdef as S
 import Sound.SC3.Server.Synthdef.Type as S
diff --git a/Sound/SC3/Server/Command.hs b/Sound/SC3/Server/Command.hs
deleted file mode 100644
--- a/Sound/SC3/Server/Command.hs
+++ /dev/null
@@ -1,447 +0,0 @@
--- | Constructors for the command set implemented by the SuperCollider
---   synthesis server.
-module Sound.SC3.Server.Command where
-
-import Data.Maybe
-import Sound.OpenSoundControl {- hosc -}
-import Sound.SC3.Server.Enum
-import Sound.SC3.Server.Utilities
-import Sound.SC3.Server.Synthdef
-import Sound.SC3.Server.Synthdef.Type
-import Sound.SC3.UGen.Enum
-
--- * Instrument definition commands
-
--- | Install a bytecode instrument definition. (Asynchronous)
-d_recv :: Synthdef -> Message
-d_recv d = message "/d_recv" [Blob (synthdefData d)]
-
--- | Load an instrument definition from a named file. (Asynchronous)
-d_load :: String -> Message
-d_load p = message "/d_load" [String p]
-
--- | Load a directory of instrument definitions files. (Asynchronous)
-d_loadDir :: String -> Message
-d_loadDir p = message "/d_loadDir" [String p]
-
--- | Remove definition once all nodes using it have ended.
-d_free :: [String] -> Message
-d_free = message "/d_free" . map String
-
--- * Node commands
-
--- | Place a node after another.
-n_after :: [(Int, Int)] -> Message
-n_after = message "/n_after" . mk_duples Int Int
-
--- | Place a node before another.
-n_before :: [(Int, Int)] -> Message
-n_before = message "/n_before" . mk_duples Int Int
-
--- | Fill ranges of a node's control values.
-n_fill :: Int -> [(String, Int, Double)] -> Message
-n_fill nid l = message "/n_fill" (Int nid : mk_triples String Int Float l)
-
--- | Delete a node.
-n_free :: [Int] -> Message
-n_free = message "/n_free" . map Int
-
--- | Map a node's controls to read from a bus.
-n_map :: Int -> [(String, Int)] -> Message
-n_map nid l = message "/n_map" (Int nid : mk_duples String Int l)
-
--- | Map a node's controls to read from buses.
-n_mapn :: Int -> [(String, Int, Int)] -> Message
-n_mapn nid l = message "/n_mapn" (Int nid : mk_triples String Int Int l)
-
--- | Map a node's controls to read from an audio bus.
-n_mapa :: Int -> [(String, Int)] -> Message
-n_mapa nid l = message "/n_mapa" (Int nid : mk_duples String Int l)
-
--- | Map a node's controls to read from audio buses.
-n_mapan :: Int -> [(String, Int, Int)] -> Message
-n_mapan nid l = message "/n_mapan" (Int nid : mk_triples String Int Int l)
-
--- | Get info about a node.
-n_query :: [Int] -> Message
-n_query = message "/n_query" . map Int
-
--- | Turn node on or off.
-n_run :: [(Int, Bool)] -> Message
-n_run = message "/n_run" . mk_duples Int (Int . fromEnum)
-
--- | Set a node's control values.
-n_set :: Int -> [(String, Double)] -> Message
-n_set nid c = message "/n_set" (Int nid : mk_duples String Float c)
-
--- | Set ranges of a node's control values.
-n_setn :: Int -> [(String, [Double])] -> Message
-n_setn nid l = message "/n_setn" (Int nid : concatMap f l)
-    where f (s,d) = String s : Int (length d) : map Float d
-
--- | Trace a node.
-n_trace :: [Int] -> Message
-n_trace = message "/n_trace" . map Int
-
--- | Move an ordered sequence of nodes.
-n_order :: AddAction -> Int -> [Int] -> Message
-n_order a n ns = message "/n_order" (Int (fromEnum a) : Int n : map Int ns)
-
--- * Synthesis node commands
-
--- | Get control values.
-s_get :: Int -> [String] -> Message
-s_get nid i = message "/s_get" (Int nid : map String i)
-
--- | Get ranges of control values.
-s_getn :: Int -> [(String, Int)] -> Message
-s_getn nid l = message "/s_getn" (Int nid : mk_duples String Int l)
-
--- | Enumeration of possible locations to add new nodes (s_new and g_new).
-data AddAction = AddToHead
-               | AddToTail
-               | AddBefore
-               | AddAfter
-               | AddReplace
-                 deriving (Eq, Show, Enum)
-
--- | Create a new synth.
-s_new :: String -> Int -> AddAction -> Int -> [(String, Double)] -> Message
-s_new n i a t c = message "/s_new" (String n : Int i : Int (fromEnum a) : Int t : mk_duples String Float c)
-
--- | Auto-reassign synth's ID to a reserved value.
-s_noid :: [Int] -> Message
-s_noid = message "/s_noid" . map Int
-
--- * Group node commands
-
--- | Free all synths in this group and all its sub-groups.
-g_deepFree :: [Int] -> Message
-g_deepFree = message "/g_deepFree" . map Int
-
--- | Delete all nodes in a group.
-g_freeAll :: [Int] -> Message
-g_freeAll = message "/g_freeAll" . map Int
-
--- | Add node to head of group.
-g_head :: [(Int, Int)] -> Message
-g_head = message "/g_head" . mk_duples Int Int
-
--- | Create a new group.
-g_new :: [(Int, AddAction, Int)] -> Message
-g_new = message "/g_new" . mk_triples Int (Int . fromEnum) Int
-
--- | Add node to tail of group.
-g_tail :: [(Int, Int)] -> Message
-g_tail = message "/g_tail" . mk_duples Int Int
-
--- | Post a representation of a group's node subtree, optionally including the current control values for synths.
-g_dumpTree :: [(Int, Bool)] -> Message
-g_dumpTree = message "/g_dumpTree" . mk_duples Int (Int . fromEnum)
-
--- | Request a representation of a group's node subtree, optionally including the current control values for synths.
---
--- Replies to the sender with a @/g_queryTree.reply@ message listing all of the nodes contained within the group in the following format:
---
--- > int - if synth control values are included 1, else 0
--- > int - node ID of the requested group
--- > int - number of child nodes contained within the requested group
--- >
--- > For each node in the subtree:
--- > [
--- >   int - node ID
--- >   int - number of child nodes contained within this node. If -1 this is a synth, if >= 0 it's a group.
--- >
--- >   If this node is a synth:
--- >     symbol - the SynthDef name for this node.
--- >
--- >   If flag (see above) is true:
--- >     int - numControls for this synth (M)
--- >     [
--- >       symbol or int: control name or index
--- >       float or symbol: value or control bus mapping symbol (e.g. 'c1')
--- >     ] * M
--- > ] * the number of nodes in the subtree
---
--- N.B. The order of nodes corresponds to their execution order on the server. Thus child nodes (those contained within a group) are listed immediately following their parent.
-g_queryTree :: [(Int, Bool)] -> Message
-g_queryTree = message "/g_queryTree" . mk_duples Int (Int . fromEnum)
-
--- | Create a new parallel group (supernova specific).
-p_new :: [(Int, AddAction, Int)] -> Message
-p_new = message "/p_new" . mk_triples Int (Int . fromEnum) Int
-
--- * Plugin commands
-
--- | Send a plugin command.
-cmd :: String -> [Datum] -> Message
-cmd name = message "/cmd" . (String name :)
-
--- * Unit Generator commands
-
--- | Send a command to a unit generator.
-u_cmd :: Int -> Int -> String -> [Datum] -> Message
-u_cmd nid uid name arg = message "/u_cmd" ([Int nid, Int uid, String name] ++ arg)
-
--- * Buffer commands
-
--- | Allocates zero filled buffer to number of channels and samples. (Asynchronous)
-b_alloc :: Int -> Int -> Int -> Message
-b_alloc nid frames channels = message "/b_alloc" [Int nid, Int frames, Int channels]
-
--- | Allocate buffer space and read a sound file. (Asynchronous)
-b_allocRead :: Int -> String -> Int -> Int -> Message
-b_allocRead nid p f n = message "/b_allocRead" [Int nid, String p, Int f, Int n]
-
--- | Allocate buffer space and read a sound file, picking specific channels. (Asynchronous)
-b_allocReadChannel :: Int -> String -> Int -> Int -> [Int] -> Message
-b_allocReadChannel nid p f n cs = message "/b_allocReadChannel" ([Int nid, String p, Int f, Int n] ++ map Int cs)
-
--- | Close attached soundfile and write header information. (Asynchronous)
-b_close :: Int -> Message
-b_close nid = message "/b_close" [Int nid]
-
--- | Fill ranges of sample values.
-b_fill :: Int -> [(Int, Int, Double)] -> Message
-b_fill nid l = message "/b_fill" (Int nid : mk_triples Int Int Float l)
-
--- | Free buffer data. (Asynchronous)
-b_free :: Int -> Message
-b_free nid = message "/b_free" [Int nid]
-
--- | Call a command to fill a buffer.  (Asynchronous)
-b_gen :: Int -> String -> [Datum] -> Message
-b_gen bid name arg = message "/b_gen" (Int bid : String name : arg)
-
--- | Call @sine1@ 'b_gen' command.
-b_gen_sine1 :: Int -> [B_Gen] -> [Double] -> Message
-b_gen_sine1 z f n = b_gen z "sine1" (Int (b_gen_flag f) : map Float n)
-
--- | Call @sine2@ 'b_gen' command.
-b_gen_sine2 :: Int -> [B_Gen] -> [(Double,Double)] -> Message
-b_gen_sine2 z f n = b_gen z "sine2" (Int (b_gen_flag f) : mk_duples Float Float n)
-
--- | Call @sine3@ 'b_gen' command.
-b_gen_sine3 :: Int -> [B_Gen] -> [(Double,Double,Double)] -> Message
-b_gen_sine3 z f n = b_gen z "sine3" (Int (b_gen_flag f) : mk_triples Float Float Float n)
-
--- | Call @cheby@ 'b_gen' command.
-b_gen_cheby :: Int -> [B_Gen] -> [Double] -> Message
-b_gen_cheby z f n = b_gen z "cheby" (Int (b_gen_flag f) : map Float n)
-
--- | Call @copy@ 'b_gen' command.
-b_gen_copy :: Int -> Int -> Int -> Int -> Maybe Int -> Message
-b_gen_copy z dst_ix src_b src_ix nf =
-    let nf' = fromMaybe (-1) nf
-    in b_gen z "copy" (map Int [dst_ix,src_b,src_ix,nf'])
-
--- | Get sample values.
-b_get :: Int -> [Int] -> Message
-b_get nid i = message "/b_get" (Int nid : map Int i)
-
--- | Get ranges of sample values.
-b_getn :: Int -> [(Int, Int)] -> Message
-b_getn nid l = message "/b_getn" (Int nid : mk_duples Int Int l)
-
--- | Request \/b_info messages.
-b_query :: [Int] -> Message
-b_query = message "/b_query" . map Int
-
--- | Read sound file data into an existing buffer. (Asynchronous)
-b_read :: Int -> String -> Int -> Int -> Int -> Bool -> Message
-b_read nid p f n f' z = message "/b_read" [Int nid, String p, Int f, Int n, Int f', Int (fromEnum z)]
-
--- | Read sound file data into an existing buffer, picking specific channels. (Asynchronous)
-b_readChannel :: Int -> String -> Int -> Int -> Int -> Bool -> [Int] -> Message
-b_readChannel nid p f n f' z cs = message "/b_readChannel" ([Int nid, String p, Int f, Int n, Int f', Int (fromEnum z)] ++ map Int cs)
-
--- | Set sample values.
-b_set :: Int -> [(Int, Double)] -> Message
-b_set nid l = message "/b_set" (Int nid : mk_duples Int Float l)
-
--- | Set ranges of sample values.
-b_setn :: Int -> [(Int, [Double])] -> Message
-b_setn nid l = message "/b_setn" (Int nid : concatMap f l)
-    where f (i,d) = Int i : Int (length d) : map Float d
-
--- | Write sound file data. (Asynchronous)
-b_write :: Int -> String -> SoundFileFormat -> SampleFormat -> Int -> Int -> Bool -> Message
-b_write nid p h t f s z = message "/b_write" [Int nid, String p, String (soundFileFormatString h), String (sampleFormatString t), Int f, Int s, Int (fromEnum z)]
-
--- | Zero sample data. (Asynchronous)
-b_zero :: Int -> Message
-b_zero nid = message "/b_zero" [Int nid]
-
--- * Control bus commands
-
--- |  Fill ranges of bus values.
-c_fill :: [(Int, Int, Double)] -> Message
-c_fill = message "/c_fill" . mk_triples Int Int Float
-
--- | Get bus values.
-c_get :: [Int] -> Message
-c_get = message "/c_get" . map Int
-
--- | Get ranges of bus values.
-c_getn :: [(Int, Int)] -> Message
-c_getn = message "/c_getn" . mk_duples Int Int
-
--- | Set bus values.
-c_set :: [(Int, Double)] -> Message
-c_set = message "/c_set" . mk_duples Int Float
-
--- | Set ranges of bus values.
-c_setn :: [(Int, [Double])] -> Message
-c_setn l = message "/c_setn" (concatMap f l)
-    where f (i,d) = Int i : Int (length d) : map Float d
-
--- * Server operation commands
-
--- | Remove all bundles from the scheduling queue.
-clearSched :: Message
-clearSched = message "/clearSched" []
-
--- | Enumeration of Message printer types.
-data PrintLevel = NoPrinter
-                | TextPrinter
-                | HexPrinter
-                | AllPrinter
-                  deriving (Eq, Show, Enum)
-
--- | Select printing of incoming Open Sound Control messages.
-dumpOSC :: PrintLevel -> Message
-dumpOSC c = message "/dumpOSC" [Int (fromEnum c)]
-
--- | Select reception of notification messages. (Asynchronous)
-notify :: Bool -> Message
-notify c = message "/notify" [Int (fromEnum c)]
-
--- | Stop synthesis server.
-quit :: Message
-quit = message "/quit" []
-
--- | Request \/status.reply message.
-status :: Message
-status = message "/status" []
-
--- | Request \/synced message when all current asynchronous commands complete.
-sync :: Int -> Message
-sync sid = message "/sync" [Int sid]
-
--- | Error posting scope.
-data ErrorScope = Globally  -- ^ Global scope
-                | Locally   -- ^ Bundle scope
-                  deriving (Eq, Show, Enum)
-
--- | Error posting mode.
-data ErrorMode = ErrorsOff  -- ^ Turn error posting off
-               | ErrorsOn   -- ^ Turn error posting on
-                 deriving (Eq, Show, Enum)
-
--- | Set error posting scope and mode.
-errorMode :: ErrorScope -> ErrorMode -> Message
-errorMode scope mode = message "/error" [Int e]
-    where e = case scope of
-                Globally -> fromEnum mode
-                Locally  -> -1 - fromEnum mode
-
--- * Variants to simplify common cases
-
--- | Pre-allocate for b_setn1, values preceding offset are zeroed.
-b_alloc_setn1 :: Int -> Int -> [Double] -> Message
-b_alloc_setn1 nid i xs =
-    let k = i + length xs
-        xs' = replicate i 0 ++ xs
-    in withCM (b_alloc nid k 1) (b_setn1 nid 0 xs')
-
--- | Get ranges of sample values.
-b_getn1 :: Int -> (Int,Int) -> Message
-b_getn1 nid = b_getn nid . return
-
--- | Set single sample value.
-b_set1 :: Int -> Int -> Double -> Message
-b_set1 nid i x = b_set nid [(i,x)]
-
--- | Set a range of sample values.
-b_setn1 :: Int -> Int -> [Double] -> Message
-b_setn1 nid i xs = b_setn nid [(i,xs)]
-
--- | Variant on 'b_query'.
-b_query1 :: Int -> Message
-b_query1 = b_query . return
-
--- | Set single bus values.
-c_set1 :: Int -> Double -> Message
-c_set1 i x = c_set [(i, x)]
-
--- | Set a signle node control value.
-n_set1 :: Int -> String -> Double -> Message
-n_set1 nid k n = n_set nid [(k, n)]
-
--- * Modify existing message to include completion message
-
--- | List of asynchronous server commands.
-async_cmds :: [String]
-async_cmds =
-    ["/b_alloc"
-    ,"/b_allocRead"
-    ,"/b_allocReadChannel"
-    ,"/b_close"
-    ,"/b_free"
-    ,"/b_read"
-    ,"/b_readChannel"
-    ,"/b_write"
-    ,"/b_zero"
-    ,"/d_load"
-    ,"/d_loadDir"
-    ,"/d_recv"
-    ,"/notify"
-    ,"/quit"
-    ,"/sync"]
-
--- | 'True' if 'Message' is an asynchronous 'Message'.
---
--- > map isAsync [b_close 0,n_set1 0 "0" 0] == [True,False]
-isAsync :: Message -> Bool
-isAsync (Message a _) = a `elem` async_cmds
-
--- | Add a completion message (or bundle, the name is misleading) to
--- an existing asynchronous command.
---
--- > let {m = n_set1 0 "0" 0
--- >     ;m' = encodeMessage m}
--- > in withCM (b_close 0) m == Message "/b_close" [Int 0,Blob m']
-withCM :: OSC o => Message -> o -> Message
-withCM (Message c xs) cm =
-    if c `elem` async_cmds
-    then let xs' = xs ++ [Blob (encodeOSC cm)]
-         in message c xs'
-    else error ("withCM: not async: " ++ c)
-
--- * Buffer segmentation and indices
-
--- | Segment a request for /m/ places into sets of at most /n/.
---
--- > b_segment 1024 2056 == [8,1024,1024]
--- > b_segment 1 5 == replicate 5 1
-b_segment :: Int -> Int -> [Int]
-b_segment n m =
-    let (q,r) = m `quotRem` n
-        s = replicate q n
-    in if r == 0 then s else r : s
-
--- | Variant of 'b_segment' that takes a starting index and returns
--- /(index,size)/ duples.
---
--- > b_indices 1 5 0 == zip [0..4] (replicate 5 1)
--- > b_indices 1024 2056 16 == [(16,8),(24,1024),(1048,1024)]
-b_indices :: Int -> Int -> Int -> [(Int,Int)]
-b_indices n m k =
-    let dx_d = scanl1 (+)
-        s = b_segment n m
-        i = 0 : dx_d s
-    in zip (map (+ k) i) s
-
--- Local Variables:
--- truncate-lines:t
--- End:
diff --git a/Sound/SC3/Server/Command/Completion.hs b/Sound/SC3/Server/Command/Completion.hs
--- a/Sound/SC3/Server/Command/Completion.hs
+++ b/Sound/SC3/Server/Command/Completion.hs
@@ -6,28 +6,27 @@
 -- @\/sync@ barrier.
 module Sound.SC3.Server.Command.Completion
   ( -- *Synthdef handling
-    d_recv'
-  , d_load'
-  , d_loadDir'
+   d_recv'
+  ,d_load'
+  ,d_loadDir'
   -- *Buffer allocation
-  , b_alloc'
-  , b_allocRead'
-  , b_allocReadChannel'
-  , b_free'
-  , b_close'
+  ,b_alloc'
+  ,b_allocRead'
+  ,b_allocReadChannel'
+  ,b_free'
+  ,b_close'
   -- *Buffer reading
-  , b_read'
-  , b_readChannel'
+  ,b_read'
+  ,b_readChannel'
   -- *Buffer writing
-  , b_write'
+  ,b_write'
   -- *Buffer operations
-  , b_zero'
+  ,b_zero'
   ) where
 
-import Sound.OpenSoundControl
+import Sound.OSC {- hosc -}
 import Sound.SC3.Server.Enum
 import Sound.SC3.Server.Synthdef
-import Sound.SC3.Server.Synthdef.Type
 
 -- Encode an OSC packet as an OSC blob.
 encode_blob :: OSC o => o -> Datum
@@ -35,51 +34,51 @@
 
 -- | Install a bytecode instrument definition. (Asynchronous)
 d_recv' :: OSC o => o -> Synthdef -> Message
-d_recv' osc d = message "/d_recv" [Blob (synthdefData d), encode_blob osc]
+d_recv' osc d = message "/d_recv" [Blob (synthdefData d),encode_blob osc]
 
 -- | Load an instrument definition from a named file. (Asynchronous)
 d_load' :: OSC o => o -> String -> Message
-d_load' osc p = message "/d_load" [String p, encode_blob osc]
+d_load' osc p = message "/d_load" [string p,encode_blob osc]
 
 -- | Load a directory of instrument definitions files. (Asynchronous)
 d_loadDir' :: OSC o => o -> String -> Message
-d_loadDir' osc p = message "/d_loadDir" [String p, encode_blob osc]
+d_loadDir' osc p = message "/d_loadDir" [string p,encode_blob osc]
 
 -- | Allocates zero filled buffer to number of channels and samples. (Asynchronous)
 b_alloc' :: OSC o => o -> Int -> Int -> Int -> Message
-b_alloc' osc nid frames channels = message "/b_alloc" [Int nid, Int frames, Int channels, encode_blob osc]
+b_alloc' osc nid frames channels = message "/b_alloc" [int32 nid,int32 frames,int32 channels,encode_blob osc]
 
 -- | Allocate buffer space and read a sound file. (Asynchronous)
 b_allocRead' :: OSC o => o -> Int -> String -> Int -> Int -> Message
-b_allocRead' osc nid p f n = message "/b_allocRead" [Int nid, String p, Int f, Int n, encode_blob osc]
+b_allocRead' osc nid p f n = message "/b_allocRead" [int32 nid,string p,int32 f,int32 n,encode_blob osc]
 
 -- | Allocate buffer space and read a sound file, picking specific channels. (Asynchronous)
 b_allocReadChannel' :: OSC o => o -> Int -> String -> Int -> Int -> [Int] -> Message
-b_allocReadChannel' osc nid p f n cs = message "/b_allocReadChannel" ([Int nid, String p, Int f, Int n] ++ map Int cs ++ [encode_blob osc])
+b_allocReadChannel' osc nid p f n cs = message "/b_allocReadChannel" ([int32 nid,string p,int32 f,int32 n] ++ map int32 cs ++ [encode_blob osc])
 
 -- | Free buffer data. (Asynchronous)
 b_free' :: OSC o => o -> Int -> Message
-b_free' osc nid = message "/b_free" [Int nid, encode_blob osc]
+b_free' osc nid = message "/b_free" [int32 nid,encode_blob osc]
 
 -- | Close attached soundfile and write header information. (Asynchronous)
 b_close' :: OSC o => o -> Int -> Message
-b_close' osc nid = message "/b_close" [Int nid, encode_blob osc]
+b_close' osc nid = message "/b_close" [int32 nid,encode_blob osc]
 
 -- | Read sound file data into an existing buffer. (Asynchronous)
 b_read' :: OSC o => o -> Int -> String -> Int -> Int -> Int -> Bool -> Message
-b_read' osc nid p f n f' z = message "/b_read" [Int nid, String p, Int f, Int n, Int f', Int (fromEnum z), encode_blob osc]
+b_read' osc nid p f n f' z = message "/b_read" [int32 nid,string p,int32 f,int32 n,int32 f',int32 (fromEnum z),encode_blob osc]
 
 -- | Read sound file data into an existing buffer. (Asynchronous)
 b_readChannel' :: OSC o => o -> Int -> String -> Int -> Int -> Int -> Bool -> [Int] -> Message
-b_readChannel' osc nid p f n f' z cs = message "/b_readChannel" ([Int nid, String p, Int f, Int n, Int f', Int (fromEnum z)] ++ map Int cs ++ [encode_blob osc])
+b_readChannel' osc 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 ++ [encode_blob osc])
 
 -- | Write sound file data. (Asynchronous)
 b_write' :: OSC o => o -> Int -> String -> SoundFileFormat -> SampleFormat -> Int -> Int -> Bool -> Message
-b_write' osc nid p h t f s z = message "/b_write" [Int nid, String p, String (soundFileFormatString h), String (sampleFormatString t), Int f, Int s, Int (fromEnum z), encode_blob osc]
+b_write' osc nid p h t f s z = message "/b_write" [int32 nid,string p,string (soundFileFormatString h),string (sampleFormatString t),int32 f,int32 s,int32 (fromEnum z),encode_blob osc]
 
 -- | Zero sample data. (Asynchronous)
 b_zero' :: OSC o => o -> Int -> Message
-b_zero' osc nid = message "/b_zero" [Int nid, encode_blob osc]
+b_zero' osc nid = message "/b_zero" [int32 nid,encode_blob osc]
 
 -- Local Variables:
 -- truncate-lines:t
diff --git a/Sound/SC3/Server/Command/Core.hs b/Sound/SC3/Server/Command/Core.hs
new file mode 100644
--- /dev/null
+++ b/Sound/SC3/Server/Command/Core.hs
@@ -0,0 +1,102 @@
+-- | Core non-type variant constructors.
+module Sound.SC3.Server.Command.Core where
+
+import Sound.OSC.Core {- hosc -}
+
+import Sound.SC3.Server.Enum
+import Sound.SC3.Server.Synthdef
+
+-- * Instrument definition commands
+
+-- | Install a bytecode instrument definition. (Asynchronous)
+d_recv :: Synthdef -> Message
+d_recv d = message "/d_recv" [Blob (synthdefData d)]
+
+-- | Load an instrument definition from a named file. (Asynchronous)
+d_load :: String -> Message
+d_load p = message "/d_load" [string p]
+
+-- | Load a directory of instrument definitions files. (Asynchronous)
+d_loadDir :: String -> Message
+d_loadDir p = message "/d_loadDir" [string p]
+
+-- | Remove definition once all nodes using it have ended.
+d_free :: [String] -> Message
+d_free = message "/d_free" . map string
+
+-- * Plugin commands
+
+-- | Send a plugin command.
+cmd :: String -> [Datum] -> Message
+cmd name = message "/cmd" . (string name :)
+
+-- * Server operation commands
+
+-- | Remove all bundles from the scheduling queue.
+clearSched :: Message
+clearSched = message "/clearSched" []
+
+-- | Select printing of incoming Open Sound Control messages.
+dumpOSC :: PrintLevel -> Message
+dumpOSC c = message "/dumpOSC" [int32 (fromEnum c)]
+
+-- | Select reception of notification messages. (Asynchronous)
+notify :: Bool -> Message
+notify c = message "/notify" [int32 (fromEnum c)]
+
+-- | Stop synthesis server.
+quit :: Message
+quit = message "/quit" []
+
+-- | Request \/status.reply message.
+status :: Message
+status = message "/status" []
+
+-- | Set error posting scope and mode.
+errorMode :: ErrorScope -> ErrorMode -> Message
+errorMode scope mode =
+    let e = case scope of
+              Globally -> fromEnum mode
+              Locally  -> -1 - fromEnum mode
+    in message "/error" [int32 e]
+
+-- * Modify existing message to include completion message
+
+-- | List of asynchronous server commands.
+async_cmds :: [String]
+async_cmds =
+    ["/b_alloc"
+    ,"/b_allocRead"
+    ,"/b_allocReadChannel"
+    ,"/b_close"
+    ,"/b_free"
+    ,"/b_read"
+    ,"/b_readChannel"
+    ,"/b_write"
+    ,"/b_zero"
+    ,"/d_load"
+    ,"/d_loadDir"
+    ,"/d_recv"
+    ,"/notify"
+    ,"/quit"
+    ,"/sync"]
+
+-- | 'True' if 'Message' is an asynchronous 'Message'.
+--
+-- > map isAsync [b_close 0,n_set1 0 "0" 0] == [True,False]
+isAsync :: Message -> Bool
+isAsync (Message a _) = a `elem` async_cmds
+
+-- | Add a completion message (or bundle, the name is misleading) to
+-- an existing asynchronous command.
+--
+-- > let {m = n_set1 0 "0" 0
+-- >     ;m' = encodeMessage m}
+-- > in withCM (b_close 0) m == Message "/b_close" [Int 0,Blob m']
+withCM :: OSC o => Message -> o -> Message
+withCM (Message c xs) cm =
+    if c `elem` async_cmds
+    then let xs' = xs ++ [Blob (encodeOSC cm)]
+         in Message c xs'
+    else error ("withCM: not async: " ++ c)
+
diff --git a/Sound/SC3/Server/Command/Double.hs b/Sound/SC3/Server/Command/Double.hs
new file mode 100644
--- /dev/null
+++ b/Sound/SC3/Server/Command/Double.hs
@@ -0,0 +1,85 @@
+-- | Functions from "Sound.SC3.Server.Command.Generic" specialised to 'Int' and 'Double'.
+module Sound.SC3.Server.Command.Double where
+
+import Sound.OSC.Core {- hosc -}
+
+import qualified Sound.SC3.Server.Command.Generic as G
+import Sound.SC3.Server.Enum
+import Sound.SC3.UGen.Enum
+
+-- | Fill ranges of a node's control values.
+n_fill :: Int -> [(String,Int,Double)] -> Message
+n_fill = G.n_fill
+
+-- | Set a node's control values.
+n_set :: Int -> [(String,Double)] -> Message
+n_set = G.n_set
+
+-- | Set ranges of a node's control values.
+n_setn :: Int -> [(String,[Double])] -> Message
+n_setn = G.n_setn
+
+-- | Create a new synth.
+s_new :: String -> Int -> AddAction -> Int -> [(String,Double)] -> Message
+s_new = G.s_new
+
+-- | Fill ranges of sample values.
+b_fill :: Int -> [(Int,Int,Double)] -> Message
+b_fill = G.b_fill
+
+-- | Call @sine1@ 'b_gen' command.
+b_gen_sine1 :: Int -> [B_Gen] -> [Double] -> Message
+b_gen_sine1 = G.b_gen_sine1
+
+-- | Call @sine2@ 'b_gen' command.
+b_gen_sine2 :: Int -> [B_Gen] -> [(Double,Double)] -> Message
+b_gen_sine2 = G.b_gen_sine2
+
+-- | Call @sine3@ 'b_gen' command.
+b_gen_sine3 :: Int -> [B_Gen] -> [(Double,Double,Double)] -> Message
+b_gen_sine3 = G.b_gen_sine3
+
+-- | Call @cheby@ 'b_gen' command.
+b_gen_cheby :: Int -> [B_Gen] -> [Double] -> Message
+b_gen_cheby = G.b_gen_cheby
+
+-- | Set sample values.
+b_set :: Int -> [(Int,Double)] -> Message
+b_set = G.b_set
+
+-- | Set ranges of sample values.
+b_setn :: Int -> [(Int,[Double])] -> Message
+b_setn = G.b_setn
+
+-- |  Fill ranges of bus values.
+c_fill :: [(Int,Int,Double)] -> Message
+c_fill = G.c_fill
+
+-- | Set bus values.
+c_set :: [(Int,Double)] -> Message
+c_set = G.c_set
+
+-- | Set ranges of bus values.
+c_setn :: [(Int,[Double])] -> Message
+c_setn = G.c_setn
+
+-- | Pre-allocate for b_setn1, values preceding offset are zeroed.
+b_alloc_setn1 :: Int -> Int -> [Double] -> Message
+b_alloc_setn1 = G.b_alloc_setn1
+
+-- | Set single sample value.
+b_set1 :: Int -> Int -> Double -> Message
+b_set1 = G.b_set1
+
+-- | Set a range of sample values.
+b_setn1 :: Int -> Int -> [Double] -> Message
+b_setn1 = G.b_setn1
+
+-- | Set single bus values.
+c_set1 :: Int -> Double -> Message
+c_set1 = G.c_set1
+
+-- | Set a single node control value.
+n_set1 :: Int -> String -> Double -> Message
+n_set1 = G.n_set1
+
diff --git a/Sound/SC3/Server/Command/Float.hs b/Sound/SC3/Server/Command/Float.hs
new file mode 100644
--- /dev/null
+++ b/Sound/SC3/Server/Command/Float.hs
@@ -0,0 +1,85 @@
+-- | Functions from "Sound.SC3.Server.Command.Generic" specialised to 'Int' and 'Float'.
+module Sound.SC3.Server.Command.Float where
+
+import Sound.OSC.Core {- hosc -}
+
+import qualified Sound.SC3.Server.Command.Generic as G
+import Sound.SC3.Server.Enum
+import Sound.SC3.UGen.Enum
+
+-- | Fill ranges of a node's control values.
+n_fill :: Int -> [(String,Int,Float)] -> Message
+n_fill = G.n_fill
+
+-- | Set a node's control values.
+n_set :: Int -> [(String,Float)] -> Message
+n_set = G.n_set
+
+-- | Set ranges of a node's control values.
+n_setn :: Int -> [(String,[Float])] -> Message
+n_setn = G.n_setn
+
+-- | Create a new synth.
+s_new :: String -> Int -> AddAction -> Int -> [(String,Float)] -> Message
+s_new = G.s_new
+
+-- | Fill ranges of sample values.
+b_fill :: Int -> [(Int,Int,Float)] -> Message
+b_fill = G.b_fill
+
+-- | Call @sine1@ 'b_gen' command.
+b_gen_sine1 :: Int -> [B_Gen] -> [Float] -> Message
+b_gen_sine1 = G.b_gen_sine1
+
+-- | Call @sine2@ 'b_gen' command.
+b_gen_sine2 :: Int -> [B_Gen] -> [(Float,Float)] -> Message
+b_gen_sine2 = G.b_gen_sine2
+
+-- | Call @sine3@ 'b_gen' command.
+b_gen_sine3 :: Int -> [B_Gen] -> [(Float,Float,Float)] -> Message
+b_gen_sine3 = G.b_gen_sine3
+
+-- | Call @cheby@ 'b_gen' command.
+b_gen_cheby :: Int -> [B_Gen] -> [Float] -> Message
+b_gen_cheby = G.b_gen_cheby
+
+-- | Set sample values.
+b_set :: Int -> [(Int,Float)] -> Message
+b_set = G.b_set
+
+-- | Set ranges of sample values.
+b_setn :: Int -> [(Int,[Float])] -> Message
+b_setn = G.b_setn
+
+-- |  Fill ranges of bus values.
+c_fill :: [(Int,Int,Float)] -> Message
+c_fill = G.c_fill
+
+-- | Set bus values.
+c_set :: [(Int,Float)] -> Message
+c_set = G.c_set
+
+-- | Set ranges of bus values.
+c_setn :: [(Int,[Float])] -> Message
+c_setn = G.c_setn
+
+-- | Pre-allocate for b_setn1, values preceding offset are zeroed.
+b_alloc_setn1 :: Int -> Int -> [Float] -> Message
+b_alloc_setn1 = G.b_alloc_setn1
+
+-- | Set single sample value.
+b_set1 :: Int -> Int -> Float -> Message
+b_set1 = G.b_set1
+
+-- | Set a range of sample values.
+b_setn1 :: Int -> Int -> [Float] -> Message
+b_setn1 = G.b_setn1
+
+-- | Set single bus values.
+c_set1 :: Int -> Float -> Message
+c_set1 = G.c_set1
+
+-- | Set a single node control value.
+n_set1 :: Int -> String -> Float -> Message
+n_set1 = G.n_set1
+
diff --git a/Sound/SC3/Server/Command/Generic.hs b/Sound/SC3/Server/Command/Generic.hs
new file mode 100644
--- /dev/null
+++ b/Sound/SC3/Server/Command/Generic.hs
@@ -0,0 +1,344 @@
+-- | Generic constructors for the command set implemented by the SuperCollider synthesis server.
+module Sound.SC3.Server.Command.Generic where
+
+import Data.List {- base -}
+import Data.Maybe {- base -}
+import Sound.OSC.Core {- hosc -}
+
+import Sound.SC3.Server.Command.Core
+import Sound.SC3.Server.Enum
+import Sound.SC3.Server.Utilities
+import Sound.SC3.UGen.Enum
+
+-- * Node commands
+
+-- | Place a node after another.
+n_after :: (Integral i) => [(i,i)] -> Message
+n_after = message "/n_after" . mk_duples int32 int32
+
+-- | Place a node before another.
+n_before :: (Integral i) => [(i,i)] -> Message
+n_before = message "/n_before" . mk_duples int32 int32
+
+-- | Fill ranges of a node's control values.
+n_fill :: (Integral i,Real n) => i -> [(String,i,n)] -> Message
+n_fill nid l = message "/n_fill" (int32 nid : mk_triples string int32 float l)
+
+-- | Delete a node.
+n_free :: (Integral i) => [i] -> Message
+n_free = message "/n_free" . map int32
+
+n_map :: (Integral i) => i -> [(String,i)] -> Message
+n_map nid l = message "/n_map" (int32 nid : mk_duples string int32 l)
+
+-- | Map a node's controls to read from buses.
+n_mapn :: (Integral i) => i -> [(String,i,i)] -> Message
+n_mapn nid l = message "/n_mapn" (int32 nid : mk_triples string 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 : 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 : mk_triples string int32 int32 l)
+
+-- | Get info about a node.
+n_query :: (Integral i) => [i] -> Message
+n_query = message "/n_query" . map int32
+
+-- | Turn node on or off.
+n_run :: (Integral i) => [(i,Bool)] -> Message
+n_run = message "/n_run" . mk_duples int32 (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 : mk_duples string float c)
+
+-- | Set ranges of a node's control values.
+n_setn :: (Integral i,Real n) => i -> [(String,[n])] -> Message
+n_setn nid l =
+    let f (s,d) = string s : int32 (length d) : map float d
+    in message "/n_setn" (int32 nid : concatMap f l)
+
+-- | Trace a node.
+n_trace :: (Integral i) => [i] -> Message
+n_trace = message "/n_trace" . map int32
+
+-- | Move an ordered sequence of nodes.
+n_order :: (Integral i) => AddAction -> i -> [i] -> Message
+n_order a n ns = message "/n_order" (int32 (fromEnum a) : int32 n : map int32 ns)
+
+-- * Synthesis node commands
+
+-- | Get control values.
+s_get :: (Integral i) => i -> [String] -> Message
+s_get nid i = message "/s_get" (int32 nid : 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 : mk_duples string int32 l)
+
+-- | Create a new synth.
+s_new :: (Integral i,Real n) => String -> i -> AddAction -> i -> [(String,n)] -> Message
+s_new n i a t c = message "/s_new" (string n : int32 i : int32 (fromEnum a) : int32 t : mk_duples string float c)
+
+-- | Auto-reassign synth's ID to a reserved value.
+s_noid :: (Integral i) => [i] -> Message
+s_noid = message "/s_noid" . map int32
+
+-- * Group node commands
+
+-- | Free all synths in this group and all its sub-groups.
+g_deepFree :: (Integral i) => [i] -> Message
+g_deepFree = message "/g_deepFree" . map int32
+
+-- | Delete all nodes in a group.
+g_freeAll :: (Integral i) => [i] -> Message
+g_freeAll = message "/g_freeAll" . map int32
+
+-- | Add node to head of group.
+g_head :: (Integral i) => [(i,i)] -> Message
+g_head = message "/g_head" . mk_duples int32 int32
+
+-- | Create a new group.
+g_new :: (Integral i) => [(i,AddAction,i)] -> Message
+g_new = message "/g_new" . mk_triples int32 (int32 . fromEnum) int32
+
+-- | Add node to tail of group.
+g_tail :: (Integral i) => [(i,i)] -> Message
+g_tail = message "/g_tail" . mk_duples int32 int32
+
+-- | Post a representation of a group's node subtree, optionally including the current control values for synths.
+g_dumpTree :: (Integral i) => [(i,Bool)] -> Message
+g_dumpTree = message "/g_dumpTree" . mk_duples int32 (int32 . fromEnum)
+
+-- | Request a representation of a group's node subtree, optionally including the current control values for synths.
+--
+-- Replies to the sender with a @/g_queryTree.reply@ message listing all of the nodes contained within the group in the following format:
+--
+-- > int32 - if synth control values are included 1, else 0
+-- > int32 - node ID of the requested group
+-- > int32 - number of child nodes contained within the requested group
+-- >
+-- > For each node in the subtree:
+-- > [
+-- >   int32 - node ID
+-- >   int32 - number of child nodes contained within this node. If -1 this is a synth, if >= 0 it's a group.
+-- >
+-- >   If this node is a synth:
+-- >     symbol - the SynthDef name for this node.
+-- >
+-- >   If flag (see above) is true:
+-- >     int32 - numControls for this synth (M)
+-- >     [
+-- >       symbol or int: control name or index
+-- >       float or symbol: value or control bus mapping symbol (e.g. 'c1')
+-- >     ] * M
+-- > ] * the number of nodes in the subtree
+--
+-- N.B. The order of nodes corresponds to their execution order on the server. Thus child nodes (those contained within a group) are listed immediately following their parent.
+g_queryTree :: (Integral i) => [(i,Bool)] -> Message
+g_queryTree = message "/g_queryTree" . mk_duples int32 (int32 . fromEnum)
+
+-- | Create a new parallel group (supernova specific).
+p_new :: (Integral i) => [(i,AddAction,i)] -> Message
+p_new = message "/p_new" . mk_triples int32 (int32 . fromEnum) int32
+
+-- * Unit Generator commands
+
+-- | 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)
+
+-- * Buffer commands
+
+-- | 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]
+
+-- | 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]
+
+-- | 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)
+
+-- | Close attached soundfile and write header information. (Asynchronous)
+b_close :: (Integral i) => i -> Message
+b_close nid = message "/b_close" [int32 nid]
+
+-- | 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 : mk_triples int32 int32 float l)
+
+-- | Free buffer data. (Asynchronous)
+b_free :: (Integral i) => i -> Message
+b_free nid = message "/b_free" [int32 nid]
+
+-- | 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)
+
+-- | Call @sine1@ 'b_gen' command.
+b_gen_sine1 :: (Integral i,Real n) => i -> [B_Gen] -> [n] -> Message
+b_gen_sine1 z f n = b_gen z "sine1" (int32 (b_gen_flag f) : map float n)
+
+-- | Call @sine2@ 'b_gen' command.
+b_gen_sine2 :: (Integral i,Real n) => i -> [B_Gen] -> [(n,n)] -> Message
+b_gen_sine2 z f n = b_gen z "sine2" (int32 (b_gen_flag f) : mk_duples float float n)
+
+-- | Call @sine3@ 'b_gen' command.
+b_gen_sine3 :: (Integral i,Real n) => i -> [B_Gen] -> [(n,n,n)] -> Message
+b_gen_sine3 z f n = b_gen z "sine3" (int32 (b_gen_flag f) : mk_triples float float float n)
+
+-- | Call @cheby@ 'b_gen' command.
+b_gen_cheby :: (Integral i,Real n) => i -> [B_Gen] -> [n] -> Message
+b_gen_cheby z f n = b_gen z "cheby" (int32 (b_gen_flag f) : map float n)
+
+-- | Call @copy@ 'b_gen' command.
+b_gen_copy :: (Integral i) => i -> i -> i -> i -> Maybe i -> Message
+b_gen_copy z dst_ix src_b src_ix nf =
+    let nf' = fromMaybe (-1) nf
+    in b_gen z "copy" (map int32 [dst_ix,src_b,src_ix,nf'])
+
+-- | Get sample values.
+b_get :: (Integral i) => i -> [i] -> Message
+b_get nid i = message "/b_get" (int32 nid : 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 : mk_duples int32 int32 l)
+
+-- | Request \/b_info messages.
+b_query :: (Integral i) => [i] -> Message
+b_query = message "/b_query" . map int32
+
+-- | 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)]
+
+-- | 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)
+
+-- | Set sample values.
+b_set :: (Integral i,Real n) => i -> [(i,n)] -> Message
+b_set nid l = message "/b_set" (int32 nid : mk_duples int32 float l)
+
+-- | Set ranges of sample values.
+b_setn :: (Integral i,Real n) => i -> [(i,[n])] -> Message
+b_setn nid l =
+    let f (i,d) = int32 i : int32 (length d) : map float d
+    in message "/b_setn" (int32 nid : concatMap f l)
+
+-- | Write sound file data. (Asynchronous)
+b_write :: (Integral i) => i -> String -> SoundFileFormat -> SampleFormat -> i -> i -> Bool -> Message
+b_write nid p h t f s z = message "/b_write" [int32 nid,string p,string (soundFileFormatString h),string (sampleFormatString 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]
+
+-- * Control bus commands
+
+-- |  Fill ranges of bus values.
+c_fill :: (Integral i,Real n) => [(i,i,n)] -> Message
+c_fill = message "/c_fill" . mk_triples int32 int32 float
+
+-- | Get bus values.
+c_get :: (Integral i) => [i] -> Message
+c_get = message "/c_get" . map int32
+
+-- | Get ranges of bus values.
+c_getn :: (Integral i) => [(i,i)] -> Message
+c_getn = message "/c_getn" . mk_duples int32 int32
+
+-- | Set bus values.
+c_set :: (Integral i,Real n) => [(i,n)] -> Message
+c_set = message "/c_set" . mk_duples int32 float
+
+-- | Set ranges of bus values.
+c_setn :: (Integral i,Real n) => [(i,[n])] -> Message
+c_setn l =
+    let f (i,d) = int32 i : int32 (length d) : map float d
+    in message "/c_setn" (concatMap f l)
+
+-- * Server operation commands
+
+-- | Request \/synced message when all current asynchronous commands complete.
+sync :: (Integral i) => i -> Message
+sync sid = message "/sync" [int32 sid]
+
+-- * Variants to simplify common cases
+
+-- | 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 =
+    let k = i + genericLength xs
+        xs' = genericReplicate i 0 ++ xs
+    in withCM (b_alloc nid k 1) (b_setn1 nid 0 xs')
+
+-- | Get ranges of sample values.
+b_getn1 :: (Integral i) => i -> (i,i) -> Message
+b_getn1 nid = b_getn nid . return
+
+-- | Set single sample value.
+b_set1 :: (Integral i,Real n) => i -> i -> n -> Message
+b_set1 nid i x = b_set nid [(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)]
+
+-- | Variant on 'b_query'.
+b_query1 :: (Integral i) => i -> Message
+b_query1 = b_query . return
+
+-- | Set single bus values.
+c_set1 :: (Integral i,Real n) => i -> n -> Message
+c_set1 i x = c_set [(i,x)]
+
+-- | 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)]
+
+-- | @s_new@ with no parameters.
+s_new0 :: (Integral i) => String -> i -> AddAction -> i -> Message
+s_new0 n i a t = s_new n i a t ([]::[(String,Double)])
+
+-- * Buffer segmentation and indices
+
+-- | Segment a request for /m/ places into sets of at most /n/.
+--
+-- > b_segment 1024 2056 == [8,1024,1024]
+-- > b_segment 1 5 == replicate 5 1
+b_segment :: (Integral i) => i -> i -> [i]
+b_segment n m =
+    let (q,r) = m `quotRem` n
+        s = genericReplicate q n
+    in if r == 0 then s else r : s
+
+-- | Variant of 'b_segment' that takes a starting index and returns
+-- /(index,size)/ duples.
+--
+-- > b_indices 1 5 0 == zip [0..4] (replicate 5 1)
+-- > b_indices 1024 2056 16 == [(16,8),(24,1024),(1048,1024)]
+b_indices :: (Integral i) => i -> i -> i -> [(i,i)]
+b_indices n m k =
+    let dx_d = scanl1 (+)
+        s = b_segment n m
+        i = 0 : dx_d s
+    in zip (map (+ k) i) s
+
+-- * UGen commands.
+
+-- | Generate accumulation buffer given time-domain IR buffer and FFT size.
+pc_preparePartConv :: (Integral i) => i -> i -> i -> Message
+pc_preparePartConv b irb fft_size =
+    b_gen b "PreparePartConv" (map int32 [irb, fft_size])
+
+-- Local Variables:
+-- truncate-lines:t
+-- End:
diff --git a/Sound/SC3/Server/Command/Int.hs b/Sound/SC3/Server/Command/Int.hs
new file mode 100644
--- /dev/null
+++ b/Sound/SC3/Server/Command/Int.hs
@@ -0,0 +1,245 @@
+-- | Functions from "Sound.SC3.Server.Command.Generic" specialised to 'Int'.
+module Sound.SC3.Server.Command.Int where
+
+import Sound.OSC.Core {- hosc -}
+
+import qualified Sound.SC3.Server.Command.Generic as G
+import Sound.SC3.Server.Enum
+
+-- * Node commands
+
+-- | Place a node after another.
+n_after :: [(Int,Int)] -> Message
+n_after = G.n_after
+
+-- | Place a node before another.
+n_before :: [(Int,Int)] -> Message
+n_before = G.n_before
+
+-- | Delete a node.
+n_free :: [Int] -> Message
+n_free = G.n_free
+
+n_map :: Int -> [(String,Int)] -> Message
+n_map = G.n_map
+
+-- | Map a node's controls to read from buses.
+n_mapn :: Int -> [(String,Int,Int)] -> Message
+n_mapn = G.n_mapn
+
+-- | Map a node's controls to read from an audio bus.
+n_mapa :: Int -> [(String,Int)] -> Message
+n_mapa = G.n_mapa
+
+-- | Map a node's controls to read from audio buses.
+n_mapan :: Int -> [(String,Int,Int)] -> Message
+n_mapan = G.n_mapan
+
+-- | Get info about a node.
+n_query :: [Int] -> Message
+n_query = G.n_query
+
+-- | Turn node on or off.
+n_run :: [(Int,Bool)] -> Message
+n_run = G.n_run
+
+-- | Trace a node.
+n_trace :: [Int] -> Message
+n_trace = G.n_trace
+
+-- | Move an ordered sequence of nodes.
+n_order :: AddAction -> Int -> [Int] -> Message
+n_order = G.n_order
+
+-- * Synthesis node commands
+
+-- | Get control values.
+s_get :: Int -> [String] -> Message
+s_get = G.s_get
+
+-- | Get ranges of control values.
+s_getn :: Int -> [(String,Int)] -> Message
+s_getn = G.s_getn
+
+-- | Auto-reassign synth's ID to a reserved value.
+s_noid :: [Int] -> Message
+s_noid = G.s_noid
+
+-- * Group node commands
+
+-- | Free all synths in this group and all its sub-groups.
+g_deepFree :: [Int] -> Message
+g_deepFree = G.g_deepFree
+
+-- | Delete all nodes in a group.
+g_freeAll :: [Int] -> Message
+g_freeAll = G.g_freeAll
+
+-- | Add node to head of group.
+g_head :: [(Int,Int)] -> Message
+g_head = G.g_head
+
+-- | Create a new group.
+g_new :: [(Int,AddAction,Int)] -> Message
+g_new = G.g_new
+
+-- | Add node to tail of group.
+g_tail :: [(Int,Int)] -> Message
+g_tail = G.g_tail
+
+-- | Post a representation of a group's node subtree, optionally including the current control values for synths.
+g_dumpTree :: [(Int,Bool)] -> Message
+g_dumpTree = G.g_dumpTree
+
+-- | Request a representation of a group's node subtree, optionally including the current control values for synths.
+--
+-- Replies to the sender with a @/g_queryTree.reply@ message listing all of the nodes contained within the group in the following format:
+--
+-- > int32 - if synth control values are included 1, else 0
+-- > int32 - node ID of the requested group
+-- > int32 - number of child nodes contained within the requested group
+-- >
+-- > For each node in the subtree:
+-- > [
+-- >   int32 - node ID
+-- >   int32 - number of child nodes contained within this node. If -1 this is a synth, if >= 0 it's a group.
+-- >
+-- >   If this node is a synth:
+-- >     symbol - the SynthDef name for this node.
+-- >
+-- >   If flag (see above) is true:
+-- >     int32 - numControls for this synth (M)
+-- >     [
+-- >       symbol or int: control name or index
+-- >       float or symbol: value or control bus mapping symbol (e.g. 'c1')
+-- >     ] * M
+-- > ] * the number of nodes in the subtree
+--
+-- N.B. The order of nodes corresponds to their execution order on the server. Thus child nodes (those contained within a group) are listed immediately following their parent.
+g_queryTree :: [(Int,Bool)] -> Message
+g_queryTree = G.g_queryTree
+
+-- | Create a new parallel group (supernova specific).
+p_new :: [(Int,AddAction,Int)] -> Message
+p_new = G.p_new
+
+-- * Unit Generator commands
+
+-- | Send a command to a unit generator.
+u_cmd :: Int -> Int -> String -> [Datum] -> Message
+u_cmd = G.u_cmd
+
+-- * Buffer commands
+
+-- | Allocates zero filled buffer to number of channels and samples. (Asynchronous)
+b_alloc :: Int -> Int -> Int -> Message
+b_alloc = G.b_alloc
+
+-- | Allocate buffer space and read a sound file. (Asynchronous)
+b_allocRead :: Int -> String -> Int -> Int -> Message
+b_allocRead = G.b_allocRead
+
+-- | Allocate buffer space and read a sound file, picking specific channels. (Asynchronous)
+b_allocReadChannel :: Int -> String -> Int -> Int -> [Int] -> Message
+b_allocReadChannel = G.b_allocReadChannel
+
+-- | Close attached soundfile and write header information. (Asynchronous)
+b_close :: Int -> Message
+b_close = G.b_close
+
+-- | Free buffer data. (Asynchronous)
+b_free :: Int -> Message
+b_free = G.b_free
+
+-- | Call a command to fill a buffer.  (Asynchronous)
+b_gen :: Int -> String -> [Datum] -> Message
+b_gen = G.b_gen
+
+-- | Call @copy@ 'b_gen' command.
+b_gen_copy :: Int -> Int -> Int -> Int -> Maybe Int -> Message
+b_gen_copy = G.b_gen_copy
+
+-- | Get sample values.
+b_get :: Int -> [Int] -> Message
+b_get = G.b_get
+
+-- | Get ranges of sample values.
+b_getn :: Int -> [(Int,Int)] -> Message
+b_getn = G.b_getn
+
+-- | Request \/b_info messages.
+b_query :: [Int] -> Message
+b_query = G.b_query
+
+-- | Read sound file data into an existing buffer. (Asynchronous)
+b_read :: Int -> String -> Int -> Int -> Int -> Bool -> Message
+b_read = G.b_read
+
+-- | Read sound file data into an existing buffer, picking specific channels. (Asynchronous)
+b_readChannel :: Int -> String -> Int -> Int -> Int -> Bool -> [Int] -> Message
+b_readChannel = G.b_readChannel
+
+-- | Write sound file data. (Asynchronous)
+b_write :: Int -> String -> SoundFileFormat -> SampleFormat -> Int -> Int -> Bool -> Message
+b_write = G.b_write
+
+-- | Zero sample data. (Asynchronous)
+b_zero :: Int -> Message
+b_zero = G.b_zero
+
+-- * Control bus commands
+
+-- | Get bus values.
+c_get :: [Int] -> Message
+c_get = G.c_get
+
+-- | Get ranges of bus values.
+c_getn :: [(Int,Int)] -> Message
+c_getn = G.c_getn
+
+-- * Server operation commands
+
+-- | Request \/synced message when all current asynchronous commands
+-- complete.
+sync :: Int -> Message
+sync = G.sync
+
+-- * Variants to simplify common cases
+
+-- | Get ranges of sample values.
+b_getn1 :: Int -> (Int,Int) -> Message
+b_getn1 = G.b_getn1
+
+-- | Variant on 'b_query'.
+b_query1 :: Int -> Message
+b_query1 = b_query . return
+
+-- | @s_new@ with no parameters.
+s_new0 :: String -> Int -> AddAction -> Int -> Message
+s_new0 = G.s_new0
+
+-- * Buffer segmentation and indices
+
+-- | Segment a request for /m/ places into sets of at most /n/.
+--
+-- > b_segment 1024 2056 == [8,1024,1024]
+-- > b_segment 1 5 == replicate 5 1
+b_segment :: Int -> Int -> [Int]
+b_segment = G.b_segment
+
+-- | Variant of 'b_segment' that takes a starting index and returns /(index,size)/ duples.
+--
+-- > b_indices 1 5 0 == zip [0..4] (replicate 5 1)
+-- > b_indices 1024 2056 16 == [(16,8),(24,1024),(1048,1024)]
+b_indices :: Int -> Int -> Int -> [(Int,Int)]
+b_indices = G.b_indices
+
+-- * UGen commands.
+
+-- | Generate accumulation buffer given time-domain IR buffer and FFT size.
+pc_preparePartConv :: Int -> Int -> Int -> Message
+pc_preparePartConv = G.pc_preparePartConv
+
+-- Local Variables:
+-- truncate-lines:t
+-- End:
diff --git a/Sound/SC3/Server/Enum.hs b/Sound/SC3/Server/Enum.hs
--- a/Sound/SC3/Server/Enum.hs
+++ b/Sound/SC3/Server/Enum.hs
@@ -1,6 +1,31 @@
 -- | Server input enumerations.
 module Sound.SC3.Server.Enum where
 
+-- | Enumeration of possible locations to add new nodes (s_new and g_new).
+data AddAction = AddToHead
+               | AddToTail
+               | AddBefore
+               | AddAfter
+               | AddReplace
+                 deriving (Eq,Show,Enum)
+
+-- | Error posting scope.
+data ErrorScope = Globally  -- ^ Global scope
+                | Locally   -- ^ Bundle scope
+                  deriving (Eq,Show,Enum)
+
+-- | Error posting mode.
+data ErrorMode = ErrorsOff  -- ^ Turn error posting off
+               | ErrorsOn   -- ^ Turn error posting on
+                 deriving (Eq,Show,Enum)
+
+-- | Enumeration of Message printer types.
+data PrintLevel = NoPrinter
+                | TextPrinter
+                | HexPrinter
+                | AllPrinter
+                  deriving (Eq,Show,Enum)
+
 -- | Sound file format.
 data SoundFileFormat = Aiff | Flac | Ircam | Next | Raw | Wave
   deriving (Enum, Eq, Read, Show)
diff --git a/Sound/SC3/Server/FD.hs b/Sound/SC3/Server/FD.hs
--- a/Sound/SC3/Server/FD.hs
+++ b/Sound/SC3/Server/FD.hs
@@ -1,4 +1,4 @@
--- | Composite of "Sound.SC3.Server" and "Sound.SC3.Server.Transport.FD".
+-- | Composite of "Sound.SC3.Server" and /FD/ transport.
 module Sound.SC3.Server.FD (module M) where
 
 import Sound.SC3.Server as M
diff --git a/Sound/SC3/Server/Help.hs b/Sound/SC3/Server/Help.hs
--- a/Sound/SC3/Server/Help.hs
+++ b/Sound/SC3/Server/Help.hs
@@ -1,10 +1,11 @@
 -- | Functions to provide mediated access to the SC3 help system.
 module Sound.SC3.Server.Help where
 
-import Control.Monad
-import Sound.SC3.UGen.Help
+import Control.Monad {- base -}
 import System.Cmd {- process -}
 import System.FilePath {- filepath -}
+
+import Sound.SC3.UGen.Help
 
 -- | Generate path to indicated SC3 instance method help.
 --
diff --git a/Sound/SC3/Server/Monad.hs b/Sound/SC3/Server/Monad.hs
--- a/Sound/SC3/Server/Monad.hs
+++ b/Sound/SC3/Server/Monad.hs
@@ -1,4 +1,4 @@
--- | Composite of "Sound.SC3.Server" and "Sound.SC3.Server.Transport.Monad".
+-- | Composite of "Sound.SC3.Server" and 'Monad' transport.
 module Sound.SC3.Server.Monad (module S) where
 
 import Sound.SC3.Server as S
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
@@ -2,9 +2,9 @@
 module Sound.SC3.Server.NRT where
 
 import qualified Data.ByteString.Lazy as B {- bytestring -}
-import Sound.OpenSoundControl {- hosc -}
-import Sound.OpenSoundControl.Coding.Byte
-import System.IO
+import Sound.OSC.Core {- hosc -}
+import Sound.OSC.Coding.Byte {- hosc -}
+import System.IO {- base -}
 
 -- | Encode and prefix with encoded length.
 oscWithSize :: Bundle -> B.ByteString
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
@@ -1,23 +1,28 @@
 -- | Request and display status information from the synthesis server.
 module Sound.SC3.Server.Status where
 
-import Sound.OpenSoundControl.Type
+import Data.Maybe {- base -}
+import Sound.OSC.Type {- hosc -}
 
--- | Get /n/th field of status as 'Double'.
-extractStatusField :: Int -> [Datum] -> Double
-extractStatusField n = datum_real_err . (!! n)
+-- | Get /n/th field of status as 'Floating'.
+extractStatusField :: Floating n => Int -> [Datum] -> n
+extractStatusField n =
+    fromMaybe (error "extractStatusField")
+    . datum_floating
+    . (!! n)
 
 -- | Names of status fields.
 statusFields :: [String]
-statusFields = ["Unused                      ",
-                "# UGens                     ",
-                "# Synths                    ",
-                "# Groups                    ",
-                "# Instruments               ",
-                "% CPU (Average)             ",
-                "% CPU (Peak)                ",
-                "Sample Rate (Nominal)       ",
-                "Sample Rate (Actual)        "]
+statusFields =
+    ["Unused                      "
+    ,"# UGens                     "
+    ,"# Synths                    "
+    ,"# Groups                    "
+    ,"# Instruments               "
+    ,"% CPU (Average)             "
+    ,"% CPU (Peak)                "
+    ,"Sample Rate (Nominal)       "
+    ,"Sample Rate (Actual)        "]
 
 -- | Status pretty printer.
 statusFormat :: [Datum] -> [String]
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,14 +2,19 @@
 --   SuperCollider synthesis server.
 module Sound.SC3.Server.Synthdef where
 
+import qualified Data.ByteString.Char8 as C {- bytestring -}
 import qualified Data.ByteString.Lazy as B {- bytestring -}
-import Data.List
-import Sound.OpenSoundControl.Coding.Byte {- hosc -}
-import Sound.OpenSoundControl.Coding.Cast
+import Data.Default {- data-default -}
+import Data.List {- base -}
+import Data.Maybe {- base -}
+import Sound.OSC.Coding.Byte {- hosc -}
+import Sound.OSC.Coding.Cast {- hosc -}
+import System.FilePath {- filepath -}
+
 import Sound.SC3.Server.Synthdef.Internal
 import Sound.SC3.Server.Synthdef.Type
+import Sound.SC3.UGen.Graph
 import Sound.SC3.UGen.Type
-import System.FilePath {- filepath -}
 
 -- | Transform a unit generator into a graph.
 --
@@ -21,23 +26,50 @@
         g' = g {ugens = reverse (ugens g)}
     in add_implicit g'
 
+-- | Binary representation of a unit generator synth definition.
+data Synthdef = Synthdef {synthdefName :: String
+                         ,synthdefGraph :: Graph}
+                deriving (Eq,Show)
+
+instance Default Synthdef where def = defaultSynthdef
+
+-- | Lift a 'UGen' graph into a 'Synthdef'.
+synthdef :: String -> UGen -> Synthdef
+synthdef s u = Synthdef s (synth u)
+
+-- | The SC3 /default/ instrument 'Synthdef'.
+defaultSynthdef :: Synthdef
+defaultSynthdef = synthdef "default" default_ugen_graph
+
+-- | Parameter names at 'Synthdef'.
+--
+-- > synthdefParam def == ["amp","pan","gate","freq"]
+synthdefParam :: Synthdef -> [String]
+synthdefParam = map node_k_name . controls . synthdefGraph
+
 -- | Transform a unit generator graph into bytecode.
 graphdef :: Graph -> Graphdef
 graphdef = encode_graphdef
 
+-- | Find the indices of the named UGen at 'Graph'.  The index is
+-- required when using 'Sound.SC3.Server.Command.u_cmd'.
+ugenIndices :: String -> Graph -> [Integer]
+ugenIndices nm =
+    let f (k,nd) =
+            case nd of
+              NodeU _ _ nm' _ _ _ _ -> if nm == nm' then Just k else Nothing
+              _ -> Nothing
+    in mapMaybe f . zip [0..] . ugens
+
 -- | Encode 'Synthdef' as a binary data stream.
 synthdefData :: Synthdef -> Graphdef
 synthdefData (Synthdef s g) =
-    B.concat [encode_str "SCgf"
+    B.concat [encode_str (C.pack "SCgf")
              ,encode_i32 0
              ,encode_i16 1
              ,B.pack (str_pstr s)
              ,encode_graphdef g]
 
--- | Transform a unit generator synth definition into bytecode.
-synthdef :: String -> UGen -> Synthdef
-synthdef s u = Synthdef s (synth u)
-
 -- | Write 'Synthdef' to indicated directory.  The filename is the
 -- 'synthdefName' with the appropriate extension (@scsyndef@).
 synthdefWrite :: Synthdef -> FilePath -> IO ()
@@ -60,5 +92,3 @@
                ,"control rates             : " ++ f node_k_rate ks
                ,"number of unit generators : " ++ show (length us)
                ,"unit generator rates      : " ++ f node_u_rate us]
-
-
diff --git a/Sound/SC3/Server/Synthdef/Internal.hs b/Sound/SC3/Server/Synthdef/Internal.hs
--- a/Sound/SC3/Server/Synthdef/Internal.hs
+++ b/Sound/SC3/Server/Synthdef/Internal.hs
@@ -2,11 +2,12 @@
 
 import qualified Data.ByteString.Lazy as B {- bytestring -}
 import qualified Data.IntMap as M {- containers -}
-import Data.Function
-import Data.List
-import Data.Maybe
-import Sound.OpenSoundControl.Coding.Byte {- hosc -}
-import Sound.OpenSoundControl.Coding.Cast
+import Data.Function {- base -}
+import Data.List{- base -}
+import Data.Maybe{- base -}
+import Sound.OSC.Coding.Byte {- hosc -}
+import Sound.OSC.Coding.Cast {- hosc -}
+
 import Sound.SC3.Server.Synthdef.Type
 import Sound.SC3.UGen.Rate
 import Sound.SC3.UGen.Type
@@ -129,14 +130,14 @@
     in Graph z cs ks' us'
 
 -- | Predicate to determine if 'Node' is a constant with indicated /value/.
-find_c_p :: Double -> Node -> Bool
+find_c_p :: Float -> Node -> Bool
 find_c_p x n =
     case n of
       NodeC _ y -> x == y
       _ -> error "find_c_p: non NodeC"
 
 -- | Insert a constant 'Node' into the 'Graph'.
-push_c :: Double -> Graph -> (Node,Graph)
+push_c :: Float -> Graph -> (Node,Graph)
 push_c x g =
     let n = NodeC (nextId g) x
     in (n,g {constants = n : constants g
@@ -157,7 +158,7 @@
       _ -> error "find_k_p"
 
 -- | Insert a control node into the 'Graph'.
-push_k :: (Rate,String,Double,Bool) -> Graph -> (Node,Graph)
+push_k :: (Rate,String,Float,Bool) -> Graph -> (Node,Graph)
 push_k (r,nm,d,tr) g =
     let n = NodeK (nextId g) r nm d (ktype r tr)
     in (n,g {controls = n : controls g
@@ -322,14 +323,15 @@
 encode_graphdef g =
     let (Graph _ cs ks us) = g
         mm = mk_maps g
-    in B.concat [encode_i16 (length cs)
-                ,B.concat (map (encode_f32 . node_c_value) cs)
-                ,encode_i16 (length ks)
-                ,B.concat (map (encode_f32 . node_k_default) ks)
-                ,encode_i16 (length ks)
-                ,B.concat (map (encode_node_k mm) ks)
-                ,encode_i16 (length us)
-                ,B.concat (map (encode_node_u mm) us)]
+    in B.concat
+           [encode_i16 (length cs)
+           ,B.concat (map (encode_f32 . node_c_value) cs)
+           ,encode_i16 (length ks)
+           ,B.concat (map (encode_f32 . node_k_default) ks)
+           ,encode_i16 (length ks)
+           ,B.concat (map (encode_node_k mm) ks)
+           ,encode_i16 (length us)
+           ,B.concat (map (encode_node_u mm) us)]
 
 -- | 4-tuple to count 'KType's.
 type KS_COUNT = (Int,Int,Int,Int)
diff --git a/Sound/SC3/Server/Synthdef/Reconstruct.hs b/Sound/SC3/Server/Synthdef/Reconstruct.hs
--- a/Sound/SC3/Server/Synthdef/Reconstruct.hs
+++ b/Sound/SC3/Server/Synthdef/Reconstruct.hs
@@ -1,15 +1,17 @@
+-- | A /disasembler/ for UGen graphs.
 module Sound.SC3.Server.Synthdef.Reconstruct where
 
-import Data.Char
-import Data.Function
-import Data.List
+import Data.Char {- base -}
+import Data.Function {- base -}
+import Data.List {- base -}
+import Text.Printf {- base -}
+
 import Sound.SC3.Server.Synthdef.Internal
 import Sound.SC3.Server.Synthdef.Type
 import Sound.SC3.UGen.Operator
 import Sound.SC3.UGen.Rate
 import Sound.SC3.UGen.Type
 import Sound.SC3.UGen.UGen
-import Text.Printf
 
 node_sort :: [Node] -> [Node]
 node_sort = sortBy (compare `on` node_id)
@@ -34,6 +36,8 @@
     then printf "(%s)" nm
     else nm
 
+-- | Generate a reconstruction of a 'Graph'.
+--
 -- > import Sound.SC3.ID
 --
 -- > let {k = control KR "bus" 0
@@ -54,12 +58,12 @@
 reconstruct_c_str u =
     let l = node_label u
         c = node_c_value u
-    in printf "%s = constant (%f::Double)" l c
+    in printf "%s = constant (%f::Float)" l c
 
 reconstruct_c_ugen :: Node -> UGen
 reconstruct_c_ugen u = constant (node_c_value u)
 
-reconstruct_k_rnd :: Node -> (Rate,String,Double)
+reconstruct_k_rnd :: Node -> (Rate,String,Float)
 reconstruct_k_rnd u =
     let r = node_k_rate u
         n = node_k_name u
@@ -75,7 +79,7 @@
 reconstruct_k_ugen :: Node -> UGen
 reconstruct_k_ugen u =
     let (r,n,d) = reconstruct_k_rnd u
-    in control r n d
+    in control_f32 r n d
 
 ugen_qname :: String -> Special -> (String,String)
 ugen_qname nm (Special n) =
diff --git a/Sound/SC3/Server/Synthdef/Transform.hs b/Sound/SC3/Server/Synthdef/Transform.hs
--- a/Sound/SC3/Server/Synthdef/Transform.hs
+++ b/Sound/SC3/Server/Synthdef/Transform.hs
@@ -1,9 +1,10 @@
 -- | Transformations over 'Graph' structure.
 module Sound.SC3.Server.Synthdef.Transform where
 
-import Data.Either
-import Data.List
-import Data.Maybe
+import Data.Either {- base -}
+import Data.List {- base -}
+import Data.Maybe {- base -}
+
 import Sound.SC3.Server.Synthdef.Internal
 import Sound.SC3.Server.Synthdef.Type
 import Sound.SC3.UGen.Rate
diff --git a/Sound/SC3/Server/Synthdef/Type.hs b/Sound/SC3/Server/Synthdef/Type.hs
--- a/Sound/SC3/Server/Synthdef/Type.hs
+++ b/Sound/SC3/Server/Synthdef/Type.hs
@@ -1,7 +1,8 @@
--- | The 'Graph' and 'Synthdef' types.
+-- | 'Node', 'Graph' and related types.
 module Sound.SC3.Server.Synthdef.Type where
 
 import qualified Data.ByteString.Lazy as B {- bytestring -}
+
 import Sound.SC3.UGen.Rate
 import Sound.SC3.UGen.Type
 
@@ -40,11 +41,11 @@
 
 -- | Type to represent nodes in unit generator graph.
 data Node = NodeC {node_id :: NodeId
-                  ,node_c_value :: Double}
+                  ,node_c_value :: Float}
           | NodeK {node_id :: NodeId
                   ,node_k_rate :: Rate
                   ,node_k_name :: String
-                  ,node_k_default :: Double
+                  ,node_k_default :: Float
                   ,node_k_type :: KType}
           | NodeU {node_id :: NodeId
                   ,node_u_rate :: Rate
@@ -57,9 +58,4 @@
                   ,node_p_node :: Node
                   ,node_p_index :: PortIndex}
             deriving (Eq,Show)
-
--- | Binary representation of a unit generator synth definition.
-data Synthdef = Synthdef {synthdefName :: String
-                         ,synthdefGraph :: Graph}
-                deriving (Eq,Show)
 
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
@@ -1,12 +1,13 @@
 -- | /FD/ variant of interaction with the scsynth server.
 module Sound.SC3.Server.Transport.FD where
 
-import Control.Monad
-import Sound.OpenSoundControl.Time
-import Sound.OpenSoundControl.Type
-import Sound.OSC.Transport.FD
-import Sound.OSC.Transport.FD.UDP
-import Sound.SC3.Server.Command
+import Data.Maybe {- base -}
+import Control.Monad {- base -}
+import Sound.OSC.FD {- hosc -}
+
+import Sound.SC3.Server.Command.Core
+import Sound.SC3.Server.Command.Int
+import Sound.SC3.Server.Enum
 import Sound.SC3.Server.NRT
 import Sound.SC3.Server.Status
 import Sound.SC3.Server.Synthdef
@@ -43,7 +44,7 @@
 playSynthdef :: Transport t => t -> Synthdef -> IO ()
 playSynthdef fd s = do
   _ <- async fd (d_recv s)
-  sendMessage fd (s_new (synthdefName s) (-1) AddToTail 1 [])
+  sendMessage fd (s_new0 (synthdefName s) (-1) AddToTail 1)
 
 -- | Send an /anonymous/ instrument definition using 'playSynthdef'.
 playUGen :: Transport t => t -> UGen -> IO ()
@@ -107,7 +108,7 @@
 b_getn1_data :: Transport t => t -> Int -> (Int,Int) -> IO [Double]
 b_getn1_data fd b s = do
   let f d = case d of
-              Int _:Int _:Int _:x -> map datum_real_err x
+              Int32 _:Int32 _:Int32 _:x -> mapMaybe datum_floating x
               _ -> error "b_getn1_data"
   sendMessage fd (b_getn1 b s)
   fmap f (waitDatum fd "/b_setn")
@@ -126,14 +127,13 @@
 b_fetch :: Transport t => t -> Int -> Int -> IO [Double]
 b_fetch fd n b = do
   let f d = case d of
-              [Int _,Int nf,Int nc,Float _] ->
-                  let ix = (0,nf * nc)
+              [Int32 _,Int32 nf,Int32 nc,Float _] ->
+                  let ix = (0,fromIntegral (nf * nc))
                   in b_getn1_data_segment fd n b ix
               _ -> error "b_fetch"
   sendMessage fd (b_query1 b)
   waitDatum fd "/b_info" >>= f
 
-
 -- * Status
 
 -- | Collect server status information.
@@ -141,11 +141,11 @@
 serverStatus = liftM statusFormat . serverStatusData
 
 -- | Read nominal sample rate of server.
-serverSampleRateNominal :: (Transport t) => t -> IO Double
+serverSampleRateNominal :: Transport t => t -> IO Double
 serverSampleRateNominal = liftM (extractStatusField 7) . serverStatusData
 
 -- | Read actual sample rate of server.
-serverSampleRateActual :: (Transport t) => t -> IO Double
+serverSampleRateActual :: Transport t => t -> IO Double
 serverSampleRateActual = liftM (extractStatusField 8) . serverStatusData
 
 -- | Retrieve status data from server.
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
@@ -1,9 +1,13 @@
 -- | /Monad/ variant of interaction with the scsynth server.
 module Sound.SC3.Server.Transport.Monad where
 
-import Control.Monad
-import Sound.OSC
-import Sound.SC3.Server.Command
+import Control.Monad {- base -}
+import Data.Maybe {- base -}
+import Sound.OSC {- hosc -}
+
+import Sound.SC3.Server.Command.Core
+import Sound.SC3.Server.Command.Int
+import Sound.SC3.Server.Enum
 import Sound.SC3.Server.NRT
 import Sound.SC3.Server.Status
 import Sound.SC3.Server.Synthdef
@@ -46,7 +50,7 @@
 playSynthdef :: DuplexOSC m => Synthdef -> m ()
 playSynthdef s = do
   _ <- async (d_recv s)
-  send (s_new (synthdefName s) (-1) AddToTail 1 [])
+  send (s_new0 (synthdefName s) (-1) AddToTail 1)
 
 -- | Send an /anonymous/ instrument definition using 'playSynthdef'.
 playUGen :: DuplexOSC m => UGen -> m ()
@@ -111,7 +115,7 @@
 b_getn1_data :: DuplexOSC m => Int -> (Int,Int) -> m [Double]
 b_getn1_data b s = do
   let f d = case d of
-              Int _:Int _:Int _:x -> map datum_real_err x
+              Int32 _:Int32 _:Int32 _:x -> mapMaybe datum_floating x
               _ -> error "b_getn1_data"
   sendMessage (b_getn1 b s)
   liftM f (waitDatum "/b_setn")
@@ -120,7 +124,8 @@
 -- messages to /n/ elements.
 --
 -- > withSC3 (b_getn1_data_segment 1 0 (0,5))
-b_getn1_data_segment :: DuplexOSC m => Int -> Int -> (Int,Int) -> m [Double]
+b_getn1_data_segment :: DuplexOSC m =>
+                        Int -> Int -> (Int,Int) -> m [Double]
 b_getn1_data_segment n b (i,j) = do
   let ix = b_indices n j i
   d <- mapM (b_getn1_data b) ix
@@ -130,8 +135,8 @@
 b_fetch :: DuplexOSC m => Int -> Int -> m [Double]
 b_fetch n b = do
   let f d = case d of
-              [Int _,Int nf,Int nc,Float _] ->
-                  let ix = (0,nf * nc)
+              [Int32 _,Int32 nf,Int32 nc,Float _] ->
+                  let ix = (0,fromIntegral (nf * nc))
                   in b_getn1_data_segment n b ix
               _ -> error "b_fetch"
   sendMessage (b_query1 b)
@@ -144,10 +149,14 @@
 serverStatus = liftM statusFormat serverStatusData
 
 -- | Read nominal sample rate of server.
+--
+-- > withSC3 serverSampleRateNominal
 serverSampleRateNominal :: DuplexOSC m => m Double
 serverSampleRateNominal = liftM (extractStatusField 7) serverStatusData
 
 -- | Read actual sample rate of server.
+--
+-- > withSC3 serverSampleRateActual
 serverSampleRateActual :: DuplexOSC m => m Double
 serverSampleRateActual = liftM (extractStatusField 8) serverStatusData
 
diff --git a/Sound/SC3/Server/Utilities.hs b/Sound/SC3/Server/Utilities.hs
--- a/Sound/SC3/Server/Utilities.hs
+++ b/Sound/SC3/Server/Utilities.hs
@@ -14,4 +14,3 @@
 -- at /z/.
 mk_triples :: (a -> d) -> (b -> d) -> (c -> d) -> [(a, b, c)] -> [d]
 mk_triples a b c = concatMap (\(x,y,z) -> [a x, b y, c z])
-
diff --git a/Sound/SC3/UGen/Analysis.hs b/Sound/SC3/UGen/Analysis.hs
--- a/Sound/SC3/UGen/Analysis.hs
+++ b/Sound/SC3/UGen/Analysis.hs
@@ -9,10 +9,6 @@
 amplitude :: Rate -> UGen -> UGen -> UGen -> UGen
 amplitude r i at rt = mkOsc r "Amplitude" [i, at, rt] 1
 
--- | Calculates mean average of audio or control rate signal.
-averageOutput :: UGen -> UGen -> UGen
-averageOutput in_ trig_ = mkFilter "AverageOutput" [in_,trig_] 1
-
 -- | Autocorrelation pitch follower.
 pitch :: UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
 pitch i initFreq minFreq maxFreq execFreq maxBinsPerOctave median ampThreshold peakThreshold downSample = mkOsc KR "Pitch" [i, initFreq, minFreq, maxFreq, execFreq, maxBinsPerOctave, median, ampThreshold, peakThreshold, downSample] 2
diff --git a/Sound/SC3/UGen/Composite/Monad.hs b/Sound/SC3/UGen/Composite/Monad.hs
--- a/Sound/SC3/UGen/Composite/Monad.hs
+++ b/Sound/SC3/UGen/Composite/Monad.hs
@@ -7,7 +7,6 @@
 import Sound.SC3.UGen.Noise.Monad
 import Sound.SC3.UGen.Type
 import Sound.SC3.UGen.UGen
-import Sound.SC3.UGen.UGen.Lift
 import Sound.SC3.UGen.UId
 
 -- | Demand rate (:) function.
@@ -17,13 +16,13 @@
   a <- dseq 1 (mce2 x xs)
   dswitch i a
 
--- | 'liftU' of 'C.choose'.
+-- | 'liftUId' of 'C.choose'.
 choose :: UId m => UGen -> m UGen
-choose = liftU C.choose
+choose = liftUId C.choose
 
--- | 'liftU' of 'C.lchoose'.
+-- | 'liftUId' of 'C.lchoose'.
 lchoose :: UId m => [UGen] -> m UGen
-lchoose = liftU C.lchoose
+lchoose = liftUId C.lchoose
 
 -- | Randomly select one of several inputs.
 tChoose :: (UId m) => UGen -> UGen -> m UGen
diff --git a/Sound/SC3/UGen/Demand.hs b/Sound/SC3/UGen/Demand.hs
--- a/Sound/SC3/UGen/Demand.hs
+++ b/Sound/SC3/UGen/Demand.hs
@@ -8,7 +8,7 @@
 
 -- | Infinte repeat counter for demand rate unit generators.
 dinf :: UGen
-dinf = constant (9E8::Double)
+dinf = constant (9e8::Float)
 
 -- | Demand results from demand rate ugens.
 demand :: UGen -> UGen -> UGen -> UGen
diff --git a/Sound/SC3/UGen/Demand/Monad.hs b/Sound/SC3/UGen/Demand/Monad.hs
--- a/Sound/SC3/UGen/Demand/Monad.hs
+++ b/Sound/SC3/UGen/Demand/Monad.hs
@@ -5,73 +5,72 @@
 import Sound.SC3.UGen.Demand.ID as D
 import Sound.SC3.UGen.Enum
 import Sound.SC3.UGen.Type
-import Sound.SC3.UGen.UGen.Lift
 import Sound.SC3.UGen.UId
 
 -- | Buffer demand ugen.
 dbufrd :: (UId m) => UGen -> UGen -> Loop -> m UGen
-dbufrd = liftU3 D.dbufrd
+dbufrd = liftUId3 D.dbufrd
 
 -- | Buffer write on demand unit generator.
 dbufwr :: (UId m) => UGen -> UGen -> UGen -> Loop -> m UGen
-dbufwr = liftU4 D.dbufwr
+dbufwr = liftUId4 D.dbufwr
 
 -- | Demand rate white noise.
 dwhite :: (UId m) => UGen -> UGen -> UGen -> m UGen
-dwhite = liftU3 D.dwhite
+dwhite = liftUId3 D.dwhite
 
 -- | Demand rate integer white noise.
 diwhite :: (UId m) => UGen -> UGen -> UGen -> m UGen
-diwhite = liftU3 D.diwhite
+diwhite = liftUId3 D.diwhite
 
 -- | Demand rate brown noise.
 dbrown :: (UId m) => UGen -> UGen -> UGen -> UGen -> m UGen
-dbrown = liftU4 D.dbrown
+dbrown = liftUId4 D.dbrown
 
 -- | Demand rate integer brown noise.
 dibrown :: (UId m) => UGen -> UGen -> UGen -> UGen -> m UGen
-dibrown = liftU4 D.dibrown
+dibrown = liftUId4 D.dibrown
 
 -- | Demand rate random selection.
 drand :: (UId m) => UGen -> UGen -> m UGen
-drand = liftU2 D.drand
+drand = liftUId2 D.drand
 
 -- | Demand rate random selection with no immediate repetition.
 dxrand :: (UId m) => UGen -> UGen -> m UGen
-dxrand = liftU2 D.dxrand
+dxrand = liftUId2 D.dxrand
 
 -- | Demand rate weighted random sequence generator.
 dwrand :: (UId m) => UGen -> UGen -> UGen -> m UGen
-dwrand = liftU3 D.dwrand
+dwrand = liftUId3 D.dwrand
 
 -- | Demand rate arithmetic series.
 dseries :: (UId m) => UGen -> UGen -> UGen -> m UGen
-dseries = liftU3 D.dseries
+dseries = liftUId3 D.dseries
 
 -- | Demand rate geometric series.
 dgeom :: (UId m) => UGen -> UGen -> UGen -> m UGen
-dgeom = liftU3 D.dgeom
+dgeom = liftUId3 D.dgeom
 
 -- | Demand rate sequence generator.
 dseq :: (UId m) => UGen -> UGen -> m UGen
-dseq = liftU2 D.dseq
+dseq = liftUId2 D.dseq
 
 -- | Demand rate series generator.
 dser :: (UId m) => UGen -> UGen -> m UGen
-dser = liftU2 D.dser
+dser = liftUId2 D.dser
 
 -- | Demand rate sequence shuffler.
 dshuf :: (UId m) => UGen -> UGen -> m UGen
-dshuf = liftU2 D.dshuf
+dshuf = liftUId2 D.dshuf
 
 -- | Demand input replication
 dstutter :: (UId m) => UGen -> UGen -> m UGen
-dstutter = liftU2 D.dstutter
+dstutter = liftUId2 D.dstutter
 
 -- | Demand rate input switching.
 dswitch1 :: (UId m) => UGen -> UGen -> m UGen
-dswitch1 = liftU2 D.dswitch1
+dswitch1 = liftUId2 D.dswitch1
 
 -- | Demand rate input switching.
 dswitch :: (UId m) => UGen -> UGen -> m UGen
-dswitch = liftU2 D.dswitch
+dswitch = liftUId2 D.dswitch
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
@@ -114,6 +114,16 @@
       EnvSqr -> squared
       EnvCub -> cubed
 
+data Buffer = Buffer_Id Int
+            | Buffer UGen
+              deriving (Eq, Show)
+
+from_buffer :: Buffer -> UGen
+from_buffer b =
+    case b of
+      Buffer_Id i -> constant i
+      Buffer u -> u
+
 -- | Enumeration of flags for '/b_gen' command.
 data B_Gen = Normalise | Wavetable | Clear
              deriving (Eq,Enum,Bounded,Show)
diff --git a/Sound/SC3/UGen/External.hs b/Sound/SC3/UGen/External.hs
--- a/Sound/SC3/UGen/External.hs
+++ b/Sound/SC3/UGen/External.hs
@@ -6,12 +6,6 @@
 import Sound.SC3.UGen.Type
 import Sound.SC3.UGen.UGen
 
--- * DFM1
-
--- | Variant FM synthesis node.
-dfm1 :: UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
-dfm1 i f r g ty nl = mkFilter "DFM1" [i,f,r,g,ty,nl] 1
-
 -- * f0plugins
 
 -- | Emulation of the sound generation hardware of the Atari TIA chip.
@@ -22,13 +16,7 @@
 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
 
--- * skUG
-
--- | Phase modulation oscillator matrix.
-fm7 :: [[UGen]] -> [[UGen]] -> UGen
-fm7 ctl m0d = mkOsc AR "FM7" (concat ctl ++ concat m0d) 6
-
--- * PitchDetection
+-- * PitchDetection (sc3-plugins)
 
 -- | Tartini model pitch tracker.
 tartini ::  Rate -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
@@ -37,6 +25,24 @@
 -- | Constant Q transform pitch follower.
 qitch ::  Rate -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
 qitch r input databufnum ampThreshold algoflag ampbufnum minfreq maxfreq = mkOscR [KR] r "Qitch" [input,databufnum,ampThreshold,algoflag,ampbufnum,minfreq,maxfreq] 2
+
+-- * RFW UGens (sc3-plugins)
+
+-- | Calculates mean average of audio or control rate signal.
+averageOutput :: UGen -> UGen -> UGen
+averageOutput in_ trig_ = mkFilter "AverageOutput" [in_,trig_] 1
+
+-- * skUG
+
+-- | Phase modulation oscillator matrix.
+fm7 :: [[UGen]] -> [[UGen]] -> UGen
+fm7 ctl m0d = mkOsc AR "FM7" (concat ctl ++ concat m0d) 6
+
+-- * TJ UGens (sc3-plugins)
+
+-- | Variant FM synthesis node.
+dfm1 :: UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
+dfm1 i f r g ty nl = mkFilter "DFM1" [i,f,r,g,ty,nl] 1
 
 -- Local Variables:
 -- truncate-lines:t
diff --git a/Sound/SC3/UGen/External/ATS.hs b/Sound/SC3/UGen/External/ATS.hs
--- a/Sound/SC3/UGen/External/ATS.hs
+++ b/Sound/SC3/UGen/External/ATS.hs
@@ -4,10 +4,10 @@
                                    ,ATSFrame,atsFrames
                                    ,atsRead) where
 
-import qualified Data.ByteString.Lazy as B
-import Data.Int
-import Data.List.Split
-import Sound.OpenSoundControl.Coding.Byte
+import qualified Data.ByteString.Lazy as B {- bytestring -}
+import Data.Int {- base -}
+import Data.List.Split {- split -}
+import Sound.OSC.Coding.Byte {- hosc -}
 
 -- | ATS analysis data.
 data ATS = ATS { atsHeader :: ATSHeader
diff --git a/Sound/SC3/UGen/External/LPC.hs b/Sound/SC3/UGen/External/LPC.hs
--- a/Sound/SC3/UGen/External/LPC.hs
+++ b/Sound/SC3/UGen/External/LPC.hs
@@ -8,7 +8,7 @@
 import Control.Monad
 import qualified Data.ByteString.Lazy as B
 import Data.List
-import Sound.OpenSoundControl.Coding.Byte
+import Sound.OSC.Coding.Byte
 import System.IO
 
 -- | LPC analysis data.
@@ -21,14 +21,14 @@
                            , lpcMagic :: Int
                            , lpcNPoles :: Int
                            , lpcFrameSize :: Int
-                           , lpcFrameRate :: Double
-                           , lpcSampleRate :: Double
-                           , lpcAnalysisDuration :: Double
+                           , lpcFrameRate :: Float
+                           , lpcSampleRate :: Float
+                           , lpcAnalysisDuration :: Float
                            , lpcNFrames :: Int
                            } deriving (Eq, Show)
 
 -- | LPC analysis frame data.
-type LPCFrame = [Double]
+type LPCFrame = [Float]
 
 -- | Read an lpanal format LPC data file.
 lpcRead :: FilePath -> IO LPC
@@ -47,7 +47,7 @@
   return (LPC hdr d)
 
 -- | Analysis data in format required by the sc3 LPC UGens.
-lpcSC3 :: LPC -> [Double]
+lpcSC3 :: LPC -> [Float]
 lpcSC3 (LPC h d) = let f = fromIntegral
                        np = f (lpcNPoles h)
                        nf = f (lpcNFrames h)
@@ -57,6 +57,6 @@
 read_i32 :: Handle -> IO Int
 read_i32 h = liftM decode_i32 (B.hGet h 4)
 
-read_f32 :: Handle -> IO Double
+read_f32 :: Handle -> IO Float
 read_f32 h = liftM decode_f32 (B.hGet h 4)
 
diff --git a/Sound/SC3/UGen/External/SC3_Plugins.hs b/Sound/SC3/UGen/External/SC3_Plugins.hs
--- a/Sound/SC3/UGen/External/SC3_Plugins.hs
+++ b/Sound/SC3/UGen/External/SC3_Plugins.hs
@@ -16,6 +16,12 @@
 ayFreqToTone :: Fractional a => a -> a
 ayFreqToTone f = 110300 / (f - 0.5)
 
+-- * Bhob
+
+-- | String resonance filter
+streson :: UGen -> UGen -> UGen -> UGen
+streson input delayTime res = mkFilter "Streson" [input,delayTime,res] 1
+
 -- * Concat
 
 -- | Concatenative cross-synthesis.
@@ -66,6 +72,12 @@
 pv_Invert :: UGen -> UGen
 pv_Invert b = mkOsc KR "PV_Invert" [b] 1
 
+-- * MCLD
+
+-- | 3D Perlin Noise
+perlin3 :: Rate -> UGen -> UGen -> UGen -> UGen
+perlin3 rate x y z = mkOscR [AR,KR] rate "Perlin3" [x,y,z] 1
+
 -- * Membrane
 
 -- | Triangular waveguide mesh of a drum-like membrane.
@@ -81,6 +93,16 @@
 -- | Tracking Phase Vocoder
 tpv :: UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
 tpv chain windowsize hopsize maxpeaks currentpeaks freqmult tolerance noisefloor = mkOsc AR "TPV" [chain,windowsize,hopsize,maxpeaks,currentpeaks,freqmult,tolerance,noisefloor] 1
+
+-- * SLU
+
+-- | Prigogine oscillator
+brusselator :: Rate -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
+brusselator rate reset rate_ mu gamma initx inity = mkOscR [AR] rate "Brusselator" [reset,rate_,mu,gamma,initx,inity] 2
+
+-- | Forced DoubleWell Oscillator
+doubleWell3 :: Rate -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
+doubleWell3 rate reset rate_ f delta initx inity = mkOscR [AR] rate "DoubleWell3" [reset,rate_,f,delta,initx,inity] 1
 
 -- * Stk
 
diff --git a/Sound/SC3/UGen/FFT.hs b/Sound/SC3/UGen/FFT.hs
--- a/Sound/SC3/UGen/FFT.hs
+++ b/Sound/SC3/UGen/FFT.hs
@@ -1,8 +1,7 @@
 -- | Frequency domain unit generators.
 module Sound.SC3.UGen.FFT where
 
-import Sound.OpenSoundControl
-import Sound.SC3.Server.Command
+--import Sound.SC3.Server.Command
 import Sound.SC3.UGen.Rate
 import Sound.SC3.UGen.Type
 import Sound.SC3.UGen.UGen
@@ -193,11 +192,6 @@
     let partition_size = fft_size `div` 2
         num_partitions = (ir_length `div` partition_size) + 1
     in fft_size * num_partitions
-
--- | Generate accumulation buffer given time-domain IR buffer and FFT size.
-pc_preparePartConv :: Int -> Int -> Int -> Message
-pc_preparePartConv b irb fft_size =
-    b_gen b "PreparePartConv" (map Int [irb, fft_size])
 
 -- | Partitioned convolution.
 partConv :: UGen -> UGen -> UGen -> UGen
diff --git a/Sound/SC3/UGen/FFT/Monad.hs b/Sound/SC3/UGen/FFT/Monad.hs
--- a/Sound/SC3/UGen/FFT/Monad.hs
+++ b/Sound/SC3/UGen/FFT/Monad.hs
@@ -3,17 +3,16 @@
 
 import Sound.SC3.UGen.FFT.ID as F
 import Sound.SC3.UGen.Type
-import Sound.SC3.UGen.UGen.Lift
 import Sound.SC3.UGen.UId
 
 -- | Randomize order of bins.
 pv_BinScramble :: (UId m) => UGen -> UGen -> UGen -> UGen -> m UGen
-pv_BinScramble = liftU4 F.pv_BinScramble
+pv_BinScramble = liftUId4 F.pv_BinScramble
 
 -- | Randomly clear bins.
 pv_RandComb :: (UId m) => UGen -> UGen -> UGen -> m UGen
-pv_RandComb = liftU3 F.pv_RandComb
+pv_RandComb = liftUId3 F.pv_RandComb
 
 -- | Cross fade, copying bins in random order.
 pv_RandWipe :: (UId m) => UGen -> UGen -> UGen -> UGen -> m UGen
-pv_RandWipe = liftU4 F.pv_RandWipe
+pv_RandWipe = liftUId4 F.pv_RandWipe
diff --git a/Sound/SC3/UGen/Filter.hs b/Sound/SC3/UGen/Filter.hs
--- a/Sound/SC3/UGen/Filter.hs
+++ b/Sound/SC3/UGen/Filter.hs
@@ -171,7 +171,7 @@
 klankSpec f a dt = mce ((concat . transpose) [f,a,dt])
 
 -- | Variant for non-UGen inputs.
-klankSpec' :: [Double] -> [Double] -> [Double] -> UGen
+klankSpec' :: Real n => [n] -> [n] -> [n] -> UGen
 klankSpec' f a dt =
     let u = map constant
     in klankSpec (u f) (u a) (u dt)
diff --git a/Sound/SC3/UGen/Graph.hs b/Sound/SC3/UGen/Graph.hs
new file mode 100644
--- /dev/null
+++ b/Sound/SC3/UGen/Graph.hs
@@ -0,0 +1,43 @@
+-- | Standard SC3 graphs, referenced in documentation.
+module Sound.SC3.UGen.Graph where
+
+import Sound.SC3.UGen.ID
+
+-- | The SC3 /default/ instrument 'UGen' graph.
+default_ugen_graph :: UGen
+default_ugen_graph =
+    let f = control KR "freq" 440
+        a = control KR "amp" 0.1
+        p = control KR "pan" 0
+        g = control KR "gate" 1
+        e = linen g 0.01 0.7 0.3 RemoveSynth
+        f3 = mce [f,f + rand 'α' (-0.4) 0,f + rand 'β' 0 0.4]
+        l = xLine KR (rand 'γ' 4000 5000) (rand 'δ' 2500 3200) 1 DoNothing
+        z = lpf (mix (varSaw AR f3 0 0.3 * 0.3)) l * e
+    in out 0 (pan2 z p a)
+
+-- | A /Gabor/ grain, envelope is by 'lfGauss'.
+gabor_grain_ugen_graph :: UGen
+gabor_grain_ugen_graph =
+    let o = control IR "out" 0
+        f = control IR "freq" 440
+        d = control IR "sustain" 1
+        l = control IR "pan" 1
+        a = control IR "amp" 0.1
+        w = control IR "width" 0.25
+        e = lfGauss AR d w 0 NoLoop RemoveSynth
+        s = fSinOsc AR f (0.5 * pi) * e
+    in offsetOut o (pan2 s l a)
+
+-- | A /sine/ grain, envelope is by 'envGen' of 'envSine'.
+sine_grain_ugen_graph :: UGen
+sine_grain_ugen_graph =
+    let o = control IR "out" 0
+        f = control IR "freq" 440
+        d = control IR "sustain" 1
+        l = control IR "pan" 1
+        a = control IR "amp" 0.1
+        w = control IR "width" 0.25
+        e = envGen AR 1 1 0 1 DoNothing (envSine (d * w) 1)
+        s = fSinOsc AR f (0.5 * pi) * e
+    in offsetOut o (pan2 s l a)
diff --git a/Sound/SC3/UGen/Help.hs b/Sound/SC3/UGen/Help.hs
--- a/Sound/SC3/UGen/Help.hs
+++ b/Sound/SC3/UGen/Help.hs
@@ -4,6 +4,7 @@
 import Control.Exception
 import Control.Monad
 import Data.List.Split {- split -}
+import Data.Maybe
 import System.IO.Error
 import System.Cmd {- process -}
 import System.Directory {- directory -}
@@ -17,6 +18,12 @@
   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@.
diff --git a/Sound/SC3/UGen/Identifier.hs b/Sound/SC3/UGen/Identifier.hs
--- a/Sound/SC3/UGen/Identifier.hs
+++ b/Sound/SC3/UGen/Identifier.hs
@@ -1,7 +1,7 @@
 -- | Typeclass and functions to manage UGen identifiers.
 module Sound.SC3.UGen.Identifier where
 
-import Data.Char
+import Data.Char {- base -}
 import qualified Data.Digest.Murmur32 as H {- murmur-hash -}
 
 -- | Typeclass to constrain UGen identifiers.
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,7 +1,9 @@
 -- | Non-standard mathematical classes and class instances.
 module Sound.SC3.UGen.Math where
 
-import qualified Data.Fixed as F
+import qualified Data.Fixed as F {- base -}
+import Data.Int
+
 import Sound.SC3.UGen.Operator
 import Sound.SC3.UGen.Type
 
@@ -9,30 +11,40 @@
 -- mangling.  True is 1.0, False is 0.0
 
 -- | Variant on Eq class, result is of the same type as the values compared.
-class EqE a where
+class (Eq a,Num a) => EqE a where
     (==*) :: a -> a -> a
+    a ==* b = if a == b then 1 else 0
     (/=*) :: a -> a -> a
+    a /=* b = if a /= b then 1 else 0
 
+instance EqE Int where
+instance EqE Integer where
+instance EqE Int32 where
+instance EqE Int64 where
+instance EqE Float where
 instance EqE Double where
-    a ==* b = if a == b then 1.0 else 0.0
-    a /=* b = if a /= b then 1.0 else 0.0
 
 instance EqE UGen where
     (==*) = mkBinaryOperator EQ_ (==*)
     (/=*) = mkBinaryOperator NE (/=*)
 
 -- | Variant on Ord class, result is of the same type as the values compared.
-class OrdE a where
+class (Ord a,Num a) => OrdE a where
     (<*) :: a -> a -> a
+    a <* b = if a < b then 1 else 0
     (<=*) :: a -> a -> a
+    a <=* b = if a <= b then 1 else 0
     (>*) :: a -> a -> a
+    a >* b = if a > b then 1 else 0
     (>=*) :: a -> a -> a
+    a >=* b = if a >= b then 1 else 0
 
-instance OrdE Double where
-    a <* b = if a < b then 1.0 else 0.0
-    a <=* b = if a <= b then 1.0 else 0.0
-    a >* b = if a > b then 1.0 else 0.0
-    a >=* b = if a >= b then 1.0 else 0.0
+instance OrdE Int
+instance OrdE Integer
+instance OrdE Int32 where
+instance OrdE Int64 where
+instance OrdE Float
+instance OrdE Double
 
 instance OrdE UGen where
     (<*) = mkBinaryOperator LT_ (<*)
@@ -41,52 +53,36 @@
     (>=*) = mkBinaryOperator GE (>=*)
 
 -- | Variant of 'RealFrac' with non 'Integral' results.
-class RealFracE a where
+class RealFrac a => RealFracE a where
   properFractionE :: a -> (a,a)
+  properFractionE a = let (p,q) = properFraction a
+                      in (fromInteger p,q)
   truncateE :: a -> a
+  truncateE a = fromInteger (truncate a)
   roundE :: a -> a
+  roundE a = fromInteger (round a)
   ceilingE :: a -> a
+  ceilingE a = fromInteger (ceiling a)
   floorE :: a -> a
-
--- | Variant of 'truncate'.
-truncatef :: RealFrac a => a -> a
-truncatef a = fromIntegral (truncate a :: Integer)
-
--- | Variant of 'round'.
-roundf :: RealFrac a => a -> a
-roundf a = fromIntegral (round a :: Integer)
-
--- | Variant of 'ceiling'.
-ceilingf :: RealFrac a => a -> a
-ceilingf a = fromIntegral (ceiling a :: Integer)
-
--- | Variant of 'floor'.
-floorf :: RealFrac a => a -> a
-floorf a = fromIntegral (floor a :: Integer)
+  floorE a = fromInteger (floor a)
 
-instance RealFracE Double where
-    properFractionE n =
-        let (i,j) = properFraction n
-        in (fromIntegral (i::Integer),j)
-    truncateE = truncatef
-    roundE = roundf
-    ceilingE = ceilingf
-    floorE = floorf
+instance RealFracE Float
+instance RealFracE Double
 
 -- | Variant of @SC3@ @roundTo@ function.
-roundTo_ :: Double -> Double -> Double
-roundTo_ a b = if b == 0 then a else floorf (a/b + 0.5) * b
+roundTo_ :: RealFracE a => a -> a -> a
+roundTo_ a b = if b == 0 then a else floorE (a/b + 0.5) * b
 
 -- | 'UGen' form or 'roundTo_'.
 roundTo :: UGen -> UGen -> UGen
 roundTo = mkBinaryOperator Round roundTo_
 
 instance RealFracE UGen where
-    properFractionE = error "RealFracE,UGen,partial"
-    truncateE = error "RealFracE,UGen,partial"
+    properFractionE = error "UGen.properFractionE"
+    truncateE = error "UGen.truncateE"
     roundE i = roundTo i 1
-    ceilingE = mkUnaryOperator Ceil ceilingf
-    floorE = mkUnaryOperator Floor floorf
+    ceilingE = mkUnaryOperator Ceil ceilingE
+    floorE = mkUnaryOperator Floor floorE
 
 -- | 'UGen' form of 'ceilingE'.
 ceil :: UGen -> UGen
@@ -143,6 +139,7 @@
     squared :: a -> a
     squared a = a * a
 
+instance UnaryOp Float where
 instance UnaryOp Double where
 
 instance UnaryOp UGen where
@@ -189,6 +186,7 @@
     firstArg :: a -> a -> a
     firstArg a _ = a
     fold2 :: a -> a -> a
+    fold2 a b = fold_ a (-b) b
     gcdE :: a -> a -> a
     gcdE = error "gcdE"
     hypot :: a -> a -> a
@@ -200,6 +198,7 @@
     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
@@ -211,6 +210,7 @@
     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
@@ -224,6 +224,7 @@
     trunc :: a -> a -> a
     trunc = error "trunc"
     wrap2 :: a -> a -> a
+    wrap2 = error "wrap2"
 
 -- | The SC3 @%@ operator is libc fmod function.
 --
@@ -246,18 +247,24 @@
 -- > (-1.2) `fmod` 1.5 -- ~= 0.3
 -- > 1.2 `fmod` (-1.5) -- ~= -0.3
 -- > (-1.2) `fmod` (-1.5) -- ~= -1.2
-fmod :: Double -> Double -> Double
-fmod = F.mod'
+fmod_f32 :: Float -> Float -> Float
+fmod_f32 = F.mod'
 
+instance BinaryOp Float where
+    fold2 a b = 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 = wrap_ a (-b) b
+
 instance BinaryOp Double where
     fold2 a b = fold_ a (-b) b
-    modE = fmod
-    roundUp a b = if b == 0 then a else ceilingf (a/b + 0.5) * b
+    modE = F.mod'
+    roundUp a b = if b == 0 then a else ceilingE (a/b + 0.5) * b
     wrap2 a b = wrap_ a (-b) b
 
 instance BinaryOp UGen where
     iDiv = mkBinaryOperator IDiv iDiv
-    modE = mkBinaryOperator Mod fmod
+    modE = mkBinaryOperator Mod F.mod'
     lcmE = mkBinaryOperator LCM lcmE
     gcdE = mkBinaryOperator GCD gcdE
     roundUp = mkBinaryOperator RoundUp roundUp
@@ -288,20 +295,28 @@
 
 -- | Wrap /k/ to within range /(i,j)/, ie. @AbstractFunction.wrap@.
 --
--- > map (wrap' 5 10) [3..12] == [8,9,5,6,7,8,9,10,6,7]
-wrap' :: Double -> Double -> Double -> Double
+-- > > [5,6].wrap(0,5) == [5,0]
+-- > map (wrap' 0 5) [5,6] == [5,0]
+--
+-- > > [9,10,5,6,7,8,9,10,5,6].wrap(5,10) == [9,10,5,6,7,8,9,10,5,6]
+-- > map (wrap' 5 10) [3..12] == [9,10,5,6,7,8,9,10,5,6]
+wrap' :: RealFracE n => n -> n -> n -> n
 wrap' i j k =
-    let r = j - i
+    let r = j - i + 1
     in if k >= i && k <= j
        then k
-       else k - r * floorf ((k-i) / r)
+       else k - r * floorE ((k-i) / r)
 
 -- | Generic variant of 'wrap''.
 --
--- > map (genericWrap (5::Integer) 10) [3..12] == [8,9,5,6,7,8,9,10,6,7]
+-- > > [5,6].wrap(0,5) == [5,0]
+-- > map (genericWrap 0 5) [5,6] == [5,0]
+--
+-- > > [9,10,5,6,7,8,9,10,5,6].wrap(5,10) == [9,10,5,6,7,8,9,10,5,6]
+-- > map (genericWrap (5::Integer) 10) [3..12] == [9,10,5,6,7,8,9,10,5,6]
 genericWrap :: (Ord a, Num a) => a -> a -> a -> a
 genericWrap l r n =
-    let d = r - l
+    let d = r - l + 1
         f = genericWrap l r
     in if n < l
        then f (n + d)
@@ -310,7 +325,7 @@
 -- | Variant of 'wrap'' with @SC3@ argument ordering.
 --
 -- > map (\n -> wrap_ n 5 10) [3..12] == map (wrap' 5 10) [3..12]
-wrap_ :: Double -> Double -> Double -> Double
+wrap_ :: RealFracE n => n -> n -> n -> n
 wrap_ a b c = wrap' b c a
 
 -- | Fold /k/ to within range /(i,j)/, ie. @AbstractFunction.fold@
diff --git a/Sound/SC3/UGen/Noise/Monad.hs b/Sound/SC3/UGen/Noise/Monad.hs
--- a/Sound/SC3/UGen/Noise/Monad.hs
+++ b/Sound/SC3/UGen/Noise/Monad.hs
@@ -4,109 +4,108 @@
 import Sound.SC3.UGen.Noise.ID as N
 import Sound.SC3.UGen.Rate
 import Sound.SC3.UGen.Type
-import Sound.SC3.UGen.UGen.Lift
 import Sound.SC3.UGen.UId
 
 -- | Brown noise.
 brownNoise :: (UId m) => Rate -> m UGen
-brownNoise = liftU N.brownNoise
+brownNoise = liftUId N.brownNoise
 
 -- | Clip noise.
 clipNoise :: (UId m) => Rate -> m UGen
-clipNoise = liftU N.clipNoise
+clipNoise = liftUId N.clipNoise
 
 -- | Randomly pass or block triggers.
 coinGate :: (UId m) => UGen -> UGen -> m UGen
-coinGate = liftU2 N.coinGate
+coinGate = liftUId2 N.coinGate
 
 -- | Random impulses in (-1, 1).
 dust2 :: (UId m) => Rate -> UGen -> m UGen
-dust2 = liftU2 N.dust2
+dust2 = liftUId2 N.dust2
 
 -- | Random impulse in (0,1).
 dust :: (UId m) => Rate -> UGen -> m UGen
-dust = liftU2 N.dust
+dust = liftUId2 N.dust
 
 -- | Random value in exponential distribution.
 expRand :: (UId m) => UGen -> UGen -> m UGen
-expRand = liftU2 N.expRand
+expRand = liftUId2 N.expRand
 
 -- | Gray noise.
 grayNoise :: (UId m) => Rate -> m UGen
-grayNoise = liftU N.grayNoise
+grayNoise = liftUId N.grayNoise
 
 -- | Random integer in uniform distribution.
 iRand :: (UId m) => UGen -> UGen -> m UGen
-iRand = liftU2 N.iRand
+iRand = liftUId2 N.iRand
 
 -- | Clip noise.
 lfClipNoise :: (UId m) => Rate -> UGen -> m UGen
-lfClipNoise = liftU2 N.lfClipNoise
+lfClipNoise = liftUId2 N.lfClipNoise
 
 -- | Dynamic clip noise.
 lfdClipNoise :: (UId m) => Rate -> UGen -> m UGen
-lfdClipNoise = liftU2 N.lfdClipNoise
+lfdClipNoise = liftUId2 N.lfdClipNoise
 
 -- | Dynamic step noise.
 lfdNoise0 :: (UId m) => Rate -> UGen -> m UGen
-lfdNoise0 = liftU2 N.lfdNoise0
+lfdNoise0 = liftUId2 N.lfdNoise0
 
 -- | Dynamic ramp noise.
 lfdNoise1 :: (UId m) => Rate -> UGen -> m UGen
-lfdNoise1 = liftU2 N.lfdNoise1
+lfdNoise1 = liftUId2 N.lfdNoise1
 
 -- | Dynamic quadratic noise
 lfdNoise2 :: (UId m) => Rate -> UGen -> m UGen
-lfdNoise2 = liftU2 N.lfdNoise2
+lfdNoise2 = liftUId2 N.lfdNoise2
 
 -- | Dynamic cubic noise
 lfdNoise3 :: (UId m) => Rate -> UGen -> m UGen
-lfdNoise3 = liftU2 N.lfdNoise3
+lfdNoise3 = liftUId2 N.lfdNoise3
 
 -- | Step noise.
 lfNoise0 :: (UId m) => Rate -> UGen -> m UGen
-lfNoise0 = liftU2 N.lfNoise0
+lfNoise0 = liftUId2 N.lfNoise0
 
 -- | Ramp noise.
 lfNoise1 :: (UId m) => Rate -> UGen -> m UGen
-lfNoise1 = liftU2 N.lfNoise1
+lfNoise1 = liftUId2 N.lfNoise1
 
 -- | Quadratic noise.
 lfNoise2 :: (UId m) => Rate -> UGen -> m UGen
-lfNoise2 = liftU2 N.lfNoise2
+lfNoise2 = liftUId2 N.lfNoise2
 
 -- | Random value in skewed linear distribution.
 linRand :: (UId m) => UGen -> UGen -> UGen -> m UGen
-linRand = liftU3 N.linRand
+linRand = liftUId3 N.linRand
 
 -- | Random value in sum of n linear distribution.
 nRand :: (UId m) => UGen -> UGen -> UGen -> m UGen
-nRand = liftU3 N.nRand
+nRand = liftUId3 N.nRand
 
 -- | Pink noise.
 pinkNoise :: (UId m) => Rate -> m UGen
-pinkNoise = liftU N.pinkNoise
+pinkNoise = liftUId N.pinkNoise
 
 -- | Random value in uniform distribution.
 rand :: (UId m) => UGen -> UGen -> m UGen
-rand = liftU2 N.rand
+rand = liftUId2 N.rand
 
 -- | Random value in exponential distribution on trigger.
 tExpRand :: (UId m) => UGen -> UGen -> UGen -> m UGen
-tExpRand = liftU3 N.tExpRand
+tExpRand = liftUId3 N.tExpRand
 
 -- | Random integer in uniform distribution on trigger.
 tIRand :: (UId m) => UGen -> UGen -> UGen -> m UGen
-tIRand = liftU3 N.tIRand
+tIRand = liftUId3 N.tIRand
 
 -- | Random value in uniform distribution on trigger.
 tRand :: (UId m) => UGen -> UGen -> UGen -> m UGen
-tRand = liftU3 N.tRand
+tRand = liftUId3 N.tRand
 
 -- | Triggered windex.
 tWindex :: (UId m) => UGen -> UGen -> UGen -> m UGen
-tWindex = liftU3 N.tWindex
+tWindex = liftUId3 N.tWindex
 
 -- | White noise.
 whiteNoise :: (UId m) => Rate -> m UGen
-whiteNoise = liftU N.whiteNoise
+whiteNoise = liftUId N.whiteNoise
diff --git a/Sound/SC3/UGen/Oscillator.hs b/Sound/SC3/UGen/Oscillator.hs
--- a/Sound/SC3/UGen/Oscillator.hs
+++ b/Sound/SC3/UGen/Oscillator.hs
@@ -9,7 +9,7 @@
 
 -- | Band Limited ImPulse generator.
 blip :: Rate -> UGen -> UGen -> UGen
-blip r freq nharm = mkOscR [AR] r "Blip" [freq, nharm] 1
+blip r freq nharm = mkOscR [AR,KR] r "Blip" [freq, nharm] 1
 
 -- | Chorusing wavetable oscillator.
 cOsc :: Rate -> UGen -> UGen -> UGen -> UGen
@@ -47,7 +47,7 @@
 klangSpec f a p = mce ((concat . transpose) [f, a, p])
 
 -- | Variant of 'klangSpec' for non-UGen inputs.
-klangSpec' :: [Double] -> [Double] -> [Double] -> UGen
+klangSpec' :: Real n => [n] -> [n] -> [n] -> UGen
 klangSpec' f a p =
     let u = map constant
     in klangSpec (u f) (u a) (u p)
@@ -86,9 +86,9 @@
 phasor :: Rate -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
 phasor r t f s e p = mkOsc r "Phasor" [t, f, s, e, p] 1
 
--- | Pulse wave generator (band limited).
+-- | Band limited pulse wave.
 pulse :: Rate -> UGen -> UGen -> UGen
-pulse r freq width = mkOscR [AR] r "Pulse" [freq, width] 1
+pulse rate freq width = mkOscR [AR,KR] rate "Pulse" [freq,width] 1
 
 -- | Sawtooth oscillator (band limited).
 saw :: Rate -> UGen -> UGen
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
@@ -1,14 +1,15 @@
 --  | Unit Generator ('UGen'), and associated types and instances.
 module Sound.SC3.UGen.Type where
 
-import Data.Bits
-import Data.List
-import Data.Maybe
+import Data.Bits {- base -}
+import Data.List {- base -}
+import Data.Maybe {- base -}
+import System.Random {- random -}
+
 import Sound.SC3.UGen.Identifier
 import Sound.SC3.UGen.MCE
 import Sound.SC3.UGen.Operator
 import Sound.SC3.UGen.Rate
-import System.Random {- random -}
 
 -- * Basic types
 
@@ -20,13 +21,13 @@
 --
 -- > Constant 3 == Constant 3
 -- > (Constant 3 > Constant 1) == True
-data Constant = Constant {constantValue :: Double}
+data Constant = Constant {constantValue :: Float}
                 deriving (Eq,Ord,Show)
 
 -- | Control inputs.
 data Control = Control {controlOperatingRate :: Rate
                        ,controlName :: String
-                       ,controlDefault :: Double
+                       ,controlDefault :: Float
                        ,controlTriggered :: Bool}
                deriving (Eq,Show)
 
@@ -94,13 +95,13 @@
 checkInput :: UGen -> UGen
 checkInput u =
     if isSink u
-    then error ("checkInput: illegal input: " ++ show u)
+    then error ("checkInput: " ++ show u)
     else u
 
 -- * Accessors
 
 -- | Value of 'Constant_U' 'Constant'.
-u_constant :: UGen -> Double
+u_constant :: UGen -> Float
 u_constant u =
     case u of
       Constant_U (Constant n) -> n
@@ -109,14 +110,14 @@
 -- * Constructors
 
 -- | Constant value node constructor.
-constant :: (Real a) => a -> UGen
+constant :: Real n => n -> UGen
 constant = Constant_U . Constant . realToFrac
 
 -- | Multiple channel expansion node constructor.
 mce :: [UGen] -> UGen
 mce xs =
     case xs of
-      [] -> error "mce: empty list"
+      [] -> error "mce: []"
       [x] -> x
       _ -> MCE_U (MCE_Vector xs)
 
@@ -124,7 +125,7 @@
 mrg :: [UGen] -> UGen
 mrg u =
     case u of
-      [] -> error "mrg: null"
+      [] -> error "mrg: []"
       [x] -> x
       (x:xs) -> MRG_U (MRG x (mrg xs))
 
@@ -133,7 +134,7 @@
 proxy u n =
     case u of
       Primitive_U p -> Proxy_U (Proxy p n)
-      _ -> error "proxy"
+      _ -> error "proxy: not primitive"
 
 -- * MCE
 
@@ -162,7 +163,7 @@
     case u of
       MCE_U m -> length (mceProxies m)
       MRG_U (MRG x _) -> mceDegree x
-      _ -> error "mceDegree: illegal ugen"
+      _ -> error "mceDegree: not mce"
 
 -- | Extend UGen to specified degree.
 mceExtend :: Int -> UGen -> [UGen]
@@ -215,7 +216,7 @@
       _ -> error "proxify: illegal ugen"
 
 -- | Construct proxied and multiple channel expanded UGen.
-mkUGen :: Maybe ([Double] -> Double) -> [Rate] -> Maybe Rate ->
+mkUGen :: Maybe ([Float] -> Float) -> [Rate] -> Maybe Rate ->
           String -> [UGen] -> Int -> Special -> UGenId -> UGen
 mkUGen cf rs r nm i o s z =
     let f h = let r' = fromMaybe (maximum (map rateOf h)) r
@@ -234,12 +235,12 @@
 -- * Operators
 
 -- | Operator UGen constructor.
-mkOperator :: ([Double] -> Double) -> String -> [UGen] -> Int -> UGen
+mkOperator :: ([Float] -> Float) -> String -> [UGen] -> Int -> UGen
 mkOperator f c i s =
     mkUGen (Just f) all_rates Nothing c i 1 (Special s) NoId
 
 -- | Unary math constructor with constant optimization.
-mkUnaryOperator :: Unary -> (Double -> Double) -> UGen -> UGen
+mkUnaryOperator :: Unary -> (Float -> Float) -> UGen -> UGen
 mkUnaryOperator i f a =
     let g [x] = f x
         g _ = error "mkUnaryOperator: non unary input"
@@ -254,8 +255,8 @@
 -- > o - 0 == o && 0 - o /= o
 -- > o / 1 == o && 1 / o /= o
 -- > o ** 1 == o && o ** 2 /= o
-mkBinaryOperator_optimize :: Binary -> (Double -> Double -> Double) ->
-                             (Either Double Double -> Bool) ->
+mkBinaryOperator_optimize :: Binary -> (Float -> Float -> Float) ->
+                             (Either Float Float -> Bool) ->
                              UGen -> UGen -> UGen
 mkBinaryOperator_optimize i f o a b =
    let g [x,y] = f x y
@@ -269,7 +270,7 @@
    in fromMaybe (mkOperator g "BinaryOpUGen" [a, b] (fromEnum i)) r
 
 -- | Binary math constructor with constant optimization.
-mkBinaryOperator :: Binary -> (Double -> Double -> Double) ->
+mkBinaryOperator :: Binary -> (Float -> Float -> Float) ->
                     UGen -> UGen -> UGen
 mkBinaryOperator i f a b =
    let g [x,y] = f x y
@@ -318,30 +319,36 @@
 -- | Unit generators are real.
 instance Real UGen where
     toRational (Constant_U (Constant n)) = toRational n
-    toRational _ = error "toRational at non-constant UGen"
+    toRational _ = error "UGen.toRational: non-constant"
 
 -- | Unit generators are integral.
 instance Integral UGen where
-    quot = mkBinaryOperator IDiv (error "ugen: quot")
-    rem = mkBinaryOperator Mod (error "ugen: rem")
+    quot = mkBinaryOperator IDiv (error "UGen.quot")
+    rem = mkBinaryOperator Mod (error "UGen.rem")
     quotRem a b = (quot a b, rem a b)
-    div = mkBinaryOperator IDiv (error "ugen: div")
-    mod = mkBinaryOperator Mod (error "ugen: mod")
+    div = mkBinaryOperator IDiv (error "UGen.div")
+    mod = mkBinaryOperator Mod (error "UGen.mod")
     toInteger (Constant_U (Constant n)) = floor n
-    toInteger _ = error "toInteger at non-constant UGen"
+    toInteger _ = error "UGen.toInteger: non-constant"
 
+instance RealFrac UGen where
+  properFraction = error "UGen.properFraction"
+  round = error "UGen.round"
+  ceiling = error "UGen.ceiling"
+  floor = error "UGen.floor"
+
 -- | Unit generators are orderable (when 'Constants').
 --
 -- > (constant 2 > constant 1) == True
 instance Ord UGen where
     (Constant_U a) < (Constant_U b) = a < b
-    _ < _ = error "< at UGen is partial, see <*"
+    _ < _ = error "UGen.<, see <*"
     (Constant_U a) <= (Constant_U b) = a <= b
-    _ <= _ = error "<= at UGen is partial, see <=*"
+    _ <= _ = error "UGen.<= at, see <=*"
     (Constant_U a) > (Constant_U b) = a > b
-    _ > _ = error "> at UGen is partial, see >*"
+    _ > _ = error "UGen.>, see >*"
     (Constant_U a) >= (Constant_U b) = a >= b
-    _ >= _ = error ">= at UGen is partial, see >=*"
+    _ >= _ = error "UGen.>=, see >=*"
     min = mkBinaryOperator Min min
     max = mkBinaryOperator Max max
 
@@ -351,7 +358,7 @@
     pred u = u - 1
     toEnum n = Constant_U (Constant (fromIntegral n))
     fromEnum (Constant_U (Constant n)) = truncate n
-    fromEnum _ = error "cannot enumerate non-constant UGens"
+    fromEnum _ = error "UGen.fromEnum: non-constant"
     enumFrom = iterate (+1)
     enumFromThen n m = iterate (+(m-n)) n
     enumFromTo n m = takeWhile (<= m+1/2) (enumFrom n)
@@ -364,7 +371,7 @@
     randomR (Constant_U (Constant l),Constant_U (Constant r)) g =
         let (n, g') = randomR (l,r) g
         in (Constant_U (Constant n), g')
-    randomR _ _ = error "randomR: non constant (l,r)"
+    randomR _ _ = error "UGen.randomR: non constant (l,r)"
     random = randomR (-1.0, 1.0)
 
 -- | UGens are bit patterns.
@@ -373,12 +380,12 @@
     (.|.) = mkBinaryOperator BitOr undefined
     xor = mkBinaryOperator BitXor undefined
     complement = mkUnaryOperator BitNot undefined
-    shift = error "Bits/UGen is partial"
-    rotate = error "Bits/UGen is partial"
-    bitSize = error "Bits/UGen is partial"
-    bit = error "Bits/UGen is partial"
-    testBit = error "Bits/UGen is partial"
-    popCount = error "Bits/UGen is partial"
+    shift = error "UGen.shift"
+    rotate = error "UGen.rotate"
+    bitSize = error "UGen.bitSize"
+    bit = error "UGen.bit"
+    testBit = error "UGen.testBit"
+    popCount = error "UGen.popCount"
     isSigned _ = True
 
 -- * UGen ID Instance
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
@@ -1,8 +1,9 @@
 -- | UGen data structure representation and associated functions.
 module Sound.SC3.UGen.UGen where
 
-import qualified Data.Char as C
-import Data.List
+import qualified Data.Char as C {- base -}
+import Data.List {- base -}
+
 import Sound.SC3.UGen.Identifier
 import Sound.SC3.UGen.Operator
 import Sound.SC3.UGen.Rate
@@ -53,21 +54,27 @@
 -- * Unit generator node constructors
 
 -- | Control input node constructor.
+control_f32 :: Rate -> String -> Float -> UGen
+control_f32 r nm d = Control_U (Control r nm d False)
+
+-- | Control input node constructor.
 --
---   Note that if the name begins with a t_ prefix the control is
---   not converted to a triggered control.  Please see tr_control.
+-- Note that if the name begins with a t_ prefix the control is /not/
+-- converted to a triggered control.  Please see tr_control.
 control :: Rate -> String -> Double -> UGen
-control r n d = Control_U (Control r n d False)
+control r nm = control_f32 r nm . realToFrac
 
 -- | Triggered (kr) control input node constructor.
+tr_control_f32 :: String -> Float -> UGen
+tr_control_f32 nm d = Control_U (Control KR nm d True)
+
+-- | Triggered (kr) control input node constructor.
 tr_control :: String -> Double -> UGen
-tr_control n d = Control_U (Control KR n d True)
+tr_control nm = tr_control_f32 nm . realToFrac
 
 -- | Multiple root graph node constructor.
 mrg2 :: UGen -> UGen -> UGen
 mrg2 u = MRG_U . MRG u
-
--- * Unit generator node predicates
 
 -- * Multiple channel expansion
 
diff --git a/Sound/SC3/UGen/UGen/Lift.hs b/Sound/SC3/UGen/UGen/Lift.hs
deleted file mode 100644
--- a/Sound/SC3/UGen/UGen/Lift.hs
+++ /dev/null
@@ -1,32 +0,0 @@
--- | Lifting functions from explicit identifier 'UGen' functions to
--- monadic 'UGen' constructors.
-module Sound.SC3.UGen.UGen.Lift where
-
-import Sound.SC3.UGen.Type
-import Sound.SC3.UGen.UId
-
--- | Lift base UGen to monadic form.
-liftU :: (UId m) => (Int -> a -> UGen) -> a -> m UGen
-liftU f a = do
-  n <- generateUId
-  return (f n a)
-
--- | Lift base UGen to monadic form.
-liftU2 :: (UId m) => (Int -> a -> b -> UGen) -> a -> b -> m UGen
-liftU2 f a b = do
-  n <- generateUId
-  return (f n a b)
-
--- | Lift base UGen to monadic form.
-liftU3 :: (UId m) => (Int -> a -> b -> c -> UGen) -> a -> b -> c -> m UGen
-liftU3 f a b c = do
-  n <- generateUId
-  return (f n a b c)
-
--- | Lift base UGen to monadic form.
-liftU4 :: (UId m) =>
-          (Int -> a -> b -> c -> d -> UGen) ->
-          a -> b -> c -> d -> m UGen
-liftU4 f a b c d = do
-  n <- generateUId
-  return (f n a b c d)
diff --git a/Sound/SC3/UGen/UId.hs b/Sound/SC3/UGen/UId.hs
--- a/Sound/SC3/UGen/UId.hs
+++ b/Sound/SC3/UGen/UId.hs
@@ -2,20 +2,58 @@
 -- non-sharable (demand) unit generators.
 module Sound.SC3.UGen.UId where
 
-import Control.Monad
+import Control.Applicative {- base -}
+import Control.Monad {- base -}
 import Control.Monad.IO.Class as M {- transformers -}
-import Control.Monad.Trans.Reader
-import Data.Unique
-import Sound.OSC.Transport.FD as T
+import Control.Monad.Trans.Reader {- transformers -}
+import Data.Unique {- base -}
+import Sound.OSC.Transport.FD as T {- hosc -}
 
 -- | A class indicating a monad that will generate a sequence of
 --   unique integer identifiers.
-class (Functor m,M.MonadIO m) => UId m where
+class (Functor m,Applicative m,M.MonadIO m) => UId m where
    generateUId :: m Int
    generateUId = fmap hashUnique (M.liftIO newUnique)
 
 instance UId IO where
     generateUId = liftM hashUnique newUnique
 
-instance (T.Transport t,Functor io,MonadIO io) => UId (ReaderT t io) where
+instance (T.Transport t,Functor io,Applicative io,MonadIO io) =>
+    UId (ReaderT t io) where
    generateUId = ReaderT (M.liftIO . const generateUId)
+
+-- | Unary function.
+type Fn1 a b = a -> b
+
+-- | Binary function.
+type Fn2 a b c = a -> b -> c
+
+-- | Ternary function.
+type Fn3 a b c d = a -> b -> c -> d
+
+-- | Quaternary function.
+type Fn4 a b c d e = a -> b -> c -> d -> e
+
+-- | Unary UId lift.
+liftUId :: UId m => (Int -> Fn1 a b) -> Fn1 a (m b)
+liftUId f a = do
+  n <- generateUId
+  return (f n a)
+
+-- | Binary UId lift.
+liftUId2 :: UId m => (Int -> Fn2 a b c) -> Fn2 a b (m c)
+liftUId2 f a b = do
+  n <- generateUId
+  return (f n a b)
+
+-- | Ternary UId lift.
+liftUId3 :: UId m => (Int -> Fn3 a b c d) -> Fn3 a b c (m d)
+liftUId3 f a b c = do
+  n <- generateUId
+  return (f n a b c)
+
+-- | Quaternary UId lift.
+liftUId4 :: UId m => (Int -> Fn4 a b c d e) -> Fn4 a b c d (m e)
+liftUId4 f a b c d = do
+  n <- generateUId
+  return (f n a b c d)
diff --git a/emacs/hsc3.el b/emacs/hsc3.el
--- a/emacs/hsc3.el
+++ b/emacs/hsc3.el
@@ -9,6 +9,7 @@
 (require 'thingatpt)
 (require 'find-lisp)
 (require 'inf-haskell)
+;;(require 'sclang)
 
 (defvar hsc3-help-directory
   nil
@@ -27,11 +28,11 @@
 
 (defun hsc3-unlit (s)
   "Remove bird literate marks and preceding comment marker"
-   (replace-regexp-in-string "^[- ]*>" "" s))
+   (replace-regexp-in-string "^[> ]* ?" "" s))
 
 (defun hsc3-uncomment (s)
   "Remove initial comment and Bird-literate markers if present"
-   (replace-regexp-in-string "^[- ]*>*" "" s))
+   (replace-regexp-in-string "^[- ]*[> ]*" "" s))
 
 (defun hsc3-remove-non-literates (s)
   "Remove non-bird literate lines"
@@ -121,26 +122,60 @@
 (defun hsc3-concat (l)
   (apply #'concat l))
 
-(defun hsc3-run-multiple-lines ()
-  "Send the current region to the interpreter as a single line."
-  (interactive)
+(defun hsc3-region-string ()
+  "Translate the current region into a single line (unlit, uncomment)."
   (let* ((s (region-string))
 	 (s* (if hsc3-literate-p
 		 (hsc3-unlit (hsc3-remove-non-literates s))
 	       (hsc3-concat (mapcar 'hsc3-uncomment (split-string s "\n"))))))
-    (hsc3-send-string (replace-regexp-in-string "\n" " " s*))))
+    (replace-regexp-in-string "\n" " " s*)))
 
+(defun hsc3-run-multiple-lines ()
+  "Send the current region to the haskell interpreter as a single line."
+  (interactive)
+  (hsc3-send-string (hsc3-region-string)))
+
+(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) t))
+
 (defun hsc3-run-consecutive-lines ()
   "Send the current region to the interpreter one line at a time."
   (interactive)
   (mapcar 'hsc3-send-string
           (mapcar 'hsc3-unlit (split-string (region-string) "\n"))))
 
+(defun hsc3-run-layout-block ()
+  "Variant of `hsc3-run-consecutive-lines' with ghci layout quoting."
+  (interactive)
+  (hsc3-send-string ":{")
+  (hsc3-run-consecutive-lines)
+  (hsc3-send-string ":}"))
+
 (defun hsc3-run-main ()
   "Run current main."
   (interactive)
   (hsc3-send-string "main"))
 
+(defun hsc3-wait ()
+  "Wait for prompt after sending command."
+  (interactive)
+  (inferior-haskell-wait-for-prompt (inferior-haskell-process)))
+
+(defun hsc3-id-rewrite-region ()
+  (interactive)
+  (shell-command-on-region
+   (region-beginning)
+   (region-end)
+   "hsc3-id-rewrite"
+   nil
+   t))
+
+(defun hsc3-id-rewrite ()
+  (interactive)
+  (shell-command-on-region (point-min) (point-max) "hsc3-id-rewrite" nil t))
+
 (defun hsc3-interrupt-haskell ()
   "Interrup haskell interpreter"
   (interactive)
@@ -189,6 +224,12 @@
   (hsc3-send-string
    (concat "Sound.SC3.UGen.Dot.draw " (thing-at-point 'symbol))))
 
+(defun hsc3-draw-graph-m ()
+  "Draw the UGen graph at point."
+  (interactive)
+  (hsc3-send-string
+   (concat "Sound.SC3.UGen.Dot.draw =<<" (thing-at-point 'symbol))))
+
 (defun hsc3-local-dot ()
   "Copy '/tmp/hsc3.dot' to 'buffer-name' .dot."
   (interactive)
@@ -223,9 +264,12 @@
   (define-key map [?\C-c ?>] 'hsc3-see-haskell)
   (define-key map [?\C-c ?\C-c] 'hsc3-run-line)
   (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 ?\C-h] 'hsc3-help)
   (define-key map [?\C-c ?\C-g] 'hsc3-draw-graph)
+  (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-i] 'hsc3-interrupt-haskell)
@@ -261,6 +305,8 @@
     '("Load buffer" . hsc3-load-buffer))
   (define-key map [menu-bar hsc3 expression run-main]
     '("Run main" . hsc3-run-main))
+  (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]
diff --git a/hsc3.cabal b/hsc3.cabal
--- a/hsc3.cabal
+++ b/hsc3.cabal
@@ -1,5 +1,5 @@
 Name:              hsc3
-Version:           0.13
+Version:           0.14
 Synopsis:          Haskell SuperCollider
 Description:       Haskell client for the SuperCollider synthesis server,
                    <http://audiosynth.com/>.
@@ -12,7 +12,7 @@
                    "Sound.SC3.UGen.Monad".
 License:           GPL
 Category:          Sound
-Copyright:         (c) Rohan Drape and others, 2006-2012
+Copyright:         (c) Rohan Drape and others, 2006-2013
 Author:            Rohan Drape
 Maintainer:        rd@slavepianos.org
 Stability:         Experimental
@@ -50,14 +50,15 @@
                    binary,
                    bytestring,
                    containers,
+                   data-default,
                    directory,
                    filepath,
-                   hosc == 0.13.*,
+                   hosc == 0.14.*,
                    murmur-hash,
                    network,
                    process,
                    random,
-                   split,
+                   split >= 0.2,
                    transformers
   GHC-Options:     -Wall -fwarn-tabs
   Exposed-modules: Sound.SC3
@@ -66,9 +67,14 @@
                    Sound.SC3.ID.FD
                    Sound.SC3.Monad
                    Sound.SC3.Monad.FD
+                   Sound.SC3.Monad.Syntax
                    Sound.SC3.Server
-                   Sound.SC3.Server.Command
                    Sound.SC3.Server.Command.Completion
+                   Sound.SC3.Server.Command.Core
+                   Sound.SC3.Server.Command.Double
+                   Sound.SC3.Server.Command.Float
+                   Sound.SC3.Server.Command.Int
+                   Sound.SC3.Server.Command.Generic
                    Sound.SC3.Server.Enum
                    Sound.SC3.Server.FD
                    Sound.SC3.Server.Help
@@ -106,6 +112,7 @@
                    Sound.SC3.UGen.FFT.ID
                    Sound.SC3.UGen.FFT.Monad
                    Sound.SC3.UGen.Filter
+                   Sound.SC3.UGen.Graph
                    Sound.SC3.UGen.Granular
                    Sound.SC3.UGen.Help
                    Sound.SC3.UGen.Identifier
@@ -127,7 +134,6 @@
                    Sound.SC3.UGen.Rate
                    Sound.SC3.UGen.Type
                    Sound.SC3.UGen.UGen
-                   Sound.SC3.UGen.UGen.Lift
                    Sound.SC3.UGen.UId
                    Sound.SC3.UGen.Wavelets
   Other-modules:   Sound.SC3.Server.Utilities
