BRUME
v0.9.2
Brume · Reference Manual · rev 0.9.2

Reference
Manual.

A complete description of Brume's synthesis engines, modulation, effects, and Lua scripting surface.

Overview

Brume is a multi-timbral instrument built on a CM5 reference platform. It runs four synthesis engines across four independent parts, each with six voices of polyphony (24 total), an SVF filter per voice, dedicated modulation routing, and a shared effects chain. The entire interface runs on a 10.1-inch touchscreen.

The four engines correspond to four distinct approaches to electronic sound design: a dual-oscillator complex architecture with FM, AM, and wavefolding; an additive harmonic engine with spectral scanning; a triangle-core timbral engine with wave-multiplier shaping; and a granular engine that generates pitched clouds of micro-oscillator grains.

Character

Brume runs four synthesis engines with a shared voice tail (SVF filter, amp envelope, modulation router), so patches stay coherent across very different sources. Each engine has its own mechanism for continuous spectral change: cross-FM feedback in Complex, a scanning window in Harmonic, cascaded wavefolding in Timbral, grain scatter in Granular. No samples sit anywhere in the signal path; every voice is generated from live math.

The lineage worth naming is the Buchla 259 and Serge wavefolder tradition, the DX family’s phase-modulation surface, and the patch-on-a-small-computer approach of Norns and Plaits, rendered in software and unified under a single touchscreen. The default transition shape is Caffeinated, a pseudo-random walk, which sets the bias for the whole instrument: engines reveal themselves over tens of seconds rather than on first press, and loops rarely repeat quite the same way.

Interface

The top menu bar provides access to all pages: the four engine mode tabs (COMPLEX, HARMONIC, TIMBRAL, GRANULAR) on the left, and navigation pages (MOD, MIX, MIDI, SYS, LIBRARY) on the right. Tapping a mode tab selects that engine for editing on the synth page.

Signal path

MIDI IN CHANNEL MAP COMPLEX HARMONIC TIMBRAL GRANULAR MOD MATRIX LFO · ENV · VEL SVF FILTER MIXER LEVEL · PAN · MUTE SEND BUSES SATURATOR CHORUS DELAY REVERB LUA FX SCRIPT FX + MASTER LIMITER · STEREO AUDIO OUT

Complex Oscillator

Brume Complex engine synth page — oscillator parameters, signal flow window, and modulation panel
Complex engine page — click to zoom

◆ Part 1 — Dual oscillator · FM · wavefold

The Complex engine pairs a carrier and modulator oscillator, both capable of continuous waveshape morphing from sine through triangle, sawtooth, and square. The modulator feeds into the carrier through several modulation paths — phase-modulation FM, amplitude modulation, ring modulation, through-zero FM, and hard sync — while a cross-FM feedback path returns the carrier's output to the modulator.

◆ COMPLEX · parameter illustrationdrag sliders
0.10
0.20
3.00
1.20
0.00

Interactive illustration rendered in the browser — the on-device DSP has more subtlety, but the parameter behaviours follow the same shape.

MODULATOR · morph MOD FOLD FM TZFM AM RING SYNC CARRIER · morph + angle XFM · z⁻¹ WAVEFOLDER SVF FILTER OUT

OSC tab — Oscillator waveforms and frequency relationship

ParameterRangeDefaultDescription
CARRIER0 – 10Carrier waveform morph. Sweeps continuously from sine (0) through triangle (0.33), sawtooth (0.66), to square (1.0).
MOD WAVE0 – 10Modulator waveform morph, using the same sine-to-square progression as the carrier.
RATIO0.5 – 163.0Frequency ratio of modulator to carrier. Integer values (1, 2, 3) produce harmonic spectra; non-integer values create inharmonic, bell-like tones.
FOLLOWoff / onoffWhen enabled, the modulator tracks the carrier's pitch with the ratio applied as a Hz offset rather than a multiplier.

MOD tab — Modulation paths

ParameterRangeDefaultDescription
FM INDEX0 – 102.0Phase-modulation FM depth. The modulator's output displaces the carrier's phase, producing sidebands whose density increases with depth.
X-FM0 – 10Cross-FM feedback. The carrier's previous output feeds back into the modulator's phase, creating a self-referential loop with chaotic character at higher values.
AM0 – 10Amplitude modulation depth. Produces tremolo at low modulator frequencies and spectral sidebands at audio rates.
RING0 – 10Ring modulation depth. Crossfades between the clean carrier and the product of carrier and modulator, producing sum-and-difference frequencies with a metallic character.
TZFM0 – 10Through-zero FM depth. Modulates the carrier's instantaneous frequency bidirectionally, allowing it to pass through zero Hz and invert.
SYNCoff / onoffHard sync. Resets the carrier's phase to zero whenever the modulator completes a cycle.

