#ifndef lint
static char sccsid[] = "@(#)musmon.c	1.2 (mg@ukc.ac.uk) 5/3/90";
#endif
#include "cs.h"                 /*                                              MUSMON.C        */

#define	SEGAMPS	01
#define	SORMSG	02

extern	INSTRTXT *instrtxtp[];
extern	INSDS	actanchor, *frstoff;

int	insno, nrecs = 0;
EVTBLK	nxtevt;
char	strmsg[100];

float	maxamp[4], smaxamp[4], omaxamp[4];
long	maxloc[4], smaxloc[4], omaxloc[4];
long	rngcnt[4], srngcnt[4], orngcnt[4];
short	rngflg = 0, srngflg = 0;

static	short	offonly = 0;
static	short	sectno = 1;
static	long	kcnt = 0;
static	float	timtot = 0.;

musmon(orchnam)
 char *orchnam;
{
	EVTBLK	*e;
	int	n;
	float	prvbt, curbt, curp2, nxtim, nxtbt, *maxp, *smaxp;
	long	*locp, *slocp, *rngp, *srngp;

	oload(orchnam);			/* load orch desblks, etc	*/
	if (synterrcnt) {
	    printf("%d syntax errors in orchestra.   performance cancelled\n",
			synterrcnt);
		exit(1);
	}
	printf("orch now loaded\n");
	if (sfwrite)			/* if sound requested,		*/
		sfinit();		/*   open a soundout file	*/
	else printf("not writing to sound disk\n");

	e = &nxtevt;
	curp2 = curbt = 0.0;
	printf("SECTION 1:\n");
	while (1) {			/* read next score event	*/
		if (rdscor(e)) {
			if (e->opcod == 'i' && e->p3orig >= 0.)
				e->p3orig += e->p2orig;
		}
		else e->opcod = 'e';
	retest:	offonly = 0;
		switch(e->opcod) {
		case 'i':
		case 'f':
		case 'a':
			if (frstoff != NULL && frstoff->offtim < e->p[2])
				goto setoff;
			nxtim = e->p[2];
			nxtbt = e->p2orig;
			break;
		case 's':
		case 'e':
			if (frstoff == NULL)
				goto scode;
	    setoff:	nxtim = frstoff->offtim;
	      		nxtbt = frstoff->offbet;
			offonly++;
			break;
		default:
			printf("error in score.  illegal opcode %c (ASCII %d)\n", e->opcod, e->opcod);
			perferrcnt++;
			continue;
		}
		if ((kcnt = (nxtim - curp2) * ekr + 0.5) > 0) {
			if (!initonly)
				kperf(kcnt);	/* perf for kcnt kprds	*/
			prvbt = curbt;
			curbt = nxtbt;
			curp2 = nxtim;
			if (msglevel & SEGAMPS || msglevel & SORMSG && rngflg) {
				printf("B%7.3f ..%7.3f T%7.3f TT%7.3f M:",
					prvbt,	curbt,	curp2,	timtot+curp2);
				for (n=nchnls, maxp=maxamp; n--;)
					printf("%9.1f", *maxp++);
				putchar('\n');
				if (rngflg) {
				  printf("\t number of samples out of range:");
					for (n=nchnls, rngp=rngcnt; n--;)
						printf("%9d", *rngp++);
					putchar('\n');
					rngflg = 0;
					srngflg++;
				}
			}
			for (n=nchnls, maxp=maxamp-1, smaxp=smaxamp-1,
					locp = maxloc-1, slocp = smaxloc-1,
					rngp=rngcnt, srngp=srngcnt; n--;) {
				++locp ; ++slocp;
				if (*++maxp > *++smaxp) {
					*smaxp = *maxp;
					*slocp = *locp;
				}
				*maxp = 0;
				*locp = 0;
				*srngp++ += *rngp;
				*rngp++ = 0;
			}
		}
		if (frstoff != NULL)		/* if turnoffs pending,	*/
			expire(curp2 + hfkprd);	/* rm any expired instrs */
		if (offonly)
			goto retest;		/*  if offonly, loop back  */

		switch(e->opcod) {
		case 'i':
			insno = abs((int)e->p[1]);
			if (insno > MAXINSNO || instrtxtp[insno] == NULL) {
				printf(
				 "B%3.3f - note deleted. instr %d undefined\n",
			 	 curp2, insno);
				perferrcnt++;
				continue;
			}
			if (e->p[1] < 0.) {	   /* if p1 neg,	*/
				infoff(-e->p[1]);  /* turnoff any infin copy */
				continue;
			}
			if (n = insert(insno)) {/* alloc, init & activate   */
				printf(
			  "B%3.3f - note deleted.  i%d had %d init errors\n",
			 	curp2, insno, n);
				perferrcnt++;
				continue;
			}
			break;
		case 'f':
			fgens();
			break;
		case 'a':
			curp2 = e->p[2] + e->p[3];
			curbt = e->p2orig + e->p3orig;
			printf("time advanced %5.3f beats by score request\n",
					e->p3orig);
			break;
		}
		continue;

	scode:	if (e->opcod == 's' || sectno > 1) {  /* for s, or e after s */
			timtot += curp2;
			prvbt = curbt = curp2 = 0;
			printf("end of section %d\t sect peak amps:",sectno);
			for (n=nchnls, maxp=smaxamp; n--; )
				printf("%9.1f", *maxp++);
			putchar('\n');
			if (srngflg) {
				printf("\t number of samples out of range:");
				for (n=nchnls, srngp=srngcnt; n--; )
					printf("%9d", *srngp++);
				putchar('\n');
				srngflg = 0;
			}
		}
		for (n=nchnls, smaxp=smaxamp-1, maxp=omaxamp-1, 
				slocp=smaxloc-1, locp=omaxloc-1, 
				srngp=srngcnt,   rngp=orngcnt; n--; ) {
			++locp ; ++slocp;
			if (*++smaxp > *++maxp) {
				*maxp = *smaxp;		/* keep ovrl maxamps */
				*locp = *slocp;
			}
			*smaxp = 0;
			*slocp = 0;
			*rngp++ += *srngp;		/*   and orng counts */
			*srngp++ = 0;
		}
		if (e->opcod == 's') {			/* if s code,	     */
			orcompact();			/*   rtn inactiv spc */
			if (actanchor.nxtact == NULL)   /*   if no indef ins */
			        rlsmemfiles();          /*    purge memfiles */
			curp2 = curbt = 0.0;		/*   reset sec times */
			printf("SECTION %d:\n", ++sectno);
		}					/*   & back for more */
		else break;
	}

	printf("end of score.\t\t   overall amps:");	/* else we're done */
	for (maxp=omaxamp, n=nchnls; n--; )
		printf("%9.1f", *maxp++);
	switch (output_format) {
	case OF_FLOAT:
		break;
	default:
		printf("\n\t   overall samples out of range:");
		for (rngp=orngcnt, n=nchnls; n--; )
			printf("%9d", *rngp++);
		break;
	}
	printf("\n%d errors in performance\n",perferrcnt);
	if (sfwrite) {
		char *p;

		sfclose();

		switch (output_format) {
		case OF_FLOAT: p = "floats"; break;
		case OF_SHORT: p = "shorts"; break;
#ifdef ULAW
		case OF_ULAW:  p = "ulaw bytes"; break;
#endif
		default: abort();
		}
		printf("%d records written to %s (%s)\n",
			nrecs, sfout, p);
	}
	else printf("0 records written to disk\n");
}
