musicxml-io 0.7.1 → 0.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-F6GPX6VW.js → chunk-CHMV7XWY.js} +259 -83
- package/dist/{chunk-67F7TX3I.mjs → chunk-IM3FS32Q.mjs} +1 -1
- package/dist/{chunk-HQEOMBJX.js → chunk-S5MWUJU2.js} +23 -23
- package/dist/{chunk-MA2TPIIG.mjs → chunk-VQUFSGB5.mjs} +191 -15
- package/dist/index.d.mts +7 -4
- package/dist/index.d.ts +7 -4
- package/dist/index.js +160 -156
- package/dist/index.mjs +42 -38
- package/dist/operations/index.js +3 -3
- package/dist/operations/index.mjs +2 -2
- package/dist/query/index.d.mts +53 -2
- package/dist/query/index.d.ts +53 -2
- package/dist/query/index.js +2 -2
- package/dist/query/index.mjs +1 -1
- package/package.json +1 -1
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
var
|
|
11
|
+
var _chunkCHMV7XWYjs = require('./chunk-CHMV7XWY.js');
|
|
12
12
|
|
|
13
13
|
// src/id.ts
|
|
14
14
|
var _nanoid = require('nanoid');
|
|
@@ -1562,18 +1562,18 @@ function setNotePitchBySemitone(score, options) {
|
|
|
1562
1562
|
const result = cloneScore(score);
|
|
1563
1563
|
const measure = result.parts[options.partIndex].measures[options.measureIndex];
|
|
1564
1564
|
const measureNumber = _nullishCoalesce(measure.number, () => ( String(options.measureIndex + 1)));
|
|
1565
|
-
const attrs =
|
|
1565
|
+
const attrs = _chunkCHMV7XWYjs.getAttributesAtMeasure.call(void 0, result, { part: options.partIndex, measure: measureNumber });
|
|
1566
1566
|
const keySignature = _nullishCoalesce(attrs.key, () => ( { fifths: 0 }));
|
|
1567
1567
|
let noteCount = 0;
|
|
1568
1568
|
for (const entry of measure.entries) {
|
|
1569
1569
|
if (entry.type === "note" && !entry.rest) {
|
|
1570
1570
|
if (noteCount === options.noteIndex) {
|
|
1571
|
-
const notePosition =
|
|
1572
|
-
const accidentalsInMeasure =
|
|
1573
|
-
const newPitch =
|
|
1571
|
+
const notePosition = _chunkCHMV7XWYjs.getAbsolutePositionForNote.call(void 0, entry, measure);
|
|
1572
|
+
const accidentalsInMeasure = _chunkCHMV7XWYjs.getAccidentalsInMeasure.call(void 0, measure, notePosition, entry.voice);
|
|
1573
|
+
const newPitch = _chunkCHMV7XWYjs.semitoneToKeyAwarePitch.call(void 0, options.semitone, keySignature, {
|
|
1574
1574
|
preferSharp: options.preferSharp
|
|
1575
1575
|
});
|
|
1576
|
-
const accidental =
|
|
1576
|
+
const accidental = _chunkCHMV7XWYjs.determineAccidental.call(void 0, newPitch, keySignature, accidentalsInMeasure);
|
|
1577
1577
|
entry.pitch = newPitch;
|
|
1578
1578
|
if (accidental) {
|
|
1579
1579
|
entry.accidental = { value: accidental };
|
|
@@ -1607,7 +1607,7 @@ function shiftNotePitch(score, options) {
|
|
|
1607
1607
|
if (!entry.pitch) {
|
|
1608
1608
|
return failure([operationError("NOTE_NOT_FOUND", "Note has no pitch", { partIndex: options.partIndex, measureIndex: options.measureIndex })]);
|
|
1609
1609
|
}
|
|
1610
|
-
currentSemitone =
|
|
1610
|
+
currentSemitone = _chunkCHMV7XWYjs.pitchToSemitone.call(void 0, entry.pitch);
|
|
1611
1611
|
break;
|
|
1612
1612
|
}
|
|
1613
1613
|
noteCount++;
|
|
@@ -1635,7 +1635,7 @@ function raiseAccidental(score, options) {
|
|
|
1635
1635
|
const result = cloneScore(score);
|
|
1636
1636
|
const measure = result.parts[options.partIndex].measures[options.measureIndex];
|
|
1637
1637
|
const measureNumber = _nullishCoalesce(measure.number, () => ( String(options.measureIndex + 1)));
|
|
1638
|
-
const attrs =
|
|
1638
|
+
const attrs = _chunkCHMV7XWYjs.getAttributesAtMeasure.call(void 0, result, { part: options.partIndex, measure: measureNumber });
|
|
1639
1639
|
const keySignature = _nullishCoalesce(attrs.key, () => ( { fifths: 0 }));
|
|
1640
1640
|
let noteCount = 0;
|
|
1641
1641
|
for (const entry of measure.entries) {
|
|
@@ -1650,9 +1650,9 @@ function raiseAccidental(score, options) {
|
|
|
1650
1650
|
return failure([operationError("ACCIDENTAL_OUT_OF_BOUNDS", `Cannot raise accidental beyond double-sharp (current: ${currentAlter})`, { partIndex: options.partIndex, measureIndex: options.measureIndex })]);
|
|
1651
1651
|
}
|
|
1652
1652
|
entry.pitch.alter = newAlter === 0 ? void 0 : newAlter;
|
|
1653
|
-
const notePosition =
|
|
1654
|
-
const accidentalsInMeasure =
|
|
1655
|
-
const accidental =
|
|
1653
|
+
const notePosition = _chunkCHMV7XWYjs.getAbsolutePositionForNote.call(void 0, entry, measure);
|
|
1654
|
+
const accidentalsInMeasure = _chunkCHMV7XWYjs.getAccidentalsInMeasure.call(void 0, measure, notePosition, entry.voice);
|
|
1655
|
+
const accidental = _chunkCHMV7XWYjs.determineAccidental.call(void 0, entry.pitch, keySignature, accidentalsInMeasure);
|
|
1656
1656
|
if (accidental) {
|
|
1657
1657
|
entry.accidental = { value: accidental };
|
|
1658
1658
|
} else {
|
|
@@ -1676,7 +1676,7 @@ function lowerAccidental(score, options) {
|
|
|
1676
1676
|
const result = cloneScore(score);
|
|
1677
1677
|
const measure = result.parts[options.partIndex].measures[options.measureIndex];
|
|
1678
1678
|
const measureNumber = _nullishCoalesce(measure.number, () => ( String(options.measureIndex + 1)));
|
|
1679
|
-
const attrs =
|
|
1679
|
+
const attrs = _chunkCHMV7XWYjs.getAttributesAtMeasure.call(void 0, result, { part: options.partIndex, measure: measureNumber });
|
|
1680
1680
|
const keySignature = _nullishCoalesce(attrs.key, () => ( { fifths: 0 }));
|
|
1681
1681
|
let noteCount = 0;
|
|
1682
1682
|
for (const entry of measure.entries) {
|
|
@@ -1691,9 +1691,9 @@ function lowerAccidental(score, options) {
|
|
|
1691
1691
|
return failure([operationError("ACCIDENTAL_OUT_OF_BOUNDS", `Cannot lower accidental beyond double-flat (current: ${currentAlter})`, { partIndex: options.partIndex, measureIndex: options.measureIndex })]);
|
|
1692
1692
|
}
|
|
1693
1693
|
entry.pitch.alter = newAlter === 0 ? void 0 : newAlter;
|
|
1694
|
-
const notePosition =
|
|
1695
|
-
const accidentalsInMeasure =
|
|
1696
|
-
const accidental =
|
|
1694
|
+
const notePosition = _chunkCHMV7XWYjs.getAbsolutePositionForNote.call(void 0, entry, measure);
|
|
1695
|
+
const accidentalsInMeasure = _chunkCHMV7XWYjs.getAccidentalsInMeasure.call(void 0, measure, notePosition, entry.voice);
|
|
1696
|
+
const accidental = _chunkCHMV7XWYjs.determineAccidental.call(void 0, entry.pitch, keySignature, accidentalsInMeasure);
|
|
1697
1697
|
if (accidental) {
|
|
1698
1698
|
entry.accidental = { value: accidental };
|
|
1699
1699
|
} else {
|
|
@@ -1727,7 +1727,7 @@ function addVoice(score, options) {
|
|
|
1727
1727
|
const context = getMeasureContext(result, options.partIndex, options.measureIndex);
|
|
1728
1728
|
const measureDuration = context.time ? getMeasureDuration(context.divisions, context.time) : context.divisions * 4;
|
|
1729
1729
|
const rest = createRest(measureDuration, options.voice, options.staff);
|
|
1730
|
-
const currentEnd =
|
|
1730
|
+
const currentEnd = _chunkCHMV7XWYjs.getMeasureEndPosition.call(void 0, measure);
|
|
1731
1731
|
if (currentEnd > 0) {
|
|
1732
1732
|
measure.entries.push({ _id: generateId(), type: "backup", duration: currentEnd });
|
|
1733
1733
|
}
|
|
@@ -1735,14 +1735,14 @@ function addVoice(score, options) {
|
|
|
1735
1735
|
return success(result);
|
|
1736
1736
|
}
|
|
1737
1737
|
function transposePitch(pitch, semitones) {
|
|
1738
|
-
const currentSemitone =
|
|
1738
|
+
const currentSemitone = _chunkCHMV7XWYjs.STEP_SEMITONES[pitch.step] + (_nullishCoalesce(pitch.alter, () => ( 0))) + pitch.octave * 12;
|
|
1739
1739
|
const targetSemitone = currentSemitone + semitones;
|
|
1740
1740
|
const targetOctave = Math.floor(targetSemitone / 12);
|
|
1741
1741
|
const targetPitchClass = (targetSemitone % 12 + 12) % 12;
|
|
1742
1742
|
let bestStep = "C";
|
|
1743
1743
|
let bestAlter = 99;
|
|
1744
|
-
for (const step of
|
|
1745
|
-
const stepSemitone =
|
|
1744
|
+
for (const step of _chunkCHMV7XWYjs.STEPS) {
|
|
1745
|
+
const stepSemitone = _chunkCHMV7XWYjs.STEP_SEMITONES[step];
|
|
1746
1746
|
let diff = targetPitchClass - stepSemitone;
|
|
1747
1747
|
if (diff > 6) diff -= 12;
|
|
1748
1748
|
if (diff < -6) diff += 12;
|
|
@@ -3805,7 +3805,7 @@ function addDaCapo(score, options) {
|
|
|
3805
3805
|
}
|
|
3806
3806
|
const result = cloneScore(score);
|
|
3807
3807
|
const measure = result.parts[partIndex].measures[measureIndex];
|
|
3808
|
-
const attrs =
|
|
3808
|
+
const attrs = _chunkCHMV7XWYjs.getAttributesAtMeasure.call(void 0, result, { part: partIndex, measure: measureIndex });
|
|
3809
3809
|
const measureDuration = getMeasureDuration(_nullishCoalesce(attrs.divisions, () => ( 1)), _nullishCoalesce(attrs.time, () => ( { beats: "4", beatType: 4 })));
|
|
3810
3810
|
const insertPos = _nullishCoalesce(position, () => ( measureDuration));
|
|
3811
3811
|
const direction = {
|
|
@@ -3834,7 +3834,7 @@ function addDalSegno(score, options) {
|
|
|
3834
3834
|
}
|
|
3835
3835
|
const result = cloneScore(score);
|
|
3836
3836
|
const measure = result.parts[partIndex].measures[measureIndex];
|
|
3837
|
-
const attrs =
|
|
3837
|
+
const attrs = _chunkCHMV7XWYjs.getAttributesAtMeasure.call(void 0, result, { part: partIndex, measure: measureIndex });
|
|
3838
3838
|
const measureDuration = getMeasureDuration(_nullishCoalesce(attrs.divisions, () => ( 1)), _nullishCoalesce(attrs.time, () => ( { beats: "4", beatType: 4 })));
|
|
3839
3839
|
const insertPos = _nullishCoalesce(position, () => ( measureDuration));
|
|
3840
3840
|
const direction = {
|
|
@@ -3863,7 +3863,7 @@ function addFine(score, options) {
|
|
|
3863
3863
|
}
|
|
3864
3864
|
const result = cloneScore(score);
|
|
3865
3865
|
const measure = result.parts[partIndex].measures[measureIndex];
|
|
3866
|
-
const attrs =
|
|
3866
|
+
const attrs = _chunkCHMV7XWYjs.getAttributesAtMeasure.call(void 0, result, { part: partIndex, measure: measureIndex });
|
|
3867
3867
|
const measureDuration = getMeasureDuration(_nullishCoalesce(attrs.divisions, () => ( 1)), _nullishCoalesce(attrs.time, () => ( { beats: "4", beatType: 4 })));
|
|
3868
3868
|
const insertPos = _nullishCoalesce(position, () => ( measureDuration));
|
|
3869
3869
|
const direction = {
|
|
@@ -3892,7 +3892,7 @@ function addToCoda(score, options) {
|
|
|
3892
3892
|
}
|
|
3893
3893
|
const result = cloneScore(score);
|
|
3894
3894
|
const measure = result.parts[partIndex].measures[measureIndex];
|
|
3895
|
-
const attrs =
|
|
3895
|
+
const attrs = _chunkCHMV7XWYjs.getAttributesAtMeasure.call(void 0, result, { part: partIndex, measure: measureIndex });
|
|
3896
3896
|
const measureDuration = getMeasureDuration(_nullishCoalesce(attrs.divisions, () => ( 1)), _nullishCoalesce(attrs.time, () => ( { beats: "4", beatType: 4 })));
|
|
3897
3897
|
const insertPos = _nullishCoalesce(position, () => ( measureDuration));
|
|
3898
3898
|
const direction = {
|
|
@@ -510,6 +510,10 @@ function hasPlaybackControls(score, options) {
|
|
|
510
510
|
}
|
|
511
511
|
|
|
512
512
|
// src/query/playback-timeline.ts
|
|
513
|
+
var DEFAULT_FERMATA_HOLD = 1.75;
|
|
514
|
+
var DEFAULT_CAESURA_SECONDS = 0.4;
|
|
515
|
+
var DEFAULT_BREATH_SECONDS = 0.25;
|
|
516
|
+
var DEFAULT_RAMP_STEPS = 12;
|
|
513
517
|
function metronomeBpm(perMinute) {
|
|
514
518
|
if (perMinute === void 0) return null;
|
|
515
519
|
const bpm = typeof perMinute === "number" ? perMinute : parseFloat(perMinute);
|
|
@@ -562,15 +566,48 @@ function measureEndTick(measure, part, divisions, measureStartTick, maxPosition,
|
|
|
562
566
|
}
|
|
563
567
|
return measureStartTick + actualTicks;
|
|
564
568
|
}
|
|
565
|
-
function
|
|
566
|
-
|
|
569
|
+
function hasFermata(note) {
|
|
570
|
+
return note.notations?.some((n) => n.type === "fermata") ?? false;
|
|
571
|
+
}
|
|
572
|
+
function pauseArticulation(note) {
|
|
573
|
+
if (!note.notations) return null;
|
|
574
|
+
for (const n of note.notations) {
|
|
575
|
+
if (n.type === "articulation") {
|
|
576
|
+
if (n.articulation === "caesura") return "caesura";
|
|
577
|
+
if (n.articulation === "breath-mark") return "breath";
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
return null;
|
|
581
|
+
}
|
|
582
|
+
function tempoRampWord(text) {
|
|
583
|
+
const t = text.trim().toLowerCase().replace(/[.\s]+$/, "");
|
|
584
|
+
if (!t) return null;
|
|
585
|
+
if (/^(rit|riten|rall|allarg|slarg|cala|smorz|morend)/.test(t)) return "rit";
|
|
586
|
+
if (/^(accel|string|affret|incalz|pi[uù]\s*mosso)/.test(t)) return "accel";
|
|
587
|
+
return null;
|
|
588
|
+
}
|
|
589
|
+
function buildGridTimeline(score, ticksPerQuarterNote, sequence, options = {}) {
|
|
590
|
+
const rawTempo = [];
|
|
567
591
|
const measures = [];
|
|
592
|
+
const rampMarkers = [];
|
|
593
|
+
const stretches = [];
|
|
568
594
|
if (score.parts.length === 0) {
|
|
569
|
-
return { tempoEvents, measures, totalTicks: 0 };
|
|
595
|
+
return { tempoEvents: [], measures, totalTicks: 0, expressions: [] };
|
|
570
596
|
}
|
|
597
|
+
const fermataHold = options.fermataHoldMultiplier ?? DEFAULT_FERMATA_HOLD;
|
|
598
|
+
const caesuraSeconds = options.caesuraSeconds ?? DEFAULT_CAESURA_SECONDS;
|
|
599
|
+
const breathSeconds = options.breathSeconds ?? DEFAULT_BREATH_SECONDS;
|
|
600
|
+
const rampSteps = Math.max(1, Math.round(options.tempoRampSteps ?? DEFAULT_RAMP_STEPS));
|
|
601
|
+
const defaultTempo = options.defaultTempo ?? 120;
|
|
571
602
|
const part = score.parts[0];
|
|
572
603
|
let divisions = 1;
|
|
573
604
|
let currentTick = 0;
|
|
605
|
+
let prevailingBpm = defaultTempo;
|
|
606
|
+
const pauseFactor = (windowTicks, bpm, pauseSeconds) => {
|
|
607
|
+
const baseSeconds = windowTicks / ticksPerQuarterNote * (60 / bpm);
|
|
608
|
+
if (baseSeconds <= 0) return 1;
|
|
609
|
+
return (baseSeconds + pauseSeconds) / baseSeconds;
|
|
610
|
+
};
|
|
574
611
|
for (const { measureIndex, repeatIteration } of sequence) {
|
|
575
612
|
const measure = part.measures[measureIndex];
|
|
576
613
|
if (!measure) continue;
|
|
@@ -579,22 +616,62 @@ function buildGridTimeline(score, ticksPerQuarterNote, sequence) {
|
|
|
579
616
|
}
|
|
580
617
|
const measureStartTick = currentTick;
|
|
581
618
|
let position = 0;
|
|
619
|
+
let chordBasePosition = 0;
|
|
582
620
|
const tickAt = (pos) => measureStartTick + Math.round(pos * ticksPerQuarterNote / divisions);
|
|
583
621
|
for (const entry of measure.entries) {
|
|
584
622
|
if (entry.type === "direction") {
|
|
585
623
|
for (const dirType of entry.directionTypes) {
|
|
586
624
|
if (dirType.kind === "metronome") {
|
|
587
625
|
const bpm = metronomeBpm(dirType.perMinute);
|
|
588
|
-
if (bpm !== null)
|
|
626
|
+
if (bpm !== null) {
|
|
627
|
+
rawTempo.push({ tick: tickAt(position), bpm });
|
|
628
|
+
prevailingBpm = bpm;
|
|
629
|
+
}
|
|
630
|
+
} else if (dirType.kind === "words") {
|
|
631
|
+
const kind = tempoRampWord(dirType.text);
|
|
632
|
+
if (kind) rampMarkers.push({ tick: tickAt(position), kind });
|
|
589
633
|
}
|
|
590
634
|
}
|
|
591
635
|
if (entry.sound?.tempo) {
|
|
592
|
-
|
|
636
|
+
rawTempo.push({ tick: tickAt(position), bpm: entry.sound.tempo });
|
|
637
|
+
prevailingBpm = entry.sound.tempo;
|
|
593
638
|
}
|
|
594
639
|
} else if (entry.type === "sound") {
|
|
595
|
-
if (entry.tempo)
|
|
596
|
-
|
|
597
|
-
|
|
640
|
+
if (entry.tempo) {
|
|
641
|
+
rawTempo.push({ tick: tickAt(position), bpm: entry.tempo });
|
|
642
|
+
prevailingBpm = entry.tempo;
|
|
643
|
+
}
|
|
644
|
+
} else if (entry.type === "note") {
|
|
645
|
+
const notePos = entry.chord ? chordBasePosition : position;
|
|
646
|
+
const noteStartTick = tickAt(notePos);
|
|
647
|
+
const noteEndTick = tickAt(notePos + entry.duration);
|
|
648
|
+
if (noteEndTick > noteStartTick) {
|
|
649
|
+
if (fermataHold !== 1 && hasFermata(entry)) {
|
|
650
|
+
stretches.push({
|
|
651
|
+
startTick: noteStartTick,
|
|
652
|
+
endTick: noteEndTick,
|
|
653
|
+
factor: fermataHold,
|
|
654
|
+
type: "fermata"
|
|
655
|
+
});
|
|
656
|
+
}
|
|
657
|
+
const pause = pauseArticulation(entry);
|
|
658
|
+
if (pause) {
|
|
659
|
+
const seconds = pause === "caesura" ? caesuraSeconds : breathSeconds;
|
|
660
|
+
if (seconds > 0) {
|
|
661
|
+
const window = Math.min(noteEndTick - noteStartTick, ticksPerQuarterNote);
|
|
662
|
+
stretches.push({
|
|
663
|
+
startTick: noteEndTick - window,
|
|
664
|
+
endTick: noteEndTick,
|
|
665
|
+
factor: pauseFactor(window, prevailingBpm, seconds),
|
|
666
|
+
type: pause
|
|
667
|
+
});
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
if (!entry.chord) {
|
|
672
|
+
chordBasePosition = position;
|
|
673
|
+
position += entry.duration;
|
|
674
|
+
}
|
|
598
675
|
} else if (entry.type === "backup") {
|
|
599
676
|
position -= entry.duration;
|
|
600
677
|
} else if (entry.type === "forward") {
|
|
@@ -618,28 +695,112 @@ function buildGridTimeline(score, ticksPerQuarterNote, sequence) {
|
|
|
618
695
|
});
|
|
619
696
|
currentTick = endTick;
|
|
620
697
|
}
|
|
621
|
-
|
|
698
|
+
const { tempoEvents, expressions } = bakeTempoMap(
|
|
699
|
+
rawTempo,
|
|
700
|
+
rampMarkers,
|
|
701
|
+
stretches,
|
|
702
|
+
defaultTempo,
|
|
703
|
+
rampSteps
|
|
704
|
+
);
|
|
705
|
+
return { tempoEvents, measures, totalTicks: currentTick, expressions };
|
|
706
|
+
}
|
|
707
|
+
function bakeTempoMap(rawTempo, rampMarkers, stretches, defaultTempo, rampSteps) {
|
|
708
|
+
const sortedRaw = [...rawTempo].sort((a, b) => a.tick - b.tick);
|
|
709
|
+
const startBpm = sortedRaw.length > 0 && sortedRaw[0].tick === 0 ? sortedRaw[0].bpm : defaultTempo;
|
|
710
|
+
const baseChanges = [{ tick: 0, bpm: startBpm }];
|
|
711
|
+
let lastBpm = startBpm;
|
|
712
|
+
for (const ev of sortedRaw) {
|
|
713
|
+
if (ev.tick === 0) continue;
|
|
714
|
+
if (ev.bpm === lastBpm) continue;
|
|
715
|
+
if (baseChanges[baseChanges.length - 1].tick === ev.tick) {
|
|
716
|
+
baseChanges[baseChanges.length - 1].bpm = ev.bpm;
|
|
717
|
+
} else {
|
|
718
|
+
baseChanges.push({ tick: ev.tick, bpm: ev.bpm });
|
|
719
|
+
}
|
|
720
|
+
lastBpm = ev.bpm;
|
|
721
|
+
}
|
|
722
|
+
const baseBpmAt = (tick) => {
|
|
723
|
+
let i = baseChanges.length - 1;
|
|
724
|
+
while (i > 0 && baseChanges[i].tick > tick) i--;
|
|
725
|
+
return baseChanges[i].bpm;
|
|
726
|
+
};
|
|
727
|
+
const rampExpressions = [];
|
|
728
|
+
const rampPoints = [];
|
|
729
|
+
for (const marker of rampMarkers) {
|
|
730
|
+
const from = baseBpmAt(marker.tick);
|
|
731
|
+
const next = baseChanges.find((c) => c.tick > marker.tick && c.bpm !== from);
|
|
732
|
+
if (!next) continue;
|
|
733
|
+
const span = next.tick - marker.tick;
|
|
734
|
+
if (span <= 0) continue;
|
|
735
|
+
for (let k = 1; k < rampSteps; k++) {
|
|
736
|
+
const tick = Math.round(marker.tick + span * k / rampSteps);
|
|
737
|
+
if (tick <= marker.tick || tick >= next.tick) continue;
|
|
738
|
+
const bpm = from + (next.bpm - from) * k / rampSteps;
|
|
739
|
+
rampPoints.push({ tick, bpm });
|
|
740
|
+
}
|
|
741
|
+
rampExpressions.push({ type: marker.kind, startTick: marker.tick, endTick: next.tick });
|
|
742
|
+
}
|
|
743
|
+
const baseTicks = new Set(baseChanges.map((c) => c.tick));
|
|
744
|
+
const stepList = [...baseChanges];
|
|
745
|
+
for (const p of rampPoints) {
|
|
746
|
+
if (!baseTicks.has(p.tick)) stepList.push(p);
|
|
747
|
+
}
|
|
748
|
+
stepList.sort((a, b) => a.tick - b.tick);
|
|
749
|
+
const stepBpmAt = (tick) => {
|
|
750
|
+
let i = stepList.length - 1;
|
|
751
|
+
while (i > 0 && stepList[i].tick > tick) i--;
|
|
752
|
+
return stepList[i].bpm;
|
|
753
|
+
};
|
|
754
|
+
const boundaries = new Set(stepList.map((s) => s.tick));
|
|
755
|
+
for (const s of stretches) {
|
|
756
|
+
boundaries.add(s.startTick);
|
|
757
|
+
boundaries.add(s.endTick);
|
|
758
|
+
}
|
|
759
|
+
const sortedBoundaries = [...boundaries].sort((a, b) => a - b);
|
|
760
|
+
const tempoEvents = [];
|
|
761
|
+
let emittedBpm = null;
|
|
762
|
+
for (const tick of sortedBoundaries) {
|
|
763
|
+
let bpm = stepBpmAt(tick);
|
|
764
|
+
for (const s of stretches) {
|
|
765
|
+
if (tick >= s.startTick && tick < s.endTick) bpm /= s.factor;
|
|
766
|
+
}
|
|
767
|
+
if (emittedBpm === null || bpm !== emittedBpm) {
|
|
768
|
+
tempoEvents.push({ tick, bpm });
|
|
769
|
+
emittedBpm = bpm;
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
const expressions = [
|
|
773
|
+
...stretches.map((s) => ({ type: s.type, startTick: s.startTick, endTick: s.endTick })),
|
|
774
|
+
...rampExpressions
|
|
775
|
+
].sort((a, b) => a.startTick - b.startTick || a.endTick - b.endTick);
|
|
776
|
+
return { tempoEvents, expressions };
|
|
777
|
+
}
|
|
778
|
+
function bpmToUsPerQuarter(bpm) {
|
|
779
|
+
return Math.round(6e7 / bpm);
|
|
622
780
|
}
|
|
623
781
|
function makeTickToSec(tempoEvents, defaultTempo, ticksPerQuarterNote) {
|
|
624
782
|
const sorted = [...tempoEvents].sort((a, b) => a.tick - b.tick);
|
|
625
783
|
const startBpm = sorted.length > 0 && sorted[0].tick === 0 ? sorted[0].bpm : defaultTempo;
|
|
626
|
-
const changes = [
|
|
784
|
+
const changes = [
|
|
785
|
+
{ tick: 0, usPerQuarter: bpmToUsPerQuarter(startBpm) }
|
|
786
|
+
];
|
|
627
787
|
let lastBpm = startBpm;
|
|
628
788
|
for (const ev of sorted) {
|
|
629
789
|
if (ev.tick === 0) continue;
|
|
630
790
|
if (ev.bpm === lastBpm) continue;
|
|
631
|
-
changes.push({ tick: ev.tick,
|
|
791
|
+
changes.push({ tick: ev.tick, usPerQuarter: bpmToUsPerQuarter(ev.bpm) });
|
|
632
792
|
lastBpm = ev.bpm;
|
|
633
793
|
}
|
|
794
|
+
const secPerTick = (usPerQuarter) => usPerQuarter / 1e6 / ticksPerQuarterNote;
|
|
634
795
|
const cumSec = [0];
|
|
635
796
|
for (let i = 1; i < changes.length; i++) {
|
|
636
797
|
const dTick = changes[i].tick - changes[i - 1].tick;
|
|
637
|
-
cumSec[i] = cumSec[i - 1] + dTick
|
|
798
|
+
cumSec[i] = cumSec[i - 1] + dTick * secPerTick(changes[i - 1].usPerQuarter);
|
|
638
799
|
}
|
|
639
800
|
return (tick) => {
|
|
640
801
|
let i = changes.length - 1;
|
|
641
802
|
while (i > 0 && changes[i].tick > tick) i--;
|
|
642
|
-
return cumSec[i] + (tick - changes[i].tick)
|
|
803
|
+
return cumSec[i] + (tick - changes[i].tick) * secPerTick(changes[i].usPerQuarter);
|
|
643
804
|
};
|
|
644
805
|
}
|
|
645
806
|
function buildTimingSidecar(grid, defaultTempo, ticksPerQuarterNote) {
|
|
@@ -676,18 +837,32 @@ function buildTimingSidecar(grid, defaultTempo, ticksPerQuarterNote) {
|
|
|
676
837
|
repeatIteration: last ? last.repeatIteration : 0
|
|
677
838
|
});
|
|
678
839
|
breakpoints.sort((a, b) => a.midiSec - b.midiSec || a.quarterPos - b.quarterPos);
|
|
679
|
-
|
|
840
|
+
const sidecar = {
|
|
680
841
|
version: "1",
|
|
681
842
|
durationSec: tickToSec(grid.totalTicks),
|
|
682
843
|
ticksPerQuarterNote,
|
|
683
844
|
breakpoints
|
|
684
845
|
};
|
|
846
|
+
if (grid.expressions.length > 0) {
|
|
847
|
+
sidecar.expressions = grid.expressions.map((e) => ({
|
|
848
|
+
type: e.type,
|
|
849
|
+
fromMidiSec: tickToSec(e.startTick),
|
|
850
|
+
toMidiSec: tickToSec(e.endTick)
|
|
851
|
+
})).sort((a, b) => a.fromMidiSec - b.fromMidiSec || a.toMidiSec - b.toMidiSec);
|
|
852
|
+
}
|
|
853
|
+
return sidecar;
|
|
685
854
|
}
|
|
686
855
|
function generatePlaybackTimeline(score, options = {}) {
|
|
687
856
|
const ticksPerQuarterNote = options.ticksPerQuarterNote ?? 480;
|
|
688
857
|
const defaultTempo = options.defaultTempo ?? 120;
|
|
689
858
|
const sequence = generatePlaybackSequence(score);
|
|
690
|
-
const grid = buildGridTimeline(score, ticksPerQuarterNote, sequence
|
|
859
|
+
const grid = buildGridTimeline(score, ticksPerQuarterNote, sequence, {
|
|
860
|
+
defaultTempo,
|
|
861
|
+
fermataHoldMultiplier: options.fermataHoldMultiplier,
|
|
862
|
+
caesuraSeconds: options.caesuraSeconds,
|
|
863
|
+
breathSeconds: options.breathSeconds,
|
|
864
|
+
tempoRampSteps: options.tempoRampSteps
|
|
865
|
+
});
|
|
691
866
|
return buildTimingSidecar(grid, defaultTempo, ticksPerQuarterNote);
|
|
692
867
|
}
|
|
693
868
|
|
|
@@ -2246,6 +2421,7 @@ export {
|
|
|
2246
2421
|
hasPlaybackControls,
|
|
2247
2422
|
measureEndTick,
|
|
2248
2423
|
buildGridTimeline,
|
|
2424
|
+
bpmToUsPerQuarter,
|
|
2249
2425
|
buildTimingSidecar,
|
|
2250
2426
|
generatePlaybackTimeline,
|
|
2251
2427
|
STEPS,
|
package/dist/index.d.mts
CHANGED
|
@@ -2,8 +2,8 @@ import { S as Score, P as Pitch, M as Measure, D as DirectionType, a as Directio
|
|
|
2
2
|
export { A as Accidental, j as AccidentalInfo, O as AdjacentNotes, a4 as AssembledLyrics, B as BackupEntry, p as Barline, a5 as BarlineWithContext, a0 as BeamGroup, k as BeamInfo, s as Chord, C as Clef, aa as ClefChangeInfo, w as Credit, v as Defaults, Q as DirectionKind, z as DirectionWithContext, R as DynamicWithContext, m as DynamicsValue, a7 as EndingInfo, E as EntryWithContext, F as ForwardEntry, a2 as HarmonyWithContext, a8 as KeyChangeInfo, K as KeySignature, L as Lyric, a3 as LyricWithContext, g as MeasureAttributes, h as MeasureEntry, l as Notation, a1 as NotationType, t as NoteIteratorItem, i as NoteType, y as NoteWithContext, r as NoteWithPosition, Y as OctaveShiftWithContext, f as Part, e as PartGroup, W as PedalWithContext, H as PositionQueryOptions, u as Print, a6 as RepeatInfo, d as ScoreMetadata, _ as SlurSpan, q as StaffGroup, G as StaffRange, ab as StructuralChanges, U as TempoWithContext, T as TieInfo, Z as TiedNoteGroup, a9 as TimeChangeInfo, n as TimeSignature, o as Transpose, $ as TupletGroup, I as VerticalSlice, V as VoiceGroup, J as VoiceLine, x as VoiceToStaffMap, X as WedgeWithContext } from './types-CkeI8vw6.mjs';
|
|
3
3
|
import { V as ValidateOptions, a as ValidationResult } from './index-8MkN7sbm.mjs';
|
|
4
4
|
export { ba as AddArticulationOptions, bj as AddBeamOptions, c8 as AddBowingOptions, ch as AddBreathMarkOptions, ck as AddCaesuraOptions, aW as AddChordOptions, c2 as AddChordSymbolOptions, bS as AddCodaOptions, bc as AddDynamicsOptions, bM as AddEndingOptions, bz as AddFermataOptions, c5 as AddFingeringOptions, bU as AddGraceNoteOptions, b$ as AddHarmonyOptions, bX as AddLyricOptions, bT as AddNavigationOptions, cd as AddOctaveShiftOptions, bB as AddOrnamentOptions, b2 as AddPartOptions, bD as AddPedalOptions, bH as AddRehearsalMarkOptions, bI as AddRepeatBarlineOptions, bK as AddRepeatOptions, bR as AddSegnoOptions, b8 as AddSlurOptions, ca as AddStringNumberOptions, bu as AddTempoOptions, bF as AddTextDirectionOptions, bG as AddTextOptions, b6 as AddTieOptions, b1 as AddVoiceOptions, bx as AddWedgeOptions, bl as AutoBeamOptions, bQ as BarStyle, c7 as BowingType, cg as BreathMarkValue, cj as CaesuraValue, bO as ChangeBarlineOptions, bg as ChangeClefOptions, aX as ChangeNoteDurationOptions, bW as ConvertToGraceOptions, br as CopyNotesMultiMeasureOptions, bo as CopyNotesOptions, bh as CreateTupletOptions, bq as CutNotesOptions, b3 as DuplicatePartOptions, b_ as HarmonyKind, bf as InsertClefChangeOptions, aU as InsertNoteOptions, cM as LocalValidateOptions, b0 as LowerAccidentalOptions, cL as MeasureValidationContext, be as ModifyDynamicsOptions, bw as ModifyTempoOptions, b5 as MoveNoteToStaffOptions, bs as MultiMeasureSelection, bn as NoteSelection, cc as OctaveShiftType, aT as OperationErrorCode, aS as OperationResult, bt as PasteNotesMultiMeasureOptions, bp as PasteNotesOptions, a$ as RaiseAccidentalOptions, bb as RemoveArticulationOptions, bk as RemoveBeamOptions, c9 as RemoveBowingOptions, ci as RemoveBreathMarkOptions, cl as RemoveCaesuraOptions, c3 as RemoveChordSymbolOptions, bd as RemoveDynamicsOptions, bN as RemoveEndingOptions, bA as RemoveFermataOptions, c6 as RemoveFingeringOptions, bV as RemoveGraceNoteOptions, c0 as RemoveHarmonyOptions, bY as RemoveLyricOptions, aV as RemoveNoteOptions, cf as RemoveOctaveShiftOptions, bC as RemoveOrnamentOptions, bE as RemovePedalOptions, bJ as RemoveRepeatBarlineOptions, bL as RemoveRepeatOptions, b9 as RemoveSlurOptions, cb as RemoveStringNumberOptions, bv as RemoveTempoOptions, b7 as RemoveTieOptions, bi as RemoveTupletOptions, by as RemoveWedgeOptions, bP as SetBarlineOptions, bm as SetBeamingOptions, aZ as SetNotePitchBySemitoneOptions, aY as SetNotePitchOptions, b4 as SetStavesOptions, a_ as ShiftNotePitchOptions, ce as StopOctaveShiftOptions, c4 as UpdateChordSymbolOptions, c1 as UpdateHarmonyOptions, bZ as UpdateLyricOptions, cH as ValidationError, cJ as ValidationErrorCode, cD as ValidationException, cK as ValidationLevel, cI as ValidationLocation, K as addArticulation, T as addBeam, aH as addBowing, aO as addBreathMark, aQ as addCaesura, b as addChord, j as addChordNote, p as addChordNoteChecked, aC as addChordSymbol, ao as addCoda, ap as addDaCapo, aq as addDalSegno, M as addDynamics, aj as addEnding, a6 as addFermata, ar as addFine, aF as addFingering, at as addGraceNote, az as addHarmony, aw as addLyric, g as addNote, n as addNoteChecked, aL as addOctaveShift, a8 as addOrnament, x as addPart, aa as addPedal, ae as addRehearsalMark, ah as addRepeat, af as addRepeatBarline, an as addSegno, I as addSlur, aJ as addStringNumber, a1 as addTempo, ad as addText, ac as addTextDirection, G as addTie, as as addToCoda, w as addVoice, a4 as addWedge, cG as assertMeasureValid, co as assertValid, W as autoBeam, al as changeBarline, Q as changeClef, C as changeKey, e as changeNoteDuration, D as changeTime, av as convertToGrace, Y as copyNotes, $ as copyNotesMultiMeasure, R as createTuplet, _ as cutNotes, F as deleteMeasure, h as deleteNote, o as deleteNoteChecked, z as duplicatePart, cC as formatLocation, cF as getMeasureContext, P as insertClefChange, E as insertMeasure, i as insertNote, cn as isValid, l as lowerAccidental, O as modifyDynamics, k as modifyNoteDuration, u as modifyNoteDurationChecked, m as modifyNotePitch, q as modifyNotePitchChecked, a3 as modifyTempo, B as moveNoteToStaff, Z as pasteNotes, a0 as pasteNotesMultiMeasure, f as raiseAccidental, L as removeArticulation, U as removeBeam, aI as removeBowing, aP as removeBreathMark, aR as removeCaesura, aD as removeChordSymbol, N as removeDynamics, ak as removeEnding, a7 as removeFermata, aG as removeFingering, au as removeGraceNote, aA as removeHarmony, ax as removeLyric, r as removeNote, aN as removeOctaveShift, a9 as removeOrnament, y as removePart, ab as removePedal, ai as removeRepeat, ag as removeRepeatBarline, J as removeSlur, aK as removeStringNumber, a2 as removeTempo, H as removeTie, S as removeTuplet, a5 as removeWedge, am as setBarline, X as setBeaming, s as setNotePitch, c as setNotePitchBySemitone, A as setStaves, d as shiftNotePitch, aM as stopOctaveShift, t as transpose, v as transposeChecked, aE as updateChordSymbol, aB as updateHarmony, ay as updateLyric, cm as validate, cr as validateBackupForward, ct as validateBeams, cp as validateDivisions, cq as validateMeasureDuration, cE as validateMeasureLocal, cw as validatePartReferences, cx as validatePartStructure, cu as validateSlurs, cB as validateSlursAcrossMeasures, cy as validateStaffStructure, cs as validateTies, cA as validateTiesAcrossMeasures, cv as validateTuplets, cz as validateVoiceStaff } from './index-8MkN7sbm.mjs';
|
|
5
|
-
import { TimingSidecar } from './query/index.mjs';
|
|
6
|
-
export { FindNotesFilter, NormalizedPositionOptions, PitchRange, PlaybackControls, PlaybackMeasure, RoundtripMetrics, TimingBreakpoint, TimingMapOptions, VoiceFilter, buildVoiceToStaffMap, buildVoiceToStaffMapForPart, countNotes, extractPlaybackControls, findBarlines, findDirectionsByType, findNotes, findNotesWithNotation, generatePlaybackSequence, generatePlaybackTimeline, getAbsolutePosition, getAdjacentNotes, getAllNotes, getAttributesAtMeasure, getBeamGroups, getChordProgression, getChords, getClefChanges, getClefForStaff, getDirections, getDirectionsAtPosition, getDivisions, getDuration, getDynamics, getEffectiveStaff, getEndings, getEntriesAtPosition, getEntriesForStaff, getEntriesInRange, getHarmonies, getHarmonyAtPosition, getKeyChanges, getLyricText, getLyrics, getMeasure, getMeasureByIndex, getMeasureCount, getNextNote, getNormalizedDuration, getNormalizedPosition, getNotesAtPosition, getNotesForStaff, getNotesForVoice, getNotesInRange, getOctaveShifts, getPartById, getPartByIndex, getPartCount, getPartIds, getPartIndex, getPedalMarkings, getPrevNote, getRepeatStructure, getSlurSpans, getStaffRange, getStaveCount, getStaves, getStructuralChanges, getTempoMarkings, getTiedNoteGroups, getTimeChanges, getTupletGroups, getVerseCount, getVerticalSlice, getVoiceLine, getVoiceLineInRange, getVoices, getVoicesForStaff, getWedges, groupByStaff, groupByVoice, hasMultipleStaves, hasNotes, hasPlaybackControls, inferStaff, isRestMeasure, iterateEntries, iterateNotes, measureRoundtrip, scoresEqual, withAbsolutePositions } from './query/index.mjs';
|
|
5
|
+
import { ExpressionOptions, TimingSidecar } from './query/index.mjs';
|
|
6
|
+
export { ExpressionHint, ExpressionKind, FindNotesFilter, NormalizedPositionOptions, PitchRange, PlaybackControls, PlaybackMeasure, RoundtripMetrics, TimingBreakpoint, TimingMapOptions, VoiceFilter, buildVoiceToStaffMap, buildVoiceToStaffMapForPart, countNotes, extractPlaybackControls, findBarlines, findDirectionsByType, findNotes, findNotesWithNotation, generatePlaybackSequence, generatePlaybackTimeline, getAbsolutePosition, getAdjacentNotes, getAllNotes, getAttributesAtMeasure, getBeamGroups, getChordProgression, getChords, getClefChanges, getClefForStaff, getDirections, getDirectionsAtPosition, getDivisions, getDuration, getDynamics, getEffectiveStaff, getEndings, getEntriesAtPosition, getEntriesForStaff, getEntriesInRange, getHarmonies, getHarmonyAtPosition, getKeyChanges, getLyricText, getLyrics, getMeasure, getMeasureByIndex, getMeasureCount, getNextNote, getNormalizedDuration, getNormalizedPosition, getNotesAtPosition, getNotesForStaff, getNotesForVoice, getNotesInRange, getOctaveShifts, getPartById, getPartByIndex, getPartCount, getPartIds, getPartIndex, getPedalMarkings, getPrevNote, getRepeatStructure, getSlurSpans, getStaffRange, getStaveCount, getStaves, getStructuralChanges, getTempoMarkings, getTiedNoteGroups, getTimeChanges, getTupletGroups, getVerseCount, getVerticalSlice, getVoiceLine, getVoiceLineInRange, getVoices, getVoicesForStaff, getWedges, groupByStaff, groupByVoice, hasMultipleStaves, hasNotes, hasPlaybackControls, inferStaff, isRestMeasure, iterateEntries, iterateNotes, measureRoundtrip, scoresEqual, withAbsolutePositions } from './query/index.mjs';
|
|
7
7
|
|
|
8
8
|
declare function parse(input: string | Uint8Array): Score;
|
|
9
9
|
|
|
@@ -76,8 +76,11 @@ declare function serializeCompressed(score: Score, options?: SerializeOptions):
|
|
|
76
76
|
|
|
77
77
|
/**
|
|
78
78
|
* MIDI export options
|
|
79
|
+
*
|
|
80
|
+
* Extends {@link ExpressionOptions} so fermata holds and rit./accel. ramps land
|
|
81
|
+
* in the exported tempo map (and the timing sidecar) identically.
|
|
79
82
|
*/
|
|
80
|
-
interface MidiExportOptions {
|
|
83
|
+
interface MidiExportOptions extends ExpressionOptions {
|
|
81
84
|
/** Ticks per quarter note (default: 480) */
|
|
82
85
|
ticksPerQuarterNote?: number;
|
|
83
86
|
/** Default tempo in BPM (default: 120) */
|
|
@@ -375,4 +378,4 @@ declare function getPartNameMap(score: Score): Record<string, string | undefined
|
|
|
375
378
|
*/
|
|
376
379
|
declare function generateId(): string;
|
|
377
380
|
|
|
378
|
-
export { type AbcSerializeOptions, DirectionEntry, DirectionType, type DirectionTypeOfKind, Measure, type MidiExportOptions, type MidiWithTimingMap, NoteEntry, PartInfo, PartListEntry, Pitch, STEPS, STEP_SEMITONES, Score, type SerializeOptions, TimingSidecar, ValidateOptions, ValidationResult, decodeBuffer, exportMidi, exportMidiWithTimingMap, generateId, getAllPartInfos, getDirectionOfKind, getDirectionsOfKind, getMeasureEndPosition, getPartAbbreviation, getPartInfo, getPartName, getPartNameMap, getSoundDamperPedal, getSoundDynamics, getSoundSoftPedal, getSoundSostenutoPedal, getSoundTempo, hasBeam, hasDirectionOfKind, hasLyrics, hasNotations, hasTie, hasTieStart, hasTieStop, hasTuplet, isChordNote, isCompressed, isCueNote, isGraceNote, isPartInfo, isPitchedNote, isRest, isUnpitchedNote, parse, parseAbc, parseAuto, parseCompressed, parseFile, pitchToSemitone, serialize, serializeAbc, serializeCompressed, serializeToFile };
|
|
381
|
+
export { type AbcSerializeOptions, DirectionEntry, DirectionType, type DirectionTypeOfKind, ExpressionOptions, Measure, type MidiExportOptions, type MidiWithTimingMap, NoteEntry, PartInfo, PartListEntry, Pitch, STEPS, STEP_SEMITONES, Score, type SerializeOptions, TimingSidecar, ValidateOptions, ValidationResult, decodeBuffer, exportMidi, exportMidiWithTimingMap, generateId, getAllPartInfos, getDirectionOfKind, getDirectionsOfKind, getMeasureEndPosition, getPartAbbreviation, getPartInfo, getPartName, getPartNameMap, getSoundDamperPedal, getSoundDynamics, getSoundSoftPedal, getSoundSostenutoPedal, getSoundTempo, hasBeam, hasDirectionOfKind, hasLyrics, hasNotations, hasTie, hasTieStart, hasTieStop, hasTuplet, isChordNote, isCompressed, isCueNote, isGraceNote, isPartInfo, isPitchedNote, isRest, isUnpitchedNote, parse, parseAbc, parseAuto, parseCompressed, parseFile, pitchToSemitone, serialize, serializeAbc, serializeCompressed, serializeToFile };
|
package/dist/index.d.ts
CHANGED
|
@@ -2,8 +2,8 @@ import { S as Score, P as Pitch, M as Measure, D as DirectionType, a as Directio
|
|
|
2
2
|
export { A as Accidental, j as AccidentalInfo, O as AdjacentNotes, a4 as AssembledLyrics, B as BackupEntry, p as Barline, a5 as BarlineWithContext, a0 as BeamGroup, k as BeamInfo, s as Chord, C as Clef, aa as ClefChangeInfo, w as Credit, v as Defaults, Q as DirectionKind, z as DirectionWithContext, R as DynamicWithContext, m as DynamicsValue, a7 as EndingInfo, E as EntryWithContext, F as ForwardEntry, a2 as HarmonyWithContext, a8 as KeyChangeInfo, K as KeySignature, L as Lyric, a3 as LyricWithContext, g as MeasureAttributes, h as MeasureEntry, l as Notation, a1 as NotationType, t as NoteIteratorItem, i as NoteType, y as NoteWithContext, r as NoteWithPosition, Y as OctaveShiftWithContext, f as Part, e as PartGroup, W as PedalWithContext, H as PositionQueryOptions, u as Print, a6 as RepeatInfo, d as ScoreMetadata, _ as SlurSpan, q as StaffGroup, G as StaffRange, ab as StructuralChanges, U as TempoWithContext, T as TieInfo, Z as TiedNoteGroup, a9 as TimeChangeInfo, n as TimeSignature, o as Transpose, $ as TupletGroup, I as VerticalSlice, V as VoiceGroup, J as VoiceLine, x as VoiceToStaffMap, X as WedgeWithContext } from './types-CkeI8vw6.js';
|
|
3
3
|
import { V as ValidateOptions, a as ValidationResult } from './index-DxLMCMTr.js';
|
|
4
4
|
export { ba as AddArticulationOptions, bj as AddBeamOptions, c8 as AddBowingOptions, ch as AddBreathMarkOptions, ck as AddCaesuraOptions, aW as AddChordOptions, c2 as AddChordSymbolOptions, bS as AddCodaOptions, bc as AddDynamicsOptions, bM as AddEndingOptions, bz as AddFermataOptions, c5 as AddFingeringOptions, bU as AddGraceNoteOptions, b$ as AddHarmonyOptions, bX as AddLyricOptions, bT as AddNavigationOptions, cd as AddOctaveShiftOptions, bB as AddOrnamentOptions, b2 as AddPartOptions, bD as AddPedalOptions, bH as AddRehearsalMarkOptions, bI as AddRepeatBarlineOptions, bK as AddRepeatOptions, bR as AddSegnoOptions, b8 as AddSlurOptions, ca as AddStringNumberOptions, bu as AddTempoOptions, bF as AddTextDirectionOptions, bG as AddTextOptions, b6 as AddTieOptions, b1 as AddVoiceOptions, bx as AddWedgeOptions, bl as AutoBeamOptions, bQ as BarStyle, c7 as BowingType, cg as BreathMarkValue, cj as CaesuraValue, bO as ChangeBarlineOptions, bg as ChangeClefOptions, aX as ChangeNoteDurationOptions, bW as ConvertToGraceOptions, br as CopyNotesMultiMeasureOptions, bo as CopyNotesOptions, bh as CreateTupletOptions, bq as CutNotesOptions, b3 as DuplicatePartOptions, b_ as HarmonyKind, bf as InsertClefChangeOptions, aU as InsertNoteOptions, cM as LocalValidateOptions, b0 as LowerAccidentalOptions, cL as MeasureValidationContext, be as ModifyDynamicsOptions, bw as ModifyTempoOptions, b5 as MoveNoteToStaffOptions, bs as MultiMeasureSelection, bn as NoteSelection, cc as OctaveShiftType, aT as OperationErrorCode, aS as OperationResult, bt as PasteNotesMultiMeasureOptions, bp as PasteNotesOptions, a$ as RaiseAccidentalOptions, bb as RemoveArticulationOptions, bk as RemoveBeamOptions, c9 as RemoveBowingOptions, ci as RemoveBreathMarkOptions, cl as RemoveCaesuraOptions, c3 as RemoveChordSymbolOptions, bd as RemoveDynamicsOptions, bN as RemoveEndingOptions, bA as RemoveFermataOptions, c6 as RemoveFingeringOptions, bV as RemoveGraceNoteOptions, c0 as RemoveHarmonyOptions, bY as RemoveLyricOptions, aV as RemoveNoteOptions, cf as RemoveOctaveShiftOptions, bC as RemoveOrnamentOptions, bE as RemovePedalOptions, bJ as RemoveRepeatBarlineOptions, bL as RemoveRepeatOptions, b9 as RemoveSlurOptions, cb as RemoveStringNumberOptions, bv as RemoveTempoOptions, b7 as RemoveTieOptions, bi as RemoveTupletOptions, by as RemoveWedgeOptions, bP as SetBarlineOptions, bm as SetBeamingOptions, aZ as SetNotePitchBySemitoneOptions, aY as SetNotePitchOptions, b4 as SetStavesOptions, a_ as ShiftNotePitchOptions, ce as StopOctaveShiftOptions, c4 as UpdateChordSymbolOptions, c1 as UpdateHarmonyOptions, bZ as UpdateLyricOptions, cH as ValidationError, cJ as ValidationErrorCode, cD as ValidationException, cK as ValidationLevel, cI as ValidationLocation, K as addArticulation, T as addBeam, aH as addBowing, aO as addBreathMark, aQ as addCaesura, b as addChord, j as addChordNote, p as addChordNoteChecked, aC as addChordSymbol, ao as addCoda, ap as addDaCapo, aq as addDalSegno, M as addDynamics, aj as addEnding, a6 as addFermata, ar as addFine, aF as addFingering, at as addGraceNote, az as addHarmony, aw as addLyric, g as addNote, n as addNoteChecked, aL as addOctaveShift, a8 as addOrnament, x as addPart, aa as addPedal, ae as addRehearsalMark, ah as addRepeat, af as addRepeatBarline, an as addSegno, I as addSlur, aJ as addStringNumber, a1 as addTempo, ad as addText, ac as addTextDirection, G as addTie, as as addToCoda, w as addVoice, a4 as addWedge, cG as assertMeasureValid, co as assertValid, W as autoBeam, al as changeBarline, Q as changeClef, C as changeKey, e as changeNoteDuration, D as changeTime, av as convertToGrace, Y as copyNotes, $ as copyNotesMultiMeasure, R as createTuplet, _ as cutNotes, F as deleteMeasure, h as deleteNote, o as deleteNoteChecked, z as duplicatePart, cC as formatLocation, cF as getMeasureContext, P as insertClefChange, E as insertMeasure, i as insertNote, cn as isValid, l as lowerAccidental, O as modifyDynamics, k as modifyNoteDuration, u as modifyNoteDurationChecked, m as modifyNotePitch, q as modifyNotePitchChecked, a3 as modifyTempo, B as moveNoteToStaff, Z as pasteNotes, a0 as pasteNotesMultiMeasure, f as raiseAccidental, L as removeArticulation, U as removeBeam, aI as removeBowing, aP as removeBreathMark, aR as removeCaesura, aD as removeChordSymbol, N as removeDynamics, ak as removeEnding, a7 as removeFermata, aG as removeFingering, au as removeGraceNote, aA as removeHarmony, ax as removeLyric, r as removeNote, aN as removeOctaveShift, a9 as removeOrnament, y as removePart, ab as removePedal, ai as removeRepeat, ag as removeRepeatBarline, J as removeSlur, aK as removeStringNumber, a2 as removeTempo, H as removeTie, S as removeTuplet, a5 as removeWedge, am as setBarline, X as setBeaming, s as setNotePitch, c as setNotePitchBySemitone, A as setStaves, d as shiftNotePitch, aM as stopOctaveShift, t as transpose, v as transposeChecked, aE as updateChordSymbol, aB as updateHarmony, ay as updateLyric, cm as validate, cr as validateBackupForward, ct as validateBeams, cp as validateDivisions, cq as validateMeasureDuration, cE as validateMeasureLocal, cw as validatePartReferences, cx as validatePartStructure, cu as validateSlurs, cB as validateSlursAcrossMeasures, cy as validateStaffStructure, cs as validateTies, cA as validateTiesAcrossMeasures, cv as validateTuplets, cz as validateVoiceStaff } from './index-DxLMCMTr.js';
|
|
5
|
-
import { TimingSidecar } from './query/index.js';
|
|
6
|
-
export { FindNotesFilter, NormalizedPositionOptions, PitchRange, PlaybackControls, PlaybackMeasure, RoundtripMetrics, TimingBreakpoint, TimingMapOptions, VoiceFilter, buildVoiceToStaffMap, buildVoiceToStaffMapForPart, countNotes, extractPlaybackControls, findBarlines, findDirectionsByType, findNotes, findNotesWithNotation, generatePlaybackSequence, generatePlaybackTimeline, getAbsolutePosition, getAdjacentNotes, getAllNotes, getAttributesAtMeasure, getBeamGroups, getChordProgression, getChords, getClefChanges, getClefForStaff, getDirections, getDirectionsAtPosition, getDivisions, getDuration, getDynamics, getEffectiveStaff, getEndings, getEntriesAtPosition, getEntriesForStaff, getEntriesInRange, getHarmonies, getHarmonyAtPosition, getKeyChanges, getLyricText, getLyrics, getMeasure, getMeasureByIndex, getMeasureCount, getNextNote, getNormalizedDuration, getNormalizedPosition, getNotesAtPosition, getNotesForStaff, getNotesForVoice, getNotesInRange, getOctaveShifts, getPartById, getPartByIndex, getPartCount, getPartIds, getPartIndex, getPedalMarkings, getPrevNote, getRepeatStructure, getSlurSpans, getStaffRange, getStaveCount, getStaves, getStructuralChanges, getTempoMarkings, getTiedNoteGroups, getTimeChanges, getTupletGroups, getVerseCount, getVerticalSlice, getVoiceLine, getVoiceLineInRange, getVoices, getVoicesForStaff, getWedges, groupByStaff, groupByVoice, hasMultipleStaves, hasNotes, hasPlaybackControls, inferStaff, isRestMeasure, iterateEntries, iterateNotes, measureRoundtrip, scoresEqual, withAbsolutePositions } from './query/index.js';
|
|
5
|
+
import { ExpressionOptions, TimingSidecar } from './query/index.js';
|
|
6
|
+
export { ExpressionHint, ExpressionKind, FindNotesFilter, NormalizedPositionOptions, PitchRange, PlaybackControls, PlaybackMeasure, RoundtripMetrics, TimingBreakpoint, TimingMapOptions, VoiceFilter, buildVoiceToStaffMap, buildVoiceToStaffMapForPart, countNotes, extractPlaybackControls, findBarlines, findDirectionsByType, findNotes, findNotesWithNotation, generatePlaybackSequence, generatePlaybackTimeline, getAbsolutePosition, getAdjacentNotes, getAllNotes, getAttributesAtMeasure, getBeamGroups, getChordProgression, getChords, getClefChanges, getClefForStaff, getDirections, getDirectionsAtPosition, getDivisions, getDuration, getDynamics, getEffectiveStaff, getEndings, getEntriesAtPosition, getEntriesForStaff, getEntriesInRange, getHarmonies, getHarmonyAtPosition, getKeyChanges, getLyricText, getLyrics, getMeasure, getMeasureByIndex, getMeasureCount, getNextNote, getNormalizedDuration, getNormalizedPosition, getNotesAtPosition, getNotesForStaff, getNotesForVoice, getNotesInRange, getOctaveShifts, getPartById, getPartByIndex, getPartCount, getPartIds, getPartIndex, getPedalMarkings, getPrevNote, getRepeatStructure, getSlurSpans, getStaffRange, getStaveCount, getStaves, getStructuralChanges, getTempoMarkings, getTiedNoteGroups, getTimeChanges, getTupletGroups, getVerseCount, getVerticalSlice, getVoiceLine, getVoiceLineInRange, getVoices, getVoicesForStaff, getWedges, groupByStaff, groupByVoice, hasMultipleStaves, hasNotes, hasPlaybackControls, inferStaff, isRestMeasure, iterateEntries, iterateNotes, measureRoundtrip, scoresEqual, withAbsolutePositions } from './query/index.js';
|
|
7
7
|
|
|
8
8
|
declare function parse(input: string | Uint8Array): Score;
|
|
9
9
|
|
|
@@ -76,8 +76,11 @@ declare function serializeCompressed(score: Score, options?: SerializeOptions):
|
|
|
76
76
|
|
|
77
77
|
/**
|
|
78
78
|
* MIDI export options
|
|
79
|
+
*
|
|
80
|
+
* Extends {@link ExpressionOptions} so fermata holds and rit./accel. ramps land
|
|
81
|
+
* in the exported tempo map (and the timing sidecar) identically.
|
|
79
82
|
*/
|
|
80
|
-
interface MidiExportOptions {
|
|
83
|
+
interface MidiExportOptions extends ExpressionOptions {
|
|
81
84
|
/** Ticks per quarter note (default: 480) */
|
|
82
85
|
ticksPerQuarterNote?: number;
|
|
83
86
|
/** Default tempo in BPM (default: 120) */
|
|
@@ -375,4 +378,4 @@ declare function getPartNameMap(score: Score): Record<string, string | undefined
|
|
|
375
378
|
*/
|
|
376
379
|
declare function generateId(): string;
|
|
377
380
|
|
|
378
|
-
export { type AbcSerializeOptions, DirectionEntry, DirectionType, type DirectionTypeOfKind, Measure, type MidiExportOptions, type MidiWithTimingMap, NoteEntry, PartInfo, PartListEntry, Pitch, STEPS, STEP_SEMITONES, Score, type SerializeOptions, TimingSidecar, ValidateOptions, ValidationResult, decodeBuffer, exportMidi, exportMidiWithTimingMap, generateId, getAllPartInfos, getDirectionOfKind, getDirectionsOfKind, getMeasureEndPosition, getPartAbbreviation, getPartInfo, getPartName, getPartNameMap, getSoundDamperPedal, getSoundDynamics, getSoundSoftPedal, getSoundSostenutoPedal, getSoundTempo, hasBeam, hasDirectionOfKind, hasLyrics, hasNotations, hasTie, hasTieStart, hasTieStop, hasTuplet, isChordNote, isCompressed, isCueNote, isGraceNote, isPartInfo, isPitchedNote, isRest, isUnpitchedNote, parse, parseAbc, parseAuto, parseCompressed, parseFile, pitchToSemitone, serialize, serializeAbc, serializeCompressed, serializeToFile };
|
|
381
|
+
export { type AbcSerializeOptions, DirectionEntry, DirectionType, type DirectionTypeOfKind, ExpressionOptions, Measure, type MidiExportOptions, type MidiWithTimingMap, NoteEntry, PartInfo, PartListEntry, Pitch, STEPS, STEP_SEMITONES, Score, type SerializeOptions, TimingSidecar, ValidateOptions, ValidationResult, decodeBuffer, exportMidi, exportMidiWithTimingMap, generateId, getAllPartInfos, getDirectionOfKind, getDirectionsOfKind, getMeasureEndPosition, getPartAbbreviation, getPartInfo, getPartName, getPartNameMap, getSoundDamperPedal, getSoundDynamics, getSoundSoftPedal, getSoundSostenutoPedal, getSoundTempo, hasBeam, hasDirectionOfKind, hasLyrics, hasNotations, hasTie, hasTieStart, hasTieStop, hasTuplet, isChordNote, isCompressed, isCueNote, isGraceNote, isPartInfo, isPitchedNote, isRest, isUnpitchedNote, parse, parseAbc, parseAuto, parseCompressed, parseFile, pitchToSemitone, serialize, serializeAbc, serializeCompressed, serializeToFile };
|