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

Reply via email to