# `mididings.extra` Units

These units offer some more advanced/specific functionality than what’s provided in the core mididings module. Unless otherwise noted, they are made available by importing the `mididings.extra` module.

Note

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

## Voicing

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

  > A diatonic harmonizer.

  Parameters:

    - tonic – The tonic of the scale, as a note name.

    - scale – The type/mode, of the scale, one of: `'major'`, `'minor'`, `'minor_harmonic'`, `'ionian'`, `'dorian'`, `'phrygian'`, `'lydian'`, `'mixolydian'`, `'aeolian'`, `'locrian'`.

    - interval –

      The number of steps to transpose the notes by (as an integer), or one of these interval names: `'unison'`, `'second'`, `'third'`, `'fourth'`, `'fifth'`, `'sixth'`, `'seventh'`, `'octave'`, `'ninth'`, `'tenth'`, `'eleventh'`, `'twelfth'`, `'thirteenth'`.

      It is also possible to pass a list of intervals, to create multiple harmonized voices.

    - non_harmonic –

      What to do with out-of-scale notes:

      - `'below'`: Transpose by the same interval as the next on-scale

      - `'above'`: Transpose by the same interval as the next on-scale

      - `'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'])

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

  > Filter individual voices from a chord.

  Parameters:

    - voice –

      The voice to be filtered.

      This can be `'highest'`, `'lowest'`, or an integer index (positive or negative, the same way Python lists are indexed, with 0 being the lowest voice and -1 the highest).

    - time – The period in seconds for which a newly played note may still be unassigned from the selected voice, when additional notes are played.

    - retrigger – If true, a new note-on event will be sent when a note is reassigned to the selected voice as a result of another note being released.

VoiceSplit(patches, fallback='highest', time=0.1, retrigger=False)

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

  Parameters:

    - patches – A list of patches, one for each voice.

    - fallback – Which note to double when the number of notes played is less than the number of voices. Can be `'highest'` or `'lowest'`.

  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.

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

LimitPolyphony(max_polyphony, remove_oldest=True)

  Limit the “MIDI polyphony”.

  Parameters:

    - max_polyphony – The maximum number of simultaneous notes.

    - remove_oldest – If true, the oldest notes will be stopped when the maximum polyphony is exceeded. If false, no new notes are accepted while max_polyphony notes are already 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()

  Make 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.

## Splits

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

  Create 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.

  Parameters:

    - threshold_lower

    - threshold_upper – The lowest and highest notes between which the split point is allowed to move.

    - patch_lower

    - patch_upper – The patch to which notes below/above the split point will be sent.

    - hold_time – How long released notes will still be taken into account when determining the split point (in seconds).

    - margin_lower

    - margin_upper – How close you must get to the split point before it starts getting pushed into the opposite direction (in semitones).

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

## Utilities

PedalToNoteoff(ctrl=64, sostenuto=False)

  Convert sustain pedal control changes to note-off events, by delaying note-offs until the pedal is released.

  Parameters:

    - ctrl – The pedal’s controller number.

    - sostenuto – If true act like a sostenuto pedal, instead of a regular sustain pedal.

LatchNotes(polyphonic=False, reset=None)

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

  Parameters:

    - polyphonic – If true, each note can be stopped individually by pressing the corresponding key again. Otherwise pressing a key will automatically turn off any previous notes.

    - reset – a note (name/number) that acts as a reset key, stopping all currently playing notes.

SuppressPC()

  Filter out program changes if the same program has already been selected on the same port/channel.

KeyColorFilter(color)

  Filter notes by key color.

  Parameters:

    color – the key color, either `'black'` or `'white'`.

CtrlToSysEx(ctrl, sysex, index, checksum_start=None)

  Convert control change to system exclusive event using a sysex pattern.

  Parameters:

    - ctrl – controller number to be replaced.

    - sysex – sysex pattern.

    - index – index of sysex pattern byte to be replaced by the controller value.

    - checksum_start – index of first sysex byte to be incorporated into Roland checksum computation. The checksum will replace the next-to-last byte of the sysex pattern. If this parameter is `None`, no checksum is computed.

Panic(bypass=True)

  Generate all-notes-off (CC #123) and sustain off (CC #64) events on all channels.

  Parameters:

    bypass – If true, events will be sent directly on all output ports, instead of originating from the `Panic()` unit and being subject to further processing.

Restart()

  Call `engine.restart()`.

Quit()

  Call `engine.quit()`.

## Messaging

SendOSC(target, path, *args)

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

  Defined in `mididings.extra.osc`. Requires pyliblo3.

SendDBUS(service, path, interface, method, *args)

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

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

      # 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)
      )