musicxml-io 0.7.0 → 0.7.1

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,188 @@ 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
+ function metronomeBpm(perMinute) {
514
+ if (perMinute === void 0) return null;
515
+ const bpm = typeof perMinute === "number" ? perMinute : parseFloat(perMinute);
516
+ return isNaN(bpm) ? null : bpm;
517
+ }
518
+ function measureMaxPosition(measure) {
519
+ let position = 0;
520
+ let max = 0;
521
+ for (const entry of measure.entries) {
522
+ if (entry.type === "note") {
523
+ if (!entry.chord && !entry.grace) {
524
+ position += entry.duration;
525
+ if (position > max) max = position;
526
+ }
527
+ } else if (entry.type === "backup") {
528
+ position -= entry.duration;
529
+ } else if (entry.type === "forward") {
530
+ position += entry.duration;
531
+ if (position > max) max = position;
532
+ }
533
+ }
534
+ return max;
535
+ }
536
+ function findTimeSignature(part, measureNumber) {
537
+ const targetMeasure = parseInt(String(measureNumber), 10);
538
+ let time;
539
+ for (const measure of part.measures) {
540
+ const mNum = parseInt(measure.number, 10);
541
+ if (!isNaN(targetMeasure) && !isNaN(mNum) && mNum > targetMeasure) break;
542
+ if (_optionalChain([measure, 'access', _5 => _5.attributes, 'optionalAccess', _6 => _6.time])) {
543
+ time = {
544
+ beats: parseInt(measure.attributes.time.beats, 10) || 4,
545
+ beatType: measure.attributes.time.beatType
546
+ };
547
+ }
548
+ }
549
+ return time;
550
+ }
551
+ function measureEndTick(measure, part, divisions, measureStartTick, maxPosition, ticksPerQuarterNote) {
552
+ const actualTicks = Math.round(maxPosition * ticksPerQuarterNote / divisions);
553
+ if (measure.implicit) {
554
+ return measureStartTick + actualTicks;
555
+ }
556
+ const timeAttrs = findTimeSignature(part, measure.number);
557
+ if (timeAttrs) {
558
+ const measureDuration = timeAttrs.beats / timeAttrs.beatType * 4 * divisions;
559
+ const calculatedTicks = Math.round(measureDuration * ticksPerQuarterNote / divisions);
560
+ const ticksToAdd = Math.min(calculatedTicks, actualTicks > 0 ? actualTicks : calculatedTicks);
561
+ return measureStartTick + ticksToAdd;
562
+ }
563
+ return measureStartTick + actualTicks;
564
+ }
565
+ function buildGridTimeline(score, ticksPerQuarterNote, sequence) {
566
+ const tempoEvents = [];
567
+ const measures = [];
568
+ if (score.parts.length === 0) {
569
+ return { tempoEvents, measures, totalTicks: 0 };
570
+ }
571
+ const part = score.parts[0];
572
+ let divisions = 1;
573
+ let currentTick = 0;
574
+ for (const { measureIndex, repeatIteration } of sequence) {
575
+ const measure = part.measures[measureIndex];
576
+ if (!measure) continue;
577
+ if (_optionalChain([measure, 'access', _7 => _7.attributes, 'optionalAccess', _8 => _8.divisions])) {
578
+ divisions = measure.attributes.divisions;
579
+ }
580
+ const measureStartTick = currentTick;
581
+ let position = 0;
582
+ const tickAt = (pos) => measureStartTick + Math.round(pos * ticksPerQuarterNote / divisions);
583
+ for (const entry of measure.entries) {
584
+ if (entry.type === "direction") {
585
+ for (const dirType of entry.directionTypes) {
586
+ if (dirType.kind === "metronome") {
587
+ const bpm = metronomeBpm(dirType.perMinute);
588
+ if (bpm !== null) tempoEvents.push({ tick: tickAt(position), bpm });
589
+ }
590
+ }
591
+ if (_optionalChain([entry, 'access', _9 => _9.sound, 'optionalAccess', _10 => _10.tempo])) {
592
+ tempoEvents.push({ tick: tickAt(position), bpm: entry.sound.tempo });
593
+ }
594
+ } 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;
598
+ } else if (entry.type === "backup") {
599
+ position -= entry.duration;
600
+ } else if (entry.type === "forward") {
601
+ position += entry.duration;
602
+ }
603
+ }
604
+ const endTick = measureEndTick(
605
+ measure,
606
+ part,
607
+ divisions,
608
+ measureStartTick,
609
+ measureMaxPosition(measure),
610
+ ticksPerQuarterNote
611
+ );
612
+ measures.push({
613
+ measureIndex,
614
+ repeatIteration,
615
+ measureNumber: measure.number,
616
+ startTick: measureStartTick,
617
+ endTick
618
+ });
619
+ currentTick = endTick;
620
+ }
621
+ return { tempoEvents, measures, totalTicks: currentTick };
622
+ }
623
+ function makeTickToSec(tempoEvents, defaultTempo, ticksPerQuarterNote) {
624
+ const sorted = [...tempoEvents].sort((a, b) => a.tick - b.tick);
625
+ const startBpm = sorted.length > 0 && sorted[0].tick === 0 ? sorted[0].bpm : defaultTempo;
626
+ const changes = [{ tick: 0, bpm: startBpm }];
627
+ let lastBpm = startBpm;
628
+ for (const ev of sorted) {
629
+ if (ev.tick === 0) continue;
630
+ if (ev.bpm === lastBpm) continue;
631
+ changes.push({ tick: ev.tick, bpm: ev.bpm });
632
+ lastBpm = ev.bpm;
633
+ }
634
+ const cumSec = [0];
635
+ for (let i = 1; i < changes.length; i++) {
636
+ const dTick = changes[i].tick - changes[i - 1].tick;
637
+ cumSec[i] = cumSec[i - 1] + dTick / ticksPerQuarterNote * (60 / changes[i - 1].bpm);
638
+ }
639
+ return (tick) => {
640
+ let i = changes.length - 1;
641
+ while (i > 0 && changes[i].tick > tick) i--;
642
+ return cumSec[i] + (tick - changes[i].tick) / ticksPerQuarterNote * (60 / changes[i].bpm);
643
+ };
644
+ }
645
+ function buildTimingSidecar(grid, defaultTempo, ticksPerQuarterNote) {
646
+ const tickToSec = makeTickToSec(grid.tempoEvents, defaultTempo, ticksPerQuarterNote);
647
+ const breakpoints = [];
648
+ const measureStartTicks = new Set(grid.measures.map((m) => m.startTick));
649
+ for (const m of grid.measures) {
650
+ breakpoints.push({
651
+ midiSec: tickToSec(m.startTick),
652
+ quarterPos: m.startTick / ticksPerQuarterNote,
653
+ measureNumber: m.measureNumber,
654
+ beatInMeasure: 0,
655
+ repeatIteration: m.repeatIteration
656
+ });
657
+ }
658
+ for (const ev of grid.tempoEvents) {
659
+ if (measureStartTicks.has(ev.tick)) continue;
660
+ const m = grid.measures.find((mm) => ev.tick >= mm.startTick && ev.tick < mm.endTick);
661
+ if (!m) continue;
662
+ breakpoints.push({
663
+ midiSec: tickToSec(ev.tick),
664
+ quarterPos: ev.tick / ticksPerQuarterNote,
665
+ measureNumber: m.measureNumber,
666
+ beatInMeasure: (ev.tick - m.startTick) / ticksPerQuarterNote,
667
+ repeatIteration: m.repeatIteration
668
+ });
669
+ }
670
+ const last = grid.measures[grid.measures.length - 1];
671
+ breakpoints.push({
672
+ midiSec: tickToSec(grid.totalTicks),
673
+ quarterPos: grid.totalTicks / ticksPerQuarterNote,
674
+ measureNumber: last ? last.measureNumber : "0",
675
+ beatInMeasure: last ? (grid.totalTicks - last.startTick) / ticksPerQuarterNote : 0,
676
+ repeatIteration: last ? last.repeatIteration : 0
677
+ });
678
+ breakpoints.sort((a, b) => a.midiSec - b.midiSec || a.quarterPos - b.quarterPos);
679
+ return {
680
+ version: "1",
681
+ durationSec: tickToSec(grid.totalTicks),
682
+ ticksPerQuarterNote,
683
+ breakpoints
684
+ };
685
+ }
686
+ function generatePlaybackTimeline(score, options = {}) {
687
+ const ticksPerQuarterNote = _nullishCoalesce(options.ticksPerQuarterNote, () => ( 480));
688
+ const defaultTempo = _nullishCoalesce(options.defaultTempo, () => ( 120));
689
+ const sequence = generatePlaybackSequence(score);
690
+ const grid = buildGridTimeline(score, ticksPerQuarterNote, sequence);
691
+ return buildTimingSidecar(grid, defaultTempo, ticksPerQuarterNote);
692
+ }
693
+
512
694
  // src/query/index.ts
