memlnaut-nisps/nisps/wasm/README.md

66 lines
3 KiB
Markdown
Raw Normal View History

feat(playground/wasm): WASM bridge between C++ core and SolidJS playground (meml-tgm) Stream 7 wires nisps/ml + nisps/engines into the playground via Emscripten. Highlights: - nisps/wasm/bindings.cpp: flat C API per architecture.md §6.2. Fixed-arch MLP<2, 10, 14, 18, 126>; engine string→type dispatch table with NoOp fallback. - scripts/build-wasm.sh: emcc invocation, MODULARIZE=1, exports listed explicitly; produces playground/public/nisps.{js,wasm}. - playground/src/ml/wasm-iml.ts: main-thread MLP host (sync inference, sync training, RL ops, weights I/O, layer stats, localStorage). - playground/src/ml/wasm-worker.ts: disposable Web Worker for off-thread async training, owns its own WASM instance. - playground/src/ml/dataset.ts: Float32Array-backed FIFO with sample-weight modes (uniform/global/local/combined). Port of legacy dataset.js. - playground/src/audio/engine-host.ts: AudioContext + AudioWorkletNode lifecycle, with start/stop/setEngine/setParams. - playground/src/audio/worklet/nisps-processor.ts: WASM-loading AudioWorkletProcessor that runs engine.process_block per 128-sample block. Loads its own WASM instance from main-thread-supplied bytes (no fetch in worklet). - playground/src/stores/ml-store.ts: wired stub methods to WasmIML singleton; lazy initialize(). - playground/src/debug/probe.ts: window.__nisps now calls real WasmIML via the store; lazy-init on first use. Verified: - bash scripts/build-wasm.sh succeeds (94 KB nisps.wasm) - bun run typecheck OK - bun run build OK (production bundle) - vite dev server serves /nisps.{js,wasm} with COOP/COEP Known limitation: WASM is fixed at one MLP shape. Multi-arch deferred — documented in nisps/wasm/README.md.
2026-04-29 15:36:29 +02:00
# nisps/wasm
Emscripten target that exposes `nisps/ml` (MLP) and `nisps/engines` (audio
engines) to the browser apps via a flat C ABI.
feat(playground/wasm): WASM bridge between C++ core and SolidJS playground (meml-tgm) Stream 7 wires nisps/ml + nisps/engines into the playground via Emscripten. Highlights: - nisps/wasm/bindings.cpp: flat C API per architecture.md §6.2. Fixed-arch MLP<2, 10, 14, 18, 126>; engine string→type dispatch table with NoOp fallback. - scripts/build-wasm.sh: emcc invocation, MODULARIZE=1, exports listed explicitly; produces playground/public/nisps.{js,wasm}. - playground/src/ml/wasm-iml.ts: main-thread MLP host (sync inference, sync training, RL ops, weights I/O, layer stats, localStorage). - playground/src/ml/wasm-worker.ts: disposable Web Worker for off-thread async training, owns its own WASM instance. - playground/src/ml/dataset.ts: Float32Array-backed FIFO with sample-weight modes (uniform/global/local/combined). Port of legacy dataset.js. - playground/src/audio/engine-host.ts: AudioContext + AudioWorkletNode lifecycle, with start/stop/setEngine/setParams. - playground/src/audio/worklet/nisps-processor.ts: WASM-loading AudioWorkletProcessor that runs engine.process_block per 128-sample block. Loads its own WASM instance from main-thread-supplied bytes (no fetch in worklet). - playground/src/stores/ml-store.ts: wired stub methods to WasmIML singleton; lazy initialize(). - playground/src/debug/probe.ts: window.__nisps now calls real WasmIML via the store; lazy-init on first use. Verified: - bash scripts/build-wasm.sh succeeds (94 KB nisps.wasm) - bun run typecheck OK - bun run build OK (production bundle) - vite dev server serves /nisps.{js,wasm} with COOP/COEP Known limitation: WASM is fixed at one MLP shape. Multi-arch deferred — documented in nisps/wasm/README.md.
2026-04-29 15:36:29 +02:00
This directory is a leaf — it does not export headers for inclusion by
other C++ code. The only artifact is `bindings.cpp` plus the build script
that turns it into `manifold/public/nisps.{wasm,js}` (with a transitional
copy to `playground/public/` until P1 of
`docs/specs/plans/one-core-engine-refactor.md` retires the playground).
feat(playground/wasm): WASM bridge between C++ core and SolidJS playground (meml-tgm) Stream 7 wires nisps/ml + nisps/engines into the playground via Emscripten. Highlights: - nisps/wasm/bindings.cpp: flat C API per architecture.md §6.2. Fixed-arch MLP<2, 10, 14, 18, 126>; engine string→type dispatch table with NoOp fallback. - scripts/build-wasm.sh: emcc invocation, MODULARIZE=1, exports listed explicitly; produces playground/public/nisps.{js,wasm}. - playground/src/ml/wasm-iml.ts: main-thread MLP host (sync inference, sync training, RL ops, weights I/O, layer stats, localStorage). - playground/src/ml/wasm-worker.ts: disposable Web Worker for off-thread async training, owns its own WASM instance. - playground/src/ml/dataset.ts: Float32Array-backed FIFO with sample-weight modes (uniform/global/local/combined). Port of legacy dataset.js. - playground/src/audio/engine-host.ts: AudioContext + AudioWorkletNode lifecycle, with start/stop/setEngine/setParams. - playground/src/audio/worklet/nisps-processor.ts: WASM-loading AudioWorkletProcessor that runs engine.process_block per 128-sample block. Loads its own WASM instance from main-thread-supplied bytes (no fetch in worklet). - playground/src/stores/ml-store.ts: wired stub methods to WasmIML singleton; lazy initialize(). - playground/src/debug/probe.ts: window.__nisps now calls real WasmIML via the store; lazy-init on first use. Verified: - bash scripts/build-wasm.sh succeeds (94 KB nisps.wasm) - bun run typecheck OK - bun run build OK (production bundle) - vite dev server serves /nisps.{js,wasm} with COOP/COEP Known limitation: WASM is fixed at one MLP shape. Multi-arch deferred — documented in nisps/wasm/README.md.
2026-04-29 15:36:29 +02:00
## Building
```bash
scripts/build-wasm.sh
```
Requires `emcc` (Emscripten). The script defaults to
`/usr/lib/emscripten/emcc` and respects an `EMCC` env var override.
Output:
- `manifold/public/nisps.wasm` — the compiled module.
- `manifold/public/nisps.js` — Emscripten glue (factory function
feat(playground/wasm): WASM bridge between C++ core and SolidJS playground (meml-tgm) Stream 7 wires nisps/ml + nisps/engines into the playground via Emscripten. Highlights: - nisps/wasm/bindings.cpp: flat C API per architecture.md §6.2. Fixed-arch MLP<2, 10, 14, 18, 126>; engine string→type dispatch table with NoOp fallback. - scripts/build-wasm.sh: emcc invocation, MODULARIZE=1, exports listed explicitly; produces playground/public/nisps.{js,wasm}. - playground/src/ml/wasm-iml.ts: main-thread MLP host (sync inference, sync training, RL ops, weights I/O, layer stats, localStorage). - playground/src/ml/wasm-worker.ts: disposable Web Worker for off-thread async training, owns its own WASM instance. - playground/src/ml/dataset.ts: Float32Array-backed FIFO with sample-weight modes (uniform/global/local/combined). Port of legacy dataset.js. - playground/src/audio/engine-host.ts: AudioContext + AudioWorkletNode lifecycle, with start/stop/setEngine/setParams. - playground/src/audio/worklet/nisps-processor.ts: WASM-loading AudioWorkletProcessor that runs engine.process_block per 128-sample block. Loads its own WASM instance from main-thread-supplied bytes (no fetch in worklet). - playground/src/stores/ml-store.ts: wired stub methods to WasmIML singleton; lazy initialize(). - playground/src/debug/probe.ts: window.__nisps now calls real WasmIML via the store; lazy-init on first use. Verified: - bash scripts/build-wasm.sh succeeds (94 KB nisps.wasm) - bun run typecheck OK - bun run build OK (production bundle) - vite dev server serves /nisps.{js,wasm} with COOP/COEP Known limitation: WASM is fixed at one MLP shape. Multi-arch deferred — documented in nisps/wasm/README.md.
2026-04-29 15:36:29 +02:00
`createNispsModule`, MODULARIZE=1).
Both files are committed (so the browser apps work from a fresh clone
feat(playground/wasm): WASM bridge between C++ core and SolidJS playground (meml-tgm) Stream 7 wires nisps/ml + nisps/engines into the playground via Emscripten. Highlights: - nisps/wasm/bindings.cpp: flat C API per architecture.md §6.2. Fixed-arch MLP<2, 10, 14, 18, 126>; engine string→type dispatch table with NoOp fallback. - scripts/build-wasm.sh: emcc invocation, MODULARIZE=1, exports listed explicitly; produces playground/public/nisps.{js,wasm}. - playground/src/ml/wasm-iml.ts: main-thread MLP host (sync inference, sync training, RL ops, weights I/O, layer stats, localStorage). - playground/src/ml/wasm-worker.ts: disposable Web Worker for off-thread async training, owns its own WASM instance. - playground/src/ml/dataset.ts: Float32Array-backed FIFO with sample-weight modes (uniform/global/local/combined). Port of legacy dataset.js. - playground/src/audio/engine-host.ts: AudioContext + AudioWorkletNode lifecycle, with start/stop/setEngine/setParams. - playground/src/audio/worklet/nisps-processor.ts: WASM-loading AudioWorkletProcessor that runs engine.process_block per 128-sample block. Loads its own WASM instance from main-thread-supplied bytes (no fetch in worklet). - playground/src/stores/ml-store.ts: wired stub methods to WasmIML singleton; lazy initialize(). - playground/src/debug/probe.ts: window.__nisps now calls real WasmIML via the store; lazy-init on first use. Verified: - bash scripts/build-wasm.sh succeeds (94 KB nisps.wasm) - bun run typecheck OK - bun run build OK (production bundle) - vite dev server serves /nisps.{js,wasm} with COOP/COEP Known limitation: WASM is fixed at one MLP shape. Multi-arch deferred — documented in nisps/wasm/README.md.
2026-04-29 15:36:29 +02:00
without a C++ toolchain). Re-run `build-wasm.sh` after changes to
`nisps/{core,ml,engines,wasm}`.
## Architecture (runtime-shaped since one-core-engine P2)
feat(playground/wasm): WASM bridge between C++ core and SolidJS playground (meml-tgm) Stream 7 wires nisps/ml + nisps/engines into the playground via Emscripten. Highlights: - nisps/wasm/bindings.cpp: flat C API per architecture.md §6.2. Fixed-arch MLP<2, 10, 14, 18, 126>; engine string→type dispatch table with NoOp fallback. - scripts/build-wasm.sh: emcc invocation, MODULARIZE=1, exports listed explicitly; produces playground/public/nisps.{js,wasm}. - playground/src/ml/wasm-iml.ts: main-thread MLP host (sync inference, sync training, RL ops, weights I/O, layer stats, localStorage). - playground/src/ml/wasm-worker.ts: disposable Web Worker for off-thread async training, owns its own WASM instance. - playground/src/ml/dataset.ts: Float32Array-backed FIFO with sample-weight modes (uniform/global/local/combined). Port of legacy dataset.js. - playground/src/audio/engine-host.ts: AudioContext + AudioWorkletNode lifecycle, with start/stop/setEngine/setParams. - playground/src/audio/worklet/nisps-processor.ts: WASM-loading AudioWorkletProcessor that runs engine.process_block per 128-sample block. Loads its own WASM instance from main-thread-supplied bytes (no fetch in worklet). - playground/src/stores/ml-store.ts: wired stub methods to WasmIML singleton; lazy initialize(). - playground/src/debug/probe.ts: window.__nisps now calls real WasmIML via the store; lazy-init on first use. Verified: - bash scripts/build-wasm.sh succeeds (94 KB nisps.wasm) - bun run typecheck OK - bun run build OK (production bundle) - vite dev server serves /nisps.{js,wasm} with COOP/COEP Known limitation: WASM is fixed at one MLP shape. Multi-arch deferred — documented in nisps/wasm/README.md.
2026-04-29 15:36:29 +02:00
The browser MLP is `MLPCore<DynamicStorage>` (`nisps/ml/dynamic_storage.hpp`):
`nisps_ml_create(input, output, hidden[3], n, seed)` HONOURS its dimensions.
The 4-layer topology (ReLU×3 + Sigmoid) is fixed; only the dimensions are
runtime, capped at 4096 per dim. Non-positive/null arguments fall back to the
historical defaults:
feat(playground/wasm): WASM bridge between C++ core and SolidJS playground (meml-tgm) Stream 7 wires nisps/ml + nisps/engines into the playground via Emscripten. Highlights: - nisps/wasm/bindings.cpp: flat C API per architecture.md §6.2. Fixed-arch MLP<2, 10, 14, 18, 126>; engine string→type dispatch table with NoOp fallback. - scripts/build-wasm.sh: emcc invocation, MODULARIZE=1, exports listed explicitly; produces playground/public/nisps.{js,wasm}. - playground/src/ml/wasm-iml.ts: main-thread MLP host (sync inference, sync training, RL ops, weights I/O, layer stats, localStorage). - playground/src/ml/wasm-worker.ts: disposable Web Worker for off-thread async training, owns its own WASM instance. - playground/src/ml/dataset.ts: Float32Array-backed FIFO with sample-weight modes (uniform/global/local/combined). Port of legacy dataset.js. - playground/src/audio/engine-host.ts: AudioContext + AudioWorkletNode lifecycle, with start/stop/setEngine/setParams. - playground/src/audio/worklet/nisps-processor.ts: WASM-loading AudioWorkletProcessor that runs engine.process_block per 128-sample block. Loads its own WASM instance from main-thread-supplied bytes (no fetch in worklet). - playground/src/stores/ml-store.ts: wired stub methods to WasmIML singleton; lazy initialize(). - playground/src/debug/probe.ts: window.__nisps now calls real WasmIML via the store; lazy-init on first use. Verified: - bash scripts/build-wasm.sh succeeds (94 KB nisps.wasm) - bun run typecheck OK - bun run build OK (production bundle) - vite dev server serves /nisps.{js,wasm} with COOP/COEP Known limitation: WASM is fixed at one MLP shape. Multi-arch deferred — documented in nisps/wasm/README.md.
2026-04-29 15:36:29 +02:00
32 inputs → [10, 14, 18] hidden → 126 outputs
feat(playground/wasm): WASM bridge between C++ core and SolidJS playground (meml-tgm) Stream 7 wires nisps/ml + nisps/engines into the playground via Emscripten. Highlights: - nisps/wasm/bindings.cpp: flat C API per architecture.md §6.2. Fixed-arch MLP<2, 10, 14, 18, 126>; engine string→type dispatch table with NoOp fallback. - scripts/build-wasm.sh: emcc invocation, MODULARIZE=1, exports listed explicitly; produces playground/public/nisps.{js,wasm}. - playground/src/ml/wasm-iml.ts: main-thread MLP host (sync inference, sync training, RL ops, weights I/O, layer stats, localStorage). - playground/src/ml/wasm-worker.ts: disposable Web Worker for off-thread async training, owns its own WASM instance. - playground/src/ml/dataset.ts: Float32Array-backed FIFO with sample-weight modes (uniform/global/local/combined). Port of legacy dataset.js. - playground/src/audio/engine-host.ts: AudioContext + AudioWorkletNode lifecycle, with start/stop/setEngine/setParams. - playground/src/audio/worklet/nisps-processor.ts: WASM-loading AudioWorkletProcessor that runs engine.process_block per 128-sample block. Loads its own WASM instance from main-thread-supplied bytes (no fetch in worklet). - playground/src/stores/ml-store.ts: wired stub methods to WasmIML singleton; lazy initialize(). - playground/src/debug/probe.ts: window.__nisps now calls real WasmIML via the store; lazy-init on first use. Verified: - bash scripts/build-wasm.sh succeeds (94 KB nisps.wasm) - bun run typecheck OK - bun run build OK (production bundle) - vite dev server serves /nisps.{js,wasm} with COOP/COEP Known limitation: WASM is fixed at one MLP shape. Multi-arch deferred — documented in nisps/wasm/README.md.
2026-04-29 15:36:29 +02:00
`nisps_ml_reshape(ml, in, out, hidden, n, spread)` constructs a new net at
the requested shape, warm-starts it by copying the overlapping weight region
(`nisps/ml/warm_start.hpp`), and swaps it in. The C-side dataset and the
feedback controller state RESET on reshape (front-end shows a confirm modal).
Heap is used only at create/reshape time, never per-call; the firmware target
never compiles the dynamic storage at all (`#error` under
`NISPS_TARGET_EMBEDDED`).
feat(playground/wasm): WASM bridge between C++ core and SolidJS playground (meml-tgm) Stream 7 wires nisps/ml + nisps/engines into the playground via Emscripten. Highlights: - nisps/wasm/bindings.cpp: flat C API per architecture.md §6.2. Fixed-arch MLP<2, 10, 14, 18, 126>; engine string→type dispatch table with NoOp fallback. - scripts/build-wasm.sh: emcc invocation, MODULARIZE=1, exports listed explicitly; produces playground/public/nisps.{js,wasm}. - playground/src/ml/wasm-iml.ts: main-thread MLP host (sync inference, sync training, RL ops, weights I/O, layer stats, localStorage). - playground/src/ml/wasm-worker.ts: disposable Web Worker for off-thread async training, owns its own WASM instance. - playground/src/ml/dataset.ts: Float32Array-backed FIFO with sample-weight modes (uniform/global/local/combined). Port of legacy dataset.js. - playground/src/audio/engine-host.ts: AudioContext + AudioWorkletNode lifecycle, with start/stop/setEngine/setParams. - playground/src/audio/worklet/nisps-processor.ts: WASM-loading AudioWorkletProcessor that runs engine.process_block per 128-sample block. Loads its own WASM instance from main-thread-supplied bytes (no fetch in worklet). - playground/src/stores/ml-store.ts: wired stub methods to WasmIML singleton; lazy initialize(). - playground/src/debug/probe.ts: window.__nisps now calls real WasmIML via the store; lazy-init on first use. Verified: - bash scripts/build-wasm.sh succeeds (94 KB nisps.wasm) - bun run typecheck OK - bun run build OK (production bundle) - vite dev server serves /nisps.{js,wasm} with COOP/COEP Known limitation: WASM is fixed at one MLP shape. Multi-arch deferred — documented in nisps/wasm/README.md.
2026-04-29 15:36:29 +02:00
## C API surface
See `bindings.cpp` for the full list. Summary:
| Group | Functions |
|-----------|------------------------------------------------------------------------------|
| ML life | `nisps_ml_create`, `nisps_ml_destroy`, `nisps_ml_reset`, `nisps_ml_reshape` |
feat(playground/wasm): WASM bridge between C++ core and SolidJS playground (meml-tgm) Stream 7 wires nisps/ml + nisps/engines into the playground via Emscripten. Highlights: - nisps/wasm/bindings.cpp: flat C API per architecture.md §6.2. Fixed-arch MLP<2, 10, 14, 18, 126>; engine string→type dispatch table with NoOp fallback. - scripts/build-wasm.sh: emcc invocation, MODULARIZE=1, exports listed explicitly; produces playground/public/nisps.{js,wasm}. - playground/src/ml/wasm-iml.ts: main-thread MLP host (sync inference, sync training, RL ops, weights I/O, layer stats, localStorage). - playground/src/ml/wasm-worker.ts: disposable Web Worker for off-thread async training, owns its own WASM instance. - playground/src/ml/dataset.ts: Float32Array-backed FIFO with sample-weight modes (uniform/global/local/combined). Port of legacy dataset.js. - playground/src/audio/engine-host.ts: AudioContext + AudioWorkletNode lifecycle, with start/stop/setEngine/setParams. - playground/src/audio/worklet/nisps-processor.ts: WASM-loading AudioWorkletProcessor that runs engine.process_block per 128-sample block. Loads its own WASM instance from main-thread-supplied bytes (no fetch in worklet). - playground/src/stores/ml-store.ts: wired stub methods to WasmIML singleton; lazy initialize(). - playground/src/debug/probe.ts: window.__nisps now calls real WasmIML via the store; lazy-init on first use. Verified: - bash scripts/build-wasm.sh succeeds (94 KB nisps.wasm) - bun run typecheck OK - bun run build OK (production bundle) - vite dev server serves /nisps.{js,wasm} with COOP/COEP Known limitation: WASM is fixed at one MLP shape. Multi-arch deferred — documented in nisps/wasm/README.md.
2026-04-29 15:36:29 +02:00
| ML I/O | `nisps_ml_set_input`, `nisps_ml_process`, `nisps_ml_outputs`, `nisps_ml_infer_batch` |
| Training | `nisps_ml_add_example`, `nisps_ml_train`, `nisps_ml_eval_loss`, `nisps_ml_clear_examples`, `nisps_ml_example_count` |
| Weights | `nisps_ml_weight_count`, `nisps_ml_get_weights`, `nisps_ml_set_weights`, `nisps_ml_draw_weights`, `nisps_ml_move_weights` |
| Diag | `nisps_ml_get_layer_stats`, `nisps_ml_describe` |
| Engines | `nisps_engine_create`, `nisps_engine_destroy`, `nisps_engine_set_params`, `nisps_engine_process_block` |
Engine-id strings follow the C++ `engine_id()` constexpr accessors:
`thru`, `paf_synth`, `channel_strip`, `xiasri`, `verb_fx`, `memlcelium`,
`breakor`, `elysiamorf`, `analysis`. Unknown ids fall back to `thru`
(silent passthrough).