@scorelabs/core 1.0.11 → 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.
Files changed (50) hide show
  1. package/dist/importers/MusicXMLParser.d.ts +2 -0
  2. package/dist/importers/MusicXMLParser.js +518 -71
  3. package/dist/models/Measure.d.ts +19 -2
  4. package/dist/models/Measure.js +79 -27
  5. package/dist/models/Note.d.ts +35 -5
  6. package/dist/models/Note.js +97 -42
  7. package/dist/models/NoteSet.d.ts +11 -2
  8. package/dist/models/NoteSet.js +33 -2
  9. package/dist/models/Part.d.ts +1 -1
  10. package/dist/models/Part.js +2 -2
  11. package/dist/models/Score.d.ts +5 -5
  12. package/dist/models/Score.js +144 -121
  13. package/dist/models/Staff.d.ts +1 -1
  14. package/dist/models/Staff.js +2 -2
  15. package/dist/types/AccidentalDisplay.d.ts +6 -0
  16. package/dist/types/AccidentalDisplay.js +1 -0
  17. package/dist/types/Arpeggio.d.ts +2 -1
  18. package/dist/types/Arpeggio.js +1 -0
  19. package/dist/types/Articulation.d.ts +3 -1
  20. package/dist/types/Articulation.js +2 -0
  21. package/dist/types/Beam.d.ts +4 -0
  22. package/dist/types/Beam.js +1 -0
  23. package/dist/types/Duration.d.ts +1 -1
  24. package/dist/types/Duration.js +14 -14
  25. package/dist/types/Grace.d.ts +7 -0
  26. package/dist/types/Grace.js +1 -0
  27. package/dist/types/Hairpin.d.ts +2 -1
  28. package/dist/types/Language.d.ts +6 -0
  29. package/dist/types/Language.js +7 -0
  30. package/dist/types/Lyric.d.ts +2 -0
  31. package/dist/types/Ornament.d.ts +23 -1
  32. package/dist/types/Ornament.js +9 -0
  33. package/dist/types/Pedal.d.ts +3 -2
  34. package/dist/types/Placement.d.ts +7 -0
  35. package/dist/types/Placement.js +1 -0
  36. package/dist/types/Repeat.d.ts +1 -0
  37. package/dist/types/RestDisplay.d.ts +6 -0
  38. package/dist/types/RestDisplay.js +1 -0
  39. package/dist/types/Slur.d.ts +1 -0
  40. package/dist/types/Technical.d.ts +20 -0
  41. package/dist/types/Technical.js +5 -0
  42. package/dist/types/Tempo.d.ts +0 -1
  43. package/dist/types/Tie.d.ts +4 -0
  44. package/dist/types/Tie.js +1 -0
  45. package/dist/types/Tuplet.d.ts +6 -0
  46. package/dist/types/User.d.ts +13 -7
  47. package/dist/types/User.js +9 -7
  48. package/dist/types/index.d.ts +8 -0
  49. package/dist/types/index.js +8 -0
  50. package/package.json +2 -1
@@ -17,15 +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
- 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, barlineStyle?: BarlineStyle);
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[];
23
30
  getNoteOffset(voiceIndex: number, noteIndex: number): number;
24
31
  moveNoteToVoice(fromVoiceIndex: number, noteIndex: number, toVoiceIndex: number): Measure;
25
32
  splitNote(voiceIndex: number, noteIndex: number, splitOffset: number): Measure;
26
33
  get hasStartRepeat(): boolean;
27
34
  get hasEndRepeat(): boolean;
28
- changeNoteDuration(noteIndex: number, newDuration: Duration, dotCountOrIsDotted?: number | boolean, voiceIndex?: number): Measure;
35
+ changeNoteDuration(noteIndex: number, newDuration: Duration, dotCount?: number, voiceIndex?: number): Measure;
29
36
  getTotalDuration(voiceIndex?: number): number;
30
37
  static fromJSON(data: MeasureJSON): Measure;
31
38
  transpose(semitones: number): Measure;
@@ -48,12 +55,17 @@ export declare class Measure {
48
55
  withRehearsalMark(mark?: string): Measure;
49
56
  withSystemText(text?: string): Measure;
50
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;
51
62
  fillVoiceWithRests(voiceIndex: number, targetDuration: number): Measure;
52
63
  simplifyRests(voiceIndex?: number): Measure;
53
64
  private decomposeToRests;
54
65
  toJSON(): MeasureJSON;
55
66
  }
