Python i MIDI

Przymierzam się do napisania edytora brzmień do mojego syntezatora Korg Triton Le, na początek zrobiłem kilka eksperymentów w pythonie, żeby zobaczyć jak sprawnie będzie szła komunikacja z interfejsem MIDI. Do komunikacji z syntezatorem używam interfejsu USB-MIDI Roland UM-ONE.

Na początek zainstalowałem bibliotekę rtmidi (https://github.com/patrickkidd/pyrtmidi) i sprawdziłem czy wykrywa ona prawidłowo porty MIDI.

import rtmidi
import random
import time

midiout = rtmidi.RtMidiOut()
ports = range(midiout.getPortCount())

if ports:
print("Available MIDI output ports:")

for i in ports:
print(str(i) + ': ' + midiout.getPortName(i))

else:
print('No MIDI output ports available')
exit()

Po wykonaniu powyższego kodu otrzymałem:

Available MIDI output ports:
0: Midi Through 14:0
1: UM-ONE 28:0

Jest dobrze, python widzi mój interfejs.

Poeksperymentowałem trochę z wysyłaniem komunikatów MIDI do urządzenia i w rezultacie napisałem poniższy kod:

import rtmidi
import random
import time

midiout = rtmidi.RtMidiOut()
ports = range(midiout.getPortCount())

if ports:
    print("Available MIDI output ports:")
    
    for i in ports:
        print(str(i) + ': ' + midiout.getPortName(i))
    
else:
    print('No MIDI output ports available')
    exit()
    
midiPort = int(input("Select a port: "))

if (midiPort < 0 or midiPort > len(ports)):
    print('Invalid port. Bye.')
    exit()

midiChannel = int(input("Select MIDI Channel (default 1): "))
if (midiChannel < 0 or midiChannel > 16):
    print('Invalid channel. Bye.')
    exit()

midiout.openPort(midiPort)

try:
    count = 100
    while count > 0:
        keyNumber = int(random.random() * 128)
        velocity = int(random.random() * 128)
        
        midiout.sendMessage(rtmidi.MidiMessage.noteOn(midiChannel, keyNumber, velocity))
        ts = random.random() * 0.5
        time.sleep(ts)
        midiout.sendMessage(rtmidi.MidiMessage.noteOff(midiChannel, keyNumber))
        count = count - 1
except KeyboardInterrupt:
    midiout.sendMessage(rtmidi.MidiMessage.allNotesOff(midiChannel))
    print("\nWhy did you stop?")

Po uruchomieniu, skrypt pyta o numer urządzenia oraz numer kanału MIDI i odtwarza 100 dźwięków o losowej długości oraz wysokości tonu.

Oto trzy przykłady, co wygenerował skrypt:

Piano
Synth Bass
Analog Synth

Projekt umieściłem na githubie pod adresem https://github.com/jakubthedeveloper/RandomMidiNotesPlayer.

W następnych etapach będę tworzył GUI do sterowania parametrami dźwięku.

Oto przykład kodu, który zmienia parametr dźwięku, a konkretnie punkt odcięcia filtra:

import rtmidi
import random
import time

midiout = rtmidi.RtMidiOut()
ports = range(midiout.getPortCount())

if ports:
    print("Available MIDI output ports:")
    
    for i in ports:
        print(str(i) + ': ' + midiout.getPortName(i))
    
else:
    print('No MIDI output ports available')
    exit()
    
midiPort = int(input("Select a port: "))

if (midiPort < 0 or midiPort > len(ports)):
    print('Invalid port. Bye.')
    exit()

midiChannel = int(input("Select MIDI Channel (default 1): "))
if (midiChannel < 0 or midiChannel > 16):
    print('Invalid channel. Bye.')
    exit()

midiout.openPort(midiPort)

ccCutoff = 74

count = 100
while count > 0:
    cutoffValue = int(random.random() * 128)
    
    midiout.sendMessage(rtmidi.MidiMessage.controllerEvent(midiChannel, ccCutoff, cutoffValue))
    ts = random.random() * 0.5
    time.sleep(ts)
    count = count - 1



Skomentuj