v1.6.1 — 90+ headers of professional audio DSP: filters, dynamics, reverbs, physically-modeled analog (tape, tube, transformer), pitch, spectral tools, EBU-verified metering. One #include, the same code on every target — desktop apps, WebAssembly, mobile, embedded, offline tools, and native VST3/CLAP/AU plugins (effects and MIDI instruments) with HTML/CSS/JS editors.
📖 Full API documentation: cristianmoresi.github.io/DSPark
CI runs a 630-case test suite and the public conformance suite on every commit across Windows (MSVC, x64 and ARM64), Linux (GCC + Clang, x64 and ARM64), macOS (ARM64) and WebAssembly (Emscripten), plus AddressSanitizer/UBSan, an exceptions-free embedded profile and a single-header amalgamation. Loudness is validated against the official EBU R128 test vectors, and a per-processor quality metrics table (THD+N, noise floor, spurious/aliasing, latency) is generated from the measurements.
#include "DSPark/DSPark.h"
dspark::Equalizer<float> eq;
dspark::Compressor<float> comp;
dspark::AlgorithmicReverb<float> reverb;
eq.prepare(spec);
comp.prepare(spec);
reverb.prepare(spec);
eq.setBand(0, 100.0f, 3.0f); // Boost bass
comp.setThreshold(-18.0f); // Compress
comp.setCharacter(dspark::Compressor<float>::Character::FET); // 1176-style
reverb.setType(dspark::AlgorithmicReverb<float>::Type::Hall); // Concert hall
eq.processBlock(buffer);
comp.processBlock(buffer);
reverb.processBlock(buffer);No build system. No linking. No configuration. Just include and go.
Most audio DSP libraries fall into two categories: either they require a massive framework dependency, or they cover only a narrow slice of what you need. Nothing gives you everything in a single, portable, dependency-free package.
DSPark was built to change that. Whether you are:
- A software developer adding audio features to an app (zero DSP knowledge required)
- A mixing engineer or sound technician building custom plugins and tools
- A DSP engineer designing professional audio processors or embedded systems
You get the same framework, the same headers, the same API. The difference is how deep you go.
Every processor exposes three levels of complexity:
// Level 1 — Just works:
eq.setBand(0, 1000.0f, -3.0f);
// Level 2 — More control:
eq.setBand(0, 1000.0f, -3.0f, 1.5f); // Adds Q factor
// Level 3 — Full control:
eq.setBand(0, { .frequency = 1000, .gain = -3, .q = 1.5,
.type = BandType::LowShelf, .slope = 24 });You never see complexity you don't need. But it's always there when you do.
Effect classes expose protected internals so you can subclass them directly to reach the delay lines, filters and early reflections inside. They are deliberately leaf classes with non-virtual destructors — honouring the zero-virtual-dispatch design — so you extend by direct inheritance and composition rather than polymorphic base-pointer deletion:
class MyReverb : public dspark::AlgorithmicReverb<float> {
// Access FDN delay lines, absorption filters, early reflections...
// Add custom processing stages, expose your own presets
};| Class | Description |
|---|---|
Equalizer<T> |
Multi-band parametric EQ with linear-phase (FFT) and IIR modes |
Compressor<T> |
Modular: 5 detectors (Peak, RMS, TruePeak, SplitPolarity, Hilbert), 2 topologies (FF/FB), 4 characters (Clean/Opto/FET/Varimu), upward/downward modes. Hold and range controls, adaptive auto-makeup gain, external sidechain. |
Limiter<T> |
ISP true-peak brickwall limiter with adaptive release |
NoiseGate<T> |
State machine with hysteresis, hold time, duck mode. External sidechain. |
Expander<T> |
Downward expander with threshold, ratio, hold, range |
DynamicEQ<T> |
Frequency-selective dynamics (above/below threshold, dual-action) |
MultibandCompressor<T> |
Crossover + per-band Compressor, configurable up to 12 bands (compile-time MaxBands) |
TransientDesigner<T> |
Attack/sustain shaping via envelope following |
DeEsser<T> |
Frequency-targeted dynamic reduction for sibilance |
AlgorithmicReverb<T> |
16-line FDN with Jot (1991) frequency-dependent absorption, Householder feedback mixing, Lexicon-style smooth random + noise modulation, serial allpass per line (Infinity2-style), feedback IIR smoothing (Verbity), allpass-interpolated modulated reads, tanh soft saturation, parallel allpass input diffuser (256 echo paths), Dattorro multi-tap output, output diffusion, M/S stereo width control, progressive ER absorption. 6 presets: Room, Hall, Chamber, Plate, Spring, Cathedral. Full parameter API for custom reverb design. |
Reverb<T> |
Convolution reverb with IR loading, pre-delay, auto-resample |
Saturation<T> |
10 algorithms (Tube, Tape, Transformer, SoftClip, HardClip, Exciter, Wavefolder, Bitcrusher, Downsample, MultiStage). Adaptive blend, slew-dependent saturation, oversampling. |
Clipper<T> |
4-mode clipper (Hard/Soft/Analog/GoldenRatio), multi-stage, slew limiter, up to 16x oversampling |
FilterEngine<T> |
Cascaded biquads, 9 shapes, 6–48 dB/oct slopes |
CrossoverFilter<T> |
Linkwitz-Riley crossover (LR12/24/48), IIR + linear-phase modes |
Chorus<T> |
Multi-voice LFO delay, stereo spread, flanger mode |
Phaser<T> |
Allpass chain with LFO modulation, configurable stages, stereo LFO spread |
Tremolo<T> |
Amplitude modulation with configurable LFO |
Vibrato<T> |
Pitch modulation via modulated delay |
RingModulator<T> |
Ring modulation with carrier oscillator |
FrequencyShifter<T> |
Single-sideband frequency shift via Hilbert transform |
Delay<T> |
Interpolated delay with feedback (clean or analog tanh regeneration), ping-pong, filters |
Panner<T> |
6 algorithms: equal-power, binaural (ITD), mid-pan, side-pan, Haas, spectral |
Gain<T> |
Smoothed gain with fade, mute, polarity inversion |
AutoGain<T> |
Automatic gain compensation based on loudness measurement |
Crossfade<T> |
Linear, equal-power, S-curve |
StereoWidth<T> |
M/S width control with bass-mono option |
MidSide<T> |
Stereo Mid/Side encoding and decoding |
NoiseGenerator<T> |
White, pink, and brown noise generation |
DCBlocker<T> |
DC offset removal (1-pole or Butterworth order 2–10) |
TapeMachine<T> |
Physical tape model: Jiles-Atherton hysteresis at 2x oversampling, NAB/CCIR record/play EQ with exact digital inverses, speed-dependent head-gap/spacing/thickness loss, head bump, common-transport wow & flutter |
TubePreamp<T> |
Koren triode stages (12AX7) solved per sample with Newton-Raphson, exact Fender FMV tone stack as a Wave Digital R-type network, power-supply sag |
TransformerModel<T> |
Audio transformer coloration: flux-domain Jiles-Atherton core (distortion rises as frequency falls — the LF "bloom"), magnetizing-inductance corner, HF resonance bell |
PitchShifter<T> |
Phase vocoder with identity phase locking (Laroche-Dolson), exact tuning, transient phase reset, formant preservation (cepstral lift), stereo-coherent |
GranularProcessor<T> |
64-grain clouds over live input: per-grain pitch/pan/jitter, freeze, equal-power spread |
SpectralDenoiser<T> |
Learnable-noise-profile spectral gating with the standard musical-noise defenses |
| Class | Description |
|---|---|
StateVariableFilter<T> |
TPT SVF: 8 modes (LP/HP/BP/Notch/AP/Bell/LowShelf/HighShelf), simultaneous multi-output |
LadderFilter<T> |
Moog-style 4-pole TPT filter, 6 modes, drive, self-oscillation |
Biquad<T> |
TDF-II biquad with 9 coefficient types and lock-free auto-promote of staged coefficients; the filter core is double whatever T is, so a corner far below the sample rate keeps its poles where they were designed |
BiquadCoeffs |
Standalone factory for biquad coefficients (LP, HP, BP, Peak, Shelf, Notch, AP, Tilt), always double |
FFTComplex<T> / FFTReal<T> |
Radix-2 FFT with SIMD (SSE3/NEON), real-optimised |
Convolver<T> |
Partitioned overlap-save FFT convolution |
ZeroLatencyConvolver<T> |
Gardner non-uniform partitioning: zero-latency convolution with time-distributed tail FFTs (flat CPU even for second-long IRs) |
wdf::* (WDF.h) |
Wave Digital Filter circuit toolkit: R/L/C leaves, series/parallel adaptors, Newton-Raphson diode roots with analytic seeds, and an R-type adaptor (MNA-derived scattering) for non-adaptable topologies |
Hysteresis<T> |
Jiles-Atherton magnetic hysteresis with implicit trapezoidal Newton-Raphson solver (tape, transformers) |
ModulationRouter<T> |
Block-rate modulation routing: any source callable to any parameter setter, with depth and smoothing |
StateWriter/StateReader |
Versioned key/value preset blobs + JSON helpers — every effect implements getState()/setState() |
FIRFilter<T> |
FIR engine with windowed-sinc design |
Oversampling<T> |
2x–16x polyphase half-band Kaiser filters (-80 dB+ rejection), transparent up/down round-trip, exact reported latency |
Oscillator<T> |
PolyBLEP (sine, saw, square, triangle) |
WavetableOscillator<T> |
Mipmapped wavetable with bandlimited harmonics |
Resampler<T> |
Polyphase windowed-sinc sample-rate conversion |
EnvelopeGenerator<T> (ADSREnvelope) |
ADSR with exponential curves |
RingBuffer<T> |
Power-of-two circular buffer with interpolated read |
SmoothedValue<T> |
Parameter smoother (exponential, linear, chase, or disabled) |
Smoothers |
9 smoothing algorithms (linear, exponential, one-pole, asymmetric, slew, SVF, Butterworth…) |
ProcessorChain<T,...> |
Zero-overhead compile-time processor chain with per-slot bypass |
SpectralProcessor<T> |
STFT-based analysis-modification-synthesis framework |
Dither<T> |
TPDF dithering with noise shaping |
DenormalGuard |
RAII FTZ/DAZ (x86 SSE, ARM, WebAssembly) |
Interpolation |
5 methods (linear, cubic, Hermite, Lagrange, allpass) |
Hilbert<T> |
FIR (windowed-sinc) Hilbert transform for analytic signals — flat magnitude across the audible band |
WindowFunctions<T> |
8 windows (Hann, Hamming, Blackman, Kaiser…) |
DryWetMixer<T> |
Parallel dry/wet mixing for effects |
TruePeakDetector<T> |
Shared ITU-R BS.1770-4 inter-sample peak detector (used by Compressor, Limiter, LoudnessMeter) |
SpinLock |
RT-safe spinlock for thread-safe parameters |
SpscQueue<T> |
Lock-free single-producer / single-consumer queue |
AudioSpec |
Audio environment descriptor (sample rate, block size, channels) |
AudioBuffer<T> |
32-byte aligned owning buffer (SIMD-ready) |
AudioBufferView<T> |
Non-owning view (what processors receive) |
SimdOps |
SIMD-accelerated buffer operations (SSE2/AVX/NEON with scalar fallback) |
DspMath |
Constants, dB ⇄ gain, fast tanh / tan / sin / cos / exp / log / pow10, range mapping |
Phasor<T> |
Phase accumulator for LFO and oscillator construction |
SampleAndHold<T> |
Sample-and-hold with configurable hold time |
WaveshapeTable<T> |
LUT-based waveshaping with linear / cubic interpolation |
AnalogRandom |
Analog-flavoured random generators (smooth, noise, jitter) |
AnalogConstants |
Reference constants from analog-hardware research (zero runtime cost) |
ProcessorTraits |
C++20 concepts: AudioProcessor, SampleProcessor, GeneratorProcessor |
| Class | Description |
|---|---|
LevelFollower<T> |
Peak and RMS envelope follower |
EnvelopeFollower<T> |
Public attack/release detector (Peak or RMS law) for sidechains, modulation and metering |
SpectrumAnalyzer<T> |
Real-time FFT spectrum with peak hold |
LoudnessMeter<T> |
EBU R128: momentary, short-term, integrated, LRA, true peak — passes the official EBU test vectors (Tech 3341/3342, BS.1770-5 K-weighting and true-peak interpolator) |
Goertzel<T> |
Single-frequency O(N) magnitude detection |
PitchDetector<T> |
YIN pitch detection with FFT-accelerated difference function (O(N log N)) |
PitchFollower<T> |
Musical pitch tracking source: confidence gating, octave-jump correction, constant-rate semitone glide |
PhaseCorrelation<T> |
Stereo correlation/balance meter with a goniometer (vectorscope) point feed |
OnsetDetector<T> |
Causal SuperFlux onset detection (log-filtered spectral flux, vibrato-suppressing max filter, Boeck-2012 adaptive peak picker); shared front-end for beat tracking |
| Class | Description |
|---|---|
WavFile |
Read/write WAV (PCM 8/16/24/32-bit, float 32/64-bit) |
Mp3File |
MPEG-1 Layer III codec — read (CBR/VBR) + write (CBR encoder, 32–320 kbps) |
AudioFile |
Abstract base class for custom format implementations |
| Class | Description |
|---|---|
HarmonyConstants |
Constexpr musical harmony toolkit: 61 scales (bitmask representation), 15 chord recipes with inversions, MIDI/note conversion, key-aware naming (sharp/flat), diatonic chord generation. Fully constexpr/consteval — generates static tables at compile time. |
ChordDetector<T> |
Real-time chord recognition: per-note Goertzel chroma, template matching over ten chord families, bass-note root disambiguation, confidence-gated hold |
Copy the DSPark/ folder into your project. Done.
#include "DSPark/DSPark.h"Requires a C++20 compiler. Tested with MSVC 19.50+, and compatible with GCC 12+, Clang 15+, Emscripten 3+.
Build with optimizations. DSPark is header-only: all DSP code compiles inside your translation units and inherits your build flags. A debug build runs the processors 3-7x slower than release, which matters more here than with libraries that ship precompiled binaries. If an effect seems too slow, check your flags first:
-O2/-O3and-DNDEBUGon GCC/Clang,/O2and/DNDEBUGon MSVC.
#include "DSPark/DSPark.h"
int main()
{
dspark::WavFile input, output;
input.openRead("input.wav");
auto info = input.getInfo();
dspark::AudioSpec spec { info.sampleRate, 512, info.numChannels };
dspark::AudioBuffer<float> buffer(info.numChannels, 512);
dspark::Compressor<float> comp;
dspark::Limiter<float> lim;
comp.prepare(spec);
lim.prepare(spec);
comp.setThreshold(-18.0f);
comp.setCharacter(dspark::Compressor<float>::Character::Opto);
lim.setCeiling(-1.0f);
output.openWrite("output.wav", info);
while (input.readSamples(buffer.toView()))
{
comp.processBlock(buffer.toView());
lim.processBlock(buffer.toView());
output.writeSamples(buffer.toView());
}
output.close();
}using namespace dspark;
ProcessorChain<float,
Equalizer<float>,
Compressor<float>,
Limiter<float>
> channelStrip;
channelStrip.prepare(spec);
channelStrip.processBlock(buffer);dspark::StateVariableFilter<float> svf;
svf.prepare(spec);
svf.setCutoff(2000.0f);
svf.setResonance(0.7f);
for (int i = 0; i < numSamples; ++i)
{
svf.setCutoff(lfo.getNextSample() * 2000 + 500); // Modulate per sample
auto [lp, hp, bp] = svf.processMultiOutput(input[i], 0);
output[i] = lp; // Or hp, bp, or any combination
}dspark::Equalizer<float> eq;
eq.prepare(spec);
eq.setBand(0, 80.0f, 4.0f);
eq.setBand(1, 3000.0f, -2.0f, 2.0f);
// Get magnitude response for drawing
std::vector<float> freqs(512), mags(512);
for (int i = 0; i < 512; ++i)
freqs[i] = 20.0f * std::pow(1000.0f, static_cast<float>(i) / 511.0f);
eq.getMagnitudeForFrequencyArray(freqs.data(), mags.data(), 512);
// mags[] now contains the combined EQ curve — plot it in your GUIDSPark is a DSP framework first, but it ships a complete native plugin layer: the same class that processes your audio becomes a loadable plugin with nothing but this repository — no external SDK to download (Steinberg's official C API header is vendored under its permissive 2025 license).
#include "plugin/vst3/DSParkVst3.h"
struct MySaturator
{
static constexpr auto descriptor = dspark::plugin::Descriptor {
.name = "My Saturator", .vendor = "Me",
.productId = "com.me.mysaturator", .version = "1.0.0",
};
static constexpr auto parameters = dspark::plugin::params(
dspark::plugin::param("drive", "Drive", -12.0f, 36.0f, 0.0f, "dB"));
void prepare(const dspark::AudioSpec& spec) { sat_.prepare(spec); }
void setParameter(int, float v) noexcept { sat_.setDrive(v); }
void processBlock(dspark::AudioBufferView<float> io) noexcept { sat_.processBlock(io); }
dspark::Saturation<float> sat_;
};
DSPARK_VST3_PLUGIN(MySaturator)cl /std:c++20 /O2 /LD /EHsc /I . mysaturator.cpp /Fe:MySaturator.vst3
Sample-accurate parameter automation, state save/restore, soft bypass,
latency reporting (including runtime changes), mono/stereo bus negotiation
and denormal protection are handled by the layer. The same binary is
also a CLAP plugin (DSPARK_CLAP_PLUGIN) and an Audio Unit for Logic Pro
(DSPARK_AU_PLUGIN, validated by Apple's auval in CI); presets are
byte-portable across all three formats by construction. The optional
contract grows with one method each: a host-routable sidechain bus
(two-buffer processBlock, examples/plugin_ducker/), MIDI input and
instruments (handleMidiEvent + Category::Instrument,
examples/plugin_synth/ — an 8-voice synth validated as an aumu music
device), host transport for tempo-synced DSP (setTransport),
offline render quality switching (setOfflineRendering) and
factory presets published to every host's preset browser
(factoryPresets). Each capability is proven functionally in CI by
dedicated smoke hosts — measured ducking, measured note pitch, measured
automation step positions — not just compiled.
For a custom GUI, write it in plain HTML/CSS/JS: the WebView editor
layer embeds it in the host window on every format and platform — WebView2
on Windows, WKWebView on macOS, WebKitGTK on Linux/X11 — with a tiny
dspark JS bridge for parameters and automation gestures, and a
dspark_add_plugin(... EDITOR_HTML ui/editor.html) build step that inlines
ordinary separate web files. Every example plugin passes Tracktion's
pluginval and clap-validator in CI, and dedicated editor smoke hosts
exercise a real web view per platform on every commit.
Start here: the plugin guide documents the complete
contract (required and optional methods, what each maps to per format, the
threading model, the editor layer per platform, shipping checklists).
Inherit dspark::plugin::PluginBase<T> to see every overridable method
with safe defaults in one place (examples/plugin_template/), or write a
free-standing struct (examples/plugin_saturator/); the WebView editor
examples are examples/plugin_webview_editor/ (single file) and
examples/plugin_webview_files/ (separate web files).
DSParkLab is an interactive, plugin-style GUI application for real-time testing of every DSPark processor. Load any audio file, enable effects, shape them on an interactive analyzer or with parameter controls, and hear the results instantly.
# Build (requires MSVC with C++20 support + Windows SDK for D3D11)
DSParkLab\build.bat
DSParkLab\DSParkLab.exeFeatures:
- Asynchronous WAV/MP3 loading with format auto-detection (audio thread never blocks on I/O)
- 34 effects organised by category (Filters, Dynamics, Distortion, Analog, Modulation, Pitch, Spatial, Utility) — including the physical tape/tube/transformer models, pitch shifter with formant preservation, granular engine and denoiser
- Interactive analyzer: log-frequency spectrum behind a live response curve, with draggable nodes for the EQ / Filter / Dynamic EQ (drag X = frequency, Y = gain, mouse-wheel = Q)
- Dynamic EQ draws its live per-band reaction in real time; multiband compressor shows crossover bands with per-band gain reduction
- Auto-generated parameter panels with mouse-wheel-adjustable sliders and combo boxes
- Live oversampling selection (up to 16x) on Saturation and Clipper for audible anti-alias comparison
- Convolution Reverb loads real impulse responses (WAV) or builds a synthetic one
- Per-channel level meters, waveform view, and gain-reduction metering
- A/B bypass for instant comparison, and transport controls (play, pause, stop, seek, loop)
Built with Dear ImGui (MIT) and miniaudio (public domain). These dependencies are bundled in DSParkLab/vendor/ and are only used by the testing app — the DSPark framework itself remains 100% dependency-free.
| Platform | Status | Notes |
|---|---|---|
| Windows (MSVC) | Tested in CI | x64 and ARM64, C++20, /W4 (only benign C4324 alignas padding notices) |
| Linux (GCC / Clang) | Tested in CI | x64 and ARM64, C++20, -Wall -Wextra |
| macOS (Clang) | Tested in CI | ARM64, C++20, -Wall -Wextra |
| WebAssembly (Emscripten) | Tested in CI | Zero syscalls in audio path; scalar and SIMD128 |
| iOS / Android | Compatible | ARM NEON denormal flush supported |
| Plugins (VST3 / CLAP / AU) | Native | Built-in plugin layer with WebView editors (guide) |
- C++20: Concepts (
AudioProcessor,SampleProcessor,GeneratorProcessor), designated initializers,std::numbers - Zero allocation in audio thread: All memory pre-allocated in
prepare() - SIMD inner loops: SSE2/SSE3/AVX/NEON-accelerated buffer operations and FFT, with automatic scalar fallback
- Cache-friendly: Contiguous memory, 32-byte aligned buffers
- Thread-safe parameters: All setters use
std::atomicwithmemory_order_relaxed— safe to call from any thread (UI, automation, audio) with zero contention - Lock-free coefficient updates:
Biquad::setCoeffs()is consumed automatically byprocessBlock()andprocessSample()via a relaxed-load fast path. No external sequencing required. - No virtual dispatch in hot path: Templates and compile-time polymorphism
- Physically-modeled algorithms: Tape (Chowdhury 2019 hysteresis with Langevin function, head bump pre-filter, gap-loss HF rolloff), FDN reverb (Jot 1991 absorption, Householder mixing, Dattorro 1997 multi-tap output, Lexicon-style modulation, serial allpass density, allpass interpolation, tanh soft saturation), TPT state-variable and ladder filters
- Full Doxygen documentation: Every public class and method documented — browse it at cristianmoresi.github.io/DSPark
DSPark/
├── DSPark.h # Single umbrella include + full documentation
├── Core/ (41) # Building blocks: filters, FFT, WDF, oscillators, SIMD
├── Effects/ (36) # Ready-to-use processors: EQ, compressor, reverb, tape...
├── Analysis/ (9) # Metering: LUFS (EBU-verified), spectrum, pitch, correlation, onset
├── IO/ (3) # File I/O: WAV read/write, MP3 read/write
├── Music/ (2) # Harmony constants + real-time chord detection
├── plugin/ # Native plugin layer: VST3, CLAP, AU + WebView editor
├── tests/ # Test suite: 630+ cases, zero dependencies
├── conformance/ # Public conformance suite (runs in CI)
├── docs/ # Cookbook, plugin guide, metrics table
├── examples/ # WAV processing, channel strip, plugins, templates
├── tools/ # VST3/CLAP/AU-editor smoke hosts, editor host, amalgamator
└── DSParkLab/ # Interactive testing app (Win32 + ImGui + miniaudio)
Reverb performance: an Eco engine for constrained targets and direct control over convolution IRs, both prompted by real-world feedback from a synthesizer firmware project (issue #2).
- Eco quality mode:
AlgorithmicReverb::setQuality(Quality::Eco)runs a reduced engine (8 FDN lines, control-rate modulation, linear allpass interpolation, leaner output stage) measuring about 3.3x cheaper per block, with the same control set and the same decay calibration. The defaultFullengine is bit-identical to v1.6.0. - IR shaping on the convolution reverb:
setDecayScale()rescales the impulse response's own T60 (estimated from its Schroeder decay curve) and trims the now-silent tail, so shorter decays also cut convolution cost roughly in proportion;setStretch()resamples the IR tape-speed style for larger or smaller spaces. Both always reshape the IR as loaded and republish atomically, exactly likeloadIR(). - DSParkLab: a Quality selector on the Reverb and Decay Scale / Stretch sliders on the Convolution Reverb, for instant A/B.
The host contract: the plugin layer now covers everything a host can offer an effect or an instrument — each capability one declarative member, each one proven functionally in CI (measured, not just compiled).
- Instruments & MIDI:
handleMidiEvent(MidiEvent)adds a note input to every format (VST3 event bus +IMidiMappingfor pitch bend / mod / sustain / pressure, CLAP note ports speaking both CLAP and raw-MIDI dialects, AU MusicDevice selectors), andCategory::Instrumentbuilds a true generator: no audio inputs, anaumuAudio Unit, cleared buffers that voices add into.examples/plugin_synth/— 8 voices, voice stealing, pitch bend, sample-accurate note starts — passesauvaland plays a measured 440 Hz in CI. - Host transport:
setTransport(TransportInfo)delivers tempo, musical position, time signature, loop points and play state per block, from the VST3 ProcessContext, the CLAP transport event and the AU host callbacks — the basis for tempo-synced delays, LFOs and gates. - Mono everywhere: every plugin now negotiates mono and stereo by
default (
ChannelSupportrestricts it when the DSP is inherently stereo); the sidechain mirrors the main width. - Sample-accurate automation by default: parameter, bypass and note events ride one time-ordered stream and processing splits at 32-frame boundaries, so fast curves land where the host drew them (declarative opt-out for FFT-heavy plugins).
- The professional details: runtime latency changes notify the host
natively in all three formats;
setOfflineRendering(bool)switches quality for bounces;factoryPresetspublishes to every host's preset browser (VST3 program list, CLAP preset-load + preset-discovery, AU factory presets); host bypass and the active program now persist in the state container;process()runs under DSPark's denormal guard. - Proven by instrumentation: the new
tools/plugin_probe.cppencodes what the wrapper delivers into its output, and the smoke hosts measure it — transport DC, the offline sign flip, an automation step landing on its exact sample, note pitch by zero crossings, the latency-changed notification — on every platform, on every commit. pluginval and clap-validator caught two real state-persistence bugs along the way; both fixed and now regression-covered.
MIT License. See LICENSE.
Free to use in commercial and open-source projects. Attribution appreciated.
Cristian Moresi — Software developer and music producer with professional experience in mixing engineering and sound design.
DSPark was created to provide a truly free, professional-grade DSP toolkit accessible to developers at every level of expertise — from desktop app builders to DSP engineers designing embedded audio systems. It is a genuine open-source alternative to commercial audio frameworks, built from the ground up with no dependencies and no compromises.
- GitHub: github.com/CristianMoresi
- LinkedIn: linkedin.com/in/cristianmoresi
- Email: dev@cristianmoresi.com
Contributions are welcome. Please open an issue to discuss proposed changes before submitting a pull request.
Building and testing the framework needs only a C++20 compiler and CMake:
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build --parallel
ctest --test-dir build --output-on-failureSee CONTRIBUTING.md for the full development workflow, the conventions the codebase follows, and what CI checks on every commit.
For bug reports, include: compiler version, platform, minimal reproduction code.