56
67
  export interface MeasureJSON {
68
+ uuid?: string;
57
69
  notes?: NoteJSON[];
58
70
  voices?: NoteSetJSON[][];
59
71
  timeSignature?: TimeSignature;
@@ -68,5 +80,10 @@ export interface MeasureJSON {
68
80
  tempo?: Tempo;
69
81
  rehearsalMark?: string;
70
82
  systemText?: string;
83
+ multiMeasureRestCount?: number;
84
+ roadmapDirections?: string[];
71
85
  barlineStyle?: BarlineStyle;
86
+ systemDistance?: number;
87
+ staffDistance?: number;
88
+ topSystemDistance?: number;
72
89
  }
@@ -1,6 +1,17 @@
1
1
  import { Note } from './Note.js';
2
2
  import { NoteSet } from './NoteSet.js';
3
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
- constructor(voices, timeSignature, keySignature, systemBreak = false, pageBreak = false, repeats = [], volta, isPickup = false, clef, tempo, rehearsalMark, systemText, barlineStyle = BarlineStyle.Regular) {
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
  }
@@ -110,11 +134,11 @@ export class Measure {
110
134
  return this;
111
135
  const leftParts = decomposeDuration(splitOffset);
112
136
  const rightParts = decomposeDuration(duration - splitOffset);
113
- const leftNotes = leftParts.map((p) => target.withDuration(p.duration, p.isDotted).withTie(target.isRest ? false : true));
137
+ const leftNotes = leftParts.map((p) => target.withDuration(p.duration, p.dotCount).withTie(target.isRest ? false : true));
114
138
  const rightNotes = rightParts.map((p, idx) => {
115
139
  const isLast = idx === rightParts.length - 1;
116
140
  return target
117
- .withDuration(p.duration, p.isDotted)
141
+ .withDuration(p.duration, p.dotCount)
118
142
  .withTie(isLast ? !!target.notes[0].tie : !target.isRest);
119
143
  });
120
144
  const newVoice = [...voice];
@@ -129,21 +153,20 @@ export class Measure {
129
153
  get hasEndRepeat() {
130
154
  return this.repeats.some((r) => r.type === 'end');
131
155
  }
132
- changeNoteDuration(noteIndex, newDuration, dotCountOrIsDotted = 0, voiceIndex = 0) {
156
+ changeNoteDuration(noteIndex, newDuration, dotCount = 0, voiceIndex = 0) {
133
157
  const voice = this.voices[voiceIndex];
134
158
  if (!voice || noteIndex < 0 || noteIndex >= voice.length)
135
159
  return this;
136
160
  const targetNoteSet = voice[noteIndex];
137
161
  const oldVal = targetNoteSet.getDurationValue();
138
- const dotCount = typeof dotCountOrIsDotted === 'number' ? dotCountOrIsDotted : (dotCountOrIsDotted ? 1 : 0);
139
162
  const newVal = calculateDurationValue(newDuration, dotCount);
140
163
  if (Math.abs(newVal - oldVal) < 0.001)
141
164
  return this;
142
165
  const updatedVoice = [...voice];
143
166
  if (newVal < oldVal) {
144
167
  const gap = oldVal - newVal;
145
- updatedVoice[noteIndex] = targetNoteSet.withDuration(newDuration, dotCountOrIsDotted);
146
- const rests = decomposeDuration(gap).map((d) => new NoteSet([new Note(d.duration, undefined, true, d.isDotted)]));
168
+ updatedVoice[noteIndex] = targetNoteSet.withDuration(newDuration, dotCount);
169
+ const rests = decomposeDuration(gap).map((d) => new NoteSet([new Note(d.duration, undefined, true, d.dotCount)]));
147
170
  updatedVoice.splice(noteIndex + 1, 0, ...rests);
148
171
  }
149
172
  else {
@@ -154,7 +177,7 @@ export class Measure {
154
177
  }
155
178
  if (available < delta - 0.001)
156
179
  return this;
157
- updatedVoice[noteIndex] = targetNoteSet.withDuration(newDuration, dotCountOrIsDotted);
180
+ updatedVoice[noteIndex] = targetNoteSet.withDuration(newDuration, dotCount);
158
181
  let consumed = 0;
159
182
  let removeCount = 0;
160
183
  const replacements = [];
@@ -169,7 +192,7 @@ export class Measure {
169
192
  }
170
193
  else {
171
194
  const remaining = consumed + val - delta;
172
- replacements.push(...decomposeDuration(remaining).map((d) => new NoteSet([new Note(d.duration, undefined, true, d.isDotted)])));
195
+ replacements.push(...decomposeDuration(remaining).map((d) => new NoteSet([new Note(d.duration, undefined, true, d.dotCount)])));
173
196
  removeCount++;
174
197
  break;
175
198
  }
@@ -178,7 +201,12 @@ export class Measure {
178
201
  }
179
202
  const newVoices = [...this.voices];
180
203
  newVoices[voiceIndex] = updatedVoice;
181
- let result = this.withVoices(newVoices).simplifyRests(voiceIndex);
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
+ }
182
210
  if (this.timeSignature) {
183
211
  result = result.autoBeam(this.timeSignature);
184
212
  }
@@ -207,7 +235,8 @@ export class Measure {
207
235
  else {
208
236
  voices = [[]];
209
237
  }
210
- 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);
211
240
  }
212
241
  transpose(semitones) {
213
242
  let newKeySignature;
@@ -274,7 +303,12 @@ export class Measure {
274
303
  }
275
304
  const newVoices = [...this.voices];
276
305
  newVoices[voiceIndex] = updatedVoice;
277
- let result = this.withVoices(newVoices).simplifyRests(voiceIndex);
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
+ }
278
312
  if (this.timeSignature) {
279
313
  result = result.autoBeam(this.timeSignature);
280
314
  }
@@ -375,25 +409,25 @@ export class Measure {
375
409
  return this.withVoices(newVoices);
376
410
  }
377
411
  withTimeSignature(timeSignature) {
378
- 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);
379
413
  }
380
414
  withKeySignature(keySignature) {
381
- 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);
382
416
  }
383
417
  withClef(clef) {
384
- 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);
385
419
  }
386
420
  withTempo(tempo) {
387
- 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);
388
422
  }
