musicxml-io 0.3.3 → 0.3.4

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.
@@ -1,1778 +1,158 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
-
20
- // src/query/index.ts
21
- var query_exports = {};
22
- __export(query_exports, {
23
- buildVoiceToStaffMap: () => buildVoiceToStaffMap,
24
- buildVoiceToStaffMapForPart: () => buildVoiceToStaffMapForPart,
25
- countNotes: () => countNotes,
26
- findBarlines: () => findBarlines,
27
- findDirectionsByType: () => findDirectionsByType,
28
- findNotes: () => findNotes,
29
- findNotesWithNotation: () => findNotesWithNotation,
30
- getAbsolutePosition: () => getAbsolutePosition,
31
- getAdjacentNotes: () => getAdjacentNotes,
32
- getAllNotes: () => getAllNotes,
33
- getAttributesAtMeasure: () => getAttributesAtMeasure,
34
- getBeamGroups: () => getBeamGroups,
35
- getChordProgression: () => getChordProgression,
36
- getChords: () => getChords,
37
- getClefChanges: () => getClefChanges,
38
- getClefForStaff: () => getClefForStaff,
39
- getDirections: () => getDirections,
40
- getDirectionsAtPosition: () => getDirectionsAtPosition,
41
- getDivisions: () => getDivisions,
42
- getDuration: () => getDuration,
43
- getDynamics: () => getDynamics,
44
- getEffectiveStaff: () => getEffectiveStaff,
45
- getEndings: () => getEndings,
46
- getEntriesAtPosition: () => getEntriesAtPosition,
47
- getEntriesForStaff: () => getEntriesForStaff,
48
- getEntriesInRange: () => getEntriesInRange,
49
- getHarmonies: () => getHarmonies,
50
- getHarmonyAtPosition: () => getHarmonyAtPosition,
51
- getKeyChanges: () => getKeyChanges,
52
- getLyricText: () => getLyricText,
53
- getLyrics: () => getLyrics,
54
- getMeasure: () => getMeasure,
55
- getMeasureByIndex: () => getMeasureByIndex,
56
- getMeasureCount: () => getMeasureCount,
57
- getNextNote: () => getNextNote,
58
- getNormalizedDuration: () => getNormalizedDuration,
59
- getNormalizedPosition: () => getNormalizedPosition,
60
- getNotesAtPosition: () => getNotesAtPosition,
61
- getNotesForStaff: () => getNotesForStaff,
62
- getNotesForVoice: () => getNotesForVoice,
63
- getNotesInRange: () => getNotesInRange,
64
- getOctaveShifts: () => getOctaveShifts,
65
- getPartById: () => getPartById,
66
- getPartByIndex: () => getPartByIndex,
67
- getPartCount: () => getPartCount,
68
- getPartIds: () => getPartIds,
69
- getPartIndex: () => getPartIndex,
70
- getPedalMarkings: () => getPedalMarkings,
71
- getPrevNote: () => getPrevNote,
72
- getRepeatStructure: () => getRepeatStructure,
73
- getSlurSpans: () => getSlurSpans,
74
- getStaffRange: () => getStaffRange,
75
- getStaveCount: () => getStaveCount,
76
- getStaves: () => getStaves,
77
- getStructuralChanges: () => getStructuralChanges,
78
- getTempoMarkings: () => getTempoMarkings,
79
- getTiedNoteGroups: () => getTiedNoteGroups,
80
- getTimeChanges: () => getTimeChanges,
81
- getTupletGroups: () => getTupletGroups,
82
- getVerseCount: () => getVerseCount,
83
- getVerticalSlice: () => getVerticalSlice,
84
- getVoiceLine: () => getVoiceLine,
85
- getVoiceLineInRange: () => getVoiceLineInRange,
86
- getVoices: () => getVoices,
87
- getVoicesForStaff: () => getVoicesForStaff,
88
- getWedges: () => getWedges,
89
- groupByStaff: () => groupByStaff,
90
- groupByVoice: () => groupByVoice,
91
- hasMultipleStaves: () => hasMultipleStaves,
92
- hasNotes: () => hasNotes,
93
- inferStaff: () => inferStaff,
94
- isRestMeasure: () => isRestMeasure,
95
- iterateEntries: () => iterateEntries,
96
- iterateNotes: () => iterateNotes,
97
- measureRoundtrip: () => measureRoundtrip,
98
- scoresEqual: () => scoresEqual,
99
- withAbsolutePositions: () => withAbsolutePositions
100
- });
101
- module.exports = __toCommonJS(query_exports);
102
-
103
- // src/utils/index.ts
104
- var STEP_SEMITONES = {
105
- "C": 0,
106
- "D": 2,
107
- "E": 4,
108
- "F": 5,
109
- "G": 7,
110
- "A": 9,
111
- "B": 11
112
- };
113
- function pitchToSemitone(pitch) {
114
- return pitch.octave * 12 + STEP_SEMITONES[pitch.step] + (pitch.alter ?? 0);
115
- }
116
- function createPositionState() {
117
- return { position: 0, lastNonChordPosition: 0 };
118
- }
119
- function updatePositionForEntry(state, entry) {
120
- const pos = state.position;
121
- switch (entry.type) {
122
- case "note": {
123
- const note = entry;
124
- if (!note.chord) {
125
- state.lastNonChordPosition = state.position;
126
- state.position += note.duration;
127
- }
128
- return note.chord ? state.lastNonChordPosition : pos;
129
- }
130
- case "backup":
131
- state.position -= entry.duration;
132
- state.lastNonChordPosition = state.position;
133
- return pos;
134
- case "forward":
135
- state.position += entry.duration;
136
- state.lastNonChordPosition = state.position;
137
- return pos;
138
- default:
139
- return pos;
140
- }
141
- }
142
- function getAbsolutePositionForNote(note, measure) {
143
- const state = createPositionState();
144
- for (const entry of measure.entries) {
145
- if (entry === note) return entry.chord ? state.lastNonChordPosition : state.position;
146
- updatePositionForEntry(state, entry);
147
- }
148
- return state.position;
149
- }
150
-
151
- // src/query/index.ts
152
- function getNotesForVoice(measure, filter) {
153
- return measure.entries.filter((entry) => {
154
- if (entry.type !== "note") return false;
155
- if (filter.voice !== void 0 && entry.voice !== filter.voice) return false;
156
- if (filter.staff !== void 0 && (entry.staff ?? 1) !== filter.staff) return false;
157
- return true;
158
- });
159
- }
160
- function getNotesForStaff(measure, filter) {
161
- return measure.entries.filter((entry) => {
162
- if (entry.type !== "note") return false;
163
- return (entry.staff ?? 1) === filter.staff;
164
- });
165
- }
166
- function groupByVoice(measure) {
167
- const groups = /* @__PURE__ */ new Map();
168
- for (const entry of measure.entries) {
169
- if (entry.type !== "note") continue;
170
- const staff = entry.staff ?? 1;
171
- const voice = entry.voice ?? 1;
172
- const key = `${staff}-${voice}`;
173
- if (!groups.has(key)) {
174
- groups.set(key, { staff, voice, notes: [] });
175
- }
176
- groups.get(key).notes.push(entry);
177
- }
178
- return Array.from(groups.values()).sort((a, b) => {
179
- if (a.staff !== b.staff) return a.staff - b.staff;
180
- return a.voice - b.voice;
181
- });
182
- }
183
- function groupByStaff(measure) {
184
- const groups = /* @__PURE__ */ new Map();
185
- for (const entry of measure.entries) {
186
- if (entry.type !== "note") continue;
187
- const staff = entry.staff ?? 1;
188
- if (!groups.has(staff)) {
189
- groups.set(staff, { staff, notes: [] });
190
- }
191
- groups.get(staff).notes.push(entry);
192
- }
193
- return Array.from(groups.values()).sort((a, b) => a.staff - b.staff);
194
- }
195
- function getAbsolutePosition(note, measure) {
196
- return getAbsolutePositionForNote(note, measure);
197
- }
198
- function withAbsolutePositions(measure) {
199
- const result = [];
200
- const state = createPositionState();
201
- for (const entry of measure.entries) {
202
- if (entry.type === "note") {
203
- const notePosition = entry.chord ? state.lastNonChordPosition : state.position;
204
- result.push({
205
- ...entry,
206
- absolutePosition: notePosition
207
- });
208
- }
209
- updatePositionForEntry(state, entry);
210
- }
211
- return result;
212
- }
213
- function getChords(measure, filter) {
214
- const notesWithPos = withAbsolutePositions(measure);
215
- const filteredNotes = filter ? notesWithPos.filter((note) => {
216
- if (filter.voice !== void 0 && note.voice !== filter.voice) return false;
217
- if (filter.staff !== void 0 && (note.staff ?? 1) !== filter.staff) return false;
218
- return true;
219
- }) : notesWithPos;
220
- const chordMap = /* @__PURE__ */ new Map();
221
- for (const note of filteredNotes) {
222
- const pos = note.absolutePosition;
223
- if (!chordMap.has(pos)) {
224
- chordMap.set(pos, []);
225
- }
226
- chordMap.get(pos).push(note);
227
- }
228
- const chords = [];
229
- for (const [position, notes] of chordMap.entries()) {
230
- const duration = notes[0].duration;
231
- chords.push({
232
- position,
233
- duration,
234
- notes: notes.map(({ absolutePosition, ...note }) => note)
235
- });
236
- }
237
- return chords.sort((a, b) => a.position - b.position);
238
- }
239
- function* iterateNotes(score) {
240
- for (const part of score.parts) {
241
- for (const measure of part.measures) {
242
- const state = createPositionState();
243
- for (const entry of measure.entries) {
244
- if (entry.type === "note") {
245
- const notePosition = entry.chord ? state.lastNonChordPosition : state.position;
246
- yield {
247
- part,
248
- measure,
249
- note: entry,
250
- position: notePosition
251
- };
252
- }
253
- updatePositionForEntry(state, entry);
254
- }
255
- }
256
- }
257
- }
258
- function getAllNotes(score) {
259
- return Array.from(iterateNotes(score));
260
- }
261
- function getVoices(measure) {
262
- const voices = /* @__PURE__ */ new Set();
263
- for (const entry of measure.entries) {
264
- if (entry.type === "note") {
265
- voices.add(entry.voice ?? 1);
266
- }
267
- }
268
- return Array.from(voices).sort((a, b) => a - b);
269
- }
270
- function getStaves(measure) {
271
- const staves = /* @__PURE__ */ new Set();
272
- for (const entry of measure.entries) {
273
- if (entry.type === "note") {
274
- staves.add(entry.staff ?? 1);
275
- }
276
- }
277
- return Array.from(staves).sort((a, b) => a - b);
278
- }
279
- function hasNotes(measure) {
280
- return measure.entries.some((entry) => entry.type === "note");
281
- }
282
- function isRestMeasure(measure) {
283
- const notes = measure.entries.filter((entry) => entry.type === "note");
284
- return notes.length === 0 || notes.every((note) => !note.pitch);
285
- }
286
- function getNormalizedPosition(note, measure, options) {
287
- const absolutePosition = getAbsolutePosition(note, measure);
288
- const currentDivisions = options.currentDivisions ?? measure.attributes?.divisions ?? 1;
289
- return absolutePosition * options.baseDivisions / currentDivisions;
290
- }
291
- function getNormalizedDuration(note, options) {
292
- const currentDivisions = options.currentDivisions ?? 1;
293
- return note.duration * options.baseDivisions / currentDivisions;
294
- }
295
- function getEntriesForStaff(measure, staff) {
296
- return measure.entries.filter((entry) => {
297
- if (entry.type === "note") {
298
- return (entry.staff ?? 1) === staff;
299
- }
300
- if (entry.type === "forward") {
301
- return (entry.staff ?? 1) === staff;
302
- }
303
- if (entry.type === "direction") {
304
- return (entry.staff ?? 1) === staff;
305
- }
306
- if (entry.type === "backup") {
307
- return false;
308
- }
309
- return false;
310
- });
311
- }
312
- function buildVoiceToStaffMap(measure) {
313
- const map = /* @__PURE__ */ new Map();
314
- for (const entry of measure.entries) {
315
- if (entry.type === "note" && entry.staff !== void 0) {
316
- const voice = entry.voice ?? 1;
317
- const staff = entry.staff;
318
- if (!map.has(voice)) {
319
- map.set(voice, staff);
320
- }
321
- }
322
- }
323
- return {
324
- get: (voice) => map.get(voice),
325
- has: (voice) => map.has(voice),
326
- entries: () => map.entries(),
327
- size: map.size
328
- };
329
- }
330
- function buildVoiceToStaffMapForPart(part) {
331
- const map = /* @__PURE__ */ new Map();
332
- for (const measure of part.measures) {
333
- for (const entry of measure.entries) {
334
- if (entry.type === "note" && entry.staff !== void 0) {
335
- const voice = entry.voice ?? 1;
336
- const staff = entry.staff;
337
- if (!map.has(voice)) {
338
- map.set(voice, staff);
339
- }
340
- }
341
- }
342
- }
343
- return {
344
- get: (voice) => map.get(voice),
345
- has: (voice) => map.has(voice),
346
- entries: () => map.entries(),
347
- size: map.size
348
- };
349
- }
350
- function inferStaff(entry, voiceToStaffMap) {
351
- if (entry.staff !== void 0) {
352
- return entry.staff;
353
- }
354
- const inferredStaff = voiceToStaffMap.get(entry.voice ?? 1);
355
- if (inferredStaff !== void 0) {
356
- return inferredStaff;
357
- }
358
- return 1;
359
- }
360
- function getEffectiveStaff(entry, measure) {
361
- if (entry.staff !== void 0) {
362
- return entry.staff;
363
- }
364
- const map = buildVoiceToStaffMap(measure);
365
- return inferStaff(entry, map);
366
- }
367
- function getClefForStaff(score, options) {
368
- const part = score.parts[options.partIndex];
369
- if (!part) return void 0;
370
- for (let i = options.measureIndex; i >= 0; i--) {
371
- const measure = part.measures[i];
372
- for (const entry of measure.entries) {
373
- if (entry.type === "attributes" && entry.attributes.clef) {
374
- for (const clef of entry.attributes.clef) {
375
- if ((clef.staff ?? 1) === options.staff) {
376
- return clef;
377
- }
378
- }
379
- }
380
- }
381
- if (measure.attributes?.clef) {
382
- for (const clef of measure.attributes.clef) {
383
- if ((clef.staff ?? 1) === options.staff) {
384
- return clef;
385
- }
386
- }
387
- }
388
- }
389
- return void 0;
390
- }
391
- function getVoicesForStaff(measure, staff) {
392
- const voices = /* @__PURE__ */ new Set();
393
- for (const entry of measure.entries) {
394
- if (entry.type === "note") {
395
- const entryStaff = entry.staff ?? 1;
396
- if (entryStaff === staff) {
397
- voices.add(entry.voice ?? 1);
398
- }
399
- }
400
- }
401
- return Array.from(voices).sort((a, b) => a - b);
402
- }
403
- function getStaffRange(score, partIndex) {
404
- const part = score.parts[partIndex];
405
- if (!part) return { min: 1, max: 1 };
406
- let min = 1;
407
- let max = 1;
408
- for (const measure of part.measures) {
409
- if (measure.attributes?.staves !== void 0) {
410
- max = Math.max(max, measure.attributes.staves);
411
- }
412
- for (const entry of measure.entries) {
413
- if (entry.type === "note" && entry.staff !== void 0) {
414
- max = Math.max(max, entry.staff);
415
- }
416
- }
417
- }
418
- return { min, max };
419
- }
420
- function getEntriesAtPosition(measure, position, options) {
421
- const result = [];
422
- const state = createPositionState();
423
- for (const entry of measure.entries) {
424
- const currentPosition = entry.type === "note" && entry.chord ? state.lastNonChordPosition : state.position;
425
- if (currentPosition === position) {
426
- if (entry.type === "note") {
427
- if (options?.staff !== void 0 && (entry.staff ?? 1) !== options.staff) {
428
- updatePositionForEntry(state, entry);
429
- continue;
430
- }
431
- if (options?.voice !== void 0 && entry.voice !== options.voice) {
432
- updatePositionForEntry(state, entry);
433
- continue;
434
- }
435
- if (options?.includeChordNotes === false && entry.chord) {
436
- updatePositionForEntry(state, entry);
437
- continue;
438
- }
439
- }
440
- result.push(entry);
441
- }
442
- updatePositionForEntry(state, entry);
443
- }
444
- return result;
445
- }
446
- function getNotesAtPosition(measure, position, options) {
447
- return getEntriesAtPosition(measure, position, options).filter(
448
- (entry) => entry.type === "note"
449
- );
450
- }
451
- function getEntriesInRange(measure, range, options) {
452
- const result = [];
453
- const state = createPositionState();
454
- for (const entry of measure.entries) {
455
- const currentPosition = entry.type === "note" && entry.chord ? state.lastNonChordPosition : state.position;
456
- if (currentPosition >= range.start && currentPosition < range.end) {
457
- if (entry.type === "note") {
458
- if (options?.staff !== void 0 && (entry.staff ?? 1) !== options.staff) {
459
- updatePositionForEntry(state, entry);
460
- continue;
461
- }
462
- if (options?.voice !== void 0 && entry.voice !== options.voice) {
463
- updatePositionForEntry(state, entry);
464
- continue;
465
- }
466
- if (options?.includeChordNotes === false && entry.chord) {
467
- updatePositionForEntry(state, entry);
468
- continue;
469
- }
470
- }
471
- result.push(entry);
472
- }
473
- updatePositionForEntry(state, entry);
474
- }
475
- return result;
476
- }
477
- function getNotesInRange(measure, range, options) {
478
- return getEntriesInRange(measure, range, options).filter(
479
- (entry) => entry.type === "note"
480
- );
481
- }
482
- function getVerticalSlice(score, options) {
483
- const parts = /* @__PURE__ */ new Map();
484
- for (let partIndex = 0; partIndex < score.parts.length; partIndex++) {
485
- const part = score.parts[partIndex];
486
- const measure = part.measures[options.measureIndex];
487
- if (!measure) continue;
488
- const notes = getNotesAtPosition(measure, options.position);
489
- if (notes.length > 0) {
490
- parts.set(partIndex, notes);
491
- }
492
- }
493
- return {
494
- measureIndex: options.measureIndex,
495
- position: options.position,
496
- parts
497
- };
498
- }
499
- function getVoiceLine(score, options) {
500
- const part = score.parts[options.partIndex];
501
- if (!part) {
502
- return { partIndex: options.partIndex, voice: options.voice, staff: options.staff, notes: [] };
503
- }
504
- const notes = [];
505
- for (let measureIndex = 0; measureIndex < part.measures.length; measureIndex++) {
506
- const measure = part.measures[measureIndex];
507
- const state = createPositionState();
508
- for (const entry of measure.entries) {
509
- if (entry.type === "note") {
510
- const entryStaff = entry.staff ?? 1;
511
- const matchesVoice = entry.voice === options.voice;
512
- const matchesStaff = options.staff === void 0 || entryStaff === options.staff;
513
- if (matchesVoice && matchesStaff) {
514
- const position = entry.chord ? state.lastNonChordPosition : state.position;
515
- notes.push({
516
- note: entry,
517
- part,
518
- partIndex: options.partIndex,
519
- measure,
520
- measureIndex,
521
- position
522
- });
523
- }
524
- }
525
- updatePositionForEntry(state, entry);
526
- }
527
- }
528
- return {
529
- partIndex: options.partIndex,
530
- voice: options.voice,
531
- staff: options.staff,
532
- notes
533
- };
534
- }
535
- function getVoiceLineInRange(score, options) {
536
- const part = score.parts[options.partIndex];
537
- if (!part) {
538
- return { partIndex: options.partIndex, voice: options.voice, staff: options.staff, notes: [] };
539
- }
540
- const notes = [];
541
- for (let measureIndex = options.startMeasure; measureIndex <= options.endMeasure && measureIndex < part.measures.length; measureIndex++) {
542
- const measure = part.measures[measureIndex];
543
- const state = createPositionState();
544
- for (const entry of measure.entries) {
545
- if (entry.type === "note") {
546
- const entryStaff = entry.staff ?? 1;
547
- const matchesVoice = entry.voice === options.voice;
548
- const matchesStaff = options.staff === void 0 || entryStaff === options.staff;
549
- if (matchesVoice && matchesStaff) {
550
- const position = entry.chord ? state.lastNonChordPosition : state.position;
551
- notes.push({
552
- note: entry,
553
- part,
554
- partIndex: options.partIndex,
555
- measure,
556
- measureIndex,
557
- position
558
- });
559
- }
560
- }
561
- updatePositionForEntry(state, entry);
562
- }
563
- }
564
- return {
565
- partIndex: options.partIndex,
566
- voice: options.voice,
567
- staff: options.staff,
568
- notes
569
- };
570
- }
571
- function* iterateEntries(score) {
572
- for (let partIndex = 0; partIndex < score.parts.length; partIndex++) {
573
- const part = score.parts[partIndex];
574
- for (let measureIndex = 0; measureIndex < part.measures.length; measureIndex++) {
575
- const measure = part.measures[measureIndex];
576
- const state = createPositionState();
577
- for (const entry of measure.entries) {
578
- const position = entry.type === "note" && entry.chord ? state.lastNonChordPosition : state.position;
579
- yield {
580
- entry,
581
- part,
582
- partIndex,
583
- measure,
584
- measureIndex,
585
- position
586
- };
587
- updatePositionForEntry(state, entry);
588
- }
589
- }
590
- }
591
- }
592
- function getNextNote(score, context) {
593
- const part = score.parts[context.partIndex];
594
- if (!part) return null;
595
- let foundCurrent = false;
596
- for (let measureIndex = context.measureIndex; measureIndex < part.measures.length; measureIndex++) {
597
- const measure = part.measures[measureIndex];
598
- const state = createPositionState();
599
- for (const entry of measure.entries) {
600
- if (entry.type === "note") {
601
- const entryPosition = entry.chord ? state.lastNonChordPosition : state.position;
602
- if (measureIndex === context.measureIndex && entry === context.note) {
603
- foundCurrent = true;
604
- updatePositionForEntry(state, entry);
605
- continue;
606
- }
607
- if (foundCurrent && entry.voice === context.note.voice && !entry.chord) {
608
- if (context.note.staff !== void 0) {
609
- if ((entry.staff ?? 1) !== context.note.staff) {
610
- updatePositionForEntry(state, entry);
611
- continue;
612
- }
613
- }
614
- return {
615
- note: entry,
616
- part,
617
- partIndex: context.partIndex,
618
- measure,
619
- measureIndex,
620
- position: entryPosition
621
- };
622
- }
623
- }
624
- updatePositionForEntry(state, entry);
625
- }
626
- }
627
- return null;
628
- }
629
- function getPrevNote(score, context) {
630
- const part = score.parts[context.partIndex];
631
- if (!part) return null;
632
- let lastCandidate = null;
633
- for (let measureIndex = 0; measureIndex <= context.measureIndex; measureIndex++) {
634
- const measure = part.measures[measureIndex];
635
- const state = createPositionState();
636
- for (const entry of measure.entries) {
637
- if (entry.type === "note") {
638
- const entryPosition = entry.chord ? state.lastNonChordPosition : state.position;
639
- if (measureIndex === context.measureIndex && entry === context.note) {
640
- return lastCandidate;
641
- }
642
- if (entry.voice === context.note.voice && !entry.chord) {
643
- if (context.note.staff !== void 0) {
644
- if ((entry.staff ?? 1) !== context.note.staff) {
645
- updatePositionForEntry(state, entry);
646
- continue;
647
- }
648
- }
649
- lastCandidate = {
650
- note: entry,
651
- part,
652
- partIndex: context.partIndex,
653
- measure,
654
- measureIndex,
655
- position: entryPosition
656
- };
657
- }
658
- }
659
- updatePositionForEntry(state, entry);
660
- }
661
- }
662
- return null;
663
- }
664
- function getAdjacentNotes(score, context) {
665
- return {
666
- prev: getPrevNote(score, context),
667
- next: getNextNote(score, context)
668
- };
669
- }
670
- function getDirections(score, options) {
671
- const results = [];
672
- const startPart = options?.partIndex ?? 0;
673
- const endPart = options?.partIndex !== void 0 ? options.partIndex + 1 : score.parts.length;
674
- for (let partIndex = startPart; partIndex < endPart; partIndex++) {
675
- const part = score.parts[partIndex];
676
- if (!part) continue;
677
- const startMeasure = options?.measureIndex ?? 0;
678
- const endMeasure = options?.measureIndex !== void 0 ? options.measureIndex + 1 : part.measures.length;
679
- for (let measureIndex = startMeasure; measureIndex < endMeasure; measureIndex++) {
680
- const measure = part.measures[measureIndex];
681
- if (!measure) continue;
682
- const state = createPositionState();
683
- for (const entry of measure.entries) {
684
- if (entry.type === "direction") {
685
- results.push({
686
- direction: entry,
687
- part,
688
- partIndex,
689
- measure,
690
- measureIndex,
691
- position: state.position
692
- });
693
- }
694
- updatePositionForEntry(state, entry);
695
- }
696
- }
697
- }
698
- return results;
699
- }
700
- function getDirectionsAtPosition(measure, position) {
701
- const results = [];
702
- const state = createPositionState();
703
- for (const entry of measure.entries) {
704
- if (entry.type === "direction" && state.position === position) {
705
- results.push(entry);
706
- }
707
- updatePositionForEntry(state, entry);
708
- }
709
- return results;
710
- }
711
- function findDirectionsByType(score, kind) {
712
- const allDirections = getDirections(score);
713
- return allDirections.filter(
714
- (d) => d.direction.directionTypes.some((dt) => dt.kind === kind)
715
- );
716
- }
717
- function getDynamics(score, options) {
718
- const results = [];
719
- const startPart = options?.partIndex ?? 0;
720
- const endPart = options?.partIndex !== void 0 ? options.partIndex + 1 : score.parts.length;
721
- for (let partIndex = startPart; partIndex < endPart; partIndex++) {
722
- const part = score.parts[partIndex];
723
- if (!part) continue;
724
- for (let measureIndex = 0; measureIndex < part.measures.length; measureIndex++) {
725
- const measure = part.measures[measureIndex];
726
- const state = createPositionState();
727
- for (const entry of measure.entries) {
728
- if (entry.type === "direction") {
729
- for (const dirType of entry.directionTypes) {
730
- if (dirType.kind === "dynamics") {
731
- results.push({
732
- dynamic: dirType.value,
733
- otherDynamics: dirType.otherDynamics,
734
- direction: entry,
735
- part,
736
- partIndex,
737
- measure,
738
- measureIndex,
739
- position: state.position
740
- });
741
- }
742
- }
743
- }
744
- updatePositionForEntry(state, entry);
745
- }
746
- }
747
- }
748
- return results;
749
- }
750
- function getTempoMarkings(score) {
751
- const results = [];
752
- for (let partIndex = 0; partIndex < score.parts.length; partIndex++) {
753
- const part = score.parts[partIndex];
754
- for (let measureIndex = 0; measureIndex < part.measures.length; measureIndex++) {
755
- const measure = part.measures[measureIndex];
756
- const state = createPositionState();
757
- for (const entry of measure.entries) {
758
- if (entry.type === "direction") {
759
- for (const dirType of entry.directionTypes) {
760
- if (dirType.kind === "metronome") {
761
- results.push({
762
- beatUnit: dirType.beatUnit,
763
- perMinute: dirType.perMinute,
764
- beatUnitDot: dirType.beatUnitDot,
765
- direction: entry,
766
- partIndex,
767
- measureIndex,
768
- position: state.position
769
- });
770
- }
771
- }
772
- }
773
- updatePositionForEntry(state, entry);
774
- }
775
- }
776
- }
777
- return results;
778
- }
779
- function getPedalMarkings(score, options) {
780
- const results = [];
781
- const startPart = options?.partIndex ?? 0;
782
- const endPart = options?.partIndex !== void 0 ? options.partIndex + 1 : score.parts.length;
783
- for (let partIndex = startPart; partIndex < endPart; partIndex++) {
784
- const part = score.parts[partIndex];
785
- if (!part) continue;
786
- for (let measureIndex = 0; measureIndex < part.measures.length; measureIndex++) {
787
- const measure = part.measures[measureIndex];
788
- const state = createPositionState();
789
- for (const entry of measure.entries) {
790
- if (entry.type === "direction") {
791
- for (const dirType of entry.directionTypes) {
792
- if (dirType.kind === "pedal") {
793
- results.push({
794
- pedalType: dirType.type,
795
- direction: entry,
796
- partIndex,
797
- measureIndex,
798
- position: state.position
799
- });
800
- }
801
- }
802
- }
803
- updatePositionForEntry(state, entry);
804
- }
805
- }
806
- }
807
- return results;
808
- }
809
- function getWedges(score, options) {
810
- const results = [];
811
- const startPart = options?.partIndex ?? 0;
812
- const endPart = options?.partIndex !== void 0 ? options.partIndex + 1 : score.parts.length;
813
- for (let partIndex = startPart; partIndex < endPart; partIndex++) {
814
- const part = score.parts[partIndex];
815
- if (!part) continue;
816
- for (let measureIndex = 0; measureIndex < part.measures.length; measureIndex++) {
817
- const measure = part.measures[measureIndex];
818
- const state = createPositionState();
819
- for (const entry of measure.entries) {
820
- if (entry.type === "direction") {
821
- for (const dirType of entry.directionTypes) {
822
- if (dirType.kind === "wedge") {
823
- results.push({
824
- wedgeType: dirType.type,
825
- direction: entry,
826
- partIndex,
827
- measureIndex,
828
- position: state.position
829
- });
830
- }
831
- }
832
- }
833
- updatePositionForEntry(state, entry);
834
- }
835
- }
836
- }
837
- return results;
838
- }
839
- function getOctaveShifts(score, options) {
840
- const results = [];
841
- const startPart = options?.partIndex ?? 0;
842
- const endPart = options?.partIndex !== void 0 ? options.partIndex + 1 : score.parts.length;
843
- for (let partIndex = startPart; partIndex < endPart; partIndex++) {
844
- const part = score.parts[partIndex];
845
- if (!part) continue;
846
- for (let measureIndex = 0; measureIndex < part.measures.length; measureIndex++) {
847
- const measure = part.measures[measureIndex];
848
- const state = createPositionState();
849
- for (const entry of measure.entries) {
850
- if (entry.type === "direction") {
851
- for (const dirType of entry.directionTypes) {
852
- if (dirType.kind === "octave-shift") {
853
- results.push({
854
- shiftType: dirType.type,
855
- size: dirType.size,
856
- direction: entry,
857
- partIndex,
858
- measureIndex,
859
- position: state.position
860
- });
861
- }
862
- }
863
- }
864
- updatePositionForEntry(state, entry);
865
- }
866
- }
867
- }
868
- return results;
869
- }
870
- function getTiedNoteGroups(score, options) {
871
- const results = [];
872
- const startPart = options?.partIndex ?? 0;
873
- const endPart = options?.partIndex !== void 0 ? options.partIndex + 1 : score.parts.length;
874
- for (let partIndex = startPart; partIndex < endPart; partIndex++) {
875
- const part = score.parts[partIndex];
876
- if (!part) continue;
877
- const pendingTies = /* @__PURE__ */ new Map();
878
- for (let measureIndex = 0; measureIndex < part.measures.length; measureIndex++) {
879
- const measure = part.measures[measureIndex];
880
- const state = createPositionState();
881
- for (const entry of measure.entries) {
882
- if (entry.type === "note" && entry.pitch) {
883
- const position = entry.chord ? state.lastNonChordPosition : state.position;
884
- const pitchKey = `${entry.pitch.step}${entry.pitch.octave}-${entry.voice}`;
885
- const context = {
886
- note: entry,
887
- part,
888
- partIndex,
889
- measure,
890
- measureIndex,
891
- position
892
- };
893
- const hasTieStart = entry.tie?.type === "start" || entry.ties?.some((t) => t.type === "start") || entry.notations?.some((n) => n.type === "tied" && n.tiedType === "start");
894
- const hasTieStop = entry.tie?.type === "stop" || entry.ties?.some((t) => t.type === "stop") || entry.notations?.some((n) => n.type === "tied" && n.tiedType === "stop");
895
- if (hasTieStop && pendingTies.has(pitchKey)) {
896
- const group = pendingTies.get(pitchKey);
897
- group.push(context);
898
- if (!hasTieStart) {
899
- const totalDuration = group.reduce((sum, nc) => sum + nc.note.duration, 0);
900
- results.push({ notes: group, totalDuration });
901
- pendingTies.delete(pitchKey);
902
- }
903
- } else if (hasTieStart) {
904
- pendingTies.set(pitchKey, [context]);
905
- }
906
- }
907
- updatePositionForEntry(state, entry);
908
- }
909
- }
910
- }
911
- return results;
912
- }
913
- function getSlurSpans(score, options) {
914
- const results = [];
915
- const startPart = options?.partIndex ?? 0;
916
- const endPart = options?.partIndex !== void 0 ? options.partIndex + 1 : score.parts.length;
917
- for (let partIndex = startPart; partIndex < endPart; partIndex++) {
918
- const part = score.parts[partIndex];
919
- if (!part) continue;
920
- const pendingSlurs = /* @__PURE__ */ new Map();
921
- for (let measureIndex = 0; measureIndex < part.measures.length; measureIndex++) {
922
- const measure = part.measures[measureIndex];
923
- const state = createPositionState();
924
- for (const entry of measure.entries) {
925
- if (entry.type === "note") {
926
- const position = entry.chord ? state.lastNonChordPosition : state.position;
927
- const context = {
928
- note: entry,
929
- part,
930
- partIndex,
931
- measure,
932
- measureIndex,
933
- position
934
- };
935
- if (entry.notations) {
936
- for (const notation of entry.notations) {
937
- if (notation.type === "slur") {
938
- const slurNumber = notation.number ?? 1;
939
- if (notation.slurType === "start") {
940
- pendingSlurs.set(slurNumber, { startNote: context, notes: [context] });
941
- } else if (notation.slurType === "stop" && pendingSlurs.has(slurNumber)) {
942
- const pending = pendingSlurs.get(slurNumber);
943
- pending.notes.push(context);
944
- results.push({
945
- number: slurNumber,
946
- startNote: pending.startNote,
947
- endNote: context,
948
- notes: pending.notes
949
- });
950
- pendingSlurs.delete(slurNumber);
951
- } else if (notation.slurType === "continue" && pendingSlurs.has(slurNumber)) {
952
- pendingSlurs.get(slurNumber).notes.push(context);
953
- }
954
- }
955
- }
956
- }
957
- for (const [, pending] of pendingSlurs) {
958
- const lastNote = pending.notes[pending.notes.length - 1];
959
- if (lastNote !== context) {
960
- pending.notes.push(context);
961
- }
962
- }
963
- }
964
- updatePositionForEntry(state, entry);
965
- }
966
- }
967
- }
968
- return results;
969
- }
970
- function getTupletGroups(score, options) {
971
- const results = [];
972
- const startPart = options?.partIndex ?? 0;
973
- const endPart = options?.partIndex !== void 0 ? options.partIndex + 1 : score.parts.length;
974
- for (let partIndex = startPart; partIndex < endPart; partIndex++) {
975
- const part = score.parts[partIndex];
976
- if (!part) continue;
977
- const pendingTuplets = /* @__PURE__ */ new Map();
978
- for (let measureIndex = 0; measureIndex < part.measures.length; measureIndex++) {
979
- const measure = part.measures[measureIndex];
980
- const state = createPositionState();
981
- for (const entry of measure.entries) {
982
- if (entry.type === "note") {
983
- const position = entry.chord ? state.lastNonChordPosition : state.position;
984
- const context = {
985
- note: entry,
986
- part,
987
- partIndex,
988
- measure,
989
- measureIndex,
990
- position
991
- };
992
- if (entry.notations) {
993
- for (const notation of entry.notations) {
994
- if (notation.type === "tuplet") {
995
- const tupletNumber = notation.number ?? 1;
996
- if (notation.tupletType === "start") {
997
- const actualNotes = entry.timeModification?.actualNotes ?? 3;
998
- const normalNotes = entry.timeModification?.normalNotes ?? 2;
999
- pendingTuplets.set(tupletNumber, {
1000
- notes: [context],
1001
- actualNotes,
1002
- normalNotes
1003
- });
1004
- } else if (notation.tupletType === "stop" && pendingTuplets.has(tupletNumber)) {
1005
- const pending = pendingTuplets.get(tupletNumber);
1006
- pending.notes.push(context);
1007
- results.push({
1008
- number: tupletNumber,
1009
- notes: pending.notes,
1010
- actualNotes: pending.actualNotes,
1011
- normalNotes: pending.normalNotes
1012
- });
1013
- pendingTuplets.delete(tupletNumber);
1014
- }
1015
- }
1016
- }
1017
- }
1018
- if (entry.timeModification && !entry.notations?.some((n) => n.type === "tuplet")) {
1019
- for (const [, pending] of pendingTuplets) {
1020
- if (entry.timeModification.actualNotes === pending.actualNotes && entry.timeModification.normalNotes === pending.normalNotes) {
1021
- pending.notes.push(context);
1022
- }
1023
- }
1024
- }
1025
- }
1026
- updatePositionForEntry(state, entry);
1027
- }
1028
- }
1029
- }
1030
- return results;
1031
- }
1032
- function getBeamGroups(measure) {
1033
- const results = [];
1034
- const state = createPositionState();
1035
- const pendingBeams = /* @__PURE__ */ new Map();
1036
- for (const entry of measure.entries) {
1037
- if (entry.type === "note" && entry.beam) {
1038
- const position = entry.chord ? state.lastNonChordPosition : state.position;
1039
- const context = {
1040
- note: entry,
1041
- part: {},
1042
- // Will be set by caller if needed
1043
- partIndex: 0,
1044
- measure,
1045
- measureIndex: 0,
1046
- position
1047
- };
1048
- for (const beam of entry.beam) {
1049
- const beamNumber = beam.number;
1050
- if (beam.type === "begin") {
1051
- pendingBeams.set(beamNumber, [context]);
1052
- } else if (beam.type === "continue" && pendingBeams.has(beamNumber)) {
1053
- pendingBeams.get(beamNumber).push(context);
1054
- } else if (beam.type === "end" && pendingBeams.has(beamNumber)) {
1055
- const group = pendingBeams.get(beamNumber);
1056
- group.push(context);
1057
- results.push({
1058
- notes: group,
1059
- beamLevel: beamNumber
1060
- });
1061
- pendingBeams.delete(beamNumber);
1062
- }
1063
- }
1064
- }
1065
- updatePositionForEntry(state, entry);
1066
- }
1067
- return results;
1068
- }
1069
- function findNotesWithNotation(score, notationType, options) {
1070
- const results = [];
1071
- const startPart = options?.partIndex ?? 0;
1072
- const endPart = options?.partIndex !== void 0 ? options.partIndex + 1 : score.parts.length;
1073
- for (let partIndex = startPart; partIndex < endPart; partIndex++) {
1074
- const part = score.parts[partIndex];
1075
- if (!part) continue;
1076
- for (let measureIndex = 0; measureIndex < part.measures.length; measureIndex++) {
1077
- const measure = part.measures[measureIndex];
1078
- const state = createPositionState();
1079
- for (const entry of measure.entries) {
1080
- if (entry.type === "note") {
1081
- const position = entry.chord ? state.lastNonChordPosition : state.position;
1082
- if (entry.notations?.some((n) => n.type === notationType)) {
1083
- results.push({
1084
- note: entry,
1085
- part,
1086
- partIndex,
1087
- measure,
1088
- measureIndex,
1089
- position
1090
- });
1091
- }
1092
- }
1093
- updatePositionForEntry(state, entry);
1094
- }
1095
- }
1096
- }
1097
- return results;
1098
- }
1099
- function getHarmonies(score, options) {
1100
- const results = [];
1101
- const startPart = options?.partIndex ?? 0;
1102
- const endPart = options?.partIndex !== void 0 ? options.partIndex + 1 : score.parts.length;
1103
- for (let partIndex = startPart; partIndex < endPart; partIndex++) {
1104
- const part = score.parts[partIndex];
1105
- if (!part) continue;
1106
- for (let measureIndex = 0; measureIndex < part.measures.length; measureIndex++) {
1107
- const measure = part.measures[measureIndex];
1108
- const state = createPositionState();
1109
- for (const entry of measure.entries) {
1110
- if (entry.type === "harmony") {
1111
- results.push({
1112
- harmony: entry,
1113
- part,
1114
- partIndex,
1115
- measure,
1116
- measureIndex,
1117
- position: state.position
1118
- });
1119
- }
1120
- updatePositionForEntry(state, entry);
1121
- }
1122
- }
1123
- }
1124
- return results;
1125
- }
1126
- function getHarmonyAtPosition(measure, position) {
1127
- const state = createPositionState();
1128
- let lastHarmony;
1129
- for (const entry of measure.entries) {
1130
- if (entry.type === "harmony") {
1131
- if (state.position <= position) {
1132
- lastHarmony = entry;
1133
- }
1134
- }
1135
- updatePositionForEntry(state, entry);
1136
- if (state.position > position && lastHarmony) {
1137
- break;
1138
- }
1139
- }
1140
- return lastHarmony;
1141
- }
1142
- function getChordProgression(score, options) {
1143
- const harmonies = getHarmonies(score, options);
1144
- return harmonies.map((h) => {
1145
- const rootAlter = h.harmony.root.rootAlter ?? 0;
1146
- const rootAccidental = rootAlter > 0 ? "#".repeat(rootAlter) : "b".repeat(-rootAlter);
1147
- const root = h.harmony.root.rootStep + rootAccidental;
1148
- let bass;
1149
- if (h.harmony.bass) {
1150
- const bassAlter = h.harmony.bass.bassAlter ?? 0;
1151
- const bassAccidental = bassAlter > 0 ? "#".repeat(bassAlter) : "b".repeat(-bassAlter);
1152
- bass = h.harmony.bass.bassStep + bassAccidental;
1153
- }
1154
- return {
1155
- root,
1156
- kind: h.harmony.kind,
1157
- bass,
1158
- measureIndex: h.measureIndex,
1159
- position: h.position
1160
- };
1161
- });
1162
- }
1163
- function getLyrics(score, options) {
1164
- const results = [];
1165
- const startPart = options?.partIndex ?? 0;
1166
- const endPart = options?.partIndex !== void 0 ? options.partIndex + 1 : score.parts.length;
1167
- for (let partIndex = startPart; partIndex < endPart; partIndex++) {
1168
- const part = score.parts[partIndex];
1169
- if (!part) continue;
1170
- for (let measureIndex = 0; measureIndex < part.measures.length; measureIndex++) {
1171
- const measure = part.measures[measureIndex];
1172
- const state = createPositionState();
1173
- for (const entry of measure.entries) {
1174
- if (entry.type === "note" && entry.lyrics) {
1175
- const position = entry.chord ? state.lastNonChordPosition : state.position;
1176
- for (const lyric of entry.lyrics) {
1177
- const verse = lyric.number ?? 1;
1178
- if (options?.verse !== void 0 && verse !== options.verse) {
1179
- continue;
1180
- }
1181
- results.push({
1182
- lyric,
1183
- note: entry,
1184
- part,
1185
- partIndex,
1186
- measure,
1187
- measureIndex,
1188
- position,
1189
- verse
1190
- });
1191
- }
1192
- }
1193
- updatePositionForEntry(state, entry);
1194
- }
1195
- }
1196
- }
1197
- return results;
1198
- }
1199
- function getLyricText(score, options) {
1200
- const lyrics = getLyrics(score, options);
1201
- const verseMap = /* @__PURE__ */ new Map();
1202
- for (const lyric of lyrics) {
1203
- if (!verseMap.has(lyric.verse)) {
1204
- verseMap.set(lyric.verse, []);
1205
- }
1206
- verseMap.get(lyric.verse).push(lyric);
1207
- }
1208
- const results = [];
1209
- for (const [verse, verseLyrics] of verseMap) {
1210
- const syllables = [];
1211
- const textParts = [];
1212
- for (const lyric of verseLyrics) {
1213
- const text = lyric.lyric.text;
1214
- syllables.push({
1215
- text,
1216
- position: lyric.position,
1217
- measureIndex: lyric.measureIndex
1218
- });
1219
- const syllabic = lyric.lyric.syllabic;
1220
- if (syllabic === "begin" || syllabic === "middle") {
1221
- textParts.push(text + "-");
1222
- } else if (syllabic === "end") {
1223
- textParts.push(text + " ");
1224
- } else {
1225
- textParts.push(text + " ");
1226
- }
1227
- }
1228
- results.push({
1229
- verse,
1230
- text: textParts.join("").trim(),
1231
- syllables
1232
- });
1233
- }
1234
- return results.sort((a, b) => a.verse - b.verse);
1235
- }
1236
- function getVerseCount(score, options) {
1237
- const verses = /* @__PURE__ */ new Set();
1238
- const startPart = options?.partIndex ?? 0;
1239
- const endPart = options?.partIndex !== void 0 ? options.partIndex + 1 : score.parts.length;
1240
- for (let partIndex = startPart; partIndex < endPart; partIndex++) {
1241
- const part = score.parts[partIndex];
1242
- if (!part) continue;
1243
- for (const measure of part.measures) {
1244
- for (const entry of measure.entries) {
1245
- if (entry.type === "note" && entry.lyrics) {
1246
- for (const lyric of entry.lyrics) {
1247
- verses.add(lyric.number ?? 1);
1248
- }
1249
- }
1250
- }
1251
- }
1252
- }
1253
- return verses.size;
1254
- }
1255
- function getRepeatStructure(score, options) {
1256
- const results = [];
1257
- const partIndex = options?.partIndex ?? 0;
1258
- const part = score.parts[partIndex];
1259
- if (!part) return results;
1260
- for (let measureIndex = 0; measureIndex < part.measures.length; measureIndex++) {
1261
- const measure = part.measures[measureIndex];
1262
- const measureNumber = measure.number ?? String(measureIndex + 1);
1263
- if (measure.barlines) {
1264
- for (const barline of measure.barlines) {
1265
- if (barline.repeat) {
1266
- results.push({
1267
- type: barline.repeat.direction,
1268
- times: barline.repeat.times,
1269
- measureIndex,
1270
- measureNumber
1271
- });
1272
- }
1273
- }
1274
- }
1275
- }
1276
- return results;
1277
- }
1278
- function findBarlines(score, options) {
1279
- const results = [];
1280
- const startPart = options?.partIndex ?? 0;
1281
- const endPart = options?.partIndex !== void 0 ? options.partIndex + 1 : score.parts.length;
1282
- for (let partIndex = startPart; partIndex < endPart; partIndex++) {
1283
- const part = score.parts[partIndex];
1284
- if (!part) continue;
1285
- for (let measureIndex = 0; measureIndex < part.measures.length; measureIndex++) {
1286
- const measure = part.measures[measureIndex];
1287
- const measureNumber = measure.number ?? String(measureIndex + 1);
1288
- if (measure.barlines) {
1289
- for (const barline of measure.barlines) {
1290
- if (options?.style !== void 0 && barline.barStyle !== options.style) {
1291
- continue;
1292
- }
1293
- if (options?.repeat !== void 0) {
1294
- const hasRepeat = barline.repeat !== void 0;
1295
- if (hasRepeat !== options.repeat) {
1296
- continue;
1297
- }
1298
- }
1299
- results.push({
1300
- barline,
1301
- partIndex,
1302
- measureIndex,
1303
- measureNumber
1304
- });
1305
- }
1306
- }
1307
- }
1308
- }
1309
- return results;
1310
- }
1311
- function getEndings(score, options) {
1312
- const results = [];
1313
- const startPart = options?.partIndex ?? 0;
1314
- const endPart = options?.partIndex !== void 0 ? options.partIndex + 1 : score.parts.length;
1315
- for (let partIndex = startPart; partIndex < endPart; partIndex++) {
1316
- const part = score.parts[partIndex];
1317
- if (!part) continue;
1318
- for (let measureIndex = 0; measureIndex < part.measures.length; measureIndex++) {
1319
- const measure = part.measures[measureIndex];
1320
- const measureNumber = measure.number ?? String(measureIndex + 1);
1321
- if (measure.barlines) {
1322
- for (const barline of measure.barlines) {
1323
- if (barline.ending) {
1324
- results.push({
1325
- number: barline.ending.number,
1326
- type: barline.ending.type,
1327
- partIndex,
1328
- measureIndex,
1329
- measureNumber
1330
- });
1331
- }
1332
- }
1333
- }
1334
- }
1335
- }
1336
- return results;
1337
- }
1338
- function getKeyChanges(score, options) {
1339
- const results = [];
1340
- const startPart = options?.partIndex ?? 0;
1341
- const endPart = options?.partIndex !== void 0 ? options.partIndex + 1 : score.parts.length;
1342
- for (let partIndex = startPart; partIndex < endPart; partIndex++) {
1343
- const part = score.parts[partIndex];
1344
- if (!part) continue;
1345
- let lastKey;
1346
- for (let measureIndex = 0; measureIndex < part.measures.length; measureIndex++) {
1347
- const measure = part.measures[measureIndex];
1348
- const measureNumber = measure.number ?? String(measureIndex + 1);
1349
- const state = createPositionState();
1350
- if (measure.attributes?.key) {
1351
- const key = measure.attributes.key;
1352
- if (!lastKey || lastKey.fifths !== key.fifths || lastKey.mode !== key.mode) {
1353
- results.push({
1354
- key,
1355
- partIndex,
1356
- measureIndex,
1357
- measureNumber,
1358
- position: 0
1359
- });
1360
- lastKey = key;
1361
- }
1362
- }
1363
- for (const entry of measure.entries) {
1364
- if (entry.type === "attributes" && entry.attributes.key) {
1365
- const key = entry.attributes.key;
1366
- if (!lastKey || lastKey.fifths !== key.fifths || lastKey.mode !== key.mode) {
1367
- results.push({
1368
- key,
1369
- partIndex,
1370
- measureIndex,
1371
- measureNumber,
1372
- position: state.position
1373
- });
1374
- lastKey = key;
1375
- }
1376
- }
1377
- updatePositionForEntry(state, entry);
1378
- }
1379
- }
1380
- }
1381
- return results;
1382
- }
1383
- function getTimeChanges(score, options) {
1384
- const results = [];
1385
- const startPart = options?.partIndex ?? 0;
1386
- const endPart = options?.partIndex !== void 0 ? options.partIndex + 1 : score.parts.length;
1387
- for (let partIndex = startPart; partIndex < endPart; partIndex++) {
1388
- const part = score.parts[partIndex];
1389
- if (!part) continue;
1390
- let lastTime;
1391
- for (let measureIndex = 0; measureIndex < part.measures.length; measureIndex++) {
1392
- const measure = part.measures[measureIndex];
1393
- const measureNumber = measure.number ?? String(measureIndex + 1);
1394
- if (measure.attributes?.time) {
1395
- const time = measure.attributes.time;
1396
- if (!lastTime || lastTime.beats !== time.beats || lastTime.beatType !== time.beatType) {
1397
- results.push({
1398
- time,
1399
- partIndex,
1400
- measureIndex,
1401
- measureNumber
1402
- });
1403
- lastTime = time;
1404
- }
1405
- }
1406
- for (const entry of measure.entries) {
1407
- if (entry.type === "attributes" && entry.attributes.time) {
1408
- const time = entry.attributes.time;
1409
- if (!lastTime || lastTime.beats !== time.beats || lastTime.beatType !== time.beatType) {
1410
- results.push({
1411
- time,
1412
- partIndex,
1413
- measureIndex,
1414
- measureNumber
1415
- });
1416
- lastTime = time;
1417
- }
1418
- }
1419
- }
1420
- }
1421
- }
1422
- return results;
1423
- }
1424
- function getClefChanges(score, options) {
1425
- const results = [];
1426
- const startPart = options?.partIndex ?? 0;
1427
- const endPart = options?.partIndex !== void 0 ? options.partIndex + 1 : score.parts.length;
1428
- for (let partIndex = startPart; partIndex < endPart; partIndex++) {
1429
- const part = score.parts[partIndex];
1430
- if (!part) continue;
1431
- const lastClefs = /* @__PURE__ */ new Map();
1432
- for (let measureIndex = 0; measureIndex < part.measures.length; measureIndex++) {
1433
- const measure = part.measures[measureIndex];
1434
- const measureNumber = measure.number ?? String(measureIndex + 1);
1435
- const state = createPositionState();
1436
- if (measure.attributes?.clef) {
1437
- for (const clef of measure.attributes.clef) {
1438
- const staff = clef.staff ?? 1;
1439
- if (options?.staff !== void 0 && staff !== options.staff) {
1440
- continue;
1441
- }
1442
- const lastClef = lastClefs.get(staff);
1443
- if (!lastClef || lastClef.sign !== clef.sign || lastClef.line !== clef.line || lastClef.clefOctaveChange !== clef.clefOctaveChange) {
1444
- results.push({
1445
- clef,
1446
- staff,
1447
- partIndex,
1448
- measureIndex,
1449
- measureNumber,
1450
- position: 0
1451
- });
1452
- lastClefs.set(staff, clef);
1453
- }
1454
- }
1455
- }
1456
- for (const entry of measure.entries) {
1457
- if (entry.type === "attributes" && entry.attributes.clef) {
1458
- for (const clef of entry.attributes.clef) {
1459
- const staff = clef.staff ?? 1;
1460
- if (options?.staff !== void 0 && staff !== options.staff) {
1461
- continue;
1462
- }
1463
- const lastClef = lastClefs.get(staff);
1464
- if (!lastClef || lastClef.sign !== clef.sign || lastClef.line !== clef.line || lastClef.clefOctaveChange !== clef.clefOctaveChange) {
1465
- results.push({
1466
- clef,
1467
- staff,
1468
- partIndex,
1469
- measureIndex,
1470
- measureNumber,
1471
- position: state.position
1472
- });
1473
- lastClefs.set(staff, clef);
1474
- }
1475
- }
1476
- }
1477
- updatePositionForEntry(state, entry);
1478
- }
1479
- }
1480
- }
1481
- return results;
1482
- }
1483
- function getStructuralChanges(score, options) {
1484
- return {
1485
- keyChanges: getKeyChanges(score, options),
1486
- timeChanges: getTimeChanges(score, options),
1487
- clefChanges: getClefChanges(score, options)
1488
- };
1489
- }
1490
- function getPartByIndex(score, index) {
1491
- return score.parts[index];
1492
- }
1493
- function getPartCount(score) {
1494
- return score.parts.length;
1495
- }
1496
- function getPartIds(score) {
1497
- return score.parts.map((part) => part.id);
1498
- }
1499
- function getMeasure(score, options) {
1500
- const part = score.parts[options.part];
1501
- if (!part) return void 0;
1502
- const targetMeasure = String(options.measure);
1503
- return part.measures.find((m) => m.number === targetMeasure);
1504
- }
1505
- function getMeasureByIndex(score, options) {
1506
- const part = score.parts[options.part];
1507
- if (!part) return void 0;
1508
- return part.measures[options.measureIndex];
1509
- }
1510
- function getMeasureCount(score) {
1511
- if (score.parts.length === 0) return 0;
1512
- return score.parts[0].measures.length;
1513
- }
1514
- function getDivisions(score, options) {
1515
- const part = score.parts[options.part];
1516
- if (!part) return 1;
1517
- const targetMeasure = parseInt(String(options.measure), 10);
1518
- if (isNaN(targetMeasure)) return 1;
1519
- for (let i = 0; i < part.measures.length; i++) {
1520
- const m = part.measures[i];
1521
- const mNum = parseInt(m.number, 10);
1522
- if (!isNaN(mNum) && mNum > targetMeasure) break;
1523
- if (m.attributes?.divisions !== void 0) {
1524
- }
1525
- }
1526
- let divisions = 1;
1527
- for (const m of part.measures) {
1528
- const mNum = parseInt(m.number, 10);
1529
- if (!isNaN(mNum) && mNum > targetMeasure) break;
1530
- if (m.attributes?.divisions !== void 0) {
1531
- divisions = m.attributes.divisions;
1532
- }
1533
- }
1534
- return divisions;
1535
- }
1536
- function getAttributesAtMeasure(score, options) {
1537
- const part = score.parts[options.part];
1538
- if (!part) return {};
1539
- const targetMeasure = parseInt(String(options.measure), 10);
1540
- const result = {};
1541
- for (const m of part.measures) {
1542
- const mNum = parseInt(m.number, 10);
1543
- if (!isNaN(targetMeasure) && !isNaN(mNum) && mNum > targetMeasure) break;
1544
- if (m.attributes) {
1545
- if (m.attributes.divisions !== void 0) result.divisions = m.attributes.divisions;
1546
- if (m.attributes.time !== void 0) result.time = m.attributes.time;
1547
- if (m.attributes.key !== void 0) result.key = m.attributes.key;
1548
- if (m.attributes.clef !== void 0) result.clef = m.attributes.clef;
1549
- if (m.attributes.staves !== void 0) result.staves = m.attributes.staves;
1550
- if (m.attributes.transpose !== void 0) result.transpose = m.attributes.transpose;
1551
- }
1552
- }
1553
- return result;
1554
- }
1555
- function findNotes(score, filter) {
1556
- const results = [];
1557
- for (const part of score.parts) {
1558
- for (const measure of part.measures) {
1559
- for (const entry of measure.entries) {
1560
- if (entry.type !== "note") continue;
1561
- if (filter.pitchRange && entry.pitch) {
1562
- const noteValue = pitchToSemitone(entry.pitch);
1563
- if (filter.pitchRange.min) {
1564
- const minValue = pitchToSemitone(filter.pitchRange.min);
1565
- if (noteValue < minValue) continue;
1566
- }
1567
- if (filter.pitchRange.max) {
1568
- const maxValue = pitchToSemitone(filter.pitchRange.max);
1569
- if (noteValue > maxValue) continue;
1570
- }
1571
- }
1572
- if (filter.voice !== void 0 && entry.voice !== filter.voice) continue;
1573
- if (filter.staff !== void 0 && (entry.staff ?? 1) !== filter.staff) continue;
1574
- if (filter.noteType !== void 0 && entry.noteType !== filter.noteType) continue;
1575
- if (filter.hasTie !== void 0) {
1576
- const hasTie = entry.tie !== void 0;
1577
- if (filter.hasTie !== hasTie) continue;
1578
- }
1579
- results.push(entry);
1580
- }
1581
- }
1582
- }
1583
- return results;
1584
- }
1585
- function getDuration(score) {
1586
- if (score.parts.length === 0) return 0;
1587
- const part = score.parts[0];
1588
- let totalDuration = 0;
1589
- let divisions = 1;
1590
- for (const measure of part.measures) {
1591
- if (measure.attributes?.divisions !== void 0) {
1592
- divisions = measure.attributes.divisions;
1593
- }
1594
- let measureDuration = 0;
1595
- for (const entry of measure.entries) {
1596
- if (entry.type === "note" && !entry.chord) {
1597
- measureDuration = Math.max(measureDuration, entry.duration);
1598
- }
1599
- }
1600
- const attrs = getAttributesAtMeasure(score, { part: 0, measure: measure.number });
1601
- if (attrs.time) {
1602
- const beats = parseInt(attrs.time.beats, 10) || 4;
1603
- const expectedDuration = beats / attrs.time.beatType * 4 * divisions;
1604
- measureDuration = Math.max(measureDuration, expectedDuration);
1605
- }
1606
- totalDuration += measureDuration;
1607
- }
1608
- return totalDuration;
1609
- }
1610
- function getPartById(score, id) {
1611
- return score.parts.find((p) => p.id === id);
1612
- }
1613
- function getPartIndex(score, id) {
1614
- return score.parts.findIndex((p) => p.id === id);
1615
- }
1616
- function hasMultipleStaves(score, partIndex = 0) {
1617
- const part = score.parts[partIndex];
1618
- if (!part) return false;
1619
- for (const measure of part.measures) {
1620
- if (measure.attributes?.staves !== void 0 && measure.attributes.staves > 1) {
1621
- return true;
1622
- }
1623
- }
1624
- return false;
1625
- }
1626
- function getStaveCount(score, partIndex = 0) {
1627
- const part = score.parts[partIndex];
1628
- if (!part) return 1;
1629
- for (const measure of part.measures) {
1630
- if (measure.attributes?.staves !== void 0) {
1631
- return measure.attributes.staves;
1632
- }
1633
- }
1634
- return 1;
1635
- }
1636
- function measureRoundtrip(original, exported) {
1637
- const notesOriginal = countNotes(original);
1638
- const notesExported = countNotes(exported);
1639
- const notesPreserved = Math.min(notesOriginal, notesExported);
1640
- const measuresOriginal = getMeasureCount(original);
1641
- const measuresExported = getMeasureCount(exported);
1642
- const measuresPreserved = Math.min(measuresOriginal, measuresExported);
1643
- const partsOriginal = original.parts.length;
1644
- const partsExported = exported.parts.length;
1645
- const partsPreserved = Math.min(partsOriginal, partsExported);
1646
- const preservationRate = notesOriginal > 0 ? notesPreserved / notesOriginal : 1;
1647
- return {
1648
- notesOriginal,
1649
- notesPreserved,
1650
- measuresOriginal,
1651
- measuresPreserved,
1652
- partsOriginal,
1653
- partsPreserved,
1654
- preservationRate
1655
- };
1656
- }
1657
- function countNotes(score) {
1658
- let count = 0;
1659
- for (const part of score.parts) {
1660
- for (const measure of part.measures) {
1661
- for (const entry of measure.entries) {
1662
- if (entry.type === "note") {
1663
- count++;
1664
- }
1665
- }
1666
- }
1667
- }
1668
- return count;
1669
- }
1670
- function scoresEqual(a, b) {
1671
- if (a.parts.length !== b.parts.length) return false;
1672
- for (let i = 0; i < a.parts.length; i++) {
1673
- const partA = a.parts[i];
1674
- const partB = b.parts[i];
1675
- if (partA.measures.length !== partB.measures.length) return false;
1676
- for (let j = 0; j < partA.measures.length; j++) {
1677
- const measureA = partA.measures[j];
1678
- const measureB = partB.measures[j];
1679
- if (measureA.number !== measureB.number) return false;
1680
- const notesA = measureA.entries.filter((e) => e.type === "note");
1681
- const notesB = measureB.entries.filter((e) => e.type === "note");
1682
- if (notesA.length !== notesB.length) return false;
1683
- for (let k = 0; k < notesA.length; k++) {
1684
- const noteA = notesA[k];
1685
- const noteB = notesB[k];
1686
- if (!pitchesEqual(noteA.pitch, noteB.pitch)) return false;
1687
- if (noteA.duration !== noteB.duration) return false;
1688
- if (noteA.voice !== noteB.voice) return false;
1689
- }
1690
- }
1691
- }
1692
- return true;
1693
- }
1694
- function pitchesEqual(a, b) {
1695
- if (a === void 0 && b === void 0) return true;
1696
- if (a === void 0 || b === void 0) return false;
1697
- return a.step === b.step && a.octave === b.octave && (a.alter ?? 0) === (b.alter ?? 0);
1698
- }
1699
- // Annotate the CommonJS export names for ESM import in node:
1700
- 0 && (module.exports = {
1701
- buildVoiceToStaffMap,
1702
- buildVoiceToStaffMapForPart,
1703
- countNotes,
1704
- findBarlines,
1705
- findDirectionsByType,
1706
- findNotes,
1707
- findNotesWithNotation,
1708
- getAbsolutePosition,
1709
- getAdjacentNotes,
1710
- getAllNotes,
1711
- getAttributesAtMeasure,
1712
- getBeamGroups,
1713
- getChordProgression,
1714
- getChords,
1715
- getClefChanges,
1716
- getClefForStaff,
1717
- getDirections,
1718
- getDirectionsAtPosition,
1719
- getDivisions,
1720
- getDuration,
1721
- getDynamics,
1722
- getEffectiveStaff,
1723
- getEndings,
1724
- getEntriesAtPosition,
1725
- getEntriesForStaff,
1726
- getEntriesInRange,
1727
- getHarmonies,
1728
- getHarmonyAtPosition,
1729
- getKeyChanges,
1730
- getLyricText,
1731
- getLyrics,
1732
- getMeasure,
1733
- getMeasureByIndex,
1734
- getMeasureCount,
1735
- getNextNote,
1736
- getNormalizedDuration,
1737
- getNormalizedPosition,
1738
- getNotesAtPosition,
1739
- getNotesForStaff,
1740
- getNotesForVoice,
1741
- getNotesInRange,
1742
- getOctaveShifts,
1743
- getPartById,
1744
- getPartByIndex,
1745
- getPartCount,
1746
- getPartIds,
1747
- getPartIndex,
1748
- getPedalMarkings,
1749
- getPrevNote,
1750
- getRepeatStructure,
1751
- getSlurSpans,
1752
- getStaffRange,
1753
- getStaveCount,
1754
- getStaves,
1755
- getStructuralChanges,
1756
- getTempoMarkings,
1757
- getTiedNoteGroups,
1758
- getTimeChanges,
1759
- getTupletGroups,
1760
- getVerseCount,
1761
- getVerticalSlice,
1762
- getVoiceLine,
1763
- getVoiceLineInRange,
1764
- getVoices,
1765
- getVoicesForStaff,
1766
- getWedges,
1767
- groupByStaff,
1768
- groupByVoice,
1769
- hasMultipleStaves,
1770
- hasNotes,
1771
- inferStaff,
1772
- isRestMeasure,
1773
- iterateEntries,
1774
- iterateNotes,
1775
- measureRoundtrip,
1776
- scoresEqual,
1777
- withAbsolutePositions
1778
- });
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
+
3
+
4
+
5
+
6
+
7
+
8
+
9
+
10
+
11
+
12
+
13
+
14
+
15
+
16
+
17
+
18
+
19
+
20
+
21
+
22
+
23
+
24
+
25
+
26
+
27
+
28
+
29
+
30
+
31
+
32
+
33
+
34
+
35
+
36
+
37
+
38
+
39
+
40
+
41
+
42
+
43
+
44
+
45
+
46
+
47
+
48
+
49
+
50
+
51
+
52
+
53
+
54
+
55
+
56
+
57
+
58
+
59
+
60
+
61
+
62
+
63
+
64
+
65
+
66
+
67
+
68
+
69
+
70
+
71
+
72
+
73
+
74
+
75
+
76
+
77
+
78
+
79
+ var _chunkTIFUKSTHjs = require('../chunk-TIFUKSTH.js');
80
+
81
+
82
+
83
+
84
+
85
+
86
+
87
+
88
+
89
+
90
+
91
+
92
+
93
+
94
+
95
+
96
+
97
+
98
+
99
+
100
+
101
+
102
+
103
+
104
+
105
+
106
+
107
+
108
+
109
+
110
+
111
+
112
+
113
+
114
+
115
+
116
+
117
+
118
+
119
+
120
+
121
+
122
+
123
+
124
+
125
+
126
+
127
+
128
+
129
+
130
+
131
+
132
+
133
+
134
+
135
+
136
+
137
+
138
+
139
+
140
+
141
+
142
+
143
+
144
+
145
+
146
+
147
+
148
+
149
+
150
+
151
+
152
+
153
+
154
+
155
+
156
+
157
+
158
+ exports.buildVoiceToStaffMap = _chunkTIFUKSTHjs.buildVoiceToStaffMap; exports.buildVoiceToStaffMapForPart = _chunkTIFUKSTHjs.buildVoiceToStaffMapForPart; exports.countNotes = _chunkTIFUKSTHjs.countNotes; exports.findBarlines = _chunkTIFUKSTHjs.findBarlines; exports.findDirectionsByType = _chunkTIFUKSTHjs.findDirectionsByType; exports.findNotes = _chunkTIFUKSTHjs.findNotes; exports.findNotesWithNotation = _chunkTIFUKSTHjs.findNotesWithNotation; exports.getAbsolutePosition = _chunkTIFUKSTHjs.getAbsolutePosition; exports.getAdjacentNotes = _chunkTIFUKSTHjs.getAdjacentNotes; exports.getAllNotes = _chunkTIFUKSTHjs.getAllNotes; exports.getAttributesAtMeasure = _chunkTIFUKSTHjs.getAttributesAtMeasure; exports.getBeamGroups = _chunkTIFUKSTHjs.getBeamGroups; exports.getChordProgression = _chunkTIFUKSTHjs.getChordProgression; exports.getChords = _chunkTIFUKSTHjs.getChords; exports.getClefChanges = _chunkTIFUKSTHjs.getClefChanges; exports.getClefForStaff = _chunkTIFUKSTHjs.getClefForStaff; exports.getDirections = _chunkTIFUKSTHjs.getDirections; exports.getDirectionsAtPosition = _chunkTIFUKSTHjs.getDirectionsAtPosition; exports.getDivisions = _chunkTIFUKSTHjs.getDivisions; exports.getDuration = _chunkTIFUKSTHjs.getDuration; exports.getDynamics = _chunkTIFUKSTHjs.getDynamics; exports.getEffectiveStaff = _chunkTIFUKSTHjs.getEffectiveStaff; exports.getEndings = _chunkTIFUKSTHjs.getEndings; exports.getEntriesAtPosition = _chunkTIFUKSTHjs.getEntriesAtPosition; exports.getEntriesForStaff = _chunkTIFUKSTHjs.getEntriesForStaff; exports.getEntriesInRange = _chunkTIFUKSTHjs.getEntriesInRange; exports.getHarmonies = _chunkTIFUKSTHjs.getHarmonies; exports.getHarmonyAtPosition = _chunkTIFUKSTHjs.getHarmonyAtPosition; exports.getKeyChanges = _chunkTIFUKSTHjs.getKeyChanges; exports.getLyricText = _chunkTIFUKSTHjs.getLyricText; exports.getLyrics = _chunkTIFUKSTHjs.getLyrics; exports.getMeasure = _chunkTIFUKSTHjs.getMeasure; exports.getMeasureByIndex = _chunkTIFUKSTHjs.getMeasureByIndex; exports.getMeasureCount = _chunkTIFUKSTHjs.getMeasureCount; exports.getNextNote = _chunkTIFUKSTHjs.getNextNote; exports.getNormalizedDuration = _chunkTIFUKSTHjs.getNormalizedDuration; exports.getNormalizedPosition = _chunkTIFUKSTHjs.getNormalizedPosition; exports.getNotesAtPosition = _chunkTIFUKSTHjs.getNotesAtPosition; exports.getNotesForStaff = _chunkTIFUKSTHjs.getNotesForStaff; exports.getNotesForVoice = _chunkTIFUKSTHjs.getNotesForVoice; exports.getNotesInRange = _chunkTIFUKSTHjs.getNotesInRange; exports.getOctaveShifts = _chunkTIFUKSTHjs.getOctaveShifts; exports.getPartById = _chunkTIFUKSTHjs.getPartById; exports.getPartByIndex = _chunkTIFUKSTHjs.getPartByIndex; exports.getPartCount = _chunkTIFUKSTHjs.getPartCount; exports.getPartIds = _chunkTIFUKSTHjs.getPartIds; exports.getPartIndex = _chunkTIFUKSTHjs.getPartIndex; exports.getPedalMarkings = _chunkTIFUKSTHjs.getPedalMarkings; exports.getPrevNote = _chunkTIFUKSTHjs.getPrevNote; exports.getRepeatStructure = _chunkTIFUKSTHjs.getRepeatStructure; exports.getSlurSpans = _chunkTIFUKSTHjs.getSlurSpans; exports.getStaffRange = _chunkTIFUKSTHjs.getStaffRange; exports.getStaveCount = _chunkTIFUKSTHjs.getStaveCount; exports.getStaves = _chunkTIFUKSTHjs.getStaves; exports.getStructuralChanges = _chunkTIFUKSTHjs.getStructuralChanges; exports.getTempoMarkings = _chunkTIFUKSTHjs.getTempoMarkings; exports.getTiedNoteGroups = _chunkTIFUKSTHjs.getTiedNoteGroups; exports.getTimeChanges = _chunkTIFUKSTHjs.getTimeChanges; exports.getTupletGroups = _chunkTIFUKSTHjs.getTupletGroups; exports.getVerseCount = _chunkTIFUKSTHjs.getVerseCount; exports.getVerticalSlice = _chunkTIFUKSTHjs.getVerticalSlice; exports.getVoiceLine = _chunkTIFUKSTHjs.getVoiceLine; exports.getVoiceLineInRange = _chunkTIFUKSTHjs.getVoiceLineInRange; exports.getVoices = _chunkTIFUKSTHjs.getVoices; exports.getVoicesForStaff = _chunkTIFUKSTHjs.getVoicesForStaff; exports.getWedges = _chunkTIFUKSTHjs.getWedges; exports.groupByStaff = _chunkTIFUKSTHjs.groupByStaff; exports.groupByVoice = _chunkTIFUKSTHjs.groupByVoice; exports.hasMultipleStaves = _chunkTIFUKSTHjs.hasMultipleStaves; exports.hasNotes = _chunkTIFUKSTHjs.hasNotes; exports.inferStaff = _chunkTIFUKSTHjs.inferStaff; exports.isRestMeasure = _chunkTIFUKSTHjs.isRestMeasure; exports.iterateEntries = _chunkTIFUKSTHjs.iterateEntries; exports.iterateNotes = _chunkTIFUKSTHjs.iterateNotes; exports.measureRoundtrip = _chunkTIFUKSTHjs.measureRoundtrip; exports.scoresEqual = _chunkTIFUKSTHjs.scoresEqual; exports.withAbsolutePositions = _chunkTIFUKSTHjs.withAbsolutePositions;