513
695
  function getNotesForVoice(measure, filter) {
514
696
  return measure.entries.filter((entry) => {
@@ -646,7 +828,7 @@ function isRestMeasure(measure) {
646
828
  }
647
829
  function getNormalizedPosition(note, measure, options) {
648
830
  const absolutePosition = getAbsolutePosition(note, measure);
649
- const currentDivisions = _nullishCoalesce(_nullishCoalesce(options.currentDivisions, () => ( _optionalChain([measure, 'access', _5 => _5.attributes, 'optionalAccess', _6 => _6.divisions]))), () => ( 1));
831
+ const currentDivisions = _nullishCoalesce(_nullishCoalesce(options.currentDivisions, () => ( _optionalChain([measure, 'access', _11 => _11.attributes, 'optionalAccess', _12 => _12.divisions]))), () => ( 1));
650
832
  return absolutePosition * options.baseDivisions / currentDivisions;
651
833
  }
652
834
  function getNormalizedDuration(note, options) {
@@ -739,7 +921,7 @@ function getClefForStaff(score, options) {
739
921
  }
740
922
  }
741
923
  }
742
- if (_optionalChain([measure, 'access', _7 => _7.attributes, 'optionalAccess', _8 => _8.clef])) {
924
+ if (_optionalChain([measure, 'access', _13 => _13.attributes, 'optionalAccess', _14 => _14.clef])) {
743
925
  for (const clef of measure.attributes.clef) {
744
926
  if ((_nullishCoalesce(clef.staff, () => ( 1))) === options.staff) {
745
927
  return clef;
@@ -767,7 +949,7 @@ function getStaffRange(score, partIndex) {
767
949
  let min = 1;
768
950
  let max = 1;
769
951
  for (const measure of part.measures) {
770
- if (_optionalChain([measure, 'access', _9 => _9.attributes, 'optionalAccess', _10 => _10.staves]) !== void 0) {
952
+ if (_optionalChain([measure, 'access', _15 => _15.attributes, 'optionalAccess', _16 => _16.staves]) !== void 0) {
771
953
  max = Math.max(max, measure.attributes.staves);
772
954
  }
773
955
  for (const entry of measure.entries) {
@@ -785,15 +967,15 @@ function getEntriesAtPosition(measure, position, options) {
785
967
  const currentPosition = entry.type === "note" && entry.chord ? state.lastNonChordPosition : state.position;
786
968
  if (currentPosition === position) {
787
969
  if (entry.type === "note") {
788
- if (_optionalChain([options, 'optionalAccess', _11 => _11.staff]) !== void 0 && (_nullishCoalesce(entry.staff, () => ( 1))) !== options.staff) {
970
+ if (_optionalChain([options, 'optionalAccess', _17 => _17.staff]) !== void 0 && (_nullishCoalesce(entry.staff, () => ( 1))) !== options.staff) {
789
971
  updatePositionForEntry(state, entry);
790
972
  continue;
791
973
  }
792
- if (_optionalChain([options, 'optionalAccess', _12 => _12.voice]) !== void 0 && entry.voice !== options.voice) {
974
+ if (_optionalChain([options, 'optionalAccess', _18 => _18.voice]) !== void 0 && entry.voice !== options.voice) {
793
975
  updatePositionForEntry(state, entry);
794
976
  continue;
795
977
  }
796
- if (_optionalChain([options, 'optionalAccess', _13 => _13.includeChordNotes]) === false && entry.chord) {
978
+ if (_optionalChain([options, 'optionalAccess', _19 => _19.includeChordNotes]) === false && entry.chord) {
797
979
  updatePositionForEntry(state, entry);
798
980
  continue;
799
981
  }
@@ -816,15 +998,15 @@ function getEntriesInRange(measure, range, options) {
816
998
  const currentPosition = entry.type === "note" && entry.chord ? state.lastNonChordPosition : state.position;
817
999
  if (currentPosition >= range.start && currentPosition < range.end) {
818
1000
  if (entry.type === "note") {
819
- if (_optionalChain([options, 'optionalAccess', _14 => _14.staff]) !== void 0 && (_nullishCoalesce(entry.staff, () => ( 1))) !== options.staff) {
1001
+ if (_optionalChain([options, 'optionalAccess', _20 => _20.staff]) !== void 0 && (_nullishCoalesce(entry.staff, () => ( 1))) !== options.staff) {
820
1002
  updatePositionForEntry(state, entry);
821
1003
  continue;
822
1004
  }
823
- if (_optionalChain([options, 'optionalAccess', _15 => _15.voice]) !== void 0 && entry.voice !== options.voice) {
1005
+ if (_optionalChain([options, 'optionalAccess', _21 => _21.voice]) !== void 0 && entry.voice !== options.voice) {
824
1006
  updatePositionForEntry(state, entry);
825
1007
  continue;
826
1008
  }
827
- if (_optionalChain([options, 'optionalAccess', _16 => _16.includeChordNotes]) === false && entry.chord) {
1009
+ if (_optionalChain([options, 'optionalAccess', _22 => _22.includeChordNotes]) === false && entry.chord) {
828
1010
  updatePositionForEntry(state, entry);
829
1011
  continue;
830
1012
  }
@@ -1030,13 +1212,13 @@ function getAdjacentNotes(score, context) {
1030
1212
  }
1031
1213
  function getDirections(score, options) {
1032
1214
  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;
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;
1035
1217
  for (let partIndex = startPart; partIndex < endPart; partIndex++) {
1036
1218
  const part = score.parts[partIndex];
1037
1219
  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;
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;
1040
1222
  for (let measureIndex = startMeasure; measureIndex < endMeasure; measureIndex++) {
1041
1223
  const measure = part.measures[measureIndex];
1042
1224
  if (!measure) continue;
@@ -1077,8 +1259,8 @@ function findDirectionsByType(score, kind) {
1077
1259
  }
1078
1260
  function getDynamics(score, options) {
1079
1261
  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;
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;
1082
1264
  for (let partIndex = startPart; partIndex < endPart; partIndex++) {
1083
1265
  const part = score.parts[partIndex];
1084
1266
  if (!part) continue;
@@ -1139,8 +1321,8 @@ function getTempoMarkings(score) {
1139
1321
  }
1140
1322
  function getPedalMarkings(score, options) {
1141
1323
  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;
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;
1144
1326
  for (let partIndex = startPart; partIndex < endPart; partIndex++) {
1145
1327
  const part = score.parts[partIndex];
1146
1328
  if (!part) continue;
@@ -1169,8 +1351,8 @@ function getPedalMarkings(score, options) {
1169
1351
  }
1170
1352
  function getWedges(score, options) {
1171
1353
  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;
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;
1174
1356
  for (let partIndex = startPart; partIndex < endPart; partIndex++) {
1175
1357
  const part = score.parts[partIndex];
1176
1358
  if (!part) continue;
@@ -1199,8 +1381,8 @@ function getWedges(score, options) {
1199
1381
  }
1200
1382
  function getOctaveShifts(score, options) {
1201
1383
  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;
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;
1204
1386
  for (let partIndex = startPart; partIndex < endPart; partIndex++) {
1205
1387
  const part = score.parts[partIndex];
1206
1388
  if (!part) continue;
@@ -1230,8 +1412,8 @@ function getOctaveShifts(score, options) {
1230
1412
  }
1231
1413
  function getTiedNoteGroups(score, options) {
1232
1414
  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;
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;
1235
1417
  for (let partIndex = startPart; partIndex < endPart; partIndex++) {
1236
1418
  const part = score.parts[partIndex];
1237
1419
  if (!part) continue;
@@ -1251,8 +1433,8 @@ function getTiedNoteGroups(score, options) {
1251
1433
  measureIndex,
1252
1434
  position
1253
1435
  };
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")]);
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")]);
1256
1438
  if (hasTieStop && pendingTies.has(pitchKey)) {
1257
1439
  const group = pendingTies.get(pitchKey);
1258
1440
  group.push(context);
@@ -1273,8 +1455,8 @@ function getTiedNoteGroups(score, options) {
1273
1455
  }
1274
1456
  function getSlurSpans(score, options) {
1275
1457
  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;
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;
1278
1460
  for (let partIndex = startPart; partIndex < endPart; partIndex++) {
1279
1461
  const part = score.parts[partIndex];
1280
1462
  if (!part) continue;
@@ -1330,8 +1512,8 @@ function getSlurSpans(score, options) {
1330
1512
  }
1331
1513
  function getTupletGroups(score, options) {
1332
1514
  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;
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;
1335
1517
  for (let partIndex = startPart; partIndex < endPart; partIndex++) {
1336
1518
  const part = score.parts[partIndex];
1337
1519
  if (!part) continue;
@@ -1355,8 +1537,8 @@ function getTupletGroups(score, options) {
1355
1537
  if (notation.type === "tuplet") {
1356
1538
  const tupletNumber = _nullishCoalesce(notation.number, () => ( 1));
1357
1539
  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));
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));
1360
1542
  pendingTuplets.set(tupletNumber, {
1361
1543
  notes: [context],
1362
1544
  actualNotes,
@@ -1376,7 +1558,7 @@ function getTupletGroups(score, options) {
1376
1558
  }
1377
1559
  }
1378
1560
  }
1379
- if (entry.timeModification && !_optionalChain([entry, 'access', _55 => _55.notations, 'optionalAccess', _56 => _56.some, 'call', _57 => _57((n) => n.type === "tuplet")])) {
1561
+ if (entry.timeModification && !_optionalChain([entry, 'access', _61 => _61.notations, 'optionalAccess', _62 => _62.some, 'call', _63 => _63((n) => n.type === "tuplet")])) {
1380
1562
  for (const [, pending] of pendingTuplets) {
1381
1563
  if (entry.timeModification.actualNotes === pending.actualNotes && entry.timeModification.normalNotes === pending.normalNotes) {
1382
1564
  pending.notes.push(context);
@@ -1429,8 +1611,8 @@ function getBeamGroups(measure) {
1429
1611
  }
1430
1612
  function findNotesWithNotation(score, notationType, options) {
1431
1613
  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;
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;
1434
1616
  for (let partIndex = startPart; partIndex < endPart; partIndex++) {
1435
1617
  const part = score.parts[partIndex];
1436
1618
  if (!part) continue;
@@ -1440,7 +1622,7 @@ function findNotesWithNotation(score, notationType, options) {
1440
1622
  for (const entry of measure.entries) {
1441
1623
  if (entry.type === "note") {
1442
1624
  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)])) {
1625
+ if (_optionalChain([entry, 'access', _66 => _66.notations, 'optionalAccess', _67 => _67.some, 'call', _68 => _68((n) => n.type === notationType)])) {
1444
1626
  results.push({
1445
1627
  note: entry,
1446
1628
  part,
@@ -1459,8 +1641,8 @@ function findNotesWithNotation(score, notationType, options) {
1459
1641
  }
1460
1642
  function getHarmonies(score, options) {
1461
1643
  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;
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;
1464
1646
  for (let partIndex = startPart; partIndex < endPart; partIndex++) {
1465
1647
  const part = score.parts[partIndex];
1466
1648
  if (!part) continue;
@@ -1523,8 +1705,8 @@ function getChordProgression(score, options) {
1523
1705
  }
1524
1706
  function getLyrics(score, options) {
1525
1707
  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;
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;
1528
1710
  for (let partIndex = startPart; partIndex < endPart; partIndex++) {
1529
1711
  const part = score.parts[partIndex];
1530
1712
  if (!part) continue;
@@ -1536,7 +1718,7 @@ function getLyrics(score, options) {
1536
1718
  const position = entry.chord ? state.lastNonChordPosition : state.position;
1537
1719
  for (const lyric of entry.lyrics) {
1538
1720
  const verse = _nullishCoalesce(lyric.number, () => ( 1));
1539
- if (_optionalChain([options, 'optionalAccess', _67 => _67.verse]) !== void 0 && verse !== options.verse) {
1721
+ if (_optionalChain([options, 'optionalAccess', _73 => _73.verse]) !== void 0 && verse !== options.verse) {
1540
1722
  continue;
1541
1723
  }
1542
1724
  results.push({
@@ -1596,8 +1778,8 @@ function getLyricText(score, options) {
1596
1778
  }
1597
1779
  function getVerseCount(score, options) {
1598
1780
  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;
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;
1601
1783
  for (let partIndex = startPart; partIndex < endPart; partIndex++) {
1602
1784
  const part = score.parts[partIndex];
1603
1785
  if (!part) continue;
@@ -1615,7 +1797,7 @@ function getVerseCount(score, options) {
1615
1797
  }
1616
1798
  function getRepeatStructure(score, options) {
1617
1799
  const results = [];
1618
- const partIndex = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _70 => _70.partIndex]), () => ( 0));
1800
+ const partIndex = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _76 => _76.partIndex]), () => ( 0));
1619
1801
  const part = score.parts[partIndex];
1620
1802
  if (!part) return results;
1621
1803
  for (let measureIndex = 0; measureIndex < part.measures.length; measureIndex++) {
@@ -1638,8 +1820,8 @@ function getRepeatStructure(score, options) {
1638
1820
  }
1639
1821
  function findBarlines(score, options) {
1640
1822
  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;
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;
1643
1825
  for (let partIndex = startPart; partIndex < endPart; partIndex++) {
1644
1826
  const part = score.parts[partIndex];
1645
1827
  if (!part) continue;
@@ -1648,10 +1830,10 @@ function findBarlines(score, options) {
1648
1830
  const measureNumber = _nullishCoalesce(measure.number, () => ( String(measureIndex + 1)));
1649
1831
  if (measure.barlines) {
1650
1832
  for (const barline of measure.barlines) {
1651
- if (_optionalChain([options, 'optionalAccess', _73 => _73.style]) !== void 0 && barline.barStyle !== options.style) {
1833
+ if (_optionalChain([options, 'optionalAccess', _79 => _79.style]) !== void 0 && barline.barStyle !== options.style) {
1652
1834
  continue;
1653
1835
  }
1654
- if (_optionalChain([options, 'optionalAccess', _74 => _74.repeat]) !== void 0) {
1836
+ if (_optionalChain([options, 'optionalAccess', _80 => _80.repeat]) !== void 0) {
1655
1837
  const hasRepeat = barline.repeat !== void 0;
1656
1838
  if (hasRepeat !== options.repeat) {
1657
1839
  continue;
@@ -1671,8 +1853,8 @@ function findBarlines(score, options) {
1671
1853
  }
1672
1854
  function getEndings(score, options) {
1673
1855
  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;
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;
1676
1858
  for (let partIndex = startPart; partIndex < endPart; partIndex++) {
1677
1859
  const part = score.parts[partIndex];
1678
1860
  if (!part) continue;
@@ -1698,8 +1880,8 @@ function getEndings(score, options) {
1698
1880
  }
1699
1881
  function getKeyChanges(score, options) {
1700
1882
  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;
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;
1703
1885
  for (let partIndex = startPart; partIndex < endPart; partIndex++) {
1704
1886
  const part = score.parts[partIndex];
1705
1887
  if (!part) continue;
@@ -1708,7 +1890,7 @@ function getKeyChanges(score, options) {
1708
1890
  const measure = part.measures[measureIndex];
1709
1891
  const measureNumber = _nullishCoalesce(measure.number, () => ( String(measureIndex + 1)));
1710
1892
  const state = createPositionState();
1711
- if (_optionalChain([measure, 'access', _79 => _79.attributes, 'optionalAccess', _80 => _80.key])) {
1893
+ if (_optionalChain([measure, 'access', _85 => _85.attributes, 'optionalAccess', _86 => _86.key])) {
1712
1894
  const key = measure.attributes.key;
1713
1895
  if (!lastKey || lastKey.fifths !== key.fifths || lastKey.mode !== key.mode) {
1714
1896
  results.push({
@@ -1743,8 +1925,8 @@ function getKeyChanges(score, options) {
1743
1925
  }
1744
1926
  function getTimeChanges(score, options) {
1745
1927
  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;
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;
1748
1930
  for (let partIndex = startPart; partIndex < endPart; partIndex++) {
1749
1931
  const part = score.parts[partIndex];
1750
1932
  if (!part) continue;
@@ -1752,7 +1934,7 @@ function getTimeChanges(score, options) {
1752
1934
  for (let measureIndex = 0; measureIndex < part.measures.length; measureIndex++) {
1753
1935
  const measure = part.measures[measureIndex];
1754
1936
  const measureNumber = _nullishCoalesce(measure.number, () => ( String(measureIndex + 1)));
1755
- if (_optionalChain([measure, 'access', _83 => _83.attributes, 'optionalAccess', _84 => _84.time])) {
1937
+ if (_optionalChain([measure, 'access', _89 => _89.attributes, 'optionalAccess', _90 => _90.time])) {
1756
1938
  const time = measure.attributes.time;
1757
1939
  if (!lastTime || lastTime.beats !== time.beats || lastTime.beatType !== time.beatType) {
1758
1940
  results.push({
@@ -1784,8 +1966,8 @@ function getTimeChanges(score, options) {
1784
1966
  }
1785
1967
  function getClefChanges(score, options) {
1786
1968
  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;
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;
1789
1971
  for (let partIndex = startPart; partIndex < endPart; partIndex++) {
1790
1972
  const part = score.parts[partIndex];
1791
1973
  if (!part) continue;
@@ -1794,10 +1976,10 @@ function getClefChanges(score, options) {
1794
1976
  const measure = part.measures[measureIndex];
1795
1977
  const measureNumber = _nullishCoalesce(measure.number, () => ( String(measureIndex + 1)));
1796
1978
  const state = createPositionState();
1797
- if (_optionalChain([measure, 'access', _87 => _87.attributes, 'optionalAccess', _88 => _88.clef])) {
1979
+ if (_optionalChain([measure, 'access', _93 => _93.attributes, 'optionalAccess', _94 => _94.clef])) {
1798
1980
  for (const clef of measure.attributes.clef) {
1799
1981
  const staff = _nullishCoalesce(clef.staff, () => ( 1));
1800
- if (_optionalChain([options, 'optionalAccess', _89 => _89.staff]) !== void 0 && staff !== options.staff) {
1982
+ if (_optionalChain([options, 'optionalAccess', _95 => _95.staff]) !== void 0 && staff !== options.staff) {
1801
1983
  continue;
1802
1984
  }
1803
1985
  const lastClef = lastClefs.get(staff);
@@ -1818,7 +2000,7 @@ function getClefChanges(score, options) {
1818
2000
  if (entry.type === "attributes" && entry.attributes.clef) {
1819
2001
  for (const clef of entry.attributes.clef) {
1820
2002
  const staff = _nullishCoalesce(clef.staff, () => ( 1));
1821
- if (_optionalChain([options, 'optionalAccess', _90 => _90.staff]) !== void 0 && staff !== options.staff) {
2003
+ if (_optionalChain([options, 'optionalAccess', _96 => _96.staff]) !== void 0 && staff !== options.staff) {
1822
2004
  continue;
1823
2005
  }
1824
2006
  const lastClef = lastClefs.get(staff);
@@ -1881,14 +2063,14 @@ function getDivisions(score, options) {
1881
2063
  const m = part.measures[i];
1882
2064
  const mNum = parseInt(m.number, 10);
1883
2065
  if (!isNaN(mNum) && mNum > targetMeasure) break;
1884
- if (_optionalChain([m, 'access', _91 => _91.attributes, 'optionalAccess', _92 => _92.divisions]) !== void 0) {
2066
+ if (_optionalChain([m, 'access', _97 => _97.attributes, 'optionalAccess', _98 => _98.divisions]) !== void 0) {
1885
2067
  }
1886
2068
  }
1887
2069
  let divisions = 1;
1888
2070
  for (const m of part.measures) {
1889
2071
  const mNum = parseInt(m.number, 10);
1890
2072
  if (!isNaN(mNum) && mNum > targetMeasure) break;
1891
- if (_optionalChain([m, 'access', _93 => _93.attributes, 'optionalAccess', _94 => _94.divisions]) !== void 0) {
2073
+ if (_optionalChain([m, 'access', _99 => _99.attributes, 'optionalAccess', _100 => _100.divisions]) !== void 0) {
1892
2074
  divisions = m.attributes.divisions;
1893
2075
  }
1894
2076
  }
@@ -1949,7 +2131,7 @@ function getDuration(score) {
1949
2131
  let totalDuration = 0;
1950
2132
  let divisions = 1;
1951
2133
  for (const measure of part.measures) {
1952
- if (_optionalChain([measure, 'access', _95 => _95.attributes, 'optionalAccess', _96 => _96.divisions]) !== void 0) {
2134
+ if (_optionalChain([measure, 'access', _101 => _101.attributes, 'optionalAccess', _102 => _102.divisions]) !== void 0) {
1953
2135
  divisions = measure.attributes.divisions;
1954
2136
  }
1955
2137
  let measureDuration = 0;
@@ -1978,7 +2160,7 @@ function hasMultipleStaves(score, partIndex = 0) {
1978
2160
  const part = score.parts[partIndex];
1979
2161
  if (!part) return false;
1980
2162
  for (const measure of part.measures) {
1981
- if (_optionalChain([measure, 'access', _97 => _97.attributes, 'optionalAccess', _98 => _98.staves]) !== void 0 && measure.attributes.staves > 1) {
2163
+ if (_optionalChain([measure, 'access', _103 => _103.attributes, 'optionalAccess', _104 => _104.staves]) !== void 0 && measure.attributes.staves > 1) {
1982
2164
  return true;
1983
2165
  }
1984
2166
  }
@@ -1988,7 +2170,7 @@ function getStaveCount(score, partIndex = 0) {
1988
2170
  const part = score.parts[partIndex];
1989
2171
  if (!part) return 1;
1990
2172
  for (const measure of part.measures) {
1991
- if (_optionalChain([measure, 'access', _99 => _99.attributes, 'optionalAccess', _100 => _100.staves]) !== void 0) {
2173
+ if (_optionalChain([measure, 'access', _105 => _105.attributes, 'optionalAccess', _106 => _106.staves]) !== void 0) {
1992
2174
  return measure.attributes.staves;
1993
2175
  }
1994
2176
  }
@@ -2147,4 +2329,8 @@ function pitchesEqual(a, b) {
2147
2329
 
2148
2330
 
2149
2331
 
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;
2332
+
2333
+
2334
+
2335
+
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;