# mididings - Extra Module Reference

## Units

These units offer some more advanced/specific functionality than what's provided in the core mididings module. Unless otherwise noted, they are defined in the mididings.extra module.

Note that some of these units are implemented in Python using Process(), and are thus not safe to use with the jack-rt backend.

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

A diatonic harmonizer.

- tonic: The tonic of the scale.
- scale: One of:
  'major', 'minor', 'minor_harmonic', 'ionian', 'dorian', 'phrygian', 'lydian', 'mixolydian', 'aeolian', 'locrian'.
- interval: The number of steps to transpose the notes by, or one of these interval names:
  'unison', 'second', 'third', 'fourth', 'fifth', 'sixth', 'seventh', 'octave', 'ninth', 'tenth', 'eleventh', 'twelfth', 'thirteenth'.
  It's also possible to pass a list of intervals, to create multiple harmonized voices.
- non_harmonic: What to do with out-of-scale notes:
  - 'below'/'above': Transpose by the same interval as the next on-scale note below/above.
  - 'skip': Ignore note.
  - 'same': Output note as is, without transposing it.

Add a third above each note, based on the C# harmonic minor scale:
Harmonize('c#', 'minor_harmonic', ['unison', 'third'])

#### FloatingKeySplit(threshold_lower, threshold_upper, patch_lower, patch_upper, hold_time=1.0, margin_lower=12, margin_upper=12)

Creates a floating split point that moves dynamically depending on what you are playing, allowing a region of the keyboard to be shared between two split zones.

- threshold_lower, threshold_upper: The lower and upper notes between which the split point is allowed to move.
- patch_lower, patch_upper: Patches to which notes below/above the split point will be sent.
- hold_time: Specifies how long released notes will still be taken into account when determining the split point.
- margin_lower, margin_upper: Numbers of semitones specifying how close you must get to the split point before it starts getting pushed into the opposite direction.

Split the keyboard somewhere between C2 and C3:
FloatingKeySplit('c2', 'c3', Channel(1), Channel(2))

#### VoiceFilter(voice='highest', time=0.1, retrigger=False)

Filters individual voices from a chord.

voice must be 'highest', 'lowest', or an index (positive or negative, the same way Python lists are indexed, with 0 being the lowest voice).
When a key is already held, and then becomes active for this voice because another key was pressed/released, the note will only be played if retrigger is True, or if the time since the key-press is less than the number of seconds specified by the time parameter.

#### VoiceSplit([patch, ...], fallback='highest', time=0.1, retrigger=False)

Creates multiple VoiceFilter() units to route each voice to a different instrument.

Regardless of the number of voices specified, the lowest and highest note played will always be routed to the first and last patch in the list, respectively. When the number of notes played is less than the number of voices specified, "surplus" voices will fall back to the highest or lowest note played, as specified by the fallback parameter.

Route up to three voices to different channels:
VoiceSplit([Channel(1), Channel(2), Channel(3)])

#### LimitPolyphony(max_polyphony, remove_oldest=True)

Limits the "MIDI polyphony" to max_polyphony.

If remove_oldest is true, the oldest notes will be stopped when the maximum polyphony is exceeded. If remove_oldest is false, no new notes are accepted while max_polyphony notes are held.
Note that the actual polyphony of a connected synthesizer can still be higher than the limit set here, e.g. due to a long release phase.

#### MakeMonophonic()

Makes the MIDI signal "monophonic", i.e. only one note can be played at any given time. When one note is released while another is still held (but silent), the previous one will be retriggered.

#### SuppressPC()

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

#### PedalToNoteoff(ctrl=64, sostenuto=False)

Converts sustain pedal CCs to note-off events (delaying note-offs until the pedal is released). Acts either like a regular sustain pedal (the default) or like a sostenuto pedal.

#### LatchNotes(polyphonic=False, reset=None)

Makes notes latching, so they will keep playing when the key is released.

If polyphonic is False, pressing a key will automatically turn off any previous notes. If polyphonic is True, each note can be stopped individually by pressing the corresponding key again. reset can be a note name/number that when pressed stops all currently playing notes.

#### KeyColorFilter(color)

Filters notes by key color ('black' or 'white').

#### Panic(bypass=True)

Generates all-notes-off messages (CC #123) on all channels. If bypass is True, these messages will be sent directly on all output ports, without going through the rest of the patch.

#### SendOSC(target, path, ...)

Defined in mididings.extra.osc. Requires pyliblo.

Sends an OSC message. Parameters are the same as for liblo.send(). Additionally, instead of a specific value, each data argument can also be a Python function that takes a single MidiEvent parameter, and returns the value to be sent.

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

Defined in mididings.extra.dbus. Requires dbus-python.

Sends a DBUS message. Instead of a specific value, each data argument can also be a Python function that takes a single MidiEvent parameter, and returns the value to be sent.

Change FFADO output volume using a MIDI controller:

    CtrlFilter(42) >> SendDBUS(
        'org.ffado.Control',
        '/org/ffado/Control/DeviceManager/%s/Mixer/OUT0Gain' % DEVICEID,
        'org.ffado.Control.Element.Continuous',
        'setValue',
        lambda ev: ev.value * (2**17)
    )

#### Restart()

Calls engine.restart().

#### Quit()

Calls engine.quit().

## Hooks

#### MemorizeScene(memo_file)

Saves the currently selected scene number to a file when terminating mididings, and restores it at the next startup. memo_file is the path of the file to be used to store the scene number.

#### OSCInterface(port=56418, notify_ports=[56419])

Defined in mididings.extra.osc. Requires pyliblo.

Allows controlling mididings via OSC. These messages are currently understood:

- /mididings/switch_scene ,i: switches to the given scene number.
- /mididings/switch_subscene ,i: switches to the given subscene number.
- /mididings/prev_scene: switches to the previous scene.
- /mididings/next_scene: switches to the next scene.
- /mididings/prev_subscene: switches to the previous subscene.
- /mididings/next_subscene: switches to the next subscene.
- /mididings/panic: sends all-notes-off on all channels and on all output ports.
- /mididings/quit: terminates mididings.

#### AutoRestart(modules=True, filenames=[])

Defined in mididings.extra.inotify. Requires pyinotify ≥ 0.8.

Automatically restarts mididings when the script changes.

If modules is True, all imported local Python modules are monitored for changes as well. The filenames parameter allows specifying additional files to be monitored.
This restarts the entire mididings script, so MIDI processing is interrupted, and mididings does not take care of reestablishing any ALSA/JACK connections. If the new script contains errors that prevent it from running, mididings exits and needs to be restarted manually once the errors are fixed.