@tspro/web-music-score 4.0.1 → 4.2.0

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 (34) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/README.md +70 -28
  3. package/dist/audio/index.js +1 -1
  4. package/dist/audio/index.mjs +2 -2
  5. package/dist/audio-cg/index.js +1 -1
  6. package/dist/audio-cg/index.mjs +2 -2
  7. package/dist/{chunk-YFPLOHP2.mjs → chunk-5NWLGWHS.mjs} +2 -2
  8. package/dist/chunk-7MNV5JN6.mjs +264 -0
  9. package/dist/core/index.js +2 -2
  10. package/dist/core/index.mjs +3 -3
  11. package/dist/iife/index.global.js +11 -11
  12. package/dist/{music-objects-DJQ4d2OA.d.mts → music-objects-3Hxlkxy6.d.mts} +172 -80
  13. package/dist/{music-objects-Dc3kR-XF.d.ts → music-objects-CI7IjsjE.d.ts} +172 -80
  14. package/dist/pieces/index.d.mts +2 -2
  15. package/dist/pieces/index.d.ts +2 -2
  16. package/dist/pieces/index.js +3 -3
  17. package/dist/pieces/index.mjs +4 -4
  18. package/dist/react-ui/index.d.mts +3 -3
  19. package/dist/react-ui/index.d.ts +3 -3
  20. package/dist/react-ui/index.js +1 -1
  21. package/dist/react-ui/index.mjs +2 -2
  22. package/dist/{scale-B2Icbetz.d.ts → scale-DGx3tJH4.d.ts} +1 -1
  23. package/dist/{scale-BbDJTbrG.d.mts → scale-DQP3b9Zx.d.mts} +1 -1
  24. package/dist/score/index.d.mts +60 -23
  25. package/dist/score/index.d.ts +60 -23
  26. package/dist/score/index.js +910 -349
  27. package/dist/score/index.mjs +630 -320
  28. package/dist/{tempo-Dt8aHpol.d.ts → tempo-GrstpD9G.d.ts} +42 -10
  29. package/dist/{tempo-CtUhvJbr.d.mts → tempo-dkctPkCS.d.mts} +42 -10
  30. package/dist/theory/index.d.mts +3 -3
  31. package/dist/theory/index.d.ts +3 -3
  32. package/dist/theory/index.js +70 -20
  33. package/dist/theory/index.mjs +84 -280
  34. package/package.json +8 -3
package/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # Changelog
2
2
 
3
+ ## [4.2.0] - 2025-10-03
4
+ ## Added
5
+ - Add support for lyrics/syllables with alignment and hyphen/extender.
6
+ - addNote accepts array of notes to add multiple notes at once.
7
+ - 3/8 time signature.
8
+
9
+ ## [4.1.0] - 2025-10-01
10
+ ## Added
11
+ - 4-4 (in adition to 2-2-2-2) beam grouping for 4/4 time signature.
12
+ - 12/8 time signature.
13
+ - 5/8 time signature and 2-3 and 3-2 beam groupings.
14
+ - 7/8 time signature and 2-2-3 and 3-2-2 beam groupings.
15
+
3
16
  ## [4.0.1] - 2025-09-28
4
17
  ## Fixed
5
18
  - Invalid typedoc @params.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
- # WebMusicScore
1
+ # Web Music Score
2
2
 
