@viritura/score-engine 0.1.1-next.25 → 0.1.1-next.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +386 -134
- package/dist/index.js.map +4 -4
- package/dist/wasm/viritura_wasm_bg.wasm +0 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -582,6 +582,230 @@ function parseChordSymbolText(input, position) {
|
|
|
582
582
|
return (!parsedQuality || parsedQuality.modifiers) && (chord.kindText = match[4]), parsedQuality?.extension !== void 0 && (chord.extension = parsedQuality.extension), match[5] && (chord.bass = parseRoot(match[5], match[6] ?? "")), chord;
|
|
583
583
|
}
|
|
584
584
|
|
|
585
|
+
// packages/core/src/operations/lyricExtenders.ts
|
|
586
|
+
init_define_import_meta_env();
|
|
587
|
+
function durationBeats(duration) {
|
|
588
|
+
let base = DURATION_BEATS[duration.base], dots = 1;
|
|
589
|
+
for (let index = 0; index < (duration.dots ?? 0); index++) dots += 0.5 ** (index + 1);
|
|
590
|
+
return base * dots;
|
|
591
|
+
}
|
|
592
|
+
function quantityBeats(quantity) {
|
|
593
|
+
return durationBeats(quantity.duration) * quantity.multiple;
|
|
594
|
+
}
|
|
595
|
+
function walkTimedContent(content, startBeat, scale, partIndex, sequenceIndex, voice, staff, measureIndex, output, ordinal) {
|
|
596
|
+
let cursor = startBeat;
|
|
597
|
+
for (let item of content) {
|
|
598
|
+
if (item.type === "event") {
|
|
599
|
+
let duration = durationBeats(item.duration) * scale;
|
|
600
|
+
output.push({
|
|
601
|
+
event: item,
|
|
602
|
+
partIndex,
|
|
603
|
+
sequenceIndex,
|
|
604
|
+
voice,
|
|
605
|
+
staff,
|
|
606
|
+
measureIndex,
|
|
607
|
+
startBeat: cursor,
|
|
608
|
+
durationBeats: duration,
|
|
609
|
+
rest: isRest(item),
|
|
610
|
+
ordinal: ordinal.value++
|
|
611
|
+
}), cursor += duration;
|
|
612
|
+
continue;
|
|
613
|
+
}
|
|
614
|
+
if (item.type === "space") {
|
|
615
|
+
cursor += 4 * item.duration[0] / item.duration[1] * scale;
|
|
616
|
+
continue;
|
|
617
|
+
}
|
|
618
|
+
if (item.type === "grace") {
|
|
619
|
+
for (let event of item.content)
|
|
620
|
+
output.push({
|
|
621
|
+
event,
|
|
622
|
+
partIndex,
|
|
623
|
+
sequenceIndex,
|
|
624
|
+
voice,
|
|
625
|
+
staff,
|
|
626
|
+
measureIndex,
|
|
627
|
+
startBeat: cursor,
|
|
628
|
+
durationBeats: 0,
|
|
629
|
+
rest: isRest(event),
|
|
630
|
+
ordinal: ordinal.value++
|
|
631
|
+
});
|
|
632
|
+
continue;
|
|
633
|
+
}
|
|
634
|
+
if (item.type === "tuplet") {
|
|
635
|
+
let inner = quantityBeats(item.inner), ratio = inner > 0 ? quantityBeats(item.outer) / inner : 1;
|
|
636
|
+
cursor = walkTimedContent(
|
|
637
|
+
item.content,
|
|
638
|
+
cursor,
|
|
639
|
+
scale * ratio,
|
|
640
|
+
partIndex,
|
|
641
|
+
sequenceIndex,
|
|
642
|
+
voice,
|
|
643
|
+
staff,
|
|
644
|
+
measureIndex,
|
|
645
|
+
output,
|
|
646
|
+
ordinal
|
|
647
|
+
);
|
|
648
|
+
continue;
|
|
649
|
+
}
|
|
650
|
+
let subdivision = item.content.length ? quantityBeats(item.outer) * scale / item.content.length : 0;
|
|
651
|
+
for (let event of item.content)
|
|
652
|
+
output.push({
|
|
653
|
+
event,
|
|
654
|
+
partIndex,
|
|
655
|
+
sequenceIndex,
|
|
656
|
+
voice,
|
|
657
|
+
staff,
|
|
658
|
+
measureIndex,
|
|
659
|
+
startBeat: cursor,
|
|
660
|
+
durationBeats: subdivision,
|
|
661
|
+
rest: isRest(event),
|
|
662
|
+
ordinal: ordinal.value++
|
|
663
|
+
}), cursor += subdivision;
|
|
664
|
+
}
|
|
665
|
+
return cursor;
|
|
666
|
+
}
|
|
667
|
+
function collectEvents(score) {
|
|
668
|
+
let offsets = [], measureOffset = 0, measureCount = Math.max(score.global.measures.length, ...score.parts.map((part) => part.measures.length)), activeMeter = { count: 4, unit: 4 }, meters = [];
|
|
669
|
+
for (let index = 0; index < measureCount; index++) {
|
|
670
|
+
let measure = score.global.measures[index];
|
|
671
|
+
measure?.time && (activeMeter = measure.time), meters.push(activeMeter), offsets.push(measureOffset), measureOffset += measureBeats(activeMeter);
|
|
672
|
+
}
|
|
673
|
+
let events = [], writtenSpans = Array(measureCount).fill(0), ordinal = { value: 0 };
|
|
674
|
+
for (let partIndex = 0; partIndex < score.parts.length; partIndex++) {
|
|
675
|
+
let part = score.parts[partIndex], { table } = resolveStaffMeterTimeline(
|
|
676
|
+
part.measures.map((measure) => measure.staffMeters),
|
|
677
|
+
meters
|
|
678
|
+
);
|
|
679
|
+
for (let measureIndex = 0; measureIndex < part.measures.length; measureIndex++) {
|
|
680
|
+
let measure = part.measures[measureIndex], start = offsets[measureIndex] ?? measureIndex * 4;
|
|
681
|
+
measure.sequences.forEach((sequence, sequenceIndex) => {
|
|
682
|
+
if (sequence.fullMeasure) {
|
|
683
|
+
events.push({
|
|
684
|
+
event: { type: "event", duration: sequence.fullMeasure.visualDuration, rest: {} },
|
|
685
|
+
partIndex,
|
|
686
|
+
sequenceIndex,
|
|
687
|
+
voice: sequence.voice,
|
|
688
|
+
staff: sequence.staff ?? 1,
|
|
689
|
+
measureIndex,
|
|
690
|
+
startBeat: start,
|
|
691
|
+
durationBeats: measureBeats(meters[measureIndex]),
|
|
692
|
+
rest: !0,
|
|
693
|
+
ordinal: ordinal.value++
|
|
694
|
+
});
|
|
695
|
+
return;
|
|
696
|
+
}
|
|
697
|
+
let end = walkTimedContent(
|
|
698
|
+
sequence.content,
|
|
699
|
+
start,
|
|
700
|
+
table[measureIndex]?.get(sequence.staff ?? 1) ? ratioToNumber(table[measureIndex].get(sequence.staff ?? 1).ratioToGlobal) : 1,
|
|
701
|
+
partIndex,
|
|
702
|
+
sequenceIndex,
|
|
703
|
+
sequence.voice,
|
|
704
|
+
sequence.staff ?? 1,
|
|
705
|
+
measureIndex,
|
|
706
|
+
events,
|
|
707
|
+
ordinal
|
|
708
|
+
);
|
|
709
|
+
sequence.fullMeasure || (writtenSpans[measureIndex] = Math.max(writtenSpans[measureIndex], end - start));
|
|
710
|
+
});
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
let correction = 0, corrections = [];
|
|
714
|
+
for (let index = 0; index < measureCount; index++) {
|
|
715
|
+
let nominal = measureBeats(meters[index]), measure = score.global.measures[index], written = writtenSpans[index];
|
|
716
|
+
corrections.push(correction), index === 0 && measure?.number === 0 && written > 0 ? correction += written - nominal : measure?.time?.display === "senzaMisura" && (correction += Math.max(nominal, written) - nominal);
|
|
717
|
+
}
|
|
718
|
+
for (let event of events) event.startBeat += corrections[event.measureIndex];
|
|
719
|
+
return events;
|
|
720
|
+
}
|
|
721
|
+
function hasLyrics(event, lineId) {
|
|
722
|
+
return event.event.lyrics?.lines?.[lineId] !== void 0;
|
|
723
|
+
}
|
|
724
|
+
function isEligibleSyllable(line) {
|
|
725
|
+
return line.type !== "start" && line.type !== "middle";
|
|
726
|
+
}
|
|
727
|
+
function sameLyricVoice(source, candidate) {
|
|
728
|
+
return source.partIndex === candidate.partIndex && source.staff === candidate.staff && (source.voice !== void 0 ? source.voice === candidate.voice : candidate.voice === void 0 && source.sequenceIndex === candidate.sequenceIndex);
|
|
729
|
+
}
|
|
730
|
+
function inferredTarget(source, lineId, events) {
|
|
731
|
+
let continuation = events.filter((event) => sameLyricVoice(source, event) && event.ordinal > source.ordinal).sort((left, right) => left.ordinal - right.ordinal), target;
|
|
732
|
+
for (let event of continuation) {
|
|
733
|
+
if (hasLyrics(event, lineId) || event.rest) break;
|
|
734
|
+
target = event;
|
|
735
|
+
}
|
|
736
|
+
return target;
|
|
737
|
+
}
|
|
738
|
+
function crossesLaterSyllable(source, target, lineId, events) {
|
|
739
|
+
return events.some(
|
|
740
|
+
(candidate) => sameLyricVoice(source, candidate) && candidate.ordinal > source.ordinal && candidate.startBeat <= target.startBeat + 1e-9 && candidate.ordinal !== target.ordinal && hasLyrics(candidate, lineId)
|
|
741
|
+
);
|
|
742
|
+
}
|
|
743
|
+
function resolveLyricExtenders(score) {
|
|
744
|
+
let events = collectEvents(score), byId = /* @__PURE__ */ new Map();
|
|
745
|
+
for (let event of events)
|
|
746
|
+
event.event.id && !byId.has(event.event.id) && byId.set(event.event.id, event);
|
|
747
|
+
let extenders = [], diagnostics = [], explicitPolicy = score.mnx.support?.useLyricExtenders === !0;
|
|
748
|
+
for (let source of events)
|
|
749
|
+
for (let [lineId, line] of Object.entries(source.event.lyrics?.lines ?? {})) {
|
|
750
|
+
let explicit = line.extender !== void 0;
|
|
751
|
+
if (line.extender?.show === !1 || !explicit && explicitPolicy || !explicit && !isEligibleSyllable(line))
|
|
752
|
+
continue;
|
|
753
|
+
let target;
|
|
754
|
+
if (line.extender?.target !== void 0) {
|
|
755
|
+
if (target = byId.get(line.extender.target), !target) {
|
|
756
|
+
diagnostics.push({
|
|
757
|
+
code: "missing-target",
|
|
758
|
+
sourceEventId: source.event.id,
|
|
759
|
+
lineId,
|
|
760
|
+
targetEventId: line.extender.target,
|
|
761
|
+
partIndex: source.partIndex,
|
|
762
|
+
measureIndex: source.measureIndex,
|
|
763
|
+
sequenceIndex: source.sequenceIndex
|
|
764
|
+
});
|
|
765
|
+
continue;
|
|
766
|
+
}
|
|
767
|
+
if (target.startBeat < source.startBeat - 1e-9) {
|
|
768
|
+
diagnostics.push({
|
|
769
|
+
code: "backward-target",
|
|
770
|
+
sourceEventId: source.event.id,
|
|
771
|
+
lineId,
|
|
772
|
+
targetEventId: line.extender.target,
|
|
773
|
+
partIndex: source.partIndex,
|
|
774
|
+
measureIndex: source.measureIndex,
|
|
775
|
+
sequenceIndex: source.sequenceIndex
|
|
776
|
+
});
|
|
777
|
+
continue;
|
|
778
|
+
}
|
|
779
|
+
if (target.ordinal !== source.ordinal && hasLyrics(target, lineId) || crossesLaterSyllable(source, target, lineId, events)) {
|
|
780
|
+
diagnostics.push({
|
|
781
|
+
code: "conflicting-target",
|
|
782
|
+
sourceEventId: source.event.id,
|
|
783
|
+
lineId,
|
|
784
|
+
targetEventId: line.extender.target,
|
|
785
|
+
partIndex: source.partIndex,
|
|
786
|
+
measureIndex: source.measureIndex,
|
|
787
|
+
sequenceIndex: source.sequenceIndex
|
|
788
|
+
});
|
|
789
|
+
continue;
|
|
790
|
+
}
|
|
791
|
+
} else
|
|
792
|
+
target = inferredTarget(source, lineId, events);
|
|
793
|
+
target && extenders.push({
|
|
794
|
+
sourceEventId: source.event.id,
|
|
795
|
+
targetEventId: target.event.id,
|
|
796
|
+
partIndex: source.partIndex,
|
|
797
|
+
sequenceIndex: source.sequenceIndex,
|
|
798
|
+
lineId,
|
|
799
|
+
startMeasure: source.measureIndex,
|
|
800
|
+
endMeasure: target.measureIndex,
|
|
801
|
+
startBeat: source.startBeat,
|
|
802
|
+
endBeat: target.startBeat + target.durationBeats,
|
|
803
|
+
explicit
|
|
804
|
+
});
|
|
805
|
+
}
|
|
806
|
+
return { extenders, diagnostics };
|
|
807
|
+
}
|
|
808
|
+
|
|
585
809
|
// packages/core/src/diagnostics.ts
|
|
586
810
|
init_define_import_meta_env();
|
|
587
811
|
var DiagnosticCollector = class {
|
|
@@ -1989,9 +2213,9 @@ function interpolateBeatAnchors(bounds, beat, endX) {
|
|
|
1989
2213
|
|
|
1990
2214
|
// packages/score-engine/src/buildInfo.ts
|
|
1991
2215
|
init_define_import_meta_env();
|
|
1992
|
-
var PACKAGE_VERSION = "0.1.1-next.
|
|
2216
|
+
var PACKAGE_VERSION = "0.1.1-next.28", BUNDLE_WORKER_FILE = "score-engine.worker.js";
|
|
1993
2217
|
function buildCommit() {
|
|
1994
|
-
return "
|
|
2218
|
+
return "29a9ddc177a7341276fc760a1004f0dd17bfcbb2";
|
|
1995
2219
|
}
|
|
1996
2220
|
function bundledAssetBase() {
|
|
1997
2221
|
let moduleUrl = import.meta.url;
|
|
@@ -15105,7 +15329,7 @@ function parseLyrics(raw) {
|
|
|
15105
15329
|
let linesObj = raw.lines, lines = {};
|
|
15106
15330
|
for (let key of Object.keys(linesObj)) {
|
|
15107
15331
|
let lineRaw = linesObj[key], line = { text: lineRaw.text };
|
|
15108
|
-
lineRaw.type !== void 0 && (line.type = lineRaw.type), lines[key] = line;
|
|
15332
|
+
lineRaw.type !== void 0 && (line.type = lineRaw.type), lineRaw.extender !== void 0 && (line.extender = lineRaw.extender), lines[key] = line;
|
|
15109
15333
|
}
|
|
15110
15334
|
lyrics.lines = lines;
|
|
15111
15335
|
}
|
|
@@ -15471,6 +15695,127 @@ function parseSystemDefinition(raw) {
|
|
|
15471
15695
|
// packages/format/src/mnx/diagnostics.ts
|
|
15472
15696
|
init_define_import_meta_env();
|
|
15473
15697
|
|
|
15698
|
+
// packages/format/src/mnx/knownFields.ts
|
|
15699
|
+
init_define_import_meta_env();
|
|
15700
|
+
var KEYS = {
|
|
15701
|
+
root: /* @__PURE__ */ new Set(["mnx", "global", "parts", "layouts", "scores", "_x"]),
|
|
15702
|
+
mnxMeta: /* @__PURE__ */ new Set(["version", "support"]),
|
|
15703
|
+
support: /* @__PURE__ */ new Set(["useAccidentalDisplay", "useBeams", "useLyricExtenders"]),
|
|
15704
|
+
global: /* @__PURE__ */ new Set(["measures", "lyrics"]),
|
|
15705
|
+
globalLyrics: /* @__PURE__ */ new Set(["lineMetadata", "lineOrder"]),
|
|
15706
|
+
globalMeasure: /* @__PURE__ */ new Set([
|
|
15707
|
+
"id",
|
|
15708
|
+
"number",
|
|
15709
|
+
"time",
|
|
15710
|
+
"key",
|
|
15711
|
+
"barline",
|
|
15712
|
+
"repeatStart",
|
|
15713
|
+
"repeatEnd",
|
|
15714
|
+
"ending",
|
|
15715
|
+
"tempos",
|
|
15716
|
+
"segno",
|
|
15717
|
+
"fine",
|
|
15718
|
+
"jump",
|
|
15719
|
+
"_x"
|
|
15720
|
+
]),
|
|
15721
|
+
time: /* @__PURE__ */ new Set(["count", "unit", "display", "_x"]),
|
|
15722
|
+
key: /* @__PURE__ */ new Set(["fifths", "color", "_x"]),
|
|
15723
|
+
barline: /* @__PURE__ */ new Set(["type"]),
|
|
15724
|
+
ending: /* @__PURE__ */ new Set(["duration", "numbers", "open", "color"]),
|
|
15725
|
+
tempo: /* @__PURE__ */ new Set(["bpm", "value", "location", "_x"]),
|
|
15726
|
+
tempoNoteValue: /* @__PURE__ */ new Set(["base", "dots"]),
|
|
15727
|
+
rhythmicPosition: /* @__PURE__ */ new Set(["fraction"]),
|
|
15728
|
+
segno: /* @__PURE__ */ new Set(["location", "glyph", "color"]),
|
|
15729
|
+
fine: /* @__PURE__ */ new Set(["location", "color"]),
|
|
15730
|
+
jump: /* @__PURE__ */ new Set(["type", "location"]),
|
|
15731
|
+
part: /* @__PURE__ */ new Set(["id", "name", "shortName", "staves", "transposition", "measures", "_x"]),
|
|
15732
|
+
transposition: /* @__PURE__ */ new Set(["interval", "keyFifthsFlipAt", "prefersWrittenPitches"]),
|
|
15733
|
+
partMeasure: /* @__PURE__ */ new Set([
|
|
15734
|
+
"sequences",
|
|
15735
|
+
"clefs",
|
|
15736
|
+
"staffConfigs",
|
|
15737
|
+
"arpeggios",
|
|
15738
|
+
"nonArpeggios",
|
|
15739
|
+
"beams",
|
|
15740
|
+
"dynamics",
|
|
15741
|
+
"ottavas",
|
|
15742
|
+
"measureRepeat",
|
|
15743
|
+
"_x"
|
|
15744
|
+
]),
|
|
15745
|
+
positionedStaffConfig: /* @__PURE__ */ new Set(["config", "position", "staff", "id", "_c", "_x"]),
|
|
15746
|
+
staffConfig: /* @__PURE__ */ new Set(["lines", "id", "_c", "_x"]),
|
|
15747
|
+
measureRepeat: /* @__PURE__ */ new Set(["number", "counter", "displayNumber", "staffPosition", "_c", "_x"]),
|
|
15748
|
+
measureRepeatCounter: /* @__PURE__ */ new Set(["count", "placement", "_c", "_x"]),
|
|
15749
|
+
arpeggio: /* @__PURE__ */ new Set(["id", "position", "span", "direction", "arrow", "_c", "_x"]),
|
|
15750
|
+
nonArpeggio: /* @__PURE__ */ new Set(["id", "position", "span", "_c", "_x"]),
|
|
15751
|
+
idPair: /* @__PURE__ */ new Set(["start", "end"]),
|
|
15752
|
+
positionedClef: /* @__PURE__ */ new Set(["clef", "position", "staff"]),
|
|
15753
|
+
clef: /* @__PURE__ */ new Set(["sign", "staffPosition", "color", "glyph", "octave", "showOctave", "hide"]),
|
|
15754
|
+
beam: /* @__PURE__ */ new Set(["events", "beams", "direction"]),
|
|
15755
|
+
dynamic: /* @__PURE__ */ new Set(["position", "value", "glyph", "staff", "voice"]),
|
|
15756
|
+
ottava: /* @__PURE__ */ new Set(["position", "end", "value", "staff", "voice"]),
|
|
15757
|
+
measureRhythmicPosition: /* @__PURE__ */ new Set(["measure", "position"]),
|
|
15758
|
+
sequence: /* @__PURE__ */ new Set(["content", "fullMeasure", "staff", "voice", "directionHint"]),
|
|
15759
|
+
fullMeasure: /* @__PURE__ */ new Set(["visualDuration", "staffPosition"]),
|
|
15760
|
+
duration: /* @__PURE__ */ new Set(["base", "dots"]),
|
|
15761
|
+
event: /* @__PURE__ */ new Set([
|
|
15762
|
+
"type",
|
|
15763
|
+
"id",
|
|
15764
|
+
"duration",
|
|
15765
|
+
"staff",
|
|
15766
|
+
"rest",
|
|
15767
|
+
"notes",
|
|
15768
|
+
"slurs",
|
|
15769
|
+
"markings",
|
|
15770
|
+
"fermata",
|
|
15771
|
+
"lyrics",
|
|
15772
|
+
"stemDirection",
|
|
15773
|
+
"smufl",
|
|
15774
|
+
"_x"
|
|
15775
|
+
]),
|
|
15776
|
+
eventLyrics: /* @__PURE__ */ new Set(["lines"]),
|
|
15777
|
+
eventLyricLine: /* @__PURE__ */ new Set(["type", "text", "extender"]),
|
|
15778
|
+
eventLyricLineExtender: /* @__PURE__ */ new Set(["show", "target", "id"]),
|
|
15779
|
+
rest: /* @__PURE__ */ new Set(["staffPosition"]),
|
|
15780
|
+
note: /* @__PURE__ */ new Set(["pitch", "id", "ties", "accidentalDisplay", "written"]),
|
|
15781
|
+
pitch: /* @__PURE__ */ new Set(["step", "octave", "alter"]),
|
|
15782
|
+
tie: /* @__PURE__ */ new Set(["target", "targetType", "side", "lv"]),
|
|
15783
|
+
accidentalDisplay: /* @__PURE__ */ new Set(["show", "force", "enclosure"]),
|
|
15784
|
+
accidentalEnclosure: /* @__PURE__ */ new Set(["symbol"]),
|
|
15785
|
+
written: /* @__PURE__ */ new Set(["diatonicDelta"]),
|
|
15786
|
+
slur: /* @__PURE__ */ new Set(["target", "side", "sideEnd", "lineType", "startNote", "endNote"]),
|
|
15787
|
+
markings: /* @__PURE__ */ new Set([
|
|
15788
|
+
"staccato",
|
|
15789
|
+
"staccatissimo",
|
|
15790
|
+
"spiccato",
|
|
15791
|
+
"staccatissimoWedge",
|
|
15792
|
+
"tenuto",
|
|
15793
|
+
"accent",
|
|
15794
|
+
"strongAccent",
|
|
15795
|
+
"tremolo",
|
|
15796
|
+
"softAccent",
|
|
15797
|
+
"stress",
|
|
15798
|
+
"unstress",
|
|
15799
|
+
"breath",
|
|
15800
|
+
"bowDirection",
|
|
15801
|
+
"_x"
|
|
15802
|
+
]),
|
|
15803
|
+
tuplet: /* @__PURE__ */ new Set(["type", "inner", "outer", "content", "bracket", "showNumber", "showValue", "placement"]),
|
|
15804
|
+
tupletDuration: /* @__PURE__ */ new Set(["duration", "multiple"]),
|
|
15805
|
+
grace: /* @__PURE__ */ new Set(["type", "content", "graceType", "slash", "color"]),
|
|
15806
|
+
multiTremolo: /* @__PURE__ */ new Set(["type", "content", "marks", "outer"]),
|
|
15807
|
+
space: /* @__PURE__ */ new Set(["type", "duration"]),
|
|
15808
|
+
layoutDefinition: /* @__PURE__ */ new Set(["id", "content"]),
|
|
15809
|
+
layoutGroup: /* @__PURE__ */ new Set(["type", "content", "symbol", "label", "barlineStyle"]),
|
|
15810
|
+
layoutStaff: /* @__PURE__ */ new Set(["type", "sources", "label", "labelref"]),
|
|
15811
|
+
layoutSource: /* @__PURE__ */ new Set(["part", "staff", "stem", "voice", "labelref"]),
|
|
15812
|
+
scoreDefinition: /* @__PURE__ */ new Set(["name", "layout", "multimeasureRests", "pages", "useWritten", "_x"]),
|
|
15813
|
+
multimeasureRest: /* @__PURE__ */ new Set(["start", "duration"]),
|
|
15814
|
+
page: /* @__PURE__ */ new Set(["systems"]),
|
|
15815
|
+
system: /* @__PURE__ */ new Set(["measure", "layout", "layoutChanges"]),
|
|
15816
|
+
layoutChange: /* @__PURE__ */ new Set(["layout", "location"])
|
|
15817
|
+
};
|
|
15818
|
+
|
|
15474
15819
|
// packages/format/src/mnx/parserCore.ts
|
|
15475
15820
|
function parseMnxUnvalidated(json) {
|
|
15476
15821
|
return parseMnxInternal(json, new DiagnosticCollector());
|
|
@@ -15478,7 +15823,7 @@ function parseMnxUnvalidated(json) {
|
|
|
15478
15823
|
function parseSupport(supportObj) {
|
|
15479
15824
|
if (!supportObj) return;
|
|
15480
15825
|
let support = {};
|
|
15481
|
-
return typeof supportObj.useAccidentalDisplay == "boolean" && (support.useAccidentalDisplay = supportObj.useAccidentalDisplay), typeof supportObj.useBeams == "boolean" && (support.useBeams = supportObj.useBeams), support;
|
|
15826
|
+
return typeof supportObj.useAccidentalDisplay == "boolean" && (support.useAccidentalDisplay = supportObj.useAccidentalDisplay), typeof supportObj.useBeams == "boolean" && (support.useBeams = supportObj.useBeams), typeof supportObj.useLyricExtenders == "boolean" && (support.useLyricExtenders = supportObj.useLyricExtenders), support;
|
|
15482
15827
|
}
|
|
15483
15828
|
function parseRootMetadata(rootX) {
|
|
15484
15829
|
let m = rootX?.viritura?.metadata;
|
|
@@ -15646,7 +15991,16 @@ function parseMnxInternal(json, diagnostics) {
|
|
|
15646
15991
|
},
|
|
15647
15992
|
parts: parseParts(partsArr)
|
|
15648
15993
|
};
|
|
15649
|
-
|
|
15994
|
+
globalObj?.lyrics && (score.global.lyrics = parseGlobalLyrics(globalObj.lyrics)), globalObj?.sounds && (score.global.sounds = parseGlobalSounds(globalObj.sounds)), layoutsArr && layoutsArr.length > 0 && (score.layouts = layoutsArr.map((l) => parseLayoutDefinition(l))), scoresArr && scoresArr.length > 0 && (score.scores = scoresArr.map((s) => parseScoreDefinition(s))), applyRootExtensions(score, obj._x), assignMissingIds(score), validateSupportConsistency(score, support, diagnostics);
|
|
15995
|
+
for (let issue of resolveLyricExtenders(score).diagnostics) {
|
|
15996
|
+
let source = issue.sourceEventId ? ` on event "${issue.sourceEventId}"` : "", message = issue.code === "missing-target" ? `Lyric extender${source} targets missing event "${issue.targetEventId}"` : issue.code === "backward-target" ? `Lyric extender${source} targets earlier event "${issue.targetEventId}"` : `Lyric extender${source} ends on an event with another syllable in lyric line "${issue.lineId}"`;
|
|
15997
|
+
diagnostics.warn(
|
|
15998
|
+
ptr("parts", "?", "measures", "?", "sequences", "?", "content", "?", "lyrics", "lines", issue.lineId, "extender"),
|
|
15999
|
+
message,
|
|
16000
|
+
"lyric-extender-reference"
|
|
16001
|
+
);
|
|
16002
|
+
}
|
|
16003
|
+
return scanUnknownFields(obj, diagnostics), score;
|
|
15650
16004
|
}
|
|
15651
16005
|
function applyRootExtensions(score, rootX) {
|
|
15652
16006
|
let metadata = parseRootMetadata(rootX);
|
|
@@ -15709,121 +16063,6 @@ function processEventIds(event, usedIds, collectOnly) {
|
|
|
15709
16063
|
for (let n of event.notes)
|
|
15710
16064
|
n.id || (n.id = mintId(usedIds));
|
|
15711
16065
|
}
|
|
15712
|
-
var KEYS = {
|
|
15713
|
-
root: /* @__PURE__ */ new Set(["mnx", "global", "parts", "layouts", "scores", "_x"]),
|
|
15714
|
-
mnxMeta: /* @__PURE__ */ new Set(["version", "support"]),
|
|
15715
|
-
support: /* @__PURE__ */ new Set(["useAccidentalDisplay", "useBeams"]),
|
|
15716
|
-
global: /* @__PURE__ */ new Set(["measures", "lyrics"]),
|
|
15717
|
-
globalLyrics: /* @__PURE__ */ new Set(["lineMetadata", "lineOrder"]),
|
|
15718
|
-
globalMeasure: /* @__PURE__ */ new Set([
|
|
15719
|
-
"id",
|
|
15720
|
-
"number",
|
|
15721
|
-
"time",
|
|
15722
|
-
"key",
|
|
15723
|
-
"barline",
|
|
15724
|
-
"repeatStart",
|
|
15725
|
-
"repeatEnd",
|
|
15726
|
-
"ending",
|
|
15727
|
-
"tempos",
|
|
15728
|
-
"segno",
|
|
15729
|
-
"fine",
|
|
15730
|
-
"jump",
|
|
15731
|
-
"_x"
|
|
15732
|
-
]),
|
|
15733
|
-
time: /* @__PURE__ */ new Set(["count", "unit", "display", "_x"]),
|
|
15734
|
-
key: /* @__PURE__ */ new Set(["fifths", "color", "_x"]),
|
|
15735
|
-
barline: /* @__PURE__ */ new Set(["type"]),
|
|
15736
|
-
ending: /* @__PURE__ */ new Set(["duration", "numbers", "open", "color"]),
|
|
15737
|
-
tempo: /* @__PURE__ */ new Set(["bpm", "value", "location", "_x"]),
|
|
15738
|
-
tempoNoteValue: /* @__PURE__ */ new Set(["base", "dots"]),
|
|
15739
|
-
rhythmicPosition: /* @__PURE__ */ new Set(["fraction"]),
|
|
15740
|
-
segno: /* @__PURE__ */ new Set(["location", "glyph", "color"]),
|
|
15741
|
-
fine: /* @__PURE__ */ new Set(["location", "color"]),
|
|
15742
|
-
jump: /* @__PURE__ */ new Set(["type", "location"]),
|
|
15743
|
-
part: /* @__PURE__ */ new Set(["id", "name", "shortName", "staves", "transposition", "measures", "_x"]),
|
|
15744
|
-
transposition: /* @__PURE__ */ new Set(["interval", "keyFifthsFlipAt", "prefersWrittenPitches"]),
|
|
15745
|
-
partMeasure: /* @__PURE__ */ new Set([
|
|
15746
|
-
"sequences",
|
|
15747
|
-
"clefs",
|
|
15748
|
-
"staffConfigs",
|
|
15749
|
-
"arpeggios",
|
|
15750
|
-
"nonArpeggios",
|
|
15751
|
-
"beams",
|
|
15752
|
-
"dynamics",
|
|
15753
|
-
"ottavas",
|
|
15754
|
-
"measureRepeat",
|
|
15755
|
-
"_x"
|
|
15756
|
-
]),
|
|
15757
|
-
positionedStaffConfig: /* @__PURE__ */ new Set(["config", "position", "staff", "id", "_c", "_x"]),
|
|
15758
|
-
staffConfig: /* @__PURE__ */ new Set(["lines", "id", "_c", "_x"]),
|
|
15759
|
-
measureRepeat: /* @__PURE__ */ new Set(["number", "counter", "displayNumber", "staffPosition", "_c", "_x"]),
|
|
15760
|
-
measureRepeatCounter: /* @__PURE__ */ new Set(["count", "placement", "_c", "_x"]),
|
|
15761
|
-
arpeggio: /* @__PURE__ */ new Set(["id", "position", "span", "direction", "arrow", "_c", "_x"]),
|
|
15762
|
-
nonArpeggio: /* @__PURE__ */ new Set(["id", "position", "span", "_c", "_x"]),
|
|
15763
|
-
idPair: /* @__PURE__ */ new Set(["start", "end"]),
|
|
15764
|
-
positionedClef: /* @__PURE__ */ new Set(["clef", "position", "staff"]),
|
|
15765
|
-
clef: /* @__PURE__ */ new Set(["sign", "staffPosition", "color", "glyph", "octave", "showOctave", "hide"]),
|
|
15766
|
-
beam: /* @__PURE__ */ new Set(["events", "beams", "direction"]),
|
|
15767
|
-
dynamic: /* @__PURE__ */ new Set(["position", "value", "glyph", "staff", "voice"]),
|
|
15768
|
-
ottava: /* @__PURE__ */ new Set(["position", "end", "value", "staff", "voice"]),
|
|
15769
|
-
measureRhythmicPosition: /* @__PURE__ */ new Set(["measure", "position"]),
|
|
15770
|
-
sequence: /* @__PURE__ */ new Set(["content", "fullMeasure", "staff", "voice", "directionHint"]),
|
|
15771
|
-
fullMeasure: /* @__PURE__ */ new Set(["visualDuration", "staffPosition"]),
|
|
15772
|
-
duration: /* @__PURE__ */ new Set(["base", "dots"]),
|
|
15773
|
-
event: /* @__PURE__ */ new Set([
|
|
15774
|
-
"type",
|
|
15775
|
-
"id",
|
|
15776
|
-
"duration",
|
|
15777
|
-
"staff",
|
|
15778
|
-
"rest",
|
|
15779
|
-
"notes",
|
|
15780
|
-
"slurs",
|
|
15781
|
-
"markings",
|
|
15782
|
-
"fermata",
|
|
15783
|
-
"lyrics",
|
|
15784
|
-
"stemDirection",
|
|
15785
|
-
"smufl",
|
|
15786
|
-
"_x"
|
|
15787
|
-
]),
|
|
15788
|
-
rest: /* @__PURE__ */ new Set(["staffPosition"]),
|
|
15789
|
-
note: /* @__PURE__ */ new Set(["pitch", "id", "ties", "accidentalDisplay", "written"]),
|
|
15790
|
-
pitch: /* @__PURE__ */ new Set(["step", "octave", "alter"]),
|
|
15791
|
-
tie: /* @__PURE__ */ new Set(["target", "targetType", "side", "lv"]),
|
|
15792
|
-
accidentalDisplay: /* @__PURE__ */ new Set(["show", "force", "enclosure"]),
|
|
15793
|
-
accidentalEnclosure: /* @__PURE__ */ new Set(["symbol"]),
|
|
15794
|
-
written: /* @__PURE__ */ new Set(["diatonicDelta"]),
|
|
15795
|
-
slur: /* @__PURE__ */ new Set(["target", "side", "sideEnd", "lineType", "startNote", "endNote"]),
|
|
15796
|
-
markings: /* @__PURE__ */ new Set([
|
|
15797
|
-
"staccato",
|
|
15798
|
-
"staccatissimo",
|
|
15799
|
-
"spiccato",
|
|
15800
|
-
"staccatissimoWedge",
|
|
15801
|
-
"tenuto",
|
|
15802
|
-
"accent",
|
|
15803
|
-
"strongAccent",
|
|
15804
|
-
"tremolo",
|
|
15805
|
-
"softAccent",
|
|
15806
|
-
"stress",
|
|
15807
|
-
"unstress",
|
|
15808
|
-
"breath",
|
|
15809
|
-
"bowDirection",
|
|
15810
|
-
"_x"
|
|
15811
|
-
]),
|
|
15812
|
-
tuplet: /* @__PURE__ */ new Set(["type", "inner", "outer", "content", "bracket", "showNumber", "showValue", "placement"]),
|
|
15813
|
-
tupletDuration: /* @__PURE__ */ new Set(["duration", "multiple"]),
|
|
15814
|
-
grace: /* @__PURE__ */ new Set(["type", "content", "graceType", "slash", "color"]),
|
|
15815
|
-
multiTremolo: /* @__PURE__ */ new Set(["type", "content", "marks", "outer"]),
|
|
15816
|
-
space: /* @__PURE__ */ new Set(["type", "duration"]),
|
|
15817
|
-
layoutDefinition: /* @__PURE__ */ new Set(["id", "content"]),
|
|
15818
|
-
layoutGroup: /* @__PURE__ */ new Set(["type", "content", "symbol", "label", "barlineStyle"]),
|
|
15819
|
-
layoutStaff: /* @__PURE__ */ new Set(["type", "sources", "label", "labelref"]),
|
|
15820
|
-
layoutSource: /* @__PURE__ */ new Set(["part", "staff", "stem", "voice", "labelref"]),
|
|
15821
|
-
scoreDefinition: /* @__PURE__ */ new Set(["name", "layout", "multimeasureRests", "pages", "useWritten", "_x"]),
|
|
15822
|
-
multimeasureRest: /* @__PURE__ */ new Set(["start", "duration"]),
|
|
15823
|
-
page: /* @__PURE__ */ new Set(["systems"]),
|
|
15824
|
-
system: /* @__PURE__ */ new Set(["measure", "layout", "layoutChanges"]),
|
|
15825
|
-
layoutChange: /* @__PURE__ */ new Set(["layout", "location"])
|
|
15826
|
-
};
|
|
15827
16066
|
function scanUnknownFields(json, dx) {
|
|
15828
16067
|
if (!json || typeof json != "object") return;
|
|
15829
16068
|
let root = json;
|
|
@@ -15937,6 +16176,19 @@ function scanContentItem(c, p, dx) {
|
|
|
15937
16176
|
let type = c.type ?? "event";
|
|
15938
16177
|
if (type === "event") {
|
|
15939
16178
|
emitUnknown(c, KEYS.event, p, dx);
|
|
16179
|
+
let lyrics = c.lyrics;
|
|
16180
|
+
if (lyrics) {
|
|
16181
|
+
emitUnknown(lyrics, KEYS.eventLyrics, p + ptr("lyrics"), dx);
|
|
16182
|
+
let lines = lyrics.lines;
|
|
16183
|
+
if (lines && typeof lines == "object")
|
|
16184
|
+
for (let [lineId, line] of Object.entries(lines)) {
|
|
16185
|
+
if (!line || typeof line != "object") continue;
|
|
16186
|
+
let linePath = p + ptr("lyrics", "lines", lineId);
|
|
16187
|
+
emitUnknown(line, KEYS.eventLyricLine, linePath, dx);
|
|
16188
|
+
let extender = line.extender;
|
|
16189
|
+
extender && emitUnknown(extender, KEYS.eventLyricLineExtender, linePath + ptr("extender"), dx);
|
|
16190
|
+
}
|
|
16191
|
+
}
|
|
15940
16192
|
let notes = c.notes;
|
|
15941
16193
|
Array.isArray(notes) && notes.forEach((n, i) => {
|
|
15942
16194
|
n && typeof n == "object" && emitUnknown(n, KEYS.note, p + ptr("notes", i), dx);
|
|
@@ -16419,7 +16671,7 @@ function fermataMultiplier(fermata) {
|
|
|
16419
16671
|
function caesuraBeats(style) {
|
|
16420
16672
|
return style === "short" ? CAESURA_SHORT_BEATS : CAESURA_BEATS;
|
|
16421
16673
|
}
|
|
16422
|
-
function
|
|
16674
|
+
function durationBeats2(d) {
|
|
16423
16675
|
let base = DURATION_BEATS[d.base] ?? 1;
|
|
16424
16676
|
return d.dots ? base * (2 - Math.pow(2, -d.dots)) : base;
|
|
16425
16677
|
}
|
|
@@ -16437,16 +16689,16 @@ function collectFromContent(content, startBeat, ratio, spans, caesuraByBeat) {
|
|
|
16437
16689
|
let cursor = startBeat;
|
|
16438
16690
|
for (let item of content)
|
|
16439
16691
|
if (item.type === "event") {
|
|
16440
|
-
let dur =
|
|
16692
|
+
let dur = durationBeats2(item.duration) * ratio, endBeat = cursor + dur;
|
|
16441
16693
|
if (item.fermata && item.fermata.duration !== "none") {
|
|
16442
16694
|
let mult = fermataMultiplier(item.fermata);
|
|
16443
16695
|
dur > 0 && mult > 1 && spans.push({ onset: cursor, end: endBeat, duration: dur, multiplier: mult });
|
|
16444
16696
|
}
|
|
16445
16697
|
item.markings?.caesura && mergeMax(caesuraByBeat, endBeat, caesuraBeats(item.markings.caesura.style)), cursor = endBeat;
|
|
16446
16698
|
} else if (item.type === "tuplet") {
|
|
16447
|
-
let outerBeats =
|
|
16699
|
+
let outerBeats = durationBeats2(item.outer.duration) * item.outer.multiple, innerBeats = durationBeats2(item.inner.duration) * item.inner.multiple, childRatio = innerBeats > 0 ? outerBeats / innerBeats * ratio : ratio;
|
|
16448
16700
|
collectFromContent(item.content, cursor, childRatio, spans, caesuraByBeat), cursor += outerBeats * ratio;
|
|
16449
|
-
} else item.type === "tremolo" ? cursor +=
|
|
16701
|
+
} else item.type === "tremolo" ? cursor += durationBeats2(item.outer.duration) * item.outer.multiple * ratio : item.type === "space" && (cursor += item.duration[0] / item.duration[1] * 4 * ratio);
|
|
16450
16702
|
return cursor - startBeat;
|
|
16451
16703
|
}
|
|
16452
16704
|
function collectPartMeasureHolds(partMeasure, originalMeasureIndex, staffMeterTable, spans, caesuraByBeat) {
|
|
@@ -16509,21 +16761,21 @@ function contentBeats(content) {
|
|
|
16509
16761
|
for (let item of content)
|
|
16510
16762
|
switch (item.type) {
|
|
16511
16763
|
case "event":
|
|
16512
|
-
beats +=
|
|
16764
|
+
beats += durationBeats3(item.duration.base, item.duration.dots);
|
|
16513
16765
|
break;
|
|
16514
16766
|
case "space":
|
|
16515
16767
|
beats += item.duration[0] / item.duration[1] * 4;
|
|
16516
16768
|
break;
|
|
16517
16769
|
case "tuplet":
|
|
16518
16770
|
case "tremolo":
|
|
16519
|
-
beats +=
|
|
16771
|
+
beats += durationBeats3(item.outer.duration.base, item.outer.duration.dots) * item.outer.multiple;
|
|
16520
16772
|
break;
|
|
16521
16773
|
case "grace":
|
|
16522
16774
|
break;
|
|
16523
16775
|
}
|
|
16524
16776
|
return beats;
|
|
16525
16777
|
}
|
|
16526
|
-
function
|
|
16778
|
+
function durationBeats3(base, dots) {
|
|
16527
16779
|
let beats = DURATION_BEATS[base];
|
|
16528
16780
|
return dots ? beats * (2 - Math.pow(2, -dots)) : beats;
|
|
16529
16781
|
}
|
|
@@ -17610,7 +17862,7 @@ function kitNoteToMidi(kn, kitMidiMap) {
|
|
|
17610
17862
|
return kitMidiMap.get(kn.kitComponent) ?? -1;
|
|
17611
17863
|
}
|
|
17612
17864
|
var GRACE_NOTE_BEATS = 0.125;
|
|
17613
|
-
function
|
|
17865
|
+
function durationBeats4(d) {
|
|
17614
17866
|
let base = DURATION_BEATS[d.base] ?? 1;
|
|
17615
17867
|
return d.dots ? base * (2 - Math.pow(2, -d.dots)) : base;
|
|
17616
17868
|
}
|
|
@@ -17927,7 +18179,7 @@ function tryProcessSpecialEvent(ctx, event, measureStartTime, beatOffset, baseVe
|
|
|
17927
18179
|
}
|
|
17928
18180
|
function processNoteEvent(ctx, event, measureStartTime, beatOffset, baseVelocity, tupletRatio) {
|
|
17929
18181
|
ctx.gmProgram = ctx.instrumentAtBeatOffset?.(beatOffset * ctx.staffMeterRatio).program ?? ctx.gmProgram;
|
|
17930
|
-
let { partIndex, channel, tieTargets, out, timeSig, kitMidiMap, kitAltProgramMap } = ctx, beats =
|
|
18182
|
+
let { partIndex, channel, tieTargets, out, timeSig, kitMidiMap, kitAltProgramMap } = ctx, beats = durationBeats4(event.duration) * tupletRatio;
|
|
17931
18183
|
if (isRest(event))
|
|
17932
18184
|
return flushVoiceLegato(ctx.pendingLegato, ctx.voiceKey, ctx.out), beats;
|
|
17933
18185
|
resolveVoiceLegato({
|
|
@@ -18240,30 +18492,30 @@ function processGrace(ctx, grace, measureStartTime, beatOffset, tupletRatio) {
|
|
|
18240
18492
|
if (grace.graceType === "stealFollowing") {
|
|
18241
18493
|
let cursor2 = beatOffset;
|
|
18242
18494
|
for (let evt of events) {
|
|
18243
|
-
let ratio = graceBeats /
|
|
18495
|
+
let ratio = graceBeats / durationBeats4(evt.duration);
|
|
18244
18496
|
processScopedNoteEvent(ctx, evt, measureStartTime, cursor2, ratio), cursor2 += graceBeats;
|
|
18245
18497
|
}
|
|
18246
18498
|
return totalGraceBeats;
|
|
18247
18499
|
}
|
|
18248
18500
|
let cursor = beatOffset - totalGraceBeats;
|
|
18249
18501
|
for (let evt of events) {
|
|
18250
|
-
let ratio = graceBeats /
|
|
18502
|
+
let ratio = graceBeats / durationBeats4(evt.duration);
|
|
18251
18503
|
processScopedNoteEvent(ctx, evt, measureStartTime, cursor, ratio), cursor += graceBeats;
|
|
18252
18504
|
}
|
|
18253
18505
|
return 0;
|
|
18254
18506
|
}
|
|
18255
18507
|
function processTuplet(ctx, tuplet, measureStartTime, beatOffset, parentTupletRatio) {
|
|
18256
|
-
let outerBeats =
|
|
18508
|
+
let outerBeats = durationBeats4(tuplet.outer.duration) * tuplet.outer.multiple, innerBeats = durationBeats4(tuplet.inner.duration) * tuplet.inner.multiple, ratio = outerBeats / innerBeats * parentTupletRatio, cursor = beatOffset;
|
|
18257
18509
|
for (let item of tuplet.content)
|
|
18258
18510
|
cursor += processContentItem(ctx, item, measureStartTime, cursor, ratio);
|
|
18259
18511
|
return outerBeats * parentTupletRatio;
|
|
18260
18512
|
}
|
|
18261
18513
|
function processTremolo(ctx, tremolo, measureStartTime, beatOffset, tupletRatio) {
|
|
18262
|
-
let outerBeats =
|
|
18514
|
+
let outerBeats = durationBeats4(tremolo.outer.duration) * tremolo.outer.multiple * tupletRatio;
|
|
18263
18515
|
if (tremolo.content.length < 2) return outerBeats;
|
|
18264
18516
|
let subdivisions = Math.pow(2, tremolo.marks), subdivBeats = outerBeats / subdivisions;
|
|
18265
18517
|
for (let s = 0; s < subdivisions; s++) {
|
|
18266
|
-
let noteEvent = tremolo.content[s % 2], subBeatOffset = beatOffset + s * subdivBeats, subRatio = subdivBeats /
|
|
18518
|
+
let noteEvent = tremolo.content[s % 2], subBeatOffset = beatOffset + s * subdivBeats, subRatio = subdivBeats / durationBeats4(noteEvent.duration);
|
|
18267
18519
|
processScopedNoteEvent(ctx, noteEvent, measureStartTime, subBeatOffset, subRatio);
|
|
18268
18520
|
}
|
|
18269
18521
|
return outerBeats;
|