@onjmin/dtm 0.1.85 → 0.1.86
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +110 -2
- package/dist/index.d.ts +110 -2
- package/dist/index.js +678 -89
- package/dist/index.mjs +678 -89
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2316,10 +2316,11 @@ var parseLyrics = (mml) => {
|
|
|
2316
2316
|
let octave = 0;
|
|
2317
2317
|
let vibrato = false;
|
|
2318
2318
|
let reverb = 0;
|
|
2319
|
+
let delay = 0;
|
|
2319
2320
|
let gender = 50;
|
|
2320
2321
|
let breathiness = 50;
|
|
2321
2322
|
const modelMatch = rest.match(
|
|
2322
|
-
/^([a-z_][a-z0-9_]*?)(?=(?:[
|
|
2323
|
+
/^([a-z_][a-z0-9_]*?)(?=(?:[vqpobrghe]-?\d)|[^a-z0-9_]|$)(?::(\d+))?/i
|
|
2323
2324
|
);
|
|
2324
2325
|
let model = "";
|
|
2325
2326
|
const metaTokens = [];
|
|
@@ -2388,6 +2389,13 @@ var parseLyrics = (mml) => {
|
|
|
2388
2389
|
rest = rest.substring(hMatch[0].length).trim();
|
|
2389
2390
|
continue;
|
|
2390
2391
|
}
|
|
2392
|
+
const eMatch = rest.match(/^e(\d+)/i);
|
|
2393
|
+
if (eMatch) {
|
|
2394
|
+
delay = clamp(Number.parseInt(eMatch[1], 10), 0, 100);
|
|
2395
|
+
metaTokens.push(eMatch[0]);
|
|
2396
|
+
rest = rest.substring(eMatch[0].length).trim();
|
|
2397
|
+
continue;
|
|
2398
|
+
}
|
|
2391
2399
|
break;
|
|
2392
2400
|
}
|
|
2393
2401
|
const lyricLines = [rest];
|
|
@@ -2404,6 +2412,7 @@ var parseLyrics = (mml) => {
|
|
|
2404
2412
|
octave,
|
|
2405
2413
|
vibrato,
|
|
2406
2414
|
reverb,
|
|
2415
|
+
delay,
|
|
2407
2416
|
gender,
|
|
2408
2417
|
breathiness,
|
|
2409
2418
|
syllables,
|
|
@@ -2491,7 +2500,7 @@ var FORMANTS = {
|
|
|
2491
2500
|
N: [250, 1e3]
|
|
2492
2501
|
};
|
|
2493
2502
|
var midiToFreq = (m) => 440 * 2 ** ((m - 69) / 12);
|
|
2494
|
-
var createKlattVoice = (ctx, destination, reverbBus) => {
|
|
2503
|
+
var createKlattVoice = (ctx, destination, reverbBus, delayBus) => {
|
|
2495
2504
|
const active = /* @__PURE__ */ new Set();
|
|
2496
2505
|
const voice = (syllable, e) => {
|
|
2497
2506
|
const t0 = ctx.currentTime + e.when;
|
|
@@ -2510,11 +2519,17 @@ var createKlattVoice = (ctx, destination, reverbBus) => {
|
|
|
2510
2519
|
panner.connect(dest);
|
|
2511
2520
|
out = panner;
|
|
2512
2521
|
}
|
|
2513
|
-
let
|
|
2522
|
+
let reverbSendGain = null;
|
|
2514
2523
|
if (reverbBus && e.reverbSend && e.reverbSend > 0 && panner) {
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
panner.connect(
|
|
2524
|
+
reverbSendGain = ctx.createGain();
|
|
2525
|
+
reverbSendGain.gain.value = Math.max(0, Math.min(1, e.reverbSend));
|
|
2526
|
+
panner.connect(reverbSendGain).connect(reverbBus);
|
|
2527
|
+
}
|
|
2528
|
+
let delaySendGain = null;
|
|
2529
|
+
if (delayBus && e.delaySend && e.delaySend > 0 && panner) {
|
|
2530
|
+
delaySendGain = ctx.createGain();
|
|
2531
|
+
delaySendGain.gain.value = Math.max(0, Math.min(1, e.delaySend));
|
|
2532
|
+
panner.connect(delaySendGain).connect(delayBus);
|
|
2518
2533
|
}
|
|
2519
2534
|
const osc = ctx.createOscillator();
|
|
2520
2535
|
osc.type = "sawtooth";
|
|
@@ -2571,7 +2586,8 @@ var createKlattVoice = (ctx, destination, reverbBus) => {
|
|
|
2571
2586
|
active.delete(osc);
|
|
2572
2587
|
osc.disconnect();
|
|
2573
2588
|
panner?.disconnect();
|
|
2574
|
-
|
|
2589
|
+
reverbSendGain?.disconnect();
|
|
2590
|
+
delaySendGain?.disconnect();
|
|
2575
2591
|
};
|
|
2576
2592
|
};
|
|
2577
2593
|
voice.stopAll = () => {
|
|
@@ -2887,7 +2903,7 @@ var createKoeVoice = async (ctx, destination, options) => {
|
|
|
2887
2903
|
return p;
|
|
2888
2904
|
};
|
|
2889
2905
|
const LEADCAP_S = 0.09;
|
|
2890
|
-
const schedule = (r, t0, peak, pan, reverbSend = 0, destOverride) => {
|
|
2906
|
+
const schedule = (r, t0, peak, pan, reverbSend = 0, delaySend = 0, destOverride) => {
|
|
2891
2907
|
const dest = destOverride ?? destination;
|
|
2892
2908
|
let out = dest;
|
|
2893
2909
|
let panner = null;
|
|
@@ -2897,11 +2913,17 @@ var createKoeVoice = async (ctx, destination, options) => {
|
|
|
2897
2913
|
panner.connect(dest);
|
|
2898
2914
|
out = panner;
|
|
2899
2915
|
}
|
|
2900
|
-
let
|
|
2916
|
+
let reverbSendGain = null;
|
|
2901
2917
|
if (options.reverbBus && reverbSend > 0 && panner) {
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
panner.connect(
|
|
2918
|
+
reverbSendGain = ctx.createGain();
|
|
2919
|
+
reverbSendGain.gain.value = Math.max(0, Math.min(1, reverbSend));
|
|
2920
|
+
panner.connect(reverbSendGain).connect(options.reverbBus);
|
|
2921
|
+
}
|
|
2922
|
+
let delaySendGain = null;
|
|
2923
|
+
if (options.delayBus && delaySend > 0 && panner) {
|
|
2924
|
+
delaySendGain = ctx.createGain();
|
|
2925
|
+
delaySendGain.gain.value = Math.max(0, Math.min(1, delaySend));
|
|
2926
|
+
panner.connect(delaySendGain).connect(options.delayBus);
|
|
2905
2927
|
}
|
|
2906
2928
|
const src = ctx.createBufferSource();
|
|
2907
2929
|
src.buffer = r.audio;
|
|
@@ -2928,7 +2950,8 @@ var createKoeVoice = async (ctx, destination, options) => {
|
|
|
2928
2950
|
src.disconnect();
|
|
2929
2951
|
env.disconnect();
|
|
2930
2952
|
panner?.disconnect();
|
|
2931
|
-
|
|
2953
|
+
reverbSendGain?.disconnect();
|
|
2954
|
+
delaySendGain?.disconnect();
|
|
2932
2955
|
};
|
|
2933
2956
|
};
|
|
2934
2957
|
const model = (syllable, e) => {
|
|
@@ -2947,7 +2970,8 @@ var createKoeVoice = async (ctx, destination, options) => {
|
|
|
2947
2970
|
const pan = e.pan ?? 0;
|
|
2948
2971
|
const durationMs = Math.max(60, e.duration * 1e3);
|
|
2949
2972
|
void renderInto(alias, e.pitch, durationMs).then((r) => {
|
|
2950
|
-
if (r)
|
|
2973
|
+
if (r)
|
|
2974
|
+
schedule(r, t0, peak, pan, e.reverbSend, e.delaySend, e.destination);
|
|
2951
2975
|
});
|
|
2952
2976
|
};
|
|
2953
2977
|
model.renderToCache = async (syllable, prevVowelArg, pitch, durationMs, vibrato, expr) => {
|
|
@@ -2965,9 +2989,9 @@ var createKoeVoice = async (ctx, destination, options) => {
|
|
|
2965
2989
|
const r = await renderInto(alias, pitch, dMs, vib, expr);
|
|
2966
2990
|
return r ? keyOf(alias, pitch, dMs, vib, expr) : null;
|
|
2967
2991
|
};
|
|
2968
|
-
model.scheduleCached = (key, t0, peak, pan, reverbSend, dest) => {
|
|
2992
|
+
model.scheduleCached = (key, t0, peak, pan, reverbSend, delaySend, dest) => {
|
|
2969
2993
|
const r = renderCache.get(key);
|
|
2970
|
-
if (r) schedule(r, t0, peak, pan, reverbSend, dest);
|
|
2994
|
+
if (r) schedule(r, t0, peak, pan, reverbSend, delaySend, dest);
|
|
2971
2995
|
};
|
|
2972
2996
|
model.stopAll = () => {
|
|
2973
2997
|
for (const src of active) {
|
|
@@ -2997,8 +3021,12 @@ var createSingingVoices = (ctx, destination, options = {}) => {
|
|
|
2997
3021
|
let streamSession = 0;
|
|
2998
3022
|
const masterGain = ctx.createGain();
|
|
2999
3023
|
masterGain.connect(destination);
|
|
3024
|
+
let masterVolumeScalar = 1;
|
|
3000
3025
|
const loaded = /* @__PURE__ */ new Map([
|
|
3001
|
-
[
|
|
3026
|
+
[
|
|
3027
|
+
FALLBACK_MODEL,
|
|
3028
|
+
createKlattVoice(ctx, masterGain, options.reverbBus, options.delayBus)
|
|
3029
|
+
]
|
|
3002
3030
|
]);
|
|
3003
3031
|
const loading = /* @__PURE__ */ new Map();
|
|
3004
3032
|
const load2 = (model) => {
|
|
@@ -3019,7 +3047,8 @@ var createSingingVoices = (ctx, destination, options = {}) => {
|
|
|
3019
3047
|
worldlineScriptUrl: options.worldlineScriptUrl,
|
|
3020
3048
|
lightweight: options.lightweight,
|
|
3021
3049
|
voiceWorkerUrl: options.voiceWorkerUrl,
|
|
3022
|
-
reverbBus: options.reverbBus
|
|
3050
|
+
reverbBus: options.reverbBus,
|
|
3051
|
+
delayBus: options.delayBus
|
|
3023
3052
|
})
|
|
3024
3053
|
))().then((v) => {
|
|
3025
3054
|
loaded.set(m, v);
|
|
@@ -3138,13 +3167,16 @@ var createSingingVoices = (ctx, destination, options = {}) => {
|
|
|
3138
3167
|
if (key) {
|
|
3139
3168
|
const delay = ctx.currentTime - t0;
|
|
3140
3169
|
if (delay < 0.05) {
|
|
3170
|
+
const dest = options.getTrackDestination?.(track.id ?? "");
|
|
3171
|
+
const effPeak = dest ? peak * masterVolumeScalar : peak;
|
|
3141
3172
|
scheduleCached(
|
|
3142
3173
|
key,
|
|
3143
3174
|
t0,
|
|
3144
|
-
|
|
3175
|
+
effPeak,
|
|
3145
3176
|
track.pan,
|
|
3146
3177
|
track.reverbSend,
|
|
3147
|
-
|
|
3178
|
+
track.delaySend,
|
|
3179
|
+
dest
|
|
3148
3180
|
);
|
|
3149
3181
|
opts?.onScheduled?.(track, note, t0);
|
|
3150
3182
|
} else {
|
|
@@ -3157,16 +3189,19 @@ var createSingingVoices = (ctx, destination, options = {}) => {
|
|
|
3157
3189
|
})();
|
|
3158
3190
|
} else {
|
|
3159
3191
|
const when = t0 - ctx.currentTime;
|
|
3192
|
+
const dest = options.getTrackDestination?.(track.id ?? "");
|
|
3193
|
+
const effPeak = dest ? peak * masterVolumeScalar : peak;
|
|
3160
3194
|
model(note.syllable, {
|
|
3161
3195
|
trackId: track.id ?? "",
|
|
3162
3196
|
pitch: note.pitch,
|
|
3163
3197
|
velocity: 100,
|
|
3164
|
-
volume:
|
|
3198
|
+
volume: effPeak,
|
|
3165
3199
|
when,
|
|
3166
3200
|
duration: note.durationSec,
|
|
3167
3201
|
pan: track.pan,
|
|
3168
3202
|
reverbSend: track.reverbSend,
|
|
3169
|
-
|
|
3203
|
+
delaySend: track.delaySend,
|
|
3204
|
+
destination: dest
|
|
3170
3205
|
});
|
|
3171
3206
|
opts?.onScheduled?.(track, note, t0);
|
|
3172
3207
|
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
@@ -3191,7 +3226,9 @@ var createSingingVoices = (ctx, destination, options = {}) => {
|
|
|
3191
3226
|
for (const v of loaded.values()) v.reset?.();
|
|
3192
3227
|
};
|
|
3193
3228
|
const setVolume = (gain) => {
|
|
3194
|
-
|
|
3229
|
+
const g = Math.max(0, gain);
|
|
3230
|
+
masterGain.gain.value = g;
|
|
3231
|
+
masterVolumeScalar = g;
|
|
3195
3232
|
};
|
|
3196
3233
|
return {
|
|
3197
3234
|
loadModels,
|
|
@@ -3225,10 +3262,13 @@ var PITCH_MAP = {
|
|
|
3225
3262
|
b: 11
|
|
3226
3263
|
};
|
|
3227
3264
|
var clamp2 = (value, lo, hi) => Math.min(hi, Math.max(lo, value));
|
|
3228
|
-
var META_DIRECTIVE = /#(inst|drum|drumfont|volume|drumvolume|reverb|mode)=([\w-]+)/gi;
|
|
3265
|
+
var META_DIRECTIVE = /#(inst|drum|drumfont|volume|drumvolume|reverb|reverbdecay|reverbpredelay|delay|delaydiv|mode)=([\w-]+)/gi;
|
|
3229
3266
|
var TRACK_INST_DIRECTIVE = /#t(\d+)inst=([^#;\r\n]+)/gi;
|
|
3230
3267
|
var TRACK_COMP_DIRECTIVE = /#t(\d+)comp=(\d+)/gi;
|
|
3231
3268
|
var TRACK_WIDTH_DIRECTIVE = /#t(\d+)width=(\d+)/gi;
|
|
3269
|
+
var TRACK_EQLOW_DIRECTIVE = /#t(\d+)eqlo=(-?\d+)/gi;
|
|
3270
|
+
var TRACK_EQMID_DIRECTIVE = /#t(\d+)eqmid=(-?\d+)/gi;
|
|
3271
|
+
var TRACK_EQHIGH_DIRECTIVE = /#t(\d+)eqhi=(-?\d+)/gi;
|
|
3232
3272
|
var parseMmlMeta = (mml) => {
|
|
3233
3273
|
const meta = {};
|
|
3234
3274
|
for (const m of mml.matchAll(META_DIRECTIVE)) {
|
|
@@ -3245,6 +3285,17 @@ var parseMmlMeta = (mml) => {
|
|
|
3245
3285
|
} else if (key === "reverb") {
|
|
3246
3286
|
const rv = Number.parseInt(m[2], 10);
|
|
3247
3287
|
if (!Number.isNaN(rv)) meta.reverb = clamp2(rv, 0, 100);
|
|
3288
|
+
} else if (key === "reverbdecay") {
|
|
3289
|
+
const rd = Number.parseInt(m[2], 10);
|
|
3290
|
+
if (!Number.isNaN(rd)) meta.reverbDecay = clamp2(rd, 3, 40);
|
|
3291
|
+
} else if (key === "reverbpredelay") {
|
|
3292
|
+
const rp = Number.parseInt(m[2], 10);
|
|
3293
|
+
if (!Number.isNaN(rp)) meta.reverbPreDelay = clamp2(rp, 0, 150);
|
|
3294
|
+
} else if (key === "delay") {
|
|
3295
|
+
const dv = Number.parseInt(m[2], 10);
|
|
3296
|
+
if (!Number.isNaN(dv)) meta.delay = clamp2(dv, 0, 100);
|
|
3297
|
+
} else if (key === "delaydiv") {
|
|
3298
|
+
if (["4", "8", "8d", "16"].includes(m[2])) meta.delayDivision = m[2];
|
|
3248
3299
|
} else if (key === "mode") {
|
|
3249
3300
|
if (m[2] === "simple" || m[2] === "advanced") {
|
|
3250
3301
|
meta.mode = m[2];
|
|
@@ -3275,9 +3326,33 @@ var parseMmlMeta = (mml) => {
|
|
|
3275
3326
|
meta.trackWidth[idx] = val;
|
|
3276
3327
|
}
|
|
3277
3328
|
}
|
|
3329
|
+
for (const m of mml.matchAll(TRACK_EQLOW_DIRECTIVE)) {
|
|
3330
|
+
const idx = Number.parseInt(m[1], 10);
|
|
3331
|
+
const val = clamp2(Number.parseInt(m[2], 10), -12, 12);
|
|
3332
|
+
if (!Number.isNaN(idx) && !Number.isNaN(val)) {
|
|
3333
|
+
meta.trackEqLow ??= {};
|
|
3334
|
+
meta.trackEqLow[idx] = val;
|
|
3335
|
+
}
|
|
3336
|
+
}
|
|
3337
|
+
for (const m of mml.matchAll(TRACK_EQMID_DIRECTIVE)) {
|
|
3338
|
+
const idx = Number.parseInt(m[1], 10);
|
|
3339
|
+
const val = clamp2(Number.parseInt(m[2], 10), -12, 12);
|
|
3340
|
+
if (!Number.isNaN(idx) && !Number.isNaN(val)) {
|
|
3341
|
+
meta.trackEqMid ??= {};
|
|
3342
|
+
meta.trackEqMid[idx] = val;
|
|
3343
|
+
}
|
|
3344
|
+
}
|
|
3345
|
+
for (const m of mml.matchAll(TRACK_EQHIGH_DIRECTIVE)) {
|
|
3346
|
+
const idx = Number.parseInt(m[1], 10);
|
|
3347
|
+
const val = clamp2(Number.parseInt(m[2], 10), -12, 12);
|
|
3348
|
+
if (!Number.isNaN(idx) && !Number.isNaN(val)) {
|
|
3349
|
+
meta.trackEqHigh ??= {};
|
|
3350
|
+
meta.trackEqHigh[idx] = val;
|
|
3351
|
+
}
|
|
3352
|
+
}
|
|
3278
3353
|
return meta;
|
|
3279
3354
|
};
|
|
3280
|
-
var stripMmlMeta = (mml) => mml.replace(META_DIRECTIVE, "").replace(TRACK_INST_DIRECTIVE, "").replace(TRACK_COMP_DIRECTIVE, "").replace(TRACK_WIDTH_DIRECTIVE, "");
|
|
3355
|
+
var stripMmlMeta = (mml) => mml.replace(META_DIRECTIVE, "").replace(TRACK_INST_DIRECTIVE, "").replace(TRACK_COMP_DIRECTIVE, "").replace(TRACK_WIDTH_DIRECTIVE, "").replace(TRACK_EQLOW_DIRECTIVE, "").replace(TRACK_EQMID_DIRECTIVE, "").replace(TRACK_EQHIGH_DIRECTIVE, "");
|
|
3281
3356
|
var formatMmlMeta = (meta, space = "") => {
|
|
3282
3357
|
const parts = [];
|
|
3283
3358
|
if (meta.instrument) parts.push(`#inst=${meta.instrument}`);
|
|
@@ -3288,6 +3363,14 @@ var formatMmlMeta = (meta, space = "") => {
|
|
|
3288
3363
|
parts.push(`#drumvolume=${meta.drumVolume}`);
|
|
3289
3364
|
if (meta.reverb !== void 0 && meta.reverb !== 0)
|
|
3290
3365
|
parts.push(`#reverb=${meta.reverb}`);
|
|
3366
|
+
if (meta.reverbDecay !== void 0 && meta.reverbDecay !== 22)
|
|
3367
|
+
parts.push(`#reverbdecay=${meta.reverbDecay}`);
|
|
3368
|
+
if (meta.reverbPreDelay !== void 0 && meta.reverbPreDelay !== 0)
|
|
3369
|
+
parts.push(`#reverbpredelay=${meta.reverbPreDelay}`);
|
|
3370
|
+
if (meta.delay !== void 0 && meta.delay !== 0)
|
|
3371
|
+
parts.push(`#delay=${meta.delay}`);
|
|
3372
|
+
if (meta.delayDivision && meta.delayDivision !== "8")
|
|
3373
|
+
parts.push(`#delaydiv=${meta.delayDivision}`);
|
|
3291
3374
|
if (meta.mode) parts.push(`#mode=${meta.mode}`);
|
|
3292
3375
|
if (meta.trackInstruments) {
|
|
3293
3376
|
for (const [idx, name] of Object.entries(meta.trackInstruments)) {
|
|
@@ -3304,6 +3387,21 @@ var formatMmlMeta = (meta, space = "") => {
|
|
|
3304
3387
|
if (val !== 100) parts.push(`#t${idx}width=${val}`);
|
|
3305
3388
|
}
|
|
3306
3389
|
}
|
|
3390
|
+
if (meta.trackEqLow) {
|
|
3391
|
+
for (const [idx, val] of Object.entries(meta.trackEqLow)) {
|
|
3392
|
+
if (val !== 0) parts.push(`#t${idx}eqlo=${val}`);
|
|
3393
|
+
}
|
|
3394
|
+
}
|
|
3395
|
+
if (meta.trackEqMid) {
|
|
3396
|
+
for (const [idx, val] of Object.entries(meta.trackEqMid)) {
|
|
3397
|
+
if (val !== 0) parts.push(`#t${idx}eqmid=${val}`);
|
|
3398
|
+
}
|
|
3399
|
+
}
|
|
3400
|
+
if (meta.trackEqHigh) {
|
|
3401
|
+
for (const [idx, val] of Object.entries(meta.trackEqHigh)) {
|
|
3402
|
+
if (val !== 0) parts.push(`#t${idx}eqhi=${val}`);
|
|
3403
|
+
}
|
|
3404
|
+
}
|
|
3307
3405
|
return parts.join(space);
|
|
3308
3406
|
};
|
|
3309
3407
|
var parseMML = (mml, options = {}) => {
|
|
@@ -9139,6 +9237,7 @@ var mountMmlPlayer = (target, mml, options = {}) => {
|
|
|
9139
9237
|
pan: panToStereo(lt.pan ?? DEFAULT_PAN),
|
|
9140
9238
|
vibrato: lt.vibrato,
|
|
9141
9239
|
reverbSend: (lt.reverb ?? 0) / 100,
|
|
9240
|
+
delaySend: (lt.delay ?? 0) / 100,
|
|
9142
9241
|
gender: (lt.gender ?? 50) / 100,
|
|
9143
9242
|
breathiness: (lt.breathiness ?? 50) / 100,
|
|
9144
9243
|
notes
|
|
@@ -10818,6 +10917,71 @@ var mountChordPlayer = (target, chords, options = {}) => {
|
|
|
10818
10917
|
};
|
|
10819
10918
|
};
|
|
10820
10919
|
|
|
10920
|
+
// src/delay.ts
|
|
10921
|
+
var DELAY_DIVISIONS = [
|
|
10922
|
+
{ value: "4", label: "4\u5206", beats: 1 },
|
|
10923
|
+
{ value: "8", label: "8\u5206", beats: 0.5 },
|
|
10924
|
+
{ value: "8d", label: "\u4ED8\u70B98\u5206", beats: 0.75 },
|
|
10925
|
+
{ value: "16", label: "16\u5206", beats: 0.25 }
|
|
10926
|
+
];
|
|
10927
|
+
var clamp3 = (v, lo, hi) => Math.max(lo, Math.min(hi, v));
|
|
10928
|
+
var divisionToSeconds = (division, bpm) => {
|
|
10929
|
+
const beats = DELAY_DIVISIONS.find((d) => d.value === division)?.beats ?? 0.5;
|
|
10930
|
+
const safeBpm = bpm > 0 ? bpm : 120;
|
|
10931
|
+
return 60 / safeBpm * beats;
|
|
10932
|
+
};
|
|
10933
|
+
var DELAY_MAX_WET = 0.45;
|
|
10934
|
+
var delayAmountToGain = (amount) => clamp3(amount, 0, 100) / 100 * DELAY_MAX_WET;
|
|
10935
|
+
var FEEDBACK_GAIN = 0.3;
|
|
10936
|
+
var MAX_DELAY_SEC = 2;
|
|
10937
|
+
var createDelayBus = (ctx, destination, options = {}) => {
|
|
10938
|
+
const input = ctx.createGain();
|
|
10939
|
+
const delayNode = ctx.createDelay(MAX_DELAY_SEC);
|
|
10940
|
+
const feedback = ctx.createGain();
|
|
10941
|
+
feedback.gain.value = FEEDBACK_GAIN;
|
|
10942
|
+
const wetGain = ctx.createGain();
|
|
10943
|
+
wetGain.gain.value = delayAmountToGain(options.amount ?? 0);
|
|
10944
|
+
input.connect(delayNode);
|
|
10945
|
+
delayNode.connect(feedback);
|
|
10946
|
+
feedback.connect(delayNode);
|
|
10947
|
+
delayNode.connect(wetGain);
|
|
10948
|
+
wetGain.connect(destination);
|
|
10949
|
+
let bpm = options.bpm ?? 120;
|
|
10950
|
+
let division = options.division ?? "8";
|
|
10951
|
+
const applyTime = () => {
|
|
10952
|
+
delayNode.delayTime.setTargetAtTime(
|
|
10953
|
+
divisionToSeconds(division, bpm),
|
|
10954
|
+
ctx.currentTime,
|
|
10955
|
+
0.05
|
|
10956
|
+
);
|
|
10957
|
+
};
|
|
10958
|
+
applyTime();
|
|
10959
|
+
return {
|
|
10960
|
+
input,
|
|
10961
|
+
setAmount: (amount) => {
|
|
10962
|
+
wetGain.gain.setTargetAtTime(
|
|
10963
|
+
delayAmountToGain(amount),
|
|
10964
|
+
ctx.currentTime,
|
|
10965
|
+
0.02
|
|
10966
|
+
);
|
|
10967
|
+
},
|
|
10968
|
+
setDivision: (d) => {
|
|
10969
|
+
division = d;
|
|
10970
|
+
applyTime();
|
|
10971
|
+
},
|
|
10972
|
+
setBpm: (b) => {
|
|
10973
|
+
bpm = b;
|
|
10974
|
+
applyTime();
|
|
10975
|
+
},
|
|
10976
|
+
dispose: () => {
|
|
10977
|
+
input.disconnect();
|
|
10978
|
+
delayNode.disconnect();
|
|
10979
|
+
feedback.disconnect();
|
|
10980
|
+
wetGain.disconnect();
|
|
10981
|
+
}
|
|
10982
|
+
};
|
|
10983
|
+
};
|
|
10984
|
+
|
|
10821
10985
|
// src/daw-ui.ts
|
|
10822
10986
|
var q = (root, sel) => root.querySelector(sel);
|
|
10823
10987
|
var buildUI = (target, options) => {
|
|
@@ -10934,6 +11098,25 @@ var buildUI = (target, options) => {
|
|
|
10934
11098
|
<span class="dtm-label" data-dtm="reverb-amount-label">0%</span>
|
|
10935
11099
|
<button class="dtm-infobtn" data-dtm="reverb-amount-info" title="\u30DE\u30B9\u30BF\u30EA\u30D0\u30FC\u30D6\u306E\u89E3\u8AAC">${icon("info", 12)}</button>
|
|
10936
11100
|
</div>
|
|
11101
|
+
<div class="dtm-row">
|
|
11102
|
+
<span class="dtm-label">Decay</span>
|
|
11103
|
+
<input type="range" class="dtm-range dtm-grow" data-dtm="reverb-decay" value="22" min="3" max="40" step="1" aria-label="\u30EA\u30D0\u30FC\u30D6\u306EDecay\uFF08\u6B8B\u97FF\u306E\u9577\u3055\u3001\u79D2\uFF09">
|
|
11104
|
+
<span class="dtm-label" data-dtm="reverb-decay-label">2.2s</span>
|
|
11105
|
+
</div>
|
|
11106
|
+
<div class="dtm-row">
|
|
11107
|
+
<span class="dtm-label">Pre Delay</span>
|
|
11108
|
+
<input type="range" class="dtm-range dtm-grow" data-dtm="reverb-predelay" value="0" min="0" max="150" step="5" aria-label="\u30EA\u30D0\u30FC\u30D6\u306EPre Delay\uFF08\u539F\u97F3\u304B\u3089\u6B8B\u97FF\u304C\u7ACB\u3061\u4E0A\u304C\u308B\u307E\u3067\u306E\u9045\u5EF6\u3001ms\uFF09">
|
|
11109
|
+
<span class="dtm-label" data-dtm="reverb-predelay-label">0ms</span>
|
|
11110
|
+
</div>
|
|
11111
|
+
<div class="dtm-row">
|
|
11112
|
+
<span class="dtm-label">\u30C7\u30A3\u30EC\u30A4</span>
|
|
11113
|
+
<input type="range" class="dtm-range dtm-grow" data-dtm="delay-amount" value="0" min="0" max="100" aria-label="\u30DE\u30B9\u30BF\u30C7\u30A3\u30EC\u30A4\uFF08\u30C6\u30F3\u30DD\u540C\u671F\u3057\u305F\u30A8\u30B3\u30FC\uFF09">
|
|
11114
|
+
<span class="dtm-label" data-dtm="delay-amount-label">0%</span>
|
|
11115
|
+
<select class="dtm-select" data-dtm="delay-division" aria-label="\u30C7\u30A3\u30EC\u30A4\u306E\u97F3\u4FA1\uFF08\u30C6\u30F3\u30DD\u306B\u540C\u671F\uFF09">
|
|
11116
|
+
${DELAY_DIVISIONS.map((d) => `<option value="${d.value}">${d.label}</option>`).join("")}
|
|
11117
|
+
</select>
|
|
11118
|
+
<button class="dtm-infobtn" data-dtm="delay-amount-info" title="\u30DE\u30B9\u30BF\u30C7\u30A3\u30EC\u30A4\u306E\u89E3\u8AAC">${icon("info", 12)}</button>
|
|
11119
|
+
</div>
|
|
10937
11120
|
</div>
|
|
10938
11121
|
</details>
|
|
10939
11122
|
|
|
@@ -11132,6 +11315,14 @@ var buildUI = (target, options) => {
|
|
|
11132
11315
|
reverbAmount: sel("reverb-amount"),
|
|
11133
11316
|
reverbAmountLabel: sel("reverb-amount-label"),
|
|
11134
11317
|
reverbAmountInfoBtn: sel("reverb-amount-info"),
|
|
11318
|
+
reverbDecay: sel("reverb-decay"),
|
|
11319
|
+
reverbDecayLabel: sel("reverb-decay-label"),
|
|
11320
|
+
reverbPreDelay: sel("reverb-predelay"),
|
|
11321
|
+
reverbPreDelayLabel: sel("reverb-predelay-label"),
|
|
11322
|
+
delayAmount: sel("delay-amount"),
|
|
11323
|
+
delayAmountLabel: sel("delay-amount-label"),
|
|
11324
|
+
delayAmountInfoBtn: sel("delay-amount-info"),
|
|
11325
|
+
delayDivision: sel("delay-division"),
|
|
11135
11326
|
autoMasterBtn: sel("auto-master"),
|
|
11136
11327
|
autoMasterInfoBtn: sel("auto-master-info"),
|
|
11137
11328
|
trackTabs: sel("track-tabs"),
|
|
@@ -12765,6 +12956,38 @@ var isChordHeavyTrack = (notes, threshold = 0.6) => {
|
|
|
12765
12956
|
return chordNotes / notes.length >= threshold;
|
|
12766
12957
|
};
|
|
12767
12958
|
|
|
12959
|
+
// src/reverb.ts
|
|
12960
|
+
var DEFAULT_REVERB_DECAY_SEC = 2.2;
|
|
12961
|
+
var MIN_REVERB_DECAY_SEC = 0.3;
|
|
12962
|
+
var MAX_REVERB_DECAY_SEC = 4;
|
|
12963
|
+
var IMPULSE_DECAY_CURVE = 2.5;
|
|
12964
|
+
var DEFAULT_REVERB_PREDELAY_MS = 0;
|
|
12965
|
+
var MIN_REVERB_PREDELAY_MS = 0;
|
|
12966
|
+
var MAX_REVERB_PREDELAY_MS = 150;
|
|
12967
|
+
var createReverbImpulse = (ctx, decaySec = DEFAULT_REVERB_DECAY_SEC) => {
|
|
12968
|
+
const rate = ctx.sampleRate;
|
|
12969
|
+
const length = Math.max(
|
|
12970
|
+
1,
|
|
12971
|
+
Math.floor(
|
|
12972
|
+
rate * Math.max(
|
|
12973
|
+
MIN_REVERB_DECAY_SEC,
|
|
12974
|
+
Math.min(MAX_REVERB_DECAY_SEC, decaySec)
|
|
12975
|
+
)
|
|
12976
|
+
)
|
|
12977
|
+
);
|
|
12978
|
+
const impulse = ctx.createBuffer(2, length, rate);
|
|
12979
|
+
for (let ch = 0; ch < impulse.numberOfChannels; ch++) {
|
|
12980
|
+
const data = impulse.getChannelData(ch);
|
|
12981
|
+
for (let i2 = 0; i2 < length; i2++) {
|
|
12982
|
+
const envelope = (1 - i2 / length) ** IMPULSE_DECAY_CURVE;
|
|
12983
|
+
data[i2] = (Math.random() * 2 - 1) * envelope;
|
|
12984
|
+
}
|
|
12985
|
+
}
|
|
12986
|
+
return impulse;
|
|
12987
|
+
};
|
|
12988
|
+
var REVERB_MAX_WET = 0.6;
|
|
12989
|
+
var reverbAmountToGain = (amount) => Math.max(0, Math.min(100, amount)) / 100 * REVERB_MAX_WET;
|
|
12990
|
+
|
|
12768
12991
|
// src/daw.ts
|
|
12769
12992
|
var CHORD_INFO_HTML2 = `
|
|
12770
12993
|
<div class="dtm-modal-body-content">
|
|
@@ -12836,14 +13059,46 @@ var LYRIC_REVERB_INFO_HTML = `
|
|
|
12836
13059
|
<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>
|
|
12837
13060
|
</div>
|
|
12838
13061
|
`;
|
|
12839
|
-
var
|
|
13062
|
+
var LYRIC_DELAY_INFO_HTML = `
|
|
12840
13063
|
<div class="dtm-modal-body-content">
|
|
12841
13064
|
<h4>\u4F55\u3092\u3059\u308B\u8A2D\u5B9A\u304B</h4>
|
|
12842
|
-
<p>\
|
|
13065
|
+
<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\u30C7\u30A3\u30EC\u30A4\u300D\u3078\u3069\u308C\u3060\u3051\u97F3\u3092\u9001\u308B\u304B\u3092\u6C7A\u3081\u307E\u3059\uFF080\u3067\u9001\u3089\u306A\u3044\u3001100\u3067\u76EE\u4E00\u676F\u9001\u308B\uFF09\u3002</p>
|
|
13066
|
+
<h4>\u30DE\u30B9\u30BF\u306E\u300C\u30C7\u30A3\u30EC\u30A4\u300D\u3064\u307E\u307F\u3068\u306E\u95A2\u4FC2\uFF08\u91CD\u8981\uFF09</h4>
|
|
13067
|
+
<p>\u30DE\u30B9\u30BF\u306E\u300C\u30C7\u30A3\u30EC\u30A4\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\u30EA\u30D0\u30FC\u30D6\u9001\u308A\u3068\u540C\u3058\u4E8C\u6BB5\u69CB\u3048\u3067\u3059\u3002</p>
|
|
13068
|
+
<h4>\u4F7F\u3044\u3069\u3053\u308D</h4>
|
|
13069
|
+
<p>\u66F2\u5168\u4F53\u306B\u3046\u3063\u3059\u3089\u639B\u3051\u308B\u30EA\u30D0\u30FC\u30D6\u3068\u9055\u3044\u3001\u30C7\u30A3\u30EC\u30A4\u306F\u30CF\u30C3\u30AD\u30EA\u805E\u3053\u3048\u308B\u7E70\u308A\u8FD4\u3057\u306A\u306E\u3067\u3001A\u30E1\u30ED\u306F0%\u30FB\u30B5\u30D3\u306E\u8A9E\u5C3E\u3060\u3051\u9001\u308A\u91CF\u3092\u4E0A\u3052\u308B\u3001\u3068\u3044\u3063\u305F\u30E1\u30EA\u30CF\u30EA\u306E\u3042\u308B\u4F7F\u3044\u65B9\u304C\u52B9\u679C\u7684\u3067\u3059\u3002\u30D0\u30C3\u30AD\u30F3\u30B0\u5168\u4F53\u306B\u5F37\u304F\u639B\u3051\u308B\u3068\u30EA\u30BA\u30E0\u304C\u6FC1\u308A\u307E\u3059\u3002</p>
|
|
13070
|
+
</div>
|
|
13071
|
+
`;
|
|
13072
|
+
var MASTER_REVERB_INFO_HTML = `
|
|
13073
|
+
<div class="dtm-modal-body-content">
|
|
13074
|
+
<h4>\u30EA\u30D0\u30FC\u30D6\uFF08Mix\uFF09</h4>
|
|
13075
|
+
<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\u306E\u91CF\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\u639B\u3051\u3059\u304E\u308B\u3068\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\u304C\u51FA\u767A\u70B9\u306E\u76EE\u5B89\u3067\u3059\u3002</p>
|
|
13076
|
+
<h4>Decay\uFF08\u6B8B\u97FF\u306E\u9577\u3055\uFF09</h4>
|
|
13077
|
+
<p>\u30EA\u30D0\u30FC\u30D6\u304C\u9CF4\u308A\u7D9A\u3051\u308B\u9577\u3055\u3067\u3059\u3002\u9577\u3044\u307B\u3069\u5E83\u3044\u30DB\u30FC\u30EB\u306E\u3088\u3046\u306A\u7A7A\u9593\u306E\u5370\u8C61\u306B\u306A\u308A\u3001\u77ED\u3044\u3068\u72ED\u3044\u90E8\u5C4B\u306E\u3088\u3046\u306A\u5BC6\u7740\u611F\u306B\u306A\u308A\u307E\u3059\u3002\u76EE\u5B89\u3068\u3057\u3066\u3001\u901F\u3044\u66F2\u3067\u306F0.6\u301C1.4\u79D2\u3001\u9045\u3044\u66F2\u30FB\u30D0\u30E9\u30FC\u30C9\u3067\u306F1.8\u301C4.0\u79D2\u7A0B\u5EA6\u304C\u3088\u304F\u4F7F\u308F\u308C\u307E\u3059\u3002</p>
|
|
13078
|
+
<h4>Pre Delay\uFF08\u539F\u97F3\u3068\u30EA\u30D0\u30FC\u30D6\u306E\u9593\u9694\uFF09</h4>
|
|
13079
|
+
<p>\u539F\u97F3\u304C\u9CF4\u3063\u3066\u304B\u3089\u6B8B\u97FF\u304C\u7ACB\u3061\u4E0A\u304C\u308B\u307E\u3067\u306E\u9045\u5EF6\u3067\u3059\u30020ms\u3060\u3068\u539F\u97F3\u3068\u6B8B\u97FF\u304C\u540C\u6642\u306B\u59CB\u307E\u308A\u97F3\u50CF\u304C\u307C\u3084\u3051\u304C\u3061\u3067\u3059\u304C\u3001\u5C11\u3057\uFF08\u6570\u5341ms\u7A0B\u5EA6\uFF09\u5165\u308C\u308B\u3068\u539F\u97F3\u306E\u8F2A\u90ED\u30FB\u30A2\u30BF\u30C3\u30AF\u611F\u3092\u4FDD\u3063\u305F\u307E\u307E\u5965\u884C\u304D\u3092\u8DB3\u305B\u307E\u3059\u3002\u7279\u306B\u30DC\u30FC\u30AB\u30EB\u3067\u52B9\u679C\u7684\u3067\u3059\u3002</p>
|
|
12843
13080
|
<h4>\u5404\u30C8\u30E9\u30C3\u30AF\u306E\u300C\u30EA\u30D0\u30FC\u30D6\u9001\u308A\u300D\u3068\u306E\u95A2\u4FC2\uFF08\u91CD\u8981\uFF09</h4>
|
|
12844
|
-
<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\
|
|
12845
|
-
|
|
12846
|
-
|
|
13081
|
+
<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\u306EMix\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\u30FB\u91CF\u30FB\u30BF\u30A4\u30DF\u30F3\u30B0\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>
|
|
13082
|
+
</div>
|
|
13083
|
+
`;
|
|
13084
|
+
var MASTER_DELAY_INFO_HTML = `
|
|
13085
|
+
<div class="dtm-modal-body-content">
|
|
13086
|
+
<h4>\u4F55\u3092\u3059\u308B\u8A2D\u5B9A\u304B</h4>
|
|
13087
|
+
<p>\u96E2\u6563\u3057\u305F\u30A8\u30B3\u30FC\uFF08\u97F3\u306E\u7E70\u308A\u8FD4\u3057\uFF09\u3092\u4ED8\u52A0\u3057\u307E\u3059\u3002\u66F2\u306EBPM\u306B\u81EA\u52D5\u540C\u671F\u3059\u308B\u97F3\u4FA1\uFF088\u5206\u30FB\u4ED8\u70B98\u5206\u306A\u3069\uFF09\u3092\u9078\u3093\u3067\u4F7F\u3046\u306E\u304C\u57FA\u672C\u3067\u3001\u7121\u95A2\u4FC2\u306A\u79D2\u6570\u3067\u9CF4\u3089\u3059\u3068\u30EA\u30BA\u30E0\u304C\u5D29\u308C\u3066\u805E\u3053\u3048\u307E\u3059\u3002</p>
|
|
13088
|
+
<h4>\u30EA\u30D0\u30FC\u30D6\u3068\u306E\u9055\u3044</h4>
|
|
13089
|
+
<p>\u30EA\u30D0\u30FC\u30D6\u306F\u62E1\u6563\u3057\u305F\u6B8B\u97FF\u3067\u7A7A\u9593\u5168\u4F53\u306B\u8584\u304F\u639B\u3051\u308B\u306E\u304C\u57FA\u672C\u3067\u3059\u304C\u3001\u30C7\u30A3\u30EC\u30A4\u306F\u30CF\u30C3\u30AD\u30EA\u805E\u3053\u3048\u308B\u7E70\u308A\u8FD4\u3057\u306A\u306E\u3067\u300C\u3053\u3053\u305E\u300D\u3068\u3044\u3046\u5834\u9762\uFF08\u30EA\u30FC\u30C9\u30DC\u30FC\u30AB\u30EB\u306E\u8A9E\u5C3E\u3001\u30AE\u30BF\u30FC\u30BD\u30ED\u3001\u30B7\u30F3\u30BB\u306E\u30D5\u30EC\u30FC\u30BA\u7B49\uFF09\u306B\u30EF\u30F3\u30DD\u30A4\u30F3\u30C8\u3067\u4F7F\u3046\u306E\u304C\u5B9A\u756A\u3067\u3059\u3002\u30D0\u30C3\u30AD\u30F3\u30B0\u5168\u4F53\u306B\u5F37\u304F\u639B\u3051\u308B\u3068\u30EA\u30BA\u30E0\u304C\u6FC1\u308A\u307E\u3059\u3002</p>
|
|
13090
|
+
<h4>\u5404\u30C8\u30E9\u30C3\u30AF\u306E\u300C\u30C7\u30A3\u30EC\u30A4\u9001\u308A\u300D\u3068\u306E\u95A2\u4FC2</h4>
|
|
13091
|
+
<p>\u30EA\u30D0\u30FC\u30D6\u3068\u540C\u3058\u4E8C\u6BB5\u69CB\u3048\u3067\u3059\u3002\u6B4C\u8A5E\u30C8\u30E9\u30C3\u30AF\u500B\u5225\u306E\u300C\u30C7\u30A3\u30EC\u30A4\u9001\u308A\u300D\u304C0%\u306A\u3089\u3053\u306E\u30DE\u30B9\u30BF\u306E\u5024\u3092\u4E0A\u3052\u3066\u3082\u7121\u97F3\u3001\u9006\u306B\u3053\u306E\u30DE\u30B9\u30BF\u304C0%\u306A\u3089\u3069\u306E\u30C8\u30E9\u30C3\u30AF\u306E\u9001\u308A\u91CF\u3092\u4E0A\u3052\u3066\u3082\u52B9\u679C\u304C\u51FA\u307E\u305B\u3093\u3002</p>
|
|
13092
|
+
</div>
|
|
13093
|
+
`;
|
|
13094
|
+
var TRACK_EQ_INFO_HTML = `
|
|
13095
|
+
<div class="dtm-modal-body-content">
|
|
13096
|
+
<h4>\u4F55\u3092\u3059\u308B\u8A2D\u5B9A\u304B</h4>
|
|
13097
|
+
<p>\u3053\u306E\u30C8\u30E9\u30C3\u30AF\u306E\u5468\u6CE2\u6570\u5E2F\u57DF\u3054\u3068\u306E\u97F3\u91CF\u3092\u8ABF\u6574\u3057\u307E\u3059\u3002\u4F4E\u57DF\u30FB\u4E2D\u57DF\u30FB\u9AD8\u57DF\u306E3\u30D0\u30F3\u30C9\u3001\u305D\u308C\u305E\u308C-12dB\uFF08\u524A\u308B\uFF09\u301C+12dB\uFF08\u6301\u3061\u4E0A\u3052\u308B\uFF09\u30010dB\u304C\u7121\u5909\u5316\u3067\u3059\u3002</p>
|
|
13098
|
+
<h4>\u4F7F\u3044\u3069\u3053\u308D\uFF08\u5E2F\u57DF\u306E\u68F2\u307F\u5206\u3051\uFF09</h4>
|
|
13099
|
+
<p>\u8907\u6570\u306E\u97F3\u304C\u540C\u3058\u5E2F\u57DF\u3067\u9CF4\u3063\u3066\u3044\u308B\u3068\u6FC1\u3063\u3066\u805E\u3053\u3048\u307E\u3059\u3002\u4F8B\u3048\u3070\u3001\u30DC\u30FC\u30AB\u30EB\u3068\u30EA\u30FC\u30C9\u697D\u5668\u304C\u4E2D\u57DF\u3067\u3076\u3064\u304B\u308B\u306A\u3089\u7247\u65B9\u306E\u4E2D\u57DF\u3092\u8EFD\u304F\u524A\u308B\u3001\u30D9\u30FC\u30B9\u3068\u30D0\u30B9\u30C9\u30E9\u30E0\u306E\u4F4E\u57DF\u304C\u3076\u3064\u304B\u308B\u306A\u3089\u7247\u65B9\u3060\u3051\u4F4E\u57DF\u3092\u524A\u308B\u3001\u3068\u3044\u3063\u305F\u300C\u5E2F\u57DF\u306E\u4EA4\u901A\u6574\u7406\u300D\u304CEQ\u306E\u4E3B\u306A\u4ED5\u4E8B\u3067\u3059\u3002</p>
|
|
13100
|
+
<h4>\u4ED6\u306E\u8A2D\u5B9A\u3068\u306E\u517C\u306D\u5408\u3044\uFF08\u9806\u5E8F\u304C\u91CD\u8981\uFF09</h4>
|
|
13101
|
+
<p>\u3053\u306E\u30C1\u30E3\u30F3\u30CD\u30EB\u30B9\u30C8\u30EA\u30C3\u30D7\u3067\u306F EQ \u2192 \u97F3\u5727\u5F37\u5316\uFF08\u30B3\u30F3\u30D7\u30EC\u30C3\u30B5\u30FC\uFF09 \u2192 \u30B9\u30C6\u30EC\u30AA\u5E45 \u306E\u9806\u3067\u51E6\u7406\u3055\u308C\u307E\u3059\u3002\u3053\u308C\u306F\u4E00\u822C\u7684\u306A\u30DF\u30C3\u30AF\u30B9\u306E\u5B9A\u77F3\u3068\u540C\u3058\u3067\u3059\u3002\u4E0D\u8981\u306A\u5E2F\u57DF\uFF08\u4F4E\u57DF\u306E\u3053\u3082\u308A\u3001\u8033\u969C\u308A\u306A\u9AD8\u57DF\u7B49\uFF09\u3092\u5148\u306BEQ\u3067\u524A\u3063\u3066\u304B\u3089\u30B3\u30F3\u30D7\u30EC\u30C3\u30B5\u30FC\u3092\u639B\u3051\u308B\u3068\u3001\u30B3\u30F3\u30D7\u304C\u672C\u5F53\u306B\u5FC5\u8981\u306A\u97F3\u3060\u3051\u306B\u53CD\u5FDC\u3059\u308B\u3088\u3046\u306B\u306A\u308A\u3001\u97F3\u5727\u5F37\u5316\u306E\u52B9\u304D\u304C\u826F\u304F\u306A\u308A\u307E\u3059\u3002\u9806\u5E8F\u3092\u5909\u3048\u308B\u3053\u3068\u306F\u3067\u304D\u307E\u305B\u3093\u3002</p>
|
|
12847
13102
|
</div>
|
|
12848
13103
|
`;
|
|
12849
13104
|
var TRACK_COMPRESSION_INFO_HTML = `
|
|
@@ -12869,14 +13124,22 @@ var TRACK_WIDTH_INFO_HTML = `
|
|
|
12869
13124
|
var AUTO_MASTER_INFO_HTML = `
|
|
12870
13125
|
<div class="dtm-modal-body-content">
|
|
12871
13126
|
<h4>\u304A\u307E\u304B\u305B\u30DE\u30B9\u30BF\u30EA\u30F3\u30B0\u3068\u306F</h4>
|
|
12872
|
-
<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>
|
|
13127
|
+
<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\u66F2\u306EBPM\u3092\u898B\u3066\u4E00\u90E8\u306E\u5024\u3092\u81EA\u52D5\u8ABF\u6574\u3057\u307E\u3059\u3002</p>
|
|
12873
13128
|
<ul>
|
|
12874
|
-
<li>\u30DE\u30B9\u30BF\u30EA\u30D0\u30FC\u30D6: 20%</li>
|
|
12875
|
-
<li>\
|
|
13129
|
+
<li>\u30DE\u30B9\u30BF\u30EA\u30D0\u30FC\u30D6 Mix: 20%</li>
|
|
13130
|
+
<li>\u30DE\u30B9\u30BF\u30EA\u30D0\u30FC\u30D6 Decay: <strong>\u73FE\u5728\u306EBPM\u306B\u5FDC\u3058\u3066\u81EA\u52D5\u8A08\u7B97</strong>\uFF08\u901F\u3044\u66F2\u307B\u3069\u77ED\u304F0.9\u79D2\u5BC4\u308A\u3001\u9045\u3044\u66F2\u307B\u3069\u9577\u304F3.0\u79D2\u5BC4\u308A\uFF09</li>
|
|
13131
|
+
<li>\u30DE\u30B9\u30BF\u30EA\u30D0\u30FC\u30D6 Pre Delay: 20ms\uFF08\u539F\u97F3\u306E\u8F2A\u90ED\u3092\u4FDD\u3063\u305F\u307E\u307E\u5965\u884C\u304D\u3092\u8DB3\u3059\u5B9A\u756A\u5024\uFF09</li>
|
|
13132
|
+
<li>\u5404\u30C8\u30E9\u30C3\u30AF\u306E\u97F3\u5727\u5F37\u5316: \u697D\u566835%\u30FB\u6B4C\u8A5E\u306E\u3042\u308B\u30C8\u30E9\u30C3\u30AF\u306F25%\uFF08\u5F37\u304F\u6F70\u3059\u3068\u8868\u60C5\u304C\u5931\u308F\u308C\u308B\u305F\u3081\u63A7\u3048\u3081\u306B\uFF09</li>
|
|
12876
13133
|
<li>\u5168\u30C8\u30E9\u30C3\u30AF\u306E\u30B9\u30C6\u30EC\u30AA\u5E45: 115%\uFF08\u308F\u305A\u304B\u306B\u5E83\u3052\u308B\uFF09</li>
|
|
12877
|
-
<li>\u6B4C\u8A5E\u306E\u3042\u308B\u30C8\u30E9\u30C3\u30AF: \u81EA\u52D5\u30D3\u30D6\u30E9\u30FC\u30C8ON
|
|
13134
|
+
<li>\u6B4C\u8A5E\u306E\u3042\u308B\u30C8\u30E9\u30C3\u30AF: \u81EA\u52D5\u30D3\u30D6\u30E9\u30FC\u30C8ON</li>
|
|
12878
13135
|
</ul>
|
|
12879
|
-
<
|
|
13136
|
+
<h4>\u30E1\u30A4\u30F3\u30DC\u30FC\u30AB\u30EB\u306E\u81EA\u52D5\u5224\u5B9A</h4>
|
|
13137
|
+
<p>\u6B4C\u8A5E\u306E\u3042\u308B\u30C8\u30E9\u30C3\u30AF\u304C\u8907\u6570\u3042\u308B\u5834\u5408\uFF08\u30CF\u30E2\u30EA\u30FB\u30B3\u30FC\u30E9\u30B9\u30FB\u639B\u3051\u58F0\u7B49\uFF09\u3001\u767A\u97F3\u6642\u9593\u304C\u6700\u3082\u9577\u3044\u30C8\u30E9\u30C3\u30AF\u3092\u300C\u30E1\u30A4\u30F3\u30DC\u30FC\u30AB\u30EB\u300D\u3068\u307F\u306A\u3057\u3001\u4ED6\u3068\u306F\u9055\u3046\u6271\u3044\u306B\u3057\u307E\u3059\u3002</p>
|
|
13138
|
+
<ul>
|
|
13139
|
+
<li>\u30E1\u30A4\u30F3\u30DC\u30FC\u30AB\u30EB: \u97F3\u5727\u5F37\u531630%\u30FB\u30EA\u30D0\u30FC\u30D6\u9001\u308A15%\uFF08\u524D\u306B\u51FA\u3059\uFF09</li>
|
|
13140
|
+
<li>\u305D\u308C\u4EE5\u5916\u306E\u30DC\u30FC\u30AB\u30EB: \u97F3\u5727\u5F37\u531625%\u30FB\u30EA\u30D0\u30FC\u30D6\u9001\u308A30%\uFF08\u5965\u3078\u99B4\u67D3\u307E\u305B\u308B\uFF09</li>
|
|
13141
|
+
</ul>
|
|
13142
|
+
<p style="margin-top:4px;"><small>\u300C\u524D\u306B\u51FA\u3057\u305F\u3044\u97F3\u306F\u30EA\u30D0\u30FC\u30D6\u5C11\u306A\u3081\u3001\u5965\u306B\u7F6E\u304D\u305F\u3044\u97F3\u306F\u30EA\u30D0\u30FC\u30D6\u591A\u3081\u300D\u3068\u3044\u3046\u5B9A\u77F3\u306B\u57FA\u3065\u3044\u3066\u3044\u307E\u3059\u3002EQ\u306F\u66F2\u30FB\u30D1\u30FC\u30C8\u3054\u3068\u306B\u4F55\u304C\u6FC1\u3063\u3066\u3044\u308B\u304B\u6B21\u7B2C\u3067\u81EA\u52D5\u5316\u306B\u5411\u304B\u306A\u3044\u305F\u3081\u5BFE\u8C61\u5916\u3067\u3059\u3002\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>
|
|
12880
13143
|
</div>
|
|
12881
13144
|
`;
|
|
12882
13145
|
var MIDI_INFO_HTML = `
|
|
@@ -13112,7 +13375,7 @@ var deriveCustomVocalKeyFromUrl = (url2) => {
|
|
|
13112
13375
|
if (name && /^[0-9]/.test(name)) name = `_${name}`;
|
|
13113
13376
|
return CUSTOM_VOCAL_KEY_RE.test(name) ? name : "";
|
|
13114
13377
|
};
|
|
13115
|
-
var
|
|
13378
|
+
var clamp4 = (v, min, max) => Math.min(Math.max(v, min), max);
|
|
13116
13379
|
var normalizeInstrumentName = (name) => {
|
|
13117
13380
|
if (!name) return "";
|
|
13118
13381
|
const stripped = name.replace(/\s+/g, "").toLowerCase();
|
|
@@ -13152,6 +13415,17 @@ var mountDAW = (target, options = {}) => {
|
|
|
13152
13415
|
refs.masterVolumeLabel.textContent = `${options.masterVolume ?? 50}%`;
|
|
13153
13416
|
refs.reverbAmount.value = String(options.reverbAmount ?? 0);
|
|
13154
13417
|
refs.reverbAmountLabel.textContent = `${options.reverbAmount ?? 0}%`;
|
|
13418
|
+
{
|
|
13419
|
+
const initDecay = options.reverbDecay ?? DEFAULT_REVERB_DECAY_SEC;
|
|
13420
|
+
const initPreDelay = options.reverbPreDelay ?? DEFAULT_REVERB_PREDELAY_MS;
|
|
13421
|
+
refs.reverbDecay.value = String(Math.round(initDecay * 10));
|
|
13422
|
+
refs.reverbDecayLabel.textContent = `${initDecay.toFixed(1)}s`;
|
|
13423
|
+
refs.reverbPreDelay.value = String(initPreDelay);
|
|
13424
|
+
refs.reverbPreDelayLabel.textContent = `${initPreDelay}ms`;
|
|
13425
|
+
}
|
|
13426
|
+
refs.delayAmount.value = String(options.delayAmount ?? 0);
|
|
13427
|
+
refs.delayAmountLabel.textContent = `${options.delayAmount ?? 0}%`;
|
|
13428
|
+
refs.delayDivision.value = options.delayDivision ?? "8";
|
|
13155
13429
|
refs.drumVolume.value = String(options.drumVolume ?? 80);
|
|
13156
13430
|
refs.drumVolumeLabel.textContent = `${options.drumVolume ?? 80}%`;
|
|
13157
13431
|
const renderConfig = {
|
|
@@ -13168,8 +13442,16 @@ var mountDAW = (target, options = {}) => {
|
|
|
13168
13442
|
let masterVolume = options.masterVolume ?? 50;
|
|
13169
13443
|
options.singingVoices?.setVolume(masterVolume / 100);
|
|
13170
13444
|
let reverbAmount = options.reverbAmount ?? 0;
|
|
13445
|
+
let reverbDecay = options.reverbDecay ?? DEFAULT_REVERB_DECAY_SEC;
|
|
13446
|
+
let reverbPreDelay = options.reverbPreDelay ?? DEFAULT_REVERB_PREDELAY_MS;
|
|
13447
|
+
let delayAmount = options.delayAmount ?? 0;
|
|
13448
|
+
let delayDivision = options.delayDivision ?? "8";
|
|
13171
13449
|
let unsubscribeClip;
|
|
13172
13450
|
options.onReverbChange?.(reverbAmount);
|
|
13451
|
+
options.onReverbDecayChange?.(reverbDecay);
|
|
13452
|
+
options.onReverbPreDelayChange?.(reverbPreDelay);
|
|
13453
|
+
options.onDelayChange?.(delayAmount);
|
|
13454
|
+
options.onDelayDivisionChange?.(delayDivision);
|
|
13173
13455
|
let drumVolume = options.drumVolume ?? 80;
|
|
13174
13456
|
let currentDrumPattern = refs.drumSelect.value;
|
|
13175
13457
|
let currentDrumFont = options.drumFont ?? "FluidR3_GM_sf2_file:0";
|
|
@@ -13250,6 +13532,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
13250
13532
|
vocalOctave: t.vocalOctave,
|
|
13251
13533
|
vocalVibrato: t.vocalVibrato,
|
|
13252
13534
|
vocalReverb: t.vocalReverb,
|
|
13535
|
+
vocalDelay: t.vocalDelay,
|
|
13253
13536
|
vocalGender: t.vocalGender,
|
|
13254
13537
|
vocalBreathiness: t.vocalBreathiness
|
|
13255
13538
|
};
|
|
@@ -13313,11 +13596,15 @@ var mountDAW = (target, options = {}) => {
|
|
|
13313
13596
|
vocalOctave: 0,
|
|
13314
13597
|
vocalVibrato: false,
|
|
13315
13598
|
vocalReverb: 0,
|
|
13599
|
+
vocalDelay: 0,
|
|
13316
13600
|
vocalGender: 50,
|
|
13317
13601
|
vocalBreathiness: 50,
|
|
13318
13602
|
trackInstrument: "",
|
|
13319
13603
|
trackCompression: 0,
|
|
13320
|
-
trackWidth: 100
|
|
13604
|
+
trackWidth: 100,
|
|
13605
|
+
trackEqLow: 0,
|
|
13606
|
+
trackEqMid: 0,
|
|
13607
|
+
trackEqHigh: 0
|
|
13321
13608
|
};
|
|
13322
13609
|
});
|
|
13323
13610
|
};
|
|
@@ -13338,6 +13625,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
13338
13625
|
octave: t.vocalOctave,
|
|
13339
13626
|
vibrato: t.vocalVibrato,
|
|
13340
13627
|
reverb: t.vocalReverb,
|
|
13628
|
+
delay: t.vocalDelay,
|
|
13341
13629
|
gender: t.vocalGender,
|
|
13342
13630
|
breathiness: t.vocalBreathiness,
|
|
13343
13631
|
syllables
|
|
@@ -13460,7 +13748,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
13460
13748
|
const thumbW = Math.max(40, canvas.width / totalContentWidth * sbW);
|
|
13461
13749
|
const ratio = currentOffsetX / maxOffsetX;
|
|
13462
13750
|
refs.hScrollThumb.style.width = `${thumbW}px`;
|
|
13463
|
-
refs.hScrollThumb.style.left = `${
|
|
13751
|
+
refs.hScrollThumb.style.left = `${clamp4(ratio * (sbW - thumbW), 0, sbW - thumbW)}px`;
|
|
13464
13752
|
}
|
|
13465
13753
|
const totalHeight = renderConfig.keyCount * renderConfig.keyHeight;
|
|
13466
13754
|
const sbH = refs.vScroll.clientHeight;
|
|
@@ -13530,9 +13818,9 @@ var mountDAW = (target, options = {}) => {
|
|
|
13530
13818
|
if (maxOffsetX <= 0) return;
|
|
13531
13819
|
const rect = refs.hScroll.getBoundingClientRect();
|
|
13532
13820
|
const thumbW = Number.parseFloat(refs.hScrollThumb.style.width) || 40;
|
|
13533
|
-
const x2 =
|
|
13821
|
+
const x2 = clamp4(clientX - rect.left - thumbW / 2, 0, rect.width - thumbW);
|
|
13534
13822
|
const ratio = x2 / (rect.width - thumbW);
|
|
13535
|
-
currentOffsetX =
|
|
13823
|
+
currentOffsetX = clamp4(ratio * maxOffsetX, 0, maxOffsetX);
|
|
13536
13824
|
setDrawOffset(currentOffsetX, currentOffsetY);
|
|
13537
13825
|
redrawAll();
|
|
13538
13826
|
};
|
|
@@ -13541,9 +13829,9 @@ var mountDAW = (target, options = {}) => {
|
|
|
13541
13829
|
if (maxOffset <= 0) return;
|
|
13542
13830
|
const rect = refs.vScroll.getBoundingClientRect();
|
|
13543
13831
|
const thumbH = Number.parseFloat(refs.vScrollThumb.style.height) || 40;
|
|
13544
|
-
const y =
|
|
13832
|
+
const y = clamp4(clientY - rect.top - thumbH / 2, 0, rect.height - thumbH);
|
|
13545
13833
|
const ratio = y / (rect.height - thumbH);
|
|
13546
|
-
currentOffsetY =
|
|
13834
|
+
currentOffsetY = clamp4(ratio * maxOffset, 0, maxOffset);
|
|
13547
13835
|
setDrawOffset(currentOffsetX, currentOffsetY);
|
|
13548
13836
|
redrawAll();
|
|
13549
13837
|
};
|
|
@@ -13590,8 +13878,8 @@ var mountDAW = (target, options = {}) => {
|
|
|
13590
13878
|
if (dx !== 0 || dy !== 0) {
|
|
13591
13879
|
const maxOffsetX = getMaxOffsetX();
|
|
13592
13880
|
const maxOffsetY = getMaxOffsetY();
|
|
13593
|
-
currentOffsetX =
|
|
13594
|
-
currentOffsetY =
|
|
13881
|
+
currentOffsetX = clamp4(currentOffsetX + dx, 0, maxOffsetX);
|
|
13882
|
+
currentOffsetY = clamp4(currentOffsetY + dy, 0, maxOffsetY);
|
|
13595
13883
|
setDrawOffset(currentOffsetX, currentOffsetY);
|
|
13596
13884
|
onPointerMove(lastMoveEvent);
|
|
13597
13885
|
}
|
|
@@ -13981,12 +14269,12 @@ var mountDAW = (target, options = {}) => {
|
|
|
13981
14269
|
"wheel",
|
|
13982
14270
|
(event) => {
|
|
13983
14271
|
event.preventDefault();
|
|
13984
|
-
currentOffsetY =
|
|
14272
|
+
currentOffsetY = clamp4(
|
|
13985
14273
|
currentOffsetY + event.deltaY,
|
|
13986
14274
|
0,
|
|
13987
14275
|
getMaxOffsetY()
|
|
13988
14276
|
);
|
|
13989
|
-
currentOffsetX =
|
|
14277
|
+
currentOffsetX = clamp4(
|
|
13990
14278
|
currentOffsetX + event.deltaX,
|
|
13991
14279
|
0,
|
|
13992
14280
|
getMaxOffsetX()
|
|
@@ -14025,7 +14313,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
14025
14313
|
const centerStep = (currentOffsetX + canvas.width / 2) / renderConfig.stepWidth;
|
|
14026
14314
|
renderConfig.stepWidth = BASE_STEP_WIDTH * (zoomX * 2) / 100;
|
|
14027
14315
|
refs.zoomXLabel.textContent = `${zoomX}%`;
|
|
14028
|
-
currentOffsetX =
|
|
14316
|
+
currentOffsetX = clamp4(
|
|
14029
14317
|
centerStep * renderConfig.stepWidth - canvas.width / 2,
|
|
14030
14318
|
0,
|
|
14031
14319
|
getMaxOffsetX()
|
|
@@ -14038,7 +14326,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
14038
14326
|
const centerKey = (currentOffsetY + canvas.height / 2) / renderConfig.keyHeight;
|
|
14039
14327
|
renderConfig.keyHeight = BASE_KEY_HEIGHT * zoomY / 100;
|
|
14040
14328
|
refs.zoomYLabel.textContent = `${zoomY}%`;
|
|
14041
|
-
currentOffsetY =
|
|
14329
|
+
currentOffsetY = clamp4(
|
|
14042
14330
|
centerKey * renderConfig.keyHeight - canvas.height / 2,
|
|
14043
14331
|
0,
|
|
14044
14332
|
getMaxOffsetY()
|
|
@@ -14088,7 +14376,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
14088
14376
|
const threshold = currentOffsetX / renderConfig.stepWidth + visibleSteps - 4;
|
|
14089
14377
|
if (currentPlayStep > threshold) {
|
|
14090
14378
|
const visibleBars = Math.round(visibleSteps / renderConfig.stepsPerBar);
|
|
14091
|
-
currentOffsetX =
|
|
14379
|
+
currentOffsetX = clamp4(
|
|
14092
14380
|
currentOffsetX + visibleBars * renderConfig.stepsPerBar * renderConfig.stepWidth,
|
|
14093
14381
|
0,
|
|
14094
14382
|
getMaxOffsetX()
|
|
@@ -14144,6 +14432,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
14144
14432
|
pan: panToStereo(lt.pan ?? DEFAULT_PAN),
|
|
14145
14433
|
vibrato: lt.vibrato,
|
|
14146
14434
|
reverbSend: (lt.reverb ?? 0) / 100,
|
|
14435
|
+
delaySend: (lt.delay ?? 0) / 100,
|
|
14147
14436
|
gender: (lt.gender ?? 50) / 100,
|
|
14148
14437
|
breathiness: (lt.breathiness ?? 50) / 100,
|
|
14149
14438
|
notes
|
|
@@ -14173,7 +14462,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
14173
14462
|
}
|
|
14174
14463
|
if (playbackState !== "paused") {
|
|
14175
14464
|
const canvas = getGridCanvas();
|
|
14176
|
-
currentOffsetX =
|
|
14465
|
+
currentOffsetX = clamp4(
|
|
14177
14466
|
playStartStep * renderConfig.stepWidth - canvas.width * 0.5,
|
|
14178
14467
|
0,
|
|
14179
14468
|
getMaxOffsetX()
|
|
@@ -14253,7 +14542,23 @@ var mountDAW = (target, options = {}) => {
|
|
|
14253
14542
|
<span class="dtm-label" data-dtm="track-vol-label">${active.volume}</span>
|
|
14254
14543
|
</div>
|
|
14255
14544
|
<details class="dtm-advanced" data-dtm="track-fx-advanced">
|
|
14256
|
-
<summary>\u8A73\u7D30\u8A2D\u5B9A\
|
|
14545
|
+
<summary>\u8A73\u7D30\u8A2D\u5B9A\uFF08EQ\u30FB\u97F3\u5727\u30FB\u30B9\u30C6\u30EC\u30AA\u5E45\uFF09</summary>
|
|
14546
|
+
<div class="dtm-row">
|
|
14547
|
+
<span class="dtm-label">EQ\u4F4E\u57DF</span>
|
|
14548
|
+
<input type="range" class="dtm-range dtm-grow" data-dtm="track-eq-low" min="-12" max="12" step="1" aria-label="\u3053\u306E\u30C8\u30E9\u30C3\u30AF\u306EEQ\u4F4E\u57DF\u30B2\u30A4\u30F3\uFF08dB\uFF09">
|
|
14549
|
+
<span class="dtm-label" data-dtm="track-eq-low-label"></span>
|
|
14550
|
+
<button class="dtm-infobtn" data-dtm="track-eq-info" title="EQ\u306E\u89E3\u8AAC">${icon("info", 12)}</button>
|
|
14551
|
+
</div>
|
|
14552
|
+
<div class="dtm-row">
|
|
14553
|
+
<span class="dtm-label">EQ\u4E2D\u57DF</span>
|
|
14554
|
+
<input type="range" class="dtm-range dtm-grow" data-dtm="track-eq-mid" min="-12" max="12" step="1" aria-label="\u3053\u306E\u30C8\u30E9\u30C3\u30AF\u306EEQ\u4E2D\u57DF\u30B2\u30A4\u30F3\uFF08dB\uFF09">
|
|
14555
|
+
<span class="dtm-label" data-dtm="track-eq-mid-label"></span>
|
|
14556
|
+
</div>
|
|
14557
|
+
<div class="dtm-row">
|
|
14558
|
+
<span class="dtm-label">EQ\u9AD8\u57DF</span>
|
|
14559
|
+
<input type="range" class="dtm-range dtm-grow" data-dtm="track-eq-high" min="-12" max="12" step="1" aria-label="\u3053\u306E\u30C8\u30E9\u30C3\u30AF\u306EEQ\u9AD8\u57DF\u30B2\u30A4\u30F3\uFF08dB\uFF09">
|
|
14560
|
+
<span class="dtm-label" data-dtm="track-eq-high-label"></span>
|
|
14561
|
+
</div>
|
|
14257
14562
|
<div class="dtm-row">
|
|
14258
14563
|
<span class="dtm-label">\u97F3\u5727\u5F37\u5316</span>
|
|
14259
14564
|
<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">
|
|
@@ -14283,6 +14588,52 @@ var mountDAW = (target, options = {}) => {
|
|
|
14283
14588
|
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" : "";
|
|
14284
14589
|
};
|
|
14285
14590
|
syncVelocityDisabled();
|
|
14591
|
+
const trackEqLowInput = refs.trackBody.querySelector(
|
|
14592
|
+
'[data-dtm="track-eq-low"]'
|
|
14593
|
+
);
|
|
14594
|
+
const trackEqLowLabel = refs.trackBody.querySelector(
|
|
14595
|
+
'[data-dtm="track-eq-low-label"]'
|
|
14596
|
+
);
|
|
14597
|
+
const trackEqMidInput = refs.trackBody.querySelector(
|
|
14598
|
+
'[data-dtm="track-eq-mid"]'
|
|
14599
|
+
);
|
|
14600
|
+
const trackEqMidLabel = refs.trackBody.querySelector(
|
|
14601
|
+
'[data-dtm="track-eq-mid-label"]'
|
|
14602
|
+
);
|
|
14603
|
+
const trackEqHighInput = refs.trackBody.querySelector(
|
|
14604
|
+
'[data-dtm="track-eq-high"]'
|
|
14605
|
+
);
|
|
14606
|
+
const trackEqHighLabel = refs.trackBody.querySelector(
|
|
14607
|
+
'[data-dtm="track-eq-high-label"]'
|
|
14608
|
+
);
|
|
14609
|
+
const trackEqInfo = refs.trackBody.querySelector(
|
|
14610
|
+
'[data-dtm="track-eq-info"]'
|
|
14611
|
+
);
|
|
14612
|
+
const fmtDb = (db) => db > 0 ? `+${db}dB` : `${db}dB`;
|
|
14613
|
+
trackEqLowInput.value = String(active.trackEqLow);
|
|
14614
|
+
trackEqLowLabel.textContent = fmtDb(active.trackEqLow);
|
|
14615
|
+
trackEqMidInput.value = String(active.trackEqMid);
|
|
14616
|
+
trackEqMidLabel.textContent = fmtDb(active.trackEqMid);
|
|
14617
|
+
trackEqHighInput.value = String(active.trackEqHigh);
|
|
14618
|
+
trackEqHighLabel.textContent = fmtDb(active.trackEqHigh);
|
|
14619
|
+
trackEqLowInput.addEventListener("input", () => {
|
|
14620
|
+
active.trackEqLow = Number.parseInt(trackEqLowInput.value, 10);
|
|
14621
|
+
trackEqLowLabel.textContent = fmtDb(active.trackEqLow);
|
|
14622
|
+
options.onTrackEqLowChange?.(active.config.id, active.trackEqLow);
|
|
14623
|
+
});
|
|
14624
|
+
trackEqMidInput.addEventListener("input", () => {
|
|
14625
|
+
active.trackEqMid = Number.parseInt(trackEqMidInput.value, 10);
|
|
14626
|
+
trackEqMidLabel.textContent = fmtDb(active.trackEqMid);
|
|
14627
|
+
options.onTrackEqMidChange?.(active.config.id, active.trackEqMid);
|
|
14628
|
+
});
|
|
14629
|
+
trackEqHighInput.addEventListener("input", () => {
|
|
14630
|
+
active.trackEqHigh = Number.parseInt(trackEqHighInput.value, 10);
|
|
14631
|
+
trackEqHighLabel.textContent = fmtDb(active.trackEqHigh);
|
|
14632
|
+
options.onTrackEqHighChange?.(active.config.id, active.trackEqHigh);
|
|
14633
|
+
});
|
|
14634
|
+
trackEqInfo.addEventListener("click", () => {
|
|
14635
|
+
showModal("EQ\uFF08\u30A4\u30B3\u30E9\u30A4\u30B6\u30FC\uFF09\u306E\u89E3\u8AAC", TRACK_EQ_INFO_HTML);
|
|
14636
|
+
});
|
|
14286
14637
|
const trackCompInput = refs.trackBody.querySelector(
|
|
14287
14638
|
'[data-dtm="track-comp"]'
|
|
14288
14639
|
);
|
|
@@ -14435,6 +14786,12 @@ var mountDAW = (target, options = {}) => {
|
|
|
14435
14786
|
<span class="dtm-label" data-dtm="lyric-reverb-label"></span>
|
|
14436
14787
|
<button class="dtm-infobtn" data-dtm="lyric-reverb-info" title="\u30EA\u30D0\u30FC\u30D6\u9001\u308A\u306E\u89E3\u8AAC">${icon("info", 12)}</button>
|
|
14437
14788
|
</div>
|
|
14789
|
+
<div class="dtm-row">
|
|
14790
|
+
<span class="dtm-label">\u30C7\u30A3\u30EC\u30A4\u9001\u308A</span>
|
|
14791
|
+
<input type="range" class="dtm-range dtm-grow" data-dtm="lyric-delay" min="0" max="100" aria-label="\u3053\u306E\u30C8\u30E9\u30C3\u30AF\u304B\u3089\u30DE\u30B9\u30BF\u30C7\u30A3\u30EC\u30A4\u3078\u9001\u308B\u91CF\uFF08\u30DE\u30B9\u30BF\u306E\u30C7\u30A3\u30EC\u30A4\u3064\u307E\u307F\u304C0%\u3060\u3068\u7121\u97F3\uFF09">
|
|
14792
|
+
<span class="dtm-label" data-dtm="lyric-delay-label"></span>
|
|
14793
|
+
<button class="dtm-infobtn" data-dtm="lyric-delay-info" title="\u30C7\u30A3\u30EC\u30A4\u9001\u308A\u306E\u89E3\u8AAC">${icon("info", 12)}</button>
|
|
14794
|
+
</div>
|
|
14438
14795
|
<div class="dtm-row">
|
|
14439
14796
|
<span class="dtm-label">\u30B8\u30A7\u30F3\u30C0\u30FC</span>
|
|
14440
14797
|
<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">
|
|
@@ -14499,6 +14856,18 @@ var mountDAW = (target, options = {}) => {
|
|
|
14499
14856
|
lyricReverbInfo.addEventListener("click", () => {
|
|
14500
14857
|
showModal("\u30EA\u30D0\u30FC\u30D6\u9001\u308A\u306E\u89E3\u8AAC", LYRIC_REVERB_INFO_HTML);
|
|
14501
14858
|
});
|
|
14859
|
+
const lyricDelay = lyricDiv.querySelector(
|
|
14860
|
+
'[data-dtm="lyric-delay"]'
|
|
14861
|
+
);
|
|
14862
|
+
const lyricDelayLabel = lyricDiv.querySelector(
|
|
14863
|
+
'[data-dtm="lyric-delay-label"]'
|
|
14864
|
+
);
|
|
14865
|
+
const lyricDelayInfo = lyricDiv.querySelector(
|
|
14866
|
+
'[data-dtm="lyric-delay-info"]'
|
|
14867
|
+
);
|
|
14868
|
+
lyricDelayInfo.addEventListener("click", () => {
|
|
14869
|
+
showModal("\u30C7\u30A3\u30EC\u30A4\u9001\u308A\u306E\u89E3\u8AAC", LYRIC_DELAY_INFO_HTML);
|
|
14870
|
+
});
|
|
14502
14871
|
const lyricGender = lyricDiv.querySelector(
|
|
14503
14872
|
'[data-dtm="lyric-gender"]'
|
|
14504
14873
|
);
|
|
@@ -14595,6 +14964,8 @@ var mountDAW = (target, options = {}) => {
|
|
|
14595
14964
|
lyricPanLabel.textContent = fmtPan(active.vocalPan);
|
|
14596
14965
|
lyricReverb.value = String(active.vocalReverb);
|
|
14597
14966
|
lyricReverbLabel.textContent = `${active.vocalReverb}%`;
|
|
14967
|
+
lyricDelay.value = String(active.vocalDelay);
|
|
14968
|
+
lyricDelayLabel.textContent = `${active.vocalDelay}%`;
|
|
14598
14969
|
lyricGender.value = String(active.vocalGender);
|
|
14599
14970
|
lyricGenderLabel.textContent = `${active.vocalGender}`;
|
|
14600
14971
|
lyricBreathiness.value = String(active.vocalBreathiness);
|
|
@@ -14749,6 +15120,11 @@ var mountDAW = (target, options = {}) => {
|
|
|
14749
15120
|
lyricReverbLabel.textContent = `${active.vocalReverb}%`;
|
|
14750
15121
|
fireLyricsChange(active);
|
|
14751
15122
|
});
|
|
15123
|
+
lyricDelay.addEventListener("input", () => {
|
|
15124
|
+
active.vocalDelay = Number.parseInt(lyricDelay.value, 10);
|
|
15125
|
+
lyricDelayLabel.textContent = `${active.vocalDelay}%`;
|
|
15126
|
+
fireLyricsChange(active);
|
|
15127
|
+
});
|
|
14752
15128
|
lyricGender.addEventListener("input", () => {
|
|
14753
15129
|
active.vocalGender = Number.parseInt(lyricGender.value, 10);
|
|
14754
15130
|
lyricGenderLabel.textContent = `${active.vocalGender}`;
|
|
@@ -14844,15 +15220,24 @@ var mountDAW = (target, options = {}) => {
|
|
|
14844
15220
|
const trackInstrumentsForMeta = {};
|
|
14845
15221
|
const trackCompressionForMeta = {};
|
|
14846
15222
|
const trackWidthForMeta = {};
|
|
15223
|
+
const trackEqLowForMeta = {};
|
|
15224
|
+
const trackEqMidForMeta = {};
|
|
15225
|
+
const trackEqHighForMeta = {};
|
|
14847
15226
|
trackStates.forEach((t, i2) => {
|
|
14848
15227
|
if (t.trackInstrument) trackInstrumentsForMeta[i2] = t.trackInstrument;
|
|
14849
15228
|
if (t.trackCompression !== 0)
|
|
14850
15229
|
trackCompressionForMeta[i2] = t.trackCompression;
|
|
14851
15230
|
if (t.trackWidth !== 100) trackWidthForMeta[i2] = t.trackWidth;
|
|
15231
|
+
if (t.trackEqLow !== 0) trackEqLowForMeta[i2] = t.trackEqLow;
|
|
15232
|
+
if (t.trackEqMid !== 0) trackEqMidForMeta[i2] = t.trackEqMid;
|
|
15233
|
+
if (t.trackEqHigh !== 0) trackEqHighForMeta[i2] = t.trackEqHigh;
|
|
14852
15234
|
});
|
|
14853
15235
|
const trackInstMeta = Object.keys(trackInstrumentsForMeta).length > 0 ? trackInstrumentsForMeta : void 0;
|
|
14854
15236
|
const trackCompMeta = Object.keys(trackCompressionForMeta).length > 0 ? trackCompressionForMeta : void 0;
|
|
14855
15237
|
const trackWidthMeta = Object.keys(trackWidthForMeta).length > 0 ? trackWidthForMeta : void 0;
|
|
15238
|
+
const trackEqLowMeta = Object.keys(trackEqLowForMeta).length > 0 ? trackEqLowForMeta : void 0;
|
|
15239
|
+
const trackEqMidMeta = Object.keys(trackEqMidForMeta).length > 0 ? trackEqMidForMeta : void 0;
|
|
15240
|
+
const trackEqHighMeta = Object.keys(trackEqHighForMeta).length > 0 ? trackEqHighForMeta : void 0;
|
|
14856
15241
|
const metaLineFull = formatMmlMeta(
|
|
14857
15242
|
{
|
|
14858
15243
|
instrument: currentInstrument || void 0,
|
|
@@ -14860,10 +15245,17 @@ var mountDAW = (target, options = {}) => {
|
|
|
14860
15245
|
volume: masterVolume,
|
|
14861
15246
|
drumVolume,
|
|
14862
15247
|
reverb: reverbAmount,
|
|
15248
|
+
reverbDecay: Math.round(reverbDecay * 10),
|
|
15249
|
+
reverbPreDelay,
|
|
15250
|
+
delay: delayAmount,
|
|
15251
|
+
delayDivision,
|
|
14863
15252
|
mode,
|
|
14864
15253
|
trackInstruments: trackInstMeta,
|
|
14865
15254
|
trackCompression: trackCompMeta,
|
|
14866
|
-
trackWidth: trackWidthMeta
|
|
15255
|
+
trackWidth: trackWidthMeta,
|
|
15256
|
+
trackEqLow: trackEqLowMeta,
|
|
15257
|
+
trackEqMid: trackEqMidMeta,
|
|
15258
|
+
trackEqHigh: trackEqHighMeta
|
|
14867
15259
|
},
|
|
14868
15260
|
" "
|
|
14869
15261
|
);
|
|
@@ -14874,10 +15266,17 @@ var mountDAW = (target, options = {}) => {
|
|
|
14874
15266
|
volume: masterVolume,
|
|
14875
15267
|
drumVolume,
|
|
14876
15268
|
reverb: reverbAmount,
|
|
15269
|
+
reverbDecay: Math.round(reverbDecay * 10),
|
|
15270
|
+
reverbPreDelay,
|
|
15271
|
+
delay: delayAmount,
|
|
15272
|
+
delayDivision,
|
|
14877
15273
|
mode,
|
|
14878
15274
|
trackInstruments: trackInstMeta,
|
|
14879
15275
|
trackCompression: trackCompMeta,
|
|
14880
|
-
trackWidth: trackWidthMeta
|
|
15276
|
+
trackWidth: trackWidthMeta,
|
|
15277
|
+
trackEqLow: trackEqLowMeta,
|
|
15278
|
+
trackEqMid: trackEqMidMeta,
|
|
15279
|
+
trackEqHigh: trackEqHighMeta
|
|
14881
15280
|
},
|
|
14882
15281
|
""
|
|
14883
15282
|
);
|
|
@@ -14927,6 +15326,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
14927
15326
|
oct: t.vocalOctave,
|
|
14928
15327
|
vib: t.vocalVibrato,
|
|
14929
15328
|
rev: t.vocalReverb,
|
|
15329
|
+
del: t.vocalDelay,
|
|
14930
15330
|
gen: t.vocalGender,
|
|
14931
15331
|
bre: t.vocalBreathiness
|
|
14932
15332
|
})).filter(
|
|
@@ -14939,6 +15339,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
14939
15339
|
x2.oct === 0 ? "" : `o${x2.oct}`,
|
|
14940
15340
|
x2.vib ? "b1" : "",
|
|
14941
15341
|
x2.rev === 0 ? "" : `r${x2.rev}`,
|
|
15342
|
+
x2.del === 0 ? "" : `e${x2.del}`,
|
|
14942
15343
|
x2.gen === 50 ? "" : `g${x2.gen}`,
|
|
14943
15344
|
x2.bre === 50 ? "" : `h${x2.bre}`
|
|
14944
15345
|
].filter((s) => s.length > 0).join(" ");
|
|
@@ -15009,7 +15410,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
15009
15410
|
const canvas = getGridCanvas();
|
|
15010
15411
|
const yIndex = renderConfig.keyCount - 1 - (pitch - renderConfig.pitchRangeStart);
|
|
15011
15412
|
const logicalY = yIndex * renderConfig.keyHeight;
|
|
15012
|
-
currentOffsetY =
|
|
15413
|
+
currentOffsetY = clamp4(
|
|
15013
15414
|
logicalY - (canvas.height - renderConfig.keyHeight) / 2,
|
|
15014
15415
|
0,
|
|
15015
15416
|
getMaxOffsetY()
|
|
@@ -15086,6 +15487,29 @@ var mountDAW = (target, options = {}) => {
|
|
|
15086
15487
|
refs.reverbAmountLabel.textContent = `${meta.reverb}%`;
|
|
15087
15488
|
options.onReverbChange?.(meta.reverb);
|
|
15088
15489
|
}
|
|
15490
|
+
if (meta.reverbDecay !== void 0) {
|
|
15491
|
+
reverbDecay = meta.reverbDecay / 10;
|
|
15492
|
+
refs.reverbDecay.value = String(meta.reverbDecay);
|
|
15493
|
+
refs.reverbDecayLabel.textContent = `${reverbDecay.toFixed(1)}s`;
|
|
15494
|
+
options.onReverbDecayChange?.(reverbDecay);
|
|
15495
|
+
}
|
|
15496
|
+
if (meta.reverbPreDelay !== void 0) {
|
|
15497
|
+
reverbPreDelay = meta.reverbPreDelay;
|
|
15498
|
+
refs.reverbPreDelay.value = String(meta.reverbPreDelay);
|
|
15499
|
+
refs.reverbPreDelayLabel.textContent = `${meta.reverbPreDelay}ms`;
|
|
15500
|
+
options.onReverbPreDelayChange?.(reverbPreDelay);
|
|
15501
|
+
}
|
|
15502
|
+
if (meta.delay !== void 0) {
|
|
15503
|
+
delayAmount = meta.delay;
|
|
15504
|
+
refs.delayAmount.value = String(meta.delay);
|
|
15505
|
+
refs.delayAmountLabel.textContent = `${meta.delay}%`;
|
|
15506
|
+
options.onDelayChange?.(meta.delay);
|
|
15507
|
+
}
|
|
15508
|
+
if (meta.delayDivision && ["4", "8", "8d", "16"].includes(meta.delayDivision)) {
|
|
15509
|
+
delayDivision = meta.delayDivision;
|
|
15510
|
+
refs.delayDivision.value = delayDivision;
|
|
15511
|
+
options.onDelayDivisionChange?.(delayDivision);
|
|
15512
|
+
}
|
|
15089
15513
|
}
|
|
15090
15514
|
trackStates.forEach((t, i2) => {
|
|
15091
15515
|
if (applyActiveOnly && i2 !== activeTrackIndex) return;
|
|
@@ -15107,6 +15531,21 @@ var mountDAW = (target, options = {}) => {
|
|
|
15107
15531
|
t.trackWidth = width;
|
|
15108
15532
|
options.onTrackWidthChange?.(t.config.id, width);
|
|
15109
15533
|
}
|
|
15534
|
+
const eqLow = meta.trackEqLow?.[i2] ?? 0;
|
|
15535
|
+
if (t.trackEqLow !== eqLow) {
|
|
15536
|
+
t.trackEqLow = eqLow;
|
|
15537
|
+
options.onTrackEqLowChange?.(t.config.id, eqLow);
|
|
15538
|
+
}
|
|
15539
|
+
const eqMid = meta.trackEqMid?.[i2] ?? 0;
|
|
15540
|
+
if (t.trackEqMid !== eqMid) {
|
|
15541
|
+
t.trackEqMid = eqMid;
|
|
15542
|
+
options.onTrackEqMidChange?.(t.config.id, eqMid);
|
|
15543
|
+
}
|
|
15544
|
+
const eqHigh = meta.trackEqHigh?.[i2] ?? 0;
|
|
15545
|
+
if (t.trackEqHigh !== eqHigh) {
|
|
15546
|
+
t.trackEqHigh = eqHigh;
|
|
15547
|
+
options.onTrackEqHighChange?.(t.config.id, eqHigh);
|
|
15548
|
+
}
|
|
15110
15549
|
});
|
|
15111
15550
|
trackStates.forEach((t, i2) => {
|
|
15112
15551
|
if (applyActiveOnly && i2 !== activeTrackIndex) return;
|
|
@@ -15126,6 +15565,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
15126
15565
|
active.vocalOctave = 0;
|
|
15127
15566
|
active.vocalVibrato = false;
|
|
15128
15567
|
active.vocalReverb = 0;
|
|
15568
|
+
active.vocalDelay = 0;
|
|
15129
15569
|
active.vocalGender = 50;
|
|
15130
15570
|
active.vocalBreathiness = 50;
|
|
15131
15571
|
} else {
|
|
@@ -15138,6 +15578,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
15138
15578
|
t.vocalOctave = 0;
|
|
15139
15579
|
t.vocalVibrato = false;
|
|
15140
15580
|
t.vocalReverb = 0;
|
|
15581
|
+
t.vocalDelay = 0;
|
|
15141
15582
|
t.vocalGender = 50;
|
|
15142
15583
|
t.vocalBreathiness = 50;
|
|
15143
15584
|
}
|
|
@@ -15154,6 +15595,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
15154
15595
|
t.vocalOctave = lt.octave ?? 0;
|
|
15155
15596
|
t.vocalVibrato = lt.vibrato ?? false;
|
|
15156
15597
|
t.vocalReverb = lt.reverb ?? 0;
|
|
15598
|
+
t.vocalDelay = lt.delay ?? 0;
|
|
15157
15599
|
t.vocalGender = lt.gender ?? 50;
|
|
15158
15600
|
t.vocalBreathiness = lt.breathiness ?? 50;
|
|
15159
15601
|
});
|
|
@@ -15236,6 +15678,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
15236
15678
|
active.vocalOctave = 0;
|
|
15237
15679
|
active.vocalVibrato = false;
|
|
15238
15680
|
active.vocalReverb = 0;
|
|
15681
|
+
active.vocalDelay = 0;
|
|
15239
15682
|
active.vocalGender = 50;
|
|
15240
15683
|
active.vocalBreathiness = 50;
|
|
15241
15684
|
} else {
|
|
@@ -15250,6 +15693,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
15250
15693
|
t.vocalOctave = 0;
|
|
15251
15694
|
t.vocalVibrato = false;
|
|
15252
15695
|
t.vocalReverb = 0;
|
|
15696
|
+
t.vocalDelay = 0;
|
|
15253
15697
|
t.vocalGender = 50;
|
|
15254
15698
|
t.vocalBreathiness = 50;
|
|
15255
15699
|
}
|
|
@@ -15300,6 +15744,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
15300
15744
|
bpm = value;
|
|
15301
15745
|
refs.bpmInput.value = String(value);
|
|
15302
15746
|
for (const t of trackStates) t.core.setTempo(value);
|
|
15747
|
+
options.onBpmChange?.(value);
|
|
15303
15748
|
};
|
|
15304
15749
|
let lastUndoTime = 0;
|
|
15305
15750
|
const undo = () => {
|
|
@@ -15475,6 +15920,32 @@ var mountDAW = (target, options = {}) => {
|
|
|
15475
15920
|
refs.reverbAmountInfoBtn.addEventListener("click", () => {
|
|
15476
15921
|
showModal("\u30DE\u30B9\u30BF\u30EA\u30D0\u30FC\u30D6\u306E\u89E3\u8AAC", MASTER_REVERB_INFO_HTML);
|
|
15477
15922
|
});
|
|
15923
|
+
refs.reverbDecay.addEventListener("input", () => {
|
|
15924
|
+
const raw = Number.parseInt(refs.reverbDecay.value, 10) || 22;
|
|
15925
|
+
reverbDecay = Math.max(
|
|
15926
|
+
MIN_REVERB_DECAY_SEC,
|
|
15927
|
+
Math.min(MAX_REVERB_DECAY_SEC, raw / 10)
|
|
15928
|
+
);
|
|
15929
|
+
refs.reverbDecayLabel.textContent = `${reverbDecay.toFixed(1)}s`;
|
|
15930
|
+
options.onReverbDecayChange?.(reverbDecay);
|
|
15931
|
+
});
|
|
15932
|
+
refs.reverbPreDelay.addEventListener("input", () => {
|
|
15933
|
+
reverbPreDelay = Number.parseInt(refs.reverbPreDelay.value, 10) || 0;
|
|
15934
|
+
refs.reverbPreDelayLabel.textContent = `${reverbPreDelay}ms`;
|
|
15935
|
+
options.onReverbPreDelayChange?.(reverbPreDelay);
|
|
15936
|
+
});
|
|
15937
|
+
refs.delayAmount.addEventListener("input", () => {
|
|
15938
|
+
delayAmount = Number.parseInt(refs.delayAmount.value, 10) || 0;
|
|
15939
|
+
refs.delayAmountLabel.textContent = `${delayAmount}%`;
|
|
15940
|
+
options.onDelayChange?.(delayAmount);
|
|
15941
|
+
});
|
|
15942
|
+
refs.delayDivision.addEventListener("change", () => {
|
|
15943
|
+
delayDivision = refs.delayDivision.value;
|
|
15944
|
+
options.onDelayDivisionChange?.(delayDivision);
|
|
15945
|
+
});
|
|
15946
|
+
refs.delayAmountInfoBtn.addEventListener("click", () => {
|
|
15947
|
+
showModal("\u30DE\u30B9\u30BF\u30C7\u30A3\u30EC\u30A4\u306E\u89E3\u8AAC", MASTER_DELAY_INFO_HTML);
|
|
15948
|
+
});
|
|
15478
15949
|
refs.autoMasterInfoBtn.addEventListener("click", () => {
|
|
15479
15950
|
showModal("\u304A\u307E\u304B\u305B\u30DE\u30B9\u30BF\u30EA\u30F3\u30B0\u89E3\u8AAC", AUTO_MASTER_INFO_HTML);
|
|
15480
15951
|
});
|
|
@@ -15483,14 +15954,39 @@ var mountDAW = (target, options = {}) => {
|
|
|
15483
15954
|
refs.reverbAmount.value = "20";
|
|
15484
15955
|
refs.reverbAmountLabel.textContent = "20%";
|
|
15485
15956
|
options.onReverbChange?.(20);
|
|
15957
|
+
const bpmT = clamp4((bpm - 60) / (180 - 60), 0, 1);
|
|
15958
|
+
reverbDecay = clamp4(
|
|
15959
|
+
3 - bpmT * (3 - 0.9),
|
|
15960
|
+
MIN_REVERB_DECAY_SEC,
|
|
15961
|
+
MAX_REVERB_DECAY_SEC
|
|
15962
|
+
);
|
|
15963
|
+
refs.reverbDecay.value = String(Math.round(reverbDecay * 10));
|
|
15964
|
+
refs.reverbDecayLabel.textContent = `${reverbDecay.toFixed(1)}s`;
|
|
15965
|
+
options.onReverbDecayChange?.(reverbDecay);
|
|
15966
|
+
reverbPreDelay = 20;
|
|
15967
|
+
refs.reverbPreDelay.value = "20";
|
|
15968
|
+
refs.reverbPreDelayLabel.textContent = "20ms";
|
|
15969
|
+
options.onReverbPreDelayChange?.(20);
|
|
15970
|
+
let mainVocalId = null;
|
|
15971
|
+
let mainVocalScore = -1;
|
|
15972
|
+
for (const t of trackStates) {
|
|
15973
|
+
if (!t.lyricModel) continue;
|
|
15974
|
+
const score = t.core.getNotes().reduce((sum, n) => sum + n.durationSteps, 0);
|
|
15975
|
+
if (score > mainVocalScore) {
|
|
15976
|
+
mainVocalScore = score;
|
|
15977
|
+
mainVocalId = t.config.id;
|
|
15978
|
+
}
|
|
15979
|
+
}
|
|
15486
15980
|
for (const t of trackStates) {
|
|
15487
|
-
t.
|
|
15981
|
+
const isMainVocal = !!t.lyricModel && t.config.id === mainVocalId;
|
|
15982
|
+
const comp = !t.lyricModel ? 35 : isMainVocal ? 30 : 25;
|
|
15983
|
+
t.trackCompression = comp;
|
|
15488
15984
|
t.trackWidth = 115;
|
|
15489
|
-
options.onTrackCompressionChange?.(t.config.id,
|
|
15985
|
+
options.onTrackCompressionChange?.(t.config.id, comp);
|
|
15490
15986
|
options.onTrackWidthChange?.(t.config.id, 115);
|
|
15491
15987
|
if (t.lyricModel) {
|
|
15492
15988
|
t.vocalVibrato = true;
|
|
15493
|
-
t.vocalReverb =
|
|
15989
|
+
t.vocalReverb = isMainVocal ? 15 : 30;
|
|
15494
15990
|
fireLyricsChange(t);
|
|
15495
15991
|
}
|
|
15496
15992
|
}
|
|
@@ -16372,7 +16868,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
16372
16868
|
currentPlayStep = step;
|
|
16373
16869
|
playbackState = "paused";
|
|
16374
16870
|
const canvas = getGridCanvas();
|
|
16375
|
-
currentOffsetX =
|
|
16871
|
+
currentOffsetX = clamp4(
|
|
16376
16872
|
step * renderConfig.stepWidth - canvas.width * 0.5,
|
|
16377
16873
|
0,
|
|
16378
16874
|
getMaxOffsetX()
|
|
@@ -16418,11 +16914,11 @@ var mountDAW = (target, options = {}) => {
|
|
|
16418
16914
|
getViewState,
|
|
16419
16915
|
setViewState: (state) => {
|
|
16420
16916
|
if (typeof state.zoomX === "number") {
|
|
16421
|
-
zoomX =
|
|
16917
|
+
zoomX = clamp4(state.zoomX, 25, 200);
|
|
16422
16918
|
applyZoomX();
|
|
16423
16919
|
}
|
|
16424
16920
|
if (typeof state.zoomY === "number") {
|
|
16425
|
-
zoomY =
|
|
16921
|
+
zoomY = clamp4(state.zoomY, 50, 200);
|
|
16426
16922
|
applyZoomY();
|
|
16427
16923
|
}
|
|
16428
16924
|
if (typeof state.decomposeChord === "boolean") {
|
|
@@ -16444,28 +16940,52 @@ var mountDAW = (target, options = {}) => {
|
|
|
16444
16940
|
forcePauseAt,
|
|
16445
16941
|
setLoading,
|
|
16446
16942
|
setMasterVolume: (volume) => {
|
|
16447
|
-
masterVolume =
|
|
16943
|
+
masterVolume = clamp4(volume, 0, 100);
|
|
16448
16944
|
refs.masterVolume.value = String(masterVolume);
|
|
16449
16945
|
refs.masterVolumeLabel.textContent = `${masterVolume}%`;
|
|
16450
16946
|
options.singingVoices?.setVolume(masterVolume / 100);
|
|
16451
16947
|
},
|
|
16452
16948
|
setVolume: (volume) => {
|
|
16453
|
-
masterVolume =
|
|
16949
|
+
masterVolume = clamp4(volume, 0, 100);
|
|
16454
16950
|
refs.masterVolume.value = String(masterVolume);
|
|
16455
16951
|
refs.masterVolumeLabel.textContent = `${masterVolume}%`;
|
|
16456
16952
|
options.singingVoices?.setVolume(masterVolume / 100);
|
|
16457
16953
|
},
|
|
16458
16954
|
setDrumVolume: (volume) => {
|
|
16459
|
-
drumVolume =
|
|
16955
|
+
drumVolume = clamp4(volume, 0, 100);
|
|
16460
16956
|
refs.drumVolume.value = String(drumVolume);
|
|
16461
16957
|
refs.drumVolumeLabel.textContent = `${drumVolume}%`;
|
|
16462
16958
|
},
|
|
16463
16959
|
setReverbAmount: (amount) => {
|
|
16464
|
-
reverbAmount =
|
|
16960
|
+
reverbAmount = clamp4(amount, 0, 100);
|
|
16465
16961
|
refs.reverbAmount.value = String(reverbAmount);
|
|
16466
16962
|
refs.reverbAmountLabel.textContent = `${reverbAmount}%`;
|
|
16467
16963
|
options.onReverbChange?.(reverbAmount);
|
|
16468
16964
|
},
|
|
16965
|
+
setReverbDecay: (seconds) => {
|
|
16966
|
+
reverbDecay = Math.max(
|
|
16967
|
+
MIN_REVERB_DECAY_SEC,
|
|
16968
|
+
Math.min(MAX_REVERB_DECAY_SEC, seconds)
|
|
16969
|
+
);
|
|
16970
|
+
refs.reverbDecay.value = String(Math.round(reverbDecay * 10));
|
|
16971
|
+
refs.reverbDecayLabel.textContent = `${reverbDecay.toFixed(1)}s`;
|
|
16972
|
+
options.onReverbDecayChange?.(reverbDecay);
|
|
16973
|
+
},
|
|
16974
|
+
setReverbPreDelay: (ms) => {
|
|
16975
|
+
reverbPreDelay = Math.max(
|
|
16976
|
+
MIN_REVERB_PREDELAY_MS,
|
|
16977
|
+
Math.min(MAX_REVERB_PREDELAY_MS, ms)
|
|
16978
|
+
);
|
|
16979
|
+
refs.reverbPreDelay.value = String(reverbPreDelay);
|
|
16980
|
+
refs.reverbPreDelayLabel.textContent = `${reverbPreDelay}ms`;
|
|
16981
|
+
options.onReverbPreDelayChange?.(reverbPreDelay);
|
|
16982
|
+
},
|
|
16983
|
+
setDelayAmount: (amount) => {
|
|
16984
|
+
delayAmount = clamp4(amount, 0, 100);
|
|
16985
|
+
refs.delayAmount.value = String(delayAmount);
|
|
16986
|
+
refs.delayAmountLabel.textContent = `${delayAmount}%`;
|
|
16987
|
+
options.onDelayChange?.(delayAmount);
|
|
16988
|
+
},
|
|
16469
16989
|
applyPatch: (trackId, added, removed) => {
|
|
16470
16990
|
const track = trackStates.find((t) => t.config.id === trackId);
|
|
16471
16991
|
if (!track) return;
|
|
@@ -16507,6 +17027,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
16507
17027
|
t.vocalOctave = data.vocalOctave;
|
|
16508
17028
|
t.vocalVibrato = data.vocalVibrato ?? false;
|
|
16509
17029
|
t.vocalReverb = data.vocalReverb ?? 0;
|
|
17030
|
+
t.vocalDelay = data.vocalDelay ?? 0;
|
|
16510
17031
|
t.vocalGender = data.vocalGender ?? 50;
|
|
16511
17032
|
t.vocalBreathiness = data.vocalBreathiness ?? 50;
|
|
16512
17033
|
},
|
|
@@ -16627,6 +17148,7 @@ var playSingingMML = async (mml, options = {}) => {
|
|
|
16627
17148
|
pan: panToStereo(lt.pan ?? DEFAULT_PAN),
|
|
16628
17149
|
vibrato: lt.vibrato,
|
|
16629
17150
|
reverbSend: (lt.reverb ?? 0) / 100,
|
|
17151
|
+
delaySend: (lt.delay ?? 0) / 100,
|
|
16630
17152
|
gender: (lt.gender ?? 50) / 100,
|
|
16631
17153
|
breathiness: (lt.breathiness ?? 50) / 100,
|
|
16632
17154
|
notes
|
|
@@ -17237,9 +17759,9 @@ var parseArrayBuffer = midiJsonParser.parseArrayBuffer;
|
|
|
17237
17759
|
URL.revokeObjectURL(url);
|
|
17238
17760
|
|
|
17239
17761
|
// src/channel-strip.ts
|
|
17240
|
-
var
|
|
17762
|
+
var clamp5 = (v, lo, hi) => Math.max(lo, Math.min(hi, v));
|
|
17241
17763
|
var compressionParams = (amount) => {
|
|
17242
|
-
const t =
|
|
17764
|
+
const t = clamp5(amount, 0, 100) / 100;
|
|
17243
17765
|
return {
|
|
17244
17766
|
threshold: 0 + (-24 - 0) * t,
|
|
17245
17767
|
ratio: 1 + (12 - 1) * t,
|
|
@@ -17248,8 +17770,29 @@ var compressionParams = (amount) => {
|
|
|
17248
17770
|
release: 0.25 + (0.15 - 0.25) * t
|
|
17249
17771
|
};
|
|
17250
17772
|
};
|
|
17773
|
+
var EQ_LOW_FREQ = 200;
|
|
17774
|
+
var EQ_MID_FREQ = 1e3;
|
|
17775
|
+
var EQ_HIGH_FREQ = 5e3;
|
|
17776
|
+
var EQ_MID_Q = 1;
|
|
17777
|
+
var EQ_MAX_DB = 12;
|
|
17251
17778
|
var createChannelStrip = (ctx, destination, options = {}) => {
|
|
17252
17779
|
const input = ctx.createGain();
|
|
17780
|
+
const eqLow = ctx.createBiquadFilter();
|
|
17781
|
+
eqLow.type = "lowshelf";
|
|
17782
|
+
eqLow.frequency.value = EQ_LOW_FREQ;
|
|
17783
|
+
eqLow.gain.value = clamp5(options.eqLow ?? 0, -EQ_MAX_DB, EQ_MAX_DB);
|
|
17784
|
+
const eqMid = ctx.createBiquadFilter();
|
|
17785
|
+
eqMid.type = "peaking";
|
|
17786
|
+
eqMid.frequency.value = EQ_MID_FREQ;
|
|
17787
|
+
eqMid.Q.value = EQ_MID_Q;
|
|
17788
|
+
eqMid.gain.value = clamp5(options.eqMid ?? 0, -EQ_MAX_DB, EQ_MAX_DB);
|
|
17789
|
+
const eqHigh = ctx.createBiquadFilter();
|
|
17790
|
+
eqHigh.type = "highshelf";
|
|
17791
|
+
eqHigh.frequency.value = EQ_HIGH_FREQ;
|
|
17792
|
+
eqHigh.gain.value = clamp5(options.eqHigh ?? 0, -EQ_MAX_DB, EQ_MAX_DB);
|
|
17793
|
+
input.connect(eqLow);
|
|
17794
|
+
eqLow.connect(eqMid);
|
|
17795
|
+
eqMid.connect(eqHigh);
|
|
17253
17796
|
const compressor = ctx.createDynamicsCompressor();
|
|
17254
17797
|
const applyCompression = (amount) => {
|
|
17255
17798
|
const p = compressionParams(amount);
|
|
@@ -17292,21 +17835,45 @@ var createChannelStrip = (ctx, destination, options = {}) => {
|
|
|
17292
17835
|
outR.connect(merger, 0, 1);
|
|
17293
17836
|
const setWidth = (width) => {
|
|
17294
17837
|
widthGain.gain.setTargetAtTime(
|
|
17295
|
-
|
|
17838
|
+
clamp5(width, 0, 200) / 100,
|
|
17296
17839
|
ctx.currentTime,
|
|
17297
17840
|
0.02
|
|
17298
17841
|
);
|
|
17299
17842
|
};
|
|
17300
17843
|
setWidth(options.width ?? 100);
|
|
17301
|
-
|
|
17844
|
+
eqHigh.connect(compressor);
|
|
17302
17845
|
compressor.connect(splitter);
|
|
17303
17846
|
merger.connect(destination);
|
|
17304
17847
|
return {
|
|
17305
17848
|
input,
|
|
17849
|
+
setEqLow: (db) => {
|
|
17850
|
+
eqLow.gain.setTargetAtTime(
|
|
17851
|
+
clamp5(db, -EQ_MAX_DB, EQ_MAX_DB),
|
|
17852
|
+
ctx.currentTime,
|
|
17853
|
+
0.02
|
|
17854
|
+
);
|
|
17855
|
+
},
|
|
17856
|
+
setEqMid: (db) => {
|
|
17857
|
+
eqMid.gain.setTargetAtTime(
|
|
17858
|
+
clamp5(db, -EQ_MAX_DB, EQ_MAX_DB),
|
|
17859
|
+
ctx.currentTime,
|
|
17860
|
+
0.02
|
|
17861
|
+
);
|
|
17862
|
+
},
|
|
17863
|
+
setEqHigh: (db) => {
|
|
17864
|
+
eqHigh.gain.setTargetAtTime(
|
|
17865
|
+
clamp5(db, -EQ_MAX_DB, EQ_MAX_DB),
|
|
17866
|
+
ctx.currentTime,
|
|
17867
|
+
0.02
|
|
17868
|
+
);
|
|
17869
|
+
},
|
|
17306
17870
|
setCompression: applyCompression,
|
|
17307
17871
|
setWidth,
|
|
17308
17872
|
dispose: () => {
|
|
17309
17873
|
input.disconnect();
|
|
17874
|
+
eqLow.disconnect();
|
|
17875
|
+
eqMid.disconnect();
|
|
17876
|
+
eqHigh.disconnect();
|
|
17310
17877
|
compressor.disconnect();
|
|
17311
17878
|
splitter.disconnect();
|
|
17312
17879
|
mid.disconnect();
|
|
@@ -17377,25 +17944,6 @@ var createClipMeter = (ctx, source, options = {}) => {
|
|
|
17377
17944
|
};
|
|
17378
17945
|
};
|
|
17379
17946
|
|
|
17380
|
-
// src/reverb.ts
|
|
17381
|
-
var IMPULSE_DURATION_SEC = 2.2;
|
|
17382
|
-
var IMPULSE_DECAY = 2.5;
|
|
17383
|
-
var createReverbImpulse = (ctx) => {
|
|
17384
|
-
const rate = ctx.sampleRate;
|
|
17385
|
-
const length = Math.max(1, Math.floor(rate * IMPULSE_DURATION_SEC));
|
|
17386
|
-
const impulse = ctx.createBuffer(2, length, rate);
|
|
17387
|
-
for (let ch = 0; ch < impulse.numberOfChannels; ch++) {
|
|
17388
|
-
const data = impulse.getChannelData(ch);
|
|
17389
|
-
for (let i2 = 0; i2 < length; i2++) {
|
|
17390
|
-
const envelope = (1 - i2 / length) ** IMPULSE_DECAY;
|
|
17391
|
-
data[i2] = (Math.random() * 2 - 1) * envelope;
|
|
17392
|
-
}
|
|
17393
|
-
}
|
|
17394
|
-
return impulse;
|
|
17395
|
-
};
|
|
17396
|
-
var REVERB_MAX_WET = 0.6;
|
|
17397
|
-
var reverbAmountToGain = (amount) => Math.max(0, Math.min(100, amount)) / 100 * REVERB_MAX_WET;
|
|
17398
|
-
|
|
17399
17947
|
// src/sf/SoundFont_drum.ts
|
|
17400
17948
|
var touch = (map, key, ctor) => {
|
|
17401
17949
|
if (!map.has(key)) map.set(key, new ctor());
|
|
@@ -17551,12 +18099,16 @@ var createDtmStudio = async (options = {}) => {
|
|
|
17551
18099
|
const drumGain = audioCtx.createGain();
|
|
17552
18100
|
drumGain.gain.value = options.drumVolume ?? 1;
|
|
17553
18101
|
drumGain.connect(masterGain);
|
|
18102
|
+
let reverbDecaySec = options.reverbDecay ?? DEFAULT_REVERB_DECAY_SEC;
|
|
18103
|
+
const reverbPreDelay = audioCtx.createDelay(MAX_REVERB_PREDELAY_MS / 1e3);
|
|
18104
|
+
reverbPreDelay.delayTime.value = (options.reverbPreDelay ?? DEFAULT_REVERB_PREDELAY_MS) / 1e3;
|
|
17554
18105
|
const reverbConvolver = audioCtx.createConvolver();
|
|
17555
|
-
reverbConvolver.buffer = createReverbImpulse(audioCtx);
|
|
18106
|
+
reverbConvolver.buffer = createReverbImpulse(audioCtx, reverbDecaySec);
|
|
17556
18107
|
reverbConvolver.normalize = true;
|
|
17557
18108
|
const reverbWetGain = audioCtx.createGain();
|
|
17558
18109
|
reverbWetGain.gain.value = reverbAmountToGain(options.reverbAmount ?? 0);
|
|
17559
|
-
masterGain.connect(
|
|
18110
|
+
masterGain.connect(reverbPreDelay);
|
|
18111
|
+
reverbPreDelay.connect(reverbConvolver);
|
|
17560
18112
|
reverbConvolver.connect(reverbWetGain);
|
|
17561
18113
|
const setReverbAmount = (amount) => {
|
|
17562
18114
|
reverbWetGain.gain.setTargetAtTime(
|
|
@@ -17565,9 +18117,28 @@ var createDtmStudio = async (options = {}) => {
|
|
|
17565
18117
|
0.02
|
|
17566
18118
|
);
|
|
17567
18119
|
};
|
|
18120
|
+
const setReverbDecay = (seconds) => {
|
|
18121
|
+
reverbDecaySec = Math.max(
|
|
18122
|
+
MIN_REVERB_DECAY_SEC,
|
|
18123
|
+
Math.min(MAX_REVERB_DECAY_SEC, seconds)
|
|
18124
|
+
);
|
|
18125
|
+
reverbConvolver.buffer = createReverbImpulse(audioCtx, reverbDecaySec);
|
|
18126
|
+
};
|
|
18127
|
+
const setReverbPreDelay = (ms) => {
|
|
18128
|
+
reverbPreDelay.delayTime.setTargetAtTime(
|
|
18129
|
+
Math.max(MIN_REVERB_PREDELAY_MS, Math.min(MAX_REVERB_PREDELAY_MS, ms)) / 1e3,
|
|
18130
|
+
audioCtx.currentTime,
|
|
18131
|
+
0.02
|
|
18132
|
+
);
|
|
18133
|
+
};
|
|
17568
18134
|
const finalMix = audioCtx.createGain();
|
|
17569
18135
|
masterGain.connect(finalMix);
|
|
17570
18136
|
reverbWetGain.connect(finalMix);
|
|
18137
|
+
const delayBus = createDelayBus(audioCtx, finalMix, {
|
|
18138
|
+
amount: options.delayAmount ?? 0,
|
|
18139
|
+
division: options.delayDivision ?? "8"
|
|
18140
|
+
});
|
|
18141
|
+
const setDelayAmount = (amount) => delayBus.setAmount(amount);
|
|
17571
18142
|
const safetyLimiter = audioCtx.createDynamicsCompressor();
|
|
17572
18143
|
safetyLimiter.threshold.value = -1;
|
|
17573
18144
|
safetyLimiter.knee.value = 0;
|
|
@@ -17620,6 +18191,8 @@ var createDtmStudio = async (options = {}) => {
|
|
|
17620
18191
|
// ボーカルトラック個別のリバーブセンド(`r`トークン)先。マスタリバーブの
|
|
17621
18192
|
// Convolver 入力へ直接センドする(masterGain 経由のドライ段は素通り)。
|
|
17622
18193
|
reverbBus: reverbConvolver,
|
|
18194
|
+
// ボーカルトラック個別のディレイセンド(`e`トークン)先。
|
|
18195
|
+
delayBus: delayBus.input,
|
|
17623
18196
|
// トラック単位チャンネルストリップ(コンプレッサー/ステレオワイド)の入口。
|
|
17624
18197
|
// 楽器と同じ getChannelStrip キャッシュを共有するので、演奏トラックと歌詞トラックが
|
|
17625
18198
|
// 同じ trackId を指していれば同じ処理が掛かる。
|
|
@@ -17900,8 +18473,20 @@ var createDtmStudio = async (options = {}) => {
|
|
|
17900
18473
|
},
|
|
17901
18474
|
reverbAmount: options.reverbAmount,
|
|
17902
18475
|
onReverbChange: setReverbAmount,
|
|
18476
|
+
reverbDecay: options.reverbDecay,
|
|
18477
|
+
onReverbDecayChange: setReverbDecay,
|
|
18478
|
+
reverbPreDelay: options.reverbPreDelay,
|
|
18479
|
+
onReverbPreDelayChange: setReverbPreDelay,
|
|
18480
|
+
delayAmount: options.delayAmount,
|
|
18481
|
+
onDelayChange: setDelayAmount,
|
|
18482
|
+
delayDivision: options.delayDivision,
|
|
18483
|
+
onDelayDivisionChange: (division) => delayBus.setDivision(division),
|
|
18484
|
+
onBpmChange: (bpm) => delayBus.setBpm(bpm),
|
|
17903
18485
|
onTrackCompressionChange: (trackId, amount) => getChannelStrip(trackId).setCompression(amount),
|
|
17904
18486
|
onTrackWidthChange: (trackId, width) => getChannelStrip(trackId).setWidth(width),
|
|
18487
|
+
onTrackEqLowChange: (trackId, db) => getChannelStrip(trackId).setEqLow(db),
|
|
18488
|
+
onTrackEqMidChange: (trackId, db) => getChannelStrip(trackId).setEqMid(db),
|
|
18489
|
+
onTrackEqHighChange: (trackId, db) => getChannelStrip(trackId).setEqHigh(db),
|
|
17905
18490
|
clipMeter,
|
|
17906
18491
|
...dawOverrides,
|
|
17907
18492
|
// dawOverrides で上書きされないよう、スプレッドの後に配置して合成する
|
|
@@ -18438,6 +19023,7 @@ var createDtmStudio = async (options = {}) => {
|
|
|
18438
19023
|
mountedChordPlayers.length = 0;
|
|
18439
19024
|
mountedEditors.length = 0;
|
|
18440
19025
|
clipMeter.dispose();
|
|
19026
|
+
delayBus.dispose();
|
|
18441
19027
|
for (const strip of channelStrips.values()) strip.dispose();
|
|
18442
19028
|
channelStrips.clear();
|
|
18443
19029
|
void audioCtx.close();
|
|
@@ -18479,6 +19065,9 @@ var createDtmStudio = async (options = {}) => {
|
|
|
18479
19065
|
setMasterVolume,
|
|
18480
19066
|
setVolume: setMasterVolume,
|
|
18481
19067
|
setReverbAmount,
|
|
19068
|
+
setReverbDecay,
|
|
19069
|
+
setReverbPreDelay,
|
|
19070
|
+
setDelayAmount,
|
|
18482
19071
|
dispose
|
|
18483
19072
|
};
|
|
18484
19073
|
};
|