Metadata-Version: 2.3
Name: gen-dsp
Version: 0.1.3
Summary: Generate multiple dsp plugin formats from Max gen~ exports
Keywords: puredata,pd,max,msp,gen~,dsp,audio,external
Author: Michael Spears, Shakeeb Alireza
Author-email: Shakeeb Alireza <shakfu@users.noreply.github.com>
License: MIT
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Other Audience
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: MacOS
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Multimedia :: Sound/Audio
Classifier: Topic :: Software Development :: Code Generators
Requires-Python: >=3.9
Project-URL: Homepage, https://github.com/shakfu/gen-dsp
Project-URL: Repository, https://github.com/shakfu/gen-dsp
Project-URL: Changelog, https://github.com/shakfu/gen-dsp/blob/master/CHANGELOG.md
Project-URL: Issues, https://github.com/shakfu/gen-dsp/issues
Description-Content-Type: text/markdown

# gen-dsp

This project is a friendly fork of Michael Spears' [gen_ext](https://github.com/samesimilar/gen_ext) which was originally created to "compile code exported from a Max gen~ object into an "external" object that can be loaded into a PureData patch."

This fork has taken this excellent original idea and implementation and extended it to include Max/MSP externals, ChucK chugins, AudioUnit (AUv2) plugins, CLAP plugins, VST3 plugins, LV2 plugins, SuperCollider UGens, VCV Rack modules, Daisy (Electrosmith) embedded firmware, and possibly other DSP architectures (see [TODO.md](TODO.md)).

gen-dsp compiles code exported from Max gen~ objects into external objects for PureData, Max/MSP, ChucK, AudioUnit (AUv2), CLAP, VST3, LV2, SuperCollider, VCV Rack, and Daisy (Electrosmith). It automates project setup, buffer detection, and platform-specific patches.

## Key Improvements

- **Python package**: gen-dsp is a pip installable zero-dependency python package with a cli which embeds all templates and related code.

- **Automated project scaffolding**: `gen-dsp init` creates a complete, buildable project from a gen~ export in one command, versus manually copying files and editing Makefiles.

- **Automatic buffer detection**: Scans exported code for buffer usage patterns and configures them without manual intervention.

- **Max/MSP support**: Generates CMake-based Max externals with proper 64-bit signal handling and buffer lock/unlock API.

- **ChucK support**: Generates chugins (.chug) with multi-channel I/O and runtime parameter control.

- **AudioUnit support**: Generates macOS AUv2 plugins (.component) using the raw C API -- no Apple SDK dependency, just system frameworks.

- **CLAP support**: Generates cross-platform CLAP plugins (`.clap`) with zero-copy audio processing -- CLAP headers fetched via CMake FetchContent.

- **VST3 support**: Generates cross-platform VST3 plugins (`.vst3`) with zero-copy audio processing -- Steinberg VST3 SDK fetched via CMake FetchContent.

- **LV2 support**: Generates cross-platform LV2 plugins (`.lv2` bundles) with TTL metadata containing real parameter names/ranges parsed from gen~ exports -- LV2 headers fetched via CMake FetchContent.

- **SuperCollider support**: Generates cross-platform SC UGens (`.scx`/`.so`) with `.sc` class files containing parameter names/defaults parsed from gen~ exports -- SC plugin headers fetched via CMake FetchContent.

- **VCV Rack support**: Generates VCV Rack modules with per-sample processing, auto-generated `plugin.json` manifest and panel SVG -- requires pre-installed Rack SDK.

- **Daisy support**: Generates Daisy Seed firmware (.bin) with custom genlib runtime (bump allocator for SRAM/SDRAM) -- first embedded/cross-compilation target, requires `arm-none-eabi-gcc`.

- **Platform-specific patches**: Automatically fixes compatibility issues like the `exp2f -> exp2` problem in Max 9 exports on macOS.

- **Analysis tools**: `gen-dsp detect` inspects exports to show I/O counts, parameters, and buffers before committing to a build.

- **Dry-run mode**: Preview what changes will be made before applying them.

- **Platform registry**: To make it easy to discover new backends

## Installation

```bash
pip install gen-dsp
```

