A single-knob audio plugin built on JUCE 8. The lone Amount parameter drives a
coherent tape-character chain — soft saturation, gentle tilt EQ, post-saturation
HF roll-off, subtle wow & flutter, and an automatic loudness compensation so the
knob actually colours instead of just turning up.
| Format | VST3, Standalone, AU (macOS) |
| DSP | 4× oversampled tanh saturator + tilt EQ + wow/flutter + loudness comp |
| Latency | Reported via setLatencySamples() (oversampler latency, ~5–10 samples) |
| C++ | C++20 |
| JUCE | 8.0.12 (fetched automatically by CMake) |
Source/
PluginProcessor.{h,cpp} # AVTS, processBlock, latency, state I/O
PluginEditor.{h,cpp} # modern minimal UI with amber halo
dsp/
AmountMapper.h # Amount ∈ [0,1] → coherent coefficient struct
OnePoleFilters.h # DcBlocker, OnePoleLpf, OnePoleShelf
Saturator.h # tanh + asymmetric (in OS domain)
TiltEQ.h # low shelf 200 Hz + high shelf 8 kHz
WowFlutter.h # Lagrange3 delay + dual-LFO + jitter
LoudnessComp.h # makeup gain with linear ramp
TapeProcessor.{h,cpp} # orchestrator + 4× oversampling
lookandfeel/ # custom LookAndFeel, fonts, palette, knob component
resources/ # 10 PNG knob frames (animated rotary)
CMakeLists.txt # primary build
CMakePresets.json # ninja-debug/release/relwithdebinfo, vs2022, xcode
OneKnob.jucer # Projucer project (legacy, kept in sync)
- CMake 3.22+
- A C++20 toolchain
- Internet on first configure (to fetch JUCE)
- Optional: Ninja generator, a plugin host for testing
- Visual Studio 2022 (MSVC 19.3+) or newer, with the "Desktop development with C++" workload.
- The bundled Ninja in the VS Developer Command Prompt is sufficient — no separate install needed.
- Run all CMake commands from a VS Developer Command Prompt (
vcvars64.bat) socl.exeandninja.exeare onPATH.
- Xcode 14+ with command-line tools:
xcode-select --install. - Optional:
brew install cmake ninjaif you don't already have them.
A recent Clang or GCC plus the JUCE GUI runtime dependencies. On Debian/Ubuntu:
sudo apt update && sudo apt install -y \
build-essential cmake ninja-build pkg-config \
libasound2-dev libjack-jackd2-dev \
libcurl4-openssl-dev \
libfreetype6-dev libfontconfig1-dev \
libx11-dev libxcomposite-dev libxcursor-dev libxext-dev \
libxinerama-dev libxrandr-dev libxrender-dev \
libwebkit2gtk-4.1-dev libgtk-3-devOn Fedora the equivalents are alsa-lib-devel, jack-audio-connection-kit-devel,
libcurl-devel, freetype-devel, fontconfig-devel, libX11-devel,
libXcomposite-devel, libXcursor-devel, libXext-devel, libXinerama-devel,
libXrandr-devel, libXrender-devel, webkit2gtk4.1-devel, gtk3-devel.
Note: libcurl and webkit2gtk are required only because JUCE links them by
default; we already disable both via JUCE_USE_CURL=0 / JUCE_WEB_BROWSER=0,
but the linker still needs the libraries present for the JUCE static modules
that probe them.
The repository ships a CMakePresets.json. JUCE is pulled in automatically via
FetchContent (default tag 8.0.12, override with -DJUCE_TAG=...).
# All platforms (Ninja, Release)
cmake --preset ninja-release
cmake --build --preset ninja-release:: Ninja (recommended — fast, generator-agnostic)
cmake --preset ninja-release
cmake --build --preset ninja-release
:: Or Visual Studio solution
cmake --preset vs2022
cmake --build --preset vs2022-release# Ninja
cmake --preset ninja-release
cmake --build --preset ninja-release
# Or Xcode project (multi-config)
cmake --preset xcode
cmake --build --preset xcode-releasecmake --preset ninja-release
cmake --build --preset ninja-releasePass with -D<name>=ON|OFF at configure time:
| Option | Default | Description |
|---|---|---|
ONEKNOB_BUILD_VST3 |
ON |
Build the VST3 plugin. |
ONEKNOB_BUILD_STANDALONE |
ON |
Build the standalone host application. |
ONEKNOB_BUILD_AU |
ON (Apple) |
Build the Audio Unit (macOS only). |
ONEKNOB_ENABLE_LTO |
ON |
Link-time optimisation in Release. |
ONEKNOB_WARNINGS_AS_ERRORS |
OFF |
Treat warnings as errors. |
ONEKNOB_COPY_PLUGIN_AFTER_BUILD |
OFF |
Install the plugin to the system VST3/AU path after building. |
ONEKNOB_COMPANY_NAME |
Borato Company |
Vendor string shown by the host. |
ONEKNOB_BUNDLE_ID |
com.oneknobaudio.OneKnob |
Reverse-DNS bundle id (must be unique per plugin). |
JUCE_TAG |
8.0.12 |
JUCE git tag/branch/commit to fetch. |
Outputs land in build/<preset>/OneKnob_artefacts/<Config>/:
- VST3 bundle:
VST3/OneKnob.vst3 - Standalone:
Standalone/OneKnob[.exe|.app] - AU bundle (macOS):
AU/OneKnob.component
Copy the built .vst3 bundle to one of:
- Windows (system):
C:\Program Files\Common Files\VST3 - Windows (user):
%LOCALAPPDATA%\Programs\Common\VST3 - macOS (system):
/Library/Audio/Plug-Ins/VST3 - macOS (user):
~/Library/Audio/Plug-Ins/VST3 - Linux (user):
~/.vst3 - Linux (system):
/usr/lib/vst3or/usr/local/lib/vst3
Then rescan in your host. On macOS, AU bundles go to
/Library/Audio/Plug-Ins/Components (system) or
~/Library/Audio/Plug-Ins/Components (user). Setting
ONEKNOB_COPY_PLUGIN_AFTER_BUILD=ON copies the artefacts automatically.
OneKnob.jucer is kept in sync with the CMake build. Open it in Projucer, set
the JUCE modules path, save, and build in the generated IDE project. Prefer the
CMake flow for CI and reproducibility — the Projucer-generated JuceLibraryCode/
and Builds/ directories are listed in .gitignore.
Amount ∈ [0, 1] maps coherently onto seven independent coefficients in
AmountMapper::mapAmount. The pipeline (per stereo block):
in
→ DC blocker (HPF ~10 Hz) base rate
→ WowFlutter (Lagrange3 delay + LFOs) base rate
→ TiltEQ (low + high 1-pole shelves) base rate
→ upsample 4×
→ Saturator (tanh + asymmetry) 4× rate (only stage that aliases)
→ downsample
→ 1-pole LPF (post-saturation taming) base rate
→ LoudnessComp (makeup gain) base rate
out
Drive and makeup gain ramp linearly across each block to avoid zipper noise on
coefficient changes from AmountMapper. The Amount parameter itself is
smoothed via juce::SmoothedValue with a 30 ms ramp before reaching the mapper.
- Sound character — tweak
AmountMapper::mapAmountcurves,Saturator::asymmetry, shelf frequencies inTiltEQ, and the LFO rates inWowFlutter. - Plugin metadata — change
PRODUCT_NAME,COMPANY_NAME,PLUGIN_CODE, andPLUGIN_MANUFACTURER_CODEinCMakeLists.txt. Plugin codes must be unique per plugin to avoid host collisions. - Knob art — replace the 10 PNGs in
Source/resources/. Frame order is set inOneKnobLookAndFeel::loadKnobFrames.
- Use JUCE's
AudioPluginHostor your DAW to validate parameter automation and state save/restore. - Sanity-check loudness with pink noise at –18 dBFS RMS at
Amount=0vsAmount=1. AdjustmakeupDbinAmountMapperif you measure more than ±0.5 LU. - For THD inspection, feed a 1 kHz sine at –6 dBFS and run an FFT on the output.
At full Amount the 2nd harmonic should sit around –25 to –35 dBc (knob of
asymmetry = 0.04inSaturator.h).
No license is provided here; add your own LICENSE before distributing.