home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C++ Games Programming
/
CPPGAMES.ISO
/
mt
/
mtsc4.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-01-13
|
9KB
|
279 lines
/* mtsc4.c */
/* `MIDI Sequencing In C', Jim Conger, M&T Books, 1989 */
/* #define TURBOC 1 Define if using TURBOC, leave out for Microsoft */
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#ifdef TURBOC
#include <alloc.h>
#else
#include <malloc.h>
#endif
#include "standard.h"
#include "screenf.h"
#include "mpu401.h"
#include "mt.h"
#include "video.h"
#include "mtsc.h"
#include "mtdeclar.h"
/* Adds note to track event list and not_time note list. Returns 1 if */
/* added, 0 if aborted */
void
add_note(struct note_time far *first_notep, int measure, int track)
{
int on_meas, on_tick, on_note, off_meas, off_tick, vel, *velp, status,
on_x, on_y, off_x, off_y;
float time_on, time_off;
struct note_time far *notetime;
struct note_pos *notepos;
struct event far *on_event;
struct event far *off_event;
velp = &vel;
writeword("Move cross hair to NOTE START, then hit return (ESC to exit)",
1, g_graph_char_v - 1, g_norm_attrib);
notepos = select_note(measure, FALSE);
if (notepos == NULL){
clearline(g_graph_char_v - 1, g_norm_attrib);
return;
}
else{
on_meas = notepos->measure;
on_tick = notepos->tick;
on_note = notepos->note;
on_x = notepos->sprite_x;
on_y = notepos->sprite_y;
xsprite(cross, on_x, on_y, g_emph_color);
}
g_sc_refresh = 2;
clearline(g_graph_char_v - 1, g_norm_attrib);
writeword("Move cross hair to NOTE END, then hit return (ESC to exit)",
1, g_graph_char_v - 1, g_norm_attrib);
notepos = select_note(measure, FALSE);
if (notepos == NULL){
clearline(g_graph_char_v - 1, g_norm_attrib);
xsprite(cross, on_x, on_y, g_emph_color);
return;
}
else{
off_meas = notepos->measure;
off_tick = notepos->tick;
off_x = notepos->sprite_x;
off_y = notepos->sprite_y;
xsprite(cross, off_x, off_y, g_emph_color);
}
clearline(g_graph_char_v - 1, g_norm_attrib);
time_on = note_to_float(on_meas, on_tick);
time_off = note_to_float(off_meas, off_tick);
if (time_off < time_on){
clearline(g_graph_char_v - 1, g_norm_attrib);
writerr("Note OFF must be after note ON - No note added.",
g_graph_char_v, g_norm_attrib, g_norm_attrib);
xsprite(cross, on_x, on_y, g_emph_color); /* erase cross hairs */
xsprite(cross, off_x, off_y, g_emph_color);
return;
}
status = getint(g_graph_char_v - 1, "Enter note VELOCITY (volume) (0 - 127)->",
velp, 0, 127, g_norm_attrib, g_norm_attrib);
if (!status)
vel = 64;
advance_to_measure(track, off_meas + 1); /* make sure measures exist */
on_event = add_event(track, on_meas, on_tick, 4, NOTE_ON +
g_trackarray[track].midichan, on_note, vel);
off_event = add_event(track, off_meas, off_tick, 4, NOTE_ON +
g_trackarray[track].midichan, on_note, 0);
notetime = add_note_time(first_notep, on_event, on_meas, on_tick,
off_event, off_meas, off_tick);
xsprite(cross, on_x, on_y, g_emph_color); /* erase cross hairs */
xsprite(cross, off_x, off_y, g_emph_color);
draw_note(notetime, g_emph_color); /* show new note on screen */
clearline(g_graph_char_v - 1, g_norm_attrib);
}
/* add an event to track data. Measure must exist - no check for off end */
struct event far
*add_event(int track, int measure, int tick, int event_bytes, int b1, int b2,
int b3)
{
int time, lastime, addtime, b0;
struct event far *ep;
struct event far *lastep;
struct event far *newep;
struct event far *nextep;
ep = advance_to_measure(track, measure + 1); /* make sure measure */
ep = advance_to_measure(track, measure); /* exists, then find */
time = 0;
while (time <= tick){ /* find event just past tick */
lastep = ep;
ep = ep->next;
b0 = ep->b[0];
if (b0 < MAX_CLOCK){ /* if a timing byte */
time += b0;
lastime = b0;
}
else if (b0 == TIME_OUT){
time += MAX_CLOCK;
lastime = MAX_CLOCK;
}
}
time -= lastime; /* time now equals ticks for lastep, before ep */
addtime = tick - time;
nextep = ep;
while (nextep->b[0] == TIME_OUT){ /* go past any linked TIME_OUT's */
nextep = nextep->next; /* nextep is first event with a */
} /* timing byte, (not a TIME_OUT). */
if (ep->b[0] != TIME_OUT){ /* normal case - just add event */
lastep->next = newep = eventalloc();
newep->next = ep;
newep->nbytes = event_bytes;
newep->b[0] = addtime;
newep->b[1] = b1;
newep->b[2] = b2;
newep->b[3] = b3;
ep->b[0] -= addtime;
} /* next event is time_out, convert it to new event */
else if (nextep->b[0] < addtime){
newep = ep;
ep->b[0] = addtime;
ep->b[1] = b1;
ep->b[2] = b2;
ep->b[3] = b3;
ep->nbytes = event_bytes;
nextep->b[0] += MAX_CLOCK - addtime;
}
else{ /* next event is time_out, but still need a time_out */
lastep->next = newep = eventalloc();
newep->next = ep;
newep->nbytes = event_bytes;
newep->b[0] = addtime;
newep->b[1] = b1;
newep->b[2] = b2;
newep->b[3] = b3;
nextep->b[0] -= addtime;
}
return(newep);
}
/* put a new note into the note_time linked list */
struct note_time far
*add_note_time(struct note_time far *first_np, struct event far *on_event,
int on_meas, int on_tick, struct event far *off_event, int off_meas,
int off_tick)
{
int first;
struct note_time far *lastnt;
struct note_time far *nextnt;
struct note_time far *newnt;
first = 1;
lastnt = nextnt = first_np;
while (nextnt->next != NULL && (nextnt->on_measure < on_meas ||
nextnt->on_tick <= on_tick)){
lastnt = nextnt;
nextnt = nextnt->next;
first = 0;
}
#ifdef TURBOC
newnt = (struct note_time far *)farmalloc(sizeof(struct note_time));
#else
newnt = (struct note_time far *)_fmalloc(sizeof(struct note_time));
#endif
if (newnt == NULL){
writerr("Unable to allocate memory for note, full?", g_graph_char_v,
g_emph_attrib, g_norm_attrib);
return(NULL);
}
/* if newnt becomes new first note_list item */
/* then put new data in old first item. */
if (first){
newnt->on_event = first_np->on_event;
newnt->on_measure = first_np->on_measure;
newnt->on_tick = first_np->on_tick;
newnt->note_number = first_np->on_event->b[2];
newnt->off_event = first_np->off_event;
newnt->off_measure = first_np->off_measure;
newnt->off_tick = first_np->off_tick;
newnt->next = first_np->next;
first_np->on_event = on_event;
first_np->on_measure = on_meas;
first_np->on_tick = on_tick;
first_np->note_number = on_event->b[2];
first_np->off_event = off_event;
first_np->off_measure = off_meas;
first_np->off_tick = off_tick;
first_np->next = newnt;
return(first_np);
}
else{
newnt->on_event = on_event;
newnt->on_measure = on_meas;
newnt->on_tick = on_tick;
newnt->note_number = on_event->b[2];
newnt->off_event = off_event;
newnt->off_measure = off_meas;
newnt->off_tick = off_tick;
lastnt->next = newnt;
newnt->next = nextnt;
return(newnt);
}
}
/* Allow the key velocity (volume) of a note to be changed */
void
change_vel(struct note_time far *first_notep, int measure)
{
int vel, *velp, status;
char buf[SCRNWIDE], nbuf[10];
struct event far *ep;
struct note_pos *notepos;
struct note_time far *note_t;
velp = &vel;
writeword("Move the cross hair to a NOTE, then hit return (ESC to exit)",
1, g_graph_char_v - 1, g_norm_attrib);
notepos = select_note(measure, FALSE);
clearline(g_graph_char_v - 1, g_norm_attrib);
if (notepos == NULL)
return;
else
note_t = find_note(first_notep, notepos->note, notepos->measure,
notepos->tick);
ep = note_t->on_event;
vel = ep->b[3];
itoa(vel, nbuf, 10);
strcpy(buf, "Note vel = ");
strcat(buf, nbuf);
strcat(buf, " Enter new value (1 - 127), RET to exit.->");
status = getint(g_graph_char_v - 1, buf, velp, 0, 127, g_norm_attrib,
g_norm_attrib);
clearline(g_graph_char_v - 1, g_norm_attrib);
if (!status)
return;
else
ep->b[3] = vel;
}