home *** CD-ROM | disk | FTP | other *** search
/ HOT Scene Stuff / hotscenestuffzyklop1996.iso / demos / sunknown / midifile.c < prev    next >
C/C++ Source or Header  |  1994-04-06  |  5KB  |  227 lines

  1. /*
  2. ** Copyright (c) 1992 Forte.  All rights reserved.
  3. ** Written late one night 6/27/93.
  4. **
  5. ** Note from Five, And Then Some:
  6. **   This file was originally included in the ultramid-package (or the
  7. **   Software Development Kit for the Gravis Ultrasound).
  8. **
  9. */
  10.  
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <string.h>
  14. #include <malloc.h>
  15. #define NULLFUNC 0
  16. #ifdef NULL
  17. #undef NULL
  18. #endif
  19. #define NULL ((void *)0L)
  20. #include "midi.h"
  21.  
  22. /* private stuff */
  23. static long to32bit(int c1,int c2,int c3,int c4);
  24. static to16bit(int c1,int c2);
  25. static long read32bit(struct MIDILIB *ml);
  26. static read16bit(struct MIDILIB *ml);
  27. static void mftrack(struct MIDILIB *ml, struct track *track);
  28.  
  29. static void mferror(struct MIDILIB *ml, char *s)
  30. {
  31.     /* if a user routine for error handling is registered, call it */
  32.     if ( ml->Mf_error )
  33.         (*ml->Mf_error)(s);
  34.     exit(1);
  35. }
  36.  
  37. void mfcleanup(struct MIDILIB *ml)
  38. {
  39.     struct track *track;
  40.  
  41.     if (ml) {
  42.         while (ml->Mp_tracks) {
  43.             track = ml->Mp_tracks;
  44.             ml->Mp_tracks = ml->Mp_tracks->next_track;
  45.             if (track->data) farfree((void far *)track->data);
  46.             free(track);
  47.         }
  48.     }
  49. }
  50.  
  51. void mfclose(struct MIDILIB **ml)
  52. {
  53.     struct track *track;
  54.  
  55.     if (*ml) {
  56.         mfcleanup(*ml);
  57.         free(*ml);
  58.         *ml = 0;
  59.     }
  60. }
  61.  
  62. struct MIDILIB *
  63. mfinit(void (*errorfunc)(char *))
  64. {
  65.     /* The midi library communicates with the application's software by
  66.     ** calling functions.  The midilibrary allocates memory for a structure
  67.     ** that the application fills in with all of the functions it can
  68.     ** fufill.  This library is operating system and machine independant.
  69.     */
  70.     struct MIDILIB *ml;
  71.  
  72.     ml = (struct MIDILIB *)malloc(sizeof(struct MIDILIB));
  73.     if (ml == NULL) {
  74.         if (errorfunc) {
  75.             (void)(*errorfunc)("Couldn't initialize midi library - out of memory\n");
  76.             exit(1);
  77.         }
  78.     }
  79.     ml->Mf_error = errorfunc;
  80.     ml->Mf_getc = NULLFUNC;        /* get a character (from a midi file) */
  81.     ml->Mf_header = NULLFUNC;    /* tell application about header info */
  82.     ml->Mf_toberead = 0L;        /* number of bytes not read yet */
  83.     ml->Mp_tracks = NULL;
  84.     return(ml);
  85. }
  86.  
  87. /* read through the "MThd" or "MTrk" header string */
  88. static readmt(struct MIDILIB *ml, char *s)
  89. {
  90.     int n = 0;
  91.     char *p = s;
  92.     int c;
  93.  
  94.     while ( n++<4 && (c=(*ml->Mf_getc)()) != EOF ) {
  95.         if ( c != *p++ ) {
  96.             char buff[32];
  97.             if (c == 26) return(EOF);
  98.             (void) strcpy(buff,"Expecting ");
  99.             (void) strcat(buff,s);
  100.             (void) strcat(buff,", corrupt midi file?");
  101.             (void)mferror(ml, buff);
  102.         }
  103.     }
  104.     return(c);
  105. }
  106.  
  107. /* read a single character and abort on EOF */
  108. static egetc(struct MIDILIB *ml)
  109. {
  110.     int c = (*ml->Mf_getc)();
  111.  
  112.     if ( c == EOF )
  113.         (void)mferror(ml, "EOF reached, corrupt midi file");
  114.     ml->Mf_toberead--;
  115.     return(c);
  116. }
  117.  
  118. /* read a header chunk */
  119. static readheader(struct MIDILIB *ml)
  120. {
  121.     int format, ntrks, division;
  122.  
  123.     if ( readmt(ml, "MThd") == EOF )
  124.         return(0);
  125.  
  126.     ml->Mf_toberead = read32bit(ml);
  127.     format = read16bit(ml);
  128.     ntrks = read16bit(ml);
  129.     division = read16bit(ml);
  130.  
  131.     if ( ml->Mf_header ) (*ml->Mf_header)(format,ntrks,division);
  132.  
  133.     /* flush any extra stuff, in case the length of header is not 6 */
  134.     while ( ml->Mf_toberead > 0 ) (void) egetc(ml);
  135.     return(1);
  136. }
  137.  
  138. /* read a track chunk */
  139. static readtrack(struct MIDILIB *ml)
  140. {
  141.     struct track *track;
  142.     char huge *cp;
  143.  
  144.     if ( readmt(ml, "MTrk") == EOF ) return(0);
  145.  
  146.     ml->Mf_toberead = read32bit(ml);
  147.     track = malloc(sizeof(struct track));
  148.     if (track == NULL) {
  149.         (void)mferror(ml, "Out of memory - read_track()");
  150.         return(0);
  151.     }
  152.     track->length = ml->Mf_toberead;
  153.     track->data = (void huge *)farmalloc(ml->Mf_toberead);
  154.     if (track->data == (void huge *)NULL) {
  155.         (void)mferror(ml, "Out of memory - read_track()");
  156.         return(0);
  157.     }
  158.     cp = track->data;
  159.     while (ml->Mf_toberead > 0) {
  160.         *cp++ = egetc(ml);
  161.     }
  162.     track->playp = track->data;
  163.     track->play_time = 0L;
  164.     track->play_state = MPS_BEGIN;
  165.     track->next_track = NULL;
  166.     mftrack(ml, track);
  167.     return(1);
  168. }
  169.  
  170. void mfread(struct MIDILIB *ml)    
  171. {
  172.     midi_message("Reading MIDI file");
  173.     ml->tracknum=0;
  174.     if ( ml->Mf_getc == NULLFUNC )
  175.         (void)mferror(ml, "mfread() called without setting Mf_getc"); 
  176.  
  177.     readheader(ml);
  178.     while ( readtrack(ml) ) ;
  179. }
  180.  
  181. static long to32bit(int c1,int c2,int c3,int c4)
  182. {
  183.     long value = 0L;
  184.  
  185.     value = (c1 & 0xff);
  186.     value = (value<<8) + (c2 & 0xff);
  187.     value = (value<<8) + (c3 & 0xff);
  188.     value = (value<<8) + (c4 & 0xff);
  189.     return (value);
  190. }
  191.  
  192. static to16bit(int c1,int c2)
  193. {
  194.     return ((c1 & 0xff ) << 8) + (c2 & 0xff);
  195. }
  196.  
  197. static long read32bit(struct MIDILIB *ml)
  198. {
  199.     int c1, c2, c3, c4;
  200.  
  201.     c1 = egetc(ml);
  202.     c2 = egetc(ml);
  203.     c3 = egetc(ml);
  204.     c4 = egetc(ml);
  205.     return to32bit(c1,c2,c3,c4);
  206. }
  207.  
  208. static read16bit(struct MIDILIB *ml)
  209. {
  210.     int c1, c2;
  211.     c1 = egetc(ml);
  212.     c2 = egetc(ml);
  213.     return to16bit(c1,c2);
  214. }
  215.  
  216. static void mftrack(struct MIDILIB *ml, struct track *track)
  217. {
  218.     struct track *tp;
  219.  
  220.     if (ml->Mp_tracks) {
  221.         for (tp=ml->Mp_tracks; tp->next_track; tp = tp->next_track) ;
  222.         tp->next_track = track;
  223.     } else {
  224.         ml->Mp_tracks = track;
  225.     }
  226. }
  227.