Bohtvaroh

Overtone singing

Apr 18th, 2013
63
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. (defn ratios [start end]
  2.   (map #(/ % start) (range start end)))
  3.  
  4. (defn split-octaves [ratios]
  5.   (loop [current-octave 1, acc [], ratios ratios]
  6.     (if-not (seq ratios)
  7.       acc
  8.       (let [next-octave-ratio (Math/pow 2 current-octave)
  9.             [octave-ratios rest] (split-with #(< % next-octave-ratio) ratios)]
  10.         (recur (inc current-octave) (conj acc (vec octave-ratios)) rest)))))
  11.  
  12. (defn normalize-ratios [octaves]
  13.   (mapv (fn [octave] (mapv #(/ % (first octave)) octave)) octaves))
  14.  
  15. (def natural-scale-ratios-map
  16.   (sorted-map 1     :tonic
  17.               16/15 :minor-second
  18.               9/8   :major-second
  19.               6/5   :minor-third
  20.               5/4   :major-third
  21.               4/3   :forth
  22.               7/5   :tritone
  23.               3/2   :fifth
  24.               8/5   :minor-sixth
  25.               5/3   :major-sixth
  26.               16/9  :minor-seventh
  27.               15/8  :major-seventh
  28.               2     :octave))
  29.  
  30. (def natural-scale-ratios
  31.   (apply sorted-set (keys natural-scale-ratios-map)))
  32.  
  33. (defn find-neighbors [ratio]
  34.   (let [[xs ys] (split-with #(> ratio %) natural-scale-ratios)]
  35.     [(last xs) (first ys)]))
  36.  
  37. (defn describe-ratio [ratio]
  38.   (if (natural-scale-ratios ratio)
  39.     [ratio (str (natural-scale-ratios-map ratio))]
  40.     [ratio (let [[lower upper] (find-neighbors ratio)
  41.                  neighbors-ratio (/ upper lower)
  42.                  third (Math/pow neighbors-ratio 1/3)
  43.                  max-lower (* lower third)
  44.                  min-upper (/ upper third)]
  45.              (cond (< ratio max-lower) (str (natural-scale-ratios-map lower) "+")
  46.                    (> ratio min-upper) (str (natural-scale-ratios-map upper) "-")
  47.                    :else (str (natural-scale-ratios-map lower) " - " (natural-scale-ratios-map upper))))]))
  48.  
  49. (defn describe-overtone-scale [start end]
  50.   (let [ratios (ratios start end)
  51.         octaves (normalize-ratios (split-octaves ratios))]
  52.     (mapv #(mapv describe-ratio %) octaves)))
Advertisement
Add Comment
Please, Sign In to add comment