UNPKG

@stringsync/vexml

Version:

MusicXML to Vexflow

96 lines (95 loc) 3.17 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Metronome = void 0; const enums_1 = require("./enums"); /** * Represents metronome marks and other metric relationships. * * Only supports simple meters in the form of [beat-unit symbol] = [bpm]. * * See https://www.w3.org/2021/06/musicxml40/musicxml-reference/elements/metronome/. */ class Metronome { element; constructor(element) { this.element = element; } /** Returns whether the metronome mark is in parentheses. */ parentheses() { return this.element.attr('parentheses').withDefault('no').str() === 'yes'; } /** Returns the metronome mark details. Defaults to a quarter note = 120 bpm. */ getMark() { const leftElements = new Array(); const rightElements = new Array(); for (const child of this.element.children()) { const hasLeftElements = leftElements.length > 0; const hasRightElements = rightElements.length > 0; if (child.isNamed('beat-unit')) { if (hasLeftElements) { rightElements.push(child); } else { leftElements.push(child); } } if (child.isNamed('beat-unit-dot')) { if (hasRightElements) { rightElements.push(child); } else { leftElements.push(child); } } if (child.isNamed('per-minute')) { rightElements.push(child); } } if (!this.isWellFormedNote(leftElements)) { return null; } const rightOperandType = this.isWellFormedNote(rightElements) ? 'note' : this.isWellFormedBpm(rightElements) ? 'bpm' : 'invalid'; if (rightOperandType === 'invalid') { return null; } return { left: this.noteOperand(leftElements), right: rightOperandType === 'note' ? this.noteOperand(rightElements) : this.bpmOperand(rightElements), }; } noteOperand(elements) { const unit = elements[0].content().enum(enums_1.NOTE_TYPES) ?? 'quarter'; const dotCount = elements.slice(1).filter((child) => child.isNamed('beat-unit-dot')).length; return { type: 'note', unit, dotCount }; } bpmOperand(elements) { const bpm = elements[0].content().int() ?? 120; return { type: 'bpm', bpm }; } isWellFormedNote(elements) { if (elements.length === 0) { return false; } if (!elements[0].isNamed('beat-unit')) { return false; } if (elements.slice(1).some((child) => !child.isNamed('beat-unit-dot'))) { return false; } return true; } isWellFormedBpm(elements) { if (elements.length > 1) { return false; } if (!elements[0].isNamed('per-minute')) { return false; } return true; } } exports.Metronome = Metronome;