Harmonic Oscillator

The Harmonic engine generates sound through additive synthesis, combining eight individually controllable harmonics with spectral shaping tools. A Gaussian scanning window sweeps across the harmonic series, isolating or blending partials as its center and width change.

Brume Harmonic engine synth page — eight harmonic-level sliders, cyan signal-flow topology with FM OSC → 8 HARMONICS → SCAN WINDOW → SVF FILTER
Harmonic engine page — click to zoom
FM OSC · ratio FUNDAMENTAL H1 H2 H3 H4 H5 H6 H7 H8 TILT ODD / EVEN SPREAD SCAN WINDOW center + width SVF FILTER OUT

SCAN tab — Spectral scanning and waveform morph

ParameterRangeDefaultDescription
CENTER0 – 10.5Position of the scanning window across the harmonic series. At 0 the window centers on the fundamental; at 1 it centers on the 8th harmonic.
WIDTH0 – 11.0Width of the scanning window. Intermediate values produce a Gaussian falloff from the center.
MORPH0 – 10Per-harmonic waveform morph. Coupled to the scan window — harmonics near the center receive more morph.
SPREAD0 – 10Phase randomization between harmonics. Thickens the sound without changing its spectral content.

Timbral Oscillator

The Timbral engine starts from a triangle-wave core and shapes it through a wave-multiplier circuit that transitions from soft saturation to cascaded wavefolding as the timbre control increases. An expanded symmetry parameter tilts the triangle core before it enters the shaper.

Brume Timbral engine synth page — FM OSC, TRIANGLE symmetry-tilt, WAVE MULT with feedback loop, SUB OSC ÷2, SVF filter; amber signal-flow topology
Timbral engine page — click to zoom
FM OSC · linear TRIANGLE · symmetry tilt WAVE MULT · timbre × stages FB · z⁻¹ + SUB OSC ÷ 2 SUM SVF FILTER OUT

SHAPE tab — Wave multiplier and feedback

ParameterRangeDefaultDescription
TIMBRE0 – 10Wave multiplier drive. At 0 the output is a pure triangle. From 0 to 0.3 a soft-clip saturator rounds the peaks; above 0.3 a triangle wavefolder blends in.
SYMMETRY-1 – 10Triangle tilt and asymmetric bias. Positive values stretch the rising slope; negative values produce the inverse.
STAGES1 – 41Number of wavefolding stages. Each stage cascades another triangle-fold pass, densifying the harmonic spectrum.
FEEDBK0 – 10Self-modulation feedback. The oscillator's previous output sample modulates its own frequency, producing growling textures at higher values.

Granular Oscillator

The Granular engine generates pitched clouds of micro-oscillator grains — short bursts of waveform output (1–500 ms) that overlap to produce evolving textures. Unlike sample-based granular systems, Brume synthesizes each grain from scratch.

Brume Granular engine synth page — GRAIN CLOUD with density/scatter, MORPH WAVE with FM sidecar, HANN/GAUSS/TRAP envelope shapes, NORMALIZE 1/√n, SVF filter; magenta signal-flow topology
Granular engine page — click to zoom
MORPH WAVE · sin → tri → saw → sq FM HANN GAUSS TRAP window GRAIN CLOUD · density × scatter DRIFT NORMALIZE · 1 / √n SVF FILTER OUT

CLOUD tab — Grain generation

ParameterRangeDefaultDescription
DENSITY0 – 10.3Grain spawn rate. Maps from 1 to 200 grains per second. Spawn timing includes a 30% jitter.
SIZE0 – 10.2Grain duration. Maps from 1 ms to 500 ms. Each grain's actual length varies by ±20%.
SCATTER0 – 10Pitch randomization per grain. At maximum, each grain's pitch is randomized within ±2 octaves of the fundamental.
SPREAD0 – 10Stereo pan randomization per grain.
DRIFT0 – 10Slow pitch random walk applied to the base frequency. Creates gradual, organic pitch wandering.

SVF Filter & Envelope

Each voice includes a state-variable filter operating in lowpass mode, with a dedicated ADSR envelope that modulates the cutoff frequency. The filter and envelope parameters are identical across all four engines.

