Releases: CristianMoresi/DSPark
Release list
v1.7.0 — Musical Timing, Pitch & Spectral Processing
DSPark 1.7.0 expands the header-only framework with production-ready musical
timing, pitch, spectral processing, native file formats, and stronger real-time
contracts.
Musical timing, pitch, and spectral processing
- Added
OnsetDetector,BeatTracker, andLoopFinderfor transient analysis,
tempo/phase tracking, and bounded crossfade-ready loop discovery. - Added
TimeStretchfor independent high-quality duration and pitch control. - Added
PitchCorrectorwith YIN detection, scale-aware quantization, glide,
and formant preservation. - Added
SpectralFreezewith phase-aware advance, reconstruction, and
decorrelation modes. - Added
KeyDetectorand offlineLoudnessNormalizerprocessing under a
true-peak ceiling.
Native formats and hardened I/O
- Added dependency-free native FLAC decoding with
FlacFile. - Added Standard MIDI File reading and writing with
MidiFile. - Hardened WAV, MP3, FLAC, and MIDI parsing against malformed sizes, truncated
data, and invalid metadata without introducing runtime codec dependencies.
Real-time and public API contracts
- Automatic analysis windows now preserve their time span across sample rates,
with resolved sizes exposed for latency accounting. - Audio-thread adoption of staged multi-word state is bounded; a contended
update may be deferred, but the callback never waits for the control thread. - Added
Biquad::setCoeffsNow()for stream-owner, single-threaded, and offline
coefficient updates.BiquadCoeffsand the biquad recursion now use double
precision for all sample types. AudioBufferViewconversions now express const-correctness as constraints,
andAudioProcessornow represents an unambiguous in-place mutable-buffer
processor.- Allocation failures and invalid
prepare()arguments preserve safe, valid
state across the affected processors and buffers.
Validation and distribution
- Package recipes for Conan and vcpkg are pinned to the immutable 1.7.0 source
authority. - CI covers GCC, Clang, MSVC, x64, ARM64, AddressSanitizer,
UndefinedBehaviorSanitizer, float-cast overflow, public header conformance,
installed-header consumption, and concurrent-suite isolation. - Plugin, DSParkLab, documentation, examples, benchmarks, and downstream CMake
package consumers remain part of the release validation surface.
Most 1.6.1 code remains source-compatible. Review the
1.7.0 migration guide
for analysis-window latency, BiquadCoeffs, AudioBufferView, and
AudioProcessor changes.
See the full changelog
or compare v1.6.1...v1.7.0.
v1.6.1 - Reverb Performance
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 (#2).
Eco quality mode
AlgorithmicReverb::setQuality(Quality::Eco)runs a reduced engine: 8 FDN lines (alternate base delays keep the full 29.7-160 ms span, per-line gains keep T60 exact), control-rate modulation, linear interpolation in the modulated allpasses, a single-stage input scatter and a leaner output stage.- Measured about 3.3x cheaper per block than the default engine, with matched tail loudness and the same control set.
- The default
Fullengine is bit-identical to v1.6.0; Eco is opt-in and applied like a preset change (at the next block, with a state reset).
Convolution reverb IR shaping
setDecayScale(0.25-2)rescales the impulse response's own T60, estimated from its Schroeder decay curve, from the direct sound onward. Values below 1 also trim the now-silent tail, so shorter decays cut convolution cost roughly in proportion.setStretch(0.5-2)resamples the IR tape-speed style: larger and darker above 1, smaller and brighter below.- Both always reshape the IR as loaded (never cumulatively), compose predictably, and rebuild/publish the convolver bank atomically, exactly like
loadIR(). - State: new tolerant keys (
quality,decayScale,stretch); blobs from older versions load unchanged.
DSParkLab
- Quality selector on the Reverb, Decay Scale / Stretch sliders on the Convolution Reverb, for instant A/B.
v1.6.0 — The Host Contract
The Host Contract — the plugin layer now covers everything a host can offer an effect or an instrument. Each capability is one declarative member on your plugin struct, and each one is proven functionally in CI: measured, not just compiled.
Instruments & MIDI
handleMidiEvent(MidiEvent)adds a note input to every format: VST3 event bus plusIMidiMapping(pitch bend, mod wheel, sustain, channel pressure), CLAP note ports speaking both the CLAP and raw-MIDI dialects, AU MusicDevice selectors behind a lock-free queue.Category::Instrumentbuilds a true generator: no audio inputs in any format, anaumuAudio Unit, cleared output buffers that voices add into.- New reference instrument
examples/plugin_synth/: 8 voices ofOscillator+ADSREnvelope, voice stealing, pitch bend, factory presets, sample-accurate note starts —auval-validated, and CI measures a 440 Hz note and its release decay from the audio output.
Host transport
setTransport(TransportInfo)delivers tempo, musical position, bar start, time signature, loop points and play/record state once per block — from the VST3 ProcessContext (requirements declared for you), the CLAP transport event and the AU host callbacks.samplesPerBeat()is the one-liner for tempo-synced delays, LFOs and gates.
Buses
- Mono everywhere: every plugin negotiates 1-in/1-out and 2-in/2-out by default (
ChannelSupport::StereoOnlyrestricts it for inherently stereo DSP). The sidechain always mirrors the main width.
Sample-accurate automation
- On by default: parameter, bypass and note events ride one time-ordered stream and processing splits at 32-frame quantum boundaries, so fast curves land where the host drew them. Declarative opt-out (
sampleAccurateAutomation = false) for plugins with a high fixed cost per call.
The professional details
- Runtime latency changes notify the host natively (VST3
restartComponent,clap_host_latency, the AU property listeners) — switchable lookahead now re-compensates projects correctly. setOfflineRendering(bool)exposes the render mode (VST3kOffline, the CLAP render extension, AUOfflineRender) for higher-quality bounces.factoryPresetspublishes to every host's preset browser: a VST3 program list with a program-change parameter, CLAP preset-load + preset-discovery (the plugin binary is the preset container), AU factory presets with a fullPresentPresetround-trip.- Host bypass and the active program persist in the shared state container (two real-world bugs caught by pluginval and clap-validator in CI — the bypass one latent since v1.3.0).
process()/render()run under DSPark's denormal guard in all three backends.
Proven by instrumentation
- New
tools/plugin_probe.cppencodes what the wrapper delivers into its audio output, so the smoke hosts measure every capability end to end on all five CI targets: transport DC, the offline sign flip, an automation step landing on its exact sample, note pitch by zero crossings, pitch bend through both routes, the latency-changed notification, mono processing and the preset paths. - pluginval (strictness 8) and clap-validator now also gate the synth and the probe; macOS CI runs four
auvalvalidations including the newaumu.
Docs
docs/plugins.md: full contract table for the new capabilities, new "Instruments & MIDI" and "Host transport" sections, a from-a-blank-folder project guide, and the examples indexed in learning order (also in the newexamples/README.md).
v1.5.0 — The Editor Everywhere
The WebView editor now runs on all three plugin formats and all three desktop platforms — and every one of those paths is exercised with a real web view in CI.
AU editor (macOS)
The AU backend announces a Cocoa view factory through kAudioUnitProperty_CocoaUI, registered at runtime from the plugin binary itself — still no Objective-C sources and no AppKit link anywhere in DSPark. UI edits flow through AUParameterSet and proper begin/end parameter gestures, so Logic-style hosts record automation and undo correctly. Both teardown orders (host releases the view first, or disposes the AudioUnit first) are handled and tested.
Linux editor (X11)
WebKitGTK resolved entirely through dlopen at runtime — no headers, no pkg-config, no link-time dependency — embedded in the host window with GtkPlug/XEmbed. GTK is pumped from the host's run loop (a VST3 IRunLoop timer / CLAP timer-support), never a private main loop; systems without WebKitGTK, or hosts without a usable run loop, cleanly keep the host's generic UI through the new runtime Editor::available() gate.
Proven, not just compiled
New tools/au_editor_smoke (macOS) and tools/x11_editor_smoke (Linux, under xvfb) play real hosts in CI: factory/attach, a live web view, the JS bridge ready-handshake and clean teardown — alongside the existing real-window editor host on Windows, auval, pluginval (strictness 8) and clap-validator on every commit.
Docs
docs/plugins.md (also on GitHub Pages) now carries a per-platform editor guide — build requirements, end-user runtime requirements, fallback behaviour — and the one-line dspark_add_plugin(... FORMATS VST3 CLAP AU ...) cross-platform path.
v1.4.1 — CMake package config
Packaging fix: find_package(dspark CONFIG) now works from any install tree or package manager — dsparkConfig.cmake/dsparkConfigVersion.cmake (ARCH_INDEPENDENT) are generated and installed alongside the targets file under lib/cmake/dspark. No library changes.
v1.4.0 — The WebView Editor
Custom plugin GUIs in plain HTML/CSS/JS, embedded in the host window — no GUI framework, nothing to install.
The editor layer (plugin/webview/): declare hasEditor = true and serve your page from editorHtml(); the VST3 and CLAP backends embed the platform web engine (WebView2 on Windows, WKWebView on macOS; Linux falls back to the host generic UI for now). The vendored MIT webview library and the BSD-3 WebView2 SDK header keep it zero-download.
The dspark JS bridge: onReady hands the page the parameter table with live values; setParam/onParam move plain values both ways using the same stable text ids as automation and state; beginEdit/endEdit drive host gestures and undo. DSP-to-UI sync polls the wrapper's atomic shadows — no native timers, no locks, nothing on the audio thread.
Sizing that survives real hosts (field-validated in REAPER at 200% display scaling): OS-level frame limits (WM_GETMINMAXINFO/WM_SIZING), honest VST3/CLAP size negotiation, and JUCE-style proportional content scaling with Fixed / Free / KeepAspect policies.
A real workflow: develop the UI as ordinary separate web files — dspark_add_plugin(... EDITOR_HTML ui/editor.html) inlines and embeds them at build time; editorDevFile() reloads the page from disk while iterating; editorDebug opens the browser DevTools; tools/vst3_editor_host opens any editor without a DAW and self-tests the resize chain; DSPARK_WEBVIEW_LOG=1 traces every size negotiation.
Hardened in CI: dspark_add_plugin now assembles AU .component bundles too (FORMATS VST3 CLAP AU), and every example plugin must pass Tracktion pluginval (strictness 8) and clap-validator on Windows, Linux and macOS — the latter immediately caught and got fixed a real toggle text-parsing bug in both backends.
Examples: examples/plugin_webview_editor/ (single-file, draggable SVG knobs) and examples/plugin_webview_files/ (separate-files workflow). Full guide: docs/plugins.md.