I am trying to send a basic MIDI message to a synthesizer, using Python.
I know that the PC-Synthesizer link is functional because the Rosegarden application can be configured to play MIDI files on the device, when the MIDI output is set to ‘DigitalKBD 20:0’ port.
I have discovered this Python library (MIDO) and installed it. The good news is that the external MIDI device is recognized and available in the port list. Unfortunately the simple note-on test does not trigger any sound on the device. Here is the code I tried:
Using PortMidi (this is the default for MIDO):
>>> import mido >>> output = mido.open_output('DigitalKBD MIDI 1') >>> output.send(mido.Message('note_on', note=60, velocity=64))
Using RtMidi:
>>> import mido >>> rtmidi = mido.Backend('mido.backends.rtmidi') >>> output = rtmidi.open_output('DigitalKBD 20:0') >>> output.send(mido.Message('note_on', note=60, velocity=64))
In both cases, there is no sound coming from the synthesizer whatsoever.
Please, can I get advice how to fix the code (or setup) so that the instrument receives and interprets the messages correctly?
Advertisement
Answer
Ok, well, I got the MIDI in/out working, by creating a small script that echoes whatever is played on the keyboard, with certain delay:
import mido import time from collections import deque print mido.get_output_names() # To list the output ports print mido.get_input_names() # To list the input ports inport = mido.open_input('DigitalKBD MIDI 1') outport = mido.open_output('DigitalKBD MIDI 1') msglog = deque() echo_delay = 2 while True: while inport.pending(): msg = inport.receive() if msg.type != "clock": print msg msglog.append({"msg": msg, "due": time.time() + echo_delay}) while len(msglog) > 0 and msglog[0]["due"] <= time.time(): outport.send(msglog.popleft()["msg"])
This script works very well, so I had opportunity to walk carefully back to see why my initial test was unsuccessful. Turns out, for the output messages to be received, the input port also has to be opened. Don’t know the reason why, but this is the simplest code that works:
import mido inport = mido.open_input('DigitalKBD MIDI 1') outport = mido.open_output('DigitalKBD MIDI 1') outport.send(mido.Message('note_on', note=72))
What’s more, if the python is exited immediately after running the above code, it might happen that MIDO did not manage to send the message, so no sound will be played. Give it some time to wrap up.