/* Functions to be called while processing the MIDI file. */
int (*mf_error)() = NULLFUNC;
int (*mf_noteon)() = NULLFUNC;
int (*mf_sysex)() = NULLFUNC;
int (*mf_arbitrary)() = NULLFUNC;
int (*mf_text)() = NULLFUNC;
int mf_nomerge = 0; /* 1 => continue'ed system exclusives are */
/* not collapsed. */
long mf_currtime = 0L; /* current time in delta-time units */
/* private stuff */
unsigned long mf_toberead = 0L;
int lastbyte;
static long readvarinum();
static long read32bit();
static long to32bit();
static int read16bit();
static int to16bit();
unsigned char huge *mid_buff = NULL;
unsigned char huge *buff_ptr = NULL;
unsigned char huge *end_of_mf = NULL;
unsigned char far *msg_start = NULL;
unsigned long msg_len = 0L;
unsigned int bufsegp;
unsigned long mf_size;
/* flush any extra stuff, in case the length of header is not 6 */
while ( mf_toberead > 0 )
(void) egetc();
}
static
readtrack() /* read a track chunk */
{
/* This array is indexed by the high half of a status byte. It's */
/* value is either the number of bytes needed (1 or 2) for a channel */
/* message, or 0 (meaning it's not a channel message). */
static int chantype[] = {
0, 0, 0, 0, 0, 0, 0, 0, /* 0x00 through 0x70 */
2, 2, 2, 2, 1, 1, 2, 0 /* 0x80 through 0xf0 */
};
unsigned long lookfor;
int c, c1, type;
int sysexcontinue = 0; /* 1 if last message was an unfinished sysex */
int running = 0; /* 1 when running status used */
int status = 0; /* status value (e.g. 0x90==note-on) */
int needed;
if ( readmt("MTrk") == EOF )
return(0);
mf_toberead = read32bit();
mf_currtime = 0L;
while ( mf_toberead > 0L ) {
mf_currtime += readvarinum(); /* delta time */
c = egetc();
if ( sysexcontinue && c != 0xf7 )
(*mf_error)("didn't find expected continuation of a sysex");
if ( (c & 0x80) == 0 ) { /* running status? */
if ( status == 0 )
(*mf_error)("unexpected running status");
running = 1;
}
else {
status = c;
running = 0;
}
needed = chantype[ (status>>4) & 0xf ];
if ( needed ) { /* ie. is it a channel message? */
static
metaevent(type)
{
switch ( type ) {
case 0x01: /* Text event */
case 0x02: /* Copyright notice */
case 0x03: /* Sequence/Track name */
case 0x04: /* Instrument name */
case 0x05: /* Lyric */
case 0x06: /* Marker */
case 0x07: /* Cue point */
case 0x08:
case 0x09:
case 0x0a:
case 0x0b:
case 0x0c:
case 0x0d:
case 0x0e:
case 0x0f: (*mf_text)(type, msg_len, msg_start);
}
}
chanmessage(int status, int c1, int c2)
{
int chan = status & 0xf;
switch ( status & 0xf0 )
{
case 0x90:
(*mf_noteon)(chan,c1,c2);
}
}
/* readvarinum - read a varying-length number, and return the */
/* number of characters it took. */
static long
readvarinum()
{
long value;
int c;
c = egetc();
value = c;
if ( c & 0x80 ) {
value &= 0x7f;
do {
c = egetc();
value = (value << 7) + (c & 0x7f);
} while (c & 0x80);
}
return (value);
}
static long
to32bit(c1,c2,c3,c4)
{
long value = 0L;
value = (c1 & 0xff);
value = (value<<8) + (c2 & 0xff);
value = (value<<8) + (c3 & 0xff);
value = (value<<8) + (c4 & 0xff);
return (value);
}