Neural Amp Modeler WASM with multi-instance support for Web Audio integration.
Based on Steven Atkinson's NeuralAmpModelerCore and the TONE3000 WASM port.
- Multi-instance support - Run multiple independent NAM models simultaneously
- Optimized for AudioWorklets - Minimal API designed for real-time audio processing
- TypeScript support - Full type definitions included
- Small footprint - ~200KB WASM binary
npm install @collabhut/nam-wasmimport { createNamModule, NamWasmModule } from "@collabhut/nam-wasm"
// Initialize the module
const emscriptenModule = await createNamModule()
const nam = NamWasmModule.fromModule(emscriptenModule)
// Set the sample rate (must match your AudioContext)
nam.setSampleRate(48000)
// Create an instance and load a model
const instanceId = nam.createInstance()
const modelJson = await fetch("model.nam").then(r => r.text())
const success = nam.loadModel(instanceId, modelJson)
// Process audio (in your AudioWorklet's process method)
nam.process(instanceId, inputBuffer, outputBuffer)
// Clean up when done
nam.destroyInstance(instanceId)
nam.dispose()// processor.ts - AudioWorklet processor
import { createNamModule, NamWasmModule } from "@collabhut/nam-wasm"
class NamProcessor extends AudioWorkletProcessor {
private nam: NamWasmModule | null = null
private instanceId: number = -1
constructor() {
super()
this.init()
this.port.onmessage = (e) => this.handleMessage(e.data)
}
private async init() {
const module = await createNamModule()
this.nam = NamWasmModule.fromModule(module)
this.nam.setSampleRate(sampleRate)
this.instanceId = this.nam.createInstance()
this.port.postMessage({ type: "ready" })
}
private handleMessage(data: any) {
if (data.type === "loadModel" && this.nam) {
const success = this.nam.loadModel(this.instanceId, data.modelJson)
this.port.postMessage({ type: "modelLoaded", success })
}
}
process(inputs: Float32Array[][], outputs: Float32Array[][]) {
if (!this.nam || !this.nam.hasModel(this.instanceId)) {
return true
}
const input = inputs[0][0]
const output = outputs[0][0]
if (input && output) {
this.nam.process(this.instanceId, input, output)
}
return true
}
}
registerProcessor("nam-processor", NamProcessor)// Create multiple independent instances
const instance1 = nam.createInstance()
const instance2 = nam.createInstance()
// Load different models
nam.loadModel(instance1, cleanAmpJson)
nam.loadModel(instance2, distortedAmpJson)
// Process independently
nam.process(instance1, guitar1Input, guitar1Output)
nam.process(instance2, guitar2Input, guitar2Output)
// Check instance count
console.log(nam.getInstanceCount()) // 2| Method | Description |
|---|---|
fromModule(module, bufferSize?) |
Create from an Emscripten module instance |
create(createModule, bufferSize?) |
Create from module factory function |
| Method | Description |
|---|---|
createInstance() |
Create a new NAM instance, returns instance ID |
destroyInstance(id) |
Destroy an instance and free resources |
getInstanceCount() |
Get number of active instances |
| Method | Description |
|---|---|
loadModel(id, json) |
Load a .nam model (JSON string), returns success |
unloadModel(id) |
Unload model from instance |
hasModel(id) |
Check if instance has a model loaded |
getModelLoudness(id) |
Get model loudness in dB (if available) |
hasModelLoudness(id) |
Check if model has loudness metadata |
| Method | Description |
|---|---|
process(id, input, output) |
Process audio through instance |
processInPlace(id, buffer) |
Process audio in-place |
reset(id) |
Reset instance state (call on transport stop) |
| Method | Description |
|---|---|
setSampleRate(rate) |
Set sample rate for all instances |
getSampleRate() |
Get current sample rate |
setMaxBufferSize(size) |
Set max buffer size (default: 128) |
getMaxBufferSize() |
Get current max buffer size |
| Method | Description |
|---|---|
dispose() |
Free all allocated memory |
- Node.js (v16+)
- Emscripten (v3.1.41+)
git clone https://github.com/emscripten-core/emsdk.git
cd emsdk
./emsdk install 3.1.41
./emsdk activate 3.1.41
source ./emsdk_env.shIF WINDOWS (replace ~ with your username, or the appropriate path) After the notepad opens, run the below code according to your emsdk path
notepad $profile
cd C:\Users\~\emsdk
.\emsdk_env.ps1# Clone with submodules
git clone --recursive https://github.com/rootlodge/nam-wasm.git
cd nam-wasm
# Or init submodules if already cloned
git submodule update --init --recursive
# Install dependencies
npm install
# Build WASM and TypeScript
npm run build
# Or build separately
npm run build:wasm # Build WASM only
npm run build:ts # Build TypeScript onlyOutput files are in dist/:
nam.wasm- WebAssembly binary (~200KB)nam.js- Emscripten ES6 module wrapperindex.js/index.d.ts- Package exportsNamWasmModule.js/NamWasmModule.d.ts- TypeScript API
| Model Type | CPU Usage* | Quality |
|---|---|---|
| Standard | ~8% | Full fidelity |
| Lite | ~5-6% | Nearly indistinguishable |
| Feather | ~4-5% | Great for live/mixing |
| Nano | ~3% | Some loss in detail |
*Per instance on i7 @ 4.2GHz
With Lite/Feather models, 6-8 simultaneous instances run comfortably.
MIT License
Neural Amp Modeler Core
Copyright 2023-2025 Steven Atkinson
MIT License
https://github.com/sdatkinson/NeuralAmpModelerCore
Neural Amp Modeler WASM (original port)
Copyright 2023 Steven Atkinson
MIT License
https://github.com/tone-3000/neural-amp-modeler-wasm