← ALL MANUALS Control Forge — Manual
CB Sounddesign
Web MIDI control surface
Version 1 · Operator's manual

Control Forge

Build a MIDI control surface in the browser, wire every element to real hardware, then play it. This manual covers the whole interface, panel by panel, and the workflows that hold it together.

Requires
Chrome, Edge or Opera. Web MIDI is not available in Safari or Firefox.
Serve it
python3 -m http.server 8000 — SysEx needs a served page, not a file URL.
On first load
Allow the MIDI and SysEx prompt. Refuse it and every message type still works except SysEx.
Section one

The window at a glance

Five zones, fixed in place. The centre is your surface; everything around it either builds that surface or plays it.

CONTROL FORGECB SOUNDDESIGN · WEB MIDI
OUTIAC Bus 1 IN— none —
Edit Perform Grid
LFO CLOCK90 Run Panic
1
ADD CONTROL
Knob Fader Pad XY
SNAPSHOTS
MOTION
Rec Play
2
Cutoff
79
3
CONTROL
NAMECutoff
COLOUR
MESSAGECC (7-bit)
CC NO.74
RANGE0127
EXTRA TARGETS
CC71Ch 1
MODULATION
LFO onSine
4
LOG 21:04:11 Web MIDI ready (SysEx enabled).   21:04:22 Snapshot 2 stored. CUTOFF = 79
5
Figure 1 — The five zones of the window
1
Header — ports, mode, grid size, pages, LFO clock, panic.
2
Left rail — build and perform tools: palette, snapshots, motion, files.
3
Surface — the grid your controls live on.
4
Inspector — every setting of the one selected control.
5
Log & readout — timestamped events on the left, last value sent on the right.
Section two

How to use it — first surface in ten steps

  1. Open the page in Chrome and allow the MIDI prompt. The log should read Web MIDI ready.
  2. Choose your destination in Out — a hardware port, or a virtual bus into your DAW. Choose an In port too if you want MIDI learn or motorised feedback.
  3. Stay in Edit mode. Optionally press Load demo at the bottom left to see a finished surface before building your own.
  4. In Add control, click a type — say Knob. The header of that panel shows place Knob; the button stays lit until you click it again.
  5. Click an empty grid cell. The control appears at its default size, snapped to the grid, and is selected. New knobs are auto-assigned the next free CC number.
  6. Drag the body to move it, drag the red corner triangle to resize it. Right-click, or press Delete, to remove it. Ctrl/Cmd-Z undoes.
  7. In the Control inspector on the right, give it a name, a colour, a channel and a CC number. Or press Listen under MIDI learn and move the matching control on your hardware.
  8. Repeat until the surface is built. Use Page + for a second bank; use Size and Cell to change the grid and the physical size of everything on it.
  9. Switch to Perform. Dragging now sends MIDI instead of moving controls. Send the whole surface once with Send every value so the receiving instrument matches what you see.
  10. Press Export .json to keep the surface. Import brings it back on any machine.
The one rule to remember
Edit mode moves controls and never sends MIDI. Perform mode sends MIDI and never moves controls. Almost every "nothing is happening" moment is the wrong mode.
Section three

Header — what each item does

Out
The global MIDI destination. Individual controls can override it in the inspector's Port field.
In
The source for MIDI learn and for Follow input. All connected inputs are listened to; the selector is a record of which one you meant.
Edit / Perform
Build or play. In Edit the cursor is a move cursor and resize handles appear; in Perform the surface is live.
Grid
Shows or hides the cell lines. Snapping stays on either way.
Cell
Pixel size of one grid cell, 24 to 96. This is your zoom: everything scales with it. 44 is the default; 64 and up is comfortable on a touchscreen.
Size
Columns × rows, 4 to 32 each. Shrinking the grid does not delete controls that fall outside it, but they can no longer be dragged back in until you grow it again.
Page
Banks of controls sharing one grid. Click to switch, double-click a page button to rename it, + adds, removes the current page. One page always remains.
LFO clock
Tempo in BPM, 20 to 300. Drives every synced LFO and the motion recorder's bar lengths.
Run
Master start/stop for all LFOs on the current page. Individual LFOs also have their own On switch.
Panic
Sends All Sound Off and All Notes Off on all sixteen channels of every port in use, and releases held pads. Bound to the Escape key.
Section four

The eleven control types

