musicxml-io 0.7.0 → 0.7.2

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.
@@ -509,6 +509,363 @@ function hasPlaybackControls(score, options) {
509
509
  return controls.repeatStarts.length > 0 || controls.repeatEnds.length > 0 || controls.voltas.length > 0 || controls.jumps.length > 0 || controls.segnoIndex !== null || controls.codaIndex !== null;
510
510
  }
511
511
 
512
+ // src/query/playback-timeline.ts
513
+ var DEFAULT_FERMATA_HOLD = 1.75;
514
+ var DEFAULT_CAESURA_SECONDS = 0.4;
515
+ var DEFAULT_BREATH_SECONDS = 0.25;
516
+ var DEFAULT_RAMP_STEPS = 12;
517
+ function metronomeBpm(perMinute) {
518
+ if (perMinute === void 0) return null;
519
+ const bpm = typeof perMinute === "number" ? perMinute : parseFloat(perMinute);
520
+ return isNaN(bpm) ? null : bpm;
521
+ }
522
+ function measureMaxPosition(measure) {
523
+ let position = 0;
524
+ let max = 0;
525
+ for (const entry of measure.entries) {
526
+ if (entry.type === "note") {
527
+ if (!entry.chord && !entry.grace) {
528
+ position += entry.duration;
529
+ if (position > max) max = position;
530
+ }
531
+ } else if (entry.type === "backup") {
532
+ position -= entry.duration;
533
+ } else if (entry.type === "forward") {
534
+ position += entry.duration;
535
+ if (position > max) max = position;
536
+ }
537
+ }
538
+ return max;
539
+ }
540
+ function findTimeSignature(part, measureNumber) {
541
+ const targetMeasure = parseInt(String(measureNumber), 10);
542
+ let time;
543
+ for (const measure of part.measures) {
544
+ const mNum = parseInt(measure.number, 10);
545
+ if (!isNaN(targetMeasure) && !isNaN(mNum) && mNum > targetMeasure) break;
546
+ if (_optionalChain([measure, 'access', _5 => _5.attributes, 'optionalAccess', _6 => _6.time])) {
547
+ time = {
548
+ beats: parseInt(measure.attributes.time.beats, 10) || 4,
549
+ beatType: measure.attributes.time.beatType
550
+ };
551
+ }
552
+ }
553
+ return time;
554
+ }
555
+ function measureEndTick(measure, part, divisions, measureStartTick, maxPosition, ticksPerQuarterNote) {
556
+ const actualTicks = Math.round(maxPosition * ticksPerQuarterNote / divisions);
557
+ if (measure.implicit) {
558
+ return measureStartTick + actualTicks;
559
+ }
560
+ const timeAttrs = findTimeSignature(part, measure.number);
561
+ if (timeAttrs) {
562
+ const measureDuration = timeAttrs.beats / timeAttrs.beatType * 4 * divisions;
563
+ const calculatedTicks = Math.round(measureDuration * ticksPerQuarterNote / divisions);
564
+ const ticksToAdd = Math.min(calculatedTicks, actualTicks > 0 ? actualTicks : calculatedTicks);
565
+ return measureStartTick + ticksToAdd;
566
+ }
567
+ return measureStartTick + actualTicks;
568
+ }
569
+ function hasFermata(note) {
570
+ return _nullishCoalesce(_optionalChain([note, 'access', _7 => _7.notations, 'optionalAccess', _8 => _8.some, 'call', _9 => _9((n) => n.type === "fermata")]), () => ( false));
571
+ }
572
+ function pauseArticulation(note) {
573
+ if (!note.notations) return null;
574
+ for (const n of note.notations) {
575
+ if (n.type === "articulation") {
576
+ if (n.articulation === "caesura") return "caesura";
577
+ if (n.articulation === "breath-mark") return "breath";
578
+ }
579
+ }
580
+ return null;
581
+ }
582
+ function tempoRampWord(text) {
583
+ const t = text.trim().toLowerCase().replace(/[.\s]+$/, "");
584
+ if (!t) return null;
585
+ if (/^(rit|riten|rall|allarg|slarg|cala|smorz|morend)/.test(t)) return "rit";
586
+ if (/^(accel|string|affret|incalz|pi[uù]\s*mosso)/.test(t)) return "accel";
587
+ return null;
588
+ }
589
+ function buildGridTimeline(score, ticksPerQuarterNote, sequence, options = {}) {
590
+ const rawTempo = [];
591
+ const measures = [];
592
+ const rampMarkers = [];
593
+ const stretches = [];
594
+ if (score.parts.length === 0) {
595
+ return { tempoEvents: [], measures, totalTicks: 0, expressions: [] };
596
+ }
597
+ const fermataHold = _nullishCoalesce(options.fermataHoldMultiplier, () => ( DEFAULT_FERMATA_HOLD));
598
+ const caesuraSeconds = _nullishCoalesce(options.caesuraSeconds, () => ( DEFAULT_CAESURA_SECONDS));
599
+ const breathSeconds = _nullishCoalesce(options.breathSeconds, () => ( DEFAULT_BREATH_SECONDS));
600
+ const rampSteps = Math.max(1, Math.round(_nullishCoalesce(options.tempoRampSteps, () => ( DEFAULT_RAMP_STEPS))));
601
+ const defaultTempo = _nullishCoalesce(options.defaultTempo, () => ( 120));
602
+ const part = score.parts[0];
603
+ let divisions = 1;
604
+ let currentTick = 0;
605
+ let prevailingBpm = defaultTempo;
606
+ const pauseFactor = (windowTicks, bpm, pauseSeconds) => {
607
+ const baseSeconds = windowTicks / ticksPerQuarterNote * (60 / bpm);
608
+ if (baseSeconds <= 0) return 1;
609
+ return (baseSeconds + pauseSeconds) / baseSeconds;
610
+ };
611
+ for (const { measureIndex, repeatIteration } of sequence) {
612
+ const measure = part.measures[measureIndex];
613
+ if (!measure) continue;
614
+ if (_optionalChain([measure, 'access', _10 => _10.attributes, 'optionalAccess', _11 => _11.divisions])) {
615
+ divisions = measure.attributes.divisions;
616
+ }
617
+ const measureStartTick = currentTick;
618
+ let position = 0;
619
+ let chordBasePosition = 0;
620
+ const tickAt = (pos) => measureStartTick + Math.round(pos * ticksPerQuarterNote / divisions);
621
+ for (const entry of measure.entries) {
622
+ if (entry.type === "direction") {
623
+ for (const dirType of entry.directionTypes) {
624
+ if (dirType.kind === "metronome") {
625
+ const bpm = metronomeBpm(dirType.perMinute);
626
+ if (bpm !== null) {
627
+ rawTempo.push({ tick: tickAt(position), bpm });
628
+ prevailingBpm = bpm;
629
+ }
630
+ } else if (dirType.kind === "words") {
631
+ const kind = tempoRampWord(dirType.text);
632
+ if (kind) rampMarkers.push({ tick: tickAt(position), kind });
633
+ }
634
+ }
635
+ if (_optionalChain([entry, 'access', _12 => _12.sound, 'optionalAccess', _13 => _13.tempo])) {
636
+ rawTempo.push({ tick: tickAt(position), bpm: entry.sound.tempo });
637
+ prevailingBpm = entry.sound.tempo;
638
+ }
639
+ } else if (entry.type === "sound") {
640
+ if (entry.tempo) {
641
+ rawTempo.push({ tick: tickAt(position), bpm: entry.tempo });
642
+ prevailingBpm = entry.tempo;
643
+ }
644
+ } else if (entry.type === "note") {
645
+ const notePos = entry.chord ? chordBasePosition : position;
646
+ const noteStartTick = tickAt(notePos);
647
+ const noteEndTick = tickAt(notePos + entry.duration);
648
+ if (noteEndTick > noteStartTick) {
649
+ if (fermataHold !== 1 && hasFermata(entry)) {
650
+ stretches.push({
651
+ startTick: noteStartTick,
652
+ endTick: noteEndTick,
653
+ factor: fermataHold,
654
+ type: "fermata"
655
+ });
656
+ }
657
+ const pause = pauseArticulation(entry);
658
+ if (pause) {
659
+ const seconds = pause === "caesura" ? caesuraSeconds : breathSeconds;
660
+ if (seconds > 0) {
661
+ const window = Math.min(noteEndTick - noteStartTick, ticksPerQuarterNote);
662
+ stretches.push({
663
+ startTick: noteEndTick - window,
664
+ endTick: noteEndTick,
665
+ factor: pauseFactor(window, prevailingBpm, seconds),
666
+ type: pause
667
+ });
668
+ }
669
+ }
670
+ }
671
+ if (!entry.chord) {
672
+ chordBasePosition = position;
673
+ position += entry.duration;
674
+ }
675
+ } else if (entry.type === "backup") {
676
+ position -= entry.duration;
677
+ } else if (entry.type === "forward") {
678
+ position += entry.duration;
679
+ }
680
+ }
681
+ const endTick = measureEndTick(
682
+ measure,
683
+ part,
684
+ divisions,
685
+ measureStartTick,
686
+ measureMaxPosition(measure),
687
+ ticksPerQuarterNote
688
+ );
689
+ measures.push({
690
+ measureIndex,
691
+ repeatIteration,
692
+ measureNumber: measure.number,
693
+ startTick: measureStartTick,
694
+ endTick
695
+ });
696
+ currentTick = endTick;
697
+ }
698
+ const { tempoEvents, expressions } = bakeTempoMap(
699
+ rawTempo,
700
+ rampMarkers,
701
+ stretches,
702
+ defaultTempo,
703
+ rampSteps
704
+ );
705
+ return { tempoEvents, measures, totalTicks: currentTick, expressions };
706
+ }
707
+ function bakeTempoMap(rawTempo, rampMarkers, stretches, defaultTempo, rampSteps) {
708
+ const sortedRaw = [...rawTempo].sort((a, b) => a.tick - b.tick);
709
+ const startBpm = sortedRaw.length > 0 && sortedRaw[0].tick === 0 ? sortedRaw[0].bpm : defaultTempo;
710
+ const baseChanges = [{ tick: 0, bpm: startBpm }];
711
+ let lastBpm = startBpm;
712
+ for (const ev of sortedRaw) {
713
+ if (ev.tick === 0) continue;
714
+ if (ev.bpm === lastBpm) continue;
715
+ if (baseChanges[baseChanges.length - 1].tick === ev.tick) {
716
+ baseChanges[baseChanges.length - 1].bpm = ev.bpm;
717
+ } else {
718
+ baseChanges.push({ tick: ev.tick, bpm: ev.bpm });
719
+ }
720
+ lastBpm = ev.bpm;
721
+ }
722
+ const baseBpmAt = (tick) => {
723
+ let i = baseChanges.length - 1;
724
+ while (i > 0 && baseChanges[i].tick > tick) i--;
725
+ return baseChanges[i].bpm;
726
+ };
727
+ const rampExpressions = [];
728
+ const rampPoints = [];
729
+ for (const marker of rampMarkers) {
730
+ const from = baseBpmAt(marker.tick);
731
+ const next = baseChanges.find((c) => c.tick > marker.tick && c.bpm !== from);
732
+ if (!next) continue;
733
+ const span = next.tick - marker.tick;
734
+ if (span <= 0) continue;
735
+ for (let k = 1; k < rampSteps; k++) {
736
+ const tick = Math.round(marker.tick + span * k / rampSteps);
737
+ if (tick <= marker.tick || tick >= next.tick) continue;
738
+ const bpm = from + (next.bpm - from) * k / rampSteps;
739
+ rampPoints.push({ tick, bpm });
740
+ }
741
+ rampExpressions.push({ type: marker.kind, startTick: marker.tick, endTick: next.tick });
742
+ }
743
+ const baseTicks = new Set(baseChanges.map((c) => c.tick));
744
+ const stepList = [...baseChanges];
745
+ for (const p of rampPoints) {
746
+ if (!baseTicks.has(p.tick)) stepList.push(p);
747
+ }
748
+ stepList.sort((a, b) => a.tick - b.tick);
749
+ const stepBpmAt = (tick) => {
750
+ let i = stepList.length - 1;
751
+ while (i > 0 && stepList[i].tick > tick) i--;
752
+ return stepList[i].bpm;
753
+ };
754
+ const boundaries = new Set(stepList.map((s) => s.tick));
755
+ for (const s of stretches) {
756
+ boundaries.add(s.startTick);
757
+ boundaries.add(s.endTick);
758
+ }
759
+ const sortedBoundaries = [...boundaries].sort((a, b) => a - b);
760
+ const tempoEvents = [];
761
+ let emittedBpm = null;
762
+ for (const tick of sortedBoundaries) {
763
+ let bpm = stepBpmAt(tick);
764
+ for (const s of stretches) {
765
+ if (tick >= s.startTick && tick < s.endTick) bpm /= s.factor;
766
+ }
767
+ if (emittedBpm === null || bpm !== emittedBpm) {
768
+ tempoEvents.push({ tick, bpm });
769
+ emittedBpm = bpm;
770
+ }
771
+ }
772
+ const expressions = [
773
+ ...stretches.map((s) => ({ type: s.type, startTick: s.startTick, endTick: s.endTick })),
774
+ ...rampExpressions
775
+ ].sort((a, b) => a.startTick - b.startTick || a.endTick - b.endTick);
776
+ return { tempoEvents, expressions };
777
+ }
778
+ function bpmToUsPerQuarter(bpm) {
779
+ return Math.round(6e7 / bpm);
780
+ }
781
+ function makeTickToSec(tempoEvents, defaultTempo, ticksPerQuarterNote) {
782
+ const sorted = [...tempoEvents].sort((a, b) => a.tick - b.tick);
783
+ const startBpm = sorted.length > 0 && sorted[0].tick === 0 ? sorted[0].bpm : defaultTempo;
784
+ const changes = [
785
+ { tick: 0, usPerQuarter: bpmToUsPerQuarter(startBpm) }
786
+ ];
787
+ let lastBpm = startBpm;
788
+ for (const ev of sorted) {
789
+ if (ev.tick === 0) continue;
790
+ if (ev.bpm === lastBpm) continue;
791
+ changes.push({ tick: ev.tick, usPerQuarter: bpmToUsPerQuarter(ev.bpm) });
792
+ lastBpm = ev.bpm;
793
+ }
794
+ const secPerTick = (usPerQuarter) => usPerQuarter / 1e6 / ticksPerQuarterNote;
795
+ const cumSec = [0];
796
+ for (let i = 1; i < changes.length; i++) {
797
+ const dTick = changes[i].tick - changes[i - 1].tick;
798
+ cumSec[i] = cumSec[i - 1] + dTick * secPerTick(changes[i - 1].usPerQuarter);
799
+ }
800
+ return (tick) => {
801
+ let i = changes.length - 1;
802
+ while (i > 0 && changes[i].tick > tick) i--;
803
+ return cumSec[i] + (tick - changes[i].tick) * secPerTick(changes[i].usPerQuarter);
804
+ };
805
+ }
806
+ function buildTimingSidecar(grid, defaultTempo, ticksPerQuarterNote) {
807
+ const tickToSec = makeTickToSec(grid.tempoEvents, defaultTempo, ticksPerQuarterNote);
808
+ const breakpoints = [];
809
+ const measureStartTicks = new Set(grid.measures.map((m) => m.startTick));
810
+ for (const m of grid.measures) {
811
+ breakpoints.push({
812
+ midiSec: tickToSec(m.startTick),
813
+ quarterPos: m.startTick / ticksPerQuarterNote,
814
+ measureNumber: m.measureNumber,
815
+ beatInMeasure: 0,
816
+ repeatIteration: m.repeatIteration
817
+ });
818
+ }
819
+ for (const ev of grid.tempoEvents) {
820
+ if (measureStartTicks.has(ev.tick)) continue;
821
+ const m = grid.measures.find((mm) => ev.tick >= mm.startTick && ev.tick < mm.endTick);
822
+ if (!m) continue;
823
+ breakpoints.push({
824
+ midiSec: tickToSec(ev.tick),
825
+ quarterPos: ev.tick / ticksPerQuarterNote,
826
+ measureNumber: m.measureNumber,
827
+ beatInMeasure: (ev.tick - m.startTick) / ticksPerQuarterNote,
828
+ repeatIteration: m.repeatIteration
829
+ });
830
+ }
831
+ const last = grid.measures[grid.measures.length - 1];
832
+ breakpoints.push({
833
+ midiSec: tickToSec(grid.totalTicks),
834
+ quarterPos: grid.totalTicks / ticksPerQuarterNote,
835
+ measureNumber: last ? last.measureNumber : "0",
836
+ beatInMeasure: last ? (grid.totalTicks - last.startTick) / ticksPerQuarterNote : 0,
837
+ repeatIteration: last ? last.repeatIteration : 0
838
+ });
839
+ breakpoints.sort((a, b) => a.midiSec - b.midiSec || a.quarterPos - b.quarterPos);
840
+ const sidecar = {
841
+ version: "1",
842
+ durationSec: tickToSec(grid.totalTicks),
843
+ ticksPerQuarterNote,
844
+ breakpoints
845
+ };
846
+ if (grid.expressions.length > 0) {
847
+ sidecar.expressions = grid.expressions.map((e) => ({
848
+ type: e.type,
849
+ fromMidiSec: tickToSec(e.startTick),
850
+ toMidiSec: tickToSec(e.endTick)
851
+ })).sort((a, b) => a.fromMidiSec - b.fromMidiSec || a.toMidiSec - b.toMidiSec);
852
+ }
853
+ return sidecar;
854
+ }
855
+ function generatePlaybackTimeline(score, options = {}) {
856
+ const ticksPerQuarterNote = _nullishCoalesce(options.ticksPerQuarterNote, () => ( 480));
857
+ const defaultTempo = _nullishCoalesce(options.defaultTempo, () => ( 120));
858
+ const sequence = generatePlaybackSequence(score);
859
+ const grid = buildGridTimeline(score, ticksPerQuarterNote, sequence, {
860
+ defaultTempo,
861
+ fermataHoldMultiplier: options.fermataHoldMultiplier,
862
+ caesuraSeconds: options.caesuraSeconds,
863
+ breathSeconds: options.breathSeconds,
864
+ tempoRampSteps: options.tempoRampSteps
865
+ });
866
+ return buildTimingSidecar(grid, defaultTempo, ticksPerQuarterNote);
867
+ }
868
+
512
869
  // src/query/index.ts
