@tspro/web-music-score 5.0.0 → 5.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 (43) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/README.md +16 -13
  3. package/dist/audio/index.d.mts +15 -2
  4. package/dist/audio/index.d.ts +16 -3
  5. package/dist/audio/index.js +37 -78
  6. package/dist/audio/index.mjs +34 -68
  7. package/dist/audio-cg/index.d.mts +6 -1
  8. package/dist/audio-cg/index.d.ts +6 -1
  9. package/dist/audio-cg/index.js +1 -1
  10. package/dist/audio-cg/index.mjs +3 -3
  11. package/dist/audio-synth/index.d.mts +15 -0
  12. package/dist/audio-synth/index.d.ts +15 -0
  13. package/dist/audio-synth/index.js +95 -0
  14. package/dist/audio-synth/index.mjs +58 -0
  15. package/dist/{chunk-AAL3CMRO.mjs → chunk-6S5BDSCM.mjs} +2 -2
  16. package/dist/{chunk-J3KU3U4W.mjs → chunk-LC5JMIVF.mjs} +2 -2
  17. package/dist/{chunk-EYFT3RWB.mjs → chunk-XUGM7SCC.mjs} +5 -6
  18. package/dist/core/index.js +2 -2
  19. package/dist/core/index.mjs +3 -3
  20. package/dist/{guitar-CaZJDA05.d.ts → guitar-BsSayRsH.d.ts} +1 -1
  21. package/dist/iife/audio-cg.global.js +9 -2
  22. package/dist/iife/index.global.js +11 -11
  23. package/dist/{music-objects-3Hxlkxy6.d.mts → music-objects-CB05XryE.d.mts} +121 -45
  24. package/dist/{music-objects-CI7IjsjE.d.ts → music-objects-CwPOlqFi.d.ts} +123 -47
  25. package/dist/{note-eA2xPPiG.d.ts → note-CgCIBwvR.d.ts} +1 -1
  26. package/dist/pieces/index.d.mts +1 -1
  27. package/dist/pieces/index.d.ts +3 -3
  28. package/dist/pieces/index.js +1 -1
  29. package/dist/pieces/index.mjs +2 -2
  30. package/dist/react-ui/index.d.mts +34 -15
  31. package/dist/react-ui/index.d.ts +38 -19
  32. package/dist/react-ui/index.js +41 -32
  33. package/dist/react-ui/index.mjs +42 -33
  34. package/dist/{scale-DGx3tJH4.d.ts → scale-CBW4eTz7.d.ts} +2 -2
  35. package/dist/score/index.d.mts +2 -2
  36. package/dist/score/index.d.ts +5 -5
  37. package/dist/score/index.js +1951 -1514
  38. package/dist/score/index.mjs +1664 -1226
  39. package/dist/{tempo-GrstpD9G.d.ts → tempo-DMt3iwz9.d.ts} +1 -1
  40. package/dist/theory/index.d.ts +6 -6
  41. package/dist/theory/index.js +3 -4
  42. package/dist/theory/index.mjs +3 -3
  43. package/package.json +12 -2
@@ -1,4 +1,4 @@
1
- /* WebMusicScore v5.0.0 | (c) 2023 PahkaSoft | MIT License | Includes: Tone.js (MIT License) */
1
+ /* WebMusicScore v5.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;
@@ -65,15 +65,17 @@ __export(score_exports, {
65
65
  MRest: () => MRest,
66
66
  MRhythmColumn: () => MRhythmColumn,
67
67
  MScoreRow: () => MScoreRow,
68
- MSignature: () => MSignature,
69
68
  MSpecialText: () => MSpecialText,
70
69
  MStaff: () => MStaff,
71
70
  MStaffBeamGroup: () => MStaffBeamGroup,
72
71
  MStaffNoteGroup: () => MStaffNoteGroup,
73
72
  MStaffRest: () => MStaffRest,
73
+ MStaffSignature: () => MStaffSignature,
74
74
  MStaffTabBarLine: () => MStaffTabBarLine,
75
75
  MTab: () => MTab,
76
76
  MTabNoteGroup: () => MTabNoteGroup,
77
+ MTabRhythm: () => MTabRhythm,
78
+ MTabSignature: () => MTabSignature,
77
79
  MText: () => MText,
78
80
  MusicInterface: () => MusicInterface6,
79
81
  Navigation: () => Navigation,
@@ -373,7 +375,7 @@ var DivRect = class _DivRect {
373
375
  };
374
376
 
375
377
  // src/score/pub/document-builder.ts
376
- var import_ts_utils_lib15 = require("@tspro/ts-utils-lib");
378
+ var import_ts_utils_lib16 = require("@tspro/ts-utils-lib");
377
379
 
378
380
  // src/score/pub/types.ts
379
381
  var StaffPreset = /* @__PURE__ */ ((StaffPreset3) => {
@@ -385,10 +387,10 @@ var StaffPreset = /* @__PURE__ */ ((StaffPreset3) => {
385
387
  StaffPreset3["GuitarCombined"] = "guitarCombined";
386
388
  return StaffPreset3;
387
389
  })(StaffPreset || {});
388
- var Clef = /* @__PURE__ */ ((Clef2) => {
389
- Clef2["G"] = "G";
390
- Clef2["F"] = "F";
391
- return Clef2;
390
+ var Clef = /* @__PURE__ */ ((Clef4) => {
391
+ Clef4["G"] = "G";
392
+ Clef4["F"] = "F";
393
+ return Clef4;
392
394
  })(Clef || {});
393
395
  function getVoiceIds() {
394
396
  return [0, 1, 2, 3];
@@ -585,7 +587,7 @@ var import_theory12 = require("@tspro/web-music-score/theory");
585
587
  var import_theory11 = require("@tspro/web-music-score/theory");
586
588
 
587
589
  // src/score/engine/renderer.ts
588
- var import_ts_utils_lib2 = require("@tspro/ts-utils-lib");
590
+ var import_ts_utils_lib3 = require("@tspro/ts-utils-lib");
589
591
 
590
592
  // src/score/engine/settings.ts
591
593
  var DebugSettings = {
@@ -617,7 +619,7 @@ var DocumentSettings = {
617
619
  };
618
620
 
619
621
  // src/score/engine/renderer.ts
620
- var import_core2 = require("@tspro/web-music-score/core");
622
+ var import_core3 = require("@tspro/web-music-score/core");
621
623
 
622
624
  // src/score/engine/assets/treble-clef.png
623
625
  var treble_clef_default = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAACWCAYAAACCe+v6AAADHXpUWHRSYXcgcHJvZmlsZSB0eXBlIGV4aWYAAHja7ZZRcu0mDIbfWUWXgCSExHIwmJnu4C6/Pxg7J2kyTdv7GJhjsJCF0CfZJ5y//hzhDzRK5iGpeS45R7RUUuGKicerHetKMa3ratL2Gr2Xh5L3AkMkU/O6LbzlJ+SY074vexO69W9D94QqZvq2UOuWH+/lxzbI/tHQ9kDo2jn2/cA2JLw9Std92x7l4vbuaH2fGYqXyN9+SYyzZrKEa+JolgvmzjEZ4tmno6NxWYb0CugjuO9vVYZPfApJxFUkXV7K/IlUjBlXrAYokhhuFMK5UFbgI1DCBXha9kY1PsF8jc1bjL5o3zlWxCbjnMov1J7xQ97k/HnePLOdBg81z3tB3mON+Rk/lZPehu4Fefbh1529PTu/k4vE9BqK8Ip7jO5jHRqnqCkjFnkf6j7KmkHvmFFcT2V0izkgax2T2Qu6xxobcqrHhko7MC/EoDsoUadKg841NmpwMfHJhpG5BZYldEAq3GQmQ5qdBpsU6eLImHblkPDjC61ty9qukcceYieoMsEY4ZH/3MN3FceYtUQU/YoT0gJ+8axOeBEJ+OcANTCgsYOqK8B3/9gm18lMV5gdB6zxCJeJQ+ktuWSBFigqxgsyWd8GECJsrXCGBARiJlHK8MiYjQiBdACqcJ0l8QECpModTnISyYCD6sDeeMZoqbLyJcZbVVJAsWYUrYNQBayUFPljyZFDVUWTqmY1dS1as+RZeTlbnq/namLJ1LIZ3tlWrLp4cvXs5u7Fa+EieH1rQZ0WL6XUik0rLFc8XaFQ68GHHOnQIx92+FHCURvSp6WmLTdr3kqrnbt0FHjP3br30utJJ1LpTKee+bTTz3LWgVQbMtLQkYeF4aOM+lCjXbYf+7+gRpsaL1JT0R5qkJrdJmi+TnQyAzFOBOAGaiCGxJ7MolNKPMlNZvgeoSqU4aROOJ0mMRBMJ7EOethtcoHr7+EWzBc3/r/kwkT3TXJ/5/YZtT6/Em0Ru8pwBjUKqg/rp1f2Oj+vX47hnxS+O/4Y+jH0Y+jrcYwROv51hb8AKbCqdGIdCl0AAAGFaUNDUElDQyBwcm9maWxlAAB4nH2RPUjDQBzFX1O1UqoOdhBxyFCd7OAH0rFUsQgWSluhVQeTS7+gSUOS4uIouBYc/FisOrg46+rgKgiCHyCuLk6KLlLi/5JCi1gPjvvx7t7j7h0gNCpMNXuigKpZRioeE7O5VdH3ij74MYgpRCRm6on0YgZdx9c9PHy9C/Os7uf+HANK3mSARySOMt2wiDeI5zYtnfM+cZCVJIX4nHjSoAsSP3JddvmNc9FhgWcGjUxqnjhILBY7WO5gVjJU4lnikKJqlC9kXVY4b3FWKzXWuid/YSCvraS5TnMMcSwhgSREyKihjAoshGnVSDGRov1YF/+o40+SSyZXGYwcC6hCheT4wf/gd7dmYWbaTQrEgN4X2/4YB3y7QLNu29/Htt08AbzPwJXW9lcbQOST9HpbCx0BQ9vAxXVbk/eAyx1g5EmXDMmRvDSFQgF4P6NvygHDt4B/ze2ttY/TByBDXS3fAAeHwESRste7vLu/s7d/z7T6+wEMNXLkxtwRywAADzRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+Cjx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDQuNC4wLUV4aXYyIj4KIDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+CiAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIgogICAgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIKICAgIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIKICAgIHhtbG5zOkdJTVA9Imh0dHA6Ly93d3cuZ2ltcC5vcmcveG1wLyIKICAgIHhtbG5zOnRpZmY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vdGlmZi8xLjAvIgogICAgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIgogICB4bXBNTTpEb2N1bWVudElEPSJnaW1wOmRvY2lkOmdpbXA6NDA3ODVjMzYtNDAxZC00YTZlLTkxODctMDQ1NTI4MmM0ZGY2IgogICB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjhiZTJkYzc1LTVlYjQtNDk0Yy1iNWRlLWQ2MzZkNzZhNjI2YiIKICAgeG1wTU06T3JpZ2luYWxEb2N1bWVudElEPSJ4bXAuZGlkOmU3YWE0MWNhLTNiYjMtNGU5Yi05NDQxLTllNTNmZTJiZjM5ZiIKICAgZGM6Rm9ybWF0PSJpbWFnZS9wbmciCiAgIEdJTVA6QVBJPSIyLjAiCiAgIEdJTVA6UGxhdGZvcm09IldpbmRvd3MiCiAgIEdJTVA6VGltZVN0YW1wPSIxNjg2NDA4NjA5MzE2NDM4IgogICBHSU1QOlZlcnNpb249IjIuMTAuMzQiCiAgIHRpZmY6T3JpZW50YXRpb249IjEiCiAgIHhtcDpDcmVhdG9yVG9vbD0iR0lNUCAyLjEwIgogICB4bXA6TWV0YWRhdGFEYXRlPSIyMDIzOjA2OjEwVDE3OjUwOjA5KzAzOjAwIgogICB4bXA6TW9kaWZ5RGF0ZT0iMjAyMzowNjoxMFQxNzo1MDowOSswMzowMCI+CiAgIDx4bXBNTTpIaXN0b3J5PgogICAgPHJkZjpTZXE+CiAgICAgPHJkZjpsaQogICAgICBzdEV2dDphY3Rpb249InNhdmVkIgogICAgICBzdEV2dDpjaGFuZ2VkPSIvIgogICAgICBzdEV2dDppbnN0YW5jZUlEPSJ4bXAuaWlkOjI3MzY2YmY0LWVkZDMtNDE5OC05NjJhLWU5ZTM5MTBlNThiZSIKICAgICAgc3RFdnQ6c29mdHdhcmVBZ2VudD0iR2ltcCAyLjEwIChXaW5kb3dzKSIKICAgICAgc3RFdnQ6d2hlbj0iMjAyMi0wOC0yMlQwMjo1NTozNiIvPgogICAgIDxyZGY6bGkKICAgICAgc3RFdnQ6YWN0aW9uPSJzYXZlZCIKICAgICAgc3RFdnQ6Y2hhbmdlZD0iLyIKICAgICAgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDo5NjVlMTM3OS0wZDlmLTQ5ODItYWQ3MC05MzhjOWMzOWE0ZjMiCiAgICAgIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkdpbXAgMi4xMCAoV2luZG93cykiCiAgICAgIHN0RXZ0OndoZW49IjIwMjItMDktMTFUMTY6MzU6MDAiLz4KICAgICA8cmRmOmxpCiAgICAgIHN0RXZ0OmFjdGlvbj0ic2F2ZWQiCiAgICAgIHN0RXZ0OmNoYW5nZWQ9Ii8iCiAgICAgIHN0RXZ0Omluc3RhbmNlSUQ9InhtcC5paWQ6MTBmYmEwYTMtOTI5Yi00NTRlLThjNGMtOGVkOGM4YWJhZGRjIgogICAgICBzdEV2dDpzb2Z0d2FyZUFnZW50PSJHaW1wIDIuMTAgKFdpbmRvd3MpIgogICAgICBzdEV2dDp3aGVuPSIyMDIzLTA2LTEwVDE3OjUwOjA5Ii8+CiAgICA8L3JkZjpTZXE+CiAgIDwveG1wTU06SGlzdG9yeT4KICA8L3JkZjpEZXNjcmlwdGlvbj4KIDwvcmRmOlJERj4KPC94OnhtcG1ldGE+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAKPD94cGFja2V0IGVuZD0idyI/Ppn4NIQAAAAGYktHRAD/AP8A/6C9p5MAAAAJcEhZcwAALiMAAC4jAXilP3YAAAAHdElNRQfnBgoOMgm5WlWBAAAAGXRFWHRDb21tZW50AENyZWF0ZWQgd2l0aCBHSU1QV4EOFwAACHtJREFUeNrtnXuQVmMcxz+77cauTWUpbGSVu2w3BpnUEBq3chkmBjGayG1GBuNWLtUgw5SJkBkjl4QKg1wyQyarK0lRSlstU20bWam9+OM8O3P6vc8553nOe97tnO18Z84f57zP7XvOc/ndnueFfQx5e6neUmAI0B3oDPwD/AJ8Dvzcml5we+Al4D+gyeOaB1S0BrLHAut9iLqvf4ERSSZbBmwwJOu+RieV8JwQZJuARjXWE4WBIck2X38AByaJ8MwsCTcBTyWFbCFQFwHhv4DiKBqUn2PCPYEin9+bgI3AUuBPn3TtgMuT8IWv8vlq7wLdRPrTgPke6d9JAuFbPBo/3UfKK1TCh8yzIQmEb/cYjx0C8pUDuzV5D477GN6mefY+UBuQby0wV/O8U9wJr9E8W2iY92vNs45xJ6zTfKoN827UPNsdd8K1SlJyo8Awb7XhEIkVYYAVmjXVBPtr1uyqJBBeLu5LDPMdppkPdiaRcHvDfKeJ+++SIFoCLBP3R1toWW58lhQFogiodwkPlYZf1y1w/AcclCQVcYWQtILwqiA8M2lGgDcFgSN90nbXiJUXRdWQ/BYiLMdxH5+0k8VavRb4JGmEl4j7vh7pRgDni2fj1RyQKBwiuqjui/Un015dBbQloXCbaTdrZuUajTp4IwnGbEHmKPX8QmCHhuwC9p4rKBI8IghdB0zCsT1Lsg0+4zwxuEiQqqcVmGWDlAETk+zSJE9Ublyjuqof2TrgxKQT7anMNSZfd1iSiZYCUwy+avP1dJLJXglsxdyV8hHQJolEDwBewc5v9J3Klzj0xYnTsCG7W4mdicMdwC7CeQaPTBLRAjUxZeMKvSwpZPcDPghBUGpE45JAthjH92NLdiUwSDz7NO5k24YkuwTHGZYvtKMtcSabD7wVguy37OkilU7v8rgSfjoE2c816+wkkebKOJK9NgTZ2Wpykxgu0k2IG9lTcMIBbchOx9tTWKHpBbFBoZpwbMi+iL9FtEC8wG1xIvyQJdlJhuVWinzd4kD2cJxYZlOyky3KfkHkvSoOhF+2IPu8Zdk3x82O1QV96JDumhJSu5KB4XsVEwzJziCcy2Z/8UK3K5G1PZnhDi2iBW02IDvPY501xY8BuvJ6JcY+AQzAPCDGGucZkF2GefiCxFk4AWoN2K0AG4HHiSBATWJqQMXr1Qxui3Jlv8o2nHiHIl4UFeF1+G/ACOMGuZVoYqfd12qgX7ZkuwZUMjyEoWBaxETd1y5gVDaEr/YpfGqIyW9ODsm6r7FhCY/z6T625tTpLUS2+bo3DOHZHoVdYFnOqBYmG3rbz1JNQbZ2p2MsZfAor604G8OMsUVTyEBLwjMsv4r7vkapl28AH+PEWNqu1++ZNjRPk3mFJdnjDBu4HBipVoUGsewVaGb6fjgRPSsMSQ8wNb/KjA9bEp5osIzcLUitEml6BNQxxGPoWVtROmoynmFJ+CefRvytxFaJt0W6GwwtqE8GkA56cZSSGVxiI74FhTUM9ch3f0irCerleNU3wbZL2xrJzwhp+hks0s6PaBitMsnsXk7WWlY8xKPi7fjvOZI94x/sHOQFPobGw+U4kHBvrrDVRrw2RE4L6C3V7Ln3sBg43qLeeuAxj996BxHeJCYxm2i4Gh8RMwjL/BpqgA/VpKgTgnwJuzdXtbWUWpZpntUCiwwlPDf6WBLeBSzWPO8URFjuHOthUWm1ptJFaizZErb9wvJjNaMkiLDck2CrYD8n7k13hUrCvUIYB3Vdui6I8FI1qzbjUstKXwe+EV3aBKtE40pwjsKwwQEeuoEv4d3ALNf9ycCpFpU24ngRVrvkYNN8y7Ps1rqlb3MQYXCc3m7YytOb1FCYa2lhzHbiqjAoU4s2GoG+D+Fg85VGijq/ssh7qEboqLGZB6QDvBLHdZpLnK6R0EzlgNs0hGfZVJ6v1lV3ARNzTLhYo0sfY5h3sYWy4ole7Blh16ismrnEStFok/ou05BdR8iA1QfJDN2/PoeEZZTQkwZL0RoN4bvCNiCPzONlGpVJNBe7Tu4TdX1h2bbmmLCCbMfWAvTew6iDQy/QzLReZJ/RtKk+pFiagXZqmdCdyzGG8J5Eic6aOuSe4yK8A+RGRfn2/SqqwdmbVBZBPX/gHbh2MfAbEbtbTAQEr7itehyX6DDCn6zyCZlhUHcoTc7Ltj2WHKNcLexBRvaFaqxdr0Q/k2OixmNudN9uo+BEMcsOAB4AzrXIU6vUxlrVU3YqJaMEOELZoUzW0PeBezz04JyjN07o0mZy7zD7EjiTmKAQOAfHJlyJ/xmWtsHlo1UPCI28FnoBJym9urtaYspwdrOUKkmprerC/6pl7lel/HdxlTORBB/7aIJnLSQuK40orlisUWRaNXpoxnHX1ky4DZlhTkNbc5duwAlNjLRb58f8Ky/e1wgv2dcmrr6aiSur3agFOWxsL6XM91a6crUSCWfi+H9NoDtEsIKY7YI52sNQ4D5uZpBFeTKMamScyJqeFL4L8yOjfhB5x8Rp0ppoaPEoBF4j86A/HerEfUlcCB8GXGGRvqPSZYPQIeAF7DXC/bE3fJsY2eWsvCEuhMtC9oouAROgPPxveVwIN4TM53f08tnifgfmh/nmnPC6kPk2+fx2k7ifpWb4WKAT9mG+foFvMqqvkRj+pYntFp0HPMrZj8wg1VieEd8Tc6NdFXr3TCFOgLc77TZifE7AaAOyv+MY9iS64pxBK7vyJXHWcLy8eu4T0dybo9vhBMBMJvMwwEbgzqSodnfhvxOtDieQzOv3ncRkE7UNytV4tJ295+LsnUgsugKPAt/jvQm7DmcX2+Bcj7eWRjFwAo4rtYOa1avUMrSTFClSpEiRIkWKFClSpEiRIkWKFClSpEiRIkWKFClSpEiRIgL8D6ed2EKeJMaTAAAAAElFTkSuQmCC";
@@ -625,6 +627,255 @@ var treble_clef_default = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAC
625
627
  // src/score/engine/assets/bass-clef.png
626
628
  var bass_clef_default = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAABGCAYAAACQRffVAAADInpUWHRSYXcgcHJvZmlsZSB0eXBlIGV4aWYAAHja7VdbktwgDPznFDkCkgCJ4/AwVblBjp8GY+/OZFPZPD7yMVADWIiWUEt2jTu+fR3uCxplTi5EtZRT8mghh8wFC/Nnq2skH9a4mrS9R49yF9LeYIhkap6Pmbf8gBxr2s95G6FL/wK6FlSwim8bpWx5fZTXDcj2DLQ3hE7Lvu8DG0h4exTO57Y9Stn04Wp93xmKp8jefkGUU0ykAWNgr5oy1sY+KOLZp6PcznP31S7B9XypMnziQ0g8RpFweinzJ1IwJ4wk4qA4hUXiGlmWGTiUEG4Fbj6BR/F3MN/H5i1GP2mfuZaHkXFM5XdXu+envOn147y5VzsN3JU3lvaGPNLq0z1/KKd4AV0bctvh95at3ZYf5ENWdt3Nvad7jG5jXRq3KCEhFmlf6rrKWkGvziiuUwldfXLANSxmz+jmi2/Iqe4bKq1inYnB/aBAnQoNOtbcqMHFwAcrZubmWJbQQFLmhlQgCbPTYJUsXQwp0c4cEr59oWU2L3ONzHfnO0GVCWCEI3/c3WcVx5i1ROTtjBM8g188qxNeeAL9c4IaGKGxgxpXgK/+3CavAgbjCrPhgsVXd0LUSG/JJYvoSW/EfFY9ad8ACBFMRzhDAgZ8IomU4JEyKxECaSCowHWWwBUMUIzc4SQHkQRyUB2wjTNKS5Ujn2K8VSU4FGsSBTdZCsgKISJ/NBhyqESJIcaYokaLOZYkaVZeSprm67moaNCoSVXNadZiYsGiJVMzy1YyZ8HrO2bUabaccykwWoBccLpAoZTKVWqosaaq1Wp2tTSkTwstttS0WcutdO7SUeA9de3Wcy8HHUilIxzxSIceduSjDKTakBFGHGmoGzbyKDdrtMv2uf8Ga7RZ48XUVNSbNUhVLwiar5M4OQNjHAiEK1gDY0jsyZk3CoEnc5MzfI9QFZHhZJzkdJqMgcFwEMdBN3ebOcfl3/Dm1BZv/LfMuUndJ5n7kbePWOvzK9EWY2cZzqB6QfVh/7DCVubn9aez+5XCZ+cX0AvoBfQCegG9gP57oIEPJ/4Bue+bLIaQwqExNwAAAYVpQ0NQSUNDIHByb2ZpbGUAAHicfZE9SMNAHMVfU7UiFQeLijhkqE4WREUcSxWLYKG0FVp1MLn0Q2jSkKS4OAquBQc/FqsOLs66OrgKguAHiKuLk6KLlPi/pNAixoPjfry797h7Bwj1MlPNjiigapaRisfEbG5FDLyiC0EMYgIDEjP1RHohA8/xdQ8fX+8iPMv73J+jV8mbDPCJxFGmGxbxOvHMpqVz3icOsZKkEJ8Tjxt0QeJHrssuv3EuOizwzJCRSc0Rh4jFYhvLbcxKhko8TRxWVI3yhazLCuctzmq5ypr35C8M5rXlNNdpjiCORSSQhAgZVWygDAsRWjVSTKRoP+bhH3b8SXLJ5NoAI8c8KlAhOX7wP/jdrVmYmnSTgjGg88W2P0aBwC7QqNn297FtN04A/zNwpbX8lTow+0l6raWFj4C+beDiuqXJe8DlDjD0pEuG5Eh+mkKhALyf0TflgP5boGfV7a25j9MHIENdLd0AB4fAWJGy1zze3d3e279nmv39ANCccsygwwDVAAAQE2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNC40LjAtRXhpdjIiPgogPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iCiAgICB4bWxuczpzdEV2dD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlRXZlbnQjIgogICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICAgeG1sbnM6R0lNUD0iaHR0cDovL3d3dy5naW1wLm9yZy94bXAvIgogICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iCiAgICB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iCiAgIHhtcE1NOkRvY3VtZW50SUQ9ImdpbXA6ZG9jaWQ6Z2ltcDo0MDc4NWMzNi00MDFkLTRhNmUtOTE4Ny0wNDU1MjgyYzRkZjYiCiAgIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6Nzg3YjYxN2YtMjg1MS00YzhlLTg2MTYtZWM3NGMwYzYwMWVlIgogICB4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ9InhtcC5kaWQ6ZTdhYTQxY2EtM2JiMy00ZTliLTk0NDEtOWU1M2ZlMmJmMzlmIgogICBkYzpGb3JtYXQ9ImltYWdlL3BuZyIKICAgR0lNUDpBUEk9IjIuMCIKICAgR0lNUDpQbGF0Zm9ybT0iV2luZG93cyIKICAgR0lNUDpUaW1lU3RhbXA9IjE2ODY2MTM5NDcxOTU2ODAiCiAgIEdJTVA6VmVyc2lvbj0iMi4xMC4zNCIKICAgdGlmZjpPcmllbnRhdGlvbj0iMSIKICAgeG1wOkNyZWF0b3JUb29sPSJHSU1QIDIuMTAiCiAgIHhtcDpNZXRhZGF0YURhdGU9IjIwMjM6MDY6MTNUMDI6NTI6MjUrMDM6MDAiCiAgIHhtcDpNb2RpZnlEYXRlPSIyMDIzOjA2OjEzVDAyOjUyOjI1KzAzOjAwIj4KICAgPHhtcE1NOkhpc3Rvcnk+CiAgICA8cmRmOlNlcT4KICAgICA8cmRmOmxpCiAgICAgIHN0RXZ0OmFjdGlvbj0ic2F2ZWQiCiAgICAgIHN0RXZ0OmNoYW5nZWQ9Ii8iCiAgICAgIHN0RXZ0Omluc3RhbmNlSUQ9InhtcC5paWQ6MjczNjZiZjQtZWRkMy00MTk4LTk2MmEtZTllMzkxMGU1OGJlIgogICAgICBzdEV2dDpzb2Z0d2FyZUFnZW50PSJHaW1wIDIuMTAgKFdpbmRvd3MpIgogICAgICBzdEV2dDp3aGVuPSIyMDIyLTA4LTIyVDAyOjU1OjM2Ii8+CiAgICAgPHJkZjpsaQogICAgICBzdEV2dDphY3Rpb249InNhdmVkIgogICAgICBzdEV2dDpjaGFuZ2VkPSIvIgogICAgICBzdEV2dDppbnN0YW5jZUlEPSJ4bXAuaWlkOjk2NWUxMzc5LTBkOWYtNDk4Mi1hZDcwLTkzOGM5YzM5YTRmMyIKICAgICAgc3RFdnQ6c29mdHdhcmVBZ2VudD0iR2ltcCAyLjEwIChXaW5kb3dzKSIKICAgICAgc3RFdnQ6d2hlbj0iMjAyMi0wOS0xMVQxNjozNTowMCIvPgogICAgIDxyZGY6bGkKICAgICAgc3RFdnQ6YWN0aW9uPSJzYXZlZCIKICAgICAgc3RFdnQ6Y2hhbmdlZD0iLyIKICAgICAgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDoxMGZiYTBhMy05MjliLTQ1NGUtOGM0Yy04ZWQ4YzhhYmFkZGMiCiAgICAgIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkdpbXAgMi4xMCAoV2luZG93cykiCiAgICAgIHN0RXZ0OndoZW49IjIwMjMtMDYtMTBUMTc6NTA6MDkiLz4KICAgICA8cmRmOmxpCiAgICAgIHN0RXZ0OmFjdGlvbj0ic2F2ZWQiCiAgICAgIHN0RXZ0OmNoYW5nZWQ9Ii8iCiAgICAgIHN0RXZ0Omluc3RhbmNlSUQ9InhtcC5paWQ6MDBmYjM4YTMtZjZiMi00NjQ1LTliMTYtMjlhNWE0ODZlMjhhIgogICAgICBzdEV2dDpzb2Z0d2FyZUFnZW50PSJHaW1wIDIuMTAgKFdpbmRvd3MpIgogICAgICBzdEV2dDp3aGVuPSIyMDIzLTA2LTEzVDAyOjUyOjI3Ii8+CiAgICA8L3JkZjpTZXE+CiAgIDwveG1wTU06SGlzdG9yeT4KICA8L3JkZjpEZXNjcmlwdGlvbj4KIDwvcmRmOlJERj4KPC94OnhtcG1ldGE+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAKPD94cGFja2V0IGVuZD0idyI/PsIRrtIAAAAGYktHRAD/AP8A/6C9p5MAAAAJcEhZcwAALiMAAC4jAXilP3YAAAAHdElNRQfnBgwXNBsqJURsAAAAGXRFWHRDb21tZW50AENyZWF0ZWQgd2l0aCBHSU1QV4EOFwAABF9JREFUeNrtmluIF1Ucxz9/E8P1VnnJ9dJWC4Frmq2JJmqolGEILoQvK2gZeXlRCSm1Fx9UEsJQERWsXhRftECs0Gq70EK9ZHlbFyHbds3VVXFX91+7664P81tYhpnfmft//st84TzMzDm/8/vOnPO7nYEMGTJkyJAhQ4YMGSJBLkJZw4FyYAIwDHgU+A9oAxqBv4C7xfyySoBlwKfAFaAb6DG0euAzoAoYXCxEnwH2A60eCGrtFrALGJNWokNEwY6QRO2tFXgPGJAmss8DlyImam/fASPTQHaeGJueBFod8FQhrfSLwM+ynDX8L1/oV+BP4LZY58eBUUAlMB94ycPSvQTMERmJ4jGgwYPh2Qg84VFmGbAP6DTI/aoQS/lzg1JfA2MDyn4ZuGaQvyZJspUGv3oKGBhyjmeBJmWOmxLMJIITiiIXIgwaZgFdylxbDeNHANXAZmAVUBpEiScNe2xRxC/3Y2WuRmUlLRHD1rd/HljvV4F3FAVqYlhNo4B7Pl/wdPEMbmOq/ShwRBH0Vkxb6LAy536fW64HuOpn8vOKoLKYCC9Q5rzs0L/JQxDjyYPkgHYXAW0xGslByrLuFuPUFw0eCI92mmiAQ4LgZoEbYyTcAZxVPsJk271ag7x6cWueCLvhfsyu8LzybKLtersUF9ywxe2BnXBnAZOUJuXZeNv1OSki3LLdzwPrgONuguw+7g7wAHjEoW+vEagAXgeelr1yUSZoCUn4hvJsqMO9byRaWyLGtFkiwOtBJnYzBKcVg/ZuSMIrlHl3RrWMnFK1OqX/q8oXOAisDqFLVxL7xonw9yHk7Q5RoxpuyLdjI3wmhLzBwMqAY0ck4SGcCNeKIQqKOTF84RtxEu4BPgohc2QM467HSRjgqBL5mBDUPU1Rnl1JwqBNUuJqrW0M+OLdYuk8Cdas38Rf4b3FR0HP/nLdZNYaioKbxSVuA6ZGQfoNvNWlO6VvEKxW5O5yGbNc4ml7ZrUtCtLjgGMSdjop9Q+wMIT8GoXwKw79ZxrKUG9r+a8flMoyr5AA4ybwo1QgggYHpZJ6Ou3Ta5IpddvufwEsVWQ2xFisCI1Nypf6RMmsIql4JI0S8bFuSs9UvmCgikeh8b6i8C/KuKOYD+VShzGSwLsprRnByYYYoSqNhE8qCv/kYfxrYjT7jmuPIC+PBWsVsl1YRzBeE45qqWGtwjo1SR0WoZ8a7KAfYa5h7/2OVaPuF1gqtS83srclpi565IAP0c+b7wOz+wPZckOc3Jt0LC52oiXABx7y6VasGnfRYgiwwRAu9raGqPLXQmAGcADvvyN+m9bgXnP4i4E9wN8+KiJ5WQG5QilumnioJP9lwHPANKw/fF7A+fxJw2ms/y9SFdiPBf4Vn9hJNL8T/iFxbyoxgej+m6zBOtnLpXlvhiXcDOyVJV8UCEL4KnBI/OnAtBP0q+ADMTq/SfshrdUFr4TzwJdY9d57WIdYzRIk1GMdeXSQIUOGDBmSwUMtd8u2ArdcUAAAAABJRU5ErkJggg==";
627
629
 
630
+ // src/theory/rhythm.ts
631
+ var import_ts_utils_lib2 = require("@tspro/ts-utils-lib");
632
+ var import_core2 = require("@tspro/web-music-score/core");
633
+ var MaxTupletRatioValue = 12;
634
+ var TicksMultiplier = 12 * 11 * 9 * 7 * 5;
635
+ var NoteLength = /* @__PURE__ */ ((NoteLength10) => {
636
+ NoteLength10["Whole"] = "1n";
637
+ NoteLength10["WholeTriplet"] = "1t";
638
+ NoteLength10["WholeDot"] = "1.";
639
+ NoteLength10["Whole2Dots"] = "1..";
640
+ NoteLength10["Whole12Dots"] = "1..";
641
+ NoteLength10["Whole3Dots"] = "1...";
642
+ NoteLength10["Whole4Dots"] = "1....";
643
+ NoteLength10["Whole5Dots"] = "1.....";
644
+ NoteLength10["Whole6Dots"] = "1......";
645
+ NoteLength10["Half"] = "2n";
646
+ NoteLength10["HalfTriplet"] = "2t";
647
+ NoteLength10["HalfDot"] = "2.";
648
+ NoteLength10["Half2Dots"] = "2..";
649
+ NoteLength10["Half3Dots"] = "2...";
650
+ NoteLength10["Half4Dots"] = "2....";
651
+ NoteLength10["Half5Dots"] = "2.....";
652
+ NoteLength10["Quarter"] = "4n";
653
+ NoteLength10["QuarterTriplet"] = "4t";
654
+ NoteLength10["QuarterDot"] = "4.";
655
+ NoteLength10["Quarter2Dots"] = "4..";
656
+ NoteLength10["Quarter3Dots"] = "4...";
657
+ NoteLength10["Quarter4Dots"] = "4....";
658
+ NoteLength10["Eighth"] = "8n";
659
+ NoteLength10["EighthTriplet"] = "8t";
660
+ NoteLength10["EighthDot"] = "8.";
661
+ NoteLength10["Eighth2Dots"] = "8..";
662
+ NoteLength10["Eighth3Dots"] = "8...";
663
+ NoteLength10["Sixteenth"] = "16n";
664
+ NoteLength10["SixteenthTriplet"] = "16t";
665
+ NoteLength10["SixteenthDot"] = "16.";
666
+ NoteLength10["Sixteenth2Dots"] = "16..";
667
+ NoteLength10["ThirtySecond"] = "32n";
668
+ NoteLength10["ThirtySecondTriplet"] = "32t";
669
+ NoteLength10["ThirtySecondDot"] = "32.";
670
+ NoteLength10["SixtyFourth"] = "64n";
671
+ NoteLength10["SixtyFourthTriplet"] = "64t";
672
+ return NoteLength10;
673
+ })(NoteLength || {});
674
+ function validateNoteLength(noteLength) {
675
+ if (import_ts_utils_lib2.Utils.Is.isEnumValue(noteLength, NoteLength)) {
676
+ return noteLength;
677
+ } else {
678
+ throw new import_core2.MusicError(import_core2.MusicErrorType.InvalidArg, `Invalid noteLength: ${noteLength}`);
679
+ }
680
+ }
681
+ var _NoteLengthProps = class _NoteLengthProps {
682
+ constructor(noteLength) {
683
+ /** Note length. */
684
+ __publicField(this, "noteLength");
685
+ /** Note size (whole=1, half=2, quarter=4, ...). */
686
+ __publicField(this, "noteSize");
687
+ /** Number of ticks (not altered by isTriplet). */
688
+ __publicField(this, "ticks");
689
+ /** Flag count. */
690
+ __publicField(this, "flagCount");
691
+ /** Dot count. */
692
+ __publicField(this, "dotCount");
693
+ /** Max dot count. */
694
+ __publicField(this, "maxDotCount");
695
+ /** Is triplet? */
696
+ __publicField(this, "isTriplet");
697
+ /** Has note stem. */
698
+ __publicField(this, "hasStem");
699
+ /** Is note head solid (black)? */
700
+ __publicField(this, "isSolid");
701
+ this.noteLength = validateNoteLength(noteLength);
702
+ this.noteSize = parseInt(noteLength);
703
+ this.isTriplet = noteLength.endsWith("t");
704
+ this.maxDotCount = this.isTriplet ? 0 : Math.floor(Math.log2(_NoteLengthProps.ShortestNoteSize / this.noteSize));
705
+ this.dotCount = import_ts_utils_lib2.Utils.Str.charCount(noteLength, ".");
706
+ this.flagCount = this.noteSize > 4 ? Math.floor(Math.log2(this.noteSize / 4)) : 0;
707
+ this.ticks = TicksMultiplier * _NoteLengthProps.ShortestNoteSize / this.noteSize;
708
+ this.hasStem = this.noteSize > 1;
709
+ this.isSolid = this.noteSize > 2;
710
+ if (this.dotCount > this.maxDotCount) {
711
+ throw new import_core2.MusicError(import_core2.MusicErrorType.Note, `dotCount ${this.dotCount} > maxDotCount ${this.maxDotCount}, for noteLength "${this.noteLength}".`);
712
+ } else if (this.isTriplet && this.dotCount > 0) {
713
+ throw new import_core2.MusicError(import_core2.MusicErrorType.Note, `noteLength "${this.noteLength}" is both triplet and dotted!`);
714
+ }
715
+ }
716
+ /**
717
+ * Get note length props.
718
+ * @param noteLength - Note length.
719
+ * @returns - Note length props.
720
+ */
721
+ static get(noteLength) {
722
+ let p = this.cache.get(noteLength);
723
+ if (!p) {
724
+ this.cache.set(noteLength, p = new _NoteLengthProps(noteLength));
725
+ }
726
+ return p;
727
+ }
728
+ /**
729
+ * Create note length props.
730
+ * @param noteLength - Note length or note size.
731
+ * @param dotCount - Dot count.
732
+ * @returns - Note length props.
733
+ */
734
+ static create(noteLength, dotCount = 0) {
735
+ let noteSize = typeof noteLength === "number" ? noteLength : this.get(noteLength).noteSize;
736
+ return this.get(noteSize + (import_ts_utils_lib2.Utils.Is.isIntegerGte(dotCount, 1) ? ".".repeat(dotCount) : "n"));
737
+ }
738
+ /**
739
+ * Compare note lengths/sizes. Whole (1) > half (2) > quarter (4), etc.
740
+ * Ignores possible triplet property of note length.
741
+ * @param a - NoteLengthProps, NoteLength/Str or noteSize
742
+ * @param b - NoteLengthProps, NoteLength/Str or noteSize
743
+ * @returns - -1: a < b, 0: a === b, +1: a > b (note length/size comparisons)
744
+ */
745
+ static cmp(a, b) {
746
+ let aNoteSize = a instanceof _NoteLengthProps ? a.noteSize : typeof a === "number" ? a : _NoteLengthProps.get(a).noteSize;
747
+ let bNoteSize = b instanceof _NoteLengthProps ? b.noteSize : typeof b === "number" ? b : _NoteLengthProps.get(b).noteSize;
748
+ return import_ts_utils_lib2.Utils.Math.cmp(bNoteSize, aNoteSize);
749
+ }
750
+ /**
751
+ * Compare note lengths/sizes for equality.
752
+ * Ignores possible triplet property of note length.
753
+ * @param a - NoteLengthProps, NoteLength/Str or noteSize
754
+ * @param b - NoteLengthProps, NoteLength/Str or noteSize
755
+ * @returns - true: a === b, false: a !== b (note length/size comparisons)
756
+ */
757
+ static equals(a, b) {
758
+ let aNoteSize = a instanceof _NoteLengthProps ? a.noteSize : typeof a === "number" ? a : _NoteLengthProps.get(a).noteSize;
759
+ let bNoteSize = b instanceof _NoteLengthProps ? b.noteSize : typeof b === "number" ? b : _NoteLengthProps.get(b).noteSize;
760
+ return aNoteSize === bNoteSize;
761
+ }
762
+ };
763
+ /** Longest note size (e.g. 1 = whole note). */
764
+ __publicField(_NoteLengthProps, "LongestNoteSize", Math.min(...import_ts_utils_lib2.Utils.Enum.getEnumValues(NoteLength).map((noteLength) => parseInt(noteLength))));
765
+ /** Shortest note size (e.g. 64 = sixtyfourth note). */
766
+ __publicField(_NoteLengthProps, "ShortestNoteSize", Math.max(...import_ts_utils_lib2.Utils.Enum.getEnumValues(NoteLength).map((noteLength) => parseInt(noteLength))));
767
+ __publicField(_NoteLengthProps, "cache", /* @__PURE__ */ new Map());
768
+ var NoteLengthProps = _NoteLengthProps;
769
+ function validateTupletRatio(tupletRatio) {
770
+ if (import_ts_utils_lib2.Utils.Is.isObject(tupletRatio) && import_ts_utils_lib2.Utils.Is.isIntegerBetween(tupletRatio.parts, 2, MaxTupletRatioValue) && import_ts_utils_lib2.Utils.Is.isIntegerBetween(tupletRatio.inTimeOf, 2, MaxTupletRatioValue)) {
771
+ return tupletRatio;
772
+ } else {
773
+ throw new import_core2.MusicError(import_core2.MusicErrorType.Note, `Invalid tupletRatio ${JSON.stringify(tupletRatio)}`);
774
+ }
775
+ }
776
+ var Tuplet = {
777
+ /** Duplet: 2 in the time of 3 */
778
+ Duplet: { parts: 2, inTimeOf: 3 },
779
+ /** Triplet: 3 in the time of 2 */
780
+ Triplet: { parts: 3, inTimeOf: 2 },
781
+ /** Quadruplet: 4 in the time of 3 */
782
+ Quadruplet: { parts: 4, inTimeOf: 3 }
783
+ };
784
+ var _RhythmProps = class _RhythmProps {
785
+ constructor(noteLength, dotCount, tupletRatio) {
786
+ /** Note length. */
787
+ __publicField(this, "noteLength");
788
+ /** Note size (whole=1, half=2, quarter=4, ...). */
789
+ __publicField(this, "noteSize");
790
+ /** Dot count. */
791
+ __publicField(this, "dotCount");
792
+ /** Tuplet ratio. */
793
+ __publicField(this, "tupletRatio");
794
+ /** Number of ticks. */
795
+ __publicField(this, "ticks");
796
+ /** Flag count. */
797
+ __publicField(this, "flagCount");
798
+ /** Has note stem. */
799
+ __publicField(this, "hasStem");
800
+ /** Is note head solid (black)? */
801
+ __publicField(this, "isSolidNoteHead");
802
+ this.noteLength = validateNoteLength(noteLength);
803
+ let p = NoteLengthProps.get(noteLength);
804
+ this.noteSize = p.noteSize;
805
+ this.ticks = p.ticks;
806
+ this.flagCount = p.flagCount;
807
+ this.dotCount = dotCount != null ? dotCount : p.dotCount;
808
+ this.hasStem = p.hasStem;
809
+ this.isSolidNoteHead = p.isSolid;
810
+ if (import_ts_utils_lib2.Utils.Is.isObject(tupletRatio)) {
811
+ this.tupletRatio = validateTupletRatio(tupletRatio);
812
+ } else if (p.isTriplet) {
813
+ this.tupletRatio = Tuplet.Triplet;
814
+ } else {
815
+ this.tupletRatio = void 0;
816
+ }
817
+ if (this.dotCount > 0 && this.tupletRatio !== void 0) {
818
+ throw new import_core2.MusicError(import_core2.MusicErrorType.Note, `Note cannot be both dotted and tuplet!`);
819
+ } else if (this.dotCount > p.maxDotCount) {
820
+ throw new import_core2.MusicError(import_core2.MusicErrorType.Note, `Too big dot count ${this.dotCount} for note length ${this.noteLength}.`);
821
+ }
822
+ for (let add = this.ticks / 2, i = 1; i <= this.dotCount; i++, add /= 2) {
823
+ this.ticks += add;
824
+ }
825
+ if (this.tupletRatio) {
826
+ this.ticks *= this.tupletRatio.inTimeOf / this.tupletRatio.parts;
827
+ }
828
+ }
829
+ /**
830
+ * Get string presentation of rhythm props.
831
+ * @returns - String presentation.
832
+ */
833
+ toString() {
834
+ let sym = _RhythmProps.NoteSymbolMap.get(this.noteSize);
835
+ let dots = ".".repeat(this.dotCount);
836
+ return sym ? sym + dots : "" + this.noteSize + (dots.length > 0 ? dots : "n");
837
+ }
838
+ /**
839
+ * Get rhythm props with given arguments.
840
+ * @param noteLength - Note length.
841
+ * @param dotCount - Dot count.
842
+ * @param tupletRatio - Tuplet ratio.
843
+ * @returns - Rhythm props.
844
+ */
845
+ static get(noteLength, dotCount, tupletRatio) {
846
+ if (dotCount !== void 0 || tupletRatio !== void 0) {
847
+ return new _RhythmProps(noteLength, dotCount, tupletRatio);
848
+ } else {
849
+ let rhythmProps = this.cache.get(noteLength);
850
+ if (!rhythmProps) {
851
+ this.cache.set(noteLength, rhythmProps = new _RhythmProps(noteLength));
852
+ }
853
+ return rhythmProps;
854
+ }
855
+ }
856
+ /**
857
+ * Compare duration of rhythm props.
858
+ * @param a - RhythmProps
859
+ * @param b - RhythmProps
860
+ * @returns - -1: a < b, 0: a === b, +1: a > b (duration comparisons)
861
+ */
862
+ static cmp(a, b) {
863
+ return import_ts_utils_lib2.Utils.Math.cmp(a.ticks, b.ticks);
864
+ }
865
+ /**
866
+ * Compare duration equality of rhythm props.
867
+ * @param a - RhythmProps
868
+ * @param b - RhythmProps
869
+ * @returns - true: a === b, false: a !== b (duration comparisons)
870
+ */
871
+ static equals(a, b) {
872
+ return a.ticks === b.ticks;
873
+ }
874
+ };
875
+ __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}"]]));
876
+ __publicField(_RhythmProps, "cache", /* @__PURE__ */ new Map());
877
+ var RhythmProps = _RhythmProps;
878
+
628
879
  // src/score/engine/renderer.ts
629
880
  var HilightStaffPosRectColor = "#55cc55";
630
881
  var HilightObjectRectColor = "#55cc55";
@@ -668,7 +919,7 @@ var Renderer = class {
668
919
  __publicField(this, "onMouseLeaveFn");
669
920
  __publicField(this, "onTouchEndFn");
670
921
  this.devicePixelRatio = window.devicePixelRatio;
671
- this.fontSize = import_ts_utils_lib2.Device.FontSize * DocumentSettings.DocumentScale * this.devicePixelRatio;
922
+ this.fontSize = import_ts_utils_lib3.Device.FontSize * DocumentSettings.DocumentScale * this.devicePixelRatio;
672
923
  this.unitSize = this.fontSize * 0.3;
673
924
  this.lineWidth = this.unitSize * 0.2;
674
925
  this.beamThickness = this.unitSize * 0.8;
@@ -682,7 +933,7 @@ var Renderer = class {
682
933
  };
683
934
  img.onerror = () => {
684
935
  this.finishImageAsset(asset);
685
- throw new import_core2.MusicError(import_core2.MusicErrorType.Score, "Failed to load image: " + asset.src);
936
+ throw new import_core3.MusicError(import_core3.MusicErrorType.Score, "Failed to load image: " + asset.src);
686
937
  };
687
938
  }
688
939
  });
@@ -748,7 +999,7 @@ var Renderer = class {
748
999
  return this.scoreEventListener !== void 0;
749
1000
  }
750
1001
  getMousePos(e) {
751
- return new import_ts_utils_lib2.Vec2(e.offsetX, e.offsetY);
1002
+ return new import_ts_utils_lib3.Vec2(e.offsetX, e.offsetY);
752
1003
  }
753
1004
  updateCurStaffPos(staffPos, click) {
754
1005
  let changed = !staffPosEquals(staffPos, this.curStaffPos);
@@ -925,7 +1176,7 @@ var Renderer = class {
925
1176
  ctx.font = savedFont;
926
1177
  return metrics.width;
927
1178
  } else {
928
- return import_ts_utils_lib2.Utils.Dom.getCanvasTextWidth(text, font);
1179
+ return import_ts_utils_lib3.Utils.Dom.getCanvasTextWidth(text, font);
929
1180
  }
930
1181
  }
931
1182
  drawDebugRect(r) {
@@ -997,29 +1248,154 @@ var Renderer = class {
997
1248
  }
998
1249
  }
999
1250
  }
1000
- };
1001
-
1002
- // src/score/engine/obj-staff-and-tab.ts
1003
- var import_core16 = require("@tspro/web-music-score/core");
1004
- var import_ts_utils_lib13 = require("@tspro/ts-utils-lib");
1005
-
1006
- // src/score/engine/obj-measure.ts
1007
- var import_ts_utils_lib12 = require("@tspro/ts-utils-lib");
1008
- var import_theory9 = require("@tspro/web-music-score/theory");
1009
- var import_theory10 = require("@tspro/web-music-score/theory");
1010
-
1011
- // src/score/engine/acc-state.ts
1012
- var import_theory = require("@tspro/web-music-score/theory");
1013
- var AccidentalState = class {
1014
- constructor(measure) {
1015
- this.measure = measure;
1016
- __publicField(this, "accidentalByDiatonicId", []);
1017
- }
1018
- getAccidentalFromKeySignature(diatonicId) {
1019
- let ks = this.measure.getKeySignature();
1020
- let accNote = ks.getOrderedAccidentalNotes().find((accNote2) => accNote2.diatonicClass === import_theory.Note.getDiatonicClass(diatonicId));
1021
- return accNote ? accNote.accidental : void 0;
1022
- }
1251
+ getRestRect(restSize) {
1252
+ let { unitSize } = this;
1253
+ let { flagCount } = NoteLengthProps.get(validateNoteLength(restSize + "n"));
1254
+ let leftw = 0;
1255
+ let rightw = 0;
1256
+ let toph = 0;
1257
+ let bottomh = 0;
1258
+ if (NoteLengthProps.equals(restSize, "1n" /* Whole */)) {
1259
+ leftw = unitSize;
1260
+ rightw = unitSize;
1261
+ toph = 0;
1262
+ bottomh = unitSize;
1263
+ } else if (NoteLengthProps.equals(restSize, "2n" /* Half */)) {
1264
+ leftw = unitSize;
1265
+ rightw = unitSize;
1266
+ toph = unitSize;
1267
+ bottomh = 0;
1268
+ } else if (NoteLengthProps.equals(restSize, "4n" /* Quarter */)) {
1269
+ leftw = unitSize * 1;
1270
+ rightw = unitSize * 1;
1271
+ toph = unitSize * 3.2;
1272
+ bottomh = unitSize * 3;
1273
+ } else {
1274
+ let adj = 1 - flagCount % 2;
1275
+ leftw = unitSize * (1 + flagCount * 0.25);
1276
+ rightw = unitSize * (1 + flagCount * 0.125);
1277
+ toph = unitSize * (0.5 + flagCount - adj);
1278
+ bottomh = unitSize * (1 + flagCount + adj);
1279
+ }
1280
+ return new DivRect(-leftw, 0, rightw, -toph, 0, bottomh);
1281
+ }
1282
+ drawRest(restSize, x, y, color) {
1283
+ let ctx = this.getCanvasContext();
1284
+ if (!ctx) {
1285
+ return;
1286
+ }
1287
+ let { unitSize, lineWidth } = this;
1288
+ let { flagCount } = NoteLengthProps.get(validateNoteLength(restSize + "n"));
1289
+ ctx.strokeStyle = ctx.fillStyle = color;
1290
+ ctx.lineWidth = lineWidth;
1291
+ if (NoteLengthProps.equals(restSize, "1n" /* Whole */)) {
1292
+ ctx.fillRect(x - unitSize, y, unitSize * 2, unitSize);
1293
+ } else if (NoteLengthProps.equals(restSize, "2n" /* Half */)) {
1294
+ ctx.fillRect(x - unitSize, y - unitSize, unitSize * 2, unitSize);
1295
+ } else if (NoteLengthProps.equals(restSize, "4n" /* Quarter */)) {
1296
+ ctx.beginPath();
1297
+ ctx.moveTo(x - unitSize * 0.6, y - unitSize * 3.2);
1298
+ ctx.lineTo(x + unitSize * 0.7, y - unitSize * 1.5);
1299
+ ctx.quadraticCurveTo(
1300
+ x - unitSize * 0.8,
1301
+ y - unitSize * 0.5,
1302
+ x + unitSize * 1,
1303
+ y + unitSize * 1.5
1304
+ );
1305
+ ctx.lineTo(x - unitSize * 1, y - unitSize * 0.75);
1306
+ ctx.quadraticCurveTo(
1307
+ x + unitSize * 0.2,
1308
+ y - unitSize * 1.5,
1309
+ x - unitSize * 0.6,
1310
+ y - unitSize * 3.2
1311
+ );
1312
+ ctx.moveTo(x + unitSize * 1, y + unitSize * 1.5);
1313
+ ctx.quadraticCurveTo(
1314
+ x - unitSize * 0.8,
1315
+ y + unitSize * 1,
1316
+ x - unitSize * 0.2,
1317
+ y + unitSize * 2.8
1318
+ );
1319
+ ctx.bezierCurveTo(
1320
+ x - unitSize * 1.8,
1321
+ y + unitSize * 1.5,
1322
+ x - unitSize * 0.6,
1323
+ y - unitSize * 0.2,
1324
+ x + unitSize * 0.9,
1325
+ y + unitSize * 1.5
1326
+ );
1327
+ ctx.fill();
1328
+ ctx.stroke();
1329
+ } else if (flagCount > 0) {
1330
+ let adj = 1 - flagCount % 2;
1331
+ let fx = (p) => x + (-p * 0.25 + 0.5) * unitSize;
1332
+ let fy = (p) => y + (p + adj) * unitSize;
1333
+ ctx.beginPath();
1334
+ ctx.moveTo(fx(1 + flagCount), fy(1 + flagCount));
1335
+ ctx.lineTo(fx(-0.5 - flagCount), fy(-0.5 - flagCount));
1336
+ ctx.stroke();
1337
+ for (let i = 0; i < flagCount; i++) {
1338
+ let t = flagCount - i * 2;
1339
+ ctx.beginPath();
1340
+ ctx.moveTo(fx(t - 2.5), fy(t - 2.5));
1341
+ ctx.quadraticCurveTo(
1342
+ fx(t - 0.5) + unitSize * 0.25,
1343
+ fy(t - 1.5),
1344
+ fx(t - 1.5) - unitSize * 1.5,
1345
+ fy(t - 1.5)
1346
+ );
1347
+ ctx.stroke();
1348
+ ctx.beginPath();
1349
+ ctx.arc(fx(t - 2) - unitSize * 1.5, fy(t - 2), unitSize * 0.5, 0, Math.PI * 2);
1350
+ ctx.fill();
1351
+ }
1352
+ }
1353
+ }
1354
+ drawFlag(rect, dir) {
1355
+ let ctx = this.getCanvasContext();
1356
+ if (!ctx) {
1357
+ return;
1358
+ }
1359
+ let left = rect.left;
1360
+ let right = rect.right;
1361
+ let width = right - left;
1362
+ let top = dir === "up" ? rect.top : rect.bottom;
1363
+ let bottom = dir === "up" ? rect.bottom : rect.top;
1364
+ ctx.beginPath();
1365
+ ctx.moveTo(left, top);
1366
+ ctx.bezierCurveTo(
1367
+ left,
1368
+ top * 0.75 + bottom * 0.25,
1369
+ left + width * 1.5,
1370
+ top * 0.5 + bottom * 0.5,
1371
+ left + width * 0.5,
1372
+ bottom
1373
+ );
1374
+ ctx.stroke();
1375
+ }
1376
+ };
1377
+
1378
+ // src/score/engine/obj-staff-and-tab.ts
1379
+ var import_core16 = require("@tspro/web-music-score/core");
1380
+ var import_ts_utils_lib14 = require("@tspro/ts-utils-lib");
1381
+
1382
+ // src/score/engine/obj-measure.ts
1383
+ var import_ts_utils_lib13 = require("@tspro/ts-utils-lib");
1384
+ var import_theory9 = require("@tspro/web-music-score/theory");
1385
+ var import_theory10 = require("@tspro/web-music-score/theory");
1386
+
1387
+ // src/score/engine/acc-state.ts
1388
+ var import_theory = require("@tspro/web-music-score/theory");
1389
+ var AccidentalState = class {
1390
+ constructor(measure) {
1391
+ this.measure = measure;
1392
+ __publicField(this, "accidentalByDiatonicId", []);
1393
+ }
1394
+ getAccidentalFromKeySignature(diatonicId) {
1395
+ let ks = this.measure.getKeySignature();
1396
+ let accNote = ks.getOrderedAccidentalNotes().find((accNote2) => accNote2.diatonicClass === import_theory.Note.getDiatonicClass(diatonicId));
1397
+ return accNote ? accNote.accidental : void 0;
1398
+ }
1023
1399
  setAccidental(note) {
1024
1400
  this.accidentalByDiatonicId[note.diatonicId] = note.accidental;
1025
1401
  }
@@ -1079,7 +1455,7 @@ var ObjImage = class extends MusicObject {
1079
1455
  };
1080
1456
 
1081
1457
  // src/score/engine/obj-accidental.ts
1082
- var import_core3 = require("@tspro/web-music-score/core");
1458
+ var import_core4 = require("@tspro/web-music-score/core");
1083
1459
  var ObjAccidental = class extends MusicObject {
1084
1460
  constructor(parent, diatonicId, accidental, color = "black") {
1085
1461
  super(parent);
@@ -1114,7 +1490,7 @@ var ObjAccidental = class extends MusicObject {
1114
1490
  this.rect = DivRect.createSections(unitSize * 1, unitSize * 1, unitSize * 1, unitSize * 1);
1115
1491
  break;
1116
1492
  default:
1117
- throw new import_core3.MusicError(import_core3.MusicErrorType.Score, "Invalid accidental value: " + this.accidental);
1493
+ throw new import_core4.MusicError(import_core4.MusicErrorType.Score, "Invalid accidental value: " + this.accidental);
1118
1494
  }
1119
1495
  }
1120
1496
  offset(dx, dy) {
@@ -1327,8 +1703,8 @@ var ObjText = class extends MusicObject {
1327
1703
  };
1328
1704
 
1329
1705
  // src/score/engine/obj-signature.ts
1330
- var import_core4 = require("@tspro/web-music-score/core");
1331
- var ObjSignature = class extends MusicObject {
1706
+ var import_core5 = require("@tspro/web-music-score/core");
1707
+ var ObjStaffSignature = class extends MusicObject {
1332
1708
  constructor(measure, staff) {
1333
1709
  super(measure);
1334
1710
  this.measure = measure;
@@ -1342,7 +1718,7 @@ var ObjSignature = class extends MusicObject {
1342
1718
  __publicField(this, "beatSizeText");
1343
1719
  __publicField(this, "tempoText");
1344
1720
  __publicField(this, "mi");
1345
- this.mi = new MSignature(this);
1721
+ this.mi = new MStaffSignature(this);
1346
1722
  }
1347
1723
  getMusicInterface() {
1348
1724
  return this.mi;
@@ -1423,7 +1799,7 @@ var ObjSignature = class extends MusicObject {
1423
1799
  if (bottomAccidentalDiatonicId !== void 0) {
1424
1800
  return import_theory2.Note.findNextDiatonicIdAbove(accNote.diatonicId, bottomAccidentalDiatonicId, false);
1425
1801
  } else {
1426
- throw new import_core4.MusicError(import_core4.MusicErrorType.Score, "Cannot get accidental diatonicId because note has no accidental.");
1802
+ throw new import_core5.MusicError(import_core5.MusicErrorType.Score, "Cannot get accidental diatonicId because note has no accidental.");
1427
1803
  }
1428
1804
  }
1429
1805
  pick(x, y) {
@@ -1541,66 +1917,169 @@ var ObjSignature = class extends MusicObject {
1541
1917
  }
1542
1918
  x = right;
1543
1919
  if (this.tempoText) {
1920
+ let tempoBottom = Math.min(
1921
+ this.clefImage ? this.clefImage.getRect().top : staff.getTopLineY(),
1922
+ ...this.ksNeutralizeAccidentals.map((o) => o.getRect().top),
1923
+ ...this.ksNewAccidentals.map((o) => o.getRect().top)
1924
+ );
1544
1925
  this.tempoText.layout(renderer);
1545
- this.tempoText.offset(x, Math.min(this.rect.top, staff.getTopLineY()));
1926
+ this.tempoText.offset(x, tempoBottom);
1546
1927
  this.rect.expandInPlace(this.tempoText.getRect());
1547
1928
  }
1548
1929
  this.rect.right += paddingX;
1549
1930
  }
1550
1931
  offset(dx, dy) {
1551
- if (this.clefImage) {
1552
- this.clefImage.offset(dx, dy);
1932
+ var _a, _b, _c, _d, _e, _f;
1933
+ (_a = this.clefImage) == null ? void 0 : _a.offset(dx, dy);
1934
+ (_b = this.eightBelowClef) == null ? void 0 : _b.offset(dx, dy);
1935
+ (_c = this.measureNumber) == null ? void 0 : _c.offset(dx, dy);
1936
+ this.ksNeutralizeAccidentals.forEach((acc) => acc.offset(dx, dy));
1937
+ this.ksNewAccidentals.forEach((acc) => acc.offset(dx, dy));
1938
+ (_d = this.beatCountText) == null ? void 0 : _d.offset(dx, dy);
1939
+ (_e = this.beatSizeText) == null ? void 0 : _e.offset(dx, dy);
1940
+ (_f = this.tempoText) == null ? void 0 : _f.offset(dx, dy);
1941
+ this.rect.offsetInPlace(dx, dy);
1942
+ }
1943
+ draw(renderer) {
1944
+ var _a, _b, _c, _d, _e, _f;
1945
+ (_a = this.clefImage) == null ? void 0 : _a.draw(renderer);
1946
+ (_b = this.eightBelowClef) == null ? void 0 : _b.draw(renderer);
1947
+ (_c = this.measureNumber) == null ? void 0 : _c.draw(renderer);
1948
+ this.ksNeutralizeAccidentals.forEach((acc) => acc.draw(renderer));
1949
+ this.ksNewAccidentals.forEach((acc) => acc.draw(renderer));
1950
+ (_d = this.beatCountText) == null ? void 0 : _d.draw(renderer);
1951
+ (_e = this.beatSizeText) == null ? void 0 : _e.draw(renderer);
1952
+ (_f = this.tempoText) == null ? void 0 : _f.draw(renderer);
1953
+ }
1954
+ };
1955
+ var ObjTabSignature = class extends MusicObject {
1956
+ constructor(measure, tab) {
1957
+ super(measure);
1958
+ this.measure = measure;
1959
+ this.tab = tab;
1960
+ __publicField(this, "measureNumber");
1961
+ __publicField(this, "beatCountText");
1962
+ __publicField(this, "beatSizeText");
1963
+ __publicField(this, "tempoText");
1964
+ __publicField(this, "mi");
1965
+ this.mi = new MTabSignature(this);
1966
+ }
1967
+ getMusicInterface() {
1968
+ return this.mi;
1969
+ }
1970
+ updateMeasureNumber(showMeasureNumber) {
1971
+ if (showMeasureNumber) {
1972
+ let text = this.measure.getMeasureNumber().toString();
1973
+ this.measureNumber = new ObjText(this, text, 0, 1);
1974
+ } else {
1975
+ this.measureNumber = void 0;
1553
1976
  }
1554
- if (this.eightBelowClef) {
1555
- this.eightBelowClef.offset(dx, dy);
1977
+ }
1978
+ updateTimeSignature(showTimeSignature) {
1979
+ if (showTimeSignature) {
1980
+ let timeSignature = this.measure.getTimeSignature();
1981
+ let beatCount = timeSignature.beatCount.toString();
1982
+ this.beatCountText = new ObjText(this, { text: beatCount, scale: 1.4 }, 0.5, 0.5);
1983
+ let beatSize = timeSignature.beatSize.toString();
1984
+ this.beatSizeText = new ObjText(this, { text: beatSize, scale: 1.4 }, 0.5, 0.5);
1985
+ } else {
1986
+ this.beatCountText = this.beatSizeText = void 0;
1556
1987
  }
1557
- if (this.measureNumber) {
1558
- this.measureNumber.offset(dx, dy);
1988
+ }
1989
+ updateTempo(showTempo) {
1990
+ if (showTempo) {
1991
+ let tempoStr = (0, import_theory2.getTempoString)(this.measure.getTempo());
1992
+ this.tempoText = new ObjText(this, tempoStr, 0, 1);
1993
+ } else {
1994
+ this.tempoText = void 0;
1995
+ }
1996
+ }
1997
+ pick(x, y) {
1998
+ if (!this.rect.contains(x, y)) {
1999
+ return [];
1559
2000
  }
1560
- this.ksNeutralizeAccidentals.forEach((acc) => acc.offset(dx, dy));
1561
- this.ksNewAccidentals.forEach((acc) => acc.offset(dx, dy));
1562
2001
  if (this.beatCountText) {
1563
- this.beatCountText.offset(dx, dy);
2002
+ let arr = this.beatCountText.pick(x, y);
2003
+ if (arr.length > 0) {
2004
+ return [this, ...arr];
2005
+ }
1564
2006
  }
1565
2007
  if (this.beatSizeText) {
1566
- this.beatSizeText.offset(dx, dy);
2008
+ let arr = this.beatSizeText.pick(x, y);
2009
+ if (arr.length > 0) {
2010
+ return [this, ...arr];
2011
+ }
1567
2012
  }
1568
2013
  if (this.tempoText) {
1569
- this.tempoText.offset(dx, dy);
1570
- }
1571
- this.rect.offsetInPlace(dx, dy);
1572
- }
1573
- draw(renderer) {
1574
- if (this.clefImage) {
1575
- this.clefImage.draw(renderer);
2014
+ let arr = this.tempoText.pick(x, y);
2015
+ if (arr.length > 0) {
2016
+ return [this, ...arr];
2017
+ }
1576
2018
  }
1577
- if (this.eightBelowClef) {
1578
- this.eightBelowClef.draw(renderer);
2019
+ if (this.measureNumber) {
2020
+ let arr = this.measureNumber.pick(x, y);
2021
+ if (arr.length > 0) {
2022
+ return [this, ...arr];
2023
+ }
1579
2024
  }
2025
+ return [this];
2026
+ }
2027
+ layout(renderer) {
2028
+ var _a, _b, _c, _d, _e, _f;
2029
+ let { unitSize } = renderer;
2030
+ let { tab } = this;
2031
+ let paddingX = unitSize;
2032
+ let x = 0;
2033
+ let topLineY = tab.getTopLineY();
2034
+ this.rect = new DivRect();
1580
2035
  if (this.measureNumber) {
1581
- this.measureNumber.draw(renderer);
2036
+ this.measureNumber.layout(renderer);
2037
+ this.measureNumber.offset(0, topLineY);
2038
+ this.rect.expandInPlace(this.measureNumber.getRect());
2039
+ x = Math.max(x, this.rect.right);
1582
2040
  }
1583
- this.ksNeutralizeAccidentals.forEach((acc) => acc.draw(renderer));
1584
- this.ksNewAccidentals.forEach((acc) => acc.draw(renderer));
2041
+ (_a = this.beatCountText) == null ? void 0 : _a.layout(renderer);
2042
+ (_b = this.beatSizeText) == null ? void 0 : _b.layout(renderer);
2043
+ let tsWidth = Math.max((_d = (_c = this.beatCountText) == null ? void 0 : _c.getRect().width) != null ? _d : 0, (_f = (_e = this.beatSizeText) == null ? void 0 : _e.getRect().width) != null ? _f : 0);
1585
2044
  if (this.beatCountText) {
1586
- this.beatCountText.draw(renderer);
2045
+ this.beatCountText.offset(0 + tsWidth / 2 + paddingX, tab.getRect().centerY - this.beatCountText.getRect().bottomh);
2046
+ this.rect.expandInPlace(this.beatCountText.getRect());
1587
2047
  }
1588
2048
  if (this.beatSizeText) {
1589
- this.beatSizeText.draw(renderer);
2049
+ this.beatSizeText.offset(0 + tsWidth / 2 + paddingX, tab.getRect().centerY + this.beatSizeText.getRect().toph);
2050
+ this.rect.expandInPlace(this.beatSizeText.getRect());
1590
2051
  }
1591
2052
  if (this.tempoText) {
1592
- this.tempoText.draw(renderer);
2053
+ this.tempoText.layout(renderer);
2054
+ this.tempoText.offset(x + unitSize * 2, topLineY);
2055
+ this.rect.expandInPlace(this.tempoText.getRect());
1593
2056
  }
2057
+ this.rect.right += paddingX;
2058
+ }
2059
+ offset(dx, dy) {
2060
+ var _a, _b, _c, _d;
2061
+ (_a = this.measureNumber) == null ? void 0 : _a.offset(dx, dy);
2062
+ (_b = this.beatCountText) == null ? void 0 : _b.offset(dx, dy);
2063
+ (_c = this.beatSizeText) == null ? void 0 : _c.offset(dx, dy);
2064
+ (_d = this.tempoText) == null ? void 0 : _d.offset(dx, dy);
2065
+ this.rect.offsetInPlace(dx, dy);
2066
+ }
2067
+ draw(renderer) {
2068
+ var _a, _b, _c, _d;
2069
+ (_a = this.measureNumber) == null ? void 0 : _a.draw(renderer);
2070
+ (_b = this.beatCountText) == null ? void 0 : _b.draw(renderer);
2071
+ (_c = this.beatSizeText) == null ? void 0 : _c.draw(renderer);
2072
+ (_d = this.tempoText) == null ? void 0 : _d.draw(renderer);
1594
2073
  }
1595
2074
  };
1596
2075
 
1597
2076
  // src/score/engine/player.ts
1598
- var import_ts_utils_lib8 = require("@tspro/ts-utils-lib");
1599
- var import_theory7 = require("@tspro/web-music-score/theory");
2077
+ var import_ts_utils_lib7 = require("@tspro/ts-utils-lib");
2078
+ var import_theory6 = require("@tspro/web-music-score/theory");
1600
2079
  var Audio = __toESM(require("@tspro/web-music-score/audio"));
1601
2080
 
1602
2081
  // src/score/engine/obj-rhythm-column.ts
1603
- var import_theory6 = require("@tspro/web-music-score/theory");
2082
+ var import_theory5 = require("@tspro/web-music-score/theory");
1604
2083
 
1605
2084
  // src/score/engine/obj-arpeggio.ts
1606
2085
  var ObjArpeggio = class extends MusicObject {
@@ -1674,7 +2153,7 @@ var ObjArpeggio = class extends MusicObject {
1674
2153
 
1675
2154
  // src/score/engine/obj-rest.ts
1676
2155
  var import_theory3 = require("@tspro/web-music-score/theory");
1677
- var import_core5 = require("@tspro/web-music-score/core");
2156
+ var import_core6 = require("@tspro/web-music-score/core");
1678
2157
  function getDiatonicIdFromStaffPos(staffPos) {
1679
2158
  if (typeof staffPos === "number") {
1680
2159
  return import_theory3.Note.getChromaticNote(staffPos).diatonicId;
@@ -1734,7 +2213,7 @@ var ObjRest = class extends MusicObject {
1734
2213
  let hasStaff = this.row.hasStaff;
1735
2214
  let staff2 = this.row.getStaff(diatonicId);
1736
2215
  if (hasStaff && !staff2) {
1737
- throw new import_core5.MusicError(import_core5.MusicErrorType.Score, "Rest staffPos is out of staff boundaries!");
2216
+ throw new import_core6.MusicError(import_core6.MusicErrorType.Score, "Rest staffPos is out of staff boundaries!");
1738
2217
  }
1739
2218
  }
1740
2219
  this.ownDiatonicId = this.measure.updateOwnDiatonicId(voiceId, diatonicId);
@@ -1810,6 +2289,9 @@ var ObjRest = class extends MusicObject {
1810
2289
  return { staff, x, y, stemHeight };
1811
2290
  });
1812
2291
  }
2292
+ hasTuplet() {
2293
+ return this.rhythmProps.tupletRatio !== void 0;
2294
+ }
1813
2295
  isEmpty() {
1814
2296
  return this.staffObjects.length === 0;
1815
2297
  }
@@ -1833,7 +2315,7 @@ var ObjRest = class extends MusicObject {
1833
2315
  case 64:
1834
2316
  return -3;
1835
2317
  default:
1836
- throw new import_core5.MusicError(import_core5.MusicErrorType.Score, `Get rest dot vertical displacement: Invalid note size: ${noteSize}`);
2318
+ throw new import_core6.MusicError(import_core6.MusicErrorType.Score, `Get rest dot vertical displacement: Invalid note size: ${noteSize}`);
1837
2319
  }
1838
2320
  }
1839
2321
  updateAccidentalState(accState) {
@@ -1846,42 +2328,16 @@ var ObjRest = class extends MusicObject {
1846
2328
  }
1847
2329
  let { unitSize } = renderer;
1848
2330
  let { ownDiatonicId } = this;
1849
- let { noteSize, dotCount, flagCount } = this.rhythmProps;
1850
- let leftw = 0;
1851
- let rightw = 0;
1852
- let toph = 0;
1853
- let bottomh = 0;
1854
- if (import_theory3.NoteLengthProps.equals(noteSize, import_theory3.NoteLength.Whole)) {
1855
- leftw = unitSize;
1856
- rightw = unitSize;
1857
- toph = 0;
1858
- bottomh = unitSize;
1859
- } else if (import_theory3.NoteLengthProps.equals(noteSize, import_theory3.NoteLength.Half)) {
1860
- leftw = unitSize;
1861
- rightw = unitSize;
1862
- toph = unitSize;
1863
- bottomh = 0;
1864
- } else if (import_theory3.NoteLengthProps.equals(noteSize, import_theory3.NoteLength.Quarter)) {
1865
- leftw = unitSize * 1;
1866
- rightw = unitSize * 1;
1867
- toph = unitSize * 3.2;
1868
- bottomh = unitSize * 3;
1869
- } else {
1870
- let adj = 1 - flagCount % 2;
1871
- leftw = unitSize * (1 + flagCount * 0.25);
1872
- rightw = unitSize * (1 + flagCount * 0.125);
1873
- toph = unitSize * (0.5 + flagCount - adj);
1874
- bottomh = unitSize * (1 + flagCount + adj);
1875
- }
2331
+ let { noteSize, dotCount } = this.rhythmProps;
1876
2332
  this.row.getStaves().forEach((staff) => {
1877
2333
  if (!staff.containsDiatonicId(ownDiatonicId) || !staff.containsVoiceId(this.voiceId)) {
1878
2334
  return;
1879
2335
  }
1880
2336
  let obj = new ObjStaffRest(staff, this);
1881
- obj.restRect = new DivRect(-leftw, 0, rightw, -toph, 0, bottomh);
2337
+ obj.restRect = renderer.getRestRect(noteSize);
1882
2338
  for (let i = 0; i < dotCount; i++) {
1883
2339
  let dotWidth = DocumentSettings.DotSize * unitSize;
1884
- let dotX = rightw + (DocumentSettings.RestDotSpace + DocumentSettings.DotSize * unitSize) + i * DocumentSettings.DotSize * unitSize * 1.5;
2340
+ let dotX = obj.restRect.rightw + (DocumentSettings.RestDotSpace + DocumentSettings.DotSize * unitSize) + i * DocumentSettings.DotSize * unitSize * 1.5;
1885
2341
  let dotY = this.getRestDotVerticalDisplacement(noteSize) * unitSize;
1886
2342
  obj.dotRects.push(DivRect.createCentered(dotX, dotY, dotWidth, dotWidth));
1887
2343
  }
@@ -1911,77 +2367,16 @@ var ObjRest = class extends MusicObject {
1911
2367
  return;
1912
2368
  }
1913
2369
  renderer.drawDebugRect(this.getRect());
1914
- let { unitSize, lineWidth } = renderer;
2370
+ let { lineWidth } = renderer;
1915
2371
  let { color } = this;
1916
- let { noteSize, flagCount } = this.rhythmProps;
2372
+ let { noteSize } = this.rhythmProps;
1917
2373
  ctx.strokeStyle = ctx.fillStyle = color;
1918
2374
  ctx.lineWidth = lineWidth;
1919
2375
  this.staffObjects.forEach((obj) => {
1920
2376
  let { dotRects, restRect } = obj;
1921
2377
  let x = restRect.centerX;
1922
2378
  let y = restRect.centerY;
1923
- if (import_theory3.NoteLengthProps.equals(noteSize, import_theory3.NoteLength.Whole)) {
1924
- ctx.fillRect(x - unitSize, y, unitSize * 2, unitSize);
1925
- } else if (import_theory3.NoteLengthProps.equals(noteSize, import_theory3.NoteLength.Half)) {
1926
- ctx.fillRect(x - unitSize, y - unitSize, unitSize * 2, unitSize);
1927
- } else if (import_theory3.NoteLengthProps.equals(noteSize, import_theory3.NoteLength.Quarter)) {
1928
- ctx.beginPath();
1929
- ctx.moveTo(x - unitSize * 0.6, y - unitSize * 3.2);
1930
- ctx.lineTo(x + unitSize * 0.7, y - unitSize * 1.5);
1931
- ctx.quadraticCurveTo(
1932
- x - unitSize * 0.8,
1933
- y - unitSize * 0.5,
1934
- x + unitSize * 1,
1935
- y + unitSize * 1.5
1936
- );
1937
- ctx.lineTo(x - unitSize * 1, y - unitSize * 0.75);
1938
- ctx.quadraticCurveTo(
1939
- x + unitSize * 0.2,
1940
- y - unitSize * 1.5,
1941
- x - unitSize * 0.6,
1942
- y - unitSize * 3.2
1943
- );
1944
- ctx.moveTo(x + unitSize * 1, y + unitSize * 1.5);
1945
- ctx.quadraticCurveTo(
1946
- x - unitSize * 0.8,
1947
- y + unitSize * 1,
1948
- x - unitSize * 0.2,
1949
- y + unitSize * 2.8
1950
- );
1951
- ctx.bezierCurveTo(
1952
- x - unitSize * 1.8,
1953
- y + unitSize * 1.5,
1954
- x - unitSize * 0.6,
1955
- y - unitSize * 0.2,
1956
- x + unitSize * 0.9,
1957
- y + unitSize * 1.5
1958
- );
1959
- ctx.fill();
1960
- ctx.stroke();
1961
- } else if (flagCount > 0) {
1962
- let adj = 1 - flagCount % 2;
1963
- let fx = (p) => x + (-p * 0.25 + 0.5) * unitSize;
1964
- let fy = (p) => y + (p + adj) * unitSize;
1965
- ctx.beginPath();
1966
- ctx.moveTo(fx(1 + flagCount), fy(1 + flagCount));
1967
- ctx.lineTo(fx(-0.5 - flagCount), fy(-0.5 - flagCount));
1968
- ctx.stroke();
1969
- for (let i = 0; i < flagCount; i++) {
1970
- let t = flagCount - i * 2;
1971
- ctx.beginPath();
1972
- ctx.moveTo(fx(t - 2.5), fy(t - 2.5));
1973
- ctx.quadraticCurveTo(
1974
- fx(t - 0.5) + unitSize * 0.25,
1975
- fy(t - 1.5),
1976
- fx(t - 1.5) - unitSize * 1.5,
1977
- fy(t - 1.5)
1978
- );
1979
- ctx.stroke();
1980
- ctx.beginPath();
1981
- ctx.arc(fx(t - 2) - unitSize * 1.5, fy(t - 2), unitSize * 0.5, 0, Math.PI * 2);
1982
- ctx.fill();
1983
- }
1984
- }
2379
+ renderer.drawRest(noteSize, x, y, color);
1985
2380
  dotRects.forEach((r) => {
1986
2381
  renderer.fillCircle(r.centerX, r.centerY, r.width / 2);
1987
2382
  });
@@ -1991,53 +2386,96 @@ var ObjRest = class extends MusicObject {
1991
2386
 
1992
2387
  // src/score/engine/obj-note-group.ts
1993
2388
  var import_ts_utils_lib4 = require("@tspro/ts-utils-lib");
1994
- var import_theory5 = require("@tspro/web-music-score/theory");
1995
-
1996
- // src/score/engine/obj-beam-group.ts
1997
- var import_ts_utils_lib3 = require("@tspro/ts-utils-lib");
1998
2389
  var import_theory4 = require("@tspro/web-music-score/theory");
1999
- var import_core6 = require("@tspro/web-music-score/core");
2000
- var adjustBeamAngle = (dx, dy) => {
2001
- let T = DocumentSettings.BeamAngleFactor;
2002
- if (!Number.isFinite(T) || T === 0) {
2003
- return dy;
2004
- } else {
2005
- let k = dx / dy / T;
2006
- k = Math.sign(k) * Math.sqrt(Math.abs(k));
2007
- return dx / k * T;
2008
- }
2009
- };
2010
- var BeamPoint = class {
2011
- constructor(staff, beamGroup, symbol, x, y) {
2390
+ var import_core7 = require("@tspro/web-music-score/core");
2391
+ function getStem(stem) {
2392
+ return import_ts_utils_lib4.Utils.Is.isEnumValue(stem, Stem) ? stem : void 0;
2393
+ }
2394
+ function getArpeggio(a) {
2395
+ return import_ts_utils_lib4.Utils.Is.isEnumValue(a, Arpeggio) ? a : a === true ? "up" /* Up */ : void 0;
2396
+ }
2397
+ function sortNoteStringData(notes, strings) {
2398
+ let stringArr = import_ts_utils_lib4.Utils.Arr.isArray(strings) ? strings : strings !== void 0 ? [strings] : [];
2399
+ let noteStringData = notes.map((note, i) => {
2400
+ return { note, string: stringArr[i] };
2401
+ });
2402
+ noteStringData = import_ts_utils_lib4.Utils.Arr.removeDuplicatesCmp(noteStringData, (a, b) => import_theory4.Note.equals(a.note, b.note)).sort((a, b) => import_theory4.Note.compareFunc(a.note, b.note));
2403
+ return {
2404
+ notes: noteStringData.map((e) => e.note),
2405
+ strings: noteStringData.every((e) => e.string === void 0) ? void 0 : noteStringData.map((e) => e.string)
2406
+ };
2407
+ }
2408
+ var ObjStaffNoteGroup = class extends MusicObject {
2409
+ constructor(staff, noteGroup) {
2410
+ super(staff);
2012
2411
  this.staff = staff;
2013
- this.beamGroup = beamGroup;
2014
- this.symbol = symbol;
2015
- this.x = x;
2016
- this.y = y;
2017
- __publicField(this, "topBeamsHeight", 0);
2018
- __publicField(this, "bottomBeamsHeight", 0);
2019
- staff.addObject(this);
2412
+ this.noteGroup = noteGroup;
2413
+ __publicField(this, "noteHeadRects", []);
2414
+ __publicField(this, "dotRects", []);
2415
+ __publicField(this, "accidentals", []);
2416
+ __publicField(this, "stemTip");
2417
+ __publicField(this, "stemBase");
2418
+ __publicField(this, "flagRects", []);
2419
+ __publicField(this, "prevTopNoteY", 0);
2420
+ __publicField(this, "prevBottomNoteY", 0);
2421
+ __publicField(this, "mi");
2422
+ this.mi = new MStaffNoteGroup(this);
2020
2423
  }
2021
- offset(dx, dy) {
2022
- this.x += dx;
2023
- this.y += dy;
2024
- this.beamGroup.requestRectUpdate();
2424
+ getMusicInterface() {
2425
+ return this.mi;
2426
+ }
2427
+ pick(x, y) {
2428
+ if (!this.getRect().contains(x, y)) {
2429
+ return [];
2430
+ }
2431
+ for (let i = 0; i < this.accidentals.length; i++) {
2432
+ let arr = this.accidentals[i].pick(x, y);
2433
+ if (arr.length > 0) {
2434
+ return [this, ...arr];
2435
+ }
2436
+ }
2437
+ return [this];
2438
+ }
2439
+ updateRect() {
2440
+ this.rect = this.noteHeadRects[0].copy();
2441
+ this.noteHeadRects.forEach((r) => this.rect.expandInPlace(r));
2442
+ if (this.stemTip) this.rect.expandInPlace(this.stemTip);
2443
+ if (this.stemBase) this.rect.expandInPlace(this.stemBase);
2444
+ this.dotRects.forEach((r) => this.rect.expandInPlace(r));
2445
+ this.flagRects.forEach((r) => this.rect.expandInPlace(r));
2446
+ this.accidentals.forEach((a) => this.rect.expandInPlace(a.getRect()));
2025
2447
  }
2026
2448
  getRect() {
2027
- return new DivRect(this.x, this.x, this.x, this.y - this.topBeamsHeight, this.y, this.y + this.bottomBeamsHeight);
2449
+ let bottomNoteRect = this.noteHeadRects[0];
2450
+ let topNoteRect = this.noteHeadRects[this.noteHeadRects.length - 1];
2451
+ if (this.prevTopNoteY !== topNoteRect.centerY || this.prevBottomNoteY !== bottomNoteRect.centerY) {
2452
+ this.prevTopNoteY = topNoteRect.centerY;
2453
+ this.prevBottomNoteY = bottomNoteRect.centerY;
2454
+ this.requestRectUpdate();
2455
+ }
2456
+ return super.getRect();
2457
+ }
2458
+ offset(dx, dy) {
2459
+ var _a, _b;
2460
+ this.noteHeadRects.forEach((n) => n.offsetInPlace(dx, dy));
2461
+ this.dotRects.forEach((n) => n.offsetInPlace(dx, dy));
2462
+ this.accidentals.forEach((n) => n.offset(dx, dy));
2463
+ (_a = this.stemTip) == null ? void 0 : _a.offsetInPlace(dx, dy);
2464
+ (_b = this.stemBase) == null ? void 0 : _b.offsetInPlace(dx, dy);
2465
+ this.flagRects.forEach((n) => n.offsetInPlace(dx, dy));
2466
+ this.requestRectUpdate();
2467
+ this.noteGroup.requestRectUpdate();
2028
2468
  }
2029
2469
  };
2030
- var ObjStaffBeamGroup = class extends MusicObject {
2031
- constructor(staff, beamGroup) {
2032
- super(staff);
2033
- this.staff = staff;
2034
- this.beamGroup = beamGroup;
2035
- __publicField(this, "tupletNumber");
2036
- __publicField(this, "tupletNumberOffsetY", 0);
2037
- __publicField(this, "points", []);
2470
+ var ObjTabNoteGroup = class extends MusicObject {
2471
+ constructor(tab, noteGroup) {
2472
+ super(tab);
2473
+ this.tab = tab;
2474
+ this.noteGroup = noteGroup;
2475
+ __publicField(this, "fretNumbers", []);
2038
2476
  __publicField(this, "mi");
2039
- staff.addObject(this);
2040
- this.mi = new MStaffBeamGroup(this);
2477
+ tab.addObject(this);
2478
+ this.mi = new MTabNoteGroup(this);
2041
2479
  }
2042
2480
  getMusicInterface() {
2043
2481
  return this.mi;
@@ -2045,95 +2483,102 @@ var ObjStaffBeamGroup = class extends MusicObject {
2045
2483
  pick(x, y) {
2046
2484
  return this.getRect().contains(x, y) ? [this] : [];
2047
2485
  }
2486
+ updateRect() {
2487
+ this.rect = this.fretNumbers[0].getRect().copy();
2488
+ this.fretNumbers.forEach((fn) => this.rect.expandInPlace(fn.getRect()));
2489
+ }
2048
2490
  offset(dx, dy) {
2049
- var _a;
2050
- this.points.forEach((p) => p.offset(dx, 0));
2051
- (_a = this.tupletNumber) == null ? void 0 : _a.offset(dx, dy);
2491
+ this.fretNumbers.forEach((f) => f.offset(dx, dy));
2052
2492
  this.requestRectUpdate();
2053
- this.beamGroup.requestRectUpdate();
2054
- }
2055
- updateRect() {
2056
- if (this.points.length > 0) {
2057
- this.rect = this.points[0].getRect().copy();
2058
- } else if (this.tupletNumber) {
2059
- this.rect = this.tupletNumber.getRect().copy();
2060
- }
2061
- this.points.forEach((pt) => this.rect.expandInPlace(pt.getRect()));
2062
- if (this.tupletNumber) {
2063
- this.rect.expandInPlace(this.tupletNumber.getRect());
2064
- }
2493
+ this.noteGroup.requestRectUpdate();
2065
2494
  }
2066
2495
  };
2067
- var ObjBeamGroup = class _ObjBeamGroup extends MusicObject {
2068
- constructor(symbols, tupletRatio) {
2069
- super(symbols[0].measure);
2070
- this.symbols = symbols;
2071
- this.tupletRatio = tupletRatio;
2072
- __publicField(this, "mi");
2073
- __publicField(this, "type");
2496
+ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2497
+ constructor(col, voiceId, notes, noteLength, options, tupletRatio) {
2498
+ var _a, _b, _c;
2499
+ super(col);
2500
+ this.col = col;
2501
+ this.voiceId = voiceId;
2502
+ this.notes = notes;
2503
+ __publicField(this, "minDiatonicId");
2504
+ __publicField(this, "maxDiatonicId");
2505
+ __publicField(this, "ownDiatonicId");
2506
+ // Average diatonicId of notes.
2507
+ __publicField(this, "ownStemDir");
2508
+ __publicField(this, "ownString");
2509
+ __publicField(this, "color");
2510
+ __publicField(this, "staccato");
2511
+ __publicField(this, "diamond");
2512
+ __publicField(this, "arpeggio");
2513
+ __publicField(this, "oldStyleTriplet");
2514
+ __publicField(this, "rhythmProps");
2515
+ __publicField(this, "startConnnectives", []);
2516
+ __publicField(this, "runningConnectives", []);
2517
+ __publicField(this, "leftBeamCount", 0);
2518
+ __publicField(this, "rightBeamCount", 0);
2519
+ __publicField(this, "beamGroup");
2074
2520
  __publicField(this, "staffObjects", []);
2075
- this.mi = new MBeamGroup(this);
2076
- let beamGroupName = tupletRatio ? "Tuplet" : "BeamGroup";
2077
- if (!symbols.every((s) => s.measure === symbols[0].measure)) {
2078
- throw new import_core6.MusicError(import_core6.MusicErrorType.Score, `All ${beamGroupName} symbols are not in same measure.`);
2079
- } else if (symbols.length < 2) {
2080
- throw new import_core6.MusicError(import_core6.MusicErrorType.Score, `${beamGroupName} needs minimum 2 symbols, but ${symbols.length} given.`);
2081
- }
2082
- if (tupletRatio !== void 0) {
2083
- let isGroup = symbols.length < 3 || symbols.some((s) => !(s instanceof ObjNoteGroup)) || symbols.some((s) => s.rhythmProps.flagCount !== symbols[0].rhythmProps.flagCount);
2084
- if (symbols.length >= 3 && symbols[0] instanceof ObjNoteGroup && symbols[symbols.length - 1] instanceof ObjNoteGroup && symbols[0].rhythmProps.flagCount === symbols[symbols.length - 1].rhythmProps.flagCount) {
2085
- isGroup = false;
2086
- }
2087
- if (symbols.some((s) => import_theory4.NoteLengthProps.cmp(s.rhythmProps.noteLength, import_theory4.NoteLength.Quarter) >= 0)) {
2088
- isGroup = true;
2089
- }
2090
- this.type = isGroup ? 2 /* TupletGroup */ : 1 /* TupletBeam */;
2091
- ObjNoteGroup.setTupletBeamCounts(this);
2092
- } else {
2093
- this.type = 0 /* RegularBeam */;
2094
- }
2095
- if (symbols.every((s) => s.getBeamGroup() === void 0)) {
2096
- symbols.forEach((s) => s.setBeamGroup(this));
2097
- symbols[0].measure.addBeamGroup(this);
2098
- } else {
2099
- throw new import_core6.MusicError(import_core6.MusicErrorType.Score, `Cannot add ${beamGroupName} because some symbol already has one.`);
2521
+ __publicField(this, "tabObjects", []);
2522
+ __publicField(this, "mi");
2523
+ if (!import_ts_utils_lib4.Utils.Is.isIntegerGte(notes.length, 1)) {
2524
+ throw new import_core7.MusicError(import_core7.MusicErrorType.Score, "Cannot create note group object because notes array is empty.");
2100
2525
  }
2526
+ let noteStringData = sortNoteStringData(notes, options == null ? void 0 : options.string);
2527
+ this.notes = noteStringData.notes;
2528
+ this.minDiatonicId = this.notes[0].diatonicId;
2529
+ this.maxDiatonicId = this.notes[this.notes.length - 1].diatonicId;
2530
+ this.ownDiatonicId = this.measure.updateOwnDiatonicId(voiceId, Math.round((this.minDiatonicId + this.maxDiatonicId) / 2));
2531
+ this.ownStemDir = this.measure.updateOwnStemDir(this, getStem(options == null ? void 0 : options.stem));
2532
+ this.ownString = this.measure.updateOwnString(this, noteStringData.strings);
2533
+ this.color = (_a = options == null ? void 0 : options.color) != null ? _a : "black";
2534
+ this.staccato = (_b = options == null ? void 0 : options.staccato) != null ? _b : false;
2535
+ this.diamond = (_c = options == null ? void 0 : options.diamond) != null ? _c : false;
2536
+ this.arpeggio = getArpeggio(options == null ? void 0 : options.arpeggio);
2537
+ this.oldStyleTriplet = tupletRatio === void 0 && ((options == null ? void 0 : options.triplet) === true || import_theory4.NoteLengthProps.get(noteLength).isTriplet);
2538
+ let dotCount = typeof (options == null ? void 0 : options.dotted) === "number" ? options.dotted > 0 ? options.dotted : void 0 : (options == null ? void 0 : options.dotted) === true ? 1 : void 0;
2539
+ this.rhythmProps = import_theory4.RhythmProps.get(noteLength, dotCount, (tupletRatio != null ? tupletRatio : this.oldStyleTriplet) ? import_theory4.Tuplet.Triplet : void 0);
2540
+ this.mi = new MNoteGroup(this);
2101
2541
  }
2102
- get showTupletRatio() {
2103
- var _a;
2104
- return ((_a = this.tupletRatio) == null ? void 0 : _a.showRatio) === true;
2542
+ getMusicInterface() {
2543
+ return this.mi;
2105
2544
  }
2106
- static createBeam(noteGroups) {
2107
- if (noteGroups.length > 1) {
2108
- new _ObjBeamGroup(noteGroups, void 0);
2109
- }
2545
+ get doc() {
2546
+ return this.col.doc;
2110
2547
  }
2111
- static createOldStyleTriplet(symbols) {
2112
- let s2 = symbols.slice(0, 2);
2113
- let n2 = s2.map((s) => s.rhythmProps.noteSize);
2114
- if (s2.length === 2 && s2.every((s) => s.oldStyleTriplet && s.getBeamGroup() === void 0) && (n2[0] * 2 === n2[1] || n2[1] * 2 === n2[0])) {
2115
- new _ObjBeamGroup(s2, import_theory4.Tuplet.Triplet);
2116
- return 2;
2117
- }
2118
- let s3 = symbols.slice(0, 3);
2119
- let n3 = s3.map((s) => s.rhythmProps.noteSize);
2120
- if (s3.length === 3 && s3.every((s) => s.oldStyleTriplet && s.getBeamGroup() === void 0) && n3.every((n) => n === n3[0])) {
2121
- new _ObjBeamGroup(s3, import_theory4.Tuplet.Triplet);
2122
- return 3;
2123
- }
2124
- return 0;
2548
+ get measure() {
2549
+ return this.col.measure;
2125
2550
  }
2126
- static createTuplet(symbols, tupletRatio) {
2127
- new _ObjBeamGroup(symbols, tupletRatio);
2551
+ get row() {
2552
+ return this.col.row;
2128
2553
  }
2129
- getMusicInterface() {
2130
- return this.mi;
2554
+ get stemDir() {
2555
+ return this.beamGroup ? this.beamGroup.stemDir : this.ownStemDir;
2131
2556
  }
2132
- detach() {
2133
- this.getSymbols().forEach((s) => s.resetBeamGroup());
2557
+ enableConnective(line) {
2558
+ return line.containsVoiceId(this.voiceId) && (line instanceof ObjTab || line.containsDiatonicId(this.ownDiatonicId));
2134
2559
  }
2135
- isEmpty() {
2136
- return this.staffObjects.length === 0;
2560
+ startConnective(connectiveProps) {
2561
+ if (!this.row.hasStaff && connectiveProps.connective === "tie" /* Tie */) {
2562
+ throw new import_core7.MusicError(import_core7.MusicErrorType.Score, "Ties not implemented for guitar tabs alone, staff is required!");
2563
+ } else if (!this.row.hasStaff && connectiveProps.connective === "slur" /* Slur */) {
2564
+ throw new import_core7.MusicError(import_core7.MusicErrorType.Score, "Slurs not implemented for guitar tabs alone, staff is required!");
2565
+ }
2566
+ this.startConnnectives.push(connectiveProps);
2567
+ this.doc.addConnectiveProps(connectiveProps);
2568
+ }
2569
+ getStaticObjects(line) {
2570
+ let staticObjects = [];
2571
+ this.staffObjects.forEach((obj) => {
2572
+ if (obj.staff === line) {
2573
+ staticObjects.push(obj);
2574
+ }
2575
+ });
2576
+ this.tabObjects.forEach((obj) => {
2577
+ if (obj.tab === line) {
2578
+ staticObjects.push(obj);
2579
+ }
2580
+ });
2581
+ return staticObjects;
2137
2582
  }
2138
2583
  pick(x, y) {
2139
2584
  if (!this.getRect().contains(x, y)) {
@@ -2145,456 +2590,16 @@ var ObjBeamGroup = class _ObjBeamGroup extends MusicObject {
2145
2590
  return [this, ...arr];
2146
2591
  }
2147
2592
  }
2148
- return [this];
2593
+ for (let i = 0; i < this.tabObjects.length; i++) {
2594
+ let arr = this.tabObjects[i].pick(x, y);
2595
+ if (arr.length > 0) {
2596
+ return [this, ...arr];
2597
+ }
2598
+ }
2599
+ return [];
2149
2600
  }
2150
- getType() {
2151
- return this.type;
2152
- }
2153
- isTuplet() {
2154
- return this.type === 1 /* TupletBeam */ || this.type === 2 /* TupletGroup */;
2155
- }
2156
- getSymbols() {
2157
- return this.symbols;
2158
- }
2159
- getFirstSymbol() {
2160
- return this.symbols[0];
2161
- }
2162
- getLastSymbol() {
2163
- return this.symbols[this.symbols.length - 1];
2164
- }
2165
- get stemDir() {
2166
- return this.symbols[0].ownStemDir;
2167
- }
2168
- layout(renderer) {
2169
- this.requestRectUpdate();
2170
- this.staffObjects.length = 0;
2171
- let symbols = this.getSymbols();
2172
- if (symbols.length === 0) {
2173
- return;
2174
- }
2175
- let voiceId = symbols[0].voiceId;
2176
- if (symbols.some((symbol) => symbol.voiceId !== voiceId)) {
2177
- return;
2178
- }
2179
- let { unitSize } = renderer;
2180
- let { stemDir } = this;
2181
- let symbolsBeamCoords = symbols.map((s) => s.getBeamCoords());
2182
- symbolsBeamCoords[0].map((s) => s == null ? void 0 : s.staff).forEach((mainStaff, index) => {
2183
- var _a, _b;
2184
- if (!mainStaff) {
2185
- return;
2186
- }
2187
- let symbolX = symbolsBeamCoords.map((s) => {
2188
- var _a2;
2189
- return (_a2 = s[index]) == null ? void 0 : _a2.x;
2190
- });
2191
- let symbolY = symbolsBeamCoords.map((s) => {
2192
- var _a2;
2193
- return (_a2 = s[index]) == null ? void 0 : _a2.y;
2194
- });
2195
- let symbolStaff = symbolsBeamCoords.map((s) => {
2196
- var _a2;
2197
- return (_a2 = s[index]) == null ? void 0 : _a2.staff;
2198
- });
2199
- let symbolStemHeight = symbolsBeamCoords.map((s) => {
2200
- var _a2;
2201
- return (_a2 = s[index]) == null ? void 0 : _a2.stemHeight;
2202
- });
2203
- let leftSymbol = symbols[0];
2204
- let leftX = symbolX[0];
2205
- let leftY = symbolY[0];
2206
- let leftStaff = symbolStaff[0];
2207
- let rightSymbol = symbols[symbols.length - 1];
2208
- let rightX = symbolX[symbolX.length - 1];
2209
- let rightY = symbolY[symbolY.length - 1];
2210
- let rightStaff = symbolStaff[symbolY.length - 1];
2211
- if (leftX === void 0 || leftY === void 0 || leftStaff === void 0 || rightX === void 0 || rightY === void 0 || rightStaff === void 0) {
2212
- return;
2213
- }
2214
- let leftStemHeight = (_a = symbolStemHeight[0]) != null ? _a : 0;
2215
- let rightStemHeight = (_b = symbolStemHeight[symbolStemHeight.length - 1]) != null ? _b : 0;
2216
- if (this.type !== 2 /* TupletGroup */) {
2217
- let leftDy = leftStemHeight < rightStemHeight ? Math.sqrt(rightStemHeight - leftStemHeight) : 0;
2218
- let rightDy = rightStemHeight < leftStemHeight ? Math.sqrt(leftStemHeight - rightStemHeight) : 0;
2219
- if (stemDir === "up" /* Up */) {
2220
- leftDy *= -1;
2221
- rightDy *= -1;
2222
- }
2223
- if (leftDy !== 0) {
2224
- leftY += leftDy;
2225
- symbolY[0] += leftDy;
2226
- }
2227
- if (rightDy !== 0) {
2228
- rightY += rightDy;
2229
- symbolY[symbolY.length - 1] += rightDy;
2230
- }
2231
- }
2232
- let groupLineDy = unitSize * 2 * (stemDir === "up" /* Up */ ? -1 : 1);
2233
- let centerY = (rightY + leftY) / 2;
2234
- let halfDy = adjustBeamAngle(rightX - leftX, rightY - leftY) / 2;
2235
- leftY = centerY - halfDy;
2236
- rightY = centerY + halfDy;
2237
- let raiseBeamY = 0;
2238
- symbolY.forEach((symY, i) => {
2239
- let symX = symbolX[i];
2240
- if (symX !== void 0 && symY !== void 0) {
2241
- let beamY = import_ts_utils_lib3.Utils.Math.interpolateY(leftX, leftY, rightX, rightY, symX);
2242
- let raiseY = symY - beamY;
2243
- if (stemDir === "up" /* Up */ && raiseY < 0) {
2244
- raiseBeamY = Math.min(raiseBeamY, raiseY);
2245
- } else if (stemDir === "down" /* Down */ && raiseY > 0) {
2246
- raiseBeamY = Math.max(raiseBeamY, raiseY);
2247
- }
2248
- }
2249
- });
2250
- leftY += raiseBeamY;
2251
- rightY += raiseBeamY;
2252
- symbolY = symbolY.map((y) => y === void 0 ? void 0 : y + raiseBeamY);
2253
- let obj = new ObjStaffBeamGroup(mainStaff, this);
2254
- if (this.type === 2 /* TupletGroup */) {
2255
- let ef = unitSize / (rightX - leftX);
2256
- let l = import_ts_utils_lib3.Utils.Math.interpolateCoord(leftX, leftY + groupLineDy, rightX, rightY + groupLineDy, -ef);
2257
- let r = import_ts_utils_lib3.Utils.Math.interpolateCoord(leftX, leftY + groupLineDy, rightX, rightY + groupLineDy, 1 + ef);
2258
- obj.points.push(new BeamPoint(leftStaff, this, leftSymbol, l.x, l.y));
2259
- obj.points.push(new BeamPoint(rightStaff, this, rightSymbol, r.x, r.y));
2260
- obj.tupletNumberOffsetY = 0;
2261
- } else if (this.type === 0 /* RegularBeam */ || this.type === 1 /* TupletBeam */) {
2262
- raiseBeamY *= 0.5;
2263
- let { beamThickness } = renderer;
2264
- const beamHeight = (i) => {
2265
- let sym = symbols[i];
2266
- if (sym instanceof ObjNoteGroup) {
2267
- let beamCount = sym instanceof ObjNoteGroup ? Math.max(sym.getLeftBeamCount(), sym.getRightBeamCount()) : 0;
2268
- return DocumentSettings.BeamSeparation * unitSize * (this.stemDir === "up" /* Up */ ? beamCount - 1 : 0);
2269
- } else {
2270
- return 0;
2271
- }
2272
- };
2273
- symbols.forEach((sym, i) => {
2274
- let symStaff = symbolStaff[i];
2275
- let symX = symbolX[i];
2276
- let symY = symbolY[i];
2277
- if (symStaff && symX !== void 0 && symY !== void 0) {
2278
- let pt = new BeamPoint(symStaff, this, sym, symX, symY);
2279
- pt.topBeamsHeight = beamThickness / 2 + (stemDir === "down" /* Down */ ? beamHeight(i) : 0);
2280
- pt.bottomBeamsHeight = beamThickness / 2 + (stemDir === "up" /* Up */ ? beamHeight(i) : 0);
2281
- obj.points.push(pt);
2282
- }
2283
- });
2284
- obj.tupletNumberOffsetY = groupLineDy;
2285
- }
2286
- if (this.isTuplet() && this.tupletRatio) {
2287
- let txt = this.showTupletRatio ? String(this.tupletRatio.parts) + ":" + String(this.tupletRatio.inTimeOf) : String(this.tupletRatio.parts);
2288
- obj.tupletNumber = new ObjText(this, txt, 0.5, 0.5);
2289
- obj.tupletNumber.layout(renderer);
2290
- obj.tupletNumber.offset((leftX + rightX) / 2, (leftY + rightY) / 2 + obj.tupletNumberOffsetY);
2291
- }
2292
- if (obj.points.length >= 2) {
2293
- this.staffObjects.push(obj);
2294
- }
2295
- });
2296
- }
2297
- updateRect() {
2298
- if (this.staffObjects.length === 0) {
2299
- this.rect = new DivRect();
2300
- } else {
2301
- this.staffObjects.forEach((obj) => obj.updateRect());
2302
- this.rect = this.staffObjects[0].getRect().copy();
2303
- for (let i = 1; i < this.staffObjects.length; i++) {
2304
- this.rect.expandInPlace(this.staffObjects[i].getRect());
2305
- }
2306
- }
2307
- }
2308
- updateStemTips() {
2309
- this.staffObjects.forEach((obj) => {
2310
- let left = obj.points[0];
2311
- let right = obj.points[obj.points.length - 1];
2312
- if (this.type !== 2 /* TupletGroup */) {
2313
- obj.points.forEach((pt) => {
2314
- if (pt.symbol instanceof ObjNoteGroup) {
2315
- if (pt !== left && pt !== right) {
2316
- pt.y = import_ts_utils_lib3.Utils.Math.interpolateY(left.x, left.y, right.x, right.y, pt.x);
2317
- }
2318
- pt.symbol.setStemTipY(pt.staff, pt.y);
2319
- }
2320
- });
2321
- }
2322
- if (obj.tupletNumber) {
2323
- let y = (left.y + right.y) / 2 + obj.tupletNumberOffsetY;
2324
- obj.tupletNumber.offset(0, -obj.tupletNumber.getRect().centerY + y);
2325
- }
2326
- });
2327
- }
2328
- offset(dx, dy) {
2329
- this.staffObjects.forEach((obj) => obj.offset(dx, 0));
2330
- this.requestRectUpdate();
2331
- }
2332
- draw(renderer) {
2333
- let { unitSize, beamThickness, lineWidth } = renderer;
2334
- let color = "black";
2335
- this.staffObjects.forEach((obj) => {
2336
- if (this.type === 2 /* TupletGroup */) {
2337
- let l = obj.points[0];
2338
- let r = obj.points[obj.points.length - 1];
2339
- if (l && r) {
2340
- let tf = obj.tupletNumber ? obj.tupletNumber.getRect().width / (r.x - l.x) * 1.2 : 0;
2341
- let lc = import_ts_utils_lib3.Utils.Math.interpolateCoord(l.x, l.y, r.x, r.y, 0.5 - tf / 2);
2342
- let rc = import_ts_utils_lib3.Utils.Math.interpolateCoord(l.x, l.y, r.x, r.y, 0.5 + tf / 2);
2343
- let tipH = this.stemDir === "up" /* Up */ ? unitSize : -unitSize;
2344
- renderer.drawLine(l.x, l.y, lc.x, lc.y, color, lineWidth);
2345
- renderer.drawLine(rc.x, rc.y, r.x, r.y, color, lineWidth);
2346
- renderer.drawLine(l.x, l.y, l.x, l.y + tipH, color, lineWidth);
2347
- renderer.drawLine(r.x, r.y, r.x, r.y + tipH, color, lineWidth);
2348
- }
2349
- } else if (this.type === 0 /* RegularBeam */ || this.type === 1 /* TupletBeam */) {
2350
- let beamSeparation = DocumentSettings.BeamSeparation * unitSize * (this.stemDir === "up" /* Up */ ? 1 : -1);
2351
- let noteGroupPoints = obj.points.filter((p) => p.symbol instanceof ObjNoteGroup);
2352
- for (let i = 0; i < noteGroupPoints.length - 1; i++) {
2353
- let left = noteGroupPoints[i];
2354
- let right = noteGroupPoints[i + 1];
2355
- if (!(left.symbol instanceof ObjNoteGroup && right.symbol instanceof ObjNoteGroup)) {
2356
- continue;
2357
- }
2358
- let leftBeamCount = left.symbol.getRightBeamCount();
2359
- let rightBeamCount = right.symbol.getLeftBeamCount();
2360
- let lx = left.x;
2361
- let ly = left.y;
2362
- let rx = right.x;
2363
- let ry = right.y;
2364
- for (let beamId = 0; beamId < Math.max(leftBeamCount, rightBeamCount); beamId++) {
2365
- if (beamId < leftBeamCount && beamId < rightBeamCount) {
2366
- renderer.drawLine(lx, ly, rx, ry, color, beamThickness);
2367
- } else if (leftBeamCount > rightBeamCount) {
2368
- renderer.drawPartialLine(lx, ly, rx, ry, 0, 0.25, color, beamThickness);
2369
- } else if (rightBeamCount > leftBeamCount) {
2370
- renderer.drawPartialLine(lx, ly, rx, ry, 0.75, 1, color, beamThickness);
2371
- }
2372
- ly += beamSeparation;
2373
- ry += beamSeparation;
2374
- }
2375
- }
2376
- }
2377
- if (obj.tupletNumber) {
2378
- obj.tupletNumber.draw(renderer);
2379
- }
2380
- });
2381
- }
2382
- };
2383
-
2384
- // src/score/engine/obj-note-group.ts
2385
- var import_core7 = require("@tspro/web-music-score/core");
2386
- function getStem(stem) {
2387
- return import_ts_utils_lib4.Utils.Is.isEnumValue(stem, Stem) ? stem : void 0;
2388
- }
2389
- function getArpeggio(a) {
2390
- return import_ts_utils_lib4.Utils.Is.isEnumValue(a, Arpeggio) ? a : a === true ? "up" /* Up */ : void 0;
2391
- }
2392
- function sortNoteStringData(notes, strings) {
2393
- let stringArr = import_ts_utils_lib4.Utils.Arr.isArray(strings) ? strings : strings !== void 0 ? [strings] : [];
2394
- let noteStringData = notes.map((note, i) => {
2395
- return { note, string: stringArr[i] };
2396
- });
2397
- noteStringData = import_ts_utils_lib4.Utils.Arr.removeDuplicatesCmp(noteStringData, (a, b) => import_theory5.Note.equals(a.note, b.note)).sort((a, b) => import_theory5.Note.compareFunc(a.note, b.note));
2398
- return {
2399
- notes: noteStringData.map((e) => e.note),
2400
- strings: noteStringData.every((e) => e.string === void 0) ? void 0 : noteStringData.map((e) => e.string)
2401
- };
2402
- }
2403
- var ObjStaffNoteGroup = class extends MusicObject {
2404
- constructor(staff, noteGroup) {
2405
- super(staff);
2406
- this.staff = staff;
2407
- this.noteGroup = noteGroup;
2408
- __publicField(this, "noteHeadRects", []);
2409
- __publicField(this, "dotRects", []);
2410
- __publicField(this, "accidentals", []);
2411
- __publicField(this, "stemTip");
2412
- __publicField(this, "stemBase");
2413
- __publicField(this, "flagRects", []);
2414
- __publicField(this, "prevTopNoteY", 0);
2415
- __publicField(this, "prevBottomNoteY", 0);
2416
- __publicField(this, "mi");
2417
- this.mi = new MStaffNoteGroup(this);
2418
- }
2419
- getMusicInterface() {
2420
- return this.mi;
2421
- }
2422
- pick(x, y) {
2423
- if (!this.getRect().contains(x, y)) {
2424
- return [];
2425
- }
2426
- for (let i = 0; i < this.accidentals.length; i++) {
2427
- let arr = this.accidentals[i].pick(x, y);
2428
- if (arr.length > 0) {
2429
- return [this, ...arr];
2430
- }
2431
- }
2432
- return [this];
2433
- }
2434
- updateRect() {
2435
- this.rect = this.noteHeadRects[0].copy();
2436
- this.noteHeadRects.forEach((r) => this.rect.expandInPlace(r));
2437
- if (this.stemTip) this.rect.expandInPlace(this.stemTip);
2438
- if (this.stemBase) this.rect.expandInPlace(this.stemBase);
2439
- this.dotRects.forEach((r) => this.rect.expandInPlace(r));
2440
- this.flagRects.forEach((r) => this.rect.expandInPlace(r));
2441
- this.accidentals.forEach((a) => this.rect.expandInPlace(a.getRect()));
2442
- }
2443
- getRect() {
2444
- let bottomNoteRect = this.noteHeadRects[0];
2445
- let topNoteRect = this.noteHeadRects[this.noteHeadRects.length - 1];
2446
- if (this.prevTopNoteY !== topNoteRect.centerY || this.prevBottomNoteY !== bottomNoteRect.centerY) {
2447
- this.prevTopNoteY = topNoteRect.centerY;
2448
- this.prevBottomNoteY = bottomNoteRect.centerY;
2449
- this.requestRectUpdate();
2450
- }
2451
- return super.getRect();
2452
- }
2453
- offset(dx, dy) {
2454
- var _a, _b;
2455
- this.noteHeadRects.forEach((n) => n.offsetInPlace(dx, dy));
2456
- this.dotRects.forEach((n) => n.offsetInPlace(dx, dy));
2457
- this.accidentals.forEach((n) => n.offset(dx, dy));
2458
- (_a = this.stemTip) == null ? void 0 : _a.offsetInPlace(dx, dy);
2459
- (_b = this.stemBase) == null ? void 0 : _b.offsetInPlace(dx, dy);
2460
- this.flagRects.forEach((n) => n.offsetInPlace(dx, dy));
2461
- this.requestRectUpdate();
2462
- this.noteGroup.requestRectUpdate();
2463
- }
2464
- };
2465
- var ObjTabNoteGroup = class extends MusicObject {
2466
- constructor(tab, noteGroup) {
2467
- super(tab);
2468
- this.tab = tab;
2469
- this.noteGroup = noteGroup;
2470
- __publicField(this, "fretNumbers", []);
2471
- __publicField(this, "mi");
2472
- tab.addObject(this);
2473
- this.mi = new MTabNoteGroup(this);
2474
- }
2475
- getMusicInterface() {
2476
- return this.mi;
2477
- }
2478
- pick(x, y) {
2479
- return this.getRect().contains(x, y) ? [this] : [];
2480
- }
2481
- updateRect() {
2482
- this.rect = this.fretNumbers[0].getRect().copy();
2483
- this.fretNumbers.forEach((fn) => this.rect.expandInPlace(fn.getRect()));
2484
- }
2485
- offset(dx, dy) {
2486
- this.fretNumbers.forEach((f) => f.offset(dx, dy));
2487
- this.requestRectUpdate();
2488
- this.noteGroup.requestRectUpdate();
2489
- }
2490
- };
2491
- var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2492
- constructor(col, voiceId, notes, noteLength, options, tupletRatio) {
2493
- var _a, _b, _c;
2494
- super(col);
2495
- this.col = col;
2496
- this.voiceId = voiceId;
2497
- this.notes = notes;
2498
- __publicField(this, "minDiatonicId");
2499
- __publicField(this, "maxDiatonicId");
2500
- __publicField(this, "ownDiatonicId");
2501
- // Average diatonicId of notes.
2502
- __publicField(this, "ownStemDir");
2503
- __publicField(this, "ownString");
2504
- __publicField(this, "color");
2505
- __publicField(this, "staccato");
2506
- __publicField(this, "diamond");
2507
- __publicField(this, "arpeggio");
2508
- __publicField(this, "oldStyleTriplet");
2509
- __publicField(this, "rhythmProps");
2510
- __publicField(this, "startConnnectives", []);
2511
- __publicField(this, "runningConnectives", []);
2512
- __publicField(this, "leftBeamCount", 0);
2513
- __publicField(this, "rightBeamCount", 0);
2514
- __publicField(this, "beamGroup");
2515
- __publicField(this, "staffObjects", []);
2516
- __publicField(this, "tabObjects", []);
2517
- __publicField(this, "mi");
2518
- if (!import_ts_utils_lib4.Utils.Is.isIntegerGte(notes.length, 1)) {
2519
- throw new import_core7.MusicError(import_core7.MusicErrorType.Score, "Cannot create note group object because notes array is empty.");
2520
- }
2521
- let noteStringData = sortNoteStringData(notes, options == null ? void 0 : options.string);
2522
- this.notes = noteStringData.notes;
2523
- this.minDiatonicId = this.notes[0].diatonicId;
2524
- this.maxDiatonicId = this.notes[this.notes.length - 1].diatonicId;
2525
- this.ownDiatonicId = this.measure.updateOwnDiatonicId(voiceId, Math.round((this.minDiatonicId + this.maxDiatonicId) / 2));
2526
- this.ownStemDir = this.measure.updateOwnStemDir(this, getStem(options == null ? void 0 : options.stem));
2527
- this.ownString = this.measure.updateOwnString(this, noteStringData.strings);
2528
- this.color = (_a = options == null ? void 0 : options.color) != null ? _a : "black";
2529
- this.staccato = (_b = options == null ? void 0 : options.staccato) != null ? _b : false;
2530
- this.diamond = (_c = options == null ? void 0 : options.diamond) != null ? _c : false;
2531
- this.arpeggio = getArpeggio(options == null ? void 0 : options.arpeggio);
2532
- this.oldStyleTriplet = tupletRatio === void 0 && ((options == null ? void 0 : options.triplet) === true || import_theory5.NoteLengthProps.get(noteLength).isTriplet);
2533
- let dotCount = typeof (options == null ? void 0 : options.dotted) === "number" ? options.dotted > 0 ? options.dotted : void 0 : (options == null ? void 0 : options.dotted) === true ? 1 : void 0;
2534
- this.rhythmProps = import_theory5.RhythmProps.get(noteLength, dotCount, (tupletRatio != null ? tupletRatio : this.oldStyleTriplet) ? import_theory5.Tuplet.Triplet : void 0);
2535
- this.mi = new MNoteGroup(this);
2536
- }
2537
- getMusicInterface() {
2538
- return this.mi;
2539
- }
2540
- get doc() {
2541
- return this.col.doc;
2542
- }
2543
- get measure() {
2544
- return this.col.measure;
2545
- }
2546
- get row() {
2547
- return this.col.row;
2548
- }
2549
- get stemDir() {
2550
- return this.beamGroup ? this.beamGroup.stemDir : this.ownStemDir;
2551
- }
2552
- enableConnective(line) {
2553
- return line.containsVoiceId(this.voiceId) && (line instanceof ObjTab || line.containsDiatonicId(this.ownDiatonicId));
2554
- }
2555
- startConnective(connectiveProps) {
2556
- if (!this.row.hasStaff && connectiveProps.connective === "tie" /* Tie */) {
2557
- throw new import_core7.MusicError(import_core7.MusicErrorType.Score, "Ties not implemented for guitar tabs alone, staff is required!");
2558
- } else if (!this.row.hasStaff && connectiveProps.connective === "slur" /* Slur */) {
2559
- throw new import_core7.MusicError(import_core7.MusicErrorType.Score, "Slurs not implemented for guitar tabs alone, staff is required!");
2560
- }
2561
- this.startConnnectives.push(connectiveProps);
2562
- this.doc.addConnectiveProps(connectiveProps);
2563
- }
2564
- getStaticObjects(line) {
2565
- let staticObjects = [];
2566
- this.staffObjects.forEach((obj) => {
2567
- if (obj.staff === line) {
2568
- staticObjects.push(obj);
2569
- }
2570
- });
2571
- this.tabObjects.forEach((obj) => {
2572
- if (obj.tab === line) {
2573
- staticObjects.push(obj);
2574
- }
2575
- });
2576
- return staticObjects;
2577
- }
2578
- pick(x, y) {
2579
- if (!this.getRect().contains(x, y)) {
2580
- return [];
2581
- }
2582
- for (let i = 0; i < this.staffObjects.length; i++) {
2583
- let arr = this.staffObjects[i].pick(x, y);
2584
- if (arr.length > 0) {
2585
- return [this, ...arr];
2586
- }
2587
- }
2588
- for (let i = 0; i < this.tabObjects.length; i++) {
2589
- let arr = this.tabObjects[i].pick(x, y);
2590
- if (arr.length > 0) {
2591
- return [this, ...arr];
2592
- }
2593
- }
2594
- return [];
2595
- }
2596
- getTopNote() {
2597
- return this.notes[this.notes.length - 1];
2601
+ getTopNote() {
2602
+ return this.notes[this.notes.length - 1];
2598
2603
  }
2599
2604
  getBottomNote() {
2600
2605
  return this.notes[0];
@@ -2766,6 +2771,15 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2766
2771
  getRightBeamCount() {
2767
2772
  return this.rightBeamCount;
2768
2773
  }
2774
+ setLeftBeamCount(count) {
2775
+ this.leftBeamCount = count;
2776
+ }
2777
+ setRightBeamCount(count) {
2778
+ this.rightBeamCount = count;
2779
+ }
2780
+ hasTuplet() {
2781
+ return this.rhythmProps.tupletRatio !== void 0;
2782
+ }
2769
2783
  isEmpty() {
2770
2784
  return this.staffObjects.length === 0 && this.tabObjects.length === 0;
2771
2785
  }
@@ -2783,11 +2797,11 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2783
2797
  return Math.max(this.rhythmProps.ticks, this.measure.getMeasureTicks() - this.col.positionTicks);
2784
2798
  }
2785
2799
  let prev = tieNoteGroups[j - 1];
2786
- if (prev && prev.notes.some((n) => import_theory5.Note.equals(n, note))) {
2800
+ if (prev && prev.notes.some((n) => import_theory4.Note.equals(n, note))) {
2787
2801
  return 0;
2788
2802
  }
2789
2803
  tieNoteGroups = tieNoteGroups.slice(j);
2790
- j = tieNoteGroups.findIndex((ng) => ng.notes.every((n) => !import_theory5.Note.equals(n, note)));
2804
+ j = tieNoteGroups.findIndex((ng) => ng.notes.every((n) => !import_theory4.Note.equals(n, note)));
2791
2805
  if (j >= 0) {
2792
2806
  tieNoteGroups = tieNoteGroups.slice(0, j);
2793
2807
  }
@@ -2979,105 +2993,20 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2979
2993
  if (isSolidNoteHead) {
2980
2994
  ctx.fill();
2981
2995
  } else {
2982
- ctx.stroke();
2983
- }
2984
- }
2985
- });
2986
- obj.dotRects.forEach((r) => renderer.fillCircle(r.centerX, r.centerY, r.width / 2));
2987
- if (obj.stemTip && obj.stemBase) {
2988
- ctx.beginPath();
2989
- ctx.moveTo(obj.stemBase.centerX, obj.stemBase.centerY);
2990
- ctx.lineTo(obj.stemTip.centerX, obj.stemTip.centerY);
2991
- ctx.stroke();
2992
- }
2993
- obj.flagRects.forEach((rect) => {
2994
- let left = rect.left;
2995
- let right = rect.right;
2996
- let width = right - left;
2997
- let top = stemDir === "up" /* Up */ ? rect.top : rect.bottom;
2998
- let bottom = stemDir === "up" /* Up */ ? rect.bottom : rect.top;
2999
- ctx.beginPath();
3000
- ctx.moveTo(left, top);
3001
- ctx.bezierCurveTo(
3002
- left,
3003
- top * 0.75 + bottom * 0.25,
3004
- left + width * 1.5,
3005
- top * 0.5 + bottom * 0.5,
3006
- left + width * 0.5,
3007
- bottom
3008
- );
3009
- ctx.stroke();
3010
- });
3011
- });
3012
- this.tabObjects.forEach((obj) => obj.fretNumbers.forEach((fn) => fn.draw(renderer)));
3013
- }
3014
- static setBeamCounts(groupNotes) {
3015
- const isADottedBHalf = (a, b) => {
3016
- let { flagCount: aFlagCount, noteSize: aNoteSize, dotCount: aDotCount } = a.rhythmProps;
3017
- let { flagCount: bFlagCount, noteSize: bNoteSize, dotCount: bDotCount } = b.rhythmProps;
3018
- return aFlagCount > 0 && bFlagCount > 0 && aDotCount > 0 && bDotCount === 0 && aNoteSize * Math.pow(2, aDotCount) === bNoteSize;
3019
- };
3020
- for (let i = 0; i < groupNotes.length; i++) {
3021
- let center = groupNotes[i];
3022
- let left = groupNotes[i - 1];
3023
- let right = groupNotes[i + 1];
3024
- if (center) {
3025
- center.leftBeamCount = 0;
3026
- center.rightBeamCount = 0;
3027
- if (left) {
3028
- if (left.rhythmProps.flagCount === center.rhythmProps.flagCount || isADottedBHalf(left, center) || isADottedBHalf(center, left)) {
3029
- center.leftBeamCount = center.rhythmProps.flagCount;
3030
- } else {
3031
- center.leftBeamCount = Math.min(left.rhythmProps.flagCount, center.rhythmProps.flagCount);
3032
- }
3033
- }
3034
- if (right) {
3035
- if (right.rhythmProps.flagCount === center.rhythmProps.flagCount || isADottedBHalf(right, center) || isADottedBHalf(center, right)) {
3036
- center.rightBeamCount = center.rhythmProps.flagCount;
3037
- } else {
3038
- center.rightBeamCount = Math.min(right.rhythmProps.flagCount, center.rhythmProps.flagCount);
3039
- }
3040
- }
3041
- }
3042
- }
3043
- let fixAgain;
3044
- do {
3045
- fixAgain = false;
3046
- for (let i = 0; i < groupNotes.length; i++) {
3047
- let center = groupNotes[i];
3048
- let left = groupNotes[i - 1];
3049
- let right = groupNotes[i + 1];
3050
- if (center && center.leftBeamCount !== center.rhythmProps.flagCount && center.rightBeamCount !== center.rhythmProps.flagCount) {
3051
- center.leftBeamCount = center.rightBeamCount = 0;
3052
- if (left && left.rightBeamCount > 0) {
3053
- left.rightBeamCount = 0;
3054
- fixAgain = true;
3055
- }
3056
- if (right && right.leftBeamCount > 0) {
3057
- right.leftBeamCount = 0;
3058
- fixAgain = true;
3059
- }
3060
- }
3061
- }
3062
- } while (fixAgain);
3063
- }
3064
- static setTupletBeamCounts(tuplet) {
3065
- let type = tuplet.getType();
3066
- let symbols = tuplet.getSymbols();
3067
- if (type === 1 /* TupletBeam */) {
3068
- symbols.forEach((s, i) => {
3069
- if (s instanceof _ObjNoteGroup) {
3070
- s.leftBeamCount = i === 0 ? 0 : s.rhythmProps.flagCount;
3071
- s.rightBeamCount = i === symbols.length - 1 ? 0 : s.rhythmProps.flagCount;
3072
- }
3073
- });
3074
- } else if (type === 2 /* TupletGroup */) {
3075
- symbols.forEach((s) => {
3076
- if (s instanceof _ObjNoteGroup) {
3077
- s.leftBeamCount = s.rightBeamCount = 0;
2996
+ ctx.stroke();
2997
+ }
3078
2998
  }
3079
2999
  });
3080
- }
3000
+ obj.dotRects.forEach((r) => renderer.fillCircle(r.centerX, r.centerY, r.width / 2));
3001
+ if (obj.stemTip && obj.stemBase) {
3002
+ ctx.beginPath();
3003
+ ctx.moveTo(obj.stemBase.centerX, obj.stemBase.centerY);
3004
+ ctx.lineTo(obj.stemTip.centerX, obj.stemTip.centerY);
3005
+ ctx.stroke();
3006
+ }
3007
+ obj.flagRects.forEach((rect) => renderer.drawFlag(rect, stemDir === "up" /* Up */ ? "up" : "down"));
3008
+ });
3009
+ this.tabObjects.forEach((obj) => obj.fretNumbers.forEach((fn) => fn.draw(renderer)));
3081
3010
  }
3082
3011
  getDotVerticalDisplacement(staff, diatonicId, stemDir) {
3083
3012
  if (staff.isLine(diatonicId)) {
@@ -3102,266 +3031,16 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
3102
3031
  };
3103
3032
 
3104
3033
  // src/score/engine/obj-rhythm-column.ts
3105
- var import_core9 = require("@tspro/web-music-score/core");
3106
-
3107
- // src/theory/rhythm.ts
3108
- var import_ts_utils_lib5 = require("@tspro/ts-utils-lib");
3109
3034
  var import_core8 = require("@tspro/web-music-score/core");
3110
- var cmp = (a, b) => a === b ? 0 : a < b ? -1 : 1;
3111
- var MaxTupletRatioValue = 12;
3112
- var TicksMultiplier = 12 * 11 * 9 * 7 * 5;
3113
- var NoteLength4 = /* @__PURE__ */ ((NoteLength10) => {
3114
- NoteLength10["Whole"] = "1n";
3115
- NoteLength10["WholeTriplet"] = "1t";
3116
- NoteLength10["WholeDot"] = "1.";
3117
- NoteLength10["Whole2Dots"] = "1..";
3118
- NoteLength10["Whole12Dots"] = "1..";
3119
- NoteLength10["Whole3Dots"] = "1...";
3120
- NoteLength10["Whole4Dots"] = "1....";
3121
- NoteLength10["Whole5Dots"] = "1.....";
3122
- NoteLength10["Whole6Dots"] = "1......";
3123
- NoteLength10["Half"] = "2n";
3124
- NoteLength10["HalfTriplet"] = "2t";
3125
- NoteLength10["HalfDot"] = "2.";
3126
- NoteLength10["Half2Dots"] = "2..";
3127
- NoteLength10["Half3Dots"] = "2...";
3128
- NoteLength10["Half4Dots"] = "2....";
3129
- NoteLength10["Half5Dots"] = "2.....";
3130
- NoteLength10["Quarter"] = "4n";
3131
- NoteLength10["QuarterTriplet"] = "4t";
3132
- NoteLength10["QuarterDot"] = "4.";
3133
- NoteLength10["Quarter2Dots"] = "4..";
3134
- NoteLength10["Quarter3Dots"] = "4...";
3135
- NoteLength10["Quarter4Dots"] = "4....";
3136
- NoteLength10["Eighth"] = "8n";
3137
- NoteLength10["EighthTriplet"] = "8t";
3138
- NoteLength10["EighthDot"] = "8.";
3139
- NoteLength10["Eighth2Dots"] = "8..";
3140
- NoteLength10["Eighth3Dots"] = "8...";
3141
- NoteLength10["Sixteenth"] = "16n";
3142
- NoteLength10["SixteenthTriplet"] = "16t";
3143
- NoteLength10["SixteenthDot"] = "16.";
3144
- NoteLength10["Sixteenth2Dots"] = "16..";
3145
- NoteLength10["ThirtySecond"] = "32n";
3146
- NoteLength10["ThirtySecondTriplet"] = "32t";
3147
- NoteLength10["ThirtySecondDot"] = "32.";
3148
- NoteLength10["SixtyFourth"] = "64n";
3149
- NoteLength10["SixtyFourthTriplet"] = "64t";
3150
- return NoteLength10;
3151
- })(NoteLength4 || {});
3152
- function validateNoteLength(noteLength) {
3153
- if (import_ts_utils_lib5.Utils.Is.isEnumValue(noteLength, NoteLength4)) {
3154
- return noteLength;
3155
- } else {
3156
- throw new import_core8.MusicError(import_core8.MusicErrorType.InvalidArg, `Invalid noteLength: ${noteLength}`);
3157
- }
3158
- }
3159
- var _NoteLengthProps = class _NoteLengthProps {
3160
- constructor(noteLength) {
3161
- /** Note length. */
3162
- __publicField(this, "noteLength");
3163
- /** Note size (whole=1, half=2, quarter=4, ...). */
3164
- __publicField(this, "noteSize");
3165
- /** Number of ticks (not altered by isTriplet). */
3166
- __publicField(this, "ticks");
3167
- /** Flag count. */
3168
- __publicField(this, "flagCount");
3169
- /** Dot count. */
3170
- __publicField(this, "dotCount");
3171
- /** Max dot count. */
3172
- __publicField(this, "maxDotCount");
3173
- /** Is triplet? */
3174
- __publicField(this, "isTriplet");
3175
- /** Has note stem. */
3176
- __publicField(this, "hasStem");
3177
- /** Is note head solid (black)? */
3178
- __publicField(this, "isSolid");
3179
- this.noteLength = validateNoteLength(noteLength);
3180
- this.noteSize = parseInt(noteLength);
3181
- this.isTriplet = noteLength.endsWith("t");
3182
- this.maxDotCount = this.isTriplet ? 0 : Math.floor(Math.log2(_NoteLengthProps.ShortestNoteSize / this.noteSize));
3183
- this.dotCount = import_ts_utils_lib5.Utils.Str.charCount(noteLength, ".");
3184
- this.flagCount = this.noteSize > 4 ? Math.floor(Math.log2(this.noteSize / 4)) : 0;
3185
- this.ticks = TicksMultiplier * _NoteLengthProps.ShortestNoteSize / this.noteSize;
3186
- this.hasStem = this.noteSize > 1;
3187
- this.isSolid = this.noteSize > 2;
3188
- if (this.dotCount > this.maxDotCount) {
3189
- throw new import_core8.MusicError(import_core8.MusicErrorType.Note, `dotCount ${this.dotCount} > maxDotCount ${this.maxDotCount}, for noteLength "${this.noteLength}".`);
3190
- } else if (this.isTriplet && this.dotCount > 0) {
3191
- throw new import_core8.MusicError(import_core8.MusicErrorType.Note, `noteLength "${this.noteLength}" is both triplet and dotted!`);
3192
- }
3193
- }
3194
- /**
3195
- * Get note length props.
3196
- * @param noteLength - Note length.
3197
- * @returns - Note length props.
3198
- */
3199
- static get(noteLength) {
3200
- let p = this.cache.get(noteLength);
3201
- if (!p) {
3202
- this.cache.set(noteLength, p = new _NoteLengthProps(noteLength));
3203
- }
3204
- return p;
3205
- }
3206
- /**
3207
- * Create note length props.
3208
- * @param noteLength - Note length or note size.
3209
- * @param dotCount - Dot count.
3210
- * @returns - Note length props.
3211
- */
3212
- static create(noteLength, dotCount = 0) {
3213
- let noteSize = typeof noteLength === "number" ? noteLength : this.get(noteLength).noteSize;
3214
- return this.get(noteSize + (import_ts_utils_lib5.Utils.Is.isIntegerGte(dotCount, 1) ? ".".repeat(dotCount) : "n"));
3215
- }
3216
- /**
3217
- * Compare note lengths/sizes. Whole (1) > half (2) > quarter (4), etc.
3218
- * Ignores possible triplet property of note length.
3219
- * @param a - NoteLengthProps, NoteLength/Str or noteSize
3220
- * @param b - NoteLengthProps, NoteLength/Str or noteSize
3221
- * @returns - -1: a < b, 0: a === b, +1: a > b (note length/size comparisons)
3222
- */
3223
- static cmp(a, b) {
3224
- let aNoteSize = a instanceof _NoteLengthProps ? a.noteSize : typeof a === "number" ? a : _NoteLengthProps.get(a).noteSize;
3225
- let bNoteSize = b instanceof _NoteLengthProps ? b.noteSize : typeof b === "number" ? b : _NoteLengthProps.get(b).noteSize;
3226
- return cmp(bNoteSize, aNoteSize);
3227
- }
3228
- /**
3229
- * Compare note lengths/sizes for equality.
3230
- * Ignores possible triplet property of note length.
3231
- * @param a - NoteLengthProps, NoteLength/Str or noteSize
3232
- * @param b - NoteLengthProps, NoteLength/Str or noteSize
3233
- * @returns - true: a === b, false: a !== b (note length/size comparisons)
3234
- */
3235
- static equals(a, b) {
3236
- let aNoteSize = a instanceof _NoteLengthProps ? a.noteSize : typeof a === "number" ? a : _NoteLengthProps.get(a).noteSize;
3237
- let bNoteSize = b instanceof _NoteLengthProps ? b.noteSize : typeof b === "number" ? b : _NoteLengthProps.get(b).noteSize;
3238
- return aNoteSize === bNoteSize;
3239
- }
3240
- };
3241
- /** Longest note size (e.g. 1 = whole note). */
3242
- __publicField(_NoteLengthProps, "LongestNoteSize", Math.min(...import_ts_utils_lib5.Utils.Enum.getEnumValues(NoteLength4).map((noteLength) => parseInt(noteLength))));
3243
- /** Shortest note size (e.g. 64 = sixtyfourth note). */
3244
- __publicField(_NoteLengthProps, "ShortestNoteSize", Math.max(...import_ts_utils_lib5.Utils.Enum.getEnumValues(NoteLength4).map((noteLength) => parseInt(noteLength))));
3245
- __publicField(_NoteLengthProps, "cache", /* @__PURE__ */ new Map());
3246
- var NoteLengthProps4 = _NoteLengthProps;
3247
- function validateTupletRatio(tupletRatio) {
3248
- if (import_ts_utils_lib5.Utils.Is.isObject(tupletRatio) && import_ts_utils_lib5.Utils.Is.isIntegerBetween(tupletRatio.parts, 2, MaxTupletRatioValue) && import_ts_utils_lib5.Utils.Is.isIntegerBetween(tupletRatio.inTimeOf, 2, MaxTupletRatioValue)) {
3249
- return tupletRatio;
3250
- } else {
3251
- throw new import_core8.MusicError(import_core8.MusicErrorType.Note, `Invalid tupletRatio ${JSON.stringify(tupletRatio)}`);
3252
- }
3253
- }
3254
- var Tuplet4 = {
3255
- /** Duplet: 2 in the time of 3 */
3256
- Duplet: { parts: 2, inTimeOf: 3 },
3257
- /** Triplet: 3 in the time of 2 */
3258
- Triplet: { parts: 3, inTimeOf: 2 },
3259
- /** Quadruplet: 4 in the time of 3 */
3260
- Quadruplet: { parts: 4, inTimeOf: 3 }
3261
- };
3262
- var _RhythmProps = class _RhythmProps {
3263
- constructor(noteLength, dotCount, tupletRatio) {
3264
- /** Note length. */
3265
- __publicField(this, "noteLength");
3266
- /** Note size (whole=1, half=2, quarter=4, ...). */
3267
- __publicField(this, "noteSize");
3268
- /** Dot count. */
3269
- __publicField(this, "dotCount");
3270
- /** Tuplet ratio. */
3271
- __publicField(this, "tupletRatio");
3272
- /** Number of ticks. */
3273
- __publicField(this, "ticks");
3274
- /** Flag count. */
3275
- __publicField(this, "flagCount");
3276
- /** Has note stem. */
3277
- __publicField(this, "hasStem");
3278
- /** Is note head solid (black)? */
3279
- __publicField(this, "isSolidNoteHead");
3280
- this.noteLength = validateNoteLength(noteLength);
3281
- let p = NoteLengthProps4.get(noteLength);
3282
- this.noteSize = p.noteSize;
3283
- this.ticks = p.ticks;
3284
- this.flagCount = p.flagCount;
3285
- this.dotCount = dotCount != null ? dotCount : p.dotCount;
3286
- this.hasStem = p.hasStem;
3287
- this.isSolidNoteHead = p.isSolid;
3288
- if (import_ts_utils_lib5.Utils.Is.isObject(tupletRatio)) {
3289
- this.tupletRatio = validateTupletRatio(tupletRatio);
3290
- } else if (p.isTriplet) {
3291
- this.tupletRatio = Tuplet4.Triplet;
3292
- } else {
3293
- this.tupletRatio = void 0;
3294
- }
3295
- if (this.dotCount > 0 && this.tupletRatio !== void 0) {
3296
- throw new import_core8.MusicError(import_core8.MusicErrorType.Note, `Note cannot be both dotted and tuplet!`);
3297
- } else if (this.dotCount > p.maxDotCount) {
3298
- throw new import_core8.MusicError(import_core8.MusicErrorType.Note, `Too big dot count ${this.dotCount} for note length ${this.noteLength}.`);
3299
- }
3300
- for (let add = this.ticks / 2, i = 1; i <= this.dotCount; i++, add /= 2) {
3301
- this.ticks += add;
3302
- }
3303
- if (this.tupletRatio) {
3304
- this.ticks *= this.tupletRatio.inTimeOf / this.tupletRatio.parts;
3305
- }
3306
- }
3307
- /**
3308
- * Get string presentation of rhythm props.
3309
- * @returns - String presentation.
3310
- */
3311
- toString() {
3312
- let sym = _RhythmProps.NoteSymbolMap.get(this.noteSize);
3313
- let dots = ".".repeat(this.dotCount);
3314
- return sym ? sym + dots : "" + this.noteSize + (dots.length > 0 ? dots : "n");
3315
- }
3316
- /**
3317
- * Get rhythm props with given arguments.
3318
- * @param noteLength - Note length.
3319
- * @param dotCount - Dot count.
3320
- * @param tupletRatio - Tuplet ratio.
3321
- * @returns - Rhythm props.
3322
- */
3323
- static get(noteLength, dotCount, tupletRatio) {
3324
- if (dotCount !== void 0 || tupletRatio !== void 0) {
3325
- return new _RhythmProps(noteLength, dotCount, tupletRatio);
3326
- } else {
3327
- let rhythmProps = this.cache.get(noteLength);
3328
- if (!rhythmProps) {
3329
- this.cache.set(noteLength, rhythmProps = new _RhythmProps(noteLength));
3330
- }
3331
- return rhythmProps;
3332
- }
3333
- }
3334
- /**
3335
- * Compare duration of rhythm props.
3336
- * @param a - RhythmProps
3337
- * @param b - RhythmProps
3338
- * @returns - -1: a < b, 0: a === b, +1: a > b (duration comparisons)
3339
- */
3340
- static cmp(a, b) {
3341
- return cmp(a.ticks, b.ticks);
3342
- }
3343
- /**
3344
- * Compare duration equality of rhythm props.
3345
- * @param a - RhythmProps
3346
- * @param b - RhythmProps
3347
- * @returns - true: a === b, false: a !== b (duration comparisons)
3348
- */
3349
- static equals(a, b) {
3350
- return a.ticks === b.ticks;
3351
- }
3352
- };
3353
- __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}"]]));
3354
- __publicField(_RhythmProps, "cache", /* @__PURE__ */ new Map());
3355
- var RhythmProps3 = _RhythmProps;
3356
3035
 
3357
3036
  // src/score/engine/obj-lyrics.ts
3358
- var import_ts_utils_lib6 = require("@tspro/ts-utils-lib");
3037
+ var import_ts_utils_lib5 = require("@tspro/ts-utils-lib");
3359
3038
  var LyricsContainer = class {
3360
3039
  constructor(col, lyricsLength) {
3361
3040
  this.col = col;
3362
3041
  __publicField(this, "lyricsObjects", []);
3363
3042
  __publicField(this, "rhythmProps");
3364
- this.rhythmProps = RhythmProps3.get(lyricsLength);
3043
+ this.rhythmProps = RhythmProps.get(lyricsLength);
3365
3044
  }
3366
3045
  addLyricsObject(lyricsObj) {
3367
3046
  var _a;
@@ -3382,7 +3061,7 @@ var ObjLyrics = class extends MusicObject {
3382
3061
  __publicField(this, "text");
3383
3062
  __publicField(this, "mi");
3384
3063
  let halign = (lyricsOptions == null ? void 0 : lyricsOptions.align) === "left" /* Left */ ? 0 : (lyricsOptions == null ? void 0 : lyricsOptions.align) === "right" /* Right */ ? 1 : 0.5;
3385
- this.hyphen = import_ts_utils_lib6.Utils.Is.isEnumValue(lyricsOptions == null ? void 0 : lyricsOptions.hyphen, LyricsHyphen) ? lyricsOptions == null ? void 0 : lyricsOptions.hyphen : void 0;
3064
+ this.hyphen = import_ts_utils_lib5.Utils.Is.isEnumValue(lyricsOptions == null ? void 0 : lyricsOptions.hyphen, LyricsHyphen) ? lyricsOptions == null ? void 0 : lyricsOptions.hyphen : void 0;
3386
3065
  this.text = new ObjText(this, { text: lyricsText, color: this.color, scale: 0.8 }, halign, 0);
3387
3066
  this.rect = new DivRect();
3388
3067
  this.mi = new MLyrics(this);
@@ -3435,11 +3114,11 @@ var ObjLyrics = class extends MusicObject {
3435
3114
 
3436
3115
  // src/score/engine/obj-rhythm-column.ts
3437
3116
  var noteHeadDataCompareFunc = (a, b) => {
3438
- let cmp3 = import_theory6.Note.compareFunc(a.note, b.note);
3439
- if (cmp3 === 0) {
3440
- cmp3 = a.noteGroup.stemDir === b.noteGroup.stemDir ? 0 : a.noteGroup.stemDir === "up" /* Up */ ? 1 : -1;
3117
+ let cmp = import_theory5.Note.compareFunc(a.note, b.note);
3118
+ if (cmp === 0) {
3119
+ cmp = a.noteGroup.stemDir === b.noteGroup.stemDir ? 0 : a.noteGroup.stemDir === "up" /* Up */ ? 1 : -1;
3441
3120
  }
3442
- return cmp3;
3121
+ return cmp;
3443
3122
  };
3444
3123
  var ObjRhythmColumn = class extends MusicObject {
3445
3124
  constructor(measure, positionTicks) {
@@ -3447,7 +3126,7 @@ var ObjRhythmColumn = class extends MusicObject {
3447
3126
  this.measure = measure;
3448
3127
  this.positionTicks = positionTicks;
3449
3128
  __publicField(this, "voiceSymbol", []);
3450
- __publicField(this, "lyricsContainers", []);
3129
+ __publicField(this, "lyricsContainerCache", /* @__PURE__ */ new Map());
3451
3130
  __publicField(this, "minDiatonicId");
3452
3131
  __publicField(this, "maxDiatonicId");
3453
3132
  __publicField(this, "staffMinDiatonicId", /* @__PURE__ */ new Map());
@@ -3477,7 +3156,7 @@ var ObjRhythmColumn = class extends MusicObject {
3477
3156
  if (colId >= 0 && colId < this.measure.getColumnCount()) {
3478
3157
  return this.measure.getColumn(colId + 1);
3479
3158
  } else {
3480
- throw new import_core9.MusicError(import_core9.MusicErrorType.Score, "Cannot get next column in measure because current column's id in mesure is invalid.");
3159
+ throw new import_core8.MusicError(import_core8.MusicErrorType.Score, "Cannot get next column in measure because current column's id in mesure is invalid.");
3481
3160
  }
3482
3161
  }
3483
3162
  /**
@@ -3573,18 +3252,20 @@ var ObjRhythmColumn = class extends MusicObject {
3573
3252
  getVoiceSymbol(voiceId) {
3574
3253
  return this.voiceSymbol[voiceId];
3575
3254
  }
3576
- getLyricsContainerDatas() {
3577
- return this.lyricsContainers;
3578
- }
3579
3255
  getLyricsContainer(verse, line, vpos, lyricsLength) {
3580
- let data = this.lyricsContainers.find((data2) => data2.verse === verse && data2.line === line && data2.vpos === vpos);
3581
- if (data === void 0 && lyricsLength !== void 0) {
3582
- data = { lyricsContainer: new LyricsContainer(this, (0, import_theory6.validateNoteLength)(lyricsLength)), verse, line, vpos };
3583
- this.lyricsContainers.push(data);
3584
- this.requestLayout();
3585
- this.requestRectUpdate();
3256
+ let vposMap = this.lyricsContainerCache.get(line);
3257
+ if (vposMap === void 0) {
3258
+ this.lyricsContainerCache.set(line, vposMap = /* @__PURE__ */ new Map());
3259
+ }
3260
+ let verseMap = vposMap.get(vpos);
3261
+ if (verseMap === void 0) {
3262
+ vposMap.set(vpos, verseMap = /* @__PURE__ */ new Map());
3586
3263
  }
3587
- return data == null ? void 0 : data.lyricsContainer;
3264
+ let lyricsContainer = verseMap.get(verse);
3265
+ if (lyricsContainer === void 0 && lyricsLength !== void 0) {
3266
+ verseMap.set(verse, lyricsContainer = new LyricsContainer(this, (0, import_theory5.validateNoteLength)(lyricsLength)));
3267
+ }
3268
+ return lyricsContainer;
3588
3269
  }
3589
3270
  getMinWidth() {
3590
3271
  let maxNoteSize = Math.max(...this.voiceSymbol.map((s) => s.rhythmProps.noteSize));
@@ -3639,7 +3320,7 @@ var ObjRhythmColumn = class extends MusicObject {
3639
3320
  }
3640
3321
  }
3641
3322
  getNoteHeadDisplacement(noteGroup, note) {
3642
- let data = this.noteHeadDisplacements.find((d) => d.noteGroup === noteGroup && import_theory6.Note.equals(d.note, note));
3323
+ let data = this.noteHeadDisplacements.find((d) => d.noteGroup === noteGroup && import_theory5.Note.equals(d.note, note));
3643
3324
  if ((data == null ? void 0 : data.displacement) !== void 0) {
3644
3325
  return data.displacement;
3645
3326
  } else {
@@ -3683,7 +3364,7 @@ var ObjRhythmColumn = class extends MusicObject {
3683
3364
  });
3684
3365
  }
3685
3366
  });
3686
- playerNotes.sort((a, b) => import_theory6.Note.compareFunc(a.note, b.note));
3367
+ playerNotes.sort((a, b) => import_theory5.Note.compareFunc(a.note, b.note));
3687
3368
  if (this.hasArpeggio() && this.getArpeggioDir() === "down" /* Down */) {
3688
3369
  playerNotes.reverse();
3689
3370
  }
@@ -3802,10 +3483,10 @@ var ObjRhythmColumn = class extends MusicObject {
3802
3483
  };
3803
3484
 
3804
3485
  // src/score/engine/extension.ts
3805
- var import_core10 = require("@tspro/web-music-score/core");
3486
+ var import_core9 = require("@tspro/web-music-score/core");
3806
3487
 
3807
3488
  // src/score/engine/element-data.ts
3808
- var import_ts_utils_lib7 = require("@tspro/ts-utils-lib");
3489
+ var import_ts_utils_lib6 = require("@tspro/ts-utils-lib");
3809
3490
 
3810
3491
  // src/score/engine/obj-special-text.ts
3811
3492
  var _ObjSpecialText = class _ObjSpecialText extends MusicObject {
@@ -3927,23 +3608,23 @@ function getNavigationString(navigation) {
3927
3608
  }
3928
3609
  }
3929
3610
  function isDynamicsText(text) {
3930
- return import_ts_utils_lib7.Utils.Is.isEnumValue(text, DynamicsAnnotation);
3611
+ return import_ts_utils_lib6.Utils.Is.isEnumValue(text, DynamicsAnnotation);
3931
3612
  }
3932
3613
  function getDynamicsVolume(text) {
3933
3614
  if (/^(p+|f+|m|mp|mf)$/.test(text)) {
3934
- let volume = 0.5 - import_ts_utils_lib7.Utils.Str.charCount(text, "p") * 0.1 + import_ts_utils_lib7.Utils.Str.charCount(text, "f") * 0.1;
3935
- return import_ts_utils_lib7.Utils.Math.clamp(volume, 0, 1);
3615
+ let volume = 0.5 - import_ts_utils_lib6.Utils.Str.charCount(text, "p") * 0.1 + import_ts_utils_lib6.Utils.Str.charCount(text, "f") * 0.1;
3616
+ return import_ts_utils_lib6.Utils.Math.clamp(volume, 0, 1);
3936
3617
  } else {
3937
3618
  return void 0;
3938
3619
  }
3939
3620
  }
3940
3621
  function isTempoText(text) {
3941
- return import_ts_utils_lib7.Utils.Is.isEnumValue(text, TempoAnnotation);
3622
+ return import_ts_utils_lib6.Utils.Is.isEnumValue(text, TempoAnnotation);
3942
3623
  }
3943
3624
  function getAnnotation(text) {
3944
- if (import_ts_utils_lib7.Utils.Is.isEnumValue(text, DynamicsAnnotation)) {
3625
+ if (import_ts_utils_lib6.Utils.Is.isEnumValue(text, DynamicsAnnotation)) {
3945
3626
  return "dynamics" /* Dynamics */;
3946
- } else if (import_ts_utils_lib7.Utils.Is.isEnumValue(text, TempoAnnotation)) {
3627
+ } else if (import_ts_utils_lib6.Utils.Is.isEnumValue(text, TempoAnnotation)) {
3947
3628
  return "tempo" /* Tempo */;
3948
3629
  } else {
3949
3630
  return void 0;
@@ -3986,7 +3667,7 @@ var Extension = class extends MusicObjectLink {
3986
3667
  if (head instanceof ObjText) {
3987
3668
  head.updateAnchorY(getTextAnchorY(linePos));
3988
3669
  } else {
3989
- throw new import_core10.MusicError(import_core10.MusicErrorType.Score, "Update anchor's y-coordinate is only implemented for text objects.");
3670
+ throw new import_core9.MusicError(import_core9.MusicErrorType.Score, "Update anchor's y-coordinate is only implemented for text objects.");
3990
3671
  }
3991
3672
  }
3992
3673
  isVisible() {
@@ -4066,7 +3747,7 @@ var RitardandoSpeedDiv = 2;
4066
3747
  var CrescendoVolumeAdd = 0.5;
4067
3748
  var DiminuendoVolumeSub = 0.5;
4068
3749
  function calcTicksDuration(ticks, tempo) {
4069
- let beatTicks = import_theory7.RhythmProps.get(tempo.options.beatLength, tempo.options.dotCount).ticks;
3750
+ let beatTicks = import_theory6.RhythmProps.get(tempo.options.beatLength, tempo.options.dotCount).ticks;
4070
3751
  let ticksPerMinute = tempo.beatsPerMinute * beatTicks;
4071
3752
  return 60 * ticks / ticksPerMinute;
4072
3753
  }
@@ -4099,8 +3780,8 @@ var PlayerColumnProps = class {
4099
3780
  return this.speed;
4100
3781
  }
4101
3782
  getTempo() {
4102
- let speed = import_ts_utils_lib8.Utils.Math.clamp(this.getSpeed(), 0.1, 10);
4103
- return (0, import_theory7.alterTempoSpeed)(this.measure.getTempo(), speed);
3783
+ let speed = import_ts_utils_lib7.Utils.Math.clamp(this.getSpeed(), 0.1, 10);
3784
+ return (0, import_theory6.alterTempoSpeed)(this.measure.getTempo(), speed);
4104
3785
  }
4105
3786
  setVolume(volume) {
4106
3787
  this.volume = volume;
@@ -4124,7 +3805,7 @@ var PlayerColumnProps = class {
4124
3805
  if (symbolsTicks.length === 0) {
4125
3806
  return 0;
4126
3807
  } else {
4127
- return import_ts_utils_lib8.Utils.Math.sum(symbolsTicks) / symbolsTicks.length;
3808
+ return import_ts_utils_lib7.Utils.Math.sum(symbolsTicks) / symbolsTicks.length;
4128
3809
  }
4129
3810
  }
4130
3811
  }
@@ -4273,7 +3954,7 @@ var Player = class _Player {
4273
3954
  } else if (layoutObj.musicObj.getLink() instanceof Extension) {
4274
3955
  let extension = layoutObj.musicObj.getLink();
4275
3956
  let { columnRange, extensionBreakText } = extension.getExtensionRangeInfo();
4276
- let totalTicks = import_ts_utils_lib8.Utils.Math.sum(columnRange.map((c) => c.getTicksToNextColumn()));
3957
+ let totalTicks = import_ts_utils_lib7.Utils.Math.sum(columnRange.map((c) => c.getTicksToNextColumn()));
4277
3958
  switch (text) {
4278
3959
  case "accel." /* accel */: {
4279
3960
  let startSpeed = curSpeed;
@@ -4327,11 +4008,11 @@ var Player = class _Player {
4327
4008
  });
4328
4009
  let speedArr = (_a = speedMap.get(col)) != null ? _a : [];
4329
4010
  if (speedArr.length > 0) {
4330
- curSpeed = import_ts_utils_lib8.Utils.Math.sum(speedArr) / speedArr.length;
4011
+ curSpeed = import_ts_utils_lib7.Utils.Math.sum(speedArr) / speedArr.length;
4331
4012
  }
4332
4013
  let volumeArr = (_b = volumeMap.get(col)) != null ? _b : [];
4333
4014
  if (volumeArr.length > 0) {
4334
- curVolume = import_ts_utils_lib8.Utils.Math.sum(volumeArr) / volumeArr.length;
4015
+ curVolume = import_ts_utils_lib7.Utils.Math.sum(volumeArr) / volumeArr.length;
4335
4016
  }
4336
4017
  col.getPlayerProps().setSpeed(curSpeed);
4337
4018
  col.getPlayerProps().setVolume(curVolume);
@@ -4356,7 +4037,11 @@ var Player = class _Player {
4356
4037
  this.stop();
4357
4038
  return;
4358
4039
  }
4359
- const col = this.playerColumnSequence[this.playPos];
4040
+ const col = this.playerColumnSequence[this.playPos];
4041
+ if (!col) {
4042
+ this.stop();
4043
+ return;
4044
+ }
4360
4045
  const getDuration = (ticks, tempo2) => {
4361
4046
  let seconds = calcTicksDuration(ticks, tempo2);
4362
4047
  return Math.max(0, seconds);
@@ -4369,11 +4054,11 @@ var Player = class _Player {
4369
4054
  } else {
4370
4055
  let playerNotes = col.getPlayerNotes();
4371
4056
  playerNotes.forEach((note, i) => {
4372
- let arpeggioDelayTicks = col.hasArpeggio() ? import_theory7.RhythmProps.get(import_theory7.NoteLength.ThirtySecond).ticks * i : 0;
4057
+ let arpeggioDelayTicks = col.hasArpeggio() ? import_theory6.RhythmProps.get(import_theory6.NoteLength.ThirtySecond).ticks * i : 0;
4373
4058
  let noteSeconds = getDuration(note.ticks + fermataHoldTicks - arpeggioDelayTicks, tempo);
4374
4059
  if (noteSeconds > 0) {
4375
4060
  if (note.staccato) {
4376
- noteSeconds = Math.min(getDuration(import_theory7.RhythmProps.get(import_theory7.NoteLength.Eighth).ticks, tempo) / 2, noteSeconds / 2);
4061
+ noteSeconds = Math.min(getDuration(import_theory6.RhythmProps.get(import_theory6.NoteLength.Eighth).ticks, tempo) / 2, noteSeconds / 2);
4377
4062
  }
4378
4063
  let volume = adjustVolume(col.getPlayerProps().getVolume());
4379
4064
  if (note.slur === "slurred") {
@@ -4441,6 +4126,9 @@ var Player = class _Player {
4441
4126
  return void 0;
4442
4127
  }
4443
4128
  let col = this.playerColumnSequence[this.playPos];
4129
+ if (!col) {
4130
+ return void 0;
4131
+ }
4444
4132
  let measure = col.measure;
4445
4133
  let x = col.getRect().centerX;
4446
4134
  let top = measure.row.getRect().top;
@@ -4605,146 +4293,676 @@ var ObjBarLineLeft = class extends ObjBarLine {
4605
4293
  __publicField(this, "mi");
4606
4294
  this.mi = new MBarLineLeft(this);
4607
4295
  }
4608
- getMusicInterface() {
4609
- return this.mi;
4296
+ getMusicInterface() {
4297
+ return this.mi;
4298
+ }
4299
+ solveBarLineType() {
4300
+ let m = this.measure;
4301
+ let prev = m.getPrevMeasure();
4302
+ if (m.hasNavigation("startRepeat" /* StartRepeat */)) {
4303
+ if (prev && prev.row === m.row && prev.hasNavigation("endRepeat" /* EndRepeat */)) {
4304
+ return 0 /* None */;
4305
+ } else {
4306
+ return 4 /* StartRepeat */;
4307
+ }
4308
+ } else {
4309
+ return 0 /* None */;
4310
+ }
4311
+ }
4312
+ };
4313
+ var ObjBarLineRight = class extends ObjBarLine {
4314
+ constructor(measure) {
4315
+ super(measure);
4316
+ __publicField(this, "playerProps");
4317
+ __publicField(this, "mi");
4318
+ this.playerProps = new PlayerColumnProps(this);
4319
+ this.mi = new MBarLineRight(this);
4320
+ }
4321
+ getMusicInterface() {
4322
+ return this.mi;
4323
+ }
4324
+ getPlayerProps() {
4325
+ return this.playerProps;
4326
+ }
4327
+ solveBarLineType() {
4328
+ let m = this.measure;
4329
+ let next = m.getNextMeasure();
4330
+ if (m.hasNavigation("endRepeat" /* EndRepeat */)) {
4331
+ if (next && next.row === m.row && next.hasNavigation("startRepeat" /* StartRepeat */)) {
4332
+ return 6 /* EndStartRepeat */;
4333
+ } else {
4334
+ return 5 /* EndRepeat */;
4335
+ }
4336
+ } else if (!m.doc.hasSingleMeasure() && (m.hasEndSong() || !m.getNextMeasure())) {
4337
+ return 3 /* EndSong */;
4338
+ } else if (m.hasEndSection()) {
4339
+ return 2 /* Double */;
4340
+ }
4341
+ if (m === m.row.getLastMeasure() && next && next.row === m.row.getNextRow() && next.hasNavigation("startRepeat" /* StartRepeat */)) {
4342
+ return 2 /* Double */;
4343
+ }
4344
+ if (next && next.hasNavigation("startRepeat" /* StartRepeat */)) {
4345
+ return 0 /* None */;
4346
+ }
4347
+ return 1 /* Single */;
4348
+ }
4349
+ };
4350
+
4351
+ // src/score/engine/obj-ending.ts
4352
+ var import_ts_utils_lib8 = require("@tspro/ts-utils-lib");
4353
+ var import_core10 = require("@tspro/web-music-score/core");
4354
+ var ObjEnding = class extends MusicObject {
4355
+ constructor(measure, passages) {
4356
+ super(measure);
4357
+ this.measure = measure;
4358
+ this.passages = passages;
4359
+ __publicField(this, "endingText");
4360
+ __publicField(this, "shapeRects", []);
4361
+ __publicField(this, "mi");
4362
+ this.mi = new MEnding(this);
4363
+ if (!import_ts_utils_lib8.Utils.Is.isIntegerGte(passages.length, 1)) {
4364
+ throw new import_core10.MusicError(import_core10.MusicErrorType.Score, "Passages is empty.");
4365
+ } else if (!this.passages.every((p) => import_ts_utils_lib8.Utils.Is.isIntegerGte(p, 1))) {
4366
+ throw new import_core10.MusicError(import_core10.MusicErrorType.Score, "Invalid passages: " + this.passages);
4367
+ }
4368
+ this.passages.sort((a, b) => a - b);
4369
+ let text = this.passages.map((p) => p + ".").join("");
4370
+ this.endingText = new ObjText(this, text, 0, 1);
4371
+ }
4372
+ getMusicInterface() {
4373
+ return this.mi;
4374
+ }
4375
+ getShapeRects() {
4376
+ return this.shapeRects;
4377
+ }
4378
+ isSingleMeasureEnding() {
4379
+ let { measure } = this;
4380
+ let next = measure.getNextMeasure();
4381
+ return (next == null ? void 0 : next.hasNavigation("ending" /* Ending */)) === true || measure.hasNavigation("endRepeat" /* EndRepeat */) || measure.isLastMeasure();
4382
+ }
4383
+ hasPassage(pass) {
4384
+ return this.passages.some((p) => p === pass);
4385
+ }
4386
+ getHighestPassage() {
4387
+ return Math.max(0, ...this.passages);
4388
+ }
4389
+ pick(x, y) {
4390
+ return this.rect.contains(x, y) ? [this] : [];
4391
+ }
4392
+ layout(renderer) {
4393
+ this.rect = new DivRect();
4394
+ this.shapeRects = [this.rect.copy()];
4395
+ }
4396
+ layoutFitToMeasure(renderer) {
4397
+ let { unitSize } = renderer;
4398
+ let { measure } = this;
4399
+ this.endingText.layout(renderer);
4400
+ let textRect = this.endingText.getRect();
4401
+ let measureContent = measure.getColumnsContentRect();
4402
+ let endingHeight = textRect.height;
4403
+ this.rect = new DivRect(measureContent.left + unitSize, measureContent.right - unitSize, -endingHeight, 0);
4404
+ this.endingText.offset(this.rect.left + unitSize / 2, this.rect.bottom);
4405
+ this.shapeRects = [
4406
+ new DivRect(this.rect.left, this.rect.left + 1, this.rect.top, this.rect.bottom),
4407
+ new DivRect(this.rect.left, this.rect.right, this.rect.top, this.rect.top + 1),
4408
+ new DivRect(this.rect.right - 1, this.rect.right, this.rect.top, this.rect.bottom),
4409
+ this.endingText.getRect().copy()
4410
+ ];
4411
+ }
4412
+ offset(dx, dy) {
4413
+ this.endingText.offset(dx, dy);
4414
+ this.shapeRects.forEach((r) => r.offsetInPlace(dx, dy));
4415
+ this.rect.offsetInPlace(dx, dy);
4416
+ }
4417
+ draw(renderer) {
4418
+ let ctx = renderer.getCanvasContext();
4419
+ if (!ctx) {
4420
+ return;
4421
+ }
4422
+ let { lineWidth } = renderer;
4423
+ let { rect } = this;
4424
+ renderer.drawDebugRect(this.rect);
4425
+ ctx.strokeStyle = ctx.fillStyle = "black";
4426
+ ctx.lineWidth = lineWidth;
4427
+ ctx.beginPath();
4428
+ ctx.moveTo(rect.left, rect.bottom);
4429
+ ctx.lineTo(rect.left, rect.top);
4430
+ ctx.lineTo(rect.right, rect.top);
4431
+ if (this.isSingleMeasureEnding()) {
4432
+ ctx.lineTo(rect.right, rect.bottom);
4433
+ }
4434
+ ctx.stroke();
4435
+ this.endingText.draw(renderer);
4436
+ }
4437
+ };
4438
+
4439
+ // src/score/engine/obj-beam-group.ts
4440
+ var import_ts_utils_lib9 = require("@tspro/ts-utils-lib");
4441
+ var import_theory7 = require("@tspro/web-music-score/theory");
4442
+ var import_core11 = require("@tspro/web-music-score/core");
4443
+ var adjustBeamAngle = (dx, dy) => {
4444
+ let T = DocumentSettings.BeamAngleFactor;
4445
+ if (!Number.isFinite(T) || T === 0) {
4446
+ return dy;
4447
+ } else {
4448
+ let k = dx / dy / T;
4449
+ k = Math.sign(k) * Math.sqrt(Math.abs(k));
4450
+ return dx / k * T;
4451
+ }
4452
+ };
4453
+ var BeamPoint = class {
4454
+ constructor(staff, beamGroup, symbol, x, y) {
4455
+ this.staff = staff;
4456
+ this.beamGroup = beamGroup;
4457
+ this.symbol = symbol;
4458
+ this.x = x;
4459
+ this.y = y;
4460
+ __publicField(this, "topBeamsHeight", 0);
4461
+ __publicField(this, "bottomBeamsHeight", 0);
4462
+ staff.addObject(this);
4463
+ }
4464
+ offset(dx, dy) {
4465
+ this.x += dx;
4466
+ this.y += dy;
4467
+ this.beamGroup.requestRectUpdate();
4468
+ }
4469
+ getRect() {
4470
+ return new DivRect(this.x, this.x, this.x, this.y - this.topBeamsHeight, this.y, this.y + this.bottomBeamsHeight);
4471
+ }
4472
+ };
4473
+ var ObjStaffBeamGroup = class extends MusicObject {
4474
+ constructor(staff, beamGroup) {
4475
+ super(staff);
4476
+ this.staff = staff;
4477
+ this.beamGroup = beamGroup;
4478
+ __publicField(this, "tupletNumber");
4479
+ __publicField(this, "tupletNumberOffsetY", 0);
4480
+ __publicField(this, "points", []);
4481
+ __publicField(this, "mi");
4482
+ staff.addObject(this);
4483
+ this.mi = new MStaffBeamGroup(this);
4484
+ }
4485
+ getMusicInterface() {
4486
+ return this.mi;
4487
+ }
4488
+ pick(x, y) {
4489
+ return this.getRect().contains(x, y) ? [this] : [];
4490
+ }
4491
+ offset(dx, dy) {
4492
+ var _a;
4493
+ this.points.forEach((p) => p.offset(dx, 0));
4494
+ (_a = this.tupletNumber) == null ? void 0 : _a.offset(dx, dy);
4495
+ this.requestRectUpdate();
4496
+ this.beamGroup.requestRectUpdate();
4497
+ }
4498
+ updateRect() {
4499
+ if (this.points.length > 0) {
4500
+ this.rect = this.points[0].getRect().copy();
4501
+ } else if (this.tupletNumber) {
4502
+ this.rect = this.tupletNumber.getRect().copy();
4503
+ }
4504
+ this.points.forEach((pt) => this.rect.expandInPlace(pt.getRect()));
4505
+ if (this.tupletNumber) {
4506
+ this.rect.expandInPlace(this.tupletNumber.getRect());
4507
+ }
4508
+ }
4509
+ };
4510
+ var InvalidBeamGroup = class {
4511
+ constructor(beamGroup, message) {
4512
+ this.beamGroup = beamGroup;
4513
+ this.message = message;
4514
+ }
4515
+ };
4516
+ var ObjBeamGroup = class _ObjBeamGroup extends MusicObject {
4517
+ constructor(symbols, tupletRatio) {
4518
+ super(symbols[0].measure);
4519
+ this.symbols = symbols;
4520
+ this.tupletRatio = tupletRatio;
4521
+ __publicField(this, "mi");
4522
+ __publicField(this, "type");
4523
+ __publicField(this, "staffObjects", []);
4524
+ this.mi = new MBeamGroup(this);
4525
+ let beamGroupName = tupletRatio ? "Tuplet" : "BeamGroup";
4526
+ if (!symbols.every((s) => s.measure === symbols[0].measure)) {
4527
+ throw new import_core11.MusicError(import_core11.MusicErrorType.Score, `All ${beamGroupName} symbols are not in same measure.`);
4528
+ } else if (symbols.length < 2) {
4529
+ throw new import_core11.MusicError(import_core11.MusicErrorType.Score, `${beamGroupName} needs minimum 2 symbols, but ${symbols.length} given.`);
4530
+ }
4531
+ if (tupletRatio !== void 0) {
4532
+ let isGroup = symbols.length < 3 || symbols.some((s) => !(s instanceof ObjNoteGroup)) || symbols.some((s) => s.rhythmProps.flagCount !== symbols[0].rhythmProps.flagCount);
4533
+ if (symbols.length >= 3 && symbols[0] instanceof ObjNoteGroup && symbols[symbols.length - 1] instanceof ObjNoteGroup && symbols[0].rhythmProps.flagCount === symbols[symbols.length - 1].rhythmProps.flagCount) {
4534
+ isGroup = false;
4535
+ }
4536
+ if (symbols.some((s) => import_theory7.NoteLengthProps.cmp(s.rhythmProps.noteLength, import_theory7.NoteLength.Quarter) >= 0)) {
4537
+ isGroup = true;
4538
+ }
4539
+ this.type = isGroup ? 2 /* TupletGroup */ : 1 /* TupletBeam */;
4540
+ this.setTupletBeamCounts();
4541
+ } else {
4542
+ this.type = 0 /* RegularBeam */;
4543
+ this.setBeamCounts();
4544
+ }
4545
+ if (symbols.every((s) => s.getBeamGroup() === void 0)) {
4546
+ symbols.forEach((s) => s.setBeamGroup(this));
4547
+ symbols[0].measure.addBeamGroup(this);
4548
+ } else {
4549
+ throw new import_core11.MusicError(import_core11.MusicErrorType.Score, `Cannot add ${beamGroupName} because some symbol already has one.`);
4550
+ }
4551
+ if (this.type === 0 /* RegularBeam */) {
4552
+ this.symbols.filter((sym) => sym instanceof ObjNoteGroup).some((sym, i) => {
4553
+ let first = i === 0;
4554
+ let last = i === this.symbols.length - 1;
4555
+ if (first && sym.getRightBeamCount() === 0 || last && sym.getLeftBeamCount() === 0 || !first && !last && (sym.getLeftBeamCount() === 0 || sym.getRightBeamCount() === 0)) {
4556
+ throw new InvalidBeamGroup(this, "Beam has zero left or right beam count!");
4557
+ }
4558
+ });
4559
+ }
4560
+ if (symbols.some((symbol) => symbol.voiceId !== symbols[0].voiceId)) {
4561
+ if (this.type === 0 /* RegularBeam */) {
4562
+ throw new InvalidBeamGroup(this, "Beam symbols have different voiceId.");
4563
+ } else {
4564
+ throw new import_core11.MusicError(import_core11.MusicErrorType.Score, `Tuplet symbols have different voiceId.`);
4565
+ }
4566
+ }
4567
+ symbols[0].row.getStaves().forEach((staff) => {
4568
+ if (staff.getActualStaff(symbols[0].ownDiatonicId) && staff.containsVoiceId(symbols[0].voiceId)) {
4569
+ symbols.forEach((sym) => {
4570
+ let actualStaff = staff.getActualStaff(sym.ownDiatonicId);
4571
+ if (!actualStaff || !actualStaff.containsVoiceId(sym.voiceId)) {
4572
+ throw new InvalidBeamGroup(this, "Some of beam or tuplet symbols are not visible!");
4573
+ }
4574
+ });
4575
+ }
4576
+ });
4577
+ }
4578
+ get showTupletRatio() {
4579
+ var _a;
4580
+ return ((_a = this.tupletRatio) == null ? void 0 : _a.showRatio) === true;
4610
4581
  }
4611
- solveBarLineType() {
4612
- let m = this.measure;
4613
- let prev = m.getPrevMeasure();
4614
- if (m.hasNavigation("startRepeat" /* StartRepeat */)) {
4615
- if (prev && prev.row === m.row && prev.hasNavigation("endRepeat" /* EndRepeat */)) {
4616
- return 0 /* None */;
4582
+ static createBeam(noteGroups) {
4583
+ if (noteGroups.length > 1 && noteGroups.every((ng) => !ng.hasTuplet())) {
4584
+ try {
4585
+ new _ObjBeamGroup(noteGroups, void 0);
4586
+ return true;
4587
+ } catch (err) {
4588
+ if (err instanceof InvalidBeamGroup) {
4589
+ err.beamGroup.detach();
4590
+ } else {
4591
+ throw err;
4592
+ }
4593
+ }
4594
+ }
4595
+ return false;
4596
+ }
4597
+ static createOldStyleTriplet(symbols) {
4598
+ try {
4599
+ let s2 = symbols.slice(0, 2);
4600
+ let n2 = s2.map((s) => s.rhythmProps.noteSize);
4601
+ if (s2.length === 2 && s2.every((s) => s.oldStyleTriplet && s.getBeamGroup() === void 0) && (n2[0] * 2 === n2[1] || n2[1] * 2 === n2[0])) {
4602
+ new _ObjBeamGroup(s2, import_theory7.Tuplet.Triplet);
4603
+ return 2;
4604
+ }
4605
+ let s3 = symbols.slice(0, 3);
4606
+ let n3 = s3.map((s) => s.rhythmProps.noteSize);
4607
+ if (s3.length === 3 && s3.every((s) => s.oldStyleTriplet && s.getBeamGroup() === void 0) && n3.every((n) => n === n3[0])) {
4608
+ new _ObjBeamGroup(s3, import_theory7.Tuplet.Triplet);
4609
+ return 3;
4610
+ }
4611
+ } catch (err) {
4612
+ if (err instanceof InvalidBeamGroup) {
4613
+ console.error(err.message);
4614
+ err.beamGroup.detach();
4617
4615
  } else {
4618
- return 4 /* StartRepeat */;
4616
+ throw err;
4619
4617
  }
4620
- } else {
4621
- return 0 /* None */;
4622
4618
  }
4619
+ return 0;
4623
4620
  }
4624
- };
4625
- var ObjBarLineRight = class extends ObjBarLine {
4626
- constructor(measure) {
4627
- super(measure);
4628
- __publicField(this, "playerProps");
4629
- __publicField(this, "mi");
4630
- this.playerProps = new PlayerColumnProps(this);
4631
- this.mi = new MBarLineRight(this);
4621
+ static createTuplet(symbols, tupletRatio) {
4622
+ try {
4623
+ new _ObjBeamGroup(symbols, tupletRatio);
4624
+ } catch (err) {
4625
+ if (err instanceof InvalidBeamGroup) {
4626
+ console.error(err.message);
4627
+ err.beamGroup.detach();
4628
+ } else {
4629
+ throw err;
4630
+ }
4631
+ }
4632
4632
  }
4633
4633
  getMusicInterface() {
4634
4634
  return this.mi;
4635
4635
  }
4636
- getPlayerProps() {
4637
- return this.playerProps;
4636
+ detach() {
4637
+ this.getSymbols().forEach((s) => s.resetBeamGroup());
4638
4638
  }
4639
- solveBarLineType() {
4640
- let m = this.measure;
4641
- let next = m.getNextMeasure();
4642
- if (m.hasNavigation("endRepeat" /* EndRepeat */)) {
4643
- if (next && next.row === m.row && next.hasNavigation("startRepeat" /* StartRepeat */)) {
4644
- return 6 /* EndStartRepeat */;
4645
- } else {
4646
- return 5 /* EndRepeat */;
4647
- }
4648
- } else if (!m.doc.hasSingleMeasure() && (m.hasEndSong() || !m.getNextMeasure())) {
4649
- return 3 /* EndSong */;
4650
- } else if (m.hasEndSection()) {
4651
- return 2 /* Double */;
4652
- }
4653
- if (m === m.row.getLastMeasure() && next && next.row === m.row.getNextRow() && next.hasNavigation("startRepeat" /* StartRepeat */)) {
4654
- return 2 /* Double */;
4639
+ isEmpty() {
4640
+ return this.staffObjects.length === 0;
4641
+ }
4642
+ pick(x, y) {
4643
+ if (!this.getRect().contains(x, y)) {
4644
+ return [];
4655
4645
  }
4656
- if (next && next.hasNavigation("startRepeat" /* StartRepeat */)) {
4657
- return 0 /* None */;
4646
+ for (let i = 0; i < this.staffObjects.length; i++) {
4647
+ let arr = this.staffObjects[i].pick(x, y);
4648
+ if (arr.length > 0) {
4649
+ return [this, ...arr];
4650
+ }
4658
4651
  }
4659
- return 1 /* Single */;
4652
+ return [this];
4660
4653
  }
4661
- };
4662
-
4663
- // src/score/engine/obj-ending.ts
4664
- var import_ts_utils_lib9 = require("@tspro/ts-utils-lib");
4665
- var import_core11 = require("@tspro/web-music-score/core");
4666
- var ObjEnding = class extends MusicObject {
4667
- constructor(measure, passages) {
4668
- super(measure);
4669
- this.measure = measure;
4670
- this.passages = passages;
4671
- __publicField(this, "endingText");
4672
- __publicField(this, "shapeRects", []);
4673
- __publicField(this, "mi");
4674
- this.mi = new MEnding(this);
4675
- if (!import_ts_utils_lib9.Utils.Is.isIntegerGte(passages.length, 1)) {
4676
- throw new import_core11.MusicError(import_core11.MusicErrorType.Score, "Passages is empty.");
4677
- } else if (!this.passages.every((p) => import_ts_utils_lib9.Utils.Is.isIntegerGte(p, 1))) {
4678
- throw new import_core11.MusicError(import_core11.MusicErrorType.Score, "Invalid passages: " + this.passages);
4679
- }
4680
- this.passages.sort((a, b) => a - b);
4681
- let text = this.passages.map((p) => p + ".").join("");
4682
- this.endingText = new ObjText(this, text, 0, 1);
4654
+ getType() {
4655
+ return this.type;
4683
4656
  }
4684
- getMusicInterface() {
4685
- return this.mi;
4657
+ isTuplet() {
4658
+ return this.type === 1 /* TupletBeam */ || this.type === 2 /* TupletGroup */;
4686
4659
  }
4687
- getShapeRects() {
4688
- return this.shapeRects;
4660
+ getTupletRatioText() {
4661
+ var _a, _b, _c;
4662
+ return this.showTupletRatio ? String((_a = this.tupletRatio) == null ? void 0 : _a.parts) + ":" + String((_b = this.tupletRatio) == null ? void 0 : _b.inTimeOf) : String((_c = this.tupletRatio) == null ? void 0 : _c.parts);
4689
4663
  }
4690
- isSingleMeasureEnding() {
4691
- let { measure } = this;
4692
- let next = measure.getNextMeasure();
4693
- return (next == null ? void 0 : next.hasNavigation("ending" /* Ending */)) === true || measure.hasNavigation("endRepeat" /* EndRepeat */) || measure.isLastMeasure();
4664
+ getSymbols() {
4665
+ return this.symbols;
4694
4666
  }
4695
- hasPassage(pass) {
4696
- return this.passages.some((p) => p === pass);
4667
+ getFirstSymbol() {
4668
+ return this.symbols[0];
4697
4669
  }
4698
- getHighestPassage() {
4699
- return Math.max(0, ...this.passages);
4670
+ getLastSymbol() {
4671
+ return this.symbols[this.symbols.length - 1];
4700
4672
  }
4701
- pick(x, y) {
4702
- return this.rect.contains(x, y) ? [this] : [];
4673
+ get stemDir() {
4674
+ return this.symbols[0].ownStemDir;
4703
4675
  }
4704
- layout(renderer) {
4705
- this.rect = new DivRect();
4706
- this.shapeRects = [this.rect.copy()];
4676
+ get color() {
4677
+ return this.symbols[0].color;
4707
4678
  }
4708
- layoutFitToMeasure(renderer) {
4679
+ layout(renderer) {
4680
+ this.requestRectUpdate();
4681
+ this.staffObjects.length = 0;
4682
+ let symbols = this.getSymbols();
4683
+ if (symbols.length === 0) {
4684
+ return;
4685
+ }
4709
4686
  let { unitSize } = renderer;
4710
- let { measure } = this;
4711
- this.endingText.layout(renderer);
4712
- let textRect = this.endingText.getRect();
4713
- let measureContent = measure.getColumnsContentRect();
4714
- let endingHeight = textRect.height;
4715
- this.rect = new DivRect(measureContent.left + unitSize, measureContent.right - unitSize, -endingHeight, 0);
4716
- this.endingText.offset(this.rect.left + unitSize / 2, this.rect.bottom);
4717
- this.shapeRects = [
4718
- new DivRect(this.rect.left, this.rect.left + 1, this.rect.top, this.rect.bottom),
4719
- new DivRect(this.rect.left, this.rect.right, this.rect.top, this.rect.top + 1),
4720
- new DivRect(this.rect.right - 1, this.rect.right, this.rect.top, this.rect.bottom),
4721
- this.endingText.getRect().copy()
4722
- ];
4687
+ let { stemDir, type } = this;
4688
+ let symbolsBeamCoords = symbols.map((s) => s.getBeamCoords());
4689
+ symbolsBeamCoords[0].map((s) => s == null ? void 0 : s.staff).forEach((mainStaff, index) => {
4690
+ var _a, _b;
4691
+ if (!mainStaff) {
4692
+ return;
4693
+ }
4694
+ let symbolX = symbolsBeamCoords.map((s) => {
4695
+ var _a2;
4696
+ return (_a2 = s[index]) == null ? void 0 : _a2.x;
4697
+ });
4698
+ let symbolY = symbolsBeamCoords.map((s) => {
4699
+ var _a2;
4700
+ return (_a2 = s[index]) == null ? void 0 : _a2.y;
4701
+ });
4702
+ let symbolStaff = symbolsBeamCoords.map((s) => {
4703
+ var _a2;
4704
+ return (_a2 = s[index]) == null ? void 0 : _a2.staff;
4705
+ });
4706
+ let symbolStemHeight = symbolsBeamCoords.map((s) => {
4707
+ var _a2;
4708
+ return (_a2 = s[index]) == null ? void 0 : _a2.stemHeight;
4709
+ });
4710
+ let leftSymbol = symbols[0];
4711
+ let leftX = symbolX[0];
4712
+ let leftY = symbolY[0];
4713
+ let leftStaff = symbolStaff[0];
4714
+ let rightSymbol = symbols[symbols.length - 1];
4715
+ let rightX = symbolX[symbolX.length - 1];
4716
+ let rightY = symbolY[symbolY.length - 1];
4717
+ let rightStaff = symbolStaff[symbolY.length - 1];
4718
+ if (leftX === void 0 || leftY === void 0 || leftStaff === void 0 || rightX === void 0 || rightY === void 0 || rightStaff === void 0) {
4719
+ return;
4720
+ }
4721
+ let leftStemHeight = (_a = symbolStemHeight[0]) != null ? _a : 0;
4722
+ let rightStemHeight = (_b = symbolStemHeight[symbolStemHeight.length - 1]) != null ? _b : 0;
4723
+ if (type !== 2 /* TupletGroup */) {
4724
+ let leftDy = leftStemHeight < rightStemHeight ? Math.sqrt(rightStemHeight - leftStemHeight) : 0;
4725
+ let rightDy = rightStemHeight < leftStemHeight ? Math.sqrt(leftStemHeight - rightStemHeight) : 0;
4726
+ if (stemDir === "up" /* Up */) {
4727
+ leftDy *= -1;
4728
+ rightDy *= -1;
4729
+ }
4730
+ if (leftDy !== 0) {
4731
+ leftY += leftDy;
4732
+ symbolY[0] += leftDy;
4733
+ }
4734
+ if (rightDy !== 0) {
4735
+ rightY += rightDy;
4736
+ symbolY[symbolY.length - 1] += rightDy;
4737
+ }
4738
+ }
4739
+ let groupLineDy = unitSize * 2 * (stemDir === "up" /* Up */ ? -1 : 1);
4740
+ let centerY = (rightY + leftY) / 2;
4741
+ let halfDy = adjustBeamAngle(rightX - leftX, rightY - leftY) / 2;
4742
+ leftY = centerY - halfDy;
4743
+ rightY = centerY + halfDy;
4744
+ let raiseBeamY = 0;
4745
+ symbolY.forEach((symY, i) => {
4746
+ let symX = symbolX[i];
4747
+ if (symX !== void 0 && symY !== void 0) {
4748
+ let beamY = import_ts_utils_lib9.Utils.Math.interpolateY(leftX, leftY, rightX, rightY, symX);
4749
+ let raiseY = symY - beamY;
4750
+ if (stemDir === "up" /* Up */ && raiseY < 0) {
4751
+ raiseBeamY = Math.min(raiseBeamY, raiseY);
4752
+ } else if (stemDir === "down" /* Down */ && raiseY > 0) {
4753
+ raiseBeamY = Math.max(raiseBeamY, raiseY);
4754
+ }
4755
+ }
4756
+ });
4757
+ leftY += raiseBeamY;
4758
+ rightY += raiseBeamY;
4759
+ symbolY = symbolY.map((y) => y === void 0 ? void 0 : y + raiseBeamY);
4760
+ let obj = new ObjStaffBeamGroup(mainStaff, this);
4761
+ if (type === 2 /* TupletGroup */) {
4762
+ let ef = unitSize / (rightX - leftX);
4763
+ let l = import_ts_utils_lib9.Utils.Math.interpolateCoord(leftX, leftY + groupLineDy, rightX, rightY + groupLineDy, -ef);
4764
+ let r = import_ts_utils_lib9.Utils.Math.interpolateCoord(leftX, leftY + groupLineDy, rightX, rightY + groupLineDy, 1 + ef);
4765
+ obj.points.push(new BeamPoint(leftStaff, this, leftSymbol, l.x, l.y));
4766
+ obj.points.push(new BeamPoint(rightStaff, this, rightSymbol, r.x, r.y));
4767
+ obj.tupletNumberOffsetY = 0;
4768
+ } else if (type === 0 /* RegularBeam */ || type === 1 /* TupletBeam */) {
4769
+ raiseBeamY *= 0.5;
4770
+ let { beamThickness } = renderer;
4771
+ const beamHeight = (i) => {
4772
+ let sym = symbols[i];
4773
+ if (sym instanceof ObjNoteGroup) {
4774
+ let beamCount = sym instanceof ObjNoteGroup ? Math.max(sym.getLeftBeamCount(), sym.getRightBeamCount()) : 0;
4775
+ return DocumentSettings.BeamSeparation * unitSize * (stemDir === "up" /* Up */ ? beamCount - 1 : 0);
4776
+ } else {
4777
+ return 0;
4778
+ }
4779
+ };
4780
+ symbols.forEach((sym, i) => {
4781
+ let symStaff = symbolStaff[i];
4782
+ let symX = symbolX[i];
4783
+ let symY = symbolY[i];
4784
+ if (symStaff && symX !== void 0 && symY !== void 0) {
4785
+ let pt = new BeamPoint(symStaff, this, sym, symX, symY);
4786
+ switch (stemDir) {
4787
+ case "up" /* Up */:
4788
+ pt.topBeamsHeight = beamThickness / 2;
4789
+ pt.bottomBeamsHeight = beamThickness / 2 + beamHeight(i);
4790
+ break;
4791
+ case "down" /* Down */:
4792
+ pt.topBeamsHeight = beamThickness / 2 + beamHeight(i);
4793
+ pt.bottomBeamsHeight = beamThickness / 2;
4794
+ break;
4795
+ }
4796
+ obj.points.push(pt);
4797
+ }
4798
+ });
4799
+ obj.tupletNumberOffsetY = groupLineDy;
4800
+ }
4801
+ if (this.isTuplet()) {
4802
+ obj.tupletNumber = new ObjText(this, this.getTupletRatioText(), 0.5, 0.5);
4803
+ obj.tupletNumber.layout(renderer);
4804
+ obj.tupletNumber.offset((leftX + rightX) / 2, (leftY + rightY) / 2 + obj.tupletNumberOffsetY);
4805
+ }
4806
+ if (obj.points.length >= 2) {
4807
+ this.staffObjects.push(obj);
4808
+ }
4809
+ });
4810
+ }
4811
+ updateRect() {
4812
+ if (this.staffObjects.length === 0) {
4813
+ this.rect = new DivRect();
4814
+ } else {
4815
+ this.staffObjects.forEach((obj) => obj.updateRect());
4816
+ this.rect = this.staffObjects[0].getRect().copy();
4817
+ for (let i = 1; i < this.staffObjects.length; i++) {
4818
+ this.rect.expandInPlace(this.staffObjects[i].getRect());
4819
+ }
4820
+ }
4821
+ }
4822
+ updateStemTips() {
4823
+ this.staffObjects.forEach((obj) => {
4824
+ let left = obj.points[0];
4825
+ let right = obj.points[obj.points.length - 1];
4826
+ if (this.type !== 2 /* TupletGroup */) {
4827
+ obj.points.forEach((pt) => {
4828
+ if (pt.symbol instanceof ObjNoteGroup) {
4829
+ if (pt !== left && pt !== right) {
4830
+ pt.y = import_ts_utils_lib9.Utils.Math.interpolateY(left.x, left.y, right.x, right.y, pt.x);
4831
+ }
4832
+ pt.symbol.setStemTipY(pt.staff, pt.y);
4833
+ }
4834
+ });
4835
+ }
4836
+ if (obj.tupletNumber) {
4837
+ let y = (left.y + right.y) / 2 + obj.tupletNumberOffsetY;
4838
+ obj.tupletNumber.offset(0, -obj.tupletNumber.getRect().centerY + y);
4839
+ }
4840
+ });
4723
4841
  }
4724
4842
  offset(dx, dy) {
4725
- this.endingText.offset(dx, dy);
4726
- this.shapeRects.forEach((r) => r.offsetInPlace(dx, dy));
4727
- this.rect.offsetInPlace(dx, dy);
4843
+ this.staffObjects.forEach((obj) => obj.offset(dx, 0));
4844
+ this.requestRectUpdate();
4728
4845
  }
4729
4846
  draw(renderer) {
4730
- let ctx = renderer.getCanvasContext();
4731
- if (!ctx) {
4732
- return;
4847
+ let { unitSize, beamThickness, lineWidth } = renderer;
4848
+ let { stemDir, color, type } = this;
4849
+ if (type === 2 /* TupletGroup */) {
4850
+ let tipHeight = (stemDir === "up" /* Up */ ? 1 : -1) * unitSize;
4851
+ this.staffObjects.forEach((obj) => {
4852
+ let { x: lx, y: ly } = obj.points[0];
4853
+ let { x: rx, y: ry } = obj.points[obj.points.length - 1];
4854
+ if (obj.tupletNumber) {
4855
+ let tf = obj.tupletNumber.getRect().width / (rx - lx) * 1.2;
4856
+ let lc = import_ts_utils_lib9.Utils.Math.interpolateCoord(lx, ly, rx, ry, 0.5 - tf / 2);
4857
+ let rc = import_ts_utils_lib9.Utils.Math.interpolateCoord(lx, ly, rx, ry, 0.5 + tf / 2);
4858
+ renderer.drawLine(lx, ly, lc.x, lc.y, color, lineWidth);
4859
+ renderer.drawLine(rc.x, rc.y, rx, ry, color, lineWidth);
4860
+ } else {
4861
+ renderer.drawLine(lx, ly, rx, ry, color, lineWidth);
4862
+ }
4863
+ renderer.drawLine(lx, ly, lx, ly + tipHeight, color, lineWidth);
4864
+ renderer.drawLine(rx, ry, rx, ry + tipHeight, color, lineWidth);
4865
+ });
4866
+ } else if (type === 0 /* RegularBeam */ || type === 1 /* TupletBeam */) {
4867
+ this.staffObjects.forEach((obj) => {
4868
+ let noteGroupPoints = obj.points.filter((p) => p.symbol instanceof ObjNoteGroup);
4869
+ let { x: lx, y: ly } = noteGroupPoints[0];
4870
+ let { x: rx, y: ry } = noteGroupPoints[noteGroupPoints.length - 1];
4871
+ let beamSeparation = DocumentSettings.BeamSeparation * unitSize * (stemDir === "up" /* Up */ ? 1 : -1) * (1 + 0.5 * Math.abs(Math.atan2(ry - ly, rx - lx)));
4872
+ for (let i = 0; i < noteGroupPoints.length - 1; i++) {
4873
+ let { x: lx2, y: ly2, symbol: lsymbol } = noteGroupPoints[i];
4874
+ let { x: rx2, y: ry2, symbol: rsymbol } = noteGroupPoints[i + 1];
4875
+ let leftBeamCount = lsymbol.getRightBeamCount();
4876
+ let rightBeamCount = rsymbol.getLeftBeamCount();
4877
+ for (let beamId = 0; beamId < Math.max(leftBeamCount, rightBeamCount); beamId++) {
4878
+ if (beamId < leftBeamCount && beamId < rightBeamCount) {
4879
+ renderer.drawLine(lx2, ly2, rx2, ry2, color, beamThickness);
4880
+ } else if (leftBeamCount > rightBeamCount) {
4881
+ renderer.drawPartialLine(lx2, ly2, rx2, ry2, 0, 0.25, color, beamThickness);
4882
+ } else if (rightBeamCount > leftBeamCount) {
4883
+ renderer.drawPartialLine(lx2, ly2, rx2, ry2, 0.75, 1, color, beamThickness);
4884
+ }
4885
+ ly2 += beamSeparation;
4886
+ ry2 += beamSeparation;
4887
+ }
4888
+ }
4889
+ });
4733
4890
  }
4734
- let { lineWidth } = renderer;
4735
- let { rect } = this;
4736
- renderer.drawDebugRect(this.rect);
4737
- ctx.strokeStyle = ctx.fillStyle = "black";
4738
- ctx.lineWidth = lineWidth;
4739
- ctx.beginPath();
4740
- ctx.moveTo(rect.left, rect.bottom);
4741
- ctx.lineTo(rect.left, rect.top);
4742
- ctx.lineTo(rect.right, rect.top);
4743
- if (this.isSingleMeasureEnding()) {
4744
- ctx.lineTo(rect.right, rect.bottom);
4891
+ this.staffObjects.forEach((obj) => {
4892
+ var _a;
4893
+ return (_a = obj.tupletNumber) == null ? void 0 : _a.draw(renderer);
4894
+ });
4895
+ }
4896
+ setBeamCounts() {
4897
+ const isADottedBHalf = (a, b) => {
4898
+ let { flagCount: aFlagCount, noteSize: aNoteSize, dotCount: aDotCount } = a.rhythmProps;
4899
+ let { flagCount: bFlagCount, noteSize: bNoteSize, dotCount: bDotCount } = b.rhythmProps;
4900
+ return aFlagCount > 0 && bFlagCount > 0 && aDotCount > 0 && bDotCount === 0 && aNoteSize * Math.pow(2, aDotCount) === bNoteSize;
4901
+ };
4902
+ let groupNotes = this.symbols.filter((s) => s instanceof ObjNoteGroup);
4903
+ for (let i = 0; i < groupNotes.length; i++) {
4904
+ let center = groupNotes[i];
4905
+ let left = groupNotes[i - 1];
4906
+ let right = groupNotes[i + 1];
4907
+ if (center) {
4908
+ center.setLeftBeamCount(0);
4909
+ center.setRightBeamCount(0);
4910
+ if (left) {
4911
+ if (left.rhythmProps.flagCount === center.rhythmProps.flagCount || isADottedBHalf(left, center) || isADottedBHalf(center, left)) {
4912
+ center.setLeftBeamCount(center.rhythmProps.flagCount);
4913
+ } else {
4914
+ center.setLeftBeamCount(Math.min(left.rhythmProps.flagCount, center.rhythmProps.flagCount));
4915
+ }
4916
+ }
4917
+ if (right) {
4918
+ if (right.rhythmProps.flagCount === center.rhythmProps.flagCount || isADottedBHalf(right, center) || isADottedBHalf(center, right)) {
4919
+ center.setRightBeamCount(center.rhythmProps.flagCount);
4920
+ } else {
4921
+ center.setRightBeamCount(Math.min(right.rhythmProps.flagCount, center.rhythmProps.flagCount));
4922
+ }
4923
+ }
4924
+ }
4925
+ }
4926
+ let fixAgain;
4927
+ do {
4928
+ fixAgain = false;
4929
+ for (let i = 0; i < groupNotes.length; i++) {
4930
+ let center = groupNotes[i];
4931
+ let left = groupNotes[i - 1];
4932
+ let right = groupNotes[i + 1];
4933
+ if (center && center.getLeftBeamCount() !== center.rhythmProps.flagCount && center.getRightBeamCount() !== center.rhythmProps.flagCount) {
4934
+ center.setLeftBeamCount(0);
4935
+ center.setRightBeamCount(0);
4936
+ if (left && left.getRightBeamCount() > 0) {
4937
+ left.setRightBeamCount(0);
4938
+ fixAgain = true;
4939
+ }
4940
+ if (right && right.getLeftBeamCount() > 0) {
4941
+ right.setLeftBeamCount(0);
4942
+ fixAgain = true;
4943
+ }
4944
+ }
4945
+ }
4946
+ } while (fixAgain);
4947
+ }
4948
+ setTupletBeamCounts() {
4949
+ let type = this.getType();
4950
+ let symbols = this.getSymbols();
4951
+ if (type === 1 /* TupletBeam */) {
4952
+ symbols.forEach((s, i) => {
4953
+ if (s instanceof ObjNoteGroup) {
4954
+ s.setLeftBeamCount(i === 0 ? 0 : s.rhythmProps.flagCount);
4955
+ s.setRightBeamCount(i === symbols.length - 1 ? 0 : s.rhythmProps.flagCount);
4956
+ }
4957
+ });
4958
+ } else if (type === 2 /* TupletGroup */) {
4959
+ symbols.forEach((s) => {
4960
+ if (s instanceof ObjNoteGroup) {
4961
+ s.setLeftBeamCount(0);
4962
+ s.setRightBeamCount(0);
4963
+ }
4964
+ });
4745
4965
  }
4746
- ctx.stroke();
4747
- this.endingText.draw(renderer);
4748
4966
  }
4749
4967
  };
4750
4968
 
@@ -5189,8 +5407,147 @@ var ConnectiveProps = class {
5189
5407
  }
5190
5408
  };
5191
5409
 
5410
+ // src/score/engine/obj-tab-rhythm.ts
5411
+ var import_ts_utils_lib12 = require("@tspro/ts-utils-lib");
5412
+ var ObjTabRhythm = class extends MusicObject {
5413
+ constructor(measure, tab) {
5414
+ super(measure);
5415
+ this.measure = measure;
5416
+ this.tab = tab;
5417
+ __publicField(this, "voiceIds");
5418
+ __publicField(this, "mi");
5419
+ // Keep non-static
5420
+ __publicField(this, "tupletPartsTextObjMap", /* @__PURE__ */ new Map());
5421
+ this.voiceIds = getVoiceIds().filter((voiceId) => tab.containsVoiceId(voiceId));
5422
+ this.rect = new DivRect();
5423
+ this.mi = new MTabRhythm(this);
5424
+ }
5425
+ getMusicInterface() {
5426
+ return this.mi;
5427
+ }
5428
+ pick(x, y) {
5429
+ return this.rect.contains(x, y) ? [this] : [];
5430
+ }
5431
+ layout(renderer) {
5432
+ let columns = this.measure.getColumns();
5433
+ let numColsInVoiceId = getVoiceIds().map((voiceId) => import_ts_utils_lib12.Utils.Math.sum(columns.map((col) => col.getVoiceSymbol(voiceId) ? 1 : 0)));
5434
+ this.voiceIds.sort((a, b) => import_ts_utils_lib12.Utils.Math.cmp(numColsInVoiceId[a], numColsInVoiceId[b]));
5435
+ this.rect = new DivRect();
5436
+ }
5437
+ hasTuplets() {
5438
+ return this.measure.getBeamGroups().some((beamGroup) => beamGroup.isTuplet());
5439
+ }
5440
+ layoutFitToMeasure(renderer) {
5441
+ let { unitSize, fontSize } = renderer;
5442
+ let { measure } = this;
5443
+ let { left, right } = measure.getColumnsContentRect();
5444
+ let stemHeight = unitSize * 5;
5445
+ this.rect.left = left;
5446
+ this.rect.centerX = (left + right) / 2;
5447
+ this.rect.right = right;
5448
+ this.rect.top = this.hasTuplets() ? -fontSize : 0;
5449
+ this.rect.centerY = 0;
5450
+ this.rect.bottom = stemHeight;
5451
+ }
5452
+ offset(dx, dy) {
5453
+ this.rect.offsetInPlace(dx, dy);
5454
+ }
5455
+ draw(renderer) {
5456
+ const ctx = renderer.getCanvasContext();
5457
+ if (!ctx) {
5458
+ return;
5459
+ }
5460
+ renderer.drawDebugRect(this.rect);
5461
+ let { unitSize, lineWidth, fontSize } = renderer;
5462
+ let flagSize = unitSize;
5463
+ let dotSpace = unitSize;
5464
+ let dotWidth = unitSize * 0.25;
5465
+ let { bottom, centerY } = this.getRect();
5466
+ let stemTop = centerY;
5467
+ let stemBottom = bottom;
5468
+ let columns = this.measure.getColumns();
5469
+ for (let colId = 0; colId < columns.length; colId++) {
5470
+ let cur = columns[colId];
5471
+ let curVoiceSymbol = this.voiceIds.map((voiceId) => cur.getVoiceSymbol(voiceId)).find((sym) => sym !== void 0);
5472
+ if (!curVoiceSymbol) {
5473
+ continue;
5474
+ }
5475
+ let beamGroup = curVoiceSymbol.getBeamGroup();
5476
+ let symbols = beamGroup ? beamGroup.getSymbols() : [curVoiceSymbol];
5477
+ for (let j = 0; j < symbols.length; j++) {
5478
+ let sym = symbols[j];
5479
+ let nextSym = symbols[j + 1];
5480
+ let colX = sym.col.getRect().centerX;
5481
+ if (sym instanceof ObjNoteGroup) {
5482
+ if (sym.rhythmProps.noteSize >= 2) {
5483
+ let stemThickness = sym.rhythmProps.noteSize === 4 ? lineWidth * 2 : lineWidth;
5484
+ renderer.drawLine(colX, stemBottom, colX, stemTop, "black", stemThickness);
5485
+ }
5486
+ if (symbols.length === 1) {
5487
+ for (let i = 0; i < sym.rhythmProps.flagCount; i++) {
5488
+ renderer.drawFlag(new DivRect(colX, colX + flagSize, stemTop + i * flagSize, stemTop + (i + 2) * flagSize), "up");
5489
+ }
5490
+ }
5491
+ for (let i = 0; i < sym.rhythmProps.dotCount; i++) {
5492
+ renderer.fillCircle(colX + dotSpace * (i + 1), stemBottom - dotWidth, dotWidth);
5493
+ }
5494
+ } else if (sym instanceof ObjRest) {
5495
+ let cx = colX;
5496
+ let cy = (stemTop + stemBottom) / 2;
5497
+ let scale = 0.65;
5498
+ ctx.save();
5499
+ ctx.scale(scale, scale);
5500
+ renderer.drawRest(sym.rhythmProps.noteSize, cx / scale, cy / scale, "black");
5501
+ ctx.restore();
5502
+ for (let i = 0; i < sym.rhythmProps.dotCount; i++) {
5503
+ cx += dotSpace * 1.5;
5504
+ renderer.fillCircle(cx, cy + dotSpace, dotWidth);
5505
+ }
5506
+ }
5507
+ if (nextSym) {
5508
+ let left = sym;
5509
+ let right = nextSym;
5510
+ let leftX = left.col.getRect().centerX;
5511
+ let rightX = right.col.getRect().centerX;
5512
+ let leftBeamCount = left.hasTuplet() ? 1 : left instanceof ObjNoteGroup ? left.getRightBeamCount() : 1;
5513
+ let rightBeamCount = right.hasTuplet() ? 1 : right instanceof ObjNoteGroup ? right.getLeftBeamCount() : 1;
5514
+ let maxBeamCount = Math.max(leftBeamCount, rightBeamCount);
5515
+ for (let i = 0; i < maxBeamCount; i++) {
5516
+ let leftT = rightBeamCount > leftBeamCount && i >= leftBeamCount ? 0.75 : 0;
5517
+ let rightT = leftBeamCount > rightBeamCount && i >= rightBeamCount ? 0.25 : 1;
5518
+ renderer.drawPartialLine(leftX, stemTop + i * flagSize, rightX, stemTop + i * flagSize, leftT, rightT, "black", lineWidth * 2);
5519
+ }
5520
+ for (let i = 0; i < left.rhythmProps.dotCount; i++) {
5521
+ renderer.fillCircle(leftX + dotSpace * (i + 1), stemBottom - dotWidth, dotWidth);
5522
+ }
5523
+ for (let i = 0; i < right.rhythmProps.dotCount; i++) {
5524
+ renderer.fillCircle(rightX + dotSpace * (i + 1), stemBottom - dotWidth, dotWidth);
5525
+ }
5526
+ }
5527
+ if (beamGroup && beamGroup.isTuplet()) {
5528
+ let cx = (symbols[0].col.getRect().centerX + symbols[symbols.length - 1].col.getRect().centerX) / 2;
5529
+ let text = beamGroup.getTupletRatioText();
5530
+ let textObj = this.tupletPartsTextObjMap.get(text);
5531
+ if (!textObj) {
5532
+ this.tupletPartsTextObjMap.set(text, textObj = new ObjText(this, { text, scale: 0.75 }, 0.5, 0.5));
5533
+ textObj.layout(renderer);
5534
+ }
5535
+ textObj.offset(-textObj.getRect().centerX, -textObj.getRect().centerY);
5536
+ textObj.offset(cx, stemTop - fontSize / 2);
5537
+ textObj.draw(renderer);
5538
+ }
5539
+ if (symbols.length > 1) {
5540
+ colId = columns.indexOf(symbols[symbols.length - 1].col);
5541
+ if (colId < 0) {
5542
+ colId = columns.length;
5543
+ }
5544
+ }
5545
+ }
5546
+ }
5547
+ }
5548
+ };
5549
+
5192
5550
  // src/score/engine/obj-measure.ts
5193
- var cmp2 = (a, b) => a === b ? 0 : a < b ? -1 : 1;
5194
5551
  function validateVoiceId(voiceId) {
5195
5552
  if (typeof voiceId === "number" && getVoiceIds().indexOf(voiceId) < 0) {
5196
5553
  throw new import_core14.MusicError(import_core14.MusicErrorType.Score, "Invalid voiceId: " + voiceId);
@@ -5202,7 +5559,7 @@ function getExtensionTicks(extensionLength) {
5202
5559
  if (typeof extensionLength === "string") {
5203
5560
  extensionLength = [extensionLength];
5204
5561
  }
5205
- if (import_ts_utils_lib12.Utils.Is.isArray(extensionLength)) {
5562
+ if (import_ts_utils_lib13.Utils.Is.isArray(extensionLength)) {
5206
5563
  let totalTicks = 0;
5207
5564
  for (let i = 0; i < extensionLength.length; ) {
5208
5565
  let str = extensionLength[i];
@@ -5227,11 +5584,11 @@ function getExtensionTicks(extensionLength) {
5227
5584
  function getVerseLayoutGroupId(verse) {
5228
5585
  switch (verse) {
5229
5586
  case 1:
5230
- return 7 /* LyricsVerse1 */;
5587
+ return 8 /* LyricsVerse1 */;
5231
5588
  case 2:
5232
- return 8 /* LyricsVerse2 */;
5589
+ return 9 /* LyricsVerse2 */;
5233
5590
  case 3:
5234
- return 9 /* LyricsVerse3 */;
5591
+ return 10 /* LyricsVerse3 */;
5235
5592
  default:
5236
5593
  throw new import_core14.MusicError(import_core14.MusicErrorType.Unknown, "VerseNumber is not 1, 2 or 3.");
5237
5594
  }
@@ -5293,6 +5650,9 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5293
5650
  this.updateKeySignature();
5294
5651
  this.updateTimeSignature();
5295
5652
  this.updateTempo();
5653
+ this.row.getTabs().forEach((tab) => {
5654
+ this.addLayoutObject(new ObjTabRhythm(this, tab), tab, 0 /* TabRhythm */, 0 /* Above */);
5655
+ });
5296
5656
  }
5297
5657
  getMusicInterface() {
5298
5658
  return this.mi;
@@ -5464,7 +5824,7 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5464
5824
  this.alterKeySignature = args[0];
5465
5825
  } else if (args[0] instanceof import_theory9.Scale) {
5466
5826
  this.alterKeySignature = args[0];
5467
- } else if (import_ts_utils_lib12.Utils.Is.isNonEmptyString(args[0])) {
5827
+ } else if (import_ts_utils_lib13.Utils.Is.isNonEmptyString(args[0])) {
5468
5828
  if (args.length === 1) {
5469
5829
  this.alterKeySignature = (0, import_theory9.getScale)(args[0]);
5470
5830
  } else if (args.length === 2) {
@@ -5575,7 +5935,7 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5575
5935
  let grp = this.doc.getStaffGroup(staffTabOrGroup);
5576
5936
  if (grp && !prevGroups.includes(staffTabOrGroup)) {
5577
5937
  let curGroups = [...prevGroups, staffTabOrGroup];
5578
- (import_ts_utils_lib12.Utils.Is.isArray(grp.staffsTabsAndGroups) ? grp.staffsTabsAndGroups : [grp.staffsTabsAndGroups]).forEach((staffTabOrGroup2) => {
5938
+ (import_ts_utils_lib13.Utils.Is.isArray(grp.staffsTabsAndGroups) ? grp.staffsTabsAndGroups : [grp.staffsTabsAndGroups]).forEach((staffTabOrGroup2) => {
5579
5939
  switch (grp.verticalPosition) {
5580
5940
  case "above" /* Above */:
5581
5941
  addToStaffTabOrGroup(staffTabOrGroup2, 0 /* Above */, curGroups);
@@ -5597,12 +5957,12 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5597
5957
  }
5598
5958
  };
5599
5959
  if (staffTabOrGroups === void 0) {
5600
- if (lines.length >= 2 && lines[0] instanceof ObjStaff && lines[0].staffConfig.clef === "G" /* G */ && lines[0].isGrand() && lines[1] instanceof ObjStaff && lines[1].staffConfig.clef === "F" /* F */ && lines[1].isGrand()) {
5960
+ if (lines.length >= 2 && lines[0] instanceof ObjStaff && lines[1] instanceof ObjStaff && lines[0].staffConfig.grandId !== void 0 && lines[0].staffConfig.grandId === lines[1].staffConfig.grandId) {
5601
5961
  addToStaffTabOrGroup(defaultVerticalPos === 1 /* Below */ ? 1 : 0, defaultVerticalPos);
5602
5962
  } else {
5603
5963
  addToStaffTabOrGroup(0, defaultVerticalPos);
5604
5964
  }
5605
- } else if (import_ts_utils_lib12.Utils.Is.isArray(staffTabOrGroups)) {
5965
+ } else if (import_ts_utils_lib13.Utils.Is.isArray(staffTabOrGroups)) {
5606
5966
  staffTabOrGroups.forEach((staffTabOrGroup) => addToStaffTabOrGroup(staffTabOrGroup, defaultVerticalPos));
5607
5967
  } else {
5608
5968
  addToStaffTabOrGroup(staffTabOrGroups, defaultVerticalPos);
@@ -5614,7 +5974,7 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5614
5974
  throw new import_core14.MusicError(import_core14.MusicErrorType.Score, "Cannot add Fermata because anchor is undefined.");
5615
5975
  }
5616
5976
  this.forEachStaffGroup(staffTabOrGroups, 0 /* Above */, (line, vpos) => {
5617
- this.addLayoutObject(new ObjFermata(anchor, vpos), line, 0 /* Fermata */, vpos);
5977
+ this.addLayoutObject(new ObjFermata(anchor, vpos), line, 1 /* Fermata */, vpos);
5618
5978
  });
5619
5979
  this.disableExtension();
5620
5980
  this.requestLayout();
@@ -5633,7 +5993,7 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5633
5993
  let passages = args;
5634
5994
  addLayoutObjectProps = {
5635
5995
  createObj: () => new ObjEnding(anchor, passages),
5636
- layoutGroupId: 3 /* Ending */,
5996
+ layoutGroupId: 4 /* Ending */,
5637
5997
  defaultVerticalPos: 0 /* Above */
5638
5998
  };
5639
5999
  break;
@@ -5645,7 +6005,7 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5645
6005
  let text = getNavigationString(navigation);
5646
6006
  addLayoutObjectProps = {
5647
6007
  createObj: () => new ObjText(anchor2, text, 1, 1),
5648
- layoutGroupId: 2 /* Navigation */,
6008
+ layoutGroupId: 3 /* Navigation */,
5649
6009
  defaultVerticalPos: 0 /* Above */
5650
6010
  };
5651
6011
  this.addNavigation(staffTabOrGroups, "endRepeat" /* EndRepeat */);
@@ -5657,7 +6017,7 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5657
6017
  let text = getNavigationString(navigation);
5658
6018
  addLayoutObjectProps = {
5659
6019
  createObj: () => new ObjText(anchor2, text, 1, 1),
5660
- layoutGroupId: 2 /* Navigation */,
6020
+ layoutGroupId: 3 /* Navigation */,
5661
6021
  defaultVerticalPos: 0 /* Above */
5662
6022
  };
5663
6023
  break;
@@ -5668,7 +6028,7 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5668
6028
  let text = getNavigationString(navigation);
5669
6029
  addLayoutObjectProps = {
5670
6030
  createObj: () => new ObjSpecialText(anchor2, text),
5671
- layoutGroupId: 2 /* Navigation */,
6031
+ layoutGroupId: 3 /* Navigation */,
5672
6032
  defaultVerticalPos: 0 /* Above */
5673
6033
  };
5674
6034
  break;
@@ -5678,7 +6038,7 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5678
6038
  let text = getNavigationString(navigation);
5679
6039
  addLayoutObjectProps = {
5680
6040
  createObj: () => new ObjSpecialText(anchor2, text),
5681
- layoutGroupId: 2 /* Navigation */,
6041
+ layoutGroupId: 3 /* Navigation */,
5682
6042
  defaultVerticalPos: 0 /* Above */
5683
6043
  };
5684
6044
  break;
@@ -5686,7 +6046,7 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5686
6046
  case "endRepeat" /* EndRepeat */:
5687
6047
  if (args.length === 0) {
5688
6048
  this.endRepeatPlayCount = 2;
5689
- } else if (import_ts_utils_lib12.Utils.Is.isIntegerGte(args[0], 2)) {
6049
+ } else if (import_ts_utils_lib13.Utils.Is.isIntegerGte(args[0], 2)) {
5690
6050
  this.endRepeatPlayCount = args[0];
5691
6051
  } else {
5692
6052
  throw new import_core14.MusicError(import_core14.MusicErrorType.Score, "Invalid end repeat play count (should be 2 or greater integer): " + args[0]);
@@ -5723,12 +6083,12 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5723
6083
  let defaultVerticalPos;
5724
6084
  switch (annotation) {
5725
6085
  case "dynamics" /* Dynamics */:
5726
- layoutGroupId = 5 /* DynamicsAnnotation */;
6086
+ layoutGroupId = 6 /* DynamicsAnnotation */;
5727
6087
  defaultVerticalPos = 0 /* Above */;
5728
6088
  textProps.italic = true;
5729
6089
  break;
5730
6090
  case "tempo" /* Tempo */:
5731
- layoutGroupId = 4 /* TempoAnnotation */;
6091
+ layoutGroupId = 5 /* TempoAnnotation */;
5732
6092
  defaultVerticalPos = 0 /* Above */;
5733
6093
  textProps.italic = true;
5734
6094
  break;
@@ -5752,11 +6112,11 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5752
6112
  let defaultVerticalPos;
5753
6113
  switch (label) {
5754
6114
  case "note" /* Note */:
5755
- layoutGroupId = 1 /* NoteLabel */;
6115
+ layoutGroupId = 2 /* NoteLabel */;
5756
6116
  defaultVerticalPos = 1 /* Below */;
5757
6117
  break;
5758
6118
  case "chord" /* Chord */:
5759
- layoutGroupId = 6 /* ChordLabel */;
6119
+ layoutGroupId = 7 /* ChordLabel */;
5760
6120
  defaultVerticalPos = 0 /* Above */;
5761
6121
  break;
5762
6122
  }
@@ -5773,15 +6133,15 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5773
6133
  throw new import_core14.MusicError(import_core14.MusicErrorType.Score, "Connective can be added to note group only.");
5774
6134
  }
5775
6135
  if (connective === "tie" /* Tie */) {
5776
- let tieSpan = import_ts_utils_lib12.Utils.Is.isInteger(args[0]) || import_ts_utils_lib12.Utils.Is.isEnumValue(args[0], TieType) ? args[0] : 2;
5777
- let noteAnchor = import_ts_utils_lib12.Utils.Is.isEnumValue(args[1], NoteAnchor) ? args[1] : "auto" /* Auto */;
6136
+ let tieSpan = import_ts_utils_lib13.Utils.Is.isInteger(args[0]) || import_ts_utils_lib13.Utils.Is.isEnumValue(args[0], TieType) ? args[0] : 2;
6137
+ let noteAnchor = import_ts_utils_lib13.Utils.Is.isEnumValue(args[1], NoteAnchor) ? args[1] : "auto" /* Auto */;
5778
6138
  anchor.startConnective(new ConnectiveProps("tie" /* Tie */, tieSpan, noteAnchor, anchor));
5779
6139
  } else if (connective === "slur" /* Slur */) {
5780
- let slurSpan = import_ts_utils_lib12.Utils.Is.isInteger(args[0]) ? args[0] : 2;
5781
- let noteAnchor = import_ts_utils_lib12.Utils.Is.isEnumValue(args[1], NoteAnchor) ? args[1] : "auto" /* Auto */;
6140
+ let slurSpan = import_ts_utils_lib13.Utils.Is.isInteger(args[0]) ? args[0] : 2;
6141
+ let noteAnchor = import_ts_utils_lib13.Utils.Is.isEnumValue(args[1], NoteAnchor) ? args[1] : "auto" /* Auto */;
5782
6142
  anchor.startConnective(new ConnectiveProps("slur" /* Slur */, slurSpan, noteAnchor, anchor));
5783
6143
  } else if (connective === "slide" /* Slide */) {
5784
- let noteAnchor = import_ts_utils_lib12.Utils.Is.isEnumValue(args[0], NoteAnchor) ? args[0] : "auto" /* Auto */;
6144
+ let noteAnchor = import_ts_utils_lib13.Utils.Is.isEnumValue(args[0], NoteAnchor) ? args[0] : "auto" /* Auto */;
5785
6145
  anchor.startConnective(new ConnectiveProps("slide" /* Slide */, 2, noteAnchor, anchor));
5786
6146
  }
5787
6147
  }
@@ -5869,7 +6229,7 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5869
6229
  let lyricsObj = new ObjLyrics(col, verse, line, vpos, lyricsText, lyricsOptions);
5870
6230
  let lyricsArr = this.getLyricsObjects(lyricsObj.line, lyricsObj.vpos, lyricsObj.verse);
5871
6231
  lyricsArr.push(lyricsObj);
5872
- lyricsArr.sort((a, b) => cmp2(a.col.positionTicks, b.col.positionTicks));
6232
+ lyricsArr.sort((a, b) => import_ts_utils_lib13.Utils.Math.cmp(a.col.positionTicks, b.col.positionTicks));
5873
6233
  lyricsContainer.addLyricsObject(lyricsObj);
5874
6234
  this.addLayoutObject(lyricsObj, line, getVerseLayoutGroupId(verse), vpos);
5875
6235
  }
@@ -5955,18 +6315,15 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5955
6315
  getLyricsObjects(line, vpos, verse) {
5956
6316
  let vposMap = this.lyricsObjectsCache.get(line);
5957
6317
  if (vposMap === void 0) {
5958
- vposMap = /* @__PURE__ */ new Map();
5959
- this.lyricsObjectsCache.set(line, vposMap);
6318
+ this.lyricsObjectsCache.set(line, vposMap = /* @__PURE__ */ new Map());
5960
6319
  }
5961
6320
  let verseMap = vposMap.get(vpos);
5962
6321
  if (verseMap === void 0) {
5963
- verseMap = /* @__PURE__ */ new Map();
5964
- vposMap.set(vpos, verseMap);
6322
+ vposMap.set(vpos, verseMap = /* @__PURE__ */ new Map());
5965
6323
  }
5966
6324
  let lyricsArr = verseMap.get(verse);
5967
6325
  if (lyricsArr === void 0) {
5968
- lyricsArr = [];
5969
- verseMap.set(verse, lyricsArr);
6326
+ verseMap.set(verse, lyricsArr = []);
5970
6327
  }
5971
6328
  return lyricsArr;
5972
6329
  }
@@ -6061,6 +6418,9 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
6061
6418
  }
6062
6419
  this.requestLayout();
6063
6420
  }
6421
+ getBeamGroups() {
6422
+ return this.beamGroups;
6423
+ }
6064
6424
  createBeams() {
6065
6425
  if (!this.needBeamsUpdate) {
6066
6426
  return;
@@ -6079,72 +6439,44 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
6079
6439
  }
6080
6440
  getVoiceIds().forEach((voiceId) => {
6081
6441
  let symbols = this.getVoiceSymbols(voiceId).slice();
6082
- if (symbols.length >= 2) {
6083
- let symbolsStartTicks = this.isUpBeat() ? Math.max(0, this.getMeasureTicks() - this.getConsumedTicks()) : 0;
6084
- let groupStartTicks = 0;
6085
- for (let groupId = 0; groupId < ts.beamGroupSizes.length; groupId++) {
6086
- let beamGroupSize = ts.beamGroupSizes[groupId];
6087
- let groupSizeSum = 0;
6088
- beamGroupSize.forEach((s) => groupSizeSum += s);
6089
- let groupLength = groupSizeSum * import_theory9.NoteLengthProps.get("8n").ticks;
6090
- let groupSymbols = [];
6091
- let groupSymbolsLength = 0;
6092
- while (symbols.length > 0 && groupSymbolsLength < groupLength) {
6093
- let symbol = symbols[0];
6094
- if (symbol.col.positionTicks >= groupStartTicks) {
6095
- groupSymbols.push(symbol);
6096
- groupSymbolsLength += symbol.rhythmProps.ticks;
6097
- symbols.shift();
6098
- } else {
6099
- break;
6442
+ if (symbols.length < 2) {
6443
+ return;
6444
+ }
6445
+ let upBeatStartTicks = this.isUpBeat() ? Math.max(0, this.getMeasureTicks() - this.getConsumedTicks()) : 0;
6446
+ let groupStartTicks = 0;
6447
+ for (let groupId = 0; groupId < ts.beamGroupSizes.length; groupId++) {
6448
+ let beamGroupSize = ts.beamGroupSizes[groupId];
6449
+ let beamGroupSizeList = [beamGroupSize];
6450
+ if (beamGroupSize.length > 1) {
6451
+ beamGroupSizeList.unshift([import_ts_utils_lib13.Utils.Math.sum(beamGroupSize)]);
6452
+ }
6453
+ let beamCreated = false;
6454
+ let groupStartTicksSave = groupStartTicks;
6455
+ while (beamGroupSizeList.length > 0 && !beamCreated) {
6456
+ let beamGroupSize2 = beamGroupSizeList.shift();
6457
+ groupStartTicks = groupStartTicksSave;
6458
+ beamGroupSize2.forEach((beamGroupSize3) => {
6459
+ let beamGroupTicks = beamGroupSize3 * import_theory9.NoteLengthProps.get("8n").ticks;
6460
+ let groupEndTicks = groupStartTicks + beamGroupTicks;
6461
+ let groupSymbols = symbols.filter((symbol) => {
6462
+ let symbolStartTicks = upBeatStartTicks + symbol.col.positionTicks;
6463
+ let symbolEndTicks = symbolStartTicks + symbol.rhythmProps.ticks;
6464
+ return symbolStartTicks >= groupStartTicks && symbolEndTicks <= groupEndTicks;
6465
+ });
6466
+ let groupSymbolsTicks = import_ts_utils_lib13.Utils.Math.sum(groupSymbols.map((sym) => sym.rhythmProps.ticks));
6467
+ if (groupSymbolsTicks === beamGroupTicks && groupSymbols.every((n) => n instanceof ObjNoteGroup) && (groupSymbols.every((n) => n.rhythmProps.flagCount === 1) || beamGroupSizeList.length === 0)) {
6468
+ if (ObjBeamGroup.createBeam(groupSymbols)) {
6469
+ beamCreated = true;
6470
+ }
6100
6471
  }
6101
- }
6102
- _ObjMeasure.setupBeamGroup(groupSymbols, beamGroupSize);
6103
- symbolsStartTicks += groupSymbolsLength;
6104
- groupStartTicks += groupLength;
6472
+ groupStartTicks += beamGroupTicks;
6473
+ });
6105
6474
  }
6106
6475
  }
6107
6476
  });
6108
6477
  this.needBeamsUpdate = false;
6109
6478
  this.requestLayout();
6110
6479
  }
6111
- static setupBeamGroup(groupSymbols, mainBeamGroupSizeArr) {
6112
- if (mainBeamGroupSizeArr.length === 0) {
6113
- return false;
6114
- }
6115
- let groupNotes = groupSymbols.map((s) => {
6116
- var _a;
6117
- return s instanceof ObjNoteGroup && ((_a = s.getBeamGroup()) == null ? void 0 : _a.isTuplet()) !== true ? s : void 0;
6118
- });
6119
- ObjNoteGroup.setBeamCounts(groupNotes);
6120
- let beamGroupSizeArrList = [mainBeamGroupSizeArr];
6121
- if (mainBeamGroupSizeArr.length > 1) {
6122
- let sum = 0;
6123
- mainBeamGroupSizeArr.forEach((s) => sum += s);
6124
- beamGroupSizeArrList.unshift([sum]);
6125
- }
6126
- let beamsCreated = false;
6127
- while (beamGroupSizeArrList.length > 0 && !beamsCreated) {
6128
- let beamGroupSizeArr = beamGroupSizeArrList.shift();
6129
- let groupSymbolsCopy = groupSymbols.slice();
6130
- beamGroupSizeArr.forEach((beamGroupSize) => {
6131
- var _a;
6132
- let beamGroupLength = beamGroupSize * import_theory9.NoteLengthProps.get("8n").ticks;
6133
- let beamNotesLength = 0;
6134
- let beamNotes = [];
6135
- while (beamNotesLength < beamGroupLength && groupSymbolsCopy.length > 0) {
6136
- let symbol = groupSymbolsCopy.shift();
6137
- beamNotesLength += symbol.rhythmProps.ticks;
6138
- beamNotes.push(symbol instanceof ObjNoteGroup && ((_a = symbol.getBeamGroup()) == null ? void 0 : _a.isTuplet()) !== true ? symbol : void 0);
6139
- }
6140
- if (beamNotesLength === beamGroupLength && beamNotes.every((n) => n !== void 0) && (beamNotes.every((n) => n.rhythmProps.flagCount === 1) || beamGroupSizeArrList.length === 0)) {
6141
- ObjBeamGroup.createBeam(beamNotes);
6142
- beamsCreated = true;
6143
- }
6144
- });
6145
- }
6146
- return beamsCreated;
6147
- }
6148
6480
  getBarLineLeft() {
6149
6481
  return this.barLineLeft;
6150
6482
  }
@@ -6165,7 +6497,7 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
6165
6497
  this.completeRests(getVoiceIds().filter((id) => this.getConsumedTicks(id) > 0));
6166
6498
  }
6167
6499
  return;
6168
- } else if (import_ts_utils_lib12.Utils.Is.isArray(voiceId)) {
6500
+ } else if (import_ts_utils_lib13.Utils.Is.isArray(voiceId)) {
6169
6501
  voiceId.forEach((id) => this.completeRests(id));
6170
6502
  return;
6171
6503
  } else {
@@ -6212,22 +6544,30 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
6212
6544
  let showKeySignature = isFirstMeasureInRow || isAfterMeasureBreak || !!this.alterKeySignature;
6213
6545
  let showTimeSignature = !!this.alterTimeSignature;
6214
6546
  let showTempo = !!this.alterTempo;
6215
- if (showClef || showMeasureNumber || showKeySignature || showTimeSignature || showTempo) {
6216
- this.signatures = this.row.getStaves().map((staff, staffId) => {
6217
- let oldSignature = this.signatures.find((s) => s.staff === staff);
6218
- let signature = oldSignature != null ? oldSignature : new ObjSignature(this, staff);
6547
+ this.signatures = [];
6548
+ this.row.getNotationLines().forEach((line, lineId) => {
6549
+ if (line instanceof ObjStaff && (showClef || showMeasureNumber || showKeySignature || showTimeSignature || showTempo)) {
6550
+ let oldSignature = this.signatures.filter((s) => s instanceof ObjStaffSignature).find((s) => s.staff === line);
6551
+ let signature = oldSignature != null ? oldSignature : new ObjStaffSignature(this, line);
6219
6552
  signature.staff.addObject(signature);
6220
6553
  signature.updateClefImage(renderer, showClef);
6221
- signature.updateMeasureNumber(showMeasureNumber && staffId === 0);
6554
+ signature.updateMeasureNumber(showMeasureNumber && lineId === 0);
6222
6555
  signature.updateKeySignature(showKeySignature);
6223
6556
  signature.updateTimeSignature(showTimeSignature);
6224
- signature.updateTempo(showTempo && staffId === 0);
6225
- return signature;
6226
- });
6227
- } else {
6228
- this.signatures = [];
6229
- }
6230
- this.signatures.forEach((signature) => signature.layout(renderer));
6557
+ signature.updateTempo(showTempo && lineId === 0);
6558
+ signature.layout(renderer);
6559
+ this.signatures.push(signature);
6560
+ } else if (line instanceof ObjTab && (showMeasureNumber || showTimeSignature || showTempo)) {
6561
+ let oldSignature = this.signatures.filter((s) => s instanceof ObjTabSignature).find((s) => s.tab === line);
6562
+ let signature = oldSignature != null ? oldSignature : new ObjTabSignature(this, line);
6563
+ signature.tab.addObject(signature);
6564
+ signature.updateMeasureNumber(showMeasureNumber && lineId === 0);
6565
+ signature.updateTimeSignature(showTimeSignature);
6566
+ signature.updateTempo(showTempo && lineId === 0);
6567
+ signature.layout(renderer);
6568
+ this.signatures.push(signature);
6569
+ }
6570
+ });
6231
6571
  this.tabStringNotes.length = 0;
6232
6572
  if (this === this.row.getFirstMeasure()) {
6233
6573
  this.row.getTabs().forEach((tab) => {
@@ -6280,7 +6620,7 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
6280
6620
  let columnsAreaLeft = this.rect.left + this.leftSolidAreaWidth;
6281
6621
  let columnsAreaRight = this.rect.right - this.rightSolidAreaWidth;
6282
6622
  let columnsAreaWidth = columnsAreaRight - columnsAreaLeft;
6283
- let columnsWidth = import_ts_utils_lib12.Utils.Math.sum(this.columns.map((col) => col.getRect().width));
6623
+ let columnsWidth = import_ts_utils_lib13.Utils.Math.sum(this.columns.map((col) => col.getRect().width));
6284
6624
  let columnScale = columnsAreaWidth / columnsWidth;
6285
6625
  let columnLeft = columnsAreaLeft;
6286
6626
  this.columns.forEach((col) => {
@@ -6401,18 +6741,19 @@ var ObjMeasure2 = _ObjMeasure;
6401
6741
  // src/score/engine/layout-object.ts
6402
6742
  var import_core15 = require("@tspro/web-music-score/core");
6403
6743
  var WidenColumnList = [
6404
- 1 /* NoteLabel */,
6405
- 6 /* ChordLabel */
6744
+ 2 /* NoteLabel */,
6745
+ 7 /* ChordLabel */
6406
6746
  ];
6407
6747
  var RowAlignList = [
6408
- 2 /* Navigation */,
6409
- 3 /* Ending */,
6410
- 4 /* TempoAnnotation */,
6411
- 5 /* DynamicsAnnotation */,
6412
- 6 /* ChordLabel */,
6413
- 7 /* LyricsVerse1 */,
6414
- 8 /* LyricsVerse2 */,
6415
- 9 /* LyricsVerse3 */
6748
+ 0 /* TabRhythm */,
6749
+ 3 /* Navigation */,
6750
+ 4 /* Ending */,
6751
+ 5 /* TempoAnnotation */,
6752
+ 6 /* DynamicsAnnotation */,
6753
+ 7 /* ChordLabel */,
6754
+ 8 /* LyricsVerse1 */,
6755
+ 9 /* LyricsVerse2 */,
6756
+ 10 /* LyricsVerse3 */
6416
6757
  ];
6417
6758
  function requireParentMeasure(p) {
6418
6759
  while (p) {
@@ -6588,7 +6929,7 @@ var ObjNotationLine4 = class extends MusicObject {
6588
6929
  let rowLayoutObjs = layoutGroup.getLayoutObjects(verticalPos).filter((layoutObj) => !layoutObj.isPositionResolved());
6589
6930
  rowLayoutObjs.forEach((layoutObj) => {
6590
6931
  let { musicObj, anchor } = layoutObj;
6591
- if (musicObj instanceof ObjEnding || musicObj instanceof ObjExtensionLine) {
6932
+ if (musicObj instanceof ObjEnding || musicObj instanceof ObjExtensionLine || musicObj instanceof ObjTabRhythm) {
6592
6933
  musicObj.layoutFitToMeasure(renderer);
6593
6934
  } else {
6594
6935
  musicObj.offset(anchor.getRect().centerX - musicObj.getRect().centerX, 0);
@@ -6710,9 +7051,6 @@ var ObjStaff = class extends ObjNotationLine4 {
6710
7051
  containsVoiceId(voiceId) {
6711
7052
  return !this.staffConfig.voiceIds || this.staffConfig.voiceIds.includes(voiceId);
6712
7053
  }
6713
- isGrand() {
6714
- return this.staffConfig.isGrand === true;
6715
- }
6716
7054
  calcTop() {
6717
7055
  let top = this.topLineY;
6718
7056
  this.objects.forEach((o) => top = Math.min(top, o.getRect().top));
@@ -6773,7 +7111,7 @@ var ObjTab = class extends ObjNotationLine4 {
6773
7111
  __publicField(this, "tuningName");
6774
7112
  __publicField(this, "tuningStrings");
6775
7113
  __publicField(this, "mi");
6776
- if (import_ts_utils_lib13.Utils.Is.isArray(tabConfig.tuning)) {
7114
+ if (import_ts_utils_lib14.Utils.Is.isArray(tabConfig.tuning)) {
6777
7115
  this.tuningName = void 0;
6778
7116
  this.tuningStrings = tabConfig.tuning.map((noteName) => import_theory11.Note.getNote(noteName)).reverse();
6779
7117
  } else if (typeof tabConfig.tuning === "string") {
@@ -6827,10 +7165,14 @@ var ObjTab = class extends ObjNotationLine4 {
6827
7165
  return true;
6828
7166
  }
6829
7167
  calcTop() {
6830
- return this.top;
7168
+ let { top } = this;
7169
+ this.objects.forEach((o) => top = Math.min(top, o.getRect().top));
7170
+ return top;
6831
7171
  }
6832
7172
  calcBottom() {
6833
- return this.bottom;
7173
+ let { bottom } = this;
7174
+ this.objects.forEach((o) => bottom = Math.max(bottom, o.getRect().bottom));
7175
+ return bottom;
6834
7176
  }
6835
7177
  pick(x, y) {
6836
7178
  return [this];
@@ -6894,7 +7236,7 @@ var ObjScoreRow = class extends MusicObject {
6894
7236
  for (let i = 0; i < notationLines.length - 1; i++) {
6895
7237
  let treble = notationLines[i];
6896
7238
  let bass = notationLines[i + 1];
6897
- if (treble instanceof ObjStaff && treble.isGrand() && treble.staffConfig.clef === "G" /* G */ && bass instanceof ObjStaff && bass.isGrand() && bass.staffConfig.clef === "F" /* F */) {
7239
+ if (treble instanceof ObjStaff && bass instanceof ObjStaff && treble.staffConfig.grandId !== void 0 && treble.staffConfig.grandId === bass.staffConfig.grandId) {
6898
7240
  treble.joinGrandStaff(bass);
6899
7241
  bass.joinGrandStaff(treble);
6900
7242
  }
@@ -7071,17 +7413,17 @@ var ObjScoreRow = class extends MusicObject {
7071
7413
  alignStemsToBeams() {
7072
7414
  this.measures.forEach((m) => m.alignStemsToBeams());
7073
7415
  }
7074
- layoutPositionLines(renderer) {
7416
+ layoutSetNotationLines(renderer) {
7075
7417
  let { unitSize } = renderer;
7076
7418
  for (let i = 1; i < this.notationLines.length; i++) {
7077
7419
  let prev = this.notationLines[i - 1];
7078
7420
  let cur = this.notationLines[i];
7079
- if (prev instanceof ObjStaff && prev.isGrand() && prev.staffConfig.clef === "G" /* G */ && cur instanceof ObjStaff && cur.isGrand() && cur.staffConfig.clef === "F" /* F */) {
7080
- let sep = unitSize * 6;
7081
- cur.offset(0, prev.getBottomLineY() - cur.getTopLineY() + sep);
7421
+ if (prev instanceof ObjStaff && cur instanceof ObjStaff && prev.staffConfig.grandId !== void 0 && prev.staffConfig.grandId === cur.staffConfig.grandId) {
7422
+ let dy = prev.getBottomLineY() - cur.getTopLineY() + unitSize * 6;
7423
+ cur.offset(0, dy);
7082
7424
  } else {
7083
- let sep = unitSize * 3;
7084
- cur.offset(0, prev.calcBottom() - cur.calcTop() + sep);
7425
+ let dy = prev.calcBottom() - cur.calcTop() + unitSize * 3;
7426
+ cur.offset(0, dy);
7085
7427
  }
7086
7428
  }
7087
7429
  this.measures.forEach((m) => {
@@ -7228,7 +7570,8 @@ var ObjHeader = class extends MusicObject {
7228
7570
  };
7229
7571
 
7230
7572
  // src/score/engine/obj-document.ts
7231
- var import_ts_utils_lib14 = require("@tspro/ts-utils-lib");
7573
+ var import_ts_utils_lib15 = require("@tspro/ts-utils-lib");
7574
+ var import_core18 = require("@tspro/web-music-score/core");
7232
7575
  var ObjDocument = class extends MusicObject {
7233
7576
  constructor() {
7234
7577
  super(void 0);
@@ -7249,7 +7592,7 @@ var ObjDocument = class extends MusicObject {
7249
7592
  return this.mi;
7250
7593
  }
7251
7594
  setScoreConfiguration(config) {
7252
- if (import_ts_utils_lib14.Utils.Is.isEnumValue(config, StaffPreset)) {
7595
+ if (import_ts_utils_lib15.Utils.Is.isEnumValue(config, StaffPreset)) {
7253
7596
  switch (config) {
7254
7597
  default:
7255
7598
  case "treble" /* Treble */:
@@ -7260,8 +7603,8 @@ var ObjDocument = class extends MusicObject {
7260
7603
  break;
7261
7604
  case "grand" /* Grand */:
7262
7605
  this.curScoreConfig = [
7263
- { type: "staff", clef: "G" /* G */, isGrand: true },
7264
- { type: "staff", clef: "F" /* F */, isGrand: true }
7606
+ { type: "staff", clef: "G" /* G */, grandId: "grand1" },
7607
+ { type: "staff", clef: "F" /* F */, grandId: "grand1" }
7265
7608
  ];
7266
7609
  break;
7267
7610
  case "guitarTreble" /* GuitarTreble */:
@@ -7277,26 +7620,57 @@ var ObjDocument = class extends MusicObject {
7277
7620
  ];
7278
7621
  break;
7279
7622
  }
7280
- } else if (import_ts_utils_lib14.Utils.Is.isArray(config)) {
7623
+ } else if (import_ts_utils_lib15.Utils.Is.isArray(config)) {
7281
7624
  this.curScoreConfig = config;
7282
7625
  } else {
7283
7626
  this.curScoreConfig = [config];
7284
7627
  }
7285
- for (let i = 0; i < this.curScoreConfig.length - 1; i++) {
7286
- let treble = this.curScoreConfig[i];
7287
- let bass = this.curScoreConfig[i + 1];
7288
- if (treble.type === "staff" && bass.type === "staff") {
7289
- if (treble.clef === "G" /* G */ && treble.isGrand && bass.clef === "F" /* F */ && bass.isGrand) {
7290
- treble.minNote = "C4";
7291
- bass.maxNote = "B3";
7292
- treble.isOctaveDown = bass.isOctaveDown = false;
7628
+ for (let cfgId = 0, grandId = "grand"; cfgId < this.curScoreConfig.length; ) {
7629
+ let treble = this.curScoreConfig[cfgId];
7630
+ let bass = this.curScoreConfig[cfgId + 1];
7631
+ while (this.curScoreConfig.filter((cfg) => cfg.type === "staff").findIndex((cfg) => cfg.grandId === grandId) >= 0) {
7632
+ grandId += "A";
7633
+ }
7634
+ if (treble && treble.type === "staff" && treble.isGrand) {
7635
+ if (treble.grandId !== void 0) {
7636
+ throw new import_core18.MusicError(import_core18.MusicErrorType.Score, `Grand staff error: mixing isGrand and grandId!`);
7637
+ } else if (bass && bass.type === "staff" && bass.isGrand) {
7638
+ if (bass.grandId !== void 0) {
7639
+ throw new import_core18.MusicError(import_core18.MusicErrorType.Score, `Grand staff error: mixing isGrand and grandId!`);
7640
+ } else {
7641
+ treble.grandId = grandId;
7642
+ bass.grandId = grandId;
7643
+ treble.isGrand = bass.isGrand = false;
7644
+ cfgId += 2;
7645
+ }
7293
7646
  } else {
7294
- treble.isGrand = bass.isGrand = false;
7647
+ throw new import_core18.MusicError(import_core18.MusicErrorType.Score, `Grand staff error: invalid use of isGrand!`);
7648
+ }
7649
+ } else {
7650
+ cfgId++;
7651
+ }
7652
+ }
7653
+ for (let cfgId = 0, usedGrandIdes = []; cfgId < this.curScoreConfig.length; ) {
7654
+ let treble = this.curScoreConfig[cfgId];
7655
+ let bass = this.curScoreConfig[cfgId + 1];
7656
+ if (treble && bass && treble.type === "staff" && bass.type === "staff" && treble.grandId !== void 0 && treble.grandId === bass.grandId) {
7657
+ if (usedGrandIdes.includes(treble.grandId)) {
7658
+ throw new import_core18.MusicError(import_core18.MusicErrorType.Score, `Grand staff error: grandId "${treble.grandId}" already used!`);
7659
+ } else if (treble.clef !== "G" /* G */) {
7660
+ throw new import_core18.MusicError(import_core18.MusicErrorType.Score, `Grand staff error: Invalid treble clef "${treble.clef}"!`);
7661
+ } else if (bass.clef !== "F" /* F */) {
7662
+ throw new import_core18.MusicError(import_core18.MusicErrorType.Score, `Grand staff error: Invalid treble clef "${treble.clef}"!`);
7663
+ } else if (treble.isOctaveDown || bass.isOctaveDown) {
7664
+ throw new import_core18.MusicError(import_core18.MusicErrorType.Score, `Grand staff error: cannot use isOctaveDown option!`);
7295
7665
  }
7296
- } else if (treble.type === "staff") {
7297
- treble.isGrand = false;
7298
- } else if (bass.type === "staff") {
7299
- bass.isGrand = false;
7666
+ usedGrandIdes.push(treble.grandId);
7667
+ treble.minNote = "C4";
7668
+ bass.maxNote = "B3";
7669
+ cfgId += 2;
7670
+ } else if (treble && treble.type === "staff" && treble.grandId !== void 0) {
7671
+ throw new import_core18.MusicError(import_core18.MusicErrorType.Score, `Grand staff error: invalid use of grandId "${treble.grandId}"!`);
7672
+ } else {
7673
+ cfgId++;
7300
7674
  }
7301
7675
  }
7302
7676
  this.requestNewRow();
@@ -7439,7 +7813,7 @@ var ObjDocument = class extends MusicObject {
7439
7813
  );
7440
7814
  this.rows.forEach((row) => row.layoutWidth(renderer, rowWidth));
7441
7815
  this.rows.forEach((row) => row.layoutLayoutGroups(renderer));
7442
- this.rows.forEach((row) => row.layoutPositionLines(renderer));
7816
+ this.rows.forEach((row) => row.layoutSetNotationLines(renderer));
7443
7817
  this.rows.forEach((row) => row.layoutPadding(renderer));
7444
7818
  this.rect = new DivRect();
7445
7819
  if (this.header) {
@@ -7504,10 +7878,10 @@ var ObjDocument = class extends MusicObject {
7504
7878
 
7505
7879
  // src/score/pub/document-builder.ts
7506
7880
  var import_theory13 = require("@tspro/web-music-score/theory");
7507
- var import_core18 = require("@tspro/web-music-score/core");
7881
+ var import_core19 = require("@tspro/web-music-score/core");
7508
7882
  function assertArg(condition, argName, argValue) {
7509
7883
  if (!condition) {
7510
- throw new import_core18.MusicError(import_core18.MusicErrorType.Score, `Invalid arg: ${argName} = ${argValue}`);
7884
+ throw new import_core19.MusicError(import_core19.MusicErrorType.Score, `Invalid arg: ${argName} = ${argValue}`);
7511
7885
  }
7512
7886
  }
7513
7887
  function isNote(note) {
@@ -7519,64 +7893,70 @@ function isNote(note) {
7519
7893
  }
7520
7894
  }
7521
7895
  function isVoiceId(value) {
7522
- return import_ts_utils_lib15.Utils.Is.isNumber(value) && getVoiceIds().indexOf(value) >= 0;
7896
+ return import_ts_utils_lib16.Utils.Is.isNumber(value) && getVoiceIds().indexOf(value) >= 0;
7523
7897
  }
7524
7898
  function isStringNumber(value) {
7525
- return import_ts_utils_lib15.Utils.Is.isNumber(value) && getStringNumbers().indexOf(value) >= 0;
7899
+ return import_ts_utils_lib16.Utils.Is.isNumber(value) && getStringNumbers().indexOf(value) >= 0;
7526
7900
  }
7527
7901
  function isVerseNumber(value) {
7528
- return import_ts_utils_lib15.Utils.Is.isNumber(value) && getVerseNumbers().indexOf(value) >= 0;
7902
+ return import_ts_utils_lib16.Utils.Is.isNumber(value) && getVerseNumbers().indexOf(value) >= 0;
7903
+ }
7904
+ function assertBaseConfig(baseConfig) {
7905
+ assertArg(import_ts_utils_lib16.Utils.Is.isObject(baseConfig), "baseConfig", baseConfig);
7906
+ assertArg(import_ts_utils_lib16.Utils.Is.isStringOrUndefined(baseConfig.name), "baseConfig.name", baseConfig.name);
7907
+ assertArg(import_ts_utils_lib16.Utils.Is.isUndefined(baseConfig.voiceIds) || import_ts_utils_lib16.Utils.Is.isArray(baseConfig.voiceIds) && baseConfig.voiceIds.every((voiceId) => import_ts_utils_lib16.Utils.Is.isNumber(voiceId)), "baseConfig.voiceIds", baseConfig.voiceIds);
7529
7908
  }
7530
7909
  function assertStaffConfig(staffConfig) {
7531
- assertArg(import_ts_utils_lib15.Utils.Is.isObject(staffConfig), "staffConfig", staffConfig);
7910
+ assertBaseConfig(staffConfig);
7911
+ assertArg(import_ts_utils_lib16.Utils.Is.isObject(staffConfig), "staffConfig", staffConfig);
7532
7912
  assertArg(staffConfig.type === "staff", "staffConfig.type", staffConfig.type);
7533
- assertArg(import_ts_utils_lib15.Utils.Is.isEnumValue(staffConfig.clef, Clef), "staffConfig.clef", staffConfig.clef);
7534
- assertArg(import_ts_utils_lib15.Utils.Is.isBooleanOrUndefined(staffConfig.isOctaveDown), "staffConfig.isOctaveDown", staffConfig.isOctaveDown);
7535
- assertArg(import_ts_utils_lib15.Utils.Is.isUndefined(staffConfig.minNote) || isNote(staffConfig.minNote), "staffConfig.minNote", staffConfig.minNote);
7536
- assertArg(import_ts_utils_lib15.Utils.Is.isUndefined(staffConfig.maxNote) || isNote(staffConfig.maxNote), "staffConfig.maxNote", staffConfig.maxNote);
7537
- assertArg(import_ts_utils_lib15.Utils.Is.isUndefined(staffConfig.voiceIds) || import_ts_utils_lib15.Utils.Is.isArray(staffConfig.voiceIds) && staffConfig.voiceIds.every((voiceId) => import_ts_utils_lib15.Utils.Is.isNumber(voiceId)), "staffConfig.voiceIds", staffConfig.voiceIds);
7538
- assertArg(import_ts_utils_lib15.Utils.Is.isBooleanOrUndefined(staffConfig.isGrand), "staffConfig.isGrand", staffConfig.isGrand);
7913
+ assertArg(import_ts_utils_lib16.Utils.Is.isEnumValue(staffConfig.clef, Clef), "staffConfig.clef", staffConfig.clef);
7914
+ assertArg(import_ts_utils_lib16.Utils.Is.isBooleanOrUndefined(staffConfig.isOctaveDown), "staffConfig.isOctaveDown", staffConfig.isOctaveDown);
7915
+ assertArg(import_ts_utils_lib16.Utils.Is.isUndefined(staffConfig.minNote) || isNote(staffConfig.minNote), "staffConfig.minNote", staffConfig.minNote);
7916
+ assertArg(import_ts_utils_lib16.Utils.Is.isUndefined(staffConfig.maxNote) || isNote(staffConfig.maxNote), "staffConfig.maxNote", staffConfig.maxNote);
7917
+ assertArg(import_ts_utils_lib16.Utils.Is.isStringOrUndefined(staffConfig.grandId), "staffConfig.grandId", staffConfig.grandId);
7918
+ assertArg(import_ts_utils_lib16.Utils.Is.isBooleanOrUndefined(staffConfig.isGrand), "staffConfig.isGrand", staffConfig.isGrand);
7539
7919
  }
7540
7920
  function assertTabConfig(tabConfig) {
7541
- assertArg(import_ts_utils_lib15.Utils.Is.isObject(tabConfig), "tabConfig", tabConfig);
7921
+ assertBaseConfig(tabConfig);
7922
+ assertArg(import_ts_utils_lib16.Utils.Is.isObject(tabConfig), "tabConfig", tabConfig);
7542
7923
  assertArg(tabConfig.type === "tab", "tabConfig.type", tabConfig.type);
7543
- if (typeof tabConfig.tuning === "string") {
7924
+ if (import_ts_utils_lib16.Utils.Is.isString(tabConfig.tuning)) {
7544
7925
  assertArg(import_theory13.TuningNameList.includes(tabConfig.tuning), "tabConfig.tuning", tabConfig.tuning);
7545
- } else if (import_ts_utils_lib15.Utils.Is.isArray(tabConfig.tuning)) {
7926
+ } else if (import_ts_utils_lib16.Utils.Is.isArray(tabConfig.tuning)) {
7546
7927
  assertArg(tabConfig.tuning.length === getStringNumbers().length && tabConfig.tuning.every((s) => isNote(s)), "tabConfig.tuning", tabConfig.tuning);
7547
7928
  }
7548
- assertArg(import_ts_utils_lib15.Utils.Is.isUndefined(tabConfig.voiceIds) || import_ts_utils_lib15.Utils.Is.isArray(tabConfig.voiceIds) && tabConfig.voiceIds.every((voiceId) => import_ts_utils_lib15.Utils.Is.isNumber(voiceId)), "tabConfig.voiceIds", tabConfig.voiceIds);
7549
7929
  }
7550
7930
  function assertNoteOptions(noteOptions) {
7551
- assertArg(import_ts_utils_lib15.Utils.Is.isObject(noteOptions), "noteOptions", noteOptions);
7552
- assertArg(import_ts_utils_lib15.Utils.Is.isBooleanOrUndefined(noteOptions.dotted) || import_ts_utils_lib15.Utils.Is.isIntegerGte(noteOptions.dotted, 0), "noteOptions.dotted", noteOptions.dotted);
7553
- assertArg(import_ts_utils_lib15.Utils.Is.isEnumValueOrUndefined(noteOptions.stem, Stem), "noteOptions.stem", noteOptions.stem);
7554
- assertArg(import_ts_utils_lib15.Utils.Is.isStringOrUndefined(noteOptions.color), "noteOptions.color", noteOptions.color);
7555
- assertArg(import_ts_utils_lib15.Utils.Is.isBooleanOrUndefined(noteOptions.arpeggio) || import_ts_utils_lib15.Utils.Is.isEnumValue(noteOptions.arpeggio, Arpeggio), "noteOptions.arpeggio", noteOptions.arpeggio);
7556
- assertArg(import_ts_utils_lib15.Utils.Is.isBooleanOrUndefined(noteOptions.staccato), "noteOptions.staccato", noteOptions.staccato);
7557
- assertArg(import_ts_utils_lib15.Utils.Is.isBooleanOrUndefined(noteOptions.diamond), "noteOptions.diamond", noteOptions.diamond);
7558
- assertArg(import_ts_utils_lib15.Utils.Is.isBooleanOrUndefined(noteOptions.triplet), "noteOptions.triplet", noteOptions.triplet);
7559
- assertArg(import_ts_utils_lib15.Utils.Is.isUndefined(noteOptions.string) || isStringNumber(noteOptions.string) || import_ts_utils_lib15.Utils.Is.isNonEmptyArray(noteOptions.string) && noteOptions.string.every((string) => isStringNumber(string)), "noteOptions.string", noteOptions.string);
7560
- assertArg(import_ts_utils_lib15.Utils.Is.isUndefined(noteOptions.tieSpan), 'NoteOptions.tieSpan was removed. Use addConnective("tie", tieSpan)', "");
7561
- assertArg(import_ts_utils_lib15.Utils.Is.isUndefined(noteOptions.slurSpan), 'NoteOptions.slurSpan was removed. Use addConnective("slur", slurSpan)', "");
7931
+ assertArg(import_ts_utils_lib16.Utils.Is.isObject(noteOptions), "noteOptions", noteOptions);
7932
+ assertArg(import_ts_utils_lib16.Utils.Is.isBooleanOrUndefined(noteOptions.dotted) || import_ts_utils_lib16.Utils.Is.isIntegerGte(noteOptions.dotted, 0), "noteOptions.dotted", noteOptions.dotted);
7933
+ assertArg(import_ts_utils_lib16.Utils.Is.isEnumValueOrUndefined(noteOptions.stem, Stem), "noteOptions.stem", noteOptions.stem);
7934
+ assertArg(import_ts_utils_lib16.Utils.Is.isStringOrUndefined(noteOptions.color), "noteOptions.color", noteOptions.color);
7935
+ assertArg(import_ts_utils_lib16.Utils.Is.isBooleanOrUndefined(noteOptions.arpeggio) || import_ts_utils_lib16.Utils.Is.isEnumValue(noteOptions.arpeggio, Arpeggio), "noteOptions.arpeggio", noteOptions.arpeggio);
7936
+ assertArg(import_ts_utils_lib16.Utils.Is.isBooleanOrUndefined(noteOptions.staccato), "noteOptions.staccato", noteOptions.staccato);
7937
+ assertArg(import_ts_utils_lib16.Utils.Is.isBooleanOrUndefined(noteOptions.diamond), "noteOptions.diamond", noteOptions.diamond);
7938
+ assertArg(import_ts_utils_lib16.Utils.Is.isBooleanOrUndefined(noteOptions.triplet), "noteOptions.triplet", noteOptions.triplet);
7939
+ assertArg(import_ts_utils_lib16.Utils.Is.isUndefined(noteOptions.string) || isStringNumber(noteOptions.string) || import_ts_utils_lib16.Utils.Is.isNonEmptyArray(noteOptions.string) && noteOptions.string.every((string) => isStringNumber(string)), "noteOptions.string", noteOptions.string);
7940
+ assertArg(import_ts_utils_lib16.Utils.Is.isUndefined(noteOptions.tieSpan), 'NoteOptions.tieSpan was removed. Use addConnective("tie", tieSpan)', "");
7941
+ assertArg(import_ts_utils_lib16.Utils.Is.isUndefined(noteOptions.slurSpan), 'NoteOptions.slurSpan was removed. Use addConnective("slur", slurSpan)', "");
7562
7942
  }
7563
7943
  function assertRestOptions(restOptions) {
7564
- assertArg(import_ts_utils_lib15.Utils.Is.isObject(restOptions), "restOptions", restOptions);
7565
- assertArg(import_ts_utils_lib15.Utils.Is.isBooleanOrUndefined(restOptions.dotted) || import_ts_utils_lib15.Utils.Is.isIntegerGte(restOptions.dotted, 0), "restOptions.dotted", restOptions.dotted);
7566
- assertArg(import_ts_utils_lib15.Utils.Is.isStringOrUndefined(restOptions.staffPos) || import_ts_utils_lib15.Utils.Is.isInteger(restOptions.staffPos) || restOptions.staffPos instanceof import_theory13.Note, "restOptions.staffPos", restOptions.staffPos);
7567
- assertArg(import_ts_utils_lib15.Utils.Is.isStringOrUndefined(restOptions.color), "restOptions.color", restOptions.color);
7568
- assertArg(import_ts_utils_lib15.Utils.Is.isBooleanOrUndefined(restOptions.hide), "restOptions.hide", restOptions.hide);
7569
- assertArg(import_ts_utils_lib15.Utils.Is.isBooleanOrUndefined(restOptions.triplet), "restOptions.triplet", restOptions.triplet);
7944
+ assertArg(import_ts_utils_lib16.Utils.Is.isObject(restOptions), "restOptions", restOptions);
7945
+ assertArg(import_ts_utils_lib16.Utils.Is.isBooleanOrUndefined(restOptions.dotted) || import_ts_utils_lib16.Utils.Is.isIntegerGte(restOptions.dotted, 0), "restOptions.dotted", restOptions.dotted);
7946
+ assertArg(import_ts_utils_lib16.Utils.Is.isStringOrUndefined(restOptions.staffPos) || import_ts_utils_lib16.Utils.Is.isInteger(restOptions.staffPos) || restOptions.staffPos instanceof import_theory13.Note, "restOptions.staffPos", restOptions.staffPos);
7947
+ assertArg(import_ts_utils_lib16.Utils.Is.isStringOrUndefined(restOptions.color), "restOptions.color", restOptions.color);
7948
+ assertArg(import_ts_utils_lib16.Utils.Is.isBooleanOrUndefined(restOptions.hide), "restOptions.hide", restOptions.hide);
7949
+ assertArg(import_ts_utils_lib16.Utils.Is.isBooleanOrUndefined(restOptions.triplet), "restOptions.triplet", restOptions.triplet);
7570
7950
  }
7571
7951
  function assertLyricsOptions(lyricsOptions) {
7572
- assertArg(import_ts_utils_lib15.Utils.Is.isObject(lyricsOptions), "lyricsOptions", lyricsOptions);
7573
- assertArg(import_ts_utils_lib15.Utils.Is.isEnumValueOrUndefined(lyricsOptions.align, LyricsAlign), "lyricsOptions.align", lyricsOptions.align);
7574
- assertArg(import_ts_utils_lib15.Utils.Is.isEnumValueOrUndefined(lyricsOptions.hyphen, LyricsHyphen), "lyricsOptions.hyphen", lyricsOptions.hyphen);
7952
+ assertArg(import_ts_utils_lib16.Utils.Is.isObject(lyricsOptions), "lyricsOptions", lyricsOptions);
7953
+ assertArg(import_ts_utils_lib16.Utils.Is.isEnumValueOrUndefined(lyricsOptions.align, LyricsAlign), "lyricsOptions.align", lyricsOptions.align);
7954
+ assertArg(import_ts_utils_lib16.Utils.Is.isEnumValueOrUndefined(lyricsOptions.hyphen, LyricsHyphen), "lyricsOptions.hyphen", lyricsOptions.hyphen);
7575
7955
  }
7576
7956
  function assertStaffTabOrGRoups(staffTabOrGroups) {
7577
7957
  assertArg(
7578
- import_ts_utils_lib15.Utils.Is.isStringOrUndefined(staffTabOrGroups) || import_ts_utils_lib15.Utils.Is.isIntegerGte(staffTabOrGroups, 0) || import_ts_utils_lib15.Utils.Is.isNonEmptyArray(staffTabOrGroups) && staffTabOrGroups.every(
7579
- (staffTabOrGroup) => import_ts_utils_lib15.Utils.Is.isString(staffTabOrGroup) || import_ts_utils_lib15.Utils.Is.isIntegerGte(staffTabOrGroup, 0)
7958
+ import_ts_utils_lib16.Utils.Is.isStringOrUndefined(staffTabOrGroups) || import_ts_utils_lib16.Utils.Is.isIntegerGte(staffTabOrGroups, 0) || import_ts_utils_lib16.Utils.Is.isNonEmptyArray(staffTabOrGroups) && staffTabOrGroups.every(
7959
+ (staffTabOrGroup) => import_ts_utils_lib16.Utils.Is.isString(staffTabOrGroup) || import_ts_utils_lib16.Utils.Is.isIntegerGte(staffTabOrGroup, 0)
7580
7960
  ),
7581
7961
  "staffTabOrGroup",
7582
7962
  staffTabOrGroups
@@ -7608,19 +7988,19 @@ var DocumentBuilder = class {
7608
7988
  this.doc = new ObjDocument();
7609
7989
  }
7610
7990
  setScoreConfiguration(config) {
7611
- if (import_ts_utils_lib15.Utils.Is.isEnumValue(config, StaffPreset)) {
7991
+ if (import_ts_utils_lib16.Utils.Is.isEnumValue(config, StaffPreset)) {
7612
7992
  this.doc.setScoreConfiguration(config);
7613
- } else if (import_ts_utils_lib15.Utils.Is.isObject(config) && config.type === "staff") {
7993
+ } else if (import_ts_utils_lib16.Utils.Is.isObject(config) && config.type === "staff") {
7614
7994
  assertStaffConfig(config);
7615
7995
  this.doc.setScoreConfiguration(config);
7616
- } else if (import_ts_utils_lib15.Utils.Is.isObject(config) && config.type === "tab") {
7996
+ } else if (import_ts_utils_lib16.Utils.Is.isObject(config) && config.type === "tab") {
7617
7997
  assertTabConfig(config);
7618
7998
  this.doc.setScoreConfiguration(config);
7619
- } else if (import_ts_utils_lib15.Utils.Is.isNonEmptyArray(config)) {
7999
+ } else if (import_ts_utils_lib16.Utils.Is.isNonEmptyArray(config)) {
7620
8000
  config.forEach((c) => {
7621
- if (import_ts_utils_lib15.Utils.Is.isObject(c) && c.type === "staff") {
8001
+ if (import_ts_utils_lib16.Utils.Is.isObject(c) && c.type === "staff") {
7622
8002
  assertStaffConfig(c);
7623
- } else if (import_ts_utils_lib15.Utils.Is.isObject(c) && c.type === "tab") {
8003
+ } else if (import_ts_utils_lib16.Utils.Is.isObject(c) && c.type === "tab") {
7624
8004
  assertTabConfig(c);
7625
8005
  } else {
7626
8006
  assertArg(false, "config", config);
@@ -7651,9 +8031,9 @@ var DocumentBuilder = class {
7651
8031
  * @returns - This document builder instance.
7652
8032
  */
7653
8033
  setHeader(title, composer, arranger) {
7654
- assertArg(import_ts_utils_lib15.Utils.Is.isStringOrUndefined(title), "title", title);
7655
- assertArg(import_ts_utils_lib15.Utils.Is.isStringOrUndefined(composer), "composer", composer);
7656
- assertArg(import_ts_utils_lib15.Utils.Is.isStringOrUndefined(arranger), "arranger", arranger);
8034
+ assertArg(import_ts_utils_lib16.Utils.Is.isStringOrUndefined(title), "title", title);
8035
+ assertArg(import_ts_utils_lib16.Utils.Is.isStringOrUndefined(composer), "composer", composer);
8036
+ assertArg(import_ts_utils_lib16.Utils.Is.isStringOrUndefined(arranger), "arranger", arranger);
7657
8037
  this.doc.setHeader(title, composer, arranger);
7658
8038
  return this;
7659
8039
  }
@@ -7663,7 +8043,7 @@ var DocumentBuilder = class {
7663
8043
  * @returns - This document builder instance.
7664
8044
  */
7665
8045
  setMeasuresPerRow(measuresPerRow) {
7666
- assertArg(import_ts_utils_lib15.Utils.Is.isIntegerGte(measuresPerRow, 1) || import_ts_utils_lib15.Utils.Is.isPosInfinity(measuresPerRow), "measuresPerRow", measuresPerRow);
8046
+ assertArg(import_ts_utils_lib16.Utils.Is.isIntegerGte(measuresPerRow, 1) || import_ts_utils_lib16.Utils.Is.isPosInfinity(measuresPerRow), "measuresPerRow", measuresPerRow);
7667
8047
  this.doc.setMeasuresPerRow(measuresPerRow);
7668
8048
  return this;
7669
8049
  }
@@ -7676,16 +8056,16 @@ var DocumentBuilder = class {
7676
8056
  return this;
7677
8057
  }
7678
8058
  setKeySignature(...args) {
7679
- assertArg(args[0] instanceof import_theory13.Scale || args[0] instanceof import_theory13.KeySignature || import_ts_utils_lib15.Utils.Is.isNonEmptyString(args[0]) && (args.length === 1 || import_ts_utils_lib15.Utils.Is.isEnumValue(args[1], import_theory13.ScaleType)), "keySignature", args);
8059
+ assertArg(args[0] instanceof import_theory13.Scale || args[0] instanceof import_theory13.KeySignature || import_ts_utils_lib16.Utils.Is.isNonEmptyString(args[0]) && (args.length === 1 || import_ts_utils_lib16.Utils.Is.isEnumValue(args[1], import_theory13.ScaleType)), "keySignature", args);
7680
8060
  this.getMeasure().setKeySignature(...args);
7681
8061
  return this;
7682
8062
  }
7683
8063
  setTimeSignature(...args) {
7684
8064
  if (args[0] instanceof import_theory13.TimeSignature) {
7685
8065
  this.getMeasure().setTimeSignature(args[0]);
7686
- } else if (import_ts_utils_lib15.Utils.Is.isEnumValue(args[0], import_theory13.TimeSignatures) && import_ts_utils_lib15.Utils.Is.isEnumValueOrUndefined(args[1], import_theory13.BeamGrouping)) {
8066
+ } else if (import_ts_utils_lib16.Utils.Is.isEnumValue(args[0], import_theory13.TimeSignatures) && import_ts_utils_lib16.Utils.Is.isEnumValueOrUndefined(args[1], import_theory13.BeamGrouping)) {
7687
8067
  this.getMeasure().setTimeSignature(new import_theory13.TimeSignature(args[0], args[1]));
7688
- } else if (import_ts_utils_lib15.Utils.Is.isIntegerGte(args[0], 1) && import_ts_utils_lib15.Utils.Is.isIntegerGte(args[1], 1) && import_ts_utils_lib15.Utils.Is.isEnumValueOrUndefined(args[2], import_theory13.BeamGrouping)) {
8068
+ } else if (import_ts_utils_lib16.Utils.Is.isIntegerGte(args[0], 1) && import_ts_utils_lib16.Utils.Is.isIntegerGte(args[1], 1) && import_ts_utils_lib16.Utils.Is.isEnumValueOrUndefined(args[2], import_theory13.BeamGrouping)) {
7689
8069
  this.getMeasure().setTimeSignature(new import_theory13.TimeSignature(args[0], args[1], args[2]));
7690
8070
  } else {
7691
8071
  assertArg(false, "timeSignature args", args);
@@ -7693,12 +8073,12 @@ var DocumentBuilder = class {
7693
8073
  return this;
7694
8074
  }
7695
8075
  setTempo(beatsPerMinute, beatLength, dotted) {
7696
- assertArg(import_ts_utils_lib15.Utils.Is.isIntegerGte(beatsPerMinute, 1), "beatsPerMinute", beatsPerMinute);
8076
+ assertArg(import_ts_utils_lib16.Utils.Is.isIntegerGte(beatsPerMinute, 1), "beatsPerMinute", beatsPerMinute);
7697
8077
  if (beatLength === void 0) {
7698
- assertArg(import_ts_utils_lib15.Utils.Is.isUndefined(dotted), "dotted", dotted);
8078
+ assertArg(import_ts_utils_lib16.Utils.Is.isUndefined(dotted), "dotted", dotted);
7699
8079
  } else {
7700
- assertArg(import_ts_utils_lib15.Utils.Is.isEnumValue(beatLength, import_theory13.NoteLength) || isNoteLength(beatLength), "beatLength", beatLength);
7701
- assertArg(import_ts_utils_lib15.Utils.Is.isBooleanOrUndefined(dotted) || import_ts_utils_lib15.Utils.Is.isIntegerGte(dotted, 0), "dotted", dotted);
8080
+ assertArg(import_ts_utils_lib16.Utils.Is.isEnumValue(beatLength, import_theory13.NoteLength) || isNoteLength(beatLength), "beatLength", beatLength);
8081
+ assertArg(import_ts_utils_lib16.Utils.Is.isBooleanOrUndefined(dotted) || import_ts_utils_lib16.Utils.Is.isIntegerGte(dotted, 0), "dotted", dotted);
7702
8082
  }
7703
8083
  this.getMeasure().setTempo(beatsPerMinute, beatLength, dotted);
7704
8084
  return this;
@@ -7714,15 +8094,19 @@ var DocumentBuilder = class {
7714
8094
  addNote(voiceId, note, noteLength, noteOptions) {
7715
8095
  assertArg(isVoiceId(voiceId), "voiceId", voiceId);
7716
8096
  assertArg(
7717
- note instanceof import_theory13.Note || import_ts_utils_lib15.Utils.Is.isNonEmptyString(note) || import_ts_utils_lib15.Utils.Is.isArray(note) && note.every((note2) => note2 instanceof import_theory13.Note || import_ts_utils_lib15.Utils.Is.isNonEmptyString(note2)),
8097
+ note instanceof import_theory13.Note || import_ts_utils_lib16.Utils.Is.isNonEmptyString(note) || import_ts_utils_lib16.Utils.Is.isArray(note) && note.every((note2) => note2 instanceof import_theory13.Note || import_ts_utils_lib16.Utils.Is.isNonEmptyString(note2)),
7718
8098
  "note",
7719
8099
  note
7720
8100
  );
7721
- assertArg(import_ts_utils_lib15.Utils.Is.isEnumValue(noteLength, import_theory13.NoteLength) || isNoteLength(noteLength), "noteLength", noteLength);
8101
+ assertArg(import_ts_utils_lib16.Utils.Is.isEnumValue(noteLength, import_theory13.NoteLength) || isNoteLength(noteLength), "noteLength", noteLength);
7722
8102
  noteOptions != null ? noteOptions : noteOptions = {};
7723
8103
  assertNoteOptions(noteOptions);
7724
- if (import_ts_utils_lib15.Utils.Is.isArray(note)) {
7725
- note.forEach((note2) => this.getMeasure().addNoteGroup(voiceId, [note2], noteLength, noteOptions));
8104
+ if (import_ts_utils_lib16.Utils.Is.isArray(note)) {
8105
+ let string = noteOptions.string;
8106
+ note.forEach((note2, noteId) => {
8107
+ noteOptions.string = import_ts_utils_lib16.Utils.Is.isArray(string) ? string[noteId] : string;
8108
+ this.getMeasure().addNoteGroup(voiceId, [note2], noteLength, noteOptions);
8109
+ });
7726
8110
  } else {
7727
8111
  this.getMeasure().addNoteGroup(voiceId, [note], noteLength, noteOptions);
7728
8112
  }
@@ -7738,8 +8122,8 @@ var DocumentBuilder = class {
7738
8122
  */
7739
8123
  addChord(voiceId, notes, noteLength, noteOptions) {
7740
8124
  assertArg(isVoiceId(voiceId), "voiceId", voiceId);
7741
- assertArg(import_ts_utils_lib15.Utils.Is.isNonEmptyArray(notes) && notes.every((note) => note instanceof import_theory13.Note || import_ts_utils_lib15.Utils.Is.isNonEmptyString(note)), "notes", notes);
7742
- assertArg(import_ts_utils_lib15.Utils.Is.isEnumValue(noteLength, import_theory13.NoteLength) || isNoteLength(noteLength), "noteLength", noteLength);
8125
+ assertArg(import_ts_utils_lib16.Utils.Is.isNonEmptyArray(notes) && notes.every((note) => note instanceof import_theory13.Note || import_ts_utils_lib16.Utils.Is.isNonEmptyString(note)), "notes", notes);
8126
+ assertArg(import_ts_utils_lib16.Utils.Is.isEnumValue(noteLength, import_theory13.NoteLength) || isNoteLength(noteLength), "noteLength", noteLength);
7743
8127
  noteOptions != null ? noteOptions : noteOptions = {};
7744
8128
  assertNoteOptions(noteOptions);
7745
8129
  this.getMeasure().addNoteGroup(voiceId, notes, noteLength, noteOptions);
@@ -7754,7 +8138,7 @@ var DocumentBuilder = class {
7754
8138
  */
7755
8139
  addRest(voiceId, restLength, restOptions) {
7756
8140
  assertArg(isVoiceId(voiceId), "voiceId", voiceId);
7757
- assertArg(import_ts_utils_lib15.Utils.Is.isEnumValue(restLength, import_theory13.NoteLength) || isNoteLength(restLength), "restLength", restLength);
8141
+ assertArg(import_ts_utils_lib16.Utils.Is.isEnumValue(restLength, import_theory13.NoteLength) || isNoteLength(restLength), "restLength", restLength);
7758
8142
  restOptions != null ? restOptions : restOptions = {};
7759
8143
  assertRestOptions(restOptions);
7760
8144
  this.getMeasure().addRest(voiceId, restLength, restOptions);
@@ -7777,22 +8161,24 @@ var DocumentBuilder = class {
7777
8161
  */
7778
8162
  addTuplet(voiceId, tupletRatio, tupletBuilder) {
7779
8163
  assertArg(isVoiceId(voiceId), "voiceId", voiceId);
7780
- assertArg(import_ts_utils_lib15.Utils.Is.isFunction(tupletBuilder), "tupletBuilder", tupletBuilder);
7781
- assertArg(isTupletRatio(tupletRatio) && import_ts_utils_lib15.Utils.Is.isBooleanOrUndefined(tupletRatio.showRatio), "tupletRatio", tupletRatio);
8164
+ assertArg(import_ts_utils_lib16.Utils.Is.isFunction(tupletBuilder), "tupletBuilder", tupletBuilder);
8165
+ assertArg(isTupletRatio(tupletRatio) && import_ts_utils_lib16.Utils.Is.isBooleanOrUndefined(tupletRatio.showRatio), "tupletRatio", tupletRatio);
7782
8166
  let tupletSymbols = [];
7783
8167
  const helper = {
7784
8168
  addNote: (note, noteLength, noteOptions) => {
7785
8169
  assertArg(
7786
- note instanceof import_theory13.Note || import_ts_utils_lib15.Utils.Is.isNonEmptyString(note) || import_ts_utils_lib15.Utils.Is.isArray(note) && note.every((note2) => note2 instanceof import_theory13.Note || import_ts_utils_lib15.Utils.Is.isNonEmptyString(note2)),
8170
+ note instanceof import_theory13.Note || import_ts_utils_lib16.Utils.Is.isNonEmptyString(note) || import_ts_utils_lib16.Utils.Is.isArray(note) && note.every((note2) => note2 instanceof import_theory13.Note || import_ts_utils_lib16.Utils.Is.isNonEmptyString(note2)),
7787
8171
  "note",
7788
8172
  note
7789
8173
  );
7790
- assertArg(import_ts_utils_lib15.Utils.Is.isEnumValue(noteLength, import_theory13.NoteLength) || isNoteLength(noteLength), "noteLength", noteLength);
8174
+ assertArg(import_ts_utils_lib16.Utils.Is.isEnumValue(noteLength, import_theory13.NoteLength) || isNoteLength(noteLength), "noteLength", noteLength);
7791
8175
  noteOptions != null ? noteOptions : noteOptions = {};
7792
8176
  delete noteOptions.triplet;
7793
8177
  assertNoteOptions(noteOptions);
7794
- if (import_ts_utils_lib15.Utils.Is.isArray(note)) {
7795
- note.forEach((note2) => {
8178
+ if (import_ts_utils_lib16.Utils.Is.isArray(note)) {
8179
+ let string = noteOptions.string;
8180
+ note.forEach((note2, noteId) => {
8181
+ noteOptions.string = import_ts_utils_lib16.Utils.Is.isArray(string) ? string[noteId] : string;
7796
8182
  let s = this.getMeasure().addNoteGroup(voiceId, [note2], noteLength, noteOptions, tupletRatio);
7797
8183
  tupletSymbols.push(s);
7798
8184
  });
@@ -7803,8 +8189,8 @@ var DocumentBuilder = class {
7803
8189
  return helper;
7804
8190
  },
7805
8191
  addChord: (notes, noteLength, noteOptions) => {
7806
- assertArg(import_ts_utils_lib15.Utils.Is.isNonEmptyArray(notes) && notes.every((note) => note instanceof import_theory13.Note || import_ts_utils_lib15.Utils.Is.isNonEmptyString(note)), "notes", notes);
7807
- assertArg(import_ts_utils_lib15.Utils.Is.isEnumValue(noteLength, import_theory13.NoteLength) || isNoteLength(noteLength), "noteLength", noteLength);
8192
+ assertArg(import_ts_utils_lib16.Utils.Is.isNonEmptyArray(notes) && notes.every((note) => note instanceof import_theory13.Note || import_ts_utils_lib16.Utils.Is.isNonEmptyString(note)), "notes", notes);
8193
+ assertArg(import_ts_utils_lib16.Utils.Is.isEnumValue(noteLength, import_theory13.NoteLength) || isNoteLength(noteLength), "noteLength", noteLength);
7808
8194
  noteOptions != null ? noteOptions : noteOptions = {};
7809
8195
  delete noteOptions.triplet;
7810
8196
  assertNoteOptions(noteOptions);
@@ -7813,7 +8199,7 @@ var DocumentBuilder = class {
7813
8199
  return helper;
7814
8200
  },
7815
8201
  addRest: (restLength, restOptions) => {
7816
- assertArg(import_ts_utils_lib15.Utils.Is.isEnumValue(restLength, import_theory13.NoteLength) || isNoteLength(restLength), "restLength", restLength);
8202
+ assertArg(import_ts_utils_lib16.Utils.Is.isEnumValue(restLength, import_theory13.NoteLength) || isNoteLength(restLength), "restLength", restLength);
7817
8203
  restOptions != null ? restOptions : restOptions = {};
7818
8204
  delete restOptions.triplet;
7819
8205
  assertRestOptions(restOptions);
@@ -7830,8 +8216,8 @@ var DocumentBuilder = class {
7830
8216
  var _a;
7831
8217
  assertStaffTabOrGRoups(staffTabOrGroups);
7832
8218
  assertArg(isVerseNumber(verse), "verse", verse);
7833
- assertArg(import_ts_utils_lib15.Utils.Is.isEnumValue(lyricsLength, import_theory13.NoteLength), "lyricsLength", lyricsLength);
7834
- assertArg(import_ts_utils_lib15.Utils.Is.isString(lyricsText) || import_ts_utils_lib15.Utils.Is.isArray(lyricsText) && lyricsText.every((text) => import_ts_utils_lib15.Utils.Is.isString(text)), "lyricsText", lyricsText);
8219
+ assertArg(import_ts_utils_lib16.Utils.Is.isEnumValue(lyricsLength, import_theory13.NoteLength), "lyricsLength", lyricsLength);
8220
+ assertArg(import_ts_utils_lib16.Utils.Is.isString(lyricsText) || import_ts_utils_lib16.Utils.Is.isArray(lyricsText) && lyricsText.every((text) => import_ts_utils_lib16.Utils.Is.isString(text)), "lyricsText", lyricsText);
7835
8221
  lyricsOptions != null ? lyricsOptions : lyricsOptions = {};
7836
8222
  assertLyricsOptions(lyricsOptions);
7837
8223
  if (lyricsOptions.align !== void 0) {
@@ -7839,7 +8225,7 @@ var DocumentBuilder = class {
7839
8225
  } else {
7840
8226
  (_a = lyricsOptions.align) != null ? _a : lyricsOptions.align = this.currentLyricsAlign;
7841
8227
  }
7842
- if (import_ts_utils_lib15.Utils.Is.isArray(lyricsText)) {
8228
+ if (import_ts_utils_lib16.Utils.Is.isArray(lyricsText)) {
7843
8229
  lyricsText.forEach((text) => this.getMeasure().addLyrics(staffTabOrGroups, verse, lyricsLength, text, lyricsOptions));
7844
8230
  } else {
7845
8231
  this.getMeasure().addLyrics(staffTabOrGroups, verse, lyricsLength, lyricsText, lyricsOptions);
@@ -7871,7 +8257,7 @@ var DocumentBuilder = class {
7871
8257
  }
7872
8258
  addFermataInternal(staffTabOrGroups, fermata) {
7873
8259
  assertStaffTabOrGRoups(staffTabOrGroups);
7874
- assertArg(import_ts_utils_lib15.Utils.Is.isEnumValue(fermata, Fermata), "fermata", fermata);
8260
+ assertArg(import_ts_utils_lib16.Utils.Is.isEnumValue(fermata, Fermata), "fermata", fermata);
7875
8261
  this.getMeasure().addFermata(staffTabOrGroups, fermata);
7876
8262
  return this;
7877
8263
  }
@@ -7894,11 +8280,11 @@ var DocumentBuilder = class {
7894
8280
  }
7895
8281
  addNavigationInternal(staffTabOrGroups, navigation, ...args) {
7896
8282
  assertStaffTabOrGRoups(staffTabOrGroups);
7897
- assertArg(import_ts_utils_lib15.Utils.Is.isEnumValue(navigation, Navigation), "navigation", navigation);
8283
+ assertArg(import_ts_utils_lib16.Utils.Is.isEnumValue(navigation, Navigation), "navigation", navigation);
7898
8284
  if (navigation === "endRepeat" /* EndRepeat */ && args.length > 0) {
7899
- assertArg(import_ts_utils_lib15.Utils.Is.isIntegerGte(args[0], 1), "playCount", args[0]);
8285
+ assertArg(import_ts_utils_lib16.Utils.Is.isIntegerGte(args[0], 1), "playCount", args[0]);
7900
8286
  } else if (navigation === "ending" /* Ending */ && args.length > 0) {
7901
- assertArg(args.every((passage) => import_ts_utils_lib15.Utils.Is.isIntegerGte(passage, 1)), "passages", args);
8287
+ assertArg(args.every((passage) => import_ts_utils_lib16.Utils.Is.isIntegerGte(passage, 1)), "passages", args);
7902
8288
  }
7903
8289
  this.getMeasure().addNavigation(staffTabOrGroups, navigation, ...args);
7904
8290
  return this;
@@ -7912,11 +8298,11 @@ var DocumentBuilder = class {
7912
8298
  addAnnotationInternal(staffTabOrGroups, annotation, text) {
7913
8299
  annotation != null ? annotation : annotation = getAnnotation(text);
7914
8300
  if (annotation === void 0) {
7915
- throw new import_core18.MusicError(import_core18.MusicErrorType.Score, `Annotation text "${text}" is not known annotation.`);
8301
+ throw new import_core19.MusicError(import_core19.MusicErrorType.Score, `Annotation text "${text}" is not known annotation.`);
7916
8302
  }
7917
8303
  assertStaffTabOrGRoups(staffTabOrGroups);
7918
- assertArg(import_ts_utils_lib15.Utils.Is.isEnumValue(annotation, Annotation), "annotation", annotation);
7919
- assertArg(import_ts_utils_lib15.Utils.Is.isNonEmptyString(text), "text", text);
8304
+ assertArg(import_ts_utils_lib16.Utils.Is.isEnumValue(annotation, Annotation), "annotation", annotation);
8305
+ assertArg(import_ts_utils_lib16.Utils.Is.isNonEmptyString(text), "text", text);
7920
8306
  this.getMeasure().addAnnotation(staffTabOrGroups, annotation, text);
7921
8307
  return this;
7922
8308
  }
@@ -7936,8 +8322,8 @@ var DocumentBuilder = class {
7936
8322
  }
7937
8323
  addLabelInternal(staffTabOrGroups, label, text) {
7938
8324
  assertStaffTabOrGRoups(staffTabOrGroups);
7939
- assertArg(import_ts_utils_lib15.Utils.Is.isEnumValue(label, Label), "label", label);
7940
- assertArg(import_ts_utils_lib15.Utils.Is.isNonEmptyString(text), "text", text);
8325
+ assertArg(import_ts_utils_lib16.Utils.Is.isEnumValue(label, Label), "label", label);
8326
+ assertArg(import_ts_utils_lib16.Utils.Is.isNonEmptyString(text), "text", text);
7941
8327
  this.getMeasure().addLabel(staffTabOrGroups, label, text);
7942
8328
  return this;
7943
8329
  }
@@ -7961,21 +8347,21 @@ var DocumentBuilder = class {
7961
8347
  return this.addLabelInternal(staffTabOrGroups, label, text);
7962
8348
  }
7963
8349
  addConnective(connective, ...args) {
7964
- assertArg(import_ts_utils_lib15.Utils.Is.isEnumValue(connective, Connective), "connective", connective);
8350
+ assertArg(import_ts_utils_lib16.Utils.Is.isEnumValue(connective, Connective), "connective", connective);
7965
8351
  if (connective === "tie" /* Tie */) {
7966
- assertArg(import_ts_utils_lib15.Utils.Is.isIntegerOrUndefined(args[0]) || import_ts_utils_lib15.Utils.Is.isEnumValue(args[0], TieType), "tieSpan", args[0]);
7967
- assertArg(import_ts_utils_lib15.Utils.Is.isEnumValueOrUndefined(args[1], NoteAnchor), "noteAnchor", args[1]);
8352
+ assertArg(import_ts_utils_lib16.Utils.Is.isIntegerOrUndefined(args[0]) || import_ts_utils_lib16.Utils.Is.isEnumValue(args[0], TieType), "tieSpan", args[0]);
8353
+ assertArg(import_ts_utils_lib16.Utils.Is.isEnumValueOrUndefined(args[1], NoteAnchor), "noteAnchor", args[1]);
7968
8354
  let tieSpan = args[0];
7969
8355
  let noteAnchor = args[1];
7970
8356
  this.getMeasure().addConnective(connective, tieSpan, noteAnchor);
7971
8357
  } else if (connective === "slur" /* Slur */) {
7972
- assertArg(import_ts_utils_lib15.Utils.Is.isIntegerOrUndefined(args[0]), "slurSpan", args[0]);
7973
- assertArg(import_ts_utils_lib15.Utils.Is.isEnumValueOrUndefined(args[1], NoteAnchor), "noteAnchor", args[1]);
8358
+ assertArg(import_ts_utils_lib16.Utils.Is.isIntegerOrUndefined(args[0]), "slurSpan", args[0]);
8359
+ assertArg(import_ts_utils_lib16.Utils.Is.isEnumValueOrUndefined(args[1], NoteAnchor), "noteAnchor", args[1]);
7974
8360
  let slurSpan = args[0];
7975
8361
  let noteAnchor = args[1];
7976
8362
  this.getMeasure().addConnective(connective, slurSpan, noteAnchor);
7977
8363
  } else if (connective === "slide" /* Slide */) {
7978
- assertArg(import_ts_utils_lib15.Utils.Is.isEnumValueOrUndefined(args[0], NoteAnchor), "noteAnchor", args[0]);
8364
+ assertArg(import_ts_utils_lib16.Utils.Is.isEnumValueOrUndefined(args[0], NoteAnchor), "noteAnchor", args[0]);
7979
8365
  let noteAnchor = args[0];
7980
8366
  this.getMeasure().addConnective(connective, noteAnchor);
7981
8367
  }
@@ -7994,18 +8380,18 @@ var DocumentBuilder = class {
7994
8380
  * @returns - This document builder instance.
7995
8381
  */
7996
8382
  addExtension(extensionBuilder) {
7997
- assertArg(import_ts_utils_lib15.Utils.Is.isFunctionOrUndefined(extensionBuilder), "addExtension() has new usage, for e.g. addExtension(ext => ext.measures(2)). Please refer to README or API Reference.", extensionBuilder);
8383
+ assertArg(import_ts_utils_lib16.Utils.Is.isFunctionOrUndefined(extensionBuilder), "addExtension() has new usage, for e.g. addExtension(ext => ext.measures(2)). Please refer to README or API Reference.", extensionBuilder);
7998
8384
  let ticks = 0;
7999
8385
  let visible = true;
8000
8386
  const helper = {
8001
8387
  notes: (noteLength, noteCount) => {
8002
- assertArg(import_ts_utils_lib15.Utils.Is.isEnumValue(noteLength, import_theory13.NoteLength) || isNoteLength(noteLength), "noteLength", noteLength);
8003
- assertArg(import_ts_utils_lib15.Utils.Is.isUndefined(noteCount) || import_ts_utils_lib15.Utils.Is.isNumber(noteCount) && noteCount >= 0, "noteCount", noteCount);
8388
+ assertArg(import_ts_utils_lib16.Utils.Is.isEnumValue(noteLength, import_theory13.NoteLength) || isNoteLength(noteLength), "noteLength", noteLength);
8389
+ assertArg(import_ts_utils_lib16.Utils.Is.isUndefined(noteCount) || import_ts_utils_lib16.Utils.Is.isNumber(noteCount) && noteCount >= 0, "noteCount", noteCount);
8004
8390
  ticks += import_theory13.RhythmProps.get(noteLength).ticks * (noteCount != null ? noteCount : 1);
8005
8391
  return helper;
8006
8392
  },
8007
8393
  measures: (measureCount) => {
8008
- assertArg(import_ts_utils_lib15.Utils.Is.isNumber(measureCount) && measureCount >= 1, "measureCount", measureCount);
8394
+ assertArg(import_ts_utils_lib16.Utils.Is.isNumber(measureCount) && measureCount >= 1, "measureCount", measureCount);
8009
8395
  ticks += this.getMeasure().getMeasureTicks() * measureCount;
8010
8396
  return helper;
8011
8397
  },
@@ -8034,13 +8420,13 @@ var DocumentBuilder = class {
8034
8420
  * @returns - This document builder instance.
8035
8421
  */
8036
8422
  addStaffGroup(groupName, staffsTabsAndGroups, verticalPosition = "auto" /* Auto */) {
8037
- assertArg(import_ts_utils_lib15.Utils.Is.isNonEmptyString(groupName), "groupName", groupName);
8423
+ assertArg(import_ts_utils_lib16.Utils.Is.isNonEmptyString(groupName), "groupName", groupName);
8038
8424
  assertArg(
8039
- import_ts_utils_lib15.Utils.Is.isNonEmptyString(staffsTabsAndGroups) || import_ts_utils_lib15.Utils.Is.isIntegerGte(staffsTabsAndGroups, 0) || import_ts_utils_lib15.Utils.Is.isNonEmptyArray(staffsTabsAndGroups) && staffsTabsAndGroups.every((line) => import_ts_utils_lib15.Utils.Is.isNonEmptyString(line) || import_ts_utils_lib15.Utils.Is.isIntegerGte(line, 0)),
8425
+ import_ts_utils_lib16.Utils.Is.isNonEmptyString(staffsTabsAndGroups) || import_ts_utils_lib16.Utils.Is.isIntegerGte(staffsTabsAndGroups, 0) || import_ts_utils_lib16.Utils.Is.isNonEmptyArray(staffsTabsAndGroups) && staffsTabsAndGroups.every((line) => import_ts_utils_lib16.Utils.Is.isNonEmptyString(line) || import_ts_utils_lib16.Utils.Is.isIntegerGte(line, 0)),
8040
8426
  "staffsTabsAndGroups",
8041
8427
  staffsTabsAndGroups
8042
8428
  );
8043
- assertArg(import_ts_utils_lib15.Utils.Is.isEnumValue(verticalPosition, VerticalPosition), "verticalPosition", verticalPosition);
8429
+ assertArg(import_ts_utils_lib16.Utils.Is.isEnumValue(verticalPosition, VerticalPosition), "verticalPosition", verticalPosition);
8044
8430
  this.doc.addStaffGroup(groupName, staffsTabsAndGroups, verticalPosition);
8045
8431
  return this;
8046
8432
  }
@@ -8075,7 +8461,7 @@ var DocumentBuilder = class {
8075
8461
  * @returns - This document builder instance.
8076
8462
  */
8077
8463
  completeRests(voiceId) {
8078
- assertArg(import_ts_utils_lib15.Utils.Is.isUndefined(voiceId) || isVoiceId(voiceId) || import_ts_utils_lib15.Utils.Is.isArray(voiceId) && voiceId.every((id) => isVoiceId(id)), "voiceId", voiceId);
8464
+ assertArg(import_ts_utils_lib16.Utils.Is.isUndefined(voiceId) || isVoiceId(voiceId) || import_ts_utils_lib16.Utils.Is.isArray(voiceId) && voiceId.every((id) => isVoiceId(id)), "voiceId", voiceId);
8079
8465
  this.getMeasure().completeRests(voiceId);
8080
8466
  return this;
8081
8467
  }
@@ -8087,8 +8473,8 @@ var DocumentBuilder = class {
8087
8473
  * @returns - This document builder instance.
8088
8474
  */
8089
8475
  addScaleArpeggio(scale, bottomNote, numOctaves) {
8090
- assertArg(import_ts_utils_lib15.Utils.Is.isNonEmptyString(bottomNote), "bottomNote", bottomNote);
8091
- assertArg(import_ts_utils_lib15.Utils.Is.isIntegerGte(numOctaves, 1), "numOctaves", numOctaves);
8476
+ assertArg(import_ts_utils_lib16.Utils.Is.isNonEmptyString(bottomNote), "bottomNote", bottomNote);
8477
+ assertArg(import_ts_utils_lib16.Utils.Is.isIntegerGte(numOctaves, 1), "numOctaves", numOctaves);
8092
8478
  let ts = this.getMeasure().getTimeSignature();
8093
8479
  let notes = scale.getScaleNotes(bottomNote, numOctaves);
8094
8480
  for (let i = 0; i < notes.length; i++) {
@@ -8104,7 +8490,7 @@ var DocumentBuilder = class {
8104
8490
  };
8105
8491
 
8106
8492
  // src/score/pub/event.ts
8107
- var import_core19 = require("@tspro/web-music-score/core");
8493
+ var import_core20 = require("@tspro/web-music-score/core");
8108
8494
  var ScoreEvent = class {
8109
8495
  /**
8110
8496
  * Create new score event instance.
@@ -8141,7 +8527,7 @@ var ScoreObjectEvent = class extends ScoreEvent {
8141
8527
  this.renderer = renderer;
8142
8528
  this.objects = objects;
8143
8529
  if (arguments.length === 0) {
8144
- throw new import_core19.MusicError(import_core19.MusicErrorType.Score, "Empty array in score object event!");
8530
+ throw new import_core20.MusicError(import_core20.MusicErrorType.Score, "Empty array in score object event!");
8145
8531
  }
8146
8532
  }
8147
8533
  /** Top object getter. */
@@ -8160,24 +8546,24 @@ var ScoreObjectEvent = class extends ScoreEvent {
8160
8546
 
8161
8547
  // src/score/pub/music-interface.ts
8162
8548
  var Audio2 = __toESM(require("@tspro/web-music-score/audio"));
8163
- var import_ts_utils_lib17 = require("@tspro/ts-utils-lib");
8549
+ var import_ts_utils_lib18 = require("@tspro/ts-utils-lib");
8164
8550
 
8165
8551
  // src/score/pub/music-objects.ts
8166
- var import_ts_utils_lib16 = require("@tspro/ts-utils-lib");
8167
- var import_core20 = require("@tspro/web-music-score/core");
8552
+ var import_ts_utils_lib17 = require("@tspro/ts-utils-lib");
8553
+ var import_core21 = require("@tspro/web-music-score/core");
8168
8554
  function assertArg2(condition, argName, argValue) {
8169
8555
  if (!condition) {
8170
- throw new import_core20.MusicError(import_core20.MusicErrorType.Score, `Invalid arg: ${argName} = ${argValue}`);
8556
+ throw new import_core21.MusicError(import_core21.MusicErrorType.Score, `Invalid arg: ${argName} = ${argValue}`);
8171
8557
  }
8172
8558
  }
8173
8559
  function isVoiceId2(value) {
8174
- return import_ts_utils_lib16.Utils.Is.isNumber(value) && getVoiceIds().indexOf(value) >= 0;
8560
+ return import_ts_utils_lib17.Utils.Is.isNumber(value) && getVoiceIds().indexOf(value) >= 0;
8175
8561
  }
8176
8562
  function getNotationLine(line) {
8177
8563
  if (line instanceof ObjStaff || line instanceof ObjTab) {
8178
8564
  return line.getMusicInterface();
8179
8565
  } else {
8180
- throw new import_core20.MusicError(import_core20.MusicErrorType.Score, `Notation line not staff nor tab.`);
8566
+ throw new import_core21.MusicError(import_core21.MusicErrorType.Score, `Notation line not staff nor tab.`);
8181
8567
  }
8182
8568
  }
8183
8569
  var MusicInterface6 = class {
@@ -8347,7 +8733,7 @@ var _MDocument = class _MDocument extends MusicInterface6 {
8347
8733
  * @returns - Player instance.
8348
8734
  */
8349
8735
  play(playStateChangeListener) {
8350
- assertArg2(import_ts_utils_lib16.Utils.Is.isFunctionOrUndefined(playStateChangeListener), "playStateChangeListener", playStateChangeListener);
8736
+ assertArg2(import_ts_utils_lib17.Utils.Is.isFunctionOrUndefined(playStateChangeListener), "playStateChangeListener", playStateChangeListener);
8351
8737
  return new MPlayer(this, playStateChangeListener).play();
8352
8738
  }
8353
8739
  };
@@ -8377,7 +8763,7 @@ var _MEnding = class _MEnding extends MusicInterface6 {
8377
8763
  * @returns - Boolean whether this ending has asked passage number.
8378
8764
  */
8379
8765
  hasPassage(passage) {
8380
- assertArg2(import_ts_utils_lib16.Utils.Is.isIntegerGte(passage, 1), "passage", passage);
8766
+ assertArg2(import_ts_utils_lib17.Utils.Is.isIntegerGte(passage, 1), "passage", passage);
8381
8767
  return this.obj.hasPassage(passage);
8382
8768
  }
8383
8769
  };
@@ -8529,7 +8915,7 @@ var _MStaffTabBarLine = class _MStaffTabBarLine extends MusicInterface6 {
8529
8915
  if (barLine instanceof ObjBarLineLeft || barLine instanceof ObjBarLineRight) {
8530
8916
  return barLine.getMusicInterface();
8531
8917
  } else {
8532
- throw new import_core20.MusicError(import_core20.MusicErrorType.Score, `Bar line not let nor right.`);
8918
+ throw new import_core21.MusicError(import_core21.MusicErrorType.Score, `Bar line not let nor right.`);
8533
8919
  }
8534
8920
  }
8535
8921
  /**
@@ -8893,10 +9279,10 @@ var _MTab = class _MTab extends MusicInterface6 {
8893
9279
  /** Object name. */
8894
9280
  __publicField(_MTab, "Name", "Tab");
8895
9281
  var MTab = _MTab;
8896
- var _MSignature = class _MSignature extends MusicInterface6 {
9282
+ var _MStaffSignature = class _MStaffSignature extends MusicInterface6 {
8897
9283
  /** @internal */
8898
9284
  constructor(obj) {
8899
- super(_MSignature.Name);
9285
+ super(_MStaffSignature.Name);
8900
9286
  this.obj = obj;
8901
9287
  }
8902
9288
  /** @internal */
@@ -8912,8 +9298,57 @@ var _MSignature = class _MSignature extends MusicInterface6 {
8912
9298
  }
8913
9299
  };
8914
9300
  /** Object name. */
8915
- __publicField(_MSignature, "Name", "Signature");
8916
- var MSignature = _MSignature;
9301
+ __publicField(_MStaffSignature, "Name", "StaffSignature");
9302
+ var MStaffSignature = _MStaffSignature;
9303
+ var _MTabSignature = class _MTabSignature extends MusicInterface6 {
9304
+ /** @internal */
9305
+ constructor(obj) {
9306
+ super(_MTabSignature.Name);
9307
+ this.obj = obj;
9308
+ }
9309
+ /** @internal */
9310
+ getMusicObject() {
9311
+ return this.obj;
9312
+ }
9313
+ /**
9314
+ * Get tab notation line this signature is in.
9315
+ * @returns - Tab object.
9316
+ */
9317
+ getTab() {
9318
+ return this.obj.tab.getMusicInterface();
9319
+ }
9320
+ };
9321
+ /** Object name. */
9322
+ __publicField(_MTabSignature, "Name", "TabSignature");
9323
+ var MTabSignature = _MTabSignature;
9324
+ var _MTabRhythm = class _MTabRhythm extends MusicInterface6 {
9325
+ /** @internal */
9326
+ constructor(obj) {
9327
+ super(_MTabRhythm.Name);
9328
+ this.obj = obj;
9329
+ }
9330
+ /** @internal */
9331
+ getMusicObject() {
9332
+ return this.obj;
9333
+ }
9334
+ /**
9335
+ * Get measure.
9336
+ * @returns - Measure.
9337
+ */
9338
+ getMeasure() {
9339
+ return this.obj.measure.getMusicInterface();
9340
+ }
9341
+ /**
9342
+ * Get tab.
9343
+ * @returns - Tab.
9344
+ */
9345
+ getTab() {
9346
+ return this.obj.tab.getMusicInterface();
9347
+ }
9348
+ };
9349
+ /** Object name. */
9350
+ __publicField(_MTabRhythm, "Name", "TabRhythm");
9351
+ var MTabRhythm = _MTabRhythm;
8917
9352
  var _MSpecialText = class _MSpecialText extends MusicInterface6 {
8918
9353
  /** @internal */
8919
9354
  constructor(obj) {
@@ -8993,10 +9428,10 @@ __publicField(_MExtensionLine, "Name", "ExtensionLine");
8993
9428
  var MExtensionLine = _MExtensionLine;
8994
9429
 
8995
9430
  // src/score/pub/music-interface.ts
8996
- var import_core21 = require("@tspro/web-music-score/core");
9431
+ var import_core22 = require("@tspro/web-music-score/core");
8997
9432
  function assertArg3(condition, argName, argValue) {
8998
9433
  if (!condition) {
8999
- throw new import_core21.MusicError(import_core21.MusicErrorType.Score, `Invalid arg: ${argName} = ${argValue}`);
9434
+ throw new import_core22.MusicError(import_core22.MusicErrorType.Score, `Invalid arg: ${argName} = ${argValue}`);
9000
9435
  }
9001
9436
  }
9002
9437
  function require_t(t, message) {
@@ -9015,7 +9450,7 @@ var _MPlayer = class _MPlayer {
9015
9450
  constructor(doc, playStateChangeListener) {
9016
9451
  __publicField(this, "player");
9017
9452
  assertArg3(doc instanceof MDocument2, "doc", doc);
9018
- assertArg3(import_ts_utils_lib17.Utils.Is.isFunctionOrUndefined(playStateChangeListener), "playStateChangeListener", playStateChangeListener);
9453
+ assertArg3(import_ts_utils_lib18.Utils.Is.isFunctionOrUndefined(playStateChangeListener), "playStateChangeListener", playStateChangeListener);
9019
9454
  this.player = new Player();
9020
9455
  this.player.setDocument(doc.getMusicObject());
9021
9456
  this.player.setCursorPositionChangeListener((cursorRect) => doc.getMusicObject().updateCursorRect(cursorRect));
@@ -9073,7 +9508,7 @@ var MRenderer2 = class {
9073
9508
  * @returns - This renderer instance.
9074
9509
  */
9075
9510
  setDocument(doc) {
9076
- assertArg3(import_ts_utils_lib17.Utils.Is.isUndefined(doc) || doc instanceof MDocument2, "doc", doc);
9511
+ assertArg3(import_ts_utils_lib18.Utils.Is.isUndefined(doc) || doc instanceof MDocument2, "doc", doc);
9077
9512
  this.renderer.setDocument(doc);
9078
9513
  return this;
9079
9514
  }
@@ -9083,7 +9518,7 @@ var MRenderer2 = class {
9083
9518
  * @returns - This renderer instance.
9084
9519
  */
9085
9520
  setCanvas(canvas) {
9086
- canvas = require_t(import_ts_utils_lib17.Utils.Dom.getCanvas(canvas), typeof canvas === "string" ? "Cannot set renderer canvas because invalid canvas id: " + canvas : "Cannot set renderer canvas because given canvas is undefined.");
9521
+ canvas = require_t(import_ts_utils_lib18.Utils.Dom.getCanvas(canvas), typeof canvas === "string" ? "Cannot set renderer canvas because invalid canvas id: " + canvas : "Cannot set renderer canvas because given canvas is undefined.");
9087
9522
  this.renderer.setCanvas(canvas);
9088
9523
  return this;
9089
9524
  }
@@ -9092,7 +9527,7 @@ var MRenderer2 = class {
9092
9527
  * @param scoreEventListener - Score event listener.
9093
9528
  */
9094
9529
  setScoreEventListener(scoreEventListener) {
9095
- assertArg3(import_ts_utils_lib17.Utils.Is.isFunctionOrUndefined(scoreEventListener), "scoreEventListener", scoreEventListener);
9530
+ assertArg3(import_ts_utils_lib18.Utils.Is.isFunctionOrUndefined(scoreEventListener), "scoreEventListener", scoreEventListener);
9096
9531
  this.renderer.setScoreEventListener(scoreEventListener);
9097
9532
  }
9098
9533
  /**
@@ -9166,7 +9601,7 @@ var _MPlaybackButtons = class _MPlaybackButtons {
9166
9601
  * @returns
9167
9602
  */
9168
9603
  setDocument(doc) {
9169
- assertArg3(import_ts_utils_lib17.Utils.Is.isUndefined(doc) || doc instanceof MDocument2, "doc", doc);
9604
+ assertArg3(import_ts_utils_lib18.Utils.Is.isUndefined(doc) || doc instanceof MDocument2, "doc", doc);
9170
9605
  this.onStop();
9171
9606
  if (doc) {
9172
9607
  this.player = new MPlayer(doc, (playState) => {
@@ -9210,9 +9645,9 @@ var _MPlaybackButtons = class _MPlaybackButtons {
9210
9645
  * @returns - This playback buttons class instance.
9211
9646
  */
9212
9647
  setPlayButton(btn, btnLabel) {
9213
- assertArg3(import_ts_utils_lib17.Utils.Is.isStringOrUndefined(btnLabel), "btnLabel", btnLabel);
9648
+ assertArg3(import_ts_utils_lib18.Utils.Is.isStringOrUndefined(btnLabel), "btnLabel", btnLabel);
9214
9649
  _MPlaybackButtons.removeOnClickListeners(this.playButton, this.onPlay);
9215
- this.playButton = require_t(import_ts_utils_lib17.Utils.Dom.getButton(btn), "Play button required!");
9650
+ this.playButton = require_t(import_ts_utils_lib18.Utils.Dom.getButton(btn), "Play button required!");
9216
9651
  this.playLabel = btnLabel != null ? btnLabel : "Play";
9217
9652
  _MPlaybackButtons.removeOnClickListeners(this.playButton, "all");
9218
9653
  _MPlaybackButtons.addOnClickListener(this.playButton, this.onPlay);
@@ -9226,9 +9661,9 @@ var _MPlaybackButtons = class _MPlaybackButtons {
9226
9661
  * @returns - This playback buttons class instance.
9227
9662
  */
9228
9663
  setStopButton(btn, btnLabel) {
9229
- assertArg3(import_ts_utils_lib17.Utils.Is.isStringOrUndefined(btnLabel), "btnLabel", btnLabel);
9664
+ assertArg3(import_ts_utils_lib18.Utils.Is.isStringOrUndefined(btnLabel), "btnLabel", btnLabel);
9230
9665
  _MPlaybackButtons.removeOnClickListeners(this.stopButton, this.onStop);
9231
- this.stopButton = require_t(import_ts_utils_lib17.Utils.Dom.getButton(btn), "Stop button required!");
9666
+ this.stopButton = require_t(import_ts_utils_lib18.Utils.Dom.getButton(btn), "Stop button required!");
9232
9667
  this.stopLabel = btnLabel != null ? btnLabel : "Stop";
9233
9668
  _MPlaybackButtons.removeOnClickListeners(this.stopButton, "all");
9234
9669
  _MPlaybackButtons.addOnClickListener(this.stopButton, this.onStop);
@@ -9243,10 +9678,10 @@ var _MPlaybackButtons = class _MPlaybackButtons {
9243
9678
  * @returns - This playback buttons class instance.
9244
9679
  */
9245
9680
  setPlayStopButton(btn, playLabel, stopLabel) {
9246
- assertArg3(import_ts_utils_lib17.Utils.Is.isStringOrUndefined(playLabel), "playLabel", playLabel);
9247
- assertArg3(import_ts_utils_lib17.Utils.Is.isStringOrUndefined(stopLabel), "stopLabel", stopLabel);
9681
+ assertArg3(import_ts_utils_lib18.Utils.Is.isStringOrUndefined(playLabel), "playLabel", playLabel);
9682
+ assertArg3(import_ts_utils_lib18.Utils.Is.isStringOrUndefined(stopLabel), "stopLabel", stopLabel);
9248
9683
  _MPlaybackButtons.removeOnClickListeners(this.playStopButton, this.onPlayStop);
9249
- this.playStopButton = require_t(import_ts_utils_lib17.Utils.Dom.getButton(btn), "Play/stop button required!");
9684
+ this.playStopButton = require_t(import_ts_utils_lib18.Utils.Dom.getButton(btn), "Play/stop button required!");
9250
9685
  this.playLabel = playLabel != null ? playLabel : "Play";
9251
9686
  this.stopLabel = stopLabel != null ? stopLabel : "Stop";
9252
9687
  _MPlaybackButtons.removeOnClickListeners(this.playStopButton, "all");
@@ -9261,9 +9696,9 @@ var _MPlaybackButtons = class _MPlaybackButtons {
9261
9696
  * @returns - This playback buttons class instance.
9262
9697
  */
9263
9698
  setPauseButton(btn, btnLabel) {
9264
- assertArg3(import_ts_utils_lib17.Utils.Is.isStringOrUndefined(btnLabel), "btnLabel", btnLabel);
9699
+ assertArg3(import_ts_utils_lib18.Utils.Is.isStringOrUndefined(btnLabel), "btnLabel", btnLabel);
9265
9700
  _MPlaybackButtons.removeOnClickListeners(this.pauseButton, this.onPause);
9266
- this.pauseButton = require_t(import_ts_utils_lib17.Utils.Dom.getButton(btn), "Pause button required!");
9701
+ this.pauseButton = require_t(import_ts_utils_lib18.Utils.Dom.getButton(btn), "Pause button required!");
9267
9702
  this.pauseLabel = btnLabel != null ? btnLabel : "Pause";
9268
9703
  _MPlaybackButtons.removeOnClickListeners(this.pauseButton, "all");
9269
9704
  _MPlaybackButtons.addOnClickListener(this.pauseButton, this.onPause);
@@ -9285,7 +9720,7 @@ var _MPlaybackButtons = class _MPlaybackButtons {
9285
9720
  }
9286
9721
  }
9287
9722
  static addOnClickListener(btn, onClick) {
9288
- assertArg3(import_ts_utils_lib17.Utils.Is.isFunction(onClick), "onClick", onClick);
9723
+ assertArg3(import_ts_utils_lib18.Utils.Is.isFunction(onClick), "onClick", onClick);
9289
9724
  btn.addEventListener("click", onClick);
9290
9725
  let clickListeners = this.savedOnClickListeners.get(btn) || [];
9291
9726
  this.savedOnClickListeners.set(btn, [...clickListeners, onClick]);
@@ -9295,8 +9730,8 @@ __publicField(_MPlaybackButtons, "savedOnClickListeners", /* @__PURE__ */ new Ma
9295
9730
  var MPlaybackButtons = _MPlaybackButtons;
9296
9731
 
9297
9732
  // src/score/index.ts
9298
- var import_core22 = require("@tspro/web-music-score/core");
9299
- (0, import_core22.init)();
9733
+ var import_core23 = require("@tspro/web-music-score/core");
9734
+ (0, import_core23.init)();
9300
9735
  // Annotate the CommonJS export names for ESM import in node:
9301
9736
  0 && (module.exports = {
9302
9737
  Annotation,
@@ -9331,15 +9766,17 @@ var import_core22 = require("@tspro/web-music-score/core");
9331
9766
  MRest,
9332
9767
  MRhythmColumn,
9333
9768
  MScoreRow,
9334
- MSignature,
9335
9769
  MSpecialText,
9336
9770
  MStaff,
9337
9771
  MStaffBeamGroup,
9338
9772
  MStaffNoteGroup,
9339
9773
  MStaffRest,
9774
+ MStaffSignature,
9340
9775
  MStaffTabBarLine,
9341
9776
  MTab,
9342
9777
  MTabNoteGroup,
9778
+ MTabRhythm,
9779
+ MTabSignature,
9343
9780
  MText,
9344
9781
  MusicInterface,
9345
9782
  Navigation,