      (assert @audio-bus-monitor-group* "Couldn't find audio bus monitor group")
      (let [bus-idx (to-sc-id audio-bus)
            bus-idx (+ chan-offset bus-idx)]
-       (if-let [[monitor _] (get @bus-monitors* bus-idx)]
+       (if-let [[monitor _] (get @audio-bus-monitors* bus-idx)]
          monitor
-         (let [monitor (atom 0)
-               cb      (control-bus (str "audio-bus-level [" bus-idx "]"))
-               m-synth (mono-audio-bus-level [:tail @audio-bus-monitor-group*]
-                                             bus-idx
-                                             cb)]
-
+         (let [m-synth (mono-audio-bus-level [:tail @audio-bus-monitor-group*]
+                                             bus-idx)
+               monitor (get-in m-synth [:taps "level"])]
+           (swap! audio-bus-monitors* assoc bus-idx [monitor m-synth])
+           monitor)))))
+
+(defn control-bus-monitor
+  "Control bus monitor. Returns an atom containing the current value of
+   the control bus. Note that this isn't the peak amplitude, rather the
+   direct value of the control bus.
+
+   For multi-channel buses, an offset may be specified. Current
+   amplitude is updated within the returned atom every 50 ms.
+
+   Note - only creates one monitor per control bus - subsequent calls for
+   the same control bus idx will return a cached monitor."
+  ([control-bus] (control-bus-monitor control-bus 0))
+  ([control-bus chan-offset]
+     (ensure-connected!)
+     (let [bus-idx (to-sc-id control-bus)
+           bus-idx (+ chan-offset bus-idx)]
+       (if-let [monitor (get @control-bus-monitors* bus-idx)]
+         monitor
+         (let [monitor (atom 0)]
            (at-at/every 50
                         #(reset! monitor (control-bus-get bus-idx))
                         bus-monitor-pool
                         :initial-delay 0
-                        :desc (str "bus-monitor [" bus-idx "]"))
-           (swap! bus-monitors* assoc bus-idx [monitor m-synth])
+                        :desc (str "control-bus-monitor [" bus-idx "]"))
+           (swap! control-bus-monitors* assoc bus-idx monitor)
            monitor)))))

  (:use [overtone.sc.machinery allocator]
        [overtone.sc.machinery.server comms]
        [overtone.sc synth ugens defaults server node]
        [overtone.helpers lib]
        [overtone.sc.foundation-groups :only [foundation-monitor-group]]
        [overtone.libs.deps            :only [on-deps]])

;; but in SC they are implemented using a simple integer referenced
;; array of float values.

(defonce ^{:private true} audio-bus-monitors* (atom {}))
(defonce ^{:private true} control-bus-monitors* (atom {}))
(defonce ^{:private true} bus-monitor-pool (at-at/mk-pool))
(defonce ^{:private true} audio-bus-monitor-group* (atom nil))

