MIDIFILE(3)

NAME
midifile - read a standard MIDI file

SYNOPSIS
#include "midifile.h" midifile ()
int (*Mf_getc) ();
int (*Mf_error) (char *msg);
int (*Mf_header) (int format, int ntrks, int division);
int (*Mf_trackstart) ();
int (*Mf_trackend) ();
int (*Mf_noteon) (int chan, int pitch, int vol);
int (*Mf_noteoff) (int chan, int pitch, int vol);
int (*Mf_pressure) (int chan, int pitch, int pressure);
int (*Mf_parameter) (int chan, int control, int value);
int (*Mf_pitchbend) (int chan, int msb, int lsb);
int (*Mf_program) (int chan, int program);
int (*Mf_chanpressure) (int chan, int pressure);
int (*Mf_sysex) (int leng, char *msg);
int (*Mf_metamisc) (int type, int leng, int msg);
int (*Mf_seqspecific) (int type, int leng, int msg);
int (*Mf_seqnum) (int num);
int (*Mf_text) (int type, int leng, int msg);
int (*Mf_eot) ();
int (*Mf_timesig) (int numer, int denom, int clocks, int qnotes);
int (*Mf_smpte) (int hour, int min, int sec, int frame, int fract);
int (*Mf_tempo) (int microsecs);
int (*Mf_keysig) (int sharpflat, int minor);
int (*Mf_arbitrary) (int leng, int msg);
int Mf_nomerge;
long Mf_currtime;

DESCRIPTION
The midifile function reads and inteprets a standard MIDI file. To use it you need to understand the general form of a MIDI file and the type of information it contains, but you don't need to know much, if anything, about the detailed format of the file and the mechanics of reading it reliably and portably. A single call to midifile will read an entire MIDI file. The interface to midifile is a set of external variables named Mf_*, most of which are function pointers to be called from within midifile during the process of parsing the MIDI file. Before calling midifile, the only requirement is that you assign a value to Mf_getc - a pointer to a function that will return characters from the MIDI file, using -1 to indicate EOF. All the rest of the function pointers are initialized to NULL, and the default action for each is to do nothing. The following is a complete program using midifile that could serve as a 'syntax checker' for MIDI files:
#include <stdio.h>
#include "midifile.h"
mygetc()
{
	/* use standard input */
	return(getchar());
}
main()
{
	Mf_getc = mygetc;
	midifile();
	exit(0);
}
This takes advantage of the default action when an error is detected, which is to exit silently with a return code of 1. An error function of your own can be used by giving a value to Mf_error; the function will be called with the error message as an argument. The other Mf_* variables can similarly be used to call arbitrary functions while parsing the MIDI file. The descriptions below of the information passed to these functions is sparse; refer to the MIDI file standard for the complete descriptions. Mf_header is the first function to be called, and its arguments contain information from the MIDI file's header; the format (0,1, or 2), the number of tracks, and the division of a quarter-note that defines the times units. Mf_trackstart and Mf_trackend are called at the beginning and end of each track. Once inside a track, each separate message causes a function to be called. For example, each note-on message causes Mf_noteon to be called with the channel, pitch, and volume as arguments. The time at which the message occurred is stored in Mf_currtime - one of the few external variables that isn't a function pointer. The other channel messages are handled in a similar and obvious fashion - Mf_noteoff, Mf_pressure, Mf_parameter, Mf_pitchbend, Mf_program, and Mf_chanpressure. See the declarations above for the arguments that are passed to each. System exclusive messages are handled by calling Mf_sysex, passing as arguments the message length and a pointer to a static buffer containing the entire message. The buffer is expanded when necessary; memory availability is the only limit to its size. Normally, 'continued' system exclusives are automatically merged, and Mf_sysex is only called once. It you want to disable this you can set Mf_nomerge to 1, causing Mf_sysex to be called once for each part of the message. Mf_seqnum is called by the meta message that provides a sequence number, which if present must appear at the beginning of a track. The tempo meta message causes Mf_tempo to be called; its argument is the number of microseconds per MIDI quarter-note (24 MIDI clocks). The end-of-track meta message causes Mf_eot to be called. The key signature meta message causes Mf_keysig to be called; the first argument conveys the number of sharps or flats, the second argument is 1 if the key is minor. The Mf_timesig and Mf_smpte functions are called when the corresponding meta messages are seen. See the MIDI file standard for a description of their arguments. The text messages in the MIDI file standard are of the following types:
0x01		Text Event
0x02		Copyright
0x03		Sequence/Track Name
0x04		Instrument
0x05		Lyric
0x06		Marker
0x07		Cue Point
0x08-0x0F	Reserverd but Undefined
Mf_text is called for each of these; the arguments are the type number, the message length, and a pointer to the message buffer. Misceallaneous meta messages are handled by Mf_metamisc, sequencer-specific messages are handled by Mf_seqspecific, and arbitrary "escape" messages (started with 0xF7) are handled by Mf_arbitrary.

EXAMPLE
The following is a strings-like program for MIDI files:
#include <stdio.h>
#include <ctype.h>
#include "midifile.h"
FILE *F;
mygetc() { return(getc(F)); }
mytext(type,leng,msg)
char *msg;
{
	char *p;
	char *ep = msg + leng;
	for ( p=msg; p<ep ; p++ )
		putchar( isprint(*p) ? *p : '?' );
	putchar(');
}
main(argc,argv)
char **argv;
{
	if ( argc > 1 )
		F = fopen(argv[1],"r");
	else
		F = stdin;
	Mf_getc = mygetc;
	Mf_text = mytext;
	midifile();
	exit(0);
}

AUTHOR
Tim Thompson, att!twitch!glimmer!tjt