home *** CD-ROM | disk | FTP | other *** search
/ PC Musician 2000 / PC_Musician_2000.iso / PCMUSIC / MISC / MTM05SRC / MTM.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-01-09  |  24.2 KB  |  1,115 lines

  1. /*
  2.  * Midtomup
  3.  * 
  4.  * Convert Midi files to MUP input files
  5.  */
  6.  
  7. #include <stdio.h>
  8. #include <ctype.h>
  9. #include <fcntl.h>
  10. #include "midifile.h"
  11. #include "mtm.h"
  12. #include "version.h"
  13.  
  14. /* for all forms of DOS we've tried, make sure __DOS__ is defined */
  15. #if defined(__WATCOMC__)
  16. #ifndef __DOS__
  17. #define __DOS__
  18. #endif
  19. #endif
  20.  
  21. /* MIDI file has to be read in binary mode */
  22. #ifdef __DOS__
  23. #define MODE    O_RDONLY | O_BINARY
  24. #else
  25. #define MODE    O_RDONLY
  26. #endif
  27.  
  28. #define TIE 1
  29. #define NO_TIE 0
  30. #define MEASURE -11
  31.  
  32. static int F;
  33.  
  34. int SECONDS;      /* global that tells whether to display seconds or ticks */
  35. int division;        /* from the file header */
  36. long tempo = 500000; /* the default tempo is 120 beats/minute */
  37.  
  38. int FUDGE;    /* Take the exact amount, or try to fudge it to a usable */
  39.         /* number of ticks? */
  40. int FFACTOR;
  41.  
  42. extern char *optarg;
  43. extern int optind;
  44.  
  45. int efopen();
  46.  
  47.  
  48. /* read and return one character from MIDI file. Return EOF on end of file
  49.  * or read error. */
  50.  
  51. int
  52. filegetc()
  53. {
  54.     unsigned char c;
  55.  
  56.     return (read(F, &c, 1) == 1) ? (c & 0xff) : EOF;
  57. }
  58.  
  59. void
  60. usage(pgmname)
  61. char *pgmname;
  62. {
  63.     fprintf(stderr, "usage: %s [-a fudge_factor] [-f inputfile] [-g] [-i cmdfile] [-n] [-v]\n", pgmname);
  64.     fprintf(stderr, "\t-g = turn on fudging\n\t-n = don't add measure number comments\n\t-v = print version number and exit\n");
  65.     exit(1);
  66. }
  67.  
  68. main(argc,argv)
  69. char **argv;
  70. {
  71.     FILE *fp;
  72.     char ifile[80];
  73.     char buf[80];
  74.     int c;
  75.     int i, j;
  76.     int pmeasure = 1;
  77.  
  78.  
  79.     SECONDS = 0;
  80.     FUDGE = 0;
  81.     for(i = 0; i < 16; i++) {
  82.         track[i].swhre = 0;
  83.         track[i].ewhre = 0;
  84.     }
  85.     twhre = 0;
  86.     bwhre = 0;
  87.     tlwhre = 0;
  88.     F = 0;
  89.     FFACTOR=10;
  90.     ifile[0] = '\0';
  91.  
  92.     while((c = getopt(argc, argv, "f:ga:i:nv")) != EOF)
  93.     switch(c) {
  94.         /**
  95.         case 's': SECONDS = 1;
  96.               break;
  97.         **/
  98.         case 'f': F = efopen(optarg);
  99.               break;
  100.         case 'g': FUDGE = 1;
  101.               break;
  102.         case 'a': FFACTOR = atoi(optarg);
  103.               break;
  104.         case 'i': strcpy(ifile, optarg);
  105.               break;
  106.         case 'n': pmeasure = 0;
  107.               break;
  108.         case 'v': fprintf(stderr, "%s\n", version);
  109.               exit(0);
  110.               break;
  111.         default:  printf("%c not understood.\n", c);
  112.               usage(argv[0]);
  113.               break;
  114.     }
  115.  
  116.     initfuncs();
  117.     Mf_getc = filegetc;
  118.     midifile();
  119.     close(F);
  120.     /*
  121.      * Done reading the midi file.  Now output the notes.
  122.      */
  123.     /*
  124.      * First read the midtomup init file...
  125.      */
  126.     if(ifile[0] == '\0')
  127.         strcpy(ifile, ".midtomup");
  128.     if((fp = fopen(ifile, "r")) != NULL) {
  129.         while(fgets(buf, 80, fp) != '\0') {
  130.             if(buf[0] != '#' && buf[0] != '/') {
  131.                 fprintf(stderr, "Parse error in .midtomup: %s\n", buf);
  132.                 break;
  133.             }
  134.             if(buf[0] == '/' && buf[1] == '/') {
  135.                 printf("%s", buf);
  136.                 continue;
  137.             }
  138.             if(strncmp(buf, "#header", 7) == 0)
  139.                 doheader(fp);
  140.             else if(strncmp(buf, "#beamstyle", 10) == 0)
  141.                 dobeamstyle(fp);
  142.             else if(strncmp(buf, "#translate", 10) == 0)
  143.                 dotranslate(buf);
  144.             else if(strncmp(buf, "#key", 4) == 0)
  145.                 dokey(buf);
  146.             else
  147.                 fprintf(stderr, "Unknown rc command: %s\n", buf);
  148.         }
  149.     }
  150.     fclose(fp);
  151.     
  152.     /* Init some vars */
  153.     for(i = 0; i < 16; i++) {
  154.         tr[i] = 0;
  155.     }
  156.     measure = 1;
  157.     ticks = 0;
  158.     twhre = 0;
  159.     mwhre = 0;
  160.     h_ticks = 0;
  161.     triplet = 0;
  162.     /* If no time sig specified, set to 4/4 */
  163.     if(tsig[0].num < 1)
  164.         tsig[0].num = 4;
  165.     if(tsig[0].dnom < 1)
  166.         tsig[0].dnom = 4;
  167.     /* Main loop to output notes */
  168.     do {
  169.         if(tsig[twhre].when == h_ticks) {
  170.             printf("score\n");
  171.             printf("\ttime=%d/%d\n", tsig[twhre].num, tsig[twhre].dnom);
  172.             for(i = 0; i < 50; i++) {
  173.                 if(bstyles[i].bnum == tsig[twhre].num && bstyles[i].bdnom == tsig[twhre].dnom) {
  174.                     printf("\tbeamstyle=%s\n", bstyles[i].style);
  175.                     break;
  176.                 }
  177.             }
  178.             printf("music\n");
  179.             twhre++;
  180.         }
  181.         if(midikey[mwhre].when == h_ticks) {
  182.             printf("score\n");
  183.             for(i = 0; i <= numtracks; i++) {
  184.                 if(track[i].swhre < 1)
  185.                     continue;
  186.                 /*
  187.                  * Print the staff number, remembering translations..
  188.                  */
  189.                 for(j = 0; j < tlwhre; j++) {
  190.                     if(i + 1 == tlate[j].in) {
  191.                         printf("staff %d\n", tlate[j].out);
  192.                         break;
  193.                     }
  194.                 }
  195.                 if(j == tlwhre)
  196.                     printf("staff %d\n", i + 1);
  197.                 j = midikey[mwhre].nkey + hkey[i + 1];
  198.                 if(j <= 0)
  199.                     printf("\tkey=%d&\n", abs(midikey[mwhre].nkey + hkey[i + 1]));
  200.                 else
  201.                     printf("\tkey=%d#\n", midikey[mwhre].nkey + hkey[i + 1]);
  202.                 printf("// New key for track %d = %d\n", i + 1, midikey[mwhre].nkey + hkey[i + 1]);
  203.                 key[i + 1] = midikey[mwhre].nkey + hkey[i + 1];
  204.             }
  205.             printf("music\n");
  206.             mwhre++;
  207.         }
  208.         if(pmeasure)
  209.             printf("// Measure %d\n", measure);
  210.         measure++;
  211.         /*
  212.          * Sorry, only quarters and eighths and halfs can be in the denominator
  213.          */
  214.         if(tsig[twhre - 1].dnom == 4)
  215.             endticks = h_ticks + (division * tsig[twhre - 1].num);
  216.         else if(tsig[twhre - 1].dnom == 8)
  217.             endticks = h_ticks + (division/2 * tsig[twhre - 1].num);
  218.         else
  219.             endticks = h_ticks + (division * 2 * tsig[twhre - 1].num);
  220.         /* Remember, we only deal with one note at a time on a track. */
  221.         /*
  222.          * We will deal with one measure at a time, one track at a time.
  223.          */
  224.         for(i = 0; i <= numtracks; i++) {
  225.             for(j = 0; j < 32; j++) {
  226.                 accnotes[j] = -1;
  227.                 sccnotes[j][0] = -1;
  228.                 sccnotes[j][1] = -1;
  229.                 sccnotes[j][2] = -1;
  230.             }
  231.             accwhre = -1;
  232.             sccwhre = -1;
  233.             ticks = h_ticks;
  234.             /*
  235.              * If tr[i] < 1, then we have, at most one note in the track.
  236.              * We're ignoring it.
  237.              */
  238.             if(track[i].swhre < 1)
  239.                 continue;
  240.             /*
  241.              * Do the requested track translations.
  242.              *
  243.              * Did the user request a translation for this track?
  244.              */
  245.             for(j = 0; j < tlwhre; j++) {
  246.                 if(i + 1 == tlate[j].in) {
  247.                     printf("\n%d:", tlate[j].out);
  248.                     break;
  249.                 }
  250.             }
  251.             /*
  252.              * If j == tlwhre, then we didn't find a translation for the
  253.              * track.
  254.              */
  255.             if(j == tlwhre)
  256.                 printf("\n%d:", i + 1);
  257.             /* Is there a note in the measure? */
  258.             if(track[i].start[tr[i]] >= ticks && track[i].start[tr[i]] < endticks) {
  259.                 do {
  260.                     /* have we reached the end of this track? */
  261.                     if(tr[i] > track[i].swhre)
  262.                         continue;
  263.                     /* No, does a note start on current tick? */
  264.                     if(track[i].start[tr[i]] != ticks) {
  265.                         /* Nope, so output a rest */
  266.                         if(tr[i] >= track[i].swhre) {
  267.                             dorest(i, endticks - ticks);
  268.                             ticks = endticks;
  269.                             break;
  270.                         } else {
  271.                             dorest(i, track[i].start[tr[i]] - ticks);
  272.                             ticks = track[i].start[tr[i]];
  273.                         }
  274.                     } else {
  275.                         /* Note is tied to a note not in this measure */
  276.                         if(track[i].end[tr[i]] > endticks) {
  277. #ifdef __STDC
  278.                             donote(i, track[i].note[tr[i]], (short) (endticks - track[i].start[tr[i]]), TIE);
  279. #else
  280.                             donote(i, track[i].note[tr[i]], endticks - track[i].start[tr[i]], TIE);
  281. #endif
  282.                             track[i].start[tr[i]] = endticks;
  283.                             ticks = endticks;
  284.                         /* note is completely contained in this measure. */
  285.                         } else {
  286.                             j = track[i].end[tr[i]]-track[i].start[tr[i]];
  287. /* HERE */
  288. /* printf("j = %d, division = %d\n", j, division); */
  289.                             if(FUDGE) {
  290.                                 j = fudge(j);
  291.                                 /*
  292.                                 if(j == 29 || j == 59 || j == 89 || j == 119 || j == 179 || j == 209 || j == 239 || j == 359 || j == 479)
  293.                                     j++;
  294.                                 */
  295.                             }
  296.                             /*
  297.                             donote(i, track[i].note[tr[i]], track[i].end[tr[i]]-track[i].start[tr[i]], NO_TIE);
  298.                             ticks += track[i].end[tr[i]] - track[i].start[tr[i]];
  299.                             */
  300.                             donote(i, track[i].note[tr[i]], j, NO_TIE);
  301.                             ticks += j;
  302.                             tr[i]++;
  303.                         }
  304.                     }
  305.                     /* Next note in track */
  306.                 } while(ticks < endticks && track[i].start[tr[i]] < endticks);
  307.                 if(ticks < endticks) {
  308.                     dorest(i, endticks - ticks);
  309.                     ticks = endticks;
  310.                 }
  311.             } else {
  312.                 dorest(i, MEASURE);
  313.             }
  314.         }
  315.         dobar();
  316.         h_ticks = endticks;
  317.     } while(h_ticks < lasttick);
  318.     exit(0);
  319. }
  320.  
  321. int
  322. efopen(name)
  323. char *name;
  324. {
  325.     int f;
  326.     extern int errno;
  327.     extern char *sys_errlist[];
  328.     extern int sys_nerr;
  329.     char *errmess;
  330.  
  331.     if ( (f=open(name,MODE,0)) == NULL ) {
  332.         (void) fprintf(stderr,"Cannot open '%s'!\n",name);
  333.         if ( errno <= sys_nerr )
  334.             errmess = sys_errlist[errno];
  335.         else
  336.             errmess = "Unknown error!";
  337.         (void) fprintf(stderr,"Reason: %s\n",errmess);
  338.         exit(1);
  339.     }
  340.     return(f);
  341. }
  342.  
  343. error(s)
  344. char *s;
  345. {
  346.     fprintf(stderr,"Error: %s\n",s);
  347. }
  348.  
  349. txt_header(format,ntrks,ldivision)
  350. {
  351.         division = ldivision; 
  352.     /*
  353.     printf("Header format=%d ntrks=%d division=%d\n",format,ntrks,division);
  354.     */
  355. }
  356.  
  357. txt_trackstart()
  358. {
  359.     /*
  360.     printf("Track start\n");
  361.     */
  362. }
  363.  
  364. txt_trackend()
  365. {
  366.     /*
  367.     printf("Track end\n");
  368.     */
  369. }
  370.  
  371. txt_noteon(chan,pitch,vol)
  372. {
  373.     /*
  374.     prtime();
  375.     printf("Note on, chan=%d pitch=%d vol=%d\n",chan+1,pitch,vol);
  376.     */
  377.     if(vol == 0) {
  378.         track[chan].end[track[chan].ewhre]=Mf_currtime;
  379.         track[chan].ewhre++;
  380.         if(lasttick < Mf_currtime)
  381.             lasttick = Mf_currtime;
  382.     } else {
  383.         if(chan > numtracks)
  384.             numtracks = chan;
  385.         track[chan].start[track[chan].swhre]=Mf_currtime;
  386.         track[chan].note[track[chan].swhre]=pitch;
  387.         track[chan].swhre++;
  388.     }
  389. }
  390.  
  391. txt_noteoff(chan,pitch,vol)
  392. {
  393.     /*
  394.     prtime();
  395.     */
  396.     track[chan].end[track[chan].ewhre]=Mf_currtime;
  397.     track[chan].ewhre++;
  398.     if(lasttick < Mf_currtime)
  399.         lasttick = Mf_currtime;
  400. }
  401.  
  402. txt_pressure(chan,pitch,press)
  403. {
  404.     /*
  405.     prtime();
  406.     printf("Pressure, chan=%d pitch=%d press=%d\n",chan+1,pitch,press);
  407.     */
  408. }
  409.  
  410. txt_parameter(chan,control,value)
  411. {
  412.     /*
  413.     prtime();
  414.     printf("Parameter, chan=%d c1=%d c2=%d\n",chan+1,control,value);
  415.     */
  416. }
  417.  
  418. txt_pitchbend(chan,msb,lsb)
  419. {
  420.     /*
  421.     prtime();
  422.     printf("Pitchbend, chan=%d msb=%d lsb=%d\n",chan+1,msb,lsb);
  423.     */
  424. }
  425.  
  426. txt_program(chan,program)
  427. {
  428.     /*
  429.     prtime();
  430.     printf("Program, chan=%d program=%d\n",chan+1,program);
  431.     */
  432. }
  433.  
  434. txt_chanpressure(chan,press)
  435. {
  436.     /*
  437.     prtime();
  438.     printf("Channel pressure, chan=%d pressure=%d\n",chan+1,press);
  439.     */
  440. }
  441.  
  442. txt_sysex(leng,mess)
  443. char *mess;
  444. {
  445.     /*
  446.     prtime();
  447.     printf("Sysex, leng=%d\n",leng);
  448.     */
  449. }
  450.  
  451. txt_metamisc(type,leng,mess)
  452. char *mess;
  453. {
  454.     /*
  455.     prtime();
  456.     printf("Meta event, unrecognized, type=0x%02x leng=%d\n",type,leng);
  457.     */
  458. }
  459.  
  460. txt_metaspecial(type,leng,mess)
  461. char *mess;
  462. {
  463.     /*
  464.     prtime();
  465.     printf("Meta event, sequencer-specific, type=0x%02x leng=%d\n",type,leng);
  466.     */
  467. }
  468.  
  469. txt_metatext(type,leng,mess)
  470. char *mess;
  471. {
  472.     static char *ttype[] = {
  473.         NULL,
  474.         "Text Event",        /* type=0x01 */
  475.         "Copyright Notice",    /* type=0x02 */
  476.         "Sequence/Track Name",
  477.         "Instrument Name",    /* ...       */
  478.         "Lyric",
  479.         "Marker",
  480.         "Cue Point",        /* type=0x07 */
  481.         "Unrecognized"
  482.     };
  483.     int unrecognized = (sizeof(ttype)/sizeof(char *)) - 1;
  484.     register int n, c;
  485.     register char *p = mess;
  486.  
  487.     if ( type < 1 || type > unrecognized )
  488.         type = unrecognized;
  489.     /*
  490.     prtime();
  491.     printf("Meta Text, type=0x%02x (%s)  leng=%d\n",type,ttype[type],leng);
  492.     printf("     Text = <");
  493.     for ( n=0; n<leng; n++ ) {
  494.         c = *p++;
  495.         printf( (isprint(c)||isspace(c)) ? "%c" : "\\0x%02x" , c);
  496.     }
  497.     printf(">\n");
  498.     */
  499. }
  500.  
  501. txt_metaseq(num)
  502. {
  503.     /*
  504.     prtime();
  505.     printf("Meta event, sequence number = %d\n",num);
  506.     */
  507. }
  508.  
  509. txt_metaeot()
  510. {
  511.     /*
  512.     prtime();
  513.     printf("Meta event, end of track\n");
  514.     */
  515. }
  516.  
  517. txt_keysig(sf,mi)
  518. {
  519.     /*
  520.     prtime();
  521.     printf("Key signature, sharp/flats=%d  minor=%d\n",sf,mi);
  522.     */
  523.     midikey[mwhre].when=Mf_currtime;
  524.     /* the ? stuff is to compensate for compilers that don't sign
  525.      * extend the sf */
  526.     midikey[mwhre].nkey = (sf & 0x80) ? (sf | ~0xff) : sf;
  527.     mwhre++;
  528. }
  529.  
  530. txt_tempo(ltempo)
  531. long ltempo;
  532. {
  533.     tempo = ltempo;
  534.     /*
  535.     prtime();
  536.     printf("Tempo, microseconds-per-MIDI-quarter-note=%d\n",tempo);
  537.     */
  538. }
  539.  
  540. txt_timesig(nn,dd,cc,bb)
  541. {
  542.     int denom = 1;
  543.     while ( dd-- > 0 )
  544.         denom *= 2;
  545. /*
  546.     prtime();
  547.     printf("Time signature=%d/%d  MIDI-clocks/click=%d  32nd-notes/24-MIDI-clocks=%d\n",
  548.         nn,denom,cc,bb);
  549. */
  550.     tsig[twhre].when=Mf_currtime;
  551.     tsig[twhre].num=nn;
  552.     tsig[twhre].dnom = denom;
  553.     twhre++;
  554. }
  555.  
  556. txt_smpte(hr,mn,se,fr,ff)
  557. {
  558.     /*
  559.     prtime();
  560.     printf("SMPTE, hour=%d minute=%d second=%d frame=%d fract-frame=%d\n",
  561.         hr,mn,se,fr,ff);
  562.     */
  563. }
  564.  
  565. txt_arbitrary(leng,mess)
  566. char *mess;
  567. {
  568.     /*
  569.     prtime();
  570.     printf("Arbitrary bytes, leng=%d\n",leng);
  571.     */
  572. }
  573.  
  574. prtime()
  575. {
  576.     if(SECONDS)
  577.     printf("Time=%f   ",mf_ticks2sec(Mf_currtime,division,tempo));
  578.     else
  579.     printf("Time=%ld  ",Mf_currtime);
  580. }
  581.  
  582. initfuncs()
  583. {
  584.     Mf_error = error;
  585.     Mf_header =  txt_header;
  586.     Mf_trackstart =  txt_trackstart;
  587.     Mf_trackend =  txt_trackend;
  588.     Mf_noteon =  txt_noteon;
  589.     Mf_noteoff =  txt_noteoff;
  590.     Mf_pressure =  txt_pressure;
  591.     Mf_parameter =  txt_parameter;
  592.     Mf_pitchbend =  txt_pitchbend;
  593.     Mf_program =  txt_program;
  594.     Mf_chanpressure =  txt_chanpressure;
  595.     Mf_sysex =  txt_sysex;
  596.     Mf_metamisc =  txt_metamisc;
  597.     Mf_seqnum =  txt_metaseq;
  598.     Mf_eot =  txt_metaeot;
  599.     Mf_timesig =  txt_timesig;
  600.     Mf_smpte =  txt_smpte;
  601.     Mf_tempo =  txt_tempo;
  602.     Mf_keysig =  txt_keysig;
  603.     Mf_seqspecific =  txt_metaspecial;
  604.     Mf_text =  txt_metatext;
  605.     Mf_arbitrary =  txt_arbitrary;
  606. }
  607. dorest(trck, len)
  608. int trck;
  609. int len;
  610. {
  611.     int i;
  612.  
  613.     if(len > 0) {
  614.         do {
  615.             len = plen(len);
  616.             printf("r;");
  617.         } while(len != 0);
  618.     } else
  619.         printf("mr;", trck);
  620. }
  621. donote(trck, nval, len, tie)
  622. short trck, nval, len, tie;
  623. {
  624.     do {
  625.         len = plen(len);
  626.         pnote(nval, trck);
  627.         accwhre++;
  628.         accnotes[accwhre] = nval;
  629.         if(len != 0) {
  630.             poctave(trck, nval);
  631.             printf("~;");
  632.             if(triplet == 3) {
  633.                 printf("}3;");
  634.                 triplet = 0;
  635.             }
  636.             tied[trck] = 1;
  637.         }
  638.     } while(len != 0);
  639.     poctave(trck, nval);
  640.     if(tie == TIE) {
  641.         printf("~");
  642.         tied[trck] = 1;
  643.     }
  644.     printf(";");
  645.     if(triplet == 3) {
  646.         printf("}3;");
  647.         triplet = 0;
  648.     }
  649. }
  650. dobar()
  651. {
  652.     printf("\nbar\n");
  653. }
  654. plen(len)
  655. int len;
  656. {
  657.     float f;
  658.  
  659.     if(len == division) {
  660.         printf("4");
  661.     } else if (len == (1.5 * division)) {
  662.         printf("4.");
  663.     } else if (len == division * 2) {
  664.         printf("2");
  665.     } else if (len == division * 3) {
  666.         printf("2.");
  667.     } else if (len == division * 4) {
  668.         printf("1");
  669.     } else if (len == (division/2)) {
  670.         printf("8");
  671.     } else if (len == (.75 * division)) {
  672.         printf("8.");
  673.     } else if (len == (division/4)) {
  674.         printf("16");
  675.     } else if (len == (division/4 + division/8)) {
  676.         printf("16.");
  677.     } else if (len == (division/8)) {
  678.         printf("32");
  679.     } else if (len == ((division*2)/3)) {
  680.         if(triplet == 0)
  681.             printf("{4");
  682.         else
  683.             printf("4");
  684.         triplet++;
  685.     } else if (len == (division/3)) {
  686.         if(triplet == 0)
  687.             printf("{8");
  688.         else
  689.             printf("8");
  690.         triplet++;
  691.     } else if (len == (division/6)) {
  692.         if(triplet == 0)
  693.             printf("{16");
  694.         else
  695.             printf("16");
  696.         triplet++;
  697.     /*
  698.      * Try to handle some things that *can't* be a single note..
  699.      * things that will have to be a tie, simply because there's
  700.      * no other way to notate that length.  (Like a halfnote tied
  701.      * to an eigthnote.)
  702.      */
  703.     } else {
  704.         /*
  705.          * Some wierd stuff to find counts like 2.5
  706.          */
  707.         if(len > division) {
  708.             /* a multiple of quarternotes tied to an 8th note? */
  709.             if((len == (2*division) + (division/2)) || (len == (3*division) + (division/2))) {
  710.                 printf("8");
  711.                 return(len - (division/2));
  712.             }
  713.             /* one or more quarternotes tied to an 16th note? */
  714.             if((len == (division) + (division/4)) + (len == (2*division) + (division/4)) || (len == (3*division) + (division/4))) {
  715.                 printf("16");
  716.                 return(len - (division/4));
  717.             }
  718.             /* one or more quarternotes tied to an 32th note? */
  719.             if((len == (division) + (division/8)) + (len == (2*division) + (division/8)) || (len == (3*division) + (division/8))) {
  720.                 printf("32");
  721.                 return(len - (division/8));
  722.             }
  723.             if(len == (division) + (division/2) + (division/4)) {
  724.                 printf("4..");
  725.                 return(0);
  726.             }
  727.             /* Nothing yet?  You're on your own. */
  728.             printf("(BADLEN=%d,%d: quarters=%f)", len, division, f=(float)len/(float)division);
  729.             triplet = 0;
  730.         /*
  731.          * Now deal with stuff less than a quarter in length.
  732.          * People may not like this, but the assumption here is
  733.          * that we have an 8th tied to a 32nd.  Anything else
  734.          * and you're on your own.
  735.          */
  736.         } else {
  737.             if(len == (division/2 + division/8)) {
  738.                 printf("32");
  739.                 return(len - division/32);
  740.             }
  741.             printf("(BADLEN=%d,%d: quarters=%f)", len, division, f=(float)len/(float)division);
  742.         }
  743.     }
  744.     return 0;
  745. }
  746. poctave(trck, nval)
  747. short trck, nval;
  748. {
  749.     /* for defoct=2 */
  750.     if(nval >= 0 && nval < 12)
  751.         printf("-----");
  752.     else if(nval > 11 && nval < 24)
  753.         printf("----");
  754.     else if(nval > 23 && nval < 36)
  755.         printf("---");
  756.     else if(nval > 35 && nval < 48)
  757.         printf("--");
  758.     else if(nval > 47 && nval < 60)
  759.         printf("-");
  760.     else if(nval > 59 && nval < 72)
  761.         printf("");
  762.     else if(nval > 71 && nval < 84)
  763.         printf("+");
  764.     else if(nval > 83 && nval < 96)
  765.         printf("++");
  766.     else if(nval > 95 && nval < 108)
  767.         printf("+++");
  768.     else /* if(nval > 23 && nval < 120); */
  769.         printf("++++");
  770. }
  771. int
  772. goctave(trck, nval)
  773. short trck, nval;
  774. {
  775.     /* for defoct=2 */
  776.     if(nval >= 0 && nval < 12)
  777.         return(0);
  778.     else if(nval > 11 && nval < 24)
  779.         return(1);
  780.     else if(nval > 23 && nval < 36)
  781.         return(2);
  782.     else if(nval > 35 && nval < 48)
  783.         return(3);
  784.     else if(nval > 47 && nval < 60)
  785.         return(4);
  786.     else if(nval > 59 && nval < 72)
  787.         return(5);
  788.     else if(nval > 71 && nval < 84)
  789.         return(6);
  790.     else if(nval > 83 && nval < 96)
  791.         return(7);
  792.     else if(nval > 95 && nval < 108)
  793.         return(8);
  794.     else /* if(nval > 23 && nval < 120); */
  795.         return(9);
  796. }
  797. doheader(fp)
  798. FILE *fp;
  799. {
  800.  
  801.     int i;
  802.     char buf[80];
  803.  
  804.     while(fgets(buf, 80, fp) != '\0') {
  805.         if(strncmp("#headend", buf, 8) == 0)
  806.             return;
  807.         else
  808.             printf("%s", buf);
  809.     }
  810.     printf("// NO \"#headend\" STATEMENT?!\n");
  811. }
  812. dobeamstyle(fp)
  813. FILE *fp;
  814. {
  815.  
  816.     int i, j;
  817.     char buf[80];
  818.     char x[2], y[2];
  819.     int n, d;
  820.  
  821.     while(fgets(buf, 80, fp) != '\0') {
  822.         if(strncmp("#beamend", buf, 8) == 0)
  823.             return;
  824.         else {
  825.             x[0]=buf[0];
  826.             if(buf[1] != '/') {
  827.                 x[1]=buf[1];
  828.                 y[0]=buf[3];
  829.                 if(buf[4] != '=') {
  830.                     y[1] = buf[4];
  831.                     i = 6;
  832.                 } else
  833.                     i = 5;
  834.             } else {
  835.                 y[0] = buf[2];
  836.                 if(buf[3] != '=') {
  837.                     y[1] = buf[3];
  838.                     i = 5;
  839.                 } else 
  840.                     i = 4;
  841.             }
  842.             n = atoi(x);
  843.             d = atoi(y);
  844.             bstyles[bwhre].bnum = n;
  845.             bstyles[bwhre].bdnom = d;
  846.             j = 0;
  847.             while(i < (strlen(buf) - 1)) {
  848.                 bstyles[bwhre].style[j] = buf[i];
  849.                 i++;
  850.                 j++;
  851.             }
  852.             printf("// beamstyle %d/%d = %s\n", bstyles[bwhre].bnum, bstyles[bwhre].bdnom, bstyles[bwhre].style);
  853.             bwhre++;
  854.         }
  855.     }
  856.     printf("// NO \"#beamend\" STATEMENT?!\n");
  857. }
  858. dotranslate(buf)
  859. char *buf;
  860. {
  861.  
  862.     int j, i, o;
  863.     char ii[3], oo[3];
  864.  
  865.     for(i = 0; i < 3; i++) {
  866.         ii[i] = '\0';
  867.         oo[i] = '\0';
  868.     }
  869.     for(j = 10; ((buf[j] == ' ') || (buf[j] == '\t')); j++)
  870.         ;
  871.  
  872.     ii[0] = buf[j];
  873.     j++;
  874.     if(buf[j] == '=') {
  875.         j++;
  876.         oo[0] = buf[j];
  877.     } else {
  878.         ii[1] = buf[j];
  879.         j += 2;
  880.         oo[0] = buf[j];
  881.     }
  882.     j++;
  883.     if(buf[j] != '\n')
  884.         oo[1] = buf[j];
  885.     tlate[tlwhre].in = atoi(ii);
  886.     tlate[tlwhre].out = atoi(oo);
  887.     printf("// Translate track %d to %d.\n", tlate[tlwhre].in, tlate[tlwhre].out);
  888.     tlwhre++;
  889.     return;
  890. }
  891. dokey(buf)
  892. char *buf;
  893. {
  894.  
  895.     int j, i, o;
  896.     char ii[3], oo[3];
  897.  
  898.     for(i = 0; i < 3; i++) {
  899.         ii[i] = '\0';
  900.         oo[i] = '\0';
  901.     }
  902.     for(j = 4; ((buf[j] == ' ') || (buf[j] == '\t')); j++)
  903.         ;
  904.  
  905.     ii[0] = buf[j];
  906.     j++;
  907.     if(buf[j] == '=') {
  908.         j++;
  909.         oo[0] = buf[j];
  910.     } else {
  911.         ii[1] = buf[j];
  912.         j += 2;
  913.         oo[0] = buf[j];
  914.     }
  915.     j++;
  916.     if(buf[j] != '\n')
  917.         oo[1] = buf[j];
  918.     j = hkey[atoi(ii)] = atoi(oo);
  919.     printf("// Key sig for track %d set to %d\n", atoi(ii), j);
  920.     /*
  921.      * printf("staff %d\n", atoi(ii));
  922.      * if(j <= 0)
  923.      *    printf("\tkey=%d&\n", j);
  924.      * else
  925.      *    printf("\tkey=%d#\n", j);
  926.      * printf("music\n");
  927.      */
  928.     return;
  929. }
  930. int
  931. fudge(len)
  932. int len;
  933. {
  934.     float f;
  935.  
  936.     if(abs(division - len) < FFACTOR) {
  937.         return(division);
  938.     } else if (abs((3 * division / 2) - len) < FFACTOR) {
  939.         return(3 * division / 2);
  940.     } else if (abs((division * 2) - len) < FFACTOR) {
  941.         return(division * 2);
  942.     } else if (abs((division * 3) - len) < FFACTOR) {
  943.         return(division * 3);
  944.     } else if (abs((division * 4) - len) < FFACTOR) {
  945.         return(division * 4);
  946.     } else if (abs((division/2) - len) < FFACTOR) {
  947.         return(division/2);
  948.     } else if (abs((3 * division / 4) - len) < FFACTOR) {
  949.         return(3 * division / 4);
  950.     } else if (abs((division/3) - len) < FFACTOR) {
  951.         return(division/3);
  952.     } else if (abs((division/4) - len) < FFACTOR) {
  953.         return(division/4);
  954.     } else if (abs((division/4 + division/8) - len) < FFACTOR) {
  955.         return(division/4 + division/8);
  956.     } else if (abs((division/8) - len) < FFACTOR) {
  957.         return(division/8);
  958.     /*
  959.      * Try to handle some things that *can't* be a single note..
  960.      * things that will have to be a tie, simply because there's
  961.      * no other way to notate that length.  (Like a halfnote tied
  962.      * to an eigthnote.)
  963.      */
  964.     } else {
  965.         /*
  966.          * Some wierd stuff to find counts like 2.5
  967.          */
  968.         if(len > division) {
  969.             /* a multiple of quarternotes tied to an 8th note? */
  970.             if(abs(((2*division) + (division/2)) - len) < FFACTOR) {
  971.                 return((2*division) + (division/2));
  972.             } else if(abs(((3*division) + (division/2)) - len) < FFACTOR) {
  973.                 return((3*division) + (division/2));
  974.             }
  975.             /* one or more quarternotes tied to an 16th note? */
  976.             if(abs(((division) + (division/4)) - len) < FFACTOR) {
  977.                 return((division) + (division/4));
  978.             } else if(abs(((division*2) + (division/4)) - len) < FFACTOR) {
  979.                 return((division*2) + (division/4));
  980.             } else if(abs(((division*3) + (division/4)) - len) < FFACTOR) {
  981.                 return((division*3) + (division/4));
  982.             }
  983.             /* one or more quarternotes tied to an 32th note? */
  984.             if(abs(((division) + (division/8)) - len) < FFACTOR) {
  985.                 return((division) + (division/8));
  986.             } else if(abs(((division*2) + (division/8)) - len) < FFACTOR) {
  987.                 return((division*2) + (division/8));
  988.             } else if(abs(((division*3) + (division/8)) - len) < FFACTOR) {
  989.                 return((division*3) + (division/8));
  990.             }
  991.             if(abs((division) + (division/2) + (division/4) - len) < FFACTOR) {
  992.                 return((division) + (division/2) + (division/4));
  993.             }
  994.             /* Nothing yet?  You're on your own. */
  995.             
  996.             fprintf(stderr, "FUDGE: BADLEN=%d,%d: quarters=%f, measure %d\n", len, division, f=(float)len/(float)division, measure);
  997.         /*
  998.          * Now deal with stuff less than a quarter in length.
  999.          * People may not like this, but the assumption here is
  1000.          * that we have an 8th tied to a 32nd.  Anything else
  1001.          * and you're on your own.
  1002.          */
  1003.         } else {
  1004.             if(abs((division/2 + division/8) - len) < 10) {
  1005.                 return(division/2 + division/8);
  1006.             }
  1007.             fprintf(stderr, "FUDGE: BADLEN=%d,%d: quarters=%f, measure %d\n", len, division, f=(float)len/(float)division, measure);
  1008.         }
  1009.     }
  1010.     return 0;
  1011. }
  1012.  
  1013.  
  1014. #ifdef __DOS__
  1015. /* for systems that don't have a getopt() function,
  1016.  * define one here. This is NOT a general purpose implementation of getopt(),
  1017.  * but something good enough to work */
  1018.  
  1019. int optind = 1;
  1020. char *optarg;
  1021. static int argoffset;
  1022.  
  1023. #define NOARG 1
  1024. #define WITHARG    2
  1025. #define BADOPT  3
  1026.  
  1027. int
  1028. getopt(argc, argv, optstring)
  1029.  
  1030. int argc;
  1031. char **argv;
  1032. char *optstring;
  1033.  
  1034. {
  1035.     int option;
  1036.  
  1037.  
  1038.     if (optind >= argc) {
  1039.         return(EOF);
  1040.     }
  1041.  
  1042.     if (argoffset == 0) {
  1043.         if (argv[optind][argoffset] == '-'
  1044.                     || argv[optind][argoffset] == '/') {
  1045.             argoffset = 1;
  1046.         }
  1047.         else {
  1048.             return(EOF);
  1049.         }
  1050.     }
  1051.  
  1052.     /* determine if option is valid and if should have an argument */
  1053.     option = argv[optind][argoffset] & 0x7f;
  1054.     switch (opttype(option, optstring)) {
  1055.     case NOARG:
  1056.         /* valid option without argument. Keep track of where
  1057.          * to look for next option */
  1058.         if (argv[optind][++argoffset] == '\0') {
  1059.             optind++;
  1060.             argoffset = 0;
  1061.         }
  1062.         break;
  1063.  
  1064.     case WITHARG:
  1065.         /* valid option with argument. */
  1066.         if (argv[optind][++argoffset] != '\0') {
  1067.             /* argument immediately follows in same argv */
  1068.             optarg = &(argv[optind][argoffset]);
  1069.             optind++;
  1070.         }
  1071.         else {
  1072.             /* white space. argument must be in next argv */
  1073.             optind++;
  1074.             if (optind >= argc) {
  1075.                 fprintf(stderr, "missing argument to %c%c option\n", Optch, option);
  1076.                 return('?');
  1077.             }
  1078.             optarg = &(argv[optind][0]);
  1079.             optind++;
  1080.         }
  1081.         argoffset = 0;
  1082.         break;
  1083.  
  1084.     default:
  1085.         fprintf(stderr, "invalid option %c%c\n", Optch, option);
  1086.         option = '?';
  1087.     }
  1088.     return(option);
  1089. }
  1090.  
  1091.  
  1092. /* look up option in optstring and return type of option */
  1093.  
  1094. int
  1095. opttype(option, optstring)
  1096.  
  1097. int option;
  1098. char *optstring;
  1099.  
  1100. {
  1101.     char *p;
  1102.  
  1103.     for (p = optstring; *p != '\0'; ) {
  1104.         if (*p++ == option) {
  1105.             return(*p == ':' ? WITHARG : NOARG);
  1106.         }
  1107.         if (*p == ':') {
  1108.             p++;
  1109.         }
  1110.     }
  1111.     return(BADOPT);
  1112. }
  1113.  
  1114. #endif
  1115.