@vessel-dsp/runtime 0.2.3 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -4,14 +4,14 @@ Headless real time MNA simulation runtime and solver console for compiled Vessel
4
4
 
5
5
  ## Install
6
6
 
7
- `@vessel-dsp/runtime` 0.2.1 is on npm. Use runtime 0.2.1 or later: 0.2.0 cannot load a program inside an AudioWorklet (`structuredClone` is not defined there).
7
+ `@vessel-dsp/runtime` 0.3.1 is on npm. Use runtime 0.2.1 or later (0.3.0 adds the packaged worklet): 0.2.0 cannot load a program inside an AudioWorklet (`structuredClone` is not defined there).
8
8
 
9
9
 
10
10
  ```bash
11
11
  bun add @vessel-dsp/runtime @vessel-dsp/compiler
12
12
  ```
13
13
 
14
- Subpath exports: `.` (the `ReferenceRuntime` console, chain runtime, admission, settling, and measurement helpers) and `./wasm/*` (the compiled solver console files: `v2_dsp.cjs` glue plus `v2_dsp.wasm`).
14
+ Subpath exports: `.` (the `ReferenceRuntime` console, chain runtime, admission, settling, and measurement helpers), `./wasm/*` (the compiled solver console files: `v2_dsp.cjs` glue plus `v2_dsp.wasm`), and `./worklet.js` (the bundled v2 AudioWorkletProcessor, ready for `audioWorklet.addModule`).
15
15
 
16
16
  ## Minimal example
17
17
 
