home *** CD-ROM | disk | FTP | other *** search
- /* trans2.c -- replacement for phase2.c for use in record program */
-
- /*****************************************************************************
- * Change Log
- * Date | Change
- *-----------+-----------------------------------------------------------------
- * 31-Dec-85 | Created changelog
- * 31-Dec-85 | Add c:\ to include directives
- * 31-Dec-85 | Changed to use new CBREAK as well as kbhit
- * 1-Jan-86 | Added stop_reason
- * 1-Jan-86 | <rgd/jmn> Require musicfns.h before adagio.h
- * | stop_time is now long
- * | Turn off all notes in moreclean
- * | changed control logic in play
- * 1-Jan-86 | Added miditrace
- * 1-Jan-86 | Added command scanner at play request level
- * 18-Jan-86 | Gave priority to note offs.
- * | Created stop_check routine.
- * 21-Jan-86 | Added mpu_error_check to main loop
- * 3-Feb-86 | Changed help message slightly
- * 7-Feb-86 | Adapted from phase2 of adagio system to do overdubs
- * 21-May-86 | Pulled over lots of code from latest phase2
- * 7-Aug-86 | Initialize bend, touch, porta, mod, and foot controls
- *****************************************************************************/
- /* This module plays notes compiled and sorted in phase1 and
- * records from the keyboard
- */
-
- #include "cext.h"
- #include "stdio.h"
- #include "adagio.h"
- #include "mpu.h"
- #include "record.h"
- #include "userio.h"
- #include "trans2.h"
-
- #define stop_code ' '
- char stop_explanation[] = "Space bar";
-
- extern int musictrace;
- extern int miditrace;
- extern int CBREAK;
- extern char outfile[]; /* output file from command line */
-
- #define STOP_CC 1
- #define STOP_CBRK 2
- #define STOP_KEY 3
- #define STOP_SPACE 4
-
- private long offset = 100; /* time offset from clock to performance */
-
- private int program[num_voices]; /* current program */
-
- /****************************************************************************
- * routines declared in this module
- ****************************************************************************/
- private void init_stuff();
- private void moreclean();
- private void play();
- private void play_help();
- private void print_status();
- private boolean stop_check();
-
- /****************************************************************************
- * init_stuff
- * Effect:
- * one-time initializations to prepare for playing and recording
- ****************************************************************************/
-
- private void init_stuff()
- {
- off_init();
- }
-
- /****************************************************************************
- * moreclean
- * Inputs:
- * event_type score: the score that was in progress
- * int stop_reason: the reason the score was stopped
- * Effect:
- * prints a message to announce stopped state
- * tells what was playing at the stop time
- * Implementation:
- * What was playing is determined by reading the time and searching
- * for notes that are on at that time. If nothing is found on a
- * given channel, it would be nice to print the last note played
- * on the channel provided it was played within say 1 sec of the
- * stop time. This is unimplemented, but would help locate short
- * notes.
- ****************************************************************************/
-
- private void moreclean(score, stop_reason)
- event_type score;
- int stop_reason;
- {
- long stop_time;
- event_type n;
-
- while (note_offs(0x7fffffff)) ; /* turn off all notes */
-
- printf ("\n * * STOPPED * *\n");
-
- switch(stop_reason)
- { /* reason for stopping */
- case STOP_CC: printf("Control-C seen\n");
- break;
- case STOP_CBRK: printf("Control-break seen\n");
- break;
- case STOP_KEY: printf("%s hit\n",stop_explanation);
- break;
- case STOP_SPACE:printf("Out of space for recording\n");
- break;
- } /* reason for stopping */
-
- stop_time = gettime() - offset;
- if (stop_time > 0)
- printf ("Stopped at time = %ld (hundreths of a second). \n\n",
- stop_time);
-
- for (n = score; n != NULL; n = n->next) {
- if (is_note(n) &&
- (n->ntime <= stop_time) &&
- (n->ntime + n->u.note.ndur) >= stop_time) {
- printf("Voice: %d was playing line: %d\n",
- n->nvoice + 1, n->nline);
- }
- }
- }
-
- /****************************************************************************
- * phase2
- * Inputs:
- * event_type root: Root of play list
- * Effect:
- * Plays the music
- ****************************************************************************/
-
- void phase2(root)
- event_type root;
- {
- char resp;
- short done = false;
- int truth = true;
-
- init_stuff();
-
- while (!done)
- { /* ask user */
- truth = true;
- printf ("\nType <RETURN> to record, q<RETURN> to quit, ?<RETURN> for help:");
- while(true)
- { /* read input */
- resp = getchar();
- switch(tolower(resp))
- { /* decode */
- case ' ':
- continue; /* ignore spaces */
- case '?':
- play_help();
- readln(stdin);
- break;
- case '-':
- truth = !truth;
- continue; /* read next char */
- case 't':
- musictrace = truth;
- readln(stdin);
- break;
- case 'm':
- miditrace = truth;
- readln(stdin);
- break;
- case 'q':
- done = true;
- readln(stdin);
- break;
- case 's':
- print_status();
- readln(stdin);
- break;
- case '\n':
- CBREAK = 0;
- play(root);
- break;
- } /* decode */
- break;
- } /* read input */
- } /* ask user */
- }
-
- /****************************************************************************
- * play
- * Inputs:
- * event_type score: Score to play
- * Effect:
- * Plays the score
- ****************************************************************************/
-
- private void play(score)
- event_type score;
- {
- event_type event = score; /* save first pointer for moreclean */
- short done = false;
- int stop_reason;
- long time = 0;
- int i;
-
- musicinit();
- /* initialize midi recording */
- if (!rec_init(outfile, askbool("Pitch bend, etc. on", false))) {
- printf("No space for recording, use a smaller adagio file\n");
- musicterm();
- exit(1);
- }
-
- printf("Type %s to stop.\n",stop_explanation);
-
- /* Initialize all midi channels with reasonable start values: */
- for (i = 1; i <= num_voices; i++) {
- midi_program(i, 1);
- program[i - 1] = 1;
- midi_bend(i, 0);
- midi_touch(i, 0);
- midi_ctrl(i, PORTARATE, 99);
- midi_ctrl(i, PORTASWITCH, 0);
- midi_ctrl(i, MODWHEEL, 0);
- midi_ctrl(i, FOOT, 99);
- }
-
- timereset();
- l_restuntil(offset);
-
- while (!done) { /* play it, Sam */
- time = gettime() - offset; /* delay everything by offset */
- if (rec_poll(time)) { /* record anything that's there */
- done = true;
- stop_reason = STOP_SPACE;
- }
- if (CBREAK || kbhit()) {
- done |= stop_check(&stop_reason);
- }
- note_offs(time);
- if (done) { /* clean up */
- moreclean(score, stop_reason);
- rec_final(true); /* write out recorded data */
- } else if (event != NULL) { /* something to play */
- if (time >= event->ntime) {
- if (is_note(event)) { /* play a note */
- /* check for correct program (preset) */
- if (event->u.note.nprogram != program[event->nvoice]) {
- midi_program(event->nvoice+1, event->u.note.nprogram);
- program[event->nvoice] = event->u.note.nprogram;
- }
- /* if it is a note (not a rest) play it */
- if (event->u.note.npitch != NO_PITCH) {
- midi_note(event->nvoice+1, event->u.note.npitch,
- event->u.note.nloud);
- off_schedule(event->ntime + event->u.note.ndur,
- event->nvoice, event->u.note.npitch);
- }
- } else { /* send control info */
- switch (vc_ctrl(event->nvoice)) {
- case 1: midi_ctrl(vc_voice(event->nvoice) + 1,
- PORTARATE,
- event->u.ctrl.value);
- break;
- case 2: midi_ctrl(vc_voice(event->nvoice) + 1,
- PORTASWITCH,
- event->u.ctrl.value);
- break;
- case 3: midi_ctrl(vc_voice(event->nvoice) + 1,
- MODWHEEL,
- event->u.ctrl.value);
- break;
- case 4: midi_touch(vc_voice(event->nvoice) + 1,
- event->u.ctrl.value);
- break;
- case 5: midi_ctrl(vc_voice(event->nvoice) + 1,
- FOOT,
- event->u.ctrl.value);
- break;
- case 6: midi_bend(vc_voice(event->nvoice) + 1,
- event->u.ctrl.value << 6);
- break;
- default: break;
- }
- }
- event = event->next;
- }
- } else mpu_error_check();
- } /* play it, Sam */
-
- /* Debugging:
- * i = gettic();
- * printf("Max Latency is %d\n", i);
- */
- musicterm();
- }
-
- /****************************************************************************
- * play_help
- * Effect:
- * Lists help for play option
- ****************************************************************************/
-
- private void play_help()
- {
- fprintf(stderr," <return> Play music\n");
- fprintf(stderr," q<return> Quit Adagio (Exit)\n\n");
- fprintf(stderr," m<return> Turn on MIDI byte trace\n");
- fprintf(stderr,"-m<return> Turn off MIDI byte trace\n");
- fprintf(stderr," s<return> Report state\n");
- fprintf(stderr," t<return> Turn on music operation trace\n");
- fprintf(stderr,"-t<return> Turn off music operation trace\n");
- fprintf(stderr," ?<return> This message\n");
- }
-
- /****************************************************************************
- * print_status
- * Effect:
- * Informative output about state
- ****************************************************************************/
-
- private void print_status()
- {
- fprintf(stderr,"MIDI trace (m option) %s\n",(miditrace ? "on" : "off"));
- fprintf(stderr,"Music trace (t option) %s\n",(musictrace ? "on" : "off"));
- }
-
- /****************************************************************************
- * stop_check
- * Outputs:
- * *reason is set to reason for stop
- * true is returned iff play should stop
- * Effect:
- * Checks for break character or stop code from kbd
- ****************************************************************************/
- private boolean stop_check(reason)
- int *reason;
- {
- boolean done = false;
- switch(CBREAK) { /* stop reason */
- case 0: /* no stop code, try keyboard */
- done = (getch() == stop_code);
- if (done) *reason = STOP_KEY;
- break;
- case 1: /* ctrl-break */
- done = true;
- if (kbhit()) getch();
- *reason = STOP_CBRK;
- break;
- case 2: /* ctrl-C */
- done = true;
- *reason = STOP_CC;
- if (kbhit()) getch();
- break;
- } /* stop reason */
- return done;
- }
-