Or install from source:

```bash
git clone https://github.com/shakfu/gen-dsp.git
cd gen-dsp
pip install -e .
```

## Quick Start

```bash
# 1. Export your gen~ code in Max (send 'exportcode' to gen~ object)

# 2. Create a project from the export
gen-dsp init ./path/to/export -n myeffect -o ./myeffect

# 3. Build the external
cd myeffect
make all

# 4. Use in PureData as myeffect~
```

## Commands

### init

Create a new project from a gen~ export:

```bash
gen-dsp init <export-path> -n <name> [-p <platform>] [-o <output>]
```

Options:

- `-n, --name` - Name for the external (required)
- `-p, --platform` - Target platform: `pd` (default), `max`, `chuck`, `au`, `clap`, `vst3`, `lv2`, `sc`, `vcvrack`, `daisy`, or `both`
- `-o, --output` - Output directory (default: `./<name>`)
- `--buffers` - Explicit buffer names (overrides auto-detection)
- `--shared-cache` - Use a shared OS cache for FetchContent downloads (clap, vst3, lv2, sc only)
- `--no-patch` - Skip automatic exp2f fix
- `--dry-run` - Preview without creating files

### build

Build an existing project:

```bash
gen-dsp build [project-path] [-p <platform>] [--clean] [-v]
```

### detect

Analyze a gen~ export:

```bash
gen-dsp detect <export-path> [--json]
```

Shows: export name, signal I/O counts, parameters, detected buffers, and needed patches.

### patch

Apply platform-specific fixes:

```bash
gen-dsp patch <target-path> [--dry-run]
```

Currently applies the exp2f -> exp2 fix for macOS compatibility with Max 9 exports.

## Features

### Automatic Buffer Detection

gen-dsp scans your gen~ export for buffer usage patterns and configures them automatically:

```bash
$ gen-dsp detect ./my_sampler_export
Gen~ Export: my_sampler
  Signal inputs: 1
  Signal outputs: 2
  Parameters: 3
  Buffers: ['sample', 'envelope']
```

Buffer names must be valid C identifiers (alphanumeric, starting with a letter).

### Platform Patches

Max 9 exports include `exp2f` which fails on macOS. gen-dsp automatically patches this to `exp2` during project creation, or you can apply it manually:

```bash
gen-dsp patch ./my_project --dry-run  # Preview
gen-dsp patch ./my_project            # Apply
```

## Using the External in PureData

### Parameters

Send `<parameter-name> <value>` messages to the first inlet:

```text
[frequency 440(
|
[mysynth~]
```

Send `bang` to print all available parameters.

### Buffers

Buffers connect to PureData arrays with matching names. To remap a buffer to a different array:

```text
[pdset original_buffer new_array(
|
[mysampler~]
```

### Sample Rate and Block Size

For subpatches with custom block sizes (e.g., spectral processing):

```text
[pdsr 96000(  <- Set sample rate
[pdbs 2048(   <- Set block size
|
[myspectral~]
```

## Max/MSP Support

gen-dsp supports generating Max/MSP externals using CMake and the max-sdk-base submodule.

### Quick Start (Max)

```bash
# Create a Max project
gen-dsp init ./my_export -n myeffect -p max -o ./myeffect_max

# Build (automatically clones max-sdk-base if needed)
gen-dsp build ./myeffect_max -p max

# Output: myeffect_max/externals/myeffect~.mxo (macOS) or myeffect~.mxe64 (Windows)
```

Or build manually:

```bash
cd myeffect_max
git clone --depth 1 https://github.com/Cycling74/max-sdk-base.git
mkdir -p build && cd build
cmake .. && cmake --build .
```

## ChucK Support

gen-dsp supports generating ChucK chugins (.chug files) using make and a bundled `chugin.h` header.

### Quick Start (ChucK)

```bash
# Create a ChucK project
gen-dsp init ./my_export -n myeffect -p chuck -o ./myeffect_chuck

# Build
cd myeffect_chuck
make mac    # macOS
make linux  # Linux

# Use in ChucK
# @import "Myeffect"
# Myeffect eff => dac;
```

### ChucK API

The generated chugin extends `UGen` and provides:

