ed.brz9.dev/proj/chordboard/js/main.js

320 lines
8.7 KiB
JavaScript

const tau = 2*Math.PI
let vm = new Vue({
data(){
return{
canvas: null,
context: null,
ogglist: [
og00, og01, og02, og03, og04, og05,
og06, og07, og08, og09, og10, og11,
og12, og13, og14, og15, og16, og17,
og18, og19, og20, og21, og22, og23,
og24, og25, og26, og27, og28, og29,
og30, og31, og32, og33, og34, og35,
],
bwKeys: [0,1,0,1,0,0,1,0,1,0,1,0],
whiteKeyWidth: 30,
whiteKeyHeight: 100,
blackKeyWidth: 16,
blackKeyHeight: 60,
lastKey: 47,
whiteKeys: {
0:0 ,2:1,4:2,5:3,7:4,9:5,11:6,
12:7,14:8,16:9,17:10,19:11,21:12,23:13,
24:14,26:15,28:16,29:17,31:18,33:19,35:20,
36:21,38:22,40:23,41:24,43:25,45:26,47:27,
48:28,50:29,52:30,53:31,55:32,57:33,59:34
},
keyColors: [
0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0
],
rootKey: 0,
domKeyColor: '#000000',
colScale: "#25465d",
colInversion: "#ffbaba",
colChord: "#ef3932",
colKey: "#e9d2d2",
colLine: "#e9d2d2",
scale: [0,2,4,5,7,9,11],
currentChord: [],
mode: 0,
modes: [
[0,2,4,5,7,9,11], // Ionian
[0,2,3,5,7,9,10], // Dorian
[0,1,3,5,7,8,10], // Phrygian
[0,2,4,6,7,9,11], // Lydian
[0,2,4,5,7,9,10], // Mixolydian
[0,2,3,5,7,8,10], // Aeolian
[0,1,3,5,6,8,10], // Locrian
[0,2,3,6,7,9,10], // Misheberak
[0,1,4,5,7,8,10], // Freygish
[0,2,3,6,7,8,11], // Hungarian Minor
[0,3,4,6,7,9,10], // Hungarian Major
[0,1,4,5,6,8,11], // Persian
[0,2,4,6,8,10] // Whole tone
],
modesdegs: [
['I','ii','iii','IV','V','vi','vii°'], // Ionian
['i','ii','III','IV','v','vi°','VII'], // Dorian
['i','II','III','iv','v°','VI','vii'], // Phrygian
['I','II','iii','iv°','V','vi','vii'], // Lydian
['I','ii','iii°','IV','v','vi','VII'], // Mixolidian
['i','ii°','III','iv','v','VI','VII'], // Aeolian
['i°','II','iii','iv','V','VI','vii'], // Locrian
['i','II','III','iv°','v','vi°','VII⁺'], // Misheberak
['I','II','iii°','iv','v°','vi⁺','vi'], // Freygish
['i','IIb5','III⁺','iv°b3','V','VI','vii'], // Hungarian Minor
['I','ii°','iii°','iv°','II','vi°','ii'], // Hungarian Major
['Ib5','II','IIIsus2','iv','Vsus4','VI⁺','vii°b3'], // Persian
['WH','A','T','E','V','ER','↓?'], // Whole tone
],
baseNoteList: [
'C','Db','D','Eb','E','F',
'F#','G','Ab','A','Bb','B'
],
noteList: [
'C','Db','D','Eb','E','F',
'F#','G','Ab','A','Bb','B'
],
noteScale: ['C','D','E','F','G','A','B'],
flatSharpList: [
['C','C'] ,['C#','Db'],['D','D'],
['D#','Eb'],['E','E'] ,['E#','F'],
['F#','Gb'],['G','G'] ,['G#','Ab'],
['A','A'],['A#','Bb'] ,['B','Cb']
],
flatList: [
'C','Db','D',
'Eb','E','F',
'Gb','G','Ab',
'A','Bb','Cb'
],
sharpList: [
'C','C#','D',
'D#','E','E#',
'F#','G','G#',
'A','A#','B'
],
chords: {
'M': [0,4,7],
'M6': [0,4,7,9],
'M7m': [0,4,7,10],
'M7M': [0,4,7,11],
'M9': [0,4,7,10,14],
'M69': [0,4,7,9,14],
'Madd2': [0,2,4,7],
'Madd9': [0,4,7,14],
'm': [0,3,7],
'm6': [0,3,7,9],
'm7m': [0,3,7,10],
'm7M': [0,3,7,11],
'm9': [0,3,7,10,14],
'm69': [0,3,7,9,14],
'madd2': [0,2,3,7],
'madd9': [0,3,7,14],
'sus2': [0,2,7],
'sus26': [0,2,7,9],
'sus27': [0,2,7,10],
'sus27M': [0,2,7,11],
'sus4': [0,5,7],
'sus46': [0,5,7,9],
'sus47': [0,5,7,10],
'sus47M': [0,5,7,11],
'dimb3': [0,2,6],
'dim': [0,3,6],
'dim7': [0,3,6,9],
'b5': [0,4,6],
'aug': [0,4,8],
'aug7': [0,4,8,10],
'p4': [0,5],
'TT': [0,6],
'p5': [0,7],
'M7f5': [0,4,6,10],
'M7s5': [0,4,8,10]
}
}
},
methods:{
sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
},
drawKey(keyNumber) {
var keyColor = this.bwKeys[keyNumber%12]
var keyIndex
var x0, x1, xc
var circleXOffset, circleYOffset
var keyHeight
this.ctx.beginPath();
if (keyColor == 0){
keyIndex = this.whiteKeys[keyNumber.toString(10)]
x0 = this.whiteKeyWidth * keyIndex + 2
x1 = x0 + this.whiteKeyWidth - 4
keyHeight = this.whiteKeyHeight
this.ctx.fillStyle = "#d5d5d5";
circleYOffset = 85;
circleXOffset = 13;
} else {
keyIndex = this.whiteKeys[(keyNumber-1).toString(10)]
x0 = this.whiteKeyWidth * (keyIndex + 1)
x0 -= (this.blackKeyWidth / 2)
x1 = x0 + this.blackKeyWidth
xc = x1 - x0;
keyHeight = this.blackKeyHeight
this.ctx.fillStyle = "#000000";
circleYOffset = 50;
circleXOffset = 8;
}
this.ctx.moveTo(x0,0)
this.ctx.lineTo(x1,0)
this.ctx.lineTo(x1,keyHeight)
this.ctx.lineTo(x0,keyHeight)
this.ctx.closePath();
this.ctx.fill();
if (this.keyColors[keyNumber] != 0) {
switch (this.keyColors[keyNumber]){
case (1):
this.ctx.fillStyle = "#636e96";
break;
case (3):
this.ctx.fillStyle = "#f40000";
break;
}
this.ctx.beginPath();
this.ctx.arc(x0+circleXOffset, circleYOffset, 6, 0, tau);
this.ctx.fill();
}
this.ctx.save();
if (this.bwKeys[(keyNumber-1+12)%12] == 1){
this.drawKey(keyNumber-1)
}
},
drawKeyBoard() {
var key
for (key=0;key<=this.lastKey;key++){
this.drawKey(key)
}
},
drawRoot() {
this.drawKey(this.rootKey + 12)
},
updateScale(clean){
if (clean == "clean") {
this.currentChord = [];
}
var deg, key
var scaleMode = this.modes[this.mode]
rootKey = Number(this.rootKey)
for (deg=0;deg<7;deg++){
nDeg = (scaleMode[deg] + rootKey) % 12;
this.scale[deg] = nDeg;
}
this.noteList = this.baseNoteList;
if (this.scale.includes(6)){
this.noteList = this.sharpList;
}
if (this.scale.includes(10) && (rootKey != 11)){
this.noteList = this.flatList;
if (this.scale.includes(3) && this.scale.includes(4)){
this.noteList[4] = 'Fb';
}
}
for (deg=0;deg<7;deg++){
nDeg = (scaleMode[deg] + rootKey) % 12;
this.noteScale[deg] = this.noteList[nDeg];
}
for (key=0;key<=this.lastKey;key++){
if (this.currentChord.includes(key-12)){
this.keyColors[key] = 3
} else if (this.scale.includes(key%12)){
this.keyColors[key] = 1
} else {
this.keyColors[key] = 0
}
}
this.drawKeyBoard();
vm.$forceUpdate();
},
playChord(root, chString){
notes = this.chords[chString];
c = notes.map(n => n + root);
this.currentChord = c;
for (n in c) {
this.ogglist[c[n]].currentTime = 0;
this.ogglist[c[n]].play()
}
this.updateScale();
},
getGoodNote(note) {
return this.noteList[note]
},
spicelvl(root, chString){
notes = this.chords[chString];
c = notes.map(n => n + root);
sl = 0;
for (n in c) {
if (!(this.scale.includes(c[n]%12))){
sl = sl + 1;
}
}
return sl;
},
spice2Color(root, chString) {
sl = this.spicelvl(root, chString);
if (sl == 0) {
color = "#ef3932";
} else {
color = "";
}
return color;
},
playScale() {
doSomething = async () => {
upBreak = false;
for (n in this.scale){
await this.sleep(200);
note = this.scale[n];
if (n > 0) {
if ((note < this.scale[n-1]) || upBreak ) {
upBreak = true;
note = note + 12;
}
}
this.ogglist[note].play();
}
await this.sleep(200);
this.ogglist[this.scale[0] + 12].play();
}
doSomething();
}
},
mounted: function() {
var vm = this
vm.canvas = vm.$refs.canvas
vm.ctx = vm.canvas.getContext("2d");
vm.ctx.lineWidth = 0;
this.drawKeyBoard();
this.updateScale();
},
}).$mount('#app')