ParameterRangeDefaultDescription
CUTOFF20 – 20,000 HzvariesFilter cutoff. Smooth resonant rolloff above this frequency.
RESO0 – 10.1Resonance. Values near 1.0 produce self-oscillation.
ENV DEP0 – 10.3Envelope depth. Modulates cutoff above its static value.

Modulation — LFOs & Step Sequencers

Brume Modulation page — two LFO panels, step sequencer, and assignment routing
MOD page — LFOs, sequencers, and routing assignments

Each of Brume's parts has an independent modulation router with two LFOs and two step sequencers. These four sources can be assigned to any synthesis parameter through the MOD page.

Evaluation formula The raw source value (0–1) passes through the response shape, is centered to ±0.5, then scaled by depth. The resulting offset is added to the parameter's base value and clamped to its valid range.

Shape library · 24 transitions

Brume’s LFOs, step sequencer transitions, and modulation assignment response curves all draw from the same 24-shape library — ported from the Formfactor plugin. Each shape has a descriptive name (shown large) and its engineering enum name (shown below) for scripting and preset editing. The default shape is Caffeinated (ChaosHeavy), a pseudo-random walk chosen as the default because it’s the most musically surprising of the 24.

Mixer

MIX page — four part level faders, master fader, mute/solo controls, and effects panel
MIX page — per-part faders with mute/solo, master, and the effects panel

The MIX page provides a four-channel mixer with horizontal faders for each part (Complex, Harmonic, Timbral, Granular), along with mute and solo controls. Each part’s level defaults to 0.8 and can be adjusted from 0 to 1. Each part also has independent delay and reverb send levels that control how much of the signal reaches the shared delay and reverb buses. A master volume control governs the final output level before the limiter. All level changes are smoothed to prevent clicks.

Effects

The EFFECTS panel on the MIX page provides four processing stages organized as tabbed controls: Saturator, Chorus, Delay, and Reverb. Saturator and Chorus operate as inserts on the dry master bus, processing all parts equally. Delay and Reverb operate as send effects, where each part’s independent send level controls how much signal reaches the effect. This architecture follows the model used in hardware instruments like the Elektron Digitone, where a dry bass line can coexist with a heavily reverbed pad without one treatment bleeding into the other.

Saturator

ParameterRangeDefaultDescription
TYPESoft / Hard / Tape / TubeSoftSaturation algorithm. Soft uses tanh waveshaping; Hard clips at ±1; Tape applies asymmetric soft clipping; Tube adds even harmonics via polynomial distortion.
DRIVE0 – 10Pre-gain into the saturation circuit. At 0 the signal passes clean; at 1 the input is boosted 5× before shaping.
MIX0 – 11Dry/wet blend.

Chorus

ParameterRangeDefaultDescription
RATE0.1 – 5 Hz0.5LFO speed controlling the modulation of the internal delay lines. Left and right voices run at slightly offset rates for stereo width.
DEPTH0 – 10.3Modulation depth. Higher values produce more pronounced pitch variation and wider stereo field.
MIX0 – 10Dry/wet blend.

Delay

The stereo delay supports both free-running millisecond timing and tempo-synced musical divisions. When a sync division is selected, the delay time auto-calculates from the transport BPM. The delay uses cross-channel ping-pong routing with a damping filter in the feedback path to darken successive repeats.

ParameterRangeDefaultDescription
SYNCFREE / MIDI / 1/1 – 1/8tFREETempo sync mode. FREE uses the TIME slider directly. MIDI and the musical divisions (including dotted and triplet variants) derive the delay time from the current transport BPM.
TIME10 – 2000 ms300Delay time in free mode. Overridden when a sync division is active.
FEEDBACK0 – 0.950.3Amount of delayed signal fed back into the input. Values above 0.8 produce long, building repeats.
DAMPING0 – 10.3High-frequency rolloff in the feedback loop. At 0 the repeats stay bright; at 1 they darken rapidly, simulating tape degradation.
MIX0 – 10Dry/wet blend.

Reverb

Four reverb algorithms are available, each built from networks of allpass diffusers and parallel comb filters with damped feedback. All algorithms share the same parameter set; the internal topology and delay lengths differ to produce distinct spatial characters.