```chuck
// Import and instantiate (connects as UGen)
@import "Myeffect"
Myeffect eff => dac;

// Set a parameter by name
eff.param("frequency", 440.0);

// Get a parameter by name
eff.param("frequency") => float freq;

// Query parameters
eff.numParams() => int n;
eff.paramName(0) => string name;

// Print info (parameters, I/O, buffers)
eff.info();

// Reset internal state
eff.reset();
```

### Key Differences from PureData

| Aspect | ChucK | PureData |
|--------|-------|----------|
| Signal type | float (32-bit) | float (32-bit) |
| Build system | make (chugin pattern) | make (pd-lib-builder) |
| Output format | .chug | .pd_darwin / .pd_linux |
| Parameter access | `param(string, float)` | message to first inlet |
| Multi-channel | `CK_DLL_TICKF` (interleaved) | per-signal inlets/outlets |

## AudioUnit (AUv2) Support

gen-dsp supports generating macOS AudioUnit v2 plugins (.component bundles) using CMake and the raw AUv2 C API. No Apple AudioUnitSDK is needed -- only system frameworks (AudioToolbox, CoreFoundation, CoreAudio).

### Quick Start (AudioUnit)

```bash
# Create an AudioUnit project
gen-dsp init ./my_export -n myeffect -p au -o ./myeffect_au

# Build
cd myeffect_au
mkdir -p build && cd build
cmake .. && cmake --build .

# Output: build/myeffect.component

# Install (optional)
cp -r myeffect.component ~/Library/Audio/Plug-Ins/Components/
```

The plugin is automatically detected as an effect (`aufx`) if the gen~ export has inputs, or a generator (`augn`) if it has no inputs. The .component bundle is ad-hoc code signed during build.

### AU Plugin Details

- **Component type**: `aufx` (effect) or `augn` (generator), auto-detected from I/O
- **Subtype**: first 4 characters of the library name (lowercased)
- **Manufacturer**: `gdsp`
- **Parameters**: all gen~ parameters are exposed as AU parameters with name, min, max
- **Audio format**: Float32, non-interleaved (standard AU format)

## CLAP Support

gen-dsp supports generating cross-platform CLAP plugins (.clap files) using CMake and the CLAP C API (header-only, MIT licensed). CLAP headers are fetched automatically at configure time via CMake FetchContent.

### Quick Start (CLAP)

```bash
# Create a CLAP project
gen-dsp init ./my_export -n myeffect -p clap -o ./myeffect_clap

# Build
cd myeffect_clap
mkdir -p build && cd build
cmake .. && cmake --build .

# Output: build/myeffect.clap

# Install (optional)
# macOS:
cp myeffect.clap ~/Library/Audio/Plug-Ins/CLAP/
# Linux:
cp myeffect.clap ~/.clap/
```

The plugin is automatically detected as an audio effect if the gen~ export has inputs, or an instrument if it has no inputs. On macOS, the .clap file is ad-hoc code signed during build.

### CLAP Plugin Details

- **Plugin type**: `audio_effect` or `instrument`, auto-detected from I/O
- **Plugin ID**: `com.gen-dsp.<lib_name>`
- **Parameters**: all gen~ parameters exposed via the CLAP params extension (automatable)
- **Audio format**: Float32, non-interleaved (zero-copy -- CLAP's `data32` layout matches gen~'s `float**` exactly)
- **Cross-platform**: macOS and Linux (unlike AudioUnit)
- **Extensions**: `audio-ports`, `params`

## VST3 Support

gen-dsp supports generating cross-platform VST3 plugins (.vst3 bundles) using CMake and the Steinberg VST3 SDK. The SDK is fetched automatically at configure time via CMake FetchContent.

### Quick Start (VST3)

```bash
# Create a VST3 project
gen-dsp init ./my_export -n myeffect -p vst3 -o ./myeffect_vst3

# Build
cd myeffect_vst3
mkdir -p build && cd build
cmake .. && cmake --build .

# Output: build/VST3/Release/myeffect.vst3/

# Install (optional)
# macOS:
cp -r VST3/Release/myeffect.vst3 ~/Library/Audio/Plug-Ins/VST3/
# Linux:
cp -r VST3/Release/myeffect.vst3 ~/.vst3/
```

