summaryrefslogtreecommitdiff
path: root/intonation.js
diff options
context:
space:
mode:
Diffstat (limited to 'intonation.js')
-rw-r--r--intonation.js106
1 files changed, 106 insertions, 0 deletions
diff --git a/intonation.js b/intonation.js
new file mode 100644
index 0000000..4485d81
--- /dev/null
+++ b/intonation.js
@@ -0,0 +1,106 @@
+var Intonation = (function(){
+ var Intonation = function(opt){
+ opt = Object.assign({
+ root: 440,
+ octave: 0,
+ interval: 2,
+ tet: 0,
+ }, opt || {})
+ this.generate()
+ }
+ Intonation.prototype.generate = function(){
+ if (this.opt.tet) {
+ this.generate_tet()
+ }
+ else {
+ this.generate_intervals()
+ }
+ }
+ Intonation.prototype.generate_intervals = function(){
+ var root = this.opt.root
+ var interval_list = this.opt.intervals
+ 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){
+ 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 = []
+ var root = this.opt.root
+ var tet = this.opt.tet
+ var interval = this.opt.interval
+ var ratio = Math.pow( interval, 1/tet )
+ var n = root
+ scale = [n]
+ for (var i = 0; i < tet; i++) {
+ n *= ratio
+ scale.push(n)
+ }
+ }
+ Intonation.prototype.index = function(i, octave){
+ octave = octave || this.opt.octave
+ var f = this.scale[ mod(i, this.scale.length)|0 ]
+ var pow = Math.floor(norm(i, 0, this.scale.length)) + octave
+ f *= Math.pow(this.opt.interval, pow)
+ return f
+ }
+ Intonation.prototype.set_root = function(f){
+ this.opt.root = f
+ this.generate()
+ }
+ Intonation.prototype.quantize_frequency = function(f){
+ if (f == 0) return 0
+ var scale_f = f
+ var pow = 0
+ while (scale_f < root) {
+ scale_f *= interval
+ pow -= 1
+ }
+ while (scale_f > root*interval) {
+ scale_f /= interval
+ pow += 1
+ }
+ for (var i = 0; i < scale.length; i++) {
+ if (scale_f > scale[i]) continue
+ scale_f = scale[i]
+ break
+ }
+ scale_f *= Math.pow(2, pow)
+ return scale_f
+ }
+ Intonation.prototype.quantize_index = function(i){
+ return mod(index-1, this.scale.length)|0
+ }
+ Intonation.prototype.parse_interval = function parseInterval (interval) {
+ if (typeof s == "number") return s
+ if (! s.indexOf("/") == -1) return parseInt(s)
+ var pp = s.split("/")
+ var num = parseInt(pp[0])
+ var den = parseInt(pp[1])
+ if (isNaN(num)) return 1
+ if (isNaN(den) || den == 0) return num
+ if (num == den) return 1
+ return num / den
+ }
+ function norm(n,a,b){ return (n-a) / (b-a) }
+ function mod(n,m){ return n-(m * Math.floor(n/m)) }
+
+ return Intonation
+})()
+