            [com.sun.media.sound SF2Soundbank]))
 
 (defn ratio [value]
-  (toRatio value))
+  (clojure.lang.Numbers/toRatio value))
 
 (defn env [num-points values & args]
-  (let [args (if (empty? args) '(:cubic) args)
+  (let [args (if (empty? args)
+               (if (= 2 (count values)) '(:linear) '(:cubic))
+               args)
         interp (apply interpolate-parametric values args)
         fix-type (cond
-                   (every? ratio? values) toRatio
+                   (every? ratio? values) ratio
                    (every? integer? values) int
-                   :else double)]
-    (map #(fix-type (interp %)) (range 0 1 (/ 1.0 num-points)))))
+                   :else double)
+        values (if (= 2 (count values))
+                 (list (first values)
+                       (fix-type (/ (+ (first values) (last values)) 2))
+                       (last values))
+                 values)]
+    (map #(fix-type (interp %)) (concat (take (- num-points 1) (range 0.0 1.0 (/ 1.0 num-points))) [1.0]))))
 
 (defn vec-rest [coll]
   (if (vector? coll)


(ns semitone.core
  (:require [clojure.pprint :refer [pprint]]
            [clojure.lang.Numbers :refer [toRatio]]
            [clojure.stacktrace :refer [print-stack-trace]]
            [incanter.interpolation :refer [interpolate-parametric]])
  (:import [javax.sound.midi

                      :repeat-length nil
                      :notes (vec-rest notes)})
        (symbol? length)
        (if-let [m (re-matches #"(-|)((?:[xwhqistjlmno](?:[0-9]*)\.*)+)" (name length))]
          (let [length-map {"x" 2 "w" 1 "h" 1/2 "q" 1/4 "i" 1/8 "s" 1/16 "t" 1/32
                            "j" 1/64 "l" 1/128 "m" 1/256 "n" 1/512 "o" 1/1024}]
            (merge state {:message-type (if (= "-" (get m 1)) nil (:message-type state))
                          :length (reduce +
                                          (map #(* 4
                                                   (get length-map (get % 1))
                                                   (- 2 (/ 1 (reduce * (repeat (count (get % 2)) 2))))
                                                   (/ 1 (if (or (= (get % 3) "") (= (Integer. (get % 3)) 0)) 1 (Integer. (get % 3))))
                                                   ppq)
                                               (re-seq #"\G([xwhqistjlmno])([0-9]*)(\.*)" (get m 2))))
                          :repeat-length nil
                          :notes (vec-rest notes)}))
          (if-let [m (re-matches #"([-=])[-=]*" (name length))]
