MIDIRouter by example

This article provides some detailed example and associated configuration file for MIDIRouter (https://github.com/NothNoth/MIDIRouter).

Simple forward

Let’s start with a very simple use case: « I want to forward all messages received on my input MIDI interface to my output MIDI interface ».

This may typically happen when you have a MIDI Usb keyboard connected to your audio interface and you want to send everything to you freshly acquired analog synthesizer connected to your MIDI output.

Our configuration file will first specify your MIDI input and output devices.

Simply run MIDIRouter with no arguments to list available devices:

Usage: ./midirouter <config file>
MIDI inputs:
   Périphérique MIDI USB
   Korg
   MOOG
   Faderfox EC4
   Port 1
   Port 2
   Port 3
   Port 4
   Port 5
   Port 6
   Port 7
   Port 8
MIDI outputs:
   Périphérique MIDI USB
   Korg
   MOOG
   Faderfox EC4
   Port 1
   Port 2
   Port 3
   Port 4
   Port 5
   Port 6
   Port 7
   Port 8

Let’s say I want to route everything from « Korg » to « MOOG ».

{
    "SourceDevice": "Korg",
    "DestinationDevice": "MOOG",
    "DefaultPassthrough": true,
    "Verbose": true
}

The « DefaultPassthrough » simply tells the MIDIRouter to forward all messages not matching any other rule. Since we don’t have any other rule set, this default behaviour will match all captured messages on the input interface.

The « Verbose » option is useful when setting everything up: it will show a message everytime a MIDI event is received (you can switch it to ‘false’ once everything works fine).

Note On/off forward only

On our previous example we’ve used the DefaultPassthrough feature to allow a complete forward of all messages from the input MIDI device to the output MIDI device.

Now we may not want to send everything to our vintage Analog Synth since it only supports NoteOn and NoteOff MIDI mesages. In order to do that, we will use what is the main feature of MIDIRouter: « rules ».

A « Rule » is built using three main sections:

  • A filter which describes what kind of MIDI message to look for on the input MIDI interface
  • A transformation which optionally defines how you want to change the extracted value
  • A generator which describes what kind of MIDI message to replay on the output MIDI interface

Our complete forward scenario is quite simple:

  • Filter: we want to match any Note On or Note Off message whatever the MIDI channel, value or velocity
  • Transform: we don’t want to transform anything
  • Generator: we want to replay using the same type of MIDI message (Note on, note Off), same MIDI channel, same note, same Velocity

We will here need two rules, one for the Note On events and one for the Note Off events.

Let’s start with Note On forward.

{
    "SourceDevice": "Korg",
    "DestinationDevice": "MOOG",
    "DefaultPassthrough": false,
    "Verbose": true,
    "Rules": [
        {
            "Name": "Raw forward of any Note On",
            "Filter": {
                "Name": "Note On in (I can write anything here)",
                "MsgType": "Note On",
                "Channel": "*",
                "Settings": {
                    "Note": "*",
                    "Velocity": "*"
                }
            },
            "Transform": {
                "Mode": "None"
            },
            "Generator": {
                "Name": "Note On out",
                "MsgType":"Note On",
                "Channel": "*",
                "Settings": {
                    "Note": "*",
                    "Velocity": "*"
                }
            }
        }
    ]
}

In the first part of this configuration file, we have the same section defining the input and output. Note that we’ve disabled the Defaultpassthrough option.

Then we have the « Rules » array which – for now – only contains one rule for our « Note On » events. The « Name » fields can be used to put any comments to be used for display only.

The « Filter » is built using:

  • MsgType: the type of midi message to look for (among « Note On », « Note Off », « Aftertouch », « Control Change », « Program Change », « Channel Pressure », « Pitch Wheel »). Here we set it to « Note On »
  • Channel: the MIDI channel to look for (1 to 16). Here we want to match any channel and use ‘*’.
  • Now comes the « Note On » specific settings which are « Note » (the note value) and « Velocity ». Since we want to match any note or velocity, we use ‘*’ again.

Then comes the « Transform » entry which would technically allow us to transform a note to another one. Here we just want to replay the MIDI message as it, so we use « None ».

The « Generator » section describes what kind of MIDI message we want to generate when a MIDI message matching our filter is captured. These settings are quite similar to the filter settings.

  • MsgType: the type of midi message to generate (among « Note On », « Note Off », « Aftertouch », « Control Change », « Program Change », « Channel Pressure », « Pitch Wheel »). So here we set it to « Note On »
  • Channel: the MIDI channel to set (1 to 16). Here we want reuse the same MIDI channel found on the captured Note on, we set it to « * ».
  • Now comes the « Note On » specific settings which are « Note » (the note value) and « Velocity ». Since we want to replay the same note and velocity, we use ‘*’ again.

And that’s it: the rule will match all Note on events and replay them to the output interface using the exact same settings (MIDI channel, note, velocity).

Because we want to send also Note Off messages, we add another rule with very similar settings:

{
    "SourceDevice": "Faderfox EC4",
    "DestinationDevice": "Périphérique MIDI USB",
    "DefaultPassthrough": false,
    "Verbose": false,
    "Rules": [
        {
            "Name": "Match any NoteOn",
            "Filter": {
                "Name": "Note On in",
                "MsgType": "Note On",
                "Channel": "*",
                "Settings": {
                    "Note": "*",
                    "Velocity": "*"
                }
            },
            "Transform": {
                "Mode": "None"
            },
            "Generator": {
                "Name": "Note On out",
                "MsgType":"Note On",
                "Channel": "*",
                "Settings": {
                    "Note": "*",
                    "Velocity": "*"
                }
            }
        },
        {
            "Name": "Match any NoteOff",
            "Filter": {
                "Name": "Note Off in",
                "MsgType": "Note Off",
                "Channel": "*",
                "Settings": {
                    "Note": "*",
                    "Velocity": "*"
                }
            },
            "Transform": {
                "Mode": "None"
            },
            "Generator": {
                "Name": "Note Off out",
                "MsgType":"Note Off",
                "Channel": "*",
                "Settings": {
                    "Note": "*",
                    "Velocity": "*"
                }
            }
        }
    ]
}

On the next article, we will see how we can send Pitch Wheel events captured on a given MIDI channel to another MIDI channel and transform them to Aftertouch events:

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *