@kongyo2/kongyoroid 1.0.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/LICENSE +21 -0
- package/README.md +7 -0
- package/dist/cache.d.ts +36 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +109 -0
- package/dist/cache.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +502 -0
- package/dist/cli.js.map +1 -0
- package/dist/concurrency.d.ts +14 -0
- package/dist/concurrency.d.ts.map +1 -0
- package/dist/concurrency.js +107 -0
- package/dist/concurrency.js.map +1 -0
- package/dist/errors.d.ts +35 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +81 -0
- package/dist/errors.js.map +1 -0
- package/dist/formant.d.ts +34 -0
- package/dist/formant.d.ts.map +1 -0
- package/dist/formant.js +622 -0
- package/dist/formant.js.map +1 -0
- package/dist/index.d.ts +40 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +23 -0
- package/dist/index.js.map +1 -0
- package/dist/io.d.ts +6 -0
- package/dist/io.d.ts.map +1 -0
- package/dist/io.js +144 -0
- package/dist/io.js.map +1 -0
- package/dist/kongyoroid.d.ts +82 -0
- package/dist/kongyoroid.d.ts.map +1 -0
- package/dist/kongyoroid.js +275 -0
- package/dist/kongyoroid.js.map +1 -0
- package/dist/limits.d.ts +18 -0
- package/dist/limits.d.ts.map +1 -0
- package/dist/limits.js +15 -0
- package/dist/limits.js.map +1 -0
- package/dist/mora.d.ts +28 -0
- package/dist/mora.d.ts.map +1 -0
- package/dist/mora.js +295 -0
- package/dist/mora.js.map +1 -0
- package/dist/notation.d.ts +15 -0
- package/dist/notation.d.ts.map +1 -0
- package/dist/notation.js +114 -0
- package/dist/notation.js.map +1 -0
- package/dist/pitch.d.ts +5 -0
- package/dist/pitch.d.ts.map +1 -0
- package/dist/pitch.js +36 -0
- package/dist/pitch.js.map +1 -0
- package/dist/player.d.ts +9 -0
- package/dist/player.d.ts.map +1 -0
- package/dist/player.js +81 -0
- package/dist/player.js.map +1 -0
- package/dist/request.d.ts +12 -0
- package/dist/request.d.ts.map +1 -0
- package/dist/request.js +115 -0
- package/dist/request.js.map +1 -0
- package/dist/schema.d.ts +9 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +267 -0
- package/dist/schema.js.map +1 -0
- package/dist/score.d.ts +37 -0
- package/dist/score.d.ts.map +1 -0
- package/dist/score.js +166 -0
- package/dist/score.js.map +1 -0
- package/dist/text.d.ts +3 -0
- package/dist/text.d.ts.map +1 -0
- package/dist/text.js +54 -0
- package/dist/text.js.map +1 -0
- package/dist/types.d.ts +121 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/validate.d.ts +13 -0
- package/dist/validate.d.ts.map +1 -0
- package/dist/validate.js +59 -0
- package/dist/validate.js.map +1 -0
- package/dist/version.d.ts +3 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +3 -0
- package/dist/version.js.map +1 -0
- package/dist/voicevox/api.d.ts +79 -0
- package/dist/voicevox/api.d.ts.map +1 -0
- package/dist/voicevox/api.js +176 -0
- package/dist/voicevox/api.js.map +1 -0
- package/dist/voicevox/client.d.ts +64 -0
- package/dist/voicevox/client.d.ts.map +1 -0
- package/dist/voicevox/client.js +321 -0
- package/dist/voicevox/client.js.map +1 -0
- package/dist/voicevox/dictionary.d.ts +21 -0
- package/dist/voicevox/dictionary.d.ts.map +1 -0
- package/dist/voicevox/dictionary.js +41 -0
- package/dist/voicevox/dictionary.js.map +1 -0
- package/dist/voicevox/song.d.ts +12 -0
- package/dist/voicevox/song.d.ts.map +1 -0
- package/dist/voicevox/song.js +45 -0
- package/dist/voicevox/song.js.map +1 -0
- package/dist/voicevox/speech.d.ts +17 -0
- package/dist/voicevox/speech.d.ts.map +1 -0
- package/dist/voicevox/speech.js +100 -0
- package/dist/voicevox/speech.js.map +1 -0
- package/dist/voicevox/styles.d.ts +15 -0
- package/dist/voicevox/styles.d.ts.map +1 -0
- package/dist/voicevox/styles.js +103 -0
- package/dist/voicevox/styles.js.map +1 -0
- package/dist/wav.d.ts +18 -0
- package/dist/wav.d.ts.map +1 -0
- package/dist/wav.js +198 -0
- package/dist/wav.js.map +1 -0
- package/examples/batch.jsonl +4 -0
- package/examples/song-notes.json +24 -0
- package/examples/song.json +12 -0
- package/examples/speech-kana.json +6 -0
- package/examples/speech.json +8 -0
- package/package.json +86 -0
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { mapConcurrent } from "../concurrency.js";
|
|
2
|
+
import { invalid } from "../errors.js";
|
|
3
|
+
import { LIMITS } from "../limits.js";
|
|
4
|
+
import { splitText } from "../text.js";
|
|
5
|
+
import { concatWav, inspectWav } from "../wav.js";
|
|
6
|
+
import { protocolError } from "./api.js";
|
|
7
|
+
export function querySeconds(query) {
|
|
8
|
+
let seconds = query.prePhonemeLength + query.postPhonemeLength;
|
|
9
|
+
for (const phrase of query.accent_phrases) {
|
|
10
|
+
const moras = phrase.pause_mora === null ? phrase.moras : [...phrase.moras, phrase.pause_mora];
|
|
11
|
+
for (const mora of moras) {
|
|
12
|
+
const pause = mora.vowel === "pau";
|
|
13
|
+
const base = pause && query.pauseLength !== null ? query.pauseLength : mora.vowel_length;
|
|
14
|
+
const vowel = pause ? base * query.pauseLengthScale : base;
|
|
15
|
+
seconds += (vowel + (mora.consonant_length ?? 0)) / query.speedScale;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return seconds;
|
|
19
|
+
}
|
|
20
|
+
export function applySpeechSettings(phrases, request, sampleRate, kana) {
|
|
21
|
+
return {
|
|
22
|
+
accent_phrases: phrases,
|
|
23
|
+
speedScale: request.speed,
|
|
24
|
+
pitchScale: request.pitch,
|
|
25
|
+
intonationScale: request.intonation,
|
|
26
|
+
volumeScale: request.volume,
|
|
27
|
+
prePhonemeLength: request.prePause,
|
|
28
|
+
postPhonemeLength: request.postPause,
|
|
29
|
+
pauseLength: request.pauseLength ?? null,
|
|
30
|
+
pauseLengthScale: request.pauseScale,
|
|
31
|
+
outputSamplingRate: sampleRate,
|
|
32
|
+
outputStereo: false,
|
|
33
|
+
kana,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
export async function synthesizeSpeech(client, request, speaker, options = {}) {
|
|
37
|
+
const manifest = await client.manifest(options);
|
|
38
|
+
const sampleRate = request.sampleRate ?? manifest.defaultSamplingRate;
|
|
39
|
+
const chunks = request.kana === undefined ? splitText(request.text, request.split) : [request.text];
|
|
40
|
+
let budget = LIMITS.audioSeconds;
|
|
41
|
+
const parts = await mapConcurrent(chunks, options.concurrency ?? 2, async (chunk) => {
|
|
42
|
+
const query = request.kana === undefined
|
|
43
|
+
? applySpeechSettings((await client.audioQuery(chunk, speaker.id, options)).accent_phrases, request, sampleRate, "")
|
|
44
|
+
: applySpeechSettings(await client.accentPhrases(request.kana, speaker.id, true, options), request, sampleRate, request.kana);
|
|
45
|
+
const kana = request.kana ?? chunkKana(query);
|
|
46
|
+
const seconds = querySeconds(query);
|
|
47
|
+
budget -= seconds;
|
|
48
|
+
if (budget < 0) {
|
|
49
|
+
invalid("$.text", `The text would produce more than ${LIMITS.audioSeconds} s of audio.`, "Split the text into separate requests.");
|
|
50
|
+
}
|
|
51
|
+
const audio = await client.synthesis(query, speaker.id, request.upspeak, options);
|
|
52
|
+
const info = inspectWav(audio);
|
|
53
|
+
if (info.channels !== 1 || info.sampleRate !== sampleRate) {
|
|
54
|
+
throw protocolError(`synthesis returned ${info.channels} channel(s) at ${info.sampleRate} Hz, expected mono ${sampleRate} Hz`);
|
|
55
|
+
}
|
|
56
|
+
return { audio, kana };
|
|
57
|
+
}, options.signal);
|
|
58
|
+
return {
|
|
59
|
+
audio: parts.length === 1 ? (parts[0]?.audio ?? new Uint8Array(0)) : concatWav(parts.map((part) => part.audio)),
|
|
60
|
+
kana: parts.map((part) => part.kana).join("/"),
|
|
61
|
+
chunks: parts.length,
|
|
62
|
+
sampleRate,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
function chunkKana(query) {
|
|
66
|
+
if (query.kana.length > 0)
|
|
67
|
+
return query.kana;
|
|
68
|
+
let text = "";
|
|
69
|
+
for (const [phraseIndex, phrase] of query.accent_phrases.entries()) {
|
|
70
|
+
for (const [index, mora] of phrase.moras.entries()) {
|
|
71
|
+
if (/^[AIUEO]$/u.test(mora.vowel))
|
|
72
|
+
text += "_";
|
|
73
|
+
text += mora.text;
|
|
74
|
+
if (index + 1 === phrase.accent)
|
|
75
|
+
text += "'";
|
|
76
|
+
}
|
|
77
|
+
if (phrase.is_interrogative)
|
|
78
|
+
text += "?";
|
|
79
|
+
if (phraseIndex < query.accent_phrases.length - 1)
|
|
80
|
+
text += phrase.pause_mora === null ? "/" : "、";
|
|
81
|
+
}
|
|
82
|
+
return text;
|
|
83
|
+
}
|
|
84
|
+
export function accentPhrasesToKana(phrases) {
|
|
85
|
+
return chunkKana({
|
|
86
|
+
accent_phrases: phrases,
|
|
87
|
+
speedScale: 1,
|
|
88
|
+
pitchScale: 0,
|
|
89
|
+
intonationScale: 1,
|
|
90
|
+
volumeScale: 1,
|
|
91
|
+
prePhonemeLength: 0,
|
|
92
|
+
postPhonemeLength: 0,
|
|
93
|
+
pauseLength: null,
|
|
94
|
+
pauseLengthScale: 1,
|
|
95
|
+
outputSamplingRate: 24000,
|
|
96
|
+
outputStereo: false,
|
|
97
|
+
kana: "",
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=speech.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"speech.js","sourceRoot":"","sources":["../../src/voicevox/speech.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { OperationOptions, StyleRef, StyleSelection, VoiceStyle } from "../types.ts";
|
|
2
|
+
import type { VoicevoxClient } from "./client.ts";
|
|
3
|
+
export type StylePurpose = "speaker" | "singer" | "teacher";
|
|
4
|
+
export declare function toSelection(style: VoiceStyle): StyleSelection;
|
|
5
|
+
export declare function describeStyle(style: VoiceStyle): string;
|
|
6
|
+
export declare class StyleCatalog {
|
|
7
|
+
private readonly client;
|
|
8
|
+
private cache;
|
|
9
|
+
constructor(client: VoicevoxClient);
|
|
10
|
+
refresh(): void;
|
|
11
|
+
all(options?: OperationOptions): Promise<readonly VoiceStyle[]>;
|
|
12
|
+
byPurpose(purpose: StylePurpose, options?: OperationOptions): Promise<readonly VoiceStyle[]>;
|
|
13
|
+
resolve(ref: StyleRef | undefined, purpose: StylePurpose, options?: OperationOptions): Promise<StyleSelection>;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=styles.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../../src/voicevox/styles.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,QAAQ,EAAE,cAAc,EAAa,UAAU,EAAE,MAAM,aAAa,CAAC;AACrG,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAC;AAkB5D,wBAAgB,WAAW,CAAC,KAAK,EAAE,UAAU,GAAG,cAAc,CAE7D;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAEvD;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiB;IACxC,OAAO,CAAC,KAAK,CAA6C;gBAEvC,MAAM,EAAE,cAAc;IAIlC,OAAO,IAAI,IAAI;IAIf,GAAG,CAAC,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC,SAAS,UAAU,EAAE,CAAC;IAmB7D,SAAS,CAAC,OAAO,EAAE,YAAY,EAAE,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC,SAAS,UAAU,EAAE,CAAC;IAKhG,OAAO,CAClB,GAAG,EAAE,QAAQ,GAAG,SAAS,EACzB,OAAO,EAAE,YAAY,EACrB,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,cAAc,CAAC;CA8D3B"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { invalid } from "../errors.js";
|
|
2
|
+
const ACCEPTED = {
|
|
3
|
+
speaker: ["talk", "streaming_talk"],
|
|
4
|
+
singer: ["frame_decode", "sing"],
|
|
5
|
+
teacher: ["singing_teacher", "sing"],
|
|
6
|
+
};
|
|
7
|
+
const PURPOSE_HINT = {
|
|
8
|
+
speaker: "Speech needs a style of type talk. Run the voices command to list them.",
|
|
9
|
+
singer: "Singing needs a style of type frame_decode or sing. Run voices --kind song to list them.",
|
|
10
|
+
teacher: "A teacher needs a style of type singing_teacher or sing. Run voices --kind song to list them.",
|
|
11
|
+
};
|
|
12
|
+
function normalize(text) {
|
|
13
|
+
return text.normalize("NFKC").trim().toLowerCase();
|
|
14
|
+
}
|
|
15
|
+
export function toSelection(style) {
|
|
16
|
+
return { id: style.id, name: style.name, character: style.character, type: style.type };
|
|
17
|
+
}
|
|
18
|
+
export function describeStyle(style) {
|
|
19
|
+
return `${style.id}: ${style.character}/${style.name} (${style.type})`;
|
|
20
|
+
}
|
|
21
|
+
export class StyleCatalog {
|
|
22
|
+
client;
|
|
23
|
+
cache;
|
|
24
|
+
constructor(client) {
|
|
25
|
+
this.client = client;
|
|
26
|
+
}
|
|
27
|
+
refresh() {
|
|
28
|
+
this.cache = undefined;
|
|
29
|
+
}
|
|
30
|
+
all(options = {}) {
|
|
31
|
+
this.cache ??= Promise.all([this.client.speakers(options), this.client.singers(options)])
|
|
32
|
+
.then(([speakers, singers]) => {
|
|
33
|
+
const seen = new Set();
|
|
34
|
+
const merged = [];
|
|
35
|
+
for (const style of [...speakers, ...singers]) {
|
|
36
|
+
if (seen.has(style.id))
|
|
37
|
+
continue;
|
|
38
|
+
seen.add(style.id);
|
|
39
|
+
merged.push(style);
|
|
40
|
+
}
|
|
41
|
+
return merged;
|
|
42
|
+
})
|
|
43
|
+
.catch((error) => {
|
|
44
|
+
this.cache = undefined;
|
|
45
|
+
throw error;
|
|
46
|
+
});
|
|
47
|
+
return this.cache;
|
|
48
|
+
}
|
|
49
|
+
async byPurpose(purpose, options = {}) {
|
|
50
|
+
const accepted = ACCEPTED[purpose];
|
|
51
|
+
return (await this.all(options)).filter((style) => accepted.includes(style.type));
|
|
52
|
+
}
|
|
53
|
+
async resolve(ref, purpose, options = {}) {
|
|
54
|
+
const path = `$.${purpose}`;
|
|
55
|
+
const all = await this.all(options);
|
|
56
|
+
const accepted = ACCEPTED[purpose];
|
|
57
|
+
const candidates = all.filter((style) => accepted.includes(style.type));
|
|
58
|
+
if (ref === undefined) {
|
|
59
|
+
const first = candidates[0];
|
|
60
|
+
if (first === undefined) {
|
|
61
|
+
invalid(path, `The engine offers no style usable as ${purpose}.`, PURPOSE_HINT[purpose]);
|
|
62
|
+
}
|
|
63
|
+
return toSelection(first);
|
|
64
|
+
}
|
|
65
|
+
if (typeof ref === "number") {
|
|
66
|
+
const exact = all.find((style) => style.id === ref);
|
|
67
|
+
if (exact === undefined) {
|
|
68
|
+
invalid(path, `No style has id ${ref}.`, PURPOSE_HINT[purpose]);
|
|
69
|
+
}
|
|
70
|
+
if (!accepted.includes(exact.type)) {
|
|
71
|
+
invalid(path, `Style ${describeStyle(exact)} cannot be used as ${purpose}.`, `${PURPOSE_HINT[purpose]} Usable: ${candidates.slice(0, 8).map(describeStyle).join(", ")}.`);
|
|
72
|
+
}
|
|
73
|
+
return toSelection(exact);
|
|
74
|
+
}
|
|
75
|
+
const query = normalize(ref);
|
|
76
|
+
const [characterPart, stylePart] = query.split(/[//]/u, 2);
|
|
77
|
+
const character = characterPart ?? query;
|
|
78
|
+
const byCharacter = candidates.filter((style) => normalize(style.character) === character);
|
|
79
|
+
if (byCharacter.length > 0) {
|
|
80
|
+
const firstOfCharacter = byCharacter[0];
|
|
81
|
+
if (firstOfCharacter !== undefined && (stylePart === undefined || stylePart.length === 0)) {
|
|
82
|
+
return toSelection(firstOfCharacter);
|
|
83
|
+
}
|
|
84
|
+
const exact = byCharacter.find((style) => normalize(style.name) === stylePart);
|
|
85
|
+
if (exact !== undefined)
|
|
86
|
+
return toSelection(exact);
|
|
87
|
+
invalid(path, `${ref}: character found but no ${purpose} style named ${JSON.stringify(stylePart)}.`, `Styles for this character: ${byCharacter.map((s) => `${s.name} (${s.id})`).join(", ")}.`);
|
|
88
|
+
}
|
|
89
|
+
const byStyleName = candidates.find((style) => normalize(style.name) === query);
|
|
90
|
+
if (byStyleName !== undefined)
|
|
91
|
+
return toSelection(byStyleName);
|
|
92
|
+
const partial = candidates.filter((style) => normalize(style.character).includes(character) || normalize(`${style.character}/${style.name}`).includes(query));
|
|
93
|
+
const characters = new Set(partial.map((style) => style.character));
|
|
94
|
+
const firstPartial = partial[0];
|
|
95
|
+
if (firstPartial !== undefined && characters.size === 1 && (stylePart === undefined || stylePart.length === 0)) {
|
|
96
|
+
return toSelection(firstPartial);
|
|
97
|
+
}
|
|
98
|
+
return invalid(path, `No ${purpose} style matches ${JSON.stringify(ref)}.`, partial.length > 0
|
|
99
|
+
? `Did you mean: ${partial.slice(0, 8).map(describeStyle).join(", ")}?`
|
|
100
|
+
: `${PURPOSE_HINT[purpose]} Available: ${candidates.slice(0, 8).map(describeStyle).join(", ")}.`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=styles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"styles.js","sourceRoot":"","sources":["../../src/voicevox/styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAMvC,MAAM,QAAQ,GAAyD;IACrE,OAAO,EAAE,CAAC,MAAM,EAAE,gBAAgB,CAAC;IACnC,MAAM,EAAE,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,OAAO,EAAE,CAAC,iBAAiB,EAAE,MAAM,CAAC;CACrC,CAAC;AAEF,MAAM,YAAY,GAA2C;IAC3D,OAAO,EAAE,yEAAyE;IAClF,MAAM,EAAE,0FAA0F;IAClG,OAAO,EAAE,+FAA+F;CACzG,CAAC;AAEF,SAAS,SAAS,CAAC,IAAY;IAC7B,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;AACrD,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAiB;IAC3C,OAAO,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC;AAC1F,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAAiB;IAC7C,OAAO,GAAG,KAAK,CAAC,EAAE,KAAK,KAAK,CAAC,SAAS,IAAI,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,IAAI,GAAG,CAAC;AACzE,CAAC;AAED,MAAM,OAAO,YAAY;IACN,MAAM,CAAiB;IAChC,KAAK,CAA6C;IAE1D,YAAmB,MAAsB;QACvC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAEM,OAAO;QACZ,IAAI,CAAC,KAAK,GAAG,SAAS,CAAC;IACzB,CAAC;IAEM,GAAG,CAAC,UAA4B,EAAE;QACvC,IAAI,CAAC,KAAK,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;aACtF,IAAI,CAAC,CAAC,CAAC,QAAQ,EAAE,OAAO,CAAC,EAAE,EAAE;YAC5B,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;YAC/B,MAAM,MAAM,GAAiB,EAAE,CAAC;YAChC,KAAK,MAAM,KAAK,IAAI,CAAC,GAAG,QAAQ,EAAE,GAAG,OAAO,CAAC,EAAE,CAAC;gBAC9C,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;oBAAE,SAAS;gBACjC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;gBACnB,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACrB,CAAC;YACD,OAAO,MAAM,CAAC;QAChB,CAAC,CAAC;aACD,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;YACxB,IAAI,CAAC,KAAK,GAAG,SAAS,CAAC;YACvB,MAAM,KAAK,CAAC;QACd,CAAC,CAAC,CAAC;QACL,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAEM,KAAK,CAAC,SAAS,CAAC,OAAqB,EAAE,UAA4B,EAAE;QAC1E,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;QACnC,OAAO,CAAC,MAAM,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;IACpF,CAAC;IAEM,KAAK,CAAC,OAAO,CAClB,GAAyB,EACzB,OAAqB,EACrB,UAA4B,EAAE;QAE9B,MAAM,IAAI,GAAG,KAAK,OAAO,EAAE,CAAC;QAC5B,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACpC,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;QACnC,MAAM,UAAU,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;QACxE,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YACtB,MAAM,KAAK,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;YAC5B,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACxB,OAAO,CAAC,IAAI,EAAE,wCAAwC,OAAO,GAAG,EAAE,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC;YAC3F,CAAC;YACD,OAAO,WAAW,CAAC,KAAK,CAAC,CAAC;QAC5B,CAAC;QACD,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;YAC5B,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC;YACpD,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACxB,OAAO,CAAC,IAAI,EAAE,mBAAmB,GAAG,GAAG,EAAE,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC;YAClE,CAAC;YACD,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;gBACnC,OAAO,CACL,IAAI,EACJ,SAAS,aAAa,CAAC,KAAK,CAAC,sBAAsB,OAAO,GAAG,EAC7D,GAAG,YAAY,CAAC,OAAO,CAAC,YAAY,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAC5F,CAAC;YACJ,CAAC;YACD,OAAO,WAAW,CAAC,KAAK,CAAC,CAAC;QAC5B,CAAC;QACD,MAAM,KAAK,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;QAC7B,MAAM,CAAC,aAAa,EAAE,SAAS,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;QAC3D,MAAM,SAAS,GAAG,aAAa,IAAI,KAAK,CAAC;QACzC,MAAM,WAAW,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,SAAS,CAAC,CAAC;QAC3F,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC3B,MAAM,gBAAgB,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;YACxC,IAAI,gBAAgB,KAAK,SAAS,IAAI,CAAC,SAAS,KAAK,SAAS,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,CAAC,EAAE,CAAC;gBAC1F,OAAO,WAAW,CAAC,gBAAgB,CAAC,CAAC;YACvC,CAAC;YACD,MAAM,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,SAAS,CAAC,CAAC;YAC/E,IAAI,KAAK,KAAK,SAAS;gBAAE,OAAO,WAAW,CAAC,KAAK,CAAC,CAAC;YACnD,OAAO,CACL,IAAI,EACJ,GAAG,GAAG,4BAA4B,OAAO,gBAAgB,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,GAAG,EACrF,8BAA8B,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAC1F,CAAC;QACJ,CAAC;QACD,MAAM,WAAW,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,KAAK,CAAC,CAAC;QAChF,IAAI,WAAW,KAAK,SAAS;YAAE,OAAO,WAAW,CAAC,WAAW,CAAC,CAAC;QAC/D,MAAM,OAAO,GAAG,UAAU,CAAC,MAAM,CAC/B,CAAC,KAAK,EAAE,EAAE,CACR,SAAS,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,SAAS,CAAC,GAAG,KAAK,CAAC,SAAS,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAClH,CAAC;QACF,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC;QACpE,MAAM,YAAY,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;QAChC,IAAI,YAAY,KAAK,SAAS,IAAI,UAAU,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,SAAS,KAAK,SAAS,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,CAAC,EAAE,CAAC;YAC/G,OAAO,WAAW,CAAC,YAAY,CAAC,CAAC;QACnC,CAAC;QACD,OAAO,OAAO,CACZ,IAAI,EACJ,MAAM,OAAO,kBAAkB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,EACrD,OAAO,CAAC,MAAM,GAAG,CAAC;YAChB,CAAC,CAAC,iBAAiB,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;YACvE,CAAC,CAAC,GAAG,YAAY,CAAC,OAAO,CAAC,eAAe,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CACnG,CAAC;IACJ,CAAC;CACF"}
|
package/dist/wav.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { AudioInfo } from "./types.ts";
|
|
2
|
+
export interface WavLayout extends AudioInfo {
|
|
3
|
+
readonly dataOffset: number;
|
|
4
|
+
readonly dataLength: number;
|
|
5
|
+
}
|
|
6
|
+
export declare function wavHeader(frames: number, sampleRate: number, channels?: number): Uint8Array;
|
|
7
|
+
export declare function encodePcm16(pcm: Float32Array, target?: Uint8Array, offset?: number): Uint8Array;
|
|
8
|
+
export declare function encodeWav(pcm: Float32Array, sampleRate: number): Uint8Array;
|
|
9
|
+
export declare function inspectWav(bytes: Uint8Array): WavLayout;
|
|
10
|
+
export declare function audioInfo(layout: WavLayout): AudioInfo;
|
|
11
|
+
export declare function decodeWav(bytes: Uint8Array): {
|
|
12
|
+
readonly info: AudioInfo;
|
|
13
|
+
readonly samples: Float32Array;
|
|
14
|
+
};
|
|
15
|
+
export declare function silenceWav(seconds: number, sampleRate: number): Uint8Array;
|
|
16
|
+
export declare function concatWav(parts: readonly Uint8Array[], gapSeconds?: number): Uint8Array;
|
|
17
|
+
export declare function pcm16Samples(bytes: Uint8Array): Int16Array;
|
|
18
|
+
//# sourceMappingURL=wav.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wav.d.ts","sourceRoot":"","sources":["../src/wav.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAO5C,MAAM,WAAW,SAAU,SAAQ,SAAS;IAC1C,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAU,GAAG,UAAU,CAwB9F;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,YAAY,EAAE,MAAM,CAAC,EAAE,UAAU,EAAE,MAAM,GAAE,MAAU,GAAG,UAAU,CAUlG;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,GAAG,UAAU,CAK3E;AAUD,wBAAgB,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG,SAAS,CAoDvD;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,SAAS,GAAG,SAAS,CAStD;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,UAAU,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAA;CAAE,CAczG;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,UAAU,CAE1E;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,SAAS,UAAU,EAAE,EAAE,UAAU,GAAE,MAAU,GAAG,UAAU,CA0B1F;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,UAAU,GAAG,UAAU,CAe1D"}
|
package/dist/wav.js
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { KongyoroidError, invalid } from "./errors.js";
|
|
2
|
+
const RIFF = 0x52494646;
|
|
3
|
+
const WAVE = 0x57415645;
|
|
4
|
+
const FMT = 0x666d7420;
|
|
5
|
+
const DATA = 0x64617461;
|
|
6
|
+
export function wavHeader(frames, sampleRate, channels = 1) {
|
|
7
|
+
if (!Number.isSafeInteger(frames) || frames < 0 || frames * channels * 2 > 0xfffffff0) {
|
|
8
|
+
invalid("$.frames", "Frame count is not representable in a WAV file.");
|
|
9
|
+
}
|
|
10
|
+
if (!Number.isSafeInteger(sampleRate) || sampleRate < 1 || sampleRate > 384_000) {
|
|
11
|
+
invalid("$.sampleRate", "Sample rate is not representable in a WAV file.");
|
|
12
|
+
}
|
|
13
|
+
const dataBytes = frames * channels * 2;
|
|
14
|
+
const header = new Uint8Array(44);
|
|
15
|
+
const view = new DataView(header.buffer);
|
|
16
|
+
view.setUint32(0, RIFF);
|
|
17
|
+
view.setUint32(4, 36 + dataBytes, true);
|
|
18
|
+
view.setUint32(8, WAVE);
|
|
19
|
+
view.setUint32(12, FMT);
|
|
20
|
+
view.setUint32(16, 16, true);
|
|
21
|
+
view.setUint16(20, 1, true);
|
|
22
|
+
view.setUint16(22, channels, true);
|
|
23
|
+
view.setUint32(24, sampleRate, true);
|
|
24
|
+
view.setUint32(28, sampleRate * channels * 2, true);
|
|
25
|
+
view.setUint16(32, channels * 2, true);
|
|
26
|
+
view.setUint16(34, 16, true);
|
|
27
|
+
view.setUint32(36, DATA);
|
|
28
|
+
view.setUint32(40, dataBytes, true);
|
|
29
|
+
return header;
|
|
30
|
+
}
|
|
31
|
+
export function encodePcm16(pcm, target, offset = 0) {
|
|
32
|
+
const bytes = target ?? new Uint8Array(pcm.length * 2);
|
|
33
|
+
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
34
|
+
for (let index = 0; index < pcm.length; index++) {
|
|
35
|
+
const value = pcm[index] ?? 0;
|
|
36
|
+
if (!Number.isFinite(value))
|
|
37
|
+
invalid(`$.pcm[${index}]`, "PCM contains a non-finite sample.");
|
|
38
|
+
const clipped = value < -1 ? -1 : value > 1 ? 1 : value;
|
|
39
|
+
view.setInt16(offset + index * 2, Math.round(clipped * (clipped < 0 ? 32768 : 32767)), true);
|
|
40
|
+
}
|
|
41
|
+
return bytes;
|
|
42
|
+
}
|
|
43
|
+
export function encodeWav(pcm, sampleRate) {
|
|
44
|
+
const bytes = new Uint8Array(44 + pcm.length * 2);
|
|
45
|
+
bytes.set(wavHeader(pcm.length, sampleRate));
|
|
46
|
+
encodePcm16(pcm, bytes, 44);
|
|
47
|
+
return bytes;
|
|
48
|
+
}
|
|
49
|
+
function malformed(reason) {
|
|
50
|
+
throw new KongyoroidError({
|
|
51
|
+
code: "ENGINE_PROTOCOL",
|
|
52
|
+
message: `Invalid or unsupported WAV data: ${reason}.`,
|
|
53
|
+
retryable: false,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
export function inspectWav(bytes) {
|
|
57
|
+
if (bytes.byteLength < 44)
|
|
58
|
+
malformed("shorter than a RIFF header");
|
|
59
|
+
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
60
|
+
if (view.getUint32(0) !== RIFF || view.getUint32(8) !== WAVE)
|
|
61
|
+
malformed("missing RIFF/WAVE signature");
|
|
62
|
+
const declared = view.getUint32(4, true) + 8;
|
|
63
|
+
if (declared > bytes.byteLength)
|
|
64
|
+
malformed(`RIFF declares ${declared} bytes but only ${bytes.byteLength} were received`);
|
|
65
|
+
const end = declared;
|
|
66
|
+
let format = 0;
|
|
67
|
+
let channels = 0;
|
|
68
|
+
let rate = 0;
|
|
69
|
+
let bits = 0;
|
|
70
|
+
let align = 0;
|
|
71
|
+
let dataOffset = -1;
|
|
72
|
+
let dataLength = -1;
|
|
73
|
+
let position = 12;
|
|
74
|
+
while (position + 8 <= end) {
|
|
75
|
+
const tag = view.getUint32(position);
|
|
76
|
+
const length = view.getUint32(position + 4, true);
|
|
77
|
+
const start = position + 8;
|
|
78
|
+
if (tag === FMT) {
|
|
79
|
+
if (format !== 0 || length < 16 || start + 16 > end)
|
|
80
|
+
malformed("bad fmt chunk");
|
|
81
|
+
format = view.getUint16(start, true);
|
|
82
|
+
channels = view.getUint16(start + 2, true);
|
|
83
|
+
rate = view.getUint32(start + 4, true);
|
|
84
|
+
align = view.getUint16(start + 12, true);
|
|
85
|
+
bits = view.getUint16(start + 14, true);
|
|
86
|
+
if (format === 0xfffe && length >= 26)
|
|
87
|
+
format = view.getUint16(start + 24, true);
|
|
88
|
+
}
|
|
89
|
+
else if (tag === DATA) {
|
|
90
|
+
if (dataOffset >= 0)
|
|
91
|
+
malformed("duplicate data chunk");
|
|
92
|
+
if (start + length > end)
|
|
93
|
+
malformed(`data chunk declares ${length} bytes past the end of the file`);
|
|
94
|
+
dataOffset = start;
|
|
95
|
+
dataLength = length;
|
|
96
|
+
}
|
|
97
|
+
position = start + length + (length % 2);
|
|
98
|
+
}
|
|
99
|
+
if (dataOffset < 0 || format === 0)
|
|
100
|
+
malformed("missing fmt or data chunk");
|
|
101
|
+
if (channels < 1 || channels > 2 || rate < 1000 || rate > 384_000)
|
|
102
|
+
malformed("unsupported channel count or rate");
|
|
103
|
+
if (!((format === 1 && bits === 16) || (format === 3 && bits === 32)))
|
|
104
|
+
malformed("only PCM16 or float32 supported");
|
|
105
|
+
if (align !== (channels * bits) / 8)
|
|
106
|
+
malformed("inconsistent block alignment");
|
|
107
|
+
const usable = dataLength - (dataLength % align);
|
|
108
|
+
const frames = usable / align;
|
|
109
|
+
return {
|
|
110
|
+
sampleRate: rate,
|
|
111
|
+
channels,
|
|
112
|
+
frames,
|
|
113
|
+
bitsPerSample: bits,
|
|
114
|
+
format: format === 1 ? "pcm" : "float",
|
|
115
|
+
durationSeconds: frames / rate,
|
|
116
|
+
dataOffset,
|
|
117
|
+
dataLength: usable,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
export function audioInfo(layout) {
|
|
121
|
+
return {
|
|
122
|
+
sampleRate: layout.sampleRate,
|
|
123
|
+
channels: layout.channels,
|
|
124
|
+
frames: layout.frames,
|
|
125
|
+
bitsPerSample: layout.bitsPerSample,
|
|
126
|
+
format: layout.format,
|
|
127
|
+
durationSeconds: layout.durationSeconds,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
export function decodeWav(bytes) {
|
|
131
|
+
const layout = inspectWav(bytes);
|
|
132
|
+
const view = new DataView(bytes.buffer, bytes.byteOffset + layout.dataOffset, layout.dataLength);
|
|
133
|
+
const samples = new Float32Array(layout.frames);
|
|
134
|
+
const channels = layout.channels;
|
|
135
|
+
for (let frame = 0; frame < layout.frames; frame++) {
|
|
136
|
+
let sum = 0;
|
|
137
|
+
for (let channel = 0; channel < channels; channel++) {
|
|
138
|
+
const index = frame * channels + channel;
|
|
139
|
+
sum += layout.format === "pcm" ? view.getInt16(index * 2, true) / 32768 : view.getFloat32(index * 4, true);
|
|
140
|
+
}
|
|
141
|
+
samples[frame] = sum / channels;
|
|
142
|
+
}
|
|
143
|
+
return { info: audioInfo(layout), samples };
|
|
144
|
+
}
|
|
145
|
+
export function silenceWav(seconds, sampleRate) {
|
|
146
|
+
return encodeWav(new Float32Array(Math.round(seconds * sampleRate)), sampleRate);
|
|
147
|
+
}
|
|
148
|
+
export function concatWav(parts, gapSeconds = 0) {
|
|
149
|
+
if (parts.length === 0)
|
|
150
|
+
invalid("$.parts", "Nothing to concatenate.");
|
|
151
|
+
const layouts = parts.map((part) => inspectWav(part));
|
|
152
|
+
const rate = layouts[0]?.sampleRate ?? 0;
|
|
153
|
+
for (const layout of layouts) {
|
|
154
|
+
if (layout.sampleRate !== rate)
|
|
155
|
+
malformed("sample rates differ between parts");
|
|
156
|
+
}
|
|
157
|
+
const gapFrames = Math.round(gapSeconds * rate);
|
|
158
|
+
let frames = 0;
|
|
159
|
+
for (const layout of layouts)
|
|
160
|
+
frames += layout.frames;
|
|
161
|
+
frames += gapFrames * (parts.length - 1);
|
|
162
|
+
const out = new Uint8Array(44 + frames * 2);
|
|
163
|
+
out.set(wavHeader(frames, rate));
|
|
164
|
+
let offset = 44;
|
|
165
|
+
for (const [index, part] of parts.entries()) {
|
|
166
|
+
const layout = layouts[index];
|
|
167
|
+
if (layout === undefined)
|
|
168
|
+
continue;
|
|
169
|
+
if (layout.format === "pcm" && layout.channels === 1) {
|
|
170
|
+
out.set(part.subarray(layout.dataOffset, layout.dataOffset + layout.dataLength), offset);
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
encodePcm16(decodeWav(part).samples, out, offset);
|
|
174
|
+
}
|
|
175
|
+
offset += layout.frames * 2;
|
|
176
|
+
if (index < parts.length - 1)
|
|
177
|
+
offset += gapFrames * 2;
|
|
178
|
+
}
|
|
179
|
+
return out;
|
|
180
|
+
}
|
|
181
|
+
export function pcm16Samples(bytes) {
|
|
182
|
+
const layout = inspectWav(bytes);
|
|
183
|
+
if (layout.format !== "pcm" || layout.channels !== 1) {
|
|
184
|
+
const decoded = decodeWav(bytes).samples;
|
|
185
|
+
const out = new Int16Array(decoded.length);
|
|
186
|
+
for (let index = 0; index < decoded.length; index++) {
|
|
187
|
+
const value = Math.max(-1, Math.min(1, decoded[index] ?? 0));
|
|
188
|
+
out[index] = Math.round(value * (value < 0 ? 32768 : 32767));
|
|
189
|
+
}
|
|
190
|
+
return out;
|
|
191
|
+
}
|
|
192
|
+
const view = new DataView(bytes.buffer, bytes.byteOffset + layout.dataOffset, layout.dataLength);
|
|
193
|
+
const out = new Int16Array(layout.frames);
|
|
194
|
+
for (let index = 0; index < layout.frames; index++)
|
|
195
|
+
out[index] = view.getInt16(index * 2, true);
|
|
196
|
+
return out;
|
|
197
|
+
}
|
|
198
|
+
//# sourceMappingURL=wav.js.map
|
package/dist/wav.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wav.js","sourceRoot":"","sources":["../src/wav.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
{"id":"greeting","request":{"kind":"speech","text":"おはようございます。","speaker":"ずんだもん"}}
|
|
2
|
+
{"id":"question","request":{"kind":"speech","text":"準備はできましたか?","speaker":"四国めたん","speed":0.9}}
|
|
3
|
+
{"id":"scale","request":{"kind":"song","notes":{"lyrics":"ドレミファソラシド","melody":"C4 D4 E4 F4 G4 A4 B4 C5","beats":"1 1 1 1 1 1 1 2"}}}
|
|
4
|
+
{"id":"builtin","request":{"kind":"speech","engine":"formant","text":"ないぞうえんじんで、よみあげます。","kana":"ナイゾーエ'ンジンデ、ヨミアゲマ'ス"}}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"kind": "song",
|
|
3
|
+
"engine": "formant",
|
|
4
|
+
"tempo": 90,
|
|
5
|
+
"transpose": -2,
|
|
6
|
+
"vibratoDepth": 35,
|
|
7
|
+
"notes": [
|
|
8
|
+
{ "key": null, "beats": 0.5, "lyric": "" },
|
|
9
|
+
{ "key": "E4", "beats": 1, "lyric": "さ" },
|
|
10
|
+
{ "key": "E4", "beats": 1, "lyric": "く" },
|
|
11
|
+
{ "key": "F4", "beats": 2, "lyric": "ら" },
|
|
12
|
+
{ "key": "E4", "beats": 1, "lyric": "さ" },
|
|
13
|
+
{ "key": "E4", "beats": 1, "lyric": "く" },
|
|
14
|
+
{ "key": "F4", "beats": 2, "lyric": "ら" },
|
|
15
|
+
{ "key": "E4", "beats": 1, "lyric": "や" },
|
|
16
|
+
{ "key": "F4", "beats": 1, "lyric": "よ" },
|
|
17
|
+
{ "key": "G4", "beats": 1, "lyric": "い" },
|
|
18
|
+
{ "key": "G4", "beats": 1, "lyric": "の" },
|
|
19
|
+
{ "key": "F4", "beats": 1, "lyric": "そ" },
|
|
20
|
+
{ "key": "E4", "beats": 1, "lyric": "ら" },
|
|
21
|
+
{ "key": "D4", "beats": 2, "lyric": "わ" },
|
|
22
|
+
{ "key": "D4", "beats": 2, "lyric": "ー" }
|
|
23
|
+
]
|
|
24
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@kongyo2/kongyoroid",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Japanese speech and singing synthesis for LLM agents: a JSON-first CLI and typed library with a built-in deterministic formant engine and an optional VOICEVOX ENGINE adapter.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"author": "kongyo2",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/kongyo2/kongyoroid.git"
|
|
11
|
+
},
|
|
12
|
+
"homepage": "https://github.com/kongyo2/kongyoroid#readme",
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/kongyo2/kongyoroid/issues"
|
|
15
|
+
},
|
|
16
|
+
"engines": {
|
|
17
|
+
"node": ">=22.4"
|
|
18
|
+
},
|
|
19
|
+
"main": "./dist/index.js",
|
|
20
|
+
"types": "./dist/index.d.ts",
|
|
21
|
+
"exports": {
|
|
22
|
+
".": {
|
|
23
|
+
"types": "./dist/index.d.ts",
|
|
24
|
+
"import": "./dist/index.js",
|
|
25
|
+
"default": "./dist/index.js"
|
|
26
|
+
},
|
|
27
|
+
"./package.json": "./package.json"
|
|
28
|
+
},
|
|
29
|
+
"bin": {
|
|
30
|
+
"kongyoroid": "./dist/cli.js"
|
|
31
|
+
},
|
|
32
|
+
"files": [
|
|
33
|
+
"dist",
|
|
34
|
+
"examples",
|
|
35
|
+
"AGENTS.md",
|
|
36
|
+
"LICENSE",
|
|
37
|
+
"README.md"
|
|
38
|
+
],
|
|
39
|
+
"sideEffects": false,
|
|
40
|
+
"publishConfig": {
|
|
41
|
+
"access": "public",
|
|
42
|
+
"provenance": true
|
|
43
|
+
},
|
|
44
|
+
"keywords": [
|
|
45
|
+
"tts",
|
|
46
|
+
"text-to-speech",
|
|
47
|
+
"singing",
|
|
48
|
+
"singing-synthesis",
|
|
49
|
+
"voicevox",
|
|
50
|
+
"japanese",
|
|
51
|
+
"speech",
|
|
52
|
+
"agent",
|
|
53
|
+
"llm",
|
|
54
|
+
"cli",
|
|
55
|
+
"formant",
|
|
56
|
+
"kongyo2"
|
|
57
|
+
],
|
|
58
|
+
"scripts": {
|
|
59
|
+
"clean": "node --input-type=module -e \"import { rmSync } from 'node:fs'; rmSync('dist', { recursive: true, force: true })\"",
|
|
60
|
+
"build": "npm run clean && tsc --pretty false",
|
|
61
|
+
"typecheck": "tsc --noEmit --pretty false",
|
|
62
|
+
"typecheck:test": "tsc -p tsconfig.test.json --pretty false",
|
|
63
|
+
"lint": "oxlint --deny-warnings --format agent",
|
|
64
|
+
"lint:fix": "oxlint --fix --deny-warnings --format agent",
|
|
65
|
+
"lint:typed": "oxlint --type-aware --type-check --deny-warnings --format agent",
|
|
66
|
+
"format": "prettier --write .",
|
|
67
|
+
"format:check": "prettier --check .",
|
|
68
|
+
"comments:check": "ts-comment-scanner --fail-on-comment src test scripts",
|
|
69
|
+
"test": "node --test --disable-warning=ExperimentalWarning \"test/**/*.test.ts\"",
|
|
70
|
+
"check": "npm run typecheck && npm run typecheck:test && npm run lint && npm run format:check && npm run comments:check && npm test",
|
|
71
|
+
"check:package": "attw --pack . --profile esm-only && publint --strict",
|
|
72
|
+
"verify:package": "node --disable-warning=ExperimentalWarning scripts/verify-package.ts",
|
|
73
|
+
"prepack": "npm run build"
|
|
74
|
+
},
|
|
75
|
+
"devDependencies": {
|
|
76
|
+
"@arethetypeswrong/cli": "0.18.5",
|
|
77
|
+
"@kongyo2/ts-comment-scanner": "1.6.0",
|
|
78
|
+
"@types/node": "22.20.1",
|
|
79
|
+
"ajv": "8.20.0",
|
|
80
|
+
"oxlint": "1.81.0",
|
|
81
|
+
"oxlint-tsgolint": "7.0.2001",
|
|
82
|
+
"prettier": "3.9.6",
|
|
83
|
+
"publint": "0.3.24",
|
|
84
|
+
"typescript": "6.0.3"
|
|
85
|
+
}
|
|
86
|
+
}
|