The plugin is automatically detected as an effect (`Fx`) if the gen~ export has inputs, or an instrument (`Instrument|Synth`) if it has no inputs. On macOS, the .vst3 bundle is ad-hoc code signed during build.

### VST3 Plugin Details

- **Plugin type**: `Fx` or `Instrument|Synth`, auto-detected from I/O
- **Plugin FUID**: deterministic 128-bit ID from MD5 of `com.gen-dsp.vst3.<lib_name>`
- **Parameters**: all gen~ parameters exposed as `RangeParameter` with real min/max/default (automatable)
- **Audio format**: Float32, non-interleaved (zero-copy -- VST3's `channelBuffers32` layout matches gen~'s `float**` exactly)
- **Cross-platform**: macOS, Linux, and Windows
- **SDK**: `SingleComponentEffect` (combined processor+controller) -- simplest VST3 plugin structure
- **License**: VST3 SDK is GPL3/proprietary dual licensed -- users needing a proprietary license must obtain one from Steinberg

## LV2 Support

gen-dsp supports generating cross-platform LV2 plugins (.lv2 bundle directories) using CMake and the LV2 C API (header-only, ISC licensed). LV2 headers are fetched automatically at configure time via CMake FetchContent.

### Quick Start (LV2)

```bash
# Create an LV2 project
gen-dsp init ./my_export -n myeffect -p lv2 -o ./myeffect_lv2

# Build
cd myeffect_lv2
mkdir -p build && cd build
cmake .. && cmake --build .

# Output: build/myeffect.lv2/

# Install (optional)
# macOS:
cp -r myeffect.lv2 ~/Library/Audio/Plug-Ins/LV2/
# Linux:
cp -r myeffect.lv2 ~/.lv2/
```

The plugin is automatically detected as an effect (`EffectPlugin`) if the gen~ export has inputs, or a generator (`GeneratorPlugin`) if it has no inputs. On macOS, the binary is ad-hoc code signed during build.

### LV2 Plugin Details

- **Plugin type**: `EffectPlugin` or `GeneratorPlugin`, auto-detected from I/O
- **Plugin URI**: `http://gen-dsp.com/plugins/<lib_name>`
- **Parameters**: all gen~ parameters exposed as LV2 control ports with real names and ranges parsed from the gen~ export
- **Audio format**: Float32, port-based (individual `float*` per audio channel, collected into arrays for `wrapper_perform()`)
- **Cross-platform**: macOS and Linux
- **TTL metadata**: `manifest.ttl` (discovery) and `<name>.ttl` (ports, parameters) generated at project creation time
- **Bundle output**: `.lv2` directory containing shared library + 2 TTL files

## SuperCollider Support

gen-dsp supports generating cross-platform SuperCollider UGens (.scx on macOS, .so on Linux) using CMake and the SC plugin interface headers. SC headers are fetched automatically at configure time via CMake FetchContent.

### Quick Start (SuperCollider)

```bash
# Create a SuperCollider project
gen-dsp init ./my_export -n myeffect -p sc -o ./myeffect_sc

# Build
cd myeffect_sc
mkdir -p build && cd build
cmake .. && cmake --build .

# Output: build/myeffect.scx (macOS) or build/myeffect.so (Linux)

# Install (copy both the binary and the .sc class file)
# macOS:
cp myeffect.scx ~/Library/Application\ Support/SuperCollider/Extensions/
cp ../Myeffect.sc ~/Library/Application\ Support/SuperCollider/Extensions/
# Linux:
cp myeffect.so ~/.local/share/SuperCollider/Extensions/
cp ../Myeffect.sc ~/.local/share/SuperCollider/Extensions/
```

The plugin is automatically detected as an effect if the gen~ export has inputs, or a generator if it has no inputs. On macOS, the binary is ad-hoc code signed during build.

### SC UGen Details