3
- The API Reference, Examples and Demos can be found [here](https://pahkasoft.github.io). The API Reference is very little commented but gives idea of the full API.
3
+ Homepage (docs, examples and demos): [Web Music Score](https://pahkasoft.github.io/web-music-score)
4
4
 
5
5
  ## About
6
6
 
@@ -13,8 +13,6 @@ This is a work in progress project. Lately there has been improvements that requ
13
13
  version update. As the project matures there might be less major updates, and more minor
14
14
  updates and patches.
15
15
 
16
- Version 4.0.0 added support for string arguments in addition to typescript enums (e.g. NoteLength.Quarter => "4n", just to name one).
17
-
18
16
  ## Installation
19
17
 
20
18
  ```sh
@@ -55,14 +53,17 @@ corresponding subpath modules (`react-ui` and `audio-cg` are not included in thi
55
53
  browser module).
56
54
 
57
55
  ```html
58
- <script src="https://unpkg.com/@tspro/web-music-score@4"></script>
59
- <script src="https://unpkg.com/@tspro/web-music-score@4.0.0"></script>
60
- <script src="https://unpkg.com/@tspro/web-music-score@4.0.0/dist/iife/index.global.js"></script>
56
+ <!--
57
+ It is recommended to use exact version number so that if something
58
+ breaks between versions then your web site does not stop working.
59
+ -->
60
+ <script src="https://unpkg.com/@tspro/web-music-score@4.2.0"></script>
61
61
 
62
62
  <!--
63
- Use one of above. It is recommended to use version number (e.g. @4.0.0 or at least @4).
64
- This way if something breaks between versions then your web site does not stop working.
63
+ Or you can use direct link to the js bundle.
65
64
  -->
65
+ <script src="https://unpkg.com/@tspro/web-music-score@4.2.0/dist/iife/index.global.js"></script>
66
+
66
67
 
67
68
  <script>
68
69
  const { Core, Audio, Theory, Score, Pieces } = window.WebMusicScore;
@@ -179,12 +180,22 @@ or corresponding string values (e.g. `"Major"`).
179
180
  ```
180
181
 
181
182
  ### Set Time Signature
183
+ For time signature you can use `Theory.TimeSignatures` enum values (e.g. `Theory.TimeSignatures._2_4`)
184
+ or corresponding string values (e.g. `"2/4"`).
185
+
186
+ For optional beam grouping argument for 5/8 and 7/8 time signatures you can use `Theory.BeamGrouping`
187
+ enum values (e.g. `Theory.BeamGrouping._2_2_3`) or corresponding string values (e.g. `"2-2-3"`).
188
+
182
189
  ```js
183
- .setTimeSignature("2/4") // Set time signature of 2/4
184
- .setTimeSignature("3/4") // Set time signature of 3/4
185
- .setTimeSignature("4/4") // Set time signature of 4/4
186
- .setTimeSignature("6/8") // Set time signature of 6/8
187
- .setTimeSignature("9/8") // Set time signature of 9/8
190
+ .setTimeSignature("2/4") // Set 2/4 time signature.
191
+ .setTimeSignature("3/4") // Set 3/4 time signature.
192
+ .setTimeSignature("4/4") // Set 4/4 time signature.
193
+ .setTimeSignature("3/8") // Set 3/8 time signature.
194
+ .setTimeSignature("5/8", "2-3") // Set 5/8 time signature. Available beam groupings are "2-3" (default) and "3-2".
195
+ .setTimeSignature("6/8") // Set 6/8 time signature.
196
+ .setTimeSignature("7/8", "2-2-3") // Set 7/8 time signature. Available beam groupings are "2-2-3" (default) and "3-2-2".
197
+ .setTimeSignature("9/8") // Set 9/8 time signature.
198
+ .setTimeSignature(12, 8) // Set 12/8 time signature using number arguments.
188
199
  ```
189
200
 
190
201
  ### Set Tempo
@@ -195,8 +206,9 @@ or corresponding string values (e.g. `"Major"`).
195
206
 
196
207
  ### Add Note
197
208
  ```js
198
- .addNote(0, "C4", "1n") // Create whole note "C4"
199
- .addNote(0, "Bb4", "2..") // Create double dotted half note "Bb4"
209
+ .addNote(0, "C4", "1n") // Add whole note "C4"
210
+ .addNote(0, ["C4", "D4", "G4"], "1n") // Add three notes "C4", "D4", "G4" seuqentially (no chord).
211
+ .addNote(0, "Bb4", "2..") // Add double dotted half note "Bb4"
200
212
  .addNote(0, "C4", "4n", { stem: "up" }) // Stem direction Up (could be also Down)
201
213
  .addNote(0, "C4", "4n", { staccate: true }) // Show staccato dot and play in short
202
214
  .addNote(0, "C4", "4n", { diamond: true }) // Show diamond shaped note head
@@ -217,7 +229,7 @@ or corresponding string values (e.g. `"Major"`).
217
229
  ```
218
230
 
219
231
  ### Add Tuplet
220
- This works for any tuplet:
232
+ This generic function works for any tuplet:
221
233
  ```js
222
234
  // Example: add triplet
223
235
  .addTuplet(0, { parts: 3, inTimeOf: 2 }, notes => {
@@ -230,14 +242,30 @@ This works for any tuplet:
230
242
  Triplets can also be created using note length (e.g. NoteLength.EighthTriplet or "8t").
231
243
  ```js
232
244
  // Example: add triplet using triplet note length.
233
- .addNote(0, "G3", "8t")
234
- .addNote(0, "B3", "8t")
235
- .addNote(0, "D4", "8t")
245
+ .addNote(0, ["G3", "B3", "D4"], "8t")
246
+ ```
247
+
248
+ ### Add Lyrics
249
+
250
+ For lyrics align you can use `Score.LyricsAlign` enum values (e.g. `Score.LyricsAlign.Left`)
251
+ or corresponding string values (e.g. `"left"`).
252
+
253
+ For lyrics hyphen you can use `Score.LyricsHyphen` enum values (e.g. `Score.LyricsHyphen.Hyphen`)
254
+ or corresponding string values (e.g. `"-"`).
255
+
256
+ ```js
257
+ .addLyrics(1, "4n", "La") // Add lyrics text/syllable "La", quarter note length, verse 1.
258
+ .addLyrics(1, "4n", ["La", "la", "la", "la"]) // Add multiple lysics texts/syllables, each quarter note length, verse 1.
259
+ .addLyrics(2, "4n", "La", { align: "left" }) // Left align lyrics text/syllable.
260
+ .addLyrics(2, "4n", "La", { align: "center" }) // Center align lyrics text/syllable.
261
+ .addLyrics(2, "4n", "La", { align: "right" }) // Right align lyrics text/syllable.
262
+ .addLyrics(3, "4n", "La", { hyphen: "-" }) // Add hyphen (short line '-') centered between this and next syllable.
263
+ .addLyrics(3, "4n", "La", { hyphen: "---" }) // Add extender (long line) between this and next syllable.
236
264
  ```
237
265
 
238
266
  ### Add Fermata
239
267
 
240
- For fermata you can use `Score.Fermata` enum values (e.g. `Scoore.Fermata.AtNote`)
268
+ For fermata you can use `Score.Fermata` enum values (e.g. `Score.Fermata.AtNote`)
241
269
  or corresponding string values (e.g. `"atNote"`).
242
270
 
243
271
  ```js
@@ -293,8 +321,8 @@ or corresponding string values (e.g. `"chord"`).
293
321
 
294
322
  ### Positioning Elements
295
323
 
296
- `addFermata`, `addNavigation`, `addAnnotation` and `addLabel` functions have alternate versions
297
- `addFermataTo`, `addNavigationTo`, `addAnnotationTo` and `addLabelTo` that contain extra first argument.
324
+ `addLyrics`, `addFermata`, `addNavigation`, `addAnnotation` and `addLabel` functions have alternate versions
325
+ `addLyricsTo`, `addFermataTo`, `addNavigationTo`, `addAnnotationTo` and `addLabelTo` that contain extra first argument.
298
326
 
299
327
  ```js
300
328
  .addLabelTo(0, "chord", "Am") // Add label to top (id 0) staff/tab.
@@ -354,7 +382,23 @@ Add notes with `string` property to specify at what string the fret number is re
354
382
 
355
383
  ### Beams
356
384
 
357
- Beams are detected and added automatically.
385
+ Beams are detected using beam grouping logic that is defined for each time signature.
386
+ These are the beam groupings for each time signature.
387
+
388
+ | Time signature | Beam grouping |
389
+ |----------------|---------------|
390
+ | `2/4` | `2-2` |
391
+ | `3/4` | `2-2-2` |
392
+ | `4/4` | `4-4` and `2-2-2-2` together |
393
+ | `3/8` | `3` |
394
+ | `5/8` | `2-3` or `3-2`, user selectable |
395
+ | `6/8` | `3-3` |
396
+ | `7/8` | `2-2-3` or `3-2-2`, user selectable |
397
+ | `9/8` | `3-3-3` |
398
+ | `12/8` | `3-3-3-3` |
399
+
400
+ How to set beam grouping for `5/8` and `7/8` time signatures,
401
+ see [Set Time Signature](#set-time-signature) section above.
358
402
 
359
403
  ### Classical Guitar Audio Module
360
404
 
@@ -457,11 +501,9 @@ While designed for compatibility in mind, the library has not been explicitly te
457
501
 
458
502
  ## Report a Bug
459
503
 
460
- Found a bug or unexpected behavior?
461
-
462
- [Please open a new issue.](https://github.com/pahkasoft/issues/issues/new)
504
+ Found a bug or unexpected behavior? Suggest a feature or impovement?
463
505
 
464
- You can also suggest a feature or impovement.
506
+ [Please open a new issue.](https://github.com/pahkasoft/web-music-score/issues/new/choose)
465
507
 
466
508
  Thanks for helping improve the project!
467
509
 
@@ -1,4 +1,4 @@
1
- /* WebMusicScore v4.0.1 | (c) 2023 PahkaSoft | MIT License | Includes: Tone.js (MIT License) */
1
+ /* WebMusicScore v4.2.0 | (c) 2023 PahkaSoft | MIT License | Includes: Tone.js (MIT License) */
2
2
  "use strict";
3
3
  var __create = Object.create;
4
4
  var __defProp = Object.defineProperty;
@@ -1,7 +1,7 @@
1
- /* WebMusicScore v4.0.1 | (c) 2023 PahkaSoft | MIT License | Includes: Tone.js (MIT License) */
1
+ /* WebMusicScore v4.2.0 | (c) 2023 PahkaSoft | MIT License | Includes: Tone.js (MIT License) */
2
2
  import {
3
3
  __publicField
4
- } from "../chunk-YFPLOHP2.mjs";
4
+ } from "../chunk-5NWLGWHS.mjs";
5
5
 
6
6
  // src/audio/index.ts
7
7
  import { Note, PitchNotation, SymbolSet } from "@tspro/web-music-score/theory";
@@ -1,4 +1,4 @@
1
- /* WebMusicScore v4.0.1 | (c) 2023 PahkaSoft | MIT License | Includes: Tone.js (MIT License) */
1
+ /* WebMusicScore v4.2.0 | (c) 2023 PahkaSoft | MIT License | Includes: Tone.js (MIT License) */
2
2
  "use strict";
3
3
  var __create = Object.create;
4
4
  var __defProp = Object.defineProperty;
@@ -1,7 +1,7 @@
1
- /* WebMusicScore v4.0.1 | (c) 2023 PahkaSoft | MIT License | Includes: Tone.js (MIT License) */
1
+ /* WebMusicScore v4.2.0 | (c) 2023 PahkaSoft | MIT License | Includes: Tone.js (MIT License) */
2
2
  import {
3
3
  __publicField
4
- } from "../chunk-YFPLOHP2.mjs";
4
+ } from "../chunk-5NWLGWHS.mjs";
5
5
 
6
6
  // src/audio-cg/index.ts
7
7
  import * as Tone from "tone";
@@ -1,4 +1,4 @@
1
- /* WebMusicScore v4.0.1 | (c) 2023 PahkaSoft | MIT License | Includes: Tone.js (MIT License) */
1
+ /* WebMusicScore v4.2.0 | (c) 2023 PahkaSoft | MIT License | Includes: Tone.js (MIT License) */
2
2
  var __defProp = Object.defineProperty;
3
3
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
4
4
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
@@ -6,4 +6,4 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
6
6
  export {
7
7
  __publicField
8
8
  };
9
- //# sourceMappingURL=chunk-YFPLOHP2.mjs.map
9
+ //# sourceMappingURL=chunk-5NWLGWHS.mjs.map
@@ -0,0 +1,264 @@
1
+ /* WebMusicScore v4.2.0 | (c) 2023 PahkaSoft | MIT License | Includes: Tone.js (MIT License) */
2
+ import {
3
+ __publicField
4
+ } from "./chunk-5NWLGWHS.mjs";
5
+
6
+ // src/theory/rhythm.ts
7
+ import { Utils } from "@tspro/ts-utils-lib";
8
+ import { MusicError, MusicErrorType } from "@tspro/web-music-score/core";
9
+ var cmp = (a, b) => a === b ? 0 : a < b ? -1 : 1;
10
+ var MaxTupletRatioValue = 12;
11
+ var TicksMultiplier = 12 * 11 * 9 * 7 * 5;
12
+ var NoteLength = /* @__PURE__ */ ((NoteLength2) => {
13
+ NoteLength2["Whole"] = "1n";
14
+ NoteLength2["WholeTriplet"] = "1t";
15
+ NoteLength2["WholeDot"] = "1.";
16
+ NoteLength2["Whole2Dots"] = "1..";
17
+ NoteLength2["Whole12Dots"] = "1..";
18
+ NoteLength2["Whole3Dots"] = "1...";
19
+ NoteLength2["Whole4Dots"] = "1....";
20
+ NoteLength2["Whole5Dots"] = "1.....";
21
+ NoteLength2["Whole6Dots"] = "1......";
22
+ NoteLength2["Half"] = "2n";
23
+ NoteLength2["HalfTriplet"] = "2t";
24
+ NoteLength2["HalfDot"] = "2.";
25
+ NoteLength2["Half2Dots"] = "2..";
26
+ NoteLength2["Half3Dots"] = "2...";
27
+ NoteLength2["Half4Dots"] = "2....";
28
+ NoteLength2["Half5Dots"] = "2.....";
29
+ NoteLength2["Quarter"] = "4n";
30
+ NoteLength2["QuarterTriplet"] = "4t";
31
+ NoteLength2["QuarterDot"] = "4.";
32
+ NoteLength2["Quarter2Dots"] = "4..";
33
+ NoteLength2["Quarter3Dots"] = "4...";
34
+ NoteLength2["Quarter4Dots"] = "4....";
35
+ NoteLength2["Eighth"] = "8n";
36
+ NoteLength2["EighthTriplet"] = "8t";
37
+ NoteLength2["EighthDot"] = "8.";
38
+ NoteLength2["Eighth2Dots"] = "8..";
39
+ NoteLength2["Eighth3Dots"] = "8...";
40
+ NoteLength2["Sixteenth"] = "16n";
41
+ NoteLength2["SixteenthTriplet"] = "16t";
42
+ NoteLength2["SixteenthDot"] = "16.";
43
+ NoteLength2["Sixteenth2Dots"] = "16..";
44
+ NoteLength2["ThirtySecond"] = "32n";
45
+ NoteLength2["ThirtySecondTriplet"] = "32t";
46
+ NoteLength2["ThirtySecondDot"] = "32.";
47
+ NoteLength2["SixtyFourth"] = "64n";
48
+ NoteLength2["SixtyFourthTriplet"] = "64t";
49
+ return NoteLength2;
50
+ })(NoteLength || {});
51
+ function validateNoteLength(noteLength) {
52
+ if (Utils.Is.isEnumValue(noteLength, NoteLength)) {
53
+ return noteLength;
54
+ } else {
55
+ throw new MusicError(MusicErrorType.InvalidArg, `Invalid noteLength: ${noteLength}`);
56
+ }
57
+ }
58
+ var _NoteLengthProps = class _NoteLengthProps {
59
+ constructor(noteLength) {
60
+ /** Note length. */
61
+ __publicField(this, "noteLength");
62
+ /** Note size (whole=1, half=2, quarter=4, ...). */
63
+ __publicField(this, "noteSize");
64
+ /** Number of ticks (not altered by isTriplet). */
65
+ __publicField(this, "ticks");
66
+ /** Flag count. */
67
+ __publicField(this, "flagCount");
68
+ /** Dot count. */
69
+ __publicField(this, "dotCount");
70
+ /** Max dot count. */
71
+ __publicField(this, "maxDotCount");
72
+ /** Is triplet? */
73
+ __publicField(this, "isTriplet");
74
+ /** Has note stem. */
75
+ __publicField(this, "hasStem");
76
+ /** Is note head solid (black)? */
77
+ __publicField(this, "isSolid");
78
+ this.noteLength = validateNoteLength(noteLength);
79
+ this.noteSize = parseInt(noteLength);
80
+ this.isTriplet = noteLength.endsWith("t");
81
+ this.maxDotCount = this.isTriplet ? 0 : Math.floor(Math.log2(_NoteLengthProps.ShortestNoteSize / this.noteSize));
82
+ this.dotCount = Utils.Str.charCount(noteLength, ".");
83
+ this.flagCount = this.noteSize > 4 ? Math.floor(Math.log2(this.noteSize / 4)) : 0;
84
+ this.ticks = TicksMultiplier * _NoteLengthProps.ShortestNoteSize / this.noteSize;
85
+ this.hasStem = this.noteSize > 1;
86
+ this.isSolid = this.noteSize > 2;
87
+ if (this.dotCount > this.maxDotCount) {
88
+ throw new MusicError(MusicErrorType.Note, `dotCount ${this.dotCount} > maxDotCount ${this.maxDotCount}, for noteLength "${this.noteLength}".`);
89
+ } else if (this.isTriplet && this.dotCount > 0) {
90
+ throw new MusicError(MusicErrorType.Note, `noteLength "${this.noteLength}" is both triplet and dotted!`);
91
+ }
92
+ }
93
+ /**
94
+ * Get note length props.
95
+ * @param noteLength - Note length.
96
+ * @returns - Note length props.
97
+ */
98
+ static get(noteLength) {
99
+ let p = this.cache.get(noteLength);
100
+ if (!p) {
101
+ this.cache.set(noteLength, p = new _NoteLengthProps(noteLength));
102
+ }
103
+ return p;
104
+ }
105
+ /**
106
+ * Create note length props.
107
+ * @param noteLength - Note length or note size.
108
+ * @param dotCount - Dot count.
109
+ * @returns - Note length props.
110
+ */
111
+ static create(noteLength, dotCount = 0) {
112
+ let noteSize = typeof noteLength === "number" ? noteLength : this.get(noteLength).noteSize;
113
+ return this.get(noteSize + (Utils.Is.isIntegerGte(dotCount, 1) ? ".".repeat(dotCount) : "n"));
114
+ }
115
+ /**
116
+ * Compare note lengths/sizes. Whole (1) > half (2) > quarter (4), etc.
117
+ * Ignores possible triplet property of note length.
118
+ * @param a - NoteLengthProps, NoteLength/Str or noteSize
119
+ * @param b - NoteLengthProps, NoteLength/Str or noteSize
120
+ * @returns - -1: a < b, 0: a === b, +1: a > b (note length/size comparisons)
121
+ */
122
+ static cmp(a, b) {
123
+ let aNoteSize = a instanceof _NoteLengthProps ? a.noteSize : typeof a === "number" ? a : _NoteLengthProps.get(a).noteSize;
124
+ let bNoteSize = b instanceof _NoteLengthProps ? b.noteSize : typeof b === "number" ? b : _NoteLengthProps.get(b).noteSize;
125
+ return cmp(bNoteSize, aNoteSize);
126
+ }
127
+ /**
128
+ * Compare note lengths/sizes for equality.
129
+ * Ignores possible triplet property of note length.
130
+ * @param a - NoteLengthProps, NoteLength/Str or noteSize
131
+ * @param b - NoteLengthProps, NoteLength/Str or noteSize
132
+ * @returns - true: a === b, false: a !== b (note length/size comparisons)
133
+ */
134
+ static equals(a, b) {
135
+ let aNoteSize = a instanceof _NoteLengthProps ? a.noteSize : typeof a === "number" ? a : _NoteLengthProps.get(a).noteSize;
136
+ let bNoteSize = b instanceof _NoteLengthProps ? b.noteSize : typeof b === "number" ? b : _NoteLengthProps.get(b).noteSize;
137
+ return aNoteSize === bNoteSize;
138
+ }
139
+ };
140
+ /** Longest note size (e.g. 1 = whole note). */
141
+ __publicField(_NoteLengthProps, "LongestNoteSize", Math.min(...Utils.Enum.getEnumValues(NoteLength).map((noteLength) => parseInt(noteLength))));
142
+ /** Shortest note size (e.g. 64 = sixtyfourth note). */
143
+ __publicField(_NoteLengthProps, "ShortestNoteSize", Math.max(...Utils.Enum.getEnumValues(NoteLength).map((noteLength) => parseInt(noteLength))));
144
+ __publicField(_NoteLengthProps, "cache", /* @__PURE__ */ new Map());
145
+ var NoteLengthProps = _NoteLengthProps;
146
+ function validateTupletRatio(tupletRatio) {
147
+ if (Utils.Is.isObject(tupletRatio) && Utils.Is.isIntegerBetween(tupletRatio.parts, 2, MaxTupletRatioValue) && Utils.Is.isIntegerBetween(tupletRatio.inTimeOf, 2, MaxTupletRatioValue)) {
148
+ return tupletRatio;
149
+ } else {
150
+ throw new MusicError(MusicErrorType.Note, `Invalid tupletRatio ${JSON.stringify(tupletRatio)}`);
151
+ }
152
+ }
153
+ var Tuplet = {
154
+ /** Duplet: 2 in the time of 3 */
155
+ Duplet: { parts: 2, inTimeOf: 3 },
156
+ /** Triplet: 3 in the time of 2 */
157
+ Triplet: { parts: 3, inTimeOf: 2 },
158
+ /** Quadruplet: 4 in the time of 3 */
159
+ Quadruplet: { parts: 4, inTimeOf: 3 }
160
+ };
161
+ var _RhythmProps = class _RhythmProps {
162
+ constructor(noteLength, dotCount, tupletRatio) {
163
+ /** Note length. */
164
+ __publicField(this, "noteLength");
165
+ /** Note size (whole=1, half=2, quarter=4, ...). */
166
+ __publicField(this, "noteSize");
167
+ /** Dot count. */
168
+ __publicField(this, "dotCount");
169
+ /** Tuplet ratio. */
170
+ __publicField(this, "tupletRatio");
171
+ /** Number of ticks. */
172
+ __publicField(this, "ticks");
173
+ /** Flag count. */
174
+ __publicField(this, "flagCount");
175
+ /** Has note stem. */
176
+ __publicField(this, "hasStem");
177
+ /** Is note head solid (black)? */
178
+ __publicField(this, "isSolidNoteHead");
179
+ this.noteLength = validateNoteLength(noteLength);
180
+ let p = NoteLengthProps.get(noteLength);
181
+ this.noteSize = p.noteSize;
182
+ this.ticks = p.ticks;
183
+ this.flagCount = p.flagCount;
184
+ this.dotCount = dotCount != null ? dotCount : p.dotCount;
185
+ this.hasStem = p.hasStem;
186
+ this.isSolidNoteHead = p.isSolid;
187
+ if (Utils.Is.isObject(tupletRatio)) {
188
+ this.tupletRatio = validateTupletRatio(tupletRatio);
189
+ } else if (p.isTriplet) {
190
+ this.tupletRatio = Tuplet.Triplet;
191
+ } else {
192
+ this.tupletRatio = void 0;
193
+ }
194
+ if (this.dotCount > 0 && this.tupletRatio !== void 0) {
195
+ throw new MusicError(MusicErrorType.Note, `Note cannot be both dotted and tuplet!`);
196
+ } else if (this.dotCount > p.maxDotCount) {
197
+ throw new MusicError(MusicErrorType.Note, `Too big dot count ${this.dotCount} for note length ${this.noteLength}.`);
198
+ }
199
+ for (let add = this.ticks / 2, i = 1; i <= this.dotCount; i++, add /= 2) {
200
+ this.ticks += add;
201
+ }
202
+ if (this.tupletRatio) {
203
+ this.ticks *= this.tupletRatio.inTimeOf / this.tupletRatio.parts;
204
+ }
205
+ }
206
+ /**
207
+ * Get string presentation of rhythm props.
208
+ * @returns - String presentation.
209
+ */
210
+ toString() {
211
+ let sym = _RhythmProps.NoteSymbolMap.get(this.noteSize);
212
+ let dots = ".".repeat(this.dotCount);
213
+ return sym ? sym + dots : "" + this.noteSize + (dots.length > 0 ? dots : "n");
214
+ }
215
+ /**
216
+ * Get rhythm props with given arguments.
217
+ * @param noteLength - Note length.
218
+ * @param dotCount - Dot count.
219
+ * @param tupletRatio - Tuplet ratio.
220
+ * @returns - Rhythm props.
221
+ */
222
+ static get(noteLength, dotCount, tupletRatio) {
223
+ if (dotCount !== void 0 || tupletRatio !== void 0) {
224
+ return new _RhythmProps(noteLength, dotCount, tupletRatio);
225
+ } else {
226
+ let rhythmProps = this.cache.get(noteLength);
227
+ if (!rhythmProps) {
228
+ this.cache.set(noteLength, rhythmProps = new _RhythmProps(noteLength));
229
+ }
230
+ return rhythmProps;
231
+ }
232
+ }
233
+ /**
234
+ * Compare duration of rhythm props.
235
+ * @param a - RhythmProps
236
+ * @param b - RhythmProps
237
+ * @returns - -1: a < b, 0: a === b, +1: a > b (duration comparisons)
238
+ */
239
+ static cmp(a, b) {
240
+ return cmp(a.ticks, b.ticks);
241
+ }
242
+ /**
243
+ * Compare duration equality of rhythm props.
244
+ * @param a - RhythmProps
245
+ * @param b - RhythmProps
246
+ * @returns - true: a === b, false: a !== b (duration comparisons)
247
+ */
248
+ static equals(a, b) {
249
+ return a.ticks === b.ticks;
250
+ }
251
+ };
252
+ __publicField(_RhythmProps, "NoteSymbolMap", /* @__PURE__ */ new Map([[1, "\u{1D15D}"], [2, "\u{1D15E}"], [4, "\u{1D15F}"], [8, "\u{1D160}"], [16, "\u{1D161}"], [32, "\u{1D162}"], [64, "\u{1D163}"], [128, "\u{1D164}"]]));
253
+ __publicField(_RhythmProps, "cache", /* @__PURE__ */ new Map());
254
+ var RhythmProps = _RhythmProps;
255
+
256
+ export {
257
+ NoteLength,
258
+ validateNoteLength,
259
+ NoteLengthProps,
260
+ validateTupletRatio,
261
+ Tuplet,
262
+ RhythmProps
263
+ };
264
+ //# sourceMappingURL=chunk-7MNV5JN6.mjs.map
@@ -1,4 +1,4 @@
1
- /* WebMusicScore v4.0.1 | (c) 2023 PahkaSoft | MIT License | Includes: Tone.js (MIT License) */
1
+ /* WebMusicScore v4.2.0 | (c) 2023 PahkaSoft | MIT License | Includes: Tone.js (MIT License) */
2
2
  "use strict";
3
3
  var __defProp = Object.defineProperty;
4
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -62,7 +62,7 @@ function init() {
62
62
  return;
63
63
  }
64
64
  initialized = true;
65
- console.log("%cWebMusicScore v4.0.1 (cjs) initialized.", "background: black; color: white; padding: 2px;");
65
+ console.log("%cWebMusicScore v4.2.0 (cjs) initialized.", "background: black; color: white; padding: 2px;");
66
66
  }
67
67
  // Annotate the CommonJS export names for ESM import in node:
68
68
  0 && (module.exports = {
@@ -1,7 +1,7 @@
1
- /* WebMusicScore v4.0.1 | (c) 2023 PahkaSoft | MIT License | Includes: Tone.js (MIT License) */
1
+ /* WebMusicScore v4.2.0 | (c) 2023 PahkaSoft | MIT License | Includes: Tone.js (MIT License) */
2
2
  import {
3
3
  __publicField
4
- } from "../chunk-YFPLOHP2.mjs";
4
+ } from "../chunk-5NWLGWHS.mjs";
5
5
 
6
6
  // src/core/error.ts
7
7
  var MusicErrorType = /* @__PURE__ */ ((MusicErrorType2) => {
@@ -36,7 +36,7 @@ function init() {
36
36
  return;
37
37
  }
38
38
  initialized = true;
39
- console.log("%cWebMusicScore v4.0.1 (esm) initialized.", "background: black; color: white; padding: 2px;");
39
+ console.log("%cWebMusicScore v4.2.0 (esm) initialized.", "background: black; color: white; padding: 2px;");
40
40
  }
41
41
  export {
42
42
  MusicError,