@onjmin/koe 1.0.3 → 1.0.4

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.ts CHANGED
@@ -1,3 +1,20 @@
1
+ /**
2
+ * UTAU `.frq` frequency-analysis files (FREQ0003). The same format OpenUtau
3
+ * reads: an 8-byte header, hop size, then the average fundamental frequency of
4
+ * the recording — exactly the reference pitch we need for correct resampling.
5
+ *
6
+ * Layout:
7
+ * char[8] "FREQ0003"
8
+ * int32 hopSize
9
+ * float64 averageF0 ← the recorded pitch in Hz
10
+ * byte[16] (blank)
11
+ * int32 length
12
+ * { float64 f0, float64 amp } × length
13
+ */
14
+ declare function parseFrqAverageF0(buffer: ArrayBuffer): number | null;
15
+ /** Map a WAV filename to its sibling frq filename: "あ.wav" → "あ_wav.frq". */
16
+ declare function frqFileName(wavName: string): string;
17
+
1
18
  /**
2
19
  * One phoneme, already trimmed to its usable oto region.
3
20
  * Sample 0 corresponds to the oto `offset` (left blank); everything before it
@@ -36,6 +53,98 @@ interface NoteEvent {
36
53
  duration: number;
37
54
  }
38
55
 
56
+ interface OtoEntry {
57
+ /** Source WAV filename */
58
+ wav: string;
59
+ /** Phoneme alias */
60
+ alias: string;
61
+ /** Left blank — offset from WAV start (ms) */
62
+ offset: number;
63
+ /** Consonant portion end from offset (ms) */
64
+ consonant: number;
65
+ /** Right blank — negative = from WAV end, positive = from offset (ms) */
66
+ cutoff: number;
67
+ /** Preutterance from offset (ms) */
68
+ pre: number;
69
+ /** Overlap / crossfade region (ms) */
70
+ overlap: number;
71
+ }
72
+ /**
73
+ * Parse oto.ini content (already decoded to UTF-8 string).
74
+ * Silently skips malformed lines.
75
+ */
76
+ declare function parseOto(content: string): OtoEntry[];
77
+
78
+ interface PackInput {
79
+ oto: OtoEntry;
80
+ /** Full normalized PCM of the source WAV (48kHz / 16bit / mono) */
81
+ pcm: Int16Array;
82
+ /** Known recorded pitch in Hz (e.g. from the .frq file). 0/undefined → auto-detect. */
83
+ recordedPitch?: number;
84
+ }
85
+ interface PackOutput {
86
+ manifest: Manifest;
87
+ /** Raw PCM blob — Int16 / 48kHz / mono */
88
+ bin: ArrayBuffer;
89
+ }
90
+ interface TrimmedPhoneme {
91
+ /** PCM trimmed to the oto region [offset, cutoff] */
92
+ pcm: Int16Array;
93
+ /** Manifest params relative to the trimmed start (sample 0 = oto offset) */
94
+ entry: Omit<PhonemeEntry, "offset">;
95
+ }
96
+ /**
97
+ * Cut the full WAV PCM down to its usable oto region and recompute parameters
98
+ * relative to the trimmed start.
99
+ *
100
+ * UTAU oto.ini values are all in ms and measured from `offset` (the left blank),
101
+ * except `cutoff` (right blank):
102
+ * - cutoff >= 0 : measured from the END of the file
103
+ * - cutoff < 0 : region length from offset = |cutoff|
104
+ *
105
+ * After trimming, sample 0 == oto offset, so pre/overlap/consonant carry over
106
+ * unchanged (just converted to samples), and the slice length is the region end.
107
+ */
108
+ declare function trimToOto(pcm: Int16Array, oto: OtoEntry, recordedPitch?: number): TrimmedPhoneme;
109
+ /**
110
+ * Pack normalized PCM phonemes into voice.bin + manifest.json.
111
+ * Each phoneme is trimmed to its oto region first.
112
+ * Duplicate aliases are silently overwritten by the later entry.
113
+ */
114
+ declare function pack(inputs: PackInput[], referencePitch?: number): PackOutput;
115
+
116
+ /** Parse a note name like "E4", "G#4", "Db5" → frequency in Hz (null if invalid). */
117
+ declare function noteNameToHz(name: string): number | null;
118
+ /** Recorded pitch encoded in a multi-pitch alias suffix: "a い_E4" → 329.63 Hz. */
119
+ declare function pitchFromAliasSuffix(alias: string): number | null;
120
+ /**
121
+ * Estimate the fundamental frequency (Hz) of a voiced region by normalized
122
+ * autocorrelation. Returns 0 when no clear pitch is found (unvoiced consonant,
123
+ * silence, or a region too short to analyse).
124
+ *
125
+ * The signal is decimated to a lower analysis rate for speed; f0 below ~700 Hz
126
+ * is well within the resulting Nyquist limit. A parabolic interpolation around
127
+ * the best lag gives sub-sample (sub-semitone) accuracy.
128
+ */
129
+ declare function detectF0(pcm: Int16Array, start: number, end: number): number;
130
+
131
+ interface WavData {
132
+ sampleRate: number;
133
+ channels: number;
134
+ /** Normalized samples in [-1, 1], interleaved if multi-channel */
135
+ samples: Float32Array;
136
+ }
137
+ /** Parse a WAV file from an ArrayBuffer. Supports PCM 8/16/24-bit and IEEE float 32-bit. */
138
+ declare function parseWav(buf: ArrayBuffer): WavData;
139
+ /** Mix down to mono by averaging all channels. */
140
+ declare function toMono(wav: WavData): WavData;
141
+ /** Linear interpolation resample to targetRate. Expects mono input. */
142
+ declare function resample(wav: WavData, targetRate: number): WavData;
143
+ /** Convert Float32 [-1,1] samples to Int16 PCM. */
144
+ declare function toInt16(samples: Float32Array): Int16Array;
145
+ /** Normalize then convert a WAV to 48kHz/16bit/mono Int16 PCM. */
146
+ declare function normalizePcm(buf: ArrayBuffer): Int16Array;
147
+
39
148
  /**
40
149
  * Read-only access to a .koe voice bank: its manifest plus per-phoneme PCM,
41
150
  * fetched on demand (Blob slice or HTTP Range). The full bank is never held in
@@ -59,6 +168,7 @@ declare class VoiceBank {
59
168
  * @param koe a Blob/File of the .koe archive, or a URL (served with Range support)
60
169
  */
