   [buf]
   (isa? (type buf) ::buffer))
 
+(defn file-buffer?
+  [buf]
+  (isa? (type buf) ::file-buffer))
+
 (defn buffer-free
   "Synchronously free an audio buffer and the memory it was consuming."
   [buf]

  ([buf-cue]
     (buffer-cue-pos buf-cue 0))
  ([buf-cue pos]
     (assert (buffer-cue? buf-cue))
     (when-not @(:open? buf-cue)
       (throw (Exception. "buffer-cue is closed.")))
     (let [{:keys [id path]} buf-cue]
       (snd "/b_close" id)
       (snd "/b_read" id path pos -1 0 1))
     buf-cue))

(defn buffer-cue-close
  "Close a buffer stream created with #'buffer-cue. Also frees the internal
  buffer. Returns the path of the streaming file."
  [buf-cue]
  (assert (buffer-cue? buf-cue))
  (when-not @(:open? buf-cue)
    (throw (Exception. "buffer-cue already closed.")))

  (snd "/b_close" (:id buf-cue))
  (buffer-free buf-cue)
  (reset! (:open? buf-cue) false)
  (:path buf-cue))

(defmulti buffer-id type)
(defmethod buffer-id java.lang.Integer [id] id)

        :path path
        :start start
        :open? (atom true))
      {:type ::buffer-in-stream})))

(derive ::buffer-in-stream ::file-buffer)

(defn buffer-in-stream?
  [bc]
  (isa? (type bc) ::buffer-in-stream))

(defn buffer-cue-pos
  "Moves the start position of a buffer cue to the frame indicated by