389
423
  withSystemBreak(systemBreak) {
390
- 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);
391
425
  }
392
426
  withPageBreak(pageBreak) {
393
- 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);
394
428
  }
395
429
  withVoices(voices) {
396
- 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);
397
431
  }
398
432
  withVoiceNotes(notes, voiceIndex = 0) {
399
433
  const newVoices = [...this.voices];
@@ -416,22 +450,34 @@ export class Measure {
416
450
  return this.withRepeats(newRepeats);
417
451
  }
418
452
  withRepeats(repeats) {
419
- 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);
420
454
  }
421
455
  withVolta(volta) {
422
- 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);
423
457
  }
424
458
  withPickup(isPickup) {
425
- 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);
426
460
  }
427
461
  withRehearsalMark(mark) {
428
- 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);
429
463
  }
430
464
  withSystemText(text) {
431
- 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);
432
466
  }
433
467
  withBarlineStyle(style) {
434
- 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);
435
481
  }
436
482
  fillVoiceWithRests(voiceIndex, targetDuration) {
437
483
  const newVoices = [...this.voices];
@@ -442,7 +488,7 @@ export class Measure {
442
488
  const currentDuration = currentVoice.reduce((sum, ns) => sum + ns.getDurationValue(), 0);
443
489
  if (currentDuration < targetDuration - 0.001) {
444
490
  const gap = targetDuration - currentDuration;
445
- const rests = decomposeDuration(gap).map((d) => new NoteSet([new Note(d.duration, undefined, true, d.isDotted)]));
491
+ const rests = decomposeDuration(gap).map((d) => new NoteSet([new Note(d.duration, undefined, true, d.dotCount)]));
446
492
  newVoices[voiceIndex] = [...currentVoice, ...rests];
447
493
  }
448
494
  return this.withVoices(newVoices);
@@ -485,10 +531,11 @@ export class Measure {
485
531
  return this.withVoices(newVoices);
486
532
  }
487
533
  decomposeToRests(value) {
488
- return decomposeDuration(value).map((d) => new NoteSet([new Note(d.duration, undefined, true, d.isDotted)]));
534
+ return decomposeDuration(value).map((d) => new NoteSet([new Note(d.duration, undefined, true, d.dotCount)]));
489
535
  }
490
536
  toJSON() {
491
537
  return {
538
+ uuid: this.uuid,
492
539
  voices: this.voices.map((v) => v.map((ns) => ns.toJSON())),
493
540
  timeSignature: this.timeSignature,
494
541
  keySignature: this.keySignature,
@@ -501,7 +548,12 @@ export class Measure {
501
548
  tempo: this.tempo,
502
549
  rehearsalMark: this.rehearsalMark,
503
550
  systemText: this.systemText,
551
+ multiMeasureRestCount: this.multiMeasureRestCount,
552
+ roadmapDirections: this.roadmapDirections,
504
553
  barlineStyle: this.barlineStyle,
554
+ systemDistance: this.systemDistance,
555
+ staffDistance: this.staffDistance,
556
+ topSystemDistance: this.topSystemDistance,
505
557
  };
506
558
  }
507
559
  }
@@ -1,9 +1,10 @@
1
1
  import { Pitch } from './Pitch.js';
2
- import { Accidental, Arpeggio, Articulation, Bowing, Duration, Dynamic, FretboardDiagram, Glissando, Hairpin, Lyric, NoteheadShape, Ornament, Ottava, Pedal, Slur, StemDirection, Tuplet } from './types.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';
3
3
  export declare class Note {
4
4
  readonly duration: Duration;
5
5
  readonly pitch?: Pitch | undefined;
6
6
  readonly isRest: boolean;
7
+ readonly dotCount: number;
7
8
  readonly accidental?: Accidental | undefined;
8
9
  readonly beamGroup?: number | undefined;
9
10
  readonly articulations: Articulation[];
@@ -13,6 +14,7 @@ export declare class Note {
13
14
  readonly tuplet?: Tuplet | undefined;
14
15
  readonly hairpin?: Hairpin | undefined;
15
16
  readonly isGrace: boolean;
17
+ readonly isCue: boolean;
16
18
  readonly lyric?: Lyric | undefined;
17
19
  readonly chord?: string | undefined;
18
20
  readonly glissando?: Glissando | undefined;
@@ -34,10 +36,20 @@ export declare class Note {
34
36
  readonly palmMute?: "start" | "stop" | undefined;
35
37
  readonly hammerOn?: "start" | "stop" | undefined;
36
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;
37
50
  constructor(duration: Duration, pitch?: Pitch | undefined, // undefined for rests
38
- isRest?: boolean, dotCountOrIsDotted?: number | boolean, accidental?: Accidental | undefined, beamGroup?: number | undefined, // Group ID for beamed notes
39
- 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);
40
- readonly dotCount: number;
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);
41
53
  get isDotted(): boolean;
42
54
  /**
43
55
  * Get all lyrics as standardized objects
@@ -56,6 +68,7 @@ export declare class Note {
56
68
  */
57
69
  isBeamable(): boolean;
58
70
  withGrace(isGrace: boolean): Note;
71
+ withCue(isCue: boolean): Note;
59
72
  withChord(chord?: string): Note;
60
73
  transpose(semitones: number): Note;
61
74
  transposeOctave(octaves: number): Note;
@@ -72,7 +85,8 @@ export declare class Note {
72
85
  withLyrics(lyrics: Lyric[]): Note;
73
86
  withHairpin(hairpin?: Hairpin): Note;
74
87
  withAccidental(accidental?: Accidental): Note;
75
- withDuration(duration: Duration, dotCountOrIsDotted?: number | boolean): Note;
88
+ withAccidentalDisplay(accidentalDisplay?: AccidentalDisplay): Note;
89
+ withDuration(duration: Duration, dotCount?: number): Note;
76
90
  withRest(isRest: boolean): Note;
77
91
  withFretboardDiagram(diagram?: FretboardDiagram): Note;
78
92
  withBeamGroup(beamGroup?: number): Note;
@@ -81,6 +95,7 @@ export declare class Note {
81
95
  withOttava(ottava?: Ottava): Note;
82
96
  withPedal(pedal?: Pedal): Note;
83
97
  withOrnament(ornament?: Ornament): Note;
98
+ withOrnamentDetails(ornamentDetails?: OrnamentDetails): Note;
84
99
  withTab(fret: number, string: number): Note;
85
100
  withStaffText(text?: string): Note;
86
101
  withColor(color?: string): Note;
@@ -92,6 +107,9 @@ export declare class Note {
92
107
  withPalmMute(palmMute?: 'start' | 'stop'): Note;
93
108
  withHammerOn(hammerOn?: 'start' | 'stop'): Note;
94
109
  withPullOff(pullOff?: 'start' | 'stop'): Note;
110
+ withHarmonic(harmonic?: Harmonic): Note;
111
+ withBend(bend?: Bend): Note;
112
+ withVibrato(vibrato?: 'start' | 'stop' | 'single'): Note;
95
113
  toJSON(): NoteJSON;
96
114
  static fromJSON(data: NoteJSON): Note;
97
115
  }
@@ -108,14 +126,18 @@ export interface NoteJSON {
108
126
  dotCount?: number;
109
127
  accidental?: string;
110
128
  beamGroup?: number;
129
+ beamLevels?: BeamLevels;
111
130
  articulation?: string;
112
131
  articulations?: string[];
113
132
  dynamic?: string;
114
133
  tie?: boolean;
115
134
  slur?: Slur;
135
+ tieSpans?: TieSpan[];
136
+ slurs?: Slur[];
116
137
  tuplet?: Tuplet;
117
138
  hairpin?: Hairpin;
118
139
  isGrace?: boolean;
140
+ isCue?: boolean;
119
141
  lyric?: Lyric;
120
142
  chord?: string;
121
143
  glissando?: Glissando;
@@ -137,4 +159,12 @@ export interface NoteJSON {
137
159
  palmMute?: 'start' | 'stop';
138
160
  hammerOn?: 'start' | 'stop';
139
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;
140
170
  }