musicxml-io 0.7.1 → 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.
@@ -510,6 +510,10 @@ function hasPlaybackControls(score, options) {
510
510
  }
511
511
 
512
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;
513
517
  function metronomeBpm(perMinute) {
514
518
  if (perMinute === void 0) return null;
515
519
  const bpm = typeof perMinute === "number" ? perMinute : parseFloat(perMinute);
@@ -562,39 +566,112 @@ function measureEndTick(measure, part, divisions, measureStartTick, maxPosition,
562
566
  }
563
567
  return measureStartTick + actualTicks;
564
568
  }
565
- function buildGridTimeline(score, ticksPerQuarterNote, sequence) {
566
- const tempoEvents = [];
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 = [];
567
591
  const measures = [];
592
+ const rampMarkers = [];
593
+ const stretches = [];
568
594
  if (score.parts.length === 0) {
569
- return { tempoEvents, measures, totalTicks: 0 };
595
+ return { tempoEvents: [], measures, totalTicks: 0, expressions: [] };
570
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));
571
602
  const part = score.parts[0];
572
603
  let divisions = 1;
573
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
+ };
574
611
  for (const { measureIndex, repeatIteration } of sequence) {
575
612
  const measure = part.measures[measureIndex];
576
613
  if (!measure) continue;
577
- if (_optionalChain([measure, 'access', _7 => _7.attributes, 'optionalAccess', _8 => _8.divisions])) {
614
+ if (_optionalChain([measure, 'access', _10 => _10.attributes, 'optionalAccess', _11 => _11.divisions])) {
578
615
  divisions = measure.attributes.divisions;
579
616
  }
580
617
  const measureStartTick = currentTick;
581
618
  let position = 0;
619
+ let chordBasePosition = 0;
582
620
  const tickAt = (pos) => measureStartTick + Math.round(pos * ticksPerQuarterNote / divisions);
583
621
  for (const entry of measure.entries) {
584
622
  if (entry.type === "direction") {
585
623
  for (const dirType of entry.directionTypes) {
586
624
  if (dirType.kind === "metronome") {
587
625
  const bpm = metronomeBpm(dirType.perMinute);
588
- if (bpm !== null) tempoEvents.push({ tick: tickAt(position), bpm });
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 });
589
633
  }
590
634
  }
591
- if (_optionalChain([entry, 'access', _9 => _9.sound, 'optionalAccess', _10 => _10.tempo])) {
592
- tempoEvents.push({ tick: tickAt(position), bpm: entry.sound.tempo });
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;
593
638
  }
594
639
  } else if (entry.type === "sound") {
595
- if (entry.tempo) tempoEvents.push({ tick: tickAt(position), bpm: entry.tempo });
596
- } else if (entry.type === "note" && !entry.chord) {
597
- position += entry.duration;
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
+ }
598
675
  } else if (entry.type === "backup") {
599
676
  position -= entry.duration;
600
677
  } else if (entry.type === "forward") {
@@ -618,28 +695,112 @@ function buildGridTimeline(score, ticksPerQuarterNote, sequence) {
618
695
  });
619
696
  currentTick = endTick;
620
697
  }
621
- return { tempoEvents, measures, totalTicks: currentTick };
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);
622
780
  }
