--- layout: default title: MIDI Binding Maps ---
Ardour 2.X supported MIDI learning for more or less any control. This was a nice feature that quite a few other DAWs are providing by now, but it didn't allow Ardour to work "out of the box" with sensible defaults for existing commercial MIDI controllers. In Ardour 3 and later versions, we have augmented the MIDI learn feature with the ability to load a MIDI binding map for a given controller, which can set up an arbitrary number of physical controls with anything inside Ardour that can be controlled.
At this time, these binding maps need to be created with a text editor. Currently, we have presets for:
MIDI binding maps are accessible by double-clicking Edit > Preferences > Control Surfaces > Generic MIDI. Ardour will retain your selection after you choose one.
Since the beginning of time (well, sometime early in the 2.X series), Ardour has had the concept of identifying each track and bus with a remote control ID. This ID uniquely identifies a track or bus so that when messages arrive from elsewhere via MIDI or OSC , we can determine which track or bus they are intended to control. Ardour has a number of ways of assigning remote control IDs, but they don't really matter very much when creating MIDI binding maps, so we won't discuss that here. You just need to know that there is a "first track" and its remote control ID is 1, and so on.
MIDI bindings are stored in files with the suffix ".map" attached to their name. The minimal content looks like this:
<?xml version="1.0" encoding="UTF-8"?> <ArdourMIDIBindings version="1.0.0" name="The name of this set of bindings"> </ArdourMIDIBindings>
So, to start, create a file with that as the initial contents.
On OS X, Ardour loads midi maps from its binary-bundle folder in
Ardour-<version>/midi_maps/
and checks
various other locations as well (defined by the ARDOUR_MIDIMAPS_PATH
environment variable). On GNU/Linux the easiest is to save the file to
~/.config/ardour3/midi_maps/
.
This is the most complex part of the job, but its still not very hard.
You need to connect the control surface to an application that will show
you the information that the device sends each time you modify a knob,
slider, button etc. There are a variety of such applications (notably
gmidimon
and kmidimon
, but you can actually use
Ardour for this if you want. Start Ardour in a terminal window, connect
MIDI ports up, and in the Preferences window, enable "Trace Input" on the
relevant MIDI port. A full trace of the MIDI data received will show up in
the terminal window. (Note: in Ardour3, you get a dedicated, custom dialog
for this kind of tracing.)
There are two basic kinds of bindings you can make between a MIDI message and something inside Ardour. The first is a binding to a specific parameter of a track or bus. The second is a binding to a function that will change Ardour's state in some way.
A track/bus binding has one of two basic structures
<Binding msg specification uri="... control address ..."/>
<Binding msg specification function="... function name ..."/>
You can create a binding for either 3 types of channel messages, or for a system exclusive ("sysex") message. A channel message specification looks like this:
<Binding channel="1" ctl="13" ....
This defines a binding for a MIDI Continuous Controller message involving
controller 13, arriving on channel 1. There are 16 MIDI channels, numbered
1 to 16. Where the example above says ctl
, you can alternatively
use note
(to create binding for a Note On message) or
pgm
(to create a binding for a Program Change message).
enc-r
, enc-l
, enc-2
and
enc-b
may be used for surfaces that have encoders that send
offsets rather than values. These accept Continuous Controller messages
but treat them as offsets. These are good for banked controls as they are
always at the right spot to start adjusting. See the link at the bottom of
the page for a longer explanation.
You can also bind sysex messages:
<Binding sysex="f0 0 0 e 9 0 5b f7" ....
<Binding sysex="f0 7f 0 6 7 f7" ....
The string after the sysex=
part is the sequence of MIDI bytes,
as hexadecimal values, that make up the sysex message.
Finally, you can bind a totally arbitrary MIDI message:
<Binding msg="f0 0 0 e 9 0 5b f7" ....
<Binding msg="80 60 40" ....
The string after the msg=
part is the sequence of MIDI bytes, as
hexadecimal values, that make up the message you want to bind. Using this is
slightly less efficient than the other variants shown above, but is useful for
some oddly designed control devices.
It is not possible at this time to use multi-event MIDI strings such as two event CC messages, RPN or NRPN.
The sysex=
and msg=
bindings will only work with
function=
or action=
control addresses. They
will not work with the uri=
control addresses.
A control address defines what the binding will actually control. There are quite a few different things that can be specified here:
Each of the specifications needs an address, which takes various forms too. For track-level controls (solo/gain/mute/recenable), the address is one the following:
For send/insert/plugin controls, the address consists of a track/bus address (as just described) followed by a number identifying the plugin/send (starting from 1). For plugin parameters, there is an additional third component: a number identifying the plugin parameter number (starting from 1).
One additional feature: for solo and mute bindings, you can also add
momentary="yes"
after the control address. This is useful
primarily for NoteOn bindings — when Ardour gets the NoteOn it
will solo or mute the targetted track or bus, but then when a NoteOff
arrives, it will un-solo or un-mute it.
Rather than binding to a specific track/bus control, it may be useful to have a MIDI controller able to alter some part of Ardour's state. A binding definition that does this looks like this:
<Binding channel="1" note="13" function="transport-roll"/>
In this case, a NoteOn message for note number 13 (on channel 1) will start the transport rolling. The following function names are available:
transport-stop
transport-roll
transport-zero
transport-start
transport-end
loop-toggle
rec-enable
rec-disable
next-bank
prev-bank
You can also bind a sysex or arbitrary message to any of the items that occur in Ardour's main menu (and its submenus). The best place to look for the (long) list of how to address each item is in your keybindings file, which will contain lines that look like this:
(gtk_accel_path "<Actions>/Editor/temporal-zoom-in" "equal")
To create a binding between an arbitrary MIDI message (we'll use a note-off on channel 1 of MIDI note 60 (hex) with release velocity 40 (hex)), the binding file would contain:
<Binding msg="80 60 40" action="Editor/temporal-zoom-in"/>
The general rule, when taken an item from the keybindings file and
using it in a MIDI binding is to simply strip the
<Action>
prefix of the second field in the
keybinding definition.
Because many modern control surfaces offer per-track/bus controls
for far fewer tracks & busses than many users want to control,
Ardour offers the relatively common place concept of banks. Banks
allow you to control any number of tracks and/or busses easily,
regardless of how many faders/knobs etc. your control surface has.
To use banking, the control addresses must be specified using the
bank relative format mentioned above ("B1" to identify
the first track of a bank of tracks, rather than "1" to identify
the first track).
One very important extra piece of information is required to use banking: an extra line near the start of the list of bindings that specifies how many tracks/busses to use per bank. If the device has 8 faders, then 8 would be a sensible value to use for this. The line looks like this:
<DeviceInfo bank-size="8"/>
In addition, you probably want to ensure that you bind something
on the control surface to the next-bank
and
prev-bank
functions, otherwise you and other users
will have to use the mouse and the GUI to change banks, which
rather defeats the purpose of the bindings.
<?xml version="1.0" encoding="UTF-8"?> <ArdourMIDIBindings version="1.0.0" name="pc1600x transport controls"> <DeviceInfo bank-size="16"/> <Binding channel="1" ctl="1" uri="/route/gain B1"/> <Binding channel="1" ctl="2" uri="/route/gain B2"/> <Binding channel="1" ctl="3" uri="/route/send/gain B1 1"/> <Binding channel="1" ctl="4" uri="/route/plugin/parameter B1 1 1"/> <Binding channel="1" ctl="6" uri="/bus/gain master"/> <Binding channel="1" note="1" uri="/route/solo B1"/> <Binding channel="1" note="2" uri="/route/solo B2" momentary="yes"/> <Binding channel="1" note="15" uri="/route/mute B1" momentary="yes"/> <Binding channel="1" note="16" uri="/route/mute B2" momentary="yes"/> <Binding sysex="f0 0 0 e 9 0 5b f7" function="transport-start"/> <Binding sysex="f0 7f 0 6 7 f7" function="rec-disable"/> <Binding sysex="f0 7f 0 6 6 f7" function="rec-enable"/> <Binding sysex="f0 0 0 e 9 0 53 0 0 f7" function="loop-toggle"/> <Binding channel="1" note="13" function="transport-roll"/> <Binding channel="1" note="14" function="transport-stop"/> <Binding channel="1" note="12" function="transport-start"/> <Binding channel="1" note="11" function="transport-zero"/> <Binding channel="1" note="10" function="transport-end"/> </ArdourMIDIBindings>
Please note that channel, controller and note numbers are specified as decimal numbers in the ranges 1-16, 0-127 and 0-127 respectively (the channel range may change at some point).
{% children %}