@onjmin/dtm 0.1.23 → 0.1.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +21 -2
- package/dist/index.d.ts +21 -2
- package/dist/index.js +893 -243
- package/dist/index.mjs +893 -243
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1216,6 +1216,9 @@ var ICONS = {
|
|
|
1216
1216
|
},
|
|
1217
1217
|
info: {
|
|
1218
1218
|
d: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z"
|
|
1219
|
+
},
|
|
1220
|
+
more: {
|
|
1221
|
+
d: "M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"
|
|
1219
1222
|
}
|
|
1220
1223
|
};
|
|
1221
1224
|
var icon = (name, size = 20) => {
|
|
@@ -1342,6 +1345,7 @@ var buildUI = (target, options) => {
|
|
|
1342
1345
|
<textarea class="dtm-textarea dtm-grow" data-dtm="mml-input" placeholder="MML\u3092\u5165\u529B"></textarea>
|
|
1343
1346
|
<button class="dtm-btn dtm-btn--primary" data-dtm="mml-load">\u8AAD\u8FBC</button>
|
|
1344
1347
|
</div>
|
|
1348
|
+
<p class="dtm-load-note dtm-hidden" data-dtm="mml-load-note"></p>
|
|
1345
1349
|
</div>
|
|
1346
1350
|
</details>
|
|
1347
1351
|
|
|
@@ -1424,6 +1428,7 @@ var buildUI = (target, options) => {
|
|
|
1424
1428
|
<div class="dtm-modal-body" data-dtm="modal-body"></div>
|
|
1425
1429
|
</div>
|
|
1426
1430
|
</div>
|
|
1431
|
+
|
|
1427
1432
|
</div>`;
|
|
1428
1433
|
const root = q(target, '[data-dtm="root"]');
|
|
1429
1434
|
const sel = (name) => q(root, `[data-dtm="${name}"]`);
|
|
@@ -1467,6 +1472,7 @@ var buildUI = (target, options) => {
|
|
|
1467
1472
|
midiPanel: sel("midi-panel"),
|
|
1468
1473
|
mmlInput: sel("mml-input"),
|
|
1469
1474
|
mmlLoadBtn: sel("mml-load"),
|
|
1475
|
+
mmlLoadNote: sel("mml-load-note"),
|
|
1470
1476
|
shiftSelect: sel("shift-select"),
|
|
1471
1477
|
shiftApplyBtn: sel("shift-apply"),
|
|
1472
1478
|
macroClear: sel("macro-clear"),
|
|
@@ -1620,6 +1626,110 @@ var DRUM_PATTERNS = {
|
|
|
1620
1626
|
]
|
|
1621
1627
|
};
|
|
1622
1628
|
|
|
1629
|
+
// src/instrument-presets.ts
|
|
1630
|
+
var INSTRUMENT_PRESETS = {
|
|
1631
|
+
// --- STANDARD: 汎用性と完成度重視 ---
|
|
1632
|
+
piano: {
|
|
1633
|
+
displayName: "\u30B0\u30E9\u30F3\u30C9\u30D4\u30A2\u30CE",
|
|
1634
|
+
description: "\u6700\u3082\u7834\u7DBB\u3057\u306B\u304F\u3044\u69CB\u6210\u3002\u697D\u66F2\u5236\u4F5C\u306E\u30B9\u30B1\u30C3\u30C1\u306B\u3082\u6700\u9069\u3002",
|
|
1635
|
+
melody: "Acoustic Grand Piano",
|
|
1636
|
+
submelody: "Vibraphone",
|
|
1637
|
+
bass: "Electric Bass (finger)",
|
|
1638
|
+
chord: "Pad 2 (warm)"
|
|
1639
|
+
},
|
|
1640
|
+
acoustic: {
|
|
1641
|
+
displayName: "\u30A2\u30B3\u30FC\u30B9\u30C6\u30A3\u30C3\u30AF",
|
|
1642
|
+
description: "\u751F\u697D\u5668\u306E\u6E29\u304B\u307F\u3092\u91CD\u8996\u3002\u30D5\u30A9\u30FC\u30AF\u3084\u30DD\u30C3\u30D7\u30B9\u306B\u3002",
|
|
1643
|
+
melody: "Acoustic Guitar (steel)",
|
|
1644
|
+
submelody: "Harmonica",
|
|
1645
|
+
bass: "Acoustic Bass",
|
|
1646
|
+
chord: "Acoustic Guitar (nylon)"
|
|
1647
|
+
},
|
|
1648
|
+
jazz_night: {
|
|
1649
|
+
displayName: "\u30B8\u30E3\u30BA\u30FB\u30CA\u30A4\u30C8",
|
|
1650
|
+
description: "Rhodes\u98A8\u306EEP\u3068\u30A6\u30C3\u30C9\u30D9\u30FC\u30B9\u306B\u3088\u308B\u3001\u5927\u4EBA\u3073\u305F\u30A2\u30F3\u30B5\u30F3\u30D6\u30EB\u3002",
|
|
1651
|
+
melody: "Electric Piano 1",
|
|
1652
|
+
submelody: "Flute",
|
|
1653
|
+
bass: "Acoustic Bass",
|
|
1654
|
+
chord: "Electric Guitar (jazz)"
|
|
1655
|
+
},
|
|
1656
|
+
// --- MODERN & VIBE: エッジの効いた現代的な響き ---
|
|
1657
|
+
synth_pop: {
|
|
1658
|
+
displayName: "\u30B7\u30F3\u30BB\u30DD\u30C3\u30D7",
|
|
1659
|
+
description: "80s\u301C\u73FE\u4EE3\u307E\u3067\u3002\u629C\u3051\u308B\u30EA\u30FC\u30C9\u3068\u592A\u3044\u30D9\u30FC\u30B9\u306E\u738B\u9053\u3002",
|
|
1660
|
+
melody: "Lead 2 (sawtooth)",
|
|
1661
|
+
submelody: "Lead 4 (chiff)",
|
|
1662
|
+
bass: "Synth Bass 2",
|
|
1663
|
+
chord: "Pad 3 (polysynth)"
|
|
1664
|
+
},
|
|
1665
|
+
cyber_punk: {
|
|
1666
|
+
displayName: "\u30B5\u30A4\u30D0\u30FC\u30D1\u30F3\u30AF",
|
|
1667
|
+
description: "\u30C7\u30B8\u30BF\u30EB\u306A\u51B7\u305F\u3055\u3068\u6B6A\u307F\u304C\u6DF7\u3056\u308A\u5408\u3046\u3001\u672A\u6765\u7684\u306A\u97FF\u304D\u3002",
|
|
1668
|
+
melody: "Lead 8 (bass + lead)",
|
|
1669
|
+
submelody: "Lead 5 (charang)",
|
|
1670
|
+
bass: "Synth Bass 2",
|
|
1671
|
+
chord: "Pad 8 (sweep)"
|
|
1672
|
+
},
|
|
1673
|
+
rock: {
|
|
1674
|
+
displayName: "\u30CF\u30FC\u30C9\u30ED\u30C3\u30AF",
|
|
1675
|
+
description: "\u6B6A\u307F\u30AE\u30BF\u30FC\u3068\u91CD\u539A\u306A\u30D9\u30FC\u30B9\u3067\u3001\u30D1\u30EF\u30FC\u3092\u524D\u9762\u306B\u3002",
|
|
1676
|
+
melody: "Distortion Guitar",
|
|
1677
|
+
submelody: "Rock Organ",
|
|
1678
|
+
bass: "Electric Bass (pick)",
|
|
1679
|
+
chord: "Overdriven Guitar"
|
|
1680
|
+
},
|
|
1681
|
+
// --- WORLD & CLASSIC: 特定のジャンル・地域 ---
|
|
1682
|
+
orchestra: {
|
|
1683
|
+
displayName: "\u30AA\u30FC\u30B1\u30B9\u30C8\u30E9",
|
|
1684
|
+
description: "\u58EE\u5927\u306A\u7269\u8A9E\u3092\u4E88\u611F\u3055\u305B\u308B\u3001\u7BA1\u5F26\u697D\u5668\u306E\u91CD\u539A\u306A\u97FF\u304D\u3002",
|
|
1685
|
+
melody: "French Horn",
|
|
1686
|
+
submelody: "Pizzicato Strings",
|
|
1687
|
+
bass: "Cello",
|
|
1688
|
+
chord: "Tremolo Strings"
|
|
1689
|
+
},
|
|
1690
|
+
japanese_wa: {
|
|
1691
|
+
displayName: "\u548C\u98A8\u30FB\u96C5",
|
|
1692
|
+
description: "\u7434\u3068\u4E09\u5473\u7DDA\u306E\u7E4A\u7D30\u306A\u8ABF\u3079\u306B\u3001\u5C3A\u516B\u306E\u60C5\u7DD2\u3092\u6DFB\u3048\u3066\u3002",
|
|
1693
|
+
melody: "Koto",
|
|
1694
|
+
submelody: "Shamisen",
|
|
1695
|
+
bass: "Taiko Drum",
|
|
1696
|
+
chord: "Shakuhachi"
|
|
1697
|
+
},
|
|
1698
|
+
arabic_exotic: {
|
|
1699
|
+
displayName: "\u30A8\u30AD\u30BE\u30C1\u30C3\u30AF",
|
|
1700
|
+
description: "\u30B7\u30BF\u30FC\u30EB\u3084\u30D0\u30B0\u30D1\u30A4\u30D7\u306B\u3088\u308B\u3001\u7570\u56FD\u60C5\u7DD2\u6EA2\u308C\u308B\u30B5\u30A6\u30F3\u30C9\u3002",
|
|
1701
|
+
melody: "Sitar",
|
|
1702
|
+
submelody: "Bagpipe",
|
|
1703
|
+
bass: "Fretless Bass",
|
|
1704
|
+
chord: "Kalimba"
|
|
1705
|
+
},
|
|
1706
|
+
// --- FANTASY & ATMOSPHERE: 雰囲気と余韻 ---
|
|
1707
|
+
fantasy_rpg: {
|
|
1708
|
+
displayName: "\u30D5\u30A1\u30F3\u30BF\u30B8\u30FCRPG",
|
|
1709
|
+
description: "\u30AA\u30AB\u30EA\u30CA\u3068\u30CF\u30FC\u30D7\u304C\u7D21\u3050\u3001\u5192\u967A\u3068\u9B54\u6CD5\u306E\u4E16\u754C\u89B3\u3002",
|
|
1710
|
+
melody: "Ocarina",
|
|
1711
|
+
submelody: "Celesta",
|
|
1712
|
+
bass: "Timpani",
|
|
1713
|
+
chord: "Orchestral Harp"
|
|
1714
|
+
},
|
|
1715
|
+
ambient_cloud: {
|
|
1716
|
+
displayName: "\u30A2\u30F3\u30D3\u30A8\u30F3\u30C8",
|
|
1717
|
+
description: "\u8F2A\u90ED\u3092\u307C\u304B\u3057\u305F\u97F3\u8272\u3067\u3001\u6DF1\u3044\u6CA1\u5165\u611F\u3068\u4F59\u97FB\u3092\u6F14\u51FA\u3002",
|
|
1718
|
+
melody: "Lead 6 (voice)",
|
|
1719
|
+
submelody: "Music Box",
|
|
1720
|
+
bass: "Synth Bass 1",
|
|
1721
|
+
chord: "Pad 7 (halo)"
|
|
1722
|
+
},
|
|
1723
|
+
retro_game: {
|
|
1724
|
+
displayName: "8-bit \u30EC\u30C8\u30ED",
|
|
1725
|
+
description: "\u77E9\u5F62\u6CE2\u3092\u60F3\u8D77\u3055\u305B\u308B\u3001\u521D\u671F\u30B2\u30FC\u30E0\u6A5F\u306E\u3088\u3046\u306A\u61D0\u304B\u3057\u3044\u97FF\u304D\u3002",
|
|
1726
|
+
melody: "Lead 1 (square)",
|
|
1727
|
+
submelody: "Lead 2 (sawtooth)",
|
|
1728
|
+
bass: "Synth Bass 1",
|
|
1729
|
+
chord: "Clavinet"
|
|
1730
|
+
}
|
|
1731
|
+
};
|
|
1732
|
+
|
|
1623
1733
|
// node_modules/.pnpm/@onjmin+koe@1.0.3/node_modules/@onjmin/koe/dist/index.js
|
|
1624
1734
|
var MAGIC = 1263486208;
|
|
1625
1735
|
function parseKoeHeader(headerBytes) {
|
|
@@ -2502,7 +2612,20 @@ var createWorkerBackend = async (workerUrl, options) => {
|
|
|
2502
2612
|
};
|
|
2503
2613
|
};
|
|
2504
2614
|
var createKoeVoice = async (ctx, destination, options) => {
|
|
2505
|
-
|
|
2615
|
+
let backend;
|
|
2616
|
+
if (options.voiceWorkerUrl) {
|
|
2617
|
+
try {
|
|
2618
|
+
backend = await createWorkerBackend(options.voiceWorkerUrl, options);
|
|
2619
|
+
} catch (err2) {
|
|
2620
|
+
console.warn(
|
|
2621
|
+
"[dtm] Failed to spawn voice worker. Falling back to local backend.",
|
|
2622
|
+
err2
|
|
2623
|
+
);
|
|
2624
|
+
backend = await createLocalBackend(options);
|
|
2625
|
+
}
|
|
2626
|
+
} else {
|
|
2627
|
+
backend = await createLocalBackend(options);
|
|
2628
|
+
}
|
|
2506
2629
|
const renderCache = /* @__PURE__ */ new Map();
|
|
2507
2630
|
const inflight = /* @__PURE__ */ new Map();
|
|
2508
2631
|
const active = /* @__PURE__ */ new Set();
|
|
@@ -4017,6 +4140,110 @@ var isChordHeavyTrack = (notes, threshold = 0.6) => {
|
|
|
4017
4140
|
return chordNotes / notes.length >= threshold;
|
|
4018
4141
|
};
|
|
4019
4142
|
|
|
4143
|
+
// src/mml-info.ts
|
|
4144
|
+
var MML_INFO_HTML = `
|
|
4145
|
+
<div class="dtm-modal-body-content">
|
|
4146
|
+
<h4>1. \u97F3\u7B26\u3068\u4F11\u7B26</h4>
|
|
4147
|
+
<p><code>c</code>(\u30C9) <code>d</code>(\u30EC) <code>e</code>(\u30DF) <code>f</code>(\u30D5\u30A1) <code>g</code>(\u30BD) <code>a</code>(\u30E9) <code>b</code>(\u30B7) \u306E\u30A2\u30EB\u30D5\u30A1\u30D9\u30C3\u30C8\u3067\u8868\u3057\u307E\u3059\u3002</p>
|
|
4148
|
+
<ul>
|
|
4149
|
+
<li>\u534A\u97F3\u4E0A\u3052\u308B: <code>c#</code> \u307E\u305F\u306F <code>c+</code></li>
|
|
4150
|
+
<li>\u534A\u97F3\u4E0B\u3052\u308B: <code>d-</code></li>
|
|
4151
|
+
<li>\u4F11\u7B26: <code>r</code></li>
|
|
4152
|
+
</ul>
|
|
4153
|
+
|
|
4154
|
+
<h4>2. \u97F3\u306E\u9577\u3055</h4>
|
|
4155
|
+
<p>\u97F3\u540D\u3084\u4F11\u7B26\u306E\u5F8C\u306B\u6570\u5024\u3067\u6307\u5B9A\u3057\u307E\u3059\uFF08\u4F8B: <code>4</code> = 4\u5206\u97F3\u7B26, <code>8</code> = 8\u5206\u97F3\u7B26, <code>16</code> = 16\u5206\u97F3\u7B26\uFF09\u3002</p>
|
|
4156
|
+
<ul>
|
|
4157
|
+
<li><code>c4</code> : 4\u5206\u97F3\u7B26\u306E\u30C9</li>
|
|
4158
|
+
<li><code>r8</code> : 8\u5206\u4F11\u7B26</li>
|
|
4159
|
+
<li><code>c4.</code> : \u4ED8\u70B94\u5206\u97F3\u7B26\u306E\u30C9\uFF08\u9577\u3055\u30921.5\u500D\u306B\uFF09</li>
|
|
4160
|
+
<li>\u6570\u5024\u3092\u7701\u7565\u3059\u308B\u3068\u3001<code>l</code> \u30B3\u30DE\u30F3\u30C9\u3067\u8A2D\u5B9A\u3055\u308C\u305F\u30C7\u30D5\u30A9\u30EB\u30C8\u9577\uFF08\u901A\u5E3816\u5206\uFF09\u306B\u306A\u308A\u307E\u3059\u3002</li>
|
|
4161
|
+
</ul>
|
|
4162
|
+
|
|
4163
|
+
<h4>3. \u30AA\u30AF\u30BF\u30FC\u30D6\uFF08\u97F3\u306E\u9AD8\u3055\uFF09</h4>
|
|
4164
|
+
<ul>
|
|
4165
|
+
<li><code>o4</code>, <code>o5</code> : \u9AD8\u3055\u3092\u76F4\u63A5\u6307\u5B9A\uFF08\u3075\u3064\u3046\u306F o4 \u304B o5\uFF09</li>
|
|
4166
|
+
<li><code>></code> : 1\u30AA\u30AF\u30BF\u30FC\u30D6\u4E0A\u3052\u308B</li>
|
|
4167
|
+
<li><code><</code> : 1\u30AA\u30AF\u30BF\u30FC\u30D6\u4E0B\u3052\u308B</li>
|
|
4168
|
+
</ul>
|
|
4169
|
+
|
|
4170
|
+
<h4>4. \u30C6\u30F3\u30DD</h4>
|
|
4171
|
+
<ul>
|
|
4172
|
+
<li><code>t120</code> : \u66F2\u306E\u901F\u3055\u3092BPM120\u306B\u6307\u5B9A\u3002\u203B\u30E1\u30ED\u30C7\u30A3\uFF08@0\uFF09\u306E\u30C6\u30F3\u30DD\u6307\u5B9A\u304C\u66F2\u5168\u4F53\u306B\u53CD\u6620\u3055\u308C\u307E\u3059\u3002</li>
|
|
4173
|
+
</ul>
|
|
4174
|
+
|
|
4175
|
+
<h4>5. \u548C\u97F3</h4>
|
|
4176
|
+
<p>\u97F3\u7B26\u3092 <code>[</code> \u3068 <code>]</code> \u3067\u56F2\u3080\u3068\u540C\u6642\u306B\u767A\u97F3\u3057\u307E\u3059\u3002</p>
|
|
4177
|
+
<pre>\u4F8B: [ceg]4 \uFF08\u30C9\u30FB\u30DF\u30FB\u30BD\u30924\u5206\u97F3\u7B26\u3067\u540C\u6642\u306B\u767A\u97F3\uFF09</pre>
|
|
4178
|
+
|
|
4179
|
+
<h4>6. \u30C8\u30E9\u30C3\u30AF\u306E\u533A\u5207\u308A</h4>
|
|
4180
|
+
<p><code>;</code> \u307E\u305F\u306F <code>@0</code>\u301C<code>@3</code> \u3067\u30C8\u30E9\u30C3\u30AF\u3092\u5207\u308A\u66FF\u3048\u307E\u3059\u3002</p>
|
|
4181
|
+
<ul>
|
|
4182
|
+
<li><code>@0</code>: \u30E1\u30ED\u30C7\u30A3</li>
|
|
4183
|
+
<li><code>@1</code>: \u30B5\u30D6\u30E1\u30ED</li>
|
|
4184
|
+
<li><code>@2</code>: \u30D9\u30FC\u30B9</li>
|
|
4185
|
+
<li><code>@3</code>: \u4F34\u594F</li>
|
|
4186
|
+
</ul>
|
|
4187
|
+
|
|
4188
|
+
<h4>7. \u6B4C\u58F0\u30FB\u6B4C\u8A5E\u5165\u529B</h4>
|
|
4189
|
+
<p><code>@@<\u30C8\u30E9\u30C3\u30AF\u756A\u53F7> <\u97F3\u6E90\u540D> <\u6B4C\u8A5E></code> \u306E\u5F62\u5F0F\u3067\u3001\u97F3\u7B26\u3068\u540C\u671F\u3059\u308B\u6B4C\u8A5E\u3092\u5165\u529B\u3067\u304D\u307E\u3059\u3002</p>
|
|
4190
|
+
<pre>\u4F8B: @@0 tsukuyomi \u3069\u3093\u3050\u308A\u3053\u308D\u3053\u308D\u3069\u3093\u3050\u308A\u3053</pre>
|
|
4191
|
+
<p style="margin-top:4px; margin-bottom:16px;"><small>\uFF08\u97F3\u6E90\u540D\u306F <code>tsukuyomi</code> \u3084 <code>klatt</code>, <code>roze</code> \u306A\u3069\u306E\u97F3\u58F0\u30E2\u30C7\u30EB\u3092\u6307\u5B9A\u3067\u304D\u307E\u3059\uFF09</small></p>
|
|
4192
|
+
|
|
4193
|
+
<h4 style="margin-top: 18px; border-top: 1px solid var(--dtm-border2); padding-top: 8px;">\u30B5\u30F3\u30D7\u30EB\u66F2\uFF08\u8A66\u8074\u30FB\u30B3\u30D4\u30FC\uFF09</h4>
|
|
4194
|
+
|
|
4195
|
+
<!-- \u30B5\u30F3\u30D7\u30EB1 -->
|
|
4196
|
+
<div class="dtm-modal-sample-box">
|
|
4197
|
+
<div class="dtm-modal-sample-header">
|
|
4198
|
+
<span class="dtm-modal-sample-tag">1. \u57FA\u672C\u306E\u30E1\u30ED\u30C7\u30A3</span>
|
|
4199
|
+
<button class="dtm-btn dtm-btn--ghost dtm-btn--xs dtm-modal-sample-copy-btn" data-mml="@0 t120 l8 o5 c d e f g a b > c">\u{1F4CB} \u30B3\u30D4\u30FC</button>
|
|
4200
|
+
</div>
|
|
4201
|
+
<pre style="margin: 0; padding: 6px;">@0 t120 l8 o5 c d e f g a b > c</pre>
|
|
4202
|
+
<div class="dtm-modal-sample-desc">
|
|
4203
|
+
\u57FA\u672C\u7684\u306A\u30E1\u30ED\u30C7\u30A3\u306E\u66F8\u304D\u65B9\uFF08\u97F3\u540D\u30FB\u9577\u3055\u30FB\u30AA\u30AF\u30BF\u30FC\u30D6\u3068\u30C6\u30F3\u30DD\uFF09\u3002
|
|
4204
|
+
</div>
|
|
4205
|
+
<div style="margin-top: 8px;">
|
|
4206
|
+
<button class="dtm-btn dtm-btn--primary dtm-btn--xs dtm-modal-sample-play-btn" data-mml="@0 t120 l8 o5 c d e f g a b > c">\u25B6 \u8A66\u8074</button>
|
|
4207
|
+
</div>
|
|
4208
|
+
<div class="dtm-modal-sample-player-container"></div>
|
|
4209
|
+
</div>
|
|
4210
|
+
|
|
4211
|
+
<!-- \u30B5\u30F3\u30D7\u30EB2 -->
|
|
4212
|
+
<div class="dtm-modal-sample-box">
|
|
4213
|
+
<div class="dtm-modal-sample-header">
|
|
4214
|
+
<span class="dtm-modal-sample-tag">2. \u8907\u6570\u30C8\u30E9\u30C3\u30AF\u3068\u548C\u97F3</span>
|
|
4215
|
+
<button class="dtm-btn dtm-btn--ghost dtm-btn--xs dtm-modal-sample-copy-btn" data-mml="@0 t120 o5 c e g2 ; @3 o4 [ceg]2 [ceg]2">\u{1F4CB} \u30B3\u30D4\u30FC</button>
|
|
4216
|
+
</div>
|
|
4217
|
+
<pre style="margin: 0; padding: 6px;">@0 t120 o5 c e g2 ;
|
|
4218
|
+
@3 o4 [ceg]2 [ceg]2</pre>
|
|
4219
|
+
<div class="dtm-modal-sample-desc">
|
|
4220
|
+
; \u3067\u30C8\u30E9\u30C3\u30AF\uFF08\u4E0A\uFF1D\u30E1\u30ED\u30C7\u30A3\uFF0F\u4E0B\uFF1D\u4F34\u594F\uFF09\u3092\u5206\u3051\u3001[ceg] \u3067\u548C\u97F3\u3092\u9CF4\u3089\u3057\u307E\u3059\u3002
|
|
4221
|
+
</div>
|
|
4222
|
+
<div style="margin-top: 8px;">
|
|
4223
|
+
<button class="dtm-btn dtm-btn--primary dtm-btn--xs dtm-modal-sample-play-btn" data-mml="@0 t120 o5 c e g2 ; @3 o4 [ceg]2 [ceg]2">\u25B6 \u8A66\u8074</button>
|
|
4224
|
+
</div>
|
|
4225
|
+
<div class="dtm-modal-sample-player-container"></div>
|
|
4226
|
+
</div>
|
|
4227
|
+
|
|
4228
|
+
<!-- \u30B5\u30F3\u30D7\u30EB3 -->
|
|
4229
|
+
<div class="dtm-modal-sample-box">
|
|
4230
|
+
<div class="dtm-modal-sample-header">
|
|
4231
|
+
<span class="dtm-modal-sample-tag">3. \u6B4C\u5531\u4ED8\u304D (\u3069\u3093\u3050\u308A\u3053\u308D\u3053\u308D)</span>
|
|
4232
|
+
<button class="dtm-btn dtm-btn--ghost dtm-btn--xs dtm-modal-sample-copy-btn" data-mml="@0 t120 v100 o4g8 g8 e8 e8 f8 e8 d8 c8 g8 g8 e8 e8 d4.; @@0 tsukuyomi \u3069\u3093\u3050\u308A\u3053\u308D\u3053\u308D\u3069\u3093\u3050\u308A\u3053;">\u{1F4CB} \u30B3\u30D4\u30FC</button>
|
|
4233
|
+
</div>
|
|
4234
|
+
<pre style="margin: 0; padding: 6px;">@0 t120 v100 o4g8 g8 e8 e8 f8 e8 d8 c8 g8 g8 e8 e8 d4.;
|
|
4235
|
+
@@0 tsukuyomi \u3069\u3093\u3050\u308A\u3053\u308D\u3053\u308D\u3069\u3093\u3050\u308A\u3053;</pre>
|
|
4236
|
+
<div class="dtm-modal-sample-desc">
|
|
4237
|
+
@@0 tsukuyomi \u6B4C\u8A5E... \u3067\u30E1\u30ED\u30C7\u30A3\u30C8\u30E9\u30C3\u30AF\u306B\u6B4C\u8A5E\u3092\u540C\u671F\u3055\u305B\u3066\u6B4C\u308F\u305B\u307E\u3059\u3002\u203B\u72EC\u81EA\u62E1\u5F35
|
|
4238
|
+
</div>
|
|
4239
|
+
<div style="margin-top: 8px;">
|
|
4240
|
+
<button class="dtm-btn dtm-btn--primary dtm-btn--xs dtm-modal-sample-play-btn" data-mml="@0 t120 v100 o4g8 g8 e8 e8 f8 e8 d8 c8 g8 g8 e8 e8 d4.; @@0 tsukuyomi \u3069\u3093\u3050\u308A\u3053\u308D\u3053\u308D\u3069\u3093\u3050\u308A\u3053;">\u25B6 \u8A66\u8074</button>
|
|
4241
|
+
</div>
|
|
4242
|
+
<div class="dtm-modal-sample-player-container"></div>
|
|
4243
|
+
</div>
|
|
4244
|
+
</div>
|
|
4245
|
+
`;
|
|
4246
|
+
|
|
4020
4247
|
// src/mml-parser.ts
|
|
4021
4248
|
var PITCH_MAP2 = {
|
|
4022
4249
|
c: 0,
|
|
@@ -4069,6 +4296,7 @@ var parseMML = (mml, options = {}) => {
|
|
|
4069
4296
|
bpm,
|
|
4070
4297
|
tokenTracks: collectTokens ? tokenTracks : void 0,
|
|
4071
4298
|
lyrics: collectLyrics ? /* @__PURE__ */ new Map() : void 0,
|
|
4299
|
+
mergedTrackCount: 0,
|
|
4072
4300
|
meta: {}
|
|
4073
4301
|
};
|
|
4074
4302
|
}
|
|
@@ -4081,13 +4309,24 @@ var parseMML = (mml, options = {}) => {
|
|
|
4081
4309
|
const fullMML = stripLyrics(noMeta).replace(endRegex, "").replace(/[\n\r]+/g, " ").trim();
|
|
4082
4310
|
const parts = fullMML.split(/(@\d+)/).filter((p) => p.trim().length > 0);
|
|
4083
4311
|
let trackIndex = 0;
|
|
4312
|
+
let sourceTrackIndex = 0;
|
|
4084
4313
|
let octave = 4;
|
|
4085
4314
|
let currentStep = 0;
|
|
4086
4315
|
let baseLength = 16;
|
|
4316
|
+
const contributors = /* @__PURE__ */ new Map();
|
|
4317
|
+
const recordContributor = () => {
|
|
4318
|
+
let set = contributors.get(trackIndex);
|
|
4319
|
+
if (!set) {
|
|
4320
|
+
set = /* @__PURE__ */ new Set();
|
|
4321
|
+
contributors.set(trackIndex, set);
|
|
4322
|
+
}
|
|
4323
|
+
set.add(sourceTrackIndex);
|
|
4324
|
+
};
|
|
4087
4325
|
for (const rawPart of parts) {
|
|
4088
4326
|
const part = rawPart.trim();
|
|
4089
4327
|
if (part.startsWith("@")) {
|
|
4090
4328
|
let idx = Number.parseInt(part.substring(1), 10);
|
|
4329
|
+
sourceTrackIndex = idx;
|
|
4091
4330
|
if (clampTrackCount !== void 0 && idx >= clampTrackCount)
|
|
4092
4331
|
idx = clampTrackCount - 1;
|
|
4093
4332
|
trackIndex = idx;
|
|
@@ -4211,6 +4450,7 @@ var parseMML = (mml, options = {}) => {
|
|
|
4211
4450
|
}
|
|
4212
4451
|
if (j < body.length && body[j] === "]") j++;
|
|
4213
4452
|
const steps = parseLength();
|
|
4453
|
+
if (chordNotes.length > 0) recordContributor();
|
|
4214
4454
|
for (const p of chordNotes) {
|
|
4215
4455
|
placements.push({
|
|
4216
4456
|
trackIndex,
|
|
@@ -4234,6 +4474,7 @@ var parseMML = (mml, options = {}) => {
|
|
|
4234
4474
|
}
|
|
4235
4475
|
const midiPitch = (octave + 1) * 12 + pitch;
|
|
4236
4476
|
const steps = parseLength();
|
|
4477
|
+
recordContributor();
|
|
4237
4478
|
placements.push({
|
|
4238
4479
|
trackIndex,
|
|
4239
4480
|
startStep: currentStep,
|
|
@@ -4247,11 +4488,16 @@ var parseMML = (mml, options = {}) => {
|
|
|
4247
4488
|
}
|
|
4248
4489
|
}
|
|
4249
4490
|
}
|
|
4491
|
+
let mergedTrackCount = 0;
|
|
4492
|
+
for (const set of contributors.values()) {
|
|
4493
|
+
if (set.size >= 2) mergedTrackCount++;
|
|
4494
|
+
}
|
|
4250
4495
|
return {
|
|
4251
4496
|
placements,
|
|
4252
4497
|
bpm,
|
|
4253
4498
|
tokenTracks: collectTokens ? tokenTracks : void 0,
|
|
4254
4499
|
lyrics,
|
|
4500
|
+
mergedTrackCount,
|
|
4255
4501
|
meta
|
|
4256
4502
|
};
|
|
4257
4503
|
};
|
|
@@ -4313,6 +4559,8 @@ var createSequencer = (options) => {
|
|
|
4313
4559
|
let active = false;
|
|
4314
4560
|
let fromStepValue = 0;
|
|
4315
4561
|
let trackVolumeMap = /* @__PURE__ */ new Map();
|
|
4562
|
+
let lastRealTime = -1;
|
|
4563
|
+
let lastAudioTime = -1;
|
|
4316
4564
|
let isLooping = false;
|
|
4317
4565
|
let loopStartStep = 0;
|
|
4318
4566
|
let loopEndStep = 0;
|
|
@@ -4386,6 +4634,21 @@ var createSequencer = (options) => {
|
|
|
4386
4634
|
const sps = secondsPerStep();
|
|
4387
4635
|
const time = options.getAudioTime() - startTime;
|
|
4388
4636
|
const soloId = options.getSoloTrackId();
|
|
4637
|
+
const nowReal = performance.now() / 1e3;
|
|
4638
|
+
if (lastRealTime > 0 && lastAudioTime >= 0) {
|
|
4639
|
+
const realDelta = nowReal - lastRealTime;
|
|
4640
|
+
const audioDelta = time - lastAudioTime;
|
|
4641
|
+
if (realDelta > 0.5 || audioDelta > 0.5) {
|
|
4642
|
+
console.warn(
|
|
4643
|
+
`[sequencer] Interruption detected (realDelta: ${realDelta.toFixed(3)}s, audioDelta: ${audioDelta.toFixed(3)}s). Stopping playback.`
|
|
4644
|
+
);
|
|
4645
|
+
stop();
|
|
4646
|
+
options.onEnd(true);
|
|
4647
|
+
return;
|
|
4648
|
+
}
|
|
4649
|
+
}
|
|
4650
|
+
lastRealTime = nowReal;
|
|
4651
|
+
lastAudioTime = time;
|
|
4389
4652
|
for (const track of options.getTracks()) {
|
|
4390
4653
|
trackVolumeMap.set(track.id, track.volume);
|
|
4391
4654
|
}
|
|
@@ -4462,7 +4725,7 @@ var createSequencer = (options) => {
|
|
|
4462
4725
|
const lastDuration = last?.duration ?? 0;
|
|
4463
4726
|
if (nowIndex >= timeline.length && time > lastWhen + lastDuration + 0.1) {
|
|
4464
4727
|
stop();
|
|
4465
|
-
options.onEnd();
|
|
4728
|
+
options.onEnd(false);
|
|
4466
4729
|
}
|
|
4467
4730
|
}
|
|
4468
4731
|
};
|
|
@@ -4503,6 +4766,8 @@ var createSequencer = (options) => {
|
|
|
4503
4766
|
}
|
|
4504
4767
|
loopBase = 0;
|
|
4505
4768
|
lastPlayStep = fromStepValue - 1e-4;
|
|
4769
|
+
lastRealTime = -1;
|
|
4770
|
+
lastAudioTime = -1;
|
|
4506
4771
|
intervalId = setInterval(scheduleTick, TICK_INTERVAL_MS);
|
|
4507
4772
|
animationId = requestAnimationFrame(animate);
|
|
4508
4773
|
};
|
|
@@ -4601,9 +4866,13 @@ var DAW_CSS = `
|
|
|
4601
4866
|
/* \u30C7\u30B6\u30A4\u30F3\u30C8\u30FC\u30AF\u30F3\u306F\u7DE8\u96C6UI\u672C\u4F53\uFF08.dtm-daw\uFF09\u306B\u52A0\u3048\u3001\u305D\u306E\u5916\u5074\u306B\u5DEE\u3057\u8FBC\u307E\u308C\u308B
|
|
4602
4867
|
\u30B3\u30F3\u30C8\u30ED\u30FC\u30EB\u30D0\u30FC\uFF08.dtm-controlbar\uFF09\u306B\u3082\u4F9B\u7D66\u3059\u308B\u3002mountPresetSelect /
|
|
4603
4868
|
mountModeSwitch \u306EUI\u306F .dtm-daw \u306E\u5144\u5F1F\u3068\u3057\u3066\u7F6E\u304B\u308C\u308B\u305F\u3081\u3001\u3053\u3053\u3067\u914D\u3089\u306A\u3044\u3068
|
|
4604
|
-
var(--dtm-*) \u304C\u89E3\u6C7A\u3067\u304D\u305A\u7121\u88C5\u98FE\uFF08\u767D\u5730\u30FB\u65E2\u5B9A\u30D5\u30A9\u30F3\u30C8\uFF09\u306B\u306A\u3063\u3066\u3057\u307E\u3046\u3002
|
|
4869
|
+
var(--dtm-*) \u304C\u89E3\u6C7A\u3067\u304D\u305A\u7121\u88C5\u98FE\uFF08\u767D\u5730\u30FB\u65E2\u5B9A\u30D5\u30A9\u30F3\u30C8\uFF09\u306B\u306A\u3063\u3066\u3057\u307E\u3046\u3002
|
|
4870
|
+
\u518D\u751F\u5C02\u7528\u30D3\u30E5\u30FC\u306E\u30E2\u30FC\u30C0\u30EB\uFF0F\u5229\u7528\u898F\u7D04\u30AB\u30D0\u30FC\u306F document.body \u76F4\u4E0B\u3078\u91CD\u306D\u308B\u305F\u3081\u3001
|
|
4871
|
+
.dtm-daw \u306E\u5916\u306B\u51FA\u308B\u3002\u3053\u308C\u3089\u3082\u540C\u69D8\u306B\u30C8\u30FC\u30AF\u30F3\u3092\u4F9B\u7D66\u3057\u306A\u3044\u3068\u9ED2\u5730\u30FB\u767D\u6587\u5B57\u306B\u306A\u308B\u3002 */
|
|
4605
4872
|
.dtm-daw,
|
|
4606
|
-
.dtm-controlbar
|
|
4873
|
+
.dtm-controlbar,
|
|
4874
|
+
.dtm-modal-overlay,
|
|
4875
|
+
.dtm-consent-overlay {
|
|
4607
4876
|
/* PICO-8 16\u8272\u30D1\u30EC\u30C3\u30C8\u3088\u308A */
|
|
4608
4877
|
--c-black: #000000;
|
|
4609
4878
|
--c-navy: #1d2b53;
|
|
@@ -4700,11 +4969,11 @@ var DAW_CSS = `
|
|
|
4700
4969
|
}
|
|
4701
4970
|
.dtm-btn:active { transform: translate(3px,3px); box-shadow: none; }
|
|
4702
4971
|
.dtm-btn:disabled { opacity: .3; cursor: default; box-shadow: none; }
|
|
4972
|
+
.dtm-btn--ghost { background: transparent; border-color: var(--dtm-border2); }
|
|
4703
4973
|
.dtm-btn--primary { border-color: var(--dtm-primary); background: var(--dtm-primary); color: var(--dtm-pfg); }
|
|
4704
4974
|
.dtm-btn--success { border-color: var(--dtm-success); background: var(--dtm-success); color: var(--c-black); }
|
|
4705
4975
|
.dtm-btn--danger { border-color: var(--dtm-danger); background: var(--dtm-danger); color: var(--c-white); }
|
|
4706
4976
|
.dtm-btn--accent { border-color: var(--dtm-accent); background: var(--dtm-accent); color: var(--c-black); }
|
|
4707
|
-
.dtm-btn--ghost { background: transparent; border-color: var(--dtm-border2); }
|
|
4708
4977
|
.dtm-btn--icon { padding: 0; }
|
|
4709
4978
|
|
|
4710
4979
|
/* \u2500\u2500\u2500 \u30A2\u30A4\u30B3\u30F3\u30DC\u30BF\u30F3 \u2500\u2500\u2500 */
|
|
@@ -5201,14 +5470,37 @@ var DAW_CSS = `
|
|
|
5201
5470
|
justify-content: center;
|
|
5202
5471
|
padding: 16px;
|
|
5203
5472
|
backdrop-filter: blur(2px);
|
|
5473
|
+
/* body\u76F4\u4E0B\u306B\u91CD\u306D\u305F\u5834\u5408\uFF08\u518D\u751F\u5C02\u7528\u30D3\u30E5\u30FC\uFF09\u3067\u3082\u6587\u5B57\u8272\u30FB\u30D5\u30A9\u30F3\u30C8\u304C
|
|
5474
|
+
.dtm-daw \u304B\u3089\u7D99\u627F\u3067\u304D\u306A\u3044\u305F\u3081\u3001\u3053\u3053\u3067\u660E\u793A\u3059\u308B\u3002 */
|
|
5475
|
+
color: var(--dtm-text);
|
|
5476
|
+
font-family: var(--dtm-font);
|
|
5204
5477
|
}
|
|
5205
5478
|
.dtm-modal-overlay[hidden] {
|
|
5206
5479
|
display: none !important;
|
|
5207
5480
|
}
|
|
5208
|
-
|
|
5209
|
-
|
|
5481
|
+
|
|
5482
|
+
/* \u2500\u2500\u2500 \u5229\u7528\u898F\u7D04\u540C\u610F\u30AB\u30D0\u30FC \u2500\u2500\u2500 */
|
|
5483
|
+
.dtm-consent-overlay {
|
|
5484
|
+
position: fixed;
|
|
5485
|
+
inset: 0;
|
|
5486
|
+
z-index: 10100;
|
|
5487
|
+
background: rgba(0, 0, 0, 0.6);
|
|
5488
|
+
display: flex;
|
|
5489
|
+
align-items: center;
|
|
5490
|
+
justify-content: center;
|
|
5491
|
+
padding: 16px;
|
|
5492
|
+
backdrop-filter: blur(2px);
|
|
5493
|
+
/* body\u76F4\u4E0B\u306B\u91CD\u306D\u308B\u305F\u3081 .dtm-daw \u304B\u3089\u7D99\u627F\u3067\u304D\u306A\u3044\u6587\u5B57\u8272\u30FB\u30D5\u30A9\u30F3\u30C8\u3092\u660E\u793A\u3002 */
|
|
5494
|
+
color: var(--dtm-text);
|
|
5495
|
+
font-family: var(--dtm-font);
|
|
5496
|
+
}
|
|
5497
|
+
.dtm-consent-overlay[hidden] {
|
|
5498
|
+
display: none !important;
|
|
5499
|
+
}
|
|
5500
|
+
.dtm-consent-modal {
|
|
5501
|
+
max-width: 450px;
|
|
5210
5502
|
width: 100%;
|
|
5211
|
-
max-height:
|
|
5503
|
+
max-height: 85vh;
|
|
5212
5504
|
display: flex;
|
|
5213
5505
|
flex-direction: column;
|
|
5214
5506
|
background: var(--dtm-surface);
|
|
@@ -5217,20 +5509,63 @@ var DAW_CSS = `
|
|
|
5217
5509
|
inset 0 0 0 2px var(--c-black),
|
|
5218
5510
|
0 0 0 2px var(--dtm-primary),
|
|
5219
5511
|
4px 4px 0 var(--c-black);
|
|
5220
|
-
overflow:
|
|
5512
|
+
overflow-y: auto;
|
|
5221
5513
|
}
|
|
5222
|
-
.dtm-
|
|
5223
|
-
display: flex;
|
|
5224
|
-
align-items: center;
|
|
5225
|
-
justify-content: space-between;
|
|
5514
|
+
.dtm-consent-header {
|
|
5226
5515
|
background: var(--dtm-deep);
|
|
5516
|
+
color: var(--dtm-text);
|
|
5227
5517
|
padding: 8px 12px;
|
|
5228
5518
|
border-bottom: 2px solid var(--c-black);
|
|
5229
|
-
|
|
5230
|
-
|
|
5231
|
-
font-
|
|
5232
|
-
|
|
5233
|
-
|
|
5519
|
+
font-weight: bold;
|
|
5520
|
+
text-align: center;
|
|
5521
|
+
font-size: 14px;
|
|
5522
|
+
}
|
|
5523
|
+
.dtm-consent-body {
|
|
5524
|
+
padding: 12px 16px;
|
|
5525
|
+
font-size: 13px;
|
|
5526
|
+
line-height: 1.6;
|
|
5527
|
+
}
|
|
5528
|
+
.dtm-consent-body a {
|
|
5529
|
+
color: var(--dtm-primary);
|
|
5530
|
+
text-decoration: underline;
|
|
5531
|
+
}
|
|
5532
|
+
.dtm-consent-body a:hover {
|
|
5533
|
+
color: var(--dtm-accent);
|
|
5534
|
+
}
|
|
5535
|
+
.dtm-consent-footer {
|
|
5536
|
+
padding: 8px;
|
|
5537
|
+
border-top: 2px solid var(--c-black);
|
|
5538
|
+
background: var(--dtm-deep);
|
|
5539
|
+
display: flex;
|
|
5540
|
+
justify-content: center;
|
|
5541
|
+
}
|
|
5542
|
+
|
|
5543
|
+
.dtm-modal {
|
|
5544
|
+
max-width: 500px;
|
|
5545
|
+
width: 100%;
|
|
5546
|
+
max-height: 80vh;
|
|
5547
|
+
display: flex;
|
|
5548
|
+
flex-direction: column;
|
|
5549
|
+
background: var(--dtm-surface);
|
|
5550
|
+
border: 2px solid var(--c-black);
|
|
5551
|
+
box-shadow:
|
|
5552
|
+
inset 0 0 0 2px var(--c-black),
|
|
5553
|
+
0 0 0 2px var(--dtm-primary),
|
|
5554
|
+
4px 4px 0 var(--c-black);
|
|
5555
|
+
overflow: hidden;
|
|
5556
|
+
}
|
|
5557
|
+
.dtm-modal-header {
|
|
5558
|
+
display: flex;
|
|
5559
|
+
align-items: center;
|
|
5560
|
+
justify-content: space-between;
|
|
5561
|
+
background: var(--dtm-deep);
|
|
5562
|
+
padding: 8px 12px;
|
|
5563
|
+
border-bottom: 2px solid var(--c-black);
|
|
5564
|
+
}
|
|
5565
|
+
.dtm-modal-title {
|
|
5566
|
+
font-family: var(--dtm-font);
|
|
5567
|
+
font-size: 14px;
|
|
5568
|
+
color: var(--dtm-gold);
|
|
5234
5569
|
font-weight: bold;
|
|
5235
5570
|
}
|
|
5236
5571
|
.dtm-modal-close {
|
|
@@ -5338,6 +5673,19 @@ var DAW_CSS = `
|
|
|
5338
5673
|
}
|
|
5339
5674
|
|
|
5340
5675
|
.dtm-hidden { display: none !important; }
|
|
5676
|
+
/* \u8AAD\u8FBC\u6642\u306E\u8B66\u544A\u304A\u77E5\u3089\u305B\uFF08\u4F8B: \u30B7\u30F3\u30D7\u30EB\u30E2\u30FC\u30C9\u3067\u306E\u30C8\u30E9\u30C3\u30AF\u5408\u7B97\uFF09\u3002 */
|
|
5677
|
+
.dtm-load-note {
|
|
5678
|
+
margin: 6px 0 0;
|
|
5679
|
+
padding: 0 2px;
|
|
5680
|
+
font-family: var(--dtm-font);
|
|
5681
|
+
font-size: 11px;
|
|
5682
|
+
line-height: 1.5;
|
|
5683
|
+
letter-spacing: .04em;
|
|
5684
|
+
color: var(--dtm-warn); /* \u8B66\u544A\u8272\uFF08\u30AA\u30EC\u30F3\u30B8\uFF09 */
|
|
5685
|
+
font-weight: bold;
|
|
5686
|
+
opacity: 1.0;
|
|
5687
|
+
}
|
|
5688
|
+
.dtm-load-note::before { content: "\u26A0 "; }
|
|
5341
5689
|
.dtm-grow { flex: 1 1 auto; }
|
|
5342
5690
|
.dtm-lyric-icon {
|
|
5343
5691
|
flex: 0 0 auto;
|
|
@@ -5437,6 +5785,62 @@ var DAW_CSS = `
|
|
|
5437
5785
|
white-space: nowrap;
|
|
5438
5786
|
}
|
|
5439
5787
|
.dtm-player-mml-link:hover { color: var(--dtm-primary); }
|
|
5788
|
+
.dtm-player-more-container {
|
|
5789
|
+
position: relative;
|
|
5790
|
+
display: inline-flex;
|
|
5791
|
+
align-items: center;
|
|
5792
|
+
}
|
|
5793
|
+
.dtm-player-more-btn {
|
|
5794
|
+
background: transparent;
|
|
5795
|
+
border: none;
|
|
5796
|
+
color: var(--dtm-muted);
|
|
5797
|
+
cursor: pointer;
|
|
5798
|
+
padding: 2px;
|
|
5799
|
+
display: flex;
|
|
5800
|
+
align-items: center;
|
|
5801
|
+
justify-content: center;
|
|
5802
|
+
border-radius: 50%;
|
|
5803
|
+
width: 24px;
|
|
5804
|
+
height: 24px;
|
|
5805
|
+
transition: color 0.15s, background-color 0.15s;
|
|
5806
|
+
}
|
|
5807
|
+
.dtm-player-more-btn:hover,
|
|
5808
|
+
.dtm-player-more-btn.is-active {
|
|
5809
|
+
color: var(--dtm-text);
|
|
5810
|
+
background: var(--dtm-border2);
|
|
5811
|
+
}
|
|
5812
|
+
.dtm-player-menu {
|
|
5813
|
+
position: absolute;
|
|
5814
|
+
top: calc(100% + 4px);
|
|
5815
|
+
right: 0;
|
|
5816
|
+
background: var(--dtm-deep);
|
|
5817
|
+
border: 2px solid var(--dtm-border2);
|
|
5818
|
+
box-shadow: 4px 4px 0 var(--c-black);
|
|
5819
|
+
z-index: 200;
|
|
5820
|
+
display: flex;
|
|
5821
|
+
flex-direction: column;
|
|
5822
|
+
padding: 4px 0;
|
|
5823
|
+
min-width: 130px;
|
|
5824
|
+
font-family: var(--dtm-font);
|
|
5825
|
+
}
|
|
5826
|
+
.dtm-player-menu-item {
|
|
5827
|
+
background: transparent;
|
|
5828
|
+
border: none;
|
|
5829
|
+
color: var(--dtm-text);
|
|
5830
|
+
padding: 6px 12px;
|
|
5831
|
+
text-align: left;
|
|
5832
|
+
cursor: pointer;
|
|
5833
|
+
font-size: 11px;
|
|
5834
|
+
font-family: inherit;
|
|
5835
|
+
white-space: nowrap;
|
|
5836
|
+
width: 100%;
|
|
5837
|
+
box-sizing: border-box;
|
|
5838
|
+
transition: background-color 0.1s, color 0.1s;
|
|
5839
|
+
}
|
|
5840
|
+
.dtm-player-menu-item:hover {
|
|
5841
|
+
background: var(--dtm-primary);
|
|
5842
|
+
color: var(--dtm-pfg);
|
|
5843
|
+
}
|
|
5440
5844
|
.dtm-player-emoji {
|
|
5441
5845
|
position: relative;
|
|
5442
5846
|
display: inline-flex;
|
|
@@ -5682,6 +6086,7 @@ var STEPS_PER_BEAT3 = 48;
|
|
|
5682
6086
|
var STEPS_PER_BAR = 192;
|
|
5683
6087
|
var DEFAULT_TRACK_COLORS = ["#00e436", "#29adff", "#ff77a8", "#ffec27"];
|
|
5684
6088
|
var activePlayer = null;
|
|
6089
|
+
var agreedModelsInSession = /* @__PURE__ */ new Set();
|
|
5685
6090
|
var LYRIC_MODEL_LABELS = {
|
|
5686
6091
|
klatt: "\u8EFD\u91CF\u30ED\u30DC\u58F0",
|
|
5687
6092
|
...KOE_VOICEBANK_LABELS
|
|
@@ -5712,6 +6117,75 @@ var showBalloon = (balloonEl) => {
|
|
|
5712
6117
|
hideActiveBalloon();
|
|
5713
6118
|
}, 3e3);
|
|
5714
6119
|
};
|
|
6120
|
+
var copyToClipboard = async (doc, text) => {
|
|
6121
|
+
try {
|
|
6122
|
+
await navigator.clipboard.writeText(text);
|
|
6123
|
+
return true;
|
|
6124
|
+
} catch {
|
|
6125
|
+
try {
|
|
6126
|
+
const textarea = doc.createElement("textarea");
|
|
6127
|
+
textarea.value = text;
|
|
6128
|
+
textarea.style.position = "fixed";
|
|
6129
|
+
textarea.style.opacity = "0";
|
|
6130
|
+
doc.body.appendChild(textarea);
|
|
6131
|
+
textarea.select();
|
|
6132
|
+
const ok = doc.execCommand("copy");
|
|
6133
|
+
doc.body.removeChild(textarea);
|
|
6134
|
+
return ok;
|
|
6135
|
+
} catch {
|
|
6136
|
+
return false;
|
|
6137
|
+
}
|
|
6138
|
+
}
|
|
6139
|
+
};
|
|
6140
|
+
var toBase64Url = (bytes) => {
|
|
6141
|
+
let bin = "";
|
|
6142
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
6143
|
+
bin += String.fromCharCode(bytes[i]);
|
|
6144
|
+
}
|
|
6145
|
+
return btoa(bin).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
6146
|
+
};
|
|
6147
|
+
var HIRAGANA_START = 12353;
|
|
6148
|
+
var HIRAGANA_END = 12447;
|
|
6149
|
+
var KATAKANA_START = 12449;
|
|
6150
|
+
var KATAKANA_END = 12543;
|
|
6151
|
+
var PROLONGED_MARK = 12540;
|
|
6152
|
+
var SHIFT_KATAKANA = 255;
|
|
6153
|
+
var VALUE_PROLONGED = 223;
|
|
6154
|
+
var customEncode = (str) => {
|
|
6155
|
+
const bytes = [];
|
|
6156
|
+
for (let i = 0; i < str.length; i++) {
|
|
6157
|
+
const code = str.charCodeAt(i);
|
|
6158
|
+
if (code <= 127) {
|
|
6159
|
+
bytes.push(code);
|
|
6160
|
+
} else if (code === PROLONGED_MARK) {
|
|
6161
|
+
bytes.push(VALUE_PROLONGED);
|
|
6162
|
+
} else if (code >= HIRAGANA_START && code <= HIRAGANA_END) {
|
|
6163
|
+
bytes.push(128 + (code - HIRAGANA_START));
|
|
6164
|
+
} else if (code >= KATAKANA_START && code <= KATAKANA_END) {
|
|
6165
|
+
bytes.push(SHIFT_KATAKANA);
|
|
6166
|
+
bytes.push(128 + (code - 96 - HIRAGANA_START));
|
|
6167
|
+
}
|
|
6168
|
+
}
|
|
6169
|
+
return new Uint8Array(bytes);
|
|
6170
|
+
};
|
|
6171
|
+
var encodeMml = async (mml) => {
|
|
6172
|
+
try {
|
|
6173
|
+
if (typeof CompressionStream !== "undefined") {
|
|
6174
|
+
const cs = new CompressionStream("gzip");
|
|
6175
|
+
const w = cs.writable.getWriter();
|
|
6176
|
+
w.write(customEncode(mml));
|
|
6177
|
+
w.close();
|
|
6178
|
+
const buf = await new Response(cs.readable).arrayBuffer();
|
|
6179
|
+
return `z.${toBase64Url(new Uint8Array(buf))}`;
|
|
6180
|
+
}
|
|
6181
|
+
} catch (e) {
|
|
6182
|
+
console.warn(
|
|
6183
|
+
"[dtm] CompressionStream failed, fallback to encodeURIComponent",
|
|
6184
|
+
e
|
|
6185
|
+
);
|
|
6186
|
+
}
|
|
6187
|
+
return `u.${encodeURIComponent(mml)}`;
|
|
6188
|
+
};
|
|
5715
6189
|
var mountMmlPlayer = (target, mml, options = {}) => {
|
|
5716
6190
|
injectStyles(target.ownerDocument ?? document);
|
|
5717
6191
|
const {
|
|
@@ -5857,6 +6331,250 @@ var mountMmlPlayer = (target, mml, options = {}) => {
|
|
|
5857
6331
|
emojiEls.push(em);
|
|
5858
6332
|
emojiByTrack.set(index, em);
|
|
5859
6333
|
}
|
|
6334
|
+
const menuContainer = doc.createElement("div");
|
|
6335
|
+
menuContainer.className = "dtm-player-more-container";
|
|
6336
|
+
const moreBtn = doc.createElement("button");
|
|
6337
|
+
moreBtn.type = "button";
|
|
6338
|
+
moreBtn.className = "dtm-player-more-btn";
|
|
6339
|
+
moreBtn.innerHTML = icon("more", 14);
|
|
6340
|
+
moreBtn.title = "\u30E1\u30CB\u30E5\u30FC";
|
|
6341
|
+
menuContainer.appendChild(moreBtn);
|
|
6342
|
+
const menuDropdown = doc.createElement("div");
|
|
6343
|
+
menuDropdown.className = "dtm-player-menu";
|
|
6344
|
+
menuDropdown.style.display = "none";
|
|
6345
|
+
const makeMenuItem = (label) => {
|
|
6346
|
+
const item = doc.createElement("button");
|
|
6347
|
+
item.type = "button";
|
|
6348
|
+
item.className = "dtm-player-menu-item";
|
|
6349
|
+
item.textContent = label;
|
|
6350
|
+
return item;
|
|
6351
|
+
};
|
|
6352
|
+
const showMmlItem = makeMenuItem("MML\u3092\u8868\u793A");
|
|
6353
|
+
const mmlInfoItem = makeMenuItem("MML\u66F8\u5F0F\u3068\u306F");
|
|
6354
|
+
const embedItem = makeMenuItem("\u57CB\u3081\u8FBC\u3080");
|
|
6355
|
+
const copyMmlItem = makeMenuItem("MML\u30B3\u30D4\u30FC");
|
|
6356
|
+
menuDropdown.appendChild(showMmlItem);
|
|
6357
|
+
menuDropdown.appendChild(mmlInfoItem);
|
|
6358
|
+
menuDropdown.appendChild(embedItem);
|
|
6359
|
+
menuDropdown.appendChild(copyMmlItem);
|
|
6360
|
+
menuContainer.appendChild(menuDropdown);
|
|
6361
|
+
mmlHeader.appendChild(menuContainer);
|
|
6362
|
+
const toggleMenu = (show) => {
|
|
6363
|
+
const visible = show !== void 0 ? show : menuDropdown.style.display === "none";
|
|
6364
|
+
menuDropdown.style.display = visible ? "flex" : "none";
|
|
6365
|
+
if (visible) {
|
|
6366
|
+
moreBtn.classList.add("is-active");
|
|
6367
|
+
doc.addEventListener("click", handleOutsideClick);
|
|
6368
|
+
} else {
|
|
6369
|
+
moreBtn.classList.remove("is-active");
|
|
6370
|
+
doc.removeEventListener("click", handleOutsideClick);
|
|
6371
|
+
}
|
|
6372
|
+
};
|
|
6373
|
+
const handleOutsideClick = (e) => {
|
|
6374
|
+
if (!menuContainer.contains(e.target)) {
|
|
6375
|
+
toggleMenu(false);
|
|
6376
|
+
}
|
|
6377
|
+
};
|
|
6378
|
+
moreBtn.addEventListener("click", (e) => {
|
|
6379
|
+
e.stopPropagation();
|
|
6380
|
+
toggleMenu();
|
|
6381
|
+
});
|
|
6382
|
+
let infoModalEl = null;
|
|
6383
|
+
let modalSamplePlayer = null;
|
|
6384
|
+
const closeInfoModal = () => {
|
|
6385
|
+
if (modalSamplePlayer) {
|
|
6386
|
+
modalSamplePlayer.stop();
|
|
6387
|
+
modalSamplePlayer.destroy();
|
|
6388
|
+
modalSamplePlayer = null;
|
|
6389
|
+
}
|
|
6390
|
+
infoModalEl?.remove();
|
|
6391
|
+
infoModalEl = null;
|
|
6392
|
+
};
|
|
6393
|
+
const openInfoModal = (title) => {
|
|
6394
|
+
closeInfoModal();
|
|
6395
|
+
const overlay = doc.createElement("div");
|
|
6396
|
+
overlay.className = "dtm-modal-overlay";
|
|
6397
|
+
const modal = doc.createElement("div");
|
|
6398
|
+
modal.className = "dtm-win dtm-modal";
|
|
6399
|
+
const header = doc.createElement("div");
|
|
6400
|
+
header.className = "dtm-modal-header";
|
|
6401
|
+
const titleEl = doc.createElement("span");
|
|
6402
|
+
titleEl.className = "dtm-modal-title";
|
|
6403
|
+
titleEl.textContent = title;
|
|
6404
|
+
const closeBtn = doc.createElement("button");
|
|
6405
|
+
closeBtn.type = "button";
|
|
6406
|
+
closeBtn.className = "dtm-modal-close";
|
|
6407
|
+
closeBtn.innerHTML = "×";
|
|
6408
|
+
closeBtn.title = "\u9589\u3058\u308B";
|
|
6409
|
+
header.append(titleEl, closeBtn);
|
|
6410
|
+
const modalBody = doc.createElement("div");
|
|
6411
|
+
modalBody.className = "dtm-modal-body";
|
|
6412
|
+
modal.append(header, modalBody);
|
|
6413
|
+
overlay.appendChild(modal);
|
|
6414
|
+
closeBtn.addEventListener("click", (e) => {
|
|
6415
|
+
e.stopPropagation();
|
|
6416
|
+
closeInfoModal();
|
|
6417
|
+
});
|
|
6418
|
+
overlay.addEventListener("click", (e) => {
|
|
6419
|
+
if (e.target === overlay) closeInfoModal();
|
|
6420
|
+
});
|
|
6421
|
+
doc.body.appendChild(overlay);
|
|
6422
|
+
infoModalEl = overlay;
|
|
6423
|
+
return modalBody;
|
|
6424
|
+
};
|
|
6425
|
+
const appendCopyButton = (parent, text) => {
|
|
6426
|
+
const actions = doc.createElement("div");
|
|
6427
|
+
actions.style.marginTop = "8px";
|
|
6428
|
+
const copyBtn = doc.createElement("button");
|
|
6429
|
+
copyBtn.type = "button";
|
|
6430
|
+
copyBtn.className = "dtm-btn dtm-btn--primary dtm-btn--xs";
|
|
6431
|
+
copyBtn.textContent = "\u{1F4CB} \u30B3\u30D4\u30FC";
|
|
6432
|
+
copyBtn.addEventListener("click", async (e) => {
|
|
6433
|
+
e.stopPropagation();
|
|
6434
|
+
const ok = await copyToClipboard(doc, text);
|
|
6435
|
+
copyBtn.textContent = ok ? "\u2713 \u30B3\u30D4\u30FC\u5B8C\u4E86" : "\u30B3\u30D4\u30FC\u5931\u6557";
|
|
6436
|
+
if (ok) copyBtn.classList.add("dtm-btn--success");
|
|
6437
|
+
setTimeout(() => {
|
|
6438
|
+
copyBtn.textContent = "\u{1F4CB} \u30B3\u30D4\u30FC";
|
|
6439
|
+
copyBtn.classList.remove("dtm-btn--success");
|
|
6440
|
+
}, 1200);
|
|
6441
|
+
});
|
|
6442
|
+
actions.appendChild(copyBtn);
|
|
6443
|
+
parent.appendChild(actions);
|
|
6444
|
+
};
|
|
6445
|
+
const wireSampleButtons = (modalBody) => {
|
|
6446
|
+
const copyBtns = modalBody.querySelectorAll(".dtm-modal-sample-copy-btn");
|
|
6447
|
+
for (const btn of copyBtns) {
|
|
6448
|
+
const el = btn;
|
|
6449
|
+
el.addEventListener("click", async (e) => {
|
|
6450
|
+
e.stopPropagation();
|
|
6451
|
+
const sampleMml = el.getAttribute("data-mml") ?? "";
|
|
6452
|
+
const original = el.textContent;
|
|
6453
|
+
const ok = await copyToClipboard(doc, sampleMml);
|
|
6454
|
+
el.textContent = ok ? "\u2713 \u30B3\u30D4\u30FC\u5B8C\u4E86" : "\u30B3\u30D4\u30FC\u5931\u6557";
|
|
6455
|
+
if (ok) el.classList.add("dtm-btn--success");
|
|
6456
|
+
setTimeout(() => {
|
|
6457
|
+
el.textContent = original;
|
|
6458
|
+
el.classList.remove("dtm-btn--success");
|
|
6459
|
+
}, 1200);
|
|
6460
|
+
});
|
|
6461
|
+
}
|
|
6462
|
+
let activeSampleBtn = null;
|
|
6463
|
+
const resetSampleBtn = (b) => {
|
|
6464
|
+
if (!b) return;
|
|
6465
|
+
b.textContent = "\u25B6 \u8A66\u8074";
|
|
6466
|
+
b.classList.remove("dtm-btn--danger");
|
|
6467
|
+
b.classList.add("dtm-btn--primary");
|
|
6468
|
+
};
|
|
6469
|
+
const markPlaying = (b) => {
|
|
6470
|
+
b.textContent = "\u25A0 \u505C\u6B62";
|
|
6471
|
+
b.classList.remove("dtm-btn--primary");
|
|
6472
|
+
b.classList.add("dtm-btn--danger");
|
|
6473
|
+
};
|
|
6474
|
+
const playBtns = modalBody.querySelectorAll(".dtm-modal-sample-play-btn");
|
|
6475
|
+
for (const btn of playBtns) {
|
|
6476
|
+
const el = btn;
|
|
6477
|
+
el.addEventListener("click", (e) => {
|
|
6478
|
+
e.stopPropagation();
|
|
6479
|
+
const sampleMml = el.getAttribute("data-mml") ?? "";
|
|
6480
|
+
if (activeSampleBtn === el && modalSamplePlayer) {
|
|
6481
|
+
if (modalSamplePlayer.isPlaying()) {
|
|
6482
|
+
modalSamplePlayer.stop();
|
|
6483
|
+
} else {
|
|
6484
|
+
modalSamplePlayer.play();
|
|
6485
|
+
markPlaying(el);
|
|
6486
|
+
}
|
|
6487
|
+
return;
|
|
6488
|
+
}
|
|
6489
|
+
if (modalSamplePlayer) {
|
|
6490
|
+
modalSamplePlayer.stop();
|
|
6491
|
+
modalSamplePlayer.destroy();
|
|
6492
|
+
modalSamplePlayer = null;
|
|
6493
|
+
}
|
|
6494
|
+
resetSampleBtn(activeSampleBtn);
|
|
6495
|
+
activeSampleBtn = el;
|
|
6496
|
+
const sampleBox = el.closest(".dtm-modal-sample-box");
|
|
6497
|
+
const container = sampleBox?.querySelector(
|
|
6498
|
+
".dtm-modal-sample-player-container"
|
|
6499
|
+
);
|
|
6500
|
+
if (!container) return;
|
|
6501
|
+
container.innerHTML = "";
|
|
6502
|
+
modalSamplePlayer = mountMmlPlayer(container, sampleMml, {
|
|
6503
|
+
onPlayNote: options.onPlayNote,
|
|
6504
|
+
onPlayDrum: options.onPlayDrum,
|
|
6505
|
+
onResumeAudio: options.onResumeAudio,
|
|
6506
|
+
getAudioTime: options.getAudioTime,
|
|
6507
|
+
singingVoices: options.singingVoices,
|
|
6508
|
+
drumPatterns: options.drumPatterns,
|
|
6509
|
+
volume: trackVolume,
|
|
6510
|
+
// 解説モーダル内の試聴サンプルは規約同意を要求しない。
|
|
6511
|
+
skipConsent: true,
|
|
6512
|
+
onStop: () => {
|
|
6513
|
+
if (activeSampleBtn === el) resetSampleBtn(el);
|
|
6514
|
+
}
|
|
6515
|
+
});
|
|
6516
|
+
markPlaying(el);
|
|
6517
|
+
modalSamplePlayer.play();
|
|
6518
|
+
});
|
|
6519
|
+
}
|
|
6520
|
+
};
|
|
6521
|
+
showMmlItem.addEventListener("click", (e) => {
|
|
6522
|
+
e.stopPropagation();
|
|
6523
|
+
toggleMenu(false);
|
|
6524
|
+
const modalBody = openInfoModal("MML");
|
|
6525
|
+
const pre = doc.createElement("pre");
|
|
6526
|
+
pre.textContent = mml;
|
|
6527
|
+
pre.style.whiteSpace = "pre-wrap";
|
|
6528
|
+
pre.style.wordBreak = "break-all";
|
|
6529
|
+
modalBody.appendChild(pre);
|
|
6530
|
+
appendCopyButton(modalBody, mml);
|
|
6531
|
+
});
|
|
6532
|
+
mmlInfoItem.addEventListener("click", (e) => {
|
|
6533
|
+
e.stopPropagation();
|
|
6534
|
+
toggleMenu(false);
|
|
6535
|
+
const modalBody = openInfoModal("MML\u306E\u66F8\u304D\u65B9\u89E3\u8AAC");
|
|
6536
|
+
modalBody.innerHTML = MML_INFO_HTML;
|
|
6537
|
+
wireSampleButtons(modalBody);
|
|
6538
|
+
});
|
|
6539
|
+
embedItem.addEventListener("click", async (e) => {
|
|
6540
|
+
e.stopPropagation();
|
|
6541
|
+
toggleMenu(false);
|
|
6542
|
+
const modalBody = openInfoModal("\u57CB\u3081\u8FBC\u307F");
|
|
6543
|
+
const loading = doc.createElement("p");
|
|
6544
|
+
loading.textContent = "\u751F\u6210\u4E2D...";
|
|
6545
|
+
modalBody.appendChild(loading);
|
|
6546
|
+
try {
|
|
6547
|
+
const embedBase = options.embedUrl ?? "https://onjmin.github.io/dtm/demo/embed.html";
|
|
6548
|
+
const payload = await encodeMml(mml);
|
|
6549
|
+
const url2 = `${embedBase}#${payload}`;
|
|
6550
|
+
const snippet = `<iframe src="${url2}" width="100%" height="260" frameborder="0" loading="lazy" title="@onjmin/dtm player"></iframe>`;
|
|
6551
|
+
if (!modalBody.isConnected) return;
|
|
6552
|
+
loading.remove();
|
|
6553
|
+
const desc = doc.createElement("p");
|
|
6554
|
+
desc.textContent = "\u3053\u306EHTML\u3092\u30D6\u30ED\u30B0\u3084\u30B5\u30A4\u30C8\u306B\u8CBC\u308A\u4ED8\u3051\u308B\u3068\u3001\u30D7\u30EC\u30A4\u30E4\u30FC\u3092\u305D\u306E\u307E\u307E\u57CB\u3081\u8FBC\u3081\u307E\u3059\u3002";
|
|
6555
|
+
const pre = doc.createElement("pre");
|
|
6556
|
+
pre.textContent = snippet;
|
|
6557
|
+
pre.style.whiteSpace = "pre-wrap";
|
|
6558
|
+
pre.style.wordBreak = "break-all";
|
|
6559
|
+
modalBody.append(desc, pre);
|
|
6560
|
+
appendCopyButton(modalBody, snippet);
|
|
6561
|
+
} catch (err2) {
|
|
6562
|
+
console.error("[dtm] failed to generate embed snippet", err2);
|
|
6563
|
+
if (modalBody.isConnected) loading.textContent = "\u751F\u6210\u306B\u5931\u6557\u3057\u307E\u3057\u305F";
|
|
6564
|
+
}
|
|
6565
|
+
});
|
|
6566
|
+
copyMmlItem.addEventListener("click", async (e) => {
|
|
6567
|
+
e.stopPropagation();
|
|
6568
|
+
const success = await copyToClipboard(doc, mml);
|
|
6569
|
+
if (success) {
|
|
6570
|
+
copyMmlItem.textContent = "\u30B3\u30D4\u30FC\u3057\u307E\u3057\u305F\uFF01";
|
|
6571
|
+
} else {
|
|
6572
|
+
copyMmlItem.textContent = "\u30B3\u30D4\u30FC\u5931\u6557";
|
|
6573
|
+
}
|
|
6574
|
+
setTimeout(() => {
|
|
6575
|
+
copyMmlItem.textContent = "MML\u30B3\u30D4\u30FC";
|
|
6576
|
+
}, 2e3);
|
|
6577
|
+
});
|
|
5860
6578
|
const promotedToImage = /* @__PURE__ */ new Set();
|
|
5861
6579
|
for (const [index, lt] of lyricTracks) {
|
|
5862
6580
|
const em = emojiByTrack.get(index);
|
|
@@ -6100,6 +6818,77 @@ var mountMmlPlayer = (target, mml, options = {}) => {
|
|
|
6100
6818
|
root.appendChild(termsDiv);
|
|
6101
6819
|
}
|
|
6102
6820
|
target.appendChild(root);
|
|
6821
|
+
let consentOverlayEl = null;
|
|
6822
|
+
const checkConsentAndShow = () => {
|
|
6823
|
+
try {
|
|
6824
|
+
if (options.skipConsent) return;
|
|
6825
|
+
const unagreed = termsModels.filter((model) => {
|
|
6826
|
+
if (agreedModelsInSession.has(model)) return false;
|
|
6827
|
+
try {
|
|
6828
|
+
if (typeof localStorage === "undefined" || !localStorage) return true;
|
|
6829
|
+
return localStorage.getItem(`dtm_agreed_terms_${model}`) !== "true";
|
|
6830
|
+
} catch (e) {
|
|
6831
|
+
console.warn(
|
|
6832
|
+
"[dtm-player] localStorage access denied in consent check",
|
|
6833
|
+
e
|
|
6834
|
+
);
|
|
6835
|
+
return true;
|
|
6836
|
+
}
|
|
6837
|
+
});
|
|
6838
|
+
if (unagreed.length === 0) return;
|
|
6839
|
+
const consentOverlay = doc.createElement("div");
|
|
6840
|
+
consentOverlay.className = "dtm-consent-overlay";
|
|
6841
|
+
const modal = doc.createElement("div");
|
|
6842
|
+
modal.className = "dtm-win dtm-consent-modal";
|
|
6843
|
+
const header = doc.createElement("div");
|
|
6844
|
+
header.className = "dtm-consent-header";
|
|
6845
|
+
header.textContent = "\u5229\u7528\u898F\u7D04\u306E\u78BA\u8A8D";
|
|
6846
|
+
const body2 = doc.createElement("div");
|
|
6847
|
+
body2.className = "dtm-consent-body";
|
|
6848
|
+
let contentHTML = `<p style="margin: 0 0 8px 0; line-height: 1.4; font-weight: bold; color: var(--dtm-danger);">\u672C\u30C7\u30FC\u30BF\u306B\u306F UTAU \u6B4C\u58F0\u97F3\u6E90\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059\u3002<br>\u3054\u5229\u7528\u306B\u3042\u305F\u3063\u3066\u306F\u3001\u4EE5\u4E0B\u306E\u97F3\u6E90\u5229\u7528\u898F\u7D04\u3078\u306E\u540C\u610F\u304C\u5FC5\u8981\u3067\u3059\u3002</p>`;
|
|
6849
|
+
for (const model of unagreed) {
|
|
6850
|
+
const label = KOE_VOICEBANK_LABELS[model] || model;
|
|
6851
|
+
const url2 = KOE_VOICEBANK_TERMS[model];
|
|
6852
|
+
contentHTML += `
|
|
6853
|
+
<div style="margin-bottom: 8px; padding: 6px 10px; background: var(--dtm-deep); border: 2px solid var(--c-black); box-shadow: 2px 2px 0 var(--c-black);">
|
|
6854
|
+
<div style="display: flex; align-items: center; gap: 4px; flex-wrap: wrap; font-size: 11px; font-weight: bold; color: var(--dtm-gold);">
|
|
6855
|
+
<span>\u4F7F\u7528\u6642\u306B\u306F</span>
|
|
6856
|
+
<a href="${url2}" target="_blank" rel="noopener noreferrer" style="color: var(--dtm-primary); text-decoration: underline;">${label}UTAU\u97F3\u6E90</a>
|
|
6857
|
+
<span>\u306E\u5229\u7528\u898F\u7D04\u306B\u5F93\u3063\u3066\u304F\u3060\u3055\u3044</span>
|
|
6858
|
+
</div>
|
|
6859
|
+
</div>
|
|
6860
|
+
`;
|
|
6861
|
+
}
|
|
6862
|
+
body2.innerHTML = contentHTML;
|
|
6863
|
+
const footer = doc.createElement("div");
|
|
6864
|
+
footer.className = "dtm-consent-footer";
|
|
6865
|
+
const btn = doc.createElement("button");
|
|
6866
|
+
btn.type = "button";
|
|
6867
|
+
btn.className = "dtm-btn dtm-btn--success";
|
|
6868
|
+
btn.textContent = "\u540C\u610F\u3057\u3066\u5229\u7528\u3059\u308B";
|
|
6869
|
+
btn.onclick = () => {
|
|
6870
|
+
for (const model of unagreed) {
|
|
6871
|
+
try {
|
|
6872
|
+
if (typeof localStorage !== "undefined" && localStorage) {
|
|
6873
|
+
localStorage.setItem(`dtm_agreed_terms_${model}`, "true");
|
|
6874
|
+
}
|
|
6875
|
+
} catch (e) {
|
|
6876
|
+
}
|
|
6877
|
+
agreedModelsInSession.add(model);
|
|
6878
|
+
}
|
|
6879
|
+
consentOverlay.remove();
|
|
6880
|
+
consentOverlayEl = null;
|
|
6881
|
+
};
|
|
6882
|
+
footer.appendChild(btn);
|
|
6883
|
+
modal.append(header, body2, footer);
|
|
6884
|
+
consentOverlay.appendChild(modal);
|
|
6885
|
+
doc.body.appendChild(consentOverlay);
|
|
6886
|
+
consentOverlayEl = consentOverlay;
|
|
6887
|
+
} catch (err2) {
|
|
6888
|
+
console.error("[dtm-player] Error in checkConsentAndShow:", err2);
|
|
6889
|
+
}
|
|
6890
|
+
};
|
|
6891
|
+
checkConsentAndShow();
|
|
6103
6892
|
const autoScroll = (lane, el) => {
|
|
6104
6893
|
if (el.offsetWidth === 0 || lane.clientWidth === 0) return;
|
|
6105
6894
|
const elementCenter = el.offsetLeft + el.offsetWidth / 2;
|
|
@@ -6165,7 +6954,7 @@ var mountMmlPlayer = (target, mml, options = {}) => {
|
|
|
6165
6954
|
onTick: (step) => {
|
|
6166
6955
|
renderPlayhead(step);
|
|
6167
6956
|
},
|
|
6168
|
-
onEnd: () => finish(),
|
|
6957
|
+
onEnd: (interrupted) => finish(),
|
|
6169
6958
|
stepsPerBar: STEPS_PER_BAR
|
|
6170
6959
|
});
|
|
6171
6960
|
let playing = false;
|
|
@@ -6260,6 +7049,7 @@ var mountMmlPlayer = (target, mml, options = {}) => {
|
|
|
6260
7049
|
else play();
|
|
6261
7050
|
});
|
|
6262
7051
|
const destroy = () => {
|
|
7052
|
+
doc.removeEventListener("click", handleOutsideClick);
|
|
6263
7053
|
seq.stop();
|
|
6264
7054
|
peekVoices()?.stopStream();
|
|
6265
7055
|
if (activePlayer === instance) activePlayer = null;
|
|
@@ -6273,6 +7063,8 @@ var mountMmlPlayer = (target, mml, options = {}) => {
|
|
|
6273
7063
|
hideActiveBalloon();
|
|
6274
7064
|
}
|
|
6275
7065
|
root.remove();
|
|
7066
|
+
consentOverlayEl?.remove();
|
|
7067
|
+
closeInfoModal();
|
|
6276
7068
|
};
|
|
6277
7069
|
const instance = {
|
|
6278
7070
|
play,
|
|
@@ -6314,108 +7106,6 @@ var CHORD_INFO_HTML = `
|
|
|
6314
7106
|
</ul>
|
|
6315
7107
|
</div>
|
|
6316
7108
|
`;
|
|
6317
|
-
var MML_INFO_HTML = `
|
|
6318
|
-
<div class="dtm-modal-body-content">
|
|
6319
|
-
<h4>1. \u97F3\u7B26\u3068\u4F11\u7B26</h4>
|
|
6320
|
-
<p><code>c</code>(\u30C9) <code>d</code>(\u30EC) <code>e</code>(\u30DF) <code>f</code>(\u30D5\u30A1) <code>g</code>(\u30BD) <code>a</code>(\u30E9) <code>b</code>(\u30B7) \u306E\u30A2\u30EB\u30D5\u30A1\u30D9\u30C3\u30C8\u3067\u8868\u3057\u307E\u3059\u3002</p>
|
|
6321
|
-
<ul>
|
|
6322
|
-
<li>\u534A\u97F3\u4E0A\u3052\u308B: <code>c#</code> \u307E\u305F\u306F <code>c+</code></li>
|
|
6323
|
-
<li>\u534A\u97F3\u4E0B\u3052\u308B: <code>d-</code></li>
|
|
6324
|
-
<li>\u4F11\u7B26: <code>r</code></li>
|
|
6325
|
-
</ul>
|
|
6326
|
-
|
|
6327
|
-
<h4>2. \u97F3\u306E\u9577\u3055</h4>
|
|
6328
|
-
<p>\u97F3\u540D\u3084\u4F11\u7B26\u306E\u5F8C\u306B\u6570\u5024\u3067\u6307\u5B9A\u3057\u307E\u3059\uFF08\u4F8B: <code>4</code> = 4\u5206\u97F3\u7B26, <code>8</code> = 8\u5206\u97F3\u7B26, <code>16</code> = 16\u5206\u97F3\u7B26\uFF09\u3002</p>
|
|
6329
|
-
<ul>
|
|
6330
|
-
<li><code>c4</code> : 4\u5206\u97F3\u7B26\u306E\u30C9</li>
|
|
6331
|
-
<li><code>r8</code> : 8\u5206\u4F11\u7B26</li>
|
|
6332
|
-
<li><code>c4.</code> : \u4ED8\u70B94\u5206\u97F3\u7B26\u306E\u30C9\uFF08\u9577\u3055\u30921.5\u500D\u306B\uFF09</li>
|
|
6333
|
-
<li>\u6570\u5024\u3092\u7701\u7565\u3059\u308B\u3068\u3001<code>l</code> \u30B3\u30DE\u30F3\u30C9\u3067\u8A2D\u5B9A\u3055\u308C\u305F\u30C7\u30D5\u30A9\u30EB\u30C8\u9577\uFF08\u901A\u5E3816\u5206\uFF09\u306B\u306A\u308A\u307E\u3059\u3002</li>
|
|
6334
|
-
</ul>
|
|
6335
|
-
|
|
6336
|
-
<h4>3. \u30AA\u30AF\u30BF\u30FC\u30D6\uFF08\u97F3\u306E\u9AD8\u3055\uFF09</h4>
|
|
6337
|
-
<ul>
|
|
6338
|
-
<li><code>o4</code>, <code>o5</code> : \u9AD8\u3055\u3092\u76F4\u63A5\u6307\u5B9A\uFF08\u3075\u3064\u3046\u306F o4 \u304B o5\uFF09</li>
|
|
6339
|
-
<li><code>></code> : 1\u30AA\u30AF\u30BF\u30FC\u30D6\u4E0A\u3052\u308B</li>
|
|
6340
|
-
<li><code><</code> : 1\u30AA\u30AF\u30BF\u30FC\u30D6\u4E0B\u3052\u308B</li>
|
|
6341
|
-
</ul>
|
|
6342
|
-
|
|
6343
|
-
<h4>4. \u30C6\u30F3\u30DD</h4>
|
|
6344
|
-
<ul>
|
|
6345
|
-
<li><code>t120</code> : \u66F2\u306E\u901F\u3055\u3092BPM120\u306B\u6307\u5B9A\u3002\u203B\u30E1\u30ED\u30C7\u30A3\uFF08@0\uFF09\u306E\u30C6\u30F3\u30DD\u6307\u5B9A\u304C\u66F2\u5168\u4F53\u306B\u53CD\u6620\u3055\u308C\u307E\u3059\u3002</li>
|
|
6346
|
-
</ul>
|
|
6347
|
-
|
|
6348
|
-
<h4>5. \u548C\u97F3</h4>
|
|
6349
|
-
<p>\u97F3\u7B26\u3092 <code>[</code> \u3068 <code>]</code> \u3067\u56F2\u3080\u3068\u540C\u6642\u306B\u767A\u97F3\u3057\u307E\u3059\u3002</p>
|
|
6350
|
-
<pre>\u4F8B: [ceg]4 \uFF08\u30C9\u30FB\u30DF\u30FB\u30BD\u30924\u5206\u97F3\u7B26\u3067\u540C\u6642\u306B\u767A\u97F3\uFF09</pre>
|
|
6351
|
-
|
|
6352
|
-
<h4>6. \u30C8\u30E9\u30C3\u30AF\u306E\u533A\u5207\u308A</h4>
|
|
6353
|
-
<p><code>;</code> \u307E\u305F\u306F <code>@0</code>\u301C<code>@3</code> \u3067\u30C8\u30E9\u30C3\u30AF\u3092\u5207\u308A\u66FF\u3048\u307E\u3059\u3002</p>
|
|
6354
|
-
<ul>
|
|
6355
|
-
<li><code>@0</code>: \u30E1\u30ED\u30C7\u30A3</li>
|
|
6356
|
-
<li><code>@1</code>: \u30B5\u30D6\u30E1\u30ED</li>
|
|
6357
|
-
<li><code>@2</code>: \u30D9\u30FC\u30B9</li>
|
|
6358
|
-
<li><code>@3</code>: \u4F34\u594F</li>
|
|
6359
|
-
</ul>
|
|
6360
|
-
|
|
6361
|
-
<h4>7. \u6B4C\u58F0\u30FB\u6B4C\u8A5E\u5165\u529B</h4>
|
|
6362
|
-
<p><code>@@<\u30C8\u30E9\u30C3\u30AF\u756A\u53F7> <\u97F3\u6E90\u540D> <\u6B4C\u8A5E></code> \u306E\u5F62\u5F0F\u3067\u3001\u97F3\u7B26\u3068\u540C\u671F\u3059\u308B\u6B4C\u8A5E\u3092\u5165\u529B\u3067\u304D\u307E\u3059\u3002</p>
|
|
6363
|
-
<pre>\u4F8B: @@0 tsukuyomi \u3069\u3093\u3050\u308A\u3053\u308D\u3053\u308D\u3069\u3093\u3050\u308A\u3053</pre>
|
|
6364
|
-
<p style="margin-top:4px; margin-bottom:16px;"><small>\uFF08\u97F3\u6E90\u540D\u306F <code>tsukuyomi</code> \u3084 <code>klatt</code>, <code>roze</code> \u306A\u3069\u306E\u97F3\u58F0\u30E2\u30C7\u30EB\u3092\u6307\u5B9A\u3067\u304D\u307E\u3059\uFF09</small></p>
|
|
6365
|
-
|
|
6366
|
-
<h4 style="margin-top: 18px; border-top: 1px solid var(--dtm-border2); padding-top: 8px;">\u30B5\u30F3\u30D7\u30EB\u66F2\uFF08\u8A66\u8074\u30FB\u30B3\u30D4\u30FC\uFF09</h4>
|
|
6367
|
-
|
|
6368
|
-
<!-- \u30B5\u30F3\u30D7\u30EB1 -->
|
|
6369
|
-
<div class="dtm-modal-sample-box">
|
|
6370
|
-
<div class="dtm-modal-sample-header">
|
|
6371
|
-
<span class="dtm-modal-sample-tag">1. \u57FA\u672C\u306E\u30E1\u30ED\u30C7\u30A3</span>
|
|
6372
|
-
<button class="dtm-btn dtm-btn--ghost dtm-btn--xs dtm-modal-sample-copy-btn" data-mml="@0 t120 l8 o5 c d e f g a b > c">\u{1F4CB} \u30B3\u30D4\u30FC</button>
|
|
6373
|
-
</div>
|
|
6374
|
-
<pre style="margin: 0; padding: 6px;">@0 t120 l8 o5 c d e f g a b > c</pre>
|
|
6375
|
-
<div class="dtm-modal-sample-desc">
|
|
6376
|
-
\u57FA\u672C\u7684\u306A\u30E1\u30ED\u30C7\u30A3\u306E\u66F8\u304D\u65B9\uFF08\u97F3\u540D\u30FB\u9577\u3055\u30FB\u30AA\u30AF\u30BF\u30FC\u30D6\u3068\u30C6\u30F3\u30DD\uFF09\u3002
|
|
6377
|
-
</div>
|
|
6378
|
-
<div style="margin-top: 8px;">
|
|
6379
|
-
<button class="dtm-btn dtm-btn--primary dtm-btn--xs dtm-modal-sample-play-btn" data-mml="@0 t120 l8 o5 c d e f g a b > c">\u25B6 \u8A66\u8074</button>
|
|
6380
|
-
</div>
|
|
6381
|
-
<div class="dtm-modal-sample-player-container"></div>
|
|
6382
|
-
</div>
|
|
6383
|
-
|
|
6384
|
-
<!-- \u30B5\u30F3\u30D7\u30EB2 -->
|
|
6385
|
-
<div class="dtm-modal-sample-box">
|
|
6386
|
-
<div class="dtm-modal-sample-header">
|
|
6387
|
-
<span class="dtm-modal-sample-tag">2. \u8907\u6570\u30C8\u30E9\u30C3\u30AF\u3068\u548C\u97F3</span>
|
|
6388
|
-
<button class="dtm-btn dtm-btn--ghost dtm-btn--xs dtm-modal-sample-copy-btn" data-mml="@0 t120 o5 c e g2 ; @3 o4 [ceg]2 [ceg]2">\u{1F4CB} \u30B3\u30D4\u30FC</button>
|
|
6389
|
-
</div>
|
|
6390
|
-
<pre style="margin: 0; padding: 6px;">@0 t120 o5 c e g2 ;
|
|
6391
|
-
@3 o4 [ceg]2 [ceg]2</pre>
|
|
6392
|
-
<div class="dtm-modal-sample-desc">
|
|
6393
|
-
; \u3067\u30C8\u30E9\u30C3\u30AF\uFF08\u4E0A\uFF1D\u30E1\u30ED\u30C7\u30A3\uFF0F\u4E0B\uFF1D\u4F34\u594F\uFF09\u3092\u5206\u3051\u3001[ceg] \u3067\u548C\u97F3\u3092\u9CF4\u3089\u3057\u307E\u3059\u3002
|
|
6394
|
-
</div>
|
|
6395
|
-
<div style="margin-top: 8px;">
|
|
6396
|
-
<button class="dtm-btn dtm-btn--primary dtm-btn--xs dtm-modal-sample-play-btn" data-mml="@0 t120 o5 c e g2 ; @3 o4 [ceg]2 [ceg]2">\u25B6 \u8A66\u8074</button>
|
|
6397
|
-
</div>
|
|
6398
|
-
<div class="dtm-modal-sample-player-container"></div>
|
|
6399
|
-
</div>
|
|
6400
|
-
|
|
6401
|
-
<!-- \u30B5\u30F3\u30D7\u30EB3 -->
|
|
6402
|
-
<div class="dtm-modal-sample-box">
|
|
6403
|
-
<div class="dtm-modal-sample-header">
|
|
6404
|
-
<span class="dtm-modal-sample-tag">3. \u6B4C\u5531\u4ED8\u304D (\u3069\u3093\u3050\u308A\u3053\u308D\u3053\u308D)</span>
|
|
6405
|
-
<button class="dtm-btn dtm-btn--ghost dtm-btn--xs dtm-modal-sample-copy-btn" data-mml="@0 t120 v100 o4g8 g8 e8 e8 f8 e8 d8 c8 g8 g8 e8 e8 d4.; @@0 tsukuyomi \u3069\u3093\u3050\u308A\u3053\u308D\u3053\u308D\u3069\u3093\u3050\u308A\u3053;">\u{1F4CB} \u30B3\u30D4\u30FC</button>
|
|
6406
|
-
</div>
|
|
6407
|
-
<pre style="margin: 0; padding: 6px;">@0 t120 v100 o4g8 g8 e8 e8 f8 e8 d8 c8 g8 g8 e8 e8 d4.;
|
|
6408
|
-
@@0 tsukuyomi \u3069\u3093\u3050\u308A\u3053\u308D\u3053\u308D\u3069\u3093\u3050\u308A\u3053;</pre>
|
|
6409
|
-
<div class="dtm-modal-sample-desc">
|
|
6410
|
-
@@0 tsukuyomi \u6B4C\u8A5E... \u3067\u30E1\u30ED\u30C7\u30A3\u30C8\u30E9\u30C3\u30AF\u306B\u6B4C\u8A5E\u3092\u540C\u671F\u3055\u305B\u3066\u6B4C\u308F\u305B\u307E\u3059\u3002\u203B\u72EC\u81EA\u62E1\u5F35
|
|
6411
|
-
</div>
|
|
6412
|
-
<div style="margin-top: 8px;">
|
|
6413
|
-
<button class="dtm-btn dtm-btn--primary dtm-btn--xs dtm-modal-sample-play-btn" data-mml="@0 t120 v100 o4g8 g8 e8 e8 f8 e8 d8 c8 g8 g8 e8 e8 d4.; @@0 tsukuyomi \u3069\u3093\u3050\u308A\u3053\u308D\u3053\u308D\u3069\u3093\u3050\u308A\u3053;">\u25B6 \u8A66\u8074</button>
|
|
6414
|
-
</div>
|
|
6415
|
-
<div class="dtm-modal-sample-player-container"></div>
|
|
6416
|
-
</div>
|
|
6417
|
-
</div>
|
|
6418
|
-
`;
|
|
6419
7109
|
var MIDI_INFO_HTML = `
|
|
6420
7110
|
<div class="dtm-modal-body-content">
|
|
6421
7111
|
<h4>1. MIDI\u30D5\u30A1\u30A4\u30EB\u3068\u306F</h4>
|
|
@@ -7178,6 +7868,10 @@ var mountDAW = (target, options = {}) => {
|
|
|
7178
7868
|
0,
|
|
7179
7869
|
Math.floor(step / snapGridSteps) * snapGridSteps
|
|
7180
7870
|
);
|
|
7871
|
+
if (playbackState === "paused") {
|
|
7872
|
+
playbackState = "stopped";
|
|
7873
|
+
updateTransport();
|
|
7874
|
+
}
|
|
7181
7875
|
redrawAll();
|
|
7182
7876
|
});
|
|
7183
7877
|
setDrawOffset(currentOffsetX, currentOffsetY);
|
|
@@ -7253,9 +7947,14 @@ var mountDAW = (target, options = {}) => {
|
|
|
7253
7947
|
}
|
|
7254
7948
|
redrawAll();
|
|
7255
7949
|
},
|
|
7256
|
-
onEnd: () => {
|
|
7257
|
-
|
|
7258
|
-
|
|
7950
|
+
onEnd: (interrupted) => {
|
|
7951
|
+
if (interrupted) {
|
|
7952
|
+
playbackState = "paused";
|
|
7953
|
+
pausedPlayStep = currentPlayStep;
|
|
7954
|
+
} else {
|
|
7955
|
+
playbackState = "stopped";
|
|
7956
|
+
currentPlayStep = 0;
|
|
7957
|
+
}
|
|
7259
7958
|
updateTransport();
|
|
7260
7959
|
redrawAll();
|
|
7261
7960
|
},
|
|
@@ -7345,13 +8044,13 @@ var mountDAW = (target, options = {}) => {
|
|
|
7345
8044
|
redrawAll();
|
|
7346
8045
|
};
|
|
7347
8046
|
const togglePlay = () => {
|
|
7348
|
-
if (playbackState === "playing")
|
|
8047
|
+
if (playbackState === "playing") pause();
|
|
7349
8048
|
else play();
|
|
7350
8049
|
};
|
|
7351
8050
|
const updateTransport = () => {
|
|
7352
8051
|
const playing = playbackState === "playing";
|
|
7353
|
-
const label = playing ? "\u505C\u6B62" : playbackState === "paused" ? "\u518D\u958B" : "\u8A66\u8074";
|
|
7354
|
-
refs.playBtn.innerHTML = `${icon(playing ? "
|
|
8052
|
+
const label = playing ? "\u4E00\u6642\u505C\u6B62" : playbackState === "paused" ? "\u518D\u958B" : "\u8A66\u8074";
|
|
8053
|
+
refs.playBtn.innerHTML = `${icon(playing ? "pause" : "play")}<span>${label}</span>`;
|
|
7355
8054
|
refs.playBtn.classList.toggle("dtm-play--stop", playing);
|
|
7356
8055
|
};
|
|
7357
8056
|
const updateUndoRedo = () => {
|
|
@@ -7740,20 +8439,25 @@ var mountDAW = (target, options = {}) => {
|
|
|
7740
8439
|
};
|
|
7741
8440
|
const loadMML = (mml) => {
|
|
7742
8441
|
if (!mml) return;
|
|
8442
|
+
stop();
|
|
7743
8443
|
clearAll();
|
|
7744
8444
|
for (const t of trackStates) t.core.setLoadMode(true);
|
|
7745
8445
|
const {
|
|
7746
8446
|
placements,
|
|
7747
8447
|
bpm: parsedBpm,
|
|
7748
8448
|
lyrics,
|
|
7749
|
-
meta
|
|
8449
|
+
meta,
|
|
8450
|
+
mergedTrackCount
|
|
7750
8451
|
} = parseMML(mml, {
|
|
7751
8452
|
stepsPerBar: renderConfig.stepsPerBar,
|
|
7752
8453
|
collectLyrics: true,
|
|
7753
8454
|
// このDAWのトラック数を超えるチャンネルはベースへ畳み込む(従来挙動)
|
|
7754
8455
|
clampTrackCount: trackStates.length
|
|
7755
8456
|
});
|
|
7756
|
-
|
|
8457
|
+
if (meta.instrument && INSTRUMENT_PRESETS[meta.instrument]) {
|
|
8458
|
+
currentInstrument = meta.instrument;
|
|
8459
|
+
options.onInstrumentChange?.(meta.instrument);
|
|
8460
|
+
}
|
|
7757
8461
|
if (meta.drum && drumPatterns[meta.drum]) {
|
|
7758
8462
|
currentDrumPattern = meta.drum;
|
|
7759
8463
|
refs.drumSelect.value = meta.drum;
|
|
@@ -7772,8 +8476,8 @@ var mountDAW = (target, options = {}) => {
|
|
|
7772
8476
|
t.vocalPan = 64;
|
|
7773
8477
|
t.vocalOctave = 0;
|
|
7774
8478
|
}
|
|
7775
|
-
lyrics?.forEach((lt
|
|
7776
|
-
const t = trackStates[
|
|
8479
|
+
lyrics?.forEach((lt) => {
|
|
8480
|
+
const t = trackStates[lt.trackId];
|
|
7777
8481
|
if (!t) return;
|
|
7778
8482
|
t.lyrics = lt.syllables.map((s) => s.kana).join("");
|
|
7779
8483
|
t.lyricModel = lt.model;
|
|
@@ -7805,6 +8509,13 @@ var mountDAW = (target, options = {}) => {
|
|
|
7805
8509
|
redrawAll();
|
|
7806
8510
|
updateTrackPanel();
|
|
7807
8511
|
updateUndoRedo();
|
|
8512
|
+
if (!isAdvanced && mergedTrackCount > 0) {
|
|
8513
|
+
refs.mmlLoadNote.textContent = "\u30B7\u30F3\u30D7\u30EB\u30E2\u30FC\u30C9\u306E\u305F\u3081\u3001\u4E00\u90E8\u306E\u30C8\u30E9\u30C3\u30AF\u3092\u5408\u7B97\u3057\u3066\u8AAD\u307F\u8FBC\u307F\u307E\u3057\u305F";
|
|
8514
|
+
refs.mmlLoadNote.classList.remove("dtm-hidden");
|
|
8515
|
+
} else {
|
|
8516
|
+
refs.mmlLoadNote.textContent = "";
|
|
8517
|
+
refs.mmlLoadNote.classList.add("dtm-hidden");
|
|
8518
|
+
}
|
|
7808
8519
|
};
|
|
7809
8520
|
const applyChord = () => {
|
|
7810
8521
|
const active = getActive();
|
|
@@ -7837,6 +8548,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
7837
8548
|
applyMidiSelection(midi, selected);
|
|
7838
8549
|
};
|
|
7839
8550
|
const applyMidiSelection = (midi, selectedIndices) => {
|
|
8551
|
+
stop();
|
|
7840
8552
|
clearAll();
|
|
7841
8553
|
for (const t of trackStates) t.core.setLoadMode(true);
|
|
7842
8554
|
const { placements, bpm: parsedBpm } = isAdvanced ? extractMidiPlacementsByTrack(
|
|
@@ -8268,6 +8980,25 @@ var mountDAW = (target, options = {}) => {
|
|
|
8268
8980
|
const setLoading = (loading) => {
|
|
8269
8981
|
refs.topbar.classList.toggle("is-loading", loading);
|
|
8270
8982
|
};
|
|
8983
|
+
const getCurrentPlayStep = () => {
|
|
8984
|
+
if (playbackState === "playing") return currentPlayStep;
|
|
8985
|
+
if (playbackState === "paused") return pausedPlayStep;
|
|
8986
|
+
return playStartStep;
|
|
8987
|
+
};
|
|
8988
|
+
const forcePauseAt = (step) => {
|
|
8989
|
+
playStartStep = step;
|
|
8990
|
+
pausedPlayStep = step;
|
|
8991
|
+
currentPlayStep = step;
|
|
8992
|
+
playbackState = "paused";
|
|
8993
|
+
const canvas = getGridCanvas();
|
|
8994
|
+
currentOffsetX = Math.max(
|
|
8995
|
+
0,
|
|
8996
|
+
step * renderConfig.stepWidth - canvas.width * 0.5
|
|
8997
|
+
);
|
|
8998
|
+
setDrawOffset(currentOffsetX, currentOffsetY);
|
|
8999
|
+
updateTransport();
|
|
9000
|
+
redrawAll();
|
|
9001
|
+
};
|
|
8271
9002
|
return {
|
|
8272
9003
|
play,
|
|
8273
9004
|
pause,
|
|
@@ -8305,9 +9036,12 @@ var mountDAW = (target, options = {}) => {
|
|
|
8305
9036
|
exportMIDI: exportMIDI2,
|
|
8306
9037
|
setBpm,
|
|
8307
9038
|
getPlaybackState: () => playbackState,
|
|
9039
|
+
getCurrentPlayStep,
|
|
9040
|
+
forcePauseAt,
|
|
8308
9041
|
setLoading,
|
|
8309
9042
|
destroy: () => {
|
|
8310
9043
|
sequencer.stop();
|
|
9044
|
+
options.singingVoices?.stopStream();
|
|
8311
9045
|
resizeObserver.disconnect();
|
|
8312
9046
|
document.removeEventListener("pointermove", onPointerMove);
|
|
8313
9047
|
document.removeEventListener("pointerup", onPointerUp);
|
|
@@ -8317,110 +9051,6 @@ var mountDAW = (target, options = {}) => {
|
|
|
8317
9051
|
};
|
|
8318
9052
|
};
|
|
8319
9053
|
|
|
8320
|
-
// src/instrument-presets.ts
|
|
8321
|
-
var INSTRUMENT_PRESETS = {
|
|
8322
|
-
// --- STANDARD: 汎用性と完成度重視 ---
|
|
8323
|
-
piano: {
|
|
8324
|
-
displayName: "\u30B0\u30E9\u30F3\u30C9\u30D4\u30A2\u30CE",
|
|
8325
|
-
description: "\u6700\u3082\u7834\u7DBB\u3057\u306B\u304F\u3044\u69CB\u6210\u3002\u697D\u66F2\u5236\u4F5C\u306E\u30B9\u30B1\u30C3\u30C1\u306B\u3082\u6700\u9069\u3002",
|
|
8326
|
-
melody: "Acoustic Grand Piano",
|
|
8327
|
-
submelody: "Vibraphone",
|
|
8328
|
-
bass: "Electric Bass (finger)",
|
|
8329
|
-
chord: "Pad 2 (warm)"
|
|
8330
|
-
},
|
|
8331
|
-
acoustic: {
|
|
8332
|
-
displayName: "\u30A2\u30B3\u30FC\u30B9\u30C6\u30A3\u30C3\u30AF",
|
|
8333
|
-
description: "\u751F\u697D\u5668\u306E\u6E29\u304B\u307F\u3092\u91CD\u8996\u3002\u30D5\u30A9\u30FC\u30AF\u3084\u30DD\u30C3\u30D7\u30B9\u306B\u3002",
|
|
8334
|
-
melody: "Acoustic Guitar (steel)",
|
|
8335
|
-
submelody: "Harmonica",
|
|
8336
|
-
bass: "Acoustic Bass",
|
|
8337
|
-
chord: "Acoustic Guitar (nylon)"
|
|
8338
|
-
},
|
|
8339
|
-
jazz_night: {
|
|
8340
|
-
displayName: "\u30B8\u30E3\u30BA\u30FB\u30CA\u30A4\u30C8",
|
|
8341
|
-
description: "Rhodes\u98A8\u306EEP\u3068\u30A6\u30C3\u30C9\u30D9\u30FC\u30B9\u306B\u3088\u308B\u3001\u5927\u4EBA\u3073\u305F\u30A2\u30F3\u30B5\u30F3\u30D6\u30EB\u3002",
|
|
8342
|
-
melody: "Electric Piano 1",
|
|
8343
|
-
submelody: "Flute",
|
|
8344
|
-
bass: "Acoustic Bass",
|
|
8345
|
-
chord: "Electric Guitar (jazz)"
|
|
8346
|
-
},
|
|
8347
|
-
// --- MODERN & VIBE: エッジの効いた現代的な響き ---
|
|
8348
|
-
synth_pop: {
|
|
8349
|
-
displayName: "\u30B7\u30F3\u30BB\u30DD\u30C3\u30D7",
|
|
8350
|
-
description: "80s\u301C\u73FE\u4EE3\u307E\u3067\u3002\u629C\u3051\u308B\u30EA\u30FC\u30C9\u3068\u592A\u3044\u30D9\u30FC\u30B9\u306E\u738B\u9053\u3002",
|
|
8351
|
-
melody: "Lead 2 (sawtooth)",
|
|
8352
|
-
submelody: "Lead 4 (chiff)",
|
|
8353
|
-
bass: "Synth Bass 2",
|
|
8354
|
-
chord: "Pad 3 (polysynth)"
|
|
8355
|
-
},
|
|
8356
|
-
cyber_punk: {
|
|
8357
|
-
displayName: "\u30B5\u30A4\u30D0\u30FC\u30D1\u30F3\u30AF",
|
|
8358
|
-
description: "\u30C7\u30B8\u30BF\u30EB\u306A\u51B7\u305F\u3055\u3068\u6B6A\u307F\u304C\u6DF7\u3056\u308A\u5408\u3046\u3001\u672A\u6765\u7684\u306A\u97FF\u304D\u3002",
|
|
8359
|
-
melody: "Lead 8 (bass + lead)",
|
|
8360
|
-
submelody: "Lead 5 (charang)",
|
|
8361
|
-
bass: "Synth Bass 2",
|
|
8362
|
-
chord: "Pad 8 (sweep)"
|
|
8363
|
-
},
|
|
8364
|
-
rock: {
|
|
8365
|
-
displayName: "\u30CF\u30FC\u30C9\u30ED\u30C3\u30AF",
|
|
8366
|
-
description: "\u6B6A\u307F\u30AE\u30BF\u30FC\u3068\u91CD\u539A\u306A\u30D9\u30FC\u30B9\u3067\u3001\u30D1\u30EF\u30FC\u3092\u524D\u9762\u306B\u3002",
|
|
8367
|
-
melody: "Distortion Guitar",
|
|
8368
|
-
submelody: "Rock Organ",
|
|
8369
|
-
bass: "Electric Bass (pick)",
|
|
8370
|
-
chord: "Overdriven Guitar"
|
|
8371
|
-
},
|
|
8372
|
-
// --- WORLD & CLASSIC: 特定のジャンル・地域 ---
|
|
8373
|
-
orchestra: {
|
|
8374
|
-
displayName: "\u30AA\u30FC\u30B1\u30B9\u30C8\u30E9",
|
|
8375
|
-
description: "\u58EE\u5927\u306A\u7269\u8A9E\u3092\u4E88\u611F\u3055\u305B\u308B\u3001\u7BA1\u5F26\u697D\u5668\u306E\u91CD\u539A\u306A\u97FF\u304D\u3002",
|
|
8376
|
-
melody: "French Horn",
|
|
8377
|
-
submelody: "Pizzicato Strings",
|
|
8378
|
-
bass: "Cello",
|
|
8379
|
-
chord: "Tremolo Strings"
|
|
8380
|
-
},
|
|
8381
|
-
japanese_wa: {
|
|
8382
|
-
displayName: "\u548C\u98A8\u30FB\u96C5",
|
|
8383
|
-
description: "\u7434\u3068\u4E09\u5473\u7DDA\u306E\u7E4A\u7D30\u306A\u8ABF\u3079\u306B\u3001\u5C3A\u516B\u306E\u60C5\u7DD2\u3092\u6DFB\u3048\u3066\u3002",
|
|
8384
|
-
melody: "Koto",
|
|
8385
|
-
submelody: "Shamisen",
|
|
8386
|
-
bass: "Taiko Drum",
|
|
8387
|
-
chord: "Shakuhachi"
|
|
8388
|
-
},
|
|
8389
|
-
arabic_exotic: {
|
|
8390
|
-
displayName: "\u30A8\u30AD\u30BE\u30C1\u30C3\u30AF",
|
|
8391
|
-
description: "\u30B7\u30BF\u30FC\u30EB\u3084\u30D0\u30B0\u30D1\u30A4\u30D7\u306B\u3088\u308B\u3001\u7570\u56FD\u60C5\u7DD2\u6EA2\u308C\u308B\u30B5\u30A6\u30F3\u30C9\u3002",
|
|
8392
|
-
melody: "Sitar",
|
|
8393
|
-
submelody: "Bagpipe",
|
|
8394
|
-
bass: "Fretless Bass",
|
|
8395
|
-
chord: "Kalimba"
|
|
8396
|
-
},
|
|
8397
|
-
// --- FANTASY & ATMOSPHERE: 雰囲気と余韻 ---
|
|
8398
|
-
fantasy_rpg: {
|
|
8399
|
-
displayName: "\u30D5\u30A1\u30F3\u30BF\u30B8\u30FCRPG",
|
|
8400
|
-
description: "\u30AA\u30AB\u30EA\u30CA\u3068\u30CF\u30FC\u30D7\u304C\u7D21\u3050\u3001\u5192\u967A\u3068\u9B54\u6CD5\u306E\u4E16\u754C\u89B3\u3002",
|
|
8401
|
-
melody: "Ocarina",
|
|
8402
|
-
submelody: "Celesta",
|
|
8403
|
-
bass: "Timpani",
|
|
8404
|
-
chord: "Orchestral Harp"
|
|
8405
|
-
},
|
|
8406
|
-
ambient_cloud: {
|
|
8407
|
-
displayName: "\u30A2\u30F3\u30D3\u30A8\u30F3\u30C8",
|
|
8408
|
-
description: "\u8F2A\u90ED\u3092\u307C\u304B\u3057\u305F\u97F3\u8272\u3067\u3001\u6DF1\u3044\u6CA1\u5165\u611F\u3068\u4F59\u97FB\u3092\u6F14\u51FA\u3002",
|
|
8409
|
-
melody: "Lead 6 (voice)",
|
|
8410
|
-
submelody: "Music Box",
|
|
8411
|
-
bass: "Synth Bass 1",
|
|
8412
|
-
chord: "Pad 7 (halo)"
|
|
8413
|
-
},
|
|
8414
|
-
retro_game: {
|
|
8415
|
-
displayName: "8-bit \u30EC\u30C8\u30ED",
|
|
8416
|
-
description: "\u77E9\u5F62\u6CE2\u3092\u60F3\u8D77\u3055\u305B\u308B\u3001\u521D\u671F\u30B2\u30FC\u30E0\u6A5F\u306E\u3088\u3046\u306A\u61D0\u304B\u3057\u3044\u97FF\u304D\u3002",
|
|
8417
|
-
melody: "Lead 1 (square)",
|
|
8418
|
-
submelody: "Lead 2 (sawtooth)",
|
|
8419
|
-
bass: "Synth Bass 1",
|
|
8420
|
-
chord: "Clavinet"
|
|
8421
|
-
}
|
|
8422
|
-
};
|
|
8423
|
-
|
|
8424
9054
|
// src/headless-player.ts
|
|
8425
9055
|
var STEPS_PER_BAR2 = 192;
|
|
8426
9056
|
var playMML = (mml, options = {}) => {
|
|
@@ -8471,7 +9101,7 @@ var playMML = (mml, options = {}) => {
|
|
|
8471
9101
|
},
|
|
8472
9102
|
onTick: () => {
|
|
8473
9103
|
},
|
|
8474
|
-
onEnd: () => finish(),
|
|
9104
|
+
onEnd: (interrupted) => finish(),
|
|
8475
9105
|
stepsPerBar: STEPS_PER_BAR2
|
|
8476
9106
|
});
|
|
8477
9107
|
const finish = () => {
|
|
@@ -9292,11 +9922,13 @@ var createDtmStudio = async (options = {}) => {
|
|
|
9292
9922
|
const mountedPlayers = [];
|
|
9293
9923
|
const mountedModeSwitches = [];
|
|
9294
9924
|
const mountEditor = (target, opts = {}) => {
|
|
9295
|
-
const { preset, presetUI, ...dawOverrides } = opts;
|
|
9925
|
+
const { preset, presetUI, onInstrumentChange, ...dawOverrides } = opts;
|
|
9296
9926
|
const tracks = dawOverrides.tracks ?? TRACKS_SIMPLE;
|
|
9297
9927
|
const trackIds = tracks.map((t) => t.id);
|
|
9298
9928
|
const presetKey = preset && INSTRUMENT_PRESETS[preset] ? preset : defaultPreset;
|
|
9299
|
-
|
|
9929
|
+
const meta = opts.initialMML ? parseMmlMeta(opts.initialMML) : {};
|
|
9930
|
+
const initialPreset = meta.instrument && INSTRUMENT_PRESETS[meta.instrument] ? meta.instrument : presetKey;
|
|
9931
|
+
let editorPreset = initialPreset;
|
|
9300
9932
|
const isAdvancedMode = dawOverrides.mode === "advanced";
|
|
9301
9933
|
const playNote = (e) => {
|
|
9302
9934
|
const sf = resolveSoundFont(
|
|
@@ -9314,6 +9946,14 @@ var createDtmStudio = async (options = {}) => {
|
|
|
9314
9946
|
duration: e.duration
|
|
9315
9947
|
});
|
|
9316
9948
|
};
|
|
9949
|
+
let presetSelect = null;
|
|
9950
|
+
const handleInstrumentChange = (key) => {
|
|
9951
|
+
editorPreset = key;
|
|
9952
|
+
if (presetSelect) {
|
|
9953
|
+
presetSelect.setValue(key);
|
|
9954
|
+
}
|
|
9955
|
+
onInstrumentChange?.(key);
|
|
9956
|
+
};
|
|
9317
9957
|
const base = {
|
|
9318
9958
|
getAudioTime: () => audioCtx.currentTime,
|
|
9319
9959
|
onResumeAudio: resumeAudio,
|
|
@@ -9322,19 +9962,19 @@ var createDtmStudio = async (options = {}) => {
|
|
|
9322
9962
|
singingVoices,
|
|
9323
9963
|
parseMidi,
|
|
9324
9964
|
onToggleRecord,
|
|
9965
|
+
onInstrumentChange: handleInstrumentChange,
|
|
9325
9966
|
...dawOverrides
|
|
9326
9967
|
};
|
|
9327
9968
|
const daw = mountDAW(target, base);
|
|
9328
9969
|
mountedEditors.push(daw);
|
|
9329
9970
|
const wantPresetUI = presetUI ?? features.presetUI;
|
|
9330
|
-
let presetSelect = null;
|
|
9331
9971
|
if (wantPresetUI) {
|
|
9332
9972
|
editorPresetSelects.get(target)?.destroy();
|
|
9333
9973
|
const rollEl = target.querySelector('[data-dtm="roll"]');
|
|
9334
9974
|
presetSelect = mountPresetSelect(target, {
|
|
9335
9975
|
getDaw: () => daw,
|
|
9336
9976
|
getTrackIds: () => trackIds,
|
|
9337
|
-
value:
|
|
9977
|
+
value: initialPreset,
|
|
9338
9978
|
loadingTarget: rollEl ?? target,
|
|
9339
9979
|
position: "prepend",
|
|
9340
9980
|
// 楽器変更時、このエディタの発音解決が使うプリセットも追従させる。
|
|
@@ -9344,10 +9984,10 @@ var createDtmStudio = async (options = {}) => {
|
|
|
9344
9984
|
});
|
|
9345
9985
|
editorPresetSelects.set(target, presetSelect);
|
|
9346
9986
|
}
|
|
9347
|
-
daw.setInstrument(
|
|
9987
|
+
daw.setInstrument(initialPreset);
|
|
9348
9988
|
daw.setLoading?.(true);
|
|
9349
9989
|
void loadPreset(
|
|
9350
|
-
|
|
9990
|
+
initialPreset,
|
|
9351
9991
|
trackIds,
|
|
9352
9992
|
isAdvancedMode ? "advanced" : "simple"
|
|
9353
9993
|
).finally(() => {
|
|
@@ -9361,7 +10001,17 @@ var createDtmStudio = async (options = {}) => {
|
|
|
9361
10001
|
const i = mountedEditors.indexOf(daw);
|
|
9362
10002
|
if (i >= 0) mountedEditors.splice(i, 1);
|
|
9363
10003
|
};
|
|
9364
|
-
return {
|
|
10004
|
+
return {
|
|
10005
|
+
...daw,
|
|
10006
|
+
setInstrument: (name) => {
|
|
10007
|
+
daw.setInstrument(name);
|
|
10008
|
+
editorPreset = name;
|
|
10009
|
+
if (presetSelect) {
|
|
10010
|
+
presetSelect.setValue(name);
|
|
10011
|
+
}
|
|
10012
|
+
},
|
|
10013
|
+
destroy
|
|
10014
|
+
};
|
|
9365
10015
|
};
|
|
9366
10016
|
const mountModeSwitch = (target, opts) => {
|
|
9367
10017
|
const doc = target.ownerDocument;
|