I have a grandiose plan to create a suite of tools for adding human tempo and dynamics to a MIDI file, inspired by Tapper[1] but more suitable for multitrack works. So I'm writing a series of programs that essentially take a MIDI file as input and play it live to a MIDI output device, while simultaneously mucking with it based on information from another MIDI device (in my case my digital keyboard, Korg NanoKONTROL or maybe NanoKEY).
Having had no experience whatsoever with hardware MIDI but a bit of experience with MIDI files, I snagged PortMidi and started playing around. I was glad to find that it didn't have some complicated abstraction layer, just a more-or-less raw connection to the MIDI device. Since MIDI isn't very abstract anyway, a couple more #defines would make it perfect IMO[2]. Then I started working on MIDI file input. I snagged PortSMF, and ... errr, it's C++. OK, I can deal with that. ... uhh, and it abstracts away all the MIDI data to these event classes. Then to actually play it you have to transform it back. So now I've got input coming in raw form (the MIDI input device) and in this highly-baked, abstract form (PortSMF). Well if you read the subject, you already know the punchline. I gave up on PortSMF. I don't want something that abstracts away the MIDI data since that just means that I have two different levels of abstraction I'm working with. Lucky me, the MIDI file format is really quite simple, so I made my own MIDI file library, which I have aptly named "midifile". I threw it into Mercurial: http://codu.org/projects/music/midifilehg/ . It's quite simple: It's C, its file is just an array of tracks, each of which is just a list of events, and the events are just a PortMidi event paired with the MIDI-file tick-based time and meta info if applicable. Its level of abstraction is nearly identical to PortMidi (i.e. no abstraction). It does allocate data, but it allows the user to override which functions it uses for allocation, so you can e.g. use libgc. It also includes a sublibrary that allows you to treat a MIDI file like a stream. With that, you can write a MIDI file player in ~100 lines of C (see: http://codu.org/projects/music/midifilehg/index.cgi/file/tip/playfile.c , which is presently 106 code lines), with live modification of the MIDI stream (tempo, dynamics, whatever). Its API isn't /quite/ identical to PortMidi since it does need events in its own format, and it also has some nonsense for tempo, time division, etc. It's definitely a one-day quick effort, and it shows; but it works, doesn't have any obvious memory leaks or other major bugs, and fits in really well with PortMidi. I'm still working on it, and it'll change as I start writing more sophisticated programs around it. Anyway, I'm just curious if anybody else out there would consider it useful. I realize it's kind of rocking the boat to make an alternative to an already-existing part of the suite, but to be perfectly frank, PortSMF seems to be kind of the black sheep of the family ... - Gregor Richards [1]: http://www.musanim.com/tapper/ [2]: Namely: Pm_MessageType, Pm_MessageChannel and a few #defines that list the common MIDI event types, such as PM_MIDI_NOTE_ON, PM_MIDI_PITCH_BEND, etc. _______________________________________________ media_api mailing list media_api@create.ucsb.edu http://lists.create.ucsb.edu/mailman/listinfo/media_api