home *** CD-ROM | disk | FTP | other *** search
/ Chestnut's Multimedia Mania / MM_MANIA.ISO / midi / cmtcmu / phase2.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-06-28  |  10.2 KB  |  343 lines

  1. /* phase2.c -- this module plays notes compiled and sorted in phase1 */
  2.  
  3. /*****************************************************************************
  4. *        Change Log
  5. *  Date        | Change
  6. *-----------+-----------------------------------------------------------------
  7. * 31-Dec-85 | Created changelog
  8. * 31-Dec-85 | Add c:\ to include directives
  9. * 31-Dec-85 | Changed to use new CBREAK as well as kbhit
  10. *  1-Jan-86 | Added stop_reason
  11. *  1-Jan-86 | <rgd/jmn> Require musicfns.h before adagio.h
  12. *        | stop_time is now long
  13. *        | Turn off all notes in moreclean
  14. *        | changed control logic in play
  15. *  1-Jan-86 | Added miditrace
  16. *  1-Jan-86 | Added command scanner at play request level
  17. * 18-Jan-86 | Gave priority to note offs.
  18. *        | Created stop_check routine.
  19. * 21-Jan-86 | Added mpu_error_check to main loop
  20. *  3-Feb-86 | Changed help message slightly
  21. * 24-Mar-86 | Changed representation from note_struct to event_struct
  22. * 16-Jul-86 | Only pass upper case letters to tolower()
  23. *  7-Aug-86 | Initialize bend, touch, porta, mod, and foot controls
  24. *****************************************************************************/
  25.  
  26. #include "cext.h"
  27. #include "stdio.h"
  28. #include "ctype.h"
  29. #include "adagio.h"
  30. #include "mpu.h"
  31. #include "userio.h"
  32. #include "phase2.h"
  33.  
  34. #define stop_code ' '
  35. char stop_explanation[] = "Space bar";
  36.  
  37. extern int musictrace;
  38. extern int miditrace;
  39. extern int CBREAK;
  40.  
  41. #define STOP_CC 1
  42. #define STOP_CBRK 2
  43. #define STOP_KEY 3
  44.  
  45. private long offset = 100;    /* time offset from clock to performance */
  46.  
  47. private int program[num_voices];    /* current program */
  48.  
  49. /****************************************************************************
  50. * Routines local to this module
  51. ****************************************************************************/
  52. private    void    init_stuff();
  53. private    void    moreclean();
  54. private    void    play();
  55. private    void    play_help();
  56. private    void    print_status();
  57. private boolean stop_check();
  58.  
  59. /****************************************************************************
  60. *                  init_stuff
  61. * Effect: initializes this module (called by phase2()).
  62. ****************************************************************************/
  63.  
  64. private void init_stuff()
  65. {
  66.     off_init();
  67. }
  68.  
  69. /****************************************************************************
  70. *                moreclean
  71. * Inputs:
  72. *    event_type root: the score that was in progress
  73. *    int stop_reason: the reason the score was stopped
  74. * Effect: 
  75. *    prints a message to announce stopped state
  76. *    tells what was playing at the stop time
  77. * Implementation:
  78. *    What was playing is determined by reading the time and searching
  79. *    for notes that are on at that time.  If nothing is found on a
  80. *    given channel, it would be nice to print the last note played
  81. *    on the channel provided it was played within say 1 sec of the
  82. *    stop time.  This is unimplemented, but would help locate short
  83. *    notes.
  84. ****************************************************************************/
  85.  
  86. private void moreclean(score, stop_reason)
  87.     event_type score;
  88.     int stop_reason;
  89. {
  90.     long stop_time;    /* time at which moreclean is called */
  91.     event_type n;    /* used to search the score */
  92.  
  93.     stop_time = gettime() - offset;    /* get current time */
  94.  
  95.     while (note_offs(0x7fffffff)) ;    /* turn off all notes */
  96.  
  97.     printf ("\n         * * STOPPED * *\n");
  98.  
  99.     switch(stop_reason)
  100.        { /* reason for stopping */
  101.     case STOP_CC:    printf("Control-C seen\n");
  102.             break;
  103.     case STOP_CBRK: printf("Control-break seen\n");
  104.             break;
  105.     case STOP_KEY:    printf("%s hit\n",stop_explanation);
  106.             break;
  107.        } /* reason for stopping */
  108.  
  109.     if (stop_time > 0)
  110.     printf ("Stopped at time = %ld (hundreths of a second). \n\n",
  111.         stop_time);
  112.  
  113.     for (n = score; n != NULL; n = n->next) {
  114.     if (is_note(n) &&
  115.         (n->ntime <= stop_time) &&
  116.         (n->ntime + n->u.note.ndur) >= stop_time) {
  117.         printf("Voice: %d was playing line: %d\n",
  118.         n->nvoice + 1, n->nline);
  119.     }
  120.     }
  121. }
  122.  
  123. /****************************************************************************
  124. *                    phase2
  125. * Inputs:
  126. *    event_type root: Root of play list
  127. * Effect: 
  128. *    Plays the music
  129. ****************************************************************************/
  130.  
  131. void phase2(root)
  132.     event_type root;
  133. {
  134.     char resp;
  135.     short done = false;
  136.     int truth;
  137.  
  138.     init_stuff();
  139.     while (!done) { /* ask user */
  140.     truth = true;
  141.     printf ("\nType <RETURN> to play notes, q<RETURN> to quit, ?<RETURN> for help:");
  142.     while (true) { /* read input */
  143.         resp = getchar();
  144.         if (isupper(resp)) resp = tolower(resp);
  145.         switch (resp) { /* decode */
  146.         case ' ':
  147.             continue;    /* ignore spaces */
  148.         case '?': 
  149.             play_help();
  150.             readln(stdin);
  151.             break;
  152.         case '-':
  153.             truth = !truth;
  154.             continue;    /* read next char */
  155.         case 't':
  156.             trace(truth);
  157.             readln(stdin);
  158.             break;
  159.         case 'm':
  160.             tracemidi(truth);
  161.             readln(stdin);
  162.             break;
  163.         case 'q':
  164.             done = true;
  165.             readln(stdin);
  166.             break;
  167.         case 'r':
  168.             readln(stdin);
  169.             read_tuning("");
  170.             break;
  171.         case 's':
  172.             print_status();
  173.             readln(stdin);
  174.             break;
  175.         case '\n':
  176.             CBREAK = 0;
  177.             play(root);
  178.             break;
  179.         } /* decode */
  180.         break;
  181.     } /* read input */
  182.     } /* ask user */
  183. }
  184.  
  185. /****************************************************************************
  186. *                     play
  187. * Inputs:
  188. *    event_type score: Score to play
  189. * Effect: 
  190. *    Plays the score
  191. ****************************************************************************/
  192.  
  193. private void play(score)
  194.     event_type score;
  195. {    
  196.     event_type event = score;    /* pointer to next note or control event */
  197.     short done = false;
  198.     int stop_reason;        /* ctrl-C, break, or space bar */
  199.     long time;            /* the current time */
  200.     int i;            /* index counter to initialize channels */
  201.  
  202.     printf("Type %s to stop.\n",stop_explanation);
  203.  
  204.     musicinit();  
  205.  
  206.     /* Initialize all midi channels with reasonable start values: */
  207.     for (i = 1; i <= num_voices; i++) {
  208.     midi_program(i, 1);
  209.     program[i - 1] = 1;
  210.     midi_bend(i, 1 << 13);
  211.     midi_touch(i, 0);
  212.     midi_ctrl(i, PORTARATE, 99);
  213.     midi_ctrl(i, PORTASWITCH, 0);
  214.     midi_ctrl(i, MODWHEEL, 0);
  215.     midi_ctrl(i, FOOT, 99);
  216.     }
  217.  
  218.     timereset();
  219.     l_restuntil(offset);
  220.  
  221.     while (!done) { /* play it, Sam */
  222.     time = gettime() - offset; /* delay everything by offset */
  223.     done = true;
  224.     if (note_offs(time)) done = false;    /* still more note offs */
  225.     if (event != NULL) {  /* something to play */
  226.         done = false;
  227.         if (time >= event->ntime) {
  228.         if (is_note(event)) { /* play a note */
  229.             /* check for correct program (preset) */
  230.             if (event->u.note.nprogram != program[event->nvoice]) {
  231.             midi_program(event->nvoice+1, event->u.note.nprogram);
  232.              program[event->nvoice] = event->u.note.nprogram;
  233.             }
  234.             /* if it is a note (not a rest) play it */
  235.             if (event->u.note.npitch != NO_PITCH) {
  236.             midi_note(event->nvoice+1, event->u.note.npitch,
  237.                   event->u.note.nloud);
  238.             off_schedule(event->ntime + event->u.note.ndur,
  239.                      event->nvoice, event->u.note.npitch);
  240.             }
  241.         } else {    /* send control info */
  242.             switch (vc_ctrl(event->nvoice)) {
  243.             case 1: midi_ctrl(vc_voice(event->nvoice) + 1,
  244.                          PORTARATE,
  245.                          event->u.ctrl.value);
  246.                 break;
  247.             case 2: midi_ctrl(vc_voice(event->nvoice) + 1,
  248.                          PORTASWITCH,
  249.                          event->u.ctrl.value);
  250.                 break;
  251.             case 3: midi_ctrl(vc_voice(event->nvoice) + 1,
  252.                          MODWHEEL,
  253.                          event->u.ctrl.value);
  254.                 break;
  255.             case 4: midi_touch(vc_voice(event->nvoice) + 1,
  256.                        event->u.ctrl.value);
  257.                 break;
  258.             case 5: midi_ctrl(vc_voice(event->nvoice) + 1,
  259.                          FOOT,
  260.                          event->u.ctrl.value);
  261.                 break;
  262.             case 6: midi_bend(vc_voice(event->nvoice) + 1,
  263.                       event->u.ctrl.value << 6);
  264.                 break;
  265.             default: break;
  266.             }
  267.         }
  268.         event = event->next;
  269.         } else if (CBREAK || kbhit()) {
  270.         done = stop_check(&stop_reason);
  271.         if (done) { /* clean up */
  272.             moreclean(score, stop_reason);
  273.         } /* clean up */
  274.         } else mpu_error_check();
  275.     } /* something to play */
  276.     } /* play it, Sam */
  277.  
  278.     musicterm();
  279. }
  280.  
  281. /****************************************************************************
  282. *                   play_help
  283. * Effect: 
  284. *    Lists help for play option
  285. ****************************************************************************/
  286.  
  287. private void play_help()
  288. {
  289.     fprintf(stderr," <return>       Play music\n");
  290.     fprintf(stderr," q<return>       Quit Adagio (Exit)\n\n");
  291.     fprintf(stderr," r<return>       Read tuning file\n");
  292.     fprintf(stderr," m<return>       Turn on MIDI byte trace\n");
  293.     fprintf(stderr,"-m<return>       Turn off MIDI byte trace\n");
  294.     fprintf(stderr," s<return>       Report state\n");
  295.     fprintf(stderr," t<return>       Turn on music operation trace\n");
  296.     fprintf(stderr,"-t<return>       Turn off music operation trace\n");
  297.     fprintf(stderr," ?<return>       This message\n");
  298. }
  299.  
  300. /****************************************************************************
  301. *                  print_status
  302. * Effect: 
  303. *    Informative output about state
  304. ****************************************************************************/
  305.  
  306. private void print_status()
  307. {
  308.     fprintf(stderr,"MIDI trace (m option) %s\n",(miditrace ? "on" : "off"));
  309.     fprintf(stderr,"Music trace (t option) %s\n",(musictrace ? "on" : "off"));
  310. }
  311.  
  312. /****************************************************************************
  313. *                     stop_check
  314. * Outputs:
  315. *    *reason is set to reason for stop
  316. *    true is returned iff play should stop
  317. * Effect: 
  318. *    Checks for break character or stop code from kbd
  319. ****************************************************************************/
  320.  
  321. private boolean stop_check(reason)
  322.     int *reason;
  323. {
  324.     boolean done = false;
  325.     switch (CBREAK) { /* stop reason */
  326.     case 0: /* no stop code, try keyboard */
  327.         done = (getch() == stop_code);
  328.         if (done) *reason = STOP_KEY;
  329.         break;
  330.     case 1: /* ctrl-break */
  331.         done = true;
  332.         if (kbhit()) getch();
  333.         *reason = STOP_CBRK;
  334.         break;
  335.     case 2: /* ctrl-C */
  336.         done = true;
  337.         *reason = STOP_CC;
  338.         if (kbhit()) getch();
  339.         break;
  340.     } /* stop reason */
  341.     return done;
  342. }
  343.