Universal Controller MIDI

Core concepts

The mapping editor

A tour of the mapping editor: live controller preview, source/target pairs, curve shaping, and the save/load flow. Where every preset gets built.

Updated

The mapping editor is where every preset, template, and haptic effect in the app gets built — a two-column workshop with the live controller on the left and your binding list on the right. Open it, press a button, watch the SVG light up. That's the whole onboarding.

The live controller

On the left is a real-time render of whatever controller is plugged in. Press a button, the SVG lights up. Move a stick, the dot tracks. Pull a trigger, the bar fills. This is your visual confirmation that the app is reading the device — and that the mapping you just made fires when you expect it to.

The render is updated at 120 Hz off the main thread, so you can stare at it while jamming without dropping events.

The binding list

On the right is the list of bindings. Each row is a single source → target pair: a control on the gamepad on the left, the MIDI output on the right. Click a row to edit it. Click the + to add a new one.

A binding holds five things:

  • Source — a button, stick axis, trigger, or touchpad zone.
  • Target type — note, CC, pitch bend, program change.
  • Target value — the note number or CC index.
  • Channel — 1–16. See MIDI messages for the why.
  • Curve — linear, exponential, S-curve, or custom — shapes the value response.
{
  "id": "kick-on-cross",
  "source": { "type": "button", "name": "cross" },
  "target": { "type": "note", "value": 36, "channel": 1 },
  "curve": "linear",
  "velocity": 100
}

Source types at a glance

Eight source types cover every control on the DualSense. Each one has a default target shape — buttons want notes, axes want CCs — and the editor auto-suggests the right target when you pick a source. Override the default any time you want a weird mapping (a button sending a CC pulse, an axis sending one-shot notes per quadrant).

Source typeValue rangeDefault targetPolling
Button0 or 127Note on/offEvent-driven
Stick axis0–127 (centred at 64)CC120 Hz
Trigger0–127CC120 Hz
Touchpad X/Y0–127CC60 Hz
Touchpad zone0 or 127Note on/offEvent-driven
Gyro pitch/roll/yaw0–127CC200 Hz
Accelerometer0–127CC200 Hz
D-pad0 or 127 per directionNote on/offEvent-driven

Curve shaping

The curve panel is a draggable graph — pull the midpoint up for soft response, down for hard. The X axis is input (0–127), the Y axis is output (0–127). This is where stick and trigger feel gets dialled in.

Custom curves are stored as four control points — input/output pairs that the editor splines between. If you want to inspect or hand-edit them, here's the shape on disk:

{
  "curve": {
    "type": "custom",
    "points": [
      { "in": 0,   "out": 0 },
      { "in": 32,  "out": 18 },
      { "in": 96,  "out": 110 },
      { "in": 127, "out": 127 }
    ]
  }
}

Keyboard shortcuts

The editor is fully keyboard-drivable. Once your hands stop reaching for the mouse, you'll build presets twice as fast. Highlights:

  • Cmd/Ctrl + N — new binding
  • Cmd/Ctrl + D — duplicate selected binding
  • Cmd/Ctrl + L — learn (next gamepad event becomes the source)
  • Cmd/Ctrl + S — save preset
  • Cmd/Ctrl + Shift + S — save as template
  • Tab / Shift+Tab — move between binding fields

Save, load, share

The toolbar across the top has save / load / export / reset. Saved bindings become a preset; renamed and parameterised they become a template. The difference is documented on the presets vs templates page.

Common mistakes

  • Binding the same source twice. The editor lets you do it, but both bindings fire and your DAW sees double events. Use the duplicate warning, don't dismiss it.
  • Forgetting to set the channel. New bindings default to channel 1. If your DAW track is set to a different channel, the mapping silently does nothing. Check the channel column first when nothing fires.
  • Using "Learn" with multiple controllers connected. Learn grabs the first event from any controller. Unplug the others, or set the editor to a specific controller before learning.
  • Picking note targets for analog axes. A stick sweep should be a CC, not a note. A note target on an axis will spam note-on/note-off as you cross 64 — useful for a single mapping, terrible as a default.
  • Saving without naming. Untitled presets pile up. Name them as you go.

Ready to build your first one? Start with map a button to a MIDI note — the 30-second hello-world.

Edit this page on GitHub Updated
ESC

Type to search.