diff --git a/Help/Server/b_alloc.help.lhs b/Help/Server/b_alloc.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/Server/b_alloc.help.lhs
@@ -0,0 +1,10 @@
+/b_alloc                                Allocate buffer space
+
+int   - buffer number
+int   - number of frames
+int   - number of channels (optional. default = 1 channel)
+bytes - an OSC message to execute upon completion. (optional)
+
+Allocates zero filled buffer to number of channels and samples.
+
+Asynchronous. Replies to sender with /done when complete.
diff --git a/Help/Server/b_allocRead.help.lhs b/Help/Server/b_allocRead.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/Server/b_allocRead.help.lhs
@@ -0,0 +1,15 @@
+/b_allocRead            Allocate buffer space and read a sound file
+
+int    - buffer number
+string - path name of a sound file.
+int    - starting frame in file (optional. default = 0)
+int    - number of frames to read (optional. default = 0, see below)
+bytes  - an OSC message to execute upon completion. (optional)
+
+Allocates buffer to number of channels of file and number of samples
+requested, or fewer if sound file is smaller than requested. Reads
+sound file data from the given starting frame in the file. If the
+number of frames argument is less than or equal to zero, the entire
+file is read.
+
+Asynchronous. Replies to sender with /done when complete.
diff --git a/Help/Server/b_close.help.lhs b/Help/Server/b_close.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/Server/b_close.help.lhs
@@ -0,0 +1,6 @@
+/b_close        Close attached soundfile and write header information
+
+int - buffer number
+
+After using a buffer with DiskOut, close the soundfile and write
+header information.
diff --git a/Help/Server/b_fill.help.lhs b/Help/Server/b_fill.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/Server/b_fill.help.lhs
@@ -0,0 +1,13 @@
+/b_fill                              Fill ranges of sample value(s)
+
+int     - buffer number
+[
+  int   - sample starting index
+  int   - number of samples to fill (M)
+  float - value
+] * N
+
+Set contiguous ranges of sample indices to single values. For each
+range, the starting sample index is given followed by the number of
+samples to change, followed by the value to fill. This is only meant
+for setting a few samples, not whole buffers or large sections.
diff --git a/Help/Server/b_free.help.lhs b/Help/Server/b_free.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/Server/b_free.help.lhs
@@ -0,0 +1,8 @@
+/b_free                                         Free buffer data.
+
+int   - buffer number
+bytes - an OSC message to execute upon completion (optional)
+
+Frees buffer space allocated for this buffer.
+
+Asynchronous. Replies to sender with /done when complete.
diff --git a/Help/Server/b_gen.help.lhs b/Help/Server/b_gen.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/Server/b_gen.help.lhs
@@ -0,0 +1,9 @@
+/b_gen                              Call a command to fill a buffer
+
+int    - buffer number
+string - command name
+...    - command arguments
+
+Plug-ins can define commands that operate on buffers. The arguments
+after the command name are defined by the command. The currently
+defined buffer fill commands are listed below in a separate section.
diff --git a/Help/Server/b_get.help.lhs b/Help/Server/b_get.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/Server/b_get.help.lhs
@@ -0,0 +1,8 @@
+/b_get					Get sample value(s)
+
+int   - buffer number
+[
+  int - a sample index
+] * N
+
+Replies to sender with the corresponding /b_set command.
diff --git a/Help/Server/b_getn.help.lhs b/Help/Server/b_getn.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/Server/b_getn.help.lhs
@@ -0,0 +1,11 @@
+/b_getn                               Get ranges of sample value(s)
+
+int   - buffer number
+[
+  int - starting sample index
+  int - number of sequential samples to get (M)
+] * N
+
+Get contiguous ranges of samples. Replies to sender with the
+corresponding /b_setn command. This is only meant for getting a few
+samples, not whole buffers or large sections.
diff --git a/Help/Server/b_query.help.lhs b/Help/Server/b_query.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/Server/b_query.help.lhs
@@ -0,0 +1,15 @@
+/b_query
+
+[
+  int - buffer number
+] * N
+
+Responds to the sender with a /b_info message.  The arguments to
+/b_info are as follows:
+
+[
+  int   - buffer number
+  int   - number of frames
+  int   - number of channels
+  float - sample rate
+] * N
diff --git a/Help/Server/b_read.help.lhs b/Help/Server/b_read.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/Server/b_read.help.lhs
@@ -0,0 +1,17 @@
+/b_read                Read sound file data into an existing buffer
+
+int    - buffer number
+string - path name of a sound file
+int    - starting frame in file (optional, default = 0)
+int    - number of frames to read (optional, default = -1, see below)
+int    - starting frame in buffer (optional, default = 0)
+int    - leave file open (optional, default = 0)
+bytes  - an OSC message to execute upon completion (optional)
+
+Reads sound file data from the given starting frame in the file and
+writes it to the given starting frame in the buffer. If number of
+frames is less than zero, the entire file is read.  If reading a file
+to be used by DiskIn ugen then you will want to set "leave file open"
+to one, otherwise set it to zero.
+
+Asynchronous.  Replies to sender with /done when complete.
diff --git a/Help/Server/b_set.help.lhs b/Help/Server/b_set.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/Server/b_set.help.lhs
@@ -0,0 +1,10 @@
+/b_set					    Set sample value(s)
+
+int     - buffer number
+[
+  int   - a sample index
+  float - a sample value
+] * N
+
+Takes a list of pairs of sample indices and values and sets the
+samples to those values.
diff --git a/Help/Server/b_setn.help.lhs b/Help/Server/b_setn.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/Server/b_setn.help.lhs
@@ -0,0 +1,14 @@
+/b_setn                               Set ranges of sample value(s)
+
+int       - buffer number
+[
+  int     - sample starting index
+  int     - number of sequential samples to change (M)
+  [
+    float - a sample value
+  ] * M
+] * N
+
+Set contiguous ranges of sample indices to sets of values. For each
+range, the starting sample index is given followed by the number of
+samples to change, followed by the values.
diff --git a/Help/Server/b_write.help.lhs b/Help/Server/b_write.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/Server/b_write.help.lhs
@@ -0,0 +1,27 @@
+/b_write					Write sound file data
+
+int    - buffer number
+string - path name of a sound file
+string - header format
+string - sample format
+int    - number of frames to write (optional. default = -1, see below)
+int    - starting frame in buffer (optional. default = 0)
+int    - leave file open (optional. default = 0)
+bytes  - an OSC message to execute upon completion (optional)
+
+Write a buffer as a sound file.  
+
+Header format is one of: "aiff", "next", "wav", "ircam"", "raw" 
+
+Sample format is one of: "int8", "int16", "int24", "int32", "float",
+"double", "mulaw", "alaw"
+
+Not all combinations of header format and sample format are possible.
+If number of frames is less than zero, all samples from the starting
+frame to the end of the buffer are written.  If opening a file to be
+used by DiskOut ugen then you will want to set "leave file open" to
+one, otherwise set it to zero. If "leave file open" is set to one then
+the file is created, but no frames are written until the DiskOut ugen
+does so.
+
+Asynchronous. Replies to sender with /done when complete.
diff --git a/Help/Server/b_zero.help.lhs b/Help/Server/b_zero.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/Server/b_zero.help.lhs
@@ -0,0 +1,8 @@
+/b_zero                                       Zero sample data
+
+int   - buffer number
+bytes - an OSC message to execute upon completion. (optional)
+
+Sets all samples in the buffer to zero.
+
+Asynchronous. Replies to sender with /done when complete.
diff --git a/Help/Server/c_fill.help.lhs b/Help/Server/c_fill.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/Server/c_fill.help.lhs
@@ -0,0 +1,11 @@
+/c_fill                                 Fill ranges of bus value(s)
+
+[
+  int   - starting bus index
+  int   - number of buses to fill (M)
+  float - value
+] * N
+
+Set contiguous ranges of buses to single values. For each range, the
+starting sample index is given followed by the number of buses to
+change, followed by the value to fill.
diff --git a/Help/Server/c_get.help.lhs b/Help/Server/c_get.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/Server/c_get.help.lhs
@@ -0,0 +1,8 @@
+/c_get					           Get bus value(s)
+
+[
+  int - a bus index
+] * N
+
+Takes a list of buses and replies to sender with the corresponding
+/c_set command.
diff --git a/Help/Server/c_getn.help.lhs b/Help/Server/c_getn.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/Server/c_getn.help.lhs
@@ -0,0 +1,9 @@
+/c_getn					Get ranges of bus value(s)
+
+[
+  int - starting bus index
+  int - number of sequential buses to get (M)
+] * N
+
+Get contiguous ranges of buses. Replies to sender with the
+corresponding /c_setn command.
diff --git a/Help/Server/c_set.help.lhs b/Help/Server/c_set.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/Server/c_set.help.lhs
@@ -0,0 +1,9 @@
+/c_set                                               Set bus value(s)
+
+[
+  int   - a bus index
+  float - a control value
+] * N
+
+Takes a list of pairs of bus indices and values and sets the buses to
+those values.
diff --git a/Help/Server/c_setn.help.lhs b/Help/Server/c_setn.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/Server/c_setn.help.lhs
@@ -0,0 +1,13 @@
+/c_setn                                    Set ranges of bus value(s)
+
+[
+  int     - starting bus index
+  int     - number of sequential buses to change (M)
+  [
+    float - a control value
+  ] * M
+] * N
+
+Set contiguous ranges of buses to sets of values. For each range, the
+starting bus index is given followed by the number of channels to
+change, followed by the values.
diff --git a/Help/Server/clearSched.help.lhs b/Help/Server/clearSched.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/Server/clearSched.help.lhs
@@ -0,0 +1,3 @@
+/clearSched                           Clear all scheduled bundles
+
+Removes all bundles from the scheduling queue.
diff --git a/Help/Server/d_free.help.lhs b/Help/Server/d_free.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/Server/d_free.help.lhs
@@ -0,0 +1,7 @@
+/d_free                                Delete synth definition
+
+[
+  string - synth def name
+] * N
+
+Removes a synth definition once all synths using it have ended.
diff --git a/Help/Server/d_load.help.lhs b/Help/Server/d_load.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/Server/d_load.help.lhs
@@ -0,0 +1,9 @@
+/d_load                                            Load synth definition
+
+string - pathname of file. Can be a pattern like "synthdefs/perc-*"
+bytes  - an OSC message to execute upon completion. (optional)
+
+Loads a file of synth definitions. Resident definitions with the same
+names are overwritten.
+
+Asynchronous. Replies to sender with /done when complete.
diff --git a/Help/Server/d_loadDir.help.lhs b/Help/Server/d_loadDir.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/Server/d_loadDir.help.lhs
@@ -0,0 +1,9 @@
+/d_loadDir                             Load directory of synth definitions
+
+string - pathname of directory.
+bytes  - an OSC message to execute upon completion. (optional)
+
+Loads a directory of synth definitions. Resident definitions with the
+same names are overwritten.
+
+Asynchronous. Replies to sender with /done when complete.
diff --git a/Help/Server/d_recv.help.lhs b/Help/Server/d_recv.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/Server/d_recv.help.lhs
@@ -0,0 +1,9 @@
+/d_recv                             Receive a synth definition file
+
+bytes - buffer of data.
+bytes - an OSC message to execute upon completion. (optional)
+
+Loads a file of synth definitions from a buffer in the message.
+Resident definitions with the same names are overwritten.
+
+Asynchronous. Replies to sender with /done when complete.
diff --git a/Help/Server/dumpOSC.help.lhs b/Help/Server/dumpOSC.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/Server/dumpOSC.help.lhs
@@ -0,0 +1,13 @@
+/dumpOSC                                  Display incoming OSC messages
+
+int - code
+
+Turns on and off printing of the contents of incoming Open Sound
+Control messages. This is useful when debugging your command stream.
+
+The values for the code are as follows:
+
+0 - turn dumping OFF.
+1 - print the parsed contents of the message.
+2 - print the contents in hexadecimal.
+3 - print both the parsed and hexadecimal representations of the contents.
diff --git a/Help/Server/g_deepFree.help.lhs b/Help/Server/g_deepFree.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/Server/g_deepFree.help.lhs
@@ -0,0 +1,9 @@
+/g_deepFree	 Free all synths in this group and all its sub-groups
+
+[
+  int - group ID
+] * N
+
+Traverses all groups below this group and frees all the synths.
+Sub-groups are not freed. A list of groups may be specified.
+
diff --git a/Help/Server/g_freeAll.help.lhs b/Help/Server/g_freeAll.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/Server/g_freeAll.help.lhs
@@ -0,0 +1,7 @@
+/g_freeAll                          Delete all nodes in a group
+
+[
+  int - group ID
+] * N
+
+Frees all nodes in the group. A list of groups may be specified.
diff --git a/Help/Server/g_head.help.lhs b/Help/Server/g_head.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/Server/g_head.help.lhs
@@ -0,0 +1,8 @@
+/g_head      		              Add node to head of group
+
+[
+  int - group ID
+  int - node ID
+] * N
+
+Adds the node to the head (first to be executed) of the group.
diff --git a/Help/Server/g_new.help.lhs b/Help/Server/g_new.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/Server/g_new.help.lhs
@@ -0,0 +1,13 @@
+/g_new				              Create a new group
+
+[
+  int - new group ID
+  int - add action (0,1,2, 3 or 4 see below)
+  int - add target ID
+] * N
+
+Create a new group and add it to the tree of nodes.
+
+For add action definitions see /s_new.
+
+Multiple groups may be created in one command by adding arguments.
diff --git a/Help/Server/g_tail.help.lhs b/Help/Server/g_tail.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/Server/g_tail.help.lhs
@@ -0,0 +1,8 @@
+/g_tail                               Add node to tail of group
+
+[
+  int - group ID
+  int - node ID
+] * N
+
+Adds the node to the tail (last to be executed) of the group.
diff --git a/Help/Server/n_after.help.lhs b/Help/Server/n_after.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/Server/n_after.help.lhs
@@ -0,0 +1,9 @@
+/n_after			      Place a node after another
+
+[
+  int - the ID of the node to place (A)
+  int - the ID of the node after which the above is placed (B)
+] * N
+
+Places node A in the same group as node B, to execute immediately
+after node B.
diff --git a/Help/Server/n_before.help.lhs b/Help/Server/n_before.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/Server/n_before.help.lhs
@@ -0,0 +1,9 @@
+/n_before			      Place a node before another
+
+[
+  int - the ID of the node to place (A)
+  int - the ID of the node before which the above is placed (B)
+] * N
+
+Places node A in the same group as node B, to execute immediately
+before node B.
diff --git a/Help/Server/n_fill.help.lhs b/Help/Server/n_fill.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/Server/n_fill.help.lhs
@@ -0,0 +1,13 @@
+/n_fill                    Fill ranges of a node's control value(s)
+
+int - node ID
+[
+  int or string - a control index or name
+  int - number of values to fill (M)
+  float - value
+] * N
+
+Set contiguous ranges of control indices to single values. For each
+range, the starting control index is given followed by the number of
+controls to change, followed by the value to fill. If the node is a
+group, then it sets the controls of every node in the group.
diff --git a/Help/Server/n_free.help.lhs b/Help/Server/n_free.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/Server/n_free.help.lhs
@@ -0,0 +1,9 @@
+/n_free                                            Delete a node
+
+[
+  int - node ID
+] * N
+
+Stops a node abruptly, removes it from its group, and frees its
+memory. A list of node IDs may be specified. Using this method can
+cause a click if the node is not silent at the time it is freed.
diff --git a/Help/Server/n_map.help.lhs b/Help/Server/n_map.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/Server/n_map.help.lhs
@@ -0,0 +1,14 @@
+/n_map                        Map a node's controls to read from a bus
+
+int          - node ID
+[
+  int|string - a control index or name
+  int        - control bus index
+] * N
+
+Takes a list of pairs of control names or indices and bus indices and
+causes those controls to be read continuously from a global control
+bus instead of responding to n_set, n_setn and n_fill commands. If the
+node is a group, then it maps the controls of every node in the
+group. If the control bus index is -1 then any current mapping is
+undone and control reverts to normal.
diff --git a/Help/Server/n_mapn.help.lhs b/Help/Server/n_mapn.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/Server/n_mapn.help.lhs
@@ -0,0 +1,16 @@
+/n_mapn                       Map a node's controls to read from buses
+
+int          - node ID
+[
+  int|string - a control index or name
+  int        - control bus index
+  int        - number of controls to map
+] * N
+
+Takes a list of triplets of control names or indices, bus indices, and
+number of controls to map and causes those controls to be mapped
+sequentially to buses. If the node is a group, then it maps the
+controls of every node in the group. If the control bus index is -1
+then any current mapping is undone and control reverts to normal.
+
+See also: /n_map
diff --git a/Help/Server/n_query.help.lhs b/Help/Server/n_query.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/Server/n_query.help.lhs
@@ -0,0 +1,10 @@
+/n_query                                        Get info about a node
+
+[
+  int - node ID
+] * N
+
+The server sends an /n_info message for each node to registered
+clients.
+
+See Node Notifications below for the format of the /n_info message.
diff --git a/Help/Server/n_run.help.lhs b/Help/Server/n_run.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/Server/n_run.help.lhs
@@ -0,0 +1,11 @@
+/n_run                                          Turn node on or off
+
+[
+  int - node ID
+  int - run flag
+] * N
+
+If the run flag set to zero then the node will not be executed.  If
+the run flag is set back to one, then it will be executed.  Using this
+method to start and stop nodes can cause a click if the node is not
+silent at the time run flag is toggled.
diff --git a/Help/Server/n_set.help.lhs b/Help/Server/n_set.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/Server/n_set.help.lhs
@@ -0,0 +1,11 @@
+/n_set                                Set a node's control value(s)
+
+int          - node ID
+[
+  int|string - a control index or name
+  float      - a control value
+] * N
+
+Takes a list of pairs of control indices and values and sets the
+controls to those values. If the node is a group, then it sets the
+controls of every node in the group.
diff --git a/Help/Server/n_setn.help.lhs b/Help/Server/n_setn.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/Server/n_setn.help.lhs
@@ -0,0 +1,15 @@
+/n_setn                       Set ranges of a node's control value(s)
+
+int - node ID
+[
+  int|string - a control index or name
+  int        - number of sequential controls to change (M)
+  [
+    float    - a control value
+  ] * M
+] * N
+
+Set contiguous ranges of control indices to sets of values. For each
+range, the starting control index is given followed by the number of
+controls to change, followed by the values. If the node is a group,
+then it sets the controls of every node in the group.
diff --git a/Help/Server/n_trace.help.lhs b/Help/Server/n_trace.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/Server/n_trace.help.lhs
@@ -0,0 +1,10 @@
+/n_trace                                               Trace a node
+
+[
+  int - node ID
+] * N
+
+Causes a synth to print out the values of the inputs and outputs of
+its unit generators for one control period. Causes a group to print
+the node IDs and names of each node in the group for one control
+period.
diff --git a/Help/Server/notify.help.lhs b/Help/Server/notify.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/Server/notify.help.lhs
@@ -0,0 +1,9 @@
+/notify            Register to receive notifications from server
+
+int - one to receive notifications, zero to stop receiving them.
+
+If argument is one, server will remember your return address and
+send you notifications. if argument is zero, server will stop
+sending you notifications.
+
+Asynchronous. Replies to sender with /done when complete.
diff --git a/Help/Server/quit.help.lhs b/Help/Server/quit.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/Server/quit.help.lhs
@@ -0,0 +1,7 @@
+/quit                                                Quit program
+
+No arguments.
+
+Exits the synthesis server.
+
+Asynchronous. Replies to sender with /done just before completion.
diff --git a/Help/Server/s_get.help.lhs b/Help/Server/s_get.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/Server/s_get.help.lhs
@@ -0,0 +1,8 @@
+/s_get				      Get control value(s)
+
+int - synth ID
+[
+  int|string - a control index or name
+] * N
+
+Replies to sender with the corresponding /n_set command.
diff --git a/Help/Server/s_getn.help.lhs b/Help/Server/s_getn.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/Server/s_getn.help.lhs
@@ -0,0 +1,10 @@
+/s_getn                          Get ranges of control value(s)
+
+int - synth ID
+[
+  int|string - a control index or name
+  int        - number of sequential controls to get (M)
+] * N
+
+Get contiguous ranges of controls. Replies to sender with the
+corresponding /n_setn command.
diff --git a/Help/Server/s_new.help.lhs b/Help/Server/s_new.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/Server/s_new.help.lhs
@@ -0,0 +1,38 @@
+/s_new                                             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
+  float      - a control value
+] * N
+
+Create a new synth from a synth definition, give it an ID, and add it
+to the tree of nodes. There are four ways to add the node to the tree
+as determined by the add action argument which is defined as follows:
+
+0 - add the new node to the the head of the target group
+1 - add the new node to the the tail of the target group
+2 - add the new node just before the target node
+3 - add the new node just after the target node
+4 - the new node replaces the target node, which is freed
+
+Controls may be set when creating the synth. The control arguments are
+the same as for the n_set command.
+
+If you send /s_new with a synth ID of -1, then the server will
+generate an ID for you. The server reserves all negative IDs. Since
+you don't know what the ID is, you cannot talk to this node directly
+later. So this is useful for nodes that are of finite duration and
+that get the control information they need from arguments and buses or
+messages directed to their group. In addition no notifications are
+sent when there are changes of state for this node, such as /go, /end,
+/on, /off.
+
+If you use a node ID of -1 for any other command, such as /n_map, then
+it refers to the most recently created node by /s_new (auto generated
+ID or not). This is how you can map the controls of a node with an
+auto generated ID. In a multi-client situation, the only way you can
+be sure what node -1 refers to is to put the messages in a bundle.
diff --git a/Help/Server/s_noid.help.lhs b/Help/Server/s_noid.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/Server/s_noid.help.lhs
@@ -0,0 +1,11 @@
+/s_noid               Auto-reassign synth's ID to a reserved value
+
+[
+  int - synth ID
+] * N
+
+This command is used when the client no longer needs to communicate
+with the synth and wants to have the freedom to reuse the ID. The
+server will reassign this synth to a reserved negative number. This
+command is purely for bookkeeping convenience of the client. No
+notification is sent when this occurs.
diff --git a/Help/Server/status.help.lhs b/Help/Server/status.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/Server/status.help.lhs
@@ -0,0 +1,16 @@
+/status				       query the status
+
+No arguments.
+
+Replies to sender with the following message.
+
+/status.reply
+	int    - unused
+	int    - number of unit generators
+	int    - number of synths
+	int    - number of groups
+	int    - number of loaded synth definitions
+	float  - average percent CPU usage for signal processing
+	float  - peak percent CPU usage for signal processing
+	double - nominal sample rate
+	double - actual sample rate
diff --git a/Help/Server/sync.help.lhs b/Help/Server/sync.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/Server/sync.help.lhs
@@ -0,0 +1,9 @@
+/sync                notify when async commands have completed.
+
+int - a unique number identifying this command.
+
+Replies with a /synced message when all asynchronous commands received
+before this one have completed. The reply will contain the sent unique
+ID.
+
+Asynchronous. Replies to sender with /synced, ID when complete.
diff --git a/Help/Server/tr.help.lhs b/Help/Server/tr.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/Server/tr.help.lhs
@@ -0,0 +1,13 @@
+/tr				a trigger message
+
+int   - node ID
+int   - trigger ID
+float - trigger value
+
+This command is the mechanism that synths can use to trigger events in
+clients.
+
+The node ID is the node that is sending the trigger. The trigger ID
+and value are determined by inputs to the SendTrig unit generator
+which is the originator of this message.
+
diff --git a/Help/Server/u_cmd.help.lhs b/Help/Server/u_cmd.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/Server/u_cmd.help.lhs
@@ -0,0 +1,9 @@
+/u_cmd                            Send a command to a unit generator
+
+int    - node ID
+int    - unit generator index
+string - command name
+...any arguments
+
+Sends all arguments following the command name to the unit generator
+to be performed. Commands are defined by unit generator plug ins.
diff --git a/Help/Tutorial/Tutorial.lhs b/Help/Tutorial/Tutorial.lhs
new file mode 100644
--- /dev/null
+++ b/Help/Tutorial/Tutorial.lhs
@@ -0,0 +1,188 @@
+* Haskell SuperCollider, a Tutorial.
+
+* Prerequisites
+
+Haskell SuperCollider requires that SuperCollider [1], GHC [2], the
+GHC binary package[3], Emacs [4] and the standard Haskell Emacs mode
+[5] are all installed and working properly.
+
+* Setting up Haskell SuperCollider
+
+Haskell SuperCollider is currently only available as a set of darcs
+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.
+
+  $ runhaskell Setup.lhs configure --prefix ~
+  $ runhaskell Setup.lhs build
+  $ runhaskell Setup.lhs install --user
+
+* 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-interpreter "ghci")
+  (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
+
+To start ghci and load the list of modules at the emacs variables
+'hsc3-main-modules' and 'hsc3-modules' use C-cC-s (Haskell
+SuperCollider -> Haskell -> Start haskell).  By default
+'hsc3-main-modules' is empty and 'hsc3-modules' contains
+Sound.OpenSoundControl, Sound.SC3, Data.List, Control.Monad,
+Control.Concurrent, System.Directory 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 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).
+
+> 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 ((flip send) (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
+
+* Multiple line expressions
+
+To evaluate expressions that don't fit on one line select the region
+and type C-cC-e (Haskell SuperCollider -> Expression -> Run region).
+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 f = sinOsc AR (xLine KR 1 1000 9 RemoveSynth) 0 * 200 + 800
+> audition (out 0 (sinOsc AR f 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.
+
+* Help Files
+
+To find help on a UGen 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
+
+* User configuration files
+
+It is straightforward to add configuration modules to the context in
+which the hsc3 emacs mode evaluates expressions using the
+'hsc3-main-modules' variable.  The search path for these modules can
+be set using 'hsc3-interpreter-arguments'.
+
+ (setq hsc3-interpreter-arguments (list "-i/home/rohan/.hsc3"))
+ (setq hsc3-main-modules (list "Config"))
+
+* 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://www.audiosynth.com/
+[2] http://www.haskell.org/ghc/
+[3] http://hackage.haskell.org/cgi-bin/hackage-scripts/package/binary-0.3
+[4] http://www.gnu.org/software/emacs/
+[5] http://www.haskell.org/haskell-mode/
diff --git a/Help/UGen/Analysis/amplitude.help.lhs b/Help/UGen/Analysis/amplitude.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Analysis/amplitude.help.lhs
@@ -0,0 +1,9 @@
+amplitude rate in attackTime releaseTime
+
+Amplitude follower. Tracks the peak amplitude of a signal.
+
+> let s = in' 1 AR numOutputBuses
+> audition (out 0 (pulse AR 90 0.3 * amplitude KR s 0.1 0.1))
+
+> let s = in' 1 AR numOutputBuses
+> audition (out 0 (sinOsc AR (amplitude KR s 0.1 0.1 * 1200 + 400) 0 * 0.3))
diff --git a/Help/UGen/Analysis/compander.help.lhs b/Help/UGen/Analysis/compander.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Analysis/compander.help.lhs
@@ -0,0 +1,75 @@
+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).
+
+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.
+
+Example signal to process.
+
+> 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)
+> audition (out 0 (e * p))
+
+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
+> 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
+> 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
+> 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
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Analysis/pitch.help.lhs
@@ -0,0 +1,30 @@
+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.
+
+> 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
+> 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
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Analysis/runningSum.help.lhs
@@ -0,0 +1,11 @@
+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)
+
+> let a = runningSum (in' 1 AR numOutputBuses) 40 * (1/40)
+> audition (out 0 (sinOsc AR 440 0 * a))
diff --git a/Help/UGen/Analysis/slope.help.lhs b/Help/UGen/Analysis/slope.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Analysis/slope.help.lhs
@@ -0,0 +1,17 @@
+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.
+
+> a <- lfNoise2 KR 2
+> let s = 1/2
+>     b = slope a * s
+>     c = slope b * squared s
+> audition (out 0 (mix (sinOsc AR (MCE [a, b, c] * 220 + 220) 0 * (1/3))))
diff --git a/Help/UGen/Analysis/zeroCrossing.help.lhs b/Help/UGen/Analysis/zeroCrossing.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Analysis/zeroCrossing.help.lhs
@@ -0,0 +1,13 @@
+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.
+
+> let a = sinOsc AR (sinOsc KR 1 0 * 600 + 700) 0 * 0.1
+> audition (out 0 (MCE [a, impulse AR (zeroCrossing a) 0 * 0.25]))
diff --git a/Help/UGen/Buffer/bufAllpassC.help.lhs b/Help/UGen/Buffer/bufAllpassC.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Buffer/bufAllpassC.help.lhs
@@ -0,0 +1,27 @@
+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.
+
+> withSC3 (\fd -> do send fd (b_alloc 0 44100 1)
+>                    wait fd "/done")
+
+> d <- dust AR 1
+> n <- whiteNoise AR
+> let x = decay d 0.2 * n * 0.25
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Buffer/bufAllpassL.help.lhs
@@ -0,0 +1,1 @@
+See bufAllpassC.
diff --git a/Help/UGen/Buffer/bufAllpassN.help.lhs b/Help/UGen/Buffer/bufAllpassN.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Buffer/bufAllpassN.help.lhs
@@ -0,0 +1,1 @@
+See bufAllpassC.
diff --git a/Help/UGen/Buffer/bufChannels.help.lhs b/Help/UGen/Buffer/bufChannels.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Buffer/bufChannels.help.lhs
@@ -0,0 +1,5 @@
+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.
diff --git a/Help/UGen/Buffer/bufCombC.help.lhs b/Help/UGen/Buffer/bufCombC.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Buffer/bufCombC.help.lhs
@@ -0,0 +1,25 @@
+bufCombC buf in delayTime decayTime
+
+Buffer based comb delay line with cubic interpolation
+
+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.
+
+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.
+
+> withSC3 (\fd -> do send fd (b_alloc 0 44100 1)
+>                    wait fd "/done")
+
+> d <- dust AR 1
+> n <- whiteNoise AR
+> let x = decay d 0.2 * n * 0.25
+> audition (out 0 (bufCombC 0 x 0.25 6))
diff --git a/Help/UGen/Buffer/bufCombL.help.lhs b/Help/UGen/Buffer/bufCombL.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Buffer/bufCombL.help.lhs
@@ -0,0 +1,1 @@
+See bufCombC.
diff --git a/Help/UGen/Buffer/bufCombN.help.lhs b/Help/UGen/Buffer/bufCombN.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Buffer/bufCombN.help.lhs
@@ -0,0 +1,1 @@
+See bufCombC.
diff --git a/Help/UGen/Buffer/bufDelayC.help.lhs b/Help/UGen/Buffer/bufDelayC.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Buffer/bufDelayC.help.lhs
@@ -0,0 +1,23 @@
+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.
+
+> withSC3 (\fd -> do send fd (b_alloc 0 44100 1)
+>                    wait fd "/done")
+
+> d <- dust AR 1
+> n <- whiteNoise AR
+> let x = decay d 0.5 * n * 0.3
+> audition (out 0 (bufDelayC 0 x 0.2 + x))
diff --git a/Help/UGen/Buffer/bufDelayL.help.lhs b/Help/UGen/Buffer/bufDelayL.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Buffer/bufDelayL.help.lhs
@@ -0,0 +1,1 @@
+See bufDelayC.
diff --git a/Help/UGen/Buffer/bufDelayN.help.lhs b/Help/UGen/Buffer/bufDelayN.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Buffer/bufDelayN.help.lhs
@@ -0,0 +1,1 @@
+See bufDelayC.
diff --git a/Help/UGen/Buffer/bufDur.help.lhs b/Help/UGen/Buffer/bufDur.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Buffer/bufDur.help.lhs
@@ -0,0 +1,10 @@
+bufDur rate bufnum
+
+Current duration of buffer.
+
+> withSC3 (\fd -> do send fd (b_allocRead 0 "/home/rohan/audio/metal.wav" 0 0)
+>                    wait fd "/done")
+
+> let t = impulse AR (recip (bufDur KR 0)) 0
+>     p = sweep t (bufSampleRate KR 0)
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Buffer/bufFrames.help.lhs
@@ -0,0 +1,13 @@
+bufFrames rate bufnum
+
+Current duration of buffer.
+
+> withSC3 (\fd -> do send fd (b_allocRead 0 "/home/rohan/audio/metal.wav" 0 0)
+>                    wait fd "/done")
+
+> let p = phasor AR 0 (bufRateScale KR 0) 0 (bufFrames KR 0) 0
+> audition (out 0 (bufRdL 1 AR 0 p NoLoop))
+
+> let r = MCE [0.05, 0.075 .. 0.15]
+>     p = k2A (mouseX KR 0 (bufFrames KR 0) Linear r)
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Buffer/bufRateScale.help.lhs
@@ -0,0 +1,11 @@
+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.
+
+> withSC3 (\fd -> do send fd (b_allocRead 0 "/home/rohan/audio/metal.wav" 0 0)
+>                    wait fd "/done")
+
+> let r = 1.25 * bufRateScale KR 0
+>     p = phasor AR 0 r 0 (bufFrames KR 0) 0
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Buffer/bufRd.help.lhs
@@ -0,0 +1,23 @@
+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).
+
+> withSC3 (\fd -> send fd (b_allocRead 0 "/home/rohan/audio/metal.wav" 0 0))
+
+> let phase = (sinOsc AR 0.1 0 * bufFrames KR 0)
+> audition (out 0 (bufRd 1 AR 0 phase Loop NoInterpolation))
+
+There are constructors, bufRdN, bufRdL, and bufRdC for the fixed
+cases.
+
+> let x = mouseX KR (MCE [5, 10]) 100 Linear 0.1
+> n <- lfNoise1 AR x
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Buffer/bufSampleRate.help.lhs
@@ -0,0 +1,12 @@
+bufSampleRate rate bufnum
+
+Buffer sample rate.
+
+> withSC3 (\fd -> do send fd (b_allocRead 0 "/home/rohan/audio/metal.wav" 0 0)
+>                    wait fd "/done")
+
+Compare a sine tone derived from sample rate of a buffer with a
+440Hz tone.
+
+> let f = MCE [bufSampleRate KR 0 * 0.01, 440]
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Buffer/detectIndex.help.lhs
@@ -0,0 +1,21 @@
+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.
+
+> withSC3 (\fd -> do send fd (b_alloc 10 6 1)
+>                    wait fd "/done"
+>                    send fd (b_setn 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
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Buffer/index.help.lhs
@@ -0,0 +1,20 @@
+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.
+
+> withSC3 (\fd -> do send fd (b_alloc 10 6 1)
+>                    wait fd "/done"
+>                    send fd (b_setn 10 [(0, [50, 100, 200, 400, 800, 1600])]))
+
+Index into the above buffer for frequency values.
+
+> let f = index 10 (lfSaw KR 2 3 * 4)
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Buffer/indexInBetween.help.lhs
@@ -0,0 +1,22 @@
+indexInBetween bufnum in
+
+Interpolating index search into a sorted table with a signal.
+
+Allocate and set values at buffer 10.
+
+> withSC3 (\fd -> do send fd (b_alloc 10 6 1)
+>                    wait fd "/done"
+>                    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
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Buffer/osc.help.lhs
@@ -0,0 +1,44 @@
+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.
+
+> withSC3 (\fd -> do send fd (b_alloc 10 512 1)
+>                    wait fd "/done"
+>                    send fd (b_gen 10 "sine1" [1 + 2 + 4, 1, 1/2, 1/3, 1/4, 1/5]))
+
+> audition (out 0 (osc AR 10 220 0 * 0.1))
+
+Modulate freq
+
+> let f = xLine KR 2000 200 1 DoNothing
+> audition (out 0 (osc AR 10 f 0 * 0.1))
+
+Modulate freq
+
+> let f = osc AR 10 (xLine KR 1 1000 9 RemoveSynth) 0 * 200 + 800
+> audition (out 0 (osc AR 10 f 0 * 0.1))
+
+Modulate phase
+
+> let p = osc AR 10 (xLine KR 20 8000 10 RemoveSynth) 0 * 2 * pi
+> audition (out 0 (osc AR 10 800 p * 0.1))
+
+Change the buffer while its playing
+
+> audition (out 0 (osc AR 10 220 0 * 0.1))
+
+> r <- getStdRandom (randomR (0.0,1.0))
+> withSC3 (\fd -> send fd (b_gen 10 "sine1" [1 + 2 + 4, 1, r, 1/4]))
diff --git a/Help/UGen/Buffer/playBuf.help.lhs b/Help/UGen/Buffer/playBuf.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Buffer/playBuf.help.lhs
@@ -0,0 +1,68 @@
+playBuf numChannels bufnum rate trigger startPos loop
+
+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.
+
+> let fileName = "/home/rohan/audio/metal.wav"
+> withSC3 (\fd -> do send fd (b_allocRead 10 fileName 0 0)
+>                    wait fd "/done")
+
+Play once only.
+
+> audition (out 0 (playBuf 1 10 (bufRateScale KR 10) 1 0 NoLoop))
+
+Play in infinite loop.
+
+> audition (out 0 (playBuf 1 10 (bufRateScale KR 10) 1 0 Loop))
+
+Trigger playback at each pulse.
+
+> let t = impulse KR 2 0
+> audition (out 0 (playBuf 1 10 (bufRateScale KR 10) t 0 NoLoop))
+
+Trigger playback at each pulse (diminishing intervals).
+
+> let f = xLine KR 0.1 100 10 RemoveSynth
+>     t = impulse KR f 0
+> audition (out 0 (playBuf 1 10 (bufRateScale KR 10) t 0 NoLoop))
+
+Loop playback, accelerating pitch.
+
+> let r = xLine KR 0.1 100 60 RemoveSynth
+> audition (out 0 (playBuf 1 10 r 1 0 Loop))
+
+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
+> audition (out 0 (playBuf 1 10 (bufRateScale KR 10 * r) 1 0 Loop))
+
+Release buffer.
+
+> withSC3 (\fd -> send fd (b_free 10))
diff --git a/Help/UGen/Buffer/recordBuf.help.lhs b/Help/UGen/Buffer/recordBuf.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Buffer/recordBuf.help.lhs
@@ -0,0 +1,1 @@
+recordBuf bufnum offset reclevel prelevel run loop trigger inputs
diff --git a/Help/UGen/Buffer/vOsc.help.lhs b/Help/UGen/Buffer/vOsc.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Buffer/vOsc.help.lhs
@@ -0,0 +1,47 @@
+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.
+
+> let square a = a * a
+>     harmonics i = map f [0 .. n - 1]
+>         where n = square (i + 1)
+>               f j = square ((n - j) / n)
+>     setup fd i = do let i' = fromIntegral i
+>                     send fd (b_alloc i 1024 1)
+>                     wait fd "/done"
+>                     send fd (b_gen i "sine1" (1 + 2 + 4 : harmonics i'))
+> 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
+> audition (out 0 (vOsc AR x (MCE [120, 121]) 0 * 0.3))
+
+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))
+> withSC3 (\fd -> mapM_ (resetTable fd) [0 .. 7])
diff --git a/Help/UGen/Chaos/crackle.help.lhs b/Help/UGen/Chaos/crackle.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Chaos/crackle.help.lhs
@@ -0,0 +1,13 @@
+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)
+
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Chaos/cuspL.help.lhs
@@ -0,0 +1,29 @@
+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:
+
+xn+1 = a - b*sqrt(|xn|)
+
+Vary frequency
+
+> let x = mouseX KR 20 sampleRate Linear 0.1
+> 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
+> 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
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Chaos/cuspN.help.lhs
@@ -0,0 +1,1 @@
+See cuspL.
diff --git a/Help/UGen/Chaos/fbSineC.help.lhs b/Help/UGen/Chaos/fbSineC.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Chaos/fbSineC.help.lhs
@@ -0,0 +1,47 @@
+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.
+
+sclang default values
+
+> audition (out 0 (fbSineC AR (sampleRate / 4) 1 0.1 1.1 0.5 0.1 0.1 * 0.2))
+
+Increase feedback
+
+> let fb = line KR 0.01 4 10 DoNothing
+> audition (out 0 (fbSineC AR sampleRate 1 fb 1.1 0.5 0.1 0.1 * 0.2))
+
+Increase phase multiplier
+
+> let a = line KR 1 2 10 DoNothing
+> audition (out 0 (fbSineC AR sampleRate 1 0 a 0.5 0.1 0.1 * 0.2))
+
+Randomly modulate parameters
+
+> let x = mouseX KR 1 12 Linear 0.1
+> n0 <- return . (+ 1e4)  . (* 1e4)  =<< lfNoise2 KR x
+> n1 <- return . (+ 33)   . (* 32)   =<< lfNoise2 KR x
+> n2 <- return . (+ 0)    . (* 0.5)  =<< lfNoise2 KR x
+> n3 <- return . (+ 1.05) . (* 0.05) =<< lfNoise2 KR x
+> n4 <- return . (+ 0.3)  . (* 0.3)  =<< lfNoise2 KR x
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Chaos/fbSineL.help.lhs
@@ -0,0 +1,1 @@
+See fbSineC.
diff --git a/Help/UGen/Chaos/fbSineN.help.lhs b/Help/UGen/Chaos/fbSineN.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Chaos/fbSineN.help.lhs
@@ -0,0 +1,1 @@
+See fbSineC.
diff --git a/Help/UGen/Chaos/henonC.help.lhs b/Help/UGen/Chaos/henonC.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Chaos/henonC.help.lhs
@@ -0,0 +1,1 @@
+See henonN.
diff --git a/Help/UGen/Chaos/henonL.help.lhs b/Help/UGen/Chaos/henonL.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Chaos/henonL.help.lhs
@@ -0,0 +1,1 @@
+See henonN.
diff --git a/Help/UGen/Chaos/henonN.help.lhs b/Help/UGen/Chaos/henonN.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Chaos/henonN.help.lhs
@@ -0,0 +1,41 @@
+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.
+
+With default initial parameters.
+
+> let x = mouseX KR 20 sampleRate Linear 0.1
+> 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
+> audition (out 0 (henonN AR (sampleRate / 4) x y 0 0 * 0.1))
+
+With randomly modulate parameters.
+
+> 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))
+
+As a frequency control.
+
+> let x = mouseX KR 1 1.4 Linear 0.1
+>     y = mouseY KR 0 0.3 Linear 0.1
+>     f = 40
+> audition (out 0 (sinOsc AR (henonN AR f x y 0 0 * 800 + 900) 0 * 0.4))
diff --git a/Help/UGen/Chaos/latoocarfianC.help.lhs b/Help/UGen/Chaos/latoocarfianC.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Chaos/latoocarfianC.help.lhs
@@ -0,0 +1,36 @@
+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.
+
+sclang default initial parameters.
+
+> let x = mouseX KR 20 sampleRate Linear 0.1
+> audition (out 0 (latoocarfianC AR x 1 3 0.5 0.5 0.5 0.5 * 0.2))
+
+Randomly modulate all parameters.
+
+> [n0, n1, n2, n3] <- replicateM 4 (lfNoise2 KR 2)
+> let f = sampleRate / 4
+>     a = n0 * 1.5 + 1.5
+>     b = n1 * 1.5 + 1.5
+>     c = n2 * 0.5 + 1.5
+>     d = n2 * 0.5 + 1.5
+> audition (out 0 (latoocarfianC AR f a b c d 0.5 0.5 * 0.2))
diff --git a/Help/UGen/Chaos/linCongC.help.lhs b/Help/UGen/Chaos/linCongC.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Chaos/linCongC.help.lhs
@@ -0,0 +1,32 @@
+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].
+
+
+Default initial parameters.
+
+> let x = mouseX KR 20 sampleRate Linear 0.1
+> audition (out 0 (linCongC AR x 1.1 0.13 1 0 * 0.2))
+
+Randomly modulate parameters.
+
+> [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
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Chaos/linCongL.help.lhs
@@ -0,0 +1,1 @@
+See linCongC.
diff --git a/Help/UGen/Chaos/linCongN.help.lhs b/Help/UGen/Chaos/linCongN.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Chaos/linCongN.help.lhs
@@ -0,0 +1,1 @@
+See linCongC.
diff --git a/Help/UGen/Chaos/logistic.help.lhs b/Help/UGen/Chaos/logistic.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Chaos/logistic.help.lhs
@@ -0,0 +1,7 @@
+logistic rate chaosParam freq
+
+UNDOCUMENTED.
+
+Implements the equation: y1 = param * y1 * (1.0 - y1)
+
+> logistic AR 3.5699457 1000.0 0.01
diff --git a/Help/UGen/Chaos/lorenzL.help.lhs b/Help/UGen/Chaos/lorenzL.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Chaos/lorenzL.help.lhs
@@ -0,0 +1,38 @@
+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
+
+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.
+
+Vary frequency
+
+> let x = mouseX KR 20 sampleRate Linear 0.1
+> audition (out 0 (lorenzL AR x 10 27 2.667 0.05 0.1 0 0 * 0.3))
+
+Randomly modulate params
+
+> n0 <- return . (+ 10) . (* 2)   =<< lfNoise0 KR 1
+> n1 <- return . (+ 38) . (* 20)  =<< lfNoise0 KR 1
+> n2 <- return . (+ 2)  . (* 1.5) =<< lfNoise0 KR 1
+> audition (out 0 (lorenzL AR sampleRate n0 n1 n2 0.05 0.1 0 0 * 0.2))
+
+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 
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Chaos/quadC.help.lhs
@@ -0,0 +1,1 @@
+See quadN.
diff --git a/Help/UGen/Chaos/quadL.help.lhs b/Help/UGen/Chaos/quadL.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Chaos/quadL.help.lhs
@@ -0,0 +1,1 @@
+See quadN.
diff --git a/Help/UGen/Chaos/quadN.help.lhs b/Help/UGen/Chaos/quadN.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Chaos/quadN.help.lhs
@@ -0,0 +1,20 @@
+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
+
+> audition (out 0 (quadC AR 4000 1 (-1) (-0.75) 0 * 0.2))
+
+> let x = mouseX KR 3.5441 4 Linear 0.1
+> 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
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Chaos/rossler.help.lhs
@@ -0,0 +1,7 @@
+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.
+
+> audition (out 0 (rossler AR 4 0.08))
diff --git a/Help/UGen/Demand/dbrown.help.lhs b/Help/UGen/Demand/dbrown.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Demand/dbrown.help.lhs
@@ -0,0 +1,19 @@
+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.
+
+> n <- dbrown 32 0 15 1
+> let x = mouseX KR 1 40 Exponential 0.1
+>     t = impulse KR x 0
+>     f = demand t 0 n * 30 + 340
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Demand/dbufrd.help.lhs
@@ -0,0 +1,42 @@
+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
+
+Example
+
+> let n = randomRs (200.0, 500.0) (mkStdGen 0)
+> withSC3 (\fd -> do send fd (b_alloc 10 24 1)
+>                    wait fd "/done"
+>                    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 8192 (MCE [s, b])
+> t <- dust KR 10
+> r <- dbufrd 10 p Loop
+> audition (out 0 (sinOsc AR (demand t 0 r) 0 * 0.1))
+
+Buffer as a time pattern (requires buffer 10 as allocated above).
+
+> let i = randomRs (0, 2) (mkStdGen 0)
+>     n = map ([1, 0.5, 0.25] !!) i
+> withSC3 (\fd -> do send fd (b_alloc 11 24 1)
+>                    wait fd "/done"
+>                    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 8192 (MCE [s, b])
+> j <- dseries 8192 0 1
+> d <- dbufrd 11 j Loop
+> l <- dbufrd 10 p Loop
+> audition (out 0 (sinOsc AR (duty KR (d * 0.5) 0 DoNothing l) 0 * 0.1))
+
+Free buffers
+
+> withSC3 (\fd -> do send fd (b_free 10)
+>                    wait fd "/done"
+>                    send fd (b_free 11)
+>                    wait fd "/done")
diff --git a/Help/UGen/Demand/demand.help.lhs b/Help/UGen/Demand/demand.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Demand/demand.help.lhs
@@ -0,0 +1,27 @@
+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.
+
+> r <- dust KR 1
+> s <- dgeom 64 (midiCPS 72) (midiRatio 1)
+> let t = impulse KR 10 0
+>     f = demand t r s
+> audition (out 0 (max (cubed (sinOsc AR (MCE [f, f + 0.7]) 0)) 0 * 0.1))
+
+> n <- diwhite 8192 60 72
+> let t = impulse KR 10 0
+>     s = midiCPS n
+>     f = demand t 0 s
+> audition (out 0 (cubed (cubed (sinOsc AR (MCE [f, f + 0.7]) 0)) * 0.1))
diff --git a/Help/UGen/Demand/demandEnvGen.help.lhs b/Help/UGen/Demand/demandEnvGen.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Demand/demandEnvGen.help.lhs
@@ -0,0 +1,41 @@
+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
+
+reset  - if reset crosses from nonpositive to positive, the ugen
+         is reset at the next level, if it is > 1, it is reset
+         immediately.
+
+Frequency ramp, exponential curve.
+
+> let inf_sc = 9e8
+> l <- dseq inf_sc (MCE [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
+> audition (out 0 (sinOsc AR f 0 * 0.1))
+
+Frequency envelope with random times.
+
+> let inf_sc = 9e8
+> l <- dseq inf_sc (MCE [204, 400, 201, 502, 300, 200])
+> t <- drand inf_sc (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
+> audition (out 0 (sinOsc AR (f * MCE [1, 1.01]) 0 * 0.1))
diff --git a/Help/UGen/Demand/dgeom.help.lhs b/Help/UGen/Demand/dgeom.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Demand/dgeom.help.lhs
@@ -0,0 +1,15 @@
+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
+
+> 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
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Demand/dibrown.help.lhs
@@ -0,0 +1,1 @@
+See dbrown.
diff --git a/Help/UGen/Demand/diwhite.help.lhs b/Help/UGen/Demand/diwhite.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Demand/diwhite.help.lhs
@@ -0,0 +1,1 @@
+See dwhite.
diff --git a/Help/UGen/Demand/drand.help.lhs b/Help/UGen/Demand/drand.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Demand/drand.help.lhs
@@ -0,0 +1,16 @@
+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.
+
+> n <- drand 32 (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
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Demand/dseq.help.lhs
@@ -0,0 +1,12 @@
+dseq length array
+
+Demand rate sequence generator.
+
+array   - array of values or other ugens
+length  - number of repeats
+
+> 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
+> audition (out 0 (sinOsc AR f 0 * 0.1))
diff --git a/Help/UGen/Demand/dser.help.lhs b/Help/UGen/Demand/dser.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Demand/dser.help.lhs
@@ -0,0 +1,12 @@
+dser length array
+
+Demand rate sequence generator.
+
+array  - array of values or other ugens
+length - number of values to return
+
+> a <- dser 8192 (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
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Demand/dseries.help.lhs
@@ -0,0 +1,15 @@
+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
+
+> 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
+> audition (out 0 (sinOsc AR f 0 * 0.1))
diff --git a/Help/UGen/Demand/dswitch1.help.lhs b/Help/UGen/Demand/dswitch1.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Demand/dswitch1.help.lhs
@@ -0,0 +1,14 @@
+dswitch1 index array
+
+Demand rate generator for switching between inputs
+
+index	- which of the inputs to return
+array	- array of values or other ugens
+
+> let x = mouseX KR 0 4 Linear 0.1
+>     y = mouseY KR 1 15 Linear 0.1
+> w <- dwhite 2 0 3
+> n <- dswitch1 x (MCE [1, 3, y, 2, w])
+> let t = impulse KR 3 0
+>     f = demand t 0 n * 30 + 340
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Demand/duty.help.lhs
@@ -0,0 +1,33 @@
+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.
+
+> n0 <- drand 8192 (MCE [0.01, 0.2, 0.4])
+> n1 <- dseq 8192 (MCE [204, 400, 201, 502, 300, 200])
+> let f = duty KR n0 0 RemoveSynth n1
+> audition (out 0 (sinOsc AR (f * MCE [1, 1.01]) 0 * 0.1))
+
+Using control rate signal, mouseX, to determine duration.
+
+> let x = mouseX KR 0.001 2 Linear 0.1
+> n <- dseq 8192 (MCE [204, 400, 201, 502, 300, 200])
+> let f = duty KR x 0 RemoveSynth n
+> audition (out 0 (sinOsc AR (f * MCE [1, 1.01]) 0 * 0.1))
diff --git a/Help/UGen/Demand/dwhite.help.lhs b/Help/UGen/Demand/dwhite.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Demand/dwhite.help.lhs
@@ -0,0 +1,18 @@
+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
+
+> n <- dwhite 32 0 15
+> let x = mouseX KR 1 40 Exponential 0.1
+>     t = impulse KR x 0
+>     f = demand t 0 n * 30 + 340
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Demand/dxrand.help.lhs
@@ -0,0 +1,1 @@
+See drand.
diff --git a/Help/UGen/Demand/tDuty.help.lhs b/Help/UGen/Demand/tDuty.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Demand/tDuty.help.lhs
@@ -0,0 +1,51 @@
+tDuty rate duration reset doneAction level
+
+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.
+
+Play a little rhythm
+
+> let inf = 1E+9
+> d <- dseq inf (MCE [0.1, 0.2, 0.4, 0.3])
+> audition (out 0 (tDuty AR d 0 DoNothing 1))
+
+Amplitude changes
+
+> let inf = 1E+9
+> d0 <- dseq inf (MCE [0.1, 0.2, 0.4, 0.3])
+> d1 <- dseq inf (MCE [0.1, 0.4, 0.01, 0.5, 1.0])
+> audition (out 0 (ringz (tDuty AR d0 0 DoNothing d1) 1000 0.1))
+
+Mouse control.
+
+> let inf = 1E+9
+> d <- dseq inf (MCE [0.1, 0.4, 0.01, 0.5, 1.0])
+> let x = mouseX KR 0.001 1 Linear 0.1
+> audition (out 0 (ringz (tDuty AR x 0 DoNothing d) 1000 0.1))
+
+Note that the 440 is the long pitch.
+
+> d0 <- dser 12 (MCE [0.1, 0.3])
+> d1 <- dser 12 (MCE [440, 880])
+> let t = tDuty AR d0 0 RemoveSynth d1
+> audition (out 0 (sinOsc AR (latch t t) 0 * 0.1))
diff --git a/Help/UGen/Envelope/detectSilence.help.lhs b/Help/UGen/Envelope/detectSilence.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Envelope/detectSilence.help.lhs
@@ -0,0 +1,7 @@
+detectSilence in amp time doneAction
+
+If the signal at `in' falls below `amp' for `time' seconds then
+`doneAction' is raised.
+
+> let s = sinOsc AR 440 0 * mouseY KR 0 0.4 Linear 0.1
+> audition (MRG [detectSilence s 0.1 0.2 RemoveSynth, out 0 s])
diff --git a/Help/UGen/Envelope/done.help.lhs b/Help/UGen/Envelope/done.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Envelope/done.help.lhs
@@ -0,0 +1,9 @@
+done src
+
+Outputs a unit signal if the 'done' flag of the unit at `src' is
+set, else output zero.
+
+> let x   = mouseX KR (-1) 1 Linear 0.1
+>     env = linen x 0.1 0.1 0.5 DoNothing
+> audition (out 0 (MCE [ done env * sinOsc AR 880 0 * 0.1
+>                       , sinOsc AR 440 0 * env]))
diff --git a/Help/UGen/Envelope/envGen.help.lhs b/Help/UGen/Envelope/envGen.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Envelope/envGen.help.lhs
@@ -0,0 +1,53 @@
+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.
+
+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.
+
+Percussive envelope
+
+> let p = envPerc 0.01 1 1 [EnvNum (-4), EnvNum (-4)]
+>     e = envGen KR 1 0.1 0 1 RemoveSynth p
+> audition (out 0 (sinOsc AR 440 0 * e))
+
+Sine envelope
+
+> let s = envSine 9 0.1
+>     e = envGen KR 1 1 0 1 RemoveSynth s
+> audition (out 0 (sinOsc AR 440 0 * e))
+
+Co-ordinate (break-point) envelope
+
+> let c = envCoord [(0,0), (0.5, 0.1), (0.55, 1), (1, 0)] 9 0.1 EnvLin
+>     e = envGen KR 1 1 0 1 RemoveSynth c
+> audition (out 0 (sinOsc AR 440 0 * e))
+
+Trapezoidal envelope
+
+> let t = envTrapezoid 0.05 0.95 3 0.1
+>     e = envGen KR 1 1 0 1 RemoveSynth t
+> audition (out 0 (sinOsc AR 440 0 * e))
diff --git a/Help/UGen/Envelope/free.help.lhs b/Help/UGen/Envelope/free.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Envelope/free.help.lhs
@@ -0,0 +1,17 @@
+free trig nodeID
+
+When triggered frees a node.
+
+trig   - when triggered, frees node
+nodeID - node to be freed
+
+> withSC3 (\fd -> do let a = out 0 (sinOsc AR 880 0 * 0.1)
+>                    send fd (d_recv (graphdef "a" (graph a)))
+>                    wait fd "/done"
+>                    n0 <- pinkNoise AR
+>                    n1 <- dust AR 2
+>                    let b = MRG [out 1 (n0 * 0.1), free n1 1001]
+>                    send fd (d_recv (graphdef "b" (graph b)))
+>                    wait fd "/done"
+>                    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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Envelope/freeSelf.help.lhs
@@ -0,0 +1,8 @@
+freeSelf src
+
+Free enclosing synth when the input signal crosses from non-positive
+to positive.
+
+> let a = freeSelf (mouseX KR (-1) 1 Linear 0.1)
+> let b = out 0 (sinOsc AR 440 0 * 0.1)
+> audition (MRG [a, b])
diff --git a/Help/UGen/Envelope/freeSelfWhenDone.help.lhs b/Help/UGen/Envelope/freeSelfWhenDone.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Envelope/freeSelfWhenDone.help.lhs
@@ -0,0 +1,11 @@
+freeSelfWhenDone src
+
+Free the synth when the 'done' flag of the unit at `src' is set.
+
+> let x = mouseX KR (-1) 1 Linear 0.1
+>     e = linen x 1 0.1 1 RemoveSynth
+> 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
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Envelope/line.help.lhs
@@ -0,0 +1,12 @@
+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
+
+Note: The SC3 UGen reorders the mul and add inputs to precede the
+doneAction input.
+
+> audition (out 0 (sinOsc AR (line KR 200 17000 5 RemoveSynth) 0 * 0.1))
diff --git a/Help/UGen/Envelope/linen.help.lhs b/Help/UGen/Envelope/linen.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Envelope/linen.help.lhs
@@ -0,0 +1,15 @@
+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.
+
+> let e = linen (impulse KR 2 0) 0.01 0.6 0.4 DoNothing
+> 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 x 1.0 DoNothing
+> audition (out 0 (sinOsc AR 440 0 * e))
diff --git a/Help/UGen/Envelope/pause.help.lhs b/Help/UGen/Envelope/pause.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Envelope/pause.help.lhs
@@ -0,0 +1,23 @@
+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
+
+> 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' = graphdef "a" (graph a)
+> withSC3 (\fd -> do send fd (d_recv a')
+>                    wait fd "/done"
+>                    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)]))
+
+Restart node 1001.
+
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Envelope/pauseSelf.help.lhs
@@ -0,0 +1,11 @@
+pauseSelf src
+
+Pause enclosing synth when input signal crosses from non-positive to
+positive.
+
+> let x = mouseX KR (-1) 1 Linear 0.1
+> audition (MRG [pauseSelf x, out 0 (sinOsc AR 440 0 * 0.1)])
+
+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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Envelope/pauseSelfWhenDone.help.lhs
@@ -0,0 +1,11 @@
+pauseSelfWhenDone src
+
+Pauses the synth when the 'done' flag of the unit at `src' is set.
+
+> let x = mouseX KR (-1) 1 Linear 0.1
+>     e = linen x 1 0.1 1 PauseSynth
+> 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
+> audition (MRG [pauseSelfWhenDone e, out 0 (sinOsc AR 440 0 * e)])
diff --git a/Help/UGen/Envelope/xLine.help.lhs b/Help/UGen/Envelope/xLine.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Envelope/xLine.help.lhs
@@ -0,0 +1,16 @@
+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.
+
+Note: The sclang interface reorders the mul and add inputs to precede
+the doneAction input.
+
+> audition (out 0 (sinOsc AR (xLine KR 200 17000 10 RemoveSynth) 0 * 0.1))
diff --git a/Help/UGen/FFT/convolution.help.lhs b/Help/UGen/FFT/convolution.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/FFT/convolution.help.lhs
@@ -0,0 +1,13 @@
+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.
+
+in        - processing target
+kernel    - processing kernel.
+framesize - size of FFT frame, must be a power of two
+
+> let i = in' 2 AR numOutputBuses
+> k <- whiteNoise AR
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/FFT/fft.help.lhs
@@ -0,0 +1,21 @@
+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.
+
+> withSC3 (\fd -> do send fd (b_alloc 10 2048 1)
+>                    wait fd "/done")
+> n <- whiteNoise AR
+> audition (out 0 (ifft' (fft' 10 (n * 0.05))))
+
+> withSC3 (\fd -> do send fd (b_alloc 10 2048 1)
+>                    wait fd "/done")
+> let s0 = sinOsc KR 0.08 0 * 6 + 6.2
+>     s1 = sinOsc KR (squared s0) 0 * 100 + 800
+>     s2 = sinOsc AR s1 0
+> audition (out 0 (ifft' (fft' 10 s2) * 0.25))
diff --git a/Help/UGen/FFT/ifft.help.lhs b/Help/UGen/FFT/ifft.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/FFT/ifft.help.lhs
@@ -0,0 +1,6 @@
+ifft buffer
+
+Inverse Fast Fourier Transform.  The inverse fast fourier transform
+converts from frequency content to a signal.
+
+See fft.
diff --git a/Help/UGen/FFT/packFFT.help.lhs b/Help/UGen/FFT/packFFT.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/FFT/packFFT.help.lhs
@@ -0,0 +1,53 @@
+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.
+
+Here's an unusual example which uses PackFFT without using
+UnpackFFT first - essentially creating our FFT data from scratch.
+
+> 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)
+>     mkC = Constant . fromIntegral
+>     c2 = packFFT c1 512 0 (mkC n - 1) 1 (packFFTSpec m3 p)
+>     s = ifft' c2
+> audition (out 0 (MCE [s, s]))
diff --git a/Help/UGen/FFT/pv_BinScramble.help.lhs b/Help/UGen/FFT/pv_BinScramble.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/FFT/pv_BinScramble.help.lhs
@@ -0,0 +1,22 @@
+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.
+
+> let fileName = "/home/rohan/audio/metal.wav"
+> withSC3 (\fd -> do send fd (b_alloc 10 2048 1)
+>                    wait fd "/done"
+>                    send fd (b_allocRead 12 fileName 0 0)
+>                    wait fd "/done")
+> let a = playBuf 1 12 (bufRateScale KR 12) 1 0 Loop
+>     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 f x y (impulse KR 4 0)
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/FFT/pv_BinShift.help.lhs
@@ -0,0 +1,15 @@
+pv_BinShift buffer stretch shift
+
+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'.
+
+> withSC3 (\fd -> do send fd (b_alloc 10 2048 1)
+>                    wait fd "/done")
+> 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
+>     pv = pv_BinShift (fft' 10 s2) y x
+> audition (out 0 (pan2 (ifft' pv) 0 0.1))
diff --git a/Help/UGen/FFT/pv_BinWipe.help.lhs b/Help/UGen/FFT/pv_BinWipe.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/FFT/pv_BinWipe.help.lhs
@@ -0,0 +1,27 @@
+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.
+
+> let fileName = "/home/rohan/audio/metal.wav"
+> withSC3 (\fd -> do send fd (b_alloc 10 2048 1)
+>                    wait fd "/done"
+>                    send fd (b_alloc 11 2048 1)
+>                    wait fd "/done"
+>                    send fd (b_allocRead 12 fileName 0 0)
+>                    wait fd "/done")
+> n <- whiteNoise AR
+> let b = playBuf 1 12 (bufRateScale KR 12) 0 0 Loop
+>     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
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/FFT/pv_BrickWall.help.lhs
@@ -0,0 +1,11 @@
+pv_BrickWall buffer wipe
+
+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.
+
+> withSC3 (\fd -> do send fd (b_alloc 10 2048 1)
+>                    wait fd "/done")
+> n <- whiteNoise AR
+> let x = mouseX KR (-1) 1 Linear 0.1
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/FFT/pv_ConformalMap.help.lhs
@@ -0,0 +1,30 @@
+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
+
+buffer - buffer number of buffer to act on, passed in through a chain
+real   - real part of a.
+imag   - imaginary part of a.
+
+> withSC3 (\fd -> do send fd (b_alloc 10 1024 1)
+>                    wait fd "/done")
+> let i = in' 1 AR numOutputBuses * 0.5
+>     x = mouseX KR (-1) 1 Linear 0.1
+>     y = mouseY KR (-1) 1 Linear 0.1
+> audition (out 0 (pan2 (ifft' (pv_ConformalMap (fft' 10 i) x y)) 0 1))
+
+With filtering.
+
+> withSC3 (\fd -> do send fd (b_alloc 0 2048 1)
+>                    wait fd "/done")
+> 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
+>     c = fft' 0 s
+>     m = ifft' (pv_ConformalMap c x y)
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/FFT/pv_Copy.help.lhs
@@ -0,0 +1,21 @@
+pv_Copy bufferA bufferB
+
+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.
+
+bufferA - source buffer.
+bufferB - destination buffer.
+
+Proof of concept, silence
+
+> withSC3 (\fd -> do send fd (b_alloc 0 2048 1)
+>                    wait fd "/done"
+>                    send fd (b_alloc 1 2048 1)
+>                    wait fd "/done")
+> i <- lfClipNoise AR 100
+> let c0 = fft' 0 i
+>     c1 = pv_Copy c0 1
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/FFT/pv_Diffuser.help.lhs
@@ -0,0 +1,18 @@
+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.
+
+> let fileName = "/home/rohan/audio/metal.wav"
+> withSC3 (\fd -> do send fd (b_alloc 10 2048 1)
+>                    wait fd "/done"
+>                    send fd (b_allocRead 12 fileName 0 0)
+>                    wait fd "/done")
+> let a = playBuf 1 12 (bufRateScale KR 12) 0 0 Loop
+>     f = fft' 10 a
+>     x = mouseX KR 0 1 Linear 0.1
+>     h = pv_Diffuser f (x >* 0.5)
+> audition (out 0 (ifft' h * 0.5))
diff --git a/Help/UGen/FFT/pv_LocalMax.help.lhs b/Help/UGen/FFT/pv_LocalMax.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/FFT/pv_LocalMax.help.lhs
@@ -0,0 +1,18 @@
+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.
+
+> let fileName = "/home/rohan/audio/metal.wav"
+> withSC3 (\fd -> do send fd (b_alloc 10 2048 1)
+>                    wait fd "/done"
+>                    send fd (b_allocRead 12 fileName 0 0)
+>                    wait fd "/done")
+> let a = playBuf 1 12 (bufRateScale KR 12) 0 0 Loop
+>     f = fft' 10 a
+>     x = mouseX KR 0 100 Linear 0.1
+>     h = pv_LocalMax f x
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/FFT/pv_MagAbove.help.lhs
@@ -0,0 +1,27 @@
+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.
+
+> let fileName = "/home/rohan/audio/metal.wav"
+> withSC3 (\fd -> do send fd (b_alloc 10 2048 1)
+>                    wait fd "/done"
+>                    send fd (b_allocRead 12 fileName 0 0)
+>                    wait fd "/done")
+> let a = playBuf 1 12 (bufRateScale KR 12) 0 0 Loop
+>     f = fft' 10 a
+>     x = mouseX KR 0 100 Linear 0.1
+>     h = pv_MagAbove f x
+> audition (out 0 (ifft' h * 0.5))
+
+Synthesised input.
+
+> withSC3 (\fd -> do send fd (b_alloc 10 2048 1)
+>                    wait fd "/done")
+> 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
+>     h = pv_MagAbove f x
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/FFT/pv_MagBelow.help.lhs
@@ -0,0 +1,27 @@
+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.
+
+> let fileName = "/home/rohan/audio/metal.wav"
+> withSC3 (\fd -> do send fd (b_alloc 10 2048 1)
+>                    wait fd "/done"
+>                    send fd (b_allocRead 12 fileName 0 0)
+>                    wait fd "/done")
+> let a = playBuf 1 12 (bufRateScale KR 12) 0 0 Loop
+>     f = fft' 10 a
+>     x = mouseX KR 0 100 Linear 0.1
+>     h = pv_MagBelow f x
+> audition (out 0 (ifft' h * 0.5))
+
+Synthesised input.
+
+> withSC3 (\fd -> do send fd (b_alloc 10 2048 1)
+>                    wait fd "/done")
+> 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
+>     h = pv_MagBelow f x
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/FFT/pv_MagClip.help.lhs
@@ -0,0 +1,26 @@
+pv_MagClip buffer threshold
+
+Clip bins to a threshold.  Clips bin magnitudes to a maximum
+threshold.
+
+> let fileName = "/home/rohan/audio/metal.wav"
+> withSC3 (\fd -> do send fd (b_alloc 10 2048 1)
+>                    wait fd "/done"
+>                    send fd (b_allocRead 12 fileName 0 0)
+>                    wait fd "/done")
+> let a = playBuf 1 12 (bufRateScale KR 12) 0 0 Loop
+>     f = fft' 10 a
+>     x = mouseX KR 0 5 Linear 0.1
+>     h = pv_MagBelow f x
+> audition (out 0 (ifft' h * 0.5))
+
+Synthesised input.
+
+> withSC3 (\fd -> do send fd (b_alloc 10 2048 1)
+>                    wait fd "/done")
+> 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
+>     h = pv_MagClip f x
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/FFT/pv_MagFreeze.help.lhs
@@ -0,0 +1,26 @@
+pv_MagClip buffer threshold
+
+Clip bins to a threshold.  Clips bin magnitudes to a maximum
+threshold.
+
+> let fileName = "/home/rohan/audio/metal.wav"
+> withSC3 (\fd -> do send fd (b_alloc 10 2048 1)
+>                    wait fd "/done"
+>                    send fd (b_allocRead 12 fileName 0 0)
+>                    wait fd "/done")
+> let a = playBuf 1 12 (bufRateScale KR 12) 0 0 Loop
+>     f = fft' 10 a
+>     x = mouseX KR 0 1 Linear 0.1
+>     h = pv_MagFreeze f (x >* 0.5)
+> audition (out 0 (ifft' h * 0.5))
+
+Synthesised input.
+
+> withSC3 (\fd -> do send fd (b_alloc 10 2048 1)
+>                    wait fd "/done")
+> 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
+>     h = pv_MagFreeze f (x >* 0.5)
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/FFT/pv_RandComb.help.lhs
@@ -0,0 +1,14 @@
+pv_RandComb buffer wipe trig
+
+Randomly clear bins.
+
+buffer = fft buffer.  wipe = clear bins from input in a random
+order (0, 1).  trig = select new random ordering.
+
+> withSC3 (\fd -> do send fd (b_alloc 10 2048 1)
+>                    wait fd "/done")
+> let x = mouseX KR 0.6 0.95 Linear 0.1
+>     t = impulse KR 0.4 0
+> n <- whiteNoise AR
+> c <- pv_RandComb (fft' 10 (n * 0.5)) x t
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/FFT/pv_RandWipe.help.lhs
@@ -0,0 +1,26 @@
+pv_RandWipe bufferA bufferB wipe trig
+
+Cross fades between two sounds by copying bins in a random order.
+
+bufferA = fft buffer A.  bufferB = fft buffer B.  wipe = copies
+bins from bufferB in a random order (0, 1).  trig = select new
+random ordering.
+
+> withSC3 (\fd -> do send fd (b_alloc 10 2048 1)
+>                    wait fd "/done"
+>                    send fd (b_alloc 11 2048 1)
+>                    wait fd "/done")
+> 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)
+>     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)
+>     a  = mix (MCE o0)
+>     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
+> h <- pv_RandWipe f g x (y >* 0.5)
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/FFT/pv_RectComb.help.lhs
@@ -0,0 +1,17 @@
+pv_RectComb buffer numTeeth phase width
+
+> n <- whiteNoise AR
+> withSC3 (\fd -> do send fd (b_alloc 10 2048 1)
+>                    wait fd "/done")
+> 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
+> audition (out 0 (pan2 (ifft' c) 0 1))
+
+> n <- whiteNoise AR
+> withSC3 (\fd -> do send fd (b_alloc 10 2048 1)
+>                    wait fd "/done")
+> 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
+> audition (out 0 (pan2 (ifft' c) 0 1))
diff --git a/Help/UGen/FFT/pvcollect.help.lhs b/Help/UGen/FFT/pvcollect.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/FFT/pvcollect.help.lhs
@@ -0,0 +1,35 @@
+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.
+
+> withSC3 (\fd -> do let async p m = send p m >> wait p "/done"
+>                    async fd (b_alloc 10 1024 1)
+>                    async fd (b_allocRead 11 "/home/rohan/audio/metal.wav" 0 0))
+> let no_op m p _ = (m, p)
+>     combf m p i = ((modE i 7.0 ==* 0) * m, p)
+>     spectral_delay m p _ = (m + delayN m 1 v, p)
+>         where v = linLin (lfPar KR 0.5 0) (-1) 1 0.1 1
+>     bpf_sweep nf m p i = ((e <* 10) * m, p)
+>         where e = abs (i - (linLin (lfPar KR 0.1 0) (-1) 1 2 (nf / 20)))
+>     nf = 1024
+>     sf = playBuf 1 11 (bufRateScale KR 11) 1 0 Loop
+>     c1 = fft' 10 sf
+>     c2 = pvcollect c1 nf spectral_delay 0 250 0
+> audition (out 0 (0.1 * ifft' c2))
diff --git a/Help/UGen/Filter/allpassC.help.lhs b/Help/UGen/Filter/allpassC.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Filter/allpassC.help.lhs
@@ -0,0 +1,1 @@
+See allPassN
diff --git a/Help/UGen/Filter/allpassL.help.lhs b/Help/UGen/Filter/allpassL.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Filter/allpassL.help.lhs
@@ -0,0 +1,1 @@
+See allPassN
diff --git a/Help/UGen/Filter/allpassN.help.lhs b/Help/UGen/Filter/allpassN.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Filter/allpassN.help.lhs
@@ -0,0 +1,43 @@
+allpassN in maxDelayTime delayTime decayTime
+
+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.
+
+Since the allpass delay has no audible effect as a resonator on steady
+state sound ...
+
+> let dly = xLine KR 0.0001 0.01 20 RemoveSynth
+> n <- whiteNoise AR
+> 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.
+
+> n <- whiteNoise AR
+> let dly = xLine KR 0.0001 0.01 20 RemoveSynth
+> audition (out 0 ((n + allpassN (n * 0.1) 0.01 dly 0.2) * 0.1))
+
+Linear variant
+
+> n <- whiteNoise AR
+> let dly = xLine KR 0.0001 0.01 20 RemoveSynth
+> audition (out 0 ((n + allpassL (n * 0.1) 0.01 dly 0.2) * 0.1))
+
+Cubic variant
+
+> n <- whiteNoise AR
+> let dly = xLine KR 0.0001 0.01 20 RemoveSynth
+> 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.
+
+> n <- whiteNoise AR
+> d <- dust AR 1
+> let src = decay (d * 0.5) 0.2 * n
+> audition (out 0 (allpassN src 0.2 0.2 3))
diff --git a/Help/UGen/Filter/bpf.help.lhs b/Help/UGen/Filter/bpf.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Filter/bpf.help.lhs
@@ -0,0 +1,15 @@
+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
+
+> let f = fSinOsc KR (xLine KR 0.7 300 20 RemoveSynth) 0 * 3600 + 4000
+> audition (out 0 (bpf (saw AR 200 * 0.5) f 0.3 ))
+
+> n <- whiteNoise AR
+> let x = mouseX KR 220 440 Exponential 0.1
+> let y = mouseY KR 0 0.01 Linear 0.1
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Filter/bpz2.help.lhs
@@ -0,0 +1,7 @@
+bpz2 in
+
+Two zero fixed midpass.  This filter cuts out 0 Hz and the Nyquist
+frequency.
+
+> n <- whiteNoise AR
+> audition (out 0 (bpz2 (n * 0.25)))
diff --git a/Help/UGen/Filter/brf.help.lhs b/Help/UGen/Filter/brf.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Filter/brf.help.lhs
@@ -0,0 +1,6 @@
+brf in freq rq
+
+Second order Butterworth band reject filter.
+
+> let f = fSinOsc KR (xLine KR 0.7 300 20 RemoveSynth) 0 * 3800 + 4000
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Filter/clip.help.lhs
@@ -0,0 +1,6 @@
+clip in lo hi
+
+Clip `in' to lie between `lo' and `hi', which are instantiate time
+inputs.
+
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Filter/combC.help.lhs
@@ -0,0 +1,1 @@
+See combN.
diff --git a/Help/UGen/Filter/combL.help.lhs b/Help/UGen/Filter/combL.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Filter/combL.help.lhs
@@ -0,0 +1,1 @@
+See combN.
diff --git a/Help/UGen/Filter/combN.help.lhs b/Help/UGen/Filter/combN.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Filter/combN.help.lhs
@@ -0,0 +1,36 @@
+combN in maxDelayTime delayTime decayTime
+
+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.
+
+Comb used as a resonator. The resonant fundamental is equal to
+reciprocal of the delay time.
+
+> n <- whiteNoise AR
+> let dt = xLine KR 0.0001 0.01 20 RemoveSynth
+> audition (out 0 (combN (n * 0.1) 0.01 dt 0.2))
+
+> n <- whiteNoise AR
+> let dt = xLine KR 0.0001 0.01 20 RemoveSynth
+> audition (out 0 (combL (n * 0.1) 0.01 dt 0.2))
+
+> n <- whiteNoise AR
+> let dt = xLine KR 0.0001 0.01 20 RemoveSynth
+> audition (out 0 (combC (n * 0.1) 0.01 dt 0.2))
+
+With negative feedback:
+
+> n <- whiteNoise AR
+> let dt = xLine KR 0.0001 0.01 20 RemoveSynth
+> audition (out 0 (combC (n * 0.1) 0.01 dt (-0.2)))
+
+Used as an echo.
+
+> d <- dust AR 1
+> n <- whiteNoise AR
+> let i = decay (d * 0.5) 0.2 * n
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Filter/decay.help.lhs
@@ -0,0 +1,13 @@
+decay in decayTime
+
+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.
+
+Used as an envelope.
+
+> let s = impulse AR (xLine KR 1 50 20 RemoveSynth) 0.25
+> n <- pinkNoise AR
+> audition (out 0 (decay s 0.2 * n))
diff --git a/Help/UGen/Filter/decay2.help.lhs b/Help/UGen/Filter/decay2.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Filter/decay2.help.lhs
@@ -0,0 +1,19 @@
+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.
+
+decay2 AR i a d is equivalent to decay AR i d - decay AR i a
+
+Used as an envelope
+
+> let s = fSinOsc AR 600 0 * 0.25
+>     f = xLine KR 1 50 20 RemoveSynth
+> audition (out 0 (decay2 (impulse AR f 0.25) 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
+> audition (out 0 (decay (impulse AR f 0.25) 0.2 * s))
diff --git a/Help/UGen/Filter/degreeToKey.help.lhs b/Help/UGen/Filter/degreeToKey.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Filter/degreeToKey.help.lhs
@@ -0,0 +1,26 @@
+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.
+
+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.
+
+> withSC3 (\fd -> do send fd (b_alloc 0 7 1)
+>                    wait fd "/done"
+>                    send fd (b_setn 0 [(0, [0, 2, 3.2, 5, 7, 9, 10])]))
+
+> n <- lfNoise1 KR (MCE [3, 3.05])
+> let x = mouseX KR 0 15 Linear 0.1
+>     k = degreeToKey 0 x 12
+>     f b = combN m 0.31 0.31 2 + m
+>         where 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
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Filter/delay1.help.lhs
@@ -0,0 +1,6 @@
+delay1 in
+
+Fixed Single sample delay.
+
+> let s = impulse AR 1 0
+> audition (out 0 (s + (delay1 s)))
diff --git a/Help/UGen/Filter/delay2.help.lhs b/Help/UGen/Filter/delay2.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Filter/delay2.help.lhs
@@ -0,0 +1,6 @@
+delay2 in
+
+Fixed two sample delay.
+
+> let s = impulse AR 1 0
+> audition (out 0 (s + (delay2 s)))
diff --git a/Help/UGen/Filter/delayA.help.lhs b/Help/UGen/Filter/delayA.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Filter/delayA.help.lhs
@@ -0,0 +1,1 @@
+See delayN.
diff --git a/Help/UGen/Filter/delayL.help.lhs b/Help/UGen/Filter/delayL.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Filter/delayL.help.lhs
@@ -0,0 +1,1 @@
+See delayN.
diff --git a/Help/UGen/Filter/delayN.help.lhs b/Help/UGen/Filter/delayN.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Filter/delayN.help.lhs
@@ -0,0 +1,25 @@
+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.
+
+> d <- dust AR 1
+> n <- whiteNoise AR
+> let z = decay d 0.3 * n
+>     x = mouseX KR 0.0 0.2 Linear 0.1
+> 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
+> audition (out 0 (o + delayN o l x))
diff --git a/Help/UGen/Filter/formlet.help.lhs b/Help/UGen/Filter/formlet.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Filter/formlet.help.lhs
@@ -0,0 +1,13 @@
+formlet in freq attackTime decayTime
+
+FOF-like filter
+
+> audition (out 0 (formlet (impulse AR 20 0.5) 1000 0.01 0.1))
+
+> let f = xLine KR 10 400 8 RemoveSynth
+> 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
+> audition (out 0 (formlet s (xLine KR 1500 700 8 RemoveSynth) 0.005 0.04))
diff --git a/Help/UGen/Filter/fos.help.lhs b/Help/UGen/Filter/fos.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Filter/fos.help.lhs
@@ -0,0 +1,13 @@
+fos in a0 a1 b1
+
+First order filter section.
+
+Same as OnePole.
+
+> let x = lfTri AR 0.4 0 * 0.99
+> 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
+> audition (out 0 (fos (lfSaw AR 200 0 * 0.2) (1 - (abs x)) x 0))
diff --git a/Help/UGen/Filter/freqShift.help.lhs b/Help/UGen/Filter/freqShift.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Filter/freqShift.help.lhs
@@ -0,0 +1,39 @@
+freqShift input shift phase
+
+freq-shift implements 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) 
+
+shifting a 100Hz tone by 1 Hz rising to 500Hz
+
+> let i = sinOsc AR 100 0
+>     s = xLine KR 1 500 5 RemoveSynth
+> 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
+> audition (out 0 (freqShift i s 0 * 0.1))
+
+modulating shift and phase
+
+> s <- lfNoise2 AR 0.3
+> let i = sinOsc AR 10 0
+>     p = linLin (sinOsc AR 500 0) (-1) 1 0 (2 * pi)
+> audition (out 0 (freqShift i (s * 1500) p * 0.1))
+
+shifting bandpassed noise
+
+> n1 <- whiteNoise AR
+> n2 <- lfNoise0 AR 5.5
+> let i = bpf n1 1000 0.001
+>     s = n2 * 1000
+> audition (out 0 (freqShift i s 0 * 32))
diff --git a/Help/UGen/Filter/hasher.help.lhs b/Help/UGen/Filter/hasher.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Filter/hasher.help.lhs
@@ -0,0 +1,8 @@
+hasher in
+
+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.
+
+> audition (out 0 (hasher (line AR 0 1 1 RemoveSynth) * 0.2))
diff --git a/Help/UGen/Filter/hpf.help.lhs b/Help/UGen/Filter/hpf.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Filter/hpf.help.lhs
@@ -0,0 +1,6 @@
+hpf in freq
+
+Second order Butterworth highpass filter.
+
+> let f = fSinOsc KR (xLine KR 0.7 300 20 RemoveSynth) 0 * 3600 + 4000
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Filter/hpz1.help.lhs
@@ -0,0 +1,6 @@
+hpz1 in
+
+Two point difference filter.
+
+> n <- whiteNoise AR
+> audition (out 0 (hpz1 (n * 0.25)))
diff --git a/Help/UGen/Filter/hpz2.help.lhs b/Help/UGen/Filter/hpz2.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Filter/hpz2.help.lhs
@@ -0,0 +1,6 @@
+hpz2 in
+
+Two zero fixed highpass filter.
+
+> n <- whiteNoise AR
+> audition (out 0 (hpz2 (n * 0.25)))
diff --git a/Help/UGen/Filter/klank.help.lhs b/Help/UGen/Filter/klank.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Filter/klank.help.lhs
@@ -0,0 +1,23 @@
+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.
+
+freqoffset - an offset added to all frequencies at initialization
+             time.
+
+decayscale - a scale factor multiplied by all ring times at
+             initialization time.
+
+> let s = klankSpec [800, 1071, 1153, 1723] [1, 1, 1, 1] [1, 1, 1, 1]
+> audition (out 0 (klank (impulse AR 2 0 * 0.1) 1 0 1 s))
diff --git a/Help/UGen/Filter/lag.help.lhs b/Help/UGen/Filter/lag.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Filter/lag.help.lhs
@@ -0,0 +1,6 @@
+lag in lagTime
+
+A simple averaging filter.
+
+> let x = mouseX KR 220 440 Linear 0.2
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Filter/lag2.help.lhs
@@ -0,0 +1,6 @@
+lag2 in lagTime
+
+Lag2 is the same as lag KR (lag KR s t) t.
+
+> let x = mouseX KR 220 440 Exponential 0.1
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Filter/lag3.help.lhs
@@ -0,0 +1,6 @@
+lag3 in lagTime
+
+Lag3 is the same as lag KR (lag KR (lag KT s t) t) t.
+
+> let x = mouseX KR 220 440 Exponential 0.1
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Filter/latch.help.lhs
@@ -0,0 +1,26 @@
+latch in trig
+
+Sample and hold. Holds input signal value when triggered.
+
+in   - input signal.
+trig - trigger. The trigger can be any signal. A trigger happens when the
+       signal changes from non-positive to positive.
+
+> n <- whiteNoise AR
+> let i = impulse AR 9 0
+> let l = latch n i
+> 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 :
+
+> 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
+
+> 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
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Filter/leakDC.help.lhs
@@ -0,0 +1,7 @@
+leakDC in coef
+
+Remove DC.  This filter removes a DC offset from a signal.  in -
+input signal.  coef - leak coefficient.
+
+> let a = lfPulse AR 800 0.5 0.5 * 0.1
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Filter/limiter.help.lhs
@@ -0,0 +1,7 @@
+limiter input level lookAheadTime
+
+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.
diff --git a/Help/UGen/Filter/linExp.help.lhs b/Help/UGen/Filter/linExp.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Filter/linExp.help.lhs
@@ -0,0 +1,20 @@
+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.
+
+> let f = linExp (mouseX KR 0 1 Linear 0.2) 0 1 440 660
+> 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
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Filter/linLin.help.lhs
@@ -0,0 +1,19 @@
+linLin in srclo srchi dstlo dsthi
+
+Map a linear range to another linear range.
+
+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.
+
+> let f = linLin (mouseX KR 0 1 Linear 0.2) 0 1 440 660
+> 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 = linLin x 0 1 y 660
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Filter/lpf.help.lhs
@@ -0,0 +1,11 @@
+lpf in freq
+
+Second order Butterworth lowpass filter.
+
+> let f = xLine KR 0.7 300 20 RemoveSynth
+> audition (out 0 (lpf (saw AR 200 * 0.1) (fSinOsc KR f 0 * 3600 + 4000)))
+
+Control rate filtering.
+
+> let ctl = lpf (lfPulse KR 8 0 0.5) (mouseX KR 2 50 Exponential 0.1)
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Filter/lpz1.help.lhs
@@ -0,0 +1,6 @@
+lpz1 in
+
+Two point average filter
+
+> n <- whiteNoise AR
+> audition (out 0 (lpz1 (n * 0.25)))
diff --git a/Help/UGen/Filter/lpz2.help.lhs b/Help/UGen/Filter/lpz2.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Filter/lpz2.help.lhs
@@ -0,0 +1,6 @@
+lpz2 in
+
+Two zero fixed lowpass filter
+
+> n <- whiteNoise AR
+> audition (out 0 (lpz2 (n * 0.25)))
diff --git a/Help/UGen/Filter/mantissaMask.help.lhs b/Help/UGen/Filter/mantissaMask.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Filter/mantissaMask.help.lhs
@@ -0,0 +1,11 @@
+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.
+
+in - input signal
+bits - the number of mantissa bits to preserve. a number from 0 to 23.
+
+> let s = sinOsc AR (sinOsc KR 0.2 0 * 400 + 500) 0 * 0.4
+> audition (out 0 (mantissaMask s 3))
diff --git a/Help/UGen/Filter/median.help.lhs b/Help/UGen/Filter/median.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Filter/median.help.lhs
@@ -0,0 +1,24 @@
+median length in
+
+Median filter.
+
+Signal with impulse noise.
+
+> n <- dust2 AR 100
+> audition (out 0 (median 3 (saw AR 500 * 0.1 + n * 0.9)))
+
+The median length can be increased for longer duration noise.
+
+> n <- dust2 AR 100
+> 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
+> 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.
+
+> n <- whiteNoise AR
+> audition (out 0 (leakDC (median 31 (n * 0.1 + sinOsc AR 800 0 * 0.1)) 0.9))
diff --git a/Help/UGen/Filter/moogFF.help.lhs b/Help/UGen/Filter/moogFF.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Filter/moogFF.help.lhs
@@ -0,0 +1,26 @@
+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
+
+> n <- whiteNoise AR
+> let y = mouseY KR 100 10000 Exponential 0.1
+>     x = mouseX KR 0 4 Linear 0.1
+> audition (out 0 (moogFF (n * 0.1) y x 0))
+
+> n <- lfNoise0 KR 0.43
+> let p = pulse AR (MCE [40, 121]) (MCE [0.3, 0.7])
+>     f = linLin (sinOsc KR (linLin n 0 1 0.001 2.2) 0) (-1) 1 30 4200
+>     y = mouseY KR 1 4 Linear 0.1
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Filter/normalizer.help.lhs
@@ -0,0 +1,7 @@
+normalizer in level dur
+
+Flattens dynamics.
+
+> let s = fSinOsc AR 500 0
+>     z = decay2 (impulse AR 8 (lfSaw KR 0.25 (-0.6) * 0.7)) 0.001 0.3 * s
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Filter/onePole.help.lhs
@@ -0,0 +1,16 @@
+onePole in coef
+
+A one pole filter.  Implements the formula: out(i) = ((1 -
+abs(coef)) * in(i)) + (coef * out(i-1)).
+
+in   - input signal to be processed
+coef - feedback coefficient. Should be between -1 and +1
+
+> n <- whiteNoise AR
+> audition (out 0 (onePole (n * 0.5) 0.95))
+
+> n <- whiteNoise AR
+> audition (out 0 (onePole (n * 0.5) (-0.95)))
+
+> n <- whiteNoise AR
+> audition (out 0 (onePole (n * 0.5) (line KR (-0.99) 0.99 10 RemoveSynth)))
diff --git a/Help/UGen/Filter/oneZero.help.lhs b/Help/UGen/Filter/oneZero.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Filter/oneZero.help.lhs
@@ -0,0 +1,12 @@
+oneZero in coef
+
+One zero filter
+
+> n <- whiteNoise AR
+> audition (out 0 (oneZero (n * 0.5) 0.5))
+
+> n <- whiteNoise AR
+> audition (out 0 (oneZero (n * 0.5) (-0.5)))
+
+> n <- whiteNoise AR
+> audition (out 0 (oneZero (n * 0.5) (line KR (-0.5) 0.5 10 RemoveSynth)))
diff --git a/Help/UGen/Filter/pitchShift.help.lhs b/Help/UGen/Filter/pitchShift.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Filter/pitchShift.help.lhs
@@ -0,0 +1,7 @@
+pitchShift in winSize pchRatio pchDispersion timeDispersion
+
+A simple time domain pitch shifter.
+
+> let r = mouseX KR 0.5 2.0 Linear 0.1
+>     d = mouseY KR 0.0 0.1 Linear 0.1
+> audition (out 0 (pitchShift (sinOsc AR 440 0) 0.2 r d 0))
diff --git a/Help/UGen/Filter/resonz.help.lhs b/Help/UGen/Filter/resonz.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Filter/resonz.help.lhs
@@ -0,0 +1,31 @@
+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
+
+> n <- whiteNoise AR
+> audition (out 0 (resonz (n * 0.5) 2000 0.1))
+
+Modulate frequency
+
+> n <- whiteNoise AR
+> audition (out 0 (resonz (n * 0.5) (xLine KR 1000 8000 10 RemoveSynth) 0.05))
+
+Modulate bandwidth
+
+> n <- whiteNoise AR
+> audition (out 0 (resonz (n * 0.5) 2000 (xLine KR 1 0.001 8 RemoveSynth)))
+
+Modulate bandwidth opposite direction
+
+> n <- whiteNoise AR
+> audition (out 0 (resonz (n * 0.5) 2000 (xLine KR 0.001 1 8 RemoveSynth)))
diff --git a/Help/UGen/Filter/rhpf.help.lhs b/Help/UGen/Filter/rhpf.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Filter/rhpf.help.lhs
@@ -0,0 +1,6 @@
+rhpf in freq rq
+
+A resonant high pass filter.
+
+> let f = fSinOsc KR (xLine KR 0.7 300 20 RemoveSynth) 0 * 3600 + 4000
+> audition (out 0 (rhpf (saw AR 200 * 0.1) f 0.2))
diff --git a/Help/UGen/Filter/ringz.help.lhs b/Help/UGen/Filter/ringz.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Filter/ringz.help.lhs
@@ -0,0 +1,30 @@
+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.
+
+> n <- dust AR 3
+> audition (out 0 (ringz (n * 0.3) 2000 2))
+
+> n <- whiteNoise AR
+> audition (out 0 (ringz (n * 0.005) 2000 0.5))
+
+Modulate frequency
+
+> n <- whiteNoise AR
+> audition (out 0 (ringz (n * 0.005) (xLine KR 100 3000 10 RemoveSynth) 0.5))
+
+> let f = xLine KR 100 3000 10 RemoveSynth
+> audition (out 0 (ringz (impulse AR 6 0.3) f 0.5))
+
+Modulate ring time
+
+> let rt = xLine KR 4 0.04 8 RemoveSynth
+> 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
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Filter/rlpf.help.lhs
@@ -0,0 +1,6 @@
+rlpf in freq rq
+
+A resonant low pass filter.
+
+> let f = fSinOsc KR (xLine KR 0.7 300 20 RemoveSynth) 0 * 3600 + 4000
+> audition (out 0 (rlpf (saw AR 200 * 0.1) f 0.2))
diff --git a/Help/UGen/Filter/select.help.lhs b/Help/UGen/Filter/select.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Filter/select.help.lhs
@@ -0,0 +1,17 @@
+select which array
+
+The output is selected from an array of inputs.
+
+> let n = 3/2
+>     a = MCE [sinOsc AR 440 0, saw AR 440, pulse AR 440 0.1]
+> 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
+> audition (out 0 (saw AR (select (lfSaw KR 0.5 0 * c + c) a) * 0.2))
diff --git a/Help/UGen/Filter/shaper.help.lhs b/Help/UGen/Filter/shaper.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Filter/shaper.help.lhs
@@ -0,0 +1,15 @@
+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.
+
+> withSC3 (\fd -> do send fd (b_alloc 10 512 1)
+>                    wait fd "/done"
+>                    send fd (b_gen 10 "cheby" [0, 1, 0, 1, 1, 0, 1])
+>                    wait fd "/done")
+> audition (out 0 (shaper 10 (sinOsc AR 300 0 * line KR 0 1 6 RemoveSynth) * 0.5))
diff --git a/Help/UGen/Filter/slew.help.lhs b/Help/UGen/Filter/slew.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Filter/slew.help.lhs
@@ -0,0 +1,5 @@
+slew in up dn
+
+Has the effect of removing transients and higher frequencies.
+
+> audition (out 0 (slew (saw AR 800 * 0.2) 400 400))
diff --git a/Help/UGen/Filter/sos.help.lhs b/Help/UGen/Filter/sos.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Filter/sos.help.lhs
@@ -0,0 +1,13 @@
+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
+
+> let theta = line KR (0.2 * pi) pi 5 RemoveSynth
+>     rho = line KR 0.6 0.99 5 RemoveSynth
+>     b1 = 2 * rho * cos theta
+>     b2 = - (rho * rho)
+> audition (out 0 (sos (lfSaw AR 200 0 * 0.1) 1 0 0 b1 b2))
diff --git a/Help/UGen/Filter/twoPole.help.lhs b/Help/UGen/Filter/twoPole.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Filter/twoPole.help.lhs
@@ -0,0 +1,12 @@
+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.
+
+> n <- whiteNoise AR
+> audition (out 0 (twoPole (n * 0.005) 2000 0.95))
+
+> n <- whiteNoise AR
+> let f = xLine KR 800 8000 8 RemoveSynth
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Filter/twoZero.help.lhs
@@ -0,0 +1,6 @@
+twoZero in freq radius
+
+Two zero filter
+
+> n <- whiteNoise AR
+> audition (out 0 (twoZero (n * 0.125) (xLine KR 20 20000 8 RemoveSynth) 1))
diff --git a/Help/UGen/Filter/wrapIndex.help.lhs b/Help/UGen/Filter/wrapIndex.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Filter/wrapIndex.help.lhs
@@ -0,0 +1,18 @@
+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.
+
+> withSC3 (\fd -> do send fd (b_alloc 0 6 1)
+>                    wait fd "/done"
+>                    send fd (b_setn 0 [(0, [200, 300, 400, 500, 600, 800])]))
+
+> let x = mouseX KR 0 18 Linear 0.1
+>     f = wrapIndex 0 x
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Granular/grainBuf.help.lhs
@@ -0,0 +1,42 @@
+grainBuf nc tr dur sndbuf rate pos interp pan envbuf
+
+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.
+
+sndbuf - the buffer holding an audio signal
+
+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 singal to use for the
+       grain envelope. -1 uses a built-in Hanning envelope.
+
+> withSC3 (\fd -> send fd (b_allocRead 10 "/home/rohan/audio/metal.wav" 0 0))
+> n1 <- lfNoise1 KR 500
+> n2 <- lfNoise2 KR 0.1
+> 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 = linLin n1 (-1) 1 0.5 2
+>     p = linLin n2 (-1) 1 0 1
+> audition (out 0 (grainBuf 2 i 0.1 b r p 2 x e))
diff --git a/Help/UGen/Granular/grainFM.help.lhs b/Help/UGen/Granular/grainFM.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Granular/grainFM.help.lhs
@@ -0,0 +1,36 @@
+grainFM nc tr dur carfreq modfreq index pan envbuf
+
+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.
+
+> n1 <- whiteNoise KR
+> n2 <- lfNoise1 KR 500
+> let 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 10 0
+>     i = linLin n2 (-1) 1 1 10
+> audition (out 0 (grainFM 2 t 0.1 f 200 i x (-1) * 0.1))
diff --git a/Help/UGen/Granular/grainIn.help.lhs b/Help/UGen/Granular/grainIn.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Granular/grainIn.help.lhs
@@ -0,0 +1,27 @@
+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.
+
+> 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
+> audition (out 0 (grainIn 2 t 0.1 n x (-1) * 0.1))
diff --git a/Help/UGen/Granular/grainSin.help.lhs b/Help/UGen/Granular/grainSin.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Granular/grainSin.help.lhs
@@ -0,0 +1,28 @@
+grainSin nc tr dur freq pan envbuf
+
+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.
+
+> 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
+> audition (out 0 (grainSin 2 t 0.1 f x (-1) * 0.1))
diff --git a/Help/UGen/Granular/warp1.help.lhs b/Help/UGen/Granular/warp1.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Granular/warp1.help.lhs
@@ -0,0 +1,40 @@
+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).
+
+> withSC3 (\fd -> send fd (b_allocRead 10 "/home/rohan/audio/metal.wav" 0 0))
+> let 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
+> audition (out 0 w)
diff --git a/Help/UGen/IO/in.help.lhs b/Help/UGen/IO/in.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/IO/in.help.lhs
@@ -0,0 +1,28 @@
+in' numChannels rate bus
+
+Read signal from an audio or control bus.
+ 
+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
+> audition (out 0 (i + d))
+
+Write noise to bus 10, then read it out.  The MRG is ordered.
+
+> n <- pinkNoise AR
+> let wr = out 10 (n * 0.3)
+>     rd = out 0 (in' 1 AR 10)
+> audition (MRG [rd, wr])
+
+Reading a control bus.
+
+> withSC3 (\fd -> send fd (c_set [(0, 300)]))
+
+> audition (out 0 (sinOsc AR (in' 1 KR 0) 0 * 0.1))
+
+> withSC3 (\fd -> send fd (c_set [(0, 600)]))
diff --git a/Help/UGen/IO/inFeedback.help.lhs b/Help/UGen/IO/inFeedback.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/IO/inFeedback.help.lhs
@@ -0,0 +1,59 @@
+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.
+
+> let f = inFeedback 1 0 * 1300 + 300
+>     s = sinOsc AR f 0 * 0.4
+> audition (out 0 s)
+
+Evaluate these in either order and hear both tones.
+
+> let b = numInputBuses + numOutputBuses
+>     s = inFeedback 1 b
+> 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)
+> audition (MRG [s0, s1])
+
+Doubters consult this.
+
+> let b = numInputBuses + numOutputBuses
+>     s = in' 1 AR b
+> 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)
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/IO/inTrig.help.lhs
@@ -0,0 +1,18 @@
+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.
+
+Run an oscillator with the trigger at bus 10.
+
+> let t = inTrig 1 10
+>     e = envGen KR t t 0 1 DoNothing envPerc'
+> audition (out 0 (sinOsc AR 440 0 * e))
+
+Set bus 10, each set will trigger a ping.
+
+> let c_set1 i n = c_set [(i,n)]
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/IO/keyState.help.lhs
@@ -0,0 +1,9 @@
+keyState rate keyNum minVal maxVal lag
+
+Report the status of a particular key.  A key is either pressed, or
+not pressed.
+
+The keycode 38 is the A key on my keyboard.  Under X the xev(1)
+command is useful in determining your keyboard layout.
+
+> audition (out 0 (sinOsc AR 800 0 * keyState KR 38 0 0.1 0.5))
diff --git a/Help/UGen/IO/lagIn.lhs b/Help/UGen/IO/lagIn.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/IO/lagIn.lhs
@@ -0,0 +1,8 @@
+lagIn numChannels bus lag
+
+Smooth a control rate input signal.
+
+> withSC3 (\fd -> do send fd (c_set [(10, 200)])
+>                    play fd (sinOsc AR (lagIn 1 10 1) 0 * 0.1)
+>                    threadDelay 500000
+>                    send fd (c_set [(10, 2000)]))
diff --git a/Help/UGen/IO/localIn.help.lhs b/Help/UGen/IO/localIn.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/IO/localIn.help.lhs
@@ -0,0 +1,17 @@
+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.
+
+> n <- whiteNoise AR
+> let 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
+> audition (MRG [localOut (mceReverse a2 * 0.8), out 0 a2])
diff --git a/Help/UGen/IO/localOut.help.lhs b/Help/UGen/IO/localOut.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/IO/localOut.help.lhs
@@ -0,0 +1,35 @@
+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.
+
+> n <- whiteNoise AR
+> let 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
+> audition (MRG [localOut (mceReverse a2 * 0.8), 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)
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/IO/mouseButton.help.lhs
@@ -0,0 +1,6 @@
+mouseButton rate minval maxval lag
+
+Report the status of the first pointer button.  The button is either
+pressed, or not pressed.
+
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/IO/mouseX.help.lhs
@@ -0,0 +1,8 @@
+mouseX rate minval maxval warp lag
+
+Cursor UGen
+
+Report mouse location on root window of the machine that the synthesis
+server is running on.
+
+> audition (out 0 (sinOsc AR (mouseX KR 40 10000 Exponential 0.2) 0 * 0.1))
diff --git a/Help/UGen/IO/mouseY.help.lhs b/Help/UGen/IO/mouseY.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/IO/mouseY.help.lhs
@@ -0,0 +1,8 @@
+mouseY rate minval maxval warp lag
+
+Report mouse location on root window of the machine that the
+synthesis server is running on.
+
+> let freq = mouseX KR 20 2000 Exponential 0.1
+> let ampl = mouseY KR 0.01 0.1 Linear 0.1
+> audition (out 0 (sinOsc AR freq 0 * ampl))
diff --git a/Help/UGen/IO/offsetOut.help.lhs b/Help/UGen/IO/offsetOut.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/IO/offsetOut.help.lhs
@@ -0,0 +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.
+
+> let a = offsetOut 0 (impulse AR 5 0)
+>     b = out 0 (sinOsc AR 60 0 * 0.1)
+> audition (MRG [a,b])
+
+> let a = out 0 (impulse AR 5 0)
+>     b = out 0 (sinOsc AR 60 0 * 0.1)
+> audition (MRG [a,b])
diff --git a/Help/UGen/IO/out.help.lhs b/Help/UGen/IO/out.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/IO/out.help.lhs
@@ -0,0 +1,7 @@
+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.
+
+> audition (out 0 (sinOsc AR (MCE [330, 331]) 0 * 0.1))
diff --git a/Help/UGen/IO/replaceOut.help.lhs b/Help/UGen/IO/replaceOut.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/IO/replaceOut.help.lhs
@@ -0,0 +1,15 @@
+replaceOut bufferIndex inputs
+
+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)
+> 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)
+> audition (MRG [a, b, c])
diff --git a/Help/UGen/IO/xOut.help.lhs b/Help/UGen/IO/xOut.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/IO/xOut.help.lhs
@@ -0,0 +1,11 @@
+xOut bufferIndex xFade inputs
+ 
+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
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Information/controlRate.help.lhs
@@ -0,0 +1,1 @@
+controlRate
diff --git a/Help/UGen/Information/numAudioBuses.help.lhs b/Help/UGen/Information/numAudioBuses.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Information/numAudioBuses.help.lhs
@@ -0,0 +1,1 @@
+numAudioBuses
diff --git a/Help/UGen/Information/numBuffers.help.lhs b/Help/UGen/Information/numBuffers.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Information/numBuffers.help.lhs
@@ -0,0 +1,1 @@
+numBuffers
diff --git a/Help/UGen/Information/numControlBuses.help.lhs b/Help/UGen/Information/numControlBuses.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Information/numControlBuses.help.lhs
@@ -0,0 +1,1 @@
+numControlBuses
diff --git a/Help/UGen/Information/numInputBuses.help.lhs b/Help/UGen/Information/numInputBuses.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Information/numInputBuses.help.lhs
@@ -0,0 +1,1 @@
+numInputBuses
diff --git a/Help/UGen/Information/numOutputBuses.help.lhs b/Help/UGen/Information/numOutputBuses.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Information/numOutputBuses.help.lhs
@@ -0,0 +1,1 @@
+numOutputBuses
diff --git a/Help/UGen/Information/numRunningSynths.help.lhs b/Help/UGen/Information/numRunningSynths.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Information/numRunningSynths.help.lhs
@@ -0,0 +1,5 @@
+numRunningSynths
+
+Number of currently running synths.
+
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Information/radiansPerSample.help.lhs
@@ -0,0 +1,2 @@
+radiansPerSample
+
diff --git a/Help/UGen/Information/sampleDur.help.lhs b/Help/UGen/Information/sampleDur.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Information/sampleDur.help.lhs
@@ -0,0 +1,3 @@
+sampleDur
+
+Duration of one sample.  Equivalent to 1 / sampleRate.
diff --git a/Help/UGen/Information/sampleRate.help.lhs b/Help/UGen/Information/sampleRate.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Information/sampleRate.help.lhs
@@ -0,0 +1,8 @@
+sampleRate
+
+Server sample rate.
+
+Compare a sine tone derived from sample rate with a 440Hz tone.
+
+> let f = MCE [sampleRate * 0.01, 440]
+> audition (out 0 (sinOsc AR f 0 * 0.1))
diff --git a/Help/UGen/Information/subsampleOffset.help.lhs b/Help/UGen/Information/subsampleOffset.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Information/subsampleOffset.help.lhs
@@ -0,0 +1,35 @@
+subsampleOffset
+
+Offset from synth start within one sample.
+
+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.
+
+See also OffsetOut.
+
+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.
+
+> 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
+> withSC3 (\fd -> do send fd (d_recv (graphdef "s" (graph g)))
+>                    wait fd "/done"
+>                    t <- utc
+>                    let t' = t + 0.2
+>                        dt = 1 / 44100.0
+>                        m n = s_new "s" (-1) AddToTail 1 [("a", n)]
+>                    send fd (Bundle t' [m 3])
+>                    send fd (Bundle (t' + dt) [m 0]))
diff --git a/Help/UGen/Math/abs.help.lhs b/Help/UGen/Math/abs.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Math/abs.help.lhs
@@ -0,0 +1,5 @@
+abs a
+
+Absolute value.
+
+> audition (out 0 (abs (syncSaw AR 100 440 * 0.1)))
diff --git a/Help/UGen/Math/absDif.help.lhs b/Help/UGen/Math/absDif.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Math/absDif.help.lhs
@@ -0,0 +1,6 @@
+absDif a b
+
+Calculates the value of (abs (- a b). Finding the magnitude of the
+difference of two values is a common operation.
+
+> audition (out 0 (fSinOsc AR 440 0 * absDif 0.2 (fSinOsc AR 2 0 * 0.5)))
diff --git a/Help/UGen/Math/amClip.help.lhs b/Help/UGen/Math/amClip.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Math/amClip.help.lhs
@@ -0,0 +1,6 @@
+amClip a b
+
+0 when b <= 0, a*b when b > 0
+
+> n <- whiteNoise AR
+> audition (out 0 (amClip n (fSinOsc KR 1 0 * 0.2)))
diff --git a/Help/UGen/Math/atan2.help.lhs b/Help/UGen/Math/atan2.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Math/atan2.help.lhs
@@ -0,0 +1,18 @@
+atan2 x y
+
+Returns the arctangent of y/x.
+
+See also hypot.
+
+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.
+
+> let x = 10
+>     y = lfSaw KR (1 / 6) 0 * 100
+>     d = hypot x y
+>     a = 40 / (squared d)
+>     s = rlpf (fSinOsc AR 200 0 * lfPulse AR 31.3 0 0.4) 400 0.3
+>     z = Sound.SC3.atan2 y x
+>     l = clip2 (z / (pi / 2)) 1
+> audition (out 0 (pan2 (delayL s (110 / 344) (d / 344)) l a))
diff --git a/Help/UGen/Math/clip2.help.lhs b/Help/UGen/Math/clip2.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Math/clip2.help.lhs
@@ -0,0 +1,7 @@
+clip2 a b
+
+Bilateral clipping.  Clips a to +/- b
+
+> audition (out 0 (clip2 (fSinOsc AR 400 0) 0.2))
+
+> audition (out 0 (clip2 (fSinOsc AR 400 0) (line KR 0 1 8 RemoveSynth)))
diff --git a/Help/UGen/Math/difSqr.help.lhs b/Help/UGen/Math/difSqr.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Math/difSqr.help.lhs
@@ -0,0 +1,15 @@
+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.
+
+> let a = fSinOsc AR 800 0
+>     b = fSinOsc AR (xLine KR 200 500 5 DoNothing) 0
+> 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
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Math/distort.help.lhs
@@ -0,0 +1,7 @@
+distort a
+
+Nonlinear distortion.
+
+> let e = xLine KR 0.1 10 10 DoNothing
+>     o = fSinOsc AR 500 0.0
+> audition (out 0 (distort (o * e) * 0.25))
diff --git a/Help/UGen/Math/fold2.help.lhs b/Help/UGen/Math/fold2.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Math/fold2.help.lhs
@@ -0,0 +1,5 @@
+fold2 a b
+
+Bilateral folding.  Folds a to +/- b.
+
+> audition (out 0 (fold2 (fSinOsc AR 1000 0) (line KR 0 1 8 DoNothing)))
diff --git a/Help/UGen/Math/hypot.help.lhs b/Help/UGen/Math/hypot.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Math/hypot.help.lhs
@@ -0,0 +1,26 @@
+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).
+
+> let x = mouseX KR 0 0.1 Linear 0.1
+>     y = mouseY KR 0 0.1 Linear 0.1
+> 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
+>     v = slope d
+>     r = (344 - v) / 344
+>     a = 10 / (squared d)
+> audition (out 0 (fSinOsc AR (1000 * r) 0 * a))
+
+> let x = 10
+>     y = lfSaw KR (1 / 6) 0 * 100
+>     d = hypot x y
+>     a = 40 / (squared d)
+>     s = rlpf (fSinOsc AR 200 0 * lfPulse AR 31.3 0 0.4) 400 0.3
+> audition (out 0 (delayL s (110 / 344) (d / 344) * a))
diff --git a/Help/UGen/Math/ring1.help.lhs b/Help/UGen/Math/ring1.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Math/ring1.help.lhs
@@ -0,0 +1,11 @@
+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.
+
+> let a = fSinOsc AR 800 0
+>     b = fSinOsc AR (xLine KR 200 500 5 DoNothing) 0
+> audition (out 0 (ring1 a b * 0.125))
diff --git a/Help/UGen/Math/scaleNeg.help.lhs b/Help/UGen/Math/scaleNeg.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Math/scaleNeg.help.lhs
@@ -0,0 +1,5 @@
+scaleNeg a b
+
+Scale negative part of input wave.  a * b when a < 0, otherwise a.
+
+> audition (out 0 (scaleNeg (fSinOsc AR 500 0) (line AR 1 (-1) 4 RemoveSynth)))
diff --git a/Help/UGen/Math/softClip.help.lhs b/Help/UGen/Math/softClip.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Math/softClip.help.lhs
@@ -0,0 +1,8 @@
+softClip a
+
+Nonlinear distortion.  Distortion with a perfectly linear region
+from -0.5 to +0.5.
+
+> let e = xLine KR 0.1 10 10 DoNothing
+>     o = fSinOsc AR 500 0.0
+> audition (out 0 (softClip (o * e) * 0.25))
diff --git a/Help/UGen/Math/sumSqr.help.lhs b/Help/UGen/Math/sumSqr.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Math/sumSqr.help.lhs
@@ -0,0 +1,14 @@
+sumSqr a b
+
+Return the value of (a*a) + (b*b). This is more efficient than
+using separate unit generators for each operation.
+
+> let a = fSinOsc AR 800 0
+>     b = fSinOsc AR (xLine KR 200 500 5 DoNothing) 0
+> 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
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Math/thresh.help.lhs
@@ -0,0 +1,6 @@
+thresh a b
+
+Signal thresholding.  0 when a < b, otherwise a.
+
+> n <- lfNoise0 AR 50
+> audition (out 0 (thresh (n * 0.5) 0.45))
diff --git a/Help/UGen/Noise/brownNoise.help.lhs b/Help/UGen/Noise/brownNoise.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Noise/brownNoise.help.lhs
@@ -0,0 +1,12 @@
+brownNoise rate
+
+Generates noise whose spectrum falls off in power by 6 dB per
+octave.
+
+> n <- brownNoise AR
+> audition (out 0 (n * 0.1))
+
+> audition . (out 0) . (* 0.1) =<< whiteNoise AR
+
+> n <- brownNoise KR
+> audition (out 0 (sinOsc AR (linExp n (-1) 1 64 9600) 0 * 0.1))
diff --git a/Help/UGen/Noise/clipNoise.help.lhs b/Help/UGen/Noise/clipNoise.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Noise/clipNoise.help.lhs
@@ -0,0 +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.
+
+> audition . (out 0) . (* 0.1) =<< clipNoise AR
+
+> audition . (out 0) . (* 0.1) =<< whiteNoise AR
diff --git a/Help/UGen/Noise/coinGate.help.lhs b/Help/UGen/Noise/coinGate.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Noise/coinGate.help.lhs
@@ -0,0 +1,8 @@
+coinGate prob in
+
+When it receives a trigger, it tosses a coin, and either passes the
+trigger or doesn't.
+
+> g <- coinGate 0.2 (impulse KR 10 0)
+> f <- tRand 300.0 400.0 g
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Noise/dust.help.lhs
@@ -0,0 +1,9 @@
+dust rate density
+
+Generates random impulses from 0 to +1 at a rate determined by the
+density argument.
+
+> audition . (out 0) . (* 0.25) =<< dust AR 200
+
+> let d = xLine KR 20000 2 10 RemoveSynth
+> audition . (out 0) . (* 0.15) =<< dust AR d
diff --git a/Help/UGen/Noise/dust2.help.lhs b/Help/UGen/Noise/dust2.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Noise/dust2.help.lhs
@@ -0,0 +1,10 @@
+dust2 rate density
+
+Generates random impulses from -1 to +1.  The `density' is in
+impulses per second.
+
+> n <- dust2 AR 200
+> audition (out 0 (n * 0.5))
+
+> let d = xLine KR 20000 2 10 RemoveSynth
+> audition . (out 0 ) . (* 0.15) =<< dust2 AR d
diff --git a/Help/UGen/Noise/expRand.help.lhs b/Help/UGen/Noise/expRand.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Noise/expRand.help.lhs
@@ -0,0 +1,8 @@
+expRand lo hi
+
+Generates a single random float value in an exponential
+distributions from `lo' to `hi'.
+
+> let a = line KR 0.5 0 0.01 RemoveSynth
+> f <- expRand 100.0 8000.0
+> audition (out 0 (fSinOsc AR f 0 * a))
diff --git a/Help/UGen/Noise/grayNoise.help.lhs b/Help/UGen/Noise/grayNoise.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Noise/grayNoise.help.lhs
@@ -0,0 +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.
+
+> audition . (out 0) . (* 0.1) =<< grayNoise AR
diff --git a/Help/UGen/Noise/iRand.help.lhs b/Help/UGen/Noise/iRand.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Noise/iRand.help.lhs
@@ -0,0 +1,7 @@
+iRand lo hi
+
+Generates a single random integer value in uniform distribution
+from `lo' to `hi'.
+
+> f <- iRand 200 1200
+> audition (out 0 (fSinOsc AR f 0 * (line KR 0.2 0 0.1 RemoveSynth)))
diff --git a/Help/UGen/Noise/lfClipNoise.help.lhs b/Help/UGen/Noise/lfClipNoise.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Noise/lfClipNoise.help.lhs
@@ -0,0 +1,18 @@
+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.
+
+> audition . (out 0) . (* 0.05) =<< lfClipNoise AR 1000
+
+Modulate frequency
+
+> let f = xLine KR 1000 10000 10 RemoveSynth
+> audition . (out 0) . (* 0.05) =<< lfClipNoise AR f
+
+Use as frequency control
+
+> n <- lfClipNoise KR 4 
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Noise/lfNoise0.help.lhs
@@ -0,0 +1,17 @@
+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.
+
+> audition . (out 0) . (* 0.05) =<< lfNoise0 AR 1000
+
+Modulate frequency.
+
+> let f = xLine KR 1000 10000 10 RemoveSynth
+> n <- lfNoise0 AR f
+> audition (out 0 (n * 0.05))
+
+Use as frequency control.
+
+> f <- lfNoise0 KR 4 
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Noise/lfNoise1.help.lhs
@@ -0,0 +1,20 @@
+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.
+
+> audition . (out 0) . (* 0.05) =<< lfNoise1 AR 1000
+
+Modulate frequency.
+
+> let f = xLine KR 1000 10000 10 RemoveSynth
+> n <- lfNoise1 AR f
+> audition (out 0 (n * 0.05))
+
+Use as frequency control.
+
+> f <- lfNoise1 KR 4 
+> audition (out 0 (sinOsc AR (f * 400 + 450) 0 * 0.1))
diff --git a/Help/UGen/Noise/lfNoise2.help.lhs b/Help/UGen/Noise/lfNoise2.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Noise/lfNoise2.help.lhs
@@ -0,0 +1,18 @@
+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.
+
+> audition . (out 0) . (* 0.05) =<< lfNoise2 AR 1000
+
+Modulate frequency.
+
+> let f = xLine KR 1000 10000 10 RemoveSynth
+> n <- lfNoise2 AR f
+> audition (out 0 (n * 0.05))
+
+Use as frequency control.
+
+> f <- lfNoise2 KR 4 
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Noise/lfdClipNoise.help.lhs
@@ -0,0 +1,32 @@
+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.
+
+> let x = mouseX KR 0.1 1000 Exponential 0.2
+> n <- lfdClipNoise 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 AR x
+> 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
+> audition . (out 0) . (* 0.05) =<< lfdClipNoise AR f
+
+> let f = xLine KR 1000 20000 10 RemoveSynth
+> audition . (out 0) . (* 0.05) =<< lfClipNoise AR f
diff --git a/Help/UGen/Noise/lfdNoise0.help.lhs b/Help/UGen/Noise/lfdNoise0.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Noise/lfdNoise0.help.lhs
@@ -0,0 +1,37 @@
+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.
+
+> let x = mouseX KR 0.1 1000 Exponential 0.2
+> audition . (out 0) . (* 0.1) =<< lfdNoise0 AR x
+
+> let x = mouseX KR 0.1 1000 Exponential 0.2
+> audition . (out 0) . (* 0.1) =<< lfNoise0 AR x
+
+silent for 2 secs before going up in freq
+
+> let f = xLine KR 0.5 10000 3 RemoveSynth
+> audition . (out 0) . (* 0.1) =<< lfdNoise0 AR f
+
+> let f = xLine KR 0.5 10000 3 RemoveSynth
+> audition . (out 0) . (* 0.1) =<< lfNoise0 AR f
+
+LFNoise quantizes time steps at high freqs, LFDNoise does not:
+
+> let f = xLine KR 1000 20000 10 RemoveSynth
+> audition . (out 0) . (* 0.1) =<< lfdNoise0 AR f
+
+> let f = xLine KR 1000 20000 10 RemoveSynth
+> audition . (out 0) . (* 0.1) =<< lfNoise0 AR f
diff --git a/Help/UGen/Noise/lfdNoise1.help.lhs b/Help/UGen/Noise/lfdNoise1.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Noise/lfdNoise1.help.lhs
@@ -0,0 +1,5 @@
+lfdNoise1 rate freq
+
+Dynamic ramp noise. 
+
+See lfdNoise0 and lfNoise1.
diff --git a/Help/UGen/Noise/lfdNoise3.help.lhs b/Help/UGen/Noise/lfdNoise3.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Noise/lfdNoise3.help.lhs
@@ -0,0 +1,5 @@
+lfdnoise3 rate freq
+
+Dynamic cubic noise. 
+
+See lfNoise3 and lfdNoise0.
diff --git a/Help/UGen/Noise/linRand.help.lhs b/Help/UGen/Noise/linRand.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Noise/linRand.help.lhs
@@ -0,0 +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.
+
+> f <- linRand 200.0 10000.0 (MCE [-1, 1])
+> audition (out 0 (fSinOsc AR f 0 * line KR 0.4 0 0.01 RemoveSynth))
diff --git a/Help/UGen/Noise/nRand.help.lhs b/Help/UGen/Noise/nRand.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Noise/nRand.help.lhs
@@ -0,0 +1,12 @@
+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
+
+> n <- nRand 1200.0 4000.0 (MCE [2, 5])
+> audition (out 0 (fSinOsc AR n 0 * line KR 0.2 0 0.01 RemoveSynth))
diff --git a/Help/UGen/Noise/pinkNoise.help.lhs b/Help/UGen/Noise/pinkNoise.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Noise/pinkNoise.help.lhs
@@ -0,0 +1,11 @@
+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.
+
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Noise/rand.help.lhs
@@ -0,0 +1,11 @@
+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.
+
+> f <- rand 200 1200
+> l <- rand (-1) 1
+> let e = line KR 0.2 0 0.1 RemoveSynth
+>     o = fSinOsc AR f 0
+> audition (out 0 (pan2 (o * e) l 1))
diff --git a/Help/UGen/Noise/randID.help.lhs b/Help/UGen/Noise/randID.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Noise/randID.help.lhs
@@ -0,0 +1,8 @@
+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.
+
diff --git a/Help/UGen/Noise/randSeed.help.lhs b/Help/UGen/Noise/randSeed.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Noise/randSeed.help.lhs
@@ -0,0 +1,8 @@
+randSeed trig seed
+
+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.
+
+See also: RandID.
diff --git a/Help/UGen/Noise/tExpRand.help.lhs b/Help/UGen/Noise/tExpRand.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Noise/tExpRand.help.lhs
@@ -0,0 +1,9 @@
+tExpRand lo hi trig
+
+Generates a random float value in exponential distribution from lo
+to hi each time the trig signal changes from nonpositive to
+positive values lo and hi must both have the same sign and be
+non-zero.
+
+> f <- tExpRand 300.0 3000.0 =<< dust KR 10
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Noise/tRand.help.lhs
@@ -0,0 +1,7 @@
+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
+
+> f <- tRand (MCE [200, 1600]) (MCE [500, 3000]) =<< dust KR (MCE [5, 12])
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Noise/tiRand.help.lhs
@@ -0,0 +1,12 @@
+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
+
+> l <- tiRand (-1) 1 =<< dust KR 10
+> n <- pinkNoise AR
+> audition (out 0 (pan2 (n * 0.1) l 1))
+
+> f <- tiRand 4 12 =<< dust KR 10
+> audition (out 0 (sinOsc AR (f * 150 + (MCE [0,1])) 0 * 0.1))
diff --git a/Help/UGen/Noise/whiteNoise.help.lhs b/Help/UGen/Noise/whiteNoise.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Noise/whiteNoise.help.lhs
@@ -0,0 +1,5 @@
+whiteNoise rate
+
+Generates noise whose spectrum has equal power at all frequencies.
+
+> audition . (out 0) . (* 0.05) =<< whiteNoise AR
diff --git a/Help/UGen/Oscillator/blip.help.lhs b/Help/UGen/Oscillator/blip.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Oscillator/blip.help.lhs
@@ -0,0 +1,27 @@
+blip rate 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.
+
+> audition (out 0 (blip AR 440 200 * 0.1))
+
+Modulate frequency
+
+> audition (out 0 (blip AR (xLine KR 20000 200 6 RemoveSynth) 100 * 0.1))
+
+Modulate number of harmonics.
+
+> audition (out 0 (blip AR 200 (line KR 1 100 20 RemoveSynth) * 0.2))
diff --git a/Help/UGen/Oscillator/fSinOsc.help.lhs b/Help/UGen/Oscillator/fSinOsc.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Oscillator/fSinOsc.help.lhs
@@ -0,0 +1,24 @@
+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
+
+Note the phase argument, which was not in the SC2 variant.
+
+> audition (out 0 (fSinOsc AR (MCE [440, 550]) 0 * 0.05))
+
+> 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)
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Oscillator/formant.help.lhs
@@ -0,0 +1,17 @@
+formant rate 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.
+
+> audition (out 0 (formant AR (xLine KR 400 1000 8 RemoveSynth) 2000 800 * 0.125))
+
+Modulate formant frequency, fundamental frequency stays constant.
+
+> let f = MCE [200, 300, 400, 500]
+> audition (out 0 (formant AR f (xLine KR 400 4000 8 RemoveSynth) 200 * 0.125))
+
+Modulate width frequency, other frequencies stay constant.
+
+> audition (out 0 (formant AR 400 2000 (xLine KR 800 8000 8 RemoveSynth) * 0.1))
diff --git a/Help/UGen/Oscillator/gendy1.help.lhs b/Help/UGen/Oscillator/gendy1.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Oscillator/gendy1.help.lhs
@@ -0,0 +1,173 @@
+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.
+
+> let g = gendy1 AR 1 1 1 1 440 660 0.5 0.5 12 12
+> 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
+> 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
+> 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
+> 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
+> 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 
+> 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
+> 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
+> 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
+> 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
+> 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
+> 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
+> 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
+> audition (out 0 (pan2 g 0 0.2))
+
+Texture
+
+> let f _ = 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
+>              return (pan2 o l 0.1)
+> m <- mapM f [0..9]
+> audition (out 0 (mix (MCE m)))
+
+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
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Oscillator/impulse.help.lhs
@@ -0,0 +1,14 @@
+impulse rate freq iPhase
+
+Impulse oscillator.  Outputs non band limited single sample impulses.
+
+freq  - frequency in Hertz
+phase - phase offset in cycles (0..1)
+
+> audition (out 0 (impulse AR 800 0 * 0.1))
+
+> let f = xLine KR 800 10 5 RemoveSynth
+> audition (out 0 (impulse AR f 0.0 * 0.1))
+
+> let f = mouseY KR 4 8 Linear 0.1
+> audition (out 0 (impulse AR f (MCE [0, mouseX KR 0 1 Linear 0.1]) * 0.1))
diff --git a/Help/UGen/Oscillator/klang.help.lhs b/Help/UGen/Oscillator/klang.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Oscillator/klang.help.lhs
@@ -0,0 +1,9 @@
+klang rate freqScale freqOffset spec
+
+Bank of fixed oscillators.  spec is constructed using klangSpec, which
+takes lists of frequency, amplitude and phase.
+
+> let f = [440,550..1100]
+>     a = take 7 (cycle [0.05, 0.02])
+>     p = replicate 7 0
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Oscillator/lfCub.help.lhs
@@ -0,0 +1,29 @@
+lfCub rate freq iphase
+ 
+A sine like shape made of two cubic pieces. Smoother than lfPar.
+
+> audition (out 0 (lfCub AR (lfCub KR (lfCub KR 0.2 0 * 8 + 10) 0 * 400 + 800) 0 * 0.1))
+> audition (out 0 (lfCub AR (lfCub KR 0.2 0 * 400 + 800) 0 * 0.1))
+> 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):
+
+> 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):
+
+> 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):
+
+> 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))
+> audition (out 0 (lfTri AR (xLine KR 100 8000 30 DoNothing) 0 * 0.1))
diff --git a/Help/UGen/Oscillator/lfPar.help.lhs b/Help/UGen/Oscillator/lfPar.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Oscillator/lfPar.help.lhs
@@ -0,0 +1,5 @@
+lfPar rate freq iphase
+
+A sine-like shape made of two parabolas. Has audible odd harmonics.
+
+See lfCub.
diff --git a/Help/UGen/Oscillator/lfPulse.help.lhs b/Help/UGen/Oscillator/lfPulse.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Oscillator/lfPulse.help.lhs
@@ -0,0 +1,11 @@
+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.
+
+freq - frequency in Hertz
+iphase - initial phase offset in cycles ( 0..1 )
+width - pulse width duty cycle from zero to one.
+
+> audition (out 0 (lfPulse AR (lfPulse KR 3 0 0.3 * 200 + 200) 0 0.2 * 0.1))
diff --git a/Help/UGen/Oscillator/lfSaw.help.lhs b/Help/UGen/Oscillator/lfSaw.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Oscillator/lfSaw.help.lhs
@@ -0,0 +1,13 @@
+lfSaw rate freq iphase
+
+Sawtooth oscillator.  A non-band-limited sawtooth
+oscillator. Output ranges from -1 to +1.
+
+freq   - frequency in Hertz
+iphase - phase in radians
+
+> 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))
diff --git a/Help/UGen/Oscillator/lfTri.help.lhs b/Help/UGen/Oscillator/lfTri.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Oscillator/lfTri.help.lhs
@@ -0,0 +1,10 @@
+lfTri rate freq iphase
+
+A non-band-limited triangular waveform oscillator. Output ranges
+from -1 to +1.
+
+> 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))
diff --git a/Help/UGen/Oscillator/oscN.help.lhs b/Help/UGen/Oscillator/oscN.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Oscillator/oscN.help.lhs
@@ -0,0 +1,10 @@
+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.
+
diff --git a/Help/UGen/Oscillator/pulse.help.lhs b/Help/UGen/Oscillator/pulse.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Oscillator/pulse.help.lhs
@@ -0,0 +1,16 @@
+pulse rate freq width
+
+Bandlimited pulse wave generator.
+
+Modulate frequency
+
+> audition (out 0 (pulse AR (xLine KR 40 4000 6 RemoveSynth) 0.1 * 0.1))
+
+Modulate pulse width
+
+> audition (out 0 (pulse AR 200 (line KR 0.01 0.99 8 RemoveSynth) * 0.1))
+
+Two band limited square waves thru a resonant low pass filter
+
+> let p = pulse AR (MCE [100, 250]) 0.5 * 0.1
+> audition (out 0 (rlpf p (xLine KR 8000 400 5 RemoveSynth) 0.05))
diff --git a/Help/UGen/Oscillator/saw.help.lhs b/Help/UGen/Oscillator/saw.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Oscillator/saw.help.lhs
@@ -0,0 +1,10 @@
+saw rate freq
+
+Band limited sawtooth wave generator.
+
+> 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
+> audition (out 0 (rlpf (saw AR (MCE [100, 250]) * 0.1) f 0.05))
diff --git a/Help/UGen/Oscillator/silent.help.lhs b/Help/UGen/Oscillator/silent.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Oscillator/silent.help.lhs
@@ -0,0 +1,5 @@
+silent numberOfChannels
+
+Generate a silent (zero) signal.
+
+> audition (out 0 (silent 1))
diff --git a/Help/UGen/Oscillator/sinOsc.help.lhs b/Help/UGen/Oscillator/sinOsc.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Oscillator/sinOsc.help.lhs
@@ -0,0 +1,23 @@
+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
+
+> 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
+> audition (out 0 (sinOsc AR f 0 * 0.1))
+
+Modulate phase
+
+> let p = sinOsc AR (xLine KR 20 8000 10 RemoveSynth) 0 * 2 * pi
+> audition (out 0 (sinOsc AR 800 p * 0.1))
diff --git a/Help/UGen/Oscillator/syncSaw.help.lhs b/Help/UGen/Oscillator/syncSaw.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Oscillator/syncSaw.help.lhs
@@ -0,0 +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.
+
+> audition (out 0 (syncSaw AR 100 (line KR 100 800 12 RemoveSynth) * 0.1))
diff --git a/Help/UGen/Oscillator/tGrains.help.lhs b/Help/UGen/Oscillator/tGrains.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Oscillator/tGrains.help.lhs
@@ -0,0 +1,63 @@
+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.
+
+> let sync fd msg = send fd msg >> wait fd "/done"
+> withSC3 (\fd -> sync fd (b_allocRead 10 "/home/rohan/audio/metal.wav" 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
+> audition (out 0 (tGrains 2 tr 10 1 ctr (4 / tRate) 0 0.1 2))
+
+> let b = 10
+>     trate = mouseY KR 8 120 Exponential 0.1
+>     dur = 4 / trate
+> clk <- dust AR trate
+> r <- tRand 0 0.01 clk
+> let x = mouseX KR 0 (bufDur KR b) Linear 0.1
+>     pos = x + r
+> pan <- return . (* 0.6) =<< whiteNoise KR
+> audition (out 0 (tGrains 2 clk b 1 pos dur pan 0.1 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
+> pan <- return . (* 0.6) =<< whiteNoise KR
+> n <- whiteNoise KR
+> let rate = shiftLeft 1.2 (roundE (n * 3) 1)
+> audition (out 0 (tGrains 2 clk b rate pos dur pan 0.1 2))
diff --git a/Help/UGen/Oscillator/twChoose.help.lhs b/Help/UGen/Oscillator/twChoose.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Oscillator/twChoose.help.lhs
@@ -0,0 +1,20 @@
+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
+
+> let twChoose t a w n = select (twindex t n w) a
+>     x = mouseX KR 1 1000 Exponential 0.1
+> d <- dust AR x
+> let a = MCE [sinOsc AR 220 0,
+>              saw AR 440,
+>              pulse AR 110 0.1]
+> audition (out 0 (twChoose d a (MCE [0.5, 0.35, 0.15]) 0 * 0.1))
+
+Note: all the ugens are continously running. This may not be the
+most efficient way if each input is cpu-expensive.
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,21 @@
+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.0, when the normalize flag is set to 1,
+the values get normalized by the ugen (less efficient) Assuming
+normalized values
+
+> let p = MCE [1/5, 2/5, 2/5]
+>     a = MCE [400, 500, 600]
+>     t = impulse KR 6 0
+>     f = select (twindex t 0.0 p) a
+> audition (out 0 (sinOsc AR f 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
+>     f = select (twindex t 1.0 p) a
+> audition (out 0 (sinOsc AR f 0 * 0.1))
diff --git a/Help/UGen/Panner/linPan2.help.lhs b/Help/UGen/Panner/linPan2.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Panner/linPan2.help.lhs
@@ -0,0 +1,8 @@
+linPan2 in pos level
+
+Two channel linear pan.  See Pan2.
+
+> n <- pinkNoise AR
+> audition (out 0 (linPan2 n (fSinOsc KR 2 0) 0.1))
+
+> audition (out 0 (linPan2 (fSinOsc AR 800 0) (fSinOsc KR 3 0) 0.1))
diff --git a/Help/UGen/Panner/pan2.help.lhs b/Help/UGen/Panner/pan2.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Panner/pan2.help.lhs
@@ -0,0 +1,10 @@
+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.
+
+> n <- pinkNoise AR
+> audition (out 0 (pan2 n (fSinOsc KR 2 0) 0.3))
+
+> n <- pinkNoise AR
+> audition (out 0 (pan2 n (mouseX KR (-1) 1 Linear 0.2) (mouseY KR 0 1 Linear 0.2)))
diff --git a/Help/UGen/Panner/rotate2.help.lhs b/Help/UGen/Panner/rotate2.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Panner/rotate2.help.lhs
@@ -0,0 +1,32 @@
+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.
+
+> x <- pinkNoise AR
+> let y = lfTri AR 800 0 * lfPulse KR 3 0 0.3 * 0.2
+> 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
+> audition (out 0 (rotate2 x y (mouseX KR 0 2 Linear 0.2)))
diff --git a/Help/UGen/Panner/splay.help.lhs b/Help/UGen/Panner/splay.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Panner/splay.help.lhs
@@ -0,0 +1,16 @@
+splay in spread level center
+
+splay spreads an array of channels across the stereo field.
+
+spread -    0 = mono, 1 = stereo
+level  -    0 = silent, 1 = unit gain (equal power level compensated)
+center -    -1 = left, 1 = right
+
+> let i = 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
+> audition (out 0 (splay o y 0.2 x))
diff --git a/Help/UGen/Trigger/gate.help.lhs b/Help/UGen/Trigger/gate.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Trigger/gate.help.lhs
@@ -0,0 +1,6 @@
+gate in trig
+
+The signal at `in' is passed while `trig' is greater than zero.
+
+> let t = lfPulse AR 1 0 0.1
+> audition (out 0 (gate (fSinOsc AR 500 0 * 0.25) t))
diff --git a/Help/UGen/Trigger/inRange.help.lhs b/Help/UGen/Trigger/inRange.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Trigger/inRange.help.lhs
@@ -0,0 +1,14 @@
+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
+
+> n <- brownNoise AR
+> let x = mouseX KR 1 2 Linear 0.1
+> audition (out 0 (inRange (sinOsc KR x 0 * 0.2) (-0.15) 0.15 * n * 0.1))
diff --git a/Help/UGen/Trigger/lastValue.help.lhs b/Help/UGen/Trigger/lastValue.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Trigger/lastValue.help.lhs
@@ -0,0 +1,9 @@
+lastValue in diff
+
+Output the last value before the input changed more than a threshhold.
+
+> let x = mouseX KR 100 400 Linear 0.1
+> audition (out 0 (sinOsc AR (lastValue x 40) 0 * 0.1))
+
+> let x = mouseX KR 0.1 4 Linear 0.1
+> audition (out 0 (sinOsc AR (abs (lastValue x 0.5 - x) * 400 + 200) 0 * 0.2))
diff --git a/Help/UGen/Trigger/mostChange.help.lhs b/Help/UGen/Trigger/mostChange.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Trigger/mostChange.help.lhs
@@ -0,0 +1,7 @@
+mostChange a b
+
+Output the input that changed most.
+
+> n <- lfNoise0 KR 1
+> let x = mouseX KR 200 300 Linear 0.1
+> audition (out 0 (sinOsc AR (mostChange (n * 400 + 900) x) 0 * 0.1))
diff --git a/Help/UGen/Trigger/peak.help.lhs b/Help/UGen/Trigger/peak.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Trigger/peak.help.lhs
@@ -0,0 +1,8 @@
+peak trig reset
+
+Outputs the maximum value read at the `trig' input until `reset' is
+triggered.
+
+> t <- dust AR 20
+> let r = impulse AR 0.4 0
+> audition (out 0 (sinOsc AR (peak t r * 500 + 200) 0 * 0.2))
diff --git a/Help/UGen/Trigger/phasor.help.lhs b/Help/UGen/Trigger/phasor.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Trigger/phasor.help.lhs
@@ -0,0 +1,20 @@
+phasor 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.
+
+> let rate = mouseX KR 0.2 2 Exponential 0.1
+>     trig = impulse AR rate 0
+>     sr   = sampleRate
+>     x    = phasor AR trig (rate / sr) 0 1 0
+> audition (out 0 (sinOsc AR (MCE [linLin x 0 1 600 1000, 1000]) 0 * 0.2))
diff --git a/Help/UGen/Trigger/pulseCount.help.lhs b/Help/UGen/Trigger/pulseCount.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Trigger/pulseCount.help.lhs
@@ -0,0 +1,7 @@
+pulseCount trig reset
+
+This outputs the number of pulses received at `trig' and outputs
+that value until `reset' is triggered.
+
+> let c = pulseCount (impulse AR 10 0) (impulse AR 0.4 0)
+> audition (out 0 (sinOsc AR (c * 200) 0 * 0.05))
diff --git a/Help/UGen/Trigger/pulseDivider.help.lhs b/Help/UGen/Trigger/pulseDivider.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Trigger/pulseDivider.help.lhs
@@ -0,0 +1,12 @@
+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.
+
+> 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
+> audition (out 0 (a + b * 0.4))
+
diff --git a/Help/UGen/Trigger/runningMax.help.lhs b/Help/UGen/Trigger/runningMax.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Trigger/runningMax.help.lhs
@@ -0,0 +1,12 @@
+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
+
+> n <- dust AR 20
+> let t = impulse AR 0.4 0
+> audition (out 0 (sinOsc AR (runningMax n t * 500 + 200) 0 * 0.2))
diff --git a/Help/UGen/Trigger/runningMin.help.lhs b/Help/UGen/Trigger/runningMin.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Trigger/runningMin.help.lhs
@@ -0,0 +1,17 @@
+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
+
+> n <- dust AR 20
+> let t = impulse AR 0.4 0
+> audition (out 0 (sinOsc AR (runningMin n t * 500 + 200) 0 * 0.2))
+
+> let o = sinOsc KR 2 0
+>     x = mouseX KR 0.01 10 Exponential 0.1
+>     t = impulse AR x 0
+> audition (out 0 (sinOsc AR (runningMin o t * 500 + 200) 0 * 0.2))
diff --git a/Help/UGen/Trigger/sendTrig.lhs b/Help/UGen/Trigger/sendTrig.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Trigger/sendTrig.lhs
@@ -0,0 +1,25 @@
+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
+
+> withSC3 (\fd -> do send fd (notify True)
+>                    wait fd "/done")
+
+> s <- lfNoise0 KR 10
+> audition (MRG [sendTrig s 0 s, out 0 (sinOsc AR (s * 200 + 500) 0 * 0.1)])
+
+> withSC3 (\fd -> do tr <- wait fd "/tr"
+>                    putStrLn (show tr))
+
+> withSC3 (\fd -> do send fd (notify False)
+>                    wait fd "/done")
diff --git a/Help/UGen/Trigger/setResetFF.help.lhs b/Help/UGen/Trigger/setResetFF.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Trigger/setResetFF.help.lhs
@@ -0,0 +1,15 @@
+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
+
+> n <- brownNoise AR
+> d0 <- dust AR 5
+> d1 <- dust AR 5
+> audition (out 0 (setResetFF d0 d1 * n * 0.2))
diff --git a/Help/UGen/Trigger/sweep.help.lhs b/Help/UGen/Trigger/sweep.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Trigger/sweep.help.lhs
@@ -0,0 +1,34 @@
+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
+
+> let x = mouseX KR 0.5 20 Exponential 0.1
+>     t = impulse KR x 0
+> audition (out 0 (sinOsc AR (sweep t 700 + 500) 0 * 0.2))
+
+Using sweep to index into a buffer
+
+> withSC3 (\fd -> send fd (b_allocRead 0 "/home/rohan/audio/metal.wav" 0 0))
+
+> let x = mouseX KR 0.5 20 Exponential 0.1
+>     t = impulse AR x 0
+> audition (out 0 (bufRdL 1 AR 0 (sweep t (bufSampleRate KR 0)) NoLoop))
+
+Backwards, variable offset
+
+> n <- lfNoise0 KR 15
+> let 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)
+> 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
+> audition (out 0 (bufRdL 1 AR 0 (sweep t (bufSampleRate KR 0 * r)) NoLoop))
diff --git a/Help/UGen/Trigger/tDelay.help.lhs b/Help/UGen/Trigger/tDelay.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Trigger/tDelay.help.lhs
@@ -0,0 +1,11 @@
+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.
+
+> let z  = impulse AR 2 0
+>     z' = tDelay z 0.5
+> audition (out 0 (MCE [z * 0.1, toggleFF z' * sinOsc AR 440 0 * 0.1]))
diff --git a/Help/UGen/Trigger/timer.help.lhs b/Help/UGen/Trigger/timer.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Trigger/timer.help.lhs
@@ -0,0 +1,9 @@
+timer trig
+
+Returns time since last triggered
+	
+Using timer to modulate sine frequency: the slower the trigger is
+the higher the frequency
+
+> let t = impulse KR (mouseX KR 0.5 20 Exponential 0.1) 0
+> 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
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Trigger/toggleFF.help.lhs
@@ -0,0 +1,8 @@
+toggleFF trig
+
+Toggle flip flop. Toggles between zero and one upon receiving a trigger.
+
+trig - trigger input
+
+> t <- dust AR (xLine KR 1 1000 60 DoNothing)
+> audition (out 0 (sinOsc AR (toggleFF t * 400 + 800) 0 * 0.1))
diff --git a/Help/UGen/Trigger/trig.help.lhs b/Help/UGen/Trigger/trig.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Trigger/trig.help.lhs
@@ -0,0 +1,6 @@
+trig in dur
+
+When `in' is trigerred output the trigger value for `dur' seconds.
+
+> d <- dust AR 1
+> audition (out 0 (trig d 0.2 * fSinOsc AR 800 0 * 0.5))
diff --git a/Help/UGen/Trigger/trig1.help.lhs b/Help/UGen/Trigger/trig1.help.lhs
new file mode 100644
--- /dev/null
+++ b/Help/UGen/Trigger/trig1.help.lhs
@@ -0,0 +1,6 @@
+trig1 in dur
+
+When `in' is trigered output a unit signal for `dur' seconds.
+
+> d <- dust AR 1
+> audition (out 0 (trig1 d 0.2 * fSinOsc AR 800 0 * 0.2))
diff --git a/Setup.lhs b/Setup.lhs
new file mode 100644
--- /dev/null
+++ b/Setup.lhs
@@ -0,0 +1,3 @@
+#!/usr/bin/env runhaskell
+> import Distribution.Simple
+> main = defaultMain
diff --git a/Sound/SC3.hs b/Sound/SC3.hs
new file mode 100644
--- /dev/null
+++ b/Sound/SC3.hs
@@ -0,0 +1,6 @@
+module Sound.SC3 (module Sound.SC3.UGen,
+                  module Sound.SC3.Server) where
+
+import Sound.SC3.UGen
+import Sound.SC3.Server
+
diff --git a/Sound/SC3/Server.hs b/Sound/SC3/Server.hs
new file mode 100644
--- /dev/null
+++ b/Sound/SC3/Server.hs
@@ -0,0 +1,11 @@
+module Sound.SC3.Server ( module Sound.SC3.Server.Command
+                        , module Sound.SC3.Server.Graphdef
+                        , module Sound.SC3.Server.Play
+                        , module Sound.SC3.Server.Status
+                        , module Sound.SC3.Server.NRT ) where
+
+import Sound.SC3.Server.Command
+import Sound.SC3.Server.Graphdef
+import Sound.SC3.Server.Play
+import Sound.SC3.Server.Status
+import Sound.SC3.Server.NRT
diff --git a/Sound/SC3/Server/Command.hs b/Sound/SC3/Server/Command.hs
new file mode 100644
--- /dev/null
+++ b/Sound/SC3/Server/Command.hs
@@ -0,0 +1,243 @@
+module Sound.SC3.Server.Command where
+
+import Sound.OpenSoundControl (OSC(..), Datum(..))
+import Sound.SC3.Server.Utilities
+import Data.Word (Word8)
+
+-- * Instrument definition commands.
+
+-- | Install a bytecode instrument definition. (Asynchronous)
+d_recv :: [Word8] -> OSC
+d_recv b = Message "/d_recv" [Blob b]
+
+-- | Load an instrument definition from a named file. (Asynchronous)
+d_load :: String -> OSC
+d_load p = Message "/d_load" [String p]
+
+-- | Load a directory of instrument definitions files. (Asynchronous)
+d_loadDir :: String -> OSC
+d_loadDir p = Message "/d_loadDir" [String p]
+
+-- | Remove definition once all nodes using it have ended.
+d_free :: [String] -> OSC
+d_free n = Message "/d_free" (map String n)
+
+-- * Node commands.
+
+-- | Place a node after another.
+n_after :: [(Int, Int)] -> OSC
+n_after l = Message "/n_after" (mkDuples Int Int l)
+
+-- | Place a node before another.
+n_before :: [(Int, Int)] -> OSC
+n_before l = Message "/n_before" (mkDuples Int Int l)
+
+-- | Fill ranges of a node's control values.
+n_fill :: Int -> [(String, Int, Double)] -> OSC
+n_fill nid l = Message "/n_fill" (Int nid : mkTriples String Int Float l)
+
+-- | Delete a node.
+n_free :: [Int] -> OSC
+n_free nid = Message "/n_free" (map Int nid)
+
+-- | Map a node's controls to read from a bus.
+n_map :: Int -> [(String, Int)] -> OSC
+n_map nid l = Message "/n_map" (Int nid : mkDuples String Int l)
+
+-- | Map a node's controls to read from buses.
+n_mapn :: Int -> [(String, Int, Int)] -> OSC
+n_mapn nid l = Message "/n_mapn" (Int nid : mkTriples String Int Int l)
+
+-- | Get info about a node.
+n_query :: [Int] -> OSC
+n_query nid = Message "/n_query" (map Int nid)
+
+-- | Turn node on or off.
+n_run :: [(Int, Bool)] -> OSC
+n_run l = Message "/n_run" (mkDuples Int (Int . fromEnum) l)
+
+-- | Set a node's control values.
+n_set :: Int -> [(String, Double)] -> OSC
+n_set nid c = Message "/n_set" (Int nid : mkDuples String Float c)
+
+-- | Set ranges of a node's control values.
+n_setn :: Int -> [(String, [Double])] -> OSC
+n_setn nid l = Message "/n_setn" (Int nid : concatMap f l)
+    where f (s,d) = String s : Int (length d) : (map Float d)
+
+-- | Trace a node.
+n_trace :: [Int] -> OSC
+n_trace nid = Message "/n_trace" (map Int nid)
+
+-- * Synthesis node commands.
+
+-- | Get control values.
+s_get :: Int -> [String] -> OSC
+s_get nid i = Message "/s_get" (Int nid : map String i)
+
+-- | Get ranges of control values.
+s_getn :: Int -> [(String, Int)] -> OSC
+s_getn nid l = Message "/s_getn" (Int nid : mkDuples String Int l)
+
+-- | Enumeration of possible locations to add new nodes (s_new and g_new).
+data AddAction = AddToHead
+               | AddToTail
+               | AddBefore
+               | AddAfter
+               | AddReplace
+                 deriving (Eq, Show, Enum)
+
+-- | Create a new synth.
+s_new :: String -> Int -> AddAction -> Int -> [(String, Double)] -> OSC
+s_new n i a t c = Message "/s_new" (String n : Int i : Int (fromEnum a) : Int t : mkDuples String Float c)
+
+-- | Auto-reassign synth's ID to a reserved value.
+s_noid :: [Int] -> OSC
+s_noid nid = Message "/s_noid" (map Int nid)
+
+-- * Group node commands.
+
+-- | Free all synths in this group and all its sub-groups.
+g_deepFree :: [Int] -> OSC
+g_deepFree nid = Message "/g_deepFree" (map Int nid)
+
+-- | Delete all nodes in a group.
+g_freeAll :: [Int] -> OSC
+g_freeAll nid = Message "/g_freeAll" (map Int nid)
+
+-- | Add node to head of group.
+g_head :: [(Int, Int)] -> OSC
+g_head l = Message "/g_head" (mkDuples Int Int l)
+
+-- | Create a new group.
+g_new :: [(Int, AddAction, Int)] -> OSC
+g_new l = Message "/g_new" (mkTriples Int (Int . fromEnum) Int l)
+
+-- | Add node to tail of group.
+g_tail :: [(Int, Int)] -> OSC
+g_tail l = Message "/g_tail" (mkDuples Int Int l)
+
+-- * 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)
+
+-- * Buffer commands.
+
+-- | Allocates zero filled buffer to number of channels and samples. (Asynchronous)
+b_alloc :: Int -> Int -> Int -> OSC
+b_alloc nid frames channels = Message "/b_alloc" [Int nid, Int frames, Int channels]
+
+-- | Allocate buffer space and read a sound file.
+b_allocRead :: Int -> String -> Int -> Int -> OSC
+b_allocRead nid p f n = Message "/b_allocRead" [Int nid, String p, Int f, Int n]
+
+-- | Close attached soundfile and write header information.
+b_close :: Int -> OSC
+b_close nid = Message "/b_close" [Int nid]
+
+-- | Fill ranges of sample values.
+b_fill :: Int -> [(Int, Int, Double)] -> OSC
+b_fill nid l = Message "/b_fill" (Int nid : mkTriples Int Int Float l)
+
+-- | Free buffer data.
+b_free :: Int -> OSC
+b_free nid = Message "/b_free" [Int nid]
+
+-- | Call a command to fill a buffer.
+b_gen :: Int -> String -> [Double] -> OSC
+b_gen bid cmd arg = Message "/b_gen" (Int bid : String cmd : map Float arg)
+
+-- | Get sample values.
+b_get :: Int -> [Int] -> OSC
+b_get nid i = Message "/b_get" (Int nid : map Int i)
+
+-- | Get ranges of sample values.
+b_getn :: Int -> [(Int, Int)] -> OSC
+b_getn nid l = Message "/b_getn" (Int nid : mkDuples Int Int l)
+
+-- | Request \/b_info messages.
+b_query :: [Int] -> OSC
+b_query nid = Message "/b_query" (map Int nid)
+
+-- | Read sound file data into an existing buffer.
+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]
+
+-- | Set sample values.
+b_set :: Int -> [(Int, Double)] -> OSC
+b_set nid l = Message "/b_set" (Int nid : mkDuples Int Float l)
+
+-- | Set ranges of sample values.
+b_setn :: Int -> [(Int, [Double])] -> OSC
+b_setn nid l = Message "/b_setn" (Int nid : concatMap f l)
+    where f (i,d) = Int i : Int (length d) : map Float d
+
+-- | Write sound file data.
+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]
+
+-- | Zero sample data.
+b_zero :: Int -> OSC
+b_zero nid = Message "/b_zero" [Int nid]
+
+-- * Control bus commands.
+
+-- |  Fill ranges of bus values.
+c_fill :: [(Int, Int, Double)] -> OSC
+c_fill l = Message "/c_fill" (mkTriples Int Int Float l)
+
+-- | Get bus values.
+c_get :: [Int] -> OSC
+c_get nid = Message "/c_get" (map Int nid)
+
+-- | Get ranges of bus values.
+c_getn :: [(Int, Int)] -> OSC
+c_getn l = Message "/c_getn" (mkDuples Int Int l)
+
+-- | Set bus values.
+c_set :: [(Int, Double)] -> OSC
+c_set l = Message "/c_set" (mkDuples Int Float l)
+
+-- | Set ranges of bus values.
+c_setn :: [(Int, [Double])] -> OSC
+c_setn l = Message "/c_setn" (concatMap f l)
+    where f (i,d) = Int i : Int (length d) : map Float d
+
+-- * Server operation commands.
+
+-- | Remove all bundles from the scheduling queue.
+clearSched :: OSC
+clearSched = Message "/clearSched" []
+
+-- | Enumeration of OSC printer types.
+data PrintLevel = NoPrinter
+                | TextPrinter
+                | HexPrinter
+                | AllPrinter
+                  deriving (Eq, Show, Enum)
+
+-- | Select printing of incoming Open Sound Control messages.
+dumpOSC :: PrintLevel -> OSC
+dumpOSC c = Message "/dumpOSC" [Int (fromEnum c)]
+
+-- | Select reception of notification messages. (Asynchronous)
+notify :: Bool -> OSC
+notify c = Message "/notify" [Int (fromEnum c)]
+
+-- | Stop synthesis server.
+quit :: OSC
+quit = Message "/quit" []
+
+-- | Request \/status.reply message.
+status :: OSC
+status = Message "/status" []
+
+-- | Request \/synced message when all current asynchronous commands complete.
+sync :: Int -> OSC
+sync sid = Message "/sync" [Int sid]
+
+-- Local Variables:
+-- truncate-lines:t
+-- End:
diff --git a/Sound/SC3/Server/Graphdef.hs b/Sound/SC3/Server/Graphdef.hs
new file mode 100644
--- /dev/null
+++ b/Sound/SC3/Server/Graphdef.hs
@@ -0,0 +1,54 @@
+module Sound.SC3.Server.Graphdef (graphdef) where
+
+import Sound.OpenSoundControl.Byte
+import Sound.OpenSoundControl.Cast
+import Sound.SC3.UGen.UGen (UGen(..), Special(..))
+import Sound.SC3.UGen.Rate (rateId)
+import Sound.SC3.UGen.Graph
+
+import Data.Word
+import qualified Data.ByteString.Lazy as B
+
+-- | Byte-encode Input value.
+encode_input :: Input -> B.ByteString
+encode_input (Input u p) = B.append (encode_i16 u) (encode_i16 p)
+
+-- | Byte-encode Control value.
+encode_control :: Graph -> UGen -> B.ByteString
+encode_control g c@(Control _ n _) = B.concat [ B.pack (str_pstr n)
+                                              , encode_i16 (nodeIndex g c)]
+encode_control _ _  = error "encode_control: illegal input"
+
+-- | Byte-encode UGen value.
+encode_ugen :: Graph -> UGen -> B.ByteString
+encode_ugen g (UGen r n i o s _) = B.concat [ B.pack (str_pstr n)
+                                            , encode_i8 (rateId r)
+                                            , encode_i16 (length i)
+                                            , encode_i16 (length o)
+                                            , encode_i16 s'
+                                            , B.concat i'
+                                            , B.concat o' ]
+    where i' = map (encode_input . makeInput g) i
+          o' = map (encode_i8 . rateId) o
+          (Special s') = s
+encode_ugen _ _ = error "encode_ugen: illegal input"
+
+-- | Construct instrument definition bytecode.
+encode_graphdef :: String -> Graph -> B.ByteString
+encode_graphdef s g = B.concat [ encode_str "SCgf"
+                               , encode_i32 0
+                               , encode_i16 1
+                               , B.pack (str_pstr s)
+                               , encode_i16 (length n)
+                               , B.concat (map (encode_f32 . constantValue) n)
+                               , encode_i16 (length c)
+                               , B.concat (map (encode_f32 . controlDefault) c)
+                               , encode_i16 (length c)
+                               , B.concat (map (encode_control g) c)
+                               , encode_i16 (length u)
+                               , B.concat (map (encode_ugen g) u) ]
+    where (Graph n c u _) = g
+
+-- | Construct instrument definition bytecode.
+graphdef :: String -> Graph -> [Word8]
+graphdef s g = B.unpack (encode_graphdef s g)
diff --git a/Sound/SC3/Server/NRT.hs b/Sound/SC3/Server/NRT.hs
new file mode 100644
--- /dev/null
+++ b/Sound/SC3/Server/NRT.hs
@@ -0,0 +1,19 @@
+module Sound.SC3.Server.NRT ( encodeNRT 
+                            , writeNRT ) where
+
+import Sound.OpenSoundControl
+import qualified Data.ByteString.Lazy as B
+
+-- | Encode and prefix with encoded length.
+oscWithSize :: OSC -> B.ByteString
+oscWithSize o = B.append l b
+    where b = encodeOSC_NTP o
+          l = encode_i32 (fromIntegral (B.length b))
+
+-- | Encode a list of OSC bundles as an NRT score.
+encodeNRT :: [OSC] -> B.ByteString
+encodeNRT s = B.concat (map oscWithSize s)
+
+-- | Write an list of OSC bundles as an NRT score.
+writeNRT :: FilePath -> [OSC] -> IO ()
+writeNRT fn s = B.writeFile fn (encodeNRT s)
diff --git a/Sound/SC3/Server/Play.hs b/Sound/SC3/Server/Play.hs
new file mode 100644
--- /dev/null
+++ b/Sound/SC3/Server/Play.hs
@@ -0,0 +1,32 @@
+module Sound.SC3.Server.Play (play, stop, reset, withSC3, audition) where
+
+import Sound.OpenSoundControl
+import Sound.SC3.UGen.UGen (UGen(..))
+import Sound.SC3.UGen.Graph (graph)
+import Sound.SC3.Server.Graphdef (graphdef)
+import Sound.SC3.Server.Command (AddAction(AddToTail), s_new, d_recv, g_new, g_freeAll)
+
+-- | 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 g = graphdef "Anonymous" (graph u)
+               send fd (d_recv g) 
+               r <- wait fd "/done"
+               send fd (s_new "Anonymous" (-1) AddToTail 1 [])
+               return r
+
+-- | Free all nodes at the group with node id 1.
+stop :: Transport t => t -> IO ()
+stop fd = send fd (g_freeAll [1])
+
+-- | Free all nodes and re-create group node with id 1.
+reset :: Transport t => t -> IO ()
+reset fd = do send fd (g_freeAll [0])
+              send fd (g_new [(1, AddToTail, 0)])
+
+-- | Bracket SC3 communication.
+withSC3 :: (UDP -> IO a) -> IO a
+withSC3 = withTransport (openUDP "127.0.0.1" 57110)
+
+-- | withSC3 . play
+audition :: UGen -> IO ()
+audition g = withSC3 (\fd -> play fd g) >> return ()
diff --git a/Sound/SC3/Server/Status.hs b/Sound/SC3/Server/Status.hs
new file mode 100644
--- /dev/null
+++ b/Sound/SC3/Server/Status.hs
@@ -0,0 +1,28 @@
+module Sound.SC3.Server.Status (serverStatus) where
+
+import Sound.OpenSoundControl
+import Sound.SC3.Server.Command (status)
+
+statusFields :: [String]
+statusFields = ["# UGens                     ", 
+                "# Synths                    ", 
+                "# Groups                    ",
+                "# Instruments               ",
+                "% CPU (Average)             ",
+                "% CPU (Peak)                ",
+                "Sample Rate (Nominal)       ",
+                "Sample Rate (Actual)        "]
+
+statusInfo :: OSC -> [String]
+statusInfo (Message "status.reply" l) = map show (tail l)
+statusInfo _                          = error "non status.reply message"
+
+statusFormat :: OSC -> [String]
+statusFormat r = s : zipWith (++) statusFields (statusInfo r)
+    where s = "***** SuperCollider Server Status *****"
+
+-- | Collect server status information.
+serverStatus :: Transport t => t -> IO [String]
+serverStatus fd = do send fd status 
+                     r <- wait fd "status.reply"
+                     return (statusFormat r)
diff --git a/Sound/SC3/Server/Utilities.hs b/Sound/SC3/Server/Utilities.hs
new file mode 100644
--- /dev/null
+++ b/Sound/SC3/Server/Utilities.hs
@@ -0,0 +1,8 @@
+module Sound.SC3.Server.Utilities where
+
+mkDuples :: (a -> c) -> (b -> c) -> [(a, b)] -> [c]
+mkDuples a b = concatMap (\(x,y) -> [a x, b y])
+
+mkTriples :: (a -> d) -> (b -> d) -> (c -> d) -> [(a, b, c)] -> [d]
+mkTriples 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
new file mode 100644
--- /dev/null
+++ b/Sound/SC3/UGen.hs
@@ -0,0 +1,59 @@
+module Sound.SC3.UGen (module Sound.SC3.UGen.Analysis,
+                       module Sound.SC3.UGen.Buffer,
+                       module Sound.SC3.UGen.Chaos,
+                       module Sound.SC3.UGen.Demand,
+                       module Sound.SC3.UGen.Demand.Monadic,
+                       module Sound.SC3.UGen.Envelope,
+                       module Sound.SC3.UGen.Envelope.Construct,
+                       module Sound.SC3.UGen.Enum,
+                       module Sound.SC3.UGen.FFT,
+                       module Sound.SC3.UGen.FFT.Monadic,
+                       module Sound.SC3.UGen.Filter,
+                       module Sound.SC3.UGen.Graph,
+                       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.Mix,
+                       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.UGen.Construct,
+                       module Sound.SC3.UGen.UGen.Math,
+                       module Sound.SC3.UGen.UGen.MCE,
+                       module Sound.SC3.UGen.UGen.Predicate,
+                       module Sound.SC3.UGen.UId) where
+
+import Sound.SC3.UGen.Analysis
+import Sound.SC3.UGen.Buffer
+import Sound.SC3.UGen.Chaos
+import Sound.SC3.UGen.Demand
+import Sound.SC3.UGen.Demand.Monadic
+import Sound.SC3.UGen.Envelope
+import Sound.SC3.UGen.Envelope.Construct
+import Sound.SC3.UGen.Enum
+import Sound.SC3.UGen.FFT
+import Sound.SC3.UGen.FFT.Monadic
+import Sound.SC3.UGen.Filter
+import Sound.SC3.UGen.Graph
+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.Mix
+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.UGen.Construct
+import Sound.SC3.UGen.UGen.Math
+import Sound.SC3.UGen.UGen.MCE
+import Sound.SC3.UGen.UGen.Predicate
+import Sound.SC3.UGen.UId
diff --git a/Sound/SC3/UGen/Analysis.hs b/Sound/SC3/UGen/Analysis.hs
new file mode 100644
--- /dev/null
+++ b/Sound/SC3/UGen/Analysis.hs
@@ -0,0 +1,29 @@
+module Sound.SC3.UGen.Analysis where
+
+import Sound.SC3.UGen.Rate (Rate(KR))
+import Sound.SC3.UGen.UGen (UGen)
+import Sound.SC3.UGen.UGen.Construct (mkFilter, mkOsc)
+
+-- | Amplitude follower.
+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
+
+-- | Slope of signal.
+slope :: UGen -> UGen
+slope i = mkFilter "Slope" [i] 1
+
+-- | Zero crossing frequency follower.
+zeroCrossing :: UGen -> UGen
+zeroCrossing i = mkFilter "ZeroCrossing" [i] 1
+
+-- Local Variables:
+-- truncate-lines:t
+-- End:
diff --git a/Sound/SC3/UGen/Buffer.hs b/Sound/SC3/UGen/Buffer.hs
new file mode 100644
--- /dev/null
+++ b/Sound/SC3/UGen/Buffer.hs
@@ -0,0 +1,133 @@
+module Sound.SC3.UGen.Buffer where
+
+import Sound.SC3.UGen.Rate (Rate(AR))
+import Sound.SC3.UGen.UGen (UGen)
+import Sound.SC3.UGen.UGen.Construct (mkFilter, mkFilterMCE, mkOsc, mkOscMCE)
+import Sound.SC3.UGen.Enum (Loop, Interpolation(..))
+import Sound.SC3.UGen.Utilities (fromLoop, fromInterpolation)
+
+-- * Buffer query UGens.
+
+-- | Buffer channel count.
+bufChannels :: Rate -> UGen -> UGen
+bufChannels r buf = mkOsc r "BufChannels" [buf] 1
+
+-- | Buffer duration, in seconds.
+bufDur :: Rate -> UGen -> UGen
+bufDur r buf = mkOsc r "BufDur" [buf] 1
+
+-- | Buffer frame count.
+bufFrames :: Rate -> UGen -> UGen
+bufFrames r buf = mkOsc r "BufFrames" [buf] 1
+
+-- | Buffer rate scalar with respect to server sample rate.
+bufRateScale :: Rate -> UGen -> UGen
+bufRateScale r buf = mkOsc r "BufRateScale" [buf] 1
+
+-- | Buffer sample rate.
+bufSampleRate :: Rate -> UGen -> UGen
+bufSampleRate r buf = mkOsc r "BufSampleRate" [buf] 1
+
+-- | Buffer sample count (ie. frame count by channel count).
+bufSamples :: Rate -> UGen -> UGen
+bufSamples r buf = mkOsc r "BufSamples" [buf] 1
+
+-- * Buffer filters and delays.
+
+-- | Allpass filter (cubic interpolation).
+bufAllpassC :: UGen -> UGen -> UGen -> UGen -> UGen
+bufAllpassC buf i dly dcy = mkFilter "BufAllpassC" [buf,i,dly,dcy] 1
+
+-- | Allpass filter (linear interpolation).
+bufAllpassL :: UGen -> UGen -> UGen -> UGen -> UGen
+bufAllpassL buf i dly dcy = mkFilter "BufAllpassL" [buf,i,dly,dcy] 1
+
+-- | Allpass filter (no interpolation).
+bufAllpassN :: UGen -> UGen -> UGen -> UGen -> UGen
+bufAllpassN buf i dly dcy = mkFilter "BufAllpassN" [buf,i,dly,dcy] 1
+
+-- | Comb filter (cubic interpolation).
+bufCombC :: UGen -> UGen -> UGen -> UGen -> UGen
+bufCombC buf i dly dcy = mkFilter "BufCombC" [buf,i,dly,dcy] 1
+
+-- | Comb filter (linear interpolation).
+bufCombL :: UGen -> UGen -> UGen -> UGen -> UGen
+bufCombL buf i dly dcy = mkFilter "BufCombL" [buf,i,dly,dcy] 1
+
+-- | Comb filter (no interpolation).
+bufCombN :: UGen -> UGen -> UGen -> UGen -> UGen
+bufCombN buf i dly dcy = mkFilter "BufCombN" [buf,i,dly,dcy] 1
+
+-- | Delay line (cubic interpolation).
+bufDelayC :: UGen -> UGen -> UGen -> UGen
+bufDelayC buf i dly = mkFilter "BufDelayC" [buf,i,dly] 1
+
+-- | Delay line (linear interpolation).
+bufDelayL :: UGen -> UGen -> UGen -> UGen
+bufDelayL buf i dly = mkFilter "BufDelayL" [buf,i,dly] 1
+
+-- | Delay line (no interpolation).
+bufDelayN :: UGen -> UGen -> UGen -> UGen
+bufDelayN buf i dly = mkFilter "BufDelayN" [buf,i,dly] 1
+
+-- * Buffer I\/O.
+
+-- | Buffer reader.
+bufRd :: Int -> Rate -> UGen -> UGen -> Loop -> Interpolation -> UGen
+bufRd n r buf phs lp intp = mkOsc r "BufRd" [buf,phs,fromLoop lp,fromInterpolation intp] n
+
+-- | Buffer reader (no interpolation).
+bufRdN :: Int -> Rate -> UGen -> UGen -> Loop -> UGen
+bufRdN n r b p l = bufRd n r b p l NoInterpolation
+
+-- | Buffer reader (linear interpolation).
+bufRdL :: Int -> Rate -> UGen -> UGen -> Loop -> UGen
+bufRdL n r b p l = bufRd n r b p l LinearInterpolation
+
+-- | Buffer reader (cubic interpolation).
+bufRdC :: Int -> Rate -> UGen -> UGen -> Loop -> UGen
+bufRdC n r b p l = bufRd n r b p l CubicInterpolation
+
+-- | Buffer writer.
+bufWr :: UGen -> UGen -> Loop -> UGen -> UGen
+bufWr buf phs lp i = mkFilterMCE "BufWr" [buf,phs,fromLoop lp] i 0
+
+-- | Search a buffer for a value.
+detectIndex :: UGen -> UGen -> UGen
+detectIndex b i = mkFilter "DetectIndex" [b, i] 1
+
+-- | Index into table with signal.
+index :: UGen -> UGen -> UGen
+index b i = mkFilter "Index" [b, i] 1
+
+-- | Interpolating search in ordered table.
+indexInBetween :: UGen -> UGen -> UGen
+indexInBetween b i = mkFilter "IndexInBetween" [b, i] 1
+
+-- | Wavetable oscillator.
+osc :: Rate -> UGen -> UGen -> UGen -> UGen
+osc r bufnum freq phase = mkOsc r "Osc" [bufnum, freq, phase] 1
+
+-- | Buffer playback.
+playBuf :: Int -> UGen -> UGen -> UGen -> UGen -> Loop -> UGen
+playBuf n b r' t s l = mkOsc AR "PlayBuf" [b,r',t,s,fromLoop l] n
+
+-- | Buffer recording.
+recordBuf :: UGen -> UGen -> UGen -> UGen -> UGen -> Loop -> UGen -> UGen -> UGen
+recordBuf b o rl pl r l t i = mkOscMCE AR "RecordBuf" [b, o, rl, pl, r, fromLoop l, t] 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
+
+-- | Three variable wavetable oscillator.
+vOsc3 :: Rate -> UGen -> UGen -> UGen -> UGen -> UGen
+vOsc3 r b f1 f2 f3 = mkOsc r "VOsc3" [b, f1, f2, f3] 1
+
+-- | Variable wavetable oscillator.
+vOsc :: Rate -> UGen -> UGen -> UGen -> UGen
+vOsc r b f phase = mkOsc r "VOsc" [b, f, phase] 1
+
+-- Local Variables:
+-- truncate-lines:t
+-- End:
diff --git a/Sound/SC3/UGen/Chaos.hs b/Sound/SC3/UGen/Chaos.hs
new file mode 100644
--- /dev/null
+++ b/Sound/SC3/UGen/Chaos.hs
@@ -0,0 +1,85 @@
+module Sound.SC3.UGen.Chaos where
+
+import Sound.SC3.UGen.Rate (Rate)
+import Sound.SC3.UGen.UGen (UGen)
+import Sound.SC3.UGen.UGen.Construct (mkOsc)
+
+-- | Chaotic noise.
+crackle :: Rate -> UGen -> UGen
+crackle r chaosParam = mkOsc r "Crackle" [chaosParam] 1
+
+-- | Cusp map chaotic generator (linear interpolation).
+cuspL :: Rate -> UGen -> UGen -> UGen -> UGen -> UGen
+cuspL r freq a b xi = mkOsc r "CuspL" [freq, a, b, xi] 1
+
+-- | Cusp map chaotic generator (no interpolation).
+cuspN :: Rate -> UGen -> UGen -> UGen -> UGen -> UGen
+cuspN r freq a b xi = mkOsc r "CuspN" [freq, a, b, xi] 1
+
+-- | Feedback sine with chaotic phase indexing (cubic interpolation).
+fbSineC :: Rate -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
+fbSineC r freq im fb a c xi yi = mkOsc r "FBSineC" [freq, im, fb, a, c, xi, yi] 1
+
+-- | Feedback sine with chaotic phase indexing (linear interpolation).
+fbSineL :: Rate -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
+fbSineL r freq im fb a c xi yi = mkOsc r "FBSineL" [freq, im, fb, a, c, xi, yi] 1
+
+-- | Feedback sine with chaotic phase indexing (no interpolation).
+fbSineN :: Rate -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
+fbSineN r freq im fb a c xi yi = mkOsc r "FBSineN" [freq, im, fb, a, c, xi, yi] 1
+
+-- | Henon map chaotic generator (cubic interpolation).
+henonC :: Rate -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
+henonC r freq a b x0 x1 = mkOsc r "HenonC" [freq, a, b, x0, x1] 1
+
+-- | Henon map chaotic generator (linear interpolation).
+henonL :: Rate -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
+henonL r freq a b x0 x1 = mkOsc r "HenonL" [freq, a, b, x0, x1] 1
+
+-- | Henon map chaotic generator (no interpolation).
+henonN :: Rate -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
+henonN r freq a b x0 x1 = mkOsc r "HenonN" [freq, a, b, x0, x1] 1
+
+-- | Latoocarfian chaotic function (cubic interpolation).
+latoocarfianC :: Rate -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
+latoocarfianC r f a b c d xi yi = mkOsc r "LatoocarfianC" [f, a, b, c, d, xi, yi] 1
+
+-- | Latoocarfian chaotic function (linear interpolation).
+latoocarfianL :: Rate -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
+latoocarfianL r f a b c d xi yi = mkOsc r "LatoocarfianL" [f, a, b, c, d, xi, yi] 1
+
+-- | Latoocarfian chaotic function (no interpolation).
+latoocarfianN :: Rate -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
+latoocarfianN r f a b c d xi yi = mkOsc r "LatoocarfianN" [f, a, b, c, d, xi, yi] 1
+
+-- | Linear congruential chaotic generator (cubic interpolation).
+linCongC :: Rate -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
+linCongC r f a c m xi = mkOsc r "LinCongC" [f, a, c, m, xi] 1
+
+-- | Linear congruential chaotic generator (linear interpolation).
+linCongL :: Rate -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
+linCongL r f a c m xi = mkOsc r "LinCongL" [f, a, c, m, xi] 1
+
+-- | Linear congruential chaotic generator (no interpolation).
+linCongN :: Rate -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
+linCongN r f a c m xi = mkOsc r "LinCongN" [f, a, c, m, xi] 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
+
+-- | General quadratic map chaotic generator (cubic interpolation).
+quadC :: Rate -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
+quadC r freq a b c xi = mkOsc r "QuadC" [freq, a, b, c, xi] 1
+
+-- | General quadratic map chaotic generator (linear interpolation).
+quadL :: Rate -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
+quadL r freq a b c xi = mkOsc r "QuadL" [freq, a, b, c, xi] 1
+
+-- | General quadratic map chaotic generator (no interpolation).
+quadN :: Rate -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
+quadN r freq a b c xi = mkOsc r "QuadN" [freq, a, b, c, xi] 1
+
+-- Local Variables:
+-- truncate-lines:t
+-- End:
diff --git a/Sound/SC3/UGen/Demand.hs b/Sound/SC3/UGen/Demand.hs
new file mode 100644
--- /dev/null
+++ b/Sound/SC3/UGen/Demand.hs
@@ -0,0 +1,23 @@
+module Sound.SC3.UGen.Demand where
+
+import Sound.SC3.UGen.Rate (Rate)
+import Sound.SC3.UGen.UGen (UGen)
+import Sound.SC3.UGen.UGen.Construct (mkOsc, mkOscMCE, mkFilterKeyed)
+import Sound.SC3.UGen.Enum (DoneAction)
+import Sound.SC3.UGen.Utilities (fromDoneAction)
+
+-- | Demand results from demand rate ugens.
+demand :: UGen -> UGen -> UGen -> UGen
+demand t r d = mkFilterKeyed "Demand" 0 [t, r, d] 1
+
+-- | Demand envlope generator.
+demandEnvGen :: Rate -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> DoneAction -> UGen
+demandEnvGen r l d s c g rst ls lb ts a = mkOsc r "DemandEnvGen" [l,d,s,c,g,rst,ls,lb,ts,fromDoneAction a] 1
+
+-- | Demand results from demand rate ugens.
+duty :: Rate -> UGen -> UGen -> DoneAction -> UGen -> UGen
+duty rate d r act l = mkOsc rate "Duty" [d, r, fromDoneAction act, l] 1
+
+-- | Demand results as trigger from demand rate ugens.
+tDuty :: Rate -> UGen -> UGen -> DoneAction -> UGen -> UGen
+tDuty r d rst act l = mkOscMCE r "TDuty" [d,rst,fromDoneAction act] l 1
diff --git a/Sound/SC3/UGen/Demand/Base.hs b/Sound/SC3/UGen/Demand/Base.hs
new file mode 100644
--- /dev/null
+++ b/Sound/SC3/UGen/Demand/Base.hs
@@ -0,0 +1,55 @@
+module Sound.SC3.UGen.Demand.Base where
+
+import Sound.SC3.UGen.Rate (Rate(DR))
+import Sound.SC3.UGen.UGen (UGen, UGenId)
+import Sound.SC3.UGen.UGen.Construct (mkOscId, mkOscMCEId)
+import Sound.SC3.UGen.Enum
+import Sound.SC3.UGen.Utilities
+
+-- | Buffer demand ugen.
+dbufrd :: UGenId -> UGen -> UGen -> Loop -> UGen
+dbufrd z b p l = mkOscId z DR "Dbufrd" [b, p, fromLoop l] 1
+
+-- | Demand rate white noise.
+dwhite :: UGenId -> UGen -> UGen -> UGen -> UGen
+dwhite z l lo hi = mkOscId z DR "Dwhite" [l, lo, hi] 1
+
+-- | Demand rate integer white noise.
+diwhite :: UGenId -> UGen -> UGen -> UGen -> UGen
+diwhite z l lo hi = mkOscId z DR "Diwhite" [l, lo, hi] 1
+
+-- | Demand rate brown noise.
+dbrown :: UGenId -> UGen -> UGen -> UGen -> UGen -> UGen
+dbrown z l lo hi step = mkOscId z DR "Dbrown" [l, lo, hi, step] 1
+
+-- | Demand rate integer brown noise.
+dibrown :: UGenId -> UGen -> UGen -> UGen -> UGen -> UGen
+dibrown z l lo hi step = mkOscId z DR "Dibrown" [l, lo, hi, step] 1
+
+-- | Demand rate random selection.
+drand :: UGenId -> UGen -> UGen -> UGen
+drand z l array = mkOscMCEId z DR "Drand" [l] array 1
+
+-- | Demand rate random selection with no immediate repetition.
+dxrand :: UGenId -> UGen -> UGen -> UGen
+dxrand z l array = mkOscMCEId z DR "Dxrand" [l] array 1
+
+-- | Demand rate arithmetic series.
+dseries :: UGenId -> UGen -> UGen -> UGen -> UGen
+dseries z l i n = mkOscId z DR "Dseries" [l, i, n] 1
+
+-- | Demand rate geometric series.
+dgeom :: UGenId -> UGen -> UGen -> UGen -> UGen
+dgeom z l i n = mkOscId z DR "Dgeom" [l, i, n] 1
+
+-- | Demand rate sequence generator.
+dseq :: UGenId -> UGen -> UGen -> UGen
+dseq z l array = mkOscMCEId z DR "Dseq" [l] array 1
+
+-- | Demand rate series generator.
+dser :: UGenId -> UGen -> UGen -> UGen
+dser z l array = mkOscMCEId z DR "Dser" [l] array 1
+
+-- | Demand rate input switching.
+dswitch1 :: UGenId -> UGen -> UGen -> UGen
+dswitch1 z l array = mkOscMCEId z DR "Dswitch1" [l] array 1
diff --git a/Sound/SC3/UGen/Demand/Monadic.hs b/Sound/SC3/UGen/Demand/Monadic.hs
new file mode 100644
--- /dev/null
+++ b/Sound/SC3/UGen/Demand/Monadic.hs
@@ -0,0 +1,55 @@
+module Sound.SC3.UGen.Demand.Monadic where
+
+import Sound.SC3.UGen.UGen
+import Sound.SC3.UGen.UGen.Construct
+import qualified Sound.SC3.UGen.Demand.Base as D
+import Sound.SC3.UGen.UId
+import Sound.SC3.UGen.Enum
+
+-- | Buffer demand ugen.
+dbufrd :: (UId m) => UGen -> UGen -> Loop -> m UGen
+dbufrd = liftU3 D.dbufrd
+
+-- | Demand rate white noise.
+dwhite :: (UId m) => UGen -> UGen -> UGen -> m UGen
+dwhite = liftU3 D.dwhite
+
+-- | Demand rate integer white noise.
+diwhite :: (UId m) => UGen -> UGen -> UGen -> m UGen
+diwhite = liftU3 D.diwhite
+
+-- | Demand rate brown noise.
+dbrown :: (UId m) => UGen -> UGen -> UGen -> UGen -> m UGen
+dbrown = liftU4 D.dbrown
+
+-- | Demand rate integer brown noise.
+dibrown :: (UId m) => UGen -> UGen -> UGen -> UGen -> m UGen
+dibrown = liftU4 D.dibrown
+
+-- | Demand rate random selection.
+drand :: (UId m) => UGen -> UGen -> m UGen
+drand = liftU2 D.drand
+
+-- | Demand rate random selection with no immediate repetition.
+dxrand :: (UId m) => UGen -> UGen -> m UGen
+dxrand = liftU2 D.dxrand
+
+-- | Demand rate arithmetic series.
+dseries :: (UId m) => UGen -> UGen -> UGen -> m UGen
+dseries = liftU3 D.dseries
+
+-- | Demand rate geometric series.
+dgeom :: (UId m) => UGen -> UGen -> UGen -> m UGen
+dgeom = liftU3 D.dgeom
+
+-- | Demand rate sequence generator.
+dseq :: (UId m) => UGen -> UGen -> m UGen
+dseq = liftU2 D.dseq
+
+-- | Demand rate series generator.
+dser :: (UId m) => UGen -> UGen -> m UGen
+dser = liftU2 D.dser
+
+-- | Demand rate input switching.
+dswitch1 :: (UId m) => UGen -> UGen -> m UGen
+dswitch1 = liftU2 D.dswitch1
diff --git a/Sound/SC3/UGen/Enum.hs b/Sound/SC3/UGen/Enum.hs
new file mode 100644
--- /dev/null
+++ b/Sound/SC3/UGen/Enum.hs
@@ -0,0 +1,40 @@
+module Sound.SC3.UGen.Enum where
+
+import Sound.SC3.UGen.UGen (UGen(..))
+
+-- | Loop indicator input.
+data Loop = Loop
+          | NoLoop
+          | WithLoop UGen
+            deriving (Eq, Show)
+
+-- | Interpolation indicator input.
+data Interpolation = NoInterpolation
+                   | LinearInterpolation
+                   | CubicInterpolation
+                   | Interpolation UGen
+                     deriving (Eq, Show)
+
+-- | Completion mode indicator input.
+data DoneAction = DoNothing
+                | PauseSynth
+                | RemoveSynth
+                | DoneAction UGen
+                  deriving (Eq, Show)
+
+-- | Warp interpolation indicator input.
+data Warp = Linear
+          | Exponential
+          | Warp UGen
+            deriving (Eq, Show)
+
+-- | Envelope curve indicator input.
+data EnvCurve = EnvStep
+              | EnvLin
+              | EnvExp
+              | EnvSin
+              | EnvCos
+              | EnvNum UGen
+              | EnvSqr
+              | EnvCub
+              deriving (Eq, Show)
diff --git a/Sound/SC3/UGen/Envelope.hs b/Sound/SC3/UGen/Envelope.hs
new file mode 100644
--- /dev/null
+++ b/Sound/SC3/UGen/Envelope.hs
@@ -0,0 +1,57 @@
+module Sound.SC3.UGen.Envelope where
+
+import Sound.SC3.UGen.UGen (UGen(..))
+import Sound.SC3.UGen.UGen.Construct (mkOsc, mkFilter)
+import Sound.SC3.UGen.Rate (Rate)
+import Sound.SC3.UGen.Enum (DoneAction)
+import Sound.SC3.UGen.Utilities (fromDoneAction)
+
+-- | 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, fromDoneAction act] ++ pts
+
+-- | Line generator.
+line :: Rate -> UGen -> UGen -> UGen -> DoneAction -> UGen
+line r start end dur act = mkOsc r "Line" [start, end, dur, fromDoneAction act] 1
+
+-- | Exponential line generator.
+xLine :: Rate -> UGen -> UGen -> UGen -> DoneAction -> UGen
+xLine r start end dur act = mkOsc r "XLine" [start, end, dur, fromDoneAction act] 1
+
+-- | Free node on trigger.
+freeSelf :: UGen -> UGen
+freeSelf i = mkFilter "FreeSelf" [i] 0
+
+-- | Free node on done action at source.
+freeSelfWhenDone :: UGen -> UGen
+freeSelfWhenDone i = mkFilter "FreeSelfWhenDone" [i] 0
+
+-- | Pause specified node on trigger.
+pause :: UGen -> UGen -> UGen
+pause t n = mkFilter "Pause" [t, n] 1
+
+-- | Pause node on trigger.
+pauseSelf :: UGen -> UGen
+pauseSelf i = mkFilter "PauseSelf" [i] 0
+
+-- | Pause node on done action at source.
+pauseSelfWhenDone :: UGen -> UGen
+pauseSelfWhenDone i = mkFilter "PauseSelfWhenDone" [i] 0
+
+-- | One while the source is marked done, else zero.
+done :: UGen -> UGen
+done i = mkFilter "Done" [i] 1
+
+-- | Raise specified done action when input goes silent.
+detectSilence ::  UGen -> UGen -> UGen -> DoneAction -> UGen
+detectSilence i a t act = mkFilter "DetectSilence" [i, a, t, fromDoneAction act] 0
+
+-- | When triggered free specified node.
+free :: UGen -> UGen -> UGen
+free i n = mkFilter "Free" [i, n] 1
+
+-- | Linear envelope generator.
+linen :: UGen -> UGen -> UGen -> UGen -> DoneAction -> UGen
+linen g at sl rt da = mkFilter "Linen" [g,at,sl,rt,fromDoneAction da] 1
+
diff --git a/Sound/SC3/UGen/Envelope/Construct.hs b/Sound/SC3/UGen/Envelope/Construct.hs
new file mode 100644
--- /dev/null
+++ b/Sound/SC3/UGen/Envelope/Construct.hs
@@ -0,0 +1,59 @@
+module Sound.SC3.UGen.Envelope.Construct where
+
+import Sound.SC3.UGen.UGen (UGen(..))
+import Sound.SC3.UGen.UGen.Math ()
+import Sound.SC3.UGen.Math ((>=*), (<=*))
+import Sound.SC3.UGen.Enum (EnvCurve(..))
+import Sound.SC3.UGen.Utilities (dbl, d_dx, env_curve, env_value)
+
+-- | Basic envelope data constructor.
+env :: [UGen] -> [UGen] -> [EnvCurve] -> UGen -> UGen -> [UGen]
+env []     _   _   _   _  = error "env: illegal specification"
+env (l:vl) tms crv rls lp =
+    [l, n', rls, lp] ++ concat (zipWith3 f vl tms (take n $ cycle crv))
+    where f l' t c = [l', t, env_curve c, env_value c]
+          n       = length tms
+          n'      = fromIntegral n
+
+-- | Co-ordinate based static envelope generator.
+envCoord :: [(UGen, UGen)] -> UGen -> UGen -> EnvCurve -> [UGen]
+envCoord bp dur amp c = env l t (repeat c) (-1) (-1)
+    where l = map (* amp) (map snd bp)
+          t = map (* dur) (d_dx (map fst bp))
+
+-- | Trapezoidal envelope generator.
+envTrapezoid ::
+     UGen {- ^ @shape@ determines the sustain time as a proportion of @dur@:
+               zero is a triangular envelope, one a rectangular envelope. -}
+  -> UGen {- ^ @skew@ determines the attack\/decay ratio:
+               zero is an immediate attack and a slow decay,
+               one a slow attack and an immediate decay. -}
+  -> UGen {- ^ @dur@ -}
+  -> UGen {- ^ @amplitude@ -}
+  -> [UGen]
+envTrapezoid shape skew dur amp = envCoord bp dur amp EnvLin
+    where x1 = skew * (1 - shape)
+          bp = [ (0, skew <=* 0)
+               , (x1, 1)
+               , (shape + x1, 1)
+               , (1, skew >=* 1) ]
+
+envPerc :: UGen -> UGen -> UGen -> [EnvCurve] -> [UGen]
+envPerc atk rls lvl crv = env [0.0, lvl, 0.0] [atk, rls] crv (-1.0) (-1.0)
+
+envPerc' :: [UGen]
+envPerc' = envPerc 0.01 1.0 1.0 (dbl (EnvNum (-4.0)))
+
+-- Triangular envelope parameter constructor.
+envTriangle :: UGen -> UGen -> [UGen]
+envTriangle dur lvl =
+   env [0.0, lvl, 0.0] (dbl (dur / 2.0)) (dbl EnvLin) (-1.0) (-1.0)
+
+-- Sine envelope parameter constructor.
+envSine :: UGen -> UGen -> [UGen]
+envSine dur lvl =
+   env [0.0, lvl, 0.0] (dbl (dur / 2.0)) (dbl EnvSin) (-1.0) (-1.0)
+
+-- Linear envelope parameter constructor.
+envLinen :: UGen -> UGen -> UGen -> UGen -> [EnvCurve] -> [UGen]
+envLinen aT sT rT l c = env [0, l, l, 0] [aT, sT, rT] c (-1) (-1)
diff --git a/Sound/SC3/UGen/FFT.hs b/Sound/SC3/UGen/FFT.hs
new file mode 100644
--- /dev/null
+++ b/Sound/SC3/UGen/FFT.hs
@@ -0,0 +1,144 @@
+module Sound.SC3.UGen.FFT where
+
+import Sound.SC3.UGen.Rate
+import Sound.SC3.UGen.UGen
+import Sound.SC3.UGen.UGen.Construct
+import Sound.SC3.UGen.UGen.Math ()
+import Sound.SC3.UGen.UGen.MCE
+
+-- | 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
+
+-- | Variant FFT constructor with default values for hop size, window
+-- | type, and active status.
+fft' :: UGen -> UGen -> UGen
+fft' buf i = fft buf i (Constant 0.5) 0 1
+
+-- | Inverse Fast Fourier Transform.
+ifft :: UGen -> UGen -> UGen
+ifft buf wt = mkOsc AR "IFFT" [buf,wt] 1
+
+-- | Variant ifft with default value for window type.
+ifft' :: UGen -> UGen
+ifft' buf = ifft buf 0
+
+-- | Strict convolution of two continuously changing inputs.
+convolution :: UGen -> UGen -> UGen -> UGen
+convolution i kernel frameSize = mkOsc AR "Convolution" [i, kernel, frameSize] 1
+
+-- | Pack demand-rate FFT bin streams into an FFT chain.
+packFFT :: UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
+packFFT b sz from to z mp = mkOscMCE KR "PackFFT" [b, sz, from, to, z, n] mp 1
+    where n = Constant (fromIntegral (mceDegree mp))
+
+-- | Format magnitude and phase data data as required for packFFT.
+packFFTSpec :: [UGen] -> [UGen] -> UGen
+packFFTSpec m p = MCE (interleave m p)
+    where interleave x y = concat (zipWith (\a b -> [a,b]) x y)
+
+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
+	p = unpackFFT c nf from to 1
+	i = [from .. to]
+	e = zipWith3 f m p i
+        mp = (uncurry packFFTSpec) (unzip e)
+
+pv_Add :: UGen -> UGen -> UGen
+pv_Add ba bb = mkOsc KR "PV_Add" [ba,bb] 1
+
+-- | Shift and scale the bin positions.
+pv_BinShift :: UGen -> UGen -> UGen -> UGen
+pv_BinShift buf str shift = mkOsc KR "PV_BinShift" [buf,str,shift] 1
+
+-- | Combine low and high bins from two inputs.
+pv_BinWipe :: UGen -> UGen -> UGen -> UGen
+pv_BinWipe ba bb wp = mkOsc KR "PV_BinWipe" [ba,bb,wp] 1
+
+-- | Clear bins above or below a cutoff point.
+pv_BrickWall :: UGen -> UGen -> UGen
+pv_BrickWall buf wp = mkOsc KR "PV_BrickWall" [buf,wp] 1
+
+pv_ConformalMap :: UGen -> UGen -> UGen -> UGen
+pv_ConformalMap buf real imag = mkOsc KR "PV_ConformalMap" [buf,real,imag] 1
+
+-- | Copies spectral frame.
+pv_Copy :: UGen -> UGen -> UGen
+pv_Copy ba bb = mkOsc KR "PV_Copy" [ba,bb] 1
+
+pv_CopyPhase :: UGen -> UGen -> UGen
+pv_CopyPhase ba bb = mkOsc KR "PV_CopyPhase" [ba,bb] 1
+
+pv_Diffuser :: UGen -> UGen -> UGen
+pv_Diffuser buf trg = mkOsc KR "PV_Diffuser" [buf,trg] 1
+
+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
+
+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
+
+pv_LocalMax :: UGen -> UGen -> UGen
+pv_LocalMax buf thr = mkOsc KR "PV_LocalMax" [buf,thr] 1
+
+pv_MagAbove :: UGen -> UGen -> UGen
+pv_MagAbove buf thr = mkOsc KR "PV_MagAbove" [buf,thr] 1
+
+pv_MagBelow :: UGen -> UGen -> UGen
+pv_MagBelow buf thr = mkOsc KR "PV_MagBelow" [buf,thr] 1
+
+pv_MagClip :: UGen -> UGen -> UGen
+pv_MagClip buf thr = mkOsc KR "PV_MagClip" [buf,thr] 1
+
+pv_MagFreeze :: UGen -> UGen -> UGen
+pv_MagFreeze buf frz = mkOsc KR "PV_MagFreeze" [buf,frz] 1
+
+pv_MagMul :: UGen -> UGen -> UGen
+pv_MagMul ba bb = mkOsc KR "PV_MagMul" [ba,bb] 1
+
+pv_MagNoise :: UGen -> UGen
+pv_MagNoise buf = mkOsc KR "PV_MagNoise" [buf] 1
+
+pv_MagShift :: UGen -> UGen -> UGen -> UGen
+pv_MagShift buf str shift = mkOsc KR "PV_MagShift" [buf,str,shift] 1
+
+pv_MagSmear :: UGen -> UGen -> UGen
+pv_MagSmear buf bins = mkOsc KR "PV_MagSmear" [buf,bins] 1
+
+pv_MagSquared :: UGen -> UGen
+pv_MagSquared buf = mkOsc KR "PV_MagSquared" [buf] 1
+
+pv_Max :: UGen -> UGen -> UGen
+pv_Max ba bb = mkOsc KR "PV_Max" [ba,bb] 1
+
+pv_Min :: UGen -> UGen -> UGen
+pv_Min ba bb = mkOsc KR "PV_Min" [ba,bb] 1
+
+pv_Mul :: UGen -> UGen -> UGen
+pv_Mul ba bb = mkOsc KR "PV_Mul" [ba,bb] 1
+
+pv_PhaseShift270 :: UGen -> UGen
+pv_PhaseShift270 buf = mkOsc KR "PV_PhaseShift270" [buf] 1
+
+pv_PhaseShift90 :: UGen -> UGen
+pv_PhaseShift90 buf = mkOsc KR "PV_PhaseShift90" [buf] 1
+
+pv_PhaseShift :: UGen -> UGen -> UGen
+pv_PhaseShift buf shift = mkOsc KR "PV_PhaseShift" [buf,shift] 1
+
+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
+
+pv_RectComb :: UGen -> UGen -> UGen -> UGen -> UGen
+pv_RectComb buf teeth phase width = mkOsc KR "PV_RectComb" [buf,teeth,phase,width] 1
+
+unpack1FFT :: UGen -> UGen -> UGen -> UGen -> UGen
+unpack1FFT buf size index which = mkOsc DR "Unpack1FFT" [buf, size, index, which] 1
+
+unpackFFT :: UGen -> UGen -> UGen -> UGen -> UGen -> [UGen]
+unpackFFT c nf from to w = map (\i -> unpack1FFT c nf i w) [from .. to]
+
+-- Local Variables:
+-- truncate-lines:t
+-- End:
diff --git a/Sound/SC3/UGen/FFT/Base.hs b/Sound/SC3/UGen/FFT/Base.hs
new file mode 100644
--- /dev/null
+++ b/Sound/SC3/UGen/FFT/Base.hs
@@ -0,0 +1,17 @@
+module Sound.SC3.UGen.FFT.Base where
+
+import Sound.SC3.UGen.Rate (Rate(KR))
+import Sound.SC3.UGen.UGen (UGen, UGenId)
+import Sound.SC3.UGen.UGen.Construct (mkOscId)
+
+-- | Randomize order of bins.
+pv_BinScramble :: UGenId -> UGen -> UGen -> UGen -> UGen -> UGen
+pv_BinScramble z buf wp width trg = mkOscId z KR "PV_BinScramble" [buf,wp,width,trg] 1
+
+-- | Randomly clear bins.
+pv_RandComb :: UGenId -> UGen -> UGen -> UGen -> UGen
+pv_RandComb z buf wp trg = mkOscId z KR "PV_RandComb" [buf,wp,trg] 1
+
+-- | Cross fade, copying bins in random order.
+pv_RandWipe :: UGenId -> UGen -> UGen -> UGen -> UGen -> UGen
+pv_RandWipe z ba bb wp trg = mkOscId z KR "PV_RandWipe" [ba,bb,wp,trg] 1
diff --git a/Sound/SC3/UGen/FFT/Monadic.hs b/Sound/SC3/UGen/FFT/Monadic.hs
new file mode 100644
--- /dev/null
+++ b/Sound/SC3/UGen/FFT/Monadic.hs
@@ -0,0 +1,18 @@
+module Sound.SC3.UGen.FFT.Monadic where
+
+import Sound.SC3.UGen.UGen
+import Sound.SC3.UGen.UGen.Construct
+import qualified Sound.SC3.UGen.FFT.Base as F
+import Sound.SC3.UGen.UId
+
+-- | Randomize order of bins.
+pv_BinScramble :: (UId m) => UGen -> UGen -> UGen -> UGen -> m UGen
+pv_BinScramble = liftU4 F.pv_BinScramble
+
+-- | Randomly clear bins.
+pv_RandComb :: (UId m) => UGen -> UGen -> UGen -> m UGen
+pv_RandComb = liftU3 F.pv_RandComb
+
+-- | Cross fade, copying bins in random order.
+pv_RandWipe :: (UId m) => UGen -> UGen -> UGen -> UGen -> m UGen
+pv_RandWipe = liftU4 F.pv_RandWipe
diff --git a/Sound/SC3/UGen/Filter.hs b/Sound/SC3/UGen/Filter.hs
new file mode 100644
--- /dev/null
+++ b/Sound/SC3/UGen/Filter.hs
@@ -0,0 +1,322 @@
+module Sound.SC3.UGen.Filter where
+
+import Sound.SC3.UGen.UGen (UGen(MCE))
+import Sound.SC3.UGen.UGen.Construct (mkFilter, mkFilterMCE)
+import Data.List (transpose)
+
+-- | Allpass filter (no interpolation)
+allpassN :: UGen -> UGen -> UGen -> UGen -> UGen
+allpassN i maxTime dly dcy = mkFilter "AllpassN" [i, maxTime, dly, dcy] 1
+
+-- | Allpass filter (linear interpolation)
+allpassL :: UGen -> UGen -> UGen -> UGen -> UGen
+allpassL i maxTime dly dcy = mkFilter "AllpassL" [i, maxTime, dly, dcy] 1
+
+-- | Allpass filter (cubic interpolation)
+allpassC :: UGen -> UGen -> UGen -> UGen -> UGen
+allpassC i maxTime dly dcy = mkFilter "AllpassC" [i, maxTime, dly, dcy] 1
+
+-- | Basic psychoacoustic amplitude compensation.
+ampComp :: UGen -> UGen -> UGen -> UGen
+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
+
+-- | Bandpass filter
+bpf :: UGen -> UGen -> UGen -> UGen
+bpf i freq rq = mkFilter "BPF" [i,freq,rq] 1
+
+-- | Two zero fixed midpass filter.
+bpz2 :: UGen -> UGen
+bpz2 i = mkFilter "BPZ2" [i] 1
+
+-- | Band reject filter
+brf :: UGen -> UGen -> UGen -> UGen
+brf i freq rq = mkFilter "BRF" [i,freq,rq] 1
+
+-- | Two zero fixed midcut filter.
+brz2 :: UGen -> UGen
+brz2 i = mkFilter "BRZ2" [i] 1
+
+-- | Clip input between lower and upper bounds.
+clip :: UGen -> UGen -> UGen -> UGen
+clip i l h = mkFilter "Clip" [i,l,h] 1
+
+-- | Comb filter (no interpolation)
+combN :: UGen -> UGen -> UGen -> UGen -> UGen
+combN i maxTime dly dcy = mkFilter "CombN" [i, maxTime, dly, dcy] 1
+
+-- | Comb filter (linear interpolation)
+combL :: UGen -> UGen -> UGen -> UGen -> UGen
+combL i maxTime dly dcy = mkFilter "CombL" [i, maxTime, dly, dcy] 1
+
+-- | Comb filter (cubic interpolation)
+combC :: UGen -> UGen -> UGen -> UGen -> UGen
+combC i maxTime dly dcy = mkFilter "CombC" [i, maxTime, dly, dcy] 1
+
+-- | Convert signal to modal pitch.
+degreeToKey :: UGen -> UGen -> UGen -> UGen
+degreeToKey b i o = mkFilter "DegreeToKey" [b, i, o] 1
+
+-- | Exponential decay.
+decay :: UGen -> UGen -> UGen
+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
+
+-- | Single sample delay.
+delay1 :: UGen -> UGen
+delay1 i = mkFilter "Delay1" [i] 1
+
+-- | Two sample delay.
+delay2 :: UGen -> UGen
+delay2 i = mkFilter "Delay2" [i] 1
+
+-- | Simple delay line (cubic interpolation).
+delayC :: UGen -> UGen -> UGen -> UGen
+delayC i maxTime dly = mkFilter "DelayC" [i,maxTime,dly] 1
+
+-- | Simple delay line (linear interpolation).
+delayL :: UGen -> UGen -> UGen -> UGen
+delayL i maxTime dly = mkFilter "DelayL" [i,maxTime,dly] 1
+
+-- | Simple delay line (no interpolation).
+delayN :: UGen -> UGen -> UGen -> UGen
+delayN i maxTime dly = mkFilter "DelayN" [i,maxTime,dly] 1
+
+-- | FOF like filter.
+formlet :: UGen -> UGen -> UGen -> UGen -> UGen
+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
+
+-- | Gate.
+gate :: UGen -> UGen -> UGen
+gate i t = mkFilter "Gate" [i,t] 1
+
+-- | Hash input values.
+hasher :: UGen -> UGen
+hasher i = mkFilter "Hasher" [i] 1
+
+-- | Hilbert transform.
+hilbert :: UGen -> UGen
+hilbert i = mkFilter "Hilbert" [i] 2
+
+-- | Highpass filter.
+hpf :: UGen -> UGen -> UGen
+hpf i f = mkFilter "HPF" [i,f] 1
+
+-- | Two point difference filter.
+hpz1 :: UGen -> UGen
+hpz1 i = mkFilter "HPZ1" [i] 1
+
+-- | Two zero fixed highpass filter.
+hpz2 :: UGen -> UGen
+hpz2 i = mkFilter "HPZ2" [i] 1
+
+-- | Is signal within specified range.
+inRange :: UGen -> UGen -> UGen -> UGen
+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 = mkFilterMCE "Klank" [i,fs,fp,d] s 1
+
+-- | 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])
+
+-- | Simple averaging filter.
+lag :: UGen -> UGen -> UGen
+lag i t = mkFilter "Lag" [i,t] 1
+
+-- | Nested lag filter.
+lag2 :: UGen -> UGen -> UGen
+lag2 i t = mkFilter "Lag2" [i,t] 1
+
+-- | Twice nested lag filter.
+lag3 :: UGen -> UGen -> UGen
+lag3 i t = mkFilter "Lag3" [i,t] 1
+
+-- | Last value before chang above threshhold.
+lastValue :: UGen -> UGen -> UGen
+lastValue i t = mkFilter "LastValue" [i,t] 1
+
+-- | Sample and hold.
+latch :: UGen -> UGen -> UGen
+latch i t = mkFilter "Latch" [i,t] 1
+
+-- | Remove DC offset.
+leakDC :: UGen -> UGen -> UGen
+leakDC i coef = mkFilter "LeakDC" [i,coef] 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
+
+-- | 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
+
+-- | Lowpass filter.
+lpf :: UGen -> UGen -> UGen
+lpf i f = mkFilter "LPF" [i,f] 1
+
+-- | Two point average filter.
+lpz1 :: UGen -> UGen
+lpz1 i = mkFilter "LPZ1" [i] 1
+
+-- | Two zero fixed lowpass filter.
+lpz2 :: UGen -> UGen
+lpz2 i = mkFilter "LPZ2" [i] 1
+
+-- | Masks off bits in the mantissa of signal.
+mantissaMask :: UGen -> UGen -> UGen
+mantissaMask i bits = mkFilter "MantissaMask" [i,bits] 1
+
+-- | Median filter.
+median :: UGen -> UGen -> UGen
+median size i = mkFilter "Median" [size,i] 1
+
+-- | Moog VCF implementation.
+moogFF :: UGen -> UGen -> UGen -> UGen -> UGen
+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
+
+-- | Multiply add ternary operator.
+mulAdd :: UGen -> UGen -> UGen -> UGen
+mulAdd s m a = mkFilter "MulAdd" [s,m,a] 1
+
+-- | Flattens dynamics.
+normalizer :: UGen -> UGen -> UGen -> UGen
+normalizer i level dur = mkFilter "Normalizer" [i,level,dur] 1
+
+-- | One pole filter.
+onePole :: UGen -> UGen -> UGen
+onePole i coef = mkFilter "OnePole" [i,coef] 1
+
+-- | One zero filter.
+oneZero :: UGen -> UGen -> UGen
+oneZero i coef = mkFilter "OneZero" [i,coef] 1
+
+-- | Maximum value.
+peak :: UGen -> UGen -> UGen
+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
+
+-- | Trigger counter.
+pulseCount :: UGen -> UGen -> UGen
+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
+
+-- | Resonant highpass filter.
+rhpf :: UGen -> UGen -> UGen -> UGen
+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
+
+-- | Resonant filter.
+resonz :: UGen -> UGen -> UGen -> UGen
+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
+
+-- | Track maximum level.
+runningMax :: UGen -> UGen -> UGen
+runningMax i t = mkFilter "RunningMax" [i,t] 1
+
+-- | Track minimum level.
+runningMin :: UGen -> UGen -> UGen
+runningMin i t = mkFilter "RunningMin" [i,t] 1
+
+-- | Running sum.
+runningSum :: UGen -> UGen -> UGen
+runningSum i n = mkFilter "RunningSum" [i,n] 1
+
+-- | Select output from array of inputs.
+select :: UGen -> UGen -> UGen
+select i a = mkFilterMCE "Select" [i] a 1
+
+-- | 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
+
+-- | Set-reset flip flop.
+setResetFF :: UGen -> UGen -> UGen
+setResetFF t r = mkFilter "SetResetFF" [t,r] 1
+
+-- | Wave shaper.
+shaper :: UGen -> UGen -> UGen
+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
+
+-- | 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
+
+-- | Stepper pulse counter.
+stepper :: UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
+stepper t r minTime maxTime s v = mkFilter "Stepper" [t,r,minTime,maxTime,s,v] 1
+
+-- | Triggered linear ramp.
+sweep :: UGen -> UGen -> UGen
+sweep t r = mkFilter "Sweep" [t,r] 1
+
+-- | Delay trigger by specified interval. 
+tDelay :: UGen -> UGen -> UGen
+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
+
+-- | When triggered output unit signal for specified duration.
+trig1 :: UGen -> UGen -> UGen
+trig1 i d = mkFilter "Trig1" [i,d] 1
+
+-- | Triggered windex.
+twindex :: UGen -> UGen -> UGen -> UGen
+twindex i n a = mkFilterMCE "TWindex" [i,n] a 1
+
+-- | Two pole filter.
+twoPole :: UGen -> UGen -> UGen -> UGen
+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
+
+-- | Index into a table with a signal.
+wrapIndex :: UGen -> UGen -> UGen
+wrapIndex b i = mkFilter "WrapIndex" [b,i] 1
+
diff --git a/Sound/SC3/UGen/Granular.hs b/Sound/SC3/UGen/Granular.hs
new file mode 100644
--- /dev/null
+++ b/Sound/SC3/UGen/Granular.hs
@@ -0,0 +1,24 @@
+module Sound.SC3.UGen.Granular where
+
+import Sound.SC3.UGen.Rate
+import Sound.SC3.UGen.UGen
+import Sound.SC3.UGen.UGen.Construct
+
+grainBuf :: Int -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
+grainBuf nc t d s r p i l e = mkOsc AR "GrainBuf" [t, d, s, r, p, i, l, e] nc
+
+grainFM :: Int -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
+grainFM nc t d c m i l e = mkOsc AR "GrainFM" [t, d, c, m, i, l, e] nc
+
+grainIn :: Int -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
+grainIn nc t d i l e = mkOsc AR "GrainIn" [t, d, i, l, e] nc
+
+grainSin :: Int -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
+grainSin nc t d f l e = mkOsc AR "GrainSin" [t, d, f, l, e] nc
+
+warp1 :: Int -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
+warp1 nc b p f w e o r i = mkOsc AR "Warp1" [b, p, f, w, e, o, r, i] nc
+
+-- Local Variables:
+-- truncate-lines:t
+-- End:
diff --git a/Sound/SC3/UGen/Graph.hs b/Sound/SC3/UGen/Graph.hs
new file mode 100644
--- /dev/null
+++ b/Sound/SC3/UGen/Graph.hs
@@ -0,0 +1,87 @@
+module Sound.SC3.UGen.Graph ( Graph(..), Input(..), Terminal(..), Edge(..)
+                            , graph
+                            , nodeIndex
+                            , makeInput ) where
+
+import Sound.SC3.UGen.Rate (Rate(KR))
+import Sound.SC3.UGen.UGen (UGen(..), Special(..), UGenId(..))
+import Sound.SC3.UGen.UGen.Predicate
+
+import Data.Maybe (fromMaybe)
+import Data.List (nub, elemIndex)
+
+data Terminal = Terminal UGen Int deriving (Eq, Show)
+data Edge = Edge Terminal Terminal deriving (Eq, Show)
+data Graph = Graph [UGen] [UGen] [UGen] [Edge] deriving (Eq, Show)
+data Input = Input Int Int deriving (Eq, Show)
+
+-- | The list of all UGens referenced in a UGen graph.
+nodes :: UGen -> [UGen]
+nodes u@(UGen _ _ i _ _ _) = u : concatMap nodes i
+nodes (Proxy u _)          = u : nodes u
+nodes (MCE u)              = concatMap nodes u
+nodes (MRG u)              = concatMap nodes u
+nodes u                    = [u]
+
+-- | Construct implicit control UGen (k-rate only).
+implicit :: Int -> UGen
+implicit n = UGen KR "Control" [] (replicate n KR) (Special 0) (UGenId 0)
+
+-- | Generate the set of edges given the complete set of UGens.
+edges :: [UGen] -> [Edge]
+edges us = concatMap ugenEdges us
+    where ugenEdges u@(UGen _ _ i _ _ _) = map f i'
+               where g (v,_) = or [isUGen v, isProxy v, isControl v, isMRG v]
+                     n = length i - 1
+                     i' = filter g $ zip i [0..n]
+                     f (k, j) = Edge (terminal k) (Terminal u j)
+          ugenEdges _ = []
+
+-- | Construct a UGen graph.
+graph :: UGen -> Graph
+graph root = Graph n c u' (edges u')
+  where e  = (nub . reverse) (nodes root)
+        n  = filter isConstant e
+        c  = filter isControl e
+        u  = filter isUGen e
+        u' = if null c then u else implicit (length c) : u
+
+-- | Determine index of a node in the Graph.
+elemIndex' :: (Eq a, Show a) => a -> [a] -> Int
+elemIndex' e l = fromMaybe (error ("node not in graph?" ++ show (e,l))) 
+                 (elemIndex e l)
+                 
+-- | Determine index of UGen in Graph.
+ugenIndex :: Graph -> UGen -> Int
+ugenIndex (Graph _ _ u _) x = elemIndex' x u
+
+-- | Determine index of Constant in Graph.
+constantIndex :: Graph -> UGen -> Int
+constantIndex (Graph n _ _ _) x = elemIndex' x n
+
+-- | Determine index of Control in Graph.
+controlIndex :: Graph -> UGen -> Int
+controlIndex (Graph _ c _ _) x = elemIndex' x c
+
+-- | Determine index of any node in Graph.
+nodeIndex :: Graph -> UGen -> Int
+nodeIndex g u@(Constant _) = constantIndex g u
+nodeIndex g u@(Control _ _ _) = controlIndex g u
+nodeIndex g u@(UGen _ _ _ _ _ _) = ugenIndex g u
+nodeIndex g (MRG (u:_)) = ugenIndex g u
+nodeIndex _ _ = error "nodeIndex: illegal input"
+
+-- | Construct Input value for UGen in Graph.
+makeInput :: Graph -> UGen -> Input
+makeInput g u@(UGen _ _ _ _ _ _) = Input (ugenIndex g u) 0
+makeInput g u@(Constant _)       = Input (-1) (constantIndex g u)
+makeInput g u@(Control _ _ _)    = Input 0 (controlIndex g u)
+makeInput g (Proxy u n)          = Input (ugenIndex g u) n
+makeInput g (MRG (u:_))          = makeInput g u
+makeInput g u                    = error ("makeInput: illegal input: " ++ show (g,u))
+
+-- | Construct a terminal value, the port index is set for proxied
+-- | UGens.
+terminal :: UGen -> Terminal
+terminal (Proxy u n) = Terminal u n
+terminal u = Terminal u 0
diff --git a/Sound/SC3/UGen/IO.hs b/Sound/SC3/UGen/IO.hs
new file mode 100644
--- /dev/null
+++ b/Sound/SC3/UGen/IO.hs
@@ -0,0 +1,76 @@
+module Sound.SC3.UGen.IO where
+
+import Sound.SC3.UGen.Rate
+import Sound.SC3.UGen.UGen
+import Sound.SC3.UGen.UGen.Construct
+import Sound.SC3.UGen.Enum (Warp)
+import Sound.SC3.UGen.Utilities (fromWarp)
+
+-- | Read signal from an audio or control bus.
+in' :: Int -> Rate -> UGen -> UGen
+in' nc r bus = mkOsc r "In" [bus] nc
+
+-- | Define and read from buses local to a synthesis node.
+localIn :: Int -> Rate -> UGen
+localIn nc r = mkOsc r "LocalIn" [] nc
+
+lagIn :: Int -> UGen -> UGen -> UGen
+lagIn nc bus lag = mkOsc KR "LagIn" [bus, lag] nc
+
+-- | Read signal from a bus without erasing it.
+inFeedback :: Int -> UGen -> UGen
+inFeedback nc bus = mkOsc AR "InFeedback" [bus] nc
+
+-- | Generate a trigger anytime a bus is set.
+inTrig :: Int -> UGen -> UGen
+inTrig nc bus = mkOsc KR "InTrig" [bus] nc
+
+-- | Mix signal to an audio or control bus.
+out :: UGen -> UGen -> UGen
+out bus i = mkFilterMCE "Out" [bus] i 0
+
+-- | Over-write signal to an audio or control bus.
+replaceOut :: UGen -> UGen -> UGen
+replaceOut bus i = mkFilterMCE "ReplaceOut" [bus] i 0
+
+-- | Mix signal to an audio bus at precise sample offset.
+offsetOut :: UGen -> UGen -> UGen
+offsetOut bus i = mkOscMCE AR "OffsetOut" [bus] i 0
+
+-- | Write signal to bus local to a synthesis node, see localIn.
+localOut :: UGen -> UGen
+localOut i = mkFilterMCE "LocalOut" [] i 0
+
+-- | Crossfade signal to an audio or control bus.
+xOut :: UGen -> UGen -> UGen -> UGen
+xOut bus xfade i = mkFilterMCE "XOut" [bus, xfade] i 0
+
+sharedOut :: UGen -> UGen -> UGen
+sharedOut bus i = mkOscMCE KR "SharedOut" [bus] i 0
+
+sharedIn :: Int -> UGen -> UGen
+sharedIn nc bus = mkOsc KR "SharedIn" [bus] nc
+
+-- | Report the status of a particular key.
+keyState :: Rate -> UGen -> UGen -> UGen -> UGen -> UGen
+keyState r key minVal maxVal lag = mkOsc r "KeyState" [key, minVal, maxVal, lag] 1
+
+-- | Report the status of the first pointer button.
+mouseButton :: Rate -> UGen -> UGen -> UGen -> UGen
+mouseButton r minVal maxVal lag = mkOsc r "MouseButton" [minVal, maxVal, lag] 1
+
+-- | Cursor UGen, X axis.
+mouseX :: Rate -> UGen -> UGen -> Warp -> UGen -> UGen
+mouseX r minVal maxVal warp lag = mkOsc r "MouseX" [minVal, maxVal, fromWarp warp, lag] 1
+
+-- | Cursor UGen, Y axis.
+mouseY :: Rate -> UGen -> UGen -> Warp -> UGen -> UGen
+mouseY r minVal maxVal warp lag = mkOsc r "MouseY" [minVal, maxVal, fromWarp warp, lag] 1
+
+-- | Control variant.
+trigControl :: Int -> Rate -> UGen
+trigControl nc r = mkOsc r "TrigControl" [] nc
+
+-- Local Variables:
+-- truncate-lines:t
+-- End:
diff --git a/Sound/SC3/UGen/Information.hs b/Sound/SC3/UGen/Information.hs
new file mode 100644
--- /dev/null
+++ b/Sound/SC3/UGen/Information.hs
@@ -0,0 +1,48 @@
+module Sound.SC3.UGen.Information where
+
+import Sound.SC3.UGen.UGen (UGen)
+import Sound.SC3.UGen.Utilities (mkInfoUGen)
+
+-- | Sample rate of synthesis server, frames per second.
+sampleRate :: UGen
+sampleRate = mkInfoUGen "SampleRate"
+
+-- | Duration of one sample, seconds.
+sampleDur :: UGen
+sampleDur = mkInfoUGen "SampleDur"
+
+-- | Duration of one sample, radians.
+radiansPerSample :: UGen
+radiansPerSample = mkInfoUGen "RadiansPerSample"
+
+-- | Control rate of synthesis server, periods per second.
+controlRate :: UGen
+controlRate = mkInfoUGen "ControlRate"
+
+-- | Sub-sample accurate scheduling offset.
+subsampleOffset :: UGen
+subsampleOffset = mkInfoUGen "SubsampleOffset"
+
+-- | Number of allocated output audio rate buses.
+numOutputBuses :: UGen
+numOutputBuses = mkInfoUGen "NumOutputBuses"
+
+-- | Number of allocated input audio rate buses.
+numInputBuses :: UGen
+numInputBuses = mkInfoUGen "NumInputBuses"
+
+-- | Number of allocated audio rate buses.
+numAudioBuses :: UGen
+numAudioBuses = mkInfoUGen "NumAudioBuses"
+
+-- | Number of allocated control rate buses.
+numControlBuses :: UGen
+numControlBuses = mkInfoUGen "NumControlBuses"
+
+-- | Number of allocated buffers.
+numBuffers :: UGen
+numBuffers = mkInfoUGen "NumBuffers"
+
+-- | Number of runnings synthesis nodes.
+numRunningSynths :: UGen
+numRunningSynths = mkInfoUGen "NumRunningSynths"
diff --git a/Sound/SC3/UGen/MachineListening.hs b/Sound/SC3/UGen/MachineListening.hs
new file mode 100644
--- /dev/null
+++ b/Sound/SC3/UGen/MachineListening.hs
@@ -0,0 +1,37 @@
+module Sound.SC3.UGen.MachineListening where
+
+import Data.List
+import Data.Maybe
+import Sound.SC3.UGen.Rate (Rate(KR))
+import Sound.SC3.UGen.UGen (UGen(Constant))
+import Sound.SC3.UGen.UGen.Construct (mkOsc)
+
+-- | Autocorrelation beat tracker.
+beatTrack :: UGen -> UGen -> UGen
+beatTrack fft lock = mkOsc KR "BeatTrack" [fft, lock] 4
+
+-- | Extraction of instantaneous loudness in sones.
+loudness :: UGen -> UGen -> UGen -> UGen
+loudness fft smask tmask = mkOsc KR "Compander" [fft, smask, tmask] 1
+
+-- | Translate onset type string to constant UGen value.
+onsetType :: String -> UGen
+onsetType s = Constant (fromIntegral (maybe 3 id (findIndex (== s) t)))
+    where t = ["power", "magsum", "complex", "rcomplex", "phase", "wphase", "mkl"]
+
+-- | Onset detector.
+onsets :: UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
+onsets c t o r f mg ms w = mkOsc KR "Onsets" [c, t, o, r, f, mg, ms, w] 1
+
+-- | Onset detector with default values for minor parameters.
+onsets' :: UGen -> UGen -> UGen -> UGen
+onsets' c t o = onsets c t o (f 1.0) (f 0.1) (f 10.0) (f 11.0) (f 1.0)
+    where f = Constant
+
+-- | Key tracker.
+keyTrack :: UGen -> UGen -> UGen -> UGen -> UGen
+keyTrack fft kd cl _ = mkOsc KR "KeyTrack" [fft, kd, cl] 1
+
+-- Local Variables:
+-- truncate-lines:t
+-- End:
diff --git a/Sound/SC3/UGen/Math.hs b/Sound/SC3/UGen/Math.hs
new file mode 100644
--- /dev/null
+++ b/Sound/SC3/UGen/Math.hs
@@ -0,0 +1,247 @@
+module Sound.SC3.UGen.Math where
+
+import Sound.SC3.UGen.Operator
+import Sound.SC3.UGen.UGen
+import Sound.SC3.UGen.UGen.Construct
+import Sound.SC3.UGen.UGen.Math ()
+
+-- The Eq and Ord classes in the Prelude require Bool, hence the name
+-- mangling.  True is 1.0, False is 0.0
+
+-- | Variant on Eq class, result is of the same type as the values compared.
+class EqE a where
+    (==*)  :: a -> a -> a
+    (/=*)  :: a -> a -> a
+
+instance EqE Double where
+    a ==* b = if a == b then 1.0 else 0.0
+    a /=* b = if a /= b then 1.0 else 0.0
+
+instance EqE UGen where
+    (==*)  = mkBinaryOperator EQ_ (==*)
+    (/=*)  = mkBinaryOperator NE (/=*)
+
+-- | Variant on Ord class, result is of the same type as the values compared.
+class OrdE a where
+    (<*)  :: a -> a -> a
+    (<=*) :: a -> a -> a
+    (>*)  :: a -> a -> a
+    (>=*) :: a -> a -> a
+
+instance OrdE Double where
+    a <* b   = if a < b   then 1.0 else 0.0
+    a <=* b  = if a <= b  then 1.0 else 0.0
+    a >* b   = if a > b   then 1.0 else 0.0
+    a >=* b  = if a >= b  then 1.0 else 0.0
+
+instance OrdE UGen where
+    (<*)  = mkBinaryOperator LT_ (<*)
+    (<=*) = mkBinaryOperator LE (<=*)
+    (>*)  = mkBinaryOperator GT_ (>*)
+    (>=*) = mkBinaryOperator GE (>=*)
+
+-- | Unary operator class.
+class (Floating a) => UnaryOp a where
+    notE           :: a -> a
+    isNil          :: a -> a
+    notNil         :: a -> a
+    bitNot         :: a -> a
+    asFloat        :: a -> a
+    asInt          :: a -> a
+    ceil           :: a -> a
+    floorE         :: a -> a
+    frac           :: a -> a
+    squared        :: a -> a
+    cubed          :: a -> a
+    midiCPS        :: a -> a
+    cpsMIDI        :: a -> a
+    midiRatio      :: a -> a
+    ratioMIDI      :: a -> a
+    dbAmp          :: a -> a
+    ampDb          :: a -> a
+    octCPS         :: a -> a
+    cpsOct         :: a -> a
+    log2           :: a -> a
+    log10          :: a -> a
+    distort        :: a -> a
+    softClip       :: a -> a
+
+instance UnaryOp Double where
+    notE a      = if a >  0.0 then 0.0 else 1.0
+    isNil a     = if a == 0.0 then 0.0 else 1.0
+    notNil a    = if a /= 0.0 then 0.0 else 1.0
+    bitNot      = undefined
+    asFloat     = undefined
+    asInt       = undefined
+    ceil a      = fromIntegral (ceiling a :: Integer)
+    floorE a    = fromIntegral (floor a   :: Integer)
+    frac        = undefined
+    squared a   = a * a
+    cubed   a   = a * a * a
+    midiCPS a   = 440.0 * (2.0 ** ((a - 69.0) * (1.0 / 12.0)))
+    cpsMIDI a   = (log2 (a * (1.0 / 440.0)) * 12.0) + 69.0
+    midiRatio a = 2.0 ** (a * (1.0 / 12.0))
+    ratioMIDI a = 12.0 * (log2 a)
+    dbAmp a     = 10 ** (a * 0.05)
+    ampDb a     = (log10 a) * 20
+    octCPS a    = 440.0 * (2.0 ** (a - 4.75))
+    cpsOct a    = log2 (a * (1.0 / 440.0)) + 4.75
+    log2 a      = logBase 2 a
+    log10 a     = logBase 10 a
+    distort     = undefined
+    softClip    = undefined
+
+instance UnaryOp UGen where
+    notE           = mkUnaryOperator Not notE
+    isNil          = mkUnaryOperator IsNil isNil
+    notNil         = mkUnaryOperator NotNil notNil
+    bitNot         = mkUnaryOperator BitNot bitNot
+    asFloat        = mkUnaryOperator AsFloat asFloat
+    asInt          = mkUnaryOperator AsInt asInt
+    ceil           = mkUnaryOperator Ceil ceil
+    floorE         = mkUnaryOperator Floor floorE
+    frac           = mkUnaryOperator Frac frac
+    squared        = mkUnaryOperator Squared squared
+    cubed          = mkUnaryOperator Cubed cubed
+    midiCPS        = mkUnaryOperator MIDICPS midiCPS
+    cpsMIDI        = mkUnaryOperator CPSMIDI cpsMIDI
+    midiRatio      = mkUnaryOperator MIDIRatio midiRatio
+    ratioMIDI      = mkUnaryOperator RatioMIDI ratioMIDI
+    dbAmp          = mkUnaryOperator DbAmp dbAmp
+    ampDb          = mkUnaryOperator AmpDb ampDb
+    octCPS         = mkUnaryOperator OctCPS octCPS
+    cpsOct         = mkUnaryOperator CPSOct cpsOct
+    log2           = mkUnaryOperator Log2 log2
+    log10          = mkUnaryOperator Log10 log10
+    distort        = mkUnaryOperator Distort distort
+    softClip       = mkUnaryOperator SoftClip softClip
+
+-- | Binary operator class.
+class (Floating a) => BinaryOp a where
+    iDiv           :: a -> a -> a
+    modE           :: a -> a -> a
+    bitAnd         :: a -> a -> a
+    bitOr          :: a -> a -> a
+    bitXOr         :: a -> a -> a
+    lcmE           :: a -> a -> a
+    gcdE           :: a -> a -> a
+    roundE         :: a -> a -> a
+    roundUp        :: a -> a -> a
+    trunc          :: a -> a -> a
+    atan2E         :: a -> a -> a
+    hypot          :: a -> a -> a
+    hypotx         :: a -> a -> a
+    shiftLeft      :: a -> a -> a
+    shiftRight     :: a -> a -> a
+    unsignedShift  :: a -> a -> a
+    fill           :: a -> a -> a
+    ring1          :: a -> a -> a
+    ring2          :: a -> a -> a
+    ring3          :: a -> a -> a
+    ring4          :: a -> a -> a
+    difSqr         :: a -> a -> a
+    sumSqr         :: a -> a -> a
+    sqrDif         :: a -> a -> a
+    sqrSum         :: a -> a -> a
+    absDif         :: a -> a -> a
+    thresh         :: a -> a -> a
+    amClip         :: a -> a -> a
+    scaleNeg       :: a -> a -> a
+    clip2          :: a -> a -> a
+    excess         :: a -> a -> a
+    fold2          :: a -> a -> a
+    wrap2          :: a -> a -> a
+    firstArg       :: a -> a -> a
+    randRange      :: a -> a -> a
+    exprandRange   :: a -> a -> a
+
+instance BinaryOp Double where
+    iDiv               = undefined
+    modE a b           = n - floorE n where n = a / b
+    bitAnd             = undefined
+    bitOr              = undefined
+    bitXOr             = undefined
+    lcmE               = undefined
+    gcdE               = undefined
+    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
+    trunc              = undefined
+    atan2E a b         = atan (b/a)
+    hypot              = undefined
+    hypotx             = undefined
+    shiftLeft          = undefined
+    shiftRight         = undefined
+    unsignedShift      = undefined
+    fill               = undefined
+    ring1 a b          = a * b + a
+    ring2 a b          = a * b + a + b
+    ring3 a b          = a * a * b
+    ring4 a b          = a * a * b - a * b * b
+    difSqr a b         = (a*a) - (b*b)
+    sumSqr a b         = (a*a) + (b*b)
+    sqrSum a b         = (a+b) * (a+b)
+    sqrDif a b         = (a-b) * (a-b)
+    absDif a b         = abs (a - b)
+    thresh a b         = if a <  b then 0 else a
+    amClip a b         = if b <= 0 then 0 else a * b
+    scaleNeg a b       = (abs a - a) * b' + a where b' = 0.5 * b + 0.5
+    clip2 a b          = clip_ a (-b) b
+    excess a b         = a - clip_ a (-b) b
+    fold2 a b          = fold a (-b) b
+    wrap2 a b          = wrap a (-b) b
+    firstArg a _       = a
+    randRange          = undefined
+    exprandRange       = undefined
+
+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
+
+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
+
+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
+
+clip_ :: (Ord a) => a -> a -> a -> a
+clip_ a b c = if a < b then b else if a > c then c else a
diff --git a/Sound/SC3/UGen/Mix.hs b/Sound/SC3/UGen/Mix.hs
new file mode 100644
--- /dev/null
+++ b/Sound/SC3/UGen/Mix.hs
@@ -0,0 +1,31 @@
+module Sound.SC3.UGen.Mix (mix, mixFill, freqShift, splay) where
+
+import Sound.SC3.UGen.Filter
+import Sound.SC3.UGen.Oscillator
+import Sound.SC3.UGen.Panner
+import Sound.SC3.UGen.Rate
+import Sound.SC3.UGen.UGen
+import Sound.SC3.UGen.UGen.Math ()
+import Sound.SC3.UGen.UGen.MCE
+
+-- | Collapse MCE by summing.
+mix :: UGen -> UGen
+mix (MCE u)  = foldl1 (+) u
+mix u        = u
+
+-- | Construct and sum a set of UGens.
+mixFill :: Int -> (Int -> UGen) -> UGen
+mixFill n f = mix (MCE (map f [0..n-1]))
+
+-- | Frequency shifter, in terms of Hilbert UGen.
+freqShift :: UGen -> UGen -> UGen -> UGen
+freqShift i f p = mix (h * o)
+    where o = sinOsc AR f (MCE [p + 0.5 * pi, p])
+          h = hilbert i
+
+-- | 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]
diff --git a/Sound/SC3/UGen/Noise/Base.hs b/Sound/SC3/UGen/Noise/Base.hs
new file mode 100644
--- /dev/null
+++ b/Sound/SC3/UGen/Noise/Base.hs
@@ -0,0 +1,101 @@
+module Sound.SC3.UGen.Noise.Base where
+
+import Sound.SC3.UGen.Rate (Rate(IR))
+import Sound.SC3.UGen.UGen (UGen, UGenId)
+import Sound.SC3.UGen.UGen.Construct (mkOscId, mkFilterId)
+
+-- | Brown noise.
+brownNoise :: UGenId -> Rate -> UGen
+brownNoise z r = mkOscId z r "BrownNoise" [] 1
+
+-- | Clip noise.
+clipNoise :: UGenId -> Rate -> UGen
+clipNoise z r = mkOscId z r "ClipNoise" [] 1
+
+-- | Randomly pass or block triggers.
+coinGate :: UGenId -> UGen -> UGen -> UGen
+coinGate z prob i = mkFilterId z "CoinGate" [prob,i] 1
+
+-- | Random impulses in (-1, 1).
+dust2 :: UGenId -> Rate -> UGen -> UGen
+dust2 z r density = mkOscId z r "Dust2" [density] 1
+
+-- | Random impulse in (0,1).
+dust :: UGenId -> Rate -> UGen -> UGen
+dust z r density = mkOscId z r "Dust" [density] 1
+
+-- | Random value in exponential distribution.
+expRand :: UGenId -> UGen -> UGen -> UGen
+expRand z lo hi = mkOscId z IR "ExpRand" [lo,hi] 1
+
+-- | Gray noise.
+grayNoise :: UGenId -> Rate -> UGen
+grayNoise z r = mkOscId z r "GrayNoise" [] 1
+
+-- | Random integer in uniform distribution.
+iRand :: UGenId -> UGen -> UGen -> UGen
+iRand z lo hi = mkOscId z IR "IRand" [lo,hi] 1
+
+-- | Clip noise.
+lfClipNoise :: UGenId -> Rate -> UGen -> UGen
+lfClipNoise z r freq = mkOscId z r "LFClipNoise" [freq] 1
+
+-- | Dynamic clip noise.
+lfdClipNoise :: UGenId -> Rate -> UGen -> UGen
+lfdClipNoise z r freq = mkOscId z r "LFDClipNoise" [freq] 1
+
+-- | Dynamic step noise.
+lfdNoise0 :: UGenId -> Rate -> UGen -> UGen
+lfdNoise0 z r freq = mkOscId z r "LFDNoise0" [freq] 1
+
+-- | Dynamic ramp noise. 
+lfdNoise1 :: UGenId -> Rate -> UGen -> UGen
+lfdNoise1 z r freq = mkOscId z r "LFDNoise1" [freq] 1
+
+-- | Dynamic quadratic noise
+lfdNoise2 :: UGenId -> Rate -> UGen -> UGen
+lfdNoise2 z r freq = mkOscId z r "LFDNoise2" [freq] 1
+
+-- | Step noise.
+lfNoise0 :: UGenId -> Rate -> UGen -> UGen
+lfNoise0 z r freq = mkOscId z r "LFNoise0" [freq] 1
+
+-- | Ramp noise.
+lfNoise1 :: UGenId -> Rate -> UGen -> UGen
+lfNoise1 z r freq = mkOscId z r "LFNoise1" [freq] 1
+
+-- | Quadratic noise.
+lfNoise2 :: UGenId -> Rate -> UGen -> UGen
+lfNoise2 z r freq = mkOscId z r "LFNoise2" [freq] 1
+
+-- | Random value in skewed linear distribution.
+linRand :: UGenId -> UGen -> UGen -> UGen -> UGen
+linRand z lo hi m = mkOscId z IR "LinRand" [lo,hi,m] 1
+
+-- | Random value in sum of n linear distribution.
+nRand :: UGenId -> UGen -> UGen -> UGen -> UGen
+nRand z lo hi n = mkOscId z IR "NRand" [lo,hi,n] 1
+
+-- | Pink noise.
+pinkNoise :: UGenId -> Rate -> UGen
+pinkNoise z r = mkOscId z r "PinkNoise" [] 1
+
+-- | Random value in uniform distribution.
+rand :: UGenId -> UGen -> UGen -> UGen
+rand z lo hi = mkOscId z IR "Rand" [lo,hi] 1
+
+-- | Random value in exponential distribution on trigger.
+tExpRand :: UGenId -> UGen -> UGen -> UGen -> UGen
+tExpRand z lo hi trig = mkFilterId z "TExpRand" [lo,hi,trig] 1
+
+-- | Random integer in uniform distribution on trigger.
+tiRand :: UGenId -> UGen -> UGen -> UGen -> UGen
+tiRand z lo hi trig = mkFilterId z "TIRand" [lo,hi,trig] 1
+
+-- | Random value in uniform distribution on trigger.
+tRand :: UGenId -> UGen -> UGen -> UGen -> UGen
+tRand z lo hi trig = mkFilterId z "TRand" [lo,hi,trig] 1
+
+-- | White noise.
+whiteNoise :: UGenId -> Rate -> UGen
+whiteNoise z r = mkOscId z r "WhiteNoise" [] 1
diff --git a/Sound/SC3/UGen/Noise/Monadic.hs b/Sound/SC3/UGen/Noise/Monadic.hs
new file mode 100644
--- /dev/null
+++ b/Sound/SC3/UGen/Noise/Monadic.hs
@@ -0,0 +1,103 @@
+module Sound.SC3.UGen.Noise.Monadic where
+
+import Sound.SC3.UGen.Rate
+import Sound.SC3.UGen.UGen
+import Sound.SC3.UGen.UGen.Construct
+import qualified Sound.SC3.UGen.Noise.Base as N
+import Sound.SC3.UGen.UId
+
+-- | Brown noise.
+brownNoise :: (UId m) => Rate -> m UGen
+brownNoise = liftU N.brownNoise
+
+-- | Clip noise.
+clipNoise :: (UId m) => Rate -> m UGen
+clipNoise = liftU N.clipNoise
+
+-- | Randomly pass or block triggers.
+coinGate :: (UId m) => UGen -> UGen -> m UGen
+coinGate = liftU2 N.coinGate
+
+-- | Random impulses in (-1, 1).
+dust2 :: (UId m) => Rate -> UGen -> m UGen
+dust2 = liftU2 N.dust2
+
+-- | Random impulse in (0,1).
+dust :: (UId m) => Rate -> UGen -> m UGen
+dust = liftU2 N.dust
+
+-- | Random value in exponential distribution.
+expRand :: (UId m) => UGen -> UGen -> m UGen
+expRand = liftU2 N.expRand
+
+-- | Gray noise.
+grayNoise :: (UId m) => Rate -> m UGen
+grayNoise = liftU N.grayNoise
+
+-- | Random integer in uniform distribution.
+iRand :: (UId m) => UGen -> UGen -> m UGen
+iRand = liftU2 N.iRand
+
+-- | Clip noise.
+lfClipNoise :: (UId m) => Rate -> UGen -> m UGen
+lfClipNoise = liftU2 N.lfClipNoise
+
+-- | Dynamic clip noise.
+lfdClipNoise :: (UId m) => Rate -> UGen -> m UGen
+lfdClipNoise = liftU2 N.lfdClipNoise
+
+-- | Dynamic step noise.
+lfdNoise0 :: (UId m) => Rate -> UGen -> m UGen
+lfdNoise0 = liftU2 N.lfdNoise0
+
+-- | Dynamic ramp noise. 
+lfdNoise1 :: (UId m) => Rate -> UGen -> m UGen
+lfdNoise1 = liftU2 N.lfdNoise1
+
+-- | Dynamic quadratic noise
+lfdNoise2 :: (UId m) => Rate -> UGen -> m UGen
+lfdNoise2 = liftU2 N.lfdNoise2
+
+-- | Step noise.
+lfNoise0 :: (UId m) => Rate -> UGen -> m UGen
+lfNoise0 = liftU2 N.lfNoise0
+
+-- | Ramp noise.
+lfNoise1 :: (UId m) => Rate -> UGen -> m UGen
+lfNoise1 = liftU2 N.lfNoise1
+
+-- | Quadratic noise.
+lfNoise2 :: (UId m) => Rate -> UGen -> m UGen
+lfNoise2 = liftU2 N.lfNoise2
+
+-- | Random value in skewed linear distribution.
+linRand :: (UId m) => UGen -> UGen -> UGen -> m UGen
+linRand = liftU3 N.linRand
+
+-- | Random value in sum of n linear distribution.
+nRand :: (UId m) => UGen -> UGen -> UGen -> m UGen
+nRand = liftU3 N.nRand
+
+-- | Pink noise.
+pinkNoise :: (UId m) => Rate -> m UGen
+pinkNoise = liftU N.pinkNoise
+
+-- | Random value in uniform distribution.
+rand :: (UId m) => UGen -> UGen -> m UGen
+rand = liftU2 N.rand
+
+-- | Random value in exponential distribution on trigger.
+tExpRand :: (UId m) => UGen -> UGen -> UGen -> m UGen
+tExpRand = liftU3 N.tExpRand
+
+-- | Random integer in uniform distribution on trigger.
+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
+
+-- | White noise.
+whiteNoise :: (UId m) => Rate -> m UGen
+whiteNoise = liftU N.whiteNoise
diff --git a/Sound/SC3/UGen/Operator.hs b/Sound/SC3/UGen/Operator.hs
new file mode 100644
--- /dev/null
+++ b/Sound/SC3/UGen/Operator.hs
@@ -0,0 +1,130 @@
+module Sound.SC3.UGen.Operator (Unary(..), unaryName,
+                                Binary(..), binaryName) where
+
+data Unary  = Neg
+            | Not
+            | IsNil
+            | NotNil
+            | BitNot
+            | Abs
+            | AsFloat
+            | AsInt
+            | Ceil
+            | Floor
+            | Frac
+            | Sign
+            | Squared
+            | Cubed
+            | Sqrt
+            | Exp
+            | Recip
+            | MIDICPS
+            | CPSMIDI
+            | MIDIRatio
+            | RatioMIDI
+            | DbAmp
+            | AmpDb
+            | OctCPS
+            | CPSOct
+            | Log
+            | Log2
+            | Log10
+            | Sin
+            | Cos
+            | Tan
+            | ArcSin
+            | ArcCos
+            | ArcTan
+            | SinH
+            | CosH
+            | TanH
+            | Rand
+            | Rand2
+            | LinRand
+            | BiLinRand
+            | Sum3Rand
+            | Distort
+            | SoftClip
+            | Coin
+            | DigitValue
+            | Silence
+            | Thru
+            | RectWindow
+            | HanWindow
+            | WelchWindow
+            | TriWindow
+            | Ramp
+            | SCurve
+              deriving (Eq, Show, Enum)
+
+data Binary = Add
+            | Sub
+            | Mul
+            | IDiv
+            | FDiv
+            | Mod
+            | EQ_
+            | NE
+            | LT_
+            | GT_
+            | LE
+            | GE
+            | Min
+            | Max
+            | BitAnd
+            | BitOr
+            | BitXor
+            | LCM
+            | GCD
+            | Round
+            | RoundUp
+            | Trunc
+            | Atan2
+            | Hypot
+            | Hypotx
+            | Pow
+            | ShiftLeft
+            | ShiftRight
+            | UnsignedShift
+            | Fill
+            | Ring1
+            | Ring2
+            | Ring3
+            | Ring4
+            | DifSqr
+            | SumSqr
+            | SqrSum
+            | SqrDif
+            | AbsDif
+            | Thresh
+            | AMClip
+            | ScaleNeg
+            | Clip2
+            | Excess
+            | Fold2
+            | Wrap2
+            | FirstArg
+            | RandRange
+            | ExpRandRange
+              deriving (Eq, Show, Enum)
+
+-- | Provide symbolic names for standard unary operators.
+unaryName :: Int -> String
+unaryName   0 = "-"
+unaryName   n = show (toEnum n :: Unary)
+
+-- | Provide symbolic names for standard binary operators.
+binaryName :: Int -> String
+binaryName  0 = "+"
+binaryName  1 = "-"
+binaryName  2 = "*"
+binaryName  4 = "/"
+binaryName  5 = "%"
+binaryName  6 = "=="
+binaryName  7 = "/="
+binaryName  8 = "<"
+binaryName  9 = ">"
+binaryName 10 = "<="
+binaryName 11 = ">="
+binaryName 25 = "**"
+binaryName n  = show (toEnum n :: Binary)
diff --git a/Sound/SC3/UGen/Oscillator.hs b/Sound/SC3/UGen/Oscillator.hs
new file mode 100644
--- /dev/null
+++ b/Sound/SC3/UGen/Oscillator.hs
@@ -0,0 +1,90 @@
+module Sound.SC3.UGen.Oscillator where
+
+import Sound.SC3.UGen.Rate (Rate(AR))
+import Sound.SC3.UGen.UGen (UGen(MCE))
+import Sound.SC3.UGen.UGen.Construct (mkOsc, mkOscMCE)
+import Data.List(transpose)
+
+-- | Band Limited ImPulse generator.
+blip :: Rate -> UGen -> UGen -> UGen
+blip r freq nharm = mkOsc r "Blip" [freq, nharm] 1
+
+-- | Formant oscillator.
+formant :: Rate -> UGen -> UGen -> UGen -> UGen
+formant r f0 f bw = mkOsc r "Formant" [f0, f, bw] 1
+
+-- | Fast sine wave oscillator implemented using a ringing filter.
+fSinOsc :: Rate -> UGen -> UGen -> UGen
+fSinOsc r freq phase = mkOsc r "FSinOsc" [freq, phase] 1
+
+-- | Dynamic stochastic synthesis generator conceived by Iannis Xenakis.
+gendy1 :: Rate -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
+gendy1 r ampDist durDist adParam ddParam minFreq maxFreq ampScale durScale initCPs kNum = mkOsc r "Gendy1" [ampDist, durDist, adParam, ddParam, minFreq, maxFreq, ampScale, durScale, initCPs, kNum] 1
+
+-- | Impulse oscillator (non band limited).
+impulse :: Rate -> UGen -> UGen -> UGen
+impulse r freq phase = mkOsc r "Impulse" [freq, phase] 1
+
+-- | Bank of fixed oscillators.
+klang :: Rate -> UGen -> UGen -> UGen -> UGen
+klang r fs fo a = mkOscMCE r "Klang" [fs, fo] a 1
+
+-- | 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])
+
+-- | Upsample control rate signal to audio rate.
+k2A :: UGen -> UGen
+k2A i = mkOsc AR "K2A" [i] 1
+
+-- | A sine like shape made of two cubic pieces.
+lfCub :: Rate -> UGen -> UGen -> UGen
+lfCub r freq phase = mkOsc r "LFCub" [freq, phase] 1
+
+-- | A sine like shape made of two cubic pieces.
+lfPar :: Rate -> UGen -> UGen -> UGen
+lfPar r freq phase = mkOsc r "LFPar" [freq, phase] 1
+
+-- | Pulse oscillator (non band limited).
+lfPulse :: Rate -> UGen -> UGen -> UGen -> UGen
+lfPulse r freq iphase width = mkOsc r "LFPulse" [freq, iphase, width] 1
+
+-- | Sawtooth oscillator (non band limited).
+lfSaw :: Rate -> UGen -> UGen -> UGen
+lfSaw r freq phase = mkOsc r "LFSaw" [freq, phase] 1
+
+-- | Sawtooth oscillator (non band limited).
+lfTri :: Rate -> UGen -> UGen -> UGen
+lfTri r freq phase = mkOsc r "LFTri" [freq, phase] 1
+
+-- | Triggered linear ramp between two levels.
+phasor :: Rate -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
+phasor r t f s e p = mkOsc r "Phasor" [t, f, s, e, p] 1
+
+-- | Pulse wave generator (band limited).
+pulse :: Rate -> UGen -> UGen -> UGen
+pulse r freq width = mkOsc r "Pulse" [freq, width] 1
+
+-- | Sawtooth oscillator (band limited).
+saw :: Rate -> UGen -> UGen
+saw r freq = mkOsc r "Saw" [freq] 1
+
+-- | Silence.
+silent :: Int -> UGen
+silent nc = mkOsc AR "Silent" [] nc
+
+-- | Sine oscillator.
+sinOsc :: Rate -> UGen -> UGen -> UGen
+sinOsc r freq phase = mkOsc r "SinOsc" [freq, phase] 1
+
+-- | Sawtooth oscillator hard synched to a fundamental. 
+syncSaw :: Rate -> UGen -> UGen -> UGen
+syncSaw r syncFreq sawFreq = mkOsc r "SyncSaw" [syncFreq, sawFreq] 1
+
+-- | Variable duty sawtooth oscillator.
+varSaw :: Rate -> UGen -> UGen -> UGen -> UGen
+varSaw r freq iphase width = mkOsc r "VarSaw" [freq, iphase, width] 1
+
+-- Local Variables:
+-- truncate-lines:t
+-- End:
diff --git a/Sound/SC3/UGen/Panner.hs b/Sound/SC3/UGen/Panner.hs
new file mode 100644
--- /dev/null
+++ b/Sound/SC3/UGen/Panner.hs
@@ -0,0 +1,45 @@
+module Sound.SC3.UGen.Panner where
+
+import Sound.SC3.UGen.UGen (UGen)
+import Sound.SC3.UGen.UGen.Construct (mkFilter, mkFilterMCE)
+
+-- | Two channel equal power panner.
+pan2 :: UGen -> UGen -> UGen -> UGen
+pan2 i x level = mkFilter "Pan2" [i, x, level] 2
+
+-- | Two channel linear pan.
+linPan2 :: UGen -> UGen -> UGen -> UGen
+linPan2 i x level = mkFilter "LinPan2" [i, x, level] 2
+
+pan4 :: UGen -> UGen -> UGen -> UGen -> UGen
+pan4 i x y level = mkFilter "Pan4" [i, x, y, level] 4
+
+balance2 :: UGen -> UGen -> UGen -> UGen -> UGen
+balance2 l r p level = mkFilter "Balance2" [l, r, p, level] 2
+
+-- | Rotate a sound field.
+rotate2 :: UGen -> UGen -> UGen -> UGen
+rotate2 x y pos = mkFilter "Rotate2" [x, y, pos] 2
+
+panB :: UGen -> UGen -> UGen -> UGen -> UGen
+panB i az el level = mkFilter "PanB" [i, az, el, level] 4
+
+-- | 2D Ambisonic B-format panner.
+panB2 :: UGen -> UGen -> UGen -> UGen
+panB2 i az level = mkFilter "PanB2" [i, az, level] 3
+
+biPanB2 :: UGen -> UGen -> UGen -> UGen -> UGen
+biPanB2 inA inB azimuth gain = mkFilter "BiPanB2" [inA, inB, azimuth, gain] 3
+
+-- | 2D Ambisonic B-format decoder.
+decodeB2 :: UGen -> UGen -> UGen -> UGen -> UGen -> UGen
+decodeB2 nc w x y o = mkFilterMCE "DecodeB2" [w, x, y, o] nc 0
+
+panAz :: UGen -> UGen -> UGen -> UGen -> UGen -> UGen -> UGen
+panAz nc i p l w o = mkFilterMCE "PanAz" [i, p, l, w, o] nc 0
+
+xFade2 :: UGen -> UGen -> UGen -> UGen -> UGen
+xFade2 inA inB pan level = mkFilter "XFade" [inA, inB, pan, level] 2
+
+linXFade2 :: UGen -> UGen -> UGen -> UGen
+linXFade2 inA inB pan = mkFilter "XFade" [inA, inB, pan] 2
diff --git a/Sound/SC3/UGen/Rate.hs b/Sound/SC3/UGen/Rate.hs
new file mode 100644
--- /dev/null
+++ b/Sound/SC3/UGen/Rate.hs
@@ -0,0 +1,17 @@
+module Sound.SC3.UGen.Rate (Rate(..), rateId) where
+
+-- | Operating rate of UGen.
+data Rate = IR | KR | AR | DR deriving (Eq, Show, Enum)
+
+instance Ord Rate where
+    compare a b = compare (rateOrd a) (rateOrd b)
+
+rateOrd :: Rate -> Int
+rateOrd IR = 0
+rateOrd KR = 1
+rateOrd AR = 2
+rateOrd DR = 3
+
+-- | Integer rate identifier, as required for scsynth bytecode.
+rateId :: Rate -> Int
+rateId = fromEnum
diff --git a/Sound/SC3/UGen/UGen.hs b/Sound/SC3/UGen/UGen.hs
new file mode 100644
--- /dev/null
+++ b/Sound/SC3/UGen/UGen.hs
@@ -0,0 +1,30 @@
+module Sound.SC3.UGen.UGen ( Name, UGenId(..), UGen(..), Output, Special(..)
+                           , clone ) where
+
+import Control.Monad (liftM, replicateM)
+import Sound.SC3.UGen.Rate (Rate)
+import Sound.SC3.UGen.UId
+
+type Name = String
+type Output = Rate
+newtype Special = Special Int deriving (Eq, Show)
+newtype UGenId = UGenId Int deriving (Eq, Show)
+data UGen = Constant { constantValue :: Double }
+          | Control { controlRate_ :: Rate
+                    , controlName :: Name
+                    , controlDefault :: Double }
+          | UGen { ugenRate :: Rate
+                 , ugenName :: Name
+                 , ugenInputs :: [UGen]
+                 , ugenOuputs :: [Output]
+                 , ugenSpecial :: Special
+                 , ugenId :: UGenId }
+          | Proxy { proxySource :: UGen
+                  , proxyIndex :: Int }
+          | MCE { mceProxies :: [UGen] }
+          | MRG { mrgRoots :: [UGen] }
+            deriving (Eq, Show)
+
+-- | Clone UGen.
+clone :: (UId m) => Int -> m UGen -> m UGen
+clone n u = liftM MCE (replicateM n u)
diff --git a/Sound/SC3/UGen/UGen/Construct.hs b/Sound/SC3/UGen/UGen/Construct.hs
new file mode 100644
--- /dev/null
+++ b/Sound/SC3/UGen/UGen/Construct.hs
@@ -0,0 +1,118 @@
+module Sound.SC3.UGen.UGen.Construct ( mkUnaryOperator, mkBinaryOperator
+                                     , mkOscId, mkOsc
+                                     , mkOscMCEId, mkOscMCE
+                                     , mkFilterId, mkFilter, mkFilterKeyed
+                                     , mkFilterMCE
+                                     , liftU, liftU2, liftU3, liftU4 ) where
+
+import Sound.SC3.UGen.Operator
+import Sound.SC3.UGen.Rate
+import Sound.SC3.UGen.UGen
+import Sound.SC3.UGen.UGen.MCE
+import Sound.SC3.UGen.UId
+
+-- * UGen Constructors.
+
+-- | Apply proxy transformation if required.
+proxy :: UGen -> UGen
+proxy (MCE l) = MCE (map proxy l)
+proxy u@(UGen _ _ _ o _ _) = case o of
+                               (_:_:_) -> MCE (map (Proxy u) [0..(length o - 1)])
+                               _       -> u
+proxy (MRG (x:xs)) = MRG (proxy x : xs)
+proxy _ = error "proxy: illegal ugen"
+
+-- | Determine the rate of a UGen.
+rateOf :: UGen -> Rate
+rateOf (Constant _) = IR
+rateOf (Control r _ _) = r
+rateOf (UGen r _ _ _ _ _) = r
+rateOf (Proxy u _) = rateOf u
+rateOf (MCE u) = maximum (map rateOf u)
+rateOf (MRG (u:_)) = rateOf u
+rateOf _ = undefined
+
+-- | True is input is a sink UGen, ie. has no outputs.
+isSink :: UGen -> Bool
+isSink (UGen _ _ _ o _ _) = null o
+isSink (MCE u) = all isSink u
+isSink (MRG (l:_)) = isSink l
+isSink _ = False
+
+-- | Ensure input UGen is valid, ie. not a sink.
+checkInput :: UGen -> UGen
+checkInput u = if isSink u then error ("illegal input" ++ show u) else u
+
+-- | Construct proxied and multiple channel expanded UGen.
+mkUGen :: Rate -> Name -> [UGen] -> [Output] -> Special -> UGenId -> UGen
+mkUGen r n i o s z = proxy (mceExpand u)
+    where u = UGen r n (map checkInput i) o s z
+
+-- | Operator UGen constructor.
+mkOperator :: Name -> [UGen] -> Int -> UGen
+mkOperator c i s = mkUGen r c i [r] (Special s) (UGenId 0)
+    where r = maximum (map rateOf i)
+
+-- | Unary math constructor with constant optimization.
+mkUnaryOperator :: Unary -> (Double -> Double) -> UGen -> UGen
+mkUnaryOperator _ f (Constant a) = Constant (f a)
+mkUnaryOperator i _ a = mkOperator "UnaryOpUGen" [a] (fromEnum i)
+
+-- | Binary math constructor with constant optimization.
+mkBinaryOperator :: Binary -> (Double -> Double -> Double) -> UGen -> UGen -> UGen
+mkBinaryOperator _ f (Constant a) (Constant b) = Constant (f a b)
+mkBinaryOperator i _ a b = mkOperator "BinaryOpUGen" [a, b] (fromEnum i)
+
+-- | Oscillator constructor.
+mkOscId :: UGenId -> Rate -> Name -> [UGen] -> Int -> UGen
+mkOscId z r c i o = mkUGen r c i (replicate o r) (Special 0) z
+
+-- | Oscillator constructor.
+mkOsc :: Rate -> Name -> [UGen] -> Int -> UGen
+mkOsc = mkOscId (UGenId 0)
+
+-- | Variant oscillator constructor with MCE collapsing input.
+mkOscMCEId :: UGenId -> Rate -> Name -> [UGen] -> UGen -> Int -> UGen
+mkOscMCEId z r c i j o = mkOscId z r c (i ++ mceChannels j) o
+
+-- | Variant oscillator constructor with MCE collapsing input.
+mkOscMCE :: Rate -> Name -> [UGen] -> UGen -> Int -> UGen
+mkOscMCE = mkOscMCEId (UGenId 0)
+
+-- | Filter UGen constructor.
+mkFilterId :: UGenId -> Name -> [UGen] -> Int -> UGen
+mkFilterId z c i o = mkUGen r c i o' (Special 0) z
+    where r = maximum (map rateOf i)
+          o'= replicate o r
+
+-- | Filter UGen constructor.
+mkFilter :: Name -> [UGen] -> Int -> UGen
+mkFilter = mkFilterId (UGenId 0)
+
+-- | Variant filter with rate derived from keyed input.
+mkFilterKeyed :: Name -> Int -> [UGen] -> Int -> UGen
+mkFilterKeyed c k i o = mkUGen r c i o' (Special 0) (UGenId 0)
+    where r = rateOf (i !! k)
+          o' = replicate o r
+
+-- | Variant filter constructor with MCE collapsing input.
+mkFilterMCE :: Name -> [UGen] -> UGen -> Int -> UGen
+mkFilterMCE c i j o = mkFilter c (i ++ mceChannels j) o
+
+-- | Lifting UGenId requiring UGens to UId
+liftU :: (UId m) => (UGenId -> a -> UGen) -> (a -> m UGen)
+liftU f a = do n <- generateUId
+               return (f (UGenId n) a)
+
+liftU2 :: (UId m) => (UGenId -> a -> b -> UGen) -> (a -> b -> m UGen)
+liftU2 f a b = do n <- generateUId
+                  return (f (UGenId n) a b)
+
+liftU3 :: (UId m) => (UGenId -> a -> b -> c -> UGen) -> (a -> b -> c -> m UGen)
+liftU3 f a b c = do n <- generateUId
+                    return (f (UGenId n) a b c)
+
+liftU4 :: (UId m) => (UGenId -> a -> b -> c -> d -> UGen) -> (a -> b -> c -> d -> m UGen)
+liftU4 f a b c d = do n <- generateUId
+                      return (f (UGenId n) a b c d)
+
diff --git a/Sound/SC3/UGen/UGen/MCE.hs b/Sound/SC3/UGen/UGen/MCE.hs
new file mode 100644
--- /dev/null
+++ b/Sound/SC3/UGen/UGen/MCE.hs
@@ -0,0 +1,56 @@
+module Sound.SC3.UGen.UGen.MCE where
+
+import Data.List (transpose)
+import Sound.SC3.UGen.UGen
+import Sound.SC3.UGen.UGen.Predicate
+
+-- * Multiple Channel Expansion
+
+-- | Number of channels to expand to.
+mceDegree :: UGen -> Int
+mceDegree (MCE l) = length l
+mceDegree _       = error "mceDegree: illegal ugen"
+
+-- | Is expansion required, ie. are any inputs MCE values.
+mceRequired :: UGen -> Bool
+mceRequired (UGen _ _ i _ _ _) = not (null (filter isMCE i))
+mceRequired (MCE l)            = any mceRequired l
+mceRequired _                  = False
+
+-- | Extend UGen to specified degree.
+mceExtend :: Int -> UGen -> [UGen]
+mceExtend n (MCE l) = take n (cycle l)
+mceExtend n u       = replicate n u
+
+-- | Apply MCE transformation.
+mceTransform :: UGen -> UGen
+mceTransform (UGen r n i o s d) = MCE (map f i')
+    where f j = UGen r n j o s d
+          upr = maximum (map mceDegree (filter isMCE i))
+          i'  = transpose (map (mceExtend upr) i)
+mceTransform _ = error "mceTransform: illegal ugen"
+
+-- | Apply MCE transformation if required.
+mceExpand :: UGen -> UGen
+mceExpand (MCE l) = MCE (map mceExpand l)
+mceExpand u       = if mceRequired u then mceExpand (mceTransform u) else u
+
+-- | 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"
+
+-- | Reverse order of channels at MCE.
+mceReverse :: UGen -> UGen
+mceReverse = mceEdit reverse
+
+-- | Obtain indexed channel at MCE.
+mceChannel :: Int -> UGen -> UGen
+mceChannel n (MCE l) = l !! n
+mceChannel _ _       = error "mceChannel: non MCE value"
+
+-- | Output channels of UGen as a list.
+mceChannels :: UGen -> [UGen]
+mceChannels (MCE l) = l
+mceChannels u       = [u]
+
diff --git a/Sound/SC3/UGen/UGen/Math.hs b/Sound/SC3/UGen/UGen/Math.hs
new file mode 100644
--- /dev/null
+++ b/Sound/SC3/UGen/UGen/Math.hs
@@ -0,0 +1,83 @@
+module Sound.SC3.UGen.UGen.Math () where
+
+import System.Random (Random, randomR, random)
+import Sound.SC3.UGen.Operator (Unary(..),Binary(..))
+import Sound.SC3.UGen.UGen
+import Sound.SC3.UGen.UGen.Construct
+
+instance Num UGen where
+    negate         = mkUnaryOperator Neg negate
+    (+)            = mkBinaryOperator Add (+)
+    (-)            = mkBinaryOperator Sub (-)
+    (*)            = mkBinaryOperator Mul (*)
+    abs            = mkUnaryOperator Abs abs
+    signum         = mkUnaryOperator Sign signum
+    fromInteger a  = Constant (fromInteger a)
+
+instance Fractional UGen where
+    recip          = mkUnaryOperator Recip recip
+    (/)            = mkBinaryOperator FDiv (/)
+    fromRational a = Constant (fromRational a)
+
+instance Floating UGen where
+    pi             = Constant pi
+    exp            = mkUnaryOperator Exp exp
+    log            = mkUnaryOperator Log log
+    sqrt           = mkUnaryOperator Sqrt sqrt
+    (**)           = mkBinaryOperator Pow (**)
+    logBase a b    = log b / log a
+    sin            = mkUnaryOperator Sin sin
+    cos            = mkUnaryOperator Cos cos
+    tan            = mkUnaryOperator Tan tan
+    asin           = mkUnaryOperator ArcSin asin
+    acos           = mkUnaryOperator ArcCos acos
+    atan           = mkUnaryOperator ArcTan atan
+    sinh           = mkUnaryOperator SinH sinh
+    cosh           = mkUnaryOperator CosH cosh
+    tanh           = mkUnaryOperator TanH tanh
+    asinh x        = log (sqrt (x*x+1) + x)
+    acosh x        = log (sqrt (x*x-1) + x)
+    atanh x        = (log (1+x) - log (1-x)) / 2
+
+instance Real UGen where
+    toRational (Constant n) = toRational n
+    toRational _ = error "toRational at non-constant UGen"
+
+instance Integral UGen where
+    quot = mkBinaryOperator IDiv undefined
+    rem = mkBinaryOperator Mod undefined
+    quotRem a b = (quot a b, rem a b)
+    div = mkBinaryOperator IDiv undefined
+    mod = mkBinaryOperator Mod undefined
+    toInteger (Constant n) = floor n
+    toInteger _ = error "toInteger at non-constant UGen"
+
+instance Ord UGen where
+    (Constant a) <  (Constant b) = a <  b
+    _            <  _            = error "< at UGen is partial, see <*"
+    (Constant a) <= (Constant b) = a <= b
+    _            <= _            = error "<= at UGen is partial, see <=*"
+    (Constant a) >  (Constant b) = a <  b
+    _            >  _            = error "> at UGen is partial, see >*"
+    (Constant a) >= (Constant b) = a >= b
+    _            >= _            = error ">= at UGen is partial, see >=*"
+    min  = mkBinaryOperator Min min
+    max  = mkBinaryOperator Max max
+
+instance Enum UGen where
+    succ u                = u + 1
+    pred u                = u - 1
+    toEnum i              = Constant (fromIntegral i)
+    fromEnum (Constant n) = truncate n
+    fromEnum _            = error "cannot enumerate non-constant UGens"
+    enumFrom              = iterate (+1)
+    enumFromThen n m      = iterate (+(m-n)) n
+    enumFromTo n m        = takeWhile (<= m+1/2) (enumFrom n)
+    enumFromThenTo n n' m = takeWhile (p (m + (n'-n)/2)) (enumFromThen n n')
+        where p = if n' >= n then (>=) else (<=)
+
+instance Random UGen where
+    randomR (Constant l, Constant r) g = (Constant n, g') 
+        where (n, g') = randomR (l,r) g
+    randomR _                        _ = error "randomR: non constant (l,r)"
+    random g = randomR (-1.0,1.0) g
diff --git a/Sound/SC3/UGen/UGen/Predicate.hs b/Sound/SC3/UGen/UGen/Predicate.hs
new file mode 100644
--- /dev/null
+++ b/Sound/SC3/UGen/UGen/Predicate.hs
@@ -0,0 +1,34 @@
+module Sound.SC3.UGen.UGen.Predicate where
+
+import Sound.SC3.UGen.UGen
+
+-- | Constant predicate.
+isConstant :: UGen -> Bool
+isConstant (Constant _) = True
+isConstant _            = False
+
+-- | Control predicate.
+isControl :: UGen -> Bool
+isControl (Control _ _ _) = True
+isControl _               = False
+
+-- | UGen predicate.
+isUGen :: UGen -> Bool
+isUGen (UGen _ _ _ _ _ _) = True
+isUGen _                  = False
+
+-- | Proxy predicate.
+isProxy :: UGen -> Bool
+isProxy (Proxy _ _) = True
+isProxy _           = False
+
+-- | MCE predicate.
+isMCE :: UGen -> Bool
+isMCE (MCE _) = True
+isMCE _       = False
+
+-- | MRG predicate.
+isMRG :: UGen -> Bool
+isMRG (MRG _) = True
+isMRG _       = False
+
diff --git a/Sound/SC3/UGen/UId.hs b/Sound/SC3/UGen/UId.hs
new file mode 100644
--- /dev/null
+++ b/Sound/SC3/UGen/UId.hs
@@ -0,0 +1,12 @@
+module Sound.SC3.UGen.UId where
+
+import Control.Monad
+import Data.Unique
+
+-- | A class indicating a monad that will generate a sequence of
+--   unique integer identifiers.
+class (Monad m) => UId m where
+   generateUId :: m Int
+
+instance UId IO where
+   generateUId = liftM hashUnique newUnique
diff --git a/Sound/SC3/UGen/Utilities.hs b/Sound/SC3/UGen/Utilities.hs
new file mode 100644
--- /dev/null
+++ b/Sound/SC3/UGen/Utilities.hs
@@ -0,0 +1,55 @@
+module Sound.SC3.UGen.Utilities where
+
+import Sound.SC3.UGen.Enum
+import Sound.SC3.UGen.UGen (UGen(..))
+import Sound.SC3.UGen.UGen.Construct (mkOsc)
+import Sound.SC3.UGen.Rate (Rate(IR))
+
+fromLoop :: Loop -> UGen
+fromLoop NoLoop       = Constant 0
+fromLoop Loop         = Constant 1
+fromLoop (WithLoop u) = u
+
+fromInterpolation :: Interpolation -> UGen
+fromInterpolation NoInterpolation     = Constant 1
+fromInterpolation LinearInterpolation = Constant 2
+fromInterpolation CubicInterpolation  = Constant 4
+fromInterpolation (Interpolation u)   = u
+
+fromDoneAction :: DoneAction -> UGen
+fromDoneAction DoNothing      = Constant 0
+fromDoneAction PauseSynth     = Constant 1
+fromDoneAction RemoveSynth    = Constant 2
+fromDoneAction (DoneAction u) = u
+
+fromWarp :: Warp -> UGen
+fromWarp Linear      = Constant 0
+fromWarp Exponential = Constant 1
+fromWarp (Warp u)    = u
+
+env_curve :: EnvCurve -> UGen
+env_curve EnvStep    = Constant 0.0
+env_curve EnvLin     = Constant 1.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
+env_curve EnvSqr     = Constant 6.0
+env_curve EnvCub     = Constant 7.0
+
+env_value :: EnvCurve -> UGen
+env_value (EnvNum u) = u
+env_value _          = Constant 0.0
+
+d_dx :: (Num a) => [a] -> [a]
+d_dx [] = []
+d_dx [_] = []
+d_dx [x,y] = [y - x]
+d_dx (x:y:r) = y - x : d_dx (y:r)
+
+dbl :: a -> [a]
+dbl x = [x,x]
+
+mkInfoUGen :: String -> UGen
+mkInfoUGen name = mkOsc IR name [] 1
+
diff --git a/emacs/hsc3.el b/emacs/hsc3.el
new file mode 100644
--- /dev/null
+++ b/emacs/hsc3.el
@@ -0,0 +1,268 @@
+;; hsc3.el - (c) rohan drape, 2006-2007
+
+;; 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
+;; point acquisition is courtesy `thingatpt'.  The directory search
+;; facilities are courtesy `find-lisp'.
+
+(require 'scheme)
+(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-main-modules
+  (list)
+  "*Modules to load (using :l) into the haskell interpreter.")
+
+(defvar hsc3-modules
+  (list "Sound.OpenSoundControl"
+	"Sound.SC3"
+	"Data.List"
+	"Control.Monad"
+	"Control.Concurrent"
+	"System.Directory"
+	"System.Random")
+  "*Modules to bring into scope (using :m +) into the haskell interpreter.")
+
+(defvar hsc3-help-directory
+  nil
+  "*The directory containing the help files (default=nil).")
+
+(defvar hsc3-literate-p
+  t
+  "*Flag to indicate if we are in literate mode (default=t).")
+
+(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-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))
+  (if (not (null hsc3-main-modules))
+      (hsc3-send-string
+       (apply 'concat (cons ":l " (hsc3-intersperse " " hsc3-main-modules)))))
+  (if (not (null hsc3-modules))
+      (hsc3-send-string
+       (apply 'concat (cons ":m + " (hsc3-intersperse " " hsc3-modules))))))
+
+(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)
+  (kill-buffer hsc3-buffer)
+  (delete-other-windows))
+
+(defun hsc3-help ()
+  "Lookup up the name at point in the Help files."
+  (interactive)
+  (mapc (lambda (filename)
+	  (find-file-other-window filename))
+	(find-lisp-find-files hsc3-help-directory
+			      (concat "^"
+				      (thing-at-point 'symbol)
+				      "\\.help\\.lhs"))))
+
+(defun hsc3-send-string (s)
+  (if (comint-check-proc hsc3-buffer)
+      (comint-send-string hsc3-buffer (concat s "\n"))
+    (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 "import " module "\n")))
+	  (append hsc3-main-modules 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)
+  (let* ((s (buffer-substring (line-beginning-position)
+			      (line-end-position)))
+	 (s* (if hsc3-literate-p
+		 (substring s 2)
+	       s)))
+    (hsc3-send-string 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."
+  (interactive)
+  (save-buffer)
+  (hsc3-send-string (format ":load \"%s\"" buffer-file-name)))
+
+(defun hsc3-run-main ()
+  "Run current main."
+  (interactive)
+  (hsc3-send-string "main"))
+
+(defun hsc3-interrupt-haskell ()
+  (interactive)
+  (if (comint-check-proc hsc3-buffer)
+      (with-current-buffer hsc3-buffer
+	(interrupt-process (get-buffer-process (current-buffer))))
+    (error "no hsc3 process running?")))
+
+(defun hsc3-reset-scsynth ()
+  "Reset"
+  (interactive)
+  (hsc3-send-string "withSC3 reset"))
+
+(defun hsc3-status-scsynth ()
+  "Status"
+  (interactive)
+  (hsc3-send-string "withSC3 serverStatus >>= mapM putStrLn"))
+
+(defun hsc3-quit-scsynth ()
+  "Quit"
+  (interactive)
+  (hsc3-send-string "withSC3 (\fd -> send fd quit)"))
+
+(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 ?\C-c] 'hsc3-run-line)
+  (define-key map [?\C-c ?\C-e] 'hsc3-run-region)
+  (define-key map [?\C-c ?\C-l] 'hsc3-load-buffer)
+  (define-key map [?\C-c ?\C-i] 'hsc3-interrupt-haskell)
+  (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-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))
+
+(defun hsc3-mode-menu (map)
+  "Haskell SuperCollider menu."
+  (define-key map [menu-bar hsc3]
+    (cons "Haskell-SuperCollider" (make-sparse-keymap "Haskell-SuperCollider")))
+  (define-key map [menu-bar hsc3 help]
+    (cons "Help" (make-sparse-keymap "Help")))
+  (define-key map [menu-bar hsc3 help hsc3]
+    '("Haskell SuperCollider help" . hsc3-help))
+  (define-key map [menu-bar hsc3 expression]
+    (cons "Expression" (make-sparse-keymap "Expression")))
+  (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-line]
+    '("Run line" . hsc3-run-line))
+  (define-key map [menu-bar hsc3 scsynth]
+    (cons "SCSynth" (make-sparse-keymap "SCSynth")))
+  (define-key map [menu-bar hsc3 scsynth quit]
+    '("Quit scsynth" . hsc3-quit-scsynth))
+  (define-key map [menu-bar hsc3 scsynth status]
+    '("Display status" . hsc3-status-scsynth))
+  (define-key map [menu-bar hsc3 scsynth reset]
+    '("Reset scsynth" . hsc3-reset-scsynth))
+  (define-key map [menu-bar hsc3 haskell]
+    (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)))
+
+(if hsc3-mode-map
+    ()
+  (let ((map (make-sparse-keymap "Haskell-SuperCollider")))
+    (hsc3-mode-keybindings map)
+    (hsc3-mode-menu map)
+    (setq hsc3-mode-map map)))
+
+(define-derived-mode
+  literate-hsc3-mode
+  hsc3-mode
+  "Literate Haskell SuperCollider"
+  "Major mode for interacting with an inferior haskell process."
+  (setq hsc3-literate-p t)
+  (setq haskell-literate 'bird)
+  (turn-on-font-lock))
+
+(add-to-list 'auto-mode-alist '("\\.lhs$" . literate-hsc3-mode))
+
+(define-derived-mode
+  hsc3-mode
+  haskell-mode
+  "Haskell SuperCollider"
+  "Major mode for interacting with an inferior haskell process."
+  (setq hsc3-literate-p nil)
+  (turn-on-font-lock))
+
+(add-to-list 'auto-mode-alist '("\\.hs$" . hsc3-mode))
+
+(provide 'hsc3)
diff --git a/hsc3.cabal b/hsc3.cabal
new file mode 100644
--- /dev/null
+++ b/hsc3.cabal
@@ -0,0 +1,371 @@
+Name:             hsc3
+Version:          0.1
+License:          GPL
+Copyright:        Rohan Drape, 2006-2007
+Author:           Rohan Drape
+Maintainer:       rd@slavepianos.org
+Stability:        Experimental
+Homepage:         http://slavepianos.org/rd/f/207949/
+Synopsis:         Haskell SuperCollider
+Description:      Haskell client for the SuperCollider synthesis server
+Category:         Sound
+Tested-With:      GHC
+Build-Depends:    base, binary, bytestring, hosc, network, random
+GHC-Options:      -Wall -fno-warn-orphans -O2
+Exposed-modules:  Sound.SC3
+                  Sound.SC3.UGen
+                  Sound.SC3.UGen.Analysis
+                  Sound.SC3.UGen.Buffer
+                  Sound.SC3.UGen.Chaos
+                  Sound.SC3.UGen.Demand
+                  Sound.SC3.UGen.Demand.Base
+                  Sound.SC3.UGen.Demand.Monadic
+                  Sound.SC3.UGen.Envelope
+                  Sound.SC3.UGen.Envelope.Construct
+                  Sound.SC3.UGen.Enum
+                  Sound.SC3.UGen.FFT
+                  Sound.SC3.UGen.FFT.Base
+                  Sound.SC3.UGen.FFT.Monadic
+                  Sound.SC3.UGen.Filter
+                  Sound.SC3.UGen.Graph
+                  Sound.SC3.UGen.Granular
+                  Sound.SC3.UGen.Information
+                  Sound.SC3.UGen.IO
+		  Sound.SC3.UGen.MachineListening
+                  Sound.SC3.UGen.Math
+                  Sound.SC3.UGen.Mix
+                  Sound.SC3.UGen.Noise.Base
+                  Sound.SC3.UGen.Noise.Monadic
+                  Sound.SC3.UGen.Operator
+                  Sound.SC3.UGen.Oscillator
+                  Sound.SC3.UGen.Panner
+                  Sound.SC3.UGen.Rate
+                  Sound.SC3.UGen.UGen
+                  Sound.SC3.UGen.UGen.Construct
+                  Sound.SC3.UGen.UGen.Math
+                  Sound.SC3.UGen.UGen.MCE
+                  Sound.SC3.UGen.UGen.Predicate
+                  Sound.SC3.UGen.UId
+                  Sound.SC3.Server
+                  Sound.SC3.Server.Command
+                  Sound.SC3.Server.Graphdef
+                  Sound.SC3.Server.Play
+                  Sound.SC3.Server.Status
+                  Sound.SC3.Server.NRT
+Other-modules:    Sound.SC3.Server.Utilities
+                  Sound.SC3.UGen.Utilities
+Data-files:       emacs/hsc3.el
+                  Help/Server/b_alloc.help.lhs
+                  Help/Server/b_allocRead.help.lhs
+                  Help/Server/b_close.help.lhs
+                  Help/Server/b_fill.help.lhs
+                  Help/Server/b_free.help.lhs
+                  Help/Server/b_gen.help.lhs
+                  Help/Server/b_get.help.lhs
+                  Help/Server/b_getn.help.lhs
+                  Help/Server/b_query.help.lhs
+                  Help/Server/b_read.help.lhs
+                  Help/Server/b_set.help.lhs
+                  Help/Server/b_setn.help.lhs
+                  Help/Server/b_write.help.lhs
+                  Help/Server/b_zero.help.lhs
+                  Help/Server/c_fill.help.lhs
+                  Help/Server/c_get.help.lhs
+                  Help/Server/c_getn.help.lhs
+                  Help/Server/clearSched.help.lhs
+                  Help/Server/c_set.help.lhs
+                  Help/Server/c_setn.help.lhs
+                  Help/Server/d_free.help.lhs
+                  Help/Server/d_loadDir.help.lhs
+                  Help/Server/d_load.help.lhs
+                  Help/Server/d_recv.help.lhs
+                  Help/Server/dumpOSC.help.lhs
+                  Help/Server/g_deepFree.help.lhs
+                  Help/Server/g_freeAll.help.lhs
+                  Help/Server/g_head.help.lhs
+                  Help/Server/g_new.help.lhs
+                  Help/Server/g_tail.help.lhs
+                  Help/Server/n_after.help.lhs
+                  Help/Server/n_before.help.lhs
+                  Help/Server/n_fill.help.lhs
+                  Help/Server/n_free.help.lhs
+                  Help/Server/n_map.help.lhs
+                  Help/Server/n_mapn.help.lhs
+                  Help/Server/notify.help.lhs
+                  Help/Server/n_query.help.lhs
+                  Help/Server/n_run.help.lhs
+                  Help/Server/n_set.help.lhs
+                  Help/Server/n_setn.help.lhs
+                  Help/Server/n_trace.help.lhs
+                  Help/Server/quit.help.lhs
+                  Help/Server/s_get.help.lhs
+                  Help/Server/s_getn.help.lhs
+                  Help/Server/s_new.help.lhs
+                  Help/Server/s_noid.help.lhs
+                  Help/Server/status.help.lhs
+                  Help/Server/sync.help.lhs
+                  Help/Server/tr.help.lhs
+                  Help/Server/u_cmd.help.lhs
+                  Help/Tutorial/Tutorial.lhs
+                  Help/UGen/Analysis/amplitude.help.lhs
+                  Help/UGen/Analysis/compander.help.lhs
+                  Help/UGen/Analysis/pitch.help.lhs
+                  Help/UGen/Analysis/runningSum.help.lhs
+                  Help/UGen/Analysis/slope.help.lhs
+                  Help/UGen/Analysis/zeroCrossing.help.lhs
+                  Help/UGen/Buffer/bufAllpassC.help.lhs
+                  Help/UGen/Buffer/bufAllpassL.help.lhs
+                  Help/UGen/Buffer/bufAllpassN.help.lhs
+                  Help/UGen/Buffer/bufChannels.help.lhs
+                  Help/UGen/Buffer/bufCombC.help.lhs
+                  Help/UGen/Buffer/bufCombL.help.lhs
+                  Help/UGen/Buffer/bufCombN.help.lhs
+                  Help/UGen/Buffer/bufDelayC.help.lhs
+                  Help/UGen/Buffer/bufDelayL.help.lhs
+                  Help/UGen/Buffer/bufDelayN.help.lhs
+                  Help/UGen/Buffer/bufDur.help.lhs
+                  Help/UGen/Buffer/bufFrames.help.lhs
+                  Help/UGen/Buffer/bufRateScale.help.lhs
+                  Help/UGen/Buffer/bufRd.help.lhs
+                  Help/UGen/Buffer/bufSampleRate.help.lhs
+                  Help/UGen/Buffer/detectIndex.help.lhs
+                  Help/UGen/Buffer/index.help.lhs
+                  Help/UGen/Buffer/indexInBetween.help.lhs
+                  Help/UGen/Buffer/osc.help.lhs
+                  Help/UGen/Buffer/playBuf.help.lhs
+                  Help/UGen/Buffer/recordBuf.help.lhs
+                  Help/UGen/Buffer/vOsc.help.lhs
+                  Help/UGen/Chaos/crackle.help.lhs
+                  Help/UGen/Chaos/cuspL.help.lhs
+                  Help/UGen/Chaos/cuspN.help.lhs
+                  Help/UGen/Chaos/fbSineC.help.lhs
+                  Help/UGen/Chaos/fbSineL.help.lhs
+                  Help/UGen/Chaos/fbSineN.help.lhs
+                  Help/UGen/Chaos/henonC.help.lhs
+                  Help/UGen/Chaos/henonL.help.lhs
+                  Help/UGen/Chaos/henonN.help.lhs
+                  Help/UGen/Chaos/latoocarfianC.help.lhs
+                  Help/UGen/Chaos/linCongC.help.lhs
+                  Help/UGen/Chaos/linCongL.help.lhs
+                  Help/UGen/Chaos/linCongN.help.lhs
+                  Help/UGen/Chaos/logistic.help.lhs
+                  Help/UGen/Chaos/lorenzL.help.lhs
+                  Help/UGen/Chaos/quadC.help.lhs
+                  Help/UGen/Chaos/quadL.help.lhs
+                  Help/UGen/Chaos/quadN.help.lhs
+                  Help/UGen/Chaos/rossler.help.lhs
+                  Help/UGen/Demand/dbrown.help.lhs
+                  Help/UGen/Demand/dbufrd.help.lhs
+                  Help/UGen/Demand/demandEnvGen.help.lhs
+                  Help/UGen/Demand/demand.help.lhs
+                  Help/UGen/Demand/dgeom.help.lhs
+                  Help/UGen/Demand/dibrown.help.lhs
+                  Help/UGen/Demand/diwhite.help.lhs
+                  Help/UGen/Demand/drand.help.lhs
+                  Help/UGen/Demand/dseq.help.lhs
+                  Help/UGen/Demand/dser.help.lhs
+                  Help/UGen/Demand/dseries.help.lhs
+                  Help/UGen/Demand/dswitch1.help.lhs
+                  Help/UGen/Demand/duty.help.lhs
+                  Help/UGen/Demand/dwhite.help.lhs
+                  Help/UGen/Demand/dxrand.help.lhs
+                  Help/UGen/Demand/tDuty.help.lhs
+                  Help/UGen/Envelope/detectSilence.help.lhs
+                  Help/UGen/Envelope/done.help.lhs
+                  Help/UGen/Envelope/envGen.help.lhs
+                  Help/UGen/Envelope/free.help.lhs
+                  Help/UGen/Envelope/freeSelf.help.lhs
+                  Help/UGen/Envelope/freeSelfWhenDone.help.lhs
+                  Help/UGen/Envelope/line.help.lhs
+                  Help/UGen/Envelope/linen.help.lhs
+                  Help/UGen/Envelope/pause.help.lhs
+                  Help/UGen/Envelope/pauseSelf.help.lhs
+                  Help/UGen/Envelope/pauseSelfWhenDone.help.lhs
+                  Help/UGen/Envelope/xLine.help.lhs
+                  Help/UGen/FFT/convolution.help.lhs
+                  Help/UGen/FFT/fft.help.lhs
+                  Help/UGen/FFT/ifft.help.lhs
+                  Help/UGen/FFT/packFFT.help.lhs
+                  Help/UGen/FFT/pv_BinScramble.help.lhs
+                  Help/UGen/FFT/pv_BinShift.help.lhs
+                  Help/UGen/FFT/pv_BinWipe.help.lhs
+                  Help/UGen/FFT/pv_BrickWall.help.lhs
+                  Help/UGen/FFT/pvcollect.help.lhs
+                  Help/UGen/FFT/pv_ConformalMap.help.lhs
+                  Help/UGen/FFT/pv_Copy.help.lhs
+                  Help/UGen/FFT/pv_Diffuser.help.lhs
+                  Help/UGen/FFT/pv_LocalMax.help.lhs
+                  Help/UGen/FFT/pv_MagAbove.help.lhs
+                  Help/UGen/FFT/pv_MagBelow.help.lhs
+                  Help/UGen/FFT/pv_MagClip.help.lhs
+                  Help/UGen/FFT/pv_MagFreeze.help.lhs
+                  Help/UGen/FFT/pv_RandComb.help.lhs
+                  Help/UGen/FFT/pv_RandWipe.help.lhs
+                  Help/UGen/FFT/pv_RectComb.help.lhs
+                  Help/UGen/Filter/allpassC.help.lhs
+                  Help/UGen/Filter/allpassL.help.lhs
+                  Help/UGen/Filter/allpassN.help.lhs
+                  Help/UGen/Filter/bpf.help.lhs
+                  Help/UGen/Filter/bpz2.help.lhs
+                  Help/UGen/Filter/brf.help.lhs
+                  Help/UGen/Filter/clip.help.lhs
+                  Help/UGen/Filter/combC.help.lhs
+                  Help/UGen/Filter/combL.help.lhs
+                  Help/UGen/Filter/combN.help.lhs
+                  Help/UGen/Filter/decay2.help.lhs
+                  Help/UGen/Filter/decay.help.lhs
+                  Help/UGen/Filter/degreeToKey.help.lhs
+                  Help/UGen/Filter/delay1.help.lhs
+                  Help/UGen/Filter/delay2.help.lhs
+                  Help/UGen/Filter/delayA.help.lhs
+                  Help/UGen/Filter/delayL.help.lhs
+                  Help/UGen/Filter/delayN.help.lhs
+                  Help/UGen/Filter/formlet.help.lhs
+                  Help/UGen/Filter/fos.help.lhs
+                  Help/UGen/Filter/freqShift.help.lhs
+                  Help/UGen/Filter/hasher.help.lhs
+                  Help/UGen/Filter/hpf.help.lhs
+                  Help/UGen/Filter/hpz1.help.lhs
+                  Help/UGen/Filter/hpz2.help.lhs
+                  Help/UGen/Filter/klank.help.lhs
+                  Help/UGen/Filter/lag2.help.lhs
+                  Help/UGen/Filter/lag3.help.lhs
+                  Help/UGen/Filter/lag.help.lhs
+                  Help/UGen/Filter/latch.help.lhs
+                  Help/UGen/Filter/leakDC.help.lhs
+                  Help/UGen/Filter/limiter.help.lhs
+                  Help/UGen/Filter/linExp.help.lhs
+                  Help/UGen/Filter/linLin.help.lhs
+                  Help/UGen/Filter/lpf.help.lhs
+                  Help/UGen/Filter/lpz1.help.lhs
+                  Help/UGen/Filter/lpz2.help.lhs
+                  Help/UGen/Filter/mantissaMask.help.lhs
+                  Help/UGen/Filter/median.help.lhs
+                  Help/UGen/Filter/moogFF.help.lhs
+                  Help/UGen/Filter/normalizer.help.lhs
+                  Help/UGen/Filter/onePole.help.lhs
+                  Help/UGen/Filter/oneZero.help.lhs
+                  Help/UGen/Filter/pitchShift.help.lhs
+                  Help/UGen/Filter/resonz.help.lhs
+                  Help/UGen/Filter/rhpf.help.lhs
+                  Help/UGen/Filter/ringz.help.lhs
+                  Help/UGen/Filter/rlpf.help.lhs
+                  Help/UGen/Filter/select.help.lhs
+                  Help/UGen/Filter/shaper.help.lhs
+                  Help/UGen/Filter/slew.help.lhs
+                  Help/UGen/Filter/sos.help.lhs
+                  Help/UGen/Filter/twoPole.help.lhs
+                  Help/UGen/Filter/twoZero.help.lhs
+                  Help/UGen/Filter/wrapIndex.help.lhs
+                  Help/UGen/Granular/grainBuf.help.lhs
+                  Help/UGen/Granular/grainFM.help.lhs
+                  Help/UGen/Granular/grainIn.help.lhs
+                  Help/UGen/Granular/grainSin.help.lhs
+                  Help/UGen/Granular/warp1.help.lhs
+                  Help/UGen/Information/controlRate.help.lhs
+                  Help/UGen/Information/numAudioBuses.help.lhs
+                  Help/UGen/Information/numBuffers.help.lhs
+                  Help/UGen/Information/numControlBuses.help.lhs
+                  Help/UGen/Information/numInputBuses.help.lhs
+                  Help/UGen/Information/numOutputBuses.help.lhs
+                  Help/UGen/Information/numRunningSynths.help.lhs
+                  Help/UGen/Information/radiansPerSample.help.lhs
+                  Help/UGen/Information/sampleDur.help.lhs
+                  Help/UGen/Information/sampleRate.help.lhs
+                  Help/UGen/Information/subsampleOffset.help.lhs
+                  Help/UGen/IO/inFeedback.help.lhs
+                  Help/UGen/IO/in.help.lhs
+                  Help/UGen/IO/inTrig.help.lhs
+                  Help/UGen/IO/keyState.help.lhs
+                  Help/UGen/IO/lagIn.lhs
+                  Help/UGen/IO/localIn.help.lhs
+                  Help/UGen/IO/localOut.help.lhs
+                  Help/UGen/IO/mouseButton.help.lhs
+                  Help/UGen/IO/mouseX.help.lhs
+                  Help/UGen/IO/mouseY.help.lhs
+                  Help/UGen/IO/offsetOut.help.lhs
+                  Help/UGen/IO/out.help.lhs
+                  Help/UGen/IO/replaceOut.help.lhs
+                  Help/UGen/IO/xOut.help.lhs
+                  Help/UGen/Math/absDif.help.lhs
+                  Help/UGen/Math/abs.help.lhs
+                  Help/UGen/Math/amClip.help.lhs
+                  Help/UGen/Math/atan2.help.lhs
+                  Help/UGen/Math/clip2.help.lhs
+                  Help/UGen/Math/difSqr.help.lhs
+                  Help/UGen/Math/distort.help.lhs
+                  Help/UGen/Math/fold2.help.lhs
+                  Help/UGen/Math/hypot.help.lhs
+                  Help/UGen/Math/ring1.help.lhs
+                  Help/UGen/Math/scaleNeg.help.lhs
+                  Help/UGen/Math/softClip.help.lhs
+                  Help/UGen/Math/sumSqr.help.lhs
+                  Help/UGen/Math/thresh.help.lhs
+                  Help/UGen/Noise/brownNoise.help.lhs
+                  Help/UGen/Noise/clipNoise.help.lhs
+                  Help/UGen/Noise/coinGate.help.lhs
+                  Help/UGen/Noise/dust2.help.lhs
+                  Help/UGen/Noise/dust.help.lhs
+                  Help/UGen/Noise/expRand.help.lhs
+                  Help/UGen/Noise/grayNoise.help.lhs
+                  Help/UGen/Noise/iRand.help.lhs
+                  Help/UGen/Noise/lfClipNoise.help.lhs
+                  Help/UGen/Noise/lfdClipNoise.help.lhs
+                  Help/UGen/Noise/lfdNoise0.help.lhs
+                  Help/UGen/Noise/lfdNoise1.help.lhs
+                  Help/UGen/Noise/lfdNoise3.help.lhs
+                  Help/UGen/Noise/lfNoise0.help.lhs
+                  Help/UGen/Noise/lfNoise1.help.lhs
+                  Help/UGen/Noise/lfNoise2.help.lhs
+                  Help/UGen/Noise/linRand.help.lhs
+                  Help/UGen/Noise/nRand.help.lhs
+                  Help/UGen/Noise/pinkNoise.help.lhs
+                  Help/UGen/Noise/rand.help.lhs
+                  Help/UGen/Noise/randID.help.lhs
+                  Help/UGen/Noise/randSeed.help.lhs
+                  Help/UGen/Noise/tExpRand.help.lhs
+                  Help/UGen/Noise/tiRand.help.lhs
+                  Help/UGen/Noise/tRand.help.lhs
+                  Help/UGen/Noise/whiteNoise.help.lhs
+                  Help/UGen/Oscillator/blip.help.lhs
+                  Help/UGen/Oscillator/formant.help.lhs
+                  Help/UGen/Oscillator/fSinOsc.help.lhs
+                  Help/UGen/Oscillator/gendy1.help.lhs
+                  Help/UGen/Oscillator/impulse.help.lhs
+                  Help/UGen/Oscillator/klang.help.lhs
+                  Help/UGen/Oscillator/lfCub.help.lhs
+                  Help/UGen/Oscillator/lfPar.help.lhs
+                  Help/UGen/Oscillator/lfPulse.help.lhs
+                  Help/UGen/Oscillator/lfSaw.help.lhs
+                  Help/UGen/Oscillator/lfTri.help.lhs
+                  Help/UGen/Oscillator/oscN.help.lhs
+                  Help/UGen/Oscillator/pulse.help.lhs
+                  Help/UGen/Oscillator/saw.help.lhs
+                  Help/UGen/Oscillator/silent.help.lhs
+                  Help/UGen/Oscillator/sinOsc.help.lhs
+                  Help/UGen/Oscillator/syncSaw.help.lhs
+                  Help/UGen/Oscillator/tGrains.help.lhs
+                  Help/UGen/Oscillator/twChoose.help.lhs
+                  Help/UGen/Oscillator/twindex.help.lhs
+                  Help/UGen/Panner/linPan2.help.lhs
+                  Help/UGen/Panner/pan2.help.lhs
+                  Help/UGen/Panner/rotate2.help.lhs
+                  Help/UGen/Panner/splay.help.lhs
+                  Help/UGen/Trigger/gate.help.lhs
+                  Help/UGen/Trigger/inRange.help.lhs
+                  Help/UGen/Trigger/lastValue.help.lhs
+                  Help/UGen/Trigger/mostChange.help.lhs
+                  Help/UGen/Trigger/peak.help.lhs
+                  Help/UGen/Trigger/phasor.help.lhs
+                  Help/UGen/Trigger/pulseCount.help.lhs
+                  Help/UGen/Trigger/pulseDivider.help.lhs
+                  Help/UGen/Trigger/runningMax.help.lhs
+                  Help/UGen/Trigger/runningMin.help.lhs
+                  Help/UGen/Trigger/sendTrig.lhs
+                  Help/UGen/Trigger/setResetFF.help.lhs
+                  Help/UGen/Trigger/sweep.help.lhs
+                  Help/UGen/Trigger/tDelay.help.lhs
+                  Help/UGen/Trigger/timer.help.lhs
+                  Help/UGen/Trigger/toggleFF.help.lhs
+                  Help/UGen/Trigger/trig1.help.lhs
+                  Help/UGen/Trigger/trig.help.lhs