- **UGen name**: lib_name with first letter capitalized (e.g., `gigaverb` -> `Gigaverb`) -- SC class names must start uppercase
- **Input layout**: audio inputs first (0..N-1), then parameters (N..N+P-1) at control rate
- **Parameters**: all gen~ parameters exposed as SC UGen inputs with real names and defaults parsed from the gen~ export
- **Audio format**: Float32, block-based (zero-copy -- SC's `IN()`/`OUT()` buffers passed directly to gen~'s `float**`)
- **Cross-platform**: macOS and Linux
- **Class file**: `.sc` file generated at project creation time; extends `MultiOutUGen` (multi-output) or `UGen` (single output)

### Using in SuperCollider

```supercollider
// Boot the server, then use the UGen
s.boot;

// Effect (has audio inputs)
{ Gigaverb.ar(SoundIn.ar([0, 1]), revtime: 0.8, damping: 0.5) }.play;

// Generator (no audio inputs)
{ MyOsc.ar(freq: 440, amp: 0.3) }.play;
```

## VCV Rack Support

gen-dsp supports generating VCV Rack modules using the Rack SDK's Makefile-based build system. The VCV Rack SDK must be pre-installed and `RACK_DIR` must point to it.

### Quick Start (VCV Rack)

```bash
# Create a VCV Rack project
gen-dsp init ./my_export -n myeffect -p vcvrack -o ./myeffect_vcvrack

# Build (requires RACK_DIR to point to Rack SDK)
cd myeffect_vcvrack
export RACK_DIR=/path/to/Rack-SDK
make

# Output: plugin.dylib (macOS), plugin.so (Linux), or plugin.dll (Windows)

# Install: copy entire plugin directory to VCV Rack plugins folder
# macOS: ~/Documents/Rack2/plugins/
# Linux: ~/.Rack2/plugins/
```

The module is automatically detected as an effect (`Effect` tag) if the gen~ export has inputs, or a generator (`Synth Voice` tag) if it has no inputs.

### VCV Rack Module Details

- **Processing**: Per-sample via `perform(n=1)` -- zero latency, called once per sample from VCV Rack's `process()`
- **Voltage scaling**: gen~ audio [-1, 1] mapped to VCV standard +/-5V; parameters map directly (gen~ min/max = knob min/max)
- **Parameters**: all gen~ parameters exposed as knobs with real names and ranges queried at construction time
- **Panel**: auto-generated dark SVG panel sized to component count (6/10/16/24 HP)
- **Auto-layout**: screws at corners, knobs for params, input/output ports arranged in columns
- **Manifest**: `plugin.json` generated with module slug, tags, and brand info
- **Cross-platform**: macOS, Linux, and Windows
- **Plugin ID**: slug matches lib_name

## Daisy (Electrosmith) Support

gen-dsp supports generating firmware for the Daisy Seed, an STM32H750-based embedded audio platform popular for Eurorack modules and DIY hardware. This is gen-dsp's first cross-compilation target -- it requires `arm-none-eabi-gcc` and produces firmware binaries (.bin) for DFU flashing.

### Quick Start (Daisy)

```bash
# Create a Daisy project
gen-dsp init ./my_export -n myeffect -p daisy -o ./myeffect_daisy

# Build (auto-clones libDaisy on first run; requires arm-none-eabi-gcc)
gen-dsp build ./myeffect_daisy -p daisy

# Output: build/myeffect.bin

# Flash via DFU (put Daisy in bootloader mode first)
# Using dfu-util:
dfu-util -a 0 -s 0x08000000:leave -D build/myeffect.bin
```

### Daisy Details

- **Target**: Daisy Seed (v1) -- 2in/2out stereo audio, no built-in controls
- **Compiler**: `arm-none-eabi-gcc` (ARM cross-compilation)
- **Output**: firmware `.bin` for DFU flashing
- **Audio format**: Float32, non-interleaved (libDaisy's callback matches gen~'s `float**` directly)
- **Memory**: custom genlib runtime with two-tier bump allocator (SRAM ~450KB + SDRAM 64MB)
- **Parameters**: retain gen~ defaults; modify `gen_ext_daisy.cpp` to add ADC reads for knobs/CV
- **SDK**: libDaisy auto-cloned and built on first use (pinned to v7.1.0)
- **SDK resolution**: `LIBDAISY_DIR` env var > `GEN_DSP_CACHE_DIR` env var > OS cache path
- **Channel mapping**: `min(gen_channels, 2)` mapped to hardware; extra gen~ I/O uses scratch buffers
- **Board targets**: Pod, Patch, Field, Petal, Versio can be added in future versions