623
781
  function makeTickToSec(tempoEvents, defaultTempo, ticksPerQuarterNote) {
624
782
  const sorted = [...tempoEvents].sort((a, b) => a.tick - b.tick);
625
783
  const startBpm = sorted.length > 0 && sorted[0].tick === 0 ? sorted[0].bpm : defaultTempo;
626
- const changes = [{ tick: 0, bpm: startBpm }];
784
+ const changes = [
785
+ { tick: 0, usPerQuarter: bpmToUsPerQuarter(startBpm) }
786
+ ];
627
787
  let lastBpm = startBpm;
628
788
  for (const ev of sorted) {
629
789
  if (ev.tick === 0) continue;
630
790
  if (ev.bpm === lastBpm) continue;
631
- changes.push({ tick: ev.tick, bpm: ev.bpm });
791
+ changes.push({ tick: ev.tick, usPerQuarter: bpmToUsPerQuarter(ev.bpm) });
632
792
  lastBpm = ev.bpm;
633
793
  }
794
+ const secPerTick = (usPerQuarter) => usPerQuarter / 1e6 / ticksPerQuarterNote;
634
795
  const cumSec = [0];
635
796
  for (let i = 1; i < changes.length; i++) {
636
797
  const dTick = changes[i].tick - changes[i - 1].tick;
637
- cumSec[i] = cumSec[i - 1] + dTick / ticksPerQuarterNote * (60 / changes[i - 1].bpm);
798
+ cumSec[i] = cumSec[i - 1] + dTick * secPerTick(changes[i - 1].usPerQuarter);
638
799
  }
639
800
  return (tick) => {
640
801
  let i = changes.length - 1;
641
802
  while (i > 0 && changes[i].tick > tick) i--;
642
- return cumSec[i] + (tick - changes[i].tick) / ticksPerQuarterNote * (60 / changes[i].bpm);
803
+ return cumSec[i] + (tick - changes[i].tick) * secPerTick(changes[i].usPerQuarter);
643
804
  };
644
805
  }
645
806
  function buildTimingSidecar(grid, defaultTempo, ticksPerQuarterNote) {
@@ -676,18 +837,32 @@ function buildTimingSidecar(grid, defaultTempo, ticksPerQuarterNote) {
676
837
  repeatIteration: last ? last.repeatIteration : 0
677
838
  });
678
839
  breakpoints.sort((a, b) => a.midiSec - b.midiSec || a.quarterPos - b.quarterPos);
679
- return {
840
+ const sidecar = {
680
841
  version: "1",
681
842
  durationSec: tickToSec(grid.totalTicks),
682
843
  ticksPerQuarterNote,
683
844
  breakpoints
684
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;
685
854
  }
686
855
  function generatePlaybackTimeline(score, options = {}) {
687
856
  const ticksPerQuarterNote = _nullishCoalesce(options.ticksPerQuarterNote, () => ( 480));
688
857
  const defaultTempo = _nullishCoalesce(options.defaultTempo, () => ( 120));
689
858
  const sequence = generatePlaybackSequence(score);
690
- const grid = buildGridTimeline(score, ticksPerQuarterNote, sequence);
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
+ });
691
866
  return buildTimingSidecar(grid, defaultTempo, ticksPerQuarterNote);
692
867
  }
693
868
 
@@ -828,7 +1003,7 @@ function isRestMeasure(measure) {
828
1003
  }
829
1004
  function getNormalizedPosition(note, measure, options) {
830
1005
  const absolutePosition = getAbsolutePosition(note, measure);
831
- const currentDivisions = _nullishCoalesce(_nullishCoalesce(options.currentDivisions, () => ( _optionalChain([measure, 'access', _11 => _11.attributes, 'optionalAccess', _12 => _12.divisions]))), () => ( 1));
1006
+ const currentDivisions = _nullishCoalesce(_nullishCoalesce(options.currentDivisions, () => ( _optionalChain([measure, 'access', _14 => _14.attributes, 'optionalAccess', _15 => _15.divisions]))), () => ( 1));
832
1007
  return absolutePosition * options.baseDivisions / currentDivisions;
833
1008
  }
834
1009
  function getNormalizedDuration(note, options) {
@@ -921,7 +1096,7 @@ function getClefForStaff(score, options) {
921
1096
  }
922
1097
  }
923
1098
  }
