@onjmin/dtm 0.1.1 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.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,
@@ -379,7 +388,10 @@ var buildUI = (target, options) => {
379
388
  <div class="dtm-tracks" data-dtm="track-tabs"></div>
380
389
 
381
390
  <div class="dtm-roll-wrap">
382
- <div class="dtm-roll" data-dtm="roll"><div data-dtm="wrapper" style="position:absolute;inset:0;"></div></div>
391
+ <div class="dtm-roll" data-dtm="roll">
392
+ <div data-dtm="wrapper" style="position:absolute;inset:0;"></div>
393
+ <div class="dtm-overlay" data-dtm="overlay" hidden><div class="dtm-spinner"></div></div>
394
+ </div>
383
395
  <div class="dtm-vscroll" data-dtm="vscroll"><div class="dtm-vscroll-thumb" data-dtm="vscroll-thumb"></div></div>
384
396
  </div>
385
397
  <div class="dtm-hscroll" data-dtm="hscroll"><div class="dtm-hscroll-thumb" data-dtm="hscroll-thumb"></div></div>
@@ -512,8 +524,6 @@ var buildUI = (target, options) => {
512
524
  </div>
513
525
  </div>
514
526
  </details>
515
-
516
- <div class="dtm-overlay" data-dtm="overlay" hidden><div class="dtm-spinner"></div></div>
517
527
  </div>`;
518
528
  const root = q(target, '[data-dtm="root"]');
519
529
  const sel = (name) => q(root, `[data-dtm="${name}"]`);
@@ -1000,6 +1010,15 @@ var Worldline = class _Worldline {
1000
1010
  }
1001
1011
  };
1002
1012
 
1013
+ // src/types.ts
1014
+ var DEFAULT_VOCAL_VOLUME = 200;
1015
+ var DEFAULT_BPM = 120;
1016
+ var DEFAULT_GATE = 100;
1017
+ var DEFAULT_PAN = 64;
1018
+ var DEFAULT_VELOCITY = 100;
1019
+ var DEFAULT_PLAYBACK_VELOCITY = 127;
1020
+ var DEFAULT_STEPS_PER_BAR = 192;
1021
+
1003
1022
  // src/lyrics.ts
1004
1023
  var kanaTable = {
1005
1024
  \u3042: ["", "a"],
@@ -1170,9 +1189,10 @@ var parseLyrics = (mml) => {
1170
1189
  const trackId = Number.parseInt(m[1], 10);
1171
1190
  const tokens = m[2].trim().split(/\s+/);
1172
1191
  const modelToken = tokens.shift() ?? "";
1173
- let volume = 300;
1192
+ let volume = DEFAULT_VOCAL_VOLUME;
1174
1193
  let gate = 100;
1175
1194
  let pan = 64;
1195
+ let octave = 0;
1176
1196
  const colon = modelToken.indexOf(":");
1177
1197
  const model = (colon === -1 ? modelToken : modelToken.slice(0, colon)).toLowerCase();
1178
1198
  if (colon !== -1) {
@@ -1184,12 +1204,15 @@ var parseLyrics = (mml) => {
1184
1204
  const v = /^v(\d+)$/.exec(tokens[0]);
1185
1205
  const q2 = /^q(\d+)$/.exec(tokens[0]);
1186
1206
  const p = /^p(\d+)$/.exec(tokens[0]);
1207
+ const o = /^o(-?\d+)$/.exec(tokens[0]);
1187
1208
  if (v) {
1188
1209
  volume = clamp(Number.parseInt(v[1], 10), 0, MAX_VOCAL_VOLUME);
1189
1210
  } else if (q2) {
1190
1211
  gate = clamp(Number.parseInt(q2[1], 10), 0, 100);
1191
1212
  } else if (p) {
1192
1213
  pan = clamp(Number.parseInt(p[1], 10), 0, 127);
1214
+ } else if (o) {
1215
+ octave = clamp(Number.parseInt(o[1], 10), -2, 2);
1193
1216
  } else {
1194
1217
  break;
1195
1218
  }
@@ -1206,6 +1229,7 @@ var parseLyrics = (mml) => {
1206
1229
  volume,
1207
1230
  gate,
1208
1231
  pan,
1232
+ octave,
1209
1233
  syllables,
1210
1234
  metaText: metaTokens.join(" "),
1211
1235
  ...lineBreaks.length > 0 ? { lineBreaks } : {}
@@ -1239,9 +1263,9 @@ var createLyricsConductor = (lyrics) => {
1239
1263
  return {
1240
1264
  model: track.model,
1241
1265
  syllable,
1242
- volume: vocalVolumeToGain(track.volume ?? 300),
1243
- gate: (track.gate ?? 100) / 100,
1244
- pan: panToStereo(track.pan ?? 64)
1266
+ volume: vocalVolumeToGain(track.volume ?? DEFAULT_VOCAL_VOLUME),
1267
+ gate: (track.gate ?? DEFAULT_GATE) / 100,
1268
+ pan: panToStereo(track.pan ?? DEFAULT_PAN)
1245
1269
  };
1246
1270
  };
1247
1271
  const reset = () => pointers.clear();
@@ -1349,7 +1373,8 @@ var KOE_VOICEBANKS = {
1349
1373
  tsukuyomi: "\u3064\u304F\u3088\u307F\u3061\u3083\u3093.koe",
1350
1374
  rino: "\u6625\u97F3\u30EA\u30CEver0.3.koe",
1351
1375
  roze: "\u675F\u97F3\u30ED\u30BCver0.\uFF151(\u591A\u97F3\u968E).koe",
1352
- ruko: "\u6B32\u97F3\u30EB\u30B3\u2640\u6B4C\u9023\u7D9A\u97F3\u666E1.00.koe",
1376
+ ruko_male: "\u6B32\u97F3\u30EB\u30B3\u2642\u9023\u7D9A\u97F3Ver.1.03.koe",
1377
+ ruko_female: "\u6B32\u97F3\u30EB\u30B3\u2640\u6B4C\u9023\u7D9A\u97F3\u666E1.00.koe",
1353
1378
  teto: "\u91CD\u97F3\u30C6\u30C8\u5358\u72EC\u97F3.koe",
1354
1379
  shiyo: "\u9769\u547D\u30B7\u30E8.koe"
1355
1380
  };
@@ -1357,10 +1382,30 @@ var KOE_VOICEBANK_LABELS = {
1357
1382
  tsukuyomi: "\u3064\u304F\u3088\u307F\u3061\u3083\u3093",
1358
1383
  rino: "\u6625\u97F3\u30EA\u30CE",
1359
1384
  roze: "\u675F\u97F3\u30ED\u30BC",
1360
- ruko: "\u6B32\u97F3\u30EB\u30B3",
1385
+ ruko_male: "\u6B32\u97F3\u30EB\u30B3\u2642",
1386
+ ruko_female: "\u6B32\u97F3\u30EB\u30B3\u2640",
1361
1387
  teto: "\u91CD\u97F3\u30C6\u30C8",
1362
1388
  shiyo: "\u9769\u547D\u30B7\u30E8"
1363
1389
  };
1390
+ var VOICE_IMAGE_KEY = {
1391
+ klatt: "puyuyu",
1392
+ tsukuyomi: "tsukuyomi",
1393
+ rino: "rino",
1394
+ roze: "roze",
1395
+ ruko_male: "ruko",
1396
+ ruko_female: "ruko",
1397
+ teto: "teto",
1398
+ shiyo: "shiyo"
1399
+ };
1400
+ var KOE_VOICEBANK_TERMS = {
1401
+ tsukuyomi: "https://tyc.rei-yumesaki.net/material/utau/terms/",
1402
+ rino: "https://hatenakun1.github.io/halunelino/",
1403
+ roze: "https://tabaneroze.ninja-web.net/terms-of-use.html",
1404
+ ruko_male: "https://long-sleeper.net/index.php?id=22",
1405
+ ruko_female: "https://long-sleeper.net/index.php?id=22",
1406
+ teto: "https://kasaneteto.jp/guidelines/voice.html",
1407
+ shiyo: "https://kakumeisiyo.my.canva.site/dagkuyjwycs"
1408
+ };
1364
1409
  var koeUrl = (name, base = KOE_BASE_URL) => `${base}/${encodeURIComponent(name)}`;
1365
1410
  var DEFAULT_WORLDLINE_SCRIPT = "https://onjmin.github.io/koe/demo/world/worldline.js";
1366
1411
  var KOE_SAMPLE_RATE = 48e3;
@@ -1508,9 +1553,10 @@ var createWorkerBackend = async (workerUrl, options) => {
1508
1553
  }
1509
1554
  }
1510
1555
  };
1511
- worker.onerror = (e) => onFail?.(
1512
- new Error(`voice worker error: ${e.message || e}`)
1513
- );
1556
+ worker.onerror = (e) => {
1557
+ const ev = e;
1558
+ onFail?.(new Error(ev.message || ev.error || `Event: ${ev.type}`));
1559
+ };
1514
1560
  await new Promise((resolve, reject) => {
1515
1561
  onReady = resolve;
1516
1562
  onFail = reject;
@@ -1686,22 +1732,18 @@ var createSingingVoices = (ctx, destination, options = {}) => {
1686
1732
  if (inflight) return inflight;
1687
1733
  const koe = catalog[m];
1688
1734
  if (!koe) return Promise.resolve(null);
1689
- const p = (async () => {
1690
- let source = koe;
1691
- if (typeof source === "string") {
1692
- const res = await fetch(source);
1693
- if (!res.ok) {
1694
- throw new Error(`fetch failed: ${res.statusText}`);
1695
- }
1696
- source = await res.blob();
1697
- }
1698
- return createKoeVoice(ctx, destination, {
1699
- koe: source,
1735
+ const p = (async () => (
1736
+ // URL文字列はそのまま渡す。koe側が VoiceBank.load 内で HTTP Range により
1737
+ // マニフェストだけ先読みし、音素PCMは歌う直前にオンデマンド取得する
1738
+ // (= 初回に .koe 全体をDLしない。モバイル初回ロードの待ちを解消)。
1739
+ // Blob/File が直接渡されたケース(ローカル読み込み)はそのまま BlobVoiceSource。
1740
+ createKoeVoice(ctx, destination, {
1741
+ koe,
1700
1742
  worldlineScriptUrl: options.worldlineScriptUrl,
1701
1743
  lightweight: options.lightweight,
1702
1744
  voiceWorkerUrl: options.voiceWorkerUrl
1703
- });
1704
- })().then((v) => {
1745
+ })
1746
+ ))().then((v) => {
1705
1747
  loaded.set(m, v);
1706
1748
  return v;
1707
1749
  }).catch((err) => {
@@ -2225,7 +2267,7 @@ var exportMIDI = (options) => {
2225
2267
  (n.startStep + (n.durationSteps || 1)) * tickPerStep
2226
2268
  );
2227
2269
  const vel = Math.round(
2228
- (n.velocity ?? 100) * (track.volume || 100) / 100
2270
+ (n.velocity ?? DEFAULT_VELOCITY) * (track.volume ?? 100) / 100
2229
2271
  );
2230
2272
  events.push({ t: startTick, m: [144 | ch & 15, n.pitch, vel] });
2231
2273
  events.push({ t: endTick, m: [144 | ch & 15, n.pitch, 0] });
@@ -2780,7 +2822,7 @@ var MMLCore = class _MMLCore {
2780
2822
  startStep: step,
2781
2823
  durationSteps: options.noteLengthSteps,
2782
2824
  pitch,
2783
- velocity: options.velocity ?? 100
2825
+ velocity: options.velocity ?? DEFAULT_VELOCITY
2784
2826
  };
2785
2827
  this.notes.push(newNote);
2786
2828
  }
@@ -2955,19 +2997,15 @@ var MMLCore = class _MMLCore {
2955
2997
  notesByStep.set(n.startStep, list);
2956
2998
  }
2957
2999
  const sortedSteps = Array.from(notesByStep.keys()).sort((a, b) => a - b);
3000
+ const MIN_STEP = config.stepsPerBar / 64;
2958
3001
  const fillRests = (until) => {
2959
- while (currentCursor < until) {
3002
+ while (until - currentCursor >= MIN_STEP) {
2960
3003
  const gap = until - currentCursor;
2961
- if (gap <= 2) {
2962
- currentCursor = until;
2963
- break;
2964
- }
2965
3004
  const { dur, steps } = this.findBestFitDuration(gap);
2966
3005
  segments.push(`r${dur}`);
2967
3006
  currentCursor += steps;
2968
3007
  }
2969
3008
  };
2970
- const MIN_STEP = config.stepsPerBar / 64;
2971
3009
  for (let i = 0; i < sortedSteps.length; i++) {
2972
3010
  const startStep = sortedSteps[i];
2973
3011
  const notes = notesByStep.get(startStep);
@@ -2976,7 +3014,6 @@ var MMLCore = class _MMLCore {
2976
3014
  const nextStart = sortedSteps[i + 1] ?? endStep;
2977
3015
  const physicsLimit = nextStart - currentCursor;
2978
3016
  if (physicsLimit < MIN_STEP) {
2979
- currentCursor = startStep;
2980
3017
  continue;
2981
3018
  }
2982
3019
  const idealDuration = notes[0].durationSteps;
@@ -3101,7 +3138,7 @@ var formatMmlMeta = (meta) => {
3101
3138
  return parts.join(" ");
3102
3139
  };
3103
3140
  var parseMML = (mml, options = {}) => {
3104
- const stepsPerBar = options.stepsPerBar ?? 192;
3141
+ const stepsPerBar = options.stepsPerBar ?? DEFAULT_STEPS_PER_BAR;
3105
3142
  const collectTokens = options.collectTokens ?? false;
3106
3143
  const collectLyrics = options.collectLyrics ?? false;
3107
3144
  const clampTrackCount = options.clampTrackCount;
@@ -3178,14 +3215,14 @@ var parseMML = (mml, options = {}) => {
3178
3215
  numStr += body[j];
3179
3216
  j++;
3180
3217
  }
3181
- octave = clamp2(Number.parseInt(numStr, 10) || 4, 0, 8);
3218
+ octave = numStr ? clamp2(Number.parseInt(numStr, 10), 0, 8) : 4;
3182
3219
  pushTok("octave", currentStep, 0, tokStart);
3183
3220
  } else if (ch === ">") {
3184
- octave++;
3221
+ octave = Math.min(8, octave + 1);
3185
3222
  j++;
3186
3223
  pushTok("shift", currentStep, 0, tokStart);
3187
3224
  } else if (ch === "<") {
3188
- octave--;
3225
+ octave = Math.max(0, octave - 1);
3189
3226
  j++;
3190
3227
  pushTok("shift", currentStep, 0, tokStart);
3191
3228
  } else if (ch === "l") {
@@ -3232,10 +3269,10 @@ var parseMML = (mml, options = {}) => {
3232
3269
  }
3233
3270
  chordNotes.push((octave + 1) * 12 + pitch);
3234
3271
  } else if (c === ">") {
3235
- octave++;
3272
+ octave = Math.min(8, octave + 1);
3236
3273
  j++;
3237
3274
  } else if (c === "<") {
3238
- octave--;
3275
+ octave = Math.max(0, octave - 1);
3239
3276
  j++;
3240
3277
  } else if (c === "o") {
3241
3278
  j++;
@@ -3244,7 +3281,7 @@ var parseMML = (mml, options = {}) => {
3244
3281
  numStr += body[j];
3245
3282
  j++;
3246
3283
  }
3247
- octave = clamp2(Number.parseInt(numStr, 10) || 4, 0, 8);
3284
+ octave = numStr ? clamp2(Number.parseInt(numStr, 10), 0, 8) : 4;
3248
3285
  } else {
3249
3286
  j++;
3250
3287
  }
@@ -3319,7 +3356,7 @@ var createSequencer = (options) => {
3319
3356
  for (const note of track.notes) {
3320
3357
  const relativeStart = note.startStep - fromStep;
3321
3358
  if (relativeStart < 0) continue;
3322
- const velocity = note.velocity ?? 127;
3359
+ const velocity = note.velocity ?? DEFAULT_PLAYBACK_VELOCITY;
3323
3360
  timeline.push({
3324
3361
  trackId: track.id,
3325
3362
  pitch: note.pitch,
@@ -3938,6 +3975,13 @@ var DAW_CSS = `
3938
3975
 
3939
3976
  .dtm-hidden { display: none !important; }
3940
3977
  .dtm-grow { flex: 1 1 auto; }
3978
+ .dtm-lyric-icon {
3979
+ flex: 0 0 auto;
3980
+ width: 20px;
3981
+ height: 20px;
3982
+ border-radius: 50%;
3983
+ object-fit: cover;
3984
+ }
3941
3985
 
3942
3986
  /* \u2500\u2500\u2500 \u5E83\u5E45\u62E1\u5F35 \u2500\u2500\u2500 */
3943
3987
  @media (min-width: 768px) {
@@ -3980,13 +4024,26 @@ var DAW_CSS = `
3980
4024
  .dtm-player-play:active { transform: translate(2px, 2px); box-shadow: none; }
3981
4025
  .dtm-player-play--stop { background: var(--dtm-danger); }
3982
4026
  .dtm-player-play:disabled { opacity: 0.4; cursor: default; }
3983
- .dtm-player-tempo,
3984
- .dtm-player-time {
4027
+ .dtm-player-beat-row {
4028
+ display: flex;
4029
+ align-items: center;
4030
+ gap: 4px;
4031
+ }
4032
+ .dtm-player-beat-dot {
4033
+ width: 8px;
4034
+ height: 8px;
4035
+ border-radius: 50%;
4036
+ background: var(--dtm-border2);
4037
+ transition: background 0.06s;
4038
+ }
4039
+ .dtm-player-beat-dot--on { background: var(--dtm-primary); }
4040
+ .dtm-player-bar {
3985
4041
  font-family: 'k8x12', monospace;
3986
- font-size: 12px;
3987
- color: var(--dtm-muted);
4042
+ font-size: 11px;
4043
+ color: var(--dtm-text);
4044
+ min-width: 2em;
4045
+ margin-left: 4px;
3988
4046
  }
3989
- .dtm-player-time { color: var(--dtm-text); min-width: 3em; }
3990
4047
  .dtm-player-dots {
3991
4048
  margin-left: auto;
3992
4049
  display: flex;
@@ -3994,6 +4051,40 @@ var DAW_CSS = `
3994
4051
  gap: 6px;
3995
4052
  }
3996
4053
  .dtm-player-dot { width: 8px; height: 8px; display: inline-block; }
4054
+ .dtm-player-mml-header {
4055
+ margin-left: auto;
4056
+ display: flex;
4057
+ align-items: center;
4058
+ gap: 4px;
4059
+ }
4060
+ .dtm-player-mml-link {
4061
+ font-family: 'k8x12', monospace;
4062
+ font-size: 10px;
4063
+ color: var(--dtm-muted);
4064
+ text-decoration: none;
4065
+ white-space: nowrap;
4066
+ }
4067
+ .dtm-player-mml-link:hover { color: var(--dtm-primary); }
4068
+ .dtm-player-emoji {
4069
+ display: inline-flex;
4070
+ align-items: center;
4071
+ justify-content: center;
4072
+ width: 20px;
4073
+ height: 20px;
4074
+ border-radius: 50%;
4075
+ font-size: 18px;
4076
+ line-height: 1;
4077
+ user-select: none;
4078
+ }
4079
+ @keyframes dtm-emoji-jump {
4080
+ 0% { transform: translateY(0); }
4081
+ 35% { transform: translateY(-5px); }
4082
+ 65% { transform: translateY(-5px); }
4083
+ 100% { transform: translateY(0); }
4084
+ }
4085
+ .dtm-player-emoji--jump {
4086
+ animation: dtm-emoji-jump 0.18s ease-out forwards;
4087
+ }
3997
4088
  .dtm-player-chip {
3998
4089
  font-family: 'k8x12', monospace;
3999
4090
  font-size: 9px;
@@ -4002,6 +4093,12 @@ var DAW_CSS = `
4002
4093
  padding: 2px 6px;
4003
4094
  white-space: nowrap;
4004
4095
  }
4096
+ .dtm-player-body {
4097
+ 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 */
4098
+ display: flex;
4099
+ flex-direction: column;
4100
+ gap: var(--dtm-gap);
4101
+ }
4005
4102
  .dtm-player-lane-row {
4006
4103
  display: flex;
4007
4104
  align-items: stretch;
@@ -4016,6 +4113,12 @@ var DAW_CSS = `
4016
4113
  gap: 2px;
4017
4114
  padding-top: 4px;
4018
4115
  }
4116
+ .dtm-player-lane-label--btn {
4117
+ cursor: pointer;
4118
+ user-select: none;
4119
+ }
4120
+ .dtm-player-lane-label--btn:hover { opacity: 0.7; }
4121
+ .dtm-player-lane-label--muted { opacity: 0.3; }
4019
4122
  .dtm-player-lane-no {
4020
4123
  font-family: 'k8x12', monospace;
4021
4124
  font-size: 9px;
@@ -4098,6 +4201,38 @@ var showLoadingOverlay = (container) => {
4098
4201
  };
4099
4202
  };
4100
4203
 
4204
+ // assets/puyuyu.png
4205
+ var puyuyu_default = "data:image/png;base64,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";
4206
+
4207
+ // assets/rino.png
4208
+ var rino_default = "data:image/png;base64,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";
4209
+
4210
+ // assets/roze.png
4211
+ var roze_default = "data:image/png;base64,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";
4212
+
4213
+ // assets/ruko.png
4214
+ var ruko_default = "data:image/png;base64,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";
4215
+
4216
+ // assets/shiyo.png
4217
+ var shiyo_default = "data:image/png;base64,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";
4218
+
4219
+ // assets/teto.png
4220
+ var teto_default = "data:image/png;base64,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";
4221
+
4222
+ // assets/tsukuyomi.png
4223
+ var tsukuyomi_default = "data:image/png;base64,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";
4224
+
4225
+ // src/voice-images.ts
4226
+ var VOICE_IMAGES = {
4227
+ puyuyu: puyuyu_default,
4228
+ rino: rino_default,
4229
+ roze: roze_default,
4230
+ ruko: ruko_default,
4231
+ shiyo: shiyo_default,
4232
+ teto: teto_default,
4233
+ tsukuyomi: tsukuyomi_default
4234
+ };
4235
+
4101
4236
  // src/daw.ts
4102
4237
  var BASE_STEP_WIDTH = 0.5;
4103
4238
  var BASE_KEY_HEIGHT = 15;
@@ -4264,7 +4399,7 @@ var mountDAW = (target, options = {}) => {
4264
4399
  tracks: trackConfigs,
4265
4400
  drumPatternNames: Object.keys(drumPatterns),
4266
4401
  defaultDrumPattern: drumPatterns.dance ? "dance" : Object.keys(drumPatterns)[0] ?? "none",
4267
- defaultBpm: options.defaultBpm ?? 120,
4402
+ defaultBpm: options.defaultBpm ?? DEFAULT_BPM,
4268
4403
  showMidi,
4269
4404
  showChord
4270
4405
  });
@@ -4279,7 +4414,7 @@ var mountDAW = (target, options = {}) => {
4279
4414
  const leftPaddingSteps = renderConfig.stepsPerBar * 16;
4280
4415
  let zoomX = 100;
4281
4416
  let zoomY = 100;
4282
- let bpm = options.defaultBpm ?? 120;
4417
+ let bpm = options.defaultBpm ?? DEFAULT_BPM;
4283
4418
  let masterVolume = 50;
4284
4419
  let drumVolume = 80;
4285
4420
  let currentDrumPattern = refs.drumSelect.value;
@@ -4324,9 +4459,10 @@ var mountDAW = (target, options = {}) => {
4324
4459
  lyrics: "",
4325
4460
  lyricModel: "",
4326
4461
  // 既定は「なし」(歌わない)
4327
- vocalVolume: 300,
4462
+ vocalVolume: DEFAULT_VOCAL_VOLUME,
4328
4463
  vocalGate: 100,
4329
- vocalPan: 64
4464
+ vocalPan: 64,
4465
+ vocalOctave: 0
4330
4466
  }));