513
870
  function getNotesForVoice(measure, filter) {
514
871
  return measure.entries.filter((entry) => {
@@ -646,7 +1003,7 @@ function isRestMeasure(measure) {
646
1003
  }
647
1004
  function getNormalizedPosition(note, measure, options) {
648
1005
  const absolutePosition = getAbsolutePosition(note, measure);
649
- const currentDivisions = _nullishCoalesce(_nullishCoalesce(options.currentDivisions, () => ( _optionalChain([measure, 'access', _5 => _5.attributes, 'optionalAccess', _6 => _6.divisions]))), () => ( 1));
1006
+ const currentDivisions = _nullishCoalesce(_nullishCoalesce(options.currentDivisions, () => ( _optionalChain([measure, 'access', _14 => _14.attributes, 'optionalAccess', _15 => _15.divisions]))), () => ( 1));
650
1007
  return absolutePosition * options.baseDivisions / currentDivisions;
651
1008
  }
652
1009
  function getNormalizedDuration(note, options) {
@@ -739,7 +1096,7 @@ function getClefForStaff(score, options) {
739
1096
  }
740
1097
  }
741
1098
  }
742
- if (_optionalChain([measure, 'access', _7 => _7.attributes, 'optionalAccess', _8 => _8.clef])) {
1099
+ if (_optionalChain([measure, 'access', _16 => _16.attributes, 'optionalAccess', _17 => _17.clef])) {
743
1100
  for (const clef of measure.attributes.clef) {
744
1101
  if ((_nullishCoalesce(clef.staff, () => ( 1))) === options.staff) {
745
1102
  return clef;
@@ -767,7 +1124,7 @@ function getStaffRange(score, partIndex) {
767
1124
  let min = 1;
768
1125
  let max = 1;
769
1126
  for (const measure of part.measures) {
770
- if (_optionalChain([measure, 'access', _9 => _9.attributes, 'optionalAccess', _10 => _10.staves]) !== void 0) {
1127
+ if (_optionalChain([measure, 'access', _18 => _18.attributes, 'optionalAccess', _19 => _19.staves]) !== void 0) {
771
1128
  max = Math.max(max, measure.attributes.staves);
772
1129
  }
773
1130
  for (const entry of measure.entries) {
@@ -785,15 +1142,15 @@ function getEntriesAtPosition(measure, position, options) {
785
1142
  const currentPosition = entry.type === "note" && entry.chord ? state.lastNonChordPosition : state.position;
786
1143
  if (currentPosition === position) {
787
1144
  if (entry.type === "note") {
788
- if (_optionalChain([options, 'optionalAccess', _11 => _11.staff]) !== void 0 && (_nullishCoalesce(entry.staff, () => ( 1))) !== options.staff) {
1145
+ if (_optionalChain([options, 'optionalAccess', _20 => _20.staff]) !== void 0 && (_nullishCoalesce(entry.staff, () => ( 1))) !== options.staff) {
789
1146
  updatePositionForEntry(state, entry);
790
1147
  continue;
791
1148
  }
792
- if (_optionalChain([options, 'optionalAccess', _12 => _12.voice]) !== void 0 && entry.voice !== options.voice) {
1149
+ if (_optionalChain([options, 'optionalAccess', _21 => _21.voice]) !== void 0 && entry.voice !== options.voice) {
793
1150
  updatePositionForEntry(state, entry);
794
1151
  continue;
795
1152
  }
796
- if (_optionalChain([options, 'optionalAccess', _13 => _13.includeChordNotes]) === false && entry.chord) {
1153
+ if (_optionalChain([options, 'optionalAccess', _22 => _22.includeChordNotes]) === false && entry.chord) {
797
1154
  updatePositionForEntry(state, entry);
798
1155
  continue;
799
1156
  }
@@ -816,15 +1173,15 @@ function getEntriesInRange(measure, range, options) {
816
1173
  const currentPosition = entry.type === "note" && entry.chord ? state.lastNonChordPosition : state.position;
817
1174
  if (currentPosition >= range.start && currentPosition < range.end) {
818
1175
  if (entry.type === "note") {
819
- if (_optionalChain([options, 'optionalAccess', _14 => _14.staff]) !== void 0 && (_nullishCoalesce(entry.staff, () => ( 1))) !== options.staff) {
1176
+ if (_optionalChain([options, 'optionalAccess', _23 => _23.staff]) !== void 0 && (_nullishCoalesce(entry.staff, () => ( 1))) !== options.staff) {
820
1177
  updatePositionForEntry(state, entry);
821
1178
  continue;
822
1179
  }
823
- if (_optionalChain([options, 'optionalAccess', _15 => _15.voice]) !== void 0 && entry.voice !== options.voice) {
1180
+ if (_optionalChain([options, 'optionalAccess', _24 => _24.voice]) !== void 0 && entry.voice !== options.voice) {
824
1181
  updatePositionForEntry(state, entry);
825
1182
  continue;
826
1183
  }
827
- if (_optionalChain([options, 'optionalAccess', _16 => _16.includeChordNotes]) === false && entry.chord) {
1184
+ if (_optionalChain([options, 'optionalAccess', _25 => _25.includeChordNotes]) === false && entry.chord) {
828
1185
  updatePositionForEntry(state, entry);
829
1186
  continue;
830
1187
  }
@@ -1030,13 +1387,13 @@ function getAdjacentNotes(score, context) {
1030
1387
  }
1031
1388
  function getDirections(score, options) {
1032
1389
  const results = [];
1033
- const startPart = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _17 => _17.partIndex]), () => ( 0));
1034
- const endPart = _optionalChain([options, 'optionalAccess', _18 => _18.partIndex]) !== void 0 ? options.partIndex + 1 : score.parts.length;
1390
+ const startPart = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _26 => _26.partIndex]), () => ( 0));
1391
+ const endPart = _optionalChain([options, 'optionalAccess', _27 => _27.partIndex]) !== void 0 ? options.partIndex + 1 : score.parts.length;
1035
1392
  for (let partIndex = startPart; partIndex < endPart; partIndex++) {
1036
1393
  const part = score.parts[partIndex];
1037
1394
  if (!part) continue;
1038
- const startMeasure = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _19 => _19.measureIndex]), () => ( 0));
1039
- const endMeasure = _optionalChain([options, 'optionalAccess', _20 => _20.measureIndex]) !== void 0 ? options.measureIndex + 1 : part.measures.length;
1395
+ const startMeasure = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _28 => _28.measureIndex]), () => ( 0));
1396
+ const endMeasure = _optionalChain([options, 'optionalAccess', _29 => _29.measureIndex]) !== void 0 ? options.measureIndex + 1 : part.measures.length;
1040
1397
  for (let measureIndex = startMeasure; measureIndex < endMeasure; measureIndex++) {
1041
1398
  const measure = part.measures[measureIndex];
1042
1399
  if (!measure) continue;
@@ -1077,8 +1434,8 @@ function findDirectionsByType(score, kind) {
1077
1434
  }
1078
1435
  function getDynamics(score, options) {
1079
1436
  const results = [];
1080
- const startPart = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _21 => _21.partIndex]), () => ( 0));
1081
- const endPart = _optionalChain([options, 'optionalAccess', _22 => _22.partIndex]) !== void 0 ? options.partIndex + 1 : score.parts.length;
1437
+ const startPart = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _30 => _30.partIndex]), () => ( 0));
1438
+ const endPart = _optionalChain([options, 'optionalAccess', _31 => _31.partIndex]) !== void 0 ? options.partIndex + 1 : score.parts.length;
1082
1439
  for (let partIndex = startPart; partIndex < endPart; partIndex++) {
1083
1440
  const part = score.parts[partIndex];
1084
1441
  if (!part) continue;
@@ -1139,8 +1496,8 @@ function getTempoMarkings(score) {
1139
1496
  }
1140
1497
  function getPedalMarkings(score, options) {
1141
1498
  const results = [];
1142
- const startPart = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _23 => _23.partIndex]), () => ( 0));
1143
- const endPart = _optionalChain([options, 'optionalAccess', _24 => _24.partIndex]) !== void 0 ? options.partIndex + 1 : score.parts.length;
1499
+ const startPart = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _32 => _32.partIndex]), () => ( 0));
1500
+ const endPart = _optionalChain([options, 'optionalAccess', _33 => _33.partIndex]) !== void 0 ? options.partIndex + 1 : score.parts.length;
1144
1501
  for (let partIndex = startPart; partIndex < endPart; partIndex++) {
1145
1502
  const part = score.parts[partIndex];
1146
1503
  if (!part) continue;
@@ -1169,8 +1526,8 @@ function getPedalMarkings(score, options) {
1169
1526
  }
1170
1527
  function getWedges(score, options) {
1171
1528
  const results = [];
1172
- const startPart = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _25 => _25.partIndex]), () => ( 0));
1173
- const endPart = _optionalChain([options, 'optionalAccess', _26 => _26.partIndex]) !== void 0 ? options.partIndex + 1 : score.parts.length;
1529
+ const startPart = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _34 => _34.partIndex]), () => ( 0));
1530
+ const endPart = _optionalChain([options, 'optionalAccess', _35 => _35.partIndex]) !== void 0 ? options.partIndex + 1 : score.parts.length;
1174
1531
  for (let partIndex = startPart; partIndex < endPart; partIndex++) {
1175
1532
  const part = score.parts[partIndex];
1176
1533
  if (!part) continue;
@@ -1199,8 +1556,8 @@ function getWedges(score, options) {
1199
1556
  }
1200
1557
  function getOctaveShifts(score, options) {
1201
1558
  const results = [];
1202
- const startPart = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _27 => _27.partIndex]), () => ( 0));
1203
- const endPart = _optionalChain([options, 'optionalAccess', _28 => _28.partIndex]) !== void 0 ? options.partIndex + 1 : score.parts.length;
1559
+ const startPart = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _36 => _36.partIndex]), () => ( 0));
1560
+ const endPart = _optionalChain([options, 'optionalAccess', _37 => _37.partIndex]) !== void 0 ? options.partIndex + 1 : score.parts.length;
1204
1561
  for (let partIndex = startPart; partIndex < endPart; partIndex++) {
1205
1562
  const part = score.parts[partIndex];
1206
1563
  if (!part) continue;
@@ -1230,8 +1587,8 @@ function getOctaveShifts(score, options) {
1230
1587
  }
1231
1588
  function getTiedNoteGroups(score, options) {
1232
1589
  const results = [];
1233
- const startPart = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _29 => _29.partIndex]), () => ( 0));
1234
- const endPart = _optionalChain([options, 'optionalAccess', _30 => _30.partIndex]) !== void 0 ? options.partIndex + 1 : score.parts.length;
1590
+ const startPart = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _38 => _38.partIndex]), () => ( 0));
1591
+ const endPart = _optionalChain([options, 'optionalAccess', _39 => _39.partIndex]) !== void 0 ? options.partIndex + 1 : score.parts.length;
1235
1592
  for (let partIndex = startPart; partIndex < endPart; partIndex++) {
1236
1593
  const part = score.parts[partIndex];
1237
1594
  if (!part) continue;
@@ -1251,8 +1608,8 @@ function getTiedNoteGroups(score, options) {
1251
1608
  measureIndex,
1252
1609
  position
1253
1610
  };
1254
- const hasTieStart = _optionalChain([entry, 'access', _31 => _31.tie, 'optionalAccess', _32 => _32.type]) === "start" || _optionalChain([entry, 'access', _33 => _33.ties, 'optionalAccess', _34 => _34.some, 'call', _35 => _35((t) => t.type === "start")]) || _optionalChain([entry, 'access', _36 => _36.notations, 'optionalAccess', _37 => _37.some, 'call', _38 => _38((n) => n.type === "tied" && n.tiedType === "start")]);
1255
- const hasTieStop = _optionalChain([entry, 'access', _39 => _39.tie, 'optionalAccess', _40 => _40.type]) === "stop" || _optionalChain([entry, 'access', _41 => _41.ties, 'optionalAccess', _42 => _42.some, 'call', _43 => _43((t) => t.type === "stop")]) || _optionalChain([entry, 'access', _44 => _44.notations, 'optionalAccess', _45 => _45.some, 'call', _46 => _46((n) => n.type === "tied" && n.tiedType === "stop")]);
1611
+ const hasTieStart = _optionalChain([entry, 'access', _40 => _40.tie, 'optionalAccess', _41 => _41.type]) === "start" || _optionalChain([entry, 'access', _42 => _42.ties, 'optionalAccess', _43 => _43.some, 'call', _44 => _44((t) => t.type === "start")]) || _optionalChain([entry, 'access', _45 => _45.notations, 'optionalAccess', _46 => _46.some, 'call', _47 => _47((n) => n.type === "tied" && n.tiedType === "start")]);
1612
+ const hasTieStop = _optionalChain([entry, 'access', _48 => _48.tie, 'optionalAccess', _49 => _49.type]) === "stop" || _optionalChain([entry, 'access', _50 => _50.ties, 'optionalAccess', _51 => _51.some, 'call', _52 => _52((t) => t.type === "stop")]) || _optionalChain([entry, 'access', _53 => _53.notations, 'optionalAccess', _54 => _54.some, 'call', _55 => _55((n) => n.type === "tied" && n.tiedType === "stop")]);
1256
1613
  if (hasTieStop && pendingTies.has(pitchKey)) {
1257
1614
  const group = pendingTies.get(pitchKey);
1258
1615
  group.push(context);
@@ -1273,8 +1630,8 @@ function getTiedNoteGroups(score, options) {
1273
1630
  }
1274
1631
  function getSlurSpans(score, options) {
1275
1632
  const results = [];
1276
- const startPart = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _47 => _47.partIndex]), () => ( 0));
1277
- const endPart = _optionalChain([options, 'optionalAccess', _48 => _48.partIndex]) !== void 0 ? options.partIndex + 1 : score.parts.length;
1633
+ const startPart = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _56 => _56.partIndex]), () => ( 0));
1634
+ const endPart = _optionalChain([options, 'optionalAccess', _57 => _57.partIndex]) !== void 0 ? options.partIndex + 1 : score.parts.length;
1278
1635
  for (let partIndex = startPart; partIndex < endPart; partIndex++) {
1279
1636
  const part = score.parts[partIndex];
1280
1637
  if (!part) continue;
@@ -1330,8 +1687,8 @@ function getSlurSpans(score, options) {
1330
1687
  }
1331
1688
  function getTupletGroups(score, options) {
1332
1689
  const results = [];
1333
- const startPart = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _49 => _49.partIndex]), () => ( 0));
1334
- const endPart = _optionalChain([options, 'optionalAccess', _50 => _50.partIndex]) !== void 0 ? options.partIndex + 1 : score.parts.length;
1690
+ const startPart = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _58 => _58.partIndex]), () => ( 0));
1691
+ const endPart = _optionalChain([options, 'optionalAccess', _59 => _59.partIndex]) !== void 0 ? options.partIndex + 1 : score.parts.length;
1335
1692
  for (let partIndex = startPart; partIndex < endPart; partIndex++) {
1336
1693
  const part = score.parts[partIndex];
1337
1694
  if (!part) continue;
@@ -1355,8 +1712,8 @@ function getTupletGroups(score, options) {
1355
1712
  if (notation.type === "tuplet") {
1356
1713
  const tupletNumber = _nullishCoalesce(notation.number, () => ( 1));
1357
1714
  if (notation.tupletType === "start") {
1358
- const actualNotes = _nullishCoalesce(_optionalChain([entry, 'access', _51 => _51.timeModification, 'optionalAccess', _52 => _52.actualNotes]), () => ( 3));
1359
- const normalNotes = _nullishCoalesce(_optionalChain([entry, 'access', _53 => _53.timeModification, 'optionalAccess', _54 => _54.normalNotes]), () => ( 2));
1715
+ const actualNotes = _nullishCoalesce(_optionalChain([entry, 'access', _60 => _60.timeModification, 'optionalAccess', _61 => _61.actualNotes]), () => ( 3));
1716
+ const normalNotes = _nullishCoalesce(_optionalChain([entry, 'access', _62 => _62.timeModification, 'optionalAccess', _63 => _63.normalNotes]), () => ( 2));
1360
1717
  pendingTuplets.set(tupletNumber, {
1361
1718
  notes: [context],
1362
1719
  actualNotes,
@@ -1376,7 +1733,7 @@ function getTupletGroups(score, options) {
1376
1733
  }
1377
1734
  }
1378
1735
  }
1379
- if (entry.timeModification && !_optionalChain([entry, 'access', _55 => _55.notations, 'optionalAccess', _56 => _56.some, 'call', _57 => _57((n) => n.type === "tuplet")])) {
1736
+ if (entry.timeModification && !_optionalChain([entry, 'access', _64 => _64.notations, 'optionalAccess', _65 => _65.some, 'call', _66 => _66((n) => n.type === "tuplet")])) {
1380
1737
  for (const [, pending] of pendingTuplets) {
1381
1738
  if (entry.timeModification.actualNotes === pending.actualNotes && entry.timeModification.normalNotes === pending.normalNotes) {
1382
1739
  pending.notes.push(context);
@@ -1429,8 +1786,8 @@ function getBeamGroups(measure) {
1429
1786
  }
1430
1787
  function findNotesWithNotation(score, notationType, options) {
1431
1788
  const results = [];
1432
- const startPart = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _58 => _58.partIndex]), () => ( 0));
1433
- const endPart = _optionalChain([options, 'optionalAccess', _59 => _59.partIndex]) !== void 0 ? options.partIndex + 1 : score.parts.length;
1789
+ const startPart = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _67 => _67.partIndex]), () => ( 0));
1790
+ const endPart = _optionalChain([options, 'optionalAccess', _68 => _68.partIndex]) !== void 0 ? options.partIndex + 1 : score.parts.length;
1434
1791
  for (let partIndex = startPart; partIndex < endPart; partIndex++) {
1435
1792
  const part = score.parts[partIndex];
1436
1793
  if (!part) continue;
@@ -1440,7 +1797,7 @@ function findNotesWithNotation(score, notationType, options) {
1440
1797
  for (const entry of measure.entries) {
1441
1798
  if (entry.type === "note") {
1442
1799
  const position = entry.chord ? state.lastNonChordPosition : state.position;
1443
- if (_optionalChain([entry, 'access', _60 => _60.notations, 'optionalAccess', _61 => _61.some, 'call', _62 => _62((n) => n.type === notationType)])) {
1800
+ if (_optionalChain([entry, 'access', _69 => _69.notations, 'optionalAccess', _70 => _70.some, 'call', _71 => _71((n) => n.type === notationType)])) {
1444
1801
  results.push({
1445
1802
  note: entry,
1446
1803
  part,
@@ -1459,8 +1816,8 @@ function findNotesWithNotation(score, notationType, options) {
1459
1816
  }
1460
1817
  function getHarmonies(score, options) {
1461
1818
  const results = [];
1462
- const startPart = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _63 => _63.partIndex]), () => ( 0));
1463
- const endPart = _optionalChain([options, 'optionalAccess', _64 => _64.partIndex]) !== void 0 ? options.partIndex + 1 : score.parts.length;
1819
+ const startPart = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _72 => _72.partIndex]), () => ( 0));
1820
+ const endPart = _optionalChain([options, 'optionalAccess', _73 => _73.partIndex]) !== void 0 ? options.partIndex + 1 : score.parts.length;
1464
1821
  for (let partIndex = startPart; partIndex < endPart; partIndex++) {
1465
1822
  const part = score.parts[partIndex];
1466
1823
  if (!part) continue;
@@ -1523,8 +1880,8 @@ function getChordProgression(score, options) {
1523
1880
  }
1524
1881
  function getLyrics(score, options) {
1525
1882
  const results = [];
1526
- const startPart = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _65 => _65.partIndex]), () => ( 0));
1527
- const endPart = _optionalChain([options, 'optionalAccess', _66 => _66.partIndex]) !== void 0 ? options.partIndex + 1 : score.parts.length;
1883
+ const startPart = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _74 => _74.partIndex]), () => ( 0));
1884
+ const endPart = _optionalChain([options, 'optionalAccess', _75 => _75.partIndex]) !== void 0 ? options.partIndex + 1 : score.parts.length;
1528
1885
  for (let partIndex = startPart; partIndex < endPart; partIndex++) {
1529
1886
  const part = score.parts[partIndex];
1530
1887
  if (!part) continue;
@@ -1536,7 +1893,7 @@ function getLyrics(score, options) {
1536
1893
  const position = entry.chord ? state.lastNonChordPosition : state.position;
1537
1894
  for (const lyric of entry.lyrics) {
1538
1895
  const verse = _nullishCoalesce(lyric.number, () => ( 1));
1539
- if (_optionalChain([options, 'optionalAccess', _67 => _67.verse]) !== void 0 && verse !== options.verse) {
1896
+ if (_optionalChain([options, 'optionalAccess', _76 => _76.verse]) !== void 0 && verse !== options.verse) {
1540
1897
  continue;
1541
1898
  }
1542
1899
  results.push({
@@ -1596,8 +1953,8 @@ function getLyricText(score, options) {
1596
1953
  }
1597
1954
  function getVerseCount(score, options) {
1598
1955
  const verses = /* @__PURE__ */ new Set();
1599
- const startPart = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _68 => _68.partIndex]), () => ( 0));
1600
- const endPart = _optionalChain([options, 'optionalAccess', _69 => _69.partIndex]) !== void 0 ? options.partIndex + 1 : score.parts.length;
1956
+ const startPart = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _77 => _77.partIndex]), () => ( 0));
1957
+ const endPart = _optionalChain([options, 'optionalAccess', _78 => _78.partIndex]) !== void 0 ? options.partIndex + 1 : score.parts.length;
1601
1958
  for (let partIndex = startPart; partIndex < endPart; partIndex++) {
1602
1959
  const part = score.parts[partIndex];
1603
1960
  if (!part) continue;
@@ -1615,7 +1972,7 @@ function getVerseCount(score, options) {
1615
1972
  }
1616
1973
  function getRepeatStructure(score, options) {
1617
1974
  const results = [];
1618
- const partIndex = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _70 => _70.partIndex]), () => ( 0));
1975
+ const partIndex = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _79 => _79.partIndex]), () => ( 0));
1619
1976
  const part = score.parts[partIndex];