### Platform Comparison

| Aspect | LV2 | VST3 | CLAP | SC | VCV Rack | Daisy | AudioUnit | ChucK | PureData | Max/MSP |
|--------|-----|------|------|----|----------|-------|-----------|-------|----------|---------|
| Signal type | float (32-bit) | float (32-bit) | float (32-bit) | float (32-bit) | float (32-bit) | float (32-bit) | float (32-bit) | float (32-bit) | float (32-bit) | double (64-bit) |
| Build system | CMake (FetchContent) | CMake (FetchContent) | CMake (FetchContent) | CMake (FetchContent) | make (Rack SDK) | make (libDaisy) | CMake | make | make (pd-lib-builder) | CMake (max-sdk-base) |
| Output format | .lv2 | .vst3 | .clap | .scx / .so | plugin.dylib / .so | .bin (firmware) | .component | .chug | .pd_darwin / .pd_linux | .mxo / .mxe64 |
| macOS only | no | no | no | no | no | no | yes | no | no | no |
| External deps | LV2 headers (fetched) | VST3 SDK (fetched) | CLAP headers (fetched) | SC headers (fetched) | Rack SDK (pre-installed) | libDaisy (auto-cloned) | none (system frameworks) | none (bundled chugin.h) | PureData headers | max-sdk-base (git) |

### PureData vs Max/MSP

| Aspect | PureData | Max/MSP |
|--------|----------|---------|
| Signal type | float (32-bit) | double (64-bit) |
| Buffer storage | float (32-bit) | float (32-bit) |
| Build system | make (pd-lib-builder) | CMake (max-sdk-base) |
| Buffer access | Direct array | Lock/unlock API |
| Output format | .pd_darwin / .pd_linux | .mxo / .mxe64 |

For PureData, gen~ is compiled with 32-bit float signals. For Max, gen~ uses native 64-bit double signals, with automatic float conversion for buffer access (Max buffers are always 32-bit).

## Shared FetchContent Cache

CLAP, VST3, LV2, and SC backends use CMake FetchContent to download their SDKs/headers at configure time. By default each project downloads its own copy. Two opt-in mechanisms allow sharing a single download across projects:

### `--shared-cache` flag

Pass `--shared-cache` to `gen-dsp init` to bake an OS-appropriate cache path into the generated CMakeLists.txt:

```bash
gen-dsp init ./my_export -n myeffect -p vst3 --shared-cache
```

This resolves to:

| OS | Cache path |
|----|------------|
| macOS | `~/Library/Caches/gen-dsp/fetchcontent/` |
| Linux | `$XDG_CACHE_HOME/gen-dsp/fetchcontent/` (defaults to `~/.cache/`) |
| Windows | `%LOCALAPPDATA%/gen-dsp/fetchcontent/` |

### `GEN_DSP_CACHE_DIR` environment variable

Set this at cmake configure time to override any baked-in path (or use it without `--shared-cache`):

```bash
GEN_DSP_CACHE_DIR=/path/to/cache cmake ..
```

The env var takes highest priority, followed by the `--shared-cache` path, followed by CMake's default (project-local `build/_deps/`).

The development Makefile exports `GEN_DSP_CACHE_DIR=build/.fetchcontent_cache` automatically, so `make example-clap`, `make example-vst3`, `make example-lv2`, and `make example-sc` share the same SDK cache used by tests.

## Limitations

