 
   "
   [path & args]
-  (let [{:keys [path args] :as s} (apply load-sample path args)
-        player (fn [& pargs]
-                 (let [{:keys [id n-channels]} (get @loaded-samples* [path args])]
-                   (cond
-                    (= n-channels 1) (apply mono-player id pargs)
-                    (= n-channels 2) (apply stereo-player id pargs))))]
-    (with-meta
-      (callable-map s player)
-      {:type ::playable-sample})))
+  (let [smpl (apply load-sample path args)]
+    (map->PlayableSample smpl)))
+
+;; Samples are just audio files loaded into a buffer, so buffer
+;; functions work on samples too.
+(derive Sample         ::sample)
+(derive PlayableSample ::playable-sample)
+
+(derive ::sample :overtone.sc.buffer/file-buffer)
+(derive ::playable-sample ::sample)
 
 (defmethod buffer-id ::sample [sample] (:id sample))
 

          start    (get arg-map :start 0)
          n-frames (get arg-map :size 0)
          buf      (buffer-alloc-read path start n-frames)]
      (let [sample (with-meta
                     (merge buf
                            {:path path
                             :args args
                             :name f-name})
                     {:type ::sample})]
        (dosync (alter loaded-samples* assoc [path args] sample))
        sample))))


  [s]
  (isa? (type s) ::sample))

(defn- free-loaded-sample
  [[[path args] buf]]
  (if (server-connected?)
