 (defn degrees->pitches
   "Convert intervals to pitches in MIDI number format.  Supports nested collections."
   [degrees scale root]
-  (let [root (resolve-note root)]
+  (let [root (note root)]
     (when (nil? root)
       (throw (IllegalArgumentException. (str "root resolved to a nil value. degrees->pitches requires a non-nil root."))))
     (map (fn [degree]


  ([root scale-name] (scale root scale-name (range 1 8)))
  ([root scale-name degrees]
     (let [root (resolve-note root)
           degrees (resolve-degrees degrees)]
       (cons root (map #(+ root (nth-interval scale-name %)) degrees)))))


           :B  11 :b  11})


(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
  unmodified. All other inputs will raise an exception.

  Usage examples:

  (note \"C4\")  ;=> 60
  (note \"C#4\") ;=> 61
  (note \"eb2\") ;=> 39
  (note :F#7)    ;=> 102
  (note :db5)    ;=> 73
  (note 60)      ;=> 60
  (note nil)     ;=> nil"

  [n]
  (cond
   (nil? n) nil
   (integer? n) (if (>= n 0)
                    n
                    (throw (IllegalArgumentException.
                            (str "Unable to resolve note: " n ". Value is out of range. Lowest value is 0"))))
   (keyword? n) (note (name n))
   (string? n) (let [midi-note-re #"\A([a-gA-G][#b]?)([-0-9]+\Z)"
                        separated (re-find midi-note-re n)
                        _ (when (nil? separated)
                            (throw (IllegalArgumentException.
                                    (str "Unable to resolve note: " n ". Does not appear to be in MIDI format i.e. C#4"))))

                        [_ pitch-class octave] separated
                        octave (Integer. octave)
                        _ (when (< octave -1)
                            (throw (IllegalArgumentException.
                                    (str "Unable to resolve note: " n ". Octave is out of range. Lowest octave value is -1"))))
                        interval (NOTES (keyword pitch-class))

                        _ (when (nil? interval)
                            (throw (IllegalArgumentException.
                                    (str "Unable to resolve note: " n ". Not a valid pitch class such as C or Db"))))]
                    (+ interval 12 (* 12 octave)))
   :else (throw (IllegalArgumentException. (str "Unable to resolve note: " n ". Wasn't a recognised format (either an integer, keyword, string or nil)")))))

;; * Each note in a scale acts as either a generator or a collector of other notes,
;; depending on their relations in time within a sequence.
