Rust real-time graybox model of Nox30, a circuit-informed approximation of a JMI-era AC30/6 with the OS/010 Top Boost unit,
implemented as CLAP/VST3 plugins and a standalone runtime with
NIH-plug and
rill-core-wdf.
This is not a component-exact circuit simulation. It follows the archived JMI schematic topology using WDF RC networks, filters, and behavioral nonlinear stages:
- bright-capped Top Boost volume and two ECC83 gain stages
- circuit-derived MNA Top Boost bass/treble network
- long-tail-pair phase inverter and post-PI Cut control
- hot cathode-biased push-pull EL84 quartet with bias shift and GZ34-like sag
- output-transformer bandwidth followed by the optional speaker IR
Model targets and reverse-engineered topology notes are in knowledge/models/. Reusable physical-part, circuit-cell, and solver notes are in knowledge/circuits/. Third-party schematic scans and service PDFs should not be committed to this repository.
Fumadocs is the project memory for architecture, progress, shared-state
decisions, monitor analysis, and contributor context. Authored engineering
content lives in knowledge/; docs/ is only the
Fumadocs/Next UI and build layer.
cd docs
npm run dev
npm run build
npm run typecheckThe local docs site starts at http://127.0.0.1:3001 when run with
npm run dev -- --hostname 127.0.0.1 --port 3001.
The topology and major time constants now follow those references, but the triodes, EL84 banks, phase inverter, transformer, and supply remain compact behavioral models. The complete amp core runs internally at 2x sample rate through linear-phase half-band filters to reduce nonlinear aliasing.
cargo test
cargo build --releaseThe release build produces the plugin library and a greybound-cli binary.
Bundle the audio plugins for the current machine:
make plugin-clap
make plugin-vst3On macOS, install them for the current user:
make plugin-clap-install
make plugin-vst3-installThe installed bundles are copied to ~/Library/Audio/Plug-Ins/CLAP/Greybound.clap
and ~/Library/Audio/Plug-Ins/VST3/Greybound.vst3.
The standalone binary opens the audio interface's native multichannel streams, processes one selected guitar input, and sends the result to selected outputs.
List device names:
target/release/greybound-cli --list-devicesThen run with a name from the list. Channel numbers are one-based:
target/release/greybound-cli \
--rig rigs/grey-nox.json5 \
--device 'Scarlett 18i8 USB' \
--input-channel 1 \
--output-channels 1,2 \
--sample-rate 48000 \
--period-size 256Run the release binary directly. Adjust the device name, sample rate, and period size for the interface:
target/release/greybound-cli --rig rigs/grey-nox.json5 --device 'Scarlett 18i8 USB' \
--input-channel 1 --output-channels 1,2 \
--sample-rate 48000 --period-size 128The CLAP/VST3 plugins always use the sample rate selected by their host.
If CoreAudio rejects a configuration, use an interface-supported sample rate
such as 44100, 48000, or 96000 and try period sizes such as 128, 256,
or 512. 44000 is not a standard Scarlett sample rate. Headphones are
strongly recommended while testing.
The speaker IR is optional and disabled by default. Enable the embedded, sample-rate-matched 200 ms Celestion Vintage 30 IR with:
target/release/greybound-cli --device 'Scarlett 18i8 USB' \
--input-channel 1 --output-channels 1,2 \
--sample-rate 48000 --period-size 128 --irThe CLAP/VST3 plugins expose the same feature as the default-off Speaker IR
parameter. It reports the fixed amp-oversampling plus 256-sample speaker-stage
latency, so switching the IR on does not change timing; when the IR is off,
convolution is skipped and only the matching dry delay runs.
Rig files define amp and pedal controls. The standalone CLI requires --rig:
target/release/greybound-cli --rig rigs/grey-nox.json5 \
--device 'Scarlett 18i8 USB' --input-channel 1 --output-channels 1,2 \
--sample-rate 48000 --period-size 16 --ir --monitorInput DB calibrates the audio interface level before the modeled input jack.
The default is unity gain because a correctly configured, non-clipping
instrument input already provides the expected level. Output DB is a safety
trim after the modeled amp because the reference circuit has no master volume.
Set the Scarlett to instrument mode and adjust its hardware gain so normal hard
playing peaks around -18 to -12 dBFS. Then adjust INPUT_DB if needed.
Add --monitor while testing driven sounds. It opens an interactive terminal
monitor with input/output RMS, peak dBFS, near-clip counts, hard-clip counts,
stream xruns, and live amp knobs. Use Tab/Shift-Tab to select a knob,
arrow keys to adjust it, and q to quit. If output peak approaches
0.0 dBFS or output near/clip is non-zero, lower --output-db before
changing the rig gain staging.
Use --input-wav "lab/references/tone3000-inputs/Brit - Guitar.wav"
to loop the dry guitar test file through the CLI instead of the live
input device.
Generic standalone runs:
target/release/greybound-cli --rig rigs/grey-nox.json5 --device 'Scarlett 18i8 USB' \
--input-channel 1 --output-channels 1,2 \
--sample-rate 48000 --period-size 16 --ir --monitor
target/release/greybound-cli --rig rigs/grey-nox.json5 \
--input-wav "lab/references/tone3000-inputs/Brit - Guitar.wav" \
--device 'Scarlett 18i8 USB' --output-channels 1,2 \
--sample-rate 48000 --period-size 16 --ir --monitor
target/release/greybound-cli --rig rigs/grey-nox.json5 \
--input-wav "lab/references/tone3000-inputs/Brit - Guitar.wav" \
--output-wav target/greybound-nox30-monitor.wav --render-seconds 10 \
--sample-rate 48000 --period-size 16 --ir --monitorFile, null, and WAV monitor runs use the same binary:
target/release/greybound-cli --rig rigs/grey-nox.json5 \
--input-wav "lab/references/tone3000-inputs/Brit - Guitar.wav" \
--output-wav target/greybound-nox30-monitor.wav --render-seconds 10 \
--sample-rate 48000 --period-size 16 --ir --monitor
target/release/greybound-cli --rig rigs/all-nox.json5 \
--input-wav "lab/references/tone3000-inputs/Brit - Guitar.wav" \
--output-wav target/greybound-fuzz-monitor.wav --render-seconds 10 \
--sample-rate 48000 --period-size 16 --ir --monitor
target/release/greybound-cli --rig rigs/grey-nox.json5 \
--input-wav "lab/references/tone3000-inputs/Brit - Guitar.wav" \
--output-wav target/greybound-overdrive-monitor.wav --render-seconds 10 \
--sample-rate 48000 --period-size 16 --ir --monitor
target/release/greybound-cli --rig rigs/all-nox.json5 \
--input-wav "lab/references/tone3000-inputs/Brit - Guitar.wav" \
--device 'Scarlett 18i8 USB' --output-channels 1,2 \
--sample-rate 48000 --period-size 16 --ir --monitoramp::VoxAmpis a reusable DSP core independent of the plugin and standalone wrappers. A future CPAL, embedded, or other device adapter can call it directly.- The amp sample-processing path uses concrete types and static dispatch. The optional IR uses preplanned FFT trait objects once per 256-sample block.
- Neither path allocates, locks, or performs I/O in the audio callback.
Vec<VoxAmp>and plugin parameter state are allocated during initialization, outside the audio callback.- The nonlinear model still has a computational cost, including
tanh()and a cutoff-coefficientexp()per sample. Benchmark the target device before treating it as hard real-time. - The CPAL standalone adapter bridges CoreAudio's input and output callbacks with a lock-free ring buffer. Use the same interface for input and output to keep both streams on the same hardware clock.
- Top Boost Volume: Top Boost channel volume and drive
- Bass: Top Boost bass control
- Treble: Top Boost treble control
- Cut: global high-frequency damping across the phase-inverter outputs
- Output Trim: safety output level; not present on the original amp