mididings - Documentation

Table of Contents

Basics

mididings configuration files are just Python scripts, although mididings uses some of Python's features in ways for which they weren't intended ;)
Basically, the MIDI processing setup is defined in Python, while the actual event processing is done entirely in C++. It is however possible to explicitly call back into Python, if necessary.

Functions

config(**kwargs)

Changes global mididings settings. This should be called only once, before constructing any processing units.
Possible keyword arguments are:

run(patch)

Starts the actual MIDI processing. This is usually the last function called by a mididings script.

run_patches(patches, control=None, pre=None, post=None)

Starts the actual MIDI processing, using multiple patches.

switch_patch(number)

Switches to another patch. This function is similar to the PatchSwitch() object, but can be called from Python.

Data Types

MidiEvent

Used in conjunction with the Call(), CallAsync() and CallThread() units.

A MidiEvent object has the following attributes:

There are also aliases for these attributes, some of which are only defined for certain types of events:

Constants

Event Types

Every event has one of these types: NOTEON, NOTEOFF, CTRL, PITCHBEND, AFTERTOUCH, PROGRAM.
When building filters, event types can be combined using the bitwise or operator.
Also defined are NOTE (= NOTEON | NOTEOFF), NONE, ANY.

Event Attributes

These constants are used to refer to an event's data attributes: EVENT_PORT, EVENT_CHANNEL, EVENT_DATA1, EVENT_DATA2, EVENT_NOTE, EVENT_VELOCITY, EVENT_PARAM, EVENT_VALUE, EVENT_PROGRAM.

Making Connections

A >> B

Connects two units in series. Incoming MIDI events will be processed by unit A first, then by unit B. If the event is filtered out by unit A, it is not processed any further, and unit B will not be called.

[ A, B, ... ]

Connects two or more units in parallel. All units will be called with identical copies of incoming MIDI events. The output will be the sum of all the units' outputs.

Fork([ A, B, ... ], types=ANY, remove_duplicates=None)

Same as the above, with some additional features:

Using Fork() explicitly (instead of just a list) is also useful in situations where both sides of operator >> would otherwise be lists, which Python does not allow.

{ T1: A, T2: B, ... }

Splits by event type. Equivalent to [ Filter(T1) >> A, Filter(T2) >> B, ... ].

Split({ T1: A, T2: B, ... })

Same as the above. Like Fork(), this can be useful to make operator >> work.

~F

Inverts the filter F. Note that for filters which only affect certain kinds of events, other events will remain unaffected when the filter is inverted.

F % A

Runs only those events through A which match filter F, but keeps those which don't. Equivalent to [ F >> A, ~F ].

Units

These are the basic building blocks from which you can build your patches.

Filters

Filter(type, ...)

Filters by one or more event types.

PortFilter(port, ...)
ChannelFilter(channel, ...)

Filters by event port or channel.

KeyFilter(key)
KeyFilter(lower, upper)
KeyFilter(range)

Filters by key or key-range. Keys can be MIDI note numbers or note names (e.g. 'g#3'). Ranges can be 2-tuples of note numbers, or note names (e.g. 'g#3:c6').

VelocityFilter(min, max)

Filters by note velocity.

CtrlFilter(ctrl, ...)

Filters by CC number.

CtrlValueFilter(value)
CtrlValueFilter(min, max)

Filters by CC value.

ProgFilter(program, ...)

Filters by PC number.

Splits

PortSplit({port: units, ...})
PortSplit({(port, ...): units, ...})
ChannelSplit({channel: units, ...})
ChannelSplit({(channel, ...): units, ...})

Splits by port or channel.

KeySplit(key, units_lower, units_upper)
KeySplit({(lower, upper): units, ...})
KeySplit({range: units, ...})

Splits by key. Non-note events are sent to all units.

VelocitySplit(threshold, units_lower, units_upper)
VelocitySplit({(min, max): units, ...})

Splits by velocity. Non-note events are sent to all units.

CtrlSplit({ctrl: units, ...})
CtrlSplit({(ctrl, ...): units, ...})

Splits by controller number. Non-controller events are left unchanged, but not sent to any of the units.

CtrlValueSplit(threshold, units_lower, units_upper)
CtrlValueSplit({value: units, ...})
CtrlValueSplit({(min, max): units, ...})

