@onjmin/dtm 0.1.47 → 0.1.49
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +55 -2
- package/dist/index.d.ts +55 -2
- package/dist/index.js +408 -51
- package/dist/index.mjs +405 -51
- package/dist/voice-worker.js +90 -25
- package/package.json +3 -3
package/dist/index.mjs
CHANGED
|
@@ -1719,7 +1719,7 @@ var INSTRUMENT_PRESETS = {
|
|
|
1719
1719
|
}
|
|
1720
1720
|
};
|
|
1721
1721
|
|
|
1722
|
-
// node_modules/.pnpm/@onjmin+koe@1.0.
|
|
1722
|
+
// node_modules/.pnpm/@onjmin+koe@1.0.4/node_modules/@onjmin/koe/dist/index.js
|
|
1723
1723
|
var MAGIC = 1263486208;
|
|
1724
1724
|
function parseKoeHeader(headerBytes) {
|
|
1725
1725
|
const view = new DataView(headerBytes);
|
|
@@ -1729,6 +1729,8 @@ function parseKoeHeader(headerBytes) {
|
|
|
1729
1729
|
return { jsonLength: view.getUint32(4, true) };
|
|
1730
1730
|
}
|
|
1731
1731
|
var pcmBase = (jsonLength) => 8 + jsonLength;
|
|
1732
|
+
var MAX_PHONEME_SAMPLES = 5242880;
|
|
1733
|
+
var MAX_JSON_LENGTH = 50 * 1024 * 1024;
|
|
1732
1734
|
var BlobVoiceSource = class {
|
|
1733
1735
|
constructor(blob2, base) {
|
|
1734
1736
|
this.blob = blob2;
|
|
@@ -1750,22 +1752,60 @@ var RangeVoiceSource = class {
|
|
|
1750
1752
|
base;
|
|
1751
1753
|
async readBytes(offset, length) {
|
|
1752
1754
|
const start = this.base + offset;
|
|
1753
|
-
|
|
1754
|
-
headers: { Range: `bytes=${start}-${start + length - 1}` }
|
|
1755
|
-
});
|
|
1756
|
-
if (!res.ok && res.status !== 206) {
|
|
1757
|
-
throw new Error(`.koe range request failed: ${res.status}`);
|
|
1758
|
-
}
|
|
1759
|
-
return res.arrayBuffer();
|
|
1755
|
+
return rangeFetch(this.url, start, length);
|
|
1760
1756
|
}
|
|
1761
1757
|
};
|
|
1762
1758
|
async function rangeFetch(url2, start, length) {
|
|
1763
1759
|
const res = await fetch(url2, {
|
|
1764
|
-
headers: { Range: `bytes=${start}-${start + length - 1}` }
|
|
1760
|
+
headers: { Range: `bytes=${start}-${start + length - 1}` },
|
|
1761
|
+
credentials: "omit"
|
|
1762
|
+
// never leak cookies / auth to a MML-supplied URL
|
|
1765
1763
|
});
|
|
1766
|
-
if (
|
|
1767
|
-
throw new Error(
|
|
1768
|
-
|
|
1764
|
+
if (res.status !== 206) {
|
|
1765
|
+
throw new Error(
|
|
1766
|
+
`.koe fetch failed: expected 206 Partial Content, got ${res.status}`
|
|
1767
|
+
);
|
|
1768
|
+
}
|
|
1769
|
+
return readCapped(res, length);
|
|
1770
|
+
}
|
|
1771
|
+
async function readCapped(res, length) {
|
|
1772
|
+
const reader = res.body?.getReader();
|
|
1773
|
+
if (!reader) {
|
|
1774
|
+
const buf = await res.arrayBuffer();
|
|
1775
|
+
if (buf.byteLength > length) {
|
|
1776
|
+
throw new Error(
|
|
1777
|
+
`.koe fetch failed: response exceeds requested ${length} bytes`
|
|
1778
|
+
);
|
|
1779
|
+
}
|
|
1780
|
+
return buf;
|
|
1781
|
+
}
|
|
1782
|
+
const out = new Uint8Array(length);
|
|
1783
|
+
let received = 0;
|
|
1784
|
+
for (; ; ) {
|
|
1785
|
+
const { done, value } = await reader.read();
|
|
1786
|
+
if (done) break;
|
|
1787
|
+
if (received + value.byteLength > length) {
|
|
1788
|
+
await reader.cancel();
|
|
1789
|
+
throw new Error(
|
|
1790
|
+
`.koe fetch failed: response exceeds requested ${length} bytes`
|
|
1791
|
+
);
|
|
1792
|
+
}
|
|
1793
|
+
out.set(value, received);
|
|
1794
|
+
received += value.byteLength;
|
|
1795
|
+
}
|
|
1796
|
+
return received === length ? out.buffer : out.buffer.slice(0, received);
|
|
1797
|
+
}
|
|
1798
|
+
function validateJsonLength(jsonLength) {
|
|
1799
|
+
if (!Number.isInteger(jsonLength) || jsonLength < 0 || jsonLength > MAX_JSON_LENGTH) {
|
|
1800
|
+
throw new Error(`manifest JSON length out of bounds: ${jsonLength}`);
|
|
1801
|
+
}
|
|
1802
|
+
}
|
|
1803
|
+
function parseManifest(json) {
|
|
1804
|
+
const manifest = JSON.parse(new TextDecoder().decode(json));
|
|
1805
|
+
if (!manifest || typeof manifest !== "object" || typeof manifest.phonemes !== "object" || manifest.phonemes === null) {
|
|
1806
|
+
throw new Error("invalid manifest: missing phonemes table");
|
|
1807
|
+
}
|
|
1808
|
+
return manifest;
|
|
1769
1809
|
}
|
|
1770
1810
|
var VoiceBank = class _VoiceBank {
|
|
1771
1811
|
constructor(manifest, source) {
|
|
@@ -1779,20 +1819,41 @@ var VoiceBank = class _VoiceBank {
|
|
|
1779
1819
|
* @param koe a Blob/File of the .koe archive, or a URL (served with Range support)
|
|
1780
1820
|
*/
|
|
1781
1821
|
static async load(koe) {
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1822
|
+
try {
|
|
1823
|
+
if (typeof koe === "string") {
|
|
1824
|
+
if (/^blob:/i.test(koe)) {
|
|
1825
|
+
const res = await fetch(koe);
|
|
1826
|
+
if (!res.ok) {
|
|
1827
|
+
throw new Error(`blob: URL fetch failed: ${res.status}`);
|
|
1828
|
+
}
|
|
1829
|
+
return await _VoiceBank.fromBlob(await res.blob());
|
|
1830
|
+
}
|
|
1831
|
+
if (!/^https?:/i.test(koe)) {
|
|
1832
|
+
throw new Error(`unsupported URL protocol: ${koe}`);
|
|
1833
|
+
}
|
|
1834
|
+
const header = await rangeFetch(koe, 0, 8);
|
|
1835
|
+
const { jsonLength } = parseKoeHeader(header);
|
|
1836
|
+
validateJsonLength(jsonLength);
|
|
1837
|
+
const json = await rangeFetch(koe, 8, jsonLength);
|
|
1838
|
+
const manifest = parseManifest(json);
|
|
1839
|
+
return new _VoiceBank(
|
|
1840
|
+
manifest,
|
|
1841
|
+
new RangeVoiceSource(koe, pcmBase(jsonLength))
|
|
1842
|
+
);
|
|
1843
|
+
}
|
|
1844
|
+
return await _VoiceBank.fromBlob(koe);
|
|
1845
|
+
} catch (error) {
|
|
1846
|
+
throw new Error(
|
|
1847
|
+
`Failed to load .koe voice bank: ${error instanceof Error ? error.message : String(error)}`
|
|
1790
1848
|
);
|
|
1791
1849
|
}
|
|
1850
|
+
}
|
|
1851
|
+
static async fromBlob(koe) {
|
|
1792
1852
|
const header = await koe.slice(0, 8).arrayBuffer();
|
|
1793
1853
|
const { jsonLength } = parseKoeHeader(header);
|
|
1854
|
+
validateJsonLength(jsonLength);
|
|
1794
1855
|
const json = await koe.slice(8, 8 + jsonLength).arrayBuffer();
|
|
1795
|
-
const manifest =
|
|
1856
|
+
const manifest = parseManifest(json);
|
|
1796
1857
|
return new _VoiceBank(
|
|
1797
1858
|
manifest,
|
|
1798
1859
|
new BlobVoiceSource(koe, pcmBase(jsonLength))
|
|
@@ -1800,7 +1861,7 @@ var VoiceBank = class _VoiceBank {
|
|
|
1800
1861
|
}
|
|
1801
1862
|
/** True if the bank contains a phoneme under this alias. */
|
|
1802
1863
|
has(phoneme) {
|
|
1803
|
-
return this.manifest.phonemes
|
|
1864
|
+
return Object.hasOwn(this.manifest.phonemes, phoneme);
|
|
1804
1865
|
}
|
|
1805
1866
|
/**
|
|
1806
1867
|
* Raw Int16 PCM bytes (48 kHz / mono) for a phoneme, or null if unknown.
|
|
@@ -1808,8 +1869,11 @@ var VoiceBank = class _VoiceBank {
|
|
|
1808
1869
|
* worker / AudioWorklet.
|
|
1809
1870
|
*/
|
|
1810
1871
|
async readPcmBytes(phoneme) {
|
|
1872
|
+
if (!Object.hasOwn(this.manifest.phonemes, phoneme)) return null;
|
|
1811
1873
|
const entry = this.manifest.phonemes[phoneme];
|
|
1812
|
-
if (!entry)
|
|
1874
|
+
if (!Number.isInteger(entry.offset) || !Number.isInteger(entry.length) || entry.offset < 0 || entry.length < 0 || entry.length > MAX_PHONEME_SAMPLES) {
|
|
1875
|
+
throw new Error(`manifest entry out of bounds for phoneme: ${phoneme}`);
|
|
1876
|
+
}
|
|
1813
1877
|
return this.source.readBytes(entry.offset, entry.length * 2);
|
|
1814
1878
|
}
|
|
1815
1879
|
/**
|
|
@@ -1819,7 +1883,7 @@ var VoiceBank = class _VoiceBank {
|
|
|
1819
1883
|
async getPcm(phoneme) {
|
|
1820
1884
|
const buf = await this.readPcmBytes(phoneme);
|
|
1821
1885
|
if (!buf) return null;
|
|
1822
|
-
const int16 = new Int16Array(buf);
|
|
1886
|
+
const int16 = new Int16Array(buf, 0, Math.floor(buf.byteLength / 2));
|
|
1823
1887
|
const f64 = new Float64Array(int16.length);
|
|
1824
1888
|
for (let i = 0; i < int16.length; i++) f64[i] = int16[i] / 32768;
|
|
1825
1889
|
return f64;
|
|
@@ -2010,7 +2074,8 @@ var Worldline = class _Worldline {
|
|
|
2010
2074
|
}
|
|
2011
2075
|
const outLen = WL._PhraseSynthSynth(ps, yPtrPtr, 0);
|
|
2012
2076
|
const yPtr = WL.getValue(yPtrPtr, "*");
|
|
2013
|
-
const audio = outLen > 0 ? new Float32Array(WL.HEAPF32.buffer, yPtr, outLen).slice() : null;
|
|
2077
|
+
const audio = outLen > 0 && yPtr ? new Float32Array(WL.HEAPF32.buffer, yPtr, outLen).slice() : null;
|
|
2078
|
+
if (yPtr) WL._free(yPtr);
|
|
2014
2079
|
WL._free(yPtrPtr);
|
|
2015
2080
|
WL._PhraseSynthDelete(ps);
|
|
2016
2081
|
return audio;
|
|
@@ -2201,7 +2266,7 @@ var parseLyrics = (mml) => {
|
|
|
2201
2266
|
let pan = 64;
|
|
2202
2267
|
let octave = 0;
|
|
2203
2268
|
const modelMatch = rest.match(
|
|
2204
|
-
/^([a-z_]
|
|
2269
|
+
/^([a-z_][a-z0-9_]*?)(?=(?:[vqpo]-?\d)|[^a-z0-9_]|$)(?::(\d+))?/i
|
|
2205
2270
|
);
|
|
2206
2271
|
let model = "";
|
|
2207
2272
|
const metaTokens = [];
|
|
@@ -2276,6 +2341,40 @@ var stripLyrics = (mml) => {
|
|
|
2276
2341
|
}
|
|
2277
2342
|
return kept.join("\n");
|
|
2278
2343
|
};
|
|
2344
|
+
var CUSTOM_VOCAL_LINE = /^@@([a-zA-Z_][a-zA-Z0-9_]*)\s+(\S+)\s+(\S+)\s*$/;
|
|
2345
|
+
var CUSTOM_VOCAL_URL_MAX_LEN = 2048;
|
|
2346
|
+
var isValidHttpUrl = (s) => {
|
|
2347
|
+
if (s.length > CUSTOM_VOCAL_URL_MAX_LEN) return false;
|
|
2348
|
+
try {
|
|
2349
|
+
const u = new URL(s);
|
|
2350
|
+
return u.protocol === "http:" || u.protocol === "https:";
|
|
2351
|
+
} catch {
|
|
2352
|
+
return false;
|
|
2353
|
+
}
|
|
2354
|
+
};
|
|
2355
|
+
var parseCustomVocals = (mml) => {
|
|
2356
|
+
const map = /* @__PURE__ */ new Map();
|
|
2357
|
+
for (const seg of splitSegments(mml)) {
|
|
2358
|
+
const m = seg.match(CUSTOM_VOCAL_LINE);
|
|
2359
|
+
if (!m) continue;
|
|
2360
|
+
const key = m[1].toLowerCase();
|
|
2361
|
+
const iconUrl = m[2];
|
|
2362
|
+
const koeUrl2 = m[3];
|
|
2363
|
+
if (!isValidHttpUrl(koeUrl2)) {
|
|
2364
|
+
console.warn(
|
|
2365
|
+
`[dtm] \u30AB\u30B9\u30BF\u30E0\u30DC\u30FC\u30AB\u30EB "${key}": koe URL \u304C\u4E0D\u6B63\u307E\u305F\u306F\u9577\u3059\u304E\u308B\u305F\u3081\u30B9\u30AD\u30C3\u30D7\u3057\u307E\u3059`,
|
|
2366
|
+
koeUrl2.slice(0, 80)
|
|
2367
|
+
);
|
|
2368
|
+
continue;
|
|
2369
|
+
}
|
|
2370
|
+
const resolvedIconUrl = isValidHttpUrl(iconUrl) ? iconUrl : "";
|
|
2371
|
+
map.set(key, { key, iconUrl: resolvedIconUrl, url: koeUrl2 });
|
|
2372
|
+
}
|
|
2373
|
+
return [...map.values()];
|
|
2374
|
+
};
|
|
2375
|
+
var stripCustomVocals = (mml) => mml.split(/[\n\r]+/).map(
|
|
2376
|
+
(line) => line.split(";").filter((seg) => !CUSTOM_VOCAL_LINE.test(seg.trim())).join(";")
|
|
2377
|
+
).join("\n");
|
|
2279
2378
|
var panToStereo = (pan) => Math.max(-1, Math.min(1, (pan - 64) / 64));
|
|
2280
2379
|
var createLyricsConductor = (lyrics) => {
|
|
2281
2380
|
const pointers = /* @__PURE__ */ new Map();
|
|
@@ -2402,7 +2501,10 @@ var KOE_VOICEBANKS = {
|
|
|
2402
2501
|
ruko_male: "\u6B32\u97F3\u30EB\u30B3\u2642\u9023\u7D9A\u97F3Ver.1.03.koe",
|
|
2403
2502
|
ruko_female: "\u6B32\u97F3\u30EB\u30B3\u2640\u6B4C\u9023\u7D9A\u97F3\u666E1.00.koe",
|
|
2404
2503
|
teto: "\u91CD\u97F3\u30C6\u30C8\u5358\u72EC\u97F3.koe",
|
|
2405
|
-
shiyo: "\u9769\u547D\u30B7\u30E8.koe"
|
|
2504
|
+
shiyo: "\u9769\u547D\u30B7\u30E8.koe",
|
|
2505
|
+
rei: "\u8DB3\u7ACB\u30EC\u30A4ver3.5.0.koe",
|
|
2506
|
+
MGRoid: "MGRoid_\u539F\u97F3\u8A2D\u5B9A\u6E08\u307F.koe",
|
|
2507
|
+
MOTRoid: "MOTRoid\u5B8C\u5168\u7248V2.koe"
|
|
2406
2508
|
};
|
|
2407
2509
|
var KOE_VOICEBANK_LABELS = {
|
|
2408
2510
|
tsukuyomi: "\u3064\u304F\u3088\u307F\u3061\u3083\u3093",
|
|
@@ -2411,7 +2513,10 @@ var KOE_VOICEBANK_LABELS = {
|
|
|
2411
2513
|
ruko_male: "\u6B32\u97F3\u30EB\u30B3\u2642",
|
|
2412
2514
|
ruko_female: "\u6B32\u97F3\u30EB\u30B3\u2640",
|
|
2413
2515
|
teto: "\u91CD\u97F3\u30C6\u30C8",
|
|
2414
|
-
shiyo: "\u9769\u547D\u30B7\u30E8"
|
|
2516
|
+
shiyo: "\u9769\u547D\u30B7\u30E8",
|
|
2517
|
+
rei: "\u8DB3\u7ACB\u30EC\u30A4",
|
|
2518
|
+
MGRoid: "MGRoid",
|
|
2519
|
+
MOTRoid: "MOTRoid"
|
|
2415
2520
|
};
|
|
2416
2521
|
var VOICE_IMAGE_KEY = {
|
|
2417
2522
|
klatt: "puyuyu",
|
|
@@ -2421,7 +2526,10 @@ var VOICE_IMAGE_KEY = {
|
|
|
2421
2526
|
ruko_male: "ruko",
|
|
2422
2527
|
ruko_female: "ruko",
|
|
2423
2528
|
teto: "teto",
|
|
2424
|
-
shiyo: "shiyo"
|
|
2529
|
+
shiyo: "shiyo",
|
|
2530
|
+
rei: "rei",
|
|
2531
|
+
MGRoid: "MGRoid",
|
|
2532
|
+
MOTRoid: "MOTRoid"
|
|
2425
2533
|
};
|
|
2426
2534
|
var KOE_VOICEBANK_TERMS = {
|
|
2427
2535
|
tsukuyomi: "https://tyc.rei-yumesaki.net/material/utau/terms/",
|
|
@@ -2430,7 +2538,10 @@ var KOE_VOICEBANK_TERMS = {
|
|
|
2430
2538
|
ruko_male: "https://long-sleeper.net/index.php?id=22",
|
|
2431
2539
|
ruko_female: "https://long-sleeper.net/index.php?id=22",
|
|
2432
2540
|
teto: "https://kasaneteto.jp/guidelines/voice.html",
|
|
2433
|
-
shiyo: "https://kakumeisiyo.my.canva.site/dagkuyjwycs"
|
|
2541
|
+
shiyo: "https://kakumeisiyo.my.canva.site/dagkuyjwycs",
|
|
2542
|
+
rei: "https://mechanicalgirl.jp/guidelines/",
|
|
2543
|
+
MGRoid: "https://x.com/nisusansu/status/1048825378188353536",
|
|
2544
|
+
MOTRoid: "https://www.nicovideo.jp/watch/sm40031282"
|
|
2434
2545
|
};
|
|
2435
2546
|
var koeUrl = (name, base = KOE_BASE_URL) => `${base}/${encodeURIComponent(name)}`;
|
|
2436
2547
|
var DEFAULT_WORLDLINE_SCRIPT = "https://onjmin.github.io/koe/demo/world/worldline.js";
|
|
@@ -2536,7 +2647,7 @@ var createLocalBackend = async (options) => {
|
|
|
2536
2647
|
}
|
|
2537
2648
|
const rate = entry.pitch > 0 ? targetHz / entry.pitch : 1;
|
|
2538
2649
|
return {
|
|
2539
|
-
pcm: Float32Array
|
|
2650
|
+
pcm: new Float32Array(pcm),
|
|
2540
2651
|
preSec: entry.pre / KOE_SAMPLE_RATE / rate,
|
|
2541
2652
|
rate
|
|
2542
2653
|
};
|
|
@@ -2797,6 +2908,16 @@ var createSingingVoices = (ctx, destination, options = {}) => {
|
|
|
2797
2908
|
for (const m of models) if (m) set.add(m.toLowerCase());
|
|
2798
2909
|
await Promise.all([...set].map((m) => load2(m)));
|
|
2799
2910
|
};
|
|
2911
|
+
const registerVoicebanks = (banks) => {
|
|
2912
|
+
for (const [k, v] of Object.entries(banks)) {
|
|
2913
|
+
const key = k.toLowerCase();
|
|
2914
|
+
if (key === FALLBACK_MODEL) continue;
|
|
2915
|
+
if (catalog[key] === v) continue;
|
|
2916
|
+
catalog[key] = v;
|
|
2917
|
+
loaded.delete(key);
|
|
2918
|
+
loading.delete(key);
|
|
2919
|
+
}
|
|
2920
|
+
};
|
|
2800
2921
|
const forEachSungNote = (track, fn) => {
|
|
2801
2922
|
let prevVowel = "";
|
|
2802
2923
|
for (const note of track.notes) {
|
|
@@ -2903,7 +3024,14 @@ var createSingingVoices = (ctx, destination, options = {}) => {
|
|
|
2903
3024
|
stopStream();
|
|
2904
3025
|
for (const v of loaded.values()) v.reset?.();
|
|
2905
3026
|
};
|
|
2906
|
-
return {
|
|
3027
|
+
return {
|
|
3028
|
+
loadModels,
|
|
3029
|
+
registerVoicebanks,
|
|
3030
|
+
warm,
|
|
3031
|
+
startStream,
|
|
3032
|
+
stopStream,
|
|
3033
|
+
reset
|
|
3034
|
+
};
|
|
2907
3035
|
};
|
|
2908
3036
|
var createVoiceRegistry = (models = {}, fallback = "klatt") => {
|
|
2909
3037
|
const sing = (model, syllable, e) => {
|
|
@@ -4357,7 +4485,8 @@ var parseMML = (mml, options = {}) => {
|
|
|
4357
4485
|
meta: {}
|
|
4358
4486
|
};
|
|
4359
4487
|
}
|
|
4360
|
-
const
|
|
4488
|
+
const noCustomVocals = stripCustomVocals(mml);
|
|
4489
|
+
const noComments = noCustomVocals.replace(/\/\*[\s\S]*?\*\//g, "").replace(/\/\/.*$/gm, "");
|
|
4361
4490
|
const meta = parseMmlMeta(noComments);
|
|
4362
4491
|
const noMeta = stripMmlMeta(noComments);
|
|
4363
4492
|
const lyrics = collectLyrics ? parseLyrics(noMeta) : void 0;
|
|
@@ -5702,6 +5831,7 @@ var DAW_CSS = `
|
|
|
5702
5831
|
height: 20px;
|
|
5703
5832
|
border-radius: 50%;
|
|
5704
5833
|
object-fit: cover;
|
|
5834
|
+
image-rendering: pixelated;
|
|
5705
5835
|
}
|
|
5706
5836
|
|
|
5707
5837
|
/* \u2500\u2500\u2500 \u5E83\u5E45\u62E1\u5F35 \u2500\u2500\u2500 */
|
|
@@ -6187,26 +6317,38 @@ var createSynth = (ctx, destination = ctx.destination) => {
|
|
|
6187
6317
|
return { playNote, playDrum };
|
|
6188
6318
|
};
|
|
6189
6319
|
|
|
6320
|
+
// assets/404Chip.png
|
|
6321
|
+
var Chip_default = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAcElEQVR42u2WOw7AIAxD7Yr7X9kdqi5IIXQKBWckKHrOTyEAodAuFJsBDGAAA7TIIT0LkuTQ/1r0L4u3XgZ6ZbNKsvf9mlBSqu5fU9DXMFP3teujeOtPQbYPZnplFK88A4xuwmM2IX0VG8AABjge4AZHeT8uyZjZYAAAAABJRU5ErkJggg==";
|
|
6322
|
+
|
|
6323
|
+
// assets/MGRoid.png
|
|
6324
|
+
var MGRoid_default = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABy0lEQVR42tWXv0tCURTHPy9dwog0AssiVLChNmnQaHaJIoj+gQgkoj+jsSEiGmpodosWA9ck6g1BDg0qQYNLDpG1GK/h3RvvxfU+nbyd6f4473C/33ve95xr0b853kk2m2UQs21bDi3v+ghDtnCQQzEWcwDO2u2+kC83mwDcTEwEMWkZx4Cjc7xMJAA4DkCeGx11GRDrjUZDefdG5YA+uwUyaQetlstEPK5ELi0ajfZ1gKEzYEkG/iK/23l0B7MDRnwV1O51fYx6dABj/wI9coHsdz1g3j0NCyZsLRPmK+HL4jMAixdlAD4KB0pmxsquQtSOCgDMs6Bkwkgd0FoqlQIgs7oFQGhjRemX+ZwW/lMAfNfo9RdZxumAshZ0r8K+Ow6lT9zBUk4d6anqIq/v+5CH17tm1wIrqAOSTHiQuJvlMzdAoYiKuSDkRjPgiE4IgPtkUlv3q19fWj/ZSRndDyhNIsyJ+n+dzyvna7e3ALwJvZisVFD1F7ZtO/9DB+SJHw53lVneqytW1PteVdDwd4HU/u3zivKDzbkZbc2QViqVtMiNZMDy5oJE8Pcu3zsdAMYjEWVAzzvg/yrhQK/ker3u20yn0wPFHjoDP1pgkXMfnLDSAAAAAElFTkSuQmCC";
|
|
6325
|
+
|
|
6326
|
+
// assets/MOTRoid.png
|
|
6327
|
+
var MOTRoid_default = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAByElEQVR42s2WTyiEURTFfyMbS1ZSlIUxScpCNrNAkpLdhClFlJRJdpQ/5V+xE7PQFJHFyJKUJKLZaBZqkhjKQslCLG3UWIw7ec/7xidq3lnNve++23fOO2/u86ChPbyd+hp3tDbzH9g5OFLivVCXByCPHMPjlrkw+KsiuhI5VyBfT/z3mev9JJZ1ezywdfeccnNmbhVyuy/3Coj7nVwv2KwpAaAn8ZiVkezT652UsO8WCK5jJ0pcH9OYOrha9un1GVivwMzEOADJ6CoApQtx48bdQNnnr3cAugMNAMRWpoz1/usbALzBQQB8/kZLFZAv0/EwVpdVESfGMV+lsb94xz4FMu4f6lTybpkLdObf+lurwNTcvOLWh6XpXzX0n54Z89JP+ts/CwRtj1cAFHq9Sj4+uWisr5sdVeLXZBKA/ZIqy6fhT3O7YmNJPdOWFmNd8vBQiW97R7JOTXtfxYKjyAwAzQPp//jxp8v0tAuFjA3Pw2EA5ourjfvt84DTQkFNVQrgrb9Dyb/UNhlvhe76ootjtd9a+gXxlrjy2P0eEOZOyDDTGLpFRtlPJezzgNPZC6LBPgDKlyPG9fvhAQCC0XWzAms7dt2CDzsGp242tsuqAAAAAElFTkSuQmCC";
|
|
6328
|
+
|
|
6190
6329
|
// assets/puyuyu.png
|
|
6191
|
-
var puyuyu_default = "data:image/png;base64,
|
|
6330
|
+
var puyuyu_default = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAB60lEQVR42tWXPUxTURiGn9vWMCgtEQoDcWhAFgdtB0dMGjfcIAwMjcYoKIObq3F1EwKixNR0cCC46YQ4ODqIi4kRjUPj0Jaa1roYi9fh9Kuck3tvb7v08C73J+/5Tt7nnPvlHoeQend3yKULXXxQc8L4IvRZsU6JM9NJAKLZOQCazox6jiU0/2Gzrgq6r5RvetsFeP+2EkjEPgJ+yd3olDL81RObEp+My7Ct6oLrRcIeAmbyyKULngOikf2uJpA6GT54kug7gfZ6HO6cdwF+pYYBGBxT12vzrwF49mKpq8JXZzcAyG9dBqBRqgJw8lNRob+ybwkBc+2vrx1oBknQq4Sg6OnyCEf7g319YGU1rSM6taWujtou9S/ZwILxid1gf2sP2NsJZZdGZz57DkhMvlG9/uVZvT906bePwO9GDYCBwSFtDUWLN1UfePxkw/tzCumXeawh0O4D59InNAL54gIAN27d1wZsPrqnvu8zz/V+EdIvBD7u/bGUgEhI/BjLae9PlwqBBf385trbQ0Buvj2ccAFGR396kuhVZvJyOQ5A6s5Xx64+UPlebd2p/wAhYSYQ3S40tef1XCxwIkn+fx4s2wPmv2FyXCdhJjcT+703k1v3V+x0OhkJiV7ll9x+Ap1Px25giWNzOv4HHKK9IIEhxAYAAAAASUVORK5CYII=";
|
|
6331
|
+
|
|
6332
|
+
// assets/rei.png
|
|
6333
|
+
var rei_default = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAACXElEQVR42s2XQWhTQRCGv1c8CFa9SSPEKkQPtfIOBQUlBgThEVIjEgRvEuuhCDkVL7Ug2N4ilqB4aCveFOnBanm+gxRUKlgJUmgraEA0YEpPRT3opeth30p2eXk0XrJzecxkZnbm39mZicM26dXAGUEblKkuOFHyvn09AmBtY90B6KLD5LSKUNH9ZB8Aw/W1/zpA2StSfuxDQGWeyWX1u5/3Nf7t8RORjk4uvYs9aOVqt8a/CQ5gBQI7WlZ9mLkZOaxGZ+jqesGpCgCe50nB2JFIO3sQ+FftRuaNbFkzSPgjGv9j+SgAe9zV2INMvbT3zRIEtkZT4buXEa3QrVUpQUWLuBX9GXwgv+O35d1Tkj94nwBYbvyUflxba0Bl7CZ2A3B6fhKA17krsQ72Tk3qSLQZQOc7oTnlMtWFVtMwRGZGGiYOxTreGk1F94XFkmU10DS3BYAQEhBx47CMcKIWadhKT2Vu8iOXixIBo7Pa8wo2c/lYRXX32yXR+CK/d8/GdkR79oHNXF4AbBzrBSCZL0Qa7OxNtodEiED/1C9t5tgzC0zB+ZknADwNeYXE0rWbkbWgOqUpf/HhIwC7wg5bfhhO0bGyZZ2wqXOJ5rsyqfpMIuPPPdLkF0rXAfhcuaPJU12+NmPS71/KjhgEWke0rwbUJqQif+weBKA+NwtANn9J0//9ta7xtbTcAVOLvmafNqfgRM2xCwEzY8LNZbBQUAoADJy7qNWE+XrKIQLckpsQQ0Oa3vNZieRwsSjsegUqIkX3pqf1qg33+/6e/dH/C9a/R+or3iSFRMcR+AtdbNaYOcb0dwAAAABJRU5ErkJggg==";
|
|
6192
6334
|
|
|
6193
6335
|
// assets/rino.png
|
|
6194
|
-
var rino_default = "data:image/png;base64,
|
|
6336
|
+
var rino_default = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABvklEQVR42mNkIACC8yv/MzAwMKSF+jOQAmat3ojCXzuxnRGbOiaGAQaM1PY5oRBBD4kBDwEWdIGdR078p6YFesryeOUHTwjAfI7u4kt3HzLgEyfWp4M/BHD5zE1BhoGBgYFh+vZdDAwMDAzKauoo4jAAk8cFkHLTf+TcMPhC4O6tm6gCaD6Fy6OJZ7o5Q0Ji194hmgbQfZ6VFA+h0TRMm7cQtSiVkcFrwc4jJ4ZYLoD5/P9/SIEobGCNNa5hPsel7t3FY1hz06xBHwLoccxj5IhV4/8nT/CqWz61D4V/bNu2wZkGGNHrAlhu2HvxBgMDAwPDmtJssgze9eAJStyHdE8d5O0BdxsLRuSWEHrcWXl5EWUgzKdwQKBFNfjbhEXailjlTf79Q+GfYYL4pe/qfQYGBgaGU9dQW8WPd18bnK1ieBqQddVCiXtOyU8MDAwMDBGrJzAwMDAw2Duj5vNMIX2UtDF9STtUH1TBNVSL0M0fvCUhIYDu81ioz3EBWMhJv0KtFZdd/j5IQwDm4oN792PVAEsTDDAaTR86iNO6xMDAwMCwiMECa0gMnTSAK0RwySNC5BJKSCTv/T64QgAAipubBW9f1GUAAAAASUVORK5CYII=";
|
|
6195
6337
|
|
|
6196
6338
|
// assets/roze.png
|
|
6197
|
-
var roze_default = "data:image/png;base64,
|
|
6339
|
+
var roze_default = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAB0klEQVR42s2XPUsDQRCGnxVbC4OVFkELlRR+lBY2dkmlpSLYWVmIpA7BOkL+gQghjYVWiaRVsBFNgiZGQbGIlR+FP2AtzEh23TsTEW6nudu529l53/nYXUVHZqbmNEC9VVWEiPwXJEHzg+wPELEMime12yvRaQCllHjunPjYfjDG42MTxnxAuZDbDEbOwHc8Rss5DfCcTBvIQ5Aa3229MDp2skfHrjM3os8BeQlCLsgWZhadBkRfLB84megSbVWFZ1VQb1UN5GvJDePH8/ppX4Znp+cB+LBySJDLev7kgC2/Ia4dFb+Qrqz9aWF/cuC/DIVkv7Nq/OkD4pFk5Y+OZsVaxiqRCI1tr7kVPQNB2S6MCFLdaJhtTWuj13/LdsEYPmUzAMTSafzeC+wO1bVLumc2mwC04ymzA1LoywF/+4Ad4/dSCYDhVKqvBeLZ3dDq8JeB970v5Ne2vsOESK+MvOTXARixqsQ/BiTrY0mzbt9yuVDk0i/sE9XQYcZ5b5BziD+nYvFIYmWfFYNkdWnLqb9pnxl9RZi1T8f+3Qts5BL7/XwegIvJZQAu7917yKZ+BWCnUjGqpmsvUH5XwW/IbaS2nrtjZ+fUnadKJIy7Y+QMfAL8JMMLhDWQAQAAAABJRU5ErkJggg==";
|
|
6198
6340
|
|
|
6199
6341
|
// assets/ruko.png
|
|
6200
|
-
var ruko_default = "data:image/png;base64,
|
|
6342
|
+
var ruko_default = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAACC0lEQVR42s2XsUsbURzHP08kinNvkWAXiy0F6dBJM0S7Bf+AUK2CkKCzS6GDZJBObkJBcNFS7NRFApaCEbRdHERQTJwKGYS4dJE2FM/h7id9P1/SKx3ufZfk3r17d9/P+/1+9ztDQgVBEPIParVaJsm8HlKWyedyTme1gwPzp/OnIyOJFjyt17sS0fdLn4D8kSfTDpI6T0pE1hPCqRPo7RQD/6tm38PYsZuExFb6BDqdkL16VSwC8DiTAeC83bbmbW1vW/NEbz99s0hA3c860CtPLk60ZHwv/n2jnK7Mzkbjm5vWeFbFgkiTSr8ObKytWVnwulKRyuW8IGw2AZiInQgZk8065w+/mAbgx8lnZ2z5kwWy1+I8DCMwS4NDzgv3VMyIU9HFl/cRGWPs87++e5YFeiCfy1nHxavLRAs9eDLeNQY6ZZe//YBod2YGgMzUVKIF2zs7ABz1RN7mPu5HdUHtvb8xIO9pIdO3sOCsA39znlT+vg1119RoNEKAr9UqAM9vbizHweQkAGf70Z6XSiUTZ0HoIutvTyhPKjpcXw8BgnwegEcDA86FLq6v7S64VgNgvFw2qs6EXvWE975etGOtwmLFOq6+W3Z/B8QEtDQRfwiI87uuNSZQnp+3Oh/R0slvAFZH7UTSnZG8NSV7NAn/6sBYoeCcKM5+PnvpJNF//KHrjfS6Qjx1ArcCiMI3kOeT7AAAAABJRU5ErkJggg==";
|
|
6201
6343
|
|
|
6202
6344
|
// assets/shiyo.png
|
|
6203
|
-
var shiyo_default = "data:image/png;base64,
|
|
6345
|
+
var shiyo_default = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAACJklEQVR42s2Xv09TURTHP5eAJJrI3ISBhIFJiaBp08GFAYKTA6FxejVBGgeTtzjxF7gwaWoNtCPEoSwSli4aa+uPSHFiaGLiQFwkDDWBBK7De6fpvd4+YOKe5eW8e+557/u959dV9BcdP1Xvy0ajoXv1dDoNQLPZBCCTyaik/bYMcMWiEpBjITcQiwhyBxOG3cbqJAC5sKW8YmDwPAOttYHMRn7n+nMATn7Iygtjn1LKZkL3MuFvDBzv3Qfg+98I0c9PywA8nBm51AeGb793xoK/MSB/eG18NUJeenwh5NXakdNOd75FVN+YNtbF3h8GJDoXn6wnbhBmRDZjhhYX3kX62we4/AizEhMSY/7WgU3r7LtnTGjogtyWk3Zo6MJILpz2PAtEcmHL+d7O425BGR1N/NDxXuhnNxw87+w+z84a+r2FNaej/+x2dpy9wK6Q/sbAbtztfm9tJZ71bq0GwOHU1KVixt+JSCriyM1nAKTGxoz1yYkJQ2/t7zsdd9ptAH51XiZml38xIJNKEHzQAEunp6aBxYDNSH17+0J1RbqkfzFgz/3FYhGApWzWsLt7dmboXwciLG/qdQAqlYpy+ZNp2V8GgiDQAIVCARcTIq+tuX85vjeI2Pu7N6lbQ55ngZx1Oq54+ZUVAMrlcqTn81H+V6sAvEqljP1iZ98jxB+Hcc/588gzBj6WShogOz/vZMRG+GVuDoCnBwdG9+ubPX3mhStn4B+i9swYdEa2xAAAAABJRU5ErkJggg==";
|
|
6204
6346
|
|
|
6205
6347
|
// assets/teto.png
|
|
6206
|
-
var teto_default = "data:image/png;base64,
|
|
6348
|
+
var teto_default = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAB00lEQVR42tVXPUsDQRB9q8GvQiyjWKS0CApBCEENafwoYiMWIoJX+gMiKFoqFskPsFQQsbLxisQqRCQIEgiksEzhRyspREU9i705suNecqmyviozszfsezs7OxEIDqfZyMTSAIBcxebrRAc50YMuQ/gx5CDGhFR/HwCg+PGp+DWKtFTICAUcHUMOYhzp1e+5/v2jVYSjSSFhhgKZWNrRMTx5ew/EvJ0S1tCA1p+r2GYoEKIffMeEcHxSKlK6BwCsJaeV+AXzhyng+nl+4/pAiFc5BzHMHslbsr1rK0r5+f1uEVfC/BoghmJxS7bLp6pkvLwn49GEW9UyDp9+8v9qgDpWFnpG2atDvZ8pZs2uml0D3ltgJ1YAAOnypfa9dwrH8gv3zP+gVlaY8+95fnPeAs08IJptv8nHKRy4jPfRZlISPvnNm4gUJebXdwAA15sRAMDCaR0A8PL8CABYarwCAPLDIwCA0bFxZT3VQrsZ0Zw+wJl723eZkJ+YWl9yXqi6Nl8fTW3Iy1E8c1opYZQCCryzPIdy9qQATUwEincKc28BgdcEx9RDTbGrE1HFr+kH5teA0rk4Q46bwYZizwVkbnQNBPp3TIjPJBX77rbUUe6uK/ALBWuzghq8Lc4AAAAASUVORK5CYII=";
|
|
6207
6349
|
|
|
6208
6350
|
// assets/tsukuyomi.png
|
|
6209
|
-
var tsukuyomi_default = "data:image/png;base64,
|
|
6351
|
+
var tsukuyomi_default = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAB3UlEQVR42tWXPUsDQRCGnwuijYIoFqKmEDSCxIgIgqnsogbsrC3ERiwN4g8Ikk6sFH+BnYofvcTKxoigBCzEYGGjWIiCOYvNBHe5TdQUt051czc3e++zO7tzHnUst7vn04BlFue9Ws8jhGxN9ZTPzU43NkIlj41E6AQ8m/JYfByAoWgXAPtHJzRCRN43SbizBkzlv1X2VzLuVoHYzf0TAMnys+aLCTGThMTJGnKfQOpyWF1cvgHQsh4FYPDzRd3vmQHgoPShJbi9uqhJyPk1UK3Jwsq1/115rLst8AX/4UFP0NsbGHf7+Kr579l7zR/ZGvbcrAJR7vvqEOwcTdZMYIuTPCYJUS7Ewydgzn2Bay2gdWzqR4nMuMPlhcC5l/HcWQOnCaU4lVU3xI9tnwFQnOgDoDmdDs5QKmlxYhdGmBA2ibhTBfKFHCkCm00dAKymJn+USAidHx8DkI+0q7PBUC7j5BJ7jlSB7RyXziVT8fM7Oz7AeLmsz3VEaWi7UvtAcmvJC+qmq4T/XT8gdTsw2692to07AF7jeU35wFq/7COqzhdVnVOnu3aHgNm1VpVXlImJX9zQffO5kDg1dlb3CNj6dZsVK2vAVP7Xf8bwCfxWuc23Eanmt/xlh07gC6oBviFE8rZHAAAAAElFTkSuQmCC";
|
|
6210
6352
|
|
|
6211
6353
|
// src/voice-images.ts
|
|
6212
6354
|
var VOICE_IMAGES = {
|
|
@@ -6216,8 +6358,12 @@ var VOICE_IMAGES = {
|
|
|
6216
6358
|
ruko: ruko_default,
|
|
6217
6359
|
shiyo: shiyo_default,
|
|
6218
6360
|
teto: teto_default,
|
|
6219
|
-
tsukuyomi: tsukuyomi_default
|
|
6361
|
+
tsukuyomi: tsukuyomi_default,
|
|
6362
|
+
rei: rei_default,
|
|
6363
|
+
MGRoid: MGRoid_default,
|
|
6364
|
+
MOTRoid: MOTRoid_default
|
|
6220
6365
|
};
|
|
6366
|
+
var FALLBACK_VOCAL_ICON = Chip_default;
|
|
6221
6367
|
|
|
6222
6368
|
// src/mml-player.ts
|
|
6223
6369
|
var STEPS_PER_BEAT3 = 48;
|
|
@@ -6416,6 +6562,9 @@ var mountMmlPlayer = (target, mml, options = {}) => {
|
|
|
6416
6562
|
collectLyrics: true
|
|
6417
6563
|
});
|
|
6418
6564
|
const lyricTracks = lyrics ?? /* @__PURE__ */ new Map();
|
|
6565
|
+
const customVocalByKey = new Map(
|
|
6566
|
+
parseCustomVocals(mml).map((d) => [d.key, d])
|
|
6567
|
+
);
|
|
6419
6568
|
const bpm = parsedBpm ?? options.defaultBpm ?? DEFAULT_BPM;
|
|
6420
6569
|
const drumPatternDict = options.drumPatterns ?? DRUM_PATTERNS;
|
|
6421
6570
|
const drumPattern = meta.drum ? drumPatternDict[meta.drum] ?? null : null;
|
|
@@ -6817,15 +6966,23 @@ var mountMmlPlayer = (target, mml, options = {}) => {
|
|
|
6817
6966
|
for (const [index, lt] of lyricTracks) {
|
|
6818
6967
|
const em = emojiByTrack.get(index);
|
|
6819
6968
|
if (!em) continue;
|
|
6969
|
+
const custom = customVocalByKey.get(lt.model.toLowerCase());
|
|
6820
6970
|
const imgKey = VOICE_IMAGE_KEY[lt.model.toLowerCase()];
|
|
6821
|
-
const src = imgKey ? VOICE_IMAGES[imgKey] : void 0;
|
|
6971
|
+
const src = custom ? custom.iconUrl || FALLBACK_VOCAL_ICON : imgKey ? VOICE_IMAGES[imgKey] : void 0;
|
|
6822
6972
|
if (!src) continue;
|
|
6823
6973
|
const img = doc.createElement("img");
|
|
6824
6974
|
img.src = src;
|
|
6975
|
+
if (custom) {
|
|
6976
|
+
img.onerror = () => {
|
|
6977
|
+
img.onerror = null;
|
|
6978
|
+
img.src = FALLBACK_VOCAL_ICON;
|
|
6979
|
+
};
|
|
6980
|
+
}
|
|
6825
6981
|
img.width = 20;
|
|
6826
6982
|
img.height = 20;
|
|
6827
6983
|
img.style.borderRadius = "50%";
|
|
6828
6984
|
img.style.objectFit = "cover";
|
|
6985
|
+
img.style.imageRendering = "pixelated";
|
|
6829
6986
|
img.draggable = false;
|
|
6830
6987
|
promotedToImage.add(em);
|
|
6831
6988
|
em.textContent = "";
|
|
@@ -7260,6 +7417,13 @@ var mountMmlPlayer = (target, mml, options = {}) => {
|
|
|
7260
7417
|
}
|
|
7261
7418
|
});
|
|
7262
7419
|
try {
|
|
7420
|
+
if (customVocalByKey.size > 0) {
|
|
7421
|
+
v.registerVoicebanks?.(
|
|
7422
|
+
Object.fromEntries(
|
|
7423
|
+
[...customVocalByKey].map(([k, d]) => [k, d.url])
|
|
7424
|
+
)
|
|
7425
|
+
);
|
|
7426
|
+
}
|
|
7263
7427
|
await v.loadModels(tracks.map((t) => t.model));
|
|
7264
7428
|
if (skipSinging) return;
|
|
7265
7429
|
const startTime = performance.now();
|
|
@@ -7415,6 +7579,29 @@ var MIDI_INFO_HTML = `
|
|
|
7415
7579
|
<p style="margin-top:4px;"><small>\u6B4C\u8A5E\u306E\u62BD\u51FA: <a href="https://rpgen3.github.io/ust2txt/" target="_blank" rel="noopener">ust2txt</a></small></p>
|
|
7416
7580
|
</div>
|
|
7417
7581
|
`;
|
|
7582
|
+
var KOE_INFO_HTML = `
|
|
7583
|
+
<div class="dtm-modal-body-content">
|
|
7584
|
+
<h4>1. UTAU\u97F3\u6E90\u3092 .koe \u306B\u5909\u63DB\u3059\u308B</h4>
|
|
7585
|
+
<p>UTAU\u7528\u306E\u97F3\u6E90\uFF08zip\uFF09\u3092\u305D\u306E\u307E\u307E\u4F7F\u3046\u3053\u3068\u306F\u3067\u304D\u307E\u305B\u3093\u3002\u4E0B\u8A18\u306E\u5909\u63DB\u30B5\u30A4\u30C8\u3067 <code>.koe</code> \u5F62\u5F0F\u306B\u5909\u63DB\u3057\u3066\u304F\u3060\u3055\u3044\u3002</p>
|
|
7586
|
+
<p style="margin-top:4px;"><small>\u5909\u63DB\u30B5\u30A4\u30C8: <a href="https://onjmin.github.io/koe/demo/" target="_blank" rel="noopener">koe\u5909\u63DB\u30C7\u30E2\uFF08onjmin.github.io/koe/demo\uFF09</a></small></p>
|
|
7587
|
+
|
|
7588
|
+
<h4>2. \u5909\u63DB\u3057\u305F .koe \u3092\u30A2\u30C3\u30D7\u30ED\u30FC\u30C9\u3059\u308B</h4>
|
|
7589
|
+
<p>\u5909\u63DB\u5F8C\u306E <code>.koe</code> \u30D5\u30A1\u30A4\u30EB\u306F\u3001\u8AB0\u3067\u3082\u76F4\u63A5\u30C0\u30A6\u30F3\u30ED\u30FC\u30C9\u3067\u304D\u308B\u5F62\u3067\u30CD\u30C3\u30C8\u4E0A\u306B\u7F6E\u304F\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\uFF08\u30ED\u30FC\u30AB\u30EB\u306E\u30D5\u30A1\u30A4\u30EB\u30D1\u30B9\u306F\u4F7F\u3048\u307E\u305B\u3093\uFF09\u3002</p>
|
|
7590
|
+
<ul>
|
|
7591
|
+
<li><strong>Google\u30C9\u30E9\u30A4\u30D6</strong>: \u30A2\u30C3\u30D7\u30ED\u30FC\u30C9\u5F8C\u3001\u5171\u6709\u8A2D\u5B9A\u3092\u300C\u30EA\u30F3\u30AF\u3092\u77E5\u3063\u3066\u3044\u308B\u5168\u54E1\u300D\u306B\u5909\u66F4 \u2192 \u5171\u6709\u30EA\u30F3\u30AF\u306E<code>/d/</code>\u3068<code>/view</code>\u306E\u9593\u306EID\uFF08\u30D5\u30A1\u30A4\u30EBID\uFF09\u3092 controlled URL \u306B\u7D44\u307F\u8FBC\u3093\u3067\u76F4\u63A5\u30EA\u30F3\u30AF\u5316\u3057\u307E\u3059\uFF08\u4F8B: <code>https://drive.google.com/uc?export=download&id=\u30D5\u30A1\u30A4\u30EBID</code>\uFF09\u3002</li>
|
|
7592
|
+
<li>\u305D\u306E\u4ED6\u3001\u76F4\u63A5\u30C0\u30A6\u30F3\u30ED\u30FC\u30C9URL\u3092\u767A\u884C\u3067\u304D\u308B\u30DB\u30B9\u30C6\u30A3\u30F3\u30B0\uFF08GitHub Pages\u3001Cloudflare R2 \u306A\u3069\uFF09\u3067\u3082\u69CB\u3044\u307E\u305B\u3093\u3002</li>
|
|
7593
|
+
</ul>
|
|
7594
|
+
|
|
7595
|
+
<h4>3. DTM\u3067\u4F7F\u3046</h4>
|
|
7596
|
+
<ul>
|
|
7597
|
+
<li>\u6B4C\u5531\u30E2\u30C7\u30EB\u306E\u30D7\u30EB\u30C0\u30A6\u30F3\u304B\u3089\u300C\u30AB\u30B9\u30BF\u30E0\u97F3\u6E90\u3092\u8FFD\u52A0\u2026\u300D\u3092\u9078\u3073\u307E\u3059\u3002</li>
|
|
7598
|
+
<li>\u300C\u97F3\u6E90URL\u300D\u306B\u624B\u98062\u306E\u76F4\u63A5\u30EA\u30F3\u30AF\u3092\u8CBC\u308A\u4ED8\u3051\u307E\u3059\u3002</li>
|
|
7599
|
+
<li>\u30A2\u30A4\u30B3\u30F3\u753B\u50CFUR\u30EB\u30FB\u8868\u793A\u540D\u30FB\u8B58\u5225\u5B50\u306F\u4EFB\u610F\u3067\u3059\uFF08\u7701\u7565\u53EF\uFF09\u3002</li>
|
|
7600
|
+
<li>\u300C\u8FFD\u52A0\u300D\u3092\u62BC\u3059\u3068\u30D7\u30EB\u30C0\u30A6\u30F3\u306B\u767B\u9332\u3055\u308C\u3001\u4EE5\u964D\u305D\u306E\u30C8\u30E9\u30C3\u30AF\u3067\u4F7F\u3048\u307E\u3059\u3002</li>
|
|
7601
|
+
</ul>
|
|
7602
|
+
<p style="margin-top:4px;"><small>\u203B\u30A2\u30C3\u30D7\u30ED\u30FC\u30C9\u3057\u305F\u97F3\u6E90\u306F\u81EA\u5DF1\u8CAC\u4EFB\u3067\u7BA1\u7406\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u6A29\u5229\u95A2\u4FC2\uFF08\u914D\u5E03\u5143\u306E\u5229\u7528\u898F\u7D04\uFF09\u306B\u3082\u5F93\u3063\u3066\u304F\u3060\u3055\u3044\u3002</small></p>
|
|
7603
|
+
</div>
|
|
7604
|
+
`;
|
|
7418
7605
|
var BASE_STEP_WIDTH = 0.5;
|
|
7419
7606
|
var BASE_KEY_HEIGHT = 15;
|
|
7420
7607
|
var TRACKS_SIMPLE = [
|
|
@@ -7555,12 +7742,14 @@ var TRACKS_ADVANCED = [
|
|
|
7555
7742
|
}
|
|
7556
7743
|
];
|
|
7557
7744
|
var DEFAULT_TRACKS = TRACKS_SIMPLE;
|
|
7558
|
-
var
|
|
7559
|
-
var
|
|
7745
|
+
var BASE_LYRIC_MODELS = ["klatt", ...Object.keys(KOE_VOICEBANKS)];
|
|
7746
|
+
var BASE_LYRIC_MODEL_LABELS = {
|
|
7560
7747
|
klatt: "\u8EFD\u91CF\u30ED\u30DC\u58F0",
|
|
7561
7748
|
...KOE_VOICEBANK_LABELS
|
|
7562
7749
|
};
|
|
7563
|
-
var lyricModelLabel = (model) =>
|
|
7750
|
+
var lyricModelLabel = (model, customMap) => BASE_LYRIC_MODEL_LABELS[model] ?? customMap.get(model)?.label ?? model;
|
|
7751
|
+
var CUSTOM_VOCAL_ADD_VALUE = "+custom";
|
|
7752
|
+
var CUSTOM_VOCAL_KEY_RE = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
|
|
7564
7753
|
var clamp3 = (v, min, max) => Math.min(Math.max(v, min), max);
|
|
7565
7754
|
var normalizeInstrumentName = (name) => {
|
|
7566
7755
|
if (!name) return "";
|
|
@@ -7617,6 +7806,22 @@ var mountDAW = (target, options = {}) => {
|
|
|
7617
7806
|
let currentPlayStep = 0;
|
|
7618
7807
|
let ready = false;
|
|
7619
7808
|
let isLoading = false;
|
|
7809
|
+
const customVocalsMap = /* @__PURE__ */ new Map();
|
|
7810
|
+
const registerCustomVocal = (def) => {
|
|
7811
|
+
const key = def.key.toLowerCase();
|
|
7812
|
+
if (BASE_LYRIC_MODELS.includes(key)) return;
|
|
7813
|
+
customVocalsMap.set(key, { ...def, key });
|
|
7814
|
+
};
|
|
7815
|
+
const resetCustomVocals = () => {
|
|
7816
|
+
customVocalsMap.clear();
|
|
7817
|
+
for (const d of options.customVocals ?? []) registerCustomVocal(d);
|
|
7818
|
+
};
|
|
7819
|
+
resetCustomVocals();
|
|
7820
|
+
const genCustomVocalKey = () => {
|
|
7821
|
+
let n = 1;
|
|
7822
|
+
while (customVocalsMap.has(`custom${n}`)) n++;
|
|
7823
|
+
return `custom${n}`;
|
|
7824
|
+
};
|
|
7620
7825
|
let selectedNotes = [];
|
|
7621
7826
|
let selectionRect = null;
|
|
7622
7827
|
let copiedNotes = [];
|
|
@@ -8370,6 +8575,13 @@ var mountDAW = (target, options = {}) => {
|
|
|
8370
8575
|
const overlay = showLoadingOverlay(refs.rollContainer);
|
|
8371
8576
|
setLoading(true);
|
|
8372
8577
|
try {
|
|
8578
|
+
if (customVocalsMap.size > 0) {
|
|
8579
|
+
voices.registerVoicebanks?.(
|
|
8580
|
+
Object.fromEntries(
|
|
8581
|
+
[...customVocalsMap].map(([k, d]) => [k, d.url])
|
|
8582
|
+
)
|
|
8583
|
+
);
|
|
8584
|
+
}
|
|
8373
8585
|
await voices.loadModels(streamTracks.map((t) => t.model));
|
|
8374
8586
|
await voices.warm(streamTracks);
|
|
8375
8587
|
} catch (err2) {
|
|
@@ -8534,6 +8746,20 @@ var mountDAW = (target, options = {}) => {
|
|
|
8534
8746
|
<a data-dtm="lyric-terms-link" target="_blank" rel="noopener" style="color:var(--dtm-primary);text-decoration:underline"></a>
|
|
8535
8747
|
<span>\u306E\u5229\u7528\u898F\u7D04\u306B\u5F93\u3063\u3066\u304F\u3060\u3055\u3044</span>
|
|
8536
8748
|
</div>
|
|
8749
|
+
<div class="dtm-row dtm-hidden" data-dtm="lyric-custom" style="flex-direction:column;align-items:stretch;gap:4px">
|
|
8750
|
+
<div class="dtm-row" style="justify-content: space-between; align-items: center;">
|
|
8751
|
+
<a data-dtm="lyric-custom-conv-link" href="https://onjmin.github.io/koe/demo/" target="_blank" rel="noopener" style="font-size:11px;color:var(--dtm-primary);text-decoration:underline">UTAU\u97F3\u6E90(zip)\u3092.koe\u306B\u5909\u63DB</a>
|
|
8752
|
+
<button class="dtm-btn dtm-btn--ghost dtm-btn--xs" data-dtm="lyric-custom-guide">\u4F7F\u3044\u65B9\u30AC\u30A4\u30C9</button>
|
|
8753
|
+
</div>
|
|
8754
|
+
<input type="url" class="dtm-input" data-dtm="lyric-custom-src" placeholder="\u97F3\u6E90URL\uFF08https://\u301C.koe\uFF09" aria-label="\u30AB\u30B9\u30BF\u30E0\u97F3\u6E90\uFF08.koe\uFF09\u306EURL">
|
|
8755
|
+
<input type="url" class="dtm-input" data-dtm="lyric-custom-icon" placeholder="\u30A2\u30A4\u30B3\u30F3\u753B\u50CFURL\uFF08\u4EFB\u610F\uFF09" aria-label="\u30AB\u30B9\u30BF\u30E0\u97F3\u6E90\u306E\u30A2\u30A4\u30B3\u30F3\u753B\u50CFURL">
|
|
8756
|
+
<input type="text" class="dtm-input" data-dtm="lyric-custom-alias" placeholder="\u8868\u793A\u540D\uFF08\u4EFB\u610F\uFF09" aria-label="\u30AB\u30B9\u30BF\u30E0\u97F3\u6E90\u306E\u8868\u793A\u540D\uFF08\u30D7\u30EB\u30C0\u30A6\u30F3\u306E\u5225\u540D\uFF09" maxlength="64">
|
|
8757
|
+
<input type="text" class="dtm-input" data-dtm="lyric-custom-key" placeholder="\u8B58\u5225\u5B50\uFF08\u4EFB\u610F\u30FB\u7701\u7565\u3067\u81EA\u52D5\u63A1\u756A\u3001\u82F1\u5B57\u59CB\u307E\u308A\u82F1\u6570\u5B57\u3068_\uFF09" aria-label="\u30AB\u30B9\u30BF\u30E0\u97F3\u6E90\u306EMML\u8B58\u5225\u5B50\uFF08\u30AD\u30FC\uFF09" maxlength="32">
|
|
8758
|
+
<div class="dtm-row">
|
|
8759
|
+
<span class="dtm-label dtm-grow" data-dtm="lyric-custom-note" style="color:var(--dtm-warn)"></span>
|
|
8760
|
+
<button class="dtm-btn dtm-btn--primary" data-dtm="lyric-custom-apply">\u8FFD\u52A0</button>
|
|
8761
|
+
</div>
|
|
8762
|
+
</div>
|
|
8537
8763
|
<div class="dtm-row" data-dtm="lyric-body" style="flex-direction:column;align-items:stretch">
|
|
8538
8764
|
<div class="dtm-row">
|
|
8539
8765
|
<span class="dtm-label">\u58F0\u91CF</span>
|
|
@@ -8584,6 +8810,30 @@ var mountDAW = (target, options = {}) => {
|
|
|
8584
8810
|
const lyricTermsLink = lyricDiv.querySelector(
|
|
8585
8811
|
'[data-dtm="lyric-terms-link"]'
|
|
8586
8812
|
);
|
|
8813
|
+
const lyricCustom = lyricDiv.querySelector(
|
|
8814
|
+
'[data-dtm="lyric-custom"]'
|
|
8815
|
+
);
|
|
8816
|
+
const lyricCustomSrc = lyricDiv.querySelector(
|
|
8817
|
+
'[data-dtm="lyric-custom-src"]'
|
|
8818
|
+
);
|
|
8819
|
+
const lyricCustomIcon = lyricDiv.querySelector(
|
|
8820
|
+
'[data-dtm="lyric-custom-icon"]'
|
|
8821
|
+
);
|
|
8822
|
+
const lyricCustomAlias = lyricDiv.querySelector(
|
|
8823
|
+
'[data-dtm="lyric-custom-alias"]'
|
|
8824
|
+
);
|
|
8825
|
+
const lyricCustomKey = lyricDiv.querySelector(
|
|
8826
|
+
'[data-dtm="lyric-custom-key"]'
|
|
8827
|
+
);
|
|
8828
|
+
const lyricCustomGuide = lyricDiv.querySelector(
|
|
8829
|
+
'[data-dtm="lyric-custom-guide"]'
|
|
8830
|
+
);
|
|
8831
|
+
const lyricCustomNote = lyricDiv.querySelector(
|
|
8832
|
+
'[data-dtm="lyric-custom-note"]'
|
|
8833
|
+
);
|
|
8834
|
+
const lyricCustomApply = lyricDiv.querySelector(
|
|
8835
|
+
'[data-dtm="lyric-custom-apply"]'
|
|
8836
|
+
);
|
|
8587
8837
|
const fmtPan = (pan) => pan === 64 ? "C" : pan < 64 ? `L${64 - pan}` : `R${pan - 64}`;
|
|
8588
8838
|
const addOpt = (value, label) => {
|
|
8589
8839
|
const o = document.createElement("option");
|
|
@@ -8592,9 +8842,15 @@ var mountDAW = (target, options = {}) => {
|
|
|
8592
8842
|
lyricModelSel.appendChild(o);
|
|
8593
8843
|
};
|
|
8594
8844
|
addOpt("", "\u30DC\u30FC\u30AB\u30EB\u306A\u3057");
|
|
8595
|
-
for (const m of
|
|
8596
|
-
|
|
8597
|
-
|
|
8845
|
+
for (const m of BASE_LYRIC_MODELS)
|
|
8846
|
+
addOpt(m, lyricModelLabel(m, customVocalsMap));
|
|
8847
|
+
for (const [k, def] of customVocalsMap) addOpt(k, def.label ?? k);
|
|
8848
|
+
addOpt(CUSTOM_VOCAL_ADD_VALUE, "\u30AB\u30B9\u30BF\u30E0\u97F3\u6E90\u3092\u8FFD\u52A0\u2026");
|
|
8849
|
+
if (active.lyricModel && !BASE_LYRIC_MODELS.includes(active.lyricModel) && !customVocalsMap.has(active.lyricModel)) {
|
|
8850
|
+
addOpt(
|
|
8851
|
+
active.lyricModel,
|
|
8852
|
+
lyricModelLabel(active.lyricModel, customVocalsMap)
|
|
8853
|
+
);
|
|
8598
8854
|
}
|
|
8599
8855
|
lyricModelSel.value = active.lyricModel;
|
|
8600
8856
|
lyricOctaveSel.value = String(active.vocalOctave);
|
|
@@ -8608,9 +8864,13 @@ var mountDAW = (target, options = {}) => {
|
|
|
8608
8864
|
lyricCount.textContent = active.lyricModel && n > 0 ? `${n}\u97F3\u7BC0` : "";
|
|
8609
8865
|
};
|
|
8610
8866
|
const syncLyricTerms = () => {
|
|
8867
|
+
if (customVocalsMap.has(active.lyricModel)) {
|
|
8868
|
+
lyricTerms.classList.add("dtm-hidden");
|
|
8869
|
+
return;
|
|
8870
|
+
}
|
|
8611
8871
|
const url2 = active.lyricModel ? KOE_VOICEBANK_TERMS[active.lyricModel] : void 0;
|
|
8612
8872
|
if (url2) {
|
|
8613
|
-
const label = lyricModelLabel(active.lyricModel);
|
|
8873
|
+
const label = lyricModelLabel(active.lyricModel, customVocalsMap);
|
|
8614
8874
|
lyricTermsLink.textContent = `${label}UTAU\u97F3\u6E90`;
|
|
8615
8875
|
lyricTermsLink.href = url2;
|
|
8616
8876
|
lyricTerms.classList.remove("dtm-hidden");
|
|
@@ -8619,7 +8879,24 @@ var mountDAW = (target, options = {}) => {
|
|
|
8619
8879
|
}
|
|
8620
8880
|
};
|
|
8621
8881
|
const syncLyricIcon = () => {
|
|
8622
|
-
|
|
8882
|
+
if (!active.lyricModel) {
|
|
8883
|
+
lyricIcon.removeAttribute("src");
|
|
8884
|
+
lyricIcon.classList.add("dtm-hidden");
|
|
8885
|
+
return;
|
|
8886
|
+
}
|
|
8887
|
+
const customDef = customVocalsMap.get(active.lyricModel);
|
|
8888
|
+
if (customDef !== void 0) {
|
|
8889
|
+
const iconSrc = customDef.iconUrl || FALLBACK_VOCAL_ICON;
|
|
8890
|
+
lyricIcon.src = iconSrc;
|
|
8891
|
+
lyricIcon.classList.remove("dtm-hidden");
|
|
8892
|
+
lyricIcon.onerror = () => {
|
|
8893
|
+
lyricIcon.onerror = null;
|
|
8894
|
+
lyricIcon.src = FALLBACK_VOCAL_ICON;
|
|
8895
|
+
};
|
|
8896
|
+
return;
|
|
8897
|
+
}
|
|
8898
|
+
lyricIcon.onerror = null;
|
|
8899
|
+
const imgKey = VOICE_IMAGE_KEY[active.lyricModel.toLowerCase()];
|
|
8623
8900
|
const src = imgKey ? VOICE_IMAGES[imgKey] : void 0;
|
|
8624
8901
|
if (src) {
|
|
8625
8902
|
lyricIcon.src = src;
|
|
@@ -8638,11 +8915,64 @@ var mountDAW = (target, options = {}) => {
|
|
|
8638
8915
|
};
|
|
8639
8916
|
syncLyricVisibility();
|
|
8640
8917
|
lyricModelSel.addEventListener("change", () => {
|
|
8918
|
+
if (lyricModelSel.value === CUSTOM_VOCAL_ADD_VALUE) {
|
|
8919
|
+
lyricCustomNote.textContent = "";
|
|
8920
|
+
lyricCustomAlias.value = "";
|
|
8921
|
+
lyricCustomKey.value = "";
|
|
8922
|
+
lyricCustom.classList.remove("dtm-hidden");
|
|
8923
|
+
return;
|
|
8924
|
+
}
|
|
8925
|
+
lyricCustom.classList.add("dtm-hidden");
|
|
8641
8926
|
active.lyricModel = lyricModelSel.value;
|
|
8642
8927
|
syncLyricVisibility();
|
|
8643
8928
|
syncInstDisabled();
|
|
8644
8929
|
fireLyricsChange(active);
|
|
8645
8930
|
});
|
|
8931
|
+
lyricCustomGuide.addEventListener("click", () => {
|
|
8932
|
+
showModal("\u30AB\u30B9\u30BF\u30E0\u97F3\u6E90(.koe)\u306E\u4F7F\u3044\u65B9", KOE_INFO_HTML);
|
|
8933
|
+
});
|
|
8934
|
+
lyricCustomApply.addEventListener("click", () => {
|
|
8935
|
+
const src = lyricCustomSrc.value.trim();
|
|
8936
|
+
if (!isValidHttpUrl(src)) {
|
|
8937
|
+
lyricCustomNote.textContent = "\u97F3\u6E90URL\u304C\u4E0D\u6B63\u3067\u3059\uFF08http/https\u306E\u307F\u30FB2048\u6587\u5B57\u307E\u3067\uFF09";
|
|
8938
|
+
return;
|
|
8939
|
+
}
|
|
8940
|
+
const iconRaw = lyricCustomIcon.value.trim();
|
|
8941
|
+
const iconUrl = isValidHttpUrl(iconRaw) ? iconRaw : "";
|
|
8942
|
+
const alias = lyricCustomAlias.value.trim();
|
|
8943
|
+
const existing = [...customVocalsMap.values()].find(
|
|
8944
|
+
(d) => d.url === src
|
|
8945
|
+
);
|
|
8946
|
+
const keyRaw = lyricCustomKey.value.trim().toLowerCase();
|
|
8947
|
+
let key;
|
|
8948
|
+
if (keyRaw) {
|
|
8949
|
+
if (!CUSTOM_VOCAL_KEY_RE.test(keyRaw)) {
|
|
8950
|
+
lyricCustomNote.textContent = "\u8B58\u5225\u5B50\u304C\u4E0D\u6B63\u3067\u3059\uFF08\u82F1\u5B57\u307E\u305F\u306F\u30A2\u30F3\u30C0\u30FC\u30B9\u30B3\u30A2\u3067\u59CB\u307E\u308B\u82F1\u6570\u5B57\u30FB_\u306E\u307F\uFF09";
|
|
8951
|
+
return;
|
|
8952
|
+
}
|
|
8953
|
+
if (BASE_LYRIC_MODELS.includes(keyRaw)) {
|
|
8954
|
+
lyricCustomNote.textContent = "\u305D\u306E\u8B58\u5225\u5B50\u306F\u5185\u8535\u30E2\u30C7\u30EB\u540D\u3068\u885D\u7A81\u3057\u3066\u3044\u307E\u3059";
|
|
8955
|
+
return;
|
|
8956
|
+
}
|
|
8957
|
+
const conflict = customVocalsMap.get(keyRaw);
|
|
8958
|
+
if (conflict && conflict.url !== src) {
|
|
8959
|
+
lyricCustomNote.textContent = "\u305D\u306E\u8B58\u5225\u5B50\u306F\u5225\u306E\u97F3\u6E90\u306B\u4F7F\u7528\u6E08\u307F\u3067\u3059";
|
|
8960
|
+
return;
|
|
8961
|
+
}
|
|
8962
|
+
key = keyRaw;
|
|
8963
|
+
} else {
|
|
8964
|
+
key = existing?.key ?? genCustomVocalKey();
|
|
8965
|
+
}
|
|
8966
|
+
registerCustomVocal({
|
|
8967
|
+
key,
|
|
8968
|
+
iconUrl: iconUrl || (existing?.iconUrl ?? ""),
|
|
8969
|
+
url: src,
|
|
8970
|
+
label: alias || existing?.label
|
|
8971
|
+
});
|
|
8972
|
+
active.lyricModel = key;
|
|
8973
|
+
fireLyricsChange(active);
|
|
8974
|
+
updateTrackPanel();
|
|
8975
|
+
});
|
|
8646
8976
|
lyricOctaveSel.addEventListener("change", () => {
|
|
8647
8977
|
active.vocalOctave = Number.parseInt(lyricOctaveSel.value, 10);
|
|
8648
8978
|
fireLyricsChange(active);
|
|
@@ -8826,9 +9156,25 @@ var mountDAW = (target, options = {}) => {
|
|
|
8826
9156
|
const head = params ? `${x.model} ${params}` : x.model;
|
|
8827
9157
|
return `@@${x.i} ${head} ${x.text}`;
|
|
8828
9158
|
});
|
|
8829
|
-
const
|
|
9159
|
+
const customVocalDecls = [];
|
|
9160
|
+
for (const [key, def] of customVocalsMap) {
|
|
9161
|
+
const isUsed = trackStates.some(
|
|
9162
|
+
(t) => t.lyricModel.trim().toLowerCase() === key && t.lyrics.trim().length > 0 && clipNotes(t.core.getNotes()).length > 0
|
|
9163
|
+
);
|
|
9164
|
+
if (!isUsed) continue;
|
|
9165
|
+
const iconPart = def.iconUrl || "-";
|
|
9166
|
+
customVocalDecls.push(`@@${key} ${iconPart} ${def.url}`);
|
|
9167
|
+
}
|
|
9168
|
+
const full = [
|
|
9169
|
+
metaLineFull,
|
|
9170
|
+
...customVocalDecls,
|
|
9171
|
+
...trackLines,
|
|
9172
|
+
...lyricLines,
|
|
9173
|
+
MML_END_MARKER
|
|
9174
|
+
].filter((s) => s.length > 0).join(";\n");
|
|
8830
9175
|
const minified = [
|
|
8831
9176
|
metaLineMini,
|
|
9177
|
+
...customVocalDecls,
|
|
8832
9178
|
...trackLinesMini,
|
|
8833
9179
|
...lyricLines,
|
|
8834
9180
|
MML_END_MARKER
|
|
@@ -8893,6 +9239,8 @@ var mountDAW = (target, options = {}) => {
|
|
|
8893
9239
|
stop();
|
|
8894
9240
|
clearAll();
|
|
8895
9241
|
for (const t of trackStates) t.core.setLoadMode(true);
|
|
9242
|
+
resetCustomVocals();
|
|
9243
|
+
for (const def of parseCustomVocals(mml)) registerCustomVocal(def);
|
|
8896
9244
|
const {
|
|
8897
9245
|
placements,
|
|
8898
9246
|
bpm: parsedBpm,
|
|
@@ -10252,6 +10600,9 @@ var SoundFont = class _SoundFont {
|
|
|
10252
10600
|
this.ch = ch;
|
|
10253
10601
|
this.isDrum = isDrum;
|
|
10254
10602
|
}
|
|
10603
|
+
zones;
|
|
10604
|
+
ch;
|
|
10605
|
+
isDrum;
|
|
10255
10606
|
static afterTime = 0.5;
|
|
10256
10607
|
static fonts = /* @__PURE__ */ new Map();
|
|
10257
10608
|
static ch = -1;
|
|
@@ -11216,12 +11567,14 @@ export {
|
|
|
11216
11567
|
init,
|
|
11217
11568
|
injectStyles,
|
|
11218
11569
|
isChordHeavyTrack,
|
|
11570
|
+
isValidHttpUrl,
|
|
11219
11571
|
koeUrl,
|
|
11220
11572
|
mountDAW,
|
|
11221
11573
|
mountMmlPlayer,
|
|
11222
11574
|
normalizeLyrics,
|
|
11223
11575
|
onClick,
|
|
11224
11576
|
panToStereo,
|
|
11577
|
+
parseCustomVocals,
|
|
11225
11578
|
parseLyrics,
|
|
11226
11579
|
parseMML,
|
|
11227
11580
|
parseMmlMeta,
|
|
@@ -11230,6 +11583,7 @@ export {
|
|
|
11230
11583
|
setDrawOffset,
|
|
11231
11584
|
shiftNotes,
|
|
11232
11585
|
showLoadingOverlay,
|
|
11586
|
+
stripCustomVocals,
|
|
11233
11587
|
stripLyrics,
|
|
11234
11588
|
stripMmlMeta,
|
|
11235
11589
|
vocalVolumeToGain
|