 (def MIDI-NOTE-RE (re-pattern MIDI-NOTE-RE-STR))
 (def ONLY-MIDI-NOTE-RE (re-pattern (str "\\A" MIDI-NOTE-RE-STR "\\Z")))
 
-(defn- parse-note-match
+(defn midi-string-matcher
+  "Determines whether a midi keyword is valid or not. If valid,
+  returns a regexp match object"
+  [mk]
+  (re-find ONLY-MIDI-NOTE-RE (name mk)))
+
+(defn validate-midi-string!
+  "Throws a friendly exception if midi-keyword mk is not
+  valid. Returns regexp match object if valid."
+  [mk]
+  (let [matcher (midi-string-matcher mk)]
+    (when-not matcher
+      (throw (IllegalArgumentException.
+              (str "Invalid midi-string. " mk
+                   " does not appear to be in MIDI format i.e. C#4"))))
+
+    (let [[match pictch-class octave] matcher]
+      (when (< (Integer. octave) -1)
+        (throw (IllegalArgumentException.
+                (str "Invalid midi-string: " mk
+                     ". Octave is out of range. Lowest octave value is -1")))))
+    matcher))
+
+(defn note-map
   "Takes a match array returned by a regexp match and returns a map of note info"
-  [match]
-  (let [[match pitch-class octave] match
+  [midi-string]
+  (let [[match pitch-class octave] (validate-midi-string! midi-string)
         pitch-class                (canonical-pitch-class-name pitch-class)
         octave                     (Integer. octave)
         interval                   (NOTES (keyword pitch-class))]

           look-ahead (if post-str (str "(?=" post-str ")") "")
           match (re-find (re-pattern (str look-behind MIDI-NOTE-RE-STR look-ahead)) s)]
       (when match
         (parse-note-match match)))))




     :interval    interval
     :midi-note   (octave-note octave interval)}))


(defn mk-midi-string
  "Takes a string or keyword representing a pitch and a number
  representing an integer and returns a new keyword which is a
  concatanation of the two. Throws an error if the resulting midi
  string is invalid.

  (midi-string :F 7)  ;=> :F7
  (midi-string :Eb 3) ;=> :Eb3"
  [pitch-key octave]
  (let [res (str (name pitch-key) octave)]
    (validate-midi-string! res)
    res))

(defn note
  "Resolves note to MIDI number format. Resolves upper and lower-case keywords
  and strings in MIDI note format. If given an integer or nil, returns them
