@onjmin/dtm 2.0.3 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +39 -0
- package/dist/index.d.mts +786 -7
- package/dist/index.d.ts +786 -7
- package/dist/index.js +4241 -283
- package/dist/index.mjs +4213 -283
- package/dist/voice-worker.js +64 -13
- package/package.json +2 -1
package/dist/voice-worker.js
CHANGED
|
@@ -517,12 +517,60 @@
|
|
|
517
517
|
var VIBRATO_RATE_HZ = 5.5;
|
|
518
518
|
var VIBRATO_DEPTH_CENTS = 35;
|
|
519
519
|
var VIBRATO_FADE_MS = 150;
|
|
520
|
-
var
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
const
|
|
524
|
-
|
|
525
|
-
|
|
520
|
+
var vibratoRatio = (sinceOnsetMs) => {
|
|
521
|
+
if (sinceOnsetMs <= 0) return 1;
|
|
522
|
+
const depth = VIBRATO_DEPTH_CENTS * Math.min(1, sinceOnsetMs / VIBRATO_FADE_MS);
|
|
523
|
+
const cents = depth * Math.sin(2 * Math.PI * VIBRATO_RATE_HZ * sinceOnsetMs / 1e3);
|
|
524
|
+
return 2 ** (cents / 1200);
|
|
525
|
+
};
|
|
526
|
+
|
|
527
|
+
// src/pitch-curve.ts
|
|
528
|
+
var STEP_GLIDE_MS = 15;
|
|
529
|
+
var PORTAMENTO_MS = 70;
|
|
530
|
+
var MIN_GLIDE_MS = 4;
|
|
531
|
+
var unitsToHz = (units) => 440 * 2 ** ((units - 2139) / 372);
|
|
532
|
+
var smoothstep = (u) => u * u * (3 - 2 * u);
|
|
533
|
+
var toKeyframes = (segments) => {
|
|
534
|
+
const kf = [];
|
|
535
|
+
let prevAtMs = 0;
|
|
536
|
+
for (const seg of segments) {
|
|
537
|
+
const atMs = seg.atSec * 1e3;
|
|
538
|
+
const glideMs = Math.max(
|
|
539
|
+
MIN_GLIDE_MS,
|
|
540
|
+
Math.min(
|
|
541
|
+
seg.portamento ? PORTAMENTO_MS : STEP_GLIDE_MS,
|
|
542
|
+
(atMs - prevAtMs) * 0.5
|
|
543
|
+
)
|
|
544
|
+
);
|
|
545
|
+
kf.push({
|
|
546
|
+
hz: unitsToHz(seg.pitch),
|
|
547
|
+
startMs: Math.max(0, atMs - glideMs / 2),
|
|
548
|
+
glideMs
|
|
549
|
+
});
|
|
550
|
+
prevAtMs = atMs;
|
|
551
|
+
}
|
|
552
|
+
return kf;
|
|
553
|
+
};
|
|
554
|
+
var pitchCurveFor = (baseHz, segments, preMs, vibrato) => {
|
|
555
|
+
const kf = segments?.length ? toKeyframes(segments) : null;
|
|
556
|
+
if (!kf && !vibrato) return baseHz;
|
|
557
|
+
return (tMs) => {
|
|
558
|
+
const sinceOnset = tMs - preMs;
|
|
559
|
+
let hz = baseHz;
|
|
560
|
+
if (kf && sinceOnset > 0) {
|
|
561
|
+
for (const k of kf) {
|
|
562
|
+
if (sinceOnset >= k.startMs + k.glideMs) {
|
|
563
|
+
hz = k.hz;
|
|
564
|
+
continue;
|
|
565
|
+
}
|
|
566
|
+
if (sinceOnset <= k.startMs) break;
|
|
567
|
+
const u = smoothstep((sinceOnset - k.startMs) / k.glideMs);
|
|
568
|
+
hz = hz * (k.hz / hz) ** u;
|
|
569
|
+
break;
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
return vibrato ? hz * vibratoRatio(sinceOnset) : hz;
|
|
573
|
+
};
|
|
526
574
|
};
|
|
527
575
|
|
|
528
576
|
// src/voice-worker-types.ts
|
|
@@ -567,7 +615,7 @@
|
|
|
567
615
|
const consonantMs = (consonantPcm.length - xfade / 2) / sampleRate * 1e3;
|
|
568
616
|
return { pcm, preMs: consonantMs, consonantMs };
|
|
569
617
|
};
|
|
570
|
-
var renderComposite = async (consonantAlias, vowelAlias, pitch, durationMs, vibrato, gender, breathiness, tension) => {
|
|
618
|
+
var renderComposite = async (consonantAlias, vowelAlias, pitch, durationMs, vibrato, gender, breathiness, tension, pitchSegments) => {
|
|
571
619
|
if (!worldline) return null;
|
|
572
620
|
const [consonantPcm, vowelPcm] = await Promise.all([
|
|
573
621
|
getPcm(consonantAlias),
|
|
@@ -579,7 +627,7 @@
|
|
|
579
627
|
const targetHz = unitsToFreq(pitch);
|
|
580
628
|
const audio = worldline.renderNote({
|
|
581
629
|
pcm: spliced.pcm,
|
|
582
|
-
pitch:
|
|
630
|
+
pitch: pitchCurveFor(targetHz, pitchSegments, spliced.preMs, !!vibrato),
|
|
583
631
|
durationMs,
|
|
584
632
|
preMs: spliced.preMs,
|
|
585
633
|
consonantMs: spliced.consonantMs,
|
|
@@ -589,7 +637,7 @@
|
|
|
589
637
|
});
|
|
590
638
|
return audio ? { pcm: audio, preSec: spliced.preMs / 1e3, rate: 1 } : null;
|
|
591
639
|
};
|
|
592
|
-
var renderAlias = async (alias, pitch, durationMs, vibrato, gender, breathiness, tension) => {
|
|
640
|
+
var renderAlias = async (alias, pitch, durationMs, vibrato, gender, breathiness, tension, pitchSegments) => {
|
|
593
641
|
if (!bank) return null;
|
|
594
642
|
const composite = unpackCompositeAlias(alias);
|
|
595
643
|
if (composite) {
|
|
@@ -601,7 +649,8 @@
|
|
|
601
649
|
vibrato,
|
|
602
650
|
gender,
|
|
603
651
|
breathiness,
|
|
604
|
-
tension
|
|
652
|
+
tension,
|
|
653
|
+
pitchSegments
|
|
605
654
|
);
|
|
606
655
|
}
|
|
607
656
|
const pcm = await getPcm(alias);
|
|
@@ -612,7 +661,7 @@
|
|
|
612
661
|
if (worldline) {
|
|
613
662
|
const audio = worldline.renderNote({
|
|
614
663
|
pcm,
|
|
615
|
-
pitch:
|
|
664
|
+
pitch: pitchCurveFor(targetHz, pitchSegments, lead.preMs, !!vibrato),
|
|
616
665
|
durationMs,
|
|
617
666
|
...lead,
|
|
618
667
|
gender,
|
|
@@ -657,7 +706,8 @@
|
|
|
657
706
|
vibrato,
|
|
658
707
|
gender,
|
|
659
708
|
breathiness,
|
|
660
|
-
tension
|
|
709
|
+
tension,
|
|
710
|
+
pitchSegments
|
|
661
711
|
} = msg;
|
|
662
712
|
try {
|
|
663
713
|
const out = await renderAlias(
|
|
@@ -667,7 +717,8 @@
|
|
|
667
717
|
vibrato,
|
|
668
718
|
gender,
|
|
669
719
|
breathiness,
|
|
670
|
-
tension
|
|
720
|
+
tension,
|
|
721
|
+
pitchSegments
|
|
671
722
|
);
|
|
672
723
|
if (out) {
|
|
673
724
|
wself.postMessage(
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"author": "onjmin",
|
|
3
3
|
"license": "MIT",
|
|
4
4
|
"name": "@onjmin/dtm",
|
|
5
|
-
"version": "2.0
|
|
5
|
+
"version": "2.1.0",
|
|
6
6
|
"description": "MMLを中間言語に用いた、モバイルファーストなDAW / ピアノロール打ち込みコンポーネント",
|
|
7
7
|
"homepage": "https://onjmin.github.io/dtm",
|
|
8
8
|
"repository": {
|
|
@@ -62,6 +62,7 @@
|
|
|
62
62
|
"dev": "rimraf dist && tsup && biome format src --write && tsx demo/server.ts",
|
|
63
63
|
"build": "rimraf dist && tsup && biome format src --write",
|
|
64
64
|
"check": "biome check src --write",
|
|
65
|
+
"test": "tsx scripts/check-compose.ts",
|
|
65
66
|
"patch": "pnpm version patch",
|
|
66
67
|
"minor": "pnpm version minor",
|
|
67
68
|
"major": "pnpm version major",
|