ParameterRangeDefaultDescription
TYPEPlate / Room / Hall / SpringPlatePlate (Dattorro): dense, bright, classic studio plate character. Room: shorter delays, clearer early reflections, intimate. Hall: long diffusion chains, expansive tail. Spring: allpass cascade with metallic chirp and resonant character.
PREDELAY0 – 200 ms20Delay before the reverb onset. Separates the dry signal from the reverb tail, preserving transient clarity at higher values.
DECAY0.1 – 82.0Reverb tail length. Controls the feedback coefficient in the comb filter network. Higher values produce longer, more sustained reverberation.
DAMPING0 – 10.4High-frequency absorption in the reverb tail. Low values produce bright, shimmering tails; high values simulate absorptive room surfaces.
MIX0 – 10Dry/wet blend.

MIDI

MIDI page — channel routing, CC mapping with the LEARN inline-capture card, and clock controls
MIDI page — channel routing, CC mapping with LEARN, clock controls

Brume receives MIDI over USB from any class-compliant device — control surfaces, keyboards, sequencers — and from the Meridian USB-C bridge to a host DAW (see below). All sources feed the same engine in parallel, so a controller plugged into a USB-A port and the DAW’s MIDI output over Meridian both reach Brume simultaneously without any routing setup. DIN 5-pin gear connects through any class-compliant USB-to-DIN bridge (e.g. iConnectMIDI4+).

The MIDI page has three sections: channel routing on the left (a part-centric list where each part shows its assigned MIDI channel; tap the channel box to cycle through CH 1–16 or NONE), CC mapping in the middle (the LEARN workflow plus the list of persisted CC→parameter bindings), and the clock controls on the right. Multiple parts can share the same channel for layered playback, and a single channel can be reassigned at any time without stopping playback.

Note-off messages use a promiscuous release strategy: when a note-off arrives on any part, Brume also releases that note on all other parts. This prevents stuck notes when channel assignments change during a performance. MIDI CC messages 120 (All Sound Off) and 123 (All Notes Off) are recognized and release all active voices on the targeted part.

Default routing Channel 1 → Complex (Part 1), Channel 2 → Harmonic (Part 2), Channel 3 → Timbral (Part 3), Channel 4 → Granular (Part 4). Channels 5–16 are unassigned by default.

CC Mapping — LEARN workflow

The CC MAPPING panel binds incoming MIDI CCs to Brume’s synthesis parameters. Brume ships with sensible defaults — CC 1 → Filter Cutoff, CC 2 → Filter Resonance, CC 7 → Master Volume, CC 11 → Filter Envelope Depth, plus a few part-specific bindings — and the LEARN workflow lets you add or override any binding directly from the touchscreen. No keyboard required.

ActionBehavior
Tap LEARNArms capture mode. The button glows orange and an inline card appears at the top of the binding list reading “LISTENING FOR MIDI CC… (turn a knob or tap LEARN to cancel)”.
Move a knob / faderCapture is continuous — the card updates to show the most recent CH / CC / value, so you can wiggle the intended control and confirm Brume sees the right one. Useful when DAW transport sync is also emitting CCs in the background.
Pick a destinationThe card’s DESTINATION grid lists every parameter for the part the captured CC’s channel routes to (or every FX-slot parameter when an FX target is picked). Tap one to select; it highlights in the part color.
Tap SAVE BINDINGWrites the binding and disarms capture. The new mapping takes effect immediately.
Tap CANCELDiscards the in-progress capture without writing anything.
Tap RESETTwo-tap confirm. Wipes all CC bindings, FX bindings, and channel routing back to factory defaults. Use when an experiment goes sideways.
Persistence All CC bindings — including channel routing and FX-slot bindings — are written atomically to ~/.brume/cc-bindings.json on every change and reloaded at startup. The file is human-readable; advanced users who need keyboard-typed CC numbers (touchscreen-only LEARN doesn’t expose a number pad) can edit it by hand over SSH.

Transport & Clock

The CLOCK window on the MIDI page controls Brume's internal transport, which drives tempo-synced delay divisions and step sequencer timing. Three clock modes determine how the transport derives its tempo:

ModeBehavior
OffInternal clock at the configured BPM. No MIDI clock is sent or received.
MasterInternal clock at the configured BPM. Brume sends MIDI clock (24 PPQN) to connected devices.
SyncBrume syncs to incoming MIDI clock messages. The BPM is estimated from the tick interval and smoothed to avoid jitter. MIDI Start, Stop, and Continue messages are recognized.

The BPM slider ranges from 20 to 300 and affects all tempo-dependent features: delay sync divisions, step sequencer beat triggers, and future arpeggiator patterns. When the clock is in Sync mode, the BPM display shows the estimated tempo from the incoming MIDI clock source.

Controllers

