MIDI I/O in Python

I want to write a MIDI effect in Python — something that can listen to my keyboard input, add a harmony*, and output both to Max. My I/O problems would be solved by a trivially simple piece of example code, one that just adds another note a halfstep up, or transposes its input an octave, or whatever. I could do the rest of it myself — I can write basic Python but I’m failing to get a handle on MIDI input/output.

I installed PythonMIDI (https://github.com/vishnubob/python-midi/) and not even its own tests would run. I installed portmidizero to discover it requires portmidi; I tried installing portmidi and could not figure it out. I tried PyMIDI but it cannot output MIDI, only input it.

I expect processing the notes to be difficult enough. Does anybody know of an easy way to input and output them?

My processing speed for your ideas leaves something to be desired. I apologize.

I may have installed PortMidi? What I got was an application called pmdefaults.app, which lets me route inputs to outputs. I don’t have any evidence that my Python library has been modified to allow me to work with PortMidi in Python. Anthony, what Python modules do you use to talk to PortMidi? Would you be willing to share your script?

I am hoping to keep the latency as low as possible, because I will be using it in real time to process my own playing, so I’m leery of using a virtual machine. I also hesitate to bind the code to Max/MSP; I would rather have it run standalone, to reduce the number of dependencies. For instance, I might later decide to go straight from Python into Ableton.

Although I would highly recommend you look into the max python external I listed above.
That way you could have Max handle all the Midi i/o and your python scripts could then
do all your processing (with Music21 or what ever package). You could also
use Max to create a nice user interface for your python environment.

Should I expect a latency advantage in using straight Python instead of Python from within Max?

I have found installing python libraries very difficult.

One of my problems is that I installed python 3.4, which I can run from the shell by typing "python3", but the default 2.7 version remains installed on my computer. When I add a library, it always seems to get grafted onto 2.7, not 3.4.

More generally, though, I just don’t understand what I’m doing when I install a library.

There should be no latency when using the python external in Max because it is Python 2.7 compiled as an external. Yes, installing packages can be a bit tricky. Normally when you install packages, you run a command from the terminal, like "python setup install". This will use the default install for python, not python3.

I installed python3 not for the core language (although I like how it changed), but to make something else run better. I think it was for Tkinter, which got overhauled between 2 and 3. I need Tkinter because it’s the only event loop construct I know how to use.

It sounds like you’re saying the python external would impose no additional latency if it’s wrapped inside Max. Does Max itself, though, impose any latency, relative to having no wrapper?

I didn’t think I needed to worry about latency until I started using the built-in sounds of a Casio CDP keyboard while simultaneously triggering Pianoteq (a VST plugin with a physical model of a piano) in Ableton Live using the CDP’s USB out. The internal sounds reach my ear noticeably earlier than the Live-generated ones.

That lag is present, though, even if I don’t transform the incoming MIDI before rendering to audio, so Max and Java might not be at all to blame.

The python external is compiled as native instructions. So you would have no more latency than you would if you were running it an a regular python shell. I doubt Max introduces any latency transferring data to and from the external. Now Java could add latency, especially if you have to transfer a lot of data across the java/max bridge. That’s why I don’t mess with it.