@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.mjs
CHANGED
|
@@ -1107,6 +1107,9 @@ var ICONS = {
|
|
|
1107
1107
|
},
|
|
1108
1108
|
info: {
|
|
1109
1109
|
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"
|
|
1110
|
+
},
|
|
1111
|
+
more: {
|
|
1112
|
+
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"
|
|
1110
1113
|
}
|
|
1111
1114
|
};
|
|
1112
1115
|
var icon = (name, size = 20) => {
|
|
@@ -1233,6 +1236,7 @@ var buildUI = (target, options) => {
|
|
|
1233
1236
|
<textarea class="dtm-textarea dtm-grow" data-dtm="mml-input" placeholder="MML\u3092\u5165\u529B"></textarea>
|
|
1234
1237
|
<button class="dtm-btn dtm-btn--primary" data-dtm="mml-load">\u8AAD\u8FBC</button>
|
|
1235
1238
|
</div>
|
|
1239
|
+
<p class="dtm-load-note dtm-hidden" data-dtm="mml-load-note"></p>
|
|
1236
1240
|
</div>
|
|
1237
1241
|
</details>
|
|
1238
1242
|
|
|
@@ -1315,6 +1319,7 @@ var buildUI = (target, options) => {
|
|
|
1315
1319
|
<div class="dtm-modal-body" data-dtm="modal-body"></div>
|
|
1316
1320
|
</div>
|
|
1317
1321
|
</div>
|
|
1322
|
+
|
|
1318
1323
|
</div>`;
|
|
1319
1324
|
const root = q(target, '[data-dtm="root"]');
|
|
1320
1325
|
const sel = (name) => q(root, `[data-dtm="${name}"]`);
|
|
@@ -1358,6 +1363,7 @@ var buildUI = (target, options) => {
|
|
|
1358
1363
|
midiPanel: sel("midi-panel"),
|
|
1359
1364
|
mmlInput: sel("mml-input"),
|
|
1360
1365
|
mmlLoadBtn: sel("mml-load"),
|
|
1366
|
+
mmlLoadNote: sel("mml-load-note"),
|
|
1361
1367
|
shiftSelect: sel("shift-select"),
|
|
1362
1368
|
shiftApplyBtn: sel("shift-apply"),
|
|
1363
1369
|
macroClear: sel("macro-clear"),
|
|
@@ -1511,6 +1517,110 @@ var DRUM_PATTERNS = {
|
|
|
1511
1517
|
]
|
|
1512
1518
|
};
|
|
1513
1519
|
|
|
1520
|
+
// src/instrument-presets.ts
|
|
1521
|
+
var INSTRUMENT_PRESETS = {
|
|
1522
|
+
// --- STANDARD: 汎用性と完成度重視 ---
|
|
1523
|
+
piano: {
|
|
1524
|
+
displayName: "\u30B0\u30E9\u30F3\u30C9\u30D4\u30A2\u30CE",
|
|
1525
|
+
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",
|
|
1526
|
+
melody: "Acoustic Grand Piano",
|
|
1527
|
+
submelody: "Vibraphone",
|
|
1528
|
+
bass: "Electric Bass (finger)",
|
|
1529
|
+
chord: "Pad 2 (warm)"
|
|
1530
|
+
},
|
|
1531
|
+
acoustic: {
|
|
1532
|
+
displayName: "\u30A2\u30B3\u30FC\u30B9\u30C6\u30A3\u30C3\u30AF",
|
|
1533
|
+
description: "\u751F\u697D\u5668\u306E\u6E29\u304B\u307F\u3092\u91CD\u8996\u3002\u30D5\u30A9\u30FC\u30AF\u3084\u30DD\u30C3\u30D7\u30B9\u306B\u3002",
|
|
1534
|
+
melody: "Acoustic Guitar (steel)",
|
|
1535
|
+
submelody: "Harmonica",
|
|
1536
|
+
bass: "Acoustic Bass",
|
|
1537
|
+
chord: "Acoustic Guitar (nylon)"
|
|
1538
|
+
},
|
|
1539
|
+
jazz_night: {
|
|
1540
|
+
displayName: "\u30B8\u30E3\u30BA\u30FB\u30CA\u30A4\u30C8",
|
|
1541
|
+
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",
|
|
1542
|
+
melody: "Electric Piano 1",
|
|
1543
|
+
submelody: "Flute",
|
|
1544
|
+
bass: "Acoustic Bass",
|
|
1545
|
+
chord: "Electric Guitar (jazz)"
|
|
1546
|
+
},
|
|
1547
|
+
// --- MODERN & VIBE: エッジの効いた現代的な響き ---
|
|
1548
|
+
synth_pop: {
|
|
1549
|
+
displayName: "\u30B7\u30F3\u30BB\u30DD\u30C3\u30D7",
|
|
1550
|
+
description: "80s\u301C\u73FE\u4EE3\u307E\u3067\u3002\u629C\u3051\u308B\u30EA\u30FC\u30C9\u3068\u592A\u3044\u30D9\u30FC\u30B9\u306E\u738B\u9053\u3002",
|
|
1551
|
+
melody: "Lead 2 (sawtooth)",
|
|
1552
|
+
submelody: "Lead 4 (chiff)",
|
|
1553
|
+
bass: "Synth Bass 2",
|
|
1554
|
+
chord: "Pad 3 (polysynth)"
|
|
1555
|
+
},
|
|
1556
|
+
cyber_punk: {
|
|
1557
|
+
displayName: "\u30B5\u30A4\u30D0\u30FC\u30D1\u30F3\u30AF",
|
|
1558
|
+
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",
|
|
1559
|
+
melody: "Lead 8 (bass + lead)",
|
|
1560
|
+
submelody: "Lead 5 (charang)",
|
|
1561
|
+
bass: "Synth Bass 2",
|
|
1562
|
+
chord: "Pad 8 (sweep)"
|
|
1563
|
+
},
|
|
1564
|
+
rock: {
|
|
1565
|
+
displayName: "\u30CF\u30FC\u30C9\u30ED\u30C3\u30AF",
|
|
1566
|
+
description: "\u6B6A\u307F\u30AE\u30BF\u30FC\u3068\u91CD\u539A\u306A\u30D9\u30FC\u30B9\u3067\u3001\u30D1\u30EF\u30FC\u3092\u524D\u9762\u306B\u3002",
|
|
1567
|
+
melody: "Distortion Guitar",
|
|
1568
|
+
submelody: "Rock Organ",
|
|
1569
|
+
bass: "Electric Bass (pick)",
|
|
1570
|
+
chord: "Overdriven Guitar"
|
|
1571
|
+
},
|
|
1572
|
+
// --- WORLD & CLASSIC: 特定のジャンル・地域 ---
|
|
1573
|
+
orchestra: {
|
|
1574
|
+
displayName: "\u30AA\u30FC\u30B1\u30B9\u30C8\u30E9",
|
|
1575
|
+
description: "\u58EE\u5927\u306A\u7269\u8A9E\u3092\u4E88\u611F\u3055\u305B\u308B\u3001\u7BA1\u5F26\u697D\u5668\u306E\u91CD\u539A\u306A\u97FF\u304D\u3002",
|
|
1576
|
+
melody: "French Horn",
|
|
1577
|
+
submelody: "Pizzicato Strings",
|
|
1578
|
+
bass: "Cello",
|
|
1579
|
+
chord: "Tremolo Strings"
|
|
1580
|
+
},
|
|
1581
|
+
japanese_wa: {
|
|
1582
|
+
displayName: "\u548C\u98A8\u30FB\u96C5",
|
|
1583
|
+
description: "\u7434\u3068\u4E09\u5473\u7DDA\u306E\u7E4A\u7D30\u306A\u8ABF\u3079\u306B\u3001\u5C3A\u516B\u306E\u60C5\u7DD2\u3092\u6DFB\u3048\u3066\u3002",
|
|
1584
|
+
melody: "Koto",
|
|
1585
|
+
submelody: "Shamisen",
|
|
1586
|
+
bass: "Taiko Drum",
|
|
1587
|
+
chord: "Shakuhachi"
|
|
1588
|
+
},
|
|
1589
|
+
arabic_exotic: {
|
|
1590
|
+
displayName: "\u30A8\u30AD\u30BE\u30C1\u30C3\u30AF",
|
|
1591
|
+
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",
|
|
1592
|
+
melody: "Sitar",
|
|
1593
|
+
submelody: "Bagpipe",
|
|
1594
|
+
bass: "Fretless Bass",
|
|
1595
|
+
chord: "Kalimba"
|
|
1596
|
+
},
|
|
1597
|
+
// --- FANTASY & ATMOSPHERE: 雰囲気と余韻 ---
|
|
1598
|
+
fantasy_rpg: {
|
|
1599
|
+
displayName: "\u30D5\u30A1\u30F3\u30BF\u30B8\u30FCRPG",
|
|
1600
|
+
description: "\u30AA\u30AB\u30EA\u30CA\u3068\u30CF\u30FC\u30D7\u304C\u7D21\u3050\u3001\u5192\u967A\u3068\u9B54\u6CD5\u306E\u4E16\u754C\u89B3\u3002",
|
|
1601
|
+
melody: "Ocarina",
|
|
1602
|
+
submelody: "Celesta",
|
|
1603
|
+
bass: "Timpani",
|
|
1604
|
+
chord: "Orchestral Harp"
|
|
1605
|
+
},
|
|
1606
|
+
ambient_cloud: {
|
|
1607
|
+
displayName: "\u30A2\u30F3\u30D3\u30A8\u30F3\u30C8",
|
|
1608
|
+
description: "\u8F2A\u90ED\u3092\u307C\u304B\u3057\u305F\u97F3\u8272\u3067\u3001\u6DF1\u3044\u6CA1\u5165\u611F\u3068\u4F59\u97FB\u3092\u6F14\u51FA\u3002",
|
|
1609
|
+
melody: "Lead 6 (voice)",
|
|
1610
|
+
submelody: "Music Box",
|
|
1611
|
+
bass: "Synth Bass 1",
|
|
1612
|
+
chord: "Pad 7 (halo)"
|
|
1613
|
+
},
|
|
1614
|
+
retro_game: {
|
|
1615
|
+
displayName: "8-bit \u30EC\u30C8\u30ED",
|
|
1616
|
+
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",
|
|
1617
|
+
melody: "Lead 1 (square)",
|
|
1618
|
+
submelody: "Lead 2 (sawtooth)",
|
|
1619
|
+
bass: "Synth Bass 1",
|
|
1620
|
+
chord: "Clavinet"
|
|
1621
|
+
}
|
|
1622
|
+
};
|
|
1623
|
+
|
|
1514
1624
|
// node_modules/.pnpm/@onjmin+koe@1.0.3/node_modules/@onjmin/koe/dist/index.js
|
|
1515
1625
|
var MAGIC = 1263486208;
|
|
1516
1626
|
function parseKoeHeader(headerBytes) {
|
|
@@ -2393,7 +2503,20 @@ var createWorkerBackend = async (workerUrl, options) => {
|
|
|
2393
2503
|
};
|
|
2394
2504
|
};
|
|
2395
2505
|
var createKoeVoice = async (ctx, destination, options) => {
|
|
2396
|
-
|
|
2506
|
+
let backend;
|
|
2507
|
+
if (options.voiceWorkerUrl) {
|
|
2508
|
+
try {
|
|
2509
|
+
backend = await createWorkerBackend(options.voiceWorkerUrl, options);
|
|
2510
|
+
} catch (err2) {
|
|
2511
|
+
console.warn(
|
|
2512
|
+
"[dtm] Failed to spawn voice worker. Falling back to local backend.",
|
|
2513
|
+
err2
|
|
2514
|
+
);
|
|
2515
|
+
backend = await createLocalBackend(options);
|
|
2516
|
+
}
|
|
2517
|
+
} else {
|
|
2518
|
+
backend = await createLocalBackend(options);
|
|
2519
|
+
}
|
|
2397
2520
|
const renderCache = /* @__PURE__ */ new Map();
|
|
2398
2521
|
const inflight = /* @__PURE__ */ new Map();
|
|
2399
2522
|
const active = /* @__PURE__ */ new Set();
|
|
@@ -3908,6 +4031,110 @@ var isChordHeavyTrack = (notes, threshold = 0.6) => {
|
|
|
3908
4031
|
return chordNotes / notes.length >= threshold;
|
|
3909
4032
|
};
|
|
3910
4033
|
|
|
4034
|
+
// src/mml-info.ts
|
|
4035
|
+
var MML_INFO_HTML = `
|
|
4036
|
+
<div class="dtm-modal-body-content">
|
|
4037
|
+
<h4>1. \u97F3\u7B26\u3068\u4F11\u7B26</h4>
|
|
4038
|
+
<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>
|
|
4039
|
+
<ul>
|
|
4040
|
+
<li>\u534A\u97F3\u4E0A\u3052\u308B: <code>c#</code> \u307E\u305F\u306F <code>c+</code></li>
|
|
4041
|
+
<li>\u534A\u97F3\u4E0B\u3052\u308B: <code>d-</code></li>
|
|
4042
|
+
<li>\u4F11\u7B26: <code>r</code></li>
|
|
4043
|
+
</ul>
|
|
4044
|
+
|
|
4045
|
+
<h4>2. \u97F3\u306E\u9577\u3055</h4>
|
|
4046
|
+
<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>
|
|
4047
|
+
<ul>
|
|
4048
|
+
<li><code>c4</code> : 4\u5206\u97F3\u7B26\u306E\u30C9</li>
|
|
4049
|
+
<li><code>r8</code> : 8\u5206\u4F11\u7B26</li>
|
|
4050
|
+
<li><code>c4.</code> : \u4ED8\u70B94\u5206\u97F3\u7B26\u306E\u30C9\uFF08\u9577\u3055\u30921.5\u500D\u306B\uFF09</li>
|
|
4051
|
+
<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>
|
|
4052
|
+
</ul>
|
|
4053
|
+
|
|
4054
|
+
<h4>3. \u30AA\u30AF\u30BF\u30FC\u30D6\uFF08\u97F3\u306E\u9AD8\u3055\uFF09</h4>
|
|
4055
|
+
<ul>
|
|
4056
|
+
<li><code>o4</code>, <code>o5</code> : \u9AD8\u3055\u3092\u76F4\u63A5\u6307\u5B9A\uFF08\u3075\u3064\u3046\u306F o4 \u304B o5\uFF09</li>
|
|
4057
|
+
<li><code>></code> : 1\u30AA\u30AF\u30BF\u30FC\u30D6\u4E0A\u3052\u308B</li>
|
|
4058
|
+
<li><code><</code> : 1\u30AA\u30AF\u30BF\u30FC\u30D6\u4E0B\u3052\u308B</li>
|
|
4059
|
+
</ul>
|
|
4060
|
+
|
|
4061
|
+
<h4>4. \u30C6\u30F3\u30DD</h4>
|
|
4062
|
+
<ul>
|
|
4063
|
+
<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>
|
|
4064
|
+
</ul>
|
|
4065
|
+
|
|
4066
|
+
<h4>5. \u548C\u97F3</h4>
|
|
4067
|
+
<p>\u97F3\u7B26\u3092 <code>[</code> \u3068 <code>]</code> \u3067\u56F2\u3080\u3068\u540C\u6642\u306B\u767A\u97F3\u3057\u307E\u3059\u3002</p>
|
|
4068
|
+
<pre>\u4F8B: [ceg]4 \uFF08\u30C9\u30FB\u30DF\u30FB\u30BD\u30924\u5206\u97F3\u7B26\u3067\u540C\u6642\u306B\u767A\u97F3\uFF09</pre>
|
|
4069
|
+
|
|
4070
|
+
<h4>6. \u30C8\u30E9\u30C3\u30AF\u306E\u533A\u5207\u308A</h4>
|
|
4071
|
+
<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>
|
|
4072
|
+
<ul>
|
|
4073
|
+
<li><code>@0</code>: \u30E1\u30ED\u30C7\u30A3</li>
|
|
4074
|
+
<li><code>@1</code>: \u30B5\u30D6\u30E1\u30ED</li>
|
|
4075
|
+
<li><code>@2</code>: \u30D9\u30FC\u30B9</li>
|
|
4076
|
+
<li><code>@3</code>: \u4F34\u594F</li>
|
|
4077
|
+
</ul>
|
|
4078
|
+
|
|
4079
|
+
<h4>7. \u6B4C\u58F0\u30FB\u6B4C\u8A5E\u5165\u529B</h4>
|
|
4080
|
+
<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>
|
|
4081
|
+
<pre>\u4F8B: @@0 tsukuyomi \u3069\u3093\u3050\u308A\u3053\u308D\u3053\u308D\u3069\u3093\u3050\u308A\u3053</pre>
|
|
4082
|
+
<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>
|
|
4083
|
+
|
|
4084
|
+
<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>
|
|
4085
|
+
|
|
4086
|
+
<!-- \u30B5\u30F3\u30D7\u30EB1 -->
|
|
4087
|
+
<div class="dtm-modal-sample-box">
|
|
4088
|
+
<div class="dtm-modal-sample-header">
|
|
4089
|
+
<span class="dtm-modal-sample-tag">1. \u57FA\u672C\u306E\u30E1\u30ED\u30C7\u30A3</span>
|
|
4090
|
+
<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>
|
|
4091
|
+
</div>
|
|
4092
|
+
<pre style="margin: 0; padding: 6px;">@0 t120 l8 o5 c d e f g a b > c</pre>
|
|
4093
|
+
<div class="dtm-modal-sample-desc">
|
|
4094
|
+
\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
|
|
4095
|
+
</div>
|
|
4096
|
+
<div style="margin-top: 8px;">
|
|
4097
|
+
<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>
|
|
4098
|
+
</div>
|
|
4099
|
+
<div class="dtm-modal-sample-player-container"></div>
|
|
4100
|
+
</div>
|
|
4101
|
+
|
|
4102
|
+
<!-- \u30B5\u30F3\u30D7\u30EB2 -->
|
|
4103
|
+
<div class="dtm-modal-sample-box">
|
|
4104
|
+
<div class="dtm-modal-sample-header">
|
|
4105
|
+
<span class="dtm-modal-sample-tag">2. \u8907\u6570\u30C8\u30E9\u30C3\u30AF\u3068\u548C\u97F3</span>
|
|
4106
|
+
<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>
|
|
4107
|
+
</div>
|
|
4108
|
+
<pre style="margin: 0; padding: 6px;">@0 t120 o5 c e g2 ;
|
|
4109
|
+
@3 o4 [ceg]2 [ceg]2</pre>
|
|
4110
|
+
<div class="dtm-modal-sample-desc">
|
|
4111
|
+
; \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
|
|
4112
|
+
</div>
|
|
4113
|
+
<div style="margin-top: 8px;">
|
|
4114
|
+
<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>
|
|
4115
|
+
</div>
|
|
4116
|
+
<div class="dtm-modal-sample-player-container"></div>
|
|
4117
|
+
</div>
|
|
4118
|
+
|
|
4119
|
+
<!-- \u30B5\u30F3\u30D7\u30EB3 -->
|
|
4120
|
+
<div class="dtm-modal-sample-box">
|
|
4121
|
+
<div class="dtm-modal-sample-header">
|
|
4122
|
+
<span class="dtm-modal-sample-tag">3. \u6B4C\u5531\u4ED8\u304D (\u3069\u3093\u3050\u308A\u3053\u308D\u3053\u308D)</span>
|
|
4123
|
+
<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>
|
|
4124
|
+
</div>
|
|
4125
|
+
<pre style="margin: 0; padding: 6px;">@0 t120 v100 o4g8 g8 e8 e8 f8 e8 d8 c8 g8 g8 e8 e8 d4.;
|
|
4126
|
+
@@0 tsukuyomi \u3069\u3093\u3050\u308A\u3053\u308D\u3053\u308D\u3069\u3093\u3050\u308A\u3053;</pre>
|
|
4127
|
+
<div class="dtm-modal-sample-desc">
|
|
4128
|
+
@@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
|
|
4129
|
+
</div>
|
|
4130
|
+
<div style="margin-top: 8px;">
|
|
4131
|
+
<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>
|
|
4132
|
+
</div>
|
|
4133
|
+
<div class="dtm-modal-sample-player-container"></div>
|
|
4134
|
+
</div>
|
|
4135
|
+
</div>
|
|
4136
|
+
`;
|
|
4137
|
+
|
|
3911
4138
|
// src/mml-parser.ts
|
|
3912
4139
|
var PITCH_MAP2 = {
|
|
3913
4140
|
c: 0,
|
|
@@ -3960,6 +4187,7 @@ var parseMML = (mml, options = {}) => {
|
|
|
3960
4187
|
bpm,
|
|
3961
4188
|
tokenTracks: collectTokens ? tokenTracks : void 0,
|
|
3962
4189
|
lyrics: collectLyrics ? /* @__PURE__ */ new Map() : void 0,
|
|
4190
|
+
mergedTrackCount: 0,
|
|
3963
4191
|
meta: {}
|
|
3964
4192
|
};
|
|
3965
4193
|
}
|
|
@@ -3972,13 +4200,24 @@ var parseMML = (mml, options = {}) => {
|
|
|
3972
4200
|
const fullMML = stripLyrics(noMeta).replace(endRegex, "").replace(/[\n\r]+/g, " ").trim();
|
|
3973
4201
|
const parts = fullMML.split(/(@\d+)/).filter((p) => p.trim().length > 0);
|
|
3974
4202
|
let trackIndex = 0;
|
|
4203
|
+
let sourceTrackIndex = 0;
|
|
3975
4204
|
let octave = 4;
|
|
3976
4205
|
let currentStep = 0;
|
|
3977
4206
|
let baseLength = 16;
|
|
4207
|
+
const contributors = /* @__PURE__ */ new Map();
|
|
4208
|
+
const recordContributor = () => {
|
|
4209
|
+
let set = contributors.get(trackIndex);
|
|
4210
|
+
if (!set) {
|
|
4211
|
+
set = /* @__PURE__ */ new Set();
|
|
4212
|
+
contributors.set(trackIndex, set);
|
|
4213
|
+
}
|
|
4214
|
+
set.add(sourceTrackIndex);
|
|
4215
|
+
};
|
|
3978
4216
|
for (const rawPart of parts) {
|
|
3979
4217
|
const part = rawPart.trim();
|
|
3980
4218
|
if (part.startsWith("@")) {
|
|
3981
4219
|
let idx = Number.parseInt(part.substring(1), 10);
|
|
4220
|
+
sourceTrackIndex = idx;
|
|
3982
4221
|
if (clampTrackCount !== void 0 && idx >= clampTrackCount)
|
|
3983
4222
|
idx = clampTrackCount - 1;
|
|
3984
4223
|
trackIndex = idx;
|
|
@@ -4102,6 +4341,7 @@ var parseMML = (mml, options = {}) => {
|
|
|
4102
4341
|
}
|
|
4103
4342
|
if (j < body.length && body[j] === "]") j++;
|
|
4104
4343
|
const steps = parseLength();
|
|
4344
|
+
if (chordNotes.length > 0) recordContributor();
|
|
4105
4345
|
for (const p of chordNotes) {
|
|
4106
4346
|
placements.push({
|
|
4107
4347
|
trackIndex,
|
|
@@ -4125,6 +4365,7 @@ var parseMML = (mml, options = {}) => {
|
|
|
4125
4365
|
}
|
|
4126
4366
|
const midiPitch = (octave + 1) * 12 + pitch;
|
|
4127
4367
|
const steps = parseLength();
|
|
4368
|
+
recordContributor();
|
|
4128
4369
|
placements.push({
|
|
4129
4370
|
trackIndex,
|
|
4130
4371
|
startStep: currentStep,
|
|
@@ -4138,11 +4379,16 @@ var parseMML = (mml, options = {}) => {
|
|
|
4138
4379
|
}
|
|
4139
4380
|
}
|
|
4140
4381
|
}
|
|
4382
|
+
let mergedTrackCount = 0;
|
|
4383
|
+
for (const set of contributors.values()) {
|
|
4384
|
+
if (set.size >= 2) mergedTrackCount++;
|
|
4385
|
+
}
|
|
4141
4386
|
return {
|
|
4142
4387
|
placements,
|
|
4143
4388
|
bpm,
|
|
4144
4389
|
tokenTracks: collectTokens ? tokenTracks : void 0,
|
|
4145
4390
|
lyrics,
|
|
4391
|
+
mergedTrackCount,
|
|
4146
4392
|
meta
|
|
4147
4393
|
};
|
|
4148
4394
|
};
|
|
@@ -4204,6 +4450,8 @@ var createSequencer = (options) => {
|
|
|
4204
4450
|
let active = false;
|
|
4205
4451
|
let fromStepValue = 0;
|
|
4206
4452
|
let trackVolumeMap = /* @__PURE__ */ new Map();
|
|
4453
|
+
let lastRealTime = -1;
|
|
4454
|
+
let lastAudioTime = -1;
|
|
4207
4455
|
let isLooping = false;
|
|
4208
4456
|
let loopStartStep = 0;
|
|
4209
4457
|
let loopEndStep = 0;
|
|
@@ -4277,6 +4525,21 @@ var createSequencer = (options) => {
|
|
|
4277
4525
|
const sps = secondsPerStep();
|
|
4278
4526
|
const time = options.getAudioTime() - startTime;
|
|
4279
4527
|
const soloId = options.getSoloTrackId();
|
|
4528
|
+
const nowReal = performance.now() / 1e3;
|
|
4529
|
+
if (lastRealTime > 0 && lastAudioTime >= 0) {
|
|
4530
|
+
const realDelta = nowReal - lastRealTime;
|
|
4531
|
+
const audioDelta = time - lastAudioTime;
|
|
4532
|
+
if (realDelta > 0.5 || audioDelta > 0.5) {
|
|
4533
|
+
console.warn(
|
|
4534
|
+
`[sequencer] Interruption detected (realDelta: ${realDelta.toFixed(3)}s, audioDelta: ${audioDelta.toFixed(3)}s). Stopping playback.`
|
|
4535
|
+
);
|
|
4536
|
+
stop();
|
|
4537
|
+
options.onEnd(true);
|
|
4538
|
+
return;
|
|
4539
|
+
}
|
|
4540
|
+
}
|
|
4541
|
+
lastRealTime = nowReal;
|
|
4542
|
+
lastAudioTime = time;
|
|
4280
4543
|
for (const track of options.getTracks()) {
|
|
4281
4544
|
trackVolumeMap.set(track.id, track.volume);
|
|
4282
4545
|
}
|
|
@@ -4353,7 +4616,7 @@ var createSequencer = (options) => {
|
|
|
4353
4616
|
const lastDuration = last?.duration ?? 0;
|
|
4354
4617
|
if (nowIndex >= timeline.length && time > lastWhen + lastDuration + 0.1) {
|
|
4355
4618
|
stop();
|
|
4356
|
-
options.onEnd();
|
|
4619
|
+
options.onEnd(false);
|
|
4357
4620
|
}
|
|
4358
4621
|
}
|
|
4359
4622
|
};
|
|
@@ -4394,6 +4657,8 @@ var createSequencer = (options) => {
|
|
|
4394
4657
|
}
|
|
4395
4658
|
loopBase = 0;
|
|
4396
4659
|
lastPlayStep = fromStepValue - 1e-4;
|
|
4660
|
+
lastRealTime = -1;
|
|
4661
|
+
lastAudioTime = -1;
|
|
4397
4662
|
intervalId = setInterval(scheduleTick, TICK_INTERVAL_MS);
|
|
4398
4663
|
animationId = requestAnimationFrame(animate);
|
|
4399
4664
|
};
|
|
@@ -4492,9 +4757,13 @@ var DAW_CSS = `
|
|
|
4492
4757
|
/* \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
|
|
4493
4758
|
\u30B3\u30F3\u30C8\u30ED\u30FC\u30EB\u30D0\u30FC\uFF08.dtm-controlbar\uFF09\u306B\u3082\u4F9B\u7D66\u3059\u308B\u3002mountPresetSelect /
|
|
4494
4759
|
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
|
|
4495
|
-
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
|
|
4760
|
+
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
|
|
4761
|
+
\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
|
|
4762
|
+
.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 */
|
|
4496
4763
|
.dtm-daw,
|
|
4497
|
-
.dtm-controlbar
|
|
4764
|
+
.dtm-controlbar,
|
|
4765
|
+
.dtm-modal-overlay,
|
|
4766
|
+
.dtm-consent-overlay {
|
|
4498
4767
|
/* PICO-8 16\u8272\u30D1\u30EC\u30C3\u30C8\u3088\u308A */
|
|
4499
4768
|
--c-black: #000000;
|
|
4500
4769
|
--c-navy: #1d2b53;
|
|
@@ -4591,11 +4860,11 @@ var DAW_CSS = `
|
|
|
4591
4860
|
}
|
|
4592
4861
|
.dtm-btn:active { transform: translate(3px,3px); box-shadow: none; }
|
|
4593
4862
|
.dtm-btn:disabled { opacity: .3; cursor: default; box-shadow: none; }
|
|
4863
|
+
.dtm-btn--ghost { background: transparent; border-color: var(--dtm-border2); }
|
|
4594
4864
|
.dtm-btn--primary { border-color: var(--dtm-primary); background: var(--dtm-primary); color: var(--dtm-pfg); }
|
|
4595
4865
|
.dtm-btn--success { border-color: var(--dtm-success); background: var(--dtm-success); color: var(--c-black); }
|
|
4596
4866
|
.dtm-btn--danger { border-color: var(--dtm-danger); background: var(--dtm-danger); color: var(--c-white); }
|
|
4597
4867
|
.dtm-btn--accent { border-color: var(--dtm-accent); background: var(--dtm-accent); color: var(--c-black); }
|
|
4598
|
-
.dtm-btn--ghost { background: transparent; border-color: var(--dtm-border2); }
|
|
4599
4868
|
.dtm-btn--icon { padding: 0; }
|
|
4600
4869
|
|
|
4601
4870
|
/* \u2500\u2500\u2500 \u30A2\u30A4\u30B3\u30F3\u30DC\u30BF\u30F3 \u2500\u2500\u2500 */
|
|
@@ -5092,14 +5361,37 @@ var DAW_CSS = `
|
|
|
5092
5361
|
justify-content: center;
|
|
5093
5362
|
padding: 16px;
|
|
5094
5363
|
backdrop-filter: blur(2px);
|
|
5364
|
+
/* 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
|
|
5365
|
+
.dtm-daw \u304B\u3089\u7D99\u627F\u3067\u304D\u306A\u3044\u305F\u3081\u3001\u3053\u3053\u3067\u660E\u793A\u3059\u308B\u3002 */
|
|
5366
|
+
color: var(--dtm-text);
|
|
5367
|
+
font-family: var(--dtm-font);
|
|
5095
5368
|
}
|
|
5096
5369
|
.dtm-modal-overlay[hidden] {
|
|
5097
5370
|
display: none !important;
|
|
5098
5371
|
}
|
|
5099
|
-
|
|
5100
|
-
|
|
5372
|
+
|
|
5373
|
+
/* \u2500\u2500\u2500 \u5229\u7528\u898F\u7D04\u540C\u610F\u30AB\u30D0\u30FC \u2500\u2500\u2500 */
|
|
5374
|
+
.dtm-consent-overlay {
|
|
5375
|
+
position: fixed;
|
|
5376
|
+
inset: 0;
|
|
5377
|
+
z-index: 10100;
|
|
5378
|
+
background: rgba(0, 0, 0, 0.6);
|
|
5379
|
+
display: flex;
|
|
5380
|
+
align-items: center;
|
|
5381
|
+
justify-content: center;
|
|
5382
|
+
padding: 16px;
|
|
5383
|
+
backdrop-filter: blur(2px);
|
|
5384
|
+
/* 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 */
|
|
5385
|
+
color: var(--dtm-text);
|
|
5386
|
+
font-family: var(--dtm-font);
|
|
5387
|
+
}
|
|
5388
|
+
.dtm-consent-overlay[hidden] {
|
|
5389
|
+
display: none !important;
|
|
5390
|
+
}
|
|
5391
|
+
.dtm-consent-modal {
|
|
5392
|
+
max-width: 450px;
|
|
5101
5393
|
width: 100%;
|
|
5102
|
-
max-height:
|
|
5394
|
+
max-height: 85vh;
|
|
5103
5395
|
display: flex;
|
|
5104
5396
|
flex-direction: column;
|
|
5105
5397
|
background: var(--dtm-surface);
|
|
@@ -5108,20 +5400,63 @@ var DAW_CSS = `
|
|
|
5108
5400
|
inset 0 0 0 2px var(--c-black),
|
|
5109
5401
|
0 0 0 2px var(--dtm-primary),
|
|
5110
5402
|
4px 4px 0 var(--c-black);
|
|
5111
|
-
overflow:
|
|
5403
|
+
overflow-y: auto;
|
|
5112
5404
|
}
|
|
5113
|
-
.dtm-
|
|
5114
|
-
display: flex;
|
|
5115
|
-
align-items: center;
|
|
5116
|
-
justify-content: space-between;
|
|
5405
|
+
.dtm-consent-header {
|
|
5117
5406
|
background: var(--dtm-deep);
|
|
5407
|
+
color: var(--dtm-text);
|
|
5118
5408
|
padding: 8px 12px;
|
|
5119
5409
|
border-bottom: 2px solid var(--c-black);
|
|
5120
|
-
|
|
5121
|
-
|
|
5122
|
-
font-
|
|
5123
|
-
|
|
5124
|
-
|
|
5410
|
+
font-weight: bold;
|
|
5411
|
+
text-align: center;
|
|
5412
|
+
font-size: 14px;
|
|
5413
|
+
}
|
|
5414
|
+
.dtm-consent-body {
|
|
5415
|
+
padding: 12px 16px;
|
|
5416
|
+
font-size: 13px;
|
|
5417
|
+
line-height: 1.6;
|
|
5418
|
+
}
|
|
5419
|
+
.dtm-consent-body a {
|
|
5420
|
+
color: var(--dtm-primary);
|
|
5421
|
+
text-decoration: underline;
|
|
5422
|
+
}
|
|
5423
|
+
.dtm-consent-body a:hover {
|
|
5424
|
+
color: var(--dtm-accent);
|
|
5425
|
+
}
|
|
5426
|
+
.dtm-consent-footer {
|
|
5427
|
+
padding: 8px;
|
|
5428
|
+
border-top: 2px solid var(--c-black);
|
|
5429
|
+
background: var(--dtm-deep);
|
|
5430
|
+
display: flex;
|
|
5431
|
+
justify-content: center;
|
|
5432
|
+
}
|
|
5433
|
+
|
|
5434
|
+
.dtm-modal {
|
|
5435
|
+
max-width: 500px;
|
|
5436
|
+
width: 100%;
|
|
5437
|
+
max-height: 80vh;
|
|
5438
|
+
display: flex;
|
|
5439
|
+
flex-direction: column;
|
|
5440
|
+
background: var(--dtm-surface);
|
|
5441
|
+
border: 2px solid var(--c-black);
|
|
5442
|
+
box-shadow:
|
|
5443
|
+
inset 0 0 0 2px var(--c-black),
|
|
5444
|
+
0 0 0 2px var(--dtm-primary),
|
|
5445
|
+
4px 4px 0 var(--c-black);
|
|
5446
|
+
overflow: hidden;
|
|
5447
|
+
}
|
|
5448
|
+
.dtm-modal-header {
|
|
5449
|
+
display: flex;
|
|
5450
|
+
align-items: center;
|
|
5451
|
+
justify-content: space-between;
|
|
5452
|
+
background: var(--dtm-deep);
|
|
5453
|
+
padding: 8px 12px;
|
|
5454
|
+
border-bottom: 2px solid var(--c-black);
|
|
5455
|
+
}
|
|
5456
|
+
.dtm-modal-title {
|
|
5457
|
+
font-family: var(--dtm-font);
|
|
5458
|
+
font-size: 14px;
|
|
5459
|
+
color: var(--dtm-gold);
|
|
5125
5460
|
font-weight: bold;
|
|
5126
5461
|
}
|
|
5127
5462
|
.dtm-modal-close {
|
|
@@ -5229,6 +5564,19 @@ var DAW_CSS = `
|
|
|
5229
5564
|
}
|
|
5230
5565
|
|
|
5231
5566
|
.dtm-hidden { display: none !important; }
|
|
5567
|
+
/* \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 */
|
|
5568
|
+
.dtm-load-note {
|
|
5569
|
+
margin: 6px 0 0;
|
|
5570
|
+
padding: 0 2px;
|
|
5571
|
+
font-family: var(--dtm-font);
|
|
5572
|
+
font-size: 11px;
|
|
5573
|
+
line-height: 1.5;
|
|
5574
|
+
letter-spacing: .04em;
|
|
5575
|
+
color: var(--dtm-warn); /* \u8B66\u544A\u8272\uFF08\u30AA\u30EC\u30F3\u30B8\uFF09 */
|
|
5576
|
+
font-weight: bold;
|
|
5577
|
+
opacity: 1.0;
|
|
5578
|
+
}
|
|
5579
|
+
.dtm-load-note::before { content: "\u26A0 "; }
|
|
5232
5580
|
.dtm-grow { flex: 1 1 auto; }
|
|
5233
5581
|
.dtm-lyric-icon {
|
|
5234
5582
|
flex: 0 0 auto;
|
|
@@ -5328,6 +5676,62 @@ var DAW_CSS = `
|
|
|
5328
5676
|
white-space: nowrap;
|
|
5329
5677
|
}
|
|
5330
5678
|
.dtm-player-mml-link:hover { color: var(--dtm-primary); }
|
|
5679
|
+
.dtm-player-more-container {
|
|
5680
|
+
position: relative;
|
|
5681
|
+
display: inline-flex;
|
|
5682
|
+
align-items: center;
|
|
5683
|
+
}
|
|
5684
|
+
.dtm-player-more-btn {
|
|
5685
|
+
background: transparent;
|
|
5686
|
+
border: none;
|
|
5687
|
+
color: var(--dtm-muted);
|
|
5688
|
+
cursor: pointer;
|
|
5689
|
+
padding: 2px;
|
|
5690
|
+
display: flex;
|
|
5691
|
+
align-items: center;
|
|
5692
|
+
justify-content: center;
|
|
5693
|
+
border-radius: 50%;
|
|
5694
|
+
width: 24px;
|
|
5695
|
+
height: 24px;
|
|
5696
|
+
transition: color 0.15s, background-color 0.15s;
|
|
5697
|
+
}
|
|
5698
|
+
.dtm-player-more-btn:hover,
|
|
5699
|
+
.dtm-player-more-btn.is-active {
|
|
5700
|
+
color: var(--dtm-text);
|
|
5701
|
+
background: var(--dtm-border2);
|
|
5702
|
+
}
|
|
5703
|
+
.dtm-player-menu {
|
|
5704
|
+
position: absolute;
|
|
5705
|
+
top: calc(100% + 4px);
|
|
5706
|
+
right: 0;
|
|
5707
|
+
background: var(--dtm-deep);
|
|
5708
|
+
border: 2px solid var(--dtm-border2);
|
|
5709
|
+
box-shadow: 4px 4px 0 var(--c-black);
|
|
5710
|
+
z-index: 200;
|
|
5711
|
+
display: flex;
|
|
5712
|
+
flex-direction: column;
|
|
5713
|
+
padding: 4px 0;
|
|
5714
|
+
min-width: 130px;
|
|
5715
|
+
font-family: var(--dtm-font);
|
|
5716
|
+
}
|
|
5717
|
+
.dtm-player-menu-item {
|
|
5718
|
+
background: transparent;
|
|
5719
|
+
border: none;
|
|
5720
|
+
color: var(--dtm-text);
|
|
5721
|
+
padding: 6px 12px;
|
|
5722
|
+
text-align: left;
|
|
5723
|
+
cursor: pointer;
|
|
5724
|
+
font-size: 11px;
|
|
5725
|
+
font-family: inherit;
|
|
5726
|
+
white-space: nowrap;
|
|
5727
|
+
width: 100%;
|
|
5728
|
+
box-sizing: border-box;
|
|
5729
|
+
transition: background-color 0.1s, color 0.1s;
|
|
5730
|
+
}
|
|
5731
|
+
.dtm-player-menu-item:hover {
|
|
5732
|
+
background: var(--dtm-primary);
|
|
5733
|
+
color: var(--dtm-pfg);
|
|
5734
|
+
}
|
|
5331
5735
|
.dtm-player-emoji {
|
|
5332
5736
|
position: relative;
|
|
5333
5737
|
display: inline-flex;
|
|
@@ -5573,6 +5977,7 @@ var STEPS_PER_BEAT3 = 48;
|
|
|
5573
5977
|
var STEPS_PER_BAR = 192;
|
|
5574
5978
|
var DEFAULT_TRACK_COLORS = ["#00e436", "#29adff", "#ff77a8", "#ffec27"];
|
|
5575
5979
|
var activePlayer = null;
|
|
5980
|
+
var agreedModelsInSession = /* @__PURE__ */ new Set();
|
|
5576
5981
|
var LYRIC_MODEL_LABELS = {
|
|
5577
5982
|
klatt: "\u8EFD\u91CF\u30ED\u30DC\u58F0",
|
|
5578
5983
|
...KOE_VOICEBANK_LABELS
|
|
@@ -5603,6 +6008,75 @@ var showBalloon = (balloonEl) => {
|
|
|
5603
6008
|
hideActiveBalloon();
|
|
5604
6009
|
}, 3e3);
|
|
5605
6010
|
};
|
|
6011
|
+
var copyToClipboard = async (doc, text) => {
|
|
6012
|
+
try {
|
|
6013
|
+
await navigator.clipboard.writeText(text);
|
|
6014
|
+
return true;
|
|
6015
|
+
} catch {
|
|
6016
|
+
try {
|
|
6017
|
+
const textarea = doc.createElement("textarea");
|
|
6018
|
+
textarea.value = text;
|
|
6019
|
+
textarea.style.position = "fixed";
|
|
6020
|
+
textarea.style.opacity = "0";
|
|
6021
|
+
doc.body.appendChild(textarea);
|
|
6022
|
+
textarea.select();
|
|
6023
|
+
const ok = doc.execCommand("copy");
|
|
6024
|
+
doc.body.removeChild(textarea);
|
|
6025
|
+
return ok;
|
|
6026
|
+
} catch {
|
|
6027
|
+
return false;
|
|
6028
|
+
}
|
|
6029
|
+
}
|
|
6030
|
+
};
|
|
6031
|
+
var toBase64Url = (bytes) => {
|
|
6032
|
+
let bin = "";
|
|
6033
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
6034
|
+
bin += String.fromCharCode(bytes[i]);
|
|
6035
|
+
}
|
|
6036
|
+
return btoa(bin).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
6037
|
+
};
|
|
6038
|
+
var HIRAGANA_START = 12353;
|
|
6039
|
+
var HIRAGANA_END = 12447;
|
|
6040
|
+
var KATAKANA_START = 12449;
|
|
6041
|
+
var KATAKANA_END = 12543;
|
|
6042
|
+
var PROLONGED_MARK = 12540;
|
|
6043
|
+
var SHIFT_KATAKANA = 255;
|
|
6044
|
+
var VALUE_PROLONGED = 223;
|
|
6045
|
+
var customEncode = (str) => {
|
|
6046
|
+
const bytes = [];
|
|
6047
|
+
for (let i = 0; i < str.length; i++) {
|
|
6048
|
+
const code = str.charCodeAt(i);
|
|
6049
|
+
if (code <= 127) {
|
|
6050
|
+
bytes.push(code);
|
|
6051
|
+
} else if (code === PROLONGED_MARK) {
|
|
6052
|
+
bytes.push(VALUE_PROLONGED);
|
|
6053
|
+
} else if (code >= HIRAGANA_START && code <= HIRAGANA_END) {
|
|
6054
|
+
bytes.push(128 + (code - HIRAGANA_START));
|
|
6055
|
+
} else if (code >= KATAKANA_START && code <= KATAKANA_END) {
|
|
6056
|
+
bytes.push(SHIFT_KATAKANA);
|
|
6057
|
+
bytes.push(128 + (code - 96 - HIRAGANA_START));
|
|
6058
|
+
}
|
|
6059
|
+
}
|
|
6060
|
+
return new Uint8Array(bytes);
|
|
6061
|
+
};
|
|
6062
|
+
var encodeMml = async (mml) => {
|
|
6063
|
+
try {
|
|
6064
|
+
if (typeof CompressionStream !== "undefined") {
|
|
6065
|
+
const cs = new CompressionStream("gzip");
|
|
6066
|
+
const w = cs.writable.getWriter();
|
|
6067
|
+
w.write(customEncode(mml));
|
|
6068
|
+
w.close();
|
|
6069
|
+
const buf = await new Response(cs.readable).arrayBuffer();
|
|
6070
|
+
return `z.${toBase64Url(new Uint8Array(buf))}`;
|
|
6071
|
+
}
|
|
6072
|
+
} catch (e) {
|
|
6073
|
+
console.warn(
|
|
6074
|
+
"[dtm] CompressionStream failed, fallback to encodeURIComponent",
|
|
6075
|
+
e
|
|
6076
|
+
);
|
|
6077
|
+
}
|
|
6078
|
+
return `u.${encodeURIComponent(mml)}`;
|
|
6079
|
+
};
|
|
5606
6080
|
var mountMmlPlayer = (target, mml, options = {}) => {
|
|
5607
6081
|
injectStyles(target.ownerDocument ?? document);
|
|
5608
6082
|
const {
|
|
@@ -5748,6 +6222,250 @@ var mountMmlPlayer = (target, mml, options = {}) => {
|
|
|
5748
6222
|
emojiEls.push(em);
|
|
5749
6223
|
emojiByTrack.set(index, em);
|
|
5750
6224
|
}
|
|
6225
|
+
const menuContainer = doc.createElement("div");
|
|
6226
|
+
menuContainer.className = "dtm-player-more-container";
|
|
6227
|
+
const moreBtn = doc.createElement("button");
|
|
6228
|
+
moreBtn.type = "button";
|
|
6229
|
+
moreBtn.className = "dtm-player-more-btn";
|
|
6230
|
+
moreBtn.innerHTML = icon("more", 14);
|
|
6231
|
+
moreBtn.title = "\u30E1\u30CB\u30E5\u30FC";
|
|
6232
|
+
menuContainer.appendChild(moreBtn);
|
|
6233
|
+
const menuDropdown = doc.createElement("div");
|
|
6234
|
+
menuDropdown.className = "dtm-player-menu";
|
|
6235
|
+
menuDropdown.style.display = "none";
|
|
6236
|
+
const makeMenuItem = (label) => {
|
|
6237
|
+
const item = doc.createElement("button");
|
|
6238
|
+
item.type = "button";
|
|
6239
|
+
item.className = "dtm-player-menu-item";
|
|
6240
|
+
item.textContent = label;
|
|
6241
|
+
return item;
|
|
6242
|
+
};
|
|
6243
|
+
const showMmlItem = makeMenuItem("MML\u3092\u8868\u793A");
|
|
6244
|
+
const mmlInfoItem = makeMenuItem("MML\u66F8\u5F0F\u3068\u306F");
|
|
6245
|
+
const embedItem = makeMenuItem("\u57CB\u3081\u8FBC\u3080");
|
|
6246
|
+
const copyMmlItem = makeMenuItem("MML\u30B3\u30D4\u30FC");
|
|
6247
|
+
menuDropdown.appendChild(showMmlItem);
|
|
6248
|
+
menuDropdown.appendChild(mmlInfoItem);
|
|
6249
|
+
menuDropdown.appendChild(embedItem);
|
|
6250
|
+
menuDropdown.appendChild(copyMmlItem);
|
|
6251
|
+
menuContainer.appendChild(menuDropdown);
|
|
6252
|
+
mmlHeader.appendChild(menuContainer);
|
|
6253
|
+
const toggleMenu = (show) => {
|
|
6254
|
+
const visible = show !== void 0 ? show : menuDropdown.style.display === "none";
|
|
6255
|
+
menuDropdown.style.display = visible ? "flex" : "none";
|
|
6256
|
+
if (visible) {
|
|
6257
|
+
moreBtn.classList.add("is-active");
|
|
6258
|
+
doc.addEventListener("click", handleOutsideClick);
|
|
6259
|
+
} else {
|
|
6260
|
+
moreBtn.classList.remove("is-active");
|
|
6261
|
+
doc.removeEventListener("click", handleOutsideClick);
|
|
6262
|
+
}
|
|
6263
|
+
};
|
|
6264
|
+
const handleOutsideClick = (e) => {
|
|
6265
|
+
if (!menuContainer.contains(e.target)) {
|
|
6266
|
+
toggleMenu(false);
|
|
6267
|
+
}
|
|
6268
|
+
};
|
|
6269
|
+
moreBtn.addEventListener("click", (e) => {
|
|
6270
|
+
e.stopPropagation();
|
|
6271
|
+
toggleMenu();
|
|
6272
|
+
});
|
|
6273
|
+
let infoModalEl = null;
|
|
6274
|
+
let modalSamplePlayer = null;
|
|
6275
|
+
const closeInfoModal = () => {
|
|
6276
|
+
if (modalSamplePlayer) {
|
|
6277
|
+
modalSamplePlayer.stop();
|
|
6278
|
+
modalSamplePlayer.destroy();
|
|
6279
|
+
modalSamplePlayer = null;
|
|
6280
|
+
}
|
|
6281
|
+
infoModalEl?.remove();
|
|
6282
|
+
infoModalEl = null;
|
|
6283
|
+
};
|
|
6284
|
+
const openInfoModal = (title) => {
|
|
6285
|
+
closeInfoModal();
|
|
6286
|
+
const overlay = doc.createElement("div");
|
|
6287
|
+
overlay.className = "dtm-modal-overlay";
|
|
6288
|
+
const modal = doc.createElement("div");
|
|
6289
|
+
modal.className = "dtm-win dtm-modal";
|
|
6290
|
+
const header = doc.createElement("div");
|
|
6291
|
+
header.className = "dtm-modal-header";
|
|
6292
|
+
const titleEl = doc.createElement("span");
|
|
6293
|
+
titleEl.className = "dtm-modal-title";
|
|
6294
|
+
titleEl.textContent = title;
|
|
6295
|
+
const closeBtn = doc.createElement("button");
|
|
6296
|
+
closeBtn.type = "button";
|
|
6297
|
+
closeBtn.className = "dtm-modal-close";
|
|
6298
|
+
closeBtn.innerHTML = "×";
|
|
6299
|
+
closeBtn.title = "\u9589\u3058\u308B";
|
|
6300
|
+
header.append(titleEl, closeBtn);
|
|
6301
|
+
const modalBody = doc.createElement("div");
|
|
6302
|
+
modalBody.className = "dtm-modal-body";
|
|
6303
|
+
modal.append(header, modalBody);
|
|
6304
|
+
overlay.appendChild(modal);
|
|
6305
|
+
closeBtn.addEventListener("click", (e) => {
|
|
6306
|
+
e.stopPropagation();
|
|
6307
|
+
closeInfoModal();
|
|
6308
|
+
});
|
|
6309
|
+
overlay.addEventListener("click", (e) => {
|
|
6310
|
+
if (e.target === overlay) closeInfoModal();
|
|
6311
|
+
});
|
|
6312
|
+
doc.body.appendChild(overlay);
|
|
6313
|
+
infoModalEl = overlay;
|
|
6314
|
+
return modalBody;
|
|
6315
|
+
};
|
|
6316
|
+
const appendCopyButton = (parent, text) => {
|
|
6317
|
+
const actions = doc.createElement("div");
|
|
6318
|
+
actions.style.marginTop = "8px";
|
|
6319
|
+
const copyBtn = doc.createElement("button");
|
|
6320
|
+
copyBtn.type = "button";
|
|
6321
|
+
copyBtn.className = "dtm-btn dtm-btn--primary dtm-btn--xs";
|
|
6322
|
+
copyBtn.textContent = "\u{1F4CB} \u30B3\u30D4\u30FC";
|
|
6323
|
+
copyBtn.addEventListener("click", async (e) => {
|
|
6324
|
+
e.stopPropagation();
|
|
6325
|
+
const ok = await copyToClipboard(doc, text);
|
|
6326
|
+
copyBtn.textContent = ok ? "\u2713 \u30B3\u30D4\u30FC\u5B8C\u4E86" : "\u30B3\u30D4\u30FC\u5931\u6557";
|
|
6327
|
+
if (ok) copyBtn.classList.add("dtm-btn--success");
|
|
6328
|
+
setTimeout(() => {
|
|
6329
|
+
copyBtn.textContent = "\u{1F4CB} \u30B3\u30D4\u30FC";
|
|
6330
|
+
copyBtn.classList.remove("dtm-btn--success");
|
|
6331
|
+
}, 1200);
|
|
6332
|
+
});
|
|
6333
|
+
actions.appendChild(copyBtn);
|
|
6334
|
+
parent.appendChild(actions);
|
|
6335
|
+
};
|
|
6336
|
+
const wireSampleButtons = (modalBody) => {
|
|
6337
|
+
const copyBtns = modalBody.querySelectorAll(".dtm-modal-sample-copy-btn");
|
|
6338
|
+
for (const btn of copyBtns) {
|
|
6339
|
+
const el = btn;
|
|
6340
|
+
el.addEventListener("click", async (e) => {
|
|
6341
|
+
e.stopPropagation();
|
|
6342
|
+
const sampleMml = el.getAttribute("data-mml") ?? "";
|
|
6343
|
+
const original = el.textContent;
|
|
6344
|
+
const ok = await copyToClipboard(doc, sampleMml);
|
|
6345
|
+
el.textContent = ok ? "\u2713 \u30B3\u30D4\u30FC\u5B8C\u4E86" : "\u30B3\u30D4\u30FC\u5931\u6557";
|
|
6346
|
+
if (ok) el.classList.add("dtm-btn--success");
|
|
6347
|
+
setTimeout(() => {
|
|
6348
|
+
el.textContent = original;
|
|
6349
|
+
el.classList.remove("dtm-btn--success");
|
|
6350
|
+
}, 1200);
|
|
6351
|
+
});
|
|
6352
|
+
}
|
|
6353
|
+
let activeSampleBtn = null;
|
|
6354
|
+
const resetSampleBtn = (b) => {
|
|
6355
|
+
if (!b) return;
|
|
6356
|
+
b.textContent = "\u25B6 \u8A66\u8074";
|
|
6357
|
+
b.classList.remove("dtm-btn--danger");
|
|
6358
|
+
b.classList.add("dtm-btn--primary");
|
|
6359
|
+
};
|
|
6360
|
+
const markPlaying = (b) => {
|
|
6361
|
+
b.textContent = "\u25A0 \u505C\u6B62";
|
|
6362
|
+
b.classList.remove("dtm-btn--primary");
|
|
6363
|
+
b.classList.add("dtm-btn--danger");
|
|
6364
|
+
};
|
|
6365
|
+
const playBtns = modalBody.querySelectorAll(".dtm-modal-sample-play-btn");
|
|
6366
|
+
for (const btn of playBtns) {
|
|
6367
|
+
const el = btn;
|
|
6368
|
+
el.addEventListener("click", (e) => {
|
|
6369
|
+
e.stopPropagation();
|
|
6370
|
+
const sampleMml = el.getAttribute("data-mml") ?? "";
|
|
6371
|
+
if (activeSampleBtn === el && modalSamplePlayer) {
|
|
6372
|
+
if (modalSamplePlayer.isPlaying()) {
|
|
6373
|
+
modalSamplePlayer.stop();
|
|
6374
|
+
} else {
|
|
6375
|
+
modalSamplePlayer.play();
|
|
6376
|
+
markPlaying(el);
|
|
6377
|
+
}
|
|
6378
|
+
return;
|
|
6379
|
+
}
|
|
6380
|
+
if (modalSamplePlayer) {
|
|
6381
|
+
modalSamplePlayer.stop();
|
|
6382
|
+
modalSamplePlayer.destroy();
|
|
6383
|
+
modalSamplePlayer = null;
|
|
6384
|
+
}
|
|
6385
|
+
resetSampleBtn(activeSampleBtn);
|
|
6386
|
+
activeSampleBtn = el;
|
|
6387
|
+
const sampleBox = el.closest(".dtm-modal-sample-box");
|
|
6388
|
+
const container = sampleBox?.querySelector(
|
|
6389
|
+
".dtm-modal-sample-player-container"
|
|
6390
|
+
);
|
|
6391
|
+
if (!container) return;
|
|
6392
|
+
container.innerHTML = "";
|
|
6393
|
+
modalSamplePlayer = mountMmlPlayer(container, sampleMml, {
|
|
6394
|
+
onPlayNote: options.onPlayNote,
|
|
6395
|
+
onPlayDrum: options.onPlayDrum,
|
|
6396
|
+
onResumeAudio: options.onResumeAudio,
|
|
6397
|
+
getAudioTime: options.getAudioTime,
|
|
6398
|
+
singingVoices: options.singingVoices,
|
|
6399
|
+
drumPatterns: options.drumPatterns,
|
|
6400
|
+
volume: trackVolume,
|
|
6401
|
+
// 解説モーダル内の試聴サンプルは規約同意を要求しない。
|
|
6402
|
+
skipConsent: true,
|
|
6403
|
+
onStop: () => {
|
|
6404
|
+
if (activeSampleBtn === el) resetSampleBtn(el);
|
|
6405
|
+
}
|
|
6406
|
+
});
|
|
6407
|
+
markPlaying(el);
|
|
6408
|
+
modalSamplePlayer.play();
|
|
6409
|
+
});
|
|
6410
|
+
}
|
|
6411
|
+
};
|
|
6412
|
+
showMmlItem.addEventListener("click", (e) => {
|
|
6413
|
+
e.stopPropagation();
|
|
6414
|
+
toggleMenu(false);
|
|
6415
|
+
const modalBody = openInfoModal("MML");
|
|
6416
|
+
const pre = doc.createElement("pre");
|
|
6417
|
+
pre.textContent = mml;
|
|
6418
|
+
pre.style.whiteSpace = "pre-wrap";
|
|
6419
|
+
pre.style.wordBreak = "break-all";
|
|
6420
|
+
modalBody.appendChild(pre);
|
|
6421
|
+
appendCopyButton(modalBody, mml);
|
|
6422
|
+
});
|
|
6423
|
+
mmlInfoItem.addEventListener("click", (e) => {
|
|
6424
|
+
e.stopPropagation();
|
|
6425
|
+
toggleMenu(false);
|
|
6426
|
+
const modalBody = openInfoModal("MML\u306E\u66F8\u304D\u65B9\u89E3\u8AAC");
|
|
6427
|
+
modalBody.innerHTML = MML_INFO_HTML;
|
|
6428
|
+
wireSampleButtons(modalBody);
|
|
6429
|
+
});
|
|
6430
|
+
embedItem.addEventListener("click", async (e) => {
|
|
6431
|
+
e.stopPropagation();
|
|
6432
|
+
toggleMenu(false);
|
|
6433
|
+
const modalBody = openInfoModal("\u57CB\u3081\u8FBC\u307F");
|
|
6434
|
+
const loading = doc.createElement("p");
|
|
6435
|
+
loading.textContent = "\u751F\u6210\u4E2D...";
|
|
6436
|
+
modalBody.appendChild(loading);
|
|
6437
|
+
try {
|
|
6438
|
+
const embedBase = options.embedUrl ?? "https://onjmin.github.io/dtm/demo/embed.html";
|
|
6439
|
+
const payload = await encodeMml(mml);
|
|
6440
|
+
const url2 = `${embedBase}#${payload}`;
|
|
6441
|
+
const snippet = `<iframe src="${url2}" width="100%" height="260" frameborder="0" loading="lazy" title="@onjmin/dtm player"></iframe>`;
|
|
6442
|
+
if (!modalBody.isConnected) return;
|
|
6443
|
+
loading.remove();
|
|
6444
|
+
const desc = doc.createElement("p");
|
|
6445
|
+
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";
|
|
6446
|
+
const pre = doc.createElement("pre");
|
|
6447
|
+
pre.textContent = snippet;
|
|
6448
|
+
pre.style.whiteSpace = "pre-wrap";
|
|
6449
|
+
pre.style.wordBreak = "break-all";
|
|
6450
|
+
modalBody.append(desc, pre);
|
|
6451
|
+
appendCopyButton(modalBody, snippet);
|
|
6452
|
+
} catch (err2) {
|
|
6453
|
+
console.error("[dtm] failed to generate embed snippet", err2);
|
|
6454
|
+
if (modalBody.isConnected) loading.textContent = "\u751F\u6210\u306B\u5931\u6557\u3057\u307E\u3057\u305F";
|
|
6455
|
+
}
|
|
6456
|
+
});
|
|
6457
|
+
copyMmlItem.addEventListener("click", async (e) => {
|
|
6458
|
+
e.stopPropagation();
|
|
6459
|
+
const success = await copyToClipboard(doc, mml);
|
|
6460
|
+
if (success) {
|
|
6461
|
+
copyMmlItem.textContent = "\u30B3\u30D4\u30FC\u3057\u307E\u3057\u305F\uFF01";
|
|
6462
|
+
} else {
|
|
6463
|
+
copyMmlItem.textContent = "\u30B3\u30D4\u30FC\u5931\u6557";
|
|
6464
|
+
}
|
|
6465
|
+
setTimeout(() => {
|
|
6466
|
+
copyMmlItem.textContent = "MML\u30B3\u30D4\u30FC";
|
|
6467
|
+
}, 2e3);
|
|
6468
|
+
});
|
|
5751
6469
|
const promotedToImage = /* @__PURE__ */ new Set();
|
|
5752
6470
|
for (const [index, lt] of lyricTracks) {
|
|
5753
6471
|
const em = emojiByTrack.get(index);
|
|
@@ -5991,6 +6709,77 @@ var mountMmlPlayer = (target, mml, options = {}) => {
|
|
|
5991
6709
|
root.appendChild(termsDiv);
|
|
5992
6710
|
}
|
|
5993
6711
|
target.appendChild(root);
|
|
6712
|
+
let consentOverlayEl = null;
|
|
6713
|
+
const checkConsentAndShow = () => {
|
|
6714
|
+
try {
|
|
6715
|
+
if (options.skipConsent) return;
|
|
6716
|
+
const unagreed = termsModels.filter((model) => {
|
|
6717
|
+
if (agreedModelsInSession.has(model)) return false;
|
|
6718
|
+
try {
|
|
6719
|
+
if (typeof localStorage === "undefined" || !localStorage) return true;
|
|
6720
|
+
return localStorage.getItem(`dtm_agreed_terms_${model}`) !== "true";
|
|
6721
|
+
} catch (e) {
|
|
6722
|
+
console.warn(
|
|
6723
|
+
"[dtm-player] localStorage access denied in consent check",
|
|
6724
|
+
e
|
|
6725
|
+
);
|
|
6726
|
+
return true;
|
|
6727
|
+
}
|
|
6728
|
+
});
|
|
6729
|
+
if (unagreed.length === 0) return;
|
|
6730
|
+
const consentOverlay = doc.createElement("div");
|
|
6731
|
+
consentOverlay.className = "dtm-consent-overlay";
|
|
6732
|
+
const modal = doc.createElement("div");
|
|
6733
|
+
modal.className = "dtm-win dtm-consent-modal";
|
|
6734
|
+
const header = doc.createElement("div");
|
|
6735
|
+
header.className = "dtm-consent-header";
|
|
6736
|
+
header.textContent = "\u5229\u7528\u898F\u7D04\u306E\u78BA\u8A8D";
|
|
6737
|
+
const body2 = doc.createElement("div");
|
|
6738
|
+
body2.className = "dtm-consent-body";
|
|
6739
|
+
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>`;
|
|
6740
|
+
for (const model of unagreed) {
|
|
6741
|
+
const label = KOE_VOICEBANK_LABELS[model] || model;
|
|
6742
|
+
const url2 = KOE_VOICEBANK_TERMS[model];
|
|
6743
|
+
contentHTML += `
|
|
6744
|
+
<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);">
|
|
6745
|
+
<div style="display: flex; align-items: center; gap: 4px; flex-wrap: wrap; font-size: 11px; font-weight: bold; color: var(--dtm-gold);">
|
|
6746
|
+
<span>\u4F7F\u7528\u6642\u306B\u306F</span>
|
|
6747
|
+
<a href="${url2}" target="_blank" rel="noopener noreferrer" style="color: var(--dtm-primary); text-decoration: underline;">${label}UTAU\u97F3\u6E90</a>
|
|
6748
|
+
<span>\u306E\u5229\u7528\u898F\u7D04\u306B\u5F93\u3063\u3066\u304F\u3060\u3055\u3044</span>
|
|
6749
|
+
</div>
|
|
6750
|
+
</div>
|
|
6751
|
+
`;
|
|
6752
|
+
}
|
|
6753
|
+
body2.innerHTML = contentHTML;
|
|
6754
|
+
const footer = doc.createElement("div");
|
|
6755
|
+
footer.className = "dtm-consent-footer";
|
|
6756
|
+
const btn = doc.createElement("button");
|
|
6757
|
+
btn.type = "button";
|
|
6758
|
+
btn.className = "dtm-btn dtm-btn--success";
|
|
6759
|
+
btn.textContent = "\u540C\u610F\u3057\u3066\u5229\u7528\u3059\u308B";
|
|
6760
|
+
btn.onclick = () => {
|
|
6761
|
+
for (const model of unagreed) {
|
|
6762
|
+
try {
|
|
6763
|
+
if (typeof localStorage !== "undefined" && localStorage) {
|
|
6764
|
+
localStorage.setItem(`dtm_agreed_terms_${model}`, "true");
|
|
6765
|
+
}
|
|
6766
|
+
} catch (e) {
|
|
6767
|
+
}
|
|
6768
|
+
agreedModelsInSession.add(model);
|
|
6769
|
+
}
|
|
6770
|
+
consentOverlay.remove();
|
|
6771
|
+
consentOverlayEl = null;
|
|
6772
|
+
};
|
|
6773
|
+
footer.appendChild(btn);
|
|
6774
|
+
modal.append(header, body2, footer);
|
|
6775
|
+
consentOverlay.appendChild(modal);
|
|
6776
|
+
doc.body.appendChild(consentOverlay);
|
|
6777
|
+
consentOverlayEl = consentOverlay;
|
|
6778
|
+
} catch (err2) {
|
|
6779
|
+
console.error("[dtm-player] Error in checkConsentAndShow:", err2);
|
|
6780
|
+
}
|
|
6781
|
+
};
|
|
6782
|
+
checkConsentAndShow();
|
|
5994
6783
|
const autoScroll = (lane, el) => {
|
|
5995
6784
|
if (el.offsetWidth === 0 || lane.clientWidth === 0) return;
|
|
5996
6785
|
const elementCenter = el.offsetLeft + el.offsetWidth / 2;
|
|
@@ -6056,7 +6845,7 @@ var mountMmlPlayer = (target, mml, options = {}) => {
|
|
|
6056
6845
|
onTick: (step) => {
|
|
6057
6846
|
renderPlayhead(step);
|
|
6058
6847
|
},
|
|
6059
|
-
onEnd: () => finish(),
|
|
6848
|
+
onEnd: (interrupted) => finish(),
|
|
6060
6849
|
stepsPerBar: STEPS_PER_BAR
|
|
6061
6850
|
});
|
|
6062
6851
|
let playing = false;
|
|
@@ -6151,6 +6940,7 @@ var mountMmlPlayer = (target, mml, options = {}) => {
|
|
|
6151
6940
|
else play();
|
|
6152
6941
|
});
|
|
6153
6942
|
const destroy = () => {
|
|
6943
|
+
doc.removeEventListener("click", handleOutsideClick);
|
|
6154
6944
|
seq.stop();
|
|
6155
6945
|
peekVoices()?.stopStream();
|
|
6156
6946
|
if (activePlayer === instance) activePlayer = null;
|
|
@@ -6164,6 +6954,8 @@ var mountMmlPlayer = (target, mml, options = {}) => {
|
|
|
6164
6954
|
hideActiveBalloon();
|
|
6165
6955
|
}
|
|
6166
6956
|
root.remove();
|
|
6957
|
+
consentOverlayEl?.remove();
|
|
6958
|
+
closeInfoModal();
|
|
6167
6959
|
};
|
|
6168
6960
|
const instance = {
|
|
6169
6961
|
play,
|
|
@@ -6205,108 +6997,6 @@ var CHORD_INFO_HTML = `
|
|
|
6205
6997
|
</ul>
|
|
6206
6998
|
</div>
|
|
6207
6999
|
`;
|
|
6208
|
-
var MML_INFO_HTML = `
|
|
6209
|
-
<div class="dtm-modal-body-content">
|
|
6210
|
-
<h4>1. \u97F3\u7B26\u3068\u4F11\u7B26</h4>
|
|
6211
|
-
<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>
|
|
6212
|
-
<ul>
|
|
6213
|
-
<li>\u534A\u97F3\u4E0A\u3052\u308B: <code>c#</code> \u307E\u305F\u306F <code>c+</code></li>
|
|
6214
|
-
<li>\u534A\u97F3\u4E0B\u3052\u308B: <code>d-</code></li>
|
|
6215
|
-
<li>\u4F11\u7B26: <code>r</code></li>
|
|
6216
|
-
</ul>
|
|
6217
|
-
|
|
6218
|
-
<h4>2. \u97F3\u306E\u9577\u3055</h4>
|
|
6219
|
-
<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>
|
|
6220
|
-
<ul>
|
|
6221
|
-
<li><code>c4</code> : 4\u5206\u97F3\u7B26\u306E\u30C9</li>
|
|
6222
|
-
<li><code>r8</code> : 8\u5206\u4F11\u7B26</li>
|
|
6223
|
-
<li><code>c4.</code> : \u4ED8\u70B94\u5206\u97F3\u7B26\u306E\u30C9\uFF08\u9577\u3055\u30921.5\u500D\u306B\uFF09</li>
|
|
6224
|
-
<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>
|
|
6225
|
-
</ul>
|
|
6226
|
-
|
|
6227
|
-
<h4>3. \u30AA\u30AF\u30BF\u30FC\u30D6\uFF08\u97F3\u306E\u9AD8\u3055\uFF09</h4>
|
|
6228
|
-
<ul>
|
|
6229
|
-
<li><code>o4</code>, <code>o5</code> : \u9AD8\u3055\u3092\u76F4\u63A5\u6307\u5B9A\uFF08\u3075\u3064\u3046\u306F o4 \u304B o5\uFF09</li>
|
|
6230
|
-
<li><code>></code> : 1\u30AA\u30AF\u30BF\u30FC\u30D6\u4E0A\u3052\u308B</li>
|
|
6231
|
-
<li><code><</code> : 1\u30AA\u30AF\u30BF\u30FC\u30D6\u4E0B\u3052\u308B</li>
|
|
6232
|
-
</ul>
|
|
6233
|
-
|
|
6234
|
-
<h4>4. \u30C6\u30F3\u30DD</h4>
|
|
6235
|
-
<ul>
|
|
6236
|
-
<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>
|
|
6237
|
-
</ul>
|
|
6238
|
-
|
|
6239
|
-
<h4>5. \u548C\u97F3</h4>
|
|
6240
|
-
<p>\u97F3\u7B26\u3092 <code>[</code> \u3068 <code>]</code> \u3067\u56F2\u3080\u3068\u540C\u6642\u306B\u767A\u97F3\u3057\u307E\u3059\u3002</p>
|
|
6241
|
-
<pre>\u4F8B: [ceg]4 \uFF08\u30C9\u30FB\u30DF\u30FB\u30BD\u30924\u5206\u97F3\u7B26\u3067\u540C\u6642\u306B\u767A\u97F3\uFF09</pre>
|
|
6242
|
-
|
|
6243
|
-
<h4>6. \u30C8\u30E9\u30C3\u30AF\u306E\u533A\u5207\u308A</h4>
|
|
6244
|
-
<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>
|
|
6245
|
-
<ul>
|
|
6246
|
-
<li><code>@0</code>: \u30E1\u30ED\u30C7\u30A3</li>
|
|
6247
|
-
<li><code>@1</code>: \u30B5\u30D6\u30E1\u30ED</li>
|
|
6248
|
-
<li><code>@2</code>: \u30D9\u30FC\u30B9</li>
|
|
6249
|
-
<li><code>@3</code>: \u4F34\u594F</li>
|
|
6250
|
-
</ul>
|
|
6251
|
-
|
|
6252
|
-
<h4>7. \u6B4C\u58F0\u30FB\u6B4C\u8A5E\u5165\u529B</h4>
|
|
6253
|
-
<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>
|
|
6254
|
-
<pre>\u4F8B: @@0 tsukuyomi \u3069\u3093\u3050\u308A\u3053\u308D\u3053\u308D\u3069\u3093\u3050\u308A\u3053</pre>
|
|
6255
|
-
<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>
|
|
6256
|
-
|
|
6257
|
-
<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>
|
|
6258
|
-
|
|
6259
|
-
<!-- \u30B5\u30F3\u30D7\u30EB1 -->
|
|
6260
|
-
<div class="dtm-modal-sample-box">
|
|
6261
|
-
<div class="dtm-modal-sample-header">
|
|
6262
|
-
<span class="dtm-modal-sample-tag">1. \u57FA\u672C\u306E\u30E1\u30ED\u30C7\u30A3</span>
|
|
6263
|
-
<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>
|
|
6264
|
-
</div>
|
|
6265
|
-
<pre style="margin: 0; padding: 6px;">@0 t120 l8 o5 c d e f g a b > c</pre>
|
|
6266
|
-
<div class="dtm-modal-sample-desc">
|
|
6267
|
-
\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
|
|
6268
|
-
</div>
|
|
6269
|
-
<div style="margin-top: 8px;">
|
|
6270
|
-
<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>
|
|
6271
|
-
</div>
|
|
6272
|
-
<div class="dtm-modal-sample-player-container"></div>
|
|
6273
|
-
</div>
|
|
6274
|
-
|
|
6275
|
-
<!-- \u30B5\u30F3\u30D7\u30EB2 -->
|
|
6276
|
-
<div class="dtm-modal-sample-box">
|
|
6277
|
-
<div class="dtm-modal-sample-header">
|
|
6278
|
-
<span class="dtm-modal-sample-tag">2. \u8907\u6570\u30C8\u30E9\u30C3\u30AF\u3068\u548C\u97F3</span>
|
|
6279
|
-
<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>
|
|
6280
|
-
</div>
|
|
6281
|
-
<pre style="margin: 0; padding: 6px;">@0 t120 o5 c e g2 ;
|
|
6282
|
-
@3 o4 [ceg]2 [ceg]2</pre>
|
|
6283
|
-
<div class="dtm-modal-sample-desc">
|
|
6284
|
-
; \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
|
|
6285
|
-
</div>
|
|
6286
|
-
<div style="margin-top: 8px;">
|
|
6287
|
-
<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>
|
|
6288
|
-
</div>
|
|
6289
|
-
<div class="dtm-modal-sample-player-container"></div>
|
|
6290
|
-
</div>
|
|
6291
|
-
|
|
6292
|
-
<!-- \u30B5\u30F3\u30D7\u30EB3 -->
|
|
6293
|
-
<div class="dtm-modal-sample-box">
|
|
6294
|
-
<div class="dtm-modal-sample-header">
|
|
6295
|
-
<span class="dtm-modal-sample-tag">3. \u6B4C\u5531\u4ED8\u304D (\u3069\u3093\u3050\u308A\u3053\u308D\u3053\u308D)</span>
|
|
6296
|
-
<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>
|
|
6297
|
-
</div>
|
|
6298
|
-
<pre style="margin: 0; padding: 6px;">@0 t120 v100 o4g8 g8 e8 e8 f8 e8 d8 c8 g8 g8 e8 e8 d4.;
|
|
6299
|
-
@@0 tsukuyomi \u3069\u3093\u3050\u308A\u3053\u308D\u3053\u308D\u3069\u3093\u3050\u308A\u3053;</pre>
|
|
6300
|
-
<div class="dtm-modal-sample-desc">
|
|
6301
|
-
@@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
|
|
6302
|
-
</div>
|
|
6303
|
-
<div style="margin-top: 8px;">
|
|
6304
|
-
<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>
|
|
6305
|
-
</div>
|
|
6306
|
-
<div class="dtm-modal-sample-player-container"></div>
|
|
6307
|
-
</div>
|
|
6308
|
-
</div>
|
|
6309
|
-
`;
|
|
6310
7000
|
var MIDI_INFO_HTML = `
|
|
6311
7001
|
<div class="dtm-modal-body-content">
|
|
6312
7002
|
<h4>1. MIDI\u30D5\u30A1\u30A4\u30EB\u3068\u306F</h4>
|
|
@@ -7069,6 +7759,10 @@ var mountDAW = (target, options = {}) => {
|
|
|
7069
7759
|
0,
|
|
7070
7760
|
Math.floor(step / snapGridSteps) * snapGridSteps
|
|
7071
7761
|
);
|
|
7762
|
+
if (playbackState === "paused") {
|
|
7763
|
+
playbackState = "stopped";
|
|
7764
|
+
updateTransport();
|
|
7765
|
+
}
|
|
7072
7766
|
redrawAll();
|
|
7073
7767
|
});
|
|
7074
7768
|
setDrawOffset(currentOffsetX, currentOffsetY);
|
|
@@ -7144,9 +7838,14 @@ var mountDAW = (target, options = {}) => {
|
|
|
7144
7838
|
}
|
|
7145
7839
|
redrawAll();
|
|
7146
7840
|
},
|
|
7147
|
-
onEnd: () => {
|
|
7148
|
-
|
|
7149
|
-
|
|
7841
|
+
onEnd: (interrupted) => {
|
|
7842
|
+
if (interrupted) {
|
|
7843
|
+
playbackState = "paused";
|
|
7844
|
+
pausedPlayStep = currentPlayStep;
|
|
7845
|
+
} else {
|
|
7846
|
+
playbackState = "stopped";
|
|
7847
|
+
currentPlayStep = 0;
|
|
7848
|
+
}
|
|
7150
7849
|
updateTransport();
|
|
7151
7850
|
redrawAll();
|
|
7152
7851
|
},
|
|
@@ -7236,13 +7935,13 @@ var mountDAW = (target, options = {}) => {
|
|
|
7236
7935
|
redrawAll();
|
|
7237
7936
|
};
|
|
7238
7937
|
const togglePlay = () => {
|
|
7239
|
-
if (playbackState === "playing")
|
|
7938
|
+
if (playbackState === "playing") pause();
|
|
7240
7939
|
else play();
|
|
7241
7940
|
};
|
|
7242
7941
|
const updateTransport = () => {
|
|
7243
7942
|
const playing = playbackState === "playing";
|
|
7244
|
-
const label = playing ? "\u505C\u6B62" : playbackState === "paused" ? "\u518D\u958B" : "\u8A66\u8074";
|
|
7245
|
-
refs.playBtn.innerHTML = `${icon(playing ? "
|
|
7943
|
+
const label = playing ? "\u4E00\u6642\u505C\u6B62" : playbackState === "paused" ? "\u518D\u958B" : "\u8A66\u8074";
|
|
7944
|
+
refs.playBtn.innerHTML = `${icon(playing ? "pause" : "play")}<span>${label}</span>`;
|
|
7246
7945
|
refs.playBtn.classList.toggle("dtm-play--stop", playing);
|
|
7247
7946
|
};
|
|
7248
7947
|
const updateUndoRedo = () => {
|
|
@@ -7631,20 +8330,25 @@ var mountDAW = (target, options = {}) => {
|
|
|
7631
8330
|
};
|
|
7632
8331
|
const loadMML = (mml) => {
|
|
7633
8332
|
if (!mml) return;
|
|
8333
|
+
stop();
|
|
7634
8334
|
clearAll();
|
|
7635
8335
|
for (const t of trackStates) t.core.setLoadMode(true);
|
|
7636
8336
|
const {
|
|
7637
8337
|
placements,
|
|
7638
8338
|
bpm: parsedBpm,
|
|
7639
8339
|
lyrics,
|
|
7640
|
-
meta
|
|
8340
|
+
meta,
|
|
8341
|
+
mergedTrackCount
|
|
7641
8342
|
} = parseMML(mml, {
|
|
7642
8343
|
stepsPerBar: renderConfig.stepsPerBar,
|
|
7643
8344
|
collectLyrics: true,
|
|
7644
8345
|
// このDAWのトラック数を超えるチャンネルはベースへ畳み込む(従来挙動)
|
|
7645
8346
|
clampTrackCount: trackStates.length
|
|
7646
8347
|
});
|
|
7647
|
-
|
|
8348
|
+
if (meta.instrument && INSTRUMENT_PRESETS[meta.instrument]) {
|
|
8349
|
+
currentInstrument = meta.instrument;
|
|
8350
|
+
options.onInstrumentChange?.(meta.instrument);
|
|
8351
|
+
}
|
|
7648
8352
|
if (meta.drum && drumPatterns[meta.drum]) {
|
|
7649
8353
|
currentDrumPattern = meta.drum;
|
|
7650
8354
|
refs.drumSelect.value = meta.drum;
|
|
@@ -7663,8 +8367,8 @@ var mountDAW = (target, options = {}) => {
|
|
|
7663
8367
|
t.vocalPan = 64;
|
|
7664
8368
|
t.vocalOctave = 0;
|
|
7665
8369
|
}
|
|
7666
|
-
lyrics?.forEach((lt
|
|
7667
|
-
const t = trackStates[
|
|
8370
|
+
lyrics?.forEach((lt) => {
|
|
8371
|
+
const t = trackStates[lt.trackId];
|
|
7668
8372
|
if (!t) return;
|
|
7669
8373
|
t.lyrics = lt.syllables.map((s) => s.kana).join("");
|
|
7670
8374
|
t.lyricModel = lt.model;
|
|
@@ -7696,6 +8400,13 @@ var mountDAW = (target, options = {}) => {
|
|
|
7696
8400
|
redrawAll();
|
|
7697
8401
|
updateTrackPanel();
|
|
7698
8402
|
updateUndoRedo();
|
|
8403
|
+
if (!isAdvanced && mergedTrackCount > 0) {
|
|
8404
|
+
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";
|
|
8405
|
+
refs.mmlLoadNote.classList.remove("dtm-hidden");
|
|
8406
|
+
} else {
|
|
8407
|
+
refs.mmlLoadNote.textContent = "";
|
|
8408
|
+
refs.mmlLoadNote.classList.add("dtm-hidden");
|
|
8409
|
+
}
|
|
7699
8410
|
};
|
|
7700
8411
|
const applyChord = () => {
|
|
7701
8412
|
const active = getActive();
|
|
@@ -7728,6 +8439,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
7728
8439
|
applyMidiSelection(midi, selected);
|
|
7729
8440
|
};
|
|
7730
8441
|
const applyMidiSelection = (midi, selectedIndices) => {
|
|
8442
|
+
stop();
|
|
7731
8443
|
clearAll();
|
|
7732
8444
|
for (const t of trackStates) t.core.setLoadMode(true);
|
|
7733
8445
|
const { placements, bpm: parsedBpm } = isAdvanced ? extractMidiPlacementsByTrack(
|
|
@@ -8159,6 +8871,25 @@ var mountDAW = (target, options = {}) => {
|
|
|
8159
8871
|
const setLoading = (loading) => {
|
|
8160
8872
|
refs.topbar.classList.toggle("is-loading", loading);
|
|
8161
8873
|
};
|
|
8874
|
+
const getCurrentPlayStep = () => {
|
|
8875
|
+
if (playbackState === "playing") return currentPlayStep;
|
|
8876
|
+
if (playbackState === "paused") return pausedPlayStep;
|
|
8877
|
+
return playStartStep;
|
|
8878
|
+
};
|
|
8879
|
+
const forcePauseAt = (step) => {
|
|
8880
|
+
playStartStep = step;
|
|
8881
|
+
pausedPlayStep = step;
|
|
8882
|
+
currentPlayStep = step;
|
|
8883
|
+
playbackState = "paused";
|
|
8884
|
+
const canvas = getGridCanvas();
|
|
8885
|
+
currentOffsetX = Math.max(
|
|
8886
|
+
0,
|
|
8887
|
+
step * renderConfig.stepWidth - canvas.width * 0.5
|
|
8888
|
+
);
|
|
8889
|
+
setDrawOffset(currentOffsetX, currentOffsetY);
|
|
8890
|
+
updateTransport();
|
|
8891
|
+
redrawAll();
|
|
8892
|
+
};
|
|
8162
8893
|
return {
|
|
8163
8894
|
play,
|
|
8164
8895
|
pause,
|
|
@@ -8196,9 +8927,12 @@ var mountDAW = (target, options = {}) => {
|
|
|
8196
8927
|
exportMIDI: exportMIDI2,
|
|
8197
8928
|
setBpm,
|
|
8198
8929
|
getPlaybackState: () => playbackState,
|
|
8930
|
+
getCurrentPlayStep,
|
|
8931
|
+
forcePauseAt,
|
|
8199
8932
|
setLoading,
|
|
8200
8933
|
destroy: () => {
|
|
8201
8934
|
sequencer.stop();
|
|
8935
|
+
options.singingVoices?.stopStream();
|
|
8202
8936
|
resizeObserver.disconnect();
|
|
8203
8937
|
document.removeEventListener("pointermove", onPointerMove);
|
|
8204
8938
|
document.removeEventListener("pointerup", onPointerUp);
|
|
@@ -8208,110 +8942,6 @@ var mountDAW = (target, options = {}) => {
|
|
|
8208
8942
|
};
|
|
8209
8943
|
};
|
|
8210
8944
|
|
|
8211
|
-
// src/instrument-presets.ts
|
|
8212
|
-
var INSTRUMENT_PRESETS = {
|
|
8213
|
-
// --- STANDARD: 汎用性と完成度重視 ---
|
|
8214
|
-
piano: {
|
|
8215
|
-
displayName: "\u30B0\u30E9\u30F3\u30C9\u30D4\u30A2\u30CE",
|
|
8216
|
-
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",
|
|
8217
|
-
melody: "Acoustic Grand Piano",
|
|
8218
|
-
submelody: "Vibraphone",
|
|
8219
|
-
bass: "Electric Bass (finger)",
|
|
8220
|
-
chord: "Pad 2 (warm)"
|
|
8221
|
-
},
|
|
8222
|
-
acoustic: {
|
|
8223
|
-
displayName: "\u30A2\u30B3\u30FC\u30B9\u30C6\u30A3\u30C3\u30AF",
|
|
8224
|
-
description: "\u751F\u697D\u5668\u306E\u6E29\u304B\u307F\u3092\u91CD\u8996\u3002\u30D5\u30A9\u30FC\u30AF\u3084\u30DD\u30C3\u30D7\u30B9\u306B\u3002",
|
|
8225
|
-
melody: "Acoustic Guitar (steel)",
|
|
8226
|
-
submelody: "Harmonica",
|
|
8227
|
-
bass: "Acoustic Bass",
|
|
8228
|
-
chord: "Acoustic Guitar (nylon)"
|
|
8229
|
-
},
|
|
8230
|
-
jazz_night: {
|
|
8231
|
-
displayName: "\u30B8\u30E3\u30BA\u30FB\u30CA\u30A4\u30C8",
|
|
8232
|
-
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",
|
|
8233
|
-
melody: "Electric Piano 1",
|
|
8234
|
-
submelody: "Flute",
|
|
8235
|
-
bass: "Acoustic Bass",
|
|
8236
|
-
chord: "Electric Guitar (jazz)"
|
|
8237
|
-
},
|
|
8238
|
-
// --- MODERN & VIBE: エッジの効いた現代的な響き ---
|
|
8239
|
-
synth_pop: {
|
|
8240
|
-
displayName: "\u30B7\u30F3\u30BB\u30DD\u30C3\u30D7",
|
|
8241
|
-
description: "80s\u301C\u73FE\u4EE3\u307E\u3067\u3002\u629C\u3051\u308B\u30EA\u30FC\u30C9\u3068\u592A\u3044\u30D9\u30FC\u30B9\u306E\u738B\u9053\u3002",
|
|
8242
|
-
melody: "Lead 2 (sawtooth)",
|
|
8243
|
-
submelody: "Lead 4 (chiff)",
|
|
8244
|
-
bass: "Synth Bass 2",
|
|
8245
|
-
chord: "Pad 3 (polysynth)"
|
|
8246
|
-
},
|
|
8247
|
-
cyber_punk: {
|
|
8248
|
-
displayName: "\u30B5\u30A4\u30D0\u30FC\u30D1\u30F3\u30AF",
|
|
8249
|
-
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",
|
|
8250
|
-
melody: "Lead 8 (bass + lead)",
|
|
8251
|
-
submelody: "Lead 5 (charang)",
|
|
8252
|
-
bass: "Synth Bass 2",
|
|
8253
|
-
chord: "Pad 8 (sweep)"
|
|
8254
|
-
},
|
|
8255
|
-
rock: {
|
|
8256
|
-
displayName: "\u30CF\u30FC\u30C9\u30ED\u30C3\u30AF",
|
|
8257
|
-
description: "\u6B6A\u307F\u30AE\u30BF\u30FC\u3068\u91CD\u539A\u306A\u30D9\u30FC\u30B9\u3067\u3001\u30D1\u30EF\u30FC\u3092\u524D\u9762\u306B\u3002",
|
|
8258
|
-
melody: "Distortion Guitar",
|
|
8259
|
-
submelody: "Rock Organ",
|
|
8260
|
-
bass: "Electric Bass (pick)",
|
|
8261
|
-
chord: "Overdriven Guitar"
|
|
8262
|
-
},
|
|
8263
|
-
// --- WORLD & CLASSIC: 特定のジャンル・地域 ---
|
|
8264
|
-
orchestra: {
|
|
8265
|
-
displayName: "\u30AA\u30FC\u30B1\u30B9\u30C8\u30E9",
|
|
8266
|
-
description: "\u58EE\u5927\u306A\u7269\u8A9E\u3092\u4E88\u611F\u3055\u305B\u308B\u3001\u7BA1\u5F26\u697D\u5668\u306E\u91CD\u539A\u306A\u97FF\u304D\u3002",
|
|
8267
|
-
melody: "French Horn",
|
|
8268
|
-
submelody: "Pizzicato Strings",
|
|
8269
|
-
bass: "Cello",
|
|
8270
|
-
chord: "Tremolo Strings"
|
|
8271
|
-
},
|
|
8272
|
-
japanese_wa: {
|
|
8273
|
-
displayName: "\u548C\u98A8\u30FB\u96C5",
|
|
8274
|
-
description: "\u7434\u3068\u4E09\u5473\u7DDA\u306E\u7E4A\u7D30\u306A\u8ABF\u3079\u306B\u3001\u5C3A\u516B\u306E\u60C5\u7DD2\u3092\u6DFB\u3048\u3066\u3002",
|
|
8275
|
-
melody: "Koto",
|
|
8276
|
-
submelody: "Shamisen",
|
|
8277
|
-
bass: "Taiko Drum",
|
|
8278
|
-
chord: "Shakuhachi"
|
|
8279
|
-
},
|
|
8280
|
-
arabic_exotic: {
|
|
8281
|
-
displayName: "\u30A8\u30AD\u30BE\u30C1\u30C3\u30AF",
|
|
8282
|
-
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",
|
|
8283
|
-
melody: "Sitar",
|
|
8284
|
-
submelody: "Bagpipe",
|
|
8285
|
-
bass: "Fretless Bass",
|
|
8286
|
-
chord: "Kalimba"
|
|
8287
|
-
},
|
|
8288
|
-
// --- FANTASY & ATMOSPHERE: 雰囲気と余韻 ---
|
|
8289
|
-
fantasy_rpg: {
|
|
8290
|
-
displayName: "\u30D5\u30A1\u30F3\u30BF\u30B8\u30FCRPG",
|
|
8291
|
-
description: "\u30AA\u30AB\u30EA\u30CA\u3068\u30CF\u30FC\u30D7\u304C\u7D21\u3050\u3001\u5192\u967A\u3068\u9B54\u6CD5\u306E\u4E16\u754C\u89B3\u3002",
|
|
8292
|
-
melody: "Ocarina",
|
|
8293
|
-
submelody: "Celesta",
|
|
8294
|
-
bass: "Timpani",
|
|
8295
|
-
chord: "Orchestral Harp"
|
|
8296
|
-
},
|
|
8297
|
-
ambient_cloud: {
|
|
8298
|
-
displayName: "\u30A2\u30F3\u30D3\u30A8\u30F3\u30C8",
|
|
8299
|
-
description: "\u8F2A\u90ED\u3092\u307C\u304B\u3057\u305F\u97F3\u8272\u3067\u3001\u6DF1\u3044\u6CA1\u5165\u611F\u3068\u4F59\u97FB\u3092\u6F14\u51FA\u3002",
|
|
8300
|
-
melody: "Lead 6 (voice)",
|
|
8301
|
-
submelody: "Music Box",
|
|
8302
|
-
bass: "Synth Bass 1",
|
|
8303
|
-
chord: "Pad 7 (halo)"
|
|
8304
|
-
},
|
|
8305
|
-
retro_game: {
|
|
8306
|
-
displayName: "8-bit \u30EC\u30C8\u30ED",
|
|
8307
|
-
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",
|
|
8308
|
-
melody: "Lead 1 (square)",
|
|
8309
|
-
submelody: "Lead 2 (sawtooth)",
|
|
8310
|
-
bass: "Synth Bass 1",
|
|
8311
|
-
chord: "Clavinet"
|
|
8312
|
-
}
|
|
8313
|
-
};
|
|
8314
|
-
|
|
8315
8945
|
// src/headless-player.ts
|
|
8316
8946
|
var STEPS_PER_BAR2 = 192;
|
|
8317
8947
|
var playMML = (mml, options = {}) => {
|
|
@@ -8362,7 +8992,7 @@ var playMML = (mml, options = {}) => {
|
|
|
8362
8992
|
},
|
|
8363
8993
|
onTick: () => {
|
|
8364
8994
|
},
|
|
8365
|
-
onEnd: () => finish(),
|
|
8995
|
+
onEnd: (interrupted) => finish(),
|
|
8366
8996
|
stepsPerBar: STEPS_PER_BAR2
|
|
8367
8997
|
});
|
|
8368
8998
|
const finish = () => {
|
|
@@ -9182,11 +9812,13 @@ var createDtmStudio = async (options = {}) => {
|
|
|
9182
9812
|
const mountedPlayers = [];
|
|
9183
9813
|
const mountedModeSwitches = [];
|
|
9184
9814
|
const mountEditor = (target, opts = {}) => {
|
|
9185
|
-
const { preset, presetUI, ...dawOverrides } = opts;
|
|
9815
|
+
const { preset, presetUI, onInstrumentChange, ...dawOverrides } = opts;
|
|
9186
9816
|
const tracks = dawOverrides.tracks ?? TRACKS_SIMPLE;
|
|
9187
9817
|
const trackIds = tracks.map((t) => t.id);
|
|
9188
9818
|
const presetKey = preset && INSTRUMENT_PRESETS[preset] ? preset : defaultPreset;
|
|
9189
|
-
|
|
9819
|
+
const meta = opts.initialMML ? parseMmlMeta(opts.initialMML) : {};
|
|
9820
|
+
const initialPreset = meta.instrument && INSTRUMENT_PRESETS[meta.instrument] ? meta.instrument : presetKey;
|
|
9821
|
+
let editorPreset = initialPreset;
|
|
9190
9822
|
const isAdvancedMode = dawOverrides.mode === "advanced";
|
|
9191
9823
|
const playNote = (e) => {
|
|
9192
9824
|
const sf = resolveSoundFont(
|
|
@@ -9204,6 +9836,14 @@ var createDtmStudio = async (options = {}) => {
|
|
|
9204
9836
|
duration: e.duration
|
|
9205
9837
|
});
|
|
9206
9838
|
};
|
|
9839
|
+
let presetSelect = null;
|
|
9840
|
+
const handleInstrumentChange = (key) => {
|
|
9841
|
+
editorPreset = key;
|
|
9842
|
+
if (presetSelect) {
|
|
9843
|
+
presetSelect.setValue(key);
|
|
9844
|
+
}
|
|
9845
|
+
onInstrumentChange?.(key);
|
|
9846
|
+
};
|
|
9207
9847
|
const base = {
|
|
9208
9848
|
getAudioTime: () => audioCtx.currentTime,
|
|
9209
9849
|
onResumeAudio: resumeAudio,
|
|
@@ -9212,19 +9852,19 @@ var createDtmStudio = async (options = {}) => {
|
|
|
9212
9852
|
singingVoices,
|
|
9213
9853
|
parseMidi,
|
|
9214
9854
|
onToggleRecord,
|
|
9855
|
+
onInstrumentChange: handleInstrumentChange,
|
|
9215
9856
|
...dawOverrides
|
|
9216
9857
|
};
|
|
9217
9858
|
const daw = mountDAW(target, base);
|
|
9218
9859
|
mountedEditors.push(daw);
|
|
9219
9860
|
const wantPresetUI = presetUI ?? features.presetUI;
|
|
9220
|
-
let presetSelect = null;
|
|
9221
9861
|
if (wantPresetUI) {
|
|
9222
9862
|
editorPresetSelects.get(target)?.destroy();
|
|
9223
9863
|
const rollEl = target.querySelector('[data-dtm="roll"]');
|
|
9224
9864
|
presetSelect = mountPresetSelect(target, {
|
|
9225
9865
|
getDaw: () => daw,
|
|
9226
9866
|
getTrackIds: () => trackIds,
|
|
9227
|
-
value:
|
|
9867
|
+
value: initialPreset,
|
|
9228
9868
|
loadingTarget: rollEl ?? target,
|
|
9229
9869
|
position: "prepend",
|
|
9230
9870
|
// 楽器変更時、このエディタの発音解決が使うプリセットも追従させる。
|
|
@@ -9234,10 +9874,10 @@ var createDtmStudio = async (options = {}) => {
|
|
|
9234
9874
|
});
|
|
9235
9875
|
editorPresetSelects.set(target, presetSelect);
|
|
9236
9876
|
}
|
|
9237
|
-
daw.setInstrument(
|
|
9877
|
+
daw.setInstrument(initialPreset);
|
|
9238
9878
|
daw.setLoading?.(true);
|
|
9239
9879
|
void loadPreset(
|
|
9240
|
-
|
|
9880
|
+
initialPreset,
|
|
9241
9881
|
trackIds,
|
|
9242
9882
|
isAdvancedMode ? "advanced" : "simple"
|
|
9243
9883
|
).finally(() => {
|
|
@@ -9251,7 +9891,17 @@ var createDtmStudio = async (options = {}) => {
|
|
|
9251
9891
|
const i = mountedEditors.indexOf(daw);
|
|
9252
9892
|
if (i >= 0) mountedEditors.splice(i, 1);
|
|
9253
9893
|
};
|
|
9254
|
-
return {
|
|
9894
|
+
return {
|
|
9895
|
+
...daw,
|
|
9896
|
+
setInstrument: (name) => {
|
|
9897
|
+
daw.setInstrument(name);
|
|
9898
|
+
editorPreset = name;
|
|
9899
|
+
if (presetSelect) {
|
|
9900
|
+
presetSelect.setValue(name);
|
|
9901
|
+
}
|
|
9902
|
+
},
|
|
9903
|
+
destroy
|
|
9904
|
+
};
|
|
9255
9905
|
};
|
|
9256
9906
|
const mountModeSwitch = (target, opts) => {
|
|
9257
9907
|
const doc = target.ownerDocument;
|