Brume supports external hardware control surfaces through two independent paths. Recognised surfaces are identified by their USB / ALSA port name on connect and get a built-in binding tailored to the actual Brume UI, with no configuration step. Any other MIDI controller can still be bound through the MIDI Learn flow on a CC-by-CC basis. The two paths coexist — a recognised surface does not block Learn from working on other controllers connected at the same time.

The tradeoff: a built-in binding covers the full surface out of the box but is fixed by the firmware; MIDI Learn is fully user-defined but scales one CC at a time. Power users can also reach the Lua scripting layer (see Extending Brume with Lua) to define per-CC behaviour that neither path provides.

Supported surfaces

The Korg nanoKONTROL2 is the shipped reference controller. Brume detects it on connect by matching the string nanoKONTROL2 in the ALSA port name, then routes its events around the MIDI Control Matrix directly to the UI, where a screen-follows binding maps every control to a current action. Because the binding follows what is on screen, switching engines or sub-tabs silently rebinds the knob row to the new visible parameters.

Full factory-preset mapping — CC numbers + per-control action
ControlCCAction
Top-row knobs 1–816–23First eight parameters of the currently-visible sub-tab on any engine. Tabs with fewer than eight params leave the higher knobs idle. Continuous value, no press edge.
Faders 1–40–3Mixer level for Complex / Harmonic / Timbral / Granular respectively. Mirrors the MIX page fader per strip; changes are reflected on the MIX page in real time.
Faders 5–84–7Reserved.
S buttons 1–432–35Exclusive solo toggle for Complex / Harmonic / Timbral / Granular. Pressing S on part N mutes the other three parts; pressing the same S again un-solos. Press edge only.
M buttons 1–448–51Per-part mute toggle. Press edge only.
S / M buttons 5–8, R 1–836–39, 52–55, 64–71Reserved.
Track ◄ / ►58 / 59Cycle active engine mode in menu-bar order (Complex → Harmonic → Timbral → Granular, wraps in both directions). Press edge only.
Marker ◄ / ►61 / 62Cycle the active engine’s sub-tabs (e.g. OSC → MOD → FOLD … on Complex). Press edge only.
Marker ◎60Reserved.
Cycle46Reserved.
Transport (Play / Stop / Rec / FF / Rew)41–45Reserved.
Factory CC Mode required The nanoKONTROL2 must be in its factory CC Mode (the default preset) for the CC numbers above to match. If the unit has been edited with Korg Kontrol Editor into a different profile, the numbers will differ; the workaround is to reset the device to factory defaults rather than editing Brume’s binding.

The Novation Launch Control XL 3 is a second planned reference surface (see the BOM entry on the landing page) and is in development. Once integrated it will expose a deeper mapping appropriate to its 24-encoder, 8-fader, 16-pad layout: each engine likely gets a full page of encoders with the Page Up / Down buttons handling tab switching, and the 16 pads become clip launchers or per-part arm targets. The detection hook will follow the same ALSA port-name pattern.

Bring your own controller

Any controller not in the recognised-surfaces list works through MIDI Learn on the MIDI page. Tap LEARN, turn a knob or press a button, then pick a destination from the binding card. Each binding persists until removed. Because Learn runs at the Control Matrix layer, it is completely independent of the engine on screen and of the recognised-surface path.

The flow has two states, both shown below on a cropped view of the CC MAPPING panel:

MIDI Learn — LISTENING state. An amber banner reads 'LISTENING FOR MIDI CC… (turn a knob or tap LEARN to cancel)'. The LISTENING… button at the bottom glows amber; RESET sits next to it.
1. Tap LEARN — the card enters LISTENING. Any incoming CC on the active channel captures.
MIDI Learn — DETECTED state. An amber-framed card shows 'DETECTED · CH 1 · CC 16 · val 77' with a DESTINATION grid of parameter names below (ModulatorMorph highlighted). CANCEL and SAVE BINDING buttons at the bottom.
2. CC captured — the card flips to DETECTED, showing the channel, CC number, and value, with every bindable destination for the active engine. Pick one and SAVE BINDING — the mapping lands in the list below and persists to ~/.brume/cc-bindings.json.
Where LEARN bindings live Every binding is serialised to ~/.brume/cc-bindings.json on the device as part of the full Control Matrix. The file is written after each LEARN save, binding removal, or reset, and read at startup; a missing or malformed file is treated as “no bindings yet” (the defaults load and startup continues). The file is plain JSON, so it can be inspected or hand-edited for bulk operations — for example, exporting a working set of bindings for backup or sharing between devices.

To add a new recognised surface at the code level, three small edits cover it:

