home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / sound / players / mp02_tar.z / mp02_tar / mp02 / mp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-02-10  |  45.9 KB  |  1,652 lines

  1. /*
  2.  * mp (Midi Play)
  3.  *
  4.  * This program is largely derived from a program
  5.  * 'mftext' by Tim Thompson, and a programs 'transcribe'
  6.  * and 'adagio' by Roger Dannenberg.  Much of the code
  7.  * for playing the SoundBlaster card came from 'fmplay'
  8.  * by Hannu Savolainen (hsavolai@cs.helsinki.fi) with
  9.  * modifications by Rob Hooft (hooft@chem.ruu.nl).
  10.  *
  11.  *        Greg Lee, lee@uhunix.uhcc.hawaii.edu
  12.  *        1/30/93
  13.  */
  14.  
  15.  
  16. #include <stdio.h>
  17. #include <ctype.h>
  18. #include "midifile.h"
  19. #include "midi.h"
  20.  
  21. static FILE *F;
  22.  
  23. #include "cext.h"
  24. #include <malloc.h>
  25. #include "midicode.h"
  26. #include "adagio.h"
  27. #include "userio.h"
  28. #include "cmdline.h"
  29. #include "vname.h"
  30.  
  31. void phase2();
  32.  
  33. #define MAXSPACE 500000
  34. /* the free space counter */
  35. long space = MAXSPACE;
  36.  
  37. #ifndef XPOLYPHANY
  38. #define XPOLYPHANY 48
  39. #endif
  40. #ifndef XMAXCHAN
  41. #define XMAXCHAN 16
  42. #endif
  43.  
  44. #define NO_VOI -1
  45. int program[num_voices] = { NO_VOI,NO_VOI,NO_VOI,NO_VOI,NO_VOI,NO_VOI,
  46.     NO_VOI,NO_VOI,NO_VOI,NO_VOI,NO_VOI,NO_VOI,NO_VOI,NO_VOI,NO_VOI,NO_VOI };
  47. int ext_program[num_voices] = { NO_VOI,NO_VOI,NO_VOI,NO_VOI,NO_VOI,NO_VOI,
  48.     NO_VOI,NO_VOI,NO_VOI,NO_VOI,NO_VOI,NO_VOI,NO_VOI,NO_VOI,NO_VOI,NO_VOI };
  49. int ext_chan[num_voices] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
  50. int ext_poly[num_voices] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
  51. int ext_pan[num_voices] = { -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 };
  52. private int ext_polyphony = 0;
  53.  
  54. /****************************************************************************
  55. * Variables set by command line switches
  56. ****************************************************************************/
  57.  
  58. /****************************************************************************
  59. * Data for command line parsing
  60. ****************************************************************************/
  61. #define nswitches 16
  62. private char *switches[nswitches] = 
  63.     { "-help", "-v",
  64.       "-init", "-i",
  65.       "-trace", "-t",
  66.       "-external", "-e",
  67.       "-drum", "-d",
  68.       "-midi", "-m",
  69.       "-adagio", "-a", "-p", "-s" };
  70.  
  71. #define noptions 1
  72. private char *options[noptions] = { "-tune" };
  73. #define n_t_sw 2
  74. private char *t_switches[n_t_sw] = { "-t", "-trace" };
  75. #define n_a_sw 2
  76. private char *a_switches[n_a_sw] = { "-a", "-adagio" };
  77. #define n_d_sw 2
  78. private char *d_switches[n_d_sw] = { "-d", "-drum" };
  79.  
  80.  
  81. /****************************************************************************
  82. *    Routines local to this module
  83. ****************************************************************************/
  84. private void cmdline_help();
  85.  
  86. /****************************************************************************
  87. *                 cmdline_help
  88. * Effect: 
  89. *    Prints out command line help
  90. ****************************************************************************/
  91.  
  92. private void cmdline_help()
  93. {
  94.     fprintf(stderr,"mp [options] filename [options]\n");
  95.     fprintf(stderr,"       -help         this message\n");
  96.     fprintf(stderr,"       -init (-i)        initialize channels\n");
  97.     fprintf(stderr,"       -v             print note data\n");
  98.     fprintf(stderr,"       -tune file         use tuning from file\n");
  99.     fprintf(stderr,"       -drum (-d)         drum mode\n");
  100.     fprintf(stderr,"       -trace (-t)       trace music\n");
  101.     fprintf(stderr,"       -adagio (-a)      adagio file on stdout\n");
  102. }
  103.  
  104.  
  105. boolean ad_print = false;    /* adagio output */
  106. boolean piano_only = false; /* ignore voice requests */
  107. boolean verbose = false;    /* verbose flag for this module */
  108. boolean vverbose = false;    /* tracing output */
  109. boolean drum_mode = false;
  110. boolean percsel = PSELECT;
  111.  
  112. int max_m_notes = -1;    /* -1 is flag that space must be allocated */
  113.  
  114. /****************************************************************
  115. * data structure m_notes: the midi stream is stored as an array 
  116. * of 4-byte records, each of which is either a time or midi
  117. * data.     Midi data always begins with a control byte (high
  118. * order bit set), and it is assumed times are positive (high
  119. * order bit clear), so the two are easy to distinguish
  120. * IF THE COMPILER PUTS THESE BITS IN THE SAME PLACE.  It looks
  121. * like the high order byte of the time lines up with the last
  122. * byte of a 4 byte array, so we will always set the high order
  123. * bit of the last array byte when the first 3 bytes are filled
  124. * with MIDI data.  This is refered to as the "tag" bit.
  125. * WARNING: Lattice C longs are UNSIGNED, therefore always
  126. * positive.  Test the high order bit with a mask.
  127. ****************************************************************/
  128.  
  129. #define MIDI_CMD_BIT        0x80
  130. #define HIGH_BIT        0x80000000
  131. #define istime(note) (!(((note)->when) & HIGH_BIT))
  132.  
  133. typedef union m_note_struct {
  134.     byte n[4];
  135.     long when;
  136. } *m_note_type, m_note_node;
  137.  
  138. private m_note_type event_buff;    /* pointer to allocated buffer */
  139. private m_note_type next;    /* pointer to next entry in buffer */
  140. private m_note_type last;    /* pointer to last entry in buffer */
  141. private int pile_ups;    /* inner loop iteration count */
  142. private int max_pile;    /* maximum of pile_ups */
  143.  
  144. private int m_division = 96;
  145. private int m_track = -1;
  146. private long m_tempo = 500000;
  147.  
  148. /****************************************************************************
  149. *    Routines local to this module
  150. ****************************************************************************/
  151. private void    bend_filter();
  152. private void    byteorder();
  153. private void    ctrl_filter();
  154. private int    event_bend();
  155. private void    filter();
  156. private long    getdur();
  157. private long    getnext();
  158. private long    diffnext();
  159. private char    map_ctrl();
  160. private char    map_nctrl();
  161. private event_type    phasem();
  162. private void    put_pitch();
  163. private void    rec_init();
  164. private void    stowevent();
  165. private event_type    rec_final();
  166. private long    m_time();
  167. /*************************/
  168.  
  169. filegetc()
  170. {
  171.     return(getc(F));
  172. }
  173.  
  174. main(argc,argv)
  175. int argc;
  176. char **argv;
  177. {
  178.     char *s;
  179.  
  180.     cl_init(switches, nswitches, options, noptions, argv, argc);
  181.  
  182.     if (cl_switch("-help")) {
  183.         cmdline_help(); 
  184.         return;
  185.     }
  186.     if (cl_switch("-v")) verbose = 1;
  187.     piano_only = cl_switch("-p");
  188.     ad_print = (cl_nswitch(a_switches, n_a_sw) != NULL);
  189.     vverbose = (cl_nswitch(t_switches, n_t_sw) != NULL);
  190.     drum_mode = (cl_nswitch(d_switches, n_d_sw) != NULL);
  191.  
  192.     if ((s = cl_arg(1)) != NULL)
  193.         F = fileopen(s, "mid", "r", "Midi song file");
  194.     else
  195.         F = stdin;
  196.  
  197.      rec_init();
  198.     initfuncs();
  199.     Mf_getc = filegetc;
  200.     midifile();
  201.     fclose(F);
  202.     if (ad_print)
  203.         (void)rec_final(true);    /* write out recorded data, */
  204.                     /* suppress time of first event*/
  205.     else    phase2((rec_final(true)));
  206.     exit(0);
  207. }
  208.  
  209.  
  210. error(s)
  211. char *s;
  212. {
  213.     fprintf(stderr,"Error: %s\n",s);
  214. }
  215.  
  216. txt_header(format,ntrks,division)
  217. {
  218.     m_division = division;
  219.     if (!vverbose) return;
  220.     printf("*Header format=%d ntrks=%d division=%d\n",format,ntrks,division);
  221. }
  222.  
  223. txt_trackstart()
  224. {
  225.     Mf_currtime = 0;
  226.     m_track++;
  227.     if (!vverbose) return;
  228.     printf("Start track %d\n", m_track);
  229. }
  230.  
  231. txt_trackend()
  232. {
  233.     if (!vverbose) return;
  234.     printf("End track %d\n", m_track);
  235. }
  236.  
  237. static int repeat_drum = -1;
  238. static int rd_chan, rd_pitch, rd_vol, repeat_vol;
  239. static long rd_time;
  240.  
  241. txt_noteon(chan,pitch,vol)
  242. {
  243.     if (percsel&(1 << chan)) {
  244.         if (pitch > 81) {
  245.             if (vol) repeat_drum = pitch;
  246.             repeat_vol = vol;
  247.             return;
  248.         }
  249.         else if (pitch < 35) return;
  250.         else if (vol) {
  251.             rd_chan = chan;
  252.             rd_pitch = pitch;
  253.             rd_vol = vol;
  254.             rd_time = Mf_currtime;
  255.         }
  256.     }
  257.     else repeat_drum = -1;
  258.  
  259.     if (program[chan] == NO_VOI) txt_program(chan,0);
  260.  
  261.     if (ext_chan[chan] && program[chan] == ext_program[ext_chan[chan]-1]) {
  262.         if (!vol) {
  263.             ext_polyphony--;
  264.             ext_poly[chan]--;
  265.         }
  266.         else if (ext_polyphony < XPOLYPHANY) {
  267.             ext_polyphony++;
  268.             ext_poly[chan]++;
  269.         }
  270.         else {
  271.             ext_chan[chan] = 0;
  272.             ext_polyphony -= ext_poly[chan];
  273.             ext_poly[chan] = 0;
  274. if (verbose)
  275. printf("too many notes on channel %d with voice %d\n", chan+1, program[chan]-1);
  276.         }
  277.     }
  278.     stowevent(NOTEON, chan, pitch, vol);
  279. }
  280.  
  281. txt_noteoff(chan,pitch,vol)
  282. {
  283.     if (percsel&(1 << chan)) {
  284.         if (repeat_drum == pitch && chan == rd_chan) {
  285.             long now = Mf_currtime;
  286.             int roll_sep = 8;
  287.             int roll_cnt = repeat_drum - 81 + 1;
  288.             Mf_currtime = rd_time;
  289.             while (1) {
  290.                 Mf_currtime += 2;
  291.                 stowevent(NOTEON, chan, rd_pitch, 0);
  292.                 if (!roll_cnt) break;
  293.                 roll_cnt--;
  294.                 Mf_currtime += roll_sep;
  295.                 stowevent(NOTEON, chan, rd_pitch, repeat_vol);
  296.             }
  297.             repeat_drum = -1;
  298.             Mf_currtime = now;
  299.         }
  300.         else if (pitch < 35 || pitch > 81) return;
  301.     }
  302.  
  303.     if (ext_chan[chan] && program[chan] == ext_program[ext_chan[chan]-1]) {
  304.         ext_polyphony--;
  305.         ext_poly[chan]--;
  306.     }
  307.     stowevent(NOTEON, chan, pitch, 0);
  308. }
  309.  
  310. txt_pressure(chan,pitch,press)
  311. {
  312.     stowevent(PRESSURE, chan, pitch, press);
  313. }
  314.  
  315. txt_parameter(chan,control,value)
  316. {
  317.     stowevent(CONTROLLER, chan, control, value);
  318. }
  319.  
  320. txt_pitchbend(chan,msb,lsb)
  321. {
  322.     stowevent(PITCHBEND, chan, msb, lsb);
  323. }
  324.  
  325. txt_program(chan,prog)
  326. {
  327.     static int ext_tot = 0;
  328.     int n;
  329.  
  330.     program[chan] = prog + 1;
  331.  
  332.     if (!ext_chan[chan] &&
  333.         !(percsel&(1 << chan)) &&
  334.         ext_tot < XMAXCHAN &&
  335. #ifdef K1
  336.         sub_voice[prog].newv >= 0) {
  337. #else
  338.         XSELECT&(1 << chan)) {
  339. #endif
  340.         ext_program[ext_tot] = prog + 1;
  341.         ext_tot++;
  342.         ext_chan[chan] = ext_tot;
  343.     }
  344.     stowevent(PROGRAM, chan, prog + 1, 0);
  345. }
  346.  
  347. txt_chanpressure(chan,press)
  348. {
  349.     stowevent(CHANPRESSURE, chan, press, 0);
  350. }
  351.  
  352. txt_sysex(leng,mess)
  353. char *mess;
  354. {
  355.     if (!vverbose) return;
  356.     if (vverbose) prtime();
  357.     printf("Sysex, leng=%d\n",leng);
  358. }
  359.  
  360. txt_metamisc(type,leng,mess)
  361. char *mess;
  362. {
  363.     if (!vverbose) return;
  364.     prtime();
  365.     printf("Meta event, unrecognized, type=0x%02x leng=%d\n",type,leng);
  366. }
  367.  
  368. txt_metaspecial(type,leng,mess)
  369. char *mess;
  370. {
  371.     if (!verbose) return;
  372.     if (vverbose) prtime();
  373.     printf("Meta event, sequencer-specific, type=0x%02x leng=%d\n",type,leng);
  374. }
  375.  
  376. txt_metatext(type,leng,mess)
  377. char *mess;
  378. {
  379.     static char *ttype[] = {
  380.         NULL,
  381.         "note",        /* type=0x01 */
  382.         "Copyright Notice",    /* type=0x02 */
  383.         "Sequence/Track Name",
  384.         "Instrument Name",    /* ...       */
  385.         "Lyric",
  386.         "Marker",
  387.         "Cue Point",        /* type=0x07 */
  388.         "note"
  389.     };
  390.     int unrecognized = (sizeof(ttype)/sizeof(char *)) - 1;
  391.     register int n, c;
  392.     register char *p = mess;
  393.  
  394.     if (!verbose) return;
  395.     if ( type < 1 || type > unrecognized )
  396.         type = unrecognized;
  397.     if (vverbose) prtime();
  398.     printf("  %s: ", ttype[type]);
  399.     for ( n=0; n<leng; n++ ) {
  400.         c = *p++;
  401.         printf( (isprint(c)||isspace(c)) ? "%c" : "\\0x%02x" , c);
  402.     }
  403.     printf("\n");
  404. }
  405.  
  406. txt_metaseq(num)
  407. {
  408.     if (!vverbose) return;
  409.     prtime();
  410.     printf("Meta event, sequence number = %d\n",num);
  411. }
  412.  
  413. txt_metaeot()
  414. {
  415.     if (!vverbose) return;
  416.     prtime();
  417.     printf("Meta event, end of track\n");
  418. }
  419.  
  420. txt_keysig(sf,mi)
  421. {
  422.     if (!vverbose) return;
  423.     prtime();
  424.     printf("Key signature, sharp/flats=%d  minor=%d\n",sf,mi);
  425. }
  426.  
  427. txt_tempo(tempo)
  428. long tempo;
  429. {
  430.     m_tempo = tempo;
  431.     if (!vverbose) return;
  432.     prtime();
  433.     printf("Tempo, microseconds-per-MIDI-quarter-note=%d\n",tempo);
  434. }
  435.  
  436. txt_timesig(nn,dd,cc,bb)
  437. {
  438.     int denom = 1;
  439.  
  440.     if (!vverbose) return;
  441.     while ( dd-- > 0 )
  442.         denom *= 2;
  443.     prtime();
  444.     printf("Time signature=%d/%d  MIDI-clocks/click=%d  32nd-notes/24-MIDI-clocks=%d\n",
  445.         nn,denom,cc,bb);
  446. }
  447.  
  448. txt_smpte(hr,mn,se,fr,ff)
  449. {
  450.     if (!vverbose) return;
  451.     prtime();
  452.     printf("SMPTE, hour=%d minute=%d second=%d frame=%d fract-frame=%d\n",
  453.         hr,mn,se,fr,ff);
  454. }
  455.  
  456. txt_arbitrary(leng,mess)
  457. char *mess;
  458. {
  459.     if (!vverbose) return;
  460.     prtime();
  461.     printf("Arbitrary bytes, leng=%d\n",leng);
  462. }
  463.  
  464. prtime()
  465. {
  466.     printf("Time=%ld (%ldcs) ", Mf_currtime,m_time());
  467. }
  468.  
  469. initfuncs()
  470. {
  471.     Mf_error = error;
  472.     Mf_header =  txt_header;
  473.     Mf_trackstart =  txt_trackstart;
  474.     Mf_trackend =  txt_trackend;
  475.     Mf_noteon =  txt_noteon;
  476.     Mf_noteoff =  txt_noteoff;
  477.     Mf_pressure =  txt_pressure;
  478.     Mf_parameter =  txt_parameter;
  479.     Mf_pitchbend =  txt_pitchbend;
  480.     Mf_program =  txt_program;
  481.     Mf_chanpressure =  txt_chanpressure;
  482.     Mf_sysex =  txt_sysex;
  483.     Mf_metamisc =  txt_metamisc;
  484.     Mf_seqnum =  txt_metaseq;
  485.     Mf_eot =  txt_metaeot;
  486.     Mf_timesig =  txt_timesig;
  487.     Mf_smpte =  txt_smpte;
  488.     Mf_tempo =  txt_tempo;
  489.     Mf_keysig =  txt_keysig;
  490.     Mf_seqspecific =  txt_metaspecial;
  491.     Mf_text =  txt_metatext;
  492.     Mf_arbitrary =  txt_arbitrary;
  493. }
  494. /****************************/
  495.  
  496. /* record.c -- keyboard to adagio recorder
  497.  *
  498.  * the interface consists of three routines:
  499.  *        rec_init()        -- initialization
  500.  *        stowevent()        -- store each midi event as encountered
  501.  *        rec_final()        -- called to finish up
  502.  */
  503.  
  504. /*****************************************************************************
  505. *        Change Log
  506. *  Date        | Change
  507. *-----------+-----------------------------------------------------------------
  508. * 27-Feb-86 | Created changelog
  509. *        | Use pedal information when computing durations (code taken
  510. *        |  from transcribe.c)
  511. * 23-Mar-86 | Determine size of transcription when rec_init is called.
  512. * 21-May-86 | Major rewrite to use continuous controls (code taken 
  513. *        |  from transcribe.c)
  514. *****************************************************************************/
  515.  
  516. private void stowevent(command, chan, s1, s2)
  517. int command;
  518. {
  519.     next->when = m_time();
  520.     next++;
  521.     next->n[0] = command | chan;
  522.     next->n[1] = s1;
  523.     next->n[2] = s2;
  524.     next->n[3] = MIDI_CMD_BIT | m_track;    /* set tag bit */
  525.     next++;
  526.  
  527.     if (next >= last) {
  528.         fprintf(stderr,"out of space\n");
  529.         exit(1);
  530.     }
  531. }
  532.  
  533. /****************************************************************************
  534. *                bend_filter
  535. * Inputs:
  536. *    m_note_type m_note: the current m_note
  537. *    m_note_type last: the last recorded event
  538. *    long now: the current time
  539. * Effect:
  540. *    remove pitch bend events in same 0.01 sec time slot
  541. * Implementation:
  542. *    If the current event is a pitch bend that bends again
  543. *    in the same time slot, make it a no-op by replacing it with
  544. *    the time.
  545. ****************************************************************************/
  546.  
  547. private void bend_filter(m_note, last, now)
  548.     m_note_type m_note;    /* current m_note */
  549.     m_note_type last;    /* the last recorded event */
  550.     long now;        /* the current time */
  551. {
  552.     /* first see if there is another bend in this time
  553.      * slot.
  554.      */
  555.     m_note_type m_note2 = m_note + 1;
  556.     while (m_note2 < last) {
  557.     if (istime(m_note2) && (m_note2->when > now)) {
  558.         break; /* new time slot */
  559.     } else if (m_note->n[0] == m_note2->n[0]) {
  560.         m_note->when = now;
  561.         return; /* found another bend */
  562.     }
  563.     m_note2++;
  564.     }
  565. }
  566.  
  567. /****************************************************************************
  568. *                byteorder
  569. * Effect: 
  570. *    check out assumptions about byte order and placement
  571. ****************************************************************************/
  572.  
  573. private void byteorder()
  574. {
  575.     if ((sizeof(event_buff[0]) != 4) ||
  576.     (sizeof(event_buff[0].when) != 4) ||
  577.     (sizeof(event_buff[0].n[0]) != 1)) {
  578.     fprintf(stderr, "implementation error: size problem\n");
  579.     exit(1);
  580.     }
  581.     event_buff[0].n[0] = 0x12;
  582.     event_buff[0].n[1] = 0x34;
  583.     event_buff[0].n[2] = 0x56;
  584.     event_buff[0].n[3] = 0x78;
  585. /**
  586. if (verbose)
  587.     printf("layout is 0x%lx\n", event_buff[0].when);
  588. **/
  589.     if ((event_buff[0].when != 0x78563412) &&
  590.     (event_buff[0].when != 0x12345678)) {
  591.     fprintf(stderr, "implementation error: layout problem\n");
  592.     exit(1);
  593.     }
  594. }
  595.  
  596. /****************************************************************************
  597. *                ctrl_filter
  598. * Inputs:
  599. *    m_note_type m_note: the current m_note
  600. *    m_note_type last: the last recorded event
  601. *    long now: the current time
  602. * Effect:
  603. *    remove ctrl change events in same 0.01 sec time slot
  604. * Implementation:
  605. *    If the current event is a control change that changes again
  606. *    in the same time slot, make it a no-op by replacing it with
  607. *    the time.
  608. ****************************************************************************/
  609.  
  610. private void ctrl_filter(m_note, last, now)
  611.     m_note_type m_note;    /* the current m_note */
  612.     m_note_type last;    /* the last recorded event */
  613.     long now;        /* the current time */
  614. {
  615.     /* see if there is another control change in this time
  616.      * slot.
  617.      */
  618.     m_note_type m_note2 = m_note+1;
  619.     while (m_note2 < last) {
  620.     if (istime(m_note2) && (m_note2->when > now)) {
  621.         break;    /* new time slot */
  622.     } else if ((m_note->n[0] == m_note2->n[0]) &&
  623.            (m_note->n[1] == m_note2->n[1])) {
  624.         m_note->when = now;
  625.         return; /* found another change */
  626.     }
  627.     m_note2++;
  628.     }
  629. }
  630.  
  631. /****************************************************************************
  632. *                event_bend
  633. * Inputs:
  634. *    m_note_type m_note: pointer to a pitch bend event
  635. * Outputs:
  636. *    returns int: an 8 bit pitch bend number
  637. ****************************************************************************/
  638.  
  639. private int event_bend(m_note)
  640.     m_note_type m_note;
  641. {
  642.     return (int) (((m_note->n[1]) >> 6) + ((m_note->n[2]) << 1)); 
  643. }
  644.  
  645. /****************************************************************************
  646. *                filter
  647. * Inputs:
  648. *    m_note_type last: the last m_note recorded
  649. * Effect: allow only one control change per time slot (0.01 sec)
  650. * Implementation:
  651. *    call ctrl_filter and bend_filter to overwrite control changes with
  652. *    noop data (the current time is used as a noop)
  653. ****************************************************************************/
  654.  
  655. private void filter(last)
  656.     m_note_type last;
  657. {
  658.     m_note_type m_note;    /* loop control variable */
  659.     long now;        /* last time seen */
  660.     int command;    /* command pointed to by m_note */
  661.     int chan;        /* channel pointed to by m_note */
  662.  
  663.     for (m_note = event_buff; m_note <= last; m_note++) {
  664.     if (istime(m_note)) {
  665.         now = m_note->when;
  666.     } else {
  667.         command = m_note->n[0] & MIDI_CODE_MASK;
  668.         chan = m_note->n[0] & MIDI_CHN_MASK;
  669.  
  670.         if (command == MIDI_CTRL &&
  671.         m_note->n[1] == SUSTAIN) {
  672.         /* do nothing */;
  673.         } else if (command == MIDI_CTRL) {
  674.         ctrl_filter(m_note, last, now);
  675.         } else if (command == MIDI_TOUCH) {
  676.         bend_filter(m_note, last, now);    /* bend and touch use the */
  677.         } else if (command == MIDI_BEND) {    /*  same filter routines  */
  678.         bend_filter(m_note, last, now);
  679.         }
  680.     }
  681.     }
  682. }
  683.  
  684.  
  685. /****************************************************************************
  686. *                getdur
  687. * Inputs:
  688. *    int i: index of the m_note
  689. *    m_note_type last: pointer to the last event recorded
  690. *    int ped: true if pedal is down at event i
  691. *    long now: the time at event i
  692. * Outputs:
  693. *    returns long: the duration of m_note i
  694. * Assumes:
  695. *    assumes i is a m_note
  696. * Implementation:
  697. *    This is tricky because of pedal messages.  The m_note is kept on by
  698. *    either the key or the pedal.  Keep 2 flags, key and ped.  Key is
  699. *    turned off when a key is released, ped goes off and on with pedal.
  700. *    Note ends when (1) both key and ped are false, (2) key is
  701. *    pressed (this event will also start another m_note).
  702. ****************************************************************************/
  703.  
  704. private long getdur(i, last, ped, now, solo)
  705.     int i;
  706.     m_note_type last;
  707.     int ped;
  708.     long now;
  709.     int solo;
  710. {
  711.     int key = true;    /* flag that says if m_note is on */
  712.     long start = now;
  713.     long lastnow = now;
  714.     int thetrack = event_buff[i].n[3] & 0x7f;
  715.     int chan = event_buff[i].n[0] & MIDI_CHN_MASK;
  716.     int pitch = event_buff[i].n[1];
  717.     m_note_type m_note = &(event_buff[i+1]);
  718.     int m_noteon; /* true if a m_noteon message received on chan */
  719.     int keyon;    /* true if m_noteon message had non-zero velocity */
  720.     int newsolo;
  721.  
  722.     /* search from the next event (i+1) to the end of the buffer:
  723.      */
  724.     for (; m_note < last; m_note++) {
  725.     if (istime(m_note)) {
  726.         now = m_note->when;
  727. /** this might interfere with roll notes
  728.         if (now < lastnow) return(lastnow - start);
  729. **/
  730.     } else {
  731.         if (thetrack != (m_note->n[3] & 0x7f)) return(lastnow - start);
  732. /**
  733. if (thetrack != (m_note->n[3] & 0x7f)) fprintf(stderr,"no term: from %d found %d\n",
  734.     thetrack, m_note->n[3] & 0x7f);
  735. **/
  736.         newsolo = m_noteon = keyon = false;
  737.         if ((m_note->n[0] & MIDI_CHN_MASK) == chan) {
  738.         if ((m_note->n[0] & MIDI_CODE_MASK) == MIDI_CTRL &&
  739.             m_note->n[1] == ALL_NOTES_OFF) return(now - start);
  740.         m_noteon = ((m_note->n[0] & MIDI_CODE_MASK) == MIDI_ON_NOTE) &&
  741.              (m_note->n[1] == pitch);
  742.         if (solo) newsolo = ((m_note->n[0] & MIDI_CODE_MASK) == MIDI_ON_NOTE) &&
  743.              (m_note->n[1] != pitch) && (m_note->n[2] != 0);
  744.         keyon = m_noteon && (m_note->n[2] != 0);
  745.         if ((m_noteon && (m_note->n[2] == 0)) ||
  746.             (((m_note->n[0] & MIDI_CODE_MASK) == MIDI_OFF_NOTE) &&
  747.              (m_note->n[1] == pitch))) key = false;
  748.         if (((m_note->n[0] & MIDI_CODE_MASK) == MIDI_CTRL) &&
  749.             m_note->n[1] == SUSTAIN && m_note->n[2] == 127) ped = true;
  750.         if (((m_note->n[0] & MIDI_CODE_MASK) == MIDI_CTRL) &&
  751.             m_note->n[1] == SUSTAIN && m_note->n[2] == 0) ped = false;
  752.  
  753.         if ((!key && !ped) || keyon || newsolo)
  754.             return now - start;
  755.         }
  756.     }
  757.     lastnow = now;
  758.     }
  759.     return last->when - start;
  760. }
  761.  
  762. /****************************************************************************
  763. *                getnext
  764. * Inputs:
  765. *    int i: the index of the current m_note
  766. *    m_note_type last: pointer to last valid data
  767. *    long now: the current time
  768. * Outputs:
  769. *    returns long: the time of the next m_note, program, or control change
  770. *        (returns time of last event if nothing else is found)
  771. ****************************************************************************/
  772.  
  773. private long getnext(i, last, now)
  774.     int i;    /* the index of the current m_note */
  775.     m_note_type last;    /* pointer to last valid data */
  776.     long now;    /* the current time */
  777. {
  778.     long lastnow = now;
  779.     int thetrack = event_buff[i].n[3] & 0x7f;
  780.  
  781.     i++;    /* advance to next item */
  782.     for (; event_buff + i < last; i++) {
  783.     m_note_type m_note = &(event_buff[i]);
  784.     int cmd = m_note->n[0] & MIDI_CODE_MASK;
  785.  
  786.     if (istime(m_note)) {
  787.         now = m_note->when;
  788.         if (now < lastnow) return(-1);
  789.         lastnow = now;
  790.     } else {
  791.         if ((m_note->n[3] & 0x7f) != thetrack) return(-1);
  792.         if (((cmd == MIDI_ON_NOTE) &&
  793.         (m_note->n[2] != 0)) /* m_note on */ ||
  794.         (cmd == MIDI_CH_PROGRAM) /* program change */ ||
  795.         ((cmd == MIDI_CTRL) &&
  796.         (map_nctrl(m_note->n[1]) < 7)
  797.         /*(m_note->n[1] != SUSTAIN)*/ /* control change */ ) ||
  798.         (cmd == MIDI_TOUCH) ||
  799.         (cmd == MIDI_BEND)) {
  800.                 return now;
  801.         }
  802.     }
  803.     }
  804.     return last->when;
  805. }
  806.  
  807. /****************************************************************************
  808. *                map_ctrl
  809. * Inputs:
  810. *    int control: a midi control number
  811. * Outputs:
  812. *    returns char: an adagio control change command letter, NULL if
  813. *        control change is not one of PORTARATE, PORTASWITCH,
  814. *        MODWHEEL, FOOT
  815. ****************************************************************************/
  816.  
  817. private char map_ctrl(control)
  818.     int control;
  819. {
  820.     switch (control) {
  821.     case PORTARATE:        return 'J';
  822.     case PORTASWITCH:    return 'K';
  823.     case MODWHEEL:        return 'M';
  824.     case FOOT:        return 'X';
  825.     default:        return  0;
  826.     }
  827. }
  828.  
  829. private char map_nctrl(control)
  830.     int control;
  831. {
  832.     switch (control) {
  833.     case PORTARATE:        return 1;
  834.     case PORTASWITCH:    return 2;
  835.     case MODWHEEL:        return 3;
  836.     case FOOT:        return 5;
  837.     case VOLUME:        return 7;
  838.     case PAN:        return 8;
  839.     case EXPRESSION:    return 9;
  840.     default:        return 15;
  841.     }
  842. }
  843.  
  844. private long diffnext(i, last, now, nxlie)
  845.     int i;    /* the index of the current m_note */
  846.     m_note_type last;    /* pointer to last valid data */
  847.     long now;    /* the current time */
  848.     boolean *nxlie;
  849. {
  850.     now = getnext(i, last, now) - now;
  851.     if (now < 0) {
  852.         *nxlie = true;
  853.         return 0;
  854.     }
  855.     *nxlie = false;
  856.     return now;
  857. }
  858.  
  859. /* beginning of interface to adagio "phase1" routines */
  860.  
  861. /****************************************************************************
  862. * The following are used to simulate fixed point with the radix point
  863. * 8 bits from the right:
  864. ****************************************************************************/
  865. #define unity 256
  866. #define round(x) (((x)+128)>>8)
  867. #define precise(x) ((x)<<8)
  868.  
  869.  
  870. private void reverse();
  871. private event_type nalloc();
  872. private event_type ctrlalloc();
  873. private void ins_event();
  874.  
  875.  
  876. private boolean pitch_flag;    /* set when a pitch is indicated */
  877.     /* (if controls changes are given, only allocate a note event if
  878.      *  a pitch was specified -- i.e. when pitch_flag is set)
  879.      */
  880. private boolean rest_flag;    /* set when a rest (R) is found */
  881.     /* this flag is NOT inherited by the next line */
  882.  
  883. private boolean symbolic_dur_flag;
  884.         /* true if last dur was not absolute
  885.          * (if this is set, then the default duration is changed
  886.          *  accordingly when the tempo is changed.)
  887.          */
  888.  
  889. private boolean ctrlflag[nctrl];
  890.         /* true if control change was present
  891.          * ctrlflag[0] true if ANY control change
  892.          * was present
  893.          */
  894. private int ctrlval[nctrl];
  895.         /* the new value of the control */
  896.  
  897. private int new_prog = -1;
  898. private int last_prog[num_voices];/*saved value of program from previous line */
  899.     /* (this is needed to implement the rule that note
  900.      *  events are generated for rests if the program has changed.)
  901.      */
  902.  
  903. /****************************************************************************
  904. *                state variables
  905. * Because each line of an Adagio score inherits properties from the previous
  906. * line, it makes sense to implement the parser as a collection of routines
  907. * that make small changes to some global state.     For example, pitch is a
  908. * global variable.  When the field G4 is encountered, the dopitch routine
  909. * assigns the pitch number for G4 to the variable pitch.  After all fields
  910. * are processed, these variables describe the current note and contain the
  911. * default parameters for the next note as well.
  912. *
  913. * Global variables that are used in this way by the parsing rountines are:
  914. ****************************************************************************/
  915. private int
  916.     linex,    /* index of the next character to be scanned */
  917.     lineno,    /* current line number */
  918.     fieldx,    /* index of the current character within a field */
  919.     pitch,    /* pitch of note */
  920.     loud,    /* loudness of note */
  921.     voice;    /* voice (midi channel) of note */
  922.  
  923. private boolean ndurp;        /* set when a next (N) is indicated */
  924.     /* (next time defaults to the current time plus duration unless
  925.      *  overridden by a next (N) command whose presence is signalled
  926.      *  by ndurp.)
  927.      */
  928.  
  929. private long
  930.     thetime,    /* the starting time of the note */
  931.     thetrack,    /* the midi track of the note */
  932.     thecontrol,    /* the controller */
  933.     rate,    /* time rate -- scales time and duration, default = 100 */
  934.     ntime,    /* the starting time of the next note */
  935.     dur,    /* the duration of the note */
  936.     tempo,    /* the current tempo */
  937.     start;    /* the reference time (time of last !tempo or !rate cmd) */
  938.  
  939. private int pitchtable[7] = { 57, 59, 48, 50, 52, 53, 55 };
  940.  
  941. extern char score_na[name_length];
  942.  
  943. private int note_count = 0;    /* the number of notes translated */
  944. private int ctrl_count = 0;    /* ditto for control commands */
  945.  
  946.  
  947. /****************************************************************************
  948. *                init
  949. * Outputs:    Returns true if OK, false on error.
  950. * Effect:    Initializes program state.
  951. ****************************************************************************/
  952.  
  953. private boolean ad_init()
  954. {
  955.     int i;
  956.  
  957.     /* see if any notes were played on the percussion channels,
  958.      * if not, no need to ask for perc mode and lose voices
  959.      */
  960.     /*if (drum_mode) {*/
  961.         for (i = 0; i < num_voices; i++) if (program[i] < 0)
  962.             percsel &= ~(1 << i);
  963.         if (!percsel) drum_mode = 0;
  964.     /*}*/
  965.  
  966.     for (i = 0; i < nctrl; i++) ctrlflag[i] = false;
  967.  
  968.     dur = precise ((long) 60); /* quarter note */
  969.     lineno = 0;
  970.     thetime = 0;
  971.     thetrack = 0;
  972.     pitch = 48;
  973.     loud = 127;
  974.     voice = 1;
  975.     for (i = 0; i < num_voices; i++) last_prog[i] = -1;
  976.     tempo = 100;
  977.     rate = 100;
  978.     start = 0;
  979.     symbolic_dur_flag = true; /*scale dur by tempo*/
  980.     return true;
  981. }
  982.  
  983. /****************************************************************************
  984. *                ins_note
  985. * Inputs:
  986. *    event_type *score: a linked list in which to insert
  987. * Outputs:
  988. *    returns true on success, false on error (not enough space)
  989. * Effect:
  990. *    note event (if any) corresponding to current line are inserted in 
  991. *    score
  992. * Implementation:
  993. *    if a note on should occur after a note off and doesn't, and the
  994. *    two notes have the same pitch, then the note off can cancel the
  995. *    note on:
  996. *        |------------------| <- this cancels *
  997. *               this -> |-----------| 
  998. *    To make it unlikely that roundoff will cause this situation,
  999. *    dur is decreased by one half of a clock tick before rounding.
  1000. *    Also, phase2 gives precedence to note-offs that are simultaneous
  1001. *    with note-ons.
  1002. ****************************************************************************/
  1003.  
  1004. private boolean ins_note(score)
  1005.     event_type *score;
  1006. {
  1007.     event_type nalloc(), note;
  1008.     if ((note = nalloc()) == NULL) {
  1009.     return false;
  1010.     }
  1011.     note->ntime = round(thetime);
  1012.     note->nvoice = voice - 1;
  1013.     note->nline = lineno;
  1014.     note->ntrack = thetrack;
  1015.     note->next = NULL;
  1016.     if (rest_flag) note->u.note.npitch = NO_PITCH;    /* a rest */
  1017.     else note->u.note.npitch = pitch;
  1018.     note->u.note.ndur = round(dur - (unity/2));
  1019.     note->u.note.nloud = loud;
  1020.     if (program[voice-1] > 0) {
  1021.     note->u.note.nprogram = program[voice-1];
  1022.     if (ext_chan[voice-1] && ext_program[ext_chan[voice-1]-1] == program[voice-1])
  1023.         note->ndest = ext_chan[voice-1];
  1024.     else note->ndest = 0;
  1025.     }
  1026.     else {
  1027.     note->u.note.nprogram = 1;
  1028.     program[voice - 1] = 0;
  1029.     note->ndest = 0;
  1030.     }
  1031.     if (vverbose)
  1032.     fprintf(stderr,
  1033.         "note: track=%d time=%ld dur=%ld pitch=%d voice=%d prog=%d vel=%d\n",
  1034.         note->ntrack, note->ntime, note->u.note.ndur, note->u.note.npitch,
  1035.         note->nvoice, note->u.note.nprogram, note->u.note.nloud);
  1036.     ins_event(score, note);
  1037.     return true;
  1038. }
  1039.  
  1040. private void doctrl(n, v)
  1041.     int n, v;
  1042. {
  1043.     ctrlval[n] = v;
  1044.     ctrlflag[n] = true;
  1045.     ctrlflag[0] = true;    /* ctrlflag[0] set if any flag is set */
  1046. }
  1047.  
  1048.  
  1049. /****************************************************************************
  1050. *                ins_ctrl
  1051. * Inputs:
  1052. *    event_type *score: a linked list in which to insert
  1053. * Outputs:
  1054. *    returns true on success, false on error (not enough space)
  1055. * Effect: 
  1056. *    control events corresponding to current line are inserted in score
  1057. * Implementation:
  1058. *    ctrlflag[i] is true if control i was specified in this line, so
  1059. *    insert one control change for each ctrlflag[i] that is true
  1060. ****************************************************************************/
  1061.  
  1062. private boolean ins_ctrl(score)
  1063.     event_type *score;
  1064. {
  1065.     int i;
  1066.     event_type ctrl;
  1067.  
  1068.     for (i = 1; i < nctrl; i++) {
  1069.     if (ctrlflag[i]) {
  1070.         ctrlflag[i] = false;
  1071.         if ((ctrl = ctrlalloc()) == NULL) {
  1072.         return false;
  1073.         }
  1074.         ctrl->ntime = round(thetime);
  1075.         ctrl->nvoice = ctrl_voice(i, voice-1);
  1076.         if (program[voice-1] > 0) {
  1077.         if (ext_chan[voice-1] && ext_program[ext_chan[voice-1]-1] == program[voice-1])
  1078.             ctrl->ndest = ext_chan[voice-1];
  1079.         else ctrl->ndest = 0;
  1080.         }
  1081.         else ctrl->ndest = 0;
  1082.         ctrl->nline = lineno;
  1083.         ctrl->ntrack = thetrack;
  1084.         ctrl->next = NULL;
  1085.         ctrl->u.ctrl.value = ctrlval[i];
  1086.         ctrl->u.ctrl.control = thecontrol;
  1087.     if (vverbose)
  1088.     fprintf(stderr,
  1089.         "ctrl: time=%ld voice=%d line=%d val=%d\n",
  1090.         ctrl->ntime, ctrl->nvoice, ctrl->nline, ctrl->u.ctrl.value);
  1091.         ins_event(score, ctrl);
  1092.         ctrl_count ++;
  1093.     }
  1094.     }
  1095.     return true;
  1096. }
  1097.  
  1098. /****************************************************************************
  1099. *                parsenote
  1100. * Inputs:
  1101. *    event_type *scoreptr: pointer to the note list
  1102. * Effect: 
  1103. *    parses a note line -- control events (if any) and note event (if
  1104. *    present) are inserted into *scoreptr
  1105. * Assumes:
  1106. *    line contains a string to be parsed
  1107. ****************************************************************************/
  1108.  
  1109. private boolean parsenote(scoreptr)
  1110.     event_type *scoreptr;    /* the translated note list */
  1111. {
  1112.     boolean out_of_memory = false;
  1113.  
  1114.     ndurp = false;
  1115.  
  1116.     if (!piano_only && new_prog >= 0) program[voice-1] = new_prog;
  1117.  
  1118. /* try controls first (see note below) -- gl */
  1119.     if (ctrlflag[0]) {
  1120.     out_of_memory |= !ins_ctrl(scoreptr);
  1121.     /*ctrlflag[0] = false;*/
  1122.     }
  1123.  
  1124.     /* insert a note if
  1125.      *    (1) a pitch was specified OR
  1126.      *    (2) no control was specified and this is not a rest 
  1127.      *        (it's a pitch by default) OR
  1128.      *    (3) there is a program change (even if this is a rest)
  1129.      *
  1130.      * NOTE: program changes during rests are advised since
  1131.      *    synthesizers may not be able to process a program
  1132.      *    change followed immediately by a note-on.  In fact, this
  1133.      *    is why we insert notes whose pitch is NO_PITCH -- so that
  1134.      *    the program change can be processed during the rest.
  1135.      */
  1136.     if (pitch_flag ||
  1137.     (!ctrlflag[0] && !rest_flag) ||
  1138.     (program[voice-1] != last_prog[voice-1])) {
  1139.     out_of_memory = !ins_note(scoreptr);
  1140.     note_count ++;
  1141.     }
  1142.     /*
  1143.      * insert ctrl's last so that when the score is reversed,
  1144.      * they will be first.
  1145.      */
  1146. /* above strategy does not seem to work, so I have moved this
  1147.    to before a note is generated.  Then ctrl's really do wind
  1148.    up before notes, when times are equal -- gl */
  1149. /*
  1150.     if (ctrlflag[0]) {
  1151.     out_of_memory |= !ins_ctrl(scoreptr);
  1152.     ctrlflag[0] = false;
  1153.     }
  1154. */
  1155.  
  1156. /* but still have to note that the ctrl's have now been generated -- gl */
  1157.     ctrlflag[0] = false;
  1158.  
  1159.     last_prog[voice-1] = program[voice-1];
  1160.     new_prog = -1;
  1161.  
  1162.     if (ndurp) thetime += ntime;
  1163.     else thetime += dur;
  1164.  
  1165.     return out_of_memory;
  1166. }
  1167.  
  1168.  
  1169.  
  1170. /****************************************************************************
  1171. *    phasem (adapted from "output" routine of transcribe and "phase1")
  1172. * Inputs:
  1173. *    m_note_type last: the last data in the buffer
  1174. *    boolean absflag: set to true if first line of the adagio score should
  1175. *        include the absolute time
  1176. * Effect: 
  1177. *    write adagio score using data in event_buff
  1178. * Implementation:
  1179. *    NOTE: put all program changes in rests
  1180. *    use N(ext) notation for all timing
  1181. *    output no more than one continuous parameter change per
  1182. *    clock tick for each continuous change parameter
  1183. ****************************************************************************/
  1184.  
  1185. private event_type phasem(last, absflag)
  1186.     m_note_type last;
  1187.     boolean absflag;
  1188. {
  1189.     int i;            /* loop counter */
  1190.     int command;        /* the current command */
  1191.     int chan;            /* the midi channel of the current event */
  1192.     int lastchan = 0;        /* the default adagio channel (1) */
  1193.     int ped = false;        /* flag maintains state of pedal */
  1194.     int how_many = last - event_buff;
  1195.     long now;        /* the time of the next event */
  1196.     boolean bad_ctrl_flag = false;    /* set to true if unknown ctrl read */
  1197.     boolean nxlie = false;
  1198. /* variables from "phase1" */
  1199.     event_type score = NULL;    /* the translated note list */
  1200.     boolean out_of_memory = false;    /* set when no more memory */
  1201.  
  1202.     if (!ad_init()) {  /* something bad happened in init(), STOP */
  1203.     fprintf(stderr,"WOOPS; something strange happened in INIT()!  ...exiting\n");
  1204.     exit(1);
  1205.     return NULL;    /* make lint happy */
  1206.     }
  1207.     lineno = 0;
  1208.  
  1209.  
  1210.     /* set the initial absolute time, all other times are relative */
  1211.     if (absflag && ad_print)
  1212.     printf("t%ld ", round(event_buff[0].when));
  1213.  
  1214.     for (i = 0; i < how_many; i++) {
  1215.     if (vverbose) {
  1216.         printf("ev %d: %x %x %x (%ld)\n", i, event_buff[i].n[0],
  1217.         event_buff[i].n[1], event_buff[i].n[2], event_buff[i].when);
  1218.     }
  1219.     if (istime(event_buff+i)) {
  1220.         now = event_buff[i].when;
  1221.         if (vverbose) printf("i = %d, now = %ld\n", i, now);
  1222.     } else {
  1223.         command = event_buff[i].n[0] & MIDI_CODE_MASK;
  1224.         chan = event_buff[i].n[0] & MIDI_CHN_MASK;
  1225.  
  1226.         if ( nxlie &&
  1227.          (command != MIDI_ON_NOTE || event_buff[i].n[2] != 0)
  1228.         ) {
  1229.         if (ad_print) printf("t%ld ", round(now));
  1230.         nxlie = false;
  1231.         }
  1232.  
  1233.         pitch_flag = false;
  1234.         thetime = now;
  1235.         voice = chan + 1;
  1236.         thetrack = event_buff[i].n[3] & 0x7f;
  1237.         dur = 0;
  1238.         rest_flag = true;
  1239.         if (command == MIDI_CTRL) thecontrol = event_buff[i].n[1];
  1240.         else thecontrol = -1;
  1241.  
  1242.         if (command == MIDI_ON_NOTE && event_buff[i].n[2] != 0) {
  1243.         int solo;
  1244.         pitch = event_buff[i].n[1] - 12;
  1245.         pitch_flag = true;
  1246.         rest_flag = false;
  1247.         if (!(percsel&(1 << chan)) && program[chan] > 0)
  1248.             solo = sub_voice[program[chan]-1].solo;
  1249.         else solo = 0;
  1250.         dur = getdur(i, last, ped, now, solo);
  1251.         loud = event_buff[i].n[2];
  1252.  
  1253.         if (ad_print) {
  1254.             put_pitch(pitch);
  1255.             printf(" u%ld l%d n%ld", round(dur), loud,
  1256.                 round(diffnext(i,last,now,&nxlie)));
  1257.             if (lastchan != chan) {
  1258.                     printf(" v%d\n", chan + 1);
  1259.                     lastchan = chan;
  1260.             } else printf("\n");
  1261.         }
  1262.         } else if (command == MIDI_CH_PROGRAM) {
  1263.         new_prog = event_buff[i].n[1];
  1264.  
  1265.         if (ad_print) {
  1266.             printf("r z%d n%ld", event_buff[i].n[1],
  1267.                 round(diffnext(i,last,now,&nxlie)));
  1268. /**
  1269.             if (lastchan != chan) {
  1270.                 printf(" v%d\n", chan + 1);
  1271.             } else printf("\n");
  1272. **/
  1273.             printf(" v%d\n", chan + 1);
  1274.         }
  1275.         } else if (command == MIDI_CTRL &&
  1276.                event_buff[i].n[1] == SUSTAIN) {
  1277.         ped = (event_buff[i].n[2] != 0);
  1278.         } else if (command == MIDI_CTRL) {
  1279.         char c = map_ctrl(thecontrol);
  1280.         int n = map_nctrl(thecontrol);
  1281.         if (thecontrol == PAN && ext_pan[chan] == -1)
  1282.             ext_pan[chan] = event_buff[i].n[2];
  1283.         if (n != 0) doctrl(n, event_buff[i].n[2]);
  1284.         if (c != 0) {
  1285.             if (ad_print) printf("%c%d n%d\n", c,
  1286.             event_buff[i].n[2], round(diffnext(i,last,now,&nxlie)));
  1287.         } else if (n == 0) bad_ctrl_flag = true;
  1288.         } else if (command == MIDI_TOUCH) {
  1289.         doctrl(4, event_buff[i].n[1]);
  1290.         if (ad_print) printf("O%d n%d\n", event_buff[i].n[1],
  1291.             round(diffnext(i,last,now,&nxlie)));
  1292.         } else if (command == MIDI_POLY_TOUCH) {
  1293. /* perhaps this would be unwise
  1294.         doctrl(4, event_buff[i].n[1]);
  1295.         if (ad_print) printf("O%d n%d\n", event_buff[i].n[1],
  1296.             round(diffnext(i,last,now,&nxlie)));
  1297. */
  1298.         } else if (command == MIDI_BEND) {
  1299.         doctrl(6, event_bend(&event_buff[i]));
  1300.         if (ad_print) {
  1301.             printf("Y%d n%d", event_bend(&event_buff[i]),
  1302.                 round(diffnext(i,last,now,&nxlie)));
  1303.             if (lastchan != chan) printf(" v%d\n", chan + 1);
  1304.             else printf("\n");
  1305.         }
  1306.         } else if (command != MIDI_ON_NOTE) {
  1307.         if (verbose) fprintf(stderr, "Command 0x%x ignored\n", command);
  1308.         }
  1309.  
  1310.         if (pitch_flag || ctrlflag[0] || lastchan != chan || new_prog > 0)
  1311.         out_of_memory = parsenote(&score);
  1312.         lastchan = chan;
  1313.     }
  1314.     }
  1315.  
  1316.     if (bad_ctrl_flag && verbose)
  1317.     fprintf(stderr,
  1318.            "Some unrecognized control changes were omitted from file.\n");
  1319.  
  1320.     if (out_of_memory) {
  1321.     fprintf(stderr,"Out of note memory at line %d,\n", lineno-1);
  1322.     fprintf(stderr,"    the rest of your file will be ignored.\n");
  1323.     }
  1324.  
  1325.     if (verbose)
  1326.     printf (
  1327.     "Phase 1 completed; %d note(s), %d ctrl(s) have been translated.\n\n",
  1328.     note_count, ctrl_count);
  1329.  
  1330.     free(event_buff);
  1331.     reverse(&score);
  1332.     return score;
  1333. }
  1334.  
  1335. /****************************************************************************
  1336. *                put_pitch
  1337. * Inputs:
  1338. *    FILE *fp: an open file
  1339. *    int p: a pitch number
  1340. * Effect: write out the pitch name for a given number
  1341. ****************************************************************************/
  1342.  
  1343. private void put_pitch(p)
  1344.     int p;
  1345. {
  1346.     static char *ptos[] = {"c", "cs", "d", "ef", "e", "f", "fs", "g",
  1347.                "gs", "a", "bf", "b"};
  1348.     printf("%s%d", ptos[p % 12], p / 12);
  1349. }
  1350.  
  1351. /**********************************************************************
  1352. *            rec_final
  1353. * Inputs:
  1354. *    boolean absflag: output absolute time of first m_note if true
  1355. * Effect:
  1356. *    Write recorded data to a file
  1357. **********************************************************************/
  1358.  
  1359. /*private void rec_final(absflag)*/
  1360. private event_type rec_final(absflag)
  1361.     boolean absflag;
  1362. {
  1363.     next->when = m_time();
  1364.     last = next;
  1365.     /*if (verbose) printf("max_pile_up = %d, ", max_pile);*/
  1366.     if (verbose) printf(" %d times and events recorded.\n", last - event_buff);
  1367.     filter(last);
  1368.     return(phasem(last, absflag));
  1369. }
  1370.  
  1371. /****************************************************************************
  1372. *                rec_init
  1373. * Inputs:
  1374. *    char *file:  pointer to file name from command line (if any)
  1375. *    boolean bender: true if pitch bend should be enabled
  1376. * Outputs:
  1377. *    returns true if initialization succeeds
  1378. * Effect:
  1379. *    prepares module to record midi input
  1380. ****************************************************************************/
  1381.  
  1382. private void rec_init()
  1383. {
  1384. #ifndef linux
  1385.     char *malloc();    /* memory allocation */
  1386. #endif
  1387.     pile_ups = 0;
  1388.     max_pile = 0;
  1389.  
  1390.     if (max_m_notes == -1) {    /* allocate space 1st time rec_init called */
  1391.     max_m_notes = space/sizeof(m_note_node);
  1392.     event_buff = (m_note_type) malloc(sizeof(m_note_node) * max_m_notes);
  1393.     if (event_buff == NULL) {
  1394.         fprintf(stderr, "Internal error allocating record space.");
  1395.         exit(1);
  1396.     }
  1397.     byteorder();
  1398. if (verbose)
  1399.     printf("Space for %d events has been allocated.\n", max_m_notes);
  1400.     }
  1401.     next = event_buff;
  1402.     last = event_buff + max_m_notes - 2;
  1403.  
  1404.  
  1405.     return;
  1406. }
  1407.  
  1408. long
  1409. m_time()
  1410. {
  1411.     double time;
  1412.  
  1413.     time = mf_ticks2sec(Mf_currtime,m_division,m_tempo);
  1414.     return( (unsigned long) (time * 100 * 256));
  1415. }
  1416.  
  1417. #if 0
  1418. /****************************************************************************
  1419. *                parsenote
  1420. * Inputs:
  1421. *    event_type *scoreptr: pointer to the note list
  1422. * Effect: 
  1423. *    parses a note line -- control events (if any) and note event (if
  1424. *    present) are inserted into *scoreptr
  1425. * Assumes:
  1426. *    line contains a string to be parsed
  1427. ****************************************************************************/
  1428.  
  1429. private boolean parsenote(scoreptr)
  1430.     event_type *scoreptr;    /* the translated note list */
  1431. {
  1432.     boolean out_of_memory = false;
  1433.  
  1434.     ndurp = false;
  1435.     rest_flag = false;
  1436.  
  1437.     /* this loop reads tokens for a note */
  1438.     while (strlen(token) > 0) {
  1439.     parsefield();
  1440.     linex += scan(&line[linex]);
  1441.     }
  1442.  
  1443.     parseend(); /* take care of note terminator */
  1444.  
  1445.     if (new_prog >= 0) program[voice-1] = new_prog;
  1446.  
  1447. /* try controls first (see note below) -- gl */
  1448.     if (ctrlflag[0]) {
  1449.     out_of_memory |= !ins_ctrl(scoreptr);
  1450.     /*ctrlflag[0] = false;*/
  1451.     }
  1452.  
  1453.     /* insert a note if
  1454.      *    (1) a pitch was specified OR
  1455.      *    (2) no control was specified and this is not a rest 
  1456.      *        (it's a pitch by default) OR
  1457.      *    (3) there is a program change (even if this is a rest)
  1458.      *
  1459.      * NOTE: program changes during rests are advised since
  1460.      *    synthesizers may not be able to process a program
  1461.      *    change followed immediately by a note-on.  In fact, this
  1462.      *    is why we insert notes whose pitch is NO_PITCH -- so that
  1463.      *    the program change can be processed during the rest.
  1464.      */
  1465.     if (pitch_flag ||
  1466.     (!ctrlflag[0] && !rest_flag) ||
  1467.     (program[voice-1] != last_prog[voice-1])) {
  1468.     out_of_memory = !ins_note(scoreptr);
  1469.     note_count ++;
  1470.     }
  1471.     /*
  1472.      * insert ctrl's last so that when the score is reversed,
  1473.      * they will be first.
  1474.      */
  1475. /* above strategy does not seem to work, so I have moved this
  1476.    to before a note is generated.  Then ctrl's really do wind
  1477.    up before notes, when times are equal -- gl */
  1478. /*
  1479.     if (ctrlflag[0]) {
  1480.     out_of_memory |= !ins_ctrl(scoreptr);
  1481.     ctrlflag[0] = false;
  1482.     }
  1483. */
  1484.  
  1485. /* but still have to note that the ctrl's have now been generated -- gl */
  1486.     ctrlflag[0] = false;
  1487.  
  1488.     last_prog[voice-1] = program[voice-1];
  1489.     new_prog = -1;
  1490.  
  1491.     if (ndurp) thetime += ntime;
  1492.     else thetime += dur;
  1493.  
  1494.     return out_of_memory;
  1495. }
  1496.  
  1497. /****************************************************************************
  1498. *                phase1
  1499. * Inputs:
  1500. *    FILE *fp: input file
  1501. * Outputs:
  1502. *    returns event_type: the parsed score
  1503. * Effect: 
  1504. *    parses score from input file and builds score data structure
  1505. ****************************************************************************/
  1506.  
  1507. event_type phase1(fp)
  1508. FILE *fp;
  1509. {
  1510.     event_type score = NULL;    /* the translated note list */
  1511.     boolean out_of_memory = false;    /* set when no more memory */
  1512.  
  1513.     if (!init()) {  /* something bad happened in init(), STOP */
  1514.     fprintf(stderr,"WOOPS; something strange happened in INIT()!  ...exiting\n");
  1515.     exit(1);
  1516.     return NULL;    /* make lint happy */
  1517.     }
  1518.  
  1519.     lineno = 0;
  1520.  
  1521.     /* this loop reads lines */
  1522.     while ((fgets(line, linesize, fp) != NULL) && !out_of_memory) {
  1523.     lineno++;
  1524.     linex = 0;
  1525.     /* this loop reads notes from a line */
  1526.     while ((line[linex] != 0) && !out_of_memory) {
  1527.         /* loop invariant: line[linex] is first char of next note */
  1528.         pitch_flag = false;
  1529.         linex += scan(&line[linex]);
  1530.         if (!nullstring(token)) {
  1531.         if (token[0] == '*') docomment();
  1532.         else if (token[0] == '!') dospecial();
  1533.         else out_of_memory = parsenote(&score);
  1534.         } else parseend();
  1535.     }
  1536.     }
  1537.  
  1538.  
  1539.     if (out_of_memory) {
  1540.     fprintf(stderr,"Out of note memory at line %d,\n", lineno-1);
  1541.     fprintf(stderr,"    the rest of your file will be ignored.\n");
  1542.     }
  1543.  
  1544. if (verbose)
  1545.     printf (
  1546.     "\nPhase 1 completed; %d note(s), %d ctrl(s) have been translated.\n",
  1547.     note_count, ctrl_count);
  1548.  
  1549.     reverse(&score);
  1550.     return score;
  1551. }
  1552. #endif
  1553.  
  1554. /****************************************************************************
  1555. *                reverse
  1556. * Inputs:
  1557. *    event_type *p: pointer to a list of notes and control events
  1558. * Effect: reverses note and control events in p
  1559. ****************************************************************************/
  1560.  
  1561. private void reverse(p)
  1562. event_type *p;
  1563. {
  1564.     event_type p1, p2, p3;
  1565.     p1 = *p;
  1566.     if (p1 == NULL) return;
  1567.     p2 = p1->next;
  1568.     p1->next = NULL;
  1569.     while (p2 != NULL) {
  1570.     p3 = p2->next;
  1571.     p2->next = p1;
  1572.     p1 = p2;
  1573.     p2 = p3;
  1574.     }
  1575.     *p = p1;
  1576. }
  1577.  
  1578. /****************************************************************************
  1579. *                ins_event
  1580. * Inputs:
  1581. *    event_type *p: a linked list in which to insert
  1582. *    event_type event: the new event to insert
  1583. * Effect: 
  1584. *    inserts event into score in reverse time order (this makes inserts
  1585. *    that are sequential in time go fast)
  1586. ****************************************************************************/
  1587.  
  1588. private void ins_event(p, event)
  1589.     event_type *p;    /* the score */
  1590.     event_type event;    /* the new event to insert */
  1591. {
  1592.     event_type ptr = *p;
  1593.     event_type prv;
  1594.  
  1595.     if (ptr == NULL || event->ntime >= ptr->ntime) {
  1596.     event->next = ptr;    /* insert at head of list */
  1597.     *p = event;
  1598.     } else { /* list insert */
  1599.     while (ptr != NULL && event->ntime < ptr->ntime) {
  1600.         prv = ptr;
  1601.         ptr = ptr->next;
  1602.     }
  1603.     prv->next = event;
  1604.     event->next = ptr;
  1605.     }
  1606. }
  1607.  
  1608.  
  1609. /****************************************************************************
  1610. *                nalloc
  1611. * Outputs: returns event_type for an event allocated from heap, NULL on error
  1612. * Effect: allocates memory, decreases space accordingly
  1613. ****************************************************************************/
  1614.  
  1615. private event_type nalloc()
  1616. {    
  1617. #ifndef linux
  1618.     char *malloc();
  1619. #endif
  1620.     event_type result;
  1621.     space -= sizeof(struct event_struct);
  1622.     if (space > 0) {
  1623.     result = ((event_type ) malloc (sizeof(struct event_struct)));
  1624.     if (result == NULL)
  1625.         printf("Internal error: Out of memory, space = %ld.\n",space);
  1626.     } else result = NULL;
  1627.     return result;
  1628. }
  1629.  
  1630. /****************************************************************************
  1631. *                ctrlalloc
  1632. * Outputs: returns an event_type for representing a control change
  1633. *       returns NULL if space is unavailable
  1634. * Effect: allocates ctrlsize bytes
  1635. * Assumes: space tells how many bytes are available
  1636. ****************************************************************************/
  1637. private event_type ctrlalloc()
  1638. {    
  1639. #ifndef linux
  1640.     char *malloc();
  1641. #endif
  1642.     event_type result;
  1643.     space -= ctrlsize;
  1644.     if (space > 0) {
  1645.     result = (event_type ) malloc(ctrlsize);
  1646.     if (result == NULL)    /* this should never happen ... */
  1647.         printf("Internal error: Out of memory, space = %ld.\n",space);
  1648.     } else result = NULL;
  1649.     return result;
  1650. }
  1651.  
  1652.