home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 8 Other / 08-Other.zip / midifos2.zip / MIDIFILE.C < prev    next >
C/C++ Source or Header  |  1993-06-14  |  11KB  |  533 lines

  1. /*
  2.  * Read a Standard MIDI File.  Externally-assigned function pointers are
  3.  * called upon recognizing things in the file.  See midifile(3).
  4.  */
  5.  
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <os2.h>
  9.  
  10. #include "midi.h"
  11. #include "midifile.h"
  12.  
  13. /* public stuff */
  14.  
  15. /* Functions to be called while processing the MIDI file. */
  16. VOID (*Mf_starttrack)(VOID) = NULL;
  17. VOID (*Mf_endtrack)(VOID) = NULL;
  18. int (*Mf_getc)(VOID) = NULL;
  19. VOID (*Mf_eot)(VOID) = NULL;
  20.  
  21. VOID (*Mf_error)(char *) = NULL;
  22. VOID (*Mf_header)(int,int,int) = NULL;
  23. VOID (*Mf_on)(int,int,int) = NULL;
  24. VOID (*Mf_off)(int,int,int) = NULL;
  25. VOID (*Mf_pressure)(int,int,int) = NULL;
  26. VOID (*Mf_controller)(int,int,int) = NULL;
  27. VOID (*Mf_pitchbend)(int,int,int) = NULL;
  28. VOID (*Mf_program)(int,int) = NULL;
  29. VOID (*Mf_chanpressure)(int,int) = NULL;
  30. VOID (*Mf_sysex)(int,char*) = NULL;
  31. VOID (*Mf_arbitrary)(int,char*) = NULL;
  32. VOID (*Mf_metamisc)(int,int,char*) = NULL;
  33. VOID (*Mf_seqnum)(int) = NULL;
  34. VOID (*Mf_smpte)(int,int,int,int,int) = NULL;
  35. VOID (*Mf_timesig)(int,int,int,int) = NULL;
  36. VOID (*Mf_tempo)(int) = NULL;
  37. VOID (*Mf_keysig)(int,int) = NULL;
  38. VOID (*Mf_sqspecific)(int,char*) = NULL;
  39. VOID (*Mf_text)(int,int,char*) = NULL;
  40.  
  41. int Mf_nomerge = 0;        /* 1 => continue'ed system exclusives are */
  42.                 /* not collapsed. */
  43. long Mf_currtime = 0L;        /* current time in delta-time units */
  44. int Mf_skipinit = 0;        /* 1 if initial garbage should be skipped */
  45.  
  46. /* private stuff */
  47.  
  48. static long Mf_toberead = 0L;
  49.  
  50. static long readvarinum(VOID);
  51. static long read32bit(VOID);
  52. static int read16bit(VOID);
  53. static VOID msgenlarge(VOID);
  54. static char *msg(VOID);
  55. static int readheader(VOID);
  56. static VOID readtrack(VOID);
  57. static VOID sysex(VOID), msginit(VOID);
  58. static int egetc(VOID);
  59. static int msgleng(VOID);
  60.  
  61. static int readmt(char*,int);
  62. static long to32bit(int,int,int,int);
  63. static int to16bit(int,int);
  64. static VOID mferror(char *);
  65. static VOID badbyte(int);
  66. static VOID metaevent(int);
  67. static VOID msgadd(int);
  68. static VOID chanmessage(int,int,int);
  69.  
  70.  
  71. /*
  72.  * The only non-static function in this file.
  73.  */
  74. VOID midifile(VOID)
  75. {
  76.     int ntrks;
  77.  
  78.     if ( Mf_getc == NULL )
  79.         mferror("mf.h() called without setting Mf_getc"); 
  80.  
  81.     ntrks = readheader();
  82.     if ( ntrks <= 0 )
  83.         mferror("No tracks!");
  84.     while ( ntrks-- > 0 )
  85.         readtrack();
  86. }
  87.  
  88.  
  89. /*
  90.  * readmt -  read through the "MThd" or "MTrk" header string
  91.  *
  92.  * if skip == 1, we attempt to skip initial garbage.
  93.  */
  94. static int readmt(char *s, int skip)
  95. {
  96.     int nread = 0;
  97.     char b[4];
  98.     char buff[32];
  99.     int c;
  100.     char *errmsg;
  101.  
  102.     do
  103.     {
  104.         while ((nread < 4) && ((c = (*Mf_getc)()) != EOF))
  105.             b[nread++] = c;
  106.  
  107.         /* See if we found the 4 characters we're looking for */
  108.         if ( s[0]==b[0] && s[1]==b[1] && s[2]==b[2] && s[3]==b[3] )
  109.             return(0);
  110.  
  111.         if (skip)
  112.         {
  113.             /* If we are supposed to skip initial garbage, */
  114.             /* try again with the next character. */
  115.             b[0]=b[1];
  116.             b[1]=b[2];
  117.             b[2]=b[3];
  118.             nread = 3;
  119.         }
  120.     }
  121.     while (nread < 4);
  122.  
  123.     if (c == EOF) errmsg = "EOF while expecting ";
  124.     else errmsg = "expecting ";
  125.     strcpy(buff,errmsg);
  126.     strcat(buff,s);
  127.     mferror(buff);
  128.     return(0);
  129. }
  130.  
  131.  
  132. /*
  133.  * egetc - read a single character and abort on EOF
  134.  */
  135. static int egetc(VOID)
  136. {
  137.     int c = (*Mf_getc)();
  138.  
  139.     if ( c == EOF )
  140.         mferror("premature EOF");
  141.     Mf_toberead--;
  142.     return(c);
  143. }
  144.  
  145.  
  146. /*
  147.  * readheader - read a header chunk
  148.  */
  149. static int readheader(VOID)
  150. {
  151.     int format, ntrks, division;
  152.  
  153.     if ( readmt("MThd",Mf_skipinit) == EOF )
  154.         return(0);
  155.  
  156.     Mf_toberead = read32bit();
  157.     format = read16bit();
  158.     ntrks = read16bit();
  159.     division = read16bit();
  160.  
  161.     if ( Mf_header )
  162.         (*Mf_header)(format,ntrks,division);
  163.  
  164.     /* flush any extra stuff, in case the length of header is not 6 */
  165.     while ( Mf_toberead > 0 )
  166.         egetc();
  167.     return(ntrks);
  168. }
  169.  
  170.  
  171. /*
  172.  * readtrack - read a track chunk
  173.  */
  174. static VOID readtrack(VOID)
  175. {
  176.     /* This array is indexed by the high half of a status byte.  It's */
  177.     /* value is either the number of bytes needed (1 or 2) for a channel */
  178.     /* message, or 0 (meaning it's not  a channel message). */
  179.     static int chantype[] = {
  180.         0, 0, 0, 0, 0, 0, 0, 0,        /* 0x00 through 0x70 */
  181.         2, 2, 2, 2, 1, 1, 2, 0        /* 0x80 through 0xf0 */
  182.     };
  183.     long lookfor, lng;
  184.     int c, c1, type;
  185.     int sysexcontinue = 0;    /* 1 if last message was an unfinished sysex */
  186.     int running = 0;    /* 1 when running status used */
  187.     int status = 0;        /* (possibly running) status byte */
  188.     int needed;
  189.  
  190.     if ( readmt("MTrk",0) == EOF )
  191.         return;
  192.  
  193.     Mf_toberead = read32bit();
  194.     Mf_currtime = 0;
  195.  
  196.     if ( Mf_starttrack )
  197.         (*Mf_starttrack)();
  198.  
  199.     while ( Mf_toberead > 0 ) {
  200.  
  201.         Mf_currtime += readvarinum();    /* delta time */
  202.  
  203.         c = egetc();
  204.  
  205.         if ( sysexcontinue && c != 0xf7 )
  206.             mferror("didn't find expected continuation of a sysex");
  207.  
  208.         if ( (c & 0x80) == 0 ) {     /* running status? */
  209.             if ( status == 0 )
  210.                 mferror("unexpected running status");
  211.             running = 1;
  212.         }
  213.         else {
  214.             status = c;
  215.             running = 0;
  216.         }
  217.  
  218.         needed = chantype[ (status>>4) & 0xf ];
  219.  
  220.         if ( needed ) {        /* ie. is it a channel message? */
  221.  
  222.             if ( running )
  223.                 c1 = c;
  224.             else
  225.                 c1 = egetc();
  226.             chanmessage( status, c1, (needed>1) ? egetc() : 0 );
  227.             continue;;
  228.         }
  229.  
  230.         switch ( c ) {
  231.  
  232.         case 0xff:            /* meta event */
  233.  
  234.             type = egetc();
  235.             /* watch out - Don't combine the next 2 statements */
  236.             lng = readvarinum();
  237.             lookfor = Mf_toberead - lng;
  238.             msginit();
  239.  
  240.             while ( Mf_toberead > lookfor )
  241.                 msgadd(egetc());
  242.  
  243.             metaevent(type);
  244.             break;
  245.  
  246.         case 0xf0:        /* start of system exclusive */
  247.  
  248.             /* watch out - Don't combine the next 2 statements */
  249.             lng = readvarinum();
  250.             lookfor = Mf_toberead - lng;
  251.             msginit();
  252.             msgadd(0xf0);
  253.  
  254.             while ( Mf_toberead > lookfor )
  255.                 msgadd(c=egetc());
  256.  
  257.             if ( c==0xf7 || Mf_nomerge==0 )
  258.                 sysex();
  259.             else
  260.                 sysexcontinue = 1;  /* merge into next msg */
  261.             break;
  262.  
  263.         case 0xf7:    /* sysex continuation or arbitrary stuff */
  264.  
  265.             /* watch out - Don't combine the next 2 statements */
  266.             lng = readvarinum();
  267.             lookfor = Mf_toberead - lng;
  268.  
  269.             if ( ! sysexcontinue )
  270.                 msginit();
  271.  
  272.             while ( Mf_toberead > lookfor )
  273.                 msgadd(c=egetc());
  274.  
  275.             if ( ! sysexcontinue ) {
  276.                 if ( Mf_arbitrary )
  277.                     (*Mf_arbitrary)(msgleng(),msg());
  278.             }
  279.             else if ( c == 0xf7 ) {
  280.                 sysex();
  281.                 sysexcontinue = 0;
  282.             }
  283.             break;
  284.         default:
  285.             badbyte(c);
  286.             break;
  287.         }
  288.     }
  289.     if ( Mf_endtrack )
  290.         (*Mf_endtrack)();
  291.     return;
  292. }
  293.  
  294.  
  295. static VOID badbyte(int c)
  296. {
  297.     char buff[32];
  298.  
  299.     (VOID) sprintf(buff,"unexpected byte: 0x%02x",c);
  300.     mferror(buff);
  301. }
  302.  
  303.  
  304. static VOID metaevent(int type)
  305. {
  306.     int leng = msgleng();
  307.     char *m = msg();
  308.  
  309.     switch  ( type ) {
  310.     case 0x00:
  311.         if ( Mf_seqnum )
  312.             (*Mf_seqnum)(to16bit(m[0],m[1]));
  313.         break;
  314.     case 0x01:    /* Text event */
  315.     case 0x02:    /* Copyright notice */
  316.     case 0x03:    /* Sequence/Track name */
  317.     case 0x04:    /* Instrument name */
  318.     case 0x05:    /* Lyric */
  319.     case 0x06:    /* Marker */
  320.     case 0x07:    /* Cue point */
  321.     case 0x08:
  322.     case 0x09:
  323.     case 0x0a:
  324.     case 0x0b:
  325.     case 0x0c:
  326.     case 0x0d:
  327.     case 0x0e:
  328.     case 0x0f:
  329.         /* These are all text events */
  330.         if ( Mf_text )
  331.             (*Mf_text)(type,leng,m);
  332.         break;
  333.     case 0x2f:    /* End of Track */
  334.         if ( Mf_eot )
  335.             (*Mf_eot)();
  336.         break;
  337.     case 0x51:    /* Set tempo */
  338.         if ( Mf_tempo )
  339.             (*Mf_tempo)(to32bit(0,m[0],m[1],m[2]));
  340.         break;
  341.     case 0x54:
  342.         if ( Mf_smpte )
  343.             (*Mf_smpte)(m[0],m[1],m[2],m[3],m[4]);
  344.         break;
  345.     case 0x58:
  346.         if ( Mf_timesig )
  347.             (*Mf_timesig)(m[0],m[1],m[2],m[3]);
  348.         break;
  349.     case 0x59:
  350.         if ( Mf_keysig )
  351.             (*Mf_keysig)(m[0],m[1]);
  352.         break;
  353.     case 0x7f:
  354.         if ( Mf_sqspecific )
  355.             (*Mf_sqspecific)(leng,m);
  356.         break;
  357.     default:
  358.         if ( Mf_metamisc )
  359.             (*Mf_metamisc)(type,leng,m);
  360.     }
  361. }
  362.  
  363.  
  364. static VOID sysex(VOID)
  365. {
  366.     if ( Mf_sysex )
  367.         (*Mf_sysex)(msgleng(),msg());
  368. }
  369.  
  370.  
  371. static VOID chanmessage(int status, int c1, int c2)
  372. {
  373.     int chan = status & 0xf;
  374.  
  375.     switch ( status & 0xf0 ) {
  376.     case NOTEOFF:
  377.         if ( Mf_off )
  378.             (*Mf_off)(chan,c1,c2);
  379.         break;
  380.     case NOTEON:
  381.         if ( Mf_on )
  382.             (*Mf_on)(chan,c1,c2);
  383.         break;
  384.     case PRESSURE:
  385.         if ( Mf_pressure )
  386.             (*Mf_pressure)(chan,c1,c2);
  387.         break;
  388.     case CONTROLLER:
  389.         if ( Mf_controller )
  390.             (*Mf_controller)(chan,c1,c2);
  391.         break;
  392.     case PITCHBEND:
  393.         if ( Mf_pitchbend )
  394.             (*Mf_pitchbend)(chan,c1,c2);
  395.         break;
  396.     case PROGRAM:
  397.         if ( Mf_program )
  398.             (*Mf_program)(chan,c1);
  399.         break;
  400.     case CHANPRESSURE:
  401.         if ( Mf_chanpressure )
  402.             (*Mf_chanpressure)(chan,c1);
  403.         break;
  404.     }
  405. }
  406.  
  407.  
  408. /*
  409.  * readvarinum - read a varying-length number, and return the
  410.  *               number of characters it took.
  411.  */
  412. static long readvarinum(VOID)
  413. {
  414.     long value;
  415.     int c;
  416.  
  417.     c = egetc();
  418.     value = c;
  419.     if ( c & 0x80 )
  420.     {
  421.         value &= 0x7f;
  422.         do
  423.         {
  424.             c = egetc();
  425.             value = (value << 7) + (c & 0x7f);
  426.         } while (c & 0x80);
  427.     }
  428.     return (value);
  429. }
  430.  
  431. static long to32bit(int c1, int c2, int c3, int c4)
  432. {
  433.     long value = 0L;
  434.  
  435.     value = (c1 & 0xff);
  436.     value = (value<<8) + (c2 & 0xff);
  437.     value = (value<<8) + (c3 & 0xff);
  438.     value = (value<<8) + (c4 & 0xff);
  439.     return (value);
  440. }
  441.  
  442.  
  443. static to16bit(int c1, int c2)
  444. {
  445.     return ((c1 & 0xff ) << 8) + (c2 & 0xff);
  446. }
  447.  
  448.  
  449. static long read32bit(VOID)
  450. {
  451.     int c1, c2, c3, c4;
  452.  
  453.     c1 = egetc();
  454.     c2 = egetc();
  455.     c3 = egetc();
  456.     c4 = egetc();
  457.     return to32bit(c1,c2,c3,c4);
  458. }
  459.  
  460.  
  461. static int read16bit(VOID)
  462. {
  463.     int c1, c2;
  464.  
  465.     c1 = egetc();
  466.     c2 = egetc();
  467.     return to16bit(c1,c2);
  468. }
  469.  
  470.  
  471. static VOID mferror(char *s)
  472. {
  473.     if ( Mf_error )
  474.         (*Mf_error)(s);
  475.     exit(1);
  476. }
  477.  
  478.  
  479. /* The code below allows collection of a system exclusive message of */
  480. /* arbitrary length.  The Msgbuff is expanded as necessary.  The only */
  481. /* visible data/routines are msginit(), msgadd(), msg(), msgleng(). */
  482.  
  483. #define MSGINCREMENT 128
  484. static char *Msgbuff = 0;    /* message buffer */
  485. static int Msgsize = 0;        /* Size of currently allocated Msg */
  486. static int Msgindex = 0;    /* index of next available location in Msg */
  487.  
  488. static VOID msginit(VOID)
  489. {
  490.     Msgindex = 0;
  491. }
  492.  
  493. static char *msg(VOID)
  494. {
  495.     return(Msgbuff);
  496. }
  497.  
  498. static int msgleng(VOID)
  499. {
  500.     return(Msgindex);
  501. }
  502.  
  503. static VOID msgadd(int c)
  504. {
  505.     /* If necessary, allocate larger message buffer. */
  506.     if ( Msgindex >= Msgsize )
  507.         msgenlarge();
  508.     Msgbuff[Msgindex++] = c;
  509. }
  510.  
  511. static VOID msgenlarge(VOID)
  512. {
  513.     char *newmess;
  514.     char *oldmess = Msgbuff;
  515.     int oldleng = Msgsize;
  516.  
  517.     Msgsize += MSGINCREMENT;
  518.     newmess = malloc( (unsigned)(sizeof(char)*Msgsize) );
  519.  
  520.     /* copy old message into larger new one */
  521.     if ( oldmess != 0 )
  522.     {
  523.         char *p = newmess;
  524.         char *q = oldmess;
  525.         char *endq = &oldmess[oldleng];
  526.  
  527.         for ( ; q!=endq ; p++,q++ )
  528.             *p = *q;
  529.         free(oldmess);
  530.     }
  531.     Msgbuff = newmess;
  532. }
  533.