[linux-audio-dev] Portable C++ MIDI libraries review

From: Carlo Capocasa <capocasa@email-addr-hidden>
Date: Sat Feb 25 2006 - 11:52:15 EET


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

(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/)


RtMidi (http://www.music.mcgill.ca/~gary/rtmidi/)

RtMidi is part of the Synthesis Toolkit (STK) but can be obtained

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,


1: Useless 5: Excellent

                            portmidi RtMidi

Availability 4 4
Learning curve 1 4
Stability 3 4
Features 3 4
Real-Time performance 1 5



Did you think this review was helpful for you? Please give a simple 1 to
5 rating, or a quick comment. Thank you.
Received on Sun Feb 26 20:21:19 2006

This archive was generated by hypermail 2.1.8 : Sun Feb 26 2006 - 20:21:19 EET