@stringsync/vexml
Version:
MusicXML to Vexflow
83 lines (82 loc) • 3.08 kB
JavaScript
import { Fraction } from '../util';
export class Note {
config;
log;
document;
noteRender;
constructor(config, log, document, noteRender) {
this.config = config;
this.log = log;
this.document = document;
this.noteRender = noteRender;
}
static create(config, log, document, noteRender) {
return new Note(config, log, document, noteRender);
}
/** The name of the element, which can be used as a type discriminant. */
name = 'note';
/** Returns the bounding box of the element. */
rect() {
return this.noteRender.rect;
}
/** Returns the subtype of the note. */
getSubtype() {
return this.noteRender.subtype;
}
/** Returns the pitches of the note. */
getPitches() {
switch (this.getSubtype()) {
case 'note':
return this.getNotePitches();
case 'chord':
return this.getChordPitches();
}
}
/** Returns whether the note contains an equivalent pitch to another note. */
containsEquivalentPitch(otherNote) {
// Let N be the number of pitches a note has. This algorithm has a time complexity of O(N^2), but N should always
// be small (<10).
return this.getPitches().some((pitch) => otherNote.getPitches().some((otherPitch) => this.isPitchEqivalent(pitch, otherPitch)));
}
/** Returns whether the note is connected to another note via a curve (tie or slur). */
sharesACurveWith(otherNote) {
return this.noteRender.curveIds.some((curveId) => otherNote.noteRender.curveIds.includes(curveId));
}
/** Returns the measure beat that this note starts on. */
getStartMeasureBeat() {
return Fraction.fromFractionLike(this.document.getVoiceEntry(this.noteRender.key).measureBeat);
}
/** Returns the number of beats that this note takes. */
getBeatCount() {
return Fraction.fromFractionLike(this.document.getVoiceEntry(this.noteRender.key).duration);
}
/** Returns the system index that this note resides in. */
getSystemIndex() {
return this.noteRender.key.systemIndex;
}
/** Returns the absolute measure index that this note resides in. */
getAbsoluteMeasureIndex() {
return this.document.getAbsoluteMeasureIndex(this.noteRender.key);
}
getNotePitches() {
const note = this.document.getNote(this.noteRender.key);
return [
{
step: note.pitch.step,
octave: note.pitch.octave,
accidentalCode: note.accidental?.code ?? null,
},
];
}
getChordPitches() {
const chord = this.document.getChord(this.noteRender.key);
return chord.notes.map((note) => ({
step: note.pitch.step,
octave: note.pitch.octave,
accidentalCode: note.accidental?.code ?? null,
}));
}
isPitchEqivalent(a, b) {
return a.step === b.step && a.octave === b.octave && a.accidentalCode === b.accidentalCode;
}
}