home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C++ Games Programming
/
CPPGAMES.ISO
/
mt
/
mtrc2.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-03-06
|
10KB
|
249 lines
/* mtrc2.c */
/* `MIDI Sequencing In C', Jim Conger, M&T Books, 1989 */
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include "screenf.h"
#include "standard.h"
#include "mpu401.h"
#include "mt.h"
#include "video.h"
#include "mtdeclar.h"
/* play() is called from record_menu(). Controls playing up to eight */
/* tracks. Calls play_event() to send event data. Uses maybe_measure_ */
/* number() to update measure number during playback. */
void
play(void)
{
int cmd, track, firstcmd, status, trackbits, stop_play, c;
struct event far *ep[NTRACK]; /* temporary pointers to note data */
writeword("Hit ESC or SPACEBAR to stop playback.", 1, g_text_char_v - 1,
g_norm_attrib);
if (g_trace_on){
trace_header();
fputs("Hit ESC key to stop playback.\n\n", stdout);
}
firstcmd = 1;
trackbits = init_401(ep); /* reset and intialize MPU-401 */
if (trackbits == 0){
writerr("No data-containing tracks have PLAY turned ON.",
g_text_char_v - 1, g_norm_attrib, g_norm_attrib);
return;
}
stop_play = 0;
while (1){
cmd = get401(); /* get next mpu-401 request */
if (cmd == -1){ /* initiate exit of play mode on keypress */
while (kbhit()){
c = getch();
if (c == ESC || c == ' '){
if (stop_play)
break;
else
stop_play = 1;
}
}
}
else if (cmd >= REQ_T1 && cmd <= REQ_T8){ /* track req */
firstcmd = 0;
track = cmd - REQ_T1;
if (ep[track]->b[1] == MES_END) /* update measure # */
maybe_measure_number(track, trackbits);
if (stop_play){ /* shutdown track */
putdata401(0); /* wait for ALL_END */
putdata401(DATA_END); /* to stop play */
}
else{
play_event(track, ep[track]); /* send data bytes */
}
/* advance track pointer to next event */
if (ep[track]->next != NULL){
ep[track] = ep[track]->next;
if (ep[track]->b[1] == DATA_END) /* track goes inactive */
trackbits &= ~(1 << track); /* erase from trackbits */
}
}
else if (cmd == ALL_END){
if (firstcmd) /* don't quit if received at start */
firstcmd = 0;
else
break; /* must be at end of song data */
}
else{
/* ignore anything else */
}
}
repeat_cmd401(STOP_PLAY); /* final MPU shutdown command sequence */
repeat_cmd401(CLEAR_PMAP);
repeat_cmd401(MET_OFF);
if (g_trace_on)
wait_for_key();
goto_measure(g_current_measure); /* end on even meas */
}
/* record() is the front end to record_track(). Checks if a track is */
/* active - then records one track. */
void
record(void)
{
if (g_record_track == -1){
writerr("No track is active for recording.",
g_text_char_v - 1, g_norm_attrib, g_emph_attrib);
}
else{ /* start on even measure number */
g_trackarray[g_record_track].current =
advance_to_measure(g_record_track, g_current_measure);
writeword("Hit ESC or SPACEBAR to stop recording.", 1,
g_text_char_v - 1, g_norm_attrib);
if (g_trace_on)
trace_header(); /* if trace is on, put header on screen */
/* go ahead and start record process */
g_trackarray[g_record_track].last = record_track(g_record_track);
clean_track(g_record_track); /* set all recorded data to the */
change_channel(g_record_track, /* the track's MIDI channel */
g_trackarray[g_record_track].midichan);
goto_measure(g_current_measure); /* end on even meas */
if (g_trace_on){
fputs("\nHit a key to return.", stdout);
wait_for_key();
}
}
calc_pct_free(); /* update the free memory left */
}
/* record_track() is the function that controls the recording process */
/* Records a track while playing back any others set to PLAY. Stops on */
/* ESC or spacebar keypress. */
struct event far
*record_track(int rec_track) /* rec_track is the track # set to record */
{
int first, second, third, fourth, mstatus, track, i, status, c, trackbits;
struct event far *firstnode;
struct event far *next_to_last_node;
struct event far *nextnode;
struct event far *ep[NTRACK]; /* temp pointers to note data */
mstatus = 0;
firstnode = g_trackarray[rec_track].current;
nextnode = firstnode->next = eventalloc(); /* create first new event */
trackbits = init_401(ep); /* reset and initialize MPU-401 */
repeat_cmd401(START_REC); /* start record process */
while (1){
first = get401(); /* get 1 byte of data from MPU-401 */
if (first == -1){ /* get401() returns -1 on keypress */
c = getch();
if (c == ESC || c == ' '){
repeat_cmd401(STOP_REC); /* tell MPU to stop recording */
first = 0;
second = ALL_END;
goto forcedstop;
}
}
next_to_last_node = nextnode; /* keep current for returned value */
if (first <= 0xEF){ /* timing byte */
second = get401(); /* so get second byte from MPU */
if (second <= 0x7F){ /* MIDI data, running status assumed */
third = get401(); /* so get third byte from MPU */
nextnode = store(nextnode, 4, first, mstatus, second, third);
}
else if (second <= 0xBF){ /* MIDI message, note on/off */
mstatus = second; /* after touch or control change */
third = get401(); /* so get two more bytes */
fourth = get401();
nextnode = store(nextnode, 4, first, second, third, fourth);
}
else if (second <= 0xDF){ /* prog change or chan after touch */
mstatus = second; /* so get just one more byte */
third = get401();
nextnode = store(nextnode, 3, first, second, third, 0);
}
else if (second <= 0xEF){ /* pitch wheel */
mstatus = second; /* so get to more bytes */
third = get401();
fourth = get401();
nextnode = store(nextnode, 4, first, second, third, fourth);
}
else if (second == 0xF9){ /* measure end - store it */
if (!g_trace_on) /* and update measure # on screen */
write_int(++g_current_measure + 1, 53, 18, g_norm_attrib);
nextnode = store(nextnode, 2, first, second, 0, 0);
}
else if (second == 0xFC){ /* data end - record process done */
forcedstop: store(nextnode, 2, first, second, 0, 0);
nextnode->next = NULL; /* null markes end of track list */
stop_401(trackbits); /* allow all tracks to s/d */
return(next_to_last_node); /* return pointer to end */
}
else{
clearline(g_text_char_v, g_norm_attrib); /* show ?? data */
csrplot(g_text_char_v, 1); /* but continue */
printf("Unrecognized data %x %x", first, second);
}
}
else if (first <= 0xF7){ /* track data request */
track = first - REQ_T1; /* track number */
play_event(track, ep[track]); /* send data bytes */
if (ep[track]->next != NULL){
/* advance track pointer to next event */
ep[track] = ep[track]->next;
}
}
else { /* first byte was not a timing byte - so decode */
switch(first){
case(TIME_OUT):
nextnode = store(nextnode, 1, first, 0, 0, 0);
break;
case(CONDUCT): /* conductor (tempo change) not implemented */
clearline(g_text_char_v, g_norm_attrib);
writeword("Unexpected conductor data request.", 1,
g_text_char_v, g_norm_attrib);
break;
case(DATA_END):
clearline(g_text_char_v, g_norm_attrib);
writeword("All playback tracks are finished.", 1,
g_text_char_v, g_norm_attrib);
break;
case(CLOCK_OUT):
clearline(g_text_char_v, g_norm_attrib);
writeword("Unexpected clock out signal ", 1,
g_text_char_v, g_norm_attrib);
break;
}
}
if (nextnode == NULL){ /* ran out of memory for recording data */
writeword(
"Could not allocate more memory (full?), record stopped.", 1,
g_text_char_v, g_emph_attrib);
repeat_cmd401(STOP_REC);
stop_401(trackbits);
return(next_to_last_node);
}
}
return(next_to_last_node);
}