         corners)
       (subgraph audio-node))))
 
-(defn adshr [attack decay sustain hold release]
+(defn adshr
+  "An ADSR envelope that also lets you specify the hold duration."
+  [attack decay sustain hold release]
   (envelope [attack 1.0] [decay sustain] [hold sustain] [release 0]))
 
-(defn adsr [attack decay sustain release]
+(defn adsr
+  "A four-stage envelope."
+  [attack decay sustain release]
   (fn [context at duration]
     (let [remainder (- duration attack decay sustain)
           hold (max 0.0 remainder)
           node (adshr attack decay sustain hold release)]
       (-> node (run-with context at duration)))))
 
-(defn percussive [attack decay]
+(defn percussive
+  "A simple envelope."
+  [attack decay]
   (envelope [attack 1.0] [decay 0.0]))
 
 

    (.setValueAtTime param input at)
    (-> input (run-with context at duration) :output (.connect param))))

(defn gain [level]
  (fn [context at duration]
    (subgraph
      (doto (.createGain context)
        (-> .-gain (plug level context at duration))))))

(def pass-through (gain 1.0))


; Envelopes

  [synth context at duration]
  (synth context at duration))

(defn destination
  "The destination of the audio context i.e. the speakers."
  [context at duration]
  (sink (.-destination context)))

(defn plug [param input context at duration]
