Created
February 7, 2013 04:19
-
-
Save rogerallen/4728474 to your computer and use it in GitHub Desktop.
Leipzig poly-player. Translate live midi playing in one key into another key entirely. Allows you to play "the white keys" on a keyboard and hear a different key without breaking your brain on manual transposition.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns explore-overtone.leipzig-poly-player | |
(:use | |
leipzig.melody | |
leipzig.scale | |
leipzig.canon) | |
(:require [overtone.live :as o] | |
[overtone.inst.sampled-piano :as p])) | |
;; "un-scale" -- the inverse translations to go from raw pitches 60, | |
;; 62, etc. to scale indices 0, 1, etc. Then, you can "re-scale" in | |
;; leipzig to get into any scale you would like. (some of this | |
;; duplicates private code in lepizig.scale.) | |
(defmacro defs {:private true} [names values] | |
`(do ~@(map | |
(fn [name value] `(def ~name ~value)) | |
names (eval values)))) | |
(defn- from [base] (partial + base)) | |
(defn- sum-n [series n] (apply + (take n series))) | |
(defn- unfrom [base] (partial + (- base))) | |
(defs [unC unD unE unF unG unA unB] | |
(map | |
(comp unfrom (from 60) major) | |
(range))) | |
(defmulti unscale-of | |
(fn [intervals degree-sum] | |
(cond | |
;; FIXME? (not= degree (floor degree)) :fraction | |
(neg? degree-sum) :negative | |
:otherwise :natural))) | |
(defmethod unscale-of :natural [intervals degree-sum] | |
(count (take-while #(<= % degree-sum) (reductions + (cycle intervals))))) | |
(defmethod unscale-of :negative [intervals degree-sum] | |
(- (count (take-while #(<= % (- degree-sum)) (reductions + (cycle (reverse intervals))))))) | |
(defn unscale [intervals] (partial unscale-of intervals)) | |
(def unMajor (unscale [2 2 1 2 2 2 1])) | |
(defs | |
[unIonian unDorian unPhrygian unLydian unMixolydian unAeolian unLocrian] | |
(map (partial mode unMajor) (range))) | |
(def unMinor unAeolian) | |
;;(major 5) -> 9 | |
;;(unMajor 9) -> 5 | |
;;(major -4) -> -7 | |
;;(unMajor -7) -> -4 | |
;;((comp unMajor unC) 50) -> 5 | |
;; let's take a live midi input and rescale the white keys on the piano | |
;; into something you wouldn't normally expect... | |
(def lpp (o/midi-poly-player | |
(fn [& {:keys [note velocity]}] | |
;; transpose the C major scale (white keys) | |
(let [pitch-index ((comp unMajor unC) note) ;; also can try "unMinor unA" | |
;; into D mixolydian | |
new-note ((comp D mixolydian) pitch-index)] | |
(p/sampled-piano :note new-note | |
:velocity velocity))))) | |
;; (o/midi-player-stop) use this when changing the |
[I swear I just posted this comment...now I'm doubly irritated with gists...losing an update & never notifying me of comments...sigh]
Yes, now anyone can play that tune in D mixolydian without breaking a sweat...
I could use some help on the naming, though. unMajor? unC? not exactly a pinnacle of clarity.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Very cool. I hadn't thought of being able to reverse the process of rendering onto a scale...
No longer will musicians have to learn the fingering for more than one scale!