MIDI I/O in Python

    Jul 21 2013 | 1:24 am
    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?
    I use a Mac.

    • Jul 28 2013 | 11:01 am
      If you don't mind spinning up a JVM, you could use Jython inside Max:
    • Jul 29 2013 | 5:42 pm
      Portmidi works for me. I usually have a python script that opens a MIDI port and sends the notes to Max which renders the audio.
      Here is the documentation for portmedia. I think I had to build it again in order to get it to install the python library. I still have the version I built if you need it.
    • Jul 29 2013 | 5:54 pm
      An even easier solution would be to use the python 2.7 external created by Thomas Grills
      You can run python scripts in it and then send the output anywhere you want without leaving the Max environment.
    • Nov 29 2013 | 7:59 pm
      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.
    • Jun 20 2014 | 4:09 am
      You can see some examples on a script I wrote here for transposing in Python using Music21.
    • Jun 22 2014 | 8:55 pm
      Thanks, Aldorath. It looks like you're using Python to read from and write to offline files, not realtime streams. Am I correct?
    • Jun 23 2014 | 4:38 pm
      Hey DopeThatWantsCash, sorry for the late response.
      I lost track of this thread.
      I am using the python package pyPortMidi to access the midi ports from python.
      It may take some code wrangling to get it to install.
      But once you do, it would make your python music environment
      Are you running windows or OSX?
    • Jun 23 2014 | 4:47 pm
      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.
    • Jun 23 2014 | 5:56 pm
      Thanks, Anthony!
      I run OS X (10.8). So far I'm using Java from within Max.
      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.
    • Jun 23 2014 | 9:05 pm
      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.
      Is there a particular reason why you are using python3?
    • Jun 24 2014 | 1:29 am
      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.
    • Jun 25 2014 | 8:13 pm
      I don't believe there is any additional latency introduced by the wrapper.
      Not sure where the latency could be coming from. When you start putting JAVA
      in the mix, you don't know what kind of timing you will get.
    • Jun 26 2014 | 6:21 pm
      So Python is better than Java regarding latency? When writing MIDI/control-rate externals for Max, using Java can introduce latency where using Python would not?
    • Jun 26 2014 | 9:54 pm
      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.