   (isa? (type s) ::sample))
 
 (defn- free-loaded-sample
-  [[[path args] buf]]
-  (if (server-connected?)
-    (do (buffer-free buf)
-        (dosync (alter loaded-samples*
-                       dissoc
-                       [path args])))))
+  [smpl]
+  (let [path (:path smpl)
+        args (:args smpl)]
+    (if (server-connected?)
+      (do (buffer-free smpl)
+          (swap! cached-samples* dissoc [path args])
+          (swap! loaded-samples* dissoc (:id smpl))))))
 
 (defn free-all-loaded-samples
   "Free all buffers associated with a loaded sample and the memory they
   consume. Also remove each sample from @loaded-samples once freed"
   []
-  (doseq [loaded-sample @loaded-samples*]
+  (doseq [loaded-sample (vals @loaded-samples*)]
     (free-loaded-sample loaded-sample)))
 
 (defn free-sample

  channels of file and number of samples requested (:size), or fewer if
  sound file is smaller than requested. Reads sound file data from the
  given starting frame in the file (:start). If the number of frames
  argument is less than or equal to zero, the entire file is read."
  [path & args]
  (let [path (canonical-path path)]
    (if-let [sample (get @loaded-samples* [path args])]
      sample
      (do
        (dosync (alter loaded-samples* assoc [path args] nil))
        (if (server-connected?)
          (apply load-sample* path args))))))

(defn load-samples
  "Takes a directoy path or glob path (see #'overtone.helpers.file/glob)

      (out out-bus (* vol
                      (scaled-v-disk-in 2 buf rate loop?))))))

(defonce loaded-samples* (atom {}))
(defonce cached-samples* (atom {}))

(defrecord Sample [id size n-channels rate allocated-on-server path args name])

(defn- load-sample*
  [path arg-map]
  (let [path (canonical-path path)
        f    (file path)]
    (when-not (.exists f)
      (throw (Exception. (str "Unable to load sample - file does not exist: " path))))
    (let [f-name   (or (:name arg-map) (.getName f))
          start    (get arg-map :start 0)
          n-frames (get arg-map :size 0)
          buf      (buffer-alloc-read path start n-frames)
          sample   (map->Sample
                    (assoc buf
                      :path path
                      :args arg-map
                      :name f-name))]
      (swap! cached-samples* assoc [path arg-map] sample)
      (swap! loaded-samples* assoc (:id buf) sample)
      sample)))

(defn load-sample
  "Synchronously load a .wav or .aiff file into a memory buffer. Returns
