@onjmin/dtm 0.1.24 → 0.1.26
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/README.md +1 -2
- package/dist/index.d.mts +8 -16
- package/dist/index.d.ts +8 -16
- package/dist/index.js +550 -252
- package/dist/index.mjs +550 -251
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -7,34 +7,6 @@ function createAudioContext() {
|
|
|
7
7
|
drumGainNode.connect(audioCtx.destination);
|
|
8
8
|
return { audioCtx, gainNode, drumGainNode };
|
|
9
9
|
}
|
|
10
|
-
function setupRecorder(audioCtx, gainNode, drumGainNode) {
|
|
11
|
-
let isRecording = false;
|
|
12
|
-
let recordedData = [[], []];
|
|
13
|
-
const recorderProcessor = audioCtx.createScriptProcessor(4096, 2, 2);
|
|
14
|
-
recorderProcessor.onaudioprocess = (e) => {
|
|
15
|
-
if (!isRecording) return;
|
|
16
|
-
const left = e.inputBuffer.getChannelData(0);
|
|
17
|
-
const right = e.inputBuffer.getChannelData(1);
|
|
18
|
-
recordedData[0].push(left.slice());
|
|
19
|
-
recordedData[1].push(right.slice());
|
|
20
|
-
};
|
|
21
|
-
gainNode.connect(recorderProcessor);
|
|
22
|
-
drumGainNode.connect(recorderProcessor);
|
|
23
|
-
recorderProcessor.connect(audioCtx.destination);
|
|
24
|
-
return {
|
|
25
|
-
startRecording: () => {
|
|
26
|
-
isRecording = true;
|
|
27
|
-
},
|
|
28
|
-
stopRecording: () => {
|
|
29
|
-
isRecording = false;
|
|
30
|
-
},
|
|
31
|
-
getRecordedData: () => recordedData,
|
|
32
|
-
isRecording: () => isRecording,
|
|
33
|
-
clearRecordedData: () => {
|
|
34
|
-
recordedData = [[], []];
|
|
35
|
-
}
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
10
|
async function fetchSoundFontList(ttl) {
|
|
39
11
|
const res = await fetch(`https://rpgen3.github.io/soundfont/list/${ttl}.txt`);
|
|
40
12
|
const str = await res.text();
|
|
@@ -1131,8 +1103,9 @@ var buildUI = (target, options) => {
|
|
|
1131
1103
|
target.innerHTML = `
|
|
1132
1104
|
<div class="dtm-daw" data-dtm="root">
|
|
1133
1105
|
<div class="dtm-topbar" data-dtm="transport">
|
|
1106
|
+
<button class="dtm-iconbtn" data-dtm="prev-bar" title="1\u5C0F\u7BC0\u524D">${icon("chevronLeft")}</button>
|
|
1134
1107
|
<button class="dtm-play" data-dtm="play" disabled>${icon("play")}<span>\u8A66\u8074</span></button>
|
|
1135
|
-
<button class="dtm-iconbtn
|
|
1108
|
+
<button class="dtm-iconbtn" data-dtm="next-bar" title="1\u5C0F\u7BC0\u5F8C">${icon("chevronRight")}</button>
|
|
1136
1109
|
<label class="dtm-toggle"><input type="checkbox" data-dtm="solo"><span>\u30BD\u30ED</span></label>
|
|
1137
1110
|
<span class="dtm-topbar-loading dtm-blink" data-dtm="topbar-loading">... LOADING ...</span>
|
|
1138
1111
|
<span class="dtm-grow"></span>
|
|
@@ -1297,10 +1270,12 @@ var buildUI = (target, options) => {
|
|
|
1297
1270
|
</div>
|
|
1298
1271
|
<div class="dtm-output dtm-hidden" data-dtm="output-container">
|
|
1299
1272
|
<p class="dtm-label" data-dtm="output-status"></p>
|
|
1273
|
+
<div class="dtm-output-label">\u6539\u884C\u3042\u308A\u7248</div>
|
|
1300
1274
|
<div class="dtm-output-row">
|
|
1301
1275
|
<pre><code data-dtm="output-full"></code></pre>
|
|
1302
1276
|
<button class="dtm-btn dtm-btn--primary dtm-btn--icon" data-dtm="copy-full" title="\u30B3\u30D4\u30FC">${icon("copy")}</button>
|
|
1303
1277
|
</div>
|
|
1278
|
+
<div class="dtm-output-label">\uFF11\u884C\u7248</div>
|
|
1304
1279
|
<div class="dtm-output-row">
|
|
1305
1280
|
<pre><code data-dtm="output-mini"></code></pre>
|
|
1306
1281
|
<button class="dtm-btn dtm-btn--primary dtm-btn--icon" data-dtm="copy-mini" title="\u30B3\u30D4\u30FC">${icon("copy")}</button>
|
|
@@ -1319,6 +1294,7 @@ var buildUI = (target, options) => {
|
|
|
1319
1294
|
<div class="dtm-modal-body" data-dtm="modal-body"></div>
|
|
1320
1295
|
</div>
|
|
1321
1296
|
</div>
|
|
1297
|
+
|
|
1322
1298
|
</div>`;
|
|
1323
1299
|
const root = q(target, '[data-dtm="root"]');
|
|
1324
1300
|
const sel = (name) => q(root, `[data-dtm="${name}"]`);
|
|
@@ -1327,7 +1303,8 @@ var buildUI = (target, options) => {
|
|
|
1327
1303
|
topbar: sel("transport"),
|
|
1328
1304
|
topbarLoading: sel("topbar-loading"),
|
|
1329
1305
|
playBtn: sel("play"),
|
|
1330
|
-
|
|
1306
|
+
prevBarBtn: sel("prev-bar"),
|
|
1307
|
+
nextBarBtn: sel("next-bar"),
|
|
1331
1308
|
soloCheckbox: sel("solo"),
|
|
1332
1309
|
toolPen: sel("tool-pen"),
|
|
1333
1310
|
toolSelect: sel("tool-select"),
|
|
@@ -2502,7 +2479,20 @@ var createWorkerBackend = async (workerUrl, options) => {
|
|
|
2502
2479
|
};
|
|
2503
2480
|
};
|
|
2504
2481
|
var createKoeVoice = async (ctx, destination, options) => {
|
|
2505
|
-
|
|
2482
|
+
let backend;
|
|
2483
|
+
if (options.voiceWorkerUrl) {
|
|
2484
|
+
try {
|
|
2485
|
+
backend = await createWorkerBackend(options.voiceWorkerUrl, options);
|
|
2486
|
+
} catch (err2) {
|
|
2487
|
+
console.warn(
|
|
2488
|
+
"[dtm] Failed to spawn voice worker. Falling back to local backend.",
|
|
2489
|
+
err2
|
|
2490
|
+
);
|
|
2491
|
+
backend = await createLocalBackend(options);
|
|
2492
|
+
}
|
|
2493
|
+
} else {
|
|
2494
|
+
backend = await createLocalBackend(options);
|
|
2495
|
+
}
|
|
2506
2496
|
const renderCache = /* @__PURE__ */ new Map();
|
|
2507
2497
|
const inflight = /* @__PURE__ */ new Map();
|
|
2508
2498
|
const active = /* @__PURE__ */ new Set();
|
|
@@ -2683,7 +2673,7 @@ var createSingingVoices = (ctx, destination, options = {}) => {
|
|
|
2683
2673
|
if (!m?.renderToCache) continue;
|
|
2684
2674
|
let n = 0;
|
|
2685
2675
|
forEachSungNote(track, (note, prevVowel) => {
|
|
2686
|
-
if (n >= count) return;
|
|
2676
|
+
if (n >= count && note.startSec >= 3) return;
|
|
2687
2677
|
n++;
|
|
2688
2678
|
promises.push(
|
|
2689
2679
|
m.renderToCache?.(
|
|
@@ -2716,14 +2706,18 @@ var createSingingVoices = (ctx, destination, options = {}) => {
|
|
|
2716
2706
|
if (opts?.isAudible && !opts.isAudible(track)) continue;
|
|
2717
2707
|
const t0 = anchorTime + note.startSec;
|
|
2718
2708
|
if (model.renderToCache && model.scheduleCached) {
|
|
2719
|
-
const
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2709
|
+
const renderToCache = model.renderToCache;
|
|
2710
|
+
const scheduleCached = model.scheduleCached;
|
|
2711
|
+
void (async () => {
|
|
2712
|
+
const key = await renderToCache(
|
|
2713
|
+
note.syllable,
|
|
2714
|
+
prevVowel,
|
|
2715
|
+
note.pitch,
|
|
2716
|
+
note.durationSec * 1e3
|
|
2717
|
+
);
|
|
2718
|
+
if (session !== streamSession) return;
|
|
2719
|
+
if (key) scheduleCached(key, t0, peak, track.pan);
|
|
2720
|
+
})();
|
|
2727
2721
|
} else {
|
|
2728
2722
|
const when = t0 - ctx.currentTime;
|
|
2729
2723
|
model(note.syllable, {
|
|
@@ -4017,6 +4011,110 @@ var isChordHeavyTrack = (notes, threshold = 0.6) => {
|
|
|
4017
4011
|
return chordNotes / notes.length >= threshold;
|
|
4018
4012
|
};
|
|
4019
4013
|
|
|
4014
|
+
// src/mml-info.ts
|
|
4015
|
+
var MML_INFO_HTML = `
|
|
4016
|
+
<div class="dtm-modal-body-content">
|
|
4017
|
+
<h4>1. \u97F3\u7B26\u3068\u4F11\u7B26</h4>
|
|
4018
|
+
<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>
|
|
4019
|
+
<ul>
|
|
4020
|
+
<li>\u534A\u97F3\u4E0A\u3052\u308B: <code>c#</code> \u307E\u305F\u306F <code>c+</code></li>
|
|
4021
|
+
<li>\u534A\u97F3\u4E0B\u3052\u308B: <code>d-</code></li>
|
|
4022
|
+
<li>\u4F11\u7B26: <code>r</code></li>
|
|
4023
|
+
</ul>
|
|
4024
|
+
|
|
4025
|
+
<h4>2. \u97F3\u306E\u9577\u3055</h4>
|
|
4026
|
+
<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>
|
|
4027
|
+
<ul>
|
|
4028
|
+
<li><code>c4</code> : 4\u5206\u97F3\u7B26\u306E\u30C9</li>
|
|
4029
|
+
<li><code>r8</code> : 8\u5206\u4F11\u7B26</li>
|
|
4030
|
+
<li><code>c4.</code> : \u4ED8\u70B94\u5206\u97F3\u7B26\u306E\u30C9\uFF08\u9577\u3055\u30921.5\u500D\u306B\uFF09</li>
|
|
4031
|
+
<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>
|
|
4032
|
+
</ul>
|
|
4033
|
+
|
|
4034
|
+
<h4>3. \u30AA\u30AF\u30BF\u30FC\u30D6\uFF08\u97F3\u306E\u9AD8\u3055\uFF09</h4>
|
|
4035
|
+
<ul>
|
|
4036
|
+
<li><code>o4</code>, <code>o5</code> : \u9AD8\u3055\u3092\u76F4\u63A5\u6307\u5B9A\uFF08\u3075\u3064\u3046\u306F o4 \u304B o5\uFF09</li>
|
|
4037
|
+
<li><code>></code> : 1\u30AA\u30AF\u30BF\u30FC\u30D6\u4E0A\u3052\u308B</li>
|
|
4038
|
+
<li><code><</code> : 1\u30AA\u30AF\u30BF\u30FC\u30D6\u4E0B\u3052\u308B</li>
|
|
4039
|
+
</ul>
|
|
4040
|
+
|
|
4041
|
+
<h4>4. \u30C6\u30F3\u30DD</h4>
|
|
4042
|
+
<ul>
|
|
4043
|
+
<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>
|
|
4044
|
+
</ul>
|
|
4045
|
+
|
|
4046
|
+
<h4>5. \u548C\u97F3</h4>
|
|
4047
|
+
<p>\u97F3\u7B26\u3092 <code>[</code> \u3068 <code>]</code> \u3067\u56F2\u3080\u3068\u540C\u6642\u306B\u767A\u97F3\u3057\u307E\u3059\u3002</p>
|
|
4048
|
+
<pre>\u4F8B: [ceg]4 \uFF08\u30C9\u30FB\u30DF\u30FB\u30BD\u30924\u5206\u97F3\u7B26\u3067\u540C\u6642\u306B\u767A\u97F3\uFF09</pre>
|
|
4049
|
+
|
|
4050
|
+
<h4>6. \u30C8\u30E9\u30C3\u30AF\u306E\u533A\u5207\u308A</h4>
|
|
4051
|
+
<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>
|
|
4052
|
+
<ul>
|
|
4053
|
+
<li><code>@0</code>: \u30E1\u30ED\u30C7\u30A3</li>
|
|
4054
|
+
<li><code>@1</code>: \u30B5\u30D6\u30E1\u30ED</li>
|
|
4055
|
+
<li><code>@2</code>: \u30D9\u30FC\u30B9</li>
|
|
4056
|
+
<li><code>@3</code>: \u4F34\u594F</li>
|
|
4057
|
+
</ul>
|
|
4058
|
+
|
|
4059
|
+
<h4>7. \u6B4C\u58F0\u30FB\u6B4C\u8A5E\u5165\u529B</h4>
|
|
4060
|
+
<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>
|
|
4061
|
+
<pre>\u4F8B: @@0 tsukuyomi \u3069\u3093\u3050\u308A\u3053\u308D\u3053\u308D\u3069\u3093\u3050\u308A\u3053</pre>
|
|
4062
|
+
<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>
|
|
4063
|
+
|
|
4064
|
+
<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>
|
|
4065
|
+
|
|
4066
|
+
<!-- \u30B5\u30F3\u30D7\u30EB1 -->
|
|
4067
|
+
<div class="dtm-modal-sample-box">
|
|
4068
|
+
<div class="dtm-modal-sample-header">
|
|
4069
|
+
<span class="dtm-modal-sample-tag">1. \u57FA\u672C\u306E\u30E1\u30ED\u30C7\u30A3</span>
|
|
4070
|
+
<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>
|
|
4071
|
+
</div>
|
|
4072
|
+
<pre style="margin: 0; padding: 6px;">@0 t120 l8 o5 c d e f g a b > c</pre>
|
|
4073
|
+
<div class="dtm-modal-sample-desc">
|
|
4074
|
+
\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
|
|
4075
|
+
</div>
|
|
4076
|
+
<div style="margin-top: 8px;">
|
|
4077
|
+
<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>
|
|
4078
|
+
</div>
|
|
4079
|
+
<div class="dtm-modal-sample-player-container"></div>
|
|
4080
|
+
</div>
|
|
4081
|
+
|
|
4082
|
+
<!-- \u30B5\u30F3\u30D7\u30EB2 -->
|
|
4083
|
+
<div class="dtm-modal-sample-box">
|
|
4084
|
+
<div class="dtm-modal-sample-header">
|
|
4085
|
+
<span class="dtm-modal-sample-tag">2. \u8907\u6570\u30C8\u30E9\u30C3\u30AF\u3068\u548C\u97F3</span>
|
|
4086
|
+
<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>
|
|
4087
|
+
</div>
|
|
4088
|
+
<pre style="margin: 0; padding: 6px;">@0 t120 o5 c e g2 ;
|
|
4089
|
+
@3 o4 [ceg]2 [ceg]2</pre>
|
|
4090
|
+
<div class="dtm-modal-sample-desc">
|
|
4091
|
+
; \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
|
|
4092
|
+
</div>
|
|
4093
|
+
<div style="margin-top: 8px;">
|
|
4094
|
+
<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>
|
|
4095
|
+
</div>
|
|
4096
|
+
<div class="dtm-modal-sample-player-container"></div>
|
|
4097
|
+
</div>
|
|
4098
|
+
|
|
4099
|
+
<!-- \u30B5\u30F3\u30D7\u30EB3 -->
|
|
4100
|
+
<div class="dtm-modal-sample-box">
|
|
4101
|
+
<div class="dtm-modal-sample-header">
|
|
4102
|
+
<span class="dtm-modal-sample-tag">3. \u6B4C\u5531\u4ED8\u304D (\u3069\u3093\u3050\u308A\u3053\u308D\u3053\u308D)</span>
|
|
4103
|
+
<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>
|
|
4104
|
+
</div>
|
|
4105
|
+
<pre style="margin: 0; padding: 6px;">@0 t120 v100 o4g8 g8 e8 e8 f8 e8 d8 c8 g8 g8 e8 e8 d4.;
|
|
4106
|
+
@@0 tsukuyomi \u3069\u3093\u3050\u308A\u3053\u308D\u3053\u308D\u3069\u3093\u3050\u308A\u3053;</pre>
|
|
4107
|
+
<div class="dtm-modal-sample-desc">
|
|
4108
|
+
@@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
|
|
4109
|
+
</div>
|
|
4110
|
+
<div style="margin-top: 8px;">
|
|
4111
|
+
<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>
|
|
4112
|
+
</div>
|
|
4113
|
+
<div class="dtm-modal-sample-player-container"></div>
|
|
4114
|
+
</div>
|
|
4115
|
+
</div>
|
|
4116
|
+
`;
|
|
4117
|
+
|
|
4020
4118
|
// src/mml-parser.ts
|
|
4021
4119
|
var PITCH_MAP2 = {
|
|
4022
4120
|
c: 0,
|
|
@@ -4028,7 +4126,7 @@ var PITCH_MAP2 = {
|
|
|
4028
4126
|
b: 11
|
|
4029
4127
|
};
|
|
4030
4128
|
var clamp2 = (value, lo, hi) => Math.min(hi, Math.max(lo, value));
|
|
4031
|
-
var META_DIRECTIVE = /#(inst|drum|volume|mode)=([\w-]+)/gi;
|
|
4129
|
+
var META_DIRECTIVE = /#(inst|drum|volume|drumvolume|mode)=([\w-]+)/gi;
|
|
4032
4130
|
var parseMmlMeta = (mml) => {
|
|
4033
4131
|
const meta = {};
|
|
4034
4132
|
for (const m of mml.matchAll(META_DIRECTIVE)) {
|
|
@@ -4038,6 +4136,9 @@ var parseMmlMeta = (mml) => {
|
|
|
4038
4136
|
else if (key === "volume") {
|
|
4039
4137
|
const v = Number.parseInt(m[2], 10);
|
|
4040
4138
|
if (!Number.isNaN(v)) meta.volume = v;
|
|
4139
|
+
} else if (key === "drumvolume") {
|
|
4140
|
+
const dv = Number.parseInt(m[2], 10);
|
|
4141
|
+
if (!Number.isNaN(dv)) meta.drumVolume = dv;
|
|
4041
4142
|
} else if (key === "mode") {
|
|
4042
4143
|
if (m[2] === "simple" || m[2] === "advanced") {
|
|
4043
4144
|
meta.mode = m[2];
|
|
@@ -4052,6 +4153,8 @@ var formatMmlMeta = (meta) => {
|
|
|
4052
4153
|
if (meta.instrument) parts.push(`#inst=${meta.instrument}`);
|
|
4053
4154
|
if (meta.drum) parts.push(`#drum=${meta.drum}`);
|
|
4054
4155
|
if (meta.volume !== void 0) parts.push(`#volume=${meta.volume}`);
|
|
4156
|
+
if (meta.drumVolume !== void 0)
|
|
4157
|
+
parts.push(`#drumvolume=${meta.drumVolume}`);
|
|
4055
4158
|
if (meta.mode) parts.push(`#mode=${meta.mode}`);
|
|
4056
4159
|
return parts.join(" ");
|
|
4057
4160
|
};
|
|
@@ -4639,9 +4742,13 @@ var DAW_CSS = `
|
|
|
4639
4742
|
/* \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
|
|
4640
4743
|
\u30B3\u30F3\u30C8\u30ED\u30FC\u30EB\u30D0\u30FC\uFF08.dtm-controlbar\uFF09\u306B\u3082\u4F9B\u7D66\u3059\u308B\u3002mountPresetSelect /
|
|
4641
4744
|
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
|
|
4642
|
-
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
|
|
4745
|
+
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
|
|
4746
|
+
\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
|
|
4747
|
+
.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 */
|
|
4643
4748
|
.dtm-daw,
|
|
4644
|
-
.dtm-controlbar
|
|
4749
|
+
.dtm-controlbar,
|
|
4750
|
+
.dtm-modal-overlay,
|
|
4751
|
+
.dtm-consent-overlay {
|
|
4645
4752
|
/* PICO-8 16\u8272\u30D1\u30EC\u30C3\u30C8\u3088\u308A */
|
|
4646
4753
|
--c-black: #000000;
|
|
4647
4754
|
--c-navy: #1d2b53;
|
|
@@ -4769,7 +4876,7 @@ var DAW_CSS = `
|
|
|
4769
4876
|
top: 0;
|
|
4770
4877
|
z-index: 20;
|
|
4771
4878
|
display: flex;
|
|
4772
|
-
flex-wrap:
|
|
4879
|
+
flex-wrap: nowrap;
|
|
4773
4880
|
align-items: center;
|
|
4774
4881
|
gap: var(--dtm-gap);
|
|
4775
4882
|
padding: 6px;
|
|
@@ -4779,6 +4886,17 @@ var DAW_CSS = `
|
|
|
4779
4886
|
inset 0 0 0 2px var(--c-black),
|
|
4780
4887
|
0 0 0 2px var(--dtm-success),
|
|
4781
4888
|
4px 4px 0 var(--c-black);
|
|
4889
|
+
overflow-x: auto;
|
|
4890
|
+
scrollbar-width: none;
|
|
4891
|
+
}
|
|
4892
|
+
.dtm-topbar::-webkit-scrollbar {
|
|
4893
|
+
display: none;
|
|
4894
|
+
}
|
|
4895
|
+
.dtm-topbar > * {
|
|
4896
|
+
flex-shrink: 0;
|
|
4897
|
+
}
|
|
4898
|
+
.dtm-topbar > .dtm-grow {
|
|
4899
|
+
flex-shrink: 1;
|
|
4782
4900
|
}
|
|
4783
4901
|
|
|
4784
4902
|
/* PLAY\u30DC\u30BF\u30F3 \u2014 \u30B2\u30FC\u30E0\u306E\u300C\u6C7A\u5B9A\u30DC\u30BF\u30F3\u300D\u7684\u5B58\u5728\u611F */
|
|
@@ -5129,6 +5247,15 @@ var DAW_CSS = `
|
|
|
5129
5247
|
line-height: 1.8;
|
|
5130
5248
|
color: var(--dtm-success);
|
|
5131
5249
|
}
|
|
5250
|
+
.dtm-output-label {
|
|
5251
|
+
font-size: 11px;
|
|
5252
|
+
color: var(--dtm-muted);
|
|
5253
|
+
font-family: var(--dtm-font);
|
|
5254
|
+
margin-top: 10px;
|
|
5255
|
+
}
|
|
5256
|
+
.dtm-output-label:first-of-type {
|
|
5257
|
+
margin-top: 0;
|
|
5258
|
+
}
|
|
5132
5259
|
.dtm-output-row { display: flex; gap: 8px; align-items: flex-start; margin-top: 6px; }
|
|
5133
5260
|
.dtm-output-row pre { flex: 1; }
|
|
5134
5261
|
|
|
@@ -5239,10 +5366,76 @@ var DAW_CSS = `
|
|
|
5239
5366
|
justify-content: center;
|
|
5240
5367
|
padding: 16px;
|
|
5241
5368
|
backdrop-filter: blur(2px);
|
|
5369
|
+
/* 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
|
|
5370
|
+
.dtm-daw \u304B\u3089\u7D99\u627F\u3067\u304D\u306A\u3044\u305F\u3081\u3001\u3053\u3053\u3067\u660E\u793A\u3059\u308B\u3002 */
|
|
5371
|
+
color: var(--dtm-text);
|
|
5372
|
+
font-family: var(--dtm-font);
|
|
5242
5373
|
}
|
|
5243
5374
|
.dtm-modal-overlay[hidden] {
|
|
5244
5375
|
display: none !important;
|
|
5245
5376
|
}
|
|
5377
|
+
|
|
5378
|
+
/* \u2500\u2500\u2500 \u5229\u7528\u898F\u7D04\u540C\u610F\u30AB\u30D0\u30FC \u2500\u2500\u2500 */
|
|
5379
|
+
.dtm-consent-overlay {
|
|
5380
|
+
position: fixed;
|
|
5381
|
+
inset: 0;
|
|
5382
|
+
z-index: 10100;
|
|
5383
|
+
background: rgba(0, 0, 0, 0.6);
|
|
5384
|
+
display: flex;
|
|
5385
|
+
align-items: center;
|
|
5386
|
+
justify-content: center;
|
|
5387
|
+
padding: 16px;
|
|
5388
|
+
backdrop-filter: blur(2px);
|
|
5389
|
+
/* 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 */
|
|
5390
|
+
color: var(--dtm-text);
|
|
5391
|
+
font-family: var(--dtm-font);
|
|
5392
|
+
}
|
|
5393
|
+
.dtm-consent-overlay[hidden] {
|
|
5394
|
+
display: none !important;
|
|
5395
|
+
}
|
|
5396
|
+
.dtm-consent-modal {
|
|
5397
|
+
max-width: 450px;
|
|
5398
|
+
width: 100%;
|
|
5399
|
+
max-height: 85vh;
|
|
5400
|
+
display: flex;
|
|
5401
|
+
flex-direction: column;
|
|
5402
|
+
background: var(--dtm-surface);
|
|
5403
|
+
border: 2px solid var(--c-black);
|
|
5404
|
+
box-shadow:
|
|
5405
|
+
inset 0 0 0 2px var(--c-black),
|
|
5406
|
+
0 0 0 2px var(--dtm-primary),
|
|
5407
|
+
4px 4px 0 var(--c-black);
|
|
5408
|
+
overflow-y: auto;
|
|
5409
|
+
}
|
|
5410
|
+
.dtm-consent-header {
|
|
5411
|
+
background: var(--dtm-deep);
|
|
5412
|
+
color: var(--dtm-text);
|
|
5413
|
+
padding: 8px 12px;
|
|
5414
|
+
border-bottom: 2px solid var(--c-black);
|
|
5415
|
+
font-weight: bold;
|
|
5416
|
+
text-align: center;
|
|
5417
|
+
font-size: 14px;
|
|
5418
|
+
}
|
|
5419
|
+
.dtm-consent-body {
|
|
5420
|
+
padding: 12px 16px;
|
|
5421
|
+
font-size: 13px;
|
|
5422
|
+
line-height: 1.6;
|
|
5423
|
+
}
|
|
5424
|
+
.dtm-consent-body a {
|
|
5425
|
+
color: var(--dtm-primary);
|
|
5426
|
+
text-decoration: underline;
|
|
5427
|
+
}
|
|
5428
|
+
.dtm-consent-body a:hover {
|
|
5429
|
+
color: var(--dtm-accent);
|
|
5430
|
+
}
|
|
5431
|
+
.dtm-consent-footer {
|
|
5432
|
+
padding: 8px;
|
|
5433
|
+
border-top: 2px solid var(--c-black);
|
|
5434
|
+
background: var(--dtm-deep);
|
|
5435
|
+
display: flex;
|
|
5436
|
+
justify-content: center;
|
|
5437
|
+
}
|
|
5438
|
+
|
|
5246
5439
|
.dtm-modal {
|
|
5247
5440
|
max-width: 500px;
|
|
5248
5441
|
width: 100%;
|
|
@@ -5376,18 +5569,19 @@ var DAW_CSS = `
|
|
|
5376
5569
|
}
|
|
5377
5570
|
|
|
5378
5571
|
.dtm-hidden { display: none !important; }
|
|
5379
|
-
/* \u8AAD\u8FBC\u6642\u306E\
|
|
5572
|
+
/* \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 */
|
|
5380
5573
|
.dtm-load-note {
|
|
5381
5574
|
margin: 6px 0 0;
|
|
5382
5575
|
padding: 0 2px;
|
|
5383
5576
|
font-family: var(--dtm-font);
|
|
5384
|
-
font-size:
|
|
5577
|
+
font-size: 11px;
|
|
5385
5578
|
line-height: 1.5;
|
|
5386
5579
|
letter-spacing: .04em;
|
|
5387
|
-
color: var(--dtm-
|
|
5388
|
-
|
|
5580
|
+
color: var(--dtm-warn); /* \u8B66\u544A\u8272\uFF08\u30AA\u30EC\u30F3\u30B8\uFF09 */
|
|
5581
|
+
font-weight: bold;
|
|
5582
|
+
opacity: 1.0;
|
|
5389
5583
|
}
|
|
5390
|
-
.dtm-load-note::before { content: "\
|
|
5584
|
+
.dtm-load-note::before { content: "\u26A0 "; }
|
|
5391
5585
|
.dtm-grow { flex: 1 1 auto; }
|
|
5392
5586
|
.dtm-lyric-icon {
|
|
5393
5587
|
flex: 0 0 auto;
|
|
@@ -5788,6 +5982,7 @@ var STEPS_PER_BEAT3 = 48;
|
|
|
5788
5982
|
var STEPS_PER_BAR = 192;
|
|
5789
5983
|
var DEFAULT_TRACK_COLORS = ["#00e436", "#29adff", "#ff77a8", "#ffec27"];
|
|
5790
5984
|
var activePlayer = null;
|
|
5985
|
+
var agreedModelsInSession = /* @__PURE__ */ new Set();
|
|
5791
5986
|
var LYRIC_MODEL_LABELS = {
|
|
5792
5987
|
klatt: "\u8EFD\u91CF\u30ED\u30DC\u58F0",
|
|
5793
5988
|
...KOE_VOICEBANK_LABELS
|
|
@@ -5904,6 +6099,7 @@ var mountMmlPlayer = (target, mml, options = {}) => {
|
|
|
5904
6099
|
const drumPatternDict = options.drumPatterns ?? DRUM_PATTERNS;
|
|
5905
6100
|
const drumPattern = meta.drum ? drumPatternDict[meta.drum] ?? null : null;
|
|
5906
6101
|
const trackVolume = meta.volume ?? options.volume ?? 100;
|
|
6102
|
+
const drumVolume = meta.drumVolume ?? 80;
|
|
5907
6103
|
const colors = options.trackColors ?? DEFAULT_TRACK_COLORS;
|
|
5908
6104
|
const useSynth = options.synth ?? !options.onPlayNote;
|
|
5909
6105
|
const secondsPerStep = 60 / bpm / STEPS_PER_BEAT3;
|
|
@@ -6043,16 +6239,21 @@ var mountMmlPlayer = (target, mml, options = {}) => {
|
|
|
6043
6239
|
const menuDropdown = doc.createElement("div");
|
|
6044
6240
|
menuDropdown.className = "dtm-player-menu";
|
|
6045
6241
|
menuDropdown.style.display = "none";
|
|
6046
|
-
const
|
|
6047
|
-
|
|
6048
|
-
|
|
6049
|
-
|
|
6050
|
-
|
|
6051
|
-
|
|
6052
|
-
|
|
6053
|
-
|
|
6054
|
-
|
|
6242
|
+
const makeMenuItem = (label) => {
|
|
6243
|
+
const item = doc.createElement("button");
|
|
6244
|
+
item.type = "button";
|
|
6245
|
+
item.className = "dtm-player-menu-item";
|
|
6246
|
+
item.textContent = label;
|
|
6247
|
+
return item;
|
|
6248
|
+
};
|
|
6249
|
+
const showMmlItem = makeMenuItem("MML\u3092\u8868\u793A");
|
|
6250
|
+
const mmlInfoItem = makeMenuItem("MML\u66F8\u5F0F\u3068\u306F");
|
|
6251
|
+
const embedItem = makeMenuItem("\u57CB\u3081\u8FBC\u3080");
|
|
6252
|
+
const copyMmlItem = makeMenuItem("MML\u30B3\u30D4\u30FC");
|
|
6253
|
+
menuDropdown.appendChild(showMmlItem);
|
|
6254
|
+
menuDropdown.appendChild(mmlInfoItem);
|
|
6055
6255
|
menuDropdown.appendChild(embedItem);
|
|
6256
|
+
menuDropdown.appendChild(copyMmlItem);
|
|
6056
6257
|
menuContainer.appendChild(menuDropdown);
|
|
6057
6258
|
mmlHeader.appendChild(menuContainer);
|
|
6058
6259
|
const toggleMenu = (show) => {
|
|
@@ -6075,38 +6276,200 @@ var mountMmlPlayer = (target, mml, options = {}) => {
|
|
|
6075
6276
|
e.stopPropagation();
|
|
6076
6277
|
toggleMenu();
|
|
6077
6278
|
});
|
|
6078
|
-
|
|
6079
|
-
|
|
6080
|
-
|
|
6081
|
-
if (
|
|
6082
|
-
|
|
6083
|
-
|
|
6084
|
-
|
|
6279
|
+
let infoModalEl = null;
|
|
6280
|
+
let modalSamplePlayer = null;
|
|
6281
|
+
const closeInfoModal = () => {
|
|
6282
|
+
if (modalSamplePlayer) {
|
|
6283
|
+
modalSamplePlayer.stop();
|
|
6284
|
+
modalSamplePlayer.destroy();
|
|
6285
|
+
modalSamplePlayer = null;
|
|
6286
|
+
}
|
|
6287
|
+
infoModalEl?.remove();
|
|
6288
|
+
infoModalEl = null;
|
|
6289
|
+
};
|
|
6290
|
+
const openInfoModal = (title) => {
|
|
6291
|
+
closeInfoModal();
|
|
6292
|
+
const overlay = doc.createElement("div");
|
|
6293
|
+
overlay.className = "dtm-modal-overlay";
|
|
6294
|
+
const modal = doc.createElement("div");
|
|
6295
|
+
modal.className = "dtm-win dtm-modal";
|
|
6296
|
+
const header = doc.createElement("div");
|
|
6297
|
+
header.className = "dtm-modal-header";
|
|
6298
|
+
const titleEl = doc.createElement("span");
|
|
6299
|
+
titleEl.className = "dtm-modal-title";
|
|
6300
|
+
titleEl.textContent = title;
|
|
6301
|
+
const closeBtn = doc.createElement("button");
|
|
6302
|
+
closeBtn.type = "button";
|
|
6303
|
+
closeBtn.className = "dtm-modal-close";
|
|
6304
|
+
closeBtn.innerHTML = "×";
|
|
6305
|
+
closeBtn.title = "\u9589\u3058\u308B";
|
|
6306
|
+
header.append(titleEl, closeBtn);
|
|
6307
|
+
const modalBody = doc.createElement("div");
|
|
6308
|
+
modalBody.className = "dtm-modal-body";
|
|
6309
|
+
modal.append(header, modalBody);
|
|
6310
|
+
overlay.appendChild(modal);
|
|
6311
|
+
closeBtn.addEventListener("click", (e) => {
|
|
6312
|
+
e.stopPropagation();
|
|
6313
|
+
closeInfoModal();
|
|
6314
|
+
});
|
|
6315
|
+
overlay.addEventListener("click", (e) => {
|
|
6316
|
+
if (e.target === overlay) closeInfoModal();
|
|
6317
|
+
});
|
|
6318
|
+
doc.body.appendChild(overlay);
|
|
6319
|
+
infoModalEl = overlay;
|
|
6320
|
+
return modalBody;
|
|
6321
|
+
};
|
|
6322
|
+
const appendCopyButton = (parent, text) => {
|
|
6323
|
+
const actions = doc.createElement("div");
|
|
6324
|
+
actions.style.marginTop = "8px";
|
|
6325
|
+
const copyBtn = doc.createElement("button");
|
|
6326
|
+
copyBtn.type = "button";
|
|
6327
|
+
copyBtn.className = "dtm-btn dtm-btn--primary dtm-btn--xs";
|
|
6328
|
+
copyBtn.textContent = "\u{1F4CB} \u30B3\u30D4\u30FC";
|
|
6329
|
+
copyBtn.addEventListener("click", async (e) => {
|
|
6330
|
+
e.stopPropagation();
|
|
6331
|
+
const ok = await copyToClipboard(doc, text);
|
|
6332
|
+
copyBtn.textContent = ok ? "\u2713 \u30B3\u30D4\u30FC\u5B8C\u4E86" : "\u30B3\u30D4\u30FC\u5931\u6557";
|
|
6333
|
+
if (ok) copyBtn.classList.add("dtm-btn--success");
|
|
6334
|
+
setTimeout(() => {
|
|
6335
|
+
copyBtn.textContent = "\u{1F4CB} \u30B3\u30D4\u30FC";
|
|
6336
|
+
copyBtn.classList.remove("dtm-btn--success");
|
|
6337
|
+
}, 1200);
|
|
6338
|
+
});
|
|
6339
|
+
actions.appendChild(copyBtn);
|
|
6340
|
+
parent.appendChild(actions);
|
|
6341
|
+
};
|
|
6342
|
+
const wireSampleButtons = (modalBody) => {
|
|
6343
|
+
const copyBtns = modalBody.querySelectorAll(".dtm-modal-sample-copy-btn");
|
|
6344
|
+
for (const btn of copyBtns) {
|
|
6345
|
+
const el = btn;
|
|
6346
|
+
el.addEventListener("click", async (e) => {
|
|
6347
|
+
e.stopPropagation();
|
|
6348
|
+
const sampleMml = el.getAttribute("data-mml") ?? "";
|
|
6349
|
+
const original = el.textContent;
|
|
6350
|
+
const ok = await copyToClipboard(doc, sampleMml);
|
|
6351
|
+
el.textContent = ok ? "\u2713 \u30B3\u30D4\u30FC\u5B8C\u4E86" : "\u30B3\u30D4\u30FC\u5931\u6557";
|
|
6352
|
+
if (ok) el.classList.add("dtm-btn--success");
|
|
6353
|
+
setTimeout(() => {
|
|
6354
|
+
el.textContent = original;
|
|
6355
|
+
el.classList.remove("dtm-btn--success");
|
|
6356
|
+
}, 1200);
|
|
6357
|
+
});
|
|
6085
6358
|
}
|
|
6086
|
-
|
|
6087
|
-
|
|
6088
|
-
|
|
6359
|
+
let activeSampleBtn = null;
|
|
6360
|
+
const resetSampleBtn = (b) => {
|
|
6361
|
+
if (!b) return;
|
|
6362
|
+
b.textContent = "\u25B6 \u8A66\u8074";
|
|
6363
|
+
b.classList.remove("dtm-btn--danger");
|
|
6364
|
+
b.classList.add("dtm-btn--primary");
|
|
6365
|
+
};
|
|
6366
|
+
const markPlaying = (b) => {
|
|
6367
|
+
b.textContent = "\u25A0 \u505C\u6B62";
|
|
6368
|
+
b.classList.remove("dtm-btn--primary");
|
|
6369
|
+
b.classList.add("dtm-btn--danger");
|
|
6370
|
+
};
|
|
6371
|
+
const playBtns = modalBody.querySelectorAll(".dtm-modal-sample-play-btn");
|
|
6372
|
+
for (const btn of playBtns) {
|
|
6373
|
+
const el = btn;
|
|
6374
|
+
el.addEventListener("click", (e) => {
|
|
6375
|
+
e.stopPropagation();
|
|
6376
|
+
const sampleMml = el.getAttribute("data-mml") ?? "";
|
|
6377
|
+
if (activeSampleBtn === el && modalSamplePlayer) {
|
|
6378
|
+
if (modalSamplePlayer.isPlaying()) {
|
|
6379
|
+
modalSamplePlayer.stop();
|
|
6380
|
+
} else {
|
|
6381
|
+
modalSamplePlayer.play();
|
|
6382
|
+
markPlaying(el);
|
|
6383
|
+
}
|
|
6384
|
+
return;
|
|
6385
|
+
}
|
|
6386
|
+
if (modalSamplePlayer) {
|
|
6387
|
+
modalSamplePlayer.stop();
|
|
6388
|
+
modalSamplePlayer.destroy();
|
|
6389
|
+
modalSamplePlayer = null;
|
|
6390
|
+
}
|
|
6391
|
+
resetSampleBtn(activeSampleBtn);
|
|
6392
|
+
activeSampleBtn = el;
|
|
6393
|
+
const sampleBox = el.closest(".dtm-modal-sample-box");
|
|
6394
|
+
const container = sampleBox?.querySelector(
|
|
6395
|
+
".dtm-modal-sample-player-container"
|
|
6396
|
+
);
|
|
6397
|
+
if (!container) return;
|
|
6398
|
+
container.innerHTML = "";
|
|
6399
|
+
modalSamplePlayer = mountMmlPlayer(container, sampleMml, {
|
|
6400
|
+
onPlayNote: options.onPlayNote,
|
|
6401
|
+
onPlayDrum: options.onPlayDrum,
|
|
6402
|
+
onResumeAudio: options.onResumeAudio,
|
|
6403
|
+
getAudioTime: options.getAudioTime,
|
|
6404
|
+
singingVoices: options.singingVoices,
|
|
6405
|
+
drumPatterns: options.drumPatterns,
|
|
6406
|
+
volume: trackVolume,
|
|
6407
|
+
// 解説モーダル内の試聴サンプルは規約同意を要求しない。
|
|
6408
|
+
skipConsent: true,
|
|
6409
|
+
onStop: () => {
|
|
6410
|
+
if (activeSampleBtn === el) resetSampleBtn(el);
|
|
6411
|
+
}
|
|
6412
|
+
});
|
|
6413
|
+
markPlaying(el);
|
|
6414
|
+
modalSamplePlayer.play();
|
|
6415
|
+
});
|
|
6416
|
+
}
|
|
6417
|
+
};
|
|
6418
|
+
showMmlItem.addEventListener("click", (e) => {
|
|
6419
|
+
e.stopPropagation();
|
|
6420
|
+
toggleMenu(false);
|
|
6421
|
+
const modalBody = openInfoModal("MML");
|
|
6422
|
+
const pre = doc.createElement("pre");
|
|
6423
|
+
pre.textContent = mml;
|
|
6424
|
+
pre.style.whiteSpace = "pre-wrap";
|
|
6425
|
+
pre.style.wordBreak = "break-all";
|
|
6426
|
+
modalBody.appendChild(pre);
|
|
6427
|
+
appendCopyButton(modalBody, mml);
|
|
6428
|
+
});
|
|
6429
|
+
mmlInfoItem.addEventListener("click", (e) => {
|
|
6430
|
+
e.stopPropagation();
|
|
6431
|
+
toggleMenu(false);
|
|
6432
|
+
const modalBody = openInfoModal("MML\u306E\u66F8\u304D\u65B9\u89E3\u8AAC");
|
|
6433
|
+
modalBody.innerHTML = MML_INFO_HTML;
|
|
6434
|
+
wireSampleButtons(modalBody);
|
|
6089
6435
|
});
|
|
6090
6436
|
embedItem.addEventListener("click", async (e) => {
|
|
6091
6437
|
e.stopPropagation();
|
|
6092
|
-
|
|
6438
|
+
toggleMenu(false);
|
|
6439
|
+
const modalBody = openInfoModal("\u57CB\u3081\u8FBC\u307F");
|
|
6440
|
+
const loading = doc.createElement("p");
|
|
6441
|
+
loading.textContent = "\u751F\u6210\u4E2D...";
|
|
6442
|
+
modalBody.appendChild(loading);
|
|
6093
6443
|
try {
|
|
6094
6444
|
const embedBase = options.embedUrl ?? "https://onjmin.github.io/dtm/demo/embed.html";
|
|
6095
6445
|
const payload = await encodeMml(mml);
|
|
6096
6446
|
const url2 = `${embedBase}#${payload}`;
|
|
6097
6447
|
const snippet = `<iframe src="${url2}" width="100%" height="260" frameborder="0" loading="lazy" title="@onjmin/dtm player"></iframe>`;
|
|
6098
|
-
|
|
6099
|
-
|
|
6100
|
-
|
|
6101
|
-
|
|
6102
|
-
|
|
6103
|
-
|
|
6448
|
+
if (!modalBody.isConnected) return;
|
|
6449
|
+
loading.remove();
|
|
6450
|
+
const desc = doc.createElement("p");
|
|
6451
|
+
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";
|
|
6452
|
+
const pre = doc.createElement("pre");
|
|
6453
|
+
pre.textContent = snippet;
|
|
6454
|
+
pre.style.whiteSpace = "pre-wrap";
|
|
6455
|
+
pre.style.wordBreak = "break-all";
|
|
6456
|
+
modalBody.append(desc, pre);
|
|
6457
|
+
appendCopyButton(modalBody, snippet);
|
|
6104
6458
|
} catch (err2) {
|
|
6105
6459
|
console.error("[dtm] failed to generate embed snippet", err2);
|
|
6106
|
-
|
|
6460
|
+
if (modalBody.isConnected) loading.textContent = "\u751F\u6210\u306B\u5931\u6557\u3057\u307E\u3057\u305F";
|
|
6461
|
+
}
|
|
6462
|
+
});
|
|
6463
|
+
copyMmlItem.addEventListener("click", async (e) => {
|
|
6464
|
+
e.stopPropagation();
|
|
6465
|
+
const success = await copyToClipboard(doc, mml);
|
|
6466
|
+
if (success) {
|
|
6467
|
+
copyMmlItem.textContent = "\u30B3\u30D4\u30FC\u3057\u307E\u3057\u305F\uFF01";
|
|
6468
|
+
} else {
|
|
6469
|
+
copyMmlItem.textContent = "\u30B3\u30D4\u30FC\u5931\u6557";
|
|
6107
6470
|
}
|
|
6108
6471
|
setTimeout(() => {
|
|
6109
|
-
|
|
6472
|
+
copyMmlItem.textContent = "MML\u30B3\u30D4\u30FC";
|
|
6110
6473
|
}, 2e3);
|
|
6111
6474
|
});
|
|
6112
6475
|
const promotedToImage = /* @__PURE__ */ new Set();
|
|
@@ -6352,6 +6715,77 @@ var mountMmlPlayer = (target, mml, options = {}) => {
|
|
|
6352
6715
|
root.appendChild(termsDiv);
|
|
6353
6716
|
}
|
|
6354
6717
|
target.appendChild(root);
|
|
6718
|
+
let consentOverlayEl = null;
|
|
6719
|
+
const checkConsentAndShow = () => {
|
|
6720
|
+
try {
|
|
6721
|
+
if (options.skipConsent) return;
|
|
6722
|
+
const unagreed = termsModels.filter((model) => {
|
|
6723
|
+
if (agreedModelsInSession.has(model)) return false;
|
|
6724
|
+
try {
|
|
6725
|
+
if (typeof localStorage === "undefined" || !localStorage) return true;
|
|
6726
|
+
return localStorage.getItem(`dtm_agreed_terms_${model}`) !== "true";
|
|
6727
|
+
} catch (e) {
|
|
6728
|
+
console.warn(
|
|
6729
|
+
"[dtm-player] localStorage access denied in consent check",
|
|
6730
|
+
e
|
|
6731
|
+
);
|
|
6732
|
+
return true;
|
|
6733
|
+
}
|
|
6734
|
+
});
|
|
6735
|
+
if (unagreed.length === 0) return;
|
|
6736
|
+
const consentOverlay = doc.createElement("div");
|
|
6737
|
+
consentOverlay.className = "dtm-consent-overlay";
|
|
6738
|
+
const modal = doc.createElement("div");
|
|
6739
|
+
modal.className = "dtm-win dtm-consent-modal";
|
|
6740
|
+
const header = doc.createElement("div");
|
|
6741
|
+
header.className = "dtm-consent-header";
|
|
6742
|
+
header.textContent = "\u5229\u7528\u898F\u7D04\u306E\u78BA\u8A8D";
|
|
6743
|
+
const body2 = doc.createElement("div");
|
|
6744
|
+
body2.className = "dtm-consent-body";
|
|
6745
|
+
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>`;
|
|
6746
|
+
for (const model of unagreed) {
|
|
6747
|
+
const label = KOE_VOICEBANK_LABELS[model] || model;
|
|
6748
|
+
const url2 = KOE_VOICEBANK_TERMS[model];
|
|
6749
|
+
contentHTML += `
|
|
6750
|
+
<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);">
|
|
6751
|
+
<div style="display: flex; align-items: center; gap: 4px; flex-wrap: wrap; font-size: 11px; font-weight: bold; color: var(--dtm-gold);">
|
|
6752
|
+
<span>\u4F7F\u7528\u6642\u306B\u306F</span>
|
|
6753
|
+
<a href="${url2}" target="_blank" rel="noopener noreferrer" style="color: var(--dtm-primary); text-decoration: underline;">${label}UTAU\u97F3\u6E90</a>
|
|
6754
|
+
<span>\u306E\u5229\u7528\u898F\u7D04\u306B\u5F93\u3063\u3066\u304F\u3060\u3055\u3044</span>
|
|
6755
|
+
</div>
|
|
6756
|
+
</div>
|
|
6757
|
+
`;
|
|
6758
|
+
}
|
|
6759
|
+
body2.innerHTML = contentHTML;
|
|
6760
|
+
const footer = doc.createElement("div");
|
|
6761
|
+
footer.className = "dtm-consent-footer";
|
|
6762
|
+
const btn = doc.createElement("button");
|
|
6763
|
+
btn.type = "button";
|
|
6764
|
+
btn.className = "dtm-btn dtm-btn--success";
|
|
6765
|
+
btn.textContent = "\u540C\u610F\u3057\u3066\u5229\u7528\u3059\u308B";
|
|
6766
|
+
btn.onclick = () => {
|
|
6767
|
+
for (const model of unagreed) {
|
|
6768
|
+
try {
|
|
6769
|
+
if (typeof localStorage !== "undefined" && localStorage) {
|
|
6770
|
+
localStorage.setItem(`dtm_agreed_terms_${model}`, "true");
|
|
6771
|
+
}
|
|
6772
|
+
} catch (e) {
|
|
6773
|
+
}
|
|
6774
|
+
agreedModelsInSession.add(model);
|
|
6775
|
+
}
|
|
6776
|
+
consentOverlay.remove();
|
|
6777
|
+
consentOverlayEl = null;
|
|
6778
|
+
};
|
|
6779
|
+
footer.appendChild(btn);
|
|
6780
|
+
modal.append(header, body2, footer);
|
|
6781
|
+
consentOverlay.appendChild(modal);
|
|
6782
|
+
doc.body.appendChild(consentOverlay);
|
|
6783
|
+
consentOverlayEl = consentOverlay;
|
|
6784
|
+
} catch (err2) {
|
|
6785
|
+
console.error("[dtm-player] Error in checkConsentAndShow:", err2);
|
|
6786
|
+
}
|
|
6787
|
+
};
|
|
6788
|
+
checkConsentAndShow();
|
|
6355
6789
|
const autoScroll = (lane, el) => {
|
|
6356
6790
|
if (el.offsetWidth === 0 || lane.clientWidth === 0) return;
|
|
6357
6791
|
const elementCenter = el.offsetLeft + el.offsetWidth / 2;
|
|
@@ -6410,7 +6844,7 @@ var mountMmlPlayer = (target, mml, options = {}) => {
|
|
|
6410
6844
|
if (useSynth) ensureSynth().playNote(e);
|
|
6411
6845
|
},
|
|
6412
6846
|
onPlayDrum: (e) => {
|
|
6413
|
-
const velocity = e.velocity * (trackVolume / 100);
|
|
6847
|
+
const velocity = e.velocity * (drumVolume / 100) * (trackVolume / 100);
|
|
6414
6848
|
options.onPlayDrum?.({ ...e, velocity });
|
|
6415
6849
|
if (useSynth) ensureSynth().playDrum({ ...e, velocity });
|
|
6416
6850
|
},
|
|
@@ -6526,6 +6960,8 @@ var mountMmlPlayer = (target, mml, options = {}) => {
|
|
|
6526
6960
|
hideActiveBalloon();
|
|
6527
6961
|
}
|
|
6528
6962
|
root.remove();
|
|
6963
|
+
consentOverlayEl?.remove();
|
|
6964
|
+
closeInfoModal();
|
|
6529
6965
|
};
|
|
6530
6966
|
const instance = {
|
|
6531
6967
|
play,
|
|
@@ -6567,108 +7003,6 @@ var CHORD_INFO_HTML = `
|
|
|
6567
7003
|
</ul>
|
|
6568
7004
|
</div>
|
|
6569
7005
|
`;
|
|
6570
|
-
var MML_INFO_HTML = `
|
|
6571
|
-
<div class="dtm-modal-body-content">
|
|
6572
|
-
<h4>1. \u97F3\u7B26\u3068\u4F11\u7B26</h4>
|
|
6573
|
-
<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>
|
|
6574
|
-
<ul>
|
|
6575
|
-
<li>\u534A\u97F3\u4E0A\u3052\u308B: <code>c#</code> \u307E\u305F\u306F <code>c+</code></li>
|
|
6576
|
-
<li>\u534A\u97F3\u4E0B\u3052\u308B: <code>d-</code></li>
|
|
6577
|
-
<li>\u4F11\u7B26: <code>r</code></li>
|
|
6578
|
-
</ul>
|
|
6579
|
-
|
|
6580
|
-
<h4>2. \u97F3\u306E\u9577\u3055</h4>
|
|
6581
|
-
<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>
|
|
6582
|
-
<ul>
|
|
6583
|
-
<li><code>c4</code> : 4\u5206\u97F3\u7B26\u306E\u30C9</li>
|
|
6584
|
-
<li><code>r8</code> : 8\u5206\u4F11\u7B26</li>
|
|
6585
|
-
<li><code>c4.</code> : \u4ED8\u70B94\u5206\u97F3\u7B26\u306E\u30C9\uFF08\u9577\u3055\u30921.5\u500D\u306B\uFF09</li>
|
|
6586
|
-
<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>
|
|
6587
|
-
</ul>
|
|
6588
|
-
|
|
6589
|
-
<h4>3. \u30AA\u30AF\u30BF\u30FC\u30D6\uFF08\u97F3\u306E\u9AD8\u3055\uFF09</h4>
|
|
6590
|
-
<ul>
|
|
6591
|
-
<li><code>o4</code>, <code>o5</code> : \u9AD8\u3055\u3092\u76F4\u63A5\u6307\u5B9A\uFF08\u3075\u3064\u3046\u306F o4 \u304B o5\uFF09</li>
|
|
6592
|
-
<li><code>></code> : 1\u30AA\u30AF\u30BF\u30FC\u30D6\u4E0A\u3052\u308B</li>
|
|
6593
|
-
<li><code><</code> : 1\u30AA\u30AF\u30BF\u30FC\u30D6\u4E0B\u3052\u308B</li>
|
|
6594
|
-
</ul>
|
|
6595
|
-
|
|
6596
|
-
<h4>4. \u30C6\u30F3\u30DD</h4>
|
|
6597
|
-
<ul>
|
|
6598
|
-
<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>
|
|
6599
|
-
</ul>
|
|
6600
|
-
|
|
6601
|
-
<h4>5. \u548C\u97F3</h4>
|
|
6602
|
-
<p>\u97F3\u7B26\u3092 <code>[</code> \u3068 <code>]</code> \u3067\u56F2\u3080\u3068\u540C\u6642\u306B\u767A\u97F3\u3057\u307E\u3059\u3002</p>
|
|
6603
|
-
<pre>\u4F8B: [ceg]4 \uFF08\u30C9\u30FB\u30DF\u30FB\u30BD\u30924\u5206\u97F3\u7B26\u3067\u540C\u6642\u306B\u767A\u97F3\uFF09</pre>
|
|
6604
|
-
|
|
6605
|
-
<h4>6. \u30C8\u30E9\u30C3\u30AF\u306E\u533A\u5207\u308A</h4>
|
|
6606
|
-
<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>
|
|
6607
|
-
<ul>
|
|
6608
|
-
<li><code>@0</code>: \u30E1\u30ED\u30C7\u30A3</li>
|
|
6609
|
-
<li><code>@1</code>: \u30B5\u30D6\u30E1\u30ED</li>
|
|
6610
|
-
<li><code>@2</code>: \u30D9\u30FC\u30B9</li>
|
|
6611
|
-
<li><code>@3</code>: \u4F34\u594F</li>
|
|
6612
|
-
</ul>
|
|
6613
|
-
|
|
6614
|
-
<h4>7. \u6B4C\u58F0\u30FB\u6B4C\u8A5E\u5165\u529B</h4>
|
|
6615
|
-
<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>
|
|
6616
|
-
<pre>\u4F8B: @@0 tsukuyomi \u3069\u3093\u3050\u308A\u3053\u308D\u3053\u308D\u3069\u3093\u3050\u308A\u3053</pre>
|
|
6617
|
-
<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>
|
|
6618
|
-
|
|
6619
|
-
<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>
|
|
6620
|
-
|
|
6621
|
-
<!-- \u30B5\u30F3\u30D7\u30EB1 -->
|
|
6622
|
-
<div class="dtm-modal-sample-box">
|
|
6623
|
-
<div class="dtm-modal-sample-header">
|
|
6624
|
-
<span class="dtm-modal-sample-tag">1. \u57FA\u672C\u306E\u30E1\u30ED\u30C7\u30A3</span>
|
|
6625
|
-
<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>
|
|
6626
|
-
</div>
|
|
6627
|
-
<pre style="margin: 0; padding: 6px;">@0 t120 l8 o5 c d e f g a b > c</pre>
|
|
6628
|
-
<div class="dtm-modal-sample-desc">
|
|
6629
|
-
\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
|
|
6630
|
-
</div>
|
|
6631
|
-
<div style="margin-top: 8px;">
|
|
6632
|
-
<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>
|
|
6633
|
-
</div>
|
|
6634
|
-
<div class="dtm-modal-sample-player-container"></div>
|
|
6635
|
-
</div>
|
|
6636
|
-
|
|
6637
|
-
<!-- \u30B5\u30F3\u30D7\u30EB2 -->
|
|
6638
|
-
<div class="dtm-modal-sample-box">
|
|
6639
|
-
<div class="dtm-modal-sample-header">
|
|
6640
|
-
<span class="dtm-modal-sample-tag">2. \u8907\u6570\u30C8\u30E9\u30C3\u30AF\u3068\u548C\u97F3</span>
|
|
6641
|
-
<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>
|
|
6642
|
-
</div>
|
|
6643
|
-
<pre style="margin: 0; padding: 6px;">@0 t120 o5 c e g2 ;
|
|
6644
|
-
@3 o4 [ceg]2 [ceg]2</pre>
|
|
6645
|
-
<div class="dtm-modal-sample-desc">
|
|
6646
|
-
; \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
|
|
6647
|
-
</div>
|
|
6648
|
-
<div style="margin-top: 8px;">
|
|
6649
|
-
<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>
|
|
6650
|
-
</div>
|
|
6651
|
-
<div class="dtm-modal-sample-player-container"></div>
|
|
6652
|
-
</div>
|
|
6653
|
-
|
|
6654
|
-
<!-- \u30B5\u30F3\u30D7\u30EB3 -->
|
|
6655
|
-
<div class="dtm-modal-sample-box">
|
|
6656
|
-
<div class="dtm-modal-sample-header">
|
|
6657
|
-
<span class="dtm-modal-sample-tag">3. \u6B4C\u5531\u4ED8\u304D (\u3069\u3093\u3050\u308A\u3053\u308D\u3053\u308D)</span>
|
|
6658
|
-
<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>
|
|
6659
|
-
</div>
|
|
6660
|
-
<pre style="margin: 0; padding: 6px;">@0 t120 v100 o4g8 g8 e8 e8 f8 e8 d8 c8 g8 g8 e8 e8 d4.;
|
|
6661
|
-
@@0 tsukuyomi \u3069\u3093\u3050\u308A\u3053\u308D\u3053\u308D\u3069\u3093\u3050\u308A\u3053;</pre>
|
|
6662
|
-
<div class="dtm-modal-sample-desc">
|
|
6663
|
-
@@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
|
|
6664
|
-
</div>
|
|
6665
|
-
<div style="margin-top: 8px;">
|
|
6666
|
-
<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>
|
|
6667
|
-
</div>
|
|
6668
|
-
<div class="dtm-modal-sample-player-container"></div>
|
|
6669
|
-
</div>
|
|
6670
|
-
</div>
|
|
6671
|
-
`;
|
|
6672
7006
|
var MIDI_INFO_HTML = `
|
|
6673
7007
|
<div class="dtm-modal-body-content">
|
|
6674
7008
|
<h4>1. MIDI\u30D5\u30A1\u30A4\u30EB\u3068\u306F</h4>
|
|
@@ -7612,7 +7946,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
7612
7946
|
};
|
|
7613
7947
|
const updateTransport = () => {
|
|
7614
7948
|
const playing = playbackState === "playing";
|
|
7615
|
-
const label = playing ? "\
|
|
7949
|
+
const label = playing ? "\u505C\u6B62" : playbackState === "paused" ? "\u518D\u958B" : "\u8A66\u8074";
|
|
7616
7950
|
refs.playBtn.innerHTML = `${icon(playing ? "pause" : "play")}<span>${label}</span>`;
|
|
7617
7951
|
refs.playBtn.classList.toggle("dtm-play--stop", playing);
|
|
7618
7952
|
};
|
|
@@ -7880,6 +8214,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
7880
8214
|
instrument: currentInstrument || void 0,
|
|
7881
8215
|
drum: currentDrumPattern !== "none" ? currentDrumPattern : void 0,
|
|
7882
8216
|
volume: masterVolume,
|
|
8217
|
+
drumVolume,
|
|
7883
8218
|
mode
|
|
7884
8219
|
});
|
|
7885
8220
|
if (refs.decomposeChordToggle.checked) {
|
|
@@ -8031,6 +8366,11 @@ var mountDAW = (target, options = {}) => {
|
|
|
8031
8366
|
refs.masterVolume.value = String(meta.volume);
|
|
8032
8367
|
refs.masterVolumeLabel.textContent = `${meta.volume}%`;
|
|
8033
8368
|
}
|
|
8369
|
+
if (meta.drumVolume !== void 0) {
|
|
8370
|
+
drumVolume = meta.drumVolume;
|
|
8371
|
+
refs.drumVolume.value = String(meta.drumVolume);
|
|
8372
|
+
refs.drumVolumeLabel.textContent = `${meta.drumVolume}%`;
|
|
8373
|
+
}
|
|
8034
8374
|
for (const t of trackStates) {
|
|
8035
8375
|
t.lyrics = "";
|
|
8036
8376
|
t.lyricModel = "";
|
|
@@ -8039,8 +8379,8 @@ var mountDAW = (target, options = {}) => {
|
|
|
8039
8379
|
t.vocalPan = 64;
|
|
8040
8380
|
t.vocalOctave = 0;
|
|
8041
8381
|
}
|
|
8042
|
-
lyrics?.forEach((lt
|
|
8043
|
-
const t = trackStates[
|
|
8382
|
+
lyrics?.forEach((lt) => {
|
|
8383
|
+
const t = trackStates[lt.trackId];
|
|
8044
8384
|
if (!t) return;
|
|
8045
8385
|
t.lyrics = lt.syllables.map((s) => s.kana).join("");
|
|
8046
8386
|
t.lyricModel = lt.model;
|
|
@@ -8184,8 +8524,17 @@ var mountDAW = (target, options = {}) => {
|
|
|
8184
8524
|
const wireEvents = () => {
|
|
8185
8525
|
refs.playBtn.addEventListener("click", togglePlay);
|
|
8186
8526
|
refs.playBtn.disabled = false;
|
|
8187
|
-
refs.
|
|
8188
|
-
|
|
8527
|
+
refs.prevBarBtn.addEventListener("click", () => {
|
|
8528
|
+
const targetStep = Math.max(
|
|
8529
|
+
0,
|
|
8530
|
+
Math.floor((getCurrentPlayStep() - 1) / renderConfig.stepsPerBar) * renderConfig.stepsPerBar
|
|
8531
|
+
);
|
|
8532
|
+
jumpTo(targetStep);
|
|
8533
|
+
});
|
|
8534
|
+
refs.nextBarBtn.addEventListener("click", () => {
|
|
8535
|
+
const targetStep = Math.floor(getCurrentPlayStep() / renderConfig.stepsPerBar + 1) * renderConfig.stepsPerBar;
|
|
8536
|
+
jumpTo(targetStep);
|
|
8537
|
+
});
|
|
8189
8538
|
refs.soloCheckbox.addEventListener("change", () => {
|
|
8190
8539
|
isSolo = refs.soloCheckbox.checked;
|
|
8191
8540
|
});
|
|
@@ -8548,6 +8897,20 @@ var mountDAW = (target, options = {}) => {
|
|
|
8548
8897
|
if (playbackState === "paused") return pausedPlayStep;
|
|
8549
8898
|
return playStartStep;
|
|
8550
8899
|
};
|
|
8900
|
+
const jumpTo = async (step) => {
|
|
8901
|
+
const wasPlaying = playbackState === "playing";
|
|
8902
|
+
if (wasPlaying) {
|
|
8903
|
+
sequencer.stop();
|
|
8904
|
+
options.singingVoices?.stopStream();
|
|
8905
|
+
playStartStep = step;
|
|
8906
|
+
pausedPlayStep = step;
|
|
8907
|
+
currentPlayStep = step;
|
|
8908
|
+
playbackState = "paused";
|
|
8909
|
+
await play();
|
|
8910
|
+
} else {
|
|
8911
|
+
forcePauseAt(step);
|
|
8912
|
+
}
|
|
8913
|
+
};
|
|
8551
8914
|
const forcePauseAt = (step) => {
|
|
8552
8915
|
playStartStep = step;
|
|
8553
8916
|
pausedPlayStep = step;
|
|
@@ -8622,6 +8985,7 @@ var playMML = (mml, options = {}) => {
|
|
|
8622
8985
|
const drumPatternDict = options.drumPatterns ?? DRUM_PATTERNS;
|
|
8623
8986
|
const drumPattern = meta.drum ? drumPatternDict[meta.drum] ?? null : null;
|
|
8624
8987
|
let masterVolume = meta.volume ?? options.volume ?? 100;
|
|
8988
|
+
let drumVolume = meta.drumVolume ?? 80;
|
|
8625
8989
|
const trackIndices = [...new Set(placements.map((p) => p.trackIndex))].sort(
|
|
8626
8990
|
(a, b) => a - b
|
|
8627
8991
|
);
|
|
@@ -8658,7 +9022,7 @@ var playMML = (mml, options = {}) => {
|
|
|
8658
9022
|
synth?.playNote(e);
|
|
8659
9023
|
},
|
|
8660
9024
|
onPlayDrum: (e) => {
|
|
8661
|
-
const velocity = e.velocity * (masterVolume / 100);
|
|
9025
|
+
const velocity = e.velocity * (drumVolume / 100) * (masterVolume / 100);
|
|
8662
9026
|
options.onPlayDrum?.({ ...e, velocity });
|
|
8663
9027
|
synth?.playDrum({ ...e, velocity });
|
|
8664
9028
|
},
|
|
@@ -9216,7 +9580,6 @@ var importFrom = async (url2, name) => {
|
|
|
9216
9580
|
var createDtmStudio = async (options = {}) => {
|
|
9217
9581
|
const cdn = { ...DEFAULT_CDN, ...options.cdn };
|
|
9218
9582
|
const features = {
|
|
9219
|
-
recorder: true,
|
|
9220
9583
|
midi: true,
|
|
9221
9584
|
chord: true,
|
|
9222
9585
|
presetUI: true,
|
|
@@ -9255,68 +9618,6 @@ var createDtmStudio = async (options = {}) => {
|
|
|
9255
9618
|
const singingVoices = createSingingVoices(audioCtx, masterGain, {
|
|
9256
9619
|
voiceWorkerUrl
|
|
9257
9620
|
});
|
|
9258
|
-
const recorder = features.recorder ? setupRecorder(audioCtx, masterGain, drumGain) : null;
|
|
9259
|
-
const downloadWav = () => {
|
|
9260
|
-
if (!recorder) return;
|
|
9261
|
-
const recordedData = recorder.getRecordedData();
|
|
9262
|
-
const ch = recordedData.length;
|
|
9263
|
-
const len = recordedData[0].length;
|
|
9264
|
-
if (len === 0) return;
|
|
9265
|
-
const bufSize = recordedData[0][0].length;
|
|
9266
|
-
const wave = new Float32Array(ch * len * bufSize);
|
|
9267
|
-
let idx = 0;
|
|
9268
|
-
for (let i = 0; i < len; i++)
|
|
9269
|
-
for (let j = 0; j < bufSize; j++)
|
|
9270
|
-
for (let k = 0; k < ch; k++) wave[idx++] = recordedData[k][i][j];
|
|
9271
|
-
const sampleRate = audioCtx.sampleRate;
|
|
9272
|
-
const channels = 2;
|
|
9273
|
-
const bitRate = 16;
|
|
9274
|
-
const step = bitRate / 8;
|
|
9275
|
-
const blockSize = channels * step;
|
|
9276
|
-
const byteLen = wave.length * step;
|
|
9277
|
-
const view = new DataView(new ArrayBuffer(44 + byteLen));
|
|
9278
|
-
const ws = (off2, s) => {
|
|
9279
|
-
for (let i = 0; i < s.length; i++)
|
|
9280
|
-
view.setUint8(off2 + i, s.charCodeAt(i));
|
|
9281
|
-
};
|
|
9282
|
-
ws(0, "RIFF");
|
|
9283
|
-
view.setUint32(4, 32 + byteLen, true);
|
|
9284
|
-
ws(8, "WAVE");
|
|
9285
|
-
ws(12, "fmt ");
|
|
9286
|
-
view.setUint32(16, 16, true);
|
|
9287
|
-
view.setUint16(20, 1, true);
|
|
9288
|
-
view.setUint16(22, channels, true);
|
|
9289
|
-
view.setUint32(24, sampleRate, true);
|
|
9290
|
-
view.setUint32(28, sampleRate * blockSize, true);
|
|
9291
|
-
view.setUint16(32, blockSize, true);
|
|
9292
|
-
view.setUint16(34, bitRate, true);
|
|
9293
|
-
ws(36, "data");
|
|
9294
|
-
view.setUint32(40, byteLen, true);
|
|
9295
|
-
const clamp4 = (n, a2, b) => Math.max(a2, Math.min(b, n));
|
|
9296
|
-
let off = 44;
|
|
9297
|
-
for (let i = 0; i < wave.length; i++, off += step)
|
|
9298
|
-
view.setInt16(
|
|
9299
|
-
off,
|
|
9300
|
-
clamp4(Math.round(wave[i] * 32768), -32768, 32767),
|
|
9301
|
-
true
|
|
9302
|
-
);
|
|
9303
|
-
const blob2 = new Blob([view], { type: "audio/wav" });
|
|
9304
|
-
const url2 = URL.createObjectURL(blob2);
|
|
9305
|
-
const a = document.createElement("a");
|
|
9306
|
-
a.href = url2;
|
|
9307
|
-
a.download = "record.wav";
|
|
9308
|
-
a.click();
|
|
9309
|
-
URL.revokeObjectURL(url2);
|
|
9310
|
-
};
|
|
9311
|
-
const onToggleRecord = recorder ? () => {
|
|
9312
|
-
if (recorder.isRecording()) {
|
|
9313
|
-
recorder.stopRecording();
|
|
9314
|
-
downloadWav();
|
|
9315
|
-
} else {
|
|
9316
|
-
recorder.clearRecordedData();
|
|
9317
|
-
recorder.startRecording();
|
|
9318
|
-
}
|
|
9319
|
-
} : void 0;
|
|
9320
9621
|
const listReady = new Promise((resolve) => {
|
|
9321
9622
|
SoundFont_list.init();
|
|
9322
9623
|
SoundFont_list.onload(() => resolve());
|
|
@@ -9523,7 +9824,6 @@ var createDtmStudio = async (options = {}) => {
|
|
|
9523
9824
|
onPlayDrum: playDrum,
|
|
9524
9825
|
singingVoices,
|
|
9525
9826
|
parseMidi,
|
|
9526
|
-
onToggleRecord,
|
|
9527
9827
|
onInstrumentChange: handleInstrumentChange,
|
|
9528
9828
|
...dawOverrides
|
|
9529
9829
|
};
|
|
@@ -9814,7 +10114,6 @@ export {
|
|
|
9814
10114
|
playMML,
|
|
9815
10115
|
playSingingMML,
|
|
9816
10116
|
setDrawOffset,
|
|
9817
|
-
setupRecorder,
|
|
9818
10117
|
shiftNotes,
|
|
9819
10118
|
stripLyrics,
|
|
9820
10119
|
stripMmlMeta,
|