home *** CD-ROM | disk | FTP | other *** search
/ PC Musician 2000 / PC_Musician_2000.iso / PCMUSIC / MISC / MIDICSND / READMIDI.C < prev    next >
Encoding:
C/C++ Source or Header  |  1990-11-01  |  7.3 KB  |  278 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. FILE    *fp,*fp2;
  4.  
  5. /*
  6. WriteVarLen(value)
  7.     long value;
  8. {
  9.     long    buffer;
  10.     buffer    = value & 0x7f;
  11.     while((value>>=7) > 0)
  12.     {
  13.         buffer    <<= 8;
  14.         buffer    |= 0x80;
  15.         buffer    += (value & 0x7f);
  16.     }
  17.     while(1);
  18.     {
  19.         putchar(buffer);
  20.         if(buffer & 0x80)
  21.              buffer    >>= 8;
  22.         else
  23.             break;
  24.     }
  25. }
  26. */
  27.  
  28. long    ReadVarLen()
  29. {
  30.     long    value;
  31.     char    c;
  32.  
  33.     if((value = getc(fp)) & 0x80)
  34.     {
  35.         value    &= 0x7f;
  36.         do
  37.         {
  38.             value = (value << 7) + ((c = getc(fp)) & 0x7f);
  39.         } while (c & 0x80);
  40.     }
  41.     return(value);
  42. }
  43.  
  44. struct event {
  45.     float time;
  46.     unsigned char type;
  47.     unsigned char data[2];
  48. } *EventArray,*eventPtr,*evPtr2,*evPtr3;
  49.  
  50. main(argc,argv)
  51.     int argc;
  52.     char    *argv[];
  53. {
  54.     double    totaltime,dt;
  55.     long    totalticks,dticks,len;
  56.     long    tempo = 1000000;    /* tempo in micro seconds per quarter note */
  57.     unsigned int        nextByte,type;
  58.     unsigned int        ch1,ch2,ch3,ch4;
  59.     unsigned int        format,tracks,ticksperquarter;
  60.     long    i,arraysize,trackcount;
  61.  
  62.     arraysize = 3500;
  63.     if(argc==4)
  64.         sscanf(argv[3],"%d",&arraysize);
  65.     if(argc!=3 && argc!=4)
  66.     {
  67.         printf("Usage: %s midifile.fil csound.sco [maxeventcount]\n",argv[0]);
  68.         exit(-1);
  69.     }
  70.     printf("This program will read the Midi format file named %s, and\n",argv[1]);
  71.     printf("then write it in C sound format to the file %s.\n\n\n",argv[2]);
  72.     
  73. /* allocate storage array */
  74.  
  75.     EventArray = (struct event *) calloc(arraysize,sizeof(struct event));
  76.     if(EventArray == NULL)
  77.     {
  78.         printf("Enough storage could not be allocated to run this program.\n");
  79.         exit(-1);
  80.     }
  81.     
  82.     fp = fopen(argv[1],"rb");
  83.     if(fp == NULL)
  84.     {
  85.         printf(" Error : The file %s could not be opened !\n",argv[1]);
  86.         exit(-1);
  87.     }
  88.  
  89.     printf(" Reading in the Midi file.\n");
  90.  
  91.     ch1 =getc(fp);    /* get 'MThd' header */
  92.     ch2 =getc(fp);
  93.     ch3 =getc(fp);
  94.     ch4 =getc(fp);
  95.     if(ch1!='M'||ch2!='T'||ch3!='h'||ch4!='d')
  96.     {
  97.         printf("This is not a standard midi file.\n");
  98.         exit(-1);
  99.     }
  100.     for(i=0;i<4;i++) getc(fp);  /* skip length */
  101.  
  102.     ch1 =getc(fp);
  103.     ch2 =getc(fp);
  104.     format = (ch1 << 8) + ch2;
  105.     ch1 =getc(fp);
  106.     ch2 =getc(fp);
  107.     tracks = (ch1 << 8) + ch2;
  108.     ch1 =getc(fp);
  109.     ch2 =getc(fp);
  110.     ticksperquarter = (ch1 << 8) + ch2;
  111.     printf("The input file has Midi file format %d.\n",format);
  112.     if(format!=0&&format!=1)
  113.     {
  114.         printf("This program only works on format 0 and 1 Midi files.\n");
  115.         exit(-1);
  116.     }
  117.  
  118.     fp2 = fopen(argv[2],"w");
  119.     if(fp2 == NULL)
  120.     {
  121.         printf(" Error : The file %s could not be opened !\n",argv[2]);
  122.         exit(-1);
  123.     }
  124.     
  125.     printf("\n writing the C Sound file.\n");
  126.  
  127.     fprintf(fp2,"; The Midi file (in C Sound format) begins here.\n");
  128.     fprintf(fp2,"; p1 = midi channel + 1\n");
  129.     fprintf(fp2,"; p2 = start time in seconds\n");
  130.     fprintf(fp2,"; p3 = duration in seconds\n");
  131.     fprintf(fp2,"; p4 = amplitue (midi velocity)\n");
  132.     fprintf(fp2,"; p5 = pitch (midi note number)\n;\n");
  133.  
  134.   for(trackcount=0;trackcount<tracks;trackcount++)
  135.   {
  136.     printf("; Track # %ld\n",trackcount);
  137.     fprintf(fp2,"; Track # %ld\n",trackcount);
  138.     ch1 =getc(fp);  /* get 'MTrk' chunk */
  139.     ch2 =getc(fp);
  140.     ch3 =getc(fp);
  141.     ch4 =getc(fp);
  142.     if(ch1!='M'||ch2!='T'||ch3!='r'||ch4!='k')
  143.     {
  144.         printf("This file did not have the proper MTrk code.\n");
  145.         exit(-1);
  146.     }
  147.     for(i=0;i<4;i++) getc(fp);    /* skip length */
  148.     
  149.     totalticks = 0;
  150.     totaltime = 0;
  151.     eventPtr = EventArray;
  152.     type = 0;
  153.     while(type!=0x2F)
  154.     {
  155.       if(eventPtr == &EventArray[arraysize-1])
  156.       {
  157.         printf("; The file was to large to be completely processed.\n");
  158.         break;
  159.       }
  160.       /* first get the time */
  161.  
  162.       dticks = ReadVarLen() ;
  163.       totalticks += dticks ;
  164.       dt = (double) dticks / (double)ticksperquarter * (double)tempo / 1000000.;
  165.       totaltime += dt ;
  166.       eventPtr->time = totaltime;
  167.  
  168.       /* now get the type */
  169.  
  170.       if ((nextByte = getc(fp)) & 0x80)        /* skip running status */
  171.       {
  172.         if (nextByte == 0xFF)  /* meta event  */
  173.           type = getc(fp);
  174.         else
  175.         {
  176.           type = nextByte;
  177.           if (type != 0xF0 && type != 0xF7)
  178.             nextByte = getc(fp);
  179.         }
  180.       }
  181.  
  182.       /* now process the events */
  183. printf(" type is %x dticks is %f\n",(int) type,(float) dticks);
  184.       if (type < 0x80 || type == 0xF0 || type == 0xF7) /* meta or system exclu. */
  185.       {
  186.         len = ReadVarLen();
  187.         switch (type)
  188.         {
  189.         case 0x58:    /* Time signature */
  190.           getc(fp);    /* get numerator */
  191.           getc(fp);    /* get denumerator */
  192.           getc(fp);    /* get cc */
  193.           getc(fp);    /* get bb */
  194.           break;
  195.         case 0x51:    /* tempo change */
  196.           ch1 = getc(fp);
  197.           ch2 = getc(fp);
  198.           ch3 = getc(fp);
  199.           tempo = ((long) ch1 << 16) + ((long) ch2 << 8) + ch3;
  200.                       printf(" tempo change %ld \n",tempo);
  201.           break;
  202.         case 0x2F:    /* track end */
  203.           eventPtr->type = type;
  204.           eventPtr++;
  205.           break;
  206.         default:   /* skip unknown event */
  207.           for (i=0; i<len; i++)
  208.             getc(fp);
  209.         }
  210.       } else    /* its a standard midi event */
  211.       {
  212.                           printf(" %f",eventPtr->time);
  213.                           printf(" %ld",totalticks);
  214.         eventPtr->type = type;
  215.                           printf(" %x",(int) eventPtr->type);
  216.         eventPtr->data[0] = nextByte;
  217.                           printf(" %x",(int) eventPtr->data[0]);
  218.         if ((type & 0xE0) != 0xC0)
  219.         {
  220.           eventPtr->data[1] = getc(fp);
  221.                           printf(" %x",(int) eventPtr->data[1]);
  222.         }
  223.         eventPtr++;
  224.                           printf("\n");
  225.       }
  226.     }     /* end of the file input loop */
  227.  
  228.     
  229.     if(eventPtr == &EventArray[arraysize-1])
  230.         printf("; The file was to large to be completely processed.\n");
  231.  
  232.     
  233. /* output the file here  */
  234.  
  235.     for(evPtr2=EventArray;evPtr2<eventPtr;evPtr2++)
  236.     {
  237.         if( (evPtr2->type|0x0F) == 0x9F && evPtr2->data[1]!=0 )   /* note on */
  238.         {
  239.             for(evPtr3=evPtr2;evPtr3<eventPtr;evPtr3++)
  240.                 if(     ( (evPtr3->type | 0x0F) == 0x8F &&  /* note off */
  241.                           (evPtr3->type & 0x0F) == (evPtr2->type & 0x0F) && /* same channel */
  242.                           evPtr3->data[0] == evPtr2->data[0] ) /* same pitch */
  243.                          ||
  244.                         ( evPtr3->type == evPtr2->type &&  /* note on */
  245.                           evPtr3->data[0] == evPtr2->data[0] && /* same pitch */
  246.                           evPtr3->data[1] == 0               )   ) /* vel 0 */
  247.                 {
  248.                     fprintf(fp2,"i%d\t%f\t%f\t%d\t%d\n",
  249.                         (format==0 ?(int) (evPtr2->type & 0x0F)+1:(int)trackcount),
  250.                         evPtr2->time,
  251.                         evPtr3->time-evPtr2->time,
  252.                         (int) evPtr2->data[1],
  253.                         (int) evPtr2->data[0]
  254.                         );
  255.                     break;
  256.                 }
  257.             if(evPtr3==eventPtr)
  258.             {
  259.                 printf("; Error : notes without end. (see score)\n");
  260.                 fprintf(fp2,"; Error : the next note started but did not end.\n");
  261.                 fprintf(fp2,"i%d\t%f\t%f\t%d\t%d\n",
  262.                     (format==0 ?(int) (evPtr2->type & 0x0F)+1:(int)trackcount),
  263.                     evPtr2->time,
  264.                     (float) 0.0,
  265.                     (int) evPtr2->data[1],
  266.                     (int) evPtr2->data[0]
  267.                     );
  268.             }
  269.         }
  270.     }
  271.   }
  272.     fprintf(fp2,"e\n");
  273.     fclose(fp2);
  274.     fclose(fp);
  275.     free(EventArray);
  276.     printf(" done.\n");
  277. }
  278.