@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.js
CHANGED
|
@@ -1466,6 +1466,149 @@ var getDrumPatternKeys = (name, dict) => {
|
|
|
1466
1466
|
return Array.from(keys);
|
|
1467
1467
|
};
|
|
1468
1468
|
|
|
1469
|
+
// src/channel-strip.ts
|
|
1470
|
+
var clamp = (v, lo, hi) => Math.max(lo, Math.min(hi, v));
|
|
1471
|
+
var compressionParams = (amount) => {
|
|
1472
|
+
const t = clamp(amount, 0, 100) / 100;
|
|
1473
|
+
return {
|
|
1474
|
+
threshold: 0 + (-24 - 0) * t,
|
|
1475
|
+
ratio: 1 + (12 - 1) * t,
|
|
1476
|
+
knee: 0 + (6 - 0) * t,
|
|
1477
|
+
attack: 0.02 + (3e-3 - 0.02) * t,
|
|
1478
|
+
release: 0.25 + (0.15 - 0.25) * t
|
|
1479
|
+
};
|
|
1480
|
+
};
|
|
1481
|
+
var EQ_LOW_FREQ = 200;
|
|
1482
|
+
var EQ_MID_FREQ = 1e3;
|
|
1483
|
+
var EQ_HIGH_FREQ = 5e3;
|
|
1484
|
+
var EQ_MID_Q = 1;
|
|
1485
|
+
var EQ_MAX_DB = 12;
|
|
1486
|
+
var createChannelStrip = (ctx, destination, options = {}) => {
|
|
1487
|
+
const input = ctx.createGain();
|
|
1488
|
+
const eqLow = ctx.createBiquadFilter();
|
|
1489
|
+
eqLow.type = "lowshelf";
|
|
1490
|
+
eqLow.frequency.value = EQ_LOW_FREQ;
|
|
1491
|
+
eqLow.gain.value = clamp(options.eqLow ?? 0, -EQ_MAX_DB, EQ_MAX_DB);
|
|
1492
|
+
const eqMid = ctx.createBiquadFilter();
|
|
1493
|
+
eqMid.type = "peaking";
|
|
1494
|
+
eqMid.frequency.value = EQ_MID_FREQ;
|
|
1495
|
+
eqMid.Q.value = EQ_MID_Q;
|
|
1496
|
+
eqMid.gain.value = clamp(options.eqMid ?? 0, -EQ_MAX_DB, EQ_MAX_DB);
|
|
1497
|
+
const eqHigh = ctx.createBiquadFilter();
|
|
1498
|
+
eqHigh.type = "highshelf";
|
|
1499
|
+
eqHigh.frequency.value = EQ_HIGH_FREQ;
|
|
1500
|
+
eqHigh.gain.value = clamp(options.eqHigh ?? 0, -EQ_MAX_DB, EQ_MAX_DB);
|
|
1501
|
+
input.connect(eqLow);
|
|
1502
|
+
eqLow.connect(eqMid);
|
|
1503
|
+
eqMid.connect(eqHigh);
|
|
1504
|
+
const compressor = ctx.createDynamicsCompressor();
|
|
1505
|
+
const applyCompression = (amount) => {
|
|
1506
|
+
const p = compressionParams(amount);
|
|
1507
|
+
const now = ctx.currentTime;
|
|
1508
|
+
compressor.threshold.setValueAtTime(p.threshold, now);
|
|
1509
|
+
compressor.ratio.setValueAtTime(p.ratio, now);
|
|
1510
|
+
compressor.knee.setValueAtTime(p.knee, now);
|
|
1511
|
+
compressor.attack.setValueAtTime(p.attack, now);
|
|
1512
|
+
compressor.release.setValueAtTime(p.release, now);
|
|
1513
|
+
};
|
|
1514
|
+
applyCompression(options.compression ?? 0);
|
|
1515
|
+
const splitter = ctx.createChannelSplitter(2);
|
|
1516
|
+
const mid = ctx.createGain();
|
|
1517
|
+
mid.gain.value = 0.5;
|
|
1518
|
+
splitter.connect(mid, 0);
|
|
1519
|
+
splitter.connect(mid, 1);
|
|
1520
|
+
const sideSum = ctx.createGain();
|
|
1521
|
+
sideSum.gain.value = 1;
|
|
1522
|
+
const sideL = ctx.createGain();
|
|
1523
|
+
sideL.gain.value = 0.5;
|
|
1524
|
+
const sideR = ctx.createGain();
|
|
1525
|
+
sideR.gain.value = -0.5;
|
|
1526
|
+
splitter.connect(sideL, 0);
|
|
1527
|
+
splitter.connect(sideR, 1);
|
|
1528
|
+
sideL.connect(sideSum);
|
|
1529
|
+
sideR.connect(sideSum);
|
|
1530
|
+
const widthGain = ctx.createGain();
|
|
1531
|
+
sideSum.connect(widthGain);
|
|
1532
|
+
const widthInv = ctx.createGain();
|
|
1533
|
+
widthInv.gain.value = -1;
|
|
1534
|
+
widthGain.connect(widthInv);
|
|
1535
|
+
const outL = ctx.createGain();
|
|
1536
|
+
mid.connect(outL);
|
|
1537
|
+
widthGain.connect(outL);
|
|
1538
|
+
const outR = ctx.createGain();
|
|
1539
|
+
mid.connect(outR);
|
|
1540
|
+
widthInv.connect(outR);
|
|
1541
|
+
const merger = ctx.createChannelMerger(2);
|
|
1542
|
+
outL.connect(merger, 0, 0);
|
|
1543
|
+
outR.connect(merger, 0, 1);
|
|
1544
|
+
const setWidth = (width) => {
|
|
1545
|
+
widthGain.gain.setTargetAtTime(
|
|
1546
|
+
clamp(width, 0, 200) / 100,
|
|
1547
|
+
ctx.currentTime,
|
|
1548
|
+
0.02
|
|
1549
|
+
);
|
|
1550
|
+
};
|
|
1551
|
+
setWidth(options.width ?? 100);
|
|
1552
|
+
eqHigh.connect(compressor);
|
|
1553
|
+
compressor.connect(splitter);
|
|
1554
|
+
merger.connect(destination);
|
|
1555
|
+
const reverbSendGain = ctx.createGain();
|
|
1556
|
+
reverbSendGain.gain.value = clamp(options.reverbSend ?? 0, 0, 100) / 100;
|
|
1557
|
+
merger.connect(reverbSendGain);
|
|
1558
|
+
if (options.reverbBus) reverbSendGain.connect(options.reverbBus);
|
|
1559
|
+
return {
|
|
1560
|
+
input,
|
|
1561
|
+
setEqLow: (db) => {
|
|
1562
|
+
eqLow.gain.setTargetAtTime(
|
|
1563
|
+
clamp(db, -EQ_MAX_DB, EQ_MAX_DB),
|
|
1564
|
+
ctx.currentTime,
|
|
1565
|
+
0.02
|
|
1566
|
+
);
|
|
1567
|
+
},
|
|
1568
|
+
setEqMid: (db) => {
|
|
1569
|
+
eqMid.gain.setTargetAtTime(
|
|
1570
|
+
clamp(db, -EQ_MAX_DB, EQ_MAX_DB),
|
|
1571
|
+
ctx.currentTime,
|
|
1572
|
+
0.02
|
|
1573
|
+
);
|
|
1574
|
+
},
|
|
1575
|
+
setEqHigh: (db) => {
|
|
1576
|
+
eqHigh.gain.setTargetAtTime(
|
|
1577
|
+
clamp(db, -EQ_MAX_DB, EQ_MAX_DB),
|
|
1578
|
+
ctx.currentTime,
|
|
1579
|
+
0.02
|
|
1580
|
+
);
|
|
1581
|
+
},
|
|
1582
|
+
setCompression: applyCompression,
|
|
1583
|
+
setWidth,
|
|
1584
|
+
setReverbSend: (amount) => {
|
|
1585
|
+
reverbSendGain.gain.setTargetAtTime(
|
|
1586
|
+
clamp(amount, 0, 100) / 100,
|
|
1587
|
+
ctx.currentTime,
|
|
1588
|
+
0.02
|
|
1589
|
+
);
|
|
1590
|
+
},
|
|
1591
|
+
dispose: () => {
|
|
1592
|
+
input.disconnect();
|
|
1593
|
+
eqLow.disconnect();
|
|
1594
|
+
eqMid.disconnect();
|
|
1595
|
+
eqHigh.disconnect();
|
|
1596
|
+
compressor.disconnect();
|
|
1597
|
+
splitter.disconnect();
|
|
1598
|
+
mid.disconnect();
|
|
1599
|
+
sideSum.disconnect();
|
|
1600
|
+
sideL.disconnect();
|
|
1601
|
+
sideR.disconnect();
|
|
1602
|
+
widthGain.disconnect();
|
|
1603
|
+
widthInv.disconnect();
|
|
1604
|
+
outL.disconnect();
|
|
1605
|
+
outR.disconnect();
|
|
1606
|
+
merger.disconnect();
|
|
1607
|
+
reverbSendGain.disconnect();
|
|
1608
|
+
}
|
|
1609
|
+
};
|
|
1610
|
+
};
|
|
1611
|
+
|
|
1469
1612
|
// src/chords.ts
|
|
1470
1613
|
var C3 = 48;
|
|
1471
1614
|
var buildChordPlacements = (options) => {
|
|
@@ -2295,7 +2438,7 @@ var normalizeLyricLines = (lines) => {
|
|
|
2295
2438
|
var LYRIC_LINE = /^@@(\d+)\s*(.*)$/;
|
|
2296
2439
|
var isLyricContinuation = (seg) => !/^[@#]/.test(seg);
|
|
2297
2440
|
var splitSegments = (mml) => mml.split(/[;\n\r]+/).map((s) => s.trim()).filter((s) => s.length > 0);
|
|
2298
|
-
var
|
|
2441
|
+
var clamp2 = (value, lo, hi) => Math.min(hi, Math.max(lo, value));
|
|
2299
2442
|
var MAX_VOCAL_VOLUME = 400;
|
|
2300
2443
|
var VOCAL_BOOST_DB_PER_PERCENT = 0.08;
|
|
2301
2444
|
var vocalVolumeToGain = (v) => {
|
|
@@ -2320,7 +2463,7 @@ var parseLyrics = (mml) => {
|
|
|
2320
2463
|
let delay = 0;
|
|
2321
2464
|
let gender = 50;
|
|
2322
2465
|
let breathiness = 50;
|
|
2323
|
-
let
|
|
2466
|
+
let octaveUnison = "none";
|
|
2324
2467
|
const modelMatch = rest.match(
|
|
2325
2468
|
/^([a-z_][a-z0-9_]*?)(?=(?:[vqpobrghew]-?\d)|[^a-z0-9_]|$)(?::(\d+))?/i
|
|
2326
2469
|
);
|
|
@@ -2329,7 +2472,7 @@ var parseLyrics = (mml) => {
|
|
|
2329
2472
|
if (modelMatch) {
|
|
2330
2473
|
model = modelMatch[1].toLowerCase();
|
|
2331
2474
|
if (modelMatch[2]) {
|
|
2332
|
-
volume =
|
|
2475
|
+
volume = clamp2(Number.parseInt(modelMatch[2], 10), 0, MAX_VOCAL_VOLUME);
|
|
2333
2476
|
}
|
|
2334
2477
|
metaTokens.push(modelMatch[0]);
|
|
2335
2478
|
rest = rest.substring(modelMatch[0].length).trim();
|
|
@@ -2337,28 +2480,28 @@ var parseLyrics = (mml) => {
|
|
|
2337
2480
|
while (true) {
|
|
2338
2481
|
const vMatch = rest.match(/^v(\d+)/i);
|
|
2339
2482
|
if (vMatch) {
|
|
2340
|
-
volume =
|
|
2483
|
+
volume = clamp2(Number.parseInt(vMatch[1], 10), 0, MAX_VOCAL_VOLUME);
|
|
2341
2484
|
metaTokens.push(vMatch[0]);
|
|
2342
2485
|
rest = rest.substring(vMatch[0].length).trim();
|
|
2343
2486
|
continue;
|
|
2344
2487
|
}
|
|
2345
2488
|
const qMatch = rest.match(/^q(\d+)/i);
|
|
2346
2489
|
if (qMatch) {
|
|
2347
|
-
gate =
|
|
2490
|
+
gate = clamp2(Number.parseInt(qMatch[1], 10), 0, 100);
|
|
2348
2491
|
metaTokens.push(qMatch[0]);
|
|
2349
2492
|
rest = rest.substring(qMatch[0].length).trim();
|
|
2350
2493
|
continue;
|
|
2351
2494
|
}
|
|
2352
2495
|
const pMatch = rest.match(/^p(\d+)/i);
|
|
2353
2496
|
if (pMatch) {
|
|
2354
|
-
pan =
|
|
2497
|
+
pan = clamp2(Number.parseInt(pMatch[1], 10), 0, 127);
|
|
2355
2498
|
metaTokens.push(pMatch[0]);
|
|
2356
2499
|
rest = rest.substring(pMatch[0].length).trim();
|
|
2357
2500
|
continue;
|
|
2358
2501
|
}
|
|
2359
2502
|
const oMatch = rest.match(/^o(-?\d+)/i);
|
|
2360
2503
|
if (oMatch) {
|
|
2361
|
-
octave =
|
|
2504
|
+
octave = clamp2(Number.parseInt(oMatch[1], 10), -2, 2);
|
|
2362
2505
|
metaTokens.push(oMatch[0]);
|
|
2363
2506
|
rest = rest.substring(oMatch[0].length).trim();
|
|
2364
2507
|
continue;
|
|
@@ -2372,35 +2515,35 @@ var parseLyrics = (mml) => {
|
|
|
2372
2515
|
}
|
|
2373
2516
|
const rMatch = rest.match(/^r(\d+)/i);
|
|
2374
2517
|
if (rMatch) {
|
|
2375
|
-
reverb =
|
|
2518
|
+
reverb = clamp2(Number.parseInt(rMatch[1], 10), 0, 100);
|
|
2376
2519
|
metaTokens.push(rMatch[0]);
|
|
2377
2520
|
rest = rest.substring(rMatch[0].length).trim();
|
|
2378
2521
|
continue;
|
|
2379
2522
|
}
|
|
2380
2523
|
const gMatch = rest.match(/^g(\d+)/i);
|
|
2381
2524
|
if (gMatch) {
|
|
2382
|
-
gender =
|
|
2525
|
+
gender = clamp2(Number.parseInt(gMatch[1], 10), 0, 100);
|
|
2383
2526
|
metaTokens.push(gMatch[0]);
|
|
2384
2527
|
rest = rest.substring(gMatch[0].length).trim();
|
|
2385
2528
|
continue;
|
|
2386
2529
|
}
|
|
2387
2530
|
const hMatch = rest.match(/^h(\d+)/i);
|
|
2388
2531
|
if (hMatch) {
|
|
2389
|
-
breathiness =
|
|
2532
|
+
breathiness = clamp2(Number.parseInt(hMatch[1], 10), 0, 100);
|
|
2390
2533
|
metaTokens.push(hMatch[0]);
|
|
2391
2534
|
rest = rest.substring(hMatch[0].length).trim();
|
|
2392
2535
|
continue;
|
|
2393
2536
|
}
|
|
2394
2537
|
const eMatch = rest.match(/^e(\d+)/i);
|
|
2395
2538
|
if (eMatch) {
|
|
2396
|
-
delay =
|
|
2539
|
+
delay = clamp2(Number.parseInt(eMatch[1], 10), 0, 100);
|
|
2397
2540
|
metaTokens.push(eMatch[0]);
|
|
2398
2541
|
rest = rest.substring(eMatch[0].length).trim();
|
|
2399
2542
|
continue;
|
|
2400
2543
|
}
|
|
2401
|
-
const wMatch = rest.match(/^w([
|
|
2544
|
+
const wMatch = rest.match(/^w([0-3])/i);
|
|
2402
2545
|
if (wMatch) {
|
|
2403
|
-
|
|
2546
|
+
octaveUnison = ["none", "down", "up", "both"][Number.parseInt(wMatch[1], 10)];
|
|
2404
2547
|
metaTokens.push(wMatch[0]);
|
|
2405
2548
|
rest = rest.substring(wMatch[0].length).trim();
|
|
2406
2549
|
continue;
|
|
@@ -2424,7 +2567,7 @@ var parseLyrics = (mml) => {
|
|
|
2424
2567
|
delay,
|
|
2425
2568
|
gender,
|
|
2426
2569
|
breathiness,
|
|
2427
|
-
|
|
2570
|
+
octaveUnison,
|
|
2428
2571
|
syllables,
|
|
2429
2572
|
metaText: metaTokens.join(" "),
|
|
2430
2573
|
...lineBreaks.length > 0 ? { lineBreaks } : {}
|
|
@@ -3021,8 +3164,19 @@ var createKoeVoice = async (ctx, destination, options) => {
|
|
|
3021
3164
|
var PREWARM_NOTES = 3;
|
|
3022
3165
|
var STREAM_LOOKAHEAD_SEC = 1.5;
|
|
3023
3166
|
var STREAM_POLL_MS = 100;
|
|
3024
|
-
var
|
|
3025
|
-
var
|
|
3167
|
+
var OCTAVE_UNISON_PEAK_SCALE = 0.6;
|
|
3168
|
+
var octaveUnisonOffsets = (mode) => {
|
|
3169
|
+
switch (mode) {
|
|
3170
|
+
case "down":
|
|
3171
|
+
return [-12];
|
|
3172
|
+
case "up":
|
|
3173
|
+
return [12];
|
|
3174
|
+
case "both":
|
|
3175
|
+
return [-12, 12];
|
|
3176
|
+
default:
|
|
3177
|
+
return [];
|
|
3178
|
+
}
|
|
3179
|
+
};
|
|
3026
3180
|
var FALLBACK_MODEL = "klatt";
|
|
3027
3181
|
var createSingingVoices = (ctx, destination, options = {}) => {
|
|
3028
3182
|
const catalog = {};
|
|
@@ -3117,12 +3271,12 @@ var createSingingVoices = (ctx, destination, options = {}) => {
|
|
|
3117
3271
|
vibrato: track.vibrato,
|
|
3118
3272
|
expr
|
|
3119
3273
|
});
|
|
3120
|
-
|
|
3274
|
+
for (const offset of octaveUnisonOffsets(track.octaveUnison)) {
|
|
3121
3275
|
tasks.push({
|
|
3122
3276
|
model: m,
|
|
3123
3277
|
note,
|
|
3124
3278
|
prevVowel,
|
|
3125
|
-
pitch: note.pitch +
|
|
3279
|
+
pitch: note.pitch + offset,
|
|
3126
3280
|
vibrato: track.vibrato,
|
|
3127
3281
|
expr
|
|
3128
3282
|
});
|
|
@@ -3237,11 +3391,8 @@ var createSingingVoices = (ctx, destination, options = {}) => {
|
|
|
3237
3391
|
}
|
|
3238
3392
|
};
|
|
3239
3393
|
dispatchNote(note.pitch, 1);
|
|
3240
|
-
|
|
3241
|
-
dispatchNote(
|
|
3242
|
-
note.pitch + OCTAVE_DOUBLE_SEMITONES,
|
|
3243
|
-
OCTAVE_DOUBLE_PEAK_SCALE
|
|
3244
|
-
);
|
|
3394
|
+
for (const offset of octaveUnisonOffsets(track.octaveUnison)) {
|
|
3395
|
+
dispatchNote(note.pitch + offset, OCTAVE_UNISON_PEAK_SCALE);
|
|
3245
3396
|
}
|
|
3246
3397
|
if (!(model.renderToCache && model.scheduleCached)) {
|
|
3247
3398
|
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
@@ -3301,11 +3452,12 @@ var PITCH_MAP = {
|
|
|
3301
3452
|
a: 9,
|
|
3302
3453
|
b: 11
|
|
3303
3454
|
};
|
|
3304
|
-
var
|
|
3455
|
+
var clamp3 = (value, lo, hi) => Math.min(hi, Math.max(lo, value));
|
|
3305
3456
|
var META_DIRECTIVE = /#(inst|drum|drumfont|volume|drumvolume|reverb|reverbdecay|reverbpredelay|delay|delaydiv|fadein|fadeout|mode)=([\w-]+)/gi;
|
|
3306
3457
|
var TRACK_INST_DIRECTIVE = /#t(\d+)inst=([^#;\r\n]+)/gi;
|
|
3307
3458
|
var TRACK_COMP_DIRECTIVE = /#t(\d+)comp=(\d+)/gi;
|
|
3308
3459
|
var TRACK_WIDTH_DIRECTIVE = /#t(\d+)width=(\d+)/gi;
|
|
3460
|
+
var TRACK_REVERBSEND_DIRECTIVE = /#t(\d+)rev=(\d+)/gi;
|
|
3309
3461
|
var TRACK_EQLOW_DIRECTIVE = /#t(\d+)eqlo=(-?\d+)/gi;
|
|
3310
3462
|
var TRACK_EQMID_DIRECTIVE = /#t(\d+)eqmid=(-?\d+)/gi;
|
|
3311
3463
|
var TRACK_EQHIGH_DIRECTIVE = /#t(\d+)eqhi=(-?\d+)/gi;
|
|
@@ -3324,24 +3476,24 @@ var parseMmlMeta = (mml) => {
|
|
|
3324
3476
|
if (!Number.isNaN(dv)) meta.drumVolume = dv;
|
|
3325
3477
|
} else if (key === "reverb") {
|
|
3326
3478
|
const rv = Number.parseInt(m[2], 10);
|
|
3327
|
-
if (!Number.isNaN(rv)) meta.reverb =
|
|
3479
|
+
if (!Number.isNaN(rv)) meta.reverb = clamp3(rv, 0, 100);
|
|
3328
3480
|
} else if (key === "reverbdecay") {
|
|
3329
3481
|
const rd = Number.parseInt(m[2], 10);
|
|
3330
|
-
if (!Number.isNaN(rd)) meta.reverbDecay =
|
|
3482
|
+
if (!Number.isNaN(rd)) meta.reverbDecay = clamp3(rd, 3, 40);
|
|
3331
3483
|
} else if (key === "reverbpredelay") {
|
|
3332
3484
|
const rp = Number.parseInt(m[2], 10);
|
|
3333
|
-
if (!Number.isNaN(rp)) meta.reverbPreDelay =
|
|
3485
|
+
if (!Number.isNaN(rp)) meta.reverbPreDelay = clamp3(rp, 0, 150);
|
|
3334
3486
|
} else if (key === "delay") {
|
|
3335
3487
|
const dv = Number.parseInt(m[2], 10);
|
|
3336
|
-
if (!Number.isNaN(dv)) meta.delay =
|
|
3488
|
+
if (!Number.isNaN(dv)) meta.delay = clamp3(dv, 0, 100);
|
|
3337
3489
|
} else if (key === "delaydiv") {
|
|
3338
3490
|
if (["4", "8", "8d", "16"].includes(m[2])) meta.delayDivision = m[2];
|
|
3339
3491
|
} else if (key === "fadein") {
|
|
3340
3492
|
const fi = Number.parseInt(m[2], 10);
|
|
3341
|
-
if (!Number.isNaN(fi)) meta.fadeIn =
|
|
3493
|
+
if (!Number.isNaN(fi)) meta.fadeIn = clamp3(fi, 0, 100);
|
|
3342
3494
|
} else if (key === "fadeout") {
|
|
3343
3495
|
const fo = Number.parseInt(m[2], 10);
|
|
3344
|
-
if (!Number.isNaN(fo)) meta.fadeOut =
|
|
3496
|
+
if (!Number.isNaN(fo)) meta.fadeOut = clamp3(fo, 0, 100);
|
|
3345
3497
|
} else if (key === "mode") {
|
|
3346
3498
|
if (m[2] === "simple" || m[2] === "advanced") {
|
|
3347
3499
|
meta.mode = m[2];
|
|
@@ -3358,7 +3510,7 @@ var parseMmlMeta = (mml) => {
|
|
|
3358
3510
|
}
|
|
3359
3511
|
for (const m of mml.matchAll(TRACK_COMP_DIRECTIVE)) {
|
|
3360
3512
|
const idx = Number.parseInt(m[1], 10);
|
|
3361
|
-
const val =
|
|
3513
|
+
const val = clamp3(Number.parseInt(m[2], 10), 0, 100);
|
|
3362
3514
|
if (!Number.isNaN(idx) && !Number.isNaN(val)) {
|
|
3363
3515
|
meta.trackCompression ??= {};
|
|
3364
3516
|
meta.trackCompression[idx] = val;
|
|
@@ -3366,15 +3518,23 @@ var parseMmlMeta = (mml) => {
|
|
|
3366
3518
|
}
|
|
3367
3519
|
for (const m of mml.matchAll(TRACK_WIDTH_DIRECTIVE)) {
|
|
3368
3520
|
const idx = Number.parseInt(m[1], 10);
|
|
3369
|
-
const val =
|
|
3521
|
+
const val = clamp3(Number.parseInt(m[2], 10), 0, 200);
|
|
3370
3522
|
if (!Number.isNaN(idx) && !Number.isNaN(val)) {
|
|
3371
3523
|
meta.trackWidth ??= {};
|
|
3372
3524
|
meta.trackWidth[idx] = val;
|
|
3373
3525
|
}
|
|
3374
3526
|
}
|
|
3527
|
+
for (const m of mml.matchAll(TRACK_REVERBSEND_DIRECTIVE)) {
|
|
3528
|
+
const idx = Number.parseInt(m[1], 10);
|
|
3529
|
+
const val = clamp3(Number.parseInt(m[2], 10), 0, 100);
|
|
3530
|
+
if (!Number.isNaN(idx) && !Number.isNaN(val)) {
|
|
3531
|
+
meta.trackReverbSend ??= {};
|
|
3532
|
+
meta.trackReverbSend[idx] = val;
|
|
3533
|
+
}
|
|
3534
|
+
}
|
|
3375
3535
|
for (const m of mml.matchAll(TRACK_EQLOW_DIRECTIVE)) {
|
|
3376
3536
|
const idx = Number.parseInt(m[1], 10);
|
|
3377
|
-
const val =
|
|
3537
|
+
const val = clamp3(Number.parseInt(m[2], 10), -12, 12);
|
|
3378
3538
|
if (!Number.isNaN(idx) && !Number.isNaN(val)) {
|
|
3379
3539
|
meta.trackEqLow ??= {};
|
|
3380
3540
|
meta.trackEqLow[idx] = val;
|
|
@@ -3382,7 +3542,7 @@ var parseMmlMeta = (mml) => {
|
|
|
3382
3542
|
}
|
|
3383
3543
|
for (const m of mml.matchAll(TRACK_EQMID_DIRECTIVE)) {
|
|
3384
3544
|
const idx = Number.parseInt(m[1], 10);
|
|
3385
|
-
const val =
|
|
3545
|
+
const val = clamp3(Number.parseInt(m[2], 10), -12, 12);
|
|
3386
3546
|
if (!Number.isNaN(idx) && !Number.isNaN(val)) {
|
|
3387
3547
|
meta.trackEqMid ??= {};
|
|
3388
3548
|
meta.trackEqMid[idx] = val;
|
|
@@ -3390,7 +3550,7 @@ var parseMmlMeta = (mml) => {
|
|
|
3390
3550
|
}
|
|
3391
3551
|
for (const m of mml.matchAll(TRACK_EQHIGH_DIRECTIVE)) {
|
|
3392
3552
|
const idx = Number.parseInt(m[1], 10);
|
|
3393
|
-
const val =
|
|
3553
|
+
const val = clamp3(Number.parseInt(m[2], 10), -12, 12);
|
|
3394
3554
|
if (!Number.isNaN(idx) && !Number.isNaN(val)) {
|
|
3395
3555
|
meta.trackEqHigh ??= {};
|
|
3396
3556
|
meta.trackEqHigh[idx] = val;
|
|
@@ -3398,7 +3558,7 @@ var parseMmlMeta = (mml) => {
|
|
|
3398
3558
|
}
|
|
3399
3559
|
return meta;
|
|
3400
3560
|
};
|
|
3401
|
-
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, "");
|
|
3561
|
+
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, "");
|
|
3402
3562
|
var formatMmlMeta = (meta, space = "") => {
|
|
3403
3563
|
const parts = [];
|
|
3404
3564
|
if (meta.instrument) parts.push(`#inst=${meta.instrument}`);
|
|
@@ -3437,6 +3597,11 @@ var formatMmlMeta = (meta, space = "") => {
|
|
|
3437
3597
|
if (val !== 100) parts.push(`#t${idx}width=${val}`);
|
|
3438
3598
|
}
|
|
3439
3599
|
}
|
|
3600
|
+
if (meta.trackReverbSend) {
|
|
3601
|
+
for (const [idx, val] of Object.entries(meta.trackReverbSend)) {
|
|
3602
|
+
if (val !== 0) parts.push(`#t${idx}rev=${val}`);
|
|
3603
|
+
}
|
|
3604
|
+
}
|
|
3440
3605
|
if (meta.trackEqLow) {
|
|
3441
3606
|
for (const [idx, val] of Object.entries(meta.trackEqLow)) {
|
|
3442
3607
|
if (val !== 0) parts.push(`#t${idx}eqlo=${val}`);
|
|
@@ -3534,7 +3699,7 @@ var parseMML = (mml, options = {}) => {
|
|
|
3534
3699
|
numStr += body[j];
|
|
3535
3700
|
j++;
|
|
3536
3701
|
}
|
|
3537
|
-
const len = numStr ?
|
|
3702
|
+
const len = numStr ? clamp3(Number.parseInt(numStr, 10), 1, 64) : baseLength;
|
|
3538
3703
|
let steps = Math.round(stepsPerBar / len);
|
|
3539
3704
|
while (j < body.length && body[j] === ".") {
|
|
3540
3705
|
steps = Math.round(steps * 1.5);
|
|
@@ -3552,7 +3717,7 @@ var parseMML = (mml, options = {}) => {
|
|
|
3552
3717
|
numStr += body[j];
|
|
3553
3718
|
j++;
|
|
3554
3719
|
}
|
|
3555
|
-
octave = numStr ?
|
|
3720
|
+
octave = numStr ? clamp3(Number.parseInt(numStr, 10), 0, 8) : 4;
|
|
3556
3721
|
pushTok("octave", currentStep, 0, tokStart);
|
|
3557
3722
|
} else if (ch === ">") {
|
|
3558
3723
|
octave = Math.min(8, octave + 1);
|
|
@@ -3569,7 +3734,7 @@ var parseMML = (mml, options = {}) => {
|
|
|
3569
3734
|
numStr += body[j];
|
|
3570
3735
|
j++;
|
|
3571
3736
|
}
|
|
3572
|
-
baseLength =
|
|
3737
|
+
baseLength = clamp3(Number.parseInt(numStr, 10) || 16, 1, 64);
|
|
3573
3738
|
pushTok("length", currentStep, 0, tokStart);
|
|
3574
3739
|
} else if (ch === "r") {
|
|
3575
3740
|
j++;
|
|
@@ -3586,10 +3751,10 @@ var parseMML = (mml, options = {}) => {
|
|
|
3586
3751
|
}
|
|
3587
3752
|
if (ch === "t" && numStr) {
|
|
3588
3753
|
if (bpm === null) {
|
|
3589
|
-
bpm =
|
|
3754
|
+
bpm = clamp3(Number.parseInt(numStr, 10), 1, 255);
|
|
3590
3755
|
}
|
|
3591
3756
|
} else if (ch === "v" && numStr) {
|
|
3592
|
-
velocity =
|
|
3757
|
+
velocity = clamp3(Number.parseInt(numStr, 10), 0, 127);
|
|
3593
3758
|
trackVelocity.set(trackIndex, velocity);
|
|
3594
3759
|
}
|
|
3595
3760
|
pushTok("ctrl", currentStep, 0, tokStart);
|
|
@@ -3623,7 +3788,7 @@ var parseMML = (mml, options = {}) => {
|
|
|
3623
3788
|
numStr += body[j];
|
|
3624
3789
|
j++;
|
|
3625
3790
|
}
|
|
3626
|
-
octave = numStr ?
|
|
3791
|
+
octave = numStr ? clamp3(Number.parseInt(numStr, 10), 0, 8) : 4;
|
|
3627
3792
|
} else {
|
|
3628
3793
|
j++;
|
|
3629
3794
|
}
|
|
@@ -3685,6 +3850,38 @@ var parseMML = (mml, options = {}) => {
|
|
|
3685
3850
|
};
|
|
3686
3851
|
};
|
|
3687
3852
|
|
|
3853
|
+
// src/reverb.ts
|
|
3854
|
+
var DEFAULT_REVERB_DECAY_SEC = 2.2;
|
|
3855
|
+
var MIN_REVERB_DECAY_SEC = 0.3;
|
|
3856
|
+
var MAX_REVERB_DECAY_SEC = 4;
|
|
3857
|
+
var IMPULSE_DECAY_CURVE = 2.5;
|
|
3858
|
+
var DEFAULT_REVERB_PREDELAY_MS = 0;
|
|
3859
|
+
var MIN_REVERB_PREDELAY_MS = 0;
|
|
3860
|
+
var MAX_REVERB_PREDELAY_MS = 150;
|
|
3861
|
+
var createReverbImpulse = (ctx, decaySec = DEFAULT_REVERB_DECAY_SEC) => {
|
|
3862
|
+
const rate = ctx.sampleRate;
|
|
3863
|
+
const length = Math.max(
|
|
3864
|
+
1,
|
|
3865
|
+
Math.floor(
|
|
3866
|
+
rate * Math.max(
|
|
3867
|
+
MIN_REVERB_DECAY_SEC,
|
|
3868
|
+
Math.min(MAX_REVERB_DECAY_SEC, decaySec)
|
|
3869
|
+
)
|
|
3870
|
+
)
|
|
3871
|
+
);
|
|
3872
|
+
const impulse = ctx.createBuffer(2, length, rate);
|
|
3873
|
+
for (let ch = 0; ch < impulse.numberOfChannels; ch++) {
|
|
3874
|
+
const data = impulse.getChannelData(ch);
|
|
3875
|
+
for (let i2 = 0; i2 < length; i2++) {
|
|
3876
|
+
const envelope = (1 - i2 / length) ** IMPULSE_DECAY_CURVE;
|
|
3877
|
+
data[i2] = (Math.random() * 2 - 1) * envelope;
|
|
3878
|
+
}
|
|
3879
|
+
}
|
|
3880
|
+
return impulse;
|
|
3881
|
+
};
|
|
3882
|
+
var REVERB_MAX_WET = 0.6;
|
|
3883
|
+
var reverbAmountToGain = (amount) => Math.max(0, Math.min(100, amount)) / 100 * REVERB_MAX_WET;
|
|
3884
|
+
|
|
3688
3885
|
// src/sequencer.ts
|
|
3689
3886
|
var STEPS_PER_BEAT = 48;
|
|
3690
3887
|
var PLAN_TIME = 0.5;
|
|
@@ -6262,9 +6459,54 @@ var playPlacements = (placements, options) => {
|
|
|
6262
6459
|
});
|
|
6263
6460
|
const ownsCtx = !options.audioContext;
|
|
6264
6461
|
const ctx = options.audioContext ?? new AudioContext();
|
|
6265
|
-
const
|
|
6462
|
+
const rawDestination = options.destination ?? ctx.destination;
|
|
6266
6463
|
const useSynth = options.synth ?? !options.onPlayNote;
|
|
6267
|
-
const
|
|
6464
|
+
const finalMix = ctx.createGain();
|
|
6465
|
+
const masterGain = ctx.createGain();
|
|
6466
|
+
masterGain.connect(finalMix);
|
|
6467
|
+
const reverbPreDelay = ctx.createDelay(MAX_REVERB_PREDELAY_MS / 1e3);
|
|
6468
|
+
reverbPreDelay.delayTime.value = (options.metaReverbPreDelay ?? DEFAULT_REVERB_PREDELAY_MS) / 1e3;
|
|
6469
|
+
const reverbConvolver = ctx.createConvolver();
|
|
6470
|
+
const reverbDecaySec = (options.metaReverbDecay ?? 22) / 10 || DEFAULT_REVERB_DECAY_SEC;
|
|
6471
|
+
reverbConvolver.buffer = createReverbImpulse(ctx, reverbDecaySec);
|
|
6472
|
+
reverbConvolver.normalize = true;
|
|
6473
|
+
const reverbWetGain = ctx.createGain();
|
|
6474
|
+
reverbWetGain.gain.value = reverbAmountToGain(options.metaReverb ?? 0);
|
|
6475
|
+
reverbPreDelay.connect(reverbConvolver);
|
|
6476
|
+
reverbConvolver.connect(reverbWetGain);
|
|
6477
|
+
reverbWetGain.connect(finalMix);
|
|
6478
|
+
finalMix.connect(rawDestination);
|
|
6479
|
+
const channelStrips = /* @__PURE__ */ new Map();
|
|
6480
|
+
const getChannelStrip = (index) => {
|
|
6481
|
+
let strip = channelStrips.get(index);
|
|
6482
|
+
if (!strip) {
|
|
6483
|
+
strip = createChannelStrip(ctx, masterGain, {
|
|
6484
|
+
compression: options.trackCompression?.[index] ?? 0,
|
|
6485
|
+
width: options.trackWidth?.[index] ?? 100,
|
|
6486
|
+
eqLow: options.trackEqLow?.[index] ?? 0,
|
|
6487
|
+
eqMid: options.trackEqMid?.[index] ?? 0,
|
|
6488
|
+
eqHigh: options.trackEqHigh?.[index] ?? 0,
|
|
6489
|
+
reverbSend: options.trackReverbSend?.[index] ?? 0,
|
|
6490
|
+
reverbBus: reverbPreDelay
|
|
6491
|
+
});
|
|
6492
|
+
channelStrips.set(index, strip);
|
|
6493
|
+
}
|
|
6494
|
+
return strip;
|
|
6495
|
+
};
|
|
6496
|
+
const synths = /* @__PURE__ */ new Map();
|
|
6497
|
+
const getSynth = (index) => {
|
|
6498
|
+
let s = synths.get(index);
|
|
6499
|
+
if (!s) {
|
|
6500
|
+
s = createSynth(ctx, getChannelStrip(index).input);
|
|
6501
|
+
synths.set(index, s);
|
|
6502
|
+
}
|
|
6503
|
+
return s;
|
|
6504
|
+
};
|
|
6505
|
+
const drumSynth = useSynth ? createSynth(ctx, masterGain) : null;
|
|
6506
|
+
const trackIndexById = /* @__PURE__ */ new Map();
|
|
6507
|
+
trackIndices.forEach((idx) => {
|
|
6508
|
+
trackIndexById.set(TRACK_ID_BY_INDEX[idx] ?? `t${idx}`, idx);
|
|
6509
|
+
});
|
|
6268
6510
|
const pauseWhenHidden = options.pauseWhenHidden ?? ownsCtx;
|
|
6269
6511
|
let playing = false;
|
|
6270
6512
|
const seq = createSequencer({
|
|
@@ -6279,12 +6521,14 @@ var playPlacements = (placements, options) => {
|
|
|
6279
6521
|
getAudioTime: () => ctx.currentTime,
|
|
6280
6522
|
onPlayNote: (e) => {
|
|
6281
6523
|
options.onPlayNote?.(e);
|
|
6282
|
-
|
|
6524
|
+
if (!useSynth) return;
|
|
6525
|
+
const index = trackIndexById.get(e.trackId);
|
|
6526
|
+
(index === void 0 ? drumSynth : getSynth(index))?.playNote(e);
|
|
6283
6527
|
},
|
|
6284
6528
|
onPlayDrum: (e) => {
|
|
6285
6529
|
const velocity = e.velocity * (drumVolume / 100) * (masterVolume / 100);
|
|
6286
6530
|
options.onPlayDrum?.({ ...e, velocity });
|
|
6287
|
-
|
|
6531
|
+
drumSynth?.playDrum({ ...e, velocity });
|
|
6288
6532
|
},
|
|
6289
6533
|
onTick: (step) => {
|
|
6290
6534
|
options.onTick?.(step);
|
|
@@ -6335,6 +6579,7 @@ var playPlacements = (placements, options) => {
|
|
|
6335
6579
|
if (pauseWhenHidden && typeof document !== "undefined") {
|
|
6336
6580
|
document.removeEventListener("visibilitychange", onVisibilityChange);
|
|
6337
6581
|
}
|
|
6582
|
+
for (const strip of channelStrips.values()) strip.dispose();
|
|
6338
6583
|
if (ownsCtx) void ctx.close();
|
|
6339
6584
|
};
|
|
6340
6585
|
return {
|
|
@@ -6354,7 +6599,16 @@ var playMML = (mml, options = {}) => {
|
|
|
6354
6599
|
bpm,
|
|
6355
6600
|
metaVolume: meta.volume,
|
|
6356
6601
|
metaDrum: meta.drum,
|
|
6357
|
-
metaDrumVolume: meta.drumVolume
|
|
6602
|
+
metaDrumVolume: meta.drumVolume,
|
|
6603
|
+
metaReverb: meta.reverb,
|
|
6604
|
+
metaReverbDecay: meta.reverbDecay,
|
|
6605
|
+
metaReverbPreDelay: meta.reverbPreDelay,
|
|
6606
|
+
trackCompression: meta.trackCompression,
|
|
6607
|
+
trackWidth: meta.trackWidth,
|
|
6608
|
+
trackReverbSend: meta.trackReverbSend,
|
|
6609
|
+
trackEqLow: meta.trackEqLow,
|
|
6610
|
+
trackEqMid: meta.trackEqMid,
|
|
6611
|
+
trackEqHigh: meta.trackEqHigh
|
|
6358
6612
|
});
|
|
6359
6613
|
};
|
|
6360
6614
|
var playNote = (options) => {
|
|
@@ -7752,11 +8006,14 @@ var DAW_CSS = `
|
|
|
7752
8006
|
user-select: none;
|
|
7753
8007
|
}
|
|
7754
8008
|
.dtm-player-balloon {
|
|
7755
|
-
|
|
7756
|
-
|
|
7757
|
-
|
|
7758
|
-
|
|
7759
|
-
|
|
8009
|
+
/* 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
|
|
8010
|
+
\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
|
|
8011
|
+
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 */
|
|
8012
|
+
position: fixed;
|
|
8013
|
+
left: 0;
|
|
8014
|
+
top: 0;
|
|
8015
|
+
transform: translate(-50%, -100%);
|
|
8016
|
+
z-index: 1000;
|
|
7760
8017
|
display: none;
|
|
7761
8018
|
pointer-events: none;
|
|
7762
8019
|
font-family: var(--dtm-font);
|
|
@@ -7785,8 +8042,8 @@ var DAW_CSS = `
|
|
|
7785
8042
|
animation: dtm-balloon-fade-in 0.1s steps(2);
|
|
7786
8043
|
}
|
|
7787
8044
|
@keyframes dtm-balloon-fade-in {
|
|
7788
|
-
from { opacity: 0; transform:
|
|
7789
|
-
to { opacity: 1; transform:
|
|
8045
|
+
from { opacity: 0; transform: translate(-50%, -100%) translateY(4px); }
|
|
8046
|
+
to { opacity: 1; transform: translate(-50%, -100%) translateY(0); }
|
|
7790
8047
|
}
|
|
7791
8048
|
@keyframes dtm-emoji-jump {
|
|
7792
8049
|
0% { transform: translateY(0); }
|
|
@@ -8209,6 +8466,27 @@ var LYRIC_MODEL_LABELS = {
|
|
|
8209
8466
|
};
|
|
8210
8467
|
var activeBalloonEl = null;
|
|
8211
8468
|
var activeBalloonTimer = null;
|
|
8469
|
+
var balloonAnchors = /* @__PURE__ */ new WeakMap();
|
|
8470
|
+
var positionBalloon = (balloonEl) => {
|
|
8471
|
+
const anchor = balloonAnchors.get(balloonEl);
|
|
8472
|
+
if (!anchor) return;
|
|
8473
|
+
const rect = anchor.getBoundingClientRect();
|
|
8474
|
+
balloonEl.style.left = `${rect.left + rect.width / 2}px`;
|
|
8475
|
+
balloonEl.style.top = `${rect.top - 6}px`;
|
|
8476
|
+
};
|
|
8477
|
+
var balloonListenersBound = false;
|
|
8478
|
+
var ensureBalloonListeners = () => {
|
|
8479
|
+
if (balloonListenersBound || typeof window === "undefined") return;
|
|
8480
|
+
balloonListenersBound = true;
|
|
8481
|
+
const reposition = () => {
|
|
8482
|
+
if (activeBalloonEl) positionBalloon(activeBalloonEl);
|
|
8483
|
+
};
|
|
8484
|
+
window.addEventListener("scroll", reposition, {
|
|
8485
|
+
capture: true,
|
|
8486
|
+
passive: true
|
|
8487
|
+
});
|
|
8488
|
+
window.addEventListener("resize", reposition, { passive: true });
|
|
8489
|
+
};
|
|
8212
8490
|
var hideActiveBalloon = () => {
|
|
8213
8491
|
if (activeBalloonEl) {
|
|
8214
8492
|
activeBalloonEl.classList.remove("dtm-player-balloon--visible");
|
|
@@ -8220,6 +8498,7 @@ var hideActiveBalloon = () => {
|
|
|
8220
8498
|
}
|
|
8221
8499
|
};
|
|
8222
8500
|
var showBalloon = (balloonEl) => {
|
|
8501
|
+
positionBalloon(balloonEl);
|
|
8223
8502
|
if (activeBalloonEl === balloonEl) {
|
|
8224
8503
|
if (activeBalloonTimer) {
|
|
8225
8504
|
clearTimeout(activeBalloonTimer);
|
|
@@ -8484,6 +8763,7 @@ var mountMmlPlayer = (target, mml, options = {}) => {
|
|
|
8484
8763
|
const doc = target.ownerDocument ?? document;
|
|
8485
8764
|
const root = doc.createElement("div");
|
|
8486
8765
|
root.className = "dtm-daw dtm-player";
|
|
8766
|
+
const playerBalloons = [];
|
|
8487
8767
|
const head = doc.createElement("div");
|
|
8488
8768
|
head.className = "dtm-player-head";
|
|
8489
8769
|
const playBtn = doc.createElement("button");
|
|
@@ -8829,7 +9109,10 @@ var mountMmlPlayer = (target, mml, options = {}) => {
|
|
|
8829
9109
|
balloon.className = "dtm-player-balloon";
|
|
8830
9110
|
const modelKey = lt.model.toLowerCase();
|
|
8831
9111
|
balloon.textContent = LYRIC_MODEL_LABELS[modelKey] ?? lt.model;
|
|
8832
|
-
|
|
9112
|
+
balloonAnchors.set(balloon, em);
|
|
9113
|
+
doc.body.appendChild(balloon);
|
|
9114
|
+
playerBalloons.push(balloon);
|
|
9115
|
+
ensureBalloonListeners();
|
|
8833
9116
|
em.addEventListener("mouseenter", () => {
|
|
8834
9117
|
showBalloon(balloon);
|
|
8835
9118
|
});
|
|
@@ -9290,7 +9573,7 @@ var mountMmlPlayer = (target, mml, options = {}) => {
|
|
|
9290
9573
|
delaySend: (lt.delay ?? 0) / 100,
|
|
9291
9574
|
gender: (lt.gender ?? 50) / 100,
|
|
9292
9575
|
breathiness: (lt.breathiness ?? 50) / 100,
|
|
9293
|
-
|
|
9576
|
+
octaveUnison: lt.octaveUnison,
|
|
9294
9577
|
notes
|
|
9295
9578
|
};
|
|
9296
9579
|
});
|
|
@@ -9426,9 +9709,10 @@ var mountMmlPlayer = (target, mml, options = {}) => {
|
|
|
9426
9709
|
}
|
|
9427
9710
|
for (const t of blinkTimers) clearTimeout(t);
|
|
9428
9711
|
clearJumpTimers();
|
|
9429
|
-
if (activeBalloonEl &&
|
|
9712
|
+
if (activeBalloonEl && playerBalloons.includes(activeBalloonEl)) {
|
|
9430
9713
|
hideActiveBalloon();
|
|
9431
9714
|
}
|
|
9715
|
+
for (const balloon of playerBalloons) balloon.remove();
|
|
9432
9716
|
root.remove();
|
|
9433
9717
|
consentOverlayEl?.remove();
|
|
9434
9718
|
closeInfoModal();
|
|
@@ -9630,20 +9914,23 @@ var adjustZone = async (ctx, fontName, zone) => {
|
|
|
9630
9914
|
const newLength = attackLength + loopLengthFrame * repeatCount + releaseLength;
|
|
9631
9915
|
let totalPeak = 0;
|
|
9632
9916
|
let loopPeak = 0;
|
|
9633
|
-
|
|
9634
|
-
const
|
|
9635
|
-
for (let i2 = 0; i2 <
|
|
9636
|
-
const abs = Math.abs(
|
|
9917
|
+
for (let ch = 0; ch < oldBuf.numberOfChannels; ch++) {
|
|
9918
|
+
const chData = oldBuf.getChannelData(ch);
|
|
9919
|
+
for (let i2 = 0; i2 < chData.length; i2++) {
|
|
9920
|
+
const abs = Math.abs(chData[i2]);
|
|
9637
9921
|
if (abs > totalPeak) totalPeak = abs;
|
|
9638
9922
|
if (i2 >= loopStartFrame && i2 < loopEndFrame) {
|
|
9639
9923
|
if (abs > loopPeak) loopPeak = abs;
|
|
9640
9924
|
}
|
|
9641
9925
|
}
|
|
9642
9926
|
}
|
|
9927
|
+
const decay = isDecayInstrument(fontName);
|
|
9928
|
+
const targetRatio = decay ? 0.4 : 0.75;
|
|
9929
|
+
const maxMultiplier = decay ? 6 : 20;
|
|
9643
9930
|
let gainMultiplier = 1;
|
|
9644
|
-
if (
|
|
9645
|
-
gainMultiplier = totalPeak *
|
|
9646
|
-
if (gainMultiplier >
|
|
9931
|
+
if (loopPeak > 0 && totalPeak > 0 && loopPeak < totalPeak * 0.8) {
|
|
9932
|
+
gainMultiplier = totalPeak * targetRatio / loopPeak;
|
|
9933
|
+
if (gainMultiplier > maxMultiplier) gainMultiplier = maxMultiplier;
|
|
9647
9934
|
}
|
|
9648
9935
|
try {
|
|
9649
9936
|
const newBuf = ctx.createBuffer(
|
|
@@ -10975,14 +11262,14 @@ var DELAY_DIVISIONS = [
|
|
|
10975
11262
|
{ value: "8d", label: "\u4ED8\u70B98\u5206", beats: 0.75 },
|
|
10976
11263
|
{ value: "16", label: "16\u5206", beats: 0.25 }
|
|
10977
11264
|
];
|
|
10978
|
-
var
|
|
11265
|
+
var clamp4 = (v, lo, hi) => Math.max(lo, Math.min(hi, v));
|
|
10979
11266
|
var divisionToSeconds = (division, bpm) => {
|
|
10980
11267
|
const beats = DELAY_DIVISIONS.find((d) => d.value === division)?.beats ?? 0.5;
|
|
10981
11268
|
const safeBpm = bpm > 0 ? bpm : 120;
|
|
10982
11269
|
return 60 / safeBpm * beats;
|
|
10983
11270
|
};
|
|
10984
11271
|
var DELAY_MAX_WET = 0.45;
|
|
10985
|
-
var delayAmountToGain = (amount) =>
|
|
11272
|
+
var delayAmountToGain = (amount) => clamp4(amount, 0, 100) / 100 * DELAY_MAX_WET;
|
|
10986
11273
|
var FEEDBACK_GAIN = 0.3;
|
|
10987
11274
|
var MAX_DELAY_SEC = 2;
|
|
10988
11275
|
var createDelayBus = (ctx, destination, options = {}) => {
|
|
@@ -13057,38 +13344,6 @@ var isChordHeavyTrack = (notes, threshold = 0.6) => {
|
|
|
13057
13344
|
return chordNotes / notes.length >= threshold;
|
|
13058
13345
|
};
|
|
13059
13346
|
|
|
13060
|
-
// src/reverb.ts
|
|
13061
|
-
var DEFAULT_REVERB_DECAY_SEC = 2.2;
|
|
13062
|
-
var MIN_REVERB_DECAY_SEC = 0.3;
|
|
13063
|
-
var MAX_REVERB_DECAY_SEC = 4;
|
|
13064
|
-
var IMPULSE_DECAY_CURVE = 2.5;
|
|
13065
|
-
var DEFAULT_REVERB_PREDELAY_MS = 0;
|
|
13066
|
-
var MIN_REVERB_PREDELAY_MS = 0;
|
|
13067
|
-
var MAX_REVERB_PREDELAY_MS = 150;
|
|
13068
|
-
var createReverbImpulse = (ctx, decaySec = DEFAULT_REVERB_DECAY_SEC) => {
|
|
13069
|
-
const rate = ctx.sampleRate;
|
|
13070
|
-
const length = Math.max(
|
|
13071
|
-
1,
|
|
13072
|
-
Math.floor(
|
|
13073
|
-
rate * Math.max(
|
|
13074
|
-
MIN_REVERB_DECAY_SEC,
|
|
13075
|
-
Math.min(MAX_REVERB_DECAY_SEC, decaySec)
|
|
13076
|
-
)
|
|
13077
|
-
)
|
|
13078
|
-
);
|
|
13079
|
-
const impulse = ctx.createBuffer(2, length, rate);
|
|
13080
|
-
for (let ch = 0; ch < impulse.numberOfChannels; ch++) {
|
|
13081
|
-
const data = impulse.getChannelData(ch);
|
|
13082
|
-
for (let i2 = 0; i2 < length; i2++) {
|
|
13083
|
-
const envelope = (1 - i2 / length) ** IMPULSE_DECAY_CURVE;
|
|
13084
|
-
data[i2] = (Math.random() * 2 - 1) * envelope;
|
|
13085
|
-
}
|
|
13086
|
-
}
|
|
13087
|
-
return impulse;
|
|
13088
|
-
};
|
|
13089
|
-
var REVERB_MAX_WET = 0.6;
|
|
13090
|
-
var reverbAmountToGain = (amount) => Math.max(0, Math.min(100, amount)) / 100 * REVERB_MAX_WET;
|
|
13091
|
-
|
|
13092
13347
|
// src/daw.ts
|
|
13093
13348
|
var CHORD_INFO_HTML2 = `
|
|
13094
13349
|
<div class="dtm-modal-body-content">
|
|
@@ -13130,14 +13385,22 @@ var VIBRATO_INFO_HTML = `
|
|
|
13130
13385
|
<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>
|
|
13131
13386
|
</div>
|
|
13132
13387
|
`;
|
|
13133
|
-
var
|
|
13388
|
+
var OCTAVE_UNISON_TOKEN = {
|
|
13389
|
+
none: "",
|
|
13390
|
+
down: "w1",
|
|
13391
|
+
up: "w2",
|
|
13392
|
+
both: "w3"
|
|
13393
|
+
};
|
|
13394
|
+
var OCTAVE_UNISON_INFO_HTML = `
|
|
13134
13395
|
<div class="dtm-modal-body-content">
|
|
13135
13396
|
<h4>\u4F55\u3092\u3059\u308B\u8A2D\u5B9A\u304B</h4>
|
|
13136
|
-
<p
|
|
13397
|
+
<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>
|
|
13398
|
+
<h4>\u4E0B\u30FB\u4E0A\u30FB\u4E21\u65B9\u306E\u9055\u3044</h4>
|
|
13399
|
+
<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>
|
|
13137
13400
|
<h4>\u4F7F\u3044\u3069\u3053\u308D</h4>
|
|
13138
13401
|
<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>
|
|
13139
13402
|
<h4>\u4ED6\u306E\u8A2D\u5B9A\u3068\u306E\u517C\u306D\u5408\u3044</h4>
|
|
13140
|
-
<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\
|
|
13403
|
+
<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>
|
|
13141
13404
|
</div>
|
|
13142
13405
|
`;
|
|
13143
13406
|
var GENDER_INFO_HTML = `
|
|
@@ -13252,6 +13515,16 @@ var TRACK_WIDTH_INFO_HTML = `
|
|
|
13252
13515
|
<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>
|
|
13253
13516
|
</div>
|
|
13254
13517
|
`;
|
|
13518
|
+
var TRACK_REVERBSEND_INFO_HTML = `
|
|
13519
|
+
<div class="dtm-modal-body-content">
|
|
13520
|
+
<h4>\u4F55\u3092\u3059\u308B\u8A2D\u5B9A\u304B</h4>
|
|
13521
|
+
<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>
|
|
13522
|
+
<h4>\u300C\u58F0\u3060\u3051\u30EA\u30D0\u30FC\u30D6\u300D\u3092\u4F5C\u308B\u306B\u306F</h4>
|
|
13523
|
+
<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>
|
|
13524
|
+
<h4>[reverb]\u30D1\u30CD\u30EB\u306EMix\u3068\u306E\u95A2\u4FC2</h4>
|
|
13525
|
+
<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>
|
|
13526
|
+
</div>
|
|
13527
|
+
`;
|
|
13255
13528
|
var AUTO_MASTER_INFO_HTML = `
|
|
13256
13529
|
<div class="dtm-modal-body-content">
|
|
13257
13530
|
<h4>\u304A\u307E\u304B\u305B\u30DE\u30B9\u30BF\u30EA\u30F3\u30B0\u3068\u306F</h4>
|
|
@@ -13506,7 +13779,7 @@ var deriveCustomVocalKeyFromUrl = (url2) => {
|
|
|
13506
13779
|
if (name && /^[0-9]/.test(name)) name = `_${name}`;
|
|
13507
13780
|
return CUSTOM_VOCAL_KEY_RE.test(name) ? name : "";
|
|
13508
13781
|
};
|
|
13509
|
-
var
|
|
13782
|
+
var clamp5 = (v, min, max) => Math.min(Math.max(v, min), max);
|
|
13510
13783
|
var normalizeInstrumentName = (name) => {
|
|
13511
13784
|
if (!name) return "";
|
|
13512
13785
|
const stripped = name.replace(/\s+/g, "").toLowerCase();
|
|
@@ -13595,6 +13868,8 @@ var mountDAW = (target, options = {}) => {
|
|
|
13595
13868
|
refs.drumFontSelect.value = currentDrumFont;
|
|
13596
13869
|
let currentInstrument = "";
|
|
13597
13870
|
let activeTrackId = options.initialActiveTrack ?? trackConfigs[0].id;
|
|
13871
|
+
let trackFxAdvancedOpen = false;
|
|
13872
|
+
let lyricAdvancedOpen = false;
|
|
13598
13873
|
let activeToolMode = "pen";
|
|
13599
13874
|
let currentInsertLength = 48;
|
|
13600
13875
|
let snapGridSteps = 12;
|
|
@@ -13672,7 +13947,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
13672
13947
|
vocalDelay: t.vocalDelay,
|
|
13673
13948
|
vocalGender: t.vocalGender,
|
|
13674
13949
|
vocalBreathiness: t.vocalBreathiness,
|
|
13675
|
-
|
|
13950
|
+
vocalOctaveUnison: t.vocalOctaveUnison
|
|
13676
13951
|
};
|
|
13677
13952
|
if (lyricsDebounceTimer) clearTimeout(lyricsDebounceTimer);
|
|
13678
13953
|
lyricsDebounceTimer = setTimeout(() => {
|
|
@@ -13737,10 +14012,11 @@ var mountDAW = (target, options = {}) => {
|
|
|
13737
14012
|
vocalDelay: 0,
|
|
13738
14013
|
vocalGender: 50,
|
|
13739
14014
|
vocalBreathiness: 50,
|
|
13740
|
-
|
|
14015
|
+
vocalOctaveUnison: "none",
|
|
13741
14016
|
trackInstrument: "",
|
|
13742
14017
|
trackCompression: 0,
|
|
13743
14018
|
trackWidth: 100,
|
|
14019
|
+
trackReverbSend: 0,
|
|
13744
14020
|
trackEqLow: 0,
|
|
13745
14021
|
trackEqMid: 0,
|
|
13746
14022
|
trackEqHigh: 0
|
|
@@ -13767,7 +14043,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
13767
14043
|
delay: t.vocalDelay,
|
|
13768
14044
|
gender: t.vocalGender,
|
|
13769
14045
|
breathiness: t.vocalBreathiness,
|
|
13770
|
-
|
|
14046
|
+
octaveUnison: t.vocalOctaveUnison,
|
|
13771
14047
|
syllables
|
|
13772
14048
|
});
|
|
13773
14049
|
});
|
|
@@ -13890,7 +14166,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
13890
14166
|
const thumbW = Math.max(40, canvas.width / totalContentWidth * sbW);
|
|
13891
14167
|
const ratio = currentOffsetX / maxOffsetX;
|
|
13892
14168
|
refs.hScrollThumb.style.width = `${thumbW}px`;
|
|
13893
|
-
refs.hScrollThumb.style.left = `${
|
|
14169
|
+
refs.hScrollThumb.style.left = `${clamp5(ratio * (sbW - thumbW), 0, sbW - thumbW)}px`;
|
|
13894
14170
|
}
|
|
13895
14171
|
const totalHeight = renderConfig.keyCount * renderConfig.keyHeight;
|
|
13896
14172
|
const sbH = refs.vScroll.clientHeight;
|
|
@@ -13960,9 +14236,9 @@ var mountDAW = (target, options = {}) => {
|
|
|
13960
14236
|
if (maxOffsetX <= 0) return;
|
|
13961
14237
|
const rect = refs.hScroll.getBoundingClientRect();
|
|
13962
14238
|
const thumbW = Number.parseFloat(refs.hScrollThumb.style.width) || 40;
|
|
13963
|
-
const x2 =
|
|
14239
|
+
const x2 = clamp5(clientX - rect.left - thumbW / 2, 0, rect.width - thumbW);
|
|
13964
14240
|
const ratio = x2 / (rect.width - thumbW);
|
|
13965
|
-
currentOffsetX =
|
|
14241
|
+
currentOffsetX = clamp5(ratio * maxOffsetX, 0, maxOffsetX);
|
|
13966
14242
|
setDrawOffset(currentOffsetX, currentOffsetY);
|
|
13967
14243
|
redrawAll();
|
|
13968
14244
|
};
|
|
@@ -13971,9 +14247,9 @@ var mountDAW = (target, options = {}) => {
|
|
|
13971
14247
|
if (maxOffset <= 0) return;
|
|
13972
14248
|
const rect = refs.vScroll.getBoundingClientRect();
|
|
13973
14249
|
const thumbH = Number.parseFloat(refs.vScrollThumb.style.height) || 40;
|
|
13974
|
-
const y =
|
|
14250
|
+
const y = clamp5(clientY - rect.top - thumbH / 2, 0, rect.height - thumbH);
|
|
13975
14251
|
const ratio = y / (rect.height - thumbH);
|
|
13976
|
-
currentOffsetY =
|
|
14252
|
+
currentOffsetY = clamp5(ratio * maxOffset, 0, maxOffset);
|
|
13977
14253
|
setDrawOffset(currentOffsetX, currentOffsetY);
|
|
13978
14254
|
redrawAll();
|
|
13979
14255
|
};
|
|
@@ -14020,8 +14296,8 @@ var mountDAW = (target, options = {}) => {
|
|
|
14020
14296
|
if (dx !== 0 || dy !== 0) {
|
|
14021
14297
|
const maxOffsetX = getMaxOffsetX();
|
|
14022
14298
|
const maxOffsetY = getMaxOffsetY();
|
|
14023
|
-
currentOffsetX =
|
|
14024
|
-
currentOffsetY =
|
|
14299
|
+
currentOffsetX = clamp5(currentOffsetX + dx, 0, maxOffsetX);
|
|
14300
|
+
currentOffsetY = clamp5(currentOffsetY + dy, 0, maxOffsetY);
|
|
14025
14301
|
setDrawOffset(currentOffsetX, currentOffsetY);
|
|
14026
14302
|
onPointerMove(lastMoveEvent);
|
|
14027
14303
|
}
|
|
@@ -14411,12 +14687,12 @@ var mountDAW = (target, options = {}) => {
|
|
|
14411
14687
|
"wheel",
|
|
14412
14688
|
(event) => {
|
|
14413
14689
|
event.preventDefault();
|
|
14414
|
-
currentOffsetY =
|
|
14690
|
+
currentOffsetY = clamp5(
|
|
14415
14691
|
currentOffsetY + event.deltaY,
|
|
14416
14692
|
0,
|
|
14417
14693
|
getMaxOffsetY()
|
|
14418
14694
|
);
|
|
14419
|
-
currentOffsetX =
|
|
14695
|
+
currentOffsetX = clamp5(
|
|
14420
14696
|
currentOffsetX + event.deltaX,
|
|
14421
14697
|
0,
|
|
14422
14698
|
getMaxOffsetX()
|
|
@@ -14455,7 +14731,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
14455
14731
|
const centerStep = (currentOffsetX + canvas.width / 2) / renderConfig.stepWidth;
|
|
14456
14732
|
renderConfig.stepWidth = BASE_STEP_WIDTH * (zoomX * 2) / 100;
|
|
14457
14733
|
refs.zoomXLabel.textContent = `${zoomX}%`;
|
|
14458
|
-
currentOffsetX =
|
|
14734
|
+
currentOffsetX = clamp5(
|
|
14459
14735
|
centerStep * renderConfig.stepWidth - canvas.width / 2,
|
|
14460
14736
|
0,
|
|
14461
14737
|
getMaxOffsetX()
|
|
@@ -14468,7 +14744,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
14468
14744
|
const centerKey = (currentOffsetY + canvas.height / 2) / renderConfig.keyHeight;
|
|
14469
14745
|
renderConfig.keyHeight = BASE_KEY_HEIGHT * zoomY / 100;
|
|
14470
14746
|
refs.zoomYLabel.textContent = `${zoomY}%`;
|
|
14471
|
-
currentOffsetY =
|
|
14747
|
+
currentOffsetY = clamp5(
|
|
14472
14748
|
centerKey * renderConfig.keyHeight - canvas.height / 2,
|
|
14473
14749
|
0,
|
|
14474
14750
|
getMaxOffsetY()
|
|
@@ -14518,7 +14794,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
14518
14794
|
const threshold = currentOffsetX / renderConfig.stepWidth + visibleSteps - 4;
|
|
14519
14795
|
if (currentPlayStep > threshold) {
|
|
14520
14796
|
const visibleBars = Math.round(visibleSteps / renderConfig.stepsPerBar);
|
|
14521
|
-
currentOffsetX =
|
|
14797
|
+
currentOffsetX = clamp5(
|
|
14522
14798
|
currentOffsetX + visibleBars * renderConfig.stepsPerBar * renderConfig.stepWidth,
|
|
14523
14799
|
0,
|
|
14524
14800
|
getMaxOffsetX()
|
|
@@ -14577,7 +14853,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
14577
14853
|
delaySend: (lt.delay ?? 0) / 100,
|
|
14578
14854
|
gender: (lt.gender ?? 50) / 100,
|
|
14579
14855
|
breathiness: (lt.breathiness ?? 50) / 100,
|
|
14580
|
-
|
|
14856
|
+
octaveUnison: lt.octaveUnison,
|
|
14581
14857
|
notes
|
|
14582
14858
|
};
|
|
14583
14859
|
}) : [];
|
|
@@ -14605,7 +14881,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
14605
14881
|
}
|
|
14606
14882
|
if (playbackState !== "paused") {
|
|
14607
14883
|
const canvas = getGridCanvas();
|
|
14608
|
-
currentOffsetX =
|
|
14884
|
+
currentOffsetX = clamp5(
|
|
14609
14885
|
playStartStep * renderConfig.stepWidth - canvas.width * 0.5,
|
|
14610
14886
|
0,
|
|
14611
14887
|
getMaxOffsetX()
|
|
@@ -14709,7 +14985,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
14709
14985
|
<input type="range" class="dtm-range dtm-grow" data-dtm="track-vol" min="0" max="127" value="${active.volume}">
|
|
14710
14986
|
<span class="dtm-label" data-dtm="track-vol-label">${active.volume}</span>
|
|
14711
14987
|
</div>
|
|
14712
|
-
<details class="dtm-advanced" data-dtm="track-fx-advanced">
|
|
14988
|
+
<details class="dtm-advanced" data-dtm="track-fx-advanced" ${trackFxAdvancedOpen ? "open" : ""}>
|
|
14713
14989
|
<summary>\u8A73\u7D30\u8A2D\u5B9A\uFF08EQ\u30FB\u97F3\u5727\u30FB\u30B9\u30C6\u30EC\u30AA\u5E45\uFF09</summary>
|
|
14714
14990
|
<div class="dtm-row">
|
|
14715
14991
|
<span class="dtm-label">EQ\u4F4E\u57DF</span>
|
|
@@ -14739,7 +15015,18 @@ var mountDAW = (target, options = {}) => {
|
|
|
14739
15015
|
<span class="dtm-label" data-dtm="track-width-label"></span>
|
|
14740
15016
|
<button class="dtm-infobtn" data-dtm="track-width-info" title="\u30B9\u30C6\u30EC\u30AA\u5E45\u306E\u89E3\u8AAC">${icon("info", 12)}</button>
|
|
14741
15017
|
</div>
|
|
15018
|
+
<div class="dtm-row">
|
|
15019
|
+
<span class="dtm-label">\u30EA\u30D0\u30FC\u30D6\u9001\u308A</span>
|
|
15020
|
+
<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">
|
|
15021
|
+
<span class="dtm-label" data-dtm="track-reverb-send-label"></span>
|
|
15022
|
+
<button class="dtm-infobtn" data-dtm="track-reverb-send-info" title="\u30EA\u30D0\u30FC\u30D6\u9001\u308A\u306E\u89E3\u8AAC">${icon("info", 12)}</button>
|
|
15023
|
+
</div>
|
|
14742
15024
|
</details>`;
|
|
15025
|
+
refs.trackBody.querySelector(
|
|
15026
|
+
'[data-dtm="track-fx-advanced"]'
|
|
15027
|
+
).addEventListener("toggle", (e) => {
|
|
15028
|
+
trackFxAdvancedOpen = e.target.open;
|
|
15029
|
+
});
|
|
14743
15030
|
const volInput = refs.trackBody.querySelector(
|
|
14744
15031
|
'[data-dtm="track-vol"]'
|
|
14745
15032
|
);
|
|
@@ -14843,6 +15130,28 @@ var mountDAW = (target, options = {}) => {
|
|
|
14843
15130
|
trackWidthInfo.addEventListener("click", () => {
|
|
14844
15131
|
showModal("\u30B9\u30C6\u30EC\u30AA\u5E45\u306E\u89E3\u8AAC", TRACK_WIDTH_INFO_HTML);
|
|
14845
15132
|
});
|
|
15133
|
+
const trackReverbSendInput = refs.trackBody.querySelector(
|
|
15134
|
+
'[data-dtm="track-reverb-send"]'
|
|
15135
|
+
);
|
|
15136
|
+
const trackReverbSendLabel = refs.trackBody.querySelector(
|
|
15137
|
+
'[data-dtm="track-reverb-send-label"]'
|
|
15138
|
+
);
|
|
15139
|
+
const trackReverbSendInfo = refs.trackBody.querySelector(
|
|
15140
|
+
'[data-dtm="track-reverb-send-info"]'
|
|
15141
|
+
);
|
|
15142
|
+
trackReverbSendInput.value = String(active.trackReverbSend);
|
|
15143
|
+
trackReverbSendLabel.textContent = `${active.trackReverbSend}%`;
|
|
15144
|
+
trackReverbSendInput.addEventListener("input", () => {
|
|
15145
|
+
active.trackReverbSend = Number.parseInt(trackReverbSendInput.value, 10);
|
|
15146
|
+
trackReverbSendLabel.textContent = `${active.trackReverbSend}%`;
|
|
15147
|
+
options.onTrackReverbSendChange?.(
|
|
15148
|
+
active.config.id,
|
|
15149
|
+
active.trackReverbSend
|
|
15150
|
+
);
|
|
15151
|
+
});
|
|
15152
|
+
trackReverbSendInfo.addEventListener("click", () => {
|
|
15153
|
+
showModal("\u30EA\u30D0\u30FC\u30D6\u9001\u308A\u306E\u89E3\u8AAC", TRACK_REVERBSEND_INFO_HTML);
|
|
15154
|
+
});
|
|
14846
15155
|
const instRow = document.createElement("div");
|
|
14847
15156
|
instRow.className = "dtm-row";
|
|
14848
15157
|
instRow.innerHTML = `<span class="dtm-label">\u697D\u5668</span>`;
|
|
@@ -14931,7 +15240,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
14931
15240
|
<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">
|
|
14932
15241
|
<span class="dtm-label" data-dtm="lyric-vol-label"></span>
|
|
14933
15242
|
</div>
|
|
14934
|
-
<details class="dtm-advanced" data-dtm="lyric-advanced">
|
|
15243
|
+
<details class="dtm-advanced" data-dtm="lyric-advanced" ${lyricAdvancedOpen ? "open" : ""}>
|
|
14935
15244
|
<summary>\u8A73\u7D30\u8A2D\u5B9A</summary>
|
|
14936
15245
|
<div class="dtm-row">
|
|
14937
15246
|
<span class="dtm-label">\u30AA\u30AF\u30BF\u30FC\u30D6</span>
|
|
@@ -14979,15 +15288,24 @@ var mountDAW = (target, options = {}) => {
|
|
|
14979
15288
|
<button class="dtm-infobtn" data-dtm="lyric-vibrato-info" title="\u81EA\u52D5\u30D3\u30D6\u30E9\u30FC\u30C8\u306E\u89E3\u8AAC">${icon("info", 12)}</button>
|
|
14980
15289
|
</div>
|
|
14981
15290
|
<div class="dtm-row">
|
|
14982
|
-
<span class="dtm-label"
|
|
14983
|
-
|
|
14984
|
-
|
|
14985
|
-
|
|
15291
|
+
<span class="dtm-label">\u30AA\u30AF\u30BF\u30FC\u30D6\u30E6\u30CB\u30BE\u30F3</span>
|
|
15292
|
+
<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">
|
|
15293
|
+
<option value="none">\u306A\u3057</option>
|
|
15294
|
+
<option value="down">\u4E0B (-1oct)</option>
|
|
15295
|
+
<option value="up">\u4E0A (+1oct)</option>
|
|
15296
|
+
<option value="both">\u4E0A\u4E0B\u4E21\u65B9</option>
|
|
15297
|
+
</select>
|
|
15298
|
+
<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>
|
|
14986
15299
|
</div>
|
|
14987
15300
|
</details>
|
|
14988
15301
|
<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>
|
|
14989
15302
|
</div>`;
|
|
14990
15303
|
refs.trackBody.appendChild(lyricDiv);
|
|
15304
|
+
lyricDiv.querySelector(
|
|
15305
|
+
'[data-dtm="lyric-advanced"]'
|
|
15306
|
+
).addEventListener("toggle", (e) => {
|
|
15307
|
+
lyricAdvancedOpen = e.target.open;
|
|
15308
|
+
});
|
|
14991
15309
|
const lyricModelSel = lyricDiv.querySelector(
|
|
14992
15310
|
'[data-dtm="lyric-model"]'
|
|
14993
15311
|
);
|
|
@@ -15075,14 +15393,14 @@ var mountDAW = (target, options = {}) => {
|
|
|
15075
15393
|
lyricVibratoInfo.addEventListener("click", () => {
|
|
15076
15394
|
showModal("\u81EA\u52D5\u30D3\u30D6\u30E9\u30FC\u30C8\u89E3\u8AAC", VIBRATO_INFO_HTML);
|
|
15077
15395
|
});
|
|
15078
|
-
const
|
|
15079
|
-
'[data-dtm="lyric-octave-
|
|
15396
|
+
const lyricOctaveUnison = lyricDiv.querySelector(
|
|
15397
|
+
'[data-dtm="lyric-octave-unison"]'
|
|
15080
15398
|
);
|
|
15081
|
-
const
|
|
15082
|
-
'[data-dtm="lyric-octave-
|
|
15399
|
+
const lyricOctaveUnisonInfo = lyricDiv.querySelector(
|
|
15400
|
+
'[data-dtm="lyric-octave-unison-info"]'
|
|
15083
15401
|
);
|
|
15084
|
-
|
|
15085
|
-
showModal("\u30AA\u30AF\u30BF\u30FC\u30D6\
|
|
15402
|
+
lyricOctaveUnisonInfo.addEventListener("click", () => {
|
|
15403
|
+
showModal("\u30AA\u30AF\u30BF\u30FC\u30D6\u30E6\u30CB\u30BE\u30F3\u89E3\u8AAC", OCTAVE_UNISON_INFO_HTML);
|
|
15086
15404
|
});
|
|
15087
15405
|
const lyricTerms = lyricDiv.querySelector(
|
|
15088
15406
|
'[data-dtm="lyric-terms"]'
|
|
@@ -15154,7 +15472,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
15154
15472
|
lyricBreathiness.value = String(active.vocalBreathiness);
|
|
15155
15473
|
lyricBreathinessLabel.textContent = `${active.vocalBreathiness}`;
|
|
15156
15474
|
lyricVibrato.checked = active.vocalVibrato;
|
|
15157
|
-
|
|
15475
|
+
lyricOctaveUnison.value = active.vocalOctaveUnison;
|
|
15158
15476
|
const updateLyricCount = () => {
|
|
15159
15477
|
const n = normalizeLyrics(lyricInput.value).length;
|
|
15160
15478
|
lyricCount.textContent = active.lyricModel && n > 0 ? `${n}\u97F3\u7BC0` : "";
|
|
@@ -15276,8 +15594,8 @@ var mountDAW = (target, options = {}) => {
|
|
|
15276
15594
|
active.vocalVibrato = lyricVibrato.checked;
|
|
15277
15595
|
fireLyricsChange(active);
|
|
15278
15596
|
});
|
|
15279
|
-
|
|
15280
|
-
active.
|
|
15597
|
+
lyricOctaveUnison.addEventListener("change", () => {
|
|
15598
|
+
active.vocalOctaveUnison = lyricOctaveUnison.value;
|
|
15281
15599
|
fireLyricsChange(active);
|
|
15282
15600
|
});
|
|
15283
15601
|
lyricInput.addEventListener("input", () => {
|
|
@@ -15408,6 +15726,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
15408
15726
|
const trackInstrumentsForMeta = {};
|
|
15409
15727
|
const trackCompressionForMeta = {};
|
|
15410
15728
|
const trackWidthForMeta = {};
|
|
15729
|
+
const trackReverbSendForMeta = {};
|
|
15411
15730
|
const trackEqLowForMeta = {};
|
|
15412
15731
|
const trackEqMidForMeta = {};
|
|
15413
15732
|
const trackEqHighForMeta = {};
|
|
@@ -15416,6 +15735,8 @@ var mountDAW = (target, options = {}) => {
|
|
|
15416
15735
|
if (t.trackCompression !== 0)
|
|
15417
15736
|
trackCompressionForMeta[i2] = t.trackCompression;
|
|
15418
15737
|
if (t.trackWidth !== 100) trackWidthForMeta[i2] = t.trackWidth;
|
|
15738
|
+
if (t.trackReverbSend !== 0)
|
|
15739
|
+
trackReverbSendForMeta[i2] = t.trackReverbSend;
|
|
15419
15740
|
if (t.trackEqLow !== 0) trackEqLowForMeta[i2] = t.trackEqLow;
|
|
15420
15741
|
if (t.trackEqMid !== 0) trackEqMidForMeta[i2] = t.trackEqMid;
|
|
15421
15742
|
if (t.trackEqHigh !== 0) trackEqHighForMeta[i2] = t.trackEqHigh;
|
|
@@ -15423,6 +15744,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
15423
15744
|
const trackInstMeta = Object.keys(trackInstrumentsForMeta).length > 0 ? trackInstrumentsForMeta : void 0;
|
|
15424
15745
|
const trackCompMeta = Object.keys(trackCompressionForMeta).length > 0 ? trackCompressionForMeta : void 0;
|
|
15425
15746
|
const trackWidthMeta = Object.keys(trackWidthForMeta).length > 0 ? trackWidthForMeta : void 0;
|
|
15747
|
+
const trackReverbSendMeta = Object.keys(trackReverbSendForMeta).length > 0 ? trackReverbSendForMeta : void 0;
|
|
15426
15748
|
const trackEqLowMeta = Object.keys(trackEqLowForMeta).length > 0 ? trackEqLowForMeta : void 0;
|
|
15427
15749
|
const trackEqMidMeta = Object.keys(trackEqMidForMeta).length > 0 ? trackEqMidForMeta : void 0;
|
|
15428
15750
|
const trackEqHighMeta = Object.keys(trackEqHighForMeta).length > 0 ? trackEqHighForMeta : void 0;
|
|
@@ -15443,6 +15765,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
15443
15765
|
trackInstruments: trackInstMeta,
|
|
15444
15766
|
trackCompression: trackCompMeta,
|
|
15445
15767
|
trackWidth: trackWidthMeta,
|
|
15768
|
+
trackReverbSend: trackReverbSendMeta,
|
|
15446
15769
|
trackEqLow: trackEqLowMeta,
|
|
15447
15770
|
trackEqMid: trackEqMidMeta,
|
|
15448
15771
|
trackEqHigh: trackEqHighMeta
|
|
@@ -15466,6 +15789,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
15466
15789
|
trackInstruments: trackInstMeta,
|
|
15467
15790
|
trackCompression: trackCompMeta,
|
|
15468
15791
|
trackWidth: trackWidthMeta,
|
|
15792
|
+
trackReverbSend: trackReverbSendMeta,
|
|
15469
15793
|
trackEqLow: trackEqLowMeta,
|
|
15470
15794
|
trackEqMid: trackEqMidMeta,
|
|
15471
15795
|
trackEqHigh: trackEqHighMeta
|
|
@@ -15521,7 +15845,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
15521
15845
|
del: t.vocalDelay,
|
|
15522
15846
|
gen: t.vocalGender,
|
|
15523
15847
|
bre: t.vocalBreathiness,
|
|
15524
|
-
|
|
15848
|
+
uni: t.vocalOctaveUnison
|
|
15525
15849
|
})).filter(
|
|
15526
15850
|
(x2) => x2.model.length > 0 && x2.text.length > 0 && x2.notes.length > 0
|
|
15527
15851
|
).map((x2) => {
|
|
@@ -15535,7 +15859,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
15535
15859
|
x2.del === 0 ? "" : `e${x2.del}`,
|
|
15536
15860
|
x2.gen === 50 ? "" : `g${x2.gen}`,
|
|
15537
15861
|
x2.bre === 50 ? "" : `h${x2.bre}`,
|
|
15538
|
-
x2.
|
|
15862
|
+
OCTAVE_UNISON_TOKEN[x2.uni]
|
|
15539
15863
|
].filter((s) => s.length > 0).join(" ");
|
|
15540
15864
|
const head = params ? `${x2.model} ${params}` : x2.model;
|
|
15541
15865
|
return `@@${x2.i} ${head} ${x2.text}`;
|
|
@@ -15604,7 +15928,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
15604
15928
|
const canvas = getGridCanvas();
|
|
15605
15929
|
const yIndex = renderConfig.keyCount - 1 - (pitch - renderConfig.pitchRangeStart);
|
|
15606
15930
|
const logicalY = yIndex * renderConfig.keyHeight;
|
|
15607
|
-
currentOffsetY =
|
|
15931
|
+
currentOffsetY = clamp5(
|
|
15608
15932
|
logicalY - (canvas.height - renderConfig.keyHeight) / 2,
|
|
15609
15933
|
0,
|
|
15610
15934
|
getMaxOffsetY()
|
|
@@ -15735,6 +16059,11 @@ var mountDAW = (target, options = {}) => {
|
|
|
15735
16059
|
t.trackWidth = width;
|
|
15736
16060
|
options.onTrackWidthChange?.(t.config.id, width);
|
|
15737
16061
|
}
|
|
16062
|
+
const reverbSend = meta.trackReverbSend?.[i2] ?? 0;
|
|
16063
|
+
if (t.trackReverbSend !== reverbSend) {
|
|
16064
|
+
t.trackReverbSend = reverbSend;
|
|
16065
|
+
options.onTrackReverbSendChange?.(t.config.id, reverbSend);
|
|
16066
|
+
}
|
|
15738
16067
|
const eqLow = meta.trackEqLow?.[i2] ?? 0;
|
|
15739
16068
|
if (t.trackEqLow !== eqLow) {
|
|
15740
16069
|
t.trackEqLow = eqLow;
|
|
@@ -15772,7 +16101,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
15772
16101
|
active.vocalDelay = 0;
|
|
15773
16102
|
active.vocalGender = 50;
|
|
15774
16103
|
active.vocalBreathiness = 50;
|
|
15775
|
-
active.
|
|
16104
|
+
active.vocalOctaveUnison = "none";
|
|
15776
16105
|
} else {
|
|
15777
16106
|
for (const t of trackStates) {
|
|
15778
16107
|
t.lyrics = "";
|
|
@@ -15786,7 +16115,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
15786
16115
|
t.vocalDelay = 0;
|
|
15787
16116
|
t.vocalGender = 50;
|
|
15788
16117
|
t.vocalBreathiness = 50;
|
|
15789
|
-
t.
|
|
16118
|
+
t.vocalOctaveUnison = "none";
|
|
15790
16119
|
}
|
|
15791
16120
|
}
|
|
15792
16121
|
lyrics?.forEach((lt) => {
|
|
@@ -15804,7 +16133,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
15804
16133
|
t.vocalDelay = lt.delay ?? 0;
|
|
15805
16134
|
t.vocalGender = lt.gender ?? 50;
|
|
15806
16135
|
t.vocalBreathiness = lt.breathiness ?? 50;
|
|
15807
|
-
t.
|
|
16136
|
+
t.vocalOctaveUnison = lt.octaveUnison ?? "none";
|
|
15808
16137
|
});
|
|
15809
16138
|
for (const p of placements) {
|
|
15810
16139
|
if (applyActiveOnly && p.trackIndex !== activeTrackIndex) continue;
|
|
@@ -15888,7 +16217,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
15888
16217
|
active.vocalDelay = 0;
|
|
15889
16218
|
active.vocalGender = 50;
|
|
15890
16219
|
active.vocalBreathiness = 50;
|
|
15891
|
-
active.
|
|
16220
|
+
active.vocalOctaveUnison = "none";
|
|
15892
16221
|
} else {
|
|
15893
16222
|
clearAll();
|
|
15894
16223
|
for (const t of trackStates) t.core.setLoadMode(true);
|
|
@@ -15904,7 +16233,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
15904
16233
|
t.vocalDelay = 0;
|
|
15905
16234
|
t.vocalGender = 50;
|
|
15906
16235
|
t.vocalBreathiness = 50;
|
|
15907
|
-
t.
|
|
16236
|
+
t.vocalOctaveUnison = "none";
|
|
15908
16237
|
}
|
|
15909
16238
|
}
|
|
15910
16239
|
const { placements, bpm: parsedBpm } = isAdvanced ? extractMidiPlacementsByTrack(
|
|
@@ -16174,8 +16503,8 @@ var mountDAW = (target, options = {}) => {
|
|
|
16174
16503
|
refs.reverbAmount.value = "20";
|
|
16175
16504
|
refs.reverbAmountLabel.textContent = "20%";
|
|
16176
16505
|
options.onReverbChange?.(20);
|
|
16177
|
-
const bpmT =
|
|
16178
|
-
reverbDecay =
|
|
16506
|
+
const bpmT = clamp5((bpm - 60) / (180 - 60), 0, 1);
|
|
16507
|
+
reverbDecay = clamp5(
|
|
16179
16508
|
3 - bpmT * (3 - 0.9),
|
|
16180
16509
|
MIN_REVERB_DECAY_SEC,
|
|
16181
16510
|
MAX_REVERB_DECAY_SEC
|
|
@@ -16204,6 +16533,10 @@ var mountDAW = (target, options = {}) => {
|
|
|
16204
16533
|
t.trackWidth = 115;
|
|
16205
16534
|
options.onTrackCompressionChange?.(t.config.id, comp);
|
|
16206
16535
|
options.onTrackWidthChange?.(t.config.id, 115);
|
|
16536
|
+
if (!t.lyricModel) {
|
|
16537
|
+
t.trackReverbSend = 15;
|
|
16538
|
+
options.onTrackReverbSendChange?.(t.config.id, 15);
|
|
16539
|
+
}
|
|
16207
16540
|
if (t.lyricModel) {
|
|
16208
16541
|
t.vocalVibrato = true;
|
|
16209
16542
|
t.vocalReverb = isMainVocal ? 15 : 30;
|
|
@@ -17102,7 +17435,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
17102
17435
|
currentPlayStep = step;
|
|
17103
17436
|
playbackState = "paused";
|
|
17104
17437
|
const canvas = getGridCanvas();
|
|
17105
|
-
currentOffsetX =
|
|
17438
|
+
currentOffsetX = clamp5(
|
|
17106
17439
|
step * renderConfig.stepWidth - canvas.width * 0.5,
|
|
17107
17440
|
0,
|
|
17108
17441
|
getMaxOffsetX()
|
|
@@ -17148,11 +17481,11 @@ var mountDAW = (target, options = {}) => {
|
|
|
17148
17481
|
getViewState,
|
|
17149
17482
|
setViewState: (state) => {
|
|
17150
17483
|
if (typeof state.zoomX === "number") {
|
|
17151
|
-
zoomX =
|
|
17484
|
+
zoomX = clamp5(state.zoomX, 25, 200);
|
|
17152
17485
|
applyZoomX();
|
|
17153
17486
|
}
|
|
17154
17487
|
if (typeof state.zoomY === "number") {
|
|
17155
|
-
zoomY =
|
|
17488
|
+
zoomY = clamp5(state.zoomY, 50, 200);
|
|
17156
17489
|
applyZoomY();
|
|
17157
17490
|
}
|
|
17158
17491
|
if (typeof state.decomposeChord === "boolean") {
|
|
@@ -17174,24 +17507,24 @@ var mountDAW = (target, options = {}) => {
|
|
|
17174
17507
|
forcePauseAt,
|
|
17175
17508
|
setLoading,
|
|
17176
17509
|
setMasterVolume: (volume) => {
|
|
17177
|
-
masterVolume =
|
|
17510
|
+
masterVolume = clamp5(volume, 0, 100);
|
|
17178
17511
|
refs.masterVolume.value = String(masterVolume);
|
|
17179
17512
|
refs.masterVolumeLabel.textContent = `${masterVolume}%`;
|
|
17180
17513
|
options.singingVoices?.setVolume(masterVolume / 100);
|
|
17181
17514
|
},
|
|
17182
17515
|
setVolume: (volume) => {
|
|
17183
|
-
masterVolume =
|
|
17516
|
+
masterVolume = clamp5(volume, 0, 100);
|
|
17184
17517
|
refs.masterVolume.value = String(masterVolume);
|
|
17185
17518
|
refs.masterVolumeLabel.textContent = `${masterVolume}%`;
|
|
17186
17519
|
options.singingVoices?.setVolume(masterVolume / 100);
|
|
17187
17520
|
},
|
|
17188
17521
|
setDrumVolume: (volume) => {
|
|
17189
|
-
drumVolume =
|
|
17522
|
+
drumVolume = clamp5(volume, 0, 100);
|
|
17190
17523
|
refs.drumVolume.value = String(drumVolume);
|
|
17191
17524
|
refs.drumVolumeLabel.textContent = `${drumVolume}%`;
|
|
17192
17525
|
},
|
|
17193
17526
|
setReverbAmount: (amount) => {
|
|
17194
|
-
reverbAmount =
|
|
17527
|
+
reverbAmount = clamp5(amount, 0, 100);
|
|
17195
17528
|
refs.reverbAmount.value = String(reverbAmount);
|
|
17196
17529
|
refs.reverbAmountLabel.textContent = `${reverbAmount}%`;
|
|
17197
17530
|
options.onReverbChange?.(reverbAmount);
|
|
@@ -17215,7 +17548,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
17215
17548
|
options.onReverbPreDelayChange?.(reverbPreDelay);
|
|
17216
17549
|
},
|
|
17217
17550
|
setDelayAmount: (amount) => {
|
|
17218
|
-
delayAmount =
|
|
17551
|
+
delayAmount = clamp5(amount, 0, 100);
|
|
17219
17552
|
refs.delayAmount.value = String(delayAmount);
|
|
17220
17553
|
refs.delayAmountLabel.textContent = `${delayAmount}%`;
|
|
17221
17554
|
options.onDelayChange?.(delayAmount);
|
|
@@ -17264,7 +17597,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
17264
17597
|
t.vocalDelay = data.vocalDelay ?? 0;
|
|
17265
17598
|
t.vocalGender = data.vocalGender ?? 50;
|
|
17266
17599
|
t.vocalBreathiness = data.vocalBreathiness ?? 50;
|
|
17267
|
-
t.
|
|
17600
|
+
t.vocalOctaveUnison = data.vocalOctaveUnison ?? "none";
|
|
17268
17601
|
},
|
|
17269
17602
|
applyTrackInstrument: (trackIndex, instrumentName) => {
|
|
17270
17603
|
const t = trackStates[trackIndex];
|
|
@@ -17386,7 +17719,7 @@ var playSingingMML = async (mml, options = {}) => {
|
|
|
17386
17719
|
delaySend: (lt.delay ?? 0) / 100,
|
|
17387
17720
|
gender: (lt.gender ?? 50) / 100,
|
|
17388
17721
|
breathiness: (lt.breathiness ?? 50) / 100,
|
|
17389
|
-
|
|
17722
|
+
octaveUnison: lt.octaveUnison,
|
|
17390
17723
|
notes
|
|
17391
17724
|
};
|
|
17392
17725
|
});
|
|
@@ -17994,137 +18327,6 @@ var isSupported = midiJsonParser.isSupported;
|
|
|
17994
18327
|
var parseArrayBuffer = midiJsonParser.parseArrayBuffer;
|
|
17995
18328
|
URL.revokeObjectURL(url);
|
|
17996
18329
|
|
|
17997
|
-
// src/channel-strip.ts
|
|
17998
|
-
var clamp5 = (v, lo, hi) => Math.max(lo, Math.min(hi, v));
|
|
17999
|
-
var compressionParams = (amount) => {
|
|
18000
|
-
const t = clamp5(amount, 0, 100) / 100;
|
|
18001
|
-
return {
|
|
18002
|
-
threshold: 0 + (-24 - 0) * t,
|
|
18003
|
-
ratio: 1 + (12 - 1) * t,
|
|
18004
|
-
knee: 0 + (6 - 0) * t,
|
|
18005
|
-
attack: 0.02 + (3e-3 - 0.02) * t,
|
|
18006
|
-
release: 0.25 + (0.15 - 0.25) * t
|
|
18007
|
-
};
|
|
18008
|
-
};
|
|
18009
|
-
var EQ_LOW_FREQ = 200;
|
|
18010
|
-
var EQ_MID_FREQ = 1e3;
|
|
18011
|
-
var EQ_HIGH_FREQ = 5e3;
|
|
18012
|
-
var EQ_MID_Q = 1;
|
|
18013
|
-
var EQ_MAX_DB = 12;
|
|
18014
|
-
var createChannelStrip = (ctx, destination, options = {}) => {
|
|
18015
|
-
const input = ctx.createGain();
|
|
18016
|
-
const eqLow = ctx.createBiquadFilter();
|
|
18017
|
-
eqLow.type = "lowshelf";
|
|
18018
|
-
eqLow.frequency.value = EQ_LOW_FREQ;
|
|
18019
|
-
eqLow.gain.value = clamp5(options.eqLow ?? 0, -EQ_MAX_DB, EQ_MAX_DB);
|
|
18020
|
-
const eqMid = ctx.createBiquadFilter();
|
|
18021
|
-
eqMid.type = "peaking";
|
|
18022
|
-
eqMid.frequency.value = EQ_MID_FREQ;
|
|
18023
|
-
eqMid.Q.value = EQ_MID_Q;
|
|
18024
|
-
eqMid.gain.value = clamp5(options.eqMid ?? 0, -EQ_MAX_DB, EQ_MAX_DB);
|
|
18025
|
-
const eqHigh = ctx.createBiquadFilter();
|
|
18026
|
-
eqHigh.type = "highshelf";
|
|
18027
|
-
eqHigh.frequency.value = EQ_HIGH_FREQ;
|
|
18028
|
-
eqHigh.gain.value = clamp5(options.eqHigh ?? 0, -EQ_MAX_DB, EQ_MAX_DB);
|
|
18029
|
-
input.connect(eqLow);
|
|
18030
|
-
eqLow.connect(eqMid);
|
|
18031
|
-
eqMid.connect(eqHigh);
|
|
18032
|
-
const compressor = ctx.createDynamicsCompressor();
|
|
18033
|
-
const applyCompression = (amount) => {
|
|
18034
|
-
const p = compressionParams(amount);
|
|
18035
|
-
const now = ctx.currentTime;
|
|
18036
|
-
compressor.threshold.setValueAtTime(p.threshold, now);
|
|
18037
|
-
compressor.ratio.setValueAtTime(p.ratio, now);
|
|
18038
|
-
compressor.knee.setValueAtTime(p.knee, now);
|
|
18039
|
-
compressor.attack.setValueAtTime(p.attack, now);
|
|
18040
|
-
compressor.release.setValueAtTime(p.release, now);
|
|
18041
|
-
};
|
|
18042
|
-
applyCompression(options.compression ?? 0);
|
|
18043
|
-
const splitter = ctx.createChannelSplitter(2);
|
|
18044
|
-
const mid = ctx.createGain();
|
|
18045
|
-
mid.gain.value = 0.5;
|
|
18046
|
-
splitter.connect(mid, 0);
|
|
18047
|
-
splitter.connect(mid, 1);
|
|
18048
|
-
const sideSum = ctx.createGain();
|
|
18049
|
-
sideSum.gain.value = 1;
|
|
18050
|
-
const sideL = ctx.createGain();
|
|
18051
|
-
sideL.gain.value = 0.5;
|
|
18052
|
-
const sideR = ctx.createGain();
|
|
18053
|
-
sideR.gain.value = -0.5;
|
|
18054
|
-
splitter.connect(sideL, 0);
|
|
18055
|
-
splitter.connect(sideR, 1);
|
|
18056
|
-
sideL.connect(sideSum);
|
|
18057
|
-
sideR.connect(sideSum);
|
|
18058
|
-
const widthGain = ctx.createGain();
|
|
18059
|
-
sideSum.connect(widthGain);
|
|
18060
|
-
const widthInv = ctx.createGain();
|
|
18061
|
-
widthInv.gain.value = -1;
|
|
18062
|
-
widthGain.connect(widthInv);
|
|
18063
|
-
const outL = ctx.createGain();
|
|
18064
|
-
mid.connect(outL);
|
|
18065
|
-
widthGain.connect(outL);
|
|
18066
|
-
const outR = ctx.createGain();
|
|
18067
|
-
mid.connect(outR);
|
|
18068
|
-
widthInv.connect(outR);
|
|
18069
|
-
const merger = ctx.createChannelMerger(2);
|
|
18070
|
-
outL.connect(merger, 0, 0);
|
|
18071
|
-
outR.connect(merger, 0, 1);
|
|
18072
|
-
const setWidth = (width) => {
|
|
18073
|
-
widthGain.gain.setTargetAtTime(
|
|
18074
|
-
clamp5(width, 0, 200) / 100,
|
|
18075
|
-
ctx.currentTime,
|
|
18076
|
-
0.02
|
|
18077
|
-
);
|
|
18078
|
-
};
|
|
18079
|
-
setWidth(options.width ?? 100);
|
|
18080
|
-
eqHigh.connect(compressor);
|
|
18081
|
-
compressor.connect(splitter);
|
|
18082
|
-
merger.connect(destination);
|
|
18083
|
-
return {
|
|
18084
|
-
input,
|
|
18085
|
-
setEqLow: (db) => {
|
|
18086
|
-
eqLow.gain.setTargetAtTime(
|
|
18087
|
-
clamp5(db, -EQ_MAX_DB, EQ_MAX_DB),
|
|
18088
|
-
ctx.currentTime,
|
|
18089
|
-
0.02
|
|
18090
|
-
);
|
|
18091
|
-
},
|
|
18092
|
-
setEqMid: (db) => {
|
|
18093
|
-
eqMid.gain.setTargetAtTime(
|
|
18094
|
-
clamp5(db, -EQ_MAX_DB, EQ_MAX_DB),
|
|
18095
|
-
ctx.currentTime,
|
|
18096
|
-
0.02
|
|
18097
|
-
);
|
|
18098
|
-
},
|
|
18099
|
-
setEqHigh: (db) => {
|
|
18100
|
-
eqHigh.gain.setTargetAtTime(
|
|
18101
|
-
clamp5(db, -EQ_MAX_DB, EQ_MAX_DB),
|
|
18102
|
-
ctx.currentTime,
|
|
18103
|
-
0.02
|
|
18104
|
-
);
|
|
18105
|
-
},
|
|
18106
|
-
setCompression: applyCompression,
|
|
18107
|
-
setWidth,
|
|
18108
|
-
dispose: () => {
|
|
18109
|
-
input.disconnect();
|
|
18110
|
-
eqLow.disconnect();
|
|
18111
|
-
eqMid.disconnect();
|
|
18112
|
-
eqHigh.disconnect();
|
|
18113
|
-
compressor.disconnect();
|
|
18114
|
-
splitter.disconnect();
|
|
18115
|
-
mid.disconnect();
|
|
18116
|
-
sideSum.disconnect();
|
|
18117
|
-
sideL.disconnect();
|
|
18118
|
-
sideR.disconnect();
|
|
18119
|
-
widthGain.disconnect();
|
|
18120
|
-
widthInv.disconnect();
|
|
18121
|
-
outL.disconnect();
|
|
18122
|
-
outR.disconnect();
|
|
18123
|
-
merger.disconnect();
|
|
18124
|
-
}
|
|
18125
|
-
};
|
|
18126
|
-
};
|
|
18127
|
-
|
|
18128
18330
|
// src/clip-meter.ts
|
|
18129
18331
|
var createClipMeter = (ctx, source, options = {}) => {
|
|
18130
18332
|
const threshold = options.threshold ?? 0.98;
|
|
@@ -18343,7 +18545,6 @@ var createDtmStudio = async (options = {}) => {
|
|
|
18343
18545
|
reverbConvolver.normalize = true;
|
|
18344
18546
|
const reverbWetGain = audioCtx.createGain();
|
|
18345
18547
|
reverbWetGain.gain.value = reverbAmountToGain(options.reverbAmount ?? 0);
|
|
18346
|
-
masterGain.connect(reverbPreDelay);
|
|
18347
18548
|
reverbPreDelay.connect(reverbConvolver);
|
|
18348
18549
|
reverbConvolver.connect(reverbWetGain);
|
|
18349
18550
|
const setReverbAmount = (amount) => {
|
|
@@ -18409,7 +18610,9 @@ var createDtmStudio = async (options = {}) => {
|
|
|
18409
18610
|
const getChannelStrip = (trackId) => {
|
|
18410
18611
|
let strip = channelStrips.get(trackId);
|
|
18411
18612
|
if (!strip) {
|
|
18412
|
-
strip = createChannelStrip(audioCtx, masterGain
|
|
18613
|
+
strip = createChannelStrip(audioCtx, masterGain, {
|
|
18614
|
+
reverbBus: reverbPreDelay
|
|
18615
|
+
});
|
|
18413
18616
|
channelStrips.set(trackId, strip);
|
|
18414
18617
|
}
|
|
18415
18618
|
return strip;
|
|
@@ -18446,7 +18649,8 @@ var createDtmStudio = async (options = {}) => {
|
|
|
18446
18649
|
voicebanks,
|
|
18447
18650
|
worldlineScriptUrl: options.worldlineScriptUrl,
|
|
18448
18651
|
// ボーカルトラック個別のリバーブセンド(`r`トークン)先。マスタリバーブの
|
|
18449
|
-
// Convolver 入力へ直接センドする(
|
|
18652
|
+
// Convolver 入力へ直接センドする(PreDelayは経由しない。チャンネルストリップの
|
|
18653
|
+
// reverbSend とは別経路の、音節単位でより細かく制御できるセンド)。
|
|
18450
18654
|
reverbBus: reverbConvolver,
|
|
18451
18655
|
// ボーカルトラック個別のディレイセンド(`e`トークン)先。
|
|
18452
18656
|
delayBus: delayBus.input,
|
|
@@ -18744,6 +18948,7 @@ var createDtmStudio = async (options = {}) => {
|
|
|
18744
18948
|
onScheduleFade: scheduleFade,
|
|
18745
18949
|
onTrackCompressionChange: (trackId, amount) => getChannelStrip(trackId).setCompression(amount),
|
|
18746
18950
|
onTrackWidthChange: (trackId, width) => getChannelStrip(trackId).setWidth(width),
|
|
18951
|
+
onTrackReverbSendChange: (trackId, amount) => getChannelStrip(trackId).setReverbSend(amount),
|
|
18747
18952
|
onTrackEqLowChange: (trackId, db) => getChannelStrip(trackId).setEqLow(db),
|
|
18748
18953
|
onTrackEqMidChange: (trackId, db) => getChannelStrip(trackId).setEqMid(db),
|
|
18749
18954
|
onTrackEqHighChange: (trackId, db) => getChannelStrip(trackId).setEqHigh(db),
|