Artifact
57433372d1d82c07553ed7273aea1a8da43ebbf2c74e45a10b1fe04f7a7f4d88:
'use strict';
import math from '../util/math';
export default class Tune {
constructor() {
// the scale as ratios
this.scale = [];
// i/o modes
this.mode = {
output: 'frequency',
input: 'step'
};
// ET major
this.etmajor = [
261.62558,
293.664764,
329.627563,
349.228241,
391.995422,
440,
493.883301,
523.25116
];
// Root frequency.
this.root = math.mtof(60); // * Math.pow(2,(60-69)/12);
// default is a major scale
this.createScale(0, 2, 4, 5, 7, 9, 11);
}
/* Return data in the mode you are in (freq, ratio, or midi) */
note(input, octave) {
let newvalue;
if (this.mode.output === 'frequency') {
newvalue = this.frequency(input, octave);
} else if (this.mode.output === 'ratio') {
newvalue = this.ratio(input, octave);
} else if (this.mode.output === 'MIDI') {
newvalue = this.MIDI(input, octave);
} else {
newvalue = this.frequency(input, octave);
}
return newvalue;
}
/* Return freq data */
frequency(stepIn, octaveIn) {
if (this.mode.input === 'midi' || this.mode.input === 'MIDI') {
this.stepIn += 60;
}
// what octave is our input
let octave = Math.floor(stepIn / this.scale.length);
if (octaveIn) {
octave += octaveIn;
}
// which scale degree (0 - scale length) is our input
let scaleDegree = stepIn % this.scale.length;
while (scaleDegree < 0) {
scaleDegree += this.scale.length;
}
let ratio = this.scale[scaleDegree];
let freq = this.root * ratio;
freq = freq * Math.pow(2, octave);
// truncate irrational numbers
freq = Math.floor(freq * 100000000000) / 100000000000;
return freq;
}
/* Force return ratio data */
ratio(stepIn, octaveIn) {
if (this.mode.input === 'midi' || this.mode.input === 'MIDI') {
this.stepIn += 60;
}
// what octave is our input
let octave = Math.floor(stepIn / this.scale.length);
if (octaveIn) {
octave += octaveIn;
}
// which scale degree (0 - scale length) is our input
let scaleDegree = stepIn % this.scale.length;
// what ratio is our input to our key
let ratio = Math.pow(2, octave) * this.scale[scaleDegree];
ratio = Math.floor(ratio * 100000000000) / 100000000000;
return ratio;
}
/* Force return adjusted MIDI data */
MIDI(stepIn, octaveIn) {
let newvalue = this.frequency(stepIn, octaveIn);
let n = 69 + (12 * Math.log(newvalue / 440)) / Math.log(2);
n = Math.floor(n * 1000000000) / 1000000000;
return n;
}
createScale() {
let newScale = [];
for (let i = 0; i < arguments.length; i++) {
newScale.push(math.mtof(60 + arguments[i]));
}
this.loadScaleFromFrequencies(newScale);
}
createJIScale() {
this.scale = [];
for (let i = 0; i < arguments.length; i++) {
this.scale.push(arguments[i]);
}
}
loadScaleFromFrequencies(freqs) {
this.scale = [];
for (let i = 0; i < freqs.length; i++) {
this.scale.push(freqs[i] / freqs[0]);
}
}
/* Load a new scale */
loadScale(name) {
/* load the scale */
let freqs = this.scales[name].frequencies;
this.loadScaleFromFrequencies(freqs);
}
/* Search the names of tunings
Returns an array of names of tunings */
search(letters) {
let possible = [];
for (let key in this.scales) {
if (key.toLowerCase().indexOf(letters.toLowerCase()) !== -1) {
possible.push(key);
}
}
return possible;
}
/* Return a collection of notes as an array */
chord(midis) {
let output = [];
for (let i = 0; i < midis.length; i++) {
output.push(this.note(midis[i]));
}
return output;
}
}