@onjmin/dtm 0.1.87 → 0.1.89
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 +49 -11
- package/dist/index.d.ts +49 -11
- package/dist/index.js +493 -288
- package/dist/index.mjs +493 -288
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1335,6 +1335,149 @@ var getDrumPatternKeys = (name, dict) => {
|
|
|
1335
1335
|
return Array.from(keys);
|
|
1336
1336
|
};
|
|
1337
1337
|
|
|
1338
|
+
// src/channel-strip.ts
|
|
1339
|
+
var clamp = (v, lo, hi) => Math.max(lo, Math.min(hi, v));
|
|
1340
|
+
var compressionParams = (amount) => {
|
|
1341
|
+
const t = clamp(amount, 0, 100) / 100;
|
|
1342
|
+
return {
|
|
1343
|
+
threshold: 0 + (-24 - 0) * t,
|
|
1344
|
+
ratio: 1 + (12 - 1) * t,
|
|
1345
|
+
knee: 0 + (6 - 0) * t,
|
|
1346
|
+
attack: 0.02 + (3e-3 - 0.02) * t,
|
|
1347
|
+
release: 0.25 + (0.15 - 0.25) * t
|
|
1348
|
+
};
|
|
1349
|
+
};
|
|
1350
|
+
var EQ_LOW_FREQ = 200;
|
|
1351
|
+
var EQ_MID_FREQ = 1e3;
|
|
1352
|
+
var EQ_HIGH_FREQ = 5e3;
|
|
1353
|
+
var EQ_MID_Q = 1;
|
|
1354
|
+
var EQ_MAX_DB = 12;
|
|
1355
|
+
var createChannelStrip = (ctx, destination, options = {}) => {
|
|
1356
|
+
const input = ctx.createGain();
|
|
1357
|
+
const eqLow = ctx.createBiquadFilter();
|
|
1358
|
+
eqLow.type = "lowshelf";
|
|
1359
|
+
eqLow.frequency.value = EQ_LOW_FREQ;
|
|
1360
|
+
eqLow.gain.value = clamp(options.eqLow ?? 0, -EQ_MAX_DB, EQ_MAX_DB);
|
|
1361
|
+
const eqMid = ctx.createBiquadFilter();
|
|
1362
|
+
eqMid.type = "peaking";
|
|
1363
|
+
eqMid.frequency.value = EQ_MID_FREQ;
|
|
1364
|
+
eqMid.Q.value = EQ_MID_Q;
|
|
1365
|
+
eqMid.gain.value = clamp(options.eqMid ?? 0, -EQ_MAX_DB, EQ_MAX_DB);
|
|
1366
|
+
const eqHigh = ctx.createBiquadFilter();
|
|
1367
|
+
eqHigh.type = "highshelf";
|
|
1368
|
+
eqHigh.frequency.value = EQ_HIGH_FREQ;
|
|
1369
|
+
eqHigh.gain.value = clamp(options.eqHigh ?? 0, -EQ_MAX_DB, EQ_MAX_DB);
|
|
1370
|
+
input.connect(eqLow);
|
|
1371
|
+
eqLow.connect(eqMid);
|
|
1372
|
+
eqMid.connect(eqHigh);
|
|
1373
|
+
const compressor = ctx.createDynamicsCompressor();
|
|
1374
|
+
const applyCompression = (amount) => {
|
|
1375
|
+
const p = compressionParams(amount);
|
|
1376
|
+
const now = ctx.currentTime;
|
|
1377
|
+
compressor.threshold.setValueAtTime(p.threshold, now);
|
|
1378
|
+
compressor.ratio.setValueAtTime(p.ratio, now);
|
|
1379
|
+
compressor.knee.setValueAtTime(p.knee, now);
|
|
1380
|
+
compressor.attack.setValueAtTime(p.attack, now);
|
|
1381
|
+
compressor.release.setValueAtTime(p.release, now);
|
|
1382
|
+
};
|
|
1383
|
+
applyCompression(options.compression ?? 0);
|
|
1384
|
+
const splitter = ctx.createChannelSplitter(2);
|
|
1385
|
+
const mid = ctx.createGain();
|
|
1386
|
+
mid.gain.value = 0.5;
|
|
1387
|
+
splitter.connect(mid, 0);
|
|
1388
|
+
splitter.connect(mid, 1);
|
|
1389
|
+
const sideSum = ctx.createGain();
|
|
1390
|
+
sideSum.gain.value = 1;
|
|
1391
|
+
const sideL = ctx.createGain();
|
|
1392
|
+
sideL.gain.value = 0.5;
|
|
1393
|
+
const sideR = ctx.createGain();
|
|
1394
|
+
sideR.gain.value = -0.5;
|
|
1395
|
+
splitter.connect(sideL, 0);
|
|
1396
|
+
splitter.connect(sideR, 1);
|
|
1397
|
+
sideL.connect(sideSum);
|
|
1398
|
+
sideR.connect(sideSum);
|
|
1399
|
+
const widthGain = ctx.createGain();
|
|
1400
|
+
sideSum.connect(widthGain);
|
|
1401
|
+
const widthInv = ctx.createGain();
|
|
1402
|
+
widthInv.gain.value = -1;
|
|
1403
|
+
widthGain.connect(widthInv);
|
|
1404
|
+
const outL = ctx.createGain();
|
|
1405
|
+
mid.connect(outL);
|
|
1406
|
+
widthGain.connect(outL);
|
|
1407
|
+
const outR = ctx.createGain();
|
|
1408
|
+
mid.connect(outR);
|
|
1409
|
+
widthInv.connect(outR);
|
|
1410
|
+
const merger = ctx.createChannelMerger(2);
|
|
1411
|
+
outL.connect(merger, 0, 0);
|
|
1412
|
+
outR.connect(merger, 0, 1);
|
|
1413
|
+
const setWidth = (width) => {
|
|
1414
|
+
widthGain.gain.setTargetAtTime(
|
|
1415
|
+
clamp(width, 0, 200) / 100,
|
|
1416
|
+
ctx.currentTime,
|
|
1417
|
+
0.02
|
|
1418
|
+
);
|
|
1419
|
+
};
|
|
1420
|
+
setWidth(options.width ?? 100);
|
|
1421
|
+
eqHigh.connect(compressor);
|
|
1422
|
+
compressor.connect(splitter);
|
|
1423
|
+
merger.connect(destination);
|
|
1424
|
+
const reverbSendGain = ctx.createGain();
|
|
1425
|
+
reverbSendGain.gain.value = clamp(options.reverbSend ?? 0, 0, 100) / 100;
|
|
1426
|
+
merger.connect(reverbSendGain);
|
|
1427
|
+
if (options.reverbBus) reverbSendGain.connect(options.reverbBus);
|
|
1428
|
+
return {
|
|
1429
|
+
input,
|
|
1430
|
+
setEqLow: (db) => {
|
|
1431
|
+
eqLow.gain.setTargetAtTime(
|
|
1432
|
+
clamp(db, -EQ_MAX_DB, EQ_MAX_DB),
|
|
1433
|
+
ctx.currentTime,
|
|
1434
|
+
0.02
|
|
1435
|
+
);
|
|
1436
|
+
},
|
|
1437
|
+
setEqMid: (db) => {
|
|
1438
|
+
eqMid.gain.setTargetAtTime(
|
|
1439
|
+
clamp(db, -EQ_MAX_DB, EQ_MAX_DB),
|
|
1440
|
+
ctx.currentTime,
|
|
1441
|
+
0.02
|
|
1442
|
+
);
|
|
1443
|
+
},
|
|
1444
|
+
setEqHigh: (db) => {
|
|
1445
|
+
eqHigh.gain.setTargetAtTime(
|
|
1446
|
+
clamp(db, -EQ_MAX_DB, EQ_MAX_DB),
|
|
1447
|
+
ctx.currentTime,
|
|
1448
|
+
0.02
|
|
1449
|
+
);
|
|
1450
|
+
},
|
|
1451
|
+
setCompression: applyCompression,
|
|
1452
|
+
setWidth,
|
|
1453
|
+
setReverbSend: (amount) => {
|
|
1454
|
+
reverbSendGain.gain.setTargetAtTime(
|
|
1455
|
+
clamp(amount, 0, 100) / 100,
|
|
1456
|
+
ctx.currentTime,
|
|
1457
|
+
0.02
|
|
1458
|
+
);
|
|
1459
|
+
},
|
|
1460
|
+
dispose: () => {
|
|
1461
|
+
input.disconnect();
|
|
1462
|
+
eqLow.disconnect();
|
|
1463
|
+
eqMid.disconnect();
|
|
1464
|
+
eqHigh.disconnect();
|
|
1465
|
+
compressor.disconnect();
|
|
1466
|
+
splitter.disconnect();
|
|
1467
|
+
mid.disconnect();
|
|
1468
|
+
sideSum.disconnect();
|
|
1469
|
+
sideL.disconnect();
|
|
1470
|
+
sideR.disconnect();
|
|
1471
|
+
widthGain.disconnect();
|
|
1472
|
+
widthInv.disconnect();
|
|
1473
|
+
outL.disconnect();
|
|
1474
|
+
outR.disconnect();
|
|
1475
|
+
merger.disconnect();
|
|
1476
|
+
reverbSendGain.disconnect();
|
|
1477
|
+
}
|
|
1478
|
+
};
|
|
1479
|
+
};
|
|
1480
|
+
|
|
1338
1481
|
// src/chords.ts
|
|
1339
1482
|
var C3 = 48;
|
|
1340
1483
|
var buildChordPlacements = (options) => {
|
|
@@ -2164,7 +2307,7 @@ var normalizeLyricLines = (lines) => {
|
|
|
2164
2307
|
var LYRIC_LINE = /^@@(\d+)\s*(.*)$/;
|
|
2165
2308
|
var isLyricContinuation = (seg) => !/^[@#]/.test(seg);
|
|
2166
2309
|
var splitSegments = (mml) => mml.split(/[;\n\r]+/).map((s) => s.trim()).filter((s) => s.length > 0);
|
|
2167
|
-
var
|
|
2310
|
+
var clamp2 = (value, lo, hi) => Math.min(hi, Math.max(lo, value));
|
|
2168
2311
|
var MAX_VOCAL_VOLUME = 400;
|
|
2169
2312
|
var VOCAL_BOOST_DB_PER_PERCENT = 0.08;
|
|
2170
2313
|
var vocalVolumeToGain = (v) => {
|
|
@@ -2189,7 +2332,7 @@ var parseLyrics = (mml) => {
|
|
|
2189
2332
|
let delay = 0;
|
|
2190
2333
|
let gender = 50;
|
|
2191
2334
|
let breathiness = 50;
|
|
2192
|
-
let
|
|
2335
|
+
let octaveUnison = "none";
|
|
2193
2336
|
const modelMatch = rest.match(
|
|
2194
2337
|
/^([a-z_][a-z0-9_]*?)(?=(?:[vqpobrghew]-?\d)|[^a-z0-9_]|$)(?::(\d+))?/i
|
|
2195
2338
|
);
|
|
@@ -2198,7 +2341,7 @@ var parseLyrics = (mml) => {
|
|
|
2198
2341
|
if (modelMatch) {
|
|
2199
2342
|
model = modelMatch[1].toLowerCase();
|
|
2200
2343
|
if (modelMatch[2]) {
|
|
2201
|
-
volume =
|
|
2344
|
+
volume = clamp2(Number.parseInt(modelMatch[2], 10), 0, MAX_VOCAL_VOLUME);
|
|
2202
2345
|
}
|
|
2203
2346
|
metaTokens.push(modelMatch[0]);
|
|
2204
2347
|
rest = rest.substring(modelMatch[0].length).trim();
|
|
@@ -2206,28 +2349,28 @@ var parseLyrics = (mml) => {
|
|
|
2206
2349
|
while (true) {
|
|
2207
2350
|
const vMatch = rest.match(/^v(\d+)/i);
|
|
2208
2351
|
if (vMatch) {
|
|
2209
|
-
volume =
|
|
2352
|
+
volume = clamp2(Number.parseInt(vMatch[1], 10), 0, MAX_VOCAL_VOLUME);
|
|
2210
2353
|
metaTokens.push(vMatch[0]);
|
|
2211
2354
|
rest = rest.substring(vMatch[0].length).trim();
|
|
2212
2355
|
continue;
|
|
2213
2356
|
}
|
|
2214
2357
|
const qMatch = rest.match(/^q(\d+)/i);
|
|
2215
2358
|
if (qMatch) {
|
|
2216
|
-
gate =
|
|
2359
|
+
gate = clamp2(Number.parseInt(qMatch[1], 10), 0, 100);
|
|
2217
2360
|
metaTokens.push(qMatch[0]);
|
|
2218
2361
|
rest = rest.substring(qMatch[0].length).trim();
|
|
2219
2362
|
continue;
|
|
2220
2363
|
}
|
|
2221
2364
|
const pMatch = rest.match(/^p(\d+)/i);
|
|
2222
2365
|
if (pMatch) {
|
|
2223
|
-
pan =
|
|
2366
|
+
pan = clamp2(Number.parseInt(pMatch[1], 10), 0, 127);
|
|
2224
2367
|
metaTokens.push(pMatch[0]);
|
|
2225
2368
|
rest = rest.substring(pMatch[0].length).trim();
|
|
2226
2369
|
continue;
|
|
2227
2370
|
}
|
|
2228
2371
|
const oMatch = rest.match(/^o(-?\d+)/i);
|
|
2229
2372
|
if (oMatch) {
|
|
2230
|
-
octave =
|
|
2373
|
+
octave = clamp2(Number.parseInt(oMatch[1], 10), -2, 2);
|
|
2231
2374
|
metaTokens.push(oMatch[0]);
|
|
2232
2375
|
rest = rest.substring(oMatch[0].length).trim();
|
|
2233
2376
|
continue;
|
|
@@ -2241,35 +2384,35 @@ var parseLyrics = (mml) => {
|
|
|
2241
2384
|
}
|
|
2242
2385
|
const rMatch = rest.match(/^r(\d+)/i);
|
|
2243
2386
|
if (rMatch) {
|
|
2244
|
-
reverb =
|
|
2387
|
+
reverb = clamp2(Number.parseInt(rMatch[1], 10), 0, 100);
|
|
2245
2388
|
metaTokens.push(rMatch[0]);
|
|
2246
2389
|
rest = rest.substring(rMatch[0].length).trim();
|
|
2247
2390
|
continue;
|
|
2248
2391
|
}
|
|
2249
2392
|
const gMatch = rest.match(/^g(\d+)/i);
|
|
2250
2393
|
if (gMatch) {
|
|
2251
|
-
gender =
|
|
2394
|
+
gender = clamp2(Number.parseInt(gMatch[1], 10), 0, 100);
|
|
2252
2395
|
metaTokens.push(gMatch[0]);
|
|
2253
2396
|
rest = rest.substring(gMatch[0].length).trim();
|
|
2254
2397
|
continue;
|
|
2255
2398
|
}
|
|
2256
2399
|
const hMatch = rest.match(/^h(\d+)/i);
|
|
2257
2400
|
if (hMatch) {
|
|
2258
|
-
breathiness =
|
|
2401
|
+
breathiness = clamp2(Number.parseInt(hMatch[1], 10), 0, 100);
|
|
2259
2402
|
metaTokens.push(hMatch[0]);
|
|
2260
2403
|
rest = rest.substring(hMatch[0].length).trim();
|
|
2261
2404
|
continue;
|
|
2262
2405
|
}
|
|
2263
2406
|
const eMatch = rest.match(/^e(\d+)/i);
|
|
2264
2407
|
if (eMatch) {
|
|
2265
|
-
delay =
|
|
2408
|
+
delay = clamp2(Number.parseInt(eMatch[1], 10), 0, 100);
|
|
2266
2409
|
metaTokens.push(eMatch[0]);
|
|
2267
2410
|
rest = rest.substring(eMatch[0].length).trim();
|
|
2268
2411
|
continue;
|
|
2269
2412
|
}
|
|
2270
|
-
const wMatch = rest.match(/^w([
|
|
2413
|
+
const wMatch = rest.match(/^w([0-3])/i);
|
|
2271
2414
|
if (wMatch) {
|
|
2272
|
-
|
|
2415
|
+
octaveUnison = ["none", "down", "up", "both"][Number.parseInt(wMatch[1], 10)];
|
|
2273
2416
|
metaTokens.push(wMatch[0]);
|
|
2274
2417
|
rest = rest.substring(wMatch[0].length).trim();
|
|
2275
2418
|
continue;
|
|
@@ -2293,7 +2436,7 @@ var parseLyrics = (mml) => {
|
|
|
2293
2436
|
delay,
|
|
2294
2437
|
gender,
|
|
2295
2438
|
breathiness,
|
|
2296
|
-
|
|
2439
|
+
octaveUnison,
|
|
2297
2440
|
syllables,
|
|
2298
2441
|
metaText: metaTokens.join(" "),
|
|
2299
2442
|
...lineBreaks.length > 0 ? { lineBreaks } : {}
|
|
@@ -2890,8 +3033,19 @@ var createKoeVoice = async (ctx, destination, options) => {
|
|
|
2890
3033
|
var PREWARM_NOTES = 3;
|
|
2891
3034
|
var STREAM_LOOKAHEAD_SEC = 1.5;
|
|
2892
3035
|
var STREAM_POLL_MS = 100;
|
|
2893
|
-
var
|
|
2894
|
-
var
|
|
3036
|
+
var OCTAVE_UNISON_PEAK_SCALE = 0.6;
|
|
3037
|
+
var octaveUnisonOffsets = (mode) => {
|
|
3038
|
+
switch (mode) {
|
|
3039
|
+
case "down":
|
|
3040
|
+
return [-12];
|
|
3041
|
+
case "up":
|
|
3042
|
+
return [12];
|
|
3043
|
+
case "both":
|
|
3044
|
+
return [-12, 12];
|
|
3045
|
+
default:
|
|
3046
|
+
return [];
|
|
3047
|
+
}
|
|
3048
|
+
};
|
|
2895
3049
|
var FALLBACK_MODEL = "klatt";
|
|
2896
3050
|
var createSingingVoices = (ctx, destination, options = {}) => {
|
|
2897
3051
|
const catalog = {};
|
|
@@ -2986,12 +3140,12 @@ var createSingingVoices = (ctx, destination, options = {}) => {
|
|
|
2986
3140
|
vibrato: track.vibrato,
|
|
2987
3141
|
expr
|
|
2988
3142
|
});
|
|
2989
|
-
|
|
3143
|
+
for (const offset of octaveUnisonOffsets(track.octaveUnison)) {
|
|
2990
3144
|
tasks.push({
|
|
2991
3145
|
model: m,
|
|
2992
3146
|
note,
|
|
2993
3147
|
prevVowel,
|
|
2994
|
-
pitch: note.pitch +
|
|
3148
|
+
pitch: note.pitch + offset,
|
|
2995
3149
|
vibrato: track.vibrato,
|
|
2996
3150
|
expr
|
|
2997
3151
|
});
|
|
@@ -3106,11 +3260,8 @@ var createSingingVoices = (ctx, destination, options = {}) => {
|
|
|
3106
3260
|
}
|
|
3107
3261
|
};
|
|
3108
3262
|
dispatchNote(note.pitch, 1);
|
|
3109
|
-
|
|
3110
|
-
dispatchNote(
|
|
3111
|
-
note.pitch + OCTAVE_DOUBLE_SEMITONES,
|
|
3112
|
-
OCTAVE_DOUBLE_PEAK_SCALE
|
|
3113
|
-
);
|
|
3263
|
+
for (const offset of octaveUnisonOffsets(track.octaveUnison)) {
|
|
3264
|
+
dispatchNote(note.pitch + offset, OCTAVE_UNISON_PEAK_SCALE);
|
|
3114
3265
|
}
|
|
3115
3266
|
if (!(model.renderToCache && model.scheduleCached)) {
|
|
3116
3267
|
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
@@ -3170,11 +3321,12 @@ var PITCH_MAP = {
|
|
|
3170
3321
|
a: 9,
|
|
3171
3322
|
b: 11
|
|
3172
3323
|
};
|
|
3173
|
-
var
|
|
3324
|
+
var clamp3 = (value, lo, hi) => Math.min(hi, Math.max(lo, value));
|
|
3174
3325
|
var META_DIRECTIVE = /#(inst|drum|drumfont|volume|drumvolume|reverb|reverbdecay|reverbpredelay|delay|delaydiv|fadein|fadeout|mode)=([\w-]+)/gi;
|
|
3175
3326
|
var TRACK_INST_DIRECTIVE = /#t(\d+)inst=([^#;\r\n]+)/gi;
|
|
3176
3327
|
var TRACK_COMP_DIRECTIVE = /#t(\d+)comp=(\d+)/gi;
|
|
3177
3328
|
var TRACK_WIDTH_DIRECTIVE = /#t(\d+)width=(\d+)/gi;
|
|
3329
|
+
var TRACK_REVERBSEND_DIRECTIVE = /#t(\d+)rev=(\d+)/gi;
|
|
3178
3330
|
var TRACK_EQLOW_DIRECTIVE = /#t(\d+)eqlo=(-?\d+)/gi;
|
|
3179
3331
|
var TRACK_EQMID_DIRECTIVE = /#t(\d+)eqmid=(-?\d+)/gi;
|
|
3180
3332
|
var TRACK_EQHIGH_DIRECTIVE = /#t(\d+)eqhi=(-?\d+)/gi;
|
|
@@ -3193,24 +3345,24 @@ var parseMmlMeta = (mml) => {
|
|
|
3193
3345
|
if (!Number.isNaN(dv)) meta.drumVolume = dv;
|
|
3194
3346
|
} else if (key === "reverb") {
|
|
3195
3347
|
const rv = Number.parseInt(m[2], 10);
|
|
3196
|
-
if (!Number.isNaN(rv)) meta.reverb =
|
|
3348
|
+
if (!Number.isNaN(rv)) meta.reverb = clamp3(rv, 0, 100);
|
|
3197
3349
|
} else if (key === "reverbdecay") {
|
|
3198
3350
|
const rd = Number.parseInt(m[2], 10);
|
|
3199
|
-
if (!Number.isNaN(rd)) meta.reverbDecay =
|
|
3351
|
+
if (!Number.isNaN(rd)) meta.reverbDecay = clamp3(rd, 3, 40);
|
|
3200
3352
|
} else if (key === "reverbpredelay") {
|
|
3201
3353
|
const rp = Number.parseInt(m[2], 10);
|
|
3202
|
-
if (!Number.isNaN(rp)) meta.reverbPreDelay =
|
|
3354
|
+
if (!Number.isNaN(rp)) meta.reverbPreDelay = clamp3(rp, 0, 150);
|
|
3203
3355
|
} else if (key === "delay") {
|
|
3204
3356
|
const dv = Number.parseInt(m[2], 10);
|
|
3205
|
-
if (!Number.isNaN(dv)) meta.delay =
|
|
3357
|
+
if (!Number.isNaN(dv)) meta.delay = clamp3(dv, 0, 100);
|
|
3206
3358
|
} else if (key === "delaydiv") {
|
|
3207
3359
|
if (["4", "8", "8d", "16"].includes(m[2])) meta.delayDivision = m[2];
|
|
3208
3360
|
} else if (key === "fadein") {
|
|
3209
3361
|
const fi = Number.parseInt(m[2], 10);
|
|
3210
|
-
if (!Number.isNaN(fi)) meta.fadeIn =
|
|
3362
|
+
if (!Number.isNaN(fi)) meta.fadeIn = clamp3(fi, 0, 100);
|
|
3211
3363
|
} else if (key === "fadeout") {
|
|
3212
3364
|
const fo = Number.parseInt(m[2], 10);
|
|
3213
|
-
if (!Number.isNaN(fo)) meta.fadeOut =
|
|
3365
|
+
if (!Number.isNaN(fo)) meta.fadeOut = clamp3(fo, 0, 100);
|
|
3214
3366
|
} else if (key === "mode") {
|
|
3215
3367
|
if (m[2] === "simple" || m[2] === "advanced") {
|
|
3216
3368
|
meta.mode = m[2];
|
|
@@ -3227,7 +3379,7 @@ var parseMmlMeta = (mml) => {
|
|
|
3227
3379
|
}
|
|
3228
3380
|
for (const m of mml.matchAll(TRACK_COMP_DIRECTIVE)) {
|
|
3229
3381
|
const idx = Number.parseInt(m[1], 10);
|
|
3230
|
-
const val =
|
|
3382
|
+
const val = clamp3(Number.parseInt(m[2], 10), 0, 100);
|
|
3231
3383
|
if (!Number.isNaN(idx) && !Number.isNaN(val)) {
|
|
3232
3384
|
meta.trackCompression ??= {};
|
|
3233
3385
|
meta.trackCompression[idx] = val;
|
|
@@ -3235,15 +3387,23 @@ var parseMmlMeta = (mml) => {
|
|
|
3235
3387
|
}
|
|
3236
3388
|
for (const m of mml.matchAll(TRACK_WIDTH_DIRECTIVE)) {
|
|
3237
3389
|
const idx = Number.parseInt(m[1], 10);
|
|
3238
|
-
const val =
|
|
3390
|
+
const val = clamp3(Number.parseInt(m[2], 10), 0, 200);
|
|
3239
3391
|
if (!Number.isNaN(idx) && !Number.isNaN(val)) {
|
|
3240
3392
|
meta.trackWidth ??= {};
|
|
3241
3393
|
meta.trackWidth[idx] = val;
|
|
3242
3394
|
}
|
|
3243
3395
|
}
|
|
3396
|
+
for (const m of mml.matchAll(TRACK_REVERBSEND_DIRECTIVE)) {
|
|
3397
|
+
const idx = Number.parseInt(m[1], 10);
|
|
3398
|
+
const val = clamp3(Number.parseInt(m[2], 10), 0, 100);
|
|
3399
|
+
if (!Number.isNaN(idx) && !Number.isNaN(val)) {
|
|
3400
|
+
meta.trackReverbSend ??= {};
|
|
3401
|
+
meta.trackReverbSend[idx] = val;
|
|
3402
|
+
}
|
|
3403
|
+
}
|
|
3244
3404
|
for (const m of mml.matchAll(TRACK_EQLOW_DIRECTIVE)) {
|
|
3245
3405
|
const idx = Number.parseInt(m[1], 10);
|
|
3246
|
-
const val =
|
|
3406
|
+
const val = clamp3(Number.parseInt(m[2], 10), -12, 12);
|
|
3247
3407
|
if (!Number.isNaN(idx) && !Number.isNaN(val)) {
|
|
3248
3408
|
meta.trackEqLow ??= {};
|
|
3249
3409
|
meta.trackEqLow[idx] = val;
|
|
@@ -3251,7 +3411,7 @@ var parseMmlMeta = (mml) => {
|
|
|
3251
3411
|
}
|
|
3252
3412
|
for (const m of mml.matchAll(TRACK_EQMID_DIRECTIVE)) {
|
|
3253
3413
|
const idx = Number.parseInt(m[1], 10);
|
|
3254
|
-
const val =
|
|
3414
|
+
const val = clamp3(Number.parseInt(m[2], 10), -12, 12);
|
|
3255
3415
|
if (!Number.isNaN(idx) && !Number.isNaN(val)) {
|
|
3256
3416
|
meta.trackEqMid ??= {};
|
|
3257
3417
|
meta.trackEqMid[idx] = val;
|
|
@@ -3259,7 +3419,7 @@ var parseMmlMeta = (mml) => {
|
|
|
3259
3419
|
}
|
|
3260
3420
|
for (const m of mml.matchAll(TRACK_EQHIGH_DIRECTIVE)) {
|
|
3261
3421
|
const idx = Number.parseInt(m[1], 10);
|
|
3262
|
-
const val =
|
|
3422
|
+
const val = clamp3(Number.parseInt(m[2], 10), -12, 12);
|
|
3263
3423
|
if (!Number.isNaN(idx) && !Number.isNaN(val)) {
|
|
3264
3424
|
meta.trackEqHigh ??= {};
|
|
3265
3425
|
meta.trackEqHigh[idx] = val;
|
|
@@ -3267,7 +3427,7 @@ var parseMmlMeta = (mml) => {
|
|
|
3267
3427
|
}
|
|
3268
3428
|
return meta;
|
|
3269
3429
|
};
|
|
3270
|
-
var stripMmlMeta = (mml) => mml.replace(META_DIRECTIVE, "").replace(TRACK_INST_DIRECTIVE, "").replace(TRACK_COMP_DIRECTIVE, "").replace(TRACK_WIDTH_DIRECTIVE, "").replace(TRACK_EQLOW_DIRECTIVE, "").replace(TRACK_EQMID_DIRECTIVE, "").replace(TRACK_EQHIGH_DIRECTIVE, "");
|
|
3430
|
+
var stripMmlMeta = (mml) => mml.replace(META_DIRECTIVE, "").replace(TRACK_INST_DIRECTIVE, "").replace(TRACK_COMP_DIRECTIVE, "").replace(TRACK_WIDTH_DIRECTIVE, "").replace(TRACK_REVERBSEND_DIRECTIVE, "").replace(TRACK_EQLOW_DIRECTIVE, "").replace(TRACK_EQMID_DIRECTIVE, "").replace(TRACK_EQHIGH_DIRECTIVE, "");
|
|
3271
3431
|
var formatMmlMeta = (meta, space = "") => {
|
|
3272
3432
|
const parts = [];
|
|
3273
3433
|
if (meta.instrument) parts.push(`#inst=${meta.instrument}`);
|
|
@@ -3306,6 +3466,11 @@ var formatMmlMeta = (meta, space = "") => {
|
|
|
3306
3466
|
if (val !== 100) parts.push(`#t${idx}width=${val}`);
|
|
3307
3467
|
}
|
|
3308
3468
|
}
|
|
3469
|
+
if (meta.trackReverbSend) {
|
|
3470
|
+
for (const [idx, val] of Object.entries(meta.trackReverbSend)) {
|
|
3471
|
+
if (val !== 0) parts.push(`#t${idx}rev=${val}`);
|
|
3472
|
+
}
|
|
3473
|
+
}
|
|
3309
3474
|
if (meta.trackEqLow) {
|
|
3310
3475
|
for (const [idx, val] of Object.entries(meta.trackEqLow)) {
|
|
3311
3476
|
if (val !== 0) parts.push(`#t${idx}eqlo=${val}`);
|
|
@@ -3403,7 +3568,7 @@ var parseMML = (mml, options = {}) => {
|
|
|
3403
3568
|
numStr += body[j];
|
|
3404
3569
|
j++;
|
|
3405
3570
|
}
|
|
3406
|
-
const len = numStr ?
|
|
3571
|
+
const len = numStr ? clamp3(Number.parseInt(numStr, 10), 1, 64) : baseLength;
|
|
3407
3572
|
let steps = Math.round(stepsPerBar / len);
|
|
3408
3573
|
while (j < body.length && body[j] === ".") {
|
|
3409
3574
|
steps = Math.round(steps * 1.5);
|
|
@@ -3421,7 +3586,7 @@ var parseMML = (mml, options = {}) => {
|
|
|
3421
3586
|
numStr += body[j];
|
|
3422
3587
|
j++;
|
|
3423
3588
|
}
|
|
3424
|
-
octave = numStr ?
|
|
3589
|
+
octave = numStr ? clamp3(Number.parseInt(numStr, 10), 0, 8) : 4;
|
|
3425
3590
|
pushTok("octave", currentStep, 0, tokStart);
|
|
3426
3591
|
} else if (ch === ">") {
|
|
3427
3592
|
octave = Math.min(8, octave + 1);
|
|
@@ -3438,7 +3603,7 @@ var parseMML = (mml, options = {}) => {
|
|
|
3438
3603
|
numStr += body[j];
|
|
3439
3604
|
j++;
|
|
3440
3605
|
}
|
|
3441
|
-
baseLength =
|
|
3606
|
+
baseLength = clamp3(Number.parseInt(numStr, 10) || 16, 1, 64);
|
|
3442
3607
|
pushTok("length", currentStep, 0, tokStart);
|
|
3443
3608
|
} else if (ch === "r") {
|
|
3444
3609
|
j++;
|
|
@@ -3455,10 +3620,10 @@ var parseMML = (mml, options = {}) => {
|
|
|
3455
3620
|
}
|
|
3456
3621
|
if (ch === "t" && numStr) {
|
|
3457
3622
|
if (bpm === null) {
|
|
3458
|
-
bpm =
|
|
3623
|
+
bpm = clamp3(Number.parseInt(numStr, 10), 1, 255);
|
|
3459
3624
|
}
|
|
3460
3625
|
} else if (ch === "v" && numStr) {
|
|
3461
|
-
velocity =
|
|
3626
|
+
velocity = clamp3(Number.parseInt(numStr, 10), 0, 127);
|
|
3462
3627
|
trackVelocity.set(trackIndex, velocity);
|
|
3463
3628
|
}
|
|
3464
3629
|
pushTok("ctrl", currentStep, 0, tokStart);
|
|
@@ -3492,7 +3657,7 @@ var parseMML = (mml, options = {}) => {
|
|
|
3492
3657
|
numStr += body[j];
|
|
3493
3658
|
j++;
|
|
3494
3659
|
}
|
|
3495
|
-
octave = numStr ?
|
|
3660
|
+
octave = numStr ? clamp3(Number.parseInt(numStr, 10), 0, 8) : 4;
|
|
3496
3661
|
} else {
|
|
3497
3662
|
j++;
|
|
3498
3663
|
}
|
|
@@ -3554,6 +3719,38 @@ var parseMML = (mml, options = {}) => {
|
|
|
3554
3719
|
};
|
|
3555
3720
|
};
|
|
3556
3721
|
|
|
3722
|
+
// src/reverb.ts
|
|
3723
|
+
var DEFAULT_REVERB_DECAY_SEC = 2.2;
|
|
3724
|
+
var MIN_REVERB_DECAY_SEC = 0.3;
|
|
3725
|
+
var MAX_REVERB_DECAY_SEC = 4;
|
|
3726
|
+
var IMPULSE_DECAY_CURVE = 2.5;
|
|
3727
|
+
var DEFAULT_REVERB_PREDELAY_MS = 0;
|
|
3728
|
+
var MIN_REVERB_PREDELAY_MS = 0;
|
|
3729
|
+
var MAX_REVERB_PREDELAY_MS = 150;
|
|
3730
|
+
var createReverbImpulse = (ctx, decaySec = DEFAULT_REVERB_DECAY_SEC) => {
|
|
3731
|
+
const rate = ctx.sampleRate;
|
|
3732
|
+
const length = Math.max(
|
|
3733
|
+
1,
|
|
3734
|
+
Math.floor(
|
|
3735
|
+
rate * Math.max(
|
|
3736
|
+
MIN_REVERB_DECAY_SEC,
|
|
3737
|
+
Math.min(MAX_REVERB_DECAY_SEC, decaySec)
|
|
3738
|
+
)
|
|
3739
|
+
)
|
|
3740
|
+
);
|
|
3741
|
+
const impulse = ctx.createBuffer(2, length, rate);
|
|
3742
|
+
for (let ch = 0; ch < impulse.numberOfChannels; ch++) {
|
|
3743
|
+
const data = impulse.getChannelData(ch);
|
|
3744
|
+
for (let i2 = 0; i2 < length; i2++) {
|
|
3745
|
+
const envelope = (1 - i2 / length) ** IMPULSE_DECAY_CURVE;
|
|
3746
|
+
data[i2] = (Math.random() * 2 - 1) * envelope;
|
|
3747
|
+
}
|
|
3748
|
+
}
|
|
3749
|
+
return impulse;
|
|
3750
|
+
};
|
|
3751
|
+
var REVERB_MAX_WET = 0.6;
|
|
3752
|
+
var reverbAmountToGain = (amount) => Math.max(0, Math.min(100, amount)) / 100 * REVERB_MAX_WET;
|
|
3753
|
+
|
|
3557
3754
|
// src/sequencer.ts
|
|
3558
3755
|
var STEPS_PER_BEAT = 48;
|
|
3559
3756
|
var PLAN_TIME = 0.5;
|
|
@@ -6131,9 +6328,54 @@ var playPlacements = (placements, options) => {
|
|
|
6131
6328
|
});
|
|
6132
6329
|
const ownsCtx = !options.audioContext;
|
|
6133
6330
|
const ctx = options.audioContext ?? new AudioContext();
|
|
6134
|
-
const
|
|
6331
|
+
const rawDestination = options.destination ?? ctx.destination;
|
|
6135
6332
|
const useSynth = options.synth ?? !options.onPlayNote;
|
|
6136
|
-
const
|
|
6333
|
+
const finalMix = ctx.createGain();
|
|
6334
|
+
const masterGain = ctx.createGain();
|
|
6335
|
+
masterGain.connect(finalMix);
|
|
6336
|
+
const reverbPreDelay = ctx.createDelay(MAX_REVERB_PREDELAY_MS / 1e3);
|
|
6337
|
+
reverbPreDelay.delayTime.value = (options.metaReverbPreDelay ?? DEFAULT_REVERB_PREDELAY_MS) / 1e3;
|
|
6338
|
+
const reverbConvolver = ctx.createConvolver();
|
|
6339
|
+
const reverbDecaySec = (options.metaReverbDecay ?? 22) / 10 || DEFAULT_REVERB_DECAY_SEC;
|
|
6340
|
+
reverbConvolver.buffer = createReverbImpulse(ctx, reverbDecaySec);
|
|
6341
|
+
reverbConvolver.normalize = true;
|
|
6342
|
+
const reverbWetGain = ctx.createGain();
|
|
6343
|
+
reverbWetGain.gain.value = reverbAmountToGain(options.metaReverb ?? 0);
|
|
6344
|
+
reverbPreDelay.connect(reverbConvolver);
|
|
6345
|
+
reverbConvolver.connect(reverbWetGain);
|
|
6346
|
+
reverbWetGain.connect(finalMix);
|
|
6347
|
+
finalMix.connect(rawDestination);
|
|
6348
|
+
const channelStrips = /* @__PURE__ */ new Map();
|
|
6349
|
+
const getChannelStrip = (index) => {
|
|
6350
|
+
let strip = channelStrips.get(index);
|
|
6351
|
+
if (!strip) {
|
|
6352
|
+
strip = createChannelStrip(ctx, masterGain, {
|
|
6353
|
+
compression: options.trackCompression?.[index] ?? 0,
|
|
6354
|
+
width: options.trackWidth?.[index] ?? 100,
|
|
6355
|
+
eqLow: options.trackEqLow?.[index] ?? 0,
|
|
6356
|
+
eqMid: options.trackEqMid?.[index] ?? 0,
|
|
6357
|
+
eqHigh: options.trackEqHigh?.[index] ?? 0,
|
|
6358
|
+
reverbSend: options.trackReverbSend?.[index] ?? 0,
|
|
6359
|
+
reverbBus: reverbPreDelay
|
|
6360
|
+
});
|
|
6361
|
+
channelStrips.set(index, strip);
|
|
6362
|
+
}
|
|
6363
|
+
return strip;
|
|
6364
|
+
};
|
|
6365
|
+
const synths = /* @__PURE__ */ new Map();
|
|
6366
|
+
const getSynth = (index) => {
|
|
6367
|
+
let s = synths.get(index);
|
|
6368
|
+
if (!s) {
|
|
6369
|
+
s = createSynth(ctx, getChannelStrip(index).input);
|
|
6370
|
+
synths.set(index, s);
|
|
6371
|
+
}
|
|
6372
|
+
return s;
|
|
6373
|
+
};
|
|
6374
|
+
const drumSynth = useSynth ? createSynth(ctx, masterGain) : null;
|
|
6375
|
+
const trackIndexById = /* @__PURE__ */ new Map();
|
|
6376
|
+
trackIndices.forEach((idx) => {
|
|
6377
|
+
trackIndexById.set(TRACK_ID_BY_INDEX[idx] ?? `t${idx}`, idx);
|
|
6378
|
+
});
|
|
6137
6379
|
const pauseWhenHidden = options.pauseWhenHidden ?? ownsCtx;
|
|
6138
6380
|
let playing = false;
|
|
6139
6381
|
const seq = createSequencer({
|
|
@@ -6148,12 +6390,14 @@ var playPlacements = (placements, options) => {
|
|
|
6148
6390
|
getAudioTime: () => ctx.currentTime,
|
|
6149
6391
|
onPlayNote: (e) => {
|
|
6150
6392
|
options.onPlayNote?.(e);
|
|
6151
|
-
|
|
6393
|
+
if (!useSynth) return;
|
|
6394
|
+
const index = trackIndexById.get(e.trackId);
|
|
6395
|
+
(index === void 0 ? drumSynth : getSynth(index))?.playNote(e);
|
|
6152
6396
|
},
|
|
6153
6397
|
onPlayDrum: (e) => {
|
|
6154
6398
|
const velocity = e.velocity * (drumVolume / 100) * (masterVolume / 100);
|
|
6155
6399
|
options.onPlayDrum?.({ ...e, velocity });
|
|
6156
|
-
|
|
6400
|
+
drumSynth?.playDrum({ ...e, velocity });
|
|
6157
6401
|
},
|
|
6158
6402
|
onTick: (step) => {
|
|
6159
6403
|
options.onTick?.(step);
|
|
@@ -6204,6 +6448,7 @@ var playPlacements = (placements, options) => {
|
|
|
6204
6448
|
if (pauseWhenHidden && typeof document !== "undefined") {
|
|
6205
6449
|
document.removeEventListener("visibilitychange", onVisibilityChange);
|
|
6206
6450
|
}
|
|
6451
|
+
for (const strip of channelStrips.values()) strip.dispose();
|
|
6207
6452
|
if (ownsCtx) void ctx.close();
|
|
6208
6453
|
};
|
|
6209
6454
|
return {
|
|
@@ -6223,7 +6468,16 @@ var playMML = (mml, options = {}) => {
|
|
|
6223
6468
|
bpm,
|
|
6224
6469
|
metaVolume: meta.volume,
|
|
6225
6470
|
metaDrum: meta.drum,
|
|
6226
|
-
metaDrumVolume: meta.drumVolume
|
|
6471
|
+
metaDrumVolume: meta.drumVolume,
|
|
6472
|
+
metaReverb: meta.reverb,
|
|
6473
|
+
metaReverbDecay: meta.reverbDecay,
|
|
6474
|
+
metaReverbPreDelay: meta.reverbPreDelay,
|
|
6475
|
+
trackCompression: meta.trackCompression,
|
|
6476
|
+
trackWidth: meta.trackWidth,
|
|
6477
|
+
trackReverbSend: meta.trackReverbSend,
|
|
6478
|
+
trackEqLow: meta.trackEqLow,
|
|
6479
|
+
trackEqMid: meta.trackEqMid,
|
|
6480
|
+
trackEqHigh: meta.trackEqHigh
|
|
6227
6481
|
});
|
|
6228
6482
|
};
|
|
6229
6483
|
var playNote = (options) => {
|
|
@@ -7621,11 +7875,14 @@ var DAW_CSS = `
|
|
|
7621
7875
|
user-select: none;
|
|
7622
7876
|
}
|
|
7623
7877
|
.dtm-player-balloon {
|
|
7624
|
-
|
|
7625
|
-
|
|
7626
|
-
|
|
7627
|
-
|
|
7628
|
-
|
|
7878
|
+
/* body \u76F4\u4E0B\u306B\u751F\u6210\u3055\u308C\u3001JS(positionBalloon)\u304C\u6BCE\u56DE left/top \u3092\u30A2\u30F3\u30AB\u30FC\u306E\u753B\u9762\u5EA7\u6A19\u3067
|
|
7879
|
+
\u8A2D\u5B9A\u3059\u308B\u3002overflow:hidden \u306A\u7956\u5148\uFF08\u6295\u7A3F\u30AB\u30FC\u30C9\u7B49\uFF09\u306B\u30AF\u30EA\u30C3\u30D7\u3055\u308C\u306A\u3044\u3088\u3046 fixed \u3067\u6D6E\u304B\u305B\u308B\u3002
|
|
7880
|
+
top \u306F\u30A2\u30F3\u30AB\u30FC\u4E0A\u7AEF-6px\u3001transform \u3067\u81EA\u8EAB\u306E\u5DE6\u4E0B\u89D2\u3092\u305D\u306E\u70B9\u306B\u5408\u308F\u305B\u308B\u3002 */
|
|
7881
|
+
position: fixed;
|
|
7882
|
+
left: 0;
|
|
7883
|
+
top: 0;
|
|
7884
|
+
transform: translate(-50%, -100%);
|
|
7885
|
+
z-index: 1000;
|
|
7629
7886
|
display: none;
|
|
7630
7887
|
pointer-events: none;
|
|
7631
7888
|
font-family: var(--dtm-font);
|
|
@@ -7654,8 +7911,8 @@ var DAW_CSS = `
|
|
|
7654
7911
|
animation: dtm-balloon-fade-in 0.1s steps(2);
|
|
7655
7912
|
}
|
|
7656
7913
|
@keyframes dtm-balloon-fade-in {
|
|
7657
|
-
from { opacity: 0; transform:
|
|
7658
|
-
to { opacity: 1; transform:
|
|
7914
|
+
from { opacity: 0; transform: translate(-50%, -100%) translateY(4px); }
|
|
7915
|
+
to { opacity: 1; transform: translate(-50%, -100%) translateY(0); }
|
|
7659
7916
|
}
|
|
7660
7917
|
@keyframes dtm-emoji-jump {
|
|
7661
7918
|
0% { transform: translateY(0); }
|
|
@@ -8078,6 +8335,27 @@ var LYRIC_MODEL_LABELS = {
|
|
|
8078
8335
|
};
|
|
8079
8336
|
var activeBalloonEl = null;
|
|
8080
8337
|
var activeBalloonTimer = null;
|
|
8338
|
+
var balloonAnchors = /* @__PURE__ */ new WeakMap();
|
|
8339
|
+
var positionBalloon = (balloonEl) => {
|
|
8340
|
+
const anchor = balloonAnchors.get(balloonEl);
|
|
8341
|
+
if (!anchor) return;
|
|
8342
|
+
const rect = anchor.getBoundingClientRect();
|
|
8343
|
+
balloonEl.style.left = `${rect.left + rect.width / 2}px`;
|
|
8344
|
+
balloonEl.style.top = `${rect.top - 6}px`;
|
|
8345
|
+
};
|
|
8346
|
+
var balloonListenersBound = false;
|
|
8347
|
+
var ensureBalloonListeners = () => {
|
|
8348
|
+
if (balloonListenersBound || typeof window === "undefined") return;
|
|
8349
|
+
balloonListenersBound = true;
|
|
8350
|
+
const reposition = () => {
|
|
8351
|
+
if (activeBalloonEl) positionBalloon(activeBalloonEl);
|
|
8352
|
+
};
|
|
8353
|
+
window.addEventListener("scroll", reposition, {
|
|
8354
|
+
capture: true,
|
|
8355
|
+
passive: true
|
|
8356
|
+
});
|
|
8357
|
+
window.addEventListener("resize", reposition, { passive: true });
|
|
8358
|
+
};
|
|
8081
8359
|
var hideActiveBalloon = () => {
|
|
8082
8360
|
if (activeBalloonEl) {
|
|
8083
8361
|
activeBalloonEl.classList.remove("dtm-player-balloon--visible");
|
|
@@ -8089,6 +8367,7 @@ var hideActiveBalloon = () => {
|
|
|
8089
8367
|
}
|
|
8090
8368
|
};
|
|
8091
8369
|
var showBalloon = (balloonEl) => {
|
|
8370
|
+
positionBalloon(balloonEl);
|
|
8092
8371
|
if (activeBalloonEl === balloonEl) {
|
|
8093
8372
|
if (activeBalloonTimer) {
|
|
8094
8373
|
clearTimeout(activeBalloonTimer);
|
|
@@ -8353,6 +8632,7 @@ var mountMmlPlayer = (target, mml, options = {}) => {
|
|
|
8353
8632
|
const doc = target.ownerDocument ?? document;
|
|
8354
8633
|
const root = doc.createElement("div");
|
|
8355
8634
|
root.className = "dtm-daw dtm-player";
|
|
8635
|
+
const playerBalloons = [];
|
|
8356
8636
|
const head = doc.createElement("div");
|
|
8357
8637
|
head.className = "dtm-player-head";
|
|
8358
8638
|
const playBtn = doc.createElement("button");
|
|
@@ -8698,7 +8978,10 @@ var mountMmlPlayer = (target, mml, options = {}) => {
|
|
|
8698
8978
|
balloon.className = "dtm-player-balloon";
|
|
8699
8979
|
const modelKey = lt.model.toLowerCase();
|
|
8700
8980
|
balloon.textContent = LYRIC_MODEL_LABELS[modelKey] ?? lt.model;
|
|
8701
|
-
|
|
8981
|
+
balloonAnchors.set(balloon, em);
|
|
8982
|
+
doc.body.appendChild(balloon);
|
|
8983
|
+
playerBalloons.push(balloon);
|
|
8984
|
+
ensureBalloonListeners();
|
|
8702
8985
|
em.addEventListener("mouseenter", () => {
|
|
8703
8986
|
showBalloon(balloon);
|
|
8704
8987
|
});
|
|
@@ -9159,7 +9442,7 @@ var mountMmlPlayer = (target, mml, options = {}) => {
|
|
|
9159
9442
|
delaySend: (lt.delay ?? 0) / 100,
|
|
9160
9443
|
gender: (lt.gender ?? 50) / 100,
|
|
9161
9444
|
breathiness: (lt.breathiness ?? 50) / 100,
|
|
9162
|
-
|
|
9445
|
+
octaveUnison: lt.octaveUnison,
|
|
9163
9446
|
notes
|
|
9164
9447
|
};
|
|
9165
9448
|
});
|
|
@@ -9295,9 +9578,10 @@ var mountMmlPlayer = (target, mml, options = {}) => {
|
|
|
9295
9578
|
}
|
|
9296
9579
|
for (const t of blinkTimers) clearTimeout(t);
|
|
9297
9580
|
clearJumpTimers();
|
|
9298
|
-
if (activeBalloonEl &&
|
|
9581
|
+
if (activeBalloonEl && playerBalloons.includes(activeBalloonEl)) {
|
|
9299
9582
|
hideActiveBalloon();
|
|
9300
9583
|
}
|
|
9584
|
+
for (const balloon of playerBalloons) balloon.remove();
|
|
9301
9585
|
root.remove();
|
|
9302
9586
|
consentOverlayEl?.remove();
|
|
9303
9587
|
closeInfoModal();
|
|
@@ -9499,20 +9783,23 @@ var adjustZone = async (ctx, fontName, zone) => {
|
|
|
9499
9783
|
const newLength = attackLength + loopLengthFrame * repeatCount + releaseLength;
|
|
9500
9784
|
let totalPeak = 0;
|
|
9501
9785
|
let loopPeak = 0;
|
|
9502
|
-
|
|
9503
|
-
const
|
|
9504
|
-
for (let i2 = 0; i2 <
|
|
9505
|
-
const abs = Math.abs(
|
|
9786
|
+
for (let ch = 0; ch < oldBuf.numberOfChannels; ch++) {
|
|
9787
|
+
const chData = oldBuf.getChannelData(ch);
|
|
9788
|
+
for (let i2 = 0; i2 < chData.length; i2++) {
|
|
9789
|
+
const abs = Math.abs(chData[i2]);
|
|
9506
9790
|
if (abs > totalPeak) totalPeak = abs;
|
|
9507
9791
|
if (i2 >= loopStartFrame && i2 < loopEndFrame) {
|
|
9508
9792
|
if (abs > loopPeak) loopPeak = abs;
|
|
9509
9793
|
}
|
|
9510
9794
|
}
|
|
9511
9795
|
}
|
|
9796
|
+
const decay = isDecayInstrument(fontName);
|
|
9797
|
+
const targetRatio = decay ? 0.4 : 0.75;
|
|
9798
|
+
const maxMultiplier = decay ? 6 : 20;
|
|
9512
9799
|
let gainMultiplier = 1;
|
|
9513
|
-
if (
|
|
9514
|
-
gainMultiplier = totalPeak *
|
|
9515
|
-
if (gainMultiplier >
|
|
9800
|
+
if (loopPeak > 0 && totalPeak > 0 && loopPeak < totalPeak * 0.8) {
|
|
9801
|
+
gainMultiplier = totalPeak * targetRatio / loopPeak;
|
|
9802
|
+
if (gainMultiplier > maxMultiplier) gainMultiplier = maxMultiplier;
|
|
9516
9803
|
}
|
|
9517
9804
|
try {
|
|
9518
9805
|
const newBuf = ctx.createBuffer(
|
|
@@ -10844,14 +11131,14 @@ var DELAY_DIVISIONS = [
|
|
|
10844
11131
|
{ value: "8d", label: "\u4ED8\u70B98\u5206", beats: 0.75 },
|
|
10845
11132
|
{ value: "16", label: "16\u5206", beats: 0.25 }
|
|
10846
11133
|
];
|
|
10847
|
-
var
|
|
11134
|
+
var clamp4 = (v, lo, hi) => Math.max(lo, Math.min(hi, v));
|
|
10848
11135
|
var divisionToSeconds = (division, bpm) => {
|
|
10849
11136
|
const beats = DELAY_DIVISIONS.find((d) => d.value === division)?.beats ?? 0.5;
|
|
10850
11137
|
const safeBpm = bpm > 0 ? bpm : 120;
|
|
10851
11138
|
return 60 / safeBpm * beats;
|
|
10852
11139
|
};
|
|
10853
11140
|
var DELAY_MAX_WET = 0.45;
|
|
10854
|
-
var delayAmountToGain = (amount) =>
|
|
11141
|
+
var delayAmountToGain = (amount) => clamp4(amount, 0, 100) / 100 * DELAY_MAX_WET;
|
|
10855
11142
|
var FEEDBACK_GAIN = 0.3;
|
|
10856
11143
|
var MAX_DELAY_SEC = 2;
|
|
10857
11144
|
var createDelayBus = (ctx, destination, options = {}) => {
|
|
@@ -12926,38 +13213,6 @@ var isChordHeavyTrack = (notes, threshold = 0.6) => {
|
|
|
12926
13213
|
return chordNotes / notes.length >= threshold;
|
|
12927
13214
|
};
|
|
12928
13215
|
|
|
12929
|
-
// src/reverb.ts
|
|
12930
|
-
var DEFAULT_REVERB_DECAY_SEC = 2.2;
|
|
12931
|
-
var MIN_REVERB_DECAY_SEC = 0.3;
|
|
12932
|
-
var MAX_REVERB_DECAY_SEC = 4;
|
|
12933
|
-
var IMPULSE_DECAY_CURVE = 2.5;
|
|
12934
|
-
var DEFAULT_REVERB_PREDELAY_MS = 0;
|
|
12935
|
-
var MIN_REVERB_PREDELAY_MS = 0;
|
|
12936
|
-
var MAX_REVERB_PREDELAY_MS = 150;
|
|
12937
|
-
var createReverbImpulse = (ctx, decaySec = DEFAULT_REVERB_DECAY_SEC) => {
|
|
12938
|
-
const rate = ctx.sampleRate;
|
|
12939
|
-
const length = Math.max(
|
|
12940
|
-
1,
|
|
12941
|
-
Math.floor(
|
|
12942
|
-
rate * Math.max(
|
|
12943
|
-
MIN_REVERB_DECAY_SEC,
|
|
12944
|
-
Math.min(MAX_REVERB_DECAY_SEC, decaySec)
|
|
12945
|
-
)
|
|
12946
|
-
)
|
|
12947
|
-
);
|
|
12948
|
-
const impulse = ctx.createBuffer(2, length, rate);
|
|
12949
|
-
for (let ch = 0; ch < impulse.numberOfChannels; ch++) {
|
|
12950
|
-
const data = impulse.getChannelData(ch);
|
|
12951
|
-
for (let i2 = 0; i2 < length; i2++) {
|
|
12952
|
-
const envelope = (1 - i2 / length) ** IMPULSE_DECAY_CURVE;
|
|
12953
|
-
data[i2] = (Math.random() * 2 - 1) * envelope;
|
|
12954
|
-
}
|
|
12955
|
-
}
|
|
12956
|
-
return impulse;
|
|
12957
|
-
};
|
|
12958
|
-
var REVERB_MAX_WET = 0.6;
|
|
12959
|
-
var reverbAmountToGain = (amount) => Math.max(0, Math.min(100, amount)) / 100 * REVERB_MAX_WET;
|
|
12960
|
-
|
|
12961
13216
|
// src/daw.ts
|
|
12962
13217
|
var CHORD_INFO_HTML2 = `
|
|
12963
13218
|
<div class="dtm-modal-body-content">
|
|
@@ -12999,14 +13254,22 @@ var VIBRATO_INFO_HTML = `
|
|
|
12999
13254
|
<p>\u30D4\u30C3\u30C1\u3092\u63FA\u3089\u3059\u52B9\u679C\u306A\u306E\u3067\u3001\u58F0\u8CEA\u305D\u306E\u3082\u306E\u3092\u5909\u3048\u308B\u30B8\u30A7\u30F3\u30C0\u30FC/\u30D6\u30EC\u30B7\u30CD\u30B9\u3068\u306F\u72EC\u7ACB\u3057\u3066\u7D44\u307F\u5408\u308F\u305B\u3089\u308C\u307E\u3059\u3002\u901F\u3055\u30FB\u6DF1\u3055\u306F\u8ABF\u6574\u3067\u304D\u307E\u305B\u3093\uFF08\u6B4C\u3068\u3057\u3066\u7834\u7DBB\u3057\u306B\u304F\u3044\u63A7\u3048\u3081\u306A\u91CF\u306B\u56FA\u5B9A\uFF09\u3002\u66F2\u3084\u7B87\u6240\u3054\u3068\u306B\u639B\u3051\u305F\u3044/\u639B\u3051\u305F\u304F\u306A\u3044\u304C\u3042\u308B\u5834\u5408\u306F\u3001\u30C8\u30E9\u30C3\u30AF\u3092\u5206\u3051\u3066\u6B4C\u8A5E\u3092\u66F8\u3044\u3066\u304F\u3060\u3055\u3044\u3002</p>
|
|
13000
13255
|
</div>
|
|
13001
13256
|
`;
|
|
13002
|
-
var
|
|
13257
|
+
var OCTAVE_UNISON_TOKEN = {
|
|
13258
|
+
none: "",
|
|
13259
|
+
down: "w1",
|
|
13260
|
+
up: "w2",
|
|
13261
|
+
both: "w3"
|
|
13262
|
+
};
|
|
13263
|
+
var OCTAVE_UNISON_INFO_HTML = `
|
|
13003
13264
|
<div class="dtm-modal-body-content">
|
|
13004
13265
|
<h4>\u4F55\u3092\u3059\u308B\u8A2D\u5B9A\u304B</h4>
|
|
13005
|
-
<p
|
|
13266
|
+
<p>\u3053\u306E\u30C8\u30E9\u30C3\u30AF\u306E\u5404\u97F3\u7BC0\u306B\u3001\u3082\u30461\u58F0\u30921\u30AA\u30AF\u30BF\u30FC\u30D6\u4E0A/\u4E0B/\u4E21\u65B9\uFF08\u63A7\u3048\u3081\u306A\u97F3\u91CF\uFF09\u3067\u540C\u6642\u306B\u91CD\u306D\u3066\u767A\u97F3\u3057\u307E\u3059\u3002\u58F0\u306B\u539A\u307F\u30FB\u30D1\u30EF\u30FC\u3092\u8DB3\u3059\u300C\u30AA\u30AF\u30BF\u30FC\u30D6\u30E6\u30CB\u30BE\u30F3\uFF08\u30C0\u30D6\u30EA\u30F3\u30B0\uFF09\u300D\u3068\u3044\u3046\u5B9A\u756A\u306E\u30DC\u30FC\u30AB\u30EB\u52A0\u5DE5\u3067\u3059\u3002</p>
|
|
13267
|
+
<h4>\u4E0B\u30FB\u4E0A\u30FB\u4E21\u65B9\u306E\u9055\u3044</h4>
|
|
13268
|
+
<p>\u300C\u4E0B\u300D\u306F\u58F0\u306B\u91CD\u307F\u30FB\u30D1\u30EF\u30FC\u3092\u8DB3\u3059\u5B9A\u756A\u306E\u4F7F\u3044\u65B9\uFF08\u30ED\u30C3\u30AF/EDM\u306E\u30D0\u30C3\u30AD\u30F3\u30B0\u7B49\uFF09\u3002\u300C\u4E0A\u300D\u306F\u592A\u3055\u3067\u306F\u306A\u304F\u714C\u3073\u3084\u304B\u3055\u30FB\u53EF\u6190\u3055\u3092\u8DB3\u3059\u4F7F\u3044\u65B9\uFF08\u30A2\u30CB\u30BD\u30F3/\u30CF\u30E2\u30EA\u7B49\uFF09\u3002\u300C\u4E21\u65B9\u300D\u306F\u4E0A\u4E0B\u540C\u6642\u306B\u91CD\u306D\u308B\u7279\u6B8A\u306A\u52B9\u679C\u3067\u3001\u30AD\u30E3\u30E9\u30AF\u30BF\u30FC\u6027\u3092\u5F37\u304F\u51FA\u3057\u305F\u3044\u3068\u304D\u306B\u3002</p>
|
|
13006
13269
|
<h4>\u4F7F\u3044\u3069\u3053\u308D</h4>
|
|
13007
13270
|
<p>\u30B5\u30D3\u306E\u6C7A\u3081\u306E\u30D5\u30EC\u30FC\u30BA\u3001\u30ED\u30DC\u30C3\u30C8\u7684/\u30C0\u30FC\u30AF\u306A\u8CEA\u611F\u306E\u6F14\u51FA\u3001\u30E6\u30CB\u30BE\u30F3\u30CF\u30FC\u30E2\u30CB\u30FC\u306A\u3069\u3067\u3088\u304F\u4F7F\u308F\u308C\u307E\u3059\u3002\u66F2\u5168\u4F53\u306B\u639B\u3051\u3063\u3071\u306A\u3057\u306B\u3059\u308B\u3068\u5E38\u306B\u304F\u3069\u3044\u5370\u8C61\u306B\u306A\u308A\u3084\u3059\u3044\u306E\u3067\u3001\u30C8\u30E9\u30C3\u30AF\u3092\u5206\u3051\u3066\u4F7F\u3044\u305F\u3044\u7B87\u6240\u3060\u3051\u306B\u7D5E\u308B\u306E\u304C\u304A\u3059\u3059\u3081\u3067\u3059\u3002</p>
|
|
13008
13271
|
<h4>\u4ED6\u306E\u8A2D\u5B9A\u3068\u306E\u517C\u306D\u5408\u3044</h4>
|
|
13009
|
-
<p>\u91CD\u306D\u308B\u58F0\u306B\u3082\u540C\u3058\u30D3\u30D6\u30E9\u30FC\u30C8/\u30B8\u30A7\u30F3\u30C0\u30FC/\u30D6\u30EC\u30B7\u30CD\u30B9/\u30EA\u30D0\u30FC\u30D6\u9001\u308A/\u30C7\u30A3\u30EC\u30A4\u9001\u308A\u306E\u8A2D\u5B9A\u304C\u305D\u306E\u307E\u307E\u9069\u7528\u3055\u308C\u307E\u3059\u3002\u97F3\u91CF\u6BD4\u30FB\u97F3\u7A0B\u5DEE\uFF081\u30AA\u30AF\u30BF\u30FC\u30D6\u56FA\u5B9A\uFF09\u306F\u8ABF\u6574\u3067\u304D\u307E\u305B\u3093\u3002\
|
|
13272
|
+
<p>\u91CD\u306D\u308B\u58F0\u306B\u3082\u540C\u3058\u30D3\u30D6\u30E9\u30FC\u30C8/\u30B8\u30A7\u30F3\u30C0\u30FC/\u30D6\u30EC\u30B7\u30CD\u30B9/\u30EA\u30D0\u30FC\u30D6\u9001\u308A/\u30C7\u30A3\u30EC\u30A4\u9001\u308A\u306E\u8A2D\u5B9A\u304C\u305D\u306E\u307E\u307E\u9069\u7528\u3055\u308C\u307E\u3059\u3002\u97F3\u91CF\u6BD4\u30FB\u97F3\u7A0B\u5DEE\uFF081\u30AA\u30AF\u30BF\u30FC\u30D6\u56FA\u5B9A\uFF09\u306F\u8ABF\u6574\u3067\u304D\u307E\u305B\u3093\u3002\u300C\u4E21\u65B9\u300D\u306F\u5408\u6210\u304C3\u500D\u8D70\u308B\u305F\u3081\u3001\u97F3\u6570\u306E\u591A\u3044\u30C8\u30E9\u30C3\u30AF\u3067\u306F\u3084\u3084\u91CD\u304F\u306A\u308A\u307E\u3059\u3002</p>
|
|
13010
13273
|
</div>
|
|
13011
13274
|
`;
|
|
13012
13275
|
var GENDER_INFO_HTML = `
|
|
@@ -13121,6 +13384,16 @@ var TRACK_WIDTH_INFO_HTML = `
|
|
|
13121
13384
|
<p>\u30B9\u30DE\u30DB\u306E\u30B9\u30D4\u30FC\u30AB\u30FC1\u500B\u306A\u3069\u3001\u30E2\u30CE\u30E9\u30EB\u306B\u8FD1\u3044\u74B0\u5883\u3067\u518D\u751F\u3059\u308B\u3068\u97F3\u304C\u8584\u304F/\u4F4D\u76F8\u304C\u4E71\u308C\u3066\u805E\u3053\u3048\u308B\u3053\u3068\u304C\u3042\u308A\u307E\u3059\uFF08\u5DE6\u53F3\u306E\u5DEE\u5206\u3092\u8A87\u5F35\u3057\u3066\u3044\u308B\u305F\u3081\u3001\u8DB3\u3057\u5408\u308F\u305B\u308B\u3068\u6253\u3061\u6D88\u3057\u5408\u3046\u6210\u5206\u304C\u5897\u3048\u308B\uFF09\u3002\u4E3B\u65CB\u5F8B\u3084\u30DC\u30FC\u30AB\u30EB\u306F\u4E2D\u592E\u4ED8\u8FD1\u3067\u72ED\u3081\u3001\u30D1\u30C3\u30C9\u3084\u30B7\u30F3\u30BB\u306E\u88C5\u98FE\u30D1\u30FC\u30C8\u306F\u5E83\u3052\u308B\u3001\u3068\u3044\u3046\u306E\u304C\u30DF\u30C3\u30AF\u30B9\u306E\u5B9A\u77F3\u3067\u3059\u3002</p>
|
|
13122
13385
|
</div>
|
|
13123
13386
|
`;
|
|
13387
|
+
var TRACK_REVERBSEND_INFO_HTML = `
|
|
13388
|
+
<div class="dtm-modal-body-content">
|
|
13389
|
+
<h4>\u4F55\u3092\u3059\u308B\u8A2D\u5B9A\u304B</h4>
|
|
13390
|
+
<p>\u3053\u306E\u30C8\u30E9\u30C3\u30AF\u306E\u97F3\u3092\u3001\u30DE\u30B9\u30BF\u30EA\u30D0\u30FC\u30D6\uFF08[reverb]\u30D1\u30CD\u30EB\u306EDecay/Pre Delay/Mix\uFF09\u3078\u3069\u308C\u3060\u3051\u9001\u308B\u304B\u3092 0-100% \u3067\u6C7A\u3081\u307E\u3059\u30020\u306A\u3089\u9001\u3089\u306A\u3044\uFF1D\u3053\u306E\u30C8\u30E9\u30C3\u30AF\u306B\u306F\u30EA\u30D0\u30FC\u30D6\u304C\u639B\u304B\u308A\u307E\u305B\u3093\u3002</p>
|
|
13391
|
+
<h4>\u300C\u58F0\u3060\u3051\u30EA\u30D0\u30FC\u30D6\u300D\u3092\u4F5C\u308B\u306B\u306F</h4>
|
|
13392
|
+
<p>\u30EA\u30D0\u30FC\u30D6\u306F\u5168\u30C8\u30E9\u30C3\u30AF\u3078\u4E00\u5F8B\u3067\u639B\u304B\u308B\u308F\u3051\u3067\u306F\u306A\u304F\u3001\u3053\u306E\u9001\u308A\u91CF\u3067\u500B\u5225\u306B\u6C7A\u307E\u308A\u307E\u3059\u3002\u30DC\u30FC\u30AB\u30EB\u306E\u30C8\u30E9\u30C3\u30AF\u3060\u3051\u9001\u308A\u91CF\u3092\u4E0A\u3052\u3001\u4ED6\u306E\u697D\u5668\u30C8\u30E9\u30C3\u30AF\u306F0\u306E\u307E\u307E\u306B\u3059\u308C\u3070\u3001\u58F0\u3060\u3051\u306B\u30EA\u30D0\u30FC\u30D6\u3092\u639B\u3051\u3089\u308C\u307E\u3059\u3002\u4F4E\u57DF\u306E\u697D\u5668\uFF08\u30D9\u30FC\u30B9\u30FB\u30AD\u30C3\u30AF\u7B49\uFF09\u306F\u9001\u3089\u306A\u3044\u3001\u30DC\u30FC\u30AB\u30EB\u3084\u30D1\u30C3\u30C9\u306F\u591A\u3081\u306B\u9001\u308B\u3001\u3068\u3044\u3046\u306E\u304C\u30DF\u30C3\u30AF\u30B9\u306E\u5B9A\u77F3\u3067\u3059\u3002</p>
|
|
13393
|
+
<h4>[reverb]\u30D1\u30CD\u30EB\u306EMix\u3068\u306E\u95A2\u4FC2</h4>
|
|
13394
|
+
<p>Mix\u306F\u300C\u9001\u3089\u308C\u3066\u304D\u305F\u97F3\u3092\u3069\u308C\u3060\u3051\u8FD4\u3059\u304B\u300D\u3068\u3044\u3046\u5168\u4F53\u306E\u8FD4\u308A\u91CF\u3067\u3059\u3002\u5404\u30C8\u30E9\u30C3\u30AF\u306E\u9001\u308A\u91CF\u304C0\u306A\u3089\u3001Mix\u3092\u4E0A\u3052\u3066\u3082\u4F55\u3082\u8FD4\u3063\u3066\u304D\u307E\u305B\u3093\u3002\u307E\u305A\u3053\u306E\u30C8\u30E9\u30C3\u30AF\u306E\u9001\u308A\u91CF\u3092\u6C7A\u3081\u3066\u304B\u3089\u3001Mix\u3067\u5168\u4F53\u306E\u639B\u304B\u308A\u5177\u5408\u3092\u5FAE\u8ABF\u6574\u3057\u3066\u304F\u3060\u3055\u3044\u3002</p>
|
|
13395
|
+
</div>
|
|
13396
|
+
`;
|
|
13124
13397
|
var AUTO_MASTER_INFO_HTML = `
|
|
13125
13398
|
<div class="dtm-modal-body-content">
|
|
13126
13399
|
<h4>\u304A\u307E\u304B\u305B\u30DE\u30B9\u30BF\u30EA\u30F3\u30B0\u3068\u306F</h4>
|
|
@@ -13375,7 +13648,7 @@ var deriveCustomVocalKeyFromUrl = (url2) => {
|
|
|
13375
13648
|
if (name && /^[0-9]/.test(name)) name = `_${name}`;
|
|
13376
13649
|
return CUSTOM_VOCAL_KEY_RE.test(name) ? name : "";
|
|
13377
13650
|
};
|
|
13378
|
-
var
|
|
13651
|
+
var clamp5 = (v, min, max) => Math.min(Math.max(v, min), max);
|
|
13379
13652
|
var normalizeInstrumentName = (name) => {
|
|
13380
13653
|
if (!name) return "";
|
|
13381
13654
|
const stripped = name.replace(/\s+/g, "").toLowerCase();
|
|
@@ -13464,6 +13737,8 @@ var mountDAW = (target, options = {}) => {
|
|
|
13464
13737
|
refs.drumFontSelect.value = currentDrumFont;
|
|
13465
13738
|
let currentInstrument = "";
|
|
13466
13739
|
let activeTrackId = options.initialActiveTrack ?? trackConfigs[0].id;
|
|
13740
|
+
let trackFxAdvancedOpen = false;
|
|
13741
|
+
let lyricAdvancedOpen = false;
|
|
13467
13742
|
let activeToolMode = "pen";
|
|
13468
13743
|
let currentInsertLength = 48;
|
|
13469
13744
|
let snapGridSteps = 12;
|
|
@@ -13541,7 +13816,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
13541
13816
|
vocalDelay: t.vocalDelay,
|
|
13542
13817
|
vocalGender: t.vocalGender,
|
|
13543
13818
|
vocalBreathiness: t.vocalBreathiness,
|
|
13544
|
-
|
|
13819
|
+
vocalOctaveUnison: t.vocalOctaveUnison
|
|
13545
13820
|
};
|
|
13546
13821
|
if (lyricsDebounceTimer) clearTimeout(lyricsDebounceTimer);
|
|
13547
13822
|
lyricsDebounceTimer = setTimeout(() => {
|
|
@@ -13606,10 +13881,11 @@ var mountDAW = (target, options = {}) => {
|
|
|
13606
13881
|
vocalDelay: 0,
|
|
13607
13882
|
vocalGender: 50,
|
|
13608
13883
|
vocalBreathiness: 50,
|
|
13609
|
-
|
|
13884
|
+
vocalOctaveUnison: "none",
|
|
13610
13885
|
trackInstrument: "",
|
|
13611
13886
|
trackCompression: 0,
|
|
13612
13887
|
trackWidth: 100,
|
|
13888
|
+
trackReverbSend: 0,
|
|
13613
13889
|
trackEqLow: 0,
|
|
13614
13890
|
trackEqMid: 0,
|
|
13615
13891
|
trackEqHigh: 0
|
|
@@ -13636,7 +13912,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
13636
13912
|
delay: t.vocalDelay,
|
|
13637
13913
|
gender: t.vocalGender,
|
|
13638
13914
|
breathiness: t.vocalBreathiness,
|
|
13639
|
-
|
|
13915
|
+
octaveUnison: t.vocalOctaveUnison,
|
|
13640
13916
|
syllables
|
|
13641
13917
|
});
|
|
13642
13918
|
});
|
|
@@ -13759,7 +14035,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
13759
14035
|
const thumbW = Math.max(40, canvas.width / totalContentWidth * sbW);
|
|
13760
14036
|
const ratio = currentOffsetX / maxOffsetX;
|
|
13761
14037
|
refs.hScrollThumb.style.width = `${thumbW}px`;
|
|
13762
|
-
refs.hScrollThumb.style.left = `${
|
|
14038
|
+
refs.hScrollThumb.style.left = `${clamp5(ratio * (sbW - thumbW), 0, sbW - thumbW)}px`;
|
|
13763
14039
|
}
|
|
13764
14040
|
const totalHeight = renderConfig.keyCount * renderConfig.keyHeight;
|
|
13765
14041
|
const sbH = refs.vScroll.clientHeight;
|
|
@@ -13829,9 +14105,9 @@ var mountDAW = (target, options = {}) => {
|
|
|
13829
14105
|
if (maxOffsetX <= 0) return;
|
|
13830
14106
|
const rect = refs.hScroll.getBoundingClientRect();
|
|
13831
14107
|
const thumbW = Number.parseFloat(refs.hScrollThumb.style.width) || 40;
|
|
13832
|
-
const x2 =
|
|
14108
|
+
const x2 = clamp5(clientX - rect.left - thumbW / 2, 0, rect.width - thumbW);
|
|
13833
14109
|
const ratio = x2 / (rect.width - thumbW);
|
|
13834
|
-
currentOffsetX =
|
|
14110
|
+
currentOffsetX = clamp5(ratio * maxOffsetX, 0, maxOffsetX);
|
|
13835
14111
|
setDrawOffset(currentOffsetX, currentOffsetY);
|
|
13836
14112
|
redrawAll();
|
|
13837
14113
|
};
|
|
@@ -13840,9 +14116,9 @@ var mountDAW = (target, options = {}) => {
|
|
|
13840
14116
|
if (maxOffset <= 0) return;
|
|
13841
14117
|
const rect = refs.vScroll.getBoundingClientRect();
|
|
13842
14118
|
const thumbH = Number.parseFloat(refs.vScrollThumb.style.height) || 40;
|
|
13843
|
-
const y =
|
|
14119
|
+
const y = clamp5(clientY - rect.top - thumbH / 2, 0, rect.height - thumbH);
|
|
13844
14120
|
const ratio = y / (rect.height - thumbH);
|
|
13845
|
-
currentOffsetY =
|
|
14121
|
+
currentOffsetY = clamp5(ratio * maxOffset, 0, maxOffset);
|
|
13846
14122
|
setDrawOffset(currentOffsetX, currentOffsetY);
|
|
13847
14123
|
redrawAll();
|
|
13848
14124
|
};
|
|
@@ -13889,8 +14165,8 @@ var mountDAW = (target, options = {}) => {
|
|
|
13889
14165
|
if (dx !== 0 || dy !== 0) {
|
|
13890
14166
|
const maxOffsetX = getMaxOffsetX();
|
|
13891
14167
|
const maxOffsetY = getMaxOffsetY();
|
|
13892
|
-
currentOffsetX =
|
|
13893
|
-
currentOffsetY =
|
|
14168
|
+
currentOffsetX = clamp5(currentOffsetX + dx, 0, maxOffsetX);
|
|
14169
|
+
currentOffsetY = clamp5(currentOffsetY + dy, 0, maxOffsetY);
|
|
13894
14170
|
setDrawOffset(currentOffsetX, currentOffsetY);
|
|
13895
14171
|
onPointerMove(lastMoveEvent);
|
|
13896
14172
|
}
|
|
@@ -14280,12 +14556,12 @@ var mountDAW = (target, options = {}) => {
|
|
|
14280
14556
|
"wheel",
|
|
14281
14557
|
(event) => {
|
|
14282
14558
|
event.preventDefault();
|
|
14283
|
-
currentOffsetY =
|
|
14559
|
+
currentOffsetY = clamp5(
|
|
14284
14560
|
currentOffsetY + event.deltaY,
|
|
14285
14561
|
0,
|
|
14286
14562
|
getMaxOffsetY()
|
|
14287
14563
|
);
|
|
14288
|
-
currentOffsetX =
|
|
14564
|
+
currentOffsetX = clamp5(
|
|
14289
14565
|
currentOffsetX + event.deltaX,
|
|
14290
14566
|
0,
|
|
14291
14567
|
getMaxOffsetX()
|
|
@@ -14324,7 +14600,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
14324
14600
|
const centerStep = (currentOffsetX + canvas.width / 2) / renderConfig.stepWidth;
|
|
14325
14601
|
renderConfig.stepWidth = BASE_STEP_WIDTH * (zoomX * 2) / 100;
|
|
14326
14602
|
refs.zoomXLabel.textContent = `${zoomX}%`;
|
|
14327
|
-
currentOffsetX =
|
|
14603
|
+
currentOffsetX = clamp5(
|
|
14328
14604
|
centerStep * renderConfig.stepWidth - canvas.width / 2,
|
|
14329
14605
|
0,
|
|
14330
14606
|
getMaxOffsetX()
|
|
@@ -14337,7 +14613,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
14337
14613
|
const centerKey = (currentOffsetY + canvas.height / 2) / renderConfig.keyHeight;
|
|
14338
14614
|
renderConfig.keyHeight = BASE_KEY_HEIGHT * zoomY / 100;
|
|
14339
14615
|
refs.zoomYLabel.textContent = `${zoomY}%`;
|
|
14340
|
-
currentOffsetY =
|
|
14616
|
+
currentOffsetY = clamp5(
|
|
14341
14617
|
centerKey * renderConfig.keyHeight - canvas.height / 2,
|
|
14342
14618
|
0,
|
|
14343
14619
|
getMaxOffsetY()
|
|
@@ -14387,7 +14663,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
14387
14663
|
const threshold = currentOffsetX / renderConfig.stepWidth + visibleSteps - 4;
|
|
14388
14664
|
if (currentPlayStep > threshold) {
|
|
14389
14665
|
const visibleBars = Math.round(visibleSteps / renderConfig.stepsPerBar);
|
|
14390
|
-
currentOffsetX =
|
|
14666
|
+
currentOffsetX = clamp5(
|
|
14391
14667
|
currentOffsetX + visibleBars * renderConfig.stepsPerBar * renderConfig.stepWidth,
|
|
14392
14668
|
0,
|
|
14393
14669
|
getMaxOffsetX()
|
|
@@ -14446,7 +14722,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
14446
14722
|
delaySend: (lt.delay ?? 0) / 100,
|
|
14447
14723
|
gender: (lt.gender ?? 50) / 100,
|
|
14448
14724
|
breathiness: (lt.breathiness ?? 50) / 100,
|
|
14449
|
-
|
|
14725
|
+
octaveUnison: lt.octaveUnison,
|
|
14450
14726
|
notes
|
|
14451
14727
|
};
|
|
14452
14728
|
}) : [];
|
|
@@ -14474,7 +14750,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
14474
14750
|
}
|
|
14475
14751
|
if (playbackState !== "paused") {
|
|
14476
14752
|
const canvas = getGridCanvas();
|
|
14477
|
-
currentOffsetX =
|
|
14753
|
+
currentOffsetX = clamp5(
|
|
14478
14754
|
playStartStep * renderConfig.stepWidth - canvas.width * 0.5,
|
|
14479
14755
|
0,
|
|
14480
14756
|
getMaxOffsetX()
|
|
@@ -14578,7 +14854,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
14578
14854
|
<input type="range" class="dtm-range dtm-grow" data-dtm="track-vol" min="0" max="127" value="${active.volume}">
|
|
14579
14855
|
<span class="dtm-label" data-dtm="track-vol-label">${active.volume}</span>
|
|
14580
14856
|
</div>
|
|
14581
|
-
<details class="dtm-advanced" data-dtm="track-fx-advanced">
|
|
14857
|
+
<details class="dtm-advanced" data-dtm="track-fx-advanced" ${trackFxAdvancedOpen ? "open" : ""}>
|
|
14582
14858
|
<summary>\u8A73\u7D30\u8A2D\u5B9A\uFF08EQ\u30FB\u97F3\u5727\u30FB\u30B9\u30C6\u30EC\u30AA\u5E45\uFF09</summary>
|
|
14583
14859
|
<div class="dtm-row">
|
|
14584
14860
|
<span class="dtm-label">EQ\u4F4E\u57DF</span>
|
|
@@ -14608,7 +14884,18 @@ var mountDAW = (target, options = {}) => {
|
|
|
14608
14884
|
<span class="dtm-label" data-dtm="track-width-label"></span>
|
|
14609
14885
|
<button class="dtm-infobtn" data-dtm="track-width-info" title="\u30B9\u30C6\u30EC\u30AA\u5E45\u306E\u89E3\u8AAC">${icon("info", 12)}</button>
|
|
14610
14886
|
</div>
|
|
14887
|
+
<div class="dtm-row">
|
|
14888
|
+
<span class="dtm-label">\u30EA\u30D0\u30FC\u30D6\u9001\u308A</span>
|
|
14889
|
+
<input type="range" class="dtm-range dtm-grow" data-dtm="track-reverb-send" min="0" max="100" aria-label="\u3053\u306E\u30C8\u30E9\u30C3\u30AF\u306E\u30DE\u30B9\u30BF\u30EA\u30D0\u30FC\u30D6\u3078\u306E\u9001\u308A\u91CF\uFF080=\u639B\u304B\u3089\u306A\u3044\uFF09">
|
|
14890
|
+
<span class="dtm-label" data-dtm="track-reverb-send-label"></span>
|
|
14891
|
+
<button class="dtm-infobtn" data-dtm="track-reverb-send-info" title="\u30EA\u30D0\u30FC\u30D6\u9001\u308A\u306E\u89E3\u8AAC">${icon("info", 12)}</button>
|
|
14892
|
+
</div>
|
|
14611
14893
|
</details>`;
|
|
14894
|
+
refs.trackBody.querySelector(
|
|
14895
|
+
'[data-dtm="track-fx-advanced"]'
|
|
14896
|
+
).addEventListener("toggle", (e) => {
|
|
14897
|
+
trackFxAdvancedOpen = e.target.open;
|
|
14898
|
+
});
|
|
14612
14899
|
const volInput = refs.trackBody.querySelector(
|
|
14613
14900
|
'[data-dtm="track-vol"]'
|
|
14614
14901
|
);
|
|
@@ -14712,6 +14999,28 @@ var mountDAW = (target, options = {}) => {
|
|
|
14712
14999
|
trackWidthInfo.addEventListener("click", () => {
|
|
14713
15000
|
showModal("\u30B9\u30C6\u30EC\u30AA\u5E45\u306E\u89E3\u8AAC", TRACK_WIDTH_INFO_HTML);
|
|
14714
15001
|
});
|
|
15002
|
+
const trackReverbSendInput = refs.trackBody.querySelector(
|
|
15003
|
+
'[data-dtm="track-reverb-send"]'
|
|
15004
|
+
);
|
|
15005
|
+
const trackReverbSendLabel = refs.trackBody.querySelector(
|
|
15006
|
+
'[data-dtm="track-reverb-send-label"]'
|
|
15007
|
+
);
|
|
15008
|
+
const trackReverbSendInfo = refs.trackBody.querySelector(
|
|
15009
|
+
'[data-dtm="track-reverb-send-info"]'
|
|
15010
|
+
);
|
|
15011
|
+
trackReverbSendInput.value = String(active.trackReverbSend);
|
|
15012
|
+
trackReverbSendLabel.textContent = `${active.trackReverbSend}%`;
|
|
15013
|
+
trackReverbSendInput.addEventListener("input", () => {
|
|
15014
|
+
active.trackReverbSend = Number.parseInt(trackReverbSendInput.value, 10);
|
|
15015
|
+
trackReverbSendLabel.textContent = `${active.trackReverbSend}%`;
|
|
15016
|
+
options.onTrackReverbSendChange?.(
|
|
15017
|
+
active.config.id,
|
|
15018
|
+
active.trackReverbSend
|
|
15019
|
+
);
|
|
15020
|
+
});
|
|
15021
|
+
trackReverbSendInfo.addEventListener("click", () => {
|
|
15022
|
+
showModal("\u30EA\u30D0\u30FC\u30D6\u9001\u308A\u306E\u89E3\u8AAC", TRACK_REVERBSEND_INFO_HTML);
|
|
15023
|
+
});
|
|
14715
15024
|
const instRow = document.createElement("div");
|
|
14716
15025
|
instRow.className = "dtm-row";
|
|
14717
15026
|
instRow.innerHTML = `<span class="dtm-label">\u697D\u5668</span>`;
|
|
@@ -14800,7 +15109,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
14800
15109
|
<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">
|
|
14801
15110
|
<span class="dtm-label" data-dtm="lyric-vol-label"></span>
|
|
14802
15111
|
</div>
|
|
14803
|
-
<details class="dtm-advanced" data-dtm="lyric-advanced">
|
|
15112
|
+
<details class="dtm-advanced" data-dtm="lyric-advanced" ${lyricAdvancedOpen ? "open" : ""}>
|
|
14804
15113
|
<summary>\u8A73\u7D30\u8A2D\u5B9A</summary>
|
|
14805
15114
|
<div class="dtm-row">
|
|
14806
15115
|
<span class="dtm-label">\u30AA\u30AF\u30BF\u30FC\u30D6</span>
|
|
@@ -14848,15 +15157,24 @@ var mountDAW = (target, options = {}) => {
|
|
|
14848
15157
|
<button class="dtm-infobtn" data-dtm="lyric-vibrato-info" title="\u81EA\u52D5\u30D3\u30D6\u30E9\u30FC\u30C8\u306E\u89E3\u8AAC">${icon("info", 12)}</button>
|
|
14849
15158
|
</div>
|
|
14850
15159
|
<div class="dtm-row">
|
|
14851
|
-
<span class="dtm-label"
|
|
14852
|
-
|
|
14853
|
-
|
|
14854
|
-
|
|
15160
|
+
<span class="dtm-label">\u30AA\u30AF\u30BF\u30FC\u30D6\u30E6\u30CB\u30BE\u30F3</span>
|
|
15161
|
+
<select class="dtm-select dtm-grow" data-dtm="lyric-octave-unison" aria-label="\u30AA\u30AF\u30BF\u30FC\u30D6\u30E6\u30CB\u30BE\u30F3\uFF08\u3082\u30461\u58F0\u3092\u4E0A/\u4E0B\u306B\u91CD\u306D\u308B\uFF09">
|
|
15162
|
+
<option value="none">\u306A\u3057</option>
|
|
15163
|
+
<option value="down">\u4E0B (-1oct)</option>
|
|
15164
|
+
<option value="up">\u4E0A (+1oct)</option>
|
|
15165
|
+
<option value="both">\u4E0A\u4E0B\u4E21\u65B9</option>
|
|
15166
|
+
</select>
|
|
15167
|
+
<button class="dtm-infobtn" data-dtm="lyric-octave-unison-info" title="\u30AA\u30AF\u30BF\u30FC\u30D6\u30E6\u30CB\u30BE\u30F3\u306E\u89E3\u8AAC">${icon("info", 12)}</button>
|
|
14855
15168
|
</div>
|
|
14856
15169
|
</details>
|
|
14857
15170
|
<textarea class="dtm-textarea" data-dtm="lyric-input" rows="2" placeholder="\u3072\u3089\u304C\u306A\u30FB\u30AB\u30BF\u30AB\u30CA\u3067\u6B4C\u8A5E\uFF08\u4F8B: \u3069\u308C\u307F\u3075\u3041\u305D\u3089\u3057\u3069\uFF09"></textarea>
|
|
14858
15171
|
</div>`;
|
|
14859
15172
|
refs.trackBody.appendChild(lyricDiv);
|
|
15173
|
+
lyricDiv.querySelector(
|
|
15174
|
+
'[data-dtm="lyric-advanced"]'
|
|
15175
|
+
).addEventListener("toggle", (e) => {
|
|
15176
|
+
lyricAdvancedOpen = e.target.open;
|
|
15177
|
+
});
|
|
14860
15178
|
const lyricModelSel = lyricDiv.querySelector(
|
|
14861
15179
|
'[data-dtm="lyric-model"]'
|
|
14862
15180
|
);
|
|
@@ -14944,14 +15262,14 @@ var mountDAW = (target, options = {}) => {
|
|
|
14944
15262
|
lyricVibratoInfo.addEventListener("click", () => {
|
|
14945
15263
|
showModal("\u81EA\u52D5\u30D3\u30D6\u30E9\u30FC\u30C8\u89E3\u8AAC", VIBRATO_INFO_HTML);
|
|
14946
15264
|
});
|
|
14947
|
-
const
|
|
14948
|
-
'[data-dtm="lyric-octave-
|
|
15265
|
+
const lyricOctaveUnison = lyricDiv.querySelector(
|
|
15266
|
+
'[data-dtm="lyric-octave-unison"]'
|
|
14949
15267
|
);
|
|
14950
|
-
const
|
|
14951
|
-
'[data-dtm="lyric-octave-
|
|
15268
|
+
const lyricOctaveUnisonInfo = lyricDiv.querySelector(
|
|
15269
|
+
'[data-dtm="lyric-octave-unison-info"]'
|
|
14952
15270
|
);
|
|
14953
|
-
|
|
14954
|
-
showModal("\u30AA\u30AF\u30BF\u30FC\u30D6\
|
|
15271
|
+
lyricOctaveUnisonInfo.addEventListener("click", () => {
|
|
15272
|
+
showModal("\u30AA\u30AF\u30BF\u30FC\u30D6\u30E6\u30CB\u30BE\u30F3\u89E3\u8AAC", OCTAVE_UNISON_INFO_HTML);
|
|
14955
15273
|
});
|
|
14956
15274
|
const lyricTerms = lyricDiv.querySelector(
|
|
14957
15275
|
'[data-dtm="lyric-terms"]'
|
|
@@ -15023,7 +15341,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
15023
15341
|
lyricBreathiness.value = String(active.vocalBreathiness);
|
|
15024
15342
|
lyricBreathinessLabel.textContent = `${active.vocalBreathiness}`;
|
|
15025
15343
|
lyricVibrato.checked = active.vocalVibrato;
|
|
15026
|
-
|
|
15344
|
+
lyricOctaveUnison.value = active.vocalOctaveUnison;
|
|
15027
15345
|
const updateLyricCount = () => {
|
|
15028
15346
|
const n = normalizeLyrics(lyricInput.value).length;
|
|
15029
15347
|
lyricCount.textContent = active.lyricModel && n > 0 ? `${n}\u97F3\u7BC0` : "";
|
|
@@ -15145,8 +15463,8 @@ var mountDAW = (target, options = {}) => {
|
|
|
15145
15463
|
active.vocalVibrato = lyricVibrato.checked;
|
|
15146
15464
|
fireLyricsChange(active);
|
|
15147
15465
|
});
|
|
15148
|
-
|
|
15149
|
-
active.
|
|
15466
|
+
lyricOctaveUnison.addEventListener("change", () => {
|
|
15467
|
+
active.vocalOctaveUnison = lyricOctaveUnison.value;
|
|
15150
15468
|
fireLyricsChange(active);
|
|
15151
15469
|
});
|
|
15152
15470
|
lyricInput.addEventListener("input", () => {
|
|
@@ -15277,6 +15595,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
15277
15595
|
const trackInstrumentsForMeta = {};
|
|
15278
15596
|
const trackCompressionForMeta = {};
|
|
15279
15597
|
const trackWidthForMeta = {};
|
|
15598
|
+
const trackReverbSendForMeta = {};
|
|
15280
15599
|
const trackEqLowForMeta = {};
|
|
15281
15600
|
const trackEqMidForMeta = {};
|
|
15282
15601
|
const trackEqHighForMeta = {};
|
|
@@ -15285,6 +15604,8 @@ var mountDAW = (target, options = {}) => {
|
|
|
15285
15604
|
if (t.trackCompression !== 0)
|
|
15286
15605
|
trackCompressionForMeta[i2] = t.trackCompression;
|
|
15287
15606
|
if (t.trackWidth !== 100) trackWidthForMeta[i2] = t.trackWidth;
|
|
15607
|
+
if (t.trackReverbSend !== 0)
|
|
15608
|
+
trackReverbSendForMeta[i2] = t.trackReverbSend;
|
|
15288
15609
|
if (t.trackEqLow !== 0) trackEqLowForMeta[i2] = t.trackEqLow;
|
|
15289
15610
|
if (t.trackEqMid !== 0) trackEqMidForMeta[i2] = t.trackEqMid;
|
|
15290
15611
|
if (t.trackEqHigh !== 0) trackEqHighForMeta[i2] = t.trackEqHigh;
|
|
@@ -15292,6 +15613,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
15292
15613
|
const trackInstMeta = Object.keys(trackInstrumentsForMeta).length > 0 ? trackInstrumentsForMeta : void 0;
|
|
15293
15614
|
const trackCompMeta = Object.keys(trackCompressionForMeta).length > 0 ? trackCompressionForMeta : void 0;
|
|
15294
15615
|
const trackWidthMeta = Object.keys(trackWidthForMeta).length > 0 ? trackWidthForMeta : void 0;
|
|
15616
|
+
const trackReverbSendMeta = Object.keys(trackReverbSendForMeta).length > 0 ? trackReverbSendForMeta : void 0;
|
|
15295
15617
|
const trackEqLowMeta = Object.keys(trackEqLowForMeta).length > 0 ? trackEqLowForMeta : void 0;
|
|
15296
15618
|
const trackEqMidMeta = Object.keys(trackEqMidForMeta).length > 0 ? trackEqMidForMeta : void 0;
|
|
15297
15619
|
const trackEqHighMeta = Object.keys(trackEqHighForMeta).length > 0 ? trackEqHighForMeta : void 0;
|
|
@@ -15312,6 +15634,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
15312
15634
|
trackInstruments: trackInstMeta,
|
|
15313
15635
|
trackCompression: trackCompMeta,
|
|
15314
15636
|
trackWidth: trackWidthMeta,
|
|
15637
|
+
trackReverbSend: trackReverbSendMeta,
|
|
15315
15638
|
trackEqLow: trackEqLowMeta,
|
|
15316
15639
|
trackEqMid: trackEqMidMeta,
|
|
15317
15640
|
trackEqHigh: trackEqHighMeta
|
|
@@ -15335,6 +15658,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
15335
15658
|
trackInstruments: trackInstMeta,
|
|
15336
15659
|
trackCompression: trackCompMeta,
|
|
15337
15660
|
trackWidth: trackWidthMeta,
|
|
15661
|
+
trackReverbSend: trackReverbSendMeta,
|
|
15338
15662
|
trackEqLow: trackEqLowMeta,
|
|
15339
15663
|
trackEqMid: trackEqMidMeta,
|
|
15340
15664
|
trackEqHigh: trackEqHighMeta
|
|
@@ -15390,7 +15714,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
15390
15714
|
del: t.vocalDelay,
|
|
15391
15715
|
gen: t.vocalGender,
|
|
15392
15716
|
bre: t.vocalBreathiness,
|
|
15393
|
-
|
|
15717
|
+
uni: t.vocalOctaveUnison
|
|
15394
15718
|
})).filter(
|
|
15395
15719
|
(x2) => x2.model.length > 0 && x2.text.length > 0 && x2.notes.length > 0
|
|
15396
15720
|
).map((x2) => {
|
|
@@ -15404,7 +15728,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
15404
15728
|
x2.del === 0 ? "" : `e${x2.del}`,
|
|
15405
15729
|
x2.gen === 50 ? "" : `g${x2.gen}`,
|
|
15406
15730
|
x2.bre === 50 ? "" : `h${x2.bre}`,
|
|
15407
|
-
x2.
|
|
15731
|
+
OCTAVE_UNISON_TOKEN[x2.uni]
|
|
15408
15732
|
].filter((s) => s.length > 0).join(" ");
|
|
15409
15733
|
const head = params ? `${x2.model} ${params}` : x2.model;
|
|
15410
15734
|
return `@@${x2.i} ${head} ${x2.text}`;
|
|
@@ -15473,7 +15797,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
15473
15797
|
const canvas = getGridCanvas();
|
|
15474
15798
|
const yIndex = renderConfig.keyCount - 1 - (pitch - renderConfig.pitchRangeStart);
|
|
15475
15799
|
const logicalY = yIndex * renderConfig.keyHeight;
|
|
15476
|
-
currentOffsetY =
|
|
15800
|
+
currentOffsetY = clamp5(
|
|
15477
15801
|
logicalY - (canvas.height - renderConfig.keyHeight) / 2,
|
|
15478
15802
|
0,
|
|
15479
15803
|
getMaxOffsetY()
|
|
@@ -15604,6 +15928,11 @@ var mountDAW = (target, options = {}) => {
|
|
|
15604
15928
|
t.trackWidth = width;
|
|
15605
15929
|
options.onTrackWidthChange?.(t.config.id, width);
|
|
15606
15930
|
}
|
|
15931
|
+
const reverbSend = meta.trackReverbSend?.[i2] ?? 0;
|
|
15932
|
+
if (t.trackReverbSend !== reverbSend) {
|
|
15933
|
+
t.trackReverbSend = reverbSend;
|
|
15934
|
+
options.onTrackReverbSendChange?.(t.config.id, reverbSend);
|
|
15935
|
+
}
|
|
15607
15936
|
const eqLow = meta.trackEqLow?.[i2] ?? 0;
|
|
15608
15937
|
if (t.trackEqLow !== eqLow) {
|
|
15609
15938
|
t.trackEqLow = eqLow;
|
|
@@ -15641,7 +15970,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
15641
15970
|
active.vocalDelay = 0;
|
|
15642
15971
|
active.vocalGender = 50;
|
|
15643
15972
|
active.vocalBreathiness = 50;
|
|
15644
|
-
active.
|
|
15973
|
+
active.vocalOctaveUnison = "none";
|
|
15645
15974
|
} else {
|
|
15646
15975
|
for (const t of trackStates) {
|
|
15647
15976
|
t.lyrics = "";
|
|
@@ -15655,7 +15984,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
15655
15984
|
t.vocalDelay = 0;
|
|
15656
15985
|
t.vocalGender = 50;
|
|
15657
15986
|
t.vocalBreathiness = 50;
|
|
15658
|
-
t.
|
|
15987
|
+
t.vocalOctaveUnison = "none";
|
|
15659
15988
|
}
|
|
15660
15989
|
}
|
|
15661
15990
|
lyrics?.forEach((lt) => {
|
|
@@ -15673,7 +16002,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
15673
16002
|
t.vocalDelay = lt.delay ?? 0;
|
|
15674
16003
|
t.vocalGender = lt.gender ?? 50;
|
|
15675
16004
|
t.vocalBreathiness = lt.breathiness ?? 50;
|
|
15676
|
-
t.
|
|
16005
|
+
t.vocalOctaveUnison = lt.octaveUnison ?? "none";
|
|
15677
16006
|
});
|
|
15678
16007
|
for (const p of placements) {
|
|
15679
16008
|
if (applyActiveOnly && p.trackIndex !== activeTrackIndex) continue;
|
|
@@ -15757,7 +16086,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
15757
16086
|
active.vocalDelay = 0;
|
|
15758
16087
|
active.vocalGender = 50;
|
|
15759
16088
|
active.vocalBreathiness = 50;
|
|
15760
|
-
active.
|
|
16089
|
+
active.vocalOctaveUnison = "none";
|
|
15761
16090
|
} else {
|
|
15762
16091
|
clearAll();
|
|
15763
16092
|
for (const t of trackStates) t.core.setLoadMode(true);
|
|
@@ -15773,7 +16102,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
15773
16102
|
t.vocalDelay = 0;
|
|
15774
16103
|
t.vocalGender = 50;
|
|
15775
16104
|
t.vocalBreathiness = 50;
|
|
15776
|
-
t.
|
|
16105
|
+
t.vocalOctaveUnison = "none";
|
|
15777
16106
|
}
|
|
15778
16107
|
}
|
|
15779
16108
|
const { placements, bpm: parsedBpm } = isAdvanced ? extractMidiPlacementsByTrack(
|
|
@@ -16043,8 +16372,8 @@ var mountDAW = (target, options = {}) => {
|
|
|
16043
16372
|
refs.reverbAmount.value = "20";
|
|
16044
16373
|
refs.reverbAmountLabel.textContent = "20%";
|
|
16045
16374
|
options.onReverbChange?.(20);
|
|
16046
|
-
const bpmT =
|
|
16047
|
-
reverbDecay =
|
|
16375
|
+
const bpmT = clamp5((bpm - 60) / (180 - 60), 0, 1);
|
|
16376
|
+
reverbDecay = clamp5(
|
|
16048
16377
|
3 - bpmT * (3 - 0.9),
|
|
16049
16378
|
MIN_REVERB_DECAY_SEC,
|
|
16050
16379
|
MAX_REVERB_DECAY_SEC
|
|
@@ -16073,6 +16402,10 @@ var mountDAW = (target, options = {}) => {
|
|
|
16073
16402
|
t.trackWidth = 115;
|
|
16074
16403
|
options.onTrackCompressionChange?.(t.config.id, comp);
|
|
16075
16404
|
options.onTrackWidthChange?.(t.config.id, 115);
|
|
16405
|
+
if (!t.lyricModel) {
|
|
16406
|
+
t.trackReverbSend = 15;
|
|
16407
|
+
options.onTrackReverbSendChange?.(t.config.id, 15);
|
|
16408
|
+
}
|
|
16076
16409
|
if (t.lyricModel) {
|
|
16077
16410
|
t.vocalVibrato = true;
|
|
16078
16411
|
t.vocalReverb = isMainVocal ? 15 : 30;
|
|
@@ -16971,7 +17304,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
16971
17304
|
currentPlayStep = step;
|
|
16972
17305
|
playbackState = "paused";
|
|
16973
17306
|
const canvas = getGridCanvas();
|
|
16974
|
-
currentOffsetX =
|
|
17307
|
+
currentOffsetX = clamp5(
|
|
16975
17308
|
step * renderConfig.stepWidth - canvas.width * 0.5,
|
|
16976
17309
|
0,
|
|
16977
17310
|
getMaxOffsetX()
|
|
@@ -17017,11 +17350,11 @@ var mountDAW = (target, options = {}) => {
|
|
|
17017
17350
|
getViewState,
|
|
17018
17351
|
setViewState: (state) => {
|
|
17019
17352
|
if (typeof state.zoomX === "number") {
|
|
17020
|
-
zoomX =
|
|
17353
|
+
zoomX = clamp5(state.zoomX, 25, 200);
|
|
17021
17354
|
applyZoomX();
|
|
17022
17355
|
}
|
|
17023
17356
|
if (typeof state.zoomY === "number") {
|
|
17024
|
-
zoomY =
|
|
17357
|
+
zoomY = clamp5(state.zoomY, 50, 200);
|
|
17025
17358
|
applyZoomY();
|
|
17026
17359
|
}
|
|
17027
17360
|
if (typeof state.decomposeChord === "boolean") {
|
|
@@ -17043,24 +17376,24 @@ var mountDAW = (target, options = {}) => {
|
|
|
17043
17376
|
forcePauseAt,
|
|
17044
17377
|
setLoading,
|
|
17045
17378
|
setMasterVolume: (volume) => {
|
|
17046
|
-
masterVolume =
|
|
17379
|
+
masterVolume = clamp5(volume, 0, 100);
|
|
17047
17380
|
refs.masterVolume.value = String(masterVolume);
|
|
17048
17381
|
refs.masterVolumeLabel.textContent = `${masterVolume}%`;
|
|
17049
17382
|
options.singingVoices?.setVolume(masterVolume / 100);
|
|
17050
17383
|
},
|
|
17051
17384
|
setVolume: (volume) => {
|
|
17052
|
-
masterVolume =
|
|
17385
|
+
masterVolume = clamp5(volume, 0, 100);
|
|
17053
17386
|
refs.masterVolume.value = String(masterVolume);
|
|
17054
17387
|
refs.masterVolumeLabel.textContent = `${masterVolume}%`;
|
|
17055
17388
|
options.singingVoices?.setVolume(masterVolume / 100);
|
|
17056
17389
|
},
|
|
17057
17390
|
setDrumVolume: (volume) => {
|
|
17058
|
-
drumVolume =
|
|
17391
|
+
drumVolume = clamp5(volume, 0, 100);
|
|
17059
17392
|
refs.drumVolume.value = String(drumVolume);
|
|
17060
17393
|
refs.drumVolumeLabel.textContent = `${drumVolume}%`;
|
|
17061
17394
|
},
|
|
17062
17395
|
setReverbAmount: (amount) => {
|
|
17063
|
-
reverbAmount =
|
|
17396
|
+
reverbAmount = clamp5(amount, 0, 100);
|
|
17064
17397
|
refs.reverbAmount.value = String(reverbAmount);
|
|
17065
17398
|
refs.reverbAmountLabel.textContent = `${reverbAmount}%`;
|
|
17066
17399
|
options.onReverbChange?.(reverbAmount);
|
|
@@ -17084,7 +17417,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
17084
17417
|
options.onReverbPreDelayChange?.(reverbPreDelay);
|
|
17085
17418
|
},
|
|
17086
17419
|
setDelayAmount: (amount) => {
|
|
17087
|
-
delayAmount =
|
|
17420
|
+
delayAmount = clamp5(amount, 0, 100);
|
|
17088
17421
|
refs.delayAmount.value = String(delayAmount);
|
|
17089
17422
|
refs.delayAmountLabel.textContent = `${delayAmount}%`;
|
|
17090
17423
|
options.onDelayChange?.(delayAmount);
|
|
@@ -17133,7 +17466,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
17133
17466
|
t.vocalDelay = data.vocalDelay ?? 0;
|
|
17134
17467
|
t.vocalGender = data.vocalGender ?? 50;
|
|
17135
17468
|
t.vocalBreathiness = data.vocalBreathiness ?? 50;
|
|
17136
|
-
t.
|
|
17469
|
+
t.vocalOctaveUnison = data.vocalOctaveUnison ?? "none";
|
|
17137
17470
|
},
|
|
17138
17471
|
applyTrackInstrument: (trackIndex, instrumentName) => {
|
|
17139
17472
|
const t = trackStates[trackIndex];
|
|
@@ -17255,7 +17588,7 @@ var playSingingMML = async (mml, options = {}) => {
|
|
|
17255
17588
|
delaySend: (lt.delay ?? 0) / 100,
|
|
17256
17589
|
gender: (lt.gender ?? 50) / 100,
|
|
17257
17590
|
breathiness: (lt.breathiness ?? 50) / 100,
|
|
17258
|
-
|
|
17591
|
+
octaveUnison: lt.octaveUnison,
|
|
17259
17592
|
notes
|
|
17260
17593
|
};
|
|
17261
17594
|
});
|
|
@@ -17863,137 +18196,6 @@ var isSupported = midiJsonParser.isSupported;
|
|
|
17863
18196
|
var parseArrayBuffer = midiJsonParser.parseArrayBuffer;
|
|
17864
18197
|
URL.revokeObjectURL(url);
|
|
17865
18198
|
|
|
17866
|
-
// src/channel-strip.ts
|
|
17867
|
-
var clamp5 = (v, lo, hi) => Math.max(lo, Math.min(hi, v));
|
|
17868
|
-
var compressionParams = (amount) => {
|
|
17869
|
-
const t = clamp5(amount, 0, 100) / 100;
|
|
17870
|
-
return {
|
|
17871
|
-
threshold: 0 + (-24 - 0) * t,
|
|
17872
|
-
ratio: 1 + (12 - 1) * t,
|
|
17873
|
-
knee: 0 + (6 - 0) * t,
|
|
17874
|
-
attack: 0.02 + (3e-3 - 0.02) * t,
|
|
17875
|
-
release: 0.25 + (0.15 - 0.25) * t
|
|
17876
|
-
};
|
|
17877
|
-
};
|
|
17878
|
-
var EQ_LOW_FREQ = 200;
|
|
17879
|
-
var EQ_MID_FREQ = 1e3;
|
|
17880
|
-
var EQ_HIGH_FREQ = 5e3;
|
|
17881
|
-
var EQ_MID_Q = 1;
|
|
17882
|
-
var EQ_MAX_DB = 12;
|
|
17883
|
-
var createChannelStrip = (ctx, destination, options = {}) => {
|
|
17884
|
-
const input = ctx.createGain();
|
|
17885
|
-
const eqLow = ctx.createBiquadFilter();
|
|
17886
|
-
eqLow.type = "lowshelf";
|
|
17887
|
-
eqLow.frequency.value = EQ_LOW_FREQ;
|
|
17888
|
-
eqLow.gain.value = clamp5(options.eqLow ?? 0, -EQ_MAX_DB, EQ_MAX_DB);
|
|
17889
|
-
const eqMid = ctx.createBiquadFilter();
|
|
17890
|
-
eqMid.type = "peaking";
|
|
17891
|
-
eqMid.frequency.value = EQ_MID_FREQ;
|
|
17892
|
-
eqMid.Q.value = EQ_MID_Q;
|
|
17893
|
-
eqMid.gain.value = clamp5(options.eqMid ?? 0, -EQ_MAX_DB, EQ_MAX_DB);
|
|
17894
|
-
const eqHigh = ctx.createBiquadFilter();
|
|
17895
|
-
eqHigh.type = "highshelf";
|
|
17896
|
-
eqHigh.frequency.value = EQ_HIGH_FREQ;
|
|
17897
|
-
eqHigh.gain.value = clamp5(options.eqHigh ?? 0, -EQ_MAX_DB, EQ_MAX_DB);
|
|
17898
|
-
input.connect(eqLow);
|
|
17899
|
-
eqLow.connect(eqMid);
|
|
17900
|
-
eqMid.connect(eqHigh);
|
|
17901
|
-
const compressor = ctx.createDynamicsCompressor();
|
|
17902
|
-
const applyCompression = (amount) => {
|
|
17903
|
-
const p = compressionParams(amount);
|
|
17904
|
-
const now = ctx.currentTime;
|
|
17905
|
-
compressor.threshold.setValueAtTime(p.threshold, now);
|
|
17906
|
-
compressor.ratio.setValueAtTime(p.ratio, now);
|
|
17907
|
-
compressor.knee.setValueAtTime(p.knee, now);
|
|
17908
|
-
compressor.attack.setValueAtTime(p.attack, now);
|
|
17909
|
-
compressor.release.setValueAtTime(p.release, now);
|
|
17910
|
-
};
|
|
17911
|
-
applyCompression(options.compression ?? 0);
|
|
17912
|
-
const splitter = ctx.createChannelSplitter(2);
|
|
17913
|
-
const mid = ctx.createGain();
|
|
17914
|
-
mid.gain.value = 0.5;
|
|
17915
|
-
splitter.connect(mid, 0);
|
|
17916
|
-
splitter.connect(mid, 1);
|
|
17917
|
-
const sideSum = ctx.createGain();
|
|
17918
|
-
sideSum.gain.value = 1;
|
|
17919
|
-
const sideL = ctx.createGain();
|
|
17920
|
-
sideL.gain.value = 0.5;
|
|
17921
|
-
const sideR = ctx.createGain();
|
|
17922
|
-
sideR.gain.value = -0.5;
|
|
17923
|
-
splitter.connect(sideL, 0);
|
|
17924
|
-
splitter.connect(sideR, 1);
|
|
17925
|
-
sideL.connect(sideSum);
|
|
17926
|
-
sideR.connect(sideSum);
|
|
17927
|
-
const widthGain = ctx.createGain();
|
|
17928
|
-
sideSum.connect(widthGain);
|
|
17929
|
-
const widthInv = ctx.createGain();
|
|
17930
|
-
widthInv.gain.value = -1;
|
|
17931
|
-
widthGain.connect(widthInv);
|
|
17932
|
-
const outL = ctx.createGain();
|
|
17933
|
-
mid.connect(outL);
|
|
17934
|
-
widthGain.connect(outL);
|
|
17935
|
-
const outR = ctx.createGain();
|
|
17936
|
-
mid.connect(outR);
|
|
17937
|
-
widthInv.connect(outR);
|
|
17938
|
-
const merger = ctx.createChannelMerger(2);
|
|
17939
|
-
outL.connect(merger, 0, 0);
|
|
17940
|
-
outR.connect(merger, 0, 1);
|
|
17941
|
-
const setWidth = (width) => {
|
|
17942
|
-
widthGain.gain.setTargetAtTime(
|
|
17943
|
-
clamp5(width, 0, 200) / 100,
|
|
17944
|
-
ctx.currentTime,
|
|
17945
|
-
0.02
|
|
17946
|
-
);
|
|
17947
|
-
};
|
|
17948
|
-
setWidth(options.width ?? 100);
|
|
17949
|
-
eqHigh.connect(compressor);
|
|
17950
|
-
compressor.connect(splitter);
|
|
17951
|
-
merger.connect(destination);
|
|
17952
|
-
return {
|
|
17953
|
-
input,
|
|
17954
|
-
setEqLow: (db) => {
|
|
17955
|
-
eqLow.gain.setTargetAtTime(
|
|
17956
|
-
clamp5(db, -EQ_MAX_DB, EQ_MAX_DB),
|
|
17957
|
-
ctx.currentTime,
|
|
17958
|
-
0.02
|
|
17959
|
-
);
|
|
17960
|
-
},
|
|
17961
|
-
setEqMid: (db) => {
|
|
17962
|
-
eqMid.gain.setTargetAtTime(
|
|
17963
|
-
clamp5(db, -EQ_MAX_DB, EQ_MAX_DB),
|
|
17964
|
-
ctx.currentTime,
|
|
17965
|
-
0.02
|
|
17966
|
-
);
|
|
17967
|
-
},
|
|
17968
|
-
setEqHigh: (db) => {
|
|
17969
|
-
eqHigh.gain.setTargetAtTime(
|
|
17970
|
-
clamp5(db, -EQ_MAX_DB, EQ_MAX_DB),
|
|
17971
|
-
ctx.currentTime,
|
|
17972
|
-
0.02
|
|
17973
|
-
);
|
|
17974
|
-
},
|
|
17975
|
-
setCompression: applyCompression,
|
|
17976
|
-
setWidth,
|
|
17977
|
-
dispose: () => {
|
|
17978
|
-
input.disconnect();
|
|
17979
|
-
eqLow.disconnect();
|
|
17980
|
-
eqMid.disconnect();
|
|
17981
|
-
eqHigh.disconnect();
|
|
17982
|
-
compressor.disconnect();
|
|
17983
|
-
splitter.disconnect();
|
|
17984
|
-
mid.disconnect();
|
|
17985
|
-
sideSum.disconnect();
|
|
17986
|
-
sideL.disconnect();
|
|
17987
|
-
sideR.disconnect();
|
|
17988
|
-
widthGain.disconnect();
|
|
17989
|
-
widthInv.disconnect();
|
|
17990
|
-
outL.disconnect();
|
|
17991
|
-
outR.disconnect();
|
|
17992
|
-
merger.disconnect();
|
|
17993
|
-
}
|
|
17994
|
-
};
|
|
17995
|
-
};
|
|
17996
|
-
|
|
17997
18199
|
// src/clip-meter.ts
|
|
17998
18200
|
var createClipMeter = (ctx, source, options = {}) => {
|
|
17999
18201
|
const threshold = options.threshold ?? 0.98;
|
|
@@ -18211,7 +18413,6 @@ var createDtmStudio = async (options = {}) => {
|
|
|
18211
18413
|
reverbConvolver.normalize = true;
|
|
18212
18414
|
const reverbWetGain = audioCtx.createGain();
|
|
18213
18415
|
reverbWetGain.gain.value = reverbAmountToGain(options.reverbAmount ?? 0);
|
|
18214
|
-
masterGain.connect(reverbPreDelay);
|
|
18215
18416
|
reverbPreDelay.connect(reverbConvolver);
|
|
18216
18417
|
reverbConvolver.connect(reverbWetGain);
|
|
18217
18418
|
const setReverbAmount = (amount) => {
|
|
@@ -18277,7 +18478,9 @@ var createDtmStudio = async (options = {}) => {
|
|
|
18277
18478
|
const getChannelStrip = (trackId) => {
|
|
18278
18479
|
let strip = channelStrips.get(trackId);
|
|
18279
18480
|
if (!strip) {
|
|
18280
|
-
strip = createChannelStrip(audioCtx, masterGain
|
|
18481
|
+
strip = createChannelStrip(audioCtx, masterGain, {
|
|
18482
|
+
reverbBus: reverbPreDelay
|
|
18483
|
+
});
|
|
18281
18484
|
channelStrips.set(trackId, strip);
|
|
18282
18485
|
}
|
|
18283
18486
|
return strip;
|
|
@@ -18314,7 +18517,8 @@ var createDtmStudio = async (options = {}) => {
|
|
|
18314
18517
|
voicebanks,
|
|
18315
18518
|
worldlineScriptUrl: options.worldlineScriptUrl,
|
|
18316
18519
|
// ボーカルトラック個別のリバーブセンド(`r`トークン)先。マスタリバーブの
|
|
18317
|
-
// Convolver 入力へ直接センドする(
|
|
18520
|
+
// Convolver 入力へ直接センドする(PreDelayは経由しない。チャンネルストリップの
|
|
18521
|
+
// reverbSend とは別経路の、音節単位でより細かく制御できるセンド)。
|
|
18318
18522
|
reverbBus: reverbConvolver,
|
|
18319
18523
|
// ボーカルトラック個別のディレイセンド(`e`トークン)先。
|
|
18320
18524
|
delayBus: delayBus.input,
|
|
@@ -18612,6 +18816,7 @@ var createDtmStudio = async (options = {}) => {
|
|
|
18612
18816
|
onScheduleFade: scheduleFade,
|
|
18613
18817
|
onTrackCompressionChange: (trackId, amount) => getChannelStrip(trackId).setCompression(amount),
|
|
18614
18818
|
onTrackWidthChange: (trackId, width) => getChannelStrip(trackId).setWidth(width),
|
|
18819
|
+
onTrackReverbSendChange: (trackId, amount) => getChannelStrip(trackId).setReverbSend(amount),
|
|
18615
18820
|
onTrackEqLowChange: (trackId, db) => getChannelStrip(trackId).setEqLow(db),
|
|
18616
18821
|
onTrackEqMidChange: (trackId, db) => getChannelStrip(trackId).setEqMid(db),
|
|
18617
18822
|
onTrackEqHighChange: (trackId, db) => getChannelStrip(trackId).setEqHigh(db),
|