Skip to content

Instantly share code, notes, and snippets.

@mattearnshaw
Last active September 27, 2016 16:00
Show Gist options
  • Save mattearnshaw/9387f646a1bc8be2486ec383f50d9b75 to your computer and use it in GitHub Desktop.
Save mattearnshaw/9387f646a1bc8be2486ec383f50d9b75 to your computer and use it in GitHub Desktop.
(ns music.chord-catalogue
(:use [overtone.live] [overtone.inst.piano]
[clojure.math.combinatorics :only [combinations]]))
(declare gen-chords)
(declare play-chord-seq)
; The Chord Catalogue - Tom Johnson
(def chord-catalogue
(mapcat (partial gen-chords 4) (range 2 14)))
(play-chord-seq chord-catalogue 300)
(defn binomial [n k]
(let [rprod (fn [a b] (reduce * (range a (inc b))))]
(/ (rprod (- n k -1) n) (rprod 1 k))))
(defn split-i [l i]
(map (fn [[s e]]
(subvec (vec l) s e))
(partition 2 1 (reductions + (cons 0 i)))))
(defn gen-chords [octave n]
(let [intervals (reduce #(%2 %1) (combinations (range 13) n)
(for [i (range n)] (partial sort-by #(nth % i))))
chords (map #(map (partial octave-note octave) %) intervals)
pause-posns (drop-while #(< % 1) (for [i (range 13)] (binomial i (dec n))))]
(mapcat #(if (sequential? %) % [%])
(interleave (split-i chords pause-posns) (repeat :pause)))))
(defn play-chord-seq [sequence delay]
(doseq [[i chord] (map vector (range) sequence)]
(if (not= chord :pause)
(after-delay (* i delay)
#(doseq [note chord]
(piano note :vel 70 :decay 0 :release 0 :sustain 0))))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment