@onjmin/dtm 0.1.90 → 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 +139 -6
- package/dist/index.mjs +139 -6
- 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) {
|
|
@@ -9572,6 +9655,7 @@ var mountMmlPlayer = (target, mml, options = {}) => {
|
|
|
9572
9655
|
delaySend: (lt.delay ?? 0) / 100,
|
|
9573
9656
|
gender: (lt.gender ?? 50) / 100,
|
|
9574
9657
|
breathiness: (lt.breathiness ?? 50) / 100,
|
|
9658
|
+
tension: (lt.tension ?? 50) / 100,
|
|
9575
9659
|
octaveUnison: lt.octaveUnison,
|
|
9576
9660
|
notes
|
|
9577
9661
|
};
|
|
@@ -13422,6 +13506,16 @@ var BREATHINESS_INFO_HTML = `
|
|
|
13422
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>
|
|
13423
13507
|
</div>
|
|
13424
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
|
+
`;
|
|
13425
13519
|
var LYRIC_REVERB_INFO_HTML = `
|
|
13426
13520
|
<div class="dtm-modal-body-content">
|
|
13427
13521
|
<h4>\u4F55\u3092\u3059\u308B\u8A2D\u5B9A\u304B</h4>
|
|
@@ -13946,6 +14040,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
13946
14040
|
vocalDelay: t.vocalDelay,
|
|
13947
14041
|
vocalGender: t.vocalGender,
|
|
13948
14042
|
vocalBreathiness: t.vocalBreathiness,
|
|
14043
|
+
vocalTension: t.vocalTension,
|
|
13949
14044
|
vocalOctaveUnison: t.vocalOctaveUnison
|
|
13950
14045
|
};
|
|
13951
14046
|
if (lyricsDebounceTimer) clearTimeout(lyricsDebounceTimer);
|
|
@@ -14011,6 +14106,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
14011
14106
|
vocalDelay: 0,
|
|
14012
14107
|
vocalGender: 50,
|
|
14013
14108
|
vocalBreathiness: 50,
|
|
14109
|
+
vocalTension: 50,
|
|
14014
14110
|
vocalOctaveUnison: "none",
|
|
14015
14111
|
trackInstrument: "",
|
|
14016
14112
|
trackCompression: 0,
|
|
@@ -14042,6 +14138,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
14042
14138
|
delay: t.vocalDelay,
|
|
14043
14139
|
gender: t.vocalGender,
|
|
14044
14140
|
breathiness: t.vocalBreathiness,
|
|
14141
|
+
tension: t.vocalTension,
|
|
14045
14142
|
octaveUnison: t.vocalOctaveUnison,
|
|
14046
14143
|
syllables
|
|
14047
14144
|
});
|
|
@@ -14852,6 +14949,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
14852
14949
|
delaySend: (lt.delay ?? 0) / 100,
|
|
14853
14950
|
gender: (lt.gender ?? 50) / 100,
|
|
14854
14951
|
breathiness: (lt.breathiness ?? 50) / 100,
|
|
14952
|
+
tension: (lt.tension ?? 50) / 100,
|
|
14855
14953
|
octaveUnison: lt.octaveUnison,
|
|
14856
14954
|
notes
|
|
14857
14955
|
};
|
|
@@ -15280,6 +15378,12 @@ var mountDAW = (target, options = {}) => {
|
|
|
15280
15378
|
<span class="dtm-label" data-dtm="lyric-breathiness-label"></span>
|
|
15281
15379
|
<button class="dtm-infobtn" data-dtm="lyric-breathiness-info" title="\u30D6\u30EC\u30B7\u30CD\u30B9\u306E\u89E3\u8AAC">${icon("info", 12)}</button>
|
|
15282
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>
|
|
15283
15387
|
<div class="dtm-row">
|
|
15284
15388
|
<span class="dtm-label" style="display:inline-flex;align-items:center;gap:2px">
|
|
15285
15389
|
<input type="checkbox" data-dtm="lyric-vibrato" aria-label="\u81EA\u52D5\u30D3\u30D6\u30E9\u30FC\u30C8">\u30D3\u30D6\u30E9\u30FC\u30C8
|
|
@@ -15383,6 +15487,18 @@ var mountDAW = (target, options = {}) => {
|
|
|
15383
15487
|
lyricBreathinessInfo.addEventListener("click", () => {
|
|
15384
15488
|
showModal("\u30D6\u30EC\u30B7\u30CD\u30B9\u306E\u89E3\u8AAC", BREATHINESS_INFO_HTML);
|
|
15385
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
|
+
});
|
|
15386
15502
|
const lyricVibrato = lyricDiv.querySelector(
|
|
15387
15503
|
'[data-dtm="lyric-vibrato"]'
|
|
15388
15504
|
);
|
|
@@ -15470,6 +15586,8 @@ var mountDAW = (target, options = {}) => {
|
|
|
15470
15586
|
lyricGenderLabel.textContent = `${active.vocalGender}`;
|
|
15471
15587
|
lyricBreathiness.value = String(active.vocalBreathiness);
|
|
15472
15588
|
lyricBreathinessLabel.textContent = `${active.vocalBreathiness}`;
|
|
15589
|
+
lyricTension.value = String(active.vocalTension);
|
|
15590
|
+
lyricTensionLabel.textContent = `${active.vocalTension}`;
|
|
15473
15591
|
lyricVibrato.checked = active.vocalVibrato;
|
|
15474
15592
|
lyricOctaveUnison.value = active.vocalOctaveUnison;
|
|
15475
15593
|
const updateLyricCount = () => {
|
|
@@ -15640,6 +15758,11 @@ var mountDAW = (target, options = {}) => {
|
|
|
15640
15758
|
lyricBreathinessLabel.textContent = `${active.vocalBreathiness}`;
|
|
15641
15759
|
fireLyricsChange(active);
|
|
15642
15760
|
});
|
|
15761
|
+
lyricTension.addEventListener("input", () => {
|
|
15762
|
+
active.vocalTension = Number.parseInt(lyricTension.value, 10);
|
|
15763
|
+
lyricTensionLabel.textContent = `${active.vocalTension}`;
|
|
15764
|
+
fireLyricsChange(active);
|
|
15765
|
+
});
|
|
15643
15766
|
}
|
|
15644
15767
|
if (active.config.id === "chord" && showChord) {
|
|
15645
15768
|
const div = document.createElement("div");
|
|
@@ -15844,6 +15967,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
15844
15967
|
del: t.vocalDelay,
|
|
15845
15968
|
gen: t.vocalGender,
|
|
15846
15969
|
bre: t.vocalBreathiness,
|
|
15970
|
+
ten: t.vocalTension,
|
|
15847
15971
|
uni: t.vocalOctaveUnison
|
|
15848
15972
|
})).filter(
|
|
15849
15973
|
(x2) => x2.model.length > 0 && x2.text.length > 0 && x2.notes.length > 0
|
|
@@ -15858,6 +15982,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
15858
15982
|
x2.del === 0 ? "" : `e${x2.del}`,
|
|
15859
15983
|
x2.gen === 50 ? "" : `g${x2.gen}`,
|
|
15860
15984
|
x2.bre === 50 ? "" : `h${x2.bre}`,
|
|
15985
|
+
x2.ten === 50 ? "" : `t${x2.ten}`,
|
|
15861
15986
|
OCTAVE_UNISON_TOKEN[x2.uni]
|
|
15862
15987
|
].filter((s) => s.length > 0).join(" ");
|
|
15863
15988
|
const head = params ? `${x2.model} ${params}` : x2.model;
|
|
@@ -16100,6 +16225,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
16100
16225
|
active.vocalDelay = 0;
|
|
16101
16226
|
active.vocalGender = 50;
|
|
16102
16227
|
active.vocalBreathiness = 50;
|
|
16228
|
+
active.vocalTension = 50;
|
|
16103
16229
|
active.vocalOctaveUnison = "none";
|
|
16104
16230
|
} else {
|
|
16105
16231
|
for (const t of trackStates) {
|
|
@@ -16114,6 +16240,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
16114
16240
|
t.vocalDelay = 0;
|
|
16115
16241
|
t.vocalGender = 50;
|
|
16116
16242
|
t.vocalBreathiness = 50;
|
|
16243
|
+
t.vocalTension = 50;
|
|
16117
16244
|
t.vocalOctaveUnison = "none";
|
|
16118
16245
|
}
|
|
16119
16246
|
}
|
|
@@ -16132,6 +16259,8 @@ var mountDAW = (target, options = {}) => {
|
|
|
16132
16259
|
t.vocalDelay = lt.delay ?? 0;
|
|
16133
16260
|
t.vocalGender = lt.gender ?? 50;
|
|
16134
16261
|
t.vocalBreathiness = lt.breathiness ?? 50;
|
|
16262
|
+
t.vocalTension = lt.tension ?? 50;
|
|
16263
|
+
t.vocalTension = lt.tension ?? 50;
|
|
16135
16264
|
t.vocalOctaveUnison = lt.octaveUnison ?? "none";
|
|
16136
16265
|
});
|
|
16137
16266
|
for (const p of placements) {
|
|
@@ -16216,6 +16345,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
16216
16345
|
active.vocalDelay = 0;
|
|
16217
16346
|
active.vocalGender = 50;
|
|
16218
16347
|
active.vocalBreathiness = 50;
|
|
16348
|
+
active.vocalTension = 50;
|
|
16219
16349
|
active.vocalOctaveUnison = "none";
|
|
16220
16350
|
} else {
|
|
16221
16351
|
clearAll();
|
|
@@ -16232,6 +16362,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
16232
16362
|
t.vocalDelay = 0;
|
|
16233
16363
|
t.vocalGender = 50;
|
|
16234
16364
|
t.vocalBreathiness = 50;
|
|
16365
|
+
t.vocalTension = 50;
|
|
16235
16366
|
t.vocalOctaveUnison = "none";
|
|
16236
16367
|
}
|
|
16237
16368
|
}
|
|
@@ -17596,6 +17727,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
17596
17727
|
t.vocalDelay = data.vocalDelay ?? 0;
|
|
17597
17728
|
t.vocalGender = data.vocalGender ?? 50;
|
|
17598
17729
|
t.vocalBreathiness = data.vocalBreathiness ?? 50;
|
|
17730
|
+
t.vocalTension = data.vocalTension ?? 50;
|
|
17599
17731
|
t.vocalOctaveUnison = data.vocalOctaveUnison ?? "none";
|
|
17600
17732
|
},
|
|
17601
17733
|
applyTrackInstrument: (trackIndex, instrumentName) => {
|
|
@@ -17718,6 +17850,7 @@ var playSingingMML = async (mml, options = {}) => {
|
|
|
17718
17850
|
delaySend: (lt.delay ?? 0) / 100,
|
|
17719
17851
|
gender: (lt.gender ?? 50) / 100,
|
|
17720
17852
|
breathiness: (lt.breathiness ?? 50) / 100,
|
|
17853
|
+
tension: (lt.tension ?? 50) / 100,
|
|
17721
17854
|
octaveUnison: lt.octaveUnison,
|
|
17722
17855
|
notes
|
|
17723
17856
|
};
|
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) {
|
|
@@ -9441,6 +9524,7 @@ var mountMmlPlayer = (target, mml, options = {}) => {
|
|
|
9441
9524
|
delaySend: (lt.delay ?? 0) / 100,
|
|
9442
9525
|
gender: (lt.gender ?? 50) / 100,
|
|
9443
9526
|
breathiness: (lt.breathiness ?? 50) / 100,
|
|
9527
|
+
tension: (lt.tension ?? 50) / 100,
|
|
9444
9528
|
octaveUnison: lt.octaveUnison,
|
|
9445
9529
|
notes
|
|
9446
9530
|
};
|
|
@@ -13291,6 +13375,16 @@ var BREATHINESS_INFO_HTML = `
|
|
|
13291
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>
|
|
13292
13376
|
</div>
|
|
13293
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
|
+
`;
|
|
13294
13388
|
var LYRIC_REVERB_INFO_HTML = `
|
|
13295
13389
|
<div class="dtm-modal-body-content">
|
|
13296
13390
|
<h4>\u4F55\u3092\u3059\u308B\u8A2D\u5B9A\u304B</h4>
|
|
@@ -13815,6 +13909,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
13815
13909
|
vocalDelay: t.vocalDelay,
|
|
13816
13910
|
vocalGender: t.vocalGender,
|
|
13817
13911
|
vocalBreathiness: t.vocalBreathiness,
|
|
13912
|
+
vocalTension: t.vocalTension,
|
|
13818
13913
|
vocalOctaveUnison: t.vocalOctaveUnison
|
|
13819
13914
|
};
|
|
13820
13915
|
if (lyricsDebounceTimer) clearTimeout(lyricsDebounceTimer);
|
|
@@ -13880,6 +13975,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
13880
13975
|
vocalDelay: 0,
|
|
13881
13976
|
vocalGender: 50,
|
|
13882
13977
|
vocalBreathiness: 50,
|
|
13978
|
+
vocalTension: 50,
|
|
13883
13979
|
vocalOctaveUnison: "none",
|
|
13884
13980
|
trackInstrument: "",
|
|
13885
13981
|
trackCompression: 0,
|
|
@@ -13911,6 +14007,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
13911
14007
|
delay: t.vocalDelay,
|
|
13912
14008
|
gender: t.vocalGender,
|
|
13913
14009
|
breathiness: t.vocalBreathiness,
|
|
14010
|
+
tension: t.vocalTension,
|
|
13914
14011
|
octaveUnison: t.vocalOctaveUnison,
|
|
13915
14012
|
syllables
|
|
13916
14013
|
});
|
|
@@ -14721,6 +14818,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
14721
14818
|
delaySend: (lt.delay ?? 0) / 100,
|
|
14722
14819
|
gender: (lt.gender ?? 50) / 100,
|
|
14723
14820
|
breathiness: (lt.breathiness ?? 50) / 100,
|
|
14821
|
+
tension: (lt.tension ?? 50) / 100,
|
|
14724
14822
|
octaveUnison: lt.octaveUnison,
|
|
14725
14823
|
notes
|
|
14726
14824
|
};
|
|
@@ -15149,6 +15247,12 @@ var mountDAW = (target, options = {}) => {
|
|
|
15149
15247
|
<span class="dtm-label" data-dtm="lyric-breathiness-label"></span>
|
|
15150
15248
|
<button class="dtm-infobtn" data-dtm="lyric-breathiness-info" title="\u30D6\u30EC\u30B7\u30CD\u30B9\u306E\u89E3\u8AAC">${icon("info", 12)}</button>
|
|
15151
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>
|
|
15152
15256
|
<div class="dtm-row">
|
|
15153
15257
|
<span class="dtm-label" style="display:inline-flex;align-items:center;gap:2px">
|
|
15154
15258
|
<input type="checkbox" data-dtm="lyric-vibrato" aria-label="\u81EA\u52D5\u30D3\u30D6\u30E9\u30FC\u30C8">\u30D3\u30D6\u30E9\u30FC\u30C8
|
|
@@ -15252,6 +15356,18 @@ var mountDAW = (target, options = {}) => {
|
|
|
15252
15356
|
lyricBreathinessInfo.addEventListener("click", () => {
|
|
15253
15357
|
showModal("\u30D6\u30EC\u30B7\u30CD\u30B9\u306E\u89E3\u8AAC", BREATHINESS_INFO_HTML);
|
|
15254
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
|
+
});
|
|
15255
15371
|
const lyricVibrato = lyricDiv.querySelector(
|
|
15256
15372
|
'[data-dtm="lyric-vibrato"]'
|
|
15257
15373
|
);
|
|
@@ -15339,6 +15455,8 @@ var mountDAW = (target, options = {}) => {
|
|
|
15339
15455
|
lyricGenderLabel.textContent = `${active.vocalGender}`;
|
|
15340
15456
|
lyricBreathiness.value = String(active.vocalBreathiness);
|
|
15341
15457
|
lyricBreathinessLabel.textContent = `${active.vocalBreathiness}`;
|
|
15458
|
+
lyricTension.value = String(active.vocalTension);
|
|
15459
|
+
lyricTensionLabel.textContent = `${active.vocalTension}`;
|
|
15342
15460
|
lyricVibrato.checked = active.vocalVibrato;
|
|
15343
15461
|
lyricOctaveUnison.value = active.vocalOctaveUnison;
|
|
15344
15462
|
const updateLyricCount = () => {
|
|
@@ -15509,6 +15627,11 @@ var mountDAW = (target, options = {}) => {
|
|
|
15509
15627
|
lyricBreathinessLabel.textContent = `${active.vocalBreathiness}`;
|
|
15510
15628
|
fireLyricsChange(active);
|
|
15511
15629
|
});
|
|
15630
|
+
lyricTension.addEventListener("input", () => {
|
|
15631
|
+
active.vocalTension = Number.parseInt(lyricTension.value, 10);
|
|
15632
|
+
lyricTensionLabel.textContent = `${active.vocalTension}`;
|
|
15633
|
+
fireLyricsChange(active);
|
|
15634
|
+
});
|
|
15512
15635
|
}
|
|
15513
15636
|
if (active.config.id === "chord" && showChord) {
|
|
15514
15637
|
const div = document.createElement("div");
|
|
@@ -15713,6 +15836,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
15713
15836
|
del: t.vocalDelay,
|
|
15714
15837
|
gen: t.vocalGender,
|
|
15715
15838
|
bre: t.vocalBreathiness,
|
|
15839
|
+
ten: t.vocalTension,
|
|
15716
15840
|
uni: t.vocalOctaveUnison
|
|
15717
15841
|
})).filter(
|
|
15718
15842
|
(x2) => x2.model.length > 0 && x2.text.length > 0 && x2.notes.length > 0
|
|
@@ -15727,6 +15851,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
15727
15851
|
x2.del === 0 ? "" : `e${x2.del}`,
|
|
15728
15852
|
x2.gen === 50 ? "" : `g${x2.gen}`,
|
|
15729
15853
|
x2.bre === 50 ? "" : `h${x2.bre}`,
|
|
15854
|
+
x2.ten === 50 ? "" : `t${x2.ten}`,
|
|
15730
15855
|
OCTAVE_UNISON_TOKEN[x2.uni]
|
|
15731
15856
|
].filter((s) => s.length > 0).join(" ");
|
|
15732
15857
|
const head = params ? `${x2.model} ${params}` : x2.model;
|
|
@@ -15969,6 +16094,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
15969
16094
|
active.vocalDelay = 0;
|
|
15970
16095
|
active.vocalGender = 50;
|
|
15971
16096
|
active.vocalBreathiness = 50;
|
|
16097
|
+
active.vocalTension = 50;
|
|
15972
16098
|
active.vocalOctaveUnison = "none";
|
|
15973
16099
|
} else {
|
|
15974
16100
|
for (const t of trackStates) {
|
|
@@ -15983,6 +16109,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
15983
16109
|
t.vocalDelay = 0;
|
|
15984
16110
|
t.vocalGender = 50;
|
|
15985
16111
|
t.vocalBreathiness = 50;
|
|
16112
|
+
t.vocalTension = 50;
|
|
15986
16113
|
t.vocalOctaveUnison = "none";
|
|
15987
16114
|
}
|
|
15988
16115
|
}
|
|
@@ -16001,6 +16128,8 @@ var mountDAW = (target, options = {}) => {
|
|
|
16001
16128
|
t.vocalDelay = lt.delay ?? 0;
|
|
16002
16129
|
t.vocalGender = lt.gender ?? 50;
|
|
16003
16130
|
t.vocalBreathiness = lt.breathiness ?? 50;
|
|
16131
|
+
t.vocalTension = lt.tension ?? 50;
|
|
16132
|
+
t.vocalTension = lt.tension ?? 50;
|
|
16004
16133
|
t.vocalOctaveUnison = lt.octaveUnison ?? "none";
|
|
16005
16134
|
});
|
|
16006
16135
|
for (const p of placements) {
|
|
@@ -16085,6 +16214,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
16085
16214
|
active.vocalDelay = 0;
|
|
16086
16215
|
active.vocalGender = 50;
|
|
16087
16216
|
active.vocalBreathiness = 50;
|
|
16217
|
+
active.vocalTension = 50;
|
|
16088
16218
|
active.vocalOctaveUnison = "none";
|
|
16089
16219
|
} else {
|
|
16090
16220
|
clearAll();
|
|
@@ -16101,6 +16231,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
16101
16231
|
t.vocalDelay = 0;
|
|
16102
16232
|
t.vocalGender = 50;
|
|
16103
16233
|
t.vocalBreathiness = 50;
|
|
16234
|
+
t.vocalTension = 50;
|
|
16104
16235
|
t.vocalOctaveUnison = "none";
|
|
16105
16236
|
}
|
|
16106
16237
|
}
|
|
@@ -17465,6 +17596,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
17465
17596
|
t.vocalDelay = data.vocalDelay ?? 0;
|
|
17466
17597
|
t.vocalGender = data.vocalGender ?? 50;
|
|
17467
17598
|
t.vocalBreathiness = data.vocalBreathiness ?? 50;
|
|
17599
|
+
t.vocalTension = data.vocalTension ?? 50;
|
|
17468
17600
|
t.vocalOctaveUnison = data.vocalOctaveUnison ?? "none";
|
|
17469
17601
|
},
|
|
17470
17602
|
applyTrackInstrument: (trackIndex, instrumentName) => {
|
|
@@ -17587,6 +17719,7 @@ var playSingingMML = async (mml, options = {}) => {
|
|
|
17587
17719
|
delaySend: (lt.delay ?? 0) / 100,
|
|
17588
17720
|
gender: (lt.gender ?? 50) / 100,
|
|
17589
17721
|
breathiness: (lt.breathiness ?? 50) / 100,
|
|
17722
|
+
tension: (lt.tension ?? 50) / 100,
|
|
17590
17723
|
octaveUnison: lt.octaveUnison,
|
|
17591
17724
|
notes
|
|
17592
17725
|
};
|
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