@@ -102,10 +102,29 @@ What it does not do: no mutation of the caller `Program` (two runtimes from one
102
102
 
103
103
  A host that cannot dynamically import the glue — an `AudioWorkletGlobalScope` bundles it statically and has no `fetch` — instantiates the module from pre-fetched bytes and passes it as the second argument: `V2WasmEngine.create(program, mod)`, where `mod` comes from the glue factory called with `{ wasmBinary }` read from `@vessel-dsp/runtime/wasm/v2_dsp.wasm`. See the Runtime guide for both paths end to end; on a biased BJT stage the two consoles agree sample by sample to about 1e-7.
104
104
 
105
+ ## Worklet bundle
106
+
107
+ `@vessel-dsp/runtime/worklet.js` resolves to `dist/worklet/v2-audio-worklet.js`: the v2 `AudioWorkletProcessor` (`src/worklet/v2-audio-worklet.ts`, ported from the workbench reference copy) bundled with esbuild into one file with no external imports, Emscripten glue included. `build` writes it via `bun scripts/build-worklet.ts` (after `build:wasm` provides the glue), and `prepack` ships it, so the published tarball always carries the bundle beside `dist/wasm/v2_dsp.wasm`. It runs `program` slots on the TS `ReferenceRuntime` or, when the `load` message carries `wasmConsole: { wasmBytes }`, on the WASM console; `nam`/`ir` slots are refused by name (their adapters ship in `@vessel-dsp/player`). The worklet scope has no `structuredClone`: programs cross it as JSON (see `V2WasmEngine.loadProgram`), so hosts must not depend on that binding either. Verified by `bun scripts/worklet-proof.ts`, which renders 1 s at 48 kHz in headless Chromium (also with `structuredClone` deleted from the page) and asserts agreement with the TS reference render within 1e-4 max abs.
108
+
109
+ ### Consuming the worklet from a bundler (Next.js)
110
+
111
+ The worklet and the wasm are static files behind subpath exports, so resolve them against the importing module rather than a relative path that a bundler rewrites:
112
+
113
+ ```ts
114
+ const workletUrl = new URL("@vessel-dsp/runtime/worklet.js", import.meta.url);
115
+ const wasmUrl = new URL("@vessel-dsp/runtime/wasm/v2_dsp.wasm", import.meta.url);
116
+ await audioContext.audioWorklet.addModule(workletUrl);
117
+ const wasmBytes = await (await fetch(wasmUrl)).arrayBuffer();
118
+ ```
119
+
120
+ For Next.js static export (or any host that serves `public/` verbatim), the copy-to-public alternative avoids bundler URL handling entirely: copy `node_modules/@vessel-dsp/runtime/dist/worklet/v2-audio-worklet.js` and `node_modules/@vessel-dsp/runtime/dist/wasm/v2_dsp.wasm` into `public/vessel-dsp/` and serve them same-origin. Serve `.wasm` as `application/wasm` and the worklet as `text/javascript`; no COOP/COEP headers are needed (single-threaded builds). Hosts that pin or CDN their assets take `workletUrl` / `dspWasmUrl` overrides instead: pass the pinned URLs to `addModule` and `fetch` and skip both patterns above. Lazy-load on first user gesture: create the context, `addModule` the worklet, fetch only the wasm bytes the chain needs, post `load`, then start — never fetch wasm or create a context on page load.
121
+
105
122
  ## Reference console surface
106
123
 
107
- Values: `ReferenceRuntime`, `DEFAULT_NEWTON_MAX_ITERATIONS`, `admissionVerdict`, `predictedWorstCaseNs`, `calibrateNsPerSolve`, `denseLinearSolveWorkload`, `ChainRuntime`, `programSlot`, `processorSlot`, `slotContract`, `resolveBypassMode`, `chainAdvisories`, `bypassNotModelledAdvisories`, `seamScale`, `dacScaleFactor`, `outputConversionFullScale`, `outputDbfs`, `supplyGroundConflicts`, `taperFraction`, `settledRender`, `settledSweepVerified`, `measureSharedWindow`, `measureInputAttributable`, `SETTLE_DEFAULTS`, `V2WasmEngine`.
124
+ Values: `ReferenceRuntime`, `DEFAULT_NEWTON_MAX_ITERATIONS`, `admissionVerdict`, `predictedWorstCaseNs`, `calibrateNsPerSolve`, `denseLinearSolveWorkload`, `ChainRuntime`, `programSlot`, `processorSlot`, `slotContract`, `resolveBypassMode`, `chainAdvisories`, `bypassNotModelledAdvisories`, `seamScale`, `dacScaleFactor`, `outputConversionFullScale`, `outputDbfs`, `supplyGroundConflicts`, `taperFraction`, `settledRender`, `settledSweepVerified`, `measureSharedWindow`, `measureInputAttributable`, `SETTLE_DEFAULTS`, `V2WasmEngine`, `v2WorkletProcessorName`, `postV2WorkletMessage`.
108
125
 
109
126
  Types (import with `import type`): `RuntimeNodeVoltageSnapshot`, `SupplyAddress`, `SupplyInfo`, `AdmissionVerdict`, `RealtimeBudget`, `ChainSlot`, `ExternalProcessor`, `SlotContract`, `StageCoverage`, `SupplyGroundConflict`, `ChainAdvisory`, `SettleOptions`, `CalibrationResult`, and the rest in the package sources.
110
127
 
128
+ Worklet protocol (import with `import type`, except the two values above): `V2WorkletSlot` (one chain slot: a compiled `program`, or an `ir`/`nam` descriptor the runtime worklet refuses by name), `V2WorkletInboundMessage` (`load` an ordered slot chain with optional `wasmConsole` bytes, `setControl` by slot and id, `setBypassMode` by slot), `V2WorkletOutboundMessage` (`loaded` per-slot controls plus supply-ground conflicts and chain advisories, `telemetry` per-slot solver census plus CPU histogram, `error` refusal text), `BypassMode` (`wire` skips the slot, `buffer` and `effect` run it), `V2WorkletPort` (the minimal `{ postMessage }` surface `postV2WorkletMessage` needs, so hosts need no DOM lib).
129
+
111
130
  `RuntimeError` is thrown for misuse: no prepare, bad rate, bad control, bad supply, unimplemented operator or model.
package/dist/index.d.ts CHANGED
@@ -11,4 +11,5 @@ export { V2WasmEngine } from "./v2-wasm-engine";
11
11
  export * from "./calibrate";
12
12
  export { admissionVerdict, predictedWorstCaseNs } from "./admission";
13
13
  export type { AdmissionVerdict, RealtimeBudget } from "./admission";
14
+ export { postV2WorkletMessage, v2WorkletProcessorName, type BypassMode, type V2WorkletInboundMessage, type V2WorkletOutboundMessage, type V2WorkletPort, type V2WorkletSlot, } from "./worklet/v2-worklet-protocol";
14
15
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EACN,2BAA2B,EAC3B,eAAe,EACf,SAAS,EACT,KAAK,aAAa,GAClB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,cAAc,EAAE,yBAAyB,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AACtF,OAAO,EACN,aAAa,EACb,WAAW,EACX,iBAAiB,EACjB,YAAY,EACZ,KAAK,SAAS,EACd,KAAK,iBAAiB,EACtB,KAAK,YAAY,EACjB,KAAK,aAAa,GAClB,MAAM,cAAc,CAAC;AACtB,OAAO,EACN,6BAA6B,EAC7B,gBAAgB,EAChB,YAAY,EACZ,KAAK,0BAA0B,GAC/B,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAC1D,OAAO,EACN,eAAe,EACf,wBAAwB,EACxB,mBAAmB,EACnB,aAAa,EACb,oBAAoB,EACpB,KAAK,aAAa,GAClB,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,qBAAqB,EAAE,KAAK,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AACnF,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,cAAc,aAAa,CAAC;AAC5B,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACrE,YAAY,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EACN,2BAA2B,EAC3B,eAAe,EACf,SAAS,EACT,KAAK,aAAa,GAClB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,cAAc,EAAE,yBAAyB,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AACtF,OAAO,EACN,aAAa,EACb,WAAW,EACX,iBAAiB,EACjB,YAAY,EACZ,KAAK,SAAS,EACd,KAAK,iBAAiB,EACtB,KAAK,YAAY,EACjB,KAAK,aAAa,GAClB,MAAM,cAAc,CAAC;AACtB,OAAO,EACN,6BAA6B,EAC7B,gBAAgB,EAChB,YAAY,EACZ,KAAK,0BAA0B,GAC/B,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAC1D,OAAO,EACN,eAAe,EACf,wBAAwB,EACxB,mBAAmB,EACnB,aAAa,EACb,oBAAoB,EACpB,KAAK,aAAa,GAClB,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,qBAAqB,EAAE,KAAK,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AACnF,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,cAAc,aAAa,CAAC;AAC5B,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACrE,YAAY,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAMpE,OAAO,EACN,oBAAoB,EACpB,sBAAsB,EACtB,KAAK,UAAU,EACf,KAAK,uBAAuB,EAC5B,KAAK,wBAAwB,EAC7B,KAAK,aAAa,EAClB,KAAK,aAAa,GAClB,MAAM,+BAA+B,CAAC"}
package/dist/index.js CHANGED
@@ -15,4 +15,10 @@ export { taperFraction } from "./taper.js";
15
15
  export { V2WasmEngine } from "./v2-wasm-engine.js";
16
16
  export * from "./calibrate.js";
17
17
  export { admissionVerdict, predictedWorstCaseNs } from "./admission.js";
18
+ // Worklet message contract: the only host-side surface for driving the bundled
19
+ // `dist/worklet/v2-audio-worklet.js` (shipped behind the `./worklet.js` subpath).
20
+ // Values: the processor name `addModule` registers, and the type-checked post
21
+ // helper. Types: the inbound/outbound messages, the chain slot descriptors, the
22
+ // bypass vocabulary, and the minimal port surface the helper needs.
23
+ export { postV2WorkletMessage, v2WorkletProcessorName, } from "./worklet/v2-worklet-protocol.js";
18
24
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,iEAAiE;AACjE,EAAE;AACF,oFAAoF;AACpF,sFAAsF;AACtF,mFAAmF;AACnF,kDAAkD;AAElD,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EACN,2BAA2B,EAC3B,eAAe,EACf,SAAS,GAET,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,cAAc,EAAE,yBAAyB,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AACtF,OAAO,EACN,aAAa,EACb,WAAW,EACX,iBAAiB,EACjB,YAAY,GAKZ,MAAM,cAAc,CAAC;AACtB,OAAO,EACN,6BAA6B,EAC7B,gBAAgB,EAChB,YAAY,GAEZ,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACN,eAAe,EACf,wBAAwB,EACxB,mBAAmB,EACnB,aAAa,EACb,oBAAoB,GAEpB,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,qBAAqB,EAA6B,MAAM,iBAAiB,CAAC;AACnF,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,cAAc,aAAa,CAAC;AAC5B,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,iEAAiE;AACjE,EAAE;AACF,oFAAoF;AACpF,sFAAsF;AACtF,mFAAmF;AACnF,kDAAkD;AAElD,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EACN,2BAA2B,EAC3B,eAAe,EACf,SAAS,GAET,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,cAAc,EAAE,yBAAyB,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AACtF,OAAO,EACN,aAAa,EACb,WAAW,EACX,iBAAiB,EACjB,YAAY,GAKZ,MAAM,cAAc,CAAC;AACtB,OAAO,EACN,6BAA6B,EAC7B,gBAAgB,EAChB,YAAY,GAEZ,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACN,eAAe,EACf,wBAAwB,EACxB,mBAAmB,EACnB,aAAa,EACb,oBAAoB,GAEpB,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,qBAAqB,EAA6B,MAAM,iBAAiB,CAAC;AACnF,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,cAAc,aAAa,CAAC;AAC5B,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAErE,+EAA+E;AAC/E,kFAAkF;AAClF,8EAA8E;AAC9E,gFAAgF;AAChF,oEAAoE;AACpE,OAAO,EACN,oBAAoB,EACpB,sBAAsB,GAMtB,MAAM,+BAA+B,CAAC"}