@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.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/koe.ts","../src/engine/voice-bank.ts","../src/engine/index.ts","../src/engine/worldline.ts","../src/converter/parse-oto.ts","../src/converter/wav.ts","../src/converter/pitch.ts","../src/converter/pack.ts","../src/converter/frq.ts"],"sourcesContent":["import type { Manifest } from \"./types.js\";\n\n/** Magic number 'KOE\\0' (stored big-endian as 0x4B 0x4F 0x45 0x00). */\nconst MAGIC = 0x4b4f4500;\n\n/**\n * Koe Archive Format (.koe)\n * [4B] magic 'KOE\\0' (big-endian)\n * [4B] JSON length (little-endian)\n * [N ] manifest JSON (UTF-8)\n * [M ] raw PCM (Int16 / 48kHz / mono); phoneme offsets are relative to here\n */\nexport function packKoe(manifest: Manifest, pcmParts: BlobPart[]): Blob {\n\tconst json = new TextEncoder().encode(JSON.stringify(manifest));\n\tconst header = new ArrayBuffer(8);\n\tconst view = new DataView(header);\n\tview.setUint32(0, MAGIC, false); // magic, big-endian\n\tview.setUint32(4, json.byteLength, true); // json length, little-endian\n\treturn new Blob([header, json, ...pcmParts]);\n}\n\n/** Read the 8-byte header → JSON length. Throws on bad magic. */\nexport function parseKoeHeader(headerBytes: ArrayBuffer): {\n\tjsonLength: number;\n} {\n\tconst view = new DataView(headerBytes);\n\tif (view.byteLength < 8 || view.getUint32(0, false) !== MAGIC) {\n\t\tthrow new Error(\"Not a .koe file (bad magic)\");\n\t}\n\treturn { jsonLength: view.getUint32(4, true) };\n}\n\n/** Byte offset where PCM data begins, given the JSON length. */\nexport const pcmBase = (jsonLength: number): number => 8 + jsonLength;\n","import type { Manifest } from \"../types.js\";\nimport { parseKoeHeader, pcmBase } from \"../koe.js\";\n\n/**\n * Supplies raw bytes from the PCM section of a .koe archive on demand.\n * - BlobVoiceSource: slices an in-memory Blob / File (no full-buffer copy)\n * - RangeVoiceSource: HTTP Range requests against a URL (mobile-friendly)\n * `base` is the byte offset where PCM data starts (8 + jsonLength).\n */\ninterface VoiceSource {\n\treadBytes(offset: number, length: number): Promise<ArrayBuffer>;\n}\n\nclass BlobVoiceSource implements VoiceSource {\n\tconstructor(\n\t\tprivate blob: Blob,\n\t\tprivate base: number,\n\t) {}\n\treadBytes(offset: number, length: number): Promise<ArrayBuffer> {\n\t\tconst start = this.base + offset;\n\t\treturn this.blob.slice(start, start + length).arrayBuffer();\n\t}\n}\n\nclass RangeVoiceSource implements VoiceSource {\n\tconstructor(\n\t\tprivate url: string,\n\t\tprivate base: number,\n\t) {}\n\tasync readBytes(offset: number, length: number): Promise<ArrayBuffer> {\n\t\tconst start = this.base + offset;\n\t\tconst res = await fetch(this.url, {\n\t\t\theaders: { Range: `bytes=${start}-${start + length - 1}` },\n\t\t});\n\t\tif (!res.ok && res.status !== 206) {\n\t\t\tthrow new Error(`.koe range request failed: ${res.status}`);\n\t\t}\n\t\treturn res.arrayBuffer();\n\t}\n}\n\nasync function rangeFetch(\n\turl: string,\n\tstart: number,\n\tlength: number,\n): Promise<ArrayBuffer> {\n\tconst res = await fetch(url, {\n\t\theaders: { Range: `bytes=${start}-${start + length - 1}` },\n\t});\n\tif (!res.ok && res.status !== 206)\n\t\tthrow new Error(`.koe fetch failed: ${res.status}`);\n\treturn res.arrayBuffer();\n}\n\n/**\n * Read-only access to a .koe voice bank: its manifest plus per-phoneme PCM,\n * fetched on demand (Blob slice or HTTP Range). The full bank is never held in\n * memory.\n *\n * Pure data — no AudioContext, no AudioWorklet, no DOM. Use this when you only\n * need the source samples (e.g. to feed the {@link Worldline} renderer or any\n * other vocoder). {@link KoeEngine} builds its concatenative playback on top of\n * this same class.\n *\n * const bank = await VoiceBank.load(koeBlobOrUrl);\n * const pcm = await bank.getPcm('a'); // Float64 [-1, 1]\n */\nexport class VoiceBank {\n\tprivate constructor(\n\t\t/** The voice bank manifest (sample rate, reference pitch, phoneme table). */\n\t\treadonly manifest: Manifest,\n\t\tprivate source: VoiceSource,\n\t) {}\n\n\t/**\n\t * Parse a .koe archive header + manifest and bind a lazy PCM source.\n\t * @param koe a Blob/File of the .koe archive, or a URL (served with Range support)\n\t */\n\tstatic async load(koe: Blob | string): Promise<VoiceBank> {\n\t\tif (typeof koe === \"string\") {\n\t\t\tconst header = await rangeFetch(koe, 0, 8);\n\t\t\tconst { jsonLength } = parseKoeHeader(header);\n\t\t\tconst json = await rangeFetch(koe, 8, jsonLength);\n\t\t\tconst manifest = JSON.parse(new TextDecoder().decode(json)) as Manifest;\n\t\t\treturn new VoiceBank(\n\t\t\t\tmanifest,\n\t\t\t\tnew RangeVoiceSource(koe, pcmBase(jsonLength)),\n\t\t\t);\n\t\t}\n\t\tconst header = await koe.slice(0, 8).arrayBuffer();\n\t\tconst { jsonLength } = parseKoeHeader(header);\n\t\tconst json = await koe.slice(8, 8 + jsonLength).arrayBuffer();\n\t\tconst manifest = JSON.parse(new TextDecoder().decode(json)) as Manifest;\n\t\treturn new VoiceBank(\n\t\t\tmanifest,\n\t\t\tnew BlobVoiceSource(koe, pcmBase(jsonLength)),\n\t\t);\n\t}\n\n\t/** True if the bank contains a phoneme under this alias. */\n\thas(phoneme: string): boolean {\n\t\treturn this.manifest.phonemes[phoneme] !== undefined;\n\t}\n\n\t/**\n\t * Raw Int16 PCM bytes (48 kHz / mono) for a phoneme, or null if unknown.\n\t * The returned ArrayBuffer is freshly allocated and safe to transfer to a\n\t * worker / AudioWorklet.\n\t */\n\tasync readPcmBytes(phoneme: string): Promise<ArrayBuffer | null> {\n\t\tconst entry = this.manifest.phonemes[phoneme];\n\t\tif (!entry) return null;\n\t\treturn this.source.readBytes(entry.offset, entry.length * 2); // Int16 = 2 bytes/sample\n\t}\n\n\t/**\n\t * A phoneme's PCM as a Float64Array normalised to [-1, 1], or null if unknown.\n\t * Intended for external analysis / resynthesis such as the WORLD vocoder.\n\t */\n\tasync getPcm(phoneme: string): Promise<Float64Array | null> {\n\t\tconst buf = await this.readPcmBytes(phoneme);\n\t\tif (!buf) return null;\n\t\tconst int16 = new Int16Array(buf);\n\t\tconst f64 = new Float64Array(int16.length);\n\t\tfor (let i = 0; i < int16.length; i++) f64[i] = int16[i] / 32768;\n\t\treturn f64;\n\t}\n}\n","import type { Manifest, NoteEvent } from \"../types.js\";\nimport { VoiceBank } from \"./voice-bank.js\";\n\nexport type { NoteEvent };\n\nexport interface KoeEngineOptions {\n\t/** URL to koe-worklet.js. Defaults to './koe-worklet.js'. */\n\tworkletUrl?: string;\n}\n\n/**\n * Main-thread API for the koe concatenative synthesis engine.\n *\n * Loads a single .koe archive. The full voice bank is never held in memory:\n * phonemes are fetched on demand (via {@link VoiceBank}) and cached in the\n * audio thread.\n *\n * const engine = new KoeEngine();\n * await engine.load(koeBlobOrUrl);\n * await engine.play([{ phoneme: 'a', pitch: 440, duration: 48000 }]);\n *\n * For analysis / resynthesis (e.g. {@link Worldline}) you usually only need the\n * raw samples — use {@link VoiceBank} directly instead, which needs no\n * AudioContext or worklet.\n */\nexport class KoeEngine {\n\tprivate ctx: AudioContext;\n\tprivate workletUrl: string;\n\tprivate node: AudioWorkletNode | null = null;\n\tprivate bank: VoiceBank | null = null;\n\tprivate delivered = new Set<string>();\n\tprivate pending = new Map<string, Promise<void>>();\n\n\tconstructor(options: KoeEngineOptions = {}) {\n\t\tthis.ctx = new AudioContext({ sampleRate: 48000 });\n\t\tthis.workletUrl = options.workletUrl ?? \"./koe-worklet.js\";\n\t}\n\n\tget audioContext(): AudioContext {\n\t\treturn this.ctx;\n\t}\n\n\tget manifest(): Manifest | null {\n\t\treturn this.bank?.manifest ?? null;\n\t}\n\n\t/** The underlying voice bank (manifest + on-demand PCM), or null before load(). */\n\tget voiceBank(): VoiceBank | null {\n\t\treturn this.bank;\n\t}\n\n\t/**\n\t * Register the worklet and bind a .koe voice bank.\n\t * @param koe a Blob/File of the .koe archive, or a URL (served with Range support)\n\t */\n\tasync load(koe: Blob | string): Promise<void> {\n\t\tawait this.ctx.audioWorklet.addModule(this.workletUrl);\n\n\t\tthis.bank = await VoiceBank.load(koe);\n\t\tthis.delivered.clear();\n\t\tthis.pending.clear();\n\n\t\tthis.node = new AudioWorkletNode(this.ctx, \"koe-processor\", {\n\t\t\tnumberOfInputs: 0,\n\t\t\tnumberOfOutputs: 1,\n\t\t\toutputChannelCount: [1],\n\t\t});\n\t\tthis.node.port.postMessage({ type: \"init\", manifest: this.bank.manifest });\n\t\tthis.node.connect(this.ctx.destination);\n\n\t\tconsole.log(\n\t\t\t\"[koe] ready —\",\n\t\t\tObject.keys(this.bank.manifest.phonemes).length,\n\t\t\t\"phonemes (on-demand)\",\n\t\t);\n\t}\n\n\t/** Fetch one phoneme's PCM and deliver it to the worklet (deduped, cached). */\n\tprivate ensurePhoneme(name: string): Promise<void> {\n\t\tif (this.delivered.has(name)) return Promise.resolve();\n\t\tconst existing = this.pending.get(name);\n\t\tif (existing) return existing;\n\t\tif (!this.bank || !this.node) return Promise.resolve();\n\n\t\tconst load = this.bank.readPcmBytes(name).then((buf) => {\n\t\t\tif (!buf) return;\n\t\t\tthis.node!.port.postMessage({ type: \"phoneme\", name, buffer: buf }, [\n\t\t\t\tbuf,\n\t\t\t]);\n\t\t\tthis.delivered.add(name);\n\t\t\tthis.pending.delete(name);\n\t\t});\n\n\t\tthis.pending.set(name, load);\n\t\treturn load;\n\t}\n\n\t/** Stop current playback, preload the phonemes for `notes`, then queue them. */\n\tasync play(notes: NoteEvent[]): Promise<void> {\n\t\tif (!this.node) throw new Error(\"KoeEngine: call load() before play()\");\n\t\tthis.node.port.postMessage({ type: \"stop\" });\n\t\tconst names = [...new Set(notes.map((n) => n.phoneme))].filter(Boolean);\n\t\tawait Promise.all(names.map((n) => this.ensurePhoneme(n)));\n\t\tthis.node.port.postMessage({ type: \"play\", notes });\n\t}\n\n\t/** Stop playback and clear the queue. */\n\tstop(): void {\n\t\tthis.node?.port.postMessage({ type: \"stop\" });\n\t}\n\n\t/** Resume the AudioContext if suspended (e.g. after autoplay block). */\n\tasync resume(): Promise<void> {\n\t\tif (this.ctx.state === \"suspended\") await this.ctx.resume();\n\t}\n\n\t/**\n\t * Read a phoneme's raw PCM and return it as a Float64Array normalised to\n\t * [-1, 1]. Convenience that forwards to the underlying {@link VoiceBank}.\n\t * Intended for external analysis such as the WORLD vocoder.\n\t */\n\tasync getPcm(phoneme: string): Promise<Float64Array | null> {\n\t\treturn this.bank?.getPcm(phoneme) ?? null;\n\t}\n}\n","import type { PhonemeEntry } from \"../types.js\";\n\n/** Output sample rate of the worldline synthesizer. */\nexport const WORLDLINE_SAMPLE_RATE = 48000;\n\n/**\n * WORLD needs roughly 85 ms of audio for stable F0 analysis. Phonemes with\n * fewer samples than this are rejected (renderNote returns null).\n */\nexport const MIN_WORLDLINE_SAMPLES = 4096;\n\n/** SynthRequest struct layout — 120 bytes, WASM32. */\nconst SYNTH_REQ_SIZE = 120;\n/** Frame period hardcoded in worldline's phrase_synth.cpp. */\nconst WL_FRAME_MS = 10;\n\n/**\n * The subset of the Emscripten module surface that we call. worldline.js is an\n * MODULARIZE=1 / EXPORT_NAME=WorldlineModule build of OpenUtau's worldline.\n */\ninterface WorldlineWasm {\n\t_PhraseSynthNew(): number;\n\t_PhraseSynthDelete(ps: number): void;\n\t_PhraseSynthAddRequest(\n\t\tps: number,\n\t\treq: number,\n\t\tposMs: number,\n\t\tskipMs: number,\n\t\tlengthMs: number,\n\t\tfadeInMs: number,\n\t\tfadeOutMs: number,\n\t\tflag: number,\n\t): void;\n\t_PhraseSynthSetCurves(\n\t\tps: number,\n\t\tf0: number,\n\t\tgender: number,\n\t\ttension: number,\n\t\tbreathiness: number,\n\t\tvoicing: number,\n\t\tlength: number,\n\t\tframeMs: number,\n\t): void;\n\t_PhraseSynthSynth(ps: number, yPtrPtr: number, flag: number): number;\n\t_malloc(size: number): number;\n\t_free(ptr: number): void;\n\tsetValue(ptr: number, value: number, type: string): void;\n\tgetValue(ptr: number, type: string): number;\n\tHEAPF32: Float32Array;\n\tHEAPF64: Float64Array;\n}\n\ntype WorldlineFactory = (opts?: {\n\tlocateFile?: (path: string) => string;\n}) => Promise<WorldlineWasm>;\n\ndeclare global {\n\t// Injected by worldline.js when loaded as a classic <script> or via importScripts.\n\t// eslint-disable-next-line no-var\n\tvar WorldlineModule: WorldlineFactory | undefined;\n\t// Present in classic Web Workers (used to load worldline.js off the main thread).\n\t// eslint-disable-next-line no-var\n\tvar importScripts: ((...urls: string[]) => void) | undefined;\n}\n\nexport interface WorldlineLoadOptions {\n\t/**\n\t * URL of `worldline.js` (the Emscripten loader). The matching\n\t * `worldline.wasm` must sit next to it — it is resolved relative to this URL.\n\t *\n\t * When consuming koe from npm + a CDN this is typically e.g.\n\t * `https://cdn.jsdelivr.net/npm/@onjmin/koe/dist/world/worldline.js`, or your\n\t * own hosted copy of `dist/world/`.\n\t */\n\tscriptUrl: string;\n}\n\nexport interface RenderNoteParams {\n\t/**\n\t * Source phoneme PCM normalised to [-1, 1] (e.g. from\n\t * `VoiceBank.getPcm()` / `KoeEngine.getPcm()`).\n\t */\n\tpcm: Float64Array;\n\t/** Target output pitch in Hz. */\n\tpitch: number;\n\t/** Sustain / vowel duration in ms (the lead-in below is rendered on top). */\n\tdurationMs: number;\n\t/** Preutterance / lead-in in ms — convert from {@link PhonemeEntry.pre}. */\n\tpreMs: number;\n\t/** Consonant length in ms — convert from {@link PhonemeEntry.consonant}. */\n\tconsonantMs: number;\n\t/** Reference tempo in BPM for worldline's internal timing. Default 120. */\n\ttempo?: number;\n}\n\n/** Convert a sample count at 48 kHz to milliseconds. */\nexport const samplesToMs = (samples: number): number =>\n\t(samples / WORLDLINE_SAMPLE_RATE) * 1000;\n\n/**\n * Derive {@link RenderNoteParams} lead-in / consonant fields from a manifest\n * entry, so callers don't repeat the sample→ms conversion.\n *\n * const params = { pcm, pitch, durationMs, ...leadInFromEntry(entry) };\n */\nexport function leadInFromEntry(entry: PhonemeEntry): {\n\tpreMs: number;\n\tconsonantMs: number;\n} {\n\treturn {\n\t\tpreMs: samplesToMs(entry.pre || 0),\n\t\tconsonantMs: samplesToMs(entry.consonant || 0),\n\t};\n}\n\n// Cache module factories by script URL so repeated loads share one WASM instance.\nconst moduleCache = new Map<string, Promise<WorldlineWasm>>();\n\nfunction injectScript(src: string): Promise<void> {\n\treturn new Promise((resolve, reject) => {\n\t\tconst existing = document.querySelector<HTMLScriptElement>(\n\t\t\t`script[data-koe-worldline=\"${src}\"]`,\n\t\t);\n\t\tif (existing) {\n\t\t\tresolve();\n\t\t\treturn;\n\t\t}\n\t\tconst s = document.createElement(\"script\");\n\t\ts.src = src;\n\t\ts.dataset.koeWorldline = src;\n\t\ts.onload = () => resolve();\n\t\ts.onerror = () => reject(new Error(`worldline: failed to load ${src}`));\n\t\tdocument.head.appendChild(s);\n\t});\n}\n\nfunction loadWasm(scriptUrl: string): Promise<WorldlineWasm> {\n\tconst cached = moduleCache.get(scriptUrl);\n\tif (cached) return cached;\n\n\tconst baseUrl = scriptUrl.slice(0, scriptUrl.lastIndexOf(\"/\") + 1);\n\tconst instantiate = (): Promise<WorldlineWasm> => {\n\t\tconst factory = globalThis.WorldlineModule;\n\t\tif (!factory)\n\t\t\tthrow new Error(\n\t\t\t\t\"worldline: WorldlineModule global was not defined by the script\",\n\t\t\t);\n\t\t// locateFile resolves worldline.wasm next to the script; fetch works in both\n\t\t// the DOM and Web Workers, so the WASM instantiates the same way off-thread.\n\t\treturn factory({ locateFile: (f: string) => baseUrl + f });\n\t};\n\n\tlet promise: Promise<WorldlineWasm>;\n\tif (typeof document !== \"undefined\") {\n\t\t// Main thread / DOM: load worldline.js via a <script> tag.\n\t\tpromise = injectScript(scriptUrl).then(instantiate);\n\t} else if (typeof globalThis.importScripts === \"function\") {\n\t\t// Classic Web Worker: importScripts runs worldline.js synchronously in the\n\t\t// worker's global scope, defining globalThis.WorldlineModule. This lets the\n\t\t// heavy WORLD synthesis run off the main thread.\n\t\tpromise = Promise.resolve().then(() => {\n\t\t\t(globalThis.importScripts as (...urls: string[]) => void)(scriptUrl);\n\t\t\treturn instantiate();\n\t\t});\n\t} else {\n\t\treturn Promise.reject(\n\t\t\tnew Error(\n\t\t\t\t\"Worldline.load requires a DOM or a classic Web Worker (importScripts) to load worldline.js\",\n\t\t\t),\n\t\t);\n\t}\n\tmoduleCache.set(scriptUrl, promise);\n\treturn promise;\n}\n\n/**\n * High-quality WORLD-vocoder note renderer (OpenUtau's worldline via WASM).\n *\n * Pure synthesis: PCM in → PCM out. No AudioContext, no scheduling — the caller\n * owns playback (schedule the returned buffer on its own timeline). Pair it with\n * {@link VoiceBank} for the source samples:\n *\n * const bank = await VoiceBank.load(koeUrl);\n * const wl = await Worldline.load({ scriptUrl: '.../world/worldline.js' });\n *\n * const entry = bank.manifest.phonemes[alias];\n * const pcm = await bank.getPcm(alias);\n * const audio = wl.renderNote({\n * pcm, pitch: 440, durationMs: 500, ...leadInFromEntry(entry),\n * });\n * // audio: Float32 @ 48 kHz, layout [lead-in/consonant ≈ preMs][vowel ≈ durationMs]\n */\nexport class Worldline {\n\treadonly sampleRate = WORLDLINE_SAMPLE_RATE;\n\n\tprivate constructor(private wasm: WorldlineWasm) {}\n\n\t/**\n\t * Load + instantiate the worldline WASM module (deduped per scriptUrl).\n\t *\n\t * Works on the main thread (loads via `<script>`) and inside a classic Web\n\t * Worker (loads via `importScripts`), so the heavy synthesis can run\n\t * off-thread. The matching `worldline.wasm` is fetched next to scriptUrl.\n\t */\n\tstatic async load(options: WorldlineLoadOptions): Promise<Worldline> {\n\t\treturn new Worldline(await loadWasm(options.scriptUrl));\n\t}\n\n\t/**\n\t * Render one note to Float32 PCM at 48 kHz.\n\t *\n\t * The output buffer is laid out as [lead-in/consonant ≈ preMs][vowel ≈\n\t * durationMs], rendered from sample offset 0 (no leading silence). The vowel\n\t * onset (the \"beat\") sits at ≈ preMs into the buffer, so a sequencer should\n\t * place the buffer at `beatTime − preMs` and may trim/crossfade the lead-in.\n\t *\n\t * No internal crossfade is applied — apply fades externally.\n\t *\n\t * @returns Float32 PCM, or null when `pcm` is shorter than\n\t * {@link MIN_WORLDLINE_SAMPLES} (too short for stable F0 analysis).\n\t */\n\trenderNote(params: RenderNoteParams): Float32Array | null {\n\t\tconst { pcm, pitch, durationMs, preMs, consonantMs, tempo = 120 } = params;\n\t\tif (!pcm || pcm.length < MIN_WORLDLINE_SAMPLES) return null;\n\n\t\tconst WL = this.wasm;\n\t\tconst FS = WORLDLINE_SAMPLE_RATE;\n\t\tconst midiNote = Math.round(69 + 12 * Math.log2(pitch / 440));\n\t\tconst posMs = 0; // no leading silence\n\t\tconst reqLen = preMs + durationMs; // render lead-in/consonant + vowel\n\n\t\t// cut_off must trim at least ~2 frames off the tail. PhraseSynth::AddRequest\n\t\t// computes the trim frame count as ceil(in_length_ms)/frame_ms, but\n\t\t// PyinEstimator yields floor(N/nhop)−1 frames — one fewer. With cut_off=0 the\n\t\t// requested frame count exceeds f0_.size() and Model::Trim's f0_.erase() runs\n\t\t// past end(), causing \"memory access out of bounds\". Trimming 2 frames keeps\n\t\t// it within bounds.\n\t\tconst cutMs = WL_FRAME_MS * 2;\n\n\t\tconst ps = WL._PhraseSynthNew();\n\t\tif (!ps) return null;\n\t\tconst reqPtr = WL._malloc(SYNTH_REQ_SIZE);\n\t\tif (!reqPtr) {\n\t\t\tWL._PhraseSynthDelete(ps);\n\t\t\treturn null;\n\t\t}\n\t\tconst samplePtr = WL._malloc(pcm.length * 8);\n\t\tif (!samplePtr) {\n\t\t\tWL._free(reqPtr);\n\t\t\tWL._PhraseSynthDelete(ps);\n\t\t\treturn null;\n\t\t}\n\t\tWL.HEAPF64.set(pcm, samplePtr >> 3);\n\n\t\tconst sv = (off: number, val: number, type: string) =>\n\t\t\tWL.setValue(reqPtr + off, val, type);\n\t\tsv(0, FS, \"i32\");\n\t\tsv(4, pcm.length, \"i32\");\n\t\tsv(8, samplePtr, \"*\");\n\t\tsv(12, 0, \"i32\");\n\t\tsv(16, 0, \"*\");\n\t\tsv(20, midiNote, \"i32\");\n\t\tsv(24, 100.0, \"double\");\n\t\tsv(32, 0.0, \"double\");\n\t\tsv(40, reqLen, \"double\");\n\t\tsv(48, consonantMs, \"double\");\n\t\tsv(56, cutMs, \"double\");\n\t\tsv(64, 100.0, \"double\");\n\t\tsv(72, 0.0, \"double\");\n\t\tsv(80, tempo, \"double\");\n\t\tsv(88, 0, \"i32\");\n\t\tsv(92, 0, \"*\");\n\t\tsv(96, 0, \"i32\");\n\t\tsv(100, 0, \"i32\");\n\t\tsv(104, 100, \"i32\");\n\t\tsv(108, 0, \"i32\");\n\t\tsv(112, 0, \"i32\");\n\t\tsv(116, 100, \"i32\");\n\n\t\t// skip/fadeIn/fadeOut all 0 — crossfade is handled externally.\n\t\tWL._PhraseSynthAddRequest(ps, reqPtr, posMs, 0.0, reqLen, 0.0, 0.0, 0);\n\t\tWL._free(samplePtr);\n\t\tWL._free(reqPtr);\n\n\t\tconst totalMs = posMs + reqLen + WL_FRAME_MS * 2;\n\t\tconst nFrames = Math.ceil(totalMs / WL_FRAME_MS) + 4;\n\t\tconst f0Arr = new Float64Array(nFrames).fill(pitch);\n\t\tconst gArr = new Float64Array(nFrames).fill(0.5);\n\t\tconst tArr = new Float64Array(nFrames).fill(0.5);\n\t\tconst bArr = new Float64Array(nFrames).fill(0.5);\n\t\tconst vArr = new Float64Array(nFrames).fill(1.0);\n\n\t\tconst f0Ptr = WL._malloc(nFrames * 8);\n\t\tconst gPtr = WL._malloc(nFrames * 8);\n\t\tconst tPtr = WL._malloc(nFrames * 8);\n\t\tconst bPtr = WL._malloc(nFrames * 8);\n\t\tconst vPtr = WL._malloc(nFrames * 8);\n\t\tif (!f0Ptr || !gPtr || !tPtr || !bPtr || !vPtr) {\n\t\t\tif (f0Ptr) WL._free(f0Ptr);\n\t\t\tif (gPtr) WL._free(gPtr);\n\t\t\tif (tPtr) WL._free(tPtr);\n\t\t\tif (bPtr) WL._free(bPtr);\n\t\t\tif (vPtr) WL._free(vPtr);\n\t\t\tWL._PhraseSynthDelete(ps);\n\t\t\treturn null;\n\t\t}\n\t\tWL.HEAPF64.set(f0Arr, f0Ptr >> 3);\n\t\tWL.HEAPF64.set(gArr, gPtr >> 3);\n\t\tWL.HEAPF64.set(tArr, tPtr >> 3);\n\t\tWL.HEAPF64.set(bArr, bPtr >> 3);\n\t\tWL.HEAPF64.set(vArr, vPtr >> 3);\n\t\tWL._PhraseSynthSetCurves(\n\t\t\tps,\n\t\t\tf0Ptr,\n\t\t\tgPtr,\n\t\t\ttPtr,\n\t\t\tbPtr,\n\t\t\tvPtr,\n\t\t\tnFrames,\n\t\t\tWL_FRAME_MS,\n\t\t);\n\t\tWL._free(f0Ptr);\n\t\tWL._free(gPtr);\n\t\tWL._free(tPtr);\n\t\tWL._free(bPtr);\n\t\tWL._free(vPtr);\n\n\t\tconst yPtrPtr = WL._malloc(4);\n\t\tif (!yPtrPtr) {\n\t\t\tWL._PhraseSynthDelete(ps);\n\t\t\treturn null;\n\t\t}\n\t\tconst outLen = WL._PhraseSynthSynth(ps, yPtrPtr, 0);\n\t\tconst yPtr = WL.getValue(yPtrPtr, \"*\");\n\t\tconst audio =\n\t\t\toutLen > 0\n\t\t\t\t? new Float32Array(WL.HEAPF32.buffer, yPtr, outLen).slice()\n\t\t\t\t: null;\n\t\tWL._free(yPtrPtr);\n\t\tWL._PhraseSynthDelete(ps);\n\t\treturn audio;\n\t}\n}\n","export interface OtoEntry {\n\t/** Source WAV filename */\n\twav: string;\n\t/** Phoneme alias */\n\talias: string;\n\t/** Left blank — offset from WAV start (ms) */\n\toffset: number;\n\t/** Consonant portion end from offset (ms) */\n\tconsonant: number;\n\t/** Right blank — negative = from WAV end, positive = from offset (ms) */\n\tcutoff: number;\n\t/** Preutterance from offset (ms) */\n\tpre: number;\n\t/** Overlap / crossfade region (ms) */\n\toverlap: number;\n}\n\n/**\n * Parse oto.ini content (already decoded to UTF-8 string).\n * Silently skips malformed lines.\n */\nexport function parseOto(content: string): OtoEntry[] {\n\tconst entries: OtoEntry[] = [];\n\n\tfor (const raw of content.split(/\\r?\\n/)) {\n\t\tconst line = raw.trim();\n\t\tif (!line || line.startsWith(\"#\")) continue;\n\n\t\tconst eq = line.indexOf(\"=\");\n\t\tif (eq === -1) continue;\n\n\t\tconst wav = line.slice(0, eq).trim();\n\t\tconst parts = line.slice(eq + 1).split(\",\");\n\t\tif (parts.length < 6) continue;\n\n\t\tconst [alias, offsetStr, consonantStr, cutoffStr, preStr, overlapStr] =\n\t\t\tparts;\n\t\t// Empty alias → use filename without extension (UTAU spec default)\n\t\tconst aliasStr = alias.trim() || wav.replace(/\\.[^.]+$/, \"\");\n\t\tconst entry: OtoEntry = {\n\t\t\twav,\n\t\t\talias: aliasStr,\n\t\t\toffset: parseFloat(offsetStr) || 0,\n\t\t\tconsonant: parseFloat(consonantStr) || 0,\n\t\t\tcutoff: parseFloat(cutoffStr) || 0,\n\t\t\tpre: parseFloat(preStr) || 0,\n\t\t\toverlap: parseFloat(overlapStr) || 0,\n\t\t};\n\n\t\tif (!entry.alias) continue;\n\t\tentries.push(entry);\n\t}\n\n\treturn entries;\n}\n","export interface WavData {\n\tsampleRate: number;\n\tchannels: number;\n\t/** Normalized samples in [-1, 1], interleaved if multi-channel */\n\tsamples: Float32Array;\n}\n\n/** Parse a WAV file from an ArrayBuffer. Supports PCM 8/16/24-bit and IEEE float 32-bit. */\nexport function parseWav(buf: ArrayBuffer): WavData {\n\tconst view = new DataView(buf);\n\n\tconst riff = readFourCC(view, 0);\n\tif (riff !== \"RIFF\") throw new Error(`Not a RIFF file (got \"${riff}\")`);\n\n\tlet sampleRate = 0;\n\tlet channels = 0;\n\tlet bitsPerSample = 0;\n\tlet audioFormat = 1;\n\tlet dataOffset = 0;\n\tlet dataLength = 0;\n\n\tlet pos = 12;\n\twhile (pos < view.byteLength - 8) {\n\t\tconst id = readFourCC(view, pos);\n\t\tconst size = view.getUint32(pos + 4, true);\n\t\tpos += 8;\n\n\t\tif (id === \"fmt \") {\n\t\t\taudioFormat = view.getUint16(pos, true);\n\t\t\tchannels = view.getUint16(pos + 2, true);\n\t\t\tsampleRate = view.getUint32(pos + 4, true);\n\t\t\tbitsPerSample = view.getUint16(pos + 14, true);\n\t\t} else if (id === \"data\") {\n\t\t\tdataOffset = pos;\n\t\t\tdataLength = size;\n\t\t\tbreak;\n\t\t}\n\n\t\tpos += size + (size & 1);\n\t}\n\n\tif (!dataOffset) throw new Error(\"WAV has no data chunk\");\n\tif (!channels || !sampleRate) throw new Error(\"WAV fmt chunk missing\");\n\n\tconst bytesPerSample = bitsPerSample >> 3;\n\tconst totalSamples = Math.floor(dataLength / bytesPerSample);\n\tconst samples = new Float32Array(totalSamples);\n\n\tfor (let i = 0; i < totalSamples; i++) {\n\t\tconst p = dataOffset + i * bytesPerSample;\n\t\tif (audioFormat === 3) {\n\t\t\tsamples[i] = view.getFloat32(p, true);\n\t\t} else if (bitsPerSample === 8) {\n\t\t\tsamples[i] = (view.getUint8(p) - 128) / 128;\n\t\t} else if (bitsPerSample === 16) {\n\t\t\tsamples[i] = view.getInt16(p, true) / 32768;\n\t\t} else if (bitsPerSample === 24) {\n\t\t\tconst lo = view.getUint8(p) | (view.getUint8(p + 1) << 8);\n\t\t\tlet hi = view.getUint8(p + 2);\n\t\t\tif (hi & 0x80) hi = hi | 0xffffff00;\n\t\t\tsamples[i] = ((hi << 16) | lo) / 8388608;\n\t\t}\n\t}\n\n\treturn { sampleRate, channels, samples };\n}\n\n/** Mix down to mono by averaging all channels. */\nexport function toMono(wav: WavData): WavData {\n\tif (wav.channels === 1) return wav;\n\tconst len = wav.samples.length / wav.channels;\n\tconst out = new Float32Array(len);\n\tfor (let i = 0; i < len; i++) {\n\t\tlet sum = 0;\n\t\tfor (let c = 0; c < wav.channels; c++)\n\t\t\tsum += wav.samples[i * wav.channels + c];\n\t\tout[i] = sum / wav.channels;\n\t}\n\treturn { sampleRate: wav.sampleRate, channels: 1, samples: out };\n}\n\n/** Linear interpolation resample to targetRate. Expects mono input. */\nexport function resample(wav: WavData, targetRate: number): WavData {\n\tif (wav.sampleRate === targetRate) return wav;\n\tconst ratio = wav.sampleRate / targetRate;\n\tconst outLen = Math.floor(wav.samples.length / ratio);\n\tconst out = new Float32Array(outLen);\n\tconst src = wav.samples;\n\tfor (let i = 0; i < outLen; i++) {\n\t\tconst x = i * ratio;\n\t\tconst xi = Math.floor(x);\n\t\tconst frac = x - xi;\n\t\tout[i] = (src[xi] ?? 0) + ((src[xi + 1] ?? 0) - (src[xi] ?? 0)) * frac;\n\t}\n\treturn { sampleRate: targetRate, channels: 1, samples: out };\n}\n\n/** Convert Float32 [-1,1] samples to Int16 PCM. */\nexport function toInt16(samples: Float32Array): Int16Array {\n\tconst out = new Int16Array(samples.length);\n\tfor (let i = 0; i < samples.length; i++) {\n\t\tout[i] = Math.round(Math.max(-1, Math.min(1, samples[i])) * 32767);\n\t}\n\treturn out;\n}\n\n/** Normalize then convert a WAV to 48kHz/16bit/mono Int16 PCM. */\nexport function normalizePcm(buf: ArrayBuffer): Int16Array {\n\tconst wav = parseWav(buf);\n\tconst mono = toMono(wav);\n\tconst resampled = resample(mono, 48000);\n\treturn toInt16(resampled.samples);\n}\n\nfunction readFourCC(view: DataView, pos: number): string {\n\treturn String.fromCharCode(\n\t\tview.getUint8(pos),\n\t\tview.getUint8(pos + 1),\n\t\tview.getUint8(pos + 2),\n\t\tview.getUint8(pos + 3),\n\t);\n}\n","const SAMPLE_RATE = 48000;\n\nconst NAME_SEMITONE: Record<string, number> = {\n\tc: 0,\n\td: 2,\n\te: 4,\n\tf: 5,\n\tg: 7,\n\ta: 9,\n\tb: 11,\n};\n\n/** Parse a note name like \"E4\", \"G#4\", \"Db5\" → frequency in Hz (null if invalid). */\nexport function noteNameToHz(name: string): number | null {\n\tconst m = /^([A-Ga-g])([#b]?)(-?\\d+)$/.exec(name);\n\tif (!m) return null;\n\tlet semi = NAME_SEMITONE[m[1].toLowerCase()];\n\tif (m[2] === \"#\") semi++;\n\telse if (m[2] === \"b\") semi--;\n\tconst midi = (parseInt(m[3], 10) + 1) * 12 + semi;\n\treturn 440 * 2 ** ((midi - 69) / 12);\n}\n\n/** Recorded pitch encoded in a multi-pitch alias suffix: \"a い_E4\" → 329.63 Hz. */\nexport function pitchFromAliasSuffix(alias: string): number | null {\n\tconst m = /_([A-Ga-g][#b]?-?\\d+)$/.exec(alias);\n\treturn m ? noteNameToHz(m[1]) : null;\n}\n\n/**\n * Estimate the fundamental frequency (Hz) of a voiced region by normalized\n * autocorrelation. Returns 0 when no clear pitch is found (unvoiced consonant,\n * silence, or a region too short to analyse).\n *\n * The signal is decimated to a lower analysis rate for speed; f0 below ~700 Hz\n * is well within the resulting Nyquist limit. A parabolic interpolation around\n * the best lag gives sub-sample (sub-semitone) accuracy.\n */\nexport function detectF0(pcm: Int16Array, start: number, end: number): number {\n\tconst DECIM = 4;\n\tconst sr = SAMPLE_RATE / DECIM; // 12 kHz analysis rate\n\tconst minLag = Math.floor(sr / 700); // highest f0 we look for\n\tconst maxLag = Math.floor(sr / 70); // lowest f0 we look for\n\n\tconst outLen = Math.floor((end - start) / DECIM);\n\tif (outLen < maxLag + 2) return 0;\n\tconst win = Math.min(outLen, 1500); // up to ~0.125 s of vowel\n\n\t// Decimate (box-average) + remove DC, and build a prefix sum of squares so\n\t// each lag's window energy is O(1).\n\tconst buf = new Float32Array(win);\n\tlet mean = 0;\n\tfor (let i = 0; i < win; i++) {\n\t\tlet s = 0;\n\t\tconst base = start + i * DECIM;\n\t\tfor (let j = 0; j < DECIM; j++) s += pcm[base + j];\n\t\tbuf[i] = s;\n\t\tmean += s;\n\t}\n\tmean /= win;\n\n\tconst sq = new Float64Array(win + 1);\n\tfor (let i = 0; i < win; i++) {\n\t\tbuf[i] -= mean;\n\t\tsq[i + 1] = sq[i] + buf[i] * buf[i];\n\t}\n\tif (sq[win] < 1) return 0; // effectively silent\n\n\t// Normalized autocorrelation: 2·r(lag) / (E[0..n] + E[lag..lag+n]) ∈ [-1, 1].\n\tconst norm = (lag: number): number => {\n\t\tconst n = win - lag;\n\t\tlet r = 0;\n\t\tfor (let i = 0; i < n; i++) r += buf[i] * buf[i + lag];\n\t\tconst e = sq[n] + (sq[lag + n] - sq[lag]);\n\t\treturn e > 0 ? (2 * r) / e : 0;\n\t};\n\n\tlet bestLag = -1;\n\tlet best = 0;\n\tfor (let lag = minLag; lag <= maxLag; lag++) {\n\t\tconst v = norm(lag);\n\t\tif (v > best) {\n\t\t\tbest = v;\n\t\t\tbestLag = lag;\n\t\t}\n\t}\n\tif (bestLag < 1 || best < 0.4) return 0; // unvoiced / no clear period\n\n\t// Parabolic interpolation around the peak\n\tconst y0 = norm(bestLag - 1);\n\tconst y1 = best;\n\tconst y2 = norm(bestLag + 1);\n\tconst denom = y0 - 2 * y1 + y2;\n\tconst shift = denom !== 0 ? (0.5 * (y0 - y2)) / denom : 0;\n\n\treturn sr / (bestLag + shift);\n}\n","import type { Manifest, PhonemeEntry } from \"../types.js\";\nimport type { OtoEntry } from \"./parse-oto.js\";\nimport { detectF0 } from \"./pitch.js\";\n\nconst TARGET_RATE = 48000;\n\nfunction msToSamples(ms: number): number {\n\treturn Math.round((ms / 1000) * TARGET_RATE);\n}\n\nconst clamp = (v: number, lo: number, hi: number) =>\n\tMath.max(lo, Math.min(hi, v));\n\nexport interface PackInput {\n\toto: OtoEntry;\n\t/** Full normalized PCM of the source WAV (48kHz / 16bit / mono) */\n\tpcm: Int16Array;\n\t/** Known recorded pitch in Hz (e.g. from the .frq file). 0/undefined → auto-detect. */\n\trecordedPitch?: number;\n}\n\nexport interface PackOutput {\n\tmanifest: Manifest;\n\t/** Raw PCM blob — Int16 / 48kHz / mono */\n\tbin: ArrayBuffer;\n}\n\nexport interface TrimmedPhoneme {\n\t/** PCM trimmed to the oto region [offset, cutoff] */\n\tpcm: Int16Array;\n\t/** Manifest params relative to the trimmed start (sample 0 = oto offset) */\n\tentry: Omit<PhonemeEntry, \"offset\">;\n}\n\n/**\n * Cut the full WAV PCM down to its usable oto region and recompute parameters\n * relative to the trimmed start.\n *\n * UTAU oto.ini values are all in ms and measured from `offset` (the left blank),\n * except `cutoff` (right blank):\n * - cutoff >= 0 : measured from the END of the file\n * - cutoff < 0 : region length from offset = |cutoff|\n *\n * After trimming, sample 0 == oto offset, so pre/overlap/consonant carry over\n * unchanged (just converted to samples), and the slice length is the region end.\n */\nexport function trimToOto(\n\tpcm: Int16Array,\n\toto: OtoEntry,\n\trecordedPitch = 0,\n): TrimmedPhoneme {\n\tconst full = pcm.length;\n\n\tconst start = clamp(msToSamples(oto.offset), 0, full);\n\tconst end =\n\t\toto.cutoff < 0\n\t\t\t? clamp(start + msToSamples(-oto.cutoff), start, full)\n\t\t\t: clamp(full - msToSamples(oto.cutoff), start, full);\n\n\tconst slice = pcm.subarray(start, end);\n\tconst length = slice.length;\n\n\tconst pre = clamp(msToSamples(oto.pre), 0, length);\n\tconst overlap = clamp(msToSamples(oto.overlap), 0, length);\n\tconst consonant = clamp(msToSamples(oto.consonant), 0, length);\n\n\t// Prefer the known recorded pitch (from the .frq file or alias suffix); only\n\t// fall back to autocorrelation on the sustained vowel when none is available.\n\tconst pitch =\n\t\trecordedPitch > 0\n\t\t\t? recordedPitch\n\t\t\t: detectF0(\n\t\t\t\t\tslice,\n\t\t\t\t\tMath.min(Math.max(pre, consonant), Math.max(0, length - 1)),\n\t\t\t\t\tlength,\n\t\t\t\t);\n\n\treturn {\n\t\tpcm: slice,\n\t\tentry: { length, pre, overlap, consonant, pitch },\n\t};\n}\n\n/**\n * Pack normalized PCM phonemes into voice.bin + manifest.json.\n * Each phoneme is trimmed to its oto region first.\n * Duplicate aliases are silently overwritten by the later entry.\n */\nexport function pack(inputs: PackInput[], referencePitch = 220): PackOutput {\n\tconst phonemes: Record<string, PhonemeEntry> = {};\n\tconst chunks: Int16Array[] = [];\n\tlet byteOffset = 0;\n\n\tfor (const { oto, pcm, recordedPitch } of inputs) {\n\t\tconst { pcm: slice, entry } = trimToOto(pcm, oto, recordedPitch);\n\t\tif (slice.length === 0) continue;\n\n\t\tphonemes[oto.alias] = { offset: byteOffset, ...entry };\n\t\tbyteOffset += slice.byteLength;\n\t\tchunks.push(slice);\n\t}\n\n\tconst bin = new ArrayBuffer(byteOffset);\n\tconst view = new Uint8Array(bin);\n\tlet pos = 0;\n\tfor (const chunk of chunks) {\n\t\tview.set(\n\t\t\tnew Uint8Array(chunk.buffer, chunk.byteOffset, chunk.byteLength),\n\t\t\tpos,\n\t\t);\n\t\tpos += chunk.byteLength;\n\t}\n\n\tconst manifest: Manifest = {\n\t\tsampleRate: 48000,\n\t\treferencePitch,\n\t\tphonemes,\n\t};\n\n\treturn { manifest, bin };\n}\n","/**\n * UTAU `.frq` frequency-analysis files (FREQ0003). The same format OpenUtau\n * reads: an 8-byte header, hop size, then the average fundamental frequency of\n * the recording — exactly the reference pitch we need for correct resampling.\n *\n * Layout:\n * char[8] \"FREQ0003\"\n * int32 hopSize\n * float64 averageF0 ← the recorded pitch in Hz\n * byte[16] (blank)\n * int32 length\n * { float64 f0, float64 amp } × length\n */\nexport function parseFrqAverageF0(buffer: ArrayBuffer): number | null {\n\tif (buffer.byteLength < 20) return null;\n\tconst view = new DataView(buffer);\n\n\tlet header = \"\";\n\tfor (let i = 0; i < 8; i++) header += String.fromCharCode(view.getUint8(i));\n\tif (header !== \"FREQ0003\") return null;\n\n\tconst avg = view.getFloat64(12, true); // little-endian\n\treturn Number.isFinite(avg) && avg > 0 ? avg : null;\n}\n\n/** Map a WAV filename to its sibling frq filename: \"あ.wav\" → \"あ_wav.frq\". */\nexport function frqFileName(wavName: string): string {\n\tconst dot = wavName.lastIndexOf(\".\");\n\tconst base = dot >= 0 ? wavName.slice(0, dot) : wavName;\n\tconst ext = dot >= 0 ? wavName.slice(dot + 1) : \"wav\";\n\treturn `${base}_${ext}.frq`;\n}\n"],"mappings":"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","names":["header","jsonLength","json","manifest"]}
1
+ {"version":3,"sources":["../src/converter/frq.ts","../src/converter/pitch.ts","../src/converter/pack.ts","../src/converter/parse-oto.ts","../src/converter/wav.ts","../src/koe.ts","../src/engine/voice-bank.ts","../src/engine/index.ts","../src/engine/worldline.ts"],"sourcesContent":["/**\n * UTAU `.frq` frequency-analysis files (FREQ0003). The same format OpenUtau\n * reads: an 8-byte header, hop size, then the average fundamental frequency of\n * the recording — exactly the reference pitch we need for correct resampling.\n *\n * Layout:\n * char[8] \"FREQ0003\"\n * int32 hopSize\n * float64 averageF0 ← the recorded pitch in Hz\n * byte[16] (blank)\n * int32 length\n * { float64 f0, float64 amp } × length\n */\nexport function parseFrqAverageF0(buffer: ArrayBuffer): number | null {\n\tif (buffer.byteLength < 20) return null;\n\tconst view = new DataView(buffer);\n\n\tlet header = \"\";\n\tfor (let i = 0; i < 8; i++) header += String.fromCharCode(view.getUint8(i));\n\tif (header !== \"FREQ0003\") return null;\n\n\tconst avg = view.getFloat64(12, true); // little-endian\n\treturn Number.isFinite(avg) && avg > 0 ? avg : null;\n}\n\n/** Map a WAV filename to its sibling frq filename: \"あ.wav\" → \"あ_wav.frq\". */\nexport function frqFileName(wavName: string): string {\n\tconst dot = wavName.lastIndexOf(\".\");\n\tconst base = dot >= 0 ? wavName.slice(0, dot) : wavName;\n\tconst ext = dot >= 0 ? wavName.slice(dot + 1) : \"wav\";\n\treturn `${base}_${ext}.frq`;\n}\n","const SAMPLE_RATE = 48000;\n\nconst NAME_SEMITONE: Record<string, number> = {\n\tc: 0,\n\td: 2,\n\te: 4,\n\tf: 5,\n\tg: 7,\n\ta: 9,\n\tb: 11,\n};\n\n/** Parse a note name like \"E4\", \"G#4\", \"Db5\" → frequency in Hz (null if invalid). */\nexport function noteNameToHz(name: string): number | null {\n\tconst m = /^([A-Ga-g])([#b]?)(-?\\d+)$/.exec(name);\n\tif (!m) return null;\n\tlet semi = NAME_SEMITONE[m[1].toLowerCase()];\n\tif (m[2] === \"#\") semi++;\n\telse if (m[2] === \"b\") semi--;\n\tconst midi = (parseInt(m[3], 10) + 1) * 12 + semi;\n\treturn 440 * 2 ** ((midi - 69) / 12);\n}\n\n/** Recorded pitch encoded in a multi-pitch alias suffix: \"a い_E4\" → 329.63 Hz. */\nexport function pitchFromAliasSuffix(alias: string): number | null {\n\tconst m = /_([A-Ga-g][#b]?-?\\d+)$/.exec(alias);\n\treturn m ? noteNameToHz(m[1]) : null;\n}\n\n/**\n * Estimate the fundamental frequency (Hz) of a voiced region by normalized\n * autocorrelation. Returns 0 when no clear pitch is found (unvoiced consonant,\n * silence, or a region too short to analyse).\n *\n * The signal is decimated to a lower analysis rate for speed; f0 below ~700 Hz\n * is well within the resulting Nyquist limit. A parabolic interpolation around\n * the best lag gives sub-sample (sub-semitone) accuracy.\n */\nexport function detectF0(pcm: Int16Array, start: number, end: number): number {\n\tconst DECIM = 4;\n\tconst sr = SAMPLE_RATE / DECIM; // 12 kHz analysis rate\n\tconst minLag = Math.floor(sr / 700); // highest f0 we look for\n\tconst maxLag = Math.floor(sr / 70); // lowest f0 we look for\n\n\tconst outLen = Math.floor((end - start) / DECIM);\n\tif (outLen < maxLag + 2) return 0;\n\tconst win = Math.min(outLen, 1500); // up to ~0.125 s of vowel\n\n\t// Decimate (box-average) + remove DC, and build a prefix sum of squares so\n\t// each lag's window energy is O(1).\n\tconst buf = new Float32Array(win);\n\tlet mean = 0;\n\tfor (let i = 0; i < win; i++) {\n\t\tlet s = 0;\n\t\tconst base = start + i * DECIM;\n\t\tfor (let j = 0; j < DECIM; j++) s += pcm[base + j];\n\t\tbuf[i] = s;\n\t\tmean += s;\n\t}\n\tmean /= win;\n\n\tconst sq = new Float64Array(win + 1);\n\tfor (let i = 0; i < win; i++) {\n\t\tbuf[i] -= mean;\n\t\tsq[i + 1] = sq[i] + buf[i] * buf[i];\n\t}\n\tif (sq[win] < 1) return 0; // effectively silent\n\n\t// Normalized autocorrelation: 2·r(lag) / (E[0..n] + E[lag..lag+n]) ∈ [-1, 1].\n\tconst norm = (lag: number): number => {\n\t\tconst n = win - lag;\n\t\tlet r = 0;\n\t\tfor (let i = 0; i < n; i++) r += buf[i] * buf[i + lag];\n\t\tconst e = sq[n] + (sq[lag + n] - sq[lag]);\n\t\treturn e > 0 ? (2 * r) / e : 0;\n\t};\n\n\tlet bestLag = -1;\n\tlet best = 0;\n\tfor (let lag = minLag; lag <= maxLag; lag++) {\n\t\tconst v = norm(lag);\n\t\tif (v > best) {\n\t\t\tbest = v;\n\t\t\tbestLag = lag;\n\t\t}\n\t}\n\tif (bestLag < 1 || best < 0.4) return 0; // unvoiced / no clear period\n\n\t// Parabolic interpolation around the peak\n\tconst y0 = norm(bestLag - 1);\n\tconst y1 = best;\n\tconst y2 = norm(bestLag + 1);\n\tconst denom = y0 - 2 * y1 + y2;\n\tconst shift = denom !== 0 ? (0.5 * (y0 - y2)) / denom : 0;\n\n\treturn sr / (bestLag + shift);\n}\n","import type { Manifest, PhonemeEntry } from \"../types.js\";\nimport type { OtoEntry } from \"./parse-oto.js\";\nimport { detectF0 } from \"./pitch.js\";\n\nconst TARGET_RATE = 48000;\n\nfunction msToSamples(ms: number): number {\n\treturn Math.round((ms / 1000) * TARGET_RATE);\n}\n\nconst clamp = (v: number, lo: number, hi: number) =>\n\tMath.max(lo, Math.min(hi, v));\n\nexport interface PackInput {\n\toto: OtoEntry;\n\t/** Full normalized PCM of the source WAV (48kHz / 16bit / mono) */\n\tpcm: Int16Array;\n\t/** Known recorded pitch in Hz (e.g. from the .frq file). 0/undefined → auto-detect. */\n\trecordedPitch?: number;\n}\n\nexport interface PackOutput {\n\tmanifest: Manifest;\n\t/** Raw PCM blob — Int16 / 48kHz / mono */\n\tbin: ArrayBuffer;\n}\n\nexport interface TrimmedPhoneme {\n\t/** PCM trimmed to the oto region [offset, cutoff] */\n\tpcm: Int16Array;\n\t/** Manifest params relative to the trimmed start (sample 0 = oto offset) */\n\tentry: Omit<PhonemeEntry, \"offset\">;\n}\n\n/**\n * Cut the full WAV PCM down to its usable oto region and recompute parameters\n * relative to the trimmed start.\n *\n * UTAU oto.ini values are all in ms and measured from `offset` (the left blank),\n * except `cutoff` (right blank):\n * - cutoff >= 0 : measured from the END of the file\n * - cutoff < 0 : region length from offset = |cutoff|\n *\n * After trimming, sample 0 == oto offset, so pre/overlap/consonant carry over\n * unchanged (just converted to samples), and the slice length is the region end.\n */\nexport function trimToOto(\n\tpcm: Int16Array,\n\toto: OtoEntry,\n\trecordedPitch = 0,\n): TrimmedPhoneme {\n\tconst full = pcm.length;\n\n\tconst start = clamp(msToSamples(oto.offset), 0, full);\n\tconst end =\n\t\toto.cutoff < 0\n\t\t\t? clamp(start + msToSamples(-oto.cutoff), start, full)\n\t\t\t: clamp(full - msToSamples(oto.cutoff), start, full);\n\n\tconst slice = pcm.subarray(start, end);\n\tconst length = slice.length;\n\n\tconst pre = clamp(msToSamples(oto.pre), 0, length);\n\tconst overlap = clamp(msToSamples(oto.overlap), 0, length);\n\tconst consonant = clamp(msToSamples(oto.consonant), 0, length);\n\n\t// Prefer the known recorded pitch (from the .frq file or alias suffix); only\n\t// fall back to autocorrelation on the sustained vowel when none is available.\n\tconst pitch =\n\t\trecordedPitch > 0\n\t\t\t? recordedPitch\n\t\t\t: detectF0(\n\t\t\t\t\tslice,\n\t\t\t\t\tMath.min(Math.max(pre, consonant), Math.max(0, length - 1)),\n\t\t\t\t\tlength,\n\t\t\t\t);\n\n\treturn {\n\t\tpcm: slice,\n\t\tentry: { length, pre, overlap, consonant, pitch },\n\t};\n}\n\n/**\n * Pack normalized PCM phonemes into voice.bin + manifest.json.\n * Each phoneme is trimmed to its oto region first.\n * Duplicate aliases are silently overwritten by the later entry.\n */\nexport function pack(inputs: PackInput[], referencePitch = 220): PackOutput {\n\tconst phonemes: Record<string, PhonemeEntry> = {};\n\tconst chunks: Int16Array[] = [];\n\tlet byteOffset = 0;\n\n\tfor (const { oto, pcm, recordedPitch } of inputs) {\n\t\tconst { pcm: slice, entry } = trimToOto(pcm, oto, recordedPitch);\n\t\tif (slice.length === 0) continue;\n\n\t\tphonemes[oto.alias] = { offset: byteOffset, ...entry };\n\t\tbyteOffset += slice.byteLength;\n\t\tchunks.push(slice);\n\t}\n\n\tconst bin = new ArrayBuffer(byteOffset);\n\tconst view = new Uint8Array(bin);\n\tlet pos = 0;\n\tfor (const chunk of chunks) {\n\t\tview.set(\n\t\t\tnew Uint8Array(chunk.buffer, chunk.byteOffset, chunk.byteLength),\n\t\t\tpos,\n\t\t);\n\t\tpos += chunk.byteLength;\n\t}\n\n\tconst manifest: Manifest = {\n\t\tsampleRate: 48000,\n\t\treferencePitch,\n\t\tphonemes,\n\t};\n\n\treturn { manifest, bin };\n}\n","export interface OtoEntry {\n\t/** Source WAV filename */\n\twav: string;\n\t/** Phoneme alias */\n\talias: string;\n\t/** Left blank — offset from WAV start (ms) */\n\toffset: number;\n\t/** Consonant portion end from offset (ms) */\n\tconsonant: number;\n\t/** Right blank — negative = from WAV end, positive = from offset (ms) */\n\tcutoff: number;\n\t/** Preutterance from offset (ms) */\n\tpre: number;\n\t/** Overlap / crossfade region (ms) */\n\toverlap: number;\n}\n\n/**\n * Parse oto.ini content (already decoded to UTF-8 string).\n * Silently skips malformed lines.\n */\nexport function parseOto(content: string): OtoEntry[] {\n\tconst entries: OtoEntry[] = [];\n\n\tfor (const raw of content.split(/\\r?\\n/)) {\n\t\tconst line = raw.trim();\n\t\tif (!line || line.startsWith(\"#\")) continue;\n\n\t\tconst eq = line.indexOf(\"=\");\n\t\tif (eq === -1) continue;\n\n\t\tconst wav = line.slice(0, eq).trim();\n\t\tconst parts = line.slice(eq + 1).split(\",\");\n\t\tif (parts.length < 6) continue;\n\n\t\tconst [alias, offsetStr, consonantStr, cutoffStr, preStr, overlapStr] =\n\t\t\tparts;\n\t\t// Empty alias → use filename without extension (UTAU spec default)\n\t\tconst aliasStr = alias.trim() || wav.replace(/\\.[^.]+$/, \"\");\n\t\tconst entry: OtoEntry = {\n\t\t\twav,\n\t\t\talias: aliasStr,\n\t\t\toffset: parseFloat(offsetStr) || 0,\n\t\t\tconsonant: parseFloat(consonantStr) || 0,\n\t\t\tcutoff: parseFloat(cutoffStr) || 0,\n\t\t\tpre: parseFloat(preStr) || 0,\n\t\t\toverlap: parseFloat(overlapStr) || 0,\n\t\t};\n\n\t\tif (!entry.alias) continue;\n\t\tentries.push(entry);\n\t}\n\n\treturn entries;\n}\n","export interface WavData {\n\tsampleRate: number;\n\tchannels: number;\n\t/** Normalized samples in [-1, 1], interleaved if multi-channel */\n\tsamples: Float32Array;\n}\n\n/** Parse a WAV file from an ArrayBuffer. Supports PCM 8/16/24-bit and IEEE float 32-bit. */\nexport function parseWav(buf: ArrayBuffer): WavData {\n\tconst view = new DataView(buf);\n\n\tconst riff = readFourCC(view, 0);\n\tif (riff !== \"RIFF\") throw new Error(`Not a RIFF file (got \"${riff}\")`);\n\n\tlet sampleRate = 0;\n\tlet channels = 0;\n\tlet bitsPerSample = 0;\n\tlet audioFormat = 1;\n\tlet dataOffset = 0;\n\tlet dataLength = 0;\n\n\tlet pos = 12;\n\twhile (pos < view.byteLength - 8) {\n\t\tconst id = readFourCC(view, pos);\n\t\tconst size = view.getUint32(pos + 4, true);\n\t\tpos += 8;\n\n\t\tif (id === \"fmt \") {\n\t\t\taudioFormat = view.getUint16(pos, true);\n\t\t\tchannels = view.getUint16(pos + 2, true);\n\t\t\tsampleRate = view.getUint32(pos + 4, true);\n\t\t\tbitsPerSample = view.getUint16(pos + 14, true);\n\t\t\t// WAVE_FORMAT_EXTENSIBLE: the real format code is the first 2 bytes of\n\t\t\t// the SubFormat GUID in the extension.\n\t\t\tif (audioFormat === 0xfffe && size >= 40) {\n\t\t\t\taudioFormat = view.getUint16(pos + 24, true);\n\t\t\t}\n\t\t} else if (id === \"data\") {\n\t\t\tdataOffset = pos;\n\t\t\t// Clamp to the actual file size — a corrupt chunk header could otherwise\n\t\t\t// send sample reads past the end of the buffer.\n\t\t\tdataLength = Math.min(size, view.byteLength - pos);\n\t\t\tbreak;\n\t\t}\n\n\t\tpos += size + (size & 1);\n\t}\n\n\tif (!dataOffset) throw new Error(\"WAV has no data chunk\");\n\tif (!channels || !sampleRate) throw new Error(\"WAV fmt chunk missing\");\n\n\t// Reject anything the sample loop below cannot decode — falling through\n\t// would silently produce all-zero (silent) audio.\n\tconst supported =\n\t\t(audioFormat === 3 && bitsPerSample === 32) ||\n\t\t(audioFormat === 1 &&\n\t\t\t(bitsPerSample === 8 || bitsPerSample === 16 || bitsPerSample === 24));\n\tif (!supported) {\n\t\tthrow new Error(\n\t\t\t`Unsupported WAV format ${audioFormat} / ${bitsPerSample}-bit (need PCM 8/16/24-bit or IEEE float 32-bit)`,\n\t\t);\n\t}\n\n\tconst bytesPerSample = bitsPerSample >> 3;\n\tconst totalSamples = Math.floor(dataLength / bytesPerSample);\n\tconst samples = new Float32Array(totalSamples);\n\n\tfor (let i = 0; i < totalSamples; i++) {\n\t\tconst p = dataOffset + i * bytesPerSample;\n\t\tif (audioFormat === 3) {\n\t\t\tsamples[i] = view.getFloat32(p, true);\n\t\t} else if (bitsPerSample === 8) {\n\t\t\tsamples[i] = (view.getUint8(p) - 128) / 128;\n\t\t} else if (bitsPerSample === 16) {\n\t\t\tsamples[i] = view.getInt16(p, true) / 32768;\n\t\t} else if (bitsPerSample === 24) {\n\t\t\tconst lo = view.getUint8(p) | (view.getUint8(p + 1) << 8);\n\t\t\tlet hi = view.getUint8(p + 2);\n\t\t\tif (hi & 0x80) hi = hi | 0xffffff00;\n\t\t\tsamples[i] = ((hi << 16) | lo) / 8388608;\n\t\t}\n\t}\n\n\treturn { sampleRate, channels, samples };\n}\n\n/** Mix down to mono by averaging all channels. */\nexport function toMono(wav: WavData): WavData {\n\tif (wav.channels === 1) return wav;\n\tconst len = wav.samples.length / wav.channels;\n\tconst out = new Float32Array(len);\n\tfor (let i = 0; i < len; i++) {\n\t\tlet sum = 0;\n\t\tfor (let c = 0; c < wav.channels; c++)\n\t\t\tsum += wav.samples[i * wav.channels + c];\n\t\tout[i] = sum / wav.channels;\n\t}\n\treturn { sampleRate: wav.sampleRate, channels: 1, samples: out };\n}\n\n/** Linear interpolation resample to targetRate. Expects mono input. */\nexport function resample(wav: WavData, targetRate: number): WavData {\n\tif (wav.sampleRate === targetRate) return wav;\n\tconst ratio = wav.sampleRate / targetRate;\n\tconst outLen = Math.floor(wav.samples.length / ratio);\n\tconst out = new Float32Array(outLen);\n\tconst src = wav.samples;\n\tfor (let i = 0; i < outLen; i++) {\n\t\tconst x = i * ratio;\n\t\tconst xi = Math.floor(x);\n\t\tconst frac = x - xi;\n\t\tout[i] = (src[xi] ?? 0) + ((src[xi + 1] ?? 0) - (src[xi] ?? 0)) * frac;\n\t}\n\treturn { sampleRate: targetRate, channels: 1, samples: out };\n}\n\n/** Convert Float32 [-1,1] samples to Int16 PCM. */\nexport function toInt16(samples: Float32Array): Int16Array {\n\tconst out = new Int16Array(samples.length);\n\tfor (let i = 0; i < samples.length; i++) {\n\t\tout[i] = Math.round(Math.max(-1, Math.min(1, samples[i])) * 32767);\n\t}\n\treturn out;\n}\n\n/** Normalize then convert a WAV to 48kHz/16bit/mono Int16 PCM. */\nexport function normalizePcm(buf: ArrayBuffer): Int16Array {\n\tconst wav = parseWav(buf);\n\tconst mono = toMono(wav);\n\tconst resampled = resample(mono, 48000);\n\treturn toInt16(resampled.samples);\n}\n\nfunction readFourCC(view: DataView, pos: number): string {\n\treturn String.fromCharCode(\n\t\tview.getUint8(pos),\n\t\tview.getUint8(pos + 1),\n\t\tview.getUint8(pos + 2),\n\t\tview.getUint8(pos + 3),\n\t);\n}\n","import type { Manifest } from \"./types.js\";\n\n/** Magic number 'KOE\\0' (stored big-endian as 0x4B 0x4F 0x45 0x00). */\nconst MAGIC = 0x4b4f4500;\n\n/**\n * Koe Archive Format (.koe)\n * [4B] magic 'KOE\\0' (big-endian)\n * [4B] JSON length (little-endian)\n * [N ] manifest JSON (UTF-8)\n * [M ] raw PCM (Int16 / 48kHz / mono); phoneme offsets are relative to here\n */\nexport function packKoe(manifest: Manifest, pcmParts: BlobPart[]): Blob {\n\tconst json = new TextEncoder().encode(JSON.stringify(manifest));\n\tconst header = new ArrayBuffer(8);\n\tconst view = new DataView(header);\n\tview.setUint32(0, MAGIC, false); // magic, big-endian\n\tview.setUint32(4, json.byteLength, true); // json length, little-endian\n\treturn new Blob([header, json, ...pcmParts]);\n}\n\n/** Read the 8-byte header → JSON length. Throws on bad magic. */\nexport function parseKoeHeader(headerBytes: ArrayBuffer): {\n\tjsonLength: number;\n} {\n\tconst view = new DataView(headerBytes);\n\tif (view.byteLength < 8 || view.getUint32(0, false) !== MAGIC) {\n\t\tthrow new Error(\"Not a .koe file (bad magic)\");\n\t}\n\treturn { jsonLength: view.getUint32(4, true) };\n}\n\n/** Byte offset where PCM data begins, given the JSON length. */\nexport const pcmBase = (jsonLength: number): number => 8 + jsonLength;\n","import { parseKoeHeader, pcmBase } from \"../koe.js\";\nimport type { Manifest } from \"../types.js\";\n\n/**\n * Supplies raw bytes from the PCM section of a .koe archive on demand.\n * - BlobVoiceSource: slices an in-memory Blob / File (no full-buffer copy)\n * - RangeVoiceSource: HTTP Range requests against a URL (mobile-friendly)\n * `base` is the byte offset where PCM data starts (8 + jsonLength).\n */\ninterface VoiceSource {\n\treadBytes(offset: number, length: number): Promise<ArrayBuffer>;\n}\n\n/** Hard ceiling on a single phoneme's PCM size (~10.5 MB / ~55s at 48kHz). */\nconst MAX_PHONEME_SAMPLES = 5_242_880;\n/** Hard ceiling on the manifest JSON header itself. */\nconst MAX_JSON_LENGTH = 50 * 1024 * 1024;\n\nclass BlobVoiceSource implements VoiceSource {\n\tconstructor(\n\t\tprivate blob: Blob,\n\t\tprivate base: number,\n\t) {}\n\treadBytes(offset: number, length: number): Promise<ArrayBuffer> {\n\t\tconst start = this.base + offset;\n\t\treturn this.blob.slice(start, start + length).arrayBuffer();\n\t}\n}\n\nclass RangeVoiceSource implements VoiceSource {\n\tconstructor(\n\t\tprivate url: string,\n\t\tprivate base: number,\n\t) {}\n\tasync readBytes(offset: number, length: number): Promise<ArrayBuffer> {\n\t\tconst start = this.base + offset;\n\t\treturn rangeFetch(this.url, start, length);\n\t}\n}\n\nasync function rangeFetch(\n\turl: string,\n\tstart: number,\n\tlength: number,\n): Promise<ArrayBuffer> {\n\tconst res = await fetch(url, {\n\t\theaders: { Range: `bytes=${start}-${start + length - 1}` },\n\t\tcredentials: \"omit\", // never leak cookies / auth to a MML-supplied URL\n\t});\n\t// A server that ignores Range and returns 200 with the full file would\n\t// blow past the requested size and exhaust memory; only accept 206.\n\tif (res.status !== 206) {\n\t\tthrow new Error(\n\t\t\t`.koe fetch failed: expected 206 Partial Content, got ${res.status}`,\n\t\t);\n\t}\n\treturn readCapped(res, length);\n}\n\n/**\n * Read a response body without trusting its declared size: a server can answer\n * 206 yet still stream an oversized body. Abort as soon as the read exceeds\n * the requested byte count, before buffering the excess.\n */\nasync function readCapped(res: Response, length: number): Promise<ArrayBuffer> {\n\tconst reader = res.body?.getReader();\n\tif (!reader) {\n\t\tconst buf = await res.arrayBuffer();\n\t\tif (buf.byteLength > length) {\n\t\t\tthrow new Error(\n\t\t\t\t`.koe fetch failed: response exceeds requested ${length} bytes`,\n\t\t\t);\n\t\t}\n\t\treturn buf;\n\t}\n\tconst out = new Uint8Array(length);\n\tlet received = 0;\n\tfor (;;) {\n\t\tconst { done, value } = await reader.read();\n\t\tif (done) break;\n\t\tif (received + value.byteLength > length) {\n\t\t\tawait reader.cancel();\n\t\t\tthrow new Error(\n\t\t\t\t`.koe fetch failed: response exceeds requested ${length} bytes`,\n\t\t\t);\n\t\t}\n\t\tout.set(value, received);\n\t\treceived += value.byteLength;\n\t}\n\treturn received === length ? out.buffer : out.buffer.slice(0, received);\n}\n\nfunction validateJsonLength(jsonLength: number): void {\n\tif (\n\t\t!Number.isInteger(jsonLength) ||\n\t\tjsonLength < 0 ||\n\t\tjsonLength > MAX_JSON_LENGTH\n\t) {\n\t\tthrow new Error(`manifest JSON length out of bounds: ${jsonLength}`);\n\t}\n}\n\nfunction parseManifest(json: ArrayBuffer): Manifest {\n\tconst manifest = JSON.parse(new TextDecoder().decode(json)) as Manifest;\n\tif (\n\t\t!manifest ||\n\t\ttypeof manifest !== \"object\" ||\n\t\ttypeof manifest.phonemes !== \"object\" ||\n\t\tmanifest.phonemes === null\n\t) {\n\t\tthrow new Error(\"invalid manifest: missing phonemes table\");\n\t}\n\treturn manifest;\n}\n\n/**\n * Read-only access to a .koe voice bank: its manifest plus per-phoneme PCM,\n * fetched on demand (Blob slice or HTTP Range). The full bank is never held in\n * memory.\n *\n * Pure data — no AudioContext, no AudioWorklet, no DOM. Use this when you only\n * need the source samples (e.g. to feed the {@link Worldline} renderer or any\n * other vocoder). {@link KoeEngine} builds its concatenative playback on top of\n * this same class.\n *\n * const bank = await VoiceBank.load(koeBlobOrUrl);\n * const pcm = await bank.getPcm('a'); // Float64 [-1, 1]\n */\nexport class VoiceBank {\n\tprivate constructor(\n\t\t/** The voice bank manifest (sample rate, reference pitch, phoneme table). */\n\t\treadonly manifest: Manifest,\n\t\tprivate source: VoiceSource,\n\t) {}\n\n\t/**\n\t * Parse a .koe archive header + manifest and bind a lazy PCM source.\n\t * @param koe a Blob/File of the .koe archive, or a URL (served with Range support)\n\t */\n\tstatic async load(koe: Blob | string): Promise<VoiceBank> {\n\t\ttry {\n\t\t\tif (typeof koe === \"string\") {\n\t\t\t\t// Range requests on blob: URLs are not portable (Firefox/Safari answer\n\t\t\t\t// 200); the data already lives in memory, so read it back as a Blob.\n\t\t\t\tif (/^blob:/i.test(koe)) {\n\t\t\t\t\tconst res = await fetch(koe);\n\t\t\t\t\tif (!res.ok) {\n\t\t\t\t\t\tthrow new Error(`blob: URL fetch failed: ${res.status}`);\n\t\t\t\t\t}\n\t\t\t\t\treturn await VoiceBank.fromBlob(await res.blob());\n\t\t\t\t}\n\t\t\t\tif (!/^https?:/i.test(koe)) {\n\t\t\t\t\tthrow new Error(`unsupported URL protocol: ${koe}`);\n\t\t\t\t}\n\t\t\t\tconst header = await rangeFetch(koe, 0, 8);\n\t\t\t\tconst { jsonLength } = parseKoeHeader(header);\n\t\t\t\tvalidateJsonLength(jsonLength);\n\t\t\t\tconst json = await rangeFetch(koe, 8, jsonLength);\n\t\t\t\tconst manifest = parseManifest(json);\n\t\t\t\treturn new VoiceBank(\n\t\t\t\t\tmanifest,\n\t\t\t\t\tnew RangeVoiceSource(koe, pcmBase(jsonLength)),\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn await VoiceBank.fromBlob(koe);\n\t\t} catch (error) {\n\t\t\tthrow new Error(\n\t\t\t\t`Failed to load .koe voice bank: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate static async fromBlob(koe: Blob): Promise<VoiceBank> {\n\t\tconst header = await koe.slice(0, 8).arrayBuffer();\n\t\tconst { jsonLength } = parseKoeHeader(header);\n\t\tvalidateJsonLength(jsonLength);\n\t\tconst json = await koe.slice(8, 8 + jsonLength).arrayBuffer();\n\t\tconst manifest = parseManifest(json);\n\t\treturn new VoiceBank(\n\t\t\tmanifest,\n\t\t\tnew BlobVoiceSource(koe, pcmBase(jsonLength)),\n\t\t);\n\t}\n\n\t/** True if the bank contains a phoneme under this alias. */\n\thas(phoneme: string): boolean {\n\t\t// Own-property check: a plain [phoneme] access would also match inherited\n\t\t// Object.prototype keys like \"toString\" / \"constructor\".\n\t\treturn Object.hasOwn(this.manifest.phonemes, phoneme);\n\t}\n\n\t/**\n\t * Raw Int16 PCM bytes (48 kHz / mono) for a phoneme, or null if unknown.\n\t * The returned ArrayBuffer is freshly allocated and safe to transfer to a\n\t * worker / AudioWorklet.\n\t */\n\tasync readPcmBytes(phoneme: string): Promise<ArrayBuffer | null> {\n\t\tif (!Object.hasOwn(this.manifest.phonemes, phoneme)) return null;\n\t\tconst entry = this.manifest.phonemes[phoneme];\n\t\tif (\n\t\t\t!Number.isInteger(entry.offset) ||\n\t\t\t!Number.isInteger(entry.length) ||\n\t\t\tentry.offset < 0 ||\n\t\t\tentry.length < 0 ||\n\t\t\tentry.length > MAX_PHONEME_SAMPLES\n\t\t) {\n\t\t\tthrow new Error(`manifest entry out of bounds for phoneme: ${phoneme}`);\n\t\t}\n\t\treturn this.source.readBytes(entry.offset, entry.length * 2); // Int16 = 2 bytes/sample\n\t}\n\n\t/**\n\t * A phoneme's PCM as a Float64Array normalised to [-1, 1], or null if unknown.\n\t * Intended for external analysis / resynthesis such as the WORLD vocoder.\n\t */\n\tasync getPcm(phoneme: string): Promise<Float64Array | null> {\n\t\tconst buf = await this.readPcmBytes(phoneme);\n\t\tif (!buf) return null;\n\t\t// A truncated read (Blob clamped at EOF) can yield an odd byte count,\n\t\t// which the Int16Array(buffer) constructor rejects — floor to whole samples.\n\t\tconst int16 = new Int16Array(buf, 0, Math.floor(buf.byteLength / 2));\n\t\tconst f64 = new Float64Array(int16.length);\n\t\tfor (let i = 0; i < int16.length; i++) f64[i] = int16[i] / 32768;\n\t\treturn f64;\n\t}\n}\n","import type { Manifest, NoteEvent } from \"../types.js\";\nimport { VoiceBank } from \"./voice-bank.js\";\n\nexport type { NoteEvent };\n\nexport interface KoeEngineOptions {\n\t/** URL to koe-worklet.js. Defaults to './koe-worklet.js'. */\n\tworkletUrl?: string;\n}\n\n/**\n * Main-thread API for the koe concatenative synthesis engine.\n *\n * Loads a single .koe archive. The full voice bank is never held in memory:\n * phonemes are fetched on demand (via {@link VoiceBank}) and cached in the\n * audio thread.\n *\n * const engine = new KoeEngine();\n * await engine.load(koeBlobOrUrl);\n * await engine.play([{ phoneme: 'a', pitch: 440, duration: 48000 }]);\n *\n * For analysis / resynthesis (e.g. {@link Worldline}) you usually only need the\n * raw samples — use {@link VoiceBank} directly instead, which needs no\n * AudioContext or worklet.\n */\nexport class KoeEngine {\n\tprivate ctx: AudioContext;\n\tprivate workletUrl: string;\n\tprivate node: AudioWorkletNode | null = null;\n\tprivate bank: VoiceBank | null = null;\n\tprivate delivered = new Set<string>();\n\tprivate pending = new Map<string, Promise<void>>();\n\n\tconstructor(options: KoeEngineOptions = {}) {\n\t\tthis.ctx = new AudioContext({ sampleRate: 48000 });\n\t\tthis.workletUrl = options.workletUrl ?? \"./koe-worklet.js\";\n\t}\n\n\tget audioContext(): AudioContext {\n\t\treturn this.ctx;\n\t}\n\n\tget manifest(): Manifest | null {\n\t\treturn this.bank?.manifest ?? null;\n\t}\n\n\t/** The underlying voice bank (manifest + on-demand PCM), or null before load(). */\n\tget voiceBank(): VoiceBank | null {\n\t\treturn this.bank;\n\t}\n\n\t/**\n\t * Register the worklet and bind a .koe voice bank.\n\t * @param koe a Blob/File of the .koe archive, or a URL (served with Range support)\n\t */\n\tasync load(koe: Blob | string): Promise<void> {\n\t\tawait this.ctx.audioWorklet.addModule(this.workletUrl);\n\n\t\t// Re-loading: tear down the previous node, or both would keep playing.\n\t\tthis.node?.disconnect();\n\t\tthis.node = null;\n\n\t\tthis.bank = await VoiceBank.load(koe);\n\t\tthis.delivered.clear();\n\t\tthis.pending.clear();\n\n\t\tthis.node = new AudioWorkletNode(this.ctx, \"koe-processor\", {\n\t\t\tnumberOfInputs: 0,\n\t\t\tnumberOfOutputs: 1,\n\t\t\toutputChannelCount: [1],\n\t\t});\n\t\tthis.node.port.postMessage({ type: \"init\", manifest: this.bank.manifest });\n\t\tthis.node.connect(this.ctx.destination);\n\n\t\tconsole.log(\n\t\t\t\"[koe] ready —\",\n\t\t\tObject.keys(this.bank.manifest.phonemes).length,\n\t\t\t\"phonemes (on-demand)\",\n\t\t);\n\t}\n\n\t/** Fetch one phoneme's PCM and deliver it to the worklet (deduped, cached). */\n\tprivate ensurePhoneme(name: string): Promise<void> {\n\t\tif (this.delivered.has(name)) return Promise.resolve();\n\t\tconst existing = this.pending.get(name);\n\t\tif (existing) return existing;\n\t\tif (!this.bank || !this.node) return Promise.resolve();\n\n\t\tconst load = this.bank\n\t\t\t.readPcmBytes(name)\n\t\t\t.then((buf) => {\n\t\t\t\tif (!buf || !this.node) return;\n\t\t\t\tthis.node.port.postMessage({ type: \"phoneme\", name, buffer: buf }, [\n\t\t\t\t\tbuf,\n\t\t\t\t]);\n\t\t\t\tthis.delivered.add(name);\n\t\t\t})\n\t\t\t.finally(() => {\n\t\t\t\t// Always clear pending — a failed fetch must stay retryable, or the\n\t\t\t\t// rejected promise would poison every later play() of this phoneme.\n\t\t\t\tthis.pending.delete(name);\n\t\t\t});\n\n\t\tthis.pending.set(name, load);\n\t\treturn load;\n\t}\n\n\t/** Stop current playback, preload the phonemes for `notes`, then queue them. */\n\tasync play(notes: NoteEvent[]): Promise<void> {\n\t\tif (!this.node) throw new Error(\"KoeEngine: call load() before play()\");\n\t\tthis.node.port.postMessage({ type: \"stop\" });\n\t\tconst names = [...new Set(notes.map((n) => n.phoneme))].filter(Boolean);\n\t\tawait Promise.all(names.map((n) => this.ensurePhoneme(n)));\n\t\tthis.node.port.postMessage({ type: \"play\", notes });\n\t}\n\n\t/** Stop playback and clear the queue. */\n\tstop(): void {\n\t\tthis.node?.port.postMessage({ type: \"stop\" });\n\t}\n\n\t/** Resume the AudioContext if suspended (e.g. after autoplay block). */\n\tasync resume(): Promise<void> {\n\t\tif (this.ctx.state === \"suspended\") await this.ctx.resume();\n\t}\n\n\t/**\n\t * Tear down the worklet node and close the AudioContext, releasing the audio\n\t * hardware. The engine cannot be reused afterwards — create a new one.\n\t */\n\tasync dispose(): Promise<void> {\n\t\tthis.node?.disconnect();\n\t\tthis.node = null;\n\t\tthis.bank = null;\n\t\tthis.delivered.clear();\n\t\tthis.pending.clear();\n\t\tif (this.ctx.state !== \"closed\") await this.ctx.close();\n\t}\n\n\t/**\n\t * Read a phoneme's raw PCM and return it as a Float64Array normalised to\n\t * [-1, 1]. Convenience that forwards to the underlying {@link VoiceBank}.\n\t * Intended for external analysis such as the WORLD vocoder.\n\t */\n\tasync getPcm(phoneme: string): Promise<Float64Array | null> {\n\t\treturn this.bank?.getPcm(phoneme) ?? null;\n\t}\n}\n","import type { PhonemeEntry } from \"../types.js\";\n\n/** Output sample rate of the worldline synthesizer. */\nexport const WORLDLINE_SAMPLE_RATE = 48000;\n\n/**\n * WORLD needs roughly 85 ms of audio for stable F0 analysis. Phonemes with\n * fewer samples than this are rejected (renderNote returns null).\n */\nexport const MIN_WORLDLINE_SAMPLES = 4096;\n\n/** SynthRequest struct layout — 120 bytes, WASM32. */\nconst SYNTH_REQ_SIZE = 120;\n/** Frame period hardcoded in worldline's phrase_synth.cpp. */\nconst WL_FRAME_MS = 10;\n\n/**\n * The subset of the Emscripten module surface that we call. worldline.js is an\n * MODULARIZE=1 / EXPORT_NAME=WorldlineModule build of OpenUtau's worldline.\n */\ninterface WorldlineWasm {\n\t_PhraseSynthNew(): number;\n\t_PhraseSynthDelete(ps: number): void;\n\t_PhraseSynthAddRequest(\n\t\tps: number,\n\t\treq: number,\n\t\tposMs: number,\n\t\tskipMs: number,\n\t\tlengthMs: number,\n\t\tfadeInMs: number,\n\t\tfadeOutMs: number,\n\t\tflag: number,\n\t): void;\n\t_PhraseSynthSetCurves(\n\t\tps: number,\n\t\tf0: number,\n\t\tgender: number,\n\t\ttension: number,\n\t\tbreathiness: number,\n\t\tvoicing: number,\n\t\tlength: number,\n\t\tframeMs: number,\n\t): void;\n\t_PhraseSynthSynth(ps: number, yPtrPtr: number, flag: number): number;\n\t_malloc(size: number): number;\n\t_free(ptr: number): void;\n\tsetValue(ptr: number, value: number, type: string): void;\n\tgetValue(ptr: number, type: string): number;\n\tHEAPF32: Float32Array;\n\tHEAPF64: Float64Array;\n}\n\ntype WorldlineFactory = (opts?: {\n\tlocateFile?: (path: string) => string;\n}) => Promise<WorldlineWasm>;\n\ndeclare global {\n\t// Injected by worldline.js when loaded as a classic <script> or via importScripts.\n\t// eslint-disable-next-line no-var\n\tvar WorldlineModule: WorldlineFactory | undefined;\n\t// Present in classic Web Workers (used to load worldline.js off the main thread).\n\t// eslint-disable-next-line no-var\n\tvar importScripts: ((...urls: string[]) => void) | undefined;\n}\n\nexport interface WorldlineLoadOptions {\n\t/**\n\t * URL of `worldline.js` (the Emscripten loader). The matching\n\t * `worldline.wasm` must sit next to it — it is resolved relative to this URL.\n\t *\n\t * When consuming koe from npm + a CDN this is typically e.g.\n\t * `https://cdn.jsdelivr.net/npm/@onjmin/koe/dist/world/worldline.js`, or your\n\t * own hosted copy of `dist/world/`.\n\t */\n\tscriptUrl: string;\n}\n\nexport interface RenderNoteParams {\n\t/**\n\t * Source phoneme PCM normalised to [-1, 1] (e.g. from\n\t * `VoiceBank.getPcm()` / `KoeEngine.getPcm()`).\n\t */\n\tpcm: Float64Array;\n\t/** Target output pitch in Hz. */\n\tpitch: number;\n\t/** Sustain / vowel duration in ms (the lead-in below is rendered on top). */\n\tdurationMs: number;\n\t/** Preutterance / lead-in in ms — convert from {@link PhonemeEntry.pre}. */\n\tpreMs: number;\n\t/** Consonant length in ms — convert from {@link PhonemeEntry.consonant}. */\n\tconsonantMs: number;\n\t/** Reference tempo in BPM for worldline's internal timing. Default 120. */\n\ttempo?: number;\n}\n\n/** Convert a sample count at 48 kHz to milliseconds. */\nexport const samplesToMs = (samples: number): number =>\n\t(samples / WORLDLINE_SAMPLE_RATE) * 1000;\n\n/**\n * Derive {@link RenderNoteParams} lead-in / consonant fields from a manifest\n * entry, so callers don't repeat the sample→ms conversion.\n *\n * const params = { pcm, pitch, durationMs, ...leadInFromEntry(entry) };\n */\nexport function leadInFromEntry(entry: PhonemeEntry): {\n\tpreMs: number;\n\tconsonantMs: number;\n} {\n\treturn {\n\t\tpreMs: samplesToMs(entry.pre || 0),\n\t\tconsonantMs: samplesToMs(entry.consonant || 0),\n\t};\n}\n\n// Cache module factories by script URL so repeated loads share one WASM instance.\nconst moduleCache = new Map<string, Promise<WorldlineWasm>>();\n\nfunction injectScript(src: string): Promise<void> {\n\treturn new Promise((resolve, reject) => {\n\t\tconst existing = document.querySelector<HTMLScriptElement>(\n\t\t\t`script[data-koe-worldline=\"${src}\"]`,\n\t\t);\n\t\tif (existing) {\n\t\t\tresolve();\n\t\t\treturn;\n\t\t}\n\t\tconst s = document.createElement(\"script\");\n\t\ts.src = src;\n\t\ts.dataset.koeWorldline = src;\n\t\ts.onload = () => resolve();\n\t\ts.onerror = () => reject(new Error(`worldline: failed to load ${src}`));\n\t\tdocument.head.appendChild(s);\n\t});\n}\n\nfunction loadWasm(scriptUrl: string): Promise<WorldlineWasm> {\n\tconst cached = moduleCache.get(scriptUrl);\n\tif (cached) return cached;\n\n\tconst baseUrl = scriptUrl.slice(0, scriptUrl.lastIndexOf(\"/\") + 1);\n\tconst instantiate = (): Promise<WorldlineWasm> => {\n\t\tconst factory = globalThis.WorldlineModule;\n\t\tif (!factory)\n\t\t\tthrow new Error(\n\t\t\t\t\"worldline: WorldlineModule global was not defined by the script\",\n\t\t\t);\n\t\t// locateFile resolves worldline.wasm next to the script; fetch works in both\n\t\t// the DOM and Web Workers, so the WASM instantiates the same way off-thread.\n\t\treturn factory({ locateFile: (f: string) => baseUrl + f });\n\t};\n\n\tlet promise: Promise<WorldlineWasm>;\n\tif (typeof document !== \"undefined\") {\n\t\t// Main thread / DOM: load worldline.js via a <script> tag.\n\t\tpromise = injectScript(scriptUrl).then(instantiate);\n\t} else if (typeof globalThis.importScripts === \"function\") {\n\t\t// Classic Web Worker: importScripts runs worldline.js synchronously in the\n\t\t// worker's global scope, defining globalThis.WorldlineModule. This lets the\n\t\t// heavy WORLD synthesis run off the main thread.\n\t\tpromise = Promise.resolve().then(() => {\n\t\t\t(globalThis.importScripts as (...urls: string[]) => void)(scriptUrl);\n\t\t\treturn instantiate();\n\t\t});\n\t} else {\n\t\treturn Promise.reject(\n\t\t\tnew Error(\n\t\t\t\t\"Worldline.load requires a DOM or a classic Web Worker (importScripts) to load worldline.js\",\n\t\t\t),\n\t\t);\n\t}\n\tmoduleCache.set(scriptUrl, promise);\n\treturn promise;\n}\n\n/**\n * High-quality WORLD-vocoder note renderer (OpenUtau's worldline via WASM).\n *\n * Pure synthesis: PCM in → PCM out. No AudioContext, no scheduling — the caller\n * owns playback (schedule the returned buffer on its own timeline). Pair it with\n * {@link VoiceBank} for the source samples:\n *\n * const bank = await VoiceBank.load(koeUrl);\n * const wl = await Worldline.load({ scriptUrl: '.../world/worldline.js' });\n *\n * const entry = bank.manifest.phonemes[alias];\n * const pcm = await bank.getPcm(alias);\n * const audio = wl.renderNote({\n * pcm, pitch: 440, durationMs: 500, ...leadInFromEntry(entry),\n * });\n * // audio: Float32 @ 48 kHz, layout [lead-in/consonant ≈ preMs][vowel ≈ durationMs]\n */\nexport class Worldline {\n\treadonly sampleRate = WORLDLINE_SAMPLE_RATE;\n\n\tprivate constructor(private wasm: WorldlineWasm) {}\n\n\t/**\n\t * Load + instantiate the worldline WASM module (deduped per scriptUrl).\n\t *\n\t * Works on the main thread (loads via `<script>`) and inside a classic Web\n\t * Worker (loads via `importScripts`), so the heavy synthesis can run\n\t * off-thread. The matching `worldline.wasm` is fetched next to scriptUrl.\n\t */\n\tstatic async load(options: WorldlineLoadOptions): Promise<Worldline> {\n\t\treturn new Worldline(await loadWasm(options.scriptUrl));\n\t}\n\n\t/**\n\t * Render one note to Float32 PCM at 48 kHz.\n\t *\n\t * The output buffer is laid out as [lead-in/consonant ≈ preMs][vowel ≈\n\t * durationMs], rendered from sample offset 0 (no leading silence). The vowel\n\t * onset (the \"beat\") sits at ≈ preMs into the buffer, so a sequencer should\n\t * place the buffer at `beatTime − preMs` and may trim/crossfade the lead-in.\n\t *\n\t * No internal crossfade is applied — apply fades externally.\n\t *\n\t * @returns Float32 PCM, or null when `pcm` is shorter than\n\t * {@link MIN_WORLDLINE_SAMPLES} (too short for stable F0 analysis).\n\t */\n\trenderNote(params: RenderNoteParams): Float32Array | null {\n\t\tconst { pcm, pitch, durationMs, preMs, consonantMs, tempo = 120 } = params;\n\t\tif (!pcm || pcm.length < MIN_WORLDLINE_SAMPLES) return null;\n\n\t\tconst WL = this.wasm;\n\t\tconst FS = WORLDLINE_SAMPLE_RATE;\n\t\tconst midiNote = Math.round(69 + 12 * Math.log2(pitch / 440));\n\t\tconst posMs = 0; // no leading silence\n\t\tconst reqLen = preMs + durationMs; // render lead-in/consonant + vowel\n\n\t\t// cut_off must trim at least ~2 frames off the tail. PhraseSynth::AddRequest\n\t\t// computes the trim frame count as ceil(in_length_ms)/frame_ms, but\n\t\t// PyinEstimator yields floor(N/nhop)−1 frames — one fewer. With cut_off=0 the\n\t\t// requested frame count exceeds f0_.size() and Model::Trim's f0_.erase() runs\n\t\t// past end(), causing \"memory access out of bounds\". Trimming 2 frames keeps\n\t\t// it within bounds.\n\t\tconst cutMs = WL_FRAME_MS * 2;\n\n\t\tconst ps = WL._PhraseSynthNew();\n\t\tif (!ps) return null;\n\t\tconst reqPtr = WL._malloc(SYNTH_REQ_SIZE);\n\t\tif (!reqPtr) {\n\t\t\tWL._PhraseSynthDelete(ps);\n\t\t\treturn null;\n\t\t}\n\t\tconst samplePtr = WL._malloc(pcm.length * 8);\n\t\tif (!samplePtr) {\n\t\t\tWL._free(reqPtr);\n\t\t\tWL._PhraseSynthDelete(ps);\n\t\t\treturn null;\n\t\t}\n\t\tWL.HEAPF64.set(pcm, samplePtr >> 3);\n\n\t\tconst sv = (off: number, val: number, type: string) =>\n\t\t\tWL.setValue(reqPtr + off, val, type);\n\t\tsv(0, FS, \"i32\");\n\t\tsv(4, pcm.length, \"i32\");\n\t\tsv(8, samplePtr, \"*\");\n\t\tsv(12, 0, \"i32\");\n\t\tsv(16, 0, \"*\");\n\t\tsv(20, midiNote, \"i32\");\n\t\tsv(24, 100.0, \"double\");\n\t\tsv(32, 0.0, \"double\");\n\t\tsv(40, reqLen, \"double\");\n\t\tsv(48, consonantMs, \"double\");\n\t\tsv(56, cutMs, \"double\");\n\t\tsv(64, 100.0, \"double\");\n\t\tsv(72, 0.0, \"double\");\n\t\tsv(80, tempo, \"double\");\n\t\tsv(88, 0, \"i32\");\n\t\tsv(92, 0, \"*\");\n\t\tsv(96, 0, \"i32\");\n\t\tsv(100, 0, \"i32\");\n\t\tsv(104, 100, \"i32\");\n\t\tsv(108, 0, \"i32\");\n\t\tsv(112, 0, \"i32\");\n\t\tsv(116, 100, \"i32\");\n\n\t\t// skip/fadeIn/fadeOut all 0 — crossfade is handled externally.\n\t\tWL._PhraseSynthAddRequest(ps, reqPtr, posMs, 0.0, reqLen, 0.0, 0.0, 0);\n\t\tWL._free(samplePtr);\n\t\tWL._free(reqPtr);\n\n\t\tconst totalMs = posMs + reqLen + WL_FRAME_MS * 2;\n\t\tconst nFrames = Math.ceil(totalMs / WL_FRAME_MS) + 4;\n\t\tconst f0Arr = new Float64Array(nFrames).fill(pitch);\n\t\tconst gArr = new Float64Array(nFrames).fill(0.5);\n\t\tconst tArr = new Float64Array(nFrames).fill(0.5);\n\t\tconst bArr = new Float64Array(nFrames).fill(0.5);\n\t\tconst vArr = new Float64Array(nFrames).fill(1.0);\n\n\t\tconst f0Ptr = WL._malloc(nFrames * 8);\n\t\tconst gPtr = WL._malloc(nFrames * 8);\n\t\tconst tPtr = WL._malloc(nFrames * 8);\n\t\tconst bPtr = WL._malloc(nFrames * 8);\n\t\tconst vPtr = WL._malloc(nFrames * 8);\n\t\tif (!f0Ptr || !gPtr || !tPtr || !bPtr || !vPtr) {\n\t\t\tif (f0Ptr) WL._free(f0Ptr);\n\t\t\tif (gPtr) WL._free(gPtr);\n\t\t\tif (tPtr) WL._free(tPtr);\n\t\t\tif (bPtr) WL._free(bPtr);\n\t\t\tif (vPtr) WL._free(vPtr);\n\t\t\tWL._PhraseSynthDelete(ps);\n\t\t\treturn null;\n\t\t}\n\t\tWL.HEAPF64.set(f0Arr, f0Ptr >> 3);\n\t\tWL.HEAPF64.set(gArr, gPtr >> 3);\n\t\tWL.HEAPF64.set(tArr, tPtr >> 3);\n\t\tWL.HEAPF64.set(bArr, bPtr >> 3);\n\t\tWL.HEAPF64.set(vArr, vPtr >> 3);\n\t\tWL._PhraseSynthSetCurves(\n\t\t\tps,\n\t\t\tf0Ptr,\n\t\t\tgPtr,\n\t\t\ttPtr,\n\t\t\tbPtr,\n\t\t\tvPtr,\n\t\t\tnFrames,\n\t\t\tWL_FRAME_MS,\n\t\t);\n\t\tWL._free(f0Ptr);\n\t\tWL._free(gPtr);\n\t\tWL._free(tPtr);\n\t\tWL._free(bPtr);\n\t\tWL._free(vPtr);\n\n\t\tconst yPtrPtr = WL._malloc(4);\n\t\tif (!yPtrPtr) {\n\t\t\tWL._PhraseSynthDelete(ps);\n\t\t\treturn null;\n\t\t}\n\t\tconst outLen = WL._PhraseSynthSynth(ps, yPtrPtr, 0);\n\t\tconst yPtr = WL.getValue(yPtrPtr, \"*\");\n\t\tconst audio =\n\t\t\toutLen > 0 && yPtr\n\t\t\t\t? new Float32Array(WL.HEAPF32.buffer, yPtr, outLen).slice()\n\t\t\t\t: null;\n\t\t// The wrapper allocates *y with `new float[]` for the caller to release;\n\t\t// Emscripten's operator new is malloc-backed, so _free reclaims it.\n\t\tif (yPtr) WL._free(yPtr);\n\t\tWL._free(yPtrPtr);\n\t\tWL._PhraseSynthDelete(ps);\n\t\treturn audio;\n\t}\n}\n"],"mappings":"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","names":[]}