Esempio n. 1
0
def play_a_note(midi_out: MidiOut, instrument: Instrument):
    note_on = midi_cmd(0x9, instrument.ch)
    note_off = midi_cmd(0x8, instrument.ch)
    midi_out.send_message([note_on, 60, 80])
    time.sleep(0.5)
    midi_out.send_message([note_off, 60, 0])
    time.sleep(0.1)
Esempio n. 2
0
def silence(port: MidiOut,
            *,
            stop: bool = True,
            channels: Iterable[int] = ALL_CHANNELS) -> None:
    if stop:
        port.send_message([STOP])
    for channel in channels:
        port.send_message([CONTROL_CHANGE | channel, ALL_NOTES_OFF, 0])
Esempio n. 3
0
def send_config_to_device(config: MPK_MINI_MK2, preset: int,
                          midi_out: MidiOut) -> None:
    config[0].preset = preset
    data = MPK_MINI_MK2.build(config)
    assert data[0] == 0xF0 and data[-1] == 0xF7
    midi_out.send_message(data)
    data_hex = str(binascii.hexlify(bytearray(data)), 'utf-8')
    logging.debug(f'- SENT {len(data)} BYTES. SYSEX:\n{data_hex}')
Esempio n. 4
0
def move_knob(midi_out: MidiOut, knob_message: list):
    for i in range(knob_message[2], -1, -1):
        knob_message[2] = i
        midi_out.send_message(knob_message)
        time.sleep(0.01)
    print('Up --> Down...DONE')

    for i in range(0, 128):
        knob_message[2] = i
        midi_out.send_message(knob_message)
        time.sleep(0.01)
    print('Down --> Up...DONE')
Esempio n. 5
0
async def play(outport: rtmidi.MidiOut, inptable: MidiTable, noloops=1):
    """An asynchronous implementation of a table player.

    Multiple miditable objects and ports can be asynchronously
    targeted for concurrent output with proper synchronization."""
    miditable = MidiTable(inptable)
    tempo = bpm2tempo(120)  # default tempo
    for i in range(noloops):
        for msg in miditable:
            if msg['del_t'] > 0:
                delta = tick2second(msg['del_t'], tempo)
                await asyncio.sleep(delta)

            if msg['mtype'] == Mtypes.TEMPO:
                tempo = metaclasses.TempoSet.decoder(msg['data'])
            elif msg['mtype'] in CHAN_MTYPES:
                outport.send_message(msg['data'])
Esempio n. 6
0
cursor_heap = []
tracks = {}
cur_time = 0

_track_id = 0

for track in score.tracks:
    notes_sets_of_sylls = [s.notes for s in track.syllables]
    notes = []
    for nset in notes_sets_of_sylls:
        notes += nset
    if len(notes) == 0:
        continue
    tracks[_track_id] = notes
    output.send_message([0xC0 + _track_id, 0])  #track.instrument])
    heappush(cursor_heap, (tracks[_track_id][0].time_in_score, (0, _track_id)))
    if type(tracks[_track_id][0]) != Rest:
        output.send_message(
            [0x90 + _track_id, tracks[_track_id][0].midi_note, 0x40])
    _track_id += 1

while len(cursor_heap) > 0:
    duration, nearest = heappop(cursor_heap)

    i, ti = nearest

    print("Track: %d, CurTime: %5d, Duration: %4d, Note: %d" %
          (ti, cur_time, duration, tracks[ti][i].midi_note))

    if duration != 0:
