Building audio plugins
From C++ to a signed plugin a DAW will load.
A working course in real-time audio C++, built from how the Quilio plugin line is actually made. You write a JUCE plugin, give it parameters the host can automate, an editor that never blocks the audio thread, and a test harness that proves the DSP is correct. It ends with a signed, notarised installer you can hand to someone else.
Level: Intermediate · Hours: 12 · Price: £79
What you build: You ship a feedback delay with tempo sync, saved state and a metered editor, signed and notarised as VST3, AU and a standalone app.
What you will be able to do
- Write processBlock code with a bounded worst case and know why every line in it is allowed
- Build VST3, AU and standalone targets from one CMake project
- Expose parameters the host can automate, save and restore, and version across releases
- Move data between the audio thread and the editor without a lock or an allocation
- Prove a processor correct with offline null tests and pluginval before you ship it
- Sign, notarise and package a plugin so it installs on a machine that has never seen your certificate
What you need first
- You can write and read modern C++ and you have compiled something with CMake
- You know what a sample, a buffer and a sample rate are
- You have a DAW installed and a machine running macOS or Windows
The syllabus
- The real-time thread: The audio callback is not your program. You can look at a processBlock and say which lines have an unbounded worst case, and you can prove a processor correct offline before a DAW ever loads it. (free to read)
- The real-time thread: Buffers, block sizes and sample rates. You can write DSP that gives the same output at any block size and any sample rate, and you can prove it with a sweep.
- The real-time thread: Measuring the audio thread. You can measure per-block CPU time inside your own plugin, find the worst case rather than the average, and catch an allocation on the audio thread at runtime.
- Project and formats: A JUCE project that builds with CMake. You can lay out a plugin project with juce_add_plugin, keep the DSP in a library target the tests also link, and build it from the command line on macOS and Windows.
- Project and formats: VST3, AU, AAX and standalone from one codebase. You know what each plugin format requires of you, which identifiers must never change after release, and how to get all four targets out of a single build.
- Project and formats: Bus layouts, channels and reported latency. You can declare which channel configurations your plugin supports, reject the ones it does not, and report latency so the host compensates for it correctly.
- Parameters and state: Parameters the host can automate. You can build an AudioProcessorValueTreeState layout with sensible ranges and skews, and understand how a host reads, writes and automates each parameter.
- Parameters and state: Saving and restoring state. You can serialise the full plugin state into a session and restore it exactly, including the values a host does not know about.
- Parameters and state: Presets, versioning and migrating old sessions. You can add, rename and remove parameters in a new release without breaking a session someone saved with the old one.
- Parameters and state: Gestures and automation that behaves. You can wrap every user edit in begin and end gesture calls so that automation write, latch and touch modes record what the user actually did.
- The editor: An editor that never blocks the processor. You can build an editor that reads processor state through atomics and a timer, and never holds a lock the audio thread could wait on.
- The editor: Meters and visualisers. You can push audio data to the UI through a lock-free FIFO and draw a meter with correct ballistics and peak hold without allocating in paint.
- The editor: Resizing, scaling and the host window. You can make an editor that resizes, remembers its size across sessions, and draws correctly on a HiDPI display in a host that scales its windows.
- Testing and shipping: Offline regression and null tests. You can render your DSP in a console executable, null it against committed reference audio, and run the whole suite in CI on every commit.
- Testing and shipping: pluginval and host sweeps. You can run pluginval at strictness 10, read the failures it reports, and work through the host-specific bugs that only appear in a real DAW.
- Testing and shipping: Signing, notarising and installers. You can sign and notarise a macOS plugin bundle, sign a Windows binary, and build installers that put each format where its host expects to find it.