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:
- client_name: MIDI client name to be used.
- in_ports/out_ports: Integers indicating the number of input/output ports to create (named in_n
or out_n), or lists of port names, in which case the list's length determines the number of ports.
- data_offset: 1 (default) or 0. Determines whether program, port and channel numbers will be
in the range 1-128 or 0-127.
- octave_offset: Default is 2, meaning that "Middle C" is designated as C3.
- start_delay: The number of seconds before sending any MIDI events (i.e. switching to the first patch).
A small value like 0.5 can be used to give tools like qjackctl's patchbay time to connect the ports.
A value of 0 instructs mididings to wait for the user to press enter. Default is None.
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.
- patches: A dictionary with program numbers as keys, and patches as values.
Values can also be tuple with two items, the first being an init-patch that's executed once every time the
patch is selected, and the second being the actual patch that processes incoming events.
- control: The "control" patch, which is always active, and run in parallel to the current patch.
- pre/post: Allows processing to take place before/after every patch. Does not affect
the control patch.
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:
- type_: The event type, one of the constants described below.
- port_: The event port.
- channel_: The event channel.
- data1, data2: Data bytes, meaning depends on event type.
There are also aliases for these attributes, some of which are only defined for certain types of events:
- port: Event port. Unlike port_, this value is affected by the data_offset setting.
- channel: Event channel. Unlike channel_, this value is affected by the data_offset setting.
- note: Note number, alias for data1.
- velocity: Note velocity, alias for data2.
- param: Controller number, alias for data1.
- value: Controller parameter, alias for data2.
- program: Program number, alias for data2. Unlike data2, this value is affected by the data_offset setting.
Constants
Event Types
Every event has one of these types: NOTEON, NOTEOFF, CTRL, PITCHBEND, 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.
{ T1: A, T2: B, ... }
Splits by event type. Equivalent to [ Filter(T1) >> A, Filter(T2) >> B, ... ].
Units
These are the basic building blocks from which you can build your patches.
- Filters: These units filter by some property of the MIDI event. If the event matches, it's passed
unmodified, otherwise it's discarded.
Events of different types (e.g. a note event going through a CtrlFilter) are also discarded.
Filters can be inverted by prepending operator ~.
- Splits: Basically just combinations of multiple filters of the same kind.
- Modifiers: These units change some property of the MIDI event.
- Generators: Converters from one event type to another.
- Function Calls: These units allow calling back into Python code.
- Miscellaneous: Anything that doesn't fit into any of the other categories :)
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, ...})
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.
Modifiers
Port(port)
Channel(channel)
Changes port or channel.
Transpose(offset)
Transposes all note events.
Velocity(offset)
VelocityFixed(value)
Changes velocity, either by adding an offset, or by 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)
VelocityGradientFixed(note_lower, note_upper, value_lower, value_upper)
Changes velocity, using a gradient from lower to upper.
CtrlMap(ctrl_in, ctrl_out)
Maps one controller to another.
CtrlRange(ctrl, out_min, out_max, in_min=0, in_max=127)
Maps controller range in to out.
Generators
CtrlChange(ctrl, value)
CtrlChange(port, channel, ctrl, value)
ProgChange(program)
ProgChange(port, channel, program)
Changes the type of the event.
If port and channel are omitted, the values of the input event are used.
To "reuse" 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.
- function: A function (or any other callable object) that will be called with a MidiEvent
object as its only argument. All of the event's data members may be modified.
The function should return True to continue processing the event, or False to discard it.
CallAsync(function)
Schedules a Python function for execution, and continues MIDI processing immediately.
- function: The function to be called. Unlike Call(), this will run the function in another thread.
Its return value will be ignored.
CallThread(function)
Like CallAsync(), but runs the function in its own thread.
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.
Print(name=None, types=ANY, portnames=Print.PORTNAMES_NONE)
Prints event data.
- name: A string to be printed before each event.
- types: Restricts printing to certain event types, using a combination of the event type constants described above.
- portnames: Pass Print.PORTNAMES_IN or Print.PORTNAMES_OUT to print input or output portnames,
rather than just numbers.
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.
Examples