Esempio n. 7
0
class Player:
    def __init__(self,
                 queue=Queue(),
                 running=Value('i', False),
                 tempo=Value('i', default_tempo),
                 deadline=Value('f', 0)):
        self.midiout = MidiOut()
        self.midi_for_file = MidiFile()
        self.last_chord = empty_chord

        self.queue_out = queue
        self.running = running
        self.tempo = tempo
        self.deadline = deadline
        self.start_peak = Value('f', 0)
        self.start_chord = 0

    def play_peak(self,
                  number=default_peak_number,
                  velocity=default_peak_velocity):
        note_on = Message('note_on',
                          note=number,
                          velocity=velocity,
                          channel=default_ultrasound_channel).bytes()
        self.midiout.send_message(note_on)
        sleep(default_peak_time)
        note_off = Message('note_off',
                           note=number,
                           velocity=min_velocity,
                           channel=default_ultrasound_channel).bytes()
        self.midiout.send_message(note_off)

    def play_chord_same_time(self):
        chord = self.queue_out.get()
        # print("player get", chord, "vel", chord.velocity, "queue", self.queue_out.qsize(), "time", time.monotonic())
        if chord.velocity > 127:
            chord.velocity = 127
        if chord.duration == 0:
            return
        for note in chord.notes:
            if note.number > 127:
                print("an incorrect note in player")
                return

        if self.last_chord != empty_chord:
            for note in self.last_chord.notes:
                note_off = Message('note_off',
                                   note=note.number,
                                   velocity=min_velocity,
                                   channel=default_channel).bytes()
                self.midiout.send_message(note_off)

        for note in chord.notes:
            note_on = Message('note_on',
                              note=note.number,
                              velocity=chord.velocity,
                              channel=default_channel).bytes()
            self.midiout.send_message(note_on)

        self.last_chord = chord

        sleep(len_in_s(chord.duration, self.tempo.value))

        if self.last_chord == chord:
            for note in chord.notes:
                note_off = Message('note_off',
                                   note=note.number,
                                   velocity=min_velocity,
                                   channel=default_channel).bytes()
                self.midiout.send_message(note_off)

    def play_chord_arpeggio(self, track=np.array([])):
        chord = self.queue_out.get()
        print("player get", chord, "vel", chord.velocity, "queue",
              self.queue_out.qsize(), "time", time.monotonic())
        if chord.velocity > 127:
            chord.velocity = 127
        if chord.duration == 0:
            return
        for note in chord.notes:
            if note.number > 127:
                print("an incorrect note in player")
                return
        chord.notes = sorted(chord.notes)
        if len(chord.notes) == 3:
            chord.notes.append(Note(chord.notes[0].number + 12))
        if track == np.array([]):
            notes_numbers = np.arange(len(chord.notes))
            notes_durations = np.array(
                [int(128 / len(chord.notes)) for i in range(len(chord.notes))])
            track = np.column_stack((notes_numbers, notes_durations))

        notes_sum_durations = np.cumsum(track.transpose(), axis=1)[1]
        if self.last_note_number is not None:
            note_off = Message('note_off',
                               note=self.last_note_number,
                               velocity=min_velocity,
                               channel=default_channel).bytes()
            self.midiout.send_message(note_off)
        self.start_chord = time.monotonic()
        pair = 0
        note_number = track[pair][0]
        note_on = Message('note_on',
                          note=chord.notes[note_number].number,
                          velocity=chord.velocity,
                          channel=default_channel).bytes()
        self.midiout.send_message(note_on)
        while (pair < len(track) - 1):
            # TODO
            if time.monotonic() > self.start_chord + max(
                (self.deadline.value - self.start_chord) *
                    notes_sum_durations[pair] / notes_sum_durations[-1],
                    len_in_s(notes_sum_durations[pair], self.tempo.value)):
                note_off = Message('note_off',
                                   note=chord.notes[note_number].number,
                                   velocity=min_velocity,
                                   channel=default_channel).bytes()
                self.midiout.send_message(note_off)
                pair += 1
                note_number = track[pair][0]
                note_on = Message('note_on',
                                  note=chord.notes[note_number].number,
                                  velocity=chord.velocity,
                                  channel=default_channel).bytes()
                self.midiout.send_message(note_on)
                self.last_note_number = chord.notes[note_number].number
            time.sleep(0.01)

    def put(self, chord):
        if type(chord) == Chord:
            self.queue_out.put(chord)
            return True
        return False

    def set_up_ports(self):
        """ This is necessary to HEAR the music """
        available_ports = self.midiout.get_ports()
        if available_ports:
            self.midiout.open_port(default_port)
        else:
            self.midiout.open_virtual_port("Tmp virtual output")

    def set_up_instrument(self, program=default_instrument):
        program_change = Message('program_change',
                                 program=program,
                                 channel=default_channel).bytes()
        self.midiout.send_message(program_change)

    def set_up_ultrasound_instrument(self,
                                     program=default_ultrasound_instrument):
        program_change = Message('program_change',
                                 program=program,
                                 channel=default_ultrasound_channel).bytes()
        self.midiout.send_message(program_change)

    def set_up_midi_for_file(self):
        self.midi_for_file.tracks.append(MidiTrack())

    def set_tempo(self, tempo=default_tempo):
        self.tempo.value = tempo

    def set_deadline(self, deadline=0):
        self.deadline.value = deadline

    def set_start_peak(self, start=max_time):
        self.start_peak.value = start

    def get_sleeping_time(self):
        return self.deadline.value - time.monotonic()

    def get_track(self):
        return self.midi_for_file.tracks[0]

    def save_file(self, filename='my track.mid'):
        self.midi_for_file.save(filename)
        return filename

    def run(self):
        self.running.value = True
        self.set_up_ports()
        self.set_up_midi_for_file()
        self.set_up_instrument()
        self.set_up_ultrasound_instrument()

        self.queue_process = Process(target=run_queue_out, args=(self, ))
        self.queue_process.start()

        self.queue_process = Process(target=run_peak, args=(self, ))
        self.queue_process.start()

    def stop(self):
        """ All chords that already sound will continue to sound """
        self.running.value = False
        self.queue_process.join()
        self.queue_process.join()
        self.queue_out = Queue()

    queue_out = None
    running = None
    tempo = None
    deadline = None
    start_peak = None
    start_chord = None
    queue_process = None
    peak_process = None
    midiout = None
    midi_for_file = None
    last_chord = None
    last_note_number = None
