diff options
| -rw-r--r-- | index.html | 183 | ||||
| -rw-r--r-- | intonation.js | 4 |
2 files changed, 112 insertions, 75 deletions
@@ -7,6 +7,12 @@ * { cursor: default; } +.heading { + cursor: pointer; +} +.active { + font-weight: bold; +} pre { white-space: pre-line; } @@ -99,88 +105,84 @@ Wendy Carlos' Alpha scale with perfect fifth divided in nine </script> <pre> +<script src="http://asdf.us/harp/js/vendor/Tone.min.js"></script> <script src="intonation.js"></script> +<div id="scale_list"></div> <script> var delim = "</span> <span>" -function write(s){ document.write("<span>" + (s || "") + "</span>\n") } - -s = new Intonation({ - intervals: '1/1 9/8 5/4 4/3 3/2 5/3 15/8 2/1', -}) -write("original scale:") -write( s.range(0, 10).map(function(i){ return i.toFixed(0) }).join(delim) ) -write("") - -s = new Intonation({ - root: 450, - intervals: '1/1 9/8 5/4 4/3 3/2 5/3 15/8 2/1', -}) -write("root @ 450:") -write( s.range(0, 10).map(function(i){ return i.toFixed(0) }).join(delim) ) -write("") - -s = new Intonation({ - tet: 5, -}) -write("5-tet") -write( s.range(0, 6).map(function(i){ return i.toFixed(0) }).join(delim) ) -write("") - -s = new Intonation({ - tet: 12, -}) -write("12-tet") -write( s.range(0, 13).map(function(i){ return i.toFixed(0) }).join(delim) ) -write("") - -s = new Intonation({ - scl: document.querySelector("#twelveet-scl").innerHTML -}) -write("12-tet.scl:") -write( s.range(0, s.scale.length+1).map(function(i){ return i.toFixed(0) }).join(delim) ) -write("") - -s = new Intonation({ - tet: 17, -}) -write("17-tet") -write( s.range(0, 18).map(function(i){ return i.toFixed(0) }).join(delim) ) -write("") +function write(s){ + var div = document.createElement("div") + div.innerHTML = s + scale_list.appendChild(div) + return div +} -s = new Intonation({ - intervals: '1/1 81/80 33/32 21/20 16/15 12/11 11/10 10/9 9/8 8/7 7/6 32/27 6/5 11/9 5/4 14/11 9/7 21/16 4/3 27/20 11/8 7/5 10/7 16/11 40/27 3/2 32/21 14/9 11/7 8/5 18/11 5/3 27/16 12/7 7/4 16/9 9/5 20/11 11/6 15/8 40/21 64/33 160/81 2/1', -}) -write("partch:") -write( s.range(0, 44).map(function(i){ return i.toFixed(0) }).join(delim) ) -write("") +var opts = [ + { + intervals: '1/1 9/8 5/4 4/3 3/2 5/3 15/8 2/1', + name: "harmonic scale", + }, + { + root: 450, + intervals: '1/1 9/8 5/4 4/3 3/2 5/3 15/8 2/1', + name: "harmonic scale @ 450", + }, + { + tet: 5, + }, + { + tet: 12, + }, + { + scl: document.querySelector("#twelveet-scl").innerHTML, + }, + { + tet: 17, + }, + { + tet: 12, + }, + { + intervals: '1/1 81/80 33/32 21/20 16/15 12/11 11/10 10/9 9/8 8/7 7/6 32/27 6/5 11/9 5/4 14/11 9/7 21/16 4/3 27/20 11/8 7/5 10/7 16/11 40/27 3/2 32/21 14/9 11/7 8/5 18/11 5/3 27/16 12/7 7/4 16/9 9/5 20/11 11/6 15/8 40/21 64/33 160/81 2/1', + name: "harry partch scale", + }, + { + scl: document.querySelector("#meantone-scl").innerHTML, + }, + { + scl: document.querySelector("#mavila12-scl").innerHTML, + }, + { + scl: document.querySelector("#carlos_alpha-scl").innerHTML, + }, +] +var scale +var scale_list = document.querySelector("#scale_list") -s = new Intonation({ - scl: document.querySelector("#meantone-scl").innerHTML -}) -write("meantone.scl:") -write( s.range(0, s.scale.length+1).map(function(i){ return i.toFixed(0) }).join(delim) ) -write("") +opts.forEach(function(opt){ + var s = new Intonation(opt) + var heading = write( s.name ) + var limit = s.interval == 2 ? s.scale.length : s.scale.length*2 + write( "<span>" + s.range(0, limit+1).map(function(i){ return i.toFixed(0) }).join(delim) + "</span>" ) + write(" ") -s = new Intonation({ - scl: document.querySelector("#mavila12-scl").innerHTML -}) -write("mavila12.scl:") -write( s.range(0, s.scale.length+1).map(function(i){ return i.toFixed(0) }).join(delim) ) -write( s.range(0, (s.scale.length*2)+1).map(function(i){ return i.toFixed(0) }).join(delim) ) -write("") + if (! scale) { + scale = s + heading.classList.add("active") + console.log("scale:", s.name) + } -s = new Intonation({ - scl: document.querySelector("#carlos_alpha-scl").innerHTML + heading.classList.add("heading") + heading.addEventListener("click", function(){ + var active = document.querySelector(".active") + active && active.classList.remove("active") + scale = s + heading.classList.add("active") + console.log("scale:", s.name) + }) }) -write("carlos_alpha.scl (does not contain octave):") -write( s.range(0, s.scale.length+1).map(function(i){ return i.toFixed(0) }).join(delim) ) -write( s.range(0, (s.scale.length*2)+1).map(function(i){ return i.toFixed(0) }).join(delim) ) -write("") -</script> -<script src="http://asdf.us/harp/js/vendor/Tone.min.js"></script> -<script> -polysynth = new Tone.PolySynth(8, Tone.synth) +var polysynth = new Tone.PolySynth(8, Tone.synth) polysynth.set({ oscillator: { type: "sine" }, envelope:{ @@ -194,11 +196,42 @@ var comp = new Tone.Compressor(-30, 3).toMaster() polysynth.connect(comp) Array.prototype.slice.apply( document.querySelectorAll("span") ).forEach(function(span){ if (! span.innerHTML.match(/[^0-9]/)) { - var f = parseInt(span.innerHTML) + var freq = parseInt(span.innerHTML) span.classList.add("note") span.addEventListener("click", function(){ - polysynth.triggerAttackRelease(f, 1.5) + play(freq) }) } }) + +var keys +var keys = {} +var key_numbers = {} +var letters = "zxcvbnmasdfghjklqwertyuiop" +var numbers = "1234567890"; +letters.toUpperCase().split("").map(function(k,i){ + keys[k.charCodeAt(0)] = i +}) +numbers.split("").map(function(k,i){ + keys[k.charCodeAt(0)] = true + key_numbers[k.charCodeAt(0)] = true +}) + +window.addEventListener("keydown", keydown, true) +function keydown (e){ + if (e.altKey || e.ctrlKey || e.metaKey) { + e.stopPropagation() + return + } + if (! (e.keyCode in keys)) return + var index = keys[e.keyCode] + if (e.shiftKey) index += letters.length + var freq = scale.index(index) + play(freq) +} + +function play (freq) { + console.log(freq.toFixed(0)) + polysynth.triggerAttackRelease(freq, 1.5) +} </script>
\ No newline at end of file diff --git a/intonation.js b/intonation.js index fe2fa37..a0cbedf 100644 --- a/intonation.js +++ b/intonation.js @@ -1,6 +1,7 @@ var Intonation = (function(){ var Intonation = function(opt){ opt = this.opt = Object.assign({ + name: "", root: 440, octave: 0, interval: 2, @@ -27,6 +28,7 @@ var Intonation = (function(){ if (typeof interval_list == "string") { interval_list = interval_list.split(" ") } + this.name = this.opt.name || "interval list" this.intervals = interval_list this.interval = this.opt.interval = parseInterval.call(this, interval_list.pop() ) this.scale = interval_list.map( parseIntervalString.bind(this) ).filter(function(v){ @@ -45,6 +47,7 @@ var Intonation = (function(){ n *= ratio scale.push(n) } + this.name = this.opt.name || tet + "-tone equal temperament" this.intervals = null } Intonation.prototype.generate_scl = function(){ @@ -52,6 +55,7 @@ var Intonation = (function(){ var scl = this.parse_scl( this.opt.scl ) this.intervals = scl.notes this.interval = scl.notes.pop() + this.name = this.opt.name || scl.description this.scale = scl.notes.map(function(v){ return v * root }) |
