Lines Matching defs:*
2 * midifile 1.11
4 * Read and write a MIDI file. Externally-assigned function pointers are
5 * called upon recognizing things in the file.
7 * Original release ?
8 * June 1989 - Added writing capability, M. Czeiszperger.
10 * The file format implemented here is called
11 * Standard MIDI Files, and is part of the Musical
12 * instrument Digital Interface specification.
13 * The spec is available from:
15 * International MIDI Association
16 * 5316 West 57th Street
17 * Los Angeles, CA 90056
19 * An in-depth description of the spec can also be found
20 * in the article "Introducing Standard MIDI Files", published
21 * in Electronic Musician magazine, April, 1989.
23 * February 1993 - Minor adjustments, Greg Lee:
24 * (1) can now set the global variable Mf_interactive to 1 to prevent the
25 * reading functions from looking for file and track headers
26 * (2) can now write system exclusive data with
27 * mf_write_midi_event(delta_time, system_exclusive, 0, data, size)
28 * (3) changed definition of 'sequencer_specific' in midifile.h to 0x7f
29 * (4) changed mf_write_tempo to take additional delta_time as first argument
30 * (since delta need not be zero)
31 * (5) added function mf_write_seqnum(unsigned long delta_time, unsigned seqnum)
32 * (6) changed mf_write_midi_event to use running status
33 * (7) removed the code to write an end of track meta event automatically
34 * -- this must now be done by the user of the library (I changed
35 * it because I need to be able to control the time delta of this
36 * meta event)
37 * (8) added global variables Mf_division, Mf_currtempo, Mf_realtime, which
38 * are updated by the reading functions. Mf_realtime is useful,
39 * because Mf_currtime does not really measure time at all, since
40 * its units change value at every tempo change. Mf_realtime is
41 * the midi-time elapsed in units of 1/16 of a centisecond (but it
42 * does not handle SMPTE times)
43 * (9) maintains a history of tempo settings to update Mf_currtempo,
44 * to handle tempo tracks.
45 * (10) if there is an Mf_error function, the error routine no longer
46 * exits, leaving it to the application to do this.
47 * (11) chanmessage skips over invalid c1 command bytes > 127 and
48 * adjusts invalid c2 argument byte > 127 to 127.
49 * (12) readmt returns EOF when it encounters a 0 or 0x1a byte instead of an expected
50 * header string (some midi files have padding at end).
52 #define NO_LC_DEFINES
53 #include "midifile.h"
54 #ifdef NO_LC_DEFINES
55 #define system_exclusive 0xf0
56 #define meta_event 0xFF
57 #define set_tempo 0x51
58 #define lowerbyte(x) ((unsigned char)(x & 0xff))
59 #define upperbyte(x) ((unsigned char)((x & 0xff00)>>8))
60 #endif
62 #define NULLFUNC 0
63 #if 0
64 #define NULL 0
65 #endif
67 #define THINK
69 #ifdef THINK
70 #include <stdlib.h>
71 #endif
73 #include <stdio.h>
74 #include <values.h>
76 #include <string.h>
77 /*void exit(), free();*/
79 /* public stuff */
81 /* Functions to be called while processing the MIDI file. */
82 int (*Mf_getc) () = NULLFUNC;
83 void (*Mf_error) () = NULLFUNC;
84 void (*Mf_header) () = NULLFUNC;
85 void (*Mf_trackstart) () = NULLFUNC;
86 void (*Mf_trackend) () = NULLFUNC;
87 void (*Mf_noteon) () = NULLFUNC;
88 void (*Mf_noteoff) () = NULLFUNC;
89 void (*Mf_pressure) () = NULLFUNC;
90 void (*Mf_parameter) () = NULLFUNC;
91 void (*Mf_pitchbend) () = NULLFUNC;
92 void (*Mf_program) () = NULLFUNC;
93 void (*Mf_chanpressure) () = NULLFUNC;
94 void (*Mf_sysex) () = NULLFUNC;
95 void (*Mf_arbitrary) () = NULLFUNC;
96 void (*Mf_metamisc) () = NULLFUNC;
97 void (*Mf_seqnum) () = NULLFUNC;
98 void (*Mf_eot) () = NULLFUNC;
99 void (*Mf_smpte) () = NULLFUNC;
100 void (*Mf_tempo) () = NULLFUNC;
101 void (*Mf_timesig) () = NULLFUNC;
102 void (*Mf_keysig) () = NULLFUNC;
103 void (*Mf_seqspecific) () = NULLFUNC;
104 void (*Mf_text) () = NULLFUNC;
106 /* Functions to implement in order to write a MIDI file */
107 int (*Mf_putc) () = NULLFUNC;
108 int (*Mf_writetrack) () = NULLFUNC;
109 int (*Mf_writetempotrack) () = NULLFUNC;
111 int Mf_nomerge = 0; /* 1 => continue'ed system exclusives are */
112 /* not collapsed. */
113 int Mf_interactive = 0; /* 1 => file and track headers are not required */
114 unsigned long Mf_currtime = 0L; /* current time in delta-time units */
115 unsigned long Mf_realtime = 0L; /* current time in 1/16 centisecond-time units */
116 static double Mf_f_realtime = 0;/* as above, floating */
117 static double old_f_realtime = 0;
118 int Mf_division = 96;
119 unsigned long Mf_currtempo = 500000;
120 static unsigned long old_currtempo = 500000;
121 static unsigned long old_realtime = 0;
122 static unsigned long old_currtime = 0;
123 static unsigned long revised_time = 0;
124 static unsigned long tempo_change_time = 0;
126 #define MAX_HISTORY 512
127 static unsigned long tempo_history[MAX_HISTORY];
128 static unsigned long tempo_history_time[MAX_HISTORY];
129 static int tempo_history_count = 0;
131 /* private stuff */
132 static long Mf_toberead = 0L;
133 static long Mf_numbyteswritten = 0L;
135 static long readvarinum ();
136 static long read32bit ();
137 static long to32bit ();
138 static int read16bit ();
139 static int to16bit ();
140 static char *msg ();
141 static void readheader ();
142 static int readtrack ();
143 static void badbyte ();
144 static void metaevent ();
145 static void sysex ();
146 static void chanmessage ();
147 static void msginit ();
148 static int msgleng ();
149 static void msgadd ();
150 static void biggermsg ();
151 static int eputc (unsigned char c);
153 double mf_ticks2sec (unsigned long ticks, int division, unsigned long tempo);
154 int mf_write_meta_event ();
155 void mf_write_tempo ();
156 void mf_write_seqnum ();
157 void WriteVarLen ();
159 #ifdef READ_MODS
160 #include "mp_mod.c"
161 static int mod_file_flag = 0;
162 #endif /* READ_MODS */
163 static int force_exit;
165 void
166 mfread ()
168 force_exit = 0;
169 if (Mf_getc == NULLFUNC)
170 mferror ("mfread() called without setting Mf_getc");
172 readheader ();
173 #ifdef READ_MODS
174 if (mod_file_flag)
175 do_module();
176 else
177 #endif
178 while (readtrack () && !force_exit)
182 /* for backward compatibility with the original lib */
183 void
184 midifile ()
186 mfread ();
189 static
190 int
191 readmt (s) /* read through the "MThd" or "MTrk" header string */
192 char *s;
194 int n = 0;
195 char *p = s;
196 int c;
198 while (n++ < 4 && (c = (*Mf_getc) ()) != EOF)
200 if (c != *p++)
202 char buff[32];
203 if (!c) return(EOF);
204 if (c == 0x1a) return(EOF);
205 (void) strcpy (buff, "expecting ");
206 (void) strcat (buff, s);
207 mferror (buff);
208 break;
211 return (c);
214 static
215 int
216 egetc () /* read a single character and abort on EOF */
218 int c = (*Mf_getc) ();
220 if (c == EOF) {
221 mferror ("premature EOF");
222 force_exit = 1;
224 Mf_toberead--;
225 return (c);
228 static
229 void
230 readheader () /* read a header chunk */
232 int format, ntrks, division;
235 Mf_division = 96;
236 Mf_currtempo = 500000;
237 old_currtempo = 500000;
238 tempo_history_count = 0;
239 tempo_history[tempo_history_count] = Mf_currtempo;
240 tempo_history_time[tempo_history_count] = 0;
242 if (Mf_interactive)
244 Mf_toberead = 0;
245 format = 0;
246 ntrks = 1;
247 division = 96;
249 else
250 #ifdef READ_MODS
251 if (!strncmp(Mf_file_contents, "MThd", 4))
252 #endif
254 if (readmt ("MThd") == EOF)
255 return;
257 Mf_toberead = read32bit ();
258 format = read16bit ();
259 ntrks = read16bit ();
260 Mf_division = division = read16bit ();
262 #ifdef READ_MODS
263 else
265 format = 0;
266 ntrks = 1;
267 division = Mf_division;
268 Mf_toberead = 0;
269 mod_file_flag = 1;
271 #endif
273 if (Mf_header)
274 (*Mf_header) (format, ntrks, division);
276 /* flush any extra stuff, in case the length of header is not 6 */
277 while (Mf_toberead > 0 && !force_exit)
278 (void) egetc ();
282 /*#define DEBUG_TIMES*/
283 static
284 unsigned long
285 find_tempo()
287 int i;
288 unsigned long old_tempo = Mf_currtempo;
289 unsigned long new_tempo = Mf_currtempo;
291 for (i = 0; i <= tempo_history_count; i++) {
292 if (tempo_history_time[i] <= Mf_currtime) old_tempo = tempo_history[i];
293 new_tempo = tempo_history[i];
294 if (tempo_history_time[i] > revised_time) break;
296 if (i > tempo_history_count || tempo_history_time[i] > Mf_currtime) {
297 #ifdef DEBUG_TIMES
298 printf("[past %d, old_tempo %d]\n", tempo_history_time[i], old_tempo);
299 #endif
300 revised_time = Mf_currtime;
301 return(old_tempo);
303 tempo_change_time = revised_time = tempo_history_time[i];
304 #ifdef DEBUG_TIMES
305 printf("[revised_time %d, new_tempo %d]\n", revised_time, new_tempo);
306 #endif
307 return(new_tempo);
310 static
311 int
312 readtrack () /* read a track chunk */
314 /* This array is indexed by the high half of a status byte. It's */
315 /* value is either the number of bytes needed (1 or 2) for a channel */
316 /* message, or 0 (meaning it's not a channel message). */
317 static int chantype[] =
319 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00 through 0x70 */
320 2, 2, 2, 2, 1, 1, 2, 0 /* 0x80 through 0xf0 */
322 long lookfor;
323 int c, c1, type;
324 int sysexcontinue = 0; /* 1 if last message was an unfinished sysex */
325 int running = 0; /* 1 when running status used */
326 int status = 0; /* status value (e.g. 0x90==note-on) */
327 int needed;
329 if (Mf_interactive)
331 Mf_toberead = MAXINT;
333 else
335 if (readmt ("MTrk") == EOF)
336 return (0);
338 Mf_toberead = read32bit ();
340 Mf_currtime = Mf_realtime = 0;
341 Mf_f_realtime = old_f_realtime = 0;
342 old_currtime = old_realtime = 0;
343 Mf_currtempo = find_tempo();
345 if (Mf_trackstart)
346 (*Mf_trackstart) ();
348 while (!force_exit && (Mf_interactive || Mf_toberead > 0))
351 if (Mf_interactive)
352 Mf_currtime += 1;
353 else
355 double delta_secs;
356 unsigned long delta_ticks = readvarinum ();
357 revised_time = Mf_currtime;
358 Mf_currtime += delta_ticks; /* delta time */
361 * Step through each tempo change from old_currtime up to now,
362 * revising Mf_realtime after each change.
365 while (revised_time < Mf_currtime) {
366 unsigned long save_time = revised_time;
367 unsigned long save_tempo = Mf_currtempo;
368 Mf_currtempo = find_tempo();
370 if (Mf_currtempo != old_currtempo) {
371 old_currtempo = Mf_currtempo;
372 old_realtime = Mf_realtime;
373 if (revised_time != tempo_change_time) {
374 old_f_realtime = Mf_f_realtime;
375 old_currtime = save_time;
377 delta_secs = mf_ticks2sec (revised_time-old_currtime, Mf_division, save_tempo);
378 #ifdef DEBUG_TIMES
379 printf("d(rev %d - old %d, div %d, tempo %d) = %.3f\n",
380 revised_time, old_currtime, Mf_division, save_tempo, delta_secs * 1600.0);
381 #endif
382 Mf_f_realtime = old_f_realtime + delta_secs * 1600.0;
383 Mf_realtime = (unsigned long)(0.5 + Mf_f_realtime);
384 #ifdef DEBUG_TIMES
385 printf("\tt=%d ticks ( = %d csec/16 < old %.2f + %.2f)\n", Mf_currtime, Mf_realtime,
386 old_f_realtime, delta_secs * 1600.0);
387 #endif
388 if (revised_time == tempo_change_time) {
389 old_currtime = revised_time;
390 old_f_realtime = Mf_f_realtime;
393 else {
394 delta_secs = mf_ticks2sec (revised_time-old_currtime, Mf_division, Mf_currtempo);
395 #ifdef DEBUG_TIMES
396 printf("d(rev %d - old %d, div %d, tempo %d) = %.3f\n",
397 revised_time, old_currtime, Mf_division, Mf_currtempo, delta_secs * 1600.0);
398 #endif
399 Mf_f_realtime = old_f_realtime + delta_secs * 1600.0;
400 Mf_realtime = (unsigned long)(0.5 + Mf_f_realtime);
401 #ifdef DEBUG_TIMES
402 printf("\tt=%d ticks ( = %d csec/16 < old %.2f + %.2f)\n", Mf_currtime, Mf_realtime,
403 old_f_realtime, delta_secs * 1600.0);
404 #endif
411 c = egetc ();
413 if (sysexcontinue && c != 0xf7)
414 mferror ("didn't find expected continuation of a sysex");
416 if ((c & 0x80) == 0)
417 { /* running status? */
418 if (status == 0)
419 mferror ("unexpected running status");
420 running = 1;
422 else
424 status = c;
425 running = 0;
428 needed = chantype[(status >> 4) & 0xf];
430 if (needed)
431 { /* ie. is it a channel message? */
433 if (running)
434 c1 = c;
435 else
436 c1 = egetc ();
437 chanmessage (status, c1, (needed > 1) ? egetc () : 0);
438 continue;;
441 switch (c)
444 case 0xff: /* meta event */
446 type = egetc ();
447 lookfor = Mf_toberead - readvarinum ();
448 msginit ();
450 while (Mf_toberead > lookfor)
451 msgadd (egetc ());
453 metaevent (type);
454 break;
456 case 0xf0: /* start of system exclusive */
458 lookfor = Mf_toberead - readvarinum ();
459 msginit ();
460 msgadd (0xf0);
462 while (Mf_toberead > lookfor)
463 msgadd (c = egetc ());
465 if (c == 0xf7 || Mf_nomerge == 0)
466 sysex ();
467 else
468 sysexcontinue = 1; /* merge into next msg */
469 break;
471 case 0xf7: /* sysex continuation or arbitrary stuff */
473 lookfor = Mf_toberead - readvarinum ();
475 if (!sysexcontinue)
476 msginit ();
478 while (Mf_toberead > lookfor)
479 msgadd (c = egetc ());
481 if (!sysexcontinue)
483 if (Mf_arbitrary)
484 (*Mf_arbitrary) (msgleng (), msg ());
486 else if (c == 0xf7)
488 sysex ();
489 sysexcontinue = 0;
491 break;
492 default:
493 badbyte (c);
494 break;
497 if (Mf_trackend)
498 (*Mf_trackend) ();
499 return (1);
502 static
503 void
504 badbyte (c)
505 int c;
507 char buff[32];
509 (void) sprintf (buff, "unexpected byte: 0x%02x", c);
510 mferror (buff);
513 static
514 void
515 metaevent (int type)
517 int leng = msgleng ();
518 char *m = msg ();
520 switch (type)
522 case 0x00:
523 if (Mf_seqnum)
524 (*Mf_seqnum) (to16bit (m[0], m[1]));
525 break;
526 case 0x01: /* Text event */
527 case 0x02: /* Copyright notice */
528 case 0x03: /* Sequence/Track name */
529 case 0x04: /* Instrument name */
530 case 0x05: /* Lyric */
531 case 0x06: /* Marker */
532 case 0x07: /* Cue point */
533 case 0x08:
534 case 0x09:
535 case 0x0a:
536 case 0x0b:
537 case 0x0c:
538 case 0x0d:
539 case 0x0e:
540 case 0x0f:
541 /* These are all text events */
542 if (Mf_text)
543 (*Mf_text) (type, leng, m);
544 break;
545 case 0x2f: /* End of Track */
546 if (Mf_eot)
547 (*Mf_eot) ();
548 break;
549 case 0x51: /* Set tempo */
550 if (Mf_tempo)
551 (*Mf_tempo) (Mf_currtempo = to32bit (0, m[0], m[1], m[2]));
552 if (tempo_history[tempo_history_count] == Mf_currtempo) break;
553 if (tempo_history_time[tempo_history_count] > Mf_currtime) break;
554 if (tempo_history_count < MAX_HISTORY - 1) tempo_history_count++;
555 tempo_history[tempo_history_count] = Mf_currtempo;
556 tempo_history_time[tempo_history_count] = Mf_currtime;
557 break;
558 case 0x54:
559 if (Mf_smpte)
560 (*Mf_smpte) (m[0], m[1], m[2], m[3], m[4]);
561 break;
562 case 0x58:
563 if (Mf_timesig)
564 (*Mf_timesig) (m[0], m[1], m[2], m[3]);
565 break;
566 case 0x59:
567 if (Mf_keysig)
568 (*Mf_keysig) (m[0], m[1]);
569 break;
570 case 0x7f:
571 if (Mf_seqspecific)
572 (*Mf_seqspecific) (leng, m);
573 break;
574 default:
575 if (Mf_metamisc)
576 (*Mf_metamisc) (type, leng, m);
580 static
581 void
582 sysex ()
584 if (Mf_sysex)
585 (*Mf_sysex) (msgleng (), msg ());
588 static
589 void
590 chanmessage (status, c1, c2)
591 int status;
592 int c1, c2;
594 int chan = status & 0xf;
596 /* I found a midi file with Mod Wheel values 128. --gl */
598 if (c1 > 127) /*mferror("chanmessage: bad c1") ??*/ return;
599 if (c2 > 127) c2 = 127;
601 switch (status & 0xf0)
603 case 0x80:
604 if (Mf_noteoff)
605 (*Mf_noteoff) (chan, c1, c2);
606 break;
607 case 0x90:
608 if (Mf_noteon)
609 (*Mf_noteon) (chan, c1, c2);
610 break;
611 case 0xa0:
612 if (Mf_pressure)
613 (*Mf_pressure) (chan, c1, c2);
614 break;
615 case 0xb0:
616 if (Mf_parameter)
617 (*Mf_parameter) (chan, c1, c2);
618 break;
619 case 0xe0:
620 if (Mf_pitchbend)
621 (*Mf_pitchbend) (chan, c1, c2);
622 break;
623 case 0xc0:
624 if (Mf_program)
625 (*Mf_program) (chan, c1);
626 break;
627 case 0xd0:
628 if (Mf_chanpressure)
629 (*Mf_chanpressure) (chan, c1);
630 break;
634 /* readvarinum - read a varying-length number, and return the */
635 /* number of characters it took. */
637 static long
638 readvarinum ()
640 long value;
641 int c;
643 c = egetc ();
644 value = c;
645 if (c & 0x80)
647 value &= 0x7f;
648 do
650 c = egetc ();
651 value = (value << 7) + (c & 0x7f);
653 while (c & 0x80);
655 return (value);
658 static long
659 to32bit (int c1, int c2, int c3, int c4)
661 long value = 0L;
663 value = (c1 & 0xff);
664 value = (value << 8) + (c2 & 0xff);
665 value = (value << 8) + (c3 & 0xff);
666 value = (value << 8) + (c4 & 0xff);
667 return (value);
670 static int
671 to16bit (c1, c2)
672 int c1, c2;
674 return ((c1 & 0xff) << 8) + (c2 & 0xff);
677 static long
678 read32bit ()
680 int c1, c2, c3, c4;
682 c1 = egetc ();
683 c2 = egetc ();
684 c3 = egetc ();
685 c4 = egetc ();
686 return to32bit (c1, c2, c3, c4);
689 static int
690 read16bit ()
692 int c1, c2;
693 c1 = egetc ();
694 c2 = egetc ();
695 return to16bit (c1, c2);
698 /* static */
699 void
700 mferror (s)
701 char *s;
703 if (Mf_error)
704 (*Mf_error) (s);
705 else exit (1);
708 /* The code below allows collection of a system exclusive message of */
709 /* arbitrary length. The Msgbuff is expanded as necessary. The only */
710 /* visible data/routines are msginit(), msgadd(), msg(), msgleng(). */
712 #define MSGINCREMENT 128
713 static char *Msgbuff = NULL; /* message buffer */
714 static int Msgsize = 0; /* Size of currently allocated Msg */
715 static int Msgindex = 0; /* index of next available location in Msg */
717 static
718 void
719 msginit ()
721 Msgindex = 0;
724 static char *
725 msg ()
727 return (Msgbuff);
730 static
731 int
732 msgleng ()
734 return (Msgindex);
737 static
738 void
739 msgadd (c)
740 int c;
742 /* If necessary, allocate larger message buffer. */
743 if (Msgindex >= Msgsize)
744 biggermsg ();
745 Msgbuff[Msgindex++] = c;
748 static
749 void
750 biggermsg ()
752 /* char *malloc(); */
753 char *newmess;
754 char *oldmess = Msgbuff;
755 int oldleng = Msgsize;
757 Msgsize += MSGINCREMENT;
758 newmess = (char *) malloc ((unsigned) (sizeof (char) * Msgsize));
760 if (newmess == NULL)
761 mferror ("malloc error!");
763 /* copy old message into larger new one */
764 if (oldmess != NULL)
766 register char *p = newmess;
767 register char *q = oldmess;
768 register char *endq = &oldmess[oldleng];
770 for (; q != endq; p++, q++)
771 *p = *q;
772 free (oldmess);
774 Msgbuff = newmess;
777 static int laststatus = 0;
780 * mfwrite() - The only function you'll need to call to write out
781 * a midi file.
783 * format 0 - Single multi-channel track
784 * 1 - Multiple simultaneous tracks
785 * 2 - One or more sequentially independent
786 * single track patterns
787 * ntracks The number of tracks in the file.
788 * division This is kind of tricky, it can represent two
789 * things, depending on whether it is positive or negative
790 * (bit 15 set or not). If bit 15 of division is zero,
791 * bits 14 through 0 represent the number of delta-time
792 * "ticks" which make up a quarter note. If bit 15 of
793 * division is a one, delta-times in a file correspond to
794 * subdivisions of a second similar to SMPTE and MIDI
795 * time code. In this format bits 14 through 8 contain
796 * one of four values - 24, -25, -29, or -30,
797 * corresponding to the four standard SMPTE and MIDI
798 * time code frame per second formats, where -29
799 * represents 30 drop frame. The second byte
800 * consisting of bits 7 through 0 corresponds the the
801 * resolution within a frame. Refer the Standard MIDI
802 * Files 1.0 spec for more details.
803 * fp This should be the open file pointer to the file you
804 * want to write. It will have be a global in order
805 * to work with Mf_putc.
807 void
808 mfwrite (format, ntracks, division, fp)
809 int format, ntracks, division;
810 FILE *fp;
812 int i;
813 void mf_write_track_chunk (), mf_write_header_chunk ();
815 if (Mf_putc == NULLFUNC)
816 mferror ("mfmf_write() called without setting Mf_putc");
818 if (Mf_writetrack == NULLFUNC)
819 mferror ("mfmf_write() called without setting Mf_mf_writetrack");
821 laststatus = 0;
823 /* every MIDI file starts with a header */
824 mf_write_header_chunk (format, ntracks, division);
826 laststatus = 0;
828 /* In format 1 files, the first track is a tempo map */
829 if (format == 1 && (Mf_writetempotrack))
831 (*Mf_writetempotrack) ();
834 /* The rest of the file is a series of tracks */
835 for (i = 0; i < ntracks; i++)
836 mf_write_track_chunk (i, fp);
839 void
840 mf_write_track_chunk (which_track, fp)
841 int which_track;
842 FILE *fp;
844 unsigned long trkhdr, trklength;
845 long offset, place_marker;
846 void write16bit (), write32bit ();
849 laststatus = 0;
851 trkhdr = MTrk;
852 trklength = 0;
854 /* Remember where the length was written, because we don't
855 know how long it will be until we've finished writing */
856 offset = ftell (fp);
858 #ifdef DEBUG
859 printf ("offset = %d\n", (int) offset);
860 #endif
862 /* Write the track chunk header */
863 write32bit (trkhdr);
864 write32bit (trklength);
866 Mf_numbyteswritten = 0L; /* the header's length doesn't count */
868 if (Mf_writetrack)
870 (*Mf_writetrack) (which_track);
873 /* mf_write End of track meta event */
874 /* but this does not necessarily have a delta of 0, so
875 * I don't want to do it -- leave it up to the user of the
876 * library functions to do
877 * --gl
878 eputc(0);
879 eputc(laststatus = meta_event);
880 eputc(end_of_track);
882 eputc(0);
885 /* It's impossible to know how long the track chunk will be beforehand,
886 so the position of the track length data is kept so that it can
887 be written after the chunk has been generated */
888 place_marker = ftell (fp);
890 /* This method turned out not to be portable because the
891 parameter returned from ftell is not guaranteed to be
892 in bytes on every machine */
893 /* track.length = place_marker - offset - (long) sizeof(track); */
895 #ifdef DEBUG
896 printf ("length = %d\n", (int) trklength);
897 #endif
899 if (fseek (fp, offset, 0) < 0)
900 mferror ("error seeking during final stage of write");
902 trklength = Mf_numbyteswritten;
904 /* Re-mf_write the track chunk header with right length */
905 write32bit (trkhdr);
906 write32bit (trklength);
908 fseek (fp, place_marker, 0);
909 } /* End gen_track_chunk() */
912 void
913 mf_write_header_chunk (format, ntracks, division)
914 int format, ntracks, division;
916 unsigned long ident, length;
917 void write16bit (), write32bit ();
919 ident = MThd; /* Head chunk identifier */
920 length = 6; /* Chunk length */
922 /* individual bytes of the header must be written separately
923 to preserve byte order across cpu types :-( */
924 write32bit (ident);
925 write32bit (length);
926 write16bit (format);
927 write16bit (ntracks);
928 write16bit (division);
929 } /* end gen_header_chunk() */
933 * mf_write_midi_event()
935 * Library routine to mf_write a single MIDI track event in the standard MIDI
936 * file format. The format is:
938 * <delta-time><event>
940 * In this case, event can be any multi-byte midi message, such as
941 * "note on", "note off", etc.
943 * delta_time - the time in ticks since the last event.
944 * type - the type of meta event.
945 * chan - The midi channel.
946 * data - A pointer to a block of chars containing the META EVENT,
947 * data.
948 * size - The length of the meta-event data.
950 int
951 mf_write_midi_event (delta_time, type, chan, data, size)
952 unsigned long delta_time;
953 int chan, type;
954 unsigned long size;
955 char *data;
957 int i;
958 unsigned char c;
960 WriteVarLen (delta_time);
962 /* all MIDI events start with the type in the first four bits,
963 and the channel in the lower four bits */
964 if (type == system_exclusive || type == 0xf7)
966 c = type;
967 laststatus = 0;
969 else
970 c = type | chan;
972 if (chan > 15)
973 perror ("error: MIDI channel greater than 16\n");
975 if (laststatus != c)
976 eputc (laststatus = c);
978 if (type == system_exclusive || type == 0xf7)
979 WriteVarLen (size);
981 /* write out the data bytes */
982 for (i = 0; i < (int)size; i++)
983 eputc (data[i]);
985 return (size);
986 } /* end mf_write MIDI event */
989 * mf_write_meta_event()
991 * Library routine to mf_write a single meta event in the standard MIDI
992 * file format. The format of a meta event is:
994 * <delta-time><FF><type><length><bytes>
996 * delta_time - the time in ticks since the last event.
997 * type - the type of meta event.
998 * data - A pointer to a block of chars containing the META EVENT,
999 * data.
1000 * size - The length of the meta-event data.
1002 int
1003 mf_write_meta_event (delta_time, type, data, size)
1004 unsigned long delta_time;
1005 unsigned char *data, type;
1006 unsigned long size;
1008 int i;
1010 WriteVarLen (delta_time);
1012 /* This marks the fact we're writing a meta-event */
1013 eputc (laststatus = meta_event);
1015 /* The type of meta event */
1016 eputc (type);
1018 /* The length of the data bytes to follow */
1019 WriteVarLen (size);
1021 for (i = 0; i < (int)size; i++)
1023 if (eputc (data[i]) != data[i])
1024 return (-1);
1026 return (size);
1027 } /* end mf_write_meta_event */
1029 void
1030 mf_write_tempo (delta_time, tempo)
1031 unsigned long delta_time;
1032 unsigned long tempo;
1034 /* Write tempo */
1035 /* all tempos are written as 120 beats/minute, */
1036 /* expressed in microseconds/quarter note */
1038 WriteVarLen (delta_time);
1039 eputc (laststatus = meta_event);
1040 eputc (set_tempo);
1042 eputc (3);
1043 eputc ((unsigned) (0xff & (tempo >> 16)));
1044 eputc ((unsigned) (0xff & (tempo >> 8)));
1045 eputc ((unsigned) (0xff & tempo));
1048 void
1049 mf_write_seqnum (delta_time, seqnum)
1050 unsigned long delta_time;
1051 unsigned seqnum;
1054 WriteVarLen (delta_time);
1055 eputc (laststatus = meta_event);
1056 eputc (0);
1058 eputc ((unsigned) (0xff & (seqnum >> 8)));
1059 eputc ((unsigned) (0xff & seqnum));
1062 unsigned long
1063 mf_sec2ticks (secs, division, tempo)
1064 int division;
1065 unsigned long tempo;
1066 double secs;
1068 return (unsigned long) (((secs * 1000.0) / 4.0 * division) / tempo);
1072 * Write multi-length bytes to MIDI format files
1074 void
1075 WriteVarLen (value)
1076 unsigned long value;
1078 unsigned long buffer;
1080 buffer = value & 0x7f;
1081 while ((value >>= 7) > 0)
1083 buffer <<= 8;
1084 buffer |= 0x80;
1085 buffer += (value & 0x7f);
1087 while (1)
1089 eputc ((unsigned) (buffer & 0xff));
1091 if (buffer & 0x80)
1092 buffer >>= 8;
1093 else
1094 return;
1096 } /* end of WriteVarLen */
1099 * This routine converts delta times in ticks into seconds. The
1100 * else statement is needed because the formula is different for tracks
1101 * based on notes and tracks based on SMPTE times.
1104 double
1105 mf_ticks2sec (ticks, division, tempo)
1106 int division;
1107 unsigned long tempo;
1108 unsigned long ticks;
1110 double smpte_format, smpte_resolution;
1112 if (division > 0)
1113 return ((double) (((double) (ticks) * (double) (tempo)) / ((double) (division) * 1000000.0)));
1114 else
1116 smpte_format = upperbyte (division);
1117 smpte_resolution = lowerbyte (division);
1118 return (double) ((double) ticks / (smpte_format * smpte_resolution * 1000000.0));
1120 } /* end of ticks2sec() */
1124 * write32bit()
1125 * write16bit()
1127 * These routines are used to make sure that the byte order of
1128 * the various data types remains constant between machines. This
1129 * helps make sure that the code will be portable from one system
1130 * to the next. It is slightly dangerous that it assumes that longs
1131 * have at least 32 bits and ints have at least 16 bits, but this
1132 * has been true at least on PCs, UNIX machines, and Macintosh's.
1135 void
1136 write32bit (data)
1137 unsigned long data;
1139 eputc ((unsigned) ((data >> 24) & 0xff));
1140 eputc ((unsigned) ((data >> 16) & 0xff));
1141 eputc ((unsigned) ((data >> 8) & 0xff));
1142 eputc ((unsigned) (data & 0xff));
1145 void
1146 write16bit (data)
1147 int data;
1149 eputc ((unsigned) ((data & 0xff00) >> 8));
1150 eputc ((unsigned) (data & 0xff));
1153 /* write a single character and abort on error */
1154 static int
1155 eputc (c)
1156 unsigned char c;
1158 int return_val;
1160 if ((Mf_putc) == NULLFUNC)
1162 mferror ("Mf_putc undefined");
1163 return (-1);
1166 return_val = (*Mf_putc) (c);
1168 if (return_val == EOF)
1169 mferror ("error writing");
1171 Mf_numbyteswritten++;
1172 return (return_val);