home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright 1991, 1992, 1993, 1994, Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
- * the contents of this file may not be disclosed to third parties, copied or
- * duplicated in any form, in whole or in part, without the prior written
- * permission of Silicon Graphics, Inc.
- *
- * RESTRICTED RIGHTS LEGEND:
- * Use, duplication or disclosure by the Government is subject to restrictions
- * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
- * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
- * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
- * rights reserved under the Copyright Laws of the United States.
- */
- /*
- * Copyright (C) 1991, Silicon Graphics, Inc.
- * All Rights Reserved.
- */
-
- /*
- * rdmf - Read a MIDI file
- *
- * Jim Bennett
- * 1991
- *
- * Contains the routines:
- * mf_read_hd (file, header)
- * mf_read_trk (file, resolution)
- */
-
- #include <stdio.h>
- #include "midif.h"
-
- extern int maxfinger;
-
- #ifdef DEBUG
-
- static int col = 0;
-
- #else
-
- #define GETC getc
-
- #endif
-
- /*
- * mf_read_hd - Read in MIDI file header
- *
- * Returns -1 if not a MIDI file
- */
-
- mf_read_hd (midifile, mf_header)
-
- FILE *midifile;
- struct s_mfhd *mf_header;
-
- {
- int c, n;
- char buf[8];
- long x;
-
- /* Check header of file */
-
- for (n=0; n<4; n++)
- {
- c = GETC (midifile);
- if (c == EOF) return (-1);
- buf [n] = c;
- }
- buf [n] = 0;
- if (strcmp (buf, MF_header) != 0) return (-1);
-
- /* Read in header */
-
- for (x=0, n=0; n<4; n++)
- {
- c = GETC (midifile);
- if (c == EOF) return (-1);
- x = (x << 8) + c;
- }
- if (x != 6) return (-1); /* Header length must be 6 */
-
- for (x=0, n=0; n<2; n++)
- {
- c = GETC (midifile);
- if (c == EOF) return (-1);
- x = (x << 8) + c;
- }
- mf_header->format = x;
-
- for (x=0, n=0; n<2; n++)
- {
- c = GETC (midifile);
- if (c == EOF) return (-1);
- x = (x << 8) + c;
- }
- mf_header->ntrks = x;
-
- for (x=0, n=0; n<2; n++)
- {
- c = GETC (midifile);
- if (c == EOF) return (-1);
- x = (x << 8) + c;
- }
- mf_header->division = x;
-
- return (0);
- }
-
- /*
- * mf_read_trk - Read in a single track
- *
- * Returns an array of events (struct s_mfevent)
- * Return negative error code if not a valid track
- * Sets the global variable maxfinger
- */
-
- struct s_mfevent *mf_read_trk (midifile, resolution)
-
- FILE *midifile;
- int resolution;
-
- {
- int c, n;
- char buf[8];
- long trklen, trkcnt;
- struct s_mfevent *mfv_base;
- struct s_mfevent *mfv;
- int evcnt, pitch, velocity;
- float mf_time;
- int last_status;
- int midi_event;
- int finger;
- int programs[16];
- int channels[16];
- int fingertab[16];
-
- last_status = -1;
- for (n=0; n<16; n++) programs[n] = n;
- for (n=0; n<16; n++) channels[n] = 0;
- for (n=0; n<16; n++) fingertab[n] = 0;
-
- /* Check for valid track */
-
- for (n=0; n<4; n++)
- {
- c = GETC (midifile);
- if (c == EOF) return ((struct s_mfevent *)-1);
- buf [n] = c;
- }
- buf [n] = 0;
- if (strcmp (buf, MF_track) != 0) return ((struct s_mfevent *)-2);
-
- /* Get length of track, and allocate an event buffer */
-
- for (trklen=0, n=0; n<4; n++)
- {
- c = GETC (midifile);
- if (c == EOF) return ((struct s_mfevent *)-3);
- trklen = (trklen << 8) + c;
- }
-
- mfv_base = (struct s_mfevent *)malloc
- (10000 * sizeof (struct s_mfevent));
- mfv = mfv_base;
-
- /* Process the track into events */
-
- finger = 0;
- maxfinger = 0;
- evcnt = 0;
- trkcnt = 0;
- mf_time = 0.0;
- while (1)
- {
-
- /* Per event: Get track relative time of event */
-
- for (n=0, c=0x80; c&0x80; )
- {
- c = GETC (midifile);
- if (c == EOF) return ((struct s_mfevent *)-4);
- trkcnt++;
- if (trkcnt > trklen) return ((struct s_mfevent *)-5);
-
- n = (n << 7) + (c & 0x7f);
- }
- mf_time = mf_time + (float)n / (float)resolution;
-
- /* Next classify event */
-
- c = GETC (midifile);
- if (c == EOF) return ((struct s_mfevent *)-6);
- trkcnt++;
- if (trkcnt > trklen) return ((struct s_mfevent *)-7);
-
- /* Check for end of track event */
-
- next_event:
- if (c == META_EVENT)
- {
- c = GETC (midifile);
- if (c == EOF) return ((struct s_mfevent *)-8);
- trkcnt++;
- if (trkcnt > trklen) return ((struct s_mfevent *)-9);
-
- if (c != END_TRACK) goto skip_event;
-
- c = GETC (midifile);
- if (c == EOF) return ((struct s_mfevent *)-10);
- trkcnt++;
-
- if (c != 0) return ((struct s_mfevent *)-11);
- if (trkcnt != trklen) return ((struct s_mfevent *)-12);
- goto end_of_track;
- }
-
- /* Skip over SYSEX events */
-
- if ((c == SYSEX_EVENT) || (c == SYSEX_EVENTA))
- {
- c = GETC (midifile);
- if (c == EOF) return ((struct s_mfevent *)-13);
- trkcnt++;
- if (trkcnt > trklen) return ((struct s_mfevent *)-14);
-
- goto skip_event;
- }
-
- /* Process normal MIDI events */
-
- midi_event = c;
-
- if (c >= 0x80)
- {
- c = GETC (midifile);
- if (c == EOF) return ((struct s_mfevent *)-15);
- trkcnt++;
- if (trkcnt > trklen)
- return ((struct s_mfevent *)-16);
-
- #ifdef DEBUG
- if (c >= 0x80)
- {
- printf ("\nInterrupt 1\n");
- goto next_event;
- }
- #endif
- }
-
- event_switch:
- switch (midi_event & 0xf0)
- {
- case NOTE_OFF:
- last_status = midi_event;
- pitch = c;
-
- c = GETC (midifile);
- if (c == EOF) return ((struct s_mfevent *)-17);
- trkcnt++;
- if (trkcnt > trklen)
- return ((struct s_mfevent *)-18);
-
- #ifdef DEBUG
- if (c >= 0x80)
- {
- printf ("\nInterrupt 2\n");
- goto next_event;
- }
- #endif
-
- velocity = c;
-
- channels[midi_event&0x0f] = 1;
- for (n=0; n<16; n++)
- if (fingertab[n] == pitch) break;
- finger = n;
- if (finger >= 16)
- {
- fprintf (stderr,
- "finger underflow!\n");
- }
- else
- {
- fingertab[finger] = 0;
- mfv->time = mf_time;
- mfv->event =
- (finger << 28) +
- (programs[midi_event&0x0f] << 24) +
- (NOTE_OFF << 16) +
- (velocity << 8) +
- pitch;
- mfv++;
- evcnt++;
- if (evcnt >= 10000)
- {
- fprintf (stderr, "Too many events!\n");
- return ((struct s_mfevent *)-20);
- }
- }
- break;
-
- case NOTE_ON:
- last_status = midi_event;
- pitch = c;
-
- c = GETC (midifile);
- if (c == EOF) return ((struct s_mfevent *)-21);
- trkcnt++;
- if (trkcnt > trklen)
- return ((struct s_mfevent *)-22);
-
- #ifdef DEBUG
- if (c >= 0x80)
- {
- printf ("\nInterrupt 3\n");
- goto next_event;
- }
- #endif
-
- velocity = c;
-
- channels[midi_event&0x0f] = 1;
- if (velocity == 0)
- {
- for (n=0; n<16; n++)
- if (fingertab[n] == pitch) break;
- finger = n;
- if (finger >= 16)
- {
- fprintf (stderr,
- "finger underflow!\n");
- }
- else
- {
- fingertab[finger] = 0;
- mfv->time = mf_time;
- mfv->event =
- (finger << 28) +
- (programs[midi_event&0x0f] << 24) +
- (NOTE_OFF << 16) +
- (velocity << 8) +
- pitch;
- mfv++;
- evcnt++;
- if (evcnt >= 10000)
- {
- fprintf (stderr, "Too many events!\n");
- return ((struct s_mfevent *)-25);
- }
- }
- }
- else
- {
- for (n=0; n<16; n++)
- if (fingertab[n] == 0) break;
- finger = n;
- if (finger >= 16)
- {
- fprintf (stderr,
- "finger overflow!\n");
- return ((struct s_mfevent *)-24);
- }
- fingertab[finger] = pitch;
- mfv->time = mf_time;
- mfv->event =
- (finger << 28) +
- (programs[midi_event&0x0f] << 24) +
- (NOTE_ON << 16) +
- (velocity << 8) +
- pitch;
- mfv++;
- evcnt++;
- if (evcnt >= 10000)
- {
- fprintf (stderr, "Too many events!\n");
- return ((struct s_mfevent *)-25);
- }
- finger++;
- if (finger > maxfinger)
- maxfinger = finger;
- }
- break;
-
- case KEY_PRESSURE:
- last_status = midi_event;
- goto skip_two;
-
- case PARAMETER:
- last_status = midi_event;
- goto skip_two;
-
- case PROGRAM:
- #ifdef DEBUG
- printf ("\nProgram change\n");
- #endif
- last_status = midi_event;
- /* Set program for this channel */
- programs[midi_event&0x0f] = c&0x0f;
- break;
-
- case CHAN_PRESSURE:
- last_status = midi_event;
- goto skip_one;
-
- case PITCH_WHEEL:
- last_status = midi_event;
- goto skip_two;
-
- default:
- if ((last_status > 0) && (midi_event <= 0x7f))
- {
- c = midi_event;
- midi_event = last_status;
- goto event_switch;
- }
- else
- return ((struct s_mfevent *)-26);
- }
- continue;
-
- /* skip_one, skip_two: skip one or two bytes */
-
- skip_two:
- c = GETC (midifile);
- if (c == EOF) return ((struct s_mfevent *)-27);
- trkcnt++;
- if (trkcnt > trklen) return ((struct s_mfevent *)-28);
-
- #ifdef DEBUG
- if (c >= 0x80)
- {
- printf ("\nInterrupt 4\n");
- goto next_event;
- }
- #endif
-
- skip_one:
- continue;
-
- /* skip_event: read event length and skip that many bytes */
-
- skip_event:
- for (n=0, c=0x80; c&0x80; )
- {
- c = GETC (midifile);
- if (c == EOF) return ((struct s_mfevent *)-29);
- trkcnt++;
- if (trkcnt > trklen) return ((struct s_mfevent *)-30);
-
- n = (n << 7) + (c & 0x7f);
- }
-
- while (n-- > 0)
- {
- c = GETC (midifile);
- if (c == EOF) return ((struct s_mfevent *)-31);
- trkcnt++;
- if (trkcnt > trklen) return ((struct s_mfevent *)-32);
- }
- }
-
- end_of_track:
- for (n=0; n<16; n++)
- if (fingertab[n] != 0) break;
- if (n < 16)
- {
- printf ("Too many fingers!\n");
- return ((struct s_mfevent *)-33);
- }
- #ifdef DEBUG
- printf ("%d events in this track\n", evcnt);
- printf ("%d fingers used in this track\n", maxfinger);
- printf ("Channels: %d %d %d %d %d %d %d %d\n",
- channels[0], channels[1], channels[2], channels[3],
- channels[4], channels[5], channels[6], channels[7]);
- printf (" %d %d %d %d %d %d %d %d\n",
- channels[8], channels[9], channels[10], channels[11],
- channels[12], channels[13], channels[14], channels[15]);
- #endif
- mfv->time = END_TIME;
- return (mfv_base);
- }
-
- #ifdef DEBUG
- /*
- * GETC - Input character and echo as hex byte
- */
-
- int GETC (f)
-
- FILE *f;
-
- {
- char buf[4];
- int ret;
-
- ret = read (fileno(f), buf, 1);
- if (ret == 1)
- ret = (buf[0])&0xff;
- else
- ret = EOF;
-
- col++;
- printf ("%2.2x", ret);
- if ((col & 0x0f) == 0)
- printf ("\n");
- else
- printf (" ");
-
- return (ret);
- }
- #endif
-