As a developer and former DJ took out my Hercules RMX2 one day and felt that every piece of
DJ Software required registration and/or was really bad and did not right the RMX
With more then a decade of DJ experience, a few decades of software development and a proper
and some proper AI agents and a boring day with nothing to do, hence taking out the dusty RMX, we got to this.
I spent some time using it and i'm happy. Besides the small jogs and faders it feel a lot more like 2 CDJ's
Added a proper filter. Decent flanger.
A two-deck DJ application for Windows, purpose-built around the Hercules DJConsole RMX2.
Not a toy, not a demo — a booth-ready instrument.
StentorDeck is a complete DJ system: a real-time dual-deck audio engine, deep
hardware integration for the RMX2, a self-maintaining music library with
automatic analysis, and a performance UI designed to be read from a meter away
in a dark booth. It installs from a single Setup.exe, updates itself from
GitHub Releases, and shuts down cleanly when you close the lid.
- An audio engine that respects your ears. Two independent decks with trim / 3-band EQ + kills / filter / flanger per channel, headphone cue with PFL and head-mix, and two routing plans — Plan A (one 4-channel interface) or Plan B (any two stereo devices, bridged). Every gain change is ramped, every playing seek is a crossfade, stop can brake with a realistic vinyl spin-down (the waveform decelerates with the audio), and a −3 dB brickwall limiter guards the PA. Master volume boots booth-safe.
- The RMX2 feels native. Factory mapping out of the box, MIDI learn for everything, soft takeover so faders never jump, LED feedback, and a dual-zone jog wheel with tunable feel — fine vinyl-style nudge on the rim, spinback when you rip it. Other controllers: see Controllers below.
- A library that looks after itself. Point it at your folders: SQLite index, live file watcher, instant search, and a background analysis pipeline (in a sandboxed worker window) that computes waveforms, BPM with a real beatgrid, musical key (Camelot), and LUFS loudness for auto-gain. Tag and manual values always win over analysis; idle backfill fills in the rest.
- MP3 click & squeak remover (Library). Got an MP3 that pops, ticks, or
squeaks when you play it — or looks wrong on the waveform? Open Library,
select the track → Check MP3 (tells you if the file is unhealthy) →
Write fixed WAV. That makes a new clean copy next to the original,
named
… (Fixed by SD).wav. Your original MP3 is never changed. Load the Fixed file on the decks and mix as usual. Still hear clicks even when Check says OK? Write the Fixed WAV anyway — some damaged files sound bad without showing a short length. (Dev: resilient decode resumes past bad MPEG frames; multi-part concat trims priming ~576 samples and overlap-adds ~6 ms / 256 samples per seam — R2.1 / R5.9; output is PCM16 WAV, no ffmpeg, original never rewritten.) - SYNC that behaves like a good human, not a robot. One-shot beat snap on the analyzed grid, tempo follow of the partner's pitch fader, then a soft PI phase assist: hysteresis so it never hunts, a slow integral that absorbs slightly-off BPM analysis (the classic "synced but slowly drifting" case), and slew-limited rate moves you can't hear. Release SYNC and phase glue keeps holding the musical offset you jogged in — your mix, not the grid's.
- A waveform well built for beatmatching. Both decks stacked with a shared latency-compensated playhead, downbeat-emphasized beatgrid ticks, and rate-aware windows: both strips scroll at the same pixel speed regardless of pitch, so when ticks line up vertically, the decks are in phase. You see drift before you hear it.
- Engineered like it matters. Strict TypeScript across four workspaces, a typed IPC contract with a channel allowlist, sandboxed renderers, ~200 unit and component tests, Playwright e2e, and hardware-verified checklists for the audio and MIDI layers.
Spec is law: see docs/README.md, docs/ROADMAP.md, docs/CHANGELOG.md.
Brand assets live in brand/ (mark, wordmark, app icon).
StentorDeck is built for the Hercules DJConsole RMX2. Fresh install, empty
database, and Reset to RMX2 defaults always restore the factory RMX2 map
(docs/04-midi-map.md). That map is owner hardware-verified.
Other controllers today
- MIDI Learn (Settings / Dev mode) — bind any ControlId to your hardware.
- Community profiles (Settings → MIDI) — opt-in packs for popular 2-deck gear (e.g. Pioneer DDJ-FLX4, Hercules Inpulse 500). Partial maps; gaps via Learn. Marked community / READY FOR HW VERIFICATION — never claimed booth-ready.
Profiles never auto-apply when you plug a device in (that would silently break an RMX2 booth). Applying a non-RMX2 profile turns LED feedback off (Hercules note echo is wrong for Pioneer); Reset / RMX2 profile turns LEDs back on.
Denied on purpose (would risk RMX2 or v1 scope): auto-switching the factory
map on hot-plug; replacing the RMX2 factory with a “generic” layout; running
Mixxx JavaScript inside the app; scratching / 4-deck / stems as first-class;
softening 14-bit / LSB Learn rules; claiming [HW] PASS without physical
verification. Full deny list: docs/BACKLOG-multi-controller.md.
Taken from the running app (Vite + mocked IPC) via Playwright — not HTML mockups.
Same pack feeds the StentorDeck website: catalog + manifest.json in
docs/screenshots/.
Regenerate after UI changes: npm run docs:screenshots.
Layout design contract (HTML): docs/mockups/MOCKUPS.md.
Header MST / CUE / PHN · waveform well · decks with pitch strip & FX · 7-column mixer (GAIN · kill LEDs · EQ/faders · labels) · library fill.
In-app Help (topbar Help or F1) searches the operator guides in docs/guides/. Library walkthrough: docs/guides/prep-library.md.
Channel curve (Linear / Smooth / Sharp), pitch range, EQ max, auto-gain, crossfader off by default (R2.4).
More Settings tabs (Jog, Library, Display): see docs/screenshots/README.md.
Electron · React 18 · TypeScript strict · MobX · better-sqlite3 · Web Audio · Web MIDI
- Install Node.js 22 LTS once (recommended).
- Double-click
INSTALL.batin the repo root.
That script installs dependencies (Electron ABI for better-sqlite3), rebuilds the native module, creates a Desktop shortcut, and starts the app (packaged .exe if present, otherwise source/dev). Same entry: npm run setup.
Start StentorDeck.bat launches a packaged .exe if present; otherwise it runs INSTALL.bat.
If it fails: close anything locking node_modules, delete that folder, run INSTALL.bat again. Prefer Node 22 — avoid Cursor’s helper Node on PATH (where node must not be under …\cursor\…\helpers\).
No Mac installer — product target stays Windows (R1.1). Willing to experiment from git?
→ docs/guides/run-from-source-macos.md
Short version: Node 22 + Xcode CLT → npm install → npm run rebuild:native → npm start. Expect Plan B audio more often than Plan A; npm run dist still builds Windows only.
npm run dist # NSIS installer — Desktop + Start Menu shortcuts with brand icon
npm run release # same + publish GitHub Release (needs GH_TOKEN) for auto-update
# or quick unpacked build:
npm run dist:dir
npm run shortcut # Desktop StentorDeck.lnk → exe (or Launch-StentorDeck.vbs)Windows packaging embeds build/icon.ico via an afterPack rcedit hook (avoids winCodeSign symlink issues).
npm run icons—scripts/make-windows-icon.mjsconvertsbuild/icon.png(frombrand/) into a multi-sizebuild/icon.icousing electron-builder's bundledapp-builder-bin.npm run build— compiles all four workspaces:shared(tsc),app/main+app/analysis(tsup, incl. both preloads),app/renderer(Vite).- electron-builder (config in
package.json"build"):- rebuilds
better-sqlite3against the packaged Electron ABI; - packs the
dist/outputs +package.jsonintoresources/app.asar, with native modules (**/*.node, better-sqlite3) kept outside the archive viaasarUnpack(native code can't load from inside an asar); - runs the
afterPackhook (scripts/embed-win-icon.cjs) to stamp the icon + version metadata intoStentorDeck.exewithrcedit; - builds the NSIS installer →
release/StentorDeck-Setup-<version>.exe(per-user, choosable install dir, Desktop + Start Menu shortcuts), pluslatest.ymland a.blockmap— the manifest + delta mapelectron-updateruses for in-app updates from GitHub Releases.
- rebuilds
Builds are intentionally unsigned (CSC_IDENTITY_AUTO_DISCOVERY=false, no
cert yet). verifyUpdateCodeSignature is disabled so auto-update still accepts
our own builds. A real code-signing cert is the proper fix later.
On a new machine Windows may show “Windows protected your PC” for
StentorDeck-Setup-*.exe (and sometimes the first launch of StentorDeck.exe).
That is expected until we ship a signed installer — not a virus warning from us.
Bypass (once per download/machine):
- Click More info.
- Click Run anyway.
If the browser blocked the download instead: keep the file → Show more → Keep / Keep anyway.
Do not turn off SmartScreen or Windows Defender for this.
The installed app is single-instance: launching a second copy (or the Setup
shortcut while the app runs — including a dev npm start instance) focuses
the running window and exits.
Double-click StentorDeck on the Desktop. Closing the window shuts down analysis, DB, and MIDI cleanly. Boot shows a short branded splash.
Silent helper: scripts/Launch-StentorDeck.vbs.
| How you run | How you update |
|---|---|
Installed .exe (booth) |
Settings → Check for updates (GitHub Releases), or run a new Setup.exe |
Source / npm start |
UPDATE.bat — not GitHub Desktop |
Details: docs/guides/updating.md.
Publish / release checklist: docs/DEVELOPMENT.md.
npm start # same as npm run devDev starts windowed (STENTOR_WINDOWED=1). Fullscreen like production: STENTOR_WINDOWED=0.
If you see NODE_MODULE_VERSION errors: npm run rebuild:native (or just re-run INSTALL.bat).
npm deprecation warnings: Leftover glob / inflight / rimraf / tar / npmlog / prebuild-install noise is from electron-builder / native tooling (upstream). EPERM on Windows = something locking node_modules.
npm test # unit + component (Vitest)
npm run test:coverage
npm run test:e2e # Playwright end-user (no RMX2)
npm run docs:screenshots # live-app PNGs → docs/screenshots/
npm run lint
npm run typecheck
npm run build
npm run dist:dir # unpackaged win build
npm run dist # NSIS installer → release/See docs/TESTING.md.
| Package | Role |
|---|---|
shared |
IPC contract, settings zod, MIDI/audio pure logic, analysis contract |
app/main |
Electron main, SQLite, scanner/watcher, analysis supervisor, IPC, splash |
app/renderer |
React/MobX UI + audio/MIDI engines + Prep browser |
app/analysis |
Hidden sandboxed BrowserWindow — decode / waveform / BPM / key / loudness (E5); file bytes are read in main and shipped with the job |
Living tracker (mirrors docs/ROADMAP.md). Decision detail: docs/CHANGELOG.md.
Legend: DONE · DOING · TODO · BACKLOG
E1 skeleton → E2 audio [HW ✓] → E3 MIDI [HW ✓]
→ E4 library ⎤
→ E5 analysis ⎦ parallel
→ E6 UI [HW mix]
→ E7 polish
| Epic | Status | When | What landed / what’s left |
|---|---|---|---|
| E1 Skeleton | DONE | 2026-07-18 | Shell, typed IPC, settings, SQLite, workspaces |
| E2 Audio engine | DONE | 2026-07-18 | Dual-deck engine, Plan A/B, cue/PFL, USB rebuild. [HW] PASS. Checklist: docs/E2-HW-CHECKLIST.md |
| E3 MIDI layer | DONE | 2026-07-18 | Decode/map/dispatch/learn/persist/takeover/LEDs. [HW] PASS. Checklist: docs/E3-HW-CHECKLIST.md |
| E4 Library | DOING | 2026-07-18 | Scan/watcher, Prep + Perf browse, roots. Left: large-library soak ACs |
| E5 Analysis | DOING | 2026-07-18 | Pipeline + idle backfill + beatgrid (v3) for SYNC. Left: accuracy harness |
| E6 Decks/mixer UI | DOING | 2026-07-18 | Perf v2: 7-col mixer, dual-zone jog (settings), load reconcile, MST default 30%. Left: curve editor UI, [HW] mix |
| E7 Polish | DOING | 2026-07-18 | Splash + graceful quit + NSIS Desktop/Start shortcuts started. Left: soak, failure drills, MANUAL |
| Time context | Milestone |
|---|---|
| Spec lock | Requirements + docs/01–07; Sync stays SYNC; library sort/duplicates |
| E1–E3 | Shell → audio [HW] → MIDI [HW] |
| E4–E5 | Library + analysis pipeline + beatgrid SYNC |
| E6 Perf v2 | Header outs, deck chrome, 7-col mixer, blue kill LEDs |
| Jog feel | Dual-zone SL-1200 / spinback; live Settings sliders + presets |
| Load / takeover | Pitch/EQ stay live on load; filter/wet adopt hardware; gain after auto-gain |
| Booth safety | MST default 30%; safety limiter threshold −3 dB |
| Packaging start | Branded splash, clean shutdown, npm run dist / shortcut |
- E4 — large-library soak against E4 ACs.
- E5 — Accuracy harness + confidence tuning.
- E6 —
[HW]full manual mix; pitch dead-zone viz; fader-curve settings surface. - E7 — Installer polish, soak, failure drills, MANUAL.
- Owner
[HW]mix pass on RMX2; finish E7 packaging / drills.
v2 Spotify + AI mixmatch — docs/BACKLOG-v2-spotify-ai.md (locked 2026-07-18).
Multi-controller Phase 3 (LEDs / shift / FLX10) — docs/BACKLOG-multi-controller.md. RMX2 factory + community FLX4 / Inpulse 500 profiles already shipped (opt-in).








