TGViewer
C++ - Reddit C++ - Reddit @r_cpp · 230 subscribers
Post #25331 9
FreeEQ8 / ProEQ8: A lock-free, variable-cadence Dynamic EQ engine built in JUCE/C++ (Looking for DSP & systems feedback)

Hey everyone,

I’ve been working on an open-source 8-band parametric EQ project called **FreeEQ8** (and its commercial 24-band sibling, ProEQ8). I just pushed the v2.2.3 and v2.2.4 stabilization updates, which focus heavily on thread-hardening, real-time safety, and optimizing dynamic coefficient churn.

The repo is fully open-source under GPL-3.0:[https://github.com/GareBear99/FreeEQ8](https://github.com/GareBear99/FreeEQ8)

I’m currently writing a technical paper mapping out the architecture for conference submission and would love to get some peer feedback on the systems design and DSP routing.

# 1. Filter Topology & The 5-DOF Cramping Reality

For the production path, I moved away from classic RBJ TDF-II biquads to a 64-bit double-precision implementation of Andrew Simper’s trapezoidal integrated State Variable Filter (SVF) topology.

To be completely transparent: both topologies use standard Bilinear Transform (BLT) mapping ($g = \\tan(\\pi \\cdot f\_c / f\_s)$), meaning they exhibit identical steady-state frequency responses and the exact same high-frequency warping near Nyquist. However, the SVF was chosen strictly for its **modulation stability**. When updating coefficients per-sample for the Dynamic EQ path, TDF-II biquads can introduce noise or state explosions, whereas the SVF maintains bounded, noise-free coefficient interpolation.

# 2. Lock-Free Concurrency & Real-Time Safety

To isolate the real-time audio thread from UI rendering or background tasks (like FIR reconstruction), the engine enforces a strict allocation-free hot path:

* **SPSC Triple-Buffering:** The spectrum analysis data uses a 3-slot index swap chain (`writeSlot`, `midSlot`, `readSlot`). The audio thread writes frames and executes atomic swaps using `std::memory_order_release`, while the UI fetches data using `std::memory_order_acquire`. Zero mutexes, zero blocking.
* **Off-Thread FIR Reconstruction:** For the plugin’s "Natural Phase" mode (which uses a 256-tap FIR kernel to correct low-frequency phase distortion), all FFT/IFFT window reconstruction happens on a background worker thread, publishing to the audio thread via the same atomic swap protocol.

# 3. Optimization: Variable-Cadence Coefficient Gating

Per-sample coefficient recalculation for 8+ dynamic bands is incredibly CPU-intensive. To solve this, I implemented a variable-cadence heuristic based on psychoacoustic thresholds.

During sustained signals, if the envelope follower's delta ($\\delta$) between samples is less than $0.1\\text{ dB}$ (well below the human broadband level JND), the engine gates per-sample recalculations and falls back to a 4-sample batch window ($0.09\\text{ ms}$ at $44.1\\text{ kHz}$). The moment a transient spikes and hits $\\delta > 0.1\\text{ dB}$, the engine instantly snaps back to per-sample accuracy. This reduces coefficient calculation overhead by up to $75\\text{--}80\\%$ on steady signals.

# 4. Reproducible Benchmarks

The repository contains a standalone benchmarking suite (`Tests/FeatureBench.cpp`) that runs outside of JUCE/DAW overhead. On a single core at $44.1\\text{ kHz}$ (512-sample blocks):

* **Standard 8-Band SVF Stereo:** Consumes $\\sim 0.63\\%$ CPU headroom ($161\\times$ real-time headroom).
* **DAW Scaling Test:** CPU usage Scales cleanly up to 128 simultaneous instances with sub-linear overhead growth due to cache warmth on shared coefficient tables.
* **Worst-Case Dynamic EQ:** 8 bands simultaneously modulated by white noise spikes maxes out at only $3.27\\%$ CPU utilizing the variable-cadence engine.

# What I'm Looking For:

If you have a few minutes to dig into the source code, I'd love to hear your thoughts on:

1. Edge cases in the `SpectrumFIFO` atomic memory ordering fences.
2. The SIMD scaffolding logic for the packed `SvfBandArray<8>` structures.
3. Roadmap feedback on implementing RBJ’s proposed 5th-constraint geometric mean pinning to natively decramp the BLT curves in v2.4.0.

Check out the repo,
GitHub GitHub - GareBear99/FreeEQ8: FreeEQ8 is a professional-grade, free and open-source 8-band parametric EQ plugin for macOS, Linux… FreeEQ8 is a professional-grade, free and open-source 8-band parametric EQ plugin for macOS, Linux, and Windows. Linear phase, dynamic EQ, match EQ, per-band drive, band linking, M/S processing, ov...
More from @r_cpp
  1. Sep 29, 2026Boost.Graph 1.95 will be C++17 Dear Boost.Graph community, In two release cycles (Boost re…
  2. Sep 26, 2026Token Sequence Injection & Modern Macros: The Most Game-Changing Compile-Time Feature in C…
  3. Sep 25, 2026myStringStream.str("") Considered Harmful Under C++20 I was recently looking at some (rath…
  4. Sep 20, 2026A clever branch free optimization I'm the developer of memlz which is an extremely fast co…
  5. Sep 15, 2026Inside Boost.PolyCollection https://bannalia.blogspot.com/2026/09/inside-boostpolycollecti…
  6. Sep 11, 2026C++26: Standard Library Hardening Experiments https://www.cppstories.com/2026/hardening-ex…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →