Reputation: 123
I referenced the Pygame MIDI documentation and this code to try to get MIDI input to work. The MIDI Interface (Avid Eleven Rack) receives MIDI data from my MIDI controller just fine in my audio software (Pro Tools). Using Pygame, however, I can not seem to read any information at all.
import pygame
from pygame.locals import *
from pygame import midi
class MidiInput():
def __init__(self):
# variables
self.elevenRackInID = 2
# init methods
pygame.init()
pygame.midi.init()
self.midiInput = pygame.midi.Input(self.elevenRackInID, 100)
def run(self):
# print(pygame.midi.Input(3, 100))
# for i in range(10):
# print(pygame.midi.get_device_info(i), i)
self.read = self.midiInput.read(100)
# self.convert = pygame.midi.midis2events(self.read, self.elevenRackInID)
print(self.read)
test = MidiInput()
while True:
test.run()
The only thing printed to the console are empty square brackets:
[]
I just checked again: the input ID is the right one and it is in fact an input.
"self.midiInput.poll()" returns False. So according to the Pygame documentation there is no data coming in.
You can see the data, poll and device info below:
data: [] || poll: False || device info: (b'MMSystem', b'Eleven Rack', 1, 0, 1)
A list of all my MIDI devices according to Pygame (with indexes):
(b'MMSystem', b'Microsoft MIDI Mapper', 0, 1, 0) 0
(b'MMSystem', b'External', 1, 0, 0) 1
(b'MMSystem', b'Eleven Rack', 1, 0, 1) 2
(b'MMSystem', b'Maschine Mikro MK2 In', 1, 0, 0) 3
(b'MMSystem', b'Microsoft GS Wavetable Synth', 0, 1, 0) 4
(b'MMSystem', b'External', 0, 1, 0) 5
(b'MMSystem', b'Eleven Rack', 0, 1, 0) 6
(b'MMSystem', b'Maschine Mikro MK2 Out', 0, 1, 0) 7
Any help or suggestions are greatly appreciated!
Upvotes: 3
Views: 6083
Reputation: 89
I don't believe the code posted below by Leonhard W is usable: neither the pygame.midi poll() method nor the pygame.midi read() method are blocking. The result is that CPU consumption goes through the roof (~50%).
Of course in practice the code to read the MIDI events would be run in a separate thread, though this won't help with CPU consumption.
In response to another very useful comment elsewhere, I've taken a look at the Mido library (https://mido.readthedocs.io/en/latest/index.html#). This provides blocking read methods and with just a few lines of code I can look for messages from a MIDI controller keyboard and pass them onto a MIDI synth.
import mido
names = mido.get_input_names()
print(names)
out_port = mido.open_output()
with mido.open_input(names[0]) as inport:
for msg in inport:
out_port.send(msg)
The only downside is that I'm getting a significant delay (perhaps 1/4s) between hitting the key and hearing the note. Oh well, onwards and upwards.
Upvotes: 2
Reputation: 123
I got an answer in another forum. It turns out that there is an example file which shows how to get the code to work. So if someone else stumbles over this problem here is the useful part of example code:
import sys
import os
import pygame as pg
import pygame.midi
def print_device_info():
pygame.midi.init()
_print_device_info()
pygame.midi.quit()
def _print_device_info():
for i in range(pygame.midi.get_count()):
r = pygame.midi.get_device_info(i)
(interf, name, input, output, opened) = r
in_out = ""
if input:
in_out = "(input)"
if output:
in_out = "(output)"
print(
"%2i: interface :%s:, name :%s:, opened :%s: %s"
% (i, interf, name, opened, in_out)
)
def input_main(device_id=None):
pg.init()
pg.fastevent.init()
event_get = pg.fastevent.get
event_post = pg.fastevent.post
pygame.midi.init()
_print_device_info()
if device_id is None:
input_id = pygame.midi.get_default_input_id()
else:
input_id = device_id
print("using input_id :%s:" % input_id)
i = pygame.midi.Input(input_id)
pg.display.set_mode((1, 1))
going = True
while going:
events = event_get()
for e in events:
if e.type in [pg.QUIT]:
going = False
if e.type in [pg.KEYDOWN]:
going = False
if e.type in [pygame.midi.MIDIIN]:
print(e)
if i.poll():
midi_events = i.read(10)
# convert them into pygame events.
midi_evs = pygame.midi.midis2events(midi_events, i.device_id)
for m_e in midi_evs:
event_post(m_e)
del i
pygame.midi.quit()
You can find the file yourself in this directory:
C:\Users\myUser\AppData\Roaming\Python\Python37\site-packages\pygame\examples\midi.py
Replace 'myUser'
with your Win username. Also, 'Python37'
can vary on the version of Python you have installed.
Upvotes: 7