       (when (< i (count freqs))
         (let [freq (nth freqs i)]
           (.emit-sound this freq started-at))
-        (recur (inc i) (+ started-at 0.4)))))
+        (recur (inc i) (+ started-at char-interval)))))
 
   (<listen [_]
     (let [c (chan)]
       (go
-        (let [stream (<! (<stream))
+        (let [stream (<! (<media-stream))
               analyser (.createAnalyser js-context)
               mic (.createMediaStreamSource js-context stream)
-              buffer-length (.-frequencyBinCount analyser)
-              buffer (js/Float32Array. buffer-length)
               nyquist (/ (.-sampleRate js-context) 2)
-              process (fn process [buf]
-                        (.getFloatFrequencyData analyser buffer)
-                        (if-let [freq (peak-freq buffer nyquist)]
-                          (.setTimeout js/window
-                                       (partial process (conj buf freq))
-                                       5)
-                          (do
-                            (when (not (empty? buf))
-                              (let [counted-freqs (map #(vector (count %)
-                                                                (first %))
-                                                       (partition-by identity
-                                                                     buf))]
-                                (when-let [freq-pairs (filter #(>= (key %) 20)
-                                                              counted-freqs)]
-                                  (doseq [freq-pair freq-pairs]
-                                    (put! c (val freq-pair))))))
-                            (.setTimeout js/window (partial process [] 10)))))]
+              process (fn process [backlog]
+                        (let [raw-freqs (fetch-freqs analyser)]
+                          (if-let [freq (peak-freq raw-freqs nyquist 18000 -80)]
+                            (.setTimeout js/window
+                                         (partial process (conj backlog freq))
+                                         process-interval)
+                            (let [freqs (select-freqs backlog peak-threshold)]
+                              (doseq [freq freqs]
+                                (.debug js/console (str "peaked: " freq))
+                                (put! c freq))
+                              (.setTimeout
+                               js/window
+                               (partial process [] process-interval))))))]
               (.connect mic analyser)
               (process [])))
       c)))
 
-(defn initialize-audio-context []
+
+(defn initialize-audio-context
+  [& {:keys [ramp-duration
+             duration
+             char-interval
+             process-interval
+             peak-threshold]
+      :or {ramp-duration 0.0001
+           duration 0.2
+           char-interval 0.4
+           process-interval 10
+           peak-threshold 20}}]
   (let [js-context (audio-context-constructor.)]
-    (AudioContext. js-context)))
+    (AudioContext. js-context
+                   ramp-duration
+                   duration
+                   char-interval
+                   process-interval
+                   peak-threshold)))

           (throw (js/Error. (str "Can't initialize media device. [" e "]")))))))
    c))

(defn- peak-freq [arr nyquist]
  (let [buffer-length (.-length arr)
        freq-to-index #(js/Math.round (* (/ % nyquist) buffer-length))
        index-to-freq #(* % (/ nyquist buffer-length))]
    (loop [i (freq-to-index 18500)
           index -1
           max (- (.-Infinity js/window))]
      (if (< i buffer-length)

  (:require [cljs.core.async :refer [<! put! chan]])
  (:require-macros [cljs.core.async.macros :refer [go]]))


(def audio-context-constructor (or js/window.AudioContext
                                   js/window.webkitAudiocontext))


(defn- <media-stream []
  (let [c (chan)]
    (go
      (let [navigator (.-navigator js/window)