FileChange
crates/midi-io/src/lib.rsIn start_with_script_tx, extend the port-name match block that sets controller_kind. Add a case matching the new surface’s ALSA port name (substring, case-insensitive) and set a unique kind string such as "LaunchControlXL3".
crates/ui-app/src/ui.jsIn window._onControllerCc / window._onControllerNote, add a branch keyed on the kind argument. The screen-follows pattern (knob index → _tabParams[i]) is reusable; any extra controls follow the same structure as the existing nanoKONTROL2 branches.
brume-web/docs.htmlAdd a mapping table under Supported surfaces for the new controller so users can see what every control does.

The protocol layer (crates/app-protocol/src/lib.rs) already carries EngineToUi::ControllerCc and EngineToUi::ControllerNote with a kind field, so no additional message variants are needed for the common case of routing a new surface through the existing screen-follows logic. Custom behaviour that escapes the screen-follows model — a pad grid triggering chords, for example — is easiest to implement directly in the UI branch that handles that surface’s kind.

Meridian — USB-C to your DAW

A line you cross. Meridian is Brume’s integrated audio-and-MIDI bridge to a host computer — comparable in role to Elektron’s Overbridge for the Elektron range, but built on open USB class-compliant standards so it works on Mac, Windows, and Linux without proprietary drivers. A single USB-C cable carries 8-channel audio out, bidirectional MIDI, and MIDI clock simultaneously.

In a DAW, arm one or more audio tracks with Brume’s capture as the input, route MIDI out from a track to Brume’s MIDI port, and Brume behaves as a first-class external instrument just like a Prophet or Moog patched into a multi-channel audio interface — with the additional convenience that it’s all on a single cable.

Incoming notes, CC, and MIDI clock over Meridian are parsed identically to other MIDI sources — they flow through the channel map, respect CC bindings, and drive the Sync clock mode. Audio output is structured for multi-track DAW workflows by default.

Per-part stems (8 channels)

Each of Brume’s four parts writes its own dry mono signal to a dedicated stereo channel pair on the USB capture endpoint:

ChannelsSource
1 – 2Complex (dry, pre-FX, mono duplicated to L/R)
3 – 4Harmonic (dry, pre-FX, mono duplicated to L/R)
5 – 6Timbral (dry, pre-FX, mono duplicated to L/R)
7 – 8Granular (dry, pre-FX, mono duplicated to L/R)

Stems are dry — no master saturation, chorus, delay, or reverb. The intent is that DAW users already have better plugin FX than anything Brume ships internally, and recording dry preserves total flexibility. Brume’s master FX chain still computes for the local monitoring path (HDMI / DAC) so your touchscreen monitoring still sounds finished, but the USB stems are clean. The SYS page includes a compact channel-mapping reference (Ch 1-2 • Complex / 3-4 • Harmonic / 5-6 • Timbral / 7-8 • Granular) so you can cross-check your DAW’s input picker without leaving the device.

macOS channel labels Apple’s class-compliant USB audio driver labels Brume’s eight capture channels with spatial-position names (Front Left, Front Right, Front Center, LFE, Back Left, Back Right, Front L of Center, Front R of Center) instead of per-part names. This is a class-compliant limitation, not a Brume choice. The fix is a one-time channel rename in your DAW’s I/O panel (Bitwig, Logic, Ableton, Reaper all support it) which then persists across sessions.

The mapping between channel pair, Brume part, and the spatial label the DAW will display:

Channel pairBrume part — DAW spatial label
1–2 Complex — Front L / R
3–4 Harmonic — Front Center / LFE
5–6 Timbral — Back L / R
7–8 Granular — Front L / R of Center

Use this when wiring input tracks in the DAW, or as the source of truth when performing the one-time channel rename to “Complex”, “Harmonic”, and so on. The same mapping is also available on the device itself in the SYS page, collapsed to save space.

macOS aggregate setup Apple’s driver splits bidirectional devices into separate input and output entries in Core Audio (you’ll see “Capture Inactive” and “Playback Inactive” in Audio MIDI Setup until something opens them). If you have another audio interface and want Brume’s channels alongside your existing I/O, create an Aggregate Device that combines Brume’s capture half with your main interface (e.g. MOTU, RME) and point your DAW at the aggregate. If Brume is your only interface, no aggregate is needed.

Meridian expands in capability over firmware releases. Already shipped: 8-channel per-part stems, bidirectional MIDI with clock, the channel-mapping SYS reference. Active follow-ons: a USB-NCM virtual network interface for the brumectl companion CLI, optional stripping of the UAC2 Feature Unit so the macOS volume slider disappears for bit-perfect passthrough.