1620
1977
  if (!part) return results;
1621
1978
  for (let measureIndex = 0; measureIndex < part.measures.length; measureIndex++) {
@@ -1638,8 +1995,8 @@ function getRepeatStructure(score, options) {
1638
1995
  }
1639
1996
  function findBarlines(score, options) {
1640
1997
  const results = [];
1641
- const startPart = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _71 => _71.partIndex]), () => ( 0));
1642
- const endPart = _optionalChain([options, 'optionalAccess', _72 => _72.partIndex]) !== void 0 ? options.partIndex + 1 : score.parts.length;
1998
+ const startPart = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _80 => _80.partIndex]), () => ( 0));
1999
+ const endPart = _optionalChain([options, 'optionalAccess', _81 => _81.partIndex]) !== void 0 ? options.partIndex + 1 : score.parts.length;
1643
2000
  for (let partIndex = startPart; partIndex < endPart; partIndex++) {
1644
2001
  const part = score.parts[partIndex];
1645
2002
  if (!part) continue;
@@ -1648,10 +2005,10 @@ function findBarlines(score, options) {
1648
2005
  const measureNumber = _nullishCoalesce(measure.number, () => ( String(measureIndex + 1)));
1649
2006
  if (measure.barlines) {
1650
2007
  for (const barline of measure.barlines) {
1651
- if (_optionalChain([options, 'optionalAccess', _73 => _73.style]) !== void 0 && barline.barStyle !== options.style) {
2008
+ if (_optionalChain([options, 'optionalAccess', _82 => _82.style]) !== void 0 && barline.barStyle !== options.style) {
1652
2009
  continue;
1653
2010
  }
1654
- if (_optionalChain([options, 'optionalAccess', _74 => _74.repeat]) !== void 0) {
2011
+ if (_optionalChain([options, 'optionalAccess', _83 => _83.repeat]) !== void 0) {
1655
2012
  const hasRepeat = barline.repeat !== void 0;
1656
2013
  if (hasRepeat !== options.repeat) {
1657
2014
  continue;
@@ -1671,8 +2028,8 @@ function findBarlines(score, options) {
1671
2028
  }
1672
2029
  function getEndings(score, options) {
1673
2030
  const results = [];
1674
- const startPart = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _75 => _75.partIndex]), () => ( 0));
1675
- const endPart = _optionalChain([options, 'optionalAccess', _76 => _76.partIndex]) !== void 0 ? options.partIndex + 1 : score.parts.length;
2031
+ const startPart = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _84 => _84.partIndex]), () => ( 0));
2032
+ const endPart = _optionalChain([options, 'optionalAccess', _85 => _85.partIndex]) !== void 0 ? options.partIndex + 1 : score.parts.length;
1676
2033
  for (let partIndex = startPart; partIndex < endPart; partIndex++) {
1677
2034
  const part = score.parts[partIndex];
1678
2035
  if (!part) continue;
@@ -1698,8 +2055,8 @@ function getEndings(score, options) {
1698
2055
  }
1699
2056
  function getKeyChanges(score, options) {
1700
2057
  const results = [];
1701
- const startPart = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _77 => _77.partIndex]), () => ( 0));
1702
- const endPart = _optionalChain([options, 'optionalAccess', _78 => _78.partIndex]) !== void 0 ? options.partIndex + 1 : score.parts.length;
2058
+ const startPart = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _86 => _86.partIndex]), () => ( 0));
2059
+ const endPart = _optionalChain([options, 'optionalAccess', _87 => _87.partIndex]) !== void 0 ? options.partIndex + 1 : score.parts.length;
1703
2060
  for (let partIndex = startPart; partIndex < endPart; partIndex++) {
1704
2061
  const part = score.parts[partIndex];
1705
2062
  if (!part) continue;
@@ -1708,7 +2065,7 @@ function getKeyChanges(score, options) {
1708
2065
  const measure = part.measures[measureIndex];
1709
2066
  const measureNumber = _nullishCoalesce(measure.number, () => ( String(measureIndex + 1)));
1710
2067
  const state = createPositionState();
1711
- if (_optionalChain([measure, 'access', _79 => _79.attributes, 'optionalAccess', _80 => _80.key])) {
2068
+ if (_optionalChain([measure, 'access', _88 => _88.attributes, 'optionalAccess', _89 => _89.key])) {
1712
2069
  const key = measure.attributes.key;
1713
2070
  if (!lastKey || lastKey.fifths !== key.fifths || lastKey.mode !== key.mode) {
1714
2071
  results.push({
@@ -1743,8 +2100,8 @@ function getKeyChanges(score, options) {
1743
2100
  }
1744
2101
  function getTimeChanges(score, options) {
1745
2102
  const results = [];
1746
- const startPart = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _81 => _81.partIndex]), () => ( 0));
1747
- const endPart = _optionalChain([options, 'optionalAccess', _82 => _82.partIndex]) !== void 0 ? options.partIndex + 1 : score.parts.length;
2103
+ const startPart = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _90 => _90.partIndex]), () => ( 0));
2104
+ const endPart = _optionalChain([options, 'optionalAccess', _91 => _91.partIndex]) !== void 0 ? options.partIndex + 1 : score.parts.length;
1748
2105
  for (let partIndex = startPart; partIndex < endPart; partIndex++) {
1749
2106
  const part = score.parts[partIndex];
1750
2107
  if (!part) continue;
@@ -1752,7 +2109,7 @@ function getTimeChanges(score, options) {
1752
2109
  for (let measureIndex = 0; measureIndex < part.measures.length; measureIndex++) {
1753
2110
  const measure = part.measures[measureIndex];
1754
2111
  const measureNumber = _nullishCoalesce(measure.number, () => ( String(measureIndex + 1)));
1755
- if (_optionalChain([measure, 'access', _83 => _83.attributes, 'optionalAccess', _84 => _84.time])) {
2112
+ if (_optionalChain([measure, 'access', _92 => _92.attributes, 'optionalAccess', _93 => _93.time])) {
1756
2113
  const time = measure.attributes.time;
1757
2114
  if (!lastTime || lastTime.beats !== time.beats || lastTime.beatType !== time.beatType) {
1758
2115
  results.push({
@@ -1784,8 +2141,8 @@ function getTimeChanges(score, options) {
1784
2141
  }
1785
2142
  function getClefChanges(score, options) {
1786
2143
  const results = [];
1787
- const startPart = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _85 => _85.partIndex]), () => ( 0));
1788
- const endPart = _optionalChain([options, 'optionalAccess', _86 => _86.partIndex]) !== void 0 ? options.partIndex + 1 : score.parts.length;
2144
+ const startPart = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _94 => _94.partIndex]), () => ( 0));
2145
+ const endPart = _optionalChain([options, 'optionalAccess', _95 => _95.partIndex]) !== void 0 ? options.partIndex + 1 : score.parts.length;
1789
2146
  for (let partIndex = startPart; partIndex < endPart; partIndex++) {
1790
2147
  const part = score.parts[partIndex];
1791
2148
  if (!part) continue;
@@ -1794,10 +2151,10 @@ function getClefChanges(score, options) {
1794
2151
  const measure = part.measures[measureIndex];
1795
2152
  const measureNumber = _nullishCoalesce(measure.number, () => ( String(measureIndex + 1)));
1796
2153
  const state = createPositionState();
1797
- if (_optionalChain([measure, 'access', _87 => _87.attributes, 'optionalAccess', _88 => _88.clef])) {
2154
+ if (_optionalChain([measure, 'access', _96 => _96.attributes, 'optionalAccess', _97 => _97.clef])) {
1798
2155
  for (const clef of measure.attributes.clef) {
1799
2156
  const staff = _nullishCoalesce(clef.staff, () => ( 1));
1800
- if (_optionalChain([options, 'optionalAccess', _89 => _89.staff]) !== void 0 && staff !== options.staff) {
2157
+ if (_optionalChain([options, 'optionalAccess', _98 => _98.staff]) !== void 0 && staff !== options.staff) {
1801
2158
  continue;
1802
2159
  }
1803
2160
  const lastClef = lastClefs.get(staff);
@@ -1818,7 +2175,7 @@ function getClefChanges(score, options) {
1818
2175
  if (entry.type === "attributes" && entry.attributes.clef) {
1819
2176
  for (const clef of entry.attributes.clef) {
1820
2177
  const staff = _nullishCoalesce(clef.staff, () => ( 1));
1821
- if (_optionalChain([options, 'optionalAccess', _90 => _90.staff]) !== void 0 && staff !== options.staff) {
2178
+ if (_optionalChain([options, 'optionalAccess', _99 => _99.staff]) !== void 0 && staff !== options.staff) {
1822
2179
  continue;
1823
2180
  }
1824
2181
  const lastClef = lastClefs.get(staff);
@@ -1881,14 +2238,14 @@ function getDivisions(score, options) {
1881
2238
  const m = part.measures[i];
1882
2239
  const mNum = parseInt(m.number, 10);
1883
2240
  if (!isNaN(mNum) && mNum > targetMeasure) break;
1884
- if (_optionalChain([m, 'access', _91 => _91.attributes, 'optionalAccess', _92 => _92.divisions]) !== void 0) {
2241
+ if (_optionalChain([m, 'access', _100 => _100.attributes, 'optionalAccess', _101 => _101.divisions]) !== void 0) {
1885
2242
  }
1886
2243
  }
1887
2244
  let divisions = 1;
1888
2245
  for (const m of part.measures) {
1889
2246
  const mNum = parseInt(m.number, 10);
1890
2247
  if (!isNaN(mNum) && mNum > targetMeasure) break;
1891
- if (_optionalChain([m, 'access', _93 => _93.attributes, 'optionalAccess', _94 => _94.divisions]) !== void 0) {
2248
+ if (_optionalChain([m, 'access', _102 => _102.attributes, 'optionalAccess', _103 => _103.divisions]) !== void 0) {
1892
2249
  divisions = m.attributes.divisions;
1893
2250
  }
1894
2251
  }
@@ -1949,7 +2306,7 @@ function getDuration(score) {
1949
2306
  let totalDuration = 0;
1950
2307
  let divisions = 1;
1951
2308
  for (const measure of part.measures) {
1952
- if (_optionalChain([measure, 'access', _95 => _95.attributes, 'optionalAccess', _96 => _96.divisions]) !== void 0) {
2309
+ if (_optionalChain([measure, 'access', _104 => _104.attributes, 'optionalAccess', _105 => _105.divisions]) !== void 0) {
1953
2310
  divisions = measure.attributes.divisions;
1954
2311
  }
1955
2312
  let measureDuration = 0;
@@ -1978,7 +2335,7 @@ function hasMultipleStaves(score, partIndex = 0) {
1978
2335
  const part = score.parts[partIndex];
1979
2336
  if (!part) return false;
1980
2337
  for (const measure of part.measures) {
1981
- if (_optionalChain([measure, 'access', _97 => _97.attributes, 'optionalAccess', _98 => _98.staves]) !== void 0 && measure.attributes.staves > 1) {
2338
+ if (_optionalChain([measure, 'access', _106 => _106.attributes, 'optionalAccess', _107 => _107.staves]) !== void 0 && measure.attributes.staves > 1) {
1982
2339
  return true;
1983
2340
  }
1984
2341
  }
@@ -1988,7 +2345,7 @@ function getStaveCount(score, partIndex = 0) {
1988
2345
  const part = score.parts[partIndex];
1989
2346
  if (!part) return 1;
1990
2347
  for (const measure of part.measures) {
1991
- if (_optionalChain([measure, 'access', _99 => _99.attributes, 'optionalAccess', _100 => _100.staves]) !== void 0) {
2348
+ if (_optionalChain([measure, 'access', _108 => _108.attributes, 'optionalAccess', _109 => _109.staves]) !== void 0) {
1992
2349
  return measure.attributes.staves;
1993
2350
  }
1994
2351
  }
@@ -2147,4 +2504,9 @@ function pitchesEqual(a, b) {
2147
2504
 
2148
2505
 
2149
2506
 
2150
- exports.extractPlaybackControls = extractPlaybackControls; exports.generatePlaybackSequence = generatePlaybackSequence; exports.hasPlaybackControls = hasPlaybackControls; exports.STEPS = STEPS; exports.STEP_SEMITONES = STEP_SEMITONES; exports.pitchToSemitone = pitchToSemitone; exports.getAccidentalsInMeasure = getAccidentalsInMeasure; exports.semitoneToKeyAwarePitch = semitoneToKeyAwarePitch; exports.determineAccidental = determineAccidental; exports.getAbsolutePositionForNote = getAbsolutePositionForNote; exports.getMeasureEndPosition = getMeasureEndPosition; exports.getNotesForVoice = getNotesForVoice; exports.getNotesForStaff = getNotesForStaff; exports.groupByVoice = groupByVoice; exports.groupByStaff = groupByStaff; exports.getAbsolutePosition = getAbsolutePosition; exports.withAbsolutePositions = withAbsolutePositions; exports.getChords = getChords; exports.iterateNotes = iterateNotes; exports.getAllNotes = getAllNotes; exports.getVoices = getVoices; exports.getStaves = getStaves; exports.hasNotes = hasNotes; exports.isRestMeasure = isRestMeasure; exports.getNormalizedPosition = getNormalizedPosition; exports.getNormalizedDuration = getNormalizedDuration; exports.getEntriesForStaff = getEntriesForStaff; exports.buildVoiceToStaffMap = buildVoiceToStaffMap; exports.buildVoiceToStaffMapForPart = buildVoiceToStaffMapForPart; exports.inferStaff = inferStaff; exports.getEffectiveStaff = getEffectiveStaff; exports.getClefForStaff = getClefForStaff; exports.getVoicesForStaff = getVoicesForStaff; exports.getStaffRange = getStaffRange; exports.getEntriesAtPosition = getEntriesAtPosition; exports.getNotesAtPosition = getNotesAtPosition; exports.getEntriesInRange = getEntriesInRange; exports.getNotesInRange = getNotesInRange; exports.getVerticalSlice = getVerticalSlice; exports.getVoiceLine = getVoiceLine; exports.getVoiceLineInRange = getVoiceLineInRange; exports.iterateEntries = iterateEntries; exports.getNextNote = getNextNote; exports.getPrevNote = getPrevNote; exports.getAdjacentNotes = getAdjacentNotes; exports.getDirections = getDirections; exports.getDirectionsAtPosition = getDirectionsAtPosition; exports.findDirectionsByType = findDirectionsByType; exports.getDynamics = getDynamics; exports.getTempoMarkings = getTempoMarkings; exports.getPedalMarkings = getPedalMarkings; exports.getWedges = getWedges; exports.getOctaveShifts = getOctaveShifts; exports.getTiedNoteGroups = getTiedNoteGroups; exports.getSlurSpans = getSlurSpans; exports.getTupletGroups = getTupletGroups; exports.getBeamGroups = getBeamGroups; exports.findNotesWithNotation = findNotesWithNotation; exports.getHarmonies = getHarmonies; exports.getHarmonyAtPosition = getHarmonyAtPosition; exports.getChordProgression = getChordProgression; exports.getLyrics = getLyrics; exports.getLyricText = getLyricText; exports.getVerseCount = getVerseCount; exports.getRepeatStructure = getRepeatStructure; exports.findBarlines = findBarlines; exports.getEndings = getEndings; exports.getKeyChanges = getKeyChanges; exports.getTimeChanges = getTimeChanges; exports.getClefChanges = getClefChanges; exports.getStructuralChanges = getStructuralChanges; exports.getPartByIndex = getPartByIndex; exports.getPartCount = getPartCount; exports.getPartIds = getPartIds; exports.getMeasure = getMeasure; exports.getMeasureByIndex = getMeasureByIndex; exports.getMeasureCount = getMeasureCount; exports.getDivisions = getDivisions; exports.getAttributesAtMeasure = getAttributesAtMeasure; exports.findNotes = findNotes; exports.getDuration = getDuration; exports.getPartById = getPartById; exports.getPartIndex = getPartIndex; exports.hasMultipleStaves = hasMultipleStaves; exports.getStaveCount = getStaveCount; exports.measureRoundtrip = measureRoundtrip; exports.countNotes = countNotes; exports.scoresEqual = scoresEqual;
2507
+
2508
+
2509
+
2510
+
2511
+
2512
+ exports.extractPlaybackControls = extractPlaybackControls; exports.generatePlaybackSequence = generatePlaybackSequence; exports.hasPlaybackControls = hasPlaybackControls; exports.measureEndTick = measureEndTick; exports.buildGridTimeline = buildGridTimeline; exports.bpmToUsPerQuarter = bpmToUsPerQuarter; exports.buildTimingSidecar = buildTimingSidecar; exports.generatePlaybackTimeline = generatePlaybackTimeline; exports.STEPS = STEPS; exports.STEP_SEMITONES = STEP_SEMITONES; exports.pitchToSemitone = pitchToSemitone; exports.getAccidentalsInMeasure = getAccidentalsInMeasure; exports.semitoneToKeyAwarePitch = semitoneToKeyAwarePitch; exports.determineAccidental = determineAccidental; exports.getAbsolutePositionForNote = getAbsolutePositionForNote; exports.getMeasureEndPosition = getMeasureEndPosition; exports.getNotesForVoice = getNotesForVoice; exports.getNotesForStaff = getNotesForStaff; exports.groupByVoice = groupByVoice; exports.groupByStaff = groupByStaff; exports.getAbsolutePosition = getAbsolutePosition; exports.withAbsolutePositions = withAbsolutePositions; exports.getChords = getChords; exports.iterateNotes = iterateNotes; exports.getAllNotes = getAllNotes; exports.getVoices = getVoices; exports.getStaves = getStaves; exports.hasNotes = hasNotes; exports.isRestMeasure = isRestMeasure; exports.getNormalizedPosition = getNormalizedPosition; exports.getNormalizedDuration = getNormalizedDuration; exports.getEntriesForStaff = getEntriesForStaff; exports.buildVoiceToStaffMap = buildVoiceToStaffMap; exports.buildVoiceToStaffMapForPart = buildVoiceToStaffMapForPart; exports.inferStaff = inferStaff; exports.getEffectiveStaff = getEffectiveStaff; exports.getClefForStaff = getClefForStaff; exports.getVoicesForStaff = getVoicesForStaff; exports.getStaffRange = getStaffRange; exports.getEntriesAtPosition = getEntriesAtPosition; exports.getNotesAtPosition = getNotesAtPosition; exports.getEntriesInRange = getEntriesInRange; exports.getNotesInRange = getNotesInRange; exports.getVerticalSlice = getVerticalSlice; exports.getVoiceLine = getVoiceLine; exports.getVoiceLineInRange = getVoiceLineInRange; exports.iterateEntries = iterateEntries; exports.getNextNote = getNextNote; exports.getPrevNote = getPrevNote; exports.getAdjacentNotes = getAdjacentNotes; exports.getDirections = getDirections; exports.getDirectionsAtPosition = getDirectionsAtPosition; exports.findDirectionsByType = findDirectionsByType; exports.getDynamics = getDynamics; exports.getTempoMarkings = getTempoMarkings; exports.getPedalMarkings = getPedalMarkings; exports.getWedges = getWedges; exports.getOctaveShifts = getOctaveShifts; exports.getTiedNoteGroups = getTiedNoteGroups; exports.getSlurSpans = getSlurSpans; exports.getTupletGroups = getTupletGroups; exports.getBeamGroups = getBeamGroups; exports.findNotesWithNotation = findNotesWithNotation; exports.getHarmonies = getHarmonies; exports.getHarmonyAtPosition = getHarmonyAtPosition; exports.getChordProgression = getChordProgression; exports.getLyrics = getLyrics; exports.getLyricText = getLyricText; exports.getVerseCount = getVerseCount; exports.getRepeatStructure = getRepeatStructure; exports.findBarlines = findBarlines; exports.getEndings = getEndings; exports.getKeyChanges = getKeyChanges; exports.getTimeChanges = getTimeChanges; exports.getClefChanges = getClefChanges; exports.getStructuralChanges = getStructuralChanges; exports.getPartByIndex = getPartByIndex; exports.getPartCount = getPartCount; exports.getPartIds = getPartIds; exports.getMeasure = getMeasure; exports.getMeasureByIndex = getMeasureByIndex; exports.getMeasureCount = getMeasureCount; exports.getDivisions = getDivisions; exports.getAttributesAtMeasure = getAttributesAtMeasure; exports.findNotes = findNotes; exports.getDuration = getDuration; exports.getPartById = getPartById; exports.getPartIndex = getPartIndex; exports.hasMultipleStaves = hasMultipleStaves; exports.getStaveCount = getStaveCount; exports.measureRoundtrip = measureRoundtrip; exports.countNotes = countNotes; exports.scoresEqual = scoresEqual;