Skip to content

Rendered instrument UI on the shared Affine design language - #38

Merged
user1303836 merged 11 commits into
mainfrom
feature/affine-ui
Sep 28, 2026
Merged

user1303836 merged 11 commits into
mainfrom
feature/affine-ui

Conversation

@user1303836

@user1303836 user1303836 commented Sep 27, 2026 •

Copy link
Copy Markdown
Collaborator

Rebuilds the HDN Ring Modulator editor as rendered matte black hardware on the shared Affine design language. Suppressor adopts the same kit in affinedsp/suppressor#3 (companion PR).

HDN Ring Modulator

Real capture from the test suite: a 110 Hz sine tracked as A2 and locked, with the carrier running at 220 Hz at a 2× rate multiplier, drawn as four sine cycles across two input periods.

This design was chosen from four alternatives (#39, #40 and #41, plus the original design first proposed here). The chosen one, Stealth (#41), is merged into this branch, and the shared kit is reduced to it.

What changed

  • libs/affine-ui (new, identical in both repos): the affine_ui JUCE module (v3.0), bundled OFL fonts, and DESIGN_LANGUAGE.md. The powder-coat panel and the knobs are shaded per pixel at the display's physical scale and cached. A product sets only its screen colour.
  • Editor, 780×480 → 960×560: a black powder-coated panel with colour only on one amber screen, read left to right in signal order.
    • Input: the note and frequency, a tuning bar in cents, and the Signal bar with the Sensitivity mark a detection must reach. LOCK lights only while the carrier actually follows the input. The input reads LISTENING, NO AUDIO or OFF (Manual) as appropriate.
    • Wave: the selected waveform drawn at the frequency the carrier actually runs at, across two periods of the input pitch, so the Rate Multiplier shows as the number of cycles. In Manual mode the window is 10 ms. It stays flat while the effect is dry.
    • Carrier: the running frequency, its note and its ratio to the input; dark while dry.
    • Knobs inside white LED rings under Tracking, Carrier and Output section titles. Rubber Source and Waveform soft keys replace the combo boxes. Controls that don't act in the current source show an unlit activity lamp and a dimmed ring but stay editable.
  • Processor (telemetry only, audio unchanged): publishes currentCarrierHz, the frequency the oscillator actually ran at (0 while dry), and processedBlocks, so the UI never shows a stale reading as live. Previously the UI treated confidence > 0.1 as locked, which could disagree with the DSP's Sensitivity gate and 50 ms hold.
  • Removed: PluginLookAndFeel.*, tests/TestPluginLookAndFeel.cpp, assets/fonts.
  • Tests: new tests/TestEditor.cpp covers theme contrast (including the screen colour), bundled fonts, control-to-parameter mapping, unique focus order, exact entry (commit, cancel, malformed text), single-gesture drags, keys and resets, selector keys, mode presentation, display states, and the processor's carrier telemetry.
  • CI: with HDN_UI_CAPTURE_DIR set, the tests render every display state and scale; CI uploads them as ui-evidence-macOS / ui-evidence-Windows.
  • README: new screenshot and an Interface section. Badge and clone URLs now point at affinedsp/hdn-ringmod, and the local origin remote was updated to match.

The family side by side:

Affine family

Verification (macOS, arm64)

  • ctest: 68/68 pass.
  • pluginval 1.0.4 at strictness 10 reports SUCCESS for the VST3.
  • I didn't run AU validation (auval), because it needs the component installed. The AU wrapper is untouched.
  • The branch history includes the alternatives round: kit 2.0 added four finishes and the last kit commit removes the three that were not chosen. The final diff contains only the Stealth kit.

Vendor the affine_ui JUCE module, its bundled OFL typefaces and the
design language it implements. The folder is identical in every Affine
plug-in and renders knobs, faceplates, meters and displays procedurally
at the display's physical scale.
The editor now shows the frequency the carrier oscillator actually runs
at, zero while the effect is dry, instead of estimating it from the
detected pitch, and treats readings as stale once blocks stop arriving.
Audio processing is unchanged.
Replace the flat editor with the Affine family instrument: a VFD input
display with lock lamp and confidence bar marked at the Sensitivity
threshold, a Nixie counter for the running carrier with a trace of the
selected waveform, calibrated knobs in Tracking, Carrier and Output
frames, and lit Source and Waveform keys. Controls that do not act in
the current source show an unlit activity lamp but stay editable.

Editor tests cover control mapping, focus order, exact entry, gestures,
selector keys, mode presentation, display states and the processor's
carrier telemetry. HDN_UI_CAPTURE_DIR renders every display state, and
CI uploads the captures.
The pitch detector analyses on its own thread and resets when its input
queue overflows. Feeding blocks in a tight loop could overflow it on slow
CI runners, so the carrier telemetry test and the state captures could
see a reset tracker. Pace the audio as a host would and wait for a steady
lock before asserting or capturing.
Add the Broadcast, Hi-Fi and Stealth finishes alongside Laboratory:
hammertone, powder-coat and black-glass faceplates; bakelite and polished
aluminium knob materials, ribbed skirts and LED rings; piano-key, toggle,
polished-square and soft-key buttons; moulded, chrome and flush meter
housings with coloured zones and a centre rest; horizontal ladders;
alphanumeric Nixie tubes; a tuning dial and illuminated legends; jewel
lamps, lit windows, rack ears, name plates, end caps and screen glass.

The design language now describes each finish and shows both products in
all four.
Matte black hardware with LED-ring knobs, soft keys and one amber screen:
the input note, its tuning in cents and the signal against the
Sensitivity mark; the carrier waveform drawn at its running frequency
across two input periods; and the carrier's frequency, note and ratio to
the input.
Describe the Stealth displays and replace the screenshot with a capture from
the editor tests.
Keep the matte black hardware the products use and remove the other three
finishes: their panel textures, knob materials, key styles, meters, tubes,
dials, panel hardware and two fonts. The Stealth values become the kit
defaults, so a product sets only its screen colour.

Add screen helpers for captions, lit numerals and segmented bars, and a
section title for control groups, and move both editors onto them. The
design language is rewritten around the one finish as version 3.0.
The design language now has a single finish, so the notes and screenshot
descriptions no longer name one.
@user1303836
user1303836 merged commit ded345d into main Sep 28, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant