Ejemplo n.º 1
0
def VoiceFilter(voice='highest', time=0.1, retrigger=False):
    """
     Filter individual voices from a chord.

    :param 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).

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

    :param 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.
    """
    if voice == 'highest':
        voice = -1
    elif voice == 'lowest':
        voice = 0

    return _m.Filter(_m.NOTE) % _m.Process(
        _PerChannel(lambda: _VoiceFilter(voice, time, retrigger)))
Ejemplo n.º 2
0
def 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.
    """
    return (_m.Filter(_m.NOTE) % _m.Process(_PerChannel(_MakeMonophonic)))
Ejemplo n.º 3
0
def LatchNotes(polyphonic=False, reset=None):
    """
    Makes notes latching, so they will keep playing when the key is
    released.

    :param 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.

    :param reset:
        a note (name/number) that acts as a reset key, stopping all
        currently playing notes.
    """
    return (_m.Filter(_m.NOTE) %
            _m.Process(_PerChannel(lambda: _LatchNotes(polyphonic, reset))))
Ejemplo n.º 4
0
def LimitPolyphony(max_polyphony, remove_oldest=True):
    """
    Limit the "MIDI polyphony".

    :param max_polyphony:
        The maximum number of simultaneous notes.

    :param 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.
    """
    return (_m.Filter(_m.NOTE) % _m.Process(
        _PerChannel(lambda: _LimitPolyphony(max_polyphony, remove_oldest))))
Ejemplo n.º 5
0
def PedalToNoteoff(ctrl=64, sostenuto=False):
    """
    Convert sustain pedal control changes to note-off events,
    by delaying note-offs until the pedal is released.

    :param ctrl:
        The pedal's controller number.

    :param sostenuto:
        If true act like a sostenuto pedal, instead of a regular sustain
        pedal.
    """
    if sostenuto:
        proc = _m.Process(_PerChannel(lambda: _SostenutoToNoteoff(ctrl)))
    else:
        proc = _m.Process(_PerChannel(lambda: _SustainToNoteoff(ctrl)))

    return (_m.Filter(_m.NOTE) | _m.CtrlFilter(ctrl)) % proc
Ejemplo n.º 6
0
def Harmonize(tonic, scale, interval, non_harmonic='below'):
    """
     A diatonic harmonizer.

    :param tonic:
        The tonic of the scale, as a note name.

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

    :param 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.

    :param 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.
    """
    t = _util.tonic_note_number(tonic)

    if _misc.issequence(scale):
        shift = 0
    elif isinstance(scale, str):
        if scale == 'major':
            scale = _MAJOR_SCALE
            shift = 0
        elif scale == 'minor':
            scale = _MAJOR_SCALE
            shift = 5
        elif scale == 'minor_harmonic':
            scale = _HARMONIC_MINOR_SCALE
            shift = 0
        elif scale in _MODES:
            shift = _MODES.index(scale)
            scale = _MAJOR_SCALE

    # shift scale to the correct mode
    s = ([x - scale[shift] for x in scale[shift:]] +
         [x + 12 - scale[shift] for x in scale[:shift]])

    if not _misc.issequence(interval):
        interval = [interval]

    # convert all interval names to numbers
    iv = [(_INTERVALS.index(x) if x in _INTERVALS else x) for x in interval]

    # python version:
    #    f = [ _m.Process(_Harmonizer(t, s, i, non_harmonic)) for i in iv ]

    # pure mididings version:
    f = []
    for i in iv:
        h = _Harmonizer(t, s, i, non_harmonic)
        # get offset for each key
        offsets = [(x, h.note_offset(x)) for x in range(128)]
        # group by offset
        groups = _itertools.groupby(sorted(offsets, key=_itemgetter(1)),
                                    key=_itemgetter(1))

        # create one KeyFilter()/Transpose() pair for each offset
        for off, keys in groups:
            if off is not None:
                f.append(
                    _m.KeyFilter(notes=[k[0]
                                        for k in keys]) >> _m.Transpose(off))

    return _m.Filter(_m.NOTE) % f
Ejemplo n.º 7
0
control_port_pattern = r'a2j:MIDI Mix.*MIDI 1'

md.config(backend='jack',
          client_name='control-map',
          in_ports=[('keys_in', keys_port_pattern),
                    ('control_in', control_port_pattern),
                    ('synth_in', synth_port_pattern)],
          out_ports=[('keys_out', keys_port_pattern),
                     ('control_out', control_port_pattern),
                     ('synth_out', synth_port_pattern)])

control_switches = [md.KeyFilter(notes=[27]) >> (TX7_DumpRequest(0) >> md.Port('synth_out')),
                    md.KeyFilter(notes=[25]) >> md.SceneSwitch(offset=-1),
                    md.KeyFilter(notes=[26]) >> md.SceneSwitch(offset=1)]

control = md.PortFilter('control_in') >> md.Filter(md.NOTEON) >> control_switches #control = md.PortFilter('control_in') >> md.Print('control')
pre = None #md.Print('input') # bank/page buttons, solo button
post = None #md.Print('output')

def fill_pages():
    """returns a dict of page descriptions.
    These are dicts as well, that map input_controller_names to parameter_names"""
    ps = {'op[1-3]_eg': {},
          'op[4-6]_eg': {},
          'frequency':  {},
          'pitch_eg/lfo': {},
          'op_mod_sensitivity': {},
          'keyboard_level_scaling_depth': {},
          'keyboard_level_scaling_curve': {},
          'name': {},
          'performance': {},
Ejemplo n.º 8
0
 def __init__(self, min=0, max=0x7f):
     self.filter = md.Filter(md.PITCHBEND)
     self.generator = md.Pitchbend(md.EVENT_VALUE)
     self.min = min
     self.max = max