       mechanism ever offers that), and :status, which is a
       human-oriented summmary of the status."))))
 
+(defn interval-to-bpm
+  "Given an interval between MIDI clock pulses in milliseconds,
+  calculate the implied beats per minute value, to the nearest
+  hundredth of a beat."
+  [interval]
+  (/ (math/round (double (/ 6000000 (* interval 24)))) 100.0))
+
+(defn bpm-to-interval
+  "Given a BPM, calculate the interval between MIDI clock pulses in
+  milliseconds."
+  [bpm]
+  (/ 2500.0 bpm))
+
+(defn std-dev
+  "Calculate the standard deviation of a set of samples."
+  ([samples]
+   (let [n (count samples)
+         mean (/ (reduce + samples) n)]
+     (std-dev samples n mean)))
+  ([samples n mean]
+   (let [intermediate (map #(Math/pow (- %1 mean) 2) samples)]
+     (Math/sqrt (/ (reduce + intermediate) n))))) 
+
+(def abs-tolerance
+  "If we are going to adjust the BPM, the adjustment we are going to
+  make needs to represent at least this many milliseconds per MIDI
+  clock tick (to reduce jitter)."
+  0.005)
+
+(def dev-tolerance
+  "If we are going to adjust the BPM, the adjustment must be at least
+  this many times the standard deviation in observed clock pulse
+  timings, so we can avoid jitter due to unstable timing."
+  2.2)
+
 (defn- sync-handler
   "Called whenever a MIDI message is received for a synced metronome.
   If it is a clock pulse, update the ring buffer in which we are

                mean (/ passed intervals)]
            (rhythm/metro-bpm metronome (double (/ 60000 mean))))))
      ;; This tap was isolated, but may start a new series.
      (reset! buffer (conj (ring-buffer max-tempo-tap-interval) timestamp))))
  nil)

(defn create-tempo-tap-handler
  "Returns a function which implements a simple tempo-tap algorithm on
  the supplied metronome."
  [metronome]
  (let [buffer (atom (ring-buffer max-tempo-tap-interval))]
    (fn [] (tap-handler buffer metronome))))

(defonce

           [java.util.regex Pattern]))

(def ^:private max-clock-intervals
  "How many MIDI clock pulses and interval averages should be kept
  around for BPM calculation?"
  30)

(def ^:private min-clock-intervals
  "How many MIDI clock pulses are needed in order to start attempting
  BPM calculation?"
  12)

(def ^:private max-clock-lag
  "How many ms is too long to wait between MIDI clock pulses?"
  150)

(def ^:private max-tempo-taps
  "How many tempo taps should be kept around for averaging?"
  4)

(def ^:private max-tempo-tap-lag
  "How long is too long for a tap to be considered part of
  establishing a tempo?"
  2000)
