@scorelabs/core 1.0.10 → 1.0.13
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/constants.d.ts +4 -0
- package/dist/constants.js +10 -0
- package/dist/importers/MusicXMLParser.d.ts +4 -1
- package/dist/importers/MusicXMLParser.js +564 -75
- package/dist/importers/index.d.ts +1 -1
- package/dist/importers/index.js +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/models/Measure.d.ts +25 -5
- package/dist/models/Measure.js +173 -35
- package/dist/models/Note.d.ts +38 -9
- package/dist/models/Note.js +104 -47
- package/dist/models/NoteSet.d.ts +14 -4
- package/dist/models/NoteSet.js +38 -4
- package/dist/models/Part.d.ts +6 -6
- package/dist/models/Part.js +4 -4
- package/dist/models/Pitch.d.ts +1 -1
- package/dist/models/Pitch.js +1 -1
- package/dist/models/PreMeasure.d.ts +1 -1
- package/dist/models/Score.d.ts +13 -9
- package/dist/models/Score.js +164 -126
- package/dist/models/Staff.d.ts +5 -5
- package/dist/models/Staff.js +4 -4
- package/dist/models/index.d.ts +10 -10
- package/dist/models/index.js +10 -10
- package/dist/types/AccidentalDisplay.d.ts +6 -0
- package/dist/types/AccidentalDisplay.js +1 -0
- package/dist/types/Arpeggio.d.ts +2 -1
- package/dist/types/Arpeggio.js +1 -0
- package/dist/types/Articulation.d.ts +3 -1
- package/dist/types/Articulation.js +2 -0
- package/dist/types/Beam.d.ts +4 -0
- package/dist/types/Beam.js +1 -0
- package/dist/types/Duration.d.ts +5 -1
- package/dist/types/Duration.js +27 -14
- package/dist/types/Grace.d.ts +7 -0
- package/dist/types/Grace.js +1 -0
- package/dist/types/Hairpin.d.ts +2 -1
- package/dist/types/Language.d.ts +6 -0
- package/dist/types/Language.js +7 -0
- package/dist/types/Lyric.d.ts +2 -0
- package/dist/types/Ornament.d.ts +23 -1
- package/dist/types/Ornament.js +9 -0
- package/dist/types/Pedal.d.ts +3 -2
- package/dist/types/Placement.d.ts +7 -0
- package/dist/types/Placement.js +1 -0
- package/dist/types/Repeat.d.ts +1 -0
- package/dist/types/RestDisplay.d.ts +6 -0
- package/dist/types/RestDisplay.js +1 -0
- package/dist/types/Slur.d.ts +1 -0
- package/dist/types/Technical.d.ts +20 -0
- package/dist/types/Technical.js +5 -0
- package/dist/types/Tempo.d.ts +1 -1
- package/dist/types/Tie.d.ts +4 -0
- package/dist/types/Tie.js +1 -0
- package/dist/types/Tuplet.d.ts +6 -0
- package/dist/types/User.d.ts +13 -7
- package/dist/types/User.js +9 -7
- package/dist/types/index.d.ts +8 -0
- package/dist/types/index.js +8 -0
- package/package.json +2 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
export * from './MusicXMLParser';
|
|
1
|
+
export * from './MusicXMLParser.js';
|
package/dist/importers/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export * from './MusicXMLParser';
|
|
1
|
+
export * from './MusicXMLParser.js';
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
package/dist/models/Measure.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { Note, NoteJSON } from './Note';
|
|
2
|
-
import { NoteSet, NoteSetJSON } from './NoteSet';
|
|
3
|
-
import { BarlineStyle, Clef, Duration, KeySignature, Repeat, Tempo, TimeSignature, Volta } from './types';
|
|
1
|
+
import { Note, NoteJSON } from './Note.js';
|
|
2
|
+
import { NoteSet, NoteSetJSON } from './NoteSet.js';
|
|
3
|
+
import { BarlineStyle, Clef, Duration, KeySignature, Repeat, Tempo, TimeSignature, Volta } from './types.js';
|
|
4
4
|
/**
|
|
5
5
|
* Represents a single measure containing note sets, potentially in multiple voices.
|
|
6
6
|
*/
|
|
@@ -17,12 +17,22 @@ export declare class Measure {
|
|
|
17
17
|
readonly tempo?: Tempo | undefined;
|
|
18
18
|
readonly rehearsalMark?: string | undefined;
|
|
19
19
|
readonly systemText?: string | undefined;
|
|
20
|
+
readonly multiMeasureRestCount?: number | undefined;
|
|
20
21
|
readonly barlineStyle: BarlineStyle;
|
|
21
|
-
|
|
22
|
+
readonly roadmapDirections?: string[] | undefined;
|
|
23
|
+
readonly systemDistance?: number | undefined;
|
|
24
|
+
readonly staffDistance?: number | undefined;
|
|
25
|
+
readonly topSystemDistance?: number | undefined;
|
|
26
|
+
/** Stable identifier for this measure. Preserved across all immutable updates. */
|
|
27
|
+
readonly uuid: string;
|
|
28
|
+
constructor(voices: NoteSet[][], timeSignature?: TimeSignature | undefined, keySignature?: KeySignature | undefined, systemBreak?: boolean, pageBreak?: boolean, repeats?: Repeat[], volta?: Volta | undefined, isPickup?: boolean, clef?: Clef | undefined, tempo?: Tempo | undefined, rehearsalMark?: string | undefined, systemText?: string | undefined, multiMeasureRestCount?: number | undefined, barlineStyle?: BarlineStyle, uuid?: string, roadmapDirections?: string[] | undefined, systemDistance?: number | undefined, staffDistance?: number | undefined, topSystemDistance?: number | undefined);
|
|
22
29
|
get notes(): NoteSet[];
|
|
30
|
+
getNoteOffset(voiceIndex: number, noteIndex: number): number;
|
|
31
|
+
moveNoteToVoice(fromVoiceIndex: number, noteIndex: number, toVoiceIndex: number): Measure;
|
|
32
|
+
splitNote(voiceIndex: number, noteIndex: number, splitOffset: number): Measure;
|
|
23
33
|
get hasStartRepeat(): boolean;
|
|
24
34
|
get hasEndRepeat(): boolean;
|
|
25
|
-
changeNoteDuration(noteIndex: number, newDuration: Duration,
|
|
35
|
+
changeNoteDuration(noteIndex: number, newDuration: Duration, dotCount?: number, voiceIndex?: number): Measure;
|
|
26
36
|
getTotalDuration(voiceIndex?: number): number;
|
|
27
37
|
static fromJSON(data: MeasureJSON): Measure;
|
|
28
38
|
transpose(semitones: number): Measure;
|
|
@@ -45,12 +55,17 @@ export declare class Measure {
|
|
|
45
55
|
withRehearsalMark(mark?: string): Measure;
|
|
46
56
|
withSystemText(text?: string): Measure;
|
|
47
57
|
withBarlineStyle(style: BarlineStyle): Measure;
|
|
58
|
+
withRoadmapDirections(roadmapDirections?: string[]): Measure;
|
|
59
|
+
withSystemDistance(systemDistance?: number): Measure;
|
|
60
|
+
withStaffDistance(staffDistance?: number): Measure;
|
|
61
|
+
withMultiMeasureRestCount(multiMeasureRestCount?: number): Measure;
|
|
48
62
|
fillVoiceWithRests(voiceIndex: number, targetDuration: number): Measure;
|
|
49
63
|
simplifyRests(voiceIndex?: number): Measure;
|
|
50
64
|
private decomposeToRests;
|
|
51
65
|
toJSON(): MeasureJSON;
|
|
52
66
|
}
|
|
53
67
|
export interface MeasureJSON {
|
|
68
|
+
uuid?: string;
|
|
54
69
|
notes?: NoteJSON[];
|
|
55
70
|
voices?: NoteSetJSON[][];
|
|
56
71
|
timeSignature?: TimeSignature;
|
|
@@ -65,5 +80,10 @@ export interface MeasureJSON {
|
|
|
65
80
|
tempo?: Tempo;
|
|
66
81
|
rehearsalMark?: string;
|
|
67
82
|
systemText?: string;
|
|
83
|
+
multiMeasureRestCount?: number;
|
|
84
|
+
roadmapDirections?: string[];
|
|
68
85
|
barlineStyle?: BarlineStyle;
|
|
86
|
+
systemDistance?: number;
|
|
87
|
+
staffDistance?: number;
|
|
88
|
+
topSystemDistance?: number;
|
|
69
89
|
}
|
package/dist/models/Measure.js
CHANGED
|
@@ -1,6 +1,17 @@
|
|
|
1
|
-
import { Note } from './Note';
|
|
2
|
-
import { NoteSet } from './NoteSet';
|
|
3
|
-
import { BarlineStyle,
|
|
1
|
+
import { Note } from './Note.js';
|
|
2
|
+
import { NoteSet } from './NoteSet.js';
|
|
3
|
+
import { BarlineStyle, Duration, calculateDurationValue, decomposeDuration, } from './types.js';
|
|
4
|
+
/** Generate a v4-like UUID that works in both browser and Node environments. */
|
|
5
|
+
function generateUuid() {
|
|
6
|
+
if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {
|
|
7
|
+
return crypto.randomUUID();
|
|
8
|
+
}
|
|
9
|
+
// Fallback for older environments
|
|
10
|
+
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
|
|
11
|
+
const r = (Math.random() * 16) | 0;
|
|
12
|
+
return (c === 'x' ? r : (r & 0x3) | 0x8).toString(16);
|
|
13
|
+
});
|
|
14
|
+
}
|
|
4
15
|
/**
|
|
5
16
|
* Represents a single measure containing note sets, potentially in multiple voices.
|
|
6
17
|
*/
|
|
@@ -17,8 +28,15 @@ export class Measure {
|
|
|
17
28
|
tempo;
|
|
18
29
|
rehearsalMark;
|
|
19
30
|
systemText;
|
|
31
|
+
multiMeasureRestCount;
|
|
20
32
|
barlineStyle;
|
|
21
|
-
|
|
33
|
+
roadmapDirections;
|
|
34
|
+
systemDistance;
|
|
35
|
+
staffDistance;
|
|
36
|
+
topSystemDistance;
|
|
37
|
+
/** Stable identifier for this measure. Preserved across all immutable updates. */
|
|
38
|
+
uuid;
|
|
39
|
+
constructor(voices, timeSignature, keySignature, systemBreak = false, pageBreak = false, repeats = [], volta, isPickup = false, clef, tempo, rehearsalMark, systemText, multiMeasureRestCount, barlineStyle = BarlineStyle.Regular, uuid, roadmapDirections, systemDistance, staffDistance, topSystemDistance) {
|
|
22
40
|
this.voices = voices;
|
|
23
41
|
this.timeSignature = timeSignature;
|
|
24
42
|
this.keySignature = keySignature;
|
|
@@ -31,7 +49,13 @@ export class Measure {
|
|
|
31
49
|
this.tempo = tempo;
|
|
32
50
|
this.rehearsalMark = rehearsalMark;
|
|
33
51
|
this.systemText = systemText;
|
|
52
|
+
this.multiMeasureRestCount = multiMeasureRestCount;
|
|
34
53
|
this.barlineStyle = barlineStyle;
|
|
54
|
+
this.roadmapDirections = roadmapDirections;
|
|
55
|
+
this.systemDistance = systemDistance;
|
|
56
|
+
this.staffDistance = staffDistance;
|
|
57
|
+
this.topSystemDistance = topSystemDistance;
|
|
58
|
+
this.uuid = uuid ?? generateUuid();
|
|
35
59
|
if (this.voices.length === 0) {
|
|
36
60
|
this.voices = [[]];
|
|
37
61
|
}
|
|
@@ -39,27 +63,110 @@ export class Measure {
|
|
|
39
63
|
get notes() {
|
|
40
64
|
return this.voices[0] || [];
|
|
41
65
|
}
|
|
66
|
+
getNoteOffset(voiceIndex, noteIndex) {
|
|
67
|
+
const voice = this.voices[voiceIndex];
|
|
68
|
+
if (!voice)
|
|
69
|
+
return 0;
|
|
70
|
+
let offset = 0;
|
|
71
|
+
for (let i = 0; i < noteIndex && i < voice.length; i++) {
|
|
72
|
+
offset += voice[i].getDurationValue();
|
|
73
|
+
}
|
|
74
|
+
return offset;
|
|
75
|
+
}
|
|
76
|
+
moveNoteToVoice(fromVoiceIndex, noteIndex, toVoiceIndex) {
|
|
77
|
+
if (fromVoiceIndex === toVoiceIndex)
|
|
78
|
+
return this;
|
|
79
|
+
const fromVoice = this.voices[fromVoiceIndex];
|
|
80
|
+
if (!fromVoice || noteIndex < 0 || noteIndex >= fromVoice.length)
|
|
81
|
+
return this;
|
|
82
|
+
const noteSetToMove = fromVoice[noteIndex];
|
|
83
|
+
if (noteSetToMove.isRest)
|
|
84
|
+
return this;
|
|
85
|
+
const onset = this.getNoteOffset(fromVoiceIndex, noteIndex);
|
|
86
|
+
// 1. Replace with rest in fromVoice first to get the source updated
|
|
87
|
+
let updatedMeasure = this.deleteNote(noteIndex, fromVoiceIndex);
|
|
88
|
+
// 2. Ensure toVoice exists and has rests up to total duration
|
|
89
|
+
const targetDur = this.timeSignature
|
|
90
|
+
? (this.timeSignature.beats * 4) / this.timeSignature.beatType
|
|
91
|
+
: this.getTotalDuration(fromVoiceIndex);
|
|
92
|
+
updatedMeasure = updatedMeasure.fillVoiceWithRests(toVoiceIndex, targetDur);
|
|
93
|
+
// 3. Find the note/rest at 'onset' in toVoice and split if necessary
|
|
94
|
+
let toVoice = updatedMeasure.voices[toVoiceIndex];
|
|
95
|
+
let currentOffset = 0;
|
|
96
|
+
let targetNoteIndex = -1;
|
|
97
|
+
for (let i = 0; i < toVoice.length; i++) {
|
|
98
|
+
const dur = toVoice[i].getDurationValue();
|
|
99
|
+
if (Math.abs(currentOffset - onset) < 0.001) {
|
|
100
|
+
targetNoteIndex = i;
|
|
101
|
+
break;
|
|
102
|
+
}
|
|
103
|
+
if (onset > currentOffset + 0.001 && onset < currentOffset + dur - 0.001) {
|
|
104
|
+
// Need to split
|
|
105
|
+
updatedMeasure = updatedMeasure.splitNote(toVoiceIndex, i, onset - currentOffset);
|
|
106
|
+
toVoice = updatedMeasure.voices[toVoiceIndex]; // Update reference
|
|
107
|
+
// After split, the target should be at i + (number of segments added - 1)
|
|
108
|
+
// Let's just re-scan to be safe
|
|
109
|
+
currentOffset = 0;
|
|
110
|
+
for (let j = 0; j < toVoice.length; j++) {
|
|
111
|
+
if (Math.abs(currentOffset - onset) < 0.001) {
|
|
112
|
+
targetNoteIndex = j;
|
|
113
|
+
break;
|
|
114
|
+
}
|
|
115
|
+
currentOffset += toVoice[j].getDurationValue();
|
|
116
|
+
}
|
|
117
|
+
break;
|
|
118
|
+
}
|
|
119
|
+
currentOffset += dur;
|
|
120
|
+
}
|
|
121
|
+
if (targetNoteIndex !== -1) {
|
|
122
|
+
// We found the correct position in the prepared target voice
|
|
123
|
+
updatedMeasure = updatedMeasure.replaceNoteSet(targetNoteIndex, noteSetToMove, toVoiceIndex);
|
|
124
|
+
}
|
|
125
|
+
return updatedMeasure;
|
|
126
|
+
}
|
|
127
|
+
splitNote(voiceIndex, noteIndex, splitOffset) {
|
|
128
|
+
const voice = this.voices[voiceIndex];
|
|
129
|
+
if (!voice || noteIndex < 0 || noteIndex >= voice.length)
|
|
130
|
+
return this;
|
|
131
|
+
const target = voice[noteIndex];
|
|
132
|
+
const duration = target.getDurationValue();
|
|
133
|
+
if (splitOffset <= 0 || splitOffset >= duration - 0.001)
|
|
134
|
+
return this;
|
|
135
|
+
const leftParts = decomposeDuration(splitOffset);
|
|
136
|
+
const rightParts = decomposeDuration(duration - splitOffset);
|
|
137
|
+
const leftNotes = leftParts.map((p) => target.withDuration(p.duration, p.dotCount).withTie(target.isRest ? false : true));
|
|
138
|
+
const rightNotes = rightParts.map((p, idx) => {
|
|
139
|
+
const isLast = idx === rightParts.length - 1;
|
|
140
|
+
return target
|
|
141
|
+
.withDuration(p.duration, p.dotCount)
|
|
142
|
+
.withTie(isLast ? !!target.notes[0].tie : !target.isRest);
|
|
143
|
+
});
|
|
144
|
+
const newVoice = [...voice];
|
|
145
|
+
newVoice.splice(noteIndex, 1, ...leftNotes, ...rightNotes);
|
|
146
|
+
const newVoices = [...this.voices];
|
|
147
|
+
newVoices[voiceIndex] = newVoice;
|
|
148
|
+
return this.withVoices(newVoices);
|
|
149
|
+
}
|
|
42
150
|
get hasStartRepeat() {
|
|
43
|
-
return this.repeats.some((r) => r.type ===
|
|
151
|
+
return this.repeats.some((r) => r.type === 'start');
|
|
44
152
|
}
|
|
45
153
|
get hasEndRepeat() {
|
|
46
|
-
return this.repeats.some((r) => r.type ===
|
|
154
|
+
return this.repeats.some((r) => r.type === 'end');
|
|
47
155
|
}
|
|
48
|
-
changeNoteDuration(noteIndex, newDuration,
|
|
156
|
+
changeNoteDuration(noteIndex, newDuration, dotCount = 0, voiceIndex = 0) {
|
|
49
157
|
const voice = this.voices[voiceIndex];
|
|
50
158
|
if (!voice || noteIndex < 0 || noteIndex >= voice.length)
|
|
51
159
|
return this;
|
|
52
160
|
const targetNoteSet = voice[noteIndex];
|
|
53
161
|
const oldVal = targetNoteSet.getDurationValue();
|
|
54
|
-
const
|
|
55
|
-
const newVal = isDotted ? base * 1.5 : base;
|
|
162
|
+
const newVal = calculateDurationValue(newDuration, dotCount);
|
|
56
163
|
if (Math.abs(newVal - oldVal) < 0.001)
|
|
57
164
|
return this;
|
|
58
165
|
const updatedVoice = [...voice];
|
|
59
166
|
if (newVal < oldVal) {
|
|
60
167
|
const gap = oldVal - newVal;
|
|
61
|
-
updatedVoice[noteIndex] = targetNoteSet.withDuration(newDuration,
|
|
62
|
-
const rests = decomposeDuration(gap).map((d) => new NoteSet([new Note(d.duration, undefined, true, d.
|
|
168
|
+
updatedVoice[noteIndex] = targetNoteSet.withDuration(newDuration, dotCount);
|
|
169
|
+
const rests = decomposeDuration(gap).map((d) => new NoteSet([new Note(d.duration, undefined, true, d.dotCount)]));
|
|
63
170
|
updatedVoice.splice(noteIndex + 1, 0, ...rests);
|
|
64
171
|
}
|
|
65
172
|
else {
|
|
@@ -70,7 +177,7 @@ export class Measure {
|
|
|
70
177
|
}
|
|
71
178
|
if (available < delta - 0.001)
|
|
72
179
|
return this;
|
|
73
|
-
updatedVoice[noteIndex] = targetNoteSet.withDuration(newDuration,
|
|
180
|
+
updatedVoice[noteIndex] = targetNoteSet.withDuration(newDuration, dotCount);
|
|
74
181
|
let consumed = 0;
|
|
75
182
|
let removeCount = 0;
|
|
76
183
|
const replacements = [];
|
|
@@ -85,7 +192,7 @@ export class Measure {
|
|
|
85
192
|
}
|
|
86
193
|
else {
|
|
87
194
|
const remaining = consumed + val - delta;
|
|
88
|
-
replacements.push(...decomposeDuration(remaining).map((d) => new NoteSet([new Note(d.duration, undefined, true, d.
|
|
195
|
+
replacements.push(...decomposeDuration(remaining).map((d) => new NoteSet([new Note(d.duration, undefined, true, d.dotCount)])));
|
|
89
196
|
removeCount++;
|
|
90
197
|
break;
|
|
91
198
|
}
|
|
@@ -94,7 +201,12 @@ export class Measure {
|
|
|
94
201
|
}
|
|
95
202
|
const newVoices = [...this.voices];
|
|
96
203
|
newVoices[voiceIndex] = updatedVoice;
|
|
97
|
-
let result = this.withVoices(newVoices)
|
|
204
|
+
let result = this.withVoices(newVoices);
|
|
205
|
+
// Skip simplification if we are explicitly changing a rest's duration,
|
|
206
|
+
// to allow the user to manually control rest fragmentation (e.g. splitting a whole rest into halves).
|
|
207
|
+
if (!targetNoteSet.isRest) {
|
|
208
|
+
result = result.simplifyRests(voiceIndex);
|
|
209
|
+
}
|
|
98
210
|
if (this.timeSignature) {
|
|
99
211
|
result = result.autoBeam(this.timeSignature);
|
|
100
212
|
}
|
|
@@ -123,7 +235,8 @@ export class Measure {
|
|
|
123
235
|
else {
|
|
124
236
|
voices = [[]];
|
|
125
237
|
}
|
|
126
|
-
return new Measure(voices, data.timeSignature, data.keySignature, data.systemBreak ?? false, data.pageBreak ?? false, data.repeats || (data.repeat ? [data.repeat] : []), data.volta, data.isPickup ?? false, data.clef, data.tempo, data.rehearsalMark, data.systemText, data.barlineStyle ?? BarlineStyle.Regular
|
|
238
|
+
return new Measure(voices, data.timeSignature, data.keySignature, data.systemBreak ?? false, data.pageBreak ?? false, data.repeats || (data.repeat ? [data.repeat] : []), data.volta, data.isPickup ?? false, data.clef, data.tempo, data.rehearsalMark, data.systemText, data.multiMeasureRestCount, data.barlineStyle ?? BarlineStyle.Regular, data.uuid, // preserve existing uuid — undefined for old scores → generates new one
|
|
239
|
+
data.roadmapDirections, data.systemDistance, data.staffDistance, data.topSystemDistance);
|
|
127
240
|
}
|
|
128
241
|
transpose(semitones) {
|
|
129
242
|
let newKeySignature;
|
|
@@ -164,7 +277,7 @@ export class Measure {
|
|
|
164
277
|
for (let i = index + 1; i < updatedVoice.length; i++) {
|
|
165
278
|
available += updatedVoice[i].getDurationValue();
|
|
166
279
|
}
|
|
167
|
-
// If there's enough space to consume, do it.
|
|
280
|
+
// If there's enough space to consume, do it.
|
|
168
281
|
// If not, we still replace it but it will overflow (which simplifyRests might fix or layout will handle)
|
|
169
282
|
updatedVoice[index] = newNoteSet;
|
|
170
283
|
let consumed = 0;
|
|
@@ -190,7 +303,12 @@ export class Measure {
|
|
|
190
303
|
}
|
|
191
304
|
const newVoices = [...this.voices];
|
|
192
305
|
newVoices[voiceIndex] = updatedVoice;
|
|
193
|
-
let result = this.withVoices(newVoices)
|
|
306
|
+
let result = this.withVoices(newVoices);
|
|
307
|
+
// Only simplify rests if the duration was actually changed,
|
|
308
|
+
// otherwise preserve the user's current rhythm organization.
|
|
309
|
+
if (Math.abs(oldVal - newVal) >= 0.001) {
|
|
310
|
+
result = result.simplifyRests(voiceIndex);
|
|
311
|
+
}
|
|
194
312
|
if (this.timeSignature) {
|
|
195
313
|
result = result.autoBeam(this.timeSignature);
|
|
196
314
|
}
|
|
@@ -235,7 +353,7 @@ export class Measure {
|
|
|
235
353
|
if (ts.beats === 4 || ts.beats === 2) {
|
|
236
354
|
// In 4/4 or 2/4, eighth notes are often beamed in groups of 2 beats (length 2.0)
|
|
237
355
|
// unless there are sixteenth notes which force 1-beat groupings.
|
|
238
|
-
beamBeatLength =
|
|
356
|
+
beamBeatLength = lastGroupHasSixteenths || isSixteenth ? 1.0 : 2.0;
|
|
239
357
|
}
|
|
240
358
|
}
|
|
241
359
|
else if (ts.beatType === 8) {
|
|
@@ -291,25 +409,25 @@ export class Measure {
|
|
|
291
409
|
return this.withVoices(newVoices);
|
|
292
410
|
}
|
|
293
411
|
withTimeSignature(timeSignature) {
|
|
294
|
-
return new Measure(this.voices, timeSignature, this.keySignature, this.systemBreak, this.pageBreak, this.repeats, this.volta, this.isPickup, this.clef, this.tempo, this.rehearsalMark, this.systemText, this.barlineStyle);
|
|
412
|
+
return new Measure(this.voices, timeSignature, this.keySignature, this.systemBreak, this.pageBreak, this.repeats, this.volta, this.isPickup, this.clef, this.tempo, this.rehearsalMark, this.systemText, this.multiMeasureRestCount, this.barlineStyle, this.uuid, this.roadmapDirections, this.systemDistance, this.staffDistance);
|
|
295
413
|
}
|
|
296
414
|
withKeySignature(keySignature) {
|
|
297
|
-
return new Measure(this.voices, this.timeSignature, keySignature, this.systemBreak, this.pageBreak, this.repeats, this.volta, this.isPickup, this.clef, this.tempo, this.rehearsalMark, this.systemText, this.barlineStyle);
|
|
415
|
+
return new Measure(this.voices, this.timeSignature, keySignature, this.systemBreak, this.pageBreak, this.repeats, this.volta, this.isPickup, this.clef, this.tempo, this.rehearsalMark, this.systemText, this.multiMeasureRestCount, this.barlineStyle, this.uuid, this.roadmapDirections, this.systemDistance, this.staffDistance);
|
|
298
416
|
}
|
|
299
417
|
withClef(clef) {
|
|
300
|
-
return new Measure(this.voices, this.timeSignature, this.keySignature, this.systemBreak, this.pageBreak, this.repeats, this.volta, this.isPickup, clef, this.tempo, this.rehearsalMark, this.systemText, this.barlineStyle);
|
|
418
|
+
return new Measure(this.voices, this.timeSignature, this.keySignature, this.systemBreak, this.pageBreak, this.repeats, this.volta, this.isPickup, clef, this.tempo, this.rehearsalMark, this.systemText, this.multiMeasureRestCount, this.barlineStyle, this.uuid, this.roadmapDirections, this.systemDistance, this.staffDistance);
|
|
301
419
|
}
|
|
302
420
|
withTempo(tempo) {
|
|
303
|
-
return new Measure(this.voices, this.timeSignature, this.keySignature, this.systemBreak, this.pageBreak, this.repeats, this.volta, this.isPickup, this.clef, tempo, this.rehearsalMark, this.systemText, this.barlineStyle);
|
|
421
|
+
return new Measure(this.voices, this.timeSignature, this.keySignature, this.systemBreak, this.pageBreak, this.repeats, this.volta, this.isPickup, this.clef, tempo, this.rehearsalMark, this.systemText, this.multiMeasureRestCount, this.barlineStyle, this.uuid, this.roadmapDirections, this.systemDistance, this.staffDistance);
|
|
304
422
|
}
|
|
305
423
|
withSystemBreak(systemBreak) {
|
|
306
|
-
return new Measure(this.voices, this.timeSignature, this.keySignature, systemBreak, this.pageBreak, this.repeats, this.volta, this.isPickup, this.clef, this.tempo, this.rehearsalMark, this.systemText, this.barlineStyle);
|
|
424
|
+
return new Measure(this.voices, this.timeSignature, this.keySignature, systemBreak, this.pageBreak, this.repeats, this.volta, this.isPickup, this.clef, this.tempo, this.rehearsalMark, this.systemText, this.multiMeasureRestCount, this.barlineStyle, this.uuid, this.roadmapDirections, this.systemDistance, this.staffDistance);
|
|
307
425
|
}
|
|
308
426
|
withPageBreak(pageBreak) {
|
|
309
|
-
return new Measure(this.voices, this.timeSignature, this.keySignature, this.systemBreak, pageBreak, this.repeats, this.volta, this.isPickup, this.clef, this.tempo, this.rehearsalMark, this.systemText, this.barlineStyle);
|
|
427
|
+
return new Measure(this.voices, this.timeSignature, this.keySignature, this.systemBreak, pageBreak, this.repeats, this.volta, this.isPickup, this.clef, this.tempo, this.rehearsalMark, this.systemText, this.multiMeasureRestCount, this.barlineStyle, this.uuid, this.roadmapDirections, this.systemDistance, this.staffDistance);
|
|
310
428
|
}
|
|
311
429
|
withVoices(voices) {
|
|
312
|
-
return new Measure(voices, this.timeSignature, this.keySignature, this.systemBreak, this.pageBreak, this.repeats, this.volta, this.isPickup, this.clef, this.tempo, this.rehearsalMark, this.systemText, this.barlineStyle);
|
|
430
|
+
return new Measure(voices, this.timeSignature, this.keySignature, this.systemBreak, this.pageBreak, this.repeats, this.volta, this.isPickup, this.clef, this.tempo, this.rehearsalMark, this.systemText, this.multiMeasureRestCount, this.barlineStyle, this.uuid, this.roadmapDirections, this.systemDistance, this.staffDistance);
|
|
313
431
|
}
|
|
314
432
|
withVoiceNotes(notes, voiceIndex = 0) {
|
|
315
433
|
const newVoices = [...this.voices];
|
|
@@ -332,22 +450,34 @@ export class Measure {
|
|
|
332
450
|
return this.withRepeats(newRepeats);
|
|
333
451
|
}
|
|
334
452
|
withRepeats(repeats) {
|
|
335
|
-
return new Measure(this.voices, this.timeSignature, this.keySignature, this.systemBreak, this.pageBreak, repeats, this.volta, this.isPickup, this.clef, this.tempo, this.rehearsalMark, this.systemText, this.barlineStyle);
|
|
453
|
+
return new Measure(this.voices, this.timeSignature, this.keySignature, this.systemBreak, this.pageBreak, repeats, this.volta, this.isPickup, this.clef, this.tempo, this.rehearsalMark, this.systemText, this.multiMeasureRestCount, this.barlineStyle, this.uuid, this.roadmapDirections, this.systemDistance, this.staffDistance);
|
|
336
454
|
}
|
|
337
455
|
withVolta(volta) {
|
|
338
|
-
return new Measure(this.voices, this.timeSignature, this.keySignature, this.systemBreak, this.pageBreak, this.repeats, volta, this.isPickup, this.clef, this.tempo, this.rehearsalMark, this.systemText, this.barlineStyle);
|
|
456
|
+
return new Measure(this.voices, this.timeSignature, this.keySignature, this.systemBreak, this.pageBreak, this.repeats, volta, this.isPickup, this.clef, this.tempo, this.rehearsalMark, this.systemText, this.multiMeasureRestCount, this.barlineStyle, this.uuid, this.roadmapDirections, this.systemDistance, this.staffDistance);
|
|
339
457
|
}
|
|
340
458
|
withPickup(isPickup) {
|
|
341
|
-
return new Measure(this.voices, this.timeSignature, this.keySignature, this.systemBreak, this.pageBreak, this.repeats, this.volta, isPickup, this.clef, this.tempo, this.rehearsalMark, this.systemText, this.barlineStyle);
|
|
459
|
+
return new Measure(this.voices, this.timeSignature, this.keySignature, this.systemBreak, this.pageBreak, this.repeats, this.volta, isPickup, this.clef, this.tempo, this.rehearsalMark, this.systemText, this.multiMeasureRestCount, this.barlineStyle, this.uuid, this.roadmapDirections, this.systemDistance, this.staffDistance);
|
|
342
460
|
}
|
|
343
461
|
withRehearsalMark(mark) {
|
|
344
|
-
return new Measure(this.voices, this.timeSignature, this.keySignature, this.systemBreak, this.pageBreak, this.repeats, this.volta, this.isPickup, this.clef, this.tempo, mark, this.systemText, this.barlineStyle);
|
|
462
|
+
return new Measure(this.voices, this.timeSignature, this.keySignature, this.systemBreak, this.pageBreak, this.repeats, this.volta, this.isPickup, this.clef, this.tempo, mark, this.systemText, this.multiMeasureRestCount, this.barlineStyle, this.uuid, this.roadmapDirections, this.systemDistance, this.staffDistance);
|
|
345
463
|
}
|
|
346
464
|
withSystemText(text) {
|
|
347
|
-
return new Measure(this.voices, this.timeSignature, this.keySignature, this.systemBreak, this.pageBreak, this.repeats, this.volta, this.isPickup, this.clef, this.tempo, this.rehearsalMark, text, this.barlineStyle);
|
|
465
|
+
return new Measure(this.voices, this.timeSignature, this.keySignature, this.systemBreak, this.pageBreak, this.repeats, this.volta, this.isPickup, this.clef, this.tempo, this.rehearsalMark, text, this.multiMeasureRestCount, this.barlineStyle, this.uuid, this.roadmapDirections, this.systemDistance, this.staffDistance);
|
|
348
466
|
}
|
|
349
467
|
withBarlineStyle(style) {
|
|
350
|
-
return new Measure(this.voices, this.timeSignature, this.keySignature, this.systemBreak, this.pageBreak, this.repeats, this.volta, this.isPickup, this.clef, this.tempo, this.rehearsalMark, this.systemText, style);
|
|
468
|
+
return new Measure(this.voices, this.timeSignature, this.keySignature, this.systemBreak, this.pageBreak, this.repeats, this.volta, this.isPickup, this.clef, this.tempo, this.rehearsalMark, this.systemText, this.multiMeasureRestCount, style, this.uuid, this.roadmapDirections, this.systemDistance, this.staffDistance);
|
|
469
|
+
}
|
|
470
|
+
withRoadmapDirections(roadmapDirections) {
|
|
471
|
+
return new Measure(this.voices, this.timeSignature, this.keySignature, this.systemBreak, this.pageBreak, this.repeats, this.volta, this.isPickup, this.clef, this.tempo, this.rehearsalMark, this.systemText, this.multiMeasureRestCount, this.barlineStyle, this.uuid, roadmapDirections, this.systemDistance, this.staffDistance);
|
|
472
|
+
}
|
|
473
|
+
withSystemDistance(systemDistance) {
|
|
474
|
+
return new Measure(this.voices, this.timeSignature, this.keySignature, this.systemBreak, this.pageBreak, this.repeats, this.volta, this.isPickup, this.clef, this.tempo, this.rehearsalMark, this.systemText, this.multiMeasureRestCount, this.barlineStyle, this.uuid, this.roadmapDirections, systemDistance, this.staffDistance);
|
|
475
|
+
}
|
|
476
|
+
withStaffDistance(staffDistance) {
|
|
477
|
+
return new Measure(this.voices, this.timeSignature, this.keySignature, this.systemBreak, this.pageBreak, this.repeats, this.volta, this.isPickup, this.clef, this.tempo, this.rehearsalMark, this.systemText, this.multiMeasureRestCount, this.barlineStyle, this.uuid, this.roadmapDirections, this.systemDistance, staffDistance);
|
|
478
|
+
}
|
|
479
|
+
withMultiMeasureRestCount(multiMeasureRestCount) {
|
|
480
|
+
return new Measure(this.voices, this.timeSignature, this.keySignature, this.systemBreak, this.pageBreak, this.repeats, this.volta, this.isPickup, this.clef, this.tempo, this.rehearsalMark, this.systemText, multiMeasureRestCount, this.barlineStyle, this.uuid, this.roadmapDirections, this.systemDistance, this.staffDistance);
|
|
351
481
|
}
|
|
352
482
|
fillVoiceWithRests(voiceIndex, targetDuration) {
|
|
353
483
|
const newVoices = [...this.voices];
|
|
@@ -358,7 +488,7 @@ export class Measure {
|
|
|
358
488
|
const currentDuration = currentVoice.reduce((sum, ns) => sum + ns.getDurationValue(), 0);
|
|
359
489
|
if (currentDuration < targetDuration - 0.001) {
|
|
360
490
|
const gap = targetDuration - currentDuration;
|
|
361
|
-
const rests = decomposeDuration(gap).map((d) => new NoteSet([new Note(d.duration, undefined, true, d.
|
|
491
|
+
const rests = decomposeDuration(gap).map((d) => new NoteSet([new Note(d.duration, undefined, true, d.dotCount)]));
|
|
362
492
|
newVoices[voiceIndex] = [...currentVoice, ...rests];
|
|
363
493
|
}
|
|
364
494
|
return this.withVoices(newVoices);
|
|
@@ -368,9 +498,11 @@ export class Measure {
|
|
|
368
498
|
if (!voice || voice.length === 0)
|
|
369
499
|
return this;
|
|
370
500
|
const totalDur = this.getTotalDuration(voiceIndex);
|
|
371
|
-
const expectedDur = this.timeSignature
|
|
501
|
+
const expectedDur = this.timeSignature
|
|
502
|
+
? (this.timeSignature.beats * 4) / this.timeSignature.beatType
|
|
503
|
+
: 4.0;
|
|
372
504
|
// Special Case: If the whole measure is rests, just return a single whole rest (or appropriate duration)
|
|
373
|
-
const allRests = voice.every(ns => ns.isRest);
|
|
505
|
+
const allRests = voice.every((ns) => ns.isRest);
|
|
374
506
|
if (allRests && Math.abs(totalDur - expectedDur) < 0.001) {
|
|
375
507
|
const newVoice = [new NoteSet([new Note(Duration.Whole, undefined, true)])];
|
|
376
508
|
const newVoices = [...this.voices];
|
|
@@ -399,10 +531,11 @@ export class Measure {
|
|
|
399
531
|
return this.withVoices(newVoices);
|
|
400
532
|
}
|
|
401
533
|
decomposeToRests(value) {
|
|
402
|
-
return decomposeDuration(value).map((d) => new NoteSet([new Note(d.duration, undefined, true, d.
|
|
534
|
+
return decomposeDuration(value).map((d) => new NoteSet([new Note(d.duration, undefined, true, d.dotCount)]));
|
|
403
535
|
}
|
|
404
536
|
toJSON() {
|
|
405
537
|
return {
|
|
538
|
+
uuid: this.uuid,
|
|
406
539
|
voices: this.voices.map((v) => v.map((ns) => ns.toJSON())),
|
|
407
540
|
timeSignature: this.timeSignature,
|
|
408
541
|
keySignature: this.keySignature,
|
|
@@ -415,7 +548,12 @@ export class Measure {
|
|
|
415
548
|
tempo: this.tempo,
|
|
416
549
|
rehearsalMark: this.rehearsalMark,
|
|
417
550
|
systemText: this.systemText,
|
|
551
|
+
multiMeasureRestCount: this.multiMeasureRestCount,
|
|
552
|
+
roadmapDirections: this.roadmapDirections,
|
|
418
553
|
barlineStyle: this.barlineStyle,
|
|
554
|
+
systemDistance: this.systemDistance,
|
|
555
|
+
staffDistance: this.staffDistance,
|
|
556
|
+
topSystemDistance: this.topSystemDistance,
|
|
419
557
|
};
|
|
420
558
|
}
|
|
421
559
|
}
|
package/dist/models/Note.d.ts
CHANGED
|
@@ -1,13 +1,10 @@
|
|
|
1
|
-
import { Pitch } from './Pitch';
|
|
2
|
-
import { Accidental, Arpeggio, Articulation, Bowing, Duration, Dynamic, FretboardDiagram, Glissando, Hairpin, Lyric, NoteheadShape, Ornament, Ottava, Pedal, Slur, StemDirection, Tuplet } from './types';
|
|
3
|
-
/**
|
|
4
|
-
* Represents a single note or rest in a measure.
|
|
5
|
-
*/
|
|
1
|
+
import { Pitch } from './Pitch.js';
|
|
2
|
+
import { Accidental, AccidentalDisplay, Arpeggio, Articulation, BeamLevels, Bend, Bowing, Duration, Dynamic, FretboardDiagram, Glissando, GraceNote, Hairpin, Harmonic, Lyric, NoteheadShape, Ornament, OrnamentDetails, Ottava, Pedal, Placement, RestDisplay, Slur, StemDirection, TieSpan, Tuplet } from './types.js';
|
|
6
3
|
export declare class Note {
|
|
7
4
|
readonly duration: Duration;
|
|
8
5
|
readonly pitch?: Pitch | undefined;
|
|
9
6
|
readonly isRest: boolean;
|
|
10
|
-
readonly
|
|
7
|
+
readonly dotCount: number;
|
|
11
8
|
readonly accidental?: Accidental | undefined;
|
|
12
9
|
readonly beamGroup?: number | undefined;
|
|
13
10
|
readonly articulations: Articulation[];
|
|
@@ -17,6 +14,7 @@ export declare class Note {
|
|
|
17
14
|
readonly tuplet?: Tuplet | undefined;
|
|
18
15
|
readonly hairpin?: Hairpin | undefined;
|
|
19
16
|
readonly isGrace: boolean;
|
|
17
|
+
readonly isCue: boolean;
|
|
20
18
|
readonly lyric?: Lyric | undefined;
|
|
21
19
|
readonly chord?: string | undefined;
|
|
22
20
|
readonly glissando?: Glissando | undefined;
|
|
@@ -38,9 +36,21 @@ export declare class Note {
|
|
|
38
36
|
readonly palmMute?: "start" | "stop" | undefined;
|
|
39
37
|
readonly hammerOn?: "start" | "stop" | undefined;
|
|
40
38
|
readonly pullOff?: "start" | "stop" | undefined;
|
|
39
|
+
readonly tieSpans: TieSpan[];
|
|
40
|
+
readonly slurs: Slur[];
|
|
41
|
+
readonly beamLevels?: BeamLevels | undefined;
|
|
42
|
+
readonly grace?: GraceNote | undefined;
|
|
43
|
+
readonly accidentalDisplay?: AccidentalDisplay | undefined;
|
|
44
|
+
readonly restDisplay?: RestDisplay | undefined;
|
|
45
|
+
readonly ornamentDetails?: OrnamentDetails | undefined;
|
|
46
|
+
readonly harmonic?: Harmonic | undefined;
|
|
47
|
+
readonly bend?: Bend | undefined;
|
|
48
|
+
readonly vibrato?: "start" | "stop" | "single" | undefined;
|
|
49
|
+
readonly placement?: Placement | undefined;
|
|
41
50
|
constructor(duration: Duration, pitch?: Pitch | undefined, // undefined for rests
|
|
42
|
-
isRest?: boolean,
|
|
43
|
-
articulations?: Articulation[], dynamic?: Dynamic | undefined, tie?: boolean | undefined, slur?: Slur | undefined, tuplet?: Tuplet | undefined, hairpin?: Hairpin | undefined, isGrace?: boolean, lyric?: Lyric | undefined, chord?: string | undefined, glissando?: Glissando | undefined, arpeggio?: Arpeggio | undefined, ottava?: Ottava | undefined, pedal?: Pedal | undefined, ornament?: Ornament | undefined, fret?: number | undefined, string?: number | undefined, fretboardDiagram?: FretboardDiagram | undefined, lyrics?: Lyric[] | undefined, staffText?: string | undefined, color?: string | undefined, notehead?: NoteheadShape | undefined, bowing?: Bowing | undefined, fingering?: number | undefined, stemDirection?: StemDirection | undefined, isStringCircled?: boolean | undefined, palmMute?: "start" | "stop" | undefined, hammerOn?: "start" | "stop" | undefined, pullOff?: "start" | "stop" | undefined);
|
|
51
|
+
isRest?: boolean, dotCount?: number, accidental?: Accidental | undefined, beamGroup?: number | undefined, // Group ID for beamed notes
|
|
52
|
+
articulations?: Articulation[], dynamic?: Dynamic | undefined, tie?: boolean | undefined, slur?: Slur | undefined, tuplet?: Tuplet | undefined, hairpin?: Hairpin | undefined, isGrace?: boolean, isCue?: boolean, lyric?: Lyric | undefined, chord?: string | undefined, glissando?: Glissando | undefined, arpeggio?: Arpeggio | undefined, ottava?: Ottava | undefined, pedal?: Pedal | undefined, ornament?: Ornament | undefined, fret?: number | undefined, string?: number | undefined, fretboardDiagram?: FretboardDiagram | undefined, lyrics?: Lyric[] | undefined, staffText?: string | undefined, color?: string | undefined, notehead?: NoteheadShape | undefined, bowing?: Bowing | undefined, fingering?: number | undefined, stemDirection?: StemDirection | undefined, isStringCircled?: boolean | undefined, palmMute?: "start" | "stop" | undefined, hammerOn?: "start" | "stop" | undefined, pullOff?: "start" | "stop" | undefined, tieSpans?: TieSpan[], slurs?: Slur[], beamLevels?: BeamLevels | undefined, grace?: GraceNote | undefined, accidentalDisplay?: AccidentalDisplay | undefined, restDisplay?: RestDisplay | undefined, ornamentDetails?: OrnamentDetails | undefined, harmonic?: Harmonic | undefined, bend?: Bend | undefined, vibrato?: "start" | "stop" | "single" | undefined, placement?: Placement | undefined);
|
|
53
|
+
get isDotted(): boolean;
|
|
44
54
|
/**
|
|
45
55
|
* Get all lyrics as standardized objects
|
|
46
56
|
*/
|
|
@@ -58,6 +68,7 @@ export declare class Note {
|
|
|
58
68
|
*/
|
|
59
69
|
isBeamable(): boolean;
|
|
60
70
|
withGrace(isGrace: boolean): Note;
|
|
71
|
+
withCue(isCue: boolean): Note;
|
|
61
72
|
withChord(chord?: string): Note;
|
|
62
73
|
transpose(semitones: number): Note;
|
|
63
74
|
transposeOctave(octaves: number): Note;
|
|
@@ -74,7 +85,8 @@ export declare class Note {
|
|
|
74
85
|
withLyrics(lyrics: Lyric[]): Note;
|
|
75
86
|
withHairpin(hairpin?: Hairpin): Note;
|
|
76
87
|
withAccidental(accidental?: Accidental): Note;
|
|
77
|
-
|
|
88
|
+
withAccidentalDisplay(accidentalDisplay?: AccidentalDisplay): Note;
|
|
89
|
+
withDuration(duration: Duration, dotCount?: number): Note;
|
|
78
90
|
withRest(isRest: boolean): Note;
|
|
79
91
|
withFretboardDiagram(diagram?: FretboardDiagram): Note;
|
|
80
92
|
withBeamGroup(beamGroup?: number): Note;
|
|
@@ -83,6 +95,7 @@ export declare class Note {
|
|
|
83
95
|
withOttava(ottava?: Ottava): Note;
|
|
84
96
|
withPedal(pedal?: Pedal): Note;
|
|
85
97
|
withOrnament(ornament?: Ornament): Note;
|
|
98
|
+
withOrnamentDetails(ornamentDetails?: OrnamentDetails): Note;
|
|
86
99
|
withTab(fret: number, string: number): Note;
|
|
87
100
|
withStaffText(text?: string): Note;
|
|
88
101
|
withColor(color?: string): Note;
|
|
@@ -94,6 +107,9 @@ export declare class Note {
|
|
|
94
107
|
withPalmMute(palmMute?: 'start' | 'stop'): Note;
|
|
95
108
|
withHammerOn(hammerOn?: 'start' | 'stop'): Note;
|
|
96
109
|
withPullOff(pullOff?: 'start' | 'stop'): Note;
|
|
110
|
+
withHarmonic(harmonic?: Harmonic): Note;
|
|
111
|
+
withBend(bend?: Bend): Note;
|
|
112
|
+
withVibrato(vibrato?: 'start' | 'stop' | 'single'): Note;
|
|
97
113
|
toJSON(): NoteJSON;
|
|
98
114
|
static fromJSON(data: NoteJSON): Note;
|
|
99
115
|
}
|
|
@@ -107,16 +123,21 @@ export interface NoteJSON {
|
|
|
107
123
|
};
|
|
108
124
|
isRest?: boolean;
|
|
109
125
|
isDotted?: boolean;
|
|
126
|
+
dotCount?: number;
|
|
110
127
|
accidental?: string;
|
|
111
128
|
beamGroup?: number;
|
|
129
|
+
beamLevels?: BeamLevels;
|
|
112
130
|
articulation?: string;
|
|
113
131
|
articulations?: string[];
|
|
114
132
|
dynamic?: string;
|
|
115
133
|
tie?: boolean;
|
|
116
134
|
slur?: Slur;
|
|
135
|
+
tieSpans?: TieSpan[];
|
|
136
|
+
slurs?: Slur[];
|
|
117
137
|
tuplet?: Tuplet;
|
|
118
138
|
hairpin?: Hairpin;
|
|
119
139
|
isGrace?: boolean;
|
|
140
|
+
isCue?: boolean;
|
|
120
141
|
lyric?: Lyric;
|
|
121
142
|
chord?: string;
|
|
122
143
|
glissando?: Glissando;
|
|
@@ -138,4 +159,12 @@ export interface NoteJSON {
|
|
|
138
159
|
palmMute?: 'start' | 'stop';
|
|
139
160
|
hammerOn?: 'start' | 'stop';
|
|
140
161
|
pullOff?: 'start' | 'stop';
|
|
162
|
+
grace?: GraceNote;
|
|
163
|
+
accidentalDisplay?: AccidentalDisplay;
|
|
164
|
+
restDisplay?: RestDisplay;
|
|
165
|
+
ornamentDetails?: OrnamentDetails;
|
|
166
|
+
harmonic?: Harmonic;
|
|
167
|
+
bend?: Bend;
|
|
168
|
+
vibrato?: 'start' | 'stop' | 'single';
|
|
169
|
+
placement?: Placement;
|
|
141
170
|
}
|