@onjmin/dtm 0.1.1 → 0.1.5
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/LICENSE +21 -21
- package/README.md +37 -37
- package/dist/index.d.mts +191 -3
- package/dist/index.d.ts +191 -3
- package/dist/index.js +794 -91
- package/dist/index.mjs +783 -91
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -21,6 +21,13 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
23
|
DAW_CSS: () => DAW_CSS,
|
|
24
|
+
DEFAULT_BPM: () => DEFAULT_BPM,
|
|
25
|
+
DEFAULT_GATE: () => DEFAULT_GATE,
|
|
26
|
+
DEFAULT_PAN: () => DEFAULT_PAN,
|
|
27
|
+
DEFAULT_PLAYBACK_VELOCITY: () => DEFAULT_PLAYBACK_VELOCITY,
|
|
28
|
+
DEFAULT_STEPS_PER_BAR: () => DEFAULT_STEPS_PER_BAR,
|
|
29
|
+
DEFAULT_VELOCITY: () => DEFAULT_VELOCITY,
|
|
30
|
+
DEFAULT_VOCAL_VOLUME: () => DEFAULT_VOCAL_VOLUME,
|
|
24
31
|
DRUM_FONT: () => DRUM_FONT,
|
|
25
32
|
DRUM_KEYS: () => DRUM_KEYS,
|
|
26
33
|
DRUM_PATTERNS: () => DRUM_PATTERNS,
|
|
@@ -28,6 +35,7 @@ __export(index_exports, {
|
|
|
28
35
|
KOE_BASE_URL: () => KOE_BASE_URL,
|
|
29
36
|
KOE_VOICEBANKS: () => KOE_VOICEBANKS,
|
|
30
37
|
KOE_VOICEBANK_LABELS: () => KOE_VOICEBANK_LABELS,
|
|
38
|
+
KOE_VOICEBANK_TERMS: () => KOE_VOICEBANK_TERMS,
|
|
31
39
|
LinkedList: () => LinkedList,
|
|
32
40
|
MAX_VOCAL_VOLUME: () => MAX_VOCAL_VOLUME,
|
|
33
41
|
MMLCore: () => MMLCore,
|
|
@@ -35,6 +43,7 @@ __export(index_exports, {
|
|
|
35
43
|
PREWARM_NOTES: () => PREWARM_NOTES,
|
|
36
44
|
TRACKS_ADVANCED: () => TRACKS_ADVANCED,
|
|
37
45
|
TRACKS_SIMPLE: () => TRACKS_SIMPLE,
|
|
46
|
+
VOICE_IMAGE_KEY: () => VOICE_IMAGE_KEY,
|
|
38
47
|
analyzeMidiTracks: () => analyzeMidiTracks,
|
|
39
48
|
applyHarmonicFilter: () => applyHarmonicFilter,
|
|
40
49
|
applyMonophonic: () => applyMonophonic,
|
|
@@ -42,6 +51,7 @@ __export(index_exports, {
|
|
|
42
51
|
buildNameToKeyMapping: () => buildNameToKeyMapping,
|
|
43
52
|
collectPitchTokens: () => collectPitchTokens,
|
|
44
53
|
createAudioContext: () => createAudioContext,
|
|
54
|
+
createDtmStudio: () => createDtmStudio,
|
|
45
55
|
createKlattVoice: () => createKlattVoice,
|
|
46
56
|
createKoeVoice: () => createKoeVoice,
|
|
47
57
|
createLyricsConductor: () => createLyricsConductor,
|
|
@@ -379,7 +389,10 @@ var buildUI = (target, options) => {
|
|
|
379
389
|
<div class="dtm-tracks" data-dtm="track-tabs"></div>
|
|
380
390
|
|
|
381
391
|
<div class="dtm-roll-wrap">
|
|
382
|
-
<div class="dtm-roll" data-dtm="roll"
|
|
392
|
+
<div class="dtm-roll" data-dtm="roll">
|
|
393
|
+
<div data-dtm="wrapper" style="position:absolute;inset:0;"></div>
|
|
394
|
+
<div class="dtm-overlay" data-dtm="overlay" hidden><div class="dtm-spinner"></div></div>
|
|
395
|
+
</div>
|
|
383
396
|
<div class="dtm-vscroll" data-dtm="vscroll"><div class="dtm-vscroll-thumb" data-dtm="vscroll-thumb"></div></div>
|
|
384
397
|
</div>
|
|
385
398
|
<div class="dtm-hscroll" data-dtm="hscroll"><div class="dtm-hscroll-thumb" data-dtm="hscroll-thumb"></div></div>
|
|
@@ -512,8 +525,6 @@ var buildUI = (target, options) => {
|
|
|
512
525
|
</div>
|
|
513
526
|
</div>
|
|
514
527
|
</details>
|
|
515
|
-
|
|
516
|
-
<div class="dtm-overlay" data-dtm="overlay" hidden><div class="dtm-spinner"></div></div>
|
|
517
528
|
</div>`;
|
|
518
529
|
const root = q(target, '[data-dtm="root"]');
|
|
519
530
|
const sel = (name) => q(root, `[data-dtm="${name}"]`);
|
|
@@ -1000,6 +1011,15 @@ var Worldline = class _Worldline {
|
|
|
1000
1011
|
}
|
|
1001
1012
|
};
|
|
1002
1013
|
|
|
1014
|
+
// src/types.ts
|
|
1015
|
+
var DEFAULT_VOCAL_VOLUME = 200;
|
|
1016
|
+
var DEFAULT_BPM = 120;
|
|
1017
|
+
var DEFAULT_GATE = 100;
|
|
1018
|
+
var DEFAULT_PAN = 64;
|
|
1019
|
+
var DEFAULT_VELOCITY = 100;
|
|
1020
|
+
var DEFAULT_PLAYBACK_VELOCITY = 127;
|
|
1021
|
+
var DEFAULT_STEPS_PER_BAR = 192;
|
|
1022
|
+
|
|
1003
1023
|
// src/lyrics.ts
|
|
1004
1024
|
var kanaTable = {
|
|
1005
1025
|
\u3042: ["", "a"],
|
|
@@ -1170,9 +1190,10 @@ var parseLyrics = (mml) => {
|
|
|
1170
1190
|
const trackId = Number.parseInt(m[1], 10);
|
|
1171
1191
|
const tokens = m[2].trim().split(/\s+/);
|
|
1172
1192
|
const modelToken = tokens.shift() ?? "";
|
|
1173
|
-
let volume =
|
|
1193
|
+
let volume = DEFAULT_VOCAL_VOLUME;
|
|
1174
1194
|
let gate = 100;
|
|
1175
1195
|
let pan = 64;
|
|
1196
|
+
let octave = 0;
|
|
1176
1197
|
const colon = modelToken.indexOf(":");
|
|
1177
1198
|
const model = (colon === -1 ? modelToken : modelToken.slice(0, colon)).toLowerCase();
|
|
1178
1199
|
if (colon !== -1) {
|
|
@@ -1184,12 +1205,15 @@ var parseLyrics = (mml) => {
|
|
|
1184
1205
|
const v = /^v(\d+)$/.exec(tokens[0]);
|
|
1185
1206
|
const q2 = /^q(\d+)$/.exec(tokens[0]);
|
|
1186
1207
|
const p = /^p(\d+)$/.exec(tokens[0]);
|
|
1208
|
+
const o = /^o(-?\d+)$/.exec(tokens[0]);
|
|
1187
1209
|
if (v) {
|
|
1188
1210
|
volume = clamp(Number.parseInt(v[1], 10), 0, MAX_VOCAL_VOLUME);
|
|
1189
1211
|
} else if (q2) {
|
|
1190
1212
|
gate = clamp(Number.parseInt(q2[1], 10), 0, 100);
|
|
1191
1213
|
} else if (p) {
|
|
1192
1214
|
pan = clamp(Number.parseInt(p[1], 10), 0, 127);
|
|
1215
|
+
} else if (o) {
|
|
1216
|
+
octave = clamp(Number.parseInt(o[1], 10), -2, 2);
|
|
1193
1217
|
} else {
|
|
1194
1218
|
break;
|
|
1195
1219
|
}
|
|
@@ -1206,6 +1230,7 @@ var parseLyrics = (mml) => {
|
|
|
1206
1230
|
volume,
|
|
1207
1231
|
gate,
|
|
1208
1232
|
pan,
|
|
1233
|
+
octave,
|
|
1209
1234
|
syllables,
|
|
1210
1235
|
metaText: metaTokens.join(" "),
|
|
1211
1236
|
...lineBreaks.length > 0 ? { lineBreaks } : {}
|
|
@@ -1239,9 +1264,9 @@ var createLyricsConductor = (lyrics) => {
|
|
|
1239
1264
|
return {
|
|
1240
1265
|
model: track.model,
|
|
1241
1266
|
syllable,
|
|
1242
|
-
volume: vocalVolumeToGain(track.volume ??
|
|
1243
|
-
gate: (track.gate ??
|
|
1244
|
-
pan: panToStereo(track.pan ??
|
|
1267
|
+
volume: vocalVolumeToGain(track.volume ?? DEFAULT_VOCAL_VOLUME),
|
|
1268
|
+
gate: (track.gate ?? DEFAULT_GATE) / 100,
|
|
1269
|
+
pan: panToStereo(track.pan ?? DEFAULT_PAN)
|
|
1245
1270
|
};
|
|
1246
1271
|
};
|
|
1247
1272
|
const reset = () => pointers.clear();
|
|
@@ -1349,7 +1374,8 @@ var KOE_VOICEBANKS = {
|
|
|
1349
1374
|
tsukuyomi: "\u3064\u304F\u3088\u307F\u3061\u3083\u3093.koe",
|
|
1350
1375
|
rino: "\u6625\u97F3\u30EA\u30CEver0.3.koe",
|
|
1351
1376
|
roze: "\u675F\u97F3\u30ED\u30BCver0.\uFF151(\u591A\u97F3\u968E).koe",
|
|
1352
|
-
|
|
1377
|
+
ruko_male: "\u6B32\u97F3\u30EB\u30B3\u2642\u9023\u7D9A\u97F3Ver.1.03.koe",
|
|
1378
|
+
ruko_female: "\u6B32\u97F3\u30EB\u30B3\u2640\u6B4C\u9023\u7D9A\u97F3\u666E1.00.koe",
|
|
1353
1379
|
teto: "\u91CD\u97F3\u30C6\u30C8\u5358\u72EC\u97F3.koe",
|
|
1354
1380
|
shiyo: "\u9769\u547D\u30B7\u30E8.koe"
|
|
1355
1381
|
};
|
|
@@ -1357,10 +1383,30 @@ var KOE_VOICEBANK_LABELS = {
|
|
|
1357
1383
|
tsukuyomi: "\u3064\u304F\u3088\u307F\u3061\u3083\u3093",
|
|
1358
1384
|
rino: "\u6625\u97F3\u30EA\u30CE",
|
|
1359
1385
|
roze: "\u675F\u97F3\u30ED\u30BC",
|
|
1360
|
-
|
|
1386
|
+
ruko_male: "\u6B32\u97F3\u30EB\u30B3\u2642",
|
|
1387
|
+
ruko_female: "\u6B32\u97F3\u30EB\u30B3\u2640",
|
|
1361
1388
|
teto: "\u91CD\u97F3\u30C6\u30C8",
|
|
1362
1389
|
shiyo: "\u9769\u547D\u30B7\u30E8"
|
|
1363
1390
|
};
|
|
1391
|
+
var VOICE_IMAGE_KEY = {
|
|
1392
|
+
klatt: "puyuyu",
|
|
1393
|
+
tsukuyomi: "tsukuyomi",
|
|
1394
|
+
rino: "rino",
|
|
1395
|
+
roze: "roze",
|
|
1396
|
+
ruko_male: "ruko",
|
|
1397
|
+
ruko_female: "ruko",
|
|
1398
|
+
teto: "teto",
|
|
1399
|
+
shiyo: "shiyo"
|
|
1400
|
+
};
|
|
1401
|
+
var KOE_VOICEBANK_TERMS = {
|
|
1402
|
+
tsukuyomi: "https://tyc.rei-yumesaki.net/material/utau/terms/",
|
|
1403
|
+
rino: "https://hatenakun1.github.io/halunelino/",
|
|
1404
|
+
roze: "https://tabaneroze.ninja-web.net/terms-of-use.html",
|
|
1405
|
+
ruko_male: "https://long-sleeper.net/index.php?id=22",
|
|
1406
|
+
ruko_female: "https://long-sleeper.net/index.php?id=22",
|
|
1407
|
+
teto: "https://kasaneteto.jp/guidelines/voice.html",
|
|
1408
|
+
shiyo: "https://kakumeisiyo.my.canva.site/dagkuyjwycs"
|
|
1409
|
+
};
|
|
1364
1410
|
var koeUrl = (name, base = KOE_BASE_URL) => `${base}/${encodeURIComponent(name)}`;
|
|
1365
1411
|
var DEFAULT_WORLDLINE_SCRIPT = "https://onjmin.github.io/koe/demo/world/worldline.js";
|
|
1366
1412
|
var KOE_SAMPLE_RATE = 48e3;
|
|
@@ -1508,9 +1554,10 @@ var createWorkerBackend = async (workerUrl, options) => {
|
|
|
1508
1554
|
}
|
|
1509
1555
|
}
|
|
1510
1556
|
};
|
|
1511
|
-
worker.onerror = (e) =>
|
|
1512
|
-
|
|
1513
|
-
|
|
1557
|
+
worker.onerror = (e) => {
|
|
1558
|
+
const ev = e;
|
|
1559
|
+
onFail?.(new Error(ev.message || ev.error || `Event: ${ev.type}`));
|
|
1560
|
+
};
|
|
1514
1561
|
await new Promise((resolve, reject) => {
|
|
1515
1562
|
onReady = resolve;
|
|
1516
1563
|
onFail = reject;
|
|
@@ -1686,22 +1733,18 @@ var createSingingVoices = (ctx, destination, options = {}) => {
|
|
|
1686
1733
|
if (inflight) return inflight;
|
|
1687
1734
|
const koe = catalog[m];
|
|
1688
1735
|
if (!koe) return Promise.resolve(null);
|
|
1689
|
-
const p = (async () =>
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
source = await res.blob();
|
|
1697
|
-
}
|
|
1698
|
-
return createKoeVoice(ctx, destination, {
|
|
1699
|
-
koe: source,
|
|
1736
|
+
const p = (async () => (
|
|
1737
|
+
// URL文字列はそのまま渡す。koe側が VoiceBank.load 内で HTTP Range により
|
|
1738
|
+
// マニフェストだけ先読みし、音素PCMは歌う直前にオンデマンド取得する
|
|
1739
|
+
// (= 初回に .koe 全体をDLしない。モバイル初回ロードの待ちを解消)。
|
|
1740
|
+
// Blob/File が直接渡されたケース(ローカル読み込み)はそのまま BlobVoiceSource。
|
|
1741
|
+
createKoeVoice(ctx, destination, {
|
|
1742
|
+
koe,
|
|
1700
1743
|
worldlineScriptUrl: options.worldlineScriptUrl,
|
|
1701
1744
|
lightweight: options.lightweight,
|
|
1702
1745
|
voiceWorkerUrl: options.voiceWorkerUrl
|
|
1703
|
-
})
|
|
1704
|
-
|
|
1746
|
+
})
|
|
1747
|
+
))().then((v) => {
|
|
1705
1748
|
loaded.set(m, v);
|
|
1706
1749
|
return v;
|
|
1707
1750
|
}).catch((err) => {
|
|
@@ -2225,7 +2268,7 @@ var exportMIDI = (options) => {
|
|
|
2225
2268
|
(n.startStep + (n.durationSteps || 1)) * tickPerStep
|
|
2226
2269
|
);
|
|
2227
2270
|
const vel = Math.round(
|
|
2228
|
-
(n.velocity ??
|
|
2271
|
+
(n.velocity ?? DEFAULT_VELOCITY) * (track.volume ?? 100) / 100
|
|
2229
2272
|
);
|
|
2230
2273
|
events.push({ t: startTick, m: [144 | ch & 15, n.pitch, vel] });
|
|
2231
2274
|
events.push({ t: endTick, m: [144 | ch & 15, n.pitch, 0] });
|
|
@@ -2780,7 +2823,7 @@ var MMLCore = class _MMLCore {
|
|
|
2780
2823
|
startStep: step,
|
|
2781
2824
|
durationSteps: options.noteLengthSteps,
|
|
2782
2825
|
pitch,
|
|
2783
|
-
velocity: options.velocity ??
|
|
2826
|
+
velocity: options.velocity ?? DEFAULT_VELOCITY
|
|
2784
2827
|
};
|
|
2785
2828
|
this.notes.push(newNote);
|
|
2786
2829
|
}
|
|
@@ -2955,19 +2998,15 @@ var MMLCore = class _MMLCore {
|
|
|
2955
2998
|
notesByStep.set(n.startStep, list);
|
|
2956
2999
|
}
|
|
2957
3000
|
const sortedSteps = Array.from(notesByStep.keys()).sort((a, b) => a - b);
|
|
3001
|
+
const MIN_STEP = config.stepsPerBar / 64;
|
|
2958
3002
|
const fillRests = (until) => {
|
|
2959
|
-
while (currentCursor
|
|
3003
|
+
while (until - currentCursor >= MIN_STEP) {
|
|
2960
3004
|
const gap = until - currentCursor;
|
|
2961
|
-
if (gap <= 2) {
|
|
2962
|
-
currentCursor = until;
|
|
2963
|
-
break;
|
|
2964
|
-
}
|
|
2965
3005
|
const { dur, steps } = this.findBestFitDuration(gap);
|
|
2966
3006
|
segments.push(`r${dur}`);
|
|
2967
3007
|
currentCursor += steps;
|
|
2968
3008
|
}
|
|
2969
3009
|
};
|
|
2970
|
-
const MIN_STEP = config.stepsPerBar / 64;
|
|
2971
3010
|
for (let i = 0; i < sortedSteps.length; i++) {
|
|
2972
3011
|
const startStep = sortedSteps[i];
|
|
2973
3012
|
const notes = notesByStep.get(startStep);
|
|
@@ -2976,7 +3015,6 @@ var MMLCore = class _MMLCore {
|
|
|
2976
3015
|
const nextStart = sortedSteps[i + 1] ?? endStep;
|
|
2977
3016
|
const physicsLimit = nextStart - currentCursor;
|
|
2978
3017
|
if (physicsLimit < MIN_STEP) {
|
|
2979
|
-
currentCursor = startStep;
|
|
2980
3018
|
continue;
|
|
2981
3019
|
}
|
|
2982
3020
|
const idealDuration = notes[0].durationSteps;
|
|
@@ -3101,7 +3139,7 @@ var formatMmlMeta = (meta) => {
|
|
|
3101
3139
|
return parts.join(" ");
|
|
3102
3140
|
};
|
|
3103
3141
|
var parseMML = (mml, options = {}) => {
|
|
3104
|
-
const stepsPerBar = options.stepsPerBar ??
|
|
3142
|
+
const stepsPerBar = options.stepsPerBar ?? DEFAULT_STEPS_PER_BAR;
|
|
3105
3143
|
const collectTokens = options.collectTokens ?? false;
|
|
3106
3144
|
const collectLyrics = options.collectLyrics ?? false;
|
|
3107
3145
|
const clampTrackCount = options.clampTrackCount;
|
|
@@ -3178,14 +3216,14 @@ var parseMML = (mml, options = {}) => {
|
|
|
3178
3216
|
numStr += body[j];
|
|
3179
3217
|
j++;
|
|
3180
3218
|
}
|
|
3181
|
-
octave = clamp2(Number.parseInt(numStr, 10)
|
|
3219
|
+
octave = numStr ? clamp2(Number.parseInt(numStr, 10), 0, 8) : 4;
|
|
3182
3220
|
pushTok("octave", currentStep, 0, tokStart);
|
|
3183
3221
|
} else if (ch === ">") {
|
|
3184
|
-
octave
|
|
3222
|
+
octave = Math.min(8, octave + 1);
|
|
3185
3223
|
j++;
|
|
3186
3224
|
pushTok("shift", currentStep, 0, tokStart);
|
|
3187
3225
|
} else if (ch === "<") {
|
|
3188
|
-
octave
|
|
3226
|
+
octave = Math.max(0, octave - 1);
|
|
3189
3227
|
j++;
|
|
3190
3228
|
pushTok("shift", currentStep, 0, tokStart);
|
|
3191
3229
|
} else if (ch === "l") {
|
|
@@ -3232,10 +3270,10 @@ var parseMML = (mml, options = {}) => {
|
|
|
3232
3270
|
}
|
|
3233
3271
|
chordNotes.push((octave + 1) * 12 + pitch);
|
|
3234
3272
|
} else if (c === ">") {
|
|
3235
|
-
octave
|
|
3273
|
+
octave = Math.min(8, octave + 1);
|
|
3236
3274
|
j++;
|
|
3237
3275
|
} else if (c === "<") {
|
|
3238
|
-
octave
|
|
3276
|
+
octave = Math.max(0, octave - 1);
|
|
3239
3277
|
j++;
|
|
3240
3278
|
} else if (c === "o") {
|
|
3241
3279
|
j++;
|
|
@@ -3244,7 +3282,7 @@ var parseMML = (mml, options = {}) => {
|
|
|
3244
3282
|
numStr += body[j];
|
|
3245
3283
|
j++;
|
|
3246
3284
|
}
|
|
3247
|
-
octave = clamp2(Number.parseInt(numStr, 10)
|
|
3285
|
+
octave = numStr ? clamp2(Number.parseInt(numStr, 10), 0, 8) : 4;
|
|
3248
3286
|
} else {
|
|
3249
3287
|
j++;
|
|
3250
3288
|
}
|
|
@@ -3319,7 +3357,7 @@ var createSequencer = (options) => {
|
|
|
3319
3357
|
for (const note of track.notes) {
|
|
3320
3358
|
const relativeStart = note.startStep - fromStep;
|
|
3321
3359
|
if (relativeStart < 0) continue;
|
|
3322
|
-
const velocity = note.velocity ??
|
|
3360
|
+
const velocity = note.velocity ?? DEFAULT_PLAYBACK_VELOCITY;
|
|
3323
3361
|
timeline.push({
|
|
3324
3362
|
trackId: track.id,
|
|
3325
3363
|
pitch: note.pitch,
|
|
@@ -3938,6 +3976,13 @@ var DAW_CSS = `
|
|
|
3938
3976
|
|
|
3939
3977
|
.dtm-hidden { display: none !important; }
|
|
3940
3978
|
.dtm-grow { flex: 1 1 auto; }
|
|
3979
|
+
.dtm-lyric-icon {
|
|
3980
|
+
flex: 0 0 auto;
|
|
3981
|
+
width: 20px;
|
|
3982
|
+
height: 20px;
|
|
3983
|
+
border-radius: 50%;
|
|
3984
|
+
object-fit: cover;
|
|
3985
|
+
}
|
|
3941
3986
|
|
|
3942
3987
|
/* \u2500\u2500\u2500 \u5E83\u5E45\u62E1\u5F35 \u2500\u2500\u2500 */
|
|
3943
3988
|
@media (min-width: 768px) {
|
|
@@ -3980,13 +4025,26 @@ var DAW_CSS = `
|
|
|
3980
4025
|
.dtm-player-play:active { transform: translate(2px, 2px); box-shadow: none; }
|
|
3981
4026
|
.dtm-player-play--stop { background: var(--dtm-danger); }
|
|
3982
4027
|
.dtm-player-play:disabled { opacity: 0.4; cursor: default; }
|
|
3983
|
-
.dtm-player-
|
|
3984
|
-
|
|
4028
|
+
.dtm-player-beat-row {
|
|
4029
|
+
display: flex;
|
|
4030
|
+
align-items: center;
|
|
4031
|
+
gap: 4px;
|
|
4032
|
+
}
|
|
4033
|
+
.dtm-player-beat-dot {
|
|
4034
|
+
width: 8px;
|
|
4035
|
+
height: 8px;
|
|
4036
|
+
border-radius: 50%;
|
|
4037
|
+
background: var(--dtm-border2);
|
|
4038
|
+
transition: background 0.06s;
|
|
4039
|
+
}
|
|
4040
|
+
.dtm-player-beat-dot--on { background: var(--dtm-primary); }
|
|
4041
|
+
.dtm-player-bar {
|
|
3985
4042
|
font-family: 'k8x12', monospace;
|
|
3986
|
-
font-size:
|
|
3987
|
-
color: var(--dtm-
|
|
4043
|
+
font-size: 11px;
|
|
4044
|
+
color: var(--dtm-text);
|
|
4045
|
+
min-width: 2em;
|
|
4046
|
+
margin-left: 4px;
|
|
3988
4047
|
}
|
|
3989
|
-
.dtm-player-time { color: var(--dtm-text); min-width: 3em; }
|
|
3990
4048
|
.dtm-player-dots {
|
|
3991
4049
|
margin-left: auto;
|
|
3992
4050
|
display: flex;
|
|
@@ -3994,6 +4052,40 @@ var DAW_CSS = `
|
|
|
3994
4052
|
gap: 6px;
|
|
3995
4053
|
}
|
|
3996
4054
|
.dtm-player-dot { width: 8px; height: 8px; display: inline-block; }
|
|
4055
|
+
.dtm-player-mml-header {
|
|
4056
|
+
margin-left: auto;
|
|
4057
|
+
display: flex;
|
|
4058
|
+
align-items: center;
|
|
4059
|
+
gap: 4px;
|
|
4060
|
+
}
|
|
4061
|
+
.dtm-player-mml-link {
|
|
4062
|
+
font-family: 'k8x12', monospace;
|
|
4063
|
+
font-size: 10px;
|
|
4064
|
+
color: var(--dtm-muted);
|
|
4065
|
+
text-decoration: none;
|
|
4066
|
+
white-space: nowrap;
|
|
4067
|
+
}
|
|
4068
|
+
.dtm-player-mml-link:hover { color: var(--dtm-primary); }
|
|
4069
|
+
.dtm-player-emoji {
|
|
4070
|
+
display: inline-flex;
|
|
4071
|
+
align-items: center;
|
|
4072
|
+
justify-content: center;
|
|
4073
|
+
width: 20px;
|
|
4074
|
+
height: 20px;
|
|
4075
|
+
border-radius: 50%;
|
|
4076
|
+
font-size: 18px;
|
|
4077
|
+
line-height: 1;
|
|
4078
|
+
user-select: none;
|
|
4079
|
+
}
|
|
4080
|
+
@keyframes dtm-emoji-jump {
|
|
4081
|
+
0% { transform: translateY(0); }
|
|
4082
|
+
35% { transform: translateY(-5px); }
|
|
4083
|
+
65% { transform: translateY(-5px); }
|
|
4084
|
+
100% { transform: translateY(0); }
|
|
4085
|
+
}
|
|
4086
|
+
.dtm-player-emoji--jump {
|
|
4087
|
+
animation: dtm-emoji-jump 0.18s ease-out forwards;
|
|
4088
|
+
}
|
|
3997
4089
|
.dtm-player-chip {
|
|
3998
4090
|
font-family: 'k8x12', monospace;
|
|
3999
4091
|
font-size: 9px;
|
|
@@ -4002,6 +4094,12 @@ var DAW_CSS = `
|
|
|
4002
4094
|
padding: 2px 6px;
|
|
4003
4095
|
white-space: nowrap;
|
|
4004
4096
|
}
|
|
4097
|
+
.dtm-player-body {
|
|
4098
|
+
position: relative; /* \u30ED\u30FC\u30C7\u30A3\u30F3\u30B0\u30AA\u30FC\u30D0\u30FC\u30EC\u30A4\u306E\u57FA\u6E96\u3002\u30EC\u30FC\u30F3\u7FA4\u3060\u3051\u3092\u8986\u3046 */
|
|
4099
|
+
display: flex;
|
|
4100
|
+
flex-direction: column;
|
|
4101
|
+
gap: var(--dtm-gap);
|
|
4102
|
+
}
|
|
4005
4103
|
.dtm-player-lane-row {
|
|
4006
4104
|
display: flex;
|
|
4007
4105
|
align-items: stretch;
|
|
@@ -4016,6 +4114,12 @@ var DAW_CSS = `
|
|
|
4016
4114
|
gap: 2px;
|
|
4017
4115
|
padding-top: 4px;
|
|
4018
4116
|
}
|
|
4117
|
+
.dtm-player-lane-label--btn {
|
|
4118
|
+
cursor: pointer;
|
|
4119
|
+
user-select: none;
|
|
4120
|
+
}
|
|
4121
|
+
.dtm-player-lane-label--btn:hover { opacity: 0.7; }
|
|
4122
|
+
.dtm-player-lane-label--muted { opacity: 0.3; }
|
|
4019
4123
|
.dtm-player-lane-no {
|
|
4020
4124
|
font-family: 'k8x12', monospace;
|
|
4021
4125
|
font-size: 9px;
|
|
@@ -4098,6 +4202,38 @@ var showLoadingOverlay = (container) => {
|
|
|
4098
4202
|
};
|
|
4099
4203
|
};
|
|
4100
4204
|
|
|
4205
|
+
// assets/puyuyu.png
|
|
4206
|
+
var puyuyu_default = "data:image/png;base64,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";
|
|
4207
|
+
|
|
4208
|
+
// assets/rino.png
|
|
4209
|
+
var rino_default = "data:image/png;base64,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";
|
|
4210
|
+
|
|
4211
|
+
// assets/roze.png
|
|
4212
|
+
var roze_default = "data:image/png;base64,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";
|
|
4213
|
+
|
|
4214
|
+
// assets/ruko.png
|
|
4215
|
+
var ruko_default = "data:image/png;base64,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";
|
|
4216
|
+
|
|
4217
|
+
// assets/shiyo.png
|
|
4218
|
+
var shiyo_default = "data:image/png;base64,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";
|
|
4219
|
+
|
|
4220
|
+
// assets/teto.png
|
|
4221
|
+
var teto_default = "data:image/png;base64,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";
|
|
4222
|
+
|
|
4223
|
+
// assets/tsukuyomi.png
|
|
4224
|
+
var tsukuyomi_default = "data:image/png;base64,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";
|
|
4225
|
+
|
|
4226
|
+
// src/voice-images.ts
|
|
4227
|
+
var VOICE_IMAGES = {
|
|
4228
|
+
puyuyu: puyuyu_default,
|
|
4229
|
+
rino: rino_default,
|
|
4230
|
+
roze: roze_default,
|
|
4231
|
+
ruko: ruko_default,
|
|
4232
|
+
shiyo: shiyo_default,
|
|
4233
|
+
teto: teto_default,
|
|
4234
|
+
tsukuyomi: tsukuyomi_default
|
|
4235
|
+
};
|
|
4236
|
+
|
|
4101
4237
|
// src/daw.ts
|
|
4102
4238
|
var BASE_STEP_WIDTH = 0.5;
|
|
4103
4239
|
var BASE_KEY_HEIGHT = 15;
|
|
@@ -4264,7 +4400,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
4264
4400
|
tracks: trackConfigs,
|
|
4265
4401
|
drumPatternNames: Object.keys(drumPatterns),
|
|
4266
4402
|
defaultDrumPattern: drumPatterns.dance ? "dance" : Object.keys(drumPatterns)[0] ?? "none",
|
|
4267
|
-
defaultBpm: options.defaultBpm ??
|
|
4403
|
+
defaultBpm: options.defaultBpm ?? DEFAULT_BPM,
|
|
4268
4404
|
showMidi,
|
|
4269
4405
|
showChord
|
|
4270
4406
|
});
|
|
@@ -4279,7 +4415,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
4279
4415
|
const leftPaddingSteps = renderConfig.stepsPerBar * 16;
|
|
4280
4416
|
let zoomX = 100;
|
|
4281
4417
|
let zoomY = 100;
|
|
4282
|
-
let bpm = options.defaultBpm ??
|
|
4418
|
+
let bpm = options.defaultBpm ?? DEFAULT_BPM;
|
|
4283
4419
|
let masterVolume = 50;
|
|
4284
4420
|
let drumVolume = 80;
|
|
4285
4421
|
let currentDrumPattern = refs.drumSelect.value;
|
|
@@ -4324,9 +4460,10 @@ var mountDAW = (target, options = {}) => {
|
|
|
4324
4460
|
lyrics: "",
|
|
4325
4461
|
lyricModel: "",
|
|
4326
4462
|
// 既定は「なし」(歌わない)
|
|
4327
|
-
vocalVolume:
|
|
4463
|
+
vocalVolume: DEFAULT_VOCAL_VOLUME,
|
|
4328
4464
|
vocalGate: 100,
|
|
4329
|
-
vocalPan: 64
|
|
4465
|
+
vocalPan: 64,
|
|
4466
|
+
vocalOctave: 0
|
|
4330
4467
|
}));
|
|
4331
4468
|
};
|
|
4332
4469
|
const buildLyricsMap = () => {
|
|
@@ -4343,6 +4480,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
4343
4480
|
volume: t.vocalVolume,
|
|
4344
4481
|
gate: t.vocalGate,
|
|
4345
4482
|
pan: t.vocalPan,
|
|
4483
|
+
octave: t.vocalOctave,
|
|
4346
4484
|
syllables
|
|
4347
4485
|
});
|
|
4348
4486
|
});
|
|
@@ -4861,6 +4999,13 @@ var mountDAW = (target, options = {}) => {
|
|
|
4861
4999
|
setDrawOffset(currentOffsetX, currentOffsetY);
|
|
4862
5000
|
redrawAll();
|
|
4863
5001
|
};
|
|
5002
|
+
const getViewState = () => ({
|
|
5003
|
+
zoomX,
|
|
5004
|
+
zoomY,
|
|
5005
|
+
decomposeChord: refs.decomposeChordToggle.checked,
|
|
5006
|
+
ignoreChordHeavy: refs.ignoreChordHeavyToggle.checked
|
|
5007
|
+
});
|
|
5008
|
+
const notifyViewState = () => options.onViewStateChange?.(getViewState());
|
|
4864
5009
|
const dispatchNote = (trackId, pitch, trackVol, velocity, when, duration) => {
|
|
4865
5010
|
const volume = trackVol / 100 * (velocity / 127) * (masterVolume / 100);
|
|
4866
5011
|
options.onPlayNote?.({ trackId, pitch, velocity, volume, when, duration });
|
|
@@ -4920,7 +5065,8 @@ var mountDAW = (target, options = {}) => {
|
|
|
4920
5065
|
const sorted = [...trackState?.core.getNotes() ?? []].sort(
|
|
4921
5066
|
(a, b) => a.startStep - b.startStep
|
|
4922
5067
|
);
|
|
4923
|
-
const gate = (lt.gate ??
|
|
5068
|
+
const gate = (lt.gate ?? DEFAULT_GATE) / 100;
|
|
5069
|
+
const semis = (lt.octave ?? 0) * 12;
|
|
4924
5070
|
const count = Math.min(sorted.length, lt.syllables.length);
|
|
4925
5071
|
const notes = [];
|
|
4926
5072
|
for (let i = 0; i < count; i++) {
|
|
@@ -4928,22 +5074,22 @@ var mountDAW = (target, options = {}) => {
|
|
|
4928
5074
|
if (n.startStep < fromStep) continue;
|
|
4929
5075
|
notes.push({
|
|
4930
5076
|
syllable: lt.syllables[i],
|
|
4931
|
-
pitch: n.pitch,
|
|
5077
|
+
pitch: n.pitch + semis,
|
|
4932
5078
|
startSec: (n.startStep - fromStep) * secondsPerStep,
|
|
4933
5079
|
durationSec: n.durationSteps * secondsPerStep * gate
|
|
4934
5080
|
});
|
|
4935
5081
|
}
|
|
4936
5082
|
return {
|
|
4937
5083
|
model: lt.model,
|
|
4938
|
-
volume: vocalVolumeToGain(lt.volume ??
|
|
4939
|
-
pan: panToStereo(lt.pan ??
|
|
5084
|
+
volume: vocalVolumeToGain(lt.volume ?? DEFAULT_VOCAL_VOLUME) * (masterVolume / 100),
|
|
5085
|
+
pan: panToStereo(lt.pan ?? DEFAULT_PAN),
|
|
4940
5086
|
notes
|
|
4941
5087
|
};
|
|
4942
5088
|
}) : [];
|
|
4943
5089
|
const voices = options.singingVoices;
|
|
4944
5090
|
const streaming = !!voices && streamTracks.some((t) => t.notes.length > 0);
|
|
4945
5091
|
if (streaming && voices) {
|
|
4946
|
-
const overlay = showLoadingOverlay(
|
|
5092
|
+
const overlay = showLoadingOverlay(refs.rollContainer);
|
|
4947
5093
|
try {
|
|
4948
5094
|
await voices.loadModels(streamTracks.map((t) => t.model));
|
|
4949
5095
|
await voices.warm(streamTracks);
|
|
@@ -5036,12 +5182,25 @@ var mountDAW = (target, options = {}) => {
|
|
|
5036
5182
|
<div class="dtm-row">
|
|
5037
5183
|
<span class="dtm-label">\u266A \u6B4C\u8A5E</span>
|
|
5038
5184
|
<select class="dtm-select" data-dtm="lyric-model" aria-label="\u6B4C\u5531\u30E2\u30C7\u30EB"></select>
|
|
5185
|
+
<img class="dtm-lyric-icon dtm-hidden" data-dtm="lyric-icon" width="20" height="20" alt="" draggable="false">
|
|
5186
|
+
<select class="dtm-select" data-dtm="lyric-octave" aria-label="\u30AA\u30AF\u30BF\u30FC\u30D6\uFF08\u97F3\u6E90\u306E\u5F97\u610F\u97F3\u57DF\u306B\u5408\u308F\u305B\u308B\uFF09" title="\u30AA\u30AF\u30BF\u30FC\u30D6">
|
|
5187
|
+
<option value="2">+2 oct</option>
|
|
5188
|
+
<option value="1">+1 oct</option>
|
|
5189
|
+
<option value="0">\xB10 oct</option>
|
|
5190
|
+
<option value="-1">-1 oct</option>
|
|
5191
|
+
<option value="-2">-2 oct</option>
|
|
5192
|
+
</select>
|
|
5039
5193
|
<span class="dtm-label dtm-grow" data-dtm="lyric-count" style="text-align:right"></span>
|
|
5040
5194
|
</div>
|
|
5195
|
+
<div class="dtm-row dtm-hidden" data-dtm="lyric-terms" style="font-size:10px;gap:4px;color:var(--dtm-warn)">
|
|
5196
|
+
<span>\u4F7F\u7528\u6642\u306B\u306F</span>
|
|
5197
|
+
<a data-dtm="lyric-terms-link" target="_blank" rel="noopener" style="color:var(--dtm-primary);text-decoration:underline"></a>
|
|
5198
|
+
<span>\u306E\u5229\u7528\u898F\u7D04\u306B\u5F93\u3063\u3066\u304F\u3060\u3055\u3044</span>
|
|
5199
|
+
</div>
|
|
5041
5200
|
<div class="dtm-row" data-dtm="lyric-body" style="flex-direction:column;align-items:stretch">
|
|
5042
5201
|
<div class="dtm-row">
|
|
5043
5202
|
<span class="dtm-label">\u58F0\u91CF</span>
|
|
5044
|
-
<input type="range" class="dtm-range dtm-grow" data-dtm="lyric-vol" min="0" max="${MAX_VOCAL_VOLUME}" aria-label="\u6B4C\u5531\u306E\u58F0\u91CF\uFF08100=\u7B49\u500D\u3001100\u8D85\u3067\u30D6\u30FC\u30B9\u30C8\u3001\u65E2\
|
|
5203
|
+
<input type="range" class="dtm-range dtm-grow" data-dtm="lyric-vol" min="0" max="${MAX_VOCAL_VOLUME}" aria-label="\u6B4C\u5531\u306E\u58F0\u91CF\uFF08100=\u7B49\u500D\u3001100\u8D85\u3067\u30D6\u30FC\u30B9\u30C8\u3001\u65E2\u5B9A200\uFF09">
|
|
5045
5204
|
<span class="dtm-label" data-dtm="lyric-vol-label"></span>
|
|
5046
5205
|
</div>
|
|
5047
5206
|
<div class="dtm-row">
|
|
@@ -5055,6 +5214,12 @@ var mountDAW = (target, options = {}) => {
|
|
|
5055
5214
|
const lyricModelSel = lyricDiv.querySelector(
|
|
5056
5215
|
'[data-dtm="lyric-model"]'
|
|
5057
5216
|
);
|
|
5217
|
+
const lyricOctaveSel = lyricDiv.querySelector(
|
|
5218
|
+
'[data-dtm="lyric-octave"]'
|
|
5219
|
+
);
|
|
5220
|
+
const lyricIcon = lyricDiv.querySelector(
|
|
5221
|
+
'[data-dtm="lyric-icon"]'
|
|
5222
|
+
);
|
|
5058
5223
|
const lyricBody = lyricDiv.querySelector(
|
|
5059
5224
|
'[data-dtm="lyric-body"]'
|
|
5060
5225
|
);
|
|
@@ -5076,6 +5241,12 @@ var mountDAW = (target, options = {}) => {
|
|
|
5076
5241
|
const lyricPanLabel = lyricDiv.querySelector(
|
|
5077
5242
|
'[data-dtm="lyric-pan-label"]'
|
|
5078
5243
|
);
|
|
5244
|
+
const lyricTerms = lyricDiv.querySelector(
|
|
5245
|
+
'[data-dtm="lyric-terms"]'
|
|
5246
|
+
);
|
|
5247
|
+
const lyricTermsLink = lyricDiv.querySelector(
|
|
5248
|
+
'[data-dtm="lyric-terms-link"]'
|
|
5249
|
+
);
|
|
5079
5250
|
const fmtPan = (pan) => pan === 64 ? "C" : pan < 64 ? `L${64 - pan}` : `R${pan - 64}`;
|
|
5080
5251
|
const addOpt = (value, label) => {
|
|
5081
5252
|
const o = document.createElement("option");
|
|
@@ -5089,6 +5260,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
5089
5260
|
addOpt(active.lyricModel, lyricModelLabel(active.lyricModel));
|
|
5090
5261
|
}
|
|
5091
5262
|
lyricModelSel.value = active.lyricModel;
|
|
5263
|
+
lyricOctaveSel.value = String(active.vocalOctave);
|
|
5092
5264
|
lyricInput.value = active.lyrics;
|
|
5093
5265
|
lyricVol.value = String(active.vocalVolume);
|
|
5094
5266
|
lyricVolLabel.textContent = String(active.vocalVolume);
|
|
@@ -5098,15 +5270,43 @@ var mountDAW = (target, options = {}) => {
|
|
|
5098
5270
|
const n = normalizeLyrics(lyricInput.value).length;
|
|
5099
5271
|
lyricCount.textContent = active.lyricModel && n > 0 ? `${n}\u97F3\u7BC0` : "";
|
|
5100
5272
|
};
|
|
5273
|
+
const syncLyricTerms = () => {
|
|
5274
|
+
const url = active.lyricModel ? KOE_VOICEBANK_TERMS[active.lyricModel] : void 0;
|
|
5275
|
+
if (url) {
|
|
5276
|
+
const label = lyricModelLabel(active.lyricModel);
|
|
5277
|
+
lyricTermsLink.textContent = `${label}UTAU\u97F3\u6E90`;
|
|
5278
|
+
lyricTermsLink.href = url;
|
|
5279
|
+
lyricTerms.classList.remove("dtm-hidden");
|
|
5280
|
+
} else {
|
|
5281
|
+
lyricTerms.classList.add("dtm-hidden");
|
|
5282
|
+
}
|
|
5283
|
+
};
|
|
5284
|
+
const syncLyricIcon = () => {
|
|
5285
|
+
const imgKey = active.lyricModel ? VOICE_IMAGE_KEY[active.lyricModel.toLowerCase()] : void 0;
|
|
5286
|
+
const src = imgKey ? VOICE_IMAGES[imgKey] : void 0;
|
|
5287
|
+
if (src) {
|
|
5288
|
+
lyricIcon.src = src;
|
|
5289
|
+
lyricIcon.classList.remove("dtm-hidden");
|
|
5290
|
+
} else {
|
|
5291
|
+
lyricIcon.removeAttribute("src");
|
|
5292
|
+
lyricIcon.classList.add("dtm-hidden");
|
|
5293
|
+
}
|
|
5294
|
+
};
|
|
5101
5295
|
const syncLyricVisibility = () => {
|
|
5102
5296
|
lyricBody.style.display = active.lyricModel ? "" : "none";
|
|
5297
|
+
lyricOctaveSel.style.display = active.lyricModel ? "" : "none";
|
|
5103
5298
|
updateLyricCount();
|
|
5299
|
+
syncLyricTerms();
|
|
5300
|
+
syncLyricIcon();
|
|
5104
5301
|
};
|
|
5105
5302
|
syncLyricVisibility();
|
|
5106
5303
|
lyricModelSel.addEventListener("change", () => {
|
|
5107
5304
|
active.lyricModel = lyricModelSel.value;
|
|
5108
5305
|
syncLyricVisibility();
|
|
5109
5306
|
});
|
|
5307
|
+
lyricOctaveSel.addEventListener("change", () => {
|
|
5308
|
+
active.vocalOctave = Number.parseInt(lyricOctaveSel.value, 10);
|
|
5309
|
+
});
|
|
5110
5310
|
lyricInput.addEventListener("input", () => {
|
|
5111
5311
|
active.lyrics = lyricInput.value;
|
|
5112
5312
|
updateLyricCount();
|
|
@@ -5255,12 +5455,14 @@ var mountDAW = (target, options = {}) => {
|
|
|
5255
5455
|
model: t.lyricModel.trim(),
|
|
5256
5456
|
vol: t.vocalVolume,
|
|
5257
5457
|
gate: t.vocalGate,
|
|
5258
|
-
pan: t.vocalPan
|
|
5458
|
+
pan: t.vocalPan,
|
|
5459
|
+
oct: t.vocalOctave
|
|
5259
5460
|
})).filter((x) => x.model.length > 0 && x.text.length > 0).map((x) => {
|
|
5260
5461
|
const params = [
|
|
5261
|
-
x.vol ===
|
|
5462
|
+
x.vol === DEFAULT_VOCAL_VOLUME ? "" : `v${x.vol}`,
|
|
5262
5463
|
x.gate === 100 ? "" : `q${x.gate}`,
|
|
5263
|
-
x.pan === 64 ? "" : `p${x.pan}
|
|
5464
|
+
x.pan === 64 ? "" : `p${x.pan}`,
|
|
5465
|
+
x.oct === 0 ? "" : `o${x.oct}`
|
|
5264
5466
|
].filter((s) => s.length > 0).join(" ");
|
|
5265
5467
|
const head = params ? `${x.model} ${params}` : x.model;
|
|
5266
5468
|
return `@@${x.i} ${head} ${x.text}`;
|
|
@@ -5341,6 +5543,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
5341
5543
|
if (meta.drum && drumPatterns[meta.drum]) {
|
|
5342
5544
|
currentDrumPattern = meta.drum;
|
|
5343
5545
|
refs.drumSelect.value = meta.drum;
|
|
5546
|
+
options.onDrumChange?.(meta.drum);
|
|
5344
5547
|
}
|
|
5345
5548
|
if (meta.volume !== void 0) {
|
|
5346
5549
|
masterVolume = meta.volume;
|
|
@@ -5350,9 +5553,10 @@ var mountDAW = (target, options = {}) => {
|
|
|
5350
5553
|
for (const t of trackStates) {
|
|
5351
5554
|
t.lyrics = "";
|
|
5352
5555
|
t.lyricModel = "";
|
|
5353
|
-
t.vocalVolume =
|
|
5556
|
+
t.vocalVolume = DEFAULT_VOCAL_VOLUME;
|
|
5354
5557
|
t.vocalGate = 100;
|
|
5355
5558
|
t.vocalPan = 64;
|
|
5559
|
+
t.vocalOctave = 0;
|
|
5356
5560
|
}
|
|
5357
5561
|
lyrics?.forEach((lt, idx) => {
|
|
5358
5562
|
const t = trackStates[idx];
|
|
@@ -5362,6 +5566,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
5362
5566
|
t.vocalVolume = lt.volume;
|
|
5363
5567
|
t.vocalGate = lt.gate;
|
|
5364
5568
|
t.vocalPan = lt.pan;
|
|
5569
|
+
t.vocalOctave = lt.octave ?? 0;
|
|
5365
5570
|
});
|
|
5366
5571
|
for (const p of placements) {
|
|
5367
5572
|
const t = trackStates[p.trackIndex];
|
|
@@ -5513,25 +5718,32 @@ var mountDAW = (target, options = {}) => {
|
|
|
5513
5718
|
refs.zoomXIn.addEventListener("click", () => {
|
|
5514
5719
|
zoomX = Math.min(200, zoomX + 25);
|
|
5515
5720
|
applyZoomX();
|
|
5721
|
+
notifyViewState();
|
|
5516
5722
|
});
|
|
5517
5723
|
refs.zoomXOut.addEventListener("click", () => {
|
|
5518
5724
|
zoomX = Math.max(25, zoomX - 25);
|
|
5519
5725
|
applyZoomX();
|
|
5726
|
+
notifyViewState();
|
|
5520
5727
|
});
|
|
5521
5728
|
refs.zoomYIn.addEventListener("click", () => {
|
|
5522
5729
|
zoomY = Math.min(200, zoomY + 25);
|
|
5523
5730
|
applyZoomY();
|
|
5731
|
+
notifyViewState();
|
|
5524
5732
|
});
|
|
5525
5733
|
refs.zoomYOut.addEventListener("click", () => {
|
|
5526
5734
|
zoomY = Math.max(50, zoomY - 25);
|
|
5527
5735
|
applyZoomY();
|
|
5736
|
+
notifyViewState();
|
|
5528
5737
|
});
|
|
5738
|
+
refs.decomposeChordToggle.addEventListener("change", notifyViewState);
|
|
5739
|
+
refs.ignoreChordHeavyToggle.addEventListener("change", notifyViewState);
|
|
5529
5740
|
refs.masterVolume.addEventListener("input", () => {
|
|
5530
5741
|
masterVolume = Number.parseInt(refs.masterVolume.value, 10) || 0;
|
|
5531
5742
|
refs.masterVolumeLabel.textContent = `${masterVolume}%`;
|
|
5532
5743
|
});
|
|
5533
5744
|
refs.drumSelect.addEventListener("change", () => {
|
|
5534
5745
|
currentDrumPattern = refs.drumSelect.value;
|
|
5746
|
+
options.onDrumChange?.(currentDrumPattern);
|
|
5535
5747
|
});
|
|
5536
5748
|
refs.drumVolume.addEventListener("input", () => {
|
|
5537
5749
|
drumVolume = Number.parseInt(refs.drumVolume.value, 10) || 0;
|
|
@@ -5724,6 +5936,30 @@ var mountDAW = (target, options = {}) => {
|
|
|
5724
5936
|
setInstrument: (name) => {
|
|
5725
5937
|
currentInstrument = name;
|
|
5726
5938
|
},
|
|
5939
|
+
getDrum: () => currentDrumPattern,
|
|
5940
|
+
setDrum: (name) => {
|
|
5941
|
+
if (name !== "none" && !drumPatterns[name]) return;
|
|
5942
|
+
currentDrumPattern = name;
|
|
5943
|
+
refs.drumSelect.value = name;
|
|
5944
|
+
options.onDrumChange?.(name);
|
|
5945
|
+
},
|
|
5946
|
+
getViewState,
|
|
5947
|
+
setViewState: (state) => {
|
|
5948
|
+
if (typeof state.zoomX === "number") {
|
|
5949
|
+
zoomX = clamp3(state.zoomX, 25, 200);
|
|
5950
|
+
applyZoomX();
|
|
5951
|
+
}
|
|
5952
|
+
if (typeof state.zoomY === "number") {
|
|
5953
|
+
zoomY = clamp3(state.zoomY, 50, 200);
|
|
5954
|
+
applyZoomY();
|
|
5955
|
+
}
|
|
5956
|
+
if (typeof state.decomposeChord === "boolean") {
|
|
5957
|
+
refs.decomposeChordToggle.checked = state.decomposeChord;
|
|
5958
|
+
}
|
|
5959
|
+
if (typeof state.ignoreChordHeavy === "boolean") {
|
|
5960
|
+
refs.ignoreChordHeavyToggle.checked = state.ignoreChordHeavy;
|
|
5961
|
+
}
|
|
5962
|
+
},
|
|
5727
5963
|
loadMML,
|
|
5728
5964
|
loadMIDI,
|
|
5729
5965
|
exportMIDI: exportMIDI2,
|
|
@@ -5849,11 +6085,6 @@ var STEPS_PER_BEAT3 = 48;
|
|
|
5849
6085
|
var STEPS_PER_BAR = 192;
|
|
5850
6086
|
var DEFAULT_TRACK_COLORS = ["#00e436", "#29adff", "#ff77a8", "#ffec27"];
|
|
5851
6087
|
var activePlayer = null;
|
|
5852
|
-
var formatTime = (seconds) => {
|
|
5853
|
-
const m = Math.floor(seconds / 60);
|
|
5854
|
-
const s = Math.floor(seconds % 60);
|
|
5855
|
-
return `${String(m).padStart(2, "0")}:${String(s).padStart(2, "0")}`;
|
|
5856
|
-
};
|
|
5857
6088
|
var freqFromPitch = (pitch) => 440 * 2 ** ((pitch - 69) / 12);
|
|
5858
6089
|
var mountMmlPlayer = (target, mml, options = {}) => {
|
|
5859
6090
|
injectStyles(target.ownerDocument ?? document);
|
|
@@ -5868,7 +6099,7 @@ var mountMmlPlayer = (target, mml, options = {}) => {
|
|
|
5868
6099
|
collectLyrics: true
|
|
5869
6100
|
});
|
|
5870
6101
|
const lyricTracks = lyrics ?? /* @__PURE__ */ new Map();
|
|
5871
|
-
const bpm = parsedBpm ?? options.defaultBpm ??
|
|
6102
|
+
const bpm = parsedBpm ?? options.defaultBpm ?? DEFAULT_BPM;
|
|
5872
6103
|
const drumPatternDict = options.drumPatterns ?? DRUM_PATTERNS;
|
|
5873
6104
|
const drumPattern = meta.drum ? drumPatternDict[meta.drum] ?? null : null;
|
|
5874
6105
|
const trackVolume = meta.volume ?? options.volume ?? 100;
|
|
@@ -5983,32 +6214,118 @@ var mountMmlPlayer = (target, mml, options = {}) => {
|
|
|
5983
6214
|
playBtn.className = "dtm-player-play";
|
|
5984
6215
|
playBtn.innerHTML = icon("play", 12);
|
|
5985
6216
|
playBtn.disabled = trackIndices.length === 0;
|
|
5986
|
-
const
|
|
5987
|
-
|
|
5988
|
-
|
|
5989
|
-
const
|
|
5990
|
-
|
|
5991
|
-
|
|
6217
|
+
const mmlHeader = doc.createElement("div");
|
|
6218
|
+
mmlHeader.className = "dtm-player-mml-header";
|
|
6219
|
+
const emojiEls = [];
|
|
6220
|
+
const emojiByTrack = /* @__PURE__ */ new Map();
|
|
6221
|
+
for (const index of trackIndices) {
|
|
6222
|
+
const em = doc.createElement("span");
|
|
6223
|
+
em.className = "dtm-player-emoji";
|
|
6224
|
+
em.style.backgroundColor = colorOf(index);
|
|
6225
|
+
em.textContent = "\u{1F97A}";
|
|
6226
|
+
mmlHeader.appendChild(em);
|
|
6227
|
+
emojiEls.push(em);
|
|
6228
|
+
emojiByTrack.set(index, em);
|
|
6229
|
+
}
|
|
6230
|
+
const promotedToImage = /* @__PURE__ */ new Set();
|
|
6231
|
+
for (const [index, lt] of lyricTracks) {
|
|
6232
|
+
const em = emojiByTrack.get(index);
|
|
6233
|
+
if (!em) continue;
|
|
6234
|
+
const imgKey = VOICE_IMAGE_KEY[lt.model.toLowerCase()];
|
|
6235
|
+
const src = imgKey ? VOICE_IMAGES[imgKey] : void 0;
|
|
6236
|
+
if (!src) continue;
|
|
6237
|
+
const img = doc.createElement("img");
|
|
6238
|
+
img.src = src;
|
|
6239
|
+
img.width = 20;
|
|
6240
|
+
img.height = 20;
|
|
6241
|
+
img.style.borderRadius = "50%";
|
|
6242
|
+
img.style.objectFit = "cover";
|
|
6243
|
+
img.draggable = false;
|
|
6244
|
+
promotedToImage.add(em);
|
|
6245
|
+
em.textContent = "";
|
|
6246
|
+
em.appendChild(img);
|
|
6247
|
+
}
|
|
6248
|
+
const JUMP_DEDUPE_MS = 50;
|
|
6249
|
+
const lastJumpAt = /* @__PURE__ */ new WeakMap();
|
|
6250
|
+
const jumpEmoji = (em) => {
|
|
6251
|
+
const now = performance.now();
|
|
6252
|
+
const prev = lastJumpAt.get(em);
|
|
6253
|
+
if (prev !== void 0 && now - prev < JUMP_DEDUPE_MS) return;
|
|
6254
|
+
lastJumpAt.set(em, now);
|
|
6255
|
+
em.classList.remove("dtm-player-emoji--jump");
|
|
6256
|
+
void em.offsetWidth;
|
|
6257
|
+
em.classList.add("dtm-player-emoji--jump");
|
|
6258
|
+
};
|
|
6259
|
+
const jumpTimers = [];
|
|
6260
|
+
const jumpEmojiAt = (em, when) => {
|
|
6261
|
+
if (when <= 0) {
|
|
6262
|
+
jumpEmoji(em);
|
|
6263
|
+
return;
|
|
6264
|
+
}
|
|
6265
|
+
jumpTimers.push(setTimeout(() => jumpEmoji(em), when * 1e3));
|
|
6266
|
+
};
|
|
6267
|
+
const clearJumpTimers = () => {
|
|
6268
|
+
for (const t of jumpTimers) clearTimeout(t);
|
|
6269
|
+
jumpTimers.length = 0;
|
|
6270
|
+
};
|
|
6271
|
+
const blinkTimers = [];
|
|
6272
|
+
const scheduleBlink = (em) => {
|
|
6273
|
+
const delay = 2e3 + Math.random() * 5e3;
|
|
6274
|
+
const t = setTimeout(() => {
|
|
6275
|
+
if (promotedToImage.has(em)) return;
|
|
6276
|
+
em.textContent = "\u{1F60C}";
|
|
6277
|
+
const t2 = setTimeout(
|
|
6278
|
+
() => {
|
|
6279
|
+
if (promotedToImage.has(em)) return;
|
|
6280
|
+
em.textContent = "\u{1F97A}";
|
|
6281
|
+
scheduleBlink(em);
|
|
6282
|
+
},
|
|
6283
|
+
200 + Math.random() * 150
|
|
6284
|
+
);
|
|
6285
|
+
blinkTimers.push(t2);
|
|
6286
|
+
}, delay);
|
|
6287
|
+
blinkTimers.push(t);
|
|
6288
|
+
};
|
|
6289
|
+
for (const em of emojiEls) scheduleBlink(em);
|
|
5992
6290
|
const dots = doc.createElement("div");
|
|
5993
6291
|
dots.className = "dtm-player-dots";
|
|
6292
|
+
dots.style.display = "none";
|
|
5994
6293
|
for (const index of trackIndices) {
|
|
5995
6294
|
const dot = doc.createElement("span");
|
|
5996
6295
|
dot.className = "dtm-player-dot";
|
|
5997
6296
|
dot.style.backgroundColor = colorOf(index);
|
|
5998
6297
|
dots.appendChild(dot);
|
|
5999
6298
|
}
|
|
6000
|
-
|
|
6001
|
-
|
|
6299
|
+
const beatRow = doc.createElement("div");
|
|
6300
|
+
beatRow.className = "dtm-player-beat-row";
|
|
6301
|
+
const beatDots = [];
|
|
6302
|
+
for (let i = 0; i < 4; i++) {
|
|
6303
|
+
const d = doc.createElement("span");
|
|
6304
|
+
d.className = "dtm-player-beat-dot";
|
|
6305
|
+
beatRow.appendChild(d);
|
|
6306
|
+
beatDots.push(d);
|
|
6307
|
+
}
|
|
6308
|
+
const barEl = doc.createElement("span");
|
|
6309
|
+
barEl.className = "dtm-player-bar";
|
|
6310
|
+
barEl.textContent = "-";
|
|
6311
|
+
beatRow.appendChild(barEl);
|
|
6312
|
+
const chips = [];
|
|
6313
|
+
const makeChip = (label) => {
|
|
6002
6314
|
const chip = doc.createElement("span");
|
|
6003
6315
|
chip.className = "dtm-player-chip";
|
|
6004
6316
|
chip.textContent = label;
|
|
6005
|
-
|
|
6317
|
+
chips.push(chip);
|
|
6318
|
+
return chip;
|
|
6006
6319
|
};
|
|
6007
|
-
if (meta.instrument)
|
|
6008
|
-
if (meta.drum)
|
|
6009
|
-
if (meta.volume !== void 0)
|
|
6010
|
-
head.
|
|
6320
|
+
if (meta.instrument) makeChip(`\u266A ${meta.instrument}`);
|
|
6321
|
+
if (meta.drum) makeChip(`\u{1F941} ${meta.drum}${drumPattern ? "" : " (?)"}`);
|
|
6322
|
+
if (meta.volume !== void 0) makeChip(`\u{1F50A} ${meta.volume}%`);
|
|
6323
|
+
head.append(playBtn, beatRow, ...chips, dots, mmlHeader);
|
|
6011
6324
|
root.appendChild(head);
|
|
6325
|
+
const body = doc.createElement("div");
|
|
6326
|
+
body.className = "dtm-player-body";
|
|
6327
|
+
root.appendChild(body);
|
|
6328
|
+
const mutedTracks = /* @__PURE__ */ new Set();
|
|
6012
6329
|
const laneViews = [];
|
|
6013
6330
|
for (const index of trackIndices) {
|
|
6014
6331
|
const lyricTrack = lyricTracks.get(index);
|
|
@@ -6016,7 +6333,7 @@ var mountMmlPlayer = (target, mml, options = {}) => {
|
|
|
6016
6333
|
const row = doc.createElement("div");
|
|
6017
6334
|
row.className = "dtm-player-lane-row";
|
|
6018
6335
|
const label = doc.createElement("div");
|
|
6019
|
-
label.className = "dtm-player-lane-label";
|
|
6336
|
+
label.className = "dtm-player-lane-label dtm-player-lane-label--btn";
|
|
6020
6337
|
const swatch = doc.createElement("span");
|
|
6021
6338
|
swatch.className = "dtm-player-dot";
|
|
6022
6339
|
swatch.style.backgroundColor = colorOf(index);
|
|
@@ -6024,13 +6341,22 @@ var mountMmlPlayer = (target, mml, options = {}) => {
|
|
|
6024
6341
|
no.className = "dtm-player-lane-no";
|
|
6025
6342
|
no.textContent = `@${index}`;
|
|
6026
6343
|
label.append(swatch, no);
|
|
6344
|
+
label.addEventListener("click", () => {
|
|
6345
|
+
if (mutedTracks.has(index)) {
|
|
6346
|
+
mutedTracks.delete(index);
|
|
6347
|
+
label.classList.remove("dtm-player-lane-label--muted");
|
|
6348
|
+
} else {
|
|
6349
|
+
mutedTracks.add(index);
|
|
6350
|
+
label.classList.add("dtm-player-lane-label--muted");
|
|
6351
|
+
}
|
|
6352
|
+
});
|
|
6027
6353
|
const lane = doc.createElement("div");
|
|
6028
6354
|
lane.className = "dtm-player-lane";
|
|
6029
6355
|
lane.style.setProperty("--tk", colorOf(index));
|
|
6030
6356
|
const laneTokens = [];
|
|
6031
6357
|
if (isLyricLane) {
|
|
6032
6358
|
const notes = placements.filter((p) => p.trackIndex === index).sort((a, b) => a.startStep - b.startStep);
|
|
6033
|
-
const gateScale = (lyricTrack.gate ??
|
|
6359
|
+
const gateScale = (lyricTrack.gate ?? DEFAULT_GATE) / 100;
|
|
6034
6360
|
const breaks = new Set(lyricTrack.lineBreaks ?? []);
|
|
6035
6361
|
if (lyricTrack.metaText) {
|
|
6036
6362
|
const metaEl = doc.createElement("span");
|
|
@@ -6077,9 +6403,46 @@ var mountMmlPlayer = (target, mml, options = {}) => {
|
|
|
6077
6403
|
}
|
|
6078
6404
|
}
|
|
6079
6405
|
row.append(label, lane);
|
|
6080
|
-
|
|
6406
|
+
body.appendChild(row);
|
|
6081
6407
|
laneViews.push({ lane, tokens: laneTokens });
|
|
6082
6408
|
}
|
|
6409
|
+
const termsModels = [
|
|
6410
|
+
...new Set([...lyricTracks.values()].map((lt) => lt.model))
|
|
6411
|
+
].filter((model) => KOE_VOICEBANK_TERMS[model]);
|
|
6412
|
+
if (termsModels.length > 0) {
|
|
6413
|
+
const termsDiv = doc.createElement("div");
|
|
6414
|
+
termsDiv.className = "dtm-player-terms";
|
|
6415
|
+
termsDiv.style.fontSize = "10px";
|
|
6416
|
+
termsDiv.style.color = "var(--dtm-warn)";
|
|
6417
|
+
termsDiv.style.display = "flex";
|
|
6418
|
+
termsDiv.style.flexDirection = "column";
|
|
6419
|
+
termsDiv.style.gap = "4px";
|
|
6420
|
+
termsDiv.style.marginTop = "4px";
|
|
6421
|
+
termsDiv.style.padding = "0 4px";
|
|
6422
|
+
for (const model of termsModels) {
|
|
6423
|
+
const termsRow = doc.createElement("div");
|
|
6424
|
+
termsRow.style.display = "flex";
|
|
6425
|
+
termsRow.style.alignItems = "center";
|
|
6426
|
+
termsRow.style.gap = "4px";
|
|
6427
|
+
termsRow.style.flexWrap = "wrap";
|
|
6428
|
+
const label = KOE_VOICEBANK_LABELS[model] ?? model;
|
|
6429
|
+
const url = KOE_VOICEBANK_TERMS[model];
|
|
6430
|
+
const span1 = doc.createElement("span");
|
|
6431
|
+
span1.textContent = "\u4F7F\u7528\u6642\u306B\u306F";
|
|
6432
|
+
const a = doc.createElement("a");
|
|
6433
|
+
a.textContent = `${label}UTAU\u97F3\u6E90`;
|
|
6434
|
+
a.href = url;
|
|
6435
|
+
a.target = "_blank";
|
|
6436
|
+
a.rel = "noopener";
|
|
6437
|
+
a.style.color = "var(--dtm-primary)";
|
|
6438
|
+
a.style.textDecoration = "underline";
|
|
6439
|
+
const span2 = doc.createElement("span");
|
|
6440
|
+
span2.textContent = "\u306E\u5229\u7528\u898F\u7D04\u306B\u5F93\u3063\u3066\u304F\u3060\u3055\u3044";
|
|
6441
|
+
termsRow.append(span1, a, span2);
|
|
6442
|
+
termsDiv.appendChild(termsRow);
|
|
6443
|
+
}
|
|
6444
|
+
root.appendChild(termsDiv);
|
|
6445
|
+
}
|
|
6083
6446
|
target.appendChild(root);
|
|
6084
6447
|
const autoScroll = (lane, el) => {
|
|
6085
6448
|
if (el.offsetWidth === 0 || lane.clientWidth === 0) return;
|
|
@@ -6089,7 +6452,10 @@ var mountMmlPlayer = (target, mml, options = {}) => {
|
|
|
6089
6452
|
lane.scrollLeft = Math.max(0, Math.min(next, maxScroll));
|
|
6090
6453
|
};
|
|
6091
6454
|
const renderPlayhead = (step) => {
|
|
6092
|
-
|
|
6455
|
+
const beatIndex = Math.floor(step / STEPS_PER_BEAT3) % 4;
|
|
6456
|
+
for (let i = 0; i < 4; i++)
|
|
6457
|
+
beatDots[i].classList.toggle("dtm-player-beat-dot--on", i === beatIndex);
|
|
6458
|
+
barEl.textContent = String(Math.floor(step / STEPS_PER_BAR) + 1);
|
|
6093
6459
|
for (const view of laneViews) {
|
|
6094
6460
|
let active = null;
|
|
6095
6461
|
for (const t of view.tokens) {
|
|
@@ -6101,7 +6467,8 @@ var mountMmlPlayer = (target, mml, options = {}) => {
|
|
|
6101
6467
|
}
|
|
6102
6468
|
};
|
|
6103
6469
|
const resetPlayhead = () => {
|
|
6104
|
-
|
|
6470
|
+
for (const d of beatDots) d.classList.remove("dtm-player-beat-dot--on");
|
|
6471
|
+
barEl.textContent = "-";
|
|
6105
6472
|
for (const view of laneViews) {
|
|
6106
6473
|
for (const t of view.tokens) t.el.classList.remove("is-active");
|
|
6107
6474
|
view.lane.scrollLeft = 0;
|
|
@@ -6115,7 +6482,11 @@ var mountMmlPlayer = (target, mml, options = {}) => {
|
|
|
6115
6482
|
getSoloTrackId: () => null,
|
|
6116
6483
|
getAudioTime,
|
|
6117
6484
|
onPlayNote: (e) => {
|
|
6118
|
-
|
|
6485
|
+
const trackIdx = Number(e.trackId);
|
|
6486
|
+
if (mutedTracks.has(trackIdx)) return;
|
|
6487
|
+
const em = emojiByTrack.get(trackIdx);
|
|
6488
|
+
if (em) jumpEmojiAt(em, e.when);
|
|
6489
|
+
if (lyricTracks.has(trackIdx)) return;
|
|
6119
6490
|
options.onPlayNote?.(e);
|
|
6120
6491
|
if (useSynth) synthPlay(e);
|
|
6121
6492
|
},
|
|
@@ -6138,6 +6509,7 @@ var mountMmlPlayer = (target, mml, options = {}) => {
|
|
|
6138
6509
|
};
|
|
6139
6510
|
const finish = () => {
|
|
6140
6511
|
setPlayingUI(false);
|
|
6512
|
+
clearJumpTimers();
|
|
6141
6513
|
resetPlayhead();
|
|
6142
6514
|
if (activePlayer === instance) activePlayer = null;
|
|
6143
6515
|
};
|
|
@@ -6146,22 +6518,23 @@ var mountMmlPlayer = (target, mml, options = {}) => {
|
|
|
6146
6518
|
const sorted = [...seqTrack?.notes ?? []].sort(
|
|
6147
6519
|
(a, b) => a.startStep - b.startStep
|
|
6148
6520
|
);
|
|
6149
|
-
const gate = (lt.gate ??
|
|
6521
|
+
const gate = (lt.gate ?? DEFAULT_GATE) / 100;
|
|
6522
|
+
const semis = (lt.octave ?? 0) * 12;
|
|
6150
6523
|
const count = Math.min(sorted.length, lt.syllables.length);
|
|
6151
6524
|
const notes = [];
|
|
6152
6525
|
for (let i = 0; i < count; i++) {
|
|
6153
6526
|
const n = sorted[i];
|
|
6154
6527
|
notes.push({
|
|
6155
6528
|
syllable: lt.syllables[i],
|
|
6156
|
-
pitch: n.pitch,
|
|
6529
|
+
pitch: n.pitch + semis,
|
|
6157
6530
|
startSec: n.startStep * secondsPerStep,
|
|
6158
6531
|
durationSec: n.durationSteps * secondsPerStep * gate
|
|
6159
6532
|
});
|
|
6160
6533
|
}
|
|
6161
6534
|
return {
|
|
6162
6535
|
model: lt.model,
|
|
6163
|
-
volume: vocalVolumeToGain(lt.volume ??
|
|
6164
|
-
pan: panToStereo(lt.pan ??
|
|
6536
|
+
volume: vocalVolumeToGain(lt.volume ?? DEFAULT_VOCAL_VOLUME) * (trackVolume / 100),
|
|
6537
|
+
pan: panToStereo(lt.pan ?? DEFAULT_PAN),
|
|
6165
6538
|
notes
|
|
6166
6539
|
};
|
|
6167
6540
|
});
|
|
@@ -6170,7 +6543,7 @@ var mountMmlPlayer = (target, mml, options = {}) => {
|
|
|
6170
6543
|
const tracks = streaming ? buildStreamTracks() : [];
|
|
6171
6544
|
if (streaming) {
|
|
6172
6545
|
const v = ensureVoices();
|
|
6173
|
-
const overlay = showLoadingOverlay(
|
|
6546
|
+
const overlay = showLoadingOverlay(body);
|
|
6174
6547
|
try {
|
|
6175
6548
|
await v.loadModels(tracks.map((t) => t.model));
|
|
6176
6549
|
await v.warm(tracks);
|
|
@@ -6215,6 +6588,8 @@ var mountMmlPlayer = (target, mml, options = {}) => {
|
|
|
6215
6588
|
void audioCtx.close();
|
|
6216
6589
|
audioCtx = null;
|
|
6217
6590
|
}
|
|
6591
|
+
for (const t of blinkTimers) clearTimeout(t);
|
|
6592
|
+
clearJumpTimers();
|
|
6218
6593
|
root.remove();
|
|
6219
6594
|
};
|
|
6220
6595
|
const instance = {
|
|
@@ -6508,9 +6883,334 @@ var createPianoRoll = (options, handlers) => {
|
|
|
6508
6883
|
}
|
|
6509
6884
|
};
|
|
6510
6885
|
};
|
|
6886
|
+
|
|
6887
|
+
// src/studio.ts
|
|
6888
|
+
var import_meta = {};
|
|
6889
|
+
var DEFAULT_CDN = {
|
|
6890
|
+
soundFont: "https://rpgen3.github.io/soundfont/mjs/surikov/SoundFont.mjs",
|
|
6891
|
+
soundFontDrum: "https://rpgen3.github.io/soundfont/mjs/surikov/SoundFont_drum.mjs",
|
|
6892
|
+
soundFontList: "https://rpgen3.github.io/soundfont/mjs/surikov/SoundFont_list.mjs",
|
|
6893
|
+
parseChord: "https://rpgen3.github.io/piano/mjs/parseChord.mjs",
|
|
6894
|
+
parseChords: "https://rpgen3.github.io/piano/mjs/parseChords.mjs",
|
|
6895
|
+
midiParser: "https://cdn.jsdelivr.net/npm/midi-parser-js@4.0.4/+esm"
|
|
6896
|
+
};
|
|
6897
|
+
var SOUNDFONT_NAME = "FluidR3_GM_sf2_file";
|
|
6898
|
+
var TRACK_ROLES = ["melody", "submelody", "bass", "chord"];
|
|
6899
|
+
var resolveDefaultVoiceWorkerUrl = () => {
|
|
6900
|
+
try {
|
|
6901
|
+
return new URL("./voice-worker.js", import_meta.url).href;
|
|
6902
|
+
} catch {
|
|
6903
|
+
return void 0;
|
|
6904
|
+
}
|
|
6905
|
+
};
|
|
6906
|
+
var importFrom = async (url, name) => {
|
|
6907
|
+
const mod = await import(
|
|
6908
|
+
/* @vite-ignore */
|
|
6909
|
+
url
|
|
6910
|
+
);
|
|
6911
|
+
return mod[name] ?? mod.default;
|
|
6912
|
+
};
|
|
6913
|
+
var createDtmStudio = async (options = {}) => {
|
|
6914
|
+
const cdn = { ...DEFAULT_CDN, ...options.cdn };
|
|
6915
|
+
const features = {
|
|
6916
|
+
recorder: true,
|
|
6917
|
+
midi: true,
|
|
6918
|
+
chord: true,
|
|
6919
|
+
presetUI: true,
|
|
6920
|
+
...options.features
|
|
6921
|
+
};
|
|
6922
|
+
const audioCtx = options.audioContext ?? new AudioContext();
|
|
6923
|
+
const masterGain = audioCtx.createGain();
|
|
6924
|
+
masterGain.gain.value = options.masterVolume ?? 1;
|
|
6925
|
+
masterGain.connect(audioCtx.destination);
|
|
6926
|
+
const drumGain = audioCtx.createGain();
|
|
6927
|
+
drumGain.gain.value = options.drumVolume ?? 1;
|
|
6928
|
+
drumGain.connect(audioCtx.destination);
|
|
6929
|
+
const resumeAudio = () => {
|
|
6930
|
+
if (audioCtx.state === "suspended") void audioCtx.resume();
|
|
6931
|
+
};
|
|
6932
|
+
const eng = options.engines ?? {};
|
|
6933
|
+
const [SoundFont, SoundFont_drum, SoundFont_list] = await Promise.all([
|
|
6934
|
+
eng.SoundFont ?? importFrom(cdn.soundFont, "SoundFont"),
|
|
6935
|
+
eng.SoundFont_drum ?? importFrom(cdn.soundFontDrum, "SoundFont_drum"),
|
|
6936
|
+
eng.SoundFont_list ?? importFrom(cdn.soundFontList, "SoundFont_list")
|
|
6937
|
+
]);
|
|
6938
|
+
let parseChord = eng.parseChord;
|
|
6939
|
+
let parseChords = eng.parseChords;
|
|
6940
|
+
if (features.chord && (!parseChord || !parseChords)) {
|
|
6941
|
+
try {
|
|
6942
|
+
[parseChord, parseChords] = await Promise.all([
|
|
6943
|
+
parseChord ?? importFrom(
|
|
6944
|
+
cdn.parseChord,
|
|
6945
|
+
"parseChord"
|
|
6946
|
+
),
|
|
6947
|
+
parseChords ?? importFrom(
|
|
6948
|
+
cdn.parseChords,
|
|
6949
|
+
"parseChords"
|
|
6950
|
+
)
|
|
6951
|
+
]);
|
|
6952
|
+
} catch (e) {
|
|
6953
|
+
console.warn("[dtm] \u30B3\u30FC\u30C9\u89E3\u6790\u306E\u8AAD\u307F\u8FBC\u307F\u306B\u5931\u6557\u3057\u307E\u3057\u305F", e);
|
|
6954
|
+
}
|
|
6955
|
+
}
|
|
6956
|
+
let midiParser = null;
|
|
6957
|
+
let parseMidi;
|
|
6958
|
+
if (features.midi) {
|
|
6959
|
+
parseMidi = eng.parseMidi;
|
|
6960
|
+
if (!parseMidi) {
|
|
6961
|
+
const midiPromise = importFrom(
|
|
6962
|
+
cdn.midiParser,
|
|
6963
|
+
"default"
|
|
6964
|
+
).then((m) => {
|
|
6965
|
+
midiParser = m;
|
|
6966
|
+
}).catch((e) => console.warn("[dtm] midi-parser \u306E\u8AAD\u307F\u8FBC\u307F\u306B\u5931\u6557", e));
|
|
6967
|
+
void midiPromise;
|
|
6968
|
+
parseMidi = (bytes) => {
|
|
6969
|
+
if (!midiParser) throw new Error("midi-parser not ready");
|
|
6970
|
+
return midiParser.parse(bytes);
|
|
6971
|
+
};
|
|
6972
|
+
}
|
|
6973
|
+
}
|
|
6974
|
+
const voiceWorkerUrl = options.voiceWorkerUrl === null ? void 0 : options.voiceWorkerUrl ?? resolveDefaultVoiceWorkerUrl();
|
|
6975
|
+
const singingVoices = createSingingVoices(audioCtx, masterGain, {
|
|
6976
|
+
voiceWorkerUrl
|
|
6977
|
+
});
|
|
6978
|
+
const recorder = features.recorder ? setupRecorder(audioCtx, masterGain, drumGain) : null;
|
|
6979
|
+
const downloadWav = () => {
|
|
6980
|
+
if (!recorder) return;
|
|
6981
|
+
const recordedData = recorder.getRecordedData();
|
|
6982
|
+
const ch = recordedData.length;
|
|
6983
|
+
const len = recordedData[0].length;
|
|
6984
|
+
if (len === 0) return;
|
|
6985
|
+
const bufSize = recordedData[0][0].length;
|
|
6986
|
+
const wave = new Float32Array(ch * len * bufSize);
|
|
6987
|
+
let idx = 0;
|
|
6988
|
+
for (let i = 0; i < len; i++)
|
|
6989
|
+
for (let j = 0; j < bufSize; j++)
|
|
6990
|
+
for (let k = 0; k < ch; k++) wave[idx++] = recordedData[k][i][j];
|
|
6991
|
+
const sampleRate = audioCtx.sampleRate;
|
|
6992
|
+
const channels = 2;
|
|
6993
|
+
const bitRate = 16;
|
|
6994
|
+
const step = bitRate / 8;
|
|
6995
|
+
const blockSize = channels * step;
|
|
6996
|
+
const byteLen = wave.length * step;
|
|
6997
|
+
const view = new DataView(new ArrayBuffer(44 + byteLen));
|
|
6998
|
+
const ws = (off2, s) => {
|
|
6999
|
+
for (let i = 0; i < s.length; i++)
|
|
7000
|
+
view.setUint8(off2 + i, s.charCodeAt(i));
|
|
7001
|
+
};
|
|
7002
|
+
ws(0, "RIFF");
|
|
7003
|
+
view.setUint32(4, 32 + byteLen, true);
|
|
7004
|
+
ws(8, "WAVE");
|
|
7005
|
+
ws(12, "fmt ");
|
|
7006
|
+
view.setUint32(16, 16, true);
|
|
7007
|
+
view.setUint16(20, 1, true);
|
|
7008
|
+
view.setUint16(22, channels, true);
|
|
7009
|
+
view.setUint32(24, sampleRate, true);
|
|
7010
|
+
view.setUint32(28, sampleRate * blockSize, true);
|
|
7011
|
+
view.setUint16(32, blockSize, true);
|
|
7012
|
+
view.setUint16(34, bitRate, true);
|
|
7013
|
+
ws(36, "data");
|
|
7014
|
+
view.setUint32(40, byteLen, true);
|
|
7015
|
+
const clamp4 = (n, a2, b) => Math.max(a2, Math.min(b, n));
|
|
7016
|
+
let off = 44;
|
|
7017
|
+
for (let i = 0; i < wave.length; i++, off += step)
|
|
7018
|
+
view.setInt16(
|
|
7019
|
+
off,
|
|
7020
|
+
clamp4(Math.round(wave[i] * 32768), -32768, 32767),
|
|
7021
|
+
true
|
|
7022
|
+
);
|
|
7023
|
+
const blob = new Blob([view], { type: "audio/wav" });
|
|
7024
|
+
const url = URL.createObjectURL(blob);
|
|
7025
|
+
const a = document.createElement("a");
|
|
7026
|
+
a.href = url;
|
|
7027
|
+
a.download = "record.wav";
|
|
7028
|
+
a.click();
|
|
7029
|
+
URL.revokeObjectURL(url);
|
|
7030
|
+
};
|
|
7031
|
+
const onToggleRecord = recorder ? () => {
|
|
7032
|
+
if (recorder.isRecording()) {
|
|
7033
|
+
recorder.stopRecording();
|
|
7034
|
+
downloadWav();
|
|
7035
|
+
} else {
|
|
7036
|
+
recorder.clearRecordedData();
|
|
7037
|
+
recorder.startRecording();
|
|
7038
|
+
}
|
|
7039
|
+
} : void 0;
|
|
7040
|
+
const listReady = new Promise((resolve) => {
|
|
7041
|
+
SoundFont_list.init();
|
|
7042
|
+
SoundFont_list.onload(() => resolve());
|
|
7043
|
+
});
|
|
7044
|
+
const drumReady = (async () => {
|
|
7045
|
+
try {
|
|
7046
|
+
await SoundFont_drum.load({
|
|
7047
|
+
ctx: audioCtx,
|
|
7048
|
+
font: DRUM_FONT,
|
|
7049
|
+
id: "0",
|
|
7050
|
+
keys: Object.values(DRUM_KEYS)
|
|
7051
|
+
});
|
|
7052
|
+
} catch (e) {
|
|
7053
|
+
console.error("[dtm] \u30C9\u30E9\u30E0\u97F3\u6E90\u306E\u8AAD\u307F\u8FBC\u307F\u306B\u5931\u6557", e);
|
|
7054
|
+
}
|
|
7055
|
+
})();
|
|
7056
|
+
let nameToKey = {};
|
|
7057
|
+
const soundFonts = /* @__PURE__ */ new Map();
|
|
7058
|
+
const loadedKeyByTrack = /* @__PURE__ */ new Map();
|
|
7059
|
+
const loadSoundFont = async (instrumentKey, trackId) => {
|
|
7060
|
+
if (loadedKeyByTrack.get(trackId) === instrumentKey) return;
|
|
7061
|
+
try {
|
|
7062
|
+
const fullName = `${instrumentKey}_${SOUNDFONT_NAME}`;
|
|
7063
|
+
soundFonts.set(
|
|
7064
|
+
trackId,
|
|
7065
|
+
await SoundFont.load({
|
|
7066
|
+
ctx: audioCtx,
|
|
7067
|
+
fontName: `_tone_${fullName}`,
|
|
7068
|
+
url: SoundFont.toURL(fullName)
|
|
7069
|
+
})
|
|
7070
|
+
);
|
|
7071
|
+
loadedKeyByTrack.set(trackId, instrumentKey);
|
|
7072
|
+
} catch (e) {
|
|
7073
|
+
console.error(`[dtm] \u697D\u5668 "${instrumentKey}" \u306E\u8AAD\u307F\u8FBC\u307F\u306B\u5931\u6557`, e);
|
|
7074
|
+
}
|
|
7075
|
+
};
|
|
7076
|
+
const defaultPreset = options.defaultPreset ?? "retro_game";
|
|
7077
|
+
const instrumentNameFor = (preset, trackId) => preset[trackId] ?? preset.melody;
|
|
7078
|
+
const loadPreset = async (presetKey, trackIds = [...TRACK_ROLES]) => {
|
|
7079
|
+
const preset = INSTRUMENT_PRESETS[presetKey];
|
|
7080
|
+
if (!preset) return;
|
|
7081
|
+
await listReady;
|
|
7082
|
+
await Promise.all(
|
|
7083
|
+
trackIds.map((trackId) => {
|
|
7084
|
+
const key = nameToKey[instrumentNameFor(preset, trackId)];
|
|
7085
|
+
return key ? loadSoundFont(key, trackId) : Promise.resolve();
|
|
7086
|
+
})
|
|
7087
|
+
);
|
|
7088
|
+
};
|
|
7089
|
+
await listReady;
|
|
7090
|
+
nameToKey = await buildNameToKeyMapping();
|
|
7091
|
+
await Promise.all([drumReady, loadPreset(defaultPreset)]);
|
|
7092
|
+
const playNote = (e) => {
|
|
7093
|
+
const sf = soundFonts.get(e.trackId);
|
|
7094
|
+
if (!sf) return;
|
|
7095
|
+
sf.play({
|
|
7096
|
+
ctx: audioCtx,
|
|
7097
|
+
destination: masterGain,
|
|
7098
|
+
pitch: e.pitch,
|
|
7099
|
+
volume: e.volume,
|
|
7100
|
+
when: e.when,
|
|
7101
|
+
duration: e.duration
|
|
7102
|
+
});
|
|
7103
|
+
};
|
|
7104
|
+
const playDrum = (e) => {
|
|
7105
|
+
if (!SoundFont_drum.font) return;
|
|
7106
|
+
SoundFont_drum.play({
|
|
7107
|
+
ctx: audioCtx,
|
|
7108
|
+
destination: drumGain,
|
|
7109
|
+
pitch: e.pitch,
|
|
7110
|
+
volume: e.velocity,
|
|
7111
|
+
when: e.when,
|
|
7112
|
+
duration: e.duration
|
|
7113
|
+
});
|
|
7114
|
+
};
|
|
7115
|
+
const sfForPlayerTrack = (trackId) => soundFonts.get(TRACK_ROLES[Number(trackId)] ?? "") ?? soundFonts.get(`t${trackId}`);
|
|
7116
|
+
const playPlayerNote = (e) => {
|
|
7117
|
+
const sf = sfForPlayerTrack(e.trackId);
|
|
7118
|
+
if (!sf) return;
|
|
7119
|
+
sf.play({
|
|
7120
|
+
ctx: audioCtx,
|
|
7121
|
+
destination: masterGain,
|
|
7122
|
+
pitch: e.pitch,
|
|
7123
|
+
volume: e.volume,
|
|
7124
|
+
when: e.when,
|
|
7125
|
+
duration: e.duration
|
|
7126
|
+
});
|
|
7127
|
+
};
|
|
7128
|
+
const editorPresetSelects = /* @__PURE__ */ new WeakMap();
|
|
7129
|
+
const mountedEditors = [];
|
|
7130
|
+
const mountedPlayers = [];
|
|
7131
|
+
const mountEditor = (target, opts = {}) => {
|
|
7132
|
+
const { preset, presetUI, ...dawOverrides } = opts;
|
|
7133
|
+
const tracks = dawOverrides.tracks ?? TRACKS_SIMPLE;
|
|
7134
|
+
const trackIds = tracks.map((t) => t.id);
|
|
7135
|
+
const base = {
|
|
7136
|
+
getAudioTime: () => audioCtx.currentTime,
|
|
7137
|
+
onResumeAudio: resumeAudio,
|
|
7138
|
+
onPlayNote: playNote,
|
|
7139
|
+
onPlayDrum: playDrum,
|
|
7140
|
+
singingVoices,
|
|
7141
|
+
parseChord,
|
|
7142
|
+
parseChords,
|
|
7143
|
+
parseMidi,
|
|
7144
|
+
onToggleRecord,
|
|
7145
|
+
...dawOverrides
|
|
7146
|
+
};
|
|
7147
|
+
const wantPresetUI = presetUI ?? features.presetUI;
|
|
7148
|
+
if (wantPresetUI) {
|
|
7149
|
+
const select = target.ownerDocument.createElement("select");
|
|
7150
|
+
select.className = "dtm-studio-preset";
|
|
7151
|
+
for (const [key, p] of Object.entries(INSTRUMENT_PRESETS)) {
|
|
7152
|
+
const opt = target.ownerDocument.createElement("option");
|
|
7153
|
+
opt.value = key;
|
|
7154
|
+
opt.textContent = p.displayName;
|
|
7155
|
+
select.appendChild(opt);
|
|
7156
|
+
}
|
|
7157
|
+
select.value = preset && INSTRUMENT_PRESETS[preset] ? preset : defaultPreset;
|
|
7158
|
+
target.appendChild(select);
|
|
7159
|
+
editorPresetSelects.set(target, select);
|
|
7160
|
+
select.addEventListener("change", async () => {
|
|
7161
|
+
daw.setInstrument(select.value);
|
|
7162
|
+
await loadPreset(select.value, trackIds);
|
|
7163
|
+
});
|
|
7164
|
+
}
|
|
7165
|
+
const daw = mountDAW(target, base);
|
|
7166
|
+
mountedEditors.push(daw);
|
|
7167
|
+
const presetKey = preset && INSTRUMENT_PRESETS[preset] ? preset : defaultPreset;
|
|
7168
|
+
daw.setInstrument(presetKey);
|
|
7169
|
+
void loadPreset(presetKey, trackIds);
|
|
7170
|
+
return daw;
|
|
7171
|
+
};
|
|
7172
|
+
const mountPlayer = (target, mml, opts = {}) => {
|
|
7173
|
+
const meta = parseMML(mml, {}).meta ?? {};
|
|
7174
|
+
if (meta.instrument && INSTRUMENT_PRESETS[meta.instrument]) {
|
|
7175
|
+
void loadPreset(meta.instrument);
|
|
7176
|
+
}
|
|
7177
|
+
const player = mountMmlPlayer(target, mml, {
|
|
7178
|
+
getAudioTime: () => audioCtx.currentTime,
|
|
7179
|
+
onResumeAudio: resumeAudio,
|
|
7180
|
+
onPlayNote: playPlayerNote,
|
|
7181
|
+
onPlayDrum: playDrum,
|
|
7182
|
+
singingVoices,
|
|
7183
|
+
...opts
|
|
7184
|
+
});
|
|
7185
|
+
mountedPlayers.push(player);
|
|
7186
|
+
return player;
|
|
7187
|
+
};
|
|
7188
|
+
const dispose = () => {
|
|
7189
|
+
for (const p of mountedPlayers) p.destroy();
|
|
7190
|
+
for (const d of mountedEditors) d.destroy();
|
|
7191
|
+
mountedPlayers.length = 0;
|
|
7192
|
+
mountedEditors.length = 0;
|
|
7193
|
+
void audioCtx.close();
|
|
7194
|
+
};
|
|
7195
|
+
return {
|
|
7196
|
+
audioContext: audioCtx,
|
|
7197
|
+
singingVoices,
|
|
7198
|
+
mountEditor,
|
|
7199
|
+
mountPlayer,
|
|
7200
|
+
loadPreset,
|
|
7201
|
+
dispose
|
|
7202
|
+
};
|
|
7203
|
+
};
|
|
6511
7204
|
// Annotate the CommonJS export names for ESM import in node:
|
|
6512
7205
|
0 && (module.exports = {
|
|
6513
7206
|
DAW_CSS,
|
|
7207
|
+
DEFAULT_BPM,
|
|
7208
|
+
DEFAULT_GATE,
|
|
7209
|
+
DEFAULT_PAN,
|
|
7210
|
+
DEFAULT_PLAYBACK_VELOCITY,
|
|
7211
|
+
DEFAULT_STEPS_PER_BAR,
|
|
7212
|
+
DEFAULT_VELOCITY,
|
|
7213
|
+
DEFAULT_VOCAL_VOLUME,
|
|
6514
7214
|
DRUM_FONT,
|
|
6515
7215
|
DRUM_KEYS,
|
|
6516
7216
|
DRUM_PATTERNS,
|
|
@@ -6518,6 +7218,7 @@ var createPianoRoll = (options, handlers) => {
|
|
|
6518
7218
|
KOE_BASE_URL,
|
|
6519
7219
|
KOE_VOICEBANKS,
|
|
6520
7220
|
KOE_VOICEBANK_LABELS,
|
|
7221
|
+
KOE_VOICEBANK_TERMS,
|
|
6521
7222
|
LinkedList,
|
|
6522
7223
|
MAX_VOCAL_VOLUME,
|
|
6523
7224
|
MMLCore,
|
|
@@ -6525,6 +7226,7 @@ var createPianoRoll = (options, handlers) => {
|
|
|
6525
7226
|
PREWARM_NOTES,
|
|
6526
7227
|
TRACKS_ADVANCED,
|
|
6527
7228
|
TRACKS_SIMPLE,
|
|
7229
|
+
VOICE_IMAGE_KEY,
|
|
6528
7230
|
analyzeMidiTracks,
|
|
6529
7231
|
applyHarmonicFilter,
|
|
6530
7232
|
applyMonophonic,
|
|
@@ -6532,6 +7234,7 @@ var createPianoRoll = (options, handlers) => {
|
|
|
6532
7234
|
buildNameToKeyMapping,
|
|
6533
7235
|
collectPitchTokens,
|
|
6534
7236
|
createAudioContext,
|
|
7237
|
+
createDtmStudio,
|
|
6535
7238
|
createKlattVoice,
|
|
6536
7239
|
createKoeVoice,
|
|
6537
7240
|
createLyricsConductor,
|