- Maximum of 5 buffers per external
- Buffers are single-channel only. Use multiple buffers for multi-channel audio.
- Max/MSP: Windows builds require Visual Studio or equivalent MSVC toolchain
- AudioUnit: macOS only; initial implementation may not pass all `auval` checks
- CLAP: first CMake configure requires network access to fetch CLAP headers (cached afterward)
- VST3: first CMake configure requires network access to fetch VST3 SDK (~50MB, cached afterward); GPL3/proprietary dual license
- LV2: first CMake configure requires network access to fetch LV2 headers (cached afterward)
- SuperCollider: first CMake configure requires network access to fetch SC headers (~80MB tarball, cached afterward)
- VCV Rack: requires pre-installed Rack SDK (`RACK_DIR` env var); per-sample `perform(n=1)` has higher CPU overhead than block-based processing
- Daisy: requires `arm-none-eabi-gcc` cross-compiler; first clone of libDaisy requires network access and `git`; v1 targets Daisy Seed only (no board-specific knob/CV mapping)

## Requirements

### Runtime

- Python >= 3.9
- C/C++ compiler (gcc, clang)

### PureData builds

- make
- PureData headers (typically installed with PureData)

### Max/MSP builds

- CMake >= 3.19
- git (for cloning max-sdk-base)

### ChucK builds

- make
- C/C++ compiler (clang on macOS, gcc on Linux)
- ChucK (for running the chugin)

### AudioUnit builds

- macOS (AudioUnit is macOS-only)
- CMake >= 3.19
- C/C++ compiler (clang via Xcode or Command Line Tools)

### CLAP builds

- CMake >= 3.19
- C/C++ compiler (clang, gcc)
- Network access on first configure (to fetch CLAP headers)

### VST3 builds

- CMake >= 3.19
- C/C++ compiler (clang, gcc, MSVC)
- Network access on first configure (to fetch VST3 SDK, ~50MB)

### LV2 builds

- CMake >= 3.19
- C/C++ compiler (clang, gcc)
- Network access on first configure (to fetch LV2 headers)

### SuperCollider builds

- CMake >= 3.19
- C/C++ compiler (clang, gcc)
- Network access on first configure (to fetch SC plugin headers)

### VCV Rack builds

- make
- C/C++ compiler (clang, gcc)
- VCV Rack SDK (`RACK_DIR` environment variable must point to SDK path)

### Daisy builds

- make
- `arm-none-eabi-gcc` (ARM GCC toolchain for cross-compilation)
- git (for cloning libDaisy on first build)
- Network access on first build (to clone libDaisy + submodules)

### macOS

Install Xcode or Command Line Tools:

```bash
xcode-select --install
```

### Linux / Organelle

Standard build tools (gcc, make) are typically pre-installed.

## Cross-Compilation Note

Build artifacts are platform-specific. When moving projects between macOS and Linux/Organelle:

```bash
make clean
make all
```

## Development

```bash
git clone https://github.com/samesimilar/gen-dsp.git
cd gen-dsp
uv venv && uv pip install -e ".[dev]"
source .venv/bin/activate
make test
```

### Building Example Plugins

The Makefile includes targets for generating and building example plugins from the test fixtures:

```bash
make example-pd       # PureData external
make example-max      # Max/MSP external
make example-chuck    # ChucK chugin
make example-au       # AudioUnit plugin (macOS only)
make example-clap     # CLAP plugin
make example-vst3     # VST3 plugin
make example-lv2      # LV2 plugin
make example-sc       # SuperCollider UGen
make example-vcvrack  # VCV Rack module (requires RACK_DIR)
make example-daisy    # Daisy firmware (requires arm-none-eabi-gcc)
make examples         # All platforms
```

Override the fixture, name, or buffers:

```bash
make example-chuck FIXTURE=RamplePlayer NAME=rampleplayer BUFFERS="--buffers sample"
```

Available fixtures: `gigaverb` (default, no buffers), `RamplePlayer` (has buffers), `spectraldelayfb`.

Output goes to `build/examples/`.

### Adding New Backends

gen-dsp uses a platform registry system that makes it straightforward to add support for new audio platforms (VCV Rack, Bela, Daisy, etc.). See [NEW_BACKENDS.md](NEW_BACKENDS.md) for a complete guide.

## Attribution

Test fixtures include code exported from examples bundled with Max:

- gigaverb: ported from Juhana Sadeharju's implementation
- spectraldelayfb: from gen~.spectraldelay_feedback

## License

MIT License. See [LICENSE](LICENSE) for details.

Note: Generated gen~ code is subject to Cycling '74's license terms.