4331
4467
  };
4332
4468
  const buildLyricsMap = () => {
@@ -4343,6 +4479,7 @@ var mountDAW = (target, options = {}) => {
4343
4479
  volume: t.vocalVolume,
4344
4480
  gate: t.vocalGate,
4345
4481
  pan: t.vocalPan,
4482
+ octave: t.vocalOctave,
4346
4483
  syllables
4347
4484
  });
4348
4485
  });
@@ -4861,6 +4998,13 @@ var mountDAW = (target, options = {}) => {
4861
4998
  setDrawOffset(currentOffsetX, currentOffsetY);
4862
4999
  redrawAll();
4863
5000
  };
5001
+ const getViewState = () => ({
5002
+ zoomX,
5003
+ zoomY,
5004
+ decomposeChord: refs.decomposeChordToggle.checked,
5005
+ ignoreChordHeavy: refs.ignoreChordHeavyToggle.checked
5006
+ });
5007
+ const notifyViewState = () => options.onViewStateChange?.(getViewState());
4864
5008
  const dispatchNote = (trackId, pitch, trackVol, velocity, when, duration) => {
4865
5009
  const volume = trackVol / 100 * (velocity / 127) * (masterVolume / 100);
4866
5010
  options.onPlayNote?.({ trackId, pitch, velocity, volume, when, duration });
@@ -4920,7 +5064,8 @@ var mountDAW = (target, options = {}) => {
4920
5064
  const sorted = [...trackState?.core.getNotes() ?? []].sort(
4921
5065
  (a, b) => a.startStep - b.startStep
4922
5066
  );
4923
- const gate = (lt.gate ?? 100) / 100;
5067
+ const gate = (lt.gate ?? DEFAULT_GATE) / 100;
5068
+ const semis = (lt.octave ?? 0) * 12;
4924
5069
  const count = Math.min(sorted.length, lt.syllables.length);
4925
5070
  const notes = [];
4926
5071
  for (let i = 0; i < count; i++) {
@@ -4928,22 +5073,22 @@ var mountDAW = (target, options = {}) => {
4928
5073
  if (n.startStep < fromStep) continue;
4929
5074
  notes.push({
4930
5075
  syllable: lt.syllables[i],
4931
- pitch: n.pitch,
5076
+ pitch: n.pitch + semis,
4932
5077
  startSec: (n.startStep - fromStep) * secondsPerStep,
4933
5078
  durationSec: n.durationSteps * secondsPerStep * gate
4934
5079
  });
4935
5080
  }
4936
5081
  return {
4937
5082
  model: lt.model,
4938
- volume: vocalVolumeToGain(lt.volume ?? 300) * (masterVolume / 100),
4939
- pan: panToStereo(lt.pan ?? 64),
5083
+ volume: vocalVolumeToGain(lt.volume ?? DEFAULT_VOCAL_VOLUME) * (masterVolume / 100),
5084
+ pan: panToStereo(lt.pan ?? DEFAULT_PAN),
4940
5085
  notes
4941
5086
  };
4942
5087
  }) : [];
4943
5088
  const voices = options.singingVoices;
4944
5089
  const streaming = !!voices && streamTracks.some((t) => t.notes.length > 0);
4945
5090
  if (streaming && voices) {
4946
- const overlay = showLoadingOverlay(target);
5091
+ const overlay = showLoadingOverlay(refs.rollContainer);
4947
5092
  try {
4948
5093
  await voices.loadModels(streamTracks.map((t) => t.model));
4949
5094
  await voices.warm(streamTracks);
@@ -5036,12 +5181,25 @@ var mountDAW = (target, options = {}) => {
5036
5181
  <div class="dtm-row">
5037
5182
  <span class="dtm-label">\u266A \u6B4C\u8A5E</span>
5038
5183
  <select class="dtm-select" data-dtm="lyric-model" aria-label="\u6B4C\u5531\u30E2\u30C7\u30EB"></select>
5184
+ <img class="dtm-lyric-icon dtm-hidden" data-dtm="lyric-icon" width="20" height="20" alt="" draggable="false">
5185
+ <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">
5186
+ <option value="2">+2 oct</option>
5187
+ <option value="1">+1 oct</option>
5188
+ <option value="0">\xB10 oct</option>
5189
+ <option value="-1">-1 oct</option>
5190
+ <option value="-2">-2 oct</option>
5191
+ </select>
5039
5192
  <span class="dtm-label dtm-grow" data-dtm="lyric-count" style="text-align:right"></span>
5040
5193
  </div>
5194
+ <div class="dtm-row dtm-hidden" data-dtm="lyric-terms" style="font-size:10px;gap:4px;color:var(--dtm-warn)">
5195
+ <span>\u4F7F\u7528\u6642\u306B\u306F</span>
5196
+ <a data-dtm="lyric-terms-link" target="_blank" rel="noopener" style="color:var(--dtm-primary);text-decoration:underline"></a>
5197
+ <span>\u306E\u5229\u7528\u898F\u7D04\u306B\u5F93\u3063\u3066\u304F\u3060\u3055\u3044</span>
5198
+ </div>
5041
5199
  <div class="dtm-row" data-dtm="lyric-body" style="flex-direction:column;align-items:stretch">
5042
5200
  <div class="dtm-row">
5043
5201
  <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\u5B9A300\uFF09">
5202
+ <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
5203
  <span class="dtm-label" data-dtm="lyric-vol-label"></span>
5046
5204
  </div>
5047
5205
  <div class="dtm-row">
@@ -5055,6 +5213,12 @@ var mountDAW = (target, options = {}) => {
5055
5213
  const lyricModelSel = lyricDiv.querySelector(
5056
5214
  '[data-dtm="lyric-model"]'
5057
5215
  );
5216
+ const lyricOctaveSel = lyricDiv.querySelector(
5217
+ '[data-dtm="lyric-octave"]'
5218
+ );
5219
+ const lyricIcon = lyricDiv.querySelector(
5220
+ '[data-dtm="lyric-icon"]'
5221
+ );
5058
5222
  const lyricBody = lyricDiv.querySelector(
5059
5223
  '[data-dtm="lyric-body"]'
5060
5224
  );
@@ -5076,6 +5240,12 @@ var mountDAW = (target, options = {}) => {
5076
5240
  const lyricPanLabel = lyricDiv.querySelector(
5077
5241
  '[data-dtm="lyric-pan-label"]'
5078
5242
  );
5243
+ const lyricTerms = lyricDiv.querySelector(
5244
+ '[data-dtm="lyric-terms"]'
5245
+ );
5246
+ const lyricTermsLink = lyricDiv.querySelector(
5247
+ '[data-dtm="lyric-terms-link"]'
5248
+ );
5079
5249
  const fmtPan = (pan) => pan === 64 ? "C" : pan < 64 ? `L${64 - pan}` : `R${pan - 64}`;
5080
5250
  const addOpt = (value, label) => {
5081
5251
  const o = document.createElement("option");
@@ -5089,6 +5259,7 @@ var mountDAW = (target, options = {}) => {
5089
5259
  addOpt(active.lyricModel, lyricModelLabel(active.lyricModel));
5090
5260
  }
5091
5261
  lyricModelSel.value = active.lyricModel;
5262
+ lyricOctaveSel.value = String(active.vocalOctave);
5092
5263
  lyricInput.value = active.lyrics;
5093
5264
  lyricVol.value = String(active.vocalVolume);
5094
5265
  lyricVolLabel.textContent = String(active.vocalVolume);
@@ -5098,15 +5269,43 @@ var mountDAW = (target, options = {}) => {
5098
5269
  const n = normalizeLyrics(lyricInput.value).length;
5099
5270
  lyricCount.textContent = active.lyricModel && n > 0 ? `${n}\u97F3\u7BC0` : "";
5100
5271
  };
5272
+ const syncLyricTerms = () => {
5273
+ const url = active.lyricModel ? KOE_VOICEBANK_TERMS[active.lyricModel] : void 0;
5274
+ if (url) {
5275
+ const label = lyricModelLabel(active.lyricModel);
5276
+ lyricTermsLink.textContent = `${label}UTAU\u97F3\u6E90`;
5277
+ lyricTermsLink.href = url;
5278
+ lyricTerms.classList.remove("dtm-hidden");
5279
+ } else {
5280
+ lyricTerms.classList.add("dtm-hidden");
5281
+ }
5282
+ };
5283
+ const syncLyricIcon = () => {
5284
+ const imgKey = active.lyricModel ? VOICE_IMAGE_KEY[active.lyricModel.toLowerCase()] : void 0;
5285
+ const src = imgKey ? VOICE_IMAGES[imgKey] : void 0;
5286
+ if (src) {
5287
+ lyricIcon.src = src;
5288
+ lyricIcon.classList.remove("dtm-hidden");
5289
+ } else {
5290
+ lyricIcon.removeAttribute("src");
5291
+ lyricIcon.classList.add("dtm-hidden");
5292
+ }
5293
+ };
5101
5294
  const syncLyricVisibility = () => {
5102
5295
  lyricBody.style.display = active.lyricModel ? "" : "none";
5296
+ lyricOctaveSel.style.display = active.lyricModel ? "" : "none";
5103
5297
  updateLyricCount();
5298
+ syncLyricTerms();
5299
+ syncLyricIcon();
5104
5300
  };
5105
5301
  syncLyricVisibility();
5106
5302
  lyricModelSel.addEventListener("change", () => {
5107
5303
  active.lyricModel = lyricModelSel.value;
5108
5304
  syncLyricVisibility();
5109
5305
  });
5306
+ lyricOctaveSel.addEventListener("change", () => {
5307
+ active.vocalOctave = Number.parseInt(lyricOctaveSel.value, 10);
5308
+ });
5110
5309
  lyricInput.addEventListener("input", () => {
5111
5310
  active.lyrics = lyricInput.value;
5112
5311
  updateLyricCount();
@@ -5255,12 +5454,14 @@ var mountDAW = (target, options = {}) => {
5255
5454
  model: t.lyricModel.trim(),
5256
5455
  vol: t.vocalVolume,
5257
5456
  gate: t.vocalGate,
5258
- pan: t.vocalPan
5457
+ pan: t.vocalPan,
5458
+ oct: t.vocalOctave
5259
5459
  })).filter((x) => x.model.length > 0 && x.text.length > 0).map((x) => {
5260
5460
  const params = [
5261
- x.vol === 300 ? "" : `v${x.vol}`,
5461
+ x.vol === DEFAULT_VOCAL_VOLUME ? "" : `v${x.vol}`,
5262
5462
  x.gate === 100 ? "" : `q${x.gate}`,
5263
- x.pan === 64 ? "" : `p${x.pan}`
5463
+ x.pan === 64 ? "" : `p${x.pan}`,
5464
+ x.oct === 0 ? "" : `o${x.oct}`
5264
5465
  ].filter((s) => s.length > 0).join(" ");
5265
5466
  const head = params ? `${x.model} ${params}` : x.model;
5266
5467
  return `@@${x.i} ${head} ${x.text}`;
@@ -5341,6 +5542,7 @@ var mountDAW = (target, options = {}) => {
5341
5542
  if (meta.drum && drumPatterns[meta.drum]) {
5342
5543
  currentDrumPattern = meta.drum;
5343
5544
  refs.drumSelect.value = meta.drum;
5545
+ options.onDrumChange?.(meta.drum);
5344
5546
  }
5345
5547
  if (meta.volume !== void 0) {
5346
5548
  masterVolume = meta.volume;
@@ -5350,9 +5552,10 @@ var mountDAW = (target, options = {}) => {
5350
5552
  for (const t of trackStates) {
5351
5553
  t.lyrics = "";
5352
5554
  t.lyricModel = "";
5353
- t.vocalVolume = 300;
5555
+ t.vocalVolume = DEFAULT_VOCAL_VOLUME;
5354
5556
  t.vocalGate = 100;
5355
5557
  t.vocalPan = 64;
5558
+ t.vocalOctave = 0;
5356
5559
  }
5357
5560
  lyrics?.forEach((lt, idx) => {
5358
5561
  const t = trackStates[idx];
@@ -5362,6 +5565,7 @@ var mountDAW = (target, options = {}) => {
5362
5565
  t.vocalVolume = lt.volume;
5363
5566
  t.vocalGate = lt.gate;
5364
5567
  t.vocalPan = lt.pan;
5568
+ t.vocalOctave = lt.octave ?? 0;
5365
5569
  });
5366
5570
  for (const p of placements) {
5367
5571
  const t = trackStates[p.trackIndex];
@@ -5513,25 +5717,32 @@ var mountDAW = (target, options = {}) => {
5513
5717
  refs.zoomXIn.addEventListener("click", () => {
5514
5718
  zoomX = Math.min(200, zoomX + 25);
5515
5719
  applyZoomX();
5720
+ notifyViewState();
5516
5721
  });
5517
5722
  refs.zoomXOut.addEventListener("click", () => {
5518
5723
  zoomX = Math.max(25, zoomX - 25);
5519
5724
  applyZoomX();
5725
+ notifyViewState();
5520
5726
  });
5521
5727
  refs.zoomYIn.addEventListener("click", () => {
5522
5728
  zoomY = Math.min(200, zoomY + 25);
5523
5729
  applyZoomY();
5730
+ notifyViewState();
5524
5731
  });
5525
5732
  refs.zoomYOut.addEventListener("click", () => {
5526
5733
  zoomY = Math.max(50, zoomY - 25);
5527
5734
  applyZoomY();
5735
+ notifyViewState();
5528
5736
  });
5737
+ refs.decomposeChordToggle.addEventListener("change", notifyViewState);
5738
+ refs.ignoreChordHeavyToggle.addEventListener("change", notifyViewState);
5529
5739
  refs.masterVolume.addEventListener("input", () => {
5530
5740
  masterVolume = Number.parseInt(refs.masterVolume.value, 10) || 0;
5531
5741
  refs.masterVolumeLabel.textContent = `${masterVolume}%`;
5532
5742
  });
5533
5743
  refs.drumSelect.addEventListener("change", () => {
5534
5744
  currentDrumPattern = refs.drumSelect.value;
5745
+ options.onDrumChange?.(currentDrumPattern);
5535
5746
  });
5536
5747
  refs.drumVolume.addEventListener("input", () => {
5537
5748
  drumVolume = Number.parseInt(refs.drumVolume.value, 10) || 0;
@@ -5724,6 +5935,30 @@ var mountDAW = (target, options = {}) => {
5724
5935
  setInstrument: (name) => {
5725
5936
  currentInstrument = name;
5726
5937
  },
5938
+ getDrum: () => currentDrumPattern,
5939
+ setDrum: (name) => {
5940
+ if (name !== "none" && !drumPatterns[name]) return;
5941
+ currentDrumPattern = name;
5942
+ refs.drumSelect.value = name;
5943
+ options.onDrumChange?.(name);
5944
+ },
5945
+ getViewState,
5946
+ setViewState: (state) => {
5947
+ if (typeof state.zoomX === "number") {
5948
+ zoomX = clamp3(state.zoomX, 25, 200);
5949
+ applyZoomX();
5950
+ }
5951
+ if (typeof state.zoomY === "number") {
5952
+ zoomY = clamp3(state.zoomY, 50, 200);
5953
+ applyZoomY();
5954
+ }
5955
+ if (typeof state.decomposeChord === "boolean") {
5956
+ refs.decomposeChordToggle.checked = state.decomposeChord;
5957
+ }
5958
+ if (typeof state.ignoreChordHeavy === "boolean") {
5959
+ refs.ignoreChordHeavyToggle.checked = state.ignoreChordHeavy;
5960
+ }
5961
+ },
5727
5962
  loadMML,
5728
5963
  loadMIDI,
5729
5964
  exportMIDI: exportMIDI2,
@@ -5849,11 +6084,6 @@ var STEPS_PER_BEAT3 = 48;
5849
6084
  var STEPS_PER_BAR = 192;
5850
6085
  var DEFAULT_TRACK_COLORS = ["#00e436", "#29adff", "#ff77a8", "#ffec27"];
5851
6086
  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
6087
  var freqFromPitch = (pitch) => 440 * 2 ** ((pitch - 69) / 12);
5858
6088
  var mountMmlPlayer = (target, mml, options = {}) => {
5859
6089
  injectStyles(target.ownerDocument ?? document);
@@ -5868,7 +6098,7 @@ var mountMmlPlayer = (target, mml, options = {}) => {
5868
6098
  collectLyrics: true
5869
6099
  });
5870
6100
  const lyricTracks = lyrics ?? /* @__PURE__ */ new Map();
5871
- const bpm = parsedBpm ?? options.defaultBpm ?? 120;
6101
+ const bpm = parsedBpm ?? options.defaultBpm ?? DEFAULT_BPM;
5872
6102
  const drumPatternDict = options.drumPatterns ?? DRUM_PATTERNS;
5873
6103
  const drumPattern = meta.drum ? drumPatternDict[meta.drum] ?? null : null;
5874
6104
  const trackVolume = meta.volume ?? options.volume ?? 100;
@@ -5983,32 +6213,118 @@ var mountMmlPlayer = (target, mml, options = {}) => {
5983
6213
  playBtn.className = "dtm-player-play";
5984
6214
  playBtn.innerHTML = icon("play", 12);
5985
6215
  playBtn.disabled = trackIndices.length === 0;
5986
- const tempoEl = doc.createElement("span");
5987
- tempoEl.className = "dtm-player-tempo";
5988
- tempoEl.textContent = `\u2669=${bpm}`;
5989
- const timeEl = doc.createElement("span");
5990
- timeEl.className = "dtm-player-time";
5991
- timeEl.textContent = "00:00";
6216
+ const mmlHeader = doc.createElement("div");
6217
+ mmlHeader.className = "dtm-player-mml-header";
6218
+ const emojiEls = [];
6219
+ const emojiByTrack = /* @__PURE__ */ new Map();
6220
+ for (const index of trackIndices) {
6221
+ const em = doc.createElement("span");
6222
+ em.className = "dtm-player-emoji";
6223
+ em.style.backgroundColor = colorOf(index);
6224
+ em.textContent = "\u{1F97A}";
6225
+ mmlHeader.appendChild(em);
6226
+ emojiEls.push(em);
6227
+ emojiByTrack.set(index, em);
6228
+ }
6229
+ const promotedToImage = /* @__PURE__ */ new Set();
6230
+ for (const [index, lt] of lyricTracks) {
6231
+ const em = emojiByTrack.get(index);
6232
+ if (!em) continue;
6233
+ const imgKey = VOICE_IMAGE_KEY[lt.model.toLowerCase()];
6234
+ const src = imgKey ? VOICE_IMAGES[imgKey] : void 0;
6235
+ if (!src) continue;
6236
+ const img = doc.createElement("img");
6237
+ img.src = src;
6238
+ img.width = 20;
6239
+ img.height = 20;
6240
+ img.style.borderRadius = "50%";
6241
+ img.style.objectFit = "cover";
6242
+ img.draggable = false;
6243
+ promotedToImage.add(em);
6244
+ em.textContent = "";
6245
+ em.appendChild(img);
6246
+ }
6247
+ const JUMP_DEDUPE_MS = 50;
6248
+ const lastJumpAt = /* @__PURE__ */ new WeakMap();
6249
+ const jumpEmoji = (em) => {
6250
+ const now = performance.now();
6251
+ const prev = lastJumpAt.get(em);
6252
+ if (prev !== void 0 && now - prev < JUMP_DEDUPE_MS) return;
6253
+ lastJumpAt.set(em, now);
6254
+ em.classList.remove("dtm-player-emoji--jump");
6255
+ void em.offsetWidth;
6256
+ em.classList.add("dtm-player-emoji--jump");
6257
+ };
6258
+ const jumpTimers = [];
6259
+ const jumpEmojiAt = (em, when) => {
6260
+ if (when <= 0) {
6261
+ jumpEmoji(em);
6262
+ return;
6263
+ }
6264
+ jumpTimers.push(setTimeout(() => jumpEmoji(em), when * 1e3));
6265
+ };
6266
+ const clearJumpTimers = () => {
6267
+ for (const t of jumpTimers) clearTimeout(t);
6268
+ jumpTimers.length = 0;
6269
+ };
6270
+ const blinkTimers = [];
6271
+ const scheduleBlink = (em) => {
6272
+ const delay = 2e3 + Math.random() * 5e3;
6273
+ const t = setTimeout(() => {
6274
+ if (promotedToImage.has(em)) return;
6275
+ em.textContent = "\u{1F60C}";
6276
+ const t2 = setTimeout(
6277
+ () => {
6278
+ if (promotedToImage.has(em)) return;
6279
+ em.textContent = "\u{1F97A}";
6280
+ scheduleBlink(em);
6281
+ },
6282
+ 200 + Math.random() * 150
6283
+ );
6284
+ blinkTimers.push(t2);
6285
+ }, delay);
6286
+ blinkTimers.push(t);
6287
+ };
6288
+ for (const em of emojiEls) scheduleBlink(em);
5992
6289
  const dots = doc.createElement("div");
5993
6290
  dots.className = "dtm-player-dots";
6291
+ dots.style.display = "none";
5994
6292
  for (const index of trackIndices) {
5995
6293
  const dot = doc.createElement("span");
5996
6294
  dot.className = "dtm-player-dot";
5997
6295
  dot.style.backgroundColor = colorOf(index);
5998
6296
  dots.appendChild(dot);
5999
6297
  }
6000
- head.append(playBtn, tempoEl, timeEl);
6001
- const addChip = (label) => {
6298
+ const beatRow = doc.createElement("div");
6299
+ beatRow.className = "dtm-player-beat-row";
6300
+ const beatDots = [];
6301
+ for (let i = 0; i < 4; i++) {
6302
+ const d = doc.createElement("span");
6303
+ d.className = "dtm-player-beat-dot";
6304
+ beatRow.appendChild(d);
6305
+ beatDots.push(d);
6306
+ }
6307
+ const barEl = doc.createElement("span");
6308
+ barEl.className = "dtm-player-bar";
6309
+ barEl.textContent = "-";
6310
+ beatRow.appendChild(barEl);
6311
+ const chips = [];
6312
+ const makeChip = (label) => {
6002
6313
  const chip = doc.createElement("span");
6003
6314
  chip.className = "dtm-player-chip";
6004
6315
  chip.textContent = label;
6005
- head.appendChild(chip);
6316
+ chips.push(chip);
6317
+ return chip;
6006
6318
  };
6007
- if (meta.instrument) addChip(`\u266A ${meta.instrument}`);
6008
- if (meta.drum) addChip(`\u{1F941} ${meta.drum}${drumPattern ? "" : " (?)"}`);
6009
- if (meta.volume !== void 0) addChip(`\u{1F50A} ${meta.volume}%`);
6010
- head.appendChild(dots);
6319
+ if (meta.instrument) makeChip(`\u266A ${meta.instrument}`);
6320
+ if (meta.drum) makeChip(`\u{1F941} ${meta.drum}${drumPattern ? "" : " (?)"}`);
6321
+ if (meta.volume !== void 0) makeChip(`\u{1F50A} ${meta.volume}%`);
6322
+ head.append(playBtn, beatRow, ...chips, dots, mmlHeader);
6011
6323
  root.appendChild(head);
6324
+ const body = doc.createElement("div");
6325
+ body.className = "dtm-player-body";
6326
+ root.appendChild(body);
6327
+ const mutedTracks = /* @__PURE__ */ new Set();
6012
6328
  const laneViews = [];
6013
6329
  for (const index of trackIndices) {
6014
6330
  const lyricTrack = lyricTracks.get(index);
@@ -6016,7 +6332,7 @@ var mountMmlPlayer = (target, mml, options = {}) => {
6016
6332
  const row = doc.createElement("div");
6017
6333
  row.className = "dtm-player-lane-row";
6018
6334
  const label = doc.createElement("div");
6019
- label.className = "dtm-player-lane-label";
6335
+ label.className = "dtm-player-lane-label dtm-player-lane-label--btn";
6020
6336
  const swatch = doc.createElement("span");
6021
6337
  swatch.className = "dtm-player-dot";
6022
6338
  swatch.style.backgroundColor = colorOf(index);
@@ -6024,13 +6340,22 @@ var mountMmlPlayer = (target, mml, options = {}) => {
6024
6340
  no.className = "dtm-player-lane-no";
6025
6341
  no.textContent = `@${index}`;
6026
6342
  label.append(swatch, no);
6343
+ label.addEventListener("click", () => {
6344
+ if (mutedTracks.has(index)) {
6345
+ mutedTracks.delete(index);
6346
+ label.classList.remove("dtm-player-lane-label--muted");
6347
+ } else {
6348
+ mutedTracks.add(index);
6349
+ label.classList.add("dtm-player-lane-label--muted");
6350
+ }
6351
+ });
6027
6352
  const lane = doc.createElement("div");
6028
6353
  lane.className = "dtm-player-lane";
6029
6354
  lane.style.setProperty("--tk", colorOf(index));
6030
6355
  const laneTokens = [];
6031
6356
  if (isLyricLane) {
6032
6357
  const notes = placements.filter((p) => p.trackIndex === index).sort((a, b) => a.startStep - b.startStep);
6033
- const gateScale = (lyricTrack.gate ?? 100) / 100;
6358
+ const gateScale = (lyricTrack.gate ?? DEFAULT_GATE) / 100;
6034
6359
  const breaks = new Set(lyricTrack.lineBreaks ?? []);
6035
6360
  if (lyricTrack.metaText) {
6036
6361
  const metaEl = doc.createElement("span");
@@ -6077,9 +6402,46 @@ var mountMmlPlayer = (target, mml, options = {}) => {
6077
6402
  }
6078
6403
  }
6079
6404
  row.append(label, lane);
6080
- root.appendChild(row);
6405
+ body.appendChild(row);
6081
6406
  laneViews.push({ lane, tokens: laneTokens });
6082
6407
  }
6408
+ const termsModels = [
6409
+ ...new Set([...lyricTracks.values()].map((lt) => lt.model))
6410
+ ].filter((model) => KOE_VOICEBANK_TERMS[model]);
6411
+ if (termsModels.length > 0) {
6412
+ const termsDiv = doc.createElement("div");
6413
+ termsDiv.className = "dtm-player-terms";
6414
+ termsDiv.style.fontSize = "10px";
6415
+ termsDiv.style.color = "var(--dtm-warn)";
6416
+ termsDiv.style.display = "flex";
6417
+ termsDiv.style.flexDirection = "column";
6418
+ termsDiv.style.gap = "4px";
6419
+ termsDiv.style.marginTop = "4px";
6420
+ termsDiv.style.padding = "0 4px";
6421
+ for (const model of termsModels) {
6422
+ const termsRow = doc.createElement("div");
6423
+ termsRow.style.display = "flex";
6424
+ termsRow.style.alignItems = "center";
6425
+ termsRow.style.gap = "4px";
6426
+ termsRow.style.flexWrap = "wrap";
6427
+ const label = KOE_VOICEBANK_LABELS[model] ?? model;
6428
+ const url = KOE_VOICEBANK_TERMS[model];
6429
+ const span1 = doc.createElement("span");
6430
+ span1.textContent = "\u4F7F\u7528\u6642\u306B\u306F";
6431
+ const a = doc.createElement("a");
6432
+ a.textContent = `${label}UTAU\u97F3\u6E90`;
6433
+ a.href = url;
6434
+ a.target = "_blank";
6435
+ a.rel = "noopener";
6436
+ a.style.color = "var(--dtm-primary)";
6437
+ a.style.textDecoration = "underline";
6438
+ const span2 = doc.createElement("span");
6439
+ span2.textContent = "\u306E\u5229\u7528\u898F\u7D04\u306B\u5F93\u3063\u3066\u304F\u3060\u3055\u3044";
6440
+ termsRow.append(span1, a, span2);
6441
+ termsDiv.appendChild(termsRow);
6442
+ }
6443
+ root.appendChild(termsDiv);
6444
+ }
6083
6445
  target.appendChild(root);
6084
6446
  const autoScroll = (lane, el) => {
6085
6447
  if (el.offsetWidth === 0 || lane.clientWidth === 0) return;
@@ -6089,7 +6451,10 @@ var mountMmlPlayer = (target, mml, options = {}) => {
6089
6451
  lane.scrollLeft = Math.max(0, Math.min(next, maxScroll));
6090
6452
  };
6091
6453
  const renderPlayhead = (step) => {
6092
- timeEl.textContent = formatTime(Math.max(0, step) * secondsPerStep);
6454
+ const beatIndex = Math.floor(step / STEPS_PER_BEAT3) % 4;
6455
+ for (let i = 0; i < 4; i++)
6456
+ beatDots[i].classList.toggle("dtm-player-beat-dot--on", i === beatIndex);
6457
+ barEl.textContent = String(Math.floor(step / STEPS_PER_BAR) + 1);
6093
6458
  for (const view of laneViews) {
6094
6459
  let active = null;
6095
6460
  for (const t of view.tokens) {
@@ -6101,7 +6466,8 @@ var mountMmlPlayer = (target, mml, options = {}) => {
6101
6466
  }
6102
6467
  };
6103
6468
  const resetPlayhead = () => {
6104
- timeEl.textContent = "00:00";
6469
+ for (const d of beatDots) d.classList.remove("dtm-player-beat-dot--on");
6470
+ barEl.textContent = "-";
6105
6471
  for (const view of laneViews) {
6106
6472
  for (const t of view.tokens) t.el.classList.remove("is-active");
6107
6473
  view.lane.scrollLeft = 0;
@@ -6115,11 +6481,17 @@ var mountMmlPlayer = (target, mml, options = {}) => {
6115
6481
  getSoloTrackId: () => null,
6116
6482
  getAudioTime,
6117
6483
  onPlayNote: (e) => {
6118
- if (lyricTracks.has(Number(e.trackId))) return;
6484
+ const trackIdx = Number(e.trackId);
6485
+ if (mutedTracks.has(trackIdx)) return;
6486
+ const em = emojiByTrack.get(trackIdx);
6487
+ if (em) jumpEmojiAt(em, e.when);
6488
+ if (lyricTracks.has(trackIdx)) return;
6119
6489
  options.onPlayNote?.(e);
6120
6490
  if (useSynth) synthPlay(e);
6121
6491
  },
6122
6492
  onPlayDrum: (e) => {
6493
+ const em = emojiEls[0];
6494
+ if (em) jumpEmojiAt(em, e.when);
6123
6495
  const velocity = e.velocity * (trackVolume / 100);
6124
6496
  options.onPlayDrum?.({ ...e, velocity });
6125
6497
  if (useSynth) drumSynth({ ...e, velocity });
@@ -6138,6 +6510,7 @@ var mountMmlPlayer = (target, mml, options = {}) => {
6138
6510
  };
6139
6511
  const finish = () => {
6140
6512
  setPlayingUI(false);
6513
+ clearJumpTimers();
6141
6514
  resetPlayhead();
6142
6515
  if (activePlayer === instance) activePlayer = null;
6143
6516
  };
@@ -6146,22 +6519,23 @@ var mountMmlPlayer = (target, mml, options = {}) => {
6146
6519
  const sorted = [...seqTrack?.notes ?? []].sort(
6147
6520
  (a, b) => a.startStep - b.startStep
6148
6521
  );
6149
- const gate = (lt.gate ?? 100) / 100;
6522
+ const gate = (lt.gate ?? DEFAULT_GATE) / 100;
6523
+ const semis = (lt.octave ?? 0) * 12;
6150
6524
  const count = Math.min(sorted.length, lt.syllables.length);
6151
6525
  const notes = [];
6152
6526
  for (let i = 0; i < count; i++) {
6153
6527
  const n = sorted[i];
6154
6528
  notes.push({
6155
6529
  syllable: lt.syllables[i],
6156
- pitch: n.pitch,
6530
+ pitch: n.pitch + semis,
6157
6531
  startSec: n.startStep * secondsPerStep,
6158
6532
  durationSec: n.durationSteps * secondsPerStep * gate
6159
6533
  });
6160
6534
  }
6161
6535
  return {
6162
6536
  model: lt.model,
6163
- volume: vocalVolumeToGain(lt.volume ?? 300) * (trackVolume / 100),
6164
- pan: panToStereo(lt.pan ?? 64),
6537
+ volume: vocalVolumeToGain(lt.volume ?? DEFAULT_VOCAL_VOLUME) * (trackVolume / 100),
6538
+ pan: panToStereo(lt.pan ?? DEFAULT_PAN),
6165
6539
  notes
6166
6540
  };
6167
6541
  });
@@ -6170,7 +6544,7 @@ var mountMmlPlayer = (target, mml, options = {}) => {
6170
6544
  const tracks = streaming ? buildStreamTracks() : [];
6171
6545
  if (streaming) {
6172
6546
  const v = ensureVoices();
6173
- const overlay = showLoadingOverlay(root);
6547
+ const overlay = showLoadingOverlay(body);
6174
6548
  try {
6175
6549
  await v.loadModels(tracks.map((t) => t.model));
6176
6550
  await v.warm(tracks);
@@ -6215,6 +6589,8 @@ var mountMmlPlayer = (target, mml, options = {}) => {
6215
6589
  void audioCtx.close();
6216
6590
  audioCtx = null;
6217
6591
  }
6592
+ for (const t of blinkTimers) clearTimeout(t);
6593
+ clearJumpTimers();
6218
6594
  root.remove();
6219
6595
  };
6220
6596
  const instance = {
@@ -6511,6 +6887,13 @@ var createPianoRoll = (options, handlers) => {
6511
6887
  // Annotate the CommonJS export names for ESM import in node:
6512
6888
  0 && (module.exports = {
6513
6889
  DAW_CSS,
6890
+ DEFAULT_BPM,
6891
+ DEFAULT_GATE,
6892
+ DEFAULT_PAN,
6893
+ DEFAULT_PLAYBACK_VELOCITY,
6894
+ DEFAULT_STEPS_PER_BAR,
6895
+ DEFAULT_VELOCITY,
6896
+ DEFAULT_VOCAL_VOLUME,
6514
6897
  DRUM_FONT,
6515
6898
  DRUM_KEYS,
6516
6899
  DRUM_PATTERNS,
@@ -6518,6 +6901,7 @@ var createPianoRoll = (options, handlers) => {
6518
6901
  KOE_BASE_URL,
6519
6902
  KOE_VOICEBANKS,
6520
6903
  KOE_VOICEBANK_LABELS,
6904
+ KOE_VOICEBANK_TERMS,
6521
6905
  LinkedList,
6522
6906
  MAX_VOCAL_VOLUME,
6523
6907
  MMLCore,
@@ -6525,6 +6909,7 @@ var createPianoRoll = (options, handlers) => {
6525
6909
  PREWARM_NOTES,
6526
6910
  TRACKS_ADVANCED,
6527
6911
  TRACKS_SIMPLE,
6912
+ VOICE_IMAGE_KEY,
6528
6913
  analyzeMidiTracks,
6529
6914
  applyHarmonicFilter,
6530
6915
  applyMonophonic,