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

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