JUCE/C++ VST3 plugin that compresses based on stereo field position rather than frequency or mid/side. Sidechain-driven spatial compression using a raised-cosine cone window.
Status: Public canonical candidate. Core DSP math is implemented. UI is minimal but functional. Not yet tuned for musical results — tuning pass required before release.
- Concept: Connor Altizer
- Build: Dave Robertson
- Forked from:
bpm-delay-calculatorshell
This public stereo-field-compressor repo is the lowercase public canonical candidate. It is separate from the private StereoFieldCompressor repo; compare and port private docs, tests, release notes, and DSP deltas deliberately before declaring the public repo fully canonical. Do not archive either repo until that owner decision is made.
git clone https://github.com/DaveHomeAssist/stereo-field-compressor.git
cd stereo-field-compressorPrerequisites: CMake ≥ 3.22, a C++17 compiler, JUCE 8.x.
JUCE is pulled automatically via FetchContent. First configure takes a few minutes; afterward, incremental builds are fast.
cmake -B build -S .
cmake --build build --config ReleaseThe VST3 output lands in build/StereoFieldCompressor_artefacts/Release/VST3/.
Default is arm64. Add -DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" for a universal binary.
- CMake build chain with JUCE FetchContent — builds clean on macOS, Windows, Linux.
SpatialDetector— per-sample stereo field position estimator, returns angle in[-π/2, π/2](hard-L to hard-R).ConeWindow— raised-cosine gain curve centered on an arbitrary angle with adjustable width. Equation:0.5 * (1 + cos(π * (θ - θ_center) / (θ_width/2)))clamped to[0, 1](the cone spans ±θ_width/2 around the centre; the half-width form matches the code).ConeCompressor— the actual compression stage, feed-forward topology, per-sample attack/release, ratio + threshold + knee.- Parameter tree (
juce::AudioProcessorValueTreeState) with automatable params: Threshold, Ratio, Attack, Release, Knee, Cone Center, Cone Width, Makeup, Mix. - Preset save/load via JUCE's state API.
- Plugin identifiers finalised —
PLUGIN_MANUFACTURER_CODE Drob/PLUGIN_CODE Sfc1inCMakeLists.txt. - Sidechain routing —
processBlockdrives the spatial detector from the external sidechain bus when the host enables one, falling back to internal detection on the main input otherwise.
These are explicit and require attention before shipping:
- Tuning — attack/release curves are conservative defaults (RC one-pole). Musical tuning (program-dependent release, auto-gain) not done.
- UI — current editor is generic sliders. No spatial visualization yet. You'll want a polar view showing cone position + input distribution.
- Latency reporting — detector uses a one-pole RC smoother (~5 ms, zero-latency), so
getLatencySamples()is 0 (the JUCE default is never overridden). Revisit if lookahead is added. - Mono / centre fallback — mono-summed input reads as centre (|L|==|R| → angle 0); verify this is musically acceptable.
- Oversampling — not implemented. Add
juce::dsp::Oversamplingbefore the gain stage to avoid inter-sample peaks. - Metering — no GR meter. Add a
LevelMeterwidget and expose reduction fromConeCompressor::getLastGainReductionDb(). - Tests — no unit tests. At minimum, add unit tests for
ConeWindow::gainAt(angle)boundary cases (center=0, width=π/2 full scale, etc.). - AU / AAX — CMake targets VST3 only. Add AU for macOS if needed; AAX requires separate SDK + NDA.
- CI — no GitHub Actions. A matrix build on macos-latest / ubuntu-latest / windows-latest is straightforward.
- Add polar spatial-view UI component (~3 hr).
- Tune attack/release defaults with Connor on real material (~1 session).
- Oversampling + GR metering (~2 hr combined).
- CI workflow.
stereo-field-compressor/
├── CMakeLists.txt
├── README.md
├── .gitignore
├── Source/
│ ├── PluginProcessor.h
│ ├── PluginProcessor.cpp
│ ├── PluginEditor.h
│ ├── PluginEditor.cpp
│ ├── SpatialDetector.h
│ ├── SpatialDetector.cpp
│ ├── ConeWindow.h
│ ├── ConeWindow.cpp
│ ├── ConeCompressor.h
│ └── ConeCompressor.cpp
Built on JUCE 8 (pulled via FetchContent) under its free-tier open-source terms, so the
product is released under the GNU AGPLv3 — see LICENSE. If you instead hold a
paid JUCE (Indie/Pro) licence, remove LICENSE and document the commercial licence here.