924
- if (_optionalChain([measure, 'access', _13 => _13.attributes, 'optionalAccess', _14 => _14.clef])) {
1099
+ if (_optionalChain([measure, 'access', _16 => _16.attributes, 'optionalAccess', _17 => _17.clef])) {
925
1100
  for (const clef of measure.attributes.clef) {
926
1101
  if ((_nullishCoalesce(clef.staff, () => ( 1))) === options.staff) {
927
1102
  return clef;
@@ -949,7 +1124,7 @@ function getStaffRange(score, partIndex) {
949
1124
  let min = 1;
950
1125
  let max = 1;
951
1126
  for (const measure of part.measures) {
952
- if (_optionalChain([measure, 'access', _15 => _15.attributes, 'optionalAccess', _16 => _16.staves]) !== void 0) {
1127
+ if (_optionalChain([measure, 'access', _18 => _18.attributes, 'optionalAccess', _19 => _19.staves]) !== void 0) {
953
1128
  max = Math.max(max, measure.attributes.staves);
954
1129
  }
955
1130
  for (const entry of measure.entries) {
@@ -967,15 +1142,15 @@ function getEntriesAtPosition(measure, position, options) {
967
1142
  const currentPosition = entry.type === "note" && entry.chord ? state.lastNonChordPosition : state.position;
968
1143
  if (currentPosition === position) {
969
1144
  if (entry.type === "note") {
970
- if (_optionalChain([options, 'optionalAccess', _17 => _17.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) {
971
1146
  updatePositionForEntry(state, entry);
972
1147
  continue;
973
1148
  }
974
- if (_optionalChain([options, 'optionalAccess', _18 => _18.voice]) !== void 0 && entry.voice !== options.voice) {
1149
+ if (_optionalChain([options, 'optionalAccess', _21 => _21.voice]) !== void 0 && entry.voice !== options.voice) {
975
1150
  updatePositionForEntry(state, entry);
976
1151
  continue;
977
1152
  }
978
- if (_optionalChain([options, 'optionalAccess', _19 => _19.includeChordNotes]) === false && entry.chord) {
1153
+ if (_optionalChain([options, 'optionalAccess', _22 => _22.includeChordNotes]) === false && entry.chord) {
979
1154
  updatePositionForEntry(state, entry);
980
1155
  continue;
981
1156
  }
@@ -998,15 +1173,15 @@ function getEntriesInRange(measure, range, options) {
998
1173
  const currentPosition = entry.type === "note" && entry.chord ? state.lastNonChordPosition : state.position;
999
1174
  if (currentPosition >= range.start && currentPosition < range.end) {
1000
1175
  if (entry.type === "note") {
1001
- if (_optionalChain([options, 'optionalAccess', _20 => _20.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) {
1002
1177
  updatePositionForEntry(state, entry);
1003
1178
  continue;
1004
1179
  }
1005
- if (_optionalChain([options, 'optionalAccess', _21 => _21.voice]) !== void 0 && entry.voice !== options.voice) {
1180
+ if (_optionalChain([options, 'optionalAccess', _24 => _24.voice]) !== void 0 && entry.voice !== options.voice) {
1006
1181
  updatePositionForEntry(state, entry);
1007
1182
  continue;
1008
1183
  }
1009
- if (_optionalChain([options, 'optionalAccess', _22 => _22.includeChordNotes]) === false && entry.chord) {
1184
+ if (_optionalChain([options, 'optionalAccess', _25 => _25.includeChordNotes]) === false && entry.chord) {
1010
1185
  updatePositionForEntry(state, entry);
1011
1186
  continue;
1012
1187
  }
@@ -1212,13 +1387,13 @@ function getAdjacentNotes(score, context) {
1212
1387
  }
1213
1388
  function getDirections(score, options) {
1214
1389
  const results = [];
1215
- const startPart = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _23 => _23.partIndex]), () => ( 0));
1216
- const endPart = _optionalChain([options, 'optionalAccess', _24 => _24.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;
1217
1392
  for (let partIndex = startPart; partIndex < endPart; partIndex++) {
1218
1393
  const part = score.parts[partIndex];
1219
1394
  if (!part) continue;
1220
- const startMeasure = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _25 => _25.measureIndex]), () => ( 0));
1221
- const endMeasure = _optionalChain([options, 'optionalAccess', _26 => _26.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;
1222
1397
  for (let measureIndex = startMeasure; measureIndex < endMeasure; measureIndex++) {
1223
1398
  const measure = part.measures[measureIndex];
1224
1399
  if (!measure) continue;
@@ -1259,8 +1434,8 @@ function findDirectionsByType(score, kind) {
1259
1434
  }
1260
1435
  function getDynamics(score, options) {
1261
1436
  const results = [];
1262
- const startPart = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _27 => _27.partIndex]), () => ( 0));
1263
- const endPart = _optionalChain([options, 'optionalAccess', _28 => _28.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;
1264
1439
  for (let partIndex = startPart; partIndex < endPart; partIndex++) {
1265
1440
  const part = score.parts[partIndex];
1266
1441
  if (!part) continue;
@@ -1321,8 +1496,8 @@ function getTempoMarkings(score) {
1321
1496
  }
1322
1497
  function getPedalMarkings(score, options) {
1323
1498
  const results = [];
1324
- const startPart = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _29 => _29.partIndex]), () => ( 0));
1325
- const endPart = _optionalChain([options, 'optionalAccess', _30 => _30.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;
1326
1501
  for (let partIndex = startPart; partIndex < endPart; partIndex++) {
1327
1502
  const part = score.parts[partIndex];
1328
1503
  if (!part) continue;
@@ -1351,8 +1526,8 @@ function getPedalMarkings(score, options) {
1351
1526
  }
1352
1527
  function getWedges(score, options) {
1353
1528
  const results = [];
1354
- const startPart = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _31 => _31.partIndex]), () => ( 0));
1355
- const endPart = _optionalChain([options, 'optionalAccess', _32 => _32.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;
1356
1531
  for (let partIndex = startPart; partIndex < endPart; partIndex++) {
1357
1532
  const part = score.parts[partIndex];
1358
1533
  if (!part) continue;
@@ -1381,8 +1556,8 @@ function getWedges(score, options) {
1381
1556
  }
1382
1557
  function getOctaveShifts(score, options) {
1383
1558
  const results = [];
1384
- const startPart = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _33 => _33.partIndex]), () => ( 0));
1385
- const endPart = _optionalChain([options, 'optionalAccess', _34 => _34.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;
1386
1561
  for (let partIndex = startPart; partIndex < endPart; partIndex++) {
1387
1562
  const part = score.parts[partIndex];
1388
1563
  if (!part) continue;
@@ -1412,8 +1587,8 @@ function getOctaveShifts(score, options) {
1412
1587
  }
1413
1588
  function getTiedNoteGroups(score, options) {
1414
1589
  const results = [];
1415
- const startPart = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _35 => _35.partIndex]), () => ( 0));
1416
- const endPart = _optionalChain([options, 'optionalAccess', _36 => _36.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;
1417
1592
  for (let partIndex = startPart; partIndex < endPart; partIndex++) {
1418
1593
  const part = score.parts[partIndex];
1419
1594
  if (!part) continue;
@@ -1433,8 +1608,8 @@ function getTiedNoteGroups(score, options) {
1433
1608
  measureIndex,
1434
1609
  position
1435
1610
  };
1436
- const hasTieStart = _optionalChain([entry, 'access', _37 => _37.tie, 'optionalAccess', _38 => _38.type]) === "start" || _optionalChain([entry, 'access', _39 => _39.ties, 'optionalAccess', _40 => _40.some, 'call', _41 => _41((t) => t.type === "start")]) || _optionalChain([entry, 'access', _42 => _42.notations, 'optionalAccess', _43 => _43.some, 'call', _44 => _44((n) => n.type === "tied" && n.tiedType === "start")]);
1437
- const hasTieStop = _optionalChain([entry, 'access', _45 => _45.tie, 'optionalAccess', _46 => _46.type]) === "stop" || _optionalChain([entry, 'access', _47 => _47.ties, 'optionalAccess', _48 => _48.some, 'call', _49 => _49((t) => t.type === "stop")]) || _optionalChain([entry, 'access', _50 => _50.notations, 'optionalAccess', _51 => _51.some, 'call', _52 => _52((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")]);
1438
1613
  if (hasTieStop && pendingTies.has(pitchKey)) {
1439
1614
  const group = pendingTies.get(pitchKey);
1440
1615
  group.push(context);
@@ -1455,8 +1630,8 @@ function getTiedNoteGroups(score, options) {
1455
1630
  }
1456
1631
  function getSlurSpans(score, options) {
1457
1632
  const results = [];
1458
- const startPart = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _53 => _53.partIndex]), () => ( 0));
1459
- const endPart = _optionalChain([options, 'optionalAccess', _54 => _54.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;
1460
1635
  for (let partIndex = startPart; partIndex < endPart; partIndex++) {
1461
1636
  const part = score.parts[partIndex];
1462
1637
  if (!part) continue;
@@ -1512,8 +1687,8 @@ function getSlurSpans(score, options) {
1512
1687
  }
1513
1688
  function getTupletGroups(score, options) {
1514
1689
  const results = [];
1515
- const startPart = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _55 => _55.partIndex]), () => ( 0));
1516
- const endPart = _optionalChain([options, 'optionalAccess', _56 => _56.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;
1517
1692
  for (let partIndex = startPart; partIndex < endPart; partIndex++) {
1518
1693
  const part = score.parts[partIndex];
1519
1694
  if (!part) continue;
@@ -1537,8 +1712,8 @@ function getTupletGroups(score, options) {
1537
1712
  if (notation.type === "tuplet") {
1538
1713
  const tupletNumber = _nullishCoalesce(notation.number, () => ( 1));
1539
1714
  if (notation.tupletType === "start") {
1540
- const actualNotes = _nullishCoalesce(_optionalChain([entry, 'access', _57 => _57.timeModification, 'optionalAccess', _58 => _58.actualNotes]), () => ( 3));
1541
- const normalNotes = _nullishCoalesce(_optionalChain([entry, 'access', _59 => _59.timeModification, 'optionalAccess', _60 => _60.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));
1542
1717
  pendingTuplets.set(tupletNumber, {
1543
1718
  notes: [context],
1544
1719
  actualNotes,
@@ -1558,7 +1733,7 @@ function getTupletGroups(score, options) {
1558
1733
  }
1559
1734
  }
1560
1735
  }
1561
- if (entry.timeModification && !_optionalChain([entry, 'access', _61 => _61.notations, 'optionalAccess', _62 => _62.some, 'call', _63 => _63((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")])) {
1562
1737
  for (const [, pending] of pendingTuplets) {
1563
1738
  if (entry.timeModification.actualNotes === pending.actualNotes && entry.timeModification.normalNotes === pending.normalNotes) {
1564
1739
  pending.notes.push(context);
@@ -1611,8 +1786,8 @@ function getBeamGroups(measure) {
1611
1786
  }
1612
1787
  function findNotesWithNotation(score, notationType, options) {
1613
1788
  const results = [];
1614
- const startPart = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _64 => _64.partIndex]), () => ( 0));
1615
- const endPart = _optionalChain([options, 'optionalAccess', _65 => _65.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;
1616
1791
  for (let partIndex = startPart; partIndex < endPart; partIndex++) {
1617
1792
  const part = score.parts[partIndex];
1618
1793
  if (!part) continue;
@@ -1622,7 +1797,7 @@ function findNotesWithNotation(score, notationType, options) {
1622
1797
  for (const entry of measure.entries) {
1623
1798
  if (entry.type === "note") {
1624
1799
  const position = entry.chord ? state.lastNonChordPosition : state.position;
1625
- if (_optionalChain([entry, 'access', _66 => _66.notations, 'optionalAccess', _67 => _67.some, 'call', _68 => _68((n) => n.type === notationType)])) {
1800
+ if (_optionalChain([entry, 'access', _69 => _69.notations, 'optionalAccess', _70 => _70.some, 'call', _71 => _71((n) => n.type === notationType)])) {
1626
1801
  results.push({
1627
1802
  note: entry,
1628
1803
  part,
@@ -1641,8 +1816,8 @@ function findNotesWithNotation(score, notationType, options) {
1641
1816
  }
1642
1817
  function getHarmonies(score, options) {
1643
1818
  const results = [];
1644
- const startPart = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _69 => _69.partIndex]), () => ( 0));
1645
- const endPart = _optionalChain([options, 'optionalAccess', _70 => _70.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;
1646
1821
  for (let partIndex = startPart; partIndex < endPart; partIndex++) {
1647
1822
  const part = score.parts[partIndex];
1648
1823
  if (!part) continue;
@@ -1705,8 +1880,8 @@ function getChordProgression(score, options) {
1705
1880
  }
1706
1881
  function getLyrics(score, options) {
1707
1882
  const results = [];
1708
- const startPart = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _71 => _71.partIndex]), () => ( 0));
1709
- const endPart = _optionalChain([options, 'optionalAccess', _72 => _72.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;
1710
1885
  for (let partIndex = startPart; partIndex < endPart; partIndex++) {
1711
1886
  const part = score.parts[partIndex];
1712
1887
  if (!part) continue;
@@ -1718,7 +1893,7 @@ function getLyrics(score, options) {
1718
1893
  const position = entry.chord ? state.lastNonChordPosition : state.position;
1719
1894
  for (const lyric of entry.lyrics) {
1720
1895
  const verse = _nullishCoalesce(lyric.number, () => ( 1));
1721
- if (_optionalChain([options, 'optionalAccess', _73 => _73.verse]) !== void 0 && verse !== options.verse) {
1896
+ if (_optionalChain([options, 'optionalAccess', _76 => _76.verse]) !== void 0 && verse !== options.verse) {
1722
1897
  continue;
1723
1898
  }
1724
1899
  results.push({
@@ -1778,8 +1953,8 @@ function getLyricText(score, options) {
1778
1953
  }
1779
1954
  function getVerseCount(score, options) {
1780
1955
  const verses = /* @__PURE__ */ new Set();
1781
- const startPart = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _74 => _74.partIndex]), () => ( 0));
1782
- const endPart = _optionalChain([options, 'optionalAccess', _75 => _75.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;
1783
1958
  for (let partIndex = startPart; partIndex < endPart; partIndex++) {
1784
1959
  const part = score.parts[partIndex];
1785
1960
  if (!part) continue;
@@ -1797,7 +1972,7 @@ function getVerseCount(score, options) {
1797
1972
  }
1798
1973
  function getRepeatStructure(score, options) {
1799
1974
  const results = [];
1800
- const partIndex = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _76 => _76.partIndex]), () => ( 0));
1975
+ const partIndex = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _79 => _79.partIndex]), () => ( 0));
1801
1976
  const part = score.parts[partIndex];
1802
1977
  if (!part) return results;
1803
1978
  for (let measureIndex = 0; measureIndex < part.measures.length; measureIndex++) {
@@ -1820,8 +1995,8 @@ function getRepeatStructure(score, options) {
1820
1995
  }
1821
1996
  function findBarlines(score, options) {
1822
1997
  const results = [];
1823
- const startPart = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _77 => _77.partIndex]), () => ( 0));
1824
- const endPart = _optionalChain([options, 'optionalAccess', _78 => _78.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;
1825
2000
  for (let partIndex = startPart; partIndex < endPart; partIndex++) {
1826
2001
  const part = score.parts[partIndex];
1827
2002
  if (!part) continue;
@@ -1830,10 +2005,10 @@ function findBarlines(score, options) {
1830
2005
  const measureNumber = _nullishCoalesce(measure.number, () => ( String(measureIndex + 1)));
1831
2006
  if (measure.barlines) {
1832
2007
  for (const barline of measure.barlines) {
1833
- if (_optionalChain([options, 'optionalAccess', _79 => _79.style]) !== void 0 && barline.barStyle !== options.style) {
2008
+ if (_optionalChain([options, 'optionalAccess', _82 => _82.style]) !== void 0 && barline.barStyle !== options.style) {
1834
2009
  continue;
1835
2010
  }
1836
- if (_optionalChain([options, 'optionalAccess', _80 => _80.repeat]) !== void 0) {
2011
+ if (_optionalChain([options, 'optionalAccess', _83 => _83.repeat]) !== void 0) {
1837
2012
  const hasRepeat = barline.repeat !== void 0;
1838
2013
  if (hasRepeat !== options.repeat) {
1839
2014
  continue;
@@ -1853,8 +2028,8 @@ function findBarlines(score, options) {
1853
2028
  }
1854
2029
  function getEndings(score, options) {
1855
2030
  const results = [];
1856
- const startPart = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _81 => _81.partIndex]), () => ( 0));
1857
- const endPart = _optionalChain([options, 'optionalAccess', _82 => _82.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;
1858
2033
  for (let partIndex = startPart; partIndex < endPart; partIndex++) {
1859
2034
  const part = score.parts[partIndex];
1860
2035
  if (!part) continue;
@@ -1880,8 +2055,8 @@ function getEndings(score, options) {
1880
2055
  }
1881
2056
  function getKeyChanges(score, options) {
1882
2057
  const results = [];
1883
- const startPart = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _83 => _83.partIndex]), () => ( 0));
1884
- const endPart = _optionalChain([options, 'optionalAccess', _84 => _84.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;
1885
2060
  for (let partIndex = startPart; partIndex < endPart; partIndex++) {
1886
2061
  const part = score.parts[partIndex];
1887
2062
  if (!part) continue;
@@ -1890,7 +2065,7 @@ function getKeyChanges(score, options) {
1890
2065
  const measure = part.measures[measureIndex];
1891
2066
  const measureNumber = _nullishCoalesce(measure.number, () => ( String(measureIndex + 1)));
1892
2067
  const state = createPositionState();
1893
- if (_optionalChain([measure, 'access', _85 => _85.attributes, 'optionalAccess', _86 => _86.key])) {
2068
+ if (_optionalChain([measure, 'access', _88 => _88.attributes, 'optionalAccess', _89 => _89.key])) {
1894
2069
  const key = measure.attributes.key;
1895
2070
  if (!lastKey || lastKey.fifths !== key.fifths || lastKey.mode !== key.mode) {
1896
2071
  results.push({
@@ -1925,8 +2100,8 @@ function getKeyChanges(score, options) {
1925
2100
  }
1926
2101
  function getTimeChanges(score, options) {
1927
2102
  const results = [];
1928
- const startPart = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _87 => _87.partIndex]), () => ( 0));
1929
- const endPart = _optionalChain([options, 'optionalAccess', _88 => _88.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;
1930
2105
  for (let partIndex = startPart; partIndex < endPart; partIndex++) {
1931
2106
  const part = score.parts[partIndex];
1932
2107
  if (!part) continue;
@@ -1934,7 +2109,7 @@ function getTimeChanges(score, options) {
1934
2109
  for (let measureIndex = 0; measureIndex < part.measures.length; measureIndex++) {
1935
2110
  const measure = part.measures[measureIndex];
1936
2111
  const measureNumber = _nullishCoalesce(measure.number, () => ( String(measureIndex + 1)));
1937
- if (_optionalChain([measure, 'access', _89 => _89.attributes, 'optionalAccess', _90 => _90.time])) {
2112
+ if (_optionalChain([measure, 'access', _92 => _92.attributes, 'optionalAccess', _93 => _93.time])) {
1938
2113
  const time = measure.attributes.time;
1939
2114
  if (!lastTime || lastTime.beats !== time.beats || lastTime.beatType !== time.beatType) {
1940
2115
  results.push({
@@ -1966,8 +2141,8 @@ function getTimeChanges(score, options) {
1966
2141
  }
1967
2142
  function getClefChanges(score, options) {
1968
2143
  const results = [];
1969
- const startPart = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _91 => _91.partIndex]), () => ( 0));
1970
- const endPart = _optionalChain([options, 'optionalAccess', _92 => _92.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;
1971
2146
  for (let partIndex = startPart; partIndex < endPart; partIndex++) {
1972
2147
  const part = score.parts[partIndex];
1973
2148
  if (!part) continue;
@@ -1976,10 +2151,10 @@ function getClefChanges(score, options) {
1976
2151
  const measure = part.measures[measureIndex];
1977
2152
  const measureNumber = _nullishCoalesce(measure.number, () => ( String(measureIndex + 1)));
1978
2153
  const state = createPositionState();
1979
- if (_optionalChain([measure, 'access', _93 => _93.attributes, 'optionalAccess', _94 => _94.clef])) {
2154
+ if (_optionalChain([measure, 'access', _96 => _96.attributes, 'optionalAccess', _97 => _97.clef])) {
1980
2155
  for (const clef of measure.attributes.clef) {
1981
2156
  const staff = _nullishCoalesce(clef.staff, () => ( 1));
1982
- if (_optionalChain([options, 'optionalAccess', _95 => _95.staff]) !== void 0 && staff !== options.staff) {
2157
+ if (_optionalChain([options, 'optionalAccess', _98 => _98.staff]) !== void 0 && staff !== options.staff) {
1983
2158
  continue;
1984
2159
  }
1985
2160
  const lastClef = lastClefs.get(staff);
@@ -2000,7 +2175,7 @@ function getClefChanges(score, options) {
2000
2175
  if (entry.type === "attributes" && entry.attributes.clef) {
2001
2176
  for (const clef of entry.attributes.clef) {
2002
2177
  const staff = _nullishCoalesce(clef.staff, () => ( 1));
2003
- if (_optionalChain([options, 'optionalAccess', _96 => _96.staff]) !== void 0 && staff !== options.staff) {
2178
+ if (_optionalChain([options, 'optionalAccess', _99 => _99.staff]) !== void 0 && staff !== options.staff) {
2004
2179
  continue;
2005
2180
  }
2006
2181
  const lastClef = lastClefs.get(staff);
@@ -2063,14 +2238,14 @@ function getDivisions(score, options) {
2063
2238
  const m = part.measures[i];
2064
2239
  const mNum = parseInt(m.number, 10);
2065
2240
  if (!isNaN(mNum) && mNum > targetMeasure) break;
2066
- if (_optionalChain([m, 'access', _97 => _97.attributes, 'optionalAccess', _98 => _98.divisions]) !== void 0) {
2241
+ if (_optionalChain([m, 'access', _100 => _100.attributes, 'optionalAccess', _101 => _101.divisions]) !== void 0) {
2067
2242
  }
2068
2243
  }
2069
2244
  let divisions = 1;
2070
2245
  for (const m of part.measures) {
2071
2246
  const mNum = parseInt(m.number, 10);
2072
2247
  if (!isNaN(mNum) && mNum > targetMeasure) break;
2073
- if (_optionalChain([m, 'access', _99 => _99.attributes, 'optionalAccess', _100 => _100.divisions]) !== void 0) {
2248
+ if (_optionalChain([m, 'access', _102 => _102.attributes, 'optionalAccess', _103 => _103.divisions]) !== void 0) {
2074
2249
  divisions = m.attributes.divisions;
2075
2250
  }
2076
2251
  }
@@ -2131,7 +2306,7 @@ function getDuration(score) {
2131
2306
  let totalDuration = 0;
2132
2307
  let divisions = 1;
2133
2308
  for (const measure of part.measures) {
2134
- if (_optionalChain([measure, 'access', _101 => _101.attributes, 'optionalAccess', _102 => _102.divisions]) !== void 0) {
2309
+ if (_optionalChain([measure, 'access', _104 => _104.attributes, 'optionalAccess', _105 => _105.divisions]) !== void 0) {
2135
2310
  divisions = measure.attributes.divisions;
2136
2311
  }
2137
2312
  let measureDuration = 0;
@@ -2160,7 +2335,7 @@ function hasMultipleStaves(score, partIndex = 0) {
2160
2335
  const part = score.parts[partIndex];
2161
2336
  if (!part) return false;
2162
2337
  for (const measure of part.measures) {
2163
- if (_optionalChain([measure, 'access', _103 => _103.attributes, 'optionalAccess', _104 => _104.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) {
2164
2339
  return true;
2165
2340
  }
2166
2341
  }
@@ -2170,7 +2345,7 @@ function getStaveCount(score, partIndex = 0) {
2170
2345
  const part = score.parts[partIndex];
2171
2346
  if (!part) return 1;
2172
2347
  for (const measure of part.measures) {
2173
- if (_optionalChain([measure, 'access', _105 => _105.attributes, 'optionalAccess', _106 => _106.staves]) !== void 0) {
2348
+ if (_optionalChain([measure, 'access', _108 => _108.attributes, 'optionalAccess', _109 => _109.staves]) !== void 0) {
2174
2349
  return measure.attributes.staves;
2175
2350
  }
2176
2351
  }
@@ -2333,4 +2508,5 @@ function pitchesEqual(a, b) {
2333
2508
 
2334
2509
 
2335
2510
 
2336
- exports.extractPlaybackControls = extractPlaybackControls; exports.generatePlaybackSequence = generatePlaybackSequence; exports.hasPlaybackControls = hasPlaybackControls; exports.measureEndTick = measureEndTick; exports.buildGridTimeline = buildGridTimeline; 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;
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;