@onjmin/dtm 0.1.89 → 0.1.91
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 +14 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +149 -12
- package/dist/index.mjs +149 -12
- package/dist/voice-worker.js +77 -4
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -297,6 +297,8 @@ type VoiceExpression = {
|
|
|
297
297
|
gender?: number;
|
|
298
298
|
/** ブレシネス(息成分)。大きいほど息っぽく(ささやき寄り)。 */
|
|
299
299
|
breathiness?: number;
|
|
300
|
+
/** テンション(張り/力強さ)。大きいほど張った・押した声(こぶし寄り、力強く歌う)。 */
|
|
301
|
+
tension?: number;
|
|
300
302
|
};
|
|
301
303
|
/** 歌唱合成モデルの実装シグネチャ */
|
|
302
304
|
type VoiceModel = {
|
|
@@ -456,6 +458,11 @@ type StreamVoiceTrack = {
|
|
|
456
458
|
* — klattフォールバックには効かない。
|
|
457
459
|
*/
|
|
458
460
|
breathiness?: number;
|
|
461
|
+
/**
|
|
462
|
+
* テンション(張り/力強さ、"こぶし"寄り)0-1。既定0.5(無変化)。koe音源(Worldline)限定
|
|
463
|
+
* — klattフォールバックには効かない。
|
|
464
|
+
*/
|
|
465
|
+
tension?: number;
|
|
459
466
|
/**
|
|
460
467
|
* オクターブユニゾン。各音節をもう1声、1オクターブ上/下(控えめな音量)で重ねて発音し、
|
|
461
468
|
* 声に厚み(下)または煌びやかさ(上)を足す。既定 "none"(重ねない)。
|
|
@@ -680,6 +687,7 @@ type LyricSyncData = {
|
|
|
680
687
|
vocalDelay?: number;
|
|
681
688
|
vocalGender?: number;
|
|
682
689
|
vocalBreathiness?: number;
|
|
690
|
+
vocalTension?: number;
|
|
683
691
|
vocalOctaveUnison?: OctaveUnisonMode;
|
|
684
692
|
};
|
|
685
693
|
/** パッチ送受信用ノートデータ(ローカルIDを持たない)。 */
|
|
@@ -854,6 +862,12 @@ type LyricTrack = {
|
|
|
854
862
|
* MMLでは `@@n klatt h70 …` のように h トークンで付与する。
|
|
855
863
|
*/
|
|
856
864
|
breathiness?: number;
|
|
865
|
+
/**
|
|
866
|
+
* テンション(張り/力強さ)0-100。既定50(無変化)。大きいほど張った・押した声
|
|
867
|
+
* (こぶし寄り、力強く歌わせる)、小さいほど脱力・リラックス(ブレシネス寄り)になる。
|
|
868
|
+
* MMLでは `@@n klatt t70 …` のように t トークンで付与する。
|
|
869
|
+
*/
|
|
870
|
+
tension?: number;
|
|
857
871
|
/**
|
|
858
872
|
* オクターブユニゾン。既定"none"。
|
|
859
873
|
* "down"/"up"/"both" にすると各音節をもう1オクターブ上/下/両方(控えめな音量)で
|
package/dist/index.d.ts
CHANGED
|
@@ -297,6 +297,8 @@ type VoiceExpression = {
|
|
|
297
297
|
gender?: number;
|
|
298
298
|
/** ブレシネス(息成分)。大きいほど息っぽく(ささやき寄り)。 */
|
|
299
299
|
breathiness?: number;
|
|
300
|
+
/** テンション(張り/力強さ)。大きいほど張った・押した声(こぶし寄り、力強く歌う)。 */
|
|
301
|
+
tension?: number;
|
|
300
302
|
};
|
|
301
303
|
/** 歌唱合成モデルの実装シグネチャ */
|
|
302
304
|
type VoiceModel = {
|
|
@@ -456,6 +458,11 @@ type StreamVoiceTrack = {
|
|
|
456
458
|
* — klattフォールバックには効かない。
|
|
457
459
|
*/
|
|
458
460
|
breathiness?: number;
|
|
461
|
+
/**
|
|
462
|
+
* テンション(張り/力強さ、"こぶし"寄り)0-1。既定0.5(無変化)。koe音源(Worldline)限定
|
|
463
|
+
* — klattフォールバックには効かない。
|
|
464
|
+
*/
|
|
465
|
+
tension?: number;
|
|
459
466
|
/**
|
|
460
467
|
* オクターブユニゾン。各音節をもう1声、1オクターブ上/下(控えめな音量)で重ねて発音し、
|
|
461
468
|
* 声に厚み(下)または煌びやかさ(上)を足す。既定 "none"(重ねない)。
|
|
@@ -680,6 +687,7 @@ type LyricSyncData = {
|
|
|
680
687
|
vocalDelay?: number;
|
|
681
688
|
vocalGender?: number;
|
|
682
689
|
vocalBreathiness?: number;
|
|
690
|
+
vocalTension?: number;
|
|
683
691
|
vocalOctaveUnison?: OctaveUnisonMode;
|
|
684
692
|
};
|
|
685
693
|
/** パッチ送受信用ノートデータ(ローカルIDを持たない)。 */
|
|
@@ -854,6 +862,12 @@ type LyricTrack = {
|
|
|
854
862
|
* MMLでは `@@n klatt h70 …` のように h トークンで付与する。
|
|
855
863
|
*/
|
|
856
864
|
breathiness?: number;
|
|
865
|
+
/**
|
|
866
|
+
* テンション(張り/力強さ)0-100。既定50(無変化)。大きいほど張った・押した声
|
|
867
|
+
* (こぶし寄り、力強く歌わせる)、小さいほど脱力・リラックス(ブレシネス寄り)になる。
|
|
868
|
+
* MMLでは `@@n klatt t70 …` のように t トークンで付与する。
|
|
869
|
+
*/
|
|
870
|
+
tension?: number;
|
|
857
871
|
/**
|
|
858
872
|
* オクターブユニゾン。既定"none"。
|
|
859
873
|
* "down"/"up"/"both" にすると各音節をもう1オクターブ上/下/両方(控えめな音量)で
|
package/dist/index.js
CHANGED
|
@@ -2285,6 +2285,15 @@ var vibratoPitchCurve = (baseHz, preMs) => (tMs) => {
|
|
|
2285
2285
|
return baseHz * 2 ** (cents / 1200);
|
|
2286
2286
|
};
|
|
2287
2287
|
|
|
2288
|
+
// src/voice-worker-types.ts
|
|
2289
|
+
var COMPOSITE_ALIAS_SEP = "\0";
|
|
2290
|
+
var packCompositeAlias = (consonantAlias, vowelAlias) => `${COMPOSITE_ALIAS_SEP}${consonantAlias}${COMPOSITE_ALIAS_SEP}${vowelAlias}`;
|
|
2291
|
+
var unpackCompositeAlias = (alias) => {
|
|
2292
|
+
if (!alias.startsWith(COMPOSITE_ALIAS_SEP)) return null;
|
|
2293
|
+
const parts = alias.slice(COMPOSITE_ALIAS_SEP.length).split(COMPOSITE_ALIAS_SEP);
|
|
2294
|
+
return parts.length === 2 ? [parts[0], parts[1]] : null;
|
|
2295
|
+
};
|
|
2296
|
+
|
|
2288
2297
|
// src/lyrics.ts
|
|
2289
2298
|
var kanaTable = {
|
|
2290
2299
|
\u3042: ["", "a"],
|
|
@@ -2463,9 +2472,10 @@ var parseLyrics = (mml) => {
|
|
|
2463
2472
|
let delay = 0;
|
|
2464
2473
|
let gender = 50;
|
|
2465
2474
|
let breathiness = 50;
|
|
2475
|
+
let tension = 50;
|
|
2466
2476
|
let octaveUnison = "none";
|
|
2467
2477
|
const modelMatch = rest.match(
|
|
2468
|
-
/^([a-z_][a-z0-9_]*?)(?=(?:[
|
|
2478
|
+
/^([a-z_][a-z0-9_]*?)(?=(?:[vqpobrghewt]-?\d)|[^a-z0-9_]|$)(?::(\d+))?/i
|
|
2469
2479
|
);
|
|
2470
2480
|
let model = "";
|
|
2471
2481
|
const metaTokens = [];
|
|
@@ -2534,6 +2544,13 @@ var parseLyrics = (mml) => {
|
|
|
2534
2544
|
rest = rest.substring(hMatch[0].length).trim();
|
|
2535
2545
|
continue;
|
|
2536
2546
|
}
|
|
2547
|
+
const tMatch = rest.match(/^t(\d+)/i);
|
|
2548
|
+
if (tMatch) {
|
|
2549
|
+
tension = clamp2(Number.parseInt(tMatch[1], 10), 0, 100);
|
|
2550
|
+
metaTokens.push(tMatch[0]);
|
|
2551
|
+
rest = rest.substring(tMatch[0].length).trim();
|
|
2552
|
+
continue;
|
|
2553
|
+
}
|
|
2537
2554
|
const eMatch = rest.match(/^e(\d+)/i);
|
|
2538
2555
|
if (eMatch) {
|
|
2539
2556
|
delay = clamp2(Number.parseInt(eMatch[1], 10), 0, 100);
|
|
@@ -2567,6 +2584,7 @@ var parseLyrics = (mml) => {
|
|
|
2567
2584
|
delay,
|
|
2568
2585
|
gender,
|
|
2569
2586
|
breathiness,
|
|
2587
|
+
tension,
|
|
2570
2588
|
octaveUnison,
|
|
2571
2589
|
syllables,
|
|
2572
2590
|
metaText: metaTokens.join(" "),
|
|
@@ -2888,8 +2906,33 @@ var resolveKoeAlias = (hasAlias, pitchTokens, syl, prevVowel, noteNum) => {
|
|
|
2888
2906
|
const hit = tryAlias(base);
|
|
2889
2907
|
if (hit) return hit;
|
|
2890
2908
|
}
|
|
2909
|
+
if (cons && vow) {
|
|
2910
|
+
const vowelAlias = tryAlias(vow) ?? tryAlias(`${pv} ${vow}`);
|
|
2911
|
+
const consAlias = vowelAlias ? tryAlias(cons) : null;
|
|
2912
|
+
if (vowelAlias && consAlias)
|
|
2913
|
+
return packCompositeAlias(consAlias, vowelAlias);
|
|
2914
|
+
}
|
|
2891
2915
|
return null;
|
|
2892
2916
|
};
|
|
2917
|
+
var COMPOSITE_SPLICE_XFADE_SEC = 5e-3;
|
|
2918
|
+
var spliceCompositePcm = (consonantPcm, vowelPcm, sampleRate) => {
|
|
2919
|
+
if (consonantPcm.length === 0 || vowelPcm.length === 0) return null;
|
|
2920
|
+
const xfade = Math.min(
|
|
2921
|
+
Math.floor(sampleRate * COMPOSITE_SPLICE_XFADE_SEC),
|
|
2922
|
+
consonantPcm.length,
|
|
2923
|
+
vowelPcm.length
|
|
2924
|
+
);
|
|
2925
|
+
const pcm = new Float64Array(consonantPcm.length + vowelPcm.length - xfade);
|
|
2926
|
+
pcm.set(consonantPcm, 0);
|
|
2927
|
+
for (let i2 = 0; i2 < xfade; i2++) {
|
|
2928
|
+
const t = (i2 + 1) / (xfade + 1);
|
|
2929
|
+
const idx = consonantPcm.length - xfade + i2;
|
|
2930
|
+
pcm[idx] = consonantPcm[idx] * (1 - t) + vowelPcm[i2] * t;
|
|
2931
|
+
}
|
|
2932
|
+
pcm.set(vowelPcm.subarray(xfade), consonantPcm.length);
|
|
2933
|
+
const consonantMs = (consonantPcm.length - xfade / 2) / sampleRate * 1e3;
|
|
2934
|
+
return { pcm, preMs: consonantMs, consonantMs };
|
|
2935
|
+
};
|
|
2893
2936
|
var createLocalBackend = async (options) => {
|
|
2894
2937
|
const bank = await VoiceBank.load(options.koe);
|
|
2895
2938
|
const worldline = options.lightweight ? null : await Worldline.load({
|
|
@@ -2904,7 +2947,40 @@ var createLocalBackend = async (options) => {
|
|
|
2904
2947
|
}
|
|
2905
2948
|
return p;
|
|
2906
2949
|
};
|
|
2950
|
+
const renderComposite = async (consonantAlias, vowelAlias, pitch, durationMs, vibrato, expr) => {
|
|
2951
|
+
if (!worldline) return null;
|
|
2952
|
+
const [consonantPcm, vowelPcm] = await Promise.all([
|
|
2953
|
+
getPcm(consonantAlias),
|
|
2954
|
+
getPcm(vowelAlias)
|
|
2955
|
+
]);
|
|
2956
|
+
if (!consonantPcm || !vowelPcm) return null;
|
|
2957
|
+
const spliced = spliceCompositePcm(consonantPcm, vowelPcm, KOE_SAMPLE_RATE);
|
|
2958
|
+
if (!spliced) return null;
|
|
2959
|
+
const targetHz = midiToFreq(pitch);
|
|
2960
|
+
const audio = worldline.renderNote({
|
|
2961
|
+
pcm: spliced.pcm,
|
|
2962
|
+
pitch: vibrato ? vibratoPitchCurve(targetHz, spliced.preMs) : targetHz,
|
|
2963
|
+
durationMs,
|
|
2964
|
+
preMs: spliced.preMs,
|
|
2965
|
+
consonantMs: spliced.consonantMs,
|
|
2966
|
+
gender: expr?.gender,
|
|
2967
|
+
breathiness: expr?.breathiness,
|
|
2968
|
+
tension: expr?.tension
|
|
2969
|
+
});
|
|
2970
|
+
return audio ? { pcm: audio, preSec: spliced.preMs / 1e3, rate: 1 } : null;
|
|
2971
|
+
};
|
|
2907
2972
|
const renderAlias = async (alias, pitch, durationMs, vibrato, expr) => {
|
|
2973
|
+
const composite = unpackCompositeAlias(alias);
|
|
2974
|
+
if (composite) {
|
|
2975
|
+
return renderComposite(
|
|
2976
|
+
composite[0],
|
|
2977
|
+
composite[1],
|
|
2978
|
+
pitch,
|
|
2979
|
+
durationMs,
|
|
2980
|
+
vibrato,
|
|
2981
|
+
expr
|
|
2982
|
+
);
|
|
2983
|
+
}
|
|
2908
2984
|
const pcm = await getPcm(alias);
|
|
2909
2985
|
if (!pcm || pcm.length === 0) return null;
|
|
2910
2986
|
const entry = bank.manifest.phonemes[alias];
|
|
@@ -2917,7 +2993,8 @@ var createLocalBackend = async (options) => {
|
|
|
2917
2993
|
durationMs,
|
|
2918
2994
|
...lead,
|
|
2919
2995
|
gender: expr?.gender,
|
|
2920
|
-
breathiness: expr?.breathiness
|
|
2996
|
+
breathiness: expr?.breathiness,
|
|
2997
|
+
tension: expr?.tension
|
|
2921
2998
|
});
|
|
2922
2999
|
if (audio) return { pcm: audio, preSec: lead.preMs / 1e3, rate: 1 };
|
|
2923
3000
|
}
|
|
@@ -2998,7 +3075,8 @@ var createWorkerBackend = async (workerUrl, options) => {
|
|
|
2998
3075
|
durationMs,
|
|
2999
3076
|
vibrato,
|
|
3000
3077
|
gender: expr?.gender,
|
|
3001
|
-
breathiness: expr?.breathiness
|
|
3078
|
+
breathiness: expr?.breathiness,
|
|
3079
|
+
tension: expr?.tension
|
|
3002
3080
|
});
|
|
3003
3081
|
});
|
|
3004
3082
|
return {
|
|
@@ -3027,7 +3105,7 @@ var createKoeVoice = async (ctx, destination, options) => {
|
|
|
3027
3105
|
const inflight = /* @__PURE__ */ new Map();
|
|
3028
3106
|
const active = /* @__PURE__ */ new Set();
|
|
3029
3107
|
let prevVowel = "";
|
|
3030
|
-
const keyOf = (alias, pitch, durationMs, vibrato, expr) => `${alias}|${pitch}|${Math.round(durationMs / 10) * 10}${vibrato ? "|vib" : ""}${expr?.gender !== void 0 ? `|g${Math.round(expr.gender * 100)}` : ""}${expr?.breathiness !== void 0 ? `|h${Math.round(expr.breathiness * 100)}` : ""}`;
|
|
3108
|
+
const keyOf = (alias, pitch, durationMs, vibrato, expr) => `${alias}|${pitch}|${Math.round(durationMs / 10) * 10}${vibrato ? "|vib" : ""}${expr?.gender !== void 0 ? `|g${Math.round(expr.gender * 100)}` : ""}${expr?.breathiness !== void 0 ? `|h${Math.round(expr.breathiness * 100)}` : ""}${expr?.tension !== void 0 ? `|t${Math.round(expr.tension * 100)}` : ""}`;
|
|
3031
3109
|
const renderInto = (alias, pitch, durationMs, vibrato, expr) => {
|
|
3032
3110
|
const key = keyOf(alias, pitch, durationMs, vibrato, expr);
|
|
3033
3111
|
const existing = renderCache.get(key);
|
|
@@ -3258,7 +3336,8 @@ var createSingingVoices = (ctx, destination, options = {}) => {
|
|
|
3258
3336
|
let n = 0;
|
|
3259
3337
|
const expr = {
|
|
3260
3338
|
gender: track.gender,
|
|
3261
|
-
breathiness: track.breathiness
|
|
3339
|
+
breathiness: track.breathiness,
|
|
3340
|
+
tension: track.tension
|
|
3262
3341
|
};
|
|
3263
3342
|
forEachSungNote(track, (note, prevVowel) => {
|
|
3264
3343
|
if (n >= count && note.startSec >= STREAM_LOOKAHEAD_SEC) return;
|
|
@@ -3345,7 +3424,11 @@ var createSingingVoices = (ctx, destination, options = {}) => {
|
|
|
3345
3424
|
pitch,
|
|
3346
3425
|
note.durationSec * 1e3,
|
|
3347
3426
|
track.vibrato,
|
|
3348
|
-
{
|
|
3427
|
+
{
|
|
3428
|
+
gender: track.gender,
|
|
3429
|
+
breathiness: track.breathiness,
|
|
3430
|
+
tension: track.tension
|
|
3431
|
+
}
|
|
3349
3432
|
);
|
|
3350
3433
|
if (session !== streamSession) return;
|
|
3351
3434
|
if (key) {
|
|
@@ -3879,8 +3962,7 @@ var createReverbImpulse = (ctx, decaySec = DEFAULT_REVERB_DECAY_SEC) => {
|
|
|
3879
3962
|
}
|
|
3880
3963
|
return impulse;
|
|
3881
3964
|
};
|
|
3882
|
-
var
|
|
3883
|
-
var reverbAmountToGain = (amount) => Math.max(0, Math.min(100, amount)) / 100 * REVERB_MAX_WET;
|
|
3965
|
+
var reverbAmountToGain = (amount) => Math.max(0, Math.min(100, amount)) / 100;
|
|
3884
3966
|
|
|
3885
3967
|
// src/sequencer.ts
|
|
3886
3968
|
var STEPS_PER_BEAT = 48;
|
|
@@ -9573,6 +9655,7 @@ var mountMmlPlayer = (target, mml, options = {}) => {
|
|
|
9573
9655
|
delaySend: (lt.delay ?? 0) / 100,
|
|
9574
9656
|
gender: (lt.gender ?? 50) / 100,
|
|
9575
9657
|
breathiness: (lt.breathiness ?? 50) / 100,
|
|
9658
|
+
tension: (lt.tension ?? 50) / 100,
|
|
9576
9659
|
octaveUnison: lt.octaveUnison,
|
|
9577
9660
|
notes
|
|
9578
9661
|
};
|
|
@@ -13423,6 +13506,16 @@ var BREATHINESS_INFO_HTML = `
|
|
|
13423
13506
|
<p>\u81EA\u52D5\u30D3\u30D6\u30E9\u30FC\u30C8\u3068\u7D44\u307F\u5408\u308F\u305B\u308B\u3068\u3001\u63FA\u308C\u306A\u304C\u3089\u606F\u3063\u307D\u3044\u3001\u3088\u308A\u30A8\u30E2\u30FC\u30B7\u30E7\u30CA\u30EB\u306A\u8868\u73FE\u306B\u306A\u308A\u3084\u3059\u3044\u3067\u3059\u3002koe\u97F3\u6E90\uFF08UTAU\u7531\u6765\u306E.koe\u97F3\u6E90\uFF09\u9650\u5B9A\u306E\u52B9\u679C\u3067\u3001klatt\uFF08\u5185\u8535\u306E\u7C21\u6613\u5408\u6210\uFF09\u3067\u306F\u5909\u5316\u3057\u307E\u305B\u3093\u3002</p>
|
|
13424
13507
|
</div>
|
|
13425
13508
|
`;
|
|
13509
|
+
var TENSION_INFO_HTML = `
|
|
13510
|
+
<div class="dtm-modal-body-content">
|
|
13511
|
+
<h4>\u4F55\u3092\u3059\u308B\u8A2D\u5B9A\u304B</h4>
|
|
13512
|
+
<p>\u58F0\u306E\u5F35\u308A\uFF0F\u62BC\u3057\u51FA\u3057\u306E\u5F37\u3055\u3067\u3059\u300250\u304C\u7121\u5909\u5316\u3001\u5927\u304D\u3044\u307B\u3069\u5F35\u3063\u305F\u30FB\u62BC\u3057\u305F\u58F0\uFF08\u300C\u3053\u3076\u3057\u300D\u5BC4\u308A\u3001\u529B\u5F37\u304F\u6B4C\u308F\u305B\u308B\uFF09\u306B\u306A\u308A\u3001\u5C0F\u3055\u3044\u307B\u3069\u8131\u529B\u3057\u305F\u30EA\u30E9\u30C3\u30AF\u30B9\u3057\u305F\u58F0\u306B\u306A\u308A\u307E\u3059\u3002</p>
|
|
13513
|
+
<h4>\u30D6\u30EC\u30B7\u30CD\u30B9\u3068\u306E\u9055\u3044</h4>
|
|
13514
|
+
<p>\u30D6\u30EC\u30B7\u30CD\u30B9\u306F\u606F\u6210\u5206\u306E\u91CF\uFF08\u82AF\u306E\u3042\u308B\u58F0\u21D4\u606F\u3063\u307D\u3044\u58F0\uFF09\u3092\u52D5\u304B\u3057\u307E\u3059\u304C\u3001\u30C6\u30F3\u30B7\u30E7\u30F3\u306F\u58F0\u5E2F\u306E\u7DE0\u307E\u308A\u30FB\u62BC\u3057\u306E\u5F37\u3055\uFF08\u8131\u529B\u21D4\u5F35\u3063\u305F\u58F0\uFF09\u3092\u52D5\u304B\u3057\u307E\u3059\u3002\u30C6\u30F3\u30B7\u30E7\u30F3\u3092\u4E0A\u3052\u308B\u3068\u30B5\u30D3\u306E\u529B\u5F37\u3055\u3001\u4E0B\u3052\u308B\u3068\u7A4F\u3084\u304B\u306A\u56C1\u304D\u306B\u5BC4\u305B\u305F\u6B4C\u308F\u305B\u65B9\u306B\u306A\u308A\u307E\u3059\u3002</p>
|
|
13515
|
+
<h4>\u4ED6\u306E\u8A2D\u5B9A\u3068\u306E\u517C\u306D\u5408\u3044</h4>
|
|
13516
|
+
<p>\u30D6\u30EC\u30B7\u30CD\u30B9\u3092\u4E0B\u3052\u3064\u3064\u30C6\u30F3\u30B7\u30E7\u30F3\u3092\u4E0A\u3052\u308B\u3068\u3001\u3088\u308A\u82AF\u304C\u3042\u308A\u529B\u5F37\u3044\u6B4C\u58F0\u306B\u306A\u308A\u307E\u3059\u3002\u9006\u306B\u30D6\u30EC\u30B7\u30CD\u30B9\u3092\u4E0A\u3052\u3064\u3064\u30C6\u30F3\u30B7\u30E7\u30F3\u3092\u4E0B\u3052\u308B\u3068\u3001\u3088\u308A\u8131\u529B\u3057\u305F\u606F\u3063\u307D\u3044\u6B4C\u58F0\u306B\u306A\u308A\u307E\u3059\u3002koe\u97F3\u6E90\uFF08UTAU\u7531\u6765\u306E.koe\u97F3\u6E90\uFF09\u9650\u5B9A\u306E\u52B9\u679C\u3067\u3001klatt\uFF08\u5185\u8535\u306E\u7C21\u6613\u5408\u6210\uFF09\u3067\u306F\u5909\u5316\u3057\u307E\u305B\u3093\u3002</p>
|
|
13517
|
+
</div>
|
|
13518
|
+
`;
|
|
13426
13519
|
var LYRIC_REVERB_INFO_HTML = `
|
|
13427
13520
|
<div class="dtm-modal-body-content">
|
|
13428
13521
|
<h4>\u4F55\u3092\u3059\u308B\u8A2D\u5B9A\u304B</h4>
|
|
@@ -13947,6 +14040,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
13947
14040
|
vocalDelay: t.vocalDelay,
|
|
13948
14041
|
vocalGender: t.vocalGender,
|
|
13949
14042
|
vocalBreathiness: t.vocalBreathiness,
|
|
14043
|
+
vocalTension: t.vocalTension,
|
|
13950
14044
|
vocalOctaveUnison: t.vocalOctaveUnison
|
|
13951
14045
|
};
|
|
13952
14046
|
if (lyricsDebounceTimer) clearTimeout(lyricsDebounceTimer);
|
|
@@ -14012,6 +14106,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
14012
14106
|
vocalDelay: 0,
|
|
14013
14107
|
vocalGender: 50,
|
|
14014
14108
|
vocalBreathiness: 50,
|
|
14109
|
+
vocalTension: 50,
|
|
14015
14110
|
vocalOctaveUnison: "none",
|
|
14016
14111
|
trackInstrument: "",
|
|
14017
14112
|
trackCompression: 0,
|
|
@@ -14043,6 +14138,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
14043
14138
|
delay: t.vocalDelay,
|
|
14044
14139
|
gender: t.vocalGender,
|
|
14045
14140
|
breathiness: t.vocalBreathiness,
|
|
14141
|
+
tension: t.vocalTension,
|
|
14046
14142
|
octaveUnison: t.vocalOctaveUnison,
|
|
14047
14143
|
syllables
|
|
14048
14144
|
});
|
|
@@ -14853,6 +14949,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
14853
14949
|
delaySend: (lt.delay ?? 0) / 100,
|
|
14854
14950
|
gender: (lt.gender ?? 50) / 100,
|
|
14855
14951
|
breathiness: (lt.breathiness ?? 50) / 100,
|
|
14952
|
+
tension: (lt.tension ?? 50) / 100,
|
|
14856
14953
|
octaveUnison: lt.octaveUnison,
|
|
14857
14954
|
notes
|
|
14858
14955
|
};
|
|
@@ -15281,6 +15378,12 @@ var mountDAW = (target, options = {}) => {
|
|
|
15281
15378
|
<span class="dtm-label" data-dtm="lyric-breathiness-label"></span>
|
|
15282
15379
|
<button class="dtm-infobtn" data-dtm="lyric-breathiness-info" title="\u30D6\u30EC\u30B7\u30CD\u30B9\u306E\u89E3\u8AAC">${icon("info", 12)}</button>
|
|
15283
15380
|
</div>
|
|
15381
|
+
<div class="dtm-row">
|
|
15382
|
+
<span class="dtm-label">\u30C6\u30F3\u30B7\u30E7\u30F3</span>
|
|
15383
|
+
<input type="range" class="dtm-range dtm-grow" data-dtm="lyric-tension" min="0" max="100" aria-label="\u30C6\u30F3\u30B7\u30E7\u30F3\uFF08\u5F35\u308A/\u529B\u5F37\u3055\u3001koe\u97F3\u6E90\u9650\u5B9A\uFF09">
|
|
15384
|
+
<span class="dtm-label" data-dtm="lyric-tension-label"></span>
|
|
15385
|
+
<button class="dtm-infobtn" data-dtm="lyric-tension-info" title="\u30C6\u30F3\u30B7\u30E7\u30F3\u306E\u89E3\u8AAC">${icon("info", 12)}</button>
|
|
15386
|
+
</div>
|
|
15284
15387
|
<div class="dtm-row">
|
|
15285
15388
|
<span class="dtm-label" style="display:inline-flex;align-items:center;gap:2px">
|
|
15286
15389
|
<input type="checkbox" data-dtm="lyric-vibrato" aria-label="\u81EA\u52D5\u30D3\u30D6\u30E9\u30FC\u30C8">\u30D3\u30D6\u30E9\u30FC\u30C8
|
|
@@ -15384,6 +15487,18 @@ var mountDAW = (target, options = {}) => {
|
|
|
15384
15487
|
lyricBreathinessInfo.addEventListener("click", () => {
|
|
15385
15488
|
showModal("\u30D6\u30EC\u30B7\u30CD\u30B9\u306E\u89E3\u8AAC", BREATHINESS_INFO_HTML);
|
|
15386
15489
|
});
|
|
15490
|
+
const lyricTension = lyricDiv.querySelector(
|
|
15491
|
+
'[data-dtm="lyric-tension"]'
|
|
15492
|
+
);
|
|
15493
|
+
const lyricTensionLabel = lyricDiv.querySelector(
|
|
15494
|
+
'[data-dtm="lyric-tension-label"]'
|
|
15495
|
+
);
|
|
15496
|
+
const lyricTensionInfo = lyricDiv.querySelector(
|
|
15497
|
+
'[data-dtm="lyric-tension-info"]'
|
|
15498
|
+
);
|
|
15499
|
+
lyricTensionInfo.addEventListener("click", () => {
|
|
15500
|
+
showModal("\u30C6\u30F3\u30B7\u30E7\u30F3\u306E\u89E3\u8AAC", TENSION_INFO_HTML);
|
|
15501
|
+
});
|
|
15387
15502
|
const lyricVibrato = lyricDiv.querySelector(
|
|
15388
15503
|
'[data-dtm="lyric-vibrato"]'
|
|
15389
15504
|
);
|
|
@@ -15471,6 +15586,8 @@ var mountDAW = (target, options = {}) => {
|
|
|
15471
15586
|
lyricGenderLabel.textContent = `${active.vocalGender}`;
|
|
15472
15587
|
lyricBreathiness.value = String(active.vocalBreathiness);
|
|
15473
15588
|
lyricBreathinessLabel.textContent = `${active.vocalBreathiness}`;
|
|
15589
|
+
lyricTension.value = String(active.vocalTension);
|
|
15590
|
+
lyricTensionLabel.textContent = `${active.vocalTension}`;
|
|
15474
15591
|
lyricVibrato.checked = active.vocalVibrato;
|
|
15475
15592
|
lyricOctaveUnison.value = active.vocalOctaveUnison;
|
|
15476
15593
|
const updateLyricCount = () => {
|
|
@@ -15641,6 +15758,11 @@ var mountDAW = (target, options = {}) => {
|
|
|
15641
15758
|
lyricBreathinessLabel.textContent = `${active.vocalBreathiness}`;
|
|
15642
15759
|
fireLyricsChange(active);
|
|
15643
15760
|
});
|
|
15761
|
+
lyricTension.addEventListener("input", () => {
|
|
15762
|
+
active.vocalTension = Number.parseInt(lyricTension.value, 10);
|
|
15763
|
+
lyricTensionLabel.textContent = `${active.vocalTension}`;
|
|
15764
|
+
fireLyricsChange(active);
|
|
15765
|
+
});
|
|
15644
15766
|
}
|
|
15645
15767
|
if (active.config.id === "chord" && showChord) {
|
|
15646
15768
|
const div = document.createElement("div");
|
|
@@ -15845,6 +15967,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
15845
15967
|
del: t.vocalDelay,
|
|
15846
15968
|
gen: t.vocalGender,
|
|
15847
15969
|
bre: t.vocalBreathiness,
|
|
15970
|
+
ten: t.vocalTension,
|
|
15848
15971
|
uni: t.vocalOctaveUnison
|
|
15849
15972
|
})).filter(
|
|
15850
15973
|
(x2) => x2.model.length > 0 && x2.text.length > 0 && x2.notes.length > 0
|
|
@@ -15859,6 +15982,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
15859
15982
|
x2.del === 0 ? "" : `e${x2.del}`,
|
|
15860
15983
|
x2.gen === 50 ? "" : `g${x2.gen}`,
|
|
15861
15984
|
x2.bre === 50 ? "" : `h${x2.bre}`,
|
|
15985
|
+
x2.ten === 50 ? "" : `t${x2.ten}`,
|
|
15862
15986
|
OCTAVE_UNISON_TOKEN[x2.uni]
|
|
15863
15987
|
].filter((s) => s.length > 0).join(" ");
|
|
15864
15988
|
const head = params ? `${x2.model} ${params}` : x2.model;
|
|
@@ -16101,6 +16225,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
16101
16225
|
active.vocalDelay = 0;
|
|
16102
16226
|
active.vocalGender = 50;
|
|
16103
16227
|
active.vocalBreathiness = 50;
|
|
16228
|
+
active.vocalTension = 50;
|
|
16104
16229
|
active.vocalOctaveUnison = "none";
|
|
16105
16230
|
} else {
|
|
16106
16231
|
for (const t of trackStates) {
|
|
@@ -16115,6 +16240,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
16115
16240
|
t.vocalDelay = 0;
|
|
16116
16241
|
t.vocalGender = 50;
|
|
16117
16242
|
t.vocalBreathiness = 50;
|
|
16243
|
+
t.vocalTension = 50;
|
|
16118
16244
|
t.vocalOctaveUnison = "none";
|
|
16119
16245
|
}
|
|
16120
16246
|
}
|
|
@@ -16133,6 +16259,8 @@ var mountDAW = (target, options = {}) => {
|
|
|
16133
16259
|
t.vocalDelay = lt.delay ?? 0;
|
|
16134
16260
|
t.vocalGender = lt.gender ?? 50;
|
|
16135
16261
|
t.vocalBreathiness = lt.breathiness ?? 50;
|
|
16262
|
+
t.vocalTension = lt.tension ?? 50;
|
|
16263
|
+
t.vocalTension = lt.tension ?? 50;
|
|
16136
16264
|
t.vocalOctaveUnison = lt.octaveUnison ?? "none";
|
|
16137
16265
|
});
|
|
16138
16266
|
for (const p of placements) {
|
|
@@ -16217,6 +16345,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
16217
16345
|
active.vocalDelay = 0;
|
|
16218
16346
|
active.vocalGender = 50;
|
|
16219
16347
|
active.vocalBreathiness = 50;
|
|
16348
|
+
active.vocalTension = 50;
|
|
16220
16349
|
active.vocalOctaveUnison = "none";
|
|
16221
16350
|
} else {
|
|
16222
16351
|
clearAll();
|
|
@@ -16233,6 +16362,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
16233
16362
|
t.vocalDelay = 0;
|
|
16234
16363
|
t.vocalGender = 50;
|
|
16235
16364
|
t.vocalBreathiness = 50;
|
|
16365
|
+
t.vocalTension = 50;
|
|
16236
16366
|
t.vocalOctaveUnison = "none";
|
|
16237
16367
|
}
|
|
16238
16368
|
}
|
|
@@ -16539,7 +16669,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
16539
16669
|
}
|
|
16540
16670
|
if (t.lyricModel) {
|
|
16541
16671
|
t.vocalVibrato = true;
|
|
16542
|
-
t.vocalReverb = isMainVocal ?
|
|
16672
|
+
t.vocalReverb = isMainVocal ? 25 : 45;
|
|
16543
16673
|
fireLyricsChange(t);
|
|
16544
16674
|
}
|
|
16545
16675
|
}
|
|
@@ -17597,6 +17727,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
17597
17727
|
t.vocalDelay = data.vocalDelay ?? 0;
|
|
17598
17728
|
t.vocalGender = data.vocalGender ?? 50;
|
|
17599
17729
|
t.vocalBreathiness = data.vocalBreathiness ?? 50;
|
|
17730
|
+
t.vocalTension = data.vocalTension ?? 50;
|
|
17600
17731
|
t.vocalOctaveUnison = data.vocalOctaveUnison ?? "none";
|
|
17601
17732
|
},
|
|
17602
17733
|
applyTrackInstrument: (trackIndex, instrumentName) => {
|
|
@@ -17719,6 +17850,7 @@ var playSingingMML = async (mml, options = {}) => {
|
|
|
17719
17850
|
delaySend: (lt.delay ?? 0) / 100,
|
|
17720
17851
|
gender: (lt.gender ?? 50) / 100,
|
|
17721
17852
|
breathiness: (lt.breathiness ?? 50) / 100,
|
|
17853
|
+
tension: (lt.tension ?? 50) / 100,
|
|
17722
17854
|
octaveUnison: lt.octaveUnison,
|
|
17723
17855
|
notes
|
|
17724
17856
|
};
|
|
@@ -18531,6 +18663,11 @@ var createDtmStudio = async (options = {}) => {
|
|
|
18531
18663
|
presetUI: true,
|
|
18532
18664
|
...options.features
|
|
18533
18665
|
};
|
|
18666
|
+
const resolveDrumPatterns = (custom) => ({
|
|
18667
|
+
...DRUM_PATTERNS,
|
|
18668
|
+
...SONG_DRUM_PATTERNS,
|
|
18669
|
+
...normalizeDrumPatterns(custom ?? {})
|
|
18670
|
+
});
|
|
18534
18671
|
const audioCtx = options.audioContext ?? new AudioContext({ sampleRate: 44100 });
|
|
18535
18672
|
const masterGain = audioCtx.createGain();
|
|
18536
18673
|
masterGain.gain.value = options.masterVolume ?? 1;
|
|
@@ -19192,7 +19329,7 @@ var createDtmStudio = async (options = {}) => {
|
|
|
19192
19329
|
await loadRequiredDrums(
|
|
19193
19330
|
getDrumPatternKeys(
|
|
19194
19331
|
meta.drum,
|
|
19195
|
-
opts.drumPatterns ?? options.drumPatterns
|
|
19332
|
+
resolveDrumPatterns(opts.drumPatterns ?? options.drumPatterns)
|
|
19196
19333
|
),
|
|
19197
19334
|
meta.drumFont || "FluidR3_GM_sf2_file:0"
|
|
19198
19335
|
);
|
|
@@ -19283,7 +19420,7 @@ var createDtmStudio = async (options = {}) => {
|
|
|
19283
19420
|
await loadRequiredDrums(
|
|
19284
19421
|
getDrumPatternKeys(
|
|
19285
19422
|
meta.drum,
|
|
19286
|
-
opts.drumPatterns ?? options.drumPatterns
|
|
19423
|
+
resolveDrumPatterns(opts.drumPatterns ?? options.drumPatterns)
|
|
19287
19424
|
)
|
|
19288
19425
|
);
|
|
19289
19426
|
}
|
|
@@ -19363,7 +19500,7 @@ var createDtmStudio = async (options = {}) => {
|
|
|
19363
19500
|
await loadRequiredDrums(
|
|
19364
19501
|
getDrumPatternKeys(
|
|
19365
19502
|
meta.drum,
|
|
19366
|
-
opts.drumPatterns ?? options.drumPatterns
|
|
19503
|
+
resolveDrumPatterns(opts.drumPatterns ?? options.drumPatterns)
|
|
19367
19504
|
)
|
|
19368
19505
|
);
|
|
19369
19506
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -2154,6 +2154,15 @@ var vibratoPitchCurve = (baseHz, preMs) => (tMs) => {
|
|
|
2154
2154
|
return baseHz * 2 ** (cents / 1200);
|
|
2155
2155
|
};
|
|
2156
2156
|
|
|
2157
|
+
// src/voice-worker-types.ts
|
|
2158
|
+
var COMPOSITE_ALIAS_SEP = "\0";
|
|
2159
|
+
var packCompositeAlias = (consonantAlias, vowelAlias) => `${COMPOSITE_ALIAS_SEP}${consonantAlias}${COMPOSITE_ALIAS_SEP}${vowelAlias}`;
|
|
2160
|
+
var unpackCompositeAlias = (alias) => {
|
|
2161
|
+
if (!alias.startsWith(COMPOSITE_ALIAS_SEP)) return null;
|
|
2162
|
+
const parts = alias.slice(COMPOSITE_ALIAS_SEP.length).split(COMPOSITE_ALIAS_SEP);
|
|
2163
|
+
return parts.length === 2 ? [parts[0], parts[1]] : null;
|
|
2164
|
+
};
|
|
2165
|
+
|
|
2157
2166
|
// src/lyrics.ts
|
|
2158
2167
|
var kanaTable = {
|
|
2159
2168
|
\u3042: ["", "a"],
|
|
@@ -2332,9 +2341,10 @@ var parseLyrics = (mml) => {
|
|
|
2332
2341
|
let delay = 0;
|
|
2333
2342
|
let gender = 50;
|
|
2334
2343
|
let breathiness = 50;
|
|
2344
|
+
let tension = 50;
|
|
2335
2345
|
let octaveUnison = "none";
|
|
2336
2346
|
const modelMatch = rest.match(
|
|
2337
|
-
/^([a-z_][a-z0-9_]*?)(?=(?:[
|
|
2347
|
+
/^([a-z_][a-z0-9_]*?)(?=(?:[vqpobrghewt]-?\d)|[^a-z0-9_]|$)(?::(\d+))?/i
|
|
2338
2348
|
);
|
|
2339
2349
|
let model = "";
|
|
2340
2350
|
const metaTokens = [];
|
|
@@ -2403,6 +2413,13 @@ var parseLyrics = (mml) => {
|
|
|
2403
2413
|
rest = rest.substring(hMatch[0].length).trim();
|
|
2404
2414
|
continue;
|
|
2405
2415
|
}
|
|
2416
|
+
const tMatch = rest.match(/^t(\d+)/i);
|
|
2417
|
+
if (tMatch) {
|
|
2418
|
+
tension = clamp2(Number.parseInt(tMatch[1], 10), 0, 100);
|
|
2419
|
+
metaTokens.push(tMatch[0]);
|
|
2420
|
+
rest = rest.substring(tMatch[0].length).trim();
|
|
2421
|
+
continue;
|
|
2422
|
+
}
|
|
2406
2423
|
const eMatch = rest.match(/^e(\d+)/i);
|
|
2407
2424
|
if (eMatch) {
|
|
2408
2425
|
delay = clamp2(Number.parseInt(eMatch[1], 10), 0, 100);
|
|
@@ -2436,6 +2453,7 @@ var parseLyrics = (mml) => {
|
|
|
2436
2453
|
delay,
|
|
2437
2454
|
gender,
|
|
2438
2455
|
breathiness,
|
|
2456
|
+
tension,
|
|
2439
2457
|
octaveUnison,
|
|
2440
2458
|
syllables,
|
|
2441
2459
|
metaText: metaTokens.join(" "),
|
|
@@ -2757,8 +2775,33 @@ var resolveKoeAlias = (hasAlias, pitchTokens, syl, prevVowel, noteNum) => {
|
|
|
2757
2775
|
const hit = tryAlias(base);
|
|
2758
2776
|
if (hit) return hit;
|
|
2759
2777
|
}
|
|
2778
|
+
if (cons && vow) {
|
|
2779
|
+
const vowelAlias = tryAlias(vow) ?? tryAlias(`${pv} ${vow}`);
|
|
2780
|
+
const consAlias = vowelAlias ? tryAlias(cons) : null;
|
|
2781
|
+
if (vowelAlias && consAlias)
|
|
2782
|
+
return packCompositeAlias(consAlias, vowelAlias);
|
|
2783
|
+
}
|
|
2760
2784
|
return null;
|
|
2761
2785
|
};
|
|
2786
|
+
var COMPOSITE_SPLICE_XFADE_SEC = 5e-3;
|
|
2787
|
+
var spliceCompositePcm = (consonantPcm, vowelPcm, sampleRate) => {
|
|
2788
|
+
if (consonantPcm.length === 0 || vowelPcm.length === 0) return null;
|
|
2789
|
+
const xfade = Math.min(
|
|
2790
|
+
Math.floor(sampleRate * COMPOSITE_SPLICE_XFADE_SEC),
|
|
2791
|
+
consonantPcm.length,
|
|
2792
|
+
vowelPcm.length
|
|
2793
|
+
);
|
|
2794
|
+
const pcm = new Float64Array(consonantPcm.length + vowelPcm.length - xfade);
|
|
2795
|
+
pcm.set(consonantPcm, 0);
|
|
2796
|
+
for (let i2 = 0; i2 < xfade; i2++) {
|
|
2797
|
+
const t = (i2 + 1) / (xfade + 1);
|
|
2798
|
+
const idx = consonantPcm.length - xfade + i2;
|
|
2799
|
+
pcm[idx] = consonantPcm[idx] * (1 - t) + vowelPcm[i2] * t;
|
|
2800
|
+
}
|
|
2801
|
+
pcm.set(vowelPcm.subarray(xfade), consonantPcm.length);
|
|
2802
|
+
const consonantMs = (consonantPcm.length - xfade / 2) / sampleRate * 1e3;
|
|
2803
|
+
return { pcm, preMs: consonantMs, consonantMs };
|
|
2804
|
+
};
|
|
2762
2805
|
var createLocalBackend = async (options) => {
|
|
2763
2806
|
const bank = await VoiceBank.load(options.koe);
|
|
2764
2807
|
const worldline = options.lightweight ? null : await Worldline.load({
|
|
@@ -2773,7 +2816,40 @@ var createLocalBackend = async (options) => {
|
|
|
2773
2816
|
}
|
|
2774
2817
|
return p;
|
|
2775
2818
|
};
|
|
2819
|
+
const renderComposite = async (consonantAlias, vowelAlias, pitch, durationMs, vibrato, expr) => {
|
|
2820
|
+
if (!worldline) return null;
|
|
2821
|
+
const [consonantPcm, vowelPcm] = await Promise.all([
|
|
2822
|
+
getPcm(consonantAlias),
|
|
2823
|
+
getPcm(vowelAlias)
|
|
2824
|
+
]);
|
|
2825
|
+
if (!consonantPcm || !vowelPcm) return null;
|
|
2826
|
+
const spliced = spliceCompositePcm(consonantPcm, vowelPcm, KOE_SAMPLE_RATE);
|
|
2827
|
+
if (!spliced) return null;
|
|
2828
|
+
const targetHz = midiToFreq(pitch);
|
|
2829
|
+
const audio = worldline.renderNote({
|
|
2830
|
+
pcm: spliced.pcm,
|
|
2831
|
+
pitch: vibrato ? vibratoPitchCurve(targetHz, spliced.preMs) : targetHz,
|
|
2832
|
+
durationMs,
|
|
2833
|
+
preMs: spliced.preMs,
|
|
2834
|
+
consonantMs: spliced.consonantMs,
|
|
2835
|
+
gender: expr?.gender,
|
|
2836
|
+
breathiness: expr?.breathiness,
|
|
2837
|
+
tension: expr?.tension
|
|
2838
|
+
});
|
|
2839
|
+
return audio ? { pcm: audio, preSec: spliced.preMs / 1e3, rate: 1 } : null;
|
|
2840
|
+
};
|
|
2776
2841
|
const renderAlias = async (alias, pitch, durationMs, vibrato, expr) => {
|
|
2842
|
+
const composite = unpackCompositeAlias(alias);
|
|
2843
|
+
if (composite) {
|
|
2844
|
+
return renderComposite(
|
|
2845
|
+
composite[0],
|
|
2846
|
+
composite[1],
|
|
2847
|
+
pitch,
|
|
2848
|
+
durationMs,
|
|
2849
|
+
vibrato,
|
|
2850
|
+
expr
|
|
2851
|
+
);
|
|
2852
|
+
}
|
|
2777
2853
|
const pcm = await getPcm(alias);
|
|
2778
2854
|
if (!pcm || pcm.length === 0) return null;
|
|
2779
2855
|
const entry = bank.manifest.phonemes[alias];
|
|
@@ -2786,7 +2862,8 @@ var createLocalBackend = async (options) => {
|
|
|
2786
2862
|
durationMs,
|
|
2787
2863
|
...lead,
|
|
2788
2864
|
gender: expr?.gender,
|
|
2789
|
-
breathiness: expr?.breathiness
|
|
2865
|
+
breathiness: expr?.breathiness,
|
|
2866
|
+
tension: expr?.tension
|
|
2790
2867
|
});
|
|
2791
2868
|
if (audio) return { pcm: audio, preSec: lead.preMs / 1e3, rate: 1 };
|
|
2792
2869
|
}
|
|
@@ -2867,7 +2944,8 @@ var createWorkerBackend = async (workerUrl, options) => {
|
|
|
2867
2944
|
durationMs,
|
|
2868
2945
|
vibrato,
|
|
2869
2946
|
gender: expr?.gender,
|
|
2870
|
-
breathiness: expr?.breathiness
|
|
2947
|
+
breathiness: expr?.breathiness,
|
|
2948
|
+
tension: expr?.tension
|
|
2871
2949
|
});
|
|
2872
2950
|
});
|
|
2873
2951
|
return {
|
|
@@ -2896,7 +2974,7 @@ var createKoeVoice = async (ctx, destination, options) => {
|
|
|
2896
2974
|
const inflight = /* @__PURE__ */ new Map();
|
|
2897
2975
|
const active = /* @__PURE__ */ new Set();
|
|
2898
2976
|
let prevVowel = "";
|
|
2899
|
-
const keyOf = (alias, pitch, durationMs, vibrato, expr) => `${alias}|${pitch}|${Math.round(durationMs / 10) * 10}${vibrato ? "|vib" : ""}${expr?.gender !== void 0 ? `|g${Math.round(expr.gender * 100)}` : ""}${expr?.breathiness !== void 0 ? `|h${Math.round(expr.breathiness * 100)}` : ""}`;
|
|
2977
|
+
const keyOf = (alias, pitch, durationMs, vibrato, expr) => `${alias}|${pitch}|${Math.round(durationMs / 10) * 10}${vibrato ? "|vib" : ""}${expr?.gender !== void 0 ? `|g${Math.round(expr.gender * 100)}` : ""}${expr?.breathiness !== void 0 ? `|h${Math.round(expr.breathiness * 100)}` : ""}${expr?.tension !== void 0 ? `|t${Math.round(expr.tension * 100)}` : ""}`;
|
|
2900
2978
|
const renderInto = (alias, pitch, durationMs, vibrato, expr) => {
|
|
2901
2979
|
const key = keyOf(alias, pitch, durationMs, vibrato, expr);
|
|
2902
2980
|
const existing = renderCache.get(key);
|
|
@@ -3127,7 +3205,8 @@ var createSingingVoices = (ctx, destination, options = {}) => {
|
|
|
3127
3205
|
let n = 0;
|
|
3128
3206
|
const expr = {
|
|
3129
3207
|
gender: track.gender,
|
|
3130
|
-
breathiness: track.breathiness
|
|
3208
|
+
breathiness: track.breathiness,
|
|
3209
|
+
tension: track.tension
|
|
3131
3210
|
};
|
|
3132
3211
|
forEachSungNote(track, (note, prevVowel) => {
|
|
3133
3212
|
if (n >= count && note.startSec >= STREAM_LOOKAHEAD_SEC) return;
|
|
@@ -3214,7 +3293,11 @@ var createSingingVoices = (ctx, destination, options = {}) => {
|
|
|
3214
3293
|
pitch,
|
|
3215
3294
|
note.durationSec * 1e3,
|
|
3216
3295
|
track.vibrato,
|
|
3217
|
-
{
|
|
3296
|
+
{
|
|
3297
|
+
gender: track.gender,
|
|
3298
|
+
breathiness: track.breathiness,
|
|
3299
|
+
tension: track.tension
|
|
3300
|
+
}
|
|
3218
3301
|
);
|
|
3219
3302
|
if (session !== streamSession) return;
|
|
3220
3303
|
if (key) {
|
|
@@ -3748,8 +3831,7 @@ var createReverbImpulse = (ctx, decaySec = DEFAULT_REVERB_DECAY_SEC) => {
|
|
|
3748
3831
|
}
|
|
3749
3832
|
return impulse;
|
|
3750
3833
|
};
|
|
3751
|
-
var
|
|
3752
|
-
var reverbAmountToGain = (amount) => Math.max(0, Math.min(100, amount)) / 100 * REVERB_MAX_WET;
|
|
3834
|
+
var reverbAmountToGain = (amount) => Math.max(0, Math.min(100, amount)) / 100;
|
|
3753
3835
|
|
|
3754
3836
|
// src/sequencer.ts
|
|
3755
3837
|
var STEPS_PER_BEAT = 48;
|
|
@@ -9442,6 +9524,7 @@ var mountMmlPlayer = (target, mml, options = {}) => {
|
|
|
9442
9524
|
delaySend: (lt.delay ?? 0) / 100,
|
|
9443
9525
|
gender: (lt.gender ?? 50) / 100,
|
|
9444
9526
|
breathiness: (lt.breathiness ?? 50) / 100,
|
|
9527
|
+
tension: (lt.tension ?? 50) / 100,
|
|
9445
9528
|
octaveUnison: lt.octaveUnison,
|
|
9446
9529
|
notes
|
|
9447
9530
|
};
|
|
@@ -13292,6 +13375,16 @@ var BREATHINESS_INFO_HTML = `
|
|
|
13292
13375
|
<p>\u81EA\u52D5\u30D3\u30D6\u30E9\u30FC\u30C8\u3068\u7D44\u307F\u5408\u308F\u305B\u308B\u3068\u3001\u63FA\u308C\u306A\u304C\u3089\u606F\u3063\u307D\u3044\u3001\u3088\u308A\u30A8\u30E2\u30FC\u30B7\u30E7\u30CA\u30EB\u306A\u8868\u73FE\u306B\u306A\u308A\u3084\u3059\u3044\u3067\u3059\u3002koe\u97F3\u6E90\uFF08UTAU\u7531\u6765\u306E.koe\u97F3\u6E90\uFF09\u9650\u5B9A\u306E\u52B9\u679C\u3067\u3001klatt\uFF08\u5185\u8535\u306E\u7C21\u6613\u5408\u6210\uFF09\u3067\u306F\u5909\u5316\u3057\u307E\u305B\u3093\u3002</p>
|
|
13293
13376
|
</div>
|
|
13294
13377
|
`;
|
|
13378
|
+
var TENSION_INFO_HTML = `
|
|
13379
|
+
<div class="dtm-modal-body-content">
|
|
13380
|
+
<h4>\u4F55\u3092\u3059\u308B\u8A2D\u5B9A\u304B</h4>
|
|
13381
|
+
<p>\u58F0\u306E\u5F35\u308A\uFF0F\u62BC\u3057\u51FA\u3057\u306E\u5F37\u3055\u3067\u3059\u300250\u304C\u7121\u5909\u5316\u3001\u5927\u304D\u3044\u307B\u3069\u5F35\u3063\u305F\u30FB\u62BC\u3057\u305F\u58F0\uFF08\u300C\u3053\u3076\u3057\u300D\u5BC4\u308A\u3001\u529B\u5F37\u304F\u6B4C\u308F\u305B\u308B\uFF09\u306B\u306A\u308A\u3001\u5C0F\u3055\u3044\u307B\u3069\u8131\u529B\u3057\u305F\u30EA\u30E9\u30C3\u30AF\u30B9\u3057\u305F\u58F0\u306B\u306A\u308A\u307E\u3059\u3002</p>
|
|
13382
|
+
<h4>\u30D6\u30EC\u30B7\u30CD\u30B9\u3068\u306E\u9055\u3044</h4>
|
|
13383
|
+
<p>\u30D6\u30EC\u30B7\u30CD\u30B9\u306F\u606F\u6210\u5206\u306E\u91CF\uFF08\u82AF\u306E\u3042\u308B\u58F0\u21D4\u606F\u3063\u307D\u3044\u58F0\uFF09\u3092\u52D5\u304B\u3057\u307E\u3059\u304C\u3001\u30C6\u30F3\u30B7\u30E7\u30F3\u306F\u58F0\u5E2F\u306E\u7DE0\u307E\u308A\u30FB\u62BC\u3057\u306E\u5F37\u3055\uFF08\u8131\u529B\u21D4\u5F35\u3063\u305F\u58F0\uFF09\u3092\u52D5\u304B\u3057\u307E\u3059\u3002\u30C6\u30F3\u30B7\u30E7\u30F3\u3092\u4E0A\u3052\u308B\u3068\u30B5\u30D3\u306E\u529B\u5F37\u3055\u3001\u4E0B\u3052\u308B\u3068\u7A4F\u3084\u304B\u306A\u56C1\u304D\u306B\u5BC4\u305B\u305F\u6B4C\u308F\u305B\u65B9\u306B\u306A\u308A\u307E\u3059\u3002</p>
|
|
13384
|
+
<h4>\u4ED6\u306E\u8A2D\u5B9A\u3068\u306E\u517C\u306D\u5408\u3044</h4>
|
|
13385
|
+
<p>\u30D6\u30EC\u30B7\u30CD\u30B9\u3092\u4E0B\u3052\u3064\u3064\u30C6\u30F3\u30B7\u30E7\u30F3\u3092\u4E0A\u3052\u308B\u3068\u3001\u3088\u308A\u82AF\u304C\u3042\u308A\u529B\u5F37\u3044\u6B4C\u58F0\u306B\u306A\u308A\u307E\u3059\u3002\u9006\u306B\u30D6\u30EC\u30B7\u30CD\u30B9\u3092\u4E0A\u3052\u3064\u3064\u30C6\u30F3\u30B7\u30E7\u30F3\u3092\u4E0B\u3052\u308B\u3068\u3001\u3088\u308A\u8131\u529B\u3057\u305F\u606F\u3063\u307D\u3044\u6B4C\u58F0\u306B\u306A\u308A\u307E\u3059\u3002koe\u97F3\u6E90\uFF08UTAU\u7531\u6765\u306E.koe\u97F3\u6E90\uFF09\u9650\u5B9A\u306E\u52B9\u679C\u3067\u3001klatt\uFF08\u5185\u8535\u306E\u7C21\u6613\u5408\u6210\uFF09\u3067\u306F\u5909\u5316\u3057\u307E\u305B\u3093\u3002</p>
|
|
13386
|
+
</div>
|
|
13387
|
+
`;
|
|
13295
13388
|
var LYRIC_REVERB_INFO_HTML = `
|
|
13296
13389
|
<div class="dtm-modal-body-content">
|
|
13297
13390
|
<h4>\u4F55\u3092\u3059\u308B\u8A2D\u5B9A\u304B</h4>
|
|
@@ -13816,6 +13909,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
13816
13909
|
vocalDelay: t.vocalDelay,
|
|
13817
13910
|
vocalGender: t.vocalGender,
|
|
13818
13911
|
vocalBreathiness: t.vocalBreathiness,
|
|
13912
|
+
vocalTension: t.vocalTension,
|
|
13819
13913
|
vocalOctaveUnison: t.vocalOctaveUnison
|
|
13820
13914
|
};
|
|
13821
13915
|
if (lyricsDebounceTimer) clearTimeout(lyricsDebounceTimer);
|
|
@@ -13881,6 +13975,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
13881
13975
|
vocalDelay: 0,
|
|
13882
13976
|
vocalGender: 50,
|
|
13883
13977
|
vocalBreathiness: 50,
|
|
13978
|
+
vocalTension: 50,
|
|
13884
13979
|
vocalOctaveUnison: "none",
|
|
13885
13980
|
trackInstrument: "",
|
|
13886
13981
|
trackCompression: 0,
|
|
@@ -13912,6 +14007,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
13912
14007
|
delay: t.vocalDelay,
|
|
13913
14008
|
gender: t.vocalGender,
|
|
13914
14009
|
breathiness: t.vocalBreathiness,
|
|
14010
|
+
tension: t.vocalTension,
|
|
13915
14011
|
octaveUnison: t.vocalOctaveUnison,
|
|
13916
14012
|
syllables
|
|
13917
14013
|
});
|
|
@@ -14722,6 +14818,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
14722
14818
|
delaySend: (lt.delay ?? 0) / 100,
|
|
14723
14819
|
gender: (lt.gender ?? 50) / 100,
|
|
14724
14820
|
breathiness: (lt.breathiness ?? 50) / 100,
|
|
14821
|
+
tension: (lt.tension ?? 50) / 100,
|
|
14725
14822
|
octaveUnison: lt.octaveUnison,
|
|
14726
14823
|
notes
|
|
14727
14824
|
};
|
|
@@ -15150,6 +15247,12 @@ var mountDAW = (target, options = {}) => {
|
|
|
15150
15247
|
<span class="dtm-label" data-dtm="lyric-breathiness-label"></span>
|
|
15151
15248
|
<button class="dtm-infobtn" data-dtm="lyric-breathiness-info" title="\u30D6\u30EC\u30B7\u30CD\u30B9\u306E\u89E3\u8AAC">${icon("info", 12)}</button>
|
|
15152
15249
|
</div>
|
|
15250
|
+
<div class="dtm-row">
|
|
15251
|
+
<span class="dtm-label">\u30C6\u30F3\u30B7\u30E7\u30F3</span>
|
|
15252
|
+
<input type="range" class="dtm-range dtm-grow" data-dtm="lyric-tension" min="0" max="100" aria-label="\u30C6\u30F3\u30B7\u30E7\u30F3\uFF08\u5F35\u308A/\u529B\u5F37\u3055\u3001koe\u97F3\u6E90\u9650\u5B9A\uFF09">
|
|
15253
|
+
<span class="dtm-label" data-dtm="lyric-tension-label"></span>
|
|
15254
|
+
<button class="dtm-infobtn" data-dtm="lyric-tension-info" title="\u30C6\u30F3\u30B7\u30E7\u30F3\u306E\u89E3\u8AAC">${icon("info", 12)}</button>
|
|
15255
|
+
</div>
|
|
15153
15256
|
<div class="dtm-row">
|
|
15154
15257
|
<span class="dtm-label" style="display:inline-flex;align-items:center;gap:2px">
|
|
15155
15258
|
<input type="checkbox" data-dtm="lyric-vibrato" aria-label="\u81EA\u52D5\u30D3\u30D6\u30E9\u30FC\u30C8">\u30D3\u30D6\u30E9\u30FC\u30C8
|
|
@@ -15253,6 +15356,18 @@ var mountDAW = (target, options = {}) => {
|
|
|
15253
15356
|
lyricBreathinessInfo.addEventListener("click", () => {
|
|
15254
15357
|
showModal("\u30D6\u30EC\u30B7\u30CD\u30B9\u306E\u89E3\u8AAC", BREATHINESS_INFO_HTML);
|
|
15255
15358
|
});
|
|
15359
|
+
const lyricTension = lyricDiv.querySelector(
|
|
15360
|
+
'[data-dtm="lyric-tension"]'
|
|
15361
|
+
);
|
|
15362
|
+
const lyricTensionLabel = lyricDiv.querySelector(
|
|
15363
|
+
'[data-dtm="lyric-tension-label"]'
|
|
15364
|
+
);
|
|
15365
|
+
const lyricTensionInfo = lyricDiv.querySelector(
|
|
15366
|
+
'[data-dtm="lyric-tension-info"]'
|
|
15367
|
+
);
|
|
15368
|
+
lyricTensionInfo.addEventListener("click", () => {
|
|
15369
|
+
showModal("\u30C6\u30F3\u30B7\u30E7\u30F3\u306E\u89E3\u8AAC", TENSION_INFO_HTML);
|
|
15370
|
+
});
|
|
15256
15371
|
const lyricVibrato = lyricDiv.querySelector(
|
|
15257
15372
|
'[data-dtm="lyric-vibrato"]'
|
|
15258
15373
|
);
|
|
@@ -15340,6 +15455,8 @@ var mountDAW = (target, options = {}) => {
|
|
|
15340
15455
|
lyricGenderLabel.textContent = `${active.vocalGender}`;
|
|
15341
15456
|
lyricBreathiness.value = String(active.vocalBreathiness);
|
|
15342
15457
|
lyricBreathinessLabel.textContent = `${active.vocalBreathiness}`;
|
|
15458
|
+
lyricTension.value = String(active.vocalTension);
|
|
15459
|
+
lyricTensionLabel.textContent = `${active.vocalTension}`;
|
|
15343
15460
|
lyricVibrato.checked = active.vocalVibrato;
|
|
15344
15461
|
lyricOctaveUnison.value = active.vocalOctaveUnison;
|
|
15345
15462
|
const updateLyricCount = () => {
|
|
@@ -15510,6 +15627,11 @@ var mountDAW = (target, options = {}) => {
|
|
|
15510
15627
|
lyricBreathinessLabel.textContent = `${active.vocalBreathiness}`;
|
|
15511
15628
|
fireLyricsChange(active);
|
|
15512
15629
|
});
|
|
15630
|
+
lyricTension.addEventListener("input", () => {
|
|
15631
|
+
active.vocalTension = Number.parseInt(lyricTension.value, 10);
|
|
15632
|
+
lyricTensionLabel.textContent = `${active.vocalTension}`;
|
|
15633
|
+
fireLyricsChange(active);
|
|
15634
|
+
});
|
|
15513
15635
|
}
|
|
15514
15636
|
if (active.config.id === "chord" && showChord) {
|
|
15515
15637
|
const div = document.createElement("div");
|
|
@@ -15714,6 +15836,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
15714
15836
|
del: t.vocalDelay,
|
|
15715
15837
|
gen: t.vocalGender,
|
|
15716
15838
|
bre: t.vocalBreathiness,
|
|
15839
|
+
ten: t.vocalTension,
|
|
15717
15840
|
uni: t.vocalOctaveUnison
|
|
15718
15841
|
})).filter(
|
|
15719
15842
|
(x2) => x2.model.length > 0 && x2.text.length > 0 && x2.notes.length > 0
|
|
@@ -15728,6 +15851,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
15728
15851
|
x2.del === 0 ? "" : `e${x2.del}`,
|
|
15729
15852
|
x2.gen === 50 ? "" : `g${x2.gen}`,
|
|
15730
15853
|
x2.bre === 50 ? "" : `h${x2.bre}`,
|
|
15854
|
+
x2.ten === 50 ? "" : `t${x2.ten}`,
|
|
15731
15855
|
OCTAVE_UNISON_TOKEN[x2.uni]
|
|
15732
15856
|
].filter((s) => s.length > 0).join(" ");
|
|
15733
15857
|
const head = params ? `${x2.model} ${params}` : x2.model;
|
|
@@ -15970,6 +16094,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
15970
16094
|
active.vocalDelay = 0;
|
|
15971
16095
|
active.vocalGender = 50;
|
|
15972
16096
|
active.vocalBreathiness = 50;
|
|
16097
|
+
active.vocalTension = 50;
|
|
15973
16098
|
active.vocalOctaveUnison = "none";
|
|
15974
16099
|
} else {
|
|
15975
16100
|
for (const t of trackStates) {
|
|
@@ -15984,6 +16109,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
15984
16109
|
t.vocalDelay = 0;
|
|
15985
16110
|
t.vocalGender = 50;
|
|
15986
16111
|
t.vocalBreathiness = 50;
|
|
16112
|
+
t.vocalTension = 50;
|
|
15987
16113
|
t.vocalOctaveUnison = "none";
|
|
15988
16114
|
}
|
|
15989
16115
|
}
|
|
@@ -16002,6 +16128,8 @@ var mountDAW = (target, options = {}) => {
|
|
|
16002
16128
|
t.vocalDelay = lt.delay ?? 0;
|
|
16003
16129
|
t.vocalGender = lt.gender ?? 50;
|
|
16004
16130
|
t.vocalBreathiness = lt.breathiness ?? 50;
|
|
16131
|
+
t.vocalTension = lt.tension ?? 50;
|
|
16132
|
+
t.vocalTension = lt.tension ?? 50;
|
|
16005
16133
|
t.vocalOctaveUnison = lt.octaveUnison ?? "none";
|
|
16006
16134
|
});
|
|
16007
16135
|
for (const p of placements) {
|
|
@@ -16086,6 +16214,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
16086
16214
|
active.vocalDelay = 0;
|
|
16087
16215
|
active.vocalGender = 50;
|
|
16088
16216
|
active.vocalBreathiness = 50;
|
|
16217
|
+
active.vocalTension = 50;
|
|
16089
16218
|
active.vocalOctaveUnison = "none";
|
|
16090
16219
|
} else {
|
|
16091
16220
|
clearAll();
|
|
@@ -16102,6 +16231,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
16102
16231
|
t.vocalDelay = 0;
|
|
16103
16232
|
t.vocalGender = 50;
|
|
16104
16233
|
t.vocalBreathiness = 50;
|
|
16234
|
+
t.vocalTension = 50;
|
|
16105
16235
|
t.vocalOctaveUnison = "none";
|
|
16106
16236
|
}
|
|
16107
16237
|
}
|
|
@@ -16408,7 +16538,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
16408
16538
|
}
|
|
16409
16539
|
if (t.lyricModel) {
|
|
16410
16540
|
t.vocalVibrato = true;
|
|
16411
|
-
t.vocalReverb = isMainVocal ?
|
|
16541
|
+
t.vocalReverb = isMainVocal ? 25 : 45;
|
|
16412
16542
|
fireLyricsChange(t);
|
|
16413
16543
|
}
|
|
16414
16544
|
}
|
|
@@ -17466,6 +17596,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
17466
17596
|
t.vocalDelay = data.vocalDelay ?? 0;
|
|
17467
17597
|
t.vocalGender = data.vocalGender ?? 50;
|
|
17468
17598
|
t.vocalBreathiness = data.vocalBreathiness ?? 50;
|
|
17599
|
+
t.vocalTension = data.vocalTension ?? 50;
|
|
17469
17600
|
t.vocalOctaveUnison = data.vocalOctaveUnison ?? "none";
|
|
17470
17601
|
},
|
|
17471
17602
|
applyTrackInstrument: (trackIndex, instrumentName) => {
|
|
@@ -17588,6 +17719,7 @@ var playSingingMML = async (mml, options = {}) => {
|
|
|
17588
17719
|
delaySend: (lt.delay ?? 0) / 100,
|
|
17589
17720
|
gender: (lt.gender ?? 50) / 100,
|
|
17590
17721
|
breathiness: (lt.breathiness ?? 50) / 100,
|
|
17722
|
+
tension: (lt.tension ?? 50) / 100,
|
|
17591
17723
|
octaveUnison: lt.octaveUnison,
|
|
17592
17724
|
notes
|
|
17593
17725
|
};
|
|
@@ -18399,6 +18531,11 @@ var createDtmStudio = async (options = {}) => {
|
|
|
18399
18531
|
presetUI: true,
|
|
18400
18532
|
...options.features
|
|
18401
18533
|
};
|
|
18534
|
+
const resolveDrumPatterns = (custom) => ({
|
|
18535
|
+
...DRUM_PATTERNS,
|
|
18536
|
+
...SONG_DRUM_PATTERNS,
|
|
18537
|
+
...normalizeDrumPatterns(custom ?? {})
|
|
18538
|
+
});
|
|
18402
18539
|
const audioCtx = options.audioContext ?? new AudioContext({ sampleRate: 44100 });
|
|
18403
18540
|
const masterGain = audioCtx.createGain();
|
|
18404
18541
|
masterGain.gain.value = options.masterVolume ?? 1;
|
|
@@ -19060,7 +19197,7 @@ var createDtmStudio = async (options = {}) => {
|
|
|
19060
19197
|
await loadRequiredDrums(
|
|
19061
19198
|
getDrumPatternKeys(
|
|
19062
19199
|
meta.drum,
|
|
19063
|
-
opts.drumPatterns ?? options.drumPatterns
|
|
19200
|
+
resolveDrumPatterns(opts.drumPatterns ?? options.drumPatterns)
|
|
19064
19201
|
),
|
|
19065
19202
|
meta.drumFont || "FluidR3_GM_sf2_file:0"
|
|
19066
19203
|
);
|
|
@@ -19151,7 +19288,7 @@ var createDtmStudio = async (options = {}) => {
|
|
|
19151
19288
|
await loadRequiredDrums(
|
|
19152
19289
|
getDrumPatternKeys(
|
|
19153
19290
|
meta.drum,
|
|
19154
|
-
opts.drumPatterns ?? options.drumPatterns
|
|
19291
|
+
resolveDrumPatterns(opts.drumPatterns ?? options.drumPatterns)
|
|
19155
19292
|
)
|
|
19156
19293
|
);
|
|
19157
19294
|
}
|
|
@@ -19231,7 +19368,7 @@ var createDtmStudio = async (options = {}) => {
|
|
|
19231
19368
|
await loadRequiredDrums(
|
|
19232
19369
|
getDrumPatternKeys(
|
|
19233
19370
|
meta.drum,
|
|
19234
|
-
opts.drumPatterns ?? options.drumPatterns
|
|
19371
|
+
resolveDrumPatterns(opts.drumPatterns ?? options.drumPatterns)
|
|
19235
19372
|
)
|
|
19236
19373
|
);
|
|
19237
19374
|
}
|
package/dist/voice-worker.js
CHANGED
|
@@ -525,6 +525,14 @@
|
|
|
525
525
|
return baseHz * 2 ** (cents / 1200);
|
|
526
526
|
};
|
|
527
527
|
|
|
528
|
+
// src/voice-worker-types.ts
|
|
529
|
+
var COMPOSITE_ALIAS_SEP = "\0";
|
|
530
|
+
var unpackCompositeAlias = (alias) => {
|
|
531
|
+
if (!alias.startsWith(COMPOSITE_ALIAS_SEP)) return null;
|
|
532
|
+
const parts = alias.slice(COMPOSITE_ALIAS_SEP.length).split(COMPOSITE_ALIAS_SEP);
|
|
533
|
+
return parts.length === 2 ? [parts[0], parts[1]] : null;
|
|
534
|
+
};
|
|
535
|
+
|
|
528
536
|
// src/voice-worker.ts
|
|
529
537
|
var KOE_SAMPLE_RATE = 48e3;
|
|
530
538
|
var midiToFreq = (m) => 440 * 2 ** ((m - 69) / 12);
|
|
@@ -540,8 +548,62 @@
|
|
|
540
548
|
}
|
|
541
549
|
return p;
|
|
542
550
|
};
|
|
543
|
-
var
|
|
551
|
+
var COMPOSITE_SPLICE_XFADE_SEC = 5e-3;
|
|
552
|
+
var spliceCompositePcm = (consonantPcm, vowelPcm, sampleRate) => {
|
|
553
|
+
if (consonantPcm.length === 0 || vowelPcm.length === 0) return null;
|
|
554
|
+
const xfade = Math.min(
|
|
555
|
+
Math.floor(sampleRate * COMPOSITE_SPLICE_XFADE_SEC),
|
|
556
|
+
consonantPcm.length,
|
|
557
|
+
vowelPcm.length
|
|
558
|
+
);
|
|
559
|
+
const pcm = new Float64Array(consonantPcm.length + vowelPcm.length - xfade);
|
|
560
|
+
pcm.set(consonantPcm, 0);
|
|
561
|
+
for (let i2 = 0; i2 < xfade; i2++) {
|
|
562
|
+
const t = (i2 + 1) / (xfade + 1);
|
|
563
|
+
const idx = consonantPcm.length - xfade + i2;
|
|
564
|
+
pcm[idx] = consonantPcm[idx] * (1 - t) + vowelPcm[i2] * t;
|
|
565
|
+
}
|
|
566
|
+
pcm.set(vowelPcm.subarray(xfade), consonantPcm.length);
|
|
567
|
+
const consonantMs = (consonantPcm.length - xfade / 2) / sampleRate * 1e3;
|
|
568
|
+
return { pcm, preMs: consonantMs, consonantMs };
|
|
569
|
+
};
|
|
570
|
+
var renderComposite = async (consonantAlias, vowelAlias, pitch, durationMs, vibrato, gender, breathiness, tension) => {
|
|
571
|
+
if (!worldline) return null;
|
|
572
|
+
const [consonantPcm, vowelPcm] = await Promise.all([
|
|
573
|
+
getPcm(consonantAlias),
|
|
574
|
+
getPcm(vowelAlias)
|
|
575
|
+
]);
|
|
576
|
+
if (!consonantPcm || !vowelPcm) return null;
|
|
577
|
+
const spliced = spliceCompositePcm(consonantPcm, vowelPcm, KOE_SAMPLE_RATE);
|
|
578
|
+
if (!spliced) return null;
|
|
579
|
+
const targetHz = midiToFreq(pitch);
|
|
580
|
+
const audio = worldline.renderNote({
|
|
581
|
+
pcm: spliced.pcm,
|
|
582
|
+
pitch: vibrato ? vibratoPitchCurve(targetHz, spliced.preMs) : targetHz,
|
|
583
|
+
durationMs,
|
|
584
|
+
preMs: spliced.preMs,
|
|
585
|
+
consonantMs: spliced.consonantMs,
|
|
586
|
+
gender,
|
|
587
|
+
breathiness,
|
|
588
|
+
tension
|
|
589
|
+
});
|
|
590
|
+
return audio ? { pcm: audio, preSec: spliced.preMs / 1e3, rate: 1 } : null;
|
|
591
|
+
};
|
|
592
|
+
var renderAlias = async (alias, pitch, durationMs, vibrato, gender, breathiness, tension) => {
|
|
544
593
|
if (!bank) return null;
|
|
594
|
+
const composite = unpackCompositeAlias(alias);
|
|
595
|
+
if (composite) {
|
|
596
|
+
return renderComposite(
|
|
597
|
+
composite[0],
|
|
598
|
+
composite[1],
|
|
599
|
+
pitch,
|
|
600
|
+
durationMs,
|
|
601
|
+
vibrato,
|
|
602
|
+
gender,
|
|
603
|
+
breathiness,
|
|
604
|
+
tension
|
|
605
|
+
);
|
|
606
|
+
}
|
|
545
607
|
const pcm = await getPcm(alias);
|
|
546
608
|
if (!pcm || pcm.length === 0) return null;
|
|
547
609
|
const entry = bank.manifest.phonemes[alias];
|
|
@@ -554,7 +616,8 @@
|
|
|
554
616
|
durationMs,
|
|
555
617
|
...lead,
|
|
556
618
|
gender,
|
|
557
|
-
breathiness
|
|
619
|
+
breathiness,
|
|
620
|
+
tension
|
|
558
621
|
});
|
|
559
622
|
if (audio) return { pcm: audio, preSec: lead.preMs / 1e3, rate: 1 };
|
|
560
623
|
}
|
|
@@ -586,7 +649,16 @@
|
|
|
586
649
|
return;
|
|
587
650
|
}
|
|
588
651
|
if (msg.type === "render") {
|
|
589
|
-
const {
|
|
652
|
+
const {
|
|
653
|
+
id,
|
|
654
|
+
alias,
|
|
655
|
+
pitch,
|
|
656
|
+
durationMs,
|
|
657
|
+
vibrato,
|
|
658
|
+
gender,
|
|
659
|
+
breathiness,
|
|
660
|
+
tension
|
|
661
|
+
} = msg;
|
|
590
662
|
try {
|
|
591
663
|
const out = await renderAlias(
|
|
592
664
|
alias,
|
|
@@ -594,7 +666,8 @@
|
|
|
594
666
|
durationMs,
|
|
595
667
|
vibrato,
|
|
596
668
|
gender,
|
|
597
|
-
breathiness
|
|
669
|
+
breathiness,
|
|
670
|
+
tension
|
|
598
671
|
);
|
|
599
672
|
if (out) {
|
|
600
673
|
wself.postMessage(
|
package/package.json
CHANGED