diff --git a/Help/Server/s_newargs.help.lhs b/Help/Server/s_newargs.help.lhs
deleted file mode 100644
--- a/Help/Server/s_newargs.help.lhs
+++ /dev/null
@@ -1,32 +0,0 @@
-/s_newargs create a new synth
-
-string - synth definition name
-int    - synth ID
-int    - add action (0,1,2, 3 or 4 see below)
-int    - add target ID
-[
-  int|string - a control index or name
-  int        - number of sequential controls to change (M)
-  [
-    float - a control value
-  ] * M
-] * N
-
-Note: this command is inherently problematic when used with 
-graphs generated by hsc3 since, as a rule, it is not possible
-to fix the ordering of control variables.
-
-> import Sound.SC3
-
-> let { ks n is = let { js = (Nothing : map Just [1..])
->                     ; f (i,j) = control KR (maybe n ((n ++) . show) j) i }
->                 in mce (reverse (map f (zip is js)))
->     ; f = ks "f" [1,2,3,4]
->     ; g = out 0 (mix (sinOsc AR f 0 * 0.1))
->     ; fs = [440, 450, 600, 700]
->     ; a fd = do { async fd (d_recv (synthdef "g" g))
->                 ; send fd (s_newargs "g" (-1) AddToTail 1 [("f", fs)]) } }
-> in do { print g
->       ; withSC3 a }
-
-> s_newargs "g" (-1) AddToTail 1 [("f", [440, 450, 600, 700])]
diff --git a/Help/UGen/Analysis/amplitude.help.lhs b/Help/UGen/Analysis/amplitude.help.lhs
--- a/Help/UGen/Analysis/amplitude.help.lhs
+++ b/Help/UGen/Analysis/amplitude.help.lhs
@@ -1,18 +1,12 @@
-amplitude r i at rt
-
-    r - operating rate
-    i - input
-   at - attack time (0.01)
-   rt - release time (0.01)
-
-Amplitude follower. Tracks the peak amplitude of a signal.
+> Sound.SC3.UGen.Help.viewSC3Help "Amplitude"
+> Sound.SC3.UGen.DB.ugenSummary "Amplitude"
 
 > import Sound.SC3
 
-> let { s = in' 1 AR numOutputBuses
->     ; a = amplitude KR s 0.1 0.1 }
+> let {s = in' 1 AR numOutputBuses
+>     ;a = amplitude KR s 0.1 0.1}
 > in audition (out 0 (pulse AR 90 0.3 * a))
 
-> let { s = in' 1 AR numOutputBuses
->     ; f = amplitude KR s 0.1 0.1 * 1200 + 400 }
+> let {s = in' 1 AR numOutputBuses
+>     ;f = amplitude KR s 0.1 0.1 * 1200 + 400}
 > in audition (out 0 (sinOsc AR f 0 * 0.3))
diff --git a/Help/UGen/Analysis/compander.help.lhs b/Help/UGen/Analysis/compander.help.lhs
--- a/Help/UGen/Analysis/compander.help.lhs
+++ b/Help/UGen/Analysis/compander.help.lhs
@@ -1,77 +1,27 @@
-compander input control thresh slopeBelow slopeAbove clampTime relaxTime
-
-Compressor, expander, limiter, gate, ducker.  General purpose dynamics
-processor.
-
-input: The signal to be compressed / expanded / gated.
-
-control: The signal whose amplitude determines the gain applied to the
-         input signal. Often the same as in (for standard gating or
-         compression) but should be different for ducking.
-
-thresh: Control signal amplitude threshold, which determines the break
-        point between slopeBelow and slopeAbove. Usually 0..1. The
-        control signal amplitude is calculated using RMS.
-
-slopeBelow: Slope of the amplitude curve below the threshold. If this
-            slope > 1.0, the amplitude will drop off more quickly the
-            softer the control signal gets when the control signal is
-            close to 0 amplitude, the output should be exactly zero --
-            hence, noise gating. Values < 1.0 are possible, but it
-            means that a very low-level control signal will cause the
-            input signal to be amplified, which would raise the noise
-            floor.
-
-slopeAbove: Same thing, but above the threshold. Values < 1.0 achieve
-            compression (louder signals are attenuated) > 1.0, you get
-            expansion (louder signals are made even louder). For 3:1
-            compression, you would use a value of 1/3 here.
-
-clampTime: The amount of time it takes for the amplitude adjustment to
-           kick in fully. This is usually pretty small, not much more
-           than 10 milliseconds (the default value).
+> Sound.SC3.UGen.Help.viewSC3Help "Compander"
+> Sound.SC3.UGen.DB.ugenSummary "Compander"
 
-relaxTime: The amount of time for the amplitude adjustment to be
-           released. Usually a bit longer than clampTime if both times
-           are too short, you can get some (possibly unwanted)
-           artifacts.
+> import Sound.SC3
 
 Example signal to process.
-
-> import Sound.SC3
+> let z = let {e = decay2 (impulse AR 8 0 * lfSaw KR 0.3 0 * 0.3) 0.001 0.3
+>             ;p = mix (pulse AR (mce [80, 81]) 0.3)}
+>         in e * p
 
-> let { e = decay2 (impulse AR 8 0 * lfSaw KR 0.3 0 * 0.3) 0.001 0.3
->     ; p = mix (pulse AR (mce [80, 81]) 0.3) }
-> in audition (out 0 (e * p))
+> audition (out 0 z)
 
 Noise gate
-
-> let { e = decay2 (impulse AR 8 0 * lfSaw KR 0.3 0 * 0.3) 0.001 0.3
->     ; p = mix (pulse AR (mce [80, 81]) 0.3)
->     ; z = e * p
->     ; x = mouseX KR 0.01 1 Linear 0.1 }
+> let x = mouseX' KR 0.01 1 Linear 0.1
 > in audition (out 0 (mce [z, compander z z x 10 1 0.01 0.01]))
 
 Compressor
-
-> let { e = decay2 (impulse AR 8 0 * lfSaw KR 0.3 0 * 0.3) 0.001 0.3
->     ; p = mix (pulse AR (mce [80, 81]) 0.3)
->     ; z = e * p
->     ; x = mouseX KR 0.01 1 Linear 0.1 }
+> let x = mouseX' KR 0.01 1 Linear 0.1
 > in audition (out 0 (mce [z, compander z z x 1 0.5 0.01 0.01]))
 
 Limiter
-
-> let { e = decay2 (impulse AR 8 0 * lfSaw KR 0.3 0 * 0.3) 0.001 0.3
->     ; p = mix (pulse AR (mce [80, 81]) 0.3)
->     ; z = e * p
->     ; x = mouseX KR 0.01 1 Linear 0.1 }
+> let x = mouseX' KR 0.01 1 Linear 0.1
 > in audition (out 0 (mce [z, compander z z x 1 0.1 0.01 0.01]))
 
 Sustainer
-
-> let { e = decay2 (impulse AR 8 0 * lfSaw KR 0.3 0 * 0.3) 0.001 0.3
->     ; p = mix (pulse AR (mce [80, 81]) 0.3)
->     ; z = e * p
->     ; x = mouseX KR 0.01 1 Linear 0.1 }
+> let x = mouseX' KR 0.01 1 Linear 0.1
 > in audition (out 0 (mce [z, compander z z x 0.1 1.0 0.01 0.01]))
diff --git a/Help/UGen/Analysis/pitch.help.lhs b/Help/UGen/Analysis/pitch.help.lhs
--- a/Help/UGen/Analysis/pitch.help.lhs
+++ b/Help/UGen/Analysis/pitch.help.lhs
@@ -1,32 +1,16 @@
-pitch in initFreq minFreq maxFreq execFreq maxBinsPerOctave median
-      ampThreshold peakThreshold downSample
-
-Autocorrelation pitch follower
-
-This is a better pitch follower than ZeroCrossing, but more costly of
-CPU. For most purposes the default settings can be used and only in
-needs to be supplied. Pitch returns two values (via an Array of
-OutputProxys, see the OutputProxy help file), a freq which is the
-pitch estimate and hasFreq, which tells whether a pitch was
-found. Some vowels are still problematic, for instance a wide open
-mouth sound somewhere between a low pitched short 'a' sound as in
-'sat', and long 'i' sound as in 'fire', contains enough overtone
-energy to confuse the algorithm.
-
-Default values at sclang are: in = 0, initFreq = 440, minFreq = 60,
-maxFreq = 4000, execFreq = 100, maxBinsPerOctave = 16, median = 1,
-ampThreshold = 0.01, peakThreshold = 0.5, downSample = 1.
+> Sound.SC3.UGen.Help.viewSC3Help "Pitch"
+> Sound.SC3.UGen.DB.ugenSummary "Pitch"
 
 > import Sound.SC3
 
-> let { x = mouseX KR 220 660 Linear 0.1
->     ; y = mouseY KR 0.05 0.25 Linear 0.1
->     ; s = sinOsc AR x 0 * y
->     ; a = amplitude KR s 0.05 0.05
->     ; f = pitch s 440 60 4000 100 16 7 0.02 0.5 1 }
+> let {x = mouseX' KR 220 660 Linear 0.1
+>     ;y = mouseY' KR 0.05 0.25 Linear 0.1
+>     ;s = sinOsc AR x 0 * y
+>     ;a = amplitude KR s 0.05 0.05
+>     ;f = pitch s 440 60 4000 100 16 7 0.02 0.5 1}
 > in audition (out 0 (mce [s, sinOsc AR (mceChannel 0 f / 2) 0 * a]))
 
-> let { s = in' 1 AR numOutputBuses
->     ; a = amplitude KR s 0.1 0.1
->     ; f = pitch s 440 60 4000 100 16 7 0.02 0.5 1 }
+> let {s = in' 1 AR numOutputBuses
+>     ;a = amplitude KR s 0.1 0.1
+>     ;f = pitch s 440 60 4000 100 16 7 0.02 0.5 1}
 > in audition (out 0 (mce [s, sinOsc AR (mceChannel 0 f) 0 * a]))
diff --git a/Help/UGen/Analysis/runningSum.help.lhs b/Help/UGen/Analysis/runningSum.help.lhs
--- a/Help/UGen/Analysis/runningSum.help.lhs
+++ b/Help/UGen/Analysis/runningSum.help.lhs
@@ -1,11 +1,5 @@
-runningSum in numSamp
-
-A running sum over a user specified number of samples, useful for
-running RMS power windowing.
-
-in      - Input signal
-numsamp - How many samples to take the running sum over 
-          (initialisation rate)
+> Sound.SC3.UGen.Help.viewSC3Help "RunningSum"
+> Sound.SC3.UGen.DB.ugenSummary "RunningSum"
 
 > import Sound.SC3
 
diff --git a/Help/UGen/Analysis/slope.help.lhs b/Help/UGen/Analysis/slope.help.lhs
--- a/Help/UGen/Analysis/slope.help.lhs
+++ b/Help/UGen/Analysis/slope.help.lhs
@@ -1,21 +1,12 @@
-slope in
-
-Slope of signal.  Measures the rate of change per second of a
-signal.  Formula implemented is:
-
-out[i] = (in[i] - in[i-1]) * sampling_rate
-
-in - input signal to measure.
-
-In the example below a is quadratic noise, b first derivative line
-segments, and c second derivative constant segments.
+> Sound.SC3.UGen.Help.viewSC3Help "Slope"
+> Sound.SC3.UGen.DB.ugenSummary "Slope"
 
-> import Sound.SC3
+> import Sound.SC3.ID
 
-> do { a <- lfNoise2 KR 2
->    ; let { s = 1/2
->          ; b = slope a * s
->          ; c = slope b * squared s 
->          ; f = mce [a, b, c] * 220 + 220
->          ; o = sinOsc AR f 0 * (1/3) }
->      in audition (out 0 (mix o)) }
+> let {a = lfNoise2 'a' KR 2 {- quadratic noise -}
+>     ;s = 1/2
+>     ;b = slope a * s {- first derivative, line segments -}
+>     ;c = slope b * squared s {- second derivative, constant segments -}
+>     ;f = mce [a, b, c] * 220 + 220
+>     ;o = sinOsc AR f 0 * (1/3)}
+> in audition (out 0 (mix o))
diff --git a/Help/UGen/Analysis/zeroCrossing.help.lhs b/Help/UGen/Analysis/zeroCrossing.help.lhs
--- a/Help/UGen/Analysis/zeroCrossing.help.lhs
+++ b/Help/UGen/Analysis/zeroCrossing.help.lhs
@@ -1,13 +1,5 @@
-zeroCrossing in
-
-Zero crossing frequency follower.
-
-Outputs a frequency based upon the distance between interceptions of
-the X axis. The X intercepts are determined via linear interpolation
-so this gives better than just integer wavelength resolution. This is
-a very crude pitch follower, but can be useful in some situations.
-
-in - input signal.
+> Sound.SC3.UGen.Help.viewSC3Help "ZeroCrossing"
+> Sound.SC3.UGen.DB.ugenSummary "ZeroCrossing"
 
 > import Sound.SC3
 
diff --git a/Help/UGen/Buffer/bufAllpassC.help.lhs b/Help/UGen/Buffer/bufAllpassC.help.lhs
--- a/Help/UGen/Buffer/bufAllpassC.help.lhs
+++ b/Help/UGen/Buffer/bufAllpassC.help.lhs
@@ -1,28 +1,13 @@
-bufAllpassC buf in delayTime decayTime
-
-Buffer based all pass delay line with cubic interpolation
-
-All pass delay line with cubic interpolation which uses a buffer
-for its internal memory. See also BufAllpassN which uses no
-interpolation, and BufAllpassL which uses linear
-interpolation. Cubic interpolation is more computationally
-expensive than linear, but more accurate.
-
-See also AllpassC.
-
-buf       - buffer number.
-in        - the input signal.
-delaytime - delay time in seconds.
-decaytime - time for the echoes to decay by 60 decibels. If this
-            time is negative then the feedback coefficient will be
-            negative, thus emphasizing only odd harmonics at an
-            octave lower.
+> Sound.SC3.UGen.Help.viewSC3Help "BufAllpassC"
+> Sound.SC3.UGen.DB.ugenSummary "BufAllpassC"
 
-> import Sound.SC3.Monadic
+> import Sound.SC3.ID
 
+Allocate buffer
 > withSC3 (\fd -> async fd (b_alloc 0 44100 1))
 
-> do { d <- dust AR 1
->    ; n <- whiteNoise AR
->    ; let x = decay d 0.2 * n * 0.25
->      in audition (out 0 (bufAllpassC 0 x 0.25 6)) }
+Filtered decaying noise bursts
+> let {d = dust 'a' AR 1
+>     ;n = whiteNoise 'a' AR
+>     ;x = decay d 0.2 * n * 0.25}
+> in audition (out 0 (bufAllpassC 0 x 0.25 6))
diff --git a/Help/UGen/Buffer/bufAllpassL.help.lhs b/Help/UGen/Buffer/bufAllpassL.help.lhs
--- a/Help/UGen/Buffer/bufAllpassL.help.lhs
+++ b/Help/UGen/Buffer/bufAllpassL.help.lhs
@@ -1,1 +1,1 @@
-See bufAllpassC.
+See bufAllpassC
diff --git a/Help/UGen/Buffer/bufAllpassN.help.lhs b/Help/UGen/Buffer/bufAllpassN.help.lhs
--- a/Help/UGen/Buffer/bufAllpassN.help.lhs
+++ b/Help/UGen/Buffer/bufAllpassN.help.lhs
@@ -1,1 +1,1 @@
-See bufAllpassC.
+See bufAllpassC
diff --git a/Help/UGen/Buffer/bufChannels.help.lhs b/Help/UGen/Buffer/bufChannels.help.lhs
--- a/Help/UGen/Buffer/bufChannels.help.lhs
+++ b/Help/UGen/Buffer/bufChannels.help.lhs
@@ -1,5 +1,2 @@
-bufChannels bufnum
-
-Current number of channels of buffer.  Using at .ir is not the
-safest choice. Since a buffer can be reallocated at any time, using
-ir will not track the changes.
+> Sound.SC3.UGen.Help.viewSC3Help "BufChannels"
+> Sound.SC3.UGen.DB.ugenSummary "BufChannels"
diff --git a/Help/UGen/Buffer/bufCombC.help.lhs b/Help/UGen/Buffer/bufCombC.help.lhs
--- a/Help/UGen/Buffer/bufCombC.help.lhs
+++ b/Help/UGen/Buffer/bufCombC.help.lhs
@@ -1,26 +1,30 @@
-bufCombC buf in delayTime decayTime
+> Sound.SC3.UGen.Help.viewSC3Help "BufCombC"
+> Sound.SC3.UGen.DB.ugenSummary "BufCombC"
 
-Buffer based comb delay line with cubic interpolation
+> import Sound.SC3.ID
 
-All pass delay line with cubic interpolation which uses a buffer
-for its internal memory. See also BufCombN which uses no
-interpolation, and BufCombL which uses linear interpolation. Cubic
-interpolation is more computationally expensive than linear, but
-more accurate.  See also CombC.
+Allocate buffer zero (required for examples below)
+> withSC3 (\fd -> async fd (b_alloc 0 44100 1))
 
-buf       - buffer number.
-in        - the input signal.
-delaytime - delay time in seconds.
-decaytime - time for the echoes to decay by 60 decibels. If this
-            time is negative then the feedback coefficient will be
-            negative, thus emphasizing only odd harmonics at an
-            octave lower.
+Filtered decaying noise bursts
+> let {d = dust 'a' AR 1
+>     ;n = whiteNoise 'a' AR
+>     ;x = decay d 0.2 * n * 0.25}
+> in audition (out 0 (bufCombC 0 x 0.25 6))
 
-> import Sound.SC3.Monadic
+Comb filter as resonator. The resonant fundamental is equal to
+reciprocal of the delay time.
+> let {n = whiteNoise 'a' AR
+>     ;dt = xLine KR 0.0001 0.01 20 RemoveSynth}
+> in audition (out 0 (bufCombC 0 (n * 0.1) dt 0.2))
 
-> withSC3 (\fd -> async fd (b_alloc 0 44100 1))
+With negative feedback
+> let {n = whiteNoise 'a' AR
+>     ;dt = xLine KR 0.0001 0.01 20 RemoveSynth}
+> in audition (out 0 (bufCombC 0 (n * 0.1) dt (-0.2)))
 
-> do { d <- dust AR 1
->    ; n <- whiteNoise AR
->    ; let x = decay d 0.2 * n * 0.25
->      in audition (out 0 (bufCombC 0 x 0.25 6)) }
+Used as an echo.
+> let {d = dust 'a' AR 1
+>     ;n = whiteNoise 'a' AR
+>     ;i = decay (d * 0.5) 0.2 * n}
+> in audition (out 0 (bufCombC 0 i 0.2 3))
diff --git a/Help/UGen/Buffer/bufCombL.help.lhs b/Help/UGen/Buffer/bufCombL.help.lhs
--- a/Help/UGen/Buffer/bufCombL.help.lhs
+++ b/Help/UGen/Buffer/bufCombL.help.lhs
@@ -1,1 +1,1 @@
-See bufCombC.
+See bufCombC
diff --git a/Help/UGen/Buffer/bufCombN.help.lhs b/Help/UGen/Buffer/bufCombN.help.lhs
--- a/Help/UGen/Buffer/bufCombN.help.lhs
+++ b/Help/UGen/Buffer/bufCombN.help.lhs
@@ -1,1 +1,1 @@
-See bufCombC.
+See bufCombC
diff --git a/Help/UGen/Buffer/bufDelayC.help.lhs b/Help/UGen/Buffer/bufDelayC.help.lhs
--- a/Help/UGen/Buffer/bufDelayC.help.lhs
+++ b/Help/UGen/Buffer/bufDelayC.help.lhs
@@ -1,24 +1,21 @@
-bufDelayC buf in delayTime
-
-Buffer based simple delay line with cubic interpolation.
-
-Simple delay line with cubic interpolation which uses a buffer for
-its internal memory. See also BufDelayN which uses no
-interpolation, and BufDelayL which uses linear interpolation. Cubic
-interpolation is more computationally expensive than linear, but
-more accurate.
-
-See also DelayC.
-
-buf       - buffer number.
-in        - the input signal.
-delaytime - delay time in seconds.
+> Sound.SC3.UGen.Help.viewSC3Help "BufDelayC"
+> Sound.SC3.UGen.DB.ugenSummary "BufDelayC"
 
-> import Sound.SC3.Monadic
+> import Sound.SC3.ID
 
+Allocate buffer zero (required for examples below)
 > withSC3 (\fd -> async fd (b_alloc 0 44100 1))
 
-> do { d <- dust AR 1
->    ; n <- whiteNoise AR
->    ; let x = decay d 0.5 * n * 0.3
->      in audition (out 0 (bufDelayC 0 x 0.2 + x)) }
+Dust randomly triggers Decay to create an exponential decay envelope
+for the WhiteNoise input source.  The input is mixed with the delay.
+> let {t = dust 'a' AR 1
+>     ;n = whiteNoise 'a' AR
+>     ;d = decay t 0.5 * n * 0.3}
+> in audition (out 0 (bufDelayC 0 d 0.2 + d))
+
+Mouse control for delay time
+> let {t = dust 'a' AR 1
+>     ;n = whiteNoise 'b' AR
+>     ;d = decay t 0.3 * n
+>     ;x = mouseX' KR 0.0 0.2 Linear 0.1}
+> in audition (out 0 (d + bufDelayC 0 d x))
diff --git a/Help/UGen/Buffer/bufDelayL.help.lhs b/Help/UGen/Buffer/bufDelayL.help.lhs
--- a/Help/UGen/Buffer/bufDelayL.help.lhs
+++ b/Help/UGen/Buffer/bufDelayL.help.lhs
@@ -1,1 +1,1 @@
-See bufDelayC.
+See bufDelayC
diff --git a/Help/UGen/Buffer/bufDelayN.help.lhs b/Help/UGen/Buffer/bufDelayN.help.lhs
--- a/Help/UGen/Buffer/bufDelayN.help.lhs
+++ b/Help/UGen/Buffer/bufDelayN.help.lhs
@@ -1,1 +1,1 @@
-See bufDelayC.
+See bufDelayC
diff --git a/Help/UGen/Buffer/bufDur.help.lhs b/Help/UGen/Buffer/bufDur.help.lhs
--- a/Help/UGen/Buffer/bufDur.help.lhs
+++ b/Help/UGen/Buffer/bufDur.help.lhs
@@ -1,12 +1,13 @@
-bufDur rate bufnum
-
-Current duration of buffer (in seconds).
+> Sound.SC3.UGen.Help.viewSC3Help "BufDur"
+> Sound.SC3.UGen.DB.ugenSummary "BufDur"
 
 > import Sound.SC3
 
-> let fn = "/home/rohan/audio/metal.wav"
+Load sound file to buffer zero (required for examples)
+> let fn = "/home/rohan/data/audio/pf-c5.aif"
 > in withSC3 (\fd -> async fd (b_allocRead 0 fn 0 0))
 
-> let { t = impulse AR (recip (bufDur KR 0)) 0
->     ; p = sweep t (bufSampleRate KR 0) }
+Read without loop, trigger reset based on buffer duration
+> let {t = impulse AR (recip (bufDur KR 0)) 0
+>     ;p = sweep t (bufSampleRate KR 0)}
 > in audition (out 0 (bufRdL 1 AR 0 p NoLoop))
diff --git a/Help/UGen/Buffer/bufFrames.help.lhs b/Help/UGen/Buffer/bufFrames.help.lhs
--- a/Help/UGen/Buffer/bufFrames.help.lhs
+++ b/Help/UGen/Buffer/bufFrames.help.lhs
@@ -1,17 +1,17 @@
-bufFrames rate bufnum
-
-Current duration of buffer.
+> Sound.SC3.UGen.Help.viewSC3Help "BufFrames"
+> Sound.SC3.UGen.DB.ugenSummary "BufFrames"
 
 > import Sound.SC3
 
-> let fn = "/home/rohan/audio/metal.wav"
+Load sound file to buffer zero (required for examples)
+> let fn = "/home/rohan/data/audio/pf-c5.aif"
 > in withSC3 (\fd -> async fd (b_allocRead 0 fn 0 0))
 
+Read without loop, trigger reset based on buffer duration
 > let p = phasor AR 0 (bufRateScale KR 0) 0 (bufFrames KR 0) 0
 > in audition (out 0 (bufRdL 1 AR 0 p NoLoop))
 
-Mouse location drags play head.
-
-> let { r = mce [0.05, 0.075 .. 0.15]
->     ; p = k2A (mouseX KR 0 (bufFrames KR 0) Linear r) }
+Mouse location drags play head
+> let {r = mce [0.05,0.075 .. 0.15]
+>     ;p = k2A (mouseX' KR 0 (bufFrames KR 0) Linear r)}
 > in audition (out 0 (mix (bufRdL 1 AR 0 p NoLoop)))
diff --git a/Help/UGen/Buffer/bufRateScale.help.lhs b/Help/UGen/Buffer/bufRateScale.help.lhs
--- a/Help/UGen/Buffer/bufRateScale.help.lhs
+++ b/Help/UGen/Buffer/bufRateScale.help.lhs
@@ -1,13 +1,13 @@
-bufRateScale rate bufnum
-
-Buffer rate scaling in respect to server samplerate.  Returns a
-ratio by which the playback of a soundfile is to be scaled.
+> Sound.SC3.UGen.Help.viewSC3Help "BufRateScale"
+> Sound.SC3.UGen.DB.ugenSummary "BufRateScale"
 
-> import Sound.SC3.Monadic
+> import Sound.SC3.ID
 
-> let fn = "/home/rohan/audio/metal.wav"
+Load sound file to buffer zero (required for examples)
+> let fn = "/home/rohan/data/audio/pf-c5.aif"
 > in withSC3 (\fd -> async fd (b_allocRead 0 fn 0 0))
 
-> let { r = 1.25 * bufRateScale KR 0
->     ; p = phasor AR 0 r 0 (bufFrames KR 0) 0 }
+Read buffer at 3/4 reported sample rate.
+> let {r = 0.75 * bufRateScale KR 0
+>     ;p = phasor AR 0 r 0 (bufFrames KR 0) 0}
 > in audition (out 0 (bufRdL 1 AR 0 p NoLoop))
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
@@ -1,28 +1,17 @@
-bufRd numChannels rate bufnum phase loop interpolation
-
-Plays the content of a buffer.
-
-The number of channels must be a fixed integer. The architechture
-of the SynthDef cannot change after it is compiled. NOTE: if you
-supply a bufnum of a buffer that has a different numChannels then
-you have specified to the BufRd, it will fail silently.
-
-The interpolation value should be either NoInterpolation,
-LinearInterpolation, CubicInterpolation or (Interpolation UGen).
+> Sound.SC3.UGen.Help.viewSC3Help "BufRd"
+> Sound.SC3.UGen.DB.ugenSummary "BufRd"
 
-> import Sound.SC3
+> import Sound.SC3.ID
 
-> let fn = "/home/rohan/audio/metal.wav"
-> in withSC3 (\fd -> send fd (b_allocRead 0 fn 0 0))
+Load sound file to buffer zero (required for examples)
+> let fn = "/home/rohan/data/audio/pf-c5.aif"
+> in withSC3 (\fd -> async fd (b_allocRead 0 fn 0 0))
 
+Audio rate sine oscillator as phase input
 > let phase = (sinOsc AR 0.1 0 * bufFrames KR 0)
 > in audition (out 0 (bufRd 1 AR 0 phase Loop NoInterpolation))
 
-There are constructors, bufRdN, bufRdL, and bufRdC for the fixed
-cases.
-
-> import Sound.SC3.ID
-
-> let { x = mouseX KR (mce [5, 10]) 100 Linear 0.1
->     ; n = lfNoise1 'a' AR x }
+There are constructors, bufRd{N|L|C}, for the fixed cases.
+> let {x = mouseX' KR (mce [5, 10]) 100 Linear 0.1
+>     ;n = lfNoise1 'a' AR x}
 > in audition (out 0 (bufRdL 1 AR 0 (n * bufFrames KR 0) Loop))
diff --git a/Help/UGen/Buffer/bufSampleRate.help.lhs b/Help/UGen/Buffer/bufSampleRate.help.lhs
--- a/Help/UGen/Buffer/bufSampleRate.help.lhs
+++ b/Help/UGen/Buffer/bufSampleRate.help.lhs
@@ -1,14 +1,12 @@
-bufSampleRate rate bufnum
-
-Buffer sample rate.
+> Sound.SC3.UGen.Help.viewSC3Help "BufSampleRate"
+> Sound.SC3.UGen.DB.ugenSummary "BufSampleRate"
 
 > import Sound.SC3
 
-> let fn = "/home/rohan/audio/metal.wav"
+Load sound file to buffer zero (required for examples)
+> let fn = "/home/rohan/data/audio/pf-c5.aif"
 > in withSC3 (\fd -> async fd (b_allocRead 0 fn 0 0))
 
-Compare a sine tone derived from sample rate of a buffer with a
-440Hz tone.
-
+Sine tone derived from sample rate of buffer an 440Hz tone.
 > let f = mce [bufSampleRate KR 0 * 0.01, 440]
 > in audition (out 0 (sinOsc AR f 0 * 0.1))
diff --git a/Help/UGen/Buffer/detectIndex.help.lhs b/Help/UGen/Buffer/detectIndex.help.lhs
--- a/Help/UGen/Buffer/detectIndex.help.lhs
+++ b/Help/UGen/Buffer/detectIndex.help.lhs
@@ -1,22 +1,16 @@
-detectIndex bufnum in
-
-Search a table for a value and return the index where the value is
-located.
-
-Allocate and set values at buffer 10.
+> Sound.SC3.UGen.Help.viewSC3Help "DetectIndex"
+> Sound.SC3.UGen.DB.ugenSummary "DetectIndex"
 
 > import Sound.SC3
 
-> withSC3 (\fd -> do { async fd (b_alloc 10 6 1)
->                    ; send fd (b_setn 10 [(0, [2, 3, 4, 0, 1, 5])]) })
+Allocate and set values at buffer ten
+> withSC3 (\fd -> async fd (b_alloc_setn1 10 0 [2,3,4,0,1,5]))
 
 Find indexes and map to an audible frequency range.
-
-> let { n = 6
->     ; x = floorE (mouseX KR 0 n Linear 0.1)
->     ; i = detectIndex 10 x }
+> let {n = 6
+>     ;x = floorE (mouseX' KR 0 n Linear 0.1)
+>     ;i = detectIndex 10 x}
 > in audition (out 0 (sinOsc AR (linExp i 0 n 200 700) 0 * 0.1))
 
 Free buffer.
-
 > withSC3 (\fd -> send fd (b_free 10))
diff --git a/Help/UGen/Buffer/index.help.lhs b/Help/UGen/Buffer/index.help.lhs
--- a/Help/UGen/Buffer/index.help.lhs
+++ b/Help/UGen/Buffer/index.help.lhs
@@ -1,21 +1,14 @@
-index bufnum in
-
-Index into a table with a signal.  The input signal value is
-truncated to an integer value and used as an index into the table.
-Out of range index values are clipped to the valid range.
-
-Allocate and set values at buffer 10.
+> Sound.SC3.UGen.Help.viewSC3Help "Index"
+> Sound.SC3.UGen.DB.ugenSummary "Index"
 
 > import Sound.SC3
 
-> withSC3 (\fd -> do { async fd (b_alloc 10 6 1)
->                    ; send fd (b_setn 10 [(0, [50, 100, 200, 400, 800, 1600])]) })
-
-Index into the above buffer for frequency values.
+Allocate and set values at buffer ten
+> withSC3 (\fd -> async fd (b_alloc_setn1 10 0 [50,100,200,400,800,1600]))
 
+Index buffer for frequency values
 > let f = index 10 (lfSaw KR 2 3 * 4)
-> in audition (out 0 (sinOsc AR (mce [f, f * 9]) 0 * 0.1))
-
-Free buffer.
+> in audition (out 0 (sinOsc AR (mce [f,f * 9]) 0 * 0.1))
 
+Free buffer
 > withSC3 (\fd -> send fd (b_free 10))
diff --git a/Help/UGen/Buffer/indexInBetween.help.lhs b/Help/UGen/Buffer/indexInBetween.help.lhs
--- a/Help/UGen/Buffer/indexInBetween.help.lhs
+++ b/Help/UGen/Buffer/indexInBetween.help.lhs
@@ -1,23 +1,18 @@
-indexInBetween bufnum in
-
-Interpolating index search into a sorted table with a signal.
-
-Allocate and set values at buffer 10.
+> Sound.SC3.UGen.Help.viewSC3Help "IndexInBetween"
+> Sound.SC3.UGen.DB.ugenSummary "IndexInBetween"
 
 > import Sound.SC3
 
-> withSC3 (\fd -> do { async fd (b_alloc 10 6 1)
->                    ; send fd (b_setn 10 [(0, [200, 210, 400, 430, 600, 800])]) })
-
-Index into the above buffer for frequency values.
-
-> let { f0 = mouseX KR 200 900 Linear 0.1
->     ; i = indexInBetween 10 f0
->     ; l0 = index 10 i
->     ; l1 = index 10 (i + 1)
->     ; f1 = linLin (frac i) 0 1 l0 l1 }
-> in audition (out 0 (sinOsc AR (mce [f0, f1]) 0 * 0.1))
+Allocate and set values at buffer ten
+> withSC3 (\fd -> async fd (b_alloc_setn1 10 0 [200,210,400,430,600,800]))
 
-Free buffer.
+Index into buffer for frequency values
+> let {f0 = mouseX' KR 200 900 Linear 0.1
+>     ;i = indexInBetween 10 f0
+>     ;l0 = index 10 i
+>     ;l1 = index 10 (i + 1)
+>     ;f1 = linLin (frac i) 0 1 l0 l1}
+> in audition (out 0 (sinOsc AR (mce [f0,f1]) 0 * 0.1))
 
+Free buffer
 > withSC3 (\fd -> send fd (b_free 10))
diff --git a/Help/UGen/Buffer/osc.help.lhs b/Help/UGen/Buffer/osc.help.lhs
--- a/Help/UGen/Buffer/osc.help.lhs
+++ b/Help/UGen/Buffer/osc.help.lhs
@@ -1,48 +1,29 @@
-osc rate bufnum freq phase
-
-Linear interpolating wavetable lookup oscillator with frequency and
-phase modulation inputs.
-
-This oscillator requires a buffer to be filled with a wavetable
-format signal.  This preprocesses the Signal into a form which can
-be used efficiently by the Oscillator.  The buffer size must be a
-power of 2.
-
-This can be acheived by creating a Buffer object and sending it one
-of the "b_gen" messages ( sine1, sine2, sine3 ) with the wavetable
-flag set to true.
-
-Note about wavetables: OscN requires the b_gen sine1 wavetable flag
-to be OFF.  Osc requires the b_gen sine1 wavetable flag to be ON.
+> Sound.SC3.UGen.Help.viewSC3Help "Osc"
+> Sound.SC3.UGen.DB.ugenSummary "Osc"
 
 > import Sound.SC3
 
-> withSC3 (\fd -> do { async fd (b_alloc 10 512 1)
->                    ; send fd (b_gen 10 "sine1" [1 + 2 + 4, 1, 1/2, 1/3, 1/4, 1/5]) })
+Allocate and generate wavetable buffer
+> withSC3 (\fd -> do {_ <- async fd (b_alloc 10 512 1)
+>                    ;send fd (b_gen 10 "sine1" [1+2+4,1,1/2,1/3,1/4,1/5])})
 
+Fixed frequency wavetable oscillator
 > audition (out 0 (osc AR 10 220 0 * 0.1))
 
-Modulate freq
-
+Modulate frequency
 > let f = xLine KR 2000 200 1 DoNothing
 > in audition (out 0 (osc AR 10 f 0 * 0.1))
 
-Modulate freq
-
+As frequency modulator
 > let f = osc AR 10 (xLine KR 1 1000 9 RemoveSynth) 0 * 200 + 800
 > in audition (out 0 (osc AR 10 f 0 * 0.1))
 
-Modulate phase
-
+As phase modulatulator
 > let p = osc AR 10 (xLine KR 20 8000 10 RemoveSynth) 0 * 2 * pi
 > in audition (out 0 (osc AR 10 800 p * 0.1))
 
-Change the buffer while its playing
-
+Fixed frequency wavetable oscillator
 > audition (out 0 (osc AR 10 220 0 * 0.1))
 
-> import System.Random
-
-> do { r <- getStdRandom (randomR (0.0,1.0))
->    ; let g = b_gen 10 "sine1" [1 + 2 + 4, 1, r, 1/4]
->      in withSC3 (\fd -> send fd g) }
+Change the wavetable while its playing
+> withSC3 (\fd -> send fd (b_gen 10 "sine1" [1+2+4,1,0.6,1/4]))
diff --git a/Help/UGen/Buffer/playBuf.help.lhs b/Help/UGen/Buffer/playBuf.help.lhs
--- a/Help/UGen/Buffer/playBuf.help.lhs
+++ b/Help/UGen/Buffer/playBuf.help.lhs
@@ -1,74 +1,40 @@
-playBuf numChannels bufnum rate trigger startPos loop doneAction
-
-Sample playback oscillator.  Plays back a memory resident sample.
-
-numChannels - number of channels that the buffer will be.  This
-              must be a fixed integer. The architechture of the
-              SynthDef cannot change after it is compiled.
-              Warning: if you supply a bufnum of a buffer that
-              has a different numChannels then you have specified
-              to the PlayBuf, it will fail silently.
-
-bufnum      - the index of the buffer to use
-
-rate        - 1.0 is the server's sample rate, 2.0 is one octave up, 0.5
-              is one octave down -1.0 is backwards normal rate
-              etc. Interpolation is cubic.  Note: If the buffer's
-              sample rate is different from the server's, you will
-              need to multiply the desired playback rate by (file's
-              rate / server's rate). The UGen BufRateScale.kr(bufnum)
-              returns this factor. See examples below. BufRateScale
-              should be used in virtually every case.
-
-trigger     - a trigger causes a jump to the startPos.  A trigger occurs
-              when a signal changes from <= 0 to > 0.
-
-startPos    - sample frame to start playback (k-rate).
-
-loop        - 1 means true, 0 means false.  This is modulate-able.
-
-Allocate buffer.
+> Sound.SC3.UGen.Help.viewSC3Help "PlayBuf"
+> Sound.SC3.UGen.DB.ugenSummary "PlayBuf"
 
 > import Sound.SC3
 
-> let fileName = "/home/rohan/audio/metal.wav"
-> in withSC3 (\fd -> async fd (b_allocRead 10 fileName 0 0))
+Load sound file to buffer zero (required for examples)
+> let fn = "/home/rohan/data/audio/pf-c5.aif"
+> in withSC3 (\fd -> async fd (b_allocRead 0 fn 0 0))
 
 Play once only.
-
-> let s = bufRateScale KR 10
-> in audition (out 0 (playBuf 1 10 s 1 0 NoLoop RemoveSynth))
+> let s = bufRateScale KR 0
+> in audition (out 0 (playBuf 1 AR 0 s 1 0 NoLoop RemoveSynth))
 
 Play in infinite loop.
-
-> let s = bufRateScale KR 10
-> in audition (out 0 (playBuf 1 10 s 1 0 Loop DoNothing))
+> let s = bufRateScale KR 0
+> in audition (out 0 (playBuf 1 AR 0 s 1 0 Loop DoNothing))
 
 Trigger playback at each pulse.
-
-> let { t = impulse KR 2 0
->     ; s = bufRateScale KR 10 }
-> in audition (out 0 (playBuf 1 10 s t 0 NoLoop DoNothing))
+> let {t = impulse KR 2 0
+>     ;s = bufRateScale KR 0}
+> in audition (out 0 (playBuf 1 AR 0 s t 0 NoLoop DoNothing))
 
 Trigger playback at each pulse (diminishing intervals).
-
-> let { f = xLine KR 0.1 100 10 RemoveSynth
->     ; t = impulse KR f 0 
->     ; s = bufRateScale KR 10 }
-> in audition (out 0 (playBuf 1 10 s t 0 NoLoop DoNothing))
+> let {f = xLine KR 0.1 100 10 RemoveSynth
+>     ;t = impulse KR f 0
+>     ;s = bufRateScale KR 0}
+> in audition (out 0 (playBuf 1 AR 0 s t 0 NoLoop DoNothing))
 
 Loop playback, accelerating pitch.
-
 > let r = xLine KR 0.1 100 60 RemoveSynth
-> in audition (out 0 (playBuf 1 10 r 1 0 Loop DoNothing))
+> in audition (out 0 (playBuf 1 AR 0 r 1 0 Loop DoNothing))
 
 Sine wave control of playback rate, negative rate plays backwards.
-
-> let { f = xLine KR 0.2 8 30 RemoveSynth
->     ; r = fSinOsc KR f 0 * 3 + 0.6
->     ; s = bufRateScale KR 10 * r }
-> in audition (out 0 (playBuf 1 10 s 1 0 Loop DoNothing))
+> let {f = xLine KR 0.2 8 30 RemoveSynth
+>     ;r = fSinOsc KR f 0 * 3 + 0.6
+>     ;s = bufRateScale KR 0 * r}
+> in audition (out 0 (playBuf 1 AR 0 s 1 0 Loop DoNothing))
 
 Release buffer.
-
-> withSC3 (\fd -> send fd (b_free 10))
+> withSC3 (\fd -> send fd (b_free 0))
diff --git a/Help/UGen/Buffer/recordBuf.help.lhs b/Help/UGen/Buffer/recordBuf.help.lhs
--- a/Help/UGen/Buffer/recordBuf.help.lhs
+++ b/Help/UGen/Buffer/recordBuf.help.lhs
@@ -1,1 +1,24 @@
-recordBuf bufnum offset reclevel prelevel run loop trigger doneAction inputs
+> Sound.SC3.UGen.Help.viewSC3Help "RecordBuf"
+> Sound.SC3.UGen.DB.ugenSummary "RecordBuf"
+
+# SC3
+reorders inputArray from last to first argument.
+
+> import Sound.SC3
+
+Allocate a buffer (assume SR of 48k)
+> withSC3 (\fd -> async fd (b_alloc 0 (48000 * 4) 1))
+
+Record for four seconds (until end of buffer)
+> let o = formant AR (xLine KR 400 1000 4 DoNothing) 2000 800 * 0.125
+> in audition (mrg2 (out 0 o)
+>                   (recordBuf AR 0 0 1 0 1 NoLoop 1 RemoveSynth o))
+
+Play it back
+> let p = playBuf 1 AR 0 1 1 0 NoLoop RemoveSynth
+> in audition (out 0 p)
+
+Mix second signal equally with existing signal
+> let o = formant AR (xLine KR 200 1000 4 DoNothing) 2000 800 * 0.125
+> in audition (mrg2 (out 0 o)
+>                   (recordBuf AR 0 0 0.5 0.5 1 NoLoop 1 RemoveSynth o))
diff --git a/Help/UGen/Buffer/vOsc.help.lhs b/Help/UGen/Buffer/vOsc.help.lhs
--- a/Help/UGen/Buffer/vOsc.help.lhs
+++ b/Help/UGen/Buffer/vOsc.help.lhs
@@ -1,51 +1,28 @@
-vOsc rate bufpos freq phase
-
-Variable wavetable oscillator.  A wavetable lookup oscillator which
-can be swept smoothly across wavetables. All the wavetables must be
-allocated to the same size. Fractional values of table will
-interpolate between two adjacent tables.
-
-This oscillator requires a buffer to be filled with a wavetable
-format signal.  This preprocesses the Signal into a form which can
-be used efficiently by the Oscillator.  The buffer size must be a
-power of 2.
-
-This can be acheived by creating a Buffer object and sending it one
-of the "b_gen" messages (sine1, sine2, sine3) with the wavetable
-flag set to true.
-
-This can also be acheived by creating a Signal object and sending
-it the 'asWavetable' message, saving it to disk, and having the
-server load it from there.
-
-Note about wavetables: VOsc requires the b_gen sine1 wavetable flag
-to be ON.
-
-Allocate and fill tables 0 to 7.
+> Sound.SC3.UGen.Help.viewSC3Help "VOsc"
+> Sound.SC3.UGen.DB.ugenSummary "VOsc"
 
 > import Sound.SC3
 
-> let { square a = a * a
->     ; harm i = let { n = square (i + 1)
->                    ; f j = square ((n - j) / n) }
+Allocate and fill tables 0 to 7.
+> let {square a = a * a
+>     ;harm i = let {n = square (i + 1)
+>                   ;f j = square ((n - j) / n)}
 >                in map f [0 .. n - 1]
->     ; setup fd i = do { i' <- return (fromIntegral i)
->                       ; async fd (b_alloc i 1024 1)
->                       ; send fd (b_gen i "sine1" (1 + 2 + 4 : harm i')) } }
+>     ;setup fd i = do {i' <- return (fromIntegral i)
+>                      ;_ <- async fd (b_alloc i 1024 1)
+>                      ;send fd (b_gen i "sine1" (1 + 2 + 4 : harm i'))}}
 > in withSC3 (\fd -> mapM_ (setup fd) [0 .. 7])
 
 Oscillator at buffers 0 through 7, mouse selects buffer.
-
-> let x = mouseX KR 0 7 Linear 0.1
+> let x = mouseX' KR 0 7 Linear 0.1
 > in audition (out 0 (vOsc AR x (mce [120, 121]) 0 * 0.3))
 
-Reallocate buffers while oscillator is running.
-
 > import Control.Monad
 > import System.Random
 
-> let { rrand l r = getStdRandom (randomR (l,r))
->     ; rrandl n l r = replicateM n (rrand l r)
->     ; resetTable fd i = do { h <- rrandl 12 0 1
->                            ; send fd (b_gen i "sine1" (1 + 2 + 4 : h)) } }
+Reallocate buffers while oscillator is running.
+> let {rrand l r = getStdRandom (randomR (l,r))
+>     ;rrandl n l r = replicateM n (rrand l r)
+>     ;resetTable fd i = do {h <- rrandl 12 0 1
+>                           ;send fd (b_gen i "sine1" (1 + 2 + 4 : h))}}
 > in withSC3 (\fd -> mapM_ (resetTable fd) [0 .. 7])
diff --git a/Help/UGen/Chaos/crackle.help.lhs b/Help/UGen/Chaos/crackle.help.lhs
--- a/Help/UGen/Chaos/crackle.help.lhs
+++ b/Help/UGen/Chaos/crackle.help.lhs
@@ -1,15 +1,8 @@
-crackle rate chaosParam
-
-A noise generator based on a chaotic function.  The parameter of
-the chaotic function has useful values from just below 1.0 to just
-above 2.0. Towards 2.0 the sound crackles.
-
-The equation implemented is: y0 = fabs(y1 * param - y2 - 0.05f)
+> Sound.SC3.UGen.Help.viewSC3Help "Crackle"
+> Sound.SC3.UGen.DB.ugenSummary "Crackle"
 
 > import Sound.SC3
-
 > audition (out 0 (crackle AR 1.95 * 0.2))
 
 Modulate chaos parameter
-
 > audition (out 0 (crackle AR (line KR 1.0 2.0 3 RemoveSynth) * 0.2))
diff --git a/Help/UGen/Chaos/cuspL.help.lhs b/Help/UGen/Chaos/cuspL.help.lhs
--- a/Help/UGen/Chaos/cuspL.help.lhs
+++ b/Help/UGen/Chaos/cuspL.help.lhs
@@ -1,31 +1,22 @@
-cuspN rate freq a b xi
-cuspL rate freq a b xi
-
-freq - iteration frequency in Hertz
-a, b - equation variables
-xi   - initial value of x
-
-Cusp map chaotic generator.  Non- and linear- interpolating sound
-generator based on the difference equation:
+> Sound.SC3.UGen.Help.viewSC3Help "CuspL"
+> Sound.SC3.UGen.DB.ugenSummary "CuspL"
 
-xn+1 = a - b*sqrt(|xn|)
+> import Sound.SC3
 
 Vary frequency
 
-> import Sound.SC3
-
-> let x = mouseX KR 20 sampleRate Linear 0.1
+> let x = mouseX' KR 20 sampleRate Linear 0.1
 > in audition (out 0 (cuspL AR x 1.0 1.99 0 * 0.3))
 
 Mouse-controlled parameters.
 
-> let { x = mouseX KR 0.9 1.1 Linear 0.1
->     ; y = mouseY KR 1.8 2.0 Linear 0.1 }
+> let {x = mouseX' KR 0.9 1.1 Linear 0.1
+>     ;y = mouseY' KR 1.8 2.0 Linear 0.1}
 > in audition (out 0 (cuspL AR (sampleRate / 4) x y 0 * 0.3))
 
 As frequency control.
 
-> let { x = mouseX KR 0.9 1.1 Linear 0.1
->     ; y = mouseY KR 1.8 2.0 Linear 0.1
->     ; n = cuspL AR 40 x y 0 * 0.3 }
+> let {x = mouseX' KR 0.9 1.1 Linear 0.1
+>     ;y = mouseY' KR 1.8 2.0 Linear 0.1
+>     ;n = cuspL AR 40 x y 0 * 0.3}
 > in audition (out 0 (sinOsc AR (n * 800 + 900) 0 * 0.4))
diff --git a/Help/UGen/Chaos/cuspN.help.lhs b/Help/UGen/Chaos/cuspN.help.lhs
--- a/Help/UGen/Chaos/cuspN.help.lhs
+++ b/Help/UGen/Chaos/cuspN.help.lhs
@@ -1,1 +1,1 @@
-See cuspL.
+See cuspL
diff --git a/Help/UGen/Chaos/fbSineC.help.lhs b/Help/UGen/Chaos/fbSineC.help.lhs
--- a/Help/UGen/Chaos/fbSineC.help.lhs
+++ b/Help/UGen/Chaos/fbSineC.help.lhs
@@ -1,54 +1,33 @@
-fbSineC rate freq im fb a c xi yi
-fbSineL rate freq im fb a c xi yi
-fbSineN rate freq im fb a c xi yi
-
-Feedback sine with chaotic phase indexing.
-
-freq - iteration frequency in Hz    - 22050
-im   - index multiplier amount      - 1
-fb   - feedback amount              - 0.1
-a    - phase multiplier amount      - 1.1
-c    - phase increment amount       - 0.5
-xi   - initial value of x           - 0.1
-yi   - initial value of y           - 0.1
-
-A cubic-interpolating sound generator based on the difference
-equations:
-	
-	xn+1 = sin(im*yn + fb*xn)
-	yn+1 = (ayn + c) % 2pi
-
-This uses a linear congruential function to drive the phase
-indexing of a sine wave.  For im = 1, fb = 0, and a = 1 a normal
-sinewave results.
+> Sound.SC3.UGen.Help.viewSC3Help "FBSineC"
+> Sound.SC3.UGen.DB.ugenSummary "FBSineC"
 
-sclang default values
+> import Sound.SC3.ID
 
-> import Sound.SC3
+SC3 default values.
 
 > let o = fbSineC AR (sampleRate / 4) 1 0.1 1.1 0.5 0.1 0.1 * 0.2
 > in audition (out 0 o)
 
 Increase feedback
 
-> let { fb = line KR 0.01 4 10 DoNothing
->     ; o = fbSineC AR sampleRate 1 fb 1.1 0.5 0.1 0.1 * 0.2 }
+> let {fb = line KR 0.01 4 10 DoNothing
+>     ;o = fbSineC AR sampleRate 1 fb 1.1 0.5 0.1 0.1 * 0.2}
 > in audition (out 0 o)
 
 Increase phase multiplier
 
-> let { a = line KR 1 2 10 DoNothing
->     ; o = fbSineC AR sampleRate 1 0 a 0.5 0.1 0.1 * 0.2 }
+> let {a = line KR 1 2 10 DoNothing
+>     ;o = fbSineC AR sampleRate 1 0 a 0.5 0.1 0.1 * 0.2}
 > in audition (out 0 o)
 
 Randomly modulate parameters
 
-> let { madd a m = return . (+ a) . (* m)
->     ; x = mouseX KR 1 12 Linear 0.1 
->     ; n = lfNoise2 KR x }
-> in do { n0 <- madd 1e4 1e4 =<< n
->       ; n1 <- madd 33 32 =<< n
->       ; n2 <- madd 0 0.5 =<< n
->       ; n3 <- madd 1.05 0.05 =<< n
->       ; n4 <- madd 0.3 0.3 =<< n
->       ; audition (out 0 (fbSineC AR n0 n1 n2 n3 n4 0.1 0.1 * 0.2)) }
+> let {madd a m = (+ a) . (* m)
+>     ;x = mouseX' KR 1 12 Linear 0.1
+>     ;n e = lfNoise2 e KR x
+>     ;n0 = madd 1e4 1e4 (n 'a')
+>     ;n1 = madd 33 32 (n 'b')
+>     ;n2 = madd 0 0.5 (n 'c')
+>     ;n3 = madd 1.05 0.05 (n 'd')
+>     ;n4 = madd 0.3 0.3 (n 'e')}
+> in audition (out 0 (fbSineC AR n0 n1 n2 n3 n4 0.1 0.1 * 0.2))
diff --git a/Help/UGen/Chaos/fbSineL.help.lhs b/Help/UGen/Chaos/fbSineL.help.lhs
--- a/Help/UGen/Chaos/fbSineL.help.lhs
+++ b/Help/UGen/Chaos/fbSineL.help.lhs
@@ -1,1 +1,1 @@
-See fbSineC.
+See fbSineC
diff --git a/Help/UGen/Chaos/fbSineN.help.lhs b/Help/UGen/Chaos/fbSineN.help.lhs
--- a/Help/UGen/Chaos/fbSineN.help.lhs
+++ b/Help/UGen/Chaos/fbSineN.help.lhs
@@ -1,1 +1,1 @@
-See fbSineC.
+See fbSineC
diff --git a/Help/UGen/Chaos/henonC.help.lhs b/Help/UGen/Chaos/henonC.help.lhs
--- a/Help/UGen/Chaos/henonC.help.lhs
+++ b/Help/UGen/Chaos/henonC.help.lhs
@@ -1,1 +1,1 @@
-See henonN.
+See henonN
diff --git a/Help/UGen/Chaos/henonL.help.lhs b/Help/UGen/Chaos/henonL.help.lhs
--- a/Help/UGen/Chaos/henonL.help.lhs
+++ b/Help/UGen/Chaos/henonL.help.lhs
@@ -1,1 +1,1 @@
-See henonN.
+See henonN
diff --git a/Help/UGen/Chaos/henonN.help.lhs b/Help/UGen/Chaos/henonN.help.lhs
--- a/Help/UGen/Chaos/henonN.help.lhs
+++ b/Help/UGen/Chaos/henonN.help.lhs
@@ -1,46 +1,29 @@
-henonN rate freq a b x0 x1
-henonL rate freq a b x0 x1
-henonC rate freq a b x0 x1
-
-Henon map chaotic generator.
-
-freq   - iteration frequency in Hertz   -- 22050
-a, b   - equation variables             -- 1.4, 0.3
-x0, x1 - initial and second values of x -- 0, 0
-
-A non-interpolating sound generator based on the difference
-equation:
-
-    xn + 2 = 1 - axn + 12 + bxn
-
-This equation was discovered by French astronomer Michel Henon
-while studying the orbits of stars in globular clusters.
+> Sound.SC3.UGen.Help.viewSC3Help "HenonN"
+> Sound.SC3.UGen.DB.ugenSummary "HenonN"
 
-With default initial parameters.
+> import Sound.SC3.ID
 
-> import Sound.SC3
+With SC3 default initial parameters.
 
-> let x = mouseX KR 20 sampleRate Linear 0.1
+> let x = mouseX' KR 20 sampleRate Linear 0.1
 > in audition (out 0 (henonN AR x 1.4 0.3 0 0 * 0.1))
 
 With mouse-control of parameters.
 
-> let { x = mouseX KR 1 1.4 Linear 0.1
->     ; y = mouseY KR 0 0.3 Linear 0.1 }
+> let {x = mouseX' KR 1 1.4 Linear 0.1
+>     ;y = mouseY' KR 0 0.3 Linear 0.1}
 > in audition (out 0 (henonN AR (sampleRate / 4) x y 0 0 * 0.1))
 
 With randomly modulated parameters.
 
-> import Sound.SC3.Monadic
-
-> do { n0 <- return . (+ 1.20) . (* 0.20) =<< lfNoise2 KR 1
->    ; n1 <- return . (+ 0.15) . (* 0.15) =<< lfNoise2 KR 1
->    ; audition (out 0 (henonN AR (sampleRate / 8) n0 n1 0 0 * 0.1)) }
+> let {n0 = lfNoise2 'a' KR 1 * 0.20 + 1.20
+>     ;n1 = lfNoise2 'a' KR 1 * 0.15 + 0.15}
+> in audition (out 0 (henonN AR (sampleRate / 8) n0 n1 0 0 * 0.1))
 
 As a frequency control.
 
-> let { x = mouseX KR 1 1.4 Linear 0.1
->     ; y = mouseY KR 0 0.3 Linear 0.1
->     ; f0 = 40 
->     ; f = henonN AR f0 x y 0 0 * 800 + 900 }
+> let {x = mouseX' KR 1 1.4 Linear 0.1
+>     ;y = mouseY' KR 0 0.3 Linear 0.1
+>     ;f0 = 40
+>     ;f = henonN AR f0 x y 0 0 * 800 + 900}
 > in audition (out 0 (sinOsc AR f 0 * 0.4))
diff --git a/Help/UGen/Chaos/latoocarfianC.help.lhs b/Help/UGen/Chaos/latoocarfianC.help.lhs
--- a/Help/UGen/Chaos/latoocarfianC.help.lhs
+++ b/Help/UGen/Chaos/latoocarfianC.help.lhs
@@ -1,42 +1,20 @@
-latoocarfianC rate freq a b c d xi yi
-latoocarfianL rate freq a b c d xi yi
-latoocarfianN rate freq a b c d xi yi
-
-This is a function given in Clifford Pickover's book Chaos In
-Wonderland, pg 26.  The function has four parameters a, b, c, and
-d.  The function is:
-
-  xnew = sin(y * b) + c * sin(x * b)
-  ynew = sin(x * a) + d * sin(y * a)
-  x = xnew
-  y = ynew
-  output = x
-
-According to Pickover, parameters a and b should be in the range
-from -3 to +3, and parameters c and d should be in the range from
-0.5 to 1.5.  The function can, depending on the parameters given,
-give continuous chaotic output, converge to a single value
-(silence) or oscillate in a cycle (tone).  This UGen is
-experimental and not optimized currently, so is rather hoggish of
-CPU.
+> Sound.SC3.UGen.Help.viewSC3Help "LatoocarfianC"
+> Sound.SC3.UGen.DB.ugenSummary "LatoocarfianC"
 
-sclang default initial parameters.
+> import Sound.SC3.ID
 
-> import Sound.SC3
+SC3 default initial parameters.
 
-> let x = mouseX KR 20 sampleRate Linear 0.1
+> let x = mouseX' KR 20 sampleRate Linear 0.1
 > in audition (out 0 (latoocarfianC AR x 1 3 0.5 0.5 0.5 0.5 * 0.2))
 
 Randomly modulate all parameters.
 
-> import Control.Monad
-> import Sound.SC3.Monadic
-
-> do { [n0, n1, n2, n3] <- replicateM 4 (lfNoise2 KR 5)
->    ; let { f = sampleRate / 4
->          ; a = n0 * 1.5 + 1.5
->          ; b = n1 * 1.5 + 1.5
->          ; c = n2 * 0.5 + 1.5
->          ; d = n3 * 0.5 + 1.5 
->          ; o = latoocarfianC AR f a b c d 0.5 0.5 * 0.2 }
->      in audition (out 0 o) }
+> let {[n0,n1,n2,n3] = map (\e -> lfNoise2 e KR 5) "abcd"
+>     ;f = sampleRate / 4
+>     ;a = n0 * 1.5 + 1.5
+>     ;b = n1 * 1.5 + 1.5
+>     ;c = n2 * 0.5 + 1.5
+>     ;d = n3 * 0.5 + 1.5
+>     ;o = latoocarfianC AR f a b c d 0.5 0.5 * 0.2}
+> in audition (out 0 o)
diff --git a/Help/UGen/Chaos/linCongC.help.lhs b/Help/UGen/Chaos/linCongC.help.lhs
--- a/Help/UGen/Chaos/linCongC.help.lhs
+++ b/Help/UGen/Chaos/linCongC.help.lhs
@@ -1,36 +1,18 @@
-linCongC rate freq a c m xi
-linCongL rate freq a c m xi
-linCongN rate freq a c m xi
-
-Linear congruential chaotic generator.
-
-freq - iteration frequency in Hertz
-a    - multiplier amount
-c    - increment amount
-m    - modulus amount
-xi   - initial value of x
-
-A cubic-interpolating sound generator based on the difference
-equation:
-
-	xn+1 = (axn + c) % m
-
-The output signal is automatically scaled to a range of [-1, 1].
-
+> Sound.SC3.UGen.Help.viewSC3Help "LinCongC"
+> Sound.SC3.UGen.DB.ugenSummary "LinCongC"
 
-Default initial parameters.
+> import Sound.SC3.ID
 
-> import Sound.SC3
+Default SC3 initial parameters.
 
-> let x = mouseX KR 20 sampleRate Linear 0.1
+> let x = mouseX' KR 20 sampleRate Linear 0.1
 > in audition (out 0 (linCongC AR x 1.1 0.13 1 0 * 0.2))
 
 Randomly modulate parameters.
 
-> import Sound.SC3.Monadic
-
-> do { [n0, n1, n2, m] <- mapM (lfNoise2 KR) [1.0, 0.1, 0.1, 0.1]
->    ; let { f = n0 * 1e4 + 1e4
->          ; a = n1 * 0.5 + 1.4
->          ; c = n2 * 0.1 + 0.1 }
->      in audition (out 0 (linCongC AR f a c m 0 * 0.2)) }
+> let {fr = [1,0.1,0.1,0.1]
+>     ;[n0,n1,n2,m] = map (\(i,j) -> lfNoise2 i KR j) (zip "abde" fr)
+>     ;f = n0 * 1e4 + 1e4
+>     ;a = n1 * 0.5 + 1.4
+>     ;c = n2 * 0.1 + 0.1}
+> in audition (out 0 (linCongC AR f a c m 0 * 0.2))
diff --git a/Help/UGen/Chaos/linCongL.help.lhs b/Help/UGen/Chaos/linCongL.help.lhs
--- a/Help/UGen/Chaos/linCongL.help.lhs
+++ b/Help/UGen/Chaos/linCongL.help.lhs
@@ -1,1 +1,1 @@
-See linCongC.
+See linCongC
diff --git a/Help/UGen/Chaos/linCongN.help.lhs b/Help/UGen/Chaos/linCongN.help.lhs
--- a/Help/UGen/Chaos/linCongN.help.lhs
+++ b/Help/UGen/Chaos/linCongN.help.lhs
@@ -1,1 +1,1 @@
-See linCongC.
+See linCongC
diff --git a/Help/UGen/Chaos/logistic.help.lhs b/Help/UGen/Chaos/logistic.help.lhs
--- a/Help/UGen/Chaos/logistic.help.lhs
+++ b/Help/UGen/Chaos/logistic.help.lhs
@@ -1,9 +1,15 @@
-logistic rate chaosParam freq
+> Sound.SC3.UGen.Help.viewSC3Help "Logistic"
+> Sound.SC3.UGen.DB.ugenSummary "Logistic"
 
-UNDOCUMENTED.
+> import Sound.SC3
 
-Implements the equation: y1 = param * y1 * (1.0 - y1)
+SC3 default parameters
+> audition (out 0 (logistic AR 3 1000 0.5))
 
-> import Sound.SC3
+Onset of chaos
+> audition (out 0 (logistic AR (line KR 3.55 3.6 5 DoNothing) 1000 0.01))
 
-> audition (out 0 (logistic AR 3.5699457 1000.0 0.01))
+Mouse control
+> let {x = mouseX' KR 3 3.99 Linear 0.1
+>     ;y = mouseY' KR 10 10000 Exponential 0.1}
+> in audition (out 0 (logistic AR x y 0.25 * 0.5))
diff --git a/Help/UGen/Chaos/lorenzL.help.lhs b/Help/UGen/Chaos/lorenzL.help.lhs
--- a/Help/UGen/Chaos/lorenzL.help.lhs
+++ b/Help/UGen/Chaos/lorenzL.help.lhs
@@ -1,45 +1,22 @@
-lorenzL rate freq s r b h xi yi zi
-
-freq    - iteration frequency in Hertz
-s, r, b - equation variables
-h       - integration time step
-xi      - initial value of x
-yi      - initial value of y
-zi      - initial value of z
-
-Lorenz chaotic generator.  A strange attractor discovered by Edward
-N. Lorenz while studying mathematical models of the atmosphere.
-The system is composed of three ordinary differential equations:
-
-x' = s(y - x)
-y' = x(r - z) - y
-z' = xy - bz
+> Sound.SC3.UGen.Help.viewSC3Help "LorenzL"
+> Sound.SC3.UGen.DB.ugenSummary "LorenzL"
 
-The time step amount h determines the rate at which the ODE is
-evaluated.  Higher values will increase the rate, but cause more
-instability.  A safe choice is the default amount of 0.05.
+> import Sound.SC3.ID
 
 Vary frequency
-
-> import Sound.SC3
-
-> let x = mouseX KR 20 sampleRate Linear 0.1
+> let x = mouseX' KR 20 sampleRate Linear 0.1
 > in audition (out 0 (lorenzL AR x 10 27 2.667 0.05 0.1 0 0 * 0.3))
 
 Randomly modulate params
-
-> import Sound.SC3.Monadic
-
-> let { madd a m = return . (+ a) . (* m)
->     ; n = lfNoise0 KR 1 }
-> in do { n0 <- madd 10 2 =<< n
->       ; n1 <- madd 38 20 =<< n
->       ; n2 <- madd 2 1.5 =<< n
->       ; let o = lorenzL AR sampleRate n0 n1 n2 0.05 0.1 0 0 * 0.2
->         in audition (out 0 o) }
+> let {madd a m = (+ a) . (* m)
+>     ;n e = lfNoise0 e KR 0.5
+>     ;n0 = madd 10 2 (n 'a')
+>     ;n1 = madd 38 20 (n 'b')
+>     ;n2 = madd 2 1.5 (n 'c')
+>     ;o = lorenzL AR sampleRate n0 n1 n2 0.05 0.1 0 0 * 0.2}
+> in audition (out 0 o)
 
 As frequency control
-
-> let { x = mouseX KR 1 200 Linear 0.1
->     ; n = lorenzL AR x 10 28 2.667 0.05 0.1 0 0 }
+> let {x = mouseX' KR 1 200 Linear 0.1
+>     ;n = lorenzL AR x 10 28 2.667 0.05 0.1 0 0}
 > in audition (out 0 (sinOsc AR (lag n 0.003 * 800 + 900) 0 * 0.4))
diff --git a/Help/UGen/Chaos/quadC.help.lhs b/Help/UGen/Chaos/quadC.help.lhs
--- a/Help/UGen/Chaos/quadC.help.lhs
+++ b/Help/UGen/Chaos/quadC.help.lhs
@@ -1,1 +1,1 @@
-See quadN.
+See quadN
diff --git a/Help/UGen/Chaos/quadL.help.lhs b/Help/UGen/Chaos/quadL.help.lhs
--- a/Help/UGen/Chaos/quadL.help.lhs
+++ b/Help/UGen/Chaos/quadL.help.lhs
@@ -1,1 +1,1 @@
-See quadN.
+See quadN
diff --git a/Help/UGen/Chaos/quadN.help.lhs b/Help/UGen/Chaos/quadN.help.lhs
--- a/Help/UGen/Chaos/quadN.help.lhs
+++ b/Help/UGen/Chaos/quadN.help.lhs
@@ -1,22 +1,13 @@
-quadN rate freq a b c xi
-quadL rate freq a b c xi
-quadC rate freq a b c xi
-
-freq    - iteration frequency in Hertz
-a, b, c - equation variables
-xi      - initial value of x
-
-General quadratic map chaotic generator.  Non-, linear- and cubic-
-interpolating sound generators based on the difference equation:
-xn+1 = axn2 + bxn + c
+> Sound.SC3.UGen.Help.viewSC3Help "QuadN"
+> Sound.SC3.UGen.DB.ugenSummary "QuadN"
 
 > import Sound.SC3
 
 > audition (out 0 (quadC AR 4000 1 (-1) (-0.75) 0 * 0.2))
 
-> let x = mouseX KR 3.5441 4 Linear 0.1
+> let x = mouseX' KR 3.5441 4 Linear 0.1
 > in audition (out 0 (quadC AR 4000 (negate x) x 0 0.1 * 0.4))
 
-> let { x = mouseX KR 3.5441 4 Linear 0.1
->     ; f = quadC AR 4 (negate x) x 0 0.1 * 800 + 900 }
+> let {x = mouseX' KR 3.5441 4 Linear 0.1
+>     ;f = quadC AR 4 (negate x) x 0 0.1 * 800 + 900}
 > in audition (out 0 (sinOsc AR f 0 * 0.4))
diff --git a/Help/UGen/Chaos/rossler.help.lhs b/Help/UGen/Chaos/rossler.help.lhs
--- a/Help/UGen/Chaos/rossler.help.lhs
+++ b/Help/UGen/Chaos/rossler.help.lhs
@@ -1,9 +0,0 @@
-rossler rate chaosParam dt
-
-The Rossler attractor is a well known chaotic function.  The
-chaosParam can be varied from 1.0 to 25.0 with a dt of 0.04.  Valid
-ranges for chaosParam vary depending on dt.
-
-> import Sound.SC3
-
-> audition (out 0 (rossler AR 4 0.08))
diff --git a/Help/UGen/Control/mrg2.help.lhs b/Help/UGen/Control/mrg2.help.lhs
--- a/Help/UGen/Control/mrg2.help.lhs
+++ b/Help/UGen/Control/mrg2.help.lhs
@@ -1,28 +1,24 @@
-mrg2 left right
-
-mrg2 defines a node indicating a multiple root graph.
+> :t mrg2
 
 > import Sound.SC3
 
-> let { l = out 0 (sinOsc AR 300 0 * 0.1)
->     ; r = out 1 (sinOsc AR 900 0 * 0.1) }
+mrg2 defines a node indicating a multiple root graph.
+> let {l = out 0 (sinOsc AR 300 0 * 0.1)
+>     ;r = out 1 (sinOsc AR 900 0 * 0.1)}
 > in audition (mrg2 l r)
 
 there is a leftmost rule, so that mrg nodes need not
 be terminal.
-
-> let { l = sinOsc AR 300 0 * 0.1
->     ; r = out 1 (sinOsc AR 900 0 * 0.1) }
+> let {l = sinOsc AR 300 0 * 0.1
+>     ;r = out 1 (sinOsc AR 900 0 * 0.1)}
 > in audition (out 0 (mrg2 l r))
 
 the leftmost node may be an mce node
-
-> let { l = sinOsc AR (mce2 300 400) 0 * 0.1
->     ; r = out 1 (sinOsc AR 900 0 * 0.1) }
+> let {l = sinOsc AR (mce2 300 400) 0 * 0.1
+>     ;r = out 1 (sinOsc AR 900 0 * 0.1)}
 > in audition (out 0 (mrg2 l r))
 
 the implementation is not thorough
-
-> let { l = sinOsc AR (mce2 300 400) 0 * 0.1
->     ; r = out 1 (sinOsc AR 900 0 * 0.1) }
+> let {l = sinOsc AR (mce2 300 400) 0 * 0.1
+>     ;r = out 1 (sinOsc AR 900 0 * 0.1)}
 > in audition (out 0 (mrg2 l r + mrg2 l r))
diff --git a/Help/UGen/Demand/dbrown.help.lhs b/Help/UGen/Demand/dbrown.help.lhs
--- a/Help/UGen/Demand/dbrown.help.lhs
+++ b/Help/UGen/Demand/dbrown.help.lhs
@@ -1,21 +1,10 @@
-dbrown  length lo hi step
-dibrown length lo hi step
-
-Demand rate brownian movement generators.
-
-lo              - minimum value
-hi              - maximum value
-step            - maximum step for each new value
-length          - number of values to create
-
-Dbrown returns numbers in the continuous range between lo and hi,
-Dibrown returns integer values.  The arguments can be a number or
-any other ugen.
+> Sound.SC3.UGen.Help.viewSC3Help "Dbrown"
+> Sound.SC3.UGen.DB.ugenSummary "Dbrown"
 
-> import Sound.SC3.Monadic
+> import Sound.SC3.ID
 
-> do { n <- dbrown dinf 0 15 1
->    ; let { x = mouseX KR 1 40 Exponential 0.1
->          ; t = impulse KR x 0
->          ; f = demand t 0 n * 30 + 340 }
->      in audition (out 0 (sinOsc AR f 0 * 0.1)) }
+> let {n = dbrown 'a' dinf 0 15 1
+>     ;x = mouseX' KR 1 40 Exponential 0.1
+>     ;t = impulse KR x 0
+>     ;f = demand t 0 n * 30 + 340}
+> in audition (out 0 (sinOsc AR f 0 * 0.1))
diff --git a/Help/UGen/Demand/dbufrd.help.lhs b/Help/UGen/Demand/dbufrd.help.lhs
--- a/Help/UGen/Demand/dbufrd.help.lhs
+++ b/Help/UGen/Demand/dbufrd.help.lhs
@@ -1,40 +1,36 @@
-dbufrd bufnum phase loop
-
-Buffer demand ugen.
-
-bufnum  - buffer number to read from
-phase   - index into the buffer (demand ugen or any other ugen)
-loop    - loop when phase exceeds number of frames in buffer
+> Sound.SC3.UGen.Help.viewSC3Help "Dbufrd"
+> Sound.SC3.UGen.DB.ugenSummary "Dbufrd"
 
-> import Sound.SC3.Monadic
+> import Sound.SC3.ID
 > import System.Random
 
-> let n = randomRs (200.0, 500.0) (mkStdGen 0)
-> in do { withSC3 (\fd -> do { async fd (b_alloc 10 24 1)
->                            ; send fd (b_setn 10 [(0, take 24 n)]) })
->       ; s <- dseq 3 (mce [0, 3, 5, 0, 3, 7, 0, 5, 9])
->       ; b <- dbrown 5 0 23 1
->       ; p <- dseq dinf (mce [s, b])
->       ; t <- dust KR 10
->       ; r <- dbufrd 10 p Loop
->       ; audition (out 0 (sinOsc AR (demand t 0 r) 0 * 0.1)) }
+setup pattern at buffer 10
+> let n = randomRs (200.0,500.0) (mkStdGen 0)
+> in withSC3 (\fd -> async fd (b_alloc_setn1 10 0 (take 24 n)))
 
-Buffer as a time pattern (requires buffer 10 as allocated above).
+pattern as frequency input
+> let {s = dseq 'a' 3 (mce [0,3,5,0,3,7,0,5,9])
+>     ;b = dbrown 'a' 5 0 23 1
+>     ;p = dseq 'a' dinf (mce [s,b])
+>     ;t = dust 'a' KR 10
+>     ;r = dbufrd 'a' 10 p Loop}
+> in audition (out 0 (sinOsc AR (demand t 0 r) 0 * 0.1))
 
-> let { i = randomRs (0, 2) (mkStdGen 0)
->     ; n = map ([1, 0.5, 0.25] !!) i }
-> in do { withSC3 (\fd -> do { async fd (b_alloc 11 24 1)
->                            ; send fd (b_setn 11 [(0, take 24 n)]) })
->       ; s <- dseq 3 (mce [0, 3, 5, 0, 3, 7, 0, 5, 9])
->       ; b <- dbrown 5 0 23 1
->       ; p <- dseq dinf (mce [s, b])
->       ; j <- dseries dinf 0 1
->       ; d <- dbufrd 11 j Loop
->       ; l <- dbufrd 10 p Loop
->       ; let f = duty KR (d * 0.5) 0 DoNothing l
->         in audition (out 0 (sinOsc AR f 0 * 0.1)) }
+setup time pattern
+> let {i = randomRs (0,2) (mkStdGen 0)
+>     ;n = map ([1,0.5,0.25] !!) i}
+> in withSC3 (\fd -> async fd (b_alloc_setn1 11 0 (take 24 n)))
 
-Free buffers
+requires buffers 10 and 11 as allocated above
+> let {s = dseq 'a' 3 (mce [0,3,5,0,3,7,0,5,9])
+>     ;b = dbrown 'a' 5 0 23 1
+>     ;p = dseq 'a' dinf (mce [s,b])
+>     ;j = dseries 'a' dinf 0 1
+>     ;d = dbufrd 'a' 11 j Loop
+>     ;l = dbufrd 'a' 10 p Loop
+>     ;f = duty KR (d * 0.5) 0 DoNothing l}
+> in audition (out 0 (sinOsc AR f 0 * 0.1))
 
-> withSC3 (\fd -> do { async fd (b_free 10)
->                    ; async fd (b_free 11) })
+free buffers
+> withSC3 (\fd -> do {async fd (b_free 10)
+>                    ;async fd (b_free 11)})
diff --git a/Help/UGen/Demand/dbufwr.help.lhs b/Help/UGen/Demand/dbufwr.help.lhs
--- a/Help/UGen/Demand/dbufwr.help.lhs
+++ b/Help/UGen/Demand/dbufwr.help.lhs
@@ -1,31 +1,23 @@
-dbufwr bufnum phase input loop
-
-Buffer demand ugen.  All inputs can be either 
-demand ugen or any other ugen.
-
-bufnum - buffer number to read from (single channel buffer)
-phase  - index into the buffer
-input  - single channel input
-loop   - when phase exceeds number of frames in buffer, 
-         loops when set to 1 (default :1)
+> Sound.SC3.UGen.Help.viewSC3Help "Dbufwr"
+> Sound.SC3.UGen.DB.ugenSummary "Dbufwr"
 
-> import Sound.SC3.Monadic
+> import Sound.SC3
+> import qualified Sound.SC3.Monadic as M
 
-> do { s1 <- dseries 30 0 3
->    ; s2 <- dseries 30 0 1
->    ; s3 <- dseries 16 1 1
->    ; s4 <- dwhite 8 1 16 
->    ; s5 <- dseq dinf (mce2 s3 s4)
->    ; wt <- dust KR 1                  {- write trigger -}
->    ; rp <- dseries dinf 0 1           {- read pointer -}
->    ; wp <- dseq dinf (mce2 s1 s2)     {- write pointer -}
->    ; r <- dbufrd 0 rp Loop            {- reader -}
->    ; w <- dbufwr 0 wp (s5 * 60) Loop  {- writer -}
->    ; let { d = demand wt 0 w
->          ; f = lag (demand (impulse KR 16 0) 0 r) 0.01
->          ; o = sinOsc AR (f * mce2 1 1.01) 0 * 0.1
->          ; g = mrg [d, out 0 o]
->          ; run fd = do { async fd (b_alloc 0 24 1)
->                        ; send fd (b_setn 0 [(0, (replicate 24 210))])
->                        ; play fd g } }
->      in withSC3 run }
+> do {s1 <- M.dseries 30 0 3
+>    ;s2 <- M.dseries 30 0 1
+>    ;s3 <- M.dseries 16 1 1
+>    ;s4 <- M.dwhite 8 1 16
+>    ;s5 <- M.dseq dinf (mce2 s3 s4)
+>    ;wt <- M.dust KR 1                  {- write trigger -}
+>    ;rp <- M.dseries dinf 0 1           {- read pointer -}
+>    ;wp <- M.dseq dinf (mce2 s1 s2)     {- write pointer -}
+>    ;r <- M.dbufrd 0 rp Loop            {- reader -}
+>    ;w <- M.dbufwr 0 wp (s5 * 60) Loop  {- writer -}
+>    ;let {d = demand wt 0 w
+>         ;f = lag (demand (impulse KR 16 0) 0 r) 0.01
+>         ;o = sinOsc AR (f * mce2 1 1.01) 0 * 0.1
+>         ;g = mrg [d, out 0 o]
+>         ;run fd = do {async fd (b_alloc_setn1 0 0 (replicate 24 210))
+>                      ;play fd g}}
+>     in withSC3 run}
diff --git a/Help/UGen/Demand/demand.help.lhs b/Help/UGen/Demand/demand.help.lhs
--- a/Help/UGen/Demand/demand.help.lhs
+++ b/Help/UGen/Demand/demand.help.lhs
@@ -1,31 +1,19 @@
-demand trig reset ugens
-
-Demand results from demand rate ugens.
-
-When there is a trigger at the trig input, a value is demanded from
-each ugen in the list and output. The unit generators in the list
-should be 'demand' rate.
-
-When there is a trigger at the reset input, the demand rate ugens
-in the list are reset.
-
-trig  - Trigger can be any signal. A trigger happens when
-        the signal changes from non-positive to positive.
-
-reset - Resets the list of ugens when triggered.
+> Sound.SC3.UGen.Help.viewSC3Help "Demand"
+> Sound.SC3.UGen.DB.ugenSummary "Demand"
 
-> import Sound.SC3.Monadic
+> import Sound.SC3.ID
+> import qualified Sound.SC3.Monadic as M
 
-> do { r <- dust KR 1
->    ; s <- dgeom dinf (midiCPS 72) (midiRatio 1)
->    ; let { t = impulse KR 10 0
->          ; f = demand t r s 
->          ; o = sinOsc AR (mce [f, f + 0.7]) 0 }
->      in audition (out 0 (max (cubed o) 0 * 0.1)) }
+> do {r <- M.dust KR 1
+>    ;s <- M.dgeom dinf (midiCPS 72) (midiRatio 1)
+>    ;let {t = impulse KR 10 0
+>         ;f = demand t r s
+>         ;o = sinOsc AR (mce [f,f + 0.7]) 0}
+>     in audition (out 0 (max (cubed o) 0 * 0.1))}
 
-> do { n <- diwhite dinf 60 72
->    ; let { t = impulse KR 10 0
->          ; s = midiCPS n
->          ; f = demand t 0 s
->          ; o = sinOsc AR (mce [f, f + 0.7]) 0 }
->      in audition (out 0 (cubed (cubed o) * 0.1)) }
+> let {n = diwhite 'a' dinf 60 72
+>     ;t = impulse KR 10 0
+>     ;s = midiCPS n
+>     ;f = demand t 0 s
+>     ;o = sinOsc AR (mce [f,f + 0.7]) 0}
+> in audition (out 0 (cubed (cubed o) * 0.1))
diff --git a/Help/UGen/Demand/demandEnvGen.help.lhs b/Help/UGen/Demand/demandEnvGen.help.lhs
--- a/Help/UGen/Demand/demandEnvGen.help.lhs
+++ b/Help/UGen/Demand/demandEnvGen.help.lhs
@@ -1,41 +1,23 @@
-demandEnvGen rate levels times shapes curves gate reset
-             levelScale levelOffset timeScale doneAction
-
-levels - a demand ugen or any other ugen
-
-times  - a demand ugen or any other ugen if one of these ends,
-         the doneAction is evaluated
-
-shapes - a demand ugen or any other ugen, the number given is
-         the shape number according to Env
-
-curves - a demand ugen or any other ugen, if shape is 5, this
-         is the curve factor some curves/shapes don't work if
-         the duration is too short. have to see how to improve
-         this. also some depend on the levels obviously, like
-         exponential cannot cross zero.
-
-gate   - if gate is x >= 1, the ugen runs, if gate is 0 > x > 1,
-         the ugen is released at the next level (doneAction), if
-         gate is x < 0, the ugen is sampled and held
+> Sound.SC3.UGen.Help.viewSC3Help "DemandEnvGen"
+> Sound.SC3.UGen.DB.ugenSummary "DemandEnvGen"
 
-reset  - if reset crosses from nonpositive to positive, the ugen
-         is reset at the next level, if it is > 1, it is reset
-         immediately.
+> import Sound.SC3.ID
+> import qualified Sound.SC3.Monadic as M
 
 Frequency ramp, exponential curve.
-
-> import Sound.SC3.Monadic
-
-> do { l <- dseq dinf (mce2 440 9600)
->    ; let { y = mouseY KR 0.01 3 Exponential 0.1
->          ; f = demandEnvGen AR l y 2 0 1 1 1 0 1 DoNothing }
->      in audition (out 0 (sinOsc AR f 0 * 0.1)) }
+> let {l = dseq 'a' dinf (mce2 440 9600)
+>     ;y = mouseY' KR 0.01 3 Exponential 0.1
+>     ;f = demandEnvGen AR l y 2 0 1 1 1 0 1 DoNothing}
+> in audition (out 0 (sinOsc AR f 0 * 0.1))
 
 Frequency envelope with random times.
+> do {l <- M.dseq dinf (mce [204, 400, 201, 502, 300, 200])
+>    ;t <- M.drand dinf (mce [1.01, 0.2, 0.1, 2.0])
+>    ;let {y = mouseY' KR 0.01 3 Exponential 0.1
+>         ;f = demandEnvGen AR l (t * y) 7 0 1 1 1 0 1 DoNothing}
+>     in audition (out 0 (sinOsc AR (f * mce2 1 1.01) 0 * 0.1))}
 
-> do { l <- dseq dinf (mce [204, 400, 201, 502, 300, 200])
->    ; t <- drand dinf (mce [1.01, 0.2, 0.1, 2.0])
->    ; let { y = mouseY KR 0.01 3 Exponential 0.1
->          ; f = demandEnvGen AR l (t * y) 7 0 1 1 1 0 1 DoNothing }
->      in audition (out 0 (sinOsc AR (f * mce2 1 1.01) 0 * 0.1)) }
+short sequence with doneAction, linear
+> let {s = dseq 'a' 1 (mce [1300,500,800,300,400])
+>     ;f = demandEnvGen KR s 2 1 0 1 1 1 0 1 RemoveSynth}
+> in audition (out 0 (sinOsc AR (f * mce2 1 1.01) 0 * 0.1))
diff --git a/Help/UGen/Demand/dgeom.help.lhs b/Help/UGen/Demand/dgeom.help.lhs
--- a/Help/UGen/Demand/dgeom.help.lhs
+++ b/Help/UGen/Demand/dgeom.help.lhs
@@ -1,17 +1,10 @@
-dgeom length start grow
-
-Demand rate geometric series ugen.
-
-start	- start value
-grow 	- value by which to grow ( x = x[-1] * grow )
-length	- number of values to create
-
-The arguments can be a number or any other ugen
+> Sound.SC3.UGen.Help.viewSC3Help "Dgeom"
+> Sound.SC3.UGen.DB.ugenSummary "Dgeom"
 
-> import Sound.SC3.Monadic
+> import Sound.SC3.ID
 
-> do { n <- dgeom 15 1 1.2
->    ; let { x = mouseX KR 1 40 Exponential 0.1
->          ; t = impulse KR x 0
->          ; f = demand t 0 n * 30 + 340 }
->      in audition (out 0 (sinOsc AR f 0 * 0.1)) }
+> let {n = dgeom 'a' 15 1 1.2
+>     ;x = mouseX' KR 1 40 Exponential 0.1
+>     ;t = impulse KR x 0
+>     ;f = demand t 0 n * 30 + 340}
+> in audition (out 0 (sinOsc AR f 0 * 0.1))
diff --git a/Help/UGen/Demand/dibrown.help.lhs b/Help/UGen/Demand/dibrown.help.lhs
--- a/Help/UGen/Demand/dibrown.help.lhs
+++ b/Help/UGen/Demand/dibrown.help.lhs
@@ -1,1 +1,4 @@
-See dbrown.
+> Sound.SC3.UGen.Help.viewSC3Help "Dibrown"
+> Sound.SC3.UGen.DB.ugenSummary "Dibrown"
+
+See dbrown
diff --git a/Help/UGen/Demand/diwhite.help.lhs b/Help/UGen/Demand/diwhite.help.lhs
--- a/Help/UGen/Demand/diwhite.help.lhs
+++ b/Help/UGen/Demand/diwhite.help.lhs
@@ -1,1 +1,4 @@
-See dwhite.
+> Sound.SC3.UGen.Help.viewSC3Help "Diwhite"
+> Sound.SC3.UGen.DB.ugenSummary "Diwhite"
+
+See dwhite
diff --git a/Help/UGen/Demand/drand.help.lhs b/Help/UGen/Demand/drand.help.lhs
--- a/Help/UGen/Demand/drand.help.lhs
+++ b/Help/UGen/Demand/drand.help.lhs
@@ -1,18 +1,10 @@
-drand  length array
-dxrand length array
-
-Demand rate random sequence generators.
-
-length	- number of values to return
-array	- array of values or other ugens
-
-Dxrand never plays the same value twice, whereas Drand chooses any
-value in the list.
+> Sound.SC3.UGen.Help.viewSC3Help "Drand"
+> Sound.SC3.UGen.DB.ugenSummary "Drand"
 
-> import Sound.SC3.Monadic
+> import Sound.SC3.ID
 
-> do { n <- drand dinf (mce [1, 3, 2, 7, 8])
->    ; let { x = mouseX KR 1 400 Exponential 0.1
->          ; t = impulse KR x 0
->          ; f = demand t 0 n * 30 + 340 }
->      in audition (out 0 (sinOsc AR f 0 * 0.1)) }
+> let {n = drand 'a' dinf (mce [1, 3, 2, 7, 8])
+>     ;x = mouseX' KR 1 400 Exponential 0.1
+>     ;t = impulse KR x 0
+>     ;f = demand t 0 n * 30 + 340}
+> in audition (out 0 (sinOsc AR f 0 * 0.1))
diff --git a/Help/UGen/Demand/dseq.help.lhs b/Help/UGen/Demand/dseq.help.lhs
--- a/Help/UGen/Demand/dseq.help.lhs
+++ b/Help/UGen/Demand/dseq.help.lhs
@@ -1,22 +1,25 @@
-dseq length array
-
-Demand rate sequence generator.
-
-array   - array of values or other ugens
-length  - number of repeats
+> Sound.SC3.UGen.Help.viewSC3Help "Dseq"
+> Sound.SC3.UGen.DB.ugenSummary "Dseq"
 
-> import Sound.SC3.Monadic
+> import Sound.SC3.ID
 
-> do { n <- dseq 3 (mce [1, 3, 2, 7, 8])
->    ; let { x = mouseX KR 1 40 Exponential 0.1
->          ; t = impulse KR x 0
->          ; f = demand t 0 n * 30 + 340 }
->      in audition (out 0 (sinOsc AR f 0 * 0.1)) }
+> let {n = dseq 'a' 3 (mce [1, 3, 2, 7, 8])
+>     ;x = mouseX' KR 1 40 Exponential 0.1
+>     ;t = impulse KR x 0
+>     ;f = demand t 0 n * 30 + 340}
+> in audition (out 0 (sinOsc AR f 0 * 0.1))
 
 At audio rate.
+> let {n = dseq 'a' dinf (mce [1,3,2,7,8,32,16,18,12,24])
+>     ;x = mouseX' KR 1 10000 Exponential 0.1
+>     ;t = impulse AR x 0
+>     ;f = demand t 0 n * 30 + 340}
+> in audition (out 0 (sinOsc AR f 0 * 0.1))
 
-> do { n <- dseq dinf (mce [1,3,2,7,8,32,16,18,12,24])
->    ; let { x = mouseX KR 1 10000 Exponential 0.1
->          ; t = impulse AR x 0
->          ; f = demand t 0 n * 30 + 340 }
->      in audition (out 0 (sinOsc AR f 0 * 0.1)) }
+The SC2 Sequencer UGen is somewhat like the sequ function below
+> let {sequ e s tr = demand tr 0 (dseq e dinf (mce s))
+>     ;t = lfPulse AR 6 0 0.5
+>     ;n0 = sequ 'a' [60,62,63,58,48,55] t
+>     ;n1 = sequ 'b' [63,60,48,62,55,58] t
+>     ;o = lfSaw AR (midiCPS (mce2 n0 n1)) 0 * 0.1}
+> in audition (out 0 o)
diff --git a/Help/UGen/Demand/dser.help.lhs b/Help/UGen/Demand/dser.help.lhs
--- a/Help/UGen/Demand/dser.help.lhs
+++ b/Help/UGen/Demand/dser.help.lhs
@@ -1,14 +1,10 @@
-dser length array
-
-Demand rate sequence generator.
-
-array  - array of values or other ugens
-length - number of values to return
+> Sound.SC3.UGen.Help.viewSC3Help "Dser"
+> Sound.SC3.UGen.DB.ugenSummary "Dser"
 
-> import Sound.SC3.Monadic
+> import Sound.SC3.ID
 
-> do { a <- dser 7 (mce [1, 3, 2, 7, 8])
->    ; let { x = mouseX KR 1 40 Exponential 0.1
->          ; t = impulse KR x 0
->          ; f = demand t 0 a * 30 + 340 }
->      in audition (out 0 (sinOsc AR f 0 * 0.1)) }
+> let {a = dser 'a' 7 (mce [1, 3, 2, 7, 8])
+>     ;x = mouseX' KR 1 40 Exponential 0.1
+>     ;t = impulse KR x 0
+>     ;f = demand t 0 a * 30 + 340}
+> in audition (out 0 (sinOsc AR f 0 * 0.1))
diff --git a/Help/UGen/Demand/dseries.help.lhs b/Help/UGen/Demand/dseries.help.lhs
--- a/Help/UGen/Demand/dseries.help.lhs
+++ b/Help/UGen/Demand/dseries.help.lhs
@@ -1,17 +1,10 @@
-dseries length start step
-
-Demand rate arithmetic series ugen.
-
-length  - number of values to create
-start   - start value
-step    - step value
-
-The arguments can be a number or any other ugen
+> Sound.SC3.UGen.Help.viewSC3Help "Dseries"
+> Sound.SC3.UGen.DB.ugenSummary "Dseries"
 
-> import Sound.SC3.Monadic
+> import Sound.SC3.ID
 
-> do { n <- dseries 15 0 1
->    ; let { x = mouseX KR 1 40 Exponential 0.1
->          ; t = impulse KR x 0
->          ; f = demand t 0 n * 30 + 340 }
->      in audition (out 0 (sinOsc AR f 0 * 0.1)) }
+> let {n = dseries 'a' 15 0 1
+>     ;x = mouseX' KR 1 40 Exponential 0.1
+>     ;t = impulse KR x 0
+>     ;f = demand t 0 n * 30 + 340}
+> in audition (out 0 (sinOsc AR f 0 * 0.1))
diff --git a/Help/UGen/Demand/dstutter.help.lhs b/Help/UGen/Demand/dstutter.help.lhs
--- a/Help/UGen/Demand/dstutter.help.lhs
+++ b/Help/UGen/Demand/dstutter.help.lhs
@@ -1,15 +1,11 @@
-dstutter n in
-
-Demand rate input replicator.
-
-n   - number of repeats (can be a demand ugen)
-in  - input ugen
+> Sound.SC3.UGen.Help.viewSC3Help "Dstutter"
+> Sound.SC3.UGen.DB.ugenSummary "Dstutter"
 
-> import Sound.SC3.Monadic
+> import Sound.SC3.ID
 
-> do { inp <- dseq dinf (mce [1, 2, 3])
->    ; nse <- diwhite dinf 2 8
->    ; rep <- dstutter nse inp
->    ; let { trg = impulse KR (mouseX KR 1 40 Exponential 0.2) 0
->          ; frq = demand trg 0 rep * 30 + 340 }
->      in audition (out 0 (sinOsc AR frq 0 * 0.1)) }
+> let {inp = dseq 'a' dinf (mce [1,2,3])
+>     ;nse = diwhite 'a' dinf 2 8
+>     ;rep = dstutter 'a' nse inp
+>     ;trg = impulse KR (mouseX' KR 1 40 Exponential 0.2) 0
+>     ;frq = demand trg 0 rep * 30 + 340}
+> in audition (out 0 (sinOsc AR frq 0 * 0.1))
diff --git a/Help/UGen/Demand/dswitch.help.lhs b/Help/UGen/Demand/dswitch.help.lhs
--- a/Help/UGen/Demand/dswitch.help.lhs
+++ b/Help/UGen/Demand/dswitch.help.lhs
@@ -1,34 +1,27 @@
-dswitch index array
-
-Demand rate generator for embedding different inputs
-
-array - array of values or other ugens
-index - which of the inputs to return
-
-In difference to dswitch1, dswitch embeds all items of 
-an input demand ugen first before looking up the next index.
+> Sound.SC3.UGen.Help.viewSC3Help "Dswitch"
+> Sound.SC3.UGen.DB.ugenSummary "Dswitch"
 
-> import Sound.SC3.Monadic
+> import Sound.SC3
+> import qualified Sound.SC3.Monadic as M
 
-> do { a0 <- dwhite 2 3 4
->    ; a1 <- dwhite 2 0 1
->    ; a2 <- dseq 2 (mce [1, 1, 1, 0])
->    ; i <- dseq 2 (mce [0, 1, 2, 1, 0])
->    ; d <- dswitch i (mce [a0, a1, a2])
->    ; let { t = impulse KR 4 0
->          ; f = demand t 0 d * 300 + 400
->          ; o = sinOsc AR f 0 * 0.1 }
->      in audition (out 0 o) }
+> do {a0 <- M.dwhite 2 3 4
+>    ;a1 <- M.dwhite 2 0 1
+>    ;a2 <- M.dseq 2 (mce [1,1,1,0])
+>    ;i <- M.dseq 2 (mce [0,1,2,1,0])
+>    ;d <- M.dswitch i (mce [a0,a1,a2])
+>    ;let {t = impulse KR 4 0
+>         ;f = demand t 0 d * 300 + 400
+>         ;o = sinOsc AR f 0 * 0.1}
+>      in audition (out 0 o)}
 
 compare with dswitch1
-
-> do { a0 <- dwhite 2 3 4
->    ; a1 <- dwhite 2 0 1
->    ; a2 <- dseq 2 (mce [1, 1, 1, 0])
->    ; i <- dseq 2 (mce [0, 1, 2, 1, 0])
->    ; d <- dswitch1 i (mce [a0, a1, a2])
->    ; let { t = impulse KR 4 0
->          ; f = demand t 0 d * 300 + 400
->          ; o = sinOsc AR f 0 * 0.1 }
->      in audition (out 0 o) }
+> do {a0 <- M.dwhite 2 3 4
+>    ;a1 <- M.dwhite 2 0 1
+>    ;a2 <- M.dseq 2 (mce [1,1,1,0])
+>    ;i <- M.dseq 2 (mce [0,1,2,1,0])
+>    ;d <- M.dswitch1 i (mce [a0,a1,a2])
+>    ;let {t = impulse KR 4 0
+>         ;f = demand t 0 d * 300 + 400
+>         ;o = sinOsc AR f 0 * 0.1}
+>      in audition (out 0 o)}
 
diff --git a/Help/UGen/Demand/dswitch1.help.lhs b/Help/UGen/Demand/dswitch1.help.lhs
--- a/Help/UGen/Demand/dswitch1.help.lhs
+++ b/Help/UGen/Demand/dswitch1.help.lhs
@@ -1,16 +1,12 @@
-dswitch1 index array
-
-Demand rate generator for switching between inputs
-
-index	- which of the inputs to return
-array	- array of values or other ugens
+> Sound.SC3.UGen.Help.viewSC3Help "Dswitch1"
+> Sound.SC3.UGen.DB.ugenSummary "Dswitch1"
 
-> import Sound.SC3.Monadic
+> import Sound.SC3.ID
 
-> let { x = mouseX KR 0 4 Linear 0.1
->     ; y = mouseY KR 1 15 Linear 0.1
->     ; t = impulse KR 3 0 }
-> in do { w <- dwhite dinf 20 23
->       ; n <- dswitch1 x (mce [1, 3, y, 2, w])
->       ; let f = demand t 0 n * 30 + 340
->         in audition (out 0 (sinOsc AR f 0 * 0.1)) }
+> let {x = mouseX' KR 0 4 Linear 0.1
+>     ;y = mouseY' KR 1 15 Linear 0.1
+>     ;t = impulse KR 3 0
+>     ;w = dwhite 'a' dinf 20 23
+>     ;n = dswitch1 'a' x (mce [1, 3, y, 2, w])
+>     ;f = demand t 0 n * 30 + 340}
+> in audition (out 0 (sinOsc AR f 0 * 0.1))
diff --git a/Help/UGen/Demand/duty.help.lhs b/Help/UGen/Demand/duty.help.lhs
--- a/Help/UGen/Demand/duty.help.lhs
+++ b/Help/UGen/Demand/duty.help.lhs
@@ -1,35 +1,16 @@
-duty rate duration reset doneAction level
-
-Demand results from demand rate ugens
-
-A value is demanded from each ugen in the list and output according
-to a stream of duration values.  The unit generators in the list
-should be 'demand' rate.  When there is a trigger at the reset
-input, the demand rate ugens in the list and the duration are
-reset.  The reset input may also be a demand ugen, providing a
-stream of reset times.
-
-duration - time values. Can be a demand ugen or any signal.  The next
-value is acquired after the duration provided by the last time value.
-
-reset - trigger or reset time values. Resets the list of ugens and
-the duration ugen when triggered.  The reset input may also be a
-demand ugen, providing a stream of reset times.
-
-doneAction - action evaluated when the duration stream ends.
-
-level - demand ugen providing the output values.
+> Sound.SC3.UGen.Help.viewSC3Help "Duty"
+> Sound.SC3.UGen.DB.ugenSummary "Duty"
 
-> import Sound.SC3.Monadic
+> import Sound.SC3
+> import qualified Sound.SC3.Monadic as M
 
-> do { n0 <- drand dinf (mce [0.01, 0.2, 0.4])
->    ; n1 <- dseq dinf (mce [204, 400, 201, 502, 300, 200])
->    ; let f = duty KR n0 0 RemoveSynth n1
->      in audition (out 0 (sinOsc AR (f * mce2 1 1.01) 0 * 0.1)) }
+> do {n0 <- M.drand dinf (mce [0.01,0.2,0.4])
+>    ;n1 <- M.dseq dinf (mce [204,400,201,502,300,200])
+>    ;let f = duty KR n0 0 RemoveSynth n1
+>     in audition (out 0 (sinOsc AR (f * mce2 1 1.01) 0 * 0.1))}
 
 Using control rate signal, mouseX, to determine duration.
-
-> do { n <- dseq dinf (mce [204, 400, 201, 502, 300, 200])
->    ; let { x = mouseX KR 0.001 2 Linear 0.1
->          ; f = duty KR x 0 RemoveSynth n }
->      in audition (out 0 (sinOsc AR (f * mce2 1 1.01) 0 * 0.1)) }
+> let {n = dseq 'a' dinf (mce [204,400,201,502,300,200])
+>     ;x = mouseX' KR 0.001 2 Linear 0.1
+>     ;f = duty KR x 0 RemoveSynth n}
+> in audition (out 0 (sinOsc AR (f * mce2 1 1.01) 0 * 0.1))
diff --git a/Help/UGen/Demand/dwhite.help.lhs b/Help/UGen/Demand/dwhite.help.lhs
--- a/Help/UGen/Demand/dwhite.help.lhs
+++ b/Help/UGen/Demand/dwhite.help.lhs
@@ -1,20 +1,10 @@
-dwhite  length lo hi
-diwhite length lo hi
-
-Demand rate white noise random generators.
-
-length  - number of values to create
-lo      - minimum value
-hi      - maximum value
-
-Dwhite returns numbers in the continuous range between lo and hi,
-Diwhite returns integer values.  The arguments can be a number or
-any other ugen
+> Sound.SC3.UGen.Help.viewSC3Help "Dwhite"
+> Sound.SC3.UGen.DB.ugenSummary "Dwhite"
 
-> import Sound.SC3.Monadic
+> import Sound.SC3.ID
 
-> do { n <- dwhite dinf 0 15
->    ; let { x = mouseX KR 1 40 Exponential 0.1
->          ; t = impulse KR x 0
->          ; f = demand t 0 n * 30 + 340 }
->      in audition (out 0 (sinOsc AR f 0 * 0.1)) }
+> let {n = dwhite 'a' dinf 0 15
+>     ;x = mouseX' KR 1 40 Exponential 0.1
+>     ;t = impulse KR x 0
+>     ;f = demand t 0 n * 30 + 340}
+> in audition (out 0 (sinOsc AR f 0 * 0.1))
diff --git a/Help/UGen/Demand/dwrand.help.lhs b/Help/UGen/Demand/dwrand.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Demand/dwrand.help.lhs
@@ -0,0 +1,10 @@
+> Sound.SC3.UGen.Help.viewSC3Help "Dwrand"
+> Sound.SC3.UGen.DB.ugenSummary "Dwrand"
+
+> import Sound.SC3.ID
+
+> let {n = dwrand 'a' dinf (mce [1,3,2,7,8]) (mce [0.4,0.4,0.05,0.05,0.1])
+>     ;x = mouseX' KR 1 400 Exponential 0.1
+>     ;t = impulse KR x 0
+>     ;f = demand t 0 n * 30 + 340}
+> in audition (out 0 (sinOsc AR f 0 * 0.1))
diff --git a/Help/UGen/Demand/dxrand.help.lhs b/Help/UGen/Demand/dxrand.help.lhs
--- a/Help/UGen/Demand/dxrand.help.lhs
+++ b/Help/UGen/Demand/dxrand.help.lhs
@@ -1,1 +1,32 @@
-See drand.
+> Sound.SC3.UGen.Help.viewSC3Help "Dxrand"
+> Sound.SC3.UGen.DB.ugenSummary "Dxrand"
+
+> import Sound.SC3.ID
+
+Select to draw or not...
+> let drw = Sound.SC3.UGen.Dot.draw
+> let drw = const (return ()) :: UGen -> IO ()
+
+> let {i = mce [0.2,0.4,dseq 'a' 2 (mce [0.1,0.1])]
+>     ;d = dxrand 'b' dinf i
+>     ;t = tDuty AR d 0 DoNothing (dwhite 'c' dinf 0.5 1) 0}
+> in audition (out 0 t) >> drw t
+
+The list inputs to demand rate ugens may operate at different rates.
+The variants i' and i'' below ought to generate the same graph.  A
+simple-minded mce rule sets the rate of the operator primitive to the
+maximum rate of the inputs and then does not revise this after mce
+transformation, where it may be lower.  The hsc3 constructors attempt
+to get this right!
+> let {i = mce [0.2,0.4,dseq 'a' 2 (mce [0.1,0.1])]
+>     ;i' = mceMap (* 0.5) i
+>     ;i'' = i * 0.5
+>     ;d = dxrand 'c' dinf i''
+>     ;t = tDuty AR d 0 DoNothing (dwhite 'c' dinf 0.5 1) 0}
+> in audition (out 0 t) >> drw t
+
+> let {n = dxrand 'a' dinf (mce [1, 3, 2, 7, 8])
+>     ;x = mouseX' KR 1 400 Exponential 0.1
+>     ;t = impulse KR x 0
+>     ;f = demand t 0 n * 30 + 340}
+> in audition (out 0 (sinOsc AR f 0 * 0.1))
diff --git a/Help/UGen/Demand/tDuty.help.lhs b/Help/UGen/Demand/tDuty.help.lhs
--- a/Help/UGen/Demand/tDuty.help.lhs
+++ b/Help/UGen/Demand/tDuty.help.lhs
@@ -1,55 +1,26 @@
-tDuty rate duration reset doneAction level gap
-
-Demand results as trigger from demand rate ugens.
-
-A value is demanded each ugen in the list and output as a trigger
-according to a stream of duration values.  The unit generators in
-the list should be 'demand' rate.  When there is a trigger at the
-reset input, the demand rate ugens in the list and the duration are
-reset.  The reset input may also be a demand ugen, providing a
-stream of reset times.
-
-duration   - time values. Can be a demand ugen or any signal.
-             The next trigger value is acquired after the
-             duration provided by the last time value.
-
-reset      - trigger or reset time values. Resets the list of ugens
-             and the duration ugen when triggered. The reset input
-             may also be a demand ugen, providing a stream of reset
-             times.
-
-doneAction - a doneAction that is evaluated when the duration
-             stream ends.
-
-level      - demand ugen providing the output values.
+> Sound.SC3.UGen.Help.viewSC3Help "TDuty"
+> Sound.SC3.UGen.DB.ugenSummary "TDuty"
 
-gap - if true the dirst duration precedes the first level,
-      else it follows it.
+> import Sound.SC3.ID
 
 Play a little rhythm
-
-> import Sound.SC3.Monadic
-
-> do { d <- dseq dinf (mce [0.1, 0.2, 0.4, 0.3])
->    ; audition (out 0 (tDuty AR d 0 DoNothing 1 1)) }
+> let d = dseq 'a' dinf (mce [0.1, 0.2, 0.4, 0.3])
+> in audition (out 0 (tDuty AR d 0 DoNothing 1 0))
 
 Amplitude changes
-
-> do { d0 <- dseq dinf (mce [0.1, 0.2, 0.4, 0.3])
->    ; d1 <- dseq dinf (mce [0.1, 0.4, 0.01, 0.5, 1.0])
->    ; let s = ringz (tDuty AR d0 0 DoNothing d1 1) 1000 0.1
->      in audition (out 0 s) }
+> let {d0 = dseq '0' dinf (mce [0.1, 0.2, 0.4, 0.3])
+>     ;d1 = dseq '1' dinf (mce [0.1, 0.4, 0.01, 0.5, 1.0])
+>     ;s = ringz (tDuty AR d0 0 DoNothing d1 1) 1000 0.1}
+> in audition (out 0 s)
 
 Mouse control.
-
-> do { d <- dseq dinf (mce [0.1, 0.4, 0.01, 0.5, 1.0])
->    ; let { x = mouseX KR 0.003 1 Exponential 0.1
->          ; s = ringz (tDuty AR x 0 DoNothing d 1) 1000 0.1 }
->      in audition (out 0 s) }
+> let {d = dseq 'a' dinf (mce [0.1, 0.4, 0.01, 0.5, 1.0])
+>     ;x = mouseX' KR 0.003 1 Exponential 0.1
+>     ;s = ringz (tDuty AR x 0 DoNothing d 1) 1000 0.1 * 0.5}
+> in audition (out 0 s)
 
 Note that the 440 is the shorter pitch, since gap is set to false
-
-> do { d0 <- dser 12 (mce [0.1, 0.3])
->    ; d1 <- dser 12 (mce [440, 880])
->    ; let t = tDuty AR d0 0 RemoveSynth d1 0
->      in audition (out 0 (sinOsc AR (latch t t) 0 * 0.1)) }
+> let {d0 = dser '0' 12 (mce [0.1, 0.3])
+>     ;d1 = dser '1' 12 (mce [440, 880])
+>     ;t = tDuty AR d0 0 RemoveSynth d1 0}
+> in audition (out 0 (sinOsc AR (latch t t) 0 * 0.1))
diff --git a/Help/UGen/DiskIO/diskIn.help.lhs b/Help/UGen/DiskIO/diskIn.help.lhs
--- a/Help/UGen/DiskIO/diskIn.help.lhs
+++ b/Help/UGen/DiskIO/diskIn.help.lhs
@@ -1,23 +1,15 @@
-diskIn nc b l
-
-  nc - number of channels
-   b - buffer number
-   l - loop indicator
-
-Continously play a soundfile from disk. This requires a buffer to
-be preloaded with one buffer size of sound.  The buffer size must
-be a multiple of twice the synth block size. The default block size
-is 64.
+> Sound.SC3.UGen.Help.viewSC3Help "DiskIn"
+> Sound.SC3.UGen.DB.ugenSummary "DiskIn"
 
 > import Sound.SC3
 
-> let { f = "/home/rohan/audio/metal.wav"
->     ; n = 1
->     ; g = out 0 (diskIn n 0 Loop) }
-> in withSC3 (\fd -> do { async fd (b_alloc 0 8192 n)
->                       ; async fd (b_read 0 f 0 (-1) 0 1)
->                       ; play fd g })
+> let {f = "/home/rohan/data/audio/pf-c5.snd"
+>     ;n = 1
+>     ;g = out 0 (diskIn n 0 Loop)}
+> in withSC3 (\fd -> do {async fd (b_alloc 0 8192 n)
+>                       ;async fd (b_read 0 f 0 (-1) 0 True)
+>                       ;play fd g})
 
-> withSC3 (\fd -> do { reset fd
->                    ; async fd (b_close 0)
->                    ; async fd (b_free 0) })
+> withSC3 (\fd -> do {reset fd
+>                    ;async fd (b_close 0)
+>                    ;async fd (b_free 0)})
diff --git a/Help/UGen/DiskIO/vDiskIn.help.lhs b/Help/UGen/DiskIO/vDiskIn.help.lhs
--- a/Help/UGen/DiskIO/vDiskIn.help.lhs
+++ b/Help/UGen/DiskIO/vDiskIn.help.lhs
@@ -1,24 +1,16 @@
-vDiskIn nc b r l
-
-  nc - number of channels
-   b - buffer number
-   r - playback rate
-   l - loop indicator
-
-Continously play a soundfile from disk with variable playback
-rate. This requires a buffer to be preloaded with one buffer size of
-sound.  The buffer size must be a multiple of twice the synth block
-size. The default block size is 64.
+> Sound.SC3.UGen.Help.viewSC3Help "VDiskIn"
+> Sound.SC3.UGen.DB.ugenSummary "VDiskIn"
 
 > import Sound.SC3
 
-> let { f = "/home/rohan/audio/metal.wav"
->     ; n = 1
->     ; g = out 0 (vDiskIn n 0 (sinOsc KR 0.25 0 * 0.25 + 1) Loop) }
-> in withSC3 (\fd -> do { async fd (b_alloc 0 8192 n)
->                       ; async fd (b_read 0 f 0 (-1) 0 1)
->                       ; play fd g })
+> let {f = "/home/rohan/data/audio/pf-c5.snd"
+>     ;n = 1
+>     ;g = out 0 (vDiskIn n 0 (sinOsc KR 0.25 0 * 0.25 + 1) Loop)}
+> in withSC3 (\fd -> do {_ <- async fd (b_alloc 0 8192 n)
+>                       ;_ <- async fd (b_read 0 f 0 (-1) 0 True)
+>                       ;play fd g })
 
-> withSC3 (\fd -> do { reset fd
->                    ; async fd (b_close 0)
->                    ; async fd (b_free 0) })
+> withSC3 (\fd -> do {reset fd
+>                    ;_ <- async fd (b_close 0)
+>                    ;_ <- async fd (b_free 0)
+>                    ;return ()})
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
@@ -1,10 +1,8 @@
-detectSilence in amp time doneAction
-
-If the signal at `in' falls below `amp' for `time' seconds then
-`doneAction' is raised.
+> Sound.SC3.UGen.Help.viewSC3Help "DetectSilence"
+> Sound.SC3.UGen.DB.ugenSummary "DetectSilence"
 
 > 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 }
-> in audition (mrg [out 0 s, d])
+> let {s = sinOsc AR 440 0 * mouseY' KR 0 0.4 Linear 0.1
+>     ;d = detectSilence s 0.1 0.2 RemoveSynth}
+> in audition (mrg [out 0 s,d])
diff --git a/Help/UGen/Envelope/done.help.lhs b/Help/UGen/Envelope/done.help.lhs
--- a/Help/UGen/Envelope/done.help.lhs
+++ b/Help/UGen/Envelope/done.help.lhs
@@ -1,12 +1,10 @@
-done src
-
-Outputs a unit signal if the 'done' flag of the unit at `src' is
-set, else output zero.
+> Sound.SC3.UGen.Help.viewSC3Help "Done"
+> Sound.SC3.UGen.DB.ugenSummary "Done"
 
 > import Sound.SC3
 
-> let { x = mouseX KR (-1) 1 Linear 0.1
->     ; e = linen x 0.1 0.1 0.5 DoNothing 
->     ; o1 = sinOsc AR 880 0 * 0.1
->     ; o2 = sinOsc AR 440 0 * e }
-> in audition (out 0 (mce [ done e * o1, o2 ]))
+> let {x = mouseX' KR (-1) 1 Linear 0.1
+>     ;e = linen x 0.1 0.1 0.5 DoNothing
+>     ;o1 = sinOsc AR 880 0 * 0.1
+>     ;o2 = sinOsc AR 440 0 * e}
+> in audition (out 0 (mce [done e * o1,o2]))
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,20 +1,15 @@
-envADSR :: UGen->UGen->UGen->UGen->UGen->EnvCurve->UGen->[UGen]
-
-Attack, decay, sustain, release envelope.  Argumets are:
-
-    aT = attackTime (0.01)
-    dT = decayTime (0.3)
-    sL = sustainLevel (0.5)
-    rT = releaseTime (1)
-    pL = peakLevel (1)
-    c = curve (-4)
-    b = bias (0)
+> Sound.SC3.UGen.Help.viewSC3Help "Env.*adsr"
+> :t envADSR
 
 > import Sound.SC3
 
-> let { g = control KR "gate" 1
->     ; p = envADSR 0.01 0.3 0.5 1 1 (EnvNum (-4)) 0
->     ; e = envGen KR g 0.1 0 1 RemoveSynth p }
+> let {g = control KR "gate" 1
+>     ;p = envADSR 0.75 0.75 0.5 0.75 1 (EnvNum (-4)) 0
+>     ;e = envGen KR g 0.1 0 1 DoNothing p}
 > in audition (out 0 (sinOsc AR 440 0 * e))
 
 > withSC3 (\fd -> send fd (n_set1 (-1) "gate" 0))
+
+> withSC3 (\fd -> send fd (n_set1 (-1) "gate" 1))
+
+> withSC3 (\fd -> send fd (n_free [-1]))
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
@@ -1,17 +1,11 @@
-envASR :: UGen -> UGen -> UGen -> EnvCurve -> [UGen]
-
-Attack, sustain, release envelope.  Arguments are:
-
-    aT = attackTime (0.01)
-    sL = sustainLevel (1)
-    rT = releaseTime (1)
-    c = curve (-4)
+> Sound.SC3.UGen.Help.viewSC3Help "Env.*asr"
+> :t envASR
 
 > import Sound.SC3
 
-> let { g = control KR "gate" 1
->     ; p = envASR 0.01 1 1 (EnvNum (-4))
->     ; e = envGen KR g 0.1 0 1 RemoveSynth p }
+> let {g = control KR "gate" 1
+>     ;p = envASR 0.01 1 1 (EnvNum (-4))
+>     ;e = envGen KR g 0.1 0 1 RemoveSynth p}
 > in audition (out 0 (sinOsc AR 440 0 * e))
 
 > withSC3 (\fd -> send fd (n_set1 (-1) "gate" 0))
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
@@ -1,11 +1,11 @@
-envCoord :: [(UGen, UGen)] -> UGen -> UGen -> EnvCurve -> [UGen]
+> :t envCoord
 
 Co-ordinate (break-point) envelope
 
 > import Sound.SC3
 
-> let { c = EnvLin
->     ; p = envCoord [(0,0), (0.5, 0.1), (0.55, 1), (1, 0)] 9 0.1 c
->     ; e = envGen KR 1 1 0 1 RemoveSynth p }
+> let {c = EnvLin
+>     ;p = envCoord [(0,0),(0.5,0.1),(0.55,1),(1,0)] 9 0.1 c
+>     ;e = envGen KR 1 1 0 1 RemoveSynth p}
 > in audition (out 0 (sinOsc AR 440 0 * e))
 
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
@@ -1,32 +1,8 @@
-envGen rate gate levelScale levelBias timeScale doneAction envelope
-
-A segment based envelope generator.  Note that the SC3 language
-reorders the inputs to this UGen so that the envelope is the first
-argument.
-
-There are utilities for contructing the envelope argument.
-
-The arguments for levelScale, levelBias, and timeScale are polled
-when the EnvGen is triggered and remain constant for the duration
-of the envelope.
-
-envelope - an breakpoint set
-
-gate - this triggers the envelope and holds it open while > 0. If
-       the Env is fixed-length (e.g. Env.linen, Env.perc), the gate
-       argument is used as a simple trigger. If it is an sustaining
-       envelope (e.g. Env.adsr, Env.asr), the envelope is held open
-       until the gate becomes 0, at which point is released.
-
-levelScale - scales the levels of the breakpoints.
-
-levelBias - offsets the levels of the breakpoints.
-
-timeScale - scales the durations of the segments.
+> Sound.SC3.UGen.Help.viewSC3Help "EnvGen"
+> Sound.SC3.UGen.DB.ugenSummary "EnvGen"
 
-doneAction - an integer representing an action to be executed when
-             the env is finished playing. This can be used to free
-             the enclosing synth, etc.
+# SC3
+SC3 reorders inputs so that the envelope is the first argument.
 
 The following envelope constructors are provided: envPerc, envSine,
 envCoord, envTrapezoid, and envLinen.
diff --git a/Help/UGen/Envelope/envLinen.help.lhs b/Help/UGen/Envelope/envLinen.help.lhs
--- a/Help/UGen/Envelope/envLinen.help.lhs
+++ b/Help/UGen/Envelope/envLinen.help.lhs
@@ -1,9 +1,8 @@
-envLinen :: UGen -> UGen -> UGen -> UGen -> [UGen]
-
-Linear envelope parameter constructor.
+> Sound.SC3.UGen.Help.viewSC3Help "Env.*linen"
+> :t envLinen
 
 > import Sound.SC3
 
-> let { t = envLinen 0.4 2 0.4 0.1
->     ; e = envGen KR 1 1 0 1 RemoveSynth t }
+> let {t = envLinen 0.4 2 0.4 0.1
+>     ;e = envGen KR 1 1 0 1 RemoveSynth t}
 > in audition (out 0 (sinOsc AR 440 0 * e))
diff --git a/Help/UGen/Envelope/envPerc.help.lhs b/Help/UGen/Envelope/envPerc.help.lhs
--- a/Help/UGen/Envelope/envPerc.help.lhs
+++ b/Help/UGen/Envelope/envPerc.help.lhs
@@ -1,9 +1,15 @@
-envPerc :: UGen -> UGen -> [UGen]
-
-Percussive envelope
+> Sound.SC3.UGen.Help.viewSC3Help "Env.*perc"
+> :t envPerc'
 
 > import Sound.SC3
 
-> let { p = envPerc 0.01 1
->     ; e = envGen KR 1 0.1 0 1 RemoveSynth p }
+> let {a = 0.1
+>     ;p = envPerc 0.01 1
+>     ;e = envGen KR 1 a 0 1 RemoveSynth p }
+> in audition (out 0 (sinOsc AR 440 0 * e))
+
+> let {a = 0.1
+>     ;c = EnvNum (-4)
+>     ;p = envPerc' 0.01 1 a (c,c)
+>     ;e = envGen KR 1 1 0 1 RemoveSynth p }
 > in audition (out 0 (sinOsc AR 440 0 * e))
diff --git a/Help/UGen/Envelope/envSine.help.lhs b/Help/UGen/Envelope/envSine.help.lhs
--- a/Help/UGen/Envelope/envSine.help.lhs
+++ b/Help/UGen/Envelope/envSine.help.lhs
@@ -1,10 +1,9 @@
-envSine :: UGen -> UGen -> [UGen]
-
-Sine envelope
+> Sound.SC3.UGen.Help.viewSC3Help "Env.*sine"
+> :t envSine
 
 > import Sound.SC3
 
-> let { s = envSine 9 0.1
->     ; e = envGen KR 1 1 0 1 RemoveSynth s }
+> let {s = envSine 9 0.1
+>     ;e = envGen KR 1 1 0 1 RemoveSynth s}
 > in audition (out 0 (sinOsc AR 440 0 * e))
 
diff --git a/Help/UGen/Envelope/envTrapezoid.help.lhs b/Help/UGen/Envelope/envTrapezoid.help.lhs
--- a/Help/UGen/Envelope/envTrapezoid.help.lhs
+++ b/Help/UGen/Envelope/envTrapezoid.help.lhs
@@ -1,9 +1,10 @@
-envTrapezoid :: UGen -> UGen -> UGen -> UGen -> [UGen]
-
-Trapezoidal envelope data.
+> :t envTrapezoid
 
 > import Sound.SC3
 
 > let { t = envTrapezoid 0.05 0.95 3 0.1
 >     ; e = envGen KR 1 1 0 1 RemoveSynth t }
 > in audition (out 0 (sinOsc AR 440 0 * e))
+
+> let e = [0,3,-1,-1,0.1,0.5,1,0,0.1,0,1,0,0,1.5,1,0]
+> in envTrapezoid 0 0.25 2 0.1 == e
diff --git a/Help/UGen/Envelope/envTriangle.help.lhs b/Help/UGen/Envelope/envTriangle.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Envelope/envTriangle.help.lhs
@@ -0,0 +1,8 @@
+> Sound.SC3.UGen.Help.viewSC3Help "Env.*triangle"
+> :t envTriangle
+
+> import Sound.SC3
+
+> let {t = envTriangle 1 0.1
+>     ;e = envGen KR 1 1 0 1 RemoveSynth t}
+> in audition (out 0 (sinOsc AR 440 0 * e))
diff --git a/Help/UGen/Envelope/free.help.lhs b/Help/UGen/Envelope/free.help.lhs
--- a/Help/UGen/Envelope/free.help.lhs
+++ b/Help/UGen/Envelope/free.help.lhs
@@ -1,17 +1,13 @@
-free trig nodeID
-
-When triggered frees a node.
-
-trig   - when triggered, frees node
-nodeID - node to be freed
+> Sound.SC3.UGen.Help.viewSC3Help "Free"
+> Sound.SC3.UGen.DB.ugenSummary "Free"
 
-> import Sound.SC3.Monadic
+> import Sound.SC3.ID
 
-> let { a = out 0 (sinOsc AR 880 0 * 0.1) 
->     ; b = do { n0 <- pinkNoise AR
->              ; n1 <- dust AR 20
->              ; return (mrg [out 1 (n0 * 0.1), free n1 1001]) } }
-> in withSC3 (\fd -> do { async fd (d_recv (synthdef "a" a))
->                       ; async fd . d_recv . synthdef "b" =<< b
->                       ; send fd (s_new "a" 1001 AddToTail 0 [])
->                       ; send fd (s_new "b" (-1) AddToTail 0 []) } )
+> let {a = out 0 (sinOsc AR 880 0 * 0.1)
+>     ;n0 = pinkNoise 'a' AR
+>     ;n1 = dust 'b' AR 20
+>     ;b = mrg [out 1 (n0 * 0.1), free n1 1001]}
+> in withSC3 (\fd -> do {_ <- async fd (d_recv (synthdef "a" a))
+>                       ;_ <- async fd (d_recv (synthdef "b" b))
+>                       ;send fd (s_new "a" 1001 AddToTail 0 [])
+>                       ;send fd (s_new "b" (-1) AddToTail 0 [])})
diff --git a/Help/UGen/Envelope/freeSelf.help.lhs b/Help/UGen/Envelope/freeSelf.help.lhs
--- a/Help/UGen/Envelope/freeSelf.help.lhs
+++ b/Help/UGen/Envelope/freeSelf.help.lhs
@@ -1,11 +1,9 @@
-freeSelf src
-
-Free enclosing synth when the input signal crosses from non-positive
-to positive.
+> Sound.SC3.UGen.Help.viewSC3Help "FreeSelf"
+> Sound.SC3.UGen.DB.ugenSummary "FreeSelf"
 
-> import Sound.SC3.Monadic
+> import Sound.SC3.ID
 
-> do { n <- dust KR 0.5
->    ; let { a = freeSelf n
->          ; b = out 0 (sinOsc AR 440 0 * 0.1) }
->      in audition (mrg [a, b]) }
+> let {n = dust 'a' KR 0.5
+>     ;a = freeSelf n
+>     ;b = out 0 (sinOsc AR 440 0 * 0.1)}
+> in audition (mrg [a,b])
diff --git a/Help/UGen/Envelope/freeSelfWhenDone.help.lhs b/Help/UGen/Envelope/freeSelfWhenDone.help.lhs
--- a/Help/UGen/Envelope/freeSelfWhenDone.help.lhs
+++ b/Help/UGen/Envelope/freeSelfWhenDone.help.lhs
@@ -1,13 +1,14 @@
-freeSelfWhenDone src
-
-Free the synth when the 'done' flag of the unit at `src' is set.
+> Sound.SC3.UGen.Help.viewSC3Help "FreeSelfWhenDone"
+> Sound.SC3.UGen.DB.ugenSummary "FreeSelfWhenDone"
 
 > import Sound.SC3
 
-> let { x = mouseX KR (-1) 1 Linear 0.1
->     ; e = linen x 1 0.1 1 RemoveSynth }
+using RemoveSynth doneAction
+> let {x = mouseX' KR (-1) 1 Linear 0.1
+>     ;e = linen x 1 0.1 1 RemoveSynth}
 > in audition (out 0 (sinOsc AR 440 0 * e))
 
-> let { x = mouseX KR (-1) 1 Linear 0.1
->     ; e = linen x 1 0.1 1 DoNothing }
+using FreeSelfWhenDone UGen
+> let {x = mouseX' KR (-1) 1 Linear 0.1
+>     ;e = linen x 1 0.1 1 DoNothing}
 > in audition (mrg [freeSelfWhenDone e, out 0 (sinOsc AR 440 0 * e)])
diff --git a/Help/UGen/Envelope/line.help.lhs b/Help/UGen/Envelope/line.help.lhs
--- a/Help/UGen/Envelope/line.help.lhs
+++ b/Help/UGen/Envelope/line.help.lhs
@@ -1,13 +1,8 @@
-line rate start end dur doneAction
-
-Generates a line from the start value to the end value.
-
-start - starting value
-end   - ending value
-dur   - duration in seconds
+> Sound.SC3.UGen.Help.viewSC3Help "Line"
+> Sound.SC3.UGen.DB.ugenSummary "Line"
 
-Note: The SC3 UGen reorders the mul and add inputs to precede the
-doneAction input.
+#SC3
+SC3 reorders the mul and add inputs to precede the doneAction input.
 
 > import Sound.SC3
 
diff --git a/Help/UGen/Envelope/linen.help.lhs b/Help/UGen/Envelope/linen.help.lhs
--- a/Help/UGen/Envelope/linen.help.lhs
+++ b/Help/UGen/Envelope/linen.help.lhs
@@ -1,17 +1,12 @@
-linen gate attackTime susLevel releaseTime doneAction
-
-A linear envelope generator.  The done flag is set when the
-envelope reaches zero.
-
-Note that the sustain level input is consulted only at the instant
-when the gate is opened.
+> Sound.SC3.UGen.Help.viewSC3Help "Linen"
+> Sound.SC3.UGen.DB.ugenSummary "Linen"
 
 > import Sound.SC3
 
 > let e = linen (impulse KR 2 0) 0.01 0.6 0.4 DoNothing
 > in audition (out 0 (e * sinOsc AR 440 0 * 0.1))
 
-> let { x = mouseX KR (-1) 1 Linear 0.1
->     ; y = mouseY KR 0.1 0.5 Linear 0.1
->     ; e = linen x 1 y 1.0 DoNothing }
+> let {x = mouseX' KR (-1) 1 Linear 0.1
+>     ;y = mouseY' KR 0.1 0.5 Linear 0.1
+>     ;e = linen x 1 y 1.0 DoNothing}
 > in audition (out 0 (sinOsc AR 440 0 * e))
diff --git a/Help/UGen/Envelope/pause.help.lhs b/Help/UGen/Envelope/pause.help.lhs
--- a/Help/UGen/Envelope/pause.help.lhs
+++ b/Help/UGen/Envelope/pause.help.lhs
@@ -1,24 +1,18 @@
-pause gate nodeID
-
-When triggered pauses a node.
-
-gate   - when gate is 0,  node is paused, when 1 it runs
-nodeID - node to be paused
+> Sound.SC3.UGen.Help.viewSC3Help "Pause"
+> Sound.SC3.UGen.DB.ugenSummary "Pause"
 
 > import Sound.SC3
 
-> let { f  = control KR "f" 440
->     ; g  = control KR "g" 1
->     ; a  = mrg [out 0 (sinOsc AR f 0 * 0.1), pause g 1001]
->     ; a' = synthdef "a" a }
-> in withSC3 (\fd -> do { async fd (d_recv a')
->                       ; send fd (s_new "a" 1001 AddToTail 0 [])
->                       ; send fd (s_new "a" 1002 AddToTail 0 [("f", 880)]) } )
+> let {f = control KR "f" 440
+>     ;g = control KR "g" 1
+>     ;a = mrg [out 0 (sinOsc AR f 0 * 0.1),pause g 1001]
+>     ;a' = synthdef "a" a}
+> in withSC3 (\fd -> do {async fd (d_recv a')
+>                       ;send fd (s_new "a" 1001 AddToTail 0 [])
+>                       ;send fd (s_new "a" 1002 AddToTail 0 [("f",880)])})
 
 Request that node 1002 pause node 1001.
-
-> withSC3 (\fd -> send fd (n_set 1002 [("g", 0)]))
+> withSC3 (\fd -> send fd (n_set 1002 [("g",0)]))
 
 Restart node 1001.
-
-> withSC3 (\fd -> send fd (n_set 1002 [("g", 1)]))
+> withSC3 (\fd -> send fd (n_set 1002 [("g",1)]))
diff --git a/Help/UGen/Envelope/pauseSelf.help.lhs b/Help/UGen/Envelope/pauseSelf.help.lhs
--- a/Help/UGen/Envelope/pauseSelf.help.lhs
+++ b/Help/UGen/Envelope/pauseSelf.help.lhs
@@ -1,14 +1,11 @@
-pauseSelf src
-
-Pause enclosing synth when input signal crosses from non-positive to
-positive.
+> Sound.SC3.UGen.Help.viewSC3Help "PauseSelf"
+> Sound.SC3.UGen.DB.ugenSummary "PauseSelf"
 
 > import Sound.SC3
 
-> let { x = mouseX KR (-1) 1 Linear 0.1
->     ; o = sinOsc AR 440 0 * 0.1 }
+> let {x = mouseX' KR (-1) 1 Linear 0.1
+>     ;o = sinOsc AR 440 0 * 0.1}
 > in audition (mrg [pauseSelf x, out 0 o])
 
 Run paused node (assuming no intermediate node is created).
-
 > withSC3 (\fd -> send fd (n_run [(-1, True)]))
diff --git a/Help/UGen/Envelope/pauseSelfWhenDone.help.lhs b/Help/UGen/Envelope/pauseSelfWhenDone.help.lhs
--- a/Help/UGen/Envelope/pauseSelfWhenDone.help.lhs
+++ b/Help/UGen/Envelope/pauseSelfWhenDone.help.lhs
@@ -1,18 +1,19 @@
-pauseSelfWhenDone src
-
-Pauses the synth when the 'done' flag of the unit at `src' is set.
+> Sound.SC3.UGen.Help.viewSC3Help "PauseSelfWhenDone"
+> Sound.SC3.UGen.DB.ugenSummary "PauseSelfWhenDone"
 
 > import Sound.SC3
 
-> let { x = mouseX KR (-1) 1 Linear 0.1
+using PauseSynth done action
+> let { x = mouseX' KR (-1) 1 Linear 0.1
 >     ; e = linen x 1 0.1 1 PauseSynth }
 > in audition (out 0 (sinOsc AR 440 0 * e))
 
 Run paused node (assuming no intermediate node is created).
-
 > withSC3 (\fd -> send fd (n_run [(-1, True)]))
 
-> let { x = mouseX KR (-1) 1 Linear 0.1
->     ; e = linen x 1 0.1 1 DoNothing 
->     ; o = sinOsc AR 440 0 * e }
+> let {x = mouseX' KR (-1) 1 Linear 0.1
+>     ;e = linen x 1 0.1 1 DoNothing
+>     ;o = sinOsc AR 440 0 * e}
 > in audition (mrg [pauseSelfWhenDone e, out 0 o])
+
+> withSC3 (\fd -> send fd (n_run [(-1, True)]))
diff --git a/Help/UGen/Envelope/xLine.help.lhs b/Help/UGen/Envelope/xLine.help.lhs
--- a/Help/UGen/Envelope/xLine.help.lhs
+++ b/Help/UGen/Envelope/xLine.help.lhs
@@ -1,20 +1,11 @@
-xLine rate start end dur doneAction
-
-Exponential line generator.  Generates an exponential curve from the
-start value to the end value. Both the start and end values must be
-non-zero and have the same sign.
-
-start      - starting value
-end        - ending value
-dur        - duration in seconds
-doneAction - a doneAction to be evaluated when the XLine is
-             completed. See EnvGen for details.
+> Sound.SC3.UGen.Help.viewSC3Help "XLine"
+> Sound.SC3.UGen.DB.ugenSummary "XLine"
 
-Note: The sclang interface reorders the mul and add inputs to precede
-the doneAction input.
+# SC3
+At SC3 mul and add inputs precede the doneAction input.
 
 > import Sound.SC3
 
-> let { f = xLine KR 200 17000 10 RemoveSynth
->     ; o = sinOsc AR f 0 * 0.1 }
+> let {f = xLine KR 200 17000 10 RemoveSynth
+>     ;o = sinOsc AR f 0 * 0.1}
 > in audition (out 0 o)
diff --git a/Help/UGen/External/atari2600.help.lhs b/Help/UGen/External/atari2600.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/External/atari2600.help.lhs
@@ -0,0 +1,65 @@
+> Sound.SC3.UGen.Help.viewSC3Help "Atari2600"
+> Sound.SC3.UGen.DB.ugenSummary "Atari2600"
+
+> import Sound.SC3
+
+> audition (out 0 (atari2600 1 2 3 4 5 5 1))
+> audition (out 0 (atari2600 2 3 10 10 5 5 1))
+
+> let {x = mouseX' KR 0 15 Linear 0.1
+>     ;y = mouseY' KR 0 15 Linear 0.1}
+> in audition (out 0 (atari2600 x y 10 10 5 5 1))
+
+> let {x = mouseX' KR 0 31 Linear 0.1
+>     ;y = mouseY' KR 0 31 Linear 0.1}
+> in audition (out 0 (atari2600 2 3 x y 5 5 1))
+
+> let {x = mouseX' KR 0 15 Linear 0.1
+>     ;y = mouseY' KR 0 15 Linear 0.1}
+> in audition (out 0 (atari2600 2 3 10 10 x y 1))
+
+> let {x = mouseX' KR 0 15 Linear 0.1
+>     ;o1 = sinOsc KR 0.35 0 * 7.5 + 7.5
+>     ;y = mouseY' KR 0 31 Linear 0.1
+>     ;o2 = sinOsc KR 0.3 0 * 5.5 + 5.5}
+> in audition (out 0 (atari2600 x o1 10 y o2 5 1))
+
+> let ati = let {gate' = control KR "gate" 1
+>               ;tone0 = control KR "tone0" 5
+>               ;tone1 = control KR "tone1" 8
+>               ;freq0 = control KR "freq0" 10
+>               ;freq1 = control KR "freq1" 20
+>               ;rate = control KR "rate" 1
+>               ;amp = control KR "amp" 1
+>               ;pan = control KR "pan" 0
+>               ;e = envASR 0.01 amp 0.05 (EnvNum (-4))
+>               ;eg = envGen KR gate' 1 0 1 RemoveSynth e
+>               ;z = atari2600 tone0 tone1 freq0 freq1 15 15 rate
+>               ;o = out 0 (pan2 (z * eg) pan 1)}
+>           in synthdef "atari2600" o
+
+> import Sound.SC3.Lang.Pattern.ID
+
+> 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 = [("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 = [("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)
diff --git a/Help/UGen/External/atsNoiSynth.help.lhs b/Help/UGen/External/atsNoiSynth.help.lhs
--- a/Help/UGen/External/atsNoiSynth.help.lhs
+++ b/Help/UGen/External/atsNoiSynth.help.lhs
@@ -1,38 +1,27 @@
-atsNoiSynth b nPartials partialStart partialSkip ptr sinP noiseP 
-            freqMul freqAdd nBands bandStart bandSkip
+> Sound.SC3.UGen.Help.viewSC3Help "AtsNoiSynth"
+> Sound.SC3.UGen.DB.ugenSummary "AtsNoiSynth"
 
-Resynthesize sine data from an ATS analysis file
+> import Sound.SC3
 
-           b - buffer containing ATS data
-   nPartials - number of partials to synthesize
-partialStart - partial in the analysis to start the 
-               synthesis on (zero indexed)
- partialSkip - increment indicating partials to synthesize
-         ptr - index into data set (0, 1)
-       sineP - scaler on sinusoidal portion of the resynthesis
-      noiseP - scaler on noise portion of the resynthesis
-     freqMul - multiplier on the sinusoidal frequency information.
-     freqAdd - value to add to frequency information.
-      nBands - number of critical bands (noise) to synthesize.  
-               There are 25 critical bands.
-   bandStart - critical band to start resynthesis on. 
-               0 is the first band.
-    bandSkip - increment indicating bands to synthesize.
+segmented file loader
+> let load_data fd b i d =
+>         if length d < 512
+>         then send fd (b_setn1 b i d)
+>         else do {send fd (b_setn1 b i (take 512 d))
+>                 ;load_data fd b (i + 512) (drop 512 d)}
 
-> let { load_data fd b i d = 
->       if length d < 512 
->       then send fd (b_setn1 b i d) 
->       else do { send fd (b_setn1 b i (take 512 d))
->               ; load_data fd b (i + 512) (drop 512 d) } }
-> in do { ats <- atsRead "/home/rohan/tn/tn-56/ats/metal.ats"
->       ; let { d = atsSC3 ats
->             ; h = atsHeader ats
->             ; x = mouseX KR 0.05 1.5 Linear 0.2
->             ; y = mouseY KR 0 1 Linear 0.2
->             ; np = constant (atsNPartials h)
->             ; f = x / constant (atsAnalysisDuration h)
->             ; ptr = clip (lfSaw AR f 1 * 0.5 + 0.5) 0 1
->             ; rs = atsNoiSynth 10 np 0 1 ptr (1 - y) y 1 0 25 0 1 }
->         in withSC3 (\fd -> do { async fd (b_alloc 10 (length d) 1)
->                               ; load_data fd 10 0 d
->                               ; play fd (out 0 rs) }) }
+read file
+> ats <- atsRead "/home/rohan/cvs/tn/tn-56/ats/metal.ats"
+
+run re-synthesis
+> let {d = atsData ats
+>     ;h = atsHeader ats
+>     ;x = mouseX' KR 0.05 1.5 Linear 0.2
+>     ;y = mouseY' KR 0 1 Linear 0.2
+>     ;np = constant (atsNPartials h)
+>     ;f = x / constant (atsAnalysisDuration h)
+>     ;ptr = clip (lfSaw AR f 1 * 0.5 + 0.5) 0 1
+>     ;rs = atsNoiSynth 10 np 0 1 ptr (1 - y) y 1 0 25 0 1}
+> in withSC3 (\fd -> do {async fd (b_alloc 10 (length d) 1)
+>                       ;load_data fd 10 0 d
+>                       ;play fd (out 0 rs)})
diff --git a/Help/UGen/External/atsSynth.help.lhs b/Help/UGen/External/atsSynth.help.lhs
--- a/Help/UGen/External/atsSynth.help.lhs
+++ b/Help/UGen/External/atsSynth.help.lhs
@@ -1,29 +1,30 @@
-atsSynth b nPartials partialStart partialSkip ptr freqMul freqAdd
+> Sound.SC3.UGen.Help.viewSC3Help "AtsSynth"
+> Sound.SC3.UGen.DB.ugenSummary "AtsSynth"
 
-Resynthesize sine data from an ATS analysis file.
+> import Sound.SC3
 
-             b - buffer containing ATS data
-     nPartials - number of partials to synthesize
-  partialStart - partial to start the synthesis at (zero indexed)
-   partialSkip - increment indicating partials to synthesize
-           ptr - data index (0, 1)
-       freqMul - multiplier for sinusoidal frequency data
-       freqAdd - value to add to frequency data
+read file
+> ats <- atsRead "/home/rohan/cvs/tn/tn-56/ats/metal.ats"
 
-> let { load_data fd b i d = 
->       if length d < 512 
->       then send fd (b_setn1 b i d) 
->       else do { send fd (b_setn1 b i (take 512 d))
->               ; load_data fd b (i + 512) (drop 512 d) } }
-> in do { ats <- atsRead "/home/rohan/tn/tn-56/ats/metal.ats"
->       ; let { d = atsSC3 ats
->             ; h = atsHeader ats
->             ; x = mouseX KR 0.05 1.5 Linear 0.2
->             ; y = mouseY KR 0.25 2.0 Linear 0.2
->             ; np = constant (atsNPartials h)
->             ; f = x / constant (atsAnalysisDuration h)
->             ; ptr = lfSaw AR f 1 * 0.5 + 0.5
->             ; rs = atsSynth 10 np 0 1 (clip ptr 0 1) y 0 }
->         in withSC3 (\fd -> do { async fd (b_alloc 10 (length d) 1)
->                               ; load_data fd 10 0 d
->                               ; play fd (out 0 rs) }) }
+show header
+> atsHeader ats
+
+data loader that works in segments (udp packet limits)
+> let load_data fd b i d =
+>         if length d < 512
+>         then send fd (b_setn1 b i d)
+>         else do {send fd (b_setn1 b i (take 512 d))
+>                 ;load_data fd b (i + 512) (drop 512 d)}
+
+simple re-synthesiser
+> let {h = atsHeader ats
+>     ;d = atsData ats
+>     ;x = mouseX' KR 0.05 1.5 Linear 0.2
+>     ;y = mouseY' KR 0.25 2.0 Linear 0.2
+>     ;np = constant (atsNPartials h)
+>     ;f = x / constant (atsAnalysisDuration h)
+>     ;ptr = lfSaw AR f 1 * 0.5 + 0.5
+>     ;rs = atsSynth 10 np 0 1 (clip ptr 0 1) y 0}
+> in withSC3 (\fd -> do {_ <- async fd (b_alloc 10 (length d) 1)
+>                       ;load_data fd 10 0 d
+>                       ;play fd (out 0 rs)})
diff --git a/Help/UGen/External/ay.help.lhs b/Help/UGen/External/ay.help.lhs
--- a/Help/UGen/External/ay.help.lhs
+++ b/Help/UGen/External/ay.help.lhs
@@ -1,68 +1,33 @@
-ay tonea toneb tonec noise ctl vola volb volc envfreq envstyle chiptype
-
-Emulates the General Instrument AY-3-8910 (a.k.a. the Yamaha
-YM2149) 3-voice sound chip, as found in the ZX Spectrum
-128, the Atari ST, and various other home computers during
-the 1980s.
-
-The inputs are as follows:
-
- * tonea, toneb, tonec - integer "tone" value for each of
-   the 3 voices, from 0 to 4095 (i.e. 12-bit range). Higher
-   value = lower pitch. For convenience, the AY.freqtotone
-   method converts a frequency value to something
-   appropriate for these inputs.
-
- * noise - the period of the pseudo-random noise generator, 
-   0 to 31
-
- * control - controls how the noise is mixed into the
-   tone(s), 0 to 32 (0 is mute). This is a binary mask value
-   which masks the noise/tone mixture in each channel, so
-   it's not linear.
-
- * vola, volb, volc - volume of the three channels, 0 to 15
-   (or 0 to 31 if using YM chiptype)
-
- * envfreq - envelope frequency, 0 to 4095
-
- * envstyle - type of envelope used, 0 to 15
-
- * chiptype - 0 for AY (default), 1 for YM. The models
-   behave slightly differently. This input cannot be
-   modulated - its value is only handled at the moment the
-   UGen starts.
-
-The chip's inputs are integer values, so non-integer values
-will be rounded off.
+> Sound.SC3.UGen.Help.viewSC3Help "AY"
+> Sound.SC3.UGen.DB.ugenSummary "AY"
 
-The emulation is provided by the libayemu library:
-http://sourceforge.net/projects/libayemu.
+> import Sound.SC3.ID
+> import qualified Sound.SC3.Monadic as M
 
 > audition (out 0 (ay 1777 1666 1555 1 7 15 15 15 4 1 0))
 
-> let { tonea = mouseY KR 10 3900 Exponential 0.2
->     ; toneb = mouseX KR 10 3900 Exponential 0.2
+> let { tonea = mouseY' KR 10 3900 Exponential 0.2
+>     ; toneb = mouseX' KR 10 3900 Exponential 0.2
 >     ; ctl = 3
 >     ; vola = 14
 >     ; volb = 14
->     ; volc = 0 
+>     ; volc = 0
 >     ; s = ay tonea toneb 1555 1 ctl vola volb volc 4 1 0 }
 > in audition (out 0 (pan2 s 0 0.25))
 
-> let { rate = mouseX KR 0.1 10 Linear 0.2
->     ; rng l r i = return (linLin i (-1) 1 l r)
->     ; mk_ctl l r = lfdNoise3 KR rate >>= rng l r
->     ; mk_ctl_0 l r = lfdNoise0 KR rate >>= rng l r }
-> in do { tonea <- mk_ctl 10 3900
->       ; toneb <- mk_ctl 10 3900
->       ; tonec <- mk_ctl 10 3900
->       ; n <- mk_ctl 0 31
->       ; ctl <- mk_ctl_0 0 31
->       ; vola <- mk_ctl 0 15
->       ; volb <- mk_ctl 0 15
->       ; volc <- mk_ctl 0 15
->       ; envfreq <- mk_ctl 0 4095
->       ; envstyle <- mk_ctl 0 15
->       ; let s = ay tonea toneb tonec n ctl vola volb volc envfreq envstyle 0
->         in audition (out 0 (pan2 s 0 0.5)) }
+> let {rate = mouseX' KR 0.1 10 Linear 0.2
+>     ;rng l r i = return (linLin i (-1) 1 l r)
+>     ;mk_ctl l r = M.lfdNoise3 KR rate >>= rng l r
+>     ;mk_ctl_0 l r = M.lfdNoise0 KR rate >>= rng l r}
+> in do {tonea <- mk_ctl 10 3900
+>       ;toneb <- mk_ctl 10 3900
+>       ;tonec <- mk_ctl 10 3900
+>       ;n <- mk_ctl 0 31
+>       ;ctl <- mk_ctl_0 0 31
+>       ;vola <- mk_ctl 0 15
+>       ;volb <- mk_ctl 0 15
+>       ;volc <- mk_ctl 0 15
+>       ;efreq <- mk_ctl 0 4095
+>       ;estyle <- mk_ctl 0 15
+>       ;let s = ay tonea toneb tonec n ctl vola volb volc efreq estyle 0
+>        in audition (out 0 (pan2 s 0 0.5))}
diff --git a/Help/UGen/External/dfm1.help.lhs b/Help/UGen/External/dfm1.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/External/dfm1.help.lhs
@@ -0,0 +1,16 @@
+> Sound.SC3.UGen.Help.viewSC3Help "DFM1"
+> Sound.SC3.UGen.DB.ugenSummary "DFM1"
+
+> import Sound.SC3.ID
+
+Play it with the mouse
+> let { n = pinkNoise 'a' 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))
+
+Bass
+> let { i = pulse AR 100 0.5 * 0.4 + pulse AR 100.1 0.5 * 0.4
+>     ; f = range 80 2000 (sinOsc KR (range 0.2 5 (sinOsc KR 0.3 0)) 0)
+>     ; s = dfm1 i f 1.1 2 0 3e-4 * 0.1 }
+> in audition (out 0 (mce2 s s))
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
@@ -1,109 +1,81 @@
-fm7 ctl mod
-
-  fm7, stefan kersten, phase modulation oscillator matrix.
-  http://darcs.k-hornz.de/repos/skUG/
-
-fm7 implements a 6x6 oscillator matrix, where each
-oscillator's phase can be modulated by any of the
-other oscillators' output.
-
-The UGen expects two (flattened) matrices: one for
-specifying the oscillator parameters frequency
-(control rate), phase (initialization only) and
-amplitude (control rate):
-
-[ [ 300, 0,    1   ],
-  [ 400, pi/2, 1   ],
-  [ 730, 0,    0.5 ],
-  [ 0,   0,    0   ],
-  [ 0,   0,    0   ],
-  [ 0,   0,    0   ] ]
-
-The modulation matrix specifies the amount of
-modulation each oscillator output has on another
-oscillator's phase. Row i in the matrix refer to
-oscillator i's phase input and the columns denote
-the amount of phase modulation in radians.
-
-The UGen outputs the six individual oscillator
-signals.
+> Sound.SC3.UGen.Help.viewSC3Help "FM7"
+> Sound.SC3.UGen.DB.ugenSummary "FM7"
 
 > 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] ]
+>     ; MCE [l,r,_,_,_,_] = fm7 c m }
 > in audition (out 0 (mce2 l r * 0.1))
 
 An algorithmically generated graph courtesy f0.
-
-> let { x = [ [ [ 0.0, -0.33333333333333, -1.0, 0.0 ]
->             , [ 0.75, 0.75, 0.0, -0.5 ]
->             , [ -0.5, -0.25, 0.25, -0.75 ]
->             , [ -0.5, 1.0, 1.0, 1.0 ]
->             , [ 0.0, 0.16666666666667, -0.75, -1.0 ]
->             , [ 0.5, 0.5, -0.5, 0.33333333333333 ] ]
->           , [ [ -0.33333333333333, 0.5, -0.5, -0.5 ]
->             , [ 0.5, 0.75, 0.25, 0.75 ]
->             , [ -0.83333333333333, 0.25, -1.0, 0.5 ]
->             , [ 1.5, 0.25, 0.25, -0.25 ]
->             , [ -0.66666666666667, -0.66666666666667, -1.0, -0.5 ]
->             , [ -1.0, 0.0, -0.83333333333333, -0.33333333333333 ] ]
->           , [ [ 0.25, -0.5, -0.5, -1.0 ]
->             , [ -0.5, 1.0, -1.5, 0.0 ]
->             , [ -1.0, -1.5, -0.5, 0.0 ]
->             , [ 0.5, -1.0, 1.1666666666667, -0.5 ]
->             , [ 0.83333333333333, -0.75, -1.5, 0.5 ]
->             , [ 0.25, -1.0, 0.5, 1.0 ] ]
->           , [ [ 1.0, 0.33333333333333, 0.0, -0.75 ]
->             , [ -0.25, 0.0, 0.0, -0.5 ]
->             , [ -0.5, -0.5, 0.0, 0.5 ]
->             , [ 1.0, 0.75, 0.5, 0.5 ]
->             , [ 0.0, 1.5, -0.5, 0.0 ]
->             , [ 1.0, 0.0, -0.25, -0.5 ] ]
->           , [ [ 0.5, -0.25, 0.0, 0.33333333333333 ]
->             , [ 0.25, -0.75, 0.33333333333333, -1.0 ]
->             , [ -0.25, -0.5, 0.25, -1.1666666666667 ]
->             , [ 0.0, 0.25, 0.5, 0.16666666666667 ]
->             , [ -1.0, -0.5, 0.83333333333333, -0.5 ]
->             , [ 0.83333333333333, -0.75, -0.5, 0.0 ] ]
->           , [ [ 0.0, -0.75, -0.16666666666667, 0.0 ]
->             , [ 1.0, 0.5, 0.5, 0.0 ]
->             , [ -0.5, 0.0, -0.5, 0.0 ]
->             , [ -0.5, -0.16666666666667, 0.0, 0.5 ]
->             , [ -0.25, 0.16666666666667, -0.75, 0.25 ]
->             , [ -1.1666666666667, -1.3333333333333, -0.16666666666667, 1.5 ] ] ]
->     ; y = [ [ [ 0.0, -0.5, 1.0, 0.0 ]
->             , [ -0.5, 1.0, 0.5, -0.5 ]
->             , [ 0.0, 0.33333333333333, 1.0, 1.0 ] ]
->           , [ [ -0.5, 0.5, 1.0, 1.0 ]
->             , [ 0.0, 0.33333333333333, 0.0, 1.5 ]
->             , [ -0.5, 0.83333333333333, 1.0, 0.0 ] ]
->           , [ [ 0.25, -0.66666666666667, 0.25, 0.0 ]
->             , [ 0.5, -0.5, -0.5, -0.5 ]
->             , [ 0.5, -0.5, -0.75, 0.83333333333333 ] ]
->           , [ [ -0.25, 1.0, 0.0, 0.33333333333333 ]
->             , [ -1.25, -0.25, 0.5, 0.0 ]
->             , [ 0.0, -1.25, -0.25, -0.5 ] ]
->           , [ [ 0.75, -0.25, 1.5, 0.0 ]
->             , [ 0.25, -1.5, 0.5, 0.5 ]
->             , [ -0.5, -0.5, -0.5, -0.25 ] ]
->           , [ [ 0.0, 0.5, -0.5, 0.25 ]
->             , [ 0.25, 0.5, -0.33333333333333, 0.0 ]
->             , [ 1.0, 0.5, -0.16666666666667, 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 
+> let { x = [[[0.0,-1/3,-1.0,0.0]
+>            ,[0.75,0.75,0.0,-0.5]
+>            ,[-0.5,-0.25,0.25,-0.75]
+>            ,[-0.5,1.0,1.0,1.0]
+>            ,[0.0,1/6,-0.75,-1.0]
+>            ,[0.5,0.5,-0.5,1/3]]
+>           ,[[-1/3,0.5,-0.5,-0.5]
+>            ,[0.5,0.75,0.25,0.75]
+>            ,[-15/18,0.25,-1.0,0.5]
+>            ,[1.5,0.25,0.25,-0.25]
+>            ,[-2/3,-2/3,-1.0,-0.5]
+>            ,[-1.0,0.0,-15/18,-1/3]]
+>           ,[[0.25,-0.5,-0.5,-1.0]
+>            ,[-0.5,1.0,-1.5,0.0]
+>            ,[-1.0,-1.5,-0.5,0.0]
+>            ,[0.5,-1.0,7/6,-0.5]
+>            ,[15/18,-0.75,-1.5,0.5]
+>            ,[0.25,-1.0,0.5,1.0]]
+>           ,[[1.0,1/3,0.0,-0.75]
+>            ,[-0.25,0.0,0.0,-0.5]
+>            ,[-0.5,-0.5,0.0,0.5]
+>            ,[1.0,0.75,0.5,0.5]
+>            ,[0.0,1.5,-0.5,0.0]
+>            ,[1.0,0.0,-0.25,-0.5]]
+>           ,[[0.5,-0.25,0.0,1/3]
+>            ,[0.25,-0.75,1/3,-1.0]
+>            ,[-0.25,-0.5,0.25,-7/6]
+>            ,[0.0,0.25,0.5,1/6]
+>            ,[-1.0,-0.5,15/18,-0.5]
+>            ,[15/18,-0.75,-0.5,0.0]]
+>           ,[[0.0,-0.75,-1/6,0.0]
+>            ,[1.0,0.5,0.5,0.0]
+>            ,[-0.5,0.0,-0.5,0.0]
+>            ,[-0.5,-1/6,0.0,0.5]
+>            ,[-0.25,1/6,-0.75,0.25]
+>            ,[-7/6,-4/3,-1/6,1.5]]]
+>     ; y = [[[0.0,-0.5,1.0,0.0]
+>            ,[-0.5,1.0,0.5,-0.5]
+>            ,[0.0,1/3,1.0,1.0]]
+>           ,[[-0.5,0.5,1.0,1.0]
+>            ,[0.0,1/3,0.0,1.5]
+>            ,[-0.5,15/18,1.0,0.0]]
+>           ,[[0.25,-2/3,0.25,0.0]
+>            ,[0.5,-0.5,-0.5,-0.5]
+>            ,[0.5,-0.5,-0.75,15/18]]
+>           ,[[-0.25,1.0,0.0,1/3]
+>            ,[-1.25,-0.25,0.5,0.0]
+>            ,[0.0,-1.25,-0.25,-0.5]]
+>           ,[[0.75,-0.25,1.5,0.0]
+>            ,[0.25,-1.5,0.5,0.5]
+>            ,[-0.5,-0.5,-0.5,-0.25]]
+>           ,[[0.0,0.5,-0.5,0.25]
+>            ,[0.25,0.5,-1/3,0.0]
+>            ,[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
 >     ; 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]))
+> in audition (out 0 (mce [c1 + c3 * g3 + c5 * g5,c2 + c4 + c5 * g5]))
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
@@ -1,33 +1,16 @@
-lpcSynth buffer excitation ptr
-lpcVals rate buffer ptr
-
-lpcSynth uses data from a LPC data file to filter a signal.
-lpcVals returns pitch, rms and error data from the LPC data
-file.
-
-      buffer - the buffer LPC data is stored
-         ptr - index into LPC data (0,1)
-  excitation - the signal to filter
-
-lpcVals reads LPC data and extracts frequency (cps), 
-amplitude (rmso) and error signals.
-
-The LPC analysis files read are those generated by 
-lpanal (see csound).
+> Sound.SC3.UGen.Help.viewSC3Help "LPCSynth"
+> Sound.SC3.UGen.DB.ugenSummary "LPCSynth"
 
-Note: since the LPC data set will likely exceed the UDP packet 
-limit, load_data splits the LPC data into 512*4 byte packets.
-Alternately use TCP, or write the LPC data to a disk file and use
-b_allocRead.
+> import Sound.SC3
 
-> let { load_data fd b i d = 
->       if length d < 512 
->       then send fd (b_setn1 b i d) 
+> let { load_data fd b i d =
+>       if length d < 512
+>       then send fd (b_setn1 b i d)
 >       else do { send fd (b_setn1 b i (take 512 d))
 >               ; load_data fd b (i + 512) (drop 512 d) }
->     ; 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
+>     ; 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
@@ -35,9 +18,9 @@
 >           ; 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/tn/tn-56/lpc/fate.lpc"
->       ; n <- pinkNoise AR
->       ; let { d = lpcSC3 lpc 
+> 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 (\fd -> do { async fd (b_alloc 10 (length d) 1)
 >                               ; load_data fd 10 0 d
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
@@ -1,27 +1,19 @@
-membraneCircle input tension loss
-membraneHexagon input tension loss
-
-Triangular waveguide meshes of a drum-like membrane.  Input is
-an excitation signal, such as a pulse of noise.  Tension and
-loss are k-rate.
+> Sound.SC3.UGen.Help.viewSC3Help "MembraneCircle"
+> Sound.SC3.UGen.DB.ugenSummary "MembraneCircle"
 
-The variants are named after the shape made out of triangular 
-meshes.
+> import Sound.SC3.ID
 
-Excite the mesh with some pink noise, triggered by an 
-impulse generator.  mouseX is tension and impulse frequency, 
+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.
-
-> import Sound.SC3
-
-> let { x = mouseX KR 0 1 Linear 0.2
->     ; y = mouseY KR 1e-9 1 Exponential 0.2
+> 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 }
-> in do { n <- pinkNoise AR
->       ; audition (out (mce2 0 1) (m (n * e) tension loss)) }
+>     ; m = membraneCircle
+>     ; n = pinkNoise 'a' AR }
+> in audition (out (mce2 0 1) (m (n * e) tension loss))
diff --git a/Help/UGen/External/membraneHexagon.help.lhs b/Help/UGen/External/membraneHexagon.help.lhs
--- a/Help/UGen/External/membraneHexagon.help.lhs
+++ b/Help/UGen/External/membraneHexagon.help.lhs
@@ -1,1 +1,1 @@
-See membraneCircle.
+See membraneCircle
diff --git a/Help/UGen/External/metro.help.lhs b/Help/UGen/External/metro.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/External/metro.help.lhs
@@ -0,0 +1,16 @@
+> Sound.SC3.UGen.Help.viewSC3Help "Metro"
+> Sound.SC3.UGen.DB.ugenSummary "Metro"
+
+> import Sound.SC3.ID
+
+> 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 }
+> 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 }
+> in audition (out 0 a)
diff --git a/Help/UGen/External/mzPokey.help.lhs b/Help/UGen/External/mzPokey.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/External/mzPokey.help.lhs
@@ -0,0 +1,31 @@
+> Sound.SC3.UGen.Help.viewSC3Help "MZPokey"
+> Sound.SC3.UGen.DB.ugenSummary "MZPokey"
+
+> import Sound.SC3
+> import qualified Sound.SC3.Lang.Math as M
+
+> let b = fromIntegral . M.parseBits :: (String -> UGen)
+> let bln = line KR 0 255 5 RemoveSynth
+> let mz1 i j = mzPokey i j 0 0 0 0 0 0 0
+> let mz1c i j c = mzPokey i j 0 0 0 0 0 0 c
+
+> audition (out 0 (mz1 bln (b "00001111")))
+> audition (out 0 (mz1 bln (b "00101111")))
+> audition (out 0 (mz1 bln (b "10101111")))
+> audition (out 0 (mz1c bln (b "10101111") (b "00000001")))
+> audition (out 0 (mz1c bln (b "10101111") (b "01000001")))
+
+> let mz2c i j p q c = mzPokey i j p q 0 0 0 0 c
+> let bX = mouseX' KR 0 255 Linear 0.1
+> let bY = mouseY' KR 0 255 Linear 0.1
+
+> audition (out 0 (mz2c bX (b "10101010") bY (b "10101010") (b "00000001")))
+
+> let mz4pc (f1,c1) (f2,c2) (f3,c3) (f4,c4) c = mzPokey f1 c1 f2 c2 f3 c3 f4 c4 c
+
+> let { v1 = (bX,b "11000111")
+>     ; v2 = (bY,b "11100111")
+>     ; v3 = (sinOsc KR 0.4 0 * 127.5 + 127.5,b "11000111")
+>     ; v4 = (sinOsc KR 0.5 0 * 127.5 + 127.5,b "01000111")
+>     ; m = mz4pc v1 v2 v3 v4 (b "00000000") }
+> in audition (out 0 (mce2 m m))
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
@@ -1,12 +1,13 @@
-pv_Invert buffer
+> Sound.SC3.UGen.Help.viewSC3Help "PV_Invert"
+> Sound.SC3.UGen.DB.ugenSummary "PV_Invert"
 
-> import Sound.SC3
+> import Sound.SC3.ID
 
 > let { s = sinOsc AR 440 0 * 0.4
->     ; n = Sound.SC3.UGen.Base.pinkNoise 'a' AR * 0.1
+>     ; n = pinkNoise 'a' AR * 0.1
 >     ; i = s + n
 >     ; c0 = fft' 10 i
->     ; c1 = pv_Invert c0 
->     ; run fd = do { async fd (b_alloc 10 2048 1)
+>     ; c1 = pv_Invert c0
+>     ; run fd = do { _ <- async fd (b_alloc 10 2048 1)
 >                   ; audition (out 0 (mce2 i (ifft' c1) * 0.5)) } }
 > in withSC3 run
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
@@ -1,4 +1,7 @@
-stkBowed rt freq bowPressure bowPosition vibFreq vibGain loudness gate
+> Sound.SC3.UGen.Help.viewSC3Help "StkBowed"
+> Sound.SC3.UGen.DB.ugenSummary "StkBowed"
 
+> import Sound.SC3
+
 > let g = toggleFF (impulse KR 1 0)
-> in audition (out 0 (stkBowed AR 220 64 64 64 64 64 g))
+> in audition (out 0 (stkBowed AR 220 64 64 64 64 64 g 1 1))
diff --git a/Help/UGen/External/stkFlute.help.lhs b/Help/UGen/External/stkFlute.help.lhs
--- a/Help/UGen/External/stkFlute.help.lhs
+++ b/Help/UGen/External/stkFlute.help.lhs
@@ -1,4 +1,7 @@
-stkFlute rate freq jetDelay noisegain vibFreq vibGain breathPressure tr
+> Sound.SC3.UGen.Help.viewSC3Help "StkFlute"
+> Sound.SC3.UGen.DB.ugenSummary "StkFlute"
+
+> import Sound.SC3
 
 > let { bp = line KR 76 32 3 RemoveSynth
 >     ; ng = line KR 16 64 3 DoNothing }
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
@@ -1,25 +1,23 @@
-stkMandolin rate f bs pp dm dt at tr
+> Sound.SC3.UGen.Help.viewSC3Help "StkMandolin"
+> Sound.SC3.UGen.DB.ugenSummary "StkMandolin"
 
-        f - frequency
-       bs - body size
-       pp - pick position
-       dm - string damping
-       dt - string detune
-       at - after touch
+> import Control.Monad
+> import Sound.SC3.ID
+> import qualified Sound.SC3.Monadic as M
 
-> let { x = mouseX KR 0.25 4 Linear 0.2 
+> let { x = mouseX' KR 0.25 4 Linear 0.2
 >     ; tr = impulse KR x 0 - 0.5 }
-> in do { mn <- tRand 54 66 tr
->       ; [bs, pp, dm, dt, at] <- replicateM 5 (tRand 0 127 tr)
+> 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 
+> let { x = mouseX' KR 3 16 Linear 0.2
+>     ; t = impulse KR x 0 - 0.5
 >     ; tr = pulseDivider t 6 0 }
-> in do { mn <- tiRand 54 66 t
->       ; bs <- tRand 72 94 tr
->       ; pp <- tRand 32 42 tr
->       ; dm <- tRand 64 72 tr
->       ; dt <- tRand 0 4 tr
->       ; at <- tRand 2 8 tr
+> 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
@@ -1,25 +1,28 @@
-stkModalBar freq instrument stickHardness stickPosition 
-            vibratoGain vibratoFreq directStickMix volume trig
+> Sound.SC3.UGen.Help.viewSC3Help "StkModalBar"
+> Sound.SC3.UGen.DB.ugenSummary "StkModalBar"
 
-  Marimba=0, Vibraphone=1, Agogo=2, Wood1=3, Reso=4,
-  Wood2=5, Beats=6, Two Fixed=7, Clump=8
+> import Control.Monad
+> import Sound.SC3.ID
+> import qualified Sound.SC3.Monadic as M
 
-> let { x = mouseX KR 0.25 4 Linear 0.2 
->     ; tr = impulse KR x 0 - 0.5
->     ; tR = tRand 0 127 tr }
-> in do { i <- tRand 0 9 tr
->       ; mn <- tiRand 25 96 tr
->       ; [sh, sp, vg, vf, mx, v] <- replicateM 6 tR
->       ; audition (out 0 (stkModalBar AR (midiCPS mn) i sh sp vg vf mx v tr)) }
+> let {x = mouseX' KR 0.25 4 Linear 0.2
+>     ;tr = impulse KR x 0 - 0.5
+>     ;tR = M.tRand 0 127 tr}
+> in do {i <- M.tRand 0 9 tr
+>       ;mn <- M.tIRand 25 96 tr
+>       ;[sh,sp,vg,vf,mx,v] <- replicateM 6 tR
+>       ;let s = stkModalBar AR (midiCPS mn) i sh sp vg vf mx v tr
+>        in audition (out 0 s)}
 
-> let { x = mouseX KR 1 6 Linear 0.2 
->     ; t = impulse KR x 0 - 0.5
->     ; tr = pulseDivider t 6 0 }
-> in do { mn <- tiRand 52 64 t
->       ; sh <- tRand 4 8 tr
->       ; sp <- tRand 54 68 tr
->       ; vg <- tRand 66 98 tr
->       ; vf <- tRand 4 12 tr
->       ; mx <- tRand 0 1 tr
->       ; v <- tRand 16 48 tr
->       ; audition (out 0 (stkModalBar AR (midiCPS mn) 1 sh sp vg vf mx v t)) }
+> let {x = mouseX' KR 1 6 Linear 0.2
+>     ;t = impulse KR x 0 - 0.5
+>     ;tr = pulseDivider t 6 0}
+> in do {mn <- M.tIRand 52 64 t
+>       ;sh <- M.tRand 4 8 tr
+>       ;sp <- M.tRand 54 68 tr
+>       ;vg <- M.tRand 66 98 tr
+>       ;vf <- M.tRand 4 12 tr
+>       ;mx <- M.tRand 0 1 tr
+>       ;v <- M.tRand 16 48 tr
+>       ;let s = stkModalBar AR (midiCPS mn) 1 sh sp vg vf mx v t
+>        in audition (out 0 s)}
diff --git a/Help/UGen/External/stkShakers.help.lhs b/Help/UGen/External/stkShakers.help.lhs
--- a/Help/UGen/External/stkShakers.help.lhs
+++ b/Help/UGen/External/stkShakers.help.lhs
@@ -1,24 +1,15 @@
-stkShakers rt instr energy decay nObjects rfreq tr
-
-     instr - model type
-    energy - initial energy
-     decay - rate of decay of system
-  nObjects - number of particles / elements
-     rfreq - resonance frequency
-        tr - reset trigger
+> Sound.SC3.UGen.Help.viewSC3Help "StkShakers"
+> Sound.SC3.UGen.DB.ugenSummary "StkShakers"
 
-  Maraca=0, Cabasa=1, Sekere=2, Guiro=3, Water Drops =4,
-  Bamboo Chimes=5, Tambourine=6, Sleigh Bells=7, Sticks=8,
-  Crunch=9, Wrench=10, Sand Paper=11, Coke Can=12, Next
-  Mug=13, Penny + Mug=14, Nickle + Mug = 15, Dime + Mug=16,
-  Quarter + Mug=17, Franc + Mug=18, Peso + Mug=19, Big
-  Rocks=20, Little Rocks=21, Tuned Bamboo Chimes=22
+> import Control.Monad
+> import Sound.SC3.ID
+> import qualified Sound.SC3.Monadic as M
 
-> let { x = mouseX KR 0.25 4 Linear 0.2 
->     ; tr = impulse KR x 0 - 0.5 }
-> in do { i <- tRand 0 23 tr
->       ; [e, sd, no, rf] <- replicateM 4 (tRand 0 127 tr)
->       ; audition (out 0 (stkShakers AR i e sd no rf tr)) }
+> let {x = mouseX' KR 0.25 4 Linear 0.2
+>     ;tr = impulse KR x 0 - 0.5}
+> in do {i <- M.tRand 0 23 tr
+>       ;[e,sd,no,rf] <- replicateM 4 (M.tRand 0 127 tr)
+>       ;audition (out 0 (stkShakers AR i e sd no rf tr))}
 
 > let tr = impulse KR 1 0 - 0.5
 > in audition (out 0 (stkShakers AR 4 64 64 64 64 tr))
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
@@ -1,34 +1,22 @@
-vosim tr freq nCycles decay
-
-      trig - starts a vosim pulse when a transition from
-             non-positive to positive occurs and no other
-             vosim is still going.  a-rate will produce
-             sample accurate triggering.
-
-      freq - sets the frequency of the squared sinewave.
-
-   nCycles - sets the number of squared sinewaves to use
-             in one vosim pulse.  nCycles gets checked
-             when VOSIM receives a trigger.
-
-     decay - sets the decay factor.
+> Sound.SC3.UGen.Help.viewSC3Help "VOSIM"
+> Sound.SC3.UGen.DB.ugenSummary "VOSIM"
 
-> import Sound.SC3
+> import Sound.SC3.ID
 
-> do { p <- tRand 0 1 (impulse AR 6 0)
->    ; let { t = impulse AR (9 * ( 1 + ( p >* 0.95))) 0
->          ; x = mouseX KR 0.25 2 Linear 0.2
->          ; y = mouseY KR 0.25 1.5 Linear 0.2
->          ; z = 9 
->          ; range i l r = linLin i (-1) 1 l r
->          ; mk_n = lfNoise2 KR z >>= return . range 0.25 2 
->          ; tR l r = tRand (mce l) (mce r) }
->      in do { 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.2, 0.6, 1] t
->            ; l <- tR [-1] [1] t
->            ; xn <- mk_n
->            ; yn <- mk_n
->            ; let v = vosim t (f * x * xn) n (d * y * yn) * a
->              in audition (out 0 (pan2 (mix v) l 1)) } }
+> let {p = tRand 'a' 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 1.5 Linear 0.2
+>     ;z = 9
+>     ;rng l r i = linLin i (-1) 1 l r
+>     ;mk_n e = rng 0.25 2 (lfNoise2 e KR z)
+>     ;tR e l r = tRand e (mce l) (mce r)
+>     ;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.2,0.6,1] t
+>     ;l = tR 'b' [-1] [1] t
+>     ;xn = mk_n 'c'
+>     ;yn = mk_n 'd'
+>     ;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/convolution.help.lhs b/Help/UGen/FFT/convolution.help.lhs
--- a/Help/UGen/FFT/convolution.help.lhs
+++ b/Help/UGen/FFT/convolution.help.lhs
@@ -1,13 +1,8 @@
-convolution in kernel frameSize
-
-Strict convolution of two continuously changing inputs. Also see
-[Convolution2] for a cheaper CPU cost alternative for the case of a
-fixed kernel which can be changed with a trigger message.
+> Sound.SC3.UGen.Help.viewSC3Help "Convolution"
+> Sound.SC3.UGen.DB.ugenSummary "Convolution"
 
-in        - processing target
-kernel    - processing kernel.
-framesize - size of FFT frame, must be a power of two
+> import Sound.SC3.ID
 
-> do { k <- whiteNoise AR
->    ; let i = in' 2 AR numOutputBuses
->      in audition (out 0 (convolution i k 2048 * 0.1)) }
+> let {k = whiteNoise 'a' AR
+>     ;i = in' 2 AR numOutputBuses}
+> in audition (out 0 (convolution i k 2048 * 0.1))
diff --git a/Help/UGen/FFT/fft.help.lhs b/Help/UGen/FFT/fft.help.lhs
--- a/Help/UGen/FFT/fft.help.lhs
+++ b/Help/UGen/FFT/fft.help.lhs
@@ -1,21 +1,13 @@
-fft buffer in hopSize windowType active
-fft' buffer in
-
-Fast fourier transform.  The fast fourier transform analyzes the
-frequency content of a signal.  fft uses a local buffer for holding
-the buffered audio.  The inverse transform, ifft, reconstructs an
-audio signal.
-
-The fft and pv_* UGens run at control rate, the ifft UGen at audio
-rate.
+> Sound.SC3.UGen.Help.viewSC3Help "FFT"
+> Sound.SC3.UGen.DB.ugenSummary "FFT"
+> :t fft'
 
-fft' is a variant FFT constructor with default values for hop size,
-window type, and active status
+> import Sound.SC3.ID
 
 > withSC3 (\fd -> async fd (b_alloc 10 2048 1))
 
-> do { n <- whiteNoise AR
->    ; audition (out 0 (ifft' (fft' 10 (n * 0.05)))) }
+> let n = whiteNoise 'a' AR
+> in audition (out 0 (ifft' (fft' 10 (n * 0.05))))
 
 > let { s0 = sinOsc KR 0.08 0 * 6 + 6.2
 >     ; s1 = sinOsc KR (squared s0) 0 * 100 + 800
diff --git a/Help/UGen/FFT/fftTrigger.help.lhs b/Help/UGen/FFT/fftTrigger.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/FFT/fftTrigger.help.lhs
@@ -0,0 +1,2 @@
+> Sound.SC3.UGen.Help.viewSC3Help "FFTTrigger"
+> Sound.SC3.UGen.DB.ugenSummary "FFTTrigger"
diff --git a/Help/UGen/FFT/ifft.help.lhs b/Help/UGen/FFT/ifft.help.lhs
--- a/Help/UGen/FFT/ifft.help.lhs
+++ b/Help/UGen/FFT/ifft.help.lhs
@@ -1,9 +1,6 @@
-ifft buffer windowType
-ifft' buffer
-
-Inverse Fast Fourier Transform.  The inverse fast fourier transform
-converts from frequency content to a signal.
-
-ifft' is a variant with the default window type.
+> Sound.SC3.UGen.Help.viewSC3Help "IFFT"
+> Sound.SC3.UGen.DB.ugenSummary "IFFT"
+> :t ifft'
 
-See fft.
+# hsc3
+ifft' is a variant with the default window type and size
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
@@ -1,54 +1,22 @@
-packFFT chain bufsize frombin tobin zeroothers magsphases
-
-Pack separate demand-rate FFT bin streams into an FFT chain buffer
-
-Takes a length-prefixed array of magnitudes and phases, and packs
-them into an FFT buffer ready for transforming back into
-time-domain audio using IFFT.
-
-Most people won't need to use this directly - instead, use
-pvcollect, pvcalc, or pvcalc2.
-
-The input data is magsphases, which should be a flat array
-containing magnitude and phase of all bins in ascending order.
-e.g. [mag0, phase0, mag1, phase1, mag2, phase2, ... magN, phaseN]
-This input is typically demand-rate.
-
-This is technically similar to Demand or Duty in that it calls
-demand-rate UGens further up the graph to process the values,
-eventually calling UnpackFFT. These two ends of the process must in
-most cases see the same chain...! Otherwise behaviour is undefined
-and, who knows, possibly unpleasant.
-
-frombin and tobin allow you to fill the supplied data only into a
-subset of the FFT bins (i.e. a single delimited frequency band),
-set zeroothers to 1 to zero all the magnitudes outside this band
-(otherwise they stay intact).
-
-For usage examples, see UnpackFFT, but also pvcollect, pvcalc,
-pvcalc2.
+> Sound.SC3.UGen.Help.viewSC3Help "PackFFT"
+> Sound.SC3.UGen.DB.ugenSummary "PackFFT"
 
-Here's an unusual example which uses PackFFT without using
-UnpackFFT first - essentially creating our FFT data from scratch.
+> import Sound.SC3.ID
 
 > withSC3 (\fd -> send fd (b_alloc 10 512 1))
 
-> let n = 100
->     range :: UGen -> UGen -> UGen -> UGen
->     range u l r = linLin u (-1) 1 l r
->     square :: Num n => n -> n
->     square a = a * a
->     r1 = do f <- expRand 0.1 1
->             return (range (fSinOsc KR f 0) 0 1)
-> m1 <- replicateM n r1
-> let m2 = zipWith (*) m1 (map square [1.0, 0.99 ..])
->     r2 = do r <- iRand (-3) 5
->             return (lfPulse KR (2 ** r) 0 0.3)
-> i <- replicateM n r2
-> let m3 = zipWith (*) m2 i
->     p = replicate n 0.0
->     c1 = fft' 10 (fSinOsc AR 440 0)
->     ci = constant . fromIntegral
->     c2 = packFFT c1 512 0 (ci n - 1) 1 (packFFTSpec m3 p)
->     s = ifft' c2
-> audition (out 0 (mce [s, s]))
+> let {n = 100
+>     ;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
+>     ;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
+>     ;m3 = zipWith (*) m2 i
+>     ;p = replicate n 0.0
+>     ;c1 = fft' 10 (fSinOsc AR 440 0)
+>     ;c2 = packFFT c1 512 0 (constant n - 1) 1 (packFFTSpec m3 p)
+>     ;s = ifft' c2}
+> in audition (out 0 (mce [s,s]))
diff --git a/Help/UGen/FFT/partConv.help.lhs b/Help/UGen/FFT/partConv.help.lhs
--- a/Help/UGen/FFT/partConv.help.lhs
+++ b/Help/UGen/FFT/partConv.help.lhs
@@ -1,55 +1,21 @@
-partConv in fft_size ir_bufnum
-
-Partitioned convolution. Various additional buffers
-must be supplied.
-
-Mono impulse response only! If inputting multiple
-channels, you'll need independent PartConvs, one
-for each channel.
-
-But the charm is: impulse response can be as large
-as you like (CPU load increases with IR
-size. Various tradeoffs based on fftsize choice,
-due to rarer but larger FFTs. This plug-in uses
-amortisation to spread processing and avoid
-spikes).
-
-Normalisation factors difficult to anticipate;
-convolution piles up multiple copies of the input
-on top of itself, so can easily overload.
-
-         in - processing target
-
-    fftsize - spectral convolution partition size
-              (twice partition size). You must
-              ensure that the blocksize divides the
-              partition size and there are at least
-              two blocks per partition (to allow
-              for amortisation)
-
-   irbufnum - Prepared buffer of spectra for each 
-              partition of the impulse response
-
-preparation; essentially, allocate an impulse
-response buffer, then follow some special buffer
-preparation steps below to set up the data the
-plugin needs. 
+> Sound.SC3.UGen.Help.viewSC3Help "PartConv"
+> Sound.SC3.UGen.DB.ugenSummary "PartConv"
 
-> import Sound.SC3
+> import Sound.SC3.ID
 
 > let { fft_size = 2048
->     ; ir_file = "/home/rohan/audio/church.ir.wav"
+>     ; ir_file = "/home/rohan/data/audio/church.ir.wav"
 >     ; ir_length = 82756
 >     ; accum_size = pc_calcAccumSize fft_size ir_length
 >     ; ir_td_b = 10 {- time domain -}
 >     ; ir_fd_b = 11 {- frequency domain -}
 >     ; target_b = 12 {- source signal -}
->     ; target_file = "/home/rohan/audio/text.snd"
+>     ; target_file = "/home/rohan/data/audio/pf-c5.snd"
 >     ; c = constant
 >     ; g = let { i = playBuf 1 (c target_b) 1 0 0 Loop DoNothing
 >               ; pc = partConv i (c fft_size) (c ir_fd_b) }
 >           in out 0 (pc * 0.1) }
-> in withSC3 (\fd -> do 
+> in withSC3 (\fd -> do
 >     { async fd (b_allocRead ir_td_b ir_file 0 ir_length)
 >     ; async fd (b_alloc ir_fd_b accum_size 1)
 >     ; send fd (pc_preparePartConv ir_fd_b ir_td_b fft_size)
diff --git a/Help/UGen/FFT/pv_BinScramble.help.lhs b/Help/UGen/FFT/pv_BinScramble.help.lhs
--- a/Help/UGen/FFT/pv_BinScramble.help.lhs
+++ b/Help/UGen/FFT/pv_BinScramble.help.lhs
@@ -1,23 +1,15 @@
-pv_BinScramble buffer wipe width trig
-
-Randomizes the order of the bins.  The trigger will select a new
-random ordering.
-
-buffer - fft' buffer.
-wipe   - scrambles more bins as wipe moves from zero to one.
-width  - a value from zero to one, indicating the maximum randomized
-         distance of a bin from its original location in the spectrum.
-trig   - a trigger selects a new random ordering.
+> Sound.SC3.UGen.Help.viewSC3Help "PV_BinScramble"
+> Sound.SC3.UGen.DB.ugenSummary "PV_BinScramble"
 
-> import Sound.SC3
+> import Sound.SC3.ID
 
-> let fileName = "/home/rohan/audio/metal.wav"
-> in withSC3 (\fd -> do { async fd (b_alloc 10 2048 1)
->                       ; async fd (b_allocRead 12 fileName 0 0) })
+> let fileName = "/home/rohan/data/audio/pf-c5.snd"
+> in withSC3 (\fd -> do {_ <- async fd (b_alloc 10 2048 1)
+>                       ;async fd (b_allocRead 12 fileName 0 0)})
 
-> let { a = playBuf 1 12 (bufRateScale KR 12) 1 0 Loop DoNothing
->     ; f = fft' 10 a
->     ; x = mouseX KR 0.0 1.0 Linear 0.1
->     ; y = mouseY KR 0.0 1.0 Linear 0.1 }
-> in do { g <- pv_BinScramble f x y (impulse KR 4 0)
->       ; audition (out 0 (pan2 (ifft' g) 0 0.5)) }
+> let {a = playBuf 1 AR 12 (bufRateScale KR 12) 1 0 Loop DoNothing
+>     ;f = fft' 10 a
+>     ;x = mouseX' KR 0.0 1.0 Linear 0.1
+>     ;y = mouseY' KR 0.0 1.0 Linear 0.1
+>     ;g = pv_BinScramble 'a' f x y (impulse KR 4 0)}
+> in audition (out 0 (pan2 (ifft' g) 0 0.5))
diff --git a/Help/UGen/FFT/pv_BinShift.help.lhs b/Help/UGen/FFT/pv_BinShift.help.lhs
--- a/Help/UGen/FFT/pv_BinShift.help.lhs
+++ b/Help/UGen/FFT/pv_BinShift.help.lhs
@@ -1,13 +1,12 @@
-pv_BinShift buffer stretch shift
+> Sound.SC3.UGen.Help.viewSC3Help "PV_BinShift"
+> Sound.SC3.UGen.DB.ugenSummary "PV_BinShift"
 
-Shift and scale the positions of the bins.  Can be used as a very
-crude frequency shifter/scaler.  Shifts the leftmost bin at `buffer'
-by `shift' places, the distance between subsequent bins is `stretch'.
+> import Sound.SC3.ID
 
 > withSC3 (\fd -> async fd (b_alloc 10 2048 1))
 
-> let { x  = mouseX KR (-10) 100 Linear 0.1
->     ; y  = mouseY KR 1 4 Linear 0.1
+> let { x  = mouseX' KR (-10) 100 Linear 0.1
+>     ; y  = mouseY' KR 1 4 Linear 0.1
 >     ; s0 = sinOsc KR 0.08 0 * 6 + 6.2
 >     ; s1 = sinOsc KR (squared s0) 0 * 100 + 800
 >     ; s2 = sinOsc AR s1 0
diff --git a/Help/UGen/FFT/pv_BinWipe.help.lhs b/Help/UGen/FFT/pv_BinWipe.help.lhs
--- a/Help/UGen/FFT/pv_BinWipe.help.lhs
+++ b/Help/UGen/FFT/pv_BinWipe.help.lhs
@@ -1,27 +1,17 @@
-pv_BinWipe bufferA bufferB wipe
-
-Combine low and high bins from two inputs.  Copies low bins from one
-input and the high bins of the other.
-
-bufferA - fft buffer A.
-bufferB - fft buffer B.
-wipe    - can range between -1 and +1.
-
-if wipe == 0 then the output is the same as inA.
-if  wipe > 0 then it begins replacing with bins from inB from the bottom up.
-if  wipe < 0 then it begins replacing with bins from inB from the top down.
+> Sound.SC3.UGen.Help.viewSC3Help "PV_BinWipe"
+> Sound.SC3.UGen.DB.ugenSummary "PV_BinWipe"
 
-> import Sound.SC3
+> import Sound.SC3.ID
 
-> let fileName = "/home/rohan/audio/metal.wav"
-> in withSC3 (\fd -> do { async fd (b_alloc 10 2048 1)
->                       ; async fd (b_alloc 11 2048 1)
->                       ; async fd (b_allocRead 12 fileName 0 0) })
+> let fileName = "/home/rohan/data/audio/pf-c5.snd"
+> in withSC3 (\fd -> do {_ <- async fd (b_alloc 10 2048 1)
+>                       ;_ <- async fd (b_alloc 11 2048 1)
+>                       ;async fd (b_allocRead 12 fileName 0 0)})
 
-> do { n <- whiteNoise AR
->    ; let { b = playBuf 1 12 (bufRateScale KR 12) 0 0 Loop DoNothing
->          ; f = fft' 10 (n * 0.2)
->          ; g = fft' 11 b
->          ; x = mouseX KR 0.0 1.0 Linear 0.1
->          ; h = pv_BinWipe f g x }
->      in audition (out 0 (pan2 (ifft' h) 0 0.5)) }
+> let {n = whiteNoise 'a' AR
+>     ;b = playBuf 1 AR 12 (bufRateScale KR 12) 0 0 Loop DoNothing
+>     ;f = fft' 10 (n * 0.2)
+>     ;g = fft' 11 b
+>     ;x = mouseX' KR 0.0 1.0 Linear 0.1
+>     ;h = pv_BinWipe f g x}
+> in audition (out 0 (pan2 (ifft' h) 0 0.5))
diff --git a/Help/UGen/FFT/pv_BrickWall.help.lhs b/Help/UGen/FFT/pv_BrickWall.help.lhs
--- a/Help/UGen/FFT/pv_BrickWall.help.lhs
+++ b/Help/UGen/FFT/pv_BrickWall.help.lhs
@@ -1,11 +1,10 @@
-pv_BrickWall buffer wipe
+> Sound.SC3.UGen.Help.viewSC3Help "PV_BrickWall"
+> Sound.SC3.UGen.DB.ugenSummary "PV_BrickWall"
 
-Clears bins above or below a cutoff point.  `wipe' = a unit signal,
-from -1 to 0 the UGen acts as a low-pass filter, from 0 to 1 it acts
-as a high pass filter.
+> import Sound.SC3.ID
 
 > withSC3 (\fd -> async fd (b_alloc 10 2048 1))
 
-> do { n <- whiteNoise AR
->    ; let x = mouseX KR (-1) 1 Linear 0.1
->      in audition (out 0 (ifft' (pv_BrickWall (fft' 10 (n * 0.2)) x))) }
+> let {n = whiteNoise 'a' AR
+>     ;x = mouseX' KR (-1) 1 Linear 0.1}
+> in audition (out 0 (ifft' (pv_BrickWall (fft' 10 (n * 0.2)) x)))
diff --git a/Help/UGen/FFT/pv_ConformalMap.help.lhs b/Help/UGen/FFT/pv_ConformalMap.help.lhs
--- a/Help/UGen/FFT/pv_ConformalMap.help.lhs
+++ b/Help/UGen/FFT/pv_ConformalMap.help.lhs
@@ -1,30 +1,23 @@
-pv_ConformalMap buffer real imag
-
-Applies the conformal mapping z -> (z-a)/(1-za*) to the phase vocoder
-bins z with a given by the real and imag imputs to the UGen.
-
-See http://mathworld.wolfram.com/ConformalMapping.html
+> Sound.SC3.UGen.Help.viewSC3Help "PV_ConformalMap"
+> Sound.SC3.UGen.DB.ugenSummary "PV_ConformalMap"
 
-buffer - buffer number of buffer to act on, passed in through a chain
-real   - real part of a.
-imag   - imaginary part of a.
+> import Sound.SC3.ID
 
 > withSC3 (\fd -> async fd (b_alloc 10 1024 1))
 
 > let { i = in' 1 AR numOutputBuses * 0.5
->     ; x = mouseX KR (-1) 1 Linear 0.1
->     ; y = mouseY KR (-1) 1 Linear 0.1 }
+>     ; x = mouseX' KR (-1) 1 Linear 0.1
+>     ; y = mouseY' KR (-1) 1 Linear 0.1 }
 > in audition (out 0 (pan2 (ifft' (pv_ConformalMap (fft' 10 i) x y)) 0 1))
 
 With filtering.
-
 > withSC3 (\fd -> async fd (b_alloc 0 2048 1))
 
 > let { o = mce [1, 1.1, 1.5, 1.78, 2.45, 6.7, 8] * 220
 >     ; f = sinOsc KR (mce [0.16, 0.33, 0.41]) 0 * 10 + o
 >     ; s = mix (lfSaw AR f 0) * 0.3
->     ; x = mouseX KR 0.01  2.0 Linear 0.1
->     ; y = mouseY KR 0.01 10.0 Linear 0.1
+>     ; x = mouseX' KR 0.01  2.0 Linear 0.1
+>     ; y = mouseY' KR 0.01 10.0 Linear 0.1
 >     ; c = fft' 0 s
 >     ; m = ifft' (pv_ConformalMap c x y) }
 > in audition (out 0 (pan2 (combN m 0.1 0.1 10 * 0.5 + m) 0 1))
diff --git a/Help/UGen/FFT/pv_Copy.help.lhs b/Help/UGen/FFT/pv_Copy.help.lhs
--- a/Help/UGen/FFT/pv_Copy.help.lhs
+++ b/Help/UGen/FFT/pv_Copy.help.lhs
@@ -1,20 +1,13 @@
-pv_Copy bufferA bufferB
+> Sound.SC3.UGen.Help.viewSC3Help "PV_Copy"
+> Sound.SC3.UGen.DB.ugenSummary "PV_Copy"
 
-Copies the spectral frame in bufferA to bufferB at that point in the
-chain of PV UGens. This allows for parallel processing of spectral
-data without the need for multiple FFT' UGens, and to copy out data at
-that point in the chain for other purposes. bufferA and bufferB must
-be the same size.
+> import Sound.SC3.ID
 
-bufferA - source buffer.
-bufferB - destination buffer.
+> withSC3 (\fd -> do {_ <- async fd (b_alloc 0 2048 1)
+>                    ;async fd (b_alloc 1 2048 1)})
 
 Proof of concept, silence
-
-> withSC3 (\fd -> do { async fd (b_alloc 0 2048 1)
->                    ; async fd (b_alloc 1 2048 1) })
-
-> do { i <- lfClipNoise AR 100
->    ; let { c0 = fft' 0 i
->          ; c1 = pv_Copy c0 1 }
->      in audition (out 0 (ifft' c0 - ifft' c1)) }
+> let {i = lfClipNoise 'a' AR 100 * 0.1
+>     ;c0 = fft' 0 i
+>     ;c1 = pv_Copy c0 1}
+> in audition (out 0 (ifft' c0 - ifft' c1))
diff --git a/Help/UGen/FFT/pv_Diffuser.help.lhs b/Help/UGen/FFT/pv_Diffuser.help.lhs
--- a/Help/UGen/FFT/pv_Diffuser.help.lhs
+++ b/Help/UGen/FFT/pv_Diffuser.help.lhs
@@ -1,19 +1,14 @@
-pv_Diffuser buffer trig
-
-Adds a different constant random phase shift to each bin.
-The trigger will select a new set of random phases.
-
-buffer - fft buffer.
-trig   - a trigger selects a new set of random values.
+> Sound.SC3.UGen.Help.viewSC3Help "PV_Diffuser"
+> Sound.SC3.UGen.DB.ugenSummary "PV_Diffuser"
 
-> import Sound.SC3
+> import Sound.SC3.ID
 
-> let fileName = "/home/rohan/audio/metal.wav"
-> in withSC3 (\fd -> do { async fd (b_alloc 10 2048 1)
->                       ; async fd (b_allocRead 12 fileName 0 0) })
+> let fileName = "/home/rohan/data/audio/pf-c5.snd"
+> in withSC3 (\fd -> do {_ <- async fd (b_alloc 10 2048 1)
+>                       ;async fd (b_allocRead 12 fileName 0 0)})
 
-> let { a = playBuf 1 12 (bufRateScale KR 12) 0 0 Loop DoNothing
+> let { a = playBuf 1 AR 12 (bufRateScale KR 12) 0 0 Loop DoNothing
 >     ; f = fft' 10 a
->     ; x = mouseX KR 0 1 Linear 0.1
+>     ; x = mouseX' KR 0 1 Linear 0.1
 >     ; h = pv_Diffuser f (x >* 0.5) }
 > in audition (out 0 (ifft' h * 0.5))
diff --git a/Help/UGen/FFT/pv_HainsworthFoote.help.lhs b/Help/UGen/FFT/pv_HainsworthFoote.help.lhs
--- a/Help/UGen/FFT/pv_HainsworthFoote.help.lhs
+++ b/Help/UGen/FFT/pv_HainsworthFoote.help.lhs
@@ -1,43 +1,12 @@
-pv_HainsworthFoote buf proph propf threshold waittime
-
-FFT onset detector based on work described in
-
-  Hainsworth, S. (2003) Techniques for the Automated Analysis of
-  Musical Audio. PhD, University of Cambridge engineering dept. See
-  especially p128.
-
-The Hainsworth metric is a modification of the Kullback Liebler
-distance.
-
-The onset detector has general ability to spot spectral change, so may
-have some ability to track chord changes aside from obvious transient
-jolts, but there's no guarantee it won't be confused by frequency
-modulation artifacts.
-
-Hainsworth metric on it's own gives good results but Foote might be
-useful in some situations: experimental.
-
-    buffer - FFT buffer to read from
-
-     proph - What strength of detection signal from
-             Hainsworth metric to use.
-
-     propf - What strength of detection signal from Foote
-             metric to use. The Foote metric is normalised
-             to [0.0,1.0]
-
- threshold - Threshold hold level for allowing a detection
-
-  waittime - If triggered, minimum wait until a further
-             frame can cause another spot (useful to stop
-             multiple detects on heavy signals)
+> Sound.SC3.UGen.Help.viewSC3Help "PV_HainsworthFoote"
+> Sound.SC3.UGen.DB.ugenSummary "PV_HainsworthFoote"
 
-> import Sound.SC3
+> import Sound.SC3.ID
 
 > let { i = soundIn 0
 >     ; b = mrg2 (localBuf 'a' 2048 1) (maxLocalBufs 1)
 >     ; f = fft' b i
->     ; x = mouseX KR 0.5 1.25 Linear 0.2
+>     ; x = mouseX' KR 0.5 1.25 Linear 0.2
 >     ; h = pv_HainsworthFoote f 1 0 x 0.04
 >     ; o = sinOsc AR (mrg2 440 445) 0 * decay (h * 0.1) 0.1 }
 > in audition (out 0 (o + i))
diff --git a/Help/UGen/FFT/pv_LocalMax.help.lhs b/Help/UGen/FFT/pv_LocalMax.help.lhs
--- a/Help/UGen/FFT/pv_LocalMax.help.lhs
+++ b/Help/UGen/FFT/pv_LocalMax.help.lhs
@@ -1,19 +1,14 @@
-pv_LocalMax buffer threshold
-
-Pass bins which are a local maximum.  Passes only bins whose magnitude
-is above a threshold and above their nearest neighbors.
-
-buffer    - fft buffer.
-threshold - magnitude threshold.
+> Sound.SC3.UGen.Help.viewSC3Help "PV_LocalMax"
+> Sound.SC3.UGen.DB.ugenSummary "PV_LocalMax"
 
-> import Sound.SC3
+> import Sound.SC3.ID
 
-> let fileName = "/home/rohan/audio/metal.wav"
-> in withSC3 (\fd -> do { async fd (b_alloc 10 2048 1)
->                       ; async fd (b_allocRead 12 fileName 0 0) })
+> let fileName = "/home/rohan/data/audio/pf-c5.snd"
+> in withSC3 (\fd -> do {_ <- async fd (b_alloc 10 2048 1)
+>                       ;async fd (b_allocRead 12 fileName 0 0)})
 
-> let { a = playBuf 1 12 (bufRateScale KR 12) 0 0 Loop DoNothing
+> let { a = playBuf 1 AR 12 (bufRateScale KR 12) 0 0 Loop DoNothing
 >     ; f = fft' 10 a
->     ; x = mouseX KR 0 100 Linear 0.1
+>     ; x = mouseX' KR 0 100 Linear 0.1
 >     ; h = pv_LocalMax f x }
 > in audition (out 0 (ifft' h * 0.5))
diff --git a/Help/UGen/FFT/pv_MagAbove.help.lhs b/Help/UGen/FFT/pv_MagAbove.help.lhs
--- a/Help/UGen/FFT/pv_MagAbove.help.lhs
+++ b/Help/UGen/FFT/pv_MagAbove.help.lhs
@@ -1,26 +1,22 @@
-pv_MagAbove buffer threshold
-
-Pass bins above a threshold.  Pass only bands where the magnitude is
-above `threshold'.  This value is not normalized and is therefore
-dependant on the buffer size.
+> Sound.SC3.UGen.Help.viewSC3Help "PV_MagAbove"
+> Sound.SC3.UGen.DB.ugenSummary "PV_MagAbove"
 
-> import Sound.SC3
+> import Sound.SC3.ID
 
-> let fileName = "/home/rohan/audio/metal.wav"
+> let fileName = "/home/rohan/data/audio/pf-c5.snd"
 > in withSC3 (\fd -> do { async fd (b_alloc 10 2048 1)
 >                       ; async fd (b_allocRead 12 fileName 0 0) })
 
-> let { a = playBuf 1 12 (bufRateScale KR 12) 0 0 Loop DoNothing
+> let { a = playBuf 1 AR 12 (bufRateScale KR 12) 0 0 Loop DoNothing
 >     ; f = fft' 10 a
->     ; x = mouseX KR 0 100 Linear 0.1
+>     ; x = mouseX' KR 0 100 Linear 0.1
 >     ; h = pv_MagAbove f x }
 > in audition (out 0 (ifft' h * 0.5))
 
 Synthesised input.
-
 > let { a = sinOsc KR (squared (sinOsc KR 0.08 0 * 6 + 6.2)) 0 * 100 + 800
 >     ; b = sinOsc AR a 0
 >     ; f = fft' 10 b
->     ; x = mouseX KR 0 1024 Linear 0.1
+>     ; x = mouseX' KR 0 1024 Linear 0.1
 >     ; h = pv_MagAbove f x }
 > in audition (out 0 (ifft' h * 0.5))
diff --git a/Help/UGen/FFT/pv_MagBelow.help.lhs b/Help/UGen/FFT/pv_MagBelow.help.lhs
--- a/Help/UGen/FFT/pv_MagBelow.help.lhs
+++ b/Help/UGen/FFT/pv_MagBelow.help.lhs
@@ -1,26 +1,22 @@
-pv_MagBelow buffer threshold
-
-Pass bins below a threshold.  Pass only bands where the magnitude is
-below `threshold'.  This value is not normalized and is therefore
-dependant on the buffer size.
+> Sound.SC3.UGen.Help.viewSC3Help "PV_MagBelow"
+> Sound.SC3.UGen.DB.ugenSummary "PV_MagBelow"
 
-> import Sound.SC3
+> import Sound.SC3.ID
 
-> let fileName = "/home/rohan/audio/metal.wav"
+> let fileName = "/home/rohan/data/audio/pf-c5.snd"
 > in withSC3 (\fd -> do { async fd (b_alloc 10 2048 1)
 >                       ; async fd (b_allocRead 12 fileName 0 0) })
 
-> let { a = playBuf 1 12 (bufRateScale KR 12) 0 0 Loop DoNothing
+> let { a = playBuf 1 AR 12 (bufRateScale KR 12) 0 0 Loop DoNothing
 >     ; f = fft' 10 a
->     ; x = mouseX KR 0 100 Linear 0.1
+>     ; x = mouseX' KR 0 100 Linear 0.1
 >     ; h = pv_MagBelow f x }
 > in audition (out 0 (ifft' h * 0.5))
 
 Synthesised input.
-
 > let { a = sinOsc KR (squared (sinOsc KR 0.08 0 * 6 + 6.2)) 0 * 100 + 800
 >     ; b = sinOsc AR a 0
 >     ; f = fft' 10 b
->     ; x = mouseX KR 0 1024 Linear 0.1
+>     ; x = mouseX' KR 0 1024 Linear 0.1
 >     ; h = pv_MagBelow f x }
 > in audition (out 0 (ifft' h * 0.5))
diff --git a/Help/UGen/FFT/pv_MagClip.help.lhs b/Help/UGen/FFT/pv_MagClip.help.lhs
--- a/Help/UGen/FFT/pv_MagClip.help.lhs
+++ b/Help/UGen/FFT/pv_MagClip.help.lhs
@@ -1,25 +1,22 @@
-pv_MagClip buffer threshold
-
-Clip bins to a threshold.  Clips bin magnitudes to a maximum
-threshold.
+> Sound.SC3.UGen.Help.viewSC3Help "PV_MagClip"
+> Sound.SC3.UGen.DB.ugenSummary "PV_MagClip"
 
-> import Sound.SC3
+> import Sound.SC3.ID
 
-> let fileName = "/home/rohan/audio/metal.wav"
+> let fileName = "/home/rohan/data/audio/pf-c5.snd"
 > in withSC3 (\fd -> do { async fd (b_alloc 10 2048 1)
 >                       ; async fd (b_allocRead 12 fileName 0 0) })
 
-> let { a = playBuf 1 12 (bufRateScale KR 12) 0 0 Loop DoNothing
+> let { a = playBuf 1 AR 12 (bufRateScale KR 12) 0 0 Loop DoNothing
 >     ; f = fft' 10 a
->     ; x = mouseX KR 0 5 Linear 0.1
+>     ; x = mouseX' KR 0 5 Linear 0.1
 >     ; h = pv_MagBelow f x }
 > in audition (out 0 (ifft' h * 0.5))
 
 Synthesised input.
-
 > let { a = sinOsc KR (squared (sinOsc KR 0.08 0 * 6 + 6.2)) 0 * 100 + 800
 >     ; b = sinOsc AR a 0
 >     ; f = fft' 10 b
->     ; x = mouseX KR 0 128 Linear 0.1
+>     ; x = mouseX' KR 0 128 Linear 0.1
 >     ; h = pv_MagClip f x }
 > in audition (out 0 (ifft' h * 0.5))
diff --git a/Help/UGen/FFT/pv_MagFreeze.help.lhs b/Help/UGen/FFT/pv_MagFreeze.help.lhs
--- a/Help/UGen/FFT/pv_MagFreeze.help.lhs
+++ b/Help/UGen/FFT/pv_MagFreeze.help.lhs
@@ -1,25 +1,22 @@
-pv_MagClip buffer threshold
-
-Clip bins to a threshold.  Clips bin magnitudes to a maximum
-threshold.
+> Sound.SC3.UGen.Help.viewSC3Help "PV_MagFreeze"
+> Sound.SC3.UGen.DB.ugenSummary "PV_MagFreeze"
 
-> import Sound.SC3
+> import Sound.SC3.ID
 
-> let fileName = "/home/rohan/audio/metal.wav"
+> let fileName = "/home/rohan/data/audio/pf-c5.snd"
 > in withSC3 (\fd -> do { async fd (b_alloc 10 2048 1)
 >                       ; async fd (b_allocRead 12 fileName 0 0) })
 
-> let { a = playBuf 1 12 (bufRateScale KR 12) 0 0 Loop DoNothing
+> let { a = playBuf 1 AR 12 (bufRateScale KR 12) 0 0 Loop DoNothing
 >     ; f = fft' 10 a
->     ; x = mouseX KR 0 1 Linear 0.1
+>     ; x = mouseX' KR 0 1 Linear 0.1
 >     ; h = pv_MagFreeze f (x >* 0.5) }
 > in audition (out 0 (ifft' h * 0.5))
 
 Synthesised input.
-
 > let { a = sinOsc KR (squared (sinOsc KR 0.08 0 * 6 + 6.2)) 0 * 100 + 800
 >     ; b = sinOsc AR a 0
 >     ; f = fft' 10 b
->     ; x = mouseX KR 0 1 Linear 0.1
+>     ; x = mouseX' KR 0 1 Linear 0.1
 >     ; h = pv_MagFreeze f (x >* 0.5) }
 > in audition (out 0 (ifft' h * 0.5))
diff --git a/Help/UGen/FFT/pv_RandComb.help.lhs b/Help/UGen/FFT/pv_RandComb.help.lhs
--- a/Help/UGen/FFT/pv_RandComb.help.lhs
+++ b/Help/UGen/FFT/pv_RandComb.help.lhs
@@ -1,14 +1,12 @@
-pv_RandComb buffer wipe trig
-
-Randomly clear bins.
+> Sound.SC3.UGen.Help.viewSC3Help "PV_RandComb"
+> Sound.SC3.UGen.DB.ugenSummary "PV_RandComb"
 
-buffer = fft buffer.  wipe = clear bins from input in a random
-order (0, 1).  trig = select new random ordering.
+> import Sound.SC3.ID
 
 > withSC3 (\fd -> async fd (b_alloc 10 2048 1))
 
-> let { x = mouseX KR 0.6 0.95 Linear 0.1
->     ; t = impulse KR 0.4 0 }
-> in do { n <- whiteNoise AR
->       ; c <- pv_RandComb (fft' 10 (n * 0.5)) x t
->       ; audition (out 0 (pan2 (ifft' c) 0 1)) }
+> let {x = mouseX' KR 0.6 0.95 Linear 0.1
+>     ;t = impulse KR 0.4 0
+>     ;n = whiteNoise 'a' AR
+>     ;c = pv_RandComb 'a' (fft' 10 (n * 0.5)) x t}
+> in audition (out 0 (pan2 (ifft' c) 0 1))
diff --git a/Help/UGen/FFT/pv_RandWipe.help.lhs b/Help/UGen/FFT/pv_RandWipe.help.lhs
--- a/Help/UGen/FFT/pv_RandWipe.help.lhs
+++ b/Help/UGen/FFT/pv_RandWipe.help.lhs
@@ -1,17 +1,15 @@
-pv_RandWipe bufferA bufferB wipe trig
-
-Cross fades between two sounds by copying bins in a random order.
+> Sound.SC3.UGen.Help.viewSC3Help "PV_RandWipe"
+> Sound.SC3.UGen.DB.ugenSummary "PV_RandWipe"
 
-bufferA = fft buffer A.  bufferB = fft buffer B.  wipe = copies
-bins from bufferB in a random order (0, 1).  trig = select new
-random ordering.
+> import Sound.SC3.ID
+> import qualified System.Random as R
 
 > withSC3 (\fd -> do { async fd (b_alloc 10 2048 1)
 >                    ; async fd (b_alloc 11 2048 1) })
 
-> let { n0 = randomRs (400.0, 1000.0) (mkStdGen 0)
->     ; n1 = randomRs (80.0, 400.0) (mkStdGen 1)
->     ; n2 = randomRs (0.0, 8.0) (mkStdGen 2)
+> let { n0 = R.randomRs (400.0, 1000.0) (R.mkStdGen 0)
+>     ; n1 = R.randomRs (80.0, 400.0) (R.mkStdGen 1)
+>     ; n2 = R.randomRs (0.0, 8.0) (R.mkStdGen 2)
 >     ; o0 = map (\n -> lfSaw AR n 0 * 0.1) (take 6 n0)
 >     ; o1 = map (\n -> lfPulse AR n 0.0 0.2) (take 6 n1)
 >     ; o2 = map (\n -> sinOsc KR n 0 * 0.2) (take 6 n2)
@@ -19,7 +17,7 @@
 >     ; b = mix (mce (zipWith (\p s -> p * (max s 0.0)) o1 o2))
 >     ; f = fft' 10 a
 >     ; g = fft' 11 b
->     ; x = mouseX KR 0 1 Linear 0.1
->     ; y = mouseY KR 0 1 Linear 0.1 }
-> in do { h <- pv_RandWipe f g x (y >* 0.5)
->       ; audition (out 0 (pan2 (ifft' h) 0 0.5)) }
+>     ; x = mouseX' KR 0 1 Linear 0.1
+>     ; y = mouseY' KR 0 1 Linear 0.1
+>     ; h = pv_RandWipe 'a' f g x (y >* 0.5) }
+> in audition (out 0 (pan2 (ifft' h) 0 0.5))
diff --git a/Help/UGen/FFT/pv_RectComb.help.lhs b/Help/UGen/FFT/pv_RectComb.help.lhs
--- a/Help/UGen/FFT/pv_RectComb.help.lhs
+++ b/Help/UGen/FFT/pv_RectComb.help.lhs
@@ -1,15 +1,18 @@
-pv_RectComb buffer numTeeth phase width
+> Sound.SC3.UGen.Help.viewSC3Help "PV_RectComb"
+> Sound.SC3.UGen.DB.ugenSummary "PV_RectComb"
 
+> import Sound.SC3.ID
+
 > withSC3 (\fd -> async fd (b_alloc 10 2048 1))
 
-> do { n <- whiteNoise AR
->    ; let { x = mouseX KR 0 0.5 Linear 0.1
->          ; y = mouseY KR 0 0.5 Linear 0.1
->          ; c = pv_RectComb (fft' 10 (n * 0.3)) 8 x y }
->      in audition (out 0 (pan2 (ifft' c) 0 1)) }
+> let { n = whiteNoise 'a' AR
+>     ; x = mouseX' KR 0 0.5 Linear 0.1
+>     ; y = mouseY' KR 0 0.5 Linear 0.1
+>     ; c = pv_RectComb (fft' 10 (n * 0.3)) 8 x y }
+> in audition (out 0 (pan2 (ifft' c) 0 1))
 
-> do { n <- whiteNoise AR
->    ; let { p = lfTri KR 0.097 0 *   0.4  + 0.5
->          ; w = lfTri KR 0.240 0 * (-0.5) + 0.5
->          ; c = pv_RectComb (fft' 10 (n * 0.3)) 8 p w }
->      in audition (out 0 (pan2 (ifft' c) 0 1)) }
+> let { n = whiteNoise 'a' AR
+>     ; p = lfTri KR 0.097 0 *   0.4  + 0.5
+>     ; w = lfTri KR 0.240 0 * (-0.5) + 0.5
+>     ; c = pv_RectComb (fft' 10 (n * 0.3)) 8 p w }
+> in audition (out 0 (pan2 (ifft' c) 0 1))
diff --git a/Help/UGen/FFT/pvcollect.help.lhs b/Help/UGen/FFT/pvcollect.help.lhs
--- a/Help/UGen/FFT/pvcollect.help.lhs
+++ b/Help/UGen/FFT/pvcollect.help.lhs
@@ -1,40 +1,24 @@
-pvcollect chain numframes func frombin tobin zeroothers
-
-Process each bin of an FFT chain separately.
-
-pvcollect applies function func to each bin of an FFT chain. func
-should be a function that takes magnitude, phase, index as inputs
-and returns a resulting [magnitude, phase].
-
-The "index" is the integer bin number, starting at 0 for DC. You
-can optionally ignore the phase and only return a single
-(magnitude) value, in which case the phase is assumed to be left
-unchanged.
-
-frombin, tobin, and zeroothers are optional arguments which limit
-the processing to a specified integer range of FFT bins. If
-zeroothers is set to 1 then bins outside of the range being
-processed are silenced.
-
-Note that this procedure can be relatively CPU-heavy, depending on
-how you use it.
+> Sound.SC3.UGen.Help.viewSC3Help "PV_ChainUGen.pvcollect"
+> :t pvcollect
 
-> import Sound.SC3
+> import Sound.SC3.ID
 
-> let fileName = "/home/rohan/audio/metal.wav"
+> let fileName = "/home/rohan/data/audio/pf-c5.snd"
 > in withSC3 (\fd -> do { async fd (b_alloc 10 1024 1)
 >                       ; async fd (b_allocRead 11 fileName 0 0) })
 
-> let { no_op m p _ = (m, p)
->     ; combf m p i = ((modE i 7.0 ==* 0) * m, p)
->     ; spectral_delay m p _ = let { l = lfPar KR 0.5 0
->                                  ; v = linLin l (-1) 1 0.1 1 }
->                              in (m + delayN m 1 v, p)
->     ; nf = 1024
->     ; bpf_sweep m p i = let { l = lfPar KR 0.1 0
->                             ; e = abs (i - (linLin l (-1) 1 2 (nf / 20))) }
->                         in ((e <* 10) * m, p)
->     ; sf = playBuf 1 11 (bufRateScale KR 11) 1 0 Loop DoNothing
->     ; c1 = fft' 10 sf
->     ; c2 = pvcollect c1 nf spectral_delay 0 250 0 }
+> let {no_op m p _ = (m,p)
+>     ;combf m p i = ((fmod i 7.0 ==* 0) * m,p)
+>     ;spectral_delay m p _ =
+>      let {l = lfPar KR 0.5 0
+>          ;v = linLin l (-1) 1 0.1 1}
+>      in (m + delayN m 1 v,p)
+>     ;nf = 1024
+>     ;bpf_sweep m p i =
+>      let {l = lfPar KR 0.1 0
+>          ;e = abs (i - (linLin l (-1) 1 2 (nf / 20)))}
+>      in ((e <* 10) * m,p)
+>     ;sf = playBuf 1 AR 11 (bufRateScale KR 11) 1 0 Loop DoNothing
+>     ;c1 = fft' 10 sf
+>     ;c2 = pvcollect c1 nf spectral_delay 0 250 0}
 > in audition (out 0 (0.1 * ifft' c2))
diff --git a/Help/UGen/Filter/allpassN.help.lhs b/Help/UGen/Filter/allpassN.help.lhs
--- a/Help/UGen/Filter/allpassN.help.lhs
+++ b/Help/UGen/Filter/allpassN.help.lhs
@@ -1,45 +1,34 @@
-allpassN in maxDelayTime delayTime decayTime
+> Sound.SC3.UGen.Help.viewSC3Help "AllpassN"
+> Sound.SC3.UGen.DB.ugenSummary "AllpassN"
 
-All pass delay line. AllpassN uses no interpolation, AllpassL uses
-linear interpolation, AllpassC uses all pass interpolation.  All time
-values are in seconds.  The decay time is the time for the echoes to
-decay by 60 decibels. If this time is negative then the feedback
-coefficient will be negative, thus emphasizing only odd harmonics at
-an octave lower.
+> import Sound.SC3.ID
 
 Since the allpass delay has no audible effect as a resonator on steady
 state sound ...
-
-> import Sound.SC3.ID
-
-> let { dly = xLine KR 0.0001 0.01 20 RemoveSynth
->     ; n = whiteNoise 'a' AR }
+> let {dly = xLine KR 0.0001 0.01 20 RemoveSynth
+>     ;n = whiteNoise 'a' AR}
 > in audition (out 0 (allpassC (n * 0.1) 0.01 dly 0.2))
 
 ...these examples add the input to the effected sound so that you
 can hear the effect of the phase comb.
-
-> let { n = whiteNoise 'a' AR
->     ; dly = xLine KR 0.0001 0.01 20 RemoveSynth }
+> let {n = whiteNoise 'a' AR
+>     ;dly = xLine KR 0.0001 0.01 20 RemoveSynth}
 > in audition (out 0 ((n + allpassN (n * 0.1) 0.01 dly 0.2) * 0.1))
 
 Linear variant
-
-> let { n = whiteNoise 'a' AR
->     ; dly = xLine KR 0.0001 0.01 20 RemoveSynth }
+> let {n = whiteNoise 'a' AR
+>     ;dly = xLine KR 0.0001 0.01 20 RemoveSynth}
 > in audition (out 0 ((n + allpassL (n * 0.1) 0.01 dly 0.2) * 0.1))
 
 Cubic variant
-
-> let { n = whiteNoise 'a' AR
->     ; dly = xLine KR 0.0001 0.01 20 RemoveSynth }
+> let {n = whiteNoise 'a' AR
+>     ;dly = xLine KR 0.0001 0.01 20 RemoveSynth}
 > in audition (out 0 ((n + allpassC (n * 0.1) 0.01 dly 0.2) * 0.1))
 
 Used as an echo - doesn't really sound different than Comb, but it
 outputs the input signal immediately (inverted) and the echoes are
 lower in amplitude.
-
-> let { n = whiteNoise 'a' AR
->     ; d = dust 'a' AR 1
->     ; src = decay (d * 0.5) 0.2 * n }
+> let {n = whiteNoise 'a' AR
+>     ;d = dust 'a' AR 1
+>     ;src = decay (d * 0.5) 0.2 * n}
 > in audition (out 0 (allpassN src 0.2 0.2 3))
diff --git a/Help/UGen/Filter/bBandPass.help.lhs b/Help/UGen/Filter/bBandPass.help.lhs
--- a/Help/UGen/Filter/bBandPass.help.lhs
+++ b/Help/UGen/Filter/bBandPass.help.lhs
@@ -1,13 +1,9 @@
-bBandPass i f bw
-
-
-   i - input signal to be processed
-   f - center frequency
-  bw - the bandwidth in octaves between -3 dB frequencies
+> Sound.SC3.UGen.Help.viewSC3Help "BBandPass"
+> Sound.SC3.UGen.DB.ugenSummary "BBandPass"
 
 > import Sound.SC3
 
 > let { i = soundIn (mce2 0 1)
->     ; f = mouseX KR 20 20000 Exponential 0.2 
->     ; bw = mouseY KR 0 10 Linear 0.2 }
+>     ; f = mouseX' KR 20 20000 Exponential 0.2
+>     ; bw = mouseY' KR 0 10 Linear 0.2 }
 > in audition (out 0 (bBandPass i f bw))
diff --git a/Help/UGen/Filter/bBandStop.help.lhs b/Help/UGen/Filter/bBandStop.help.lhs
--- a/Help/UGen/Filter/bBandStop.help.lhs
+++ b/Help/UGen/Filter/bBandStop.help.lhs
@@ -1,13 +1,14 @@
-bBandStop i f bw
-
-
-   i - input signal to be processed
-   f - center frequency
-  bw - the bandwidth in octaves between -3 dB frequencies
+> Sound.SC3.UGen.Help.viewSC3Help "BBandStop"
+> Sound.SC3.UGen.DB.ugenSummary "BBandStop"
 
 > import Sound.SC3
 
-> let { i = soundIn (mce2 0 1)
->     ; f = mouseX KR 20 20000 Exponential 0.2 
->     ; bw = mouseY KR 0 10 Linear 0.2 }
+> let {i = soundIn (mce2 0 1)
+>     ;f = mouseX' KR 20 20000 Exponential 0.2
+>     ;bw = mouseY' KR 0 10 Linear 0.2}
+> in audition (out 0 (bBandStop i f bw))
+
+> let {i = sinOsc AR 1000 (mce2 0 0)
+>     ;f = mouseX' KR 800 1200 Exponential 0.2
+>     ;bw = mouseY' KR 0 10 Linear 0.2}
 > in audition (out 0 (bBandStop i f bw))
diff --git a/Help/UGen/Filter/bHiPass.help.lhs b/Help/UGen/Filter/bHiPass.help.lhs
--- a/Help/UGen/Filter/bHiPass.help.lhs
+++ b/Help/UGen/Filter/bHiPass.help.lhs
@@ -1,14 +1,9 @@
-bHiPass i f rq
-
-   i - input signal to be processed
-   f - cutoff frequency
-  rq - the reciprocal of Q, ie. bandwidth / cutoffFreq
-
-12db/oct rolloff - 2nd order resonant high pass filter.
+> Sound.SC3.UGen.Help.viewSC3Help "BHiPass"
+> Sound.SC3.UGen.DB.ugenSummary "BHiPass"
 
 > import Sound.SC3
 
 > let { i = soundIn (mce2 0 1)
->     ; f = mouseX KR 10 20000 Exponential 0.2 
->     ; rq = mouseY KR 0 1 Linear 0.2 }
+>     ; f = mouseX' KR 10 20000 Exponential 0.2
+>     ; rq = mouseY' KR 0 1 Linear 0.2 }
 > in audition (out 0 (bHiPass i f rq))
diff --git a/Help/UGen/Filter/bHiShelf.help.lhs b/Help/UGen/Filter/bHiShelf.help.lhs
--- a/Help/UGen/Filter/bHiShelf.help.lhs
+++ b/Help/UGen/Filter/bHiShelf.help.lhs
@@ -1,22 +1,14 @@
-bHiShelf i f rs db
-
-   i - input signal to be processed
-   f - center frequency
-  rs - the reciprocal of S.  Shell boost/cut slope. When S = 1, the
-       shelf slope is as steep as it can be and remain monotonically
-       increasing or decreasing gain with frequency.  The shelf slope,
-       in dB/octave, remains proportional to S for all other values
-       for a fixed freq/SampleRate.ir and db.
-  db - gain. boost/cut the center frequency in decibels.
+> Sound.SC3.UGen.Help.viewSC3Help "BHiShelf"
+> Sound.SC3.UGen.DB.ugenSummary "BHiShelf"
 
 > import Sound.SC3
 
 > let { i = soundIn (mce2 0 1)
->     ; f = mouseX KR 2200 18000 Exponential 0.2 
->     ; db = mouseY KR 18 (-18) Linear 0.2 }
+>     ; f = mouseX' KR 2200 18000 Exponential 0.2
+>     ; db = mouseY' KR 18 (-18) Linear 0.2 }
 > in audition (out 0 (bHiShelf i f 1 db))
 
 > let { i = soundIn (mce2 0 1)
->     ; f = mouseX KR 2200 18000 Exponential 0.2 
->     ; rs = mouseY KR 0.1 1 Linear 0.2 }
+>     ; f = mouseX' KR 2200 18000 Exponential 0.2
+>     ; rs = mouseY' KR 0.1 1 Linear 0.2 }
 > in audition (out 0 (bHiShelf i f rs 6))
diff --git a/Help/UGen/Filter/bLowPass.help.lhs b/Help/UGen/Filter/bLowPass.help.lhs
--- a/Help/UGen/Filter/bLowPass.help.lhs
+++ b/Help/UGen/Filter/bLowPass.help.lhs
@@ -1,30 +1,23 @@
-bLowPass i f rq
-bLowPassCoef sr f rq
-
-   i - input signal to be processed
-  sr - sample rate
-   f - cutoff frequency
-  rq - the reciprocal of Q, ie. bandwidth / cutoffFreq
-
-12db/oct rolloff - 2nd order resonant low pass filter.
+> Sound.SC3.UGen.Help.viewSC3Help "BLowPass"
+> Sound.SC3.UGen.DB.ugenSummary "BLowPass"
+> :t bLowPassCoef
 
-> import Sound.SC3
+> import Sound.SC3.ID
 
 > let { i = soundIn (mce2 0 1)
->     ; f = mouseX KR 10 20000 Exponential 0.2
->     ; rq = mouseY KR 0 1 Linear 0.2 }
+>     ; f = mouseX' KR 10 20000 Exponential 0.2
+>     ; rq = mouseY' KR 0 1 Linear 0.2 }
 > in audition (out 0 (bLowPass i f rq))
 
 > let { i = mix (saw AR (mce [0.99, 1, 1.01] * 440) * 0.3)
->     ; f = mouseX KR 100 20000 Exponential 0.2
->     ; rq = mouseY KR 0.1 1 Linear 0.2 }
+>     ; f = mouseX' KR 100 20000 Exponential 0.2
+>     ; rq = mouseY' KR 0.1 1 Linear 0.2 }
 > in audition (out 0 (bLowPass i f rq))
 
 Calculate coefficients and use sos.
-
 > let { i = mix (saw AR (mce [0.99, 1, 1.01] * 440) * 0.3)
->     ; f = mouseX KR 100 20000 Exponential 0.2
->     ; rq = mouseY KR 0.1 1 Linear 0.2
+>     ; f = mouseX' KR 100 20000 Exponential 0.2
+>     ; rq = mouseY' KR 0.1 1 Linear 0.2
 >     ; (a0, a1, a2, b1, b2) = bLowPassCoef sampleRate f rq
 >     ; flt ip = sos ip a0 a1 a2 b1 b2 }
 > in audition (out 0 (flt (flt i)))
diff --git a/Help/UGen/Filter/bLowShelf.help.lhs b/Help/UGen/Filter/bLowShelf.help.lhs
--- a/Help/UGen/Filter/bLowShelf.help.lhs
+++ b/Help/UGen/Filter/bLowShelf.help.lhs
@@ -1,24 +1,16 @@
-bLowShelf i f rs db
-
-   i - input signal to be processed
-   f - center frequency
-  rs - the reciprocal of S.  Shelf boost/cut slope. When S = 1, the
-       shelf slope is as steep as it can be and remain monotonically
-       increasing or decreasing gain with frequency.  The shelf slope,
-       in dB/octave, remains proportional to S for all other values
-       for a fixed freq/SampleRate.ir and db.
-  db - gain. boost/cut the center frequency in decibels.
+> Sound.SC3.UGen.Help.viewSC3Help "BLowShelf"
+> Sound.SC3.UGen.DB.ugenSummary "BLowShelf"
 
-> import Sound.SC3
+> import Sound.SC3.ID
 
 > let { i = soundIn (mce2 0 1)
->     ; f = mouseX KR 40 6000 Exponential 0.2
+>     ; f = mouseX' KR 40 6000 Exponential 0.2
 >     ; rs = 1
->     ; db = mouseY KR 24 (-24) Linear 0.2 }
+>     ; db = mouseY' KR 24 (-24) Linear 0.2 }
 > in audition (out 0 (bLowShelf i f rs db))
 
 > let { i = soundIn (mce2 0 1)
->     ; f = mouseX KR 20 6000 Exponential 0.2 
->     ; rs = mouseY KR 0.1 1 Linear 0.2 
+>     ; f = mouseX' KR 20 6000 Exponential 0.2
+>     ; rs = mouseY' KR 0.1 1 Linear 0.2
 >     ; db = 6}
 > in audition (out 0 (bLowShelf i f rs db))
diff --git a/Help/UGen/Filter/bPeakEQ.help.lhs b/Help/UGen/Filter/bPeakEQ.help.lhs
--- a/Help/UGen/Filter/bPeakEQ.help.lhs
+++ b/Help/UGen/Filter/bPeakEQ.help.lhs
@@ -1,20 +1,14 @@
-bPeakEQ i f rq db
-
-    i - input signal to be processed
-    f - center frequency
-   rq - the reciprocal of Q, ie.  bandwidth / cutoffFreq
-   db - boost/cut the center frequency (in dBs)
-
-Parametric equalizer.
+> Sound.SC3.UGen.Help.viewSC3Help "BPeakEQ"
+> Sound.SC3.UGen.DB.ugenSummary "BPeakEQ"
 
-> import Sound.SC3
+> import Sound.SC3.ID
 
 > let { i = soundIn (mce2 0 1)
->     ; f = mouseX KR 2200 18000 Exponential 0.2 
->     ; db = mouseY KR 12 (-12) Linear 0.2 }
+>     ; f = mouseX' KR 2200 18000 Exponential 0.2
+>     ; db = mouseY' KR 12 (-12) Linear 0.2 }
 > in audition (out 0 (bPeakEQ i f 0.8 db))
 
 > let { i = soundIn (mce2 0 1)
->     ; f = mouseX KR 2200 18000 Exponential 0.2 
->     ; rq = mouseY KR 10 0.4 Linear 0.2 }
+>     ; f = mouseX' KR 2200 18000 Exponential 0.2
+>     ; rq = mouseY' KR 10 0.4 Linear 0.2 }
 > in audition (out 0 (bPeakEQ i f rq 6))
diff --git a/Help/UGen/Filter/bpf.help.lhs b/Help/UGen/Filter/bpf.help.lhs
--- a/Help/UGen/Filter/bpf.help.lhs
+++ b/Help/UGen/Filter/bpf.help.lhs
@@ -1,17 +1,12 @@
-bpf in freq rq
-
-Second order Butterworth bandpass filter
-
-in    - input signal to be processed
-freq  - cutoff frequency in Hertz
-rq    - the reciprocal of Q, ie. bandwidth / cutoffFreq
+> Sound.SC3.UGen.Help.viewSC3Help "BPF"
+> Sound.SC3.UGen.DB.ugenSummary "BPF"
 
-> import Sound.SC3
+> import Sound.SC3.ID
 
 > let f = fSinOsc KR (xLine KR 0.7 300 20 RemoveSynth) 0 * 3600 + 4000
 > in audition (out 0 (bpf (saw AR 200 * 0.5) f 0.3 ))
 
-> do { n <- whiteNoise AR
->    ; let { x = mouseX KR 220 440 Exponential 0.1
->          ; y = mouseY KR 0.01 0.2 Linear 0.1 }
->      in audition (out 0 (bpf n (mce [x, 550 - x]) y)) }
+> let { n = whiteNoise 'a' AR
+>     ; x = mouseX' KR 220 440 Exponential 0.1
+>     ; y = mouseY' KR 0.01 0.2 Linear 0.1 }
+> in audition (out 0 (bpf n (mce [x, 550 - x]) y))
diff --git a/Help/UGen/Filter/bpz2.help.lhs b/Help/UGen/Filter/bpz2.help.lhs
--- a/Help/UGen/Filter/bpz2.help.lhs
+++ b/Help/UGen/Filter/bpz2.help.lhs
@@ -1,7 +1,7 @@
-bpz2 in
+> Sound.SC3.UGen.Help.viewSC3Help "BPZ2"
+> Sound.SC3.UGen.DB.ugenSummary "BPZ2"
 
-Two zero fixed midpass.  This filter cuts out 0 Hz and the Nyquist
-frequency.
+> import Sound.SC3.ID
 
-> do { n <- whiteNoise AR
->    ; audition (out 0 (bpz2 (n * 0.25))) }
+> let n = whiteNoise 'a' AR
+> in audition (out 0 (bpz2 (n * 0.25)))
diff --git a/Help/UGen/Filter/brf.help.lhs b/Help/UGen/Filter/brf.help.lhs
--- a/Help/UGen/Filter/brf.help.lhs
+++ b/Help/UGen/Filter/brf.help.lhs
@@ -1,6 +1,7 @@
-brf in freq rq
+> Sound.SC3.UGen.Help.viewSC3Help "BRF"
+> Sound.SC3.UGen.DB.ugenSummary "BRF"
 
-Second order Butterworth band reject filter.
+> import Sound.SC3.ID
 
 > let f = fSinOsc KR (xLine KR 0.7 300 20 RemoveSynth) 0 * 3800 + 4000
 > in audition (out 0 (brf (saw AR 200 * 0.1) f 0.3))
diff --git a/Help/UGen/Filter/clip.help.lhs b/Help/UGen/Filter/clip.help.lhs
--- a/Help/UGen/Filter/clip.help.lhs
+++ b/Help/UGen/Filter/clip.help.lhs
@@ -1,6 +1,4 @@
-clip in lo hi
-
-Clip `in' to lie between `lo' and `hi', which are instantiate time
-inputs.
+> Sound.SC3.UGen.Help.viewSC3Help "Clip"
+> Sound.SC3.UGen.DB.ugenSummary "Clip"
 
 > audition (out 0 (clip (sinOsc AR 440 0 * 0.4) (-0.25) 0.25))
diff --git a/Help/UGen/Filter/combC.help.lhs b/Help/UGen/Filter/combC.help.lhs
--- a/Help/UGen/Filter/combC.help.lhs
+++ b/Help/UGen/Filter/combC.help.lhs
@@ -1,1 +1,1 @@
-See combN.
+See combN
diff --git a/Help/UGen/Filter/combL.help.lhs b/Help/UGen/Filter/combL.help.lhs
--- a/Help/UGen/Filter/combL.help.lhs
+++ b/Help/UGen/Filter/combL.help.lhs
@@ -1,1 +1,1 @@
-See combN.
+See combN
diff --git a/Help/UGen/Filter/combN.help.lhs b/Help/UGen/Filter/combN.help.lhs
--- a/Help/UGen/Filter/combN.help.lhs
+++ b/Help/UGen/Filter/combN.help.lhs
@@ -1,36 +1,29 @@
-combN in maxDelayTime delayTime decayTime
+> Sound.SC3.UGen.Help.viewSC3Help "CombN"
+> Sound.SC3.UGen.DB.ugenSummary "CombN"
 
-Comb delay line. CombN uses no interpolation, CombL uses linear
-interpolation, CombC uses all pass interpolation.  All times are in
-seconds.  The decay time is the time for the echoes to decay by 60
-decibels. If this time is negative then the feedback coefficient
-will be negative, thus emphasizing only odd harmonics at an octave
-lower.
+> import Sound.SC3.ID
 
-Comb used as a resonator. The resonant fundamental is equal to
+Comb filter as resonator. The resonant fundamental is equal to
 reciprocal of the delay time.
-
-> do { n <- whiteNoise AR
->    ; let dt = xLine KR 0.0001 0.01 20 RemoveSynth
->      in audition (out 0 (combN (n * 0.1) 0.01 dt 0.2)) }
-
-> do { n <- whiteNoise AR
->    ; let dt = xLine KR 0.0001 0.01 20 RemoveSynth
->      in audition (out 0 (combL (n * 0.1) 0.01 dt 0.2)) }
+> let {n = whiteNoise 'a' AR
+>     ;dt = xLine KR 0.0001 0.01 20 RemoveSynth}
+> in audition (out 0 (combN (n * 0.1) 0.01 dt 0.2))
 
-> do { n <- whiteNoise AR
->    ; let dt = xLine KR 0.0001 0.01 20 RemoveSynth
->      in audition (out 0 (combC (n * 0.1) 0.01 dt 0.2)) }
+> let {n = whiteNoise 'a' AR
+>     ;dt = xLine KR 0.0001 0.01 20 RemoveSynth}
+> in audition (out 0 (combL (n * 0.1) 0.01 dt 0.2))
 
-With negative feedback:
+> let {n = whiteNoise 'a' AR
+>     ;dt = xLine KR 0.0001 0.01 20 RemoveSynth}
+> in audition (out 0 (combC (n * 0.1) 0.01 dt 0.2))
 
-> do { n <- whiteNoise AR
->    ; let dt = xLine KR 0.0001 0.01 20 RemoveSynth
->      in audition (out 0 (combC (n * 0.1) 0.01 dt (-0.2))) }
+With negative feedback
+> let {n = whiteNoise 'a' AR
+>     ;dt = xLine KR 0.0001 0.01 20 RemoveSynth}
+> in audition (out 0 (combC (n * 0.1) 0.01 dt (-0.2)))
 
 Used as an echo.
-
-> do { d <- dust AR 1
->    ; n <- whiteNoise AR
->    ; let i = decay (d * 0.5) 0.2 * n
->      in audition (out 0 (combC i 0.2 0.2 3)) }
+> let {d = dust 'a' AR 1
+>     ;n = whiteNoise 'a' AR
+>     ;i = decay (d * 0.5) 0.2 * n}
+> in audition (out 0 (combC i 0.2 0.2 3))
diff --git a/Help/UGen/Filter/decay.help.lhs b/Help/UGen/Filter/decay.help.lhs
--- a/Help/UGen/Filter/decay.help.lhs
+++ b/Help/UGen/Filter/decay.help.lhs
@@ -1,13 +1,9 @@
-decay in decayTime
+> Sound.SC3.UGen.Help.viewSC3Help "Decay"
+> Sound.SC3.UGen.DB.ugenSummary "Decay"
 
-Exponential decay.  This is essentially the same as Integrator
-except that instead of supplying the coefficient directly, it is
-caculated from a 60 dB decay time. This is the time required for
-the integrator to lose 99.9 % of its value or -60dB. This is useful
-for exponential decaying envelopes triggered by impulses.
+> import Sound.SC3.ID
 
 Used as an envelope.
-
-> do { n <- pinkNoise AR
->    ; let s = impulse AR (xLine KR 1 50 20 RemoveSynth) 0.25
->      in audition (out 0 (decay s 0.2 * n)) }
+> let {n = pinkNoise 'a' AR
+>     ;s = impulse AR (xLine KR 1 50 20 RemoveSynth) 0.25}
+> in audition (out 0 (decay s 0.2 * n))
diff --git a/Help/UGen/Filter/decay2.help.lhs b/Help/UGen/Filter/decay2.help.lhs
--- a/Help/UGen/Filter/decay2.help.lhs
+++ b/Help/UGen/Filter/decay2.help.lhs
@@ -1,19 +1,14 @@
-decay2 in attackTime decayTime
-
-Exponential decay.  Decay has a very sharp attack and can produce
-clicks.  Decay2 rounds off the attack by subtracting one Decay from
-another.
+> Sound.SC3.UGen.Help.viewSC3Help "Decay2"
+> Sound.SC3.UGen.DB.ugenSummary "Decay2"
 
-decay2 AR i a d is equivalent to decay AR i d - decay AR i a
+> import Sound.SC3
 
 Used as an envelope
-
 > let { s = fSinOsc AR 600 0 * 0.25
 >     ; f = xLine KR 1 50 20 RemoveSynth }
 > in audition (out 0 (decay2 (impulse AR f 0) 0.01 0.2 * s))
 
 Compare the above with Decay used as the envelope.
-
 > let { s = fSinOsc AR 600 0 * 0.25
 >     ; f = xLine KR 1 50 20 RemoveSynth }
 > in audition (out 0 (decay (impulse AR f 0) 0.2 * s))
diff --git a/Help/UGen/Filter/degreeToKey.help.lhs b/Help/UGen/Filter/degreeToKey.help.lhs
--- a/Help/UGen/Filter/degreeToKey.help.lhs
+++ b/Help/UGen/Filter/degreeToKey.help.lhs
@@ -1,25 +1,18 @@
-degreeToKey bufnum in octave
-
-Convert signal to modal pitch
-
-The input signal value is truncated to an integer value and used
-as an index into an octave repeating table of note values.
-Indices wrap around the table and shift octaves as they do.
+> Sound.SC3.UGen.Help.viewSC3Help "DegreeToKey"
+> Sound.SC3.UGen.DB.ugenSummary "DegreeToKey"
 
-bufnum - index of the buffer which contains the steps for each
-         scale degree.
-in     - the input signal.
-octave - the number of steps per octave in the scale.
+> import Sound.SC3.ID
 
-> withSC3 (\fd -> do { async fd (b_alloc 0 7 1)
->                    ; send fd (b_setn 0 [(0, [0, 2, 3.2, 5, 7, 9, 10])]) })
+allocate & initialise buffer zero
+> withSC3 (\fd -> async fd (b_alloc_setn1 0 0 [0,2,3.2,5,7,9,10]))
 
-> do { n <- lfNoise1 KR (mce [3, 3.05])
->    ; let { x = mouseX KR 0 15 Linear 0.1
->          ; k = degreeToKey 0 x 12
->          ; f b = let { o = sinOsc AR (midiCPS (b + k + n * 0.04)) 0 * 0.1
->                      ; t = lfPulse AR (midiCPS (mce [48, 55])) 0.15 0.5
->                      ; d = rlpf t (midiCPS (sinOsc KR 0.1 0 * 10 + b)) 0.1 * 0.1
->                      ; m = o + d }
->                  in combN m 0.31 0.31 2 + m }
->      in audition (out 0 ((f 48 + f 72) * 0.25)) }
+modal space, mouse x controls discrete pitch in dorian mode
+> let {n = lfNoise1 'a' KR (mce [3,3.05])
+>     ;x = mouseX' KR 0 15 Linear 0.1
+>     ;k = degreeToKey 0 x 12
+>     ;f b = let {o = sinOsc AR (midiCPS (b + k + n * 0.04)) 0 * 0.1
+>                ;t = lfPulse AR (midiCPS (mce [48,55])) 0.15 0.5
+>                ;d = rlpf t (midiCPS (sinOsc KR 0.1 0 * 10 + b)) 0.1 * 0.1
+>                ;m = o + d}
+>            in combN m 0.31 0.31 2 + m}
+> in audition (out 0 ((f 48 + f 72) * 0.25))
diff --git a/Help/UGen/Filter/delay1.help.lhs b/Help/UGen/Filter/delay1.help.lhs
--- a/Help/UGen/Filter/delay1.help.lhs
+++ b/Help/UGen/Filter/delay1.help.lhs
@@ -1,6 +1,9 @@
-delay1 in
-
-Fixed Single sample delay.
+> Sound.SC3.UGen.Help.viewSC3Help "Delay1"
+> Sound.SC3.UGen.DB.ugenSummary "Delay1"
 
 > let s = impulse AR 1 0
 > in audition (out 0 (s + (delay1 s)))
+
+original, subtract delayed from original
+> let z = dust 'a' AR 1000
+> in audition (out 0 (mce2 z (z - delay1 z)))
diff --git a/Help/UGen/Filter/delay2.help.lhs b/Help/UGen/Filter/delay2.help.lhs
--- a/Help/UGen/Filter/delay2.help.lhs
+++ b/Help/UGen/Filter/delay2.help.lhs
@@ -1,6 +1,7 @@
-delay2 in
+> Sound.SC3.UGen.Help.viewSC3Help "Delay2"
+> Sound.SC3.UGen.DB.ugenSummary "Delay2"
 
-Fixed two sample delay.
+> import Sound.SC3.ID
 
 > let s = impulse AR 1 0
 > in audition (out 0 (s + (delay2 s)))
diff --git a/Help/UGen/Filter/delayC.help.lhs b/Help/UGen/Filter/delayC.help.lhs
--- a/Help/UGen/Filter/delayC.help.lhs
+++ b/Help/UGen/Filter/delayC.help.lhs
@@ -1,1 +1,1 @@
-See delayN.
+See delayN
diff --git a/Help/UGen/Filter/delayL.help.lhs b/Help/UGen/Filter/delayL.help.lhs
--- a/Help/UGen/Filter/delayL.help.lhs
+++ b/Help/UGen/Filter/delayL.help.lhs
@@ -1,1 +1,1 @@
-See delayN.
+See delayN
diff --git a/Help/UGen/Filter/delayN.help.lhs b/Help/UGen/Filter/delayN.help.lhs
--- a/Help/UGen/Filter/delayN.help.lhs
+++ b/Help/UGen/Filter/delayN.help.lhs
@@ -1,25 +1,19 @@
-delayN in maxDelayTime delayTime
-
-Simple delay line.  There are three forms, delayN uses no
-interpolation, delayL uses linear interpolation, delayA uses
-all pass interpolation.  The maximum delay length is set at
-initialization time and cannot be extended.
-
-Dust randomly triggers Decay to create an exponential decay
-envelope for the WhiteNoise input source.  The input is
-mixed with the delay.
+> Sound.SC3.UGen.Help.viewSC3Help "DelayN"
+> Sound.SC3.UGen.DB.ugenSummary "DelayN"
 
-> do { d <- dust AR 1
->    ; n <- whiteNoise AR
->    ; let { z = decay d 0.3 * n
->          ; x = mouseX KR 0.0 0.2 Linear 0.1 }
->      in audition (out 0 (z + delayN z 0.2 x)) }
+> import Sound.SC3.ID
 
-The delay time can be varied at control rate.
-An oscillator either reinforcing or cancelling
-with the delayed copy of itself.
+Dust randomly triggers Decay to create an exponential decay envelope
+for the WhiteNoise input source.  The input is mixed with the delay.
+> let {d = dust 'a' AR 1
+>     ;n = whiteNoise 'b' AR
+>     ;z = decay d 0.3 * n
+>     ;x = mouseX' KR 0.0 0.2 Linear 0.1}
+> in audition (out 0 (z + delayN z 0.2 x))
 
+The delay time can be varied at control rate.  An oscillator either
+reinforcing or cancelling with the delayed copy of itself.
 > let { o = sinOsc AR 320 0 * 0.1
 >     ; l = 0.005
->     ; x = mouseX KR 0.0 l Linear 0.15 }
+>     ; x = mouseX' KR 0.0 l Linear 0.15 }
 > in audition (out 0 (o + delayN o l x))
diff --git a/Help/UGen/Filter/formlet.help.lhs b/Help/UGen/Filter/formlet.help.lhs
--- a/Help/UGen/Filter/formlet.help.lhs
+++ b/Help/UGen/Filter/formlet.help.lhs
@@ -1,6 +1,7 @@
-formlet in freq attackTime decayTime
+> Sound.SC3.UGen.Help.viewSC3Help "Formlet"
+> Sound.SC3.UGen.DB.ugenSummary "Formlet"
 
-FOF-like filter
+> import Sound.SC3.ID
 
 > audition (out 0 (formlet (impulse AR 20 0.5) 1000 0.01 0.1))
 
@@ -8,6 +9,6 @@
 > in audition (out 0 (formlet (blip AR f 1000 * 0.1) 1000 0.01 0.1))
 
 Modulating formant frequency.
-
-> let s = blip AR (sinOsc KR 5 0 * 20 + 300) 1000 * 0.1
-> in audition (out 0 (formlet s (xLine KR 1500 700 8 RemoveSynth) 0.005 0.04))
+> let {s = blip AR (sinOsc KR 5 0 * 20 + 300) 1000 * 0.1
+>     ;ff = xLine KR 1500 700 8 RemoveSynth}
+> in audition (out 0 (formlet s ff 0.005 0.04))
diff --git a/Help/UGen/Filter/fos.help.lhs b/Help/UGen/Filter/fos.help.lhs
--- a/Help/UGen/Filter/fos.help.lhs
+++ b/Help/UGen/Filter/fos.help.lhs
@@ -1,13 +1,12 @@
-fos in a0 a1 b1
+> Sound.SC3.UGen.Help.viewSC3Help "FOS"
+> Sound.SC3.UGen.DB.ugenSummary "FOS"
 
-First order filter section.
+> import Sound.SC3.ID
 
 Same as OnePole.
-
 > let x = lfTri AR 0.4 0 * 0.99
 > in audition (out 0 (fos (lfSaw AR 200 0 * 0.2) (1 - (abs x)) 0 x))
 
 Same as OneZero
-
 > let x = lfTri AR 0.4 0 * 0.99
 > in audition (out 0 (fos (lfSaw AR 200 0 * 0.2) (1 - (abs x)) x 0))
diff --git a/Help/UGen/Filter/freeVerb.help.lhs b/Help/UGen/Filter/freeVerb.help.lhs
--- a/Help/UGen/Filter/freeVerb.help.lhs
+++ b/Help/UGen/Filter/freeVerb.help.lhs
@@ -1,24 +1,20 @@
-freeVerb in mix room damp
-freeVerb2 in1 in2 mix room damp
-
-A simple reverb.
+> Sound.SC3.UGen.Help.viewSC3Help "FreeVerb"
+> Sound.SC3.UGen.DB.ugenSummary "FreeVerb"
 
- in, in1, in2 - input signal
-          mix - dry/wet balance (0,1)
-         room - room size (0,1)
-         damp - reverb high frequency damping (0,1)
+> import Sound.SC3
 
-> let { i = impulse AR 1 0
->     ; c = lfCub AR 1200 0
->     ; s = decay i 0.25 * c * 0.1
->     ; x = mouseX KR 0 1 Linear 0.1
->     ; y = mouseY KR 0 1 Linear 0.1
->     ; r = freeVerb s y x 0.5 }
+> let {i = impulse AR 1 0
+>     ;c = lfCub AR 1200 0
+>     ;s = decay i 0.25 * c * 0.1
+>     ;x = mouseX' KR 0 1 Linear 0.1
+>     ;y = mouseY' KR 0 1 Linear 0.1
+>     ;r = freeVerb s y x 0.5}
 > in audition (out 0 r)
 
-> let { i = soundIn (mce2 0 1)
->     ; c = mceChannel
->     ; x = mouseX KR 0 1 Linear 0.1
->     ; y = mouseY KR 0 1 Linear 0.1
->     ; r = freeVerb2 (c 0 i) (c 1 i) y x 0.5 }
+Process input channels
+> let {i = soundIn (mce2 0 1)
+>     ;c = mceChannel
+>     ;x = mouseX' KR 0 1 Linear 0.1
+>     ;y = mouseY' KR 0 1 Linear 0.1
+>     ;r = freeVerb2 (c 0 i) (c 1 i) y x 0.5}
 > in audition (out 0 r)
diff --git a/Help/UGen/Filter/freqShift.help.lhs b/Help/UGen/Filter/freqShift.help.lhs
--- a/Help/UGen/Filter/freqShift.help.lhs
+++ b/Help/UGen/Filter/freqShift.help.lhs
@@ -1,40 +1,28 @@
-freqShift input shift phase
-
-Single sideband amplitude modulation, also known as frequency
-shifting, but not to be confused with pitch shifting.  Frequency
-shifting moves all the components of a signal by a fixed amount but
-does not preserve the original harmonic relationships.
-
-   input - audio input
-   shift - amount of shift in cycles per second
-   phase - phase of the frequency shift (0 - 2pi)
+> Sound.SC3.UGen.Help.viewSC3Help "FreqShift"
+> Sound.SC3.UGen.DB.ugenSummary "FreqShift"
 
-> import Sound.SC3
+> import Sound.SC3.ID
 
 shifting a 100Hz tone by 1 Hz rising to 500Hz
-
-> let { i = sinOsc AR 100 0
->     ; s = xLine KR 1 500 5 RemoveSynth }
+> let {i = sinOsc AR 100 0
+>     ;s = xLine KR 1 500 5 RemoveSynth}
 > in audition (out 0 (freqShift i s 0 * 0.1))
 
 shifting a complex tone by 1 Hz rising to 500Hz
-
-> let { d = klangSpec [101, 303, 606, 808] [1, 1, 1, 1] [1, 1, 1, 1]
->     ; i = klang AR 1 0 d
->     ; s = xLine KR 1 500 5 RemoveSynth }
+> let {d = klangSpec [101, 303, 606, 808] [1, 1, 1, 1] [1, 1, 1, 1]
+>     ;i = klang AR 1 0 d
+>     ;s = xLine KR 1 500 5 RemoveSynth}
 > in audition (out 0 (freqShift i s 0 * 0.1))
 
 modulating shift and phase
-
-> do { s <- lfNoise2 AR 0.3
->    ; let { i = sinOsc AR 10 0
->          ; p = linLin (sinOsc AR 500 0) (-1) 1 0 (2 * pi) }
->      in audition (out 0 (freqShift i (s * 1500) p * 0.1)) }
+> let {s = lfNoise2 'a' AR 0.3
+>     ;i = sinOsc AR 10 0
+>     ;p = linLin (sinOsc AR 500 0) (-1) 1 0 (2 * pi)}
+> in audition (out 0 (freqShift i (s * 1500) p * 0.1))
 
 shifting bandpassed noise
-
-> do { n1 <- whiteNoise AR
->    ; n2 <- lfNoise0 AR 5.5
->    ; let { i = bpf n1 1000 0.001
->          ; s = n2 * 1000 }
->      in audition (out 0 (freqShift i s 0 * 32)) }
+> let {n1 = whiteNoise 'a' AR
+>     ;n2 = lfNoise0 'a' AR 5.5
+>     ;i = bpf n1 1000 0.001
+>     ;s = n2 * 1000}
+> in audition (out 0 (freqShift i s 0 * 32))
diff --git a/Help/UGen/Filter/gVerb.help.lhs b/Help/UGen/Filter/gVerb.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Filter/gVerb.help.lhs
@@ -0,0 +1,10 @@
+> Sound.SC3.UGen.Help.viewSC3Help "GVerb"
+> Sound.SC3.UGen.DB.ugenSummary "GVerb"
+
+> import Sound.SC3.ID
+
+> let {i = impulse AR 1 0
+>     ;c = lfCub AR 1200 0
+>     ;s = decay i 0.25 * c * 0.1
+>     ;r = gVerb s 10 3 0.5 0.5 15 1 0.7 0.5 300}
+> in audition (out 0 r)
diff --git a/Help/UGen/Filter/hasher.help.lhs b/Help/UGen/Filter/hasher.help.lhs
--- a/Help/UGen/Filter/hasher.help.lhs
+++ b/Help/UGen/Filter/hasher.help.lhs
@@ -1,8 +1,12 @@
-hasher in
+> Sound.SC3.UGen.Help.viewSC3Help "Hasher"
+> Sound.SC3.UGen.DB.ugenSummary "Hasher"
 
-Returns a unique output value from zero to one for each input value
-according to a hash function. The same input value will always
-produce the same output value. The input need not be from zero to
-one.
+> import Sound.SC3.ID
 
+noise
 > audition (out 0 (hasher (line AR 0 1 1 RemoveSynth) * 0.2))
+
+remap x
+> let {x = mouseX' KR 0 10 Linear 0.2
+>     ;f = hasher (roundTo x 1) * 300 + 500}
+> in audition (out 0 (sinOsc AR f 0 * 0.1))
diff --git a/Help/UGen/Filter/hpf.help.lhs b/Help/UGen/Filter/hpf.help.lhs
--- a/Help/UGen/Filter/hpf.help.lhs
+++ b/Help/UGen/Filter/hpf.help.lhs
@@ -1,6 +1,7 @@
-hpf in freq
+> Sound.SC3.UGen.Help.viewSC3Help "HPF"
+> Sound.SC3.UGen.DB.ugenSummary "HPF"
 
-Second order Butterworth highpass filter.
+> import Sound.SC3.ID
 
 > let f = fSinOsc KR (xLine KR 0.7 300 20 RemoveSynth) 0 * 3600 + 4000
 > in audition (out 0 (hpf (saw AR 200 * 0.2) f))
diff --git a/Help/UGen/Filter/hpz1.help.lhs b/Help/UGen/Filter/hpz1.help.lhs
--- a/Help/UGen/Filter/hpz1.help.lhs
+++ b/Help/UGen/Filter/hpz1.help.lhs
@@ -1,6 +1,7 @@
-hpz1 in
+> Sound.SC3.UGen.Help.viewSC3Help "HPZ1"
+> Sound.SC3.UGen.DB.ugenSummary "HPZ1"
 
-Two point difference filter.
+> import Sound.SC3.ID
 
-> do { n <- whiteNoise AR
->    ; audition (out 0 (hpz1 (n * 0.25))) }
+> let n = whiteNoise 'a' AR
+> in audition (out 0 (hpz1 (n * 0.25)))
diff --git a/Help/UGen/Filter/hpz2.help.lhs b/Help/UGen/Filter/hpz2.help.lhs
--- a/Help/UGen/Filter/hpz2.help.lhs
+++ b/Help/UGen/Filter/hpz2.help.lhs
@@ -1,6 +1,7 @@
-hpz2 in
+> Sound.SC3.UGen.Help.viewSC3Help "HPZ2"
+> Sound.SC3.UGen.DB.ugenSummary "HPZ2"
 
-Two zero fixed highpass filter.
+> import Sound.SC3.ID
 
-> do { n <- whiteNoise AR
->    ; audition (out 0 (hpz2 (n * 0.25))) }
+> let n = whiteNoise 'a' AR
+> in audition (out 0 (hpz2 (n * 0.25)))
diff --git a/Help/UGen/Filter/klank.help.lhs b/Help/UGen/Filter/klank.help.lhs
--- a/Help/UGen/Filter/klank.help.lhs
+++ b/Help/UGen/Filter/klank.help.lhs
@@ -1,39 +1,33 @@
-klank in freqScale freqOffset decayScale spec
-
-Klank is a bank of fixed frequency resonators which can be used to
-simulate the resonant modes of an object. Each mode is given a ring
-time, which is the time for the mode to decay by 60 dB.
-
-The UGen assistant Klank.spec can help create the 'spec' entry.
-Note that the SC3 language reorders the inputs, the Hsc client does
-not.
-
-input - the excitation input to the resonant filter bank.
-
-freqscale - a scale factor multiplied by all frequencies at
-            initialization time.
+> Sound.SC3.UGen.Help.viewSC3Help "Klank"
+> Sound.SC3.UGen.DB.ugenSummary "Klank"
 
-freqoffset - an offset added to all frequencies at initialization
-             time.
+# SC3
+SC3 reorders the inputs, hsc3 does not.
 
-decayscale - a scale factor multiplied by all ring times at
-             initialization time.
+# hsc3
+The function klankSpec can help create the 'spec' entry.
 
 > import Sound.SC3
 
-> let s = klankSpec [800, 1071, 1153, 1723] [1, 1, 1, 1] [1, 1, 1, 1]
+> let s = klankSpec [800,1071,1153,1723] [1,1,1,1] [1,1,1,1]
 > in audition (out 0 (klank (impulse AR 2 0 * 0.1) 1 0 1 s))
 
-There is a limited form of multiple channel expansion possible
-at 'specification' input, below three equal dimensional 
-specifications are tranposed and force expansion in a sensible manner.
+A variant spec function takes non-UGen inputs
+> let {f = [800::Double,1071,1153,1723]
+>     ;u = [1,1,1,1]
+>     ;s = klankSpec' f u u}
+> in audition (out 0 (klank (impulse AR 2 0 * 0.1) 1 0 1 s))
 
-> let { u = [1, 1, 1, 1]
->     ; p = [200, 171, 153, 172]
->     ; q = [930, 971, 953, 1323]
->     ; r = [8900, 16062, 9013, 7892]
->     ; k = mce [klankSpec p u u, klankSpec q u u, klankSpec r u u]
+There is a limited form of multiple channel expansion possible at
+'specification' input, below three equal dimensional specifications
+are transposed and force expansion in a sensible manner.
+> let { u = [1,1,1,1]
+>     ; p = [200,171,153,172]
+>     ; q = [930,971,953,1323]
+>     ; r = [8900,16062,9013,7892]
+>     ; k = mce [klankSpec' p u u,klankSpec' q u u,klankSpec' r u u]
 >     ; s = mceTranspose k
->     ; i = mce [2, 2.07, 2.13]
->     ; t = impulse AR i 0 * 0.1 }
-> in audition (out 0 (mix (klank t 1 0 1 s)))
+>     ; i = mce [2,2.07,2.13]
+>     ; t = impulse AR i 0 * 0.1
+>     ; l = mce [-1,0,1] }
+> in audition (out 0 (mix (pan2 (klank t 1 0 1 s) l 1)))
diff --git a/Help/UGen/Filter/lag.help.lhs b/Help/UGen/Filter/lag.help.lhs
--- a/Help/UGen/Filter/lag.help.lhs
+++ b/Help/UGen/Filter/lag.help.lhs
@@ -1,6 +1,8 @@
-lag in lagTime
+> Sound.SC3.UGen.Help.viewSC3Help "Lag"
+> Sound.SC3.UGen.DB.ugenSummary "Lag"
 
-A simple averaging filter.
+> import Sound.SC3
 
-> let x = mouseX KR 220 440 Linear 0.2
+used to lag pitch
+> let x = mouseX' KR 220 440 Linear 0.2
 > in audition (out 0 (sinOsc AR (mce [x, lag x 1]) 0 * 0.1))
diff --git a/Help/UGen/Filter/lag2.help.lhs b/Help/UGen/Filter/lag2.help.lhs
--- a/Help/UGen/Filter/lag2.help.lhs
+++ b/Help/UGen/Filter/lag2.help.lhs
@@ -1,6 +1,7 @@
-lag2 in lagTime
+> Sound.SC3.UGen.Help.viewSC3Help "Lag2"
+> Sound.SC3.UGen.DB.ugenSummary "Lag2"
 
-Lag2 is the same as lag KR (lag KR s t) t.
+> import Sound.SC3
 
-> let x = mouseX KR 220 440 Exponential 0.1
+> let x = mouseX' KR 220 440 Exponential 0.1
 > in audition (out 0 (sinOsc AR (mce [x, lag2 x 1]) 0 * 0.1))
diff --git a/Help/UGen/Filter/lag3.help.lhs b/Help/UGen/Filter/lag3.help.lhs
--- a/Help/UGen/Filter/lag3.help.lhs
+++ b/Help/UGen/Filter/lag3.help.lhs
@@ -1,6 +1,7 @@
-lag3 in lagTime
+> Sound.SC3.UGen.Help.viewSC3Help "Lag3"
+> Sound.SC3.UGen.DB.ugenSummary "Lag3"
 
-Lag3 is the same as lag KR (lag KR (lag KT s t) t) t.
+> import Sound.SC3
 
-> let x = mouseX KR 220 440 Exponential 0.1
+> let x = mouseX' KR 220 440 Exponential 0.1
 > in audition (out 0 (sinOsc AR (mce [x, lag3 x 1]) 0 * 0.1))
diff --git a/Help/UGen/Filter/latch.help.lhs b/Help/UGen/Filter/latch.help.lhs
--- a/Help/UGen/Filter/latch.help.lhs
+++ b/Help/UGen/Filter/latch.help.lhs
@@ -1,26 +1,21 @@
-latch in trig
-
-Sample and hold. Holds input signal value when triggered.
+> Sound.SC3.UGen.Help.viewSC3Help "Latch"
+> Sound.SC3.UGen.DB.ugenSummary "Latch"
 
-in   - input signal.
-trig - trigger. The trigger can be any signal. A trigger happens when the
-       signal changes from non-positive to positive.
+> import Sound.SC3.Monadic
 
-> do { n <- whiteNoise AR
->    ; let { i = impulse AR 9 0
->          ; l = latch n i }
->      in audition (out 0 (blip AR (l * 400 + 500) 4 * 0.2)) }
+> do {n <- whiteNoise AR
+>    ;let {i = impulse AR 9 0
+>         ;l = latch n i}
+>     in audition (out 0 (blip AR (l * 400 + 500) 4 * 0.2))}
 
 The above is just meant as example. LFNoise0 is a faster way to
 generate random steps :
-
-> do { n <- lfNoise0 KR 9
->    ; audition (out 0 (blip AR (n * 400 + 500) 4 * 0.2)) }
+> do {n <- lfNoise0 KR 9
+>    ;audition (out 0 (blip AR (n * 400 + 500) 4 * 0.2))}
 
 http://create.ucsb.edu/pipermail/sc-users/2006-December/029991.html
-
-> do { n0 <- lfNoise2 KR 8
->    ; n1 <- lfNoise2 KR 3
->    ; let { s = blip AR (n0 * 200 + 300) (n1 * 10 + 20)
->          ; x = mouseX KR 1000 (sampleRate * 0.1) Exponential 0.1 }
->      in audition (out 0 (latch s (impulse AR x 0))) }
+> do {n0 <- lfNoise2 KR 8
+>    ;n1 <- lfNoise2 KR 3
+>    ;let {s = blip AR (n0 * 200 + 300) (n1 * 10 + 20)
+>         ;x = mouseX' KR 1000 (sampleRate * 0.1) Exponential 0.1}
+>     in audition (out 0 (latch s (impulse AR x 0)))}
diff --git a/Help/UGen/Filter/leakDC.help.lhs b/Help/UGen/Filter/leakDC.help.lhs
--- a/Help/UGen/Filter/leakDC.help.lhs
+++ b/Help/UGen/Filter/leakDC.help.lhs
@@ -1,7 +1,7 @@
-leakDC in coef
+> Sound.SC3.UGen.Help.viewSC3Help "LeakDC"
+> Sound.SC3.UGen.DB.ugenSummary "LeakDC"
 
-Remove DC.  This filter removes a DC offset from a signal.  in -
-input signal.  coef - leak coefficient.
+> import Sound.SC3
 
-> let a = lfPulse AR 800 0.5 0.5 * 0.1
-> in audition (out 0 (mce [a, leakDC a 0.995]))
+> let a = lfPulse AR 800 0 0.5 * 0.1 + 0.5
+> in audition (out 0 (mce [a,leakDC a 0.995]))
diff --git a/Help/UGen/Filter/limiter.help.lhs b/Help/UGen/Filter/limiter.help.lhs
--- a/Help/UGen/Filter/limiter.help.lhs
+++ b/Help/UGen/Filter/limiter.help.lhs
@@ -1,7 +1,14 @@
-limiter input level lookAheadTime
+> Sound.SC3.UGen.Help.viewSC3Help "Limiter"
+> Sound.SC3.UGen.DB.ugenSummary "Limiter"
 
-Peak limiter.  Limits the input amplitude to the given
-level. Limiter will not overshoot like Compander will, but it needs
-to look ahead in the audio. Thus there is a delay equal to twice
-the lookAheadTime.  Limiter, unlike Compander, is completely
-transparent for an in range signal.
+> import Sound.SC3
+
+example signal
+> let z = let i = impulse AR 8 0 * lfSaw KR 0.25 0 * (-0.6) + 0.7
+>         in decay2 i 0.001 0.3 * fSinOsc AR 500 0
+
+unprocessed
+> audition (out 0 z)
+
+limited
+> audition (out 0 (limiter z 0.4 0.01))
diff --git a/Help/UGen/Filter/linExp.help.lhs b/Help/UGen/Filter/linExp.help.lhs
--- a/Help/UGen/Filter/linExp.help.lhs
+++ b/Help/UGen/Filter/linExp.help.lhs
@@ -1,20 +1,11 @@
-linExp in srclo srchi dstlo dsthi
-
-Map a linear range to an exponential range.  The dstlo and dsthi
-arguments must be nonzero and have the same sign.
-
-in    - input to convert.
-srclo - lower limit of input range.
-srchi - upper limit of input range.
-dstlo - lower limit of output range.
-dsthi - upper limit of output range.
+> Sound.SC3.UGen.Help.viewSC3Help "LinExp"
+> Sound.SC3.UGen.DB.ugenSummary "LinExp"
 
-> let f = linExp (mouseX KR 0 1 Linear 0.2) 0 1 440 660
+> let f = linExp (mouseX' KR 0 1 Linear 0.2) 0 1 440 660
 > in audition (out 0 (sinOsc AR f 0 * 0.1))
 
 The destination range may be k-rate.
-
-> let { x = mouseX KR 0 1 Linear 0.2
->     ; y = mouseY KR 220 440 Linear 0.2
->     ; f = linExp x 0 1 y 660 }
+> let {x = mouseX' KR 0 1 Linear 0.2
+>     ;y = mouseY' KR 220 440 Linear 0.2
+>     ;f = linExp x 0 1 y 660}
 > in audition (out 0 (sinOsc AR f 0 * 0.1))
diff --git a/Help/UGen/Filter/linLin.help.lhs b/Help/UGen/Filter/linLin.help.lhs
--- a/Help/UGen/Filter/linLin.help.lhs
+++ b/Help/UGen/Filter/linLin.help.lhs
@@ -1,19 +1,20 @@
-linLin in srclo srchi dstlo dsthi
-
-Map a linear range to another linear range.
+> Sound.SC3.UGen.Help.viewSC3Help "LinLin"
+> Sound.SC3.UGen.DB.ugenSummary "LinLin"
 
-in    - input to convert.
-srclo - lower limit of input range.
-srchi - upper limit of input range.
-dstlo - lower limit of output range.
-dsthi - upper limit of output range.
+> import Sound.SC3
 
-> let f = linLin (mouseX KR 0 1 Linear 0.2) 0 1 440 660
+> let f = linLin (mouseX' KR 0 1 Linear 0.2) 0 1 440 660
 > in audition (out 0 (sinOsc AR f 0 * 0.1))
 
 The destination range may be k-rate.
-
-> let { x = mouseX KR 0 1 Linear 0.2
->     ; y = mouseY KR 220 440 Linear 0.2
+> let { x = mouseX' KR 0 1 Linear 0.2
+>     ; y = mouseY' KR 220 440 Linear 0.2
 >     ; f = linLin x 0 1 y 660 }
+> in audition (out 0 (sinOsc AR f 0 * 0.1))
+
+Modulating source and destination values.
+> let {n = lfNoise2 'a' AR 80
+>     ;x = mouseX' KR 200 8000 Linear 0.2
+>     ;y = mouseY' KR 200 8000 Linear 0.2
+>     ;f = linLin n (sinOsc KR 0.2 0) (sinOsc KR 0.2543 0) x y}
 > in audition (out 0 (sinOsc AR f 0 * 0.1))
diff --git a/Help/UGen/Filter/lpf.help.lhs b/Help/UGen/Filter/lpf.help.lhs
--- a/Help/UGen/Filter/lpf.help.lhs
+++ b/Help/UGen/Filter/lpf.help.lhs
@@ -1,11 +1,12 @@
-lpf in freq
+> Sound.SC3.UGen.Help.viewSC3Help "LPF"
+> Sound.SC3.UGen.DB.ugenSummary "LPF"
 
-Second order Butterworth lowpass filter.
+> import Sound.SC3
 
-> let f = xLine KR 0.7 300 20 RemoveSynth
-> in audition (out 0 (lpf (saw AR 200 * 0.1) (fSinOsc KR f 0 * 3600 + 4000)))
+> let {f = xLine KR 0.7 300 20 RemoveSynth
+>     ;ff = fSinOsc KR f 0 * 3600 + 4000}
+> in audition (out 0 (lpf (saw AR 200 * 0.1) ff))
 
 Control rate filtering.
-
-> let ctl = lpf (lfPulse KR 8 0 0.5) (mouseX KR 2 50 Exponential 0.1)
+> let ctl = lpf (lfPulse KR 8 0 0.5) (mouseX' KR 2 50 Exponential 0.1)
 > in audition (out 0 (sinOsc AR (ctl * 200 + 400) 0 * 0.1))
diff --git a/Help/UGen/Filter/lpz1.help.lhs b/Help/UGen/Filter/lpz1.help.lhs
--- a/Help/UGen/Filter/lpz1.help.lhs
+++ b/Help/UGen/Filter/lpz1.help.lhs
@@ -1,6 +1,7 @@
-lpz1 in
+> Sound.SC3.UGen.Help.viewSC3Help "LPZ1"
+> Sound.SC3.UGen.DB.ugenSummary "LPZ1"
 
-Two point average filter
+> import Sound.SC3.ID
 
-> do { n <- whiteNoise AR
->    ; audition (out 0 (lpz1 (n * 0.25))) }
+> let n = whiteNoise 'a' AR * 0.1
+> in audition (out 0 (mce2 n (lpz1 n)))
diff --git a/Help/UGen/Filter/lpz2.help.lhs b/Help/UGen/Filter/lpz2.help.lhs
--- a/Help/UGen/Filter/lpz2.help.lhs
+++ b/Help/UGen/Filter/lpz2.help.lhs
@@ -1,6 +1,7 @@
-lpz2 in
+> Sound.SC3.UGen.Help.viewSC3Help "LPZ2"
+> Sound.SC3.UGen.DB.ugenSummary "LPZ2"
 
-Two zero fixed lowpass filter
+> import Sound.SC3.ID
 
-> do { n <- whiteNoise AR
->    ; audition (out 0 (lpz2 (n * 0.25))) }
+> let n = whiteNoise 'a' AR
+> in audition (out 0 (lpz2 (n * 0.25)))
diff --git a/Help/UGen/Filter/mantissaMask.help.lhs b/Help/UGen/Filter/mantissaMask.help.lhs
--- a/Help/UGen/Filter/mantissaMask.help.lhs
+++ b/Help/UGen/Filter/mantissaMask.help.lhs
@@ -1,11 +1,7 @@
-mantissaMask in bits
-
-Masks off bits in the mantissa of the floating point sample
-value. This introduces a quantization noise, but is less severe
-than linearly quantizing the signal.
+> Sound.SC3.UGen.Help.viewSC3Help "MantissaMask"
+> Sound.SC3.UGen.DB.ugenSummary "MantissaMask"
 
-in - input signal
-bits - the number of mantissa bits to preserve. a number from 0 to 23.
+> import Sound.SC3
 
 > let s = sinOsc AR (sinOsc KR 0.2 0 * 400 + 500) 0 * 0.4
 > in audition (out 0 (mantissaMask s 3))
diff --git a/Help/UGen/Filter/median.help.lhs b/Help/UGen/Filter/median.help.lhs
--- a/Help/UGen/Filter/median.help.lhs
+++ b/Help/UGen/Filter/median.help.lhs
@@ -1,25 +1,22 @@
-median length in
+> Sound.SC3.UGen.Help.viewSC3Help "Median"
+> Sound.SC3.UGen.DB.ugenSummary "Median"
 
-Median filter.
+> import Sound.SC3.ID
 
 Signal with impulse noise.
-
-> do { n <- dust2 AR 100
->    ; audition (out 0 (median 3 (saw AR 500 * 0.1 + n * 0.9))) }
+> let n = dust2 'a' AR 100
+> in audition (out 0 (median 3 (saw AR 500 * 0.1 + n * 0.9)))
 
 The median length can be increased for longer duration noise.
-
-> do { n <- dust2 AR 100
->    ; audition (out 0 (median 5 (saw AR 500 * 0.1 + lpz1 (n * 0.9)))) }
+> let n = dust2 'a' AR 100
+> in audition (out 0 (median 5 (saw AR 500 * 0.1 + lpz1 (n * 0.9))))
 
 Long Median filters begin chopping off the peaks of the waveform
-
 > let x = sinOsc AR 1000 0 * 0.2
 > in audition (out 0 (mce [x, median 31 x]))
 
 Another noise reduction application. Use Median filter for high
 frequency noise.  Use LeakDC for low frequency noise.
-
-> do { n <- whiteNoise AR
->    ; let s = median 31 (n * 0.1 + sinOsc AR 800 0 * 0.1)
->      in audition (out 0 (leakDC s 0.9)) }
+> let {n = whiteNoise 'a' AR
+>     ;s = median 31 (n * 0.1 + sinOsc AR 800 0 * 0.1)}
+> in audition (out 0 (leakDC s 0.9))
diff --git a/Help/UGen/Filter/midEQ.help.lhs b/Help/UGen/Filter/midEQ.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Filter/midEQ.help.lhs
@@ -0,0 +1,11 @@
+> Sound.SC3.UGen.Help.viewSC3Help "MidEQ"
+> Sound.SC3.UGen.DB.ugenSummary "MidEQ"
+
+> import Sound.SC3.ID
+
+> let f = midiCPS (fSinOsc KR 1 0 * 24 + 84)
+> in audition (out 0 (midEQ (saw AR 200 * 0.2) f 0.3 12))
+
+> let {i = pinkNoise 'a' AR * 0.2 + sinOsc AR 600 0 * 0.1
+>     ;f = sinOsc KR 0.2 (0.5 * pi) * 2 + 600}
+> in audition (out 0 (midEQ i f 0.01 (-24)))
diff --git a/Help/UGen/Filter/moogFF.help.lhs b/Help/UGen/Filter/moogFF.help.lhs
--- a/Help/UGen/Filter/moogFF.help.lhs
+++ b/Help/UGen/Filter/moogFF.help.lhs
@@ -1,36 +1,22 @@
-moogFF in freq gain reset
-
-Moog VCF implementation, designed by Federico Fontana. A digital
-implementation of the Moog VCF (filter).
-
-     in - the input signal
-   freq - the cutoff frequency
-   gain - the filter resonance gain, between zero and 4
-  reset - when greater than zero, this will reset the
-          state of the digital filters at the beginning
-          of a computational block.
-
-The design of this filter is described in the conference paper
-Fontana, F. (2007) Preserving the Digital Structure of the Moog
-VCF. In Proc. ICMC07, Copenhagen, 25-31 August 2007
+> Sound.SC3.UGen.Help.viewSC3Help "MoogFF"
+> Sound.SC3.UGen.DB.ugenSummary "MoogFF"
 
-> import Sound.SC3
+> import Sound.SC3.ID
 
-> do { n <- whiteNoise AR
->    ; let { y = mouseY KR 100 10000 Exponential 0.1
->          ; x = mouseX KR 0 4 Linear 0.1 }
->      in audition (out 0 (moogFF (n * 0.1) y x 0)) }
+> let {n = whiteNoise 'a' AR
+>     ;y = mouseY' KR 100 10000 Exponential 0.1
+>     ;x = mouseX' KR 0 4 Linear 0.1}
+> in audition (out 0 (moogFF (n * 0.1) y x 0))
 
 Note distortion at high gain.
-
-> let { x = mouseX KR 100 20000 Exponential 0.1
->     ; y = mouseY KR 0.1 4.0 Linear 0.1
->     ; i = mix (saw AR (mce [0.99, 1, 1.01] * 440)) * 0.3 }
+> let {x = mouseX' KR 100 20000 Exponential 0.1
+>     ;y = mouseY' KR 0.1 4.0 Linear 0.1
+>     ;i = mix (saw AR (mce [0.99, 1, 1.01] * 440)) * 0.3 }
 > in audition (out 0 (moogFF i x y 0))
 
-> do { n <- lfNoise0 KR 0.43
->    ; let { p = pulse AR (mce [40, 121]) (mce [0.3, 0.7])
->          ; f0 = linLin n 0 1 0.001 2.2
->          ; f = linLin (sinOsc KR f0 0) (-1) 1 30 4200
->          ; y = mouseY KR 1 4 Linear 0.1 }
->      in audition (out 0 (moogFF p f (0.83 * y) 0)) }
+> let {n = lfNoise0 'a' KR 0.43
+>     ;p = pulse AR (mce [40, 121]) (mce [0.3, 0.7])
+>     ;f0 = linLin n 0 1 0.001 2.2
+>     ;f = linLin (sinOsc KR f0 0) (-1) 1 30 4200
+>     ;y = mouseY' KR 1 4 Linear 0.1}
+> in audition (out 0 (moogFF p f (0.83 * y) 0))
diff --git a/Help/UGen/Filter/normalizer.help.lhs b/Help/UGen/Filter/normalizer.help.lhs
--- a/Help/UGen/Filter/normalizer.help.lhs
+++ b/Help/UGen/Filter/normalizer.help.lhs
@@ -1,11 +1,9 @@
-normalizer i l d
-
-    i - input signal
-    l - level
-    d - duration (0.01)
+> Sound.SC3.UGen.Help.viewSC3Help "Normalizer"
+> Sound.SC3.UGen.DB.ugenSummary "Normalizer"
 
-Flattens dynamics.
+> import Sound.SC3
 
-> let { s = fSinOsc AR 500 0
->     ; z = decay2 (impulse AR 8 (lfSaw KR 0.25 (-0.6) * 0.7)) 0.001 0.3 * s }
+> let {s = fSinOsc AR 500 0
+>     ;t = impulse AR 8 (lfSaw KR 0.25 (-0.6) * 0.7)
+>     ;z = decay2 t 0.001 0.3 * s}
 > in audition (out 0 (mce [z, normalizer z 0.4 0.01]))
diff --git a/Help/UGen/Filter/onePole.help.lhs b/Help/UGen/Filter/onePole.help.lhs
--- a/Help/UGen/Filter/onePole.help.lhs
+++ b/Help/UGen/Filter/onePole.help.lhs
@@ -1,17 +1,14 @@
-onePole in coef
-
-A one pole filter.  Implements the formula: out(i) = ((1 -
-abs(coef)) * in(i)) + (coef * out(i-1)).
+> Sound.SC3.UGen.Help.viewSC3Help "OnePole"
+> Sound.SC3.UGen.DB.ugenSummary "OnePole"
 
-in   - input signal to be processed
-coef - feedback coefficient. Should be between -1 and +1
+> import Sound.SC3.ID
 
-> do { n <- whiteNoise AR
->    ; audition (out 0 (onePole (n * 0.5) 0.95)) }
+> let n = whiteNoise 'a' AR
+> in audition (out 0 (onePole (n * 0.5) 0.95))
 
-> do { n <- whiteNoise AR
->    ; audition (out 0 (onePole (n * 0.5) (-0.95))) }
+> let n = whiteNoise 'a' AR
+> in audition (out 0 (onePole (n * 0.5) (-0.95)))
 
-> do { n <- whiteNoise AR
->    ; let c = line KR (-0.99) 0.99 10 RemoveSynth
->      in audition (out 0 (onePole (n * 0.5) c)) }
+> let {n = whiteNoise 'a' AR
+>     ;c = line KR (-0.99) 0.99 10 RemoveSynth}
+> in audition (out 0 (onePole (n * 0.5) c))
diff --git a/Help/UGen/Filter/oneZero.help.lhs b/Help/UGen/Filter/oneZero.help.lhs
--- a/Help/UGen/Filter/oneZero.help.lhs
+++ b/Help/UGen/Filter/oneZero.help.lhs
@@ -1,13 +1,14 @@
-oneZero in coef
+> Sound.SC3.UGen.Help.viewSC3Help "OneZero"
+> Sound.SC3.UGen.DB.ugenSummary "OneZero"
 
-One zero filter
+> import Sound.SC3.ID
 
-> do { n <- whiteNoise AR
->    ; audition (out 0 (oneZero (n * 0.5) 0.5)) }
+> let n = whiteNoise 'a' AR
+> in audition (out 0 (oneZero (n * 0.5) 0.5))
 
-> do { n <- whiteNoise AR
->    ; audition (out 0 (oneZero (n * 0.5) (-0.5))) }
+> let n = whiteNoise 'a' AR
+> in audition (out 0 (oneZero (n * 0.5) (-0.5)))
 
-> do { n <- whiteNoise AR
->    ; let c = line KR (-0.5) 0.5 10 RemoveSynth
->      in audition (out 0 (oneZero (n * 0.5) c)) }
+> let {n = whiteNoise 'a' AR
+>     ;c = line KR (-0.5) 0.5 10 RemoveSynth}
+> in audition (out 0 (oneZero (n * 0.5) c))
diff --git a/Help/UGen/Filter/pitchShift.help.lhs b/Help/UGen/Filter/pitchShift.help.lhs
--- a/Help/UGen/Filter/pitchShift.help.lhs
+++ b/Help/UGen/Filter/pitchShift.help.lhs
@@ -1,7 +1,8 @@
-pitchShift in winSize pchRatio pchDispersion timeDispersion
+> Sound.SC3.UGen.Help.viewSC3Help "PitchShift"
+> Sound.SC3.UGen.DB.ugenSummary "PitchShift"
 
-A simple time domain pitch shifter.
+> import Sound.SC3
 
-> let { r = mouseX KR 0.5 2.0 Linear 0.1
->     ; d = mouseY KR 0.0 0.1 Linear 0.1 }
+> let {r = mouseX' KR 0.5 2.0 Linear 0.1
+>     ;d = mouseY' KR 0.0 0.1 Linear 0.1}
 > in audition (out 0 (pitchShift (sinOsc AR 440 0) 0.2 r d 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
@@ -1,45 +1,26 @@
-pluck in tr maxdelaytime delaytime decaytime coef
-
-Karplus-Strong synthesis.
-
-in - an excitation signal
-
-tr - upon a negative to positive transition, the excitation signal
-     will be fed into the delay line
-
-maxdelaytime - the max delay time in seconds (initializes the
-               internal delay buffer).
-
-delaytime - delay time in seconds.
-
-decaytime - time for the echoes to decay by 60 decibels. Negative
-            times emphasize odd partials.
+> Sound.SC3.UGen.Help.viewSC3Help "Pluck"
+> Sound.SC3.UGen.DB.ugenSummary "Pluck"
 
-coef - the coef of the internal OnePole filter. Values should be
-       between -1 and +1 (larger values will be unstable... so be
-       careful!).
+> import Sound.SC3.ID
 
-Excitation signal is WhiteNoise, triggered twice a second with
+Excitation signal is white noise, triggered twice a second with
 varying OnePole coef.
-
-> import Sound.SC3.Monadic
-
-> do { n <- whiteNoise AR
->    ; let { t = impulse KR 9 0
->          ; x = mouseX KR (-0.999) 0.999 Linear 0.1
->          ; y = mouseY KR 0.1 1 Linear 0.1
->          ; dl = 1 / 440 }
->      in audition (out 0 (pluck (n * 0.25) t dl (dl * y) 10 x)) }
+> let {n = whiteNoise 'a' AR
+>     ;t = impulse KR 9 0
+>     ;x = mouseX' KR (-0.999) 0.999 Linear 0.1
+>     ;y = mouseY' KR 0.1 1 Linear 0.1
+>     ;dl = 1 / 440}
+> in audition (out 0 (pluck (n * 0.25) t dl (dl * y) 10 x))
 
-> let n = 25
-> in do { f <- clone n (rand 0.05 0.2)
->       ; p <- clone n (rand 0 1)
->       ; w <- clone n (whiteNoise AR)
->       ; fi <- clone n (rand 10 12)
->       ; coef <- rand 0.01 0.2
->       ; l <- clone n (rand (-1) 1)
->       ; let { x = mouseX KR 60 1000 Exponential 0.1
->             ; o = linLin (sinOsc KR f p) (-1) 1 x 3000
->             ; i = impulse KR fi 0
->             ; ks = pluck (w * 0.1) i 0.01 (1 / o) 2 coef }
->         in audition (out 0 (leakDC (mix (pan2 ks l 1)) 0.995)) }
+> let {n = 25
+>     ;f = udup n (rand 'a' 0.05 0.2)
+>     ;p = udup n (rand 'a' 0 1)
+>     ;w = udup n (whiteNoise 'a' AR)
+>     ;fi = udup n (rand 'a' 10 12)
+>     ;coef = rand 'a' 0.01 0.2
+>     ;l = udup n (rand 'a' (-1) 1)
+>     ;x = mouseX' KR 60 1000 Exponential 0.1
+>     ;o = linLin (sinOsc KR f p) (-1) 1 x 3000
+>     ;i = impulse KR fi 0
+>     ;ks = pluck (w * 0.1) i 0.01 (1 / o) 2 coef}
+> in audition (out 0 (leakDC (mix (pan2 ks l 1)) 0.995))
diff --git a/Help/UGen/Filter/ramp.help.lhs b/Help/UGen/Filter/ramp.help.lhs
--- a/Help/UGen/Filter/ramp.help.lhs
+++ b/Help/UGen/Filter/ramp.help.lhs
@@ -1,16 +1,10 @@
-ramp in lagTime
-
-Linear lag.  This is similar to Lag but with a linear rather than
-exponential lag. This is useful for smoothing out control signals.
-
-       in - input signal
-  lagTime - 60 dB lag time in seconds
-
-Used to lag pitch
+> Sound.SC3.UGen.Help.viewSC3Help "Ramp"
+> Sound.SC3.UGen.DB.ugenSummary "Ramp"
 
 > import Sound.SC3
 
-> let { o = lfPulse KR 4 0 0.5 * 50 + 400
->     ; l = line KR 0 1 15 DoNothing
->     ; f = ramp o l }
+Used to lag pitch
+> let {o = lfPulse KR 4 0 0.5 * 50 + 400
+>     ;l = line KR 0 1 15 DoNothing
+>     ;f = ramp o l}
 > in audition (out 0 (sinOsc AR f 0 * 0.3))
diff --git a/Help/UGen/Filter/resonz.help.lhs b/Help/UGen/Filter/resonz.help.lhs
--- a/Help/UGen/Filter/resonz.help.lhs
+++ b/Help/UGen/Filter/resonz.help.lhs
@@ -1,17 +1,5 @@
-resonz in freq bwr
-
-Resonant filter.
-
-A two pole resonant filter with zeroes at z = +/- 1. Based on
-K. Steiglitz, "A Note on Constant-Gain Digital Resonators,"
-Computer Music Journal, vol 18, no. 4, pp. 8-10, Winter 1994.  The
-reciprocal of Q is used rather than Q because it saves a divide
-operation inside the unit generator.
-
-    in - input signal to be processed
-  freq - resonant frequency in Hertz
-    rq - bandwidth ratio (reciprocal of Q). 
-         rq = bandwidth / centerFreq
+> Sound.SC3.UGen.Help.viewSC3Help "Resonz"
+> Sound.SC3.UGen.DB.ugenSummary "Resonz"
 
 > import Sound.SC3.ID
 
@@ -19,19 +7,16 @@
 > in audition (out 0 (resonz (n * 0.5) 2000 0.1))
 
 Modulate frequency
-
 > let { n = whiteNoise 'a' AR
 >     ; f = xLine KR 1000 8000 10 RemoveSynth }
 > in audition (out 0 (resonz (n * 0.5) f 0.05))
 
 Modulate bandwidth
-
 > let { n = whiteNoise 'a' AR
 >     ; bw = xLine KR 1 0.001 8 RemoveSynth }
 > in audition (out 0 (resonz (n * 0.5) 2000 bw))
 
 Modulate bandwidth opposite direction
-
 > let { n = whiteNoise 'a' AR
 >     ; bw = xLine KR 0.001 1 8 RemoveSynth }
 > in audition (out 0 (resonz (n * 0.5) 2000 bw))
diff --git a/Help/UGen/Filter/rhpf.help.lhs b/Help/UGen/Filter/rhpf.help.lhs
--- a/Help/UGen/Filter/rhpf.help.lhs
+++ b/Help/UGen/Filter/rhpf.help.lhs
@@ -1,6 +1,5 @@
-rhpf in freq rq
-
-A resonant high pass filter.
+> Sound.SC3.UGen.Help.viewSC3Help "RHPF"
+> Sound.SC3.UGen.DB.ugenSummary "RHPF"
 
 > import Sound.SC3
 
diff --git a/Help/UGen/Filter/ringz.help.lhs b/Help/UGen/Filter/ringz.help.lhs
--- a/Help/UGen/Filter/ringz.help.lhs
+++ b/Help/UGen/Filter/ringz.help.lhs
@@ -1,33 +1,26 @@
-ringz in freq decayTime
-
-Ringing filter.  This is the same as Resonz, except that instead of
-a resonance parameter, the bandwidth is specified in a 60dB ring
-decay time. One Ringz is equivalent to one component of the Klank
-UGen.
+> Sound.SC3.UGen.Help.viewSC3Help "Ringz"
+> Sound.SC3.UGen.DB.ugenSummary "Ringz"
 
-> import Sound.SC3.Monadic
+> import Sound.SC3.ID
 
-> do { n <- dust AR 3
->    ; audition (out 0 (ringz (n * 0.3) 2000 2)) }
+> let n = dust 'a' AR 3
+> in audition (out 0 (ringz (n * 0.3) 2000 2))
 
-> do { n <- whiteNoise AR
->    ; audition (out 0 (ringz (n * 0.005) 2000 0.5)) }
+> let n = whiteNoise 'a' AR
+> in audition (out 0 (ringz (n * 0.005) 2000 0.5))
 
 Modulate frequency
-
-> do { n <- whiteNoise AR
->    ; let f = xLine KR 100 3000 10 RemoveSynth
->      in audition (out 0 (ringz (n * 0.005) f 0.5)) }
+> let {n = whiteNoise 'a' AR
+>     ;f = xLine KR 100 3000 10 RemoveSynth}
+> in audition (out 0 (ringz (n * 0.005) f 0.5))
 
 > let f = xLine KR 100 3000 10 RemoveSynth
 > in audition (out 0 (ringz (impulse AR 6 0.3) f 0.5))
 
 Modulate ring time
-
 > let rt = xLine KR 4 0.04 8 RemoveSynth
 > in audition (out 0 (ringz (impulse AR 6 0.3) 2000 rt))
 
 Modulate ring time opposite direction
-
 > let rt = xLine KR 0.04 4 8 RemoveSynth
 > in audition (out 0 (ringz (impulse AR 6 0.3) 2000 rt))
diff --git a/Help/UGen/Filter/rlpf.help.lhs b/Help/UGen/Filter/rlpf.help.lhs
--- a/Help/UGen/Filter/rlpf.help.lhs
+++ b/Help/UGen/Filter/rlpf.help.lhs
@@ -1,12 +1,11 @@
-rlpf in freq rq
-
-A resonant low pass filter.
+> Sound.SC3.UGen.Help.viewSC3Help "RLPF"
+> Sound.SC3.UGen.DB.ugenSummary "RLPF"
 
 > import Sound.SC3.ID
 
-> let { n = whiteNoise 'a' AR
->     ; f = sinOsc AR 0.5 0 * 40 + 220
->     ; r = rlpf n f 0.1 }
+> let {n = whiteNoise 'a' AR
+>     ;f = sinOsc AR 0.5 0 * 40 + 220
+>     ;r = rlpf n f 0.1}
 > in audition (out 0 r)
 
 > let f = fSinOsc KR (xLine KR 0.7 300 20 RemoveSynth) 0 * 3600 + 4000
diff --git a/Help/UGen/Filter/select.help.lhs b/Help/UGen/Filter/select.help.lhs
--- a/Help/UGen/Filter/select.help.lhs
+++ b/Help/UGen/Filter/select.help.lhs
@@ -1,6 +1,5 @@
-select which array
-
-The output is selected from an array of inputs.
+> Sound.SC3.UGen.Help.viewSC3Help "Select"
+> Sound.SC3.UGen.DB.ugenSummary "Select"
 
 > import Sound.SC3
 
@@ -8,13 +7,10 @@
 >     ; a = mce [sinOsc AR 440 0, saw AR 440, pulse AR 440 0.1] }
 > in audition (out 0 (select (lfSaw KR 1 0 * n + n) a * 0.2))
 
-Note: all input ugens are continously running. This may not be the
-most efficient way if each input is cpu-expensive.
-
 Here used as a sequencer:
-
 > let { n = 10
 >     ; a = mce [517, 403, 89, 562, 816, 107, 241, 145, 90, 224]
->     ; c = n / 2 
+>     ; c = n / 2
 >     ; f = select (lfSaw KR 0.5 0 * c + c) a }
 > in audition (out 0 (saw AR f * 0.2))
+
diff --git a/Help/UGen/Filter/selectX.help.lhs b/Help/UGen/Filter/selectX.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Filter/selectX.help.lhs
@@ -0,0 +1,21 @@
+> Sound.SC3.UGen.Help.viewSC3Help "SelectX"
+> :t selectX
+
+# composite
+
+> import Sound.SC3
+> import Sound.SC3.UGen.Dot
+
+> let { n = 3/2
+>     ; f = mce2 440 441
+>     ; a = mce [sinOsc AR f 0, saw AR f, pulse AR f 0.1]
+>     ; s = mceSum (selectX (lfSaw KR 1 0 * n + n) a * 0.2) }
+> in audition (out 0 s) >> draw s
+
+Here used as a sequencer:
+> let { n = 10
+>     ; a = mce [517, 403, 89, 562, 816, 107, 241, 145, 90, 224]
+>     ; c = n / 2
+>     ; f = mceSum (selectX (lfSaw KR 0.5 0 * c + c) a)
+>     ; s = saw AR f * 0.2 }
+> in audition (out 0 s) >> draw s
diff --git a/Help/UGen/Filter/shaper.help.lhs b/Help/UGen/Filter/shaper.help.lhs
--- a/Help/UGen/Filter/shaper.help.lhs
+++ b/Help/UGen/Filter/shaper.help.lhs
@@ -1,16 +1,9 @@
-shaper bufnum in
-
-Wave shaper.  Performs waveshaping on the input signal by indexing
-into the table.
-
-bufnum - the number of a buffer filled in wavetable format
-         containing the transfer function.
-
-in     - the input signal.
+> Sound.SC3.UGen.Help.viewSC3Help "Shaper"
+> Sound.SC3.UGen.DB.ugenSummary "Shaper"
 
 > import Sound.SC3
 
 > let s = sinOsc AR 300 0 * line KR 0 1 6 RemoveSynth
-> in withSC3 (\fd -> do { async fd (b_alloc 10 512 1)
->                       ; async fd (b_gen 10 "cheby" [0, 1, 0, 1, 1, 0, 1])
->                       ; audition (out 0 (shaper 10 s * 0.5)) })
+> in withSC3 (\fd -> do {async fd (b_alloc 10 512 1)
+>                       ;async fd (b_gen 10 "cheby" [0, 1, 0, 1, 1, 0, 1])
+>                       ;audition (out 0 (shaper 10 s * 0.5))})
diff --git a/Help/UGen/Filter/slew.help.lhs b/Help/UGen/Filter/slew.help.lhs
--- a/Help/UGen/Filter/slew.help.lhs
+++ b/Help/UGen/Filter/slew.help.lhs
@@ -1,7 +1,10 @@
-slew in up dn
-
-Has the effect of removing transients and higher frequencies.
+> Sound.SC3.UGen.Help.viewSC3Help "Slew"
+> Sound.SC3.UGen.DB.ugenSummary "Slew"
 
 > import Sound.SC3
 
-> audition (out 0 (slew (saw AR 800 * 0.2) 400 400))
+> let z = lfPulse AR 800 0 0.5 * 0.2
+> in audition (out 0 (mce2 z (slew z 4000 4000)))
+
+> let z = saw AR 800 * 0.2
+> in audition (out 0 (mce2 z (slew z 400 400)))
diff --git a/Help/UGen/Filter/sos.help.lhs b/Help/UGen/Filter/sos.help.lhs
--- a/Help/UGen/Filter/sos.help.lhs
+++ b/Help/UGen/Filter/sos.help.lhs
@@ -1,13 +1,9 @@
-sos in a0 a1 a2 b1 b2
-
-Second order filter section (biquad).  A standard second order
-filter section. Filter coefficients are given directly rather than
-calculated for you.
-
-Same as TwoPole
+> Sound.SC3.UGen.Help.viewSC3Help "SOS"
+> Sound.SC3.UGen.DB.ugenSummary "SOS"
 
 > import Sound.SC3
 
+Same as TwoPole
 > let { theta = line KR (0.2 * pi) pi 5 RemoveSynth
 >     ; rho = line KR 0.6 0.99 5 RemoveSynth
 >     ; b1 = 2 * rho * cos theta
diff --git a/Help/UGen/Filter/twoPole.help.lhs b/Help/UGen/Filter/twoPole.help.lhs
--- a/Help/UGen/Filter/twoPole.help.lhs
+++ b/Help/UGen/Filter/twoPole.help.lhs
@@ -1,14 +1,11 @@
-twoPole in freq radius
-
-Two pole filter.  A two pole filter. This provides lower level
-access to setting of pole location.  For general purposes Resonz is
-better.
+> Sound.SC3.UGen.Help.viewSC3Help "TwoPole"
+> Sound.SC3.UGen.DB.ugenSummary "TwoPole"
 
-> import Sound.SC3.Monadic
+> import Sound.SC3.ID
 
-> do { n <- whiteNoise AR
->    ; audition (out 0 (twoPole (n * 0.005) 2000 0.95)) }
+> let n = whiteNoise 'a' AR
+> in audition (out 0 (twoPole (n * 0.005) 2000 0.95))
 
-> do { n <- whiteNoise AR
->    ; let f = xLine KR 800 8000 8 RemoveSynth
->      in audition (out 0 (twoPole (n * 0.005) f 0.95)) }
+> let {n = whiteNoise 'a' AR
+>     ;f = xLine KR 800 8000 8 RemoveSynth}
+> in audition (out 0 (twoPole (n * 0.005) f 0.95))
diff --git a/Help/UGen/Filter/twoZero.help.lhs b/Help/UGen/Filter/twoZero.help.lhs
--- a/Help/UGen/Filter/twoZero.help.lhs
+++ b/Help/UGen/Filter/twoZero.help.lhs
@@ -1,9 +1,8 @@
-twoZero in freq radius
-
-Two zero filter
+> Sound.SC3.UGen.Help.viewSC3Help "TwoZero"
+> Sound.SC3.UGen.DB.ugenSummary "TwoZero"
 
-> import Sound.SC3.Monadic
+> import Sound.SC3.ID
 
-> do { n <- whiteNoise AR
->    ; let f = xLine KR 20 20000 8 RemoveSynth
->      in audition (out 0 (twoZero (n * 0.125) f 1)) }
+> let {n = whiteNoise 'a' AR
+>     ;f = xLine KR 20 20000 8 RemoveSynth}
+> in audition (out 0 (twoZero (n * 0.125) f 1))
diff --git a/Help/UGen/Filter/wrapIndex.help.lhs b/Help/UGen/Filter/wrapIndex.help.lhs
--- a/Help/UGen/Filter/wrapIndex.help.lhs
+++ b/Help/UGen/Filter/wrapIndex.help.lhs
@@ -1,19 +1,10 @@
-wrapIndex bufnum in
-
-Index into a table with a signal.
-
-The input signal value is truncated to an integer value and used as
-an index into the table.  Out of range index values are wrapped
-cyclically to the valid range.
-
-bufnum - index of the buffer
-in     - the input signal.
+> Sound.SC3.UGen.Help.viewSC3Help "WrapIndex"
+> Sound.SC3.UGen.DB.ugenSummary "WrapIndex"
 
 > import Sound.SC3
 
-> withSC3 (\fd -> do { async fd (b_alloc 0 6 1)
->                    ; send fd (b_setn 0 [(0, [200, 300, 400, 500, 600, 800])]) })
+> withSC3 (\fd -> async fd (b_alloc_setn1 0 0 [200,300,400,500,600,800]))
 
-> let { x = mouseX KR 0 18 Linear 0.1
->     ; f = wrapIndex 0 x }
+> let {x = mouseX' KR 0 18 Linear 0.1
+>     ;f = wrapIndex 0 x}
 > in audition (out 0 (sinOsc AR f 0 * 0.5))
diff --git a/Help/UGen/Granular/grainBuf.help.lhs b/Help/UGen/Granular/grainBuf.help.lhs
--- a/Help/UGen/Granular/grainBuf.help.lhs
+++ b/Help/UGen/Granular/grainBuf.help.lhs
@@ -1,60 +1,30 @@
-grainBuf nc tr dur sndbuf rate pos interp pan envbuf maxgrn
-
-Granular synthesis with sound stored in a buffer
-
-nc - the number of channels to output. If 1, mono is returned and
-     pan is ignored.
-
-tr - a kr or ar trigger to start a new grain. If ar, grains after
-     the start of the synth are sample accurate.
-
-The following args are polled at grain creation time
-
-dur - size of the grain (in seconds).
-
-sndbuf - the buffer holding an audio signal (must be single channel)
-
-rate - the playback rate of the sampled sound
-
-pos - the playback position for the grain to start with (0 is
-      beginning, 1 is end of file)
-
-interp - the interpolation method used for pitchshifting grains.
-         1 = no interpolation. 2 = linear. 4 = cubic interpolation
-         (more computationally intensive).
-
-pan - a value from -1 to 1. Determines where to pan the output in
-      the same manner as PanAz.
-
-envb - the buffer number containing a signal to use for the
-       grain envelope. -1 uses a built-in Hanning envelope.
-
-maxgrn - maxiumum number of grains
+> Sound.SC3.UGen.Help.viewSC3Help "GrainBuf"
+> Sound.SC3.UGen.DB.ugenSummary "GrainBuf"
 
-> import Sound.SC3.Monadic
+> import Sound.SC3.ID
 
-> let fn = "/home/rohan/audio/metal.wav"
+> let fn = "/home/rohan/data/audio/pf-c5.snd"
 > in withSC3 (\fd -> send fd (b_allocRead 10 fn 0 0))
 
-> let { buf = 10
->     ; dur = 15
->     ; lin a b = line KR a b dur RemoveSynth
->     ; tr = impulse KR (lin 7.5 15) 0
->     ; gd = lin 0.05 0.1
->     ; r = lin 1 0.5
->     ; i = lin 0 1
->     ; l = lin (-0.5) 0.5
->     ; g = grainBuf 2 tr gd buf r i 2 0 (-1) 512 }
+> let {buf = 10
+>     ;dur = 15
+>     ;lin a b = line KR a b dur RemoveSynth
+>     ;tr = impulse KR (lin 7.5 15) 0
+>     ;gd = lin 0.05 0.1
+>     ;r = lin 1 0.5
+>     ;i = lin 0 1
+>     ;l = lin (-0.5) 0.5
+>     ;g = grainBuf 2 tr gd buf r i 2 0 (-1) 512}
 > in audition (out 0 g)
 
-> let { b = 10
->     ; e = -1
->     ; x = mouseX KR (-1) 1 Linear 0.1
->     ; y = mouseY KR 10 45 Linear 0.1
->     ; i = impulse KR y 0
->     ; r n = linLin n (-1) 1 0.5 2
->     ; p n = linLin n (-1) 1 0 1
->     ; g n1 n2 = grainBuf 2 i 0.1 b (r n1) (p n2) 2 x e 512 }
-> in withSC3 (\fd -> do { n1 <- lfNoise1 KR 500
->                       ; n2 <- lfNoise2 KR 0.1
->                       ; play fd (out 0 (g n1 n2)) })
+> let {b = 10
+>     ;e = -1
+>     ;x = mouseX' KR (-1) 1 Linear 0.1
+>     ;y = mouseY' KR 10 45 Linear 0.1
+>     ;i = impulse KR y 0
+>     ;n1 = lfNoise1 'a' KR 500
+>     ;n2 = lfNoise2 'b' KR 0.1
+>     ;r = linLin n1 (-1) 1 0.5 2
+>     ;p = linLin n2 (-1) 1 0 1
+>     ;g = grainBuf 2 i 0.1 b r p 2 x e 512}
+> in audition (out 0 g)
diff --git a/Help/UGen/Granular/grainFM.help.lhs b/Help/UGen/Granular/grainFM.help.lhs
--- a/Help/UGen/Granular/grainFM.help.lhs
+++ b/Help/UGen/Granular/grainFM.help.lhs
@@ -1,47 +1,22 @@
-grainFM nc tr dur carfreq modfreq index pan envbuf maxgrn
-
-Granular synthesis with frequency modulated sine tones
-
-nc - the number of channels to output. If 1, mono is returned and
-     pan is ignored.
-
-tr - a kr or ar trigger to start a new grain. If ar, grains after
-     the start of the synth are sample accurate.
-
-The following args are polled at grain creation time
-
-dur - size of the grain.
-
-carfreq - the carrier freq of the grain generators internal
-          oscillator
-
-modfreq - the modulating freq of the grain generators internal
-          oscillator
-
-index - the index of modulation
-
-pan - a value from -1 to 1. Determines where to pan the output in
-      the same manner as PanAz.
-
-envbuf - the buffer number containing a singal to use for the grain
-         envelope. -1 uses a built-in Hanning envelope.
+> Sound.SC3.UGen.Help.viewSC3Help "GrainFM"
+> Sound.SC3.UGen.DB.ugenSummary "GrainFM"
 
-> import Sound.SC3.Monadic
+> import Sound.SC3.ID
 
-> let { d = 15
->     ; lin a b = line KR a b d RemoveSynth
->     ; l = lin (-0.5) 0.5
->     ; f = lin 200 800
->     ; t = impulse KR (lin 7.5 15) 0
->     ; i = lin (-1) 1 }
+> let {d = 15
+>     ;lin a b = line KR a b d RemoveSynth
+>     ;l = lin (-0.5) 0.5
+>     ;f = lin 200 800
+>     ;t = impulse KR (lin 7.5 15) 0
+>     ;i = lin (-1) 1}
 > in audition (out 0 (grainFM 2 t 0.1 f 200 i l (-1) 512 * 0.1))
 
-> do { n1 <- whiteNoise KR
->    ; n2 <- lfNoise1 KR 500
->    ; let { d = 5
->          ; x = mouseX KR (-0.5) 0.5 Linear 0.1
->          ; y = mouseY KR 0 400 Linear 0.1
->          ; f = n1 * y + 440
->          ; t = impulse KR 12.5 0
->          ; i = linLin n2 (-1) 1 1 10 }
->      in audition (out 0 (grainFM 2 t 0.1 f 200 i x (-1) 512 * 0.1)) }
+> let {n1 = whiteNoise 'a' KR
+>     ;n2 = lfNoise1 'b' KR 500
+>     ;d = 5
+>     ;x = mouseX' KR (-0.5) 0.5 Linear 0.1
+>     ;y = mouseY' KR 0 400 Linear 0.1
+>     ;f = n1 * y + 440
+>     ;t = impulse KR 12.5 0
+>     ;i = linLin n2 (-1) 1 1 10}
+> in audition (out 0 (grainFM 2 t 0.1 f 200 i x (-1) 512 * 0.1))
diff --git a/Help/UGen/Granular/grainIn.help.lhs b/Help/UGen/Granular/grainIn.help.lhs
--- a/Help/UGen/Granular/grainIn.help.lhs
+++ b/Help/UGen/Granular/grainIn.help.lhs
@@ -1,30 +1,11 @@
-grainIn nc tr dur in pan envbuf
-
-Granulate an input signal
-
-nc - the number of channels to output. If 1, mono is
-     returned and pan is ignored.
-
-tr - a kr or ar trigger to start a new grain. If ar, grains
-     after the start of the synth are sample accurate.
-
-The following args are polled at grain creation time
-
-dur - size of the grain.
-
-in - the input to granulate
-
-pan - a value from -1 to 1. Determines where to pan the output in
-      the same manner as PanAz.
-
-envbuf - the buffer number containing a singal to use for the
-         grain envelope. -1 uses a built-in Hanning envelope.
+> Sound.SC3.UGen.Help.viewSC3Help "GrainIn"
+> Sound.SC3.UGen.DB.ugenSummary "GrainIn"
 
-> import Sound.SC3.Monadic
+> import Sound.SC3.ID
 
-> do { n <- pinkNoise AR
->    ; let { x = mouseX KR (-0.5) 0.5 Linear 0.1
->          ; y = mouseY KR 5 25 Linear 0.1
->          ; t = impulse KR y 0 
->          ; g = grainIn 2 t 0.1 n x (-1) * 0.1 }
->      in audition (out 0 g) }
+> let {n = pinkNoise 'a' AR
+>     ;x = mouseX' KR (-0.5) 0.5 Linear 0.1
+>     ;y = mouseY' KR 5 25 Linear 0.1
+>     ;t = impulse KR y 0
+>     ;g = grainIn 2 t 0.1 n x (-1) 512 * 0.1}
+> in audition (out 0 g)
diff --git a/Help/UGen/Granular/grainSin.help.lhs b/Help/UGen/Granular/grainSin.help.lhs
--- a/Help/UGen/Granular/grainSin.help.lhs
+++ b/Help/UGen/Granular/grainSin.help.lhs
@@ -1,30 +1,11 @@
-grainSin nc tr dur freq pan envbuf maxgrn
-
-Granular synthesis with sine tones
-
-nc - the number of channels to output. If 1, mono is returned and
-     pan is ignored.
-
-tr - a kr or ar trigger to start a new grain. If ar, grains after
-     the start of the synth are sample accurate.
-
-The following args are polled at grain creation time
-
-dur - size of the grain.
-
-freq - the input to granulate
-
-pan - a value from -1 to 1. Determines where to pan the output in
-      the same manner as PanAz.
-
-envbuf - the buffer number containing a singal to use for the grain
-         envelope. -1 uses a built-in Hanning envelope.
+> Sound.SC3.UGen.Help.viewSC3Help "GrainSin"
+> Sound.SC3.UGen.DB.ugenSummary "GrainSin"
 
-> import Sound.SC3.Monadic
+> import Sound.SC3.ID
 
-> do { n <- whiteNoise KR
->    ; let { x = mouseX KR (-0.5) 0.5 Linear 0.1
->          ; y = mouseY KR 0 400 Linear 0.1
->          ; f = n * y + 440
->          ; t = impulse KR 10 0 }
->      in audition (out 0 (grainSin 2 t 0.1 f x (-1) 512 * 0.1)) }
+> let {n = whiteNoise 'a' KR
+>     ;x = mouseX' KR (-0.5) 0.5 Linear 0.1
+>     ;y = mouseY' KR 0 400 Linear 0.1
+>     ;f = n * y + 440
+>     ;t = impulse KR 10 0}
+> in audition (out 0 (grainSin 2 t 0.1 f x (-1) 512 * 0.1))
diff --git a/Help/UGen/Granular/warp1.help.lhs b/Help/UGen/Granular/warp1.help.lhs
--- a/Help/UGen/Granular/warp1.help.lhs
+++ b/Help/UGen/Granular/warp1.help.lhs
@@ -1,43 +1,12 @@
-warp1 nc buf ptr freqScale windowSize envbuf overlaps windowRandRatio interp
-
-Warp a buffer with a time pointer
-
-Inspired by Chad Kirby's SuperCollider2 Warp1 class, which was
-inspired by Richard Karpen's sndwarp for CSound. A granular time
-strecher and pitchshifter.
-
-nc - the number of channels in the soundfile used in bufnum.
-
-buf - the buffer number of a mono soundfile.
-
-ptr - the position in the buffer.  The value should be between 0
-      and 1, with 0 being the begining of the buffer, and 1 the
-      end.
-
-freqScale - the amount of frequency shift. 1.0 is normal, 0.5 is
-            one octave down, 2.0 is one octave up. Negative values
-            play the soundfile backwards.
-
-windowSize - the size of each grain window.
-
-envbuf - the buffer number containing a singal to use for the grain
-         envelope. -1 uses a built-in Hanning envelope.
-
-overlaps - the number of overlaping windows.
-
-windowRandRatio - the amount of randomness to the windowing
-                  function.  Must be between 0 (no randomness) to
-                  1.0 (probably to random actually)
-
-interp - the interpolation method used for pitchshifting grains. 1
-         = no interpolation. 2 = linear. 4 = cubic interpolation
-         (more computationally intensive).
+> Sound.SC3.UGen.Help.viewSC3Help "Warp1"
+> Sound.SC3.UGen.DB.ugenSummary "Warp1"
 
 > import Sound.SC3
 
-> let { fn = "/home/rohan/audio/metal.wav"
->     ; p = linLin (lfSaw KR 0.05 0) (-1) 1 0 1
->     ; x = mouseX KR 0.5 2 Linear 0.1
->     ; w = warp1 1 10 p x 0.1 (-1) 8 0.1 2 }
-> in withSC3 (\fd -> do { send fd (b_allocRead 10 fn 0 0)
->                       ; play fd (out 0 w) })
+> let {fn = "/home/rohan/data/audio/pf-c5.aif"
+>     ;p = linLin (lfSaw KR 0.05 0) (-1) 1 0 1
+>     ;x = mouseX' KR 0.5 2 Linear 0.1
+>     ;w = warp1 1 10 p x 0.1 (-1) 8 0.1 2}
+> in withSC3 (\fd -> do {send fd (b_allocRead 10 fn 0 0)
+>                       ;play fd (out 0 w)})
+
diff --git a/Help/UGen/IO/in.help.lhs b/Help/UGen/IO/in.help.lhs
--- a/Help/UGen/IO/in.help.lhs
+++ b/Help/UGen/IO/in.help.lhs
@@ -1,32 +1,30 @@
-in' numChannels rate bus
-
-Read signal from an audio or control bus.
+> Sound.SC3.UGen.Help.viewSC3Help "In"
+> Sound.SC3.UGen.DB.ugenSummary "In"
 
-Patching input to output.
+# hsc3
+hsc3 renames UGen to in' since in is a reserved keyword
 
-> import Sound.SC3
+> import Sound.SC3.ID
 
+Patching input to output.
 > audition (out 0 (in' 2 AR numOutputBuses))
 
 Patching input to output, with delay.
-
-> let { i = in' 2 AR numOutputBuses
->     ; d = delayN i 0.5 0.5 }
+> let {i = in' 2 AR numOutputBuses
+>     ;d = delayN i 0.5 0.5}
 > in audition (out 0 (i + d))
 
-Write noise to bus 10, then read it out.  The multiple root graph is ordered.
-
-> import Sound.SC3.ID
-
-> let { n = pinkNoise 'a' AR
->     ; wr = out 10 (n * 0.3)
->     ; rd = out 0 (in' 1 AR 10) }
+Write noise to bus 10, then read it out, the multiple root graph is ordered.
+> let {n = pinkNoise 'a' AR
+>     ;wr = out 10 (n * 0.3)
+>     ;rd = out 0 (in' 1 AR 10)}
 > in audition (mrg [rd, wr])
 
-Reading a control bus.
-
+Set value on a control bus
 > withSC3 (\fd -> send fd (c_set [(0, 300)]))
 
+Read a control bus
 > audition (out 0 (sinOsc AR (in' 1 KR 0) 0 * 0.1))
 
+Re-set value on bus
 > withSC3 (\fd -> send fd (c_set [(0, 600)]))
diff --git a/Help/UGen/IO/inFeedback.help.lhs b/Help/UGen/IO/inFeedback.help.lhs
--- a/Help/UGen/IO/inFeedback.help.lhs
+++ b/Help/UGen/IO/inFeedback.help.lhs
@@ -1,61 +1,34 @@
-inFeedback numChannels bus
-
-Read signal from a bus without erasing it.
-
-The output (Out) ugens overwrite data on the bus, giving this bus a
-new timestamp so that any input (In) ugen can check if the data was
-written within the current cycle. The next cycle this data is still
-there, but in case of audio one normally doesn't want an in ugen to
-read it again, as it might cause feedback.
-
-This is the reason why In ar checks the timestamp and ignores
-everything that was not written within this cycle. This means that
-nodes can only read data from a bus that was written by a
-preceeding node when using the In ar ugen which overwrites the old
-data. This is good for audio, but for control data it is more
-convenient to be able to read a bus from any place in the node
-order.
-
-This is why In kr behaves differently and reads also data with a
-timestamp that is one cycle old. Now in some cases we want to be
-able to read audio from a bus independant of the current node
-order, which is the use of InFeedback.  The delay introduced by
-this is at a maximum one block size, which equals about 0.0014 sec
-at the default block size and sample rate.
-
-Audio feedback modulation.
+> Sound.SC3.UGen.Help.viewSC3Help "InFeedback"
+> Sound.SC3.UGen.DB.ugenSummary "InFeedback"
 
 > import Sound.SC3
 
-> let { f = inFeedback 1 0 * 1300 + 300
->     ; s = sinOsc AR f 0 * 0.4 }
+Audio feedback modulation
+> let {f = inFeedback 1 0 * 1300 + 300
+>     ;s = sinOsc AR f 0 * 0.4}
 > in audition (out 0 s)
 
 Evaluate these in either order and hear both tones.
-
-> let { b = numInputBuses + numOutputBuses
->     ; s = inFeedback 1 b }
+> let {b = numInputBuses + numOutputBuses
+>     ;s = inFeedback 1 b}
 > in audition (out 0 s)
 
-> let { b  = numInputBuses + numOutputBuses
->     ; s0 = out b (sinOsc AR 220 0 * 0.1)
->     ; s1 = out 0 (sinOsc AR 660 0 * 0.1) }
+> let {b  = numInputBuses + numOutputBuses
+>     ;s0 = out b (sinOsc AR 220 0 * 0.1)
+>     ;s1 = out 0 (sinOsc AR 660 0 * 0.1)}
 > in audition (mrg [s0, s1])
 
-Doubters consult this.
-
-> let { b = numInputBuses + numOutputBuses
->     ; s = in' 1 AR b }
+Doubters consult this
+> let {b = numInputBuses + numOutputBuses
+>     ;s = in' 1 AR b}
 > in audition (out 0 s)
 
 Resonator, see localOut for variant.
-
-> let { b = numInputBuses + numOutputBuses
->     ; p = inFeedback 1 b
->     ; i = impulse AR 1 0
->     ; d = delayC (i + (p * 0.995)) 1 (recip 440 - recip controlRate) }
+> let {b = numInputBuses + numOutputBuses
+>     ;p = inFeedback 1 b
+>     ;i = impulse AR 1 0
+>     ;d = delayC (i + (p * 0.995)) 1 (recip 440 - recip controlRate)}
 > in audition (mrg [offsetOut b d, offsetOut 0 p])
 
 Compare with oscillator.
-
 > audition (out 1 (sinOsc AR 440 0 * 0.2))
diff --git a/Help/UGen/IO/inTrig.help.lhs b/Help/UGen/IO/inTrig.help.lhs
--- a/Help/UGen/IO/inTrig.help.lhs
+++ b/Help/UGen/IO/inTrig.help.lhs
@@ -1,19 +1,15 @@
-inTrig numChannels bus
-
-Generate a trigger anytime a bus is set.
-
-Any time the bus is "touched" ie. has its value set (using "/c_set"
-etc.), a single impulse trigger will be generated.  Its amplitude
-is the value that the bus was set to.
+> Sound.SC3.UGen.Help.viewSC3Help "InTrig"
+> Sound.SC3.UGen.DB.ugenSummary "InTrig"
 
-Run an oscillator with the trigger at bus 10.
+# hsc3
+channel count (Int) is first argument
 
 > import Sound.SC3
 
-> let { t = inTrig 1 10
->     ; e = envGen KR t t 0 1 DoNothing (envPerc 0.01 1) }
+Run an oscillator with the trigger at bus 10.
+> let {t = inTrig 1 10
+>     ;e = envGen KR t t 0 1 DoNothing (envPerc 0.01 1)}
 > in audition (out 0 (sinOsc AR 440 0 * e))
 
 Set bus 10, each set will trigger a ping.
-
 > withSC3 (\fd -> send fd (c_set1 10 0.1))
diff --git a/Help/UGen/IO/keyState.help.lhs b/Help/UGen/IO/keyState.help.lhs
--- a/Help/UGen/IO/keyState.help.lhs
+++ b/Help/UGen/IO/keyState.help.lhs
@@ -1,11 +1,8 @@
-keyState KR keyNum minVal maxVal lag
+> Sound.SC3.UGen.Help.viewSC3Help "KeyState"
+> Sound.SC3.UGen.DB.ugenSummary "KeyState"
 
-Report the status of a particular key.  A key is either pressed, or
-not pressed.
+> import Sound.SC3
 
 The keycode 38 is the A key on my keyboard.  Under X the xev(1)
 command is useful in determining your keyboard layout.
-
-> import Sound.SC3
-
 > audition (out 0 (sinOsc AR 800 0 * keyState KR 38 0 0.1 0.5))
diff --git a/Help/UGen/IO/lagIn.help.lhs b/Help/UGen/IO/lagIn.help.lhs
--- a/Help/UGen/IO/lagIn.help.lhs
+++ b/Help/UGen/IO/lagIn.help.lhs
@@ -1,12 +1,13 @@
-lagIn numChannels bus lag
-
-Smooth a control rate input signal.
+> Sound.SC3.UGen.Help.viewSC3Help "LagIn"
+> Sound.SC3.UGen.DB.ugenSummary "LagIn"
 
-> import Control.Concurrent
 > import Sound.SC3
 
-> withSC3 (\fd -> do 
->          { send fd (c_set [(10, 200)])
->          ; play fd (out 0 (sinOsc AR (lagIn 1 10 1) 0 * 0.1))
->          ; threadDelay 500000
->          ; send fd (c_set [(10, 2000)]) })
+Set frequency at control bus
+> withSC3 (\fd -> send fd (c_set1 10 200))
+
+Oscillator reading frequency at control bus
+> audition (out 0 (sinOsc AR (lagIn 1 10 1) 0 * 0.1))
+
+Re-set frequency at control bus
+> withSC3 (\fd -> send fd (c_set1 10 2000))
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
@@ -1,81 +1,73 @@
-localBuf id nf nc
-maxLocalBufs n
-setBuf b xs o
-asLocalBuf id xs
-
-    id - node identifier
-    nf - number of frames (default: 1)
-    nc - number of channels for multiple channel buffers (default: 1)
-     n - maximum number of local buffers per graph
-     b - buffer identifier
-    xs - sequential values to store at buffer
-
-Allocate a buffer local to the synthesis graph.
+> Sound.SC3.UGen.Help.viewSC3Help "LocalBuf"
+> Sound.SC3.UGen.DB.ugenSummary "LocalBuf"
 
-> import Sound.SC3.Monadic
+# SC3
+automatically inserts a maxLocalBufs into graphs
 
-> do { n <- whiteNoise AR
->    ; let { m = maxLocalBufs 1
->          ; b = mrg2 (localBuf 'α' 2048 1) m
->          ; f = fft' b n
->          ; c = pv_BrickWall f (sinOsc KR 0.1 0 * 0.75) }
->      in audition (out 0 (ifft' c * 0.1)) }
+> import Sound.SC3.ID
 
-> do { n <- clone 2 (whiteNoise AR)
->    ; let { m = maxLocalBufs 2
->          ; b = mrg2 (mce (map (\i -> localBuf i 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)) }
+Allocate a buffer local to the synthesis graph.
+> let {n = whiteNoise 'α' AR
+>     ;m = maxLocalBufs 1
+>     ;b = mrg2 (localBuf 'α' 2048 1) m
+>     ;f = fft' b n
+>     ;c = pv_BrickWall f (sinOsc KR 0.1 0 * 0.75)}
+> in audition (out 0 (ifft' c * 0.1))
 
-not clearing the buffer accesses old data:
-slowly overwrite data with noise
+Variant with two local buffers
+> let {n = udup 2 (whiteNoise 'α' AR)
+>     ;m = maxLocalBufs 2
+>     ;b = mrg2 (udup 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))
 
-> let { m = maxLocalBufs 1
->     ; b = mrg2 (localBuf 'α' 2048 2) m
->     ; nf = bufFrames KR b
->     ; x = mouseX KR 1 2 Linear 0.2
->     ; r = playBuf 2 b x 1 0 Loop DoNothing * 0.1
->     ; wr ph i = bufWr b (linLin ph (-1) 1 0 nf) Loop i }
-> in do { n <- clone 2 (whiteNoise AR)
->       ; ph <- lfNoise0 AR 530
->       ; audition (mrg2 (out 0 r) (wr ph n)) }
+Not clearing the buffer accesses old data, slowly overwrite data with noise
+> let {m = maxLocalBufs 1
+>     ;b = mrg2 (localBuf 'α' 2048 2) m
+>     ;nf = bufFrames KR b
+>     ;x = mouseX' KR 1 2 Linear 0.2
+>     ;r = playBuf 2 AR b x 1 0 Loop DoNothing * 0.1
+>     ;wr p i = bufWr b (linLin p (-1) 1 0 nf) Loop i
+>     ;n = udup 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
-
-> do { d <- clone 2 (dust AR 1)
->    ; n <- whiteNoise AR
->    ; let { z = decay d 0.3 * n
->          ; l = xLine KR 0.0001 0.01 20 DoNothing
->          ; sr = sampleRate
->          ; m = maxLocalBufs 2
->          ; b = mrg2 (mce (map (\i -> localBuf i sr 2) ['α', 'β'])) m }
->      in audition (out 0 (bufCombC b z l 0.2)) }
+> let {d = udup 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}
+> in audition (out 0 (bufCombC b z l 0.2))
 
 asLocalBuf combines localBuf and setBuf
-
-> let { b = asLocalBuf 'α' [2, 1, 5, 3, 4, 0]
->     ; x = mouseX KR 0 (bufFrames KR b) Linear 0.2
->     ; f = indexL b x * 100 + 40
->     ; o = saw AR (f * mce2 1 1.1) * 0.1 }
+> let {b = asLocalBuf 'α' [2,1,5,3,4,0]
+>     ;x = mouseX' KR 0 (bufFrames KR b) Linear 0.2
+>     ;f = indexL b x * 100 + 40
+>     ;o = saw AR (f * mce2 1 1.1) * 0.1}
 > in audition (out 0 o)
 
-> let { b = asLocalBuf 'α' [2, 3, 4, 0, 1, 5]
->     ; n = bufFrames KR b
->     ; x = floorE (mouseX KR 0 n Linear 0.1)
->     ; i = detectIndex b x }
+detectIndex example using local buffer
+> let {b = asLocalBuf 'α' [2,3,4,0,1,5]
+>     ;n = bufFrames KR b
+>     ;x = floorE (mouseX' KR 0 n Linear 0.1)
+>     ;i = detectIndex b x}
 > in audition (out 0 (sinOsc AR (linExp i 0 n 200 700) 0 * 0.1))
 
-> do { n <- lfNoise1 KR (mce [3, 3.05])
->    ; let { x = mouseX KR 0 15 Linear 0.1
->          ; b = asLocalBuf 'α' [0, 2, 3.2, 5, 7, 9, 10]
->          ; k = degreeToKey b x 12
->          ; mk_c bf = let { f0 = midiCPS (bf + k + n * 0.04)
->                          ; o = sinOsc AR f0 0 * 0.1
->                          ; f1 = midiCPS (mce [48, 55])
->                          ; t = lfPulse AR f1 0.15 0.5
->                          ; f2 = midiCPS (sinOsc KR 0.1 0 * 10 + bf)
->                          ; d = rlpf t f2 0.1 * 0.1
->                          ; m = o + d }
->                  in combN m 0.31 0.31 2 + m }
->      in audition (out 0 ((mk_c 48 + mk_c 72) * 0.25)) }
+degreeToKey example using local buffer
+> let {n = lfNoise1 'a' KR (mce [3,3.05])
+>     ;x = mouseX' KR 0 15 Linear 0.1
+>     ;b = asLocalBuf 'α' [0,2,3.2,5,7,9,10]
+>     ;k = degreeToKey b x 12
+>     ;mk_c bf = let {f0 = midiCPS (bf + k + n * 0.04)
+>                    ;o = sinOsc AR f0 0 * 0.1
+>                    ;f1 = midiCPS (mce [48,55])
+>                    ;t = lfPulse AR f1 0.15 0.5
+>                    ;f2 = midiCPS (sinOsc KR 0.1 0 * 10 + bf)
+>                    ;d = rlpf t f2 0.1 * 0.1
+>                    ;m = o + d}
+>                 in combN m 0.31 0.31 2 + m}
+> in audition (out 0 ((mk_c 48 + mk_c 72) * 0.25))
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
@@ -1,20 +1,12 @@
-localIn numChannels rate
-
-Define and read from buses local to a SynthDef
-
-numChannels - the number of channels of local buses.
-
-LocalIn defines buses that are local to the SynthDef. These are like
-the global buses, but are more convenient if you want to implement a
-self contained effect that uses a feedback processing loop.  There can
-only be one audio rate and one control rate LocalIn per SynthDef.  The
-audio can be written to the bus using LocalOut.
+> Sound.SC3.UGen.Help.viewSC3Help "LocalIn"
+> Sound.SC3.UGen.DB.ugenSummary "LocalIn"
 
 > import Sound.SC3.ID
 
-> let { n = whiteNoise 'a' 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 
->     ; a3 = mceEdit reverse a2 * 0.8 }
-> in audition (mrg [localOut a3, out 0 a2])
+Ping-pong delay
+> let {n = whiteNoise 'a' 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
+>     ;a3 = mceEdit reverse a2 * 0.8}
+> in audition (mrg [localOut a3,out 0 a2])
diff --git a/Help/UGen/IO/localOut.help.lhs b/Help/UGen/IO/localOut.help.lhs
--- a/Help/UGen/IO/localOut.help.lhs
+++ b/Help/UGen/IO/localOut.help.lhs
@@ -1,38 +1,13 @@
-localOut signal
-
-Write to buses local to a synth.
-
-LocalOut writes to buses that are local to the enclosing synth. The
-buses should have been defined by a LocalIn ugen. The channelsArray
-must be the same number of channels as were declared in the
-LocalIn. These are like the global buses, but are more convenient if
-you want to implement a self contained effect that uses a feedback
-processing loop.  See [LocalIn].
-
-N.B. Audio written to a LocalOut will not be read by a corresponding
-LocalIn until the next cycle, i.e. one block size of samples
-later. Because of this it is important to take this additional delay
-into account when using LocalIn to create feedback delays with delay
-times shorter than the threshold of pitch (i.e. < 0.05 seconds or >
-20Hz), or where sample accurate alignment is required. See the
-resonator example below.
+> Sound.SC3.UGen.Help.viewSC3Help "LocalOut"
+> Sound.SC3.UGen.DB.ugenSummary "LocalOut"
 
 > import Sound.SC3.ID
 
-> let { n = whiteNoise 'a' 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
->     ; a3 = mceEdit reverse a2 * 0.8 }
-> in audition (mrg [localOut a3, out 0 a2])
-
 Resonator, must subtract blockSize for correct tuning
-
-> let { p = localIn 1 AR
->     ; i = impulse AR 1 0
->     ; d = delayC (i + (p * 0.995)) 1 (recip 440 - recip controlRate) }
-> in audition (mrg [offsetOut 0 p, localOut d])
+> let {p = localIn 1 AR
+>     ;i = impulse AR 1 0
+>     ;d = delayC (i + (p * 0.995)) 1 (recip 440 - recip controlRate)}
+> in audition (mrg [offsetOut 0 p,localOut d])
 
 Compare with oscillator.
-
 > audition (out 1 (sinOsc AR 440 0 * 0.2))
diff --git a/Help/UGen/IO/mouseButton.help.lhs b/Help/UGen/IO/mouseButton.help.lhs
--- a/Help/UGen/IO/mouseButton.help.lhs
+++ b/Help/UGen/IO/mouseButton.help.lhs
@@ -1,8 +1,10 @@
-mouseButton KR minval maxval lag
-
-Report the status of the first pointer button.  The button is either
-pressed, or not pressed.
+> Sound.SC3.UGen.Help.viewSC3Help "MouseButton"
+> Sound.SC3.UGen.DB.ugenSummary "MouseButton"
 
 > import Sound.SC3
 
+As amplitude envelope
 > audition (out 0 (sinOsc AR 800 0 * mouseButton KR 0 0.1 0.1))
+
+There is a variant that randomly presses the button.
+> audition (out 0 (sinOsc AR 800 0 * mouseButton' KR 0 0.1 0.1))
diff --git a/Help/UGen/IO/mouseX.help.lhs b/Help/UGen/IO/mouseX.help.lhs
--- a/Help/UGen/IO/mouseX.help.lhs
+++ b/Help/UGen/IO/mouseX.help.lhs
@@ -1,9 +1,12 @@
-mouseX KR minval maxval warp lag
-
-Report mouse location on root window of the machine that the synthesis
-server is running on.
+> Sound.SC3.UGen.Help.viewSC3Help "MouseX"
+> Sound.SC3.UGen.DB.ugenSummary "MouseX"
 
 > import Sound.SC3
 
+Frequency control
 > let x = mouseX KR 40 10000 Exponential 0.2
+> in audition (out 0 (sinOsc AR x 0 * 0.1))
+
+There is a variant with equal arguments but random traversal.
+> let x = mouseX' KR 40 10000 Exponential 0.2
 > in audition (out 0 (sinOsc AR x 0 * 0.1))
diff --git a/Help/UGen/IO/mouseY.help.lhs b/Help/UGen/IO/mouseY.help.lhs
--- a/Help/UGen/IO/mouseY.help.lhs
+++ b/Help/UGen/IO/mouseY.help.lhs
@@ -1,10 +1,14 @@
-mouseY KR minval maxval warp lag
-
-Report mouse location on root window of the machine that the
-synthesis server is running on.
+> Sound.SC3.UGen.Help.viewSC3Help "MouseY"
+> Sound.SC3.UGen.DB.ugenSummary "MouseY"
 
 > import Sound.SC3
 
-> let { freq = mouseX KR 20 2000 Exponential 0.1
->     ; ampl = mouseY KR 0.01 0.1 Linear 0.1 }
+Frequency at X axis and amplitude at Y axis.
+> let {freq = mouseX KR 20 2000 Exponential 0.1
+>     ;ampl = mouseY KR 0.01 0.1 Linear 0.1}
+> in audition (out 0 (sinOsc AR freq 0 * ampl))
+
+There is a variant with equal arguments but a random traversal.
+> let {freq = mouseX' KR 20 2000 Exponential 0.1
+>     ;ampl = mouseY' KR 0.01 0.1 Linear 0.1}
 > in audition (out 0 (sinOsc AR freq 0 * ampl))
diff --git a/Help/UGen/IO/offsetOut.help.lhs b/Help/UGen/IO/offsetOut.help.lhs
--- a/Help/UGen/IO/offsetOut.help.lhs
+++ b/Help/UGen/IO/offsetOut.help.lhs
@@ -1,14 +1,12 @@
-offsetOut bufferIndex inputs
- 
-Output signal to a bus, the sample offset within the bus is kept
-exactly.  This ugen is used where sample accurate output is needed.
+> Sound.SC3.UGen.Help.viewSC3Help "OffsetOut"
+> Sound.SC3.UGen.DB.ugenSummary "OffsetOut"
 
 > import Sound.SC3
 
-> let { a = offsetOut 0 (impulse AR 5 0)
->     ; b = out 0 (sinOsc AR 60 0 * 0.1) }
-> in audition (mrg [a, b])
+> let {a = offsetOut 0 (impulse AR 5 0)
+>     ;b = out 0 (sinOsc AR 60 0 * 0.1)}
+> in audition (mrg [a,b])
 
-> let { a = out 0 (impulse AR 5 0)
->     ; b = out 0 (sinOsc AR 60 0 * 0.1) }
-> in audition (mrg [a, b])
+> let {a = out 0 (impulse AR 5 0)
+>     ;b = out 0 (sinOsc AR 60 0 * 0.1) }
+> in audition (mrg [a,b])
diff --git a/Help/UGen/IO/out.help.lhs b/Help/UGen/IO/out.help.lhs
--- a/Help/UGen/IO/out.help.lhs
+++ b/Help/UGen/IO/out.help.lhs
@@ -1,9 +1,11 @@
-out bufferIndex inputs
-
-Send signal to an audio or control buss, mix with existing signal.
-The user is responsible for making sure that the number of channels
-match and that there are no conflicts.
+> Sound.SC3.UGen.Help.viewSC3Help "Out"
+> Sound.SC3.UGen.DB.ugenSummary "Out"
 
 > import Sound.SC3
 
-> audition (out 0 (sinOsc AR (mce [330, 331]) 0 * 0.1))
+Oscillators at outputs zero (330) and one (331)
+> audition (out 0 (sinOsc AR (mce2 330 331) 0 * 0.1))
+
+out is summing, as opposed to replaceOut
+> audition (mrg [out 0 (sinOsc AR (mce2 330 990) 0 * 0.1)
+>               ,out 0 (sinOsc AR (mce2 331 991) 0 * 0.1)])
diff --git a/Help/UGen/IO/replaceOut.help.lhs b/Help/UGen/IO/replaceOut.help.lhs
--- a/Help/UGen/IO/replaceOut.help.lhs
+++ b/Help/UGen/IO/replaceOut.help.lhs
@@ -1,17 +1,16 @@
-replaceOut bufferIndex inputs
-
-Send signal to a bus, overwrite existing signal.
+> Sound.SC3.UGen.Help.viewSC3Help "ReplaceOut"
+> Sound.SC3.UGen.DB.ugenSummary "ReplaceOut"
 
 > import Sound.SC3
 
-> let { a = out 0 (sinOsc AR (mce [330, 331]) 0 * 0.1)
->     ; b = replaceOut 0 (sinOsc AR (mce [880, 881]) 0 * 0.1)
->     ; c = out 0 (sinOsc AR (mce [120, 121]) 0 * 0.1) }
+Send signal to a bus, overwrite existing signal.
+> let {a = out 0 (sinOsc AR (mce [330, 331]) 0 * 0.1)
+>     ;b = replaceOut 0 (sinOsc AR (mce [880, 881]) 0 * 0.1)
+>     ;c = out 0 (sinOsc AR (mce [120, 121]) 0 * 0.1)}
 > in audition (mrg [a, b, c])
 
-Compare to:
-
-> let { a = out 0 (sinOsc AR (mce [330, 331]) 0 * 0.1)
->     ; b = out 0 (sinOsc AR (mce [880, 881]) 0 * 0.1)
->     ; c = out 0 (sinOsc AR (mce [120, 121]) 0 * 0.1) }
+Compare to
+> let {a = out 0 (sinOsc AR (mce [330, 331]) 0 * 0.1)
+>     ;b = out 0 (sinOsc AR (mce [880, 881]) 0 * 0.1)
+>     ;c = out 0 (sinOsc AR (mce [120, 121]) 0 * 0.1)}
 > in audition (mrg [a, b, c])
diff --git a/Help/UGen/IO/soundIn.help.lhs b/Help/UGen/IO/soundIn.help.lhs
--- a/Help/UGen/IO/soundIn.help.lhs
+++ b/Help/UGen/IO/soundIn.help.lhs
@@ -1,14 +1,9 @@
-soundIn channel
-
-Read audio from the sound input hardware.
+> Sound.SC3.UGen.Help.viewSC3Help "SoundIn"
 
-channel - input channel number to read, 
-          indexed from zero, can be mce.
+# composite
 
 > import Sound.SC3
 
 > audition (out 0 (soundIn 0))
-
 > audition (out 0 (soundIn (mce2 0 1)))
-
 > audition (out 0 (soundIn (mce [0, 2, 1, 3])))
diff --git a/Help/UGen/IO/xOut.help.lhs b/Help/UGen/IO/xOut.help.lhs
--- a/Help/UGen/IO/xOut.help.lhs
+++ b/Help/UGen/IO/xOut.help.lhs
@@ -1,13 +1,13 @@
-xOut bufferIndex xFade inputs
- 
-Send signal to a bus, crossfading with existing contents.
+> Sound.SC3.UGen.Help.viewSC3Help "XOut"
+> Sound.SC3.UGen.DB.ugenSummary "XOut"
 
 > import Sound.SC3
 
-> let { p a b = sinOsc AR (mce [a, b]) 0 * 0.1
->     ; x = mouseX KR 0 1 Linear 0.1
->     ; y = mouseY KR 0 1 Linear 0.1 }
-> in audition (mrg [ out  0   (p 220 221)
->                  , xOut 0 x (p 330 331)
->                  , xOut 0 y (p 440 441)
->                  , out  0   (p 120 121)])
+Send signal to a bus, crossfading with existing contents.
+> let {p a b = sinOsc AR (mce [a, b]) 0 * 0.1
+>     ;x = mouseX' KR 0 1 Linear 0.1
+>     ;y = mouseY' KR 0 1 Linear 0.1}
+> in audition (mrg [out  0   (p 220 221)
+>                  ,xOut 0 x (p 330 331)
+>                  ,xOut 0 y (p 440 441)
+>                  ,out  0   (p 120 121)])
diff --git a/Help/UGen/Information/controlRate.help.lhs b/Help/UGen/Information/controlRate.help.lhs
--- a/Help/UGen/Information/controlRate.help.lhs
+++ b/Help/UGen/Information/controlRate.help.lhs
@@ -1,1 +1,7 @@
-controlRate
+> Sound.SC3.UGen.Help.viewSC3Help "ControlRate"
+> Sound.SC3.UGen.DB.ugenSummary "ControlRate"
+
+> import Sound.SC3
+
+play a sine tone at control rate
+> audition (out 0 (sinOsc AR controlRate 0 * 0.1))
diff --git a/Help/UGen/Information/numAudioBuses.help.lhs b/Help/UGen/Information/numAudioBuses.help.lhs
--- a/Help/UGen/Information/numAudioBuses.help.lhs
+++ b/Help/UGen/Information/numAudioBuses.help.lhs
@@ -1,1 +1,3 @@
-numAudioBuses
+> Sound.SC3.UGen.Help.viewSC3Help "NumAudioBuses"
+> Sound.SC3.UGen.DB.ugenSummary "NumAudioBuses"
+
diff --git a/Help/UGen/Information/numBuffers.help.lhs b/Help/UGen/Information/numBuffers.help.lhs
--- a/Help/UGen/Information/numBuffers.help.lhs
+++ b/Help/UGen/Information/numBuffers.help.lhs
@@ -1,1 +1,2 @@
-numBuffers
+> Sound.SC3.UGen.Help.viewSC3Help "NumBuffers"
+> Sound.SC3.UGen.DB.ugenSummary "NumBuffers"
diff --git a/Help/UGen/Information/numControlBuses.help.lhs b/Help/UGen/Information/numControlBuses.help.lhs
--- a/Help/UGen/Information/numControlBuses.help.lhs
+++ b/Help/UGen/Information/numControlBuses.help.lhs
@@ -1,1 +1,2 @@
-numControlBuses
+> Sound.SC3.UGen.Help.viewSC3Help "NumControlBuses"
+> Sound.SC3.UGen.DB.ugenSummary "NumControlBuses"
diff --git a/Help/UGen/Information/numInputBuses.help.lhs b/Help/UGen/Information/numInputBuses.help.lhs
--- a/Help/UGen/Information/numInputBuses.help.lhs
+++ b/Help/UGen/Information/numInputBuses.help.lhs
@@ -1,1 +1,2 @@
-numInputBuses
+> Sound.SC3.UGen.Help.viewSC3Help "NumInputBuses"
+> Sound.SC3.UGen.DB.ugenSummary "NumInputBuses"
diff --git a/Help/UGen/Information/numOutputBuses.help.lhs b/Help/UGen/Information/numOutputBuses.help.lhs
--- a/Help/UGen/Information/numOutputBuses.help.lhs
+++ b/Help/UGen/Information/numOutputBuses.help.lhs
@@ -1,1 +1,2 @@
-numOutputBuses
+> Sound.SC3.UGen.Help.viewSC3Help "NumOutputBuses"
+> Sound.SC3.UGen.DB.ugenSummary "NumOutputBuses"
diff --git a/Help/UGen/Information/numRunningSynths.help.lhs b/Help/UGen/Information/numRunningSynths.help.lhs
--- a/Help/UGen/Information/numRunningSynths.help.lhs
+++ b/Help/UGen/Information/numRunningSynths.help.lhs
@@ -1,5 +1,5 @@
-numRunningSynths
-
-Number of currently running synths.
+> Sound.SC3.UGen.Help.viewSC3Help "NumRunningSynths"
+> Sound.SC3.UGen.DB.ugenSummary "NumRunningSynths"
 
+each concurrent audition increases oscillator frequency
 > audition (out 0 (sinOsc AR (numRunningSynths * 200 + 400) 0 * 0.1))
diff --git a/Help/UGen/Information/radiansPerSample.help.lhs b/Help/UGen/Information/radiansPerSample.help.lhs
--- a/Help/UGen/Information/radiansPerSample.help.lhs
+++ b/Help/UGen/Information/radiansPerSample.help.lhs
@@ -1,2 +1,3 @@
-radiansPerSample
+> Sound.SC3.UGen.Help.viewSC3Help "RadiansPerSample"
+> Sound.SC3.UGen.DB.ugenSummary "RadiansPerSample"
 
diff --git a/Help/UGen/Information/sampleDur.help.lhs b/Help/UGen/Information/sampleDur.help.lhs
--- a/Help/UGen/Information/sampleDur.help.lhs
+++ b/Help/UGen/Information/sampleDur.help.lhs
@@ -1,3 +1,2 @@
-sampleDur
-
-Duration of one sample.  Equivalent to 1 / sampleRate.
+> Sound.SC3.UGen.Help.viewSC3Help "SampleDur"
+> Sound.SC3.UGen.DB.ugenSummary "SampleDur"
diff --git a/Help/UGen/Information/sampleRate.help.lhs b/Help/UGen/Information/sampleRate.help.lhs
--- a/Help/UGen/Information/sampleRate.help.lhs
+++ b/Help/UGen/Information/sampleRate.help.lhs
@@ -1,15 +1,15 @@
-sampleRate
+> Sound.SC3.UGen.Help.viewSC3Help "SampleRate"
+> Sound.SC3.UGen.DB.ugenSummary "SampleRate"
 
-Server sample rate.
+> import Sound.SC3
 
 Compare a sine tone derived from sample rate with a 440Hz tone.
-
 > let f = mce [sampleRate * 0.01, 440]
 > in audition (out 0 (sinOsc AR f 0 * 0.1))
 
-The server status command can extract nominal and
-actual sample rates from a running server.
-
-> withSC3 (\fd -> liftM2 (,)
->                        (serverSampleRateNominal fd)
->                        (serverSampleRateActual fd))
+The server status command can extract nominal and actual sample rates
+from a running server.
+> withSC3 (\fd -> Control.Monad.liftM2
+>                 (,)
+>                 (serverSampleRateNominal fd)
+>                 (serverSampleRateActual fd))
diff --git a/Help/UGen/Information/subsampleOffset.help.lhs b/Help/UGen/Information/subsampleOffset.help.lhs
--- a/Help/UGen/Information/subsampleOffset.help.lhs
+++ b/Help/UGen/Information/subsampleOffset.help.lhs
@@ -1,34 +1,29 @@
-subsampleOffset
-
-Offset from synth start within one sample.
+> Sound.SC3.UGen.Help.viewSC3Help "SubsampleOffset"
+> Sound.SC3.UGen.DB.ugenSummary "SubsampleOffset"
 
-When a synth is created from a time stamped osc-bundle, it starts
-calculation at the next possible block (normally 64 samples). Using
-an OffsetOut ugen, one can delay the audio so that it matches
-sample accurately.  For some synthesis methods, one needs subsample
-accuracy. SubsampleOffset provides the information where, within
-the current sample, the synth was scheduled. It can be used to
-offset envelopes or resample the audio output.
+> import Sound.OpenSoundControl
+> import Sound.SC3
 
-See also OffsetOut.
+Impulse train that can be moved between samples
+> let s = let {a = control KR "a" 0
+>             ;i = impulse AR 2000 0 * 0.3
+>             ;d = sampleDur
+>             ;x = 4
+>             ;o = (1 - subsampleOffset) + mouseX' KR 0 a Linear 0.1
+>             ;r = delayC i (d * (1 + x)) (d * (o + x))}
+>         in (synthdef "s" (offsetOut 0 r))
 
-Demonstrate cubic subsample interpolation.  An impulse train that can
-be moved between samples.  Create two pulse trains one sample apart,
-move one relative to the other.  When cursor is at the left, the
-impulses are adjacent, on the right, they are exactly 1 sample apart.
-View this with an oscilloscope.
+Create two pulse trains one sample apart, move one relative to the
+other.  When cursor is at the left, the impulses are adjacent, on the
+right, they are exactly 1 sample apart.  View this with an
+oscilloscope.
+> let run s fd = do
+>       {_ <- async fd (d_recv s)
+>       ;t <- utcr
+>       ;let {t' = t + 0.2
+>            ;dt = 1 / 44100.0
+>            ;m n = s_new "s" (-1) AddToTail 1 [("a", n)]}
+>        in do {send fd (Bundle (UTCr t') [m 3])
+>              ;send fd (Bundle (UTCr (t' + dt)) [m 0]) }}
 
-> let { a = control KR "a" 0
->     ; i = impulse AR 2000 0 * 0.3
->     ; d = sampleDur
->     ; x = 4
->     ; o = (1 - subsampleOffset) + mouseX KR 0 a Linear 0.1
->     ; r = delayC i (d * (1 + x)) (d * (o + x))
->     ; g = offsetOut 0 r }
-> in withSC3 (\fd -> do { async fd (d_recv (synthdef "s" g))
->                       ; t <- utcr
->                       ; let { t' = t + 0.2
->                             ; dt = 1 / 44100.0
->                             ; m n = s_new "s" (-1) AddToTail 1 [("a", n)] }
->                         in do { send fd (Bundle (UTCr t') [m 3])
->                               ; send fd (Bundle (UTCr (t' + dt)) [m 0]) } })
+> withSC3 (run s)
diff --git a/Help/UGen/MachineListening/beatTrack.help.lhs b/Help/UGen/MachineListening/beatTrack.help.lhs
--- a/Help/UGen/MachineListening/beatTrack.help.lhs
+++ b/Help/UGen/MachineListening/beatTrack.help.lhs
@@ -1,60 +1,15 @@
-beatTrack c lock
-
-     c - Audio input to track, already passed through an FFT
-         UGen; the expected size of FFT is 1024 for 44100
-         and 48000 sampling rate, and 2048 for double
-         those. No other sampling rates are supported.
-
-  lock - If this argument is greater than 0.5, the tracker
-         will lock at its current periodicity and continue
-         from the current phase. Whilst it updates the
-         model's phase and period, this is not reflected in
-         the output until lock goes back below 0.5.
-
-Autocorrelation based beat tracker; the underlying model
-assumes 4/4, but it should work on any isochronous beat
-structure, though there are biases to 100-120 bpm; a fast
-7/8 may not be tracked in that sense. There are four k-rate
-outputs, being ticks at quarter, eighth and sixteenth level
-from the determined beat, and the current detected
-tempo. Note that the sixteenth note output won't necessarily
-make much sense if the music being tracked has swing; it is
-provided just as a convenience.
-
-This beat tracker determines the beat, biased to the
-midtempo range by weighting functions. It does not determine
-the measure level, only a tactus. It is also slow reacting,
-using a 6 second temporal window for its autocorrelation
-maneouvres. Don't expect human musician level predictive
-tracking.
-
-On the other hand, it is tireless, relatively general
-(though obviously best at transient 4/4 heavy material
-without much expressive tempo variation), and can form the
-basis of computer processing that is decidedly faster than
-human.
+> Sound.SC3.UGen.Help.viewSC3Help "BeatTrack"
+> Sound.SC3.UGen.DB.ugenSummary "BeatTrack"
 
 > import Sound.SC3
 
 > let { i = soundIn 0
->     ; x = mouseX KR (-1) 1 Linear 0.2
+>     ; x = mouseX' KR (-1) 1 Linear 0.2
 >     ; MCE [b, h, q, t] = beatTrack (fft' 10 i) x
 >     ; f = mce [440, 660, 880]
 >     ; a = mce [0.4, 0.2, 0.1]
 >     ; s = mix (sinOsc AR f 0 * a * decay (mce [b, h, q]) 0.05) }
 > in withSC3 (\fd -> do { async fd (b_alloc 10 1024 1)
 >                       ; play fd (out 0 (i + s)) })
-
-Davies, M. E. P.  and Plumbley, M. D. Beat Tracking With A
-Two State Model. Proceedings of the IEEE International
-Conference on Acoustics, Speech and Signal Processing
-(ICASSP 2005), Philadelphia, USA, March 19-23, 2005
-
-The UGen was converted by Nick Collins for beat tracking
-research in the course of his PhD and uses an original C
-implementation of Matthew Davies' MATLAB model. It first
-appeared as part of BBCut2 as AutoTrack but has now been
-added to core to enhance SuperCollider's realtime machine
-listening options.
 
 
diff --git a/Help/UGen/MachineListening/loudness.help.lhs b/Help/UGen/MachineListening/loudness.help.lhs
--- a/Help/UGen/MachineListening/loudness.help.lhs
+++ b/Help/UGen/MachineListening/loudness.help.lhs
@@ -1,44 +1,14 @@
-loudness chain smask tmask
-
-Extraction of instantaneous loudness in sones.
-
- chain [fft] - Audio input to track, which has been pre-analysed by
-               the FFT UGen; see examples below for the expected FFT
-               size
-
-  smask [sk] - Spectral masking param: lower bins mask higher bin
-               power within ERB bands, with a power falloff (leaky
-               integration multiplier) of smask per bin. (=0.25)
-
-  tmask [sk] - Temporal masking param: the phon level let through in
-               an ERB band is the maximum of the new measurement, and
-               the previous minus tmask phons (=6)
-
-A perceptual loudness function which outputs loudness in sones; this
-is a variant of an MP3 perceptual model, summing excitation in ERB
-bands. It models simple spectral and temporal masking, with equal
-loudness contour correction in ERB bands to obtain phons (relative
-dB), then a phon to sone transform. The final output is typically in
-the range of 0 to 64 sones, though higher values can occur with
-specific synthesised stimuli
-
- given a sinOsc at 1000hz: gain 0.001 => loudness 1 sone
-                           gain 0.010 => loudness 4 sone
-                           gain 0.100 => loudness 16 sone
-                           gain 1.000 => loudness 64 sone
-
-Assume hop of half fftsize.
+> Sound.SC3.UGen.Help.viewSC3Help "Loudness"
+> Sound.SC3.UGen.DB.ugenSummary "Loudness"
 
 > import Sound.SC3
 
-> let { b = 10
->     ; x = mouseX KR 0.001 0.1 Exponential 0.2
+Assume hop of half fftsize
+> withSC3 (\fd -> async fd (b_alloc 10 1024 1))
+
+> let { x = mouseX' KR 0.001 0.1 Exponential 0.2
 >     ; i = sinOsc AR 1000 0 * x
->     ; f = fft' (constant b) i
+>     ; f = fft' 10 i
 >     ; l = loudness f 0.25 6
 >     ; o = sinOsc AR (mce2 900 (l * 300 + 600)) 0 * 0.1 }
-> in withSC3 (\fd -> do { async fd (b_alloc b 1024 1)
->                       ; audition (out 0 o) })
-
-Research note: This UGen is an informal juxtaposition of perceptual
-coding, and a Zwicker and Glasberg/Moore/Stone loudness model.
+> in audition (out 0 o)
diff --git a/Help/UGen/MachineListening/onsets.help.lhs b/Help/UGen/MachineListening/onsets.help.lhs
--- a/Help/UGen/MachineListening/onsets.help.lhs
+++ b/Help/UGen/MachineListening/onsets.help.lhs
@@ -1,104 +1,34 @@
-onsets c threshold odftype relaxtime floor mingap medianspan whtype rawodf
-onsets' c threshold odftype
-
-An onset detector for musical audio signals - detects the
-beginning of notes/drumbeats/etc. Outputs a control-rate
-trigger signal which is 1 when an onset is detected, and 0
-otherwise.
-
-          c - an FFT chain
-
-  threshold - the detection threshold, typically between 0
-              and 1, although in rare cases you may find
-              values outside this range useful
-
-    odftype - the function used to analyse the signal
-              (options described below; OK to leave this at
-              its default value)
-
-  relaxtime - specifies the time (in seconds) for the
-              normalisation to "forget" about a recent
-              onset. If you find too much re-triggering
-              (e.g. as a note dies away unevenly) then you
-              might wish to increase this value.
-
-      floor - is a lower limit, connected to the idea of how
-              quiet the sound is expected to get without
-              becoming indistinguishable from noise. For
-              some cleanly-recorded classical music with
-              wide dynamic variations, I found it helpful to
-              go down as far as 0.000001.
-
-     mingap - specifies a minimum gap (in seconds) between
-              onset detections, a brute-force way to prevent
-              too many doubled detections.
-
- medianspan - specifies the size (in FFT frames) of the
-              median window used for smoothing the detection
-              function before triggering.
-
-For the FFT chain, you should typically use a frame size of
-512 or 1024 (at 44.1 kHz sampling rate) and 50% hop size
-(which is the default setting in SC). For different sampling
-rates choose an FFT size to cover a similar time-span
-(around 10 to 20 ms).
+> Sound.SC3.UGen.Help.viewSC3Help "Onsets"
+> Sound.SC3.UGen.DB.ugenSummary "Onsets"
 
-The onset detection should work well for a general range of
-monophonic and polyphonic audio signals. The onset detection
-is purely based on signal analysis and does not make use of
-any "top-down" inferences such as tempo.
+> import Sound.SC3.ID
 
-> import Sound.SC3
+allocate buffer 10
+> withSC3 (\fd -> async fd (b_alloc 10 512 1))
 
-> let { x = mouseX KR 0 1 Linear 0.2
+> let { x = mouseX' KR 0 1 Linear 0.2
 >     ; i = soundIn 0
 >     ; c = fft' 10 i
 >     ; o = onsets' c x (onsetType "rcomplex")
 >     ; s = sinOsc AR 440 0 * 0.2
 >     ; e = envGen KR o 1 0 1 DoNothing (envPerc 0.001 0.1) }
-> in withSC3 (\fd -> do { async fd (b_alloc 10 512 1)
->                       ; play fd (out 0 (s * e)) })
+> in audition (out 0 (s * e))
 
 > audition (out 0 (soundIn 0 * 0.1))
 
-The type argument chooses which onset detection function is
-used. In many cases the default will be fine. The following
-choices are available:
-
-    power - generally OK, good for percussive input, and
-            also very efficient
-
-   magsum - generally OK, good for percussive input, and
-            also very efficient
-
-  complex - performs generally very well, but more
-            CPU-intensive
-
- rcomplex - performs generally very well, and slightly more
-            efficient than complex
-
-    phase - generally good, especially for tonal input,
-            medium efficiency
-
-   wphase - generally very good, especially for tonal input,
-            medium efficiency
-
-      mkl - generally very good, medium efficiency, pretty
-            different from the other methods
-
-Which of these should you choose? The differences aren't
-large, so I'd recommend you stick with the default \rcomplex
-unless you find specific problems with it. Then maybe try
-\wphase. The \mkl type is a bit different from the others so
-maybe try that too. They all have slightly different
-characteristics, and in tests perform at a similar quality
-level.
+a generative signal with distinct onsets!
+> let z = let {e = linLin (saw AR 2) (-1) 1 0 1
+>             ;p = let f = midiCPS (tIRand 'a' 63 75 (impulse KR 2 0))
+>                  in pulse AR f 0.5
+>             ;f = linExp (lfNoise2 'a' KR 0.5) (-1) 1 100 10000}
+>         in lpf p f * e
 
-For more details of all the processes involved, the
-different onset detection functions, and their evaluation,
-see
+> audition (out 0 z)
 
-D. Stowell and M. D. Plumbley. Adaptive whitening for
-improved real-time audio onset detection. Proceedings of the
-International Computer Music Conference (ICMC’07),
-Copenhagen, Denmark, August 2007.
+x varies threshold, whitenoise bursts indicate detected onsets
+> let {c = fft' 10 z
+>     ;x = mouseX' KR 0 1 Linear 0.2
+>     ;o = onsets' c x (onsetType "rcomplex")
+>     ;p = let d = envPerc 0.001 0.1
+>          in whiteNoise 'a' AR * envGen KR o 0.2 0 1 DoNothing d}
+> in audition (out 0 (pan2 z (-0.75) 0.2 + pan2 p 0.75 1))
diff --git a/Help/UGen/Math/abs.help.lhs b/Help/UGen/Math/abs.help.lhs
--- a/Help/UGen/Math/abs.help.lhs
+++ b/Help/UGen/Math/abs.help.lhs
@@ -1,6 +1,5 @@
-abs a
-
-Absolute value.
+> Sound.SC3.UGen.Help.viewSC3Help "Operator.abs"
+> :t abs
 
 > import Sound.SC3
 
diff --git a/Help/UGen/Math/absDif.help.lhs b/Help/UGen/Math/absDif.help.lhs
--- a/Help/UGen/Math/absDif.help.lhs
+++ b/Help/UGen/Math/absDif.help.lhs
@@ -1,10 +1,9 @@
-absDif a b
-
-Calculates the value of (abs (- a b). Finding the magnitude of the
-difference of two values is a common operation.
+> Sound.SC3.UGen.Help.viewSC3Help "Operator.absdif"
+> :t absDif
 
 > import Sound.SC3
 
-> let { p = fSinOsc AR 440 0
->     ; q = fSinOsc AR 2 0 * 0.5 }
-> in audition (out 0 (p * absDif 0.2 q))
+Finding the magnitude of the difference of two values is a common operation.
+> let {p = fSinOsc AR 440 0
+>     ;q = fSinOsc AR 2 0 * 0.5}
+> in audition (out 0 (p * 0.2 `absDif` q))
diff --git a/Help/UGen/Math/add.help.lhs b/Help/UGen/Math/add.help.lhs
--- a/Help/UGen/Math/add.help.lhs
+++ b/Help/UGen/Math/add.help.lhs
@@ -1,4 +1,5 @@
-a + b
+> Sound.SC3.UGen.Help.viewSC3Help "Operator.+"
+> :t (+)
 
 > import Sound.SC3.ID
 
@@ -7,5 +8,4 @@
 > in audition (out 0 ((o + n) * 0.1))
 
 DC offset.
-
 > audition (out 0 ((fSinOsc AR 440 0 * 0.1) + 0.5))
diff --git a/Help/UGen/Math/amClip.help.lhs b/Help/UGen/Math/amClip.help.lhs
--- a/Help/UGen/Math/amClip.help.lhs
+++ b/Help/UGen/Math/amClip.help.lhs
@@ -1,6 +1,5 @@
-amClip a b
-
-0 when b <= 0, a*b when b > 0
+> Sound.SC3.UGen.Help.viewSC3Help "Operator.amclip"
+> :t amClip
 
 > import Sound.SC3.ID
 
diff --git a/Help/UGen/Math/atan2.help.lhs b/Help/UGen/Math/atan2.help.lhs
--- a/Help/UGen/Math/atan2.help.lhs
+++ b/Help/UGen/Math/atan2.help.lhs
@@ -1,15 +1,11 @@
-atan2 x y
-
-Returns the arctangent of y/x.
+> Sound.SC3.UGen.Help.viewSC3Help "Operator.atan2"
+> :t atan2
 
-See also hypot.
+> import Sound.SC3
 
 Add a pan to the hypot doppler examples by using atan2 to find the
 azimuth, or direction angle, of the sound source.  Assume speakers
 at +/- 45 degrees and clip the direction to between those.
-
-> import Sound.SC3
-
 > let { x = 10
 >     ; y = lfSaw KR (1 / 6) 0 * 100
 >     ; d = hypot x y
diff --git a/Help/UGen/Math/clip2.help.lhs b/Help/UGen/Math/clip2.help.lhs
--- a/Help/UGen/Math/clip2.help.lhs
+++ b/Help/UGen/Math/clip2.help.lhs
@@ -1,9 +1,9 @@
-clip2 a b
-
-Bilateral clipping.  Clips a to +/- b
+> Sound.SC3.UGen.Help.viewSC3Help "Operator.clip2"
+> :t clip2
 
 > import Sound.SC3
 
+clipping distortion
 > audition (out 0 (clip2 (fSinOsc AR 400 0) 0.2))
 
 > let l = line KR 0 1 8 RemoveSynth
diff --git a/Help/UGen/Math/dbAmp.help.lhs b/Help/UGen/Math/dbAmp.help.lhs
--- a/Help/UGen/Math/dbAmp.help.lhs
+++ b/Help/UGen/Math/dbAmp.help.lhs
@@ -1,9 +1,12 @@
-dbAmp a
-
-Convert decibels to linear amplitude.
+> Sound.SC3.UGen.Help.viewSC3Help "Operator.dbamp"
+> :t dbAmp
 
 > import Sound.SC3
 
-> let { a = dbAmp (line KR (-6) (-40) 10 RemoveSynth)
->     ; o = fSinOsc AR 800 0 * a }
+Linear db motion is exponential amplitude decay
+> let {a = dbAmp (line KR (-6) (-40) 10 RemoveSynth)
+>     ;o = fSinOsc AR 800 0 * a}
 > in audition (out 0 o)
+
+There is a non-UGen variant.
+> dbAmp (-26::Double)
diff --git a/Help/UGen/Math/difSqr.help.lhs b/Help/UGen/Math/difSqr.help.lhs
--- a/Help/UGen/Math/difSqr.help.lhs
+++ b/Help/UGen/Math/difSqr.help.lhs
@@ -1,8 +1,5 @@
-difSqr a b
-
-Difference of squares.  Return the value of (a*a) - (b*b). This is
-more efficient than using separate unit generators for each
-operation.
+> Sound.SC3.UGen.Help.viewSC3Help "Operator.difsqr"
+> :t difSqr
 
 > import Sound.SC3
 
@@ -11,7 +8,6 @@
 > in audition (out 0 (difSqr a b * 0.125))
 
 Written out:
-
 > let { a = fSinOsc AR 800 0
 >     ; b = fSinOsc AR (xLine KR 200 500 5 DoNothing) 0 }
 > in audition (out 0 ((a * a - b * b) * 0.125))
diff --git a/Help/UGen/Math/distort.help.lhs b/Help/UGen/Math/distort.help.lhs
--- a/Help/UGen/Math/distort.help.lhs
+++ b/Help/UGen/Math/distort.help.lhs
@@ -1,9 +1,8 @@
-distort a
-
-Nonlinear distortion.
+> Sound.SC3.UGen.Help.viewSC3Help "Operator.distort"
+> :t distort
 
 > import Sound.SC3
 
-> let { e = xLine KR 0.1 10 10 DoNothing
->     ; o = fSinOsc AR 500 0.0 }
+> let {e = xLine KR 0.1 10 10 DoNothing
+>     ;o = fSinOsc AR 500 0.0}
 > in audition (out 0 (distort (o * e) * 0.25))
diff --git a/Help/UGen/Math/excess.help.lhs b/Help/UGen/Math/excess.help.lhs
--- a/Help/UGen/Math/excess.help.lhs
+++ b/Help/UGen/Math/excess.help.lhs
@@ -1,7 +1,5 @@
-excess a b
-
-Clipping residual.  Returns the difference of the original signal and
-its clipped form: (a - clip2(a,b)).
+> Sound.SC3.UGen.Help.viewSC3Help "Operator.excess"
+> :t excess
 
 > import Sound.SC3
 
@@ -9,6 +7,7 @@
 >     ; l = line KR 0 1 8 DoNothing }
 > in audition (out 0 (excess o l))
 
+or written out in terms of clip2
 > let { o = fSinOsc AR 1000 0
 >     ; l = line KR 0 1 8 DoNothing }
 > in audition (out 0 (o - (clip2 o l)))
diff --git a/Help/UGen/Math/fdiv.help.lhs b/Help/UGen/Math/fdiv.help.lhs
--- a/Help/UGen/Math/fdiv.help.lhs
+++ b/Help/UGen/Math/fdiv.help.lhs
@@ -1,8 +1,5 @@
-a / b
-
-Division, written '/'.
-
-Division can be tricky with signals because of division by zero.
+> Sound.SC3.UGen.Help.viewSC3Help "Operator./"
+> :t (/)
 
 > import Sound.SC3.ID
 
diff --git a/Help/UGen/Math/fold2.help.lhs b/Help/UGen/Math/fold2.help.lhs
--- a/Help/UGen/Math/fold2.help.lhs
+++ b/Help/UGen/Math/fold2.help.lhs
@@ -1,6 +1,5 @@
-fold2 a b
-
-Bilateral folding.  Folds a to +/- b.
+> Sound.SC3.UGen.Help.viewSC3Help "Operator.fold2"
+> :t fold2
 
 > import Sound.SC3
 
diff --git a/Help/UGen/Math/gt.help.lhs b/Help/UGen/Math/gt.help.lhs
--- a/Help/UGen/Math/gt.help.lhs
+++ b/Help/UGen/Math/gt.help.lhs
@@ -1,23 +1,19 @@
-a >* b
-a >=* b
-a <* b
-a <=* b
-a ==* b
-
-Greater than, written '>*'.  The star extensions are because the
-result of the operatros is not of type Bool, as is required by the
-signature for the class Ord.
-
-The resulting signal is 1.0 if a > b, otherwise it is 0.0. Similarly
-less than is <*, greater than or equal to is >=*, and so on.  
+> Sound.SC3.UGen.Help.viewSC3Help "Operator.=="
+> :t (==*)
 
-These operators can be useful for triggering purposes, among other
-things.
+#hsc3
+The star suffixes (<*,<=*,>*,>=*) are because the result of the
+operatros is not of type Bool, as is required by the signature for the
+class Ord.
 
 > import Sound.SC3
 
 > let { o = sinOsc KR 1 0
->     ; t = [o >* 0, o >=* 0, o <* 0, o <=* 0, o ==* 0
+>     ; t = [o >* 0
+>           ,o >=* 0
+>           ,o <* 0
+>           ,o <=* 0
+>           ,o ==* 0
 >           ,(o <* 0.001) * (o >* (-0.001))]
 >     ; f = [220, 330, 440, 550, 660, 770]
 >     ; p = envPerc 0.01 1
diff --git a/Help/UGen/Math/hypot.help.lhs b/Help/UGen/Math/hypot.help.lhs
--- a/Help/UGen/Math/hypot.help.lhs
+++ b/Help/UGen/Math/hypot.help.lhs
@@ -1,17 +1,14 @@
-hypot x y
-
-Returns the square root of the sum of the squares of a and b. Or
-equivalently, the distance from the origin to the point (x, y).
+> Sound.SC3.UGen.Help.viewSC3Help "Operator.hypot"
+> :t hypot
 
 > import Sound.SC3
 
-> let { x = mouseX KR 0 0.1 Linear 0.1
->     ; y = mouseY KR 0 0.1 Linear 0.1 }
+> let { x = mouseX' KR 0 0.1 Linear 0.1
+>     ; y = mouseY' KR 0 0.1 Linear 0.1 }
 > in audition (out 0 (sinOsc AR 440 0 * hypot x y))
 
 Object travels 200 meters in 6 secs (=120kph) passing 10 meters
 from the listener.  The speed of sound is 344 meters/sec.
-
 > let { x = 10
 >     ; y = lfSaw KR (1 / 6) 0 * 100
 >     ; d = hypot x y
diff --git a/Help/UGen/Math/max.help.lhs b/Help/UGen/Math/max.help.lhs
--- a/Help/UGen/Math/max.help.lhs
+++ b/Help/UGen/Math/max.help.lhs
@@ -1,9 +1,9 @@
-max a b
-
-Maximum.
+> Sound.SC3.UGen.Help.viewSC3Help "Operator.max"
+> :t max
 
 > import Sound.SC3
 
+q modulates and envelopes p
 > let { p = fSinOsc AR 500 0 * 0.25
 >     ; q = fSinOsc AR 0.5 0 }
 > in audition (out 0 (p `max` q))
diff --git a/Help/UGen/Math/mod.help.lhs b/Help/UGen/Math/mod.help.lhs
--- a/Help/UGen/Math/mod.help.lhs
+++ b/Help/UGen/Math/mod.help.lhs
@@ -1,7 +1,6 @@
-a `mod` b
-
-Modulo, written % in sclang.  outputs a modulo b.
+> Sound.SC3.UGen.Help.viewSC3Help "Operator.%"
+> :t modE
 
 > import Sound.SC3
 
-> audition (out 0 (fSinOsc AR 100 4 `mod` 1))
+> audition (out 0 (fSinOsc AR 100 4 `modE` 1))
diff --git a/Help/UGen/Math/mul.help.lhs b/Help/UGen/Math/mul.help.lhs
--- a/Help/UGen/Math/mul.help.lhs
+++ b/Help/UGen/Math/mul.help.lhs
@@ -1,20 +1,15 @@
-a * b
-
-Multiplication.
+> Sound.SC3.UGen.Help.viewSC3Help "Operator.*"
+> :t (*)
 
-> import Sound.SC3
+> import Sound.SC3.ID
 
 > audition (out 0 (sinOsc AR 440 0 * 0.5))
 
 Creates a beating effect (subaudio rate).
-
-> import Sound.SC3.ID
-
 > let n = pinkNoise 'a' AR
 > in audition (out 0 (fSinOsc kr 10 0 * n * 0.5))
 
 Ring modulation.
-
 > let { p = sinOsc AR (xLine KR 100 1001 10 DoNothing) 0
 >     ; q = syncSaw AR 100 200 }
 > in audition (out 0 (p * q * 0.25))
diff --git a/Help/UGen/Math/pow.help.lhs b/Help/UGen/Math/pow.help.lhs
--- a/Help/UGen/Math/pow.help.lhs
+++ b/Help/UGen/Math/pow.help.lhs
@@ -1,24 +1,17 @@
-a ** b
-
-Exponentiation.  When the signal is negative this function extends the
-usual definition of exponentiation and returns neg(neg(a) ** b). This
-allows exponentiation of negative signal values by noninteger
-exponents.
+> Sound.SC3.UGen.Help.viewSC3Help "Operator.**"
+> :t (**)
 
-> import Sound.SC3
+> import Sound.SC3.Monadic
 
 > let a = fSinOsc AR 100 0 * 0.1
 > in audition (out 0 (mce2 a (a ** 10)))
 
 http://create.ucsb.edu/pipermail/sc-users/2006-December/029998.html
-
-> import Sound.SC3.Monadic
-
 > do { n0 <- lfNoise2 KR 8
 >    ; n1 <- lfNoise2 KR 3
 >    ; let { s = blip AR (n0 * 200 + 300) (n1 * 10 + 20)
->          ; x = mouseX KR 1000 (sampleRate * 0.5) Exponential 0.1
->          ; y = mouseY KR 1 24 Exponential 0.1
+>          ; x = mouseX' KR 1000 (sampleRate * 0.5) Exponential 0.1
+>          ; y = mouseY' KR 1 24 Exponential 0.1
 >          ; d = latch s (impulse AR x 0)
 >          ; b = roundUp d (0.5 ** y) }
 >      in audition (out 0 (mce2 d b)) }
diff --git a/Help/UGen/Math/ring1.help.lhs b/Help/UGen/Math/ring1.help.lhs
--- a/Help/UGen/Math/ring1.help.lhs
+++ b/Help/UGen/Math/ring1.help.lhs
@@ -1,10 +1,5 @@
-ring1 a b
-
-Ring modulation plus first source.  Return the value of ((a*b) +
-a). This is more efficient than using separate unit generators for the
-multiply and add.
-
-See also Mul, Ring1, Ring2, Ring3, Ring4.
+> Sound.SC3.UGen.Help.viewSC3Help "Operator.ring1"
+> :t ring1
 
 > import Sound.SC3
 
@@ -13,7 +8,6 @@
 > in audition (out 0 (ring1 a b * 0.125))
 
 is equivalent to:
-
 > let { a = fSinOsc AR 800 0
 >     ; b = fSinOsc AR (xLine KR 200 500 5 DoNothing) 0 }
 > in audition (out 0 (((a * b) + a) * 0.125))
diff --git a/Help/UGen/Math/roundUp.help.lhs b/Help/UGen/Math/roundUp.help.lhs
--- a/Help/UGen/Math/roundUp.help.lhs
+++ b/Help/UGen/Math/roundUp.help.lhs
@@ -1,10 +1,9 @@
-roundUp a b
-
-Rounds a up to the nearest multiple of b.
+> Sound.SC3.UGen.Help.viewSC3Help "Operator.round"
+> :t roundUp
 
 > import Sound.SC3
 
-> let { x = mouseX KR 60 4000 Linear 0.1
+> let { x = mouseX' KR 60 4000 Linear 0.1
 >     ; f = roundUp x 100 }
 > in audition (out 0 (sinOsc ar f 0 * 0.1))
 
diff --git a/Help/UGen/Math/scaleNeg.help.lhs b/Help/UGen/Math/scaleNeg.help.lhs
--- a/Help/UGen/Math/scaleNeg.help.lhs
+++ b/Help/UGen/Math/scaleNeg.help.lhs
@@ -1,9 +1,14 @@
-scaleNeg a b
-
-Scale negative part of input wave.  a * b when a < 0, otherwise a.
+> Sound.SC3.UGen.Help.viewSC3Help "Operator.scaleneg"
+> :t scaleNeg
 
 > import Sound.SC3
 
-> let { o = fSinOsc AR 1000 0
->     ; l = line AR 1 (-1) 4 RemoveSynth }
+> let {o = fSinOsc AR 1000 0
+>     ;l = line AR 1 (-1) 4 RemoveSynth}
 > in audition (out 0 (scaleNeg o l))
+
+written out:
+> let {o = fSinOsc AR 1000 0
+>     ;l = line AR 1 (-1) 4 RemoveSynth
+>     ;c = o <* 0}
+> in audition (out 0 (c * (o * l) + (1 - c) * o))
diff --git a/Help/UGen/Math/softClip.help.lhs b/Help/UGen/Math/softClip.help.lhs
--- a/Help/UGen/Math/softClip.help.lhs
+++ b/Help/UGen/Math/softClip.help.lhs
@@ -1,10 +1,8 @@
-softClip a
-
-Nonlinear distortion.  Distortion with a perfectly linear region
-from -0.5 to +0.5.
+> Sound.SC3.UGen.Help.viewSC3Help "Operator.softclip"
+> :t softClip
 
 > import Sound.SC3
 
-> let { e = xLine KR 0.1 10 10 DoNothing
->     ; o = fSinOsc AR 500 0.0 }
+> let {e = xLine KR 0.1 10 10 RemoveSynth
+>     ;o = fSinOsc AR 500 0.0}
 > in audition (out 0 (softClip (o * e) * 0.25))
diff --git a/Help/UGen/Math/sumSqr.help.lhs b/Help/UGen/Math/sumSqr.help.lhs
--- a/Help/UGen/Math/sumSqr.help.lhs
+++ b/Help/UGen/Math/sumSqr.help.lhs
@@ -1,7 +1,5 @@
-sumSqr a b
-
-Return the value of (a*a) + (b*b). This is more efficient than
-using separate unit generators for each operation.
+> Sound.SC3.UGen.Help.viewSC3Help "Operator.sumsqr"
+> :t sumSqr
 
 > import Sound.SC3
 
@@ -10,7 +8,6 @@
 > in audition (out 0 (sumSqr a b * 0.125))
 
 Written out:
-
 > let { a = fSinOsc AR 800 0
 >     ; b = fSinOsc AR (xLine KR 200 500 5 DoNothing) 0 }
 > in audition (out 0 ((a * a + b * b) * 0.125))
diff --git a/Help/UGen/Math/thresh.help.lhs b/Help/UGen/Math/thresh.help.lhs
--- a/Help/UGen/Math/thresh.help.lhs
+++ b/Help/UGen/Math/thresh.help.lhs
@@ -1,8 +1,8 @@
-thresh a b
-
-Signal thresholding.  0 when a < b, otherwise a.
+> Sound.SC3.UGen.Help.viewSC3Help "Operator.thresh"
+> :t thresh
 
 > import Sound.SC3.ID
 
-> let n = lfNoise0 'a' AR 50
-> in audition (out 0 (thresh (n * 0.5) 0.45))
+low-rent gate
+> let n = lfNoise0 'a' AR 50 * 0.5
+> in audition (out 0 (thresh n 0.45))
diff --git a/Help/UGen/Noise/brownNoise.help.lhs b/Help/UGen/Noise/brownNoise.help.lhs
--- a/Help/UGen/Noise/brownNoise.help.lhs
+++ b/Help/UGen/Noise/brownNoise.help.lhs
@@ -1,14 +1,12 @@
-brownNoise rate
-
-Generates noise whose spectrum falls off in power by 6 dB per
-octave.
+> Sound.SC3.UGen.Help.viewSC3Help "BrownNoise"
+> Sound.SC3.UGen.DB.ugenSummary "BrownNoise"
 
 > import Sound.SC3.ID
 
 > let n = brownNoise 'a' AR
 > in audition (out 0 (n * 0.1))
 
-> let { n = brownNoise 'a' KR
->     ; o = sinOsc AR (linExp n (-1) 1 64 9600) 0 * 0.1 }
+> let {n = brownNoise 'a' KR
+>     ;o = sinOsc AR (linExp n (-1) 1 64 9600) 0 * 0.1}
 > in audition (out 0 o)
 
diff --git a/Help/UGen/Noise/clipNoise.help.lhs b/Help/UGen/Noise/clipNoise.help.lhs
--- a/Help/UGen/Noise/clipNoise.help.lhs
+++ b/Help/UGen/Noise/clipNoise.help.lhs
@@ -1,10 +1,8 @@
-clipNoise rate
-
-Generates noise whose values are either -1 or 1.  This produces the
-maximum energy for the least peak to peak amplitude.
-
-> import Sound.SC3.Monadic
+> Sound.SC3.UGen.Help.viewSC3Help "ClipNoise"
+> Sound.SC3.UGen.DB.ugenSummary "ClipNoise"
 
-> audition . (out 0) . (* 0.1) =<< clipNoise AR
+> import Sound.SC3
+> import qualified Sound.SC3.Monadic as M
 
-> audition . (out 0) . (* 0.1) =<< whiteNoise AR
+> audition . (out 0) . (* 0.1) =<< M.clipNoise AR
+> audition . (out 0) . (* 0.1) =<< M.whiteNoise AR
diff --git a/Help/UGen/Noise/coinGate.help.lhs b/Help/UGen/Noise/coinGate.help.lhs
--- a/Help/UGen/Noise/coinGate.help.lhs
+++ b/Help/UGen/Noise/coinGate.help.lhs
@@ -1,10 +1,8 @@
-coinGate prob in
-
-When it receives a trigger, it tosses a coin, and either passes the
-trigger or doesn't.
+> Sound.SC3.UGen.Help.viewSC3Help "CoinGate"
+> Sound.SC3.UGen.DB.ugenSummary "CoinGate"
 
-> import Sound.SC3.Monadic
+> import Sound.SC3.ID
 
-> do { g <- coinGate 0.2 (impulse KR 10 0)
->    ; f <- tRand 300.0 400.0 g
->    ; audition (out 0 (sinOsc AR f 0 * 0.1)) }
+> let {g = coinGate 'a' 0.2 (impulse KR 10 0)
+>     ;f = tRand 'b' 300.0 400.0 g}
+> in audition (out 0 (sinOsc AR f 0 * 0.1))
diff --git a/Help/UGen/Noise/dust.help.lhs b/Help/UGen/Noise/dust.help.lhs
--- a/Help/UGen/Noise/dust.help.lhs
+++ b/Help/UGen/Noise/dust.help.lhs
@@ -1,11 +1,17 @@
-dust rate density
+> Sound.SC3.UGen.Help.viewSC3Help "Dust"
+> Sound.SC3.UGen.DB.ugenSummary "Dust"
 
-Generates random impulses from 0 to +1 at a rate determined by the
-density argument.
+> import Sound.SC3.ID
 
-> import Sound.SC3.Monadic
+> audition (out 0 (dust 'a' AR 200 * 0.25))
 
-> audition . (out 0) . (* 0.25) =<< dust AR 200
+> let d = xLine KR 20000 2 10 RemoveSynth
+> in audition (out 0 (dust 'a' AR d * 0.15))
 
+Illustrate monadic constructor
+> import qualified Sound.SC3.Monadic as M
+
+> audition . (out 0) . (* 0.25) =<< M.dust AR 200
+
 > let d = xLine KR 20000 2 10 RemoveSynth
-> in audition . (out 0) . (* 0.15) =<< dust AR d
+> in audition . (out 0) . (* 0.15) =<< M.dust AR d
diff --git a/Help/UGen/Noise/dust2.help.lhs b/Help/UGen/Noise/dust2.help.lhs
--- a/Help/UGen/Noise/dust2.help.lhs
+++ b/Help/UGen/Noise/dust2.help.lhs
@@ -1,12 +1,10 @@
-dust2 rate density
-
-Generates random impulses from -1 to +1.  The `density' is in
-impulses per second.
+> Sound.SC3.UGen.Help.viewSC3Help "Dust2"
+> Sound.SC3.UGen.DB.ugenSummary "Dust2"
 
-> import Sound.SC3.Monadic
+> import Sound.SC3.ID
 
-> do { n <- dust2 AR 200
->    ; audition (out 0 (n * 0.5)) }
+> let n = dust2 'a' AR 200
+> in audition (out 0 (n * 0.5))
 
 > let d = xLine KR 20000 2 10 RemoveSynth
-> in audition . (out 0 ) . (* 0.15) =<< dust2 AR d
+> in audition (out 0 (dust2 'b' AR d * 0.15))
diff --git a/Help/UGen/Noise/expRand.help.lhs b/Help/UGen/Noise/expRand.help.lhs
--- a/Help/UGen/Noise/expRand.help.lhs
+++ b/Help/UGen/Noise/expRand.help.lhs
@@ -1,10 +1,8 @@
-expRand lo hi
-
-Generates a single random float value in an exponential
-distributions from `lo' to `hi'.
+> Sound.SC3.UGen.Help.viewSC3Help "ExpRand"
+> Sound.SC3.UGen.DB.ugenSummary "ExpRand"
 
 > import Sound.SC3.ID
 
-> let { a = line KR 0.5 0 0.01 RemoveSynth
->     ; f = expRand 'a' 100.0 8000.0 }
+> let {a = line KR 0.5 0 0.01 RemoveSynth
+>     ;f = expRand 'a' 100.0 8000.0}
 > in audition (out 0 (fSinOsc AR f 0 * a))
diff --git a/Help/UGen/Noise/grayNoise.help.lhs b/Help/UGen/Noise/grayNoise.help.lhs
--- a/Help/UGen/Noise/grayNoise.help.lhs
+++ b/Help/UGen/Noise/grayNoise.help.lhs
@@ -1,9 +1,7 @@
-grayNoise rate
-
-Generates noise which results from flipping random bits in a word.
-This type of noise has a high RMS level relative to its peak to
-peak level.  The spectrum is emphasized towards lower frequencies.
+> Sound.SC3.UGen.Help.viewSC3Help "GrayNoise"
+> Sound.SC3.UGen.DB.ugenSummary "GrayNoise"
 
-> import Sound.SC3.Monadic
+> import Sound.SC3
+> import qualified Sound.SC3.Monadic as M
 
-> audition . (out 0) . (* 0.1) =<< grayNoise AR
+> audition . (out 0) . (* 0.1) =<< M.grayNoise AR
diff --git a/Help/UGen/Noise/iChoose.help.lhs b/Help/UGen/Noise/iChoose.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Noise/iChoose.help.lhs
@@ -0,0 +1,9 @@
+> :t iChoose
+
+# composite
+iChoose is a composite of iRand and select.
+
+> import Sound.SC3.ID
+
+> let f = udup 2 (iChoose 'a' (mce [440,460 .. 880]))
+> in audition (out 0 (sinOsc AR f  0 * 0.1))
diff --git a/Help/UGen/Noise/iRand.help.lhs b/Help/UGen/Noise/iRand.help.lhs
--- a/Help/UGen/Noise/iRand.help.lhs
+++ b/Help/UGen/Noise/iRand.help.lhs
@@ -1,10 +1,8 @@
-iRand lo hi
-
-Generates a single random integer value in uniform distribution
-from `lo' to `hi'.
+> Sound.SC3.UGen.Help.viewSC3Help "IRand"
+> Sound.SC3.UGen.DB.ugenSummary "IRand"
 
 > import Sound.SC3.ID
 
-> let { f = iRand 'a' 200 1200
->     ; e = line KR 0.2 0 0.1 RemoveSynth }
+> let {f = iRand 'a' 200 1200
+>     ;e = line KR 0.2 0 0.1 RemoveSynth}
 > in audition (out 0 (fSinOsc AR f 0 * e))
diff --git a/Help/UGen/Noise/lfClipNoise.help.lhs b/Help/UGen/Noise/lfClipNoise.help.lhs
--- a/Help/UGen/Noise/lfClipNoise.help.lhs
+++ b/Help/UGen/Noise/lfClipNoise.help.lhs
@@ -1,20 +1,15 @@
-lfClipNoise rate freq
-
-Randomly generates the values -1 or +1 at a rate given by the
-nearest integer division of the sample rate by the freq argument.
-It is probably pretty hard on your speakers.  The freq argument is
-the approximate rate at which to generate random values.
+> Sound.SC3.UGen.Help.viewSC3Help "LFClipNoise"
+> Sound.SC3.UGen.DB.ugenSummary "LFClipNoise"
 
-> import Sound.SC3.Monadic
+> import Sound.SC3.ID
+> import qualified Sound.SC3.Monadic as M
 
-> audition . (out 0) . (* 0.05) =<< lfClipNoise AR 1000
+> audition . (out 0) . (* 0.05) =<< M.lfClipNoise AR 1000
 
 Modulate frequency
-
 > let f = xLine KR 1000 10000 10 RemoveSynth
-> in audition . (out 0) . (* 0.05) =<< lfClipNoise AR f
+> in audition . (out 0) . (* 0.05) =<< M.lfClipNoise AR f
 
 Use as frequency control
-
-> do { n <- lfClipNoise KR 4 
->    ; audition (out 0 (sinOsc AR (n * 200 + 600) 0 * 0.1)) }
+> let n = lfClipNoise 'a' KR 4
+> in audition (out 0 (sinOsc AR (n * 200 + 600) 0 * 0.1))
diff --git a/Help/UGen/Noise/lfNoise0.help.lhs b/Help/UGen/Noise/lfNoise0.help.lhs
--- a/Help/UGen/Noise/lfNoise0.help.lhs
+++ b/Help/UGen/Noise/lfNoise0.help.lhs
@@ -1,19 +1,16 @@
-lfNoise0 rate freq
-
-Step noise.  Generates random values at a rate given by the nearest
-integer division of the sample rate by the freq argument.
+> Sound.SC3.UGen.Help.viewSC3Help "LFNoise0"
+> Sound.SC3.UGen.DB.ugenSummary "LFNoise0"
 
-> import Sound.SC3.Monadic
+> import Sound.SC3.ID
+> import qualified Sound.SC3.Monadic as M
 
-> audition . (out 0) . (* 0.05) =<< lfNoise0 AR 1000
+> audition . (out 0) . (* 0.05) =<< M.lfNoise0 AR 1000
 
 Modulate frequency.
-
-> let f = xLine KR 1000 10000 10 RemoveSynth
-> in do { n <- lfNoise0 AR f
->       ; audition (out 0 (n * 0.05)) }
+> let {f = xLine KR 1000 10000 10 RemoveSynth
+>     ;n = lfNoise0 'a' AR f}
+> in audition (out 0 (n * 0.05))
 
 Use as frequency control.
-
-> do { f <- lfNoise0 KR 4
->    ; audition (out 0 (sinOsc AR (f * 400 + 450) 0 * 0.1)) }
+> let f = lfNoise0 'a' KR 4
+> in audition (out 0 (sinOsc AR (f * 400 + 450) 0 * 0.1))
diff --git a/Help/UGen/Noise/lfNoise1.help.lhs b/Help/UGen/Noise/lfNoise1.help.lhs
--- a/Help/UGen/Noise/lfNoise1.help.lhs
+++ b/Help/UGen/Noise/lfNoise1.help.lhs
@@ -1,23 +1,16 @@
-lfNoise1 rate freq
-
-Ramp noise.  Generates linearly interpolated random values at a
-rate given by the nearest integer division of the sample rate by
-the freq argument.
-
-freq - approximate rate at which to generate random values.
+> Sound.SC3.UGen.Help.viewSC3Help "LFNoise1"
+> Sound.SC3.UGen.DB.ugenSummary "LFNoise1"
 
-> import Sound.SC3.Monadic
+> import Sound.SC3.ID
 
-> audition . (out 0) . (* 0.05) =<< lfNoise1 AR 1000
+> audition (out 0 (lfNoise1 'a' AR 1000 * 0.05))
 
 Modulate frequency.
-
-> let f = xLine KR 1000 10000 10 RemoveSynth
-> in do { n <- lfNoise1 AR f
->       ; audition (out 0 (n * 0.05)) }
+> let {f = xLine KR 1000 10000 10 RemoveSynth
+>     ;n = lfNoise1 'a' AR f}
+> in audition (out 0 (n * 0.05))
 
 Use as frequency control.
-
-> do { n <- lfNoise1 KR 4 
->    ; let f = n * 400 + 450
->      in audition (out 0 (sinOsc AR f 0 * 0.1)) }
+> let {n = lfNoise1 'a' KR 4
+>     ;f = n * 400 + 450}
+> in audition (out 0 (sinOsc AR f 0 * 0.1))
diff --git a/Help/UGen/Noise/lfNoise2.help.lhs b/Help/UGen/Noise/lfNoise2.help.lhs
--- a/Help/UGen/Noise/lfNoise2.help.lhs
+++ b/Help/UGen/Noise/lfNoise2.help.lhs
@@ -1,20 +1,16 @@
-lfNoise2 rate freq
-
-Quadratic noise.  Generates quadratically interpolated random
-values at a rate given by the nearest integer division of the
-sample rate by the freq argument.
+> Sound.SC3.UGen.Help.viewSC3Help "LFNoise2"
+> Sound.SC3.UGen.DB.ugenSummary "LFNoise2"
 
-> import Sound.SC3.Monadic
+> import Sound.SC3.ID
+> import qualified Sound.SC3.Monadic as M
 
-> audition . (out 0) . (* 0.05) =<< lfNoise2 AR 1000
+> audition . (out 0) . (* 0.05) =<< M.lfNoise2 AR 1000
 
 Modulate frequency.
-
-> let f = xLine KR 1000 10000 10 RemoveSynth
-> in do { n <- lfNoise2 AR f
->       ; audition (out 0 (n * 0.05)) }
+> let {f = xLine KR 1000 10000 10 RemoveSynth
+>     ;n = lfNoise2 'a' AR f}
+> in audition (out 0 (n * 0.05))
 
 Use as frequency control.
-
-> do { f <- lfNoise2 KR 4 
->    ; audition (out 0 (sinOsc AR (f * 400 + 450) 0 * 0.1)) }
+> let f = lfNoise2 'a' KR 4
+> in audition (out 0 (sinOsc AR (f * 400 + 450) 0 * 0.1))
diff --git a/Help/UGen/Noise/lfdClipNoise.help.lhs b/Help/UGen/Noise/lfdClipNoise.help.lhs
--- a/Help/UGen/Noise/lfdClipNoise.help.lhs
+++ b/Help/UGen/Noise/lfdClipNoise.help.lhs
@@ -1,34 +1,21 @@
-lfdClipNoise rate freq
-
-Like LFClipNoise, it generates the values -1 or +1 at a rate given
-by the freq argument, with two differences: no time quantization,
-and fast recovery from low freq values.
-
-LFClipNoise, as well as LFNoise0,1,2 quantize to the nearest
-integer division of the samplerate, and they poll the freq argument
-only when scheduled, and thus seem to hang when freqs get very
-low.
-
-If you don't need very high or very low freqs, or use fixed freqs,
-LFClipNoise is more efficient.
-
-Try wiggling mouse quickly; lfClipNoise frequently seems stuck,
-lfdClipNoise changes smoothly.
+> Sound.SC3.UGen.Help.viewSC3Help "LFDClipNoise"
+> Sound.SC3.UGen.DB.ugenSummary "LFDClipNoise"
 
-> import Sound.SC3.Monadic
+> import Sound.SC3.ID
+> import qualified Sound.SC3.Monadic as M
 
-> let x = mouseX KR 0.1 1000 Exponential 0.2
-> in do { n <- lfdClipNoise AR x
->       ; audition (out 0 (sinOsc AR (n * 200 + 500) 0 * 0.05)) }
+for fast x lfClipNoise frequently seems stuck, lfdClipNoise changes smoothly
+> let {x = mouseX' KR 0.1 1000 Exponential 0.2
+>     ;n = lfdClipNoise 'a' AR x}
+> in audition (out 0 (sinOsc AR (n * 200 + 500) 0 * 0.05))
 
-> let x = mouseX KR 0.1 1000 Exponential 0.2
-> in do { n <- lfClipNoise AR x
->       ; audition (out 0 (sinOsc AR (n * 200 + 500) 0 * 0.05)) }
+> let {x = mouseX' KR 0.1 1000 Exponential 0.2
+>     ;n = lfClipNoise 'a' AR x}
+> in audition (out 0 (sinOsc AR (n * 200 + 500) 0 * 0.05))
 
 lfClipNoise quantizes time steps at high freqs, lfdClipNoise does not:
-
 > let f = xLine KR 1000 20000 10 RemoveSynth
-> in audition . (out 0) . (* 0.05) =<< lfdClipNoise AR f
+> in audition . (out 0) . (* 0.05) =<< M.lfdClipNoise AR f
 
 > let f = xLine KR 1000 20000 10 RemoveSynth
-> in audition . (out 0) . (* 0.05) =<< lfClipNoise AR f
+> in audition . (out 0) . (* 0.05) =<< M.lfClipNoise AR f
diff --git a/Help/UGen/Noise/lfdNoise0.help.lhs b/Help/UGen/Noise/lfdNoise0.help.lhs
--- a/Help/UGen/Noise/lfdNoise0.help.lhs
+++ b/Help/UGen/Noise/lfdNoise0.help.lhs
@@ -1,39 +1,26 @@
-lfdNoise0 rate freq
-
-Dynamic step noise. Like lfNoise0, it generates random values at a
-rate given by the freq argument, with two differences: no time
-quantization, and fast recovery from low freq values.
-
-lfNoise0,1,2 quantize to the nearest integer division of the
-samplerate, and they poll the freq argument only when scheduled, and
-thus seem to hang when freqs get very low.
-
-If you don't need very high or very low freqs, or use fixed freqs,
-LFNoise0 is more efficient.
-
-Try wiggling mouse quickly; LFNoise frequently seems stuck,
-LFDNoise changes smoothly.
+> Sound.SC3.UGen.Help.viewSC3Help "LFDNoise0"
+> Sound.SC3.UGen.DB.ugenSummary "LFDNoise0"
 
-> import Sound.SC3.Monadic
+> import Sound.SC3
+> import qualified Sound.SC3.Monadic as M
 
-> let x = mouseX KR 0.1 1000 Exponential 0.2
-> in audition . (out 0) . (* 0.1) =<< lfdNoise0 AR x
+for fast x LFNoise frequently seems stuck, LFDNoise changes smoothly
+> let x = mouseX' KR 0.1 1000 Exponential 0.2
+> in audition . (out 0) . (* 0.1) =<< M.lfdNoise0 AR x
 
-> let x = mouseX KR 0.1 1000 Exponential 0.2
-> in audition . (out 0) . (* 0.1) =<< lfNoise0 AR x
+> let x = mouseX' KR 0.1 1000 Exponential 0.2
+> in audition . (out 0) . (* 0.1) =<< M.lfNoise0 AR x
 
 silent for 2 secs before going up in freq
-
 > let f = xLine KR 0.5 10000 3 RemoveSynth
-> in audition . (out 0) . (* 0.1) =<< lfdNoise0 AR f
+> in audition . (out 0) . (* 0.1) =<< M.lfdNoise0 AR f
 
 > let f = xLine KR 0.5 10000 3 RemoveSynth
-> in audition . (out 0) . (* 0.1) =<< lfNoise0 AR f
+> in audition . (out 0) . (* 0.1) =<< M.lfNoise0 AR f
 
 LFNoise quantizes time steps at high freqs, LFDNoise does not:
-
 > let f = xLine KR 1000 20000 10 RemoveSynth
-> in audition . (out 0) . (* 0.1) =<< lfdNoise0 AR f
+> in audition . (out 0) . (* 0.1) =<< M.lfdNoise0 AR f
 
 > let f = xLine KR 1000 20000 10 RemoveSynth
-> in audition . (out 0) . (* 0.1) =<< lfNoise0 AR f
+> in audition . (out 0) . (* 0.1) =<< M.lfNoise0 AR f
diff --git a/Help/UGen/Noise/lfdNoise1.help.lhs b/Help/UGen/Noise/lfdNoise1.help.lhs
--- a/Help/UGen/Noise/lfdNoise1.help.lhs
+++ b/Help/UGen/Noise/lfdNoise1.help.lhs
@@ -1,5 +1,4 @@
-lfdNoise1 rate freq
-
-Dynamic ramp noise. 
+> Sound.SC3.UGen.Help.viewSC3Help "LFDNoise1"
+> Sound.SC3.UGen.DB.ugenSummary "LFDNoise1"
 
-See lfdNoise0 and lfNoise1.
+See lfdNoise0
diff --git a/Help/UGen/Noise/lfdNoise3.help.lhs b/Help/UGen/Noise/lfdNoise3.help.lhs
--- a/Help/UGen/Noise/lfdNoise3.help.lhs
+++ b/Help/UGen/Noise/lfdNoise3.help.lhs
@@ -1,5 +1,4 @@
-lfdnoise3 rate freq
-
-Dynamic cubic noise. 
+> Sound.SC3.UGen.Help.viewSC3Help "LFDNoise3"
+> Sound.SC3.UGen.DB.ugenSummary "LFDNoise3"
 
-See lfNoise3 and lfdNoise0.
+See lfdNoise0
diff --git a/Help/UGen/Noise/linRand.help.lhs b/Help/UGen/Noise/linRand.help.lhs
--- a/Help/UGen/Noise/linRand.help.lhs
+++ b/Help/UGen/Noise/linRand.help.lhs
@@ -1,11 +1,8 @@
-linRand lo hi minmax
-
-Generates a single random float value in linear distribution from
-lo to hi, skewed towards lo if minmax < 0, otherwise skewed towards
-hi.
+> Sound.SC3.UGen.Help.viewSC3Help "LinRand"
+> Sound.SC3.UGen.DB.ugenSummary "LinRand"
 
-> import Sound.SC3.Monadic
+> import Sound.SC3.ID
 
-> do { f <- linRand 200.0 10000.0 (mce [-1, 1])
->    ; let e = line KR 0.4 0 0.01 RemoveSynth
->      in audition (out 0 (fSinOsc AR f 0 * e)) }
+> let {f = linRand 'a' 200.0 10000.0 (mce [-1, 1])
+>     ;e = line KR 0.4 0 0.01 RemoveSynth}
+> in audition (out 0 (fSinOsc AR f 0 * e))
diff --git a/Help/UGen/Noise/nRand.help.lhs b/Help/UGen/Noise/nRand.help.lhs
--- a/Help/UGen/Noise/nRand.help.lhs
+++ b/Help/UGen/Noise/nRand.help.lhs
@@ -1,15 +1,8 @@
-nRand lo hi n
-
-Generates a single random float value in a sum of `n' uniform
-distributions from `lo' to `hi'.
-
-n = 1 : uniform distribution - same as Rand
-n = 2 : triangular distribution
-n = 3 : smooth hump
-as n increases, distribution converges towards gaussian
+> Sound.SC3.UGen.Help.viewSC3Help "NRand"
+> Sound.SC3.UGen.DB.ugenSummary "NRand"
 
-> import Sound.SC3.Monadic
+> import Sound.SC3.ID
 
-> do { n <- nRand 1200.0 4000.0 (mce [2, 5])
->    ; let e = line KR 0.2 0 0.01 RemoveSynth
->      in audition (out 0 (fSinOsc AR n 0 * e)) }
+> let {n = nRand 'a' 1200.0 4000.0 (mce [2,5])
+>     ;e = line KR 0.2 0 0.1 RemoveSynth}
+> in audition (out 0 (fSinOsc AR n 0 * e))
diff --git a/Help/UGen/Noise/pinkNoise.help.lhs b/Help/UGen/Noise/pinkNoise.help.lhs
--- a/Help/UGen/Noise/pinkNoise.help.lhs
+++ b/Help/UGen/Noise/pinkNoise.help.lhs
@@ -1,13 +1,8 @@
-pinkNoise rate
-
-Generates noise whose spectrum falls off in power by 3 dB per
-octave.  This gives equal power over the span of each octave.  This
-version gives 8 octaves of pink noise.
+> Sound.SC3.UGen.Help.viewSC3Help "PinkNoise"
+> Sound.SC3.UGen.DB.ugenSummary "PinkNoise"
 
 > import Sound.SC3.Monadic
 
 > audition . (out 0) . (* 0.05) =<< pinkNoise AR
-
 > audition . (out 0) . (* 0.05) =<< whiteNoise AR
-
 > audition . (out 0) . (* 0.05) =<< brownNoise AR
diff --git a/Help/UGen/Noise/rand.help.lhs b/Help/UGen/Noise/rand.help.lhs
--- a/Help/UGen/Noise/rand.help.lhs
+++ b/Help/UGen/Noise/rand.help.lhs
@@ -1,13 +1,10 @@
-rand lo hi
-
-Generates a single random value in uniform distribution from lo to
-hi.  It generates this when the SynthDef first starts playing, and
-remains fixed for the duration of the synth's existence.
+> Sound.SC3.UGen.Help.viewSC3Help "Rand"
+> Sound.SC3.UGen.DB.ugenSummary "Rand"
 
-> import Sound.SC3.Monadic
+> import Sound.SC3.ID
 
-> do { f <- rand 200 1200
->    ; l <- rand (-1) 1
->    ; let { e = line KR 0.2 0 0.1 RemoveSynth
->          ; o = fSinOsc AR f 0 }
->      in audition (out 0 (pan2 (o * e) l 1)) }
+> let {f = rand 'a' 200 1200
+>     ;l = rand 'b' (-1) 1
+>     ;e = line KR 0.2 0 0.1 RemoveSynth
+>     ;o = fSinOsc AR f 0}
+> in audition (out 0 (pan2 (o * e) l 1))
diff --git a/Help/UGen/Noise/randID.help.lhs b/Help/UGen/Noise/randID.help.lhs
--- a/Help/UGen/Noise/randID.help.lhs
+++ b/Help/UGen/Noise/randID.help.lhs
@@ -1,8 +1,2 @@
-randID id
-
-Choose which random number generator to use for this synth.  All
-synths that use the same generator reproduce the same sequence of
-numbers when the same seed is set again.
-
-See also: RandSeed.
-
+> Sound.SC3.UGen.Help.viewSC3Help "RandID"
+> Sound.SC3.UGen.DB.ugenSummary "RandID"
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
@@ -1,8 +1,22 @@
-randSeed trig seed
+> Sound.SC3.UGen.Help.viewSC3Help "RandSeed"
+> Sound.SC3.UGen.DB.ugenSummary "RandSeed"
 
-When the trigger signal changes from nonpositive to positve, the
-synth's random generator seed is reset to the given value. All
-other synths that use the same random number generator reproduce
-the same sequence of numbers again.
+> import Sound.SC3.ID
 
-See also: RandID.
+start a noise patch
+> let {n = udup 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)
+
+reset the seed at a variable rate
+> let {s = control KR "seed" 1956
+>     ;r = randSeed KR (impulse KR (mouseX' KR 0.1 100 Linear 0.2) 0) s}
+> in audition r
+
+always the same (for a given seed)...
+> let {sd = 1957
+>     ;n = tIRand 'a' 4 12 (dust 'a' KR 1)
+>     ;f = n * 150 + (mce [0,1])
+>     ;r = randSeed IR 1 sd}
+> in audition (out 0 (mrg2 (sinOsc AR f 0 * 0.1) r))
diff --git a/Help/UGen/Noise/tIRand.help.lhs b/Help/UGen/Noise/tIRand.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Noise/tIRand.help.lhs
@@ -0,0 +1,13 @@
+> Sound.SC3.UGen.Help.viewSC3Help "TIRand"
+> Sound.SC3.UGen.DB.ugenSummary "TIRand"
+
+> import Sound.SC3
+> import qualified Sound.SC3.Monadic as M
+
+> do {l <- M.tIRand (-1) 1 =<< M.dust KR 10
+>    ;n <- M.pinkNoise AR
+>    ;audition (out 0 (pan2 (n * 0.1) l 1))}
+
+> do {n <- M.tIRand 4 12 =<< M.dust KR 10
+>    ;let f = n * 150 + (mce [0,1])
+>     in audition (out 0 (sinOsc AR f 0 * 0.1))}
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
@@ -1,10 +1,8 @@
-tRand lo hi trig
-
-Generates a random float value in uniform distribution from lo each
-time the trig signal changes from nonpositive to positive values
+> Sound.SC3.UGen.Help.viewSC3Help "TRand"
+> Sound.SC3.UGen.DB.ugenSummary "TRand"
 
-> import Sound.SC3.Monadic
+> import Sound.SC3.ID
 
-> do { t <- dust KR (mce [5, 12])
->    ; f <- tRand (mce [200, 1600]) (mce [500, 3000]) t
->    ; audition (out 0 (sinOsc AR f 0 * 0.2)) }
+> let {t = dust 'a' KR (mce2 5 12)
+>     ;f = tRand 'b' (mce2 200 1600) (mce2 500 3000) t}
+> in audition (out 0 (sinOsc AR f 0 * 0.2))
diff --git a/Help/UGen/Noise/tiRand.help.lhs b/Help/UGen/Noise/tiRand.help.lhs
deleted file mode 100644
--- a/Help/UGen/Noise/tiRand.help.lhs
+++ /dev/null
@@ -1,15 +0,0 @@
-tiRand lo hi trig
-
-Generates a random integer value in uniform distribution from lo to
-hi each time the trig signal changes from nonpositive to positive
-values
-
-> import Sound.SC3.Monadic
-
-> do { l <- tiRand (-1) 1 =<< dust KR 10
->    ; n <- pinkNoise AR
->    ; audition (out 0 (pan2 (n * 0.1) l 1)) }
-
-> do { n <- tiRand 4 12 =<< dust KR 10
->    ; let f = n * 150 + (mce [0,1])
->      in audition (out 0 (sinOsc AR f 0 * 0.1)) }
diff --git a/Help/UGen/Noise/whiteNoise.help.lhs b/Help/UGen/Noise/whiteNoise.help.lhs
--- a/Help/UGen/Noise/whiteNoise.help.lhs
+++ b/Help/UGen/Noise/whiteNoise.help.lhs
@@ -1,29 +1,35 @@
-whiteNoise rate
-
-Generates noise whose spectrum has equal power at all frequencies.
+> Sound.SC3.UGen.Help.viewSC3Help "WhiteNoise"
+> Sound.SC3.UGen.DB.ugenSummary "WhiteNoise"
 
-> import Sound.SC3.Monadic
+> import Sound.SC3.ID
 
-> audition . (out 0) . (* 0.05) =<< whiteNoise AR
+> audition (out 0 (whiteNoise 'a' AR * 0.05))
 
 Random filtered noise bursts.
+> let {n = whiteNoise 'a' AR
+>     ;t = dust 'a' AR (mce [3, 7])
+>     ;f = tExpRand 'a' 20 1800 t
+>     ;bw = tExpRand 'a' 0.001 1 t
+>     ;e = decay2 t 0.01 0.2
+>     ;r = resonz (n * e) f bw}
+> in audition (out 0 r)
 
-> do { n <- whiteNoise AR
->    ; t <- dust AR (mce [3, 7])
->    ; f <- tExpRand 20 1800 t
->    ; bw <- tExpRand 0.001 1 t
->    ; let { e = decay2 t 0.01 0.2
->          ; r = resonz (n * e) f bw }
->      in audition (out 0 r) }
+> import qualified Sound.SC3.Monadic as M
 
-The same graph, without using do notation.
+Monadic form of above graph.
+> do {n <- M.whiteNoise AR
+>    ;t <- M.dust AR (mce [3, 7])
+>    ;f <- M.tExpRand 20 1800 t
+>    ;bw <- M.tExpRand 0.001 1 t
+>    ;let {e = decay2 t 0.01 0.2
+>         ;r = resonz (n * e) f bw}
+>      in audition (out 0 r)}
 
-> whiteNoise AR >>= \n -> 
-> dust AR (mce [3, 7]) >>= \t -> 
-> tExpRand 20 1800 t >>= \f ->
-> tExpRand 0.001 1 t >>= \bw -> 
-> let { e = decay2 t 0.01 0.2
->     ; r = resonz (n * e) f bw }
+The same graph again, without using do notation.
+> M.whiteNoise AR >>= \n ->
+> M.dust AR (mce [3, 7]) >>= \t ->
+> M.tExpRand 20 1800 t >>= \f ->
+> M.tExpRand 0.001 1 t >>= \bw ->
+> let {e = decay2 t 0.01 0.2
+>     ;r = resonz (n * e) f bw}
 > in audition (out 0 r)
-
- 
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
@@ -1,31 +1,14 @@
-blip AR freq numHarm
-
-Band Limited ImPulse generator. All harmonics have equal amplitude.
-
-This is the equivalent of 'buzz' in MusicN languages. WARNING: This
-waveform in its raw form could be damaging to your ears at high
-amplitudes or for long periods.
-
-Implementation notes: It is improved from other implementations in
-that it will crossfade in a control period when the number of
-harmonics changes, so that there are no audible pops. It also
-eliminates the divide in the formula by using a 1/sin table (with
-special precautions taken for 1/0).  The lookup tables are linearly
-interpolated for better quality.
-
-The number of harmonics may be lowered internally if it would cause
-aliasing.
+> Sound.SC3.UGen.Help.viewSC3Help "Blip"
+> Sound.SC3.UGen.DB.ugenSummary "Blip"
 
 > import Sound.SC3
 
 > audition (out 0 (blip AR 440 200 * 0.1))
 
 Modulate frequency
-
 > let f = xLine KR 20000 200 6 RemoveSynth
 > in audition (out 0 (blip AR f 100 * 0.1))
 
 Modulate number of harmonics.
-
 > let nh = line KR 1 100 20 RemoveSynth
 > in audition (out 0 (blip AR 200 nh * 0.2))
diff --git a/Help/UGen/Oscillator/cOsc.help.lhs b/Help/UGen/Oscillator/cOsc.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Oscillator/cOsc.help.lhs
@@ -0,0 +1,18 @@
+> Sound.SC3.UGen.Help.viewSC3Help "COsc"
+> Sound.SC3.UGen.DB.ugenSummary "COsc"
+
+> import Sound.SC3
+
+Allocate and fill buffer.
+> let d = [1+2+4,1,1/2,1/3,1/4,1/5,1/6,1/7,1/8,1/9,1/10]
+> in withSC3 (\fd -> do {_ <- async fd (b_alloc 10 512 1)
+>                       ;async fd (b_gen 10 "sine1" d)})
+
+Fixed beat frequency
+> audition (out 0 (cOsc AR 10 200 0.7 * 0.25))
+
+Modulate beat frequency with mouseX
+> audition (out 0 (cOsc AR 10 200 (mouseX' KR 0 4 Linear 0.2) * 0.25))
+
+Compare with plain osc
+> audition (out 0 (osc AR 10 200 0.0 * 0.25))
diff --git a/Help/UGen/Oscillator/dc.help.lhs b/Help/UGen/Oscillator/dc.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Oscillator/dc.help.lhs
@@ -0,0 +1,18 @@
+> Sound.SC3.UGen.Help.viewSC3Help "DC"
+> Sound.SC3.UGen.DB.ugenSummary "DC"
+
+> import Sound.SC3
+
+Not DC offset 0.5
+> audition (out 0 0.5)
+
+Constantly zero
+> audition (out 0 (dc AR 0.5))
+
+DC offset; will click on start and finish
+> audition (out 0 (0.5 + sinOsc AR 440 0 * 0.1))
+> audition (out 0 (dc AR 0.5 + sinOsc AR 440 0 * 0.1))
+
+Transient before LeakDC adapts and suppresses the offset?
+> audition (out 0 (dc AR 1))
+> audition (out 0 (leakDC (dc AR 1) 0.995))
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
@@ -1,26 +1,16 @@
-fSinOsc rate freq iPhase
-
-Very fast sine wave generator implemented using a ringing filter.
-This generates a much cleaner sine wave than a table lookup oscillator
-and is a lot faster.  However, the amplitude of the wave will vary
-with frequency. Generally the amplitude will go down as you raise the
-frequency and go up as you lower the frequency.
-
-WARNING: In the current implementation, the amplitude can blow up if
-the frequency is modulated by certain alternating signals.
-
-freq   - frequency in Hertz
-iPhase - initial phase
+> Sound.SC3.UGen.Help.viewSC3Help "FSinOsc"
+> Sound.SC3.UGen.DB.ugenSummary "FSinOsc"
 
-Note the phase argument, which was not in the SC2 variant.
+# SC2
+The initial phase argument was not in the SC2 variant.
 
 > import Sound.SC3
 
-> audition (out 0 (fSinOsc AR (mce [440, 550]) 0 * 0.05))
+> audition (out 0 (fSinOsc AR (mce2 440 550) 0 * 0.05))
 
+Modulate frequency
 > audition (out 0 (fSinOsc AR (xLine KR 200 4000 1 RemoveSynth) 0 * 0.1))
 
 Loses amplitude towards the end
-
 > let f = fSinOsc AR (xLine KR 4 401 8 RemoveSynth)
 > in audition (out 0 (fSinOsc AR (f 0 * 200 + 800) 0 * 0.1))
diff --git a/Help/UGen/Oscillator/formant.help.lhs b/Help/UGen/Oscillator/formant.help.lhs
--- a/Help/UGen/Oscillator/formant.help.lhs
+++ b/Help/UGen/Oscillator/formant.help.lhs
@@ -1,22 +1,17 @@
-formant AR fundFreq formFreq bwFreq
-
-Formant oscillator. Generates a set of harmonics around a formant
-frequency at a given fundamental frequency.
-
-Modulate fundamental frequency, formant frequency stays constant.
+> Sound.SC3.UGen.Help.viewSC3Help "Formant"
+> Sound.SC3.UGen.DB.ugenSummary "Formant"
 
 > import Sound.SC3
 
+Modulate fundamental frequency, formant frequency stays constant.
 > let f = xLine KR 400 1000 8 RemoveSynth
 > in audition (out 0 (formant AR f 2000 800 * 0.125))
 
 Modulate formant frequency, fundamental frequency stays constant.
-
-> let { f = mce [200, 300, 400, 500]
->     ; ff = xLine KR 400 4000 8 RemoveSynth }
+> let {f = mce [200, 300, 400, 500]
+>     ;ff = xLine KR 400 4000 8 RemoveSynth}
 > in audition (out 0 (formant AR f ff 200 * 0.125))
 
 Modulate width frequency, other frequencies stay constant.
-
 > let bw = xLine KR 800 8000 8 RemoveSynth
 > in audition (out 0 (formant AR 400 2000 bw * 0.1))
diff --git a/Help/UGen/Oscillator/gendy1.help.lhs b/Help/UGen/Oscillator/gendy1.help.lhs
--- a/Help/UGen/Oscillator/gendy1.help.lhs
+++ b/Help/UGen/Oscillator/gendy1.help.lhs
@@ -1,178 +1,96 @@
-gendy1 rate ampDist durDist adParam ddParam minFreq maxFreq 
-       ampScale durScale initCPs kNum
-
-An implementation of the dynamic stochastic synthesis generator
-conceived by Iannis Xenakis and described in Formalized Music
-(1992, Stuyvesant, NY: Pendragon Press) chapter 9 (pp 246-254) and
-chapters 13 and 14 (pp 289-322). The BASIC program in the book was
-written by Marie-Helene Serra so I think it helpful to credit her
-too.
-
-ampdist - Choice of probability distribution for the next
-          perturbation of the amplitude of a control point.
-
-The distributions are (adapted from the GENDYN program in
-Formalized Music):
-
-  0- LINEAR
-  1- CAUCHY
-  2- LOGIST
-  3- HYPERBCOS
-  4- ARCSINE
-  5- EXPON
-  6- SINUS
-
-Where the sinus (Xenakis' name) is in this implementation taken as
-sampling from a third party oscillator. See example below.
-
-durdist - Choice of distribution for the perturbation of the
-          current inter control point duration.
-
-adparam - A parameter for the shape of the amplitude probability
-          distribution, requires values in the range 0.0001 to 1
-          (there are safety checks in the code so don't worry too
-          much if you want to modulate.)
-
-ddparam - A parameter for the shape of the duration probability
-          distribution, requires values in the range 0.0001 to 1
-
-minfreq - Minimum allowed frequency of oscillation for the Gendy1
-          oscillator, so gives the largest period the duration is
-          allowed to take on.
-
-maxfreq - Maximum allowed frequency of oscillation for the Gendy1
-          oscillator, so gives the smallest period the duration is
-          allowed to take on.
-
-ampscale - Normally 0.0 to 1.0, multiplier for the distribution's
-           delta value for amplitude. An ampscale of 1.0 allows the
-           full range of -1 to 1 for a change of amplitude.
-
-durscale - Normally 0.0 to 1.0, multiplier for the distribution's
-           delta value for duration. An ampscale of 1.0 allows the
-           full range of -1 to 1 for a change of duration.
-
-initCPs - Initialise the number of control points in the
-          memory. Xenakis specifies 12. There would be this number
-          of control points per cycle of the oscillator, though the
-          oscillator's period will constantly change due to the
-          duration distribution.
-
-knum - Current number of utilised control points, allows
-       modulation.
-
-
-sclang defaults: ampdist=1, durdist=1, adparam=1.0, ddparam=1.0,
-minfreq=440, maxfreq=660, ampscale= 0.5, durscale=0.5, initCPs= 12,
-knum=12.
+> Sound.SC3.UGen.Help.viewSC3Help "Gendy1"
+> Sound.SC3.UGen.DB.ugenSummary "Gendy1"
 
-> import Sound.SC3
+> import Sound.SC3.ID
 
+SC3 default parameters
 > let g = gendy1 AR 1 1 1 1 440 660 0.5 0.5 12 12
 > in audition (out 0 (pan2 g 0 0.15))
 
 Wandering bass
-
 > let g = gendy1 AR 1 1 1.0 1.0 30 100 0.3 0.05 5 5
 > in audition (out 0 (pan2 g 0 0.15))
 
-Play me	
-
-> let { x = mouseX KR 100 1000 Exponential 0.1
->     ; g = gendy1 AR 1 1 1.0 1.0 30 100 0.3 0.05 5 5 }
+Play me
+> let {x = mouseX' KR 100 1000 Exponential 0.1
+>     ;g = gendy1 AR 1 1 1.0 1.0 30 100 0.3 0.05 5 5}
 > in audition (out 0 (pan2 (rlpf g 500 0.3 * 0.2) 0 0.25))
 
 Scream!
-
-> let { x = mouseX KR 220 440 Exponential 0.1
->     ; y = mouseY KR 0.0 1.0 Linear 0.1 }
+> let {x = mouseX' KR 220 440 Exponential 0.1
+>     ;y = mouseY' KR 0.0 1.0 Linear 0.1}
 > in audition (out 0 (pan2 (gendy1 AR 2 3 1 1 x (8 * x) y y 7 7) 0.0 0.3))
 
 1 CP = random noise
-
 > let g = gendy1 AR 1 1 1 1 440 660 0.5 0.5 1 1
 > in audition (out 0 (pan2 g 0 0.15))
 
 2 CPs = an oscillator
-
-> let g = gendy1 AR 1 1 1 1 440 660 0.5 0.5 2 2 
+> let g = gendy1 AR 1 1 1 1 440 660 0.5 0.5 2 2
 > in audition (out 0 (pan2 g 0 0.15))
 
 Used as an LFO
-
-> let { ad = sinOsc KR 0.10 0 * 0.49 + 0.51
->     ; dd = sinOsc KR 0.13 0 * 0.49 + 0.51
->     ; as = sinOsc KR 0.17 0 * 0.49 + 0.51
->     ; ds = sinOsc KR 0.19 0 * 0.49 + 0.51
->     ; g = gendy1 KR 2 4 ad dd 3.4 3.5 as ds 10 10 }
+> let {ad = sinOsc KR 0.10 0 * 0.49 + 0.51
+>     ;dd = sinOsc KR 0.13 0 * 0.49 + 0.51
+>     ;as = sinOsc KR 0.17 0 * 0.49 + 0.51
+>     ;ds = sinOsc KR 0.19 0 * 0.49 + 0.51
+>     ;g = gendy1 KR 2 4 ad dd 3.4 3.5 as ds 10 10}
 > in audition (out 0 (pan2 (sinOsc AR (g * 50 + 350) 0) 0.0 0.3))
 
 Wasp
-
 > let ad = sinOsc KR 0.1 0 * 0.1 + 0.9
 > in audition (out 0 (pan2 (gendy1 AR 0 0 ad 1.0 50 1000 1 0.005 12 12) 0.0 0.2))
 
 Modulate distributions. Change of pitch as distributions change
 the duration structure and spectrum
-
-> let { x = mouseX KR 0 7 Linear 0.1
->     ; y = mouseY KR 0 7 Linear 0.1
->     ; g = gendy1 AR x y 1 1 440 660 0.5 0.5 12 12 }
+> let {x = mouseX' KR 0 7 Linear 0.1
+>     ;y = mouseY' KR 0 7 Linear 0.1
+>     ;g = gendy1 AR x y 1 1 440 660 0.5 0.5 12 12}
 > in audition (out 0 (pan2 g 0 0.2))
 
 Modulate number of CPs.
-
-> let { x = mouseX KR 1 13 Linear 0.1
->     ; g = gendy1 AR 1 1 1 1 440 660 0.5 0.5 12 x }
+> let {x = mouseX' KR 1 13 Linear 0.1
+>     ;g = gendy1 AR 1 1 1 1 440 660 0.5 0.5 12 x}
 > in audition (out 0 (pan2 g 0 0.2))
 
 Self modulation.
-
-> let { x = mouseX KR 1   13 Linear 0.1
->     ; y = mouseY KR 0.1 10 Linear 0.1
->     ; g0 = gendy1 AR 5 4 0.3 0.7 0.1 y 1.0 1.0 5 5
->     ; g1 = gendy1 AR 1 1 1 1 440 (g0 * 500 + 600) 0.5 0.5 12 x }
+> let {x = mouseX' KR 1   13 Linear 0.1
+>     ;y = mouseY' KR 0.1 10 Linear 0.1
+>     ;g0 = gendy1 AR 5 4 0.3 0.7 0.1 y 1.0 1.0 5 5
+>     ;g1 = gendy1 AR 1 1 1 1 440 (g0 * 500 + 600) 0.5 0.5 12 x}
 > in audition (out 0 (pan2 g1 0 0.2))
 
 Use SINUS to track any oscillator and take CP positions from it use
 adParam and ddParam as the inputs to sample.
-
-> let { p = lfPulse KR 100 0 0.4
->     ; s = sinOsc KR 30 0 * 0.5
->     ; g = gendy1 AR 6 6 p s 440 660 0.5 0.5 12 12 }
+> let {p = lfPulse KR 100 0 0.4
+>     ;s = sinOsc KR 30 0 * 0.5
+>     ;g = gendy1 AR 6 6 p s 440 660 0.5 0.5 12 12}
 > in audition (out 0 (pan2 g 0 0.2))
 
 Near the corners are interesting.
-
-> let { x = mouseX KR 0 200 Linear 0.1
->     ; y = mouseY KR 0 200 Linear 0.1
->     ; p = lfPulse KR x 0 0.4
->     ; s = sinOsc KR y 0 * 0.5
->     ; g = gendy1 AR 6 6 p s 440 660 0.5 0.5 12 12 }
+> let {x = mouseX' KR 0 200 Linear 0.1
+>     ;y = mouseY' KR 0 200 Linear 0.1
+>     ;p = lfPulse KR x 0 0.4
+>     ;s = sinOsc KR y 0 * 0.5
+>     ;g = gendy1 AR 6 6 p s 440 660 0.5 0.5 12 12}
 > in audition (out 0 (pan2 g 0 0.2))
 
 Texture
-
-> import Sound.SC3.Monadic
-> import Control.Monad
-
-> let node = do { f  <- rand 130 160.3
->               ; r0 <- rand 0 6
->               ; r1 <- rand 0 6
->               ; l  <- rand (-1) 1
->               ; let { ad = sinOsc KR 0.10 0 * 0.49 + 0.51
->                     ; dd = sinOsc KR 0.13 0 * 0.49 + 0.51
->                     ; as = sinOsc KR 0.17 0 * 0.49 + 0.51
->                     ; ds = sinOsc KR 0.19 0 * 0.49 + 0.51
->                     ; g = gendy1 AR r0 r1 ad dd f f as ds 12 12
->                     ; o = sinOsc AR (g * 200 + 400) 0 }
->                 in return (pan2 o l 0.1) }
-> in do { m <- replicateM 9 node
->       ; audition (out 0 (mix (mce m))) }
+> let node e = let {f = rand e 130 160.3
+>                  ;r0 = rand e 0 6
+>                  ;r1 = rand (Data.Char.toUpper e) 0 6
+>                  ;l = rand e (-1) 1
+>                  ;ad = sinOsc KR 0.10 0 * 0.49 + 0.51
+>                  ;dd = sinOsc KR 0.13 0 * 0.49 + 0.51
+>                  ;as = sinOsc KR 0.17 0 * 0.49 + 0.51
+>                  ;ds = sinOsc KR 0.19 0 * 0.49 + 0.51
+>                  ;g = gendy1 AR r0 r1 ad dd f f as ds 12 12
+>                  ;o = sinOsc AR (g * 200 + 400) 0}
+>              in pan2 o l 0.1
+> in audition (out 0 (mix (mce (map node ['a'..'i']))))
 
 Try durscale 10.0 and 0.0 too.
-
-> let { x = mouseX KR 10 700 Linear 0.1
->     ; y = mouseY KR 50 1000 Linear 0.1
->     ; g = gendy1 AR 2 3 1 1 1 x 0.5 0.1 10 10 }
+> let {x = mouseX' KR 10 700 Linear 0.1
+>     ;y = mouseY' KR 50 1000 Linear 0.1
+>     ;g = gendy1 AR 2 3 1 1 1 x 0.5 0.1 10 10}
 > in audition (out 0 (pan2 (combN (resonz g y 0.1) 0.1 0.1 5) 0.0 0.6))
diff --git a/Help/UGen/Oscillator/impulse.help.lhs b/Help/UGen/Oscillator/impulse.help.lhs
--- a/Help/UGen/Oscillator/impulse.help.lhs
+++ b/Help/UGen/Oscillator/impulse.help.lhs
@@ -1,9 +1,5 @@
-impulse rate freq iPhase
-
-Impulse oscillator.  Outputs non band limited single sample impulses.
-
-freq  - frequency in Hertz
-phase - phase offset in cycles (0..1)
+> Sound.SC3.UGen.Help.viewSC3Help "Impulse"
+> Sound.SC3.UGen.DB.ugenSummary "Impulse"
 
 > import Sound.SC3
 
@@ -12,6 +8,9 @@
 > let f = xLine KR 800 10 5 RemoveSynth
 > in audition (out 0 (impulse AR f 0.0 * 0.1))
 
-> let { f = mouseY KR 4 8 Linear 0.1
-      ; x = mouseX KR 0 1 Linear 0.1 }
-> in audition (out 0 (impulse AR f (mce [0, x]) * 0.1))
+> let {f = mouseY' KR 4 8 Linear 0.1
+>     ;x = mouseX' KR 0 1 Linear 0.1}
+> in audition (out 0 (impulse AR f (mce [0,x]) * 0.1))
+
+An impulse with frequency 0 returns a single impulse
+> audition (out 0 (decay (impulse AR 0 0) 1 * brownNoise 'a' AR * 0.1))
diff --git a/Help/UGen/Oscillator/klang.help.lhs b/Help/UGen/Oscillator/klang.help.lhs
--- a/Help/UGen/Oscillator/klang.help.lhs
+++ b/Help/UGen/Oscillator/klang.help.lhs
@@ -1,11 +1,12 @@
-klang rate freqScale freqOffset spec
+> Sound.SC3.UGen.Help.viewSC3Help "Klang"
+> Sound.SC3.UGen.DB.ugenSummary "Klang"
 
-Bank of fixed oscillators.  spec is constructed using klangSpec, which
-takes lists of frequency, amplitude and phase.
+# SC3
+Input re-ordering of specification array.
 
 > import Sound.SC3
 
-> let { f = [440,550..1100]
->     ; a = take 7 (cycle [0.05, 0.02])
->     ; p = replicate 7 0 }
+> let {f = [440,550..1100]
+>     ;a = take 7 (cycle [0.05, 0.02])
+>     ;p = replicate 7 0}
 > in audition (out 0 (klang AR 1 0 (klangSpec f a p)))
diff --git a/Help/UGen/Oscillator/lfCub.help.lhs b/Help/UGen/Oscillator/lfCub.help.lhs
--- a/Help/UGen/Oscillator/lfCub.help.lhs
+++ b/Help/UGen/Oscillator/lfCub.help.lhs
@@ -1,6 +1,5 @@
-lfCub rate freq iphase
- 
-A sine like shape made of two cubic pieces. Smoother than lfPar.
+> Sound.SC3.UGen.Help.viewSC3Help "LFCub"
+> Sound.SC3.UGen.DB.ugenSummary "LFCub"
 
 > import Sound.SC3
 
@@ -9,22 +8,19 @@
 > audition (out 0 (lfCub AR 800 0 * 0.1))
 > audition (out 0 (lfCub AR (xLine KR 100 8000 30 DoNothing) 0 * 0.1))
 
-Compare (lfPar):
-
+Compare w/ lfPar
 > audition (out 0 (lfPar AR (lfPar KR (lfPar KR 0.2 0 * 8 + 10) 0 * 400 + 800) 0 * 0.1))
 > audition (out 0 (lfPar AR (lfPar KR 0.2 0 * 400 + 800) 0 * 0.1))
 > audition (out 0 (lfPar AR 800 0 * 0.1))
 > audition (out 0 (lfPar AR (xLine KR 100 8000 30 DoNothing) 0 * 0.1))
 
-Compare (sinOsc):
-
+Compare w/ sinOsc
 > audition (out 0 (sinOsc AR (sinOsc KR (sinOsc KR 0.2 0 * 8 + 10) 0 * 400 + 800) 0 * 0.1))
 > audition (out 0 (sinOsc AR (sinOsc KR 0.2 0 * 400 + 800) 0 * 0.1))
 > audition (out 0 (sinOsc AR 800 0 * 0.1))
 > audition (out 0 (sinOsc AR (xLine KR 100 8000 30 DoNothing) 0 * 0.1))
 
-Compare (lfTri):
-
+Compare w/ lfTri
 > audition (out 0 (lfTri AR (lfTri KR (lfTri KR 0.2 0 * 8 + 10) 0 * 400 + 800) 0 * 0.1))
 > audition (out 0 (lfTri AR (lfTri KR 0.2 0 * 400 + 800) 0 * 0.1))
 > audition (out 0 (lfTri AR 800 0 * 0.1))
diff --git a/Help/UGen/Oscillator/lfPar.help.lhs b/Help/UGen/Oscillator/lfPar.help.lhs
--- a/Help/UGen/Oscillator/lfPar.help.lhs
+++ b/Help/UGen/Oscillator/lfPar.help.lhs
@@ -1,5 +1,4 @@
-lfPar rate freq iphase
-
-A sine-like shape made of two parabolas. Has audible odd harmonics.
+> Sound.SC3.UGen.Help.viewSC3Help "LFPar"
+> Sound.SC3.UGen.DB.ugenSummary "LFPar"
 
-See lfCub.
+See lfCub
diff --git a/Help/UGen/Oscillator/lfPulse.help.lhs b/Help/UGen/Oscillator/lfPulse.help.lhs
--- a/Help/UGen/Oscillator/lfPulse.help.lhs
+++ b/Help/UGen/Oscillator/lfPulse.help.lhs
@@ -1,17 +1,13 @@
-lfPulse rate freq iphase width
-
-A non-band-limited pulse oscillator. Outputs a high value of one
-and a low value of zero.  Note that the iphase argument was not
-present in SC2.
+> Sound.SC3.UGen.Help.viewSC3Help "LFPulse"
+> Sound.SC3.UGen.DB.ugenSummary "LFPulse"
 
-freq - frequency in Hertz
-iphase - initial phase offset in cycles ( 0..1 )
-width - pulse width duty cycle from zero to one.
+#SC2
+The initial phase argument was not present in SC2.
 
 > import Sound.SC3
 
 > let f = lfPulse KR 3 0 0.3 * 200 + 200
 > in audition (out 0 (lfPulse AR f 0 0.2 * 0.1))
 
-> let x = mouseX KR 0 1 Linear 0.2
+> let x = mouseX' KR 0 1 Linear 0.2
 > in audition (out 0 (lfPulse AR 220 0 x * 0.1))
diff --git a/Help/UGen/Oscillator/lfSaw.help.lhs b/Help/UGen/Oscillator/lfSaw.help.lhs
--- a/Help/UGen/Oscillator/lfSaw.help.lhs
+++ b/Help/UGen/Oscillator/lfSaw.help.lhs
@@ -1,21 +1,17 @@
-lfSaw rate freq iphase
-
-Sawtooth oscillator.  A non-band-limited sawtooth
-oscillator. Output ranges from -1 to +1.
+> Sound.SC3.UGen.Help.viewSC3Help "LFSaw"
+> Sound.SC3.UGen.DB.ugenSummary "LFSaw"
 
-freq   - frequency in Hertz
-iphase - initial phase [0,2]
+# SC2
+SC2 LFSaw did not have an initial phase argument.
 
 > import Sound.SC3
 
 > audition (out 0 (lfSaw AR 500 1 * 0.1))
 
 Used as both Oscillator and LFO.
-
 > audition (out 0 (lfSaw AR (lfSaw KR 4 0 * 400 + 400) 0 * 0.1))
 
 Output range is bi-polar.
-
-> let { f = mce [linLin (lfSaw KR 0.5 0) (-1) 1 200 1600, 200, 1600]
->     ; a = mce [0.1, 0.05, 0.05] }
+> let {f = mce [linLin (lfSaw KR 0.5 0) (-1) 1 200 1600, 200, 1600]
+>     ;a = mce [0.1,0.05,0.05]}
 > in audition (out 0 (mix (sinOsc AR f 0 * a)))
diff --git a/Help/UGen/Oscillator/lfTri.help.lhs b/Help/UGen/Oscillator/lfTri.help.lhs
--- a/Help/UGen/Oscillator/lfTri.help.lhs
+++ b/Help/UGen/Oscillator/lfTri.help.lhs
@@ -1,12 +1,13 @@
-lfTri rate freq iphase
-
-A non-band-limited triangular waveform oscillator. Output ranges
-from -1 to +1.
+> Sound.SC3.UGen.Help.viewSC3Help "LFTri"
+> Sound.SC3.UGen.DB.ugenSummary "LFTri"
 
 > import Sound.SC3
 
 > audition (out 0 (lfTri AR 500 1 * 0.1))
 
 Used as both Oscillator and LFO.
-
 > audition (out 0 (lfTri AR (lfTri KR 4 0 * 400 + 400) 0 * 0.1))
+
+Multiple phases
+> let f = lfTri KR 0.4 (mce [0..3]) * 200 + 400
+> in audition (out 0 (mix (lfTri AR f 0 * 0.1)))
diff --git a/Help/UGen/Oscillator/oscN.help.lhs b/Help/UGen/Oscillator/oscN.help.lhs
--- a/Help/UGen/Oscillator/oscN.help.lhs
+++ b/Help/UGen/Oscillator/oscN.help.lhs
@@ -1,10 +1,4 @@
-oscN rate bufnum freq phase
-
-Noninterpolating wavetable lookup oscillator with frequency and
-phase modulation inputs.  It is usually better to use the
-interpolating oscillator.
-
-The buffer size must be a power of 2.  The buffer should NOT be
-filled using Wavetable format (b_gen commands should set wavetable
-flag to false.
+> Sound.SC3.UGen.Help.viewSC3Help "OscN"
+> Sound.SC3.UGen.DB.ugenSummary "OscN"
 
+See osc
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
@@ -1,23 +1,22 @@
-pmOsc rate cf mf pm mp
-
-phase modulation oscillator (composite UGen)
+> Sound.SC3.UGen.Help.viewSC3Help "PMOsc"
+> :t pmOsc
 
-    cf = carrier frequency
-    mf = modulation frequency
-    pm = modulator amplitude
-    mp = modulator phase
+# composite
+sinOsc r cf (sinOsc r mf mp * pm)
 
-The definition is:
+> import Sound.SC3.ID
 
-  pmOsc r cf mf pm mp = sinOsc r cf (sinOsc r mf mp * pm)
+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
+>                 ;pm = line KR 0 pme n DoNothing}
+> in linPan2 (pmOsc AR cf mf pm 0) l 0.05
 
-> import Sound.SC3.Monadic
+> audition (out 0 (pmi 2))
 
-> do { cf <- rand 0 2000
->    ; mf <- rand 0 800
->    ; pm' <- rand 0 12
->    ; l <- rand (-1) 1
->    ; let { t = envLinen' 2 5 2 1 (EnvLin, EnvLin, EnvLin)
->          ; e = envGen KR 1 0.1 0 1 RemoveSynth t
->          ; pm = line KR 0 pm' 9 DoNothing }
->      in audition (out 0 (linPan2 (pmOsc AR cf mf pm 0) l e)) }
+PM textures
+> import qualified Sound.SC3.Lang.Control.OverlapTexture as L
+> L.overlapTextureU (1,0,5,maxBound) (pmi 1)
+> L.overlapTextureU (6,6,6,maxBound) (pmi 12)
diff --git a/Help/UGen/Oscillator/pulse.help.lhs b/Help/UGen/Oscillator/pulse.help.lhs
--- a/Help/UGen/Oscillator/pulse.help.lhs
+++ b/Help/UGen/Oscillator/pulse.help.lhs
@@ -1,26 +1,17 @@
-pulse AR f w
-
-   r - operating rate
-   f - frequency (hz)
-   w - width (0.5)
-
-Bandlimited pulse wave generator.
-
-Modulate frequency
+> Sound.SC3.UGen.Help.viewSC3Help "Pulse"
+> Sound.SC3.UGen.DB.ugenSummary "Pulse"
 
 > import Sound.SC3
 
+Modulate frequency
 > let f = xLine KR 40 4000 6 RemoveSynth
 > in audition (out 0 (pulse AR f 0.1 * 0.1))
 
 Modulate pulse width
-
 > let w = line KR 0.01 0.99 8 RemoveSynth
 > in audition (out 0 (pulse AR 200 w * 0.1))
 
-Two band limited square waves through a resonant 
-low pass filter
-
-> let { p = pulse AR (mce [100, 250]) 0.5 * 0.1
->     ; f = xLine KR 8000 400 5 RemoveSynth }
+Two band limited square waves through a resonant low pass filter
+> let {p = pulse AR (mce2 100 250) 0.5 * 0.1
+>     ;f = xLine KR 8000 400 5 DoNothing}
 > in audition (out 0 (rlpf p f 0.05))
diff --git a/Help/UGen/Oscillator/saw.help.lhs b/Help/UGen/Oscillator/saw.help.lhs
--- a/Help/UGen/Oscillator/saw.help.lhs
+++ b/Help/UGen/Oscillator/saw.help.lhs
@@ -1,12 +1,10 @@
-saw AR freq
-
-Band limited sawtooth wave generator.
+> Sound.SC3.UGen.Help.viewSC3Help "Saw"
+> Sound.SC3.UGen.DB.ugenSummary "Saw"
 
 > import Sound.SC3
 
 > audition (out 0 (saw AR (xLine KR 40 4000 6 RemoveSynth) * 0.1))
 
 Two band limited sawtooth waves thru a resonant low pass filter
-
 > let f = xLine KR 8000 400 5 DoNothing
-> in audition (out 0 (rlpf (saw AR (mce [100, 250]) * 0.1) f 0.05))
+> in audition (out 0 (rlpf (saw AR (mce2 100 250) * 0.1) f 0.05))
diff --git a/Help/UGen/Oscillator/silent.help.lhs b/Help/UGen/Oscillator/silent.help.lhs
--- a/Help/UGen/Oscillator/silent.help.lhs
+++ b/Help/UGen/Oscillator/silent.help.lhs
@@ -1,6 +1,5 @@
-silent numberOfChannels
-
-Generate a silent (zero) signal.
+> Sound.SC3.UGen.Help.viewSC3Help "Silent"
+> Sound.SC3.UGen.DB.ugenSummary "Silent"
 
 > import Sound.SC3
 
diff --git a/Help/UGen/Oscillator/sinOsc.help.lhs b/Help/UGen/Oscillator/sinOsc.help.lhs
--- a/Help/UGen/Oscillator/sinOsc.help.lhs
+++ b/Help/UGen/Oscillator/sinOsc.help.lhs
@@ -1,33 +1,25 @@
-sinOsc rate freq phase
-
-Interpolating sine wavetable oscillator.  This is the same as osc
-except that the table is a sine table of 8192 entries.
-
-freq  - frequency in Hertz
-phase - phase offset or modulator in radians
+> Sound.SC3.UGen.Help.viewSC3Help "SinOsc"
+> Sound.SC3.UGen.DB.ugenSummary "SinOsc"
 
 > import Sound.SC3
 
+Fixed frequency
 > audition (out 0 (sinOsc AR 440 0 * 0.25))
 
 Modulate freq
-
 > audition (out 0 (sinOsc AR (xLine KR 2000 200 9 RemoveSynth) 0 * 0.5))
 
 Modulate freq
-
 > let f = sinOsc AR (xLine KR 1 1000 9 RemoveSynth) 0 * 200 + 800
 > in audition (out 0 (sinOsc AR f 0 * 0.1))
 
 Modulate phase
-
 > let p = sinOsc AR (xLine KR 20 8000 10 RemoveSynth) 0 * 2 * pi
 > in audition (out 0 (sinOsc AR 800 p * 0.1))
 
 Simple bell-like tone.
-
-> let { f = mce [0.5, 1, 1.19, 1.56, 2, 2.51, 2.66, 3.01, 4.1]
->     ; a = mce [0.25, 1, 0.8, 0.5, 0.9, 0.4, 0.3, 0.6, 0.1]
->     ; o = sinOsc AR (500 * f) 0 * a
->     ; e = envGen KR 1 0.1 0 1 RemoveSynth (envPerc 0.01 10) }
+> let {f = mce [0.5,1,1.19,1.56,2,2.51,2.66,3.01,4.1]
+>     ;a = mce [0.25,1,0.8,0.5,0.9,0.4,0.3,0.6,0.1]
+>     ;o = sinOsc AR (500 * f) 0 * a
+>     ;e = envGen KR 1 0.1 0 1 RemoveSynth (envPerc 0.01 10)}
 > in audition (out 0 (mix o * e))
diff --git a/Help/UGen/Oscillator/syncSaw.help.lhs b/Help/UGen/Oscillator/syncSaw.help.lhs
--- a/Help/UGen/Oscillator/syncSaw.help.lhs
+++ b/Help/UGen/Oscillator/syncSaw.help.lhs
@@ -1,14 +1,12 @@
-syncSaw rate syncFreq sawFreq
-
-A sawtooth wave that is hard synched to a fundamental pitch. This
-produces an effect similar to moving formants or pulse width
-modulation. The sawtooth oscillator has its phase reset when the
-sync oscillator completes a cycle. This is not a band limited
-waveform, so it may alias.
-
-The frequency of the slave synched sawtooth wave should always be
-greater than the syncFreq.
+> Sound.SC3.UGen.Help.viewSC3Help "SyncSaw"
+> Sound.SC3.UGen.DB.ugenSummary "SyncSaw"
 
 > import Sound.SC3
 
-> audition (out 0 (syncSaw AR 100 (line KR 100 800 12 RemoveSynth) * 0.1))
+> let f = line KR 100 800 12 RemoveSynth
+> in audition (out 0 (syncSaw AR 100 f * 0.1))
+
+Mouse control
+> let {sy_f = mouseY' KR 80 220 Exponential 0.2
+>     ;sw_f = sy_f * mouseX' KR 1 3 Linear 0.2}
+> in audition (out 0 (syncSaw AR sy_f sw_f * 0.1))
diff --git a/Help/UGen/Oscillator/tChoose.help.lhs b/Help/UGen/Oscillator/tChoose.help.lhs
--- a/Help/UGen/Oscillator/tChoose.help.lhs
+++ b/Help/UGen/Oscillator/tChoose.help.lhs
@@ -1,19 +1,16 @@
-tChoose trig inputs
-
-The output is selected randomly on recieving a trigger from an
-array of inputs.  tChoose is a composite of tiRand and select.
+> Sound.SC3.UGen.Help.viewSC3Help "TChoose"
+> :t tChoose
 
-> import Control.Monad
-> import Sound.SC3.Monadic
+# composite
+tChoose is a composite of tIRand and select.
 
-> let x = mouseX kr 1 1000 Exponential 0.1
-> in do { t <- dust AR x
->       ; f <- liftM midiCPS (tiRand 48 60 t)
->       ; o <- let a = mce [ sinOsc AR f 0
->                          , saw AR (f * 2)
->                          , pulse AR (f * 0.5) 0.1 ]
->              in tChoose t a
->       ; audition (out 0 (o * 0.1)) }
+> import Sound.SC3.ID
 
-;; Note: all the ugens are continously running. This may not be the
-;; most efficient way if each input is cpu-expensive.
+> let {x = mouseX' kr 1 1000 Exponential 0.1
+>     ;t = dust 'a' AR x
+>     ;f = midiCPS (tIRand 'b' 48 60 t)
+>     ;o = let a = mce [sinOsc AR f 0
+>                      ,saw AR (f * 2)
+>                      ,pulse AR (f * 0.5) 0.1]
+>           in tChoose 'c' t a}
+> in audition (out 0 (o * 0.1))
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
@@ -1,67 +1,49 @@
-tGrains numChannels trigger bufnum rate centerPos dur pan amp interp
-
-Buffer granulator.  Triggers generate grains from a buffer. Each
-grain has a Hanning envelope (sin^2(x) for x from 0 to pi) and is
-panned between two channels of multiple outputs.
-
-numChannels - number of output channels.
-
-trigger - at each trigger, the following arguments are sampled and
-          used as the arguments of a new grain.  A trigger occurs
-          when a signal changes from <= 0 to > 0.  If the trigger
-          is audio rate then the grains will start with sample
-          accuracy.
-
-bufnum - the index of the buffer to use. It must be a one channel
-         (mono) buffer.
-
-rate - 1.0 is normal, 2.0 is one octave up, 0.5 is one octave down
-       and -1.0 is backwards normal rate ... etc.  Unlike PlayBuf,
-       the rate is multiplied by BufRate, so you needn't do that
-       yourself.
-
-centerPos - the position in the buffer in seconds at which the
-            grain envelope will reach maximum amplitude.
-
-dur - duration of the grain in seconds.
-
-pan - a value from -1 to 1. Determines where to pan the output in
-      the same manner as PanAz.
-
-amp - amplitude of the grain.
-
-interp - 1, 2, or 4. Determines whether the grain uses (1) no
-         interpolation, (2) linear interpolation, or (4) cubic
-         interpolation.
+> Sound.SC3.UGen.Help.viewSC3Help "TGrains"
+> Sound.SC3.UGen.DB.ugenSummary "TGrains"
 
-> import Sound.SC3
+> import Sound.SC3.ID
 
-> let fn = "/home/rohan/audio/metal.wav"
+Load audio data
+> let fn = "/home/rohan/data/audio/pf-c5.aif"
 > in withSC3 (\fd -> async fd (b_allocRead 10 fn 0 0))
 
-> let { tRate = mouseY KR 2 200 Exponential 0.1
->     ; ctr = mouseX KR 0 (bufDur KR 10) Linear 0.1
->     ; tr = impulse AR tRate 0 }
+Mouse control
+> let {tRate = mouseY' KR 2 200 Exponential 0.1
+>     ;ctr = mouseX' KR 0 (bufDur KR 10) Linear 0.1
+>     ;tr = impulse AR tRate 0}
 > in audition (out 0 (tGrains 2 tr 10 1 ctr (4 / tRate) 0 0.1 2))
 
-> import Sound.SC3.Monadic
+> 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
+>     ;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))
 
-> let { b = 10
->     ; trate = mouseY KR 8 120 Exponential 0.1
->     ; dur = 4 / trate }
-> in do { clk <- dust AR trate
->       ; r <- tRand 0 0.01 clk
->       ; pan <- return . (* 0.6) =<< whiteNoise KR
->       ; let { 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)) }
+> let {b = 10
+>     ;rt = mouseY' KR 2 120 Exponential 0.1
+>     ;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
+>     ;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))
 
-> let { b = 10
->     ; trate = mouseY KR 2 120 Exponential 0.1
->     ; dur = 1.2 / trate
->     ; clk = impulse AR trate 0
->     ; pos = mouseX KR 0 (bufDur KR b) Linear 0.1 }
-> in do { n0 <- whiteNoise KR
->       ; n1 <- whiteNoise KR
->       ; let rate = shiftLeft 1.2 (roundE (n0 * 3) 1)
->         in audition (out 0 (tGrains 2 clk b rate pos dur (n1 * 0.6) 0.25 2)) }
+Demand UGens as inputs (will eventually hang scsynth...)
+> let {b = 10
+>     ;rt = mouseY' KR 2 100 Linear 0.2
+>     ;d e = dwhite e 1 0.1 0.2
+>     ;z e0 e1 = drand e0 1 (mce [dgeom e0 (diwhite e0 1 20 40) 0.1 (1 + d e0)
+>                                ,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]}
+> in audition (out 0 (tGrains 2 clk b rate pos dur pan amp 2))
diff --git a/Help/UGen/Oscillator/tWindex.help.lhs b/Help/UGen/Oscillator/tWindex.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Oscillator/tWindex.help.lhs
@@ -0,0 +1,17 @@
+> Sound.SC3.UGen.Help.viewSC3Help "TWindex"
+> Sound.SC3.UGen.DB.ugenSummary "TWindex"
+
+> import Sound.SC3.ID
+
+> let {p = mce [1/5, 2/5, 2/5]
+>     ;a = mce [400, 500, 600]
+>     ;t = impulse KR 6 0
+>     ;i = tWindex 'a' t 0 p}
+> in audition (out 0 (sinOsc AR (select i  a) 0 * 0.1))
+
+Modulating probability values
+> let {p = mce [1/4, 1/2, sinOsc KR 0.3 0 * 0.5 + 0.5]
+>     ;a = mce [400, 500, 600]
+>     ;t = impulse KR 6 0
+>     ;i = tWindex 'a' t 1 p}
+> in audition (out 0 (sinOsc AR (select i a) 0 * 0.1))
diff --git a/Help/UGen/Oscillator/twChoose.help.lhs b/Help/UGen/Oscillator/twChoose.help.lhs
--- a/Help/UGen/Oscillator/twChoose.help.lhs
+++ b/Help/UGen/Oscillator/twChoose.help.lhs
@@ -1,23 +1,15 @@
-twChoose trig array weights normalize
-
-The output is selected randomly on recieving a trigger from an
-array of inputs.  The weights of this choice are determined from
-the weights array.  If normalize is set to 1 the weights are
-continuously normalized, which means an extra calculation overhead.
-When using fixed values the normalizeSum method can be used to
-normalize the values.  TWChoose is a composite of TWindex and
-Select
+> Sound.SC3.UGen.Help.viewSC3Help "TWChoose"
 
-> import Sound.SC3.Monadic
+# composite
+tWChoose is a composite of tWindex and select
 
-> let x = mouseX KR 1 1000 Exponential 0.1
-> in do { d <- dust AR x
->       ; let { a = mce [ sinOsc AR 220 0
->                       , saw AR 440
->                       , pulse AR 110 0.1] 
->             ; w = mce [0.5, 0.35, 0.15] }
->         in do { o <- twChoose d a w 0
->               ; audition (out 0 (o * 0.1)) } }
+> import Sound.SC3.ID
 
-Note: all the ugens are continously running. This may not be the
-most efficient way if each input is cpu-expensive.
+> let {x = mouseX' KR 1 1000 Exponential 0.1
+>     ;d = dust 'a' AR x
+>     ;a = mce [sinOsc AR 220 0
+>              ,saw AR 440
+>              ,pulse AR 110 0.1]
+>     ;w = mce [0.5, 0.35, 0.15]
+>     ;o = tWChoose 'b' d a w 0}
+> in audition (out 0 (o * 0.1))
diff --git a/Help/UGen/Oscillator/twindex.help.lhs b/Help/UGen/Oscillator/twindex.help.lhs
deleted file mode 100644
--- a/Help/UGen/Oscillator/twindex.help.lhs
+++ /dev/null
@@ -1,23 +0,0 @@
-twindex in normalize array
-
-Triggered windex.  When triggered, returns a random index value based
-on array as a list of probabilities.  By default the list of
-probabilities should sum to 1, when the normalize flag is set to 1,
-the values get normalized by the ugen (less efficient) Assuming
-normalized values
-
-> import Sound.SC3.Monadic
-
-> let { p = mce [1/5, 2/5, 2/5]
->     ; a = mce [400, 500, 600]
->     ; t = impulse KR 6 0 }
-> in do { i <- twindex t 0 p
->       ; audition (out 0 (sinOsc AR (select i  a) 0 * 0.1)) }
-
-Modulating probability values
-
-> let { p = mce [1/4, 1/2, sinOsc KR 0.3 0 * 0.5 + 0.5]
->     ; a = mce [400, 500, 600]
->     ; t = impulse KR 6 0 }
-> in do { i <- twindex t 1 p
->       ; audition (out 0 (sinOsc AR (select i a) 0 * 0.1)) }
diff --git a/Help/UGen/Oscillator/varSaw.help.lhs b/Help/UGen/Oscillator/varSaw.help.lhs
--- a/Help/UGen/Oscillator/varSaw.help.lhs
+++ b/Help/UGen/Oscillator/varSaw.help.lhs
@@ -1,13 +1,13 @@
-varSaw rate freq iphasewidth
-
-Variable duty saw
-
-freq   - frequency in Hertz
-iphase - initial phase offset in cycles ( 0..1 )
-width  - duty cycle from zero to one.
+> Sound.SC3.UGen.Help.viewSC3Help "VarSaw"
+> Sound.SC3.UGen.DB.ugenSummary "VarSaw"
 
 > import Sound.SC3
 
-> let { f = lfPulse KR (mce2 3 3.03) 0 0.3 * 200 + 200
->     ; w = linLin (lfTri KR 1 0) (-1) 1 0 1 }
+> let {f = lfPulse KR (mce2 3 3.03) 0 0.3 * 200 + 200
+>     ;w = linLin (lfTri KR 1 0) (-1) 1 0 1}
 > in audition (out 0 (varSaw AR f 0 w * 0.1))
+
+Compare with lfPulse at AR
+> let f = lfPulse KR 3 0 0.3 * 200 + 200
+> in audition (out 0 (mce [varSaw AR f 0 0.2
+>                         ,lfPulse AR f 0 0.2] * 0.1))
diff --git a/Help/UGen/Panner/linPan2.help.lhs b/Help/UGen/Panner/linPan2.help.lhs
--- a/Help/UGen/Panner/linPan2.help.lhs
+++ b/Help/UGen/Panner/linPan2.help.lhs
@@ -1,6 +1,5 @@
-linPan2 in pos level
-
-Two channel linear pan.  See Pan2.
+> Sound.SC3.UGen.Help.viewSC3Help "LinPan2"
+> Sound.SC3.UGen.DB.ugenSummary "LinPan2"
 
 > import Sound.SC3.ID
 
diff --git a/Help/UGen/Panner/pan2.help.lhs b/Help/UGen/Panner/pan2.help.lhs
--- a/Help/UGen/Panner/pan2.help.lhs
+++ b/Help/UGen/Panner/pan2.help.lhs
@@ -1,14 +1,12 @@
-pan2 in pos level
-
-Two channel equal power panner.  The pan position is bipolar, -1 is
-left, +1 is right.  The level is a control rate input.
+> Sound.SC3.UGen.Help.viewSC3Help "Pan2"
+> Sound.SC3.UGen.DB.ugenSummary "Pan2"
 
 > import Sound.SC3.ID
 
 > let n = pinkNoise 'a' AR
 > in audition (out 0 (pan2 n (fSinOsc KR 2 0) 0.3))
 
-> let { n = pinkNoise 'a' AR
->     ; x = mouseX KR (-1) 1 Linear 0.2
->     ; y = mouseY KR 0 1 Linear 0.2 }
+> let {n = pinkNoise 'a' AR
+>     ;x = mouseX' KR (-1) 1 Linear 0.2
+>     ;y = mouseY' KR 0 1 Linear 0.2}
 > in audition (out 0 (pan2 n x y))
diff --git a/Help/UGen/Panner/panAz.help.lhs b/Help/UGen/Panner/panAz.help.lhs
--- a/Help/UGen/Panner/panAz.help.lhs
+++ b/Help/UGen/Panner/panAz.help.lhs
@@ -1,39 +1,9 @@
-panAz :: Int -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
-
-Azimuth panner.  Multichannel equal power panner.
-
-numChans - number of output channels
-
-in - input signal
-
-pos - pan position. Channels are evenly spaced over a
-      cyclic period of 2.0 with 0.0 equal to the
-      position directly in front, 2.0/numChans a
-      clockwise shift 1/numChans of the way around the
-      ring, 4.0/numChans equal to a shift of
-      2/numChans, etc. Thus all channels will be
-      cyclically panned through if a sawtooth wave from
-      -1 to +1 is used to modulate the pos. N.B. Front
-      may or may not correspond to a speaker depending
-      on the setting of the orientation arg, see below.
-
-level - a control rate level input.
-
-width - The width of the panning envelope. Nominally
-        this is 2.0 which pans between pairs of
-        adjacent speakers. Width values greater than
-        two will spread the pan over greater numbers of
-        speakers. Width values less than one will leave
-        silent gaps between speakers.
-
-orientation - Should be zero if the front is a vertex
-              of the polygon. The first speaker will be
-              directly in front. Should be 0.5 if the
-              front bisects a side of the polygon. Then
-              the first speaker will be the one left of
-              center. Default is 0.5.
+> Sound.SC3.UGen.Help.viewSC3Help "PanAZ"
+> Sound.SC3.UGen.DB.ugenSummary "PanAZ"
 
 > import Sound.SC3.ID
 
-> let n = pinkNoise 'a' AR
-> in audition (out 0 (panAz 2 n (lfSaw KR 2 0) 0.1 2 0.5))
+> let {o = pinkNoise 'a' AR
+>     ;nc = 4
+>     ;fr = 0.15}
+> in audition (out 0 (panAz nc o (lfSaw KR fr 0) 0.1 2 0.5))
diff --git a/Help/UGen/Panner/rotate2.help.lhs b/Help/UGen/Panner/rotate2.help.lhs
--- a/Help/UGen/Panner/rotate2.help.lhs
+++ b/Help/UGen/Panner/rotate2.help.lhs
@@ -1,35 +1,15 @@
-rotate2 x y pos
-
-Rotate a sound field.  Rotate2 can be used for rotating an
-ambisonic B-format sound field around an axis.  Rotate2 does an
-equal power rotation so it also works well on stereo sounds.  It
-takes two audio inputs (x, y) and an angle control (pos).  It
-outputs two channels (x, y).
-
-It computes:
-
-     xout = cos(angle) * xin + sin(angle) * yin
-     yout = cos(angle) * yin - sin(angle) * xin
-
-where angle = pos * pi, so that -1 becomes -pi and +1 becomes +pi.
-This allows you to use an LFSaw to do continuous rotation around a
-circle.
-
-The control pos is the angle to rotate around the circle from -1
-to +1. -1 is 180 degrees, -0.5 is left, 0 is forward, +0.5 is
-right, +1 is behind.
-
-Rotation of stereo sound, via LFO.
+> Sound.SC3.UGen.Help.viewSC3Help "Rotate2"
+> Sound.SC3.UGen.DB.ugenSummary "Rotate2"
 
 > import Sound.SC3.ID
 
-> let { x = pinkNoise 'a' AR
->     ; y = lfTri AR 800 0 * lfPulse KR 3 0 0.3 * 0.2 }
+Rotation of stereo sound, via LFO.
+> let {x = pinkNoise 'a' AR
+>     ;y = lfTri AR 800 0 * lfPulse KR 3 0 0.3 * 0.2}
 > in audition (out 0 (rotate2 x y (lfSaw KR 0.1 0)))
 
 Rotation of stereo sound, via mouse.
-
-> let { x = mix (lfSaw AR (mce [198..201]) 0 * 0.1)
->     ; y = sinOsc AR 900 0 * lfPulse KR 3 0 0.3 * 0.2 
->     ; p = mouseX KR 0 2 Linear 0.2 }
+> let {x = mix (lfSaw AR (mce [198..201]) 0 * 0.1)
+>     ;y = sinOsc AR 900 0 * lfPulse KR 3 0 0.3 * 0.2
+>     ;p = mouseX' KR 0 2 Linear 0.2}
 > in audition (out 0 (rotate2 x y p))
diff --git a/Help/UGen/Panner/splay.help.lhs b/Help/UGen/Panner/splay.help.lhs
--- a/Help/UGen/Panner/splay.help.lhs
+++ b/Help/UGen/Panner/splay.help.lhs
@@ -1,19 +1,43 @@
-splay in spread level center
+> Sound.SC3.UGen.Help.viewSC3Help "Splay"
+splay inArray spread=1 level=1 center=0 levelComp=true
 
-splay spreads an array of channels across the stereo field.
+splay is a composite UGen.
 
-   spread - 0 = mono, 1 = stereo
-    level - 0 = silent, 1 = unit gain (equal power level compensated)
-   center - negate 1 = left, 1 = right
+> import Sound.SC3.ID
 
-> import Sound.SC3.Monadic
-> import Control.Monad
+mouse control
+> let {i = 6
+>     ;r = map (\e -> rand e 10 20) (take i ['a'..])
+>     ;n = lfNoise2 'a' KR (mce r)
+>     ;x = mouseX' KR (-1) 1 Linear 0.1
+>     ;y = mouseY' KR 1 0 Linear 0.1
+>     ;ci = constant . fromIntegral
+>     ;f = mce [1 .. ci i] + 3 * 100
+>     ;o = sinOsc AR (n * 200 + f) 0}
+> in audition (out 0 (splay o y 0.2 x True))
 
-> do { i <- return 6
->    ; r <- replicateM i (rand 10 20)
->    ; n <- lfNoise2 KR (mce r)
->    ; let { ci = constant . fromIntegral
->          ; x = mouseX KR (-1) 1 Linear 0.1
->          ; y = mouseY KR 1 0 Linear 0.1
->          ; o = sinOsc AR (n * 200 + (mce [1 .. ci i] + 3 * 100)) 0 }
->      in audition (out 0 (splay o y 0.2 x)) }
+n_set control
+> let {i = 10
+>     ;s = control KR "spread" 1
+>     ;l = control KR "level" 0.2
+>     ;c = control KR "center" 0
+>     ;r = map (\e -> rand e 10 20) (take i ['a'..])
+>     ;ci = constant . fromIntegral
+>     ;f = mce [1 .. ci i] + 3 * 100
+>     ;n = lfNoise2 'a' KR (mce r) * 200 + f}
+> in audition (out 0 (splay (sinOsc AR n 0) s l c True))
+
+full stereo
+> withSC3 (\fd -> send fd (n_set (-1) [("spread",1),("center",0)]))
+
+less wide
+> withSC3 (\fd -> send fd (n_set (-1) [("spread",0.5),("center",0)]))
+
+mono center
+> withSC3 (\fd -> send fd (n_set (-1) [("spread",0),("center",0)]))
+
+from center to right
+> withSC3 (\fd -> send fd (n_set (-1) [("spread",0.5),("center",0.5)]))
+
+all left
+> withSC3 (\fd -> send fd (n_set (-1) [("spread",0),("center",-1)]))
diff --git a/Help/UGen/Trigger/gate.help.lhs b/Help/UGen/Trigger/gate.help.lhs
--- a/Help/UGen/Trigger/gate.help.lhs
+++ b/Help/UGen/Trigger/gate.help.lhs
@@ -1,6 +1,7 @@
-gate in trig
+> Sound.SC3.UGen.Help.viewSC3Help "Gate"
+> Sound.SC3.UGen.DB.ugenSummary "Gate"
 
-The signal at `in' is passed while `trig' is greater than zero.
+# hsc3: filter
 
 > import Sound.SC3
 
diff --git a/Help/UGen/Trigger/inRange.help.lhs b/Help/UGen/Trigger/inRange.help.lhs
--- a/Help/UGen/Trigger/inRange.help.lhs
+++ b/Help/UGen/Trigger/inRange.help.lhs
@@ -1,17 +1,10 @@
-inRange in lo hi
-
-Tests if a signal is within a given range.
-
-If in is >= lo and <= hi output 1.0, otherwise output 0.0. Output
-is initially zero.
-
-in - signal to be tested
-lo - low threshold
-hi - high threshold
+> Sound.SC3.UGen.Help.viewSC3Help "InRange"
+> Sound.SC3.UGen.DB.ugenSummary "InRange"
 
 > import Sound.SC3.ID
 
-> let { n = brownNoise 'α' AR
->     ; x = mouseX KR 1 2 Linear 0.1 
->     ; o = sinOsc KR x 0 * 0.2 }
-> in audition (out 0 (inRange o (-0.15) 0.15 * n * 0.1))
+trigger noise burst
+> let {n = brownNoise 'α' AR * 0.1
+>     ;x = mouseX' KR 1 2 Linear 0.1
+>     ;o = sinOsc KR x 0 * 0.2}
+> in audition (out 0 (inRange o (-0.15) 0.15 * n))
diff --git a/Help/UGen/Trigger/lastValue.help.lhs b/Help/UGen/Trigger/lastValue.help.lhs
--- a/Help/UGen/Trigger/lastValue.help.lhs
+++ b/Help/UGen/Trigger/lastValue.help.lhs
@@ -1,12 +1,12 @@
-lastValue in diff
-
-Output the last value before the input changed more than a threshhold.
+> Sound.SC3.UGen.Help.viewSC3Help "LastValue"
+> Sound.SC3.UGen.DB.ugenSummary "LastValue"
 
 > import Sound.SC3
 
-> let x = mouseX KR 100 400 Linear 0.1
+> let x = mouseX' KR 100 400 Linear 0.1
 > in audition (out 0 (sinOsc AR (lastValue x 40) 0 * 0.1))
 
-> let { x = mouseX KR 0.1 4 Linear 0.1
->     ; f = abs (lastValue x 0.5 - x) * 400 + 200 }
+Difference between currrent and the last changed
+> let {x = mouseX' KR 0.1 4 Linear 0.1
+>     ;f = abs (lastValue x 0.5 - x) * 400 + 200}
 > in audition (out 0 (sinOsc AR f 0 * 0.2))
diff --git a/Help/UGen/Trigger/mostChange.help.lhs b/Help/UGen/Trigger/mostChange.help.lhs
--- a/Help/UGen/Trigger/mostChange.help.lhs
+++ b/Help/UGen/Trigger/mostChange.help.lhs
@@ -1,10 +1,9 @@
-mostChange a b
-
-Output the input that changed most.
+> Sound.SC3.UGen.Help.viewSC3Help "MostChange"
+> Sound.SC3.UGen.DB.ugenSummary "MostChange"
 
 > import Sound.SC3.ID
 
-> let { n = lfNoise0 'α' KR 1
->     ; x = mouseX KR 200 300 Linear 0.1
->     ; f = mostChange (n * 400 + 900) x }
+> let {n = lfNoise0 'α' KR 1
+>     ;x = mouseX' KR 200 300 Linear 0.1
+>     ;f = mostChange (n * 400 + 900) x}
 > in audition (out 0 (sinOsc AR f 0 * 0.1))
diff --git a/Help/UGen/Trigger/peak.help.lhs b/Help/UGen/Trigger/peak.help.lhs
--- a/Help/UGen/Trigger/peak.help.lhs
+++ b/Help/UGen/Trigger/peak.help.lhs
@@ -1,11 +1,9 @@
-peak trig reset
-
-Outputs the maximum value read at the `trig' input until `reset' is
-triggered.
+> Sound.SC3.UGen.Help.viewSC3Help "Peak"
+> Sound.SC3.UGen.DB.ugenSummary "Peak"
 
 > import Sound.SC3.ID
 
-> let { t = dust 'α' AR 20
->     ; r = impulse AR 0.4 0
->     ; f = peak t r * 500 + 200 }
+> let {t = dust 'α' AR 20
+>     ;r = impulse AR 0.4 0
+>     ;f = peak t r * 500 + 200}
 > in audition (out 0 (sinOsc AR f 0 * 0.2))
diff --git a/Help/UGen/Trigger/phasor.help.lhs b/Help/UGen/Trigger/phasor.help.lhs
--- a/Help/UGen/Trigger/phasor.help.lhs
+++ b/Help/UGen/Trigger/phasor.help.lhs
@@ -1,23 +1,12 @@
-phasor rate trig rate start end resetPos
-
-Triggered linear ramp between two levels.  Starts a linear ramp
-when trig input crosses from non-positive to positive.
-
-trig       - sets phase to resetPos (default: 0, equivalent to start)
-rate       - rate value in 1 / frameDur (at 44.1 kHz sample rate: rate
-             1 is eqivalent to 44100/sec)
-start, end - start and end points of ramp
-resetPos   - determines where to jump to on recieving a trigger.  the
-             value at that position can be calculated as follows:
-             (end - start) * resetPos
-
-phasor controls sine frequency: end frequency matches a second sine wave.
+> Sound.SC3.UGen.Help.viewSC3Help "Phasor"
+> Sound.SC3.UGen.DB.ugenSummary "Phasor"
 
 > import Sound.SC3
 
-> let { rate = mouseX KR 0.2 2 Exponential 0.1
->     ; tr = impulse AR rate 0
->     ; sr = sampleRate
->     ; x = phasor AR tr (rate / sr) 0 1 0 
->     ; f = mce [linLin x 0 1 600 1000, 1000] }
+phasor controls sine frequency, end frequency matches second sine.
+> let {rate = mouseX' KR 0.2 2 Exponential 0.1
+>     ;tr = impulse AR rate 0
+>     ;sr = sampleRate
+>     ;x = phasor AR tr (rate / sr) 0 1 0
+>     ;f = mce [linLin x 0 1 600 1000, 1000]}
 > in audition (out 0 (sinOsc AR f 0 * 0.2))
diff --git a/Help/UGen/Trigger/pulseCount.help.lhs b/Help/UGen/Trigger/pulseCount.help.lhs
--- a/Help/UGen/Trigger/pulseCount.help.lhs
+++ b/Help/UGen/Trigger/pulseCount.help.lhs
@@ -1,7 +1,5 @@
-pulseCount trig reset
-
-This outputs the number of pulses received at `trig' and outputs
-that value until `reset' is triggered.
+> Sound.SC3.UGen.Help.viewSC3Help "PulseCount"
+> Sound.SC3.UGen.DB.ugenSummary "PulseCount"
 
 > import Sound.SC3
 
diff --git a/Help/UGen/Trigger/pulseDivider.help.lhs b/Help/UGen/Trigger/pulseDivider.help.lhs
--- a/Help/UGen/Trigger/pulseDivider.help.lhs
+++ b/Help/UGen/Trigger/pulseDivider.help.lhs
@@ -1,13 +1,10 @@
-pulseDivider trig div start
-
-Outputs one impulse each time it receives a certain number of triggers
-at its input.  A trigger happens when the signal changes from
-non-positive to positive.
+> Sound.SC3.UGen.Help.viewSC3Help "PulseDivider"
+> Sound.SC3.UGen.DB.ugenSummary "PulseDivider"
 
 > import Sound.SC3
 
-> let { p = impulse AR 8 0
->     ; d = pulseDivider p (mce [4,7]) 0
->     ; a = sinOsc AR 1200 0 * decay2 p 0.005 0.1
->     ; b = sinOsc AR 600  0 * decay2 d 0.005 0.5 }
+> let {p = impulse AR 8 0
+>     ;d = pulseDivider p (mce [4,7]) 0
+>     ;a = sinOsc AR 1200 0 * decay2 p 0.005 0.1
+>     ;b = sinOsc AR 600  0 * decay2 d 0.005 0.5}
 > in audition (out 0 (a + b * 0.4))
diff --git a/Help/UGen/Trigger/runningMax.help.lhs b/Help/UGen/Trigger/runningMax.help.lhs
--- a/Help/UGen/Trigger/runningMax.help.lhs
+++ b/Help/UGen/Trigger/runningMax.help.lhs
@@ -1,15 +1,14 @@
-runningMax in trig
-
-Track maximum level.  Outputs the maximum value received at the
-input.  When triggered, the maximum output value is reset to the
-current value.
-
-in   - input signal
-trig - reset the output value to the current input value
+> Sound.SC3.UGen.Help.viewSC3Help "RunningMax"
+> Sound.SC3.UGen.DB.ugenSummary "RunningMax"
 
 > import Sound.SC3.ID
 
-> let { n = dust 'α' AR 20
->     ; t = impulse AR 0.4 0
->     ; f = runningMax n t * 500 + 200 }
+> let {n = dust 'α' AR 20
+>     ;t = impulse AR 0.4 0
+>     ;f = runningMax n t * 500 + 200}
+> in audition (out 0 (sinOsc AR f 0 * 0.2))
+
+follow a sine lfo, reset rate controlled by mouse x
+> let {t = impulse KR (mouseX' KR 0.01 2 Linear 0.1) 0
+>     ;f = runningMax (sinOsc KR 0.2 0) t * 500 + 200}
 > in audition (out 0 (sinOsc AR f 0 * 0.2))
diff --git a/Help/UGen/Trigger/runningMin.help.lhs b/Help/UGen/Trigger/runningMin.help.lhs
--- a/Help/UGen/Trigger/runningMin.help.lhs
+++ b/Help/UGen/Trigger/runningMin.help.lhs
@@ -1,23 +1,16 @@
-runningMin in trig
-
-Track maximum level.  Outputs the maximum value received at the
-input.  When triggered, the maximum output value is reset to the
-current value.
-
-in   - input signal
-trig - reset the output value to the current input value
+> Sound.SC3.UGen.Help.viewSC3Help "RunningMin"
+> Sound.SC3.UGen.DB.ugenSummary "RunningMin"
 
-> import Sound.SC3
+> import Sound.SC3.ID
 
-> let { o = sinOsc KR 2 0
->     ; x = mouseX KR 0.01 10 Exponential 0.1
->     ; t = impulse AR x 0 
->     ; f = runningMin o t * 500 + 200 }
+Follow a sine lfo, reset rate controlled by mouseX
+> let {o = sinOsc KR 2 0
+>     ;x = mouseX' KR 0.01 10 Exponential 0.1
+>     ;t = impulse AR x 0
+>     ;f = runningMin o t * 500 + 200 }
 > in audition (out 0 (sinOsc AR f 0 * 0.2))
 
-> import Sound.SC3.ID
-
-> let { n = dust 'α' AR 20
->     ; t = impulse AR 0.4 0
->     ; f = runningMin n t * 500 + 200 }
+> let {n = dust 'α' AR 20
+>     ;t = impulse AR 0.4 0
+>     ;f = runningMin n t * 500 + 200}
 > in audition (out 0 (sinOsc AR f 0 * 0.2))
diff --git a/Help/UGen/Trigger/sendReply.help.lhs b/Help/UGen/Trigger/sendReply.help.lhs
--- a/Help/UGen/Trigger/sendReply.help.lhs
+++ b/Help/UGen/Trigger/sendReply.help.lhs
@@ -1,31 +1,16 @@
-sendReply in replyID cmdName values
-
-On receiving a trigger (0 to non-zero transition), send a trigger
-message from the server back to all registered clients.  Clients
-register by sending a /notify message to the server.
-
-in      - the trigger
-
-replyId - an integer that will be passed with the 
-          trigger message.  This is useful if you
-          have more than one SendReply in a SynthDef
-
-cmdName - the name of the reply command to send
-
-values  - a list of UGen or float values will be polled 
-          at the time of trigger, and returned with the 
-          trigger message
+> Sound.SC3.UGen.Help.viewSC3Help "SendReply"
+> Sound.SC3.UGen.DB.ugenSummary "SendReply"
 
 > import Sound.SC3.ID
 
-> let { s0 = lfNoise0 'a' KR 5
->     ; s1 = lfNoise0 'b' KR 5
->     ; o = sinOsc AR (s0 * 200 + 500) 0 * s1 * 0.1 }
-> in audition (mrg [sendReply s0 0 "/s-reply" [s0, s1], out 0 o])
+> let {s0 = lfNoise0 'a' KR 5
+>     ;s1 = lfNoise0 'b' KR 5
+>     ;o = sinOsc AR (s0 * 200 + 500) 0 * s1 * 0.1}
+> in audition (mrg [sendReply s0 0 "/s-reply" [s0,s1],out 0 o])
 
 > import Sound.OpenSoundControl
 
-> withSC3 (\fd -> do { async fd (notify True)
->                    ; r <- wait fd "/s-reply"
->                    ; putStrLn (show r)
->                    ; async fd (notify False) })
+> withSC3 (\fd -> do {async fd (notify True)
+>                    ;r <- wait fd "/s-reply"
+>                    ;putStrLn (show r)
+>                    ;async fd (notify False)})
diff --git a/Help/UGen/Trigger/sendTrig.help.lhs b/Help/UGen/Trigger/sendTrig.help.lhs
--- a/Help/UGen/Trigger/sendTrig.help.lhs
+++ b/Help/UGen/Trigger/sendTrig.help.lhs
@@ -1,26 +1,16 @@
-sendTrig in id value
-
-On receiving a trigger (0 to non-zero transition), send a trigger
-message from the server back to all registered clients.  Clients
-register by sending a /notify message to the server.
-
-input - the trigger
-
-id    - an integer that will be passed with the trigger message.  This
-  	is useful if you have more than one SendTrig in a SynthDef
-
-value - a UGen or float that will be polled at the time of trigger,
-        and its value passed with the trigger message
+> Sound.SC3.UGen.Help.viewSC3Help "SendTrig"
+> Sound.SC3.UGen.DB.ugenSummary "SendTrig"
 
 > import Sound.SC3.ID
 
-> let { s = lfNoise0 'α' KR 5
->     ; o = sinOsc AR (s * 200 + 500) 0 * 0.1 }
-> in audition (mrg [sendTrig s 0 s, out 0 o])
+> let {s = lfNoise0 'α' KR 5
+>     ;o = sinOsc AR (s * 200 + 500) 0 * 0.1}
+> in audition (mrg [sendTrig s 0 s,out 0 o])
 
 > import Sound.OpenSoundControl
 
-> withSC3 (\fd -> do { async fd (notify True)
->                    ; tr <- wait fd "/tr"
->                    ; putStrLn (show tr)
->                    ; async fd (notify False) })
+Retrieve a single message
+> withSC3 (\fd -> do {_ <- async fd (notify True)
+>                    ;tr <- wait fd "/tr"
+>                    ;putStrLn (show tr)
+>                    ;async fd (notify False)})
diff --git a/Help/UGen/Trigger/setResetFF.help.lhs b/Help/UGen/Trigger/setResetFF.help.lhs
--- a/Help/UGen/Trigger/setResetFF.help.lhs
+++ b/Help/UGen/Trigger/setResetFF.help.lhs
@@ -1,17 +1,10 @@
-setResetFF trig reset
-
-Set-reset flip flop.  Output is set to 1.0 upon receiving a trigger
-in the set input, and to 0.0 upon receiving a trigger in the reset
-input. Once the flip flop is set to zero or one further triggers in
-the same input are have no effect. One use of this is to have some
-precipitating event cause something to happen until you reset it.
-
-trig  - trigger sets output to one
-reset - trigger resets output to zero
+> Sound.SC3.UGen.Help.viewSC3Help "SetResetFF"
+> Sound.SC3.UGen.DB.ugenSummary "SetResetFF"
 
 > import Sound.SC3.ID
 
-> let { n = brownNoise 'α' AR
->     ; d0 = dust 'α' AR 5
->     ; d1 = dust 'β' AR 5 }
+d0 is the set trigger, d1 the reset trigger
+> let {n = brownNoise 'α' AR
+>     ;d0 = dust 'α' AR 5
+>     ;d1 = dust 'β' AR 5}
 > in audition (out 0 (setResetFF d0 d1 * n * 0.2))
diff --git a/Help/UGen/Trigger/stepper.help.lhs b/Help/UGen/Trigger/stepper.help.lhs
--- a/Help/UGen/Trigger/stepper.help.lhs
+++ b/Help/UGen/Trigger/stepper.help.lhs
@@ -1,57 +1,41 @@
-stepper trig reset min max step resetval
-
-Stepper pulse counter.  Each trigger increments a counter which is
-output as a signal. The counter wraps between min and max.
-
-    trig - trigger. Trigger can be any signal. A trigger happens when
-           the signal changes from non-positive to positive.
-
-   reset - resets the counter to resetval when triggered.
-
-     min - minimum value of the counter.
-
-     max - maximum value of the counter.
-
-    step - step value each trigger. May be negative.
-
-resetval - value to which the counter is reset when it receives a
-           reset trigger. If nil, then this is patched to min.
+> Sound.SC3.UGen.Help.viewSC3Help "Stepper"
+> Sound.SC3.UGen.DB.ugenSummary "Stepper"
 
-> import Sound.SC3
+> import Sound.SC3.ID
 
-> let { i = impulse KR 10 0
->     ; f = stepper i 0 4 16 (-3) 4 * 100 }
+> let {i = impulse KR 10 0
+>     ;f = stepper i 0 4 16 (-3) 4 * 100}
 > in audition (out 0 (sinOsc AR f 0 * 0.1))
 
-> import System.Random
-
-> let { compose = foldl (flip (.)) id
->     ; noisec n l r = randomRs (l,r) (mkStdGen n)
->     ; rvb s r0 r1 r2 = let f dl1 dl2 dc i = allpassN i 0.05 (mce [dl1,dl2]) dc
->                        in compose (take 5 (zipWith3 f r0 r1 r2)) s
->     ; rvb' s = rvb s (noisec 0 0 0.05) (noisec 1 0 0.05) (noisec 2 1.5 2.0)
->     ; stpr = let { rate = mouseX KR 1 5 Exponential 0.1
->                  ; clock = impulse KR rate 0
->                  ; envl = decay2 clock 0.002 2.5
->                  ; indx = stepper clock 0 0 15 1 0
->                  ; freq = bufRdN 1 KR 10 indx Loop
->                  ; ffreq = lag2 freq 0.1 + mce [0, 0.3]
->                  ; lfo = sinOsc KR 0.2 (mce [0, pi/2]) * 0.0024 + 0.0025
->                  ; top = mix (lfPulse AR (freq * mce [1, 1.5, 2]) 0 0.3)
->                  ; chn = [ \s -> rlpf s ffreq 0.3 * envl
->                          , \s -> rlpf s ffreq 0.3 * envl
->                          , \s -> s * 0.5
->                          , \s -> combL s 1 (0.66 / rate) 2 * 0.8 + s
->                          , \s -> s + (rvb' s * 0.3)
->                          , \s -> leakDC s 0.1
->                          , \s -> delayL s 0.1 lfo + s
->                          , \s -> onePole s 0.9 ] }
->       in compose chn top
->     ; stprInit fd = let n = [ 97.999, 195.998, 523.251, 466.164, 195.998
->                             , 233.082, 87.307, 391.995, 87.307, 261.626
->                             , 195.998, 77.782, 233.082, 195.998, 97.999
->                             , 155.563]
->                     in do { async fd (b_alloc 10 128 1)
->                           ; send fd (b_setn 10 [(0, n)]) } }
-> in withSC3 (\fd -> do { stprInit fd
->                       ; audition (out 0 stpr) })
+Using Stepper and BufRd for sequencing
+> let {compose = foldl (flip (.)) id
+>     ;rvb s =
+>         let f i = let dly = mce [rand (i//'a') 0 0.5,rand (i//'b') 0 0.5]
+>                   in allpassN i 0.05 dly (rand i 1.5 2)
+>         in compose (replicate 5 f) s
+>     ;stpr = let {rate = mouseX' KR 2 2.01 Exponential 0.1
+>                 ;clock = impulse KR rate 0
+>                 ;envl = decay2 clock 0.002 2.5
+>                 ;indx = stepper clock 0 0 15 1 0
+>                 ;freq = bufRdN 1 KR 10 indx Loop
+>                 ;ffreq = lag2 freq 0.1 + mce [0,0.3]
+>                 ;lfo = sinOsc KR 0.2 (mce [0,pi/2]) * 0.0024 + 0.0025
+>                 ;top = mix (lfPulse AR (freq * mce [1,1.5,2]) 0 0.3)
+>                 ;chn = [\s -> rlpf s ffreq 0.3 * envl
+>                        ,\s -> rlpf s ffreq 0.3 * envl
+>                        ,\s -> s * 0.5
+>                        ,\s -> combL s 1 (0.66 / rate) 2 * 0.8 + s
+>                        ,\s -> s + (rvb s * 0.3)
+>                        ,\s -> leakDC s 0.1
+>                        ,\s -> delayL s 0.1 lfo + s
+>                        ,\s -> onePole s 0.9]}
+>             in compose chn top
+>     ;stprInit fd =
+>      let n = [97.999,195.998,523.251,466.164,195.998
+>              ,233.082,87.307,391.995,87.307,261.626
+>              ,195.998,77.782,233.082,195.998,97.999
+>              ,155.563]
+>      in do {_ <- async fd (b_alloc 10 128 1)
+>            ;send fd (b_setn 10 [(0,n)])}}
+> in withSC3 (\fd -> do {stprInit fd
+>                       ;audition (out 0 stpr)})
diff --git a/Help/UGen/Trigger/sweep.help.lhs b/Help/UGen/Trigger/sweep.help.lhs
--- a/Help/UGen/Trigger/sweep.help.lhs
+++ b/Help/UGen/Trigger/sweep.help.lhs
@@ -1,42 +1,35 @@
-sweep trig rate
-
-Triggered linear ramp.  Starts a linear raise by rate/sec from zero
-when trig input crosses from non-positive to positive.
-	
-Using sweep to modulate sine frequency
+> Sound.SC3.UGen.Help.viewSC3Help "Sweep"
+> Sound.SC3.UGen.DB.ugenSummary "Sweep"
 
-> import Sound.SC3
+> import Sound.SC3.ID
 
-> let { x = mouseX KR 0.5 20 Exponential 0.1
->     ; t = impulse KR x 0 
->     ; f = sweep t 700 + 500 }
+Using sweep to modulate sine frequency
+> let {x = mouseX' KR 0.5 20 Exponential 0.1
+>     ;t = impulse KR x 0
+>     ;f = sweep t 700 + 500}
 > in audition (out 0 (sinOsc AR f 0 * 0.2))
 
-Using sweep to index into a buffer
-
-> let fn = "/home/rohan/audio/metal.wav"
+Load audio to buffer
+> let fn = "/home/rohan/data/audio/pf-c5.aif"
 > in withSC3 (\fd -> send fd (b_allocRead 0 fn 0 0))
 
-> let { x = mouseX KR 0.5 20 Exponential 0.1
->     ; t = impulse AR x 0
->     ; p = sweep t (bufSampleRate KR 0) }
+Using sweep to index into a buffer
+> let {x = mouseX' KR 0.5 20 Exponential 0.1
+>     ;t = impulse AR x 0
+>     ;p = sweep t (bufSampleRate KR 0)}
 > in audition (out 0 (bufRdL 1 AR 0 p NoLoop))
 
 Backwards, variable offset
-
-> import Sound.SC3.ID
-
-> let { n = lfNoise0 'a' KR 15
->     ; x = mouseX KR 0.5 10 Exponential 0.1
->     ; t = impulse AR x 0
->     ; r = bufSampleRate KR 0
->     ; p = sweep t (negate r) + (bufFrames KR 0 * n) }
+> let {n = lfNoise0 'a' KR 15
+>     ;x = mouseX' KR 0.5 10 Exponential 0.1
+>     ;t = impulse AR x 0
+>     ;r = bufSampleRate KR 0
+>     ;p = sweep t (negate r) + (bufFrames KR 0 * n)}
 > in audition (out 0 (bufRdL 1 AR 0 p NoLoop))
 
 Raising rate
-
-> let { x = mouseX KR 0.5 10 Exponential 0.1
->     ; t = impulse AR x 0
->     ; r = sweep t 2 + 0.5
->     ; p = sweep t (bufSampleRate KR 0 * r) }
+> let {x = mouseX' KR 0.5 10 Exponential 0.1
+>     ;t = impulse AR x 0
+>     ;r = sweep t 2 + 0.5
+>     ;p = sweep t (bufSampleRate KR 0 * r)}
 > in audition (out 0 (bufRdL 1 AR 0 p NoLoop))
diff --git a/Help/UGen/Trigger/tDelay.help.lhs b/Help/UGen/Trigger/tDelay.help.lhs
--- a/Help/UGen/Trigger/tDelay.help.lhs
+++ b/Help/UGen/Trigger/tDelay.help.lhs
@@ -1,14 +1,9 @@
-tDelay trigger delayTime
-
-Delays a trigger by a given time. Any triggers which arrive in the
-time between an input trigger and its delayed output, are ignored.
-
-trigger   - input trigger signal.
-delayTime - delay time in seconds.
+> Sound.SC3.UGen.Help.viewSC3Help "TDelay"
+> Sound.SC3.UGen.DB.ugenSummary "TDelay"
 
 > import Sound.SC3
 
-> let { z = impulse AR 2 0
->     ; z' = tDelay z 0.5 
->     ; o = sinOsc AR 440 0 * 0.1 }
-> in audition (out 0 (mce [z * 0.1, toggleFF z' * o]))
+> let {z = impulse AR 2 0
+>     ;z' = tDelay z 0.5
+>     ;o = sinOsc AR 440 0 * 0.1}
+> in audition (out 0 (mce [z * 0.1,toggleFF z' * o]))
diff --git a/Help/UGen/Trigger/timer.help.lhs b/Help/UGen/Trigger/timer.help.lhs
--- a/Help/UGen/Trigger/timer.help.lhs
+++ b/Help/UGen/Trigger/timer.help.lhs
@@ -1,11 +1,7 @@
-timer trig
-
-Returns time since last triggered
-	
-Using timer to modulate sine frequency: the slower the trigger is
-the higher the frequency
+> Sound.SC3.UGen.Help.viewSC3Help "Timer"
+> Sound.SC3.UGen.DB.ugenSummary "Timer"
 
 > import Sound.SC3
 
-> let t = impulse KR (mouseX KR 0.5 20 Exponential 0.1) 0
+> let t = impulse KR (mouseX' KR 0.5 20 Exponential 0.1) 0
 > in audition (out 0 (sinOsc AR (timer t * 500 + 500) 0 * 0.2))
diff --git a/Help/UGen/Trigger/toggleFF.help.lhs b/Help/UGen/Trigger/toggleFF.help.lhs
--- a/Help/UGen/Trigger/toggleFF.help.lhs
+++ b/Help/UGen/Trigger/toggleFF.help.lhs
@@ -1,12 +1,8 @@
-toggleFF trig
-
-Toggle flip flop. Toggles between zero and one upon receiving a
-trigger.
-
-trig - trigger input
+> Sound.SC3.UGen.Help.viewSC3Help "ToggleFF"
+> Sound.SC3.UGen.DB.ugenSummary "ToggleFF"
 
 > import Sound.SC3.ID
 
-> let { t = dust 'a' AR (xLine KR 1 1000 60 DoNothing)
->     ; t' = toggleFF t * 400 + 800 }
+> let {t = dust 'a' AR (xLine KR 1 1000 60 DoNothing)
+>     ;t' = toggleFF t * 400 + 800}
 > in audition (out 0 (sinOsc AR t' 0 * 0.1))
diff --git a/Help/UGen/Trigger/trig.help.lhs b/Help/UGen/Trigger/trig.help.lhs
--- a/Help/UGen/Trigger/trig.help.lhs
+++ b/Help/UGen/Trigger/trig.help.lhs
@@ -1,9 +1,8 @@
-trig in dur
-
-When `in' is trigerred output the trigger value for `dur' seconds.
+> Sound.SC3.UGen.Help.viewSC3Help "Trig"
+> Sound.SC3.UGen.DB.ugenSummary "Trig"
 
 > import Sound.SC3.ID
 
-> let { d = dust 'a' AR 1
->     ; o = fSinOsc AR 800 0 * 0.5 }
+> let {d = dust 'a' AR 1
+>     ;o = fSinOsc AR 800 0 * 0.5}
 > in audition (out 0 (trig d 0.2 * o))
diff --git a/Help/UGen/Trigger/trig1.help.lhs b/Help/UGen/Trigger/trig1.help.lhs
--- a/Help/UGen/Trigger/trig1.help.lhs
+++ b/Help/UGen/Trigger/trig1.help.lhs
@@ -1,6 +1,5 @@
-trig1 in dur
-
-When `in' is trigered output a unit signal for `dur' seconds.
+> Sound.SC3.UGen.Help.viewSC3Help "Trig1"
+> Sound.SC3.UGen.DB.ugenSummary "Trig1"
 
 > import Sound.SC3.ID
 
diff --git a/Help/UGen/Wavelets/dwt.help.lhs b/Help/UGen/Wavelets/dwt.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Wavelets/dwt.help.lhs
@@ -0,0 +1,3 @@
+> Sound.SC3.UGen.Help.viewSC3Help "DWT"
+> Sound.SC3.UGen.DB.ugenSummary "DWT"
+
diff --git a/Help/UGen/Wavelets/idwt.help.lhs b/Help/UGen/Wavelets/idwt.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Wavelets/idwt.help.lhs
@@ -0,0 +1,33 @@
+> Sound.SC3.UGen.Help.viewSC3Help "IDWT"
+> Sound.SC3.UGen.DB.ugenSummary "IDWT"
+
+> import Sound.SC3.ID
+
+> let {i = whiteNoise 'a' AR * 0.05
+>     ;b = mrg2 (localBuf 'α' 1024 1) (maxLocalBufs 1)
+>     ;c = dwt b i 0.5 0 1 0 0}
+> in audition (out 0 (mce2 (idwt c 0 0 0) i))
+
+direct synthesis via writing values to buffer (try changing wavelet
+type...)
+> withSC3 (\fd -> do {_ <- async fd (b_alloc 10 1024 1)
+>                    ;send fd (b_zero 10)})
+
+> let {c = fftTrigger 10 0.5 0
+>     ;i = idwt c (-1) 0 0}
+> in audition (out 0 (i * 0.1))
+
+> import Control.Monad.Random
+> import Sound.SC3.Lang.Random.Monad
+
+> withSC3 (\fd -> send fd (b_zero 10))
+
+run this to change sound: WARNING, NOISY!
+> do {a <- evalRandIO (nrrand 1024 (-1) 1)
+>    ;withSC3 (\fd -> send fd (b_setn 10 [(0,a)]))}
+
+> let a = map (/ 1024) [0..1023]
+> in withSC3 (\fd -> send fd (b_setn 10 [(0,a)]))
+
+> let a = map (\i -> 1 - i / 1024) [0..1023]
+> in withSC3 (\fd -> send fd (b_setn 10 [(0,a)]))
diff --git a/Help/UGen/Wavelets/wt_FilterScale.help.lhs b/Help/UGen/Wavelets/wt_FilterScale.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Wavelets/wt_FilterScale.help.lhs
@@ -0,0 +1,11 @@
+> Sound.SC3.UGen.Help.viewSC3Help "WT_FilterScale"
+> Sound.SC3.UGen.DB.ugenSummary "WT_FilterScale"
+
+> import Sound.SC3.ID
+
+> let {i = whiteNoise 'α' AR * 0.2
+>     ;b = mrg2 (localBuf 'α' 2048 1) (maxLocalBufs 1)
+>     ;c = dwt b i 0.5 0 1 0 0
+>     ;x = mouseX' KR (-1) 1 Linear 0.1
+>     ;c' = wt_FilterScale c x}
+> in audition (out 0 (pan2 (idwt c' 0 0 0) x 1))
diff --git a/Help/UGen/Wavelets/wt_TimeWipe.help.lhs b/Help/UGen/Wavelets/wt_TimeWipe.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Wavelets/wt_TimeWipe.help.lhs
@@ -0,0 +1,11 @@
+> Sound.SC3.UGen.Help.viewSC3Help "WT_TimeWipe"
+> Sound.SC3.UGen.DB.ugenSummary "WT_TimeWipe"
+
+> import Sound.SC3.ID
+
+> let {i = whiteNoise 'α' AR * 0.2
+>     ;b = mrg2 (localBuf 'α' 2048 1) (maxLocalBufs 1)
+>     ;c = dwt b i 0.5 0 1 0 0
+>     ;x = mouseX' KR 0 1 Linear 0.1
+>     ;c' = wt_TimeWipe c x}
+> in audition (out 0 (pan2 (idwt c' 0 0 0) (x * 2 - 1) 1))
diff --git a/Help/hsc3.help.lhs b/Help/hsc3.help.lhs
deleted file mode 100644
--- a/Help/hsc3.help.lhs
+++ /dev/null
@@ -1,656 +0,0 @@
-* Abstract
-
-This document describes the hsc3 haskell
-bindings to the supercollider synthesis
-server.
-
-The bindings allow haskell to be used
-to write unit generator graphs, to control
-the supercollider synthesiser interactively
-while it is running, and to write scores for
-offline rendering.
-
-For detailed introductory materials on
-haskell and supercollider, see
-
-  http://haskell.org/
-  http://audiosynth.com/
-
-* Questions, Dartmouth, 2002
-
-| What should a computer music language do?
-| ...
-| Is a specialized computer music language
-| even necessary? (McCartney, 2002)
-
-These questions are asked in a paper that
-documents a reimplementation of the supercollider
-language for real time audio synthesis (McCartney,
-1998).
-
-The redesigned system consists of two parts, an
-elegant, efficient, and musically neutral real
-time audio synthesiser in the music-n family
-(Mathews, 1961), and a language interpreter in the
-smalltalk family (Goldberg, 1983).
-
-The interpreter and synthesiser communicate using
-the open sound control protocol (Wright & Freed,
-1997).
-
-Using this model of discrete communicating
-processes, the computer music language is relieved
-of many onerous tasks.
-
-In part the question is rhetorical, given an
-appropriately designed and implemented
-synthesiser, the control language need not be
-particularly specialised.
-
-* What needs to be done
-
-The requirements are rather minimal.
-
-An open sound control protocol implementation and
-a usable notation for server commands.
-
-A unit generator graph protocol implementation and
-a usable notation for writing graphs.
-
-For interactive use a suitably responsive run time
-system, where suitable is a function of the kind
-of work being done.
-
-* Questions, San Dimas, 1965
-
-| (1) What are declarative languages?
-| ...
-| (4) How can we use them to program?
-| (5) How can we implement them?
-| (Strachey, in Landin, 1966)
-
-(1) Haskell is a non-strict (Wadler, 1996) and
-    purely functional (Sabry, 1993) language, one
-    result of many years of research into these
-    questions (Hudak et al, 2007).
-
-(4) Computation in haskell is structured using a
-    small number of simple type classes; monads
-    (Wadler, 1990), applicative functors (McBride
-    and Paterson, 2007) & arrows (Hughes, 2000).
-
-(5) The glasgow haskell system includes both an
-    optimizing compiler generating efficient
-    machine programs and a bytecode generator and
-    intepreter for interative use.
-
-In the authors experience the glasgow run-time
-system is adequate for real-time control of the
-supercollider synthesiser, capable of generating
-high density & low latency control streams such as
-those required for waveset synthesis etc.
-
-* Types, Unit Generators, Parametric Polymorphism
-
-In haskell polymorphism is provided by type
-classes (Wadler & Blott, 1989).
-
-Type class polymorphism is parametric, as distinct
-from the ad hoc polymorphism of supercollider
-language (Strachey, 1967).
-
-Since unit generators are a sort of numerical
-value, we wish to make their representation
-amenable to the standard haskell numerical type
-classes.
-
-These give signatures such as:
-
-> (+) :: (Num a) => a -> a -> a
-
-meaning that a value can only be summed with a
-value of the same type, and that the resulting
-value must also be of the same type.
-
-This implies that the type of a unit generator
-must be inclusive, since we wish to combine
-constants, control inputs, and actual unit
-generators operating at varying rates and with
-varying numbers of input and output ports.
-
-This leads us to a representation that is simple
-but somewhat uninformative, and delays evaluating
-unit generator graph correctness to run-time.
-
-We note that a more rigorous type representation
-is possible, either in standard haskell or using
-one of the many implemented type system
-extensions, and could be layered either above or
-below the current representation.
-
-* Multiple channel expansion
-
-The supercollider language implements a very
-elegant rule for composing graphs from nodes with
-different numbers of channels.  The model is
-referred to as multiple channel expansion, a
-behaviour that, although it can become confusing
-in deeply nested uses, is very intuitive for
-simple cases.
-
-The simple type representation of unit generators
-allows us to implement the multiple channel
-expansion model in much the same way as in the
-supercollider language
-
-Unit generators with multiple outputs, such
-as pan2, are represented as a specific kind
-of unit generator value, an ordered set of
-proxies.
-
-We can also write these sets directly using
-the 'mce' function.
-
-Multiple channel expansion flows downward
-through unit generator graphs.
-
-In the expression below, the frequency input
-causes two sinOsc unit generators to be created.
-
-> import Sound.SC3
-
-> let { x = mouseX KR (-1) 1 Linear 0.1
->     ; o1 = pulse AR 440 0.1
->     ; o2 = sinOsc AR (mce [110, 2300]) 0 * 0.1 }
-> in audition (out 0 (pan2 o1 x 0.1 + o2))
-
-This is turn causes the (*) function to
-expand and perform channel matching, that is
-to duplicate the right hand side input as
-required.
-
-The (+) function is also expanded, since the
-left and right hand sides are of equal degree
-there is not replication of inputs.
-
-The out function does not expand, since it is
-defined to flatten one layer of mce values at
-it's second input to support a variable number
-of input channels; it would however expand on
-mce at the first argument, or nested mce at the
-second.
-
-Equal inputs do also push the expansion
-downwards, however in complex graphs this
-seems occasionally unreliable.
-
-> let f = mce2 440 440
-> in audition (out 0 (sinOsc AR f 0 * 0.1))
-
-* Multiply add inputs, Haskell Curry, and cloning
-
-The supercollider language provides optional multiply
-and add inputs for most unit generator constructors.
-
-Optional arguments do not interact well with the
-haskell behaviour of treating functions as monadic.
-
-That is, one way to write the number thirteen is:
-
-> let { sum_squares x y = x * x + y * y
->     ; f = sum_squares 2 }
-> in f 3
-
-The absent multiply add inputs can in most cases be
-simply re-written using (*) and (+).
-
-The expression:
-
-| { Out.ar(0, SinOsc.ar(440, 0, 0.1, 0.05)) }.play
-
-is equivalent to:
-
-> audition (out 0 (sinOsc AR 440 0 * 0.1 + 0.05))
-
-However there is a subtle distinction in behaviour
-relating to multiple channel expansion.
-
-The supercollider language expression:
-
-| { var a = WhiteNoise.ar([0.1, 0.05])
-| ; var b = PinkNoise.ar * [0.1, 0.05]
-| ; Out.ar(0, a + b) }.play
-
-describes a graph with two WhiteNoise nodes
-and a single PinkNoise node.
-
-We note that this distinction is only relevant
-for non-deterministic unit generators.
-
-To write this simple graph in haskell we can use
-the clone function:
-
-> import Control.Monad
-> import Sound.SC3.Monadic
-
-> let f = liftM (* mce [0.1, 0.05])
-> in do { a <- f (clone 2 (whiteNoise AR))
->       ; b <- f (pinkNoise AR)
->       ; audition (out 0 (a + b)) }
-
-which is defined in relation to the standard
-monad functions replicateM and liftM.
-
-> clone :: (UId m) => Int -> m UGen -> m UGen
-> clone n u = liftM mce (replicateM n u)
-
-* Multiple Root Graphs
-
-The mrg function, pronounced multiple root graph,
-allows us to write unit generator graphs with
-multiple sink nodes.
-
-Consider the freeSelf unit generator:
-
-> do { n <- dust KR 0.5
->    ; let { a = freeSelf n
->          ; b = out 0 (sinOsc AR 440 0 * 0.1) }
->      in audition (mrg [a, b]) }
-
-In order to allow multiple root graphs to be
-freely composed we implement a leftmost rule,
-whereby the leftmost root need not be a sink
-node, in which case the mrg node may be used
-as an input node.
-
-Consider a simple ping pong delay filter:
-
-> let ppd s = let { a = localIn 2 AR + mce [s, 0]
->                 ; b = delayN a 0.2 0.2
->                 ; c = mceEdit reverse b * 0.8 }
->             in mrg [b, localOut c]
-> in do { n <- whiteNoise AR
->       ; let s = decay (impulse AR 0.3 0) 0.1 * n * 0.2
->         in audition (out 0 (ppd s)) }
-
-* Literals, Overloading, Coercion, Constants
-
-This is a somewhat subtle distinction.  Numeric
-literals in haskell are overloaded, not coerced.
-The numerical type classes provide two functions:
-
-> fromInteger :: (Num a) => Integer -> a
-
-and
-
-> fromRational :: (Fractional a) => Rational -> a
-
-which are implicitly applied to all integer and
-rational literals respectively.
-
-It is for this reason that we can write:
-
-> sinOsc AR 440.0 0 * 0.1
-
-but must explicitly construct constants from values
-of a concrete numerical type using the constant
-function.
-
-> let { f = 440.0 :: Double
->     ; p = 0 :: Int
->     ; a = 0.1 :: Float }
-> in sinOsc AR (constant f) (constant p) * (constant a)
-
-The most common case requiring constant annotations
-is buffer numbers, which must be provided to unit
-generator graphs as values of type 'UGen' and to
-the server command constructors as values of type
-'Int'.
-
-* Unit generators are comparable
-
-In haskell the Eq and Ord type classes define
-equality and ordering operators.
-
-In unit generator graphs these operators have a
-somewhat different meaning, and require a different
-type signature.
-
-For instance the greater-than operator defines a
-unit generator that is zero for sample values
-where the comparison fails, and one when it
-succeeds.
-
-Since the Ord type gives the signature:
-
-> (>) :: (Ord a) => a -> a -> Bool
-
-we define a variant with a star suffix, such
-that:
-
-> let { x = mouseX KR 3 45 Exponential 0.1
->     ; t = sinOsc AR x 0 >* 0
->     ; d = envTriangle 0.01 0.1
->     ; e = envGen AR t 1 0 1 DoNothing d
->     ; f = 220 + 880 * (toggleFF t)
->     ; o = sinOsc AR f 0 }
-> in audition (out 0 (o * e))
-
-is a sequence of low and high tones.
-
-For functions where the signature is
-consistent with the meaning of the unit
-generator operator we use the haskell name.
-
-| max :: (Ord a) => a -> a -> a
-
-> let { l = fSinOsc AR 500 0 * 0.25
->     ; r = fSinOsc AR 0.5 0 * 0.23 }
-> in audition (out 0 (l `max` r))
-
-* Observable Sharing, Pure Noise
-
-The haskell expression:
-
-> let { a = sinOsc AR 440 0
->     ; b = sinOsc AR 440 0
->     ; c = a - b }
-> in audition (out 0 c)
-
-denotes a graph that has three nodes: sinOsc, (-)
-and out.
-
-  # UGens                     Int 3
-  # Synths                    Int 1
-
-The graph constructor, when traversing the
-structure denoted by (out 0 c), cannot distinguish
-between a and b, they are the same value.
-
-In other words, it is the same graph as if we had
-written:
-
-> let { x = sinOsc AR 440 0
->     ; y = x - x }
-> in audition (out 0 y)
-
-Expressions with the same notation have the same
-value.
-
-This is acceptable for deterministic unit
-generators, such as sinOsc, but of course fails
-for non-deterministic unit generators such as
-whiteNoise, and also for demand rate sources
-such as dseq.
-
-In supercollider language, the graph
-
-| { var a = WhiteNoise.ar
-| ; var b = WhiteNoise.ar
-| ; var c = a - b
-| ; Out.ar(0, c * 0.1) }.play
-
-does not describe silence, it describes white
-noise.
-
-We read WhiteNoise.ar as a computation that
-constructs a value, not as an expression that
-denotes a value.
-
-In procedural languages we are familiar with many
-different types of equality.  Scheme has eq?, eqv?
-and equal?, supercollider language has == and ===.
-
-| { var a = "x"
-| ; var b = "x"
-| ; [a == b, a === b] }.value
-
-In a purely functional language expressions denote
-values, and equal expressions denote the same
-value.  Therefore the graph given by the haskell
-expression:
-
-> let { z = 'α'
->     ; n = Sound.SC3.UGen.Noise.ID.whiteNoise z
->     ; a = n AR
->     ; b = n AR
->     ; c = a - b }
-> in audition (out 0 (c * 0.1))
-
-describes silence.  To describe white noise we
-would need to distinguish a and b, which can only
-be done by providing non-equal identifiers in
-place of z.
-
-The whiteNoise function used above is written
-using a fully qualified name because it is not the
-whiteNoise function provided by Sound.SC3, that
-function has the signature:
-
-> whiteNoise :: (UId m) => Rate -> m UGen
-
-where the type-class UId is defined as:
-
-> class (Monad m) => UId m where
->     generateUId :: m Int
-
-The signature indicates that whiteNoise is a
-function from a Rate value to an (m UGen)
-value.
-
-* Non-determinism, monadic structure, do notation
-
-It is quite clear that a value of type (m UGen) is
-not of type UGen.
-
-Compare the whiteNoise signature with that of the
-deterministic sin oscillator:
-
-> sinOsc :: Rate -> UGen -> UGen -> UGen
-
-We can write a white noise graph using this
-function and the haskell 'do' notation as:
-
-> do { a <- whiteNoise AR
->    ; b <- whiteNoise AR
->    ; let c = a - b
->      in audition (out 0 (c * 0.1)) }
-
-which brings us more or less to the supercollider
-language notation, with the exception that there
-are two distinct binding notations, one for
-computations and one for expressions.
-
-The type system does not allow us to confuse these
-two bindings.
-
-The do notation allows us to write expressions
-that involve computations using a familiar and
-readable right to left binding notation.
-
-The above expression is equal to:
-
-> whiteNoise AR >>= \a ->
-> whiteNoise AR >>= \b ->
-> let c = a - b
-> in audition (out 0 (c * 0.1))
-
-where (>>=) is the monadic bind function, and (\x
--> y) is the notation for lambda expressions
-(ie. for function definition, ie. {|x| y} in
-supercollider language).  The signature for bind is:
-
-> (>>=) :: (Monad m) => m a -> (a -> m b) -> m b
-
-which indicates that the value bound in the
-function definition can only be accessed in a
-function that produces a value in the same monad.
-
-The audition function has an appropriate
-signature:
-
-> audition :: UGen -> IO ()
-
-since IO is an instance of the UId class.
-
-It is the type of audition that determines the
-type of a, the type is inferred so there is no
-need to write it.
-
-> let { (|>) = flip (.)
->     ; a >>=* b = a >>= b |> return
->     ; u1 = sinOsc ar 440 0 * 0.1
->     ; u2 = pinkNoise ar >>=* (* 0.1)
->     ; u3 = Sound.SC3.UGen.Noise.ID.pinkNoise 'α' ar * 1
->     ; u4 = resonz u3 (440 * 4) 0.1
->     ; g = u2 >>=* (+ (u1 + u4)) }
-> in g >>= out 0 |> audition
-
-* Unsafe unit generator constructors
-
-Haskell provides a mechanism to force values
-from the IO monad, unsafePerformIO.
-
-Using this we can write unit generator graphs
-that have non-deterministic nodes using only
-orindary let binding.
-
-> import System.IO.Unsafe
-
-> let { u = unsafePerformIO
->     ; a = u (whiteNoise AR)
->     ; b = u (whiteNoise AR)
->     ; c = a - b }
-> in audition (out 0 (c * 0.1))
-
-This is hardly more convenient than do notation,
-however we can also insert non-determinstic nodes
-directly into function arguments.  The package
-hsc3-unsafe provides unsafe variant unnit generator
-constructors.
-
-> let { n = Sound.SC3.UGen.Unsafe.whiteNoise
->     ; x = n AR - n AR }
-> in audition (out 0 (x * 0.1))
-
-The above uses the unsafe unit generator functions
-provided at Sound.SC3.UGen.Unsafe, and avoids the
-lifting operations which, for functions of many
-arguments, can be cumbersome.
-
-> import Control.Monad
-> import Sound.SC3.Monadic
-
-> let n = whiteNoise
-> in do { x <- liftM2 (-) (n AR) (n AR)
->       ; audition (out 0 (x * 0.1)) }
-
-* Demand Rate, Sharing Again
-
-Demand rate UGens are similarly not functions only
-of their arguments.
-
-In the supercollider language expression below the
-left and right channels have different signals,
-despite each receiving the same input unit
-generator.
-
-| { var a = Dseq([1, 3, 2, 7, 8], 3)
-| ; var t = Impulse.kr(5,0)
-| ; var f = Demand.kr(t, 0, [a, a]) * 30 + 340
-| ; Out.ar(0, SinOsc.ar(f, 0) * 0.1) }.play
-
-The distinction here concerns multiple
-reads from a single demand rate source, ie.
-it is not that the source is non-deterministic,
-it is rather that each read request consumes
-the value it reads.
-
-Therefore in haskell demand rate unit generators have
-similar constructor functions to non-deterministic
-unit generators, in order that we can distinguish:
-
-> do { a <- dseq 3 (mce [1, 3, 2, 7, 8])
->    ; let { t = impulse KR 5 0
->          ; f = demand t 0 (mce [a, a]) * 30 + 340 }
->      in audition (out 0 (sinOsc AR f 0 * 0.1)) }
-
-which is the same graph as given in supercollider
-language above, from:
-
-> do { a <- clone 2 (dseq 3 (mce [1, 3, 2, 7, 8]))
->    ; let { t = impulse KR 5 0
->          ; f = demand t 0 a * 30 + 340 }
->      in audition (out 0 (sinOsc AR f 0 * 0.1)) }
-
-which gives an equal sequence of tones in each
-channel.
-
-* References
-
-+ A. Goldberg and D. Robson.  Smalltalk-80: The
-  language and its implementation.
-  Addison-Wesley, Reading, MA, 1983.
-
-+ P. Hudak, J. Hughes, S. P. Jones, and P. Wadler.
-  A History of Haskell: being lazy with class.  In
-  The Third ACM SIGPLAN History of Programming
-  Languages Conference, San Diego, California,
-  June 2007.  Association for Computing Machinery.
-
-+ John Hughes. Generalising monads to arrows.
-  Sci. Comput. Program., 37(1-3):67-111, 2000.
-
-+ P. Landin.  The next 700 programming languages.
-  Communications of the ACM, 9(3):157-164, March
-  1966.  Presented at the ACM Programming and
-  Pragmatics Conference, August 1965.
-
-+ M. V. Mathews.  An Acoustical Compiler for Music
-  and Psychological Stimuli.  AT&T Bell
-  Laboratories Technical Journal, 40:677-694,
-  1961.
-
-+ C. McBride and R. Paterson.  Applicative
-  Programming with Effects.  Journal of Functional
-  Programming, 17(4), 2007.
-
-+ J. McCarthy.  Recursive functions of symbolic
-  expressions and their computation by machine.
-  Communications of the ACM, 3(4):184-195, 1960.
-
-+ J. McCartney.  Continued evolution of the
-  SuperCollider real time synthesis environment.
-  In Proceedings of the International Computer
-  Music Conference, pages 133-136. International
-  Computer Music Association, 1998.
-
-+ J. McCartney.  Rethinking the Computer Music
-  Language: SuperCollider.  Computer Music
-  Journal, 26(4):61-68, 2002.
-
-+ Amr Sabry. What is a Purely Functional Language?
-  Journal of Functional Programming, 1(1), 1993.
-
-+ C. Strachey.  Fundamental Concepts in
-  Programming Languages.  Higher-Order and
-  Symbolic Computation, 13:11-49, 2000.
-
-+ Philip Wadler. Lazy versus strict.  ACM
-  Comput. Surv., 28(2):318-320, 1996.
-
-+ P. Wadler.  Comprehending Monads.  In Conference
-  on Lisp and Funcional Programming, Nice, France,
-  June 1990. ACM.
-
-+ P. Wadler and S. Blott.  How to make ad hoc
-  polymorphism less ad hoc.  In Proceedings of
-  16th ACM Symposium on Principles of Programming
-  Languages, pages 60-76, January 1989.
-
-+ M. Wright and A. Freed.  Open Sound Control: A
-  New Protocol for Communicating with Sound
-  Synthesizers.  In Proceedings of the
-  International Computer Music Conference, pages
-  101-104.  International Computer Music
-  Association, 1997.
diff --git a/Help/tutorial.lhs b/Help/tutorial.lhs
deleted file mode 100644
--- a/Help/tutorial.lhs
+++ /dev/null
@@ -1,313 +0,0 @@
-* Haskell SuperCollider, a Tutorial.
-
-* Prerequisites
-
-Haskell SuperCollider requires that SuperCollider [1], GHC [2],
-Emacs [4] and the standard Haskell Emacs mode [5] are all
-installed and working properly.
-
-* Setting up Haskell SuperCollider
-
-Haskell SuperCollider is available through the haskell community
-library system Hackage [6].  To install type:
-
-  $ cabal install hsc3
-
-Haskell SuperCollider is also available as a set of darcs [7]
-repositories, the first implementing the Sound.OpenSoundControl
-module, the second the Sound.SC3 module.
-
-  $ darcs get http://slavepianos.org/rd/sw/hosc
-  $ darcs get http://slavepianos.org/rd/sw/hsc3
-
-To build use the standard Cabal process in each repository in
-sequence.  To install to the user package database type:
-
-  $ cabal install
-
-* Setting up the Haskell SuperCollider Emacs mode
-
-Add an appropriately modified variant of the following to
-~/.emacs
-
-  (push "~/sw/hsc3/emacs" load-path)
-  (setq hsc3-help-directory "~/sw/hsc3/Help/")
-  (require 'hsc3)
-
-The hsc3 emacs mode associates itself with files having the
-extension '.lhs'.  When the hsc3 emacs mode is active there is a
-'Haskell SuperCollider' menu available.
-
-* Literate Haskell
-
-The documentation for Haskell SuperCollider, including this
-tutorial, is written in 'Bird' notation, a form of 'literate
-Haskell' where lines starting with '>' are Haskell code and
-everything else is commentary.
-
-Unlike ordinary literate programs the Haskell SuperCollider help
-files cannot be compiled to executables.  Each help file contains
-multiple independant examples that can be evaluated using editor
-commands, either by selecting from the 'Haskell SuperCollider'
-menu or using the associated keybinding.
-
-* Interpreter Interaction & User Configuration
-
-To start ghci and load the file at 'hsc3-run-control' file use
-C-cC-s (Haskell SuperCollider -> Haskell -> Start haskell).
-
-If there is no file at 'hsc3-run-control' one will be created and
-the modules at 'hsc3-modules' will be imported.  By default this
-list contains the hosc and hsc3 modules as well as
-Control.Concurrent, Control.Monad, Data.List, and System.Random.
-
-Starting the interpreter splits the current window into two
-windows.  If the ghci output window becomes obscured during a
-session you can see it again by typing C-cC-g (Haskell
-SuperCollider -> Haskell -> See output).
-
-To interrupt ghci type C-cC-i (Haskell SuperCollider -> Haskell
--> Interrupt haskell).
-
-To stop ghci type C-cC-x (Haskell SuperCollider -> Haskell ->
-Quit haskell).
-
-* Starting the SuperCollider server
-
-The SuperCollider server can be started from the command line.
-The help files assume that scsynth is listening for UDP
-connections at the standard port on the local machine.
-
-  $ scsynth -u 57110
-
-* Basic SuperCollider Interaction
-
-The SuperCollider server manages a graph of nodes with integer
-identifiers.  The root node has ID zero.  By convention ordinary
-graph nodes are placed in a group with identifier 1, however this
-node is not created when scsynth starts.
-
-To create this node we need to send an OSC message to the server,
-the expression to do this is written below.  To run single line
-expressions move the cursor to the line and type C-cC-c (Haskell
-SuperCollider -> Expression -> Run line).
-
-> import Sound.SC3
-
-> withSC3 (\fd -> send fd (g_new [(1, AddToTail, 0)]))
-
-We can then audition a quiet sine oscillator at A440.
-
-> audition (out 0 (sinOsc AR 440 0 * 0.1))
-
-To stop the sound we can delete the group it is a part of, the
-audition function places the synthesis node into the group node
-with ID 1, the expression below deletes that group.
-
-> withSC3 (\fd -> send fd (n_free [1]))
-
-In order to audition another graph we need to re-create a group
-with ID 1.  Sound.SC3 includes a function 'reset' that sequences
-these two actions, first deleting the group node, then
-re-creating a new empty group.
-
-> withSC3 reset
-
-Using this command is so common there is a keybinding for it,
-C-cC-k (Haskell SuperCollider -> SCSynth -> Reset scsynth).
-After a reset we can audition a new graph.
-
-> audition (out 0 (sinOsc AR 220 0 * 0.1))
-
-To see the server status type C-cC-w (Haskell SuperCollider ->
-SCSynth -> Display status).  This prints a table indicating
-server activity to the ghci output window.
-
-  ***** SuperCollider Server Status *****
-  # UGens                     Int 3
-  # Synths                    Int 1
-  # Groups                    Int 2
-  # Instruments               Int 1
-  % CPU (Average)             Float 2.6957032680511475
-  % CPU (Peak)                Float 2.7786526679992676
-  Sample Rate (Nominal)       Double 44100.0
-  Sample Rate (Actual)        Double 44099.958404246536
-
-* Completion messages
-
-To send a completion message add one to an existing
-asynchronous message using withCM.
-
-> let { g = out 0 (sinOsc AR 660 0 * 0.15)
->     ; m = d_recv (synthdef "sin" g)
->     ; cm = s_new "sin" 100 AddToTail 1 [] }
-> in withSC3 (\fd -> send fd (withCM m cm))
-
-Alternately use variant constructors for the
-asynchronous commands.
-
-> import Sound.SC3.Server.Command.Completion
-
-> let { g = out 0 (sinOsc AR 660 0 * 0.15)
->     ; cm = s_new "sin" 100 AddToTail 1 []
->     ; m = d_recv' cm (synthdef "sin" g) }
-> in withSC3 (\fd -> send fd m)
-
-* Controls
-
-In hsc3 control parameters must be indexed by name.
-
-There are four types of control parameters,
-initialisation-rate (ir), control-rate (kr),
-triggered-control-rate (tr) and audio-rate.
-
-The graph below illustrates the first three of these.
-Note the specialised constructor for triggered
-controls.  
-
-> let { b1 = control IR "b1" 0
->     ; b2 = control IR "b2" 1
->     ; f1 = control KR "f1" 450
->     ; f2 = control KR "f2" 900
->     ; a1 = tr_control "a1" 0
->     ; a2 = tr_control "a2" 0
->     ; m = impulse KR 1 0 * 0.1
->     ; d x = decay2 (m + x) 0.01 0.2
->     ; o1 = sinOsc AR f1 0 * d a1
->     ; o2 = saw AR f2 * d a2
->     ; g = mrg2 (out b1 o1) (out b2 o2)
->     ; i fd = do { async fd (d_recv (synthdef "g" g))
->                 ; send fd (s_new "g" 100 AddToTail 1 []) } }
-> in withSC3 i
-
-The output buses cannot be set, since they are
-initialisation rate only.
-
-> withSC3 (\fd -> send fd (n_set1 100 "b1" 1))
-> withSC3 (\fd -> send fd (n_set1 100 "b2" 0))
-
-The frequency controls can be set since they are
-control rate.
-
-> withSC3 (\fd -> send fd (n_set1 100 "f1" 200))
-> withSC3 (\fd -> send fd (n_set1 100 "f2" 300))
-
-The audio controls can be set, however they are
-immediately reset to zero at the next control cycle.
-
-> withSC3 (\fd -> send fd (n_set1 100 "a1" 1))
-> withSC3 (\fd -> send fd (n_set1 100 "a2" 1))
-
-* Multiple line expressions
-
-There are two variants for expressions that are written over
-multiple lines.
-
-To evaluate an expression that is written without using the
-Haskell layout rules select the region and type C-cC-e (Haskell
-SuperCollider -> Expression -> Run multiple lines).  To select a
-region use the mouse or place the cursor at one end, type
-C-[Space] then move the cursor to the other end.
-
-> let { f0 = xLine KR 1 1000 9 RemoveSynth
->     ; f1 = sinOsc AR f0 0 * 200 + 800 }
-> in audition (out 0 (sinOsc AR f1 0 * 0.1))
-
-To evaluate a multiple line expression written using the layout
-rules as applicable within a do block, select the region and type
-C-cC-r (Haskell SuperCollider -> Expression -> Run region).
-
-> let f0 = xLine KR 1 1000 9 RemoveSynth
->     f1 = sinOsc AR f0 0 * 200 + 800
-> audition (out 0 (sinOsc AR f1 0 * 0.1))
-
-This writes the region in a do block in a procedure to a
-temporary file, /tmp/hsc3.lhs, loads the file and then runs the
-procedure.  The preamble imports the modules listed at the emacs
-variable hsc3-modules.
-
-ghci understands import expressions, so to add a module to the
-current scope it is enough to type C-cC-c at an appropriate
-location.  If hsc3-dot is installed, the following two
-expressions will load the module and make a drawing.
-
-> import Sound.SC3
-> import Sound.SC3.UGen.Dot
-
-> let { o = control KR "bus" 0
->     ; f = mouseX KR 440 880 Exponential 0.1 }
-> in draw (out o (sinOsc AR f 0))
-
-* Help Files
-
-To find help on a unit generator or on a SuperCollider server
-command place the cursor over the identifier and type C-cC-h
-(Haskell SuperCollider -> Help -> Haskell SuperCollider help).
-This opens the help file, which ought to have working examples in
-it, the above graph is in the sinOsc help file, the s_new help
-file explains what arguments are required and what they mean.
-
-The Haskell SuperCollider help files are derived from the help
-files distributed with SuperCollider, the text is re-formatted to
-read well as plain text and examples are translated into Haskell.
-
-There is also partial haddock documentation for the Sound.SC3 and
-Sound.OpenSoundControl modules, to build type:
-
-  $ runhaskell Setup.lhs haddock
-
-* Identifier lookup & hasktags
-
-The emacs command M-. (find-tag) looks up an identifier in a
-'tags' table.  The hasktags utility can generate tags files from
-haskell source files that are usable with emacs.
-
-To generate a tags file for hsc3, visit the hsc3 directory and
-type:
-
-  $ find Sound -name '*.*hs' | xargs hasktags -e
-
-To use the hsc3 tags table type `M-x visit-tags-table', or add an
-entry to ~/.emacs:
-
-  (setq tags-table-list '("~/sw/hsc3"))
-
-* External Unit Generators
-
-hsc3 includes bindings and help files for some unit generators
-not in the standard supercollider distribution.  In order to use
-these unit generators they must be installed, see:
-
-  http://sf.net/projects/sc3-plugins/
-
-* Example Unit Generator Graphs
-
-The Help/ directory contains example unit generator
-graphs.  To audition a graph from Emacs type C-cC-l
-C-cC-m.  Many of the graphs are self contained,
-selecting the graph (excluding the 'main =' line) and
-typing C-cC-e will audition it.  In many cases both
-supercollider language and haskell versions are given,
-switch the emacs buffer to sclang-mode to run the
-supercollider language versions.
-
-* Monitoring incoming server messages
-
-To monitor what OSC messages scsynth is receiving use the
-'dumpOSC' server command to request that scsynth print text
-traces of incoming messages to its standard output.
-
-> withSC3 ((flip send) (dumpOSC TextPrinter))
-
-To end printing send:
-
-> withSC3 ((flip send) (dumpOSC NoPrinter))
-
-* References
-
-[1] http://audiosynth.com/
-[2] http://haskell.org/ghc/
-[4] http://gnu.org/software/emacs/
-[5] http://haskell.org/haskell-mode/
-[6] http://hackage.haskell.org/
-[7] http://darcs.net/
diff --git a/README b/README
--- a/README
+++ b/README
@@ -1,10 +1,10 @@
 hsc3 - haskell supercollider
 
 hsc3 provides Sound.SC3, a Haskell module that facilitates using
-Haskell as a client to the SuperCollider synthesis server.  
+Haskell as a client to the SuperCollider synthesis server.
 
 For installation and configuration information please consult the
-tutorial file at Help/tutorial.lhs
+tutorial file at http://slavepianos.org/rd/ut/hsc3-texts/
 
 The hsc3 interaction environment is written for GNU Emacs.
 
diff --git a/Sound/SC3.hs b/Sound/SC3.hs
--- a/Sound/SC3.hs
+++ b/Sound/SC3.hs
@@ -1,22 +1,8 @@
-module Sound.SC3 (-- $help
-                  module Sound.SC3.Server
+-- | Exports both "Sound.SC3.Server" and "Sound.SC3.UGen", however see
+-- also "Sound.SC3.ID" and "Sound.SC3.Monadic".
+module Sound.SC3 (module Sound.SC3.Server
                  ,module Sound.SC3.UGen) where
 
 import Sound.SC3.Server
 import Sound.SC3.UGen
-
--- $help
--- Once the hsc3 library has been installed, you will find help files
--- installed in @$PREFIX\/share\/hsc3-VERSION\/Help\/@.
---
--- For installation and configuration information please consult the
--- tutorial file at @Help\/tutorial.lhs@.
---
--- For general information on supercollider and the overall design of
--- the hsc3 bindings, see @Help\/hsc3.help.lhs@.
---
--- For documentation and examples for unit generators, see
--- @Help\/UGen\/@.  Note that the Haddock documentation for many unit
--- generators is incomplete; see the appropriate file in
--- @Help\/UGen\/@ for complete documentation.
 
diff --git a/Sound/SC3/ID.hs b/Sound/SC3/ID.hs
--- a/Sound/SC3/ID.hs
+++ b/Sound/SC3/ID.hs
@@ -1,11 +1,12 @@
-module Sound.SC3.ID (module Sound.SC3.UGen
-                    ,module Sound.SC3.UGen.Demand.ID
-                    ,module Sound.SC3.UGen.FFT.ID
-                    ,module Sound.SC3.UGen.Noise.ID
-                    ,module Sound.SC3.Server) where
+-- | Module exporting all of "Sound.SC3" and also the explicit
+-- identifier variants for non-deterministic and non-sharable unit
+-- generators.
+module Sound.SC3.ID (module I) where
 
-import Sound.SC3.UGen
-import Sound.SC3.UGen.Demand.ID
-import Sound.SC3.UGen.FFT.ID
-import Sound.SC3.UGen.Noise.ID
-import Sound.SC3.Server
+import Sound.SC3.Identifier as I
+import Sound.SC3.UGen as I
+import Sound.SC3.UGen.Composite.ID as I
+import Sound.SC3.UGen.Demand.ID as I
+import Sound.SC3.UGen.FFT.ID as I
+import Sound.SC3.UGen.Noise.ID as I
+import Sound.SC3.Server as I
diff --git a/Sound/SC3/Identifier.hs b/Sound/SC3/Identifier.hs
new file mode 100644
--- /dev/null
+++ b/Sound/SC3/Identifier.hs
@@ -0,0 +1,27 @@
+-- | Typeclass and functions to manage UGen identifiers.
+module Sound.SC3.Identifier where
+
+import Data.Char
+import qualified Data.Digest.Murmur32 as H
+
+-- | Typeclass to constrain UGen identifiers.
+class ID a where
+    resolveID :: a -> Int
+
+instance ID Int where
+    resolveID = id
+
+instance ID Char where
+    resolveID = ord
+
+-- | Hash 'ID' to 'Int'.
+idHash :: ID a => a -> Int
+idHash = fromIntegral . H.asWord32 . H.hash32 . resolveID
+
+-- | Resolve the ID at 'i' and add the resolved enumeration of 'j'.
+editID :: (ID a, Enum b) => a -> b -> Int
+editID i j = resolveID i + fromEnum j
+
+-- | Infix alias for editID
+(//) :: (ID a, Enum b) => a -> b -> Int
+(//) = editID
diff --git a/Sound/SC3/Monadic.hs b/Sound/SC3/Monadic.hs
--- a/Sound/SC3/Monadic.hs
+++ b/Sound/SC3/Monadic.hs
@@ -1,14 +1,11 @@
-module Sound.SC3.Monadic (module Sound.SC3.UGen
-                         ,module Sound.SC3.UGen.Composite.Monadic
-                         ,module Sound.SC3.UGen.Demand.Monadic
-                         ,module Sound.SC3.UGen.FFT.Monadic
-                         ,module Sound.SC3.UGen.Noise.Monadic
-                         ,module Sound.SC3.Server) where
-
-import Sound.SC3.UGen
-import Sound.SC3.UGen.Composite.Monadic
-import Sound.SC3.UGen.Demand.Monadic
-import Sound.SC3.UGen.FFT.Monadic
-import Sound.SC3.UGen.Noise.Monadic
-import Sound.SC3.Server
+-- | Module exporting all of "Sound.SC3" and also the monadic
+-- constructor variants for non-deterministic and non-sharable unit
+-- generators.
+module Sound.SC3.Monadic (module M) where
 
+import Sound.SC3.UGen as M
+import Sound.SC3.UGen.Composite.Monadic as M
+import Sound.SC3.UGen.Demand.Monadic as M
+import Sound.SC3.UGen.FFT.Monadic as M
+import Sound.SC3.UGen.Noise.Monadic as M
+import Sound.SC3.Server as M
diff --git a/Sound/SC3/Server.hs b/Sound/SC3/Server.hs
--- a/Sound/SC3/Server.hs
+++ b/Sound/SC3/Server.hs
@@ -1,13 +1,9 @@
 -- | Collection of modules for communicating with the SuperCollider
 --   synthesis server.
-module Sound.SC3.Server ( module Sound.SC3.Server.Command
-                        , module Sound.SC3.Server.Synthdef
-                        , module Sound.SC3.Server.Play
-                        , module Sound.SC3.Server.Status
-                        , module Sound.SC3.Server.NRT ) where
+module Sound.SC3.Server (module S) where
 
-import Sound.SC3.Server.Command
-import Sound.SC3.Server.Synthdef
-import Sound.SC3.Server.Play
-import Sound.SC3.Server.Status
-import Sound.SC3.Server.NRT
+import Sound.SC3.Server.Command as S
+import Sound.SC3.Server.Synthdef as S
+import Sound.SC3.Server.Play as S
+import Sound.SC3.Server.Status as S
+import Sound.SC3.Server.NRT as S
diff --git a/Sound/SC3/Server/Command.hs b/Sound/SC3/Server/Command.hs
--- a/Sound/SC3/Server/Command.hs
+++ b/Sound/SC3/Server/Command.hs
@@ -2,16 +2,15 @@
 --   synthesis server.
 module Sound.SC3.Server.Command where
 
-import qualified Data.ByteString.Lazy as B
-import Data.Word
 import Sound.OpenSoundControl
 import Sound.SC3.Server.Utilities
+import Sound.SC3.Server.Synthdef
 
 -- * Instrument definition commands
 
 -- | Install a bytecode instrument definition. (Asynchronous)
-d_recv :: [Word8] -> OSC
-d_recv b = message "/d_recv" [Blob b]
+d_recv :: Synthdef -> OSC
+d_recv d = message "/d_recv" [Blob (synthdefData d)]
 
 -- | Load an instrument definition from a named file. (Asynchronous)
 d_load :: String -> OSC
@@ -51,6 +50,14 @@
 n_mapn :: Int -> [(String, Int, Int)] -> OSC
 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)] -> OSC
+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)] -> OSC
+n_mapan nid l = message "/n_mapan" (Int nid : mk_triples String Int Int l)
+
 -- | Get info about a node.
 n_query :: [Int] -> OSC
 n_query = message "/n_query" . map Int
@@ -72,6 +79,10 @@
 n_trace :: [Int] -> OSC
 n_trace = message "/n_trace" . map Int
 
+-- | Move an ordered sequence of nodes.
+n_order :: AddAction -> Int -> [Int] -> OSC
+n_order a n ns = message "/n_order" (Int (fromEnum a) : Int n : map Int ns)
+
 -- * Synthesis node commands
 
 -- | Get control values.
@@ -94,10 +105,6 @@
 s_new :: String -> Int -> AddAction -> Int -> [(String, Double)] -> OSC
 s_new n i a t c = message "/s_new" (String n : Int i : Int (fromEnum a) : Int t : mk_duples String Float c)
 
--- | Create a new synth.
-s_newargs :: String -> Int -> AddAction -> Int -> [(String, [Double])] -> OSC
-s_newargs n i a t c = message "/s_newargs" (String n : Int i : Int (fromEnum a) : Int t : mk_duples_l Int String Float c)
-
 -- | Auto-reassign synth's ID to a reserved value.
 s_noid :: [Int] -> OSC
 s_noid = message "/s_noid" . map Int
@@ -124,11 +131,53 @@
 g_tail :: [(Int, Int)] -> OSC
 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)] -> OSC
+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)] -> OSC
+g_queryTree = message "/g_queryTree" . mk_duples Int (Int . fromEnum)
+
+-- | Create a new parallel group (supernova specific).
+p_new :: [(Int, AddAction, Int)] -> OSC
+p_new = message "/p_new" . mk_triples Int (Int . fromEnum) Int
+
+-- * Plugin commands
+
+-- | Send a plugin command.
+cmd :: String -> [Datum] -> OSC
+cmd name = message "/cmd" . (String name :)
+
 -- * Unit Generator commands
 
 -- | Send a command to a unit generator.
 u_cmd :: Int -> Int -> String -> [Datum] -> OSC
-u_cmd nid uid cmd arg = message "/u_cmd" ([Int nid, Int uid, String cmd] ++ arg)
+u_cmd nid uid name arg = message "/u_cmd" ([Int nid, Int uid, String name] ++ arg)
 
 -- * Buffer commands
 
@@ -158,7 +207,7 @@
 
 -- | Call a command to fill a buffer.  (Asynchronous)
 b_gen :: Int -> String -> [Double] -> OSC
-b_gen bid cmd arg = message "/b_gen" (Int bid : String cmd : map Float arg)
+b_gen bid name arg = message "/b_gen" (Int bid : String name : map Float arg)
 
 -- | Get sample values.
 b_get :: Int -> [Int] -> OSC
@@ -173,12 +222,12 @@
 b_query = message "/b_query" . map Int
 
 -- | Read sound file data into an existing buffer. (Asynchronous)
-b_read :: Int -> String -> Int -> Int -> Int -> Int -> OSC
-b_read nid p f n f' z = message "/b_read" [Int nid, String p, Int f, Int n, Int f', Int z]
+b_read :: Int -> String -> Int -> Int -> Int -> Bool -> OSC
+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 -> Int -> [Int] -> OSC
-b_readChannel nid p f n f' z cs = message "/b_readChannel" ([Int nid, String p, Int f, Int n, Int f', Int z] ++ map Int cs)
+b_readChannel :: Int -> String -> Int -> Int -> Int -> Bool -> [Int] -> OSC
+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)] -> OSC
@@ -190,8 +239,8 @@
     where f (i,d) = Int i : Int (length d) : map Float d
 
 -- | Write sound file data. (Asynchronous)
-b_write :: Int -> String -> Int -> Int -> Int -> Int -> Int -> OSC
-b_write nid p h t f s z = message "/b_write" [Int nid, String p, Int h, Int t, Int f, Int s, Int z]
+b_write :: Int -> String -> String -> String -> Int -> Int -> Bool -> OSC
+b_write nid p h t f s z = message "/b_write" [Int nid, String p, String h, String t, Int f, Int s, Int (fromEnum z)]
 
 -- | Zero sample data. (Asynchronous)
 b_zero :: Int -> OSC
@@ -253,8 +302,32 @@
 sync :: Int -> OSC
 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 -> OSC
+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] -> OSC
+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')
+
 -- | Set single sample value.
 b_set1 :: Int -> Int -> Double -> OSC
 b_set1 nid i x = b_set nid [(i,x)]
@@ -273,19 +346,37 @@
 
 -- * Modify existing message to include completion message
 
--- List of asynchronous server commands.
+-- | List of asynchronous server commands.
 async_cmds :: [String]
-async_cmds = ["/d_recv", "/d_load", "/d_loadDir"
-             ,"/b_alloc", "/b_allocRead", "/b_allocReadChannel"
-             ,"/b_free", "/b_close"
-             ,"/b_read", "/b_readChannel"
-             ,"/b_write", "/b_zero"]
+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 'OSC' is an asynchronous 'Message'.
+isAsync :: OSC -> Bool
+isAsync o =
+    case o of
+      Message a _ -> a `elem` async_cmds
+      Bundle _ _ -> error "isAsync: bundle"
+
 -- | Add a completion message to an existing asynchronous command.
 withCM :: OSC -> OSC -> OSC
 withCM (Message c xs) cm =
     if c `elem` async_cmds
-    then let xs' = xs ++ [Blob (B.unpack (encodeOSC cm))]
+    then let xs' = xs ++ [Blob (encodeOSC cm)]
          in message c xs'
     else error ("withCM: not async: " ++ c)
 withCM _ _ = error "withCM: not message"
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
@@ -4,8 +4,8 @@
 -- that this mechanism is for synchronizing server side processes only, for
 -- client side synchronization use @\/done@ message notification or the
 -- @\/sync@ barrier.
-module Sound.SC3.Server.Command.Completion (
-  -- *Synthdef handling
+module Sound.SC3.Server.Command.Completion
+  ( -- *Synthdef handling
     d_recv'
   , d_load'
   , d_loadDir'
@@ -22,19 +22,18 @@
   , b_write'
   -- *Buffer operations
   , b_zero'
-) where
+  ) where
 
-import           Data.Word (Word8)
-import qualified Data.ByteString.Lazy as B
-import           Sound.OpenSoundControl
+import Sound.OpenSoundControl
+import Sound.SC3.Server.Synthdef
 
 -- Encode an OSC packet as an OSC blob.
 encode_osc_blob :: OSC -> Datum
-encode_osc_blob = Blob . B.unpack . encodeOSC
+encode_osc_blob = Blob . encodeOSC
 
 -- | Install a bytecode instrument definition. (Asynchronous)
-d_recv' :: OSC -> [Word8] -> OSC
-d_recv' osc b = message "/d_recv" [Blob b, encode_osc_blob osc]
+d_recv' :: OSC -> Synthdef -> OSC
+d_recv' osc d = message "/d_recv" [Blob (synthdefData d), encode_osc_blob osc]
 
 -- | Load an instrument definition from a named file. (Asynchronous)
 d_load' :: OSC -> String -> OSC
@@ -65,16 +64,16 @@
 b_close' osc nid = message "/b_close" [Int nid, encode_osc_blob osc]
 
 -- | Read sound file data into an existing buffer. (Asynchronous)
-b_read' :: OSC -> Int -> String -> Int -> Int -> Int -> Int -> OSC
-b_read' osc nid p f n f' z = message "/b_read" [Int nid, String p, Int f, Int n, Int f', Int z, encode_osc_blob osc]
+b_read' :: OSC -> Int -> String -> Int -> Int -> Int -> Bool -> OSC
+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_osc_blob osc]
 
 -- | Read sound file data into an existing buffer. (Asynchronous)
-b_readChannel' :: OSC -> Int -> String -> Int -> Int -> Int -> Int -> [Int] -> OSC
-b_readChannel' osc nid p f n f' z cs = message "/b_readChannel" ([Int nid, String p, Int f, Int n, Int f', Int z] ++ map Int cs ++ [encode_osc_blob osc])
+b_readChannel' :: OSC -> Int -> String -> Int -> Int -> Int -> Bool -> [Int] -> OSC
+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_osc_blob osc])
 
 -- | Write sound file data. (Asynchronous)
-b_write' :: OSC -> Int -> String -> Int -> Int -> Int -> Int -> Int -> OSC
-b_write' osc nid p h t f s z = message "/b_write" [Int nid, String p, Int h, Int t, Int f, Int s, Int z, encode_osc_blob osc]
+b_write' :: OSC -> Int -> String -> String -> String -> Int -> Int -> Bool -> OSC
+b_write' osc nid p h t f s z = message "/b_write" [Int nid, String p, String h, String t, Int f, Int s, Int (fromEnum z), encode_osc_blob osc]
 
 -- | Zero sample data. (Asynchronous)
 b_zero' :: OSC -> Int -> OSC
diff --git a/Sound/SC3/Server/NRT.hs b/Sound/SC3/Server/NRT.hs
--- a/Sound/SC3/Server/NRT.hs
+++ b/Sound/SC3/Server/NRT.hs
@@ -1,10 +1,11 @@
 -- | Non-realtime score generation.
-module Sound.SC3.Server.NRT ( encodeNRT 
-                            , writeNRT
-                            , putNRT ) where
+module Sound.SC3.Server.NRT (encodeNRT
+                            ,writeNRT
+                            ,putNRT ) where
 
 import qualified Data.ByteString.Lazy as B
 import Sound.OpenSoundControl
+import Sound.OpenSoundControl.Coding.Byte
 import System.IO
 
 -- | Encode and prefix with encoded length.
diff --git a/Sound/SC3/Server/Play.hs b/Sound/SC3/Server/Play.hs
--- a/Sound/SC3/Server/Play.hs
+++ b/Sound/SC3/Server/Play.hs
@@ -1,38 +1,74 @@
 -- | Basic user interaction with the scsynth server.
-module Sound.SC3.Server.Play ( play, stop, reset, send, async
-                             , withSC3, audition ) where
+module Sound.SC3.Server.Play (stop,reset,send,async
+                             ,withSC3
+                             ,Audible(..)
+                             ,perform) where
 
 import Sound.OpenSoundControl
 import Sound.SC3.Server.Command
 import Sound.SC3.Server.Synthdef
 import Sound.SC3.UGen.UGen
 
--- | Construct an instrument definition, send /d_recv and /s_new
--- | messages to scsynth.
-play :: Transport t => t -> UGen -> IO OSC
-play fd u = do let d = synthdef "Anonymous" u
-               send fd (d_recv d) 
-               r <- wait fd "/done"
-               send fd (s_new "Anonymous" (-1) AddToTail 1 [])
-               return r
-
--- | Free all nodes at the group with node id 1.
+-- | Free all nodes ('g_freeAll') at group @1@.
 stop :: Transport t => t -> IO ()
 stop fd = send fd (g_freeAll [1])
 
--- | Send an osc message and wait for a reply.
+-- | Send an 'OSC' message and wait for a @\/done@ reply.
 async :: Transport t => t -> OSC -> IO OSC
 async fd m = send fd m >> wait fd "/done"
 
--- | Free all nodes and re-create group node with id 1.
+-- | Free all nodes ('g_freeAll') at group @0@ and re-create groups
+-- @1@ and @2@.
 reset :: Transport t => t -> IO ()
-reset fd = do send fd (g_freeAll [0])
-              send fd (g_new [(1, AddToTail, 0)])
+reset fd = do
+  send fd (g_freeAll [0])
+  send fd (g_new [(1,AddToTail,0),(2,AddToTail,0)])
 
--- | Bracket SC3 communication.
+-- | Bracket @SC3@ communication.
 withSC3 :: (UDP -> IO a) -> IO a
 withSC3 = withTransport (openUDP "127.0.0.1" 57110)
 
--- | withSC3 . play
-audition :: UGen -> IO ()
-audition u = withSC3 (\fd -> play fd u) >> return ()
+-- | Send 'd_recv' and 's_new' messages to scsynth.
+playSynthdef :: Transport t => t -> Synthdef -> IO ()
+playSynthdef fd s = do
+  _ <- async fd (d_recv s)
+  send fd (s_new (synthdefName s) (-1) AddToTail 1 [])
+
+-- | Send an /anonymous/ instrument definition using 'playSynthdef'.
+playUGen :: Transport t => t -> UGen -> IO ()
+playUGen fd = playSynthdef fd . synthdef "Anonymous"
+
+-- | Class for values that can be encoded and send to @scsynth@ for
+-- audition.
+class Audible e where
+    play :: Transport t => t -> e -> IO ()
+    audition :: e -> IO ()
+    audition e = withSC3 (`play` e)
+
+instance Audible Synthdef where
+    play = playSynthdef
+
+instance Audible UGen where
+    play = playUGen
+
+-- | Wait ('pauseThreadUntil') until bundle is due to be sent relative
+-- to initial 'UTCr' time, then send each message, asynchronously if
+-- required.
+run_bundle :: Transport t => t -> Double -> OSC -> IO ()
+run_bundle fd i o =
+    let wr m = if isAsync m
+               then async fd m >> return ()
+               else send fd m
+    in case o of
+         Bundle (NTPr t) x' -> do
+             pauseThreadUntil (i + t)
+             mapM_ wr x'
+         _ -> error "run_bundle: non bundle or non-NTPr bundle"
+
+-- | Perform an 'OSC' score (as would be rendered by 'writeNRT').  In
+-- particular note that: (1) all 'OSC' must be 'Bundle's and (2)
+-- timestamps /must/ be in 'NTPr' form.
+perform :: [OSC] -> IO ()
+perform s = do
+  let f i fd = run_bundle fd i
+  withSC3 (\fd -> utcr >>= \i -> mapM_ (f i fd) s)
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,7 +1,7 @@
 -- | Request and display status information from the synthesis server.
-module Sound.SC3.Server.Status ( serverStatus
-                               , serverSampleRateNominal
-                               , serverSampleRateActual ) where
+module Sound.SC3.Server.Status (serverStatus
+                               ,serverSampleRateNominal
+                               ,serverSampleRateActual) where
 
 import Control.Monad
 import Sound.OpenSoundControl
@@ -32,8 +32,8 @@
 
 statusFields :: [String]
 statusFields = ["Unused                      ",
-                "# UGens                     ", 
-                "# Synths                    ", 
+                "# UGens                     ",
+                "# Synths                    ",
                 "# Groups                    ",
                 "# Instruments               ",
                 "% CPU (Average)             ",
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
@@ -1,13 +1,16 @@
 -- | The unit-generator graph structure implemented by the
 --   SuperCollider synthesis server.
-module Sound.SC3.Server.Synthdef ( Node(..), FromPort(..), Graph(..)
-                                 , synth, synthdef, synthstat ) where
+module Sound.SC3.Server.Synthdef (NodeId,PortIndex,KType(..)
+                                 ,Node(..),FromPort(..)
+                                 ,Graph(..),Graphdef,graphdef
+                                 ,Synthdef(..),synthdefData,synth,synthdef
+                                 ,synthstat) where
 
 import qualified Data.ByteString.Lazy as B
 import qualified Data.IntMap as M
 import Data.List
-import Data.Word
-import Sound.OpenSoundControl
+import Sound.OpenSoundControl.Coding.Byte
+import Sound.OpenSoundControl.Coding.Cast
 import Sound.SC3.UGen.UGen
 import Sound.SC3.UGen.Rate
 
@@ -18,36 +21,36 @@
 type PortIndex = Int
 
 -- | Type to represent unit generator graph.
-data Graph = Graph { nextId :: NodeId
-                   , constants :: [Node]
-                   , controls :: [Node]
-                   , ugens :: [Node] }
-            deriving (Eq, Show)
-
--- | Type to represent nodes in unit generator graph.
-data Node = NodeC { node_id :: NodeId
-                  , node_c_value :: Double }
-          | NodeK { node_id :: NodeId
-                  , node_k_rate :: Rate
-                  , node_k_name :: String
-                  , node_k_default :: Double
-                  , node_k_type :: KType }
-          | NodeU { node_id :: NodeId
-                  , node_u_rate :: Rate
-                  , node_u_name :: String
-                  , node_u_inputs :: [FromPort]
-                  , node_u_outputs :: [Output]
-                  , node_u_special :: Special
-                  , node_u_ugenid :: Int }
-          | NodeP { node_id :: NodeId
-                  , node_p_node :: Node
-                  , node_p_index :: PortIndex }
-            deriving (Eq, Show)
+data Graph = Graph {nextId :: NodeId
+                   ,constants :: [Node]
+                   ,controls :: [Node]
+                   ,ugens :: [Node]}
+            deriving (Eq,Show)
 
--- There are four classes of controls.
+-- | Enumeration of the four operating rates for controls.
 data KType = K_IR | K_KR | K_TR | K_AR
-             deriving (Eq, Show, Ord)
+             deriving (Eq,Show,Ord)
 
+-- | Type to represent nodes in unit generator graph.
+data Node = NodeC {node_id :: NodeId
+                  ,node_c_value :: Double}
+          | NodeK {node_id :: NodeId
+                  ,node_k_rate :: Rate
+                  ,node_k_name :: String
+                  ,node_k_default :: Double
+                  ,node_k_type :: KType}
+          | NodeU {node_id :: NodeId
+                  ,node_u_rate :: Rate
+                  ,node_u_name :: String
+                  ,node_u_inputs :: [FromPort]
+                  ,node_u_outputs :: [Output]
+                  ,node_u_special :: Special
+                  ,node_u_ugenid :: UGenId}
+          | NodeP {node_id :: NodeId
+                  ,node_p_node :: Node
+                  ,node_p_index :: PortIndex}
+            deriving (Eq,Show)
+
 node_k_cmp :: Node -> Node -> Ordering
 node_k_cmp p q = compare (node_k_type p) (node_k_type q)
 
@@ -66,25 +69,47 @@
 
 -- | Type to represent the left hand side of an edge in a unit
 --   generator graph.
-data FromPort = C NodeId
-              | K NodeId KType
-              | U NodeId PortIndex
-                deriving (Eq, Show)
+data FromPort = FromPort_C {port_nid :: NodeId}
+              | FromPort_K {port_nid :: NodeId,port_kt :: KType}
+              | FromPort_U {port_nid :: NodeId,port_idx :: PortIndex}
+                deriving (Eq,Show)
 
 -- | Transform a unit generator into a graph.
 synth :: UGen -> Graph
-synth u = let (_, g) = mk_node (prepare_root u) empty_graph
-              (Graph _ cs ks us) = g
-              ks' = sortBy node_k_cmp ks
-              us' = if null ks'
-                    then reverse us
-                    else implicit ks' ++ reverse us
-          in Graph (-1) cs ks' us'
+synth u =
+    let (_,g) = mk_node (prepare_root u) empty_graph
+        (Graph _ cs ks us) = g
+        ks' = sortBy node_k_cmp ks
+        us' = if null ks'
+              then reverse us
+              else implicit ks' ++ reverse us
+    in Graph (-1) cs ks' us'
 
--- | Transform a unit generator into bytecode.
-synthdef :: String -> UGen -> [Word8]
-synthdef s = B.unpack . encode_graphdef s . synth
+-- | Binary representation of a unit generator graph.
+type Graphdef = B.ByteString
 
+-- | Transform a unit generator graph into bytecode.
+graphdef :: Graph -> Graphdef
+graphdef = encode_graphdef
+
+-- | Binary representation of a unit generator synth definition.
+data Synthdef = Synthdef {synthdefName :: String
+                         ,synthdefGraph :: Graph}
+                deriving (Eq,Show)
+
+-- | Encode 'Synthdef' as binary data stream.
+synthdefData :: Synthdef -> B.ByteString
+synthdefData (Synthdef s g) =
+    B.concat [encode_str "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)
+
 -- | Simple statistical analysis of a unit generator graph.
 synthstat :: UGen -> String
 synthstat u =
@@ -92,8 +117,8 @@
         cs = constants s
         ks = controls s
         us = ugens s
-        f g = let h (x:xs) = (x, length (x:xs))
-                  h [] = undefined
+        f g = let h (x:xs) = (x,length (x:xs))
+                  h [] = error "synthstat"
               in show . map h . group . sort . map g
     in unlines ["number of constants       : " ++ show (length cs)
                ,"number of controls        : " ++ show (length ks)
@@ -102,10 +127,12 @@
                ,"unit generator rates      : " ++ f node_u_rate us]
 
 as_from_port :: Node -> FromPort
-as_from_port (NodeC n _) = C n
-as_from_port (NodeK n _ _ _ t) = K n t
-as_from_port (NodeU n _ _ _ _ _ _) = U n 0
-as_from_port (NodeP _ u p) = U (node_id u) p
+as_from_port d =
+    case d of
+      NodeC n _ -> FromPort_C n
+      NodeK n _ _ _ t -> FromPort_K n t
+      NodeU n _ _ _ _ _ _ -> FromPort_U n 0
+      NodeP _ u p -> FromPort_U (node_id u) p
 
 -- The empty graph.
 empty_graph :: Graph
@@ -113,105 +140,122 @@
 
 -- Predicate to locate constant.
 find_c_p :: Double -> Node -> Bool
-find_c_p x (NodeC _ y) = x == y
-find_c_p _ _ = error "find_c_p"
+find_c_p x n =
+    case n of
+      NodeC _ y -> x == y
+      _ -> error "find_c_p"
 
 -- Insert a constant node into the graph.
-push_c :: Double -> Graph -> (Node, Graph)
-push_c x g = let n = NodeC (nextId g) x
-             in (n, g { constants = n : constants g
-                      , nextId = nextId g + 1 })
+push_c :: Double -> Graph -> (Node,Graph)
+push_c x g =
+    let n = NodeC (nextId g) x
+    in (n,g {constants = n : constants g
+             ,nextId = nextId g + 1})
 
--- Either find existing constant node, or insert a new node.
-mk_node_c :: UGen -> Graph -> (Node, Graph)
-mk_node_c (Constant x) g =
-    let y = find (find_c_p x) (constants g)
-    in maybe (push_c x g) (\y' -> (y', g)) y
-mk_node_c _ _ = error "mk_node_c"
+-- Either find existing constant node,or insert a new node.
+mk_node_c :: UGen -> Graph -> (Node,Graph)
+mk_node_c u g =
+    case u of
+      Constant x ->
+          let y = find (find_c_p x) (constants g)
+          in maybe (push_c x g) (\y' -> (y',g)) y
+      _ -> error "mk_node_c"
 
--- Predicate to locate control, names must be unique.
+-- Predicate to locate control,names must be unique.
 find_k_p :: String -> Node -> Bool
-find_k_p x (NodeK _ _ y _ _) = x == y
-find_k_p _ _ = error "find_k_p"
+find_k_p x n =
+    case n of
+      NodeK _ _ y _ _ -> x == y
+      _ -> error "find_k_p"
 
 -- Insert a control node into the graph.
-push_k :: (Rate, String, Double, Bool) -> Graph -> (Node, Graph)
-push_k (r, nm, d, tr) g =
+push_k :: (Rate,String,Double,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
-             , nextId = nextId g + 1 })
+    in (n,g {controls = n : controls g
+             ,nextId = nextId g + 1})
 
--- Either find existing control node, or insert a new node.
-mk_node_k :: UGen -> Graph -> (Node, Graph)
-mk_node_k (Control r nm d tr) g =
-    let y = find (find_k_p nm) (controls g)
-    in maybe (push_k (r, nm, d, tr) g) (\y' -> (y', g)) y
-mk_node_k _ _ = error "mk_node_k"
+-- Either find existing control node,or insert a new node.
+mk_node_k :: UGen -> Graph -> (Node,Graph)
+mk_node_k u g =
+    case u of
+      Control r nm d tr ->
+          let y = find (find_k_p nm) (controls g)
+          in maybe (push_k (r,nm,d,tr) g) (\y' -> (y',g)) y
+      _ -> error "mk_node_k"
 
-acc :: [UGen] -> [Node] -> Graph -> ([Node], Graph)
-acc [] n g = (reverse n, g)
-acc (x:xs) ys g = let (y, g') = mk_node x g
-                  in acc xs (y:ys) g'
+acc :: [UGen] -> [Node] -> Graph -> ([Node],Graph)
+acc [] n g = (reverse n,g)
+acc (x:xs) ys g =
+    let (y,g') = mk_node x g
+    in acc xs (y:ys) g'
 
-type UGenParts = (Rate, String, [FromPort], [Output], Special, Int)
+type UGenParts = (Rate,String,[FromPort],[Output],Special,UGenId)
 
--- Predicate to locate primitive, names must be unique.
+-- Predicate to locate primitive,names must be unique.
 find_u_p :: UGenParts -> Node -> Bool
-find_u_p (r, n, i, o, s, d) (NodeU _ r' n' i' o' s' d')
-    = r == r' && n == n' && i == i' && o == o' && s == s' && d == d'
-find_u_p _ _ = error "find_u_p"
+find_u_p (r,n,i,o,s,d) nd =
+    case nd of
+      NodeU _ r' n' i' o' s' d' ->
+          r == r' && n == n' && i == i' && o == o' && s == s' && d == d'
+      _ ->  error "find_u_p"
 
 -- Insert a primitive node into the graph.
-push_u :: UGenParts -> Graph -> (Node, Graph)
-push_u (r, nm, i, o, s, d) g =
+push_u :: UGenParts -> Graph -> (Node,Graph)
+push_u (r,nm,i,o,s,d) g =
     let n = NodeU (nextId g) r nm i o s d
-    in (n, g { ugens = n : ugens g
-             , nextId = nextId g + 1 })
+    in (n,g {ugens = n : ugens g
+             ,nextId = nextId g + 1})
 
--- Either find existing control node, or insert a new node.
-mk_node_u :: UGen -> Graph -> (Node, Graph)
-mk_node_u (Primitive r nm i o s d) g =
-    let (i', g') = acc i [] g
-        i'' = map as_from_port i'
-        u = (r, nm, i'', o, s, d)
-        y = find (find_u_p u) (ugens g')
-    in maybe (push_u u g') (\y' -> (y', g')) y
-mk_node_u _ _ = error "mk_node_u"
+-- Either find existing control node,or insert a new node.
+mk_node_u :: UGen -> Graph -> (Node,Graph)
+mk_node_u ug g =
+    case ug of
+      Primitive r nm i o s d ->
+          let (i',g') = acc i [] g
+              i'' = map as_from_port i'
+              u = (r,nm,i'',o,s,d)
+              y = find (find_u_p u) (ugens g')
+          in maybe (push_u u g') (\y' -> (y',g')) y
+      _ -> error "mk_node_u"
 
 -- Proxies do not get stored in the graph.
-mk_node_p :: Node -> PortIndex -> Graph -> (Node, Graph)
-mk_node_p n p g = let z = nextId g
-                  in (NodeP z n p, g { nextId = z + 1 })
+mk_node_p :: Node -> PortIndex -> Graph -> (Node,Graph)
+mk_node_p n p g =
+    let z = nextId g
+    in (NodeP z n p,g {nextId = z + 1})
 
-mk_node :: UGen -> Graph -> (Node, Graph)
-mk_node u g
-    | isConstant u = mk_node_c u g
-    | isControl u = mk_node_k u g
-    | isUGen u = mk_node_u u g
-    | isProxy u = let (n, g') = mk_node_u (proxySource u) g
-                  in mk_node_p n (proxyIndex u) g'
-    | isMRG u = let (_, g') = mk_node (mrgRight u) g
-                in mk_node (mrgLeft u) g'
-    | isMCE u = error "mk_node: mce"
-    | otherwise = error "mk_node"
+mk_node :: UGen -> Graph -> (Node,Graph)
+mk_node u g =
+    case ugenType u of
+      Constant_U -> mk_node_c u g
+      Control_U -> mk_node_k u g
+      Primitive_U -> mk_node_u u g
+      Proxy_U ->
+          let (n,g') = mk_node_u (proxySource u) g
+          in mk_node_p n (proxyIndex u) g'
+      MRG_U ->
+          let (_,g') = mk_node (mrgRight u) g
+          in mk_node (mrgLeft u) g'
+      MCE_U -> error "mk_node: mce"
 
 type Map = M.IntMap Int
-type Maps = (Map, [Node], Map, Map)
+type Maps = (Map,[Node],Map,Map)
 
 -- Generate maps from node identifiers to synthdef indexes.
 mk_maps :: Graph -> Maps
 mk_maps (Graph _ cs ks us) =
-    ( M.fromList (zip (map node_id cs) [0..])
-    , ks
-    , M.fromList (zip (map node_id ks) [0..])
-    , M.fromList (zip (map node_id us) [0..]) )
+    (M.fromList (zip (map node_id cs) [0..])
+    ,ks
+    ,M.fromList (zip (map node_id ks) [0..])
+    ,M.fromList (zip (map node_id us) [0..]))
 
 -- Locate index in map given node identifer.
 fetch :: NodeId -> Map -> Int
 fetch = M.findWithDefault (error "fetch")
 
 data Input = Input Int Int
-             deriving (Eq, Show)
+             deriving (Eq,Show)
 
 -- For controls we need to know not the overall index
 -- but in relation to controls of the same type.
@@ -228,15 +272,16 @@
 
 -- Construct input form required by byte-code generator.
 make_input :: Maps -> FromPort -> Input
-make_input (cs, _, _, _) (C n) = Input (-1) (fetch n cs)
-make_input (_, ks, _, _) (K n t) =
-    let i = case t of
-              K_IR -> 0
-              K_KR -> 1
-              K_TR -> 2
-              K_AR -> 3
-    in Input i (fetch_k n t ks)
-make_input (_, _, _, us) (U n p) = Input (fetch n us) p
+make_input (cs,ks,_,us) fp =
+    case fp of
+      FromPort_C n -> Input (-1) (fetch n cs)
+      FromPort_K n t -> let i = case t of
+                                  K_IR -> 0
+                                  K_KR -> 1
+                                  K_TR -> 2
+                                  K_AR -> 3
+                        in Input i (fetch_k n t ks)
+      FromPort_U n p -> Input (fetch n us) p
 
 -- Byte-encode input value.
 encode_input :: Input -> B.ByteString
@@ -244,43 +289,42 @@
 
 -- Byte-encode control node.
 encode_node_k :: Maps -> Node -> B.ByteString
-encode_node_k (_, _, ks, _) (NodeK n _ nm _ _) =
-    B.concat [ B.pack (str_pstr nm)
-             , encode_i16 (fetch n ks) ]
-encode_node_k _ _ = error "encode_node_k"
+encode_node_k (_,_,ks,_) nd =
+    case nd of
+      NodeK n _ nm _ _ -> B.concat [B.pack (str_pstr nm)
+                                   ,encode_i16 (fetch n ks)]
+      _ -> error "encode_node_k"
 
 -- Byte-encode primitive node.
 encode_node_u :: Maps -> Node -> B.ByteString
-encode_node_u m (NodeU _ r nm i o s _) =
-    let i' = map (encode_input . make_input m) i
-        o' = map (encode_i8 . rateId) o
-        (Special s') = s
-    in B.concat [ B.pack (str_pstr nm)
-                , encode_i8 (rateId r)
-                , encode_i16 (length i)
-                , encode_i16 (length o)
-                , encode_i16 s'
-                , B.concat i'
-                , B.concat o' ]
-encode_node_u _ _ = error "encode_ugen: illegal input"
+encode_node_u m n =
+    case n of
+      NodeU _ r nm i o s _ ->
+          let i' = map (encode_input . make_input m) i
+              o' = map (encode_i8 . rateId) o
+              (Special s') = s
+          in B.concat [B.pack (str_pstr nm)
+                      ,encode_i8 (rateId r)
+                      ,encode_i16 (length i)
+                      ,encode_i16 (length o)
+                      ,encode_i16 s'
+                      ,B.concat i'
+                      ,B.concat o']
+      _ -> error "encode_node_u: illegal input"
 
 -- Construct instrument definition bytecode.
-encode_graphdef :: String -> Graph -> B.ByteString
-encode_graphdef s g =
+encode_graphdef :: Graph -> B.ByteString
+encode_graphdef g =
     let (Graph _ cs ks us) = g
         mm = mk_maps g
-    in B.concat [ encode_str "SCgf"
-                , encode_i32 0
-                , encode_i16 1
-                , B.pack (str_pstr s)
-                , 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)]
 
 type KS_COUNT = (Int,Int,Int,Int)
 
@@ -301,13 +345,13 @@
 implicit ks =
     let (ni,nk,nt,na) = ks_count ks
         mk_n t n o =
-            let (nm, r) = case t of
-                            K_IR -> ("Control", IR)
-                            K_KR -> ("Control", KR)
-                            K_TR -> ("TrigControl", KR)
-                            K_AR -> ("AudioControl", AR)
+            let (nm,r) = case t of
+                            K_IR -> ("Control",IR)
+                            K_KR -> ("Control",KR)
+                            K_TR -> ("TrigControl",KR)
+                            K_AR -> ("AudioControl",AR)
                 i = replicate n r
-            in NodeU (-1) r nm [] i (Special o) defaultID
+            in NodeU (-1) r nm [] i (Special o) NoId
     in [mk_n K_IR ni 0
        ,mk_n K_KR nk ni
        ,mk_n K_TR nt (ni + nk)
@@ -315,7 +359,8 @@
 
 -- Transform mce nodes to mrg nodes
 prepare_root :: UGen -> UGen
-prepare_root u
-    | isMCE u = mrg (mceProxies u)
-    | isMRG u = MRG (prepare_root (mrgLeft u)) (prepare_root (mrgRight u))
-    | otherwise = u
+prepare_root u =
+    case ugenType u of
+      MCE_U -> mrg (mceProxies u)
+      MRG_U -> MRG (prepare_root (mrgLeft u)) (prepare_root (mrgRight u))
+      _ -> u
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
@@ -1,11 +1,17 @@
+-- | Various utility functions, not exported.
 module Sound.SC3.Server.Utilities where
 
+-- | Concatentative application of /f/ at /x/ and /g/ at /y/.
 mk_duples :: (a -> c) -> (b -> c) -> [(a, b)] -> [c]
 mk_duples a b = concatMap (\(x,y) -> [a x, b y])
 
+-- | Concatentative application of /g/ at /x/ and /f/ at length of /y/
+-- and /g/ at each element of /y/.
 mk_duples_l :: (Int -> c) -> (a -> c) -> (b -> c) -> [(a, [b])] -> [c]
 mk_duples_l i a b = concatMap (\(x,y) -> a x : i (length y) : map b y)
 
+-- | Concatentative application of /f/ at /x/ and /g/ at /y/ and /h/
+-- 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.hs b/Sound/SC3/UGen.hs
--- a/Sound/SC3/UGen.hs
+++ b/Sound/SC3/UGen.hs
@@ -1,60 +1,30 @@
 -- | Collection of modules for writing unit-generator graphs.
-module Sound.SC3.UGen (module Sound.SC3.UGen.Analysis,
-                       module Sound.SC3.UGen.Buffer,
-                       module Sound.SC3.UGen.Chaos,
-                       module Sound.SC3.UGen.Composite,
---                       module Sound.SC3.UGen.Composite.Monadic,
-                       module Sound.SC3.UGen.Demand,
---                       module Sound.SC3.UGen.Demand.Monadic,
-                       module Sound.SC3.UGen.DiskIO,
-                       module Sound.SC3.UGen.Envelope,
-                       module Sound.SC3.UGen.Envelope.Construct,
-                       module Sound.SC3.UGen.Enum,
-                       module Sound.SC3.UGen.External,
-                       module Sound.SC3.UGen.External.ATS,
-                       module Sound.SC3.UGen.External.LPC,
-                       module Sound.SC3.UGen.FFT,
---                       module Sound.SC3.UGen.FFT.Monadic,
-                       module Sound.SC3.UGen.Filter,
-                       module Sound.SC3.UGen.Granular,
-                       module Sound.SC3.UGen.Information,
-                       module Sound.SC3.UGen.IO,
-                       module Sound.SC3.UGen.MachineListening,
-                       module Sound.SC3.UGen.Math,
---                       module Sound.SC3.UGen.Noise.Monadic,
-                       module Sound.SC3.UGen.Operator,
-                       module Sound.SC3.UGen.Oscillator,
-                       module Sound.SC3.UGen.Panner,
-                       module Sound.SC3.UGen.Rate,
-                       module Sound.SC3.UGen.UGen,
-                       module Sound.SC3.UGen.UId) where
+module Sound.SC3.UGen (module U) where
 
-import Sound.SC3.UGen.Analysis
-import Sound.SC3.UGen.Buffer
-import Sound.SC3.UGen.Chaos
-import Sound.SC3.UGen.Composite
---import Sound.SC3.UGen.Composite.Monadic
-import Sound.SC3.UGen.Demand
---import Sound.SC3.UGen.Demand.Monadic
-import Sound.SC3.UGen.DiskIO
-import Sound.SC3.UGen.Envelope
-import Sound.SC3.UGen.Envelope.Construct
-import Sound.SC3.UGen.Enum
-import Sound.SC3.UGen.External
-import Sound.SC3.UGen.External.ATS
-import Sound.SC3.UGen.External.LPC
-import Sound.SC3.UGen.FFT
---import Sound.SC3.UGen.FFT.Monadic
-import Sound.SC3.UGen.Filter
-import Sound.SC3.UGen.Granular
-import Sound.SC3.UGen.Information
-import Sound.SC3.UGen.IO
-import Sound.SC3.UGen.Math
-import Sound.SC3.UGen.MachineListening
---import Sound.SC3.UGen.Noise.Monadic
-import Sound.SC3.UGen.Operator
-import Sound.SC3.UGen.Oscillator
-import Sound.SC3.UGen.Panner
-import Sound.SC3.UGen.Rate
-import Sound.SC3.UGen.UGen
-import Sound.SC3.UGen.UId
+import Sound.SC3.UGen.Analysis as U
+import Sound.SC3.UGen.Buffer as U
+import Sound.SC3.UGen.Chaos as U
+import Sound.SC3.UGen.Composite as U
+import Sound.SC3.UGen.Demand as U
+import Sound.SC3.UGen.DiskIO as U
+import Sound.SC3.UGen.Envelope as U
+import Sound.SC3.UGen.Envelope.Construct as U
+import Sound.SC3.UGen.Enum as U
+import Sound.SC3.UGen.External as U
+import Sound.SC3.UGen.External.ATS as U
+import Sound.SC3.UGen.External.LPC as U
+import Sound.SC3.UGen.FFT as U
+import Sound.SC3.UGen.Filter as U
+import Sound.SC3.UGen.Granular as U
+import Sound.SC3.UGen.Help as U
+import Sound.SC3.UGen.Information as U
+import Sound.SC3.UGen.IO as U
+import Sound.SC3.UGen.Math as U
+import Sound.SC3.UGen.MachineListening as U
+import Sound.SC3.UGen.Operator as U
+import Sound.SC3.UGen.Oscillator as U
+import Sound.SC3.UGen.Panner as U
+import Sound.SC3.UGen.Rate as U
+import Sound.SC3.UGen.UGen as U
+import Sound.SC3.UGen.UId as U
+import Sound.SC3.UGen.Wavelets as U
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
@@ -8,10 +8,6 @@
 amplitude :: Rate -> UGen -> UGen -> UGen -> UGen
 amplitude r i at rt = mkOsc r "Amplitude" [i, at, rt] 1
 
--- | Compressor, expander, limiter, gate, ducker.
-compander :: UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
-compander i c t sb sa ct rt = mkFilter "Compander" [i, c, t, sb, sa, ct, rt] 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/Buffer.hs b/Sound/SC3/UGen/Buffer.hs
--- a/Sound/SC3/UGen/Buffer.hs
+++ b/Sound/SC3/UGen/Buffer.hs
@@ -1,6 +1,7 @@
 -- | Unit generators to query, read and write audio buffers.
 module Sound.SC3.UGen.Buffer where
 
+import Sound.SC3.Identifier
 import Sound.SC3.UGen.Enum
 import Sound.SC3.UGen.Rate
 import Sound.SC3.UGen.UGen
@@ -113,16 +114,16 @@
 oscN r bufnum freq phase = mkOsc r "OscN" [bufnum, freq, phase] 1
 
 -- | Buffer playback.
-playBuf :: Int -> UGen -> UGen -> UGen -> UGen -> Loop -> DoneAction -> UGen
-playBuf n b r t s l a = mkOsc AR "PlayBuf" [b, r, t, s, from_loop l, from_done_action a] n
+playBuf :: Int -> Rate -> UGen -> UGen -> UGen -> UGen -> Loop -> DoneAction -> UGen
+playBuf n rt b r t s l a = mkOsc rt "PlayBuf" [b, r, t, s, from_loop l, from_done_action a] n
 
 -- | Buffer recording.
-recordBuf :: UGen -> UGen -> UGen -> UGen -> UGen -> Loop -> UGen -> DoneAction -> UGen -> UGen
-recordBuf b o rl pl r l t a i = mkOscMCE AR "RecordBuf" [b, o, rl, pl, r, from_loop l, t, from_done_action a] i 0
+recordBuf :: Rate -> UGen -> UGen -> UGen -> UGen -> UGen -> Loop -> UGen -> DoneAction -> UGen -> UGen
+recordBuf rt b o rl pl r l t a i = mkOscMCE rt "RecordBuf" [b, o, rl, pl, r, from_loop l, t, from_done_action a] i 0
 
 -- | Triggered buffer shuffler (grain generator).
 tGrains :: Int -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
-tGrains n t b r c d p a i = mkFilter "TGrains" [t, b, r, c, d, p, a, i] n
+tGrains n t b r c d p a i = mkOsc AR "TGrains" [t, b, r, c, d, p, a, i] n
 
 -- | Three variable wavetable oscillator.
 vOsc3 :: Rate -> UGen -> UGen -> UGen -> UGen -> UGen
diff --git a/Sound/SC3/UGen/Chaos.hs b/Sound/SC3/UGen/Chaos.hs
--- a/Sound/SC3/UGen/Chaos.hs
+++ b/Sound/SC3/UGen/Chaos.hs
@@ -64,6 +64,10 @@
 linCongN :: Rate -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
 linCongN r f a c m xi = mkOsc r "LinCongN" [f, a, c, m, xi] 1
 
+-- | The logistic map y = chaosParam * y * (1.0 - y)
+logistic :: Rate -> UGen -> UGen -> UGen -> UGen
+logistic r cp f i = mkOsc r "Logistic" [cp,f,i] 1
+
 -- | Lorenz chaotic generator (linear interpolation).
 lorenzL :: Rate -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
 lorenzL rate freq s r b h xi yi zi = mkOsc rate "LorenzL" [freq, s, r, b, h, xi, yi, zi] 1
diff --git a/Sound/SC3/UGen/Composite.hs b/Sound/SC3/UGen/Composite.hs
--- a/Sound/SC3/UGen/Composite.hs
+++ b/Sound/SC3/UGen/Composite.hs
@@ -4,11 +4,14 @@
 import Control.Monad
 import Data.List
 import Data.List.Split
+import Sound.SC3.Identifier
 import Sound.SC3.UGen.Buffer
+import Sound.SC3.UGen.Enum
 import Sound.SC3.UGen.Filter
 import Sound.SC3.UGen.Information
 import Sound.SC3.UGen.IO
 import Sound.SC3.UGen.Math
+import Sound.SC3.UGen.Noise.ID
 import Sound.SC3.UGen.Oscillator
 import Sound.SC3.UGen.Panner
 import Sound.SC3.UGen.Rate
@@ -35,13 +38,13 @@
 
 -- | Collapse possible mce by summing.
 mix :: UGen -> UGen
-mix = foldl1 (+) . mceChannels
+mix = sum . mceChannels
 
 -- | Mix variant, sum to n channels.
 mixN :: Int -> UGen -> UGen
 mixN n u =
     let xs = transpose (splitEvery n (mceChannels u))
-    in mce (map (foldl1 (+)) xs)
+    in mce (map sum xs)
 
 -- | Construct and sum a set of UGens.
 mixFill :: Int -> (Int -> UGen) -> UGen
@@ -51,10 +54,53 @@
 mixFillM :: (Monad m) => Int -> (Int -> m UGen) -> m UGen
 mixFillM n f = liftM sum (mapM f [0 .. n - 1])
 
+-- | Variant that is randomly pressed.
+mouseButton' :: Rate -> UGen -> UGen -> UGen -> UGen
+mouseButton' rt l r tm =
+    let o = lfClipNoise 'z' rt 1
+    in lag (linLin o (-1) 1 l r) tm
+
+-- | Randomised mouse UGen (see also 'mouseX'' and 'mouseY'').
+mouseR :: ID a => a -> Rate -> UGen -> UGen -> Warp -> UGen -> UGen
+mouseR z rt l r ty tm =
+  let f = case ty of
+            Linear -> linLin
+            Exponential -> linExp
+            _ -> undefined
+  in lag (f (lfNoise1 z rt 1) (-1) 1 l r) tm
+
+-- | Variant that randomly traverses the mouseX space.
+mouseX' :: Rate -> UGen -> UGen -> Warp -> UGen -> UGen
+mouseX' = mouseR 'x'
+
+-- | Variant that randomly traverses the mouseY space.
+mouseY' :: Rate -> UGen -> UGen -> Warp -> UGen -> UGen
+mouseY' = mouseR 'y'
+
 -- | PM oscillator.
 pmOsc :: Rate -> UGen -> UGen -> UGen -> UGen -> UGen
 pmOsc r cf mf pm mp = sinOsc r cf (sinOsc r mf mp * pm)
 
+-- | Scale uni-polar (0,1) input to linear (l,r) range
+urange :: Fractional c => c -> c -> c -> c
+urange l r =
+    let m = r - l
+    in (+ l) . (* m)
+
+-- | Scale bi-polar (-1,1) input to linear (l,r) range
+range :: Fractional c => c -> c -> c -> c
+range l r =
+    let m = (r - l) * 0.5
+        a = m + l
+    in (+ a) . (* m)
+
+-- | Mix one output from many sources
+selectX :: UGen -> UGen -> UGen
+selectX ix xs =
+    let s0 = select (roundTo ix 2) xs
+        s1 = select (trunc ix 2 + 1) xs
+    in xFade2 s0 s1 (fold2 (ix * 2 - 1) 1) 1
+
 -- | Zero indexed audio input buses.
 soundIn :: UGen -> UGen
 soundIn (MCE ns) | all (==1) $ zipWith (-) (tail ns) ns =
@@ -63,8 +109,10 @@
     in' 1 AR (numOutputBuses + n)
 
 -- | Pan a set of channels across the stereo field.
-splay :: UGen -> UGen -> UGen -> UGen -> UGen
-splay i s l c = mix (pan2 i (mce p * s + c) 1) * l * sqrt (1 / n)
-    where n = fromIntegral (mceDegree i)
-          m = n - 1
-          p = map ( (+ (-1.0)) . (* (2 / m)) ) [0 .. m]
+splay :: UGen -> UGen -> UGen -> UGen -> Bool -> UGen
+splay i s l c lc =
+    let n = fromIntegral (mceDegree i)
+        m = n - 1
+        p = map ( (+ (-1.0)) . (* (2 / m)) ) [0 .. m]
+        a = if lc then sqrt (1 / n) else 1
+    in mix (pan2 i (mce p * s + c) 1) * l * a
diff --git a/Sound/SC3/UGen/Composite/ID.hs b/Sound/SC3/UGen/Composite/ID.hs
new file mode 100644
--- /dev/null
+++ b/Sound/SC3/UGen/Composite/ID.hs
@@ -0,0 +1,37 @@
+-- | Explicit identifier functions for composite 'UGen's.
+module Sound.SC3.UGen.Composite.ID where
+
+import Sound.SC3.Identifier
+import Sound.SC3.UGen.Demand.ID
+import Sound.SC3.UGen.Filter
+import Sound.SC3.UGen.Noise.ID
+import Sound.SC3.UGen.UGen
+
+-- | Demand rate (:) function.
+dcons :: ID m => (m,m,m) -> UGen -> UGen -> UGen
+dcons (z0,z1,z2) x xs =
+    let i = dseq z0 1 (mce2 0 1)
+        a = dseq z1 1 (mce2 x xs)
+    in dswitch z2 i a
+
+-- | Count 'mce' channels.
+mceN :: UGen -> UGen
+mceN = constant . length . mceChannels
+
+-- | Randomly select one of several inputs (initialiastion rate).
+iChoose :: ID m => m -> UGen -> UGen
+iChoose e a = select (iRand e 0 (mceN a)) a
+
+-- | 'mce' variant of 'iChoose'.
+iChoose' :: ID m => m -> [UGen] -> UGen
+iChoose' e = iChoose e . mce
+
+-- | Randomly select one of several inputs on trigger.
+tChoose :: ID m => m -> UGen -> UGen -> UGen
+tChoose z t a = select (tIRand z 0 (mceN a) t) a
+
+-- | Randomly select one of several inputs on trigger (weighted).
+tWChoose :: ID m => m -> UGen -> UGen -> UGen -> UGen -> UGen
+tWChoose z t a w n =
+    let i = tWindex z t n w
+    in select i a
diff --git a/Sound/SC3/UGen/Composite/Monadic.hs b/Sound/SC3/UGen/Composite/Monadic.hs
--- a/Sound/SC3/UGen/Composite/Monadic.hs
+++ b/Sound/SC3/UGen/Composite/Monadic.hs
@@ -1,21 +1,37 @@
+-- | Monadic constructors for composite 'UGen's.
 module Sound.SC3.UGen.Composite.Monadic where
 
+import qualified Sound.SC3.UGen.Composite.ID as C
 import Sound.SC3.UGen.Demand.Monadic
 import Sound.SC3.UGen.Filter
 import Sound.SC3.UGen.Noise.Monadic
 import Sound.SC3.UGen.UGen
+import Sound.SC3.UGen.UGen.Lift
 import Sound.SC3.UGen.UId
 
 -- | Demand rate (:) function.
 dcons :: (UId m) => UGen -> UGen -> m UGen
-dcons x xs = do i <- dseq 1 (mce2 0 1)
-                a <- dseq 1 (mce2 x xs)
-                dswitch i a
+dcons x xs = do
+  i <- dseq 1 (mce2 0 1)
+  a <- dseq 1 (mce2 x xs)
+  dswitch i a
 
+-- | 'liftU' of 'C.iChoose'.
+iChoose :: UId m => UGen -> m UGen
+iChoose = liftU C.iChoose
+
+-- | 'liftU' of 'C.iChoose''.
+iChoose' :: UId m => [UGen] -> m UGen
+iChoose' = liftU C.iChoose'
+
+-- | Randomly select one of several inputs.
 tChoose :: (UId m) => UGen -> UGen -> m UGen
-tChoose t a = do r <- tiRand 0 (constant (length (mceChannels a))) t
-                 return (select r a)
+tChoose t a = do
+  r <- tIRand 0 (constant (length (mceChannels a))) t
+  return (select r a)
 
-twChoose :: (UId m) => UGen -> UGen -> UGen -> UGen -> m UGen
-twChoose t a w n = do i <- twindex t n w
-                      return (select i a)
+-- | Randomly select one of several inputs (weighted).
+tWChoose :: (UId m) => UGen -> UGen -> UGen -> UGen -> m UGen
+tWChoose t a w n = do
+  i <- tWindex t n w
+  return (select i a)
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
@@ -12,8 +12,9 @@
 
 -- | Demand results from demand rate ugens.
 demand :: UGen -> UGen -> UGen -> UGen
-demand t r d = mkFilterKeyed "Demand" 0 (t : r : d') (length d')
-    where d' = mceChannels d
+demand t r d =
+    let d' = mceChannels d
+    in mkFilterKeyed "Demand" 0 (t : r : d') (length d')
 
 -- | Demand envlope generator.
 demandEnvGen :: Rate -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> DoneAction -> UGen
diff --git a/Sound/SC3/UGen/Demand/ID.hs b/Sound/SC3/UGen/Demand/ID.hs
--- a/Sound/SC3/UGen/Demand/ID.hs
+++ b/Sound/SC3/UGen/Demand/ID.hs
@@ -1,5 +1,7 @@
+-- | Explicit identifier demand rate 'UGen' functions.
 module Sound.SC3.UGen.Demand.ID where
 
+import Sound.SC3.Identifier
 import Sound.SC3.UGen.Enum
 import Sound.SC3.UGen.Rate
 import Sound.SC3.UGen.UGen
@@ -36,6 +38,13 @@
 -- | Demand rate random selection with no immediate repetition.
 dxrand :: ID i => i -> UGen -> UGen -> UGen
 dxrand z l array = mkOscMCEId z DR "Dxrand" [l] array 1
+
+-- | Demand rate weighted random sequence generator.
+dwrand :: ID i => i -> UGen -> UGen -> UGen -> UGen
+dwrand z l a w =
+    let n = mceDegree a
+        w' = mceExtend n w
+    in mkOscMCEId z DR "Dxrand" (l:w') a 1
 
 -- | Demand rate arithmetic series.
 dseries :: ID i => i -> UGen -> UGen -> UGen -> UGen
diff --git a/Sound/SC3/UGen/Demand/Monadic.hs b/Sound/SC3/UGen/Demand/Monadic.hs
--- a/Sound/SC3/UGen/Demand/Monadic.hs
+++ b/Sound/SC3/UGen/Demand/Monadic.hs
@@ -1,3 +1,5 @@
+-- | Monadic constructors for demand 'UGen's, see also
+-- "Sound.SC3.UGen.Demand.ID".
 module Sound.SC3.UGen.Demand.Monadic where
 
 import Sound.SC3.UGen.UGen
@@ -37,6 +39,10 @@
 -- | Demand rate random selection with no immediate repetition.
 dxrand :: (UId m) => UGen -> UGen -> m UGen
 dxrand = liftU2 D.dxrand
+
+-- | Demand rate weighted random sequence generator.
+dwrand :: (UId m) => UGen -> UGen -> UGen -> m UGen
+dwrand = liftU3 D.dwrand
 
 -- | Demand rate arithmetic series.
 dseries :: (UId m) => UGen -> UGen -> UGen -> m UGen
diff --git a/Sound/SC3/UGen/DiskIO.hs b/Sound/SC3/UGen/DiskIO.hs
--- a/Sound/SC3/UGen/DiskIO.hs
+++ b/Sound/SC3/UGen/DiskIO.hs
@@ -1,3 +1,4 @@
+-- | Disk file input and output UGens.
 module Sound.SC3.UGen.DiskIO where
 
 import Sound.SC3.UGen.Enum
@@ -13,7 +14,6 @@
 --             open, see the @/b_read@ server command).
 --
 --  [@loop@] Whether to loop playback (0, 1)
---
 diskIn :: Int -> UGen -> Loop -> UGen
 diskIn nc bufnum loop = mkOsc AR "DiskIn" [bufnum, from_loop loop] nc
 
@@ -27,6 +27,14 @@
 --  [@rate@] Playback rate
 --
 --  [@loop@] Whether to loop playback (0,1)
---
 vDiskIn :: Int -> UGen -> UGen -> Loop -> UGen
 vDiskIn nc bufnum rate loop = mkOsc AR "VDiskIn" [bufnum, rate, from_loop loop] nc
+
+-- | Stream soundfile to disk.
+--
+--  [@bufnum@] Buffer used for streaming (the file descriptor has to be left
+--             open, see the @/b_write@ server command).
+--
+--  [@output@] Current number of written frames.
+diskOut :: UGen -> UGen -> UGen
+diskOut bufnum inputs = mkOscMCE AR "DiskOut" [bufnum] inputs 1
diff --git a/Sound/SC3/UGen/Envelope.hs b/Sound/SC3/UGen/Envelope.hs
--- a/Sound/SC3/UGen/Envelope.hs
+++ b/Sound/SC3/UGen/Envelope.hs
@@ -8,8 +8,9 @@
 
 -- | Segment based envelope generator.
 envGen :: Rate -> UGen -> UGen -> UGen -> UGen -> DoneAction -> [UGen] -> UGen
-envGen r gate lvl bias scale act pts = mkOsc r "EnvGen" i 1
- where i = [gate, lvl, bias, scale, from_done_action act] ++ pts
+envGen r gate lvl bias scale act pts =
+    let i = [gate, lvl, bias, scale, from_done_action act] ++ pts
+    in mkOsc r "EnvGen" i 1
 
 -- | Line generator.
 line :: Rate -> UGen -> UGen -> UGen -> DoneAction -> UGen
@@ -21,7 +22,7 @@
 
 -- | Free node on trigger.
 freeSelf :: UGen -> UGen
-freeSelf i = mkFilter "FreeSelf" [i] 0
+freeSelf i = mkFilter "FreeSelf" [i] 1
 
 -- | Free node on done action at source.
 freeSelfWhenDone :: UGen -> UGen
@@ -33,11 +34,11 @@
 
 -- | Pause node on trigger.
 pauseSelf :: UGen -> UGen
-pauseSelf i = mkFilter "PauseSelf" [i] 0
+pauseSelf i = mkFilter "PauseSelf" [i] 1
 
 -- | Pause node on done action at source.
 pauseSelfWhenDone :: UGen -> UGen
-pauseSelfWhenDone i = mkFilter "PauseSelfWhenDone" [i] 0
+pauseSelfWhenDone i = mkFilter "PauseSelfWhenDone" [i] 1
 
 -- | One while the source is marked done, else zero.
 done :: UGen -> UGen
@@ -45,7 +46,7 @@
 
 -- | Raise specified done action when input goes silent.
 detectSilence ::  UGen -> UGen -> UGen -> DoneAction -> UGen
-detectSilence i a t act = mkFilter "DetectSilence" [i, a, t, from_done_action act] 0
+detectSilence i a t act = mkFilter "DetectSilence" [i, a, t, from_done_action act] 1
 
 -- | When triggered free specified node.
 free :: UGen -> UGen -> UGen
diff --git a/Sound/SC3/UGen/Envelope/Construct.hs b/Sound/SC3/UGen/Envelope/Construct.hs
--- a/Sound/SC3/UGen/Envelope/Construct.hs
+++ b/Sound/SC3/UGen/Envelope/Construct.hs
@@ -26,17 +26,17 @@
 
 -- | Co-ordinate based static envelope generator.
 envCoord :: [(UGen, UGen)] -> UGen -> UGen -> EnvCurve -> [UGen]
-envCoord bp dur amp c = 
+envCoord bp dur amp c =
     let l = map ((* amp) . snd) bp
         t = map (* dur) (d_dx (map fst bp))
     in env l t (repeat c) (-1) (-1)
 
-{- | Trapezoidal envelope generator.  The arguments are: 1. @shape@
-determines the sustain time as a proportion of @dur@, zero is a
-triangular envelope, one a rectangular envelope; 2. @skew@ determines
-the attack\/decay ratio, zero is an immediate attack and a slow decay,
-one a slow attack and an immediate decay; 3. @duration@ in seconds;
-4. @amplitude@ as linear gain.  -}
+-- | Trapezoidal envelope generator.  The arguments are: 1. @shape@
+-- determines the sustain time as a proportion of @dur@, zero is a
+-- triangular envelope, one a rectangular envelope; 2. @skew@
+-- determines the attack\/decay ratio, zero is an immediate attack and
+-- a slow decay, one a slow attack and an immediate decay;
+-- 3. @duration@ in seconds; 4. @amplitude@ as linear gain.
 envTrapezoid :: UGen -> UGen -> UGen -> UGen -> [UGen]
 envTrapezoid shape skew dur amp =
     let x1 = skew * (1 - shape)
@@ -46,6 +46,7 @@
              , (1, skew >=* 1) ]
     in envCoord bp dur amp EnvLin
 
+-- | Variant 'envPerc' with user specified 'EnvCurve'.
 envPerc' :: UGen -> UGen -> UGen -> (EnvCurve, EnvCurve) -> [UGen]
 envPerc' atk rls lvl (c0, c1) =
     let c = [c0, c1]
@@ -72,6 +73,7 @@
         d = replicate 2 (dur / 2.0)
     in env [0.0, lvl, 0.0] d c (-1.0) (-1.0)
 
+-- | Variant of 'envLinen' with user specified 'EnvCurve'.
 envLinen' :: UGen -> UGen -> UGen -> UGen -> (EnvCurve, EnvCurve, EnvCurve) -> [UGen]
 envLinen' aT sT rT l (c0, c1, c2) =
     env [0, l, l, 0] [aT, sT, rT] [c0, c1, c2] (-1) (-1)
@@ -112,7 +114,7 @@
 env_curve :: EnvCurve -> UGen
 env_curve EnvStep = Constant 0.0
 env_curve EnvLin = Constant 1.0
-env_curve EnvExp = Constant 2.0 
+env_curve EnvExp = Constant 2.0
 env_curve EnvSin = Constant 3.0
 env_curve EnvCos = Constant 4.0
 env_curve (EnvNum _) = Constant 5.0
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
@@ -5,6 +5,10 @@
 import Sound.SC3.UGen.Rate
 import Sound.SC3.UGen.UGen
 
+-- | Emulation of the sound generation hardware of the Atari TIA chip.
+atari2600 :: UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
+atari2600 audc0 audc1 audf0 audf1 audv0 audv1 rate = mkOsc AR "Atari2600" [audc0,audc1,audf0,audf1,audv0,audv1,rate] 1
+
 -- | Resynthesize sinusoidal ATS analysis data.
 atsSynth :: UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
 atsSynth b np ps pk fp m a = mkOsc AR "AtsSynth" [b, np, ps, pk, fp, m, a] 1
@@ -21,6 +25,10 @@
 ayFreqToTone :: Fractional a => a -> a
 ayFreqToTone f = 110300 / (f - 0.5)
 
+-- | 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
+
 -- | Phase modulation oscillator matrix.
 fm7 :: [[UGen]] -> [[UGen]] -> UGen
 fm7 ctl m0d = mkOsc AR "FM7" (concat ctl ++ concat m0d) 6
@@ -33,6 +41,14 @@
 membraneHexagon :: UGen -> UGen -> UGen -> UGen
 membraneHexagon i t l = mkOsc AR "MembraneHexagon" [i, t, l] 1
 
+-- | Metronome
+metro :: Rate -> UGen -> UGen -> UGen
+metro rt bpm nb = mkOsc rt "Metro" [bpm,nb] 1
+
+-- | POKEY Chip Sound Simulator
+mzPokey :: UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
+mzPokey f1 c1 f2 c2 f3 c3 f4 c4 ctl = mkOsc AR "MZPokey" [f1,c1,f2,c2,f3,c3,f4,c4,ctl] 1
+
 -- | Extract cps, rmso and err signals from LPC data.
 lpcVals :: Rate -> UGen -> UGen -> UGen
 lpcVals r b ptr = mkOsc r "LPCVals" [b, ptr] 3
@@ -54,8 +70,8 @@
 stkModalBar rt f i sh sp vg vf mx v tr = mkOsc rt "StkModalBar" [f, i, sh, sp, vg, vf, mx, v, tr] 1
 
 -- | STK bowed string model.
-stkBowed :: Rate -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
-stkBowed rt f pr po vf vg l g = mkOsc rt "StkBowed" [f, pr, po, vf, vg, l, g] 1
+stkBowed :: Rate -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
+stkBowed rt f pr po vf vg l g at dc = mkOsc rt "StkBowed" [f, pr, po, vf, vg, l, g, at, dc] 1
 
 -- | STK mandolin model.
 stkMandolin :: Rate -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
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
@@ -1,19 +1,17 @@
 -- | Reader for ATS analyis data files.
-module Sound.SC3.UGen.External.ATS ( ATS(..)
-                                   , ATSHeader(..)
-                                   , ATSFrame
-                                   , atsRead
-                                   , atsSC3 ) where
+module Sound.SC3.UGen.External.ATS (ATS(..)
+                                   ,ATSHeader(..)
+                                   ,ATSFrame,atsFrames
+                                   ,atsRead) where
 
-import Control.Monad
 import qualified Data.ByteString.Lazy as B
-import Data.List
-import Sound.OpenSoundControl
-import System.IO
+import Data.Int
+import Data.List.Split
+import Sound.OpenSoundControl.Coding.Byte
 
 -- | ATS analysis data.
 data ATS = ATS { atsHeader :: ATSHeader
-               , atsFrames :: [ATSFrame] }
+               , atsData :: [Double] }
            deriving (Eq, Show)
 
 -- | ATS analysis meta-data.
@@ -26,34 +24,66 @@
                            , atsMaxFrequency :: Double
                            , atsAnalysisDuration :: Double
                            , atsFileType :: Int
+                           , atsFrameLength :: Int
                            } deriving (Eq, Show)
 
--- | ATS analysis frame data. 
+-- | ATS analysis frame data.
 type ATSFrame = [Double]
 
+bSep :: Int64 -> Int64 -> B.ByteString -> [B.ByteString]
+bSep n i d =
+    if i == 1
+    then [d]
+    else let (p,q) = B.splitAt n d
+         in p : bSep n (i - 1) q
+
+atsParse :: FilePath -> IO [Double]
+atsParse fn = do
+  d <- B.readFile fn
+  let n = B.length d `div` 8
+      v = B.take 8 d
+      f = get_decoder v
+  return (map f (bSep 8 n d))
+
 -- | Read an ATS data file.
 atsRead :: FilePath -> IO ATS
 atsRead fn = do
-  h <- openFile fn ReadMode
-  v <- B.hGet h 8
-  let reader = get_reader v
-  hdr_r <- replicateM 9 (reader h)
-  let f j = hdr_r !! (j - 1)
+  d <- atsParse fn
+  let f j = d !! j
       g = floor . f
       ft = g 9
       (n, x) = ftype_n ft
       np = g 4
       nf = g 5
       fl = np * n + x
-      hdr = ATSHeader (f 1) (g 2) (g 3) np nf (f 6) (f 7) (f 8) ft
-      get_f = replicateM fl (reader h)
-  d <- replicateM nf get_f
-  hClose h
+      hdr = ATSHeader (f 1) (g 2) (g 3) np nf (f 6) (f 7) (f 8) ft fl
   return (ATS hdr d)
 
+-- | Extract set of 'ATSFrame's from 'ATS'.
+atsFrames :: ATS -> [ATSFrame]
+atsFrames a = splitEvery (atsFrameLength (atsHeader a)) (atsData a)
+
+-- Determine endianess and hence decoder.
+get_decoder :: B.ByteString -> B.ByteString -> Double
+get_decoder v =
+    if decode_f64 v == 123.0
+    then decode_f64
+    else decode_f64 . B.reverse
+
+-- Calculate partial depth and frame constant.
+ftype_n :: Int -> (Int, Int)
+ftype_n n =
+    case n of
+      1 -> (2, 1)
+      2 -> (3, 1)
+      3 -> (2, 26)
+      4 -> (3, 26)
+      _ -> error "ftype_n"
+
+{-
 -- | Analysis data in format required by the sc3 ATS UGens.
 atsSC3 :: ATS -> [Double]
-atsSC3 (ATS h d) = 
+atsSC3 (ATS h d) =
     let f = fromIntegral
         td = transpose d
     in f (atsFileType h) :
@@ -62,31 +92,9 @@
        f (atsWindowSize h) :
        concatMap (td !!) (atsSC3Indices h)
 
--- be
-read_f64 :: Handle -> IO Double
-read_f64 h = liftM decode_f64 (B.hGet h 8)
-
--- le
-read_f64LE :: Handle -> IO Double
-read_f64LE h = liftM (decode_f64 . B.reverse) (B.hGet h 8)
-
--- Determine endianess and hence reader.
-get_reader :: B.ByteString -> (Handle -> IO Double)
-get_reader v = if decode_f64 v == 123.0
-               then read_f64
-               else read_f64LE
-
--- Calculate partial depth and frame constant.
-ftype_n :: Int -> (Int, Int)
-ftype_n 1 = (2, 1)
-ftype_n 2 = (3, 1)
-ftype_n 3 = (2, 26)
-ftype_n 4 = (3, 26)
-ftype_n _ = undefined
-
 -- Indices for track data in the order required by sc3.
 atsSC3Indices :: ATSHeader -> [Int]
-atsSC3Indices h = 
+atsSC3Indices h =
     let np = atsNPartials h
         o = 3 * (np - 1)
         a = [1,4 .. (1 + o)]
@@ -96,3 +104,4 @@
     in if atsFileType h == 4
        then a ++ f ++ p ++ n
        else error "atsSC3Indices: illegal ATS file type (/= 4)"
+-}
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
+import Sound.OpenSoundControl.Coding.Byte
 import System.IO
 
 -- | LPC analysis data.
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
@@ -7,21 +7,25 @@
 import Sound.SC3.UGen.UGen
 
 -- | Fast fourier transform.
-fft :: UGen -> UGen -> UGen -> UGen -> UGen -> UGen
-fft buf i h wt a = mkOsc KR "FFT" [buf,i,h,wt,a] 1
+fft :: UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
+fft buf i h wt a ws = mkOsc KR "FFT" [buf,i,h,wt,a,ws] 1
 
 -- | Variant FFT constructor with default values for hop size, window
--- | type, and active status.
+-- | type, active status and window size.
 fft' :: UGen -> UGen -> UGen
-fft' buf i = fft buf i 0.5 0 1
+fft' buf i = fft buf i 0.5 0 1 0
 
+-- | Outputs signal for @FFT@ chains, without performing FFT.
+fftTrigger :: UGen -> UGen -> UGen -> UGen
+fftTrigger b h p = mkOsc KR "FFTTrigger" [b,h,p] 1
+
 -- | Inverse Fast Fourier Transform.
-ifft :: UGen -> UGen -> UGen
-ifft buf wt = mkOsc AR "IFFT" [buf,wt] 1
+ifft :: UGen -> UGen -> UGen -> UGen
+ifft buf wt ws = mkOsc AR "IFFT" [buf,wt,ws] 1
 
 -- | Variant ifft with default value for window type.
 ifft' :: UGen -> UGen
-ifft' buf = ifft buf 0
+ifft' buf = ifft buf 0 0
 
 -- | Strict convolution of two continuously changing inputs.
 convolution :: UGen -> UGen -> UGen -> UGen
@@ -37,6 +41,8 @@
 packFFTSpec m p = mce (interleave m p)
     where interleave x = concat . zipWith (\a b -> [a,b]) x
 
+-- | Apply function /f/ to each bin of an @FFT@ chain, /f/ receives
+-- magnitude, phase and index and returns a (magnitude,phase).
 pvcollect :: UGen -> UGen -> (UGen -> UGen -> UGen -> (UGen, UGen)) -> UGen -> UGen -> UGen -> UGen
 pvcollect c nf f from to z = packFFT c nf from to z mp
   where m = unpackFFT c nf from to 0
@@ -45,6 +51,7 @@
         e = zipWith3 f m p i
         mp = uncurry packFFTSpec (unzip e)
 
+-- | Complex addition.
 pv_Add :: UGen -> UGen -> UGen
 pv_Add ba bb = mkOsc KR "PV_Add" [ba,bb] 1
 
@@ -60,6 +67,7 @@
 pv_BrickWall :: UGen -> UGen -> UGen
 pv_BrickWall buf wp = mkOsc KR "PV_BrickWall" [buf,wp] 1
 
+-- | Complex plane attack.
 pv_ConformalMap :: UGen -> UGen -> UGen -> UGen
 pv_ConformalMap buf real imag = mkOsc KR "PV_ConformalMap" [buf,real,imag] 1
 
@@ -67,75 +75,99 @@
 pv_Copy :: UGen -> UGen -> UGen
 pv_Copy ba bb = mkOsc KR "PV_Copy" [ba,bb] 1
 
+-- | Copy magnitudes and phases.
 pv_CopyPhase :: UGen -> UGen -> UGen
 pv_CopyPhase ba bb = mkOsc KR "PV_CopyPhase" [ba,bb] 1
 
+-- | Random phase shifting.
 pv_Diffuser :: UGen -> UGen -> UGen
 pv_Diffuser buf trg = mkOsc KR "PV_Diffuser" [buf,trg] 1
 
+-- | FFT onset detector.
 pv_HainsworthFoote :: UGen -> UGen -> UGen -> UGen -> UGen -> UGen
 pv_HainsworthFoote buf h f thr wait = mkOsc AR "PV_HainsworthFoote" [buf,h,f,thr,wait] 1
 
+-- | FFT feature detector for onset detection.
 pv_JensenAndersen :: UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
 pv_JensenAndersen buf sc hfe hfc sf thr wait = mkOsc AR "PV_JensenAndersen" [buf,sc,hfe,hfc,sf,thr,wait] 1
 
+-- | Pass bins which are a local maximum.
 pv_LocalMax :: UGen -> UGen -> UGen
 pv_LocalMax buf thr = mkOsc KR "PV_LocalMax" [buf,thr] 1
 
+-- | Pass bins above a threshold.
 pv_MagAbove :: UGen -> UGen -> UGen
 pv_MagAbove buf thr = mkOsc KR "PV_MagAbove" [buf,thr] 1
 
+-- | Pass bins below a threshold.
 pv_MagBelow :: UGen -> UGen -> UGen
 pv_MagBelow buf thr = mkOsc KR "PV_MagBelow" [buf,thr] 1
 
+-- | Clip bins to a threshold.
 pv_MagClip :: UGen -> UGen -> UGen
 pv_MagClip buf thr = mkOsc KR "PV_MagClip" [buf,thr] 1
 
+-- | Freeze magnitudes.
 pv_MagFreeze :: UGen -> UGen -> UGen
 pv_MagFreeze buf frz = mkOsc KR "PV_MagFreeze" [buf,frz] 1
 
+-- | Multiply magnitudes.
 pv_MagMul :: UGen -> UGen -> UGen
 pv_MagMul ba bb = mkOsc KR "PV_MagMul" [ba,bb] 1
 
+-- | Multiply magnitudes by noise.
 pv_MagNoise :: UGen -> UGen
 pv_MagNoise buf = mkOsc KR "PV_MagNoise" [buf] 1
 
+-- | Shift and stretch magnitude bin position.
 pv_MagShift :: UGen -> UGen -> UGen -> UGen
 pv_MagShift buf str shift = mkOsc KR "PV_MagShift" [buf,str,shift] 1
 
+-- | Average magnitudes across bins.
 pv_MagSmear :: UGen -> UGen -> UGen
 pv_MagSmear buf bins = mkOsc KR "PV_MagSmear" [buf,bins] 1
 
+-- | Square magnitudes.
 pv_MagSquared :: UGen -> UGen
 pv_MagSquared buf = mkOsc KR "PV_MagSquared" [buf] 1
 
+-- | Maximum magnitude.
 pv_Max :: UGen -> UGen -> UGen
 pv_Max ba bb = mkOsc KR "PV_Max" [ba,bb] 1
 
+-- | Minimum magnitude.
 pv_Min :: UGen -> UGen -> UGen
 pv_Min ba bb = mkOsc KR "PV_Min" [ba,bb] 1
 
+-- | Complex multiply.
 pv_Mul :: UGen -> UGen -> UGen
 pv_Mul ba bb = mkOsc KR "PV_Mul" [ba,bb] 1
 
+-- | Shift phase by 270 degrees.
 pv_PhaseShift270 :: UGen -> UGen
 pv_PhaseShift270 buf = mkOsc KR "PV_PhaseShift270" [buf] 1
 
+-- | Shift phase by 90 degrees.
 pv_PhaseShift90 :: UGen -> UGen
 pv_PhaseShift90 buf = mkOsc KR "PV_PhaseShift90" [buf] 1
 
+-- | Shift phase.
 pv_PhaseShift :: UGen -> UGen -> UGen
 pv_PhaseShift buf shift = mkOsc KR "PV_PhaseShift" [buf,shift] 1
 
+-- | Make gaps in spectrum.
 pv_RectComb2 :: UGen -> UGen -> UGen -> UGen -> UGen -> UGen
 pv_RectComb2 ba bb teeth phase width = mkOsc KR "PV_RectComb2" [ba,bb,teeth,phase,width] 1
 
+-- | Make gaps in spectrum.
 pv_RectComb :: UGen -> UGen -> UGen -> UGen -> UGen
 pv_RectComb buf teeth phase width = mkOsc KR "PV_RectComb" [buf,teeth,phase,width] 1
 
+-- | Unpack a single value (magnitude or phase) from an FFT chain
 unpack1FFT :: UGen -> UGen -> UGen -> UGen -> UGen
 unpack1FFT buf size index which = mkOsc DR "Unpack1FFT" [buf, size, index, which] 1
 
+-- | Unpack an FFT chain into separate demand-rate FFT bin streams.
 unpackFFT :: UGen -> UGen -> UGen -> UGen -> UGen -> [UGen]
 unpackFFT c nf from to w = map (\i -> unpack1FFT c nf i w) [from .. to]
 
diff --git a/Sound/SC3/UGen/FFT/ID.hs b/Sound/SC3/UGen/FFT/ID.hs
--- a/Sound/SC3/UGen/FFT/ID.hs
+++ b/Sound/SC3/UGen/FFT/ID.hs
@@ -1,5 +1,7 @@
+-- | Non-deterministic FFT 'UGen's.
 module Sound.SC3.UGen.FFT.ID where
 
+import Sound.SC3.Identifier
 import Sound.SC3.UGen.Rate
 import Sound.SC3.UGen.UGen
 
diff --git a/Sound/SC3/UGen/FFT/Monadic.hs b/Sound/SC3/UGen/FFT/Monadic.hs
--- a/Sound/SC3/UGen/FFT/Monadic.hs
+++ b/Sound/SC3/UGen/FFT/Monadic.hs
@@ -1,3 +1,4 @@
+-- | Monadic constructors for non-deterministic FFT 'UGen's.
 module Sound.SC3.UGen.FFT.Monadic where
 
 import Sound.SC3.UGen.UGen
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
@@ -7,27 +7,27 @@
 
 -- | Allpass filter (no interpolation)
 allpassN :: UGen -> UGen -> UGen -> UGen -> UGen
-allpassN i mt dly dcy = mkFilter "AllpassN" [i, mt, dly, dcy] 1
+allpassN i mt dly dcy = mkFilter "AllpassN" [i,mt,dly,dcy] 1
 
 -- | Allpass filter (linear interpolation)
 allpassL :: UGen -> UGen -> UGen -> UGen -> UGen
-allpassL i mt dly dcy = mkFilter "AllpassL" [i, mt, dly, dcy] 1
+allpassL i mt dly dcy = mkFilter "AllpassL" [i,mt,dly,dcy] 1
 
 -- | Allpass filter (cubic interpolation)
 allpassC :: UGen -> UGen -> UGen -> UGen -> UGen
-allpassC i mt dly dcy = mkFilter "AllpassC" [i, mt, dly, dcy] 1
+allpassC i mt dly dcy = mkFilter "AllpassC" [i,mt,dly,dcy] 1
 
 -- | Basic psychoacoustic amplitude compensation.
 ampComp :: UGen -> UGen -> UGen -> UGen
-ampComp f r e = mkFilter "AmpComp" [f, r, e] 1
+ampComp f r e = mkFilter "AmpComp" [f,r,e] 1
 
 -- | ANSI A-weighting curve psychoacoustic amplitude compensation.
 ampCompA :: UGen -> UGen -> UGen -> UGen -> UGen
-ampCompA f r ma ra = mkFilter "AmpCompA" [f, r, ma, ra] 1
+ampCompA f r ma ra = mkFilter "AmpCompA" [f,r,ma,ra] 1
 
 -- | Bandpass filter
 bpf :: UGen -> UGen -> UGen -> UGen
-bpf i freq rq = mkFilter "BPF" [i, freq, rq] 1
+bpf i freq rq = mkFilter "BPF" [i,freq,rq] 1
 
 -- | Two zero fixed midpass filter.
 bpz2 :: UGen -> UGen
@@ -35,7 +35,7 @@
 
 -- | Band reject filter
 brf :: UGen -> UGen -> UGen -> UGen
-brf i freq rq = mkFilter "BRF" [i, freq, rq] 1
+brf i freq rq = mkFilter "BRF" [i,freq,rq] 1
 
 -- | Two zero fixed midcut filter.
 brz2 :: UGen -> UGen
@@ -43,31 +43,35 @@
 
 -- | Clip input between lower and upper bounds.
 clip :: UGen -> UGen -> UGen -> UGen
-clip i l h = mkFilter "Clip" [i, l, h] 1
+clip i l h = mkFilter "Clip" [i,l,h] 1
 
 -- | Comb filter (no interpolation)
 combN :: UGen -> UGen -> UGen -> UGen -> UGen
-combN i mt dly dcy = mkFilter "CombN" [i, mt, dly, dcy] 1
+combN i mt dly dcy = mkFilter "CombN" [i,mt,dly,dcy] 1
 
 -- | Comb filter (linear interpolation)
 combL :: UGen -> UGen -> UGen -> UGen -> UGen
-combL i mt dly dcy = mkFilter "CombL" [i, mt, dly, dcy] 1
+combL i mt dly dcy = mkFilter "CombL" [i,mt,dly,dcy] 1
 
 -- | Comb filter (cubic interpolation)
 combC :: UGen -> UGen -> UGen -> UGen -> UGen
-combC i mt dly dcy = mkFilter "CombC" [i, mt, dly, dcy] 1
+combC i mt dly dcy = mkFilter "CombC" [i,mt,dly,dcy] 1
 
+-- | Compressor,expander,limiter,gate,ducker.
+compander :: UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
+compander i c t sb sa ct rt = mkFilter "Compander" [i,c,t,sb,sa,ct,rt] 1
+
 -- | Convert signal to modal pitch.
 degreeToKey :: UGen -> UGen -> UGen -> UGen
-degreeToKey b i o = mkFilter "DegreeToKey" [b, i, o] 1
+degreeToKey b i o = mkFilter "DegreeToKey" [b,i,o] 1
 
 -- | Exponential decay.
 decay :: UGen -> UGen -> UGen
-decay i dcy = mkFilter "Decay" [i, dcy] 1
+decay i dcy = mkFilter "Decay" [i,dcy] 1
 
 -- | Exponential decay (equvalent to $decay dcy - decay atk$).
 decay2 :: UGen -> UGen -> UGen -> UGen
-decay2 i atk dcy = mkFilter "Decay2" [i, atk, dcy] 1
+decay2 i atk dcy = mkFilter "Decay2" [i,atk,dcy] 1
 
 -- | Single sample delay.
 delay1 :: UGen -> UGen
@@ -79,36 +83,44 @@
 
 -- | Simple delay line (cubic interpolation).
 delayC :: UGen -> UGen -> UGen -> UGen
-delayC i mt dly = mkFilter "DelayC" [i, mt, dly] 1
+delayC i mt dly = mkFilter "DelayC" [i,mt,dly] 1
 
 -- | Simple delay line (linear interpolation).
 delayL :: UGen -> UGen -> UGen -> UGen
-delayL i mt dly = mkFilter "DelayL" [i, mt, dly] 1
+delayL i mt dly = mkFilter "DelayL" [i,mt,dly] 1
 
 -- | Simple delay line (no interpolation).
 delayN :: UGen -> UGen -> UGen -> UGen
-delayN i mt dly = mkFilter "DelayN" [i, mt, dly] 1
+delayN i mt dly = mkFilter "DelayN" [i,mt,dly] 1
 
+-- | Fold to range.
+fold :: UGen -> UGen -> UGen -> UGen
+fold i j k = mkFilter "Fold" [i,j,k] 1
+
 -- | FOF like filter.
 formlet :: UGen -> UGen -> UGen -> UGen -> UGen
-formlet i f a d = mkFilter "Formlet" [i, f, a, d] 1
+formlet i f a d = mkFilter "Formlet" [i,f,a,d] 1
 
 -- | First order filter section.
 fos :: UGen -> UGen -> UGen -> UGen -> UGen
-fos i a0 a1 b1 = mkFilter "FOS" [i, a0, a1, b1] 1
+fos i a0 a1 b1 = mkFilter "FOS" [i,a0,a1,b1] 1
 
 -- | A simple reverb.
 freeVerb :: UGen -> UGen -> UGen -> UGen -> UGen
-freeVerb i mx room damp = mkFilter "FreeVerb" [i, mx, room, damp] 1
+freeVerb i mx room damp = mkFilter "FreeVerb" [i,mx,room,damp] 1
 
 -- | A simple reverb (two channel).
 freeVerb2 :: UGen -> UGen -> UGen -> UGen -> UGen -> UGen
-freeVerb2 i1 i2 mx room damp = mkFilter "FreeVerb2" [i1, i2, mx, room, damp] 2
+freeVerb2 i1 i2 mx room damp = mkFilter "FreeVerb2" [i1,i2,mx,room,damp] 2
 
 -- | Gate.
 gate :: UGen -> UGen -> UGen
-gate i t = mkFilter "Gate" [i, t] 1
+gate i t = mkFilter "Gate" [i,t] 1
 
+-- | A less-simple reverb.
+gVerb :: UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
+gVerb i rs rt d bw sp dl rl tl mrs = mkFilter "GVerb" [i,rs,rt,d,bw,sp,dl,rl,tl,mrs] 2
+
 -- | Hash input values.
 hasher :: UGen -> UGen
 hasher i = mkFilter "Hasher" [i] 1
@@ -119,7 +131,7 @@
 
 -- | Highpass filter.
 hpf :: UGen -> UGen -> UGen
-hpf i f = mkFilter "HPF" [i, f] 1
+hpf i f = mkFilter "HPF" [i,f] 1
 
 -- | Two point difference filter.
 hpz1 :: UGen -> UGen
@@ -131,51 +143,73 @@
 
 -- | Is signal within specified range.
 inRange :: UGen -> UGen -> UGen -> UGen
-inRange i lo hi = mkFilter "InRange" [i, lo, hi] 1
+inRange i lo hi = mkFilter "InRange" [i,lo,hi] 1
 
 -- | Fixed resonator filter bank.
 klank :: UGen -> UGen -> UGen -> UGen -> UGen -> UGen
-klank i fs fp d s = mkFilterMCER [AR] "Klank" [i, fs, fp, d] s 1
+klank i fs fp d s = mkFilterMCER [AR] "Klank" [i,fs,fp,d] s 1
 
--- | Format frequency, amplitude and decay time data as required for klank.
+-- | Format frequency,amplitude and decay time data as required for klank.
 klankSpec :: [UGen] -> [UGen] -> [UGen] -> UGen
-klankSpec f a p = mce ((concat . transpose) [f, a, p])
+klankSpec f a p = mce ((concat . transpose) [f,a,p])
 
+-- | Variant for non-UGen inputs.
+klankSpec' :: [Double] -> [Double] -> [Double] -> UGen
+klankSpec' f a p =
+    let u = map constant
+    in klankSpec (u f) (u a) (u p)
+
 -- | Simple averaging filter.
 lag :: UGen -> UGen -> UGen
-lag i t = mkFilter "Lag" [i, t] 1
+lag i t = mkFilter "Lag" [i,t] 1
 
 -- | Nested lag filter.
 lag2 :: UGen -> UGen -> UGen
-lag2 i t = mkFilter "Lag2" [i, t] 1
+lag2 i t = mkFilter "Lag2" [i,t] 1
 
 -- | Twice nested lag filter.
 lag3 :: UGen -> UGen -> UGen
-lag3 i t = mkFilter "Lag3" [i, t] 1
+lag3 i t = mkFilter "Lag3" [i,t] 1
 
+-- | Lag variant with separate upward and downward times.
+lagUD :: UGen -> UGen -> UGen -> UGen
+lagUD i t1 t2 = mkFilter "LagUD" [i,t1,t2] 1
+
+-- | Nested lag filter.
+lag2UD :: UGen -> UGen -> UGen -> UGen
+lag2UD i t1 t2 = mkFilter "Lag2UD" [i,t1,t2] 1
+
+-- | Twice nested lag filter.
+lag3UD :: UGen -> UGen -> UGen -> UGen
+lag3UD i t1 t2 = mkFilter "Lag3UD" [i,t1,t2] 1
+
 -- | Last value before chang above threshhold.
 lastValue :: UGen -> UGen -> UGen
-lastValue i t = mkFilter "LastValue" [i, t] 1
+lastValue i t = mkFilter "LastValue" [i,t] 1
 
 -- | Sample and hold.
 latch :: UGen -> UGen -> UGen
-latch i t = mkFilter "Latch" [i, t] 1
+latch i t = mkFilter "Latch" [i,t] 1
 
 -- | Remove DC offset.
 leakDC :: UGen -> UGen -> UGen
-leakDC i coef = mkFilter "LeakDC" [i, coef] 1
+leakDC i coef = mkFilter "LeakDC" [i,coef] 1
 
+-- | Limiter.
+limiter :: UGen -> UGen -> UGen -> UGen
+limiter i l d = mkFilter "Limiter" [i,l,d] 1
+
 -- | Map from one linear range to another linear range.
 linLin :: UGen -> UGen -> UGen -> UGen -> UGen -> UGen
-linLin i sl sh dl dh = mkFilter "LinLin" [i, sl, sh, dl, dh] 1
+linLin i sl sh dl dh = mkFilter "LinLin" [i,sl,sh,dl,dh] 1
 
 -- | Map from a linear range to an exponential range.
 linExp :: UGen -> UGen -> UGen -> UGen -> UGen -> UGen
-linExp i sl sh dl dh = mkFilter "LinExp" [i, sl, sh, dl, dh] 1
+linExp i sl sh dl dh = mkFilter "LinExp" [i,sl,sh,dl,dh] 1
 
 -- | Lowpass filter.
 lpf :: UGen -> UGen -> UGen
-lpf i f = mkFilter "LPF" [i, f] 1
+lpf i f = mkFilter "LPF" [i,f] 1
 
 -- | Two point average filter.
 lpz1 :: UGen -> UGen
@@ -187,87 +221,91 @@
 
 -- | Masks off bits in the mantissa of signal.
 mantissaMask :: UGen -> UGen -> UGen
-mantissaMask i bits = mkFilter "MantissaMask" [i, bits] 1
+mantissaMask i bits = mkFilter "MantissaMask" [i,bits] 1
 
 -- | Median filter.
 median :: UGen -> UGen -> UGen
-median size i = mkFilter "Median" [size, i] 1
+median size i = mkFilter "Median" [size,i] 1
 
+-- | Parametric filter.
+midEQ :: UGen -> UGen -> UGen -> UGen -> UGen
+midEQ i f rq db = mkFilter "MidEQ" [i,f,rq,db] 1
+
 -- | Moog VCF implementation.
 moogFF :: UGen -> UGen -> UGen -> UGen -> UGen
-moogFF i f g r = mkFilter "MoogFF" [i, f, g, r] 1
+moogFF i f g r = mkFilter "MoogFF" [i,f,g,r] 1
 
 -- | Most changed input.
 mostChange :: UGen -> UGen -> UGen
-mostChange a b = mkFilter "MostChange" [a, b] 1
+mostChange a b = mkFilter "MostChange" [a,b] 1
 
 -- | Multiply add ternary operator.
 mulAdd :: UGen -> UGen -> UGen -> UGen
-mulAdd s m a = mkFilter "MulAdd" [s, m, a] 1
+mulAdd s m a = mkFilter "MulAdd" [s,m,a] 1
 
--- | Flattens dynamics.
+-- | Normalizer (flattens dynamics).
 normalizer :: UGen -> UGen -> UGen -> UGen
-normalizer i level dur = mkFilter "Normalizer" [i, level, dur] 1
+normalizer i l d = mkFilter "Normalizer" [i,l,d] 1
 
 -- | One pole filter.
 onePole :: UGen -> UGen -> UGen
-onePole i coef = mkFilter "OnePole" [i, coef] 1
+onePole i coef = mkFilter "OnePole" [i,coef] 1
 
 -- | One zero filter.
 oneZero :: UGen -> UGen -> UGen
-oneZero i coef = mkFilter "OneZero" [i, coef] 1
+oneZero i coef = mkFilter "OneZero" [i,coef] 1
 
 -- | Maximum value.
 peak :: UGen -> UGen -> UGen
-peak t r = mkFilter "Peak" [t, r] 1
+peak t r = mkFilter "Peak" [t,r] 1
 
 -- | Simple time domain pitch shifter.
 pitchShift :: UGen -> UGen -> UGen -> UGen -> UGen -> UGen
-pitchShift i w p d t = mkFilter "PitchShift" [i, w, p, d, t] 1
+pitchShift i w p d t = mkFilter "PitchShift" [i,w,p,d,t] 1
 
 -- | Karplus-Strong synthesis.
 pluck :: UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
-pluck i tr mdl dl dc coef = mkFilter "Pluck" [i, tr, mdl, dl, dc, coef] 1
+pluck i tr mdl dl dc coef = mkFilter "Pluck" [i,tr,mdl,dl,dc,coef] 1
 
 -- | Trigger counter.
 pulseCount :: UGen -> UGen -> UGen
-pulseCount t r = mkFilter "PulseCount" [t, r] 1
+pulseCount t r = mkFilter "PulseCount" [t,r] 1
 
 -- | Pass every nth trigger.
 pulseDivider :: UGen -> UGen -> UGen -> UGen
-pulseDivider t factor start = mkFilter "PulseDivider" [t, factor, start] 1
+pulseDivider t factor start = mkFilter "PulseDivider" [t,factor,start] 1
 
 -- | Linear lag.
 ramp :: UGen -> UGen -> UGen
-ramp i t = mkFilter "Ramp" [i, t] 1
+ramp i t = mkFilter "Ramp" [i,t] 1
 
 -- | Resonant highpass filter.
 rhpf :: UGen -> UGen -> UGen -> UGen
-rhpf i freq rq = mkFilter "RHPF" [i, freq, rq] 1
+rhpf i freq rq = mkFilter "RHPF" [i,freq,rq] 1
 
 -- | Resonant lowpass filter.
 rlpf :: UGen -> UGen -> UGen -> UGen
-rlpf i freq rq = mkFilter "RLPF" [i, freq, rq] 1
+rlpf i freq rq = mkFilter "RLPF" [i,freq,rq] 1
 
 -- | Resonant filter.
 resonz :: UGen -> UGen -> UGen -> UGen
-resonz i freq bwr = mkFilter "Resonz" [i, freq, bwr] 1
+resonz i freq bwr = mkFilter "Resonz" [i,freq,bwr] 1
 
 -- | Ringing filter (equivalent to Resonz).
 ringz :: UGen -> UGen -> UGen -> UGen
-ringz i freq dcy = mkFilter "Ringz" [i, freq, dcy] 1
+ringz i freq dcy = mkFilter "Ringz" [i,freq,dcy] 1
 
 -- | Track maximum level.
 runningMax :: UGen -> UGen -> UGen
-runningMax i t = mkFilter "RunningMax" [i, t] 1
+runningMax i t = mkFilter "RunningMax" [i,t] 1
 
 -- | Track minimum level.
 runningMin :: UGen -> UGen -> UGen
-runningMin i t = mkFilter "RunningMin" [i, t] 1
+runningMin i t = mkFilter "RunningMin" [i,t] 1
 
 -- | Running sum.
 runningSum :: UGen -> UGen -> UGen
-runningSum i n = mkFilter "RunningSum" [i, n] 1
+runningSum i n = mkFilter "RunningSum" [i,n] 1
 
 -- | Select output from array of inputs.
 select :: UGen -> UGen -> UGen
@@ -275,98 +313,111 @@
 
 -- | Send a trigger message from the server back to the all registered clients.
 sendTrig :: UGen -> UGen -> UGen -> UGen
-sendTrig i k v = mkFilter "SendTrig" [i, k, v] 0
+sendTrig i k v = mkFilter "SendTrig" [i,k,v] 0
 
 -- | Send a reply message from the server back to the all registered clients.
 sendReply :: UGen -> UGen -> String -> [UGen] -> UGen
 sendReply i k n v =
     let n' = map (fromIntegral . fromEnum) n
         s = fromIntegral (length n')
-    in mkFilter "SendReply" ([i, k, s] ++ n' ++ v) 0
+    in mkFilter "SendReply" ([i,k,s] ++ n' ++ v) 0
 
 -- | Set-reset flip flop.
 setResetFF :: UGen -> UGen -> UGen
-setResetFF t r = mkFilter "SetResetFF" [t, r] 1
+setResetFF t r = mkFilter "SetResetFF" [t,r] 1
 
 -- | Wave shaper.
 shaper :: UGen -> UGen -> UGen
-shaper b s = mkFilter "Shaper" [b, s] 1
+shaper b s = mkFilter "Shaper" [b,s] 1
 
 -- | Remove transients and higher frequencies.
 slew :: UGen -> UGen -> UGen -> UGen
-slew i up dn = mkFilter "Slew" [i, up, dn] 1
+slew i up dn = mkFilter "Slew" [i,up,dn] 1
 
--- | Second order filter section (biquad). 
+-- | Second order filter section (biquad).
 sos :: UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
-sos i a0 a1 a2 b1 b2 = mkFilter "SOS" [i, a0, a1, a2, b1, b2] 1
+sos i a0 a1 a2 b1 b2 = mkFilter "SOS" [i,a0,a1,a2,b1,b2] 1
 
 -- | Stepper pulse counter.
 stepper :: UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
-stepper t r mn mx s v = mkFilter "Stepper" [t, r, mn, mx, s, v] 1
+stepper t r mn mx s v = mkFilter "Stepper" [t,r,mn,mx,s,v] 1
 
 -- | Triggered linear ramp.
 sweep :: UGen -> UGen -> UGen
-sweep t r = mkFilter "Sweep" [t, r] 1
+sweep t r = mkFilter "Sweep" [t,r] 1
 
--- | Delay trigger by specified interval. 
+-- | Delay trigger by specified interval.
 tDelay :: UGen -> UGen -> UGen
-tDelay i d = mkFilter "TDelay" [i, d] 1
+tDelay i d = mkFilter "TDelay" [i,d] 1
 
 -- | Time since last triggered.
 timer :: UGen -> UGen
 timer t = mkFilter "Timer" [t] 1
- 
+
 -- | Toggle flip flop.
 toggleFF :: UGen -> UGen
 toggleFF t = mkFilter "ToggleFF" [t] 1
 
 -- | When triggered output trigger for specified duration.
 trig :: UGen -> UGen -> UGen
-trig i d = mkFilter "Trig" [i, d] 1
+trig i d = mkFilter "Trig" [i,d] 1
 
 -- | When triggered output unit signal for specified duration.
 trig1 :: UGen -> UGen -> UGen
-trig1 i d = mkFilter "Trig1" [i, d] 1
+trig1 i d = mkFilter "Trig1" [i,d] 1
 
 -- | Two pole filter.
 twoPole :: UGen -> UGen -> UGen -> UGen
-twoPole i freq radius = mkFilter "TwoPole" [i, freq, radius] 1
+twoPole i freq radius = mkFilter "TwoPole" [i,freq,radius] 1
 
 -- | Two zero filter.
 twoZero :: UGen -> UGen -> UGen -> UGen
-twoZero i freq radius = mkFilter "TwoZero" [i, freq, radius] 1
+twoZero i freq radius = mkFilter "TwoZero" [i,freq,radius] 1
 
+-- | Wrap to range.
+wrap :: UGen -> UGen -> UGen -> UGen
+wrap i j k = mkFilter "Wrap" [i,j,k] 1
+
 -- | Index into a table with a signal.
 wrapIndex :: UGen -> UGen -> UGen
-wrapIndex b i = mkFilter "WrapIndex" [b, i] 1
+wrapIndex b i = mkFilter "WrapIndex" [b,i] 1
 
 -- * BEQ filters
 
+-- | Bi-quad low-pass filter.
 bLowPass :: UGen -> UGen -> UGen -> UGen
-bLowPass i f rq = mkFilter "BLowPass" [i, f, rq] 1
+bLowPass i f rq = mkFilter "BLowPass" [i,f,rq] 1
 
+-- | Bi-quad high-pass filter.
 bHiPass :: UGen -> UGen -> UGen -> UGen
-bHiPass i f rq = mkFilter "BHiPass" [i, f, rq] 1
+bHiPass i f rq = mkFilter "BHiPass" [i,f,rq] 1
 
+-- | Bi-quad all-pass filter.
 bAllPass :: UGen -> UGen -> UGen -> UGen
-bAllPass i f rq = mkFilter "BAllPass" [i, f, rq] 1
+bAllPass i f rq = mkFilter "BAllPass" [i,f,rq] 1
 
+-- | Bi-quad band-pass filter.
 bBandPass :: UGen -> UGen -> UGen -> UGen
-bBandPass i f bw = mkFilter "BBandPass" [i, f, bw] 1
+bBandPass i f bw = mkFilter "BBandPass" [i,f,bw] 1
 
+-- | Bi-quad band-stop filter.
 bBandStop :: UGen -> UGen -> UGen -> UGen
-bBandStop i f bw = mkFilter "BBandStop" [i, f, bw] 1
+bBandStop i f bw = mkFilter "BBandStop" [i,f,bw] 1
 
+-- | Bi-quad peak equaliser.
 bPeakEQ :: UGen -> UGen -> UGen -> UGen -> UGen
-bPeakEQ i f rq db = mkFilter "BPeakEQ" [i, f, rq, db] 1
+bPeakEQ i f rq db = mkFilter "BPeakEQ" [i,f,rq,db] 1
 
+-- | Bi-quad low shelf filter.
 bLowShelf :: UGen -> UGen -> UGen -> UGen -> UGen
-bLowShelf i f rs db = mkFilter "BLowShelf" [i, f, rs, db] 1
+bLowShelf i f rs db = mkFilter "BLowShelf" [i,f,rs,db] 1
 
+-- | Bi-quad high shelf filter.
 bHiShelf :: UGen -> UGen -> UGen -> UGen -> UGen
-bHiShelf i f rs db = mkFilter "BHiShelf" [i, f, rs, db] 1
+bHiShelf i f rs db = mkFilter "BHiShelf" [i,f,rs,db] 1
 
-bLowPassCoef :: Floating a => a -> a -> a -> (a, a, a, a, a)
+-- | Calculate coefficients for bi-quad low pass filter.
+bLowPassCoef :: Floating a => a -> a -> a -> (a,a,a,a,a)
 bLowPassCoef sr freq rq =
     let w0 = pi * 2 * freq * (1 / sr)
         cos_w0 = cos w0
@@ -377,4 +428,4 @@
         a1 = i * b0rz
         b1 = cos_w0 * 2 * b0rz
         b2 = (1 - alpha) * negate b0rz
-    in (a0, a1, a0, b1, b2)
+    in (a0,a1,a0,b1,b2)
diff --git a/Sound/SC3/UGen/Help.hs b/Sound/SC3/UGen/Help.hs
new file mode 100644
--- /dev/null
+++ b/Sound/SC3/UGen/Help.hs
@@ -0,0 +1,97 @@
+-- | Functions to provide mediated access to the SC3 help system.
+module Sound.SC3.UGen.Help where
+
+import Control.Exception
+import Control.Monad
+import Data.Char
+import Data.List.Split {- split -}
+import System.IO.Error
+import System.Cmd {- process -}
+import System.Directory {- directory -}
+import System.Environment
+import System.FilePath
+
+-- | Read the environment variable @SC3_HELP@, the default value is
+-- @~\/.local\/share\/SuperCollider@.
+sc3HelpDirectory :: IO String
+sc3HelpDirectory = do
+  r <- tryJust (guard . isDoesNotExistError) (getEnv "SC3_HELP")
+  case r of
+    Right v -> return v
+    _ -> do h <- getEnv "HOME"
+            return (h </> ".local/share/SuperCollider")
+
+-- | Locate path to indicated SC3 class help file.
+--
+-- > sc3HelpDirectory >>= (flip sc3HelpClassFile) "SinOsc"
+sc3HelpClassFile :: FilePath -> String -> IO (Maybe FilePath)
+sc3HelpClassFile d c = do
+  let f = d </> "Classes" </> c <.> "html"
+  e <- doesFileExist f
+  if e then return (Just f) else return Nothing
+
+-- | Generate path to indicated SC3 operator help file.
+--
+-- > sc3HelpOperatorEntry "." "+" == "./Overviews/Operators.html#.+"
+sc3HelpOperatorEntry :: FilePath -> String -> FilePath
+sc3HelpOperatorEntry d o = d </> "Overviews/Operators.html#." ++ o
+
+-- | Generate path to indicated SC3 method help.
+--
+-- > sc3HelpMethod "." '*' ("C","m") == "./Classes/C.html#*m"
+sc3HelpMethod :: FilePath -> Char -> (String,String) -> FilePath
+sc3HelpMethod d z (c,m) = d </> "Classes" </> c <.> "html#" ++ [z] ++ m
+
+-- | Generate path to indicated SC3 class method help.
+--
+-- > sc3HelpClassMethod "." ("C","m") == "./Classes/C.html#*m"
+sc3HelpClassMethod :: FilePath -> (String,String) -> FilePath
+sc3HelpClassMethod d = sc3HelpMethod d '*'
+
+-- | Generate path to indicated SC3 instance method help.
+--
+-- > sc3HelpInstanceMethod "." ("C","m") == "./Classes/C.html#-m"
+sc3HelpInstanceMethod :: FilePath -> (String,String) -> FilePath
+sc3HelpInstanceMethod d = sc3HelpMethod d '-'
+
+-- | The name of the local SC3 Help file documenting `u'.  Deletes
+-- @\@@ to allow use on haddock quoted comments.
+--
+-- > ugenSC3HelpFile (toSC3Name "Collection.*fill")
+-- > ugenSC3HelpFile (toSC3Name "Collection.inject")
+-- > ugenSC3HelpFile (toSC3Name "sinOsc")
+ugenSC3HelpFile :: String -> IO FilePath
+ugenSC3HelpFile x = do
+  let s = filter (`notElem` "@") x
+  d <- sc3HelpDirectory
+  cf <- sc3HelpClassFile d s
+  case splitOn "." s of
+    ["Operator",m] -> return (sc3HelpOperatorEntry d m)
+    [c,'*':m] -> return (sc3HelpClassMethod d (c,m))
+    [c,m] -> return (sc3HelpInstanceMethod d (c,m))
+    _ -> case cf of
+           Just cf' -> return cf'
+           Nothing -> error (show ("ugenSC3HelpFile",d,cf,x,s))
+
+-- | Convert from hsc3 name to SC3 name.
+--
+-- > toSC3Name "sinOsc" == "SinOsc"
+-- > toSC3Name "lfSaw" == "LFSaw"
+-- > toSC3Name "pv_Copy" == "PV_Copy"
+toSC3Name :: String -> String
+toSC3Name nm =
+    case nm of
+      'l':'f':nm' -> "LF"++nm'
+      'p':'v':'_':nm' -> "PV_"++nm'
+      p:q -> toUpper p : q
+      [] -> []
+
+-- | Use x-www-browser to view SC3 help file for `u'.
+--
+-- > viewSC3Help (toSC3Name "Collection.*fill")
+-- > viewSC3Help (toSC3Name "Collection.inject")
+-- > viewSC3Help (toSC3Name "sinOsc")
+viewSC3Help :: String -> IO ()
+viewSC3Help u = do
+  nm <- ugenSC3HelpFile u
+  void (system ("x-www-browser file://" ++ nm))
diff --git a/Sound/SC3/UGen/IO.hs b/Sound/SC3/UGen/IO.hs
--- a/Sound/SC3/UGen/IO.hs
+++ b/Sound/SC3/UGen/IO.hs
@@ -46,9 +46,11 @@
 xOut :: UGen -> UGen -> UGen -> UGen
 xOut bus xfade i = mkFilterMCE "XOut" [bus, xfade] i 0
 
+-- | Write to a shared control bus.
 sharedOut :: UGen -> UGen -> UGen
 sharedOut bus i = mkOscMCE KR "SharedOut" [bus] i 0
 
+-- | Read from a shared control bus.
 sharedIn :: Int -> UGen -> UGen
 sharedIn nc bus = mkOsc KR "SharedIn" [bus] nc
 
@@ -71,6 +73,14 @@
 -- | Control variant.
 trigControl :: Int -> Rate -> UGen
 trigControl nc r = mkOsc r "TrigControl" [] nc
+
+-- | Set the synth's random generator ID.
+randID :: Rate -> UGen -> UGen
+randID r n = mkOsc r "RandID" [n] 1
+
+-- | Set the synth's random generator seed.
+randSeed :: Rate -> UGen -> UGen -> UGen
+randSeed r tr sd = mkOsc r "RandSeed" [tr,sd] 1
 
 -- Local Variables:
 -- truncate-lines:t
diff --git a/Sound/SC3/UGen/MachineListening.hs b/Sound/SC3/UGen/MachineListening.hs
--- a/Sound/SC3/UGen/MachineListening.hs
+++ b/Sound/SC3/UGen/MachineListening.hs
@@ -20,8 +20,9 @@
 
 -- | Translate onset type string to constant UGen value.
 onsetType :: Num a => String -> a
-onsetType s = fromIntegral (fromMaybe 3 (findIndex (== s) t))
-    where t = ["power", "magsum", "complex", "rcomplex", "phase", "wphase", "mkl"]
+onsetType s =
+    let t = ["power", "magsum", "complex", "rcomplex", "phase", "wphase", "mkl"]
+    in fromIntegral (fromMaybe 3 (findIndex (== s) t))
 
 -- | Onset detector.
 onsets :: UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
@@ -39,12 +40,15 @@
 mfcc :: Int -> UGen -> UGen
 mfcc nc b = mkOsc KR "MFCC" [b, constant nc] nc
 
+-- | Spectral Flatness measure.
 specFlatness :: UGen -> UGen
 specFlatness b = mkOsc KR "SpecFlatness" [b] 1
 
+-- | Find a percentile of FFT magnitude spectrum.
 specPcile :: UGen -> UGen -> UGen -> UGen
 specPcile b f i = mkOsc KR "SpecPcile" [b, f, i] 1
 
+-- | Spectral centroid.
 specCentroid :: UGen -> UGen
 specCentroid b = mkOsc KR "SpecCentroid" [b] 1
 
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,6 +1,7 @@
 -- | Non-standard mathematical classes and class instances.
 module Sound.SC3.UGen.Math where
 
+import qualified Foreign.C.Math.Double as M
 import Sound.SC3.UGen.Operator
 import Sound.SC3.UGen.UGen
 
@@ -39,17 +40,88 @@
     (>*) = mkBinaryOperator GT_ (>*)
     (>=*) = mkBinaryOperator GE (>=*)
 
+-- | Variant of 'RealFrac' with non 'Integral' results.
+class RealFracE a where
+  properFractionE :: a -> (a,a)
+  truncateE :: a -> a
+  roundE :: a -> a
+  ceilingE :: a -> 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)
+
+-- | Variant of 'truncatef' (via libc).
+ftruncate :: Double -> Double
+ftruncate = M.trunc
+
+-- | Variant of 'roundf' (via libc).
+fround :: Double -> Double
+fround = M.round
+
+-- | Variant of 'ceilingf' (via libc).
+fceiling :: Double -> Double
+fceiling = M.ceil
+
+-- | Variant of 'floorf' (via libc).
+ffloor :: Double -> Double
+ffloor = M.floor
+
+instance RealFracE Double where
+    properFractionE n =
+        let (i,j) = properFraction n
+        in (fromIntegral (i::Integer),j)
+    truncateE = ftruncate
+    roundE = fround
+    ceilingE = fceiling
+    floorE = ffloor
+
+-- | Variant of @SC3@ @roundTo@ function.
+roundTo_ :: Double -> Double -> Double
+roundTo_ a b = if b == 0 then a else ffloor (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"
+    roundE i = roundTo i 1
+    ceilingE = mkUnaryOperator Ceil fceiling
+    floorE = mkUnaryOperator Floor ffloor
+
+-- | 'UGen' form of 'ceilingE'.
+ceil :: UGen -> UGen
+ceil = ceilingE
+
+-- | 'Floating' form of 'midiCPS'.
+midiCPS' :: Floating a => a -> a
+midiCPS' i = 440.0 * (2.0 ** ((i - 69.0) * (1.0 / 12.0)))
+
 -- | Unary operator class.
 class (Floating a, Ord a) => UnaryOp a where
     ampDb :: a -> a
     ampDb a = log10 a * 20
     asFloat :: a -> a
-    asFloat = undefined
+    asFloat = error "asFloat"
     asInt :: a -> a
-    asInt = undefined
+    asInt = error "asInt"
     bitNot :: a -> a
-    bitNot = undefined
-    ceil :: a -> a
+    bitNot = error "bitNot"
     cpsMIDI :: a -> a
     cpsMIDI a = (log2 (a * (1.0 / 440.0)) * 12.0) + 69.0
     cpsOct :: a -> a
@@ -59,10 +131,9 @@
     dbAmp :: a -> a
     dbAmp a = 10 ** (a * 0.05)
     distort :: a -> a
-    distort = undefined
-    floorE :: a -> a
+    distort = error "distort"
     frac :: a -> a
-    frac = undefined
+    frac = error "frac"
     isNil :: a -> a
     isNil a = if a == 0.0 then 0.0 else 1.0
     log10 :: a -> a
@@ -70,7 +141,7 @@
     log2 :: a -> a
     log2 = logBase 2
     midiCPS :: a -> a
-    midiCPS a = 440.0 * (2.0 ** ((a - 69.0) * (1.0 / 12.0)))
+    midiCPS = midiCPS'
     midiRatio :: a -> a
     midiRatio a = 2.0 ** (a * (1.0 / 12.0))
     notE :: a -> a
@@ -80,30 +151,26 @@
     octCPS :: a -> a
     octCPS a = 440.0 * (2.0 ** (a - 4.75))
     ramp_ :: a -> a
-    ramp_ _ = undefined
+    ramp_ _ = error "ramp_"
     ratioMIDI :: a -> a
     ratioMIDI a = 12.0 * log2 a
     softClip :: a -> a
-    softClip = undefined
+    softClip = error "softClip"
     squared :: a -> a
     squared a = a * a
 
 instance UnaryOp Double where
-    ceil a = fromIntegral (ceiling a :: Integer)
-    floorE a = fromIntegral (floor a :: Integer)
 
 instance UnaryOp UGen where
     ampDb = mkUnaryOperator AmpDb ampDb
     asFloat = mkUnaryOperator AsFloat asFloat
     asInt = mkUnaryOperator AsInt asInt
     bitNot = mkUnaryOperator BitNot bitNot
-    ceil = mkUnaryOperator Ceil ceil
     cpsMIDI = mkUnaryOperator CPSMIDI cpsMIDI
     cpsOct = mkUnaryOperator CPSOct cpsOct
     cubed = mkUnaryOperator Cubed cubed
     dbAmp = mkUnaryOperator DbAmp dbAmp
     distort = mkUnaryOperator Distort distort
-    floorE = mkUnaryOperator Floor floorE
     frac = mkUnaryOperator Frac frac
     isNil = mkUnaryOperator IsNil isNil
     log10 = mkUnaryOperator Log10 log10
@@ -127,11 +194,11 @@
     atan2E :: a -> a -> a
     atan2E a b = atan (b/a)
     bitAnd :: a -> a -> a
-    bitAnd = undefined
+    bitAnd = error "bitAnd"
     bitOr :: a -> a -> a
-    bitOr = undefined
+    bitOr = error "bitOr"
     bitXOr :: a -> a -> a
-    bitXOr = undefined
+    bitXOr = error "bitXOr"
     clip2 :: a -> a -> a
     clip2 a b = clip_ a (-b) b
     difSqr :: a -> a -> a
@@ -139,25 +206,25 @@
     excess :: a -> a -> a
     excess a b = a - clip_ a (-b) b
     exprandRange :: a -> a -> a
-    exprandRange = undefined
+    exprandRange = error "exprandRange"
     fill :: a -> a -> a
-    fill = undefined
+    fill = error "fill"
     firstArg :: a -> a -> a
     firstArg a _ = a
     fold2 :: a -> a -> a
     gcdE :: a -> a -> a
-    gcdE = undefined
+    gcdE = error "gcdE"
     hypot :: a -> a -> a
-    hypot = undefined
+    hypot = error "hypot"
     hypotx :: a -> a -> a
-    hypotx = undefined
+    hypotx = error "hypotx"
     iDiv :: a -> a -> a
-    iDiv = undefined
+    iDiv = error "iDiv"
     lcmE :: a -> a -> a
-    lcmE = undefined
+    lcmE = error "lcmE"
     modE :: a -> a -> a
     randRange :: a -> a -> a
-    randRange = undefined
+    randRange = error "randRange"
     ring1 :: a -> a -> a
     ring1 a b = a * b + a
     ring2 :: a -> a -> a
@@ -166,14 +233,13 @@
     ring3 a b = a * a * b
     ring4 :: a -> a -> a
     ring4 a b = a * a * b - a * b * b
-    roundE :: a -> a -> a
     roundUp :: a -> a -> a
     scaleNeg :: a -> a -> a
     scaleNeg a b = (abs a - a) * b' + a where b' = 0.5 * b + 0.5
     shiftLeft :: a -> a -> a
-    shiftLeft = undefined
+    shiftLeft = error "shiftLeft"
     shiftRight :: a -> a -> a
-    shiftRight = undefined
+    shiftRight = error "shiftRight"
     sqrDif :: a -> a -> a
     sqrDif a b = (a-b) * (a-b)
     sqrSum :: a -> a -> a
@@ -183,67 +249,109 @@
     thresh :: a -> a -> a
     thresh a b = if a <  b then 0 else a
     trunc :: a -> a -> a
-    trunc = undefined
+    trunc = error "trunc"
     unsignedShift :: a -> a -> a
-    unsignedShift = undefined
+    unsignedShift = error "unsignedShift"
     wrap2 :: a -> a -> a
 
+-- | SC3 @%@ does not return negative numbers.
+fmod :: Double -> Double -> Double
+fmod i j =
+    let k = i `M.fmod` j
+    in if k < 0 then fmod (i + j) j else k
+
 instance BinaryOp Double where
-    fold2 a b = fold a (-b) b
-    modE a b = n - floorE n where n = a / b
-    roundE a b = if b == 0 then a else floorE (a/b + 0.5) * b
-    roundUp a b = if b == 0 then a else ceil (a/b + 0.5) * b
-    wrap2 a b = wrap a (-b) b
+    fold2 a b = fold_ a (-b) b
+    modE = fmod
+    roundUp a b = if b == 0 then a else fceiling (a/b + 0.5) * b
+    wrap2 a b = wrap_ a (-b) b
 
 instance BinaryOp UGen where
-    iDiv = mkBinaryOperator IDiv undefined
-    modE = mkBinaryOperator Mod modE
-    bitAnd = mkBinaryOperator BitAnd undefined
-    bitOr = mkBinaryOperator BitOr undefined
-    bitXOr = mkBinaryOperator BitXor undefined
-    lcmE = mkBinaryOperator LCM undefined
-    gcdE = mkBinaryOperator GCD undefined
-    roundE = mkBinaryOperator Round undefined
-    roundUp = mkBinaryOperator RoundUp undefined
-    trunc = mkBinaryOperator Trunc undefined
-    atan2E = mkBinaryOperator Atan2 undefined
-    hypot = mkBinaryOperator Hypot undefined
-    hypotx = mkBinaryOperator Hypotx undefined
-    shiftLeft = mkBinaryOperator ShiftLeft undefined
-    shiftRight = mkBinaryOperator ShiftRight undefined
-    unsignedShift = mkBinaryOperator UnsignedShift undefined
-    fill = mkBinaryOperator Fill undefined
-    ring1 = mkBinaryOperator Ring1 undefined
-    ring2 = mkBinaryOperator Ring2 undefined
-    ring3 = mkBinaryOperator Ring3 undefined
-    ring4 = mkBinaryOperator Ring4 undefined
-    difSqr = mkBinaryOperator DifSqr undefined
-    sumSqr = mkBinaryOperator SumSqr undefined
-    sqrSum = mkBinaryOperator SqrSum undefined
-    sqrDif = mkBinaryOperator SqrDif undefined
-    absDif = mkBinaryOperator AbsDif undefined
-    thresh = mkBinaryOperator Thresh undefined
-    amClip = mkBinaryOperator AMClip undefined
-    scaleNeg = mkBinaryOperator ScaleNeg undefined
-    clip2 = mkBinaryOperator Clip2 undefined
-    excess = mkBinaryOperator Excess undefined
-    fold2 = mkBinaryOperator Fold2 undefined
-    wrap2 = mkBinaryOperator Wrap2 undefined
-    firstArg = mkBinaryOperator FirstArg undefined
-    randRange = mkBinaryOperator RandRange undefined
-    exprandRange = mkBinaryOperator ExpRandRange undefined
+    iDiv = mkBinaryOperator IDiv iDiv
+    modE = mkBinaryOperator Mod fmod
+    bitAnd = mkBinaryOperator BitAnd bitAnd
+    bitOr = mkBinaryOperator BitOr bitOr
+    bitXOr = mkBinaryOperator BitXor bitXOr
+    lcmE = mkBinaryOperator LCM lcmE
+    gcdE = mkBinaryOperator GCD gcdE
+    roundUp = mkBinaryOperator RoundUp roundUp
+    trunc = mkBinaryOperator Trunc trunc
+    atan2E = mkBinaryOperator Atan2 atan2E
+    hypot = mkBinaryOperator Hypot hypot
+    hypotx = mkBinaryOperator Hypotx hypotx
+    shiftLeft = mkBinaryOperator ShiftLeft shiftLeft
+    shiftRight = mkBinaryOperator ShiftRight shiftRight
+    unsignedShift = mkBinaryOperator UnsignedShift unsignedShift
+    fill = mkBinaryOperator Fill fill
+    ring1 = mkBinaryOperator Ring1 ring1
+    ring2 = mkBinaryOperator Ring2 ring2
+    ring3 = mkBinaryOperator Ring3 ring3
+    ring4 = mkBinaryOperator Ring4 ring4
+    difSqr = mkBinaryOperator DifSqr difSqr
+    sumSqr = mkBinaryOperator SumSqr sumSqr
+    sqrSum = mkBinaryOperator SqrSum sqrSum
+    sqrDif = mkBinaryOperator SqrDif sqrDif
+    absDif = mkBinaryOperator AbsDif absDif
+    thresh = mkBinaryOperator Thresh thresh
+    amClip = mkBinaryOperator AMClip amClip
+    scaleNeg = mkBinaryOperator ScaleNeg scaleNeg
+    clip2 = mkBinaryOperator Clip2 clip2
+    excess = mkBinaryOperator Excess excess
+    fold2 = mkBinaryOperator Fold2 fold2
+    wrap2 = mkBinaryOperator Wrap2 wrap2
+    firstArg = mkBinaryOperator FirstArg firstArg
+    randRange = mkBinaryOperator RandRange randRange
+    exprandRange = mkBinaryOperator ExpRandRange exprandRange
 
-wrap :: (UnaryOp a, Ord a) => a -> a -> a -> a
-wrap a b c = if a >= b && a <= c then a else a - r * floorE (a-b)/r 
-    where r = c - b
+-- | 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
+wrap' i j k =
+    let r = j - i
+    in if k >= i && k <= j
+       then k
+       else k - r * ffloor ((k-i) / r)
 
-fold :: (UnaryOp a, Ord a) => a -> a -> a -> a
-fold a b c = if a >= b && a <= c then a else y' + b
-    where r = c - b
-          r' = r + r
-          x = a - b
-          y = x - r' * floorE x/r'
-          y' = if y >= r then r' - y else y
+-- | Generic variant of 'wrap''.
+--
+-- > map (genericWrap (5::Integer) 10) [3..12] == [8,9,5,6,7,8,9,10,6,7]
+genericWrap :: (Ord a, Num a) => a -> a -> a -> a
+genericWrap l r n =
+    let d = r - l
+        f = genericWrap l r
+    in if n < l
+       then f (n + d)
+       else if n > r then f (n - d) else n
 
+-- | 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_ a b c = wrap' b c a
+
+-- | Fold /k/ to within range /(i,j)/, ie. @AbstractFunction.fold@
+--
+-- > map (foldToRange 5 10) [3..12] == [7,6,5,6,7,8,9,10,9,8]
+foldToRange :: (Ord a,Num a) => a -> a -> a -> a
+foldToRange i j =
+    let f n = if n > j
+              then f (j - (n - j))
+              else if n < i
+                   then f (i - (n - i))
+                   else n
+    in f
+
+-- | Variant of 'foldToRange' with @SC3@ argument ordering.
+fold_ :: (Ord a,Num a) => a -> a -> a -> a
+fold_ n i j = foldToRange i j n
+
+-- | Clip /k/ to within range /(i,j)/,
+--
+-- > map (clip' 5 10) [3..12] == [5,5,5,6,7,8,9,10,10,10]
+clip' :: (Ord a) => a -> a -> a -> a
+clip' i j n = if n < i then i else if n > j then j else n
+
+-- | Variant of 'clip'' with @SC3@ argument ordering.
 clip_ :: (Ord a) => a -> a -> a -> a
-clip_ a b c = if a < b then b else if a > c then c else a
+clip_ n i j = clip' i j n
diff --git a/Sound/SC3/UGen/Noise/ID.hs b/Sound/SC3/UGen/Noise/ID.hs
--- a/Sound/SC3/UGen/Noise/ID.hs
+++ b/Sound/SC3/UGen/Noise/ID.hs
@@ -1,5 +1,7 @@
+-- | Non-deterministic noise 'UGen's.
 module Sound.SC3.UGen.Noise.ID where
 
+import Sound.SC3.Identifier
 import Sound.SC3.UGen.Rate
 import Sound.SC3.UGen.UGen
 
@@ -92,16 +94,16 @@
 tExpRand z lo hi trig = mkFilterId z "TExpRand" [lo, hi, trig] 1
 
 -- | Random integer in uniform distribution on trigger.
-tiRand :: ID a => a -> UGen -> UGen -> UGen -> UGen
-tiRand z lo hi trig = mkFilterId z "TIRand" [lo, hi, trig] 1
+tIRand :: ID a => a -> UGen -> UGen -> UGen -> UGen
+tIRand z lo hi trig = mkFilterId z "TIRand" [lo, hi, trig] 1
 
 -- | Random value in uniform distribution on trigger.
 tRand :: ID a => a -> UGen -> UGen -> UGen -> UGen
 tRand z lo hi trig = mkFilterId z "TRand" [lo, hi, trig] 1
 
 -- | Triggered windex.
-twindex :: ID a => a -> UGen -> UGen -> UGen -> UGen
-twindex z i n a = mkFilterMCEId z "TWindex" [i, n] a 1
+tWindex :: ID a => a -> UGen -> UGen -> UGen -> UGen
+tWindex z i n a = mkFilterMCEId z "TWindex" [i, n] a 1
 
 -- | White noise.
 whiteNoise :: ID a => a -> Rate -> UGen
diff --git a/Sound/SC3/UGen/Noise/Monadic.hs b/Sound/SC3/UGen/Noise/Monadic.hs
--- a/Sound/SC3/UGen/Noise/Monadic.hs
+++ b/Sound/SC3/UGen/Noise/Monadic.hs
@@ -1,3 +1,4 @@
+-- | Monadic constructors for noise 'UGen's.
 module Sound.SC3.UGen.Noise.Monadic where
 
 import Sound.SC3.UGen.Rate
@@ -95,16 +96,16 @@
 tExpRand = liftU3 N.tExpRand
 
 -- | Random integer in uniform distribution on trigger.
-tiRand :: (UId m) => UGen -> UGen -> UGen -> m UGen
-tiRand = liftU3 N.tiRand
+tIRand :: (UId m) => UGen -> UGen -> UGen -> m UGen
+tIRand = liftU3 N.tIRand
 
 -- | Random value in uniform distribution on trigger.
 tRand :: (UId m) => UGen -> UGen -> UGen -> m UGen
 tRand = liftU3 N.tRand
 
 -- | Triggered windex.
-twindex :: (UId m) => UGen -> UGen -> UGen -> m UGen
-twindex = liftU3 N.twindex
+tWindex :: (UId m) => UGen -> UGen -> UGen -> m UGen
+tWindex = liftU3 N.tWindex
 
 -- | White noise.
 whiteNoise :: (UId m) => Rate -> m UGen
diff --git a/Sound/SC3/UGen/Operator.hs b/Sound/SC3/UGen/Operator.hs
--- a/Sound/SC3/UGen/Operator.hs
+++ b/Sound/SC3/UGen/Operator.hs
@@ -2,6 +2,7 @@
 module Sound.SC3.UGen.Operator (Unary(..), unaryName,
                                 Binary(..), binaryName) where
 
+-- | Enumeration of @SC3@ unary operator UGens.
 data Unary  = Neg
             | Not
             | IsNil
@@ -58,6 +59,7 @@
             | SCurve
               deriving (Eq, Show, Enum)
 
+-- | Enumeration of @SC3@ unary operator UGens.
 data Binary = Add
             | Sub
             | Mul
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,6 +9,14 @@
 blip :: Rate -> UGen -> UGen -> UGen
 blip r freq nharm = mkOscR [AR] r "Blip" [freq, nharm] 1
 
+-- | Chorusing wavetable oscillator.
+cOsc :: Rate -> UGen -> UGen -> UGen -> UGen
+cOsc r n f b = mkOsc r "COsc" [n,f,b] 1
+
+-- | Create a constant amplitude signal.
+dc :: Rate -> UGen -> UGen
+dc r k = mkOsc r "DC" [k] 1
+
 -- | Formant oscillator.
 formant :: Rate -> UGen -> UGen -> UGen -> UGen
 formant r f0 f bw = mkOscR [AR] r "Formant" [f0, f, bw] 1
@@ -27,14 +35,21 @@
 
 -- | Bank of fixed oscillators.
 klang :: Rate -> UGen -> UGen -> UGen -> UGen
-klang r fs fo a
-    | r == AR = mkOscMCE r "Klang" [fs, fo] a 1
-    | otherwise = undefined
+klang r fs fo a =
+    if r == AR
+    then mkOscMCE r "Klang" [fs, fo] a 1
+    else error "klang: not AR"
 
 -- | Format frequency, amplitude and phase data as required for klang.
 klangSpec :: [UGen] -> [UGen] -> [UGen] -> UGen
 klangSpec f a p = mce ((concat . transpose) [f, a, p])
 
+-- | Variant for non-UGen inputs.
+klangSpec' :: [Double] -> [Double] -> [Double] -> UGen
+klangSpec' f a p =
+    let u = map constant
+    in klangSpec (u f) (u a) (u p)
+
 -- | Upsample control rate signal to audio rate.
 k2A :: UGen -> UGen
 k2A i = mkOsc AR "K2A" [i] 1
@@ -69,7 +84,7 @@
 
 -- | Sawtooth oscillator (band limited).
 saw :: Rate -> UGen -> UGen
-saw r freq = mkOscR [AR] r "Saw" [freq] 1
+saw r freq = mkOscR [AR,KR] r "Saw" [freq] 1
 
 -- | Silence.
 silent :: Int -> UGen
diff --git a/Sound/SC3/UGen/Panner.hs b/Sound/SC3/UGen/Panner.hs
--- a/Sound/SC3/UGen/Panner.hs
+++ b/Sound/SC3/UGen/Panner.hs
@@ -11,9 +11,11 @@
 linPan2 :: UGen -> UGen -> UGen -> UGen
 linPan2 i x level = mkFilter "LinPan2" [i, x, level] 2
 
+-- | Four channel equal power panner.
 pan4 :: UGen -> UGen -> UGen -> UGen -> UGen
 pan4 i x y level = mkFilter "Pan4" [i, x, y, level] 4
 
+-- | Stereo signal balancer.
 balance2 :: UGen -> UGen -> UGen -> UGen -> UGen
 balance2 l r p level = mkFilter "Balance2" [l, r, p, level] 2
 
@@ -21,6 +23,7 @@
 rotate2 :: UGen -> UGen -> UGen -> UGen
 rotate2 x y pos = mkFilter "Rotate2" [x, y, pos] 2
 
+-- | Ambisonic B-format panner.
 panB :: UGen -> UGen -> UGen -> UGen -> UGen
 panB i az el level = mkFilter "PanB" [i, az, el, level] 4
 
@@ -28,6 +31,7 @@
 panB2 :: UGen -> UGen -> UGen -> UGen
 panB2 i az level = mkFilter "PanB2" [i, az, level] 3
 
+-- | 2D Ambisonic B-format panner.
 biPanB2 :: UGen -> UGen -> UGen -> UGen -> UGen
 biPanB2 inA inB azimuth gain = mkFilter "BiPanB2" [inA, inB, azimuth, gain] 3
 
@@ -35,11 +39,14 @@
 decodeB2 :: UGen -> UGen -> UGen -> UGen -> UGen -> UGen
 decodeB2 nc w x y o = mkFilterMCE "DecodeB2" [w, x, y, o] nc 0
 
+-- | Azimuth panner.
 panAz :: Int -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
 panAz nc i p l w o = mkFilter "PanAz" [i, p, l, w, o] nc
 
+-- | Equal power two channel cross fade.
 xFade2 :: UGen -> UGen -> UGen -> UGen -> UGen
 xFade2 inA inB pan level = mkFilter "XFade2" [inA, inB, pan, level] 2
 
+-- | Two channel linear crossfade.
 linXFade2 :: UGen -> UGen -> UGen -> UGen
 linXFade2 inA inB pan = mkFilter "LinXFade2" [inA, inB, pan] 2
diff --git a/Sound/SC3/UGen/Rate.hs b/Sound/SC3/UGen/Rate.hs
--- a/Sound/SC3/UGen/Rate.hs
+++ b/Sound/SC3/UGen/Rate.hs
@@ -1,23 +1,32 @@
 -- | Operating rate definitions and utilities.
-module Sound.SC3.UGen.Rate ( Rate(..)
-                           , rateId
-                           , ar, kr, ir, dr ) where
+module Sound.SC3.UGen.Rate (Rate(..)
+                           ,rateId
+                           ,ar,kr,ir,dr) where
 
 import Data.Function
 
 -- | Operating rate of unit generator.
-data Rate = IR | KR | AR | DR 
+data Rate = IR | KR | AR | DR
             deriving (Eq, Show, Enum, Bounded)
 
 instance Ord Rate where
     compare = compare `on` rate_ord
 
--- | Rate constructors (lower case aliases of upper case data
---   constructors).
-ar, kr, ir, dr :: Rate
+{-# DEPRECATED ar,kr,ir,dr "Aliases to be removed" #-}
+-- | Rate constructors alias.
+ar :: Rate
 ar = AR
+
+-- | Rate constructors alias.
+kr :: Rate
 kr = KR
+
+-- | Rate constructors alias.
+ir :: Rate
 ir = IR
+
+-- | Rate constructors alias.
+dr :: Rate
 dr = DR
 
 -- | Integer rate identifier, as required for scsynth bytecode.
@@ -26,7 +35,9 @@
 
 -- Rates as ordered for filter rate selection.
 rate_ord :: Rate -> Int
-rate_ord IR = 0
-rate_ord KR = 1
-rate_ord AR = 2
-rate_ord DR = 3
+rate_ord r =
+    case r of
+      IR -> 0
+      KR -> 1
+      AR -> 2
+      DR -> 3
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,27 +1,65 @@
+-- | UGen data structure representation and associated functions.
 module Sound.SC3.UGen.UGen where
 
 import Control.Monad
-import qualified Data.Char as C
-import qualified Data.HashTable as H
+import qualified Data.Digest.Murmur32 as H
 import Data.List
+import Data.Maybe
+import Sound.SC3.Identifier
 import Sound.SC3.UGen.Operator
 import Sound.SC3.UGen.Rate
 import Sound.SC3.UGen.UId
 import System.Random
 
--- | Typeclass to constrain UGen identifiers.
-class ID a where
-    resolveID :: a -> Int
+-- * UGen Id type and functions
 
-instance ID Int where
-    resolveID = id
+-- | Data type for internalised identifier at 'UGen'.
+data UGenId = NoId
+            | UserId {userId :: (String,Int)}
+            | SystemId {systemId :: Int}
+              deriving (Eq,Show)
 
-instance ID Char where
-    resolveID = C.ord
+-- | Predicate for 'NoId'.
+isNoId :: UGenId -> Bool
+isNoId i =
+    case i of
+      NoId -> True
+      _ -> False
 
-instance ID UGen where
-    resolveID = hashUGen
+-- | Predicate for 'UserId'.
+isUserId :: UGenId -> Bool
+isUserId i =
+    case i of
+      UserId _ -> True
+      _ -> False
 
+-- | Predicate for 'SystemId'.
+isSystemId :: UGenId -> Bool
+isSystemId i =
+    case i of
+      SystemId _ -> True
+      _ -> False
+
+-- | Hash value to 'Int'.
+hash :: H.Hashable32 a => a -> Int
+hash = fromIntegral . H.asWord32 . H.hash32
+
+-- | Shift from 'UserId' to 'SystemId'.
+userIdProtect :: Int -> UGenId -> UGenId
+userIdProtect k i =
+    case i of
+      UserId j -> SystemId (fromIntegral (hash (show (k,j))))
+      _ -> i
+
+-- | Increment 'UserId'.
+userIdIncr :: Int -> UGenId -> UGenId
+userIdIncr n i =
+        case i of
+          UserId (nm,k) -> UserId (nm,k+n)
+          _ -> i
+
+-- * Unit Generator type
+
 -- | Unit generator.
 data UGen = Constant { constantValue :: Double }
           | Control { controlOperatingRate :: Rate
@@ -33,7 +71,7 @@
                       , ugenInputs :: [UGen]
                       , ugenOutputs :: [Output]
                       , ugenSpecial :: Special
-                      , ugenId :: Int }
+                      , ugenId :: UGenId }
           | Proxy { proxySource :: UGen
                   , proxyIndex :: Int }
           | MCE { mceProxies :: [UGen] }
@@ -41,6 +79,116 @@
                 , mrgRight :: UGen }
             deriving (Eq, Show)
 
+-- * UGen graph functions
+
+-- | Depth first traversal of graph at `u' applying `f' to each node.
+ugenTraverse :: (UGen -> UGen) -> UGen -> UGen
+ugenTraverse f u =
+    let rec = ugenTraverse f
+    in case u of
+         Primitive _ _ i _ _ _ -> f (u {ugenInputs = map rec i})
+         Proxy s _ -> f (u {proxySource = rec s})
+         MCE p -> f (u {mceProxies = map rec p})
+         MRG l r -> f (MRG (rec l) (rec r))
+         _ -> f u
+
+-- | Right fold of UGen graph.
+ugenFoldr :: (UGen -> a -> a) -> a -> UGen -> a
+ugenFoldr f st u =
+    let rec = flip (ugenFoldr f)
+    in case u of
+         Primitive _ _ i _ _ _ -> f u (foldr rec st i)
+         Proxy s _ -> f u (f s st)
+         MCE p -> f u (foldr rec st p)
+         MRG l r -> f u (f l (f r st))
+         _ -> f u st
+
+-- * UGen graph Id reassignment
+
+-- | Collect Ids at UGen graph
+ugenIds :: UGen -> [UGenId]
+ugenIds =
+    let f u = case ugenType u of
+                Primitive_U -> [ugenId u]
+                _ -> []
+    in ugenFoldr ((++) . f) []
+
+-- | Recursive replacement of 'UGenId's according to table.
+ugenReplaceIds :: [(UGenId,UGenId)] -> UGen -> UGen
+ugenReplaceIds m =
+    let f u = case ugenType u of
+                Primitive_U ->
+                    case lookup (ugenId u) m of
+                      Just j -> u {ugenId = j}
+                      Nothing -> u
+                _ -> u
+    in ugenTraverse f
+
+-- | Protect user specified UGen Ids.
+ugenProtectUserId :: Int -> UGen -> UGen
+ugenProtectUserId k =
+    let f u = case ugenType u of
+                Primitive_U -> u {ugenId = userIdProtect k (ugenId u)}
+                _ -> u
+    in ugenTraverse f
+
+-- | 'idHash' variant of 'ugenProtectUserId'.
+uprotect :: ID a => a -> UGen -> UGen
+uprotect e = ugenProtectUserId (idHash e)
+
+-- | Variant of 'uprotect' with subsequent identifiers derived by
+-- incrementing initial identifier.
+uprotect' :: ID a => a -> [UGen] -> [UGen]
+uprotect' e =
+    let n = map (+ idHash e) [1..]
+    in zipWith ugenProtectUserId n
+
+-- | Make /n/ parallel instances of 'UGen' with protected identifiers.
+uclone' :: ID a => a -> Int -> UGen -> [UGen]
+uclone' e n = uprotect' e . replicate n
+
+-- | 'mce' variant of 'uclone''.
+uclone :: ID a => a -> Int -> UGen -> UGen
+uclone e n = mce . uclone' e n
+
+-- | Left to right UGen function composition with user id protection.
+ucompose :: ID a => a -> [UGen -> UGen] -> UGen -> UGen
+ucompose e xs =
+    let go [] u = u
+        go ((f,k):f') u = go f' (ugenProtectUserId k (f u))
+    in go (zip xs [idHash e ..])
+
+-- | Make /n/ sequential instances of `f' with protected Ids.
+useq :: ID a => a -> Int -> (UGen -> UGen) -> UGen -> UGen
+useq e n f = ucompose e (replicate n f)
+
+-- | Increment user specified UGen Ids.
+ugenIncrUserId :: Int -> UGen -> UGen
+ugenIncrUserId k =
+    let f u = case ugenType u of
+                Primitive_U -> u {ugenId = userIdIncr k (ugenId u)}
+                _ -> u
+    in ugenTraverse f
+
+-- | Duplicate `u' `n' times, increment user assigned Ids.
+udup' :: Int -> UGen -> [UGen]
+udup' n u =
+    let g k = ugenIncrUserId k u
+    in u : map g [1..n-1]
+
+-- | 'mce' variant of 'udup''.
+udup :: Int -> UGen -> UGen
+udup n = mce . udup' n
+
+-- * UGen ID Instance
+
+-- | Hash function for unit generators.
+hashUGen :: UGen -> Int
+hashUGen = hash . show
+
+instance ID UGen where
+    resolveID = hashUGen
+
 -- | Unit generator output descriptor.
 type Output = Rate
 
@@ -50,13 +198,6 @@
 
 -- * Unit generator node constructors
 
-defaultID :: Int
-defaultID = (-1)
-
--- | Hash function for unit generators.
-hashUGen :: UGen -> Int
-hashUGen = fromIntegral . H.hashString . show
-
 -- | Constant value node constructor.
 constant :: (Real a) => a -> UGen
 constant = Constant . realToFrac
@@ -74,8 +215,11 @@
 
 -- | Multiple channel expansion node constructor.
 mce :: [UGen] -> UGen
-mce [] = error "mce: empty list"
-mce xs = MCE xs
+mce xs =
+    case xs of
+      [] -> error "mce: empty list"
+      [x] -> x
+      _ -> MCE xs
 
 -- | Multiple root graph node constructor.
 mrg2 :: UGen -> UGen -> UGen
@@ -87,79 +231,82 @@
 
 -- * Unit generator node predicates
 
--- | Constant node predicate.
-isConstant :: UGen -> Bool
-isConstant (Constant _) = True
-isConstant _ = False
-
--- | Control node predicate.
-isControl :: UGen -> Bool
-isControl (Control _ _ _ _) = True
-isControl _ = False
-
--- | Unit generator primitive node predicate.
-isUGen :: UGen -> Bool
-isUGen (Primitive _ _ _ _ _ _) = True
-isUGen _ = False
-
--- | Proxy node predicate.
-isProxy :: UGen -> Bool
-isProxy (Proxy _ _) = True
-isProxy _ = False
+-- | Enumeration of 'UGen' types.
+data UGenType = Constant_U
+              | Control_U
+              | Primitive_U
+              | Proxy_U
+              | MCE_U
+              | MRG_U
+                deriving (Eq,Enum,Bounded,Show)
 
 -- | Multiple channel expansion node predicate.
 isMCE :: UGen -> Bool
-isMCE (MCE _) = True
-isMCE _ = False
+isMCE = (== MCE_U) . ugenType
 
--- | MRG predicate.
-isMRG :: UGen -> Bool
-isMRG (MRG _ _) = True
-isMRG _ = False
+-- | Constant node predicate.
+isConstant :: UGen -> Bool
+isConstant = (== Constant_U) . ugenType
 
+-- | Constant node predicate.
+ugenType :: UGen -> UGenType
+ugenType u =
+    case u of
+      Constant _ -> Constant_U
+      Control _ _ _ _ -> Control_U
+      Primitive _ _ _ _ _ _ -> Primitive_U
+      Proxy _ _ -> Proxy_U
+      MCE _ -> MCE_U
+      MRG _ _ -> MRG_U
+
 -- * Multiple channel expansion
 
 -- | Multiple channel expansion for two inputs.
 mce2 :: UGen -> UGen -> UGen
 mce2 x y = mce [x, y]
 
+-- | Extract two channels from possible MCE.
+mce2c :: UGen -> (UGen,UGen)
+mce2c u =
+    case u of
+      MCE (p:q:_) -> (p,q)
+      _ -> (u,u)
+
 -- | Clone a unit generator (mce . replicateM).
 clone :: (UId m) => Int -> m UGen -> m UGen
 clone n = liftM mce . replicateM n
 
 -- | Number of channels to expand to.
 mceDegree :: UGen -> Int
-mceDegree (MCE l) = length l
-mceDegree (MRG u _) = mceDegree u
-mceDegree _ = error "mceDegree: illegal ugen"
+mceDegree u =
+    case u of
+      MCE l -> length l
+      MRG x _ -> mceDegree x
+      _ -> error "mceDegree: illegal ugen"
 
 -- | Extend UGen to specified degree.
 mceExtend :: Int -> UGen -> [UGen]
-mceExtend n (MCE l) = take n (cycle l)
-mceExtend n (MRG x y) =
-    let (r:rs) = mceExtend n x
-    in MRG r y : rs
-mceExtend n u = replicate n u
+mceExtend n u =
+    case u of
+      MCE l -> take n (cycle l)
+      MRG x y -> let (r:rs) = mceExtend n x
+                 in MRG r y : rs
+      _ -> replicate n u
 
--- | Apply MCE transformation.
-mceTransform :: UGen -> UGen
-mceTransform (Primitive r n i o s d) =
-    let f j = Primitive r n j o s d
-        upr = maximum (map mceDegree (filter isMCE i))
-        i' = transpose (map (mceExtend upr) i)
-    in MCE (map f i')
-mceTransform _ = error "mceTransform: illegal ugen"
+-- | Apply MCE transform to a list of inputs.
+mceInputTransform :: [UGen] -> Maybe [[UGen]]
+mceInputTransform i =
+    if any isMCE i
+    then let n = maximum (map mceDegree (filter isMCE i))
+         in Just (transpose (map (mceExtend n) i))
+    else Nothing
 
--- | Apply MCE transformation if required.
-mceExpand :: UGen -> UGen
-mceExpand (MCE l) = MCE (map mceExpand l)
-mceExpand (MRG x y) = MRG (mceExpand x) y
-mceExpand u =
-    let required (Primitive _ _ i _ _ _) = not (null (filter isMCE i))
-        required _ = False
-    in if required u
-       then mceExpand (mceTransform u)
-       else u
+-- | Build a UGen after MCE transformation of inputs.
+mceBuild :: ([UGen] -> UGen) -> [UGen] -> UGen
+mceBuild f i =
+    case mceInputTransform i of
+      Nothing -> f i
+      Just i' -> MCE (map (mceBuild f) i')
 
 -- | Apply a function to each channel at a unit generator.
 mceMap :: (UGen -> UGen) -> UGen -> UGen
@@ -167,8 +314,10 @@
 
 -- | Apply UGen list operation on MCE contents.
 mceEdit :: ([UGen] -> [UGen]) -> UGen -> UGen
-mceEdit f (MCE l) = MCE (f l)
-mceEdit _ _ = error "mceEdit: non MCE value"
+mceEdit f u =
+    case u of
+      MCE l -> MCE (f l)
+      _ -> error "mceEdit: non MCE value"
 
 -- | Reverse order of channels at MCE.
 mceReverse :: UGen -> UGen
@@ -176,19 +325,22 @@
 
 -- | Obtain indexed channel at MCE.
 mceChannel :: Int -> UGen -> UGen
-mceChannel n (MCE l) = l !! n
-mceChannel _ _ = error "mceChannel: non MCE value"
+mceChannel n u =
+    case u of
+      MCE l -> l !! n
+      _ -> error "mceChannel: non MCE value"
 
 -- | Output channels of UGen as a list.
 mceChannels :: UGen -> [UGen]
-mceChannels (MCE l) = l
-mceChannels (MRG x y) = let (r:rs) = mceChannels x in MRG r y : rs
-mceChannels u = [u]
+mceChannels u =
+    case u of
+      MCE l -> l
+      MRG x y -> let (r:rs) = mceChannels x in MRG r y : rs
+      _ -> [u]
 
 -- | Transpose rows and columns, ie. {{a,b},{c,d}} to {{a,c},{b,d}}.
 mceTranspose :: UGen -> UGen
-mceTranspose =
-    mce . map mce . transpose . map mceChannels . mceChannels
+mceTranspose = mce . map mce . transpose . map mceChannels . mceChannels
 
 -- | Collapse mce by summing (see also mix and mixN).
 mceSum :: UGen -> UGen
@@ -198,161 +350,170 @@
 
 -- | Multiple root graph constructor.
 mrg :: [UGen] -> UGen
-mrg [] = undefined
-mrg [x] = x
-mrg (x:xs) = MRG x (mrg xs)
+mrg u =
+    case u of
+      [] -> error "mrg: null"
+      [x] -> x
+      (x:xs) -> MRG x (mrg xs)
 
 -- * Unit generator function builders
 
 -- | Apply proxy transformation if required.
 proxify :: UGen -> UGen
-proxify u
-    | isMCE u = mce (map proxify (mceProxies u))
-    | isMRG u = mrg [proxify (mrgLeft u), mrgRight u]
-    | isUGen u =
+proxify u =
+    case ugenType u of
+    MCE_U -> mce (map proxify (mceProxies u))
+    MRG_U -> mrg [proxify (mrgLeft u), mrgRight u]
+    Primitive_U ->
         let o = ugenOutputs u
         in case o of
              (_:_:_) -> mce (map (proxy u) [0..(length o - 1)])
              _ -> u
-    | otherwise = error "proxify: illegal ugen"
+    Constant_U -> u
+    _ -> error "proxify: illegal ugen"
 
 -- | Determine the rate of a UGen.
 rateOf :: UGen -> Rate
-rateOf u
-    | isConstant u = IR
-    | isControl u = controlOperatingRate u
-    | isUGen u = ugenRate u
-    | isProxy u = rateOf (proxySource u)
-    | isMCE u = maximum (map rateOf (mceProxies u))
-    | isMRG u = rateOf (mrgLeft u)
-    | otherwise = undefined
+rateOf u =
+    case ugenType u of
+      Constant_U -> IR
+      Control_U -> controlOperatingRate u
+      Primitive_U -> ugenRate u
+      Proxy_U -> rateOf (proxySource u)
+      MCE_U -> maximum (map rateOf (mceChannels u))
+      MRG_U -> rateOf (mrgLeft u)
 
--- True is input is a sink UGen, ie. has no outputs.
+-- | True if input is a sink 'UGen', ie. has no outputs.
 is_sink :: UGen -> Bool
-is_sink u
-    | isUGen u = null (ugenOutputs u)
-    | isMCE u = all is_sink (mceProxies u)
-    | isMRG u = is_sink (mrgLeft u)
-    | otherwise = False
+is_sink u =
+    case ugenType u of
+      Primitive_U -> null (ugenOutputs u)
+      MCE_U -> all is_sink (mceProxies u)
+      MRG_U -> is_sink (mrgLeft u)
+      _ -> False
 
--- Ensure input UGen is valid, ie. not a sink.
+-- | Ensure input 'UGen' is valid, ie. not a sink.
 check_input :: UGen -> UGen
-check_input u = if is_sink u
-                then error ("illegal input: " ++ show u)
-                else u
+check_input u =
+    if is_sink u
+    then error ("illegal input: " ++ show u)
+    else u
 
 -- | Construct proxied and multiple channel expanded UGen.
-mkUGen :: (ID a) =>
-          Rate -> String -> [UGen] -> [Output] -> Special -> a -> UGen
-mkUGen r n i o s z =
-    let u = Primitive r n (map check_input i) o s (resolveID z)
-    in proxify (mceExpand u)
+mkUGen :: Maybe ([Double] -> Double) -> [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
+                  o' = replicate o r'
+                  u = Primitive r' nm h o' s z
+              in if r' `elem` rs
+                 then case cf of
+                        Just cf' ->
+                            if all isConstant h
+                            then Constant (cf' (map constantValue h))
+                            else u
+                        Nothing -> u
+                 else error ("mkUGen: rate restricted: " ++ show (r,rs,nm))
+    in proxify (mceBuild f (map check_input i))
 
+-- | Set of all 'Rate' values.
+all_rates :: [Rate]
+all_rates = [minBound .. maxBound]
+
 -- | Operator UGen constructor.
-mkOperator :: String -> [UGen] -> Int -> UGen
-mkOperator c i s =
-    let r = maximum (map rateOf i)
-    in mkUGen r c i [r] (Special s) defaultID
+mkOperator :: ([Double] -> Double) -> 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 i f a
-    | isConstant a = constant (f (constantValue a))
-    | otherwise = mkOperator "UnaryOpUGen" [a] (fromEnum i)
+mkUnaryOperator i f a =
+    let g [x] = f x
+        g _ = error "mkUnaryOperator: non unary input"
+    in mkOperator g "UnaryOpUGen" [a] (fromEnum i)
 
 -- | Binary math constructor with constant optimization.
 mkBinaryOperator :: Binary -> (Double -> Double -> Double) ->
                     UGen -> UGen -> UGen
 mkBinaryOperator i f a b =
-    if isConstant a && isConstant b
-    then let a' = constantValue a
-             b' = constantValue b
-         in constant (f a' b')
-    else mkOperator "BinaryOpUGen" [a, b] (fromEnum i)
+   let g [x,y] = f x y
+       g _ = error "mkBinaryOperator: non binary input"
+   in mkOperator g "BinaryOpUGen" [a, b] (fromEnum i)
 
-mk_osc :: (ID a) =>
-          [Rate] -> a ->
-          Rate -> String -> [UGen] -> Int -> UGen
+-- | Oscillator constructor with constrained set of operating 'Rate's.
+mk_osc :: [Rate] -> UGenId -> Rate -> String -> [UGen] -> Int -> UGen
 mk_osc rs z r c i o =
     if r `elem` rs
-    then mkUGen r c i (replicate o r) (Special 0) z
+    then mkUGen Nothing rs (Just r) c i o (Special 0) z
     else error ("mk_osc: rate restricted: " ++ show (r, rs, c))
 
--- | Oscillator constructor.
+-- | Oscillator constructor with 'all_rates'.
 mkOsc :: Rate -> String -> [UGen] -> Int -> UGen
-mkOsc = mk_osc [minBound .. maxBound] defaultID
+mkOsc = mk_osc all_rates NoId
 
 -- | Oscillator constructor, rate restricted variant.
 mkOscR :: [Rate] -> Rate -> String -> [UGen] -> Int -> UGen
-mkOscR rs = mk_osc rs defaultID
+mkOscR rs = mk_osc rs NoId
 
+-- | Transform 'String' and 'ID' to a 'UserId'.
+toUserId :: ID a => String -> a -> UGenId
+toUserId nm z = UserId (nm,resolveID z)
+
 -- | Oscillator constructor, setting identifier.
-mkOscId :: (ID a) =>
-           a -> Rate -> String -> [UGen] -> Int -> UGen
-mkOscId = mk_osc [minBound .. maxBound]
+mkOscId :: (ID a) => a -> Rate -> String -> [UGen] -> Int -> UGen
+mkOscId z r nm = mk_osc all_rates (toUserId nm z) r nm
 
-mk_osc_mce :: (ID a) =>
-              a -> Rate -> String -> [UGen] -> UGen -> Int -> UGen
+-- | Provided 'UGenId' variant of 'mkOscMCE'.
+mk_osc_mce :: UGenId -> Rate -> String -> [UGen] -> UGen -> Int -> UGen
 mk_osc_mce z r c i j =
     let i' = i ++ mceChannels j
-    in mk_osc [minBound .. maxBound] z r c i'
+    in mk_osc all_rates z r c i'
 
 -- | Variant oscillator constructor with MCE collapsing input.
 mkOscMCE :: Rate -> String -> [UGen] -> UGen -> Int -> UGen
-mkOscMCE = mk_osc_mce defaultID
+mkOscMCE = mk_osc_mce NoId
 
 -- | Variant oscillator constructor with MCE collapsing input.
-mkOscMCEId :: (ID a) =>
-              a -> Rate -> String -> [UGen] -> UGen -> Int -> UGen
-mkOscMCEId = mk_osc_mce
-
-mk_filter :: (ID a) =>
-             [Rate] -> a -> String -> [UGen] -> Int -> UGen
-mk_filter rs z c i o =
-    let r = maximum (map rateOf i)
-        o'= replicate o r
-    in if r `elem` rs
-       then mkUGen r c i o' (Special 0) z
-       else error ("mk_filter: rate restriceted: " ++ show (r, rs, c))
+mkOscMCEId :: ID a => a -> Rate -> String -> [UGen] -> UGen -> Int -> UGen
+mkOscMCEId z r nm = mk_osc_mce (toUserId nm z) r nm
 
-all_rates :: [Rate]
-all_rates = [minBound .. maxBound]
+-- | Rate constrained filter 'UGen' constructor.
+mk_filter :: [Rate] -> UGenId -> String -> [UGen] -> Int -> UGen
+mk_filter rs z c i o = mkUGen Nothing rs Nothing c i o (Special 0) z
 
--- | Filter UGen constructor.
+-- | Filter 'UGen' constructor.
 mkFilter :: String -> [UGen] -> Int -> UGen
-mkFilter = mk_filter all_rates defaultID
+mkFilter = mk_filter all_rates NoId
 
 -- | Filter UGen constructor.
 mkFilterR :: [Rate] -> String -> [UGen] -> Int -> UGen
-mkFilterR rs = mk_filter rs defaultID
+mkFilterR rs = mk_filter rs NoId
 
 -- | Filter UGen constructor.
 mkFilterId :: (ID a) => a -> String -> [UGen] -> Int -> UGen
-mkFilterId = mk_filter all_rates
+mkFilterId z nm = mk_filter all_rates (toUserId nm z) nm
 
 -- | Variant filter with rate derived from keyed input.
 mkFilterKeyed :: String -> Int -> [UGen] -> Int -> UGen
 mkFilterKeyed c k i o =
     let r = rateOf (i !! k)
-        o' = replicate o r
-    in mkUGen r c i o' (Special 0) defaultID
+    in mkUGen Nothing all_rates (Just r) c i o (Special 0) NoId
 
-mk_filter_mce :: (ID a) => [Rate] -> a ->
-                 String -> [UGen] -> UGen -> Int -> UGen
+-- | Provided 'UGenId' filter with 'mce' input.
+mk_filter_mce :: [Rate] -> UGenId -> String -> [UGen] -> UGen -> Int -> UGen
 mk_filter_mce rs z c i j = mk_filter rs z c (i ++ mceChannels j)
 
 -- | Variant filter constructor with MCE collapsing input.
 mkFilterMCER :: [Rate] -> String -> [UGen] -> UGen -> Int -> UGen
-mkFilterMCER rs = mk_filter_mce rs defaultID
+mkFilterMCER rs = mk_filter_mce rs NoId
 
 -- | Variant filter constructor with MCE collapsing input.
 mkFilterMCE :: String -> [UGen] -> UGen -> Int -> UGen
-mkFilterMCE = mk_filter_mce all_rates defaultID
+mkFilterMCE = mk_filter_mce all_rates NoId
 
 -- | Variant filter constructor with MCE collapsing input.
-mkFilterMCEId :: (ID a) =>
-                 a -> String -> [UGen] -> UGen -> Int -> UGen
-mkFilterMCEId = mk_filter_mce all_rates
+mkFilterMCEId :: ID a => a -> String -> [UGen] -> UGen -> Int -> UGen
+mkFilterMCEId z nm = mk_filter_mce all_rates (toUserId nm z) nm
 
 -- | Information unit generators are very specialized.
 mkInfo :: String -> UGen
@@ -402,11 +563,11 @@
 
 -- Unit generators are integral.
 instance Integral UGen where
-    quot = mkBinaryOperator IDiv undefined
-    rem = mkBinaryOperator Mod undefined
+    quot = mkBinaryOperator IDiv (error "ugen: quot")
+    rem = mkBinaryOperator Mod (error "ugen: rem")
     quotRem a b = (quot a b, rem a b)
-    div = mkBinaryOperator IDiv undefined
-    mod = mkBinaryOperator Mod undefined
+    div = mkBinaryOperator IDiv (error "ugen: div")
+    mod = mkBinaryOperator Mod (error "ugen: mod")
     toInteger (Constant n) = floor n
     toInteger _ = error "toInteger at non-constant UGen"
 
diff --git a/Sound/SC3/UGen/UGen/Lift.hs b/Sound/SC3/UGen/UGen/Lift.hs
--- a/Sound/SC3/UGen/UGen/Lift.hs
+++ b/Sound/SC3/UGen/UGen/Lift.hs
@@ -1,28 +1,24 @@
+-- | Lifting functions from explicit identifier 'UGen' functions to
+-- monadic 'UGen' constructors.
 module Sound.SC3.UGen.UGen.Lift where
 
 import Sound.SC3.UGen.UGen
 import Sound.SC3.UGen.UId
 
 -- | Lift base UGen to monadic form.
-liftU :: (UId m) =>
-         (Int -> a -> UGen) ->
-         (a -> m UGen)
+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 :: (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 :: (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)
@@ -30,7 +26,7 @@
 -- | Lift base UGen to monadic form.
 liftU4 :: (UId m) =>
           (Int -> a -> b -> c -> d -> UGen) ->
-          (a -> b -> c -> d -> m 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
@@ -1,3 +1,5 @@
+-- | Unique identifier class for use by non-deterministic (noise) and
+-- non-sharable (demand) unit generators.
 module Sound.SC3.UGen.UId where
 
 import Control.Monad
diff --git a/Sound/SC3/UGen/Utilities.hs b/Sound/SC3/UGen/Utilities.hs
--- a/Sound/SC3/UGen/Utilities.hs
+++ b/Sound/SC3/UGen/Utilities.hs
@@ -1,26 +1,41 @@
+-- | Internal UGen related functions.
 module Sound.SC3.UGen.Utilities where
 
 import Sound.SC3.UGen.Enum
 import Sound.SC3.UGen.UGen
 
+-- * Un-enumerations.
+
+-- | Resolve 'Loop'.
 from_loop :: Loop -> UGen
-from_loop NoLoop = Constant 0
-from_loop Loop = Constant 1
-from_loop (WithLoop u) = u
+from_loop e =
+    case e of
+      NoLoop -> Constant 0
+      Loop -> Constant 1
+      WithLoop u -> u
 
+-- | Resolve 'Interpolation'.
 from_interpolation :: Interpolation -> UGen
-from_interpolation NoInterpolation = Constant 1
-from_interpolation LinearInterpolation = Constant 2
-from_interpolation CubicInterpolation = Constant 4
-from_interpolation (Interpolation u) = u
+from_interpolation e =
+    case e of
+      NoInterpolation -> Constant 1
+      LinearInterpolation -> Constant 2
+      CubicInterpolation -> Constant 4
+      Interpolation u -> u
 
+-- | Resolve 'DoneAction'.
 from_done_action :: DoneAction -> UGen
-from_done_action DoNothing = Constant 0
-from_done_action PauseSynth = Constant 1
-from_done_action RemoveSynth = Constant 2
-from_done_action (DoneAction u) = u
+from_done_action e =
+    case e of
+      DoNothing -> Constant 0
+      PauseSynth -> Constant 1
+      RemoveSynth -> Constant 2
+      DoneAction u -> u
 
+-- | Resolve 'Warp'.
 from_warp :: Warp -> UGen
-from_warp Linear = Constant 0
-from_warp Exponential = Constant 1
-from_warp (Warp u) = u
+from_warp e =
+    case e of
+      Linear -> Constant 0
+      Exponential -> Constant 1
+      Warp u -> u
diff --git a/Sound/SC3/UGen/Wavelets.hs b/Sound/SC3/UGen/Wavelets.hs
new file mode 100644
--- /dev/null
+++ b/Sound/SC3/UGen/Wavelets.hs
@@ -0,0 +1,30 @@
+-- | Wavelet unit generators (Nick Collins).
+module Sound.SC3.UGen.Wavelets where
+
+import Sound.SC3.UGen.Rate
+import Sound.SC3.UGen.UGen
+
+-- | Forward wavelet transform.
+dwt :: UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
+dwt buf i h wnt a wns wlt = mkOsc KR "DWT" [buf,i,h,wnt,a,wns,wlt] 1
+
+-- | Inverse of 'dwt'.
+idwt :: UGen -> UGen -> UGen -> UGen -> UGen
+idwt buf wnt wns wlt = mkOsc AR "IDWT" [buf,wnt,wns,wlt] 1
+
+-- | Pass wavelets above a threshold, ie. 'pv_MagAbove'.
+wt_MagAbove :: UGen -> UGen -> UGen
+wt_MagAbove buf thr = mkOsc KR "WT_MagAbove" [buf,thr] 1
+
+-- | Pass wavelets with /scale/ above threshold.
+wt_FilterScale :: UGen -> UGen -> UGen
+wt_FilterScale buf wp = mkOsc KR "WT_FilterScale" [buf,wp] 1
+
+-- | Pass wavelets with /time/ above threshold.
+wt_TimeWipe :: UGen -> UGen -> UGen
+wt_TimeWipe buf wp = mkOsc KR "WT_TimeWipe" [buf,wp] 1
+
+-- | Product in /W/ domain, ie. 'pv_Mul'.
+wt_Mul :: UGen -> UGen -> UGen
+wt_Mul ba bb = mkOsc KR "WT_Mul" [ba,bb] 1
+
diff --git a/emacs/hsc3.el b/emacs/hsc3.el
--- a/emacs/hsc3.el
+++ b/emacs/hsc3.el
@@ -1,5 +1,3 @@
-;; hsc3.el - (c) rohan drape, 2006-2008
-
 ;; This mode is implemented as a derivation of `haskell' mode,
 ;; indentation and font locking is courtesy that mode.  The
 ;; inter-process communication is courtesy `comint'.  The symbol at
@@ -10,34 +8,7 @@
 (require 'comint)
 (require 'thingatpt)
 (require 'find-lisp)
-
-(defvar hsc3-buffer
-  "*hsc3*"
-  "*The name of the hsc3 process buffer (default=*hsc3*).")
-
-(defvar hsc3-interpreter
-  "ghci"
-  "*The haskell interpter to use (default=ghci).")
-
-(defvar hsc3-interpreter-arguments
-  (list)
-  "*Arguments to the haskell interpreter (default=none).")
-
-(defvar hsc3-run-control
-  "~/.hsc3.hs"
-  "*Run control file (default=~/.hsc3.hs)")
-
-(defvar hsc3-modules
-  (list "import Control.Concurrent"
-        "import Control.Monad"
-        "import Data.List"
-        "import Sound.OpenSoundControl"
-        "import Sound.SC3"
-        "import qualified Sound.SC3.UGen.Base as B"
-        "import qualified Sound.SC3.UGen.Monadic as M"
-        "import qualified Sound.SC3.UGen.Unsafe as U"
-        "import System.Random")
-  "*List of modules (possibly qualified) to bring into interpreter context.")
+(require 'inf-haskell)
 
 (defvar hsc3-help-directory
   nil
@@ -49,63 +20,25 @@
 
 (make-variable-buffer-local 'hsc3-literate-p)
 
-(defun hsc3-unlit (s)
-  "Remove bird literate marks"
-  (replace-regexp-in-string "^> " "" s))
-
-(defun hsc3-intersperse (e l)
-  (if (null l)
-      '()
-    (cons e (cons (car l) (hsc3-intersperse e (cdr l))))))
-
-(defun hsc3-write-default-run-control ()
-  "Write default run control file if no file exists."
-  (if (not (file-exists-p hsc3-run-control))
-      (with-temp-file
-          hsc3-run-control
-        (mapc 
-         (lambda (s)
-           (insert (concat s "\n")))
-         hsc3-modules))))
-
-(defun hsc3-start-haskell ()
-  "Start haskell."
-  (interactive)
-  (if (comint-check-proc hsc3-buffer)
-      (error "An hsc3 process is already running")
-    (apply
-     'make-comint
-     "hsc3"
-     hsc3-interpreter
-     nil
-     hsc3-interpreter-arguments)
-    (hsc3-see-output))
-  (hsc3-write-default-run-control)
-  (hsc3-send-string (concat ":l " hsc3-run-control))
-  (hsc3-send-string ":set prompt \"hsc3> \""))
-
-(defun hsc3-see-output ()
-  "Show haskell output."
-  (interactive)
-  (when (comint-check-proc hsc3-buffer)
-    (delete-other-windows)
-    (split-window-vertically)
-    (with-current-buffer hsc3-buffer
-      (let ((window (display-buffer (current-buffer))))
-	(goto-char (point-max))
-	(save-selected-window
-	  (set-window-point window (point-max)))))))
-
 (defun hsc3-quit-haskell ()
   "Quit haskell."
   (interactive)
-  (hsc3-send-string ":quit")
-  (sit-for 0.25)
-  (kill-buffer hsc3-buffer)
-  (delete-other-windows))
+  (hsc3-send-string ":quit"))
 
+(defun hsc3-unlit (s)
+  "Remove bird literate marks and preceding comment marker"
+   (replace-regexp-in-string "^[- ]*>" "" s))
+
+(defun hsc3-uncomment (s)
+  "Remove initial comment and Bird-literate markers if present"
+   (replace-regexp-in-string "^[- ]*>*" "" s))
+
+(defun hsc3-remove-non-literates (s)
+  "Remove non-bird literate lines"
+  (replace-regexp-in-string "^[^>]*$" "" s))
+
 (defun hsc3-help ()
-  "Lookup up the name at point in the Help files."
+  "Lookup up the name at point in the hsc3 help files."
   (interactive)
   (mapc (lambda (filename)
 	  (find-file-other-window filename))
@@ -114,6 +47,19 @@
 				      (thing-at-point 'symbol)
 				      "\\.help\\.lhs"))))
 
+(defun hsc3-sc3-help ()
+  "Lookup up the name at point in the SC3 help files."
+  (interactive)
+  (hsc3-send-string
+   (format "Sound.SC3.viewSC3Help (Sound.SC3.toSC3Name \"%s\")"
+           (thing-at-point 'symbol))))
+
+(defun hsc3-ugen-summary ()
+  "Lookup up the UGen at point in hsc3-db"
+  (interactive)
+  (hsc3-send-string (format "Sound.SC3.UGen.DB.ugenSummary_ci \"%s\""
+                            (thing-at-point 'symbol))))
+
 (defun hsc3-request-type ()
   "Ask ghci for the type of the name at point."
   (interactive)
@@ -128,21 +74,26 @@
         (list c)
       (cons c (chunk-string n (substring s n))))))
 
+(defun hsc3-cd ()
+  "Change directory at ghci to current value of 'default-directory'."
+  (interactive)
+  (hsc3-send-string (format ":cd %s" default-directory)))
+
+(defun hsc3-load-buffer ()
+  "Load the current buffer."
+  (interactive)
+  (save-buffer)
+  (hsc3-see-haskell)
+  (hsc3-send-string (format ":load \"%s\"" buffer-file-name)))
+
 (defun hsc3-send-string (s)
-  (if (comint-check-proc hsc3-buffer)
+  (if (comint-check-proc inferior-haskell-buffer)
       (let ((cs (chunk-string 64 (concat s "\n"))))
-        (mapcar (lambda (c) (comint-send-string hsc3-buffer c)) cs))
+        (mapcar
+         (lambda (c) (comint-send-string inferior-haskell-buffer c))
+         cs))
     (error "no hsc3 process running?")))
 
-(defun hsc3-transform-and-store (f s)
-  "Transform example text into compilable form."
-  (with-temp-file f
-    (mapc (lambda (module)
-	    (insert (concat module "\n")))
-	  hsc3-modules)
-    (insert "main = do\n")
-    (insert (if hsc3-literate-p (hsc3-unlit s) s))))
-
 (defun hsc3-run-line ()
   "Send the current line to the interpreter."
   (interactive)
@@ -150,33 +101,31 @@
 			      (line-end-position)))
 	 (s* (if hsc3-literate-p
 		 (hsc3-unlit s)
-	       s)))
+	       (hsc3-uncomment s))))
     (hsc3-send-string s*)))
 
+(defun region-string ()
+  "Get region as string (no properties)"
+  (buffer-substring-no-properties (region-beginning)
+                                  (region-end)))
+
+(defun hsc3-concat (l)
+  (apply #'concat l))
+
 (defun hsc3-run-multiple-lines ()
   "Send the current region to the interpreter as a single line."
   (interactive)
-  (let* ((s (buffer-substring-no-properties (region-beginning)
-					    (region-end)))
+  (let* ((s (region-string))
 	 (s* (if hsc3-literate-p
-		 (hsc3-unlit s)
-	       s)))
+		 (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*))))
 
-(defun hsc3-run-region ()
-  "Place the region in a do block and compile."
-  (interactive)
-  (hsc3-transform-and-store
-   "/tmp/hsc3.hs"
-   (buffer-substring-no-properties (region-beginning) (region-end)))
-  (hsc3-send-string ":load \"/tmp/hsc3.hs\"")
-  (hsc3-send-string "main"))
-
-(defun hsc3-load-buffer ()
-  "Load the current buffer."
+(defun hsc3-run-consecutive-lines ()
+  "Send the current region to the interpreter one line at a time."
   (interactive)
-  (save-buffer)
-  (hsc3-send-string (format ":load \"%s\"" buffer-file-name)))
+  (mapcar 'hsc3-send-string
+          (mapcar 'hsc3-unlit (split-string (region-string) "\n"))))
 
 (defun hsc3-run-main ()
   "Run current main."
@@ -184,17 +133,25 @@
   (hsc3-send-string "main"))
 
 (defun hsc3-interrupt-haskell ()
+  "Interrup haskell interpreter"
   (interactive)
-  (if (comint-check-proc hsc3-buffer)
-      (with-current-buffer hsc3-buffer
-	(interrupt-process (get-buffer-process (current-buffer))))
-    (error "no hsc3 process running?")))
+  (if (comint-check-proc inferior-haskell-buffer)
+      (with-current-buffer inferior-haskell-buffer
+        (interrupt-process (get-buffer-process (current-buffer))))
+    (error "no haskell interpreter process running?")))
 
 (defun hsc3-reset-scsynth ()
-  "Reset"
+  "Reset scsynth"
   (interactive)
   (hsc3-send-string "withSC3 reset"))
 
+(defun hsc3-stop ()
+  "Interrup haskell interpreter & reset scsynth"
+  (interactive)
+  (progn
+    (hsc3-interrupt-haskell)
+    (hsc3-reset-scsynth)))
+
 (defun hsc3-status-scsynth ()
   "Status"
   (interactive)
@@ -205,40 +162,55 @@
   (interactive)
   (hsc3-send-string "withSC3 (\fd -> send fd quit)"))
 
+(defun hsc3-update-hsc3-tags ()
+  "Update hsc3 TAGS file, must be run from hsc3 directory."
+  (interactive)
+  (if (file-exists-p "hsc3.cabal")
+      (call-process-shell-command
+       "find Sound . -name '*.*hs' | xargs hasktags -e"
+       nil
+       nil)
+    (error "not at hsc3 directory?")))
+
+(defun hsc3-set-prompt ()
+  "Set ghci prompt to hsc3."
+  (interactive)
+  (hsc3-send-string ":set prompt \"hsc3> \""))
+
+(defun hsc3-see-haskell ()
+ "Show haskell output."
+ (interactive)
+ (let* ((p (inferior-haskell-process))
+        (b (process-buffer p)))
+   (hsc3-set-prompt)
+   (delete-other-windows)
+   (split-window-vertically)
+   (with-current-buffer b
+     (let ((window (display-buffer (current-buffer))))
+       (goto-char (point-max))
+       (save-selected-window
+         (set-window-point window (point-max)))))))
+
 (defvar hsc3-mode-map nil
   "Haskell SuperCollider keymap.")
 
 (defun hsc3-mode-keybindings (map)
   "Haskell SuperCollider keybindings."
-  (define-key map [?\C-c ?\C-s] 'hsc3-start-haskell)
-  (define-key map [?\C-c ?\C-g] 'hsc3-see-output)
-  (define-key map [?\C-c ?\C-x] 'hsc3-quit-haskell)
-  (define-key map [?\C-c ?\C-k] 'hsc3-reset-scsynth)
-  (define-key map [?\C-c ?\C-w] 'hsc3-status-scsynth)
+  (define-key map [?\C-c ?<] 'hsc3-load-buffer)
+  (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 ?\C-r] 'hsc3-run-region)
-  (define-key map [?\C-c ?\C-l] 'hsc3-load-buffer)
+  (define-key map [?\C-c ?\C-r] 'hsc3-run-consecutive-lines)
+  (define-key map [?\C-c ?\C-h] 'hsc3-help)
+  (define-key map [?\C-c ?\C-j] 'hsc3-sc3-help)
   (define-key map [?\C-c ?\C-i] 'hsc3-interrupt-haskell)
+  (define-key map [?\C-c ?\C-k] 'hsc3-reset-scsynth)
   (define-key map [?\C-c ?\C-m] 'hsc3-run-main)
-  (define-key map [?\C-c ?\C-o] 'hsc3-quit-scsynth)
-  (define-key map [?\C-c ?\C-h] 'hsc3-help))
-
-(defun turn-on-hsc3-keybindings ()
-  "Haskell SuperCollider keybindings in the local map."
-  (local-set-key [?\C-c ?\C-s] 'hsc3-start-haskell)
-  (local-set-key [?\C-c ?\C-g] 'hsc3-see-output)
-  (local-set-key [?\C-c ?\C-x] 'hsc3-quit-haskell)
-  (local-set-key [?\C-c ?\C-k] 'hsc3-reset-scsynth)
-  (local-set-key [?\C-c ?\C-w] 'hsc3-status-scsynth)
-  (local-set-key [?\C-c ?\C-c] 'hsc3-run-line)
-  (local-set-key [?\C-c ?\C-e] 'hsc3-run-multiple-lines)
-  (local-set-key [?\C-c ?\C-r] 'hsc3-run-region)
-  (local-set-key [?\C-c ?\C-l] 'hsc3-load-buffer)
-  (local-set-key [?\C-c ?\C-i] 'hsc3-interrupt-haskell)
-  (local-set-key [?\C-c ?\C-m] 'hsc3-run-main)
-  (local-set-key [?\C-c ?\C-o] 'hsc3-quit-scsynth)
-  (local-set-key [?\C-c ?\C-h] 'hsc3-help))
+  (define-key map [?\C-c ?\C-p] 'hsc3-status-scsynth)
+  (define-key map [?\C-c ?\C-q] 'hsc3-quit-haskell)
+  (define-key map [?\C-c ?\C-0] 'hsc3-quit-scsynth)
+  (define-key map [?\C-c ?\C-s] 'hsc3-stop)
+  (define-key map [?\C-c ?\C-u] 'hsc3-ugen-summary))
 
 (defun hsc3-mode-menu (map)
   "Haskell SuperCollider menu."
@@ -248,14 +220,20 @@
     (cons "Help" (make-sparse-keymap "Help")))
   (define-key map [menu-bar hsc3 help hsc3]
     '("Haskell SuperCollider help" . hsc3-help))
+  (define-key map [menu-bar hsc3 help ugen]
+    '("UGen parameter summary" . hsc3-ugen-summary))
   (define-key map [menu-bar hsc3 expression]
     (cons "Expression" (make-sparse-keymap "Expression")))
+  (define-key map [menu-bar hsc3 expression stop]
+    '("Stop (interrupt and reset)" . hsc3-stop))
+  (define-key map [menu-bar hsc3 expression change-directory]
+    '("Change directory" . hsc3-cd))
   (define-key map [menu-bar hsc3 expression load-buffer]
     '("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-region]
-    '("Run region" . hsc3-run-region))
+  (define-key map [menu-bar hsc3 expression run-consecutive-lines]
+    '("Run consecutive lines" . hsc3-run-consecutive-lines))
   (define-key map [menu-bar hsc3 expression run-multiple-lines]
     '("Run multiple lines" . hsc3-run-multiple-lines))
   (define-key map [menu-bar hsc3 expression run-line]
@@ -272,10 +250,10 @@
     (cons "Haskell" (make-sparse-keymap "Haskell")))
   (define-key map [menu-bar hsc3 haskell quit-haskell]
     '("Quit haskell" . hsc3-quit-haskell))
-  (define-key map [menu-bar hsc3 haskell see-output]
-    '("See output" . hsc3-see-output))
-  (define-key map [menu-bar hsc3 haskell start-haskell]
-    '("Start haskell" . hsc3-start-haskell)))
+  (define-key map [menu-bar hsc3 haskell interrupt-haskell]
+    '("Interrupt haskell" . hsc3-interrupt-haskell))
+  (define-key map [menu-bar hsc3 haskell see-haskell]
+    '("See haskell" . hsc3-see-haskell)))
 
 (if hsc3-mode-map
     ()
diff --git a/hsc3.cabal b/hsc3.cabal
--- a/hsc3.cabal
+++ b/hsc3.cabal
@@ -1,9 +1,14 @@
 Name:              hsc3
-Version:           0.9
+Version:           0.11
 Synopsis:          Haskell SuperCollider
-Description:       hsc3 provides Sound.SC3, a haskell module that 
-                   facilitates using haskell as a client to the 
-                   SuperCollider synthesis server.  
+Description:       hsc3 facilitates using haskell as a client to the
+                   SuperCollider synthesis server.
+
+                   For detailed installation and configuration
+                   information please consult the /Tutorial/ and
+                   /Introduction/ documents at
+                   <http://slavepianos.org/rd/ut/hsc3-texts/>
+
 License:           GPL
 Category:          Sound
 Copyright:         (c) Rohan Drape and others, 2006-2011
@@ -11,14 +16,12 @@
 Maintainer:        rd@slavepianos.org
 Stability:         Experimental
 Homepage:          http://slavepianos.org/rd/?t=hsc3
-Tested-With:       GHC == 6.12.1
+Tested-With:       GHC == 7.2.2
 Build-Type:        Simple
-Cabal-Version:     >= 1.6
+Cabal-Version:     >= 1.8
 
 Data-files:        README
                    emacs/hsc3.el
-                   Help/hsc3.help.lhs
-                   Help/tutorial.lhs
                    Help/Server/*.help.lhs
                    Help/UGen/Analysis/*.help.lhs
                    Help/UGen/Buffer/*.help.lhs
@@ -39,19 +42,25 @@
                    Help/UGen/Oscillator/*.help.lhs
                    Help/UGen/Panner/*.help.lhs
                    Help/UGen/Trigger/*.help.lhs
+                   Help/UGen/Wavelets/*.help.lhs
 
 Library
   Build-Depends:   base == 4.*,
                    binary,
                    bytestring,
+                   cmath,
                    containers,
-                   hosc == 0.9,
+                   directory,
+                   filepath,
+                   hosc == 0.11.*,
+                   murmur-hash,
                    network,
                    process,
                    random,
                    split
   GHC-Options:     -Wall -fwarn-tabs
   Exposed-modules: Sound.SC3
+                   Sound.SC3.Identifier
                    Sound.SC3.ID
                    Sound.SC3.Monadic
                    Sound.SC3.Server
@@ -66,6 +75,7 @@
                    Sound.SC3.UGen.Buffer
                    Sound.SC3.UGen.Chaos
                    Sound.SC3.UGen.Composite
+                   Sound.SC3.UGen.Composite.ID
                    Sound.SC3.UGen.Composite.Monadic
                    Sound.SC3.UGen.Demand
                    Sound.SC3.UGen.Demand.ID
@@ -82,6 +92,7 @@
                    Sound.SC3.UGen.FFT.Monadic
                    Sound.SC3.UGen.Filter
                    Sound.SC3.UGen.Granular
+                   Sound.SC3.UGen.Help
                    Sound.SC3.UGen.IO
                    Sound.SC3.UGen.Information
                    Sound.SC3.UGen.MachineListening
@@ -95,6 +106,7 @@
                    Sound.SC3.UGen.UGen
                    Sound.SC3.UGen.UGen.Lift
                    Sound.SC3.UGen.UId
+                   Sound.SC3.UGen.Wavelets
   Other-modules:   Sound.SC3.Server.Utilities
                    Sound.SC3.UGen.Utilities
 
