            (when (every? zero? [size rate n-channels])
              (free-id :audio-buffer id)
              (throw (Exception. (str "Unable to read file - perhaps path is not a valid audio file: " path))))
-           (with-meta
-             (merge info
-                    {:allocated-on-server (atom true)})
-             {:type ::file-buffer}))))))
+
+           (map->BufferFile
+            (assoc info
+              :allocated-on-server (atom true))))))))
+
+(derive BufferInfo ::buffer-info)
+(derive Buffer     ::buffer)
+(derive BufferFile ::file-buffer)
 
 (derive ::buffer ::buffer-info)
 (derive ::file-buffer ::buffer)

  (buffer-free buf-stream)
  (reset! (:open? buf-stream) false)
  (:path buf-stream))

(defn buffer-cue
  "Returns a buffer-cue which is similar to a regular buffer but may be used

  (let [path    (resolve-tilde-path path)
        f-ext   (file-extension path)
        arg-map (merge {:n-chans 2
                        :size 65536
                        :header (or f-ext "wav")
                        :samples "int16"}
                       (apply hash-map args))
        {:keys [n-chans size header samples]} arg-map
        buf (buffer size n-chans)]
    (snd "/b_write" (:id buf) path header samples -1 0 1)
    (map->BufferOutStream
     (assoc buf
       :path path
       :open? (atom true)))))

(derive BufferOutStream ::buffer-out-stream)
(derive ::buffer-out-stream ::file-buffer)

(defn buffer-out-stream?