Library

The LIBRARY page provides preset storage and recall for each engine. Presets capture all oscillator, filter, and envelope parameters for a single part and are stored as JSON files on the device’s filesystem, organized by engine type. Mode tabs at the top of the library page switch between the Complex, Harmonic, Timbral, and Granular collections.

Tapping SAVE captures the current state of the active engine and writes it to disk using an atomic write-then-rename operation that survives unexpected power loss. Tapping a preset name in the list loads its parameters into the corresponding engine and switches the display to that engine’s synth page. Presets can be deleted with the × button beside each entry.

Storage location ~/.brume/library/{complex,harmonic,timbral,granular}/

The preset format is versioned and uses optional fields for future expansion. Current presets store oscillator and filter parameters; future versions may include modulation scenes, effects chain state, and multi-part combinations without breaking compatibility with existing files.

System

System page — audio output, channel mapping, MIDI, hardware diagnostics, and display info
SYS page — audio output selector, Meridian channel mapping, MIDI, hardware diagnostics, display

The SYS page is Brume’s diagnostic and configuration surface. Every value on the page is read live from the running system — no hardcoded numbers. Plug in a different display, swap controllers, change sample rate, switch audio outputs, and SYS reflects it immediately. Sections are accent-colored: green = audio, cyan = MIDI, orange = system, magenta = display.

Audio Output

The audio-output section picks where Brume’s master mix lands. Brume enumerates every ALSA card on the device — the USB Meridian gadget, the HDMI output through the touchscreen speakers, any DAC hat, plus any USB audio interface plugged into a USB-A port — and renders one row per detected output. The active device shows in the section accent color with a filled dot and an “ACTIVE” label; alternate devices render below as tappable “OPTION” rows. Tapping an option tears down the current audio stream and reopens on the chosen device with a brief (~100–200 ms) silence gap. The choice persists to ~/.brume/settings.json and is restored at startup.

Default vs. fallback First-boot default is Meridian (the USB-C gadget). If the persisted device is missing on a later boot (e.g. you persisted an HDMI panel that’s not currently connected), Brume falls back to the first available output and logs a warning. The choice stays pointed at the missing device so reconnecting it picks back up where you left off.
CHANNELS — Meridian stem → DAW spatial label

On-device recap of the mapping between the eight Meridian stems, their Brume part, and the spatial-position label Apple’s class-compliant UAC2 driver shows in the DAW. The full treatment lives in Meridian.

Channel pairBrume part — DAW spatial label
1–2 Complex — Front L / R
3–4 Harmonic — Front Center / LFE
5–6 Timbral — Back L / R
7–8 Granular — Front L / R of Center

SAMPLE RATE shows the actual rate the audio backend opened the device at — 48 000 Hz on Meridian, HDMI, and any modern audio interface. FORMAT shows the engine’s internal sample format.

MIDI

DEVICE shows the connected MIDI input by its OS-reported name (e.g. nanoKONTROL2). PORTS lists every MIDI port currently feeding the engine, joined with “ + ” when multiple sources are attached — a USB control surface and Meridian’s f_midi endpoint commonly run side by side. With no MIDI device connected, both rows show “—”.

Hardware

Hardware diagnostics for the CM5 reference platform. TEMPERATURE reads from the CM5 thermal sysfs and updates once per second. MEMORY shows the in-use resident memory for the Brume process. UPTIME is system uptime since boot. ENGINE reports the configured polyphony layout (4 parts × 6 voices = 24 total).

Display

RESOLUTION is detected from the connected monitor at startup via GDK and used to compute the auto-fit zoom level — Brume is canvas-designed against a 1024×600 logical resolution and auto-scales to whatever panel you plug in (the reference 1920×1200 touchscreen runs at scale 1.875). FPS shows the animation frame-rate cap. TOUCH reads the connected touch input device’s OS-reported name — useful when troubleshooting input issues or confirming the touchscreen probed correctly at boot.

BRUME_UI_SCALE override If the auto-fit scale isn’t what you want (e.g. you want pixel-doubled GEM aesthetic on a 1080p panel), set BRUME_UI_SCALE=2.0 in the environment before launching Brume. SYS’s RESOLUTION row still shows the panel’s native size; the override only affects the UI zoom multiplier.

Extending Brume with Lua