class Device:
    MIDI_IN = None
    MIDI_OUT = None
    MIDI_PORT_COUNT = 0
    IS_FIRST_CONNECTION = True

    UPDATE_LIST = []
    KEY_BINDINGS = {}

    PULSE_AUDIO = PulseAudioHelper()
    XORG = XorgHelper()

    def __init__(self, name='Generic Device', regex=None):
        self.NAME = name
        self.DEVICE_REGEX = regex
        self.UPDATE_LIST.append(self.update_midi_connection_on_reconnect)

    def __enter__(self):
        self.MIDI_IN = MidiIn()
        self.MIDI_OUT = MidiOut()
        return self

    def __exit__(self, _type, _value, _traceback):
        del self.MIDI_IN, self.MIDI_OUT

    def __repr__(self):
        return self.NAME

    def update(self, ELAPSED_TIME):
        for update in self.UPDATE_LIST:
            update(ELAPSED_TIME)

    def send_signal(self, channel, key, payload):
        self.MIDI_OUT.send_message([channel, key, payload])

    def update_midi_connection_on_reconnect(self, _elapsed_time):
        current_port_count = len([
            x for x in self.MIDI_OUT.get_ports()
            if not re.search(r'[rR]t[Mm]idi', x)
        ])

        if current_port_count != self.MIDI_PORT_COUNT:
            self.MIDI_PORT_COUNT = current_port_count
            self.activate()

    def activate(self):
        if self.DEVICE_REGEX is not None:
            self.activate_ports()

    def activate_ports(self):
        activated = False
        self.MIDI_IN.close_port()
        self.MIDI_OUT.close_port()

        if not self.IS_FIRST_CONNECTION:
            print(f'{self} disconnected!')

        sleep(1.0)

        for midi in (self.MIDI_IN, self.MIDI_OUT):
            port_number = None
            for i, port_name in enumerate(midi.get_ports()):
                if re.search(self.DEVICE_REGEX, port_name):
                    port_number = i
                    break

            if port_number is not None:
                midi.open_port(port_number)
                activated = True

        if activated:
            self.IS_FIRST_CONNECTION = False
            print(f'{self} connected!')

        self.MIDI_IN.set_callback(self.input_callback)

    def input_callback(self, midi_signal_in, *_args, **_kwargs):
        byte_signal = midi_signal_in[0]
        key = str(byte_signal[1])

        if key in self.KEY_BINDINGS.keys():
            self.KEY_BINDINGS[key](byte_signal)
        else:
            self.animation_callback(byte_signal)

    def animation_callback(self, byte_signal):
        print(f'{self}:{byte_signal}')
Esempio n. 9
0
def send_sysex_from_hex_string(hex_string: str, midi_out: MidiOut) -> None:
    data = bytearray.fromhex(hex_string)
    assert data[0] == 0xF0 and data[-1] == 0xF7
    midi_out.send_message(data)
    data_hex = str(binascii.hexlify(bytearray(data)), 'utf-8')
    logging.debug(f'- SENT {len(data)} BYTES. SYSEX:\n{data_hex}')
Esempio n. 10
0
def send_all_notes_off(port: rtmidi.MidiOut):
    for ch in range(16):
        port.send_message((MTYPE_SPECS[Mtypes.CC].status | ch,
                           ALL_NOTES_OFF,
                           0))
Esempio n. 11
0
def send_pitch_bend(touchpad: TouchpadInputDevice, x: int, midiout: MidiOut) -> None:
    pbend = min(16383, int(16384 * touchpad.normalize_x(x)))
    msg = [PITCH_BEND, pbend & 0x7F, (pbend >> 7) & 0x7F]
    midiout.send_message(msg)
    print(pbend // 260 * " ", msg)
Esempio n. 12
0
def set_instrument(midi_out: MidiOut, instrument: Instrument):
    cc = midi_cmd(0xB, instrument.ch)
    pc = midi_cmd(0xC, instrument.ch)
    midi_out.send_message([pc, instrument.pc])
    midi_out.send_message([cc, 0, instrument.cc])