A production-ready JUCE audio plugin template with config-driven setup, modular architecture, comprehensive testing, and CI/CD infrastructure.
This repo plays two roles in the DirektDSP ecosystem:
- Shared SDK — sibling plugin repos (Churn, Polygraph, …) consume
cmake/,cmake-local/, andmodules/via../PluginTemplate(sibling checkout). CI here must stay green: every plugin build depends on these files. - Scaffold source — new plugins are generated from
scaffold/(the tokenized copy-me tree) plus this repo'ssource/,tests/,benchmarks/.
python3 scripts/new_plugin.py <Name> --plugin-code <Xxxx> \
--description "..." --tagline "..."Renders a complete sibling repo into ../<Name> — sibling-checkout CMake,
house CI (lint → sanitizers → builds → pluginval/clapval → installers →
Moonbase → GitHub release), Moonbase wiring, and the
InstallerGenerator/plugins/<name>.toml manifest so the plugin is in the
central installer factory + catalog from day one. See scaffold/README.md
and the /new-plugin skill. CI runs scripts/new_plugin.py --check to keep
the scaffold render-clean.
# Clone with submodules
git clone --recursive <your-repo-url>
cd PluginTemplate
# Or if already cloned:
./scripts/setup.sh
# Build
cmake --preset debug
cmake --build build/debug
# Test
ctest --preset debugEdit project.toml to configure your plugin:
[project]
name = "MyPlugin"
product_name = "My Plugin"
company_name = "MyCompany"
bundle_id = "com.mycompany.myplugin"
manufacturer_code = "Myco"
plugin_code = "MyPl"
version = "1.0.0"
formats = ["VST3", "AU", "CLAP", "Standalone"]
[modules]
melatonin = true
clap = true
[build]
cpp_standard = 20
copy_after_build = truesource/
PluginProcessor.h/cpp — Main audio processor with APVTS, state versioning
PluginEditor.h/cpp — Resizable GUI with level meters, parameter controls
DSP/
Core/ProcessorCore.h — Template DSP scaffold (smoothing, wet/dry, bypass, metering)
Utils/ParameterSmoother.h — Exponential parameter smoothing
Utils/DSPUtils.h — dB↔gain, clipping, frequency clamping utilities
Utils/MeteringFIFO.h — Lock-free SPSC FIFO for audio→GUI metering
Service/
PresetManager.h/cpp — Category-based presets, dirty detection, menu building
common/ — Multi-plugin interfaces (IPluginProcessor, IPluginState, etc.)
tests/
PluginBasics.cpp — Smoke tests (name, buses, parameters, state)
safety/AudioSafetyTests.cpp — NaN, Inf, denormal, extreme input, buffer size tests
daw/StatePersistenceTests.cpp — State roundtrip, DAW session simulation
helpers/ — DSPTestHelpers, TestSignalGenerators, test_helpers
benchmarks/
Benchmarks.cpp — processBlock benchmarks at various block sizes
cmake-local/
Sanitizers.cmake — ASan + UBSan + TSan toggles
Packaging.cmake — Cross-platform installer generation
ModuleSystem.cmake — Conditional module loading
| Preset | Description |
|---|---|
debug |
Debug build with compile_commands.json |
release |
Optimized release build |
relwithdebinfo |
Release with debug symbols |
asan |
Debug + AddressSanitizer + UBSan |
tsan |
Debug + ThreadSanitizer |
cmake --preset asan
cmake --build build/asan
ctest --preset asanToggle in project.toml or via CMake flags:
| Module | Flag | Description |
|---|---|---|
| CLAP | ENABLE_CLAP |
CLAP plugin format support |
| Melatonin Inspector | ENABLE_MELATONIN |
Debug UI overlay |
| Moonbase | ENABLE_MOONBASE |
DRM/licensing |
| DirektDSP GUI | ENABLE_DIREKTDSP_GUI |
Config-driven GUI framework |
| Cycfi Q | ENABLE_CYCFI_Q |
DSP library for pitch detection |
| Common Layer | ENABLE_COMMON_LAYER |
Multi-plugin ecosystem interfaces |
Input → [Input Gain Smoother] → [Your DSP Chain] → [Wet/Dry Mix] → [Output Gain] → [Bypass Crossfade] → Output
↓
[Lock-free Metering FIFO]
↓
[GUI Level Meters @ 30fps]
- Parameter smoothing: Exponential smoothing with configurable time per parameter (1-5ms typical)
- Update throttling: DSP components updated every 32 samples (not per-sample)
- Bypass: Ramped crossfade (5ms) — no clicks, VST3 compliant
- Denormals:
ScopedNoDenormalsin processBlock - Metering: Lock-free SPSC FIFO, no mutexes on audio thread
- Schema versioning:
stateSchemaVersionembedded in serialized state - Migration pattern: Check version on load, run migration functions for old states
- Preset manager: Category-based file organization, dirty state detection
| Category | What it tests |
|---|---|
[plugin] |
Instance creation, bus layouts, parameter existence |
[state] |
State serialization, schema version, round-trip |
[safety] |
NaN, Inf, denormals, extreme input, buffer sizes, sample rates |
[daw] |
State persistence across instances, DAW session simulation |
[benchmark] |
processBlock performance at various configurations |
The GitHub Actions workflow runs:
- Build & Test on Linux, macOS, Windows
- Format Check via clang-format
- ASan + UBSan sanitizer build on Linux
- Artifact Upload of built plugin binaries
- Subclass
DSP::Core::ProcessorCore<float>or use it directly - Override
onPrepare(),onProcess(),onReset(),onUpdateDSPComponents() - Add parameters to
createParameterLayout()in PluginProcessor.cpp - Read parameters in
processBlock()and callupdateParameters() - Increment
stateSchemaVersionwhen changing the parameter layout
See LICENSE file.