Documentation

JavaScript Start

Use this path for offline processing in Node.js or a browser module.

npm install @effetune/dsp

The package is ESM-only. Save the example as start.mjs and run node start.mjs, or set "type": "module" in the consumer’s package.json. CommonJS require() is not supported.

Node.js >=18 is required. Chromium is acceptance-tested; other evergreen browsers are designed for but not verified in v0.1. The package accepts equal-length Float32Array[] channels and does not decode, encode, or resample audio. In Node.js, @effetune/dsp resolves after installation. In a browser, use a bundler or an import map that maps the bare @effetune/dsp specifier to the package’s dist/index.js; serve that module and its relative WASM/metadata assets from the same secure origin.

import { createChain } from '@effetune/dsp';

const frames = 512;
const mono = Float32Array.from(
  { length: frames },
  (_, frame) => 0.5 * Math.sin(2 * Math.PI * frame / 97)
);
const input = [mono.slice(), mono.slice()];
const chain = await createChain({
  version: 1,
  chain: [{
    id: 'volume',
    type: 'Volume',
    parameters: { volume: -6 }
  }]
});
const output = await chain.process(input, { sampleRate: 48000 });
console.log(output.length, output[0].length, output[0][0]);
chain.close();

The generic createEffect(type), Chain JSON, catalog, and generated named class/factory exports all support every registered type.

Every input sample must be finite. Offline and streaming calls reject NaN, Infinity, and -Infinity with ValidationError before native processing; a rejected stream block does not change filter state.

Graph v1 quickstart

Graph v1 is opt-in routing for branching and merging. This complete example uses the wet/dry recipe, processes once with fresh state, then opens a stateful static stream and reads its prepared compile snapshot:

import { Graph, createGraph, createVolume } from '@effetune/dsp';

const input = [
  new Float32Array(128).fill(0.25),
  new Float32Array(128).fill(0.25)
];
const graphDocument = Graph.wetDry(
  createVolume({ id: 'wet', volume: -6 }),
  { dry: 0.5, wet: 0.5 }
);
const graph = await createGraph(graphDocument);
let stream;

try {
  const offline = await graph.process(input, { sampleRate: 48000 });
  stream = await graph.stream({
    sampleRate: 48000,
    channels: 2,
    blockSize: 128
  });
  const continuous = await stream.process(input);
  console.log(
    offline[0][0],
    continuous[0][0],
    stream.latencySamples,
    stream.compileSnapshot.effectiveSchedule
  );
} finally {
  stream?.close();
  graph.close();
}

See Graph v1 for the document contract, conversion from a Chain, capacity, and stable error fields.