Brume Scripting page — folder tree browser, Lua FX parameters, and interactive console
SCRIPT page — folder tree, Lua FX controls, interactive console

Brume embeds a Lua 5.4 scripting engine. Scripts are loaded from ~/brume/scripts/ and managed through the SCRIPT page.

API reference

-- Set any of the 52 synthesis parameters
brume.set_param(part, name, value)

-- Trigger notes; velocity is 0.0–1.0
brume.note_on(part, note, velocity)
brume.note_off(part, note)

-- Chord and scale helpers
local notes = brume.chord(note.C4, "maj7")

Coroutine clock

clock.run(function()
  while true do
    brume.note_on(brume.TIMBRAL, note.C3, 0.4)
    clock.sync(1/4)  -- wait a quarter note
    brume.note_off(brume.TIMBRAL, note.C3)
    clock.sync(1/4)
  end
end)
Hot-reload If a loaded script file is modified on disk, Brume detects the change within 2 seconds and automatically reloads — calling cleanup() on the old version and init() on the new one.

Brumectl — companion CLI

brumectl is the host-side companion command-line tool for Brume. Everything the device can’t do for itself — flashing a blank CM5 from a raw eMMC state, probing live status, opening a maintenance shell, watching device vitals, pushing OS updates — lives here. It is a single Rust binary distributed alongside the instrument; you install it on the workstation you already use to power the device over USB-C. The status, shell, and watch verbs work on any Unix host; the flash wizard currently requires macOS (it shells out to diskutil and ioreg), with a Linux port planned.

The tool is scoped narrowly. It is not a general-purpose Raspberry Pi utility — every subcommand assumes the connected device is a Brume, and authorization is established by physical possession of the USB-C cable rather than any account or token. The default invocation drops into an interactive ratatui wizard for first-boot flashing; the other subcommands are one-shot SSH-backed probes designed to feel like local commands.

Commands

CommandStatusDescription
flashshippedDefault subcommand. Interactive ratatui wizard that walks you through flashing a blank CM5 eMMC over rpiboot: gathers WiFi credentials, hostname, SSH public key; writes the image; seeds the boot partition; verifies post-boot. Requires sudo.
statusshippedOne-shot SSH probe that reports firmware version, kernel, uptime, memory and temperature, the Brume process state, and network interfaces (eth0 + wlan0). Falls back to ARP-scan discovery when mDNS resolution fails.
shellshippedPass-through SSH shell to the connected device. Honours $BRUME_HOST and $BRUME_SSH_KEY as well as the global --host and -i flags.
watchpartialLive three-panel ratatui dashboard: device vitals (working), console stream (stub), script watcher (stub). The console and watch panels light up once the device-side logging socket lands.
updateplannedPush a signed image bundle (Phase 2) or app tarball (Phase 1) to the connected device, with A/B slot management and rollback on boot failure. Channels: stable and beta.
logsplannedTail Brume’s journal or /var/log/brume.jsonl over SSH; will also feed the watch dashboard’s console panel.
config get / setplannedRead and write user-facing config (WiFi, hostname, MIDI channels, audio routing) without a re-flash.
recoverplannedForce boot into the read-only recovery partition. Phase 2 only.
channelplannedSwitch update channel (stable / beta); each channel is gated by a separate signing key.
doctorplannedDiagnostic mode — checks Audio MIDI Setup, USB-NCM enumeration, Meridian UAC2 endpoint visibility, and the like.

Build & install

# From a clone of the brume repo
cargo build --release -p brumectl

# Resulting binary
./target/release/brumectl status

A Homebrew tap (brew install aftertonesignal/tap/brumectl) and direct GitHub release downloads are planned but not yet live. Until then the cargo build is the canonical install.

How it talks to the device

Brume exposes a USB Network Control Model (NCM) interface, so the moment you plug it into your Mac it appears as a USB-Ethernet peer with a stable link-local address and announces itself as brume.local over Bonjour on that interface only. Every brumectl subcommand other than flash is a thin layer over SSH to that address — no bespoke protocol, no API tokens, no pairing flow. The flash subcommand is the exception: it uses rpiboot to talk to the bare CM5 over USB mass-storage before any operating system is on the device, then hands off to SSH once the first boot completes.

Trust model Authorization is established by physical possession of the USB-C cable. brumectl never connects over WiFi or the open internet, never reads or writes credentials beyond the SSH key already on your Mac, and binds brume.local exclusively to the USB-NCM interface. If you can plug it in, you can manage it; if you can’t, you can’t.

End of manual · rev 0.9.2 · Aftertone & Signal