Splits by controller value. Non-controller events are left unchanged, but not sent to any of the units.

ProgSplit({program: units, ...})
ProgSplit({(program, ...): units, ...})

Splits by program number. Non-program-change events are left unchanged, but not sent to any of the units.

Modifiers

Port(port)
Channel(channel)

Changes port or channel.

Transpose(offset)

Transposes all note events.

Velocity(offset)
VelocityMultiply(mult)
VelocityFixed(value)

Changes velocity by adding an offset, multiplying with a factor, or setting it to a fixed value.

VelocityCurve(gamma)

Applies a "gamma"-curve to all velocity values.

VelocityGradient(note_lower, note_upper, value_lower, value_upper)
VelocityGradientMultiply(note_lower, note_upper, value_lower, value_upper)
VelocityGradientFixed(note_lower, note_upper, value_lower, value_upper)

Changes velocity, using a gradient from lower to upper.
This can be used for example to fade-in a sound over a region of the keyboard.

CtrlMap(ctrl_in, ctrl_out)

Maps one controller to another (i.e. changes the CC number).

CtrlRange(ctrl, out_min, out_max, in_min=0, in_max=127)

Maps controller range in to out.
An input value of in_min or less results in an output value of out_min. Likewise, an in value of in_max or greater results in an output value of out_max.

Generators

CtrlChange(ctrl, value)
CtrlChange(port, channel, ctrl, value)
ProgChange(program)
ProgChange(port, channel, program)
NoteOn(note, velocity)
NoteOn(port, channel, note, velocity)
NoteOff(note, velocity)
NoteOff(port, channel, note, velocity)

Changes the type of the event. If port and channel are omitted, the values of the input event are used.
To "reuse" other values from the incoming event, one of the EVENT_* constants can be used in place of any parameter.

Function Calls

Call(function)

Calls a Python function. This will stall any other MIDI processing until the function returns.

CallAsync(function)

Schedules a Python function for execution, and continues MIDI processing immediately.

CallThread(function)

Like CallAsync(), but runs the function in its own thread.

System(cmd)

Runs an arbitrary shell command, without waiting for the command to complete.

Miscellaneous

Pass()

Does nothing.

Discard()

Discards the current event.

PatchSwitch()
PatchSwitch(number)

Switches to another patch. number should be a patch number, or one of the EVENT_* constants. Without parameters, the program number of the incoming event (should be a program change) will be used.

InitAction(action)

Executes action when switching to the patch containing this unit (essentially adding it to the init-patch, see run_patches() for more information).

Output(port, channel, program=None)

Based on InitAction(), this sends a program change when the patch is selected, and routes all incoming events to the specified port/channel.

Print(name=None, types=ANY, portnames=Print.PORTNAMES_NONE)

Prints event data.

PrintString(string)

Prints a fixed string.

Sanitize()

Makes sure the event is a valid MIDI message. Events with invalid port, channel, controller, program or note number are discarded, note velocity and controller values are confined to the range 0-127.

Additional Units and Functions

These units are defined in the mididings.extra module, and offer some more advanced/specific functionality, based on the more basic mididings units.
Some of these are implemented in Python using Call(), and thus not safe to use with the jack-rt backend.

Harmonize(tonic, scale, interval, non_harmonic='below')

A diatonic harmonizer.

SuppressPC()

Filters out program changes if the same program had previously been selected on the same port/channel.

PedalToNoteoff(ctrl=64)

Converts sustain pedal CCs to note-off events (delaying note-offs until the pedal is released).

BlackKeys()
WhiteKeys()

Filters notes by key color.

SendOSC(target, path, ...)

Defined in mididings.extra.osc. Requires pyliblo.
Sends an OSC message. Parameters are the same as for liblo.send(). Additionally, rather than a concrete value, each data argument can be a Python function instead. The function should take a single MidiEvent parameter, and return the value to be sent.

SendDBUS(service, path, interface, method, ...)

Defined in mididings.extra.dbus. Requires dbus-python.
Sends a DBUS message. Rather than a concrete value, each data argument can be a Python function instead. The function should take a single MidiEvent parameter, and return the value to be sent.

run_patches_memorize(memo_file, patches, control=None, pre=None, post=None)

Like run_patches(), but saves the selected patch number to a file, and restores it the next time it's called. memo_file is the path of the file to be used to store the patch number.

Examples