
Midi Router Client
Create routes from anywhere to anywhere
Midi Router Client is an advanced, cross-platform tool designed to route and manipulate MIDI signals in real time. It allows users to create virtual MIDI ports, map MIDI events (e.g., CC to pitch wheel), monitor inputs, and build custom controls like program change dropdowns—all with minimal latency
Homepage: https://sourceforge.net/projects/midi-router-client/
Github and support: https://github.com/shemeshg/MidiRouterClient
Installation Guide
Windows
Install via winget:
winget install Shemeshg.MidiRouterClient
macOS
Install via Homebrew:
brew install --cask midi-router-client
codesign --force --deep --sign - /Applications/midi-router-client.app/
xattr -c /Applications/midi-router-client.app/
Note: macOS requires manual code signing and removal of extended attributes to ensure proper execution.
Linux
Prebuilt .zip
and .deb
packages are available, targeting the oldest supported Ubuntu LTS at the time of release.
⚠️ Additional Notes
- Distributed binaries are not code-signed.
- The macOS cask may be relocated to a different tap in the future due to a
deleted <date>: unsigned
tag.
Configuration
The configuration includes essential information such as:
-
Connected Inputs and Outputs
A list of currently active MIDI ports. -
Presets
Settings for both connected and disconnected ports, including:- Routing definitions
- User control mappings (e.g., sliders, dropdowns)
-
Dropdowns
A mapping between user-friendly preset names and their correspondingProgram Change
IDs. -
Virtual Ports
Definitions for virtual MIDI ports used for internal routing.
⚠️ Note: Virtual ports are currently not supported on Windows.
Persist configuration
Configuration is stored in a json
file. Since the schema may change with version upgrades, it's recommended to back up your configuration regularly.
To simplifying the process of persisting changes, In the login
tab, you can manage automatically load on application start and save on close.
Clicking the link
at login
tab redirects to the server folder where the JSON configuration is stored. You can copy this file for backup.
The ⋮
button provides about
information and options to download or upload and apply the current configuration.
Screenshots
Settings

Login tab

Presets
Presets are containers for user-defined input configurations. They can be activated via mouse click or MIDI event, offering flexible and dynamic control.
Each preset holds its own distinct settings across all available input channels.
Usage Notes
While multiple presets can be active at once, it's generally recommended to use only one at a time—especially when applying advanced input configurations such as 14-bit resolution or clock routing.
Using a single preset helps maintain clarity and avoids potential conflicts between overlapping input settings.
MIDI Preset Activation Modes
when the assigned MIDI event is received
- select — Activates the selected preset and disables all others.
- toggle — Enables or disables the current preset.
- on — Enables the preset.
- off — Disables the preset.
Screenshots
Presets

Preset

Input Ports
This tab lets you set up and manage your input ports.
Only ports that are currently connected will be shown.
Port Settings
Here’s what you can adjust:
- Ignore Message Types: Choose which types of MIDI messages to ignore.
- MIDI Clock Settings: Control how MIDI clock signals are handled, including advanced options like converting
SPP
(Song Position Pointer) to time signatures. - 14-bit CC Translation: Enables more accurate conversion of 14-bit MIDI messages—for example, turning them into pitch wheel data.
Monitoring
Monitoring lets you keep an eye on incoming MIDI messages. It also makes tricky stuff—like 14-bit values or NRPNs—way easier to read by turning them into something more understandable.
Routing Options
You can set up routing in two ways:
- EasyConfig: A simple, beginner-friendly tool that helps you create routing setups without needing to dive into technical details.
- Routes: A more advanced option for users who want full control over routing configurations.
EasyConfig automatically builds the Routes setup for you, so you get the best of both worlds!
Screenshots
In ports

