cdp-wasm
v0.6.0
Published
CDP (Composers Desktop Project) audio processing programs compiled to WebAssembly, for Node.js and the browser.
Downloads
2,003
Maintainers
Readme
cdp-wasm
The Composers Desktop Project (CDP) compiled to WebAssembly and wrapped in a small typed API for Node.js and the browser.
npm i cdp-wasm # the library
npm i -g cdp-wasm # the `cdp` command line toolQuick start · Effect catalog · Command line · Agent skills · Install details · FAQ
The published package ships the prebuilt
.wasm; you do not need the submodule or a toolchain. The submodule below is only for building from source.
Architecture
CDP programs are individual command-line tools: each reads and writes audio files and takes its parameters as command-line arguments. This package adds a few layers on top so you can drive them with in-memory audio buffers and named parameters, in Node and the browser.
- WebAssembly modules — each CDP program compiled to a
.wasm, sharing onecdp-core(libc + the CDP core libraries). This is the full suite: the same programs, arguments and file formats as native CDP. - The
CDPruntime (cdp.run/cdp.process) — stages your audio into an in-memory filesystem, runs the program, and returns the result as byte arrays /AudioBuffers. You work withUint8Arrays rather than files on disk, and$IN/$OUTtokens stand in for paths. Every bundled program is reachable here. - Data helpers (
decodeWav,extractEnvelope,getPitch,findPeaks, …) — convert CDP's audio and text formats to and from plain JS values: float channel data,[[time, value], …]breakpoint arrays, pitch contours, peak times. - The typed catalog (
EFFECTS/applyEffect,GENERATORS/applyGenerator) — describes each effect and generator as data (named parameters with ranges and defaults) and runs it for you, taking care of spectral (pvoc) analysis/resynthesis wrapping, per-channel splitting and recombining, two-input effects, breakpoint automation, and multi-step pipelines.
applyEffect(cdp, effect, values, wav) typed catalog — named params, pvoc + channels
└─ cdp.process(program, args, bytes) byte interface — $IN/$OUT, one in / one out
└─ cdp.run(program, argv) in-memory FS staging + callMain(argv)
└─ blur.wasm on cdp-core a CDP program (same arguments/formats as native)Each layer is usable on its own: reach for the catalog when you want ready-made
effects with named parameters, or drop down to cdp.run for any bundled program
the catalog doesn't cover.
Building from source
The CDP C sources are a pinned git submodule (CDP8/) tracking the
cdp-wasm-suite/CDP8 fork of upstream
ComposersDesktop/CDP8 — upstream
plus a small set of bug fixes and portability changes (Emscripten support
among them), each maintained as a reviewable topic branch on the fork and
proposed upstream. The sources build unmodified; nothing is patched at build
time.
git clone --recurse-submodules https://github.com/cdp-wasm-suite/cdp-wasm
cd cdp-wasm
source /path/to/emsdk/emsdk_env.sh # activate Emscripten
npm run build:wasm # builds wasm/
npm test # catalog (mono+stereo), helpers, CLI, externals, docs(If you cloned without --recurse-submodules, run git submodule update --init.)
Build knobs (env vars): CDP_SPECTRAL_O3=0 reverts the core + FFT/spectral
programs to -Oz instead of the default -O3 (smaller, ~15% slower
spectral; time-domain programs are always -Oz); CDP_WASM_OUT=<dir> writes
to an alternate output dir; CDP_SIMD_FFT=0 disables the hand-written SIMD128 FFT that
replaces the Singleton FFT in the phase-vocoder path (pvoc/synth) and
fastconv — it is on by default and gated by a build-time scalar-vs-SIMD
self-test. Engines without SIMD128 are handled at runtime, not build
time: each SIMD-bearing program also ships a <program>.scalar.* variant
(~250 KB total), and the loader auto-detects the engine's SIMD support and
picks the right one — old webviews and pre-16.4 Safari/Node just work, a few
percent slower. new CDP({ simd: false }) forces the scalar variants
explicitly. npm run bench measures performance against a baseline build.
libc and the CDP core libraries are compiled once into a shared
cdp-core.{js,wasm}; each program is a small program-only .wasm side module
loaded into that core on demand. The wrapper stages your audio into Emscripten's
in-memory filesystem, runs the program, and hands the results back as byte
arrays / AudioBuffers — you never touch the virtual filesystem directly. (The
loader also transparently supports a legacy self-contained module per program;
build with CDP_WASM_LINKING=static for that.)
The package bundles every CDP audio-processing program — 215 program modules
plus the shared cdp-core (197 main-suite side modules and 18 self-contained
externals), the entire suite that builds to WebAssembly (the only exclusions
are 3 internal build-helper utilities and a few programs that don't
compile/aren't usable headless). Any of them is callable via
cdp.run('<name>', [...args], { inputs, outputs }). The most useful processes
are also exposed through a typed effect catalog (below) with named parameters,
ranges and defaults — 232 effects across 110 CDP programs: abfpan, blur,
bounce, brownian, cantor, cascade, ceracu, clip, combine, constrict,
crumble, crystal, distcut, distmark, distmore, distort, distortt, distrep,
distshift, dvdwind, envcut, envel, envnu, envspeak, extend, fastconv,
filter, flatten, flutter, focus, formants, fractal, fracture,
frfractal, gate, glisten, grain, grainex, hilite, housekeep, hover,
hover2, isolate, iterfof, iterline, madrid, matrix, mchanpan, mchanrev,
mchshred, modify, morph, motor, multimix, newdelay, newmorph, newtex,
packet, panorama, partition, phase, phasor, pitch, psow, pulser, quirk, rejoin, repeater,
repitch, retime, reverb, rmverb, rotor, scramble, selfsim,
sfecho, shifter, shrink, specenv, specfnu, specfold, speclean,
specnu, specross, specsphinx, spectstr, spectune, spectwin,
spike, spin, splinter, strange, strans, stretch, stutter,
submix, subtract, superaccu, suppress, tangent, tesselate, texture, transit,
tremenv, tremolo, tunevary, tweet, verges, waveform, wrappage
(plus synth/sndinfo/pvoc as utilities). A further
16 synthesis generators (no audio input) are exposed the same way (see
below).
Effect catalog
For ready-to-use effects with named parameters, the package ships a curated
catalog (EFFECTS) plus a runner (applyEffect) that handles spectral (pvoc)
wrapping and multichannel sources automatically:
import { CDP, EFFECTS, applyEffect } from 'cdp-wasm';
const cdp = new CDP();
const effect = EFFECTS.find((e) => e.id === 'blur.blur');
const values = { windows: 20 }; // override any of effect.params
const wavOut = await applyEffect(cdp, effect, values, wavIn);Each entry is one mode of one CDP program: it names the program, an argument
template, and its parameters. If you already know CDP, read
The catalog and CDP — it explains what an entry
decides on your behalf (the mode it picks, arguments it fixes, why its ranges are
narrower than CDP's, how its parameter names map back) and when to drop to
cdp.run instead. Every effect page shows the command line its effect really
runs, next to CDP's own synopsis.
Each effect lists its category, program, params (with min/max/default for
building UI), and whether it is spectral, mono-only, or spatial. The catalog
effects span pitch/time, filtering/dynamics, waveset distortion, envelope,
granular, spatialisation, extend/segment, delay/reverb, morph/combine,
spectral and spectral-pitch processing, mixing, texture and synthesis, and are
exercised on mono + stereo by npm test. See the
effect reference for the full list; the
cdp-web app is a UI built
directly from this catalog.
Synthesis generators
Pure generators (no audio input) live in a parallel GENERATORS catalog run by
applyGenerator — 16 synthesis generators: synth wave/noise/silence/spectra/chord,
clicknew clicktrack, impulse, multiosc, synspline, chirikov,
newsynth additive/wave-packet/fractal/Duffing, multisynth
(score-driven), and strands (spiralling pitch-stream texture). Same param
metadata as effects; entries with a text input
(chord notes, click score…) carry a data descriptor:
import { CDP, GENERATORS, applyGenerator } from 'cdp-wasm';
const cdp = new CDP();
const gen = GENERATORS.find((g) => g.id === 'wave');
const wav = await applyGenerator(cdp, gen, { freq: 220, dur: 2 },
{ sampleRate: 48000 }); // default 44100$SR tokens in the generator arg templates resolve to extra.sampleRate, so
generated audio matches your session rate. See the
generator reference.
Envelope / breakpoint helpers
CDP's envelopes are plain-text breakpoint files — time value pairs. The
package can extract a sound's amplitude envelope as editable points, transform
them, and feed one back into any time-varying parameter (see the
ENVELOPE_PARAMS map for which params accept a breakpoint envelope):
import { CDP, extractEnvelope, warpBreakpoints, formatBreakpoints,
applyEffect, EFFECTS } from 'cdp-wasm';
const cdp = new CDP();
// 1. extract an amplitude envelope from a sound -> [[time, value], …]
let points = await extractEnvelope(cdp, wavIn, { windowMs: 15, dataReduce: 0.05 });
// 2. (optional) transform it — normalise / reverse / invert / gate / …
points = await warpBreakpoints(cdp, points, 'normalise');
// 3. drive a parameter with it (here: gain over time)
const gain = EFFECTS.find((e) => e.id === 'modify.loudness');
const wavOut = await applyEffect(cdp, gain, { gain: 1 }, otherWav,
{ brk: { gain: formatBreakpoints(points.map(([t, v]) => [t, 0.2 + v * 1.8])) } });parseBreakpoints / formatBreakpoints convert between the [[t, v], …]
array (easy to draw and edit) and CDP's text format; REPLOT_MODES lists the
warpBreakpoints warp modes. All of these are thin wrappers over the envel
program, so they run in Node and the browser.
Analysis helpers (pitch, peaks)
Beyond envelopes, the package can pull other editable data out of a sound — a pitch contour and transient markers — for display, editing, or driving parameters:
import { CDP, getPitch, findPeaks } from 'cdp-wasm';
const cdp = new CDP();
const pitch = await getPitch(cdp, wav); // [[time, Hz], …] (empty if unpitched)
const peaks = await findPeaks(cdp, wav, { windowMs: 50 }); // [time, …] peak timesgetPitch(cdp, wav)— pitch contour viapvoc anal → repitch getpitch(mixed to mono; monophonic). Feed it back throughextra.brkto make a sound track its own (or another's) pitch. Needs harmonic material — silence, noise, or a pure sine returns[].findPeaks(cdp, wav, { windowMs, threshold })— amplitude-peak times for slicing / rhythmic analysis; works on any channel count.
These sit alongside a larger set of bundled data-producing programs (onset, partials, spectral and MIDI analysis) surveyed in docs/data-programs.md.
Tests
npm test— runs every catalog effect on a mono and a stereo source (plus every generator on its defaults), checking each yields valid, non-silent audio with the expected channel count; also the AIFF, envelope/analysis-helper, CLI, externals, docs-coverage, agent-plugin and cdp-web patch-builder checks.npm run test:parity— compares WASM output against the native CDP command-line tools for every parity-testable effect (deterministic effects match bit-for-bit; effects using a seeded RNG / platform-dependent edge handling are exempt and only checked for valid audio; multi-stepderive/pipelineandexternaleffects are covered bynpm testinstead). Needs native binaries built with CMake andCDP_NATIVE_BINpointing at them. Both run in CI (.github/workflows/ci.yml).
Install
npm install cdp-wasmNo registry configuration and no auth — it's a public package on npmjs.org. Releases carry a provenance attestation linking the tarball to the commit and workflow run that built it.
The compiled .wasm modules are built when the package is published (via a
prepack step) and shipped in the tarball — they are not committed to the repo.
To build them yourself from the CDP sources you need the
Emscripten SDK activated, then:
npm run build:wasmA tagged release publishes automatically: push a tag like v0.3.0 and the
Publish workflow builds the WASM, tests, and publishes.
The per-effect reference under
docs/ is not
shipped in the npm tarball — read it on GitHub. The cdp CLI's own man pages
are included: man cdp.
Command line
The package ships a cdp command that runs the original CDP programs against
files on disk — invoke it exactly like the native CDP tool, just prefixed
with cdp:
cdp modify speed 2 in.wav out.wav -12
cdp pvoc anal 1 in.wav out.ana
cdp sndinfo len in.wav # read-only: prints to stdoutInstall it globally to get that bare cdp command — worth it for a tool you
run against files over and over:
npm install -g cdp-wasmOr run it without installing, which is handy for a one-off:
npx cdp-wasm sndinfo len in.wav…or, from a local checkout of this repo, symlink it onto your PATH:
npm link # then `cdp …` runs bin/cdp.jsAny argument with an audio/analysis extension (.wav .aif .aiff .ana .frq .for
.brk .txt .dat) or a / is treated as a file — existing ones are read in, files the
program writes are saved back to disk — and everything else (numbers, flags) is
passed to CDP untouched. Existing outputs are protected unless you pass --force.
Spectral programs (blur, morph, stretch, pitch, …) natively read and
write phase-vocoder .ana files. Either bracket them yourself:
cdp pvoc anal 1 in.wav in.ana
cdp blur blur in.ana out.ana 10
cdp pvoc synth out.ana out.wav…or let --pvoc analyse the WAV input and resynthesise the WAV output for you:
cdp --pvoc blur blur in.wav out.wav 10Options (before the program name): --pvoc/--spectral, -f/--force,
--in <path>, --out <path>. Helpers: cdp help <program> [mode] (native usage
plus a link to the online CDP reference; add --catalog for the catalog's named
parameters, ranges and defaults), cdp list [--spectral],
cdp doctor, cdp --version. Generated man pages ship in the package
(man cdp, and cdp-<program>.1 for the cataloged programs).
For multi-step chains from a single JSON spec, see the plugin's
render-chain.mjs;
for programmatic use, the library API below.
Agent skills and plugins
The repo ships a shared agent plugin for Codex and Claude Code containing three skills:
cdp-sound-designorchestrates and renders CDP processing through this library — multi-effect chains, breakpoint automation, analysis, batch jobs, and raw access to every bundled program.build-cdp-web-patchesbuilds and validates editable.cdpgraph files, inserts the explicit PVOC nodes cdp-web needs, and produces compressed links that open directly in cdp-web. URL-backed sound Sources travel with those links; their host must permit CORS.drive-cdp-webdrives a running cdp-web in Chrome through the app's WebMCP agent tools, using the chrome-devtools MCP as the transport — building and editing a patch live on the canvas, loading sounds, setting parameters, and rendering, instead of authoring files offline.
Codex:
codex plugin marketplace add cdp-wasm-suite/cdp-wasm
codex plugin add cdp-sound-design@cdp-wasmClaude Code:
/plugin marketplace add cdp-wasm-suite/cdp-wasm
/plugin install cdp-sound-design@cdp-wasmIt can also be installed into Codex, Claude Code, Cursor, and other compatible agents with the open Skills CLI:
npx skills add https://github.com/cdp-wasm-suite/cdp-wasm/tree/main/plugins/cdp-sound-design/skills/cdp-sound-design
npx skills add https://github.com/cdp-wasm-suite/cdp-wasm/tree/main/plugins/cdp-sound-design/skills/build-cdp-web-patches
npx skills add https://github.com/cdp-wasm-suite/cdp-wasm/tree/main/plugins/cdp-sound-design/skills/drive-cdp-webThe plugin also carries a portable
Agent Plugins 1.0.0
manifest, so any client implementing that spec can load it directly from
plugins/cdp-sound-design.
The integration ships the skills, not the library — they use whichever
cdp-wasm they find: a project-local install, a global
npm install -g cdp-wasm, or a checkout of this repo, in that order. Install
it globally if you want Claude or Codex to work on loose audio files anywhere,
not just inside a Node project.
build-cdp-web-patches can serialize Faust nodes for cdp-web, but cdp-wasm
itself does not include a Faust compiler and cannot render or verify them.
Faust patches must be compiled and auditioned in cdp-web, which supplies its
own @grame/faustwasm dependency.
See plugins/cdp-sound-design/README.md.
Quick start (Node)
import { CDP, decodeWav } from 'cdp-wasm';
const cdp = new CDP();
// Generate a 1s 440 Hz tone with CDP `synth`
const { outputs } = await cdp.run(
'synth', ['wave', '1', '/tone.wav', '44100', '1', '1.0', '440', '-a0.8'],
{ outputs: ['/tone.wav'] }
);
const tone = outputs['/tone.wav'];
// Transpose it down an octave with `modify` ($IN/$OUT are virtual paths)
const { bytes } = await cdp.process('modify', ['speed', '2', '$IN', '$OUT', '-12'], tone);
// Inspect the result
const { sampleRate, numChannels, length } = decodeWav(bytes);
console.log(sampleRate, numChannels, length);Spectral processing (analysis → transform → resynthesis)
CDP's signature spectral programs operate on phase-vocoder analysis files.
Chain them by passing the intermediate .ana bytes between runs:
const ana = await cdp.process('pvoc', ['anal', '1', '$IN', '$OUT'], wav, { outExt: 'ana' });
const blurred = await cdp.process('blur', ['blur', '$IN', '$OUT', '10'], ana.bytes, { inExt: 'ana', outExt: 'ana' });
const out = await cdp.process('pvoc', ['synth', '$IN', '$OUT'], blurred.bytes, { inExt: 'ana' });
// out.bytes is a WAVMultichannel input and mono-only programs
Many classic CDP programs are mono-only (e.g. pvoc analysis, and distort)
and reject a multichannel infile, while others (modify) handle multichannel
natively. To keep stereo/quad/8-channel width through a mono-only program, run
it per channel and recombine:
// single mono-only program: pass channels:'split' (or 'mix' to fold to mono)
const { bytes } = await cdp.process('distort', ['multiply', '$IN', '$OUT', '2'],
stereoWav, { channels: 'split' });
// a multi-step mono chain (analysis → transform → resynthesis), per channel:
const out = await cdp.eachChannel(stereoWav, async (mono) => {
const ana = await cdp.process('pvoc', ['anal', '1', '$IN', '$OUT'], mono, { outExt: 'ana' });
const blr = await cdp.process('blur', ['blur', '$IN', '$OUT', '10'], ana.bytes, { inExt: 'ana', outExt: 'ana' });
return (await cdp.process('pvoc', ['synth', '$IN', '$OUT'], blr.bytes, { inExt: 'ana' })).bytes;
});eachChannel works for any channel count and returns a recombined WAV with the
same number of channels. (Processing channels independently is correct for
per-channel effects; for stereo-correlated processing it can affect the image.)
Browser
import { CDP, wavToAudioBuffer, audioBufferToWav } from 'cdp-wasm';
const cdp = new CDP();
const ctx = new AudioContext();
// from a Web Audio AudioBuffer ...
const wavIn = audioBufferToWav(myAudioBuffer);
const { bytes } = await cdp.process('distort', ['multiply', '$IN', '$OUT', '2'], wavIn);
const processed = wavToAudioBuffer(bytes, ctx); // ... back to an AudioBuffer
const src = ctx.createBufferSource();
src.buffer = processed; src.connect(ctx.destination); src.start();For heavier jobs run the CDP instance inside a Web Worker so the UI thread
stays responsive — the API is identical.
Old engines without WASM SIMD128 (pre-16.4 Safari, aging webview hosts) are
handled automatically: the loader detects support and falls back to the
bundled no-SIMD .scalar variants of the FFT-bearing modules, a few percent
slower but otherwise identical. new CDP({ simd: false }) forces that path
if you want to test what such hosts will run.
See cdp-web for a complete, runnable browser app built on this package.
Serving the .wasm modules
new CDP() resolves the modules relative to the package itself (../wasm/),
which is right under Node and for bundlers that leave the package on disk.
Programs are looked up by name at run time, though, so a bundler that only
traces static imports will not emit them — point baseUrl at a copy you serve
instead. Copy the whole wasm/ directory: the loader needs manifest.json and
cdp-core.js/cdp-core.wasm alongside the per-program files and their
.scalar variants.
const cdp = new CDP({ baseUrl: '/wasm/' });Or host nothing at all — the published tarball is served per file by jsDelivr and unpkg, with CORS:
const cdp = new CDP({
baseUrl: 'https://cdn.jsdelivr.net/npm/[email protected]/wasm/',
});Substitute the cdp-wasm version you installed rather than a floating tag —
the loader and the modules are built and published together. Only the programs
you actually run are fetched, so the directory's total size is not a download
cost.
API
new CDP({ baseUrl?, simd? })—baseUrlpoints at the folder of.wasmmodules (defaults to this package's bundledwasm/);simd: falseforces the no-SIMD.scalarmodule variants (default: auto-detect the engine).cdp.run(program, args, { inputs?, outputs? })→{ exitCode, stdout, stderr, outputs }— full control: stage any input files, read any output files.cdp.process(program, args, inputBytes, { inExt?, outExt? })→{ bytes, stdout, stderr, exitCode }— one in, one out;$IN/$OUTinargsare replaced with virtual paths.cdp.processWav(program, args, inputWav)→ decoded float channel data plus the rawwav.EFFECTS+applyEffect(cdp, effect, values, srcWav, extra?)— the typed effect catalog and its runner (spectral wrapping, per-channel processing and two-input effects handled for you).GENERATORS+applyGenerator(cdp, gen, values, extra?)— the synthesis generators (extra.sampleRatesets the output rate,extra.datafeeds score/note text inputs).decodeAudio(WAV or AIFF, sniffed),decodeWav,decodeAiff,encodeWav,wavToAudioBuffer,audioBufferToWav— audio ↔ float/AudioBufferhelpers.
Input formats
CDP reads WAV and AIFF/AIFF-C natively, so the package accepts both
directly (decodeAudio sniffs the header; AIFF decoding covers PCM 8/16/24/32
and the sowt/fl32/fl64 AIFF-C variants). In the browser, a consuming app
typically passes WAV and AIFF straight to CDP and decodes any other container
(MP3, FLAC, Ogg…) via the Web Audio API first. CDP output is always 32-bit float WAV.
Typings are in index.d.ts.
How it works
The modules are built with -sMODULARIZE -sEXPORT_ES6 and run via callMain,
with INVOKE_RUN=0/EXIT_RUNTIME=0 so the in-memory filesystem stays readable
after the program returns. Each run() uses a fresh module instance, so there's
no shared state between invocations; the core's wasm is compiled once and
cached (a compiled WebAssembly.Module is stateless), and the shared core is
linked MAIN_MODULE=2 — dead-code-eliminated against the side modules — so
per-run instantiation costs a few milliseconds rather than tens. The loader
probes the engine's SIMD128 support once and, per the manifest's simd list,
loads either a program's SIMD build or its .scalar fallback. CDP writes
32-bit float WAVs by default, which the Web Audio API reads directly.
File size limits
The modules are 32-bit WebAssembly and stage every file in memory, so a single
run() has to hold the input, the output, and CDP's working buffers in one
linear address space — capped at 4 GB (the wasm32 limit). There is no
streaming; files are read and written whole.
In practice that ceiling is generous. A 32-bit float WAV is roughly 10 MB/min
mono (~20 MB/min stereo) at 44.1 kHz, so ~1 GB is about 100 minutes mono / 50
minutes stereo. A modify pass of ~1.5 GB in → ~1.5 GB out (~3 GB peak memory)
completes under Node; browsers are more variable (per-engine wasm memory and
ArrayBuffer caps), so keep a single file comfortably under ~1 GB and split
longer material into chunks. Spectral work (pvoc) is tighter — the analysis
file is several times larger than the source audio — so long spectral chains
reach the limit sooner.
FAQ
How does this relate to Sound Loom, Soundshaper, Soundthread and the other CDP front-ends? Only in that they all drive the same CDP programs. cdp-wasm is a new WebAssembly port of CDP — an engine, with a JS API and a CLI, no user interface. cdp-web is a graphical front-end built on that engine. Neither shares code or lineage with the existing front-ends, and neither is a replacement for them: they are separate projects that happen to sit in front of the same suite.
Do I need CDP installed, or a CDP licence? No. The compiled programs ship inside the npm package — no native CDP installation, no toolchain, nothing to buy. CDP8 itself is open source (LGPL-2.1-or-later); see License for how that applies if you redistribute the modules.
Is this all of CDP?
215 programs are bundled, which is the suite. The typed catalog gives named,
range-checked parameters for 232 effects across 110 of them plus 16 generators;
the remainder are reachable raw through cdp.run / the cdp CLI with the same
arguments as native CDP.
Does it sound the same as native CDP?
That's tested, not assumed: npm run test:parity compares WASM output against
the native command-line tools and deterministic effects match bit-for-bit.
Effects with a seeded RNG or platform-dependent edge handling are exempt and
checked for valid audio instead. See Tests.
Does it run in the browser?
Yes — the same API, with AudioBuffer in and out. See Browser.
Is this an official CDP project? No. It's an independent port. The C sources are a pinned submodule tracking a fork of upstream CDP8 that adds bug fixes and portability changes (Emscripten support among them); they build unmodified, and the changes are maintained as reviewable topic branches and proposed upstream.
License
Two licenses, split along the CDP boundary:
- The wrapper is MIT — the JavaScript API (
src/), the CLI (bin/), the type definitions, build scripts, tests and documentation are original work, licensed under the MIT License. - The CDP programs are LGPL — the compiled WebAssembly modules
(
wasm/*.wasm) and the CDP8 sources they're built from (theCDP8/submodule) are Copyright Trevor Wishart and Composers Desktop Project Ltd, licensed LGPL-2.1-or-later. Seewasm/LICENSE.
The wrapper drives the CDP programs at arm's length (argv + an in-memory
filesystem), so using this package does not make your application a derivative
of CDP — but if you redistribute the .wasm modules (including by bundling
this package), the LGPL's terms apply to them: keep the license notice, and
users must be able to swap in their own builds of the modules (they're loaded
as separate files at runtime, so this is normally already the case). The
baseUrl constructor option lets an application host the modules outside its
own bundle entirely and load them from a user-controllable location.
