PageRenderTime 26ms CodeModel.GetById 14ms app.highlight 8ms RepoModel.GetById 1ms app.codeStats 1ms

/project/jni/sdl_mixer/native_midi_gpl/readmidi_native.c

https://github.com/aichunyu/FFPlayer
C | 188 lines | 150 code | 11 blank | 27 comment | 45 complexity | 0ffa9dbcb349b0caa73a608a509f5032 MD5 | raw file
  1/************************************************************************
  2   readmidi.c -- last change: 1 Jan 96
  3
  4   Creates a linked list of each chunk in a midi file.
  5   ENTIRE MIDI FILE IS RETAINED IN MEMORY so that no additional malloc
  6   calls need be made to store the data of the events in the midi file.
  7
  8   Copyright (C) 1995-1996 Nathan I. Laredo
  9
 10   This program is modifiable/redistributable under the terms
 11   of the GNU General Public Licence.
 12
 13   You should have received a copy of the GNU General Public License
 14   along with this program; if not, write to the Free Software
 15   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 16   Send your comments and all your spare pocket change to
 17   laredo@gnu.ai.mit.edu (Nathan Laredo) or to PSC 1, BOX 709, 2401
 18   Kelly Drive, Lackland AFB, TX 78236-5128, USA.
 19 *************************************************************************/
 20/*    edited by Peter Kutak           */
 21/*    email : kutak@stonline.sk       */
 22
 23#if defined(linux) || defined(__FreeBSD__)
 24
 25#include "playmidi.h"
 26#include <unistd.h>
 27
 28int format, ntrks, division;
 29unsigned char *midifilebuf;
 30
 31/* the following few lines are needed for dealing with CMF files */
 32int reloadfm = 0;
 33extern void loadfm();
 34extern int seqfd, sb_dev, wantopl3, play_fm, fmloaded[256];
 35SEQ_USE_EXTBUF();
 36
 37extern struct miditrack seq[MAXTRKS];
 38extern unsigned long int default_tempo;
 39
 40unsigned short Read16()
 41{
 42    register unsigned short x;
 43
 44    x = (*(midifilebuf) << 8) | midifilebuf[1];
 45    midifilebuf += 2;
 46    return x;
 47}
 48
 49unsigned long Read32()
 50{
 51    register unsigned long x;
 52
 53    x = (*(midifilebuf) << 24) | (midifilebuf[1] << 16) |
 54	(midifilebuf[2] << 8) | midifilebuf[3];
 55    midifilebuf += 4;
 56    return x;
 57}
 58
 59int readmidi(filebuf, filelength)
 60unsigned char *filebuf;
 61off_t filelength;
 62{
 63    unsigned long int i = 0, track, tracklen;
 64
 65    midifilebuf = filebuf;
 66    /* allow user to specify header number in from large archive */
 67#if 0
 68    while (i != find_header && midifilebuf < (filebuf + filelength - 32)) {
 69	if (strncmp(midifilebuf, "MThd", 4) == 0) {
 70	    i++;
 71	    midifilebuf += 4;
 72	} else
 73	    midifilebuf++;
 74    }
 75    if (i != find_header) {	/* specified header was not found */
 76	midifilebuf = filebuf;
 77	return find_header = 0;
 78    }
 79#endif
 80    if (midifilebuf != filebuf)
 81	midifilebuf -= 4;
 82    i = Read32();
 83    if (i == RIFF) {
 84	midifilebuf += 16;
 85	i = Read32();
 86    }
 87    if (i == MThd) {
 88	tracklen = Read32();
 89	format = Read16();
 90	ntrks = Read16();
 91	division = Read16();
 92    } else if (i == CTMF) {
 93	/* load a creative labs CMF file, with instruments for fm */
 94	tracklen = midifilebuf[4] | (midifilebuf[5] << 8);
 95	format = 0;
 96	ntrks = 1;
 97	division = midifilebuf[6] | (midifilebuf[7] << 8);
 98	default_tempo = 1000000 * division /
 99		(midifilebuf[8] | (midifilebuf[9] << 8));
100	seq[0].data = filebuf + tracklen;
101	seq[0].length = filelength - tracklen;
102	i = (unsigned long int) (*(short *) &midifilebuf[2]) - 4;
103	/* if fm playback is enabled, load all fm patches from file */
104	if (play_fm) {
105	    struct sbi_instrument instr;
106	    int j, k;
107	    reloadfm = midifilebuf[32]; /* number of custom patches */
108            instr.device = sb_dev;
109	    for (j = 0; j < 32; j++)
110		instr.operators[j] = 0x3f;
111	    instr.key = FM_PATCH;
112	    for (j = 0; j < reloadfm && j < 255; j++) {
113                instr.channel = j;
114		fmloaded[j] = instr.key;
115                for (k = 0; k < 16; k++)
116		    instr.operators[k] = midifilebuf[i + (16 * j) + k];
117		SEQ_WRPATCH(&instr, sizeof(instr));
118	    }
119	}
120	return ntrks;
121    } else {
122	int found = 0;
123	while (!found && midifilebuf < (filebuf + filelength - 8))
124	    if (strncmp(midifilebuf, "MThd", 4) == 0)
125		found++;
126	    else
127		midifilebuf++;
128	if (found) {
129	    midifilebuf += 4;
130	    tracklen = Read32();
131	    format = Read16();
132	    ntrks = Read16();
133	    division = Read16();
134	} else {
135#ifndef DISABLE_RAW_MIDI_FILES
136	    /* this allows playing ANY file, so watch out */
137	    midifilebuf -= 4;
138	    format = 0;		/* assume it's .mus file ? */
139	    ntrks = 1;
140	    division = 40;
141#else
142	    return -1;
143#endif
144	}
145    }
146    if (ntrks > MAXTRKS) {
147	fprintf(stderr, "\nWARNING: %d TRACKS IGNORED!\n", ntrks - MAXTRKS);
148	ntrks = MAXTRKS;
149    }
150    if (play_fm && reloadfm) {
151	loadfm();	/* if custom CMF patches loaded, replace */
152	reloadfm = 0;
153    }
154    for (track = 0; track < ntrks; track++) {
155	if (Read32() != MTrk) {
156	    /* MTrk isn't where it's supposed to be, search rest of file */
157	    int fuzz, found = 0;
158	    midifilebuf -= 4;
159	    if (strncmp(midifilebuf, "MThd", 4) == 0)
160		continue;
161	    else {
162		if (!track) {
163		    seq[0].length = filebuf + filelength - midifilebuf;
164		    seq[0].data = midifilebuf;
165		    continue;	/* assume raw midi data file */
166		}
167		midifilebuf -= seq[track - 1].length;
168		for (fuzz = 0; (fuzz + midifilebuf) <
169		     (filebuf + filelength - 8) && !found; fuzz++)
170		    if (strncmp(&midifilebuf[fuzz], "MTrk", 4) == 0)
171			found++;
172		seq[track - 1].length = fuzz;
173		midifilebuf += fuzz;
174		if (!found)
175		    continue;
176	    }
177	}
178	tracklen = Read32();
179	if (midifilebuf + tracklen > filebuf + filelength)
180	    tracklen = filebuf + filelength - midifilebuf;
181	seq[track].length = tracklen;
182	seq[track].data = midifilebuf;
183	midifilebuf += tracklen;
184    }
185    ntrks = track;
186    return ntrks;
187}
188#endif /* linux || FreeBSD */