danzig

A VST3 plugin framework written in pure Zig. No JUCE. No Steinberg SDK. No C++ at all in the core.

Source: github.com/godofecht/danzig

What danzig is

VST3 is a C ABI dressed up as COM. A plugin is a shared library exporting one symbol, GetPluginFactory. The host calls it, reads the first machine word of the returned pointer as a vtable pointer, and calls through that vtable to discover classes, create objects, and push audio buffers.

That contract is small. It is also the only part of Steinberg's SDK a plugin strictly needs. Everything else in the SDK is C++ scaffolding around it.

danzig implements the contract directly in Zig. src/vst3.zig declares the interfaces as extern structs of callconv(.c) function pointers, which is exactly what a C++ vtable is at the machine level. A plugin fills in the function pointers and returns a pointer to the struct. The host cannot tell the difference.

The reasons to do this rather than use JUCE:

Fast builds. A clean build of the library, five example binaries, and both architectures of the plugin takes about 5.6 seconds on an M-series Mac. A no-change rebuild takes 0.6 seconds, and packaging the universal bundle on top of a warm cache takes 0.5 seconds. There is no CMake step and no dependency tree.

One binary format decision, made explicitly. The bundle layout, the Info.plist, and the lipo invocation are twenty lines of build.zig you can read. Nothing is hidden behind a framework's packaging step.

Allocation is visible. Zig has no hidden allocations and no destructors that run at surprising times. On the audio thread that matters. The parameter store in src/params.zig is a fixed array of atomics with no heap involvement at all, which you can verify by reading 160 lines.

Cross-compilation is free. Zig builds x86_64-macos from an arm64 machine with no extra toolchain. That is what makes the universal bundle a build step rather than a CI matrix: build.zig compiles the plugin for both architectures and merges them with lipo, on whichever machine you happen to be on.

macOS is the only supported platform today. The VST3 bundle layout, the install-vst3 step, and the GUI example are all macOS-specific. The library, the unit tests, and the command-line examples are portable Zig and should build anywhere Zig runs, though only macOS is tested.

Current state

danzig builds a VST3 plugin that a host loads, instantiates, and validates.

Working and tested.

The plugin validates.

The factory in examples/danzig-gain is complete. getClassInfo returns a populated PClassInfo, and createInstance builds one object exposing IComponent, IAudioProcessor, and IEditController over a shared lock-free parameter store. A host scans the bundle, finds the class, and instantiates it. pluginval passes at strictness level 5:

/Applications/pluginval.app/Contents/MacOS/pluginval \
  --validate zig-out/DanzigGain.vst3 --strictness-level 5 --timeout-ms 30000
Starting tests in: pluginval / Scan for plugins located in: .../DanzigGain.vst3...
Num plugins found: 1
Testing plugin: VST3-Danzig Gain-...
Superelectric: Danzig Gain v0.1.0
...
SUCCESS

Nineteen test groups run, from instantiation and bus layouts through parameter automation and state round-trips, with no failures. So danzig loads in a DAW as a working gain plugin, and doubles as a DSP and parameter library with a validated VST3 build pipeline.