EasyConfig Overview
EasyConfig makes MIDI routing simple and approachable—no need to dive into complex low-level setup.
The interface is organized into two main tabs: Routes and Split, each designed to help you configure your MIDI setup quickly and efficiently.
EasyConfig Routes
Destination Setup
You can route MIDI data to either:
- A local output name, or
- A network destination using the format:
<address>:<port>/<destinationName>
To make remote setup easier, there's a Query button that checks if the remote port is available and confirms connectivity.
All network communication uses WebSocket over TCP, ensuring reliable data transfer.
Keyboard Split
The Split tab lets you define a split point on your keyboard—this divides it into separate zones. This is especially useful for setting up layered instruments or assigning different sounds to different parts of the keyboard.
Once zones are created, you can assign them as sources for note on/off
events (when a key is pressed or released)
Screenshots
Split

EasyConfig

Route
A Route is a container for multiple chains, enabling modular and sequential processing of MIDI data.
Learning to Create Routes
If you're trying to understand how routes are built, the easiest way is to start with an EasyConfig
. Once you've created one, inspect how it's automatically translated into a full route. This reverse-engineering method offers a hands-on, intuitive way to grasp the structure and logic of route creation—without needing to dive into low-level details right away.
Chains
A chain defines a linear path composed of a sequence of filters. Each filter performs a specific transformation or analysis on the MIDI stream, allowing for flexible and customizable data manipulation as it flows through the chain.
Filter Types
TO_MIDI_DESTINATION
Routes MIDI events to a specific local MIDI destination.
TO_CONSOLE
Logs MIDI events to the console (either server or client). This filter is also used for inter-server communication, such as sending logged MIDI messages to a client or triggering preset changes via MIDI.
TO_NETWORK
Sends all MIDI events to a remote destination.
SCHEDULE_TO
Holds MIDI events and schedules them for future delivery based on deferredType
and deferredTo
parameters. Requires MIDI clock events to function properly.
FILTER_AND_TRANSFORM
Allows both filtering and transforming MIDI event data. Transformation notation includes:
[[fromStart, fromEnd, toStart, toEnd]]
— Maps a range fromfromStart
tofromEnd
ontotoStart
totoEnd
.[[fromStart, fromEnd, toStart]]
— Short form wheretoEnd = toStart + (fromEnd - fromStart)
.[[value1, value2]]
— Mapsvalue1
tovalue2
.[[value]]
— Equivalent to[[value, value]]
, a single value mapping.
📚 Reference
Filter Type 0: TO_MIDI_DESTINATION
Parameters:
filterType
:0
midiInputName
: Name of the MIDI input port
Filter Type 1: TO_CONSOLE
Parameters:
filterType
:1
logTo
: Logging destination0
(CLIENT): Client console1
(SERVER): Server console
userdata
: Optional user-defined JSON data
Filter Type 2: TO_NETWORK
Parameters:
filterType
:2
midiInputName
: MIDI input port nameserverName
: Target server nameserverPort
: Target server port
Filter Type 3: SCHEDULE_TO
Parameters:
filterType
:3
deferredType
: Scheduling mode0
: IN_SPP (relative to Song Position Pointer)1
: IN_BAR (relative to current bar)2
: AT_SPP (specific SPP)3
: AT_BAR (specific bar)4
: QUANTIZE_SPP (nearest SPP)5
: QUANTIZE_BAR (nearest bar)
deferredTo
: Number of units to defer
Filter Type 4: FILTER_AND_TRANSFORM
Parameters:
conditionAction
: Event deletion logic0
: DO_NOT_DELETE1
: DELETE_IF_NOT_MET_CONDITION2
: DELETE_IF_MET_CONDITION
filterChannel
: MIDI channel filterfilterData1
: Data1 byte filter/transformfilterData2
: Data2 byte filter/transformfilterEvents
: MIDI event types to filter (e.g.,[8]
for Note On)filterType
:4
name
: Filter name
User Controls
Each preset can include interactive controls such as sliders, optionally paired with dropdown menus.
Only the controls associated with the currently selected preset are displayed.
These controls send MIDI events to a predefined local port. The following MIDI event types are supported:
- Control Change (CC)
- Program Change
- NRPN (Non-Registered Parameter Number)
The is64Mode
flag interprets the value 64
as the center or zero point, commonly used for bipolar ranges.
Dropdowns can also be used to store and select predefined preset names.
Screenshorts
controls

control

