abcjs
Version:
Renderer for abc music notation
216 lines (200 loc) • 5.43 kB
JavaScript
var {noteToMidi, midiToNote} = require('../../synth/note-to-midi');
/**
*
* Note structure for Tabs
*
*/
var notes = ['A', 'B', 'C', 'D', 'E', 'F', 'G'];
function TabNote(note, clefTranspose) {
var pitch = noteToMidi(note)
if (clefTranspose)
pitch += clefTranspose
var newNote = midiToNote(pitch);
var isFlat = false;
var isSharp = false;
var isAltered = false;
var natural = null;
var quarter = null;
var isDouble = false;
var acc = 0;
if (note.startsWith('_')) {
isFlat = true;
acc = -1;
// check quarter flat
if (note[1] == '/') {
isFlat = false;
quarter = "v";
acc = 0;
} else if (note[1] == '_') {
// double flat
isDouble = true;
acc -= 1;
}
} else if (note.startsWith('^')) {
isSharp = true;
acc = +1;
// check quarter sharp
if (note[1] == '/') {
isSharp = false;
quarter = "^";
acc = 0;
} else if (note[1] == '^') {
// double sharp
isDouble = true;
acc += 1;
}
} else if (note.startsWith('=')) {
natural = true;
acc = 0;
}
isAltered = isFlat || isSharp || (quarter != null);
if (isAltered || natural) {
if ((quarter != null) || (isDouble)) {
newNote = note.slice(2);
} else {
newNote = note.slice(1);
}
}
var hasComma = (newNote.match(/,/g) || []).length;
var hasQuote = (newNote.match(/'/g) || []).length;
this.pitch = pitch
this.pitchAltered = 0
this.name = newNote;
this.acc = acc;
this.isSharp = isSharp;
this.isKeySharp = false;
this.isDouble = isDouble;
this.isAltered = isAltered;
this.isFlat = isFlat;
this.isKeyFlat = false;
this.natural = natural;
this.quarter = quarter;
this.isLower = (this.name == this.name.toLowerCase());
this.name = this.name[0].toUpperCase();
this.hasComma = hasComma;
this.isQuoted = hasQuote;
}
function cloneNote(self) {
var newNote = self.name;
var newTabNote = new TabNote(newNote);
newTabNote.pitch = self.pitch;
newTabNote.hasComma = self.hasComma;
newTabNote.isLower = self.isLower;
newTabNote.isQuoted = self.isQuoted;
newTabNote.isSharp = self.isSharp;
newTabNote.isKeySharp = self.isKeySharp;
newTabNote.isFlat = self.isFlat;
newTabNote.isKeyFlat = self.isKeyFlat;
return newTabNote;
}
TabNote.prototype.sameNoteAs = function (note) {
return note.pitch === this.pitch
};
TabNote.prototype.isLowerThan = function (note) {
return note.pitch > this.pitch
};
TabNote.prototype.checkKeyAccidentals = function(accidentals, measureAccidentals) {
if (this.isAltered || this.natural)
return
if (measureAccidentals[this.name.toUpperCase()]) {
switch (measureAccidentals[this.name.toUpperCase()]) {
case "__": this.acc = -2; this.pitchAltered = -2; return;
case "_": this.acc = -1; this.pitchAltered = -1; return;
case "=": this.acc = 0; this.pitchAltered = 0; return;
case "^": this.acc = 1; this.pitchAltered = 1; return;
case "^^": this.acc = 2; this.pitchAltered = 2; return;
}
} else if (accidentals) {
var curNote = this.name;
for (var iii = 0; iii < accidentals.length; iii++) {
var curAccidentals = accidentals[iii];
if (curNote == curAccidentals.note.toUpperCase()) {
if (curAccidentals.acc == 'flat') {
this.acc = -1;
this.isKeyFlat = true;
this.pitchAltered = -1
}
if (curAccidentals.acc == 'sharp') {
this.acc = +1;
this.isKeySharp = true;
this.pitchAltered = 1
}
}
}
}
};
TabNote.prototype.getAccidentalEquiv = function () {
var cloned = cloneNote(this);
if (cloned.isSharp || cloned.isKeySharp ) {
cloned = cloned.nextNote();
cloned.isFlat = true;
cloned.isSharp = false;
cloned.isKeySharp = false;
} else if (cloned.isFlat || cloned.isKeyFlat ) {
cloned = cloned.prevNote();
cloned.isSharp = true;
cloned.isFlat = false;
cloned.isKeyFlat = false;
}
return cloned;
};
TabNote.prototype.nextNote = function () {
var note = midiToNote(this.pitch+1+this.pitchAltered)
return new TabNote(note)
};
TabNote.prototype.prevNote = function () {
var note = midiToNote(this.pitch-1+this.pitchAltered)
return new TabNote(note)
};
TabNote.prototype.emitNoAccidentals = function ( ) {
var returned = this.name;
if (this.isLower) {
returned = returned.toLowerCase();
}
for (var ii = 0; ii < this.isQuoted; ii++) {
returned += "'";
}
for (var jj = 0; jj < this.hasComma; jj++) {
returned += ",";
}
return returned;
};
TabNote.prototype.emit = function () {
var returned = this.name;
if (this.isSharp || this.isKeySharp ) {
returned = '^' + returned;
if (this.isDouble) {
returned = '^' + returned;
}
}
if (this.isFlat || this.isKeyFlat) {
returned = '_' + returned;
if (this.isDouble) {
returned = '_' + returned;
}
}
if (this.quarter) {
if (this.quarter == "^") {
returned = "^/" + returned;
} else {
returned = "_/" + returned;
}
}
if (this.natural) {
returned = '=' + returned;
}
for (var ii = 1; ii <= this.hasComma; ii++) {
returned += ',';
}
if (this.isLower) {
returned = returned.toLowerCase();
for (var jj = 1; jj <= this.isQuoted; jj++) {
returned += "'";
}
}
return returned;
};
module.exports = {
'TabNote': TabNote,
'notes': notes
};