61
170
  static load(koe: Blob | string): Promise<VoiceBank>;
171
+ private static fromBlob;
62
172
  /** True if the bank contains a phoneme under this alias. */
63
173
  has(phoneme: string): boolean;
64
174
  /**
@@ -118,6 +228,11 @@ declare class KoeEngine {
118
228
  stop(): void;
119
229
  /** Resume the AudioContext if suspended (e.g. after autoplay block). */
120
230
  resume(): Promise<void>;
231
+ /**
232
+ * Tear down the worklet node and close the AudioContext, releasing the audio
233
+ * hardware. The engine cannot be reused afterwards — create a new one.
234
+ */
235
+ dispose(): Promise<void>;
121
236
  /**
122
237
  * Read a phoneme's raw PCM and return it as a Float64Array normalised to
123
238
  * [-1, 1]. Convenience that forwards to the underlying {@link VoiceBank}.
@@ -242,115 +357,6 @@ declare class Worldline {
242
357
  renderNote(params: RenderNoteParams): Float32Array | null;
243
358
  }
244
359
 
245
- interface OtoEntry {
246
- /** Source WAV filename */
247
- wav: string;
248
- /** Phoneme alias */
249
- alias: string;
250
- /** Left blank — offset from WAV start (ms) */
251
- offset: number;
252
- /** Consonant portion end from offset (ms) */
253
- consonant: number;
254
- /** Right blank — negative = from WAV end, positive = from offset (ms) */
255
- cutoff: number;
256
- /** Preutterance from offset (ms) */
257
- pre: number;
258
- /** Overlap / crossfade region (ms) */
259
- overlap: number;
260
- }
261
- /**
262
- * Parse oto.ini content (already decoded to UTF-8 string).
263
- * Silently skips malformed lines.
264
- */
265
- declare function parseOto(content: string): OtoEntry[];
266
-
267
- interface WavData {
268
- sampleRate: number;
269
- channels: number;
270
- /** Normalized samples in [-1, 1], interleaved if multi-channel */
271
- samples: Float32Array;
272
- }
273
- /** Parse a WAV file from an ArrayBuffer. Supports PCM 8/16/24-bit and IEEE float 32-bit. */
274
- declare function parseWav(buf: ArrayBuffer): WavData;
275
- /** Mix down to mono by averaging all channels. */
276
- declare function toMono(wav: WavData): WavData;
277
- /** Linear interpolation resample to targetRate. Expects mono input. */
278
- declare function resample(wav: WavData, targetRate: number): WavData;
279
- /** Convert Float32 [-1,1] samples to Int16 PCM. */
280
- declare function toInt16(samples: Float32Array): Int16Array;
281
- /** Normalize then convert a WAV to 48kHz/16bit/mono Int16 PCM. */
282
- declare function normalizePcm(buf: ArrayBuffer): Int16Array;
283
-
284
- interface PackInput {
285
- oto: OtoEntry;
286
- /** Full normalized PCM of the source WAV (48kHz / 16bit / mono) */
287
- pcm: Int16Array;
288
- /** Known recorded pitch in Hz (e.g. from the .frq file). 0/undefined → auto-detect. */
289
- recordedPitch?: number;
290
- }
291
- interface PackOutput {
292
- manifest: Manifest;
293
- /** Raw PCM blob — Int16 / 48kHz / mono */
294
- bin: ArrayBuffer;
295
- }
296
- interface TrimmedPhoneme {
297
- /** PCM trimmed to the oto region [offset, cutoff] */
298
- pcm: Int16Array;
299
- /** Manifest params relative to the trimmed start (sample 0 = oto offset) */
300
- entry: Omit<PhonemeEntry, "offset">;
301
- }
302
- /**
303
- * Cut the full WAV PCM down to its usable oto region and recompute parameters
304
- * relative to the trimmed start.
305
- *
306
- * UTAU oto.ini values are all in ms and measured from `offset` (the left blank),
307
- * except `cutoff` (right blank):
308
- * - cutoff >= 0 : measured from the END of the file
309
- * - cutoff < 0 : region length from offset = |cutoff|
310
- *
311
- * After trimming, sample 0 == oto offset, so pre/overlap/consonant carry over
312
- * unchanged (just converted to samples), and the slice length is the region end.
313
- */
314
- declare function trimToOto(pcm: Int16Array, oto: OtoEntry, recordedPitch?: number): TrimmedPhoneme;
315
- /**
316
- * Pack normalized PCM phonemes into voice.bin + manifest.json.
317
- * Each phoneme is trimmed to its oto region first.
318
- * Duplicate aliases are silently overwritten by the later entry.
319
- */
320
- declare function pack(inputs: PackInput[], referencePitch?: number): PackOutput;
321
-
322
- /** Parse a note name like "E4", "G#4", "Db5" → frequency in Hz (null if invalid). */
323
- declare function noteNameToHz(name: string): number | null;
324
- /** Recorded pitch encoded in a multi-pitch alias suffix: "a い_E4" → 329.63 Hz. */
325
- declare function pitchFromAliasSuffix(alias: string): number | null;
326
- /**
327
- * Estimate the fundamental frequency (Hz) of a voiced region by normalized
328
- * autocorrelation. Returns 0 when no clear pitch is found (unvoiced consonant,
329
- * silence, or a region too short to analyse).
330
- *
331
- * The signal is decimated to a lower analysis rate for speed; f0 below ~700 Hz
332
- * is well within the resulting Nyquist limit. A parabolic interpolation around
333
- * the best lag gives sub-sample (sub-semitone) accuracy.
334
- */
335
- declare function detectF0(pcm: Int16Array, start: number, end: number): number;
336
-
337
- /**
338
- * UTAU `.frq` frequency-analysis files (FREQ0003). The same format OpenUtau
339
- * reads: an 8-byte header, hop size, then the average fundamental frequency of
340
- * the recording — exactly the reference pitch we need for correct resampling.
341
- *
342
- * Layout:
343
- * char[8] "FREQ0003"
344
- * int32 hopSize
345
- * float64 averageF0 ← the recorded pitch in Hz
346
- * byte[16] (blank)
347
- * int32 length
348
- * { float64 f0, float64 amp } × length
349
- */
350
- declare function parseFrqAverageF0(buffer: ArrayBuffer): number | null;
351
- /** Map a WAV filename to its sibling frq filename: "あ.wav" → "あ_wav.frq". */
352
- declare function frqFileName(wavName: string): string;
353
-
354
360
  /**
355
361
  * Koe Archive Format (.koe)
356
362
  * [4B] magic 'KOE\0' (big-endian)