Each type has a default footprint in cells and a default message. Both are free to change afterwards — a Pad wired to CC and a Knob wired to Note are perfectly legal.

Knob
2×2 · CC
Fader ↕
1×4 · CC
Fader ↔
4×1 · CC
Button
2×1 · toggle
Pad
2×2 · note
XY pad
4×4 · 2 CCs
Encoder
2×2 · relative
123
Switch
3×1 · CC steps
Meter
1×4 · input only
3× 70%
Macro
2×2 · targets
Filter
Label
3×1 · silent
Figure 2 — Control gallery, with default footprint and default message

Playing them in Perform mode

Knob, encoder,
macro, fader ↕
Drag up and down. Hold Shift for a quarter-speed fine drag. The mouse wheel also works — Shift makes it ten times finer.
Fader ↔
Drag left and right.
Button, pad
Click. In Toggle behaviour it latches; in Momentary it holds only while pressed. A key trigger does the same thing from the keyboard.
XY pad
Absolute — the dot jumps to the pointer. X sends the CC number, Y sends the Second CC, both 7-bit.
Switch
Click a segment. The position count follows the Detents field; the value is spread evenly across the range.
Meter, label
Not touchable. A meter displays incoming CC values on its channel; a label is decoration and sends nothing.
Section five

Inspector — every field

The right rail always shows the single selected control. Fields appear and disappear with the message type, so you only ever see what applies.

Name
Shown above the control, and used as the text of a Label.
Colour
Six swatches — cyan, violet, red, amber, green, white. Colour is grouping, nothing more; use one per section of the surface.
Port
Per-control output override. Leave on Follow global out unless this control belongs to a different instrument.
Channel
1 to 16.
Message
CC 7-bit, CC 14-bit pair, NRPN, RPN, Note, Program change, Pitch bend, SysEx template, or None. None makes the control silent on its own — the right choice for a pure macro.
CC number
0–127. For a 14-bit pair this is the MSB; the LSB is automatically CC number + 32.
Second CC
XY pads only — the vertical axis.
Param
NRPN/RPN parameter number, 0–16383.
Note / velocity
Note number with its name shown alongside, and a fixed velocity 1–127.
SysEx hex
A byte template in hex, starting F0 and ending F7. Write vv where the 7-bit value goes, or VV for a 14-bit MSB/LSB pair. Bad templates are reported in the log and nothing is sent.
Checksum from
Byte index where a Roland-style checksum starts. −1 disables it.
Range
Value at minimum and value at maximum. Setting min above max inverts the control — a legitimate move.
Curve
Linear, Exponential (slow at the bottom), Logarithmic (fast at the bottom), or S-curve (soft at both ends).
Detents
Number of discrete steps; 0 is smooth. On a Switch this also sets how many segments it has.
Behaviour
Absolute sends the value. Relative sends increments for endless encoders. Toggle latches; Momentary holds.
Encoder format
How increments are encoded: two's complement, binary offset around 64, or signed bit. Match your instrument's manual.
Key trigger
Press Grab, then any key. That key now fires the control from anywhere in the page.
Feedback
On by default: matching incoming CCs and notes move this control so the surface tracks your instrument.
Lock
Protects the value from snapshot recall, morph, randomize and motion playback. Manual moves still work.
MIDI learn
Press Listen, then move a control on your hardware. The first CC or note received sets this control's message, number and channel.
Duplicate / Delete
At the foot of the rail. Duplicate places a copy one width to the right, keeping every setting. Ctrl/Cmd-D does the same.
Section six

Signal path — value to bytes

Knowing the order of operations explains most surprises: why an LFO seems shallow, why detents and curve interact, why a macro target ignores the parent's range.

Gesture
drag · wheel · key · motion · snapshot
+ LFO
depth 100% = ±50% of travel
Detents
quantise to N steps
Curve
lin · exp · log · S
Range
min…max, 7 or 14 bit
Primary message
one message on this control's port and channel · repeats suppressed unless forced
Extra targets
each re-maps the same gesture with its own number, channel, range and curve
Figure 3 — Order of operations from gesture to MIDI bytes

Extra targets and macros

Any control can drive several destinations. Press Add target and set message type, number, channel, minimum, maximum and curve. Targets take the gesture after quantising but map it themselves, so one knob can open a filter while closing a drive, each on its own curve.

For a macro that only drives targets, set Message to None, or place the Macro control, which starts that way. Its readout shows the number of targets and the percentage of travel.

