Hi, I've had the pleasure and misfortune to test both of the widely known portable MIDI libraries, and now believe I have found one that works to my satisfaction.
This is not a quantifiable review with benchmarking but the subjective experience of someone who has implemented a very simple yet nonetheless professionally implemented, low-latency, jitter-free and real time application. (note: to my knowledge, sched_fifo functionality has not been implemented with either library and is next on the priority list to implement in the application). The two candidates are portmidi (http://www.cs.cmu.edu/~music/portmusic/) and RtMidi (http://www.music.mcgill.ca/~gary/rtmidi/) RtMidi is part of the Synthesis Toolkit (STK) but can be obtained stand-alone. For comparison, I have chosen the following criteria: * Availability * Learning curve * Stability * Features * Real-Time performance First thing I did was download PortMidi, mainly because I didn't know what static linking was at the time and RtMidi (I had found both easily through Google) I decided I would go for the library with the smaller size. (As I later discovered RtMidi is available as a seperate library, but was not packaged for my OS, Debian Etch) Even while on the site I got a bit suspicious about PortMidi, as there were quite many 'projects that use portmidi' listed on their site, and a lot of titles and fancy names, but very little actual software. I've got a little bit of entrepreneurial experience under my belt, just enough to tell it is a bad idea to proudly display 'Future Projects' as references. Nonetheless, I decided to give portmidi a chance, in the hope things would get better. They didn't. The 'Documentation' was sparse, cryptically written, and still in the header file (IE no HTML had been generated). I found this to be quite a careless attitude but I had decided to try it out and I did. The API isn't much better. To open an interface, a six parameter function was necessary, of which two were actually relevant (device ID and stream pointer). In order to send a message it was necessary to create a 'buffer' object, write timestamp and message data to it, and pass it on to a 'write' function. Also, it was riddled with pointers-to-pointers and various combinations of references and de-references and I had to revert to plain trial and error to get it to work. It finally did, though. After a similar odyssee with the input library, which, unlike my experience with portmidi I attribute to the fact I had never programmed C++ before, the application finally stood. Pressing buttons on the keyboard generated MIDI events. How grand! However, there was a downside; somehow, pressing and holding keys generated randomly-spaced additional sounds. "How funny," I thought, "my physical keyboard must be not appropriate for such fine use." After battling with C++ polymorphism for DAYS ON END to get the plugin architecture to work I decided it was time to implement threading. Looking for a good thread class I realized that is not such a trivial thing currently. Realizing that RtMidi already had one, and that it was implemented in an audio environment, I decided to switch MIDI libraries too as the Thread class was probably optimized for RtMidi. What a world of difference! I was greeted with a very friendly page titled 'RtMidi', the author had a picture of himself on the page (it's VERY reassuring to know he is not hiding from the police) and looked like he's been meditating a lot, and had it not been for the advanced C++ functionality used in the class that I hadn't learned yet ('advanced' is relative, I mean the vector class and the concept of 'templates') I would have been done implementing in an hour or two. Seriously, RtMidi is one of the most beautifully crafted interfaces I have seen to date, with examples in the beautifully done tutorial. Unlike portmidi it was possible to create ALSA MIDI virtual devices, and the code for sending MIDI events was ONE LINE. Using references it was possible to write a callback function for application plugins that DIRECTLY affect the raw data sent. Clearly, I had a winner. When I tested it I realized what had seemed like a broken keyboard was simply how portmidi responded to repeated, fast events; I had not turned off KeyRepeat events in the event handler, and what was left of them with PortMidi were randomly spaced events between 200 and 500ms apart, somehow mangled in the obscurity of the code I can only presume. With RtMidi it was possible to recognize the events for what they were, crystal clear, fast and evenly spaced KeyRepeats clogging my synthesizer with utmost precision. I have yet to fix the KeyRepeat problem, but it tought me a lot about performance. Perhaps the 'KeyRepeat' test could evolve to a rather good rule-of-thumb benchmark for MIDI performance. And I haven't even implemented SCHED_FIFO yet. As a conclusion, I can draw the following ratings matrix for the two, I can assume the care with which documentation is crafted is a good indicator for code quality, and I can only recommend: Keep your hands of portmidi. Write a wrapper if you need to use C, but for heaven's sake if you don't want all your musical timing ruined, just don't use portmidi, period. MATRIX 1: Useless 5: Excellent portmidi RtMidi Availability 4 4 Learning curve 1 4 Stability 3 4 Features 3 4 Real-Time performance 1 5 Carlo -X-X-X- Did you think this review was helpful for you? Please give a simple 1 to 5 rating, or a quick comment. Thank you.
