@onjmin/dtm 0.1.83 → 0.1.85
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/README.md +1 -1
- package/dist/index.d.mts +165 -5
- package/dist/index.d.ts +165 -5
- package/dist/index.js +1345 -338
- package/dist/index.mjs +1344 -338
- package/dist/voice-worker.js +185 -14
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -219,8 +219,8 @@ var Input = class _Input {
|
|
|
219
219
|
}
|
|
220
220
|
return str.length ? Number(str) : null;
|
|
221
221
|
}
|
|
222
|
-
slice(
|
|
223
|
-
return this.str.slice(this.idx, this.idx +
|
|
222
|
+
slice(i2) {
|
|
223
|
+
return this.str.slice(this.idx, this.idx + i2);
|
|
224
224
|
}
|
|
225
225
|
};
|
|
226
226
|
var Output = class {
|
|
@@ -256,8 +256,8 @@ var Matcher = class {
|
|
|
256
256
|
else this._set(key, value);
|
|
257
257
|
}
|
|
258
258
|
parse(input) {
|
|
259
|
-
for (const
|
|
260
|
-
const s = input.slice(
|
|
259
|
+
for (const i2 of this.lengths) {
|
|
260
|
+
const s = input.slice(i2);
|
|
261
261
|
if (this.map.has(s)) {
|
|
262
262
|
input.idx += s.length;
|
|
263
263
|
return this.map.get(s);
|
|
@@ -311,7 +311,7 @@ var parseFormula = (input, output = new Output(), nest = 0) => {
|
|
|
311
311
|
if (o.isChord) {
|
|
312
312
|
output.value = [...o.value].concat(v);
|
|
313
313
|
} else {
|
|
314
|
-
const a = v.sort((
|
|
314
|
+
const a = v.sort((x2, y) => x2 - y);
|
|
315
315
|
const pitch = (o.pitch + 3) % 12 - 3;
|
|
316
316
|
if (a[0] < pitch) {
|
|
317
317
|
while (a[0] < pitch) a.push(a.shift() + 12);
|
|
@@ -348,16 +348,16 @@ halfMatcher.set("+", 1);
|
|
|
348
348
|
halfMatcher.set("-", -1);
|
|
349
349
|
var parseHalf = (input, isPitch = false) => (isPitch ? halfMatcherStrict : halfMatcher).parse(input);
|
|
350
350
|
var idx2pitch = [0, 2, 4, 5, 7, 9, 11];
|
|
351
|
-
for (const
|
|
351
|
+
for (const i2 of [...idx2pitch.keys()]) idx2pitch.push(idx2pitch[i2] + 12);
|
|
352
352
|
var deg2pitch = (deg) => idx2pitch[deg - 1];
|
|
353
353
|
var pitchMatcher = new Matcher();
|
|
354
|
-
for (const [
|
|
355
|
-
pitchMatcher.set(v, idx2pitch[
|
|
354
|
+
for (const [i2, v] of [..."CDEFGAB"].entries())
|
|
355
|
+
pitchMatcher.set(v, idx2pitch[i2]);
|
|
356
356
|
var parsePitch = (input, output) => {
|
|
357
357
|
const pitch = pitchMatcher.parse(input);
|
|
358
358
|
if (pitch === null) err(input, "Not found pitch");
|
|
359
359
|
output.pitch = pitch;
|
|
360
|
-
for (let
|
|
360
|
+
for (let i2 = 0; i2 < 2; i2++) {
|
|
361
361
|
const half = parseHalf(input, true);
|
|
362
362
|
if (half === null) break;
|
|
363
363
|
output.pitch += half;
|
|
@@ -563,11 +563,11 @@ var pearson = (a, b) => {
|
|
|
563
563
|
let num = 0;
|
|
564
564
|
let da = 0;
|
|
565
565
|
let db = 0;
|
|
566
|
-
for (let
|
|
567
|
-
const
|
|
568
|
-
const y = b[
|
|
569
|
-
num +=
|
|
570
|
-
da +=
|
|
566
|
+
for (let i2 = 0; i2 < a.length; i2++) {
|
|
567
|
+
const x2 = a[i2] - ma;
|
|
568
|
+
const y = b[i2] - mb;
|
|
569
|
+
num += x2 * y;
|
|
570
|
+
da += x2 * x2;
|
|
571
571
|
db += y * y;
|
|
572
572
|
}
|
|
573
573
|
const den = Math.sqrt(da * db);
|
|
@@ -643,19 +643,19 @@ var coalesce = (segments) => {
|
|
|
643
643
|
var mergeShortSegments = (segments, min) => {
|
|
644
644
|
if (min <= 0) return segments;
|
|
645
645
|
const result = segments.map((s) => ({ ...s }));
|
|
646
|
-
let
|
|
647
|
-
while (
|
|
648
|
-
if (result[
|
|
649
|
-
|
|
646
|
+
let i2 = 0;
|
|
647
|
+
while (i2 < result.length && result.length > 1) {
|
|
648
|
+
if (result[i2].duration >= min) {
|
|
649
|
+
i2++;
|
|
650
650
|
continue;
|
|
651
651
|
}
|
|
652
|
-
if (
|
|
653
|
-
result[
|
|
654
|
-
result.splice(
|
|
652
|
+
if (i2 > 0) {
|
|
653
|
+
result[i2 - 1].duration += result[i2].duration;
|
|
654
|
+
result.splice(i2, 1);
|
|
655
655
|
} else {
|
|
656
|
-
result[
|
|
657
|
-
result[
|
|
658
|
-
result.splice(
|
|
656
|
+
result[i2 + 1].when = result[i2].when;
|
|
657
|
+
result[i2 + 1].duration += result[i2].duration;
|
|
658
|
+
result.splice(i2, 1);
|
|
659
659
|
}
|
|
660
660
|
}
|
|
661
661
|
return coalesce(result);
|
|
@@ -874,19 +874,19 @@ var viterbi = (emissions, changePenalty) => {
|
|
|
874
874
|
const curr = new Array(N).fill(0);
|
|
875
875
|
const em = emissions[t];
|
|
876
876
|
const switchVal = bestPrevVal - changePenalty;
|
|
877
|
-
for (let
|
|
878
|
-
if (prev[
|
|
879
|
-
curr[
|
|
880
|
-
back[t][
|
|
877
|
+
for (let i2 = 0; i2 < N; i2++) {
|
|
878
|
+
if (prev[i2] >= switchVal) {
|
|
879
|
+
curr[i2] = em[i2] + prev[i2];
|
|
880
|
+
back[t][i2] = i2;
|
|
881
881
|
} else {
|
|
882
|
-
curr[
|
|
883
|
-
back[t][
|
|
882
|
+
curr[i2] = em[i2] + switchVal;
|
|
883
|
+
back[t][i2] = bestPrevIdx;
|
|
884
884
|
}
|
|
885
885
|
}
|
|
886
886
|
prev = curr;
|
|
887
887
|
}
|
|
888
888
|
let bestIdx = 0;
|
|
889
|
-
for (let
|
|
889
|
+
for (let i2 = 1; i2 < N; i2++) if (prev[i2] > prev[bestIdx]) bestIdx = i2;
|
|
890
890
|
const path = new Array(T).fill(0);
|
|
891
891
|
path[T - 1] = bestIdx;
|
|
892
892
|
for (let t = T - 1; t > 0; t--) path[t - 1] = back[t][path[t]];
|
|
@@ -983,20 +983,20 @@ var parseChords = (str, bpm = 120) => {
|
|
|
983
983
|
if (!str2.length) continue;
|
|
984
984
|
const when = idx++ * secBar;
|
|
985
985
|
const a = [];
|
|
986
|
-
for (let
|
|
987
|
-
const char = str2[
|
|
988
|
-
const prev = str2[
|
|
989
|
-
const prev2 = str2.slice(
|
|
986
|
+
for (let i2 = 0; i2 < str2.length; i2++) {
|
|
987
|
+
const char = str2[i2];
|
|
988
|
+
const prev = str2[i2 - 1];
|
|
989
|
+
const prev2 = str2.slice(i2 - 2, i2);
|
|
990
990
|
if (!frontChars.has(char)) continue;
|
|
991
991
|
if (prev === "/" || prev2 === "on") continue;
|
|
992
992
|
if (prev2 === "N." && char === "C") continue;
|
|
993
|
-
a.push(
|
|
993
|
+
a.push(i2);
|
|
994
994
|
}
|
|
995
995
|
if (!a.length) continue;
|
|
996
996
|
const divide = 2 ** Math.ceil(Math.log2(a.length));
|
|
997
997
|
const unitTime = secBar / divide;
|
|
998
|
-
for (const [
|
|
999
|
-
const s = str2.slice(v,
|
|
998
|
+
for (const [i2, v] of a.entries()) {
|
|
999
|
+
const s = str2.slice(v, i2 === a.length - 1 ? str2.length : a[i2 + 1]).replace(/\s+/g, "");
|
|
1000
1000
|
const c = s[0];
|
|
1001
1001
|
if (c === "_" || c === "N") {
|
|
1002
1002
|
last = null;
|
|
@@ -1006,7 +1006,7 @@ var parseChords = (str, bpm = 120) => {
|
|
|
1006
1006
|
if (last) last.duration += unitTime;
|
|
1007
1007
|
continue;
|
|
1008
1008
|
}
|
|
1009
|
-
const _when = when +
|
|
1009
|
+
const _when = when + i2 * unitTime;
|
|
1010
1010
|
if (c === "%") {
|
|
1011
1011
|
if (last === null) continue;
|
|
1012
1012
|
const base = last;
|
|
@@ -1171,19 +1171,19 @@ var resolveDrumPattern = (name, dict, currentBar) => {
|
|
|
1171
1171
|
if (Array.isArray(patternObj) && patternObj.length > 0 && "ranges" in patternObj[0]) {
|
|
1172
1172
|
const songDef = patternObj;
|
|
1173
1173
|
const instructions = songDef.filter(
|
|
1174
|
-
(
|
|
1174
|
+
(i2) => i2.ranges.some(([s, e]) => currentBar >= s && currentBar <= e)
|
|
1175
1175
|
);
|
|
1176
1176
|
if (instructions.length > 0) {
|
|
1177
|
-
return instructions.flatMap((
|
|
1178
|
-
const maxStep = Math.max(...
|
|
1179
|
-
const loopLengthBars =
|
|
1180
|
-
const range =
|
|
1177
|
+
return instructions.flatMap((i2) => {
|
|
1178
|
+
const maxStep = Math.max(...i2.pattern.map((p) => p.step), 0);
|
|
1179
|
+
const loopLengthBars = i2.patternBars ?? Math.max(1, Math.ceil((maxStep + 1) / 192));
|
|
1180
|
+
const range = i2.ranges.find(
|
|
1181
1181
|
([s, e]) => currentBar >= s && currentBar <= e
|
|
1182
1182
|
);
|
|
1183
1183
|
const startBar = range ? range[0] : 1;
|
|
1184
1184
|
const barInLoop = (currentBar - startBar) % loopLengthBars;
|
|
1185
1185
|
const stepOffset = barInLoop * 192;
|
|
1186
|
-
return
|
|
1186
|
+
return i2.pattern.filter((p) => p.step >= stepOffset && p.step < stepOffset + 192).map((p) => ({ ...p, step: p.step - stepOffset }));
|
|
1187
1187
|
});
|
|
1188
1188
|
}
|
|
1189
1189
|
}
|
|
@@ -1326,8 +1326,8 @@ var getDrumPatternKeys = (name, dict) => {
|
|
|
1326
1326
|
const keys = /* @__PURE__ */ new Set();
|
|
1327
1327
|
if (Array.isArray(patternObj) && patternObj.length > 0 && "ranges" in patternObj[0]) {
|
|
1328
1328
|
const songDef = patternObj;
|
|
1329
|
-
for (const
|
|
1330
|
-
for (const p of
|
|
1329
|
+
for (const i2 of songDef) {
|
|
1330
|
+
for (const p of i2.pattern) keys.add(p.pitch);
|
|
1331
1331
|
}
|
|
1332
1332
|
} else if (Array.isArray(patternObj)) {
|
|
1333
1333
|
for (const p of patternObj) keys.add(p.pitch);
|
|
@@ -1384,21 +1384,21 @@ var buildChordPlacements = (options) => {
|
|
|
1384
1384
|
}
|
|
1385
1385
|
} else if (patternType === "arpeggio") {
|
|
1386
1386
|
const arpInterval = Math.floor(noteLength / notes.length);
|
|
1387
|
-
notes.forEach((noteOffset,
|
|
1387
|
+
notes.forEach((noteOffset, i2) => {
|
|
1388
1388
|
placements.push({
|
|
1389
|
-
startStep: chord.whenStep +
|
|
1389
|
+
startStep: chord.whenStep + i2 * arpInterval,
|
|
1390
1390
|
pitch: C3 + noteOffset + offset,
|
|
1391
|
-
durationSteps: noteLength -
|
|
1391
|
+
durationSteps: noteLength - i2 * arpInterval,
|
|
1392
1392
|
velocity: 100
|
|
1393
1393
|
});
|
|
1394
1394
|
});
|
|
1395
1395
|
} else if (patternType === "arpeggio-fast") {
|
|
1396
1396
|
const arpInterval = 6;
|
|
1397
|
-
notes.forEach((noteOffset,
|
|
1397
|
+
notes.forEach((noteOffset, i2) => {
|
|
1398
1398
|
placements.push({
|
|
1399
|
-
startStep: chord.whenStep +
|
|
1399
|
+
startStep: chord.whenStep + i2 * arpInterval,
|
|
1400
1400
|
pitch: C3 + noteOffset + offset,
|
|
1401
|
-
durationSteps: Math.max(12, noteLength -
|
|
1401
|
+
durationSteps: Math.max(12, noteLength - i2 * arpInterval),
|
|
1402
1402
|
velocity: 100
|
|
1403
1403
|
});
|
|
1404
1404
|
});
|
|
@@ -1438,8 +1438,8 @@ var buildChordPlacements = (options) => {
|
|
|
1438
1438
|
}
|
|
1439
1439
|
}
|
|
1440
1440
|
} else if (patternType === "alternating") {
|
|
1441
|
-
notes.forEach((noteOffset,
|
|
1442
|
-
const stepOffset =
|
|
1441
|
+
notes.forEach((noteOffset, i2) => {
|
|
1442
|
+
const stepOffset = i2 * Math.floor(stepsPerBar / 4);
|
|
1443
1443
|
placements.push({
|
|
1444
1444
|
startStep: chord.whenStep + stepOffset,
|
|
1445
1445
|
pitch: C3 + noteOffset + offset,
|
|
@@ -1461,8 +1461,8 @@ var buildChordPlacements = (options) => {
|
|
|
1461
1461
|
}
|
|
1462
1462
|
if (notes.length === 0) return;
|
|
1463
1463
|
const startStep = barIndex * chordLength;
|
|
1464
|
-
notes.forEach((noteOffset,
|
|
1465
|
-
const stepOffset =
|
|
1464
|
+
notes.forEach((noteOffset, i2) => {
|
|
1465
|
+
const stepOffset = i2 * 3;
|
|
1466
1466
|
placements.push({
|
|
1467
1467
|
startStep: startStep + stepOffset,
|
|
1468
1468
|
pitch: C3 + noteOffset + offset,
|
|
@@ -1475,7 +1475,136 @@ var buildChordPlacements = (options) => {
|
|
|
1475
1475
|
return placements;
|
|
1476
1476
|
};
|
|
1477
1477
|
|
|
1478
|
-
// node_modules/.pnpm/@onjmin+koe@1.0.
|
|
1478
|
+
// node_modules/.pnpm/@onjmin+koe@1.0.5/node_modules/@onjmin/koe/dist/index.js
|
|
1479
|
+
var u8 = Uint8Array;
|
|
1480
|
+
var u16 = Uint16Array;
|
|
1481
|
+
var i32 = Int32Array;
|
|
1482
|
+
var fleb = new u8([
|
|
1483
|
+
0,
|
|
1484
|
+
0,
|
|
1485
|
+
0,
|
|
1486
|
+
0,
|
|
1487
|
+
0,
|
|
1488
|
+
0,
|
|
1489
|
+
0,
|
|
1490
|
+
0,
|
|
1491
|
+
1,
|
|
1492
|
+
1,
|
|
1493
|
+
1,
|
|
1494
|
+
1,
|
|
1495
|
+
2,
|
|
1496
|
+
2,
|
|
1497
|
+
2,
|
|
1498
|
+
2,
|
|
1499
|
+
3,
|
|
1500
|
+
3,
|
|
1501
|
+
3,
|
|
1502
|
+
3,
|
|
1503
|
+
4,
|
|
1504
|
+
4,
|
|
1505
|
+
4,
|
|
1506
|
+
4,
|
|
1507
|
+
5,
|
|
1508
|
+
5,
|
|
1509
|
+
5,
|
|
1510
|
+
5,
|
|
1511
|
+
0,
|
|
1512
|
+
/* unused */
|
|
1513
|
+
0,
|
|
1514
|
+
0,
|
|
1515
|
+
/* impossible */
|
|
1516
|
+
0
|
|
1517
|
+
]);
|
|
1518
|
+
var fdeb = new u8([
|
|
1519
|
+
0,
|
|
1520
|
+
0,
|
|
1521
|
+
0,
|
|
1522
|
+
0,
|
|
1523
|
+
1,
|
|
1524
|
+
1,
|
|
1525
|
+
2,
|
|
1526
|
+
2,
|
|
1527
|
+
3,
|
|
1528
|
+
3,
|
|
1529
|
+
4,
|
|
1530
|
+
4,
|
|
1531
|
+
5,
|
|
1532
|
+
5,
|
|
1533
|
+
6,
|
|
1534
|
+
6,
|
|
1535
|
+
7,
|
|
1536
|
+
7,
|
|
1537
|
+
8,
|
|
1538
|
+
8,
|
|
1539
|
+
9,
|
|
1540
|
+
9,
|
|
1541
|
+
10,
|
|
1542
|
+
10,
|
|
1543
|
+
11,
|
|
1544
|
+
11,
|
|
1545
|
+
12,
|
|
1546
|
+
12,
|
|
1547
|
+
13,
|
|
1548
|
+
13,
|
|
1549
|
+
/* unused */
|
|
1550
|
+
0,
|
|
1551
|
+
0
|
|
1552
|
+
]);
|
|
1553
|
+
var clim = new u8([16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]);
|
|
1554
|
+
var freb = function(eb, start) {
|
|
1555
|
+
var b = new u16(31);
|
|
1556
|
+
for (var i2 = 0; i2 < 31; ++i2) {
|
|
1557
|
+
b[i2] = start += 1 << eb[i2 - 1];
|
|
1558
|
+
}
|
|
1559
|
+
var r = new i32(b[30]);
|
|
1560
|
+
for (var i2 = 1; i2 < 30; ++i2) {
|
|
1561
|
+
for (var j = b[i2]; j < b[i2 + 1]; ++j) {
|
|
1562
|
+
r[j] = j - b[i2] << 5 | i2;
|
|
1563
|
+
}
|
|
1564
|
+
}
|
|
1565
|
+
return { b, r };
|
|
1566
|
+
};
|
|
1567
|
+
var _a = freb(fleb, 2);
|
|
1568
|
+
var fl = _a.b;
|
|
1569
|
+
var revfl = _a.r;
|
|
1570
|
+
fl[28] = 258, revfl[258] = 28;
|
|
1571
|
+
var _b = freb(fdeb, 0);
|
|
1572
|
+
var fd = _b.b;
|
|
1573
|
+
var revfd = _b.r;
|
|
1574
|
+
var rev = new u16(32768);
|
|
1575
|
+
for (i = 0; i < 32768; ++i) {
|
|
1576
|
+
x = (i & 43690) >> 1 | (i & 21845) << 1;
|
|
1577
|
+
x = (x & 52428) >> 2 | (x & 13107) << 2;
|
|
1578
|
+
x = (x & 61680) >> 4 | (x & 3855) << 4;
|
|
1579
|
+
rev[i] = ((x & 65280) >> 8 | (x & 255) << 8) >> 1;
|
|
1580
|
+
}
|
|
1581
|
+
var x;
|
|
1582
|
+
var i;
|
|
1583
|
+
var flt = new u8(288);
|
|
1584
|
+
for (i = 0; i < 144; ++i)
|
|
1585
|
+
flt[i] = 8;
|
|
1586
|
+
var i;
|
|
1587
|
+
for (i = 144; i < 256; ++i)
|
|
1588
|
+
flt[i] = 9;
|
|
1589
|
+
var i;
|
|
1590
|
+
for (i = 256; i < 280; ++i)
|
|
1591
|
+
flt[i] = 7;
|
|
1592
|
+
var i;
|
|
1593
|
+
for (i = 280; i < 288; ++i)
|
|
1594
|
+
flt[i] = 8;
|
|
1595
|
+
var i;
|
|
1596
|
+
var fdt = new u8(32);
|
|
1597
|
+
for (i = 0; i < 32; ++i)
|
|
1598
|
+
fdt[i] = 5;
|
|
1599
|
+
var i;
|
|
1600
|
+
var et = /* @__PURE__ */ new u8(0);
|
|
1601
|
+
var td = typeof TextDecoder != "undefined" && /* @__PURE__ */ new TextDecoder();
|
|
1602
|
+
var tds = 0;
|
|
1603
|
+
try {
|
|
1604
|
+
td.decode(et, { stream: true });
|
|
1605
|
+
tds = 1;
|
|
1606
|
+
} catch (e) {
|
|
1607
|
+
}
|
|
1479
1608
|
var MAGIC = 1263486208;
|
|
1480
1609
|
function parseKoeHeader(headerBytes) {
|
|
1481
1610
|
const view = new DataView(headerBytes);
|
|
@@ -1641,7 +1770,7 @@ var VoiceBank = class _VoiceBank {
|
|
|
1641
1770
|
if (!buf) return null;
|
|
1642
1771
|
const int16 = new Int16Array(buf, 0, Math.floor(buf.byteLength / 2));
|
|
1643
1772
|
const f64 = new Float64Array(int16.length);
|
|
1644
|
-
for (let
|
|
1773
|
+
for (let i2 = 0; i2 < int16.length; i2++) f64[i2] = int16[i2] / 32768;
|
|
1645
1774
|
return f64;
|
|
1646
1775
|
}
|
|
1647
1776
|
};
|
|
@@ -1649,6 +1778,7 @@ var WORLDLINE_SAMPLE_RATE = 48e3;
|
|
|
1649
1778
|
var MIN_WORLDLINE_SAMPLES = 4096;
|
|
1650
1779
|
var SYNTH_REQ_SIZE = 120;
|
|
1651
1780
|
var WL_FRAME_MS = 10;
|
|
1781
|
+
var sampleCurve = (input, curve, totalMs) => typeof curve === "function" ? curve(input, totalMs) : curve;
|
|
1652
1782
|
var samplesToMs = (samples) => samples / WORLDLINE_SAMPLE_RATE * 1e3;
|
|
1653
1783
|
function leadInFromEntry(entry) {
|
|
1654
1784
|
return {
|
|
@@ -1734,11 +1864,23 @@ var Worldline = class _Worldline {
|
|
|
1734
1864
|
* {@link MIN_WORLDLINE_SAMPLES} (too short for stable F0 analysis).
|
|
1735
1865
|
*/
|
|
1736
1866
|
renderNote(params) {
|
|
1737
|
-
const {
|
|
1867
|
+
const {
|
|
1868
|
+
pcm,
|
|
1869
|
+
pitch,
|
|
1870
|
+
durationMs,
|
|
1871
|
+
preMs,
|
|
1872
|
+
consonantMs,
|
|
1873
|
+
tempo = 120,
|
|
1874
|
+
gender = 0.5,
|
|
1875
|
+
tension = 0.5,
|
|
1876
|
+
breathiness = 0.5,
|
|
1877
|
+
voicing = 1
|
|
1878
|
+
} = params;
|
|
1738
1879
|
if (!pcm || pcm.length < MIN_WORLDLINE_SAMPLES) return null;
|
|
1739
1880
|
const WL = this.wasm;
|
|
1740
1881
|
const FS = WORLDLINE_SAMPLE_RATE;
|
|
1741
|
-
const
|
|
1882
|
+
const basePitch = sampleCurve(preMs + durationMs / 2, pitch, preMs + durationMs);
|
|
1883
|
+
const midiNote = Math.round(69 + 12 * Math.log2(basePitch / 440));
|
|
1742
1884
|
const posMs = 0;
|
|
1743
1885
|
const reqLen = preMs + durationMs;
|
|
1744
1886
|
const cutMs = WL_FRAME_MS * 2;
|
|
@@ -1784,11 +1926,19 @@ var Worldline = class _Worldline {
|
|
|
1784
1926
|
WL._free(reqPtr);
|
|
1785
1927
|
const totalMs = posMs + reqLen + WL_FRAME_MS * 2;
|
|
1786
1928
|
const nFrames = Math.ceil(totalMs / WL_FRAME_MS) + 4;
|
|
1787
|
-
const f0Arr = new Float64Array(nFrames)
|
|
1788
|
-
const gArr = new Float64Array(nFrames)
|
|
1789
|
-
const tArr = new Float64Array(nFrames)
|
|
1790
|
-
const bArr = new Float64Array(nFrames)
|
|
1791
|
-
const vArr = new Float64Array(nFrames)
|
|
1929
|
+
const f0Arr = new Float64Array(nFrames);
|
|
1930
|
+
const gArr = new Float64Array(nFrames);
|
|
1931
|
+
const tArr = new Float64Array(nFrames);
|
|
1932
|
+
const bArr = new Float64Array(nFrames);
|
|
1933
|
+
const vArr = new Float64Array(nFrames);
|
|
1934
|
+
for (let i2 = 0; i2 < nFrames; i2++) {
|
|
1935
|
+
const tMs = i2 * WL_FRAME_MS;
|
|
1936
|
+
f0Arr[i2] = sampleCurve(tMs, pitch, totalMs);
|
|
1937
|
+
gArr[i2] = sampleCurve(tMs, gender, totalMs);
|
|
1938
|
+
tArr[i2] = sampleCurve(tMs, tension, totalMs);
|
|
1939
|
+
bArr[i2] = sampleCurve(tMs, breathiness, totalMs);
|
|
1940
|
+
vArr[i2] = sampleCurve(tMs, voicing, totalMs);
|
|
1941
|
+
}
|
|
1792
1942
|
const f0Ptr = WL._malloc(nFrames * 8);
|
|
1793
1943
|
const gPtr = WL._malloc(nFrames * 8);
|
|
1794
1944
|
const tPtr = WL._malloc(nFrames * 8);
|
|
@@ -1848,6 +1998,19 @@ var DEFAULT_PLAYBACK_VELOCITY = 127;
|
|
|
1848
1998
|
var DEFAULT_STEPS_PER_BAR = 192;
|
|
1849
1999
|
var MML_END_MARKER = "#end;";
|
|
1850
2000
|
|
|
2001
|
+
// src/vibrato.ts
|
|
2002
|
+
var VIBRATO_MIN_SEC = 0.35;
|
|
2003
|
+
var VIBRATO_RATE_HZ = 5.5;
|
|
2004
|
+
var VIBRATO_DEPTH_CENTS = 35;
|
|
2005
|
+
var VIBRATO_FADE_MS = 150;
|
|
2006
|
+
var vibratoPitchCurve = (baseHz, preMs) => (tMs) => {
|
|
2007
|
+
const sinceOnset = tMs - preMs;
|
|
2008
|
+
if (sinceOnset <= 0) return baseHz;
|
|
2009
|
+
const depth = VIBRATO_DEPTH_CENTS * Math.min(1, sinceOnset / VIBRATO_FADE_MS);
|
|
2010
|
+
const cents = depth * Math.sin(2 * Math.PI * VIBRATO_RATE_HZ * sinceOnset / 1e3);
|
|
2011
|
+
return baseHz * 2 ** (cents / 1200);
|
|
2012
|
+
};
|
|
2013
|
+
|
|
1851
2014
|
// src/lyrics.ts
|
|
1852
2015
|
var kanaTable = {
|
|
1853
2016
|
\u3042: ["", "a"],
|
|
@@ -2012,8 +2175,8 @@ var vocalVolumeToGain = (v) => {
|
|
|
2012
2175
|
var parseLyrics = (mml) => {
|
|
2013
2176
|
const tracks = /* @__PURE__ */ new Map();
|
|
2014
2177
|
const segments = splitSegments(mml);
|
|
2015
|
-
for (let
|
|
2016
|
-
const m = segments[
|
|
2178
|
+
for (let i2 = 0; i2 < segments.length; i2++) {
|
|
2179
|
+
const m = segments[i2].match(LYRIC_LINE);
|
|
2017
2180
|
if (!m) continue;
|
|
2018
2181
|
const trackId = Number.parseInt(m[1], 10);
|
|
2019
2182
|
let rest = m[2].trim();
|
|
@@ -2021,8 +2184,12 @@ var parseLyrics = (mml) => {
|
|
|
2021
2184
|
let gate = 100;
|
|
2022
2185
|
let pan = 64;
|
|
2023
2186
|
let octave = 0;
|
|
2187
|
+
let vibrato = false;
|
|
2188
|
+
let reverb = 0;
|
|
2189
|
+
let gender = 50;
|
|
2190
|
+
let breathiness = 50;
|
|
2024
2191
|
const modelMatch = rest.match(
|
|
2025
|
-
/^([a-z_][a-z0-9_]*?)(?=(?:[
|
|
2192
|
+
/^([a-z_][a-z0-9_]*?)(?=(?:[vqpobrgh]-?\d)|[^a-z0-9_]|$)(?::(\d+))?/i
|
|
2026
2193
|
);
|
|
2027
2194
|
let model = "";
|
|
2028
2195
|
const metaTokens = [];
|
|
@@ -2063,11 +2230,39 @@ var parseLyrics = (mml) => {
|
|
|
2063
2230
|
rest = rest.substring(oMatch[0].length).trim();
|
|
2064
2231
|
continue;
|
|
2065
2232
|
}
|
|
2233
|
+
const bMatch = rest.match(/^b([01])/i);
|
|
2234
|
+
if (bMatch) {
|
|
2235
|
+
vibrato = bMatch[1] === "1";
|
|
2236
|
+
metaTokens.push(bMatch[0]);
|
|
2237
|
+
rest = rest.substring(bMatch[0].length).trim();
|
|
2238
|
+
continue;
|
|
2239
|
+
}
|
|
2240
|
+
const rMatch = rest.match(/^r(\d+)/i);
|
|
2241
|
+
if (rMatch) {
|
|
2242
|
+
reverb = clamp(Number.parseInt(rMatch[1], 10), 0, 100);
|
|
2243
|
+
metaTokens.push(rMatch[0]);
|
|
2244
|
+
rest = rest.substring(rMatch[0].length).trim();
|
|
2245
|
+
continue;
|
|
2246
|
+
}
|
|
2247
|
+
const gMatch = rest.match(/^g(\d+)/i);
|
|
2248
|
+
if (gMatch) {
|
|
2249
|
+
gender = clamp(Number.parseInt(gMatch[1], 10), 0, 100);
|
|
2250
|
+
metaTokens.push(gMatch[0]);
|
|
2251
|
+
rest = rest.substring(gMatch[0].length).trim();
|
|
2252
|
+
continue;
|
|
2253
|
+
}
|
|
2254
|
+
const hMatch = rest.match(/^h(\d+)/i);
|
|
2255
|
+
if (hMatch) {
|
|
2256
|
+
breathiness = clamp(Number.parseInt(hMatch[1], 10), 0, 100);
|
|
2257
|
+
metaTokens.push(hMatch[0]);
|
|
2258
|
+
rest = rest.substring(hMatch[0].length).trim();
|
|
2259
|
+
continue;
|
|
2260
|
+
}
|
|
2066
2261
|
break;
|
|
2067
2262
|
}
|
|
2068
2263
|
const lyricLines = [rest];
|
|
2069
|
-
while (
|
|
2070
|
-
lyricLines.push(segments[++
|
|
2264
|
+
while (i2 + 1 < segments.length && isLyricContinuation(segments[i2 + 1])) {
|
|
2265
|
+
lyricLines.push(segments[++i2]);
|
|
2071
2266
|
}
|
|
2072
2267
|
const { syllables, lineBreaks } = normalizeLyricLines(lyricLines);
|
|
2073
2268
|
tracks.set(trackId, {
|
|
@@ -2077,6 +2272,10 @@ var parseLyrics = (mml) => {
|
|
|
2077
2272
|
gate,
|
|
2078
2273
|
pan,
|
|
2079
2274
|
octave,
|
|
2275
|
+
vibrato,
|
|
2276
|
+
reverb,
|
|
2277
|
+
gender,
|
|
2278
|
+
breathiness,
|
|
2080
2279
|
syllables,
|
|
2081
2280
|
metaText: metaTokens.join(" "),
|
|
2082
2281
|
...lineBreaks.length > 0 ? { lineBreaks } : {}
|
|
@@ -2087,13 +2286,13 @@ var parseLyrics = (mml) => {
|
|
|
2087
2286
|
var stripLyrics = (mml) => {
|
|
2088
2287
|
const segments = splitSegments(mml);
|
|
2089
2288
|
const kept = [];
|
|
2090
|
-
for (let
|
|
2091
|
-
if (LYRIC_LINE.test(segments[
|
|
2092
|
-
while (
|
|
2093
|
-
|
|
2289
|
+
for (let i2 = 0; i2 < segments.length; i2++) {
|
|
2290
|
+
if (LYRIC_LINE.test(segments[i2])) {
|
|
2291
|
+
while (i2 + 1 < segments.length && isLyricContinuation(segments[i2 + 1]))
|
|
2292
|
+
i2++;
|
|
2094
2293
|
continue;
|
|
2095
2294
|
}
|
|
2096
|
-
kept.push(segments[
|
|
2295
|
+
kept.push(segments[i2]);
|
|
2097
2296
|
}
|
|
2098
2297
|
return kept.join("\n");
|
|
2099
2298
|
};
|
|
@@ -2162,7 +2361,7 @@ var FORMANTS = {
|
|
|
2162
2361
|
N: [250, 1e3]
|
|
2163
2362
|
};
|
|
2164
2363
|
var midiToFreq = (m) => 440 * 2 ** ((m - 69) / 12);
|
|
2165
|
-
var createKlattVoice = (ctx, destination) => {
|
|
2364
|
+
var createKlattVoice = (ctx, destination, reverbBus) => {
|
|
2166
2365
|
const active = /* @__PURE__ */ new Set();
|
|
2167
2366
|
const voice = (syllable, e) => {
|
|
2168
2367
|
const t0 = ctx.currentTime + e.when;
|
|
@@ -2172,14 +2371,21 @@ var createKlattVoice = (ctx, destination) => {
|
|
|
2172
2371
|
const attack = 0.02;
|
|
2173
2372
|
const release = 0.06;
|
|
2174
2373
|
const sustainEnd = t0 + Math.max(attack + 0.02, e.duration);
|
|
2374
|
+
const dest = e.destination ?? destination;
|
|
2175
2375
|
let panner = null;
|
|
2176
|
-
let out =
|
|
2376
|
+
let out = dest;
|
|
2177
2377
|
if (typeof ctx.createStereoPanner === "function") {
|
|
2178
2378
|
panner = ctx.createStereoPanner();
|
|
2179
2379
|
panner.pan.value = Math.max(-1, Math.min(1, e.pan ?? 0));
|
|
2180
|
-
panner.connect(
|
|
2380
|
+
panner.connect(dest);
|
|
2181
2381
|
out = panner;
|
|
2182
2382
|
}
|
|
2383
|
+
let sendGain = null;
|
|
2384
|
+
if (reverbBus && e.reverbSend && e.reverbSend > 0 && panner) {
|
|
2385
|
+
sendGain = ctx.createGain();
|
|
2386
|
+
sendGain.gain.value = Math.max(0, Math.min(1, e.reverbSend));
|
|
2387
|
+
panner.connect(sendGain).connect(reverbBus);
|
|
2388
|
+
}
|
|
2183
2389
|
const osc = ctx.createOscillator();
|
|
2184
2390
|
osc.type = "sawtooth";
|
|
2185
2391
|
osc.frequency.value = midiToFreq(e.pitch);
|
|
@@ -2208,7 +2414,7 @@ var createKlattVoice = (ctx, destination) => {
|
|
|
2208
2414
|
const length = Math.max(1, Math.floor(ctx.sampleRate * dur));
|
|
2209
2415
|
const buffer = ctx.createBuffer(1, length, ctx.sampleRate);
|
|
2210
2416
|
const data = buffer.getChannelData(0);
|
|
2211
|
-
for (let
|
|
2417
|
+
for (let i2 = 0; i2 < length; i2++) data[i2] = Math.random() * 2 - 1;
|
|
2212
2418
|
const src = ctx.createBufferSource();
|
|
2213
2419
|
src.buffer = buffer;
|
|
2214
2420
|
const hp = ctx.createBiquadFilter();
|
|
@@ -2235,6 +2441,7 @@ var createKlattVoice = (ctx, destination) => {
|
|
|
2235
2441
|
active.delete(osc);
|
|
2236
2442
|
osc.disconnect();
|
|
2237
2443
|
panner?.disconnect();
|
|
2444
|
+
sendGain?.disconnect();
|
|
2238
2445
|
};
|
|
2239
2446
|
};
|
|
2240
2447
|
voice.stopAll = () => {
|
|
@@ -2253,6 +2460,7 @@ var KOE_BASE_URL = "https://pub-12482a6b5cbc4c9e906b2e1904cabae5.r2.dev";
|
|
|
2253
2460
|
var KOE_VOICEBANKS = {
|
|
2254
2461
|
tsukuyomi: "\u3064\u304F\u3088\u307F\u3061\u3083\u3093.koe",
|
|
2255
2462
|
rino: "\u6625\u97F3\u30EA\u30CEver0.3.koe",
|
|
2463
|
+
rino121: "\u6625\u97F3\u30EA\u30CEver.1.1(226).koe",
|
|
2256
2464
|
roze: "\u675F\u97F3\u30ED\u30BCver0.\uFF151(\u591A\u97F3\u968E).koe",
|
|
2257
2465
|
ruko_male: "\u6B32\u97F3\u30EB\u30B3\u2642\u9023\u7D9A\u97F3Ver.1.03.koe",
|
|
2258
2466
|
ruko_female: "\u6B32\u97F3\u30EB\u30B3\u2640\u6B4C\u9023\u7D9A\u97F3\u666E1.00.koe",
|
|
@@ -2261,11 +2469,13 @@ var KOE_VOICEBANKS = {
|
|
|
2261
2469
|
rei: "\u8DB3\u7ACB\u30EC\u30A4ver3.5.0.koe",
|
|
2262
2470
|
mgroid: "MGRoid_\u539F\u97F3\u8A2D\u5B9A\u6E08\u307F.koe",
|
|
2263
2471
|
motroid: "MOTRoid\u5B8C\u5168\u7248V2.koe",
|
|
2264
|
-
nynroid: "NYNRoidver1.4.koe"
|
|
2472
|
+
nynroid: "NYNRoidver1.4.koe",
|
|
2473
|
+
uc: "\u84C4\u97F3\u30AD\u30EA\u30B3\u97F3\u6E90.koe"
|
|
2265
2474
|
};
|
|
2266
2475
|
var KOE_VOICEBANK_LABELS = {
|
|
2267
2476
|
tsukuyomi: "\u3064\u304F\u3088\u307F\u3061\u3083\u3093",
|
|
2268
2477
|
rino: "\u6625\u97F3\u30EA\u30CE",
|
|
2478
|
+
rino121: "\u6625\u97F3\u30EA\u30CEv1.2.1",
|
|
2269
2479
|
roze: "\u675F\u97F3\u30ED\u30BC",
|
|
2270
2480
|
ruko_male: "\u6B32\u97F3\u30EB\u30B3\u2642",
|
|
2271
2481
|
ruko_female: "\u6B32\u97F3\u30EB\u30B3\u2640",
|
|
@@ -2274,12 +2484,14 @@ var KOE_VOICEBANK_LABELS = {
|
|
|
2274
2484
|
rei: "\u8DB3\u7ACB\u30EC\u30A4",
|
|
2275
2485
|
mgroid: "MGRoid",
|
|
2276
2486
|
motroid: "MOTRoid",
|
|
2277
|
-
nynroid: "NYNRoid"
|
|
2487
|
+
nynroid: "NYNRoid",
|
|
2488
|
+
uc: "\u84C4\u97F3\u30AD\u30EA\u30B3"
|
|
2278
2489
|
};
|
|
2279
2490
|
var VOICE_IMAGE_KEY = {
|
|
2280
2491
|
klatt: "puyuyu",
|
|
2281
2492
|
tsukuyomi: "tsukuyomi",
|
|
2282
2493
|
rino: "rino",
|
|
2494
|
+
rino121: "rino",
|
|
2283
2495
|
roze: "roze",
|
|
2284
2496
|
ruko_male: "ruko",
|
|
2285
2497
|
ruko_female: "ruko",
|
|
@@ -2288,11 +2500,13 @@ var VOICE_IMAGE_KEY = {
|
|
|
2288
2500
|
rei: "rei",
|
|
2289
2501
|
mgroid: "MGRoid",
|
|
2290
2502
|
motroid: "MOTRoid",
|
|
2291
|
-
nynroid: "NYNRoid"
|
|
2503
|
+
nynroid: "NYNRoid",
|
|
2504
|
+
uc: "uc"
|
|
2292
2505
|
};
|
|
2293
2506
|
var KOE_VOICEBANK_TERMS = {
|
|
2294
2507
|
tsukuyomi: "https://tyc.rei-yumesaki.net/material/utau/terms/",
|
|
2295
2508
|
rino: "https://hatenakun1.github.io/halunelino/",
|
|
2509
|
+
rino121: "https://harunerino.vercel.app/",
|
|
2296
2510
|
roze: "https://tabaneroze.ninja-web.net/terms-of-use.html",
|
|
2297
2511
|
ruko_male: "https://long-sleeper.net/index.php?id=22",
|
|
2298
2512
|
ruko_female: "https://long-sleeper.net/index.php?id=22",
|
|
@@ -2301,7 +2515,8 @@ var KOE_VOICEBANK_TERMS = {
|
|
|
2301
2515
|
rei: "https://mechanicalgirl.jp/guidelines/",
|
|
2302
2516
|
mgroid: "https://x.com/nisusansu/status/1048825378188353536",
|
|
2303
2517
|
motroid: "https://www.nicovideo.jp/watch/sm40031282",
|
|
2304
|
-
nynroid: "https://www.bilibili.com/video/BV1V24y1a7qs"
|
|
2518
|
+
nynroid: "https://www.bilibili.com/video/BV1V24y1a7qs",
|
|
2519
|
+
uc: "https://chi9nekiriko.wixsite.com/home/%E5%88%A9%E7%94%A8%E8%A6%8F%E7%B4%84"
|
|
2305
2520
|
};
|
|
2306
2521
|
var koeUrl = (name, base = KOE_BASE_URL) => `${base}/${encodeURIComponent(name)}`;
|
|
2307
2522
|
var DEFAULT_WORLDLINE_SCRIPT = "https://onjmin.github.io/koe/demo/world/worldline.js";
|
|
@@ -2390,7 +2605,7 @@ var createLocalBackend = async (options) => {
|
|
|
2390
2605
|
}
|
|
2391
2606
|
return p;
|
|
2392
2607
|
};
|
|
2393
|
-
const renderAlias = async (alias, pitch, durationMs) => {
|
|
2608
|
+
const renderAlias = async (alias, pitch, durationMs, vibrato, expr) => {
|
|
2394
2609
|
const pcm = await getPcm(alias);
|
|
2395
2610
|
if (!pcm || pcm.length === 0) return null;
|
|
2396
2611
|
const entry = bank.manifest.phonemes[alias];
|
|
@@ -2399,9 +2614,11 @@ var createLocalBackend = async (options) => {
|
|
|
2399
2614
|
if (worldline) {
|
|
2400
2615
|
const audio = worldline.renderNote({
|
|
2401
2616
|
pcm,
|
|
2402
|
-
pitch: targetHz,
|
|
2617
|
+
pitch: vibrato ? vibratoPitchCurve(targetHz, lead.preMs) : targetHz,
|
|
2403
2618
|
durationMs,
|
|
2404
|
-
...lead
|
|
2619
|
+
...lead,
|
|
2620
|
+
gender: expr?.gender,
|
|
2621
|
+
breathiness: expr?.breathiness
|
|
2405
2622
|
});
|
|
2406
2623
|
if (audio) return { pcm: audio, preSec: lead.preMs / 1e3, rate: 1 };
|
|
2407
2624
|
}
|
|
@@ -2466,7 +2683,7 @@ var createWorkerBackend = async (workerUrl, options) => {
|
|
|
2466
2683
|
});
|
|
2467
2684
|
onReady = null;
|
|
2468
2685
|
onFail = null;
|
|
2469
|
-
const renderAlias = (alias, pitch, durationMs) => new Promise((resolve) => {
|
|
2686
|
+
const renderAlias = (alias, pitch, durationMs, vibrato, expr) => new Promise((resolve) => {
|
|
2470
2687
|
const id = ++reqId;
|
|
2471
2688
|
pending.set(
|
|
2472
2689
|
id,
|
|
@@ -2479,7 +2696,10 @@ var createWorkerBackend = async (workerUrl, options) => {
|
|
|
2479
2696
|
id,
|
|
2480
2697
|
alias,
|
|
2481
2698
|
pitch,
|
|
2482
|
-
durationMs
|
|
2699
|
+
durationMs,
|
|
2700
|
+
vibrato,
|
|
2701
|
+
gender: expr?.gender,
|
|
2702
|
+
breathiness: expr?.breathiness
|
|
2483
2703
|
});
|
|
2484
2704
|
});
|
|
2485
2705
|
return {
|
|
@@ -2508,15 +2728,21 @@ var createKoeVoice = async (ctx, destination, options) => {
|
|
|
2508
2728
|
const inflight = /* @__PURE__ */ new Map();
|
|
2509
2729
|
const active = /* @__PURE__ */ new Set();
|
|
2510
2730
|
let prevVowel = "";
|
|
2511
|
-
const keyOf = (alias, pitch, durationMs) => `${alias}|${pitch}|${Math.round(durationMs / 10) * 10}`;
|
|
2512
|
-
const renderInto = (alias, pitch, durationMs) => {
|
|
2513
|
-
const key = keyOf(alias, pitch, durationMs);
|
|
2731
|
+
const keyOf = (alias, pitch, durationMs, vibrato, expr) => `${alias}|${pitch}|${Math.round(durationMs / 10) * 10}${vibrato ? "|vib" : ""}${expr?.gender !== void 0 ? `|g${Math.round(expr.gender * 100)}` : ""}${expr?.breathiness !== void 0 ? `|h${Math.round(expr.breathiness * 100)}` : ""}`;
|
|
2732
|
+
const renderInto = (alias, pitch, durationMs, vibrato, expr) => {
|
|
2733
|
+
const key = keyOf(alias, pitch, durationMs, vibrato, expr);
|
|
2514
2734
|
const existing = renderCache.get(key);
|
|
2515
2735
|
if (existing !== void 0) return Promise.resolve(existing);
|
|
2516
2736
|
const flying = inflight.get(key);
|
|
2517
2737
|
if (flying) return flying;
|
|
2518
2738
|
const p = (async () => {
|
|
2519
|
-
const out = await backend.renderAlias(
|
|
2739
|
+
const out = await backend.renderAlias(
|
|
2740
|
+
alias,
|
|
2741
|
+
pitch,
|
|
2742
|
+
durationMs,
|
|
2743
|
+
vibrato,
|
|
2744
|
+
expr
|
|
2745
|
+
);
|
|
2520
2746
|
let rendered = null;
|
|
2521
2747
|
if (out) {
|
|
2522
2748
|
const buf = ctx.createBuffer(1, out.pcm.length, KOE_SAMPLE_RATE);
|
|
@@ -2531,15 +2757,22 @@ var createKoeVoice = async (ctx, destination, options) => {
|
|
|
2531
2757
|
return p;
|
|
2532
2758
|
};
|
|
2533
2759
|
const LEADCAP_S = 0.09;
|
|
2534
|
-
const schedule = (r, t0, peak, pan) => {
|
|
2535
|
-
|
|
2760
|
+
const schedule = (r, t0, peak, pan, reverbSend = 0, destOverride) => {
|
|
2761
|
+
const dest = destOverride ?? destination;
|
|
2762
|
+
let out = dest;
|
|
2536
2763
|
let panner = null;
|
|
2537
2764
|
if (typeof ctx.createStereoPanner === "function") {
|
|
2538
2765
|
panner = ctx.createStereoPanner();
|
|
2539
2766
|
panner.pan.value = Math.max(-1, Math.min(1, pan));
|
|
2540
|
-
panner.connect(
|
|
2767
|
+
panner.connect(dest);
|
|
2541
2768
|
out = panner;
|
|
2542
2769
|
}
|
|
2770
|
+
let sendGain = null;
|
|
2771
|
+
if (options.reverbBus && reverbSend > 0 && panner) {
|
|
2772
|
+
sendGain = ctx.createGain();
|
|
2773
|
+
sendGain.gain.value = Math.max(0, Math.min(1, reverbSend));
|
|
2774
|
+
panner.connect(sendGain).connect(options.reverbBus);
|
|
2775
|
+
}
|
|
2543
2776
|
const src = ctx.createBufferSource();
|
|
2544
2777
|
src.buffer = r.audio;
|
|
2545
2778
|
src.playbackRate.value = r.rate;
|
|
@@ -2565,6 +2798,7 @@ var createKoeVoice = async (ctx, destination, options) => {
|
|
|
2565
2798
|
src.disconnect();
|
|
2566
2799
|
env.disconnect();
|
|
2567
2800
|
panner?.disconnect();
|
|
2801
|
+
sendGain?.disconnect();
|
|
2568
2802
|
};
|
|
2569
2803
|
};
|
|
2570
2804
|
const model = (syllable, e) => {
|
|
@@ -2583,10 +2817,10 @@ var createKoeVoice = async (ctx, destination, options) => {
|
|
|
2583
2817
|
const pan = e.pan ?? 0;
|
|
2584
2818
|
const durationMs = Math.max(60, e.duration * 1e3);
|
|
2585
2819
|
void renderInto(alias, e.pitch, durationMs).then((r) => {
|
|
2586
|
-
if (r) schedule(r, t0, peak, pan);
|
|
2820
|
+
if (r) schedule(r, t0, peak, pan, e.reverbSend, e.destination);
|
|
2587
2821
|
});
|
|
2588
2822
|
};
|
|
2589
|
-
model.renderToCache = async (syllable, prevVowelArg, pitch, durationMs) => {
|
|
2823
|
+
model.renderToCache = async (syllable, prevVowelArg, pitch, durationMs, vibrato, expr) => {
|
|
2590
2824
|
if (syllable.consonant === "Q" || syllable.vowel === "") return null;
|
|
2591
2825
|
const alias = resolveKoeAlias(
|
|
2592
2826
|
backend.hasAlias,
|
|
@@ -2597,12 +2831,13 @@ var createKoeVoice = async (ctx, destination, options) => {
|
|
|
2597
2831
|
);
|
|
2598
2832
|
if (!alias) return null;
|
|
2599
2833
|
const dMs = Math.max(60, durationMs);
|
|
2600
|
-
const
|
|
2601
|
-
|
|
2834
|
+
const vib = !!vibrato && dMs / 1e3 >= VIBRATO_MIN_SEC;
|
|
2835
|
+
const r = await renderInto(alias, pitch, dMs, vib, expr);
|
|
2836
|
+
return r ? keyOf(alias, pitch, dMs, vib, expr) : null;
|
|
2602
2837
|
};
|
|
2603
|
-
model.scheduleCached = (key, t0, peak, pan) => {
|
|
2838
|
+
model.scheduleCached = (key, t0, peak, pan, reverbSend, dest) => {
|
|
2604
2839
|
const r = renderCache.get(key);
|
|
2605
|
-
if (r) schedule(r, t0, peak, pan);
|
|
2840
|
+
if (r) schedule(r, t0, peak, pan, reverbSend, dest);
|
|
2606
2841
|
};
|
|
2607
2842
|
model.stopAll = () => {
|
|
2608
2843
|
for (const src of active) {
|
|
@@ -2633,7 +2868,7 @@ var createSingingVoices = (ctx, destination, options = {}) => {
|
|
|
2633
2868
|
const masterGain = ctx.createGain();
|
|
2634
2869
|
masterGain.connect(destination);
|
|
2635
2870
|
const loaded = /* @__PURE__ */ new Map([
|
|
2636
|
-
[FALLBACK_MODEL, createKlattVoice(ctx, masterGain)]
|
|
2871
|
+
[FALLBACK_MODEL, createKlattVoice(ctx, masterGain, options.reverbBus)]
|
|
2637
2872
|
]);
|
|
2638
2873
|
const loading = /* @__PURE__ */ new Map();
|
|
2639
2874
|
const load2 = (model) => {
|
|
@@ -2653,7 +2888,8 @@ var createSingingVoices = (ctx, destination, options = {}) => {
|
|
|
2653
2888
|
koe,
|
|
2654
2889
|
worldlineScriptUrl: options.worldlineScriptUrl,
|
|
2655
2890
|
lightweight: options.lightweight,
|
|
2656
|
-
voiceWorkerUrl: options.voiceWorkerUrl
|
|
2891
|
+
voiceWorkerUrl: options.voiceWorkerUrl,
|
|
2892
|
+
reverbBus: options.reverbBus
|
|
2657
2893
|
})
|
|
2658
2894
|
))().then((v) => {
|
|
2659
2895
|
loaded.set(m, v);
|
|
@@ -2695,10 +2931,14 @@ var createSingingVoices = (ctx, destination, options = {}) => {
|
|
|
2695
2931
|
const m = loaded.get(track.model.toLowerCase());
|
|
2696
2932
|
if (!m?.renderToCache) continue;
|
|
2697
2933
|
let n = 0;
|
|
2934
|
+
const expr = {
|
|
2935
|
+
gender: track.gender,
|
|
2936
|
+
breathiness: track.breathiness
|
|
2937
|
+
};
|
|
2698
2938
|
forEachSungNote(track, (note, prevVowel) => {
|
|
2699
2939
|
if (n >= count && note.startSec >= STREAM_LOOKAHEAD_SEC) return;
|
|
2700
2940
|
n++;
|
|
2701
|
-
tasks.push({ model: m, note, prevVowel });
|
|
2941
|
+
tasks.push({ model: m, note, prevVowel, vibrato: track.vibrato, expr });
|
|
2702
2942
|
});
|
|
2703
2943
|
}
|
|
2704
2944
|
const total = tasks.length;
|
|
@@ -2713,7 +2953,9 @@ var createSingingVoices = (ctx, destination, options = {}) => {
|
|
|
2713
2953
|
task.note.syllable,
|
|
2714
2954
|
task.prevVowel,
|
|
2715
2955
|
task.note.pitch,
|
|
2716
|
-
task.note.durationSec * 1e3
|
|
2956
|
+
task.note.durationSec * 1e3,
|
|
2957
|
+
task.vibrato,
|
|
2958
|
+
task.expr
|
|
2717
2959
|
) ?? Promise.resolve(null));
|
|
2718
2960
|
done++;
|
|
2719
2961
|
onProgress?.(done, total);
|
|
@@ -2758,13 +3000,22 @@ var createSingingVoices = (ctx, destination, options = {}) => {
|
|
|
2758
3000
|
note.syllable,
|
|
2759
3001
|
prevVowel,
|
|
2760
3002
|
note.pitch,
|
|
2761
|
-
note.durationSec * 1e3
|
|
3003
|
+
note.durationSec * 1e3,
|
|
3004
|
+
track.vibrato,
|
|
3005
|
+
{ gender: track.gender, breathiness: track.breathiness }
|
|
2762
3006
|
);
|
|
2763
3007
|
if (session !== streamSession) return;
|
|
2764
3008
|
if (key) {
|
|
2765
3009
|
const delay = ctx.currentTime - t0;
|
|
2766
3010
|
if (delay < 0.05) {
|
|
2767
|
-
scheduleCached(
|
|
3011
|
+
scheduleCached(
|
|
3012
|
+
key,
|
|
3013
|
+
t0,
|
|
3014
|
+
peak,
|
|
3015
|
+
track.pan,
|
|
3016
|
+
track.reverbSend,
|
|
3017
|
+
options.getTrackDestination?.(track.id ?? "")
|
|
3018
|
+
);
|
|
2768
3019
|
opts?.onScheduled?.(track, note, t0);
|
|
2769
3020
|
} else {
|
|
2770
3021
|
console.warn(
|
|
@@ -2777,13 +3028,15 @@ var createSingingVoices = (ctx, destination, options = {}) => {
|
|
|
2777
3028
|
} else {
|
|
2778
3029
|
const when = t0 - ctx.currentTime;
|
|
2779
3030
|
model(note.syllable, {
|
|
2780
|
-
trackId: "",
|
|
3031
|
+
trackId: track.id ?? "",
|
|
2781
3032
|
pitch: note.pitch,
|
|
2782
3033
|
velocity: 100,
|
|
2783
3034
|
volume: peak,
|
|
2784
3035
|
when,
|
|
2785
3036
|
duration: note.durationSec,
|
|
2786
|
-
pan: track.pan
|
|
3037
|
+
pan: track.pan,
|
|
3038
|
+
reverbSend: track.reverbSend,
|
|
3039
|
+
destination: options.getTrackDestination?.(track.id ?? "")
|
|
2787
3040
|
});
|
|
2788
3041
|
opts?.onScheduled?.(track, note, t0);
|
|
2789
3042
|
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
@@ -2842,8 +3095,10 @@ var PITCH_MAP = {
|
|
|
2842
3095
|
b: 11
|
|
2843
3096
|
};
|
|
2844
3097
|
var clamp2 = (value, lo, hi) => Math.min(hi, Math.max(lo, value));
|
|
2845
|
-
var META_DIRECTIVE = /#(inst|drum|drumfont|volume|drumvolume|mode)=([\w-]+)/gi;
|
|
3098
|
+
var META_DIRECTIVE = /#(inst|drum|drumfont|volume|drumvolume|reverb|mode)=([\w-]+)/gi;
|
|
2846
3099
|
var TRACK_INST_DIRECTIVE = /#t(\d+)inst=([^#;\r\n]+)/gi;
|
|
3100
|
+
var TRACK_COMP_DIRECTIVE = /#t(\d+)comp=(\d+)/gi;
|
|
3101
|
+
var TRACK_WIDTH_DIRECTIVE = /#t(\d+)width=(\d+)/gi;
|
|
2847
3102
|
var parseMmlMeta = (mml) => {
|
|
2848
3103
|
const meta = {};
|
|
2849
3104
|
for (const m of mml.matchAll(META_DIRECTIVE)) {
|
|
@@ -2857,6 +3112,9 @@ var parseMmlMeta = (mml) => {
|
|
|
2857
3112
|
} else if (key === "drumvolume") {
|
|
2858
3113
|
const dv = Number.parseInt(m[2], 10);
|
|
2859
3114
|
if (!Number.isNaN(dv)) meta.drumVolume = dv;
|
|
3115
|
+
} else if (key === "reverb") {
|
|
3116
|
+
const rv = Number.parseInt(m[2], 10);
|
|
3117
|
+
if (!Number.isNaN(rv)) meta.reverb = clamp2(rv, 0, 100);
|
|
2860
3118
|
} else if (key === "mode") {
|
|
2861
3119
|
if (m[2] === "simple" || m[2] === "advanced") {
|
|
2862
3120
|
meta.mode = m[2];
|
|
@@ -2871,9 +3129,25 @@ var parseMmlMeta = (mml) => {
|
|
|
2871
3129
|
meta.trackInstruments[idx] = name;
|
|
2872
3130
|
}
|
|
2873
3131
|
}
|
|
3132
|
+
for (const m of mml.matchAll(TRACK_COMP_DIRECTIVE)) {
|
|
3133
|
+
const idx = Number.parseInt(m[1], 10);
|
|
3134
|
+
const val = clamp2(Number.parseInt(m[2], 10), 0, 100);
|
|
3135
|
+
if (!Number.isNaN(idx) && !Number.isNaN(val)) {
|
|
3136
|
+
meta.trackCompression ??= {};
|
|
3137
|
+
meta.trackCompression[idx] = val;
|
|
3138
|
+
}
|
|
3139
|
+
}
|
|
3140
|
+
for (const m of mml.matchAll(TRACK_WIDTH_DIRECTIVE)) {
|
|
3141
|
+
const idx = Number.parseInt(m[1], 10);
|
|
3142
|
+
const val = clamp2(Number.parseInt(m[2], 10), 0, 200);
|
|
3143
|
+
if (!Number.isNaN(idx) && !Number.isNaN(val)) {
|
|
3144
|
+
meta.trackWidth ??= {};
|
|
3145
|
+
meta.trackWidth[idx] = val;
|
|
3146
|
+
}
|
|
3147
|
+
}
|
|
2874
3148
|
return meta;
|
|
2875
3149
|
};
|
|
2876
|
-
var stripMmlMeta = (mml) => mml.replace(META_DIRECTIVE, "").replace(TRACK_INST_DIRECTIVE, "");
|
|
3150
|
+
var stripMmlMeta = (mml) => mml.replace(META_DIRECTIVE, "").replace(TRACK_INST_DIRECTIVE, "").replace(TRACK_COMP_DIRECTIVE, "").replace(TRACK_WIDTH_DIRECTIVE, "");
|
|
2877
3151
|
var formatMmlMeta = (meta, space = "") => {
|
|
2878
3152
|
const parts = [];
|
|
2879
3153
|
if (meta.instrument) parts.push(`#inst=${meta.instrument}`);
|
|
@@ -2882,12 +3156,24 @@ var formatMmlMeta = (meta, space = "") => {
|
|
|
2882
3156
|
if (meta.volume !== void 0) parts.push(`#volume=${meta.volume}`);
|
|
2883
3157
|
if (meta.drumVolume !== void 0)
|
|
2884
3158
|
parts.push(`#drumvolume=${meta.drumVolume}`);
|
|
3159
|
+
if (meta.reverb !== void 0 && meta.reverb !== 0)
|
|
3160
|
+
parts.push(`#reverb=${meta.reverb}`);
|
|
2885
3161
|
if (meta.mode) parts.push(`#mode=${meta.mode}`);
|
|
2886
3162
|
if (meta.trackInstruments) {
|
|
2887
3163
|
for (const [idx, name] of Object.entries(meta.trackInstruments)) {
|
|
2888
3164
|
if (name) parts.push(`#t${idx}inst=${name}`);
|
|
2889
3165
|
}
|
|
2890
3166
|
}
|
|
3167
|
+
if (meta.trackCompression) {
|
|
3168
|
+
for (const [idx, val] of Object.entries(meta.trackCompression)) {
|
|
3169
|
+
if (val !== 0) parts.push(`#t${idx}comp=${val}`);
|
|
3170
|
+
}
|
|
3171
|
+
}
|
|
3172
|
+
if (meta.trackWidth) {
|
|
3173
|
+
for (const [idx, val] of Object.entries(meta.trackWidth)) {
|
|
3174
|
+
if (val !== 100) parts.push(`#t${idx}width=${val}`);
|
|
3175
|
+
}
|
|
3176
|
+
}
|
|
2891
3177
|
return parts.join(space);
|
|
2892
3178
|
};
|
|
2893
3179
|
var parseMML = (mml, options = {}) => {
|
|
@@ -5644,7 +5930,7 @@ var createSynth = (ctx, destination = ctx.destination, tone = {}) => {
|
|
|
5644
5930
|
const length = Math.max(1, Math.floor(ctx.sampleRate * dur));
|
|
5645
5931
|
const buffer = ctx.createBuffer(1, length, ctx.sampleRate);
|
|
5646
5932
|
const data = buffer.getChannelData(0);
|
|
5647
|
-
for (let
|
|
5933
|
+
for (let i2 = 0; i2 < length; i2++) data[i2] = Math.random() * 2 - 1;
|
|
5648
5934
|
const src = ctx.createBufferSource();
|
|
5649
5935
|
src.buffer = buffer;
|
|
5650
5936
|
const filter = ctx.createBiquadFilter();
|
|
@@ -6629,6 +6915,23 @@ var DAW_CSS = `
|
|
|
6629
6915
|
@keyframes dtm-blink { 0%,100%{opacity:1} 50%{opacity:0} }
|
|
6630
6916
|
.dtm-blink { animation: dtm-blink 1s steps(1) infinite; }
|
|
6631
6917
|
|
|
6918
|
+
/* \u2500\u2500\u2500 \u97F3\u5272\u308C\u691C\u77E5\u30D0\u30C3\u30B8 \u2500\u2500\u2500 \u30AF\u30EA\u30C3\u30D7\u767A\u751F\u4E2D\u3060\u3051\u8868\u793A\u3055\u308C\u308B\u8B66\u544A\u30DC\u30BF\u30F3\u3002\u30AF\u30EA\u30C3\u30AF\u3067\u6D88\u305B\u308B\u3002 */
|
|
6919
|
+
.dtm-clip-badge {
|
|
6920
|
+
flex: 0 0 auto;
|
|
6921
|
+
min-height: 24px;
|
|
6922
|
+
padding: 0 8px;
|
|
6923
|
+
border: 2px solid var(--c-black);
|
|
6924
|
+
background: var(--dtm-danger);
|
|
6925
|
+
color: var(--c-white);
|
|
6926
|
+
font-family: var(--dtm-font);
|
|
6927
|
+
font-size: 10px;
|
|
6928
|
+
letter-spacing: .1em;
|
|
6929
|
+
cursor: pointer;
|
|
6930
|
+
box-shadow: 0 0 0 2px var(--dtm-danger), 2px 2px 0 var(--c-black);
|
|
6931
|
+
animation: dtm-blink .5s steps(1) infinite;
|
|
6932
|
+
}
|
|
6933
|
+
.dtm-clip-badge:active { transform: translate(2px,2px); box-shadow: none; }
|
|
6934
|
+
|
|
6632
6935
|
/* \u2500\u2500\u2500 \u30A4\u30F3\u30D5\u30A9\u30DC\u30BF\u30F3 \u2500\u2500\u2500 */
|
|
6633
6936
|
.dtm-infobtn {
|
|
6634
6937
|
display: inline-flex;
|
|
@@ -6904,6 +7207,37 @@ var DAW_CSS = `
|
|
|
6904
7207
|
object-fit: cover;
|
|
6905
7208
|
image-rendering: pixelated;
|
|
6906
7209
|
}
|
|
7210
|
+
/* \u6B4C\u8A5E\u30C8\u30E9\u30C3\u30AF\u306E\u300C\u8A73\u7D30\u8A2D\u5B9A\u300D\u2014 \u5E38\u7528\u3057\u306A\u3044\u30D1\u30E9\u30E1\u30FC\u30BF\uFF08\u30AA\u30AF\u30BF\u30FC\u30D6/\u5B9A\u4F4D/\u30EA\u30D0\u30FC\u30D6\u9001\u308A/
|
|
7211
|
+
\u30B8\u30A7\u30F3\u30C0\u30FC/\u30D6\u30EC\u30B7\u30CD\u30B9/\u30D3\u30D6\u30E9\u30FC\u30C8\uFF09\u3092\u7573\u3093\u3067\u304A\u304F\u8EFD\u91CF\u306A details\u3002dtm-panel \u307B\u3069
|
|
7212
|
+
\u4EF0\u3005\u3057\u304F\u305B\u305A\u3001\u63A7\u3048\u3081\u306A\u4ED5\u5207\u308A\u7DDA\uFF0B\u5C0F\u3055\u3044\u25B6\u30DE\u30FC\u30AB\u30FC\u3060\u3051\u4ED8\u3051\u308B\u3002 */
|
|
7213
|
+
.dtm-advanced {
|
|
7214
|
+
border-top: 1px dashed var(--dtm-border2);
|
|
7215
|
+
padding-top: 6px;
|
|
7216
|
+
display: flex;
|
|
7217
|
+
flex-direction: column;
|
|
7218
|
+
gap: 6px;
|
|
7219
|
+
}
|
|
7220
|
+
.dtm-advanced > summary {
|
|
7221
|
+
list-style: none;
|
|
7222
|
+
cursor: pointer;
|
|
7223
|
+
font-size: 11px;
|
|
7224
|
+
letter-spacing: .08em;
|
|
7225
|
+
color: var(--dtm-text);
|
|
7226
|
+
display: flex;
|
|
7227
|
+
align-items: center;
|
|
7228
|
+
gap: 6px;
|
|
7229
|
+
min-height: 28px;
|
|
7230
|
+
padding: 0 8px;
|
|
7231
|
+
border: 2px solid var(--dtm-border2);
|
|
7232
|
+
background: var(--dtm-deep);
|
|
7233
|
+
box-shadow: 2px 2px 0 var(--c-black);
|
|
7234
|
+
width: fit-content;
|
|
7235
|
+
}
|
|
7236
|
+
.dtm-advanced > summary:active { transform: translate(2px,2px); box-shadow: none; }
|
|
7237
|
+
.dtm-advanced > summary::-webkit-details-marker { display: none; }
|
|
7238
|
+
.dtm-advanced > summary::before { content: "\u25B6"; font-size: 9px; color: var(--dtm-accent); }
|
|
7239
|
+
.dtm-advanced[open] > summary::before { content: "\u25BC"; }
|
|
7240
|
+
.dtm-advanced[open] > summary { border-color: var(--dtm-primary); color: var(--dtm-primary); }
|
|
6907
7241
|
|
|
6908
7242
|
/* \u2500\u2500\u2500 \u5E83\u5E45\u62E1\u5F35 \u2500\u2500\u2500 */
|
|
6909
7243
|
@media (min-width: 768px) {
|
|
@@ -7565,6 +7899,9 @@ var teto_default = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAA
|
|
|
7565
7899
|
// assets/tsukuyomi.png
|
|
7566
7900
|
var tsukuyomi_default = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAB3UlEQVR42tWXPUsDQRCGnwuijYIoFqKmEDSCxIgIgqnsogbsrC3ERiwN4g8Ikk6sFH+BnYofvcTKxoigBCzEYGGjWIiCOYvNBHe5TdQUt051czc3e++zO7tzHnUst7vn04BlFue9Ws8jhGxN9ZTPzU43NkIlj41E6AQ8m/JYfByAoWgXAPtHJzRCRN43SbizBkzlv1X2VzLuVoHYzf0TAMnys+aLCTGThMTJGnKfQOpyWF1cvgHQsh4FYPDzRd3vmQHgoPShJbi9uqhJyPk1UK3Jwsq1/115rLst8AX/4UFP0NsbGHf7+Kr579l7zR/ZGvbcrAJR7vvqEOwcTdZMYIuTPCYJUS7Ewydgzn2Bay2gdWzqR4nMuMPlhcC5l/HcWQOnCaU4lVU3xI9tnwFQnOgDoDmdDs5QKmlxYhdGmBA2ibhTBfKFHCkCm00dAKymJn+USAidHx8DkI+0q7PBUC7j5BJ7jlSB7RyXziVT8fM7Oz7AeLmsz3VEaWi7UvtAcmvJC+qmq4T/XT8gdTsw2692to07AF7jeU35wFq/7COqzhdVnVOnu3aHgNm1VpVXlImJX9zQffO5kDg1dlb3CNj6dZsVK2vAVP7Xf8bwCfxWuc23Eanmt/xlh07gC6oBviFE8rZHAAAAAElFTkSuQmCC";
|
|
7567
7901
|
|
|
7902
|
+
// assets/uc.png
|
|
7903
|
+
var uc_default = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAB/ElEQVR42s2WPUhbURTHfxHniEEIVdvFmDaTiIJjBpcuGQrFr2JDaoeCkxRdAg6WVPAD20FwqEoUQUs7hdAuDaSbYNpGF6VxiaLooCCdREyHlxs4z/deEhG8Zwn/m8d57/+759x7XEAB53BxuyhU8lAN9xyusLfe8UvTrT4ALhr3q0ocSjsDiJ+c60Gg9q6dq1jYbATgTdeR3jVQW63z5t6nABxufBd6syMLQFemDYDA0jEA829nAPg8O6ApAVWNYW99RU7tQjkvkcDQw9kpAILa14B579203iqhmURqv1gDDIj+Vyesfl1Qbq/NNRFJ7gDwsblBPthh/AxuvQDgzORc33PgImv0r7vtgeV6icTkFQDvCBgL26ZEr04r+oD7J6D6P21DoqR3s0LnIntC+5YfC900ViT5xOiKkPeP6oKC3l1A6p+QblqE/tV/aZnoBpG09QsVcUVCHwLBvznxRyJotGsu+FCsj0zkLRPNjT8qOj9wrB39ZsJEIiGGt/Bq2HqPy5CwI2CeDZ9/WjHWQyFNCJjn9+TUN3GGr3auAXAdME6+TCYjEtTlv8rqf/Ze6C+vXwrnJTLaEfD0eBxvRXUL+vN+x4TRaFTon2sfAJhe/6H5bThU0w7A4vXvqmZBO+fmGO3rViQ0vwvsSMQH4wDEYrGKnKu9134e+A/zObZWSEHtdQAAAABJRU5ErkJggg==";
|
|
7904
|
+
|
|
7568
7905
|
// src/voice-images.ts
|
|
7569
7906
|
var VOICE_IMAGES = {
|
|
7570
7907
|
puyuyu: puyuyu_default,
|
|
@@ -7577,7 +7914,8 @@ var VOICE_IMAGES = {
|
|
|
7577
7914
|
rei: rei_default,
|
|
7578
7915
|
MGRoid: MGRoid_default,
|
|
7579
7916
|
MOTRoid: MOTRoid_default,
|
|
7580
|
-
NYNRoid: NYNRoid_default
|
|
7917
|
+
NYNRoid: NYNRoid_default,
|
|
7918
|
+
uc: uc_default
|
|
7581
7919
|
};
|
|
7582
7920
|
var FALLBACK_VOCAL_ICON = Chip_default;
|
|
7583
7921
|
|
|
@@ -7639,8 +7977,8 @@ var copyToClipboard = async (doc, text) => {
|
|
|
7639
7977
|
};
|
|
7640
7978
|
var toBase64Url = (bytes) => {
|
|
7641
7979
|
let bin = "";
|
|
7642
|
-
for (let
|
|
7643
|
-
bin += String.fromCharCode(bytes[
|
|
7980
|
+
for (let i2 = 0; i2 < bytes.length; i2++) {
|
|
7981
|
+
bin += String.fromCharCode(bytes[i2]);
|
|
7644
7982
|
}
|
|
7645
7983
|
return btoa(bin).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
7646
7984
|
};
|
|
@@ -7653,8 +7991,8 @@ var SHIFT_KATAKANA = 255;
|
|
|
7653
7991
|
var VALUE_PROLONGED = 223;
|
|
7654
7992
|
var customEncode = (str) => {
|
|
7655
7993
|
const bytes = [];
|
|
7656
|
-
for (let
|
|
7657
|
-
const code = str.charCodeAt(
|
|
7994
|
+
for (let i2 = 0; i2 < str.length; i2++) {
|
|
7995
|
+
const code = str.charCodeAt(i2);
|
|
7658
7996
|
if (code === 32) {
|
|
7659
7997
|
continue;
|
|
7660
7998
|
}
|
|
@@ -7696,37 +8034,37 @@ var fromBase64Url = (s) => {
|
|
|
7696
8034
|
}
|
|
7697
8035
|
const bin = atob(normalized);
|
|
7698
8036
|
const bytes = new Uint8Array(bin.length);
|
|
7699
|
-
for (let
|
|
7700
|
-
bytes[
|
|
8037
|
+
for (let i2 = 0; i2 < bin.length; i2++) {
|
|
8038
|
+
bytes[i2] = bin.charCodeAt(i2);
|
|
7701
8039
|
}
|
|
7702
8040
|
return bytes;
|
|
7703
8041
|
};
|
|
7704
8042
|
var customDecode = (bytes) => {
|
|
7705
8043
|
let str = "";
|
|
7706
|
-
let
|
|
7707
|
-
while (
|
|
7708
|
-
const byte = bytes[
|
|
8044
|
+
let i2 = 0;
|
|
8045
|
+
while (i2 < bytes.length) {
|
|
8046
|
+
const byte = bytes[i2];
|
|
7709
8047
|
if (byte <= 127) {
|
|
7710
8048
|
str += String.fromCharCode(byte);
|
|
7711
|
-
|
|
8049
|
+
i2++;
|
|
7712
8050
|
} else if (byte === VALUE_PROLONGED) {
|
|
7713
8051
|
str += String.fromCharCode(PROLONGED_MARK);
|
|
7714
|
-
|
|
8052
|
+
i2++;
|
|
7715
8053
|
} else if (byte >= 128 && byte <= 222) {
|
|
7716
8054
|
str += String.fromCharCode(HIRAGANA_START + (byte - 128));
|
|
7717
|
-
|
|
8055
|
+
i2++;
|
|
7718
8056
|
} else if (byte === SHIFT_KATAKANA) {
|
|
7719
|
-
if (
|
|
7720
|
-
const nextByte = bytes[
|
|
8057
|
+
if (i2 + 1 < bytes.length) {
|
|
8058
|
+
const nextByte = bytes[i2 + 1];
|
|
7721
8059
|
if (nextByte >= 128 && nextByte <= 222) {
|
|
7722
8060
|
str += String.fromCharCode(HIRAGANA_START + 96 + (nextByte - 128));
|
|
7723
8061
|
}
|
|
7724
|
-
|
|
8062
|
+
i2 += 2;
|
|
7725
8063
|
} else {
|
|
7726
|
-
|
|
8064
|
+
i2++;
|
|
7727
8065
|
}
|
|
7728
8066
|
} else {
|
|
7729
|
-
|
|
8067
|
+
i2++;
|
|
7730
8068
|
}
|
|
7731
8069
|
}
|
|
7732
8070
|
return str;
|
|
@@ -8291,7 +8629,7 @@ var mountMmlPlayer = (target, mml, options = {}) => {
|
|
|
8291
8629
|
const beatRow = doc.createElement("div");
|
|
8292
8630
|
beatRow.className = "dtm-player-beat-row";
|
|
8293
8631
|
const beatDots = [];
|
|
8294
|
-
for (let
|
|
8632
|
+
for (let i2 = 0; i2 < 4; i2++) {
|
|
8295
8633
|
const d = doc.createElement("span");
|
|
8296
8634
|
d.className = "dtm-player-beat-dot";
|
|
8297
8635
|
beatRow.appendChild(d);
|
|
@@ -8395,9 +8733,9 @@ var mountMmlPlayer = (target, mml, options = {}) => {
|
|
|
8395
8733
|
lane.appendChild(metaEl);
|
|
8396
8734
|
}
|
|
8397
8735
|
const count = Math.min(notes.length, lyricTrack.syllables.length);
|
|
8398
|
-
for (let
|
|
8399
|
-
const note = notes[
|
|
8400
|
-
if (breaks.has(
|
|
8736
|
+
for (let i2 = 0; i2 < count; i2++) {
|
|
8737
|
+
const note = notes[i2];
|
|
8738
|
+
if (breaks.has(i2)) {
|
|
8401
8739
|
const br = doc.createElement("span");
|
|
8402
8740
|
br.className = "dtm-tk dtm-tk--break";
|
|
8403
8741
|
br.textContent = "\\n";
|
|
@@ -8405,7 +8743,7 @@ var mountMmlPlayer = (target, mml, options = {}) => {
|
|
|
8405
8743
|
}
|
|
8406
8744
|
const span = doc.createElement("span");
|
|
8407
8745
|
span.className = "dtm-tk dtm-tk--lyric";
|
|
8408
|
-
span.textContent = lyricTrack.syllables[
|
|
8746
|
+
span.textContent = lyricTrack.syllables[i2].kana;
|
|
8409
8747
|
lane.appendChild(span);
|
|
8410
8748
|
laneTokens.push({
|
|
8411
8749
|
el: span,
|
|
@@ -8558,8 +8896,8 @@ var mountMmlPlayer = (target, mml, options = {}) => {
|
|
|
8558
8896
|
const intStep = Math.floor(step);
|
|
8559
8897
|
playStep = intStep;
|
|
8560
8898
|
const beatIndex = Math.floor(step / STEPS_PER_BEAT2) % 4;
|
|
8561
|
-
for (let
|
|
8562
|
-
beatDots[
|
|
8899
|
+
for (let i2 = 0; i2 < 4; i2++)
|
|
8900
|
+
beatDots[i2].classList.toggle("dtm-player-beat-dot--on", i2 === beatIndex);
|
|
8563
8901
|
barEl.textContent = String(Math.floor(step / STEPS_PER_BAR2) + 1);
|
|
8564
8902
|
if (!isSeeking) {
|
|
8565
8903
|
seekInput.value = String(Math.min(maxStep, Math.max(0, intStep)));
|
|
@@ -8654,11 +8992,11 @@ var mountMmlPlayer = (target, mml, options = {}) => {
|
|
|
8654
8992
|
const semis = (lt.octave ?? 0) * 12;
|
|
8655
8993
|
const count = Math.min(sorted.length, lt.syllables.length);
|
|
8656
8994
|
const notes = [];
|
|
8657
|
-
for (let
|
|
8658
|
-
const n = sorted[
|
|
8995
|
+
for (let i2 = 0; i2 < count; i2++) {
|
|
8996
|
+
const n = sorted[i2];
|
|
8659
8997
|
if (n.startStep < fromStep) continue;
|
|
8660
8998
|
notes.push({
|
|
8661
|
-
syllable: lt.syllables[
|
|
8999
|
+
syllable: lt.syllables[i2],
|
|
8662
9000
|
pitch: n.pitch + semis,
|
|
8663
9001
|
startSec: (n.startStep - fromStep) * secondsPerStep,
|
|
8664
9002
|
durationSec: n.durationSteps * secondsPerStep * gate
|
|
@@ -8669,6 +9007,10 @@ var mountMmlPlayer = (target, mml, options = {}) => {
|
|
|
8669
9007
|
model: lt.model,
|
|
8670
9008
|
volume: vocalVolumeToGain(lt.volume ?? DEFAULT_VOCAL_VOLUME),
|
|
8671
9009
|
pan: panToStereo(lt.pan ?? DEFAULT_PAN),
|
|
9010
|
+
vibrato: lt.vibrato,
|
|
9011
|
+
reverbSend: (lt.reverb ?? 0) / 100,
|
|
9012
|
+
gender: (lt.gender ?? 50) / 100,
|
|
9013
|
+
breathiness: (lt.breathiness ?? 50) / 100,
|
|
8672
9014
|
notes
|
|
8673
9015
|
};
|
|
8674
9016
|
});
|
|
@@ -8928,13 +9270,13 @@ var findZone = (ctx, fontName, zones, pitchs = []) => {
|
|
|
8928
9270
|
for (const zone of zones) {
|
|
8929
9271
|
const low = zone.keyRangeLow | 0, high = zone.keyRangeHigh | 0;
|
|
8930
9272
|
if (low > high) continue;
|
|
8931
|
-
for (let
|
|
9273
|
+
for (let i2 = low; i2 <= high; i2++) pitchs.push(i2);
|
|
8932
9274
|
}
|
|
8933
9275
|
const set = new Set(pitchs);
|
|
8934
9276
|
const map = new Map(pitchs.map((v) => [v, zones[0]]));
|
|
8935
|
-
for (let
|
|
9277
|
+
for (let i2 = zones.length - 1; i2 >= 0; i2--)
|
|
8936
9278
|
for (const v of set) {
|
|
8937
|
-
const zone = zones[
|
|
9279
|
+
const zone = zones[i2];
|
|
8938
9280
|
if (v < zone.keyRangeLow || v > zone.keyRangeHigh) continue;
|
|
8939
9281
|
set.delete(v);
|
|
8940
9282
|
map.set(v, { ...zone });
|
|
@@ -8964,13 +9306,13 @@ var adjustZone = async (ctx, fontName, zone) => {
|
|
|
8964
9306
|
const decoded = atob(zone.sample);
|
|
8965
9307
|
zone.buffer = ctx.createBuffer(1, decoded.length / 2, zone.sampleRate);
|
|
8966
9308
|
const a = zone.buffer.getChannelData(0);
|
|
8967
|
-
for (let
|
|
8968
|
-
let b1 = decoded.charCodeAt(
|
|
9309
|
+
for (let i2 = 0; i2 < decoded.length / 2; i2++) {
|
|
9310
|
+
let b1 = decoded.charCodeAt(i2 * 2), b2 = decoded.charCodeAt(i2 * 2 + 1);
|
|
8969
9311
|
if (b1 < 0) b1 = 256 + b1;
|
|
8970
9312
|
if (b2 < 0) b2 = 256 + b2;
|
|
8971
9313
|
let n = b2 * 256 + b1;
|
|
8972
9314
|
if (n >= 65536 / 2) n = n - 65536;
|
|
8973
|
-
a[
|
|
9315
|
+
a[i2] = n / 65536;
|
|
8974
9316
|
}
|
|
8975
9317
|
} else if (zone.file) {
|
|
8976
9318
|
const bytes = Uint8Array.from(atob(zone.file), (c) => c.charCodeAt(0));
|
|
@@ -9010,10 +9352,10 @@ var adjustZone = async (ctx, fontName, zone) => {
|
|
|
9010
9352
|
let loopPeak = 0;
|
|
9011
9353
|
if (oldBuf.numberOfChannels > 0) {
|
|
9012
9354
|
const ch0 = oldBuf.getChannelData(0);
|
|
9013
|
-
for (let
|
|
9014
|
-
const abs = Math.abs(ch0[
|
|
9355
|
+
for (let i2 = 0; i2 < ch0.length; i2++) {
|
|
9356
|
+
const abs = Math.abs(ch0[i2]);
|
|
9015
9357
|
if (abs > totalPeak) totalPeak = abs;
|
|
9016
|
-
if (
|
|
9358
|
+
if (i2 >= loopStartFrame && i2 < loopEndFrame) {
|
|
9017
9359
|
if (abs > loopPeak) loopPeak = abs;
|
|
9018
9360
|
}
|
|
9019
9361
|
}
|
|
@@ -9032,16 +9374,16 @@ var adjustZone = async (ctx, fontName, zone) => {
|
|
|
9032
9374
|
for (let ch = 0; ch < oldBuf.numberOfChannels; ch++) {
|
|
9033
9375
|
const oldData = oldBuf.getChannelData(ch);
|
|
9034
9376
|
const newData = newBuf.getChannelData(ch);
|
|
9035
|
-
for (let
|
|
9036
|
-
const ratio = attackLength > 1 ?
|
|
9377
|
+
for (let i2 = 0; i2 < attackLength; i2++) {
|
|
9378
|
+
const ratio = attackLength > 1 ? i2 / (attackLength - 1) : 0;
|
|
9037
9379
|
const m = 1 + (gainMultiplier - 1) * ratio;
|
|
9038
|
-
newData[
|
|
9380
|
+
newData[i2] = oldData[i2] * m;
|
|
9039
9381
|
}
|
|
9040
9382
|
let offset = attackLength;
|
|
9041
9383
|
const loopData = oldData.subarray(loopStartFrame, loopEndFrame);
|
|
9042
9384
|
const normalizedLoopData = new Float32Array(loopLengthFrame);
|
|
9043
|
-
for (let
|
|
9044
|
-
normalizedLoopData[
|
|
9385
|
+
for (let i2 = 0; i2 < loopLengthFrame; i2++) {
|
|
9386
|
+
normalizedLoopData[i2] = loopData[i2] * gainMultiplier;
|
|
9045
9387
|
}
|
|
9046
9388
|
for (let r = 0; r < repeatCount; r++) {
|
|
9047
9389
|
newData.set(normalizedLoopData, offset);
|
|
@@ -9051,8 +9393,8 @@ var adjustZone = async (ctx, fontName, zone) => {
|
|
|
9051
9393
|
const releaseData = oldData.subarray(loopEndFrame);
|
|
9052
9394
|
if (gainMultiplier !== 1) {
|
|
9053
9395
|
const normalizedRelease = new Float32Array(releaseLength);
|
|
9054
|
-
for (let
|
|
9055
|
-
normalizedRelease[
|
|
9396
|
+
for (let i2 = 0; i2 < releaseLength; i2++) {
|
|
9397
|
+
normalizedRelease[i2] = releaseData[i2] * gainMultiplier;
|
|
9056
9398
|
}
|
|
9057
9399
|
newData.set(normalizedRelease, offset);
|
|
9058
9400
|
} else {
|
|
@@ -9248,10 +9590,10 @@ var buildDisplayLines = (chords, eventsCount) => {
|
|
|
9248
9590
|
if (segments.length === 0) continue;
|
|
9249
9591
|
const hasMultiSeg = segments.length > 1;
|
|
9250
9592
|
const parts = [];
|
|
9251
|
-
for (let
|
|
9252
|
-
if (hasMultiSeg &&
|
|
9593
|
+
for (let i2 = 0; i2 < segments.length; i2++) {
|
|
9594
|
+
if (hasMultiSeg && i2 > 0)
|
|
9253
9595
|
parts.push({ text: "|", isChord: false, eventIdx: -1 });
|
|
9254
|
-
const bar = segments[
|
|
9596
|
+
const bar = segments[i2].trim();
|
|
9255
9597
|
if (!bar) continue;
|
|
9256
9598
|
const splitAt = [];
|
|
9257
9599
|
for (let j = 0; j < bar.length; j++) {
|
|
@@ -10370,6 +10712,7 @@ var buildUI = (target, options) => {
|
|
|
10370
10712
|
<button class="dtm-iconbtn" data-dtm="next-bar" title="1\u5C0F\u7BC0\u5F8C">${icon("chevronRight")}</button>
|
|
10371
10713
|
<label class="dtm-toggle"><input type="checkbox" data-dtm="solo"><span>\u30BD\u30ED</span></label>
|
|
10372
10714
|
<span class="dtm-topbar-loading dtm-blink" data-dtm="topbar-loading">... LOADING ...</span>
|
|
10715
|
+
<button class="dtm-clip-badge dtm-hidden" data-dtm="clip-badge" title="\u97F3\u5272\u308C\u691C\u77E5\uFF08\u30AF\u30EA\u30C3\u30AF\u3067\u6D88\u3059\uFF09">CLIP</button>
|
|
10373
10716
|
<span class="dtm-grow"></span>
|
|
10374
10717
|
<span class="dtm-label">BPM</span>
|
|
10375
10718
|
<input type="number" class="dtm-input dtm-input--num" data-dtm="bpm" value="${defaultBpm}" min="20" max="300">
|
|
@@ -10407,13 +10750,8 @@ var buildUI = (target, options) => {
|
|
|
10407
10750
|
<div class="dtm-hscroll" data-dtm="hscroll"><div class="dtm-hscroll-thumb" data-dtm="hscroll-thumb"></div></div>
|
|
10408
10751
|
|
|
10409
10752
|
<details class="dtm-panel" open>
|
|
10410
|
-
<summary>\u30C8\u30E9\u30C3\u30AF\u8A2D\u5B9A</summary>
|
|
10753
|
+
<summary>\u500B\u5225\u30C8\u30E9\u30C3\u30AF\u8A2D\u5B9A</summary>
|
|
10411
10754
|
<div class="dtm-panel-body">
|
|
10412
|
-
<div class="dtm-row">
|
|
10413
|
-
<span class="dtm-label">\u5168\u4F53\u97F3\u91CF</span>
|
|
10414
|
-
<input type="range" class="dtm-range dtm-grow" data-dtm="master-volume" value="50" min="0" max="100">
|
|
10415
|
-
<span class="dtm-label" data-dtm="master-volume-label">50%</span>
|
|
10416
|
-
</div>
|
|
10417
10755
|
<div class="dtm-track-body" data-dtm="track-body"></div>
|
|
10418
10756
|
</div>
|
|
10419
10757
|
</details>
|
|
@@ -10446,6 +10784,29 @@ var buildUI = (target, options) => {
|
|
|
10446
10784
|
</div>
|
|
10447
10785
|
</details>
|
|
10448
10786
|
|
|
10787
|
+
<details class="dtm-panel" open>
|
|
10788
|
+
<summary>\u5168\u4F53\u30C8\u30E9\u30C3\u30AF\u8A2D\u5B9A</summary>
|
|
10789
|
+
<div class="dtm-panel-body">
|
|
10790
|
+
<div data-dtm="preset-select-slot"></div>
|
|
10791
|
+
<div class="dtm-row">
|
|
10792
|
+
<span class="dtm-label">\u5168\u4F53\u97F3\u91CF</span>
|
|
10793
|
+
<input type="range" class="dtm-range dtm-grow" data-dtm="master-volume" value="50" min="0" max="100">
|
|
10794
|
+
<span class="dtm-label" data-dtm="master-volume-label">50%</span>
|
|
10795
|
+
</div>
|
|
10796
|
+
<div class="dtm-row">
|
|
10797
|
+
<button class="dtm-btn dtm-btn--ghost dtm-btn--xs" data-dtm="auto-master" title="\u97F3\u5727\u30FB\u30B9\u30C6\u30EC\u30AA\u5E45\u30FB\u30EA\u30D0\u30FC\u30D6\u3092\u5546\u696D\u66F2\u5BC4\u308A\u306E\u5024\u306B\u4E00\u62EC\u8A2D\u5B9A\u3057\u307E\u3059">\u304A\u307E\u304B\u305B\u30DE\u30B9\u30BF\u30EA\u30F3\u30B0</button>
|
|
10798
|
+
<button class="dtm-infobtn" data-dtm="auto-master-info" title="\u304A\u307E\u304B\u305B\u30DE\u30B9\u30BF\u30EA\u30F3\u30B0\u306E\u89E3\u8AAC">${icon("info", 12)}</button>
|
|
10799
|
+
<span class="dtm-grow"></span>
|
|
10800
|
+
</div>
|
|
10801
|
+
<div class="dtm-row">
|
|
10802
|
+
<span class="dtm-label">\u30EA\u30D0\u30FC\u30D6</span>
|
|
10803
|
+
<input type="range" class="dtm-range dtm-grow" data-dtm="reverb-amount" value="0" min="0" max="100" aria-label="\u30DE\u30B9\u30BF\u30EA\u30D0\u30FC\u30D6\uFF08\u5168\u30C8\u30E9\u30C3\u30AF\u3078\u4E00\u5F8B\u306B\u639B\u304B\u308B\u6B8B\u97FF\uFF09">
|
|
10804
|
+
<span class="dtm-label" data-dtm="reverb-amount-label">0%</span>
|
|
10805
|
+
<button class="dtm-infobtn" data-dtm="reverb-amount-info" title="\u30DE\u30B9\u30BF\u30EA\u30D0\u30FC\u30D6\u306E\u89E3\u8AAC">${icon("info", 12)}</button>
|
|
10806
|
+
</div>
|
|
10807
|
+
</div>
|
|
10808
|
+
</details>
|
|
10809
|
+
|
|
10449
10810
|
<details class="dtm-panel">
|
|
10450
10811
|
<summary>\u30C9\u30E9\u30E0\u8A2D\u5B9A</summary>
|
|
10451
10812
|
<div class="dtm-panel-body">
|
|
@@ -10611,6 +10972,7 @@ var buildUI = (target, options) => {
|
|
|
10611
10972
|
prevBarBtn: sel("prev-bar"),
|
|
10612
10973
|
nextBarBtn: sel("next-bar"),
|
|
10613
10974
|
soloCheckbox: sel("solo"),
|
|
10975
|
+
clipBadge: sel("clip-badge"),
|
|
10614
10976
|
toolPen: sel("tool-pen"),
|
|
10615
10977
|
toolSelect: sel("tool-select"),
|
|
10616
10978
|
toolEraser: sel("tool-eraser"),
|
|
@@ -10637,6 +10999,11 @@ var buildUI = (target, options) => {
|
|
|
10637
10999
|
hScrollThumb: sel("hscroll-thumb"),
|
|
10638
11000
|
masterVolume: sel("master-volume"),
|
|
10639
11001
|
masterVolumeLabel: sel("master-volume-label"),
|
|
11002
|
+
reverbAmount: sel("reverb-amount"),
|
|
11003
|
+
reverbAmountLabel: sel("reverb-amount-label"),
|
|
11004
|
+
reverbAmountInfoBtn: sel("reverb-amount-info"),
|
|
11005
|
+
autoMasterBtn: sel("auto-master"),
|
|
11006
|
+
autoMasterInfoBtn: sel("auto-master-info"),
|
|
10640
11007
|
trackTabs: sel("track-tabs"),
|
|
10641
11008
|
trackBody: sel("track-body"),
|
|
10642
11009
|
drumSelect: sel("drum-select"),
|
|
@@ -10805,16 +11172,16 @@ var generateRandomPattern = (core, options) => {
|
|
|
10805
11172
|
const scale = SCALES[Math.floor(Math.random() * SCALES.length)];
|
|
10806
11173
|
const rootOffset = Math.floor(Math.random() * 12);
|
|
10807
11174
|
const availablePitches = [];
|
|
10808
|
-
for (let
|
|
10809
|
-
const noteInOctave = (
|
|
10810
|
-
if (scale.includes(noteInOctave)) availablePitches.push(basePitch +
|
|
11175
|
+
for (let i2 = 0; i2 < 12; i2++) {
|
|
11176
|
+
const noteInOctave = (i2 - rootOffset + 12) % 12;
|
|
11177
|
+
if (scale.includes(noteInOctave)) availablePitches.push(basePitch + i2);
|
|
10811
11178
|
}
|
|
10812
11179
|
core.beginBatch();
|
|
10813
11180
|
for (let bar = 0; bar < numBars; bar++) {
|
|
10814
11181
|
const barStart = startStep + bar * stepsPerBar;
|
|
10815
11182
|
const numNotes = Math.floor(Math.random() * 4) + 2;
|
|
10816
11183
|
const occupied = /* @__PURE__ */ new Set();
|
|
10817
|
-
for (let
|
|
11184
|
+
for (let i2 = 0; i2 < numNotes; i2++) {
|
|
10818
11185
|
const stepInRange = Math.floor(Math.random() * (stepsPerBar / noteLength)) * noteLength;
|
|
10819
11186
|
const step = barStart + stepInRange;
|
|
10820
11187
|
if (occupied.has(step)) continue;
|
|
@@ -10915,10 +11282,10 @@ var STEPS_PER_BEAT3 = 48;
|
|
|
10915
11282
|
var analyzeMidiTracks = (midi) => {
|
|
10916
11283
|
const { tracks } = midi;
|
|
10917
11284
|
const result = [];
|
|
10918
|
-
for (let
|
|
11285
|
+
for (let i2 = 0; i2 < tracks.length; i2++) {
|
|
10919
11286
|
const notes = [];
|
|
10920
11287
|
let currentTime = 0;
|
|
10921
|
-
for (const event of tracks[
|
|
11288
|
+
for (const event of tracks[i2]) {
|
|
10922
11289
|
currentTime += event.delta;
|
|
10923
11290
|
if (event.noteOn && event.noteOn.velocity > 0) {
|
|
10924
11291
|
notes.push({
|
|
@@ -10941,8 +11308,8 @@ var analyzeMidiTracks = (midi) => {
|
|
|
10941
11308
|
const editableNotes = validNotes.filter((n) => n.channel !== 9);
|
|
10942
11309
|
if (validNotes.length > 0 && editableNotes.length === 0) continue;
|
|
10943
11310
|
result.push({
|
|
10944
|
-
index:
|
|
10945
|
-
name: `Ch${
|
|
11311
|
+
index: i2,
|
|
11312
|
+
name: `Ch${i2 + 1}`,
|
|
10946
11313
|
noteCount: editableNotes.length,
|
|
10947
11314
|
selected: editableNotes.length > 0
|
|
10948
11315
|
});
|
|
@@ -10989,8 +11356,8 @@ var extractMidiPlacements = (midi, selectedTrackIndices) => {
|
|
|
10989
11356
|
const pitch = noteOff.noteNumber;
|
|
10990
11357
|
const channel = event.channel ?? 0;
|
|
10991
11358
|
if (channelNotes[channel]) {
|
|
10992
|
-
for (let
|
|
10993
|
-
const note = channelNotes[channel][
|
|
11359
|
+
for (let i2 = channelNotes[channel].length - 1; i2 >= 0; i2--) {
|
|
11360
|
+
const note = channelNotes[channel][i2];
|
|
10994
11361
|
if (note.pitch === pitch && note.end === null) {
|
|
10995
11362
|
note.end = currentTime;
|
|
10996
11363
|
break;
|
|
@@ -11020,10 +11387,10 @@ var extractMidiPlacements = (midi, selectedTrackIndices) => {
|
|
|
11020
11387
|
const avgPitch = validNotes.reduce((sum, n) => sum + n.pitch, 0) / validNotes.length;
|
|
11021
11388
|
let maxSimultaneous = 0;
|
|
11022
11389
|
const sortedNotes = [...validNotes].sort((a, b) => a.start - b.start);
|
|
11023
|
-
for (let
|
|
11390
|
+
for (let i2 = 0; i2 < sortedNotes.length; i2++) {
|
|
11024
11391
|
let simultaneous = 1;
|
|
11025
|
-
for (let j =
|
|
11026
|
-
if (sortedNotes[j].start < sortedNotes[
|
|
11392
|
+
for (let j = i2 + 1; j < sortedNotes.length; j++) {
|
|
11393
|
+
if (sortedNotes[j].start < sortedNotes[i2].end) {
|
|
11027
11394
|
simultaneous++;
|
|
11028
11395
|
}
|
|
11029
11396
|
}
|
|
@@ -11034,14 +11401,14 @@ var extractMidiPlacements = (midi, selectedTrackIndices) => {
|
|
|
11034
11401
|
const blocks = [];
|
|
11035
11402
|
let blockStart = sortedNotes[0].start;
|
|
11036
11403
|
let blockEnd = sortedNotes[0].end;
|
|
11037
|
-
for (let
|
|
11038
|
-
const gap = sortedNotes[
|
|
11404
|
+
for (let i2 = 1; i2 < sortedNotes.length; i2++) {
|
|
11405
|
+
const gap = sortedNotes[i2].start - sortedNotes[i2 - 1].end;
|
|
11039
11406
|
if (gap >= ticksPerBar) {
|
|
11040
11407
|
blocks.push({ start: blockStart, end: blockEnd });
|
|
11041
|
-
blockStart = sortedNotes[
|
|
11042
|
-
blockEnd = sortedNotes[
|
|
11408
|
+
blockStart = sortedNotes[i2].start;
|
|
11409
|
+
blockEnd = sortedNotes[i2].end;
|
|
11043
11410
|
} else {
|
|
11044
|
-
blockEnd = sortedNotes[
|
|
11411
|
+
blockEnd = sortedNotes[i2].end;
|
|
11045
11412
|
}
|
|
11046
11413
|
}
|
|
11047
11414
|
blocks.push({ start: blockStart, end: blockEnd });
|
|
@@ -11155,9 +11522,9 @@ var extractMidiPlacementsByTrack = (midi, selectedIndices, trackIds) => {
|
|
|
11155
11522
|
const noteOff = event.noteOff || event.noteOn;
|
|
11156
11523
|
if (noteOff) {
|
|
11157
11524
|
const pitch = noteOff.noteNumber;
|
|
11158
|
-
for (let
|
|
11159
|
-
if (active[
|
|
11160
|
-
active[
|
|
11525
|
+
for (let i2 = active.length - 1; i2 >= 0; i2--) {
|
|
11526
|
+
if (active[i2].pitch === pitch && active[i2].end === null) {
|
|
11527
|
+
active[i2].end = currentTime;
|
|
11161
11528
|
break;
|
|
11162
11529
|
}
|
|
11163
11530
|
}
|
|
@@ -11322,17 +11689,17 @@ var extractDrumPatternFromNotes = (rawNotes, drumFont = "FluidR3_GM_sf2_file:0")
|
|
|
11322
11689
|
let prev = bList[0];
|
|
11323
11690
|
const parts = key.split("_");
|
|
11324
11691
|
const noteObj = { step: +parts[0], pitch: +parts[1], velocity: +parts[2] };
|
|
11325
|
-
for (let
|
|
11326
|
-
if (
|
|
11692
|
+
for (let i2 = 1; i2 <= bList.length; i2++) {
|
|
11693
|
+
if (i2 === bList.length || bList[i2] !== prev + 1) {
|
|
11327
11694
|
const rKey = `${start}-${prev}`;
|
|
11328
11695
|
if (!rangeMap[rKey]) rangeMap[rKey] = [];
|
|
11329
11696
|
rangeMap[rKey].push(noteObj);
|
|
11330
|
-
if (
|
|
11331
|
-
start = bList[
|
|
11332
|
-
prev = bList[
|
|
11697
|
+
if (i2 < bList.length) {
|
|
11698
|
+
start = bList[i2];
|
|
11699
|
+
prev = bList[i2];
|
|
11333
11700
|
}
|
|
11334
11701
|
} else {
|
|
11335
|
-
prev = bList[
|
|
11702
|
+
prev = bList[i2];
|
|
11336
11703
|
}
|
|
11337
11704
|
}
|
|
11338
11705
|
}
|
|
@@ -11709,8 +12076,8 @@ var drawHeader = () => {
|
|
|
11709
12076
|
(g_draw_offset_x + g_header_canvas.width) / (stepsPerBar * stepWidth)
|
|
11710
12077
|
);
|
|
11711
12078
|
for (let bar = startBar; bar <= endBar + 1; bar++) {
|
|
11712
|
-
const
|
|
11713
|
-
const screenX =
|
|
12079
|
+
const x2 = bar * stepsPerBar * stepWidth;
|
|
12080
|
+
const screenX = x2;
|
|
11714
12081
|
g_header_ctx.beginPath();
|
|
11715
12082
|
g_header_ctx.moveTo(screenX, 0);
|
|
11716
12083
|
g_header_ctx.lineTo(screenX, HEADER_HEIGHT);
|
|
@@ -11757,11 +12124,11 @@ var drawGrid = (noteLengthSteps = 1) => {
|
|
|
11757
12124
|
const startX = Math.floor(g_draw_offset_x / (stepWidth * gridStep)) * stepWidth * gridStep;
|
|
11758
12125
|
const endX = g_draw_offset_x + g_grid_canvas.width;
|
|
11759
12126
|
const lineStep = stepWidth * gridStep;
|
|
11760
|
-
for (let
|
|
11761
|
-
const step =
|
|
12127
|
+
for (let x2 = startX; x2 <= endX; x2 += lineStep) {
|
|
12128
|
+
const step = x2 / stepWidth;
|
|
11762
12129
|
const isBarLine = step % stepsPerBar === 0;
|
|
11763
12130
|
const isNoteLine = step % gridStep === 0;
|
|
11764
|
-
const screenX =
|
|
12131
|
+
const screenX = x2 - g_draw_offset_x;
|
|
11765
12132
|
g_grid_ctx.beginPath();
|
|
11766
12133
|
g_grid_ctx.strokeStyle = isBarLine ? "#3d405b" : isNoteLine ? "#242840" : "#1a1d30";
|
|
11767
12134
|
g_grid_ctx.lineWidth = isBarLine ? 2 : 1;
|
|
@@ -11823,26 +12190,26 @@ var drawSelectedNotes = (notes, selectedIds, baseColor = [59, 130, 246, 1]) => {
|
|
|
11823
12190
|
var getXY = (e) => {
|
|
11824
12191
|
const { clientX, clientY } = e;
|
|
11825
12192
|
const rect = g_grid_canvas.getBoundingClientRect();
|
|
11826
|
-
const
|
|
12193
|
+
const x2 = Math.floor(clientX - rect.left);
|
|
11827
12194
|
const y = Math.floor(clientY - rect.top);
|
|
11828
|
-
return [
|
|
12195
|
+
return [x2, y, e.buttons];
|
|
11829
12196
|
};
|
|
11830
12197
|
var getGridPosition = (e) => {
|
|
11831
|
-
const [
|
|
12198
|
+
const [x2, y] = getXY(e);
|
|
11832
12199
|
const { keyCount, pitchRangeStart, keyHeight, stepWidth } = g_config;
|
|
11833
|
-
const step = Math.floor((
|
|
12200
|
+
const step = Math.floor((x2 + g_draw_offset_x) / stepWidth);
|
|
11834
12201
|
const absoluteY = y + g_draw_offset_y;
|
|
11835
12202
|
const yIndex = Math.floor(absoluteY / keyHeight);
|
|
11836
12203
|
const pitch = keyCount - 1 - yIndex + pitchRangeStart;
|
|
11837
|
-
return { step, pitch, x, y };
|
|
12204
|
+
return { step, pitch, x: x2, y };
|
|
11838
12205
|
};
|
|
11839
12206
|
var onClick = (callback) => {
|
|
11840
12207
|
g_grid_canvas.addEventListener(
|
|
11841
12208
|
"click",
|
|
11842
12209
|
(e) => {
|
|
11843
|
-
const [
|
|
12210
|
+
const [x2, y] = getXY(e);
|
|
11844
12211
|
const { keyCount, pitchRangeStart, keyHeight, stepWidth } = g_config;
|
|
11845
|
-
const step = Math.floor((
|
|
12212
|
+
const step = Math.floor((x2 + g_draw_offset_x) / stepWidth);
|
|
11846
12213
|
const absoluteY = y + g_draw_offset_y;
|
|
11847
12214
|
const yIndex = Math.floor(absoluteY / keyHeight);
|
|
11848
12215
|
const pitch = keyCount - 1 - yIndex + pitchRangeStart;
|
|
@@ -11854,8 +12221,8 @@ var onClick = (callback) => {
|
|
|
11854
12221
|
);
|
|
11855
12222
|
g_grid_canvas.addEventListener("contextmenu", (e) => e.preventDefault());
|
|
11856
12223
|
};
|
|
11857
|
-
var setDrawOffset = (
|
|
11858
|
-
g_draw_offset_x =
|
|
12224
|
+
var setDrawOffset = (x2, y) => {
|
|
12225
|
+
g_draw_offset_x = x2;
|
|
11859
12226
|
g_draw_offset_y = y;
|
|
11860
12227
|
drawKeyboard();
|
|
11861
12228
|
drawHeader();
|
|
@@ -12170,12 +12537,12 @@ var MMLCore = class _MMLCore {
|
|
|
12170
12537
|
currentCursor += steps;
|
|
12171
12538
|
}
|
|
12172
12539
|
};
|
|
12173
|
-
for (let
|
|
12174
|
-
const startStep = sortedSteps[
|
|
12540
|
+
for (let i2 = 0; i2 < sortedSteps.length; i2++) {
|
|
12541
|
+
const startStep = sortedSteps[i2];
|
|
12175
12542
|
const notes = notesByStep.get(startStep);
|
|
12176
12543
|
if (!notes) continue;
|
|
12177
12544
|
fillRests(startStep);
|
|
12178
|
-
const nextStart = sortedSteps[
|
|
12545
|
+
const nextStart = sortedSteps[i2 + 1] ?? endStep;
|
|
12179
12546
|
const physicsLimit = nextStart - currentCursor;
|
|
12180
12547
|
if (physicsLimit < MIN_STEP) {
|
|
12181
12548
|
continue;
|
|
@@ -12240,10 +12607,10 @@ var decomposeToMonophonic = (notes) => {
|
|
|
12240
12607
|
for (const note of sorted) {
|
|
12241
12608
|
let assigned = -1;
|
|
12242
12609
|
let minEnd = Infinity;
|
|
12243
|
-
for (let
|
|
12244
|
-
if (trackEnds[
|
|
12245
|
-
minEnd = trackEnds[
|
|
12246
|
-
assigned =
|
|
12610
|
+
for (let i2 = 0; i2 < tracks.length; i2++) {
|
|
12611
|
+
if (trackEnds[i2] <= note.startStep && trackEnds[i2] < minEnd) {
|
|
12612
|
+
minEnd = trackEnds[i2];
|
|
12613
|
+
assigned = i2;
|
|
12247
12614
|
}
|
|
12248
12615
|
}
|
|
12249
12616
|
if (assigned === -1) {
|
|
@@ -12299,6 +12666,89 @@ var CHORD_INFO_HTML2 = `
|
|
|
12299
12666
|
</ul>
|
|
12300
12667
|
</div>
|
|
12301
12668
|
`;
|
|
12669
|
+
var VIBRATO_INFO_HTML = `
|
|
12670
|
+
<div class="dtm-modal-body-content">
|
|
12671
|
+
<h4>\u4F55\u3092\u3059\u308B\u8A2D\u5B9A\u304B</h4>
|
|
12672
|
+
<p>ON\u306B\u3059\u308B\u3068\u3001\u4E00\u5B9A\u306E\u9577\u3055\uFF08\u7D040.35\u79D2\uFF09\u4EE5\u4E0A\u306E\u97F3\u7B26\uFF08\u30ED\u30F3\u30B0\u30C8\u30FC\u30F3\uFF09\u306B\u3060\u3051\u3001\u81EA\u52D5\u3067\u30D4\u30C3\u30C1\u304C\u5C0F\u523B\u307F\u306B\u63FA\u308C\u308B\u6B4C\u5531\u8868\u73FE\uFF08\u30D3\u30D6\u30E9\u30FC\u30C8\uFF09\u304C\u639B\u304B\u308A\u307E\u3059\u3002</p>
|
|
12673
|
+
<h4>\u77ED\u3044\u97F3\u7B26\u306B\u639B\u304B\u3089\u306A\u3044\u7406\u7531</h4>
|
|
12674
|
+
<p>1\u5468\u671F\u3082\u63FA\u308C\u304D\u3089\u306A\u3044\u3046\u3061\u306B\u6B21\u306E\u97F3\u3078\u79FB\u3063\u3066\u3057\u307E\u3044\u3001\u30D3\u30D6\u30E9\u30FC\u30C8\u3068\u3044\u3046\u3088\u308A\u5358\u306A\u308B\u97F3\u7A0B\u306E\u30D6\u30EC\u3068\u3057\u3066\u4E0D\u81EA\u7136\u306B\u805E\u3053\u3048\u308B\u305F\u3081\u3067\u3059\u3002</p>
|
|
12675
|
+
<h4>\u4ED6\u306E\u8A2D\u5B9A\u3068\u306E\u517C\u306D\u5408\u3044</h4>
|
|
12676
|
+
<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>
|
|
12677
|
+
</div>
|
|
12678
|
+
`;
|
|
12679
|
+
var GENDER_INFO_HTML = `
|
|
12680
|
+
<div class="dtm-modal-body-content">
|
|
12681
|
+
<h4>\u4F55\u3092\u3059\u308B\u8A2D\u5B9A\u304B</h4>
|
|
12682
|
+
<p>\u30D4\u30C3\u30C1\uFF08\u97F3\u306E\u9AD8\u3055\uFF09\u306F\u305D\u306E\u307E\u307E\u306B\u3001\u58F0\u306E\u592A\u3055/\u7D30\u3055\uFF08\u30D5\u30A9\u30EB\u30DE\u30F3\u30C8\uFF1D\u58F0\u9053\u306E\u5171\u9CF4\u3001\u5E74\u9F62\u30FB\u6027\u5225\u611F\u306E\u5370\u8C61\uFF09\u3060\u3051\u3092\u52D5\u304B\u3057\u307E\u3059\u300250\u304C\u7121\u5909\u5316\u300150\u672A\u6E80\u3067\u4F4E\u3081/\u592A\u3081\uFF08\u5927\u4EBA\u3073\u308B\uFF09\u300150\u8D85\u3067\u9AD8\u3081/\u7D30\u3081\uFF08\u82E5\u304F/\u660E\u308B\u304F\uFF09\u306B\u5BC4\u308A\u307E\u3059\u3002</p>
|
|
12683
|
+
<h4>\u30AA\u30AF\u30BF\u30FC\u30D6\u30B7\u30D5\u30C8\u3068\u306E\u9055\u3044</h4>
|
|
12684
|
+
<p>\u30AA\u30AF\u30BF\u30FC\u30D6\u306F\u97F3\u7A0B\u305D\u306E\u3082\u306E\u3092\u4E0A\u4E0B\u3055\u305B\u307E\u3059\u304C\u3001\u30B8\u30A7\u30F3\u30C0\u30FC\u306F\u97F3\u7A0B\u3092\u5909\u3048\u305A\u306B\u58F0\u8272\u3060\u3051\u3092\u52D5\u304B\u3057\u307E\u3059\u3002\u300C\u9AD8\u3044\u58F0\u306E\u307E\u307E\u5927\u4EBA\u3073\u3055\u305B\u308B\u300D\u300C\u4F4E\u3044\u58F0\u306E\u307E\u307E\u82E5\u3005\u3057\u304F\u3059\u308B\u300D\u3068\u3044\u3063\u305F\u3001\u97F3\u7A0B\u3068\u58F0\u8CEA\u3092\u5225\u3005\u306B\u8ABF\u6574\u3057\u305F\u3044\u3068\u304D\u306B\u4F7F\u3044\u307E\u3059\u3002</p>
|
|
12685
|
+
<h4>\u4ED6\u306E\u8A2D\u5B9A\u3068\u306E\u517C\u306D\u5408\u3044</h4>
|
|
12686
|
+
<p>\u30D6\u30EC\u30B7\u30CD\u30B9\u3068\u7D44\u307F\u5408\u308F\u305B\u3066\u58F0\u306E\u30AD\u30E3\u30E9\u30AF\u30BF\u30FC\u3092\u4F5C\u308A\u307E\u3059\uFF08\u4F8B: \u4F4E\u3081+\u606F\u591A\u3081\u3067\u6E0B\u3044/\u5927\u4EBA\u3063\u307D\u3044\u5370\u8C61\u3001\u9AD8\u3081+\u606F\u5C11\u306A\u3081\u3067\u5143\u6C17/\u82E5\u3005\u3057\u3044\u5370\u8C61\uFF09\u3002koe\u97F3\u6E90\uFF08UTAU\u7531\u6765\u306E.koe\u97F3\u6E90\uFF09\u9650\u5B9A\u306E\u52B9\u679C\u3067\u3001klatt\uFF08\u5185\u8535\u306E\u7C21\u6613\u5408\u6210\uFF09\u3067\u306F\u5909\u5316\u3057\u307E\u305B\u3093\u3002</p>
|
|
12687
|
+
</div>
|
|
12688
|
+
`;
|
|
12689
|
+
var BREATHINESS_INFO_HTML = `
|
|
12690
|
+
<div class="dtm-modal-body-content">
|
|
12691
|
+
<h4>\u4F55\u3092\u3059\u308B\u8A2D\u5B9A\u304B</h4>
|
|
12692
|
+
<p>\u606F\u6210\u5206\u306E\u91CF\u3067\u3059\u300250\u304C\u7121\u5909\u5316\u3001\u5927\u304D\u3044\u307B\u3069\u606F\u3063\u307D\u304F\uFF08\u3055\u3055\u3084\u304D\u5BC4\u308A\uFF09\u3001\u5C0F\u3055\u3044\u307B\u3069\u82AF\u306E\u3042\u308B\u58F0\u306B\u306A\u308A\u307E\u3059\u3002</p>
|
|
12693
|
+
<h4>\u4E0A\u3052\u3059\u304E\u308B\u3068\u3069\u3046\u306A\u308B\u304B</h4>
|
|
12694
|
+
<p>\u30ED\u30F3\u30B0\u30C8\u30FC\u30F3\u3067\u97F3\u7A0B\u611F\u304C\u8584\u308C\u3066\u805E\u3053\u3048\u307E\u3059\uFF08\u606F\u306E\u97F3\u304C\u30D4\u30C3\u30C1\u611F\u3092\u96A0\u3059\u305F\u3081\uFF09\u3002\u56C1\u304F\u3088\u3046\u306A\u30D0\u30E9\u30FC\u30C9\u8868\u73FE\u306B\u306F\u52B9\u679C\u7684\u3067\u3059\u304C\u3001\u4E0A\u3052\u3059\u304E\u308B\u3068\u30E1\u30ED\u30C7\u30A3\u304C\u4F1D\u308F\u308A\u306B\u304F\u304F\u306A\u308A\u307E\u3059\u3002</p>
|
|
12695
|
+
<h4>\u4ED6\u306E\u8A2D\u5B9A\u3068\u306E\u517C\u306D\u5408\u3044</h4>
|
|
12696
|
+
<p>\u81EA\u52D5\u30D3\u30D6\u30E9\u30FC\u30C8\u3068\u7D44\u307F\u5408\u308F\u305B\u308B\u3068\u3001\u63FA\u308C\u306A\u304C\u3089\u606F\u3063\u307D\u3044\u3001\u3088\u308A\u30A8\u30E2\u30FC\u30B7\u30E7\u30CA\u30EB\u306A\u8868\u73FE\u306B\u306A\u308A\u3084\u3059\u3044\u3067\u3059\u3002koe\u97F3\u6E90\uFF08UTAU\u7531\u6765\u306E.koe\u97F3\u6E90\uFF09\u9650\u5B9A\u306E\u52B9\u679C\u3067\u3001klatt\uFF08\u5185\u8535\u306E\u7C21\u6613\u5408\u6210\uFF09\u3067\u306F\u5909\u5316\u3057\u307E\u305B\u3093\u3002</p>
|
|
12697
|
+
</div>
|
|
12698
|
+
`;
|
|
12699
|
+
var LYRIC_REVERB_INFO_HTML = `
|
|
12700
|
+
<div class="dtm-modal-body-content">
|
|
12701
|
+
<h4>\u4F55\u3092\u3059\u308B\u8A2D\u5B9A\u304B</h4>
|
|
12702
|
+
<p>\u3053\u306E\u30DC\u30FC\u30AB\u30EB\u30C8\u30E9\u30C3\u30AF\u304B\u3089\u3001\u66F2\u5168\u4F53\u306B\u639B\u304B\u308B\u300C\u30DE\u30B9\u30BF\u30EA\u30D0\u30FC\u30D6\u300D\u3078\u3069\u308C\u3060\u3051\u97F3\u3092\u9001\u308B\u304B\u3092\u6C7A\u3081\u307E\u3059\uFF080\u3067\u9001\u3089\u306A\u3044\uFF1D\u30C9\u30E9\u30A4\u3001100\u3067\u76EE\u4E00\u676F\u9001\u308B\uFF09\u3002</p>
|
|
12703
|
+
<h4>\u30DE\u30B9\u30BF\u306E\u300C\u30EA\u30D0\u30FC\u30D6\u300D\u3064\u307E\u307F\u3068\u306E\u95A2\u4FC2\uFF08\u91CD\u8981\uFF09</h4>
|
|
12704
|
+
<p>\u30C8\u30E9\u30C3\u30AF\u8A2D\u5B9A\u30D1\u30CD\u30EB\u306B\u3042\u308B\u30DE\u30B9\u30BF\u306E\u300C\u30EA\u30D0\u30FC\u30D6\u300D\u3064\u307E\u307F\u304C0%\u3060\u3068\u3001\u3053\u3053\u3092\u3044\u304F\u3089\u4E0A\u3052\u3066\u3082\u7121\u97F3\u306E\u307E\u307E\u3067\u3059\u3002\u300C\u9001\u308A\u91CF\uFF08\u3053\u306E\u30C8\u30E9\u30C3\u30AF\u304C\u3069\u308C\u3060\u3051\u63D0\u4F9B\u3059\u308B\u304B\uFF09\u300D\u3068\u300C\u30DE\u30B9\u30BF\u306E\u6B8B\u97FF\u8A2D\u5B9A\uFF08\u5B9F\u969B\u306B\u3069\u3093\u306A\u97FF\u304D\u304C\u639B\u304B\u308B\u304B\uFF09\u300D\u306E\u4E8C\u6BB5\u69CB\u3048\u306B\u306A\u3063\u3066\u3044\u308B\u305F\u3081\u3067\u3059\u3002\u4E21\u65B9\u3092\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044\u3002</p>
|
|
12705
|
+
<h4>\u639B\u3051\u3059\u304E\u308B\u3068\u3069\u3046\u306A\u308B\u304B</h4>
|
|
12706
|
+
<p>\u6B8B\u97FF\u3067\u97F3\u304C\u6EF2\u307F\u3001\u6B4C\u8A5E\u304C\u805E\u304D\u53D6\u308A\u306B\u304F\u304F\u306A\u308A\u307E\u3059\u3002\u30C9\u30E9\u30A4\u306A\u30DC\u30FC\u30AB\u30EB\u306F\u300C\u8FD1\u3044\u300D\u300C\u524D\u306B\u51FA\u308B\u300D\u5370\u8C61\u3001\u30EA\u30D0\u30FC\u30D6\u305F\u3063\u3077\u308A\u306E\u30DC\u30FC\u30AB\u30EB\u306F\u300C\u5965\u884C\u304D\u304C\u3042\u308B\u300D\u300C\u5E7B\u60F3\u7684\u300D\u306A\u5370\u8C61\u306B\u306A\u308A\u307E\u3059\u3002\u8868\u73FE\u3057\u305F\u3044\u8DDD\u96E2\u611F\u306B\u5408\u308F\u305B\u3066\u8ABF\u6574\u3057\u3066\u304F\u3060\u3055\u3044\u3002</p>
|
|
12707
|
+
</div>
|
|
12708
|
+
`;
|
|
12709
|
+
var MASTER_REVERB_INFO_HTML = `
|
|
12710
|
+
<div class="dtm-modal-body-content">
|
|
12711
|
+
<h4>\u4F55\u3092\u3059\u308B\u8A2D\u5B9A\u304B</h4>
|
|
12712
|
+
<p>\u66F2\u5168\u4F53\u306B\u4E00\u5F8B\u3067\u639B\u304B\u308B\u6B8B\u97FF\uFF08\u90E8\u5C4B\u9CF4\u308A\u30FB\u7A7A\u9593\u306E\u97FF\u304D\uFF09\u3067\u3059\u30020%\u3067\u5B8C\u5168\u306B\u30C9\u30E9\u30A4\uFF08\u97FF\u304D\u306A\u3057\uFF09\u3001\u4E0A\u3052\u308B\u307B\u3069\u5E83\u3044\u7A7A\u9593\u3067\u9CF4\u3063\u3066\u3044\u308B\u3088\u3046\u306A\u5965\u884C\u304D\u304C\u51FA\u307E\u3059\u3002</p>
|
|
12713
|
+
<h4>\u5404\u30C8\u30E9\u30C3\u30AF\u306E\u300C\u30EA\u30D0\u30FC\u30D6\u9001\u308A\u300D\u3068\u306E\u95A2\u4FC2\uFF08\u91CD\u8981\uFF09</h4>
|
|
12714
|
+
<p>\u6B4C\u8A5E\u30C8\u30E9\u30C3\u30AF\u306B\u306F\u305D\u308C\u305E\u308C\u300C\u30EA\u30D0\u30FC\u30D6\u9001\u308A\u300D\u3068\u3044\u3046\u500B\u5225\u306E\u3064\u307E\u307F\u304C\u3042\u308A\u3001\u305D\u3061\u3089\u304C0%\u306E\u30C8\u30E9\u30C3\u30AF\u306F\u3053\u306E\u30DE\u30B9\u30BF\u306E\u5024\u3092\u3044\u304F\u3089\u4E0A\u3052\u3066\u3082\u7121\u97F3\u306E\u307E\u307E\u3067\u3059\u3002\u9006\u306B\u3053\u306E\u30DE\u30B9\u30BF\u304C0%\u306A\u3089\u3001\u3069\u306E\u30C8\u30E9\u30C3\u30AF\u306E\u9001\u308A\u91CF\u3092\u4E0A\u3052\u3066\u3082\u52B9\u679C\u304C\u51FA\u307E\u305B\u3093\u3002\u300C\u30DE\u30B9\u30BF\uFF1D\u6B8B\u97FF\u306E\u8CEA\u3068\u91CF\u305D\u306E\u3082\u306E\u300D\u300C\u30C8\u30E9\u30C3\u30AF\u9001\u308A\uFF1D\u305D\u306E\u30C8\u30E9\u30C3\u30AF\u3092\u3069\u308C\u3060\u3051\u6DF7\u305C\u308B\u304B\u300D\u3068\u3044\u3046\u4E8C\u6BB5\u69CB\u3048\u3067\u3059\u3002\u697D\u5668\u30C8\u30E9\u30C3\u30AF\u306B\u306F\u73FE\u72B6\u30BB\u30F3\u30C9\u6A5F\u80FD\u304C\u7121\u3044\u305F\u3081\u3001\u5E38\u306B\u4E00\u5F8B\u3067\u639B\u304B\u308A\u307E\u3059\u3002</p>
|
|
12715
|
+
<h4>\u639B\u3051\u3059\u304E\u308B\u3068\u3069\u3046\u306A\u308B\u304B</h4>
|
|
12716
|
+
<p>\u30DF\u30C3\u30AF\u30B9\u5168\u4F53\u306E\u8F2A\u90ED\u304C\u307C\u3084\u3051\u3001\u9060\u304F\u30FB\u3053\u3082\u3063\u305F\u5370\u8C61\u306B\u306A\u308A\u307E\u3059\u300210\u301C30%\u7A0B\u5EA6\u3092\u51FA\u767A\u70B9\u306B\u3001\u66F2\u306E\u30B8\u30E3\u30F3\u30EB\u3084\u7A7A\u9593\u306E\u5E83\u3055\u306E\u30A4\u30E1\u30FC\u30B8\u306B\u5408\u308F\u305B\u3066\u8ABF\u6574\u3059\u308B\u306E\u304C\u304A\u3059\u3059\u3081\u3067\u3059\u3002</p>
|
|
12717
|
+
</div>
|
|
12718
|
+
`;
|
|
12719
|
+
var TRACK_COMPRESSION_INFO_HTML = `
|
|
12720
|
+
<div class="dtm-modal-body-content">
|
|
12721
|
+
<h4>\u4F55\u3092\u3059\u308B\u8A2D\u5B9A\u304B</h4>
|
|
12722
|
+
<p>\u3053\u306E\u30C8\u30E9\u30C3\u30AF\u306B\u30B3\u30F3\u30D7\u30EC\u30C3\u30B5\u30FC\u3092\u639B\u3051\u3001\u97F3\u91CF\u306E\u5927\u5C0F\u5DEE\u3092\u7E2E\u3081\u3066\u300C\u524D\u306B\u51FA\u308B\u300D\u300C\u805E\u3053\u3048\u3084\u3059\u3044\u300D\u97F3\u306B\u3057\u307E\u3059\u3002\u5E02\u8CA9\u66F2\u306E\u30DE\u30B9\u30BF\u30EA\u30F3\u30B0\u3084\u30DF\u30C3\u30AF\u30B9\u3067\u5B9A\u756A\u306E\u51E6\u7406\u3067\u3059\u30020\u3067\u7121\u5727\u7E2E\u3001100\u306B\u8FD1\u3065\u304F\u307B\u3069\u5F37\u304F\u5727\u7E2E\u3055\u308C\u307E\u3059\u3002</p>
|
|
12723
|
+
<h4>\u639B\u3051\u3059\u304E\u308B\u3068\u3069\u3046\u306A\u308B\u304B</h4>
|
|
12724
|
+
<p>\u5F37\u5F31\u306E\u8868\u60C5\uFF08\u30C0\u30A4\u30CA\u30DF\u30AF\u30B9\uFF09\u304C\u5931\u308F\u308C\u3066\u5358\u8ABF\u306B\u805E\u3053\u3048\u307E\u3059\u3002\u30DC\u30FC\u30AB\u30EB\u3084\u30EA\u30FC\u30C9\u697D\u5668\u306F\u63A7\u3048\u3081\uFF0820\u301C40\u7A0B\u5EA6\uFF09\u3001\u30C9\u30E9\u30E0\u3084\u30D9\u30FC\u30B9\u306F\u3084\u3084\u5F37\u3081\u3001\u304C\u4E00\u822C\u7684\u306A\u76EE\u5B89\u3067\u3059\u3002</p>
|
|
12725
|
+
<h4>\u4ED6\u306E\u8A2D\u5B9A\u3068\u306E\u517C\u306D\u5408\u3044</h4>
|
|
12726
|
+
<p>\u30DE\u30B9\u30BF\u306E\u300C\u5B89\u5168\u30EA\u30DF\u30C3\u30BF\u30FC\u300D\uFF08\u5E38\u6642ON\u3001[reverb]\u30D1\u30CD\u30EB\u306E\u5916\u5074\u3067\u81EA\u52D5\u7684\u306B\u50CD\u304F\u4FDD\u967A\uFF09\u3068\u306F\u5225\u7269\u3067\u3059\u3002\u3042\u3061\u3089\u306F\u97F3\u5272\u308C\u3092\u7269\u7406\u7684\u306B\u9632\u3050\u305F\u3081\u306E\u6700\u7D42\u9632\u885B\u30E9\u30A4\u30F3\u3067\u3001\u5E38\u306B\u63A7\u3048\u3081\u306B\u52D5\u3044\u3066\u3044\u307E\u3059\u3002\u3053\u3061\u3089\u306E\u30B3\u30F3\u30D7\u30EC\u30C3\u30B5\u30FC\u306F\u97F3\u4F5C\u308A\uFF08\u8868\u73FE\uFF09\u306E\u305F\u3081\u306E\u51E6\u7406\u3067\u3001\u30C8\u30E9\u30C3\u30AF\u3054\u3068\u306B\u597D\u304D\u306A\u3060\u3051\u5F37\u304F/\u5F31\u304F\u639B\u3051\u3089\u308C\u307E\u3059\u3002\u300C\u304A\u307E\u304B\u305B\u30DE\u30B9\u30BF\u30EA\u30F3\u30B0\u300D\u306F\u5168\u30C8\u30E9\u30C3\u30AF\u4E00\u5F8B35%\u3092\u5F53\u3066\u308B\u3060\u3051\u306A\u306E\u3067\u3001\u30DC\u30FC\u30AB\u30EB\u306A\u3069\u76EE\u7ACB\u305F\u305B\u305F\u3044\u30D1\u30FC\u30C8\u306F\u5F8C\u3067\u500B\u5225\u306B\u4E0B\u3052\u308B\u3068\u8F2A\u90ED\u304C\u51FA\u3084\u3059\u304F\u306A\u308A\u307E\u3059\u3002</p>
|
|
12727
|
+
</div>
|
|
12728
|
+
`;
|
|
12729
|
+
var TRACK_WIDTH_INFO_HTML = `
|
|
12730
|
+
<div class="dtm-modal-body-content">
|
|
12731
|
+
<h4>\u4F55\u3092\u3059\u308B\u8A2D\u5B9A\u304B</h4>
|
|
12732
|
+
<p>\u5DE6\u53F3\u306E\u5E83\u304C\u308A\u3092\u8ABF\u6574\u3057\u307E\u3059\u3002100\u304C\u539F\u97F3\u306E\u307E\u307E\u30010\u3067\u5B8C\u5168\u30E2\u30CE\u30E9\u30EB\uFF08\u5DE6\u53F3\u304C\u540C\u3058\u97F3\uFF09\u3001100\u3092\u8D85\u3048\u308B\u3068\u5DE6\u53F3\u306E\u9055\u3044\u304C\u8A87\u5F35\u3055\u308C\u3066\u5E83\u304F\u805E\u3053\u3048\u307E\u3059\u3002</p>
|
|
12733
|
+
<h4>\u300C\u5B9A\u4F4D\uFF08\u30D1\u30F3\uFF09\u300D\u3068\u306E\u9055\u3044</h4>
|
|
12734
|
+
<p>\u5B9A\u4F4D\u306F\u300C\u97F3\u3092\u3069\u3053\u306B\u7F6E\u304F\u304B\u300D\uFF08\u5DE6\u5BC4\u308A/\u4E2D\u592E/\u53F3\u5BC4\u308A\uFF09\u3001\u30B9\u30C6\u30EC\u30AA\u5E45\u306F\u300C\u305D\u306E\u97F3\u81EA\u4F53\u304C\u3069\u308C\u3060\u3051\u5E83\u304C\u3063\u3066\u805E\u3053\u3048\u308B\u304B\u300D\u3067\u3001\u5F79\u5272\u304C\u7570\u306A\u308A\u307E\u3059\u3002\u4E21\u65B9\u3092\u5F37\u304F\u4F7F\u3046\u3068\u5B9A\u4F4D\u304C\u307C\u3084\u3051\u3066\u66D6\u6627\u306B\u306A\u308A\u304C\u3061\u3067\u3059\u3002</p>
|
|
12735
|
+
<h4>\u5E83\u3052\u3059\u304E\u308B\u3068\u3069\u3046\u306A\u308B\u304B</h4>
|
|
12736
|
+
<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>
|
|
12737
|
+
</div>
|
|
12738
|
+
`;
|
|
12739
|
+
var AUTO_MASTER_INFO_HTML = `
|
|
12740
|
+
<div class="dtm-modal-body-content">
|
|
12741
|
+
<h4>\u304A\u307E\u304B\u305B\u30DE\u30B9\u30BF\u30EA\u30F3\u30B0\u3068\u306F</h4>
|
|
12742
|
+
<p>\u5E02\u8CA9\u66F2\u3067\u3088\u304F\u4F7F\u308F\u308C\u308B\u5024\u3092\u76EE\u5B89\u306B\u3001\u4EE5\u4E0B\u3092\u307E\u3068\u3081\u3066\u8A2D\u5B9A\u3059\u308B\u30DC\u30BF\u30F3\u3067\u3059\u3002</p>
|
|
12743
|
+
<ul>
|
|
12744
|
+
<li>\u30DE\u30B9\u30BF\u30EA\u30D0\u30FC\u30D6: 20%</li>
|
|
12745
|
+
<li>\u5168\u30C8\u30E9\u30C3\u30AF\u306E\u97F3\u5727\u5F37\u5316: 35%</li>
|
|
12746
|
+
<li>\u5168\u30C8\u30E9\u30C3\u30AF\u306E\u30B9\u30C6\u30EC\u30AA\u5E45: 115%\uFF08\u308F\u305A\u304B\u306B\u5E83\u3052\u308B\uFF09</li>
|
|
12747
|
+
<li>\u6B4C\u8A5E\u306E\u3042\u308B\u30C8\u30E9\u30C3\u30AF: \u81EA\u52D5\u30D3\u30D6\u30E9\u30FC\u30C8ON\u3001\u30EA\u30D0\u30FC\u30D6\u9001\u308A25%</li>
|
|
12748
|
+
</ul>
|
|
12749
|
+
<p style="margin-top:4px;"><small>\u300C\u3044\u3044\u611F\u3058\u306E\u521D\u671F\u5024\u300D\u3092\u4E00\u62EC\u3067\u5F53\u3066\u308B\u3060\u3051\u3067\u3001\u66F2\u3084\u597D\u307F\u306B\u5FDC\u3058\u305F\u5FAE\u8ABF\u6574\u307E\u3067\u306F\u884C\u3044\u307E\u305B\u3093\u3002\u65E2\u5B58\u306E\u8A2D\u5B9A\u306F\u4E0A\u66F8\u304D\u3055\u308C\u308B\u306E\u3067\u3001\u6C17\u306B\u5165\u3089\u306A\u3051\u308C\u3070\u5404\u30B9\u30E9\u30A4\u30C0\u30FC\u304B\u3089\u500B\u5225\u306B\u623B\u3057\u3066\u304F\u3060\u3055\u3044\u3002</small></p>
|
|
12750
|
+
</div>
|
|
12751
|
+
`;
|
|
12302
12752
|
var MIDI_INFO_HTML = `
|
|
12303
12753
|
<div class="dtm-modal-body-content">
|
|
12304
12754
|
<h4>1. MIDI\u30D5\u30A1\u30A4\u30EB\u3068\u306F</h4>
|
|
@@ -12502,7 +12952,7 @@ var LYRIC_MODEL_CATEGORIES = [
|
|
|
12502
12952
|
},
|
|
12503
12953
|
{
|
|
12504
12954
|
label: "\u304A\u3093J",
|
|
12505
|
-
models: ["roze", "shiyo", "rino"]
|
|
12955
|
+
models: ["roze", "shiyo", "rino", "rino121", "uc"]
|
|
12506
12956
|
},
|
|
12507
12957
|
{
|
|
12508
12958
|
label: "\u4E00\u822C",
|
|
@@ -12570,6 +13020,8 @@ var mountDAW = (target, options = {}) => {
|
|
|
12570
13020
|
});
|
|
12571
13021
|
refs.masterVolume.value = String(options.masterVolume ?? 50);
|
|
12572
13022
|
refs.masterVolumeLabel.textContent = `${options.masterVolume ?? 50}%`;
|
|
13023
|
+
refs.reverbAmount.value = String(options.reverbAmount ?? 0);
|
|
13024
|
+
refs.reverbAmountLabel.textContent = `${options.reverbAmount ?? 0}%`;
|
|
12573
13025
|
refs.drumVolume.value = String(options.drumVolume ?? 80);
|
|
12574
13026
|
refs.drumVolumeLabel.textContent = `${options.drumVolume ?? 80}%`;
|
|
12575
13027
|
const renderConfig = {
|
|
@@ -12585,6 +13037,9 @@ var mountDAW = (target, options = {}) => {
|
|
|
12585
13037
|
let bpm = options.defaultBpm ?? DEFAULT_BPM;
|
|
12586
13038
|
let masterVolume = options.masterVolume ?? 50;
|
|
12587
13039
|
options.singingVoices?.setVolume(masterVolume / 100);
|
|
13040
|
+
let reverbAmount = options.reverbAmount ?? 0;
|
|
13041
|
+
let unsubscribeClip;
|
|
13042
|
+
options.onReverbChange?.(reverbAmount);
|
|
12588
13043
|
let drumVolume = options.drumVolume ?? 80;
|
|
12589
13044
|
let currentDrumPattern = refs.drumSelect.value;
|
|
12590
13045
|
let currentDrumFont = options.drumFont ?? "FluidR3_GM_sf2_file:0";
|
|
@@ -12662,7 +13117,11 @@ var mountDAW = (target, options = {}) => {
|
|
|
12662
13117
|
vocalVolume: t.vocalVolume,
|
|
12663
13118
|
vocalGate: t.vocalGate,
|
|
12664
13119
|
vocalPan: t.vocalPan,
|
|
12665
|
-
vocalOctave: t.vocalOctave
|
|
13120
|
+
vocalOctave: t.vocalOctave,
|
|
13121
|
+
vocalVibrato: t.vocalVibrato,
|
|
13122
|
+
vocalReverb: t.vocalReverb,
|
|
13123
|
+
vocalGender: t.vocalGender,
|
|
13124
|
+
vocalBreathiness: t.vocalBreathiness
|
|
12666
13125
|
};
|
|
12667
13126
|
if (lyricsDebounceTimer) clearTimeout(lyricsDebounceTimer);
|
|
12668
13127
|
lyricsDebounceTimer = setTimeout(() => {
|
|
@@ -12722,25 +13181,35 @@ var mountDAW = (target, options = {}) => {
|
|
|
12722
13181
|
vocalGate: 100,
|
|
12723
13182
|
vocalPan: 64,
|
|
12724
13183
|
vocalOctave: 0,
|
|
12725
|
-
|
|
13184
|
+
vocalVibrato: false,
|
|
13185
|
+
vocalReverb: 0,
|
|
13186
|
+
vocalGender: 50,
|
|
13187
|
+
vocalBreathiness: 50,
|
|
13188
|
+
trackInstrument: "",
|
|
13189
|
+
trackCompression: 0,
|
|
13190
|
+
trackWidth: 100
|
|
12726
13191
|
};
|
|
12727
13192
|
});
|
|
12728
13193
|
};
|
|
12729
13194
|
const buildLyricsMap = () => {
|
|
12730
13195
|
const map = /* @__PURE__ */ new Map();
|
|
12731
|
-
trackStates.forEach((t,
|
|
13196
|
+
trackStates.forEach((t, i2) => {
|
|
12732
13197
|
const model = t.lyricModel.trim();
|
|
12733
13198
|
const text = t.lyrics.trim();
|
|
12734
13199
|
if (!model || !text) return;
|
|
12735
13200
|
const syllables = normalizeLyrics(text);
|
|
12736
13201
|
if (syllables.length === 0) return;
|
|
12737
|
-
map.set(
|
|
12738
|
-
trackId:
|
|
13202
|
+
map.set(i2, {
|
|
13203
|
+
trackId: i2,
|
|
12739
13204
|
model: model.toLowerCase(),
|
|
12740
13205
|
volume: t.vocalVolume,
|
|
12741
13206
|
gate: t.vocalGate,
|
|
12742
13207
|
pan: t.vocalPan,
|
|
12743
13208
|
octave: t.vocalOctave,
|
|
13209
|
+
vibrato: t.vocalVibrato,
|
|
13210
|
+
reverb: t.vocalReverb,
|
|
13211
|
+
gender: t.vocalGender,
|
|
13212
|
+
breathiness: t.vocalBreathiness,
|
|
12744
13213
|
syllables
|
|
12745
13214
|
});
|
|
12746
13215
|
});
|
|
@@ -12780,15 +13249,15 @@ var mountDAW = (target, options = {}) => {
|
|
|
12780
13249
|
const ctx = getGridContext();
|
|
12781
13250
|
const canvas = getGridCanvas();
|
|
12782
13251
|
if (!ctx) return;
|
|
12783
|
-
const
|
|
12784
|
-
if (
|
|
13252
|
+
const x2 = playStartStep * renderConfig.stepWidth - currentOffsetX;
|
|
13253
|
+
if (x2 < -10 || x2 > canvas.width + 10) return;
|
|
12785
13254
|
ctx.save();
|
|
12786
13255
|
ctx.strokeStyle = "#ffec27";
|
|
12787
13256
|
ctx.lineWidth = 2;
|
|
12788
13257
|
ctx.setLineDash([4, 4]);
|
|
12789
13258
|
ctx.beginPath();
|
|
12790
|
-
ctx.moveTo(
|
|
12791
|
-
ctx.lineTo(
|
|
13259
|
+
ctx.moveTo(x2, 0);
|
|
13260
|
+
ctx.lineTo(x2, canvas.height);
|
|
12792
13261
|
ctx.stroke();
|
|
12793
13262
|
ctx.restore();
|
|
12794
13263
|
};
|
|
@@ -12796,14 +13265,14 @@ var mountDAW = (target, options = {}) => {
|
|
|
12796
13265
|
const ctx = getGridContext();
|
|
12797
13266
|
const canvas = getGridCanvas();
|
|
12798
13267
|
if (!ctx) return;
|
|
12799
|
-
const
|
|
12800
|
-
if (
|
|
13268
|
+
const x2 = currentPlayStep * renderConfig.stepWidth - currentOffsetX;
|
|
13269
|
+
if (x2 < 0 || x2 > canvas.width) return;
|
|
12801
13270
|
ctx.save();
|
|
12802
13271
|
ctx.strokeStyle = "#ff004d";
|
|
12803
13272
|
ctx.lineWidth = 2;
|
|
12804
13273
|
ctx.beginPath();
|
|
12805
|
-
ctx.moveTo(
|
|
12806
|
-
ctx.lineTo(
|
|
13274
|
+
ctx.moveTo(x2, 0);
|
|
13275
|
+
ctx.lineTo(x2, canvas.height);
|
|
12807
13276
|
ctx.stroke();
|
|
12808
13277
|
ctx.restore();
|
|
12809
13278
|
};
|
|
@@ -12931,8 +13400,8 @@ var mountDAW = (target, options = {}) => {
|
|
|
12931
13400
|
if (maxOffsetX <= 0) return;
|
|
12932
13401
|
const rect = refs.hScroll.getBoundingClientRect();
|
|
12933
13402
|
const thumbW = Number.parseFloat(refs.hScrollThumb.style.width) || 40;
|
|
12934
|
-
const
|
|
12935
|
-
const ratio =
|
|
13403
|
+
const x2 = clamp3(clientX - rect.left - thumbW / 2, 0, rect.width - thumbW);
|
|
13404
|
+
const ratio = x2 / (rect.width - thumbW);
|
|
12936
13405
|
currentOffsetX = clamp3(ratio * maxOffsetX, 0, maxOffsetX);
|
|
12937
13406
|
setDrawOffset(currentOffsetX, currentOffsetY);
|
|
12938
13407
|
redrawAll();
|
|
@@ -12959,13 +13428,60 @@ var mountDAW = (target, options = {}) => {
|
|
|
12959
13428
|
let selectionStart = null;
|
|
12960
13429
|
let selectedOriginal = [];
|
|
12961
13430
|
let lastMultiPreviewPitch = null;
|
|
13431
|
+
const AUTO_SCROLL_MARGIN = 30;
|
|
13432
|
+
const AUTO_SCROLL_MAX_SPEED = 22;
|
|
13433
|
+
let autoScrollRAF = null;
|
|
13434
|
+
let lastMoveEvent = null;
|
|
13435
|
+
const computeEdgeSpeed = (pos, size) => {
|
|
13436
|
+
if (pos < AUTO_SCROLL_MARGIN) {
|
|
13437
|
+
const t = (AUTO_SCROLL_MARGIN - pos) / AUTO_SCROLL_MARGIN;
|
|
13438
|
+
return -Math.ceil(t * AUTO_SCROLL_MAX_SPEED);
|
|
13439
|
+
}
|
|
13440
|
+
if (pos > size - AUTO_SCROLL_MARGIN) {
|
|
13441
|
+
const t = (pos - (size - AUTO_SCROLL_MARGIN)) / AUTO_SCROLL_MARGIN;
|
|
13442
|
+
return Math.ceil(t * AUTO_SCROLL_MAX_SPEED);
|
|
13443
|
+
}
|
|
13444
|
+
return 0;
|
|
13445
|
+
};
|
|
13446
|
+
const stopAutoScroll = () => {
|
|
13447
|
+
if (autoScrollRAF !== null) {
|
|
13448
|
+
cancelAnimationFrame(autoScrollRAF);
|
|
13449
|
+
autoScrollRAF = null;
|
|
13450
|
+
}
|
|
13451
|
+
lastMoveEvent = null;
|
|
13452
|
+
};
|
|
13453
|
+
const autoScrollTick = () => {
|
|
13454
|
+
autoScrollRAF = null;
|
|
13455
|
+
if (!isSelecting || !lastMoveEvent) return;
|
|
13456
|
+
const canvas = getGridCanvas();
|
|
13457
|
+
const { x: x2, y } = getGridPosition(lastMoveEvent);
|
|
13458
|
+
const dx = computeEdgeSpeed(x2, canvas.width);
|
|
13459
|
+
const dy = computeEdgeSpeed(y, canvas.height);
|
|
13460
|
+
if (dx !== 0 || dy !== 0) {
|
|
13461
|
+
const maxOffsetX = getMaxOffsetX();
|
|
13462
|
+
const maxOffsetY = getMaxOffsetY();
|
|
13463
|
+
currentOffsetX = clamp3(currentOffsetX + dx, 0, maxOffsetX);
|
|
13464
|
+
currentOffsetY = clamp3(currentOffsetY + dy, 0, maxOffsetY);
|
|
13465
|
+
setDrawOffset(currentOffsetX, currentOffsetY);
|
|
13466
|
+
onPointerMove(lastMoveEvent);
|
|
13467
|
+
}
|
|
13468
|
+
if (isSelecting) {
|
|
13469
|
+
autoScrollRAF = requestAnimationFrame(autoScrollTick);
|
|
13470
|
+
}
|
|
13471
|
+
};
|
|
13472
|
+
const ensureAutoScroll = (event) => {
|
|
13473
|
+
lastMoveEvent = event;
|
|
13474
|
+
if (autoScrollRAF === null) {
|
|
13475
|
+
autoScrollRAF = requestAnimationFrame(autoScrollTick);
|
|
13476
|
+
}
|
|
13477
|
+
};
|
|
12962
13478
|
const playPreview = (pitch) => {
|
|
12963
13479
|
if (isLoading) return;
|
|
12964
13480
|
options.onResumeAudio?.();
|
|
12965
13481
|
const active = getActive();
|
|
12966
13482
|
dispatchNote(active.config.id, pitch, active.volume, 100, 0, 0.5);
|
|
12967
13483
|
};
|
|
12968
|
-
const findActiveNoteAt = (
|
|
13484
|
+
const findActiveNoteAt = (x2, y, margin = 0) => {
|
|
12969
13485
|
const active = getActive();
|
|
12970
13486
|
const { stepWidth, keyHeight, keyCount, pitchRangeStart } = renderConfig;
|
|
12971
13487
|
const offset = getDrawOffset();
|
|
@@ -12976,7 +13492,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
12976
13492
|
const w = note.durationSteps * stepWidth;
|
|
12977
13493
|
const renderX = logicalX - offset.x;
|
|
12978
13494
|
const renderY = logicalY - offset.y;
|
|
12979
|
-
if (
|
|
13495
|
+
if (x2 >= renderX - margin && x2 <= renderX + w + margin && y >= renderY - margin && y <= renderY + keyHeight + margin)
|
|
12980
13496
|
return note;
|
|
12981
13497
|
}
|
|
12982
13498
|
return null;
|
|
@@ -12995,17 +13511,17 @@ var mountDAW = (target, options = {}) => {
|
|
|
12995
13511
|
const onGridPointerDown = (event) => {
|
|
12996
13512
|
event.preventDefault();
|
|
12997
13513
|
options.onResumeAudio?.();
|
|
12998
|
-
const { x, y, step, pitch } = getGridPosition(event);
|
|
13514
|
+
const { x: x2, y, step, pitch } = getGridPosition(event);
|
|
12999
13515
|
const active = getActive();
|
|
13000
13516
|
if (activeToolMode === "eraser") {
|
|
13001
13517
|
if (isActiveLocked()) return;
|
|
13002
|
-
const note = findActiveNoteAt(
|
|
13518
|
+
const note = findActiveNoteAt(x2, y);
|
|
13003
13519
|
if (note) active.core.deleteNoteById(note.id);
|
|
13004
13520
|
return;
|
|
13005
13521
|
}
|
|
13006
13522
|
if (activeToolMode === "select") {
|
|
13007
13523
|
if (selectedNotes.length > 0) {
|
|
13008
|
-
const clicked2 = findActiveNoteAt(
|
|
13524
|
+
const clicked2 = findActiveNoteAt(x2, y);
|
|
13009
13525
|
if (clicked2 && selectedNotes.some((n) => n.id === clicked2.id)) {
|
|
13010
13526
|
selectedOriginal = selectedNotes.map((n) => ({
|
|
13011
13527
|
id: n.id,
|
|
@@ -13014,7 +13530,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
13014
13530
|
}));
|
|
13015
13531
|
isSelecting = true;
|
|
13016
13532
|
dragMode = "move";
|
|
13017
|
-
selectionStart = { x, y, step, pitch };
|
|
13533
|
+
selectionStart = { x: x2, y, step, pitch };
|
|
13018
13534
|
hasDragged = false;
|
|
13019
13535
|
lastMultiPreviewPitch = null;
|
|
13020
13536
|
return;
|
|
@@ -13022,7 +13538,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
13022
13538
|
selectedNotes = [];
|
|
13023
13539
|
selectionRect = null;
|
|
13024
13540
|
}
|
|
13025
|
-
const clicked = findActiveNoteAt(
|
|
13541
|
+
const clicked = findActiveNoteAt(x2, y);
|
|
13026
13542
|
if (clicked) {
|
|
13027
13543
|
selectedNotes = [clicked];
|
|
13028
13544
|
selectedOriginal = [
|
|
@@ -13040,19 +13556,19 @@ var mountDAW = (target, options = {}) => {
|
|
|
13040
13556
|
isSelecting = true;
|
|
13041
13557
|
dragMode = "rect";
|
|
13042
13558
|
}
|
|
13043
|
-
selectionStart = { x, y, step, pitch };
|
|
13559
|
+
selectionStart = { x: x2, y, step, pitch };
|
|
13044
13560
|
hasDragged = false;
|
|
13045
13561
|
return;
|
|
13046
13562
|
}
|
|
13047
13563
|
hasDragged = false;
|
|
13048
|
-
const existing = findActiveNoteAt(
|
|
13564
|
+
const existing = findActiveNoteAt(x2, y, TOUCH_HIT_MARGIN);
|
|
13049
13565
|
if (existing) {
|
|
13050
13566
|
playPreview(existing.pitch);
|
|
13051
13567
|
const { stepWidth } = renderConfig;
|
|
13052
13568
|
const offset = getDrawOffset();
|
|
13053
13569
|
const renderX = existing.startStep * stepWidth - offset.x;
|
|
13054
13570
|
const w = existing.durationSteps * stepWidth;
|
|
13055
|
-
if (
|
|
13571
|
+
if (x2 >= renderX + w - resizeHandleWidth && x2 <= renderX + w) {
|
|
13056
13572
|
dragState = {
|
|
13057
13573
|
noteId: existing.id,
|
|
13058
13574
|
mode: "resize",
|
|
@@ -13131,12 +13647,13 @@ var mountDAW = (target, options = {}) => {
|
|
|
13131
13647
|
return;
|
|
13132
13648
|
}
|
|
13133
13649
|
if (activeToolMode === "select" && isSelecting && selectionStart) {
|
|
13134
|
-
|
|
13650
|
+
ensureAutoScroll(event);
|
|
13651
|
+
const { x: x2, y, step, pitch } = getGridPosition(event);
|
|
13135
13652
|
if (dragMode === "rect") {
|
|
13136
13653
|
const rect = {
|
|
13137
|
-
x: Math.min(
|
|
13654
|
+
x: Math.min(x2, selectionStart.x),
|
|
13138
13655
|
y: Math.min(y, selectionStart.y),
|
|
13139
|
-
width: Math.abs(
|
|
13656
|
+
width: Math.abs(x2 - selectionStart.x),
|
|
13140
13657
|
height: Math.abs(y - selectionStart.y)
|
|
13141
13658
|
};
|
|
13142
13659
|
selectionRect = rect;
|
|
@@ -13149,7 +13666,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
13149
13666
|
const nx = logicalX - offset.x;
|
|
13150
13667
|
const ny = logicalY - offset.y;
|
|
13151
13668
|
const nw = note.durationSteps * stepWidth;
|
|
13152
|
-
return rect.x
|
|
13669
|
+
return nx >= rect.x && nx + nw <= rect.x + rect.width && ny >= rect.y && ny + keyHeight <= rect.y + rect.height;
|
|
13153
13670
|
});
|
|
13154
13671
|
redrawAll();
|
|
13155
13672
|
} else {
|
|
@@ -13206,8 +13723,11 @@ var mountDAW = (target, options = {}) => {
|
|
|
13206
13723
|
selectionStart = null;
|
|
13207
13724
|
hasDragged = false;
|
|
13208
13725
|
lastMultiPreviewPitch = null;
|
|
13209
|
-
|
|
13726
|
+
if (dragMode !== "rect" || selectedNotes.length === 0) {
|
|
13727
|
+
selectionRect = null;
|
|
13728
|
+
}
|
|
13210
13729
|
selectedOriginal = [];
|
|
13730
|
+
stopAutoScroll();
|
|
13211
13731
|
redrawAll();
|
|
13212
13732
|
}
|
|
13213
13733
|
};
|
|
@@ -13355,8 +13875,8 @@ var mountDAW = (target, options = {}) => {
|
|
|
13355
13875
|
headerCanvas.addEventListener("click", (event) => {
|
|
13356
13876
|
if (playbackState === "playing") return;
|
|
13357
13877
|
const rect = headerCanvas.getBoundingClientRect();
|
|
13358
|
-
const
|
|
13359
|
-
const step = Math.floor((
|
|
13878
|
+
const x2 = event.clientX - rect.left;
|
|
13879
|
+
const step = Math.floor((x2 + currentOffsetX) / renderConfig.stepWidth);
|
|
13360
13880
|
playStartStep = Math.max(
|
|
13361
13881
|
0,
|
|
13362
13882
|
Math.floor(step / snapGridSteps) * snapGridSteps
|
|
@@ -13477,11 +13997,11 @@ var mountDAW = (target, options = {}) => {
|
|
|
13477
13997
|
const semis = (lt.octave ?? 0) * 12;
|
|
13478
13998
|
const count = Math.min(sorted.length, lt.syllables.length);
|
|
13479
13999
|
const notes = [];
|
|
13480
|
-
for (let
|
|
13481
|
-
const n = sorted[
|
|
14000
|
+
for (let i2 = 0; i2 < count; i2++) {
|
|
14001
|
+
const n = sorted[i2];
|
|
13482
14002
|
if (n.startStep < fromStep) continue;
|
|
13483
14003
|
notes.push({
|
|
13484
|
-
syllable: lt.syllables[
|
|
14004
|
+
syllable: lt.syllables[i2],
|
|
13485
14005
|
pitch: n.pitch + semis,
|
|
13486
14006
|
startSec: (n.startStep - fromStep) * secondsPerStep,
|
|
13487
14007
|
durationSec: n.durationSteps * secondsPerStep * gate
|
|
@@ -13492,6 +14012,10 @@ var mountDAW = (target, options = {}) => {
|
|
|
13492
14012
|
model: lt.model,
|
|
13493
14013
|
volume: vocalVolumeToGain(lt.volume ?? DEFAULT_VOCAL_VOLUME),
|
|
13494
14014
|
pan: panToStereo(lt.pan ?? DEFAULT_PAN),
|
|
14015
|
+
vibrato: lt.vibrato,
|
|
14016
|
+
reverbSend: (lt.reverb ?? 0) / 100,
|
|
14017
|
+
gender: (lt.gender ?? 50) / 100,
|
|
14018
|
+
breathiness: (lt.breathiness ?? 50) / 100,
|
|
13495
14019
|
notes
|
|
13496
14020
|
};
|
|
13497
14021
|
}) : [];
|
|
@@ -13580,13 +14104,13 @@ var mountDAW = (target, options = {}) => {
|
|
|
13580
14104
|
const updateTrackPanel = () => {
|
|
13581
14105
|
refs.trackTabs.innerHTML = "";
|
|
13582
14106
|
trackPillEls.clear();
|
|
13583
|
-
for (const [
|
|
14107
|
+
for (const [i2, t] of trackStates.entries()) {
|
|
13584
14108
|
const [r, g, b] = t.config.color;
|
|
13585
14109
|
const btn = document.createElement("button");
|
|
13586
14110
|
btn.className = `dtm-pill ${t.config.id === activeTrackId ? "dtm-pill--active" : ""}`;
|
|
13587
14111
|
btn.style.setProperty("--dtm-pill-color", `rgb(${r},${g},${b})`);
|
|
13588
14112
|
btn.title = t.config.name;
|
|
13589
|
-
btn.textContent = String(
|
|
14113
|
+
btn.textContent = String(i2 + 1);
|
|
13590
14114
|
btn.addEventListener("click", () => switchTrack(t.config.id));
|
|
13591
14115
|
refs.trackTabs.appendChild(btn);
|
|
13592
14116
|
trackPillEls.set(t.config.id, btn);
|
|
@@ -13597,7 +14121,22 @@ var mountDAW = (target, options = {}) => {
|
|
|
13597
14121
|
<span class="dtm-label">\u30D9\u30ED\u30B7\u30C6\u30A3</span>
|
|
13598
14122
|
<input type="range" class="dtm-range dtm-grow" data-dtm="track-vol" min="0" max="127" value="${active.volume}">
|
|
13599
14123
|
<span class="dtm-label" data-dtm="track-vol-label">${active.volume}</span>
|
|
13600
|
-
</div
|
|
14124
|
+
</div>
|
|
14125
|
+
<details class="dtm-advanced" data-dtm="track-fx-advanced">
|
|
14126
|
+
<summary>\u8A73\u7D30\u8A2D\u5B9A\uFF08\u97F3\u5727\u30FB\u30B9\u30C6\u30EC\u30AA\u5E45\uFF09</summary>
|
|
14127
|
+
<div class="dtm-row">
|
|
14128
|
+
<span class="dtm-label">\u97F3\u5727\u5F37\u5316</span>
|
|
14129
|
+
<input type="range" class="dtm-range dtm-grow" data-dtm="track-comp" min="0" max="100" aria-label="\u3053\u306E\u30C8\u30E9\u30C3\u30AF\u306E\u30B3\u30F3\u30D7\u30EC\u30C3\u30B5\u30FC\u91CF\uFF08\u97F3\u5727\u5F37\u5316\uFF09">
|
|
14130
|
+
<span class="dtm-label" data-dtm="track-comp-label"></span>
|
|
14131
|
+
<button class="dtm-infobtn" data-dtm="track-comp-info" title="\u97F3\u5727\u5F37\u5316\u306E\u89E3\u8AAC">${icon("info", 12)}</button>
|
|
14132
|
+
</div>
|
|
14133
|
+
<div class="dtm-row">
|
|
14134
|
+
<span class="dtm-label">\u30B9\u30C6\u30EC\u30AA\u5E45</span>
|
|
14135
|
+
<input type="range" class="dtm-range dtm-grow" data-dtm="track-width" min="0" max="200" aria-label="\u3053\u306E\u30C8\u30E9\u30C3\u30AF\u306E\u30B9\u30C6\u30EC\u30AA\u5E45\uFF08100=\u539F\u97F3\u30010=\u30E2\u30CE\u30E9\u30EB\uFF09">
|
|
14136
|
+
<span class="dtm-label" data-dtm="track-width-label"></span>
|
|
14137
|
+
<button class="dtm-infobtn" data-dtm="track-width-info" title="\u30B9\u30C6\u30EC\u30AA\u5E45\u306E\u89E3\u8AAC">${icon("info", 12)}</button>
|
|
14138
|
+
</div>
|
|
14139
|
+
</details>`;
|
|
13601
14140
|
const volInput = refs.trackBody.querySelector(
|
|
13602
14141
|
'[data-dtm="track-vol"]'
|
|
13603
14142
|
);
|
|
@@ -13614,6 +14153,47 @@ var mountDAW = (target, options = {}) => {
|
|
|
13614
14153
|
volInput.title = active.lyricModel ? "\u6B4C\u8A5E\u30E2\u30FC\u30C9\u306E\u3068\u304D\u306F\u30D9\u30ED\u30B7\u30C6\u30A3\u304C\u518D\u751F\u306B\u53CD\u6620\u3055\u308C\u307E\u305B\u3093\uFF08\u58F0\u91CF\u3067\u8ABF\u6574\u3057\u3066\u304F\u3060\u3055\u3044\uFF09" : "";
|
|
13615
14154
|
};
|
|
13616
14155
|
syncVelocityDisabled();
|
|
14156
|
+
const trackCompInput = refs.trackBody.querySelector(
|
|
14157
|
+
'[data-dtm="track-comp"]'
|
|
14158
|
+
);
|
|
14159
|
+
const trackCompLabel = refs.trackBody.querySelector(
|
|
14160
|
+
'[data-dtm="track-comp-label"]'
|
|
14161
|
+
);
|
|
14162
|
+
const trackWidthInput = refs.trackBody.querySelector(
|
|
14163
|
+
'[data-dtm="track-width"]'
|
|
14164
|
+
);
|
|
14165
|
+
const trackWidthLabel = refs.trackBody.querySelector(
|
|
14166
|
+
'[data-dtm="track-width-label"]'
|
|
14167
|
+
);
|
|
14168
|
+
const trackCompInfo = refs.trackBody.querySelector(
|
|
14169
|
+
'[data-dtm="track-comp-info"]'
|
|
14170
|
+
);
|
|
14171
|
+
const trackWidthInfo = refs.trackBody.querySelector(
|
|
14172
|
+
'[data-dtm="track-width-info"]'
|
|
14173
|
+
);
|
|
14174
|
+
trackCompInput.value = String(active.trackCompression);
|
|
14175
|
+
trackCompLabel.textContent = `${active.trackCompression}%`;
|
|
14176
|
+
trackWidthInput.value = String(active.trackWidth);
|
|
14177
|
+
trackWidthLabel.textContent = `${active.trackWidth}%`;
|
|
14178
|
+
trackCompInput.addEventListener("input", () => {
|
|
14179
|
+
active.trackCompression = Number.parseInt(trackCompInput.value, 10);
|
|
14180
|
+
trackCompLabel.textContent = `${active.trackCompression}%`;
|
|
14181
|
+
options.onTrackCompressionChange?.(
|
|
14182
|
+
active.config.id,
|
|
14183
|
+
active.trackCompression
|
|
14184
|
+
);
|
|
14185
|
+
});
|
|
14186
|
+
trackWidthInput.addEventListener("input", () => {
|
|
14187
|
+
active.trackWidth = Number.parseInt(trackWidthInput.value, 10);
|
|
14188
|
+
trackWidthLabel.textContent = `${active.trackWidth}%`;
|
|
14189
|
+
options.onTrackWidthChange?.(active.config.id, active.trackWidth);
|
|
14190
|
+
});
|
|
14191
|
+
trackCompInfo.addEventListener("click", () => {
|
|
14192
|
+
showModal("\u97F3\u5727\u5F37\u5316\u306E\u89E3\u8AAC", TRACK_COMPRESSION_INFO_HTML);
|
|
14193
|
+
});
|
|
14194
|
+
trackWidthInfo.addEventListener("click", () => {
|
|
14195
|
+
showModal("\u30B9\u30C6\u30EC\u30AA\u5E45\u306E\u89E3\u8AAC", TRACK_WIDTH_INFO_HTML);
|
|
14196
|
+
});
|
|
13617
14197
|
const instRow = document.createElement("div");
|
|
13618
14198
|
instRow.className = "dtm-row";
|
|
13619
14199
|
instRow.innerHTML = `<span class="dtm-label">\u697D\u5668</span>`;
|
|
@@ -13677,13 +14257,6 @@ var mountDAW = (target, options = {}) => {
|
|
|
13677
14257
|
<span class="dtm-label">\u266A UTAU</span>
|
|
13678
14258
|
<select class="dtm-select" data-dtm="lyric-model" aria-label="\u6B4C\u5531\u30E2\u30C7\u30EB"></select>
|
|
13679
14259
|
<img class="dtm-lyric-icon dtm-hidden" data-dtm="lyric-icon" width="20" height="20" alt="" draggable="false">
|
|
13680
|
-
<select class="dtm-select" data-dtm="lyric-octave" aria-label="\u30AA\u30AF\u30BF\u30FC\u30D6\uFF08\u97F3\u6E90\u306E\u5F97\u610F\u97F3\u57DF\u306B\u5408\u308F\u305B\u308B\uFF09" title="\u30AA\u30AF\u30BF\u30FC\u30D6">
|
|
13681
|
-
<option value="2">+2 oct</option>
|
|
13682
|
-
<option value="1">+1 oct</option>
|
|
13683
|
-
<option value="0">\xB10 oct</option>
|
|
13684
|
-
<option value="-1">-1 oct</option>
|
|
13685
|
-
<option value="-2">-2 oct</option>
|
|
13686
|
-
</select>
|
|
13687
14260
|
<span class="dtm-label dtm-grow" data-dtm="lyric-count" style="text-align:right"></span>
|
|
13688
14261
|
</div>
|
|
13689
14262
|
<div class="dtm-row dtm-hidden" data-dtm="lyric-terms" style="font-size:10px;gap:4px;color:var(--dtm-warn)">
|
|
@@ -13709,11 +14282,48 @@ var mountDAW = (target, options = {}) => {
|
|
|
13709
14282
|
<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">
|
|
13710
14283
|
<span class="dtm-label" data-dtm="lyric-vol-label"></span>
|
|
13711
14284
|
</div>
|
|
13712
|
-
<
|
|
13713
|
-
<
|
|
13714
|
-
<
|
|
13715
|
-
|
|
13716
|
-
|
|
14285
|
+
<details class="dtm-advanced" data-dtm="lyric-advanced">
|
|
14286
|
+
<summary>\u8A73\u7D30\u8A2D\u5B9A</summary>
|
|
14287
|
+
<div class="dtm-row">
|
|
14288
|
+
<span class="dtm-label">\u30AA\u30AF\u30BF\u30FC\u30D6</span>
|
|
14289
|
+
<select class="dtm-select" data-dtm="lyric-octave" aria-label="\u30AA\u30AF\u30BF\u30FC\u30D6\uFF08\u97F3\u6E90\u306E\u5F97\u610F\u97F3\u57DF\u306B\u5408\u308F\u305B\u308B\uFF09" title="\u30AA\u30AF\u30BF\u30FC\u30D6">
|
|
14290
|
+
<option value="2">+2 oct</option>
|
|
14291
|
+
<option value="1">+1 oct</option>
|
|
14292
|
+
<option value="0">\xB10 oct</option>
|
|
14293
|
+
<option value="-1">-1 oct</option>
|
|
14294
|
+
<option value="-2">-2 oct</option>
|
|
14295
|
+
</select>
|
|
14296
|
+
</div>
|
|
14297
|
+
<div class="dtm-row">
|
|
14298
|
+
<span class="dtm-label">\u5B9A\u4F4D</span>
|
|
14299
|
+
<input type="range" class="dtm-range dtm-grow" data-dtm="lyric-pan" min="0" max="127" aria-label="\u6B4C\u5531\u306E\u30B9\u30C6\u30EC\u30AA\u5B9A\u4F4D\uFF08\u5DE6\u53F3\uFF09">
|
|
14300
|
+
<span class="dtm-label" data-dtm="lyric-pan-label"></span>
|
|
14301
|
+
</div>
|
|
14302
|
+
<div class="dtm-row">
|
|
14303
|
+
<span class="dtm-label">\u30EA\u30D0\u30FC\u30D6\u9001\u308A</span>
|
|
14304
|
+
<input type="range" class="dtm-range dtm-grow" data-dtm="lyric-reverb" min="0" max="100" aria-label="\u3053\u306E\u30C8\u30E9\u30C3\u30AF\u304B\u3089\u30DE\u30B9\u30BF\u30EA\u30D0\u30FC\u30D6\u3078\u9001\u308B\u91CF\uFF08\u30DE\u30B9\u30BF\u306E\u30EA\u30D0\u30FC\u30D6\u3064\u307E\u307F\u304C0%\u3060\u3068\u7121\u97F3\uFF09">
|
|
14305
|
+
<span class="dtm-label" data-dtm="lyric-reverb-label"></span>
|
|
14306
|
+
<button class="dtm-infobtn" data-dtm="lyric-reverb-info" title="\u30EA\u30D0\u30FC\u30D6\u9001\u308A\u306E\u89E3\u8AAC">${icon("info", 12)}</button>
|
|
14307
|
+
</div>
|
|
14308
|
+
<div class="dtm-row">
|
|
14309
|
+
<span class="dtm-label">\u30B8\u30A7\u30F3\u30C0\u30FC</span>
|
|
14310
|
+
<input type="range" class="dtm-range dtm-grow" data-dtm="lyric-gender" min="0" max="100" aria-label="\u30D5\u30A9\u30EB\u30DE\u30F3\u30C8/\u30B8\u30A7\u30F3\u30C0\u30FC\u30D5\u30A1\u30AF\u30BF\u30FC\uFF08koe\u97F3\u6E90\u9650\u5B9A\uFF09">
|
|
14311
|
+
<span class="dtm-label" data-dtm="lyric-gender-label"></span>
|
|
14312
|
+
<button class="dtm-infobtn" data-dtm="lyric-gender-info" title="\u30B8\u30A7\u30F3\u30C0\u30FC\u306E\u89E3\u8AAC">${icon("info", 12)}</button>
|
|
14313
|
+
</div>
|
|
14314
|
+
<div class="dtm-row">
|
|
14315
|
+
<span class="dtm-label">\u30D6\u30EC\u30B7\u30CD\u30B9</span>
|
|
14316
|
+
<input type="range" class="dtm-range dtm-grow" data-dtm="lyric-breathiness" min="0" max="100" aria-label="\u30D6\u30EC\u30B7\u30CD\u30B9\uFF08\u606F\u6210\u5206\u3001koe\u97F3\u6E90\u9650\u5B9A\uFF09">
|
|
14317
|
+
<span class="dtm-label" data-dtm="lyric-breathiness-label"></span>
|
|
14318
|
+
<button class="dtm-infobtn" data-dtm="lyric-breathiness-info" title="\u30D6\u30EC\u30B7\u30CD\u30B9\u306E\u89E3\u8AAC">${icon("info", 12)}</button>
|
|
14319
|
+
</div>
|
|
14320
|
+
<div class="dtm-row">
|
|
14321
|
+
<span class="dtm-label" style="display:inline-flex;align-items:center;gap:2px">
|
|
14322
|
+
<input type="checkbox" data-dtm="lyric-vibrato" aria-label="\u81EA\u52D5\u30D3\u30D6\u30E9\u30FC\u30C8">\u30D3\u30D6\u30E9\u30FC\u30C8
|
|
14323
|
+
</span>
|
|
14324
|
+
<button class="dtm-infobtn" data-dtm="lyric-vibrato-info" title="\u81EA\u52D5\u30D3\u30D6\u30E9\u30FC\u30C8\u306E\u89E3\u8AAC">${icon("info", 12)}</button>
|
|
14325
|
+
</div>
|
|
14326
|
+
</details>
|
|
13717
14327
|
<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>
|
|
13718
14328
|
</div>`;
|
|
13719
14329
|
refs.trackBody.appendChild(lyricDiv);
|
|
@@ -13747,6 +14357,51 @@ var mountDAW = (target, options = {}) => {
|
|
|
13747
14357
|
const lyricPanLabel = lyricDiv.querySelector(
|
|
13748
14358
|
'[data-dtm="lyric-pan-label"]'
|
|
13749
14359
|
);
|
|
14360
|
+
const lyricReverb = lyricDiv.querySelector(
|
|
14361
|
+
'[data-dtm="lyric-reverb"]'
|
|
14362
|
+
);
|
|
14363
|
+
const lyricReverbLabel = lyricDiv.querySelector(
|
|
14364
|
+
'[data-dtm="lyric-reverb-label"]'
|
|
14365
|
+
);
|
|
14366
|
+
const lyricReverbInfo = lyricDiv.querySelector(
|
|
14367
|
+
'[data-dtm="lyric-reverb-info"]'
|
|
14368
|
+
);
|
|
14369
|
+
lyricReverbInfo.addEventListener("click", () => {
|
|
14370
|
+
showModal("\u30EA\u30D0\u30FC\u30D6\u9001\u308A\u306E\u89E3\u8AAC", LYRIC_REVERB_INFO_HTML);
|
|
14371
|
+
});
|
|
14372
|
+
const lyricGender = lyricDiv.querySelector(
|
|
14373
|
+
'[data-dtm="lyric-gender"]'
|
|
14374
|
+
);
|
|
14375
|
+
const lyricGenderLabel = lyricDiv.querySelector(
|
|
14376
|
+
'[data-dtm="lyric-gender-label"]'
|
|
14377
|
+
);
|
|
14378
|
+
const lyricGenderInfo = lyricDiv.querySelector(
|
|
14379
|
+
'[data-dtm="lyric-gender-info"]'
|
|
14380
|
+
);
|
|
14381
|
+
lyricGenderInfo.addEventListener("click", () => {
|
|
14382
|
+
showModal("\u30B8\u30A7\u30F3\u30C0\u30FC\u306E\u89E3\u8AAC", GENDER_INFO_HTML);
|
|
14383
|
+
});
|
|
14384
|
+
const lyricBreathiness = lyricDiv.querySelector(
|
|
14385
|
+
'[data-dtm="lyric-breathiness"]'
|
|
14386
|
+
);
|
|
14387
|
+
const lyricBreathinessLabel = lyricDiv.querySelector(
|
|
14388
|
+
'[data-dtm="lyric-breathiness-label"]'
|
|
14389
|
+
);
|
|
14390
|
+
const lyricBreathinessInfo = lyricDiv.querySelector(
|
|
14391
|
+
'[data-dtm="lyric-breathiness-info"]'
|
|
14392
|
+
);
|
|
14393
|
+
lyricBreathinessInfo.addEventListener("click", () => {
|
|
14394
|
+
showModal("\u30D6\u30EC\u30B7\u30CD\u30B9\u306E\u89E3\u8AAC", BREATHINESS_INFO_HTML);
|
|
14395
|
+
});
|
|
14396
|
+
const lyricVibrato = lyricDiv.querySelector(
|
|
14397
|
+
'[data-dtm="lyric-vibrato"]'
|
|
14398
|
+
);
|
|
14399
|
+
const lyricVibratoInfo = lyricDiv.querySelector(
|
|
14400
|
+
'[data-dtm="lyric-vibrato-info"]'
|
|
14401
|
+
);
|
|
14402
|
+
lyricVibratoInfo.addEventListener("click", () => {
|
|
14403
|
+
showModal("\u81EA\u52D5\u30D3\u30D6\u30E9\u30FC\u30C8\u89E3\u8AAC", VIBRATO_INFO_HTML);
|
|
14404
|
+
});
|
|
13750
14405
|
const lyricTerms = lyricDiv.querySelector(
|
|
13751
14406
|
'[data-dtm="lyric-terms"]'
|
|
13752
14407
|
);
|
|
@@ -13808,6 +14463,13 @@ var mountDAW = (target, options = {}) => {
|
|
|
13808
14463
|
lyricVolLabel.textContent = String(active.vocalVolume);
|
|
13809
14464
|
lyricPan.value = String(active.vocalPan);
|
|
13810
14465
|
lyricPanLabel.textContent = fmtPan(active.vocalPan);
|
|
14466
|
+
lyricReverb.value = String(active.vocalReverb);
|
|
14467
|
+
lyricReverbLabel.textContent = `${active.vocalReverb}%`;
|
|
14468
|
+
lyricGender.value = String(active.vocalGender);
|
|
14469
|
+
lyricGenderLabel.textContent = `${active.vocalGender}`;
|
|
14470
|
+
lyricBreathiness.value = String(active.vocalBreathiness);
|
|
14471
|
+
lyricBreathinessLabel.textContent = `${active.vocalBreathiness}`;
|
|
14472
|
+
lyricVibrato.checked = active.vocalVibrato;
|
|
13811
14473
|
const updateLyricCount = () => {
|
|
13812
14474
|
const n = normalizeLyrics(lyricInput.value).length;
|
|
13813
14475
|
lyricCount.textContent = active.lyricModel && n > 0 ? `${n}\u97F3\u7BC0` : "";
|
|
@@ -13857,7 +14519,6 @@ var mountDAW = (target, options = {}) => {
|
|
|
13857
14519
|
};
|
|
13858
14520
|
const syncLyricVisibility = () => {
|
|
13859
14521
|
lyricBody.style.display = active.lyricModel ? "" : "none";
|
|
13860
|
-
lyricOctaveSel.style.display = active.lyricModel ? "" : "none";
|
|
13861
14522
|
updateLyricCount();
|
|
13862
14523
|
syncLyricTerms();
|
|
13863
14524
|
syncLyricIcon();
|
|
@@ -13926,6 +14587,10 @@ var mountDAW = (target, options = {}) => {
|
|
|
13926
14587
|
active.vocalOctave = Number.parseInt(lyricOctaveSel.value, 10);
|
|
13927
14588
|
fireLyricsChange(active);
|
|
13928
14589
|
});
|
|
14590
|
+
lyricVibrato.addEventListener("change", () => {
|
|
14591
|
+
active.vocalVibrato = lyricVibrato.checked;
|
|
14592
|
+
fireLyricsChange(active);
|
|
14593
|
+
});
|
|
13929
14594
|
lyricInput.addEventListener("input", () => {
|
|
13930
14595
|
active.lyrics = lyricInput.value;
|
|
13931
14596
|
updateLyricCount();
|
|
@@ -13949,6 +14614,21 @@ var mountDAW = (target, options = {}) => {
|
|
|
13949
14614
|
lyricPanLabel.textContent = fmtPan(64);
|
|
13950
14615
|
fireLyricsChange(active);
|
|
13951
14616
|
});
|
|
14617
|
+
lyricReverb.addEventListener("input", () => {
|
|
14618
|
+
active.vocalReverb = Number.parseInt(lyricReverb.value, 10);
|
|
14619
|
+
lyricReverbLabel.textContent = `${active.vocalReverb}%`;
|
|
14620
|
+
fireLyricsChange(active);
|
|
14621
|
+
});
|
|
14622
|
+
lyricGender.addEventListener("input", () => {
|
|
14623
|
+
active.vocalGender = Number.parseInt(lyricGender.value, 10);
|
|
14624
|
+
lyricGenderLabel.textContent = `${active.vocalGender}`;
|
|
14625
|
+
fireLyricsChange(active);
|
|
14626
|
+
});
|
|
14627
|
+
lyricBreathiness.addEventListener("input", () => {
|
|
14628
|
+
active.vocalBreathiness = Number.parseInt(lyricBreathiness.value, 10);
|
|
14629
|
+
lyricBreathinessLabel.textContent = `${active.vocalBreathiness}`;
|
|
14630
|
+
fireLyricsChange(active);
|
|
14631
|
+
});
|
|
13952
14632
|
}
|
|
13953
14633
|
if (active.config.id === "chord" && showChord) {
|
|
13954
14634
|
const div = document.createElement("div");
|
|
@@ -14032,18 +14712,28 @@ var mountDAW = (target, options = {}) => {
|
|
|
14032
14712
|
const limitSteps = barLimitBars > 0 ? barLimitBars * renderConfig.stepsPerBar : Infinity;
|
|
14033
14713
|
const clipNotes = (notes) => limitSteps === Infinity ? notes : notes.filter((n) => n.startStep < limitSteps);
|
|
14034
14714
|
const trackInstrumentsForMeta = {};
|
|
14035
|
-
|
|
14036
|
-
|
|
14715
|
+
const trackCompressionForMeta = {};
|
|
14716
|
+
const trackWidthForMeta = {};
|
|
14717
|
+
trackStates.forEach((t, i2) => {
|
|
14718
|
+
if (t.trackInstrument) trackInstrumentsForMeta[i2] = t.trackInstrument;
|
|
14719
|
+
if (t.trackCompression !== 0)
|
|
14720
|
+
trackCompressionForMeta[i2] = t.trackCompression;
|
|
14721
|
+
if (t.trackWidth !== 100) trackWidthForMeta[i2] = t.trackWidth;
|
|
14037
14722
|
});
|
|
14038
14723
|
const trackInstMeta = Object.keys(trackInstrumentsForMeta).length > 0 ? trackInstrumentsForMeta : void 0;
|
|
14724
|
+
const trackCompMeta = Object.keys(trackCompressionForMeta).length > 0 ? trackCompressionForMeta : void 0;
|
|
14725
|
+
const trackWidthMeta = Object.keys(trackWidthForMeta).length > 0 ? trackWidthForMeta : void 0;
|
|
14039
14726
|
const metaLineFull = formatMmlMeta(
|
|
14040
14727
|
{
|
|
14041
14728
|
instrument: currentInstrument || void 0,
|
|
14042
14729
|
drum: currentDrumPattern !== "none" ? currentDrumPattern : void 0,
|
|
14043
14730
|
volume: masterVolume,
|
|
14044
14731
|
drumVolume,
|
|
14732
|
+
reverb: reverbAmount,
|
|
14045
14733
|
mode,
|
|
14046
|
-
trackInstruments: trackInstMeta
|
|
14734
|
+
trackInstruments: trackInstMeta,
|
|
14735
|
+
trackCompression: trackCompMeta,
|
|
14736
|
+
trackWidth: trackWidthMeta
|
|
14047
14737
|
},
|
|
14048
14738
|
" "
|
|
14049
14739
|
);
|
|
@@ -14053,8 +14743,11 @@ var mountDAW = (target, options = {}) => {
|
|
|
14053
14743
|
drum: currentDrumPattern !== "none" ? currentDrumPattern : void 0,
|
|
14054
14744
|
volume: masterVolume,
|
|
14055
14745
|
drumVolume,
|
|
14746
|
+
reverb: reverbAmount,
|
|
14056
14747
|
mode,
|
|
14057
|
-
trackInstruments: trackInstMeta
|
|
14748
|
+
trackInstruments: trackInstMeta,
|
|
14749
|
+
trackCompression: trackCompMeta,
|
|
14750
|
+
trackWidth: trackWidthMeta
|
|
14058
14751
|
},
|
|
14059
14752
|
""
|
|
14060
14753
|
);
|
|
@@ -14068,10 +14761,10 @@ var mountDAW = (target, options = {}) => {
|
|
|
14068
14761
|
const monoTracks = decomposeToMonophonic(allNotes);
|
|
14069
14762
|
const refCore = trackStates[0].core;
|
|
14070
14763
|
const decomposedFull = monoTracks.map(
|
|
14071
|
-
(notes,
|
|
14764
|
+
(notes, i2) => `@${i2} ${refCore.getMMLFromNotes(notes, bpm, 100).trim()}`
|
|
14072
14765
|
);
|
|
14073
14766
|
const decomposedMini = monoTracks.map(
|
|
14074
|
-
(notes,
|
|
14767
|
+
(notes, i2) => `@${i2}${refCore.getMMLFromNotes(notes, bpm, 100).trim().replace(/\s+/g, "")}`
|
|
14075
14768
|
);
|
|
14076
14769
|
const full2 = [metaLineFull, ...decomposedFull, MML_END_MARKER].filter((s) => s.length > 0).join(";\n");
|
|
14077
14770
|
const minified2 = [metaLineMini, ...decomposedMini, MML_END_MARKER].filter((s) => s.length > 0).join(";");
|
|
@@ -14085,34 +14778,42 @@ var mountDAW = (target, options = {}) => {
|
|
|
14085
14778
|
}
|
|
14086
14779
|
const trackLines = [];
|
|
14087
14780
|
const trackLinesMini = [];
|
|
14088
|
-
trackStates.forEach((t,
|
|
14781
|
+
trackStates.forEach((t, i2) => {
|
|
14089
14782
|
const notes = clipNotes(t.core.getNotes());
|
|
14090
14783
|
if (notes.length > 0) {
|
|
14091
14784
|
const mml = t.core.getMMLFromNotes(notes, bpm, t.volume).trim();
|
|
14092
|
-
trackLines.push(`@${
|
|
14093
|
-
trackLinesMini.push(`@${
|
|
14785
|
+
trackLines.push(`@${i2} ${mml}`);
|
|
14786
|
+
trackLinesMini.push(`@${i2}${mml.replace(/\s+/g, "")}`);
|
|
14094
14787
|
}
|
|
14095
14788
|
});
|
|
14096
|
-
const lyricLines = trackStates.map((t,
|
|
14097
|
-
i,
|
|
14789
|
+
const lyricLines = trackStates.map((t, i2) => ({
|
|
14790
|
+
i: i2,
|
|
14098
14791
|
notes: clipNotes(t.core.getNotes()),
|
|
14099
14792
|
text: t.lyrics.replace(/[\r\n]+/g, " ").trim(),
|
|
14100
14793
|
model: t.lyricModel.trim(),
|
|
14101
14794
|
vol: t.vocalVolume,
|
|
14102
14795
|
gate: t.vocalGate,
|
|
14103
14796
|
pan: t.vocalPan,
|
|
14104
|
-
oct: t.vocalOctave
|
|
14797
|
+
oct: t.vocalOctave,
|
|
14798
|
+
vib: t.vocalVibrato,
|
|
14799
|
+
rev: t.vocalReverb,
|
|
14800
|
+
gen: t.vocalGender,
|
|
14801
|
+
bre: t.vocalBreathiness
|
|
14105
14802
|
})).filter(
|
|
14106
|
-
(
|
|
14107
|
-
).map((
|
|
14803
|
+
(x2) => x2.model.length > 0 && x2.text.length > 0 && x2.notes.length > 0
|
|
14804
|
+
).map((x2) => {
|
|
14108
14805
|
const params = [
|
|
14109
|
-
|
|
14110
|
-
|
|
14111
|
-
|
|
14112
|
-
|
|
14806
|
+
x2.vol === DEFAULT_VOCAL_VOLUME ? "" : `v${x2.vol}`,
|
|
14807
|
+
x2.gate === 100 ? "" : `q${x2.gate}`,
|
|
14808
|
+
x2.pan === 64 ? "" : `p${x2.pan}`,
|
|
14809
|
+
x2.oct === 0 ? "" : `o${x2.oct}`,
|
|
14810
|
+
x2.vib ? "b1" : "",
|
|
14811
|
+
x2.rev === 0 ? "" : `r${x2.rev}`,
|
|
14812
|
+
x2.gen === 50 ? "" : `g${x2.gen}`,
|
|
14813
|
+
x2.bre === 50 ? "" : `h${x2.bre}`
|
|
14113
14814
|
].filter((s) => s.length > 0).join(" ");
|
|
14114
|
-
const head = params ? `${
|
|
14115
|
-
return `@@${
|
|
14815
|
+
const head = params ? `${x2.model} ${params}` : x2.model;
|
|
14816
|
+
return `@@${x2.i} ${head} ${x2.text}`;
|
|
14116
14817
|
});
|
|
14117
14818
|
const customVocalDecls = [];
|
|
14118
14819
|
for (const [key, def] of customVocalsMap) {
|
|
@@ -14249,18 +14950,37 @@ var mountDAW = (target, options = {}) => {
|
|
|
14249
14950
|
refs.drumVolume.value = String(meta.drumVolume);
|
|
14250
14951
|
refs.drumVolumeLabel.textContent = `${drumVolume}%`;
|
|
14251
14952
|
}
|
|
14953
|
+
if (meta.reverb !== void 0) {
|
|
14954
|
+
reverbAmount = meta.reverb;
|
|
14955
|
+
refs.reverbAmount.value = String(meta.reverb);
|
|
14956
|
+
refs.reverbAmountLabel.textContent = `${meta.reverb}%`;
|
|
14957
|
+
options.onReverbChange?.(meta.reverb);
|
|
14958
|
+
}
|
|
14252
14959
|
}
|
|
14253
|
-
trackStates.forEach((t,
|
|
14254
|
-
if (applyActiveOnly &&
|
|
14255
|
-
const name = normalizeInstrumentName(meta.trackInstruments?.[
|
|
14960
|
+
trackStates.forEach((t, i2) => {
|
|
14961
|
+
if (applyActiveOnly && i2 !== activeTrackIndex) return;
|
|
14962
|
+
const name = normalizeInstrumentName(meta.trackInstruments?.[i2] ?? "");
|
|
14256
14963
|
if (t.trackInstrument !== name) {
|
|
14257
14964
|
t.trackInstrument = name;
|
|
14258
|
-
options.onTrackInstrumentChange?.(
|
|
14965
|
+
options.onTrackInstrumentChange?.(i2, name);
|
|
14966
|
+
}
|
|
14967
|
+
});
|
|
14968
|
+
trackStates.forEach((t, i2) => {
|
|
14969
|
+
if (applyActiveOnly && i2 !== activeTrackIndex) return;
|
|
14970
|
+
const comp = meta.trackCompression?.[i2] ?? 0;
|
|
14971
|
+
if (t.trackCompression !== comp) {
|
|
14972
|
+
t.trackCompression = comp;
|
|
14973
|
+
options.onTrackCompressionChange?.(t.config.id, comp);
|
|
14974
|
+
}
|
|
14975
|
+
const width = meta.trackWidth?.[i2] ?? 100;
|
|
14976
|
+
if (t.trackWidth !== width) {
|
|
14977
|
+
t.trackWidth = width;
|
|
14978
|
+
options.onTrackWidthChange?.(t.config.id, width);
|
|
14259
14979
|
}
|
|
14260
14980
|
});
|
|
14261
|
-
trackStates.forEach((t,
|
|
14262
|
-
if (applyActiveOnly &&
|
|
14263
|
-
const v = trackVelocity.get(
|
|
14981
|
+
trackStates.forEach((t, i2) => {
|
|
14982
|
+
if (applyActiveOnly && i2 !== activeTrackIndex) return;
|
|
14983
|
+
const v = trackVelocity.get(i2);
|
|
14264
14984
|
if (v !== void 0 && v !== t.volume) {
|
|
14265
14985
|
t.volume = v;
|
|
14266
14986
|
t.core.setVolume(v);
|
|
@@ -14274,6 +14994,10 @@ var mountDAW = (target, options = {}) => {
|
|
|
14274
14994
|
active.vocalGate = 100;
|
|
14275
14995
|
active.vocalPan = 64;
|
|
14276
14996
|
active.vocalOctave = 0;
|
|
14997
|
+
active.vocalVibrato = false;
|
|
14998
|
+
active.vocalReverb = 0;
|
|
14999
|
+
active.vocalGender = 50;
|
|
15000
|
+
active.vocalBreathiness = 50;
|
|
14277
15001
|
} else {
|
|
14278
15002
|
for (const t of trackStates) {
|
|
14279
15003
|
t.lyrics = "";
|
|
@@ -14282,6 +15006,10 @@ var mountDAW = (target, options = {}) => {
|
|
|
14282
15006
|
t.vocalGate = 100;
|
|
14283
15007
|
t.vocalPan = 64;
|
|
14284
15008
|
t.vocalOctave = 0;
|
|
15009
|
+
t.vocalVibrato = false;
|
|
15010
|
+
t.vocalReverb = 0;
|
|
15011
|
+
t.vocalGender = 50;
|
|
15012
|
+
t.vocalBreathiness = 50;
|
|
14285
15013
|
}
|
|
14286
15014
|
}
|
|
14287
15015
|
lyrics?.forEach((lt) => {
|
|
@@ -14294,6 +15022,10 @@ var mountDAW = (target, options = {}) => {
|
|
|
14294
15022
|
t.vocalGate = lt.gate;
|
|
14295
15023
|
t.vocalPan = lt.pan;
|
|
14296
15024
|
t.vocalOctave = lt.octave ?? 0;
|
|
15025
|
+
t.vocalVibrato = lt.vibrato ?? false;
|
|
15026
|
+
t.vocalReverb = lt.reverb ?? 0;
|
|
15027
|
+
t.vocalGender = lt.gender ?? 50;
|
|
15028
|
+
t.vocalBreathiness = lt.breathiness ?? 50;
|
|
14297
15029
|
});
|
|
14298
15030
|
for (const p of placements) {
|
|
14299
15031
|
if (applyActiveOnly && p.trackIndex !== activeTrackIndex) continue;
|
|
@@ -14372,6 +15104,10 @@ var mountDAW = (target, options = {}) => {
|
|
|
14372
15104
|
active.vocalGate = 100;
|
|
14373
15105
|
active.vocalPan = 64;
|
|
14374
15106
|
active.vocalOctave = 0;
|
|
15107
|
+
active.vocalVibrato = false;
|
|
15108
|
+
active.vocalReverb = 0;
|
|
15109
|
+
active.vocalGender = 50;
|
|
15110
|
+
active.vocalBreathiness = 50;
|
|
14375
15111
|
} else {
|
|
14376
15112
|
clearAll();
|
|
14377
15113
|
for (const t of trackStates) t.core.setLoadMode(true);
|
|
@@ -14382,6 +15118,10 @@ var mountDAW = (target, options = {}) => {
|
|
|
14382
15118
|
t.vocalGate = 100;
|
|
14383
15119
|
t.vocalPan = 64;
|
|
14384
15120
|
t.vocalOctave = 0;
|
|
15121
|
+
t.vocalVibrato = false;
|
|
15122
|
+
t.vocalReverb = 0;
|
|
15123
|
+
t.vocalGender = 50;
|
|
15124
|
+
t.vocalBreathiness = 50;
|
|
14385
15125
|
}
|
|
14386
15126
|
}
|
|
14387
15127
|
const { placements, bpm: parsedBpm } = isAdvanced ? extractMidiPlacementsByTrack(
|
|
@@ -14516,6 +15256,12 @@ var mountDAW = (target, options = {}) => {
|
|
|
14516
15256
|
isSolo = refs.soloCheckbox.checked;
|
|
14517
15257
|
redrawAll();
|
|
14518
15258
|
});
|
|
15259
|
+
unsubscribeClip = options.clipMeter?.onClipChange((clipping) => {
|
|
15260
|
+
refs.clipBadge.classList.toggle("dtm-hidden", !clipping);
|
|
15261
|
+
});
|
|
15262
|
+
refs.clipBadge.addEventListener("click", () => {
|
|
15263
|
+
options.clipMeter?.reset();
|
|
15264
|
+
});
|
|
14519
15265
|
refs.toolPen.addEventListener("click", () => setToolMode("pen"));
|
|
14520
15266
|
refs.toolSelect.addEventListener("click", () => setToolMode("select"));
|
|
14521
15267
|
refs.toolEraser.addEventListener("click", () => setToolMode("eraser"));
|
|
@@ -14591,6 +15337,35 @@ var mountDAW = (target, options = {}) => {
|
|
|
14591
15337
|
refs.masterVolumeLabel.textContent = `${masterVolume}%`;
|
|
14592
15338
|
options.singingVoices?.setVolume(masterVolume / 100);
|
|
14593
15339
|
});
|
|
15340
|
+
refs.reverbAmount.addEventListener("input", () => {
|
|
15341
|
+
reverbAmount = Number.parseInt(refs.reverbAmount.value, 10) || 0;
|
|
15342
|
+
refs.reverbAmountLabel.textContent = `${reverbAmount}%`;
|
|
15343
|
+
options.onReverbChange?.(reverbAmount);
|
|
15344
|
+
});
|
|
15345
|
+
refs.reverbAmountInfoBtn.addEventListener("click", () => {
|
|
15346
|
+
showModal("\u30DE\u30B9\u30BF\u30EA\u30D0\u30FC\u30D6\u306E\u89E3\u8AAC", MASTER_REVERB_INFO_HTML);
|
|
15347
|
+
});
|
|
15348
|
+
refs.autoMasterInfoBtn.addEventListener("click", () => {
|
|
15349
|
+
showModal("\u304A\u307E\u304B\u305B\u30DE\u30B9\u30BF\u30EA\u30F3\u30B0\u89E3\u8AAC", AUTO_MASTER_INFO_HTML);
|
|
15350
|
+
});
|
|
15351
|
+
refs.autoMasterBtn.addEventListener("click", () => {
|
|
15352
|
+
reverbAmount = 20;
|
|
15353
|
+
refs.reverbAmount.value = "20";
|
|
15354
|
+
refs.reverbAmountLabel.textContent = "20%";
|
|
15355
|
+
options.onReverbChange?.(20);
|
|
15356
|
+
for (const t of trackStates) {
|
|
15357
|
+
t.trackCompression = 35;
|
|
15358
|
+
t.trackWidth = 115;
|
|
15359
|
+
options.onTrackCompressionChange?.(t.config.id, 35);
|
|
15360
|
+
options.onTrackWidthChange?.(t.config.id, 115);
|
|
15361
|
+
if (t.lyricModel) {
|
|
15362
|
+
t.vocalVibrato = true;
|
|
15363
|
+
t.vocalReverb = 25;
|
|
15364
|
+
fireLyricsChange(t);
|
|
15365
|
+
}
|
|
15366
|
+
}
|
|
15367
|
+
updateTrackPanel();
|
|
15368
|
+
});
|
|
14594
15369
|
refs.drumSelect.addEventListener("change", () => {
|
|
14595
15370
|
currentDrumPattern = refs.drumSelect.value;
|
|
14596
15371
|
options.onDrumChange?.(currentDrumPattern);
|
|
@@ -14871,7 +15646,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
14871
15646
|
console.error(e);
|
|
14872
15647
|
}
|
|
14873
15648
|
refs.midiTrackSelection.innerHTML = `<span class="dtm-label">\u30C8\u30E9\u30C3\u30AF</span>`;
|
|
14874
|
-
detectedTracks.forEach((t,
|
|
15649
|
+
detectedTracks.forEach((t, i2) => {
|
|
14875
15650
|
const btn = document.createElement("button");
|
|
14876
15651
|
btn.className = `dtm-btn ${t.selected ? "dtm-btn--primary" : "dtm-btn--ghost"}`;
|
|
14877
15652
|
btn.dataset.selected = String(t.selected);
|
|
@@ -14883,7 +15658,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
14883
15658
|
btn.classList.toggle("dtm-btn--ghost", !on);
|
|
14884
15659
|
});
|
|
14885
15660
|
refs.midiTrackSelection.appendChild(btn);
|
|
14886
|
-
if (
|
|
15661
|
+
if (i2 === 0) refs.midiTrackSelection.dataset.ready = "1";
|
|
14887
15662
|
});
|
|
14888
15663
|
refs.midiTrackSelection.classList.remove("dtm-hidden");
|
|
14889
15664
|
refs.overlay.hidden = true;
|
|
@@ -14893,9 +15668,9 @@ var mountDAW = (target, options = {}) => {
|
|
|
14893
15668
|
if (!pendingMidi) return;
|
|
14894
15669
|
const selected = [];
|
|
14895
15670
|
const btns = refs.midiTrackSelection.querySelectorAll("button");
|
|
14896
|
-
btns.forEach((b,
|
|
15671
|
+
btns.forEach((b, i2) => {
|
|
14897
15672
|
if (b.dataset.selected === "true")
|
|
14898
|
-
selected.push(detectedTracks[
|
|
15673
|
+
selected.push(detectedTracks[i2].index);
|
|
14899
15674
|
});
|
|
14900
15675
|
if (selected.length === 0) return;
|
|
14901
15676
|
if (!isAdvanced && options.onRequestAdvancedMode && selected.length > trackStates.length) {
|
|
@@ -14929,7 +15704,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
14929
15704
|
const refCore = trackStates[0].core;
|
|
14930
15705
|
const tempo = Math.round(parsedBpm) || bpm;
|
|
14931
15706
|
const lines = [];
|
|
14932
|
-
let
|
|
15707
|
+
let i2 = 0;
|
|
14933
15708
|
for (const notes of byTrack.values()) {
|
|
14934
15709
|
const asNotes = notes.map((p) => ({
|
|
14935
15710
|
id: 0,
|
|
@@ -14939,8 +15714,8 @@ var mountDAW = (target, options = {}) => {
|
|
|
14939
15714
|
velocity: p.velocity
|
|
14940
15715
|
}));
|
|
14941
15716
|
const mml = refCore.getMMLFromNotes(asNotes, tempo, 100).trim();
|
|
14942
|
-
lines.push(`@${
|
|
14943
|
-
|
|
15717
|
+
lines.push(`@${i2} ${mml}`);
|
|
15718
|
+
i2++;
|
|
14944
15719
|
}
|
|
14945
15720
|
return [...lines, MML_END_MARKER].join(";\n");
|
|
14946
15721
|
};
|
|
@@ -15555,6 +16330,12 @@ var mountDAW = (target, options = {}) => {
|
|
|
15555
16330
|
refs.drumVolume.value = String(drumVolume);
|
|
15556
16331
|
refs.drumVolumeLabel.textContent = `${drumVolume}%`;
|
|
15557
16332
|
},
|
|
16333
|
+
setReverbAmount: (amount) => {
|
|
16334
|
+
reverbAmount = clamp3(amount, 0, 100);
|
|
16335
|
+
refs.reverbAmount.value = String(reverbAmount);
|
|
16336
|
+
refs.reverbAmountLabel.textContent = `${reverbAmount}%`;
|
|
16337
|
+
options.onReverbChange?.(reverbAmount);
|
|
16338
|
+
},
|
|
15558
16339
|
applyPatch: (trackId, added, removed) => {
|
|
15559
16340
|
const track = trackStates.find((t) => t.config.id === trackId);
|
|
15560
16341
|
if (!track) return;
|
|
@@ -15594,6 +16375,10 @@ var mountDAW = (target, options = {}) => {
|
|
|
15594
16375
|
t.vocalGate = data.vocalGate;
|
|
15595
16376
|
t.vocalPan = data.vocalPan;
|
|
15596
16377
|
t.vocalOctave = data.vocalOctave;
|
|
16378
|
+
t.vocalVibrato = data.vocalVibrato ?? false;
|
|
16379
|
+
t.vocalReverb = data.vocalReverb ?? 0;
|
|
16380
|
+
t.vocalGender = data.vocalGender ?? 50;
|
|
16381
|
+
t.vocalBreathiness = data.vocalBreathiness ?? 50;
|
|
15597
16382
|
},
|
|
15598
16383
|
applyTrackInstrument: (trackIndex, instrumentName) => {
|
|
15599
16384
|
const t = trackStates[trackIndex];
|
|
@@ -15604,21 +16389,22 @@ var mountDAW = (target, options = {}) => {
|
|
|
15604
16389
|
},
|
|
15605
16390
|
noteToCanvas: (step, pitch) => {
|
|
15606
16391
|
const canvas = getGridCanvas();
|
|
15607
|
-
const
|
|
16392
|
+
const x2 = step * renderConfig.stepWidth - currentOffsetX;
|
|
15608
16393
|
const y = (renderConfig.keyCount - 1 - pitch) * renderConfig.keyHeight - currentOffsetY;
|
|
15609
|
-
const onScreen =
|
|
16394
|
+
const onScreen = x2 >= 0 && x2 <= canvas.width && y >= 0 && y <= canvas.height;
|
|
15610
16395
|
let side = null;
|
|
15611
16396
|
if (!onScreen) {
|
|
15612
|
-
if (
|
|
15613
|
-
else if (
|
|
16397
|
+
if (x2 < 0) side = "left";
|
|
16398
|
+
else if (x2 > canvas.width) side = "right";
|
|
15614
16399
|
else if (y < 0) side = "top";
|
|
15615
16400
|
else side = "bottom";
|
|
15616
16401
|
}
|
|
15617
|
-
return { x, y, onScreen, side };
|
|
16402
|
+
return { x: x2, y, onScreen, side };
|
|
15618
16403
|
},
|
|
15619
16404
|
destroy: () => {
|
|
15620
16405
|
sequencer.stop();
|
|
15621
16406
|
options.singingVoices?.stopStream();
|
|
16407
|
+
unsubscribeClip?.();
|
|
15622
16408
|
resizeObserver.disconnect();
|
|
15623
16409
|
document.removeEventListener("pointermove", onPointerMove);
|
|
15624
16410
|
document.removeEventListener("pointerup", onPointerUp);
|
|
@@ -15694,11 +16480,11 @@ var playSingingMML = async (mml, options = {}) => {
|
|
|
15694
16480
|
const semis = (lt.octave ?? 0) * 12;
|
|
15695
16481
|
const count = Math.min(sorted.length, lt.syllables.length);
|
|
15696
16482
|
const notes = [];
|
|
15697
|
-
for (let
|
|
15698
|
-
const n = sorted[
|
|
16483
|
+
for (let i2 = 0; i2 < count; i2++) {
|
|
16484
|
+
const n = sorted[i2];
|
|
15699
16485
|
if (n.startStep < fromStep) continue;
|
|
15700
16486
|
notes.push({
|
|
15701
|
-
syllable: lt.syllables[
|
|
16487
|
+
syllable: lt.syllables[i2],
|
|
15702
16488
|
pitch: n.pitch + semis,
|
|
15703
16489
|
startSec: (n.startStep - fromStep) * secondsPerStep,
|
|
15704
16490
|
durationSec: n.durationSteps * secondsPerStep * gate
|
|
@@ -15709,6 +16495,10 @@ var playSingingMML = async (mml, options = {}) => {
|
|
|
15709
16495
|
model: lt.model,
|
|
15710
16496
|
volume: vocalVolumeToGain(lt.volume ?? DEFAULT_VOCAL_VOLUME),
|
|
15711
16497
|
pan: panToStereo(lt.pan ?? DEFAULT_PAN),
|
|
16498
|
+
vibrato: lt.vibrato,
|
|
16499
|
+
reverbSend: (lt.reverb ?? 0) / 100,
|
|
16500
|
+
gender: (lt.gender ?? 50) / 100,
|
|
16501
|
+
breathiness: (lt.breathiness ?? 50) / 100,
|
|
15712
16502
|
notes
|
|
15713
16503
|
};
|
|
15714
16504
|
});
|
|
@@ -15923,7 +16713,7 @@ var createPianoRoll = (options, handlers) => {
|
|
|
15923
16713
|
let dragState = null;
|
|
15924
16714
|
let hasDragged = false;
|
|
15925
16715
|
let lastPreviewPitch = null;
|
|
15926
|
-
const findNoteAtPosition = (
|
|
16716
|
+
const findNoteAtPosition = (x2, y) => {
|
|
15927
16717
|
const { stepWidth, keyHeight, keyCount, pitchRangeStart } = getRenderConfig();
|
|
15928
16718
|
const offset = getDrawOffset();
|
|
15929
16719
|
for (const note of core.getNotes()) {
|
|
@@ -15934,7 +16724,7 @@ var createPianoRoll = (options, handlers) => {
|
|
|
15934
16724
|
const h = keyHeight;
|
|
15935
16725
|
const renderX = logicalX - offset.x;
|
|
15936
16726
|
const renderY = logicalY - offset.y;
|
|
15937
|
-
if (
|
|
16727
|
+
if (x2 >= renderX && x2 <= renderX + w && y >= renderY && y <= renderY + h) {
|
|
15938
16728
|
return note;
|
|
15939
16729
|
}
|
|
15940
16730
|
}
|
|
@@ -15942,10 +16732,10 @@ var createPianoRoll = (options, handlers) => {
|
|
|
15942
16732
|
};
|
|
15943
16733
|
const handlePointerMove = (e) => {
|
|
15944
16734
|
if (core.getToolMode() === "select" && isSelecting && selectionStart) {
|
|
15945
|
-
const { x, y } = getGridPosition(e);
|
|
15946
|
-
const minX = Math.min(
|
|
16735
|
+
const { x: x2, y } = getGridPosition(e);
|
|
16736
|
+
const minX = Math.min(x2, selectionStart.x);
|
|
15947
16737
|
const minY = Math.min(y, selectionStart.y);
|
|
15948
|
-
const width2 = Math.abs(
|
|
16738
|
+
const width2 = Math.abs(x2 - selectionStart.x);
|
|
15949
16739
|
const height2 = Math.abs(y - selectionStart.y);
|
|
15950
16740
|
selectionRect = { x: minX, y: minY, width: width2, height: height2 };
|
|
15951
16741
|
selectedNotes = getNotesInRect(selectionRect);
|
|
@@ -16003,10 +16793,10 @@ var createPianoRoll = (options, handlers) => {
|
|
|
16003
16793
|
}
|
|
16004
16794
|
};
|
|
16005
16795
|
gridCanvas.addEventListener("pointerdown", (e) => {
|
|
16006
|
-
const { x, y, step, pitch } = getGridPosition(e);
|
|
16796
|
+
const { x: x2, y, step, pitch } = getGridPosition(e);
|
|
16007
16797
|
const currentMode = core.getToolMode();
|
|
16008
16798
|
if (currentMode === "select") {
|
|
16009
|
-
const clickedNote = findNoteAtPosition(
|
|
16799
|
+
const clickedNote = findNoteAtPosition(x2, y);
|
|
16010
16800
|
if (selectionRect && clickedNote) {
|
|
16011
16801
|
const notesInRect = getNotesInRect(selectionRect);
|
|
16012
16802
|
if (notesInRect.some((n) => n.id === clickedNote.id)) {
|
|
@@ -16027,10 +16817,10 @@ var createPianoRoll = (options, handlers) => {
|
|
|
16027
16817
|
selectedNotes = [];
|
|
16028
16818
|
selectionRect = null;
|
|
16029
16819
|
isSelecting = true;
|
|
16030
|
-
selectionStart = { x, y, step, pitch };
|
|
16820
|
+
selectionStart = { x: x2, y, step, pitch };
|
|
16031
16821
|
return;
|
|
16032
16822
|
}
|
|
16033
|
-
const note = findNoteAtPosition(
|
|
16823
|
+
const note = findNoteAtPosition(x2, y);
|
|
16034
16824
|
if (!note) return;
|
|
16035
16825
|
const { stepWidth, keyHeight, keyCount, pitchRangeStart } = getRenderConfig();
|
|
16036
16826
|
const offset = getDrawOffset();
|
|
@@ -16040,7 +16830,7 @@ var createPianoRoll = (options, handlers) => {
|
|
|
16040
16830
|
const renderX = logicalX - offset.x;
|
|
16041
16831
|
const renderY = logicalY - offset.y;
|
|
16042
16832
|
const w = note.durationSteps * stepWidth;
|
|
16043
|
-
if (
|
|
16833
|
+
if (x2 >= renderX + w - resizeHandleWidth && x2 <= renderX + w && y >= renderY && y <= renderY + keyHeight) {
|
|
16044
16834
|
dragState = {
|
|
16045
16835
|
noteId: note.id,
|
|
16046
16836
|
mode: "resize",
|
|
@@ -16316,6 +17106,166 @@ var isSupported = midiJsonParser.isSupported;
|
|
|
16316
17106
|
var parseArrayBuffer = midiJsonParser.parseArrayBuffer;
|
|
16317
17107
|
URL.revokeObjectURL(url);
|
|
16318
17108
|
|
|
17109
|
+
// src/channel-strip.ts
|
|
17110
|
+
var clamp4 = (v, lo, hi) => Math.max(lo, Math.min(hi, v));
|
|
17111
|
+
var compressionParams = (amount) => {
|
|
17112
|
+
const t = clamp4(amount, 0, 100) / 100;
|
|
17113
|
+
return {
|
|
17114
|
+
threshold: 0 + (-24 - 0) * t,
|
|
17115
|
+
ratio: 1 + (12 - 1) * t,
|
|
17116
|
+
knee: 0 + (6 - 0) * t,
|
|
17117
|
+
attack: 0.02 + (3e-3 - 0.02) * t,
|
|
17118
|
+
release: 0.25 + (0.15 - 0.25) * t
|
|
17119
|
+
};
|
|
17120
|
+
};
|
|
17121
|
+
var createChannelStrip = (ctx, destination, options = {}) => {
|
|
17122
|
+
const input = ctx.createGain();
|
|
17123
|
+
const compressor = ctx.createDynamicsCompressor();
|
|
17124
|
+
const applyCompression = (amount) => {
|
|
17125
|
+
const p = compressionParams(amount);
|
|
17126
|
+
const now = ctx.currentTime;
|
|
17127
|
+
compressor.threshold.setValueAtTime(p.threshold, now);
|
|
17128
|
+
compressor.ratio.setValueAtTime(p.ratio, now);
|
|
17129
|
+
compressor.knee.setValueAtTime(p.knee, now);
|
|
17130
|
+
compressor.attack.setValueAtTime(p.attack, now);
|
|
17131
|
+
compressor.release.setValueAtTime(p.release, now);
|
|
17132
|
+
};
|
|
17133
|
+
applyCompression(options.compression ?? 0);
|
|
17134
|
+
const splitter = ctx.createChannelSplitter(2);
|
|
17135
|
+
const mid = ctx.createGain();
|
|
17136
|
+
mid.gain.value = 0.5;
|
|
17137
|
+
splitter.connect(mid, 0);
|
|
17138
|
+
splitter.connect(mid, 1);
|
|
17139
|
+
const sideSum = ctx.createGain();
|
|
17140
|
+
sideSum.gain.value = 1;
|
|
17141
|
+
const sideL = ctx.createGain();
|
|
17142
|
+
sideL.gain.value = 0.5;
|
|
17143
|
+
const sideR = ctx.createGain();
|
|
17144
|
+
sideR.gain.value = -0.5;
|
|
17145
|
+
splitter.connect(sideL, 0);
|
|
17146
|
+
splitter.connect(sideR, 1);
|
|
17147
|
+
sideL.connect(sideSum);
|
|
17148
|
+
sideR.connect(sideSum);
|
|
17149
|
+
const widthGain = ctx.createGain();
|
|
17150
|
+
sideSum.connect(widthGain);
|
|
17151
|
+
const widthInv = ctx.createGain();
|
|
17152
|
+
widthInv.gain.value = -1;
|
|
17153
|
+
widthGain.connect(widthInv);
|
|
17154
|
+
const outL = ctx.createGain();
|
|
17155
|
+
mid.connect(outL);
|
|
17156
|
+
widthGain.connect(outL);
|
|
17157
|
+
const outR = ctx.createGain();
|
|
17158
|
+
mid.connect(outR);
|
|
17159
|
+
widthInv.connect(outR);
|
|
17160
|
+
const merger = ctx.createChannelMerger(2);
|
|
17161
|
+
outL.connect(merger, 0, 0);
|
|
17162
|
+
outR.connect(merger, 0, 1);
|
|
17163
|
+
const setWidth = (width) => {
|
|
17164
|
+
widthGain.gain.setTargetAtTime(
|
|
17165
|
+
clamp4(width, 0, 200) / 100,
|
|
17166
|
+
ctx.currentTime,
|
|
17167
|
+
0.02
|
|
17168
|
+
);
|
|
17169
|
+
};
|
|
17170
|
+
setWidth(options.width ?? 100);
|
|
17171
|
+
input.connect(compressor);
|
|
17172
|
+
compressor.connect(splitter);
|
|
17173
|
+
merger.connect(destination);
|
|
17174
|
+
return {
|
|
17175
|
+
input,
|
|
17176
|
+
setCompression: applyCompression,
|
|
17177
|
+
setWidth,
|
|
17178
|
+
dispose: () => {
|
|
17179
|
+
input.disconnect();
|
|
17180
|
+
compressor.disconnect();
|
|
17181
|
+
splitter.disconnect();
|
|
17182
|
+
mid.disconnect();
|
|
17183
|
+
sideSum.disconnect();
|
|
17184
|
+
sideL.disconnect();
|
|
17185
|
+
sideR.disconnect();
|
|
17186
|
+
widthGain.disconnect();
|
|
17187
|
+
widthInv.disconnect();
|
|
17188
|
+
outL.disconnect();
|
|
17189
|
+
outR.disconnect();
|
|
17190
|
+
merger.disconnect();
|
|
17191
|
+
}
|
|
17192
|
+
};
|
|
17193
|
+
};
|
|
17194
|
+
|
|
17195
|
+
// src/clip-meter.ts
|
|
17196
|
+
var createClipMeter = (ctx, source, options = {}) => {
|
|
17197
|
+
const threshold = options.threshold ?? 0.98;
|
|
17198
|
+
const holdMs = options.holdMs ?? 800;
|
|
17199
|
+
const analyser = ctx.createAnalyser();
|
|
17200
|
+
analyser.fftSize = 512;
|
|
17201
|
+
source.connect(analyser);
|
|
17202
|
+
const buf = new Float32Array(analyser.fftSize);
|
|
17203
|
+
let clipping = false;
|
|
17204
|
+
let clipUntil = 0;
|
|
17205
|
+
let peakLevel = 0;
|
|
17206
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
17207
|
+
let rafId = null;
|
|
17208
|
+
const tick = () => {
|
|
17209
|
+
analyser.getFloatTimeDomainData(buf);
|
|
17210
|
+
let peak = 0;
|
|
17211
|
+
let clipped = false;
|
|
17212
|
+
for (let i2 = 0; i2 < buf.length; i2++) {
|
|
17213
|
+
const v = Math.abs(buf[i2]);
|
|
17214
|
+
if (v > peak) peak = v;
|
|
17215
|
+
if (v >= threshold) clipped = true;
|
|
17216
|
+
}
|
|
17217
|
+
peakLevel = peak;
|
|
17218
|
+
const now = performance.now();
|
|
17219
|
+
if (clipped) clipUntil = now + holdMs;
|
|
17220
|
+
const nextClipping = now < clipUntil;
|
|
17221
|
+
if (nextClipping !== clipping) {
|
|
17222
|
+
clipping = nextClipping;
|
|
17223
|
+
for (const cb of listeners) cb(clipping);
|
|
17224
|
+
}
|
|
17225
|
+
rafId = requestAnimationFrame(tick);
|
|
17226
|
+
};
|
|
17227
|
+
rafId = requestAnimationFrame(tick);
|
|
17228
|
+
return {
|
|
17229
|
+
onClipChange: (cb) => {
|
|
17230
|
+
listeners.add(cb);
|
|
17231
|
+
return () => listeners.delete(cb);
|
|
17232
|
+
},
|
|
17233
|
+
getPeakLevel: () => peakLevel,
|
|
17234
|
+
reset: () => {
|
|
17235
|
+
clipUntil = 0;
|
|
17236
|
+
if (clipping) {
|
|
17237
|
+
clipping = false;
|
|
17238
|
+
for (const cb of listeners) cb(false);
|
|
17239
|
+
}
|
|
17240
|
+
},
|
|
17241
|
+
dispose: () => {
|
|
17242
|
+
if (rafId !== null) cancelAnimationFrame(rafId);
|
|
17243
|
+
rafId = null;
|
|
17244
|
+
analyser.disconnect();
|
|
17245
|
+
listeners.clear();
|
|
17246
|
+
}
|
|
17247
|
+
};
|
|
17248
|
+
};
|
|
17249
|
+
|
|
17250
|
+
// src/reverb.ts
|
|
17251
|
+
var IMPULSE_DURATION_SEC = 2.2;
|
|
17252
|
+
var IMPULSE_DECAY = 2.5;
|
|
17253
|
+
var createReverbImpulse = (ctx) => {
|
|
17254
|
+
const rate = ctx.sampleRate;
|
|
17255
|
+
const length = Math.max(1, Math.floor(rate * IMPULSE_DURATION_SEC));
|
|
17256
|
+
const impulse = ctx.createBuffer(2, length, rate);
|
|
17257
|
+
for (let ch = 0; ch < impulse.numberOfChannels; ch++) {
|
|
17258
|
+
const data = impulse.getChannelData(ch);
|
|
17259
|
+
for (let i2 = 0; i2 < length; i2++) {
|
|
17260
|
+
const envelope = (1 - i2 / length) ** IMPULSE_DECAY;
|
|
17261
|
+
data[i2] = (Math.random() * 2 - 1) * envelope;
|
|
17262
|
+
}
|
|
17263
|
+
}
|
|
17264
|
+
return impulse;
|
|
17265
|
+
};
|
|
17266
|
+
var REVERB_MAX_WET = 0.6;
|
|
17267
|
+
var reverbAmountToGain = (amount) => Math.max(0, Math.min(100, amount)) / 100 * REVERB_MAX_WET;
|
|
17268
|
+
|
|
16319
17269
|
// src/sf/SoundFont_drum.ts
|
|
16320
17270
|
var touch = (map, key, ctor) => {
|
|
16321
17271
|
if (!map.has(key)) map.set(key, new ctor());
|
|
@@ -16467,10 +17417,44 @@ var createDtmStudio = async (options = {}) => {
|
|
|
16467
17417
|
const audioCtx = options.audioContext ?? new AudioContext({ sampleRate: 44100 });
|
|
16468
17418
|
const masterGain = audioCtx.createGain();
|
|
16469
17419
|
masterGain.gain.value = options.masterVolume ?? 1;
|
|
16470
|
-
masterGain.connect(audioCtx.destination);
|
|
16471
17420
|
const drumGain = audioCtx.createGain();
|
|
16472
17421
|
drumGain.gain.value = options.drumVolume ?? 1;
|
|
16473
17422
|
drumGain.connect(masterGain);
|
|
17423
|
+
const reverbConvolver = audioCtx.createConvolver();
|
|
17424
|
+
reverbConvolver.buffer = createReverbImpulse(audioCtx);
|
|
17425
|
+
reverbConvolver.normalize = true;
|
|
17426
|
+
const reverbWetGain = audioCtx.createGain();
|
|
17427
|
+
reverbWetGain.gain.value = reverbAmountToGain(options.reverbAmount ?? 0);
|
|
17428
|
+
masterGain.connect(reverbConvolver);
|
|
17429
|
+
reverbConvolver.connect(reverbWetGain);
|
|
17430
|
+
const setReverbAmount = (amount) => {
|
|
17431
|
+
reverbWetGain.gain.setTargetAtTime(
|
|
17432
|
+
reverbAmountToGain(amount),
|
|
17433
|
+
audioCtx.currentTime,
|
|
17434
|
+
0.02
|
|
17435
|
+
);
|
|
17436
|
+
};
|
|
17437
|
+
const finalMix = audioCtx.createGain();
|
|
17438
|
+
masterGain.connect(finalMix);
|
|
17439
|
+
reverbWetGain.connect(finalMix);
|
|
17440
|
+
const safetyLimiter = audioCtx.createDynamicsCompressor();
|
|
17441
|
+
safetyLimiter.threshold.value = -1;
|
|
17442
|
+
safetyLimiter.knee.value = 0;
|
|
17443
|
+
safetyLimiter.ratio.value = 20;
|
|
17444
|
+
safetyLimiter.attack.value = 1e-3;
|
|
17445
|
+
safetyLimiter.release.value = 0.1;
|
|
17446
|
+
finalMix.connect(safetyLimiter);
|
|
17447
|
+
safetyLimiter.connect(options.destination ?? audioCtx.destination);
|
|
17448
|
+
const clipMeter = createClipMeter(audioCtx, finalMix);
|
|
17449
|
+
const channelStrips = /* @__PURE__ */ new Map();
|
|
17450
|
+
const getChannelStrip = (trackId) => {
|
|
17451
|
+
let strip = channelStrips.get(trackId);
|
|
17452
|
+
if (!strip) {
|
|
17453
|
+
strip = createChannelStrip(audioCtx, masterGain);
|
|
17454
|
+
channelStrips.set(trackId, strip);
|
|
17455
|
+
}
|
|
17456
|
+
return strip;
|
|
17457
|
+
};
|
|
16474
17458
|
const resumeAudio = () => {
|
|
16475
17459
|
if (audioCtx.state === "closed") return Promise.resolve();
|
|
16476
17460
|
return audioCtx.resume();
|
|
@@ -16501,7 +17485,14 @@ var createDtmStudio = async (options = {}) => {
|
|
|
16501
17485
|
const singingVoices = createSingingVoices(audioCtx, masterGain, {
|
|
16502
17486
|
voiceWorkerUrl,
|
|
16503
17487
|
voicebanks,
|
|
16504
|
-
worldlineScriptUrl: options.worldlineScriptUrl
|
|
17488
|
+
worldlineScriptUrl: options.worldlineScriptUrl,
|
|
17489
|
+
// ボーカルトラック個別のリバーブセンド(`r`トークン)先。マスタリバーブの
|
|
17490
|
+
// Convolver 入力へ直接センドする(masterGain 経由のドライ段は素通り)。
|
|
17491
|
+
reverbBus: reverbConvolver,
|
|
17492
|
+
// トラック単位チャンネルストリップ(コンプレッサー/ステレオワイド)の入口。
|
|
17493
|
+
// 楽器と同じ getChannelStrip キャッシュを共有するので、演奏トラックと歌詞トラックが
|
|
17494
|
+
// 同じ trackId を指していれば同じ処理が掛かる。
|
|
17495
|
+
getTrackDestination: (trackId) => getChannelStrip(trackId).input
|
|
16505
17496
|
});
|
|
16506
17497
|
const listReady = new Promise((resolve) => {
|
|
16507
17498
|
sfList.init();
|
|
@@ -16731,7 +17722,7 @@ var createDtmStudio = async (options = {}) => {
|
|
|
16731
17722
|
if (!sfInst) return;
|
|
16732
17723
|
sfInst.play({
|
|
16733
17724
|
ctx: audioCtx,
|
|
16734
|
-
destination:
|
|
17725
|
+
destination: getChannelStrip(e.trackId).input,
|
|
16735
17726
|
pitch: e.pitch,
|
|
16736
17727
|
volume: e.volume,
|
|
16737
17728
|
when: e.when,
|
|
@@ -16776,6 +17767,11 @@ var createDtmStudio = async (options = {}) => {
|
|
|
16776
17767
|
void handleTrackInstrumentChange(idx, name);
|
|
16777
17768
|
externalOnTrackInstrumentChange?.(idx, name);
|
|
16778
17769
|
},
|
|
17770
|
+
reverbAmount: options.reverbAmount,
|
|
17771
|
+
onReverbChange: setReverbAmount,
|
|
17772
|
+
onTrackCompressionChange: (trackId, amount) => getChannelStrip(trackId).setCompression(amount),
|
|
17773
|
+
onTrackWidthChange: (trackId, width) => getChannelStrip(trackId).setWidth(width),
|
|
17774
|
+
clipMeter,
|
|
16779
17775
|
...dawOverrides,
|
|
16780
17776
|
// dawOverrides で上書きされないよう、スプレッドの後に配置して合成する
|
|
16781
17777
|
onDrumChange: (name) => {
|
|
@@ -16802,17 +17798,22 @@ var createDtmStudio = async (options = {}) => {
|
|
|
16802
17798
|
mountedEditors.push(daw);
|
|
16803
17799
|
const wantPresetUI = presetUI ?? features.presetUI;
|
|
16804
17800
|
const rollEl = target.querySelector('[data-dtm="roll"]');
|
|
17801
|
+
const presetSlot = target.querySelector(
|
|
17802
|
+
'[data-dtm="preset-select-slot"]'
|
|
17803
|
+
);
|
|
16805
17804
|
if (wantPresetUI) {
|
|
16806
17805
|
editorPresetSelects.get(target)?.destroy();
|
|
16807
|
-
presetSelect = mountPresetSelect(target, {
|
|
17806
|
+
presetSelect = mountPresetSelect(presetSlot ?? target, {
|
|
16808
17807
|
getDaw: () => daw,
|
|
16809
17808
|
getTrackIds: () => trackIds,
|
|
16810
17809
|
value: initialPreset,
|
|
16811
17810
|
loadingTarget: rollEl ?? target,
|
|
16812
|
-
position: "prepend",
|
|
16813
|
-
//
|
|
17811
|
+
position: presetSlot ? "append" : "prepend",
|
|
17812
|
+
// 楽器変更時、このエディタの発音解決が使うプリセットも追従させ、
|
|
17813
|
+
// 外部の onInstrumentChange(呼び出し側の永続化フック等)へも通知する。
|
|
17814
|
+
// #inst= 付きMML読込時の通知経路(handleInstrumentChange)と揃える。
|
|
16814
17815
|
onChange: (key) => {
|
|
16815
|
-
|
|
17816
|
+
handleInstrumentChange(key);
|
|
16816
17817
|
}
|
|
16817
17818
|
});
|
|
16818
17819
|
editorPresetSelects.set(target, presetSelect);
|
|
@@ -16833,8 +17834,8 @@ var createDtmStudio = async (options = {}) => {
|
|
|
16833
17834
|
presetSelect?.destroy();
|
|
16834
17835
|
if (editorPresetSelects.get(target) === presetSelect)
|
|
16835
17836
|
editorPresetSelects.delete(target);
|
|
16836
|
-
const
|
|
16837
|
-
if (
|
|
17837
|
+
const i2 = mountedEditors.indexOf(daw);
|
|
17838
|
+
if (i2 >= 0) mountedEditors.splice(i2, 1);
|
|
16838
17839
|
};
|
|
16839
17840
|
return {
|
|
16840
17841
|
...daw,
|
|
@@ -16937,8 +17938,8 @@ var createDtmStudio = async (options = {}) => {
|
|
|
16937
17938
|
destroy: () => {
|
|
16938
17939
|
doUnmount();
|
|
16939
17940
|
wrapper.remove();
|
|
16940
|
-
const
|
|
16941
|
-
if (
|
|
17941
|
+
const i2 = mountedModeSwitches.indexOf(instance);
|
|
17942
|
+
if (i2 >= 0) mountedModeSwitches.splice(i2, 1);
|
|
16942
17943
|
}
|
|
16943
17944
|
};
|
|
16944
17945
|
mountedModeSwitches.push(instance);
|
|
@@ -16995,7 +17996,7 @@ var createDtmStudio = async (options = {}) => {
|
|
|
16995
17996
|
if (!sfInst) return;
|
|
16996
17997
|
sfInst.play({
|
|
16997
17998
|
ctx: audioCtx,
|
|
16998
|
-
destination:
|
|
17999
|
+
destination: getChannelStrip(e.trackId).input,
|
|
16999
18000
|
pitch: e.pitch,
|
|
17000
18001
|
volume: e.volume,
|
|
17001
18002
|
when: e.when,
|
|
@@ -17025,8 +18026,8 @@ var createDtmStudio = async (options = {}) => {
|
|
|
17025
18026
|
mountedPlayers.push(player);
|
|
17026
18027
|
const destroy = () => {
|
|
17027
18028
|
player.destroy();
|
|
17028
|
-
const
|
|
17029
|
-
if (
|
|
18029
|
+
const i2 = mountedPlayers.indexOf(player);
|
|
18030
|
+
if (i2 >= 0) mountedPlayers.splice(i2, 1);
|
|
17030
18031
|
};
|
|
17031
18032
|
return { ...player, destroy };
|
|
17032
18033
|
};
|
|
@@ -17081,7 +18082,7 @@ var createDtmStudio = async (options = {}) => {
|
|
|
17081
18082
|
if (!sfInst) return;
|
|
17082
18083
|
sfInst.play({
|
|
17083
18084
|
ctx: audioCtx,
|
|
17084
|
-
destination:
|
|
18085
|
+
destination: getChannelStrip(e.trackId).input,
|
|
17085
18086
|
pitch: e.pitch,
|
|
17086
18087
|
volume: e.volume,
|
|
17087
18088
|
when: e.when,
|
|
@@ -17160,7 +18161,7 @@ var createDtmStudio = async (options = {}) => {
|
|
|
17160
18161
|
if (!sfInst) return;
|
|
17161
18162
|
sfInst.play({
|
|
17162
18163
|
ctx: audioCtx,
|
|
17163
|
-
destination:
|
|
18164
|
+
destination: getChannelStrip(e.trackId).input,
|
|
17164
18165
|
pitch: e.pitch,
|
|
17165
18166
|
volume: e.volume,
|
|
17166
18167
|
when: e.when,
|
|
@@ -17199,7 +18200,7 @@ var createDtmStudio = async (options = {}) => {
|
|
|
17199
18200
|
if (!sfInst) return;
|
|
17200
18201
|
sfInst.play({
|
|
17201
18202
|
ctx: audioCtx,
|
|
17202
|
-
destination:
|
|
18203
|
+
destination: getChannelStrip(e.trackId).input,
|
|
17203
18204
|
pitch: e.pitch,
|
|
17204
18205
|
volume: e.volume,
|
|
17205
18206
|
when: e.when,
|
|
@@ -17255,7 +18256,7 @@ var createDtmStudio = async (options = {}) => {
|
|
|
17255
18256
|
if (!sfInst) return;
|
|
17256
18257
|
sfInst.play({
|
|
17257
18258
|
ctx: audioCtx,
|
|
17258
|
-
destination:
|
|
18259
|
+
destination: getChannelStrip("chord").input,
|
|
17259
18260
|
pitch: e.pitch,
|
|
17260
18261
|
volume: e.volume,
|
|
17261
18262
|
when: e.when,
|
|
@@ -17287,8 +18288,8 @@ var createDtmStudio = async (options = {}) => {
|
|
|
17287
18288
|
mountedChordPlayers.push(player);
|
|
17288
18289
|
const destroy = () => {
|
|
17289
18290
|
player.destroy();
|
|
17290
|
-
const
|
|
17291
|
-
if (
|
|
18291
|
+
const i2 = mountedChordPlayers.indexOf(player);
|
|
18292
|
+
if (i2 >= 0) mountedChordPlayers.splice(i2, 1);
|
|
17292
18293
|
};
|
|
17293
18294
|
return {
|
|
17294
18295
|
...player,
|
|
@@ -17305,6 +18306,9 @@ var createDtmStudio = async (options = {}) => {
|
|
|
17305
18306
|
mountedPlayers.length = 0;
|
|
17306
18307
|
mountedChordPlayers.length = 0;
|
|
17307
18308
|
mountedEditors.length = 0;
|
|
18309
|
+
clipMeter.dispose();
|
|
18310
|
+
for (const strip of channelStrips.values()) strip.dispose();
|
|
18311
|
+
channelStrips.clear();
|
|
17308
18312
|
void audioCtx.close();
|
|
17309
18313
|
};
|
|
17310
18314
|
const setMasterVolume = (volume) => {
|
|
@@ -17343,6 +18347,7 @@ var createDtmStudio = async (options = {}) => {
|
|
|
17343
18347
|
mountModeSwitch,
|
|
17344
18348
|
setMasterVolume,
|
|
17345
18349
|
setVolume: setMasterVolume,
|
|
18350
|
+
setReverbAmount,
|
|
17346
18351
|
dispose
|
|
17347
18352
|
};
|
|
17348
18353
|
};
|
|
@@ -17373,6 +18378,7 @@ export {
|
|
|
17373
18378
|
PREWARM_NOTES,
|
|
17374
18379
|
TRACKS_ADVANCED,
|
|
17375
18380
|
TRACKS_SIMPLE,
|
|
18381
|
+
VIBRATO_MIN_SEC,
|
|
17376
18382
|
VOICE_IMAGES,
|
|
17377
18383
|
VOICE_IMAGE_KEY,
|
|
17378
18384
|
analyzeMidiTracks,
|