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)
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])
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}')
def get_out_port(port_name: str) -> MidiOut: midi_out = MidiOut() midi_out_ports = midi_out.get_ports() try: midi_out.open_port(midi_out_ports.index(port_name)) except ValueError: raise ValueError(port_name) from None return midi_out
def getDeviceList(self): midiin = MidiIn() midiout = MidiOut() try: return (midiin.get_ports(), midiout.get_ports()) except Exception as e: if DEBUG == True: print(e) return False
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')
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
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'])
def list_ports(): midi_in = None midi_out = None try: api_out = MidiOut() api_in = MidiIn() ports = api_in.get_ports() return ports except: print("Unable to open MIDI ports") return
def get_ports(port_name: str, *, clock_source: bool = False) -> Tuple[MidiIn, MidiOut]: midi_in = MidiIn() midi_out = MidiOut() midi_in_ports = midi_in.get_ports() midi_out_ports = midi_out.get_ports() try: midi_in.open_port(midi_in_ports.index(port_name)) except ValueError: raise ValueError(port_name) from None if clock_source: midi_in.ignore_types(timing=False) try: midi_out.open_port(midi_out_ports.index(port_name)) except ValueError: raise ValueError(port_name) from None return midi_in, midi_out
def setup_output(self): api_out = MidiOut() port_out = self.get_mixer_port(api_out) try: midi_out, port_name = open_midioutput(port_out, interactive=False) except InvalidPortError: return except NoDevicesError: return self.api_out = api_out self.output = midi_out return port_name
def _open_midi(self): """Starts MIDI without opening a port""" self.__log.info("Opening MIDI interfaces") try: self._midi_out = MidiOut() self._midi_in = MidiIn() #Note: if you need to catch SysEx, MIDI clock, and active sense #messages, then use the method: ignore_types as follows: #self._midi_in.ignore_types(sysex = False, timing = False, # active_sense = False) #They are ignored by default. I don't need this right now, so the #standard behaviour is OK for me except: error = traceback.format_exc() self.__log.info(error) self._free_midi() return False self.__log.debug("MIDI interfaces were opened") return True
from miniaudio import Backend, Devices from rtmidi import MidiIn, MidiOut print("- Audio devices") for backend in Backend: try: devices = Devices([backend]).get_playbacks() print(f" - {backend}") for device in devices: name = device["name"] print(f" 🔊 {name}") except: pass print("- MIDI inputs") for port in MidiIn().get_ports(): print(f" 🎶 {port}") print("- MIDI outputs") for port in MidiOut().get_ports(): print(f" 🎶 {port}") print( """ Note that this script can display a lot of error or warning messages from other libraries when trying to open backends that don't exist, or when probing interfaces on some backends. Pay attention only to the lines with 🔊 and 🎶! """ )
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)
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}')
import time from collections import deque import numpy as np from keras.models import load_model from music21 import midi, instrument, stream, note, chord from rtmidi import MidiOut from rtmidi.midiutil import open_midiinput from rtmidi.midiconstants import NOTE_ON, NOTE_OFF seq_len = 32 bpm = 120 / 60 instru = instrument.Piano() # MIDI Setup midiout = MidiOut() available_ports = midiout.get_ports() if available_ports: midiout.open_port(0) else: midiout.open_virtual_port("My virtual output") log = logging.getLogger('midiin_callback') logging.basicConfig(level=logging.DEBUG) # Load data from training print("\nLoading, please wait...\n", flush=True) vocab_file = "Piano_50.npy" vocab = np.load(os.path.join("vocab_save", vocab_file), allow_pickle=True) notes_vocab = vocab[0]
def __enter__(self): self.MIDI_IN = MidiIn() self.MIDI_OUT = MidiOut() return self
def get_midi_out(device_index: int): midiout = MidiOut() midiout.open_port(device_index) return midiout
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))
else: check_value(name, value) if name == 'data': vars(self)['data'] = SysexData(value) else: vars(self)[name] = value __setattr__ = _setattr def bytes(self): """Encode message and return as a list of integers.""" return encode_message(vars(self)) midi_in = MidiIn() midi_out = MidiOut() in_ports = midi_in.get_ports() out_ports = midi_out.get_ports() print("IN ports:", in_ports) print("OUT ports:", out_ports) def call_obs_api(command='pause-toggle'): url = f'http://localhost:28000/{command}' print("Calling:", url) response = requests.get(url).json() print("OBS RESPONSE:", response) def __callback(msg_data, data):
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}')
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])
def list_mididevices(): midiout = MidiOut() ports = midiout.get_ports() for idx, port in enumerate(ports): print(f'{idx}: {port}')
from rtmidi import MidiOut from heapq import heappop, heappush from time import sleep from pymusic.midi.parser import MidiParser from pymusic.score import Rest p = MidiParser('res/palestrina_missa_papae_marcelli_kyrie.mid') score = p.parse() output = MidiOut() output.open_port(5) 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])
from serial import Serial from time import time, sleep from rtmidi import MidiIn, MidiOut from _thread import start_new_thread mode = 0 pir_mode_color = [False, False, True] open_ports = [] LEDs = [] PIRs = [] m_out = MidiOut().open_virtual_port("Python PIR Output") melody_in = MidiIn().open_virtual_port("Python Melody Input") drum_in = MidiIn().open_virtual_port("Python Drum Input") last_drum = 0 DRUM_TIMEOUT = 0.1 PIR_TIMEOUT = 0.7 stair_modes = [ [48, 50, 52, 53, 55, 57, 59, 60], [ [48, 52, 55], [50, 53, 57], [52, 55, 59], [53, 57, 60], [55, 59, 62],