Scaffold NIH-plug project: full-band gain VST3/CLAP with one-slider egui GUI
Sets up the Rust/NIH-plug build (pinned to nih-plug rev f36931f) producing VST3 and CLAP bundles via 'cargo xtask bundle'. Implements the first landmark: a full-band gain plugin with a single egui ParamSlider. - Cargo workspace + xtask bundler, .cargo alias, bundler.toml - src/lib.rs: Codename206 plugin (gain param, egui editor) - deploy.ps1/.bat: build + install to system VST3/CLAP folders (real copy, not a junction, for FL Studio); -User flag for a no-admin dev loop - LICENSE: GPL-3.0 (required by NIH-plug's VST3 bindings) - README: corrected architecture for the 'All' aggregate channel (4th comp/lim stack on the summed bands; all-bands-bypassed = simple full-band comp) - .gitignore excludes /target and the local nih-plug + _template reference clones Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -10,6 +10,7 @@ Built with **Rust** + **NIH-plug** (VST3 + CLAP output) + **egui** for the UI.
|
||||
|
||||
**Goals:**
|
||||
- 3-band (configurable crossover points) compressor/limiter
|
||||
- An 'All' aggregate channel: a 4th comp/lim stack on the summed bands, so bypassing all bands turns the plugin into a simple full-band compressor (mirrors FL's Maximizer)
|
||||
- Look-ahead brickwall output limiter with true-peak detection
|
||||
- Real-time gain reduction metering per band
|
||||
- Custom gain curve visualiser
|
||||
@@ -33,13 +34,23 @@ Built with **Rust** + **NIH-plug** (VST3 + CLAP output) + **egui** for the UI.
|
||||
```
|
||||
Input
|
||||
└─ Crossover filterbank (Linkwitz-Riley LR4 @ each crossover freq)
|
||||
├─ Band 1 (low) → look-ahead delay → compressor VCA → gain stage
|
||||
├─ Band 2 (mid) → look-ahead delay → compressor VCA → gain stage
|
||||
└─ Band 3 (high) → look-ahead delay → compressor VCA → gain stage
|
||||
└─ Sum → output brickwall limiter (true-peak, 4x oversampled) → output
|
||||
├─ Band 1 (low) → look-ahead delay → compressor VCA → gain stage ─┐ (bypassable)
|
||||
├─ Band 2 (mid) → look-ahead delay → compressor VCA → gain stage ─┤ (bypassable)
|
||||
└─ Band 3 (high) → look-ahead delay → compressor VCA → gain stage ─┤ (bypassable)
|
||||
│
|
||||
Sum of bands ◄──────────────────────────────────────────────------┘
|
||||
└─ 'All' channel → look-ahead delay → compressor VCA → gain stage
|
||||
└─ output brickwall limiter (true-peak, 4x oversampled) → output
|
||||
```
|
||||
|
||||
The detector for each band reads `look_ahead_ms` ahead of the VCA, so gain reduction is already ramping when the transient arrives.
|
||||
|
||||
**The 'All' aggregate channel** (mirrors FL's Maximizer): the three bands are summed and the
|
||||
result passes through a *fourth*, full-band compressor/limiter stack before the output limiter.
|
||||
Because the LR4 filterbank sums phase-coherently flat, **bypassing all three bands leaves the
|
||||
summed signal identical to the input** — so the plugin collapses into a plain single-band
|
||||
compressor/limiter driven entirely by the 'All' channel. That makes "multiband off = simple comp"
|
||||
a first-class mode, not an afterthought.
|
||||
|
||||
---
|
||||
|
||||
@@ -56,6 +67,11 @@ The detector for each band reads `look_ahead_ms` ahead of the VCA, so gain reduc
|
||||
- Attack / release envelopes (logarithmic ballistics)
|
||||
- Makeup gain per band
|
||||
- Look-ahead: circular delay buffer on the audio path; detector reads ahead
|
||||
### 'All' Aggregate Channel
|
||||
- Structurally **identical to a per-band compressor** — reuse the same comp/lim code/params, just fed the summed signal instead of a filtered band
|
||||
- Runs after the three bands are summed, before the output brickwall limiter
|
||||
- Bands are individually bypassable; with all three bypassed the (phase-coherent) crossover sum equals the dry input, so the 'All' channel alone acts as a full-band comp/lim
|
||||
- Has its own look-ahead delay; total reported latency = max(band look-ahead) + 'All' look-ahead
|
||||
### Output Limiter
|
||||
- True-peak brickwall (ceiling = 0 dBFS or user-defined)
|
||||
- 4x oversampling for inter-sample peak detection
|
||||
@@ -73,14 +89,16 @@ The detector for each band reads `look_ahead_ms` ahead of the VCA, so gain reduc
|
||||
- `look_ahead_ms` — look-ahead time (0–10 ms)
|
||||
- `crossover_low_hz` — low/mid crossover frequency
|
||||
- `crossover_high_hz` — mid/high crossover frequency
|
||||
### Per Band (× 3, use a `#[nested]` params struct)
|
||||
### Per-Channel Compressor (× 4: low, mid, high, **all** — one `#[nested]` params struct reused)
|
||||
- `threshold_db`
|
||||
- `ratio` — 1.0 (off) to ∞ (limiting)
|
||||
- `attack_ms`
|
||||
- `release_ms`
|
||||
- `knee_db` — soft knee width
|
||||
- `makeup_gain_db`
|
||||
- `bypass` — per-band bypass
|
||||
- `bypass` — per-channel bypass (bypassing low+mid+high = simple full-band comp via the 'all' channel)
|
||||
|
||||
The 'all' channel uses the same struct so its UI and DSP are identical to a band; it just sits after the band sum.
|
||||
---
|
||||
|
||||
## Project Structure
|
||||
@@ -109,22 +127,38 @@ src/
|
||||
|
||||
## Build Steps
|
||||
|
||||
```bash
|
||||
# Install Rust (if not already)
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
|
||||
|
||||
# Clone NIH-plug cookiecutter or start fresh
|
||||
cargo new --lib my_maximizer
|
||||
cd my_maximizer
|
||||
|
||||
# Add dependencies to Cargo.toml:
|
||||
# nih-plug = { git = "https://github.com/robbert-vdh/nih-plug", features = ["assert_process_allocs"] }
|
||||
# nih-plug-egui = { git = "https://github.com/robbert-vdh/nih-plug" }
|
||||
|
||||
# Build and bundle
|
||||
cargo xtask bundle my_maximizer --release
|
||||
# Output: target/bundled/my_maximizer.vst3
|
||||
The project is already scaffolded (NIH-plug + nih_plug_egui, pinned to a fixed git rev in
|
||||
`Cargo.toml`). You do **not** need the Steinberg VST3 SDK — NIH-plug bundles its own bindings.
|
||||
|
||||
**Prerequisites (Windows):**
|
||||
- Rust stable (`rustup` — `winget install Rustlang.Rustup`)
|
||||
- Visual Studio 2022 with the "Desktop development with C++" workload (provides the MSVC linker)
|
||||
|
||||
```powershell
|
||||
# Build + bundle the VST3 and CLAP
|
||||
cargo xtask bundle codename_206 --release
|
||||
# Output: target\bundled\Codename 206.vst3 and Codename 206.clap
|
||||
```
|
||||
|
||||
### Deployment
|
||||
|
||||
FL Studio scans `C:\Program Files\Common Files\VST3` by default, **ignores directory junctions**
|
||||
(so a symlinked bundle is invisible to its scanner), and caches failed scans. So deployment must
|
||||
copy a *real* bundle into a folder FL scans, then FL must be told to rescan failed plugins.
|
||||
|
||||
Use the provided script (no need to remember the details):
|
||||
|
||||
```powershell
|
||||
.\deploy.ps1 # build, then copy to the global VST3/CLAP folders (one UAC prompt)
|
||||
.\deploy.ps1 -SkipBuild # reinstall the last build without rebuilding
|
||||
.\deploy.ps1 -User # copy to %LOCALAPPDATA%\Programs\Common\VST3 instead (no admin) — best for a dev loop
|
||||
```
|
||||
|
||||
`deploy.bat` is a double-click wrapper around the same script.
|
||||
|
||||
After deploying, in FL Studio: **Options → Manage plugins → tick "Rescan previously failed
|
||||
plugins" → Find installed plugins**, then search for **Codename 206**. (The rescan-failed step
|
||||
is essential — without it FL silently skips a plugin it has seen before.)
|
||||
|
||||
---
|
||||
|
||||
@@ -146,8 +180,10 @@ Work through these stages in order — each stage produces a loadable, audible p
|
||||
### Stage 3 — Crossover filterbank
|
||||
- [ ] Implement LR4 LP and HP biquad chains in `crossover.rs`
|
||||
- [ ] Verify bands sum flat (null test: sum vs dry should be silence)
|
||||
- [ ] Add per-band bypass; with all bands bypassed, output must null against dry (proves the "simple comp" mode path)
|
||||
- [ ] Apply per-band compressor to each band
|
||||
- [ ] Sum bands back to output
|
||||
- [ ] Sum bands back together
|
||||
- [ ] Run the summed signal through the 'All' channel comp/lim (reuse the per-band compressor) before output
|
||||
### Stage 4 — Look-ahead + brickwall limiter
|
||||
- [ ] Implement `delay.rs` circular buffer
|
||||
- [ ] Wire look-ahead: detector reads N samples ahead of VCA
|
||||
|
||||
Reference in New Issue
Block a user