Section seven

Modulation, snapshots, motion

LFO — per control

Every control has its own LFO. Switch it On, pick a shape — sine, triangle, ramp, square, sample & hold, random walk — then either Sync to the header BPM at a division from 8/1 down to 1/32, or leave Sync off and set a free rate in hertz. Depth is how far it swings around the control's current position; Phase offsets it so several LFOs can run in formation. A modulated control is outlined in violet. Nothing moves until the header's Run is lit.

Snapshots — eight per page

Shift-click a numbered slot to store every value on the page; click it to recall. Stored slots are lit. Recall sends immediately, skipping locked controls. Snapshots are matched to controls by identity, so they survive renaming and rearranging but not a re-import.

Morph A→B glides from one snapshot to another over the time you set, in an eased ramp, streaming every intermediate value. Use long times for slow transitions and short ones for a snap with a tail. Randomize nudges every unlocked continuous control by up to the percentage set; note controls are left alone. Send every value forces the whole page out, which is how you re-sync an instrument that was switched on late.

Motion recorder

Press Record and move controls: every gesture is captured with its time. Recording implies play, so the loop starts immediately. Press Record again while it loops to overdub on top. Loop length is one to sixteen bars at the header tempo, or Length of take to let the first pass define the loop. The progress bar shows the playhead; Erase moves of selected control removes one control's automation and leaves the rest.

Layering the three
Motion playback writes values, the LFO adds to them, and locked controls ignore both. A pad on a key trigger, a filter on a four-bar motion loop and a slow synced LFO on the reverb send is a complete performance patch with no sequencer involved.
Section eight

Files, pages, undo

Export .json
Writes the whole surface — all pages, controls, targets, LFOs, grid and tempo — to a file named after the surface. Values themselves are not stored; snapshots are not stored.
Import
Replaces the current surface. Export first if you care about it. A file that is not a Control Forge surface is refused with a message in the log.
Load demo
Builds a full example page — filter knobs, an ADSR fader bank, an XY space control, drum pads, a mode switch, a relative bank encoder, an input meter and a three-target macro. The fastest way to see the whole feature set at once.
Clear page
Empties the current page only. Undoable.
Undo
Forty steps of structural history: adding, moving, resizing, deleting, duplicating, clearing, page changes. Values, LFO settings and inspector edits are not on the undo stack.
Surface name
Used as the export filename.
Section nine

Keyboard and mouse

Esc
Panic — all notes off
Ctrl/Cmd-Z
Undo
Ctrl/Cmd-D
Duplicate selection
Delete
Remove selection (Edit mode)
Shift-drag
Fine adjust, quarter speed
Shift-wheel
Fine adjust, one tenth of a step
Right-click
Delete a control (Edit mode)
Shift-click slot
Store a snapshot
Double-click page
Rename a page
Any bound key
Fires its control, with proper release
Section ten

When something goes wrong

No ports in the lists
The browser has no Web MIDI, the prompt was refused, or nothing is connected. The log says which. Safari and Firefox will never work.
Dragging moves controls instead of playing
You are in Edit mode. Press Perform.
Values move on screen but nothing arrives
No Out port chosen, or the control's own Port points at something else. Check the readout at the bottom right — if it changes, the surface is working and the routing is not.
SysEx sends nothing
Either SysEx was refused on load — reload and allow it — or the template does not parse. It must begin F0 and end F7.
A control will not respond to anything
It may be locked, or it is a Meter or Label, which are not playable.
A note is stuck
Escape, or the Panic button.
Controls drift on their own
An LFO is running, or motion playback is looping. The header Run button and the Motion Play button are your two suspects.
Appendix

What is actually sent

Bytes per message type, with n as the zero-based channel and v as the mapped value.

CC
Bn cc v
CC 14-bit
Bn cc msb then Bn cc+32 lsb
NRPN
Bn 99 pmsb · Bn 98 plsb · Bn 06 vmsb · Bn 26 vlsb
RPN
As NRPN, with controllers 101 and 100
Note
9n note vel on press, 8n note 00 on release
Program change
Cn v
Pitch bend
En lsb msb, full 14-bit range
Relative
A single CC per detent of movement, encoded per the Encoder format field
Panic
Bn 120 00 and Bn 123 00 on all sixteen channels of every port in use
CB Sounddesign · Control ForgeOperator's manual · v1