mirror of
https://codeberg.org/armin/rmx-19.git
synced 2026-10-11 16:51:55 +02:00
290 lines
11 KiB
Markdown
290 lines
11 KiB
Markdown
# RMX-19 - Super Sound Module (VST3 / AU)
|
||
|
||
RMX-19 is a virtual synthesizer sound module, implemented as an audio plugin in C++ with JUCE.
|
||
|
||
The plugin is a self-contained subtractive synth: two oscillators, a
|
||
state-variable filter, dual envelopes, an LFO, a built-in FX unit (chorus /
|
||
delay / space), and a factory patch bank - all edited and browsed through the
|
||
on-screen LCD instead of a conventional panel of knobs.
|
||
|
||
## Screenshot
|
||
|
||

|
||
|
||
---
|
||
|
||
## Blueprint
|
||
|
||

|
||
|
||
|
||
---
|
||
|
||
## What it is at a glance
|
||
|
||
| | |
|
||
|---|---|
|
||
| **Format** | VST3 and Audio Unit (AU) plugin |
|
||
| **Transport** | Host JUCE-based AU / VST3 on macOS arm64 |
|
||
| **Architecture** | Subtractive / virtual-analog synthesizer |
|
||
| **UI model** | Simulated 19" rack module with a 160×64 dot-matrix LCD |
|
||
| **Voice count** | 16-voice polyphonic engine (1–16 selectable) |
|
||
| **Audio** | 24-bit/96 kHz capable; optional 2× HQ oversampling |
|
||
| **MIDI** | Note on/off, aftertouch-style CCs, pitch wheel, sustain pedal |
|
||
|
||
---
|
||
|
||
## Feature overview
|
||
|
||
### Sound engine
|
||
|
||
- **Two oscillators** per voice, each with five waveforms:
|
||
sine, triangle, sawtooth, pulse, and noise.
|
||
- **Oscillator mix** (blend between OSC1 and OSC2) and **detune** (in cents)
|
||
for rich, thick unison-style stacking.
|
||
- **State-variable filter** in the Chamberlin style with three modes:
|
||
low-pass, band-pass, and high-pass, plus **cutoff**, **resonance**,
|
||
**filter envelope amount**, and **key tracking**.
|
||
- **Two ADSR envelopes**: one for the amplifier and one for the filter,
|
||
each with independent attack / decay / sustain / release.
|
||
- **One LFO** with rate, depth, and four selectable shapes
|
||
(sine, triangle, square, sample-and-hold), routable to three targets:
|
||
filter cutoff, pitch, or amplitude (tremolo).
|
||
- **Portamento / glide** per patch, **master tune** (±12 semitones).
|
||
- **Voice panning**: user pan plus a small per-voice random offset to spread
|
||
the stereo image.
|
||
|
||
### Effects
|
||
|
||
The FX unit is stacked **chorus** and **delay**, selectable via **FX TYPE**:
|
||
|
||
- **OFF** - bypass.
|
||
- **CHORUS** - modulated short delay (uses the FX time as a base).
|
||
- **DELAY** - ping-pong-style feedback delay with a cross-feedback network.
|
||
- **SPACE** - a combination of chorus + delay (widened stereo ambience).
|
||
|
||
**FX DEPTH** sets the wet/dry mix; **FX TIME** sets the delay time in seconds
|
||
when running free. Crucially, the delay can also be **quantized to the host
|
||
tempo** (see below).
|
||
|
||
#### Delay tempo sync
|
||
|
||
The delay can be locked to your DAW's transport tempo. On the **FX** screen
|
||
there is a fourth row labeled **SYNC** that chooses from these rhythmic
|
||
divisions (values are multiplied against `60 / BPM` to derive the delay in
|
||
seconds):
|
||
|
||
| SYNC value | Music-notation equivalent |
|
||
|------------|---------------------------|
|
||
| `OFF` | free (use FX TIME in seconds) |
|
||
| `1/16` | sixteenth note |
|
||
| `1/8` | eighth note |
|
||
| `1/8T` | eighth-note triplet |
|
||
| `1/8D` | dotted eighth |
|
||
| `1/4` | quarter note |
|
||
| `1/4T` | quarter-note triplet |
|
||
| `1/4D` | dotted quarter |
|
||
| `1/2` | half note |
|
||
| `3/4` | dotted half |
|
||
| `1/1` | whole note |
|
||
|
||
When a SYNC value other than `OFF` is selected, the FX TIME knob is ignored
|
||
for the delay and the delay time follows the host tempo in real time.
|
||
|
||
### Factory patches
|
||
|
||
RMX-19 ships with a hand-tuned bank of factory presets organized by category
|
||
(POLY PAD, KEY, BASS, LEAD, and more). Patches are stored as parameter
|
||
settings and can be recalled either from the LCD patch browser or from the
|
||
DAW's own program list.
|
||
|
||
---
|
||
|
||
## The rack front panel (UI)
|
||
|
||
The plugin looks like a 19" rack unit sitting in your DAW. The main elements:
|
||
|
||
- **LCD display** - the green-on-black dot-matrix screen where all editing
|
||
happens.
|
||
- **Nav diamond** (`▲ ▼ ◀ ▶`) - move the cursor / change values.
|
||
- **ENTER** and **BACK** - confirm a selection or return to the previous
|
||
screen.
|
||
- **UI scale** dropdown (bottom-right) - resize the whole rack anywhere from
|
||
50% to 300%.
|
||
- A **power LED** and cosmetic backplate graphics round out the hardware
|
||
illusion.
|
||
|
||
You can also drive the whole interface with the keyboard: **arrow keys** for
|
||
navigation, **Return / Space** for ENTER, and **Escape** for BACK.
|
||
|
||
### Using the LCD
|
||
|
||
The interface is a small nested menu system:
|
||
|
||
1. **SPLASH** - the boot-up screen; press ENTER to continue.
|
||
2. **HOME** - shows the current patch number, name, category, and a live
|
||
voice-activity bar. Use ◀/▶ (or ▲/▼) to step through patches.
|
||
3. **MENU** - eight destinations:
|
||
`PATCH`, `VOICE`, `FILTER`, `ENVELOPE`, `LFO`, `FX`, `MASTER`, `ABOUT`.
|
||
4. **PATCH** - scroll through the factory bank; press ENTER to load the
|
||
highlighted patch.
|
||
5. **VOICE / FILTER / ENVELOPE / LFO / FX / MASTER** - parameter screens.
|
||
Highlight a row and use ◀/▶ to adjust it (defaults to fine steps).
|
||
|
||
#### The parameter screens
|
||
|
||
| Screen | Parameters |
|
||
|--------|------------|
|
||
| **VOICE** | OSC1 WAVE, OSC2 WAVE, COARSE TUNE 1, COARSE TUNE 2, DETUNE 1, DETUNE 2, OSC BAL |
|
||
| **FILTER** | FILTER TYPE, CUTOFF, RESONANCE, FILT ENV, KEY TRACK |
|
||
| **ENVELOPE** | AMP ATTACK, AMP DECAY, AMP SUSTAIN, AMP RELEASE, FENV ATTACK, FENV DECAY, FENV SUSTAIN, FENV RELEASE |
|
||
| **LFO** | LFO RATE, LFO SHAPE, LFO DEPTH, LFO TARGET |
|
||
| **FX** | FX TYPE, FX DEPTH, FX TIME, **SYNC** (delay tempo sync) |
|
||
| **MASTER** | MASTER VOL, STEREO PAN, POLYPHONY, PORTAMENTO, MASTER TUNE, HQ MODE |
|
||
|
||
> **Finding the delay sync.** On the **FX** screen the rows are FX TYPE,
|
||
> FX DEPTH, FX TIME, and then a fourth row labeled **SYNC**. Press **DOWN**
|
||
> three times from the top of the FX screen to reach it, then use **◀/▶** to
|
||
> pick a rhythmic division (see the table above).
|
||
|
||
### About screen
|
||
|
||
Shows the RMX-19 build: git branch / SHA / dirty marker, the build date/time,
|
||
the JUCE version, and the target platform. The LCD **footer** also shows the
|
||
git branch@commit and build timestamp on every screen.
|
||
|
||
---
|
||
|
||
## MIDI
|
||
|
||
RMX-19 accepts MIDI input and maps the following messages:
|
||
|
||
| MIDI | Action |
|
||
|------|--------|
|
||
| Note on / off | Play / release voices |
|
||
| Pitch wheel | ±2 semitones, smoothed |
|
||
| CC 64 | Sustain pedal (sustains held notes) |
|
||
| CC 1 / 74 | Filter cutoff |
|
||
| CC 2 / 71 | Filter resonance |
|
||
| CC 3 / 76 | LFO rate |
|
||
| CC 4 / 91 | FX depth |
|
||
| CC 7 | Master volume |
|
||
| CC 10 | Stereo pan |
|
||
| CC 72 | Amp release |
|
||
| CC 73 | Amp attack |
|
||
| CC 77 | LFO depth |
|
||
|
||
The plugin also exposes each patch as a DAW program, so preset changes from
|
||
the host map onto the factory bank.
|
||
|
||
---
|
||
|
||
## DSP notes
|
||
|
||
- **Voice engine** - each voice is a classic two-osc → mix → SVF filter →
|
||
amp-envelope chain. The oscillator mix is a crossfade between OSC1 and
|
||
OSC2, and each oscillator has its own tuning: a coarse tune in semitones
|
||
(`2^(ctune/12)`) plus a fine detune in cents (`2^(detuneN/1200)`, DETUNE 1 →
|
||
OSC1, DETUNE 2 → OSC2).
|
||
- **Filter** - a stable Chamberlin state-variable filter; cutoff is modulated
|
||
by the filter envelope, key tracking, the LFO, and the mod wheel, with a
|
||
smoothed control signal to suppress zipper noise.
|
||
- **Envelopes** - exponential ADSRs (attack/decay/release are time-domain
|
||
tau-based approximations, sustain is a level).
|
||
- **HQ mode** - a MASTER-screen toggle that renders the engine at **2× the
|
||
host sample rate** internally, then downsamples, reducing alias artifacts
|
||
at high cutoff / bright oscillators.
|
||
- **Output stage** - per-sample `tanh` soft-clipping plus a DC-blocking
|
||
filter, and a master volume gain.
|
||
- **FX** - a modulated short delay (chorus) and a cross-feedback delay line
|
||
(delay). The feedback delay supports host-tempo sync via the SYNC setting.
|
||
Tail length is sized to fit the longest possible sync delay.
|
||
|
||
---
|
||
|
||
## Building from source
|
||
|
||
### Prerequisites
|
||
|
||
macOS on Apple Silicon (arm64), macOS 12.0 or later:
|
||
|
||
- CMake ≥ 3.22
|
||
- A C++17 compiler (Apple Clang via Xcode / Command Line Tools)
|
||
- `git` (to fetch the JUCE framework)
|
||
|
||
Linux:
|
||
|
||
- CMake ≥ 3.22, a C++17 compiler (GCC or Clang), `git`, `pkg-config`
|
||
- Development packages used by JUCE (Debian/Ubuntu):
|
||
`libasound2-dev libx11-dev libxext-dev libxinerama-dev libxrandr-dev`
|
||
`libxcursor-dev libxcomposite-dev libfreetype6-dev libfontconfig1-dev
|
||
libcurl4-openssl-dev libgl1-mesa-dev`
|
||
- No GTK/WebKit packages are needed: the plug-in does not use the web browser,
|
||
native file-chooser dialogs, or `<gtk/gtk.h>`.
|
||
|
||
The build fetches **JUCE 8.0.4** automatically into `build/JUCE` on first
|
||
configure - no manual JUCE setup is required.
|
||
|
||
### Commands
|
||
|
||
```sh
|
||
make # configure + build VST3 (and AU on macOS)
|
||
make install # build + install (~/Library/Audio/Plug-Ins on macOS, ~/.vst3 on Linux)
|
||
make uninstall # remove installed bundles
|
||
make clean # delete the CMake build tree
|
||
make info # print build paths
|
||
```
|
||
|
||
On Linux the AU format is skipped automatically; only the VST3 is produced, and
|
||
`make install` copies it to `~/.vst3` (JUCE's default Linux VST3 scan path).
|
||
A plain `cmake -S . -B build -DJUCE_ROOT=<JUCE source> && cmake --build build --parallel`
|
||
works on Linux as well. Both `make` and that command compile with all logical
|
||
cores by default; override with `make JOBS=8`.
|
||
|
||
`make` (configure) is designed to be cheap when nothing changed and refreshes
|
||
the git branch/hash and timestamp embedded in the LCD footer on every
|
||
configure, so the About screen always reflects the current source state.
|
||
|
||
### Notes
|
||
|
||
- After `make install`, **restart (or cold-start) your DAW** so macOS rescans
|
||
AudioComponents. A freshly-installed AU may not appear until the host is
|
||
relaunched.
|
||
- Installed bundles are ad-hoc code-signed; if your DAW refuses to load the
|
||
AU, run `codesign --force --deep --sign - <bundle>` again or re-install.
|
||
|
||
---
|
||
|
||
## Project layout
|
||
|
||
```
|
||
CMakeLists.txt Build configuration (JUCE plugin target, git build info)
|
||
Makefile Building / installing convenience wrapper
|
||
b3.png Rack faceplate background image (embedded as binary data)
|
||
Source/
|
||
PluginProcessor.cpp/.h Audio processor: MIDI, FX engine, patch I/O, state save/load
|
||
PluginEditor.cpp/.h Rack front panel: buttons, scale dropdown, rendering
|
||
LcdPanel.cpp/.h Dot-matrix LCD: all screens, navigation, glyph rendering
|
||
SynthEngine.cpp/.h The voice / oscillator / filter / envelope DSP core
|
||
Params.cpp/.h Parameter table, formatting, UI value stepping, delay sync names
|
||
PresetBank.cpp/.h Factory patch definitions and bank lookup
|
||
Probe.cpp Offline dev probe (scripted MIDI, no GUI/DAW)
|
||
BuildInfo.h.in Compile-time git/timestamp template
|
||
```
|
||
|
||
### Development probe
|
||
|
||
`Source/Probe.cpp` is an offline executable (`rmx_probe`) used during
|
||
development to drive the processor with scripted MIDI events without a DAW or
|
||
GUI. It is defined in `CMakeLists.txt` for convenience and is not part of the
|
||
shipped plugin.
|
||
|
||
---
|
||
|
||
## License / attribution
|
||
|
||
RMX-19 is a personal / hobby project. It is built on the
|
||
[JUCE](https://juce.com) audio framework under its own license. The rack
|
||
hardware aesthetic pays tribute to classic 90s synthesizer rack gear; the
|
||
plugin is an original implementation and is not affiliated with or endorsed
|
||
by any hardware manufacturer.
|