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')