@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.mjs
CHANGED
|
@@ -2186,10 +2186,11 @@ var parseLyrics = (mml) => {
|
|
|
2186
2186
|
let octave = 0;
|
|
2187
2187
|
let vibrato = false;
|
|
2188
2188
|
let reverb = 0;
|
|
2189
|
+
let delay = 0;
|
|
2189
2190
|
let gender = 50;
|
|
2190
2191
|
let breathiness = 50;
|
|
2191
2192
|
const modelMatch = rest.match(
|
|
2192
|
-
/^([a-z_][a-z0-9_]*?)(?=(?:[
|
|
2193
|
+
/^([a-z_][a-z0-9_]*?)(?=(?:[vqpobrghe]-?\d)|[^a-z0-9_]|$)(?::(\d+))?/i
|
|
2193
2194
|
);
|
|
2194
2195
|
let model = "";
|
|
2195
2196
|
const metaTokens = [];
|
|
@@ -2258,6 +2259,13 @@ var parseLyrics = (mml) => {
|
|
|
2258
2259
|
rest = rest.substring(hMatch[0].length).trim();
|
|
2259
2260
|
continue;
|
|
2260
2261
|
}
|
|
2262
|
+
const eMatch = rest.match(/^e(\d+)/i);
|
|
2263
|
+
if (eMatch) {
|
|
2264
|
+
delay = clamp(Number.parseInt(eMatch[1], 10), 0, 100);
|
|
2265
|
+
metaTokens.push(eMatch[0]);
|
|
2266
|
+
rest = rest.substring(eMatch[0].length).trim();
|
|
2267
|
+
continue;
|
|
2268
|
+
}
|
|
2261
2269
|
break;
|
|
2262
2270
|
}
|
|
2263
2271
|
const lyricLines = [rest];
|
|
@@ -2274,6 +2282,7 @@ var parseLyrics = (mml) => {
|
|
|
2274
2282
|
octave,
|
|
2275
2283
|
vibrato,
|
|
2276
2284
|
reverb,
|
|
2285
|
+
delay,
|
|
2277
2286
|
gender,
|
|
2278
2287
|
breathiness,
|
|
2279
2288
|
syllables,
|
|
@@ -2361,7 +2370,7 @@ var FORMANTS = {
|
|
|
2361
2370
|
N: [250, 1e3]
|
|
2362
2371
|
};
|
|
2363
2372
|
var midiToFreq = (m) => 440 * 2 ** ((m - 69) / 12);
|
|
2364
|
-
var createKlattVoice = (ctx, destination, reverbBus) => {
|
|
2373
|
+
var createKlattVoice = (ctx, destination, reverbBus, delayBus) => {
|
|
2365
2374
|
const active = /* @__PURE__ */ new Set();
|
|
2366
2375
|
const voice = (syllable, e) => {
|
|
2367
2376
|
const t0 = ctx.currentTime + e.when;
|
|
@@ -2380,11 +2389,17 @@ var createKlattVoice = (ctx, destination, reverbBus) => {
|
|
|
2380
2389
|
panner.connect(dest);
|
|
2381
2390
|
out = panner;
|
|
2382
2391
|
}
|
|
2383
|
-
let
|
|
2392
|
+
let reverbSendGain = null;
|
|
2384
2393
|
if (reverbBus && e.reverbSend && e.reverbSend > 0 && panner) {
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
panner.connect(
|
|
2394
|
+
reverbSendGain = ctx.createGain();
|
|
2395
|
+
reverbSendGain.gain.value = Math.max(0, Math.min(1, e.reverbSend));
|
|
2396
|
+
panner.connect(reverbSendGain).connect(reverbBus);
|
|
2397
|
+
}
|
|
2398
|
+
let delaySendGain = null;
|
|
2399
|
+
if (delayBus && e.delaySend && e.delaySend > 0 && panner) {
|
|
2400
|
+
delaySendGain = ctx.createGain();
|
|
2401
|
+
delaySendGain.gain.value = Math.max(0, Math.min(1, e.delaySend));
|
|
2402
|
+
panner.connect(delaySendGain).connect(delayBus);
|
|
2388
2403
|
}
|
|
2389
2404
|
const osc = ctx.createOscillator();
|
|
2390
2405
|
osc.type = "sawtooth";
|
|
@@ -2441,7 +2456,8 @@ var createKlattVoice = (ctx, destination, reverbBus) => {
|
|
|
2441
2456
|
active.delete(osc);
|
|
2442
2457
|
osc.disconnect();
|
|
2443
2458
|
panner?.disconnect();
|
|
2444
|
-
|
|
2459
|
+
reverbSendGain?.disconnect();
|
|
2460
|
+
delaySendGain?.disconnect();
|
|
2445
2461
|
};
|
|
2446
2462
|
};
|
|
2447
2463
|
voice.stopAll = () => {
|
|
@@ -2757,7 +2773,7 @@ var createKoeVoice = async (ctx, destination, options) => {
|
|
|
2757
2773
|
return p;
|
|
2758
2774
|
};
|
|
2759
2775
|
const LEADCAP_S = 0.09;
|
|
2760
|
-
const schedule = (r, t0, peak, pan, reverbSend = 0, destOverride) => {
|
|
2776
|
+
const schedule = (r, t0, peak, pan, reverbSend = 0, delaySend = 0, destOverride) => {
|
|
2761
2777
|
const dest = destOverride ?? destination;
|
|
2762
2778
|
let out = dest;
|
|
2763
2779
|
let panner = null;
|
|
@@ -2767,11 +2783,17 @@ var createKoeVoice = async (ctx, destination, options) => {
|
|
|
2767
2783
|
panner.connect(dest);
|
|
2768
2784
|
out = panner;
|
|
2769
2785
|
}
|
|
2770
|
-
let
|
|
2786
|
+
let reverbSendGain = null;
|
|
2771
2787
|
if (options.reverbBus && reverbSend > 0 && panner) {
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
panner.connect(
|
|
2788
|
+
reverbSendGain = ctx.createGain();
|
|
2789
|
+
reverbSendGain.gain.value = Math.max(0, Math.min(1, reverbSend));
|
|
2790
|
+
panner.connect(reverbSendGain).connect(options.reverbBus);
|
|
2791
|
+
}
|
|
2792
|
+
let delaySendGain = null;
|
|
2793
|
+
if (options.delayBus && delaySend > 0 && panner) {
|
|
2794
|
+
delaySendGain = ctx.createGain();
|
|
2795
|
+
delaySendGain.gain.value = Math.max(0, Math.min(1, delaySend));
|
|
2796
|
+
panner.connect(delaySendGain).connect(options.delayBus);
|
|
2775
2797
|
}
|
|
2776
2798
|
const src = ctx.createBufferSource();
|
|
2777
2799
|
src.buffer = r.audio;
|
|
@@ -2798,7 +2820,8 @@ var createKoeVoice = async (ctx, destination, options) => {
|
|
|
2798
2820
|
src.disconnect();
|
|
2799
2821
|
env.disconnect();
|
|
2800
2822
|
panner?.disconnect();
|
|
2801
|
-
|
|
2823
|
+
reverbSendGain?.disconnect();
|
|
2824
|
+
delaySendGain?.disconnect();
|
|
2802
2825
|
};
|
|
2803
2826
|
};
|
|
2804
2827
|
const model = (syllable, e) => {
|
|
@@ -2817,7 +2840,8 @@ var createKoeVoice = async (ctx, destination, options) => {
|
|
|
2817
2840
|
const pan = e.pan ?? 0;
|
|
2818
2841
|
const durationMs = Math.max(60, e.duration * 1e3);
|
|
2819
2842
|
void renderInto(alias, e.pitch, durationMs).then((r) => {
|
|
2820
|
-
if (r)
|
|
2843
|
+
if (r)
|
|
2844
|
+
schedule(r, t0, peak, pan, e.reverbSend, e.delaySend, e.destination);
|
|
2821
2845
|
});
|
|
2822
2846
|
};
|
|
2823
2847
|
model.renderToCache = async (syllable, prevVowelArg, pitch, durationMs, vibrato, expr) => {
|
|
@@ -2835,9 +2859,9 @@ var createKoeVoice = async (ctx, destination, options) => {
|
|
|
2835
2859
|
const r = await renderInto(alias, pitch, dMs, vib, expr);
|
|
2836
2860
|
return r ? keyOf(alias, pitch, dMs, vib, expr) : null;
|
|
2837
2861
|
};
|
|
2838
|
-
model.scheduleCached = (key, t0, peak, pan, reverbSend, dest) => {
|
|
2862
|
+
model.scheduleCached = (key, t0, peak, pan, reverbSend, delaySend, dest) => {
|
|
2839
2863
|
const r = renderCache.get(key);
|
|
2840
|
-
if (r) schedule(r, t0, peak, pan, reverbSend, dest);
|
|
2864
|
+
if (r) schedule(r, t0, peak, pan, reverbSend, delaySend, dest);
|
|
2841
2865
|
};
|
|
2842
2866
|
model.stopAll = () => {
|
|
2843
2867
|
for (const src of active) {
|
|
@@ -2867,8 +2891,12 @@ var createSingingVoices = (ctx, destination, options = {}) => {
|
|
|
2867
2891
|
let streamSession = 0;
|
|
2868
2892
|
const masterGain = ctx.createGain();
|
|
2869
2893
|
masterGain.connect(destination);
|
|
2894
|
+
let masterVolumeScalar = 1;
|
|
2870
2895
|
const loaded = /* @__PURE__ */ new Map([
|
|
2871
|
-
[
|
|
2896
|
+
[
|
|
2897
|
+
FALLBACK_MODEL,
|
|
2898
|
+
createKlattVoice(ctx, masterGain, options.reverbBus, options.delayBus)
|
|
2899
|
+
]
|
|
2872
2900
|
]);
|
|
2873
2901
|
const loading = /* @__PURE__ */ new Map();
|
|
2874
2902
|
const load2 = (model) => {
|
|
@@ -2889,7 +2917,8 @@ var createSingingVoices = (ctx, destination, options = {}) => {
|
|
|
2889
2917
|
worldlineScriptUrl: options.worldlineScriptUrl,
|
|
2890
2918
|
lightweight: options.lightweight,
|
|
2891
2919
|
voiceWorkerUrl: options.voiceWorkerUrl,
|
|
2892
|
-
reverbBus: options.reverbBus
|
|
2920
|
+
reverbBus: options.reverbBus,
|
|
2921
|
+
delayBus: options.delayBus
|
|
2893
2922
|
})
|
|
2894
2923
|
))().then((v) => {
|
|
2895
2924
|
loaded.set(m, v);
|
|
@@ -3008,13 +3037,16 @@ var createSingingVoices = (ctx, destination, options = {}) => {
|
|
|
3008
3037
|
if (key) {
|
|
3009
3038
|
const delay = ctx.currentTime - t0;
|
|
3010
3039
|
if (delay < 0.05) {
|
|
3040
|
+
const dest = options.getTrackDestination?.(track.id ?? "");
|
|
3041
|
+
const effPeak = dest ? peak * masterVolumeScalar : peak;
|
|
3011
3042
|
scheduleCached(
|
|
3012
3043
|
key,
|
|
3013
3044
|
t0,
|
|
3014
|
-
|
|
3045
|
+
effPeak,
|
|
3015
3046
|
track.pan,
|
|
3016
3047
|
track.reverbSend,
|
|
3017
|
-
|
|
3048
|
+
track.delaySend,
|
|
3049
|
+
dest
|
|
3018
3050
|
);
|
|
3019
3051
|
opts?.onScheduled?.(track, note, t0);
|
|
3020
3052
|
} else {
|
|
@@ -3027,16 +3059,19 @@ var createSingingVoices = (ctx, destination, options = {}) => {
|
|
|
3027
3059
|
})();
|
|
3028
3060
|
} else {
|
|
3029
3061
|
const when = t0 - ctx.currentTime;
|
|
3062
|
+
const dest = options.getTrackDestination?.(track.id ?? "");
|
|
3063
|
+
const effPeak = dest ? peak * masterVolumeScalar : peak;
|
|
3030
3064
|
model(note.syllable, {
|
|
3031
3065
|
trackId: track.id ?? "",
|
|
3032
3066
|
pitch: note.pitch,
|
|
3033
3067
|
velocity: 100,
|
|
3034
|
-
volume:
|
|
3068
|
+
volume: effPeak,
|
|
3035
3069
|
when,
|
|
3036
3070
|
duration: note.durationSec,
|
|
3037
3071
|
pan: track.pan,
|
|
3038
3072
|
reverbSend: track.reverbSend,
|
|
3039
|
-
|
|
3073
|
+
delaySend: track.delaySend,
|
|
3074
|
+
destination: dest
|
|
3040
3075
|
});
|
|
3041
3076
|
opts?.onScheduled?.(track, note, t0);
|
|
3042
3077
|
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
@@ -3061,7 +3096,9 @@ var createSingingVoices = (ctx, destination, options = {}) => {
|
|
|
3061
3096
|
for (const v of loaded.values()) v.reset?.();
|
|
3062
3097
|
};
|
|
3063
3098
|
const setVolume = (gain) => {
|
|
3064
|
-
|
|
3099
|
+
const g = Math.max(0, gain);
|
|
3100
|
+
masterGain.gain.value = g;
|
|
3101
|
+
masterVolumeScalar = g;
|
|
3065
3102
|
};
|
|
3066
3103
|
return {
|
|
3067
3104
|
loadModels,
|
|
@@ -3095,10 +3132,13 @@ var PITCH_MAP = {
|
|
|
3095
3132
|
b: 11
|
|
3096
3133
|
};
|
|
3097
3134
|
var clamp2 = (value, lo, hi) => Math.min(hi, Math.max(lo, value));
|
|
3098
|
-
var META_DIRECTIVE = /#(inst|drum|drumfont|volume|drumvolume|reverb|mode)=([\w-]+)/gi;
|
|
3135
|
+
var META_DIRECTIVE = /#(inst|drum|drumfont|volume|drumvolume|reverb|reverbdecay|reverbpredelay|delay|delaydiv|mode)=([\w-]+)/gi;
|
|
3099
3136
|
var TRACK_INST_DIRECTIVE = /#t(\d+)inst=([^#;\r\n]+)/gi;
|
|
3100
3137
|
var TRACK_COMP_DIRECTIVE = /#t(\d+)comp=(\d+)/gi;
|
|
3101
3138
|
var TRACK_WIDTH_DIRECTIVE = /#t(\d+)width=(\d+)/gi;
|
|
3139
|
+
var TRACK_EQLOW_DIRECTIVE = /#t(\d+)eqlo=(-?\d+)/gi;
|
|
3140
|
+
var TRACK_EQMID_DIRECTIVE = /#t(\d+)eqmid=(-?\d+)/gi;
|
|
3141
|
+
var TRACK_EQHIGH_DIRECTIVE = /#t(\d+)eqhi=(-?\d+)/gi;
|
|
3102
3142
|
var parseMmlMeta = (mml) => {
|
|
3103
3143
|
const meta = {};
|
|
3104
3144
|
for (const m of mml.matchAll(META_DIRECTIVE)) {
|
|
@@ -3115,6 +3155,17 @@ var parseMmlMeta = (mml) => {
|
|
|
3115
3155
|
} else if (key === "reverb") {
|
|
3116
3156
|
const rv = Number.parseInt(m[2], 10);
|
|
3117
3157
|
if (!Number.isNaN(rv)) meta.reverb = clamp2(rv, 0, 100);
|
|
3158
|
+
} else if (key === "reverbdecay") {
|
|
3159
|
+
const rd = Number.parseInt(m[2], 10);
|
|
3160
|
+
if (!Number.isNaN(rd)) meta.reverbDecay = clamp2(rd, 3, 40);
|
|
3161
|
+
} else if (key === "reverbpredelay") {
|
|
3162
|
+
const rp = Number.parseInt(m[2], 10);
|
|
3163
|
+
if (!Number.isNaN(rp)) meta.reverbPreDelay = clamp2(rp, 0, 150);
|
|
3164
|
+
} else if (key === "delay") {
|
|
3165
|
+
const dv = Number.parseInt(m[2], 10);
|
|
3166
|
+
if (!Number.isNaN(dv)) meta.delay = clamp2(dv, 0, 100);
|
|
3167
|
+
} else if (key === "delaydiv") {
|
|
3168
|
+
if (["4", "8", "8d", "16"].includes(m[2])) meta.delayDivision = m[2];
|
|
3118
3169
|
} else if (key === "mode") {
|
|
3119
3170
|
if (m[2] === "simple" || m[2] === "advanced") {
|
|
3120
3171
|
meta.mode = m[2];
|
|
@@ -3145,9 +3196,33 @@ var parseMmlMeta = (mml) => {
|
|
|
3145
3196
|
meta.trackWidth[idx] = val;
|
|
3146
3197
|
}
|
|
3147
3198
|
}
|
|
3199
|
+
for (const m of mml.matchAll(TRACK_EQLOW_DIRECTIVE)) {
|
|
3200
|
+
const idx = Number.parseInt(m[1], 10);
|
|
3201
|
+
const val = clamp2(Number.parseInt(m[2], 10), -12, 12);
|
|
3202
|
+
if (!Number.isNaN(idx) && !Number.isNaN(val)) {
|
|
3203
|
+
meta.trackEqLow ??= {};
|
|
3204
|
+
meta.trackEqLow[idx] = val;
|
|
3205
|
+
}
|
|
3206
|
+
}
|
|
3207
|
+
for (const m of mml.matchAll(TRACK_EQMID_DIRECTIVE)) {
|
|
3208
|
+
const idx = Number.parseInt(m[1], 10);
|
|
3209
|
+
const val = clamp2(Number.parseInt(m[2], 10), -12, 12);
|
|
3210
|
+
if (!Number.isNaN(idx) && !Number.isNaN(val)) {
|
|
3211
|
+
meta.trackEqMid ??= {};
|
|
3212
|
+
meta.trackEqMid[idx] = val;
|
|
3213
|
+
}
|
|
3214
|
+
}
|
|
3215
|
+
for (const m of mml.matchAll(TRACK_EQHIGH_DIRECTIVE)) {
|
|
3216
|
+
const idx = Number.parseInt(m[1], 10);
|
|
3217
|
+
const val = clamp2(Number.parseInt(m[2], 10), -12, 12);
|
|
3218
|
+
if (!Number.isNaN(idx) && !Number.isNaN(val)) {
|
|
3219
|
+
meta.trackEqHigh ??= {};
|
|
3220
|
+
meta.trackEqHigh[idx] = val;
|
|
3221
|
+
}
|
|
3222
|
+
}
|
|
3148
3223
|
return meta;
|
|
3149
3224
|
};
|
|
3150
|
-
var stripMmlMeta = (mml) => mml.replace(META_DIRECTIVE, "").replace(TRACK_INST_DIRECTIVE, "").replace(TRACK_COMP_DIRECTIVE, "").replace(TRACK_WIDTH_DIRECTIVE, "");
|
|
3225
|
+
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, "");
|
|
3151
3226
|
var formatMmlMeta = (meta, space = "") => {
|
|
3152
3227
|
const parts = [];
|
|
3153
3228
|
if (meta.instrument) parts.push(`#inst=${meta.instrument}`);
|
|
@@ -3158,6 +3233,14 @@ var formatMmlMeta = (meta, space = "") => {
|
|
|
3158
3233
|
parts.push(`#drumvolume=${meta.drumVolume}`);
|
|
3159
3234
|
if (meta.reverb !== void 0 && meta.reverb !== 0)
|
|
3160
3235
|
parts.push(`#reverb=${meta.reverb}`);
|
|
3236
|
+
if (meta.reverbDecay !== void 0 && meta.reverbDecay !== 22)
|
|
3237
|
+
parts.push(`#reverbdecay=${meta.reverbDecay}`);
|
|
3238
|
+
if (meta.reverbPreDelay !== void 0 && meta.reverbPreDelay !== 0)
|
|
3239
|
+
parts.push(`#reverbpredelay=${meta.reverbPreDelay}`);
|
|
3240
|
+
if (meta.delay !== void 0 && meta.delay !== 0)
|
|
3241
|
+
parts.push(`#delay=${meta.delay}`);
|
|
3242
|
+
if (meta.delayDivision && meta.delayDivision !== "8")
|
|
3243
|
+
parts.push(`#delaydiv=${meta.delayDivision}`);
|
|
3161
3244
|
if (meta.mode) parts.push(`#mode=${meta.mode}`);
|
|
3162
3245
|
if (meta.trackInstruments) {
|
|
3163
3246
|
for (const [idx, name] of Object.entries(meta.trackInstruments)) {
|
|
@@ -3174,6 +3257,21 @@ var formatMmlMeta = (meta, space = "") => {
|
|
|
3174
3257
|
if (val !== 100) parts.push(`#t${idx}width=${val}`);
|
|
3175
3258
|
}
|
|
3176
3259
|
}
|
|
3260
|
+
if (meta.trackEqLow) {
|
|
3261
|
+
for (const [idx, val] of Object.entries(meta.trackEqLow)) {
|
|
3262
|
+
if (val !== 0) parts.push(`#t${idx}eqlo=${val}`);
|
|
3263
|
+
}
|
|
3264
|
+
}
|
|
3265
|
+
if (meta.trackEqMid) {
|
|
3266
|
+
for (const [idx, val] of Object.entries(meta.trackEqMid)) {
|
|
3267
|
+
if (val !== 0) parts.push(`#t${idx}eqmid=${val}`);
|
|
3268
|
+
}
|
|
3269
|
+
}
|
|
3270
|
+
if (meta.trackEqHigh) {
|
|
3271
|
+
for (const [idx, val] of Object.entries(meta.trackEqHigh)) {
|
|
3272
|
+
if (val !== 0) parts.push(`#t${idx}eqhi=${val}`);
|
|
3273
|
+
}
|
|
3274
|
+
}
|
|
3177
3275
|
return parts.join(space);
|
|
3178
3276
|
};
|
|
3179
3277
|
var parseMML = (mml, options = {}) => {
|
|
@@ -9009,6 +9107,7 @@ var mountMmlPlayer = (target, mml, options = {}) => {
|
|
|
9009
9107
|
pan: panToStereo(lt.pan ?? DEFAULT_PAN),
|
|
9010
9108
|
vibrato: lt.vibrato,
|
|
9011
9109
|
reverbSend: (lt.reverb ?? 0) / 100,
|
|
9110
|
+
delaySend: (lt.delay ?? 0) / 100,
|
|
9012
9111
|
gender: (lt.gender ?? 50) / 100,
|
|
9013
9112
|
breathiness: (lt.breathiness ?? 50) / 100,
|
|
9014
9113
|
notes
|
|
@@ -10688,6 +10787,71 @@ var mountChordPlayer = (target, chords, options = {}) => {
|
|
|
10688
10787
|
};
|
|
10689
10788
|
};
|
|
10690
10789
|
|
|
10790
|
+
// src/delay.ts
|
|
10791
|
+
var DELAY_DIVISIONS = [
|
|
10792
|
+
{ value: "4", label: "4\u5206", beats: 1 },
|
|
10793
|
+
{ value: "8", label: "8\u5206", beats: 0.5 },
|
|
10794
|
+
{ value: "8d", label: "\u4ED8\u70B98\u5206", beats: 0.75 },
|
|
10795
|
+
{ value: "16", label: "16\u5206", beats: 0.25 }
|
|
10796
|
+
];
|
|
10797
|
+
var clamp3 = (v, lo, hi) => Math.max(lo, Math.min(hi, v));
|
|
10798
|
+
var divisionToSeconds = (division, bpm) => {
|
|
10799
|
+
const beats = DELAY_DIVISIONS.find((d) => d.value === division)?.beats ?? 0.5;
|
|
10800
|
+
const safeBpm = bpm > 0 ? bpm : 120;
|
|
10801
|
+
return 60 / safeBpm * beats;
|
|
10802
|
+
};
|
|
10803
|
+
var DELAY_MAX_WET = 0.45;
|
|
10804
|
+
var delayAmountToGain = (amount) => clamp3(amount, 0, 100) / 100 * DELAY_MAX_WET;
|
|
10805
|
+
var FEEDBACK_GAIN = 0.3;
|
|
10806
|
+
var MAX_DELAY_SEC = 2;
|
|
10807
|
+
var createDelayBus = (ctx, destination, options = {}) => {
|
|
10808
|
+
const input = ctx.createGain();
|
|
10809
|
+
const delayNode = ctx.createDelay(MAX_DELAY_SEC);
|
|
10810
|
+
const feedback = ctx.createGain();
|
|
10811
|
+
feedback.gain.value = FEEDBACK_GAIN;
|
|
10812
|
+
const wetGain = ctx.createGain();
|
|
10813
|
+
wetGain.gain.value = delayAmountToGain(options.amount ?? 0);
|
|
10814
|
+
input.connect(delayNode);
|
|
10815
|
+
delayNode.connect(feedback);
|
|
10816
|
+
feedback.connect(delayNode);
|
|
10817
|
+
delayNode.connect(wetGain);
|
|
10818
|
+
wetGain.connect(destination);
|
|
10819
|
+
let bpm = options.bpm ?? 120;
|
|
10820
|
+
let division = options.division ?? "8";
|
|
10821
|
+
const applyTime = () => {
|
|
10822
|
+
delayNode.delayTime.setTargetAtTime(
|
|
10823
|
+
divisionToSeconds(division, bpm),
|
|
10824
|
+
ctx.currentTime,
|
|
10825
|
+
0.05
|
|
10826
|
+
);
|
|
10827
|
+
};
|
|
10828
|
+
applyTime();
|
|
10829
|
+
return {
|
|
10830
|
+
input,
|
|
10831
|
+
setAmount: (amount) => {
|
|
10832
|
+
wetGain.gain.setTargetAtTime(
|
|
10833
|
+
delayAmountToGain(amount),
|
|
10834
|
+
ctx.currentTime,
|
|
10835
|
+
0.02
|
|
10836
|
+
);
|
|
10837
|
+
},
|
|
10838
|
+
setDivision: (d) => {
|
|
10839
|
+
division = d;
|
|
10840
|
+
applyTime();
|
|
10841
|
+
},
|
|
10842
|
+
setBpm: (b) => {
|
|
10843
|
+
bpm = b;
|
|
10844
|
+
applyTime();
|
|
10845
|
+
},
|
|
10846
|
+
dispose: () => {
|
|
10847
|
+
input.disconnect();
|
|
10848
|
+
delayNode.disconnect();
|
|
10849
|
+
feedback.disconnect();
|
|
10850
|
+
wetGain.disconnect();
|
|
10851
|
+
}
|
|
10852
|
+
};
|
|
10853
|
+
};
|
|
10854
|
+
|
|
10691
10855
|
// src/daw-ui.ts
|
|
10692
10856
|
var q = (root, sel) => root.querySelector(sel);
|
|
10693
10857
|
var buildUI = (target, options) => {
|
|
@@ -10804,6 +10968,25 @@ var buildUI = (target, options) => {
|
|
|
10804
10968
|
<span class="dtm-label" data-dtm="reverb-amount-label">0%</span>
|
|
10805
10969
|
<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
10970
|
</div>
|
|
10971
|
+
<div class="dtm-row">
|
|
10972
|
+
<span class="dtm-label">Decay</span>
|
|
10973
|
+
<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">
|
|
10974
|
+
<span class="dtm-label" data-dtm="reverb-decay-label">2.2s</span>
|
|
10975
|
+
</div>
|
|
10976
|
+
<div class="dtm-row">
|
|
10977
|
+
<span class="dtm-label">Pre Delay</span>
|
|
10978
|
+
<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">
|
|
10979
|
+
<span class="dtm-label" data-dtm="reverb-predelay-label">0ms</span>
|
|
10980
|
+
</div>
|
|
10981
|
+
<div class="dtm-row">
|
|
10982
|
+
<span class="dtm-label">\u30C7\u30A3\u30EC\u30A4</span>
|
|
10983
|
+
<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">
|
|
10984
|
+
<span class="dtm-label" data-dtm="delay-amount-label">0%</span>
|
|
10985
|
+
<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">
|
|
10986
|
+
${DELAY_DIVISIONS.map((d) => `<option value="${d.value}">${d.label}</option>`).join("")}
|
|
10987
|
+
</select>
|
|
10988
|
+
<button class="dtm-infobtn" data-dtm="delay-amount-info" title="\u30DE\u30B9\u30BF\u30C7\u30A3\u30EC\u30A4\u306E\u89E3\u8AAC">${icon("info", 12)}</button>
|
|
10989
|
+
</div>
|
|
10807
10990
|
</div>
|
|
10808
10991
|
</details>
|
|
10809
10992
|
|
|
@@ -11002,6 +11185,14 @@ var buildUI = (target, options) => {
|
|
|
11002
11185
|
reverbAmount: sel("reverb-amount"),
|
|
11003
11186
|
reverbAmountLabel: sel("reverb-amount-label"),
|
|
11004
11187
|
reverbAmountInfoBtn: sel("reverb-amount-info"),
|
|
11188
|
+
reverbDecay: sel("reverb-decay"),
|
|
11189
|
+
reverbDecayLabel: sel("reverb-decay-label"),
|
|
11190
|
+
reverbPreDelay: sel("reverb-predelay"),
|
|
11191
|
+
reverbPreDelayLabel: sel("reverb-predelay-label"),
|
|
11192
|
+
delayAmount: sel("delay-amount"),
|
|
11193
|
+
delayAmountLabel: sel("delay-amount-label"),
|
|
11194
|
+
delayAmountInfoBtn: sel("delay-amount-info"),
|
|
11195
|
+
delayDivision: sel("delay-division"),
|
|
11005
11196
|
autoMasterBtn: sel("auto-master"),
|
|
11006
11197
|
autoMasterInfoBtn: sel("auto-master-info"),
|
|
11007
11198
|
trackTabs: sel("track-tabs"),
|
|
@@ -12635,6 +12826,38 @@ var isChordHeavyTrack = (notes, threshold = 0.6) => {
|
|
|
12635
12826
|
return chordNotes / notes.length >= threshold;
|
|
12636
12827
|
};
|
|
12637
12828
|
|
|
12829
|
+
// src/reverb.ts
|
|
12830
|
+
var DEFAULT_REVERB_DECAY_SEC = 2.2;
|
|
12831
|
+
var MIN_REVERB_DECAY_SEC = 0.3;
|
|
12832
|
+
var MAX_REVERB_DECAY_SEC = 4;
|
|
12833
|
+
var IMPULSE_DECAY_CURVE = 2.5;
|
|
12834
|
+
var DEFAULT_REVERB_PREDELAY_MS = 0;
|
|
12835
|
+
var MIN_REVERB_PREDELAY_MS = 0;
|
|
12836
|
+
var MAX_REVERB_PREDELAY_MS = 150;
|
|
12837
|
+
var createReverbImpulse = (ctx, decaySec = DEFAULT_REVERB_DECAY_SEC) => {
|
|
12838
|
+
const rate = ctx.sampleRate;
|
|
12839
|
+
const length = Math.max(
|
|
12840
|
+
1,
|
|
12841
|
+
Math.floor(
|
|
12842
|
+
rate * Math.max(
|
|
12843
|
+
MIN_REVERB_DECAY_SEC,
|
|
12844
|
+
Math.min(MAX_REVERB_DECAY_SEC, decaySec)
|
|
12845
|
+
)
|
|
12846
|
+
)
|
|
12847
|
+
);
|
|
12848
|
+
const impulse = ctx.createBuffer(2, length, rate);
|
|
12849
|
+
for (let ch = 0; ch < impulse.numberOfChannels; ch++) {
|
|
12850
|
+
const data = impulse.getChannelData(ch);
|
|
12851
|
+
for (let i2 = 0; i2 < length; i2++) {
|
|
12852
|
+
const envelope = (1 - i2 / length) ** IMPULSE_DECAY_CURVE;
|
|
12853
|
+
data[i2] = (Math.random() * 2 - 1) * envelope;
|
|
12854
|
+
}
|
|
12855
|
+
}
|
|
12856
|
+
return impulse;
|
|
12857
|
+
};
|
|
12858
|
+
var REVERB_MAX_WET = 0.6;
|
|
12859
|
+
var reverbAmountToGain = (amount) => Math.max(0, Math.min(100, amount)) / 100 * REVERB_MAX_WET;
|
|
12860
|
+
|
|
12638
12861
|
// src/daw.ts
|
|
12639
12862
|
var CHORD_INFO_HTML2 = `
|
|
12640
12863
|
<div class="dtm-modal-body-content">
|
|
@@ -12706,14 +12929,46 @@ var LYRIC_REVERB_INFO_HTML = `
|
|
|
12706
12929
|
<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
12930
|
</div>
|
|
12708
12931
|
`;
|
|
12709
|
-
var
|
|
12932
|
+
var LYRIC_DELAY_INFO_HTML = `
|
|
12710
12933
|
<div class="dtm-modal-body-content">
|
|
12711
12934
|
<h4>\u4F55\u3092\u3059\u308B\u8A2D\u5B9A\u304B</h4>
|
|
12712
|
-
<p>\
|
|
12935
|
+
<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>
|
|
12936
|
+
<h4>\u30DE\u30B9\u30BF\u306E\u300C\u30C7\u30A3\u30EC\u30A4\u300D\u3064\u307E\u307F\u3068\u306E\u95A2\u4FC2\uFF08\u91CD\u8981\uFF09</h4>
|
|
12937
|
+
<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>
|
|
12938
|
+
<h4>\u4F7F\u3044\u3069\u3053\u308D</h4>
|
|
12939
|
+
<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>
|
|
12940
|
+
</div>
|
|
12941
|
+
`;
|
|
12942
|
+
var MASTER_REVERB_INFO_HTML = `
|
|
12943
|
+
<div class="dtm-modal-body-content">
|
|
12944
|
+
<h4>\u30EA\u30D0\u30FC\u30D6\uFF08Mix\uFF09</h4>
|
|
12945
|
+
<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>
|
|
12946
|
+
<h4>Decay\uFF08\u6B8B\u97FF\u306E\u9577\u3055\uFF09</h4>
|
|
12947
|
+
<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>
|
|
12948
|
+
<h4>Pre Delay\uFF08\u539F\u97F3\u3068\u30EA\u30D0\u30FC\u30D6\u306E\u9593\u9694\uFF09</h4>
|
|
12949
|
+
<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>
|
|
12713
12950
|
<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\
|
|
12715
|
-
|
|
12716
|
-
|
|
12951
|
+
<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>
|
|
12952
|
+
</div>
|
|
12953
|
+
`;
|
|
12954
|
+
var MASTER_DELAY_INFO_HTML = `
|
|
12955
|
+
<div class="dtm-modal-body-content">
|
|
12956
|
+
<h4>\u4F55\u3092\u3059\u308B\u8A2D\u5B9A\u304B</h4>
|
|
12957
|
+
<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>
|
|
12958
|
+
<h4>\u30EA\u30D0\u30FC\u30D6\u3068\u306E\u9055\u3044</h4>
|
|
12959
|
+
<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>
|
|
12960
|
+
<h4>\u5404\u30C8\u30E9\u30C3\u30AF\u306E\u300C\u30C7\u30A3\u30EC\u30A4\u9001\u308A\u300D\u3068\u306E\u95A2\u4FC2</h4>
|
|
12961
|
+
<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>
|
|
12962
|
+
</div>
|
|
12963
|
+
`;
|
|
12964
|
+
var TRACK_EQ_INFO_HTML = `
|
|
12965
|
+
<div class="dtm-modal-body-content">
|
|
12966
|
+
<h4>\u4F55\u3092\u3059\u308B\u8A2D\u5B9A\u304B</h4>
|
|
12967
|
+
<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>
|
|
12968
|
+
<h4>\u4F7F\u3044\u3069\u3053\u308D\uFF08\u5E2F\u57DF\u306E\u68F2\u307F\u5206\u3051\uFF09</h4>
|
|
12969
|
+
<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>
|
|
12970
|
+
<h4>\u4ED6\u306E\u8A2D\u5B9A\u3068\u306E\u517C\u306D\u5408\u3044\uFF08\u9806\u5E8F\u304C\u91CD\u8981\uFF09</h4>
|
|
12971
|
+
<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>
|
|
12717
12972
|
</div>
|
|
12718
12973
|
`;
|
|
12719
12974
|
var TRACK_COMPRESSION_INFO_HTML = `
|
|
@@ -12739,14 +12994,22 @@ var TRACK_WIDTH_INFO_HTML = `
|
|
|
12739
12994
|
var AUTO_MASTER_INFO_HTML = `
|
|
12740
12995
|
<div class="dtm-modal-body-content">
|
|
12741
12996
|
<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>
|
|
12997
|
+
<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>
|
|
12743
12998
|
<ul>
|
|
12744
|
-
<li>\u30DE\u30B9\u30BF\u30EA\u30D0\u30FC\u30D6: 20%</li>
|
|
12745
|
-
<li>\
|
|
12999
|
+
<li>\u30DE\u30B9\u30BF\u30EA\u30D0\u30FC\u30D6 Mix: 20%</li>
|
|
13000
|
+
<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>
|
|
13001
|
+
<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>
|
|
13002
|
+
<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>
|
|
12746
13003
|
<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
|
|
13004
|
+
<li>\u6B4C\u8A5E\u306E\u3042\u308B\u30C8\u30E9\u30C3\u30AF: \u81EA\u52D5\u30D3\u30D6\u30E9\u30FC\u30C8ON</li>
|
|
12748
13005
|
</ul>
|
|
12749
|
-
<
|
|
13006
|
+
<h4>\u30E1\u30A4\u30F3\u30DC\u30FC\u30AB\u30EB\u306E\u81EA\u52D5\u5224\u5B9A</h4>
|
|
13007
|
+
<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>
|
|
13008
|
+
<ul>
|
|
13009
|
+
<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>
|
|
13010
|
+
<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>
|
|
13011
|
+
</ul>
|
|
13012
|
+
<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>
|
|
12750
13013
|
</div>
|
|
12751
13014
|
`;
|
|
12752
13015
|
var MIDI_INFO_HTML = `
|
|
@@ -12982,7 +13245,7 @@ var deriveCustomVocalKeyFromUrl = (url2) => {
|
|
|
12982
13245
|
if (name && /^[0-9]/.test(name)) name = `_${name}`;
|
|
12983
13246
|
return CUSTOM_VOCAL_KEY_RE.test(name) ? name : "";
|
|
12984
13247
|
};
|
|
12985
|
-
var
|
|
13248
|
+
var clamp4 = (v, min, max) => Math.min(Math.max(v, min), max);
|
|
12986
13249
|
var normalizeInstrumentName = (name) => {
|
|
12987
13250
|
if (!name) return "";
|
|
12988
13251
|
const stripped = name.replace(/\s+/g, "").toLowerCase();
|
|
@@ -13022,6 +13285,17 @@ var mountDAW = (target, options = {}) => {
|
|
|
13022
13285
|
refs.masterVolumeLabel.textContent = `${options.masterVolume ?? 50}%`;
|
|
13023
13286
|
refs.reverbAmount.value = String(options.reverbAmount ?? 0);
|
|
13024
13287
|
refs.reverbAmountLabel.textContent = `${options.reverbAmount ?? 0}%`;
|
|
13288
|
+
{
|
|
13289
|
+
const initDecay = options.reverbDecay ?? DEFAULT_REVERB_DECAY_SEC;
|
|
13290
|
+
const initPreDelay = options.reverbPreDelay ?? DEFAULT_REVERB_PREDELAY_MS;
|
|
13291
|
+
refs.reverbDecay.value = String(Math.round(initDecay * 10));
|
|
13292
|
+
refs.reverbDecayLabel.textContent = `${initDecay.toFixed(1)}s`;
|
|
13293
|
+
refs.reverbPreDelay.value = String(initPreDelay);
|
|
13294
|
+
refs.reverbPreDelayLabel.textContent = `${initPreDelay}ms`;
|
|
13295
|
+
}
|
|
13296
|
+
refs.delayAmount.value = String(options.delayAmount ?? 0);
|
|
13297
|
+
refs.delayAmountLabel.textContent = `${options.delayAmount ?? 0}%`;
|
|
13298
|
+
refs.delayDivision.value = options.delayDivision ?? "8";
|
|
13025
13299
|
refs.drumVolume.value = String(options.drumVolume ?? 80);
|
|
13026
13300
|
refs.drumVolumeLabel.textContent = `${options.drumVolume ?? 80}%`;
|
|
13027
13301
|
const renderConfig = {
|
|
@@ -13038,8 +13312,16 @@ var mountDAW = (target, options = {}) => {
|
|
|
13038
13312
|
let masterVolume = options.masterVolume ?? 50;
|
|
13039
13313
|
options.singingVoices?.setVolume(masterVolume / 100);
|
|
13040
13314
|
let reverbAmount = options.reverbAmount ?? 0;
|
|
13315
|
+
let reverbDecay = options.reverbDecay ?? DEFAULT_REVERB_DECAY_SEC;
|
|
13316
|
+
let reverbPreDelay = options.reverbPreDelay ?? DEFAULT_REVERB_PREDELAY_MS;
|
|
13317
|
+
let delayAmount = options.delayAmount ?? 0;
|
|
13318
|
+
let delayDivision = options.delayDivision ?? "8";
|
|
13041
13319
|
let unsubscribeClip;
|
|
13042
13320
|
options.onReverbChange?.(reverbAmount);
|
|
13321
|
+
options.onReverbDecayChange?.(reverbDecay);
|
|
13322
|
+
options.onReverbPreDelayChange?.(reverbPreDelay);
|
|
13323
|
+
options.onDelayChange?.(delayAmount);
|
|
13324
|
+
options.onDelayDivisionChange?.(delayDivision);
|
|
13043
13325
|
let drumVolume = options.drumVolume ?? 80;
|
|
13044
13326
|
let currentDrumPattern = refs.drumSelect.value;
|
|
13045
13327
|
let currentDrumFont = options.drumFont ?? "FluidR3_GM_sf2_file:0";
|
|
@@ -13120,6 +13402,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
13120
13402
|
vocalOctave: t.vocalOctave,
|
|
13121
13403
|
vocalVibrato: t.vocalVibrato,
|
|
13122
13404
|
vocalReverb: t.vocalReverb,
|
|
13405
|
+
vocalDelay: t.vocalDelay,
|
|
13123
13406
|
vocalGender: t.vocalGender,
|
|
13124
13407
|
vocalBreathiness: t.vocalBreathiness
|
|
13125
13408
|
};
|
|
@@ -13183,11 +13466,15 @@ var mountDAW = (target, options = {}) => {
|
|
|
13183
13466
|
vocalOctave: 0,
|
|
13184
13467
|
vocalVibrato: false,
|
|
13185
13468
|
vocalReverb: 0,
|
|
13469
|
+
vocalDelay: 0,
|
|
13186
13470
|
vocalGender: 50,
|
|
13187
13471
|
vocalBreathiness: 50,
|
|
13188
13472
|
trackInstrument: "",
|
|
13189
13473
|
trackCompression: 0,
|
|
13190
|
-
trackWidth: 100
|
|
13474
|
+
trackWidth: 100,
|
|
13475
|
+
trackEqLow: 0,
|
|
13476
|
+
trackEqMid: 0,
|
|
13477
|
+
trackEqHigh: 0
|
|
13191
13478
|
};
|
|
13192
13479
|
});
|
|
13193
13480
|
};
|
|
@@ -13208,6 +13495,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
13208
13495
|
octave: t.vocalOctave,
|
|
13209
13496
|
vibrato: t.vocalVibrato,
|
|
13210
13497
|
reverb: t.vocalReverb,
|
|
13498
|
+
delay: t.vocalDelay,
|
|
13211
13499
|
gender: t.vocalGender,
|
|
13212
13500
|
breathiness: t.vocalBreathiness,
|
|
13213
13501
|
syllables
|
|
@@ -13330,7 +13618,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
13330
13618
|
const thumbW = Math.max(40, canvas.width / totalContentWidth * sbW);
|
|
13331
13619
|
const ratio = currentOffsetX / maxOffsetX;
|
|
13332
13620
|
refs.hScrollThumb.style.width = `${thumbW}px`;
|
|
13333
|
-
refs.hScrollThumb.style.left = `${
|
|
13621
|
+
refs.hScrollThumb.style.left = `${clamp4(ratio * (sbW - thumbW), 0, sbW - thumbW)}px`;
|
|
13334
13622
|
}
|
|
13335
13623
|
const totalHeight = renderConfig.keyCount * renderConfig.keyHeight;
|
|
13336
13624
|
const sbH = refs.vScroll.clientHeight;
|
|
@@ -13400,9 +13688,9 @@ var mountDAW = (target, options = {}) => {
|
|
|
13400
13688
|
if (maxOffsetX <= 0) return;
|
|
13401
13689
|
const rect = refs.hScroll.getBoundingClientRect();
|
|
13402
13690
|
const thumbW = Number.parseFloat(refs.hScrollThumb.style.width) || 40;
|
|
13403
|
-
const x2 =
|
|
13691
|
+
const x2 = clamp4(clientX - rect.left - thumbW / 2, 0, rect.width - thumbW);
|
|
13404
13692
|
const ratio = x2 / (rect.width - thumbW);
|
|
13405
|
-
currentOffsetX =
|
|
13693
|
+
currentOffsetX = clamp4(ratio * maxOffsetX, 0, maxOffsetX);
|
|
13406
13694
|
setDrawOffset(currentOffsetX, currentOffsetY);
|
|
13407
13695
|
redrawAll();
|
|
13408
13696
|
};
|
|
@@ -13411,9 +13699,9 @@ var mountDAW = (target, options = {}) => {
|
|
|
13411
13699
|
if (maxOffset <= 0) return;
|
|
13412
13700
|
const rect = refs.vScroll.getBoundingClientRect();
|
|
13413
13701
|
const thumbH = Number.parseFloat(refs.vScrollThumb.style.height) || 40;
|
|
13414
|
-
const y =
|
|
13702
|
+
const y = clamp4(clientY - rect.top - thumbH / 2, 0, rect.height - thumbH);
|
|
13415
13703
|
const ratio = y / (rect.height - thumbH);
|
|
13416
|
-
currentOffsetY =
|
|
13704
|
+
currentOffsetY = clamp4(ratio * maxOffset, 0, maxOffset);
|
|
13417
13705
|
setDrawOffset(currentOffsetX, currentOffsetY);
|
|
13418
13706
|
redrawAll();
|
|
13419
13707
|
};
|
|
@@ -13460,8 +13748,8 @@ var mountDAW = (target, options = {}) => {
|
|
|
13460
13748
|
if (dx !== 0 || dy !== 0) {
|
|
13461
13749
|
const maxOffsetX = getMaxOffsetX();
|
|
13462
13750
|
const maxOffsetY = getMaxOffsetY();
|
|
13463
|
-
currentOffsetX =
|
|
13464
|
-
currentOffsetY =
|
|
13751
|
+
currentOffsetX = clamp4(currentOffsetX + dx, 0, maxOffsetX);
|
|
13752
|
+
currentOffsetY = clamp4(currentOffsetY + dy, 0, maxOffsetY);
|
|
13465
13753
|
setDrawOffset(currentOffsetX, currentOffsetY);
|
|
13466
13754
|
onPointerMove(lastMoveEvent);
|
|
13467
13755
|
}
|
|
@@ -13851,12 +14139,12 @@ var mountDAW = (target, options = {}) => {
|
|
|
13851
14139
|
"wheel",
|
|
13852
14140
|
(event) => {
|
|
13853
14141
|
event.preventDefault();
|
|
13854
|
-
currentOffsetY =
|
|
14142
|
+
currentOffsetY = clamp4(
|
|
13855
14143
|
currentOffsetY + event.deltaY,
|
|
13856
14144
|
0,
|
|
13857
14145
|
getMaxOffsetY()
|
|
13858
14146
|
);
|
|
13859
|
-
currentOffsetX =
|
|
14147
|
+
currentOffsetX = clamp4(
|
|
13860
14148
|
currentOffsetX + event.deltaX,
|
|
13861
14149
|
0,
|
|
13862
14150
|
getMaxOffsetX()
|
|
@@ -13895,7 +14183,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
13895
14183
|
const centerStep = (currentOffsetX + canvas.width / 2) / renderConfig.stepWidth;
|
|
13896
14184
|
renderConfig.stepWidth = BASE_STEP_WIDTH * (zoomX * 2) / 100;
|
|
13897
14185
|
refs.zoomXLabel.textContent = `${zoomX}%`;
|
|
13898
|
-
currentOffsetX =
|
|
14186
|
+
currentOffsetX = clamp4(
|
|
13899
14187
|
centerStep * renderConfig.stepWidth - canvas.width / 2,
|
|
13900
14188
|
0,
|
|
13901
14189
|
getMaxOffsetX()
|
|
@@ -13908,7 +14196,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
13908
14196
|
const centerKey = (currentOffsetY + canvas.height / 2) / renderConfig.keyHeight;
|
|
13909
14197
|
renderConfig.keyHeight = BASE_KEY_HEIGHT * zoomY / 100;
|
|
13910
14198
|
refs.zoomYLabel.textContent = `${zoomY}%`;
|
|
13911
|
-
currentOffsetY =
|
|
14199
|
+
currentOffsetY = clamp4(
|
|
13912
14200
|
centerKey * renderConfig.keyHeight - canvas.height / 2,
|
|
13913
14201
|
0,
|
|
13914
14202
|
getMaxOffsetY()
|
|
@@ -13958,7 +14246,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
13958
14246
|
const threshold = currentOffsetX / renderConfig.stepWidth + visibleSteps - 4;
|
|
13959
14247
|
if (currentPlayStep > threshold) {
|
|
13960
14248
|
const visibleBars = Math.round(visibleSteps / renderConfig.stepsPerBar);
|
|
13961
|
-
currentOffsetX =
|
|
14249
|
+
currentOffsetX = clamp4(
|
|
13962
14250
|
currentOffsetX + visibleBars * renderConfig.stepsPerBar * renderConfig.stepWidth,
|
|
13963
14251
|
0,
|
|
13964
14252
|
getMaxOffsetX()
|
|
@@ -14014,6 +14302,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
14014
14302
|
pan: panToStereo(lt.pan ?? DEFAULT_PAN),
|
|
14015
14303
|
vibrato: lt.vibrato,
|
|
14016
14304
|
reverbSend: (lt.reverb ?? 0) / 100,
|
|
14305
|
+
delaySend: (lt.delay ?? 0) / 100,
|
|
14017
14306
|
gender: (lt.gender ?? 50) / 100,
|
|
14018
14307
|
breathiness: (lt.breathiness ?? 50) / 100,
|
|
14019
14308
|
notes
|
|
@@ -14043,7 +14332,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
14043
14332
|
}
|
|
14044
14333
|
if (playbackState !== "paused") {
|
|
14045
14334
|
const canvas = getGridCanvas();
|
|
14046
|
-
currentOffsetX =
|
|
14335
|
+
currentOffsetX = clamp4(
|
|
14047
14336
|
playStartStep * renderConfig.stepWidth - canvas.width * 0.5,
|
|
14048
14337
|
0,
|
|
14049
14338
|
getMaxOffsetX()
|
|
@@ -14123,7 +14412,23 @@ var mountDAW = (target, options = {}) => {
|
|
|
14123
14412
|
<span class="dtm-label" data-dtm="track-vol-label">${active.volume}</span>
|
|
14124
14413
|
</div>
|
|
14125
14414
|
<details class="dtm-advanced" data-dtm="track-fx-advanced">
|
|
14126
|
-
<summary>\u8A73\u7D30\u8A2D\u5B9A\
|
|
14415
|
+
<summary>\u8A73\u7D30\u8A2D\u5B9A\uFF08EQ\u30FB\u97F3\u5727\u30FB\u30B9\u30C6\u30EC\u30AA\u5E45\uFF09</summary>
|
|
14416
|
+
<div class="dtm-row">
|
|
14417
|
+
<span class="dtm-label">EQ\u4F4E\u57DF</span>
|
|
14418
|
+
<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">
|
|
14419
|
+
<span class="dtm-label" data-dtm="track-eq-low-label"></span>
|
|
14420
|
+
<button class="dtm-infobtn" data-dtm="track-eq-info" title="EQ\u306E\u89E3\u8AAC">${icon("info", 12)}</button>
|
|
14421
|
+
</div>
|
|
14422
|
+
<div class="dtm-row">
|
|
14423
|
+
<span class="dtm-label">EQ\u4E2D\u57DF</span>
|
|
14424
|
+
<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">
|
|
14425
|
+
<span class="dtm-label" data-dtm="track-eq-mid-label"></span>
|
|
14426
|
+
</div>
|
|
14427
|
+
<div class="dtm-row">
|
|
14428
|
+
<span class="dtm-label">EQ\u9AD8\u57DF</span>
|
|
14429
|
+
<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">
|
|
14430
|
+
<span class="dtm-label" data-dtm="track-eq-high-label"></span>
|
|
14431
|
+
</div>
|
|
14127
14432
|
<div class="dtm-row">
|
|
14128
14433
|
<span class="dtm-label">\u97F3\u5727\u5F37\u5316</span>
|
|
14129
14434
|
<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">
|
|
@@ -14153,6 +14458,52 @@ var mountDAW = (target, options = {}) => {
|
|
|
14153
14458
|
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" : "";
|
|
14154
14459
|
};
|
|
14155
14460
|
syncVelocityDisabled();
|
|
14461
|
+
const trackEqLowInput = refs.trackBody.querySelector(
|
|
14462
|
+
'[data-dtm="track-eq-low"]'
|
|
14463
|
+
);
|
|
14464
|
+
const trackEqLowLabel = refs.trackBody.querySelector(
|
|
14465
|
+
'[data-dtm="track-eq-low-label"]'
|
|
14466
|
+
);
|
|
14467
|
+
const trackEqMidInput = refs.trackBody.querySelector(
|
|
14468
|
+
'[data-dtm="track-eq-mid"]'
|
|
14469
|
+
);
|
|
14470
|
+
const trackEqMidLabel = refs.trackBody.querySelector(
|
|
14471
|
+
'[data-dtm="track-eq-mid-label"]'
|
|
14472
|
+
);
|
|
14473
|
+
const trackEqHighInput = refs.trackBody.querySelector(
|
|
14474
|
+
'[data-dtm="track-eq-high"]'
|
|
14475
|
+
);
|
|
14476
|
+
const trackEqHighLabel = refs.trackBody.querySelector(
|
|
14477
|
+
'[data-dtm="track-eq-high-label"]'
|
|
14478
|
+
);
|
|
14479
|
+
const trackEqInfo = refs.trackBody.querySelector(
|
|
14480
|
+
'[data-dtm="track-eq-info"]'
|
|
14481
|
+
);
|
|
14482
|
+
const fmtDb = (db) => db > 0 ? `+${db}dB` : `${db}dB`;
|
|
14483
|
+
trackEqLowInput.value = String(active.trackEqLow);
|
|
14484
|
+
trackEqLowLabel.textContent = fmtDb(active.trackEqLow);
|
|
14485
|
+
trackEqMidInput.value = String(active.trackEqMid);
|
|
14486
|
+
trackEqMidLabel.textContent = fmtDb(active.trackEqMid);
|
|
14487
|
+
trackEqHighInput.value = String(active.trackEqHigh);
|
|
14488
|
+
trackEqHighLabel.textContent = fmtDb(active.trackEqHigh);
|
|
14489
|
+
trackEqLowInput.addEventListener("input", () => {
|
|
14490
|
+
active.trackEqLow = Number.parseInt(trackEqLowInput.value, 10);
|
|
14491
|
+
trackEqLowLabel.textContent = fmtDb(active.trackEqLow);
|
|
14492
|
+
options.onTrackEqLowChange?.(active.config.id, active.trackEqLow);
|
|
14493
|
+
});
|
|
14494
|
+
trackEqMidInput.addEventListener("input", () => {
|
|
14495
|
+
active.trackEqMid = Number.parseInt(trackEqMidInput.value, 10);
|
|
14496
|
+
trackEqMidLabel.textContent = fmtDb(active.trackEqMid);
|
|
14497
|
+
options.onTrackEqMidChange?.(active.config.id, active.trackEqMid);
|
|
14498
|
+
});
|
|
14499
|
+
trackEqHighInput.addEventListener("input", () => {
|
|
14500
|
+
active.trackEqHigh = Number.parseInt(trackEqHighInput.value, 10);
|
|
14501
|
+
trackEqHighLabel.textContent = fmtDb(active.trackEqHigh);
|
|
14502
|
+
options.onTrackEqHighChange?.(active.config.id, active.trackEqHigh);
|
|
14503
|
+
});
|
|
14504
|
+
trackEqInfo.addEventListener("click", () => {
|
|
14505
|
+
showModal("EQ\uFF08\u30A4\u30B3\u30E9\u30A4\u30B6\u30FC\uFF09\u306E\u89E3\u8AAC", TRACK_EQ_INFO_HTML);
|
|
14506
|
+
});
|
|
14156
14507
|
const trackCompInput = refs.trackBody.querySelector(
|
|
14157
14508
|
'[data-dtm="track-comp"]'
|
|
14158
14509
|
);
|
|
@@ -14305,6 +14656,12 @@ var mountDAW = (target, options = {}) => {
|
|
|
14305
14656
|
<span class="dtm-label" data-dtm="lyric-reverb-label"></span>
|
|
14306
14657
|
<button class="dtm-infobtn" data-dtm="lyric-reverb-info" title="\u30EA\u30D0\u30FC\u30D6\u9001\u308A\u306E\u89E3\u8AAC">${icon("info", 12)}</button>
|
|
14307
14658
|
</div>
|
|
14659
|
+
<div class="dtm-row">
|
|
14660
|
+
<span class="dtm-label">\u30C7\u30A3\u30EC\u30A4\u9001\u308A</span>
|
|
14661
|
+
<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">
|
|
14662
|
+
<span class="dtm-label" data-dtm="lyric-delay-label"></span>
|
|
14663
|
+
<button class="dtm-infobtn" data-dtm="lyric-delay-info" title="\u30C7\u30A3\u30EC\u30A4\u9001\u308A\u306E\u89E3\u8AAC">${icon("info", 12)}</button>
|
|
14664
|
+
</div>
|
|
14308
14665
|
<div class="dtm-row">
|
|
14309
14666
|
<span class="dtm-label">\u30B8\u30A7\u30F3\u30C0\u30FC</span>
|
|
14310
14667
|
<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">
|
|
@@ -14369,6 +14726,18 @@ var mountDAW = (target, options = {}) => {
|
|
|
14369
14726
|
lyricReverbInfo.addEventListener("click", () => {
|
|
14370
14727
|
showModal("\u30EA\u30D0\u30FC\u30D6\u9001\u308A\u306E\u89E3\u8AAC", LYRIC_REVERB_INFO_HTML);
|
|
14371
14728
|
});
|
|
14729
|
+
const lyricDelay = lyricDiv.querySelector(
|
|
14730
|
+
'[data-dtm="lyric-delay"]'
|
|
14731
|
+
);
|
|
14732
|
+
const lyricDelayLabel = lyricDiv.querySelector(
|
|
14733
|
+
'[data-dtm="lyric-delay-label"]'
|
|
14734
|
+
);
|
|
14735
|
+
const lyricDelayInfo = lyricDiv.querySelector(
|
|
14736
|
+
'[data-dtm="lyric-delay-info"]'
|
|
14737
|
+
);
|
|
14738
|
+
lyricDelayInfo.addEventListener("click", () => {
|
|
14739
|
+
showModal("\u30C7\u30A3\u30EC\u30A4\u9001\u308A\u306E\u89E3\u8AAC", LYRIC_DELAY_INFO_HTML);
|
|
14740
|
+
});
|
|
14372
14741
|
const lyricGender = lyricDiv.querySelector(
|
|
14373
14742
|
'[data-dtm="lyric-gender"]'
|
|
14374
14743
|
);
|
|
@@ -14465,6 +14834,8 @@ var mountDAW = (target, options = {}) => {
|
|
|
14465
14834
|
lyricPanLabel.textContent = fmtPan(active.vocalPan);
|
|
14466
14835
|
lyricReverb.value = String(active.vocalReverb);
|
|
14467
14836
|
lyricReverbLabel.textContent = `${active.vocalReverb}%`;
|
|
14837
|
+
lyricDelay.value = String(active.vocalDelay);
|
|
14838
|
+
lyricDelayLabel.textContent = `${active.vocalDelay}%`;
|
|
14468
14839
|
lyricGender.value = String(active.vocalGender);
|
|
14469
14840
|
lyricGenderLabel.textContent = `${active.vocalGender}`;
|
|
14470
14841
|
lyricBreathiness.value = String(active.vocalBreathiness);
|
|
@@ -14619,6 +14990,11 @@ var mountDAW = (target, options = {}) => {
|
|
|
14619
14990
|
lyricReverbLabel.textContent = `${active.vocalReverb}%`;
|
|
14620
14991
|
fireLyricsChange(active);
|
|
14621
14992
|
});
|
|
14993
|
+
lyricDelay.addEventListener("input", () => {
|
|
14994
|
+
active.vocalDelay = Number.parseInt(lyricDelay.value, 10);
|
|
14995
|
+
lyricDelayLabel.textContent = `${active.vocalDelay}%`;
|
|
14996
|
+
fireLyricsChange(active);
|
|
14997
|
+
});
|
|
14622
14998
|
lyricGender.addEventListener("input", () => {
|
|
14623
14999
|
active.vocalGender = Number.parseInt(lyricGender.value, 10);
|
|
14624
15000
|
lyricGenderLabel.textContent = `${active.vocalGender}`;
|
|
@@ -14714,15 +15090,24 @@ var mountDAW = (target, options = {}) => {
|
|
|
14714
15090
|
const trackInstrumentsForMeta = {};
|
|
14715
15091
|
const trackCompressionForMeta = {};
|
|
14716
15092
|
const trackWidthForMeta = {};
|
|
15093
|
+
const trackEqLowForMeta = {};
|
|
15094
|
+
const trackEqMidForMeta = {};
|
|
15095
|
+
const trackEqHighForMeta = {};
|
|
14717
15096
|
trackStates.forEach((t, i2) => {
|
|
14718
15097
|
if (t.trackInstrument) trackInstrumentsForMeta[i2] = t.trackInstrument;
|
|
14719
15098
|
if (t.trackCompression !== 0)
|
|
14720
15099
|
trackCompressionForMeta[i2] = t.trackCompression;
|
|
14721
15100
|
if (t.trackWidth !== 100) trackWidthForMeta[i2] = t.trackWidth;
|
|
15101
|
+
if (t.trackEqLow !== 0) trackEqLowForMeta[i2] = t.trackEqLow;
|
|
15102
|
+
if (t.trackEqMid !== 0) trackEqMidForMeta[i2] = t.trackEqMid;
|
|
15103
|
+
if (t.trackEqHigh !== 0) trackEqHighForMeta[i2] = t.trackEqHigh;
|
|
14722
15104
|
});
|
|
14723
15105
|
const trackInstMeta = Object.keys(trackInstrumentsForMeta).length > 0 ? trackInstrumentsForMeta : void 0;
|
|
14724
15106
|
const trackCompMeta = Object.keys(trackCompressionForMeta).length > 0 ? trackCompressionForMeta : void 0;
|
|
14725
15107
|
const trackWidthMeta = Object.keys(trackWidthForMeta).length > 0 ? trackWidthForMeta : void 0;
|
|
15108
|
+
const trackEqLowMeta = Object.keys(trackEqLowForMeta).length > 0 ? trackEqLowForMeta : void 0;
|
|
15109
|
+
const trackEqMidMeta = Object.keys(trackEqMidForMeta).length > 0 ? trackEqMidForMeta : void 0;
|
|
15110
|
+
const trackEqHighMeta = Object.keys(trackEqHighForMeta).length > 0 ? trackEqHighForMeta : void 0;
|
|
14726
15111
|
const metaLineFull = formatMmlMeta(
|
|
14727
15112
|
{
|
|
14728
15113
|
instrument: currentInstrument || void 0,
|
|
@@ -14730,10 +15115,17 @@ var mountDAW = (target, options = {}) => {
|
|
|
14730
15115
|
volume: masterVolume,
|
|
14731
15116
|
drumVolume,
|
|
14732
15117
|
reverb: reverbAmount,
|
|
15118
|
+
reverbDecay: Math.round(reverbDecay * 10),
|
|
15119
|
+
reverbPreDelay,
|
|
15120
|
+
delay: delayAmount,
|
|
15121
|
+
delayDivision,
|
|
14733
15122
|
mode,
|
|
14734
15123
|
trackInstruments: trackInstMeta,
|
|
14735
15124
|
trackCompression: trackCompMeta,
|
|
14736
|
-
trackWidth: trackWidthMeta
|
|
15125
|
+
trackWidth: trackWidthMeta,
|
|
15126
|
+
trackEqLow: trackEqLowMeta,
|
|
15127
|
+
trackEqMid: trackEqMidMeta,
|
|
15128
|
+
trackEqHigh: trackEqHighMeta
|
|
14737
15129
|
},
|
|
14738
15130
|
" "
|
|
14739
15131
|
);
|
|
@@ -14744,10 +15136,17 @@ var mountDAW = (target, options = {}) => {
|
|
|
14744
15136
|
volume: masterVolume,
|
|
14745
15137
|
drumVolume,
|
|
14746
15138
|
reverb: reverbAmount,
|
|
15139
|
+
reverbDecay: Math.round(reverbDecay * 10),
|
|
15140
|
+
reverbPreDelay,
|
|
15141
|
+
delay: delayAmount,
|
|
15142
|
+
delayDivision,
|
|
14747
15143
|
mode,
|
|
14748
15144
|
trackInstruments: trackInstMeta,
|
|
14749
15145
|
trackCompression: trackCompMeta,
|
|
14750
|
-
trackWidth: trackWidthMeta
|
|
15146
|
+
trackWidth: trackWidthMeta,
|
|
15147
|
+
trackEqLow: trackEqLowMeta,
|
|
15148
|
+
trackEqMid: trackEqMidMeta,
|
|
15149
|
+
trackEqHigh: trackEqHighMeta
|
|
14751
15150
|
},
|
|
14752
15151
|
""
|
|
14753
15152
|
);
|
|
@@ -14797,6 +15196,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
14797
15196
|
oct: t.vocalOctave,
|
|
14798
15197
|
vib: t.vocalVibrato,
|
|
14799
15198
|
rev: t.vocalReverb,
|
|
15199
|
+
del: t.vocalDelay,
|
|
14800
15200
|
gen: t.vocalGender,
|
|
14801
15201
|
bre: t.vocalBreathiness
|
|
14802
15202
|
})).filter(
|
|
@@ -14809,6 +15209,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
14809
15209
|
x2.oct === 0 ? "" : `o${x2.oct}`,
|
|
14810
15210
|
x2.vib ? "b1" : "",
|
|
14811
15211
|
x2.rev === 0 ? "" : `r${x2.rev}`,
|
|
15212
|
+
x2.del === 0 ? "" : `e${x2.del}`,
|
|
14812
15213
|
x2.gen === 50 ? "" : `g${x2.gen}`,
|
|
14813
15214
|
x2.bre === 50 ? "" : `h${x2.bre}`
|
|
14814
15215
|
].filter((s) => s.length > 0).join(" ");
|
|
@@ -14879,7 +15280,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
14879
15280
|
const canvas = getGridCanvas();
|
|
14880
15281
|
const yIndex = renderConfig.keyCount - 1 - (pitch - renderConfig.pitchRangeStart);
|
|
14881
15282
|
const logicalY = yIndex * renderConfig.keyHeight;
|
|
14882
|
-
currentOffsetY =
|
|
15283
|
+
currentOffsetY = clamp4(
|
|
14883
15284
|
logicalY - (canvas.height - renderConfig.keyHeight) / 2,
|
|
14884
15285
|
0,
|
|
14885
15286
|
getMaxOffsetY()
|
|
@@ -14956,6 +15357,29 @@ var mountDAW = (target, options = {}) => {
|
|
|
14956
15357
|
refs.reverbAmountLabel.textContent = `${meta.reverb}%`;
|
|
14957
15358
|
options.onReverbChange?.(meta.reverb);
|
|
14958
15359
|
}
|
|
15360
|
+
if (meta.reverbDecay !== void 0) {
|
|
15361
|
+
reverbDecay = meta.reverbDecay / 10;
|
|
15362
|
+
refs.reverbDecay.value = String(meta.reverbDecay);
|
|
15363
|
+
refs.reverbDecayLabel.textContent = `${reverbDecay.toFixed(1)}s`;
|
|
15364
|
+
options.onReverbDecayChange?.(reverbDecay);
|
|
15365
|
+
}
|
|
15366
|
+
if (meta.reverbPreDelay !== void 0) {
|
|
15367
|
+
reverbPreDelay = meta.reverbPreDelay;
|
|
15368
|
+
refs.reverbPreDelay.value = String(meta.reverbPreDelay);
|
|
15369
|
+
refs.reverbPreDelayLabel.textContent = `${meta.reverbPreDelay}ms`;
|
|
15370
|
+
options.onReverbPreDelayChange?.(reverbPreDelay);
|
|
15371
|
+
}
|
|
15372
|
+
if (meta.delay !== void 0) {
|
|
15373
|
+
delayAmount = meta.delay;
|
|
15374
|
+
refs.delayAmount.value = String(meta.delay);
|
|
15375
|
+
refs.delayAmountLabel.textContent = `${meta.delay}%`;
|
|
15376
|
+
options.onDelayChange?.(meta.delay);
|
|
15377
|
+
}
|
|
15378
|
+
if (meta.delayDivision && ["4", "8", "8d", "16"].includes(meta.delayDivision)) {
|
|
15379
|
+
delayDivision = meta.delayDivision;
|
|
15380
|
+
refs.delayDivision.value = delayDivision;
|
|
15381
|
+
options.onDelayDivisionChange?.(delayDivision);
|
|
15382
|
+
}
|
|
14959
15383
|
}
|
|
14960
15384
|
trackStates.forEach((t, i2) => {
|
|
14961
15385
|
if (applyActiveOnly && i2 !== activeTrackIndex) return;
|
|
@@ -14977,6 +15401,21 @@ var mountDAW = (target, options = {}) => {
|
|
|
14977
15401
|
t.trackWidth = width;
|
|
14978
15402
|
options.onTrackWidthChange?.(t.config.id, width);
|
|
14979
15403
|
}
|
|
15404
|
+
const eqLow = meta.trackEqLow?.[i2] ?? 0;
|
|
15405
|
+
if (t.trackEqLow !== eqLow) {
|
|
15406
|
+
t.trackEqLow = eqLow;
|
|
15407
|
+
options.onTrackEqLowChange?.(t.config.id, eqLow);
|
|
15408
|
+
}
|
|
15409
|
+
const eqMid = meta.trackEqMid?.[i2] ?? 0;
|
|
15410
|
+
if (t.trackEqMid !== eqMid) {
|
|
15411
|
+
t.trackEqMid = eqMid;
|
|
15412
|
+
options.onTrackEqMidChange?.(t.config.id, eqMid);
|
|
15413
|
+
}
|
|
15414
|
+
const eqHigh = meta.trackEqHigh?.[i2] ?? 0;
|
|
15415
|
+
if (t.trackEqHigh !== eqHigh) {
|
|
15416
|
+
t.trackEqHigh = eqHigh;
|
|
15417
|
+
options.onTrackEqHighChange?.(t.config.id, eqHigh);
|
|
15418
|
+
}
|
|
14980
15419
|
});
|
|
14981
15420
|
trackStates.forEach((t, i2) => {
|
|
14982
15421
|
if (applyActiveOnly && i2 !== activeTrackIndex) return;
|
|
@@ -14996,6 +15435,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
14996
15435
|
active.vocalOctave = 0;
|
|
14997
15436
|
active.vocalVibrato = false;
|
|
14998
15437
|
active.vocalReverb = 0;
|
|
15438
|
+
active.vocalDelay = 0;
|
|
14999
15439
|
active.vocalGender = 50;
|
|
15000
15440
|
active.vocalBreathiness = 50;
|
|
15001
15441
|
} else {
|
|
@@ -15008,6 +15448,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
15008
15448
|
t.vocalOctave = 0;
|
|
15009
15449
|
t.vocalVibrato = false;
|
|
15010
15450
|
t.vocalReverb = 0;
|
|
15451
|
+
t.vocalDelay = 0;
|
|
15011
15452
|
t.vocalGender = 50;
|
|
15012
15453
|
t.vocalBreathiness = 50;
|
|
15013
15454
|
}
|
|
@@ -15024,6 +15465,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
15024
15465
|
t.vocalOctave = lt.octave ?? 0;
|
|
15025
15466
|
t.vocalVibrato = lt.vibrato ?? false;
|
|
15026
15467
|
t.vocalReverb = lt.reverb ?? 0;
|
|
15468
|
+
t.vocalDelay = lt.delay ?? 0;
|
|
15027
15469
|
t.vocalGender = lt.gender ?? 50;
|
|
15028
15470
|
t.vocalBreathiness = lt.breathiness ?? 50;
|
|
15029
15471
|
});
|
|
@@ -15106,6 +15548,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
15106
15548
|
active.vocalOctave = 0;
|
|
15107
15549
|
active.vocalVibrato = false;
|
|
15108
15550
|
active.vocalReverb = 0;
|
|
15551
|
+
active.vocalDelay = 0;
|
|
15109
15552
|
active.vocalGender = 50;
|
|
15110
15553
|
active.vocalBreathiness = 50;
|
|
15111
15554
|
} else {
|
|
@@ -15120,6 +15563,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
15120
15563
|
t.vocalOctave = 0;
|
|
15121
15564
|
t.vocalVibrato = false;
|
|
15122
15565
|
t.vocalReverb = 0;
|
|
15566
|
+
t.vocalDelay = 0;
|
|
15123
15567
|
t.vocalGender = 50;
|
|
15124
15568
|
t.vocalBreathiness = 50;
|
|
15125
15569
|
}
|
|
@@ -15170,6 +15614,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
15170
15614
|
bpm = value;
|
|
15171
15615
|
refs.bpmInput.value = String(value);
|
|
15172
15616
|
for (const t of trackStates) t.core.setTempo(value);
|
|
15617
|
+
options.onBpmChange?.(value);
|
|
15173
15618
|
};
|
|
15174
15619
|
let lastUndoTime = 0;
|
|
15175
15620
|
const undo = () => {
|
|
@@ -15345,6 +15790,32 @@ var mountDAW = (target, options = {}) => {
|
|
|
15345
15790
|
refs.reverbAmountInfoBtn.addEventListener("click", () => {
|
|
15346
15791
|
showModal("\u30DE\u30B9\u30BF\u30EA\u30D0\u30FC\u30D6\u306E\u89E3\u8AAC", MASTER_REVERB_INFO_HTML);
|
|
15347
15792
|
});
|
|
15793
|
+
refs.reverbDecay.addEventListener("input", () => {
|
|
15794
|
+
const raw = Number.parseInt(refs.reverbDecay.value, 10) || 22;
|
|
15795
|
+
reverbDecay = Math.max(
|
|
15796
|
+
MIN_REVERB_DECAY_SEC,
|
|
15797
|
+
Math.min(MAX_REVERB_DECAY_SEC, raw / 10)
|
|
15798
|
+
);
|
|
15799
|
+
refs.reverbDecayLabel.textContent = `${reverbDecay.toFixed(1)}s`;
|
|
15800
|
+
options.onReverbDecayChange?.(reverbDecay);
|
|
15801
|
+
});
|
|
15802
|
+
refs.reverbPreDelay.addEventListener("input", () => {
|
|
15803
|
+
reverbPreDelay = Number.parseInt(refs.reverbPreDelay.value, 10) || 0;
|
|
15804
|
+
refs.reverbPreDelayLabel.textContent = `${reverbPreDelay}ms`;
|
|
15805
|
+
options.onReverbPreDelayChange?.(reverbPreDelay);
|
|
15806
|
+
});
|
|
15807
|
+
refs.delayAmount.addEventListener("input", () => {
|
|
15808
|
+
delayAmount = Number.parseInt(refs.delayAmount.value, 10) || 0;
|
|
15809
|
+
refs.delayAmountLabel.textContent = `${delayAmount}%`;
|
|
15810
|
+
options.onDelayChange?.(delayAmount);
|
|
15811
|
+
});
|
|
15812
|
+
refs.delayDivision.addEventListener("change", () => {
|
|
15813
|
+
delayDivision = refs.delayDivision.value;
|
|
15814
|
+
options.onDelayDivisionChange?.(delayDivision);
|
|
15815
|
+
});
|
|
15816
|
+
refs.delayAmountInfoBtn.addEventListener("click", () => {
|
|
15817
|
+
showModal("\u30DE\u30B9\u30BF\u30C7\u30A3\u30EC\u30A4\u306E\u89E3\u8AAC", MASTER_DELAY_INFO_HTML);
|
|
15818
|
+
});
|
|
15348
15819
|
refs.autoMasterInfoBtn.addEventListener("click", () => {
|
|
15349
15820
|
showModal("\u304A\u307E\u304B\u305B\u30DE\u30B9\u30BF\u30EA\u30F3\u30B0\u89E3\u8AAC", AUTO_MASTER_INFO_HTML);
|
|
15350
15821
|
});
|
|
@@ -15353,14 +15824,39 @@ var mountDAW = (target, options = {}) => {
|
|
|
15353
15824
|
refs.reverbAmount.value = "20";
|
|
15354
15825
|
refs.reverbAmountLabel.textContent = "20%";
|
|
15355
15826
|
options.onReverbChange?.(20);
|
|
15827
|
+
const bpmT = clamp4((bpm - 60) / (180 - 60), 0, 1);
|
|
15828
|
+
reverbDecay = clamp4(
|
|
15829
|
+
3 - bpmT * (3 - 0.9),
|
|
15830
|
+
MIN_REVERB_DECAY_SEC,
|
|
15831
|
+
MAX_REVERB_DECAY_SEC
|
|
15832
|
+
);
|
|
15833
|
+
refs.reverbDecay.value = String(Math.round(reverbDecay * 10));
|
|
15834
|
+
refs.reverbDecayLabel.textContent = `${reverbDecay.toFixed(1)}s`;
|
|
15835
|
+
options.onReverbDecayChange?.(reverbDecay);
|
|
15836
|
+
reverbPreDelay = 20;
|
|
15837
|
+
refs.reverbPreDelay.value = "20";
|
|
15838
|
+
refs.reverbPreDelayLabel.textContent = "20ms";
|
|
15839
|
+
options.onReverbPreDelayChange?.(20);
|
|
15840
|
+
let mainVocalId = null;
|
|
15841
|
+
let mainVocalScore = -1;
|
|
15842
|
+
for (const t of trackStates) {
|
|
15843
|
+
if (!t.lyricModel) continue;
|
|
15844
|
+
const score = t.core.getNotes().reduce((sum, n) => sum + n.durationSteps, 0);
|
|
15845
|
+
if (score > mainVocalScore) {
|
|
15846
|
+
mainVocalScore = score;
|
|
15847
|
+
mainVocalId = t.config.id;
|
|
15848
|
+
}
|
|
15849
|
+
}
|
|
15356
15850
|
for (const t of trackStates) {
|
|
15357
|
-
t.
|
|
15851
|
+
const isMainVocal = !!t.lyricModel && t.config.id === mainVocalId;
|
|
15852
|
+
const comp = !t.lyricModel ? 35 : isMainVocal ? 30 : 25;
|
|
15853
|
+
t.trackCompression = comp;
|
|
15358
15854
|
t.trackWidth = 115;
|
|
15359
|
-
options.onTrackCompressionChange?.(t.config.id,
|
|
15855
|
+
options.onTrackCompressionChange?.(t.config.id, comp);
|
|
15360
15856
|
options.onTrackWidthChange?.(t.config.id, 115);
|
|
15361
15857
|
if (t.lyricModel) {
|
|
15362
15858
|
t.vocalVibrato = true;
|
|
15363
|
-
t.vocalReverb =
|
|
15859
|
+
t.vocalReverb = isMainVocal ? 15 : 30;
|
|
15364
15860
|
fireLyricsChange(t);
|
|
15365
15861
|
}
|
|
15366
15862
|
}
|
|
@@ -16242,7 +16738,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
16242
16738
|
currentPlayStep = step;
|
|
16243
16739
|
playbackState = "paused";
|
|
16244
16740
|
const canvas = getGridCanvas();
|
|
16245
|
-
currentOffsetX =
|
|
16741
|
+
currentOffsetX = clamp4(
|
|
16246
16742
|
step * renderConfig.stepWidth - canvas.width * 0.5,
|
|
16247
16743
|
0,
|
|
16248
16744
|
getMaxOffsetX()
|
|
@@ -16288,11 +16784,11 @@ var mountDAW = (target, options = {}) => {
|
|
|
16288
16784
|
getViewState,
|
|
16289
16785
|
setViewState: (state) => {
|
|
16290
16786
|
if (typeof state.zoomX === "number") {
|
|
16291
|
-
zoomX =
|
|
16787
|
+
zoomX = clamp4(state.zoomX, 25, 200);
|
|
16292
16788
|
applyZoomX();
|
|
16293
16789
|
}
|
|
16294
16790
|
if (typeof state.zoomY === "number") {
|
|
16295
|
-
zoomY =
|
|
16791
|
+
zoomY = clamp4(state.zoomY, 50, 200);
|
|
16296
16792
|
applyZoomY();
|
|
16297
16793
|
}
|
|
16298
16794
|
if (typeof state.decomposeChord === "boolean") {
|
|
@@ -16314,28 +16810,52 @@ var mountDAW = (target, options = {}) => {
|
|
|
16314
16810
|
forcePauseAt,
|
|
16315
16811
|
setLoading,
|
|
16316
16812
|
setMasterVolume: (volume) => {
|
|
16317
|
-
masterVolume =
|
|
16813
|
+
masterVolume = clamp4(volume, 0, 100);
|
|
16318
16814
|
refs.masterVolume.value = String(masterVolume);
|
|
16319
16815
|
refs.masterVolumeLabel.textContent = `${masterVolume}%`;
|
|
16320
16816
|
options.singingVoices?.setVolume(masterVolume / 100);
|
|
16321
16817
|
},
|
|
16322
16818
|
setVolume: (volume) => {
|
|
16323
|
-
masterVolume =
|
|
16819
|
+
masterVolume = clamp4(volume, 0, 100);
|
|
16324
16820
|
refs.masterVolume.value = String(masterVolume);
|
|
16325
16821
|
refs.masterVolumeLabel.textContent = `${masterVolume}%`;
|
|
16326
16822
|
options.singingVoices?.setVolume(masterVolume / 100);
|
|
16327
16823
|
},
|
|
16328
16824
|
setDrumVolume: (volume) => {
|
|
16329
|
-
drumVolume =
|
|
16825
|
+
drumVolume = clamp4(volume, 0, 100);
|
|
16330
16826
|
refs.drumVolume.value = String(drumVolume);
|
|
16331
16827
|
refs.drumVolumeLabel.textContent = `${drumVolume}%`;
|
|
16332
16828
|
},
|
|
16333
16829
|
setReverbAmount: (amount) => {
|
|
16334
|
-
reverbAmount =
|
|
16830
|
+
reverbAmount = clamp4(amount, 0, 100);
|
|
16335
16831
|
refs.reverbAmount.value = String(reverbAmount);
|
|
16336
16832
|
refs.reverbAmountLabel.textContent = `${reverbAmount}%`;
|
|
16337
16833
|
options.onReverbChange?.(reverbAmount);
|
|
16338
16834
|
},
|
|
16835
|
+
setReverbDecay: (seconds) => {
|
|
16836
|
+
reverbDecay = Math.max(
|
|
16837
|
+
MIN_REVERB_DECAY_SEC,
|
|
16838
|
+
Math.min(MAX_REVERB_DECAY_SEC, seconds)
|
|
16839
|
+
);
|
|
16840
|
+
refs.reverbDecay.value = String(Math.round(reverbDecay * 10));
|
|
16841
|
+
refs.reverbDecayLabel.textContent = `${reverbDecay.toFixed(1)}s`;
|
|
16842
|
+
options.onReverbDecayChange?.(reverbDecay);
|
|
16843
|
+
},
|
|
16844
|
+
setReverbPreDelay: (ms) => {
|
|
16845
|
+
reverbPreDelay = Math.max(
|
|
16846
|
+
MIN_REVERB_PREDELAY_MS,
|
|
16847
|
+
Math.min(MAX_REVERB_PREDELAY_MS, ms)
|
|
16848
|
+
);
|
|
16849
|
+
refs.reverbPreDelay.value = String(reverbPreDelay);
|
|
16850
|
+
refs.reverbPreDelayLabel.textContent = `${reverbPreDelay}ms`;
|
|
16851
|
+
options.onReverbPreDelayChange?.(reverbPreDelay);
|
|
16852
|
+
},
|
|
16853
|
+
setDelayAmount: (amount) => {
|
|
16854
|
+
delayAmount = clamp4(amount, 0, 100);
|
|
16855
|
+
refs.delayAmount.value = String(delayAmount);
|
|
16856
|
+
refs.delayAmountLabel.textContent = `${delayAmount}%`;
|
|
16857
|
+
options.onDelayChange?.(delayAmount);
|
|
16858
|
+
},
|
|
16339
16859
|
applyPatch: (trackId, added, removed) => {
|
|
16340
16860
|
const track = trackStates.find((t) => t.config.id === trackId);
|
|
16341
16861
|
if (!track) return;
|
|
@@ -16377,6 +16897,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
16377
16897
|
t.vocalOctave = data.vocalOctave;
|
|
16378
16898
|
t.vocalVibrato = data.vocalVibrato ?? false;
|
|
16379
16899
|
t.vocalReverb = data.vocalReverb ?? 0;
|
|
16900
|
+
t.vocalDelay = data.vocalDelay ?? 0;
|
|
16380
16901
|
t.vocalGender = data.vocalGender ?? 50;
|
|
16381
16902
|
t.vocalBreathiness = data.vocalBreathiness ?? 50;
|
|
16382
16903
|
},
|
|
@@ -16497,6 +17018,7 @@ var playSingingMML = async (mml, options = {}) => {
|
|
|
16497
17018
|
pan: panToStereo(lt.pan ?? DEFAULT_PAN),
|
|
16498
17019
|
vibrato: lt.vibrato,
|
|
16499
17020
|
reverbSend: (lt.reverb ?? 0) / 100,
|
|
17021
|
+
delaySend: (lt.delay ?? 0) / 100,
|
|
16500
17022
|
gender: (lt.gender ?? 50) / 100,
|
|
16501
17023
|
breathiness: (lt.breathiness ?? 50) / 100,
|
|
16502
17024
|
notes
|
|
@@ -17107,9 +17629,9 @@ var parseArrayBuffer = midiJsonParser.parseArrayBuffer;
|
|
|
17107
17629
|
URL.revokeObjectURL(url);
|
|
17108
17630
|
|
|
17109
17631
|
// src/channel-strip.ts
|
|
17110
|
-
var
|
|
17632
|
+
var clamp5 = (v, lo, hi) => Math.max(lo, Math.min(hi, v));
|
|
17111
17633
|
var compressionParams = (amount) => {
|
|
17112
|
-
const t =
|
|
17634
|
+
const t = clamp5(amount, 0, 100) / 100;
|
|
17113
17635
|
return {
|
|
17114
17636
|
threshold: 0 + (-24 - 0) * t,
|
|
17115
17637
|
ratio: 1 + (12 - 1) * t,
|
|
@@ -17118,8 +17640,29 @@ var compressionParams = (amount) => {
|
|
|
17118
17640
|
release: 0.25 + (0.15 - 0.25) * t
|
|
17119
17641
|
};
|
|
17120
17642
|
};
|
|
17643
|
+
var EQ_LOW_FREQ = 200;
|
|
17644
|
+
var EQ_MID_FREQ = 1e3;
|
|
17645
|
+
var EQ_HIGH_FREQ = 5e3;
|
|
17646
|
+
var EQ_MID_Q = 1;
|
|
17647
|
+
var EQ_MAX_DB = 12;
|
|
17121
17648
|
var createChannelStrip = (ctx, destination, options = {}) => {
|
|
17122
17649
|
const input = ctx.createGain();
|
|
17650
|
+
const eqLow = ctx.createBiquadFilter();
|
|
17651
|
+
eqLow.type = "lowshelf";
|
|
17652
|
+
eqLow.frequency.value = EQ_LOW_FREQ;
|
|
17653
|
+
eqLow.gain.value = clamp5(options.eqLow ?? 0, -EQ_MAX_DB, EQ_MAX_DB);
|
|
17654
|
+
const eqMid = ctx.createBiquadFilter();
|
|
17655
|
+
eqMid.type = "peaking";
|
|
17656
|
+
eqMid.frequency.value = EQ_MID_FREQ;
|
|
17657
|
+
eqMid.Q.value = EQ_MID_Q;
|
|
17658
|
+
eqMid.gain.value = clamp5(options.eqMid ?? 0, -EQ_MAX_DB, EQ_MAX_DB);
|
|
17659
|
+
const eqHigh = ctx.createBiquadFilter();
|
|
17660
|
+
eqHigh.type = "highshelf";
|
|
17661
|
+
eqHigh.frequency.value = EQ_HIGH_FREQ;
|
|
17662
|
+
eqHigh.gain.value = clamp5(options.eqHigh ?? 0, -EQ_MAX_DB, EQ_MAX_DB);
|
|
17663
|
+
input.connect(eqLow);
|
|
17664
|
+
eqLow.connect(eqMid);
|
|
17665
|
+
eqMid.connect(eqHigh);
|
|
17123
17666
|
const compressor = ctx.createDynamicsCompressor();
|
|
17124
17667
|
const applyCompression = (amount) => {
|
|
17125
17668
|
const p = compressionParams(amount);
|
|
@@ -17162,21 +17705,45 @@ var createChannelStrip = (ctx, destination, options = {}) => {
|
|
|
17162
17705
|
outR.connect(merger, 0, 1);
|
|
17163
17706
|
const setWidth = (width) => {
|
|
17164
17707
|
widthGain.gain.setTargetAtTime(
|
|
17165
|
-
|
|
17708
|
+
clamp5(width, 0, 200) / 100,
|
|
17166
17709
|
ctx.currentTime,
|
|
17167
17710
|
0.02
|
|
17168
17711
|
);
|
|
17169
17712
|
};
|
|
17170
17713
|
setWidth(options.width ?? 100);
|
|
17171
|
-
|
|
17714
|
+
eqHigh.connect(compressor);
|
|
17172
17715
|
compressor.connect(splitter);
|
|
17173
17716
|
merger.connect(destination);
|
|
17174
17717
|
return {
|
|
17175
17718
|
input,
|
|
17719
|
+
setEqLow: (db) => {
|
|
17720
|
+
eqLow.gain.setTargetAtTime(
|
|
17721
|
+
clamp5(db, -EQ_MAX_DB, EQ_MAX_DB),
|
|
17722
|
+
ctx.currentTime,
|
|
17723
|
+
0.02
|
|
17724
|
+
);
|
|
17725
|
+
},
|
|
17726
|
+
setEqMid: (db) => {
|
|
17727
|
+
eqMid.gain.setTargetAtTime(
|
|
17728
|
+
clamp5(db, -EQ_MAX_DB, EQ_MAX_DB),
|
|
17729
|
+
ctx.currentTime,
|
|
17730
|
+
0.02
|
|
17731
|
+
);
|
|
17732
|
+
},
|
|
17733
|
+
setEqHigh: (db) => {
|
|
17734
|
+
eqHigh.gain.setTargetAtTime(
|
|
17735
|
+
clamp5(db, -EQ_MAX_DB, EQ_MAX_DB),
|
|
17736
|
+
ctx.currentTime,
|
|
17737
|
+
0.02
|
|
17738
|
+
);
|
|
17739
|
+
},
|
|
17176
17740
|
setCompression: applyCompression,
|
|
17177
17741
|
setWidth,
|
|
17178
17742
|
dispose: () => {
|
|
17179
17743
|
input.disconnect();
|
|
17744
|
+
eqLow.disconnect();
|
|
17745
|
+
eqMid.disconnect();
|
|
17746
|
+
eqHigh.disconnect();
|
|
17180
17747
|
compressor.disconnect();
|
|
17181
17748
|
splitter.disconnect();
|
|
17182
17749
|
mid.disconnect();
|
|
@@ -17247,25 +17814,6 @@ var createClipMeter = (ctx, source, options = {}) => {
|
|
|
17247
17814
|
};
|
|
17248
17815
|
};
|
|
17249
17816
|
|
|
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
|
-
|
|
17269
17817
|
// src/sf/SoundFont_drum.ts
|
|
17270
17818
|
var touch = (map, key, ctor) => {
|
|
17271
17819
|
if (!map.has(key)) map.set(key, new ctor());
|
|
@@ -17420,12 +17968,16 @@ var createDtmStudio = async (options = {}) => {
|
|
|
17420
17968
|
const drumGain = audioCtx.createGain();
|
|
17421
17969
|
drumGain.gain.value = options.drumVolume ?? 1;
|
|
17422
17970
|
drumGain.connect(masterGain);
|
|
17971
|
+
let reverbDecaySec = options.reverbDecay ?? DEFAULT_REVERB_DECAY_SEC;
|
|
17972
|
+
const reverbPreDelay = audioCtx.createDelay(MAX_REVERB_PREDELAY_MS / 1e3);
|
|
17973
|
+
reverbPreDelay.delayTime.value = (options.reverbPreDelay ?? DEFAULT_REVERB_PREDELAY_MS) / 1e3;
|
|
17423
17974
|
const reverbConvolver = audioCtx.createConvolver();
|
|
17424
|
-
reverbConvolver.buffer = createReverbImpulse(audioCtx);
|
|
17975
|
+
reverbConvolver.buffer = createReverbImpulse(audioCtx, reverbDecaySec);
|
|
17425
17976
|
reverbConvolver.normalize = true;
|
|
17426
17977
|
const reverbWetGain = audioCtx.createGain();
|
|
17427
17978
|
reverbWetGain.gain.value = reverbAmountToGain(options.reverbAmount ?? 0);
|
|
17428
|
-
masterGain.connect(
|
|
17979
|
+
masterGain.connect(reverbPreDelay);
|
|
17980
|
+
reverbPreDelay.connect(reverbConvolver);
|
|
17429
17981
|
reverbConvolver.connect(reverbWetGain);
|
|
17430
17982
|
const setReverbAmount = (amount) => {
|
|
17431
17983
|
reverbWetGain.gain.setTargetAtTime(
|
|
@@ -17434,9 +17986,28 @@ var createDtmStudio = async (options = {}) => {
|
|
|
17434
17986
|
0.02
|
|
17435
17987
|
);
|
|
17436
17988
|
};
|
|
17989
|
+
const setReverbDecay = (seconds) => {
|
|
17990
|
+
reverbDecaySec = Math.max(
|
|
17991
|
+
MIN_REVERB_DECAY_SEC,
|
|
17992
|
+
Math.min(MAX_REVERB_DECAY_SEC, seconds)
|
|
17993
|
+
);
|
|
17994
|
+
reverbConvolver.buffer = createReverbImpulse(audioCtx, reverbDecaySec);
|
|
17995
|
+
};
|
|
17996
|
+
const setReverbPreDelay = (ms) => {
|
|
17997
|
+
reverbPreDelay.delayTime.setTargetAtTime(
|
|
17998
|
+
Math.max(MIN_REVERB_PREDELAY_MS, Math.min(MAX_REVERB_PREDELAY_MS, ms)) / 1e3,
|
|
17999
|
+
audioCtx.currentTime,
|
|
18000
|
+
0.02
|
|
18001
|
+
);
|
|
18002
|
+
};
|
|
17437
18003
|
const finalMix = audioCtx.createGain();
|
|
17438
18004
|
masterGain.connect(finalMix);
|
|
17439
18005
|
reverbWetGain.connect(finalMix);
|
|
18006
|
+
const delayBus = createDelayBus(audioCtx, finalMix, {
|
|
18007
|
+
amount: options.delayAmount ?? 0,
|
|
18008
|
+
division: options.delayDivision ?? "8"
|
|
18009
|
+
});
|
|
18010
|
+
const setDelayAmount = (amount) => delayBus.setAmount(amount);
|
|
17440
18011
|
const safetyLimiter = audioCtx.createDynamicsCompressor();
|
|
17441
18012
|
safetyLimiter.threshold.value = -1;
|
|
17442
18013
|
safetyLimiter.knee.value = 0;
|
|
@@ -17489,6 +18060,8 @@ var createDtmStudio = async (options = {}) => {
|
|
|
17489
18060
|
// ボーカルトラック個別のリバーブセンド(`r`トークン)先。マスタリバーブの
|
|
17490
18061
|
// Convolver 入力へ直接センドする(masterGain 経由のドライ段は素通り)。
|
|
17491
18062
|
reverbBus: reverbConvolver,
|
|
18063
|
+
// ボーカルトラック個別のディレイセンド(`e`トークン)先。
|
|
18064
|
+
delayBus: delayBus.input,
|
|
17492
18065
|
// トラック単位チャンネルストリップ(コンプレッサー/ステレオワイド)の入口。
|
|
17493
18066
|
// 楽器と同じ getChannelStrip キャッシュを共有するので、演奏トラックと歌詞トラックが
|
|
17494
18067
|
// 同じ trackId を指していれば同じ処理が掛かる。
|
|
@@ -17769,8 +18342,20 @@ var createDtmStudio = async (options = {}) => {
|
|
|
17769
18342
|
},
|
|
17770
18343
|
reverbAmount: options.reverbAmount,
|
|
17771
18344
|
onReverbChange: setReverbAmount,
|
|
18345
|
+
reverbDecay: options.reverbDecay,
|
|
18346
|
+
onReverbDecayChange: setReverbDecay,
|
|
18347
|
+
reverbPreDelay: options.reverbPreDelay,
|
|
18348
|
+
onReverbPreDelayChange: setReverbPreDelay,
|
|
18349
|
+
delayAmount: options.delayAmount,
|
|
18350
|
+
onDelayChange: setDelayAmount,
|
|
18351
|
+
delayDivision: options.delayDivision,
|
|
18352
|
+
onDelayDivisionChange: (division) => delayBus.setDivision(division),
|
|
18353
|
+
onBpmChange: (bpm) => delayBus.setBpm(bpm),
|
|
17772
18354
|
onTrackCompressionChange: (trackId, amount) => getChannelStrip(trackId).setCompression(amount),
|
|
17773
18355
|
onTrackWidthChange: (trackId, width) => getChannelStrip(trackId).setWidth(width),
|
|
18356
|
+
onTrackEqLowChange: (trackId, db) => getChannelStrip(trackId).setEqLow(db),
|
|
18357
|
+
onTrackEqMidChange: (trackId, db) => getChannelStrip(trackId).setEqMid(db),
|
|
18358
|
+
onTrackEqHighChange: (trackId, db) => getChannelStrip(trackId).setEqHigh(db),
|
|
17774
18359
|
clipMeter,
|
|
17775
18360
|
...dawOverrides,
|
|
17776
18361
|
// dawOverrides で上書きされないよう、スプレッドの後に配置して合成する
|
|
@@ -18307,6 +18892,7 @@ var createDtmStudio = async (options = {}) => {
|
|
|
18307
18892
|
mountedChordPlayers.length = 0;
|
|
18308
18893
|
mountedEditors.length = 0;
|
|
18309
18894
|
clipMeter.dispose();
|
|
18895
|
+
delayBus.dispose();
|
|
18310
18896
|
for (const strip of channelStrips.values()) strip.dispose();
|
|
18311
18897
|
channelStrips.clear();
|
|
18312
18898
|
void audioCtx.close();
|
|
@@ -18348,6 +18934,9 @@ var createDtmStudio = async (options = {}) => {
|
|
|
18348
18934
|
setMasterVolume,
|
|
18349
18935
|
setVolume: setMasterVolume,
|
|
18350
18936
|
setReverbAmount,
|
|
18937
|
+
setReverbDecay,
|
|
18938
|
+
setReverbPreDelay,
|
|
18939
|
+
setDelayAmount,
|
|
18351
18940
|
dispose
|
|
18352
18941
|
};
|
|
18353
18942
|
};
|