 (ns klangmeister.sound.synthesis)
+
+; A synth is a function that returns a section.
+(defn section
+  ([input output] {:input input :output output})
+  ([singleton] (section singleton singleton)))
 
 ; Plumbing
 
 (defn run-with
-  "Convert a node (actually a reader fn) into a concrete audio node by supplying context and timing."
-  [node context at duration]
-  (node context at duration))
+  "Convert a synth (actually a reader fn) into a concrete section by supplying context and timing."
+  [synth context at duration]
+  (synth context at duration))
 
 (defn destination [context at duration]
-  (.-destination context))
+  (section (.-destination context)))
 
 (defn plug [param input context at duration]
-  "Plug an input into an audio parameter, accepting both numbers and nodes."
+  "Plug an input into an audio parameter, accepting both numbers and synths."
   (if (number? input)
     (.setValueAtTime param input at)
-    (-> input (run-with context at duration) (.connect param))))
+    (-> input (run-with context at duration) :output (.connect param))))
 
 (defn gain [level]
   (fn [context at duration]
-    (doto (.createGain context)
-      (-> .-gain (plug level context at duration)))))
+    (section
+      (doto (.createGain context)
+        (-> .-gain (plug level context at duration))))))
 
 
 ; Envelopes

(defn biquad-filter
  ([type freq q]
   (fn [context at duration]
     (doto (-> (biquad-filter type freq) (run-with context at duration))
       (-> .-Q (plug q context at duration)))))
  ([type freq]
   (fn [context at duration]
     (doto (.createBiquadFilter context)
       (-> .-frequency .-value (set! 0))
       (-> .-frequency (plug freq context at duration))
       (-> .-type (set! type))))))

(def low-pass (partial biquad-filter "lowpass"))
(def high-pass (partial biquad-filter "highpass"))


(defn stereo-panner [pan]
  (fn [context at duration]
    (section
      (doto (.createStereoPanner context)
        (-> .-pan (plug pan context at duration))))))

(defn delay-line
  [time]
  (fn [context at duration]
    (let [maximum 5]
      (section
        (doto (.createDelay context maximum)
          (-> .-delayTime (plug time context at duration)))))))

; FIXME: Unify with noise.
(defn convolver
