diff options
| -rw-r--r-- | index.html | 77 | ||||
| -rw-r--r-- | intonation.js | 49 |
2 files changed, 104 insertions, 22 deletions
diff --git a/index.html b/index.html new file mode 100644 index 0000000..358b4a3 --- /dev/null +++ b/index.html @@ -0,0 +1,77 @@ +<style> +.note { + color: #339; + text-decoration: underline; + cursor: pointer; +} +* { + cursor: default; +} +</style> +<pre> +<script src="intonation.js"></script> +<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({ + tet: 17, +}) +write("17-tet") +write( s.range(0, 18).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) +polysynth.set({ + oscillator: { type: "sine" }, + envelope:{ + attack: 0.01, + decay: 2.5, + sustain: 0.0, + release: 0.1, + } +}) +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) + span.classList.add("note") + span.addEventListener("click", function(){ + polysynth.triggerAttackRelease(f, 1.5) + }) + } +}) +</script>
\ No newline at end of file diff --git a/intonation.js b/intonation.js index 4485d81..509addd 100644 --- a/intonation.js +++ b/intonation.js @@ -1,18 +1,20 @@ var Intonation = (function(){ var Intonation = function(opt){ - opt = Object.assign({ + opt = this.opt = Object.assign({ root: 440, octave: 0, interval: 2, tet: 0, + intervals: null, }, opt || {}) this.generate() } - Intonation.prototype.generate = function(){ - if (this.opt.tet) { + Intonation.prototype.generate = function(opt){ + opt = Object.assign(this.opt, opt || {}) + if (opt.tet) { this.generate_tet() } - else { + else if (opt.intervals) { this.generate_intervals() } } @@ -22,23 +24,11 @@ var Intonation = (function(){ if (typeof interval_list == "string") { interval_list = interval_list.split(" ") } - var intervals = .map(function(v){ - if (v.indexOf("/") !== -1) return parseInterval(v) // intervals - if (v.indexOf("f") !== -1) return parseFloat(v) // pure frequencies - return parseFloat(v) - }).filter(function(v){ + this.intervals = interval_list + this.opt.interval = parseInterval.call(this, interval_list.pop() ) + this.scale = interval_list.map( parseIntervalString.bind(this) ).filter(function(v){ return !! v }) - if (! intervals.length) return - this.opt.interval = intervals.pop() - scale = intervals.map(function(v){ - if (v < 20) { - return v * root - } - else { - return v - } - }) } Intonation.prototype.generate_tet = function(){ var scale = this.scale = [] @@ -47,11 +37,12 @@ var Intonation = (function(){ var interval = this.opt.interval var ratio = Math.pow( interval, 1/tet ) var n = root - scale = [n] + scale.push(n) for (var i = 0; i < tet; i++) { n *= ratio scale.push(n) } + this.intervals = null } Intonation.prototype.index = function(i, octave){ octave = octave || this.opt.octave @@ -60,6 +51,13 @@ var Intonation = (function(){ f *= Math.pow(this.opt.interval, pow) return f } + Intonation.prototype.range = function(min, max){ + var a = [] + for (var i = min; i < max; i++) { + a.push( this.index(i) ) + } + return a + } Intonation.prototype.set_root = function(f){ this.opt.root = f this.generate() @@ -68,11 +66,13 @@ var Intonation = (function(){ if (f == 0) return 0 var scale_f = f var pow = 0 + var interval = this.opt.interval + var scale = this.scale while (scale_f < root) { scale_f *= interval pow -= 1 } - while (scale_f > root*interval) { + while (scale_f > root * interval) { scale_f /= interval pow += 1 } @@ -87,7 +87,7 @@ var Intonation = (function(){ Intonation.prototype.quantize_index = function(i){ return mod(index-1, this.scale.length)|0 } - Intonation.prototype.parse_interval = function parseInterval (interval) { + var parseInterval = Intonation.prototype.parse_interval = function (s) { if (typeof s == "number") return s if (! s.indexOf("/") == -1) return parseInt(s) var pp = s.split("/") @@ -98,6 +98,11 @@ var Intonation = (function(){ if (num == den) return 1 return num / den } + var parseIntervalString = Intonation.prototype.parse_interval_string = function(s){ + if (s.indexOf("/") !== -1) return parseInterval(s) * this.opt.root // intervals + if (s.indexOf("f") !== -1) return parseFloat(s) // pure frequencies + return parseFloat(s) + } function norm(n,a,b){ return (n-a) / (b-a) } function mod(n,m){ return n-(m * Math.floor(n/m)) } |
