@stringsync/vexml
Version:
MusicXML to Vexflow
108 lines (107 loc) • 5.16 kB
JavaScript
import * as util from '../../util';
import * as conversions from './conversions';
import { Measure } from './measure';
import { Signature } from './signature';
import { SystemContext } from './contexts';
import { EventCalculator } from './eventcalculator';
import { JumpGroup } from './jumpgroup';
export class System {
config;
log;
measures;
constructor(config, log, measures) {
this.config = config;
this.log = log;
this.measures = measures;
}
static create(config, log, musicXML) {
const partIds = musicXML.scorePartwise.getParts().map((part) => part.getId());
const measureCount = util.max(musicXML.scorePartwise.getParts().map((part) => part.getMeasures().length));
const measureLabels = System.getMeasureLabels(measureCount, musicXML);
const measureEvents = new EventCalculator(config, log, { scorePartwise: musicXML.scorePartwise }).calculate();
const jumpGroups = System.getJumpGroups(config, log, measureCount, musicXML);
const startBarlineStyles = System.getBarlineStyles(measureCount, 'left', musicXML, jumpGroups);
const endBarlineStyles = System.getBarlineStyles(measureCount, 'right', musicXML, jumpGroups);
const measures = new Array(measureCount);
let signature = Signature.default(config, log);
for (let measureIndex = 0; measureIndex < measureCount; measureIndex++) {
const measureLabel = measureLabels[measureIndex];
const jumpGroup = jumpGroups[measureIndex];
const startBarlineStyle = startBarlineStyles[measureIndex];
const endBarlineStyle = endBarlineStyles[measureIndex];
const measure = Measure.create(config, log, signature, measureIndex, measureLabel, measureEvents.filter((event) => event.measureIndex === measureIndex), partIds, jumpGroup, startBarlineStyle, endBarlineStyle);
measures[measureIndex] = measure;
signature = measure.getLastSignature();
}
return new System(config, log, measures);
}
static getMeasureLabels(measureCount, musicXML) {
const measureLabels = new Array(measureCount).fill(null);
const part = util.first(musicXML.scorePartwise.getParts());
if (!part) {
return measureLabels;
}
const measures = part.getMeasures();
for (let measureIndex = 0; measureIndex < measureCount; measureIndex++) {
const measure = measures[measureIndex];
if (measure.isImplicit()) {
measureLabels[measureIndex] = null;
}
const number = parseInt(measure.getNumber(), 10);
if (Number.isInteger(number) && !Number.isNaN(number)) {
measureLabels[measureIndex] = number;
}
else {
measureLabels[measureIndex] = measureIndex + 1;
}
}
return measureLabels;
}
static getJumpGroups(config, log, measureCount, musicXML) {
const jumpGroups = new Array();
for (let measureIndex = 0; measureIndex < measureCount; measureIndex++) {
const jumpGroup = JumpGroup.create(config, log, measureIndex, musicXML);
jumpGroups.push(jumpGroup);
}
return jumpGroups;
}
static getBarlineStyles(measureCount, location, musicXML, jumpGroups) {
const barlineStyles = new Array(measureCount).fill(null);
for (let measureIndex = 0; measureIndex < measureCount; measureIndex++) {
const jumpGroup = jumpGroups[measureIndex];
let jumpGroupBarlineStyle = null;
if (location === 'left') {
jumpGroupBarlineStyle = jumpGroup.getStartBarlineStyle();
}
if (location === 'right') {
jumpGroupBarlineStyle = jumpGroup.getEndBarlineStyle();
}
const barlineStyle = jumpGroupBarlineStyle ??
conversions.fromMusicXMLBarStyleToBarlineStyle(musicXML.scorePartwise
.getParts()
.flatMap((part) => part.getMeasures().at(measureIndex)?.getBarlines() ?? [])
.filter((barline) => barline.getLocation() === location)
.map((barline) => barline.getBarStyle())
.at(0));
barlineStyles[measureIndex] = barlineStyle;
}
return barlineStyles;
}
parse(scoreCtx) {
const systemCtx = new SystemContext(scoreCtx);
const parsedMeasures = new Array();
for (const measure of this.measures) {
const multiRestEvents = measure.getEvents().filter((event) => event.type === 'multirest');
for (const multiRestEvent of multiRestEvents) {
systemCtx.incrementMultiRestCount(multiRestEvent.partId, multiRestEvent.staveNumber, multiRestEvent.measureCount);
}
const parsedMeasure = measure.parse(systemCtx);
parsedMeasures.push(parsedMeasure);
systemCtx.decrementMultiRestCounts();
}
return {
type: 'system',
measures: parsedMeasures,
};
}
}