/* noteoff.c -- this module keeps track of pending note offs for adagio */ /***************************************************************************** * Change Log * Date | Change *-----------+----------------------------------------------------------------- * 31-Dec-85 | Created changelog * 31-Dec-85 | Add c:\ to include directives * 1-Jan-86 | Declare getmem char * for lint consistency * 21-Jan-86 | note_offs can now turn off more than one note per call *****************************************************************************/ #include "cext.h" #include "stdio.h" #include "ctype.h" #include "adagio.h" /* off_type is a structure containing note-off information */ typedef struct off_struct { long when; int voice; int pitch; struct off_struct *next; } *off_type; private off_type free_off; /* free list of off_type structures */ private off_type off_events = NULL; /* active list */ extern char * getmem(); /**************************************************************************** * Routines declared in this module ****************************************************************************/ boolean note_offs(); private off_type off_alloc(); private void off_free(); void off_init(); void off_schedule(); /**************************************************************************** * note_offs * Inputs: * long time: the current time * Outputs: * return true if off list has more notes * Effect: turn off notes if it is time * Assumes: * Implementation: * Find scheduled note off events in off_events, compare with time ****************************************************************************/ boolean note_offs(time) long time; { off_type temp; while (off_events != NULL && off_events->when <= time) { midi_note((off_events->voice) + 1, off_events->pitch, 0); temp = off_events; off_events = off_events->next; off_free(temp); } return (off_events != NULL); } /**************************************************************************** * off_alloc * Outputs: * returns off_type: an allocated note off structure * Effect: * allocates a structure using getmem ****************************************************************************/ private off_type off_alloc() { return (off_type) getmem(sizeof(struct off_struct)); } /**************************************************************************** * off_free * Inputs: * off_type off: a structure to deallocate * Effect: * returns off to freelist ****************************************************************************/ private void off_free(off) off_type off; { off->next = free_off; free_off = off; } /**************************************************************************** * off_init * Effect: initialize this module * Assumes: * only called once, otherwise storage is leaked ****************************************************************************/ void off_init() { int i; for (i = 0; i < 50; i++) off_free(off_alloc()); } /**************************************************************************** * off_schedule * Inputs: * long offtime: time to turn note off * int voice: the midi channel * int pitch: the pitch * Effect: * schedules a note to be turned off * Assumes: * note_offs will be called frequently to actually turn off notes ****************************************************************************/ void off_schedule(offtime, voice, pitch) long offtime; int voice, pitch; { off_type off, ptr, prv; /* allocate off */ if ((off = free_off) == NULL) { off = off_alloc(); } else free_off = off->next; if (off == NULL) { fprintf(stderr, "out of space for note off events"); musicterm(); exit(1); } off->when = offtime; off->voice = voice; off->pitch = pitch; /* insert into list of off events */ ptr = off_events; if (ptr == NULL || offtime <= ptr->when) { off->next = ptr; off_events = off; } else { while (ptr != NULL && offtime > ptr->when) { prv = ptr; ptr = ptr->next; } prv->next = off; off->next = ptr; } /* * printf("off_schedule(%ld, %d, %d): \n", offtime, voice, pitch); * for (ptr = off_events; ptr != NULL; ptr = ptr->next) { * printf(" %ld: %d, %d\n", ptr->when, ptr->voice, ptr->pitch); * } */ }