Reference
Event Types
The value used at the json
mapped to midi event id
[
{ "value": 0, "text": "[] - -" },
{ "value": 1, "text": "[8, 9] - Note on/off" },
{ "value": 2, "text": "[9] - Note off" },
{ "value": 3, "text": "[8] - Note on" },
{ "value": 4, "text": "[10] - Key Aftertouch" },
{ "value": 5, "text": "[11] - Control Change" },
{ "value": 7, "text": "[100] - NRPN" },
{ "value": 8, "text": "[12] - Program Change" },
{ "value": 9, "text": "[13] - Channel Aftertouch" },
{ "value": 10, "text": "[14] - Pitch Bend" }
]
Preset configuration example
Users aren't expected to manually edit or create json
files—this example is provided solely to help you understand the configuration structure.
As the configuration grows, it may become increasingly difficult to grasp its overall purpose. It's recommended to maintain a separate README file outside the app to document and explain your configuration.
Routing a Control Change (CC) event to NRPN, using channel 6 for both, and mapping a value range from 0–127 to 0–255.
{
"midiRoutePresets": [
{
"midiRouteInputs": [
{
"midiInputName": "0_Launch Control XL",
"easyConfig": {
"easyConfigRoutes": [
{
"fromCcOrNrpnEnd": 127,
"fromCcOrNrpnStart": 0,
"fromChannel": 6,
"fromData1": -1,
"fromSelectedMidiEventTypeId": 5,
"splitRangeId": -1,
"toCcOrNrpnEnd": 255,
"toCcOrNrpnStart": 0,
"toChannel": 6,
"toData1": 8,
"toDestinationName": "localhost:12345/0_Scarlett 2i4 USB",
"toSelectedMidiEventTypeId": 7,
"transpose": 0,
"uuid": "d3bc0cb8-0de6-43ec-94c5-91b4a6ed7c6d"
}
],
"keyboardSplits": [],
"zoneNames": []
}
}
]
}
]
}
List of Midi CC commands
Some of these commands may be reserved, although certain devices might not reserve them at all and instead use them for different functions. The following list represents a common convention, but individual devices are not strictly required to adhere to it.
bankselectcoarse: 0,
modulationwheelcoarse: 1,
breathcontrollercoarse: 2,
footcontrollercoarse: 4,
portamentotimecoarse: 5,
dataentrycoarse: 6,
volumecoarse: 7,
balancecoarse: 8,
pancoarse: 10,
expressioncoarse: 11,
effectcontrol1coarse: 12,
effectcontrol2coarse: 13,
generalpurposeslider1: 16,
generalpurposeslider2: 17,
generalpurposeslider3: 18,
generalpurposeslider4: 19,
bankselectfine: 32,
modulationwheelfine: 33,
breathcontrollerfine: 34,
footcontrollerfine: 36,
portamentotimefine: 37,
dataentryfine: 38,
volumefine: 39,
balancefine: 40,
panfine: 42,
expressionfine: 43,
effectcontrol1fine: 44,
effectcontrol2fine: 45,
holdpedal: 64,
portamento: 65,
sustenutopedal: 66,
softpedal: 67,
legatopedal: 68,
hold2pedal: 69,
soundvariation: 70,
resonance: 71,
soundreleasetime: 72,
soundattacktime: 73,
brightness: 74,
soundcontrol6: 75,
soundcontrol7: 76,
soundcontrol8: 77,
soundcontrol9: 78,
soundcontrol10: 79,
generalpurposebutton1: 80,
generalpurposebutton2: 81,
generalpurposebutton3: 82,
generalpurposebutton4: 83,
reverblevel: 91,
tremololevel: 92,
choruslevel: 93,
celestelevel: 94,
phaserlevel: 95,
databuttonincrement: 96,
databuttondecrement: 97,
nonregisteredparametercoarse: 98,
nonregisteredparameterfine: 99,
registeredparametercoarse: 100,
registeredparameterfine: 101
SBOM
https://github.com/shemeshg/MidiRouterClient/blob/main/SBOM.md
LICENSE
https://github.com/shemeshg/MidiRouterClient/blob/main/LICENSE