diff options
| -rw-r--r-- | index.html | 55 | ||||
| -rw-r--r-- | intonation.js | 51 |
2 files changed, 105 insertions, 1 deletions
@@ -11,6 +11,47 @@ pre { white-space: pre-line; } </style> + +<script type="text/scale" id="meantone-scl"> +! meanquar.scl +! +1/4-comma meantone scale. Pietro Aaron's temperament (1523) + 12 +! + 76.04900 + 193.15686 + 310.26471 + 5/4 + 503.42157 + 579.47057 + 696.57843 + 25/16 + 889.73529 + 1006.84314 + 1082.89214 + 2/1 +</script> + +<script type="text/scale" id="twelveet-scl"> +! 12et.scl +! +12 equal temperament + 12 +! + 100. + 200. + 300. + 400. + 500. + 600. + 700. + 800. + 900. + 1000. + 1100. + 1200. +</script> + <pre> <script src="intonation.js"></script> <script> @@ -47,6 +88,13 @@ 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") @@ -60,6 +108,13 @@ write("partch:") write( s.range(0, 44).map(function(i){ return i.toFixed(0) }).join(delim) ) write("") +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("") + </script> <script src="http://asdf.us/harp/js/vendor/Tone.min.js"></script> <script> diff --git a/intonation.js b/intonation.js index 509addd..8c12847 100644 --- a/intonation.js +++ b/intonation.js @@ -11,7 +11,10 @@ var Intonation = (function(){ } Intonation.prototype.generate = function(opt){ opt = Object.assign(this.opt, opt || {}) - if (opt.tet) { + if (opt.scl) { + this.generate_scl() + } + else if (opt.tet) { this.generate_tet() } else if (opt.intervals) { @@ -44,6 +47,52 @@ var Intonation = (function(){ } this.intervals = null } + Intonation.prototype.generate_scl = function(){ + var root = this.opt.root + var scl = this.parse_scl( this.opt.scl ) + this.intervals = scl.notes + this.interval = scl.notes.pop() + this.scale = scl.notes.map(function(v){ + return v * root + }) + } + Intonation.prototype.parse_scl = function(s){ + var scl = {} + scl.comments = [] + scl.notes = [] + s.trim().split("\n").forEach(function(line){ + // Lines beginning with an exclamation mark are regarded as comments + // and are to be ignored. + if ( line.indexOf("!") !== -1 ) { + scl.comments.push(line) + } + // The first (non comment) line contains a short description of the scale. + // If there is no description, there should be an empty line. (nb: which is falsey) + else if ( ! ('description' in scl) ) { + scl.description = line + } + // The second line contains the number of notes. + // The first note of 1/1 or 0.0 cents is implicit and not in the files. + else if ( ! scl.notes.length) { + scl.notes.push(1) + } + else { + // If the value contains a period, it is a cents value, otherwise a ratio. + var note = line.replace(/^[^-\.0-9]+/,"").replace(/[^-\/\.0-9]+$/,"") + if ( note.indexOf(".") !== -1 ) { + note = Math.pow( 2, (parseFloat(note) / 1200) ) + } + else { + console.log("note", line, note) + note = parseInterval(note) + } + if (note) { + scl.notes.push(note) + } + } + }) + return scl + } Intonation.prototype.index = function(i, octave){ octave = octave || this.opt.octave var f = this.scale[ mod(i, this.scale.length)|0 ] |
